/** * @file gadget_bridge.c * @author Anatole SCHRAMM-HENRY * @brief Source file implementing the API used to communicate/interact with the GadgetBridge Android application * over BLE. * @version 0.1 * @date 2023-04-05 * * @copyright MIT * */ #include "gadget_bridge.h" #include #include #include #include "ble_service.h" #include "wm_mem.h" /* Internal enum definition */ typedef enum gadget_bridge_parser_fsm { GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE = 0, GADGET_BRIDGE_PARSER_FSM_FOUND_GB, GADGET_BRIDGE_PARSER_FSM_FOUND_NOTIFY, GADGET_BRIDGE_PARSER_FSM_FOUND_ID_BODY, GADGET_BRIDGE_PARSER_FSM_FOUND_SENDER, GADGET_BRIDGE_PARSER_FSM_FOUND_TEL, GADGET_BRIDGE_PARSER_FSM_FOUND_TITLE, GADGET_BRIDGE_PARSER_FSM_PARSING_TITLE_CONTENT, GADGET_BRIDGE_PARSER_FSM_FOUND_ID_SRC, GADGET_BRIDGE_PARSER_FSM_FOUND_SRC_BODY, GADGET_BRIDGE_PARSER_FSM_PARSING_BODY_CONTENT, GADGET_BRIDGE_PARSER_FSM_FOUND_CALL, GADGET_BRIDGE_PARSER_FSM_FOUND_NAME, GADGET_BRIDGE_PARSER_FSM_FOUND_NUMBER, GADGET_BRIDGE_PARSER_FSM_FOUND_WEATHER, GADGET_BRIDGE_PARSER_FSM_FOUND_TEMP, GADGET_BRIDGE_PARSER_FSM_FOUND_HUM, GADGET_BRIDGE_PARSER_FSM_FOUND_TXT, GADGET_BRIDGE_PARSER_FSM_FOUND_WIND, GADGET_BRIDGE_PARSER_FSM_FOUND_WINDDIR, GADGET_BRIDGE_PARSER_FSM_FOUND_LOC, GADGET_BRIDGE_PARSER_FSM_FOUND_FIND, GADGET_BRIDGE_PARSER_FSM_FOUND_ACT, GADGET_BRIDGE_PARSER_FSM_FOUND_STP, GADGET_BRIDGE_PARSER_FSM_FOUND_HRM_INT, GADGET_BRIDGE_PARSER_FSM_FOUND_MUSICSTATE, GADGET_BRIDGE_PARSER_FSM_FOUND_POSITION, GADGET_BRIDGE_PARSER_FSM_FOUND_SHUFFLE, GADGET_BRIDGE_PARSER_FSM_FOUND_REPEAT, GADGET_BRIDGE_PARSER_FSM_FOUND_MUSICINFO, GADGET_BRIDGE_PARSER_FSM_FOUND_TRACK, GADGET_BRIDGE_PARSER_FSM_FOUND_DURATION, GADGET_BRIDGE_PARSER_FSM_ERROR, } gadget_bridge_parser_fsm_e; /* Internal variable definition */ struct { char buffer[GADGET_BRIDGE_PARSER_BUFFER_SIZE + 1]; // The +1 is for the string termination character. uint16_t buffer_content_size; // Without counting the string termination character. gadget_bridge_parser_fsm_e gadget_bridge_parser_fsm; bool new_data; parser_event_callback_t parser_event_callback; gadget_bridge_event_data_t event_data; } _gadget_bridge_internals = { .buffer_content_size = 0, .gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE, .new_data = false, .parser_event_callback = NULL, .event_data = { .event_type = GADGET_BRIDGE_EVENT_TYPE_NONE}, }; time_t _unix_timestamp = 0; /* Internal function definition */ static const char *_gadget_bridge_toast_type_2_str(gadget_bridge_toast_type_e toast_type); static const char *_gadget_bridge_music_control_2_str(gadget_bridge_music_control_e music_control); static const char *_gadget_bridge_http_request_method_2_str(gadget_bridge_http_request_method_e http_request_method); static void _parser_free_buffer(uint16_t length); static void _free_event_data(void); bool gadget_bridge_send_toast(gadget_bridge_toast_type_e toast_type, const char *message) { if(!message || !strlen(message)) return true; bool to_return = true; to_return &= ble_service_send_nus_data((const uint8_t *)"{\"t\":\"", 6); to_return &= ble_service_send_nus_data((const uint8_t *)_gadget_bridge_toast_type_2_str(toast_type), strlen(_gadget_bridge_toast_type_2_str(toast_type))); to_return &= ble_service_send_nus_data((const uint8_t *)"\",\"msg\":\"", 9); to_return &= ble_service_send_nus_data((const uint8_t *)message, strlen(message)); to_return &= ble_service_send_nus_data((const uint8_t *)"\"} \n", 4); return to_return; } bool gadget_bridge_send_firmware_version(const char *fw1, const char *fw2) { if(!fw1 && !fw2) return true; bool to_return = true; to_return &= ble_service_send_nus_data((const uint8_t *)"{\"t\":\"ver\",\"fw1\":\"", 18); if(fw1) { to_return &= ble_service_send_nus_data((const uint8_t *)fw1, strlen(fw1)); } to_return &= ble_service_send_nus_data((const uint8_t *)"\",\"fw2\":\"", 9); if(fw2) { to_return &= ble_service_send_nus_data((const uint8_t *)fw2, strlen(fw2)); } to_return &= ble_service_send_nus_data((const uint8_t *)"\"} \n", 4); return to_return; } bool gadget_bridge_send_battery_status(uint8_t battery_level_in_percent, float battery_level_in_V, bool is_charging) { bool to_return = true; char num_2_str[30] = ""; to_return &= ble_service_send_nus_data((const uint8_t *)"{\"t\":\"status\",\"bat\":", 20); sprintf(num_2_str, "%u,\"chg\":%u,\"volt\":%.3f} \n", battery_level_in_percent, is_charging, battery_level_in_V); to_return &= ble_service_send_nus_data((const uint8_t *)num_2_str, strlen(num_2_str)); return to_return; } bool gadget_bridge_send_find_phone(bool find_phone) { bool to_return = true; to_return &= ble_service_send_nus_data((const uint8_t *)"{\"t\":\"findPhone\",\"n\":", 21); if(find_phone) to_return &= ble_service_send_nus_data((const uint8_t *)"true} \n", 7); else to_return &= ble_service_send_nus_data((const uint8_t *)"false} \n", 8); return to_return; } bool gadget_bridge_send_music_control(gadget_bridge_music_control_e music_control) { bool to_return = true; to_return &= ble_service_send_nus_data((const uint8_t *)"{\"t\":\"music\",\"n\":\"", 18); to_return &= ble_service_send_nus_data((const uint8_t *)_gadget_bridge_music_control_2_str(music_control), strlen(_gadget_bridge_music_control_2_str(music_control))); to_return &= ble_service_send_nus_data((const uint8_t *)"\"} \n", 4); return to_return; } bool gadget_bridge_send_activity_data(uint16_t heart_rate_in_bpm, uint32_t step_count) { bool to_return = true; char num_2_str[11] = ""; //{\"t\":\"act\",\"hrm\":%s,\"stp\":%s} \n to_return &= ble_service_send_nus_data((const uint8_t *)"{\"t\":\"act\",\"hrm\":", 17); sprintf(num_2_str, "%u", heart_rate_in_bpm); to_return &= ble_service_send_nus_data((const uint8_t *)num_2_str, strlen(num_2_str)); to_return &= ble_service_send_nus_data((const uint8_t *)",\"stp\":", 7); sprintf(num_2_str, "%u", step_count); to_return &= ble_service_send_nus_data((const uint8_t *)num_2_str, strlen(num_2_str)); to_return &= ble_service_send_nus_data((const uint8_t *)"} \n", 3); return to_return; } bool gadget_bridge_send_http_request(uint32_t id, const char *url, gadget_bridge_http_request_method_e http_request_method, const char *http_body, const http_header_t *http_headers) { bool to_return = true; char num_2_str[11] = ""; sprintf(num_2_str, "%u", id); to_return &= ble_service_send_nus_data((const uint8_t *)"{\"t\":\"http\",\"id\":\"", 18); to_return &= ble_service_send_nus_data((const uint8_t *)num_2_str, strlen(num_2_str)); to_return &= ble_service_send_nus_data((const uint8_t *)"\",\"url\":\"", 9); to_return &= ble_service_send_nus_data((const uint8_t *)url, strlen(url)); to_return &= ble_service_send_nus_data((const uint8_t *)"\",\"method\":\"", 12); to_return &= ble_service_send_nus_data((const uint8_t *)_gadget_bridge_http_request_method_2_str(http_request_method), strlen(_gadget_bridge_http_request_method_2_str(http_request_method))); to_return &= ble_service_send_nus_data((const uint8_t *)"\"} \n", 4); return to_return; } /*bool gadget_bridge_send_force_calendar_sync(void) { bool to_return = true; to_return &= ble_service_send_nus_data((const uint8_t *)"{\"t\":\"force_calendar_sync\"} \n", 29); return to_return; }*/ void gadget_bridge_parser_register_event_callback(parser_event_callback_t parser_event_callback) { _gadget_bridge_internals.parser_event_callback = parser_event_callback; } gadget_bridge_parser_code_e gadget_bridge_parser_feed(const char *data, uint16_t length) { // First we check if there is still space left in the parser buffer if(_gadget_bridge_internals.buffer_content_size >= GADGET_BRIDGE_PARSER_BUFFER_SIZE) return GADGET_BRIDGE_PARSER_CODE_BUFFER_FULL; // We check if the incoming data is not too long for the buffer if(_gadget_bridge_internals.buffer_content_size + length > GADGET_BRIDGE_PARSER_BUFFER_SIZE) return GADGET_BRIDGE_PARSER_CODE_DATA_TOO_LONG; strncat(_gadget_bridge_internals.buffer, data, length); _gadget_bridge_internals.buffer_content_size += length; _gadget_bridge_internals.new_data = true; return GADGET_BRIDGE_PARSER_CODE_OK; } static bool _parser_extract_time(char *start, char *end); static bool _parser_extract_handle(char *start, char *end); //static void _parser_extract_body(char *start, char *end); //static void _parser_extract_sender(char *start, char *end); //static void _parser_extract_tel(char *start, char *end); static void _parser_extract_src(char *start, char *end); static void _parser_extract_char_str(char *start, char *end, char **data); static void _parser_extract_cmd(char *start, char *end); static void _parser_extract_state(char *start, char *end); static bool _parser_extract_uint8_t(char *start, char *end, uint8_t *data); static bool _parser_extract_float(char *start, char *end, float *data); static bool _parser_extract_uint16_t(char *start, char *end, uint16_t *data); static bool _parser_extract_bool(char *start, char *end, bool *data); gadget_bridge_parser_code_e gadget_bridge_parser_run(void) { if(!_gadget_bridge_internals.new_data) return GADGET_BRIDGE_PARSER_CODE_OK; char *start = NULL, *end = NULL; bool free_some_space = false; gadget_bridge_parser_code_e to_return = GADGET_BRIDGE_PARSER_CODE_PARSING; switch(_gadget_bridge_internals.gadget_bridge_parser_fsm) { case GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE: if((start = strstr(_gadget_bridge_internals.buffer, "setTime(")) && (end = strstr(_gadget_bridge_internals.buffer, ");"))) { //printf("###Found setTime\n"); _parser_extract_time(start + 8, end); // We remove the parsed part from the buffer end += 2; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); } else if((start = strstr(_gadget_bridge_internals.buffer, "setTimeZone(")) && (end = strstr(_gadget_bridge_internals.buffer, ");"))) { //printf("###Found setTimeZone\n"); float time_zone = 0.0; if(_parser_extract_float(start + 12, end, &time_zone)) { _gadget_bridge_internals.event_data.event_type = GADGET_BRIDGE_EVENT_TYPE_SET_TIME; _gadget_bridge_internals.event_data.time.time_zone = time_zone; // Set the local time if(_unix_timestamp) { _unix_timestamp += _gadget_bridge_internals.event_data.time.time_zone*3600; _gadget_bridge_internals.event_data.time.local_time = *gmtime(&_unix_timestamp); } // If a callback was registered, we call it and pass the data to it if(_gadget_bridge_internals.parser_event_callback) { _gadget_bridge_internals.parser_event_callback(&_gadget_bridge_internals.event_data); } } // We remove the parsed part from the buffer end += 2; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) { //printf("###Found GB\n"); start += 3; _parser_free_buffer( start -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_GB; } else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else _gadget_bridge_internals.new_data = false; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_GB: if((start = strstr(_gadget_bridge_internals.buffer, "t:\"notify\","))) { //printf("###Found notify\n"); _gadget_bridge_internals.event_data.event_type = GADGET_BRIDGE_EVENT_TYPE_NOTIFY; // We remove the parsed part from the buffer start += 11; _parser_free_buffer( start -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_NOTIFY; } else if((start = strstr(_gadget_bridge_internals.buffer, "t:\"call\","))) { //printf("###Found call\n"); _gadget_bridge_internals.event_data.event_type = GADGET_BRIDGE_EVENT_TYPE_CALL; // We remove the parsed part from the buffer start += 9; _parser_free_buffer( start -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_CALL; } else if((start = strstr(_gadget_bridge_internals.buffer, "t:\"weather\","))) { //printf("###Found weather\n"); _gadget_bridge_internals.event_data.event_type = GADGET_BRIDGE_EVENT_TYPE_WEATHER; // We remove the parsed part from the buffer start += 12; _parser_free_buffer( start -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_WEATHER; } else if((start = strstr(_gadget_bridge_internals.buffer, "t:\"find\","))) { //printf("###Found find\n"); _gadget_bridge_internals.event_data.event_type = GADGET_BRIDGE_EVENT_TYPE_FIND; // We remove the parsed part from the buffer start += 9; _parser_free_buffer( start -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_FIND; } else if((start = strstr(_gadget_bridge_internals.buffer, "t:\"act\","))) { //printf("###Found act\n"); _gadget_bridge_internals.event_data.event_type = GADGET_BRIDGE_EVENT_TYPE_ACT; // We remove the parsed part from the buffer start += 8; _parser_free_buffer( start -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_ACT; } else if((start = strstr(_gadget_bridge_internals.buffer, "t:\"musicstate\","))) { //printf("###Found musicstate\n"); _gadget_bridge_internals.event_data.event_type = GADGET_BRIDGE_EVENT_TYPE_MUSIC_STATE; // We remove the parsed part from the buffer start += 15; _parser_free_buffer( start -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_MUSICSTATE; } else if((start = strstr(_gadget_bridge_internals.buffer, "t:\"musicinfo\","))) { //printf("###Found musicinfo\n"); _gadget_bridge_internals.event_data.event_type = GADGET_BRIDGE_EVENT_TYPE_MUSIC_INFO; // We remove the parsed part from the buffer start += 14; _parser_free_buffer( start -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_MUSICINFO; } // If we did not find the rest but found GB again, then some payload was lost... else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; // Here we parse the notify type of payloads case GADGET_BRIDGE_PARSER_FSM_FOUND_NOTIFY: if((start = strstr(_gadget_bridge_internals.buffer, "id:")) && (end = strstr(_gadget_bridge_internals.buffer, ",src"))) { //printf("###Found ID SRC\n"); _parser_extract_handle(start + 3, end); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_ID_SRC; } /*else if((start = strstr(_gadget_bridge_internals.buffer, "id:")) && (end = strstr(_gadget_bridge_internals.buffer, ",body"))) { printf("###Found ID BODY\n"); _parser_extract_handle(start + 3, end); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_ID_BODY; }*/ else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_ID_SRC: if((start = strstr(_gadget_bridge_internals.buffer, "src:")) && (end = strstr(_gadget_bridge_internals.buffer, ",title"))) { //printf("###Found TITLE\n"); _parser_extract_src(start + 5, end - 1); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_TITLE; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_TITLE: if((start = strstr(_gadget_bridge_internals.buffer, "title:"))) { //printf("###Parsing TITLE content\n"); // We remove the parsed part from the buffer start += 7; _parser_free_buffer( start -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_PARSING_TITLE_CONTENT; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_PARSING_TITLE_CONTENT: { end = strstr(_gadget_bridge_internals.buffer, ",body"); if(end) { //printf("###Found BODY\n"); _parser_extract_char_str(_gadget_bridge_internals.buffer, end - 1, &_gadget_bridge_internals.event_data.notification.title); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_SRC_BODY; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; // Then we have a very long title, in this case we juste keep the max set up else if(!end && _gadget_bridge_internals.buffer_content_size >= GADGET_BRIDGE_PARSER_MAX_TITLE_SIZE) { printf("###NOTIFICATION (MAX TITLE SIZE)\n"); _parser_extract_char_str(_gadget_bridge_internals.buffer, _gadget_bridge_internals.buffer + GADGET_BRIDGE_PARSER_MAX_TITLE_SIZE, &_gadget_bridge_internals.event_data.notification.title); // We remove the parsed part from the buffer _parser_free_buffer( GADGET_BRIDGE_PARSER_MAX_TITLE_SIZE+1 ); // The end of the road for this object _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_SRC_BODY; } else to_return = GADGET_BRIDGE_PARSER_CODE_OK; } break; case GADGET_BRIDGE_PARSER_FSM_FOUND_SRC_BODY: if((start = strstr(_gadget_bridge_internals.buffer, "body:"))) { //printf("###Parsing BODY content\n"); // We remove the : "body":" part start += 6; _parser_free_buffer( start -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_PARSING_BODY_CONTENT; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_PARSING_BODY_CONTENT: { end = strstr(_gadget_bridge_internals.buffer, "})"); if(end) { //printf("###NOTIFICATION Type done\n"); _parser_extract_char_str(_gadget_bridge_internals.buffer, end - 1, &_gadget_bridge_internals.event_data.notification.body); // We remove the parsed part from the buffer end += 2; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); // If a callback was registered, we call it and pass the data to it if(_gadget_bridge_internals.parser_event_callback) { _gadget_bridge_internals.parser_event_callback(&_gadget_bridge_internals.event_data); } // Free the allocated data _free_event_data(); // The end of the road for this object _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; // Then we have a very long body, in this case we juste keep the max set up else if(!end && _gadget_bridge_internals.buffer_content_size >= GADGET_BRIDGE_PARSER_MAX_BODY_SIZE) { //printf("###NOTIFICATION (MAX BODY SIZE) Type done\n"); _parser_extract_char_str(_gadget_bridge_internals.buffer, _gadget_bridge_internals.buffer + GADGET_BRIDGE_PARSER_MAX_BODY_SIZE, &_gadget_bridge_internals.event_data.notification.body); // We remove the parsed part from the buffer _parser_free_buffer( GADGET_BRIDGE_PARSER_MAX_BODY_SIZE + 1 ); // If a callback was registered, we call it and pass the data to it if(_gadget_bridge_internals.parser_event_callback) { _gadget_bridge_internals.parser_event_callback(&_gadget_bridge_internals.event_data); } // Free the allocated data _free_event_data(); // The end of the road for this object _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; } else to_return = GADGET_BRIDGE_PARSER_CODE_OK; } break; /*case GADGET_BRIDGE_PARSER_FSM_FOUND_ID_BODY: if((start = strstr(_gadget_bridge_internals.buffer, "body:")) && (end = strstr(_gadget_bridge_internals.buffer, ",sender"))) { printf("###Found SENDER\n"); _parser_extract_body(start + 6, end - 1); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_SENDER; } else _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_SENDER: if((start = strstr(_gadget_bridge_internals.buffer, "sender:")) && (end = strstr(_gadget_bridge_internals.buffer, ",tel"))) { printf("###Found TEL\n"); _parser_extract_sender(start + 8, end - 1); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_TEL; } else _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_TEL: if((start = strstr(_gadget_bridge_internals.buffer, "tel:")) && (end = strstr(_gadget_bridge_internals.buffer, "})"))) { printf("###SMS Type one done\n"); _parser_extract_tel(start + 5, end - 1); // We remove the parsed part from the buffer end += 2; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); // If a callback was registered, we call it and pass the data to it if(_gadget_bridge_internals.parser_event_callback) _gadget_bridge_internals.parser_event_callback(&_gadget_bridge_internals.event_data); // The end of the road for this object } _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; break;*/ case GADGET_BRIDGE_PARSER_FSM_FOUND_CALL: if((start = strstr(_gadget_bridge_internals.buffer, "cmd:")) && (end = strstr(_gadget_bridge_internals.buffer, ",name"))) { //printf("###Found NAME\n"); _parser_extract_cmd(start + 5, end - 1); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_NAME; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_NAME: if((start = strstr(_gadget_bridge_internals.buffer, "name:")) && (end = strstr(_gadget_bridge_internals.buffer, ",number"))) { //printf("###Found NUMBER\n"); _parser_extract_char_str(start + 6, end - 1, &_gadget_bridge_internals.event_data.call.contact); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_NUMBER; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_NUMBER: if((start = strstr(_gadget_bridge_internals.buffer, "number:")) && (end = strstr(_gadget_bridge_internals.buffer, "})"))) { //printf("###CALL Type done\n"); _parser_extract_char_str(start + 8, end - 1, &_gadget_bridge_internals.event_data.call.phone_number); // We remove the parsed part from the buffer end += 2; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); // If a callback was registered, we call it and pass the data to it if(_gadget_bridge_internals.parser_event_callback) { _gadget_bridge_internals.parser_event_callback(&_gadget_bridge_internals.event_data); } // Free the allocated data _free_event_data(); // The end of the road for this object _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_WEATHER: if((start = strstr(_gadget_bridge_internals.buffer, "temp:")) && (end = strstr(_gadget_bridge_internals.buffer, ",hum"))) { //printf("###Found HUM\n"); _parser_extract_float(start + 5, end, &_gadget_bridge_internals.event_data.weather.temperature_celsius); // Do get °C instead of kelvins _gadget_bridge_internals.event_data.weather.temperature_celsius += -273.15; // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_HUM; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_HUM: if((start = strstr(_gadget_bridge_internals.buffer, "hum:")) && (end = strstr(_gadget_bridge_internals.buffer, ",code"))) { // We don't care about code... //printf("###Found TXT\n"); _parser_extract_uint8_t(start + 4, end, &_gadget_bridge_internals.event_data.weather.humidity); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_TXT; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_TXT: if((start = strstr(_gadget_bridge_internals.buffer, "txt:")) && (end = strstr(_gadget_bridge_internals.buffer, ",wind"))) { // We don't care about code... //printf("###Found WIND\n"); _parser_extract_char_str(start + 5, end - 1, &_gadget_bridge_internals.event_data.weather.weather_desc); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_WIND; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_WIND: if((start = strstr(_gadget_bridge_internals.buffer, "wind:")) && (end = strstr(_gadget_bridge_internals.buffer, ",wdir"))) { // We don't care about code... //printf("###Found WIND DIR\n"); _parser_extract_float(start + 5, end, &_gadget_bridge_internals.event_data.weather.wind_speed_kmh); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_WINDDIR; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_WINDDIR: if((start = strstr(_gadget_bridge_internals.buffer, "wdir:")) && (end = strstr(_gadget_bridge_internals.buffer, ",loc"))) { // We don't care about code... //printf("###Found LOC\n"); _parser_extract_uint16_t(start + 5, end, &_gadget_bridge_internals.event_data.weather.wind_dir); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_LOC; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_LOC: if((start = strstr(_gadget_bridge_internals.buffer, "loc:")) && (end = strstr(_gadget_bridge_internals.buffer, "})"))) { //printf("###WEATHER Type done\n"); _parser_extract_char_str(start + 5, end - 1, &_gadget_bridge_internals.event_data.weather.location); // We remove the parsed part from the buffer end += 2; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); // If a callback was registered, we call it and pass the data to it if(_gadget_bridge_internals.parser_event_callback) { _gadget_bridge_internals.parser_event_callback(&_gadget_bridge_internals.event_data); } // Free the allocated data _free_event_data(); // The end of the road for this object _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_FIND: if((start = strstr(_gadget_bridge_internals.buffer, "n:")) && (end = strstr(_gadget_bridge_internals.buffer, "})"))) { //printf("###FIND Type done\n"); _parser_extract_bool(start + 2, end, &_gadget_bridge_internals.event_data.find.find); // We remove the parsed part from the buffer end += 2; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); // If a callback was registered, we call it and pass the data to it if(_gadget_bridge_internals.parser_event_callback) { _gadget_bridge_internals.parser_event_callback(&_gadget_bridge_internals.event_data); } // The end of the road for this object _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_ACT: if((start = strstr(_gadget_bridge_internals.buffer, "hrm:")) && (end = strstr(_gadget_bridge_internals.buffer, ",stp"))) { //printf("###Found STP\n"); _parser_extract_bool(start + 4, end, &_gadget_bridge_internals.event_data.act.heart_rate_monitor); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_STP; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_STP: if((start = strstr(_gadget_bridge_internals.buffer, "stp:")) && (end = strstr(_gadget_bridge_internals.buffer, ",int"))) { //printf("###Found INT\n"); _parser_extract_bool(start + 4, end, &_gadget_bridge_internals.event_data.act.steps); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_HRM_INT; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_HRM_INT: if((start = strstr(_gadget_bridge_internals.buffer, "int:")) && (end = strstr(_gadget_bridge_internals.buffer, "})"))) { //printf("###ACT Type done\n"); _parser_extract_uint8_t(start + 4, end, &_gadget_bridge_internals.event_data.act.heart_rate_interval); // We remove the parsed part from the buffer end += 2; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); // If a callback was registered, we call it and pass the data to it if(_gadget_bridge_internals.parser_event_callback) { _gadget_bridge_internals.parser_event_callback(&_gadget_bridge_internals.event_data); } // The end of the road for this object _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_MUSICSTATE: if((start = strstr(_gadget_bridge_internals.buffer, "state:")) && (end = strstr(_gadget_bridge_internals.buffer, ",position"))) { //printf("###Found POSITION\n"); _parser_extract_state(start + 7, end - 1); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_POSITION; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_POSITION: if((start = strstr(_gadget_bridge_internals.buffer, "position:")) && (end = strstr(_gadget_bridge_internals.buffer, ",shuffle"))) { //printf("###Found SHUFFLE\n"); _parser_extract_uint16_t(start + 9, end, &_gadget_bridge_internals.event_data.music_state.position_in_seconds); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_SHUFFLE; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_SHUFFLE: if((start = strstr(_gadget_bridge_internals.buffer, "shuffle:")) && (end = strstr(_gadget_bridge_internals.buffer, ",repeat"))) { //printf("###Found REPEAT\n"); _parser_extract_uint8_t(start + 8, end, &_gadget_bridge_internals.event_data.music_state.shuffle); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_REPEAT; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_REPEAT: if((start = strstr(_gadget_bridge_internals.buffer, "repeat:")) && (end = strstr(_gadget_bridge_internals.buffer, "})"))) { //printf("###MUSICSTATE Type done\n"); _parser_extract_uint8_t(start + 7, end, &_gadget_bridge_internals.event_data.music_state.repeat); // We remove the parsed part from the buffer end += 2; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); // If a callback was registered, we call it and pass the data to it if(_gadget_bridge_internals.parser_event_callback) { _gadget_bridge_internals.parser_event_callback(&_gadget_bridge_internals.event_data); } // The end of the road for this object _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_MUSICINFO: if((start = strstr(_gadget_bridge_internals.buffer, "artist:")) && (end = strstr(_gadget_bridge_internals.buffer, ",track"))) { //printf("###Found TRACK\n"); _parser_extract_char_str(start + 8, end - 1, &_gadget_bridge_internals.event_data.music_info.artist); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_TRACK; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_TRACK: if((start = strstr(_gadget_bridge_internals.buffer, "track:")) && (end = strstr(_gadget_bridge_internals.buffer, ",dur"))) { //printf("###Found DURATION\n"); _parser_extract_char_str(start + 7, end - 1, &_gadget_bridge_internals.event_data.music_info.track); // We remove the parsed part from the buffer end += 1; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_DURATION; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_FOUND_DURATION: if((start = strstr(_gadget_bridge_internals.buffer, "dur:")) && (end = strstr(_gadget_bridge_internals.buffer, ",c"))) { //printf("###MUSICINFO Type done\n"); _parser_extract_uint16_t(start + 4, end, &_gadget_bridge_internals.event_data.music_info.duration_in_seconds); // We remove the parsed part from the buffer end += 2; _parser_free_buffer( end -_gadget_bridge_internals.buffer ); // If a callback was registered, we call it and pass the data to it if(_gadget_bridge_internals.parser_event_callback) { _gadget_bridge_internals.parser_event_callback(&_gadget_bridge_internals.event_data); } // Free the allocated data _free_event_data(); // The end of the road for this object _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; } else if((start = strstr(_gadget_bridge_internals.buffer, "GB("))) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; else if(_gadget_bridge_internals.buffer_content_size > GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD) free_some_space = true; else to_return = GADGET_BRIDGE_PARSER_CODE_OK; break; case GADGET_BRIDGE_PARSER_FSM_ERROR: //printf("###Parser error\n"); default: _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; } if(free_some_space) { //printf("###Freeing some space\n"); uint16_t free_buffer_from_size = _gadget_bridge_internals.buffer_content_size - GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD; _parser_free_buffer(free_buffer_from_size); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; } return to_return; } #ifndef CASE_RETURN_STR #define CASE_RETURN_STR(const) case const: return #const; #endif const char *gadget_bridge_parser_code_2_str(gadget_bridge_parser_code_e parser_code) { switch(parser_code) { CASE_RETURN_STR(GADGET_BRIDGE_PARSER_CODE_OK) CASE_RETURN_STR(GADGET_BRIDGE_PARSER_CODE_PARSING) CASE_RETURN_STR(GADGET_BRIDGE_PARSER_CODE_BUFFER_FULL) CASE_RETURN_STR(GADGET_BRIDGE_PARSER_CODE_DATA_TOO_LONG) default: return "Unknown parser code"; } } const char *gadget_bridge_event_type_2_str(gadget_bridge_event_type_e event_type) { switch(event_type) { CASE_RETURN_STR(GADGET_BRIDGE_EVENT_TYPE_NONE) CASE_RETURN_STR(GADGET_BRIDGE_EVENT_TYPE_SET_TIME) CASE_RETURN_STR(GADGET_BRIDGE_EVENT_TYPE_NOTIFY) CASE_RETURN_STR(GADGET_BRIDGE_EVENT_TYPE_CALL) CASE_RETURN_STR(GADGET_BRIDGE_EVENT_TYPE_WEATHER) CASE_RETURN_STR(GADGET_BRIDGE_EVENT_TYPE_FIND) CASE_RETURN_STR(GADGET_BRIDGE_EVENT_TYPE_ACT) CASE_RETURN_STR(GADGET_BRIDGE_EVENT_TYPE_MUSIC_INFO) CASE_RETURN_STR(GADGET_BRIDGE_EVENT_TYPE_MUSIC_STATE) default: return "Unknown event type"; } } const char *gadget_bridge_notification_type_2_str(gadget_bridge_notification_type_e notification_type) { switch(notification_type) { CASE_RETURN_STR(GADGET_BRIDGE_NOTIFICATION_TYPE_SMS) CASE_RETURN_STR(GADGET_BRIDGE_NOTIFICATION_TYPE_EMAIL) CASE_RETURN_STR(GADGET_BRIDGE_NOTIFICATION_TYPE_UNKNOWN) default: return "Unknown notification type"; } } const char *gadget_bridge_music_state_2_str(gadget_bridge_music_state_e music_state) { switch(music_state) { CASE_RETURN_STR(GADGET_BRIDGE_MUSIC_STATE_PAUSE) CASE_RETURN_STR(GADGET_BRIDGE_MUSIC_STATE_PLAY) CASE_RETURN_STR(GADGET_BRIDGE_MUSIC_STATE_UNKNOWN) default: return "Unknown music state"; } } void gadget_bridge_parser_debug(void) { //printf("Buffer size : %u\nBuffer content : #%s#\n", _gadget_bridge_internals.buffer_content_size, _gadget_bridge_internals.buffer); } /* Internal function declaration */ static const char *_gadget_bridge_toast_type_2_str(gadget_bridge_toast_type_e toast_type) { switch(toast_type) { case GADGET_BRIDGE_TOAST_TYPE_ERROR: return "error"; case GADGET_BRIDGE_TOAST_TYPE_WARN: return "warn"; case GADGET_BRIDGE_TOAST_TYPE_INFO: default: return "info"; } } static const char *_gadget_bridge_music_control_2_str(gadget_bridge_music_control_e music_control) { switch(music_control) { case GADGET_BRIDGE_MUSIC_CONTROL_PLAY: return "play"; case GADGET_BRIDGE_MUSIC_CONTROL_PLAYPAUSE: return "playpause"; case GADGET_BRIDGE_MUSIC_CONTROL_NEXT: return "next"; case GADGET_BRIDGE_MUSIC_CONTROL_PREVIOUS: return "previous"; case GADGET_BRIDGE_MUSIC_CONTROL_VOLUMEUP: return "volumeup"; case GADGET_BRIDGE_MUSIC_CONTROL_VOLUMEDOWN: return "volumedown"; case GADGET_BRIDGE_MUSIC_CONTROL_FORWARD: return "forward"; case GADGET_BRIDGE_MUSIC_CONTROL_REWIND: return "rewind"; case GADGET_BRIDGE_MUSIC_CONTROL_PAUSE: default : return "pause"; } } static const char *_gadget_bridge_http_request_method_2_str(gadget_bridge_http_request_method_e http_request_method) { switch(http_request_method) { case GADGET_BRIDGE_HTTP_REQUEST_POST: return "post"; case GADGET_BRIDGE_HTTP_REQUEST_HEAD: return "head"; case GADGET_BRIDGE_HTTP_REQUEST_PUT: return "put"; case GADGET_BRIDGE_HTTP_REQUEST_PATCH: return "patch"; case GADGET_BRIDGE_HTTP_REQUEST_DELETE: return "delete"; case GADGET_BRIDGE_HTTP_REQUEST_GET: default: return "get"; } } static bool _parser_extract_time(char *start, char *end) { *end = '\0'; char *is_valid = NULL; _unix_timestamp = strtoul(start, &is_valid, 10); // We set the type of the data and its content _gadget_bridge_internals.event_data.event_type = GADGET_BRIDGE_EVENT_TYPE_SET_TIME; // Turn the timestamp into a date and time _gadget_bridge_internals.event_data.time.gm_time = *gmtime(&_unix_timestamp); return *is_valid == '\0'; } static bool _parser_extract_handle(char *start, char *end) { *end = '\0'; char *is_valid = NULL; uint32_t handle = strtoul(start, &is_valid, 10); // We set the type of the data and its content _gadget_bridge_internals.event_data.notification.handle = handle; //printf("###Extracted handle : %u\n", handle); return *is_valid == '\0'; } static bool _parser_extract_uint8_t(char *start, char *end, uint8_t *data) { *end = '\0'; char *is_valid = NULL; *data = strtoul(start, &is_valid, 10); //printf("###Extracted uint8_t : %u\n", *data); return *is_valid == '\0'; } static bool _parser_extract_float(char *start, char *end, float *data) { *end = '\0'; char *is_valid = NULL; *data = strtof(start, &is_valid); //printf("###Extracted float : %.2f\n", *data); return *is_valid == '\0'; } static bool _parser_extract_uint16_t(char *start, char *end, uint16_t *data) { *end = '\0'; char *is_valid = NULL; *data = strtoul(start, &is_valid, 10); //printf("###Extracted uint16_t : %u\n", *data); return *is_valid == '\0'; } /*static void _parser_extract_body(char *start, char *end) { *end = '\0'; _gadget_bridge_internals.event_data.sms.body = strdup(start); _gadget_bridge_internals.event_data.event_type = GADGET_BRIDGE_EVENT_TYPE_SMS; printf("###Extracted body : %s\n", _gadget_bridge_internals.event_data.sms.body); } static void _parser_extract_sender(char *start, char *end) { *end = '\0'; _gadget_bridge_internals.event_data.sms.contact = strdup(start); printf("###Extracted sender : %s\n", _gadget_bridge_internals.event_data.sms.contact); } static void _parser_extract_tel(char *start, char *end) { *end = '\0'; _gadget_bridge_internals.event_data.sms.phone_number = strdup(start); printf("###Extracted tel : %s\n", _gadget_bridge_internals.event_data.sms.phone_number); }*/ static void _parser_extract_src(char *start, char *end) { *end = '\0'; if(strcmp(start, "Messages") == 0) _gadget_bridge_internals.event_data.notification.notification_type = GADGET_BRIDGE_NOTIFICATION_TYPE_SMS; else if(strcmp(start, "E-mail") == 0) _gadget_bridge_internals.event_data.notification.notification_type = GADGET_BRIDGE_NOTIFICATION_TYPE_EMAIL; else _gadget_bridge_internals.event_data.notification.notification_type = GADGET_BRIDGE_NOTIFICATION_TYPE_UNKNOWN; //printf("###Source is : %s\n", start); } static void _parser_extract_char_str(char *start, char *end, char **data) { *end = '\0'; *data = strdup(start); //printf("###Extracted char str : #%s#\n", *data); } static void _parser_extract_cmd(char *start, char *end) { *end = '\0'; if(strcmp(start, "incoming") == 0) _gadget_bridge_internals.event_data.call.call_action = GADGET_BRIDGE_CALL_ACTION_INCOMING; else if(strcmp(start, "end") == 0) _gadget_bridge_internals.event_data.call.call_action = GADGET_BRIDGE_CALL_ACTION_END; else _gadget_bridge_internals.event_data.call.call_action = GADGET_BRIDGE_CALL_ACTION_UNKNOWN; //printf("###Commande is : %s\n", start); } static void _parser_extract_state(char *start, char *end) { *end = '\0'; if(strcmp(start, "play") == 0) _gadget_bridge_internals.event_data.music_state.music_state = GADGET_BRIDGE_MUSIC_STATE_PLAY; else if(strcmp(start, "pause") == 0) _gadget_bridge_internals.event_data.music_state.music_state = GADGET_BRIDGE_MUSIC_STATE_PAUSE; else _gadget_bridge_internals.event_data.music_state.music_state = GADGET_BRIDGE_MUSIC_STATE_UNKNOWN; //printf("###State is : %s\n", start); } static bool _parser_extract_bool(char *start, char *end, bool *data) { *end = '\0'; if(strcmp(start, "true") == 0) *data = true; else if(strcmp(start, "false") == 0) *data = false; else return false; //printf("###Extracted bool : %s\n", *data ? "true" : "false"); return true; } static void _parser_free_buffer(uint16_t length) { length = length > _gadget_bridge_internals.buffer_content_size ? _gadget_bridge_internals.buffer_content_size : length; memmove(_gadget_bridge_internals.buffer, _gadget_bridge_internals.buffer + length, _gadget_bridge_internals.buffer_content_size - length + 1); // +1 to include \0 _gadget_bridge_internals.buffer_content_size -= length; } static void _free_event_data(void) { switch(_gadget_bridge_internals.event_data.event_type) { case GADGET_BRIDGE_EVENT_TYPE_NOTIFY: tls_mem_free(_gadget_bridge_internals.event_data.notification.title); _gadget_bridge_internals.event_data.notification.title = NULL; tls_mem_free(_gadget_bridge_internals.event_data.notification.body); _gadget_bridge_internals.event_data.notification.body = NULL; break; case GADGET_BRIDGE_EVENT_TYPE_CALL: tls_mem_free(_gadget_bridge_internals.event_data.call.phone_number); _gadget_bridge_internals.event_data.call.phone_number = NULL; tls_mem_free(_gadget_bridge_internals.event_data.call.contact); _gadget_bridge_internals.event_data.call.contact = NULL; break; case GADGET_BRIDGE_EVENT_TYPE_WEATHER: tls_mem_free(_gadget_bridge_internals.event_data.weather.location); _gadget_bridge_internals.event_data.weather.location = NULL; tls_mem_free(_gadget_bridge_internals.event_data.weather.weather_desc); _gadget_bridge_internals.event_data.weather.weather_desc = NULL; break; case GADGET_BRIDGE_EVENT_TYPE_MUSIC_INFO: tls_mem_free(_gadget_bridge_internals.event_data.music_info.artist); _gadget_bridge_internals.event_data.music_info.artist = NULL; tls_mem_free(_gadget_bridge_internals.event_data.music_info.track); _gadget_bridge_internals.event_data.music_info.track = NULL; break; default: break; } }