Merge branch 'development' into pre-release-12.3

This commit is contained in:
Theo Arends 2022-12-14 11:31:41 +01:00
commit 23cbdb93b0
14 changed files with 159 additions and 65 deletions

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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/

View File

@ -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"

View File

@ -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 *******************************************************************
/*********************************************************************************************\

View File

@ -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

View File

@ -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);
}

View File

@ -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++) {

View File

@ -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,

View File

@ -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 */
}