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>
31 Q_SCRIPT_DECLARE_QMETAOBJECT(QTimer, QObject*)
33 extern "C" AbstractSinkManager * create(AbstractRoutingEngine* routingengine, map<string, string> config)
35 return new BluemonkeySinkManager(routingengine, config);
38 QVariant gvariantToQVariant(GVariant *value)
40 GVariantClass c = g_variant_classify(value);
41 if(c == G_VARIANT_CLASS_BOOLEAN)
42 return QVariant((bool) g_variant_get_boolean(value));
44 else if(c == G_VARIANT_CLASS_BYTE)
45 return QVariant((char) g_variant_get_byte(value));
47 else if(c == G_VARIANT_CLASS_INT16)
48 return QVariant((int) g_variant_get_int16(value));
50 else if(c == G_VARIANT_CLASS_UINT16)
51 return QVariant((unsigned int) g_variant_get_uint16(value));
53 else if(c == G_VARIANT_CLASS_INT32)
54 return QVariant((int) g_variant_get_int32(value));
56 else if(c == G_VARIANT_CLASS_UINT32)
57 return QVariant((unsigned int) g_variant_get_uint32(value));
59 else if(c == G_VARIANT_CLASS_INT64)
60 return QVariant((long long) g_variant_get_int64(value));
62 else if(c == G_VARIANT_CLASS_UINT64)
63 return QVariant((unsigned long long) g_variant_get_uint64(value));
65 else if(c == G_VARIANT_CLASS_DOUBLE)
66 return QVariant(g_variant_get_double(value));
68 else if(c == G_VARIANT_CLASS_STRING)
69 return QVariant(g_variant_get_string(value, NULL));
71 else if(c == G_VARIANT_CLASS_ARRAY)
73 gsize dictsize = g_variant_n_children(value);
75 for (int i=0;i<dictsize;i++)
77 GVariant *childvariant = g_variant_get_child_value(value,i);
78 GVariant *innervariant = g_variant_get_variant(childvariant);
79 list.append(gvariantToQVariant(innervariant));
85 return QVariant::Invalid;
89 BluemonkeySink::BluemonkeySink(AbstractRoutingEngine* e, map<string, string> config): QObject(0), AbstractSink(e, config), engine(nullptr)
91 irc = new IrcCommunication(config, this);
95 auth = new Authenticate(config, this);
97 connect(irc, &IrcCommunication::message, [&](QString sender, QString prefix, QString codes ) {
99 if(codes.contains("authenticate"))
102 int i = codes.indexOf("authenticate");
103 QString pin = codes.mid(i+13);
107 if(!auth->authorize(prefix, pin))
108 irc->respond(sender,"failed");
112 else if(codes.startsWith("bluemonkey"))
114 if(!auth->isAuthorized(prefix))
116 irc->respond(sender, "denied");
120 QString bm("bluemonkey");
122 codes = codes.mid(bm.length()+1);
124 irc->respond(sender, engine->evaluate(codes).toString());
133 PropertyList BluemonkeySink::subscriptions()
138 void BluemonkeySink::supportedChanged(PropertyList supportedProperties)
143 void BluemonkeySink::propertyChanged(VehicleProperty::Property property, AbstractPropertyType* value, std::string uuid)
148 std::string BluemonkeySink::uuid()
153 QObject *BluemonkeySink::subscribeTo(QString str)
155 return new Property(str.toStdString(), routingEngine, this);
158 bool BluemonkeySink::authenticate(QString pass)
163 void BluemonkeySink::loadConfig(QString str)
165 configsToLoad.append(str);
166 QTimer::singleShot(1,this,SLOT(loadConfigPriv()));
169 void BluemonkeySink::loadConfigPriv()
171 if(!configsToLoad.count()) return;
173 QString str = configsToLoad.first();
174 configsToLoad.pop_front();
177 if(!file.open(QIODevice::ReadOnly))
179 qDebug()<<"failed to open config file: "<<str;
183 QString script = file.readAll();
187 QScriptValue val = engine->evaluate(script);
189 qDebug()<<val.toString();
192 void BluemonkeySink::reloadEngine()
195 engine->deleteLater();
197 engine = new QScriptEngine(this);
199 QScriptValue value = engine->newQObject(this);
200 engine->globalObject().setProperty("bluemonkey", value);
202 QScriptValue qtimerClass = engine->scriptValueFromQMetaObject<QTimer>();
203 engine->globalObject().setProperty("QTimer", qtimerClass);
207 loadConfig(configuration["config"].c_str());
210 void BluemonkeySink::writeProgram(QString program)
212 QFile file(configuration["customPrograms"].c_str());
214 file.open(QIODevice::ReadWrite | QIODevice::Append);
216 file.write(program.toUtf8());
223 QVariant Property::value()
225 return gvariantToQVariant(mValue->toVariant());
228 void Property::setValue(QVariant v)
230 if(v.type() == QVariant::List || v.type() == QVariant::Map)
233 QJsonDocument doc = QJsonDocument::fromVariant(v);
235 QString json = doc.toJson();
237 mValue->fromString(json.toStdString());
244 QString tempVal = v.toString();
245 mValue->fromString(tempVal.toStdString());
248 AsyncSetPropertyRequest request;
249 request.property = mValue->name;
250 request.value = mValue;
251 request.completed = [&](AsyncPropertyReply* reply)
255 propertyChanged(reply->property,reply->value,reply->value->sourceUuid);
259 routingEngine->setProperty(request);
262 Property::Property(VehicleProperty::Property prop, AbstractRoutingEngine* re, QObject *parent)
263 :QObject(parent), AbstractSink(re, std::map<std::string,std::string>()),mValue(nullptr)
265 setType(prop.c_str());
268 QString Property::type()
270 return mValue->name.c_str();
273 void Property::setType(QString t)
275 if(mValue && type() != "")
276 routingEngine->unsubscribeToProperty(type().toStdString(),this);
278 routingEngine->subscribeToProperty(t.toStdString(),this);
280 mValue = VehicleProperty::getPropertyTypeForPropertyNameValue(t.toStdString());
282 AsyncPropertyRequest request;
283 request.property = mValue->name;
284 request.completed = [this](AsyncPropertyReply* reply)
286 propertyChanged(reply->property, reply->value,uuid());
290 routingEngine->getPropertyAsync(request);
293 void Property::propertyChanged(VehicleProperty::Property property, AbstractPropertyType *value, string uuid)
295 mValue = value->copy();
297 changed(gvariantToQVariant(mValue->toVariant()));