#include #include #include #include #include #include #include #include "../../status.h" #include "../../feeder.h" static unsigned char * int_buffer; static unsigned int int_buffer_pos = 0, int_buffer_pos_wr = 0; static int imei_flag = 0; char imei_str[16]; //todo: tohle nejak predavat unsigned char reply_buffer[32]; unsigned int reply_len; static double values_out[6]; static uint32_t values_sensor[6]; static time_t values_time; static uint8_t values_type; void (* feederLog)(int priority, const char * fmt, ...); int setLog(void * func) { feederLog = func; return 0; } double conv_latlon(char * str) { double res; char min[3], dg[4], * point; point = strchr(str, '.'); memcpy(dg, str, point - str - 2); dg[point - str - 2] = 0; memcpy(min, point - 2, 2); min[2] = 0; // printf("str %s: dg %s, min %s, tis %s \n", str, dg, min, point + 1); // printf("%p, %p, %d\n", str, point, point - str - 2); res = atof(dg); res += (atof(min) + atof(point + 1) / 100000) / 60.0; return res; } typedef struct avl_header_t { uint16_t dummy __attribute__ ((packed)); char imei[15]; } avl_header_t; uint16_t byteSwap16(uint16_t value) { uint16_t swapped; swapped = (((0x00FF) & (value >> 8)) | ((0xFF00) & (value << 8))); return swapped; } uint32_t byteSwap32(uint32_t value) { uint32_t swapped; swapped = (((0x000000FF) & (value >> 24)) | ((0x0000FF00) & (value >> 8)) | ((0x00FF0000) & (value << 8)) | ((0xFF000000) & (value << 24))); return swapped; } uint64_t byteSwap64(uint64_t value) { uint64_t swapped; swapped = (((0x00000000000000FFULL) & (value >> 56)) | ((0x000000000000FF00ULL) & (value >> 40)) | ((0x0000000000FF0000ULL) & (value >> 24)) | ((0x00000000FF000000ULL) & (value >> 8)) | ((0x000000FF00000000ULL) & (value << 8)) | ((0x0000FF0000000000ULL) & (value << 24)) | ((0x00FF000000000000ULL) & (value << 40)) | ((0xFF00000000000000ULL) & (value << 56))); return swapped; } void arraySwap4(uint8_t * array) { uint8_t temp; temp = array[0]; array[0] = array[3]; array[3] = temp; temp = array[1]; array[1] = array[2]; array[2] = temp; } enum states {STATE_IDLE = 0, STATE_DATA_LENGTH, STATE_CODEC_ID, STATE_NO_OF_REC, STATE_PR_TS, STATE_G_MASK, STATE_MASK, STATE_LATLON, STATE_ALT, STATE_ANGLE, STATE_SPEED, STATE_SATTS, STATE_CELL, STATE_QUA, STATE_OP, STATE_IO1_Q, STATE_IO1_ID, STATE_IO1_VAL, STATE_IO2_Q, STATE_IO2_ID, STATE_IO2_VAL, STATE_IO4_Q, STATE_IO4_ID, STATE_IO4_VAL, STATE_NO_OF_REC_END, STATE_CRC }; unsigned char counts[] = { 4, 4, 1, 1, 4, 1, 1, 8, 2, 1, 1, 1, 4, 1, 4, 1, 1, 1, 1, 1, 2, 1, 1, 4, 1, 4 }; #define MASK_LATLON(x) (x & 0x01) #define MASK_ALT(x) ((x >> 1) & 0x01) #define MASK_ANGLE(x) ((x >> 2) & 0x01) #define MASK_SPEED(x) ((x >> 3) & 0x01) #define MASK_SATS(x) ((x >> 4) & 0x01) #define MASK_CELL(x) ((x >> 5) & 0x01) #define MASK_QUA(x) ((x >> 6) & 0x01) #define MASK_OP(x) ((x >> 7) & 0x01) #define MASK_GEN(x, y) ((x >> y) & 0x01) #define MASK_GPS(x) (MASK_GEN(x, 0)) #define MASK_IO1(x) (MASK_GEN(x, 1)) #define MASK_IO2(x) (MASK_GEN(x, 2)) #define MASK_IO4(x) (MASK_GEN(x, 3)) #define PRIO_TRACK 0 #define PRIO_PERIODIC 1 #define PRIO_ALARM 2 #define PRIO_UNDEFINED 3 unsigned char maskGlobalNext(unsigned char mask, unsigned char state, unsigned char end_of_data) { unsigned int i, c; unsigned char order[] = {STATE_G_MASK, STATE_MASK, STATE_IO1_Q, STATE_IO2_Q, STATE_IO4_Q}; c = 0; // printf("gs%d|%d ", state, mask); for (i = 0; i < 5; i++) { if (order[i] == state) c = i; } for (i = c; i < 5; i++) { // printf("g%d|%d ", i, mask); if (MASK_GEN(mask, i)) { return order[i + 1]; } } // printf("End of rec\n"); if (end_of_data) return STATE_NO_OF_REC_END; else return STATE_PR_TS; } unsigned char maskNext(unsigned char mask, unsigned char state) { unsigned char i; for (i = state - STATE_MASK; i < 8; i++) { // printf(" %d|%d ", i, mask); if (MASK_GEN(mask, i)) { return STATE_MASK + 1 + i; } } return STATE_MASK; } uint8_t sensorTypes[][2] = { {001, TYPE_CAPACITY}, {010, TYPE_ALARM}, {0, 0} }; uint8_t getSensorType(uint8_t sensor) { int i; i = 0; while (sensorTypes[i][0] != 0) { if (sensorTypes[i][0] == sensor) return sensorTypes[i][1]; i++; } return 0; } void valuesCopyPos(double lat, double lon, double alt, time_t t, double * values) { values[0] = lat; values[1] = lon; values[2] = alt; values_time = t; values_type = VALUES_TYPE_POS; } void valuesCopySingle(double val, uint8_t sensor, time_t t, double * values) { values[0] = val; values_sensor[0] = sensor * 10000 + getSensorType(sensor) * 10000000; values_time = t; if (sensor == 010) values_type = VALUES_TYPE_ALARM; else values_type = VALUES_TYPE_OBS; } int stateMachine(unsigned char c) { static unsigned char state = STATE_IDLE; static uint8_t temp[16]; static unsigned char count = 0; static unsigned char mask = 0, mask_global = 0; static unsigned char state_type = STATE_IDLE; static unsigned char qua = 0, c_qua = 0; static unsigned char no_of_recs = 0, current_rec = 0; static float lat, lon, alt; static uint8_t prio, io_type; static struct tm rec_time; static time_t t_t; int ret; ret = 0; /* if (state != STATE_IDLE) printf("0x%x %d|", c, state);*/ temp[count] = c; count++; if (count < counts[state]) return 0; count = 0; switch (state) { case STATE_IDLE: if (*((uint32_t *)temp) == 0x00000000) state = STATE_DATA_LENGTH; break; case STATE_DATA_LENGTH: feederLog(LOG_DEBUG, "Data size: %d\n", byteSwap32(*((uint32_t *)temp))); state = STATE_CODEC_ID; break; case STATE_CODEC_ID: if (temp[0] == 0x07) state = STATE_NO_OF_REC; else { feederLog(LOG_DEBUG, "Bad codec, going to idle state\n"); state = STATE_IDLE; } break; case STATE_NO_OF_REC: no_of_recs = temp[0]; current_rec = 0; feederLog(LOG_DEBUG, "Number of records: %d\n", no_of_recs); state = STATE_PR_TS; break; case STATE_PR_TS: gmtime_r(&t_t, &rec_time); t_t = (byteSwap32(*((uint32_t *)temp)) & 0x3fffffff) + 1166832000 + 777600; /* if (current_rec > 0) { if ((lat != 0.0) && (lon != 0.0)) { } }*/ lat = lon = alt = 0.0; prio = PRIO_UNDEFINED; t_t = 0; gmtime_r(&t_t, &rec_time); t_t = (byteSwap32(*((uint32_t *)temp)) & 0x3fffffff) + 1166832000 + 777600; localtime_r(&t_t, &rec_time); feederLog(LOG_DEBUG, "Time of rec: %04d-%02d-%02d %02d:%02d:%02d\n", rec_time.tm_year + 1900, rec_time.tm_mon + 1, rec_time.tm_mday, rec_time.tm_hour, rec_time.tm_min, rec_time.tm_sec); prio = temp[0] >> 6; feederLog(LOG_DEBUG, "Priority: %d\n", prio); if (prio == 2) { valuesCopySingle(1.0, 010, t_t, values_out); ret = 2; } feederLog(LOG_DEBUG, "Next processed record will be: %d\n", current_rec); current_rec++; state = STATE_G_MASK; break; case STATE_G_MASK: feederLog(LOG_DEBUG, "gps:%d, io_1:%d, io_2:%d, io_4:%d\n", MASK_GPS(temp[0]), MASK_IO1(temp[0]), MASK_IO2(temp[0]), MASK_IO4(temp[0])); state_type = STATE_G_MASK; mask_global = temp[0]; state = maskGlobalNext(mask_global, state_type, current_rec == no_of_recs); state_type = state; break; case STATE_MASK: feederLog(LOG_DEBUG, "latlon:%d, alt:%d, angle:%d, speed:%d, sats:%d, cell:%d, qua:%d, op:%d\n", MASK_LATLON(temp[0]), MASK_ALT(temp[0]), MASK_ANGLE(temp[0]), MASK_SPEED(temp[0]), MASK_SATS(temp[0]), MASK_CELL(temp[0]), MASK_QUA(temp[0]), MASK_OP(temp[0])); mask = temp[0]; state = maskNext(mask, state); break; case STATE_LATLON: arraySwap4(temp); arraySwap4(&temp[4]); lon = *((float *)(&temp[4])); lat = *((float *)(&temp[0])); feederLog(LOG_DEBUG, "latlon: %f, %f\n", lat, lon); state = maskNext(mask, state); break; case STATE_ALT: alt = (float)byteSwap16(*(uint16_t *)temp); feederLog(LOG_DEBUG, "alt: %f\n", alt); if ((lat != 0.0) && (lon != 0.0)) { valuesCopyPos(lat, lon, alt, t_t, values_out); ret = 2; } state = maskNext(mask, state); break; case STATE_ANGLE: feederLog(LOG_DEBUG, "angle: %f\n", temp[0] * 360.0 / 256.0); state = maskNext(mask, state); break; case STATE_SPEED: feederLog(LOG_DEBUG, "speed: %d\n", *(uint8_t *)temp); state = maskNext(mask, state); break; case STATE_SATTS: feederLog(LOG_DEBUG, "sats: %d\n", *(uint8_t *)temp); state = maskNext(mask, state); if (state == STATE_MASK) { feederLog(LOG_DEBUG, "End of gps\n"); state = maskGlobalNext(mask_global, STATE_MASK, current_rec == no_of_recs); state_type = state; } break; case STATE_CELL: feederLog(LOG_DEBUG, "cell:\n"); state = maskNext(mask, state); break; case STATE_QUA: feederLog(LOG_DEBUG, "quality: %d\n", temp[0]); state = maskNext(mask, state); break; case STATE_OP: feederLog(LOG_DEBUG, "operator: %d\n", byteSwap32(*(uint32_t *)temp)); state = maskGlobalNext(mask_global, state_type, current_rec == no_of_recs); //todo: ted predpokladam ze jsou vsechny v gps (0xff)(rep minimalne tahle posledni) state_type = state; break; case STATE_IO1_Q: qua = temp[0]; feederLog(LOG_DEBUG, "io1 qua: %d\n", qua); c_qua = 0; if (c_qua == qua) { state = maskGlobalNext(mask_global, state_type, current_rec == no_of_recs); state_type = state; } else state = STATE_IO1_ID; break; case STATE_IO1_ID: feederLog(LOG_DEBUG, "io1 id: %d\n", temp[0]); io_type = temp[0]; state = STATE_IO1_VAL; break; case STATE_IO1_VAL: feederLog(LOG_DEBUG, "io1 val: %d\n", temp[0]); if (io_type == 1) { valuesCopySingle(temp[0], io_type, t_t, values_out); ret = 2; } c_qua++; if (c_qua == qua) { state = maskGlobalNext(mask_global, state_type, current_rec == no_of_recs); state_type = state; } else state = STATE_IO1_ID; break; case STATE_IO2_Q: qua = temp[0]; feederLog(LOG_DEBUG, "io2 qua: %d\n", qua); c_qua = 0; if (c_qua == qua) { state = maskGlobalNext(mask_global, state_type, current_rec == no_of_recs); state_type = state; } else state = STATE_IO2_ID; break; case STATE_IO2_ID: // feederLog(LOG_DEBUG, "io2 id:\n"); state = STATE_IO2_VAL; break; case STATE_IO2_VAL: // feederLog(LOG_DEBUG, "io2 val:\n"); c_qua++; if (c_qua == qua) { state = maskGlobalNext(mask_global, state_type, current_rec == no_of_recs); state_type = state; } else state = STATE_IO2_ID; break; case STATE_IO4_Q: qua = temp[0]; feederLog(LOG_DEBUG, "io4 qua: %d\n", qua); c_qua = 0; if (c_qua == qua) { state = maskGlobalNext(mask_global, state_type, current_rec == no_of_recs); state_type = state; } else state = STATE_IO4_ID; break; case STATE_IO4_ID: // feederLog(LOG_DEBUG, "io4 id:\n"); state = STATE_IO4_VAL; break; case STATE_IO4_VAL: // feederLog(LOG_DEBUG, "io4 val:\n"); c_qua++; if (c_qua == qua) { state = maskGlobalNext(mask_global, state_type, current_rec == no_of_recs); state_type = state; } else state = STATE_IO4_ID; break; case STATE_NO_OF_REC_END: no_of_recs = temp[0]; feederLog(LOG_DEBUG, "Number of records: %d\n", temp[0]); state = STATE_CRC; break; case STATE_CRC: state = STATE_IDLE; feederLog(LOG_DEBUG, "Crc\n"); reply_buffer[0] = 0x00; reply_buffer[1] = 0x00; reply_buffer[2] = 0x00; reply_buffer[3] = no_of_recs; reply_len = 4; ret = 1; break; } return ret; } int translate(unsigned char * data) { int ret, res; ret = 0; while (res = stateMachine(int_buffer[int_buffer_pos]), res == 0) { if (int_buffer_pos + 1 >= int_buffer_pos_wr) break; int_buffer_pos++; } int_buffer_pos++; if (res == 1) { feederLog(LOG_DEBUG, "End of data packet\n"); int_buffer_pos_wr = int_buffer_pos = 0; } if (res == 2) ret = 1; return ret; } //---------------------------------------------------------------------------------------------- int imei(unsigned char * data) { struct avl_header_t * avl_header; avl_header = (struct avl_header_t *)data; memcpy(imei_str, avl_header->imei, 15); imei_str[15] = 0; feederLog(LOG_DEBUG, "Imei is %s\n", imei_str); reply_buffer[0] = 0x01; reply_len = 1; return 1; } int init(void * param) { param = param; imei_flag = 0; bzero(imei_str, 16); bzero(reply_buffer, 32); reply_len = 0; int_buffer = malloc(32768); return 0; } unsigned int process(void *lib_data, int socket, unsigned char *data, unsigned int length, unsigned long long int *id, time_t * tm, double *result_array, uint64_t * sensors, unsigned int *type) { unsigned int ret = 0; if ((!imei_flag) && (length != 0)) { if (!imei_flag) { if (imei(data)) imei_flag = 1; } ret = 0; } else { if (length != 0) { feederLog(LOG_DEBUG, "Copying data\n", int_buffer_pos); memcpy(int_buffer + int_buffer_pos_wr, data, length); int_buffer_pos_wr += length; } if (translate(int_buffer)) { *id = atol(imei_str); *tm = values_time; if (values_type == VALUES_TYPE_POS) { memcpy(result_array, values_out, sizeof(double) * 3); sensors[0] = sensors[1] = sensors[2] = 0x10; *type = VALUES_TYPE_POS; ret = 3; } if (values_type == VALUES_TYPE_ALARM) { result_array[0] = 1.0; *type = VALUES_TYPE_ALARM; sensors[0] = TYPE_ALARM * 10000000 + 10 * 10000; ret = 1; } if (values_type == VALUES_TYPE_OBS) { result_array[0] = values_out[0]; *type = VALUES_TYPE_OBS; sensors[0] = values_sensor[0]; ret = 1; } } } return ret; } int reply(void *lib_data, int socket, unsigned char *data) { unsigned int temp_reply_len; feederLog(LOG_DEBUG, "gh120x: replying\n"); memcpy(data, reply_buffer, reply_len); temp_reply_len = reply_len; reply_len = 0; return temp_reply_len; } int close(void *lib_data, int socket) { feederLog(LOG_DEBUG, "gh120x: socket closed\n"); int_buffer_pos_wr = int_buffer_pos = 0; imei_flag = 0; imei_str[0] = 0; return 0; } int open(void *lib_data, int socket) { feederLog(LOG_DEBUG, "gh120x: socket open\n"); return 0; }