mirror of https://github.com/arendst/Tasmota.git
Add initial support for shutters
Add initial support for shutters by Stefan Bode (#288)
This commit is contained in:
parent
728d162be8
commit
e40475b563
|
@ -4,6 +4,7 @@
|
|||
* Remove support for define USE_DS18x20_LEGACY and legacy DS18x20 driver (#6486)
|
||||
* Add initial support for MQTT logging using command MqttLog <loglevel> (#6498)
|
||||
* Add Zigbee more support - collect endpoints and clusters, added ZigbeeDump command
|
||||
* Add initial support for shutters by Stefan Bode (#288)
|
||||
*
|
||||
* 6.6.0.13 20190922
|
||||
* Add command EnergyReset4 x,x to initialize total usage for two tarrifs
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Използвана енергия вчера"
|
||||
#define D_ENERGY_TOTAL "Използвана енергия общо"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Датчикът DS18x20 е зает"
|
||||
#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - грешка CRC"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Spotřeba Včera"
|
||||
#define D_ENERGY_TOTAL "Celková spotřeba"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensor DS18x20 obsazen"
|
||||
#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Energie gestern"
|
||||
#define D_ENERGY_TOTAL "Energie insgesamt"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensor beschäftigt"
|
||||
#define D_SENSOR_CRC_ERROR "Sensor CRC-Fehler"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Ενέργεια χθες"
|
||||
#define D_ENERGY_TOTAL "Ενέργεια συνολικά"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Ο αισθητήρας είναι απασχολημένος"
|
||||
#define D_SENSOR_CRC_ERROR "Σφάλμα CRC αισθητήρα"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Energy Yesterday"
|
||||
#define D_ENERGY_TOTAL "Energy Total"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensor busy"
|
||||
#define D_SENSOR_CRC_ERROR "Sensor CRC error"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Energía Ayer"
|
||||
#define D_ENERGY_TOTAL "Energía Total"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensor ocupado"
|
||||
#define D_SENSOR_CRC_ERROR "Error CRC del Sensor"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Énergie hier"
|
||||
#define D_ENERGY_TOTAL "Énergie totale"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Capteur occupé"
|
||||
#define D_SENSOR_CRC_ERROR "Erreur CRC capteur"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "צריכה בעבר"
|
||||
#define D_ENERGY_TOTAL "צריכה כללית"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "שרת עסוק"
|
||||
#define D_SENSOR_CRC_ERROR "בחיישן CRC שגיאת"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Tegnapi energia"
|
||||
#define D_ENERGY_TOTAL "Összes energia"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Szenzor foglalt"
|
||||
#define D_SENSOR_CRC_ERROR "Szenzor CRC hiba"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Energia Ieri"
|
||||
#define D_ENERGY_TOTAL "Energia Totale"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensore occupato"
|
||||
#define D_SENSOR_CRC_ERROR "Sensore errore CRC"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "어제 전력 사용량"
|
||||
#define D_ENERGY_TOTAL "총 전력 사용량"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "센서가 사용 중"
|
||||
#define D_SENSOR_CRC_ERROR "센서 CRC 에러"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Verbruik gisteren"
|
||||
#define D_ENERGY_TOTAL "Verbruik totaal"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensor bezet"
|
||||
#define D_SENSOR_CRC_ERROR "Sensor CRC fout"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Energia Wczoraj"
|
||||
#define D_ENERGY_TOTAL "Energia suma"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Czujnik DS18x20 zajęty"
|
||||
#define D_SENSOR_CRC_ERROR "Czujnik DS18x20 błąd CRC"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Consumo energético de ontem"
|
||||
#define D_ENERGY_TOTAL "Consumo total de energia"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensor ocupado"
|
||||
#define D_SENSOR_CRC_ERROR "Erro sensor CRC"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Consumo energético de ontem"
|
||||
#define D_ENERGY_TOTAL "Consumo total de energial"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensor ocupado"
|
||||
#define D_SENSOR_CRC_ERROR "Erro Sensor CRC"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Энергия Вчера"
|
||||
#define D_ENERGY_TOTAL "Энергия Всего"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Датчик DS18x20 занят"
|
||||
#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - ошибка CRC"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Spotreba včera"
|
||||
#define D_ENERGY_TOTAL "Celková spotreba"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensor DS18x20 obsadený"
|
||||
#define D_SENSOR_CRC_ERROR "Sensor DS18x20 chyba CRC"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Energi igår"
|
||||
#define D_ENERGY_TOTAL "Energi totalt"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensor upptagen"
|
||||
#define D_SENSOR_CRC_ERROR "Sensor CRC-fel"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Energy Yesterday"
|
||||
#define D_ENERGY_TOTAL "Energy Total"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Sensör başgül"
|
||||
#define D_SENSOR_CRC_ERROR "Sensor CRC hatası"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "Енергія Вчора"
|
||||
#define D_ENERGY_TOTAL "Енергія Всього"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "Датчик DS18x20 зайнятий"
|
||||
#define D_SENSOR_CRC_ERROR "Датчик DS18x20 - помилка CRC"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "昨日用电量"
|
||||
#define D_ENERGY_TOTAL "总用电量"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "传感器正忙"
|
||||
#define D_SENSOR_CRC_ERROR "传感器 CRC 校验错误"
|
||||
|
|
|
@ -442,6 +442,11 @@
|
|||
#define D_ENERGY_YESTERDAY "昨日用電量"
|
||||
#define D_ENERGY_TOTAL "總用電量"
|
||||
|
||||
// xdrv_27_shutter.ino
|
||||
#define D_OPEN "Open"
|
||||
#define D_CLOSE "Close"
|
||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
||||
|
||||
// xsns_05_ds18b20.ino
|
||||
#define D_SENSOR_BUSY "傳感器正忙"
|
||||
#define D_SENSOR_CRC_ERROR "傳感器 CRC 校驗錯誤"
|
||||
|
|
|
@ -313,6 +313,7 @@
|
|||
#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code)
|
||||
#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
||||
//#define ROTARY_V1 // Add support for MI Desk Lamp
|
||||
//#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+6k code)
|
||||
|
||||
// -- Counter input -------------------------------
|
||||
#define USE_COUNTER // Enable inputs as counter (+0k8 code)
|
||||
|
|
|
@ -93,7 +93,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||
uint32_t spare27 : 1;
|
||||
uint32_t spare28 : 1;
|
||||
uint32_t spare29 : 1;
|
||||
uint32_t spare30 : 1;
|
||||
uint32_t shutter_mode : 1; // bit 30 (v6.6.0.15) - SetOption80 - Enable shutter support
|
||||
uint32_t spare31 : 1;
|
||||
};
|
||||
} SysBitfield3;
|
||||
|
@ -227,7 +227,8 @@ struct SYSCFG {
|
|||
uint8_t weblog_level; // 1AC
|
||||
uint8_t mqtt_fingerprint[2][20]; // 1AD
|
||||
uint8_t adc_param_type; // 1D5
|
||||
uint8_t register8[17]; // 1D6 - 17 x 8-bit registers indexed by enum SettingsRegister8
|
||||
uint8_t register8[16]; // 1D6 - 16 x 8-bit registers indexed by enum SettingsRegister8
|
||||
uint8_t shutter_accuracy; // 1E6
|
||||
uint8_t mqttlog_level; // 1E7
|
||||
uint8_t sps30_inuse_hours; // 1E8
|
||||
char mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6
|
||||
|
@ -376,7 +377,15 @@ struct SYSCFG {
|
|||
uint16_t ina226_i_fs[4]; // E28
|
||||
uint16_t tariff[4][2]; // E30
|
||||
|
||||
uint8_t free_e40[440]; // E40
|
||||
uint16_t shutter_opentime[MAX_SHUTTERS]; // E40
|
||||
uint16_t shutter_closetime[MAX_SHUTTERS]; // E48
|
||||
int16_t shuttercoeff[5][MAX_SHUTTERS]; // E50
|
||||
uint8_t shutter_invert[MAX_SHUTTERS]; // E78
|
||||
uint8_t shutter_set50percent[MAX_SHUTTERS]; // E7C
|
||||
uint8_t shutter_position[MAX_SHUTTERS]; // E80
|
||||
uint8_t shutter_startrelay[MAX_SHUTTERS]; // E84
|
||||
|
||||
uint8_t free_e88[368]; // E88
|
||||
|
||||
uint32_t cfg_timestamp; // FF8
|
||||
uint32_t cfg_crc32; // FFC
|
||||
|
@ -427,7 +436,11 @@ struct XDRVMAILBOX {
|
|||
char *command;
|
||||
} XdrvMailbox;
|
||||
|
||||
#ifdef USE_SHUTTER
|
||||
const uint8_t MAX_RULES_FLAG = 10; // Number of bits used in RulesBitfield (tricky I know...)
|
||||
#else
|
||||
const uint8_t MAX_RULES_FLAG = 8; // Number of bits used in RulesBitfield (tricky I know...)
|
||||
#endif // USE_SHUTTER
|
||||
typedef union { // Restricted by MISRA-C Rule 18.4 but so useful...
|
||||
uint16_t data; // Allow bit manipulation
|
||||
struct {
|
||||
|
@ -439,8 +452,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||
uint16_t wifi_connected : 1;
|
||||
uint16_t wifi_disconnected : 1;
|
||||
uint16_t http_init : 1;
|
||||
uint16_t spare08 : 1;
|
||||
uint16_t spare09 : 1;
|
||||
uint16_t shutter_moved : 1;
|
||||
uint16_t shutter_moving : 1;
|
||||
uint16_t spare10 : 1;
|
||||
uint16_t spare11 : 1;
|
||||
uint16_t spare12 : 1;
|
||||
|
|
|
@ -67,6 +67,7 @@ const uint8_t MAX_XNRG_DRIVERS = 32; // Max number of allowed energy driv
|
|||
const uint8_t MAX_XDSP_DRIVERS = 32; // Max number of allowed display drivers
|
||||
const uint8_t MAX_XDRV_DRIVERS = 96; // Max number of allowed driver drivers
|
||||
const uint8_t MAX_XSNS_DRIVERS = 96; // Max number of allowed sensor drivers
|
||||
const uint8_t MAX_SHUTTERS = 4; // Max number of shutters
|
||||
const uint8_t MAX_RULE_MEMS = 5; // Max number of saved vars
|
||||
const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters
|
||||
const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules
|
||||
|
@ -255,10 +256,10 @@ enum SettingsParamIndex { P_HOLD_TIME, P_MAX_POWER_RETRY, P_ex_TUYA_DIMMER_ID, P
|
|||
enum SettingsRegister8 { R8_SPARE00, R8_SPARE01, R8_SPARE02, R8_SPARE03,
|
||||
R8_SPARE04, R8_SPARE05, R8_SPARE06, R8_SPARE07,
|
||||
R8_SPARE08, R8_SPARE09, R8_SPARE10, R8_SPARE11,
|
||||
R8_SPARE12, R8_SPARE13, R8_SPARE14, R8_SPARE15,
|
||||
R8_SPARE16 }; // Max size is 17 (Settings.register8[])
|
||||
R8_SPARE12, R8_SPARE13, R8_SPARE14, R8_SPARE15 }; // Max size is 16 (Settings.register8[])
|
||||
|
||||
enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_P1_SMART_METER, DZ_MAX_SENSORS};
|
||||
enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT,
|
||||
DZ_AIRQUALITY, DZ_P1_SMART_METER, DZ_SHUTTER, DZ_MAX_SENSORS};
|
||||
|
||||
enum Ws2812ClockIndex { WS_SECOND, WS_MINUTE, WS_HOUR, WS_MARKER };
|
||||
enum Ws2812Color { WS_RED, WS_GREEN, WS_BLUE };
|
||||
|
@ -282,8 +283,10 @@ enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FU
|
|||
enum AddressConfigSteps { ADDR_IDLE, ADDR_RECEIVE, ADDR_SEND };
|
||||
|
||||
enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER,
|
||||
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_MAX };
|
||||
const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|Timer|Rule|MaxPower|MaxEnergy|Overtemp|Light|Knx|Display|Wemo|Hue|Retry|Remote";
|
||||
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER,
|
||||
SRC_MAX };
|
||||
const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|"
|
||||
"Timer|Rule|MaxPower|MaxEnergy|Overtemp|Light|Knx|Display|Wemo|Hue|Retry|Remote|Shutter";
|
||||
|
||||
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ power_t blink_mask = 0; // Blink relay active mask
|
|||
power_t blink_powersave; // Blink start power save state
|
||||
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 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 serial_in_byte_counter = 0; // Index in receive buffer
|
||||
int ota_state_flag = 0; // OTA state flag
|
||||
|
@ -138,6 +139,8 @@ uint8_t seriallog_level; // Current copy of Settings.seriallo
|
|||
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_adc0; // Active copy of Module ADC0
|
||||
uint8_t last_source = 0;
|
||||
uint8_t shutters_present = 0; // Number of actual define shutters
|
||||
//uint8_t mdns_delayed_start = 0; // mDNS delayed start
|
||||
bool serial_local = false; // Handle serial locally;
|
||||
bool fallback_topic_flag = false; // Use Topic or FallbackTopic
|
||||
|
|
|
@ -132,7 +132,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM =
|
|||
"rfsh=0;"
|
||||
"}"
|
||||
"}"
|
||||
#else // USE_SCRIPT_WEB_DISPLAY
|
||||
#else // USE_SCRIPT_WEB_DISPLAY
|
||||
"function la(p){"
|
||||
"var a='';"
|
||||
"if(la.arguments.length==1){"
|
||||
|
@ -151,8 +151,7 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM =
|
|||
"x.send();"
|
||||
"lt=setTimeout(la,%d);" // Settings.web_refresh
|
||||
"}"
|
||||
#endif // USE_SCRIPT_WEB_DISPLAY
|
||||
|
||||
#endif // USE_SCRIPT_WEB_DISPLAY
|
||||
|
||||
#ifdef USE_JAVASCRIPT_ES6
|
||||
"lb=p=>la('&d='+p);" // Dark - Bright &d related to lb(value) and WebGetArg("d", tmp, sizeof(tmp));
|
||||
|
@ -164,7 +163,29 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM =
|
|||
"function lc(p){"
|
||||
"la('&t='+p);" // &t related to WebGetArg("t", tmp, sizeof(tmp));
|
||||
"}"
|
||||
#endif
|
||||
#endif // USE_JAVASCRIPT_ES6
|
||||
|
||||
#ifdef USE_SHUTTER
|
||||
#ifdef USE_JAVASCRIPT_ES6
|
||||
"ld1=p=>la('&u1='+p);"
|
||||
"ld2=p=>la('&u2='+p);"
|
||||
"ld3=p=>la('&u3='+p);"
|
||||
"ld4=p=>la('&u4='+p);"
|
||||
#else
|
||||
"function ld1(p){"
|
||||
"la('&u1='+p);"
|
||||
"}"
|
||||
"function ld2(p){"
|
||||
"la('&u2='+p);"
|
||||
"}"
|
||||
"function ld3(p){"
|
||||
"la('&u3='+p);"
|
||||
"}"
|
||||
"function ld4(p){"
|
||||
"la('&u4='+p);"
|
||||
"}"
|
||||
#endif // USE_JAVASCRIPT_ES6
|
||||
#endif // USE_SHUTTER
|
||||
|
||||
"wl(la);";
|
||||
|
||||
|
@ -380,6 +401,11 @@ const char HTTP_MSG_SLIDER1[] PROGMEM =
|
|||
const char HTTP_MSG_SLIDER2[] PROGMEM =
|
||||
"<div><span class='p'>" D_DARKLIGHT "</span><span class='q'>" D_BRIGHTLIGHT "</span></div>"
|
||||
"<div><input type='range' min='1' max='100' value='%d' onchange='lb(value)'></div>";
|
||||
#ifdef USE_SHUTTER
|
||||
const char HTTP_MSG_SLIDER3[] PROGMEM =
|
||||
"<div><span class='p'>" D_CLOSE "</span><span class='q'>" D_OPEN "</span></div>"
|
||||
"<div><input type='range' min='0' max='100' value='%d' onchange='ld%d(value)'></div>";
|
||||
#endif // USE_SHUTTER
|
||||
const char HTTP_MSG_RSTRT[] PROGMEM =
|
||||
"<br><div style='text-align:center;'>" D_DEVICE_WILL_RESTART "</div><br>";
|
||||
|
||||
|
@ -554,6 +580,7 @@ void ShowWebSource(uint32_t source)
|
|||
void ExecuteWebCommand(char* svalue, uint32_t source)
|
||||
{
|
||||
ShowWebSource(source);
|
||||
last_source = source;
|
||||
ExecuteCommand(svalue, SRC_IGNORE);
|
||||
}
|
||||
|
||||
|
@ -992,6 +1019,13 @@ void HandleRoot(void)
|
|||
WSContentSend_P(HTTP_MSG_SLIDER2, Settings.light_dimmer);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SHUTTER
|
||||
if (Settings.flag3.shutter_mode) {
|
||||
for (uint32_t i = 0; i < shutters_present; i++) {
|
||||
WSContentSend_P(HTTP_MSG_SLIDER3, Settings.shutter_position[i], i+1);
|
||||
}
|
||||
}
|
||||
#endif // USE_SHUTTER
|
||||
WSContentSend_P(HTTP_TABLE100);
|
||||
WSContentSend_P(PSTR("<tr>"));
|
||||
#ifdef USE_SONOFF_IFAN
|
||||
|
@ -1092,6 +1126,17 @@ bool HandleRootStatusRefresh(void)
|
|||
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp);
|
||||
ExecuteWebCommand(svalue, SRC_WEBGUI);
|
||||
}
|
||||
#ifdef USE_SHUTTER
|
||||
char webindex[5]; // WebGetArg name
|
||||
for (uint32_t j = 1; j < 5; j++) {
|
||||
snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j);
|
||||
WebGetArg(webindex, tmp, sizeof(tmp)); // 0 - 100 percent
|
||||
if (strlen(tmp)) {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), j, tmp);
|
||||
ExecuteWebCommand(svalue, SRC_WEBGUI);
|
||||
}
|
||||
}
|
||||
#endif // USE_SHUTTER
|
||||
WebGetArg("k", tmp, sizeof(tmp)); // 1 - 16 Pre defined RF keys
|
||||
if (strlen(tmp)) {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_RFKEY "%s"), tmp);
|
||||
|
|
|
@ -42,7 +42,7 @@ const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"
|
|||
|
||||
const char kDomoticzSensors[] PROGMEM =
|
||||
D_DOMOTICZ_TEMP "|" D_DOMOTICZ_TEMP_HUM "|" D_DOMOTICZ_TEMP_HUM_BARO "|" D_DOMOTICZ_POWER_ENERGY "|" D_DOMOTICZ_ILLUMINANCE "|"
|
||||
D_DOMOTICZ_COUNT "|" D_DOMOTICZ_VOLTAGE "|" D_DOMOTICZ_CURRENT "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER ;
|
||||
D_DOMOTICZ_COUNT "|" D_DOMOTICZ_VOLTAGE "|" D_DOMOTICZ_CURRENT "|" D_DOMOTICZ_AIRQUALITY "|" D_DOMOTICZ_P1_SMART_METER "|" D_DOMOTICZ_SHUTTER ;
|
||||
|
||||
char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC;
|
||||
char domoticz_out_topic[] = DOMOTICZ_OUT_TOPIC;
|
||||
|
@ -347,8 +347,15 @@ void DomoticzSensor(uint8_t idx, char *data)
|
|||
Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"),
|
||||
Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality());
|
||||
} else {
|
||||
uint8_t nvalue = 0;
|
||||
#ifdef USE_SHUTTER
|
||||
if (DZ_SHUTTER == idx) {
|
||||
uint8_t position = atoi(data);
|
||||
nvalue = position < 2 ? 0 : (position == 100 ? 1 : 2);
|
||||
}
|
||||
#endif // USE_SHUTTER
|
||||
Response_P(DOMOTICZ_MESSAGE,
|
||||
Settings.domoticz_sensor_idx[idx], 0, data, DomoticzBatteryQuality(), DomoticzRssiQuality());
|
||||
Settings.domoticz_sensor_idx[idx], nvalue, data, DomoticzBatteryQuality(), DomoticzRssiQuality());
|
||||
}
|
||||
MqttPublish(domoticz_in_topic);
|
||||
memcpy(mqtt_data, dmess, sizeof(dmess));
|
||||
|
|
|
@ -605,6 +605,10 @@ void RulesEvery50ms(void)
|
|||
case 5: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break;
|
||||
case 6: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Disconnected\":1}}"), sizeof(json_event)); break;
|
||||
case 7: strncpy_P(json_event, PSTR("{\"HTTP\":{\"Initialized\":1}}"), sizeof(json_event)); break;
|
||||
#ifdef USE_SHUTTER
|
||||
case 8: strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moved\":1}}"), sizeof(json_event)); break;
|
||||
case 9: strncpy_P(json_event, PSTR("{\"SHUTTER\":{\"Moving\":1}}"), sizeof(json_event)); break;
|
||||
#endif // USE_SHUTTER
|
||||
}
|
||||
if (json_event[0]) {
|
||||
RulesProcessEvent(json_event);
|
||||
|
@ -1881,9 +1885,6 @@ bool Xdrv10(uint8_t function)
|
|||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
case FUNC_PRE_INIT:
|
||||
RulesInit();
|
||||
break;
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
RulesEvery50ms();
|
||||
break;
|
||||
|
@ -1910,6 +1911,9 @@ bool Xdrv10(uint8_t function)
|
|||
result = RulesMqttData();
|
||||
break;
|
||||
#endif // SUPPORT_MQTT_EVENT
|
||||
case FUNC_PRE_INIT:
|
||||
RulesInit();
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1514,6 +1514,19 @@ chknext:
|
|||
len+=1;
|
||||
goto exit;
|
||||
}
|
||||
#ifdef USE_SHUTTER
|
||||
if (!strncmp(vname,"sht[",4)) {
|
||||
GetNumericResult(vname+4,OPER_EQU,&fvar,0);
|
||||
uint8_t index=fvar;
|
||||
if (index<=shutters_present) {
|
||||
fvar=Settings.shutter_position[index-1];
|
||||
} else {
|
||||
fvar=-1;
|
||||
}
|
||||
len+=1;
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
if (!strncmp(vname,"pc[",3)) {
|
||||
GetNumericResult(vname+3,OPER_EQU,&fvar,0);
|
||||
uint8_t index=fvar;
|
||||
|
|
|
@ -276,6 +276,12 @@ void HueLightStatus1(uint8_t device, String *response)
|
|||
if (bri > 254) bri = 254; // Philips Hue bri is between 1 and 254
|
||||
if (bri < 1) bri = 1;
|
||||
|
||||
#ifdef USE_SHUTTER
|
||||
if (ShutterState(device)) {
|
||||
bri = (float)(Settings.shutter_invert[device-1] ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (light_type) {
|
||||
light_state.getHSB(&hue, &sat, nullptr);
|
||||
|
||||
|
@ -519,19 +525,32 @@ void HueLights(String *path)
|
|||
response.replace("{id", String(EncodeLightId(device)));
|
||||
response.replace("{cm", "on");
|
||||
|
||||
on = hue_json["on"];
|
||||
switch(on)
|
||||
{
|
||||
case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE);
|
||||
response.replace("{re", "false");
|
||||
break;
|
||||
case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE);
|
||||
response.replace("{re", "true");
|
||||
break;
|
||||
default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false");
|
||||
break;
|
||||
#ifdef USE_SHUTTER
|
||||
if (ShutterState(device)) {
|
||||
if (!change) {
|
||||
on = hue_json["on"];
|
||||
bri = on ? 1.0f : 0.0f; // when bri is not part of this request then calculate it
|
||||
change = true;
|
||||
}
|
||||
response.replace("{re", on ? "true" : "false");
|
||||
} else {
|
||||
#endif
|
||||
on = hue_json["on"];
|
||||
switch(on)
|
||||
{
|
||||
case false : ExecuteCommandPower(device, POWER_OFF, SRC_HUE);
|
||||
response.replace("{re", "false");
|
||||
break;
|
||||
case true : ExecuteCommandPower(device, POWER_ON, SRC_HUE);
|
||||
response.replace("{re", "true");
|
||||
break;
|
||||
default : response.replace("{re", (power & (1 << (device-1))) ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
resp = true;
|
||||
#ifdef USE_SHUTTER
|
||||
}
|
||||
resp = true;
|
||||
#endif // USE_SHUTTER
|
||||
}
|
||||
|
||||
if (light_type && (local_light_subtype >= LST_SINGLE)) {
|
||||
|
@ -637,6 +656,12 @@ void HueLights(String *path)
|
|||
resp = true;
|
||||
}
|
||||
if (change) {
|
||||
#ifdef USE_SHUTTER
|
||||
if (ShutterState(device)) {
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_invert[device-1]);
|
||||
SetShutterPosition(device, bri * 100.0f );
|
||||
} else
|
||||
#endif
|
||||
if (light_type && (local_light_subtype > LST_NONE)) { // not relay
|
||||
if (!Settings.flag3.pwm_multi_channels) {
|
||||
if (g_gotct) {
|
||||
|
|
|
@ -0,0 +1,588 @@
|
|||
/*
|
||||
xdrv_27_shutter.ino - Shutter/Blind support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2019 Stefan Bode
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_SHUTTER // +3.8k code
|
||||
/*********************************************************************************************\
|
||||
* Energy
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XDRV_27 27
|
||||
|
||||
#define D_PRFX_SHUTTER "Shutter"
|
||||
#define D_CMND_SHUTTER_OPEN "Open"
|
||||
#define D_CMND_SHUTTER_CLOSE "Close"
|
||||
#define D_CMND_SHUTTER_STOP "Stop"
|
||||
#define D_CMND_SHUTTER_POSITION "Position"
|
||||
#define D_CMND_SHUTTER_OPENTIME "OpenDuration"
|
||||
#define D_CMND_SHUTTER_CLOSETIME "CloseDuration"
|
||||
#define D_CMND_SHUTTER_RELAY "Relay"
|
||||
#define D_CMND_SHUTTER_SETHALFWAY "SetHalfway"
|
||||
#define D_CMND_SHUTTER_SETCLOSE "SetClose"
|
||||
#define D_CMND_SHUTTER_INVERT "Invert"
|
||||
#define D_CMND_SHUTTER_CLIBRATION "Calibration"
|
||||
|
||||
#define D_SHUTTER "SHUTTER"
|
||||
|
||||
enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_OPEN__PULSE_CLOSE };
|
||||
|
||||
const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|"
|
||||
D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|"
|
||||
D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|"
|
||||
D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION;
|
||||
|
||||
void (* const ShutterCommand[])(void) PROGMEM = {
|
||||
&CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition,
|
||||
&CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay,
|
||||
&CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration };
|
||||
|
||||
const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_SHUTTER "%d\":{\"position\":%d,\"direction\":%d}";
|
||||
|
||||
Ticker TickerShutter;
|
||||
|
||||
const uint16_t MOTOR_STOP_TIME=500; // in mS
|
||||
|
||||
uint16_t Shutter_Open_Time[MAX_SHUTTERS] ; // duration to open the shutter
|
||||
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++) {
|
||||
shutter_time[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t percent_to_realposition(uint8_t percent,uint8_t index)
|
||||
{
|
||||
if (Settings.shutter_set50percent[index] != 50) {
|
||||
return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index];
|
||||
} else {
|
||||
return percent <= 5 ? Settings.shuttercoeff[2][index] * percent : Settings.shuttercoeff[1][index] * percent + Settings.shuttercoeff[0][index];
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t realposition_to_percent(int32_t realpos, uint8_t index)
|
||||
{
|
||||
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];
|
||||
} else {
|
||||
return Settings.shuttercoeff[2][index] * 5 > realpos ? realpos / Settings.shuttercoeff[2][index] : (realpos-Settings.shuttercoeff[0][index]) / Settings.shuttercoeff[1][index];
|
||||
}
|
||||
}
|
||||
|
||||
void ShutterInit()
|
||||
{
|
||||
shutters_present = 0;
|
||||
shutter_mask = 0;
|
||||
//Initialize to get relay that changed
|
||||
old_power = power;
|
||||
char shutter_open_chr[10];
|
||||
char shutter_close_chr[10];
|
||||
bool relay_in_interlock = false;
|
||||
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Accuracy digits: %d"), Settings.shutter_accuracy);
|
||||
|
||||
for (byte i=0;i < MAX_SHUTTERS; i++) {
|
||||
// upgrade to 0.1sec calculation base.
|
||||
if ( Settings.shutter_accuracy == 0) {
|
||||
Settings.shutter_closetime[i] = Settings.shutter_closetime[i] * 10;
|
||||
Settings.shutter_opentime[i] = Settings.shutter_opentime[i] * 10;
|
||||
}
|
||||
// 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] <9) {
|
||||
shutters_present++;
|
||||
|
||||
// Determine shutter types
|
||||
shutter_mask |= 3 << (Settings.shutter_startrelay[i] -1) ;
|
||||
|
||||
for (uint8_t i = 0; i < MAX_INTERLOCKS * Settings.flag.interlock; i++) {
|
||||
//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) {
|
||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Relay in Interlock group"));
|
||||
relay_in_interlock = true;
|
||||
}
|
||||
}
|
||||
if ( relay_in_interlock) {
|
||||
if (Settings.pulse_timer[i] > 0) {
|
||||
shutterMode = SHT_PULSE_OPEN__PULSE_CLOSE;
|
||||
} else {
|
||||
shutterMode = SHT_OFF_OPEN__OFF_CLOSE;
|
||||
}
|
||||
} else {
|
||||
shutterMode = SHT_OFF_ON__OPEN_CLOSE;
|
||||
}
|
||||
|
||||
TickerShutter.attach_ms(50, Rtc_ms50_Second );
|
||||
// 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]);
|
||||
// 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_Close_Time[i] = Settings.shutter_closetime[i] > 0 ? Settings.shutter_closetime[i] : 100;
|
||||
|
||||
// Update Calculation 20 because time interval is 0.05 sec
|
||||
Shutter_Open_Max[i] = 200 * Shutter_Open_Time[i];
|
||||
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
|
||||
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[2][i] = (Settings.shuttercoeff[0][i] + 5 * Settings.shuttercoeff[1][i]) / 5;
|
||||
shutter_mask |= 3 << (Settings.shutter_startrelay[i] -1) ;
|
||||
|
||||
Shutter_Real_Position[i] = percent_to_realposition(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_Start_Position[i] = Shutter_Real_Position[i];
|
||||
dtostrfd((double)Shutter_Open_Time[i] / 10 , 1, shutter_open_chr);
|
||||
dtostrfd((double)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],shutterMode );
|
||||
} else {
|
||||
// terminate loop at first INVALID shutter.
|
||||
break;
|
||||
}
|
||||
Settings.shutter_accuracy = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Schutter_Update_Position()
|
||||
{
|
||||
char scommand[CMDSZ];
|
||||
char stopic[TOPSZ];
|
||||
|
||||
for (byte i=0; i < shutters_present; i++) {
|
||||
if (Shutter_Direction[i] != 0) {
|
||||
//char stemp1[20];
|
||||
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.
|
||||
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.
|
||||
if (Shutter_Target_Position[i] == Shutter_Real_Position[i] && Shutter_Target_Position[i] == 0) {
|
||||
// for every operation add 5x50ms = 250ms to stop position
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Adding additional runtime"));
|
||||
Shutter_Real_Position[i] += 500 * Shutter_Operations[i] ;
|
||||
Shutter_Operations[i] = 0;
|
||||
}
|
||||
if (Shutter_Real_Position[i] * Shutter_Direction[i] >= Shutter_Target_Position[i] * Shutter_Direction[i] ) {
|
||||
// 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]);
|
||||
uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter_Direction[i] == 1 ? 0 : 1) ;
|
||||
char stemp2[10];
|
||||
|
||||
Settings.shutter_position[i] = realposition_to_percent(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;
|
||||
|
||||
if (0 < Settings.shutter_position[i] && Settings.shutter_position[i] < 100) {
|
||||
Shutter_Operations[i]++;
|
||||
} else {
|
||||
Shutter_Operations[i] = 0;
|
||||
}
|
||||
|
||||
dtostrfd((double)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]);
|
||||
Shutter_Start_Position[i] = Shutter_Real_Position[i];
|
||||
|
||||
// sending MQTT result to broker
|
||||
snprintf_P(scommand, sizeof(scommand),PSTR("%s%d"), D_SHUTTER, i+1);
|
||||
GetTopic_P(stopic, STAT, mqtt_topic, scommand);
|
||||
Response_P("%d", Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]);
|
||||
MqttPublish(stopic, Settings.flag.mqtt_power_retain);
|
||||
|
||||
switch (shutterMode) {
|
||||
case SHT_PULSE_OPEN__PULSE_CLOSE:
|
||||
// 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) {
|
||||
ExecuteCommandPower(cur_relay, 1, SRC_SHUTTER);
|
||||
} else {
|
||||
last_source = SRC_SHUTTER;
|
||||
}
|
||||
break;
|
||||
case SHT_OFF_ON__OPEN_CLOSE:
|
||||
// This is a failsafe configuration. Relay1 ON/OFF Relay2 -1/1 direction
|
||||
if ((1 << (Settings.shutter_startrelay[i]-1)) & power) {
|
||||
ExecuteCommandPower(Settings.shutter_startrelay[i], 0, SRC_SHUTTER);
|
||||
}
|
||||
break;
|
||||
case SHT_OFF_OPEN__OFF_CLOSE:
|
||||
// avoid switching OFF a relay already OFF
|
||||
if ((1 << (cur_relay-1)) & power) {
|
||||
// Relay is on and need to be switched off.
|
||||
ExecuteCommandPower(cur_relay, 0, SRC_SHUTTER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
Shutter_Direction[i] = 0;
|
||||
byte position = Settings.shutter_invert[i] ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i];
|
||||
Response_P(PSTR("{"));
|
||||
ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, 0 /*Shutter_Direction[i]*/);
|
||||
ResponseJsonEnd();
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data);
|
||||
XdrvRulesProcess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool ShutterState(uint8_t device)
|
||||
{
|
||||
device--;
|
||||
device &= 3;
|
||||
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)
|
||||
{
|
||||
Shutter_Direction[index] = direction;
|
||||
Shutter_Target_Position[index] = target_pos;
|
||||
Shutter_Start_Position[index] = Shutter_Real_Position[index];
|
||||
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]);
|
||||
}
|
||||
|
||||
void DelayForMotorStop()
|
||||
{
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Wait for Motorstop %d"), MOTOR_STOP_TIME);
|
||||
delay(MOTOR_STOP_TIME);
|
||||
}
|
||||
|
||||
void Schutter_Report_Position()
|
||||
{
|
||||
uint16_t shutter_moving = 0;
|
||||
for (byte i=0; i < shutters_present; i++) {
|
||||
if (Shutter_Direction[i] != 0) {
|
||||
char stemp1[20];
|
||||
char stemp2[10];
|
||||
dtostrfd((double)shutter_time[i] / 20, 1, stemp2);
|
||||
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];
|
||||
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) {
|
||||
rules_flag.shutter_moved = 1;
|
||||
} else {
|
||||
rules_flag.shutter_moved = 0;
|
||||
}
|
||||
rules_flag.shutter_moving = shutter_moving;
|
||||
//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()
|
||||
{
|
||||
|
||||
// SwitchedRelay = binary relay that was recently changed and cause an Action
|
||||
// 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
|
||||
char stemp1[10];
|
||||
|
||||
|
||||
for (byte i=0; i < shutters_present; i++) {
|
||||
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 = ((SwitchedRelay >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != last_source && SRC_PULSETIMER != last_source ;
|
||||
if (manual_relays_changed) {
|
||||
if (shutterMode == SHT_OFF_ON__OPEN_CLOSE) {
|
||||
switch (powerstate_local) {
|
||||
case 1:
|
||||
DelayForMotorStop();
|
||||
Shutter_StartInit(i, 1, Shutter_Open_Max[i]);
|
||||
break;
|
||||
case 3:
|
||||
DelayForMotorStop();
|
||||
Shutter_StartInit(i, -1, 0);
|
||||
break;
|
||||
default:
|
||||
Shutter_Direction[i] = 0;
|
||||
Shutter_Target_Position[i] = Shutter_Real_Position[i];
|
||||
}
|
||||
} else {
|
||||
if (Shutter_Direction[i] != 0 && (!powerstate_local || (powerstate_local && shutterMode == SHT_PULSE_OPEN__PULSE_CLOSE))) {
|
||||
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);
|
||||
} else {
|
||||
last_source = SRC_SHUTTER; // avoid switch off in the next loop
|
||||
if (powerstate_local == 2) { // testing on CLOSE relay, if ON
|
||||
// close with relay two
|
||||
DelayForMotorStop();
|
||||
Shutter_StartInit(i, -1, 0);
|
||||
} else {
|
||||
// opens with relay one
|
||||
DelayForMotorStop();
|
||||
Shutter_StartInit(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Shutter specific functions
|
||||
// TODO: move to shutter driver and make them accessible in a generic way
|
||||
|
||||
// device: 1..<numberOfShutters>
|
||||
// position: 0-100
|
||||
void SetShutterPosition(uint8_t device, uint8_t position)
|
||||
{
|
||||
char svalue[32]; // Command and number parameter
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_POSITION "%d %d"), device, position);
|
||||
ExecuteCommand(svalue, SRC_IGNORE);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Commands
|
||||
\*********************************************************************************************/
|
||||
|
||||
void CmndShutterOpen(void)
|
||||
{
|
||||
XdrvMailbox.payload = 100;
|
||||
last_source = SRC_WEBGUI;
|
||||
CmndShutterPosition();
|
||||
}
|
||||
|
||||
void CmndShutterClose(void)
|
||||
{
|
||||
XdrvMailbox.payload = 0;
|
||||
last_source = SRC_WEBGUI;
|
||||
CmndShutterPosition();
|
||||
}
|
||||
|
||||
void CmndShutterStop(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
|
||||
uint32_t index = XdrvMailbox.index -1;
|
||||
if (Shutter_Direction[index] != 0) {
|
||||
|
||||
//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]));
|
||||
XdrvMailbox.payload = realposition_to_percent(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];
|
||||
last_source = SRC_WEBGUI;
|
||||
CmndShutterPosition();
|
||||
} else {
|
||||
ResponseCmndDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CmndShutterPosition(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
|
||||
uint32_t index = XdrvMailbox.index -1;
|
||||
//limit the payload
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Position in: payload %d, index %d, source %d"), XdrvMailbox.payload , XdrvMailbox.index, last_source );
|
||||
|
||||
int8_t target_pos_percent = XdrvMailbox.payload < 0 ? 0 : (XdrvMailbox.payload > 100 ? 100 : XdrvMailbox.payload);
|
||||
// webgui still send also on inverted shutter the native position.
|
||||
target_pos_percent = Settings.shutter_invert[index] && SRC_WEBGUI != last_source ? 100 - target_pos_percent : target_pos_percent;
|
||||
if (target_pos_percent != -99) {
|
||||
//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] = 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);
|
||||
}
|
||||
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;
|
||||
if (Shutter_Direction[index] == -new_shutterdirection ) {
|
||||
// direction need to be changed. on momentary switches first stop the Shutter
|
||||
if (shutterMode == SHT_PULSE_OPEN__PULSE_CLOSE) {
|
||||
// code for momentary shutters only small switch on to stop Shutter
|
||||
ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER);
|
||||
delay(100);
|
||||
} else {
|
||||
ExecuteCommandPower(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), 0, SRC_SHUTTER);
|
||||
DelayForMotorStop();
|
||||
}
|
||||
}
|
||||
if (Shutter_Direction[index] != new_shutterdirection ) {
|
||||
Shutter_StartInit(index, new_shutterdirection, Shutter_Target_Position[index]);
|
||||
Shutter_Operations[index]++;
|
||||
if (shutterMode == SHT_OFF_ON__OPEN_CLOSE) {
|
||||
ExecuteCommandPower(Settings.shutter_startrelay[index] , 0, SRC_SHUTTER);
|
||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: Delay5 5s, xdrv %d"), XdrvMailbox.payload);
|
||||
DelayForMotorStop();
|
||||
// Code for shutters with circuit safe configuration, switch the direction Relay
|
||||
ExecuteCommandPower(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER);
|
||||
// power on
|
||||
ExecuteCommandPower(Settings.shutter_startrelay[index] , 1, SRC_SHUTTER);
|
||||
} else {
|
||||
// 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]);
|
||||
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);
|
||||
}
|
||||
SwitchedRelay = 0;
|
||||
}
|
||||
} else {
|
||||
target_pos_percent = realposition_to_percent(Shutter_Real_Position[index], index);
|
||||
}
|
||||
ResponseCmndIdxNumber(Settings.shutter_invert[index] ? 100 - target_pos_percent : target_pos_percent);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndShutterOpenTime(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
Settings.shutter_opentime[XdrvMailbox.index-1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data));
|
||||
ShutterInit();
|
||||
}
|
||||
char time_chr[10];
|
||||
dtostrfd((float)(Settings.shutter_opentime[XdrvMailbox.index-1]) / 10, 1, time_chr);
|
||||
ResponseCmndIdxChar(time_chr);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndShutterCloseTime(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
Settings.shutter_closetime[XdrvMailbox.index-1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data));
|
||||
ShutterInit();
|
||||
}
|
||||
char time_chr[10];
|
||||
dtostrfd((float)(Settings.shutter_closetime[XdrvMailbox.index-1]) / 10, 1, time_chr);
|
||||
ResponseCmndIdxChar(time_chr);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndShutterRelay(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) {
|
||||
Settings.shutter_startrelay[XdrvMailbox.index-1] = XdrvMailbox.payload;
|
||||
if (XdrvMailbox.payload > 0) {
|
||||
shutter_mask |= 3 << (XdrvMailbox.payload - 1);
|
||||
} else {
|
||||
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);
|
||||
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
|
||||
}
|
||||
ResponseCmndIdxNumber(Settings.shutter_startrelay[XdrvMailbox.index -1]);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndShutterSetHalfway(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
|
||||
Settings.shutter_set50percent[XdrvMailbox.index-1] = Settings.shutter_invert[XdrvMailbox.index-1] ? 100 - XdrvMailbox.payload : XdrvMailbox.payload;
|
||||
ShutterInit();
|
||||
ResponseCmndIdxNumber(XdrvMailbox.payload); // ????
|
||||
} else {
|
||||
ResponseCmndIdxNumber(Settings.shutter_set50percent[XdrvMailbox.index-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CmndShutterSetClose(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
|
||||
Shutter_Real_Position[XdrvMailbox.index-1] = 0;
|
||||
Shutter_StartInit(XdrvMailbox.index-1, 0, 0);
|
||||
Settings.shutter_position[XdrvMailbox.index-1] = 0;
|
||||
ResponseCmndChar(D_CONFIGURATION_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndShutterInvert(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
||||
Settings.shutter_invert[XdrvMailbox.index-1] = XdrvMailbox.payload;
|
||||
}
|
||||
ResponseCmndIdxNumber(Settings.shutter_invert[XdrvMailbox.index-1]);
|
||||
}
|
||||
}
|
||||
|
||||
void CmndShutterCalibration(void) // ????
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
ResponseCmndIdxChar(XdrvMailbox.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xdrv27(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (Settings.flag3.shutter_mode) {
|
||||
switch (function) {
|
||||
case FUNC_PRE_INIT:
|
||||
ShutterInit();
|
||||
break;
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
Schutter_Update_Position();
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
Schutter_Report_Position();
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = DecodeCommand(kShutterCommands, ShutterCommand);
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
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];
|
||||
ResponseAppend_P(",");
|
||||
ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter_Direction[i]);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if ((0 == tele_period) && (0 == i)) {
|
||||
DomoticzSensor(DZ_SHUTTER, position);
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
break;
|
||||
case FUNC_SET_POWER:
|
||||
char stemp1[10];
|
||||
// extract the number of the relay that was switched and save for later in Update Position.
|
||||
SwitchedRelay = power ^ old_power;
|
||||
old_power = power;
|
||||
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Switched relay: %d by %s"), SwitchedRelay,GetTextIndexed(stemp1, sizeof(stemp1), last_source, kCommandSource));
|
||||
Shutter_Relay_changed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif //USE_SHUTTER
|
Loading…
Reference in New Issue