wli.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <stdint.h>
  6. #include <syslog.h>
  7. #include <stdarg.h>
  8. //#include <unistd.h>
  9. #include "../../status.h"
  10. #include "../../feeder.h"
  11. static void (* feederLog)(int priority, const char * fmt, ...);
  12. int setLog(void * func)
  13. {
  14. feederLog = func;
  15. return 0;
  16. }
  17. #define WLI_STX 0x02
  18. #define WLI_ETX 0x03
  19. #define WLI_PCLASS_APPLICATION 0x31
  20. #define WLI_PCLASS_PRESENTATION 0x32
  21. #define WLI_PCLASS_KEEPALIVE 0x34
  22. #define ESCAPE_HDR 0xDB
  23. #define ESCAPE_STX 0xD2
  24. #define ESCAPE_ETX 0xD3
  25. #define ESCAPE_DB 0xDD
  26. // Classes
  27. //#define APP_CLASS 0x31
  28. //#define PRESENTATION_CLASS 0x32
  29. // #define KEEP_ALIVE_CLASS 0x34
  30. //
  31. // // APP MSG Types
  32. // #define APP_GPS_MSG 0xC9
  33. // #define APP_NO_GPS_MSG 0xE4
  34. // #define APP_LOC_BOUND 0xCD
  35. // #define APP_IO_STATE 0xCB
  36. // #define APP_LOGIN 0xFE
  37. // #define APP_LOGOUT 0xFD
  38. // #define APP_LOW_BAT 0xFB
  39. // #define APP_EMERGENCY 0x0a
  40. // #define APP_IN_COVERAGE 0xF8
  41. // #define APP_ACK 0xFC
  42. // #define APP_IP_CHANGED 0x17
  43. //
  44. // GPS FIELD NUMBERS
  45. #define FLD_GPS_FORMAT 1
  46. #define FLD_GPS_LONG 2
  47. #define FLD_GPS_SHORT 5
  48. #define FLD_GPS_REASON 6
  49. #define FLD_GPS_STOP_LEN 7
  50. #define FLD_GPS_STOP_TIME 8
  51. #define FLD_GPS_DISTANCE 9
  52. #define FLD_GPS_START_STATE 10
  53. #define FLD_GPS_MSG_NUM 19
  54. #define FLD_GPS_ACC_ALRM_CNT 20
  55. #define FLD_GPS_A2D 22
  56. #define FLD_GPS_ENGINE_STATE 26
  57. #define FLD_GPS_NUM_SAT 27
  58. #define FLD_GPS_SV_SNR 28
  59. #define FLD_GPS_SAT_USED 29
  60. #define FLD_GPS_HDOP 30
  61. #define FLD_GPS_CELL_MCC 35
  62. #define FLD_GPS_CELL_MNC 36
  63. #define FLD_GPS_CELL_LAC 37
  64. #define FLD_GPS_CELL_ID 38
  65. #define FLD_GPS_GSM_RSSI 39
  66. // COMMON FIELD NUMBERS
  67. #define FLD_GLB_PWR 246
  68. #define FLD_GLB_SERIAL_NUM 247
  69. #define FLD_GLB_BAT_CONV 249
  70. #define FLD_GLB_INTERN_TEMP 250
  71. #define FLD_GLB_BAT_AT_STRT 251
  72. #define FLD_GLB_BAT_NOW 252
  73. #define FLD_GLB_TIME 255
  74. // Reserved Fields to be ignored
  75. #define FLD_GLB_RESERVED_248 248
  76. #define FLD_GLB_RESERVED_40 40
  77. typedef struct wli_packet_t
  78. {
  79. uint8_t stx;
  80. uint8_t packet_class;
  81. /* class specific data */
  82. uint8_t data[1];
  83. uint8_t etx;
  84. } __attribute__((packed)) wli_packet_t;
  85. uint16_t byteSwap16(uint16_t value)
  86. {
  87. uint16_t swapped;
  88. swapped = (((0x00FF) & (value >> 8)) |
  89. ((0xFF00) & (value << 8)));
  90. return swapped;
  91. }
  92. uint32_t byteSwap32(uint32_t value)
  93. {
  94. uint32_t swapped;
  95. swapped = (((0x000000FF) & (value >> 24)) |
  96. ((0x0000FF00) & (value >> 8)) |
  97. ((0x00FF0000) & (value << 8)) |
  98. ((0xFF000000) & (value << 24)));
  99. return swapped;
  100. }
  101. uint64_t byteSwap64(uint64_t value)
  102. {
  103. uint64_t swapped;
  104. swapped = (((0x00000000000000FFULL) & (value >> 56)) |
  105. ((0x000000000000FF00ULL) & (value >> 40)) |
  106. ((0x0000000000FF0000ULL) & (value >> 24)) |
  107. ((0x00000000FF000000ULL) & (value >> 8)) |
  108. ((0x000000FF00000000ULL) & (value << 8)) |
  109. ((0x0000FF0000000000ULL) & (value << 24)) |
  110. ((0x00FF000000000000ULL) & (value << 40)) |
  111. ((0xFF00000000000000ULL) & (value << 56)));
  112. return swapped;
  113. }
  114. void arraySwap4(uint8_t * array)
  115. {
  116. uint8_t temp;
  117. temp = array[0];
  118. array[0] = array[3];
  119. array[3] = temp;
  120. temp = array[1];
  121. array[1] = array[2];
  122. array[2] = temp;
  123. }
  124. //----------------------------------------------------------------------------------------------
  125. #define TYPE_START 0
  126. #define TYPE_POS 1
  127. #define TYPE_OBS 2
  128. typedef struct rec_t
  129. {
  130. struct rec_t * next;
  131. uint8_t type;
  132. time_t timestamp;
  133. } rec_t;
  134. typedef struct pos_t
  135. {
  136. struct rec_t * next;
  137. uint8_t type;
  138. time_t timestamp;
  139. float lat;
  140. float lon;
  141. } pos_t;
  142. typedef struct obs_t
  143. {
  144. struct rec_t * next;
  145. uint8_t type;
  146. time_t timestamp;
  147. uint64_t sensor_id;
  148. float val;
  149. } obs_t;
  150. int recAdd(struct rec_t * list, struct rec_t * rec)
  151. {
  152. if (list == NULL)
  153. return -1;
  154. while (list->next != NULL)
  155. list = list->next;
  156. list->next = rec;
  157. return 0;
  158. }
  159. struct rec_t * recAlloc(int type)
  160. {
  161. struct rec_t * rec;
  162. switch (type)
  163. {
  164. case TYPE_POS:
  165. rec = malloc(sizeof(struct pos_t));
  166. break;
  167. case TYPE_OBS:
  168. rec = malloc(sizeof(struct obs_t));
  169. break;
  170. default:
  171. return NULL;
  172. break;
  173. }
  174. if (rec == NULL)
  175. return NULL;
  176. rec->type = type;
  177. rec->next = NULL;
  178. return rec;
  179. }
  180. void recCheckTimestamp(struct rec_t * rec, time_t timestamp)
  181. {
  182. while (rec != NULL)
  183. {
  184. if (rec->timestamp == 0)
  185. rec->timestamp = timestamp;
  186. rec = rec->next;
  187. }
  188. }
  189. int wliPwr(char * b, struct rec_t * list)
  190. {
  191. char *s;
  192. int i;
  193. struct obs_t * obs;
  194. i = 0;
  195. while (s = strchr(b, ','), s != NULL)//todo: ignoruje posledni parametr
  196. {
  197. *s = '\0';
  198. if (i == 3) //interal voltage
  199. {
  200. if (obs = (struct obs_t *)recAlloc(TYPE_OBS), obs == NULL)
  201. return -1;
  202. obs->timestamp = 0; //ted jeste nevim, musime pockat na doparseni celeho paketu a vyplnit az pri odevzdani dat
  203. obs->sensor_id = 360190000;
  204. obs->val = ((float)atoi(b)) / 100.0;
  205. recAdd(list, (struct rec_t *)obs);
  206. }
  207. b = s + 1;
  208. i++;
  209. }
  210. return 0;
  211. }
  212. int wliTemp(char * b, struct rec_t * list)
  213. {
  214. struct obs_t * obs;
  215. if (obs = (struct obs_t *)recAlloc(TYPE_OBS), obs == NULL)
  216. return -1;
  217. obs->timestamp = 0; //ted jeste nevim, musime pockat na doparseni celeho paketu a vyplnit az pri odevzdani dat
  218. obs->sensor_id = 340290000;
  219. obs->val = (0.98 * ((float)atoi(b))) - 60.0;
  220. recAdd(list, (struct rec_t *)obs);
  221. return 0;
  222. }
  223. int wliGpsShort(uint8_t * binVal, struct rec_t * list)
  224. {
  225. int minutsInDay, minutes, hours, dayOfMonth, year, month;
  226. struct tm gps_tm;
  227. struct pos_t * pos;
  228. struct obs_t * obs;
  229. float speed;
  230. float course;
  231. if (pos = (struct pos_t *)recAlloc(TYPE_POS), pos == NULL)
  232. return -1;
  233. pos->type = TYPE_POS;
  234. pos->next = NULL;
  235. pos->lat = ((float)((binVal[0]<<24) + (binVal[1]<<16) + (binVal[2]<<8) + binVal[3]))/600000;
  236. pos->lon = ((float)((binVal[4]<<24) + (binVal[5]<<16) + (binVal[6]<<8) + binVal[7]))/600000;
  237. // fprintf(stdout, "Latitude(deg):%.4f, Longitude(deg):%.4f", pos->lat, pos->lon);
  238. // Speed over Ground, the value is 0.1 knots, so divide by 10 to get it by knots
  239. // To convert to MPH: divide by 1.151
  240. // To convert to KPH: divide by 1.852 - yes, converted
  241. speed = (((binVal[8]<<8) + binVal[9])/10) / 1.852;
  242. // fprintf(stdout, ", Speed (km/h): %.2f", pos->speed);
  243. // Get date & time of GPS message
  244. minutsInDay = ((binVal[10] & 0x7)<<8) + binVal[11];
  245. minutes = minutsInDay%60;
  246. hours = minutsInDay/60;
  247. dayOfMonth = ((binVal[10] & 0xF8)>>3);
  248. month = (binVal[12] & 0x0F);
  249. year = 2000 + ((binVal[12] & 0xF0)>>4);
  250. // ***** Year bug workaround (Alex: May 2013 ) ********
  251. // In short high precision extended format (4) year is sent using 4 bits (0...15).
  252. // We suppose that the century is 20 always
  253. // As a result in 2016,2032 etc the Year sending value will be 0 + 2000 = 2000
  254. // The workaround is based on the following:
  255. // when the WLI unit is running and communcates with host,the UTC year received from GPS may be:
  256. // same as host computer year;
  257. // one year after then the computer UTC year ( e.g., due to computer clock delay at Dec 31 - Jan 01)
  258. // one year before then the computer UTC year ( e.g., due to GPS sending delay)
  259. // The workaround algorithm implements the assertion that GPS UTC time can not be more then 14 years before
  260. // current UTC time as set on the computer
  261. // Current terminal time is sent as time_t value. This parameter value is the number of seconds
  262. // elapsed since midnight (00:00:00), January 1, 1970, coordinated universal time, according to the
  263. // system clock.
  264. time_t ltime;
  265. time(&ltime);
  266. struct tm gmt;
  267. // Breakdown of the time is done using gmtime_r and NOT gmtime, as gmtime_r is NOT thread safe.
  268. gmtime_r(&ltime, &gmt);
  269. // Calculate current year (full value, e.g., 2013). tm_year field of struct tm is a year since 1900
  270. short shCurrentYear = gmt.tm_year + 1900;
  271. int DeltaYear = (int)(shCurrentYear - year);
  272. while (DeltaYear > 14)
  273. {
  274. year += 16;
  275. DeltaYear -= 16;
  276. }
  277. // ***** Year bug workaround end (Alex: May 2013 ) ********
  278. gps_tm.tm_sec = binVal[13];
  279. gps_tm.tm_min = minutes;
  280. gps_tm.tm_hour = hours;
  281. gps_tm.tm_mday = dayOfMonth;
  282. gps_tm.tm_mon = month - 1;
  283. gps_tm.tm_year = year - 1900;
  284. gps_tm.tm_isdst = 0;
  285. pos->timestamp = timegm(&gps_tm);
  286. // fprintf(stdout, ", Time: %02d/%02d/%04d %2d:%2d:%2d", month, dayOfMonth, year, hours, minutes, binVal[13]);
  287. // Course is tenth of degrees, so divided by 10 to get it in degrees
  288. course = ((float)(binVal[14]<<8) + binVal[15])/10;
  289. //fprintf(stdout, ", Course (deg): %.2f\n", pos->course);
  290. feederLog(LOG_DEBUG, "wli:, Latitude(deg):%.4f, Longitude(deg):%.4f, Speed (km/h): %.2f, Course (deg): %.2f, Timestamp (sec from 1.1.1970): %ld\n", pos->lat, pos->lon, speed, course, pos->timestamp);
  291. recAdd(list, (struct rec_t *)pos);
  292. if (obs = (struct obs_t *)recAlloc(TYPE_OBS), obs == NULL)
  293. return -1;
  294. obs->timestamp = pos->timestamp;
  295. obs->sensor_id = 440090000;
  296. obs->val = speed;
  297. recAdd(list, (struct rec_t *)obs);
  298. if (obs = (struct obs_t *)recAlloc(TYPE_OBS), obs == NULL)
  299. return -1;
  300. obs->timestamp = pos->timestamp;
  301. obs->sensor_id = 710030000;
  302. obs->val = course;
  303. recAdd(list, (struct rec_t *)obs);
  304. return 0;
  305. }
  306. void logHex(char * buffer, unsigned char * data, unsigned int length)
  307. {
  308. unsigned int i;
  309. buffer[0] = 0;
  310. for (i = 0; i < length; i++)
  311. {
  312. sprintf(buffer + strlen(buffer), "%02X ", data[i]);
  313. }
  314. }
  315. typedef struct wli_application_header_t
  316. {
  317. uint16_t sequence;
  318. uint16_t length;
  319. uint16_t checksum;
  320. } __attribute__((packed)) wli_application_header_t;
  321. unsigned int
  322. wliApplication(struct wli_application_header_t * p)
  323. {
  324. feederLog(LOG_DEBUG, "wli: Application message\n");
  325. feederLog(LOG_DEBUG, "wli: message sequence %d\n", byteSwap16(p->sequence));
  326. feederLog(LOG_DEBUG, "wli: app message len %d\n", byteSwap16(p->length));
  327. return 0;
  328. }
  329. unsigned int
  330. wliPresentation(char * p)
  331. {
  332. (void)p;
  333. feederLog(LOG_DEBUG, "wli: Presentation message\n");
  334. return 0;
  335. }
  336. enum { STATE_OUT = 0, STATE_PACKET_CLASS, STATE_APPLICATION, STATE_PRESENTATION, STATE_KEEPALIVE, STATE_APP_LENGTH, STATE_APP_CHECKSUM, STATE_MESS_TYPE, STATE_FIELD_NO, STATE_FIELD_VAL, STATE_FIELD_BIN, STATE_FIELD_BIN_LEN, STATE_FIELD_TEXT } wli_state;
  337. #define STATE_BUFFER_SIZE 64
  338. int wliStateMachine(uint8_t c, struct rec_t * list, unsigned long long int *id, time_t * timestamp)
  339. {
  340. static unsigned int state = STATE_OUT;
  341. static uint8_t b[STATE_BUFFER_SIZE];
  342. static uint8_t bl = 0;
  343. static uint8_t esc = 0;
  344. static uint8_t bin_len = 0;
  345. static uint8_t field_no = 0;
  346. if (c == WLI_ETX)
  347. {
  348. feederLog(LOG_DEBUG, "wli: end of message\n");
  349. state = STATE_OUT;
  350. bl = 0;
  351. return 0;
  352. }
  353. if (esc)
  354. {
  355. if (c == 0xDD)
  356. c = 0xDB;
  357. else
  358. c -= 0xD0;
  359. esc = 0;
  360. }
  361. else if (c == 0xDB)
  362. {
  363. esc = 1;
  364. return 0;
  365. }
  366. b[bl++] = c;
  367. if (bl == STATE_BUFFER_SIZE)
  368. bl = 0;
  369. // feederLog(LOG_DEBUG, "wli: byte in %d, state %d \n", c, state);
  370. switch (state)
  371. {
  372. case STATE_OUT:
  373. if (c == WLI_STX)
  374. state = STATE_PACKET_CLASS;
  375. break;
  376. case STATE_PACKET_CLASS:
  377. switch (c)
  378. {
  379. case WLI_PCLASS_APPLICATION:
  380. state = STATE_APPLICATION;
  381. bl = 0;
  382. break;
  383. case WLI_PCLASS_PRESENTATION:
  384. state = STATE_PRESENTATION;
  385. bl = 0;
  386. break;
  387. case WLI_PCLASS_KEEPALIVE:
  388. state = STATE_KEEPALIVE;
  389. break;
  390. default:
  391. feederLog(LOG_ERR, "wli: bad packet class\n");
  392. return -1;
  393. }
  394. break;
  395. case STATE_APPLICATION:
  396. if (bl == sizeof(struct wli_application_header_t))
  397. {
  398. wliApplication((struct wli_application_header_t *)b);
  399. bl = 0;
  400. state = STATE_MESS_TYPE;
  401. }
  402. break;
  403. case STATE_MESS_TYPE:
  404. if (bl == 2)
  405. {
  406. feederLog(LOG_DEBUG, "wli: message type %d\n", b[0]);
  407. bl = 0;
  408. state = STATE_FIELD_NO;
  409. }
  410. break;
  411. case STATE_FIELD_NO:
  412. if (bl == 2)
  413. {
  414. field_no = b[0];
  415. feederLog(LOG_DEBUG, "wli: field number %d\n", field_no);
  416. bl = 0;
  417. state = STATE_FIELD_VAL;
  418. }
  419. break;
  420. case STATE_FIELD_VAL:
  421. if (bl == 1)
  422. {
  423. if (c == 0xFF)
  424. {
  425. bl = 0;
  426. state = STATE_FIELD_BIN_LEN;
  427. }
  428. else
  429. {
  430. state = STATE_FIELD_TEXT;
  431. }
  432. }
  433. break;
  434. case STATE_FIELD_TEXT:
  435. if (c == 0)
  436. {
  437. switch (field_no)
  438. {
  439. case FLD_GLB_SERIAL_NUM:
  440. * id = atol((char *)b);
  441. break;
  442. case FLD_GLB_PWR:
  443. wliPwr((char *)b, list);
  444. break;
  445. case FLD_GLB_TIME:
  446. *timestamp = (time_t)atol((char *)b);
  447. recCheckTimestamp(list, *timestamp);
  448. break;
  449. case FLD_GLB_INTERN_TEMP:
  450. wliTemp((char *)b, list);
  451. break;
  452. }
  453. feederLog(LOG_DEBUG, "wli: field text val: \"%s\"\n", b);
  454. bl = 0;
  455. state = STATE_FIELD_NO;
  456. }
  457. break;
  458. case STATE_FIELD_BIN_LEN:
  459. if (bl == 2)
  460. {
  461. bin_len = byteSwap16(*((uint16_t *)b));
  462. bl = 0;
  463. state = STATE_FIELD_BIN;
  464. }
  465. break;
  466. case STATE_FIELD_BIN:
  467. if (bl == bin_len + 1)
  468. {
  469. if (field_no == FLD_GPS_SHORT)
  470. {
  471. wliGpsShort(b, list);
  472. }
  473. feederLog(LOG_DEBUG, "wli: field bin len: %d\n", bin_len);
  474. bl = 0;
  475. state = STATE_FIELD_NO;
  476. }
  477. break;
  478. }
  479. return 0;
  480. }
  481. static struct rec_t list;
  482. int init(void * param)
  483. {
  484. (void)param;
  485. list.type = TYPE_START;
  486. list.next = NULL;
  487. return 0;
  488. }
  489. unsigned int
  490. process(void *lib_data, int socket, unsigned char *data,
  491. unsigned int length, unsigned long long int *id, time_t * tm,
  492. double *result_array, uint64_t * sensors, unsigned int *type)
  493. {
  494. unsigned int ret = 0;
  495. unsigned int l;
  496. char buffer[1024];
  497. // struct wli_packet_t * p;
  498. unsigned int i;
  499. struct rec_t * rec, * rec_f;
  500. static time_t timestamp;
  501. (void)lib_data;
  502. (void)socket;
  503. if (data != NULL)
  504. {
  505. feederLog(LOG_DEBUG, "wli: Incoming data: len %d: \n", length);
  506. l = length;
  507. while (l > 0)
  508. {
  509. logHex(buffer, data + length - l, (l > 16) ? 16:l);
  510. feederLog(LOG_DEBUG, "%s\n", buffer);
  511. l -= (l > 16) ? 16:l;
  512. }
  513. for (i = 0; i < length; i++)
  514. {
  515. if (wliStateMachine(data[i], &list, id, &timestamp) < 0)
  516. return 0;
  517. }
  518. }
  519. rec = &list;
  520. if (rec->next != NULL)
  521. {
  522. feederLog(LOG_DEBUG, "wli: new record type %d\n", rec->next->type);
  523. if (rec->next->type == TYPE_POS)
  524. {
  525. struct pos_t * pos;
  526. pos = (struct pos_t *)rec->next;
  527. result_array[0] = (float)pos->lat;
  528. result_array[1] = (float)pos->lon;
  529. sensors[0] = sensors[1] = 0x10;
  530. *type = VALUES_TYPE_POS;
  531. ret = 2;
  532. // *id = atol(aunit->imei);
  533. *tm = pos->timestamp;
  534. }
  535. if (rec->next->type == TYPE_OBS)
  536. {
  537. struct obs_t * obs;
  538. obs = (struct obs_t *)rec->next;
  539. result_array[0] = (float)obs->val;
  540. sensors[0] = obs->sensor_id;
  541. *type = VALUES_TYPE_OBS;
  542. ret = 1;
  543. // *id = atol(aunit->imei);
  544. feederLog(LOG_DEBUG, "wli: timestmap %ld, %ld\n", timestamp, obs->timestamp);
  545. if (obs->timestamp == 0)
  546. *tm = timestamp;
  547. else
  548. *tm = obs->timestamp;
  549. }
  550. rec_f = rec->next;
  551. rec->next = rec->next->next;
  552. free(rec_f);
  553. }
  554. return ret;
  555. }
  556. int reply(void *lib_data, int socket, unsigned char *data)
  557. {
  558. unsigned int temp_reply_len = 0;
  559. (void)lib_data;
  560. (void)socket;
  561. (void)data;
  562. feederLog(LOG_DEBUG, "wli: replying\n");
  563. return temp_reply_len;
  564. }
  565. int open(void *lib_data, int socket)
  566. {
  567. (void)lib_data;
  568. (void)socket;
  569. feederLog(LOG_DEBUG, "wli: socket %d opened\n", socket);
  570. return 0;
  571. }
  572. int close(void *lib_data, int socket)
  573. {
  574. (void)lib_data;
  575. (void)socket;
  576. feederLog(LOG_DEBUG, "wli: socket %d closed\n", socket);
  577. return 0;
  578. }