#include #include #include #include #include #include #include #include "libfixmath/libfixmath/fixmath.h" //#include "../../status.h" #include "../../../feeder.h" #include "sensob.h" typedef struct sensob_item_t { uint8_t flag; uint32_t sensor; uint32_t timestamp; uint8_t type; } __attribute__((packed)) sensob_item_t; typedef struct sensob_header_t { uint8_t delimiter; uint64_t id; uint16_t seq; uint16_t size; } __attribute__((packed)) sensob_header_t; typedef struct sensob_footer_t { uint16_t crc; } __attribute__((packed)) sensob_footer_t; typedef struct sensob_ack_t { uint8_t delimiter; uint16_t seq; } __attribute__((packed)) sensob_ack_t; typedef struct sensoblite_t { union { uint32_t raw; // struct sensoblite_timespec_t timespec; } timespec; uint32_t sensor_id; uint32_t value; } __attribute__((packed)) sensoblite_t; typedef struct sensoblite_ack_t { uint32_t timestamp; uint32_t dummy; } __attribute__((packed)) sensoblite_ack_t; typedef struct sensobtinymessage_t { uint8_t sensor_id_meta; uint16_t tm_diff; } __attribute__((packed)) sensobtinymessage_t; typedef struct sensob_item_position_data_t { double lat; double lon; double alt; } __attribute__((packed)) sensob_item_position_data_t; uint8_t sensob_types_len[] = { sizeof(uint8_t), sizeof(int8_t), sizeof(uint16_t), sizeof(int16_t), sizeof(uint32_t), sizeof(int32_t), sizeof(uint64_t), sizeof(int64_t), sizeof(float), sizeof(double), sizeof(time_t), sizeof(uint8_t), sizeof(sensob_item_position_data_t), sizeof(uint32_t), sizeof(fix16_t) }; // todo: oifovat podle endianes 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; } //todo: kontrolvat jestli to jde - tj len=2,4,8,16 ... void memSwap(uint8_t * data, uint8_t len) { uint8_t temp; uint8_t i; for (i = 0; i < len / 2; i++) { temp = data[i]; data[i] = data[len - 1 - i]; data[len - 1 - i] = temp; } } #define SENSOB_TYPE_UINT8 0 #define SENSOB_TYPE_INT8 1 #define SENSOB_TYPE_UINT16 2 #define SENSOB_TYPE_INT16 3 #define SENSOB_TYPE_UINT32 4 #define SENSOB_TYPE_INT32 5 #define SENSOB_TYPE_UINT64 6 #define SENSOB_TYPE_INT64 7 #define SENSOB_TYPE_FLOAT 8 #define SENSOB_TYPE_DOUBLE 9 #define SENSOB_TYPE_TIMESTAMP 10 #define SENSOB_TYPE_ERROR 11 #define SENSOB_TYPE_POSITION 12 #define SENSOB_TYPE_ALERT 13 #define SENSOB_TYPE_FIX16 14 static uint8_t * ld = NULL; static uint8_t * pd = NULL; static uint16_t sd = 0; static uint16_t seq = 0; uint8_t * findDelimiter(uint8_t * data, uint16_t len) { uint8_t * res; for (res = data; res < data + len; res++) { if (*res == 0xff) return res; } return NULL; } #define SENSOBLITE_MASK_FIX16 0x00000000 #define SENSOBLITE_MASK_FLOAT 0x40000000 #define SENSOBLITE_MASK_INT32 0x80000000 #define SENSOBLITE_MASK_RES 0xC0000000 int sensoblite_parse(uint8_t * data, uint16_t length, time_t * tm, double *result_array, uint64_t * sensors, unsigned int *type) { struct sensoblite_t * sensoblite = (struct sensoblite_t *)data; uint32_t val_swapped; float val_float; (void)length; *tm = byteSwap32(sensoblite->timespec.raw); sensors[0] = byteSwap32(sensoblite->sensor_id); if ((sensors[0] & 0xC0000000) == SENSOBLITE_MASK_FIX16) { if (((fix16_t)(byteSwap32((uint32_t)(sensoblite->value)))) == fix16_overflow) result_array[0] = NAN; else result_array[0] = fix16_to_dbl((fix16_t)(byteSwap32((uint32_t)(sensoblite->value)))); } if ((sensors[0] & 0xC0000000) == SENSOBLITE_MASK_FLOAT) { val_swapped = byteSwap32((uint32_t)(sensoblite->value)); //result_array[0] = byteSwap32((uint32_t)(sensoblite->value)); memcpy(&val_float, &val_swapped, 4); result_array[0] = val_float; } if ((sensors[0] & 0xC0000000) == SENSOBLITE_MASK_INT32) { result_array[0] = (float)(byteSwap32((uint32_t)(sensoblite->value))); } sensors[0] &= 0xBFFFFFFF; *type = VALUES_TYPE_OBS; return 1; } typedef struct meta_u_t { uint64_t id; double multi; } meta_u_t; typedef struct sensobtinymeta_t { struct meta_u_t u[32]; } sensobtinymeta_t; static struct sensobtinymeta_t metas[24] =//todo: konfigurovat toto a casovou zonu devicy v conf, nebo to bude posilat noda { {{{100000000,1.0}}}, //0 {{{340340092,1.0},{340350004,1.0},{360200000,1.0}}}, //1 {{{360200000,1.0}}}, //2 {{{340070001,1.0},{410050001,1.0},{460010001,1.0}}}, //3 {{{480020001,1.0},{490010001,1.0}}}, //4 {{{470020001,1.0},{470010001,1.0}}}, //5 {{{540090004,10.0},{550020004,10.0},{340370004,10.0}}}, //6 {{{0,0.0}}} }; #define SENSOB_TINY_DATA_SIZE 3 int sensobtiny_parse(uint8_t * data, uint16_t length, uint32_t time_of_receive, time_t * tm, double *result_array, uint64_t * sensors, unsigned int *type) { uint8_t meta_id; uint16_t i; fix16_t val; struct sensobtinymessage_t * sensobtinymessage = (struct sensobtinymessage_t *)data; struct tm t; (void)length; feederLog(LOG_DEBUG, "sensobtiny: Analyzing data, size %d\n", length); meta_id = sensobtinymessage->sensor_id_meta - 0xA0; /* localtime_r((time_t *)&time_of_receive, &t); time_of_receive = mktime(&t); */ *tm = (time_of_receive / 60) * 60 - (byteSwap16(sensobtinymessage->tm_diff) * 60); localtime_r((time_t *)tm, &t);//todo: z konfigurace *tm = timegm(&t); length -= sizeof(struct sensobtinymessage_t); data += sizeof(struct sensobtinymessage_t); feederLog(LOG_DEBUG, "sensobtiny: time of receive %lld, diff %lld, timestamp %lld\n", time_of_receive, byteSwap16(sensobtinymessage->tm_diff), *tm); feederLog(LOG_DEBUG, "sensobtiny: meta id %lld, diff %lld, timestamp %lld\n", meta_id); i = 0; while (length > 0) { feederLog(LOG_DEBUG, "sensobtiny: field %d\n", i); sensors[i] = metas[meta_id].u[i].id; val = 0; memSwap(data, SENSOB_TINY_DATA_SIZE); memcpy(((uint8_t *)&val) + 1, data, SENSOB_TINY_DATA_SIZE); data += SENSOB_TINY_DATA_SIZE; if (val == fix16_overflow) result_array[i] = NAN; else // val = fix16_div(val, fix16_from_dbl(metas[meta_id].u[i].multi));//todo: result_array[i] = round(fix16_to_dbl(val) * 100.0) / 100.0; result_array[i] /= metas[meta_id].u[i].multi; i++; length -= SENSOB_TINY_DATA_SIZE; } *type = VALUES_TYPE_OBS; /* *tm = byteSwap32(sensoblite->timespec.raw); sensors[0] = byteSwap32(sensoblite->sensor_id); result_array[0] = fix16_to_dbl((fix16_t)(byteSwap32((uint32_t)(sensoblite->value)))); *type = VALUES_TYPE_OBS; */ return i; } int sensob_parse(uint8_t * data, uint16_t length, uint64_t * id, time_t * tm, double *result_array, uint64_t * sensors, unsigned int *type) { static struct sensob_header_t * header; struct sensob_item_t * item; struct sensob_footer_t * footer; double val; unsigned int ret, i; static double lat, lon; //todo: do lib_data static uint8_t pos_flag = 0; uint8_t temp[256]; time_t tm_prev; feederLog(LOG_DEBUG, "sensob: Analyzing data, size %d\n", length); ret = 0; if ((data != NULL) && (length > 0)) { if (ld != NULL) { free(ld); ld = pd = NULL; sd = 0; } ld = malloc(length); if (ld == NULL) { feederLog(LOG_WARNING, "sensob: Can not allocate data buffer\n"); return -1; } memcpy(ld, data, length); pd = NULL; sd = length; pd = findDelimiter(ld, sd); if (pd == NULL) { feederLog(LOG_WARNING, "sensob: No delimiter\n"); free(ld); ld = NULL; return -1; } header = (sensob_header_t *)pd; feederLog(LOG_DEBUG, "sensob: Id %llu, seq %d, size %d\n", header->id, header->seq, header->size); seq = header->seq; pd += sizeof(struct sensob_header_t); } if (pd == NULL) { return 0; } // *id = byteSwap64(header->id); *id = header->id; i = 0; tm_prev = 0; feederLog(LOG_DEBUG, "sensob: header size %d\n", header->size); if (header->size > 0) { item = (sensob_item_t *)pd; pd += sizeof(struct sensob_item_t); val = 0.0; memcpy(temp, pd, sensob_types_len[item->type]); // memSwap(temp, sensob_types_len[item->type]); switch (item->type) { case SENSOB_TYPE_UINT8: val = (uint8_t)*pd; break; case SENSOB_TYPE_FLOAT: // val = byteSwap32(*((float *)pd)); val = *((float *)temp); break; case SENSOB_TYPE_DOUBLE: // val = byteSwap64(*((double *)pd)); val = *((double *)temp); break; case SENSOB_TYPE_ERROR: val = (uint8_t)*pd; break; case SENSOB_TYPE_ALERT: val = (uint32_t)*pd; break; case SENSOB_TYPE_POSITION: break; case SENSOB_TYPE_FIX16: val = fix16_to_dbl(*((fix16_t *)temp)); break; } pd += sensob_types_len[item->type]; feederLog(LOG_DEBUG, "sensob: item sensor %lu, value %f, type %d\n", item->sensor, val, item->type); header->size--; if (item->type == SENSOB_TYPE_POSITION) { lat = val; lon = val; pos_flag = 0; *tm = item->timestamp; //todo: ted bere posledni cas, musime predelat na casy jednotlivych mereni *type = VALUES_TYPE_POS; result_array[0] = ((sensob_item_position_data_t *) temp)->lat; result_array[1] = ((sensob_item_position_data_t *) temp)->lon; result_array[2] = 0.0; result_array[3] = 1.0; result_array[4] = 0.0; sensors[0] = sensors[1] = sensors[2] = sensors[3] = sensors[4] = 0x10; ret = 5; } else { /* if ((item->sensor != 4294967295) && (item->timestamp != 4294967295) && (!isnan(val))) //BEWARE: tohle je kontrola proti lugioho meteoskam - obcas poslou FFFFFFF -> kontrola tamniho posilani*/ // if ((!isnan(val))) //todo: poustime i nan jako oznaceni nevalidniho mereni { sensors[i] = item->sensor; result_array[i] = val; i++; *tm = item->timestamp; feederLog(LOG_DEBUG, "sensob: Timestamp %lu\n", item->timestamp); if ((item->type == SENSOB_TYPE_ERROR) || (item->type == SENSOB_TYPE_ALERT)) *type = VALUES_TYPE_ALERT; else *type = VALUES_TYPE_OBS; ret = i; } } } if (header->size == 0) { free(ld); ld = pd = NULL; sd = 0; } return ret; } int sensob_reply(uint8_t * data) { struct sensob_ack_t * ack; if (seq == 0) return 0; ack = (struct sensob_ack_t *)data; ack->delimiter = 0xff; ack->seq = seq; seq = 0; // feederLog(LOG_DEBUG, "sensob: replying\n"); return sizeof(struct sensob_ack_t); }