diff --git a/CHANGELOG.md b/CHANGELOG.md index e01addfa8..41d2a4511 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,13 +15,15 @@ All notable changes to this project will be documented in this file. ### Changed - TasmotaSerial library from v3.5.0 to v3.6.0 - Removed leading spaces on commands ``(S)SerialSend1 to 6`` but keep on duplicate commands ``(S)SerialSend11 to 16`` (#16723) +- MQTT now uses Tasmota's DNS resolver instead of LWIP (#17387) +- Shutter bug fixes and functionality upgrade (#17380) ### Fixed - TasmotaSerial ``read(buffer, size)`` regression from v9.3.0 - RCSwitch exception 0/6 on some protocols (#17285) - ESP32 exception 28 when RtcNtpServer is enabled on restart (#17338) - Analog MQ exception 28 on restart (#17271) -- ESP32 fix ``Ping`` +- ESP32 fix ``Ping`` (#17373) ## [12.2.0.5] 20221129 ### Added diff --git a/RELEASENOTES.md b/RELEASENOTES.md index cd7f36a2b..48a7f2f3e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -155,6 +155,8 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - AC PWM dimmer lineair power distribution [#17177](https://github.com/arendst/Tasmota/issues/17177) - Zigbee improved Aqara plug support and completed cluster 0x0702 [#17073](https://github.com/arendst/Tasmota/issues/17073) - Removed leading spaces on commands ``(S)SerialSend1 to 6`` but keep on duplicate commands ``(S)SerialSend11 to 16`` [#16723](https://github.com/arendst/Tasmota/issues/16723 +- Shutter bug fixes and functionality upgrade [#17380](https://github.com/arendst/Tasmota/issues/17380 +- MQTT now uses Tasmota's DNS resolver instead of LWIP [#17387](https://github.com/arendst/Tasmota/issues/17387 ### Fixed - TasmotaSerial ``read(buffer, size)`` regression from v9.3.0 diff --git a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp index 4028c4c5e..aa1aab9dd 100755 --- a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp +++ b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.cpp @@ -299,7 +299,7 @@ int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port, int32_t timeout setLastError(ERR_TCP_CONNECT); return 0; } - return _connectSSL(nullptr); + return _connectSSL(_domain.isEmpty() ? nullptr : _domain.c_str()); } #else // ESP32 int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port) { diff --git a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h index 65a3544be..a93960086 100755 --- a/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h +++ b/lib/lib_ssl/tls_mini/src/WiFiClientSecureLightBearSSL.h @@ -126,6 +126,10 @@ class WiFiClientSecure_light : public WiFiClient { void setInsecure(); + void setDomainName(const char * domain) { + _domain = domain; + } + private: void _clear(); bool _ctx_present; @@ -172,6 +176,9 @@ class WiFiClientSecure_light : public WiFiClient { // record the maximum use of ThunkStack for monitoring size_t _max_thunkstack_use; + // domain name (string) that will be used with SNI when the address provided is already resolved + String _domain; + // ALPN const char ** _alpn_names; size_t _alpn_num; diff --git a/pio-tools/gzip-firmware.py b/pio-tools/gzip-firmware.py index 90e7f80d6..a497e03fb 100644 --- a/pio-tools/gzip-firmware.py +++ b/pio-tools/gzip-firmware.py @@ -29,8 +29,7 @@ def map_gzip(source, target, env): if not tasmotapiolib.is_env_set(tasmotapiolib.DISABLE_MAP_GZ, env): env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [map_gzip]) -# gzip only for ESP8266 -if env["PIOPLATFORM"] != "espressif32": +if tasmotapiolib.is_env_set(tasmotapiolib.ENABLE_ESP32_GZ, env) or env["PIOPLATFORM"] != "espressif32": from zopfli.gzip import compress def bin_gzip(source, target, env): # create string with location and file names based on variant @@ -50,7 +49,7 @@ if env["PIOPLATFORM"] != "espressif32": ORG_FIRMWARE_SIZE = bin_file.stat().st_size GZ_FIRMWARE_SIZE = gzip_file.stat().st_size - if ORG_FIRMWARE_SIZE > 995326: + if ORG_FIRMWARE_SIZE > 995326 and env["PIOPLATFORM"] != "espressif32": print( "\u001b[31;1m!!! Tasmota firmware size is too big with {} bytes. Max size is 995326 bytes !!! \u001b[0m".format( ORG_FIRMWARE_SIZE diff --git a/pio-tools/tasmotapiolib.py b/pio-tools/tasmotapiolib.py index 7ee8fe9a3..3105739c1 100644 --- a/pio-tools/tasmotapiolib.py +++ b/pio-tools/tasmotapiolib.py @@ -25,8 +25,10 @@ import pathlib import os # === AVAILABLE OVERRIDES === -# if set to 1, will not gzip esp8266 bin files +# if set to 1, will not gzip bin files at all DISABLE_BIN_GZ = "disable_bin_gz" +# if set to 1, will gzip esp32 bin files +ENABLE_ESP32_GZ = "enable_esp32_gz" # if set, an alternative ptah to put generated .bin files, relative to project directory BIN_DIR = "bin_dir" # if set to 1, will not gzip generated .map files diff --git a/platformio.ini b/platformio.ini index 3e08f6cb2..3a77eb1a1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -58,8 +58,10 @@ lib_extra_dirs = ;disable_map_gz = 1 ; Uncomment and specify a folder where to place the map file(s) (default set to folder build_output) ;map_dir = /tmp/map_files/ -; Uncomment if you do NOT want additionally gzipped firmware file(s) +; Uncomment if you do NOT want additionally gzipped firmware file(s) at all ;disable_bin_gz = 1 +; Uncomment if you want additionally gzipped esp32x firmware file(s) +;enable_esp32_gz = 1 ; Uncomment and specify a folder where to place the firmware file(s) (default set to folder build_output) ;bin_dir = /tmp/bin_files/ diff --git a/tasmota/include/i18n.h b/tasmota/include/i18n.h index 4294c3297..e228989e1 100644 --- a/tasmota/include/i18n.h +++ b/tasmota/include/i18n.h @@ -738,6 +738,7 @@ #define D_CMND_SHUTTER_TILTCONFIG "TiltConfig" #define D_CMND_SHUTTER_SETTILT "Tilt" #define D_CMND_SHUTTER_TILTINCDEC "TiltChange" +#define D_CMND_SHUTTER_MOTORSTOP "MotorStop" // Commands xdrv_32_hotplug.ino #define D_CMND_HOTPLUG "HotPlug" diff --git a/tasmota/include/tasmota_configurations_ESP32.h b/tasmota/include/tasmota_configurations_ESP32.h index 11966f961..aa1c0d823 100644 --- a/tasmota/include/tasmota_configurations_ESP32.h +++ b/tasmota/include/tasmota_configurations_ESP32.h @@ -264,6 +264,8 @@ #define USE_MI_ESP32 // (ESP32 only) Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash) #endif // enable USE_MI_HOMEKIT +#define USE_ETHERNET // Add support for ethernet (+20k code + #endif // FIRMWARE_BLUETOOTH /*********************************************************************************************\ @@ -454,6 +456,8 @@ #define USE_IR_REMOTE +#define USE_ETHERNET // Add support for ethernet (+20k code + #endif // FIRMWARE_TASMOTA_LVGL ******************************************************************* /*********************************************************************************************\ diff --git a/tasmota/include/tasmota_types.h b/tasmota/include/tasmota_types.h index fbd94f0ab..4ee133e04 100644 --- a/tasmota/include/tasmota_types.h +++ b/tasmota/include/tasmota_types.h @@ -730,8 +730,8 @@ typedef struct { #endif // ESP32 uint16_t artnet_universe; // 734 uint16_t modbus_sbaudrate; // 736 - - uint8_t free_esp32_738[5]; // 738 + uint16_t shutter_motorstop; // 738 + uint8_t free_esp32_73A[3]; // 73A uint8_t novasds_startingoffset; // 73D uint8_t web_color[18][3]; // 73E diff --git a/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino index 950085016..b4407804d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino @@ -1065,11 +1065,12 @@ void MqttReconnect(void) { MqttClient.setCallback(MqttDataHandler); // Keep using hostname to solve rc -4 issues - if (!WifiDnsPresent(SettingsText(SET_MQTT_HOST))) { + IPAddress ip; + if (!WifiHostByName(SettingsText(SET_MQTT_HOST), ip)) { MqttDisconnected(-5); // MQTT_DNS_DISCONNECTED return; } - MqttClient.setServer(SettingsText(SET_MQTT_HOST), Settings->mqtt_port); + MqttClient.setServer(ip, Settings->mqtt_port); if (2 == Mqtt.initial_connection_state) { // Executed once just after power on and wifi is connected Mqtt.initial_connection_state = 1; @@ -1085,9 +1086,11 @@ void MqttReconnect(void) { } #ifdef USE_MQTT_TLS + uint32_t mqtt_connect_time = millis(); if (Mqtt.mqtt_tls) { tlsClient->stop(); + tlsClient->setDomainName(SettingsText(SET_MQTT_HOST)); // set domain name for TLS SNI (selection of certificate based on domain name) } else { MqttClient.setClient(EspClient); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino index 07b839957..83b005930 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino @@ -56,8 +56,8 @@ int32_t next_possible_stop_position = 0; int32_t current_real_position = 0; int32_t current_pwm_velocity = 0; -const uint8_t MAX_MODES = 7; -enum Shutterposition_mode {SHT_UNDEF, SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,}; +const uint8_t MAX_MODES = 8; +enum Shutterposition_mode {SHT_UNDEF, SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,SHT_AUTOCONFIG}; enum Shutterswitch_mode {SHT_SWITCH, SHT_PULSE,}; enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_EXT_HOLD, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,}; @@ -67,7 +67,7 @@ const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_SETOPEN "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|" D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME "|" D_CMND_SHUTTER_INVERTWEBBUTTONS "|" D_CMND_SHUTTER_STOPOPEN "|" D_CMND_SHUTTER_STOPCLOSE "|" D_CMND_SHUTTER_STOPTOGGLE "|" D_CMND_SHUTTER_STOPTOGGLEDIR "|" D_CMND_SHUTTER_STOPPOSITION "|" D_CMND_SHUTTER_INCDEC "|" - D_CMND_SHUTTER_UNITTEST "|" D_CMND_SHUTTER_TILTCONFIG "|" D_CMND_SHUTTER_SETTILT "|" D_CMND_SHUTTER_TILTINCDEC; + D_CMND_SHUTTER_UNITTEST "|" D_CMND_SHUTTER_TILTCONFIG "|" D_CMND_SHUTTER_SETTILT "|" D_CMND_SHUTTER_TILTINCDEC "|" D_CMND_SHUTTER_MOTORSTOP; void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterOpen, &CmndShutterClose, &CmndShutterToggle, &CmndShutterToggleDir, &CmndShutterStop, &CmndShutterPosition, @@ -75,7 +75,7 @@ void (* const ShutterCommand[])(void) PROGMEM = { &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterSetOpen, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay, &CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime, &CmndShutterInvertWebButtons, &CmndShutterStopOpen, &CmndShutterStopClose, &CmndShutterStopToggle, &CmndShutterStopToggleDir, &CmndShutterStopPosition, &CmndShutterIncDec, - &CmndShutterUnitTest,&CmndShutterTiltConfig,&CmndShutterSetTilt,&CmndShutterTiltIncDec}; + &CmndShutterUnitTest,&CmndShutterTiltConfig,&CmndShutterSetTilt,&CmndShutterTiltIncDec,&CmndShutterMotorStop}; const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d,\"Tilt\":%d}"; const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}"; @@ -111,6 +111,7 @@ struct SHUTTER { uint16_t min_realPositionChange = 0; // minimum change of the position before the shutter operates. different for PWM and time based operations uint16_t min_TiltChange = 0; // minimum change of the tilt before the shutter operates. different for PWM and time based operations uint16_t last_reported_time =0; + uint32_t last_stop_time = 0; // record the last time the relay was switched off } Shutter[MAX_SHUTTERS]; struct SHUTTERGLOBAL { @@ -276,8 +277,9 @@ void ShutterInit(void) } for (uint32_t i = 0; i < MAX_SHUTTERS; i++) { // set startrelay to 1 on first init, but only to shutter 1. 90% usecase - Settings->shutter_startrelay[i] = (Settings->shutter_startrelay[i] == 0 && i == 0? 1 : Settings->shutter_startrelay[i]); - if (Settings->shutter_startrelay[i] && (Settings->shutter_startrelay[i] <= MAX_RELAYS )) { + //Settings->shutter_startrelay[i] = (Settings->shutter_startrelay[i] == 0 && i == 0? 1 : Settings->shutter_startrelay[i]); + if (Settings->shutter_startrelay[i] && (Settings->shutter_startrelay[i] <= 32 )) { + bool relay_in_interlock = false; TasmotaGlobal.shutters_present++; // Add the two relays to the mask to knaw they belong to shutters @@ -293,31 +295,32 @@ void ShutterInit(void) break; } - if (Settings->shutter_mode == SHT_UNDEF) { - bool relay_in_interlock = false; - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Mode undef.. calculate...")); - - for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings->flag.interlock; j++) { // CMND_INTERLOCK - Enable/disable interlock - //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Interlock state i=%d %d, flag %d, Shuttermask %d, MaskedIL %d"),i, Settings->interlock[i], Settings->flag.interlock,ShutterGlobal.RelayShutterMask, Settings->interlock[i]&ShutterGlobal.RelayShutterMask); - if (Settings->interlock[j] && (Settings->interlock[j] & ShutterGlobal.RelayShutterMask)) { - //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Relay in Interlock group")); - relay_in_interlock = true; - } + // Check if the relay is in an INTERLOCK group. required to set the right mode or + // verify that on SHT_TIME INTERLOCK is set + for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings->flag.interlock; j++) { // CMND_INTERLOCK - Enable/disable interlock + //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Interlock state i=%d %d, flag %d, Shuttermask %d, MaskedIL %d"),i, Settings->interlock[i], Settings->flag.interlock,ShutterGlobal.RelayShutterMask, Settings->interlock[i]&ShutterGlobal.RelayShutterMask); + if (Settings->interlock[j] && (Settings->interlock[j] & ShutterGlobal.RelayShutterMask)) { + //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Relay in Interlock group")); + relay_in_interlock = true; } + } - if (relay_in_interlock) { - ShutterGlobal.position_mode = SHT_TIME; - } else { - ShutterGlobal.position_mode = SHT_TIME_UP_DOWN; + if (Settings->shutter_mode == SHT_AUTOCONFIG || Settings->shutter_mode == SHT_UNDEF) { + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Mode undef.. calculate...")); + ShutterGlobal.position_mode = SHT_TIME; + if (!relay_in_interlock) { + // temporary to maintain old functionality + if (Settings->shutter_mode == SHT_UNDEF) { + ShutterGlobal.position_mode = SHT_TIME_UP_DOWN; + } if (PinUsed(GPIO_PWM1, i) && PinUsed(GPIO_CNTR1, i)) { ShutterGlobal.position_mode = SHT_COUNTER; } } - } else { ShutterGlobal.position_mode = Settings->shutter_mode; } - + AddLog(LOG_LEVEL_INFO, PSTR("SHT: ShutterMode: %d"), ShutterGlobal.position_mode); // main function for stepper and servos to control velocity and acceleration. TickerShutter.attach_ms(50, ShutterRtc50mS ); @@ -369,6 +372,14 @@ void ShutterInit(void) Shutter[i].min_realPositionChange = 0; Shutter[i].min_TiltChange = 0; break; + case SHT_TIME: + // Test is the relays are in interlock mode. Disable shuttermode if error + if (!relay_in_interlock) { + TasmotaGlobal.shutters_present = 0, + AddLog(LOG_LEVEL_ERROR, PSTR("SHT: ERROR: Shtr%d Relays are not in INTERLOCK. Pls read documentation. Shutter DISABLE. Fix and REBOOT"),i+1); + return; + } + break; } AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d min realpos_chg: %d, min tilt_chg %d"),i+1,Shutter[i].min_realPositionChange,Shutter[i].min_TiltChange); AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Openvel %d, Closevel: %d"),i, ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max); @@ -382,6 +393,9 @@ void ShutterInit(void) } ShutterLimitRealAndTargetPositions(i); Settings->shutter_accuracy = 1; + Settings->shutter_mode = ShutterGlobal.position_mode; + // initialize MotorStop time with 500ms if not set + Settings->shutter_motorstop = Settings->shutter_motorstop == 0?500:Settings->shutter_motorstop; } } @@ -568,7 +582,22 @@ void ShutterPowerOff(uint8_t i) if (Settings->save_data) { TasmotaGlobal.save_data_counter = Settings->save_data; } - delay(MOTOR_STOP_TIME); + //delay(MOTOR_STOP_TIME); + Shutter[i].last_stop_time = millis(); +} + +void ShutterWaitForMotorStop(uint8_t index) +{ + Shutter[index-1].last_stop_time = millis(); + ShutterWaitForMotorStart(index); +} + +void ShutterWaitForMotorStart(uint8_t index) +{ + while (millis() < Shutter[index-1].last_stop_time + Settings->shutter_motorstop) { + loop(); + } + //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Stoptime done")); } void ShutterUpdatePosition(void) @@ -583,8 +612,8 @@ void ShutterUpdatePosition(void) } int32_t deltatime = Shutter[i].time-Shutter[i].last_reported_time; Shutter[i].last_reported_time = Shutter[i].time+1; - AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Time %d(%d), cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), - Shutter[i].time, deltatime, current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Time %d(%d), cStop %d, cVelo %d, mVelo %d, aVelo %d, mRun %d, aPos %d, aPos2 %d, nStop %d, Trgt %d, mVelo %d, Dir %d, Tilt %d, TrgtTilt: %d, Tiltmove: %d"), + i+1, Shutter[i].time, deltatime, current_stop_way, current_pwm_velocity, velocity_max, Shutter[i].accelerator, min_runtime_ms, current_real_position,Shutter[i].real_position, next_possible_stop_position, Shutter[i].target_position, velocity_change_per_step_max, Shutter[i].direction,Shutter[i].tilt_real_pos, Shutter[i].tilt_target_pos, Shutter[i].tiltmoving); if ( ((Shutter[i].real_position * Shutter[i].direction >= Shutter[i].target_position * Shutter[i].direction && Shutter[i].tiltmoving==0) || @@ -661,6 +690,7 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) ShutterGlobal.skip_relay_change = 1; } else { Shutter[i].pwm_velocity = 0; + ShutterWaitForMotorStart(i+1); switch (ShutterGlobal.position_mode) { #ifdef SHUTTER_STEPPER case SHT_COUNTER: @@ -704,6 +734,7 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos) } } //AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Start shtr%d from %d to %d in dir: %d"), i, Shutter[i].start_position, Shutter[i].target_position, direction); + Shutter[i].direction = direction; // Last action. This causes RTC to start. } @@ -1189,6 +1220,8 @@ void CmndShutterPosition(void) // special handling fo UP,DOWN,TOGGLE,STOP command comming with payload -99 // STOP will come with payload 0 because predefined value in TASMOTA if ((XdrvMailbox.data_len > 3) && (XdrvMailbox.payload <= 0)) { + // set len to 0 to avoid loop on close where payload is 0 + XdrvMailbox.data_len = 0; if ( ((Shutter[index].direction==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPOPEN))) { CmndShutterOpen(); return; @@ -1279,9 +1312,11 @@ void CmndShutterPosition(void) AddLog(LOG_LEVEL_INFO, PSTR("SHT: Garage not move in this direction: %d"), Shutter[index].switch_mode == SHT_PULSE); for (uint8_t k=0 ; k <= (uint8_t)(Shutter[index].switch_mode == SHT_PULSE) ; k++) { ExecuteCommandPowerShutter(Settings->shutter_startrelay[index], 1, SRC_SHUTTER); - delay(MOTOR_STOP_TIME); + //delay(MOTOR_STOP_TIME); + ShutterWaitForMotorStop(index); ExecuteCommandPowerShutter(Settings->shutter_startrelay[index], 0, SRC_SHUTTER); - delay(MOTOR_STOP_TIME); + //delay(MOTOR_STOP_TIME); + ShutterWaitForMotorStop(index); } // reset shutter time to avoid 2 seconds above count as runtime Shutter[index].time = 0; @@ -1363,10 +1398,9 @@ void CmndShutterMotorDelay(void) void CmndShutterMode(void) { - if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) { + if (!XdrvMailbox.usridx) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAX_MODES)) { - ShutterGlobal.position_mode = XdrvMailbox.payload; - Settings->shutter_mode = XdrvMailbox.payload; + Settings->shutter_mode = ShutterGlobal.position_mode = XdrvMailbox.payload; ShutterInit(); } ResponseCmndNumber(ShutterGlobal.position_mode); @@ -1375,14 +1409,22 @@ void CmndShutterMode(void) void CmndShutterRelay(void) { - if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64) && (XdrvMailbox.index <= MAX_SHUTTERS)) { - Settings->shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 32) && (XdrvMailbox.index <= MAX_SHUTTERS)) { + //Settings->shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; if (XdrvMailbox.payload > 0) { ShutterGlobal.RelayShutterMask |= 3 << (XdrvMailbox.payload - 1); } else { ShutterGlobal.RelayShutterMask ^= 3 << (Settings->shutter_startrelay[XdrvMailbox.index -1] - 1); } + AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: relold:%d index:%d, mode:%d, relaymask: %ld"), + Settings->shutter_startrelay[XdrvMailbox.index -1] , XdrvMailbox.index ,Settings->shutter_mode, ShutterGlobal.RelayShutterMask ); + if (Settings->shutter_startrelay[XdrvMailbox.index -1] == 0 && XdrvMailbox.index == 1 && Settings->shutter_mode == SHT_UNDEF) { + // first shutter was not defined, maybe init + Settings->shutter_mode = SHT_AUTOCONFIG; + AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Autoconfig")); + } Settings->shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload; + ShutterInit(); // if payload is 0 to disable the relay there must be a reboot. Otherwhise does not work } @@ -1391,7 +1433,7 @@ void CmndShutterRelay(void) // {"ShutterRelay1":"1","ShutterRelay2":"3","ShutterRelay3":"5"} Response_P(PSTR("{")); for (uint32_t i = start; i < end; i++) { - ResponseAppend_P(PSTR("%s\"" D_PRFX_SHUTTER D_CMND_SHUTTER_RELAY "%d\":\"%d\""), (i)?",":"", i+1,Settings->shutter_startrelay[i]); + ResponseAppend_P(PSTR("%s\"" D_PRFX_SHUTTER D_CMND_SHUTTER_RELAY "%d\":\"%d\""), (i>start)?",":"", i+1,Settings->shutter_startrelay[i]); } ResponseAppend_P(PSTR("}")); } @@ -1729,6 +1771,16 @@ void CmndShutterTiltIncDec(void) } } +void CmndShutterMotorStop(void) +{ + if (!XdrvMailbox.usridx) { + if ((XdrvMailbox.payload >= 0) ) { + Settings->shutter_motorstop = XdrvMailbox.payload; + } + ResponseCmndNumber(Settings->shutter_motorstop); + } +} + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -1738,6 +1790,10 @@ bool Xdrv27(uint32_t function) bool result = false; if (Settings->flag3.shutter_mode) { // SetOption80 - Enable shutter support + uint8_t counter = XdrvMailbox.index==0?1:XdrvMailbox.index; + uint8_t counterend = XdrvMailbox.index==0?TasmotaGlobal.shutters_present:XdrvMailbox.index; + int32_t rescue_payload = XdrvMailbox.payload; + uint32_t rescue_data_len = XdrvMailbox.data_len; switch (function) { case FUNC_PRE_INIT: ShutterInit(); @@ -1749,9 +1805,13 @@ bool Xdrv27(uint32_t function) //case FUNC_EVERY_250_MSECOND: ShutterReportPosition(false, MAX_SHUTTERS); break; - case FUNC_COMMAND: - result = DecodeCommand(kShutterCommands, ShutterCommand); + for (uint8_t i = counter; i <= counterend; i++) { + XdrvMailbox.index = i; + XdrvMailbox.payload = rescue_payload; + XdrvMailbox.data_len = rescue_data_len; + result = DecodeCommand(kShutterCommands, ShutterCommand); + } break; case FUNC_JSON_APPEND: for (uint8_t i = 0; i < TasmotaGlobal.shutters_present; i++) { diff --git a/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino b/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino index 449b4d40e..de9cfb61f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_38_ping.ino @@ -45,7 +45,7 @@ extern "C" { const uint32_t Ping_coarse = 1000; // interval between sending packets, 1 packet every second typedef struct Ping_t { - uint32 ip; // target IPv4 address + ip_addr_t ip; // target IPv4 address Ping_t *next; // next object in linked list uint16_t seq_num; // next sequence number uint16_t seqno; // reject a packet already received @@ -71,10 +71,11 @@ extern "C" { // // find the ping structure corresponding to the specified IP, or nullptr if not found // - Ping_t ICACHE_FLASH_ATTR * t_ping_find(uint32_t ip) { + Ping_t ICACHE_FLASH_ATTR * t_ping_find(const ip_addr_t *ip) { Ping_t *ping = ping_head; while (ping != nullptr) { - if (ping->ip == ip) { + if (ip_addr_cmp(&ping->ip, ip)) { + // if (ping->ip == ip) { return ping; } ping = ping->next; @@ -129,13 +130,11 @@ extern "C" { p = pbuf_alloc(PBUF_IP, ping_size, PBUF_RAM); if (!p) { return; } if ((p->len == p->tot_len) && (p->next == nullptr)) { - ip_addr_t ping_target; struct icmp_echo_hdr *iecho; - ip_addr_set_ip4_u32(&ping_target, ping->ip); - iecho = (struct icmp_echo_hdr *) p->payload; + iecho = (struct icmp_echo_hdr *) p->payload; t_ping_prepare_echo(iecho, ping_size, ping); - raw_sendto(raw, p, &ping_target); + raw_sendto(raw, p, &ping->ip); } pbuf_free(p); } @@ -166,7 +165,7 @@ extern "C" { // Reveived packet // static uint8_t ICACHE_FLASH_ATTR t_ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr) { - Ping_t *ping = t_ping_find(ip_addr_get_ip4_u32(addr)); + Ping_t *ping = t_ping_find(addr); if (nullptr == ping) { // unknown source address return 0; // don't eat the packet and ignore it @@ -234,14 +233,18 @@ extern "C" { // -2: unable to resolve address int32_t t_ping_start(const char *hostname, uint32_t count) { IPAddress ipfull; - if (!WifiHostByName(hostname, ipfull)) { - ipfull = 0xFFFFFFFF; - } + bool host_resolved = WifiHostByName(hostname, ipfull); - uint32_t ip = ipfull; + ip_addr_t ip; + ip_addr_set_any_val(false, ip); +#ifdef USE_IPV6 + ip = (ip_addr_t)ipfull; +#else + ip_addr_set_ip4_u32_val(ip, (uint32_t)ipfull); +#endif // check if pings are already ongoing for this IP - if (0xFFFFFFFF != ip && t_ping_find(ip)) { + if (host_resolved && t_ping_find(&ip)) { return -1; } @@ -259,7 +262,7 @@ extern "C" { ping->next = ping_head; ping_head = ping; // insert at head - if (0xFFFFFFFF == ip) { // If invalid address, set as completed + if (!host_resolved) { // If invalid address, set as completed ping->done = true; return -2; } @@ -285,9 +288,9 @@ void PingResponsePoll(void) { while (ping != nullptr) { if (ping->done) { uint32_t success = ping->success_count; - uint32_t ip = ping->ip; + bool resolved = !ip_addr_isany_val(ping->ip); - if (0xFFFFFFFF == ip) { + if (!resolved) { Response_P(PSTR("{\"" D_JSON_PING "\":{\"%s\":{" "\"Reachable\":false" ",\"IP\":\"\"" @@ -298,7 +301,7 @@ void PingResponsePoll(void) { } else { Response_P(PSTR("{\"" D_JSON_PING "\":{\"%s\":{" "\"Reachable\":%s" - ",\"IP\":\"%d.%d.%d.%d\"" + ",\"IP\":\"%s\"" ",\"Success\":%d" ",\"Timeout\":%d" ",\"MinTime\":%d" @@ -307,7 +310,12 @@ void PingResponsePoll(void) { "}}}"), ping->hostname.c_str(), success ? PSTR("true") : PSTR("false"), - ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24, +#ifdef USE_IPV6 + IPAddress(ping->ip).toString().c_str(), +#else + IPAddress(ip_addr_get_ip4_u32(&ping->ip)).toString().c_str(), +#endif + // ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24, success, ping->timeout_count, success ? ping->min_time : 0, diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webclient.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webclient.ino index 0971c098b..198103fd3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webclient.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_webclient.ino @@ -194,7 +194,11 @@ extern "C" { timeout = be_toint(vm, 4); } // open connection - bool success = tcp->connect(address, port, timeout); + IPAddress ipaddr; + bool success = WifiHostByName(address, ipaddr); + if (success) { + success = tcp->connect(ipaddr, port, timeout); + } be_pushbool(vm, success); be_return(vm); /* return self */ }