VSM C++ SDK
Vehicle Specific Modules SDK
mavlink_demuxer.h
Go to the documentation of this file.
1 // Copyright (c) 2014, Smart Projects Holdings Ltd
2 // All rights reserved.
3 // See LICENSE file for license details.
4 
11 #ifndef _MAVLINK_DEMUXER_H_
12 #define _MAVLINK_DEMUXER_H_
13 
15 #include <unordered_map>
17 
18 namespace ugcs {
19 namespace vsm {
20 
27 public:
30  typedef signed Message_id;
31 
33  static constexpr Message_id MESSAGE_ID_ANY = -1;
34 
37  typedef int64_t System_id;
38 
40  static constexpr System_id SYSTEM_ID_ANY = -1;
41 
44  typedef signed Component_id;
45 
47  static constexpr Component_id COMPONENT_ID_ANY = -1;
48 
51 
53  template<mavlink::MESSAGE_ID_TYPE message_id, class Extention_type = mavlink::Extension>
54  using Handler = Callback_proxy<
56 
64 
66  DEFINE_CALLBACK_BUILDER(Make_default_handler,
67  (mavlink::MESSAGE_ID_TYPE, System_id, uint8_t, uint32_t),
68  (mavlink::MESSAGE_ID::DEBUG_VALUE, mavlink::SYSTEM_ID_NONE, 0, 0))
69 
70 
72  (mavlink::MESSAGE_ID_TYPE message_id, class Extention_type),
73  (typename mavlink::Message<message_id, Extention_type>::Ptr),
74  (typename mavlink::Message<message_id, Extention_type>::Ptr(nullptr)))
75 
77  class Key {
78  public:
80  Key(mavlink::MESSAGE_ID_TYPE message_id, System_id system_id, Component_id component_id) :
81  message_id(message_id),
82  system_id(system_id),
83  component_id(component_id) {
84  }
85 
87  Key() {}
88 
90  class Hasher {
91  public:
92 
94  size_t
95  operator ()(const Key& key) const
96  {
97  static_assert(sizeof(key.message_id) == sizeof(uint8_t), "Please adjust bit shift!");
98  return static_cast<uint8_t>(key.message_id) ^
99  key.system_id ^
100  key.component_id << 16;
101  }
102  };
103 
105  void
106  Reset()
107  {
108  id = 0;
109  }
110 
112  explicit operator bool() const
113  {
114  return id != 0;
115  }
116 
118  bool
119  operator ==(const Key& key) const
120  {
121  return this->message_id == key.message_id &&
122  this->system_id == key.system_id &&
123  this->component_id == key.component_id;
124  }
125 
126  private:
127 
129 
130  System_id system_id;
131 
132  Component_id component_id;
133 
134  static std::atomic_int generator;
135  int id = 0;
136 
137  // used only when inserting into handlers.
138  void
139  Generate_id()
140  {
141  id = std::atomic_fetch_add(&Key::generator, 1);
142  }
143 
144  friend class Mavlink_demuxer;
145  };
146 
148  Mavlink_demuxer() = default;
149 
151  Mavlink_demuxer(const Mavlink_demuxer&) = delete;
152 
154  void
155  Disable();
156 
159  void
161 
175  template<mavlink::MESSAGE_ID_TYPE message_id, class Extention_type>
176  Key
179  System_id system_id = SYSTEM_ID_ANY,
180  Component_id component_id = COMPONENT_ID_ANY,
181  Request_processor::Ptr processor = nullptr)
182  {
184  handler, processor);
185  Key key(message_id, system_id, component_id);
186  key.Generate_id();
187  std::unique_lock<std::mutex> lock(mutex);
188  handlers.insert(std::make_pair(key, std::move(callback)));
189  return key;
190  }
191 
196  bool
198  System_id system_id, uint8_t component_id, uint32_t request_id);
199 
202  void
203  Unregister_handler(Key&);
204 
205 private:
206 
211  bool
212  Demux_try(Io_buffer::Ptr buffer, mavlink::MESSAGE_ID_TYPE message_id,
213  System_id system_id, uint8_t component_id, uint32_t request_id);
214 
219  bool
220  Demux_try_one(Io_buffer::Ptr buffer, mavlink::MESSAGE_ID_TYPE message_id,
221  System_id system_id, Component_id component_id,
222  System_id real_system_id,
223  uint8_t real_component_id,
224  uint32_t request_id);
225 
230  class Callback_base: public std::enable_shared_from_this<Callback_base> {
231  DEFINE_COMMON_CLASS(Callback_base, Callback_base)
232  public:
233 
234  Callback_base(Request_processor::Ptr processor) :
235  processor(processor) {}
236 
237  virtual
238  ~Callback_base()
239  {};
240 
241  virtual void
242  operator ()(Io_buffer::Ptr buffer, System_id system_id,
243  uint8_t component_id, uint32_t request_id) = 0;
244 
245  protected:
247  Request_processor::Ptr processor;
248  };
249 
251  template<mavlink::MESSAGE_ID_TYPE message_id, class Extention_type>
252  class Callback: public Callback_base {
253  DEFINE_COMMON_CLASS(Callback, Callback_base)
254  public:
255 
258 
259  Callback(Handler<message_id, Extention_type> handler,
260  Request_processor::Ptr processor):
261  Callback_base(processor),
262  handler(handler)
263  {}
264 
265  virtual void
266  operator ()(Io_buffer::Ptr buffer, System_id system_id,
267  uint8_t component_id, uint32_t request_id) override
268  {
269  typename Message_type::Ptr message =
270  Message_type::Create(system_id, component_id, request_id, buffer);
271  if (processor) {
272  /* Callback will be invoked from processor context. */
273  auto request = Request::Create();
274  request->Set_processing_handler(Make_callback(&Callback::Invoke,
275  Shared_from_this(), std::move(message), request));
276  processor->Submit_request(std::move(request));
277 
278  } else {
279  /* Invoke from the calling thread. */
280  handler(message);
281  }
282  }
283 
284  private:
287 
289  void
290  Invoke(typename Message_type::Ptr message, Request::Ptr request)
291  {
292  handler(message);
293  if (request) {
294  request->Complete();
295  }
296  }
297  };
298 
300  Default_handler default_handler;
301 
303  std::unordered_multimap<Key, Callback_base::Ptr, Key::Hasher> handlers;
304 
306  std::mutex mutex;
307 };
308 
309 } /* namespace vsm */
310 } /* namespace ugcs */
311 
312 #endif /* _MAVLINK_DEMUXER_H_ */
UGCS root namespace.
Definition: android-linux/ugcs/vsm/platform_sockets.h:27
static Ptr Create(Args &&...args)
Create an instance.
Definition: request_container.h:38
Exception class with one parameter.
Definition: exception.h:88
#define DEFINE_CALLBACK_BUILDER(__name, __types, __values)
Define callback builder function.
Definition: callback.h:42
#define DEFINE_CALLBACK_BUILDER_TEMPLATE(__name, __template, __types, __values)
The same as DEFINE_CALLBACK_BUILDER, but allows specifying additional template parameters for builder...
Definition: callback.h:55
std::shared_ptr< Request > Ptr
Pointer type.
Definition: request_container.h:38
Request execution context.
#define VSM_DEFINE_EXCEPTION(__exc_class,...)
Define custom exception type.
Definition: exception.h:202
Helper class for proxying callback invocation.
Definition: callback.h:691
Callback< Callable, void, Args... >::Ptr Make_callback(Callable &&callable, Args &&...args)
Create a callback.
Definition: callback.h:389
Base_type::Result_t Invoke(callback_internal::Sequence< s... >)
Invoke callable entity with user provided arguments.
Definition: callback.h:283
std::shared_ptr< Request_context > Ptr
Pointer type.
Definition: request_context.h:25
static Ptr Create(Callable &&callable, Args &&...args)
Create callback instance.
Definition: callback.h:235
std::shared_ptr< Io_buffer > Ptr
Pointer type.
Definition: io_buffer.h:34
#define DEFINE_COMMON_CLASS(__class_name,...)
Use this macro to define some common attributes for a class.
Definition: utils.h:25