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"
25 #include <QJsonDocument>
26 #include <QScriptEngine>
32 Q_SCRIPT_DECLARE_QMETAOBJECT(QTimer, QObject*)
34 #define foreach Q_FOREACH
36 extern "C" AbstractSinkManager * create(AbstractRoutingEngine* routingengine, map<string, string> config)
38 return new BluemonkeySinkManager(routingengine, config);
41 QVariant gvariantToQVariant(GVariant *value)
43 GVariantClass c = g_variant_classify(value);
44 if(c == G_VARIANT_CLASS_BOOLEAN)
45 return QVariant((bool) g_variant_get_boolean(value));
47 else if(c == G_VARIANT_CLASS_BYTE)
48 return QVariant((char) g_variant_get_byte(value));
50 else if(c == G_VARIANT_CLASS_INT16)
51 return QVariant((int) g_variant_get_int16(value));
53 else if(c == G_VARIANT_CLASS_UINT16)
54 return QVariant((unsigned int) g_variant_get_uint16(value));
56 else if(c == G_VARIANT_CLASS_INT32)
57 return QVariant((int) g_variant_get_int32(value));
59 else if(c == G_VARIANT_CLASS_UINT32)
60 return QVariant((unsigned int) g_variant_get_uint32(value));
62 else if(c == G_VARIANT_CLASS_INT64)
63 return QVariant((long long) g_variant_get_int64(value));
65 else if(c == G_VARIANT_CLASS_UINT64)
66 return QVariant((unsigned long long) g_variant_get_uint64(value));
68 else if(c == G_VARIANT_CLASS_DOUBLE)
69 return QVariant(g_variant_get_double(value));
71 else if(c == G_VARIANT_CLASS_STRING)
72 return QVariant(g_variant_get_string(value, NULL));
74 else if(c == G_VARIANT_CLASS_ARRAY)
76 gsize dictsize = g_variant_n_children(value);
78 for (int i=0;i<dictsize;i++)
80 GVariant *childvariant = g_variant_get_child_value(value,i);
81 GVariant *innervariant = g_variant_get_variant(childvariant);
82 list.append(gvariantToQVariant(innervariant));
88 return QVariant::Invalid;
92 BluemonkeySink::BluemonkeySink(AbstractRoutingEngine* e, map<string, string> config): QObject(0), AbstractSink(e, config), agent(nullptr), engine(nullptr), mSilentMode(false)
94 irc = new IrcCommunication(config, this);
96 QTimer::singleShot(1,this,SLOT(reloadEngine()));
98 auth = new Authenticate(config, this);
100 connect(irc, &IrcCommunication::message, [&](QString sender, QString prefix, QString codes ) {
102 if(codes.startsWith("authenticate"))
105 int i = codes.indexOf("authenticate");
106 QString pin = codes.mid(i+13);
110 if(!auth->authorize(prefix, pin))
111 irc->respond(sender,"failed");
115 else if(codes.startsWith("bluemonkey"))
117 if(!auth->isAuthorized(prefix))
120 irc->respond(sender, "denied");
124 QString bm("bluemonkey");
126 codes = codes.mid(bm.length()+1);
128 QString response = engine->evaluate(codes).toString();
130 if(!mSilentMode || response != "undefined" )
131 irc->respond(sender, response);
138 PropertyList BluemonkeySink::subscriptions()
143 void BluemonkeySink::supportedChanged(PropertyList supportedProperties)
145 DebugOut()<<"supported changed"<<endl;
148 void BluemonkeySink::propertyChanged(VehicleProperty::Property property, AbstractPropertyType* value, std::string uuid)
153 const string BluemonkeySink::uuid()
158 QObject *BluemonkeySink::subscribeTo(QString str)
160 return new Property(str.toStdString(), "", routingEngine, this);
163 QObject *BluemonkeySink::subscribeTo(QString str, QString srcFilter)
165 return new Property(str.toStdString(), srcFilter, routingEngine, this);
168 QStringList BluemonkeySink::sourcesForProperty(QString property)
170 std::list<std::string> list = routingEngine->sourcesForProperty(property.toStdString());
172 for(auto itr = list.begin(); itr != list.end(); itr++)
174 strList<<(*itr).c_str();
181 bool BluemonkeySink::authenticate(QString pass)
186 void BluemonkeySink::loadConfig(QString str)
189 if(!file.open(QIODevice::ReadOnly))
191 DebugOut()<<"failed to open config file: "<<str.toStdString()<<endl;
195 QString script = file.readAll();
199 DebugOut()<<"evaluating script: "<<script.toStdString()<<endl;
201 QScriptValue val = engine->evaluate(script);
203 DebugOut()<<val.toString().toStdString()<<endl;
206 void BluemonkeySink::reloadEngine()
209 engine->deleteLater();
211 engine = new QScriptEngine(this);
213 if(agent) delete agent;
215 agent = new BluemonkeyAgent(engine);
217 //engine->setAgent(agent);
219 QScriptValue value = engine->newQObject(this);
220 engine->globalObject().setProperty("bluemonkey", value);
222 QScriptValue qtimerClass = engine->scriptValueFromQMetaObject<QTimer>();
223 engine->globalObject().setProperty("QTimer", qtimerClass);
225 QScriptValue ircValue = engine->newQObject(irc);
226 engine->globalObject().setProperty("irc", ircValue);
228 loadConfig(configuration["config"].c_str());
231 void BluemonkeySink::writeProgram(QString program)
233 QScriptSyntaxCheckResult result = QScriptEngine::checkSyntax(program);
234 if(result.state() != QScriptSyntaxCheckResult::Valid)
236 DebugOut(DebugOut::Error)<<"Syntax error in program: "<<result.errorMessage().toStdString()<<endl;
240 QFile file(configuration["customPrograms"].c_str());
242 if(!file.open(QIODevice::ReadWrite | QIODevice::Append))
244 DebugOut(DebugOut::Error)<<"failed to open file: "<<file.fileName().toStdString()<<endl;
248 file.write(program.toUtf8());
254 void BluemonkeySink::log(QString str)
256 DebugOut()<<str.toStdString()<<endl;
259 void BluemonkeySink::getHistory(QStringList properties, QDateTime begin, QDateTime end, QScriptValue cbFunction)
261 double b = (double)begin.toMSecsSinceEpoch() / 1000.0;
262 double e = (double)end.toMSecsSinceEpoch() / 1000.0;
263 AsyncRangePropertyRequest request;
264 request.timeBegin = b;
267 PropertyList reqlist;
269 foreach(QString prop, properties)
271 reqlist.push_back(prop.toStdString());
274 request.properties = reqlist;
275 request.completed = [&cbFunction](AsyncRangePropertyReply* reply)
279 DebugOut(DebugOut::Error)<<"bluemoney get history call failed"<<endl;
283 if(cbFunction.isFunction())
287 for(auto itr = reply->values.begin(); itr != reply->values.end(); itr++)
289 AbstractPropertyType *val = *itr;
291 list.append(gvariantToQVariant(val->toVariant()));
294 cbFunction.call(QScriptValue(),cbFunction.engine()->newVariant(list));
301 routingEngine->getRangePropertyAsync(request);
305 QVariant Property::value()
307 return mValue ? gvariantToQVariant(mValue->toVariant()) : QVariant::Invalid;
310 void Property::setValue(QVariant v)
312 if(v.type() == QVariant::List || v.type() == QVariant::Map)
315 QJsonDocument doc = QJsonDocument::fromVariant(v);
317 QString json = doc.toJson();
319 mValue->fromString(json.toStdString());
323 QString tempVal = v.toString();
324 mValue->fromString(tempVal.toStdString());
327 AsyncSetPropertyRequest request;
328 request.property = mValue->name;
329 request.value = mValue->copy();
330 request.completed = [&](AsyncPropertyReply* reply)
334 propertyChanged(reply->property,reply->value,reply->value->sourceUuid);
338 routingEngine->setProperty(request);
341 void Property::getHistory(QDateTime begin, QDateTime end, QScriptValue cbFunction)
343 double b = (double)begin.toMSecsSinceEpoch() / 1000.0;
344 double e = (double)end.toMSecsSinceEpoch() / 1000.0;
345 AsyncRangePropertyRequest request;
346 request.timeBegin = b;
349 PropertyList reqlist;
350 reqlist.push_back(mValue->name);
352 request.properties = reqlist;
353 request.completed = [&cbFunction](AsyncRangePropertyReply* reply)
357 DebugOut(DebugOut::Error)<<"bluemoney get history call failed"<<endl;
361 if(cbFunction.isFunction())
365 for(auto itr = reply->values.begin(); itr != reply->values.end(); itr++)
367 AbstractPropertyType *val = *itr;
369 list.append(gvariantToQVariant(val->toVariant()));
372 cbFunction.call(QScriptValue(),cbFunction.engine()->newVariant(list));
379 routingEngine->getRangePropertyAsync(request);
382 Property::Property(VehicleProperty::Property prop, QString srcFilter, AbstractRoutingEngine* re, QObject *parent)
383 :QObject(parent), AbstractSink(re, std::map<std::string,std::string>()),mValue(nullptr), mUuid(amb::createUuid())
385 setType(prop.c_str());
388 QString Property::type()
390 return mValue->name.c_str();
393 void Property::setType(QString t)
395 if(mValue && type() != "")
396 routingEngine->unsubscribeToProperty(type().toStdString(),this);
398 routingEngine->subscribeToProperty(t.toStdString(),this);
400 mValue = VehicleProperty::getPropertyTypeForPropertyNameValue(t.toStdString());
405 AsyncPropertyRequest request;
406 request.property = mValue->name;
407 request.completed = [this](AsyncPropertyReply* reply)
410 propertyChanged(reply->property, reply->value,uuid());
415 routingEngine->getPropertyAsync(request);
418 void Property::propertyChanged(VehicleProperty::Property property, AbstractPropertyType *value, string uuid)
424 mValue = value->copy();
426 changed(gvariantToQVariant(mValue->toVariant()));