From c3ced3d087c33c1402a8fac5d6ff73963bc71641 Mon Sep 17 00:00:00 2001 From: Ran Bao Date: Fri, 15 Mar 2024 23:42:12 +1300 Subject: [PATCH] Refactor existing code to support WebGUI for Safari --- .vscode/settings.json | 5 +- scripts/html2header.py | 3 + src/CMakeLists.txt | 12 +- src/button.c | 2 +- src/charge_mode.cpp | 176 +++++++++++++----- src/charge_mode.h | 16 +- src/eeprom.c | 1 + ...obile_portal.html => mobile_frontend.html} | 146 +++++++++++++-- src/lwipopts.h | 1 + src/menu.cpp | 11 +- src/motors.c | 2 + src/neopixel_led.c | 1 + src/profile.c | 1 + src/rest_endpoints.c | 9 +- src/rotary_button.cpp | 3 +- src/scale.c | 3 +- src/wireless.c | 1 + 17 files changed, 312 insertions(+), 81 deletions(-) rename src/html/{mobile_portal.html => mobile_frontend.html} (63%) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9f1d6db..719111c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -29,6 +29,9 @@ "queue.h": "c", "limits": "c", "*.tcc": "c", - "scale.h": "c" + "scale.h": "c", + "rotary_button.h": "c", + "freertos.h": "c", + "lwipopts_examples_common.h": "c" } } diff --git a/scripts/html2header.py b/scripts/html2header.py index 0373453..408eb7c 100644 --- a/scripts/html2header.py +++ b/scripts/html2header.py @@ -51,6 +51,9 @@ def main(input_filepth, output_filepath, skip_minify): else: minified_html = input_file + # Append HTML header + minified_html = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n" + minified_html + # Escape characters escaped_html = minified_html.replace("\\", "\\\\") escaped_html = escaped_html.replace('"', '\\"') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b3b543b..71f1b7e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,17 +25,17 @@ add_custom_command( add_dependencies("${TARGET_NAME}" generate_dashboard_header) -# mobile_portal.html +# mobile_frontend.html add_custom_target( generate_mobile_portal_header ALL - DEPENDS "${SRC_DIRECTORY}/generated/mobile_portal.html.h" + DEPENDS "${SRC_DIRECTORY}/generated/mobile_frontend.html.h" ) add_custom_command( - OUTPUT "${SRC_DIRECTORY}/generated/mobile_portal.html.h" - DEPENDS "${SRC_DIRECTORY}/html/mobile_portal.html" - COMMAND "${Python_EXECUTABLE}" "${SCRIPTS_DIRECTORY}/html2header.py" -vv --no-minify -f ${SRC_DIRECTORY}/html/mobile_portal.html -o ${SRC_DIRECTORY}/generated/mobile_portal.html.h - COMMENT "Generating mobile_portal.html header" + OUTPUT "${SRC_DIRECTORY}/generated/mobile_frontend.html.h" + DEPENDS "${SRC_DIRECTORY}/html/mobile_frontend.html" + COMMAND "${Python_EXECUTABLE}" "${SCRIPTS_DIRECTORY}/html2header.py" -vv --no-minify -f ${SRC_DIRECTORY}/html/mobile_frontend.html -o ${SRC_DIRECTORY}/generated/mobile_frontend.html.h + COMMENT "Generating mobile_frontend.html header" ) add_dependencies("${TARGET_NAME}" generate_mobile_portal_header) diff --git a/src/button.c b/src/button.c index 9fcaf9c..26cef89 100644 --- a/src/button.c +++ b/src/button.c @@ -29,4 +29,4 @@ ButtonEncoderEvent_t button_wait_for_input(bool block) { } return button_encoder_event; -} \ No newline at end of file +} diff --git a/src/charge_mode.cpp b/src/charge_mode.cpp index 5a4a8cb..9235235 100644 --- a/src/charge_mode.cpp +++ b/src/charge_mode.cpp @@ -51,16 +51,17 @@ const eeprom_charge_mode_data_t default_charge_mode_data = { TaskHandle_t scale_measurement_render_task_handler = NULL; static char title_string[30]; +// Menu system +extern AppState_t exit_state; +extern QueueHandle_t encoder_event_queue; +// Definitions typedef enum { - CHARGE_MODE_WAIT_FOR_ZERO, - CHARGE_MODE_WAIT_FOR_COMPLETE, - CHARGE_MODE_WAIT_FOR_CUP_REMOVAL, - CHARGE_MODE_WAIT_FOR_CUP_RETURN, - CHARGE_MODE_EXIT, - -} ChargeModeState_t; + CHARGE_MODE_EVENT_NO_EVENT = (1 << 0), + CHARGE_MODE_EVENT_UNDER_CHARGE = (1 << 1), + CHARGE_MODE_EVENT_OVER_CHARGE = (1 << 2), +} ChargeModeEventBit_t; void scale_measurement_render_task(void *p) { @@ -107,7 +108,7 @@ void scale_measurement_render_task(void *p) { } -ChargeModeState_t charge_mode_wait_for_zero(ChargeModeState_t prev_state) { +void charge_mode_wait_for_zero() { // Set colour to not ready neopixel_led_set_colour( NEOPIXEL_LED_DEFAULT_COLOUR, @@ -129,7 +130,8 @@ ChargeModeState_t charge_mode_wait_for_zero(ChargeModeState_t prev_state) { // Non block waiting for the input ButtonEncoderEvent_t button_encoder_event = button_wait_for_input(false); if (button_encoder_event == BUTTON_RST_PRESSED) { - return CHARGE_MODE_EXIT; + charge_mode_config.charge_mode_state = CHARGE_MODE_EXIT; + return; } else if (button_encoder_event == BUTTON_ENCODER_PRESSED) { scale_config.scale_handle->force_zero(); @@ -153,10 +155,10 @@ ChargeModeState_t charge_mode_wait_for_zero(ChargeModeState_t prev_state) { vTaskDelayUntil(&last_measurement_tick, pdMS_TO_TICKS(300)); } - return CHARGE_MODE_WAIT_FOR_COMPLETE; + charge_mode_config.charge_mode_state = CHARGE_MODE_WAIT_FOR_COMPLETE; } -ChargeModeState_t charge_mode_wait_for_complete(ChargeModeState_t prev_state) { +void charge_mode_wait_for_complete() { // Set colour to under charge neopixel_led_set_colour( NEOPIXEL_LED_DEFAULT_COLOUR, @@ -197,7 +199,8 @@ ChargeModeState_t charge_mode_wait_for_complete(ChargeModeState_t prev_state) { // Non block waiting for the input ButtonEncoderEvent_t button_encoder_event = button_wait_for_input(false); if (button_encoder_event == BUTTON_RST_PRESSED) { - return CHARGE_MODE_EXIT; + charge_mode_config.charge_mode_state = CHARGE_MODE_EXIT; + return; } // Run the PID controlled loop to start charging @@ -259,10 +262,10 @@ ChargeModeState_t charge_mode_wait_for_complete(ChargeModeState_t prev_state) { vTaskDelay(pdMS_TO_TICKS(20)); // Wait for other tasks to complete - return CHARGE_MODE_WAIT_FOR_CUP_REMOVAL; + charge_mode_config.charge_mode_state = CHARGE_MODE_WAIT_FOR_CUP_REMOVAL; } -ChargeModeState_t charge_mode_wait_for_cup_removal(ChargeModeState_t prev_state) { +void charge_mode_wait_for_cup_removal() { // Update current status snprintf(title_string, sizeof(title_string), "Remove Cup", charge_mode_config.target_charge_weight); @@ -284,6 +287,9 @@ ChargeModeState_t charge_mode_wait_for_cup_removal(ChargeModeState_t prev_state) charge_mode_config.eeprom_charge_mode_data.neopixel_over_charge_colour, true ); + + // Set over charge + charge_mode_config.charge_mode_event |= CHARGE_MODE_EVENT_OVER_CHARGE; } // Under charged else if (error >= charge_mode_config.eeprom_charge_mode_data.fine_stop_threshold) { @@ -293,6 +299,10 @@ ChargeModeState_t charge_mode_wait_for_cup_removal(ChargeModeState_t prev_state) charge_mode_config.eeprom_charge_mode_data.neopixel_under_charge_colour, true ); + + // Set under charge flag + charge_mode_config.charge_mode_event |= CHARGE_MODE_EVENT_UNDER_CHARGE; + } // Normal else { @@ -302,6 +312,9 @@ ChargeModeState_t charge_mode_wait_for_cup_removal(ChargeModeState_t prev_state) charge_mode_config.eeprom_charge_mode_data.neopixel_normal_charge_colour, true ); + + // Clear over and under charge bit + charge_mode_config.charge_mode_event &= ~(CHARGE_MODE_EVENT_UNDER_CHARGE | CHARGE_MODE_EVENT_OVER_CHARGE); } // Stop condition: 5 stable measurements in 300ms apart (1.5 seconds minimum) @@ -311,7 +324,8 @@ ChargeModeState_t charge_mode_wait_for_cup_removal(ChargeModeState_t prev_state) // Non block waiting for the input ButtonEncoderEvent_t button_encoder_event = button_wait_for_input(false); if (button_encoder_event == BUTTON_RST_PRESSED) { - return CHARGE_MODE_EXIT; + charge_mode_config.charge_mode_state = CHARGE_MODE_EXIT; + return; } // Perform measurement @@ -337,10 +351,10 @@ ChargeModeState_t charge_mode_wait_for_cup_removal(ChargeModeState_t prev_state) // Reset LED to default colour neopixel_led_set_colour(NEOPIXEL_LED_DEFAULT_COLOUR, NEOPIXEL_LED_DEFAULT_COLOUR, NEOPIXEL_LED_DEFAULT_COLOUR, true); - return CHARGE_MODE_WAIT_FOR_CUP_RETURN; + charge_mode_config.charge_mode_state = CHARGE_MODE_WAIT_FOR_CUP_RETURN; } -ChargeModeState_t charge_mode_wait_for_cup_return(ChargeModeState_t prev_state) { +void charge_mode_wait_for_cup_return() { // Set colour to not ready neopixel_led_set_colour( NEOPIXEL_LED_DEFAULT_COLOUR, @@ -359,7 +373,8 @@ ChargeModeState_t charge_mode_wait_for_cup_return(ChargeModeState_t prev_state) // Non block waiting for the input ButtonEncoderEvent_t button_encoder_event = button_wait_for_input(false); if (button_encoder_event == BUTTON_RST_PRESSED) { - return CHARGE_MODE_EXIT; + charge_mode_config.charge_mode_state = CHARGE_MODE_EXIT; + return; } else if (button_encoder_event == BUTTON_ENCODER_PRESSED) { scale_config.scale_handle->force_zero(); @@ -380,37 +395,37 @@ ChargeModeState_t charge_mode_wait_for_cup_return(ChargeModeState_t prev_state) vTaskDelayUntil(&last_sample_tick, pdMS_TO_TICKS(20)); } - return CHARGE_MODE_WAIT_FOR_ZERO; + charge_mode_config.charge_mode_state = CHARGE_MODE_WAIT_FOR_ZERO; } -uint8_t charge_mode_menu() { +uint8_t charge_mode_menu(bool charge_mode_skip_user_input) { // Reset LED to default colour neopixel_led_set_colour(NEOPIXEL_LED_DEFAULT_COLOUR, NEOPIXEL_LED_DEFAULT_COLOUR, NEOPIXEL_LED_DEFAULT_COLOUR, true); - // Create target weight - switch (charge_mode_config.eeprom_charge_mode_data.decimal_places) { - case DP_2: - charge_mode_config.target_charge_weight = charge_weight_digits[4] * 100 + \ - charge_weight_digits[3] * 10 + \ - charge_weight_digits[2] * 1 + \ - charge_weight_digits[1] * 0.1 + \ - charge_weight_digits[0] * 0.01; - break; - case DP_3: - charge_mode_config.target_charge_weight = charge_weight_digits[4] * 10 + \ - charge_weight_digits[3] * 1 + \ - charge_weight_digits[2] * 0.1 + \ - charge_weight_digits[1] * 0.01 + \ - charge_weight_digits[0] * 0.001; - break; - default: - charge_mode_config.target_charge_weight = 0; - break; + // Create target weight, if the charge mode weight is built by charge_weight_digits + if (!charge_mode_skip_user_input) { + switch (charge_mode_config.eeprom_charge_mode_data.decimal_places) { + case DP_2: + charge_mode_config.target_charge_weight = charge_weight_digits[4] * 100 + \ + charge_weight_digits[3] * 10 + \ + charge_weight_digits[2] * 1 + \ + charge_weight_digits[1] * 0.1 + \ + charge_weight_digits[0] * 0.01; + break; + case DP_3: + charge_mode_config.target_charge_weight = charge_weight_digits[4] * 10 + \ + charge_weight_digits[3] * 1 + \ + charge_weight_digits[2] * 0.1 + \ + charge_weight_digits[1] * 0.01 + \ + charge_weight_digits[0] * 0.001; + break; + default: + charge_mode_config.target_charge_weight = 0; + break; + } } - printf("Target Charge Weight: %f\n", charge_mode_config.target_charge_weight); - // If the display task is never created then we shall create one, otherwise we shall resume the task if (scale_measurement_render_task_handler == NULL) { // The render task shall have lower priority than the current one @@ -425,22 +440,22 @@ uint8_t charge_mode_menu() { motor_enable(SELECT_COARSE_TRICKLER_MOTOR, true); motor_enable(SELECT_FINE_TRICKLER_MOTOR, true); - ChargeModeState_t state = CHARGE_MODE_WAIT_FOR_ZERO; + charge_mode_config.charge_mode_state = CHARGE_MODE_WAIT_FOR_ZERO; bool quit = false; while (quit == false) { - switch (state) { + switch (charge_mode_config.charge_mode_state) { case CHARGE_MODE_WAIT_FOR_ZERO: - state = charge_mode_wait_for_zero(state); + charge_mode_wait_for_zero(); break; case CHARGE_MODE_WAIT_FOR_COMPLETE: - state = charge_mode_wait_for_complete(state); + charge_mode_wait_for_complete(); break; case CHARGE_MODE_WAIT_FOR_CUP_REMOVAL: - state = charge_mode_wait_for_cup_removal(state); + charge_mode_wait_for_cup_removal(); break; case CHARGE_MODE_WAIT_FOR_CUP_RETURN: - state = charge_mode_wait_for_cup_return(state); + charge_mode_wait_for_cup_return(); break; case CHARGE_MODE_EXIT: default: @@ -572,6 +587,7 @@ bool http_rest_charge_mode_config(struct fs_file *file, int num_params, char *pa // Response snprintf(charge_mode_json_buffer, sizeof(charge_mode_json_buffer), + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"c1\":\"#%06x\",\"c2\":\"#%06x\",\"c3\":\"#%06x\",\"c4\":\"#%06x\"," "\"c5\":%.3f,\"c6\":%.3f,\"c7\":%.3f,\"c8\":%.3f,\"c9\":%d}", charge_mode_config.eeprom_charge_mode_data.neopixel_normal_charge_colour, @@ -595,21 +611,36 @@ bool http_rest_charge_mode_config(struct fs_file *file, int num_params, char *pa } -bool http_rest_charge_mode_setpoint(struct fs_file *file, int num_params, char *params[], char *values[]) { +bool http_rest_charge_mode_set_point(struct fs_file *file, int num_params, char *params[], char *values[]) { + // Mappings + // c0 (float): Charge weight set point (unitless) + static char charge_mode_json_buffer[64]; + float target_charge_weight = -1; // Control for (int idx = 0; idx < num_params; idx += 1) { - if (strcmp(params[idx], "target_charge_weight") == 0) { - float target_charge_weight = strtof(values[idx], NULL); + if (strcmp(params[idx], "c0") == 0) { + target_charge_weight = strtof(values[idx], NULL); charge_mode_config.target_charge_weight = target_charge_weight; } } + // Perform action + if (target_charge_weight > 0) { + // Set exit_status for the menu + exit_state = APP_STATE_ENTER_CHARGE_MODE; + + // Then signal the menu to stop + ButtonEncoderEvent_t button_event = OVERRIDE_FROM_REST; + xQueueSend(encoder_event_queue, &button_event, portMAX_DELAY); + } + // Response snprintf(charge_mode_json_buffer, sizeof(charge_mode_json_buffer), - "{\"target_charge_weight\":%0.3f}", + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" + "{\"c0\":%0.3f}", charge_mode_config.target_charge_weight); size_t data_length = strlen(charge_mode_json_buffer); @@ -618,5 +649,48 @@ bool http_rest_charge_mode_setpoint(struct fs_file *file, int num_params, char * file->index = data_length; file->flags = FS_FILE_FLAGS_HEADER_INCLUDED; + return true; +} + + +bool http_rest_charge_mode_status(struct fs_file *file, int num_params, char *params[], char *values[]) { + // Mappings + // s0 (float): Charge weight set point (unitless) + // s1 (float): Current weight (unitless) + // s2 (ChargeModeState_t | int): Charge mode state + // s3 (uint32_t): Charge mode event + + static char charge_mode_json_buffer[128]; + + // Control + for (int idx = 0; idx < num_params; idx += 1) { + if (strcmp(params[idx], "s2") == 0) { + charge_mode_config.charge_mode_state = (ChargeModeState_t) atoi(values[idx]); + + // Also send termination request via button + ButtonEncoderEvent_t button_event = BUTTON_RST_PRESSED; + xQueueSend(encoder_event_queue, &button_event, portMAX_DELAY); + } + } + + // Response + snprintf(charge_mode_json_buffer, + sizeof(charge_mode_json_buffer), + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" + "{\"s0\":%0.3f,\"s1\":%0.3f,\"s2\":%d,\"s3\":%lu}", + charge_mode_config.target_charge_weight, + scale_get_current_measurement(), + (int) charge_mode_config.charge_mode_state, + charge_mode_config.charge_mode_event); + + // Clear events + charge_mode_config.charge_mode_event = 0; + + size_t data_length = strlen(charge_mode_json_buffer); + file->data = charge_mode_json_buffer; + file->len = data_length; + file->index = data_length; + file->flags = FS_FILE_FLAGS_HEADER_INCLUDED; + return true; } \ No newline at end of file diff --git a/src/charge_mode.h b/src/charge_mode.h index 701689f..d084822 100644 --- a/src/charge_mode.h +++ b/src/charge_mode.h @@ -10,6 +10,14 @@ #define WEIGHT_STRING_LEN 8 +typedef enum { + CHARGE_MODE_WAIT_FOR_ZERO = 0, + CHARGE_MODE_WAIT_FOR_COMPLETE = 1, + CHARGE_MODE_WAIT_FOR_CUP_REMOVAL = 2, + CHARGE_MODE_WAIT_FOR_CUP_RETURN = 3, + CHARGE_MODE_EXIT = 4, +} ChargeModeState_t; + typedef struct { uint16_t charge_mode_data_rev; @@ -32,11 +40,13 @@ typedef struct { typedef struct { eeprom_charge_mode_data_t eeprom_charge_mode_data; float target_charge_weight; + uint32_t charge_mode_event; + ChargeModeState_t charge_mode_state; } charge_mode_config_t; bool charge_mode_config_init(void); -uint8_t charge_mode_menu(); +uint8_t charge_mode_menu(bool charge_mode_skip_user_input); // C Functions #ifdef __cplusplus @@ -47,7 +57,9 @@ bool charge_mode_config_save(void); // REST interface bool http_rest_charge_mode_config(struct fs_file *file, int num_params, char *params[], char *values[]); -bool http_rest_charge_mode_setpoint(struct fs_file *file, int num_params, char *params[], char *values[]); +bool http_rest_charge_mode_set_point(struct fs_file *file, int num_params, char *params[], char *values[]); +bool http_rest_charge_mode_status(struct fs_file *file, int num_params, char *params[], char *values[]); + #ifdef __cplusplus } // __cplusplus diff --git a/src/eeprom.c b/src/eeprom.c index efd3f66..11ca48c 100644 --- a/src/eeprom.c +++ b/src/eeprom.c @@ -230,6 +230,7 @@ bool http_rest_system_control(struct fs_file *file, int num_params, char *params // Response snprintf(eeprom_config_json_buffer, sizeof(eeprom_config_json_buffer), + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"s0\":\"%s\",\"s1\":\"%s\",\"s2\":\"%s\",\"s3\":\"%s\",\"s4\":%s,\"s5\":%s,\"s6\":%s}", metadata.unique_id, version_string, vcs_hash, build_type, boolean_to_string(save_to_eeprom_flag), diff --git a/src/html/mobile_portal.html b/src/html/mobile_frontend.html similarity index 63% rename from src/html/mobile_portal.html rename to src/html/mobile_frontend.html index 68fca00..d8746da 100644 --- a/src/html/mobile_portal.html +++ b/src/html/mobile_frontend.html @@ -25,9 +25,6 @@ -
Control
- - + +
Control
+ - + - + + + +
+ +
@@ -68,8 +76,42 @@

Error

+ + + + + + + + + + diff --git a/src/lwipopts.h b/src/lwipopts.h index cc0a616..d1c7c7e 100644 --- a/src/lwipopts.h +++ b/src/lwipopts.h @@ -32,5 +32,6 @@ #define LWIP_HTTPD_DYNAMIC_FILE_READ 0 #define LWIP_HTTPD_DYNAMIC_HEADERS 0 #define LWIP_HTTPD_MAX_REQUEST_URI_LEN 128 +#define LWIP_HTTPD_DYNAMIC_HEADERS 0 #endif \ No newline at end of file diff --git a/src/menu.cpp b/src/menu.cpp index f837134..2f97886 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -44,6 +44,9 @@ void menu_task(void *p){ mui_Draw(&mui); u8g2_SendBuffer(display_handler); + // Flags + bool charge_mode_skip_user_input = false; // Used to skip user input if the charge mode weight is received from REST + while (true) { if (mui_IsFormActive(&mui)) { // Block wait for the user input @@ -57,13 +60,19 @@ void menu_task(void *p){ else if (button_encoder_event == BUTTON_ENCODER_PRESSED) { mui_SendSelect(&mui); } + else if (button_encoder_event == OVERRIDE_FROM_REST) { + // Assuming the caller code will set the exit_state + mui_SaveForm(&mui); // store the current form and position so that the child can jump back + mui_LeaveForm(&mui); + charge_mode_skip_user_input = true; + } } else { uint8_t exit_form_id = 1; // by default it goes to the main menu // menu is not active, leave the control to the app switch (exit_state) { case APP_STATE_ENTER_CHARGE_MODE: - exit_form_id = charge_mode_menu(); + exit_form_id = charge_mode_menu(charge_mode_skip_user_input); break; case APP_STATE_ENTER_CLEANUP_MODE: exit_form_id = cleanup_mode_menu(); diff --git a/src/motors.c b/src/motors.c index 2b3060e..4486aa6 100644 --- a/src/motors.c +++ b/src/motors.c @@ -634,6 +634,7 @@ void populate_rest_motor_config(motor_config_t * motor_config, char * buf, size_ // Build response snprintf(buf, max_len, + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"m0\":%f,\"m1\":%d,\"m2\":%d,\"m3\":%d,\"m4\":%d,\"m5\":%d,\"m6\":%0.3f,\"m7\":%f,\"m8\":%s,\"m9\":%s}", motor_config->persistent_config.angular_acceleration, motor_config->persistent_config.full_steps_per_rotation, @@ -773,6 +774,7 @@ bool http_rest_motor_speed(struct fs_file *file, int num_params, char *params[], // Build response snprintf(motor_speed_json_buffer, sizeof(motor_speed_json_buffer), + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"speed\":%0.3f,\"direction\":%d}", motor_config->prev_velocity, motor_config->step_direction); diff --git a/src/neopixel_led.c b/src/neopixel_led.c index 90c4c3b..8d247fe 100644 --- a/src/neopixel_led.c +++ b/src/neopixel_led.c @@ -238,6 +238,7 @@ bool http_rest_neopixel_led_config(struct fs_file *file, int num_params, char *p // Response snprintf(neopixel_config_json_buffer, sizeof(neopixel_config_json_buffer), + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"bl\":\"#%06x\",\"l1\":\"#%06x\",\"l2\":\"#%06x\"}", neopixel_led_config.eeprom_neopixel_led_metadata.default_led_colours.mini12864_backlight_colour, neopixel_led_config.eeprom_neopixel_led_metadata.default_led_colours.led1_colour, diff --git a/src/profile.c b/src/profile.c index c7f35ca..47a5b29 100644 --- a/src/profile.c +++ b/src/profile.c @@ -222,6 +222,7 @@ bool http_rest_profile_config(struct fs_file *file, int num_params, char *params // Response snprintf(buf, sizeof(buf), + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"pf\":%d,\"p0\":%d,\"p1\":%d,\"p2\":\"%s\",\"p3\":%0.3f,\"p4\":%0.3f,\"p5\":%0.3f,\"p6\":%0.3f,\"p7\":%0.3f,\"p8\":%0.3f,\"p9\":%0.3f,\"p10\":%0.3f,\"p11\":%0.3f,\"p12\":%0.3f}", profile_idx, current_profile->rev, diff --git a/src/rest_endpoints.c b/src/rest_endpoints.c index d5e3d64..5d8fbd7 100644 --- a/src/rest_endpoints.c +++ b/src/rest_endpoints.c @@ -18,7 +18,7 @@ #include "bootstrap.min.js.h" #include "jquery-3.7.0.min.js.h" #include "dashboard.html.h" -#include "mobile_portal.html.h" +#include "mobile_frontend.html.h" bool http_404_error(struct fs_file *file, int num_params, char *params[], char *values[]) { @@ -92,9 +92,9 @@ bool http_dashboard(struct fs_file *file, int num_params, char *params[], char * bool http_mobile_portal(struct fs_file *file, int num_params, char *params[], char *values[]) { - size_t len = strlen(html_mobile_portal_html); + size_t len = strlen(html_mobile_frontend_html); - file->data = html_mobile_portal_html; + file->data = html_mobile_frontend_html; file->len = len; file->index = len; file->flags = FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT; @@ -111,7 +111,8 @@ bool rest_endpoints_init() { rest_register_handler("/rest/scale_weight", http_rest_scale_weight); rest_register_handler("/rest/scale_config", http_rest_scale_config); rest_register_handler("/rest/charge_mode_config", http_rest_charge_mode_config); - rest_register_handler("/rest/charge_mode_setpoint", http_rest_charge_mode_setpoint); + rest_register_handler("/rest/charge_mode_set_point", http_rest_charge_mode_set_point); + rest_register_handler("/rest/charge_mode_status", http_rest_charge_mode_status); rest_register_handler("/rest/system_control", http_rest_system_control); rest_register_handler("/rest/coarse_motor_config", http_rest_coarse_motor_config); rest_register_handler("/rest/fine_motor_config", http_rest_fine_motor_config); diff --git a/src/rotary_button.cpp b/src/rotary_button.cpp index 4cc284d..5b6e752 100644 --- a/src/rotary_button.cpp +++ b/src/rotary_button.cpp @@ -232,7 +232,7 @@ bool http_rest_button_control(struct fs_file *file, int num_params, char *params static char button_control_json_buffer[256]; memset(button_control_json_buffer, 0x0, sizeof(button_control_json_buffer)); - strcat(button_control_json_buffer, "{\"button_pressed\":["); + strcat(button_control_json_buffer, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{\"button_pressed\":["); for (int idx = 0; idx < num_params; idx += 1) { if (strcmp(params[idx], "CW") == 0) { @@ -317,6 +317,7 @@ bool http_rest_button_config(struct fs_file *file, int num_params, char *params[ // Response snprintf(buf, sizeof(buf), + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"b0\":%s}", boolean_to_string(rotary_button_config.inverted_encoder_direction)); diff --git a/src/scale.c b/src/scale.c index 4ea13d6..6e426b3 100644 --- a/src/scale.c +++ b/src/scale.c @@ -204,6 +204,7 @@ bool http_rest_scale_config(struct fs_file *file, int num_params, char *params[] snprintf(scale_config_to_json_buffer, sizeof(scale_config_to_json_buffer), + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"s0\":\"%d\",\"s1\":%d}", scale_config.persistent_config.scale_driver, scale_config.persistent_config.scale_baudrate); @@ -223,7 +224,7 @@ bool http_rest_scale_weight(struct fs_file *file, int num_params, char *params[] snprintf(scale_weight_to_json_buffer, sizeof(scale_weight_to_json_buffer), - "{\"weight\":%0.3f}", + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{\"weight\":%0.3f}", scale_get_current_measurement()); size_t data_length = strlen(scale_weight_to_json_buffer); diff --git a/src/wireless.c b/src/wireless.c index 8e417dd..93054dc 100644 --- a/src/wireless.c +++ b/src/wireless.c @@ -424,6 +424,7 @@ bool http_rest_wireless_config(struct fs_file *file, int num_params, char *param // Response snprintf(wireless_config_json_buffer, sizeof(wireless_config_json_buffer), + "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" "{\"w0\":\"%s\",\"w1\":\"%s\",\"w2\":\"%d\",\"w3\":%"PRId32",\"w4\":%s}", wireless_config.eeprom_wireless_metadata.ssid, wireless_config.eeprom_wireless_metadata.pw,