diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino
index d23eafc96..8958e121c 100644
--- a/tasmota/tasmota.ino
+++ b/tasmota/tasmota.ino
@@ -578,6 +578,7 @@ void setup(void) {
}
if (RtcReboot.fast_reboot_count > Settings->param[P_BOOT_LOOP_OFFSET] +2) { // Restarted 4 times
Settings->rule_enabled = 0; // Disable all rules
+ Settings->flag3.shutter_mode = 0; // disable shutter support
TasmotaGlobal.no_autoexec = true;
}
if (RtcReboot.fast_reboot_count > Settings->param[P_BOOT_LOOP_OFFSET] +3) { // Restarted 5 times
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino
index 84f5368fb..2ab1afa99 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino
@@ -264,9 +264,6 @@ const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM =
"
"
""
"
";
-const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM =
- "" D_CLOSE "" D_OPEN "
"
- "";
const char HTTP_MSG_RSTRT[] PROGMEM =
"
" D_DEVICE_WILL_RESTART "
";
@@ -1229,13 +1226,6 @@ void HandleRoot(void)
} // Settings->flag3.pwm_multi_channels
}
#endif // USE_LIGHT
-#ifdef USE_SHUTTER
- if (Settings->flag3.shutter_mode) { // SetOption80 - Enable shutter support
- for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
- WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, ShutterRealToPercentPosition(-9999, i), i+1);
- }
- }
-#endif // USE_SHUTTER
WSContentSend_P(HTTP_TABLE100);
WSContentSend_P(PSTR(""));
#ifdef USE_SONOFF_IFAN
@@ -1258,7 +1248,7 @@ void HandleRoot(void)
int32_t ShutterWebButton;
if (ShutterWebButton = IsShutterWebButton(idx)) {
WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / cols, idx,
- (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings->shutter_options[abs(ShutterWebButton)-1] & 2) /* is locked */ ? "-" : ((Settings->shutter_options[abs(ShutterWebButton)-1] & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "▼" : "▲") : ((ShutterWebButton>0) ? "▲" : "▼"))),
+ (set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((ShutterGetOptions(abs(ShutterWebButton)-1) & 2) /* is locked */ ? "-" : ((Settings->shutter_options[abs(ShutterWebButton)-1] & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "▼" : "▲") : ((ShutterWebButton>0) ? "▲" : "▼"))),
"");
} else {
#endif // USE_SHUTTER
@@ -1410,10 +1400,12 @@ bool HandleRootStatusRefresh(void)
#endif // USE_LIGHT
#ifdef USE_SHUTTER
for (uint32_t j = 1; j <= TasmotaGlobal.shutters_present; j++) {
+ uint8_t percent;
snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j);
WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent
+ percent = atoi(tmp);
if (strlen(tmp)) {
- snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), j, tmp);
+ snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %d"), j, (ShutterGetOptions(j-1) & 1) ? 100 - percent : percent);
ExecuteWebCommand(svalue);
}
}
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino b/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino
index ae31ab6cb..6fb523dc0 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_12_discovery.ino
@@ -200,9 +200,9 @@ void TasDiscoverMessage(void) {
light_controller_isCTRGBLinked,
light_subtype);
- for (uint32_t i = 0; i < tmin(TasmotaGlobal.shutters_present, MAX_SHUTTERS); i++) {
+ for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
#ifdef USE_SHUTTER
- ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), Settings->shutter_options[i]);
+ ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), ShutterGetOptions(i));
#else
ResponseAppend_P(PSTR("%s0"), (i > 0 ? "," : ""));
#endif // USE_SHUTTER
@@ -210,7 +210,7 @@ void TasDiscoverMessage(void) {
ResponseAppend_P(PSTR("]," // Shutter Options (end)
"\"sht\":[")); // Shutter Tilt (start)
- for (uint32_t i = 0; i < tmax(TasmotaGlobal.shutters_present, MAX_SHUTTERS); i++) {
+ for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
#ifdef USE_SHUTTER
ResponseAppend_P(PSTR("%s[%d,%d,%d]"), (i > 0 ? "," : ""),
ShutterGetTiltConfig(0,i),
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino
index eb5569e4f..a4739135e 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_27_esp32_shutter.ino
@@ -54,7 +54,10 @@
#define D_ERROR_FILESYSTEM_NOT_READY "SHT: ERROR File system not enabled"
#define D_ERROR_FILE_NOT_FOUND "SHT: ERROR File system not ready or file not found"
-//
+const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM =
+ "%s%s
"
+ "";
+
const uint32_t SHUTTER_VERSION = 0x01010100; // Latest driver version (See settings deltas below)
typedef struct { // depreciated 2023-04-28
@@ -364,7 +367,7 @@ bool ShutterStatus(void) {
"\"Mode\":\"%d\","
"\"TiltConfig\":[%d,%d,%d,%d,%d]}"),
i, ShutterSettings.shutter_startrelay[i], ShutterSettings.shutter_startrelay[i] +1, ShutterSettings.shutter_opentime[i], ShutterSettings.shutter_closetime[i],
- ShutterSettings.shutter_set50percent[i], ShutterSettings.shutter_motordelay[i], GetBinary8(Settings->shutter_options[i], 4).c_str(),
+ ShutterSettings.shutter_set50percent[i], ShutterSettings.shutter_motordelay[i], GetBinary8(ShutterSettings.shutter_options[i], 4).c_str(),
ShutterSettings.shuttercoeff[0][i], ShutterSettings.shuttercoeff[1][i], ShutterSettings.shuttercoeff[2][i], ShutterSettings.shuttercoeff[3][i], ShutterSettings.shuttercoeff[4][i],
ShutterSettings.shutter_mode,
ShutterSettings.shutter_tilt_config[0][i], ShutterSettings.shutter_tilt_config[1][i], ShutterSettings.shutter_tilt_config[2][i], ShutterSettings.shutter_tilt_config[3][i], ShutterSettings.shutter_tilt_config[4][i]
@@ -389,6 +392,10 @@ uint8_t ShutterGetStartRelay(uint8_t index) {
return ShutterSettings.shutter_startrelay[index];
}
+uint8_t ShutterGetOptions(uint8_t index) {
+ return ShutterSettings.shutter_options[index];
+}
+
int8_t ShutterGetTiltConfig(uint8_t config_idx,uint8_t index) {
return Shutter[index].tilt_config[config_idx];
}
@@ -497,13 +504,13 @@ int32_t ShutterPercentToRealPosition(int16_t percent, uint32_t index)
uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
{
+ int64_t realpercent;
if (realpos == -9999) {
realpos = Shutter[index].real_position;
}
if (ShutterSettings.shutter_set50percent[index] != 50) {
- return (ShutterSettings.shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, ShutterSettings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-ShutterSettings.shuttercoeff[0][index]*10, ShutterSettings.shuttercoeff[1][index]);
+ realpercent = (ShutterSettings.shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, ShutterSettings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-ShutterSettings.shuttercoeff[0][index]*10, ShutterSettings.shuttercoeff[1][index]);
} else {
- int64_t realpercent;
for (uint32_t j = 0; j < 5; j++) {
if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) {
realpercent = SHT_DIV_ROUND(ShutterSettings.shuttercoeff[j][index], 10);
@@ -521,10 +528,10 @@ uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
break;
}
}
- realpercent = realpercent < 0 ? 0 : realpercent;
- // if inverted recalculate the percentposition
- return (ShutterSettings.shutter_options[index] & 1) ? 100 - realpercent : realpercent;
}
+ realpercent = realpercent < 0 ? 0 : realpercent;
+ // if inverted recalculate the percentposition
+ return (ShutterSettings.shutter_options[index] & 1) ? 100 - realpercent : realpercent;
}
void ShutterInit(void)
@@ -1127,8 +1134,8 @@ void ShutterRelayChanged(void)
// powerstate_local == 1 => direction=1, target=Shutter[i].open_max
// powerstate_local == 2 => direction=-1, target=0 // only happen on SHT_TIME
// powerstate_local == 3 => direction=-1, target=0 // only happen if NOT SHT_TIME
- int direction = (powerstate_local == 0) ? 0 : (powerstate_local == 1) ? 1 : -1;
- int target = (powerstate_local == 1) ? Shutter[i].open_max : 0;
+ int8_t direction = (powerstate_local == 0) ? 0 : (powerstate_local == 1) ? 1 : -1;
+ int8_t target = (powerstate_local == 1) ? Shutter[i].open_max : 0;
if (direction != 0) {
ShutterStartInit(i, direction, target);
@@ -1318,6 +1325,11 @@ void ShutterToggle(bool dir)
}
}
+void ShutterShow(){
+ for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
+ WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, (ShutterSettings.shutter_options[i] & 1) ? D_OPEN : D_CLOSE,(ShutterSettings.shutter_options[i] & 1) ? D_CLOSE : D_OPEN, ShutterRealToPercentPosition(-9999, i), i+1);
+ }
+}
/*********************************************************************************************\
* Commands
\*********************************************************************************************/
@@ -2328,6 +2340,11 @@ bool Xdrv27(uint32_t function)
result = false;
}
break;
+#ifdef USE_WEBSERVER
+ case FUNC_WEB_SENSOR:
+ ShutterShow();
+ break;
+#endif // USE_WEBSERVER
}
}
return result;
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino
index 7229a8942..c9dbb9545 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_27_shutter.ino
@@ -72,6 +72,10 @@ int32_t next_possible_stop_position = 0;
int32_t current_real_position = 0;
int32_t current_pwm_velocity = 0;
+const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM =
+ "%s%s
"
+ "";
+
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,};
@@ -189,6 +193,10 @@ uint8_t ShutterGetStartRelay(uint8_t index) {
return Settings->shutter_startrelay[index];
}
+uint8_t ShutterGetOptions(uint8_t index) {
+ return Settings->shutter_options[index];
+}
+
int8_t ShutterGetTiltConfig(uint8_t config_idx,uint8_t index) {
return Shutter[index].tilt_config[config_idx];
}
@@ -259,6 +267,8 @@ void ShutterRtc50mS(void)
int32_t ShutterPercentToRealPosition(int16_t percent, uint32_t index)
{
+ // if inverted recalculate the percentposition
+ percent = (Settings->shutter_options[index] & 1) ? 100 - percent : percent;
if (Settings->shutter_set50percent[index] != 50) {
return (percent <= 5) ? Settings->shuttercoeff[2][index] * percent*10 : (Settings->shuttercoeff[1][index] * percent + (Settings->shuttercoeff[0][index]*10))*10;
} else {
@@ -295,13 +305,13 @@ int32_t ShutterPercentToRealPosition(int16_t percent, uint32_t index)
uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
{
+ int64_t realpercent;
if (realpos == -9999) {
realpos = Shutter[index].real_position;
}
if (Settings->shutter_set50percent[index] != 50) {
- return (Settings->shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, Settings->shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-Settings->shuttercoeff[0][index]*10, Settings->shuttercoeff[1][index]);
+ realpercent = (Settings->shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, Settings->shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-Settings->shuttercoeff[0][index]*10, Settings->shuttercoeff[1][index]);
} else {
- int64_t realpercent;
for (uint32_t j = 0; j < 5; j++) {
if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) {
realpercent = SHT_DIV_ROUND(Settings->shuttercoeff[j][index], 10);
@@ -319,8 +329,10 @@ uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
break;
}
}
- return realpercent < 0 ? 0 : realpercent;
}
+ realpercent = realpercent < 0 ? 0 : realpercent;
+ // if inverted recalculate the percentposition
+ return (Settings->shutter_options[index] & 1) ? 100 - realpercent : realpercent;
}
void ShutterInit(void)
@@ -876,52 +888,38 @@ void ShutterRelayChanged(void)
Shutter[i].tiltmoving = 0;
}
switch (ShutterGlobal.position_mode) {
- // enum Shutterposition_mode {SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,};
- case SHT_TIME_UP_DOWN:
- case SHT_COUNTER:
- case SHT_PWM_VALUE:
- case SHT_PWM_TIME:
- //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: power off manual change"));
- ShutterPowerOff(i);
- switch (powerstate_local) {
- case 1:
- ShutterStartInit(i, 1, Shutter[i].open_max);
- break;
- case 3:
- ShutterStartInit(i, -1, 0);
- break;
- default:
- //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Switch OFF motor."),i);
+ // enum Shutterposition_mode {SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,};
+ case SHT_TIME_UP_DOWN:
+ case SHT_COUNTER:
+ case SHT_PWM_VALUE:
+ case SHT_PWM_TIME:
+ case SHT_TIME: {
+ ShutterPowerOff(i);
+ // powerstate_local == 0 => direction=0, stop
+ // powerstate_local == 1 => direction=1, target=Shutter[i].open_max
+ // powerstate_local == 2 => direction=-1, target=0 // only happen on SHT_TIME
+ // powerstate_local == 3 => direction=-1, target=0 // only happen if NOT SHT_TIME
+ int8_t direction = (powerstate_local == 0) ? 0 : (powerstate_local == 1) ? 1 : -1;
+ int8_t target = (powerstate_local == 1) ? Shutter[i].open_max : 0;
+
+ if (direction != 0) {
+ ShutterStartInit(i, direction, target);
+ } else {
Shutter[i].target_position = Shutter[i].real_position;
Shutter[i].last_stop_time = millis();
}
- break;
- case SHT_TIME:
- switch (powerstate_local) {
- case 1:
- ShutterStartInit(i, 1, Shutter[i].open_max);
- break;
- case 2:
- ShutterStartInit(i, -1, 0);
- break;
- default:
- //AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Switch OFF motor."),i+1);
- Shutter[i].target_position = Shutter[i].real_position;
- Shutter[i].last_stop_time = millis();
+ break;
}
- break;
- case SHT_TIME_GARAGE:
- switch (powerstate_local) {
- case 1:
- ShutterStartInit(i, Shutter[i].lastdirection*-1 , Shutter[i].lastdirection == 1 ? 0 : Shutter[i].open_max);
- AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Garage. NewTarget %d"), i, Shutter[i].target_position);
- break;
- default:
- Shutter[i].target_position = Shutter[i].real_position;
- }
-
-
- } // switch (ShutterGlobal.position_mode)
+ case SHT_TIME_GARAGE:
+ switch (powerstate_local) {
+ case 1:
+ ShutterStartInit(i, Shutter[i].lastdirection * -1, Shutter[i].lastdirection == 1 ? 0 : Shutter[i].open_max);
+ AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Garage. NewTarget %d"), i, Shutter[i].target_position);
+ break;
+ default:
+ Shutter[i].target_position = Shutter[i].real_position;
+ }
+ }
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Target %ld, Power: %d, tiltmv: %d"), i+1, Shutter[i].target_position, powerstate_local,Shutter[i].tiltmoving);
} // if (manual_relays_changed)
} // for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++)
@@ -940,11 +938,11 @@ bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_ind
bool ShutterButtonHandler(void)
{
- uint8_t buttonState = SHT_NOT_PRESSED;
- uint8_t button = XdrvMailbox.payload;
- uint8_t press_index;
+ uint8_t buttonState = SHT_NOT_PRESSED;
+ uint8_t button = XdrvMailbox.payload;
+ uint8_t press_index;
uint32_t button_index = XdrvMailbox.index;
- uint8_t shutter_index = Settings->shutter_button[button_index] & 0x03;
+ uint8_t shutter_index = Settings->shutter_button[button_index] & 0x03;
uint16_t loops_per_second = 1000 / Settings->button_debounce; // ButtonDebounce (50)
if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
@@ -976,8 +974,8 @@ bool ShutterButtonHandler(void)
Button.hold_timer[button_index] = 0;
} else {
Button.hold_timer[button_index]++;
- if (!Settings->flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
- if (Settings->param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
+ if (!Settings->flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
+ if (Settings->param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
if (Button.hold_timer[button_index] > loops_per_second * Settings->param[P_HOLD_IGNORE] / 10) {
Button.hold_timer[button_index] = 0; // Reset button hold counter to stay below hold trigger
Button.press_counter[button_index] = 0; // Discard button press to disable functionality
@@ -1159,6 +1157,12 @@ void ShutterToggle(bool dir)
}
}
+void ShutterShow(){
+ for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
+ WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, (Settings->shutter_options[i] & 1) ? D_OPEN : D_CLOSE,(Settings->shutter_options[i] & 1) ? D_CLOSE : D_OPEN, ShutterRealToPercentPosition(-9999, i), i+1);
+ }
+}
+
/*********************************************************************************************\
* Commands
\*********************************************************************************************/
@@ -1980,6 +1984,11 @@ bool Xdrv27(uint32_t function)
result = true;
}
break;
+#ifdef USE_WEBSERVER
+ case FUNC_WEB_SENSOR:
+ ShutterShow();
+ break;
+#endif // USE_WEBSERVER
}
}
return result;