~~~~~~~~~~~~~{.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"
}
~~~~~~~~~~~~~
-set(amb_sources abstractpropertytype.cpp abstractroutingengine.cpp listplusplus.cpp abstractsink.cpp vehicleproperty.cpp abstractsource.cpp debugout.cpp timestamp.cpp uuidhelper.cpp mappropertytype.hpp propertyinfo.hpp superptr.hpp asyncqueue.hpp ambpluginimpl.cpp ambplugin.h picojson.h)
-set(amb_headers_install abstractpropertytype.h nullptr.h abstractroutingengine.h listplusplus.h abstractsink.h vehicleproperty.h debugout.h abstractsource.h timestamp.h uuidhelper.h mappropertytype.hpp propertyinfo.hpp superptr.hpp asyncqueue.hpp ambplugin.h ambpluginimpl.h picojson.h)
+set(amb_sources abstractpropertytype.cpp abstractroutingengine.cpp listplusplus.cpp abstractsink.cpp vehicleproperty.cpp abstractsource.cpp debugout.cpp timestamp.cpp uuidhelper.cpp mappropertytype.hpp propertyinfo.hpp superptr.hpp asyncqueue.hpp ambpluginimpl.cpp ambplugin.h picojson.h jsonhelper.cpp)
+set(amb_headers_install abstractpropertytype.h nullptr.h abstractroutingengine.h listplusplus.h abstractsink.h vehicleproperty.h debugout.h abstractsource.h timestamp.h uuidhelper.h mappropertytype.hpp propertyinfo.hpp superptr.hpp asyncqueue.hpp ambplugin.h ambpluginimpl.h picojson.h jsonhelper.h)
add_library(amb SHARED ${amb_sources})
const Zone::Type Zone::MiddleLeft = Zone::Type(Zone::Middle | Zone::Left);
const Zone::Type Zone::RearRight = Zone::Type(Zone::Rear | Zone::Right);
const Zone::Type Zone::RearLeft = Zone::Type(Zone::Rear | Zone::Left);
+
+
+const picojson::value AbstractPropertyType::toJson()
+{
+ picojson::object obj;
+
+ obj["name"] = picojson::value(name);
+ obj["alias"] = picojson::value(alias());
+ obj["source"] = picojson::value(sourceUuid);
+ obj["zone"] = picojson::value((double)zone);
+ obj["timestamp"] = picojson::value(timestamp);
+ obj["sequence"] = picojson::value((double)sequence);
+ obj["type"] = picojson::value(amb::BasicTypes::fromAbstractProperty(this));
+
+ return picojson::value(obj);
+}
+
+void AbstractPropertyType::fromJson(const picojson::value &json)
+{
+ name = json.get("name").to_str();
+ mAlias = json.get("alias").to_str();
+ sourceUuid = json.get("source").to_str();
+ zone = json.get("zone").get<double>();
+ timestamp = json.get("timestamp").get<double>();
+ sequence = json.get("sequence").get<double>();
+}
#ifndef _ABSTRACTPROPERTYTYPE_H_
#define _ABSTRACTPROPERTYTYPE_H_
-#include <string>
-#include <sstream>
-#include <stdexcept>
-#include <vector>
-#include <iostream>
-#include <memory>
+#include "debugout.h"
+#include "jsonhelper.h"
+#include "picojson.h"
+#include "superptr.hpp"
+#include "timestamp.h"
+
+#include <boost/algorithm/string.hpp>
#include <boost/any.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/utility.hpp>
+#include <iostream>
+#include <list>
+#include <memory>
+#include <string>
+#include <sstream>
+#include <stdexcept>
#include <type_traits>
+#include <vector>
+
#include <glib.h>
-#include <list>
-#include "timestamp.h"
-#include <debugout.h>
-#include <boost/algorithm/string.hpp>
-#include <superptr.hpp>
class Zone {
}
}
- /**
- * @brief toString
- * @return strigified value
+ /*!
+ * \brief toJson convert this type to json representation.
+ * The json typically looks something like this:
+ * \code
+ * {
+ * "name" : "VehicleSpeed",
+ * "type" : "UInt16",
+ * "source" : "daf23v32342ddsdffafaeefe",
+ * "zone" : 0,
+ * "value" : 25
+ * }
+ * \endcode
+ * \return json value representing the type
+ */
+ virtual const picojson::value toJson();
+
+ /*!
+ * \brief fromJson instantiate this type from json
+ * \param json
+ */
+ virtual void fromJson(const picojson::value & json);
+
+ /*!
+ * \brief toString
+ * \return strigified value
*/
virtual std::string toString() const = 0;
- /**
- * @brief fromString converts from string value
+ /*!
+ * \brief fromString converts from string value
*/
- virtual void fromString(std::string)= 0;
+ virtual void fromString(std::string) = 0;
- /**
- * @brief toVariant
- * @return GVariant representation of value. Caller must unref the returned GVariant
+ /*!
+ * \brief toVariant
+ * \return GVariant representation of value. Caller must unref the returned GVariant
*/
virtual GVariant* toVariant() = 0;
- /**
- * @brief fromVariant converts GVariant value into compatible native value. Caller owns
+ /*!
+ * \brief fromVariant converts GVariant value into compatible native value. Caller owns
* GVariant argument.
*/
virtual void fromVariant(GVariant*) = 0;
- /**
- * @brief copy
- * @return a copy of the AbstractPropertyType
+ /*!
+ * \brief copy
+ * \return a copy of the AbstractPropertyType
*/
virtual AbstractPropertyType* copy() = 0;
- /**
- * @brief quickCopy is intended as a way to quickly copy the often changing bits from one abstract property to another
+ /*!
+ * \brief quickCopy is intended as a way to quickly copy the often changing bits from one abstract property to another
* It assumes that the properties are almost identical in name, source, and zone.
- * @param other the property to copy from
+ * \param other the property to copy from
*/
virtual void quickCopy(AbstractPropertyType* other)
{
return one != two;
}
- /**
- * @brief name Property name. @see VehicleProperty for built-in supported property names
+ /*!
+ * \brief name Property name. \see VehicleProperty for built-in supported property names
*/
std::string name;
- /**
- * @brief timestamp. Timestamp when the value was last updated by the system. This is updated automatically
+ /*!
+ * \brief alias alias for the property name
+ * \return alias if any of name if alias has not been set
+ */
+ const std::string alias() { return mAlias.empty() ? name : mAlias; }
+
+ void setAlias(const std::string & a) { mAlias = a; }
+
+ /*!
+ * \brief timestamp. Timestamp when the value was last updated by the system. This is updated automatically
* any time setValue() is called
- * @see amb::currentTime()
- * @see setValue()
+ * \see amb::currentTime()
+ * \see setValue()
*/
double timestamp;
- /**
- * @brief sequence internal counter. Useful as a unique indentifier. values is -1 if not used (default).
+ /*!
+ * \brief sequence internal counter. Useful as a unique indentifier. values is -1 if not used (default).
*/
int32_t sequence;
- /**
- * @brief sourceUuid uuid of the source that produced this property. This is set by the routingengine
+ /*!
+ * \brief sourceUuid uuid of the source that produced this property. This is set by the routingengine
* if left unmodified.
*/
std::string sourceUuid;
- /**
- * @brief zone that the property is situated in.
+ /*!
+ * \brief zone that the property is situated in.
*/
Zone::Type zone;
*/
Priority priority;
- /**
- * @brief setValue
- * @param val boost::any value. NOTE: boost::any does not accept type coercion. Types must match exactly
+ /*!
+ * \brief setValue
+ * \param val boost::any value. NOTE: boost::any does not accept type coercion. Types must match exactly
* with native type. (ie, don't use "int" if the native type is "uint")
*/
virtual void setValue(boost::any val)
timestamp = amb::currentTime();
}
- /**
+ /*!
* \brief value() native value. Does not use type coercion. Will throw if types do not match.
*/
template <typename T>
return boost::any_cast<T>(mValue);
}
- /**
- * @brief anyValue
- * @return boost::any value
+ /*!
+ * \brief anyValue
+ * \return boost::any value
*/
boost::any anyValue()
{
return s;
}
- /**
- * @brief destroyed is called if this property is destroyed.
+ /*!
+ * \brief destroyed is called if this property is destroyed.
*/
std::vector<std::function<void(AbstractPropertyType*)>> destroyed;
boost::any mValue;
+ std::string mAlias;
};
namespace amb
}
+class JsonNumber
+{
+public:
+ static double fromJson(picojson::value v)
+ {
+ return v.get<double>();
+ }
+
+ static picojson::value toJson(double v)
+ {
+ return picojson::value(v);
+ }
+};
+
+class JsonBoolean
+{
+public:
+ static bool fromJson(picojson::value v)
+ {
+ return v.get<bool>();
+ }
+
+ static picojson::value toJson(bool v)
+ {
+ return picojson::value(v);
+ }
+};
+
+class JsonString
+{
+public:
+ static std::string fromJson(picojson::value v)
+ {
+ return v.get<std::string>();
+ }
+
+ static picojson::value toJson(std::string v)
+ {
+ return picojson::value(v);
+ }
+};
+
+
+template <typename T>
+class BaseGVS
+{
+public:
+ static T gvalue(T t)
+ {
+ return t;
+ }
+};
+
template <typename T>
class GVS;
template <>
-class GVS<int>
+class GVS<int> : public BaseGVS<int>, public JsonNumber
{
public:
static const char* signature() { return "i"; }
};
template <>
-class GVS<double>
+class GVS<double> : public BaseGVS<double>, public JsonNumber
{
public:
static const char* signature() { return "d"; }
};
template <>
-class GVS<uint16_t>
+class GVS<uint16_t> : public BaseGVS<uint16_t>, public JsonNumber
{
public:
static const char* signature() { return "q"; }
};
template <>
-class GVS<int16_t>
+class GVS<int16_t> : public BaseGVS<int16_t>, public JsonNumber
{
public:
static const char* signature() { return "n"; }
};
template <>
-class GVS<char>
+class GVS<char> : public BaseGVS<char>, public JsonNumber
{
public:
static const char* signature() { return "y"; }
};
template <>
-class GVS<uint32_t>
+class GVS<uint32_t> : public BaseGVS<uint32_t>, public JsonNumber
{
public:
static const char* signature() { return "u"; }
};
template <>
-class GVS<int64_t>
+class GVS<int64_t> : public BaseGVS<int64_t>, public JsonNumber
{
public:
static const char* signature() { return "x"; }
};
template <>
-class GVS<uint64_t>
+class GVS<uint64_t> : public BaseGVS<uint64_t>, public JsonNumber
{
public:
static const char* signature() { return "t"; }
};
template <>
-class GVS<bool>
+class GVS<bool> : public BaseGVS<bool>, public JsonBoolean
{
public:
static const char* signature() { return "b"; }
}
};
-/**
+template <>
+class GVS<std::string> : public JsonString
+{
+public:
+ static const char* signature() { return "s"; }
+
+ static const char* value(GVariant *v)
+ {
+ return g_variant_get_string(v, nullptr);
+ }
+ static std::string stringize(std::string v)
+ {
+ return v;
+ }
+ static const char* gvalue(std::string v)
+ {
+ return v.c_str();
+ }
+};
+
+/*!
* \brief BasicPropertyType is a typed property type. Most internal types are derived from this class
* \example
* std::unique_ptr<BasicPropertyType<int>> boostPSI = new BasicPropertyType<int>("BoostPSI",5);
return new BasicPropertyType<T>(*this);
}
+ const picojson::value toJson()
+ {
+ picojson::value v = AbstractPropertyType::toJson();
+
+ picojson::object object = v.get<picojson::object>();
+
+ object["value"] = amb::gvariantToJson(toVariant());
+
+ return picojson::value(object);
+ }
+
+ virtual void fromJson(const picojson::value &json)
+ {
+ AbstractPropertyType::fromJson(json);
+
+ fromVariant(amb::jsonToGVariant(json.get("value"), signature()));
+ }
+
void fromString(std::string val)
{
if(!val.empty() && val != "")
setValue(deserializeVariant<T>(v));
}
- /**
- * @brief basicValue
- * @return Typed version of value. Slightly more useful than @see AbstractPropertyType::value()
+ /*!
+ * \brief basicValue
+ * \return Typed version of value. Slightly more useful than \see AbstractPropertyType::value()
*/
T basicValue()
private:
- //GVariant* mVariant;
-
template <class N>
- void serialize(std::string val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
+ void serialize(const std::string & val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
{
int someTemp;
}
template <class N>
- void serialize(std::string val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
+ void serialize(const std::string & val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
{
std::stringstream stream(GVS<T>::stringize(val));
N someTemp;
}
template <class N>
- GVariant* serializeVariant(T val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
+ GVariant* serializeVariant(const T val, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
{
- //mVariant = Glib::VariantBase(Glib::Variant<gint16>::create((int)val).gobj());
-
return (g_variant_new("i",(int)val));
}
template <class N>
- GVariant* serializeVariant(T val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
+ GVariant* serializeVariant(const T val, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
{
- //mVariant = Glib::Variant<T>::create(val);
- //mVariant = g_variant_ref(g_variant_new(GVS<T>::signature(),val));
return g_variant_new(GVS<T>::signature(),val);
}
template <class N>
T deserializeVariant(GVariant* v, typename std::enable_if<std::is_enum<N>::value, N>::type* = 0)
{
-// return (T)((Glib::Variant<int>::cast_dynamic<Glib::Variant<int> >(*v)).get());
-
return (T)GVS<int>::value(v);
}
template <class N>
T deserializeVariant(GVariant* v, typename std::enable_if<!std::is_enum<N>::value, N>::type* = 0)
{
- // return Glib::VariantBase::cast_dynamic<Glib::Variant<T> >(*v).get();
return GVS<T>::value(v);
}
};
return value<std::string>() < other.value<std::string>();
}
+ virtual const picojson::value toJson()
+ {
+ auto val = AbstractPropertyType::toJson();
+
+ picojson::object obj = val.get<picojson::object>();
+
+ obj["value"] = amb::gvariantToJson(toVariant());
+ }
+
+ virtual void fromJson(const picojson::value &json)
+ {
+ AbstractPropertyType::fromJson(json);
+
+ fromString(json.get("value").to_str());
+ }
void fromString(std::string val)
{
/*!
* \brief ListPropertyType is a AbstractPropertyType for arrays of AbstractPropertyTypes
*/
-template <class T = AbstractPropertyType>
+template <class T>
class ListPropertyType: public AbstractPropertyType
{
public:
clear();
}
- /** \brief append - appends a property to the list
- * @arg property - property to be appended.
+ /*! \brief append - appends a property to the list
+ * \arg property - property to be appended.
**/
void append(T property)
{
std::string toString() const
{
- std::string str = "[";
+ picojson::array array;
- for(auto itr = mList.begin(); itr != mList.end(); itr++)
+ for(auto i : mList)
{
- if(str != "[")
- str += ",";
-
- T t = *itr;
-
- str += t.toString();
+ array.push_back(GVS<T>::toJson(i));
}
- str += "]";
-
- return str;
+ return picojson::value(array).serialize();
}
- void fromString(std::string str )
+ void fromString(std::string str)
{
- clear();
+ picojson::value value;
+ picojson::parse(value, str);
- if(!str.length())
- return;
+ picojson::array array = value.get<picojson::array>();
- if(str[0] == '[' && str[str.length()-1] == ']')
+ for(auto i : array)
{
- str = str.substr(1,str.length() - 2);
+ mList.push_back(GVS<T>::fromJson(i));
}
- std::vector<std::string> elements;
-
- std::istringstream f(str);
-
- std::string element;
- while(std::getline(f,element,','))
- {
- T foo("", element);
- append (foo);
- }
timestamp = amb::currentTime();
}
GVariant* toVariant()
{
-
GVariantBuilder params;
g_variant_builder_init(¶ms, ((const GVariantType *) "av"));
- for(auto itr = mList.begin(); itr != mList.end(); itr++)
+ for(auto itr : mList)
{
- T t = *itr;
- auto var = t.toVariant();
- GVariant *newvar = g_variant_new("v", var);
+ GVariant *newvar = g_variant_new(GVS<T>::signature(), GVS<T>::gvalue(itr));
g_variant_builder_add_value(¶ms, newvar);
}
{
GVariant *childvariant = g_variant_get_child_value(v,i);
GVariant *innervariant = g_variant_get_variant(childvariant);
- T t;
- t.fromVariant(innervariant);
- appendPriv(t);
+ appendPriv(GVS<T>::value(innervariant));
}
}
DebugOut const& operator << (ostream & (*manip)(std::ostream&)) const
{
-
-
if(mDebugLevel <= debugThreshhold || mDebugLevel == Error || mDebugLevel == Warning)
{
ostream out(buf);
--- /dev/null
+#include "jsonhelper.h"
+
+#include "abstractpropertytype.h"
+#include "debugout.h"
+
+const char * amb::BasicTypes::UInt16Str = "UInt16";
+const char * amb::BasicTypes::UInt32Str = "UInt32";
+const char * amb::BasicTypes::Int16Str = "Int16";
+const char * amb::BasicTypes::Int32Str = "Int32";
+const char * amb::BasicTypes::StringStr = "String";
+const char * amb::BasicTypes::DoubleStr = "Double";
+const char * amb::BasicTypes::BooleanStr = "Boolean";
+
+picojson::value amb::gvariantToJson(GVariant* value)
+{
+ std::string type = g_variant_get_type_string(value);
+ picojson::value v;
+
+ if (type == "i")
+ {
+ int tempVal = GVS<int>::value(value);
+ v = picojson::value(static_cast<double>(tempVal));
+ }
+ else if (type == "d")
+ {
+ v = picojson::value(GVS<double>::value(value));
+ }
+ else if (type == "q")
+ {
+ v = picojson::value(static_cast<double>(GVS<uint16_t>::value(value)));
+ }
+ else if (type == "n")
+ {
+ v = picojson::value(static_cast<double>(GVS<int16_t>::value(value)));
+ }
+ else if (type == "y")
+ {
+ v = picojson::value(static_cast<double>(GVS<char>::value(value)));
+ }
+ else if (type == "u")
+ {
+ v = picojson::value(static_cast<double>(GVS<uint32_t>::value(value)));
+ }
+ else if (type == "x")
+ {
+ v = picojson::value(static_cast<double>(GVS<int64_t>::value(value)));
+ }
+ else if (type == "t")
+ {
+ v = picojson::value(static_cast<double>(GVS<uint64_t>::value(value)));
+ }
+ else if (type == "b")
+ {
+ v = picojson::value(GVS<bool>::value(value));
+ }
+ else if (type == "s")
+ {
+ v = picojson::value(g_variant_get_string(value, nullptr));
+ }
+ else
+ {
+ DebugOut(DebugOut::Error) << "Unsupported type: " << type << endl;
+ }
+
+ return v;
+}
+
+const std::string amb::BasicTypes::fromSignature(const string &sig)
+{
+ if(sig.empty()) return "";
+
+ char c = sig[0];
+
+ if(c == G_VARIANT_CLASS_BOOLEAN)
+ return BooleanStr;
+
+ else if(c == G_VARIANT_CLASS_BYTE)
+ return "";
+
+ else if(c == G_VARIANT_CLASS_INT16)
+ return Int16Str;
+
+ else if(c == G_VARIANT_CLASS_UINT16)
+ return UInt16Str;
+
+ else if(c == G_VARIANT_CLASS_INT32)
+ return Int32Str;
+
+ else if(c == G_VARIANT_CLASS_UINT32)
+ return UInt32Str;
+
+ else if(c == G_VARIANT_CLASS_INT64)
+ return "";
+
+ else if(c == G_VARIANT_CLASS_UINT64)
+ return "";
+
+ else if(c == G_VARIANT_CLASS_DOUBLE)
+ return DoubleStr;
+
+ else if(c == G_VARIANT_CLASS_STRING)
+ return StringStr;
+
+ else if(c == G_VARIANT_CLASS_ARRAY)
+ {
+ ///TODO support array and map
+ return "";
+ }
+ return "";
+}
+
+
+
+
+const string amb::BasicTypes::fromAbstractProperty(AbstractPropertyType *property)
+{
+ return fromSignature(property->signature());
+}
+
+
+GVariant *amb::jsonToGVariant(const picojson::value & value, const std::string& type)
+{
+ GVariant* v = nullptr;
+
+ if (type == "i") {
+ v = g_variant_new(type.c_str(), (int32_t)value.get<double>());
+ } else if (type == "d") {
+ v = g_variant_new(type.c_str(), value.get<double>());
+ } else if (type == "q") {
+ v = g_variant_new(type.c_str(), (uint16_t)value.get<double>());
+ } else if (type == "n") {
+ v = g_variant_new(type.c_str(), (int16_t)value.get<double>());
+ } else if (type == "u") {
+ v = g_variant_new(type.c_str(), (uint32_t)value.get<double>());
+ } else if (type == "x") {
+ v = g_variant_new(type.c_str(), (int64_t)value.get<double>());
+ } else if (type == "t") {
+ v = g_variant_new(type.c_str(), (uint64_t)value.get<double>());
+ } else if (type == "b") {
+ v = g_variant_new(type.c_str(), value.get<bool>());
+ } else if (type == "s") {
+ v = g_variant_new(type.c_str(), value.get<std::string>().c_str());
+ } else {
+ DebugOut(DebugOut::Error) << "Unsupported type: " << type << endl;
+ }
+
+ return v;
+}
--- /dev/null
+#ifndef _JSON_HELPER_H_
+#define _JSON_HELPER_H_
+
+#include "picojson.h"
+
+#include <memory>
+
+#include <glib.h>
+
+class AbstractPropertyType;
+
+namespace amb
+{
+namespace BasicTypes
+{
+enum BasicTypeEnum
+{
+ UInt16,
+ UInt32,
+ Int16,
+ Int32,
+ String,
+ Double,
+ Boolean
+};
+
+extern const char * UInt16Str;
+extern const char * UInt32Str;
+extern const char * Int16Str;
+extern const char * Int32Str;
+extern const char * StringStr;
+extern const char * DoubleStr;
+extern const char * BooleanStr;
+
+const std::string fromSignature(std::string const & sig);
+
+const std::string fromAbstractProperty(AbstractPropertyType *property);
+
+} // BasicTypes
+
+picojson::value gvariantToJson(GVariant* value);
+
+GVariant * jsonToGVariant(const picojson::value & json, const std::string & signature);
+
+std::shared_ptr<AbstractPropertyType> jsonToProperty(const picojson::value& json);
+
+picojson::value propertyToJson(std::shared_ptr<AbstractPropertyType> property);
+
+}
+
+#endif
+
}
}
+namespace amb
+{
+template <class T, class Key>
+bool containsKey(const T & map, const Key & key)
+{
+ return map.find(key) != map.end();
+}
+}
+
#endif // LISTPLUSPLUS_H
#include <debugout.h>
#include "picojson.h"
-template <class N = AbstractPropertyType*>
+template <class N>
class MapPropertyType: public AbstractPropertyType
{
public:
return t;
}
- bool contains(std::string key)
- {
- return mMap.find(key) != mMap.end();
- }
-
- N operator[](std::string key)
- {
- return mMap[key];
- }
-
- std::vector<std::string> keys()
- {
- std::vector<std::string> list;
-
- for(auto itr : mMap)
- {
- list.push_back(itr.first);
- }
-
- return list;
- }
-
std::string toString() const
{
std::stringstream str;
REGISTERPROPERTY( VehiclePowerMode, Power::Off);
registerPropertyPriv(TripMeters, [](){
TripMetersType* t = new TripMetersType();
- BasicPropertyType<uint16_t> v(0);
- t->append(v);
+ t->append(0);
return t;
});
REGISTERPROPERTY(Direction, 0);
REGISTERPROPERTY(VehicleType, Vehicle::Unknown);
registerPropertyPriv(DoorsPerRow, []() {
- BasicPropertyType<uint16_t> d(0);
DoorsPerRowType* doors = new DoorsPerRowType();
- doors->append(d);
+ doors->append(0);
return doors;
});
REGISTERPROPERTY(TransmissionGearType, Transmission::Unknown);
REGISTERPROPERTY(ActiveNoiseControlMode, false);
registerPropertyPriv(AvailableSounds, [](){
AvailableSoundsType* t = new AvailableSoundsType();
- StringPropertyType v;
- t->append(v);
+ t->append("");
return t;
});
REGISTERPROPERTY(EngineSoundEnhancementMode, "");
*/
static const Property VehiclePowerMode;
PROPERTYTYPE(VehiclePowerMode, VehiclePowerModeType, BasicPropertyType<Power::Modes>, Power::Modes)
- //typedef BasicPropertyType<Power::PowerModes> VehiclePowerModeType;
static const Property TripMeters;
- PROPERTYTYPE(TripMeters, TripMetersType, ListPropertyType<BasicPropertyType<uint16_t> >, uint16_t)
- //typedef ListPropertyType<BasicPropertyType<uint16_t> > TripMetersType;
+ PROPERTYTYPE(TripMeters, TripMetersType, ListPropertyType<uint16_t>, uint16_t)
static const Property CruiseControlActive;
PROPERTYTYPE(CruiseControlActive, CruiseControlActiveType, BasicPropertyType<bool>, bool)
- //typedef BasicPropertyType<bool> CruiseControlActiveType;
static const Property CruiseControlSpeed;
PROPERTYTYPE(CruiseControlSpeed, CruiseControlSpeedType, BasicPropertyType<uint16_t>, uint16_t)
- //typedef BasicPropertyType<uint16_t> CruiseControlSpeedType;
static const Property LightHead;
PROPERTYTYPE(LightHead, LightHeadType, BasicPropertyType<bool>, bool)
PROPERTYTYPE(VehicleType, VehicleTypeType, BasicPropertyType<Vehicle::Type>, Vehicle::Type)
static const Property DoorsPerRow;
- PROPERTYTYPE(DoorsPerRow, DoorsPerRowType, ListPropertyType<BasicPropertyType<uint16_t> >, uint16_t)
+ PROPERTYTYPE(DoorsPerRow, DoorsPerRowType, ListPropertyType<uint16_t>, uint16_t)
static const Property TransmissionGearType;
PROPERTYTYPE(TransmissionGearType, TransmissionGearTypeType, BasicPropertyType<Transmission::Type>, Transmission::Type)
PROPERTYTYPEBASIC(ActiveNoiseControlMode, bool)
static const Property AvailableSounds;
- PROPERTYTYPE(AvailableSounds, AvailableSoundsType, ListPropertyType<StringPropertyType>, StringPropertyType)
+ PROPERTYTYPE(AvailableSounds, AvailableSoundsType, ListPropertyType<std::string>, std::string)
static const Property EngineSoundEnhancementMode;
PROPERTYTYPE(EngineSoundEnhancementMode, EngineSoundEnhancementModeType, StringPropertyType, std::string)
{
QVariant subVariant = var.toList().at(0);
if(subVariant.type() == QVariant::UInt)
- return new ListPropertyType<BasicPropertyType<uint>>(name.toStdString(), subVariant.toUInt());
+ return new ListPropertyType<uint>(name.toStdString(), subVariant.toUInt());
else if(subVariant.type() == QVariant::Double)
- return new ListPropertyType<BasicPropertyType<double>>(name.toStdString(), subVariant.toDouble());
+ return new ListPropertyType<double>(name.toStdString(), subVariant.toDouble());
else if(subVariant.type() == QVariant::Bool)
- return new ListPropertyType<BasicPropertyType<bool>>(name.toStdString(), subVariant.toBool());
+ return new ListPropertyType<bool>(name.toStdString(), subVariant.toBool());
else if(subVariant.type() == QVariant::Int)
- return new ListPropertyType<BasicPropertyType<int>>(name.toStdString(), subVariant.toInt());
+ return new ListPropertyType<int>(name.toStdString(), subVariant.toInt());
else if(subVariant.type() == QVariant::String)
- return new ListPropertyType<StringPropertyType>(name.toStdString(), subVariant.toString().toStdString());
+ return new ListPropertyType<std::string>(name.toStdString(), subVariant.toString().toStdString());
}
return nullptr;
}
#include "jsonprotocol.h"
-#include <glib.h>
-
-const char * amb::BasicTypes::UInt16Str = "UInt16";
-const char * amb::BasicTypes::UInt32Str = "UInt32";
-const char * amb::BasicTypes::Int16Str = "Int16";
-const char * amb::BasicTypes::Int32Str = "Int32";
-const char * amb::BasicTypes::StringStr = "String";
-const char * amb::BasicTypes::DoubleStr = "Double";
-const char * amb::BasicTypes::BooleanStr = "Boolean";
-
-const std::string amb::BasicTypes::fromSignature(const string &sig)
-{
- if(sig.empty()) return "";
-
- char c = sig[0];
-
- if(c == G_VARIANT_CLASS_BOOLEAN)
- return BooleanStr;
-
- else if(c == G_VARIANT_CLASS_BYTE)
- return "";
-
- else if(c == G_VARIANT_CLASS_INT16)
- return Int16Str;
-
- else if(c == G_VARIANT_CLASS_UINT16)
- return UInt16Str;
-
- else if(c == G_VARIANT_CLASS_INT32)
- return Int32Str;
-
- else if(c == G_VARIANT_CLASS_UINT32)
- return UInt32Str;
-
- else if(c == G_VARIANT_CLASS_INT64)
- return "";
-
- else if(c == G_VARIANT_CLASS_UINT64)
- return "";
-
- else if(c == G_VARIANT_CLASS_DOUBLE)
- return DoubleStr;
+#include <jsonhelper.h>
+#include <listplusplus.h>
- else if(c == G_VARIANT_CLASS_STRING)
- return StringStr;
-
- else if(c == G_VARIANT_CLASS_ARRAY)
- {
- ///TODO support array and map
- return "";
- }
- return "";
-}
+#include <glib.h>
bool readCallback(GIOChannel *source, GIOCondition condition, gpointer data)
{
void amb::AmbRemoteClient::get(const string &objectName, amb::AmbRemoteClient::ObjectCallback cb)
{
-
+ get(objectName, "", Zone::None, cb);
}
void amb::AmbRemoteClient::get(const string &objectName, const string &sourceUuid, amb::AmbRemoteClient::ObjectCallback cb)
{
-
+ get(objectName, sourceUuid, Zone::None, cb);
}
void amb::AmbRemoteClient::get(const string &objectName, Zone::Type zone, amb::AmbRemoteClient::ObjectCallback cb)
{
-
+ get(objectName, "", zone, cb);
}
void amb::AmbRemoteClient::get(const string &objectName, const string &sourceUuid, Zone::Type zone, amb::AmbRemoteClient::ObjectCallback cb)
{
+ GetMethodCall getCall;
+ getCall.sourceUuid = sourceUuid;
+ getCall.zone = zone;
+
+ mGetMethodCalls[getCall.messageId] = cb;
+ send(getCall);
}
-void amb::AmbRemoteClient::set(const string &objectName, MapPropertyType<> *value, amb::AmbRemoteClient::ObjectCallback cb)
+void amb::AmbRemoteClient::set(const string &objectName, const Object & value, SetCallback cb)
{
-
+ set(objectName, value, "", Zone::None, cb);
}
-void amb::AmbRemoteClient::set(const string &objectName, MapPropertyType<> *value, const string &sourceUuid, Zone::Type zone, amb::AmbRemoteClient::ObjectCallback cb)
+void amb::AmbRemoteClient::set(const string &objectName, const Object & value, const string &sourceUuid, Zone::Type zone, SetCallback cb)
{
+ SetMethodCall setCall;
+ setCall.sourceUuid = sourceUuid;
+ setCall.zone = zone;
+ setCall.value = value;
+ mSetMethodCalls[setCall.messageId] = cb;
+
+ send(setCall);
}
void amb::AmbRemoteClient::listen(const string &objectName, const string &sourceUuid, Zone::Type zone, amb::AmbRemoteClient::ObjectCallback cb)
void amb::AmbRemoteClient::hasJsonMessage(const picojson::value &json)
{
- BaseMessage message;
-
- message.fromJson(json);
+ DebugOut(7) << "json: " << json.serialize() << endl;
- if(message.is<MethodCall>())
+ if(BaseMessage::is<MethodCall>(json))
{
- MethodCall methodCall(message);
- methodCall.fromJson(json);
-
- if(message.is<ListMethodCall>())
+ if(BaseMessage::is<ListMethodCall>(json))
{
- ListMethodCall listMethodCall(methodCall);
-
+ ListMethodCall listMethodCall;
listMethodCall.fromJson(json);
if(mListCalls.find(listMethodCall.messageId) != mListCalls.end())
mListCalls.erase(listMethodCall.messageId);
}
}
+ else if(BaseMessage::is<GetMethodCall>(json))
+ {
+ GetMethodCall getCall;
+ getCall.fromJson(json);
+
+ if(amb::containsKey(mGetMethodCalls, getCall.messageId))
+ {
+ auto cb = mGetMethodCalls[getCall.messageId];
+
+ try
+ {
+ cb(getCall.value);
+ }
+ catch(...)
+ {
+ DebugOut(DebugOut::Warning) << "Invalid Get callback " << endl;
+ }
+
+ mGetMethodCalls.erase(getCall.messageId);
+ }
+ }
+ else if(BaseMessage::is<SetMethodCall>(json))
+ {
+
+ }
}
}
name = obj["name"].to_str();
messageId = obj["messageId"].to_str();
- if(data.contains("data"))
+ if(json.contains("data"))
{
data = json.get("data");
}
for(auto i : objectNames)
{
- list.push_back(property2Json(i));
+ list.push_back(Object::toJson(i));
}
v["data"] = picojson::value(list);
bool amb::ListMethodCall::fromJson(const picojson::value &json)
{
- if(!MethodCall::fromJson(json) || json.get("type").to_str() != "list" || !data.is<picojson::array>())
+ if(!MethodCall::fromJson(json) || name != "list" || !data.is<picojson::array>())
{
- DebugOut(DebugOut::Error) << "type not 'list' or data not type json array";
+ DebugOut(DebugOut::Error) << "type not 'list' or data not type json array" << endl;
return false;
}
objectNames.clear();
- for(auto i : data.get<picojson::array>())
+ picojson::array dataList = json.get("data").get<picojson::array>();
+
+ for(auto i : dataList)
{
- objectNames.push_back(json2Property(i));
+ if(!i.is<picojson::object>())
+ {
+ DebugOut(DebugOut::Warning) << "Malformed data. Expected 'object'. Got '" << i.to_str() << "'" << endl;
+ continue;
+ }
+ picojson::object obj = i.get<picojson::object>();
+
+ Object ambObj = Object::fromJson(obj);
+
+ objectNames.push_back(ambObj);
}
return true;
}
+picojson::value amb::MethodCall::toJson()
+{
+ picojson::value value = BaseMessage::toJson();
+
+ picojson::object obj = value.get<picojson::object>();
+
+ obj["source"] = picojson::value(sourceUuid);
+ obj["zone"] = picojson::value((double)zone);
+ obj["methodSuccess"] = picojson::value(success);
+
+ return picojson::value(obj);
+}
+
bool amb::MethodCall::fromJson(const picojson::value &json)
{
+ if(!BaseMessage::fromJson(json))
+ return false;
+
+ sourceUuid = json.get("source").to_str();
+ zone = json.get("zone").get<double>();
+
+ if(json.contains("success"))
+ success = json.get("methodSuccess").get<bool>();
return true;
}
-std::shared_ptr<AbstractPropertyType> amb::json2Property(const picojson::value &json)
+std::shared_ptr<AbstractPropertyType> amb::jsonToProperty(const picojson::value &json)
{
- Zone::Type zone = json.get("zone").get<double>();
- std::string name = json.get("property").to_str();
+ std::string name = json.get("name").to_str();
std::string type = json.get("type").to_str();
- std::string source = json.get("source").to_str();
auto t = VehicleProperty::getPropertyTypeForPropertyNameValue(name);
t = VehicleProperty::getPropertyTypeForPropertyNameValue(name);
}
- t->sourceUuid = source;
- t->zone = zone;
+ t->fromJson(json);
return std::shared_ptr<AbstractPropertyType>(t);
}
-picojson::value amb::property2Json(std::shared_ptr<AbstractPropertyType> property)
-{
- std::string signature = property->signature();
- const std::string basicType = amb::BasicTypes::fromSignature(signature);
-
- picojson::object map;
- map["zone"] = picojson::value((double)property->zone);
- map["property"] = picojson::value(property->name);
- map["type"] = picojson::value(basicType);
- map["source"] = picojson::value(property->sourceUuid);
-
- return picojson::value(map);
-}
-
-
-amb::AmbRemoteServer::AmbRemoteServer(AbstractIo *io)
- :BaseJsonMessageReader(io)
+amb::AmbRemoteServer::AmbRemoteServer(AbstractIo *io, AbstractRoutingEngine *re)
+ :BaseJsonMessageReader(io), routingEngine(re)
{
}
}
-void amb::AmbRemoteServer::get()
+void amb::AmbRemoteServer::get(GetMethodCall & get)
{
}
void amb::AmbRemoteServer::hasJsonMessage(const picojson::value &json)
{
+ DebugOut(7) << "json: " << json.serialize() << endl;
+
if(!BaseMessage::validate(json))
{
- DebugOut(DebugOut::Warning) << "not a valid message" << endl;
+ DebugOut(DebugOut::Warning) << "not a valid message: " << json.serialize() << endl;
+ return;
}
if(BaseMessage::is<MethodCall>(json))
listCall.fromJson(json);
list(listCall);
+ }
+ else if(BaseMessage::is<GetMethodCall>(json))
+ {
+ GetMethodCall getCall;
+ getCall.fromJson(json);
- send(&listCall);
+ get(getCall);
}
}
}
-void amb::AmbRemoteServer::send(amb::BaseMessage *msg)
+picojson::value amb::GetMethodCall::toJson()
+{
+ picojson::value val = MethodCall::toJson();
+
+ picojson::object obj = val.get<picojson::object>();
+
+ obj["data"] = Object::toJson(value);
+
+ return picojson::value(obj);
+}
+
+bool amb::GetMethodCall::fromJson(const picojson::value &json)
+{
+ MethodCall::fromJson(json);
+
+ value = Object::fromJson(json.get<picojson::object>());
+}
+
+
+amb::Object amb::Object::fromJson(const picojson::object &obj)
+{
+ if(!amb::containsKey(obj, "interfaceName"))
+ {
+ DebugOut(DebugOut::Warning) << "object missing interfaceName" << endl;
+ return Object();
+ }
+ Object ambObj(obj.at("interfaceName").to_str());
+
+ for(auto i : obj)
+ {
+ if(i.second.is<picojson::object>())
+ ambObj[i.first] = std::shared_ptr<AbstractPropertyType>(amb::jsonToProperty(i.second));
+ }
+
+ return ambObj;
+}
+
+picojson::value amb::Object::toJson(const amb::Object &obj)
+{
+ picojson::object jsonObj;
+ jsonObj["interfaceName"] = picojson::value(obj.interfaceName);
+ for(auto i : obj)
+ {
+ jsonObj[i.second->alias()] = i.second->toJson();
+ }
+
+ return picojson::value(jsonObj);
+}
+
+
+picojson::value amb::SetMethodCall::toJson()
{
- mIo->write(msg->toJson().serialize());
+ picojson::value val = MethodCall::toJson();
+
+ picojson::object obj = val.get<picojson::object>();
+
+ obj["data"] = Object::toJson(value);
+
+ return picojson::value(obj);
+}
+
+bool amb::SetMethodCall::fromJson(const picojson::value &json)
+{
+ MethodCall::fromJson(json);
+
+ value = Object::fromJson(json.get<picojson::object>());
}
namespace amb
{
-namespace BasicTypes
+class Object : public std::unordered_map<std::string, std::shared_ptr<AbstractPropertyType>>
{
-enum BasicTypeEnum
-{
- UInt16,
- UInt32,
- Int16,
- Int32,
- String,
- Double,
- Boolean
-};
+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)
+ {
-extern const char * UInt16Str;
-extern const char * UInt32Str;
-extern const char * Int16Str;
-extern const char * Int32Str;
-extern const char * StringStr;
-extern const char * DoubleStr;
-extern const char * BooleanStr;
+ }
-const std::string fromSignature(std::string const & sig);
+ static Object fromJson(const picojson::object & obj);
-} // BasicTypes
+ static picojson::value toJson(const Object & obj);
-std::shared_ptr<AbstractPropertyType> json2Property(const picojson::value& json);
+ std::string interfaceName;
-picojson::value property2Json(std::shared_ptr<AbstractPropertyType> property );
+};
class BaseMessage
{
static bool validate(const picojson::value & json)
{
- return json.is<picojson::object>() && json.contains("type") && !json.contains("name") && json.contains("messageId");
+ return json.is<picojson::object>() && json.contains("type") && json.contains("name") && json.contains("messageId");
}
template <typename T>
{
public:
MethodCall(std::string name)
- :BaseMessage(name, "method"), zone(Zone::None)
+ :BaseMessage(name, "method"), zone(Zone::None), success(false)
{
}
MethodCall(const BaseMessage & other)
- :BaseMessage(other), zone(Zone::None)
+ :BaseMessage(other), zone(Zone::None), success(false)
{
name = other.name;
}
:MethodCall(other.name)
{
sourceUuid = other.sourceUuid;
+ zone = other.zone;
+ success = other.success;
}
static bool is(const BaseMessage * msg)
*/
static bool is(const picojson::value & json)
{
- return json.contains("sourceUuid") && json.contains("zone");
+ return json.contains("source") && json.get("source").is<std::string>()
+ && json.contains("zone") && json.get("zone").is<double>();
}
+ virtual picojson::value toJson();
virtual bool fromJson(const picojson::value &json);
std::string sourceUuid;
Zone::Type zone;
+ bool success;
};
class ListMethodCall : public MethodCall
picojson::value toJson();
bool fromJson(const picojson::value &json);
- std::vector<std::shared_ptr<AbstractPropertyType>> objectNames;
+ std::vector<Object> objectNames;
static bool is(const BaseMessage * msg)
{
static bool is(const picojson::value & json)
{
- return json.get("type").to_str() != "list" && json.is<picojson::array>();
+ return json.get("name").to_str() == "list";
+ }
+};
+
+class GetMethodCall : public MethodCall
+{
+public:
+ GetMethodCall()
+ : MethodCall("get")
+ {
+
+ }
+
+ picojson::value toJson();
+ bool fromJson(const picojson::value &json);
+
+ static bool is(const BaseMessage * msg)
+ {
+ return msg->name == "get";
+ }
+
+ static bool is(const picojson::value & json)
+ {
+ return json.get("name").to_str() == "get";
}
+
+ Object value;
+};
+
+class SetMethodCall : public MethodCall
+{
+public:
+ SetMethodCall()
+ : MethodCall("set")
+ {
+
+ }
+
+ picojson::value toJson();
+ bool fromJson(const picojson::value &json);
+
+ static bool is(const BaseMessage * msg)
+ {
+ return msg->name == "set";
+ }
+
+ static bool is(const picojson::value & json)
+ {
+ return json.get("name").to_str() != "set";
+ }
+
+ Object value;
};
class BaseJsonMessageReader
virtual void hasJsonMessage(const picojson::value & message) = 0;
+ template <class T>
+ void send(T & msg)
+ {
+ mIo->write(msg.toJson().serialize());
+ }
+
std::shared_ptr<AbstractIo> mIo;
private:
class AmbRemoteClient: public BaseJsonMessageReader
{
public:
- typedef std::function<void (std::vector<std::shared_ptr<AbstractPropertyType>>)> ListCallback;
- typedef std::function<void (MapPropertyType<> *)> ObjectCallback;
+ typedef std::function<void (std::vector<Object>)> ListCallback;
+ typedef std::function<void (Object)> ObjectCallback;
typedef std::function<void (bool)> SetCallback;
AmbRemoteClient(AbstractIo* io);
void get(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
- void set(const std::string & objectName, MapPropertyType<>* value, ObjectCallback cb);
+ void set(const std::string & objectName, const Object & value, SetCallback cb);
- void set(const std::string & objectName, MapPropertyType<>* value, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
+ void set(const std::string & objectName, const Object & value, const std::string & sourceUuid, Zone::Type zone, SetCallback cb);
void listen(const std::string & objectName, const std::string & sourceUuid, Zone::Type zone, ObjectCallback cb);
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, AsyncPropertyReply*> mMethodCalls;
+ std::unordered_map<std::string, ObjectCallback> mGetMethodCalls;
+ std::unordered_map<std::string, SetCallback> mSetMethodCalls;
std::unordered_map<std::string, std::vector<ObjectCallback>> mSubsriptions;
};
class AmbRemoteServer : public BaseJsonMessageReader
{
public:
- AmbRemoteServer(AbstractIo* io);
+ AmbRemoteServer(AbstractIo* io, AbstractRoutingEngine* routingEngine);
protected:
/*!
* \brief get called when a GetMessageCall was received
*/
- virtual void get();
+ virtual void get(GetMethodCall &get);
/*!
* \brief set called when SetMessageCall was received
void hasJsonMessage(const picojson::value & json);
- void send(BaseMessage* msg);
+protected:
+ AbstractRoutingEngine* routingEngine;
+
+
};
} //namespace amb
{
VehicleProperty::DoorsPerRowType temp;
- BasicPropertyType<uint16_t> row1(2);
- BasicPropertyType<uint16_t> row2(2);
- BasicPropertyType<uint16_t> row3(1);
-
- temp.append(row1);
- temp.append(row2);
- temp.append(row3);
+ temp.append(2);
+ temp.append(2);
+ temp.append(1);
reply->value = &temp;
reply->success = true;
DebugOut() << "Testing ListPropertyType... " << endl;
VehicleProperty::TripMetersType* tfirst = new VehicleProperty::TripMetersType();
VehicleProperty::TripMetersType* tsecond = new VehicleProperty::TripMetersType();
- BasicPropertyType<uint16_t> v1(0);
- BasicPropertyType<uint16_t> v2(5);
- BasicPropertyType<uint16_t> v3(10);
- tfirst->append(v1);
- tfirst->append(v2);
- tfirst->append(v3);
+ tfirst->append(0);
+ tfirst->append(5);
+ tfirst->append(10);
tsecond->fromVariant(tfirst->toVariant());
GVariant* testGVSVariant = g_variant_new("i", 9);
*/
-#ifndef OBD2SOURCE_H
-#define OBD2SOURCE_H
-
-
+#ifndef TESTSOURCE_H
+#define TESTSOURCE_H
#include <abstractsource.h>
#include <string>
#include <termios.h>
#include <glib.h>
-
-
-
class TestPlugin : public AbstractSource
{
bool doBinary = false;
-const char * amb::BasicTypes::UInt16Str = "UInt16";
-const char * amb::BasicTypes::UInt32Str = "UInt32";
-const char * amb::BasicTypes::Int16Str = "Int16";
-const char * amb::BasicTypes::Int32Str = "Int32";
-const char * amb::BasicTypes::StringStr = "String";
-const char * amb::BasicTypes::DoubleStr = "Double";
-const char * amb::BasicTypes::BooleanStr = "Boolean";
-
int lwsWrite(libwebsocket *lws, QByteArray d)
{
if(!lws)
json.replace("\t", "");
}
-const std::string amb::BasicTypes::fromSignature(const string &sig)
-{
- if(sig.empty()) return "";
-
- char c = sig[0];
-
- if(c == G_VARIANT_CLASS_BOOLEAN)
- return BooleanStr;
-
- else if(c == G_VARIANT_CLASS_BYTE)
- return "";
-
- else if(c == G_VARIANT_CLASS_INT16)
- return Int16Str;
-
- else if(c == G_VARIANT_CLASS_UINT16)
- return UInt16Str;
-
- else if(c == G_VARIANT_CLASS_INT32)
- return Int32Str;
-
- else if(c == G_VARIANT_CLASS_UINT32)
- return UInt32Str;
-
- else if(c == G_VARIANT_CLASS_INT64)
- return "";
-
- else if(c == G_VARIANT_CLASS_UINT64)
- return "";
-
- else if(c == G_VARIANT_CLASS_DOUBLE)
- return DoubleStr;
-
- else if(c == G_VARIANT_CLASS_STRING)
- return StringStr;
-
- else if(c == G_VARIANT_CLASS_ARRAY)
- {
- ///TODO support array and map
- return "";
- }
- return "";
-}
int lwsWrite(struct libwebsocket *lws, QByteArray d);
int lwsWriteVariant(struct libwebsocket *lws, QVariant d);
-namespace amb
-{
-namespace BasicTypes
-{
-enum BasicTypeEnum
-{
- UInt16,
- UInt32,
- Int16,
- Int32,
- String,
- Double,
- Boolean
-};
-
-extern const char * UInt16Str;
-extern const char * UInt32Str;
-extern const char * Int16Str;
-extern const char * Int32Str;
-extern const char * StringStr;
-extern const char * DoubleStr;
-extern const char * BooleanStr;
-
-const std::string fromSignature(std::string const & sig);
-
-} // BasicTypes
-} // amb
-
#endif
install (PROGRAMS ${amb_tests} DESTINATION bin)
+find_package(Qt5Network)
+find_package(Qt5Core)
+
+if(Qt5Network_FOUND)
+ set(QT_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS})
+ set(QT_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5Network_LIBRARIES})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
+ add_definitions(${Qt5Core_DEFINITIONS})
+
+ include_directories(${CMAKE_SOURCE_DIR}/lib ${include_dirs} ${QT_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/plugins/common)
+
+ add_executable(testProtocol testProtocol.cpp testProtocolCommon.h)
+ target_link_libraries(testProtocol ${link_libraries} amb -L${CMAKE_CURRENT_BINARY_DIR}/lib amb-plugins-common amb-json-protocol -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${QT_LIBRARIES})
+
+ add_executable(testProtocolClient testProtocolClient.cpp testProtocolCommon.h)
+ target_link_libraries(testProtocolClient ${link_libraries} amb -L${CMAKE_CURRENT_BINARY_DIR}/lib amb-plugins-common amb-json-protocol -L${CMAKE_CURRENT_BINARY_DIR}/plugins/common ${QT_LIBRARIES})
+endif()
--- /dev/null
+#include "testProtocolCommon.h"
+
+#include <debugout.h>
+#include <jsonprotocol.h>
+
+#include <QLocalSocket>
+#include <QLocalServer>
+#include <QCoreApplication>
+#include <QObject>
+
+#include <memory>
+
+class Server : public amb::AmbRemoteServer
+{
+public:
+ Server(QLocalSocket* socketConnection): amb::AmbRemoteServer(new DomainSocket(socketConnection), nullptr) {}
+
+
+ // AmbRemoteServer interface
+protected:
+ void list(amb::ListMethodCall &call)
+ {
+ DebugOut(0) << "list called" << endl;
+
+ amb::Object interface1("interface1");
+ amb::Object interface2("interface2");
+
+ interface1.emplace("vehicleSpeed", std::shared_ptr<AbstractPropertyType>(new VehicleProperty::VehicleSpeedType(100)));
+
+ call.objectNames.push_back(interface1);
+ call.objectNames.push_back(interface2);
+ call.success = true;
+
+ send(call);
+ }
+ void get(amb::GetMethodCall &get)
+ {
+ DebugOut(0) << "get called" << endl;
+ }
+};
+
+int main(int argc, char** argv)
+{
+ DebugOut::setDebugThreshhold(7);
+ DebugOut::setThrowErr(true);
+ DebugOut::setThrowWarn(true);
+
+ DebugOut(0) << "Testing AMB json server/client" << endl;
+
+ QCoreApplication app(argc, argv);
+
+ QLocalServer server;
+
+ QLocalServer::removeServer("/tmp/amb");
+
+ if(!server.listen("/tmp/amb"))
+ {
+ DebugOut(DebugOut::Error) << server.errorString().toStdString() << endl;
+ }
+
+
+ DebugOut(0) << "parent waiting for new connection..." << endl;
+ server.waitForNewConnection(-1);
+ QLocalSocket *clientSocket = server.nextPendingConnection();
+
+ g_assert(clientSocket);
+
+ Server *s = new Server(clientSocket);
+
+ app.exec();
+}
--- /dev/null
+#include "testProtocolCommon.h"
+
+#include <debugout.h>
+#include <jsonprotocol.h>
+
+#include <QLocalSocket>
+#include <QLocalServer>
+#include <QCoreApplication>
+#include <QObject>
+
+#include <memory>
+
+void runTest(amb::AmbRemoteClient *c)
+{
+ DebugOut(0) << "calling client->list()" << endl;
+ c->list([](std::vector<amb::Object> supported)
+ {
+ DebugOut(0) << "list call reply" << endl;
+ g_assert(supported.size() == 2);
+ });
+}
+
+int main(int argc, char** argv)
+{
+ DebugOut::setDebugThreshhold(7);
+ DebugOut::setThrowErr(true);
+ DebugOut::setThrowWarn(false);
+
+ DebugOut(0) << "Testing AMB json server/client" << endl;
+
+ QCoreApplication app(argc, argv);
+
+ DomainSocket socket;
+
+ socket.open();
+
+ socket.getSocket()->waitForConnected();
+
+ DebugOut(0) << "We are connected!" << endl;
+
+ amb::AmbRemoteClient client(&socket);
+
+ runTest(&client);
+
+ app.exec();
+}
--- /dev/null
+#ifndef TESTS_PROTOCOL_COMMON_H_
+#define TESTS_PROTOCOL_COMMON_H_
+
+#include <jsonprotocol.h>
+#include <abstractio.hpp>
+#include <QLocalSocket>
+
+class DomainSocket : public AbstractIo
+{
+public:
+
+ DomainSocket() { }
+ DomainSocket(QLocalSocket* sock): socket(sock) { }
+ // AbstractIo interface
+public:
+ bool open()
+ {
+ if(!socket)
+ socket = std::shared_ptr<QLocalSocket>(new QLocalSocket());
+
+ socket->connectToServer("/tmp/amb");
+
+ return socket->errorString().isEmpty();
+ }
+ bool close()
+ {
+ if(socket)
+ socket->close();
+
+ return true;
+ }
+ bool isOpen()
+ {
+ return socket && socket->state() == QLocalSocket::ConnectedState;
+ }
+
+ string read()
+ {
+ return socket->readAll().data();
+ }
+
+ void write(string data)
+ {
+ socket->write(data.c_str(), data.length());
+ }
+
+ int fileDescriptor()
+ {
+ return socket->socketDescriptor();
+ }
+
+ std::string errorString()
+ {
+ return socket->errorString().toStdString();
+ }
+
+ QLocalSocket *getSocket() { return socket.get(); }
+
+private:
+ std::shared_ptr<QLocalSocket> socket;
+};
+
+#endif