From b45c5fdcbfd9cfe242858b0f5d21fc6999e46203 Mon Sep 17 00:00:00 2001 From: Th3maz1ng Date: Sun, 23 Apr 2023 20:27:29 +0200 Subject: [PATCH] Updated the Gadget Bridge parser to parse debug frames needed when implementing the notification manager --- src/gadget_bridge_parser/gadget_bridge.c | 106 +++++++++++++++++- src/gadget_bridge_parser/gadget_bridge.h | 31 ++--- .../gadget_bridge_parser.depend | 17 +++ src/gadget_bridge_parser/main.c | 30 ++++- 4 files changed, 159 insertions(+), 25 deletions(-) diff --git a/src/gadget_bridge_parser/gadget_bridge.c b/src/gadget_bridge_parser/gadget_bridge.c index ec1186e..86233a3 100644 --- a/src/gadget_bridge_parser/gadget_bridge.c +++ b/src/gadget_bridge_parser/gadget_bridge.c @@ -34,6 +34,9 @@ typedef enum gadget_bridge_parser_fsm GADGET_BRIDGE_PARSER_FSM_FOUND_TITLE, GADGET_BRIDGE_PARSER_FSM_PARSING_TITLE_CONTENT, + GADGET_BRIDGE_PARSER_FSM_FOUND_SUBJECT, + GADGET_BRIDGE_PARSER_FSM_PARSING_SUBJECT_BODY_CONTENT, + GADGET_BRIDGE_PARSER_FSM_FOUND_ID_SRC, GADGET_BRIDGE_PARSER_FSM_FOUND_SRC_BODY, GADGET_BRIDGE_PARSER_FSM_PARSING_BODY_CONTENT, @@ -239,7 +242,7 @@ 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; + char *start = NULL, *end = NULL, *end2 = NULL; // end2 is used when more than one next tag is possible bool free_some_space = false; gadget_bridge_parser_code_e to_return = GADGET_BRIDGE_PARSER_CODE_PARSING; @@ -419,10 +422,20 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) 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"))) + if((start = strstr(_gadget_bridge_internals.buffer, "src:")) && + ((end = strstr(_gadget_bridge_internals.buffer, ",title")) || (end2 = strstr(_gadget_bridge_internals.buffer, ",subject")))) { - printf("###Found TITLE\n"); + if((end && !end2) || (end != NULL && end < end2)) + { + printf("###Found TITLE\n"); + _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_TITLE; + } + else if((!end && end2) || (end2 != NULL && end2 < end)) + { + printf("###Found SUBJECT\n"); + end = end2; + _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_FOUND_SUBJECT; + } _parser_extract_src(start + 5, end - 1); @@ -431,7 +444,6 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) _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; @@ -503,7 +515,11 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) _parser_free_buffer( start -_gadget_bridge_internals.buffer ); - _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_PARSING_BODY_CONTENT; + + if(_gadget_bridge_internals.event_data.notification.notification_type == GADGET_BRIDGE_NOTIFICATION_TYPE_GADGET_BRIDGE) + _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_PARSING_SUBJECT_BODY_CONTENT; + else + _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; @@ -567,6 +583,63 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) else to_return = GADGET_BRIDGE_PARSER_CODE_OK; } break; + case GADGET_BRIDGE_PARSER_FSM_PARSING_SUBJECT_BODY_CONTENT: + { + end = strstr(_gadget_bridge_internals.buffer, ",sender"); + if(end) + { + // We don't care about the sender nor the tel tag + printf("###TEST 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 += 7; + _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("###TEST 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"))) @@ -624,6 +697,24 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void) _gadget_bridge_internals.gadget_bridge_parser_fsm = GADGET_BRIDGE_PARSER_FSM_NEW_MESSAGE; break;*/ + case GADGET_BRIDGE_PARSER_FSM_FOUND_SUBJECT: + if((start = strstr(_gadget_bridge_internals.buffer, "subject:"))) + { + printf("###Parsing SUBJECT content\n"); + + // 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_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_FOUND_CALL: if((start = strstr(_gadget_bridge_internals.buffer, "cmd:")) && (end = strstr(_gadget_bridge_internals.buffer, ",name"))) @@ -1144,6 +1235,7 @@ const char *gadget_bridge_notification_type_2_str(gadget_bridge_notification_typ { CASE_RETURN_STR(GADGET_BRIDGE_NOTIFICATION_TYPE_SMS) CASE_RETURN_STR(GADGET_BRIDGE_NOTIFICATION_TYPE_EMAIL) + CASE_RETURN_STR(GADGET_BRIDGE_NOTIFICATION_TYPE_GADGET_BRIDGE) CASE_RETURN_STR(GADGET_BRIDGE_NOTIFICATION_TYPE_UNKNOWN) default: return "Unknown notification type"; @@ -1319,6 +1411,8 @@ static void _parser_extract_src(char *start, char *end) _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 if(strcmp(start, "Gadgetbridge") == 0) + _gadget_bridge_internals.event_data.notification.notification_type = GADGET_BRIDGE_NOTIFICATION_TYPE_GADGET_BRIDGE; else _gadget_bridge_internals.event_data.notification.notification_type = GADGET_BRIDGE_NOTIFICATION_TYPE_UNKNOWN; diff --git a/src/gadget_bridge_parser/gadget_bridge.h b/src/gadget_bridge_parser/gadget_bridge.h index 3f445b3..3ab615f 100644 --- a/src/gadget_bridge_parser/gadget_bridge.h +++ b/src/gadget_bridge_parser/gadget_bridge.h @@ -28,21 +28,21 @@ * @brief GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD permits to set a size threshold used to free up * some space in the parser's internal buffer when the threshold is reached. * This ensures that we can keep on feeding new data and not get stuck. - * + * */ #define GADGET_BRIDGE_PARSER_BUFFER_THRESHOLD (100) /** * @brief GADGET_BRIDGE_PARSER_MAX_BODY_SIZE defines the max body size that will be saved in the event_data * structure when parsing the body of a notification. - * + * */ #define GADGET_BRIDGE_PARSER_MAX_BODY_SIZE (200) /** * @brief GADGET_BRIDGE_PARSER_MAX_TITLE_SIZE defines the max title size that will be saved in the event_data * structure when parsing the title of a notification. - * + * */ #define GADGET_BRIDGE_PARSER_MAX_TITLE_SIZE (100) @@ -130,6 +130,7 @@ typedef enum gadget_bridge_notification_type { GADGET_BRIDGE_NOTIFICATION_TYPE_SMS = 0, GADGET_BRIDGE_NOTIFICATION_TYPE_EMAIL, + GADGET_BRIDGE_NOTIFICATION_TYPE_GADGET_BRIDGE, GADGET_BRIDGE_NOTIFICATION_TYPE_UNKNOWN, } gadget_bridge_notification_type_e; @@ -203,7 +204,7 @@ typedef void (*parser_event_callback_t)(const gadget_bridge_event_data_t *gadget /** * @brief Sends an Android toast to GadgetBridge to be displayed on the phone. - * + * * @param toast_type the type of the toast (INFO, WARN or ERROR). * @param message a string representing the message to display. * @return true if the command was successfully sent. @@ -214,7 +215,7 @@ bool gadget_bridge_send_toast(gadget_bridge_toast_type_e toast_type, const char /** * @brief Sends up to two firmwares version to GadgetBridge. * These are displayed in the display details section of the watch in GadgetBridge. - * + * * @param fw1 a string representing the first firmware version. * @param fw2 a string representing the second firmware version. * @return true if the command was successfully sent. @@ -224,7 +225,7 @@ bool gadget_bridge_send_firmware_version(const char *fw1, const char *fw2); /** * @brief Sends the current battery status to GadgetBridge. - * + * * @param battery_level_in_percent the current battery level from 0 to 100%. * @param battery_level_in_V the current battery voltage in volts (3.942 for example). * @param is_charging a boolean which indicates if the battery is currently charging or not. @@ -236,7 +237,7 @@ bool gadget_bridge_send_battery_status(uint8_t battery_level_in_percent, float b /** * @brief Sends the find phone command to GagdetBridge, this will make the phone ring and vibrate * so that you can locate it. - * + * * @param find_phone a boolean which indicates to make the phone rind and vibrate or not. * @return true if the command was successfully sent. * @return false otherwise. @@ -245,7 +246,7 @@ bool gadget_bridge_send_find_phone(bool find_phone); /** * @brief Sends a command to control the music playback of the phone through GadgetBridge. - * + * * @param music_control an enumeration value indicating the action to perform: * PLAY, PAUSE, NEXT, PREVIOUS, VOLUMEUP etc.. * @return true if the command was successfully sent. @@ -258,9 +259,9 @@ bool gadget_bridge_handle_call(gadget_bridge_call_action_e call_action); bool gadget_bridge_handle_notification(gadget_bridge_call_action_e notification_action, uint32_t handle, const char *phone_number, const char *message); /** - * @brief Sends the provided activity data to GadgetBridge. This will then be displayed + * @brief Sends the provided activity data to GadgetBridge. This will then be displayed * on the app in the activity section. - * + * * @param heart_rate_in_bpm the current heart rate in beat per minute * @param step_count the number of new steps since the last time the count was sent. * @return true if the command was successfully sent. @@ -271,7 +272,7 @@ bool gadget_bridge_send_activity_data(uint16_t heart_rate_in_bpm, uint32_t step_ /** * @brief Tells GadgetBridge to perform an HTTP request for us. * @note THIS DOES NOT WORK as GadgetBridge don't and will never have network permission... what a pitty ! - * + * * @param id an unsigned integer representing the ID of the http request * @param url a string representing the URL to fetch * @param http_request_method a enumeration value specifying the http verb to use : GET, POST, PATCH etc.. @@ -286,14 +287,14 @@ bool gadget_bridge_send_http_request(uint32_t id, const char *url, gadget_bridge /** * @brief Registers a callback function used to listen for GadgetBridge events. - * - * @param parser_event_callback + * + * @param parser_event_callback */ void gadget_bridge_parser_register_event_callback(parser_event_callback_t parser_event_callback); /** * @brief Feeds new data to the GadgetBridge parser. - * + * * @param data the new chunk of data to parse, it will be copied to the parser's internal buffer, * so you can free the memory containing the string after calling the function. * @param length the length in bytes of the new chunk. @@ -304,7 +305,7 @@ gadget_bridge_parser_code_e gadget_bridge_parser_feed(const char *data, uint16_t /** * @brief Call this function to run the parser. * It should be safe to call if in a loop like : while((code = gadget_bridge_parser_run()) == GADGET_BRIDGE_PARSER_CODE_PARSING); - * + * * @return gadget_bridge_parser_code_e the parser's execution status code. */ gadget_bridge_parser_code_e gadget_bridge_parser_run(void); diff --git a/src/gadget_bridge_parser/gadget_bridge_parser.depend b/src/gadget_bridge_parser/gadget_bridge_parser.depend index 19ac5f2..ce4a82c 100644 --- a/src/gadget_bridge_parser/gadget_bridge_parser.depend +++ b/src/gadget_bridge_parser/gadget_bridge_parser.depend @@ -33,3 +33,20 @@ "gadget_bridge.h" +1682237814 source:/home/think/Desktop/Mes_documents/Programming/C_C++/W800_Smart_Watch/src/gadget_bridge_parser/main.c + + + + "gadget_bridge.h" + +1682233727 /home/think/Desktop/Mes_documents/Programming/C_C++/W800_Smart_Watch/src/gadget_bridge_parser/gadget_bridge.h + + + + +1682237962 source:/home/think/Desktop/Mes_documents/Programming/C_C++/W800_Smart_Watch/src/gadget_bridge_parser/gadget_bridge.c + "gadget_bridge.h" + + + + diff --git a/src/gadget_bridge_parser/main.c b/src/gadget_bridge_parser/main.c index bddf94d..189d0da 100644 --- a/src/gadget_bridge_parser/main.c +++ b/src/gadget_bridge_parser/main.c @@ -37,8 +37,6 @@ GB({t:"act",hrm:false,stp:true,int:10})[10] [16]GB({t:"act",hrm:true,stp:true,int:10})[10] [16]GB({t:"act",hrm:true,stp:false,int:10})[10] [16]GB({t:"act",hrm:false,stp:false,int:10})[10] - -Add time zone **/ void parser_event(const gadget_bridge_event_data_t *gadget_bridge_event_data) @@ -294,6 +292,30 @@ const char *sample[] = "sender :\"This is a test", "payload \",tel:\"This is", " a test payload \"})[10]", + +"[16]GB({t:\"notify\",id:", +"1682154002,src:\"Gadgetb", +"ridge\",subject:\"This i", +"s a test payload with a ", +"pretty long text because", +" it has to be also teste", +"d, we never know if some", +"thing was badly design", +"e\",body:\"", +"This is a test payload w", +"ith a very long content ", +"to make sure this case i", +"s handled in the parser ", +"and we do not crash the ", +"thing because we forgot ", +"to handle such a case, d", +"on't you think ? I need ", +"some more text apparentl", +"y as what I Wrote still ", +"isn't enough\",", +"sender :\"This is a test", +"payload \",tel:\"This is", +" a test payload \"})[10]", }; int main() @@ -311,10 +333,10 @@ int main() { gadget_bridge_parser_feed(sample[i], strlen(sample[i])); - gadget_bridge_parser_debug(); + //gadget_bridge_parser_debug(); while((code = gadget_bridge_parser_run()) == GADGET_BRIDGE_PARSER_CODE_PARSING); printf("Parser code : %s\n", gadget_bridge_parser_code_2_str(code)); - gadget_bridge_parser_debug(); + //gadget_bridge_parser_debug(); } return 0;