From 5206181a32b09814d7f60611e046650a4a716e9e Mon Sep 17 00:00:00 2001 From: Th3maz1ng Date: Sun, 9 Apr 2023 17:03:53 +0200 Subject: [PATCH] Fixed potential memory leak, added the music state and music info events type --- app/ble/gadget_bridge.c | 254 +++++++++++++++++++++++++++++++++++++-- app/ble/gadget_bridge.h | 24 ++++ app/nano_shell_command.c | 25 +++- 3 files changed, 291 insertions(+), 12 deletions(-) diff --git a/app/ble/gadget_bridge.c b/app/ble/gadget_bridge.c index 930ea30..b8caa7f 100644 --- a/app/ble/gadget_bridge.c +++ b/app/ble/gadget_bridge.c @@ -49,10 +49,18 @@ typedef enum gadget_bridge_parser_fsm GADGET_BRIDGE_PARSER_FSM_FOUND_FIND, GADGET_BRIDGE_PARSER_FSM_FOUND_ACT, - GADGET_BRIDGE_PARSER_FSM_FOUND_HRM, 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; @@ -226,6 +234,7 @@ static bool _parser_extract_handle(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); @@ -352,7 +361,29 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) ); _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_ACT; } - // If we did not find the rest but found GB again, the some payload was lost... + 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) @@ -472,7 +503,7 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) case GADGET_BRIDGE_PARSER_FSM_FOUND_SRC_BODY: if((start = strstr(_gadget_bridge_internals.buffer, "body:"))) { - //printf("###Parsing body content\n"); + //printf("###Parsing BODY content\n"); // We remove the : "body":" part start += 6; @@ -506,9 +537,11 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) 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(); } + + // 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; } @@ -530,9 +563,11 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) 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(); } + + // 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; } @@ -653,9 +688,11 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) 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(); } + + // 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; } @@ -788,9 +825,11 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) 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(); } + + // 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; } @@ -895,6 +934,165 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) 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: @@ -940,6 +1138,8 @@ const char *gadget_bridge_event_type_2_str(gadget_bridge_event_type_e event_type 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"; } @@ -957,6 +1157,18 @@ const char *gadget_bridge_notification_type_2_str(gadget_bridge_notification_typ } } +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); @@ -1142,6 +1354,20 @@ static void _parser_extract_cmd(char *start, char *end) //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'; @@ -1186,6 +1412,12 @@ static void _free_event_data(void) 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; } diff --git a/app/ble/gadget_bridge.h b/app/ble/gadget_bridge.h index d548f57..cc45711 100644 --- a/app/ble/gadget_bridge.h +++ b/app/ble/gadget_bridge.h @@ -120,6 +120,8 @@ typedef enum gadget_bridge_event_type GADGET_BRIDGE_EVENT_TYPE_WEATHER, GADGET_BRIDGE_EVENT_TYPE_FIND, GADGET_BRIDGE_EVENT_TYPE_ACT, + GADGET_BRIDGE_EVENT_TYPE_MUSIC_INFO, + GADGET_BRIDGE_EVENT_TYPE_MUSIC_STATE, GADGET_BRIDGE_EVENT_TYPE_UNKNOWN, } gadget_bridge_event_type_e; @@ -130,6 +132,13 @@ typedef enum gadget_bridge_notification_type GADGET_BRIDGE_NOTIFICATION_TYPE_UNKNOWN, } gadget_bridge_notification_type_e; +typedef enum +{ + GADGET_BRIDGE_MUSIC_STATE_PAUSE = 0, + GADGET_BRIDGE_MUSIC_STATE_PLAY, + GADGET_BRIDGE_MUSIC_STATE_UNKNOWN, +} gadget_bridge_music_state_e; + typedef struct gadget_bridge_event_data { gadget_bridge_event_type_e event_type; @@ -173,6 +182,19 @@ typedef struct gadget_bridge_event_data bool steps; uint8_t heart_rate_interval; } act; + struct + { + gadget_bridge_music_state_e music_state; + uint16_t position_in_seconds; + uint8_t shuffle; + uint8_t repeat; + } music_state; + struct + { + char *artist; + char *track; + uint16_t duration_in_seconds; + } music_info; }; } gadget_bridge_event_data_t; @@ -292,6 +314,8 @@ const char *gadget_bridge_event_type_2_str(gadget_bridge_event_type_e event_type const char *gadget_bridge_notification_type_2_str(gadget_bridge_notification_type_e notification_type); +const char *gadget_bridge_music_state_2_str(gadget_bridge_music_state_e music_state); + void gadget_bridge_parser_debug(void); #endif //GADGET_BRIDGE_H diff --git a/app/nano_shell_command.c b/app/nano_shell_command.c index ab6aa3d..82e2742 100644 --- a/app/nano_shell_command.c +++ b/app/nano_shell_command.c @@ -147,6 +147,19 @@ static void parser_event_cb(const gadget_bridge_event_data_t *gadget_bridge_even gadget_bridge_event_data->act.steps, gadget_bridge_event_data->act.heart_rate_interval); break; + case GADGET_BRIDGE_EVENT_TYPE_MUSIC_STATE: + shell_printf("%s\n%u\n%u\n%u\n", + gadget_bridge_music_state_2_str(gadget_bridge_event_data->music_state.music_state), + gadget_bridge_event_data->music_state.position_in_seconds, + gadget_bridge_event_data->music_state.shuffle, + gadget_bridge_event_data->music_state.repeat); + break; + case GADGET_BRIDGE_EVENT_TYPE_MUSIC_INFO: + shell_printf("%s\n%s\n%u\n", + gadget_bridge_event_data->music_info.artist, + gadget_bridge_event_data->music_info.track, + gadget_bridge_event_data->music_info.duration_in_seconds); + break; default: shell_printf("Unhandled\n"); } @@ -748,10 +761,20 @@ int _bluetooth(const shell_cmd_t *pcmd, int argc, char *const argv[]) { to_return = gadget_bridge_send_activity_data(atoi(argv[3]), atoi(argv[4])); } + /*else if(strcmp(argv[2], "calendar") == 0 && argc == 3) + { + to_return = gadget_bridge_send_force_calendar_sync(); + }*/ + else if(strcmp(argv[2], "http") == 0 && argc == 6) + { + to_return = gadget_bridge_send_http_request(atoi(argv[3]), argv[4], GADGET_BRIDGE_HTTP_REQUEST_GET, NULL, NULL); + } else { shell_printf("Unknown %s action, list of send_ble_notif actions :"NEW_LINE"toast info|warn|error \"msg\""NEW_LINE"bat \"XX%%\" 1|0 X.X"NEW_LINE"find_phone true|false"NEW_LINE"music play|pause|playpause|previous|next|volumeup|volumedown|forward|rewind"NEW_LINE"notify reply|dismiss_all id \"tel\" \"msg\""NEW_LINE - "act hrm steps"NEW_LINE, argv[2]); + "act hrm steps"NEW_LINE + "ver \"version 1\" \"version 2\""NEW_LINE + , argv[2]); } shell_printf("Sending ble ntf : %d"NEW_LINE, to_return);