VSM C++ SDK
Vehicle Specific Modules SDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
device.h
1 // Copyright (c) 2018, Smart Projects Holdings Ltd
2 // All rights reserved.
3 // See LICENSE file for license details.
4 
5 #ifndef _UGCS_VSM_DEVICE_H_
6 #define _UGCS_VSM_DEVICE_H_
7 
8 #include <ugcs/vsm/property.h>
9 #include <ugcs/vsm/callback.h>
11 #include <ugcs/vsm/optional.h>
12 #include <ugcs/vsm/subsystem.h>
14 
15 #include <memory>
16 #include <unordered_map>
17 #include <unordered_set>
18 
19 namespace ugcs {
20 namespace vsm {
21 
22 class Ucs_request :public Request
23 {
25 
26 public:
27  Ucs_request(ugcs::vsm::proto::Vsm_message);
28 
29  void
30  Complete(
31  ugcs::vsm::proto::Status_code = ugcs::vsm::proto::STATUS_OK,
32  const std::string& description = std::string());
33 
34  // Device can modify device_response of this message
35  Proto_msg_ptr response = nullptr;
36 
37  // Used to send in-progress status for the request.
38  uint32_t stream_id = 0;
39 
40  ugcs::vsm::proto::Vsm_message request;
41 };
42 
43 // Structure to get info about ucs servers device is registered with.
44 // Used in Handle_ucs_info callback.
45 typedef struct {
46  uint32_t ucs_id;
47  Socket_address::Ptr address;
48  // This is the primary connection to given ucs. Telemetry/registrations sent only over this connection.
49  bool is_primary;
50  // Last time something was received over this connection.
51  std::chrono::time_point<std::chrono::steady_clock> last_message_time;
52 } Ucs_info;
53 
54 class Device: public std::enable_shared_from_this<Device>
55 {
57 
58 public:
59  // Constructor for device with provided processor and completion context.
60  // If processor and completion_ctx are not specified then
61  // Device will create it's own contexts and execute them in separate thread.
62  // If processor and completion_ctx are specified then
63  // Device will use provided contexts and will not create the thread.
64  Device(
65  proto::Device_type type,
66  Request_processor::Ptr processor = nullptr,
67  Request_completion_context::Ptr completion_ctx = nullptr);
68 
69  typedef Callback_proxy<
70  void,
71  std::vector<Property::Ptr>>
73 
75  typedef Callback_proxy<void, uint32_t, Proto_msg_ptr> Response_sender;
76 
77  virtual
78  ~Device();
79 
83  void
84  Enable();
85 
89  void
90  Disable();
91 
93  bool
94  Is_enabled() { return is_enabled;}
95 
97  Device(const Device &) = delete;
98 
102  void
103  On_ucs_message(
104  ugcs::vsm::proto::Vsm_message message,
105  Response_sender completion_handler = Response_sender(),
106  ugcs::vsm::Request_completion_context::Ptr completion_ctx = nullptr);
107 
108  // Used by Cucs_processor only.
109  // Derived class must override.
110  void
111  Register(ugcs::vsm::proto::Vsm_message&);
112 
113  // Create/replace property value. By default type is derived from value.
114  template<typename Type>
116  Set_property(
117  const std::string& name,
118  Type value,
119  proto::Field_semantic semantic = proto::FIELD_SEMANTIC_DEFAULT)
120  {
121  auto it = properties.find(name);
122  if (it == properties.end()) {
123  auto f = Property::Create(name, value, semantic);
124  properties.emplace(name, f);
125  return f;
126  } else {
127  it->second->Set_value(value);
128  return it->second;
129  }
130  }
131 
132  uint32_t
133  Get_session_id();
134 
137  Get_completion_ctx();
138 
139  static void
140  Set_failsafe_actions(Property::Ptr p, std::initializer_list<proto::Failsafe_action> actions);
141 
145  void
146  Register();
147 
149  void
150  Unregister();
151 
153  bool
154  Is_registered();
155 
156  std::string
157  Dump_command(const ugcs::vsm::proto::Device_command &);
158 
160  Add_subsystem(proto::Subsystem_type);
161 
164  Get_processing_ctx();
165 
175  virtual void
176  Handle_ucs_info(std::vector<Ucs_info> /*ucs_data*/)
177  {};
178 
179 protected:
183  virtual void
185  {};
186 
190  virtual void
192  {};
193 
199  virtual void
200  Handle_ucs_command(Ucs_request::Ptr request);
201 
207  void
208  Report_progress(
209  Ucs_request::Ptr request,
210  float progress = -1.0,
211  const std::string& description = std::string());
212 
213  void
214  Send_ucs_message(Proto_msg_ptr msg);
215 
217  Get_command(int id);
218 
219  // Append to the list of status messages. Commit_to_ucs will push all to ucs.
220  void
221  Add_status_message(const std::string& m);
222 
223  class Commit_scope {
224  public:
225  Commit_scope(Device& d):d(d) {}
226  ~Commit_scope() {d.Commit_to_ucs();}
227  private:
228  Device& d;
229  };
230 
231  // Add this in each scope which requires a call to Commit_to_ucs().
232  // This guarantees the commit on scope leave and you do not need to
233  // add Commit_to_ucs() before each return.
234  #define CREATE_COMMIT_SCOPE auto auto_device_commit_scope = Commit_scope(*this)
235 
236  // Set log_message to true to see what gets sent to the server.
237  void
238  Commit_to_ucs(bool log_message = false);
239 
240  const proto::Device_type device_type;
241 
242  Request_processor::Ptr processor;
243  Request_completion_context::Ptr completion_ctx;
244 
245  std::chrono::time_point<std::chrono::system_clock> begin_of_epoch;
246 
247  std::vector<Subsystem::Ptr> subsystems;
248 
249 private:
250  Request_worker::Ptr worker = nullptr;
251 
252  // Status messages to be sent to ucs.
253  std::list<std::string> device_status_messages;
254 
255  uint32_t my_handle = 0;
256 
258  bool is_enabled = false;
259 
260  std::unordered_map<std::string, Property::Ptr> properties;
261 };
262 
265 #define DEVICE_LOG(level_, vehicle_, fmt_, ...) \
266  _LOG_WRITE_MSG(level_, "[%d] " fmt_, \
267  (vehicle_).Get_session_id(), ## __VA_ARGS__)
268 
271 // @{
272 #define DEVICE_LOG_DBG(vehicle_, fmt_, ...) \
273  DEVICE_LOG(::ugcs::vsm::Log::Level::DEBUGGING, vehicle_, fmt_, ## __VA_ARGS__)
274 
275 #define DEVICE_LOG_INF(vehicle_, fmt_, ...) \
276  DEVICE_LOG(::ugcs::vsm::Log::Level::INFO, vehicle_, fmt_, ## __VA_ARGS__)
277 
278 #define DEVICE_LOG_WRN(vehicle_, fmt_, ...) \
279  DEVICE_LOG(::ugcs::vsm::Log::Level::WARNING, vehicle_, fmt_, ## __VA_ARGS__)
280 
281 #define DEVICE_LOG_ERR(vehicle_, fmt_, ...) \
282  DEVICE_LOG(::ugcs::vsm::Log::Level::ERROR, vehicle_, fmt_, ## __VA_ARGS__)
283 // @}
284 
285 } /* namespace vsm */
286 } /* namespace ugcs */
287 
288 #endif /* _UGCS_VSM_DEVICE_H_ */
static Ptr Create(Args &&...args)
Create an instance.
Definition: property.h:18
Generic request for implementing inter-threads communications and asynchronous operations.
Definition: request_container.h:37
Request worker.
std::shared_ptr< Property > Ptr
Pointer type.
Definition: property.h:18
virtual void On_enable()
Device enable event handler.
Definition: device.h:184
virtual void Handle_ucs_info(std::vector< Ucs_info >)
Called when number of ucs connections change.
Definition: device.h:176
virtual void On_disable()
Device disable event handler.
Definition: device.h:191
Generic callback which can be used to define and create an instance of an abstract callable operation...
std::shared_ptr< Request_worker > Ptr
Pointer type.
Definition: request_worker.h:25
Request execution context.
Definition: request_context.h:24
Socket processor.
Definition: property.h:16
Helper class for proxying callback invocation.
Definition: callback.h:699
Definition: device.h:22
Definition: device.h:54
std::shared_ptr< Vsm_command > Ptr
Pointer type.
Definition: subsystem.h:24
std::shared_ptr< Device > Ptr
Pointer type.
Definition: device.h:56
std::shared_ptr< Request_context > Ptr
Pointer type.
Definition: request_context.h:25
std::shared_ptr< Subsystem > Ptr
Pointer type.
Definition: subsystem.h:88
#define DEFINE_COMMON_CLASS(__class_name,...)
Use this macro to define some common attributes for a class.
Definition: utils.h:25
T value
Stored value (in wire byte order).
Definition: endian.h:376
std::shared_ptr< Ucs_request > Ptr
Pointer type.
Definition: device.h:24
Definition: device.h:223
Definition: device.h:45