2 Copyright (C) 2012 Intel Corporation
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.
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.
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
19 #include "openxcplugin.h"
20 #include "timestamp.h"
23 #include <boost/assert.hpp>
26 #include "bluetooth.hpp"
32 bool gioPollingFunc(GIOChannel *source,GIOCondition condition,gpointer data)
34 if (condition == G_IO_HUP)
36 //Hang up. Returning false closes out the GIOChannel.
37 //printf("Callback on G_IO_HUP\n");
41 OpenXCPlugin* plugin = static_cast<OpenXCPlugin*>(data);
45 throw std::runtime_error("Bad cast to OpenXCPlugin*");
48 plugin->processData();
53 OpenXCPlugin::OpenXCPlugin(AbstractRoutingEngine* re, map<string, string> config)
54 :AbstractSource(re, config)
56 re->setSupported(supported(), this);
58 /// populate the openxc to amb map:
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;
80 if(config.find("test") != config.end())
82 test = config["test"] == "true";
90 std::string bluetoothAddy = config["device"];
91 std::string bluetoothAdapter = config["bluetoothAdapter"];
92 std::string serialDevice;
94 if(bluetoothAddy != "")
96 BluetoothDevice btDevice;
98 serialDevice = btDevice.getDeviceForAddress(bluetoothAddy, bluetoothAdapter);
101 device = new SerialPort(serialDevice);
104 throw std::runtime_error("unable to open serial device " + serialDevice);
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.
118 extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config)
120 return new OpenXCPlugin(routingengine, config);
124 const string OpenXCPlugin::uuid()
130 void OpenXCPlugin::getPropertyAsync(AsyncPropertyReply *reply)
135 void OpenXCPlugin::getRangePropertyAsync(AsyncRangePropertyReply *reply)
140 AsyncPropertyReply *OpenXCPlugin::setProperty(AsyncSetPropertyRequest request )
145 void OpenXCPlugin::subscribeToPropertyChanges(VehicleProperty::Property property)
147 mRequests.push_back(property);
150 PropertyList OpenXCPlugin::supported()
157 int OpenXCPlugin::supportedOperations()
162 void OpenXCPlugin::unsubscribeToPropertyChanges(VehicleProperty::Property property)
164 mRequests.remove(property);
169 bool OpenXCPlugin::translateOpenXCEvent(string json)
172 /// {"name": "steering_wheel_angle", "value": 45}
175 /// {"name": "button_event", "value": "up", "event": "pressed"}
177 json_object *rootobject;
178 json_tokener *tokener = json_tokener_new();
181 ///TODO: we have several json leaks here
183 enum json_tokener_error err;
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)
190 fprintf(stderr, "Error: %s\n", json_tokener_error_desc(err));
191 // Handle errors, as appropriate for your application.
193 if (tokener->char_offset < json.length()) // XXX shouldn't access internal fields
195 // Handle extra characters after parsed object as desired.
196 // e.g. issue an error, parse another object from that point, etc...
199 VehicleProperty::Property property;
201 json_object *name = json_object_object_get(rootobject,"name");
204 string namestr = string(json_object_get_string(name));
206 property = openXC2AmbMap[namestr];
209 json_object *value = json_object_object_get(rootobject, "value");
212 if (property == VehicleProperty::SteeringWheelAngle)
214 int val = json_object_get_int(value);
215 VehicleProperty::SteeringWheelAngleType ambVal(val);
217 routingEngine->updateProperty(property, &ambVal,uuid());
222 else if (property == VehicleProperty::EngineSpeed)
224 int val = json_object_get_int(value);
225 VehicleProperty::EngineSpeedType ambVal(val);
227 routingEngine->updateProperty(property, &ambVal,uuid());
231 else if (property == VehicleProperty::VehicleSpeed)
233 int val = json_object_get_int(value);
234 VehicleProperty::VehicleSpeedType ambVal(val);
236 routingEngine->updateProperty(property, &ambVal,uuid());
240 else if (property == VehicleProperty::ThrottlePosition)
242 int val = json_object_get_int(value);
243 VehicleProperty::ThrottlePositionType ambVal(val);
245 routingEngine->updateProperty(property, &ambVal,uuid());
250 else if (property == VehicleProperty::LightBrake)
252 bool val = json_object_get_boolean(value);
253 VehicleProperty::LightBrakeType ambVal(val);
255 routingEngine->updateProperty(property, &ambVal,uuid());
260 else if (property == VehicleProperty::ParkingBrakeStatus)
262 bool val = json_object_get_boolean(value);
263 VehicleProperty::ParkingBrakeStatusType ambVal(val);
265 routingEngine->updateProperty(property, &ambVal,uuid());
270 else if (property == VehicleProperty::TransmissionGearPosition)
276 else if (property == VehicleProperty::Odometer)
278 int val = json_object_get_int(value);
279 VehicleProperty::OdometerType ambVal(val);
281 routingEngine->updateProperty(property, &ambVal,uuid());
286 else if (property == VehicleProperty::VehiclePowerMode)
292 else if (property == VehicleProperty::FuelLevel)
294 int val = json_object_get_int(value);
295 VehicleProperty::FuelLevelType ambVal(val);
297 routingEngine->updateProperty(property, &ambVal,uuid());
302 else if (property == VehicleProperty::FuelConsumption)
304 /// This is a different concept than our 'instant' fuel consumption.
305 /// TODO: we should probably do a CumulativeFuelConsuption
308 else if (property == VehicleProperty::DoorStatus)
313 else if (property == VehicleProperty::LightHead)
315 bool val = json_object_get_boolean(value);
316 VehicleProperty::LightHeadType ambVal(val);
318 routingEngine->updateProperty(property, &ambVal,uuid());
323 else if (property == VehicleProperty::LightHighBeam)
325 bool val = json_object_get_boolean(value);
326 VehicleProperty::LightHighBeamType ambVal(val);
328 routingEngine->updateProperty(property, &ambVal, uuid());
333 else if (property == VehicleProperty::WindshieldWiper)
335 bool val = json_object_get_boolean(value);
338 Window::WiperSpeed speed = Window::Auto;
340 VehicleProperty::WindshieldWiperType ambVal(speed);
341 routingEngine->updateProperty(property, &ambVal, uuid());
347 Window::WiperSpeed speed = Window::Off;
349 VehicleProperty::WindshieldWiperType ambVal(speed);
350 routingEngine->updateProperty(property, &ambVal, uuid());
357 else if (property == VehicleProperty::Latitude)
359 double val = json_object_get_double(value);
360 VehicleProperty::LatitudeType ambVal(val);
362 routingEngine->updateProperty(property, &ambVal, uuid());
367 else if (property == VehicleProperty::Longitude)
369 double val = json_object_get_double(value);
370 VehicleProperty::LongitudeType ambVal(val);
372 routingEngine->updateProperty(property, &ambVal, uuid());
377 else if (property == VehicleProperty::ButtonEvent)
380 DebugOut(DebugOut::Error)<<"OpenXC button event not implemented"<<endl;
389 void OpenXCPlugin::testParseEngine()
393 if(!translateOpenXCEvent("{\"name\": \"steering_wheel_angle\", \"value\": 45}"))
395 DebugOut(0)<<"OpenXC Parse Test (steering_wheel_angle): \tFailed"<<endl;
398 else DebugOut(0)<<"OpenXC Parse Test (steering_wheel_angle): \tPassed"<<endl;
400 if(!translateOpenXCEvent("{\"name\": \"engine_speed\", \"value\": 5000}"))
402 DebugOut(0)<<"OpenXC Parse Test (engine_speed): \t\tFailed"<<endl;
405 else DebugOut(0)<<"OpenXC Parse Test (engine_speed): \t\tPassed"<<endl;
406 if(!translateOpenXCEvent("{\"name\": \"vehicle_speed\", \"value\": 100}"))
408 DebugOut(0)<<"OpenXC Parse Test (vehicle_speed): \t\tFailed"<<endl;
411 else DebugOut(0)<<"OpenXC Parse Test (vehicle_speed): \t\tPassed"<<endl;
412 if(!translateOpenXCEvent("{\"name\": \"accelerator_pedal_position\", \"value\": 90}"))
414 DebugOut(0)<<"OpenXC Parse Test (accelerator_pedal_position): tFailed"<<endl;
417 else DebugOut(0)<<"OpenXC Parse Test (accelerator_pedal_position):\tPassed"<<endl;
418 if(!translateOpenXCEvent("{\"name\": \"parking_brake_status\", \"value\": \"false\" }"))
420 DebugOut(0)<<"OpenXC Parse Test (parking_brake_status):\tFailed"<<endl;
423 else DebugOut(0)<<"OpenXC Parse Test (parking_brake_status):\tPassed"<<endl;
424 if(!translateOpenXCEvent("{\"name\": \"brake_pedal_status\", \"value\": \"false\" }"))
426 DebugOut(0)<<"OpenXC Parse Test (brake_pedal_status):\tFailed"<<endl;
429 else DebugOut(0)<<"OpenXC Parse Test (brake_pedal_status):\tPassed"<<endl;
430 if(!translateOpenXCEvent("{\"name\": \"transmission_gear_position\", \"value\": \"fourth\"}"))
432 DebugOut(0)<<"OpenXC Parse Test (transmission_gear_position):\tFailed"<<endl;
435 else DebugOut(0)<<"OpenXC Parse Test (transmission_gear_position):\tPassed"<<endl;
436 if(!translateOpenXCEvent("{\"name\": \"odometer\", \"value\": 1000}"))
438 DebugOut(0)<<"OpenXC Parse Test (odometer): \t\tFailed"<<endl;
441 else DebugOut(0)<<"OpenXC Parse Test (odometer): \t\tPassed"<<endl;
442 if(!translateOpenXCEvent("{\"name\": \"ignition_status\", \"value\": \"run\"}"))
444 DebugOut(0)<<"OpenXC Parse Test (ignition_status): \t\tFailed"<<endl;
447 else DebugOut(0)<<"OpenXC Parse Test (ignition_status): \t\tPassed"<<endl;
448 if(!translateOpenXCEvent("{\"name\": \"fuel_level\", \"value\": 30}"))
450 DebugOut(0)<<"OpenXC Parse Test (fuel_level): \t\tFailed"<<endl;
453 else DebugOut(0)<<"OpenXC Parse Test (fuel_level): \t\tPassed"<<endl;
454 if(!translateOpenXCEvent("{\"name\": \"fuel_consumed_since_restart\", \"value\": 45}"))
456 DebugOut(0)<<"OpenXC Parse Test (fuel_consumed_since_restart):\tFailed"<<endl;
459 else DebugOut(0)<<"OpenXC Parse Test (fuel_consumed_since_restart):\tPassed"<<endl;
460 if(!translateOpenXCEvent("{\"name\": \"headlamp_status\", \"value\": \"true\"}"))
462 DebugOut(0)<<"OpenXC Parse Test (headlamp_status): \t\tFailed"<<endl;
465 else DebugOut(0)<<"OpenXC Parse Test (headlamp_status): \t\tPassed"<<endl;
466 if(!translateOpenXCEvent("{\"name\": \"latitude\", \"value\": 88.12125}"))
468 DebugOut(0)<<"OpenXC Parse Test (latitude): \t\tFailed"<<endl;
471 else DebugOut(0)<<"OpenXC Parse Test (latitude): \t\tPassed"<<endl;
472 if(!translateOpenXCEvent("{\"name\": \"longitude\", \"value\": 108.12125}"))
474 DebugOut(0)<<"OpenXC Parse Test (longitude): \t\tFailed"<<endl;
477 else DebugOut(0)<<"OpenXC Parse Test (longitude): \t\tPassed"<<endl;
478 if(!translateOpenXCEvent("{\"name\": \"button_event\", \"value\": \"up\", \"event\": \"pressed\"}"))
480 DebugOut(0)<<"OpenXC Parse Test (button_event): \t\tFailed"<<endl;
483 else DebugOut(0)<<"OpenXC Parse Test (button_event): \t\tPassed"<<endl;
487 DebugOut(0)<<"Some OpenXC Parse Tests failed. Aborting";
488 throw std::runtime_error("OpenXC Parse tests failed.");
493 void OpenXCPlugin::processData()
495 std::string data = device->read();
497 translateOpenXCEvent(data);