added overload for subscribe that includes a zone filter. it is unimplemented in...
[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 <QString>
28 #include <QFile>
29 #include <QTimer>
30
31 Q_SCRIPT_DECLARE_QMETAOBJECT(QTimer, QObject*)
32
33 extern "C" AbstractSinkManager * create(AbstractRoutingEngine* routingengine, map<string, string> config)
34 {
35         return new BluemonkeySinkManager(routingengine, config);
36 }
37
38 QVariant gvariantToQVariant(GVariant *value)
39 {
40         GVariantClass c = g_variant_classify(value);
41         if(c == G_VARIANT_CLASS_BOOLEAN)
42                 return QVariant((bool) g_variant_get_boolean(value));
43
44         else if(c == G_VARIANT_CLASS_BYTE)
45                 return QVariant((char) g_variant_get_byte(value));
46
47         else if(c == G_VARIANT_CLASS_INT16)
48                 return QVariant((int) g_variant_get_int16(value));
49
50         else if(c == G_VARIANT_CLASS_UINT16)
51                 return QVariant((unsigned int) g_variant_get_uint16(value));
52
53         else if(c == G_VARIANT_CLASS_INT32)
54                 return QVariant((int) g_variant_get_int32(value));
55
56         else if(c ==  G_VARIANT_CLASS_UINT32)
57                 return QVariant((unsigned int) g_variant_get_uint32(value));
58
59         else if(c == G_VARIANT_CLASS_INT64)
60                 return QVariant((long long) g_variant_get_int64(value));
61
62         else if(c == G_VARIANT_CLASS_UINT64)
63                 return QVariant((unsigned long long) g_variant_get_uint64(value));
64
65         else if(c == G_VARIANT_CLASS_DOUBLE)
66                 return QVariant(g_variant_get_double(value));
67
68         else if(c == G_VARIANT_CLASS_STRING)
69                 return QVariant(g_variant_get_string(value, NULL));
70
71         else if(c == G_VARIANT_CLASS_ARRAY)
72         {
73                 gsize dictsize = g_variant_n_children(value);
74                 QVariantList list;
75                 for (int i=0;i<dictsize;i++)
76                 {
77                         GVariant *childvariant = g_variant_get_child_value(value,i);
78                         GVariant *innervariant = g_variant_get_variant(childvariant);
79                         list.append(gvariantToQVariant(innervariant));
80                 }
81                 return list;
82         }
83
84         else
85                 return QVariant::Invalid;
86
87 }
88
89 BluemonkeySink::BluemonkeySink(AbstractRoutingEngine* e, map<string, string> config): QObject(0), AbstractSink(e, config), engine(nullptr)
90 {
91         irc = new IrcCommunication(config, this);
92
93         reloadEngine();
94
95         auth = new Authenticate(config, this);
96
97         connect(irc, &IrcCommunication::message, [&](QString sender, QString prefix, QString codes ) {
98
99                 if(codes.contains("authenticate"))
100                 {
101
102                         int i = codes.indexOf("authenticate");
103                         QString pin = codes.mid(i+13);
104                         pin = pin.trimmed();
105
106
107                         if(!auth->authorize(prefix, pin))
108                                 irc->respond(sender,"failed");
109                         qDebug()<<sender;
110
111                 }
112                 else if(codes.startsWith("bluemonkey"))
113                 {
114                         if(!auth->isAuthorized(prefix))
115                         {
116                                 irc->respond(sender, "denied");
117                                 return;
118                         }
119
120                         QString bm("bluemonkey");
121
122                         codes = codes.mid(bm.length()+1);
123
124                         irc->respond(sender, engine->evaluate(codes).toString());
125                 }
126         });
127
128
129
130 }
131
132
133 PropertyList BluemonkeySink::subscriptions()
134 {
135
136 }
137
138 void BluemonkeySink::supportedChanged(PropertyList supportedProperties)
139 {
140
141 }
142
143 void BluemonkeySink::propertyChanged(VehicleProperty::Property property, AbstractPropertyType* value, std::string uuid)
144 {
145
146 }
147
148 std::string BluemonkeySink::uuid()
149 {
150         return "bluemonkey";
151 }
152
153 QObject *BluemonkeySink::subscribeTo(QString str)
154 {
155         return new Property(str.toStdString(), "", routingEngine, this);
156 }
157
158 QObject *BluemonkeySink::subscribeTo(QString str, QString srcFilter)
159 {
160         return new Property(str.toStdString(), srcFilter, routingEngine, this);
161 }
162
163 QStringList BluemonkeySink::sourcesForProperty(QString property)
164 {
165         std::list<std::string> list = routingEngine->sourcesForProperty(property.toStdString());
166         QStringList strList;
167         for(auto itr = list.begin(); itr != list.end(); itr++)
168         {
169                 strList<<(*itr).c_str();
170         }
171
172         return strList;
173 }
174
175
176 bool BluemonkeySink::authenticate(QString pass)
177 {
178
179 }
180
181 void BluemonkeySink::loadConfig(QString str)
182 {
183         configsToLoad.append(str);
184         QTimer::singleShot(1,this,SLOT(loadConfigPriv()));
185 }
186
187 void BluemonkeySink::loadConfigPriv()
188 {
189         if(!configsToLoad.count()) return;
190
191         QString str = configsToLoad.first();
192         configsToLoad.pop_front();
193
194         QFile file(str);
195         if(!file.open(QIODevice::ReadOnly))
196         {
197                 qDebug()<<"failed to open config file: "<<str;
198                 return;
199         }
200
201         QString script = file.readAll();
202
203         file.close();
204
205         QScriptValue val = engine->evaluate(script);
206
207         qDebug()<<val.toString();
208 }
209
210 void BluemonkeySink::reloadEngine()
211 {
212         if(engine)
213                 engine->deleteLater();
214
215         engine = new QScriptEngine(this);
216
217         QScriptValue value = engine->newQObject(this);
218         engine->globalObject().setProperty("bluemonkey", value);
219
220         QScriptValue qtimerClass = engine->scriptValueFromQMetaObject<QTimer>();
221         engine->globalObject().setProperty("QTimer", qtimerClass);
222
223         QScriptValue ircValue = engine->newQObject(irc);
224         engine->globalObject().setProperty("irc", ircValue);
225
226         loadConfig(configuration["config"].c_str());
227 }
228
229 void BluemonkeySink::writeProgram(QString program)
230 {
231         QFile file(configuration["customPrograms"].c_str());
232
233         if(!file.open(QIODevice::ReadWrite | QIODevice::Append))
234         {
235                 DebugOut(DebugOut::Error)<<"failed to open file: "<<file.fileName().toStdString()<<endl;
236                 return;
237         }
238
239         file.write(program.toUtf8());
240         file.write("\n");
241
242         file.close();
243 }
244
245 void BluemonkeySink::log(QString str)
246 {
247         DebugOut()<<str.toStdString()<<endl;
248 }
249
250
251 QVariant Property::value()
252 {
253         return gvariantToQVariant(mValue->toVariant());
254 }
255
256 void Property::setValue(QVariant v)
257 {
258         if(v.type() == QVariant::List || v.type() == QVariant::Map)
259         {
260
261                 QJsonDocument doc = QJsonDocument::fromVariant(v);
262
263                 QString json = doc.toJson();
264
265                 mValue->fromString(json.toStdString());
266         }
267
268
269
270         else
271         {
272                 QString tempVal = v.toString();
273                 mValue->fromString(tempVal.toStdString());
274         }
275
276         AsyncSetPropertyRequest request;
277         request.property = mValue->name;
278         request.value = mValue;
279         request.completed = [&](AsyncPropertyReply* reply)
280         {
281                 if(reply->success)
282                 {
283                         propertyChanged(reply->property,reply->value,reply->value->sourceUuid);
284                 }
285                 delete reply;
286         };
287         routingEngine->setProperty(request);
288 }
289
290 Property::Property(VehicleProperty::Property prop, QString srcFilter, AbstractRoutingEngine* re, QObject *parent)
291         :QObject(parent), AbstractSink(re, std::map<std::string,std::string>()),mValue(nullptr)
292 {
293         setType(prop.c_str());
294 }
295
296 QString Property::type()
297 {
298         return mValue->name.c_str();
299 }
300
301 void Property::setType(QString t)
302 {
303         if(mValue && type() != "")
304                 routingEngine->unsubscribeToProperty(type().toStdString(),this);
305
306         routingEngine->subscribeToProperty(t.toStdString(),this);
307
308         mValue = VehicleProperty::getPropertyTypeForPropertyNameValue(t.toStdString());
309
310         AsyncPropertyRequest request;
311         request.property = mValue->name;
312         request.completed = [this](AsyncPropertyReply* reply)
313         {
314                 if(reply->success)
315                         propertyChanged(reply->property, reply->value,uuid());
316
317                 delete reply;
318         };
319
320         routingEngine->getPropertyAsync(request);
321 }
322
323 void Property::propertyChanged(VehicleProperty::Property property, AbstractPropertyType *value, string uuid)
324 {
325         if(mValue)
326         {
327                 delete mValue;
328         }
329         mValue = value->copy();
330
331         changed(gvariantToQVariant(mValue->toVariant()));
332 }