Refactor shutter support

Refactor shutter support (#6516)
This commit is contained in:
Theo Arends 2019-09-30 11:21:43 +02:00
parent f2ed754f11
commit 7689534cf5
3 changed files with 148 additions and 143 deletions

View File

@ -96,7 +96,6 @@ power_t blink_mask = 0; // Blink relay active mask
power_t blink_powersave; // Blink start power save state power_t blink_powersave; // Blink start power save state
power_t latching_power = 0; // Power state at latching start power_t latching_power = 0; // Power state at latching start
power_t rel_inverted = 0; // Relay inverted flag (1 = (0 = On, 1 = Off)) power_t rel_inverted = 0; // Relay inverted flag (1 = (0 = On, 1 = Off))
power_t shutter_mask = 0; // Bit Array to mark all relays that belong to at least one shutter
int baudrate = APP_BAUDRATE; // Serial interface baud rate int baudrate = APP_BAUDRATE; // Serial interface baud rate
int serial_in_byte_counter = 0; // Index in receive buffer int serial_in_byte_counter = 0; // Index in receive buffer
int ota_state_flag = 0; // OTA state flag int ota_state_flag = 0; // OTA state flag
@ -139,7 +138,7 @@ uint8_t seriallog_level; // Current copy of Settings.seriallo
uint8_t syslog_level; // Current copy of Settings.syslog_level uint8_t syslog_level; // Current copy of Settings.syslog_level
uint8_t my_module_type; // Current copy of Settings.module or user template type uint8_t my_module_type; // Current copy of Settings.module or user template type
uint8_t my_adc0; // Active copy of Module ADC0 uint8_t my_adc0; // Active copy of Module ADC0
uint8_t last_source = 0; uint8_t last_source = 0; // Last command source
uint8_t shutters_present = 0; // Number of actual define shutters uint8_t shutters_present = 0; // Number of actual define shutters
//uint8_t mdns_delayed_start = 0; // mDNS delayed start //uint8_t mdns_delayed_start = 0; // mDNS delayed start
bool serial_local = false; // Handle serial locally; bool serial_local = false; // Handle serial locally;

View File

@ -669,7 +669,7 @@ void HueLights(String *path)
#ifdef USE_SHUTTER #ifdef USE_SHUTTER
if (ShutterState(device)) { if (ShutterState(device)) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_invert[device-1]); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_invert[device-1]);
SetShutterPosition(device, bri * 100.0f ); ShutterSetPosition(device, bri * 100.0f );
} else } else
#endif #endif
if (light_type && (local_light_subtype > LST_NONE)) { // not relay if (light_type && (local_light_subtype > LST_NONE)) { // not relay

View File

@ -17,9 +17,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef USE_SHUTTER // +3.8k code #ifdef USE_SHUTTER
/*********************************************************************************************\ /*********************************************************************************************\
* Energy * Shutter or Blind support using two consecutive relays
\*********************************************************************************************/ \*********************************************************************************************/
#define XDRV_27 27 #define XDRV_27 27
@ -39,6 +39,8 @@
#define D_SHUTTER "SHUTTER" #define D_SHUTTER "SHUTTER"
const uint16_t MOTOR_STOP_TIME = 500; // in mS
enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE }; enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE };
const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|" const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|"
@ -51,35 +53,37 @@ void (* const ShutterCommand[])(void) PROGMEM = {
&CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay, &CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay,
&CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration }; &CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration };
const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d}"; const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"direction\":%d}";
#include <Ticker.h>
Ticker TickerShutter; Ticker TickerShutter;
const uint16_t MOTOR_STOP_TIME=500; // in mS struct SHUTTER {
power_t mask = 0; // bit mask with 11 at the position of relays that belong to at least ONE shutter
power_t old_power = 0; // preserve old bitmask for power to extract the relay that changes.
power_t switched_relay = 0; // bitmatrix that contain the relays that was lastly changed.
uint32_t time[MAX_SHUTTERS];
int32_t open_max[MAX_SHUTTERS]; // max value on maximum open calculated
int32_t target_position[MAX_SHUTTERS]; // position to go to
int32_t start_position[MAX_SHUTTERS];
int32_t real_position[MAX_SHUTTERS]; // value between 0 and Shutter.open_max
uint16_t open_time[MAX_SHUTTERS]; // duration to open the shutter
uint16_t close_time[MAX_SHUTTERS]; // duration to close the shutter
uint16_t close_velocity[MAX_SHUTTERS]; // in relation to open velocity. higher value = faster
uint16_t operations[MAX_SHUTTERS];
int8_t direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down
uint8_t mode = 0; // operation mode definition. see enum type above SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE
} Shutter;
uint16_t Shutter_Open_Time[MAX_SHUTTERS] ; // duration to open the shutter void ShutterRtc50mS(void)
uint16_t Shutter_Close_Time[MAX_SHUTTERS]; // duration to close the shutter
int32_t Shutter_Open_Max[MAX_SHUTTERS]; // max value on maximum open calculated
int32_t Shutter_Target_Position[MAX_SHUTTERS] ; // position to go to
int32_t Shutter_Start_Position[MAX_SHUTTERS] ;
uint16_t Shutter_Close_Velocity[MAX_SHUTTERS]; // in relation to open velocity. higher value = faster
uint16_t Shutter_Operations[MAX_SHUTTERS];
int8_t Shutter_Direction[MAX_SHUTTERS]; // 1 == UP , 0 == stop; -1 == down
int32_t Shutter_Real_Position[MAX_SHUTTERS]; // value between 0 and Shutter_Open_Max
//power_t shutter_mask = 0; // bit mask with 11 at the position of relays that belong to at least ONE shutter
power_t old_power = power; // preserve old bitmask for power to extract the relay that changes.
power_t SwitchedRelay = 0; // bitmatrix that contain the relays that was lastly changed.
uint32_t shutter_time[MAX_SHUTTERS] ;
uint8_t shutterMode = 0; // operation mode definition. see enum type above OFF_OPEN-OFF_CLOSE, OFF_ON-OPEN_CLOSE, PULSE_OPEN-PULSE_CLOSE
void Rtc_ms50_Second()
{ {
for (byte i=0;i < MAX_SHUTTERS; i++) { for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
shutter_time[i]++; Shutter.time[i]++;
} }
} }
int32_t percent_to_realposition(uint8_t percent,uint8_t index) int32_t ShutterPercentToRealPosition(uint8_t percent,uint8_t index)
{ {
if (Settings.shutter_set50percent[index] != 50) { if (Settings.shutter_set50percent[index] != 50) {
return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index]; return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index];
@ -88,7 +92,7 @@ int32_t percent_to_realposition(uint8_t percent,uint8_t index)
} }
} }
uint8_t realposition_to_percent(int32_t realpos, uint8_t index) uint8_t ShutterRealToPercentlPosition(int32_t realpos, uint8_t index)
{ {
if (Settings.shutter_set50percent[index] != 50) { if (Settings.shutter_set50percent[index] != 50) {
return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index]; return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index];
@ -97,19 +101,19 @@ uint8_t realposition_to_percent(int32_t realpos, uint8_t index)
} }
} }
void ShutterInit() void ShutterInit(void)
{ {
shutters_present = 0; shutters_present = 0;
shutter_mask = 0; Shutter.mask = 0;
//Initialize to get relay that changed //Initialize to get relay that changed
old_power = power; Shutter.old_power = power;
char shutter_open_chr[10]; char shutter_open_chr[10];
char shutter_close_chr[10]; char shutter_close_chr[10];
bool relay_in_interlock = false; bool relay_in_interlock = false;
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Accuracy digits: %d"), Settings.shutter_accuracy); AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Accuracy digits: %d"), Settings.shutter_accuracy);
for (byte i=0;i < MAX_SHUTTERS; i++) { for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
// upgrade to 0.1sec calculation base. // upgrade to 0.1sec calculation base.
if ( Settings.shutter_accuracy == 0) { if ( Settings.shutter_accuracy == 0) {
Settings.shutter_closetime[i] = Settings.shutter_closetime[i] * 10; Settings.shutter_closetime[i] = Settings.shutter_closetime[i] * 10;
@ -121,49 +125,53 @@ void ShutterInit()
shutters_present++; shutters_present++;
// Determine shutter types // Determine shutter types
shutter_mask |= 3 << (Settings.shutter_startrelay[i] -1) ; Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1) ;
for (uint8_t i = 0; i < MAX_INTERLOCKS * Settings.flag.interlock; i++) { for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) {
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Interlock state i=%d %d, flag %d, , shuttermask %d, maskedIL %d"),i, Settings.interlock[i], Settings.flag.interlock,shutter_mask, Settings.interlock[i]&shutter_mask); //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Interlock state i=%d %d, flag %d, , shuttermask %d, maskedIL %d"),i, Settings.interlock[i], Settings.flag.interlock,Shutter.mask, Settings.interlock[i]&Shutter.mask);
if (Settings.interlock[i] && Settings.interlock[i] & shutter_mask) { if (Settings.interlock[j] && Settings.interlock[j] & Shutter.mask) {
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay in Interlock group")); //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay in Interlock group"));
relay_in_interlock = true; relay_in_interlock = true;
} }
} }
if ( relay_in_interlock) { if (relay_in_interlock) {
if (Settings.pulse_timer[i] > 0) { if (Settings.pulse_timer[i] > 0) {
shutterMode = SHT_PULSE_OPEN__PULSE_CLOSE; Shutter.mode = SHT_PULSE_OPEN__PULSE_CLOSE;
} else { } else {
shutterMode = SHT_OFF_OPEN__OFF_CLOSE; Shutter.mode = SHT_OFF_OPEN__OFF_CLOSE;
} }
} else { } else {
shutterMode = SHT_OFF_ON__OPEN_CLOSE; Shutter.mode = SHT_OFF_ON__OPEN_CLOSE;
} }
TickerShutter.attach_ms(50, Rtc_ms50_Second ); TickerShutter.attach_ms(50, ShutterRtc50mS );
// default the 50 percent should not have any impact without changing it. set to 60 // default the 50 percent should not have any impact without changing it. set to 60
Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] == 0 ? 50 : Settings.shutter_set50percent[i]); Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] == 0 ? 50 : Settings.shutter_set50percent[i]);
// use 10 sec. as default to allow everybody to play without deep initialize // use 10 sec. as default to allow everybody to play without deep initialize
Shutter_Open_Time[i] = Settings.shutter_opentime[i] > 0 ? Settings.shutter_opentime[i] : 100; Shutter.open_time[i] = Settings.shutter_opentime[i] > 0 ? Settings.shutter_opentime[i] : 100;
Shutter_Close_Time[i] = Settings.shutter_closetime[i] > 0 ? Settings.shutter_closetime[i] : 100; Shutter.close_time[i] = Settings.shutter_closetime[i] > 0 ? Settings.shutter_closetime[i] : 100;
// Update Calculation 20 because time interval is 0.05 sec // Update Calculation 20 because time interval is 0.05 sec
Shutter_Open_Max[i] = 200 * Shutter_Open_Time[i]; Shutter.open_max[i] = 200 * Shutter.open_time[i];
Shutter_Close_Velocity[i] = Shutter_Open_Max[i] / Shutter_Close_Time[i] / 2 ; Shutter.close_velocity[i] = Shutter.open_max[i] / Shutter.close_time[i] / 2 ;
// calculate a ramp slope at the first 5 percent to compensate that shutters move with down part later than the upper part // calculate a ramp slope at the first 5 percent to compensate that shutters move with down part later than the upper part
Settings.shuttercoeff[1][i] = Shutter_Open_Max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000; Settings.shuttercoeff[1][i] = Shutter.open_max[i] * (100 - Settings.shutter_set50percent[i] ) / 5000;
Settings.shuttercoeff[0][i] = Shutter_Open_Max[i] - (Settings.shuttercoeff[1][i] * 100); Settings.shuttercoeff[0][i] = Shutter.open_max[i] - (Settings.shuttercoeff[1][i] * 100);
Settings.shuttercoeff[2][i] = (Settings.shuttercoeff[0][i] + 5 * Settings.shuttercoeff[1][i]) / 5; Settings.shuttercoeff[2][i] = (Settings.shuttercoeff[0][i] + 5 * Settings.shuttercoeff[1][i]) / 5;
shutter_mask |= 3 << (Settings.shutter_startrelay[i] -1) ; Shutter.mask |= 3 << (Settings.shutter_startrelay[i] -1) ;
Shutter_Real_Position[i] = percent_to_realposition(Settings.shutter_position[i], i); Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i);
//Shutter_Real_Position[i] = Settings.shutter_position[i] <= 5 ? Settings.shuttercoeff[2][i] * Settings.shutter_position[i] : Settings.shuttercoeff[1][i] * Settings.shutter_position[i] + Settings.shuttercoeff[0,i]; //Shutter.real_position[i] = Settings.shutter_position[i] <= 5 ? Settings.shuttercoeff[2][i] * Settings.shutter_position[i] : Settings.shuttercoeff[1][i] * Settings.shutter_position[i] + Settings.shuttercoeff[0,i];
Shutter_Start_Position[i] = Shutter_Real_Position[i]; Shutter.start_position[i] = Shutter.real_position[i];
dtostrfd((double)Shutter_Open_Time[i] / 10 , 1, shutter_open_chr); dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr);
dtostrfd((double)Shutter_Close_Time[i] / 10, 1, shutter_close_chr); dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr);
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d"),
i, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr,
Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i],
Shutter.mask, Settings.shutter_invert[i], Shutter.mode);
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d"), i, Settings.shutter_startrelay[i],Shutter_Real_Position[i],Settings.shutter_position[i], Shutter_Close_Velocity[i] , Shutter_Open_Max[i], shutter_open_chr, shutter_close_chr,Settings.shuttercoeff[0][i],Settings.shuttercoeff[1][i],Settings.shuttercoeff[2][i],Settings.shuttercoeff[3][i],Settings.shuttercoeff[4][i],shutter_mask,Settings.shutter_invert[i],shutterMode );
} else { } else {
// terminate loop at first INVALID shutter. // terminate loop at first INVALID shutter.
break; break;
@ -172,43 +180,43 @@ void ShutterInit()
} }
} }
void Schutter_Update_Position() void ShutterUpdatePosition(void)
{ {
char scommand[CMDSZ]; char scommand[CMDSZ];
char stopic[TOPSZ]; char stopic[TOPSZ];
for (byte i=0; i < shutters_present; i++) { for (uint32_t i = 0; i < shutters_present; i++) {
if (Shutter_Direction[i] != 0) { if (Shutter.direction[i] != 0) {
//char stemp1[20]; //char stemp1[20];
Shutter_Real_Position[i] = Shutter_Start_Position[i] + ( shutter_time[i] * (Shutter_Direction[i] > 0 ? 100 : -Shutter_Close_Velocity[i])); Shutter.real_position[i] = Shutter.start_position[i] + ( Shutter.time[i] * (Shutter.direction[i] > 0 ? 100 : -Shutter.close_velocity[i]));
// avoid real position leaving the boundaries. // avoid real position leaving the boundaries.
Shutter_Real_Position[i] = Shutter_Real_Position[i] < 0 ? 0 : (Shutter_Real_Position[i] > Shutter_Open_Max[i] ? Shutter_Open_Max[i] : Shutter_Real_Position[i]) ; Shutter.real_position[i] = Shutter.real_position[i] < 0 ? 0 : (Shutter.real_position[i] > Shutter.open_max[i] ? Shutter.open_max[i] : Shutter.real_position[i]) ;
// Add additional runtime, if shutter did not reach the endstop for some time. // Add additional runtime, if shutter did not reach the endstop for some time.
if (Shutter_Target_Position[i] == Shutter_Real_Position[i] && Shutter_Target_Position[i] == 0) { if (Shutter.target_position[i] == Shutter.real_position[i] && Shutter.target_position[i] == 0) {
// for every operation add 5x50ms = 250ms to stop position // for every operation add 5x50ms = 250ms to stop position
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Adding additional runtime")); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Adding additional runtime"));
Shutter_Real_Position[i] += 500 * Shutter_Operations[i] ; Shutter.real_position[i] += 500 * Shutter.operations[i] ;
Shutter_Operations[i] = 0; Shutter.operations[i] = 0;
} }
if (Shutter_Real_Position[i] * Shutter_Direction[i] >= Shutter_Target_Position[i] * Shutter_Direction[i] ) { if (Shutter.real_position[i] * Shutter.direction[i] >= Shutter.target_position[i] * Shutter.direction[i] ) {
// calculate relay number responsible for current movement. // calculate relay number responsible for current movement.
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Condition detected: real: %d, Target: %d, direction: %d"),Shutter_Real_Position[i], Shutter_Target_Position[i],Shutter_Direction[i]); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Condition detected: real: %d, Target: %d, direction: %d"),Shutter.real_position[i], Shutter.target_position[i],Shutter.direction[i]);
uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter_Direction[i] == 1 ? 0 : 1) ; uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter.direction[i] == 1 ? 0 : 1) ;
char stemp2[10]; char stemp2[10];
Settings.shutter_position[i] = realposition_to_percent(Shutter_Real_Position[i], i); Settings.shutter_position[i] = ShutterRealToPercentlPosition(Shutter.real_position[i], i);
//Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter_Real_Position[i] ? (Shutter_Real_Position[i] * 10 / Settings.shuttercoeff[2][i] + 4)/10 : ((Shutter_Real_Position[i]-Settings.shuttercoeff[0,i]) *10 / Settings.shuttercoeff[1][i] +4) / 10; //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? (Shutter.real_position[i] * 10 / Settings.shuttercoeff[2][i] + 4)/10 : ((Shutter.real_position[i]-Settings.shuttercoeff[0,i]) *10 / Settings.shuttercoeff[1][i] +4) / 10;
if (0 < Settings.shutter_position[i] && Settings.shutter_position[i] < 100) { if (0 < Settings.shutter_position[i] && Settings.shutter_position[i] < 100) {
Shutter_Operations[i]++; Shutter.operations[i]++;
} else { } else {
Shutter_Operations[i] = 0; Shutter.operations[i] = 0;
} }
dtostrfd((double)shutter_time[i] / 20, 1, stemp2); dtostrfd((float)Shutter.time[i] / 20, 1, stemp2);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, rtcshutter: %s [s], operationtime %d"), i, Shutter_Real_Position[i], Settings.shutter_position[i], cur_relay -1, Shutter_Direction[i], Settings.pulse_timer[cur_relay -1], stemp2, Shutter_Operations[i]); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Real Pos. %d, Stoppos: %ld, relay: %d, direction %d, pulsetimer: %d, rtcshutter: %s [s], operationtime %d"), i, Shutter.real_position[i], Settings.shutter_position[i], cur_relay -1, Shutter.direction[i], Settings.pulse_timer[cur_relay -1], stemp2, Shutter.operations[i]);
Shutter_Start_Position[i] = Shutter_Real_Position[i]; Shutter.start_position[i] = Shutter.real_position[i];
// sending MQTT result to broker // sending MQTT result to broker
snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1); snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1);
@ -216,7 +224,7 @@ void Schutter_Update_Position()
Response_P("%d", Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]); Response_P("%d", Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]);
MqttPublish(stopic, Settings.flag.mqtt_power_retain); MqttPublish(stopic, Settings.flag.mqtt_power_retain);
switch (shutterMode) { switch (Shutter.mode) {
case SHT_PULSE_OPEN__PULSE_CLOSE: case SHT_PULSE_OPEN__PULSE_CLOSE:
// we have a momentary switch here. Needs additional pulse on same relay after the end // we have a momentary switch here. Needs additional pulse on same relay after the end
if (SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source) { if (SRC_PULSETIMER == last_source || SRC_SHUTTER == last_source || SRC_WEBGUI == last_source) {
@ -239,52 +247,51 @@ void Schutter_Update_Position()
} }
break; break;
} }
Shutter_Direction[i] = 0; Shutter.direction[i] = 0;
byte position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; uint8_t position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i];
Response_P(PSTR("{")); Response_P(PSTR("{"));
ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, 0 /*Shutter_Direction[i]*/); ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, 0 /*Shutter.direction[i]*/);
ResponseJsonEnd(); ResponseJsonEnd();
MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data);
XdrvRulesProcess(); XdrvRulesProcess();
} }
} }
} }
} }
bool ShutterState(uint8_t device) bool ShutterState(uint8_t device)
{ {
device--; device--;
device &= 3; device &= 3;
return (Settings.flag3.shutter_mode && (shutter_mask & (1 << (Settings.shutter_startrelay[device]-1))) ); return (Settings.flag3.shutter_mode && (Shutter.mask & (1 << (Settings.shutter_startrelay[device]-1))) );
} }
void Shutter_StartInit (uint8_t index, uint8_t direction, int32_t target_pos) void ShutterStartInit(uint8_t index, uint8_t direction, int32_t target_pos)
{ {
Shutter_Direction[index] = direction; Shutter.direction[index] = direction;
Shutter_Target_Position[index] = target_pos; Shutter.target_position[index] = target_pos;
Shutter_Start_Position[index] = Shutter_Real_Position[index]; Shutter.start_position[index] = Shutter.real_position[index];
shutter_time[index] = 0; Shutter.time[index] = 0;
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter_Start_Position[index], Shutter_Target_Position[index], Shutter_Direction[index]); //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter: %d from %d to %d in directin %d"), index, Shutter.start_position[index], Shutter.target_position[index], Shutter.direction[index]);
} }
void DelayForMotorStop() void ShutterDelayForMotorStop(void)
{ {
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop %d"), MOTOR_STOP_TIME); AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop %d"), MOTOR_STOP_TIME);
delay(MOTOR_STOP_TIME); delay(MOTOR_STOP_TIME);
} }
void Schutter_Report_Position() void ShutterReportPosition(void)
{ {
uint16_t shutter_moving = 0; uint16_t shutter_moving = 0;
for (byte i=0; i < shutters_present; i++) { for (uint32_t i = 0; i < shutters_present; i++) {
if (Shutter_Direction[i] != 0) { if (Shutter.direction[i] != 0) {
char stemp1[20]; char stemp1[20];
char stemp2[10]; char stemp2[10];
dtostrfd((double)shutter_time[i] / 20, 1, stemp2); dtostrfd((float)Shutter.time[i] / 20, 1, stemp2);
shutter_moving = 1; shutter_moving = 1;
//Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter_Real_Position[i] ? Shutter_Real_Position[i] / Settings.shuttercoeff[2][i] : (Shutter_Real_Position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i]; //Settings.shutter_position[i] = Settings.shuttercoeff[2][i] * 5 > Shutter.real_position[i] ? Shutter.real_position[i] / Settings.shuttercoeff[2][i] : (Shutter.real_position[i]-Settings.shuttercoeff[0,i]) / Settings.shuttercoeff[1][i];
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d, Target %d, source: %s, start-pos: %d %%, direction: %d, rtcshutter: %s [s]"), i,Shutter_Real_Position[i], Shutter_Target_Position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), Settings.shutter_position[i], Shutter_Direction[i], stemp2 ); AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d: Real Pos: %d, Target %d, source: %s, start-pos: %d %%, direction: %d, rtcshutter: %s [s]"), i,Shutter.real_position[i], Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), Settings.shutter_position[i], Shutter.direction[i], stemp2 );
} }
} }
if (rules_flag.shutter_moving > shutter_moving) { if (rules_flag.shutter_moving > shutter_moving) {
@ -296,51 +303,50 @@ void Schutter_Report_Position()
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved); //AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: rules_flag.shutter_moving: %d, moved %d"), rules_flag.shutter_moving, rules_flag.shutter_moved);
} }
void Shutter_Relay_changed() void ShutterRelayChanged(void)
{ {
// SwitchedRelay = binary relay that was recently changed and cause an Action // Shutter.switched_relay = binary relay that was recently changed and cause an Action
// powerstate_local = binary powermatrix and relays from shutter: 0..3 // powerstate_local = binary powermatrix and relays from shutter: 0..3
// relays_changed = bool if one of the relays that belong to the shutter changed not by shutter or pulsetimer // relays_changed = bool if one of the relays that belong to the shutter changed not by shutter or pulsetimer
char stemp1[10]; char stemp1[10];
for (uint32_t i = 0; i < shutters_present; i++) {
for (byte i=0; i < shutters_present; i++) {
power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3; power_t powerstate_local = (power >> (Settings.shutter_startrelay[i] -1)) & 3;
//uint8 manual_relays_changed = ((SwitchedRelay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != last_source && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; //uint8 manual_relays_changed = ((Shutter.switched_relay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != last_source && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ;
uint8 manual_relays_changed = ((SwitchedRelay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ; uint8 manual_relays_changed = ((Shutter.switched_relay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ;
if (manual_relays_changed) { if (manual_relays_changed) {
if (shutterMode == SHT_OFF_ON__OPEN_CLOSE) { if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) {
switch (powerstate_local) { switch (powerstate_local) {
case 1: case 1:
DelayForMotorStop(); ShutterDelayForMotorStop();
Shutter_StartInit(i, 1, Shutter_Open_Max[i]); ShutterStartInit(i, 1, Shutter.open_max[i]);
break; break;
case 3: case 3:
DelayForMotorStop(); ShutterDelayForMotorStop();
Shutter_StartInit(i, -1, 0); ShutterStartInit(i, -1, 0);
break; break;
default: default:
Shutter_Direction[i] = 0; Shutter.direction[i] = 0;
Shutter_Target_Position[i] = Shutter_Real_Position[i]; Shutter.target_position[i] = Shutter.real_position[i];
} }
} else { } else {
if (Shutter_Direction[i] != 0 && (!powerstate_local || (powerstate_local && shutterMode == SHT_PULSE_OPEN__PULSE_CLOSE))) { if (Shutter.direction[i] != 0 && (!powerstate_local || (powerstate_local && Shutter.mode == SHT_PULSE_OPEN__PULSE_CLOSE))) {
Shutter_Target_Position[i] = Shutter_Real_Position[i]; Shutter.target_position[i] = Shutter.real_position[i];
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, switchedRelay %d, manual change %d"), i, Shutter_Target_Position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,SwitchedRelay,manual_relays_changed); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Switch OFF motor. Target: %ld, source: %s, powerstate_local %ld, Shutter.switched_relay %d, manual change %d"), i, Shutter.target_position[i], GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource), powerstate_local,Shutter.switched_relay,manual_relays_changed);
} else { } else {
last_source = SRC_SHUTTER; // avoid switch off in the next loop last_source = SRC_SHUTTER; // avoid switch off in the next loop
if (powerstate_local == 2) { // testing on CLOSE relay, if ON if (powerstate_local == 2) { // testing on CLOSE relay, if ON
// close with relay two // close with relay two
DelayForMotorStop(); ShutterDelayForMotorStop();
Shutter_StartInit(i, -1, 0); ShutterStartInit(i, -1, 0);
} else { } else {
// opens with relay one // opens with relay one
DelayForMotorStop(); ShutterDelayForMotorStop();
Shutter_StartInit(i, 1, Shutter_Open_Max[i]); ShutterStartInit(i, 1, Shutter.open_max[i]);
} }
} }
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i, Shutter_Target_Position[i], powerstate_local); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Shutter %d: Target: %ld, powerstatelocal %d"), i, Shutter.target_position[i], powerstate_local);
} }
} }
} }
@ -352,7 +358,7 @@ void Shutter_Relay_changed()
// device: 1..<numberOfShutters> // device: 1..<numberOfShutters>
// position: 0-100 // position: 0-100
void SetShutterPosition(uint8_t device, uint8_t position) void ShutterSetPosition(uint8_t device, uint8_t position)
{ {
char svalue[32]; // Command and number parameter char svalue[32]; // Command and number parameter
snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION "%d %d"), device, position); snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION "%d %d"), device, position);
@ -381,12 +387,12 @@ void CmndShutterStop(void)
{ {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
uint32_t index = XdrvMailbox.index -1; uint32_t index = XdrvMailbox.index -1;
if (Shutter_Direction[index] != 0) { if (Shutter.direction[index] != 0) {
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving shutter %d: direction:%d"), XdrvMailbox.index, Shutter_Direction[index]); //AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Stop moving shutter %d: direction: %d"), XdrvMailbox.index, Shutter.direction[index]);
int32_t temp_realpos = Shutter_Start_Position[index] + ( (shutter_time[index]+10) * (Shutter_Direction[index] > 0 ? 100 : -Shutter_Close_Velocity[index])); int32_t temp_realpos = Shutter.start_position[index] + ( (Shutter.time[index]+10) * (Shutter.direction[index] > 0 ? 100 : -Shutter.close_velocity[index]));
XdrvMailbox.payload = realposition_to_percent(temp_realpos, index); XdrvMailbox.payload = ShutterRealToPercentlPosition(temp_realpos, index);
//XdrvMailbox.payload = Settings.shuttercoeff[2][index] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][index] : (temp_realpos-Settings.shuttercoeff[0,index]) / Settings.shuttercoeff[1][index]; //XdrvMailbox.payload = Settings.shuttercoeff[2][index] * 5 > temp_realpos ? temp_realpos / Settings.shuttercoeff[2][index] : (temp_realpos-Settings.shuttercoeff[0,index]) / Settings.shuttercoeff[1][index];
last_source = SRC_WEBGUI; last_source = SRC_WEBGUI;
CmndShutterPosition(); CmndShutterPosition();
@ -408,44 +414,44 @@ void CmndShutterPosition(void)
target_pos_percent = Settings.shutter_invert[index] && SRC_WEBGUI != last_source ? 100 - target_pos_percent : target_pos_percent; target_pos_percent = Settings.shutter_invert[index] && SRC_WEBGUI != last_source ? 100 - target_pos_percent : target_pos_percent;
if (target_pos_percent != -99) { if (target_pos_percent != -99) {
//target_pos_percent = Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent; //target_pos_percent = Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent;
Shutter_Target_Position[index] = percent_to_realposition(target_pos_percent, index); Shutter.target_position[index] = ShutterPercentToRealPosition(target_pos_percent, index);
//Shutter_Target_Position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index]; //Shutter.target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index];
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, realpos %d, target %d, payload %d"), last_source, Shutter_Real_Position[index] ,Shutter_Target_Position[index],target_pos_percent); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: lastsource %d:, realpos %d, target %d, payload %d"), last_source, Shutter.real_position[index] ,Shutter.target_position[index],target_pos_percent);
} }
if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter_Target_Position[index] - Shutter_Real_Position[index] ) / Shutter_Close_Velocity[index] > 2) { if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter.target_position[index] - Shutter.real_position[index] ) / Shutter.close_velocity[index] > 2) {
int8_t new_shutterdirection = Shutter_Real_Position[index] < Shutter_Target_Position[index] ? 1 : -1; int8_t new_shutterdirection = Shutter.real_position[index] < Shutter.target_position[index] ? 1 : -1;
if (Shutter_Direction[index] == -new_shutterdirection ) { if (Shutter.direction[index] == -new_shutterdirection ) {
// direction need to be changed. on momentary switches first stop the Shutter // direction need to be changed. on momentary switches first stop the Shutter
if (shutterMode == SHT_PULSE_OPEN__PULSE_CLOSE) { if (Shutter.mode == SHT_PULSE_OPEN__PULSE_CLOSE) {
// code for momentary shutters only small switch on to stop Shutter // code for momentary shutters only small switch on to stop Shutter
ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER);
delay(100); delay(100);
} else { } else {
ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), 0, SRC_SHUTTER); ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), 0, SRC_SHUTTER);
DelayForMotorStop(); ShutterDelayForMotorStop();
} }
} }
if (Shutter_Direction[index] != new_shutterdirection ) { if (Shutter.direction[index] != new_shutterdirection ) {
Shutter_StartInit(index, new_shutterdirection, Shutter_Target_Position[index]); ShutterStartInit(index, new_shutterdirection, Shutter.target_position[index]);
Shutter_Operations[index]++; Shutter.operations[index]++;
if (shutterMode == SHT_OFF_ON__OPEN_CLOSE) { if (Shutter.mode == SHT_OFF_ON__OPEN_CLOSE) {
ExecuteCommandPower(Settings.shutter_startrelay[index] , 0, SRC_SHUTTER); ExecuteCommandPower(Settings.shutter_startrelay[index] , 0, SRC_SHUTTER);
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload);
DelayForMotorStop(); ShutterDelayForMotorStop();
// Code for shutters with circuit safe configuration, switch the direction Relay // Code for shutters with circuit safe configuration, switch the direction Relay
ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER); ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER);
// power on // power on
ExecuteCommandPower(Settings.shutter_startrelay[index] , 1, SRC_SHUTTER); ExecuteCommandPower(Settings.shutter_startrelay[index] , 1, SRC_SHUTTER);
} else { } else {
// now start the motor for the right direction, work for momentary and normal shutters. // now start the motor for the right direction, work for momentary and normal shutters.
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter in direction %d"), Shutter_Direction[index]); AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Start shutter in direction %d"), Shutter.direction[index]);
ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER); ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER);
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay6 5s, xdrv %d"), XdrvMailbox.payload); //AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay6 5s, xdrv %d"), XdrvMailbox.payload);
} }
SwitchedRelay = 0; Shutter.switched_relay = 0;
} }
} else { } else {
target_pos_percent = realposition_to_percent(Shutter_Real_Position[index], index); target_pos_percent = ShutterRealToPercentlPosition(Shutter.real_position[index], index);
} }
ResponseCmndIdxNumber(Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent); ResponseCmndIdxNumber(Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent);
} }
@ -483,9 +489,9 @@ void CmndShutterRelay(void)
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) {
Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload; Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload;
if (XdrvMailbox.payload > 0) { if (XdrvMailbox.payload > 0) {
shutter_mask |= 3 << (XdrvMailbox.payload - 1); Shutter.mask |= 3 << (XdrvMailbox.payload - 1);
} else { } else {
shutter_mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index-1] - 1); Shutter.mask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index-1] - 1);
} }
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay %d is %d"), XdrvMailbox.index, XdrvMailbox.payload); AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay %d is %d"), XdrvMailbox.index, XdrvMailbox.payload);
Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload; Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload;
@ -512,8 +518,8 @@ void CmndShutterSetHalfway(void)
void CmndShutterSetClose(void) void CmndShutterSetClose(void)
{ {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
Shutter_Real_Position[XdrvMailbox.index-1] = 0; Shutter.real_position[XdrvMailbox.index-1] = 0;
Shutter_StartInit(XdrvMailbox.index-1, 0, 0); ShutterStartInit(XdrvMailbox.index-1, 0, 0);
Settings.shutter_position[XdrvMailbox.index-1] = 0; Settings.shutter_position[XdrvMailbox.index-1] = 0;
ResponseCmndChar(D_CONFIGURATION_RESET); ResponseCmndChar(D_CONFIGURATION_RESET);
} }
@ -552,10 +558,10 @@ bool Xdrv27(uint8_t function)
ShutterInit(); ShutterInit();
break; break;
case FUNC_EVERY_50_MSECOND: case FUNC_EVERY_50_MSECOND:
Schutter_Update_Position(); ShutterUpdatePosition();
break; break;
case FUNC_EVERY_SECOND: case FUNC_EVERY_SECOND:
Schutter_Report_Position(); ShutterReportPosition();
break; break;
case FUNC_COMMAND: case FUNC_COMMAND:
result = DecodeCommand(kShutterCommands, ShutterCommand); result = DecodeCommand(kShutterCommands, ShutterCommand);
@ -564,7 +570,7 @@ bool Xdrv27(uint8_t function)
for (uint32_t i = 0; i < shutters_present; i++) { for (uint32_t i = 0; i < shutters_present; i++) {
uint8_t position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]; uint8_t position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i];
ResponseAppend_P(","); ResponseAppend_P(",");
ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter_Direction[i]); ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter.direction[i]);
#ifdef USE_DOMOTICZ #ifdef USE_DOMOTICZ
if ((0 == tele_period) && (0 == i)) { if ((0 == tele_period) && (0 == i)) {
DomoticzSensor(DZ_SHUTTER, position); DomoticzSensor(DZ_SHUTTER, position);
@ -575,10 +581,10 @@ bool Xdrv27(uint8_t function)
case FUNC_SET_POWER: case FUNC_SET_POWER:
char stemp1[10]; char stemp1[10];
// extract the number of the relay that was switched and save for later in Update Position. // extract the number of the relay that was switched and save for later in Update Position.
SwitchedRelay = power ^ old_power; Shutter.switched_relay = power ^ Shutter.old_power;
old_power = power; Shutter.old_power = power;
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), SwitchedRelay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource)); AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), Shutter.switched_relay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource));
Shutter_Relay_changed(); ShutterRelayChanged();
break; break;
} }
} }