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