MotionLib  1.0.0
SamBuCa motion library
AsyncGpioController.hpp
1 /*
2 ** Copyright (C) 2023 CERN
3 **
4 ** This software is provided 'as-is', without any express or implied
5 ** warranty. In no event will the authors be held liable for any damages
6 ** arising from the use of this software.
7 **
8 ** Permission is granted to anyone to use this software for any purpose,
9 ** including commercial applications, and to alter it and redistribute it
10 ** freely, subject to the following restrictions:
11 **
12 ** 1. The origin of this software must not be misrepresented; you must not
13 ** claim that you wrote the original software. If you use this software
14 ** in a product, an acknowledgment in the product documentation would be
15 ** appreciated but is not required.
16 ** 2. Altered source versions must be plainly marked as such, and must not be
17 ** misrepresented as being the original software.
18 ** 3. This notice may not be removed or altered from any source distribution.
19 **
20 ** Created on: 2023-03-09T09:47:19
21 ** Author: Sylvain Fargier <sylvain.fargier@cern.ch>
22 */
23 
24 #ifndef ASYNCGPIOCONTROLLER_HPP__
25 #define ASYNCGPIOCONTROLLER_HPP__
26 
27 #include <algorithm>
28 #include <cmath>
29 #include <memory>
30 
31 #include <ccut/async.hpp>
32 #include <ccut/utils.hpp>
33 #include <logger/Logger.hpp>
34 #include <oatpp/core/macro/component.hpp>
35 #include <oatpp/web/protocol/http/incoming/Request.hpp>
36 
37 #include "Exception.hpp"
38 #include "FutureCoroutine.hpp"
39 #include "OatExt.hpp"
40 #include "SmcController.hpp"
41 #include "device/Axis.hpp"
42 #include "device/DeviceBase.hpp"
43 #include "device/DeviceStore.hpp"
44 #include "platform/PlatformFactory.hpp"
45 #include "util/serialize.hpp"
46 
47 #include OATPP_CODEGEN_BEGIN(ApiController)
48 
49 // clang-format off
51 {
52 public:
53  explicit AsyncGpioController(OATPP_COMPONENT(std::shared_ptr<ObjectMapper>,
54  objectMapper)) :
55  SmcController(objectMapper)
56  {
57  addTag(*this, "gpio");
58  }
59 
60  void addParams(const std::shared_ptr<oatpp::web::server::api::Endpoint::Info>& info)
61  {
62  info->pathParams.add<String>("id")
63  .addExample("Gpio id", String("mfe://1/gpio/limit"));
64  }
65 
66  ENDPOINT_INFO(getIoValue)
67  {
68  info->summary = "get gpio value";
69  info->addResponse<UInt64>(Status::CODE_200, "application/json")
70  .addExample("example", UInt64(1234));
71  addParams(info);
72  }
73  ENDPOINT_ASYNC("GET", "/gpio/{id}/value", getIoValue)
74  {
75  public:
76  ENDPOINT_ASYNC_INIT(getIoValue)
77  Action act() override
78  {
79  auto deviceStore(controller->deviceStore.lock());
80  if (deviceStore)
81  {
82  smc::Gpio::Shared device = deviceStore->getDevice<smc::Gpio>(
83  ccut::urldecode(request->getPathVariable("id").getValue("")));
84 
85  auto future = device->getIoState();
86  return smc::debug::wait(future.share())
87  .callbackTo(&getIoValue::onResult);
88  }
89  return _return(controller->createResponse(Status::CODE_500, "no deviceStore"));
90  }
91 
92  Action onResult(const smc::units::io_port_t &value)
93  {
94  return _return(
95  controller->createDtoResponse(Status::CODE_200, UInt64(value.value)));
96  }
97  };
98 
99  ENDPOINT_INFO(getIoSize)
100  {
101  info->summary = "get gpio size (in bits)";
102  info->addResponse<UInt64>(Status::CODE_200, "application/json")
103  .addExample("example", UInt32(16));
104  addParams(info);
105  }
106  ENDPOINT_ASYNC("GET", "/gpio/{id}/size", getIoSize)
107  {
108  public:
109  ENDPOINT_ASYNC_INIT(getIoSize)
110  Action act() override
111  {
112  auto deviceStore(controller->deviceStore.lock());
113  if (deviceStore)
114  {
115  smc::Gpio::Shared device = deviceStore->getDevice<smc::Gpio>(
116  ccut::urldecode(request->getPathVariable("id").getValue("")));
117 
118  auto future = device->getIoState();
119  return smc::debug::wait(future.share())
120  .callbackTo(&getIoSize::onResult);
121  }
122  return _return(controller->createResponse(Status::CODE_500, "no deviceStore"));
123  }
124 
125  Action onResult(const smc::units::io_port_t &value)
126  {
127  return _return(
128  controller->createDtoResponse(Status::CODE_200, UInt32(value.size)));
129  }
130  };
131 
132  ENDPOINT_INFO(putIoValue)
133  {
134  info->summary = "set gpio value";
135  info->addResponse(Status::CODE_200, "application/json");
136  info->addConsumes<UInt64>("application/json")
137  .addExample("gpio value", UInt64(1234));
138 
139  {
140  auto &param = info->queryParams.add<UInt32>("size")
141  .addExample("size", UInt32(32));
142 
143  param.required = false;
144  param.description = "request unit";
145  }
146  addParams(info);
147  }
148  ENDPOINT_ASYNC("PUT", "/gpio/{id}/value", putIoValue)
149  {
150  public:
151  ENDPOINT_ASYNC_INIT(putIoValue)
152  Action act() override
153  {
154  return request
155  ->readBodyToDtoAsync<UInt64>(
156  controller->getDefaultObjectMapper())
157  .callbackTo(&putIoValue::onSetIoState);
158  }
159 
160  Action onSetIoState(const UInt64 &value)
161  {
162  size_t size = getQueryParameter<uint32_t>(request, "size", sizeof(smc::units::io_port_t::value_type));
163  auto deviceStore(controller->deviceStore.lock());
164  if (deviceStore)
165  {
166  smc::Gpio::Shared device = deviceStore->getDevice<smc::Gpio>(
167  ccut::urldecode(request->getPathVariable("id").getValue("")));
168 
169  auto future = device->setIoState(smc::units::io_port_t{value.getValue(0), size});
170  return smc::debug::wait(future.share())
171  .next(_return(
172  controller->createResponse(Status::CODE_200, "done")));
173  }
174  return _return(controller->createResponse(Status::CODE_500, "no deviceStore"));
175  }
176  };
177 };
178 
179 //clang-format on
180 
181 #include OATPP_CODEGEN_END(ApiController)
182 
183 #endif
virtual std::future< void > setIoState(const units::io_port_t &state) const =0
Set state of this IO.
virtual std::future< units::io_port_t > getIoState() const =0
Get current state of this GPIO.
value_type value
port value
Definition: Units.hpp:209
size_type size
size in bits
Definition: Units.hpp:210