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