2 Copyright (C) 2012 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
20 #include "bluemonkey.h"
21 #include "abstractroutingengine.h"
22 #include "ambplugin.h"
25 #include <QJsonDocument>
35 #define foreach Q_FOREACH
37 typedef std::map<std::string, QObject*> create_bluemonkey_module_t(std::map<std::string, std::string> config, QObject* parent);
39 extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config)
41 auto plugin = new AmbPlugin<BluemonkeySink>(routingengine, config);
47 QVariant gvariantToQVariant(GVariant *value)
49 GVariantClass c = g_variant_classify(value);
50 if(c == G_VARIANT_CLASS_BOOLEAN)
51 return QVariant((bool) g_variant_get_boolean(value));
53 else if(c == G_VARIANT_CLASS_BYTE)
54 return QVariant((char) g_variant_get_byte(value));
56 else if(c == G_VARIANT_CLASS_INT16)
57 return QVariant((int) g_variant_get_int16(value));
59 else if(c == G_VARIANT_CLASS_UINT16)
60 return QVariant((unsigned int) g_variant_get_uint16(value));
62 else if(c == G_VARIANT_CLASS_INT32)
63 return QVariant((int) g_variant_get_int32(value));
65 else if(c == G_VARIANT_CLASS_UINT32)
66 return QVariant((unsigned int) g_variant_get_uint32(value));
68 else if(c == G_VARIANT_CLASS_INT64)
69 return QVariant((long long) g_variant_get_int64(value));
71 else if(c == G_VARIANT_CLASS_UINT64)
72 return QVariant((unsigned long long) g_variant_get_uint64(value));
74 else if(c == G_VARIANT_CLASS_DOUBLE)
75 return QVariant(g_variant_get_double(value));
77 else if(c == G_VARIANT_CLASS_STRING)
78 return QVariant(g_variant_get_string(value, NULL));
80 else if(c == G_VARIANT_CLASS_ARRAY)
82 gsize dictsize = g_variant_n_children(value);
84 for (int i=0;i<dictsize;i++)
86 GVariant *childvariant = g_variant_get_child_value(value,i);
87 GVariant *innervariant = g_variant_get_variant(childvariant);
88 list.append(gvariantToQVariant(innervariant));
94 return QVariant::Invalid;
98 BluemonkeySink::BluemonkeySink(AbstractRoutingEngine* e, map<string, string> config, AbstractSource &parent): QObject(0), AmbPluginImpl(e, config, parent), engine(nullptr), mSilentMode(false)
100 QTimer::singleShot(1,this,SLOT(reloadEngine()));
102 auth = new Authenticate(config, this);
104 qmlRegisterType<QTimer>("", 1, 0, "QTimer");
108 PropertyList BluemonkeySink::subscriptions()
113 void BluemonkeySink::supportedChanged(const PropertyList & supportedProperties)
115 DebugOut()<<"supported changed"<<endl;
118 void BluemonkeySink::propertyChanged(AbstractPropertyType * value)
123 const string BluemonkeySink::uuid() const
128 int BluemonkeySink::supportedOperations()
130 return AbstractSource::Get | AbstractSource::Set;
133 QObject *BluemonkeySink::subscribeTo(QString str)
135 return new Property(str.toStdString(), "", routingEngine, Zone::None, this);
138 QObject *BluemonkeySink::subscribeToSource(QString str, QString srcFilter)
140 return new Property(str.toStdString(), srcFilter, routingEngine, Zone::None, this);
143 QObject* BluemonkeySink::subscribeToZone(QString str, int zone)
145 return new Property(str.toStdString(), "", routingEngine, zone, this);
149 QStringList BluemonkeySink::sourcesForProperty(QString property)
151 std::list<std::string> list = routingEngine->sourcesForProperty(property.toStdString());
153 for(auto itr = list.begin(); itr != list.end(); itr++)
155 strList<<(*itr).c_str();
161 QStringList BluemonkeySink::supportedProperties()
163 PropertyList props = routingEngine->supported();
174 bool BluemonkeySink::authenticate(QString pass)
179 void BluemonkeySink::loadConfig(QString str)
182 if(!file.open(QIODevice::ReadOnly))
184 DebugOut(DebugOut::Error)<<"failed to open config file: "<<str.toStdString()<<endl;
188 QString script = file.readAll();
192 DebugOut()<<"evaluating script: "<<script.toStdString()<<endl;
194 QJSValue val = engine->evaluate(script);
196 DebugOut()<<val.toString().toStdString()<<endl;
199 bool BluemonkeySink::loadModule(QString path)
201 void* handle = dlopen(path.toUtf8().data(), RTLD_LAZY);
205 DebugOut(DebugOut::Warning) << "bluemonkey load module failed: " << dlerror() << endl;
209 void* c = dlsym(handle, "create");
213 DebugOut(DebugOut::Warning) << "bluemonkey load module failed: " << path.toStdString() << " " << dlerror() << endl;
217 create_bluemonkey_module_t* create = (create_bluemonkey_module_t*)(c);
219 std::map<std::string, QObject*> exports = create(configuration, this);
221 for(auto i : exports)
223 QJSValue val = engine->newQObject(i.second);
224 engine->globalObject().setProperty(i.first.c_str(), val);
230 void BluemonkeySink::reloadEngine()
233 engine->deleteLater();
235 engine = new QJSEngine(this);
237 QJSValue value = engine->newQObject(this);
238 engine->globalObject().setProperty("bluemonkey", value);
240 loadConfig(configuration["config"].c_str());
243 void BluemonkeySink::writeProgram(QString program)
247 QJSValue result = temp.evaluate(program);
250 DebugOut(DebugOut::Error)<<"Syntax error in program: "<<result.toString().toStdString()<<endl;
254 QFile file(configuration["customPrograms"].c_str());
256 if(!file.open(QIODevice::ReadWrite | QIODevice::Append))
258 DebugOut(DebugOut::Error)<<"failed to open file: "<<file.fileName().toStdString()<<endl;
262 file.write(program.toUtf8());
268 void BluemonkeySink::log(QString str)
270 DebugOut()<<str.toStdString()<<endl;
273 QObject *BluemonkeySink::createTimer()
275 return new QTimer(this);
278 void BluemonkeySink::getHistory(QStringList properties, QDateTime begin, QDateTime end, QJSValue cbFunction)
280 double b = (double)begin.toMSecsSinceEpoch() / 1000.0;
281 double e = (double)end.toMSecsSinceEpoch() / 1000.0;
282 AsyncRangePropertyRequest request;
283 request.timeBegin = b;
286 PropertyList reqlist;
288 foreach(QString prop, properties)
290 reqlist.push_back(prop.toStdString());
293 request.properties = reqlist;
294 request.completed = [&cbFunction](AsyncRangePropertyReply* reply)
298 DebugOut(DebugOut::Error)<<"bluemoney get history call failed"<<endl;
302 if(cbFunction.isCallable())
306 for(auto itr = reply->values.begin(); itr != reply->values.end(); itr++)
308 AbstractPropertyType *val = *itr;
310 list.append(gvariantToQVariant(val->toVariant()));
313 QJSValue val = cbFunction.engine()->toScriptValue<QVariantList>(list);
315 cbFunction.call(QJSValueList()<<val);
322 routingEngine->getRangePropertyAsync(request);
325 void BluemonkeySink::createCustomProperty(QString name, QJSValue defaultValue, int zone)
327 QVariant var = defaultValue.toVariant();
329 auto create = [defaultValue, name, var]() -> AbstractPropertyType*
334 if(var.type() == QVariant::UInt)
335 return new BasicPropertyType<uint>(name.toStdString(), var.toUInt());
336 else if(var.type() == QVariant::Double)
337 return new BasicPropertyType<double>(name.toStdString(), var.toDouble());
338 else if(var.type() == QVariant::Bool)
339 return new BasicPropertyType<bool>(name.toStdString(), var.toBool());
340 else if(var.type() == QVariant::Int)
341 return new BasicPropertyType<int>(name.toStdString(), var.toInt());
342 else if(var.type() == QVariant::String)
343 return new StringPropertyType(name.toStdString(), var.toString().toStdString());
348 addPropertySupport(zone, create);
350 AsyncSetPropertyRequest request;
351 request.property = name.toStdString();
352 request.zoneFilter = zone;
353 request.value = VehicleProperty::getPropertyTypeForPropertyNameValue(name.toStdString(), var.toString().toStdString());
355 routingEngine->updateSupported(supported(), PropertyList(), &source);
356 routingEngine->setProperty(request);
360 QVariant Property::value()
362 return mValue ? gvariantToQVariant(mValue->toVariant()) : QVariant::Invalid;
365 void Property::setValue(QVariant v)
367 if(v.type() == QVariant::List || v.type() == QVariant::Map)
370 QJsonDocument doc = QJsonDocument::fromVariant(v);
372 QString json = doc.toJson();
374 mValue->fromString(json.toStdString());
378 QString tempVal = v.toString();
379 mValue->fromString(tempVal.toStdString());
382 AsyncSetPropertyRequest request;
383 request.property = mValue->name;
384 request.value = mValue->copy();
385 request.completed = [&](AsyncPropertyReply* reply)
389 propertyChanged(reply->value);
393 DebugOut(DebugOut::Warning) << "Error, trying to set value: " << reply->error << endl;
397 routingEngine->setProperty(request);
400 void Property::getHistory(QDateTime begin, QDateTime end, QJSValue cbFunction)
402 double b = (double)begin.toMSecsSinceEpoch() / 1000.0;
403 double e = (double)end.toMSecsSinceEpoch() / 1000.0;
404 AsyncRangePropertyRequest request;
405 request.timeBegin = b;
408 PropertyList reqlist;
409 reqlist.push_back(mValue->name);
411 request.properties = reqlist;
412 request.completed = [&cbFunction](AsyncRangePropertyReply* reply)
416 DebugOut(DebugOut::Error)<<"bluemoney get history call failed"<<endl;
420 if(cbFunction.isCallable())
424 for(auto itr = reply->values.begin(); itr != reply->values.end(); itr++)
426 AbstractPropertyType *val = *itr;
428 list.append(gvariantToQVariant(val->toVariant()));
430 QJSValue val = cbFunction.engine()->toScriptValue<QVariantList>(list);
431 cbFunction.call(QJSValueList()<<val);
438 routingEngine->getRangePropertyAsync(request);
441 Property::Property(VehicleProperty::Property prop, QString srcFilter, AbstractRoutingEngine* re, Zone::Type zone, QObject *parent)
442 :QObject(parent), AbstractSink(re, std::map<std::string,std::string>()),mValue(nullptr), mUuid(amb::createUuid()), mZone(zone)
444 setType(prop.c_str());
447 QString Property::type()
449 return mValue->name.c_str();
452 void Property::setType(QString t)
454 if(mValue && type() != "")
455 routingEngine->unsubscribeToProperty(type().toStdString(), this);
457 routingEngine->subscribeToProperty(t.toStdString(), this);
459 mValue = VehicleProperty::getPropertyTypeForPropertyNameValue(t.toStdString());
464 AsyncPropertyRequest request;
465 request.property = mValue->name;
466 request.completed = [this](AsyncPropertyReply* reply)
469 propertyChanged(reply->value);
474 routingEngine->getPropertyAsync(request);
477 void Property::propertyChanged(AbstractPropertyType *value)
479 if(value->zone != mZone)
486 mValue = value->copy();
488 changed(gvariantToQVariant(mValue->toVariant()));
492 QVariant BluemonkeySink::zonesForProperty(QString prop, QString src)
494 PropertyInfo info = routingEngine->getPropertyInfo(prop.toStdString(), src.toStdString());
498 for(auto i : info.zones())