MotionLib  1.0.0
SamBuCa motion library
AsyncApiController.hpp
1 /*
2 ** Copyright (C) 2022 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: 2022-07-26T11:50:41
21 ** Author: Sylvain Fargier <sylvain.fargier@cern.ch>
22 */
23 
24 #ifndef ASYNCAPICONTROLLER_HPP__
25 #define ASYNCAPICONTROLLER_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/Types.hpp>
35 #include <oatpp/core/macro/codegen.hpp>
36 #include <oatpp/core/macro/component.hpp>
37 #include <oatpp/web/server/api/ApiController.hpp>
38 
39 #include "Exception.hpp"
40 #include "FutureCoroutine.hpp"
41 #include "SmcController.hpp"
42 #include "device/Axis.hpp"
43 #include "device/DeviceBase.hpp"
44 #include "device/DeviceStore.hpp"
45 #include "platform/PlatformFactory.hpp"
46 #include "util/serialize.hpp"
47 
48 #include OATPP_CODEGEN_BEGIN(ApiController)
49 
50 // clang-format off
52 {
53 public:
54  explicit AsyncApiController(OATPP_COMPONENT(std::shared_ptr<ObjectMapper>,
55  objectMapper)) :
56  SmcController(objectMapper)
57  {}
58 
59  ENDPOINT_INFO(root)
60  {
61  info->summary = "api-docs redirection";
62  info->addResponse<List<String>>(Status::CODE_302, "");
63  }
64  ENDPOINT_ASYNC("GET", "/", root)
65  {
66  ENDPOINT_ASYNC_INIT(root)
67 
68  Action act() override
69  {
70  auto ret = controller->createResponse(Status::CODE_302);
71  ret->putHeader("Location", "/api-docs/ui");
72  return _return(ret);
73  }
74  };
75 
76  ENDPOINT_INFO(devices)
77  {
78  info->summary = "List available devices";
79  info->addResponse<List<String>>(Status::CODE_200, "application/json")
80  .addExample("example",
81  List<String>{"grbl://1/platform", "grbl://1/axis/X",
82  "grbl://1/axis/Y", "grbl://1/axis/Z",
83  "grbl://1/axis/A", "grbl://1/axis/B",
84  "grbl://1/axis/C"});
85  {
86  auto &param = info->queryParams.add<String>("type")
87  .addExample("fetch all", String())
88  .addExample("trigger", String("trigger"))
89  .addExample("axis", String("axis"))
90  .addExample("platform", String("platform"));
91  param.description = "device type filter, accepted values are listed in "
92  "`GET /devices/types`";
93  param.required = false;
94  }
95  {
96  auto &param = info->queryParams.add<Boolean>("typed")
97  .addExample("default results", Boolean(false))
98  .addExample("typed results", Boolean(true));
99  param.description = "get a deviceId : type map rather than a simple list";
100  param.required = false;
101  }
102 
103  }
104  ENDPOINT_ASYNC("GET", "/devices", devices)
105  {
106  ENDPOINT_ASYNC_INIT(devices)
107 
108  Action act() override
109  {
110  const std::string deviceType =
111  request->getQueryParameter("type").getValue("");
112  bool success = false;
113  bool typed = TypeInterpretation<Boolean>::fromString("Boolean",
114  request->getQueryParameter("typed"), success);
115  if (!success)
116  typed = false;
117 
118 
119  auto deviceStore(controller->deviceStore.lock());
120  if (deviceStore)
121  {
122  std::set<smc::DeviceId> devices = deviceType.empty() ?
123  deviceStore->getDeviceList() :
124  deviceStore->getDeviceList(
125  smc::from_string<smc::DeviceType>(deviceType));
126  if (!typed)
127  {
128  oatpp::UnorderedSet<String> ret{oatpp::UnorderedSet<String>::createShared()};
129  ret->insert(devices.begin(), devices.end());
130  return _return(controller->createDtoResponse(Status::CODE_200, ret));
131  }
132  else
133  {
134  oatpp::UnorderedFields<String> ret{oatpp::UnorderedFields<String>::createShared()};
135  for (smc::DeviceId id : devices)
136  ret[String(id)] = String(smc::to_string(deviceStore->getDevice(id)->type()));
137  return _return(controller->createDtoResponse(Status::CODE_200, ret));
138  }
139  }
140 
141  return _return(controller->createResponse(Status::CODE_500, "no deviceStore"));
142  }
143  };
144 };
145 // clang-format on
146 #include OATPP_CODEGEN_END(ApiController)
147 
148 #endif
const std::string & to_string(Axis::State state)
convert State to string
Definition: Axis.cpp:78