diff --git a/code/espurna/button.ino b/code/espurna/button.ino index 3bb70e79..451d9596 100644 --- a/code/espurna/button.ino +++ b/code/espurna/button.ino @@ -93,6 +93,12 @@ void buttonEvent(unsigned char id, unsigned char event) { } #endif + #if THERMOSTAT_DISPLAY_SUPPORT + if (BUTTON_MODE_DISPLAY_ON == action) { + displayOn(); + } + #endif + if (BUTTON_MODE_TOGGLE == action) { relayToggle(button.relayID); } diff --git a/code/espurna/config/dependencies.h b/code/espurna/config/dependencies.h index 2ab46c9d..a396f4d6 100644 --- a/code/espurna/config/dependencies.h +++ b/code/espurna/config/dependencies.h @@ -156,3 +156,13 @@ #else #define NTP_LEGACY_SUPPORT 0 #endif + +//------------------------------------------------------------------------------ +// It looks more natural that one click will enable display +// and long click will switch relay +#if THERMOSTAT_DISPLAY_SUPPORT +#undef BUTTON1_CLICK +#define BUTTON1_CLICK BUTTON_MODE_DISPLAY_ON +#undef BUTTON1_LNGCLICK +#define BUTTON1_LNGCLICK BUTTON_MODE_TOGGLE +#endif diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index b657877d..a614f8fa 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -9,7 +9,9 @@ // GENERAL //------------------------------------------------------------------------------ +#ifndef DEVICE_NAME #define DEVICE_NAME MANUFACTURER "_" DEVICE // Concatenate both to get a unique device name +#endif // When defined, ADMIN_PASS must be 8..63 printable ASCII characters. See: // https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#Target_users_(authentication_key_distribution) @@ -232,9 +234,17 @@ #define THERMOSTAT_DISPLAY_SUPPORT 0 #endif +#ifndef THERMOSTAT_DISPLAY_OFF_INTERVAL // Interval in seconds after which display will be switched off +#define THERMOSTAT_DISPLAY_OFF_INTERVAL 0 // This will prevent it from burnout +#endif // 0 - newer switch display off + #define THERMOSTAT_SERVER_LOST_INTERVAL 120000 //server means lost after 2 min from last response #define THERMOSTAT_REMOTE_TEMP_MAX_WAIT 120 // 2 min +#ifndef THERMOSTAT_REMOTE_SENSOR_NAME +#define THERMOSTAT_REMOTE_SENSOR_NAME "" // Get remote temp(hum) from mqtt topic of this device +#endif + //------------------------------------------------------------------------------ // HEARTBEAT //------------------------------------------------------------------------------ diff --git a/code/espurna/config/types.h b/code/espurna/config/types.h index 38d28aa6..f0c1f8ec 100644 --- a/code/espurna/config/types.h +++ b/code/espurna/config/types.h @@ -43,6 +43,7 @@ #define BUTTON_MODE_SMART_CONFIG 9 #define BUTTON_MODE_DIM_UP 10 #define BUTTON_MODE_DIM_DOWN 11 +#define BUTTON_MODE_DISPLAY_ON 12 // Needed for ESP8285 boards under Windows using PlatformIO (?) diff --git a/code/espurna/thermostat.ino b/code/espurna/thermostat.ino index 476845d3..1adf88ac 100644 --- a/code/espurna/thermostat.ino +++ b/code/espurna/thermostat.ino @@ -54,6 +54,8 @@ const char* NAME_OPERATION_MODE = "thermostatOperationMode"; #define THERMOSTAT_ALONE_OFF_TIME 55 // 55 min #define THERMOSTAT_MAX_ON_TIME 30 // 30 min #define THERMOSTAT_MIN_OFF_TIME 10 // 10 min +#define THERMOSTAT_ENABLED_BY_DEFAULT true +#define THERMOSTAT_MODE_COOLER_BY_DEFAULT false unsigned long _thermostat_remote_temp_max_wait = THERMOSTAT_REMOTE_TEMP_MAX_WAIT * MILLIS_IN_SEC; unsigned long _thermostat_alone_on_time = THERMOSTAT_ALONE_ON_TIME * MILLIS_IN_MIN; @@ -81,7 +83,7 @@ struct temp_range_t { int max = THERMOSTAT_TEMP_RANGE_MAX; unsigned long last_update = 0; unsigned long ask_time = 0; - unsigned int ask_interval = 0; + unsigned long ask_interval = ASK_TEMP_RANGE_INTERVAL_INITIAL; bool need_display_update = true; }; temp_range_t _temp_range; @@ -167,8 +169,6 @@ void thermostatMQTTCallback(unsigned int type, const char * topic, const char * if (type == MQTT_CONNECT_EVENT) { mqttSubscribeRaw(thermostat_remote_sensor_topic.c_str()); mqttSubscribe(MQTT_TOPIC_HOLD_TEMP); - _temp_range.ask_interval = ASK_TEMP_RANGE_INTERVAL_INITIAL; - _temp_range.ask_time = millis(); } if (type == MQTT_MESSAGE_EVENT) { @@ -253,10 +253,10 @@ void notifyRangeChanged(bool min) { // Setup //------------------------------------------------------------------------------ void commonSetup() { - _thermostat_enabled = getSetting(NAME_THERMOSTAT_ENABLED, false); + _thermostat_enabled = getSetting(NAME_THERMOSTAT_ENABLED, THERMOSTAT_ENABLED_BY_DEFAULT); DEBUG_MSG_P(PSTR("[THERMOSTAT] _thermostat_enabled = %d\n"), _thermostat_enabled); - _thermostat_mode_cooler = getSetting(NAME_THERMOSTAT_MODE, false); + _thermostat_mode_cooler = getSetting(NAME_THERMOSTAT_MODE, THERMOSTAT_MODE_COOLER_BY_DEFAULT); DEBUG_MSG_P(PSTR("[THERMOSTAT] _thermostat_mode_cooler = %d\n"), _thermostat_mode_cooler); _temp_range.min = getSetting(NAME_TEMP_RANGE_MIN, THERMOSTAT_TEMP_RANGE_MIN); @@ -264,7 +264,7 @@ void commonSetup() { DEBUG_MSG_P(PSTR("[THERMOSTAT] _temp_range.min = %d\n"), _temp_range.min); DEBUG_MSG_P(PSTR("[THERMOSTAT] _temp_range.max = %d\n"), _temp_range.max); - _thermostat.remote_sensor_name = getSetting(NAME_REMOTE_SENSOR_NAME); + _thermostat.remote_sensor_name = getSetting(NAME_REMOTE_SENSOR_NAME, THERMOSTAT_REMOTE_SENSOR_NAME); thermostat_remote_sensor_topic = _thermostat.remote_sensor_name + String("/") + String(MQTT_TOPIC_JSON); _thermostat_remote_temp_max_wait = getSetting(NAME_REMOTE_TEMP_MAX_WAIT, THERMOSTAT_REMOTE_TEMP_MAX_WAIT) * MILLIS_IN_SEC; @@ -275,7 +275,7 @@ void commonSetup() { } //------------------------------------------------------------------------------ -void thermostatConfigure() { +void thermostatSetup() { commonSetup(); _thermostat.temperature_source = temp_none; @@ -286,6 +286,21 @@ void thermostatConfigure() { _thermostat_burn_prev_month = getSetting(NAME_BURN_PREV_MONTH, 0); _thermostat_burn_day = getSetting(NAME_BURN_DAY, 0); _thermostat_burn_month = getSetting(NAME_BURN_MONTH, 0); + + #if MQTT_SUPPORT + thermostatSetupMQTT(); + #endif + + // Websockets + #if WEB_SUPPORT + wsRegister() + .onConnected(_thermostatWebSocketOnConnected) + .onKeyCheck(_thermostatWebSocketOnKeyCheck) + .onAction(_thermostatWebSocketOnAction); + #endif + + espurnaRegisterLoop(thermostatLoop); + espurnaRegisterReload(_thermostatReload); } //------------------------------------------------------------------------------ @@ -353,26 +368,6 @@ void _thermostatWebSocketOnAction(uint32_t client_id, const char * action, JsonO } #endif -//------------------------------------------------------------------------------ -void thermostatSetup() { - thermostatConfigure(); - - #if MQTT_SUPPORT - thermostatSetupMQTT(); - #endif - - // Websockets - #if WEB_SUPPORT - wsRegister() - .onConnected(_thermostatWebSocketOnConnected) - .onKeyCheck(_thermostatWebSocketOnKeyCheck) - .onAction(_thermostatWebSocketOnAction); - #endif - - espurnaRegisterLoop(thermostatLoop); - espurnaRegisterReload(_thermostatReload); -} - //------------------------------------------------------------------------------ void sendTempRangeRequest() { DEBUG_MSG_P(PSTR("[THERMOSTAT] sendTempRangeRequest\n")); @@ -638,12 +633,16 @@ SSD1306 display(0x3c, 1, 3); unsigned long _local_temp_last_update = 0xFFFF; unsigned long _local_hum_last_update = 0xFFFF; +unsigned long _thermostat_display_off_interval = THERMOSTAT_DISPLAY_OFF_INTERVAL * MILLIS_IN_SEC; +unsigned long _thermostat_display_on_time = millis(); +bool _thermostat_display_is_on = true; bool _display_wifi_status = true; bool _display_mqtt_status = true; bool _display_server_status = true; bool _display_remote_temp_status = true; -bool _display_need_refresh = false; +bool _display_need_refresh = true; bool _temp_range_need_update = true; + //------------------------------------------------------------------------------ void drawIco(int16_t x, int16_t y, const char *ico, bool on = true) { display.drawIco16x16(x, y, ico, !on); @@ -695,7 +694,7 @@ void display_remote_temp() { display.setColor(WHITE); display.setFont(ArialMT_Plain_16); display.setTextAlignment(TEXT_ALIGN_LEFT); - String temp_range_title = String("Remote t"); + String temp_range_title = String("Remote t"); display.drawString(0, 16, temp_range_title); String temp_range_vol = String("= ") + (_display_remote_temp_status ? String(_remote_temp.temp, 1) : String("?")) + "°"; @@ -712,7 +711,7 @@ void display_local_temp() { display.setFont(ArialMT_Plain_16); display.setTextAlignment(TEXT_ALIGN_LEFT); - String local_temp_title = String("Local t"); + String local_temp_title = String("Local t"); display.drawString(0, 32, local_temp_title); String local_temp_vol = String("= ") + (getLocalTemperature() != DBL_MIN ? String(getLocalTemperature(), 1) : String("?")) + "°"; @@ -729,7 +728,7 @@ void display_local_humidity() { display.setFont(ArialMT_Plain_16); display.setTextAlignment(TEXT_ALIGN_LEFT); - String local_hum_title = String("Local h "); + String local_hum_title = String("Local h "); display.drawString(0, 48, local_hum_title); String local_hum_vol = String("= ") + (getLocalHumidity() != DBL_MIN ? String(getLocalHumidity(), 0) : String("?")) + "%"; @@ -737,6 +736,23 @@ void display_local_humidity() { _display_need_refresh = true; } + +//------------------------------------------------------------------------------ +void displayOn() { + DEBUG_MSG_P(PSTR("[THERMOSTAT] Display is On.\n")); + _thermostat_display_on_time = millis(); + _thermostat_display_is_on = true; + _display_need_refresh = true; + display_wifi_status(_display_wifi_status); + display_mqtt_status(_display_mqtt_status); + display_server_status(_display_server_status); + display_remote_temp_status(_display_remote_temp_status); + _temp_range.need_display_update = true; + _remote_temp.need_display_update = true; + display_local_temp(); + display_local_humidity(); +} + //------------------------------------------------------------------------------ // Setup //------------------------------------------------------------------------------ @@ -744,16 +760,21 @@ void displaySetup() { display.init(); display.flipScreenVertically(); - // display.setFont(ArialMT_Plain_24); - // display.setTextAlignment(TEXT_ALIGN_CENTER); - // display.drawString(64, 17, "Thermostat"); + displayOn(); - espurnaRegisterLoop(displayLoop); + espurnaRegisterLoop(displayLoop); } //------------------------------------------------------------------------------ void displayLoop() { - _display_need_refresh = false; + if (THERMOSTAT_DISPLAY_OFF_INTERVAL > 0 && millis() - _thermostat_display_on_time > _thermostat_display_off_interval) { + if (_thermostat_display_is_on) { + DEBUG_MSG_P(PSTR("[THERMOSTAT] Display Off by timeout\n")); + _thermostat_display_is_on = false; + display.resetDisplay(); + } + return; + } //------------------------------------------------------------------------------ // Indicators @@ -772,14 +793,14 @@ void displayLoop() { display_mqtt_status(false); } - if (millis() - _temp_range.last_update < THERMOSTAT_SERVER_LOST_INTERVAL) { + if (_temp_range.last_update != 0 && millis() - _temp_range.last_update < THERMOSTAT_SERVER_LOST_INTERVAL) { if (!_display_server_status) display_server_status(true); } else if (_display_server_status) { display_server_status(false); } - if (millis() - _remote_temp.last_update < _thermostat_remote_temp_max_wait) { + if (_remote_temp.last_update != 0 && millis() - _remote_temp.last_update < _thermostat_remote_temp_max_wait) { if (!_display_remote_temp_status) display_remote_temp_status(true); } else if (_display_remote_temp_status) { @@ -823,6 +844,7 @@ void displayLoop() { if (_display_need_refresh) { yield(); display.display(); + _display_need_refresh = false; } } diff --git a/code/platformio.ini b/code/platformio.ini index e8dfb772..52682d0d 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -132,7 +132,7 @@ lib_deps = https://github.com/sparkfun/SparkFun_VEML6075_Arduino_Library#V_1.0.3 https://github.com/pololu/vl53l1x-arduino#1.0.1 https://github.com/mcleng/MAX6675-Library#2.0.1 - https://github.com/ElderJoy/esp8266-oled-ssd1306#4.0.1 + https://github.com/ThingPulse/esp8266-oled-ssd1306#3398c97 lib_ignore = AsyncTCP