mirror of https://github.com/arendst/Tasmota.git
Merge branch 'development' into serial_iarm_send
This commit is contained in:
commit
7735f95058
|
@ -7,6 +7,10 @@
|
||||||
* Add initial support for shutters by Stefan Bode (#288)
|
* Add initial support for shutters by Stefan Bode (#288)
|
||||||
* Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE
|
* Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE
|
||||||
* Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode
|
* Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode
|
||||||
|
* Add command SetOption71 0/1 to switch between different Modbus Active Energy registers on DDS238-2 energy meters (#6531)
|
||||||
|
* Change command SetOption43 to make it more general. Now supports PS_16_DZ driver too (#6547)
|
||||||
|
* Change command handling by moving buffers up in chain solving MQTTlog support (#6524)
|
||||||
|
* Change detection of non-MQTT commands by allowing non-space characters as delimiter (#6540)
|
||||||
* Fix TasmotaSerial: move serial send to IRAM for high speed baud rates
|
* Fix TasmotaSerial: move serial send to IRAM for high speed baud rates
|
||||||
*
|
*
|
||||||
* 6.6.0.13 20190922
|
* 6.6.0.13 20190922
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||||
* Use online command Prefix to translate cmnd, stat and tele.
|
* Use online command Prefix to translate cmnd, stat and tele.
|
||||||
*
|
*
|
||||||
* Updated until v6.6.0.4
|
* Updated until v6.6.0.14
|
||||||
\*********************************************************************/
|
\*********************************************************************/
|
||||||
|
|
||||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||||
|
@ -443,17 +443,17 @@
|
||||||
#define D_ENERGY_TOTAL "Energie insgesamt"
|
#define D_ENERGY_TOTAL "Energie insgesamt"
|
||||||
|
|
||||||
// xdrv_27_shutter.ino
|
// xdrv_27_shutter.ino
|
||||||
#define D_OPEN "Open"
|
#define D_OPEN "Öffnen"
|
||||||
#define D_CLOSE "Close"
|
#define D_CLOSE "Schliessen"
|
||||||
#define D_DOMOTICZ_SHUTTER "Shutter"
|
#define D_DOMOTICZ_SHUTTER "Rollo"
|
||||||
|
|
||||||
// xdrv_28_pcf8574.ino
|
// xdrv_28_pcf8574.ino
|
||||||
#define D_CONFIGURE_PCF8574 "Configure PCF8574"
|
#define D_CONFIGURE_PCF8574 "Konfiguriere PCF8574"
|
||||||
#define D_PCF8574_PARAMETERS "PCF8574 parameters"
|
#define D_PCF8574_PARAMETERS "PCF8574 Parameter"
|
||||||
#define D_INVERT_PORTS "Invert Ports"
|
#define D_INVERT_PORTS "Invertiere Ports"
|
||||||
#define D_DEVICE "Device"
|
#define D_DEVICE "Gerät"
|
||||||
#define D_DEVICE_INPUT "Input"
|
#define D_DEVICE_INPUT "Eingang"
|
||||||
#define D_DEVICE_OUTPUT "Output"
|
#define D_DEVICE_OUTPUT "Ausgang"
|
||||||
|
|
||||||
// xsns_05_ds18b20.ino
|
// xsns_05_ds18b20.ino
|
||||||
#define D_SENSOR_BUSY "Sensor beschäftigt"
|
#define D_SENSOR_BUSY "Sensor beschäftigt"
|
||||||
|
|
|
@ -84,7 +84,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
||||||
uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM
|
uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM
|
||||||
uint32_t tuya_dimmer_min_limit : 1; // bit 19 (v6.6.0.5) - SetOption69 - Limits Tuya dimmers to minimum of 10% (25) when enabled.
|
uint32_t tuya_dimmer_min_limit : 1; // bit 19 (v6.6.0.5) - SetOption69 - Limits Tuya dimmers to minimum of 10% (25) when enabled.
|
||||||
uint32_t energy_weekend : 1; // bit 20 (v6.6.0.8) - CMND_TARIFF
|
uint32_t energy_weekend : 1; // bit 20 (v6.6.0.8) - CMND_TARIFF
|
||||||
uint32_t spare21 : 1;
|
uint32_t dds2382_model : 1; // bit 21 (v6.6.0.14) - SetOption71 - Select different Modbus registers for Active Energy (#6531)
|
||||||
uint32_t spare22 : 1;
|
uint32_t spare22 : 1;
|
||||||
uint32_t spare23 : 1;
|
uint32_t spare23 : 1;
|
||||||
uint32_t spare24 : 1;
|
uint32_t spare24 : 1;
|
||||||
|
|
|
@ -125,8 +125,8 @@
|
||||||
#ifndef ENERGY_OVERTEMP
|
#ifndef ENERGY_OVERTEMP
|
||||||
#define ENERGY_OVERTEMP 90 // Overtemp in Celsius
|
#define ENERGY_OVERTEMP 90 // Overtemp in Celsius
|
||||||
#endif
|
#endif
|
||||||
#ifndef TUYA_DIMMER_MAX
|
#ifndef DEFAULT_DIMMER_MAX
|
||||||
#define TUYA_DIMMER_MAX 100
|
#define DEFAULT_DIMMER_MAX 100
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum WebColors {
|
enum WebColors {
|
||||||
|
@ -774,7 +774,7 @@ void SettingsDefaultSet2(void)
|
||||||
// Settings.light_rotation = 0;
|
// Settings.light_rotation = 0;
|
||||||
SettingsDefaultSet_5_8_1(); // Clock color
|
SettingsDefaultSet_5_8_1(); // Clock color
|
||||||
|
|
||||||
Settings.param[P_TUYA_DIMMER_MAX] = TUYA_DIMMER_MAX;
|
Settings.param[P_DIMMER_MAX] = DEFAULT_DIMMER_MAX;
|
||||||
|
|
||||||
// Display
|
// Display
|
||||||
SettingsDefaultSet_5_10_1(); // Display settings
|
SettingsDefaultSet_5_10_1(); // Display settings
|
||||||
|
@ -1084,9 +1084,9 @@ void SettingsDelta(void)
|
||||||
if (Settings.version < 0x06060008) {
|
if (Settings.version < 0x06060008) {
|
||||||
// Move current tuya dimmer range to the new param.
|
// Move current tuya dimmer range to the new param.
|
||||||
if (Settings.flag3.tuya_dimmer_range_255) {
|
if (Settings.flag3.tuya_dimmer_range_255) {
|
||||||
Settings.param[P_TUYA_DIMMER_MAX] = 100;
|
Settings.param[P_DIMMER_MAX] = 100;
|
||||||
} else {
|
} else {
|
||||||
Settings.param[P_TUYA_DIMMER_MAX] = 255;
|
Settings.param[P_DIMMER_MAX] = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Settings.version < 0x06060009) {
|
if (Settings.version < 0x06060009) {
|
||||||
|
|
|
@ -249,7 +249,7 @@ enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER };
|
||||||
|
|
||||||
enum SettingsParamIndex { P_HOLD_TIME, P_MAX_POWER_RETRY, P_ex_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38
|
enum SettingsParamIndex { P_HOLD_TIME, P_MAX_POWER_RETRY, P_ex_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38
|
||||||
P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_ex_TUYA_RELAYS, P_OVER_TEMP, // SetOption39 .. SetOption42
|
P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_ex_TUYA_RELAYS, P_OVER_TEMP, // SetOption39 .. SetOption42
|
||||||
P_TUYA_DIMMER_MAX,
|
P_DIMMER_MAX,
|
||||||
P_ex_TUYA_VOLTAGE_ID, P_ex_TUYA_CURRENT_ID, P_ex_TUYA_POWER_ID, // SetOption43 .. SetOption46
|
P_ex_TUYA_VOLTAGE_ID, P_ex_TUYA_CURRENT_ID, P_ex_TUYA_POWER_ID, // SetOption43 .. SetOption46
|
||||||
P_ex_ENERGY_TARIFF1, P_ex_ENERGY_TARIFF2, // SetOption47 .. SetOption48
|
P_ex_ENERGY_TARIFF1, P_ex_ENERGY_TARIFF2, // SetOption47 .. SetOption48
|
||||||
P_MAX_PARAM8 }; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49
|
P_MAX_PARAM8 }; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49
|
||||||
|
|
|
@ -81,55 +81,61 @@ void ResponseCmndIdxChar(const char* value)
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
void ExecuteCommand(char *cmnd, uint32_t source)
|
void ExecuteCommand(const char *cmnd, uint32_t source)
|
||||||
{
|
{
|
||||||
char *start;
|
// cmnd: "status 0" = stopic "status" and svalue " 0"
|
||||||
char *token;
|
// cmnd: "var1 =1" = stopic "var1" and svalue " =1"
|
||||||
|
// cmnd: "var1=1" = stopic "var1" and svalue "=1"
|
||||||
#ifdef USE_DEBUG_DRIVER
|
#ifdef USE_DEBUG_DRIVER
|
||||||
ShowFreeMem(PSTR("ExecuteCommand"));
|
ShowFreeMem(PSTR("ExecuteCommand"));
|
||||||
#endif
|
#endif
|
||||||
ShowSource(source);
|
ShowSource(source);
|
||||||
|
|
||||||
token = strtok(cmnd, " ");
|
const char *pos = cmnd;
|
||||||
if (token != nullptr) {
|
while (*pos && isspace(*pos)) {
|
||||||
start = strrchr(token, '/'); // Skip possible cmnd/sonoff/ preamble
|
pos++; // Skip all spaces
|
||||||
if (start) { token = start +1; }
|
|
||||||
}
|
}
|
||||||
uint32_t size = (token != nullptr) ? strlen(token) : 0;
|
|
||||||
char stopic[size +2]; // / + \0
|
|
||||||
snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == nullptr) ? "" : token);
|
|
||||||
|
|
||||||
token = strtok(nullptr, "");
|
const char *start = pos;
|
||||||
size = (token != nullptr) ? strlen(token) : 0;
|
// Get a command. Commands can only use letters, digits and underscores
|
||||||
char svalue[size +1];
|
while (*pos && (isalpha(*pos) || isdigit(*pos) || '_' == *pos || '/' == *pos)) {
|
||||||
strlcpy(svalue, (token == nullptr) ? "" : token, sizeof(svalue)); // Fixed 5.8.0b
|
if ('/' == *pos) { // Skip possible cmnd/sonoff/ preamble
|
||||||
CommandHandler(stopic, (uint8_t*)svalue, strlen(svalue));
|
start = pos + 1;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
if ('\0' == *start || pos <= start) {
|
||||||
|
return; // Did not find any command to execute
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t size = pos - start;
|
||||||
|
char stopic[size + 2]; // with leader '/' and end '\0'
|
||||||
|
stopic[0] = '/';
|
||||||
|
memcpy(stopic+1, start, size);
|
||||||
|
stopic[size+1] = '\0';
|
||||||
|
|
||||||
|
char svalue[strlen(pos) +1]; // pos point to the start of parameters
|
||||||
|
strlcpy(svalue, pos, sizeof(svalue));
|
||||||
|
CommandHandler(stopic, svalue, strlen(svalue));
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
// topic: /power1 data: toggle = Console command
|
// topicBuf: /power1 dataBuf: toggle = Console command
|
||||||
// topic: cmnd/sonoff/power1 data: toggle = Mqtt command using topic
|
// topicBuf: cmnd/sonoff/power1 dataBuf: toggle = Mqtt command using topic
|
||||||
// topic: cmnd/sonoffs/power1 data: toggle = Mqtt command using a group topic
|
// topicBuf: cmnd/sonoffs/power1 dataBuf: toggle = Mqtt command using a group topic
|
||||||
// topic: cmnd/DVES_83BB10_fb/power1 data: toggle = Mqtt command using fallback topic
|
// topicBuf: cmnd/DVES_83BB10_fb/power1 dataBuf: toggle = Mqtt command using fallback topic
|
||||||
|
|
||||||
void CommandHandler(char* topic, uint8_t* data, uint32_t data_len)
|
void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len)
|
||||||
{
|
{
|
||||||
#ifdef USE_DEBUG_DRIVER
|
#ifdef USE_DEBUG_DRIVER
|
||||||
ShowFreeMem(PSTR("CommandHandler"));
|
ShowFreeMem(PSTR("CommandHandler"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char topicBuf[TOPSZ];
|
while (*dataBuf && isspace(*dataBuf)) {
|
||||||
strlcpy(topicBuf, topic, sizeof(topicBuf));
|
dataBuf++; // Skip leading spaces in data
|
||||||
|
data_len--;
|
||||||
uint32_t i = 0;
|
|
||||||
for (i = 0; i < data_len; i++) {
|
|
||||||
if (!isspace(data[i])) { break; } // Skip leading spaces in data
|
|
||||||
}
|
}
|
||||||
data_len -= i;
|
|
||||||
char dataBuf[data_len+1];
|
|
||||||
memcpy(dataBuf, data +i, sizeof(dataBuf));
|
|
||||||
|
|
||||||
bool grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr);
|
bool grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr);
|
||||||
|
|
||||||
|
@ -137,8 +143,9 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len)
|
||||||
GetFallbackTopic_P(stemp1, CMND, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/
|
GetFallbackTopic_P(stemp1, CMND, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/
|
||||||
fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1)));
|
fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1)));
|
||||||
|
|
||||||
char *type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type)
|
char *type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type)
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
uint32_t index = 1;
|
uint32_t index = 1;
|
||||||
bool user_index = false;
|
bool user_index = false;
|
||||||
if (type != nullptr) {
|
if (type != nullptr) {
|
||||||
|
@ -156,7 +163,7 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len)
|
||||||
type[i] = '\0';
|
type[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_CORE_LOG(PSTR("CMD: " D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " \"%s\", " D_DATA " \"%s\""), grpflg, index, type, dataBuf);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("CMD: " D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " \"%s\", " D_DATA " \"%s\""), grpflg, index, type, dataBuf);
|
||||||
|
|
||||||
if (type != nullptr) {
|
if (type != nullptr) {
|
||||||
Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}"));
|
Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}"));
|
||||||
|
@ -686,11 +693,9 @@ void CmndSetoption(void)
|
||||||
IrReceiveUpdateThreshold();
|
IrReceiveUpdateThreshold();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_TUYA_MCU
|
case P_DIMMER_MAX:
|
||||||
case P_TUYA_DIMMER_MAX:
|
|
||||||
restart_flag = 2; // Need a restart to update GUI
|
restart_flag = 2; // Need a restart to update GUI
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,11 @@ void PollUdp(void)
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer);
|
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer);
|
||||||
|
|
||||||
// Simple Service Discovery Protocol (SSDP)
|
// Simple Service Discovery Protocol (SSDP)
|
||||||
|
#ifdef USE_SCRIPT_HUE
|
||||||
|
if (!udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) {
|
||||||
|
#else
|
||||||
if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) {
|
if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) {
|
||||||
|
#endif
|
||||||
udp_response_mutex = true;
|
udp_response_mutex = true;
|
||||||
|
|
||||||
udp_remote_ip = PortUdp.remoteIP();
|
udp_remote_ip = PortUdp.remoteIP();
|
||||||
|
|
|
@ -251,7 +251,7 @@ bool MqttPublishLib(const char* topic, bool retained)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len)
|
||||||
{
|
{
|
||||||
#ifdef USE_DEBUG_DRIVER
|
#ifdef USE_DEBUG_DRIVER
|
||||||
ShowFreeMem(PSTR("MqttDataHandler"));
|
ShowFreeMem(PSTR("MqttDataHandler"));
|
||||||
|
@ -262,8 +262,8 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
||||||
|
|
||||||
// Do not execute multiple times if Prefix1 equals Prefix2
|
// Do not execute multiple times if Prefix1 equals Prefix2
|
||||||
if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) {
|
if (!strcmp(Settings.mqtt_prefix[0], Settings.mqtt_prefix[1])) {
|
||||||
char *str = strstr(topic, Settings.mqtt_prefix[0]);
|
char *str = strstr(mqtt_topic, Settings.mqtt_prefix[0]);
|
||||||
if ((str == topic) && mqtt_cmnd_publish) {
|
if ((str == mqtt_topic) && mqtt_cmnd_publish) {
|
||||||
if (mqtt_cmnd_publish > 3) {
|
if (mqtt_cmnd_publish > 3) {
|
||||||
mqtt_cmnd_publish -= 3;
|
mqtt_cmnd_publish -= 3;
|
||||||
} else {
|
} else {
|
||||||
|
@ -273,13 +273,22 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data[data_len] = 0;
|
// Save MQTT data ASAP as it's data is discarded by PubSubClient with next publish as used in MQTTlog
|
||||||
|
char topic[TOPSZ];
|
||||||
|
strlcpy(topic, mqtt_topic, sizeof(topic));
|
||||||
|
mqtt_data[data_len] = 0;
|
||||||
|
char data[data_len +1];
|
||||||
|
memcpy(data, mqtt_data, sizeof(data));
|
||||||
|
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_RECEIVED_TOPIC " %s, " D_DATA_SIZE " %d, " D_DATA " %s"), topic, data_len, data);
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_RECEIVED_TOPIC " \"%s\", " D_DATA_SIZE " %d, " D_DATA " \"%s\""), topic, data_len, data);
|
||||||
// if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(dataBuf); }
|
// if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(data); }
|
||||||
|
|
||||||
// MQTT pre-processing
|
// MQTT pre-processing
|
||||||
if (XdrvMqttData(topic, strlen(topic), (char*)data, data_len)) { return; }
|
XdrvMailbox.index = strlen(topic);
|
||||||
|
XdrvMailbox.data_len = data_len;
|
||||||
|
XdrvMailbox.topic = topic;
|
||||||
|
XdrvMailbox.data = (char*)data;
|
||||||
|
if (XdrvCall(FUNC_MQTT_DATA)) { return; }
|
||||||
|
|
||||||
ShowSource(SRC_MQTT);
|
ShowSource(SRC_MQTT);
|
||||||
|
|
||||||
|
|
|
@ -199,102 +199,104 @@ void DomoticzMqttSubscribe(void)
|
||||||
|
|
||||||
bool DomoticzMqttData(void)
|
bool DomoticzMqttData(void)
|
||||||
{
|
{
|
||||||
char stemp1[10];
|
|
||||||
unsigned long idx = 0;
|
|
||||||
int16_t nvalue = -1;
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
domoticz_update_flag = true;
|
domoticz_update_flag = true;
|
||||||
if (!strncmp(XdrvMailbox.topic, domoticz_out_topic, strlen(domoticz_out_topic))) {
|
|
||||||
if (XdrvMailbox.data_len < 20) {
|
if (strncasecmp(XdrvMailbox.topic, domoticz_out_topic, strlen(domoticz_out_topic)) != 0) {
|
||||||
return true; // No valid data
|
return false; // Process unchanged data
|
||||||
}
|
}
|
||||||
StaticJsonBuffer<400> jsonBuf;
|
|
||||||
JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data);
|
// topic is domoticz/out so try to analyse
|
||||||
if (!domoticz.success()) {
|
if (XdrvMailbox.data_len < 20) {
|
||||||
return true; // To much or invalid data
|
return true; // No valid data
|
||||||
}
|
}
|
||||||
|
StaticJsonBuffer<400> jsonBuf;
|
||||||
|
JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data);
|
||||||
|
if (!domoticz.success()) {
|
||||||
|
return true; // To much or invalid data
|
||||||
|
}
|
||||||
// if (strcmp_P(domoticz["dtype"],PSTR("Light/Switch"))) {
|
// if (strcmp_P(domoticz["dtype"],PSTR("Light/Switch"))) {
|
||||||
// return true;
|
// return true;
|
||||||
// }
|
// }
|
||||||
idx = domoticz["idx"];
|
uint32_t idx = domoticz["idx"];
|
||||||
if (domoticz.containsKey("nvalue")) {
|
int16_t nvalue = -1;
|
||||||
nvalue = domoticz["nvalue"];
|
if (domoticz.containsKey("nvalue")) {
|
||||||
}
|
nvalue = domoticz["nvalue"];
|
||||||
|
}
|
||||||
|
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue);
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue);
|
||||||
|
|
||||||
if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) {
|
bool found = false;
|
||||||
uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present;
|
if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) {
|
||||||
for (uint32_t i = 0; i < maxdev; i++) {
|
uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present;
|
||||||
if (idx == Settings.domoticz_relay_idx[i]) {
|
for (uint32_t i = 0; i < maxdev; i++) {
|
||||||
bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0;
|
if (idx == Settings.domoticz_relay_idx[i]) {
|
||||||
snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1);
|
bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0;
|
||||||
|
char stemp1[10];
|
||||||
|
snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1);
|
||||||
#ifdef USE_SONOFF_IFAN
|
#ifdef USE_SONOFF_IFAN
|
||||||
if (IsModuleIfan() && (1 == i)) { // Idx 2 is fanspeed
|
if (IsModuleIfan() && (1 == i)) { // Idx 2 is fanspeed
|
||||||
uint8_t svalue = 0;
|
uint8_t svalue = 0;
|
||||||
if (domoticz.containsKey("svalue1")) {
|
if (domoticz.containsKey("svalue1")) {
|
||||||
svalue = domoticz["svalue1"];
|
svalue = domoticz["svalue1"];
|
||||||
} else {
|
} else {
|
||||||
return true; // Invalid data
|
return true; // Invalid data
|
||||||
}
|
}
|
||||||
svalue = (nvalue == 2) ? svalue / 10 : 0;
|
svalue = (nvalue == 2) ? svalue / 10 : 0;
|
||||||
if (GetFanspeed() == svalue) {
|
if (GetFanspeed() == svalue) {
|
||||||
return true; // Stop loop as already set
|
return true; // Stop loop as already set
|
||||||
}
|
}
|
||||||
if (TimePassedSince(domoticz_fan_debounce) < 1000) {
|
if (TimePassedSince(domoticz_fan_debounce) < 1000) {
|
||||||
return true; // Stop loop if device in limbo
|
return true; // Stop loop if device in limbo
|
||||||
}
|
}
|
||||||
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED));
|
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED));
|
||||||
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue);
|
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue);
|
||||||
found = true;
|
found = true;
|
||||||
} else
|
} else
|
||||||
#endif // USE_SONOFF_IFAN
|
#endif // USE_SONOFF_IFAN
|
||||||
if (iscolordimmer && 10 == nvalue) { // Color_SetColor
|
if (iscolordimmer && 10 == nvalue) { // Color_SetColor
|
||||||
JsonObject& color = domoticz["Color"];
|
JsonObject& color = domoticz["Color"];
|
||||||
uint16_t level = nvalue = domoticz["svalue1"];
|
uint16_t level = nvalue = domoticz["svalue1"];
|
||||||
uint16_t r = color["r"]; r = r * level / 100;
|
uint16_t r = color["r"]; r = r * level / 100;
|
||||||
uint16_t g = color["g"]; g = g * level / 100;
|
uint16_t g = color["g"]; g = g * level / 100;
|
||||||
uint16_t b = color["b"]; b = b * level / 100;
|
uint16_t b = color["b"]; b = b * level / 100;
|
||||||
uint16_t cw = color["cw"]; cw = cw * level / 100;
|
uint16_t cw = color["cw"]; cw = cw * level / 100;
|
||||||
uint16_t ww = color["ww"]; ww = ww * level / 100;
|
uint16_t ww = color["ww"]; ww = ww * level / 100;
|
||||||
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR));
|
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_COLOR));
|
||||||
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww);
|
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%02x%02x%02x%02x%02x"), r, g, b, cw, ww);
|
||||||
found = true;
|
found = true;
|
||||||
}
|
|
||||||
else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel
|
|
||||||
(iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel
|
|
||||||
if (domoticz.containsKey("svalue1")) {
|
|
||||||
nvalue = domoticz["svalue1"];
|
|
||||||
} else {
|
|
||||||
return true; // Invalid data
|
|
||||||
}
|
|
||||||
if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) {
|
|
||||||
return true; // State already set
|
|
||||||
}
|
|
||||||
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER));
|
|
||||||
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
else if (1 == nvalue || 0 == nvalue) {
|
|
||||||
if (((power >> i) &1) == (power_t)nvalue) {
|
|
||||||
return true; // Stop loop
|
|
||||||
}
|
|
||||||
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : "");
|
|
||||||
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel
|
||||||
|
(iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel
|
||||||
|
if (domoticz.containsKey("svalue1")) {
|
||||||
|
nvalue = domoticz["svalue1"];
|
||||||
|
} else {
|
||||||
|
return true; // Invalid data
|
||||||
|
}
|
||||||
|
if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) {
|
||||||
|
return true; // State already set
|
||||||
|
}
|
||||||
|
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER));
|
||||||
|
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else if (1 == nvalue || 0 == nvalue) {
|
||||||
|
if (((power >> i) &1) == (power_t)nvalue) {
|
||||||
|
return true; // Stop loop
|
||||||
|
}
|
||||||
|
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_POWER "%s"), (devices_present > 1) ? stemp1 : "");
|
||||||
|
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) { return true; } // No command received
|
|
||||||
|
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data);
|
|
||||||
|
|
||||||
domoticz_update_flag = false;
|
|
||||||
}
|
}
|
||||||
return false; // Process unchanged or new data
|
if (!found) { return true; } // No command received
|
||||||
|
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data);
|
||||||
|
|
||||||
|
domoticz_update_flag = false;
|
||||||
|
return false; // Process new data
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
|
@ -698,10 +698,10 @@ void RulesTeleperiod(void)
|
||||||
*/
|
*/
|
||||||
bool RulesMqttData(void)
|
bool RulesMqttData(void)
|
||||||
{
|
{
|
||||||
bool serviced = false;
|
|
||||||
if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) {
|
if (XdrvMailbox.data_len < 1 || XdrvMailbox.data_len > 256) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool serviced = false;
|
||||||
String sTopic = XdrvMailbox.topic;
|
String sTopic = XdrvMailbox.topic;
|
||||||
String sData = XdrvMailbox.data;
|
String sData = XdrvMailbox.data;
|
||||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: MQTT Topic %s, Event %s"), XdrvMailbox.topic, XdrvMailbox.data);
|
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: MQTT Topic %s, Event %s"), XdrvMailbox.topic, XdrvMailbox.data);
|
||||||
|
|
|
@ -3366,30 +3366,8 @@ void ScriptSaveSettings(void) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT)
|
#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT)
|
||||||
|
|
||||||
/*
|
|
||||||
"state": {
|
|
||||||
"temperature": 2674,
|
|
||||||
"lastupdated": "2017-08-04T12:13:04"
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"on": true,
|
|
||||||
"battery": 100,
|
|
||||||
"reachable": true,
|
|
||||||
"alert": "none",
|
|
||||||
"ledindication": false,
|
|
||||||
"usertest": false,
|
|
||||||
"pending": []
|
|
||||||
},
|
|
||||||
"name": "Hue temperature sensor 1",
|
|
||||||
"type": "ZLLTemperature",
|
|
||||||
"modelid": "SML001",
|
|
||||||
"manufacturername": "Philips",
|
|
||||||
"swversion": "6.1.0.18912",
|
|
||||||
"uniqueid": "xxx"
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define HUE_DEV_MVNUM 5
|
#define HUE_DEV_MVNUM 5
|
||||||
#define HUE_DEV_NSIZE 16
|
#define HUE_DEV_NSIZE 16
|
||||||
|
@ -3414,8 +3392,76 @@ const char SCRIPT_HUE_LIGHTS_STATUS_JSON1[] PROGMEM =
|
||||||
"\"uniqueid\":\"{j2\","
|
"\"uniqueid\":\"{j2\","
|
||||||
"\"swversion\":\"5.50.1.19085\"}";
|
"\"swversion\":\"5.50.1.19085\"}";
|
||||||
|
|
||||||
|
/*
|
||||||
|
const char SCRIPT_HUE_LIGHTS_STATUS_JSON2[] PROGMEM =
|
||||||
|
"{\"state\":"
|
||||||
|
"{\"temperature\": 2674,"
|
||||||
|
"\"lastupdated\": \"2019-08-04T12:13:04\"},"
|
||||||
|
"\"config\": {"
|
||||||
|
"\"on\": true,"
|
||||||
|
"\"battery\": 100,"
|
||||||
|
"\"reachable\": true,"
|
||||||
|
"\"alert\": \"none\","
|
||||||
|
"\"ledindication\": false,"
|
||||||
|
"\"usertest\": false,"
|
||||||
|
"\"pending\": []"
|
||||||
|
"},"
|
||||||
|
"\"name\": \"{j1\","
|
||||||
|
"\"type\": \"ZLLTemperature\","
|
||||||
|
"\"modelid\": \"SML001\","
|
||||||
|
"\"manufacturername\": \"Philips\","
|
||||||
|
"\"swversion\": \"6.1.0.18912\","
|
||||||
|
"\"uniqueid\": \"{j2\"}";
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
const char SCRIPT_HUE_LIGHTS_STATUS_JSON2[] PROGMEM =
|
||||||
|
"{\"state\":{"
|
||||||
|
"\"presence\":{state},"
|
||||||
|
"\"lastupdated\":\"2017-10-01T12:37:30\""
|
||||||
|
"},"
|
||||||
|
"\"swupdate\":{"
|
||||||
|
"\"state\":\"noupdates\","
|
||||||
|
"\"lastinstall\": null"
|
||||||
|
"},"
|
||||||
|
"\"config\":{"
|
||||||
|
"\"on\":true,"
|
||||||
|
"\"battery\":100,"
|
||||||
|
"\"reachable\":true,"
|
||||||
|
"\"alert\":\"none\","
|
||||||
|
"\"ledindication\":false,"
|
||||||
|
"\"usertest\":false,"
|
||||||
|
"\"sensitivity\":2,"
|
||||||
|
"\"sensitivitymax\":2,"
|
||||||
|
"\"pending\":[]"
|
||||||
|
"},"
|
||||||
|
"\"name\":\"{j1\","
|
||||||
|
"\"type\":\"ZLLPresence\","
|
||||||
|
"\"modelid\":\"SML001\","
|
||||||
|
"\"manufacturername\":\"Philips\","
|
||||||
|
"\"swversion\":\"6.1.0.18912\","
|
||||||
|
"\"uniqueid\":\"{j2\""
|
||||||
|
"}";
|
||||||
|
|
||||||
|
/*
|
||||||
|
temperature ZLLTemperature
|
||||||
|
lightlevel ZLLLightLevel
|
||||||
|
presence ZLLPresence
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Script_HueStatus(String *response, uint16_t hue_devs) {
|
void Script_HueStatus(String *response, uint16_t hue_devs) {
|
||||||
|
|
||||||
|
if (hue_script[hue_devs].type=='P') {
|
||||||
|
*response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON2);
|
||||||
|
response->replace("{j1",hue_script[hue_devs].name);
|
||||||
|
response->replace("{j2", GetHueDeviceId(hue_devs));
|
||||||
|
uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1];
|
||||||
|
response->replace("{state}", (pwr ? "true" : "false"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
*response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON1);
|
*response+=FPSTR(SCRIPT_HUE_LIGHTS_STATUS_JSON1);
|
||||||
uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1];
|
uint8_t pwr=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1];
|
||||||
response->replace("{state}", (pwr ? "true" : "false"));
|
response->replace("{state}", (pwr ? "true" : "false"));
|
||||||
|
@ -3454,16 +3500,44 @@ void Script_HueStatus(String *response, uint16_t hue_devs) {
|
||||||
light_status += ",";
|
light_status += ",";
|
||||||
}
|
}
|
||||||
|
|
||||||
response->replace("{light_status}", light_status);
|
float temp;
|
||||||
response->replace("{j1",hue_script[hue_devs].name);
|
switch (hue_script[hue_devs].type) {
|
||||||
response->replace("{j2", GetHueDeviceId(hue_devs<<8));
|
case 'E':
|
||||||
|
response->replace("{type}","Extended color light");
|
||||||
if (hue_script[hue_devs].type=='E') {
|
break;
|
||||||
response->replace("{type}","Extended color light");
|
case 'S':
|
||||||
} else {
|
response->replace("{type}","color light");
|
||||||
response->replace("{type}","color light");
|
break;
|
||||||
|
case 'T':
|
||||||
|
response->replace("{type}","ZLLTemperature");
|
||||||
|
temp=glob_script_mem.fvars[hue_script[hue_devs].index[2]-1];
|
||||||
|
light_status += "\"temperature\":";
|
||||||
|
light_status += String(temp*100);
|
||||||
|
light_status += ",";
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
response->replace("{type}","ZLLLightLevel");
|
||||||
|
temp=glob_script_mem.fvars[hue_script[hue_devs].index[2]-1];
|
||||||
|
light_status += "\"lightlevel\":";
|
||||||
|
light_status += String(temp);
|
||||||
|
light_status += ",";
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
response->replace("{type}","ZLLPresence");
|
||||||
|
temp=glob_script_mem.fvars[hue_script[hue_devs].index[0]-1];
|
||||||
|
light_status += "\"presence\":";
|
||||||
|
if (temp==0)light_status += "false";
|
||||||
|
else light_status += "true";
|
||||||
|
light_status += ",";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
response->replace("{type}","color light");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response->replace("{light_status}", light_status);
|
||||||
|
response->replace("{j1",hue_script[hue_devs].name);
|
||||||
|
response->replace("{j2", GetHueDeviceId(hue_devs));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3570,7 +3644,13 @@ void Script_Check_Hue(String *response) {
|
||||||
}
|
}
|
||||||
// append response
|
// append response
|
||||||
if (response) {
|
if (response) {
|
||||||
*response+=",\""+String(EncodeLightId(hue_devs+devices_present+1))+"\":";
|
if (devices_present) {
|
||||||
|
*response+=",\"";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (hue_devs>0) *response+=",\"";
|
||||||
|
}
|
||||||
|
*response+=String(EncodeLightId(hue_devs+devices_present+1))+"\":";
|
||||||
Script_HueStatus(response,hue_devs);
|
Script_HueStatus(response,hue_devs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3584,16 +3664,22 @@ void Script_Check_Hue(String *response) {
|
||||||
lp++;
|
lp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 0
|
#if 1
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Hue: %d"), hue_devs);
|
if (response) {
|
||||||
toLog(">>>>");
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("Hue: %d"), hue_devs);
|
||||||
toLog(response->c_str());
|
toLog(">>>>");
|
||||||
toLog(response->c_str()+LOGSZ);
|
toLog(response->c_str());
|
||||||
|
toLog(response->c_str()+LOGSZ);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const char sHUE_LIGHT_RESPONSE_JSON[] PROGMEM =
|
const char sHUE_LIGHT_RESPONSE_JSON[] PROGMEM =
|
||||||
"{\"success\":{\"/lights/{id/state/{cm\":{re}}";
|
"{\"success\":{\"/lights/{id/state/{cm\":{re}}";
|
||||||
|
|
||||||
|
const char sHUE_SENSOR_RESPONSE_JSON[] PROGMEM =
|
||||||
|
"{\"success\":{\"/lights/{id/state/{cm\":{re}}";
|
||||||
|
|
||||||
const char sHUE_ERROR_JSON[] PROGMEM =
|
const char sHUE_ERROR_JSON[] PROGMEM =
|
||||||
"[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]";
|
"[{\"error\":{\"type\":901,\"address\":\"/\",\"description\":\"Internal Error\"}}]";
|
||||||
|
|
||||||
|
@ -3649,6 +3735,27 @@ void Script_Handle_Hue(String *path) {
|
||||||
glob_script_mem.type[hue_script[index].vindex[1]].bits.changed=1;
|
glob_script_mem.type[hue_script[index].vindex[1]].bits.changed=1;
|
||||||
resp = true;
|
resp = true;
|
||||||
}
|
}
|
||||||
|
if (hue_json.containsKey("xy")) { // Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white).
|
||||||
|
float x, y;
|
||||||
|
x = hue_json["xy"][0];
|
||||||
|
y = hue_json["xy"][1];
|
||||||
|
const String &x_str = hue_json["xy"][0];
|
||||||
|
const String &y_str = hue_json["xy"][1];
|
||||||
|
uint8_t rr,gg,bb;
|
||||||
|
LightStateClass::XyToRgb(x, y, &rr, &gg, &bb);
|
||||||
|
LightStateClass::RgbToHsb(rr, gg, bb, &hue, &sat, nullptr);
|
||||||
|
if (resp) { response += ","; }
|
||||||
|
response += FPSTR(sHUE_LIGHT_RESPONSE_JSON);
|
||||||
|
response.replace("{id", String(device));
|
||||||
|
response.replace("{cm", "xy");
|
||||||
|
response.replace("{re", "[" + x_str + "," + y_str + "]");
|
||||||
|
glob_script_mem.fvars[hue_script[index].index[2]-1]=hue;
|
||||||
|
glob_script_mem.type[hue_script[index].vindex[2]].bits.changed=1;
|
||||||
|
glob_script_mem.fvars[hue_script[index].index[3]-1]=sat;
|
||||||
|
glob_script_mem.type[hue_script[index].vindex[3]].bits.changed=1;
|
||||||
|
resp = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (hue_json.containsKey("hue")) { // The hue value is a wrapping value between 0 and 65535. Both 0 and 65535 are red, 25500 is green and 46920 is blue.
|
if (hue_json.containsKey("hue")) { // The hue value is a wrapping value between 0 and 65535. Both 0 and 65535 are red, 25500 is green and 46920 is blue.
|
||||||
tmp = hue_json["hue"];
|
tmp = hue_json["hue"];
|
||||||
//hue = changeUIntScale(tmp, 0, 65535, 0, 359);
|
//hue = changeUIntScale(tmp, 0, 65535, 0, 359);
|
||||||
|
@ -4067,7 +4174,7 @@ const char SCRIPT_MSG_BUTTONa_TBL[] PROGMEM =
|
||||||
"<td style=\"width:%d%%\"><button type='submit' onclick='seva(%d,\"%s\")'>%s</button></td>";
|
"<td style=\"width:%d%%\"><button type='submit' onclick='seva(%d,\"%s\")'>%s</button></td>";
|
||||||
|
|
||||||
const char SCRIPT_MSG_BUTTONb[] PROGMEM =
|
const char SCRIPT_MSG_BUTTONb[] PROGMEM =
|
||||||
"<img width=\"%d%%\"><\img>";
|
"<img width=\"%d%%\"></img>";
|
||||||
|
|
||||||
const char SCRIPT_MSG_BUT_START[] PROGMEM =
|
const char SCRIPT_MSG_BUT_START[] PROGMEM =
|
||||||
"<div>";
|
"<div>";
|
||||||
|
@ -4437,7 +4544,9 @@ bool Xdrv10(uint8_t function)
|
||||||
if (bitRead(Settings.rule_enabled, 0)) {
|
if (bitRead(Settings.rule_enabled, 0)) {
|
||||||
Run_Scripter(">B",2,0);
|
Run_Scripter(">B",2,0);
|
||||||
fast_script=Run_Scripter(">F",-2,0);
|
fast_script=Run_Scripter(">F",-2,0);
|
||||||
|
#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT)
|
||||||
Script_Check_Hue(0);
|
Script_Check_Hue(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FUNC_EVERY_100_MSECOND:
|
case FUNC_EVERY_100_MSECOND:
|
||||||
|
|
|
@ -297,14 +297,14 @@ void LightSerialDuty(uint8_t duty)
|
||||||
if (Settings.flag3.tuya_dimmer_min_limit) { // Enable dimming limit SetOption69: Enabled by default
|
if (Settings.flag3.tuya_dimmer_min_limit) { // Enable dimming limit SetOption69: Enabled by default
|
||||||
if (duty < 25) { duty = 25; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself
|
if (duty < 25) { duty = 25; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself
|
||||||
}
|
}
|
||||||
duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]);
|
duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_DIMMER_MAX]);
|
||||||
if (Tuya.new_dim != duty) {
|
if (Tuya.new_dim != duty) {
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid);
|
||||||
TuyaSendValue(dpid, duty);
|
TuyaSendValue(dpid, duty);
|
||||||
}
|
}
|
||||||
} else if (dpid > 0) {
|
} else if (dpid > 0) {
|
||||||
Tuya.ignore_dim = false; // reset flag
|
Tuya.ignore_dim = false; // reset flag
|
||||||
duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]);
|
duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_DIMMER_MAX]);
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set
|
||||||
} else {
|
} else {
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); //
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); //
|
||||||
|
@ -375,7 +375,7 @@ void TuyaPacketProcess(void)
|
||||||
bool tuya_energy_enabled = (XNRG_16 == energy_flg);
|
bool tuya_energy_enabled = (XNRG_16 == energy_flg);
|
||||||
if (fnId == TUYA_MCU_FUNC_DIMMER) {
|
if (fnId == TUYA_MCU_FUNC_DIMMER) {
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]);
|
||||||
Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100);
|
Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_DIMMER_MAX], 0, 100);
|
||||||
if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) {
|
if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) {
|
||||||
Tuya.ignore_dim = true;
|
Tuya.ignore_dim = true;
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@ void PS16DZSerialSendUpdateCommand(void)
|
||||||
uint8_t light_state_dimmer = light_state.getDimmer();
|
uint8_t light_state_dimmer = light_state.getDimmer();
|
||||||
// Dimming acts odd below 10% - this mirrors the threshold set on the faceplate itself
|
// Dimming acts odd below 10% - this mirrors the threshold set on the faceplate itself
|
||||||
light_state_dimmer = (light_state_dimmer < 10) ? 10 : light_state_dimmer;
|
light_state_dimmer = (light_state_dimmer < 10) ? 10 : light_state_dimmer;
|
||||||
|
light_state_dimmer = (light_state_dimmer > Settings.param[P_DIMMER_MAX]) ? Settings.param[P_DIMMER_MAX] : light_state_dimmer;
|
||||||
|
|
||||||
snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"),
|
snprintf_P(Ps16dz.tx_buffer, PS16DZ_BUFFER_SIZE, PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"),
|
||||||
LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer);
|
LocalTime(), millis()%1000, power?"on":"off", light_state_dimmer);
|
||||||
|
|
|
@ -36,7 +36,7 @@ const char HUE_RESPONSE[] PROGMEM =
|
||||||
"CACHE-CONTROL: max-age=100\r\n"
|
"CACHE-CONTROL: max-age=100\r\n"
|
||||||
"EXT:\r\n"
|
"EXT:\r\n"
|
||||||
"LOCATION: http://%s:80/description.xml\r\n"
|
"LOCATION: http://%s:80/description.xml\r\n"
|
||||||
"SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.17.0\r\n"
|
"SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.24.0\r\n" // was 1.17
|
||||||
"hue-bridgeid: %s\r\n";
|
"hue-bridgeid: %s\r\n";
|
||||||
const char HUE_ST1[] PROGMEM =
|
const char HUE_ST1[] PROGMEM =
|
||||||
"ST: upnp:rootdevice\r\n"
|
"ST: upnp:rootdevice\r\n"
|
||||||
|
@ -503,7 +503,7 @@ void HueLights(String *path)
|
||||||
response += ",\"";
|
response += ",\"";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef USE_SCRIPT
|
#ifdef USE_SCRIPT_HUE
|
||||||
Script_Check_Hue(&response);
|
Script_Check_Hue(&response);
|
||||||
#endif
|
#endif
|
||||||
response += "}";
|
response += "}";
|
||||||
|
@ -513,7 +513,7 @@ void HueLights(String *path)
|
||||||
path->remove(path->indexOf("/state")); // Remove /state
|
path->remove(path->indexOf("/state")); // Remove /state
|
||||||
device = DecodeLightId(atoi(path->c_str()));
|
device = DecodeLightId(atoi(path->c_str()));
|
||||||
|
|
||||||
#ifdef USE_SCRIPT
|
#ifdef USE_SCRIPT_HUE
|
||||||
if (device>devices_present) {
|
if (device>devices_present) {
|
||||||
return Script_Handle_Hue(path);
|
return Script_Handle_Hue(path);
|
||||||
}
|
}
|
||||||
|
@ -706,7 +706,7 @@ void HueLights(String *path)
|
||||||
path->remove(0,8); // Remove /lights/
|
path->remove(0,8); // Remove /lights/
|
||||||
device = DecodeLightId(atoi(path->c_str()));
|
device = DecodeLightId(atoi(path->c_str()));
|
||||||
|
|
||||||
#ifdef USE_SCRIPT
|
#ifdef USE_SCRIPT_HUE
|
||||||
if (device>devices_present) {
|
if (device>devices_present) {
|
||||||
Script_HueStatus(&response,device-devices_present-1);
|
Script_HueStatus(&response,device-devices_present-1);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -799,7 +799,11 @@ bool Xdrv20(uint8_t function)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
|
#ifdef USE_SCRIPT_HUE
|
||||||
|
if ((EMUL_HUE == Settings.flag2.emulation)) {
|
||||||
|
#else
|
||||||
if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) {
|
if (devices_present && (EMUL_HUE == Settings.flag2.emulation)) {
|
||||||
|
#endif
|
||||||
switch (function) {
|
switch (function) {
|
||||||
case FUNC_WEB_ADD_HANDLER:
|
case FUNC_WEB_ADD_HANDLER:
|
||||||
WebServer->on("/description.xml", HandleUpnpSetupHue);
|
WebServer->on("/description.xml", HandleUpnpSetupHue);
|
||||||
|
|
|
@ -847,16 +847,6 @@ void XsnsDriverState(void)
|
||||||
|
|
||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
||||||
bool XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t sdataBuf)
|
|
||||||
{
|
|
||||||
XdrvMailbox.index = stopicBuf;
|
|
||||||
XdrvMailbox.data_len = sdataBuf;
|
|
||||||
XdrvMailbox.topic = topicBuf;
|
|
||||||
XdrvMailbox.data = dataBuf;
|
|
||||||
|
|
||||||
return XdrvCall(FUNC_MQTT_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool XdrvRulesProcess(void)
|
bool XdrvRulesProcess(void)
|
||||||
{
|
{
|
||||||
return XdrvCallDriver(10, FUNC_RULES_PROCESS);
|
return XdrvCallDriver(10, FUNC_RULES_PROCESS);
|
||||||
|
|
|
@ -54,8 +54,10 @@ void Dds2382EverySecond(void)
|
||||||
} else {
|
} else {
|
||||||
Energy.data_valid[0] = 0;
|
Energy.data_valid[0] = 0;
|
||||||
|
|
||||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 = ModBus register
|
||||||
// SA FC BC EnergyTotal ExportActiv ImportActiv Volta Curre APowe RPowe PFact Frequ Crc--
|
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 = Buffer index
|
||||||
|
// SA FC BC EnergyTotal ExportActiv ImportActiv Volta Curre APowe RPowe PFact Frequ Crc-- = DDS238-2 ZN/S version 1 (#6384)
|
||||||
|
// SA FC BC EnergyTotal ExportActiv ImportActiv Volta Curre APowe RPowe PFact Frequ Crc-- = DDS238-2 ZN/S version 2 (#6531)
|
||||||
|
|
||||||
Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0;
|
Energy.voltage[0] = (float)((buffer[27] << 8) + buffer[28]) / 10.0;
|
||||||
Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0;
|
Energy.current[0] = (float)((buffer[29] << 8) + buffer[30]) / 100.0;
|
||||||
|
@ -63,9 +65,12 @@ void Dds2382EverySecond(void)
|
||||||
Energy.reactive_power[0] = (float)((buffer[33] << 8) + buffer[34]);
|
Energy.reactive_power[0] = (float)((buffer[33] << 8) + buffer[34]);
|
||||||
Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; // 1.00
|
Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; // 1.00
|
||||||
Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; // 50.0 Hz
|
Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; // 50.0 Hz
|
||||||
Energy.export_active = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[13] << 8) + buffer[14]) / 100.0; // 429496729.0 W
|
uint8_t offset = 11;
|
||||||
// float energy_total = (float)((buffer[3] << 24) + (buffer[4] << 16) + (buffer[5] << 8) + buffer[6]) / 100.0; // 429496729.0 W
|
if (Settings.flag3.dds2382_model) {
|
||||||
float import_active = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[17] << 8) + buffer[18]) / 100.0; // 429496729.0 W
|
offset = 19;
|
||||||
|
}
|
||||||
|
Energy.export_active = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; // 429496729.0 W
|
||||||
|
float import_active = (float)((buffer[offset +4] << 24) + (buffer[offset +5] << 16) + (buffer[offset +6] << 8) + buffer[offset +7]) / 100.0; // 429496729.0 W
|
||||||
|
|
||||||
EnergyUpdateTotal(import_active, false); // 484.708 kWh
|
EnergyUpdateTotal(import_active, false); // 484.708 kWh
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,8 @@ a_setoption = [[
|
||||||
"Enable multi-channels PWM instead of Color PWM",
|
"Enable multi-channels PWM instead of Color PWM",
|
||||||
"Limits Tuya MCU dimmers to minimum of 10% (25) when enabled",
|
"Limits Tuya MCU dimmers to minimum of 10% (25) when enabled",
|
||||||
"Enable Weekend Energy Tariff",
|
"Enable Weekend Energy Tariff",
|
||||||
"","","",
|
"Select different Modbus registers for Active Energy",
|
||||||
|
"","",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","",
|
"","",
|
||||||
"Enable shutter support",
|
"Enable shutter support",
|
||||||
|
|
Loading…
Reference in New Issue