| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <syslog.h>
- #include <stdint.h>
- #include <math.h>
- #include <curl/curl.h>
- #include <confuse.h>
- #include "libyuarel/yuarel.h"
- #include "json-c/json.h"
- #include "sensob/sensob.h"
- #include "aes.h"
- //#include "../../status.h"
- #include "../../feeder.h"
- #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 uint64_t jid = 0;
- //static uint32_t seq;
- static uint8_t ack;
- static cfg_t * cfg;
- 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;
- cfg_opt_t cfg_opts[] =
- {
- CFG_STR((char *)"url", 0, CFGF_NONE),
- CFG_STR((char *)"user", 0, CFGF_NONE),
- CFG_STR((char *)"pass", 0, CFGF_NONE),
- CFG_END()
- };
-
- cfg = cfg_init(cfg_opts, CFGF_NONE);
- if (cfg_parse(cfg, "cra.conf") != CFG_SUCCESS)
- {
- return -1;
- }
- curl_global_init(CURL_GLOBAL_DEFAULT);
- 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';
- }
- #define CMD_DATETIME_REQ 0xD0
- #define CMD_DATETIME_SYNC 0xD1
- #define CMD_DATETIME_RESPONSE 0xD2
- #define CMD_VARVAL 0xD3
- #define CMD_NONE 0xCF
- typedef struct cmd_datetimereq_t
- {
- uint32_t tm;
- } __attribute__((packed)) cmd_datetimereq_t;
- typedef struct cmd_datetimeresponse_t
- {
- int32_t diff;
- } __attribute__((packed)) cmd_datetimeresponse_t;
- typedef struct cmd_datetimesync_t
- {
- } __attribute__((packed)) cmd_datetimesync_t;
- typedef struct cmd_header_t
- {
- // uint8_t delimiter;
- // uint64_t id;
- uint8_t cmd;
- } __attribute__((packed)) cmd_header_t;
- typedef struct cmd_footer_t
- {
- // uint16_t crc;
- } __attribute__((packed)) cmd_footer_t;
- int curlDebug(CURL * curl, curl_infotype info, char * string, size_t size, void * data)
- {
- (void)curl;
- (void)data;
-
- if (feederLog != NULL)
- {
- if (info == CURLINFO_TEXT)
- {
- string[size] = 0;
- feederLog(LOG_DEBUG, "cra: curl debug: %s", string);
- }
- }
- return 0;
- }
- typedef struct cb_t
- {
- uint8_t cmd;
- } cb_t;
- size_t curlWriteCB(void *contents, size_t size, size_t nmemb, void *userp)
- {
- size_t realsize;
- char * fetch = (char *)userp;
-
- realsize = size * nmemb;
- feederLog(LOG_DEBUG, "cra: Fetched %s\n", (char *)contents);
- memcpy(fetch, contents, realsize);
- fetch[realsize] = 0;
- /* return size */
- return realsize;
- }
- void craApi(char * method, char * header_id, char * req_body, char * fetch)
- {
- CURL *ch;
- CURLcode res;
- char url[1024];
- char post[2048];
- char header[256];
- int info;
- struct curl_slist * headers = NULL;
- ch = curl_easy_init();
- if (ch)
- {
- curl_easy_setopt(ch, CURLOPT_DEBUGFUNCTION, curlDebug);
- curl_easy_setopt(ch, CURLOPT_VERBOSE, 1L);
- // strcpy(url, "http://82.99.180.180/Message");
- // strcpy(url, "https://api.iot.cra.cz/cxf/IOTServices/v2/");
- strcpy(url, cfg_getstr(cfg, "url"));
-
- strcpy(url + strlen(url), method);
- curl_easy_setopt(ch, CURLOPT_URL, url);
- curl_easy_setopt(ch, CURLOPT_POST, 1L);
- headers = curl_slist_append(headers, "Accept: application/json");
- headers = curl_slist_append(headers, "Content-Type: application/json");
- if (header_id != NULL)
- {
- strcpy(header, "SessionId: ");
- strcpy(header + strlen(header), header_id);
- headers = curl_slist_append(headers, header);
- }
- curl_easy_setopt(ch, CURLOPT_HTTPHEADER, headers);
- // curl_easy_setopt(ch, CURLOPT_HEADER, 0);
- // curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 0);
- /* sprintf((char *)post,
- "{\r\n\t\"EUI\": \"%s\",\r\n\t\"data\": \"{\\\"cmd\\\":\\\"tx\\\",\\\"port\\\":1,\\\"data\\\":\\\"%s\\\",\\\"EUI\\\":\\\"%s\\\"}\"\r\n}\r\n",
- "0004A30B0022088F", "2C","0004A30B0022088F");
- */
- strcpy(post, req_body);
- curl_easy_setopt(ch, CURLOPT_CUSTOMREQUEST, "POST");
- curl_easy_setopt(ch, CURLOPT_POSTFIELDS, post);
- curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, strlen(post));
-
- // cf.payload = (char *)calloc(1, sizeof(cf.payload));
- // cf.size = 0;
- // curl_easy_setopt(ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_0); //!!!!!!!!!!!!
- if (fetch != NULL)
- {
- curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, curlWriteCB);
- curl_easy_setopt(ch, CURLOPT_WRITEDATA, (void *)fetch);
- }
-
- // res = curl_fetch_url(curl_g, path, &cf);
- feederLog(LOG_INFO, "cra: %s %s\n", url, post);
-
- res = curl_easy_perform(ch);
- curl_easy_cleanup(ch);
-
- curl_easy_getinfo(ch, CURLINFO_HTTP_CODE, &info);
- if (res != CURLE_OK)
- {
- feederLog(LOG_ERR, "cra: curl POST error %d\n", res);
- return;
- }
- if (info != 200)
- {
- feederLog(LOG_ERR, "cra: curl page error %d\n", info);
- return;
- }
- }
- }
- char * craLogin(void)
- {
- char fetch[2048];
- char req[1024];
- json_object * json;
- enum json_tokener_error jerr = json_tokener_success;
- char * id = NULL;
-
- // craApi((char *)"Login", NULL, (char *)"{\r\n\t\"username\": \"krivanek@lesprojekt.cz\",\r\n\t\"password\": \"#LESPloRa2020@\"\r\n}\r\n", fetch);//todo: conf
- sprintf(req, (char *)"{\r\n\t\"username\": \"%s\",\r\n\t\"password\": \"%s\"\r\n}\r\n", cfg_getstr(cfg, "user"), cfg_getstr(cfg, "pass"));
- craApi((char *)"Login", NULL, req, fetch);//todo: conf
- json = json_tokener_parse_verbose(fetch, &jerr);
- if (jerr != json_tokener_success)
- {
- feederLog(LOG_ERR, "cra: Failed to parse json err %s\n", json_tokener_error_desc(jerr));
- json_object_put(json);
- return NULL;
- }
- id = (char *)json_object_get_string(json_object_object_get(json, "sessionId"));
- feederLog(LOG_INFO, "cra: Session id %s\n", id);
-
- return id;
- }
- void cmdMessage(uint8_t * d, uint64_t id, uint8_t cmd)
- {
- struct cmd_header_t * header;
- // struct cmd_footer_t * footer;
- (void)id;
- header = (struct cmd_header_t *)(d);
- // footer = (struct cmd_footer_t *)(d + sizeof(struct cmd_header_t) + cmd_tyope_size);//todo: footer
- // header->delimiter = '.';
- // header->id = id;
- header->cmd = cmd;
- }
- void cmdFooter(uint8_t * d, uint16_t len)
- {
- struct cmd_footer_t * footer;
-
- footer = (struct cmd_footer_t *)(d + len);
- // footer->crc = 0;//todo: spocitat
- }
- void cmdDateTimeReq(struct cmd_datetimereq_t * req, uint64_t id)
- {
- char body[2048];
- char message[256];
- uint8_t data[32];
- struct cmd_datetimeresponse_t * response;
- char * sid;
- time_t tm;
- int32_t diff;
- uint16_t len;
-
-
- tm = time(NULL);
- diff = tm - byteSwap32(req->tm);
- feederLog(LOG_INFO, "cra: device time %lld, system time %lld, difference %lld\n", byteSwap32(req->tm), tm, diff);
-
- cmdMessage(data, 0, CMD_DATETIME_RESPONSE);
- response = (struct cmd_datetimeresponse_t *)(data + sizeof(struct cmd_header_t));
- response->diff = byteSwap32(diff);
- cmdFooter(data, sizeof(struct cmd_header_t) + sizeof(struct cmd_datetimeresponse_t));
- len = sizeof(struct cmd_header_t) + sizeof(struct cmd_datetimeresponse_t) + sizeof(struct cmd_footer_t);
- sid = craLogin();
- if (sid != NULL)
- {
- arraynToString(message, data, len);
- /* sprintf((char *)body,
- "{\r\n\t\"EUI\": \"%s\",\r\n\t\"data\": \"{\\\"cmd\\\":\\\"tx\\\",\\\"port\\\":1,\\\"data\\\":\\\"%s\\\",\\\"EUI\\\":\\\"%s\\\"}\"\r\n}\r\n",
- "0004A30B0022088F", message,"0004A30B0022088F");*/
- sprintf((char *)body,
- "{\r\n\t\"EUI\": \"%016llX\",\r\n\t\"data\": \"{\\\"cmd\\\":\\\"tx\\\",\\\"port\\\":1,\\\"data\\\":\\\"%s\\\",\\\"EUI\\\":\\\"%016llX\\\"}\"\r\n}\r\n",
- id, message, id);
- craApi((char *)"Message", sid, body, NULL);
- }
- }
- void cmdParse(uint8_t * data, uint16_t len, uint64_t id)
- {
- struct cmd_header_t * header = (struct cmd_header_t *)data;
- (void)len;
- switch (header->cmd)
- {
- case CMD_DATETIME_REQ:
- feederLog(LOG_DEBUG, "cra: Cmd datetimereq\n");
- cmdDateTimeReq((struct cmd_datetimereq_t *)(data + sizeof(struct cmd_header_t)), id);
- break;
- case CMD_DATETIME_SYNC:
- feederLog(LOG_DEBUG, "cra: Cmd datetimesync\n");
- break;
- default:
- feederLog(LOG_ERR, "cra: Unknowen command %d\n", header->cmd);
- break;
- }
- }
- #define LW_KEY_LEN (16)
- unsigned int
- process(void *lib_data, int sock, unsigned char *data,
- unsigned int length, unsigned long long int *id, time_t * tm,
- double *result_array, uint64_t * sensors, unsigned int *type)
- {
- uint32_t seq;
- json_object *json, *json_data, * jdata;
- enum json_tokener_error jerr = json_tokener_success;
- char * data_json, * json_data_data_str;
- uint8_t json_data_data_bin[255];
- uint32_t json_data_ts_int;
- uint8_t json_data_bat_int;
- unsigned int res;
- (void)lib_data;
- (void)sock;
- if ((data == NULL) || (length == 0))
- {
- res = sensob_parse(NULL, 0, (uint64_t *)id, tm, result_array, sensors, type);
- *id = jid;
- // feederLog(LOG_DEBUG, "cra: item sensor %lu, value %f, type %d\n", sensors[0], result_array[0], *type);
- return res;
- }
- while (data[length - 1] < ' ')
- length--;
- data[length] = 0;
-
- feederLog(LOG_DEBUG, "cra: raw data in:\n%s\n", (char *)data);
- seq = 0;
- *id = 0;
- feederLog(LOG_DEBUG, "cra:1\n");
- data_json = strchr((char *)data, '{');//todo: proparsit i hlavicku
- if (data_json == NULL)
- {
- feederLog(LOG_ERR, "cra: Json not found\n");
- return -1;
- }
- json = json_tokener_parse_verbose(data_json, &jerr);
- if (jerr != json_tokener_success)
- {
- feederLog(LOG_ERR, "cra: Failed to parse json err %s\n", json_tokener_error_desc(jerr));
- json_object_put(json);
- return -1;
- }
-
- jdata = json_object_object_get(json, "data");
-
- // todo: check
- // feederLog(LOG_DEBUG, "cra: %s\n", json_object_get_string(jdata));
- json_data = json_tokener_parse_verbose(json_object_get_string(jdata), &jerr);
- jid = strtol(json_object_get_string(json_object_object_get(json_data, "EUI")), NULL, 16);
- feederLog(LOG_DEBUG, "cra: id %lld\n", *id);
- json_data_data_str = (char *)json_object_get_string(json_object_object_get(json_data, "data"));
- json_data_ts_int = json_object_get_int64(json_object_object_get(json_data, "ts")) / 1000;
- json_data_bat_int = json_object_get_int64(json_object_object_get(json_data, "bat"));
- if ((json_data_data_str == NULL) || (strlen(json_data_data_str) == 0))
- {
- /* json_data_data_str = (char *)json_object_get_string(json_object_object_get(json_data, "encdata"));
- feederLog(LOG_DEBUG, "cra: encdata %s\n", json_data_data_str);
- stringToArrayn(json_data_data_bin, json_data_data_str, strlen(json_data_data_str) / 2);
-
-
-
- aes_context aesContext;
- uint8_t aeskey[] = {0x45, 0xf3, 0x22, 0x67, 0x98, 0x95, 0x6f, 0xcd, 0x46, 0x67, 0x0b, 0x8c, 0x13, 0xb8, 0x23, 0x15};
- aes_set_key(aeskey, LW_KEY_LEN, &aesContext);
- aes_encrypt(json_data_data_bin, json_data_data_bin, &aesContext);
- */
- // feederLog(LOG_ERR, "cra: Encoded data not yet supported\n");
- feederLog(LOG_ERR, "cra: Data shape not yet supported\n");
- json_object_put(json);
- return -1;
- }
- else
- {
- feederLog(LOG_DEBUG, "cra: data %s\n", json_data_data_str);
- stringToArrayn(json_data_data_bin, json_data_data_str, strlen(json_data_data_str) / 2);
- }
- feederLog(LOG_DEBUG, "cra: binary data: ");
- uint16_t i;
- for (i = 0; i < (strlen(json_data_data_str) / 2); i++)
- feederLog(LOG_DEBUG, "%02X ", json_data_data_bin[i]);
- feederLog(LOG_DEBUG, "\n");
-
- if (json_data_data_bin[0] == 0xFF)//this is sensob message
- {
- feederLog(LOG_DEBUG, "cra: sensob detected\n");
-
- res = sensob_parse(json_data_data_bin, strlen(json_data_data_str) / 2, (uint64_t *)id, tm, result_array, sensors, type);
- feederLog(LOG_DEBUG, "cra: item sensor %lu, value %f, type %d\n", sensors[0], result_array[0], *type);
- *id = jid;
- }
- // else if (json_data_data_bin[0] == 0xFE)//this is command todo: nebo rozlisit podle portu
- else if (json_data_data_bin[0] > 0xC0)//this is command todo: nebo rozlisit podle portu
- {
- feederLog(LOG_DEBUG, "cra: cmd detected\n");
-
- cmdParse(json_data_data_bin, strlen(json_data_data_str) / 2, jid);
- }
- else if (json_data_data_bin[0] >= 0xA0) //this is sensob tiny message
- {
- feederLog(LOG_DEBUG, "cra: sensob tiny detected\n");
-
- res = sensobtiny_parse(json_data_data_bin, strlen(json_data_data_str) / 2, json_data_ts_int, tm, result_array, sensors, type);
- *id = jid;
- }
- else //this is sensob lite message
- {
- feederLog(LOG_DEBUG, "cra: sensob lite detected\n");
-
- res = sensoblite_parse(json_data_data_bin, strlen(json_data_data_str) / 2, tm, result_array, sensors, type);
- *id = jid;
- }
-
- result_array[res] = (double)json_data_bat_int; //get lora battery status as sensor measurement
- sensors[res] = 560030000;
- res++;
-
- return res;
- }
- int reply(void * lib_data, int sock, unsigned char *data)
- {
- struct unit_t * unit;
- char * buf;
-
- (void)lib_data;
- (void)sock;
-
- 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, "cra: raw data out: \n%s\n", (char *)data);
- feederLog(LOG_DEBUG, "cra: replying\n");
-
- unit->seq = 0;
- return strlen((char *)data);
- }
|