From 3a81c7001823dae498f022c5e1ccd0df1a53f45b Mon Sep 17 00:00:00 2001 From: proddy Date: Wed, 5 Aug 2026 15:43:30 +0200 Subject: [PATCH 1/7] add DHCP workaround (disabled for now) --- src/core/network.cpp | 11 +++++++++++ src/core/network.h | 1 + 2 files changed, 12 insertions(+) diff --git a/src/core/network.cpp b/src/core/network.cpp index 96fc2f50d..3eee3ae14 100644 --- a/src/core/network.cpp +++ b/src/core/network.cpp @@ -539,6 +539,17 @@ void Network::startEthernet() { return; } + /* + // The Tasmota SDK is built with CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=2, so the Ethernet MAC is derived as + // a locally-administered address from base+1 instead of the universal base+3 that Arduino Core 2 used. + // Seed the MAC table with the old value before the EMAC driver reads it, so DHCP reservations survive an upgrade. + uint8_t eth_mac[6]; + if (esp_read_mac(eth_mac, ESP_MAC_BASE) == ESP_OK) { + eth_mac[5] += 3; + esp_iface_mac_addr_set(eth_mac, ESP_MAC_ETH); + } + */ + // reset power and add a delay as ETH doesn't not always start up correctly after a warm boot if (eth_power_ != -1) { pinMode(eth_power_, OUTPUT); diff --git a/src/core/network.h b/src/core/network.h index 92da60be3..d081f0232 100644 --- a/src/core/network.h +++ b/src/core/network.h @@ -20,6 +20,7 @@ #define EMSESP_NETWORK_H_ #ifndef EMSESP_STANDALONE +#include #include #include #include From 1956ff83861dec808d2db4bf2c1171dc14774baa Mon Sep 17 00:00:00 2001 From: proddy Date: Wed, 5 Aug 2026 15:43:40 +0200 Subject: [PATCH 2/7] fix LED flashing --- src/core/led.cpp | 612 ++++++++++++++++++++++++----------------------- 1 file changed, 314 insertions(+), 298 deletions(-) diff --git a/src/core/led.cpp b/src/core/led.cpp index 56a58fcc8..28de6180c 100644 --- a/src/core/led.cpp +++ b/src/core/led.cpp @@ -16,301 +16,317 @@ * along with this program. If not, see . */ -#include "led.h" -#include "emsesp.h" - -namespace emsesp { - -uuid::log::Logger LED::logger_{F_(led), uuid::log::Facility::KERN}; - -// initialise the LED, fetching the settings from the WebSettingsService -// set the LED to on or off when in normal operating mode -void LED::init() { - // copy the application settings - EMSESP::webSettingsService.read([&](WebSettings & settings) { - led_gpio_ = settings.led_gpio; - led_type_ = settings.led_type; - hide_led_ = settings.hide_led; - }); - - if (!led_gpio_) { // 0 means disabled - LOG_INFO("LED disabled"); - return; - } - - // for safety - if (!led_type_) { - pinMode(led_gpio_, OUTPUT); - } - - reset_led(); // start with LED in default state, depending on if it's hidden or not -} - -// handle LED routine -// called from the System::loop() -// returns true if the LED flash is active, i.e its a lock down state -bool LED::loop(uint8_t healthcheck, bool button_busy) { - // if LED flashing is active it means its about to perform a factory reset, so don't do anything else and keep it flashing - if (led_fast_flash_timer_) { - led_fast_flash(); - return true; - } - - // the user-requested LED blink always has preference - if (!is_user_led_blink_) { - // check for button press. - // if button is pressed, show LED (yellow on RGB LED, on/off on standard LED) - // it will turn off on the next loop cycle - if (last_button_busy_ != button_busy) { - last_button_busy_ = button_busy; - set_led(button_busy ? Color::OFF : Color::YELLOW); // Yellow - return false; - } - - // check the system health. - // Set the sequence accordingly, only if the healthcheck is not 0 and has changed - if (healthcheck != previous_healthcheck_) { - previous_healthcheck_ = healthcheck; - color_steps_[0] = Color::OFF; - color_steps_[1] = Color::OFF; - color_steps_[2] = Color::OFF; - - // if the healthcheck is 0, i.e. system is healthy, reset the LED - if (healthcheck == 0) { - reset_led(); - return false; - } - - // 1 flash (blue) is the EMS bus is not connected - // 2 flashes (red, red) if the network (wifi or ethernet) is not connected - // 3 flashes (red, red, blue) is both the bus and the network are not connected - bool no_network = (healthcheck & System::HEALTHCHECK_NO_NETWORK) == System::HEALTHCHECK_NO_NETWORK; - bool no_bus = (healthcheck & System::HEALTHCHECK_NO_BUS) == System::HEALTHCHECK_NO_BUS; - - // set step 1 - if (no_network) { - color_steps_[0] = Color::RED; // red, no network - } else if (no_bus) { - color_steps_[0] = Color::BLUE; // blue, no bus - } - - // set step 2 - if (no_network) { - color_steps_[1] = Color::RED; // red, no network - } - - // set step 3 - if (no_network && no_bus) { - color_steps_[2] = Color::BLUE; // blue, no network and no bus - } - } - } - - // show the LED status based on the healthcheck and button busy status - sequence_led(); - - return false; -} - -// turn the LED back it's default state depending on if it's hidden or not -void LED::reset_led() { - is_user_led_blink_ = false; - set_led(hide_led_ ? Color::OFF : Color::GREEN); // Green - color_steps_[0] = Color::OFF; - color_steps_[1] = Color::OFF; - color_steps_[2] = Color::OFF; -} - -// LED flash every few ms and then perform a factory reset -void LED::led_fast_flash() { - uint32_t current_time = uuid::get_uptime(); - - if (current_time - last_toggle_time_ >= LED_FLASH_INTERVAL_MS) { - led_flash_state_ = !led_flash_state_; - last_toggle_time_ = current_time; - set_led(led_flash_state_ ? Color::YELLOW : Color::OFF); // Yellow - } - - // after duration, turn off the LED, and call the format command - if (current_time - led_flash_start_time_ >= led_flash_duration_) { - set_led(Color::OFF); - led_fast_flash_timer_ = false; -#ifndef EMSESP_DEBUG - System::command_format(nullptr, 0); // Execute format operation, unless in debug mode -#endif - } -} - -// set LED on/off or RGB color -// ignores whether the LED is hidden or not (if hide_led_ is set) -void LED::set_led(Color color) { - if (!led_gpio_) { - return; - } - - // RGB lookup table indexed by Color enum (must match enum order in led.h) - static constexpr uint8_t B = RGB_LED_BRIGHTNESS; - static constexpr uint8_t H = RGB_LED_BRIGHTNESS / 2; - static constexpr uint8_t rgb_table[][3] = { - {0, 0, 0}, // OFF - {B, B, B}, // ON (white) - {B, 0, 0}, // RED - {0, B, 0}, // GREEN - {0, 0, B}, // BLUE - {B, B, 0}, // YELLOW - {B, H, 0}, // ORANGE - {0, B, B}, // CYAN - {H, 0, H} // PINK - }; - - const uint8_t color_idx = static_cast(color); - const uint8_t idx = (color_idx < sizeof(rgb_table) / sizeof(rgb_table[0])) ? color_idx : static_cast(Color::OFF); - const uint8_t red = rgb_table[idx][0]; - const uint8_t green = rgb_table[idx][1]; - const uint8_t blue = rgb_table[idx][2]; - - if (led_type_) { - rgbLedWrite(led_gpio_, red, green, blue); - } else { - digitalWrite(led_gpio_, (red == 0 && green == 0 && blue == 0) || color == Color::OFF ? !LED_ON : LED_ON); - } -} - -// set LED custom routine -// For example: /api/system/led?data=red:blink1 -// For older non-RGB models, the colour would default to just being on. -bool LED::set_custom_led_routine(std::string color, std::string pattern) { - static constexpr struct { - const char * name; - Color value; - } color_map[] = { - {"off", Color::OFF}, - {"on", Color::ON}, - {"white", Color::ON}, - {"red", Color::RED}, - {"green", Color::GREEN}, - {"blue", Color::BLUE}, - {"yellow", Color::YELLOW}, - {"orange", Color::ORANGE}, - {"cyan", Color::CYAN}, - {"pink", Color::PINK}, - }; - - Color color_type = Color::OFF; - bool color_matched = false; - for (const auto & entry : color_map) { - if (color == entry.name) { - color_type = entry.value; - color_matched = true; - break; - } - } - if (!color_matched) { - return false; - } - - // reset the color steps - color_steps_[0] = Color::OFF; - color_steps_[1] = Color::OFF; - color_steps_[2] = Color::OFF; - - // blink patterns - if (pattern == "blink1") { - color_steps_[0] = color_type; - } else if (pattern == "blink2") { - color_steps_[0] = color_type; - color_steps_[1] = color_type; - } else if (pattern == "blink3") { - color_steps_[0] = color_type; - color_steps_[1] = color_type; - color_steps_[2] = color_type; - - // special patterns, ignores the user color - } else if (pattern == "rgb") { - color_steps_[0] = Color::RED; - color_steps_[1] = Color::GREEN; - color_steps_[2] = Color::BLUE; - } else if (pattern == "cpc") { - color_steps_[0] = Color::CYAN; - color_steps_[1] = Color::PINK; - color_steps_[2] = Color::CYAN; - } else { - return false; // pattern not recognized - } - - is_user_led_blink_ = true; // user routine is active - - // when this is called we want the sequence_led to restart immediately and skip the long pause - led_long_timer_ = uuid::get_uptime() + HEALTHCHECK_LED_FLASH_FAST_DURATION + 200UL; - - return true; -} - -// uses LED to show system health and user-requested LED blinks -// it works in a batch of 3 configured flashes, then a long pause -// the timing is different for user-requested LED blink and for system healthcheck -void LED::sequence_led() { - // first long pause before we start flashing - auto current_time = uuid::get_uptime(); - if (led_long_timer_ - && (uint32_t)(current_time - led_long_timer_) >= (is_user_led_blink_ ? HEALTHCHECK_LED_LONG_FAST_DURATION : HEALTHCHECK_LED_LONG_DURATION)) { - led_short_timer_ = current_time; // start the short timer - led_long_timer_ = 0; // stop long timer - led_flash_step_ = 1; // enable the short flash timer - } - - // the flash timer which starts after the long pause - if (led_flash_step_ - && (uint32_t)(current_time - led_short_timer_) >= (is_user_led_blink_ ? HEALTHCHECK_LED_FLASH_FAST_DURATION : HEALTHCHECK_LED_FLASH_DURATION)) { - led_long_timer_ = 0; // stop the long timer - led_short_timer_ = current_time; - - if (++led_flash_step_ == 8) { - // finished first iteration, reset the whole sequence, turn off LED - led_long_timer_ = uuid::get_uptime(); - led_flash_step_ = 0; - set_led(Color::OFF); // turn off the LED - - // if we're running a user-requested LED blink, turn it off and go back to the healthcheck sequence - if (is_user_led_blink_) { - is_user_led_blink_ = false; - previous_healthcheck_ = System::HEALTHCHECK_RESET; // this will force the healthcheck to be checked again - } - return; - } - - if (led_flash_step_ % 2) { - // handle the three step events (on odd numbers 3,5,7 etc). see if we need to set a LED color - switch (led_flash_step_) { - case 3: // first flash - set_led(color_steps_[0]); - break; - case 5: // second flash - set_led(color_steps_[1]); - break; - case 7: // third flash - set_led(color_steps_[2]); - break; - default: - break; - } - } else { - set_led(Color::OFF); // turn off on even number count, to make it flash - } - } -} - -// Start the LED flash timer - duration in seconds -void LED::start_led_fast_flash(uint8_t duration) { - // Don't start if already running - if (led_fast_flash_timer_) { - return; - } - - // Reset counter and state - led_flash_start_time_ = uuid::get_uptime(); // current time - led_flash_duration_ = (uint32_t)duration * 1000; // duration in milliseconds - led_fast_flash_timer_ = true; // it's active -} - -} // namespace emsesp + #include "led.h" + #include "emsesp.h" + + namespace emsesp { + + uuid::log::Logger LED::logger_{F_(led), uuid::log::Facility::KERN}; + + // initialise the LED, fetching the settings from the WebSettingsService + // set the LED to on or off when in normal operating mode + void LED::init() { + // copy the application settings + EMSESP::webSettingsService.read([&](WebSettings & settings) { + led_gpio_ = settings.led_gpio; + led_type_ = settings.led_type; + hide_led_ = settings.hide_led; + }); + + if (!led_gpio_) { // 0 means disabled + LOG_INFO("LED disabled"); + return; + } + + // for safety + if (!led_type_) { + pinMode(led_gpio_, OUTPUT); + } + + reset_led(); // start with LED in default state, depending on if it's hidden or not + } + + // handle LED routine + // called from the System::loop() + // returns true if the LED flash is active, i.e its a lock down state + bool LED::loop(uint8_t healthcheck, bool button_busy) { + // if LED flashing is active it means its about to perform a factory reset, so don't do anything else and keep it flashing + if (led_fast_flash_timer_) { + led_fast_flash(); + return true; + } + + // the user-requested LED blink always has preference + if (!is_user_led_blink_) { + // check for button press. + // while the button is held show the LED (yellow on RGB LED, on/off on standard LED), + // and on release go back to the default state and re-check the health on the next cycle + if (last_button_busy_ != button_busy) { + last_button_busy_ = button_busy; + if (button_busy) { + set_led(Color::YELLOW); // Yellow + } else { + reset_led(); + previous_healthcheck_ = System::HEALTHCHECK_RESET; + } + return false; + } + + // check the system health. + // Set the sequence accordingly, only if the healthcheck is not 0 and has changed + if (healthcheck != previous_healthcheck_) { + previous_healthcheck_ = healthcheck; + color_steps_[0] = Color::OFF; + color_steps_[1] = Color::OFF; + color_steps_[2] = Color::OFF; + + // if the healthcheck is 0, i.e. system is healthy, reset the LED + if (healthcheck == 0) { + reset_led(); + return false; + } + + // 1 flash (blue) is the EMS bus is not connected + // 2 flashes (red, red) if the network (wifi or ethernet) is not connected + // 3 flashes (red, red, blue) is both the bus and the network are not connected + bool no_network = (healthcheck & System::HEALTHCHECK_NO_NETWORK) == System::HEALTHCHECK_NO_NETWORK; + bool no_bus = (healthcheck & System::HEALTHCHECK_NO_BUS) == System::HEALTHCHECK_NO_BUS; + + // set step 1 + if (no_network) { + color_steps_[0] = Color::RED; // red, no network + } else if (no_bus) { + color_steps_[0] = Color::BLUE; // blue, no bus + } + + // set step 2 + if (no_network) { + color_steps_[1] = Color::RED; // red, no network + } + + // set step 3 + if (no_network && no_bus) { + color_steps_[2] = Color::BLUE; // blue, no network and no bus + } + } + + // there's nothing to flash, so leave the LED in the state reset_led() gave it. + // Running the sequence here would keep writing Color::OFF and a healthy system would never show green. + if (healthcheck == 0 || button_busy) { + return false; + } + } + + // show the LED status based on the healthcheck and button busy status + sequence_led(); + + return false; + } + + // turn the LED back it's default state depending on if it's hidden or not + void LED::reset_led() { + is_user_led_blink_ = false; + set_led(hide_led_ ? Color::OFF : Color::GREEN); // Green + color_steps_[0] = Color::OFF; + color_steps_[1] = Color::OFF; + color_steps_[2] = Color::OFF; + + // rewind the sequence so it starts from the top if the health degrades again + led_long_timer_ = 1; // 1 will kick it off immediately + led_short_timer_ = 0; + led_flash_step_ = 0; + } + + // LED flash every few ms and then perform a factory reset + void LED::led_fast_flash() { + uint32_t current_time = uuid::get_uptime(); + + if (current_time - last_toggle_time_ >= LED_FLASH_INTERVAL_MS) { + led_flash_state_ = !led_flash_state_; + last_toggle_time_ = current_time; + set_led(led_flash_state_ ? Color::YELLOW : Color::OFF); // Yellow + } + + // after duration, turn off the LED, and call the format command + if (current_time - led_flash_start_time_ >= led_flash_duration_) { + set_led(Color::OFF); + led_fast_flash_timer_ = false; + #ifndef EMSESP_DEBUG + System::command_format(nullptr, 0); // Execute format operation, unless in debug mode + #endif + } + } + + // set LED on/off or RGB color + // ignores whether the LED is hidden or not (if hide_led_ is set) + void LED::set_led(Color color) { + if (!led_gpio_) { + return; + } + + // RGB lookup table indexed by Color enum (must match enum order in led.h) + static constexpr uint8_t B = RGB_LED_BRIGHTNESS; + static constexpr uint8_t H = RGB_LED_BRIGHTNESS / 2; + static constexpr uint8_t rgb_table[][3] = { + {0, 0, 0}, // OFF + {B, B, B}, // ON (white) + {B, 0, 0}, // RED + {0, B, 0}, // GREEN + {0, 0, B}, // BLUE + {B, B, 0}, // YELLOW + {B, H, 0}, // ORANGE + {0, B, B}, // CYAN + {H, 0, H} // PINK + }; + + const uint8_t color_idx = static_cast(color); + const uint8_t idx = (color_idx < sizeof(rgb_table) / sizeof(rgb_table[0])) ? color_idx : static_cast(Color::OFF); + const uint8_t red = rgb_table[idx][0]; + const uint8_t green = rgb_table[idx][1]; + const uint8_t blue = rgb_table[idx][2]; + + if (led_type_) { + rgbLedWrite(led_gpio_, red, green, blue); + } else { + digitalWrite(led_gpio_, (red == 0 && green == 0 && blue == 0) || color == Color::OFF ? !LED_ON : LED_ON); + } + } + + // set LED custom routine + // For example: /api/system/led?data=red:blink1 + // For older non-RGB models, the colour would default to just being on. + bool LED::set_custom_led_routine(std::string color, std::string pattern) { + static constexpr struct { + const char * name; + Color value; + } color_map[] = { + {"off", Color::OFF}, + {"on", Color::ON}, + {"white", Color::ON}, + {"red", Color::RED}, + {"green", Color::GREEN}, + {"blue", Color::BLUE}, + {"yellow", Color::YELLOW}, + {"orange", Color::ORANGE}, + {"cyan", Color::CYAN}, + {"pink", Color::PINK}, + }; + + Color color_type = Color::OFF; + bool color_matched = false; + for (const auto & entry : color_map) { + if (color == entry.name) { + color_type = entry.value; + color_matched = true; + break; + } + } + if (!color_matched) { + return false; + } + + // reset the color steps + color_steps_[0] = Color::OFF; + color_steps_[1] = Color::OFF; + color_steps_[2] = Color::OFF; + + // blink patterns + if (pattern == "blink1") { + color_steps_[0] = color_type; + } else if (pattern == "blink2") { + color_steps_[0] = color_type; + color_steps_[1] = color_type; + } else if (pattern == "blink3") { + color_steps_[0] = color_type; + color_steps_[1] = color_type; + color_steps_[2] = color_type; + + // special patterns, ignores the user color + } else if (pattern == "rgb") { + color_steps_[0] = Color::RED; + color_steps_[1] = Color::GREEN; + color_steps_[2] = Color::BLUE; + } else if (pattern == "cpc") { + color_steps_[0] = Color::CYAN; + color_steps_[1] = Color::PINK; + color_steps_[2] = Color::CYAN; + } else { + return false; // pattern not recognized + } + + is_user_led_blink_ = true; // user routine is active + + // when this is called we want the sequence_led to restart immediately and skip the long pause + led_long_timer_ = uuid::get_uptime() + HEALTHCHECK_LED_FLASH_FAST_DURATION + 200UL; + + return true; + } + + // uses LED to show system health and user-requested LED blinks + // it works in a batch of 3 configured flashes, then a long pause + // the timing is different for user-requested LED blink and for system healthcheck + void LED::sequence_led() { + // first long pause before we start flashing + auto current_time = uuid::get_uptime(); + if (led_long_timer_ + && (uint32_t)(current_time - led_long_timer_) >= (is_user_led_blink_ ? HEALTHCHECK_LED_LONG_FAST_DURATION : HEALTHCHECK_LED_LONG_DURATION)) { + led_short_timer_ = current_time; // start the short timer + led_long_timer_ = 0; // stop long timer + led_flash_step_ = 1; // enable the short flash timer + } + + // the flash timer which starts after the long pause + if (led_flash_step_ + && (uint32_t)(current_time - led_short_timer_) >= (is_user_led_blink_ ? HEALTHCHECK_LED_FLASH_FAST_DURATION : HEALTHCHECK_LED_FLASH_DURATION)) { + led_long_timer_ = 0; // stop the long timer + led_short_timer_ = current_time; + + if (++led_flash_step_ == 8) { + // finished first iteration, reset the whole sequence, turn off LED + led_long_timer_ = uuid::get_uptime(); + led_flash_step_ = 0; + set_led(Color::OFF); // turn off the LED + + // if we're running a user-requested LED blink, turn it off and go back to the healthcheck sequence + if (is_user_led_blink_) { + is_user_led_blink_ = false; + previous_healthcheck_ = System::HEALTHCHECK_RESET; // this will force the healthcheck to be checked again + } + return; + } + + if (led_flash_step_ % 2) { + // handle the three step events (on odd numbers 3,5,7 etc). see if we need to set a LED color + switch (led_flash_step_) { + case 3: // first flash + set_led(color_steps_[0]); + break; + case 5: // second flash + set_led(color_steps_[1]); + break; + case 7: // third flash + set_led(color_steps_[2]); + break; + default: + break; + } + } else { + set_led(Color::OFF); // turn off on even number count, to make it flash + } + } + } + + // Start the LED flash timer - duration in seconds + void LED::start_led_fast_flash(uint8_t duration) { + // Don't start if already running + if (led_fast_flash_timer_) { + return; + } + + // Reset counter and state + led_flash_start_time_ = uuid::get_uptime(); // current time + led_flash_duration_ = (uint32_t)duration * 1000; // duration in milliseconds + led_fast_flash_timer_ = true; // it's active + } + + } // namespace emsesp \ No newline at end of file From 0f396200a22bd3ef5749bb13a0a264494177c02a Mon Sep 17 00:00:00 2001 From: proddy Date: Wed, 5 Aug 2026 15:43:51 +0200 Subject: [PATCH 3/7] update with dev.2 changes --- CHANGELOG_LATEST.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index e25ea5919..d0f4932be 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -16,6 +16,8 @@ This release is based on the latest Espressif/Arduino core version 3. It brings ## Fixed - shunting yard show json +- LED stayed off on a healthy system when "Disable LED" was unchecked +- Ethernet MAC address changed with the new SDK, breaking DHCP reservations (currently disabled) ## Changed From 1b2371c67a5e3d505e4edd0722552c5219d07352 Mon Sep 17 00:00:00 2001 From: proddy Date: Thu, 6 Aug 2026 12:10:21 +0200 Subject: [PATCH 4/7] scan all dns slots, prevent STA warning on boot --- src/core/system.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/core/system.cpp b/src/core/system.cpp index d39618fe5..6c98ba8c3 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -93,6 +93,20 @@ uint32_t System::min_free_mem_; std::vector> System::valid_system_gpios_; std::vector> System::used_gpios_; +#ifndef EMSESP_STANDALONE +// The DNS slots are shared between IPv4 and IPv6, so with IPv6 enabled the first slot can hold an +// IPv6 server. Pick the first IPv4 one so it matches the label we print it under. +static IPAddress dns_ipv4(const NetworkInterface & netif) { + for (uint8_t i = 0; i < ESP_NETIF_DNS_MAX; i++) { + IPAddress ip = netif.dnsIP(i); + if (ip.type() == IPv4 && static_cast(ip) != 0) { + return ip; + } + } + return IPAddress(); +} +#endif + // find the index of the language // 0 = EN, 1 = DE, etc... uint8_t System::language_index() { @@ -858,8 +872,7 @@ void System::send_info_mqtt() { doc["MAC"] = WiFi.macAddress(); doc["IPv4 address"] = uuid::printable_to_string(WiFi.localIP()) + "/" + uuid::printable_to_string(WiFi.subnetMask()); doc["IPv4 gateway"] = uuid::printable_to_string(WiFi.gatewayIP()); - doc["IPv4 nameserver"] = uuid::printable_to_string(WiFi.dnsIP()); - + doc["IPv4 DNS Server"] = uuid::printable_to_string(dns_ipv4(WiFi.STA)); if (WiFi.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.linkLocalIPv6().toString() != "::") { doc["IPv6 address"] = uuid::printable_to_string(WiFi.linkLocalIPv6()); } @@ -1168,7 +1181,7 @@ void System::show_system(uuid::console::Shell & shell) { shell.printfln(" Hostname: %s", WiFi.getHostname()); shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(WiFi.localIP()).c_str(), uuid::printable_to_string(WiFi.subnetMask()).c_str()); shell.printfln(" IPv4 gateway: %s", uuid::printable_to_string(WiFi.gatewayIP()).c_str()); - shell.printfln(" IPv4 nameserver: %s", uuid::printable_to_string(WiFi.dnsIP()).c_str()); + shell.printfln(" IPv4 DNS Server: %s", uuid::printable_to_string(dns_ipv4(WiFi.STA)).c_str()); if (WiFi.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.linkLocalIPv6().toString() != "::") { shell.printfln(" IPv6 address: %s", uuid::printable_to_string(WiFi.linkLocalIPv6()).c_str()); } @@ -1201,7 +1214,7 @@ void System::show_system(uuid::console::Shell & shell) { shell.printfln(" Hostname: %s", ETH.getHostname()); shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str()); shell.printfln(" IPv4 gateway: %s", uuid::printable_to_string(ETH.gatewayIP()).c_str()); - shell.printfln(" IPv4 nameserver: %s", uuid::printable_to_string(ETH.dnsIP()).c_str()); + shell.printfln(" IPv4 DNS Server: %s", uuid::printable_to_string(dns_ipv4(ETH)).c_str()); if (ETH.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && ETH.linkLocalIPv6().toString() != "::") { shell.printfln(" IPv6 address: %s", uuid::printable_to_string(ETH.linkLocalIPv6()).c_str()); } From dac1e1a69c18a155f60b211412a3dce000c7a8a5 Mon Sep 17 00:00:00 2001 From: proddy Date: Thu, 6 Aug 2026 12:10:39 +0200 Subject: [PATCH 5/7] prevent STA warning on boot --- src/core/network.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/network.cpp b/src/core/network.cpp index 3eee3ae14..467171626 100644 --- a/src/core/network.cpp +++ b/src/core/network.cpp @@ -82,7 +82,13 @@ void Network::begin() { WiFi.persistent(false); WiFi.setAutoReconnect(false); WiFi.mode(WIFI_STA); - WiFi.disconnect(true, true); // wipe old settings in NVS. Will give a warning on boot but can be ignored. + + if (WiFi.STA.started()) { + WiFi.disconnect(true, true); // wipe old settings; only when STA is up + } else { + WiFi.disconnect(true, false); // disconnect/off without erase, so no warning is shown + } + WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); WiFi.setHostname(hostname_.c_str()); // updates shared default_hostname buffer WiFi.enableSTA(true); // creates the STA netif From 901721fb99ccba0c53cec6017f00155bc52082c7 Mon Sep 17 00:00:00 2001 From: proddy Date: Thu, 6 Aug 2026 12:10:45 +0200 Subject: [PATCH 6/7] pkg update --- CHANGELOG_LATEST.md | 1 + interface/package.json | 10 +- interface/pnpm-lock.yaml | 443 +++++++++++++++++---------------------- mock-api/package.json | 2 +- 4 files changed, 199 insertions(+), 257 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index d0f4932be..a54f31db6 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -18,6 +18,7 @@ This release is based on the latest Espressif/Arduino core version 3. It brings - shunting yard show json - LED stayed off on a healthy system when "Disable LED" was unchecked - Ethernet MAC address changed with the new SDK, breaking DHCP reservations (currently disabled) +- "IPv4 nameserver" showed an IPv6 address when IPv6 was in use ## Changed diff --git a/interface/package.json b/interface/package.json index a835f59f3..9e8fdc7ed 100644 --- a/interface/package.json +++ b/interface/package.json @@ -26,8 +26,8 @@ "@alova/adapter-xhr": "2.3.1", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", - "@mui/icons-material": "^9.2.0", - "@mui/material": "^9.2.0", + "@mui/icons-material": "^9.3.0", + "@mui/material": "^9.3.0", "@table-library/react-table-library": "4.1.15", "alova": "^3.5.3", "jwt-decode": "^4.0.0", @@ -52,11 +52,11 @@ "mime-types": "^3.0.2", "prettier": "^3.9.6", "rollup-plugin-visualizer": "^7.0.1", - "terser": "^5.49.0", + "terser": "^5.49.1", "typescript": "^6.0.3", - "typescript-eslint": "^8.65.0", + "typescript-eslint": "^8.66.0", "vite": "^8.2.0", "vite-plugin-imagemin": "^0.6.1" }, - "packageManager": "pnpm@11.18.0+sha512.33d83c77da82f49fba836925c6f1b841181ec3132b670639bd012f7075f5c7cf634c5f870147c19aae7478fac01df09d8892e880454896edd23ee9b33757563c" + "packageManager": "pnpm@11.20.0+sha512.9a6f330a95b66446ea088faf1521405a8a01f07fde7124cc9958dfed52d4bb436737e65b08f85f37b46fcba375092558ac51262b816844b22f63406ed166bfee" } diff --git a/interface/pnpm-lock.yaml b/interface/pnpm-lock.yaml index 126709bab..12dfc57fb 100644 --- a/interface/pnpm-lock.yaml +++ b/interface/pnpm-lock.yaml @@ -18,11 +18,11 @@ importers: specifier: ^11.14.1 version: 11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2) '@mui/icons-material': - specifier: ^9.2.0 - version: 9.2.0(@mui/material@9.2.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/react@19.2.18)(react@19.2.8) + specifier: ^9.3.0 + version: 9.3.0(@mui/material@9.3.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/react@19.2.18)(react@19.2.8) '@mui/material': - specifier: ^9.2.0 - version: 9.2.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + specifier: ^9.3.0 + version: 9.3.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) '@table-library/react-table-library': specifier: 4.1.15 version: 4.1.15(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(react-dom@19.2.8(react@19.2.8))(react@19.2.8) @@ -56,7 +56,7 @@ importers: version: 10.0.1(eslint@10.8.0(supports-color@10.2.2)) '@preact/preset-vite': specifier: ^2.10.6 - version: 2.10.6(@babel/core@7.29.7(supports-color@10.2.2))(preact@10.29.8)(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.0)) + version: 2.10.6(@babel/core@7.29.7(supports-color@10.2.2))(preact@10.29.8)(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.1)) '@trivago/prettier-plugin-sort-imports': specifier: ^6.0.2 version: 6.0.2(prettier@3.9.6)(supports-color@10.2.2) @@ -89,22 +89,22 @@ importers: version: 3.9.6 rollup-plugin-visualizer: specifier: ^7.0.1 - version: 7.0.1(rolldown@1.2.1) + version: 7.0.1(rolldown@1.2.2) terser: - specifier: ^5.49.0 - version: 5.49.0 + specifier: ^5.49.1 + version: 5.49.1 typescript: specifier: ^6.0.3 version: 6.0.3 typescript-eslint: - specifier: ^8.65.0 - version: 8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + specifier: ^8.66.0 + version: 8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) vite: specifier: ^8.2.0 - version: 8.2.0(@types/node@26.1.2)(terser@5.49.0) + version: 8.2.0(@types/node@26.1.2)(terser@5.49.1) vite-plugin-imagemin: specifier: ^0.6.1 - version: 0.6.1(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.0)) + version: 0.6.1(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.1)) packages: @@ -216,15 +216,6 @@ packages: resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} engines: {node: '>=6.9.0'} - '@emnapi/core@2.0.0-alpha.3': - resolution: {integrity: sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g==} - - '@emnapi/runtime@2.0.0-alpha.3': - resolution: {integrity: sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA==} - - '@emnapi/wasi-threads@2.0.1': - resolution: {integrity: sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ==} - '@emotion/babel-plugin@11.13.5': resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} @@ -363,27 +354,27 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@mui/core-downloads-tracker@9.2.0': - resolution: {integrity: sha512-+XMav+ZaXkZKUFUgzjrfMEedfyJKxxviAske2q8N8CWDMeqZdDU2lWMkiUPiB388hGaDqhwvOAwkrsc/pUyp8g==} + '@mui/core-downloads-tracker@9.3.0': + resolution: {integrity: sha512-CrjNKhozfI6kSbD4bvfS8Nx+eFOVX/I5Tb3L73YBXSG0e4PyYbEwu03lp7AOM/ERdceQQrpBnQeSgL4FMZO5mg==} - '@mui/icons-material@9.2.0': - resolution: {integrity: sha512-VgBd3z7Qc3vd/thcNSMC03nHRh/U4DzMUd+1dRyJTbm/hGo7+N6N4GDuJZDNHa6LZhhwG6Cu1X3DNvrVv8sNag==} + '@mui/icons-material@9.3.0': + resolution: {integrity: sha512-6kk+cbt7fyehTRIrt3LyeoD4C36lX0biR1NMnwy0Wz7Sj6lwOh6ghY5BZzd1UncyOZGCmTZROBQxSPawcKES7A==} engines: {node: '>=14.0.0'} peerDependencies: - '@mui/material': ^9.2.0 + '@mui/material': ^9.3.0 '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: '@types/react': optional: true - '@mui/material@9.2.0': - resolution: {integrity: sha512-+YTRSgGKGrrRo2XJZXs7JRA6qHoHWvNtxyqxnrRJTBmIuLOUpxxh7m4G9lF4tWberxGFY+EqkkRPgJCl+fSMJg==} + '@mui/material@9.3.0': + resolution: {integrity: sha512-H9WJkuaT7YthTOnz8ecygQoKZNVqvgZsTv/oJl6ttalfg6F1MkEi4fx/4j8f5+ju4U9mPX+lALLEZGVT9Jb3Gg==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.5.0 '@emotion/styled': ^11.3.0 - '@mui/material-pigment-css': ^9.2.0 + '@mui/material-pigment-css': ^9.3.0 '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -397,8 +388,8 @@ packages: '@types/react': optional: true - '@mui/private-theming@9.2.0': - resolution: {integrity: sha512-w9wpyDxGPGnAACPB2hKhCDmILJIAvQxrfjUbIAEa0AznX1rOjaz5N+yB1uuw8ixnJcpEh/tPbD9oEe19wcWPHw==} + '@mui/private-theming@9.3.0': + resolution: {integrity: sha512-ERvqk5pejf9aRnQcDILSWGtFmsEMiVxlQ4+xsVCjsEvmK0fV9BiVP/cQwAF5dwyDFbve4lTrlcgeFEecVzTNiA==} engines: {node: '>=14.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -407,8 +398,8 @@ packages: '@types/react': optional: true - '@mui/styled-engine@9.1.1': - resolution: {integrity: sha512-neaYKdJfvEG54q8efHLJR7swpHG/gfSv9xGqW5iTSMsubD7yPCPFrhVBt284j1DOF3uZaaDJSHQL7gz6jGF21Q==} + '@mui/styled-engine@9.3.0': + resolution: {integrity: sha512-x9+KYxhjoHYZ4nioxdKnvQWdw0RScbhoZfQ4tv3Db742683U3wlYSp6zV6Us78dMFnKnyTrPTkQKyutp14gnKA==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.4.1 @@ -420,8 +411,8 @@ packages: '@emotion/styled': optional: true - '@mui/system@9.2.0': - resolution: {integrity: sha512-YvUJwKoGVtbnOm2PyPi5TvX2d1rOA6sqSpEWVs4WmXNIaFTuYmNUaVdU2o1NKUEe31URnD3E8ZVUMcsLQXwcYg==} + '@mui/system@9.3.0': + resolution: {integrity: sha512-0l4LqHJxZj65xSrioniGsxm7VNoGXonPo203oZjhBUvIDPeBqRTb7Mqc45Qxs6sO6WGR7WE/9cJ6lb4lkvHkjg==} engines: {node: '>=14.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -436,16 +427,16 @@ packages: '@types/react': optional: true - '@mui/types@9.1.1': - resolution: {integrity: sha512-Zjt7u8wNvDg40rPTGoL+TnfkpuSKjwubsNSFRH1KAVZLcaV4I3AFNHIFbvH7p4F3alEibSbdd90xAgn5Rnfndg==} + '@mui/types@9.3.0': + resolution: {integrity: sha512-2JSxyfpEFWNUB2vKs/T1BvkfyNisMHWph8bLMj8T0uHwmLl/0qfAwQkfwMT6kxLXN9uIum9AEbECXU8er3amIg==} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: '@types/react': optional: true - '@mui/utils@9.2.0': - resolution: {integrity: sha512-OsUH5zhlSOM4xmLl53+agug1M1UyWb4zxFxWQCqwKTKUeQPvTENtg3JhrroBD2qpCLKsX5W/DYGERJ4mBUbc8g==} + '@mui/utils@9.3.0': + resolution: {integrity: sha512-2HZdHwWJ6eB+7lVGSOHsByGw8jeRulT4g0NZ608Wb8Q57DE2jbNqrWPFuJsvkQQiBiTmlpvQL3i+/62zsiPrkw==} engines: {node: '>=14.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -454,13 +445,6 @@ packages: '@types/react': optional: true - '@napi-rs/wasm-runtime@1.2.2': - resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} - peerDependencies: - '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.3 - '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.3 - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -502,96 +486,92 @@ packages: preact: ^10.4.0 || ^11.0.0-0 vite: '>=2.0.0' - '@rolldown/binding-android-arm64@1.2.1': - resolution: {integrity: sha512-02hOeOSryYxVrOIphmLAsqnCJWxwlzFk+pEt/N/i6OgT3lShHO7xGCU5cpgchRDHboAEbSjzgGh+O/u1GswQmA==} + '@rolldown/binding-android-arm64@1.2.2': + resolution: {integrity: sha512-l7x215OGvo1s52JWmR8U/DAVzEDWBCIbTm28aeJV/WDTSHgcKXaZTuBT0hJMs5NggilfJTW3clZVvd24yfKJxA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.2.1': - resolution: {integrity: sha512-fMsTOnN0OjFm3CyppWPitKnc8UlliVARUULW6cfU6AIqjdtgmSFWSk9vecHzZduv/yMWIHDlRhM1e8Iff9uAfA==} + '@rolldown/binding-darwin-arm64@1.2.2': + resolution: {integrity: sha512-9u9Xv6c1AJZT0FfwH5vrMG5Jjcwhc1MlyrPu0XfTqkzsmqfks2M6W/o5XwAJgVVN/jHpqqngC1WevHKKTIUtIA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.2.1': - resolution: {integrity: sha512-1wjKdz/XLGKHaTNHjQveQ/B23TKx4ItAqm1JbyVuvNPc4Ze0Fb48s49TAd/2zcplPl8okE/UbTgmlVfwT7eFeQ==} + '@rolldown/binding-darwin-x64@1.2.2': + resolution: {integrity: sha512-9W1mbGZAfW3oqd85bhBkmpyHCCzL1TeG/zFFP3vg7b0rlly8cxOcre5nXwz+LHazCwac2MNWgPdPCHndABjpWQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.2.1': - resolution: {integrity: sha512-Fa0jHR07E7YBN4vOEsbVf2briYNsuOowfLJaXULZM0ldMlaCaj2LJgLMbMe4iacRyZmvR8efFhgR9wKuGclQUg==} + '@rolldown/binding-freebsd-x64@1.2.2': + resolution: {integrity: sha512-0p1lhiCSCyaerFwtrdZQUx7NqGk6LQnaRKWX7tFQqwQgvX0rjM15cIkm3pax1UpEakK14C4mOxx/jSqCBdBRqQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.2.1': - resolution: {integrity: sha512-pzkgu1SSHGgRRyRZ4fbmSgmajbVt+epaLP99NDjFft69v/ypfTi6swBMiVdh2EkQ0OSnHE1lZDM7DRGkyAzUpA==} + '@rolldown/binding-linux-arm-gnueabihf@1.2.2': + resolution: {integrity: sha512-e+cOJXrJ2L3zx6YzqPg+f6Wbk3V1cKB8bOhbaYdVYN3DdquzNdRAmrbETz1qnt5yp/c7JNlNjmITiA2cVneQ7w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.2.1': - resolution: {integrity: sha512-QI5SEDY8cbiYWHx0VO4vIc3UlS6a32vXHjU8Qy/17adEmZIPuByJg13UEvo9c/UCiUkdcVWY83C+b+JrwnNyUg==} + '@rolldown/binding-linux-arm64-gnu@1.2.2': + resolution: {integrity: sha512-JsSMsj6sNat/MuhG5fnBD7QgbtpHKVe30x5/bAVirDHdhoQRXJkF6xc0Jqk8O4fiCUQAzMOoH9wZi3m60c8wtg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.2.1': - resolution: {integrity: sha512-Sm41FyCeXqmYcERoYOCbGIL5hNfd8w9LQ7Y61Bev48HkcjaJqV/iiVOaiDxjVTRMS+QKrZmD8cfPt4uMVnvM+A==} + '@rolldown/binding-linux-arm64-musl@1.2.2': + resolution: {integrity: sha512-B5G/zJdHaoJn9vD50eGHWkiWfmq8Uhi3IiLPJTzmZTrAalk1bztUikSXo0qga18ibE0IXboyeMUnhPjhAJ45wQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.2.1': - resolution: {integrity: sha512-2x+WhXTGl9yJYPbltW/BSEPTVz9OIWQyER4N+gJEDWkkn904eRcBzELqh/Hf7K0w/ubGbKNMv0ZC+94QK/IFEg==} + '@rolldown/binding-linux-ppc64-gnu@1.2.2': + resolution: {integrity: sha512-6mC/awzKka8W6EoekjegpfGkjz8jXWDX63pqu/HYVpyKtZfu65Jsh4QAH3Kej3CAv/c1oGX7psTmFEbr0mDxLA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.2.1': - resolution: {integrity: sha512-eEjmQpuRQayHPWWnywaWHkFT3ToPbP3RYy42VVd/B9aBGDA+Ol25EIWHxKQST3IiWJjikCWUF7KtbfqwZrzVwQ==} + '@rolldown/binding-linux-s390x-gnu@1.2.2': + resolution: {integrity: sha512-412MX9fJLdA1IK28EZnc8jYv2HRTleOZgfLQumJ5zy7OeJLZlg/CETwFaXjNmGVxG51cFHpKLqb5LKvBC+HsHA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.2.1': - resolution: {integrity: sha512-/Orga1fZYkLc/56jBICcHrKchl8Z2UKdDSr3LG9ToWO1lQ6a4Livk9Xz+9WN91zsz5QR3XQz2NNoSDEvP6qadw==} + '@rolldown/binding-linux-x64-gnu@1.2.2': + resolution: {integrity: sha512-Q/+HI/ToJafZ1iCqGgVQXUEkIjufHCTF0gBQ2a5o3cg7GJ2h0qyq3nvvSmU+bGda2/7ygXpTY4TM6gO9OhQ0ZA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.2.1': - resolution: {integrity: sha512-xxBJRL+0q0Kce7orznGWLuylHDY65vuARXZRpX+hPdv+DqK2c3NlCsVA98tlWzWNEE7yPqA/1NQ5nnCrj49Y5A==} + '@rolldown/binding-linux-x64-musl@1.2.2': + resolution: {integrity: sha512-ZKp/w41n6wCvxzxQHtQSbuphfX3Y4cCvbjkKHusrLx4lh+JWLTU7StSltO/DKARISzbj368d+qUaCjI8K2wzXw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.2.1': - resolution: {integrity: sha512-M6AdXIXw3s+/8XpKMzdGDEXGS1S7kwUsy+rcTIUIOx5Ge4nXKCtAFHFV9YKkXvGcC5WMoTjAteLzlsQROVI0Yw==} + '@rolldown/binding-openharmony-arm64@1.2.2': + resolution: {integrity: sha512-pxE6xD4KS3eAROkKK5yrhB9/3+vhlhVGMvlQLbdpzrBGDbKrnzx3RLwPaHvasLo6jgaiBLn7e04Df9C4tYhjmA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.2.1': - resolution: {integrity: sha512-/TX0SoRGojHzSAHpfVBbavRVSazg5U3h3Y3VXfcc0cdugq6kxdqw8LPGFiPr+/7gE/60zRcsOY2Vi9b9eT0jww==} - engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} - - '@rolldown/binding-win32-arm64-msvc@1.2.1': - resolution: {integrity: sha512-EvRrivJieyHG+AO9lleZWgq+g0+S7oV2C51yuqlcyU/R9net+sI4Pj0F+lUoP2bEr6TWX3SqFaaS0SzfLxSzkw==} + '@rolldown/binding-win32-arm64-msvc@1.2.2': + resolution: {integrity: sha512-4MqEue5re+xIZzAWsB8sj0P1kqZySWqIuN4t6QaIO/YA6SFwySOLruvWQFzfmqk8LBK2P30KCSJwf6mJCZZ5/A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.2.1': - resolution: {integrity: sha512-Z4eCmn5QJ/5+azF9knpLWKfVd9aidn0mAe9TpJgvBLId9Ax3t0+JVxBmT25Bv7NBbVW1TZyKjQjQReouMeH5UQ==} + '@rolldown/binding-win32-x64-msvc@1.2.2': + resolution: {integrity: sha512-NweNxxD0Nf9t8v7kodun45Ijp3EIwYY+uydPP6qBEYvfBqhIjN6dZMzlQja3tqX/aLs3F3Uz+AxDpKgRhpOZQg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -642,9 +622,6 @@ packages: svelte: optional: true - '@tybys/wasm-util@0.10.3': - resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} - '@types/esrecurse@4.3.1': resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} @@ -716,63 +693,63 @@ packages: '@types/svgo@2.6.4': resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==} - '@typescript-eslint/eslint-plugin@8.65.0': - resolution: {integrity: sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==} + '@typescript-eslint/eslint-plugin@8.66.0': + resolution: {integrity: sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.65.0 + '@typescript-eslint/parser': ^8.66.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.65.0': - resolution: {integrity: sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==} + '@typescript-eslint/parser@8.66.0': + resolution: {integrity: sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.65.0': - resolution: {integrity: sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==} + '@typescript-eslint/project-service@8.66.0': + resolution: {integrity: sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.65.0': - resolution: {integrity: sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==} + '@typescript-eslint/scope-manager@8.66.0': + resolution: {integrity: sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.65.0': - resolution: {integrity: sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==} + '@typescript-eslint/tsconfig-utils@8.66.0': + resolution: {integrity: sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.65.0': - resolution: {integrity: sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==} + '@typescript-eslint/type-utils@8.66.0': + resolution: {integrity: sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.65.0': - resolution: {integrity: sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==} + '@typescript-eslint/types@8.66.0': + resolution: {integrity: sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.65.0': - resolution: {integrity: sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==} + '@typescript-eslint/typescript-estree@8.66.0': + resolution: {integrity: sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.65.0': - resolution: {integrity: sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==} + '@typescript-eslint/utils@8.66.0': + resolution: {integrity: sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.65.0': - resolution: {integrity: sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==} + '@typescript-eslint/visitor-keys@8.66.0': + resolution: {integrity: sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} acorn-jsx@5.3.2: @@ -2147,8 +2124,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.16: - resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + nanoid@3.3.17: + resolution: {integrity: sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -2521,8 +2498,8 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true - rolldown@1.2.1: - resolution: {integrity: sha512-4FKJhg8d3OiyQOA6Q1Q0hoFFpW9/OoX+VsHzpECsdsIZoOArrAK90gl59YK/Z+gnDel45bgJZK03ozH/9bCqEw==} + rolldown@1.2.2: + resolution: {integrity: sha512-opwpo1tQBAcpSUJDt94B7hhLNGOKjCdE//XXjeLrnx9b83bjnw45tXdg1b09yEw/VLFBJGZpwRULMmOZo7ol+A==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -2762,8 +2739,8 @@ packages: resolution: {integrity: sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA==} engines: {node: '>=4'} - terser@5.49.0: - resolution: {integrity: sha512-SNiDnXyHSrxVcIOtVbULzcTmniUiwcV7Nwdyj1twVubeTmbjoa8p69KKDpfkdoOavuM4/GRm1+ykI8qqnavHoA==} + terser@5.49.1: + resolution: {integrity: sha512-7A2xlQ5EnGT8KPA92dUh6RbRYTVw8hEaEN9L1K68l4UOXFuV511NnAqObGoRqGOQofQcMypisu1s3xawCEHrvA==} engines: {node: '>=10'} hasBin: true @@ -2828,8 +2805,8 @@ packages: peerDependencies: typescript: '>=3.5.1' - typescript-eslint@8.65.0: - resolution: {integrity: sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==} + typescript-eslint@8.66.0: + resolution: {integrity: sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 @@ -3145,22 +3122,6 @@ snapshots: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@emnapi/core@2.0.0-alpha.3': - dependencies: - '@emnapi/wasi-threads': 2.0.1 - tslib: 2.8.1 - optional: true - - '@emnapi/runtime@2.0.0-alpha.3': - dependencies: - tslib: 2.8.1 - optional: true - - '@emnapi/wasi-threads@2.0.1': - dependencies: - tslib: 2.8.1 - optional: true - '@emotion/babel-plugin@11.13.5(supports-color@10.2.2)': dependencies: '@babel/helper-module-imports': 7.29.7(supports-color@10.2.2) @@ -3321,23 +3282,23 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@mui/core-downloads-tracker@9.2.0': {} + '@mui/core-downloads-tracker@9.3.0': {} - '@mui/icons-material@9.2.0(@mui/material@9.2.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/react@19.2.18)(react@19.2.8)': + '@mui/icons-material@9.3.0(@mui/material@9.3.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(@types/react@19.2.18)(react@19.2.8)': dependencies: '@babel/runtime': 7.29.7 - '@mui/material': 9.2.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + '@mui/material': 9.3.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8) react: 19.2.8 optionalDependencies: '@types/react': 19.2.18 - '@mui/material@9.2.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + '@mui/material@9.3.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': dependencies: '@babel/runtime': 7.29.7 - '@mui/core-downloads-tracker': 9.2.0 - '@mui/system': 9.2.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8) - '@mui/types': 9.1.1(@types/react@19.2.18) - '@mui/utils': 9.2.0(@types/react@19.2.18)(react@19.2.8) + '@mui/core-downloads-tracker': 9.3.0 + '@mui/system': 9.3.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8) + '@mui/types': 9.3.0(@types/react@19.2.18) + '@mui/utils': 9.3.0(@types/react@19.2.18)(react@19.2.8) '@popperjs/core': 2.11.8 '@types/react-transition-group': 4.4.12(@types/react@19.2.18) clsx: 2.1.1 @@ -3352,16 +3313,16 @@ snapshots: '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2) '@types/react': 19.2.18 - '@mui/private-theming@9.2.0(@types/react@19.2.18)(react@19.2.8)': + '@mui/private-theming@9.3.0(@types/react@19.2.18)(react@19.2.8)': dependencies: '@babel/runtime': 7.29.7 - '@mui/utils': 9.2.0(@types/react@19.2.18)(react@19.2.8) + '@mui/utils': 9.3.0(@types/react@19.2.18)(react@19.2.8) prop-types: 15.8.1 react: 19.2.8 optionalDependencies: '@types/react': 19.2.18 - '@mui/styled-engine@9.1.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(react@19.2.8)': + '@mui/styled-engine@9.3.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(react@19.2.8)': dependencies: '@babel/runtime': 7.29.7 '@emotion/cache': 11.14.0 @@ -3374,13 +3335,13 @@ snapshots: '@emotion/react': 11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2) '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2) - '@mui/system@9.2.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)': + '@mui/system@9.3.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)': dependencies: '@babel/runtime': 7.29.7 - '@mui/private-theming': 9.2.0(@types/react@19.2.18)(react@19.2.8) - '@mui/styled-engine': 9.1.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(react@19.2.8) - '@mui/types': 9.1.1(@types/react@19.2.18) - '@mui/utils': 9.2.0(@types/react@19.2.18)(react@19.2.8) + '@mui/private-theming': 9.3.0(@types/react@19.2.18)(react@19.2.8) + '@mui/styled-engine': 9.3.0(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(react@19.2.8) + '@mui/types': 9.3.0(@types/react@19.2.18) + '@mui/utils': 9.3.0(@types/react@19.2.18)(react@19.2.8) clsx: 2.1.1 csstype: 3.2.3 prop-types: 15.8.1 @@ -3390,16 +3351,16 @@ snapshots: '@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2))(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2) '@types/react': 19.2.18 - '@mui/types@9.1.1(@types/react@19.2.18)': + '@mui/types@9.3.0(@types/react@19.2.18)': dependencies: '@babel/runtime': 7.29.7 optionalDependencies: '@types/react': 19.2.18 - '@mui/utils@9.2.0(@types/react@19.2.18)(react@19.2.8)': + '@mui/utils@9.3.0(@types/react@19.2.18)(react@19.2.8)': dependencies: '@babel/runtime': 7.29.7 - '@mui/types': 9.1.1(@types/react@19.2.18) + '@mui/types': 9.3.0(@types/react@19.2.18) '@types/prop-types': 15.7.15 clsx: 2.1.1 prop-types: 15.8.1 @@ -3408,13 +3369,6 @@ snapshots: optionalDependencies: '@types/react': 19.2.18 - '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@2.0.0-alpha.3)(@emnapi/runtime@2.0.0-alpha.3)': - dependencies: - '@emnapi/core': 2.0.0-alpha.3 - '@emnapi/runtime': 2.0.0-alpha.3 - '@tybys/wasm-util': 0.10.3 - optional: true - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -3431,19 +3385,19 @@ snapshots: '@popperjs/core@2.11.8': {} - '@preact/preset-vite@2.10.6(@babel/core@7.29.7(supports-color@10.2.2))(preact@10.29.8)(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.0))': + '@preact/preset-vite@2.10.6(@babel/core@7.29.7(supports-color@10.2.2))(preact@10.29.8)(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.1))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) '@babel/plugin-transform-react-jsx-development': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2) - '@prefresh/vite': 2.4.12(preact@10.29.8)(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.0)) + '@prefresh/vite': 2.4.12(preact@10.29.8)(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.1)) '@rollup/pluginutils': 5.4.0 babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.29.7(supports-color@10.2.2)) debug: 4.4.3(supports-color@10.2.2) magic-string: 0.30.21 picocolors: 1.1.1 - vite: 8.2.0(@types/node@26.1.2)(terser@5.49.0) - vite-prerender-plugin: 0.5.13(vite@8.2.0(@types/node@26.1.2)(terser@5.49.0)) + vite: 8.2.0(@types/node@26.1.2)(terser@5.49.1) + vite-prerender-plugin: 0.5.13(vite@8.2.0(@types/node@26.1.2)(terser@5.49.1)) zimmerframe: 1.1.4 transitivePeerDependencies: - preact @@ -3458,7 +3412,7 @@ snapshots: '@prefresh/utils@1.2.1': {} - '@prefresh/vite@2.4.12(preact@10.29.8)(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.0))': + '@prefresh/vite@2.4.12(preact@10.29.8)(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.1))': dependencies: '@babel/core': 7.29.7(supports-color@10.2.2) '@prefresh/babel-plugin': 0.5.3 @@ -3466,57 +3420,50 @@ snapshots: '@prefresh/utils': 1.2.1 '@rollup/pluginutils': 4.2.1 preact: 10.29.8 - vite: 8.2.0(@types/node@26.1.2)(terser@5.49.0) + vite: 8.2.0(@types/node@26.1.2)(terser@5.49.1) transitivePeerDependencies: - supports-color - '@rolldown/binding-android-arm64@1.2.1': + '@rolldown/binding-android-arm64@1.2.2': optional: true - '@rolldown/binding-darwin-arm64@1.2.1': + '@rolldown/binding-darwin-arm64@1.2.2': optional: true - '@rolldown/binding-darwin-x64@1.2.1': + '@rolldown/binding-darwin-x64@1.2.2': optional: true - '@rolldown/binding-freebsd-x64@1.2.1': + '@rolldown/binding-freebsd-x64@1.2.2': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.2.1': + '@rolldown/binding-linux-arm-gnueabihf@1.2.2': optional: true - '@rolldown/binding-linux-arm64-gnu@1.2.1': + '@rolldown/binding-linux-arm64-gnu@1.2.2': optional: true - '@rolldown/binding-linux-arm64-musl@1.2.1': + '@rolldown/binding-linux-arm64-musl@1.2.2': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.2.1': + '@rolldown/binding-linux-ppc64-gnu@1.2.2': optional: true - '@rolldown/binding-linux-s390x-gnu@1.2.1': + '@rolldown/binding-linux-s390x-gnu@1.2.2': optional: true - '@rolldown/binding-linux-x64-gnu@1.2.1': + '@rolldown/binding-linux-x64-gnu@1.2.2': optional: true - '@rolldown/binding-linux-x64-musl@1.2.1': + '@rolldown/binding-linux-x64-musl@1.2.2': optional: true - '@rolldown/binding-openharmony-arm64@1.2.1': + '@rolldown/binding-openharmony-arm64@1.2.2': optional: true - '@rolldown/binding-wasm32-wasi@1.2.1': - dependencies: - '@emnapi/core': 2.0.0-alpha.3 - '@emnapi/runtime': 2.0.0-alpha.3 - '@napi-rs/wasm-runtime': 1.2.2(@emnapi/core@2.0.0-alpha.3)(@emnapi/runtime@2.0.0-alpha.3) + '@rolldown/binding-win32-arm64-msvc@1.2.2': optional: true - '@rolldown/binding-win32-arm64-msvc@1.2.1': - optional: true - - '@rolldown/binding-win32-x64-msvc@1.2.1': + '@rolldown/binding-win32-x64-msvc@1.2.2': optional: true '@rolldown/pluginutils@1.0.1': {} @@ -3557,11 +3504,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@tybys/wasm-util@0.10.3': - dependencies: - tslib: 2.8.1 - optional: true - '@types/esrecurse@4.3.1': {} '@types/estree@1.0.9': {} @@ -3642,14 +3584,14 @@ snapshots: dependencies: '@types/node': 26.1.2 - '@typescript-eslint/eslint-plugin@8.65.0(@typescript-eslint/parser@8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.66.0(@typescript-eslint/parser@8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/type-utils': 8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/utils': 8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.65.0 + '@typescript-eslint/parser': 8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.66.0 + '@typescript-eslint/type-utils': 8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.66.0 eslint: 10.8.0(supports-color@10.2.2) ignore: 7.0.6 natural-compare: 1.4.0 @@ -3658,41 +3600,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/parser@8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.65.0 + '@typescript-eslint/scope-manager': 8.66.0 + '@typescript-eslint/types': 8.66.0 + '@typescript-eslint/typescript-estree': 8.66.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.66.0 debug: 4.4.3(supports-color@10.2.2) eslint: 10.8.0(supports-color@10.2.2) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.65.0(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/project-service@8.66.0(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@6.0.3) - '@typescript-eslint/types': 8.65.0 + '@typescript-eslint/tsconfig-utils': 8.66.0(typescript@6.0.3) + '@typescript-eslint/types': 8.66.0 debug: 4.4.3(supports-color@10.2.2) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.65.0': + '@typescript-eslint/scope-manager@8.66.0': dependencies: - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/visitor-keys': 8.65.0 + '@typescript-eslint/types': 8.66.0 + '@typescript-eslint/visitor-keys': 8.66.0 - '@typescript-eslint/tsconfig-utils@8.65.0(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.66.0(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/utils': 8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/types': 8.66.0 + '@typescript-eslint/typescript-estree': 8.66.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) debug: 4.4.3(supports-color@10.2.2) eslint: 10.8.0(supports-color@10.2.2) ts-api-utils: 2.5.0(typescript@6.0.3) @@ -3700,14 +3642,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.65.0': {} + '@typescript-eslint/types@8.66.0': {} - '@typescript-eslint/typescript-estree@8.65.0(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.66.0(supports-color@10.2.2)(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.65.0(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.65.0(typescript@6.0.3) - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/visitor-keys': 8.65.0 + '@typescript-eslint/project-service': 8.66.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.66.0(typescript@6.0.3) + '@typescript-eslint/types': 8.66.0 + '@typescript-eslint/visitor-keys': 8.66.0 debug: 4.4.3(supports-color@10.2.2) minimatch: 10.2.6 semver: 7.8.5 @@ -3717,20 +3659,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': + '@typescript-eslint/utils@8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)': dependencies: '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.0(supports-color@10.2.2)) - '@typescript-eslint/scope-manager': 8.65.0 - '@typescript-eslint/types': 8.65.0 - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.66.0 + '@typescript-eslint/types': 8.66.0 + '@typescript-eslint/typescript-estree': 8.66.0(supports-color@10.2.2)(typescript@6.0.3) eslint: 10.8.0(supports-color@10.2.2) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.65.0': + '@typescript-eslint/visitor-keys@8.66.0': dependencies: - '@typescript-eslint/types': 8.65.0 + '@typescript-eslint/types': 8.66.0 eslint-visitor-keys: 5.0.1 acorn-jsx@5.3.2(acorn@8.18.0): @@ -5138,7 +5080,7 @@ snapshots: ms@2.1.3: {} - nanoid@3.3.16: {} + nanoid@3.3.17: {} natural-compare@1.4.0: {} @@ -5337,7 +5279,7 @@ snapshots: postcss@8.5.25: dependencies: - nanoid: 3.3.16 + nanoid: 3.3.17 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -5476,35 +5418,34 @@ snapshots: dependencies: glob: 7.2.3 - rolldown@1.2.1: + rolldown@1.2.2: dependencies: '@oxc-project/types': 0.142.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.2.1 - '@rolldown/binding-darwin-arm64': 1.2.1 - '@rolldown/binding-darwin-x64': 1.2.1 - '@rolldown/binding-freebsd-x64': 1.2.1 - '@rolldown/binding-linux-arm-gnueabihf': 1.2.1 - '@rolldown/binding-linux-arm64-gnu': 1.2.1 - '@rolldown/binding-linux-arm64-musl': 1.2.1 - '@rolldown/binding-linux-ppc64-gnu': 1.2.1 - '@rolldown/binding-linux-s390x-gnu': 1.2.1 - '@rolldown/binding-linux-x64-gnu': 1.2.1 - '@rolldown/binding-linux-x64-musl': 1.2.1 - '@rolldown/binding-openharmony-arm64': 1.2.1 - '@rolldown/binding-wasm32-wasi': 1.2.1 - '@rolldown/binding-win32-arm64-msvc': 1.2.1 - '@rolldown/binding-win32-x64-msvc': 1.2.1 + '@rolldown/binding-android-arm64': 1.2.2 + '@rolldown/binding-darwin-arm64': 1.2.2 + '@rolldown/binding-darwin-x64': 1.2.2 + '@rolldown/binding-freebsd-x64': 1.2.2 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.2 + '@rolldown/binding-linux-arm64-gnu': 1.2.2 + '@rolldown/binding-linux-arm64-musl': 1.2.2 + '@rolldown/binding-linux-ppc64-gnu': 1.2.2 + '@rolldown/binding-linux-s390x-gnu': 1.2.2 + '@rolldown/binding-linux-x64-gnu': 1.2.2 + '@rolldown/binding-linux-x64-musl': 1.2.2 + '@rolldown/binding-openharmony-arm64': 1.2.2 + '@rolldown/binding-win32-arm64-msvc': 1.2.2 + '@rolldown/binding-win32-x64-msvc': 1.2.2 - rollup-plugin-visualizer@7.0.1(rolldown@1.2.1): + rollup-plugin-visualizer@7.0.1(rolldown@1.2.2): dependencies: open: 11.0.0 picomatch: 4.0.5 source-map: 0.7.6 yargs: 18.1.0 optionalDependencies: - rolldown: 1.2.1 + rolldown: 1.2.2 run-applescript@7.1.0: {} @@ -5706,7 +5647,7 @@ snapshots: temp-dir: 1.0.0 uuid: 3.4.0 - terser@5.49.0: + terser@5.49.1: dependencies: '@jridgewell/source-map': 0.3.11 acorn: 8.18.0 @@ -5766,12 +5707,12 @@ snapshots: dependencies: typescript: 6.0.3 - typescript-eslint@8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3): + typescript-eslint@8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.65.0(@typescript-eslint/parser@8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/parser': 8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.65.0(supports-color@10.2.2)(typescript@6.0.3) - '@typescript-eslint/utils': 8.65.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/eslint-plugin': 8.66.0(@typescript-eslint/parser@8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/parser': 8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.66.0(supports-color@10.2.2)(typescript@6.0.3) + '@typescript-eslint/utils': 8.66.0(eslint@10.8.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3) eslint: 10.8.0(supports-color@10.2.2) typescript: 6.0.3 transitivePeerDependencies: @@ -5817,7 +5758,7 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - vite-plugin-imagemin@0.6.1(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.0)): + vite-plugin-imagemin@0.6.1(supports-color@10.2.2)(vite@8.2.0(@types/node@26.1.2)(terser@5.49.1)): dependencies: '@types/imagemin': 7.0.1 '@types/imagemin-gifsicle': 7.0.4 @@ -5842,11 +5783,11 @@ snapshots: imagemin-webp: 6.1.0 jpegtran-bin: 6.0.1 pathe: 0.2.0 - vite: 8.2.0(@types/node@26.1.2)(terser@5.49.0) + vite: 8.2.0(@types/node@26.1.2)(terser@5.49.1) transitivePeerDependencies: - supports-color - vite-prerender-plugin@0.5.13(vite@8.2.0(@types/node@26.1.2)(terser@5.49.0)): + vite-prerender-plugin@0.5.13(vite@8.2.0(@types/node@26.1.2)(terser@5.49.1)): dependencies: kolorist: 1.8.0 magic-string: 0.30.21 @@ -5854,19 +5795,19 @@ snapshots: simple-code-frame: 1.3.0 source-map: 0.7.6 stack-trace: 1.0.0 - vite: 8.2.0(@types/node@26.1.2)(terser@5.49.0) + vite: 8.2.0(@types/node@26.1.2)(terser@5.49.1) - vite@8.2.0(@types/node@26.1.2)(terser@5.49.0): + vite@8.2.0(@types/node@26.1.2)(terser@5.49.1): dependencies: lightningcss: 1.33.0 picomatch: 4.0.5 postcss: 8.5.25 - rolldown: 1.2.1 + rolldown: 1.2.2 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 26.1.2 fsevents: 2.3.3 - terser: 5.49.0 + terser: 5.49.1 which-typed-array@1.1.22: dependencies: diff --git a/mock-api/package.json b/mock-api/package.json index a70a3ef0b..241cd644c 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -18,5 +18,5 @@ "@trivago/prettier-plugin-sort-imports": "^6.0.2", "prettier": "^3.9.6" }, - "packageManager": "pnpm@11.18.0+sha512.33d83c77da82f49fba836925c6f1b841181ec3132b670639bd012f7075f5c7cf634c5f870147c19aae7478fac01df09d8892e880454896edd23ee9b33757563c" + "packageManager": "pnpm@11.20.0+sha512.9a6f330a95b66446ea088faf1521405a8a01f07fde7124cc9958dfed52d4bb436737e65b08f85f37b46fcba375092558ac51262b816844b22f63406ed166bfee" } From bde9ab53a136982d308fd7fbd1ee71efbd751493 Mon Sep 17 00:00:00 2001 From: proddy Date: Thu, 6 Aug 2026 16:17:17 +0200 Subject: [PATCH 7/7] fix formatting --- src/core/led.cpp | 628 +++++++++++++++++++++++------------------------ 1 file changed, 314 insertions(+), 314 deletions(-) diff --git a/src/core/led.cpp b/src/core/led.cpp index 28de6180c..e56a41143 100644 --- a/src/core/led.cpp +++ b/src/core/led.cpp @@ -16,317 +16,317 @@ * along with this program. If not, see . */ - #include "led.h" - #include "emsesp.h" - - namespace emsesp { - - uuid::log::Logger LED::logger_{F_(led), uuid::log::Facility::KERN}; - - // initialise the LED, fetching the settings from the WebSettingsService - // set the LED to on or off when in normal operating mode - void LED::init() { - // copy the application settings - EMSESP::webSettingsService.read([&](WebSettings & settings) { - led_gpio_ = settings.led_gpio; - led_type_ = settings.led_type; - hide_led_ = settings.hide_led; - }); - - if (!led_gpio_) { // 0 means disabled - LOG_INFO("LED disabled"); - return; - } - - // for safety - if (!led_type_) { - pinMode(led_gpio_, OUTPUT); - } - - reset_led(); // start with LED in default state, depending on if it's hidden or not - } - - // handle LED routine - // called from the System::loop() - // returns true if the LED flash is active, i.e its a lock down state - bool LED::loop(uint8_t healthcheck, bool button_busy) { - // if LED flashing is active it means its about to perform a factory reset, so don't do anything else and keep it flashing - if (led_fast_flash_timer_) { - led_fast_flash(); - return true; - } - - // the user-requested LED blink always has preference - if (!is_user_led_blink_) { - // check for button press. - // while the button is held show the LED (yellow on RGB LED, on/off on standard LED), - // and on release go back to the default state and re-check the health on the next cycle - if (last_button_busy_ != button_busy) { - last_button_busy_ = button_busy; - if (button_busy) { - set_led(Color::YELLOW); // Yellow - } else { - reset_led(); - previous_healthcheck_ = System::HEALTHCHECK_RESET; - } - return false; - } - - // check the system health. - // Set the sequence accordingly, only if the healthcheck is not 0 and has changed - if (healthcheck != previous_healthcheck_) { - previous_healthcheck_ = healthcheck; - color_steps_[0] = Color::OFF; - color_steps_[1] = Color::OFF; - color_steps_[2] = Color::OFF; - - // if the healthcheck is 0, i.e. system is healthy, reset the LED - if (healthcheck == 0) { - reset_led(); - return false; - } - - // 1 flash (blue) is the EMS bus is not connected - // 2 flashes (red, red) if the network (wifi or ethernet) is not connected - // 3 flashes (red, red, blue) is both the bus and the network are not connected - bool no_network = (healthcheck & System::HEALTHCHECK_NO_NETWORK) == System::HEALTHCHECK_NO_NETWORK; - bool no_bus = (healthcheck & System::HEALTHCHECK_NO_BUS) == System::HEALTHCHECK_NO_BUS; - - // set step 1 - if (no_network) { - color_steps_[0] = Color::RED; // red, no network - } else if (no_bus) { - color_steps_[0] = Color::BLUE; // blue, no bus - } - - // set step 2 - if (no_network) { - color_steps_[1] = Color::RED; // red, no network - } - - // set step 3 - if (no_network && no_bus) { - color_steps_[2] = Color::BLUE; // blue, no network and no bus - } - } - - // there's nothing to flash, so leave the LED in the state reset_led() gave it. - // Running the sequence here would keep writing Color::OFF and a healthy system would never show green. - if (healthcheck == 0 || button_busy) { - return false; - } - } - - // show the LED status based on the healthcheck and button busy status - sequence_led(); - - return false; - } - - // turn the LED back it's default state depending on if it's hidden or not - void LED::reset_led() { - is_user_led_blink_ = false; - set_led(hide_led_ ? Color::OFF : Color::GREEN); // Green - color_steps_[0] = Color::OFF; - color_steps_[1] = Color::OFF; - color_steps_[2] = Color::OFF; - - // rewind the sequence so it starts from the top if the health degrades again - led_long_timer_ = 1; // 1 will kick it off immediately - led_short_timer_ = 0; - led_flash_step_ = 0; - } - - // LED flash every few ms and then perform a factory reset - void LED::led_fast_flash() { - uint32_t current_time = uuid::get_uptime(); - - if (current_time - last_toggle_time_ >= LED_FLASH_INTERVAL_MS) { - led_flash_state_ = !led_flash_state_; - last_toggle_time_ = current_time; - set_led(led_flash_state_ ? Color::YELLOW : Color::OFF); // Yellow - } - - // after duration, turn off the LED, and call the format command - if (current_time - led_flash_start_time_ >= led_flash_duration_) { - set_led(Color::OFF); - led_fast_flash_timer_ = false; - #ifndef EMSESP_DEBUG - System::command_format(nullptr, 0); // Execute format operation, unless in debug mode - #endif - } - } - - // set LED on/off or RGB color - // ignores whether the LED is hidden or not (if hide_led_ is set) - void LED::set_led(Color color) { - if (!led_gpio_) { - return; - } - - // RGB lookup table indexed by Color enum (must match enum order in led.h) - static constexpr uint8_t B = RGB_LED_BRIGHTNESS; - static constexpr uint8_t H = RGB_LED_BRIGHTNESS / 2; - static constexpr uint8_t rgb_table[][3] = { - {0, 0, 0}, // OFF - {B, B, B}, // ON (white) - {B, 0, 0}, // RED - {0, B, 0}, // GREEN - {0, 0, B}, // BLUE - {B, B, 0}, // YELLOW - {B, H, 0}, // ORANGE - {0, B, B}, // CYAN - {H, 0, H} // PINK - }; - - const uint8_t color_idx = static_cast(color); - const uint8_t idx = (color_idx < sizeof(rgb_table) / sizeof(rgb_table[0])) ? color_idx : static_cast(Color::OFF); - const uint8_t red = rgb_table[idx][0]; - const uint8_t green = rgb_table[idx][1]; - const uint8_t blue = rgb_table[idx][2]; - - if (led_type_) { - rgbLedWrite(led_gpio_, red, green, blue); - } else { - digitalWrite(led_gpio_, (red == 0 && green == 0 && blue == 0) || color == Color::OFF ? !LED_ON : LED_ON); - } - } - - // set LED custom routine - // For example: /api/system/led?data=red:blink1 - // For older non-RGB models, the colour would default to just being on. - bool LED::set_custom_led_routine(std::string color, std::string pattern) { - static constexpr struct { - const char * name; - Color value; - } color_map[] = { - {"off", Color::OFF}, - {"on", Color::ON}, - {"white", Color::ON}, - {"red", Color::RED}, - {"green", Color::GREEN}, - {"blue", Color::BLUE}, - {"yellow", Color::YELLOW}, - {"orange", Color::ORANGE}, - {"cyan", Color::CYAN}, - {"pink", Color::PINK}, - }; - - Color color_type = Color::OFF; - bool color_matched = false; - for (const auto & entry : color_map) { - if (color == entry.name) { - color_type = entry.value; - color_matched = true; - break; - } - } - if (!color_matched) { - return false; - } - - // reset the color steps - color_steps_[0] = Color::OFF; - color_steps_[1] = Color::OFF; - color_steps_[2] = Color::OFF; - - // blink patterns - if (pattern == "blink1") { - color_steps_[0] = color_type; - } else if (pattern == "blink2") { - color_steps_[0] = color_type; - color_steps_[1] = color_type; - } else if (pattern == "blink3") { - color_steps_[0] = color_type; - color_steps_[1] = color_type; - color_steps_[2] = color_type; - - // special patterns, ignores the user color - } else if (pattern == "rgb") { - color_steps_[0] = Color::RED; - color_steps_[1] = Color::GREEN; - color_steps_[2] = Color::BLUE; - } else if (pattern == "cpc") { - color_steps_[0] = Color::CYAN; - color_steps_[1] = Color::PINK; - color_steps_[2] = Color::CYAN; - } else { - return false; // pattern not recognized - } - - is_user_led_blink_ = true; // user routine is active - - // when this is called we want the sequence_led to restart immediately and skip the long pause - led_long_timer_ = uuid::get_uptime() + HEALTHCHECK_LED_FLASH_FAST_DURATION + 200UL; - - return true; - } - - // uses LED to show system health and user-requested LED blinks - // it works in a batch of 3 configured flashes, then a long pause - // the timing is different for user-requested LED blink and for system healthcheck - void LED::sequence_led() { - // first long pause before we start flashing - auto current_time = uuid::get_uptime(); - if (led_long_timer_ - && (uint32_t)(current_time - led_long_timer_) >= (is_user_led_blink_ ? HEALTHCHECK_LED_LONG_FAST_DURATION : HEALTHCHECK_LED_LONG_DURATION)) { - led_short_timer_ = current_time; // start the short timer - led_long_timer_ = 0; // stop long timer - led_flash_step_ = 1; // enable the short flash timer - } - - // the flash timer which starts after the long pause - if (led_flash_step_ - && (uint32_t)(current_time - led_short_timer_) >= (is_user_led_blink_ ? HEALTHCHECK_LED_FLASH_FAST_DURATION : HEALTHCHECK_LED_FLASH_DURATION)) { - led_long_timer_ = 0; // stop the long timer - led_short_timer_ = current_time; - - if (++led_flash_step_ == 8) { - // finished first iteration, reset the whole sequence, turn off LED - led_long_timer_ = uuid::get_uptime(); - led_flash_step_ = 0; - set_led(Color::OFF); // turn off the LED - - // if we're running a user-requested LED blink, turn it off and go back to the healthcheck sequence - if (is_user_led_blink_) { - is_user_led_blink_ = false; - previous_healthcheck_ = System::HEALTHCHECK_RESET; // this will force the healthcheck to be checked again - } - return; - } - - if (led_flash_step_ % 2) { - // handle the three step events (on odd numbers 3,5,7 etc). see if we need to set a LED color - switch (led_flash_step_) { - case 3: // first flash - set_led(color_steps_[0]); - break; - case 5: // second flash - set_led(color_steps_[1]); - break; - case 7: // third flash - set_led(color_steps_[2]); - break; - default: - break; - } - } else { - set_led(Color::OFF); // turn off on even number count, to make it flash - } - } - } - - // Start the LED flash timer - duration in seconds - void LED::start_led_fast_flash(uint8_t duration) { - // Don't start if already running - if (led_fast_flash_timer_) { - return; - } - - // Reset counter and state - led_flash_start_time_ = uuid::get_uptime(); // current time - led_flash_duration_ = (uint32_t)duration * 1000; // duration in milliseconds - led_fast_flash_timer_ = true; // it's active - } - - } // namespace emsesp \ No newline at end of file +#include "led.h" +#include "emsesp.h" + +namespace emsesp { + +uuid::log::Logger LED::logger_{F_(led), uuid::log::Facility::KERN}; + +// initialise the LED, fetching the settings from the WebSettingsService +// set the LED to on or off when in normal operating mode +void LED::init() { + // copy the application settings + EMSESP::webSettingsService.read([&](WebSettings & settings) { + led_gpio_ = settings.led_gpio; + led_type_ = settings.led_type; + hide_led_ = settings.hide_led; + }); + + if (!led_gpio_) { // 0 means disabled + LOG_INFO("LED disabled"); + return; + } + + // for safety + if (!led_type_) { + pinMode(led_gpio_, OUTPUT); + } + + reset_led(); // start with LED in default state, depending on if it's hidden or not +} + +// handle LED routine +// called from the System::loop() +// returns true if the LED flash is active, i.e its a lock down state +bool LED::loop(uint8_t healthcheck, bool button_busy) { + // if LED flashing is active it means its about to perform a factory reset, so don't do anything else and keep it flashing + if (led_fast_flash_timer_) { + led_fast_flash(); + return true; + } + + // the user-requested LED blink always has preference + if (!is_user_led_blink_) { + // check for button press. + // while the button is held show the LED (yellow on RGB LED, on/off on standard LED), + // and on release go back to the default state and re-check the health on the next cycle + if (last_button_busy_ != button_busy) { + last_button_busy_ = button_busy; + if (button_busy) { + set_led(Color::YELLOW); // Yellow + } else { + reset_led(); + previous_healthcheck_ = System::HEALTHCHECK_RESET; + } + return false; + } + + // check the system health. + // Set the sequence accordingly, only if the healthcheck is not 0 and has changed + if (healthcheck != previous_healthcheck_) { + previous_healthcheck_ = healthcheck; + color_steps_[0] = Color::OFF; + color_steps_[1] = Color::OFF; + color_steps_[2] = Color::OFF; + + // if the healthcheck is 0, i.e. system is healthy, reset the LED + if (healthcheck == 0) { + reset_led(); + return false; + } + + // 1 flash (blue) is the EMS bus is not connected + // 2 flashes (red, red) if the network (wifi or ethernet) is not connected + // 3 flashes (red, red, blue) is both the bus and the network are not connected + bool no_network = (healthcheck & System::HEALTHCHECK_NO_NETWORK) == System::HEALTHCHECK_NO_NETWORK; + bool no_bus = (healthcheck & System::HEALTHCHECK_NO_BUS) == System::HEALTHCHECK_NO_BUS; + + // set step 1 + if (no_network) { + color_steps_[0] = Color::RED; // red, no network + } else if (no_bus) { + color_steps_[0] = Color::BLUE; // blue, no bus + } + + // set step 2 + if (no_network) { + color_steps_[1] = Color::RED; // red, no network + } + + // set step 3 + if (no_network && no_bus) { + color_steps_[2] = Color::BLUE; // blue, no network and no bus + } + } + + // there's nothing to flash, so leave the LED in the state reset_led() gave it. + // Running the sequence here would keep writing Color::OFF and a healthy system would never show green. + if (healthcheck == 0 || button_busy) { + return false; + } + } + + // show the LED status based on the healthcheck and button busy status + sequence_led(); + + return false; +} + +// turn the LED back it's default state depending on if it's hidden or not +void LED::reset_led() { + is_user_led_blink_ = false; + set_led(hide_led_ ? Color::OFF : Color::GREEN); // Green + color_steps_[0] = Color::OFF; + color_steps_[1] = Color::OFF; + color_steps_[2] = Color::OFF; + + // rewind the sequence so it starts from the top if the health degrades again + led_long_timer_ = 1; // 1 will kick it off immediately + led_short_timer_ = 0; + led_flash_step_ = 0; +} + +// LED flash every few ms and then perform a factory reset +void LED::led_fast_flash() { + uint32_t current_time = uuid::get_uptime(); + + if (current_time - last_toggle_time_ >= LED_FLASH_INTERVAL_MS) { + led_flash_state_ = !led_flash_state_; + last_toggle_time_ = current_time; + set_led(led_flash_state_ ? Color::YELLOW : Color::OFF); // Yellow + } + + // after duration, turn off the LED, and call the format command + if (current_time - led_flash_start_time_ >= led_flash_duration_) { + set_led(Color::OFF); + led_fast_flash_timer_ = false; +#ifndef EMSESP_DEBUG + System::command_format(nullptr, 0); // Execute format operation, unless in debug mode +#endif + } +} + +// set LED on/off or RGB color +// ignores whether the LED is hidden or not (if hide_led_ is set) +void LED::set_led(Color color) { + if (!led_gpio_) { + return; + } + + // RGB lookup table indexed by Color enum (must match enum order in led.h) + static constexpr uint8_t B = RGB_LED_BRIGHTNESS; + static constexpr uint8_t H = RGB_LED_BRIGHTNESS / 2; + static constexpr uint8_t rgb_table[][3] = { + {0, 0, 0}, // OFF + {B, B, B}, // ON (white) + {B, 0, 0}, // RED + {0, B, 0}, // GREEN + {0, 0, B}, // BLUE + {B, B, 0}, // YELLOW + {B, H, 0}, // ORANGE + {0, B, B}, // CYAN + {H, 0, H} // PINK + }; + + const uint8_t color_idx = static_cast(color); + const uint8_t idx = (color_idx < sizeof(rgb_table) / sizeof(rgb_table[0])) ? color_idx : static_cast(Color::OFF); + const uint8_t red = rgb_table[idx][0]; + const uint8_t green = rgb_table[idx][1]; + const uint8_t blue = rgb_table[idx][2]; + + if (led_type_) { + rgbLedWrite(led_gpio_, red, green, blue); + } else { + digitalWrite(led_gpio_, (red == 0 && green == 0 && blue == 0) || color == Color::OFF ? !LED_ON : LED_ON); + } +} + +// set LED custom routine +// For example: /api/system/led?data=red:blink1 +// For older non-RGB models, the colour would default to just being on. +bool LED::set_custom_led_routine(std::string color, std::string pattern) { + static constexpr struct { + const char * name; + Color value; + } color_map[] = { + {"off", Color::OFF}, + {"on", Color::ON}, + {"white", Color::ON}, + {"red", Color::RED}, + {"green", Color::GREEN}, + {"blue", Color::BLUE}, + {"yellow", Color::YELLOW}, + {"orange", Color::ORANGE}, + {"cyan", Color::CYAN}, + {"pink", Color::PINK}, + }; + + Color color_type = Color::OFF; + bool color_matched = false; + for (const auto & entry : color_map) { + if (color == entry.name) { + color_type = entry.value; + color_matched = true; + break; + } + } + if (!color_matched) { + return false; + } + + // reset the color steps + color_steps_[0] = Color::OFF; + color_steps_[1] = Color::OFF; + color_steps_[2] = Color::OFF; + + // blink patterns + if (pattern == "blink1") { + color_steps_[0] = color_type; + } else if (pattern == "blink2") { + color_steps_[0] = color_type; + color_steps_[1] = color_type; + } else if (pattern == "blink3") { + color_steps_[0] = color_type; + color_steps_[1] = color_type; + color_steps_[2] = color_type; + + // special patterns, ignores the user color + } else if (pattern == "rgb") { + color_steps_[0] = Color::RED; + color_steps_[1] = Color::GREEN; + color_steps_[2] = Color::BLUE; + } else if (pattern == "cpc") { + color_steps_[0] = Color::CYAN; + color_steps_[1] = Color::PINK; + color_steps_[2] = Color::CYAN; + } else { + return false; // pattern not recognized + } + + is_user_led_blink_ = true; // user routine is active + + // when this is called we want the sequence_led to restart immediately and skip the long pause + led_long_timer_ = uuid::get_uptime() + HEALTHCHECK_LED_FLASH_FAST_DURATION + 200UL; + + return true; +} + +// uses LED to show system health and user-requested LED blinks +// it works in a batch of 3 configured flashes, then a long pause +// the timing is different for user-requested LED blink and for system healthcheck +void LED::sequence_led() { + // first long pause before we start flashing + auto current_time = uuid::get_uptime(); + if (led_long_timer_ + && (uint32_t)(current_time - led_long_timer_) >= (is_user_led_blink_ ? HEALTHCHECK_LED_LONG_FAST_DURATION : HEALTHCHECK_LED_LONG_DURATION)) { + led_short_timer_ = current_time; // start the short timer + led_long_timer_ = 0; // stop long timer + led_flash_step_ = 1; // enable the short flash timer + } + + // the flash timer which starts after the long pause + if (led_flash_step_ + && (uint32_t)(current_time - led_short_timer_) >= (is_user_led_blink_ ? HEALTHCHECK_LED_FLASH_FAST_DURATION : HEALTHCHECK_LED_FLASH_DURATION)) { + led_long_timer_ = 0; // stop the long timer + led_short_timer_ = current_time; + + if (++led_flash_step_ == 8) { + // finished first iteration, reset the whole sequence, turn off LED + led_long_timer_ = uuid::get_uptime(); + led_flash_step_ = 0; + set_led(Color::OFF); // turn off the LED + + // if we're running a user-requested LED blink, turn it off and go back to the healthcheck sequence + if (is_user_led_blink_) { + is_user_led_blink_ = false; + previous_healthcheck_ = System::HEALTHCHECK_RESET; // this will force the healthcheck to be checked again + } + return; + } + + if (led_flash_step_ % 2) { + // handle the three step events (on odd numbers 3,5,7 etc). see if we need to set a LED color + switch (led_flash_step_) { + case 3: // first flash + set_led(color_steps_[0]); + break; + case 5: // second flash + set_led(color_steps_[1]); + break; + case 7: // third flash + set_led(color_steps_[2]); + break; + default: + break; + } + } else { + set_led(Color::OFF); // turn off on even number count, to make it flash + } + } +} + +// Start the LED flash timer - duration in seconds +void LED::start_led_fast_flash(uint8_t duration) { + // Don't start if already running + if (led_fast_flash_timer_) { + return; + } + + // Reset counter and state + led_flash_start_time_ = uuid::get_uptime(); // current time + led_flash_duration_ = (uint32_t)duration * 1000; // duration in milliseconds + led_fast_flash_timer_ = true; // it's active +} + +} // namespace emsesp \ No newline at end of file