fixed compile errors in a few source plugins
[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 #include "timestamp.h"
31
32 #define __SMALLFILE__ std::string(__FILE__).substr(std::string(__FILE__).rfind("/")+1)
33 AbstractRoutingEngine *m_re;
34
35 //std::list<ObdPid*> Obd2Amb::supportedPidsList;
36 Obd2Amb *obd2AmbInstance = new Obd2Amb;
37 VehicleProperty::Property Obd2Connected = "Obd2Connected";
38 int calledPersecond = 0;
39
40 bool sendElmCommand(obdLib *obd,std::string command)
41 {
42         std::vector<unsigned char> replyVector;
43         std::string reply;
44         obd->sendObdRequestString(command.append("\r").c_str(),command.length()+1,&replyVector,10,3);
45         for (unsigned int i=0;i<replyVector.size();i++)
46         {
47                 reply += replyVector[i];
48         }
49         if (reply.find("OK") == -1)
50         {
51                 //No OK reply found
52                 return false;
53         }
54         else
55         {
56                 return true;
57         }
58
59 }
60
61 bool beginsWith(std::string a, std::string b)
62 {
63         return (a.compare(0, b.length(), b) == 0);
64 }
65
66 bool connect(obdLib* obd, std::string device, std::string strbaud)
67 {
68         //printf("First: %s\nSecond: %s\n",req->arg.substr(0,req->arg.find(':')).c_str(),req->arg.substr(req->arg.find(':')+1).c_str());
69         std::string port = device;
70         DebugOut() << "Obd2Source::Connect()" << device << strbaud << endl;
71         int baud = boost::lexical_cast<int>(strbaud);
72
73         if(obd->openPort(port.c_str(),baud) == -1)
74                 return false;
75
76         ObdPid::ByteArray replyVector;
77         std::string reply;
78         obd->sendObdRequestString("ATZ\r",4,&replyVector,500,3);
79         for (unsigned int i=0;i<replyVector.size();i++)
80         {
81                 reply += replyVector[i];
82         }
83         if (reply.find("ELM") == -1)
84         {
85                 //No reply found
86                 //printf("Error!\n");
87                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error resetting ELM"<<endl;
88                 return false;
89         }
90         else
91         {
92                 //printf("Reply to reset: %s\n",reply.c_str());
93         }
94         if (!sendElmCommand(obd,"ATSP0"))
95         {
96                 //printf("Error sending echo\n");
97                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error setting auto protocol"<<endl;
98                 return false;
99         }
100         if (!sendElmCommand(obd,"ATE0"))
101         {
102                 //printf("Error sending echo\n");
103                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error turning off echo"<<endl;
104                 return false;
105         }
106         if (!sendElmCommand(obd,"ATH0"))
107         {
108                 //printf("Error sending headers off\n");
109                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error turning off headers"<<endl;
110                 return false;
111         }
112         if (!sendElmCommand(obd,"ATL0"))
113         {
114                 //printf("Error turning linefeeds off\n");
115                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Error turning off linefeeds"<<endl;
116                 return false;
117         }
118         obd->sendObdRequestString("010C1\r",6,&replyVector,500,5);
119
120         return true;
121 }
122
123 void threadLoop(gpointer data)
124 {
125         GAsyncQueue *privCommandQueue = g_async_queue_ref(((OBD2Source*)data)->commandQueue);
126         GAsyncQueue *privResponseQueue = g_async_queue_ref(((OBD2Source*)data)->responseQueue);
127         GAsyncQueue *privSingleShotQueue = g_async_queue_ref(((OBD2Source*)data)->singleShotQueue);
128         GAsyncQueue *privSubscriptionAddQueue = g_async_queue_ref(((OBD2Source*)data)->subscriptionAddQueue);
129         GAsyncQueue *privSubscriptionRemoveQueue = g_async_queue_ref(((OBD2Source*)data)->subscriptionRemoveQueue);
130         GAsyncQueue *privStatusQueue = g_async_queue_ref(((OBD2Source*)data)->statusQueue);
131         
132         obdLib *obd = new obdLib();
133         OBD2Source *source = (OBD2Source*)data;
134
135         obd->setCommsCallback([](const char* mssg, void* data) { DebugOut(6)<<mssg<<endl; },NULL);
136         obd->setDebugCallback([](const char* mssg, void* data, obdLib::DebugLevel debugLevel) { DebugOut(debugLevel)<<mssg<<endl; },NULL);
137         
138         std::list<ObdPid*> reqList;
139         std::list<ObdPid*> repeatReqList;
140         ObdPid::ByteArray replyVector;
141         std::string reply;
142         std::string port;
143         std::string baud;
144         bool connected=false;
145         int emptycount = 0;
146         int timeoutCount = 0;
147         while (source->m_threadLive)
148         {
149                 //gpointer query = g_async_queue_pop(privCommandQueue);
150                 
151                 
152                 gpointer query = g_async_queue_try_pop(privSingleShotQueue);
153                 if (query != nullptr)
154                 {
155                         //printf("Got request!\n");
156                         
157                         ObdPid *req = (ObdPid*)query;
158                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got single shot request: " << req->pid.substr(0,req->pid.length()-1) << ":" << req->property <<endl;
159                         repeatReqList.push_back(req);
160                 }
161                 query = g_async_queue_try_pop(privSubscriptionAddQueue);
162                 if (query != nullptr)
163                 {
164
165                         ObdPid *req = (ObdPid*)query;
166                         //DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got subscription request for "<<req->req<<endl;
167                         reqList.push_back(req);
168                 }
169                 query = g_async_queue_try_pop(privCommandQueue);
170                 if (query != nullptr)
171                 {
172                         //ObdPid *req = (ObdPid*)query;
173                         CommandRequest *req = (CommandRequest*)query;
174                         //commandMap[req->req] = req->arg;
175                         //printf("Command: %s\n",req->req.c_str());
176                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Command:" << req->req << endl;
177                         if (req->req == "connect" )
178                         {
179
180                                 if (source->m_isBluetooth)
181                                 {
182                                         BluetoothDevice bt;
183                                         std::string tempPort = bt.getDeviceForAddress(source->m_btDeviceAddress, source->m_btAdapterAddress);
184                                         if(tempPort != "")
185                                         {
186                                                 DebugOut(3)<<"Using bluetooth device \""<<source->m_btDeviceAddress<<"\" bound to: "<<tempPort<<endl;
187                                                 port = tempPort;
188                                         }
189                                 }
190                                 else
191                                 {
192                                         port = req->arglist[0];
193                                         baud = req->arglist[1];
194                                 }
195                                 connected = connect(obd,port,baud);
196
197                                 if(connected)
198                                 {
199                                         StatusMessage *statusreq = new StatusMessage();
200                                         statusreq->statusStr = "connected";
201                                         g_async_queue_push(privStatusQueue,statusreq);
202                                 }
203                                 else
204                                 {
205                                         StatusMessage *statusreq = new StatusMessage();
206                                         statusreq->statusStr = "disconnected";
207                                         g_async_queue_push(privStatusQueue,statusreq);
208                                 }
209                                 
210                         }
211                         else if (req->req == "connectifnot")
212                         {
213                                 if (!connected)
214                                 {
215                                         if (source->m_isBluetooth)
216                                         {
217                                                 BluetoothDevice bt;
218                                                 std::string tempPort = bt.getDeviceForAddress(source->m_btDeviceAddress, source->m_btAdapterAddress);
219                                                 if(tempPort != "")
220                                                 {
221                                                         DebugOut(3)<<"Using bluetooth device \""<<source->m_btDeviceAddress<<"\" bound to: "<<tempPort<<endl;
222                                                         port = tempPort;
223                                                 }
224                                                 else
225                                                 {
226                                                         DebugOut(DebugOut::Error)<<"Error creating bluetooth device"<<endl;
227                                                         continue;
228                                                 }
229                                         }
230
231                                         connected = connect(obd,port,baud);
232
233                                         if(connected)
234                                         {
235                                                 StatusMessage *statusreq = new StatusMessage();
236                                                 statusreq->statusStr = "connected";
237                                                 g_async_queue_push(privStatusQueue,statusreq);
238                                         }
239                                         else
240                                         {
241                                                 StatusMessage *statusreq = new StatusMessage();
242                                                 statusreq->statusStr = "disconnected";
243                                                 g_async_queue_push(privStatusQueue,statusreq);
244                                         }
245                                 }
246                         }
247                         else if (req->req == "setportandbaud")
248                         {
249                                 port = req->arglist[0];
250                                 baud = req->arglist[1];
251                         }
252                         else if (req->req == "disconnect")
253                         {
254                                 DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "Using queued disconnect" << (ulong)req << endl;
255                                 obd->closePort();
256                                 BluetoothDevice bt;
257                                 bt.disconnect(source->m_btDeviceAddress, source->m_btAdapterAddress);
258                                 connected = false;
259                                 StatusMessage *statusreq = new StatusMessage();
260                                 statusreq->statusStr = "disconnected";
261                                 g_async_queue_push(privStatusQueue,statusreq);
262                         }
263                         delete req;
264                 }
265                 query = g_async_queue_try_pop(privSubscriptionRemoveQueue);
266                 if (query != nullptr)
267                 {
268                         DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Got unsubscription request"<<endl;
269                         ObdPid *req = (ObdPid*)query;
270                         for (std::list<ObdPid*>::iterator i=reqList.begin();i!= reqList.end();i++)
271                         {
272                                 if ((*i)->property == req->property)
273                                 {
274                                         reqList.erase(i);
275                                         delete (*i);
276                                         i--;
277                                         if (reqList.size() == 0)
278                                         {
279                                                 break;
280                                         }
281                                 }
282                         }
283                         //reqList.push_back(req->req);
284                         delete req;
285                 }
286                 if (reqList.size() > 0 && !connected)
287                 {
288                         /*CommandRequest *req = new CommandRequest();
289                         req->req = "connect";
290                         req->arglist.push_back(port);
291                         req->arglist.push_back(baud);
292                         g_async_queue_push(privCommandQueue,req);
293                         continue;*/
294                 }
295                 else if (reqList.size() == 0 && connected)
296                 {
297                         emptycount++;
298                         if (emptycount < 1000)
299                         {
300                                 usleep(10000);
301                                 continue;
302                         }
303                         emptycount = 0;
304                         CommandRequest *req = new CommandRequest();
305                         req->req = "disconnect";
306                         g_async_queue_push(privCommandQueue,req);
307                         continue;
308                 }
309                 if (!connected)
310                 {
311                         usleep(10000);
312                         continue;
313                 }
314                 for (std::list<ObdPid*>::iterator i=reqList.begin();i!= reqList.end();i++)
315                 {
316                         repeatReqList.push_back(*i);
317                 }
318                 int badloop = 0;
319                 for (std::list<ObdPid*>::iterator i=repeatReqList.begin();i!= repeatReqList.end();i++)
320                 {
321                         DebugOut(10) << __SMALLFILE__ << ":" << __LINE__ << "Requesting pid: " << (*i)->pid.substr(0,(*i)->pid.length()-1) << (*i)->property << endl;
322                         if (source->m_blacklistPidCountMap.find((*i)->pid) != source->m_blacklistPidCountMap.end())
323                         {
324                                 //Don't erase the pid, just skip over it.
325                                 int count = (*source->m_blacklistPidCountMap.find((*i)->pid)).second;
326                                 if (count > 10)
327                                 {
328                                         continue;
329                                 }
330                         }
331                         badloop++;
332
333                         bool result = false;
334
335                         if(beginsWith((*i)->pid,"AT") || beginsWith((*i)->pid, "ST"))
336                         {
337                                 result = obd->sendObdRequestString((*i)->pid.c_str(),(*i)->pid.length(),&replyVector);
338                         }
339                         else result = obd->sendObdRequestString((*i)->pid.c_str(),(*i)->pid.length(),&replyVector,5,3);
340
341                         if (!result)
342                         {
343                                 //This only happens during a error with the com port. Close it and re-open it later.
344                                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "Unable to send request:" << (*i)->pid.substr(0,(*i)->pid.length()-1) << endl;
345                                 if (obd->lastError() == obdLib::NODATA)
346                                 {
347                                         DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "OBDLib::NODATA for pid" << (*i)->pid.substr(0,(*i)->pid.length()-1) << " expected property: " << (*i)->property << endl;
348                                         if (source->m_blacklistPidCountMap.find((*i)->pid) != source->m_blacklistPidCountMap.end())
349                                         {
350                                                 //pid value i not yet in the list.
351                                                 int count = (*source->m_blacklistPidCountMap.find((*i)->pid)).second;
352                                                 if (count > 10)
353                                                 {
354                                                         
355                                                 }
356                                                 source->m_blacklistPidCountMap.erase(source->m_blacklistPidCountMap.find((*i)->pid));
357                                                 source->m_blacklistPidCountMap.insert(pair<std::string,int>((*i)->pid,count));
358                                         }
359                                         else
360                                         {
361                                                 source->m_blacklistPidCountMap.insert(pair<std::string,int>((*i)->pid,1));
362                                         }
363                                         StatusMessage *statusreq = new StatusMessage();
364                                         statusreq->statusStr = "error:nodata";
365                                         statusreq->property = (*i)->property;
366                                         g_async_queue_push(privStatusQueue,statusreq);
367                                         continue;
368                                 }
369                                 else if (obd->lastError() == obdLib::TIMEOUT)
370                                 {
371                                         timeoutCount++;
372                                         if (timeoutCount < 2)
373                                         {
374                                                 DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "OBDLib::TIMEOUT for pid" << (*i)->pid << endl;
375                                                 StatusMessage *statusreq = new StatusMessage();
376                                                 statusreq->statusStr = "error:timeout";
377                                                 g_async_queue_push(privStatusQueue,statusreq);
378                                                 continue;
379                                         }
380                                 }
381                                 else
382                                 {
383                                         DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "OBD Other error:" << obd->lastError() << endl;
384                                 }
385                                 
386                                 CommandRequest *req = new CommandRequest();
387                                 DebugOut() << __SMALLFILE__ << ":" << __LINE__ << "Queuing up a disconnect" << (ulong)req << endl;
388                                 req->req = "disconnect";
389                                 g_async_queue_push(privCommandQueue,req);
390                                 i = repeatReqList.end();
391                                 i--;
392                                 continue;
393                         }
394                         if (source->m_blacklistPidCountMap.find((*i)->pid) != source->m_blacklistPidCountMap.end())
395                         {
396                                 //If we get the pid response, then we want to clear out the blacklist list.
397                                 source->m_blacklistPidCountMap.erase(source->m_blacklistPidCountMap.find((*i)->pid));
398                         }
399                         timeoutCount = 0;
400                         //ObdPid *pid = ObdPid::pidFromReply(replyVector);
401                         ObdPid *pid = obd2AmbInstance->createPidFromReply(replyVector);
402                         if (!pid)
403                         {
404                                 //Invalid reply
405                                 DebugOut() << "Invalid reply"<<endl;
406                                 continue;
407                         }
408                         else
409                         {
410                                 DebugOut(11) << __SMALLFILE__ <<":"<< __LINE__ << "Reply recieved and queued for:" << (*i)->pid.substr(0,(*i)->pid.length()-1) << endl;
411                                 std::string repstr;
412                                 for (int i=0;i<replyVector.size();i++)
413                                 {
414                                   if (replyVector[i] != 13)
415                                   {
416                                   repstr += (char)replyVector[i];
417                                   }
418                                         //DebugOut(11) << replyVector[i];
419                                 }
420                                 DebugOut(11) << "Reply:" << repstr << endl;
421                         }
422                         g_async_queue_push(privResponseQueue,pid);
423                 }
424                 if (badloop == 0)
425                 {
426                         //We had zero non-blacklisted events. Pause for a moment here to keep from burning CPU.
427                         //usleep(10000);
428                 }
429                 repeatReqList.clear();
430                 
431         }
432         if (connected)
433         {
434                 obd->closePort();
435         }
436 }
437 static int updateProperties( gpointer data)
438 {
439
440         OBD2Source* src = (OBD2Source*)data;
441         
442         while (gpointer retval = g_async_queue_try_pop(src->statusQueue))
443         {
444                 StatusMessage *reply = (StatusMessage*)retval;
445                 if (reply->statusStr == "disconnected")
446                 {
447                         OBD2Source::Obd2ConnectType val(Obd2Connected,false);
448                         src->updateProperty(Obd2Connected,&val);
449                 }
450                 else if (reply->statusStr == "connected")
451                 {
452                         OBD2Source::Obd2ConnectType val(Obd2Connected, true);
453                         src->updateProperty(Obd2Connected,&val);
454                 }
455                 else if (reply->statusStr == "error:nodata" || reply->statusStr == "error:timeout")
456                 {
457                         if (src->propertyReplyMap.find(reply->property) != src->propertyReplyMap.end())
458                         {
459                                 DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << reply->statusStr << " on property:" << reply->property << endl;
460                                 src->propertyReplyMap[reply->property]->success = false;
461                                 src->propertyReplyMap[reply->property]->error = AsyncPropertyReply::InvalidOperation;
462                                 src->propertyReplyMap[reply->property]->completed(src->propertyReplyMap[reply->property]);
463                                 src->propertyReplyMap.erase(reply->property);
464
465                                 /// Remove support for this pid:
466                                 PropertyList list = src->supported();
467                                 list.remove(reply->property);
468                                 src->setSupported(list);
469                         }
470                         else
471                         {
472                                 DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << reply->statusStr << " on unrequested property:" << reply->property << endl;
473                         }
474                 }
475                 delete reply;
476         }
477         while(gpointer retval = g_async_queue_try_pop(src->responseQueue))
478         {
479                 ObdPid *reply = (ObdPid*)retval;
480
481                 
482                 AbstractPropertyType* value = VehicleProperty::getPropertyTypeForPropertyNameValue(reply->property, reply->value);
483                 src->updateProperty(reply->property, value);
484                 delete value;
485         }
486
487         return true;
488 }
489
490 void OBD2Source::updateProperty(VehicleProperty::Property property,AbstractPropertyType* value)
491 {
492         if(property == Obd2Connected)
493                 obd2Connected.setValue(value->anyValue());
494         
495         if (propertyReplyMap.find(property) != propertyReplyMap.end())
496         {
497                 propertyReplyMap[property]->value = value;
498                 propertyReplyMap[property]->success = true;
499                 try {
500                         propertyReplyMap[property]->completed(propertyReplyMap[property]);
501                 }catch(...)
502                 {
503                         DebugOut(DebugOut::Error)<<"failed to call reply completed callback"<<endl;
504                 }
505
506                 propertyReplyMap.erase(property);
507         }
508         else
509         {
510                 if(oldValueMap.find(property) != oldValueMap.end())
511                 {
512                         AbstractPropertyType* old = oldValueMap[property];
513
514                         if((*old) == (*value))
515                         {
516                                 return;
517                         }
518
519                         delete old;
520                 }
521
522                 oldValueMap[property] = value->copy();
523
524                 m_re->updateProperty(value,uuid());
525         }
526 }
527
528 void OBD2Source::setSupported(PropertyList list)
529 {
530         m_supportedProperties = list;
531         m_re->updateSupported(list,PropertyList(),this);
532 }
533 /*void OBD2Source::propertySignal(VehicleProperty::Property property,boost::any value)
534 {
535 }
536 void OBD2Source::checkProperty()
537 {
538 }*/
539 void OBD2Source::setConfiguration(map<string, string> config)
540 {
541 //      //Config has been passed, let's start stuff up.
542         configuration = config;
543         
544         //Default values
545         std::string port = "/dev/ttyUSB0";
546         std::string baud = "115200";
547         std::string btadapter = "";
548         m_isBluetooth = false;
549         
550         //Try to load config
551         //printf("OBD2Source::setConfiguration\n");
552         for (map<string,string>::iterator i=configuration.begin();i!=configuration.end();i++)
553         {
554                 //printf("Incoming setting: %s:%s\n",(*i).first.c_str(),(*i).second.c_str());
555                 DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << "Incoming setting:" << (*i).first << ":" << (*i).second << endl;
556                 if ((*i).first == "device")
557                 {
558                         port = (*i).second;
559                 }
560                 else if ((*i).first == "baud")
561                 {
562                         if((*i).second != "")
563                                 baud = (*i).second;
564                 }
565
566                 else if ((*i).first == "bluetoothAdapter")
567                 {
568                         btadapter = (*i).second;
569                 }
570         }
571
572         if(port.find(":") != string::npos)
573         {
574                 m_btDeviceAddress = port;
575                 m_btAdapterAddress = btadapter;
576                 m_isBluetooth = true;
577                 ///TODO: bluetooth!!
578                 /*DebugOut()<<"bluetooth device?"<<endl;
579                 BluetoothDevice bt;
580
581                 std::string tempPort = bt.getDeviceForAddress(port, btadapter);
582                 if(tempPort != "")
583                 {
584                         DebugOut(3)<<"Using bluetooth device \""<<port<<"\" bound to: "<<tempPort<<endl;
585                         port = tempPort;
586                 }
587                 else
588                 {
589                         DebugOut(0)<<"Device Error"<<endl;
590                         ///Don't throw here.
591                         //throw std::runtime_error("Device Error");
592                 }*/
593         }
594
595         //connect(obd, port, baud);
596         CommandRequest *req = new CommandRequest();
597         req->req = "setportandbaud";
598         req->arglist.push_back(port);
599         req->arglist.push_back(baud);
600         g_async_queue_push(commandQueue,req);
601         
602         m_port = port;
603         m_baud = baud;
604         m_gThread = g_thread_new("mythread",(GThreadFunc)&threadLoop,this);
605         //g_idle_add(updateProperties, this);
606         g_timeout_add(5,updateProperties,this);
607 }
608
609 OBD2Source::OBD2Source(AbstractRoutingEngine *re, map<string, string> config)
610         : AbstractSource(re, config),obd2Connected(Obd2Connected,false)
611 {
612         bool success = VehicleProperty::registerProperty(Obd2Connected,[](){ return new Obd2ConnectType(Obd2Connected,false); });
613
614         if(!success)
615         {
616                 ///ERROR!
617         }
618
619         clientConnected = false;
620         m_re = re;  
621
622         m_threadLive = true;
623         Obd2Amb obd2amb;
624         obd = new obdLib();
625
626         for(auto itr = obd2amb.supportedPidsList.begin(); itr != obd2amb.supportedPidsList.end(); itr++)
627         {
628                 m_supportedProperties.push_back((*itr)->property);
629         }
630
631         m_supportedProperties.push_back(Obd2Connected);
632
633         re->setSupported(supported(), this);
634         /*if (openPort(std::string("/dev/pts/7"),115200))
635         {
636           printf("Error opening OBD2 port\n");
637         }*/
638         statusQueue = g_async_queue_new();
639         commandQueue = g_async_queue_new();
640         subscriptionAddQueue = g_async_queue_new();
641         subscriptionRemoveQueue = g_async_queue_new();
642         responseQueue = g_async_queue_new();
643         singleShotQueue = g_async_queue_new();
644
645         setConfiguration(config);
646 }
647 OBD2Source::~OBD2Source()
648 {
649         DebugOut() << "OBD2Source Destructor called!!!"<<endl;
650         m_threadLive = false;
651         g_thread_join(m_gThread);
652 }
653
654 PropertyList OBD2Source::supported()
655 {
656         return m_supportedProperties;
657 }
658
659 int OBD2Source::supportedOperations()
660 {
661         return Get | Set;
662 }
663
664 extern "C" AbstractSource * create(AbstractRoutingEngine* routingengine, map<string, string> config)
665 {
666         return new OBD2Source(routingengine, config);
667         
668 }
669 const string OBD2Source::uuid()
670 {
671         return "f77af740-f1f8-11e1-aff1-0800200c9a66";
672 }
673 void OBD2Source::subscribeToPropertyChanges(VehicleProperty::Property property)
674 {
675         if (property == VehicleProperty::VIN)
676         {
677                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "VIN subscription requested... but there's no point!"<<endl;
678         }
679         else if (property == VehicleProperty::WMI)
680         {
681                 DebugOut() << __SMALLFILE__ <<":"<< __LINE__ << "WMI subscription requested... but there's no point!"<<endl;
682         }
683         else
684         {
685                 if(!ListPlusPlus<VehicleProperty::Property>(&m_supportedProperties).contains(property))
686                 {
687                         DebugOut(0)<<"obd plugin does not support: "<<property<<endl;
688                         return;
689                 }
690
691
692                 ObdPid *pid = obd2AmbInstance->createPidforProperty(property);
693
694                 if(!pid)
695                 {
696                         return;
697                 }
698                 
699                 //If the pid is currently in the blacklist map, erase it. This allows for applications
700                 //to "un-blacklist" a pid by re-subscribing to it.
701                 if (m_blacklistPidCountMap.find(pid->pid) != m_blacklistPidCountMap.end())
702                 {
703                         m_blacklistPidCountMap.erase(m_blacklistPidCountMap.find(pid->pid));
704                 }
705                                         
706                                         
707                 g_async_queue_push(subscriptionAddQueue,pid);
708                 CommandRequest *req = new CommandRequest();
709                 req->req = "connectifnot";
710                 g_async_queue_push(commandQueue,req);
711         }
712 }
713
714
715 void OBD2Source::unsubscribeToPropertyChanges(VehicleProperty::Property property)
716 {
717         if(!ListPlusPlus<VehicleProperty::Property>(&m_supportedProperties).contains(property))
718         {
719                 DebugOut(0)<<"obd plugin does not support: "<<property<<endl;
720                 return;
721         }
722
723         ObdPid *pid = obd2AmbInstance->createPidforProperty(property);
724         g_async_queue_push(subscriptionRemoveQueue,pid);
725 }
726
727
728 void OBD2Source::getPropertyAsync(AsyncPropertyReply *reply)
729 {
730         DebugOut(5) << __SMALLFILE__ <<":"<< __LINE__ << "getPropertyAsync requested for " << reply->property << endl;
731
732         VehicleProperty::Property property = reply->property;
733
734
735         if(!ListPlusPlus<VehicleProperty::Property>(&m_supportedProperties).contains(property))
736         {
737                 DebugOut(0)<<"obd plugin does not support: "<<property<<endl;
738                 return;
739         }
740
741         if(reply->property == Obd2Connected)
742         {
743                 reply->success = true;
744                 reply->value = &obd2Connected;
745                 reply->completed(reply);
746                 return;
747         }
748
749         propertyReplyMap[reply->property] = reply;
750
751         ObdPid* requ = obd2AmbInstance->createPidforProperty(property);
752         g_async_queue_push(singleShotQueue,requ);
753         CommandRequest *req = new CommandRequest();
754         req->req = "connectifnot";
755         g_async_queue_push(commandQueue,req);
756 }
757
758 AsyncPropertyReply *OBD2Source::setProperty(AsyncSetPropertyRequest request )
759 {
760         AsyncPropertyReply* reply = new AsyncPropertyReply (request);
761
762
763
764         if(request.property == Obd2Connected)
765         {
766                 propertyReplyMap[reply->property] = reply;
767                 reply->success = true;
768
769                 if(request.value->value<bool>() == true)
770                 {
771                         CommandRequest *req = new CommandRequest();
772                         req->req = "connectifnot";
773                         g_async_queue_push(commandQueue,req);
774                 }
775                 else
776                 {
777                         CommandRequest *req = new CommandRequest();
778                         req->req = "disconnect";
779                         g_async_queue_push(commandQueue,req);
780                 }
781
782         }
783
784         else
785         {
786                 reply->success = false;
787                 try
788                 {
789                         reply->completed(reply);
790                 }
791                 catch (...)
792                 {
793
794                 }
795         }
796
797
798         return reply;
799 }