~~~~~~~~~~~~~{.json}
{
- "mainloop" : "/usr/lib/i386-linux-gnu/automotive-message-broker/qtmainloopplugin.so",
+ "mainloop" : "/usr/lib/x86_64-linux-gnu/automotive-message-broker/qtmainloopplugin.so",
"plugins" : "/etc/ambd/plugins.d"
}
~~~~~~~~~~~~~
- [AMBClient] c++ client and server library for interfacing with AMB over bluetooth, websockets, etc
## Changes:
+- [Bluemonkey] Bluemonkey and Amb functions now split into separate properties: "bluemonkey" and "amb" respectively. See bluemonkey docs.
## Fixes:
- [AMBClient] c++ client and server library for interfacing with AMB over bluetooth, websockets, etc
## Changes:
+- [Bluemonkey] Bluemonkey and Amb functions now split into separate properties: "bluemonkey" and "amb" respectively. See bluemonkey docs.
## Fixes:
send(timeSyncRequest);
}
-void amb::AmbRemoteClient::list(amb::AmbRemoteClient::ListCallback cb)
+void amb::AmbRemoteClient::list(amb::ListCallback cb)
{
- ListMethodCall methodCall;
-
- mListCalls[methodCall.messageId] = cb;
+ ListMethodCall::Ptr methodCall = ListMethodCall::create();
+ methodCall->replyCallback = cb;
+ mListCalls.push_back(methodCall);
send(methodCall);
}
-void amb::AmbRemoteClient::get(const string &objectName, amb::AmbRemoteClient::ObjectCallback cb)
+void amb::AmbRemoteClient::get(const string &objectName, amb::ObjectCallback cb)
{
get(objectName, "", Zone::None, cb);
}
-void amb::AmbRemoteClient::get(const string &objectName, const string &sourceUuid, amb::AmbRemoteClient::ObjectCallback cb)
+void amb::AmbRemoteClient::get(const string &objectName, const string &sourceUuid, amb::ObjectCallback cb)
{
get(objectName, sourceUuid, Zone::None, cb);
}
-void amb::AmbRemoteClient::get(const string &objectName, Zone::Type zone, amb::AmbRemoteClient::ObjectCallback cb)
+void amb::AmbRemoteClient::get(const string &objectName, Zone::Type zone, amb::ObjectCallback cb)
{
get(objectName, "", zone, cb);
}
-void amb::AmbRemoteClient::get(const string &objectName, const string &sourceUuid, Zone::Type zone, amb::AmbRemoteClient::ObjectCallback cb)
+void amb::AmbRemoteClient::get(const string &objectName, const string &sourceUuid, Zone::Type zone, amb::ObjectCallback cb)
{
- GetMethodCall getCall;
- getCall.sourceUuid = sourceUuid;
- getCall.zone = zone;
- getCall.value = amb::make_shared(new Object(objectName));
+ GetMethodCall::Ptr getCall = GetMethodCall::create();
+ getCall->sourceUuid = sourceUuid;
+ getCall->zone = zone;
+ getCall->value = amb::make_shared(new Object(objectName));
+ getCall->replyCallback = cb;
- mGetMethodCalls[getCall.messageId] = cb;
+ mGetMethodCalls.push_back(getCall);
send(getCall);
}
-void amb::AmbRemoteClient::set(const string &objectName, Object::ObjectPtr value, SetCallback cb)
+void amb::AmbRemoteClient::set(const string &objectName, Object::Ptr value, SetCallback cb)
{
set(objectName, value, "", Zone::None, cb);
}
-void amb::AmbRemoteClient::set(const string &objectName, Object::ObjectPtr value, const string &sourceUuid, Zone::Type zone, SetCallback cb)
+void amb::AmbRemoteClient::set(const string &objectName, Object::Ptr value, const string &sourceUuid, Zone::Type zone, SetCallback cb)
{
- SetMethodCall setCall;
- setCall.sourceUuid = sourceUuid;
- setCall.zone = zone;
- setCall.value = value;
+ SetMethodCall::Ptr setCall = SetMethodCall::create();
+ setCall->sourceUuid = sourceUuid;
+ setCall->zone = zone;
+ setCall->value = value;
+ setCall->replyCallback = cb;
- mSetMethodCalls[setCall.messageId] = cb;
+ mSetMethodCalls.push_back(setCall);
send(setCall);
}
-const string amb::AmbRemoteClient::subscribe(const string &objectName, const string &sourceUuid, Zone::Type zone, amb::AmbRemoteClient::ObjectCallback cb)
+const string amb::AmbRemoteClient::subscribe(const string &objectName, const string &sourceUuid, Zone::Type zone, amb::ObjectCallback cb)
{
std::string subscription = createSubscriptionId(objectName, sourceUuid, zone);
mSubscriptions[subscription].push_back(sub);
+ send(call);
+
return call.messageId;
}
-void amb::AmbRemoteClient::subscribe(const string &objectName, amb::AmbRemoteClient::ObjectCallback cb)
+void amb::AmbRemoteClient::subscribe(const string &objectName, amb::ObjectCallback cb)
{
subscribe(objectName, "", Zone::None, cb);
}
MethodReply<ListMethodCall> listMethodReply;
listMethodReply.fromJson(json);
- const ListMethodCallPtr listMethod = listMethodReply.method();
+ const ListMethodCall::Ptr listMethod = listMethodReply.method();
- if(amb::containsKey(mListCalls, listMethod->messageId))
+ auto itr = std::find_if(mListCalls.begin(), mListCalls.end(),[&listMethod](auto o)
+ {
+ return o->messageId == listMethod->messageId;
+ });
+ if(itr != mListCalls.end())
{
- auto cb = mListCalls[listMethod->messageId];
+ auto found = *itr;
+ auto cb = found->replyCallback;
try
{
DebugOut(DebugOut::Warning) << "callback for 'list' is not valid" << endl;
}
- mListCalls.erase(listMethod->messageId);
+ mListCalls.erase(itr);
}
}
else if(BaseMessage::is<MethodReply<GetMethodCall>>(json))
{
MethodReply<GetMethodCall> reply;
reply.fromJson(json);
- GetMethodCallPtr getCall = reply.method();
+ GetMethodCall::Ptr getCall = reply.method();
- if(amb::containsKey(mGetMethodCalls, getCall->messageId))
+ auto itr = std::find_if(mGetMethodCalls.begin(), mGetMethodCalls.end(),[&getCall](auto o)
{
- auto cb = mGetMethodCalls[getCall->messageId];
+ return o->messageId == getCall->messageId;
+ });
+
+ if(itr != mGetMethodCalls.end())
+ {
+ auto found = *itr;
+ auto cb = found->replyCallback;
try
{
DebugOut(DebugOut::Warning) << "Invalid Get callback " << endl;
}
- mGetMethodCalls.erase(getCall->messageId);
+ mGetMethodCalls.erase(itr);
}
}
else if(BaseMessage::is<MethodReply<SetMethodCall>>(json))
auto call = reply.method();
- if(amb::containsKey(mSetMethodCalls, call->messageId))
+ auto itr = std::find_if(mSetMethodCalls.begin(), mSetMethodCalls.end(),[&call](auto o)
+ {
+ return o->messageId == call->messageId;
+ });
+
+ if(itr != mSetMethodCalls.end())
{
- auto cb = mSetMethodCalls[call->messageId];
+ auto found = *itr;
+ auto cb = found->replyCallback;
try
{
{
DebugOut(DebugOut::Warning) << "Invalid Set callback " << endl;
}
- mSetMethodCalls.erase(call->messageId);
+ mSetMethodCalls.erase(itr);
}
}
}
}
picojson::object obj = i.get<picojson::object>();
- Object::ObjectPtr ambObj = Object::fromJson(obj);
+ Object::Ptr ambObj = Object::fromJson(obj);
objectNames.push_back(ambObj);
}
}
-void amb::AmbRemoteServer::list(ListMethodCallPtr call)
+void amb::AmbRemoteServer::list(ListMethodCall::Ptr call)
{
}
-void amb::AmbRemoteServer::get(GetMethodCallPtr get)
+void amb::AmbRemoteServer::get(GetMethodCall::Ptr get)
{
}
-void amb::AmbRemoteServer::set(SetMethodCallPtr set)
+void amb::AmbRemoteServer::set(SetMethodCall::Ptr set)
{
}
-void amb::AmbRemoteServer::subscribe(SubscribeMethodCallPtr call)
+void amb::AmbRemoteServer::subscribe(SubscribeMethodCall::Ptr call)
{
}
-void amb::AmbRemoteServer::unsubscribe(amb::UnsubscribeMethodCallPtr call)
+void amb::AmbRemoteServer::unsubscribe(amb::UnsubscribeMethodCall::Ptr call)
{
}
{
if(BaseMessage::is<ListMethodCall>(json))
{
- ListMethodCallPtr listCall = BaseMessage::create<ListMethodCall>();
+ ListMethodCall::Ptr listCall = ListMethodCall::create();
listCall->fromJson(json);
list(listCall);
}
else if(BaseMessage::is<GetMethodCall>(json))
{
- GetMethodCallPtr getCall = BaseMessage::create<GetMethodCall>();
+ GetMethodCall::Ptr getCall = GetMethodCall::create();
getCall->fromJson(json);
get(getCall);
}
else if(BaseMessage::is<SetMethodCall>(json))
{
- SetMethodCallPtr setCall = BaseMessage::create<SetMethodCall>();
+ SetMethodCall::Ptr setCall = SetMethodCall::create();
setCall->fromJson(json);
set(setCall);
}
else if(BaseMessage::is<SubscribeMethodCall>(json))
{
- SubscribeMethodCallPtr call = BaseMessage::create<SubscribeMethodCall>();
+ SubscribeMethodCall::Ptr call = SubscribeMethodCall::create();
call->fromJson(json);
subscribe(call);
}
else if(BaseMessage::is<UnsubscribeMethodCall>(json))
{
- UnsubscribeMethodCallPtr call = BaseMessage::create<UnsubscribeMethodCall>();
+ UnsubscribeMethodCall::Ptr call = UnsubscribeMethodCall::create();
call->fromJson(json);
unsubscribe(call);
}
else if(BaseMessage::is<TimeSyncMessage>(json))
{
- TimeSyncMessagePtr call(new TimeSyncMessage);
+ TimeSyncMessage::Ptr call = TimeSyncMessage::create();
call->fromJson(json);
call->serverTime = amb::Timestamp::instance()->epochTime();
}
-amb::Object::ObjectPtr amb::Object::fromJson(const picojson::object &obj)
+amb::Object::Ptr amb::Object::fromJson(const picojson::object &obj)
{
if(!amb::containsKey(obj, "interfaceName"))
{
DebugOut(DebugOut::Warning) << "object missing interfaceName" << endl;
- return ObjectPtr(new Object());
+ return Object::Ptr(new Object());
}
Object * ambObj = new Object(obj.at("interfaceName").to_str());
}
}
- return ObjectPtr(ambObj);
+ return Object::Ptr(ambObj);
}
-picojson::value amb::Object::toJson(const ObjectPtr &obj)
+picojson::value amb::Object::toJson(const Object::Ptr &obj)
{
picojson::object jsonObj;
jsonObj["interfaceName"] = picojson::value(obj->interfaceName);
return true;
}
+picojson::value amb::UnsubscribeMethodCall::toJson()
+{
+ auto json = MethodCall::toJson();
+
+ auto obj = json.get<picojson::object>();
+
+ obj["interfaceName"] = picojson::value(interfaceName);
+
+ return picojson::value(obj);
+}
+
+bool amb::UnsubscribeMethodCall::fromJson(const picojson::value &json)
+{
+ if(!MethodCall::fromJson(json))
+ return false;
+
+ interfaceName = json.get("interfaceName").to_str();
+
+ return true;
+}
+
picojson::value amb::TimeSyncMessage::toJson()
{
return true;
}
+
+
+picojson::value amb::PropertyChangeEvent::toJson()
+{
+ auto val = EventMessage::toJson();
+
+ auto obj = val.get<picojson::object>();
+ obj["data"] = Object::toJson(value);
+ obj["zone"] = picojson::value((double)zone);
+ obj["source"] = picojson::value(sourceUuid);
+
+ return picojson::value(obj);
+}
+
+bool amb::PropertyChangeEvent::fromJson(const picojson::value &json)
+{
+ if(!EventMessage::fromJson(json))
+ return false;
+
+ value = Object::fromJson(json.get("data").get<picojson::object>());
+
+ return true;
+}
namespace amb
{
-class Object : public std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>
+template <class T>
+class PtrMaker
{
public:
- typedef std::shared_ptr<Object> ObjectPtr;
+ typedef std::shared_ptr<T> Ptr;
+
+ static std::shared_ptr<T> create()
+ {
+ return Ptr(new T());
+ }
+};
+class Object : public std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>, public PtrMaker<Object>
+{
+public:
Object(): std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>() { }
Object(const std::string & ifaceName): std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>(),
interfaceName(ifaceName)
}
- static ObjectPtr fromJson(const picojson::object & obj);
+ static Object::Ptr fromJson(const picojson::object & obj);
- static picojson::value toJson(const ObjectPtr & obj);
+ static picojson::value toJson(const Object::Ptr & obj);
std::string interfaceName;
};
+
class BaseMessage
{
public:
- BaseMessage() { }
+ BaseMessage():BaseMessage("", "message") { }
+
+ BaseMessage(std::string t): BaseMessage("", t) {}
BaseMessage(std::string n, std::string t)
: name(n), type(t)
}
BaseMessage(const BaseMessage & other)
- : name(other.name), type(other.type), data(other.data)
+ : BaseMessage(other.name, other.type)
{
}
return T::is(json);
}
- template <class T>
- static std::shared_ptr<T> create()
- {
- return std::shared_ptr<T>(new T());
- }
-
protected:
picojson::value data;
AsyncPropertyReply::Error err;
};
-class ListMethodCall : public MethodCall
+typedef std::function<void (std::vector<Object::Ptr>)> ListCallback;
+
+class ListMethodCall : public MethodCall, public PtrMaker<ListMethodCall>
{
public:
ListMethodCall(): MethodCall("list") {}
picojson::value toJson();
bool fromJson(const picojson::value &json);
- std::vector<Object::ObjectPtr> objectNames;
+ std::vector<Object::Ptr> objectNames;
+
+ ListCallback replyCallback;
static bool is(const BaseMessage * msg)
{
}
};
-class GetMethodCall : public MethodCall
+typedef std::function<void (Object::Ptr)> ObjectCallback;
+
+class GetMethodCall : public MethodCall, public PtrMaker<GetMethodCall>
{
public:
GetMethodCall()
return json.get("name").to_str() == "get";
}
- Object::ObjectPtr value;
+ Object::Ptr value;
+
+ ObjectCallback replyCallback;
};
-class SetMethodCall : public MethodCall
+typedef std::function<void (bool)> SetCallback;
+
+class SetMethodCall : public MethodCall, public PtrMaker<SetMethodCall>
{
public:
SetMethodCall()
return json.get("name").to_str() == "set";
}
- Object::ObjectPtr value;
+ Object::Ptr value;
+ SetCallback replyCallback;
};
-class SubscribeMethodCall : virtual public MethodCall
+class SubscribeMethodCall : virtual public MethodCall, public PtrMaker<SubscribeMethodCall>
{
public:
SubscribeMethodCall()
std::string interfaceName;
};
-class UnsubscribeMethodCall : virtual public MethodCall, public SubscribeMethodCall
+class UnsubscribeMethodCall : public MethodCall, public PtrMaker<UnsubscribeMethodCall>
{
public:
UnsubscribeMethodCall()
return json.get("name").to_str() == "unsubscribe";
}
+ picojson::value toJson();
+ bool fromJson(const picojson::value &json);
+
std::string interfaceName;
};
-class TimeSyncMessage : public BaseMessage
+class EventMessage : public BaseMessage
+{
+public:
+ EventMessage(const std::string & name)
+ :BaseMessage("event", name) {}
+
+ static bool is(const BaseMessage & msg)
+ {
+ return msg.type == "event";
+ }
+
+ static bool is(const picojson::value &json)
+ {
+ return json.get("type").to_str() == "event";
+ }
+};
+
+class TimeSyncMessage : public BaseMessage, public PtrMaker<TimeSyncMessage>
{
public:
TimeSyncMessage()
}
};
+class PropertyChangeEvent: public EventMessage, public PtrMaker<PropertyChangeEvent>
+{
+public:
+ PropertyChangeEvent() : EventMessage("propertyChanged") {}
+
+
+ picojson::value toJson();
+ bool fromJson(const picojson::value &json);
+
+ static bool is(const BaseMessage & msg)
+ {
+ return msg.type == "event" && msg.name == "propertyChanged";
+ }
+
+ static bool is(const picojson::value &json)
+ {
+ return EventMessage::is(json) && json.get("name").to_str() == "propertyChanged" && json.contains("data") && json.get("data").is<picojson::object>();
+ }
+
+ Object::Ptr value;
+ std::string sourceUuid;
+ Zone::Type zone;
+};
+
class BaseJsonMessageReader
{
public:
mIo->write(buff);
}
+ template <class T>
+ void send(std::shared_ptr<T> msg)
+ {
+ std::string buff = msg->toJson().serialize()+"\n";
+ DebugOut() << "writing: " << buff << endl;
+ mIo->write(buff);
+ }
+
std::shared_ptr<AbstractIo> mIo;
private:
};
-
-typedef std::shared_ptr<ListMethodCall> ListMethodCallPtr;
-typedef std::shared_ptr<GetMethodCall> GetMethodCallPtr;
-typedef std::shared_ptr<SetMethodCall> SetMethodCallPtr;
-typedef std::shared_ptr<SubscribeMethodCall> SubscribeMethodCallPtr;
-typedef std::shared_ptr<UnsubscribeMethodCall> UnsubscribeMethodCallPtr;
-typedef std::shared_ptr<TimeSyncMessage> TimeSyncMessagePtr;
-
class AmbRemoteClient: public BaseJsonMessageReader
{
public:
- typedef std::function<void (std::vector<Object::ObjectPtr>)> ListCallback;
- typedef std::function<void (Object::ObjectPtr)> ObjectCallback;
- typedef std::function<void (bool)> SetCallback;
class Subscription
{
const std::string subscriptionId() const { return call.messageId; }
SubscribeMethodCall call;
- AmbRemoteClient::ObjectCallback callback;
+ ObjectCallback callback;
};
AmbRemoteClient(AbstractIo* io);
void get(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
- void set(const std::string & objectName, Object::ObjectPtr value, SetCallback cb);
+ void set(const std::string & objectName, Object::Ptr value, SetCallback cb);
- void set(const std::string & objectName, Object::ObjectPtr value, const std::string & sourceUuid, Zone::Type zone, SetCallback cb);
+ void set(const std::string & objectName, Object::Ptr value, const std::string & sourceUuid, Zone::Type zone, SetCallback cb);
const std::string subscribe(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
void hasJsonMessage(const picojson::value & message);
std::string createSubscriptionId(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone);
- std::unordered_map<std::string, ListCallback> mListCalls;
- std::unordered_map<std::string, ObjectCallback> mGetMethodCalls;
- std::unordered_map<std::string, SetCallback> mSetMethodCalls;
+ std::vector<ListMethodCall::Ptr> mListCalls;
+ std::vector<GetMethodCall::Ptr> mGetMethodCalls;
+ std::vector<SetMethodCall::Ptr> mSetMethodCalls;
std::unordered_map<std::string, std::vector<Subscription>> mSubscriptions;
double serverTimeOffset;
/*!
* \brief list called when a ListMessageCall was received
*/
- virtual void list(ListMethodCallPtr call);
+ virtual void list(ListMethodCall::Ptr call);
/*!
* \brief get called when a GetMessageCall was received
*/
- virtual void get(GetMethodCallPtr get);
+ virtual void get(GetMethodCall::Ptr get);
/*!
* \brief set called when SetMessageCall was received
*/
- virtual void set(SetMethodCallPtr set);
+ virtual void set(SetMethodCall::Ptr set);
/*!
* \brief listen called when ListenMessageCall was received
*/
- virtual void subscribe(SubscribeMethodCallPtr call);
+ virtual void subscribe(SubscribeMethodCall::Ptr call);
- virtual void unsubscribe(UnsubscribeMethodCallPtr call);
+ virtual void unsubscribe(UnsubscribeMethodCall::Ptr call);
void hasJsonMessage(const picojson::value & json);
// AmbRemoteServer interface
protected:
- void list(amb::ListMethodCallPtr call)
+ void list(amb::ListMethodCall::Ptr call)
{
DebugOut(0) << "list called" << endl;
- amb::Object::ObjectPtr interface1(new amb::Object("interface1"));
- amb::Object::ObjectPtr interface2( new amb::Object("interface2"));
+ amb::Object::Object::Ptr interface1(new amb::Object("interface1"));
+ amb::Object::Object::Ptr interface2( new amb::Object("interface2"));
interface1->emplace("vehicleSpeed", std::shared_ptr<AbstractPropertyType>(new VehicleProperty::VehicleSpeedType(speed)));
interface1->emplace("engineSpeed", std::shared_ptr<AbstractPropertyType>(new VehicleProperty::EngineSpeedType(engineSpeed)));
send(reply);
}
- void get(amb::GetMethodCallPtr get)
+ void get(amb::GetMethodCall::Ptr get)
{
DebugOut(0) << "get called" << endl;
if(get->value->interfaceName == "interface1")
{
- amb::Object::ObjectPtr interface1(new amb::Object("interface1"));
+ amb::Object::Object::Ptr interface1(new amb::Object("interface1"));
interface1->emplace("vehicleSpeed", std::shared_ptr<AbstractPropertyType>(new VehicleProperty::VehicleSpeedType(100)));
interface1->emplace("engineSpeed", std::shared_ptr<AbstractPropertyType>(new VehicleProperty::EngineSpeedType(1999)));
}
else if(get->value->interfaceName == "interface2")
{
- amb::Object::ObjectPtr interface2(new amb::Object("interface2"));
+ amb::Object::Object::Ptr interface2(new amb::Object("interface2"));
interface2->emplace("engineSpeed", std::shared_ptr<AbstractPropertyType>(new VehicleProperty::EngineSpeedType(3099)));
get->value = interface2;
amb::MethodReply<amb::GetMethodCall> reply(get, true);
send(reply);
}
}
- void set(amb::SetMethodCallPtr set)
+ void set(amb::SetMethodCall::Ptr set)
{
if(set->value->interfaceName == "interface1")
{
send(reply);
}
}
+ void subscribe(amb::SubscribeMethodCall::Ptr call)
+ {
+ DebugOut(0) << "subcribe to interface " << call->interfaceName << " zone: " << call->zone << " source" << call->sourceUuid << endl;
+
+ if(call->interfaceName == "interface1")
+ {
+ amb::Object::Object::Ptr interface1(new amb::Object("interface1"));
+
+ interface1->emplace("vehicleSpeed", std::shared_ptr<AbstractPropertyType>(new VehicleProperty::VehicleSpeedType(++speed)));
+ interface1->emplace("engineSpeed", std::shared_ptr<AbstractPropertyType>(new VehicleProperty::EngineSpeedType(++engineSpeed)));
+
+ amb::PropertyChangeEvent event;
+ event.value = interface1;
+
+ send(event);
+ }
+ }
uint16_t speed;
uint16_t engineSpeed;
void runTest(amb::AmbRemoteClient *c)
{
DebugOut(0) << "calling client->list()" << endl;
- c->list([](std::vector<amb::Object::ObjectPtr> supported)
+ c->list([](std::vector<amb::Object::Ptr> supported)
{
DebugOut(0) << "list call reply" << endl;
g_assert(supported.size() == 2);
});
DebugOut(0) << "calling client->get()" << endl;
- c->get("interface1", [&c](amb::Object::ObjectPtr obj)
+ c->get("interface1", [&c](amb::Object::Ptr obj)
{
DebugOut(0) << "get call reply" << endl;
g_assert(obj->size() == 2);