refactored setProperty: made it async with callback
[profile/ivi/automotive-message-broker.git] / plugins / obd2plugin / obd2source.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 "obd2source.h"
21 #include <iostream>
22 #include <boost/assert.hpp>
23 #include <boost/lexical_cast.hpp>
24 #include <glib.h>
25 #include <sstream>
26 #include <json-glib/json-glib.h>
27 #include <listplusplus.h>
28 #include "debugout.h"
29 #include "bluetooth.hpp"
30
31
32 #define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
33 AbstractRoutingEngine *m_re;
34
35 int calledPersecond = 0;
36
37 bool sendElmCommand(obdLib *obd,std::string command)
38 {
39         std::vector<unsigned char> replyVector;
40         std::string reply;
41         obd->sendObdRequestString(command.append("\r").c_str(),command.length()+1,&replyVector,10,3);
42         for (unsigned int i=0;i<replyVector.size();i++)
43         {
44                 reply += replyVector[i];
45         }
46         if (reply.find("OK") == -1)
47         {
48                 //No OK reply found
49                 return false;
50         }
51         else
52         {
53                 return true;
54         }
55
56 }
57 void threadLoop(gpointer data)
58 {
59         GAsyncQueue *privCommandQueue = g_async_queue_ref(((OBD2Source*)data)->commandQueue);
60         GAsyncQueue *privResponseQueue = g_async_queue_ref(((OBD2Source*)data)->responseQueue);
61         GAsyncQueue *privSingleShotQueue = g_async_queue_ref(((OBD2Source*)data)->singleShotQueue);
62         GAsyncQueue *privSubscriptionAddQueue = g_async_queue_ref(((OBD2Source*)data)->subscriptionAddQueue);
63         GAsyncQueue *privSubscriptionRemoveQueue = g_async_queue_ref(((OBD2Source*)data)->subscriptionRemoveQueue);
64         obdLib *obd = new obdLib();
65
66         obd->setCommsCallback([](const char* mssg, void* data) { DebugOut(6)<<mssg<<endl; },NULL);
67         obd->setDebugCallback([](const char* mssg, void* data, obdLib::DebugLevel debugLevel) { DebugOut(debugLevel)<<mssg<<endl; },NULL);
68         
69         std::list<std::string> reqList;
70         std::list<std::string> repeatReqList;
71         std::map<std::string,std::string> commandMap;
72         std::vector<unsigned char> replyVector;
73         std::string reply;
74         while (true)
75         {
76                 //gpointer query = g_async_queue_pop(privCommandQueue);
77                 
78                 
79                 gpointer query = g_async_queue_try_pop(privSingleShotQueue);
80                 if (query != nullptr)
81                 {
82                         //printf("Got request!\n");
83                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got single shot request!"<<endl;
84                         ObdRequest *req = (ObdRequest*)query;
85                         repeatReqList.push_back(req->req);
86                         delete req;
87                 }
88                 query = g_async_queue_try_pop(privSubscriptionAddQueue);
89                 if (query != nullptr)
90                 {
91
92                         ObdRequest *req = (ObdRequest*)query;
93                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got subscription request for "<<req->req<<endl;
94                         reqList.push_back(req->req);
95                         delete req;
96                 }
97                 query = g_async_queue_try_pop(privCommandQueue);
98                 if (query != nullptr)
99                 {
100                         ObdRequest *req = (ObdRequest*)query;
101                         //commandMap[req->req] = req->arg;
102                         //printf("Command: %s\n",req->req.c_str());
103                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Command:" << req->req << endl;
104                         if (req->req == "connect")
105                         {
106                                 //printf("First: %s\nSecond: %s\n",req->arg.substr(0,req->arg.find(':')).c_str(),req->arg.substr(req->arg.find(':')+1).c_str());
107                                 std::string port = req->arg.substr(0,req->arg.find(':'));
108                                 int baud = boost::lexical_cast<int>(req->arg.substr(req->arg.find(':')+1));
109                                 obd->openPort(port.c_str(),baud);
110                                 
111                                 obd->sendObdRequestString("ATZ\r",4,&replyVector,500,3);
112                                 for (unsigned int i=0;i<replyVector.size();i++)
113                                 {
114                                         reply += replyVector[i];
115                                 }
116                                 if (reply.find("ELM") == -1)
117                                 {
118                                         //No reply found
119                                         //printf("Error!\n");
120                                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error resetting ELM\n";
121                                 }
122                                 else
123                                 {
124                                         //printf("Reply to reset: %s\n",reply.c_str());
125                                 }
126                                 if (!sendElmCommand(obd,"ATSP0"))
127                                 {
128                                         //printf("Error sending echo\n");
129                                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error setting auto protocol"<<endl;
130                                 }
131                                 if (!sendElmCommand(obd,"ATE0"))
132                                 {
133                                         //printf("Error sending echo\n");
134                                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error turning off echo"<<endl;
135                                 }
136                                 if (!sendElmCommand(obd,"ATH0"))
137                                 {
138                                         //printf("Error sending headers off\n");
139                                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error turning off headers"<<endl;
140                                 }
141                                 if (!sendElmCommand(obd,"ATL0"))
142                                 {
143                                         //printf("Error turning linefeeds off\n");
144                                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error turning off linefeeds"<<endl;
145                                 }
146                         }
147                         delete req;
148                 }
149                 query = g_async_queue_try_pop(privSubscriptionRemoveQueue);
150                 if (query != nullptr)
151                 {
152                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got unsubscription request\n";
153                         ObdRequest *req = (ObdRequest*)query;
154                         for (std::list<std::string>::iterator i=reqList.begin();i!= reqList.end();i++)
155                         {
156                                 if ((*i) == req->req)
157                                 {
158                                         reqList.erase(i);
159                                         i--;
160                                 }
161                         }
162                         //reqList.push_back(req->req);
163                         delete req;
164                 }
165                 
166                 for (std::list<std::string>::iterator i=reqList.begin();i!= reqList.end();i++)
167                 {
168                         repeatReqList.push_back(*i);
169                 }
170                 for (std::list<std::string>::iterator i=repeatReqList.begin();i!= repeatReqList.end();i++)
171                 {
172                         //printf("Req: %s\n",(*i).c_str());
173                         if ((*i) == "ATRV\r")
174                         {
175                                 //printf("Requesting voltage...\n");
176                                 if (!obd->sendObdRequestString((*i).c_str(),(*i).length(),&replyVector))
177                                 {
178                                         //printf("Unable to request voltage!!!\n");
179                                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Unable to request voltage!\n";
180                                         continue;
181                                 }
182                                 std::string replystring = "";
183                                 for (int j=0;j<replyVector.size();j++)
184                                 {
185                                         replystring += replyVector[j];
186                                 }
187                                 //printf("Voltage reply: %s\n",replystring.c_str());
188                                 replystring.substr(0,replystring.find("V"));
189                                 ObdReply *rep = new ObdReply();
190                                 rep->req = "ATRV\r";
191                                 rep->reply = replystring;
192                                 g_async_queue_push(privResponseQueue,rep);
193                         }
194                         if (!obd->sendObdRequest((*i).c_str(),(*i).length(),&replyVector))
195                         {
196                                 //printf("Error sending obd2 request\n");
197                                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error sending OBD2 request\n";
198                                 continue;
199                         }
200                         //printf("Reply: %i %i\n",replyVector[0],replyVector[1]);
201                         if (replyVector[0] == 0x41)
202                         {
203                                 if (replyVector[1] == 0x0C)
204                                 {
205                                         double rpm = ((replyVector[2] << 8) + replyVector[3]) / 4.0;
206                                         ObdReply *rep = new ObdReply();
207                                         rep->req = "0C";
208                                         rep->reply = boost::lexical_cast<string>(rpm);
209                                         g_async_queue_push(privResponseQueue,rep);
210                                         //printf("RPM: %f\n",rpm);
211                                 }
212                                 else if (replyVector[1] == 0x0D)
213                                 {
214                                       int mph = replyVector[2];
215                                       ObdReply *rep = new ObdReply();
216                                       rep->req = "0D";
217                                       rep->reply = boost::lexical_cast<string>(mph);
218                                       g_async_queue_push(privResponseQueue,rep);
219                                 }
220                                 else if (replyVector[1] == 0x05)
221                                 {
222                                         int temp = replyVector[2] - 40;
223                                         ObdReply *rep = new ObdReply();
224                                         rep->req = "05";
225                                         rep->reply = boost::lexical_cast<string>(temp);
226                                         g_async_queue_push(privResponseQueue,rep);
227                                 }
228                                 else if (replyVector[1] == 0x10)
229                                 {
230                                         double maf = ((replyVector[2] << 8) + replyVector[3]) / 100.0;
231                                         ObdReply *rep = new ObdReply();
232                                         rep->req = "10";
233                                         rep->reply = boost::lexical_cast<string>(maf);
234                                         g_async_queue_push(privResponseQueue,rep);
235                                 }
236                                 else
237                                 {
238                                         //printf("Unknown response type: %i\n",replyVector[1]);
239                                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Unknown response type" << replyVector[1] << "\n";
240                                 }
241                         }
242                         else if (replyVector[0] == 0x49)
243                         {
244                                 /*
245                                 49 02 01 00 00 00 31 
246                                 49 02 02 47 31 4A 43 
247                                 49 02 03 35 34 34 34 
248                                 49 02 04 52 37 32 35 
249                                 49 02 05 32 33 36 37 
250                                 */
251                                 //VIN number reply
252                                 string vinstring;
253                                 for (int j=0;j<replyVector.size();j++)
254                                 {
255                                         if(replyVector[j] == 0x49 && replyVector[j+1] == 0x02)
256                                         {
257                                                 //We're at a reply header
258                                                 j+=3;
259                                         }
260                                         if (replyVector[j] != 0x00)
261                                         {
262                                                 vinstring += (char)replyVector[j];
263                                                 //printf("VIN: %i %c\n",replyVector[j],replyVector[j]);
264                                         }
265                                 }
266                                 ObdReply *rep = new ObdReply();
267                                 rep->req = "0902";
268                                 rep->reply = vinstring;
269                                 g_async_queue_push(privResponseQueue,rep);
270                                 //printf("VIN Number: %i %s\n",replyVector.size(),vinstring.c_str());
271                                 
272                         }
273                         
274                         //DebugOut()<<"Reply: "<<replyVector[2]<<" "<<replyVector[3]<<endl;
275                 }
276                 if(!reqList.size()) usleep(10000);
277                 repeatReqList.clear();
278         }
279         
280 }
281
282 static int updateProperties(/*gpointer retval,*/ gpointer data)
283 {
284
285         OBD2Source* src = (OBD2Source*)data;
286         
287         while(gpointer retval = g_async_queue_try_pop(src->responseQueue))
288         {
289                 ObdReply *reply = (ObdReply*)retval;
290                 if (reply->req == "05")
291                 {
292                         VehicleProperty::EngineCoolantTemperatureType speed(reply->reply);
293                         src->updateProperty(VehicleProperty::EngineCoolantTemperature,&speed);
294                 }
295                 else if (reply->req == "0C")
296                 {
297                         VehicleProperty::EngineSpeedType speed(reply->reply);
298                         src->updateProperty(VehicleProperty::EngineSpeed,&speed); 
299                 }
300                 else if (reply->req == "0D")
301                 {
302                         VehicleProperty::VehicleSpeedType speed(reply->reply);
303                         src->updateProperty(VehicleProperty::VehicleSpeed,&speed);
304                 }
305                 else if (reply->req == "10")
306                 {
307                         VehicleProperty::MassAirFlowType mass(reply->reply);
308                         src->updateProperty(VehicleProperty::MassAirFlow,&mass);
309                 }
310                 else if (reply->req == "ATRV\r")
311                 {
312                         VehicleProperty::BatteryVoltageType volts(reply->reply);
313                         src->updateProperty(VehicleProperty::BatteryVoltage,&volts);
314                         
315                 }
316                 else if (reply->req == "0902")
317                 {
318                         //VIN number and WMI
319                         VehicleProperty::VINType vin(reply->reply);
320                         src->updateProperty(VehicleProperty::VIN,&vin);
321                         VehicleProperty::WMIType wmi(reply->reply.substr(0,3));
322                         src->updateProperty(VehicleProperty::WMI,&wmi);
323                 }
324                 else if (reply->req == "5C")
325                 {
326                         VehicleProperty::EngineCoolantTemperatureType ect(reply->reply);
327                         src->updateProperty(VehicleProperty::EngineCoolantTemperature,&ect);
328                 }
329                 else if (reply->req == "46")
330                 {
331                         VehicleProperty::InteriorTemperatureType temp(reply->reply);
332                         src->updateProperty(VehicleProperty::InteriorTemperature,&temp);
333                 }
334                 //5C -- engine oil temp
335                 //46 interior temp
336                 delete reply;
337         }
338
339         return true;
340 }
341 void OBD2Source::updateProperty(VehicleProperty::Property property,AbstractPropertyType* value)
342 {
343         //m_re->updateProperty(property,&value);
344         m_re->updateProperty(property,value); 
345         if (propertyReplyMap.find(property) != propertyReplyMap.end())
346         {
347                 propertyReplyMap[property]->value = value;
348                 propertyReplyMap[property]->completed(propertyReplyMap[property]);
349                 propertyReplyMap.erase(property);
350         }
351 }
352 void OBD2Source::mafValue(double maf)
353 {
354         VehicleProperty::VehicleSpeedType emaf(maf);
355         m_re->updateProperty(VehicleProperty::MassAirFlow,&emaf);
356 }
357 void OBD2Source::engineCoolantTemp(int temp)
358 {
359         VehicleProperty::VehicleSpeedType etemp(temp);
360         m_re->updateProperty(VehicleProperty::EngineCoolantTemperature,&etemp);
361 }
362 void OBD2Source::engineSpeed(double speed)
363 {
364         VehicleProperty::VehicleSpeedType espeed(speed);
365         m_re->updateProperty(VehicleProperty::EngineSpeed,&espeed);
366 }
367 void OBD2Source::vehicleSpeed(int speed)
368 {
369         VehicleProperty::EngineSpeedType vspeed(speed);
370         m_re->updateProperty(VehicleProperty::VehicleSpeed,&vspeed);
371 }
372 void OBD2Source::setSupported(PropertyList list)
373 {
374         m_supportedProperties = list;
375         m_re->updateSupported(list,PropertyList());
376 }
377 /*void OBD2Source::propertySignal(VehicleProperty::Property property,boost::any value)
378 {
379 }
380 void OBD2Source::checkProperty()
381 {
382 }*/
383 void OBD2Source::setConfiguration(map<string, string> config)
384 {
385 //      //Config has been passed, let's start stuff up.
386         configuration = config;
387         
388         //Default values
389         std::string port = "/dev/ttyUSB0";
390         std::string baud = "115200";
391         std::string btadapter = "";
392         
393         //Try to load config
394         //printf("OBD2Source::setConfiguration\n");
395         for (map<string,string>::iterator i=configuration.begin();i!=configuration.end();i++)
396         {
397                 //printf("Incoming setting: %s:%s\n",(*i).first.c_str(),(*i).second.c_str());
398                 DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << "Incoming setting:" << (*i).first << ":" << (*i).second << "\n";
399                 if ((*i).first == "device")
400                 {
401                         port = (*i).second;
402                 }
403                 else if ((*i).first == "baud")
404                 {
405                         baud = (*i).second;
406                 }
407
408                 else if ((*i).first == "bluetoothAdapter")
409                 {
410                         btadapter = (*i).second;
411                 }
412         }
413
414         if(port.find(":") != string::npos)
415         {
416                 ///TODO: bluetooth!!
417                 DebugOut()<<"bluetooth device?"<<endl;
418                 ObdBluetoothDevice bt;
419
420                 std::string tempPort = bt.getDeviceForAddress(port, btadapter);
421                 if(tempPort != "")
422                 {
423                         DebugOut(3)<<"Using bluetooth device \""<<port<<"\" bound to: "<<tempPort<<endl;
424                         port = tempPort;
425                 }
426                 else throw std::runtime_error("Device Error");
427         }
428
429         ObdRequest *requ = new ObdRequest();
430         requ->req = "connect";
431         requ->arg = port + ":" + baud;
432         g_async_queue_push(commandQueue,requ);
433 }
434
435 OBD2Source::OBD2Source(AbstractRoutingEngine *re, map<string, string> config) : AbstractSource(re, config)
436 {
437         clientConnected = false;
438         m_re = re;  
439
440         Obd2Amb obd2amb;
441
442         for(auto itr = obd2amb.propertyPidMap.begin(); itr != obd2amb.propertyPidMap.end(); itr++)
443         {
444                 m_supportedProperties.push_back((*itr).first);
445         }
446
447         re->setSupported(supported(), this);
448         /*if (openPort(std::string("/dev/pts/7"),115200))
449         {
450           printf("Error opening OBD2 port\n");
451         }*/
452         commandQueue = g_async_queue_new();
453         subscriptionAddQueue = g_async_queue_new();
454         subscriptionRemoveQueue = g_async_queue_new();
455         responseQueue = g_async_queue_new();
456         singleShotQueue = g_async_queue_new();
457         g_thread_new("mythread",(GThreadFunc)&threadLoop,this);
458
459         setConfiguration(config);
460
461         //AsyncQueueWatcher * watcher = new AsyncQueueWatcher(responseQueue, (AsyncQueueWatcherCallback) updateProperties, this);
462
463         //g_timeout_add(1,updateProperties, this);
464         g_idle_add(updateProperties, this);
465         //g_timeout_add(1000,calcCPS,NULL);
466
467 }
468
469 PropertyList OBD2Source::supported()
470 {
471         return m_supportedProperties;
472 }
473 extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config)
474 {
475         return new OBD2Source(routingengine, config);
476         
477 }
478 string OBD2Source::uuid()
479 {
480         return "f77af740-f1f8-11e1-aff1-0800200c9a66";
481 }
482 void OBD2Source::subscribeToPropertyChanges(VehicleProperty::Property property)
483 {
484         /*//printf("Subscribed to property: %s\n",property.c_str());
485         if (property == VehicleProperty::EngineSpeed)
486         {
487                 ObdRequest *requ = new ObdRequest();
488                 requ->req = "010C1\r";
489                 g_async_queue_push(subscriptionAddQueue,requ);
490         }
491         else if (property == VehicleProperty::MassAirFlow)
492         {
493                 ObdRequest *requ = new ObdRequest();
494                 requ->req = "01101\r";
495                 g_async_queue_push(subscriptionAddQueue,requ);
496         }
497         else if (property == VehicleProperty::VehicleSpeed)
498         {
499                 ObdRequest *requ = new ObdRequest();
500                 requ->req = "010D1\r";
501                 g_async_queue_push(subscriptionAddQueue,requ);
502         }
503         else if (property == VehicleProperty::EngineCoolantTemperature)
504         {
505                 ObdRequest *requ = new ObdRequest();
506                 requ->req = "01051\r";
507                 g_async_queue_push(subscriptionAddQueue,requ);
508         }
509         else if (property == VehicleProperty::VIN)
510         {
511                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "VIN subscription requested... but there's no point!\n";
512         }
513         else if (property == VehicleProperty::WMI)
514         {
515                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "WMI subscription requested... but there's no point!\n";
516         }
517         else if (property == VehicleProperty::EngineOilTemperature)
518         {
519                 ObdRequest *requ = new ObdRequest();
520                 requ->req = "015C1\r";
521                 g_async_queue_push(subscriptionAddQueue,requ);
522         }
523         else if (property == VehicleProperty::InteriorTemperature)
524         {
525                 ObdRequest *requ = new ObdRequest();
526                 requ->req = "01461\r";
527                 g_async_queue_push(subscriptionAddQueue,requ);
528         }
529         else if (property == VehicleProperty::BatteryVoltage)
530         {
531                 ObdRequest *requ = new ObdRequest();
532                 requ->req = "ATRV\r";
533                 g_async_queue_push(subscriptionAddQueue,requ);
534         }
535         /*m_supportedProperties.push_back(VehicleProperty::VIN);
536         m_supportedProperties.push_back(VehicleProperty::WMI);
537         m_supportedProperties.push_back(VehicleProperty::EngineOilTemperature);
538         m_supportedProperties.push_back(VehicleProperty::InteriorTemperature);
539         m_supportedProperties.push_back(VehicleProperty::BatteryVoltage);*/
540         /*else
541         {
542                 //printf("Unsupported property: %s\n",property.c_str());
543                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Unsupported property requested:" << property << "\n";
544         }*/
545
546         if (property == VehicleProperty::VIN)
547         {
548                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "VIN subscription requested... but there's no point!"<<endl;
549         }
550         else if (property == VehicleProperty::WMI)
551         {
552                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "WMI subscription requested... but there's no point!"<<endl;
553         }
554         else
555         {
556                 if(!ListPlusPlus<VehicleProperty::Property>(&m_supportedProperties).contains(property))
557                 {
558                         DebugOut(0)<<"obd plugin does not support: "<<property<<endl;
559                         return;
560                 }
561
562                 Obd2Amb obd2amb;
563                 ObdRequest *requ = new ObdRequest();
564                 requ->req = obd2amb.propertyPidMap[property];
565                 g_async_queue_push(subscriptionAddQueue,requ);
566         }
567 }
568
569
570 void OBD2Source::unsubscribeToPropertyChanges(VehicleProperty::Property property)
571 {
572         //
573         /*if (property == VehicleProperty::EngineSpeed)
574         {
575                 ObdRequest *requ = new ObdRequest();
576                 requ->req = "010C1\r";
577                 g_async_queue_push(subscriptionRemoveQueue,requ);
578         }
579         else if (property == VehicleProperty::MassAirFlow)
580         {
581                 ObdRequest *requ = new ObdRequest();
582                 requ->req = "01101\r";
583                 g_async_queue_push(subscriptionRemoveQueue,requ);
584         }
585         else if (property == VehicleProperty::VehicleSpeed)
586         {
587                 ObdRequest *requ = new ObdRequest();
588                 requ->req = "010D1\r";
589                 g_async_queue_push(subscriptionRemoveQueue,requ);
590         }
591         else if (property == VehicleProperty::EngineCoolantTemperature)
592         {
593                 ObdRequest *requ = new ObdRequest();
594                 requ->req = "01051\r";
595                 g_async_queue_push(subscriptionRemoveQueue,requ);
596         }
597         else if (property == VehicleProperty::VIN)
598         {
599                 ObdRequest *requ = new ObdRequest();
600                 requ->req = "0902\r";
601                 g_async_queue_push(subscriptionRemoveQueue,requ);
602         }
603         else if (property == VehicleProperty::WMI)
604         {
605                 ObdRequest *requ = new ObdRequest();
606                 requ->req = "0902\r";
607                 g_async_queue_push(subscriptionRemoveQueue,requ);
608         }
609         else if (property == VehicleProperty::EngineOilTemperature)
610         {
611                 ObdRequest *requ = new ObdRequest();
612                 requ->req = "015C1\r";
613                 g_async_queue_push(subscriptionRemoveQueue,requ);
614         }
615         else if (property == VehicleProperty::InteriorTemperature)
616         {
617                 ObdRequest *requ = new ObdRequest();
618                 requ->req = "01461\r";
619                 g_async_queue_push(subscriptionRemoveQueue,requ);
620         }
621         else if (property == VehicleProperty::BatteryVoltage)
622         {
623                 ObdRequest *requ = new ObdRequest();
624                 requ->req = "ATRV\r";
625                 g_async_queue_push(subscriptionRemoveQueue,requ);
626         }
627         */
628
629         if(!ListPlusPlus<VehicleProperty::Property>(&m_supportedProperties).contains(property))
630         {
631                 DebugOut(0)<<"obd plugin does not support: "<<property<<endl;
632                 return;
633         }
634
635         Obd2Amb obd2amb;
636         ObdRequest *requ = new ObdRequest();
637         requ->req = obd2amb.propertyPidMap[property];
638         g_async_queue_push(subscriptionRemoveQueue,requ);
639 }
640
641
642 void OBD2Source::getPropertyAsync(AsyncPropertyReply *reply)
643 {
644         propertyReplyMap[reply->property] = reply;
645         VehicleProperty::Property property = reply->property;
646
647         //TODO: There is a much better way to do this, but for now it's hardcoded.
648         /*if (property == VehicleProperty::EngineSpeed)
649         {
650                 ObdRequest *requ = new ObdRequest();
651                 requ->req = "010C\r";
652                 g_async_queue_push(singleShotQueue,requ);
653         }
654         else if (property == VehicleProperty::MassAirFlow)
655         {
656                 ObdRequest *requ = new ObdRequest();
657                 requ->req = "0110\r";
658                 g_async_queue_push(singleShotQueue,requ);
659         }
660         else if (property == VehicleProperty::VehicleSpeed)
661         {
662                 ObdRequest *requ = new ObdRequest();
663                 requ->req = "010D\r";
664                 g_async_queue_push(singleShotQueue,requ);
665         }
666         else if (property == VehicleProperty::EngineCoolantTemperature)
667         {
668                 ObdRequest *requ = new ObdRequest();
669                 requ->req = "0105\r";
670                 g_async_queue_push(singleShotQueue,requ);
671         }
672         else if (property == VehicleProperty::VIN)
673         {
674                 ObdRequest *requ = new ObdRequest();
675                 requ->req = "0902\r";
676                 g_async_queue_push(singleShotQueue,requ);
677         }
678         else if (property == VehicleProperty::WMI)
679         {
680                 ObdRequest *requ = new ObdRequest();
681                 requ->req = "0902\r";
682                 g_async_queue_push(singleShotQueue,requ);
683         }
684         else if (property == VehicleProperty::EngineOilTemperature)
685         {
686                 ObdRequest *requ = new ObdRequest();
687                 requ->req = "015C\r";
688                 g_async_queue_push(singleShotQueue,requ);
689         }
690         else if (property == VehicleProperty::InteriorTemperature)
691         {
692                 ObdRequest *requ = new ObdRequest();
693                 requ->req = "0146\r";
694                 g_async_queue_push(singleShotQueue,requ);
695         }
696         else if (property == VehicleProperty::BatteryVoltage)
697         {
698                 ObdRequest *requ = new ObdRequest();
699                 requ->req = "ATRV\r";
700                 g_async_queue_push(singleShotQueue,requ);
701         }
702         */
703
704         ///Here's a better way:
705
706         if(!ListPlusPlus<VehicleProperty::Property>(&m_supportedProperties).contains(property))
707         {
708                 DebugOut(0)<<"obd plugin does not support: "<<property<<endl;
709                 return;
710         }
711
712         Obd2Amb obd2amb;
713         ObdRequest *requ = new ObdRequest();
714         requ->req = obd2amb.propertyPidMap[property];
715         g_async_queue_push(singleShotQueue,requ);
716 }
717
718 AsyncPropertyReply *OBD2Source::setProperty(AsyncSetPropertyRequest request )
719 {
720         AsyncPropertyReply* reply = new AsyncPropertyReply (request);
721         reply->success = false;
722         try
723         {
724                 reply->completed(reply);
725         }
726         catch (...)
727         {
728
729         }
730         return reply;
731 }