diff --git a/src/WebSettingsService.cpp b/src/WebSettingsService.cpp index 263a10f66..6309f27c8 100644 --- a/src/WebSettingsService.cpp +++ b/src/WebSettingsService.cpp @@ -21,6 +21,8 @@ namespace emsesp { +uint8_t WebSettings::flags_; + WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) : _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager) , _fsPersistence(WebSettings::read, WebSettings::update, this, fs, EMSESP_SETTINGS_FILE) { @@ -49,24 +51,86 @@ void WebSettings::read(WebSettings & settings, JsonObject & root) { } StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings) { - settings.tx_mode = root["tx_mode"] | EMSESP_DEFAULT_TX_MODE; - settings.ems_bus_id = root["ems_bus_id"] | EMSESP_DEFAULT_EMS_BUS_ID; + std::string crc_before(40, '\0'); + std::string crc_after(40, '\0'); + reset_flags(); + + // tx_mode, rx and tx pins + snprintf_P(&crc_before[0], crc_before.capacity() + 1, PSTR("%d%d%d"), settings.tx_mode, settings.rx_gpio, settings.tx_gpio); + settings.tx_mode = root["tx_mode"] | EMSESP_DEFAULT_TX_MODE; + settings.rx_gpio = root["rx_gpio"] | EMSESP_DEFAULT_RX_GPIO; + settings.tx_gpio = root["tx_gpio"] | EMSESP_DEFAULT_TX_GPIO; + snprintf_P(&crc_after[0], crc_after.capacity() + 1, PSTR("%d%d%d"), settings.tx_mode, settings.rx_gpio, settings.tx_gpio); + if (crc_before != crc_after) { + Serial.printf("UART CHANGED (%s) (%s)\n\r", crc_before.c_str(), crc_after.c_str()); + add_flags(ChangeFlags::UART); + } + + // syslog + snprintf_P(&crc_before[0], + crc_before.capacity() + 1, + PSTR("%d%d%d%s"), + settings.syslog_enabled, + settings.syslog_level, + settings.syslog_mark_interval, + settings.syslog_host.c_str()); settings.syslog_enabled = root["syslog_enabled"] | EMSESP_DEFAULT_SYSLOG_ENABLED; settings.syslog_level = root["syslog_level"] | EMSESP_DEFAULT_SYSLOG_LEVEL; settings.syslog_mark_interval = root["syslog_mark_interval"] | EMSESP_DEFAULT_SYSLOG_MARK_INTERVAL; settings.syslog_host = root["syslog_host"] | EMSESP_DEFAULT_SYSLOG_HOST; - settings.master_thermostat = root["master_thermostat"] | EMSESP_DEFAULT_MASTER_THERMOSTAT; - settings.shower_timer = root["shower_timer"] | EMSESP_DEFAULT_SHOWER_TIMER; - settings.shower_alert = root["shower_alert"] | EMSESP_DEFAULT_SHOWER_ALERT; - settings.rx_gpio = root["rx_gpio"] | EMSESP_DEFAULT_RX_GPIO; - settings.tx_gpio = root["tx_gpio"] | EMSESP_DEFAULT_TX_GPIO; - settings.dallas_gpio = root["dallas_gpio"] | EMSESP_DEFAULT_DALLAS_GPIO; - settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE; - settings.led_gpio = root["led_gpio"] | EMSESP_DEFAULT_LED_GPIO; - settings.hide_led = root["hide_led"] | EMSESP_DEFAULT_HIDE_LED; - settings.api_enabled = root["api_enabled"] | EMSESP_DEFAULT_API_ENABLED; - settings.bool_format = root["bool_format"] | EMSESP_DEFAULT_BOOL_FORMAT; - settings.analog_enabled = root["analog_enabled"] | EMSESP_DEFAULT_ANALOG_ENABLED; + snprintf_P(&crc_after[0], + crc_after.capacity() + 1, + PSTR("%d%d%d%s"), + settings.syslog_enabled, + settings.syslog_level, + settings.syslog_mark_interval, + settings.syslog_host.c_str()); + if (crc_before != crc_after) { + add_flags(ChangeFlags::SYSLOG); + } + + // other + snprintf_P(&crc_before[0], crc_before.capacity() + 1, PSTR("%d%d"), settings.bool_format, settings.analog_enabled); + settings.bool_format = root["bool_format"] | EMSESP_DEFAULT_BOOL_FORMAT; + settings.analog_enabled = root["analog_enabled"] | EMSESP_DEFAULT_ANALOG_ENABLED; + snprintf_P(&crc_after[0], crc_after.capacity() + 1, PSTR("%d%d"), settings.bool_format, settings.analog_enabled); + if (crc_before != crc_after) { + add_flags(ChangeFlags::OTHER); + } + + // dallas + snprintf_P(&crc_before[0], crc_before.capacity() + 1, PSTR("%d%d"), settings.dallas_gpio, settings.dallas_parasite); + settings.dallas_gpio = root["dallas_gpio"] | EMSESP_DEFAULT_DALLAS_GPIO; + settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE; + snprintf_P(&crc_after[0], crc_after.capacity() + 1, PSTR("%d%d"), settings.dallas_gpio, settings.dallas_parasite); + if (crc_before != crc_after) { + add_flags(ChangeFlags::DALLAS); + } + + // shower + snprintf_P(&crc_before[0], crc_before.capacity() + 1, PSTR("%d%d"), settings.shower_timer, settings.shower_alert); + settings.shower_timer = root["shower_timer"] | EMSESP_DEFAULT_SHOWER_TIMER; + settings.shower_alert = root["shower_alert"] | EMSESP_DEFAULT_SHOWER_ALERT; + snprintf_P(&crc_after[0], crc_after.capacity() + 1, PSTR("%d%d"), settings.shower_timer, settings.shower_alert); + if (crc_before != crc_after) { + add_flags(ChangeFlags::SHOWER); + } + + // led + snprintf_P(&crc_before[0], crc_before.capacity() + 1, PSTR("%d%d"), settings.led_gpio, settings.hide_led); + settings.led_gpio = root["led_gpio"] | EMSESP_DEFAULT_LED_GPIO; + settings.hide_led = root["hide_led"] | EMSESP_DEFAULT_HIDE_LED; + snprintf_P(&crc_after[0], crc_after.capacity() + 1, PSTR("%d%d"), settings.led_gpio, settings.hide_led); + if (crc_before != crc_after) { + add_flags(ChangeFlags::LED); + } + + // these both need reboots to be applied + settings.ems_bus_id = root["ems_bus_id"] | EMSESP_DEFAULT_EMS_BUS_ID; + settings.master_thermostat = root["master_thermostat"] | EMSESP_DEFAULT_MASTER_THERMOSTAT; + + // doesn't need any follow-up actions + settings.api_enabled = root["api_enabled"] | EMSESP_DEFAULT_API_ENABLED; return StateUpdateResult::CHANGED; } @@ -74,9 +138,35 @@ StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings) // this is called after any of the settings have been persisted to the filesystem // either via the Web UI or via the Console void WebSettingsService::onUpdate() { - EMSESP::shower_.start(); - EMSESP::dallassensor_.start(); - System::init(); + if (WebSettings::has_flags(WebSettings::ChangeFlags::SHOWER)) { + // EMSESP::logger().info(F("shower changed!")); + EMSESP::shower_.start(); + } + + if (WebSettings::has_flags(WebSettings::ChangeFlags::DALLAS)) { + // EMSESP::logger().info(F("dallas changed!")); + EMSESP::dallassensor_.start(); + } + + if (WebSettings::has_flags(WebSettings::ChangeFlags::UART)) { + // EMSESP::logger().info(F("uart changed!")); + EMSESP::init_tx(); + } + + if (WebSettings::has_flags(WebSettings::ChangeFlags::SYSLOG)) { + // EMSESP::logger().info(F("syslog changed!")); + System::syslog_init(); + } + + if (WebSettings::has_flags(WebSettings::ChangeFlags::OTHER)) { + // EMSESP::logger().info(F("other changed!")); + System::other_init(); + } + + if (WebSettings::has_flags(WebSettings::ChangeFlags::LED)) { + // EMSESP::logger().info(F("led changed!")); + System::led_init(); + } } void WebSettingsService::begin() { diff --git a/src/WebSettingsService.h b/src/WebSettingsService.h index 412c6ee0d..bf7b9373c 100644 --- a/src/WebSettingsService.h +++ b/src/WebSettingsService.h @@ -84,6 +84,33 @@ class WebSettings { static void read(WebSettings & settings, JsonObject & root); static StateUpdateResult update(JsonObject & root, WebSettings & settings); + + enum ChangeFlags : uint8_t { + + NONE = 0, + UART = (1 << 0), + SYSLOG = (1 << 1), + OTHER = (1 << 2), + DALLAS = (1 << 3), + SHOWER = (1 << 4), + LED = (1 << 5) + + }; + + static void add_flags(uint8_t flags) { + flags_ |= flags; + } + + static bool has_flags(uint8_t flags) { + return (flags_ & flags) == flags; + } + + static void reset_flags() { + flags_ = ChangeFlags::NONE; + } + + private: + static uint8_t flags_; }; class WebSettingsService : public StatefulService { diff --git a/src/system.cpp b/src/system.cpp index 205f8f884..0c0e54361 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -35,7 +35,6 @@ uuid::syslog::SyslogService System::syslog_; // init statics uint32_t System::heap_start_ = 0; -int System::reset_counter_ = 0; bool System::upload_status_ = false; bool System::hide_led_ = false; uint8_t System::led_gpio_ = 0; @@ -43,11 +42,6 @@ uint16_t System::analog_ = 0; bool System::analog_enabled_ = false; bool System::syslog_enabled_ = false; std::string System::hostname_; -int8_t System::syslog_level_ = -1; -uint32_t System::syslog_mark_interval_ = 0; -String System::syslog_host_; - - // send on/off to a gpio pin // value: true = HIGH, false = LOW @@ -91,6 +85,7 @@ bool System::command_publish(const char * value, const int8_t id) { return true; } } + EMSESP::publish_all(); // ignore value and id LOG_INFO(F("Publishing all data to MQTT")); return true; @@ -147,6 +142,10 @@ uint8_t System::free_mem() { } void System::syslog_init() { + int8_t syslog_level_; + uint32_t syslog_mark_interval_; + String syslog_host_; + // fetch settings EMSESP::webSettingsService.read([&](WebSettings & settings) { syslog_enabled_ = settings.syslog_enabled; @@ -156,24 +155,26 @@ void System::syslog_init() { }); #ifndef EMSESP_STANDALONE + + // check for empty hostname + IPAddress addr; + if (!addr.fromString(syslog_host_.c_str())) { + syslog_enabled_ = false; + } + if (!syslog_enabled_) { - syslog_.log_level((uuid::log::Level)-1); - syslog_.mark_interval(0); - syslog_.destination((IPAddress)((uint32_t)0)); + // syslog_.log_level((uuid::log::Level)-1); // in case service is still running, this flushes the queue return; } - syslog_.start(); // syslog service re-start - - // configure syslog - IPAddress addr; - if (!addr.fromString(syslog_host_.c_str())) { - addr = (uint32_t)0; - } + // start & configure syslog + syslog_.start(); syslog_.log_level((uuid::log::Level)syslog_level_); syslog_.mark_interval(syslog_mark_interval_); syslog_.destination(addr); EMSESP::esp8266React.getWiFiSettingsService()->read([&](WiFiSettings & wifiSettings) { syslog_.hostname(wifiSettings.hostname.c_str()); }); + + EMSESP::logger().info(F("Syslog started")); #endif } @@ -206,19 +207,23 @@ void System::start() { #endif }); - init(); } -// init stuff. This is called when settings are changed in the web -void System::init() { - set_led(); // init LED - +void System::other_init() { // set the boolean format used for rendering booleans EMSESP::webSettingsService.read([&](WebSettings & settings) { Helpers::bool_format(settings.bool_format); analog_enabled_ = settings.analog_enabled; }); +} + +// init stuff. This is called when settings are changed in the web +void System::init() { + led_init(); // init LED + + other_init(); + syslog_init(); // init SysLog EMSESP::esp8266React.getWiFiSettingsService()->read([&](WiFiSettings & settings) { hostname(settings.hostname.c_str()); }); @@ -227,7 +232,7 @@ void System::init() { } // set the LED to on or off when in normal operating mode -void System::set_led() { +void System::led_init() { EMSESP::webSettingsService.read([&](WebSettings & settings) { hide_led_ = settings.hide_led; led_gpio_ = settings.led_gpio; diff --git a/src/system.h b/src/system.h index 7a5caad02..ffdeb48a0 100644 --- a/src/system.h +++ b/src/system.h @@ -63,9 +63,11 @@ class System { static void upload_status(bool in_progress); static bool upload_status(); static void show_mem(const char * note); - static void set_led(); - static void init(); - static void syslog_init(); + + static void init(); + static void led_init(); + static void syslog_init(); + static void other_init(); bool check_upgrade(); void send_heartbeat(); @@ -104,23 +106,20 @@ class System { static void wifi_reconnect(); static int8_t wifi_quality(); - bool system_healthy_ = false; - uint32_t led_flash_speed_ = LED_WARNING_BLINK_FAST; // default boot flashes quickly - static uint32_t heap_start_; - static int reset_counter_; - uint32_t last_heartbeat_ = 0; - static bool upload_status_; // true if we're in the middle of a OTA firmware upload - static uint16_t analog_; - static std::string hostname_; + bool system_healthy_ = false; + uint32_t led_flash_speed_ = LED_WARNING_BLINK_FAST; // default boot flashes quickly + uint32_t last_heartbeat_ = 0; + + static bool upload_status_; // true if we're in the middle of a OTA firmware upload + static uint32_t heap_start_; + static uint16_t analog_; // settings - static bool hide_led_; - static bool syslog_enabled_; - static int8_t syslog_level_; - static uint32_t syslog_mark_interval_; - static String syslog_host_; - static uint8_t led_gpio_; - static bool analog_enabled_; + static std::string hostname_; + static bool hide_led_; + static uint8_t led_gpio_; + static bool syslog_enabled_; + static bool analog_enabled_; }; } // namespace emsesp