Documented almost every function of the API, implemented the http request command which is useless since GadgetBridge does not have internet permissions :(
This commit is contained in:
parent
bfba12e43b
commit
b3bf6ce896
@ -6,7 +6,7 @@
|
||||
* @version 0.1
|
||||
* @date 2023-04-05
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
* @copyright MIT
|
||||
*
|
||||
*/
|
||||
|
||||
@ -28,9 +28,11 @@ typedef enum gadget_bridge_parser_fsm
|
||||
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,
|
||||
@ -77,6 +79,7 @@ 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);
|
||||
|
||||
@ -169,6 +172,30 @@ bool gadget_bridge_send_activity_data(uint16_t heart_rate_in_bpm, uint32_t step_
|
||||
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;
|
||||
@ -389,12 +416,31 @@ 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_TITLE:
|
||||
if((start = strstr(_gadget_bridge_internals.buffer, "title:"))
|
||||
&& (end = strstr(_gadget_bridge_internals.buffer, ",body")))
|
||||
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(start + 7, end - 1, &_gadget_bridge_internals.event_data.notification.title);
|
||||
_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;
|
||||
@ -403,19 +449,52 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void)
|
||||
);
|
||||
_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_FOUND_SRC_BODY:
|
||||
if((start = strstr(_gadget_bridge_internals.buffer, "body:"))
|
||||
&& (end = strstr(_gadget_bridge_internals.buffer, "})")))
|
||||
case GADGET_BRIDGE_PARSER_FSM_PARSING_BODY_CONTENT:
|
||||
{
|
||||
end = strstr(_gadget_bridge_internals.buffer, "})");
|
||||
if(end)
|
||||
{
|
||||
//printf("###NOTIFICATION Type one done\n");
|
||||
//printf("###NOTIFICATION Type done\n");
|
||||
|
||||
_parser_extract_char_str(start + 6, end - 1, &_gadget_bridge_internals.event_data.notification.body);
|
||||
_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;
|
||||
@ -431,12 +510,34 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void)
|
||||
_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;
|
||||
// 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:"))
|
||||
@ -556,6 +657,7 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void)
|
||||
_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;
|
||||
@ -690,6 +792,7 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void)
|
||||
_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;
|
||||
@ -716,6 +819,7 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void)
|
||||
_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;
|
||||
@ -783,6 +887,7 @@ gadget_bridge_parser_code_e gadget_bridge_parser_run(void)
|
||||
}
|
||||
|
||||
// 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;
|
||||
@ -898,6 +1003,26 @@ static const char *_gadget_bridge_music_control_2_str(gadget_bridge_music_contro
|
||||
}
|
||||
}
|
||||
|
||||
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';
|
||||
|
@ -17,13 +17,34 @@
|
||||
#include <time.h>
|
||||
|
||||
/**
|
||||
* @brief Size of the internal buffer used to store incoming data
|
||||
* which needs to be parsed.
|
||||
* @brief GADGET_BRIDGE_PARSER_BUFFER_SIZE allows to set the size of the buffer
|
||||
* which is internally used by the parser to do it's job.
|
||||
*
|
||||
*/
|
||||
#define GADGET_BRIDGE_PARSER_BUFFER_SIZE (300)
|
||||
|
||||
/**
|
||||
* @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)
|
||||
|
||||
typedef enum gadget_bridge_toast_type
|
||||
{
|
||||
GADGET_BRIDGE_TOAST_TYPE_INFO = 0,
|
||||
@ -157,28 +178,112 @@ typedef struct gadget_bridge_event_data
|
||||
|
||||
typedef void (*parser_event_callback_t)(const gadget_bridge_event_data_t *gadget_bridge_event_data);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @return false otherwise.
|
||||
*/
|
||||
bool gadget_bridge_send_toast(gadget_bridge_toast_type_e toast_type, const char *message);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @return false otherwise.
|
||||
*/
|
||||
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.
|
||||
* @return true if the command was successfully sent.
|
||||
* @return false otherwise.
|
||||
*/
|
||||
bool gadget_bridge_send_battery_status(uint8_t battery_level_in_percent, float battery_level_in_V, bool is_charging);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
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.
|
||||
* @return false otherwise.
|
||||
*/
|
||||
bool gadget_bridge_send_music_control(gadget_bridge_music_control_e music_control);
|
||||
|
||||
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
|
||||
* 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.
|
||||
* @return false otherwise.
|
||||
*/
|
||||
bool gadget_bridge_send_activity_data(uint16_t heart_rate_in_bpm, uint32_t step_count);
|
||||
|
||||
/**
|
||||
* @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..
|
||||
* @param http_body the body to include in the request (not implemented yet)
|
||||
* @param http_headers various headers to include in the request (not implemented yet)
|
||||
* @return true if the request has been successfully sent to GadgetBridge
|
||||
* @return false otherwise
|
||||
*/
|
||||
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 gadget_bridge_send_force_calendar_sync(void);
|
||||
|
||||
/**
|
||||
* @brief Registers a callback function used to listen for GadgetBridge events.
|
||||
*
|
||||
* @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.
|
||||
* @return gadget_bridge_parser_code_e GADGET_BRIDGE_PARSER_CODE_OK if no error occured.
|
||||
*/
|
||||
gadget_bridge_parser_code_e gadget_bridge_parser_feed(const char *data, uint16_t length);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
const char *gadget_bridge_parser_code_2_str(gadget_bridge_parser_code_e parser_code);
|
||||
|
Loading…
Reference in New Issue
Block a user