From 315342791df16bfee8cd95837ab35cddf4cd6d70 Mon Sep 17 00:00:00 2001 From: Lixie Labs <5051485+connornishijima@users.noreply.github.com> Date: Wed, 29 May 2024 12:04:37 -0600 Subject: [PATCH] BROKEN VERSION: Still overhauling websockets communication! --- data/js/websockets_connection.js | 4 +- src/configuration.h | 130 ++++++++++++++++---- src/cpu_core.h | 24 +--- src/profiler.h | 107 +++++++---------- src/types.h | 26 +++- src/web_core.h | 13 ++ src/wireless.h | 196 +++++++++++++++++++++++-------- 7 files changed, 338 insertions(+), 162 deletions(-) diff --git a/data/js/websockets_connection.js b/data/js/websockets_connection.js index b2bfd15..52c5e38 100644 --- a/data/js/websockets_connection.js +++ b/data/js/websockets_connection.js @@ -286,8 +286,8 @@ function connect_to_emotiscope() { attempt_to_reach_emotiscope_interval = setInterval(attempt_to_reach_emotiscope, 250); setInterval(function(){ - wstx("EMO~config|brightness|float|0.991|slider|1|softness|float|1.000|slider|1"); - }, 500); + wstx("EMO~set_config|Softness|0.250"); + }, 5000); }; ws.onmessage = function(event) { diff --git a/src/configuration.h b/src/configuration.h index ef3713c..671f439 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -15,110 +15,190 @@ volatile bool save_request_open = false; volatile bool filesystem_ready = true; +// Load configuration from NVS void load_config(){ - // Load configuration from NVS - - memset(&configuration, 0, sizeof(config)); // Clear the configuration struct + // This is where defaults are stored! Config items must be manually initialized here + // before being loaded from NVS. There are three datatypes: u32, i32, and f32. + // These correspond to uint32_t, int32_t, and float, respectively. Bools are stored + // as u32s. + // + // To add a new config item, add it to the config struct in types.h, then add a + // matching loader to this function. The loader should look like the ones below, + // defining the name, pretty_name, type, ui_type, and default value of the config item. + // + // The configuration can be accessed in two ways: by key name (configuration.brightness) + // or by iteration with pointer offsets (config_item my_config_item = *(config_location + i)) + + memset(&configuration, 0, sizeof(configuration)); // Clear the configuration struct // Brightness strcpy(configuration.brightness.name, "brightness"); strcpy(configuration.brightness.pretty_name, "Brightness"); + strcpy(configuration.brightness.type_string, "f32"); + strcpy(configuration.brightness.ui_type_string, "s"); + configuration.brightness.type = f32; + configuration.brightness.ui_type = ui_type_slider; configuration.brightness.value.f32 = preferences.getFloat(configuration.brightness.name, 1.00); // Softness strcpy(configuration.softness.name, "softness"); strcpy(configuration.softness.pretty_name, "Softness"); + strcpy(configuration.softness.type_string, "f32"); + strcpy(configuration.softness.ui_type_string, "s"); + configuration.softness.type = f32; + configuration.softness.ui_type = ui_type_slider; configuration.softness.value.f32 = preferences.getFloat(configuration.softness.name, 0.25); // Color strcpy(configuration.color.name, "color"); strcpy(configuration.color.pretty_name, "Color"); + strcpy(configuration.color.type_string, "f32"); + strcpy(configuration.color.ui_type_string, "s"); + configuration.color.type = f32; + configuration.color.ui_type = ui_type_slider; configuration.color.value.f32 = preferences.getFloat(configuration.color.name, 0.33); // Color Range strcpy(configuration.color_range.name, "color_range"); strcpy(configuration.color_range.pretty_name, "Color Range"); + strcpy(configuration.color_range.type_string, "f32"); + strcpy(configuration.color_range.ui_type_string, "s"); + configuration.color_range.type = f32; + configuration.color_range.ui_type = ui_type_slider; configuration.color_range.value.f32 = preferences.getFloat(configuration.color_range.name, 0.0); // Warmth strcpy(configuration.warmth.name, "warmth"); strcpy(configuration.warmth.pretty_name, "Warmth"); + strcpy(configuration.warmth.type_string, "f32"); + strcpy(configuration.warmth.ui_type_string, "s"); + configuration.warmth.type = f32; + configuration.warmth.ui_type = ui_type_slider; configuration.warmth.value.f32 = preferences.getFloat(configuration.warmth.name, 0.50); // Speed strcpy(configuration.speed.name, "speed"); strcpy(configuration.speed.pretty_name, "Speed"); + strcpy(configuration.speed.type_string, "f32"); + strcpy(configuration.speed.ui_type_string, "s"); + configuration.speed.type = f32; + configuration.speed.ui_type = ui_type_slider; configuration.speed.value.f32 = preferences.getFloat(configuration.speed.name, 0.50); // Saturation strcpy(configuration.saturation.name, "saturation"); strcpy(configuration.saturation.pretty_name, "Saturation"); + strcpy(configuration.saturation.type_string, "f32"); + strcpy(configuration.saturation.ui_type_string, "s"); + configuration.saturation.type = f32; + configuration.saturation.ui_type = ui_type_slider; configuration.saturation.value.f32 = preferences.getFloat(configuration.saturation.name, 0.85); // Background strcpy(configuration.background.name, "background"); strcpy(configuration.background.pretty_name, "Background"); + strcpy(configuration.background.type_string, "f32"); + strcpy(configuration.background.ui_type_string, "s"); + configuration.background.type = f32; + configuration.background.ui_type = ui_type_slider; configuration.background.value.f32 = preferences.getFloat(configuration.background.name, 0.25); // Current Mode strcpy(configuration.current_mode.name, "current_mode"); strcpy(configuration.current_mode.pretty_name, "Current Mode"); + strcpy(configuration.current_mode.type_string, "u32"); + strcpy(configuration.current_mode.ui_type_string, "n"); + configuration.current_mode.type = u32; + configuration.current_mode.ui_type = ui_type_none; configuration.current_mode.value.u32 = (uint32_t)preferences.getInt(configuration.current_mode.name, 1); // Mirror Mode strcpy(configuration.mirror_mode.name, "mirror_mode"); strcpy(configuration.mirror_mode.pretty_name, "Mirror Mode"); - configuration.mirror_mode.value.u32 = (uint32_t)preferences.getBool(configuration.mirror_mode.name, true); + strcpy(configuration.mirror_mode.type_string, "u32"); + strcpy(configuration.mirror_mode.ui_type_string, "t"); + configuration.mirror_mode.type = u32; + configuration.mirror_mode.ui_type = ui_type_toggle; + configuration.mirror_mode.value.u32 = (uint32_t)preferences.getInt(configuration.mirror_mode.name, 1); // Screensaver strcpy(configuration.screensaver.name, "screensaver"); strcpy(configuration.screensaver.pretty_name, "Screensaver"); - configuration.screensaver.value.u32 = (uint32_t)preferences.getBool(configuration.screensaver.name, true); + strcpy(configuration.screensaver.type_string, "u32"); + strcpy(configuration.screensaver.ui_type_string, "mt"); + configuration.screensaver.type = u32; + configuration.screensaver.ui_type = ui_type_menu_toggle; + configuration.screensaver.value.u32 = (uint32_t)preferences.getInt(configuration.screensaver.name, 1); // Temporal Dithering strcpy(configuration.temporal_dithering.name, "dithering"); strcpy(configuration.temporal_dithering.pretty_name, "Temporal Dithering"); - configuration.temporal_dithering.value.u32 = (uint32_t)preferences.getBool(configuration.temporal_dithering.name, true); + strcpy(configuration.temporal_dithering.type_string, "u32"); + strcpy(configuration.temporal_dithering.ui_type_string, "mt"); + configuration.temporal_dithering.type = u32; + configuration.temporal_dithering.ui_type = ui_type_menu_toggle; + configuration.temporal_dithering.value.u32 = (uint32_t)preferences.getInt(configuration.temporal_dithering.name, 1); // Reverse Color strcpy(configuration.reverse_color_range.name, "reverse_color"); strcpy(configuration.reverse_color_range.pretty_name, "Reverse Color Range"); - configuration.reverse_color_range.value.u32 = (uint32_t)preferences.getBool(configuration.reverse_color_range.name, false); + strcpy(configuration.reverse_color_range.type_string, "u32"); + strcpy(configuration.reverse_color_range.ui_type_string, "t"); + configuration.reverse_color_range.type = u32; + configuration.reverse_color_range.ui_type = ui_type_toggle; + configuration.reverse_color_range.value.u32 = (uint32_t)preferences.getInt(configuration.reverse_color_range.name, 0); // Auto Color Cycling strcpy(configuration.auto_color_cycle.name, "auto_color"); strcpy(configuration.auto_color_cycle.pretty_name, "Auto Color Cycle"); - configuration.auto_color_cycle.value.u32 = (uint32_t)preferences.getBool(configuration.auto_color_cycle.name, false); + strcpy(configuration.auto_color_cycle.type_string, "u32"); + strcpy(configuration.auto_color_cycle.ui_type_string, "t"); + configuration.auto_color_cycle.type = u32; + configuration.auto_color_cycle.ui_type = ui_type_toggle; + configuration.auto_color_cycle.value.u32 = (uint32_t)preferences.getInt(configuration.auto_color_cycle.name, 0); // Blur strcpy(configuration.blur.name, "blur"); strcpy(configuration.blur.pretty_name, "Blur"); + strcpy(configuration.blur.type_string, "f32"); + strcpy(configuration.blur.ui_type_string, "slider"); + configuration.blur.type = f32; + configuration.blur.ui_type = ui_type_slider; configuration.blur.value.f32 = preferences.getFloat(configuration.blur.name, 0.00); // Show Interface strcpy(configuration.show_ui.name, "show_ui"); strcpy(configuration.show_ui.pretty_name, "Show Interface"); - configuration.show_ui.value.u32 = (uint32_t)preferences.getBool(configuration.show_ui.name, true); + strcpy(configuration.show_ui.type_string, "u32"); + strcpy(configuration.show_ui.ui_type_string, "mt"); + configuration.show_ui.type = u32; + configuration.show_ui.ui_type = ui_type_menu_toggle; + configuration.show_ui.value.u32 = (uint32_t)preferences.getInt(configuration.show_ui.name, 1); } // Save configuration to LittleFS bool save_config() { - preferences.putFloat(configuration.brightness.name, configuration.brightness.value.f32); - preferences.putFloat(configuration.softness.name, configuration.softness.value.f32); - preferences.putFloat(configuration.color.name, configuration.color.value.f32); - preferences.putFloat(configuration.color_range.name, configuration.color_range.value.f32); - preferences.putFloat(configuration.warmth.name, configuration.warmth.value.f32); - preferences.putFloat(configuration.speed.name, configuration.speed.value.f32); - preferences.putFloat(configuration.saturation.name, configuration.saturation.value.f32); - preferences.putFloat(configuration.background.name, configuration.background.value.f32); - preferences.putInt(configuration.current_mode.name, configuration.current_mode.value.u32); - preferences.putBool(configuration.mirror_mode.name, configuration.mirror_mode.value.u32); - preferences.putBool(configuration.screensaver.name, configuration.screensaver.value.u32); - preferences.putBool(configuration.temporal_dithering.name, configuration.temporal_dithering.value.u32); - preferences.putBool(configuration.reverse_color_range.name, configuration.reverse_color_range.value.u32); - preferences.putBool(configuration.auto_color_cycle.name, configuration.auto_color_cycle.value.u32); - preferences.putFloat(configuration.blur.name, configuration.blur.value.f32); - preferences.putBool(configuration.show_ui.name, configuration.show_ui.value.u32); + config_item* config_location = reinterpret_cast(&configuration); + uint16_t num_config_items = sizeof(configuration) / sizeof(config_item); + + for(uint16_t i = 0; i < num_config_items; i++){ + config_item item = *(config_location + i); + type_t type = item.type; + + if(type == u32){ + //printf("Saving u32 %s: %d\n", item.name, item.value.u32); + preferences.putInt(item.name, item.value.u32); + } else if(type == i32){ + //printf("Saving i32 %s: %d\n", item.name, item.value.i32); + preferences.putInt(item.name, item.value.i32); + } else if(type == f32){ + //printf("Saving f32 %s: %f\n", item.name, item.value.f32); + preferences.putFloat(item.name, item.value.f32); + } else { + printf("ERROR: Unknown type in save_config\n"); + return false; + } + } return true; } diff --git a/src/cpu_core.h b/src/cpu_core.h index 43cb2b0..3ae60ae 100644 --- a/src/cpu_core.h +++ b/src/cpu_core.h @@ -40,11 +40,8 @@ void run_cpu() { update_tempo(); // (tempo.h) //})); - // Update the FPS_CPU variable - watch_cpu_fps(); // (system.h) - - // Occasionally print the average frame rate - print_system_info(); + // Send out stats like FPS and heap + update_stats(); // print_audio_data(); @@ -56,21 +53,8 @@ void run_cpu() { //neural_network_feed_forward(); - //------------------------------------------------------------------------------------------ - // WIFI - // ------------------------------------------------------------------------------------ - //run_wireless(); // (wireless.h) - - //------------------------------------------------------------------------------------------ - // TESTING AREA, SHOULD BE BLANK IN PRODUCTION - - /* - printf("MATCH STRCMP | microseconds taken = %.4f\n", measure_execution([&]() { - (strcmp("test_string_value", "test_string_value") == 0); - })); - */ - - //------------------------------------------------------------------------------------------ + // Update the FPS_CPU variable + watch_cpu_fps(); // (system.h) //------------------------------------------------------------------------------------------ // CPU USAGE CALCULATION diff --git a/src/profiler.h b/src/profiler.h index 5996ad0..4aa01f4 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -24,11 +24,10 @@ bool profiler_locked = false; float FPS_CPU_SAMPLES[16]; float FPS_GPU_SAMPLES[16]; +float CPU_CORE_USAGE = 0.0; float FPS_CPU = 0.0; float FPS_GPU = 0.0; -float CPU_CORE_USAGE = 0.0; - inline bool fastcmp_func_name(const char* input_a, const char* input_b){ // Is first char different? DISQUALIFIED! if(input_a[0] != input_b[0]){ return false; } @@ -156,70 +155,54 @@ void watch_gpu_fps() { }, __func__ ); } -void print_system_info() { - static uint32_t next_print_ms = 0; - const uint16_t print_interval_ms = 2000; - bool printing_enabled = false; - - if (t_now_ms >= next_print_ms) { - next_print_ms += print_interval_ms; - - FPS_CPU = 0.0; - FPS_GPU = 0.0; - for (uint8_t i = 0; i < 16; i++) { - FPS_CPU += FPS_CPU_SAMPLES[i]; - FPS_GPU += FPS_GPU_SAMPLES[i]; - } - FPS_CPU /= 16.0; - FPS_GPU /= 16.0; +void update_stats() { + const uint16_t update_hz = 10; + const uint32_t update_interval = 1000 / update_hz; + static uint32_t last_update = 0; + + if (t_now_ms - last_update < update_interval) { + return; + } + + FPS_CPU = 0.0; + FPS_GPU = 0.0; + for (uint8_t i = 0; i < 16; i++) { + FPS_CPU += FPS_CPU_SAMPLES[i]; + FPS_GPU += FPS_GPU_SAMPLES[i]; + } + FPS_CPU /= 16.0; + FPS_GPU /= 16.0; - uint32_t free_heap = esp_get_free_heap_size(); - UBaseType_t free_stack_cpu = uxTaskGetStackHighWaterMark(NULL); // CPU core (this one) - UBaseType_t free_stack_gpu = uxTaskGetStackHighWaterMark(xTaskGetHandle("loop_gpu")); // GPU core + uint32_t free_heap = esp_get_free_heap_size(); + UBaseType_t free_stack_cpu = uxTaskGetStackHighWaterMark(NULL); // CPU core (this one) + UBaseType_t free_stack_gpu = uxTaskGetStackHighWaterMark(xTaskGetHandle("loop_gpu")); // GPU core + /* extern volatile bool web_server_ready; - extern PsychicWebSocketClient *get_client_in_slot(uint8_t slot); - - char stat_buffer[64] = { 0 }; - - memset(stat_buffer, 0, 64); - snprintf(stat_buffer, 64, "fps_cpu|%d", int16_t(FPS_CPU)); - broadcast(stat_buffer); - - memset(stat_buffer, 0, 64); - snprintf(stat_buffer, 64, "fps_gpu|%d", int16_t(FPS_GPU)); - broadcast(stat_buffer); - - memset(stat_buffer, 0, 64); - snprintf(stat_buffer, 64, "heap|%lu", (uint32_t)free_heap); - broadcast(stat_buffer); - - if(printing_enabled == true){ - printf("# SYSTEM INFO ####################\n"); - printf("CPU CORE USAGE --- %.2f%%\n", CPU_CORE_USAGE*100); - printf("CPU FPS ---------- %.3f\n", FPS_CPU); - printf("GPU FPS ---------- %.3f\n", FPS_GPU); - printf("Free Heap -------- %lu\n", (uint32_t)free_heap); - printf("Free Stack CPU --- %lu\n", (uint32_t)free_stack_cpu); - printf("Free Stack GPU --- %lu\n", (uint32_t)free_stack_gpu); - //printf("Total PSRAM ------ %lu\n", (uint32_t)ESP.getPsramSize()); - //printf("Free PSRAM ------- %lu\n", (uint32_t)ESP.getFreePsram()); - printf("IP Address ------- %s\n", WiFi.localIP().toString().c_str()); - printf("MAC Address ------ %s\n", mac_str); - printf("\n"); - printf("- WS CLIENTS -----------------\n"); - if(web_server_ready == true){ - for(uint16_t i = 0; i < MAX_WEBSOCKET_CLIENTS; i++){ - PsychicWebSocketClient *client = get_client_in_slot(i); - if (client != NULL) { - printf("%s\n", client->remoteIP().toString().c_str()); - } + printf("# SYSTEM INFO ####################\n"); + printf("CPU CORE USAGE --- %.2f%%\n", CPU_CORE_USAGE*100); + printf("CPU FPS ---------- %.3f\n", FPS_CPU); + printf("GPU FPS ---------- %.3f\n", FPS_GPU); + printf("Free Heap -------- %lu\n", (uint32_t)free_heap); + printf("Free Stack CPU --- %lu\n", (uint32_t)free_stack_cpu); + printf("Free Stack GPU --- %lu\n", (uint32_t)free_stack_gpu); + //printf("Total PSRAM ------ %lu\n", (uint32_t)ESP.getPsramSize()); + //printf("Free PSRAM ------- %lu\n", (uint32_t)ESP.getFreePsram()); + printf("IP Address ------- %s\n", WiFi.localIP().toString().c_str()); + printf("MAC Address ------ %s\n", mac_str); + printf("\n"); + printf("- WS CLIENTS -----------------\n"); + if(web_server_ready == true){ + for(uint16_t i = 0; i < MAX_WEBSOCKET_CLIENTS; i++){ + PsychicWebSocketClient *client = get_client_in_slot(i); + if (client != NULL) { + printf("%s\n", client->remoteIP().toString().c_str()); } } - printf("------------------------------\n"); - - print_profiled_function_hits(); - printf("##################################\n\n"); } - } + printf("------------------------------\n"); + + print_profiled_function_hits(); + printf("##################################\n\n"); + */ } \ No newline at end of file diff --git a/src/types.h b/src/types.h index 6e78bc8..6ca0998 100644 --- a/src/types.h +++ b/src/types.h @@ -152,9 +152,33 @@ union config_value { float f32; }; +// enum that stores the type of a config item +enum type_t { + u32, + i32, + f32 +}; + +// enum that stores the UI type of a config item +enum ui_type_t { + ui_type_none, + ui_type_slider, + ui_type_toggle, + ui_type_menu_toggle +}; + struct config_item { - char name[32]; + // Strings + char name[16]; char pretty_name[32]; + char type_string[16]; + char ui_type_string[16]; + + // Enums + type_t type; + ui_type_t ui_type; + + // Raw Value config_value value; }; diff --git a/src/web_core.h b/src/web_core.h index 0be53fd..9e75f42 100644 --- a/src/web_core.h +++ b/src/web_core.h @@ -8,6 +8,19 @@ void run_web() { // Write pending changes to LittleFS sync_configuration_to_file_system(); + + // Broadcast the current state to all clients + static uint32_t last_state_broadcast_ms = 0; + if (t_now_ms - last_state_broadcast_ms >= 100) { + last_state_broadcast_ms = t_now_ms; + + //uint32_t t_start = micros(); + broadcast_emotiscope_state(); + //uint32_t t_end = micros(); + + //printf("STATE TIME: %luus\n", t_end - t_start); + //printf("STATE HZ: %f\n", 1000000.0 / (float)(t_end - t_start)); + } } }, __func__ ); } \ No newline at end of file diff --git a/src/wireless.h b/src/wireless.h index d027c84..572edcf 100644 --- a/src/wireless.h +++ b/src/wireless.h @@ -109,43 +109,144 @@ bool load_section_at( char* section_buffer, char* command, int16_t* byte_index ) (*byte_index)++; } + //printf("LOADED SECTION: %s\n", section_buffer); + return hit_end_of_chunk; } -void parse_config_data(char* config_name, char* config_type, char* config_value, char* config_ui_type, char* config_preset_enabled){ - printf("CONFIG DATA: %s|%s|%s|%s|%s\n", config_name, config_type, config_value, config_ui_type, config_preset_enabled); +void set_config_value_by_pretty_name(char* config_pretty_name, char* new_config_value){ + config_item* config_location = reinterpret_cast(&configuration); + const uint16_t num_config_items = sizeof(configuration) / sizeof(config_item); + + for(uint16_t i = 0; i < num_config_items; i++){ + config_item* item = config_location + i; + type_t type = item->type; + + if(fastcmp(item->pretty_name, config_pretty_name)){ + if(type == u32){ + item->value.u32 = atoi(new_config_value); + //printf("Setting u32 %s: %d\n", item->name, item->value.u32); + } else if(type == i32){ + item->value.i32 = atoi(new_config_value); + //printf("Setting i32 %s: %d\n", item->name, item->value.i32); + } else if(type == f32){ + item->value.f32 = atof(new_config_value); + //printf("Setting f32 %s: %f\n", item->name, item->value.f32); + } else { + printf("ERROR: Unknown type in set_config_value_by_pretty_name\n"); + } - if(fastcmp(config_type, "float")){ - float value = atof(config_value); - printf("FLOAT VALUE: %f\n", value); - //place_float_in_config_by_key( TBD ); - } - else if(fastcmp(config_type, "int")){ - int value = atoi(config_value); - printf("INT VALUE: %i\n", value); - } - else if(fastcmp(config_type, "bool")){ - bool value = fastcmp(config_value, "true"); - printf("BOOL VALUE: %i\n", value); - } - else if(fastcmp(config_type, "string")){ - printf("STRING VALUE: %s\n", config_value); - } - else{ - printf("UNKNOWN CONFIG TYPE: %s\n", config_type); + break; + } } } void broadcast_emotiscope_state(){ char output_string[2048]; + char temp_buffer[128]; + + // Stats + memset(output_string, 0, 2048); + memset(temp_buffer, 0, 128); + + strcat(output_string, "EMO"); + strcat(output_string, "~stats"); + + memset(temp_buffer, 0, 128); + sprintf(temp_buffer, "|cpu_usage|%.3f", CPU_CORE_USAGE); + strcat(output_string, temp_buffer); + + memset(temp_buffer, 0, 128); + sprintf(temp_buffer, "|fps_cpu|%.3f", FPS_CPU); + strcat(output_string, temp_buffer); + + memset(temp_buffer, 0, 128); + sprintf(temp_buffer, "|fps_gpu|%.3f", FPS_GPU); + strcat(output_string, temp_buffer); + + memset(temp_buffer, 0, 128); + sprintf(temp_buffer, "|heap|%lu", esp_get_free_heap_size()); + strcat(output_string, temp_buffer); + + //printf("TX: %s\n", output_string); + websocket_handler.sendAll(output_string); + + // Configuration + memset(output_string, 0, 2048); + memset(temp_buffer, 0, 128); + + strcat(output_string, "EMO"); + strcat(output_string, "~config"); + + config_item* config_location = reinterpret_cast(&configuration); + uint16_t num_config_items = sizeof(configuration) / sizeof(config_item); + + for(uint16_t i = 0; i < num_config_items; i++){ + config_item item = *(config_location + i); + + strcat(output_string, "|"); + strcat(output_string, item.pretty_name); + strcat(output_string, "|"); + strcat(output_string, item.type_string); + strcat(output_string, "|"); + strcat(output_string, item.ui_type_string); + strcat(output_string, "|"); + + if(item.type == u32){ + memset(temp_buffer, 0, 128); + sprintf(temp_buffer, "%lu", item.value.u32); + strcat(output_string, temp_buffer); + } + else if(item.type == i32){ + memset(temp_buffer, 0, 128); + sprintf(temp_buffer, "%li", item.value.i32); + strcat(output_string, temp_buffer); + } + else if(item.type == f32){ + memset(temp_buffer, 0, 128); + sprintf(temp_buffer, "%.3f", item.value.f32); + strcat(output_string, temp_buffer); + } + else{ + printf("ERROR: Unknown type in broadcast_emotiscope_state\n"); + } + } + + //printf("TX: %s\n", output_string); + websocket_handler.sendAll(output_string); + + // Light Modes memset(output_string, 0, 2048); + memset(temp_buffer, 0, 128); + + strcat(output_string, "EMO"); + strcat(output_string, "~modes"); + + for(uint16_t i = 0; i < NUM_LIGHT_MODES; i++){ + light_mode_type_t type = light_modes[i].type; + if(type != LIGHT_MODE_TYPE_SYSTEM){ + strcat(output_string, "|"); + strcat(output_string, light_modes[i].name); + strcat(output_string, "|"); + + if(type == LIGHT_MODE_TYPE_ACTIVE){ + strcat(output_string, "0"); + } + else if(type == LIGHT_MODE_TYPE_INACTIVE){ + strcat(output_string, "1"); + } + else{ + printf("ERROR: Unknown light mode type in broadcast_emotiscope_state\n"); + } + } + } - // Packet Header - strcat(output_string, "EMO~"); + //printf("TX: %s\n", output_string); + websocket_handler.sendAll(output_string); } -void parse_emotiscope_state(char* command, PsychicWebSocketRequest *request){ - printf("Parsing Emotiscope State...\n"); +void parse_emotiscope_packet(char* command, PsychicWebSocketRequest *request){ + //printf("Parsing Emotiscope Packet...\n"); int16_t num_bytes = strlen(command); int16_t byte_index = 0; @@ -155,59 +256,50 @@ void parse_emotiscope_state(char* command, PsychicWebSocketRequest *request){ char chunk_type[32]; memset(chunk_type, 0, 32); - static int16_t config_data_index = 0; + int16_t config_data_index = 0; while(byte_index <= num_bytes){ bool chunk_ended = load_section_at(section_buffer, command, &byte_index); - printf("LOADED SECTION: %s\n", section_buffer); - if(fastcmp(chunk_type, "config")){ - static char config_name[32]; - static char config_type[32]; - static char config_value[32]; - static char config_ui_type[32]; - static char config_preset_enabled[32]; + + if(fastcmp(chunk_type, "set_config")){ + static char config_pretty_name[32]; + static char new_config_value[32]; if(config_data_index == 0){ - memcpy(config_name, section_buffer, 32); + memcpy(config_pretty_name, section_buffer, 32); config_data_index = 1; } else if(config_data_index == 1){ - memcpy(config_type, section_buffer, 32); - config_data_index = 2; - } - else if(config_data_index == 2){ - memcpy(config_value, section_buffer, 32); - config_data_index = 3; - } - else if(config_data_index == 3){ - memcpy(config_ui_type, section_buffer, 32); - config_data_index = 4; - } - else if(config_data_index == 4){ - memcpy(config_preset_enabled, section_buffer, 32); + memcpy(new_config_value, section_buffer, 32); config_data_index = 0; - parse_config_data(config_name, config_type, config_value, config_ui_type, config_preset_enabled); + set_config_value_by_pretty_name(config_pretty_name, new_config_value); + save_config_delayed(); } } else{ - printf("UNKNOWN CHUNK TYPE: %s\n", chunk_type); + if(chunk_type[0] == '\0'){ + //printf("PACKET HEADER: %s\n", section_buffer); + } + else{ + printf("UNKNOWN CHUNK TYPE: %s\n", chunk_type); + } } if(chunk_ended == true){ - printf("Chunk ended.\n"); + //printf("Chunk ended.\n"); if(byte_index < num_bytes){ // Prepare for new chunk type memset(chunk_type, 0, 32); load_section_at(section_buffer, command, &byte_index); memcpy(chunk_type, section_buffer, 32); - printf("NEW CHUNK TYPE: %s\n"); + printf("PACKET CHUNK TYPE: %s\n", chunk_type); config_data_index = 0; } else{ - printf("EOF\n"); + //printf("EOF\n"); } } } @@ -242,7 +334,7 @@ void init_web_server() { printf("RX: %s\n", command); if(command[0] == 'E' && command[1] == 'M' && command[2] == 'O'){ - parse_emotiscope_state(command, request); + parse_emotiscope_packet(command, request); } else{ parse_command(command, request);