automotive-message-broker  0.14.803
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
jsonprotocol.h
1 /*
2 Copyright (C) 2015 Intel Corporation
3 
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8 
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13 
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #ifndef AMB_JSON_PROTOCOL_H_
20 #define AMB_JSON_PROTOCOL_H_
21 
22 #include <functional>
23 #include <memory>
24 #include <string>
25 #include <unordered_map>
26 #include <vector>
27 
28 #include <abstractroutingengine.h>
29 #include <mappropertytype.hpp>
30 #include <picojson.h>
31 #include <uuidhelper.h>
32 #include <vehicleproperty.h>
33 
34 #include "abstractio.hpp"
35 
36 
37 namespace amb
38 {
39 
40 template <class T>
41 class PtrMaker
42 {
43 public:
44  typedef std::shared_ptr<T> Ptr;
45 
46  static std::shared_ptr<T> create()
47  {
48  return Ptr(new T());
49  }
50 };
51 
52 class Object : public std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>, public PtrMaker<Object>
53 {
54 public:
55  Object(): std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>() { }
56  Object(const std::string & ifaceName): std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>(),
57  interfaceName(ifaceName)
58  {
59 
60  }
61 
62  static Object::Ptr fromJson(const picojson::object & obj);
63 
64  static picojson::value toJson(const Object::Ptr & obj);
65 
66  std::string interfaceName;
67 };
68 
69 
71 {
72 public:
73  BaseMessage():BaseMessage("", "message") { }
74 
75  BaseMessage(std::string t): BaseMessage("", t) {}
76 
77  BaseMessage(std::string n, std::string t)
78  : name(n), type(t)
79  {
80  messageId = amb::createUuid();
81  }
82 
83  BaseMessage(const BaseMessage & other)
84  : BaseMessage(other.name, other.type)
85  {
86 
87  }
88 
89  std::string name;
90  std::string type;
91 
92  std::string messageId;
93 
94  virtual picojson::value toJson();
95  virtual bool fromJson(const picojson::value & json);
96 
97  template <typename T>
98  bool is()
99  {
100  return T::is(this);
101  }
102 
103  static bool validate(const picojson::value & json)
104  {
105  return json.is<picojson::object>() && json.contains("type") && json.contains("name") && json.contains("messageId");
106  }
107 
108  template <typename T>
109  static bool is(const picojson::value & json)
110  {
111  return T::is(json);
112  }
113 
114 protected:
115 
116  picojson::value data;
117 
118 private:
119 };
120 
121 class MethodCall : public BaseMessage
122 {
123 public:
124  MethodCall(std::string name)
125  :BaseMessage(name, "method"), zone(Zone::None)
126  {
127 
128  }
129 
130  MethodCall(const BaseMessage & other)
131  :BaseMessage(other), zone(Zone::None)
132  {
133  name = other.name;
134  }
135 
136  MethodCall(const MethodCall & other)
137  :MethodCall(other.name)
138  {
139  sourceUuid = other.sourceUuid;
140  zone = other.zone;
141  }
142 
143  static bool is(const BaseMessage * msg)
144  {
145  return (msg->type == "method");
146  }
147 
154  static bool is(const picojson::value & json)
155  {
156  return json.contains("source") && json.get("source").is<std::string>()
157  && json.contains("zone") && json.get("zone").is<double>();
158  }
159 
160  virtual picojson::value toJson();
161  virtual bool fromJson(const picojson::value &json);
162 
163  std::string sourceUuid;
164  Zone::Type zone;
165 };
166 
167 template <class T>
169 {
170 public:
171 
172  MethodReply(): MethodReply(nullptr, false) {}
173  MethodReply(std::shared_ptr<T> t, bool success): mMethod(t), methodSuccess(success), err(AsyncPropertyReply::NoError) { }
174  bool methodSuccess;
175 
176  picojson::value toJson()
177  {
178  picojson::value v = mMethod->toJson();
179 
180  picojson::object obj = v.get<picojson::object>();
181  obj["methodSuccess"] = picojson::value(methodSuccess);
182  obj["error"] = picojson::value((double)err);
183 
184  return picojson::value(obj);
185  }
186 
187  bool fromJson(const picojson::value & json)
188  {
189  if(!mMethod) mMethod = std::shared_ptr<T>(new T());
190  mMethod->fromJson(json);
191  methodSuccess = json.get("methodSuccess").get<bool>();
192  err = AsyncPropertyReply::Error(json.get("error").get<double>());
193 
194  return true;
195  }
196 
197  static bool is(const picojson::value & v)
198  {
199  return v.contains("methodSuccess") && v.contains("error") && v.get("methodSuccess").is<bool>()
200  && v.get("error").is<double>() && T::is(v);
201  }
202 
204  {
205  return err;
206  }
207 
208  const std::string errorString() { return AsyncPropertyReply::errorToStr(err); }
209 
210  const std::shared_ptr<T> method() { return mMethod; }
211 
212 protected:
213  std::shared_ptr<T> mMethod;
215 };
216 
217 typedef std::function<void (std::vector<Object::Ptr>)> ListCallback;
218 
219 class ListMethodCall : public MethodCall, public PtrMaker<ListMethodCall>
220 {
221 public:
222  ListMethodCall(): MethodCall("list") {}
223  ListMethodCall(const MethodCall & other)
224  :MethodCall(other)
225  {
226  if(!is(&other))
227  throw std::runtime_error("type not list");
228  }
229 
230  picojson::value toJson();
231  bool fromJson(const picojson::value &json);
232 
233  std::vector<Object::Ptr> objectNames;
234 
235  ListCallback replyCallback;
236 
237  static bool is(const BaseMessage * msg)
238  {
239  return msg->name == "list";
240  }
241 
242  static bool is(const picojson::value & json)
243  {
244  return json.get("name").to_str() == "list";
245  }
246 };
247 
248 typedef std::function<void (Object::Ptr)> ObjectCallback;
249 
250 class GetMethodCall : public MethodCall, public PtrMaker<GetMethodCall>
251 {
252 public:
253  GetMethodCall()
254  : MethodCall("get")
255  {
256 
257  }
258 
259  picojson::value toJson();
260  bool fromJson(const picojson::value &json);
261 
262  static bool is(const BaseMessage * msg)
263  {
264  return msg->name == "get";
265  }
266 
267  static bool is(const picojson::value & json)
268  {
269  return json.get("name").to_str() == "get";
270  }
271 
272  Object::Ptr value;
273 
274  ObjectCallback replyCallback;
275 };
276 
277 typedef std::function<void (bool)> SetCallback;
278 
279 class SetMethodCall : public MethodCall, public PtrMaker<SetMethodCall>
280 {
281 public:
282  SetMethodCall()
283  : MethodCall("set")
284  {
285 
286  }
287 
288  picojson::value toJson();
289  bool fromJson(const picojson::value &json);
290 
291  static bool is(const BaseMessage * msg)
292  {
293  return msg->name == "set";
294  }
295 
296  static bool is(const picojson::value & json)
297  {
298  return json.get("name").to_str() == "set";
299  }
300 
301  Object::Ptr value;
302  SetCallback replyCallback;
303 };
304 
305 class SubscribeMethodCall : virtual public MethodCall, public PtrMaker<SubscribeMethodCall>
306 {
307 public:
310  {
311 
312  }
313  SubscribeMethodCall(const std::string & ifaceName)
314  :MethodCall("subscribe"), interfaceName(ifaceName)
315  {
316 
317  }
318 
319  picojson::value toJson();
320  bool fromJson(const picojson::value &json);
321 
322  static bool is(const BaseMessage *msg)
323  {
324  return msg->name == "subscribe";
325  }
326 
327  static bool is(const picojson::value & json)
328  {
329  return json.get("name").to_str() == "subscribe";
330  }
331 
332  std::string interfaceName;
333 };
334 
335 class UnsubscribeMethodCall : public MethodCall, public PtrMaker<UnsubscribeMethodCall>
336 {
337 public:
340  {
341 
342  }
343 
345  : UnsubscribeMethodCall(call.interfaceName)
346  {
347  sourceUuid = call.sourceUuid;
348  zone = call.zone;
349  }
350 
351  UnsubscribeMethodCall(const std::string & ifaceName)
352  :MethodCall("unsubscribe"), interfaceName(ifaceName)
353  {
354 
355  }
356 
357  static bool is(const BaseMessage *msg)
358  {
359  return msg->name == "unsubscribe";
360  }
361 
362  static bool is(const picojson::value & json)
363  {
364  return json.get("name").to_str() == "unsubscribe";
365  }
366 
367  picojson::value toJson();
368  bool fromJson(const picojson::value &json);
369 
370  std::string interfaceName;
371 };
372 
373 class EventMessage : public BaseMessage
374 {
375 public:
376  EventMessage(const std::string & name)
377  :BaseMessage("event", name) {}
378 
379  static bool is(const BaseMessage & msg)
380  {
381  return msg.type == "event";
382  }
383 
384  static bool is(const picojson::value &json)
385  {
386  return json.get("type").to_str() == "event";
387  }
388 };
389 
390 class TimeSyncMessage : public BaseMessage, public PtrMaker<TimeSyncMessage>
391 {
392 public:
394  :BaseMessage("timeSync", "message"), serverTime(0)
395  {
396 
397  }
398 
399  double serverTime;
400 
401  picojson::value toJson();
402  bool fromJson(const picojson::value &json);
403 
404  static bool is(const BaseMessage & msg)
405  {
406  return msg.type == "message" && msg.name == "timeSync";
407  }
408 
409  static bool is(const picojson::value &json)
410  {
411  return json.contains("serverTime") && json.get("name").to_str() == "timeSync" && json.get("serverTime").is<double>();
412  }
413 };
414 
415 class PropertyChangeEvent: public EventMessage, public PtrMaker<PropertyChangeEvent>
416 {
417 public:
418  PropertyChangeEvent() : EventMessage("propertyChanged"), zone(Zone::None) {}
419 
420 
421  picojson::value toJson();
422  bool fromJson(const picojson::value &json);
423 
424  static bool is(const BaseMessage & msg)
425  {
426  return msg.type == "event" && msg.name == "propertyChanged";
427  }
428 
429  static bool is(const picojson::value &json)
430  {
431  return EventMessage::is(json) && json.get("name").to_str() == "propertyChanged" && json.contains("data") && json.get("data").is<picojson::object>();
432  }
433 
434  Object::Ptr value;
435  std::string sourceUuid;
436  Zone::Type zone;
437 };
438 
440 {
441 public:
442  BaseJsonMessageReader(AbstractIo* io);
443 
444  void canHasData();
445  void closed();
446 
447  std::function<void (void)> disconnected;
448 
449 protected:
450 
451  virtual void hasJsonMessage(const picojson::value & message) = 0;
452 
453  template <class T>
454  void send(T & msg)
455  {
456  std::string buff = msg.toJson().serialize()+"\n";
457  DebugOut() << "writing: " << buff << endl;
458  mIo->write(buff);
459  }
460 
461  template <class T>
462  void send(std::shared_ptr<T> msg)
463  {
464  std::string buff = msg->toJson().serialize()+"\n";
465  DebugOut() << "writing: " << buff << endl;
466  mIo->write(buff);
467  }
468 
469  std::shared_ptr<AbstractIo> mIo;
470 
471 private:
472 
473  bool hasJson();
474 
475  std::string incompleteMessage;
476 
477 };
478 
480 {
481 public:
482 
484  {
485  public:
486  Subscription(SubscribeMethodCall subscribeCall, const ObjectCallback & cb)
487  :call(subscribeCall), callback(cb) {}
488  bool operator ==(const Subscription &rhs)
489  {
490  return rhs.subscriptionId() == subscriptionId();
491  }
492 
493  const std::string subscriptionId() const { return call.messageId; }
494  SubscribeMethodCall call;
495  ObjectCallback callback;
496  };
497 
498  AmbRemoteClient(AbstractIo* io);
499 
500  void list(ListCallback cb);
501 
502  void get(const std::string & objectName, ObjectCallback cb);
503 
504  void get(const std::string & objectName, const std::string & sourceUuid, ObjectCallback cb);
505 
506  void get(const std::string & objectName, Zone::Type zone, ObjectCallback cb);
507 
508  void get(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
509 
510  void set(const std::string & objectName, Object::Ptr value, SetCallback cb);
511 
512  void set(const std::string & objectName, Object::Ptr value, const std::string & sourceUuid, Zone::Type zone, SetCallback cb);
513 
514  const std::string subscribe(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
515 
516  void subscribe(const std::string & objectName, ObjectCallback cb);
517 
518  void unsubscribe(const std::string & subscribeId);
519 
520 protected:
521 
522  double correctTimeFromServer(double serverTimestamp);
523 
524 private:
525 
526  void hasJsonMessage(const picojson::value & message);
527 
528  std::string createSubscriptionId(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone);
529  std::vector<ListMethodCall::Ptr> mListCalls;
530  std::vector<GetMethodCall::Ptr> mGetMethodCalls;
531  std::vector<SetMethodCall::Ptr> mSetMethodCalls;
532  std::unordered_map<std::string, std::vector<Subscription>> mSubscriptions;
533 
534  double serverTimeOffset;
535 };
536 
537 class AmbRemoteServer : public BaseJsonMessageReader, public PtrMaker<AmbRemoteServer>
538 {
539 public:
540  AmbRemoteServer(AbstractIo* io, AbstractRoutingEngine* routingEngine);
541 
542 protected:
543 
547  virtual void list(ListMethodCall::Ptr call);
548 
552  virtual void get(GetMethodCall::Ptr get);
553 
557  virtual void set(SetMethodCall::Ptr set);
561  virtual void subscribe(SubscribeMethodCall::Ptr call);
562 
563  virtual void unsubscribe(UnsubscribeMethodCall::Ptr call);
564 
565  void hasJsonMessage(const picojson::value & json);
566 
567 protected:
568  AbstractRoutingEngine* routingEngine;
569 };
570 
571 } //namespace amb
572 
573 #endif