fixed some compiler errors. disabled qscript agent
[profile/ivi/automotive-message-broker.git] / plugins / openxc / openxcplugin.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 #include "openxcplugin.h"
20 #include "timestamp.h"
21
22 #include <iostream>
23 #include <boost/assert.hpp>
24 #include <glib.h>
25
26 #include "bluetooth.hpp"
27
28 using namespace std;
29
30 #include "debugout.h"
31
32 bool gioPollingFunc(GIOChannel *source,GIOCondition condition,gpointer data)
33 {
34         if (condition == G_IO_HUP)
35         {
36                 //Hang up. Returning false closes out the GIOChannel.
37                 //printf("Callback on G_IO_HUP\n");
38                 return false;
39         }
40
41         OpenXCPlugin* plugin = static_cast<OpenXCPlugin*>(data);
42
43         if(!plugin)
44         {
45                 throw std::runtime_error("Bad cast to OpenXCPlugin*");
46         }
47
48         plugin->processData();
49
50         return true;
51 }
52
53 OpenXCPlugin::OpenXCPlugin(AbstractRoutingEngine* re, map<string, string> config)
54 :AbstractSource(re, config)
55 {
56         re->setSupported(supported(), this);    
57
58         /// populate the openxc to amb map:
59
60         openXC2AmbMap["steering_wheel_angle"] = VehicleProperty::SteeringWheelAngle;
61         //openXC2AmbMap["torque_at_transmission"] = VehicleProperty::Engine;
62         openXC2AmbMap["engine_speed"] = VehicleProperty::EngineSpeed;
63         openXC2AmbMap["vehicle_speed"] = VehicleProperty::VehicleSpeed;
64         openXC2AmbMap["accelerator_pedal_position"] = VehicleProperty::ThrottlePosition;
65         openXC2AmbMap["parking_brake_status"] = VehicleProperty::ParkingBrakeStatus;
66         openXC2AmbMap["brake_pedal_status"] = VehicleProperty::LightBrake;
67         openXC2AmbMap["transmission_gear_position"] = VehicleProperty::TransmissionGearPosition;
68         openXC2AmbMap["odometer"] = VehicleProperty::Odometer;
69         openXC2AmbMap["ignition_status"] = VehicleProperty::VehiclePowerMode;
70         openXC2AmbMap["fuel_level"] = VehicleProperty::FuelLevel;
71         openXC2AmbMap["fuel_consumed_since_restart"] = VehicleProperty::FuelConsumption;
72         openXC2AmbMap["headlamp_status"] = VehicleProperty::LightHead;
73         openXC2AmbMap["high_beam_status"] = VehicleProperty::LightHighBeam;
74         openXC2AmbMap["windshield_wiper_status"] = VehicleProperty::WindshieldWiper;
75         openXC2AmbMap["latitude"] = VehicleProperty::Latitude;
76         openXC2AmbMap["longitude"] = VehicleProperty::Longitude;
77         openXC2AmbMap["button_event"] = VehicleProperty::ButtonEvent;
78
79         bool test = false;
80         if(config.find("test") != config.end())
81         {
82                 test = config["test"] == "true";
83         }
84
85         if(test)
86         {
87                 testParseEngine();
88         }
89
90         std::string bluetoothAddy = config["device"];
91         std::string bluetoothAdapter = config["bluetoothAdapter"];
92         std::string serialDevice;
93
94         if(bluetoothAddy != "")
95         {
96                 BluetoothDevice btDevice;
97
98                 serialDevice = btDevice.getDeviceForAddress(bluetoothAddy, bluetoothAdapter);
99         }
100
101         device = new SerialPort(serialDevice);
102         if(!device->open())
103         {
104                 throw std::runtime_error("unable to open serial device " + serialDevice);
105         }
106
107         GIOChannel *chan = g_io_channel_unix_new(device->fileDescriptor());
108         g_io_add_watch(chan, G_IO_IN,(GIOFunc)gioPollingFunc, this);
109         g_io_add_watch(chan,G_IO_HUP,(GIOFunc)gioPollingFunc,this);
110         g_io_add_watch(chan,G_IO_ERR,(GIOFunc)gioPollingFunc,this);
111         g_io_channel_unref(chan); //Pass ownership of the GIOChannel to the watch.
112
113
114 }
115
116
117
118 extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config)
119 {
120         return new OpenXCPlugin(routingengine, config);
121         
122 }
123
124 const string OpenXCPlugin::uuid()
125 {
126         return "openxc";
127 }
128
129
130 void OpenXCPlugin::getPropertyAsync(AsyncPropertyReply *reply)
131 {
132
133 }
134
135 void OpenXCPlugin::getRangePropertyAsync(AsyncRangePropertyReply *reply)
136 {
137
138 }
139
140 AsyncPropertyReply *OpenXCPlugin::setProperty(AsyncSetPropertyRequest request )
141 {
142
143 }
144
145 void OpenXCPlugin::subscribeToPropertyChanges(VehicleProperty::Property property)
146 {
147         mRequests.push_back(property);
148 }
149
150 PropertyList OpenXCPlugin::supported()
151 {
152         PropertyList props;
153         
154         return props;
155 }
156
157 int OpenXCPlugin::supportedOperations()
158 {
159         return Get;
160 }
161
162 void OpenXCPlugin::unsubscribeToPropertyChanges(VehicleProperty::Property property)
163 {
164         mRequests.remove(property);
165 }
166
167
168
169 bool OpenXCPlugin::translateOpenXCEvent(string json)
170 {
171         /// signal:
172         /// {"name": "steering_wheel_angle", "value": 45}
173
174         /// event:
175         /// {"name": "button_event", "value": "up", "event": "pressed"}
176
177         json_object *rootobject;
178         json_tokener *tokener = json_tokener_new();
179
180
181         ///TODO: we have several json leaks here
182
183         enum json_tokener_error err;
184         do
185         {
186                 rootobject = json_tokener_parse_ex(tokener, json.c_str(),json.length());
187         } while ((err = json_tokener_get_error(tokener)) == json_tokener_continue);
188         if (err != json_tokener_success)
189         {
190                 fprintf(stderr, "Error: %s\n", json_tokener_error_desc(err));
191                 // Handle errors, as appropriate for your application.
192         }
193         if (tokener->char_offset < json.length()) // XXX shouldn't access internal fields
194         {
195                 // Handle extra characters after parsed object as desired.
196                 // e.g. issue an error, parse another object from that point, etc...
197         }
198
199         VehicleProperty::Property property;
200
201         json_object *name = json_object_object_get(rootobject,"name");
202         if (name)
203         {
204                 string namestr = string(json_object_get_string(name));
205
206                 property = openXC2AmbMap[namestr];
207         }
208
209         json_object *value = json_object_object_get(rootobject, "value");
210         if(value)
211         {
212                 if (property == VehicleProperty::SteeringWheelAngle)
213                 {
214                         int val = json_object_get_int(value);
215                         VehicleProperty::SteeringWheelAngleType ambVal(val);
216
217                         routingEngine->updateProperty(property, &ambVal,uuid());
218
219                         return true;
220                 }
221
222                 else if (property == VehicleProperty::EngineSpeed)
223                 {
224                         int val = json_object_get_int(value);
225                         VehicleProperty::EngineSpeedType ambVal(val);
226
227                         routingEngine->updateProperty(property, &ambVal,uuid());
228                         return true;
229                 }
230
231                 else if (property == VehicleProperty::VehicleSpeed)
232                 {
233                         int val = json_object_get_int(value);
234                         VehicleProperty::VehicleSpeedType ambVal(val);
235
236                         routingEngine->updateProperty(property, &ambVal,uuid());
237                         return true;
238                 }
239
240                 else if (property == VehicleProperty::ThrottlePosition)
241                 {
242                         int val = json_object_get_int(value);
243                         VehicleProperty::ThrottlePositionType ambVal(val);
244
245                         routingEngine->updateProperty(property, &ambVal,uuid());
246
247                         return true;
248                 }
249
250                 else if (property == VehicleProperty::LightBrake)
251                 {
252                         bool val = json_object_get_boolean(value);
253                         VehicleProperty::LightBrakeType ambVal(val);
254
255                         routingEngine->updateProperty(property, &ambVal,uuid());
256
257                         return true;
258                 }
259
260                 else if (property == VehicleProperty::ParkingBrakeStatus)
261                 {
262                         bool val = json_object_get_boolean(value);
263                         VehicleProperty::ParkingBrakeStatusType ambVal(val);
264
265                         routingEngine->updateProperty(property, &ambVal,uuid());
266
267                         return true;
268                 }
269
270                 else if (property == VehicleProperty::TransmissionGearPosition)
271                 {
272                         /// TODO: implement
273                         return false;
274                 }
275
276                 else if (property == VehicleProperty::Odometer)
277                 {
278                         int val = json_object_get_int(value);
279                         VehicleProperty::OdometerType ambVal(val);
280
281                         routingEngine->updateProperty(property, &ambVal,uuid());
282
283                         return true;
284                 }
285
286                 else if (property == VehicleProperty::VehiclePowerMode)
287                 {
288                         /// TODO: implement
289                         return false;
290                 }
291
292                 else if (property == VehicleProperty::FuelLevel)
293                 {
294                         int val = json_object_get_int(value);
295                         VehicleProperty::FuelLevelType ambVal(val);
296
297                         routingEngine->updateProperty(property, &ambVal,uuid());
298
299                         return true;
300                 }
301
302                 else if (property == VehicleProperty::FuelConsumption)
303                 {
304                         /// This is a different concept than our 'instant' fuel consumption.
305                         /// TODO: we should probably do a CumulativeFuelConsuption
306                 }
307
308                 else if (property == VehicleProperty::DoorStatus)
309                 {
310
311                 }
312
313                 else if (property == VehicleProperty::LightHead)
314                 {
315                         bool val = json_object_get_boolean(value);
316                         VehicleProperty::LightHeadType ambVal(val);
317
318                         routingEngine->updateProperty(property, &ambVal,uuid());
319
320                         return true;
321                 }
322
323                 else if (property == VehicleProperty::LightHighBeam)
324                 {
325                         bool val = json_object_get_boolean(value);
326                         VehicleProperty::LightHighBeamType ambVal(val);
327
328                         routingEngine->updateProperty(property, &ambVal, uuid());
329
330                         return true;
331                 }
332
333                 else if (property == VehicleProperty::WindshieldWiper)
334                 {
335                         bool val = json_object_get_boolean(value);
336                         if(val)
337                         {
338                                 Window::WiperSpeed speed = Window::Auto;
339
340                                 VehicleProperty::WindshieldWiperType ambVal(speed);
341                                 routingEngine->updateProperty(property, &ambVal, uuid());
342
343                                 return true;
344                         }
345                         else
346                         {
347                                 Window::WiperSpeed speed = Window::Off;
348
349                                 VehicleProperty::WindshieldWiperType ambVal(speed);
350                                 routingEngine->updateProperty(property, &ambVal, uuid());
351
352                                 return true;
353                         }
354
355                 }
356
357                 else if (property == VehicleProperty::Latitude)
358                 {
359                         double val = json_object_get_double(value);
360                         VehicleProperty::LatitudeType ambVal(val);
361
362                         routingEngine->updateProperty(property, &ambVal, uuid());
363
364                         return true;
365                 }
366
367                 else if (property == VehicleProperty::Longitude)
368                 {
369                         double val = json_object_get_double(value);
370                         VehicleProperty::LongitudeType ambVal(val);
371
372                         routingEngine->updateProperty(property, &ambVal, uuid());
373
374                         return true;
375                 }
376
377                 else if (property == VehicleProperty::ButtonEvent)
378                 {
379                         /// TODO: implement
380                         DebugOut(DebugOut::Error)<<"OpenXC button event not implemented"<<endl;
381                         return false;
382                 }
383         }
384
385         return false;
386
387 }
388
389 void OpenXCPlugin::testParseEngine()
390 {
391         bool passed = true;
392
393         if(!translateOpenXCEvent("{\"name\": \"steering_wheel_angle\", \"value\": 45}"))
394         {
395                 DebugOut(0)<<"OpenXC Parse Test (steering_wheel_angle): \tFailed"<<endl;
396                 passed = false;
397         }
398         else DebugOut(0)<<"OpenXC Parse Test (steering_wheel_angle): \tPassed"<<endl;
399
400         if(!translateOpenXCEvent("{\"name\": \"engine_speed\", \"value\": 5000}"))
401         {
402                 DebugOut(0)<<"OpenXC Parse Test (engine_speed): \t\tFailed"<<endl;
403                 passed = false;
404         }
405         else DebugOut(0)<<"OpenXC Parse Test (engine_speed): \t\tPassed"<<endl;
406         if(!translateOpenXCEvent("{\"name\": \"vehicle_speed\", \"value\": 100}"))
407         {
408                 DebugOut(0)<<"OpenXC Parse Test (vehicle_speed): \t\tFailed"<<endl;
409                 passed = false;
410         }
411         else DebugOut(0)<<"OpenXC Parse Test (vehicle_speed): \t\tPassed"<<endl;
412         if(!translateOpenXCEvent("{\"name\": \"accelerator_pedal_position\", \"value\": 90}"))
413         {
414                 DebugOut(0)<<"OpenXC Parse Test (accelerator_pedal_position): tFailed"<<endl;
415                 passed = false;
416         }
417         else DebugOut(0)<<"OpenXC Parse Test (accelerator_pedal_position):\tPassed"<<endl;
418         if(!translateOpenXCEvent("{\"name\": \"parking_brake_status\", \"value\": \"false\" }"))
419         {
420                 DebugOut(0)<<"OpenXC Parse Test (parking_brake_status):\tFailed"<<endl;
421                 passed = false;
422         }
423         else DebugOut(0)<<"OpenXC Parse Test (parking_brake_status):\tPassed"<<endl;
424         if(!translateOpenXCEvent("{\"name\": \"brake_pedal_status\", \"value\": \"false\" }"))
425         {
426                 DebugOut(0)<<"OpenXC Parse Test (brake_pedal_status):\tFailed"<<endl;
427                 passed = false;
428         }
429         else DebugOut(0)<<"OpenXC Parse Test (brake_pedal_status):\tPassed"<<endl;
430         if(!translateOpenXCEvent("{\"name\": \"transmission_gear_position\", \"value\": \"fourth\"}"))
431         {
432                 DebugOut(0)<<"OpenXC Parse Test (transmission_gear_position):\tFailed"<<endl;
433                 passed = false;
434         }
435         else DebugOut(0)<<"OpenXC Parse Test (transmission_gear_position):\tPassed"<<endl;
436         if(!translateOpenXCEvent("{\"name\": \"odometer\", \"value\": 1000}"))
437         {
438                 DebugOut(0)<<"OpenXC Parse Test (odometer): \t\tFailed"<<endl;
439                 passed = false;
440         }
441         else DebugOut(0)<<"OpenXC Parse Test (odometer): \t\tPassed"<<endl;
442         if(!translateOpenXCEvent("{\"name\": \"ignition_status\", \"value\": \"run\"}"))
443         {
444                 DebugOut(0)<<"OpenXC Parse Test (ignition_status): \t\tFailed"<<endl;
445                 passed = false;
446         }
447         else DebugOut(0)<<"OpenXC Parse Test (ignition_status): \t\tPassed"<<endl;
448         if(!translateOpenXCEvent("{\"name\": \"fuel_level\", \"value\": 30}"))
449         {
450                 DebugOut(0)<<"OpenXC Parse Test (fuel_level): \t\tFailed"<<endl;
451                 passed = false;
452         }
453         else DebugOut(0)<<"OpenXC Parse Test (fuel_level): \t\tPassed"<<endl;
454         if(!translateOpenXCEvent("{\"name\": \"fuel_consumed_since_restart\", \"value\": 45}"))
455         {
456                 DebugOut(0)<<"OpenXC Parse Test (fuel_consumed_since_restart):\tFailed"<<endl;
457                 passed = false;
458         }
459         else DebugOut(0)<<"OpenXC Parse Test (fuel_consumed_since_restart):\tPassed"<<endl;
460         if(!translateOpenXCEvent("{\"name\": \"headlamp_status\", \"value\": \"true\"}"))
461         {
462                 DebugOut(0)<<"OpenXC Parse Test (headlamp_status): \t\tFailed"<<endl;
463                 passed = false;
464         }
465         else DebugOut(0)<<"OpenXC Parse Test (headlamp_status): \t\tPassed"<<endl;
466         if(!translateOpenXCEvent("{\"name\": \"latitude\", \"value\": 88.12125}"))
467         {
468                 DebugOut(0)<<"OpenXC Parse Test (latitude): \t\tFailed"<<endl;
469                 passed = false;
470         }
471         else DebugOut(0)<<"OpenXC Parse Test (latitude): \t\tPassed"<<endl;
472         if(!translateOpenXCEvent("{\"name\": \"longitude\", \"value\": 108.12125}"))
473         {
474                 DebugOut(0)<<"OpenXC Parse Test (longitude): \t\tFailed"<<endl;
475                 passed = false;
476         }
477         else DebugOut(0)<<"OpenXC Parse Test (longitude): \t\tPassed"<<endl;
478         if(!translateOpenXCEvent("{\"name\": \"button_event\", \"value\": \"up\", \"event\": \"pressed\"}"))
479         {
480                 DebugOut(0)<<"OpenXC Parse Test (button_event): \t\tFailed"<<endl;
481                 passed = false;
482         }
483         else DebugOut(0)<<"OpenXC Parse Test (button_event): \t\tPassed"<<endl;
484
485         if(!passed)
486         {
487                 DebugOut(0)<<"Some OpenXC Parse Tests failed.  Aborting";
488                 throw std::runtime_error("OpenXC Parse tests failed.");
489         }
490 }
491
492
493 void OpenXCPlugin::processData()
494 {
495         std::string data = device->read();
496
497         translateOpenXCEvent(data);
498 }