#include #include #include #include #include #include #include #include #include "libyuarel/yuarel.h" //#include "libfixmath/libfixmath/fixmath.h" #include "sensob/sensob.h" //#include "../../status.h" #include "../../feeder.h" cfg_opt_t metaid_opts[] = { CFG_INT((char *)"metaid", 0, CFGF_NONE), CFG_INT_LIST((char *)"sensorid", 0, CFGF_NONE), CFG_END() }; cfg_opt_t device_opts[] = { CFG_STR((char *)"unit_id", 0, CFGF_NONE), CFG_SEC((char *)"metaid", metaid_opts, CFGF_MULTI | CFGF_TITLE), CFG_END() }; cfg_opt_t cfg_opts[] = { CFG_SEC((char *)"device", device_opts, CFGF_MULTI | CFGF_TITLE), CFG_END() }; #define RECVD_HISTORY_SIZE 32//must be dividable by 8 typedef struct unit_t { uint32_t id; uint8_t recvd[RECVD_HISTORY_SIZE]; uint8_t pos, recvd_size; uint32_t seq; uint8_t ack; struct unit_t * next; } unit_t; static struct unit_t * units, * unit_now; //static uint32_t seq; static uint8_t ack; static void (* feederLog)(int priority, const char * fmt, ...); int setLog(void * func) { feederLog = (void(*)(int, const char * , ...))func; return 0; } int init(void * param) { (void)param; // seq = 0; units = unit_now = NULL; ack = 0; return 0; } struct unit_t * unitFind(struct unit_t * unit, uint32_t id) { while (unit != NULL) { if (unit->id == id) return unit; unit = unit->next; } return NULL; } struct unit_t * unitCreate(uint32_t id) { struct unit_t * unit; unit = (struct unit_t *)malloc(sizeof(struct unit_t)); unit->id = id; memset(unit->recvd, 0, RECVD_HISTORY_SIZE); unit->seq = 0; unit->pos = 0; unit->next = NULL; return unit; } void unitUpdateRecvd(struct unit_t * unit, uint8_t flag) { unit->recvd[unit->pos++] = flag; if (unit->pos > RECVD_HISTORY_SIZE) unit->pos = 0; } void stringToArrayn(uint8_t * data, char * str, uint16_t len) { uint16_t i; uint8_t j; char c; for (i = 0; i < len; i++) { data[i] = 0; for (j = 0; j < 2; j++) { c = str[i * 2 + j]; if (c >= 'a') //to high case c -= 0x20; data[i] += (c - ((c < 'A')?'0':'7')) << ((j == 0)?4:0); } } } void arraynToString(char * str, uint8_t * data, uint16_t len) { uint16_t i; uint8_t j; char c; for (i = 0; i < len; i++) { for (j = 0; j < 2; j++) { c = (data[i] >> ((j == 0)?4:0)) & 0x0F; str[i * 2 + j] = c + ((c < 0x0A)?'0':'7'); } } str[len * 2] = '\0'; } char * yarel_get_param(struct yuarel_param * params, int params_count, const char * param_name) { int i; i = 0; while (i < params_count) { if (strcmp(params[i].key, param_name) == 0) return params[i].val; i++; } return NULL; } 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) { struct yuarel url; int p, i; // char * parts[3]; struct yuarel_param params[16]; char *c; struct unit_t * unit; uint32_t seq; uint8_t params_data_bin[12]; uint8_t params_data_len; uint64_t pid; unsigned int res; (void)lib_data; (void)socket; (void)type; if ((data == NULL) || (length == 0)) return 0; feederLog(LOG_DEBUG, "sigfox: raw data in:\n%s\n", (char *)data); seq = 0; *id = 0; data[length] = 0; if (yuarel_parse(&url, (char *)(data + 4)) != 0)//skip leading GET { feederLog(LOG_WARNING, "sigfox: Yuarel can not parse input\n"); return 0; } c = strchr(url.query, ' '); if (c != NULL) *c = 0; // feederLog(LOG_DEBUG, "sigfox: scheme: %s\n", url.scheme); // feederLog(LOG_DEBUG, "sigfox: host: %s\n", url.host);pada? // feederLog(LOG_DEBUG, "sigfox: port: %d\n", url.port); // feederLog(LOG_DEBUG, "sigfox: path: %s\n", url.path); feederLog(LOG_DEBUG, "sigfox: query: %s\n", url.query); // feederLog(LOG_DEBUG, "sigfox: fragment: %s\n", url.fragment);pada? /* if (3 != yuarel_split_path(url.path, parts, 3)) { fprintf(stderr, "Could not split path!\n"); return 0; } feederLog(LOG_DEBUG, "sigfox: path parts: %s, %s, %s\n", parts[0], parts[1], parts[2]); feederLog(LOG_DEBUG, "sigfox: Query string parameters:\n"); */ p = yuarel_parse_query(url.query, '&', params, 16); params_data_len = strlen(yarel_get_param(params, p, "data")) / 2; stringToArrayn(params_data_bin, yarel_get_param(params, p, "data"), params_data_len); feederLog(LOG_DEBUG, "sigfox: binary data: "); for (i = 0; i < params_data_len; i++) feederLog(LOG_DEBUG, "%02X ", params_data_bin[i]); feederLog(LOG_DEBUG, "\n"); pid = strtoll(yarel_get_param(params, p, "unit_id"), NULL, 16); seq = atoi(yarel_get_param(params, p, "seq")); if (params_data_bin[0] == 0xFF)//this is sensob message { feederLog(LOG_DEBUG, "sigfox: sensob detected\n"); feederLog(LOG_WARNING, "sigfox: sensob protocol not supported\n"); } // else if (json_data_data_bin[0] == 0xFE)//this is command todo: nebo rozlisit podle portu else if (params_data_bin[0] > 0xC0)//this is command todo: nebo rozlisit podle portu { feederLog(LOG_DEBUG, "sigfox: cmd detected\n"); //cmdParse(params_data_bin, params_data_len, pid); } else if (params_data_bin[0] >= 0xA0) //this is sensob tiny message { feederLog(LOG_DEBUG, "sigfox: sensob tiny detected\n"); res = sensobtiny_parse(params_data_bin, params_data_len, strtol(yarel_get_param(params, p, "ts"), NULL, 10), tm, result_array, sensors, type); *id = pid; } else //this is sensob lite message { feederLog(LOG_DEBUG, "sigfox: sensob lite detected\n"); res = sensoblite_parse(params_data_bin, params_data_len, tm, result_array, sensors, type); *id = pid; } /* i = 0; ack = 0; while (i < p) { feederLog(LOG_DEBUG, "sigfox: %s: %s\n", params[i].key, params[i].val); if (strcmp(params[i].key, "date") == 0) *tm = atoll(params[i].val); if (strcmp(params[i].key, "sensor_id") == 0) sensors[0] = atoll(params[i].val); if (strcmp(params[i].key, "unit_id") == 0) { *id = strtoll(params[i].val, NULL, 16); } if (strcmp(params[i].key, "value") == 0) // result_array[0] = atof(params[i].val); result_array[0] = fix16_to_float(atoll(params[i].val)); if (strcmp(params[i].key, "seq") == 0) seq = atoi(params[i].val); if (strcmp(params[i].key, "ack") == 0) ack = (strcmp(params[i].val, "true") == 0)?1:0; i++; }*/ *type = VALUES_TYPE_OBS; unit = unitFind(units, *id); if (unit == NULL) { feederLog(LOG_DEBUG, "sigfox: creating new unit %ld\n", *id); unit = unitCreate(*id); if (units != NULL) { unit->next = units; } units = unit; } else feederLog(LOG_DEBUG, "sigfox: unit %ld found\n", unit->id); if (unit->seq == 0)//todo: je nula opravdu vyjimecna? unit->seq = seq; else { while (unit->seq++, unit->seq < seq) unitUpdateRecvd(unit, 0); } unitUpdateRecvd(unit, 1); unit->ack = ack; unit_now = unit; if (*id != 0) return res; return 0; } int reply(void * lib_data, int socket, unsigned char *data) { // uint8_t i, j; struct unit_t * unit; char * buf; (void)lib_data; (void)socket; unit = unit_now; if (unit == NULL) { //todo: odpovededet nejakym chybou return 0; } if (unit->seq == 0) return 0; time((time_t *)data); /*todo memset(data + 4, 0, 4); for (i = 0; i < RECVD_HISTORY_SIZE; i++) { j = unit->pos - (RECVD_HISTORY_SIZE + i); if (j > RECVD_HISTORY_SIZE) //rotated (less then zero) j += RECVD_HISTORY_SIZE; data[4 + i / 8] |= unit->recvd[j] << (i % 8); } */ buf = (char *)data; time_t now = time(0); struct tm tm = *gmtime(&now); sprintf(buf, "HTTP/1.0 204 NO CONTENT\r\nServer: feeder\r\nContent-Length: %d\r\nDate: ", 0); strftime(buf + strlen(buf), 1000, "%a, %d %b %Y %H:%M:%S %Z", &tm); sprintf(buf + strlen(buf), "\r\n\r\n"); feederLog(LOG_DEBUG, "sigfox: raw data out: \n%s\n", (char *)data); feederLog(LOG_DEBUG, "sigfox: replying\n"); unit->seq = 0; return strlen((char *)data); }