fixed some compiler errors. disabled qscript agent
[profile/ivi/automotive-message-broker.git] / plugins / bluemonkey / bluemonkey.cpp
1 /*
2     Copyright (C) 2012  Intel Corporation
3
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.
8
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.
13
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
17 */
18
19
20 #include "bluemonkey.h"
21 #include "abstractroutingengine.h"
22 #include "debugout.h"
23 #include "irccoms.h"
24
25 #include <QJsonDocument>
26 #include <QScriptEngine>
27 #include <QDateTime>
28 #include <QString>
29 #include <QFile>
30 #include <QTimer>
31
32 Q_SCRIPT_DECLARE_QMETAOBJECT(QTimer, QObject*)
33
34 #define foreach Q_FOREACH
35
36 extern "C" AbstractSinkManager * create(AbstractRoutingEngine* routingengine, map<string, string> config)
37 {
38         return new BluemonkeySinkManager(routingengine, config);
39 }
40
41 QVariant gvariantToQVariant(GVariant *value)
42 {
43         GVariantClass c = g_variant_classify(value);
44         if(c == G_VARIANT_CLASS_BOOLEAN)
45                 return QVariant((bool) g_variant_get_boolean(value));
46
47         else if(c == G_VARIANT_CLASS_BYTE)
48                 return QVariant((char) g_variant_get_byte(value));
49
50         else if(c == G_VARIANT_CLASS_INT16)
51                 return QVariant((int) g_variant_get_int16(value));
52
53         else if(c == G_VARIANT_CLASS_UINT16)
54                 return QVariant((unsigned int) g_variant_get_uint16(value));
55
56         else if(c == G_VARIANT_CLASS_INT32)
57                 return QVariant((int) g_variant_get_int32(value));
58
59         else if(c ==  G_VARIANT_CLASS_UINT32)
60                 return QVariant((unsigned int) g_variant_get_uint32(value));
61
62         else if(c == G_VARIANT_CLASS_INT64)
63                 return QVariant((long long) g_variant_get_int64(value));
64
65         else if(c == G_VARIANT_CLASS_UINT64)
66                 return QVariant((unsigned long long) g_variant_get_uint64(value));
67
68         else if(c == G_VARIANT_CLASS_DOUBLE)
69                 return QVariant(g_variant_get_double(value));
70
71         else if(c == G_VARIANT_CLASS_STRING)
72                 return QVariant(g_variant_get_string(value, NULL));
73
74         else if(c == G_VARIANT_CLASS_ARRAY)
75         {
76                 gsize dictsize = g_variant_n_children(value);
77                 QVariantList list;
78                 for (int i=0;i<dictsize;i++)
79                 {
80                         GVariant *childvariant = g_variant_get_child_value(value,i);
81                         GVariant *innervariant = g_variant_get_variant(childvariant);
82                         list.append(gvariantToQVariant(innervariant));
83                 }
84                 return list;
85         }
86
87         else
88                 return QVariant::Invalid;
89
90 }
91
92 BluemonkeySink::BluemonkeySink(AbstractRoutingEngine* e, map<string, string> config): QObject(0), AbstractSink(e, config), agent(nullptr), engine(nullptr), mSilentMode(false)
93 {
94         irc = new IrcCommunication(config, this);
95
96         QTimer::singleShot(1,this,SLOT(reloadEngine()));
97
98         auth = new Authenticate(config, this);
99
100         connect(irc, &IrcCommunication::message, [&](QString sender, QString prefix, QString codes ) {
101
102                 if(codes.startsWith("authenticate"))
103                 {
104
105                         int i = codes.indexOf("authenticate");
106                         QString pin = codes.mid(i+13);
107                         pin = pin.trimmed();
108
109
110                         if(!auth->authorize(prefix, pin))
111                                 irc->respond(sender,"failed");
112                         qDebug()<<sender;
113
114                 }
115                 else if(codes.startsWith("bluemonkey"))
116                 {
117                         if(!auth->isAuthorized(prefix))
118                         {
119                                 if(!mSilentMode)
120                                         irc->respond(sender, "denied");
121                                 return;
122                         }
123
124                         QString bm("bluemonkey");
125
126                         codes = codes.mid(bm.length()+1);
127
128                         QString response = engine->evaluate(codes).toString();
129
130                         if(!mSilentMode || response != "undefined" )
131                                 irc->respond(sender, response);
132                 }
133         });
134
135 }
136
137
138 PropertyList BluemonkeySink::subscriptions()
139 {
140
141 }
142
143 void BluemonkeySink::supportedChanged(PropertyList supportedProperties)
144 {
145         DebugOut()<<"supported changed"<<endl;
146 }
147
148 void BluemonkeySink::propertyChanged(VehicleProperty::Property property, AbstractPropertyType* value, std::string uuid)
149 {
150
151 }
152
153 const string BluemonkeySink::uuid()
154 {
155         return "bluemonkey";
156 }
157
158 QObject *BluemonkeySink::subscribeTo(QString str)
159 {
160         return new Property(str.toStdString(), "", routingEngine, this);
161 }
162
163 QObject *BluemonkeySink::subscribeTo(QString str, QString srcFilter)
164 {
165         return new Property(str.toStdString(), srcFilter, routingEngine, this);
166 }
167
168 QStringList BluemonkeySink::sourcesForProperty(QString property)
169 {
170         std::list<std::string> list = routingEngine->sourcesForProperty(property.toStdString());
171         QStringList strList;
172         for(auto itr = list.begin(); itr != list.end(); itr++)
173         {
174                 strList<<(*itr).c_str();
175         }
176
177         return strList;
178 }
179
180
181 bool BluemonkeySink::authenticate(QString pass)
182 {
183
184 }
185
186 void BluemonkeySink::loadConfig(QString str)
187 {
188         QFile file(str);
189         if(!file.open(QIODevice::ReadOnly))
190         {
191                 DebugOut()<<"failed to open config file: "<<str.toStdString()<<endl;
192                 return;
193         }
194
195         QString script = file.readAll();
196
197         file.close();
198
199         DebugOut()<<"evaluating script: "<<script.toStdString()<<endl;
200
201         QScriptValue val = engine->evaluate(script);
202
203         DebugOut()<<val.toString().toStdString()<<endl;
204 }
205
206 void BluemonkeySink::reloadEngine()
207 {
208         if(engine)
209                 engine->deleteLater();
210
211         engine = new QScriptEngine(this);
212
213         if(agent) delete agent;
214
215         agent = new BluemonkeyAgent(engine);
216
217         //engine->setAgent(agent);
218
219         QScriptValue value = engine->newQObject(this);
220         engine->globalObject().setProperty("bluemonkey", value);
221
222         QScriptValue qtimerClass = engine->scriptValueFromQMetaObject<QTimer>();
223         engine->globalObject().setProperty("QTimer", qtimerClass);
224
225         QScriptValue ircValue = engine->newQObject(irc);
226         engine->globalObject().setProperty("irc", ircValue);
227
228         loadConfig(configuration["config"].c_str());
229 }
230
231 void BluemonkeySink::writeProgram(QString program)
232 {
233         QScriptSyntaxCheckResult result = QScriptEngine::checkSyntax(program);
234         if(result.state() != QScriptSyntaxCheckResult::Valid)
235         {
236                 DebugOut(DebugOut::Error)<<"Syntax error in program: "<<result.errorMessage().toStdString()<<endl;
237                 return;
238         }
239
240         QFile file(configuration["customPrograms"].c_str());
241
242         if(!file.open(QIODevice::ReadWrite | QIODevice::Append))
243         {
244                 DebugOut(DebugOut::Error)<<"failed to open file: "<<file.fileName().toStdString()<<endl;
245                 return;
246         }
247
248         file.write(program.toUtf8());
249         file.write("\n");
250
251         file.close();
252 }
253
254 void BluemonkeySink::log(QString str)
255 {
256         DebugOut()<<str.toStdString()<<endl;
257 }
258
259 void BluemonkeySink::getHistory(QStringList properties, QDateTime begin, QDateTime end, QScriptValue cbFunction)
260 {
261         double b = (double)begin.toMSecsSinceEpoch() / 1000.0;
262         double e = (double)end.toMSecsSinceEpoch() / 1000.0;
263         AsyncRangePropertyRequest request;
264         request.timeBegin = b;
265         request.timeEnd = e;
266
267         PropertyList reqlist;
268
269         foreach(QString prop, properties)
270         {
271                 reqlist.push_back(prop.toStdString());
272         }
273
274         request.properties = reqlist;
275         request.completed = [&cbFunction](AsyncRangePropertyReply* reply)
276         {
277                 if(!reply->success)
278                 {
279                         DebugOut(DebugOut::Error)<<"bluemoney get history call failed"<<endl;
280                         return;
281                 }
282
283                 if(cbFunction.isFunction())
284                 {
285                         QVariantList list;
286
287                         for(auto itr = reply->values.begin(); itr != reply->values.end(); itr++)
288                         {
289                                 AbstractPropertyType *val = *itr;
290
291                                 list.append(gvariantToQVariant(val->toVariant()));
292                         }
293
294                         cbFunction.call(QScriptValue(),cbFunction.engine()->newVariant(list));
295
296                 }
297
298                 delete reply;
299         };
300
301         routingEngine->getRangePropertyAsync(request);
302 }
303
304
305 QVariant Property::value()
306 {
307         return mValue ? gvariantToQVariant(mValue->toVariant()) : QVariant::Invalid;
308 }
309
310 void Property::setValue(QVariant v)
311 {
312         if(v.type() == QVariant::List || v.type() == QVariant::Map)
313         {
314
315                 QJsonDocument doc = QJsonDocument::fromVariant(v);
316
317                 QString json = doc.toJson();
318
319                 mValue->fromString(json.toStdString());
320         }
321         else
322         {
323                 QString tempVal = v.toString();
324                 mValue->fromString(tempVal.toStdString());
325         }
326
327         AsyncSetPropertyRequest request;
328         request.property = mValue->name;
329         request.value = mValue->copy();
330         request.completed = [&](AsyncPropertyReply* reply)
331         {
332                 if(reply->success)
333                 {
334                         propertyChanged(reply->property,reply->value,reply->value->sourceUuid);
335                 }
336                 delete reply;
337         };
338         routingEngine->setProperty(request);
339 }
340
341 void Property::getHistory(QDateTime begin, QDateTime end, QScriptValue cbFunction)
342 {
343         double b = (double)begin.toMSecsSinceEpoch() / 1000.0;
344         double e = (double)end.toMSecsSinceEpoch() / 1000.0;
345         AsyncRangePropertyRequest request;
346         request.timeBegin = b;
347         request.timeEnd = e;
348
349         PropertyList reqlist;
350         reqlist.push_back(mValue->name);
351
352         request.properties = reqlist;
353         request.completed = [&cbFunction](AsyncRangePropertyReply* reply)
354         {
355                 if(!reply->success)
356                 {
357                         DebugOut(DebugOut::Error)<<"bluemoney get history call failed"<<endl;
358                         return;
359                 }
360
361                 if(cbFunction.isFunction())
362                 {
363                         QVariantList list;
364
365                         for(auto itr = reply->values.begin(); itr != reply->values.end(); itr++)
366                         {
367                                 AbstractPropertyType *val = *itr;
368
369                                 list.append(gvariantToQVariant(val->toVariant()));
370                         }
371
372                         cbFunction.call(QScriptValue(),cbFunction.engine()->newVariant(list));
373
374                 }
375
376                 delete reply;
377         };
378
379         routingEngine->getRangePropertyAsync(request);
380 }
381
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())
384 {
385         setType(prop.c_str());
386 }
387
388 QString Property::type()
389 {
390         return mValue->name.c_str();
391 }
392
393 void Property::setType(QString t)
394 {
395         if(mValue && type() != "")
396                 routingEngine->unsubscribeToProperty(type().toStdString(),this);
397
398         routingEngine->subscribeToProperty(t.toStdString(),this);
399
400         mValue = VehicleProperty::getPropertyTypeForPropertyNameValue(t.toStdString());
401
402         if(!mValue)
403                 return;
404
405         AsyncPropertyRequest request;
406         request.property = mValue->name;
407         request.completed = [this](AsyncPropertyReply* reply)
408         {
409                 if(reply->success)
410                         propertyChanged(reply->property, reply->value,uuid());
411
412                 delete reply;
413         };
414
415         routingEngine->getPropertyAsync(request);
416 }
417
418 void Property::propertyChanged(VehicleProperty::Property property, AbstractPropertyType *value, string uuid)
419 {
420         if(mValue)
421         {
422                 delete mValue;
423         }
424         mValue = value->copy();
425
426         changed(gvariantToQVariant(mValue->toVariant()));
427 }