2 Copyright (C) 2015 Intel Corporation
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.
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.
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
19 #ifndef AMB_JSON_PROTOCOL_H_
20 #define AMB_JSON_PROTOCOL_H_
25 #include <unordered_map>
28 #include <abstractroutingengine.h>
29 #include <mappropertytype.hpp>
31 #include <uuidhelper.h>
32 #include <vehicleproperty.h>
34 #include "abstractio.hpp"
44 typedef std::shared_ptr<T> Ptr;
46 static std::shared_ptr<T> create()
52 class Object : public std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>, public PtrMaker<Object>
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)
62 static Object::Ptr fromJson(const picojson::object & obj);
64 static picojson::value toJson(const Object::Ptr & obj);
66 std::string interfaceName;
73 BaseMessage():BaseMessage("", "message") { }
75 BaseMessage(std::string t): BaseMessage("", t) {}
77 BaseMessage(std::string n, std::string t)
80 messageId = amb::createUuid();
83 BaseMessage(const BaseMessage & other)
84 : BaseMessage(other.name, other.type)
92 std::string messageId;
94 virtual picojson::value toJson();
95 virtual bool fromJson(const picojson::value & json);
103 static bool validate(const picojson::value & json)
105 return json.is<picojson::object>() && json.contains("type") && json.contains("name") && json.contains("messageId");
108 template <typename T>
109 static bool is(const picojson::value & json)
116 picojson::value data;
121 class MethodCall : public BaseMessage
124 MethodCall(std::string name)
125 :BaseMessage(name, "method"), zone(Zone::None)
130 MethodCall(const BaseMessage & other)
131 :BaseMessage(other), zone(Zone::None)
136 MethodCall(const MethodCall & other)
137 :MethodCall(other.name)
139 sourceUuid = other.sourceUuid;
143 static bool is(const BaseMessage * msg)
145 return (msg->type == "method");
149 * \brief is checks if json message is of this message type
150 * Assumes that json is already a valid \ref BaseMessage
154 static bool is(const picojson::value & json)
156 return json.contains("source") && json.get("source").is<std::string>()
157 && json.contains("zone") && json.get("zone").is<double>();
160 virtual picojson::value toJson();
161 virtual bool fromJson(const picojson::value &json);
163 std::string sourceUuid;
172 MethodReply(): MethodReply(nullptr, false) {}
173 MethodReply(std::shared_ptr<T> t, bool success): mMethod(t), methodSuccess(success), err(AsyncPropertyReply::NoError) { }
176 picojson::value toJson()
178 picojson::value v = mMethod->toJson();
180 picojson::object obj = v.get<picojson::object>();
181 obj["methodSuccess"] = picojson::value(methodSuccess);
182 obj["error"] = picojson::value((double)err);
184 return picojson::value(obj);
187 bool fromJson(const picojson::value & json)
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>());
197 static bool is(const picojson::value & v)
199 return v.contains("methodSuccess") && v.contains("error") && v.get("methodSuccess").is<bool>()
200 && v.get("error").is<double>() && T::is(v);
203 AsyncPropertyReply::Error error()
208 const std::string errorString() { return AsyncPropertyReply::errorToStr(err); }
210 const std::shared_ptr<T> method() { return mMethod; }
213 std::shared_ptr<T> mMethod;
214 AsyncPropertyReply::Error err;
217 typedef std::function<void (std::vector<Object::Ptr>)> ListCallback;
219 class ListMethodCall : public MethodCall, public PtrMaker<ListMethodCall>
222 ListMethodCall(): MethodCall("list") {}
223 ListMethodCall(const MethodCall & other)
227 throw std::runtime_error("type not list");
230 picojson::value toJson();
231 bool fromJson(const picojson::value &json);
233 std::vector<Object::Ptr> objectNames;
235 ListCallback replyCallback;
237 static bool is(const BaseMessage * msg)
239 return msg->name == "list";
242 static bool is(const picojson::value & json)
244 return json.get("name").to_str() == "list";
248 typedef std::function<void (Object::Ptr)> ObjectCallback;
250 class GetMethodCall : public MethodCall, public PtrMaker<GetMethodCall>
259 picojson::value toJson();
260 bool fromJson(const picojson::value &json);
262 static bool is(const BaseMessage * msg)
264 return msg->name == "get";
267 static bool is(const picojson::value & json)
269 return json.get("name").to_str() == "get";
274 ObjectCallback replyCallback;
277 typedef std::function<void (bool)> SetCallback;
279 class SetMethodCall : public MethodCall, public PtrMaker<SetMethodCall>
288 picojson::value toJson();
289 bool fromJson(const picojson::value &json);
291 static bool is(const BaseMessage * msg)
293 return msg->name == "set";
296 static bool is(const picojson::value & json)
298 return json.get("name").to_str() == "set";
302 SetCallback replyCallback;
305 class SubscribeMethodCall : virtual public MethodCall, public PtrMaker<SubscribeMethodCall>
308 SubscribeMethodCall()
309 :SubscribeMethodCall("")
313 SubscribeMethodCall(const std::string & ifaceName)
314 :MethodCall("subscribe"), interfaceName(ifaceName)
319 picojson::value toJson();
320 bool fromJson(const picojson::value &json);
322 static bool is(const BaseMessage *msg)
324 return msg->name == "subscribe";
327 static bool is(const picojson::value & json)
329 return json.get("name").to_str() == "subscribe";
332 std::string interfaceName;
335 class UnsubscribeMethodCall : public MethodCall, public PtrMaker<UnsubscribeMethodCall>
338 UnsubscribeMethodCall()
339 :UnsubscribeMethodCall("")
344 UnsubscribeMethodCall(const SubscribeMethodCall & call)
345 : UnsubscribeMethodCall(call.interfaceName)
347 sourceUuid = call.sourceUuid;
351 UnsubscribeMethodCall(const std::string & ifaceName)
352 :MethodCall("unsubscribe"), interfaceName(ifaceName)
357 static bool is(const BaseMessage *msg)
359 return msg->name == "unsubscribe";
362 static bool is(const picojson::value & json)
364 return json.get("name").to_str() == "unsubscribe";
367 picojson::value toJson();
368 bool fromJson(const picojson::value &json);
370 std::string interfaceName;
373 class EventMessage : public BaseMessage
376 EventMessage(const std::string & name)
377 :BaseMessage("event", name) {}
379 static bool is(const BaseMessage & msg)
381 return msg.type == "event";
384 static bool is(const picojson::value &json)
386 return json.get("type").to_str() == "event";
390 class TimeSyncMessage : public BaseMessage, public PtrMaker<TimeSyncMessage>
394 :BaseMessage("timeSync", "message"), serverTime(0)
401 picojson::value toJson();
402 bool fromJson(const picojson::value &json);
404 static bool is(const BaseMessage & msg)
406 return msg.type == "message" && msg.name == "timeSync";
409 static bool is(const picojson::value &json)
411 return json.contains("serverTime") && json.get("name").to_str() == "timeSync" && json.get("serverTime").is<double>();
415 class PropertyChangeEvent: public EventMessage, public PtrMaker<PropertyChangeEvent>
418 PropertyChangeEvent() : EventMessage("propertyChanged"), zone(Zone::None) {}
421 picojson::value toJson();
422 bool fromJson(const picojson::value &json);
424 static bool is(const BaseMessage & msg)
426 return msg.type == "event" && msg.name == "propertyChanged";
429 static bool is(const picojson::value &json)
431 return EventMessage::is(json) && json.get("name").to_str() == "propertyChanged" && json.contains("data") && json.get("data").is<picojson::object>();
435 std::string sourceUuid;
439 class BaseJsonMessageReader
442 BaseJsonMessageReader(AbstractIo* io);
447 std::function<void (void)> disconnected;
451 virtual void hasJsonMessage(const picojson::value & message) = 0;
456 std::string buff = msg.toJson().serialize()+"\n";
457 DebugOut() << "writing: " << buff << endl;
462 void send(std::shared_ptr<T> msg)
464 std::string buff = msg->toJson().serialize()+"\n";
465 DebugOut() << "writing: " << buff << endl;
469 std::shared_ptr<AbstractIo> mIo;
475 std::string incompleteMessage;
479 class AmbRemoteClient: public BaseJsonMessageReader
486 Subscription(SubscribeMethodCall subscribeCall, const ObjectCallback & cb)
487 :call(subscribeCall), callback(cb) {}
488 bool operator ==(const Subscription &rhs)
490 return rhs.subscriptionId() == subscriptionId();
493 const std::string subscriptionId() const { return call.messageId; }
494 SubscribeMethodCall call;
495 ObjectCallback callback;
498 AmbRemoteClient(AbstractIo* io);
500 void list(ListCallback cb);
502 void get(const std::string & objectName, ObjectCallback cb);
504 void get(const std::string & objectName, const std::string & sourceUuid, ObjectCallback cb);
506 void get(const std::string & objectName, Zone::Type zone, ObjectCallback cb);
508 void get(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
510 void set(const std::string & objectName, Object::Ptr value, SetCallback cb);
512 void set(const std::string & objectName, Object::Ptr value, const std::string & sourceUuid, Zone::Type zone, SetCallback cb);
514 const std::string subscribe(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
516 void subscribe(const std::string & objectName, ObjectCallback cb);
518 void unsubscribe(const std::string & subscribeId);
522 double correctTimeFromServer(double serverTimestamp);
526 void hasJsonMessage(const picojson::value & message);
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;
534 double serverTimeOffset;
537 class AmbRemoteServer : public BaseJsonMessageReader, public PtrMaker<AmbRemoteServer>
540 AmbRemoteServer(AbstractIo* io, AbstractRoutingEngine* routingEngine);
545 * \brief list called when a ListMessageCall was received
547 virtual void list(ListMethodCall::Ptr call);
550 * \brief get called when a GetMessageCall was received
552 virtual void get(GetMethodCall::Ptr get);
555 * \brief set called when SetMessageCall was received
557 virtual void set(SetMethodCall::Ptr set);
559 * \brief listen called when ListenMessageCall was received
561 virtual void subscribe(SubscribeMethodCall::Ptr call);
563 virtual void unsubscribe(UnsubscribeMethodCall::Ptr call);
565 void hasJsonMessage(const picojson::value & json);
568 AbstractRoutingEngine* routingEngine;