automotive-message-broker  0.14.803
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
obdpid.h
1 #ifndef _OBDPID_H__H_H_
2 #define _OBDPID_H__H_H_
3 
4 #include <vector>
5 #include <string>
6 #include <vehicleproperty.h>
7 #include "obdlib.h"
8 #include <time.h>
9 
10 class ObdPid
11 {
12 public:
13  typedef std::vector<unsigned char> ByteArray;
14 
15  ObdPid(VehicleProperty::Property prop, std::string p, int i)
16  :property(prop), pid(p), id(i), type(0x41)
17  {
18  isValidVal = false;
19  }
20  static ByteArray cleanup(ByteArray replyVector)
21  {
22  ByteArray tmp;
23 
24  for (int i=0;i<replyVector.size();i++)
25  {
26  if ((replyVector[i] != 0x20) && (replyVector[i] != '\r') && (replyVector[i] != '\n'))
27  {
28  tmp.push_back(replyVector[i]);
29  }
30  }
31  return tmp;
32  }
33  static ByteArray compress(ByteArray replyVector)
34  {
35  ByteArray tmp;
36  for (int i=0;i<replyVector.size()-1;i++)
37  {
38  tmp.push_back(obdLib::byteArrayToByte(replyVector[i], replyVector[i+1]));
39  i++;
40  }
41  return tmp;
42  }
43  virtual ObdPid* create() = 0;
44 
45  bool tryParse(ByteArray replyVector)
46  {
47  if (!isValid(replyVector))
48  {
49  return false;
50  }
51  parse(replyVector);
52  return true;
53  }
54  virtual void parse(const ByteArray &replyVector) = 0;
55  virtual bool isValid(const ByteArray &replyVector) = 0;
56  virtual bool needsCompress() { return true; }
57 
58  VehicleProperty::Property property;
59  std::string pid;
60  int id;
61  int type;
62  std::string value;
63  bool isValidVal;
64 };
65 
66 template <class T>
67 class CopyMe: public ObdPid
68 {
69 public:
70 
71  CopyMe(VehicleProperty::Property prop, std::string p, int i)
72  :ObdPid(prop, p, i)
73  {
74  }
75 
76  ObdPid* create()
77  {
78  T* t = new T();
79  t->value = value;
80  t->isValidVal = isValidVal;
81  return t;
82  }
83 };
84 
85 
86 class VehicleSpeedPid: public CopyMe<VehicleSpeedPid>
87 {
88 public:
89 
91  :CopyMe(VehicleProperty::VehicleSpeed, "010D1\r", 0x0D)
92  {
93 
94  }
95  bool isValid(const ByteArray &replyVector)
96  {
97  isValidVal = true;
98  if (replyVector[1] != id)
99  {
100  return isValidVal = false;
101  }
102 
103  return isValidVal;
104  }
105  void parse(const ByteArray &replyVector)
106  {
107  if (!isValidVal)
108  {
109  //TODO: Determine if we should throw an exception here, rather than just returning without a value?
110  return;
111  }
112 
113  int mph = replyVector[2];
114  value = boost::lexical_cast<std::string>(mph);
115  }
116 };
117 
118 class EngineSpeedPid: public CopyMe<EngineSpeedPid>
119 {
120 public:
121 
123  :CopyMe(VehicleProperty::EngineSpeed,"010C1\r",0x0C)
124  {
125 
126  }
127  bool isValid(const ByteArray &replyVector)
128  {
129  if (replyVector[1] != id)
130  {
131  isValidVal = false;
132  return false;
133  }
134  isValidVal = true;
135  return true;
136  }
137  void parse(const ByteArray &replyVector)
138  {
139  if (!isValidVal)
140  {
141  //TODO: Determine if we should throw an exception here, rather than just returning without a value?
142  return;
143  }
144  double rpm = ((replyVector[2] << 8) + replyVector[3]) / 4.0;
145  value = boost::lexical_cast<std::string>(rpm);
146  }
147 };
148 
149 class EngineCoolantPid: public CopyMe<EngineCoolantPid>
150 {
151 public:
152 
154  :CopyMe(VehicleProperty::EngineCoolantTemperature,"01051\r",0x05)
155  {
156 
157  }
158  bool isValid(const ByteArray &replyVector)
159  {
160  if (replyVector[1] != id)
161  {
162  isValidVal = false;
163  return false;
164  }
165  isValidVal = true;
166  return true;
167  }
168  void parse(const ByteArray &replyVector)
169  {
170  if (!isValidVal)
171  {
172  //TODO: Determine if we should throw an exception here, rather than just returning without a value?
173  return;
174  }
175  int temp = replyVector[2] - 40;
176  value = boost::lexical_cast<std::string>(temp);
177  }
178 };
179 
180 class MassAirFlowPid: public CopyMe<MassAirFlowPid>
181 {
182 public:
183 
185  :CopyMe(VehicleProperty::MassAirFlow,"01101\r", 0x10)
186  {
187 
188  }
189  bool isValid(const ByteArray &replyVector)
190  {
191  if (replyVector[1] != id)
192  {
193  isValidVal = false;
194  return false;
195  }
196  isValidVal = true;
197  return true;
198  }
199  void parse(const ByteArray &replyVector)
200  {
201  if (!isValidVal)
202  {
203  //TODO: Determine if we should throw an exception here, rather than just returning without a value?
204  return;
205  }
206 
207  maf = ((replyVector[2] << 8) + replyVector[3]) / 100.0;
208  value = boost::lexical_cast<std::string>(maf);
209  }
210 
211 protected:
212  double maf;
213 };
214 
215 
217 {
218 public:
220 
221  {
222 
223  }
224  bool isValid(const ByteArray &replyVector)
225  {
226  return isValidVal = MassAirFlowPid::isValid(replyVector);
227  }
228  void parse(const ByteArray & replyVector)
229  {
230  if (!isValidVal)
231  {
232  //TODO: Determine if we should throw an exception here, rather than just returning without a value?
233  return;
234  }
235 
236  timespec t;
237  clock_gettime(CLOCK_REALTIME, &t);
238 
239  double currentTime = t.tv_sec + t.tv_nsec / 1000000;
240 
241  double diffTime = currentTime - oldTime;
242  oldTime = currentTime;
243 
244  double consumption = 1 / (14.75 * 6.26) * maf * diffTime/60;
245 
246  value = boost::lexical_cast<std::string>(consumption);
247  }
248 
249 private:
250 
251  static double oldTime;
252 };
253 
254 
255 class VinPid: public CopyMe<VinPid>
256 {
257 public:
258 
259  VinPid()
260  :CopyMe(VehicleProperty::VIN,"0902\r",0x02)
261  {
262  type = 0x49;
263  }
264  bool isValid(const ByteArray & replyVector)
265  {
266  isValidVal = true;
267 
268  if (replyVector[0] != 0x49 || replyVector[1] != 0x02)
269  {
270  isValidVal = false;
271 
272  }
273  return isValidVal;
274  }
275  void parse(const ByteArray & replyVector)
276  {
277  if (!isValidVal)
278  {
279  //TODO: Determine if we should throw an exception here, rather than just returning without a value?
280  return;
281  }
282  std::string vinstring;
283  for (int j=0;j<replyVector.size();j++)
284  {
285  if(replyVector[j] == 0x49 && replyVector[j+1] == 0x02)
286  {
287  //We're at a reply header
288  j+=3;
289  }
290  if (replyVector[j] != 0x00)
291  {
292  vinstring += (char)replyVector[j];
293  //printf("VIN: %i %c\n",replyVector[j],replyVector[j]);
294  }
295  }
296 
297  value = vinstring;
298  }
299 };
300 
301 class WmiPid: public VinPid
302 {
303 public:
304 
305  WmiPid()
306  :VinPid()
307  {
308  property = VehicleProperty::WMI;
309  }
310  bool isValid(const ByteArray & replyVector)
311  {
312  return isValidVal = VinPid::isValid(replyVector);
313  }
314  void parse(const ByteArray &replyVector)
315  {
316  if (!isValidVal)
317  {
318  //TODO: Determine if we should throw an exception here, rather than just returning without a value?
319  return;
320  }
321  VinPid::parse(replyVector);
322  value = value.substr(0,3);
323  }
324 };
325 
326 class AirIntakeTemperaturePid: public CopyMe<AirIntakeTemperaturePid>
327 {
328 public:
330  :CopyMe(VehicleProperty::AirIntakeTemperature,"010F1\r",0x0F)
331  {
332 
333  }
334  bool isValid(const ByteArray & replyVector)
335  {
336  if (replyVector[1] != id)
337  {
338  isValidVal = false;
339  return false;
340  }
341  isValidVal = true;
342  return true;
343  }
344  void parse(const ByteArray & replyVector)
345  {
346  if (!isValidVal)
347  {
348  //TODO: Determine if we should throw an exception here, rather than just returning without a value?
349  return;
350  }
351  int temp = replyVector[2] - 40;
352  value = boost::lexical_cast<std::string>(temp);
353  }
354 };
355 
356 class EngineLoadPid: public CopyMe<EngineCoolantPid>
357 {
358 public:
359  EngineLoadPid()
360  :CopyMe(VehicleProperty::EngineLoad,"01041\r",0x04)
361  {
362 
363  }
364  bool isValid(const ByteArray & replyVector)
365  {
366  if (replyVector[1] != id)
367  {
368  isValidVal = false;
369  return false;
370  }
371  isValidVal = true;
372  return true;
373  }
374  void parse(const ByteArray &replyVector)
375  {
376  if (!isValidVal)
377  {
378  //TODO: Determine if we should throw an exception here, rather than just returning without a value?
379  return;
380  }
381  int load = replyVector[2]*100.0/255.0;
382  value = boost::lexical_cast<std::string>(load);
383  }
384 };
385 
386 class ThrottlePositionPid: public CopyMe<ThrottlePositionPid>
387 {
388 public:
390  :CopyMe(VehicleProperty::ThrottlePosition,"01111\r",0x11)
391  {
392 
393  }
394  bool isValid(const ByteArray & replyVector)
395  {
396  if (replyVector[1] != id)
397  {
398  isValidVal = false;
399  return false;
400  }
401  isValidVal = true;
402  return true;
403  }
404  void parse(const ByteArray & replyVector)
405  {
406  if (!isValidVal)
407  {
408  //TODO: Determine if we should throw an exception here, rather than just returning without a value?
409  return;
410  }
411  int temp = replyVector[2]*100.0/255.0;
412  value = boost::lexical_cast<std::string>(temp);
413  }
414 };
415 
416 class BatteryVoltagePid: public CopyMe<BatteryVoltagePid>
417 {
418 public:
421  {
422 
423  }
424 
425  bool needsCompress() { return false; }
426 
427  bool isValid(const ByteArray & replyVector)
428  {
429  if(replyVector[replyVector.size() - 1] == 'V')
430  {
431  return isValidVal = true;
432  }
433  return false;
434  }
435 
436  void parse(const ByteArray & replyVector)
437  {
438  value = "";
439  for(int i=0; i<replyVector.size() - 1; i++)
440  {
441  value += replyVector[i];
442  }
443  }
444 
445 };
446 
447 #endif