2017-01-28 13:41:01 +00:00
|
|
|
/*
|
2018-05-28 10:35:23 +01:00
|
|
|
xdrv_07_domoticz.ino - domoticz support for Sonoff-Tasmota
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2019-01-01 12:55:01 +00:00
|
|
|
Copyright (C) 2019 Theo Arends
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2017-05-13 12:02:10 +01:00
|
|
|
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.
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2017-05-13 12:02:10 +01:00
|
|
|
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/>.
|
2017-01-28 13:41:01 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef USE_DOMOTICZ
|
|
|
|
|
2018-11-07 09:30:03 +00:00
|
|
|
#define XDRV_07 7
|
|
|
|
|
2018-04-01 20:37:00 +01:00
|
|
|
const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}";
|
|
|
|
|
2018-01-24 16:31:20 +00:00
|
|
|
enum DomoticzCommands { CMND_IDX, CMND_KEYIDX, CMND_SWITCHIDX, CMND_SENSORIDX, CMND_UPDATETIMER };
|
|
|
|
const char kDomoticzCommands[] PROGMEM = D_CMND_IDX "|" D_CMND_KEYIDX "|" D_CMND_SWITCHIDX "|" D_CMND_SENSORIDX "|" D_CMND_UPDATETIMER ;
|
2017-10-29 17:18:46 +00:00
|
|
|
|
2018-01-05 11:26:19 +00:00
|
|
|
//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_MAX_SENSORS};
|
2017-12-22 13:55:24 +00:00
|
|
|
|
|
|
|
#if MAX_DOMOTICZ_SNS_IDX < DZ_MAX_SENSORS
|
|
|
|
#error "Domoticz: Too many sensors or change settings.h layout"
|
|
|
|
#endif
|
2017-10-25 13:27:30 +01:00
|
|
|
|
|
|
|
const char kDomoticzSensors[] PROGMEM =
|
2017-12-22 13:55:24 +00:00
|
|
|
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 ;
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2017-11-11 11:33:30 +00:00
|
|
|
const char S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DOMOTICZ "%s%d\":%d}";
|
2018-02-03 22:25:05 +00:00
|
|
|
const char S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE[] PROGMEM = "{\"" D_CMND_DOMOTICZ "%s%d\":%lu}";
|
2017-11-11 11:33:30 +00:00
|
|
|
|
2017-06-06 22:23:23 +01:00
|
|
|
char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC;
|
|
|
|
char domoticz_out_topic[] = DOMOTICZ_OUT_TOPIC;
|
|
|
|
|
2019-01-28 13:08:33 +00:00
|
|
|
bool domoticz_subscribe = false;
|
|
|
|
uint8_t domoticz_update_flag = 1;
|
2018-12-06 14:03:42 +00:00
|
|
|
int domoticz_update_timer = 0;
|
|
|
|
unsigned long fan_debounce = 0; // iFan02 state debounce timer
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2018-11-14 13:32:09 +00:00
|
|
|
int DomoticzBatteryQuality(void)
|
2018-04-01 20:37:00 +01:00
|
|
|
{
|
|
|
|
// Battery 0%: ESP 2.6V (minimum operating voltage is 2.5)
|
|
|
|
// Battery 100%: ESP 3.6V (maximum operating voltage is 3.6)
|
|
|
|
// Battery 101% to 200%: ESP over 3.6V (means over maximum operating voltage)
|
|
|
|
|
|
|
|
int quality = 0; // Voltage range from 2,6V > 0% to 3,6V > 100%
|
|
|
|
|
|
|
|
uint16_t voltage = ESP.getVcc();
|
|
|
|
if (voltage <= 2600) {
|
|
|
|
quality = 0;
|
|
|
|
} else if (voltage >= 4600) {
|
|
|
|
quality = 200;
|
|
|
|
} else {
|
|
|
|
quality = (voltage - 2600) / 10;
|
|
|
|
}
|
|
|
|
return quality;
|
|
|
|
}
|
|
|
|
|
2018-11-14 13:32:09 +00:00
|
|
|
int DomoticzRssiQuality(void)
|
2018-04-01 20:37:00 +01:00
|
|
|
{
|
|
|
|
// RSSI range: 0% to 10% (12 means disable RSSI in Domoticz)
|
|
|
|
|
|
|
|
return WifiGetRssiAsQuality(WiFi.RSSI()) / 10;
|
|
|
|
}
|
|
|
|
|
2018-12-06 14:03:42 +00:00
|
|
|
void MqttPublishDomoticzFanState()
|
|
|
|
{
|
|
|
|
if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[1]) {
|
|
|
|
char svalue[8]; // Fanspeed value
|
|
|
|
|
|
|
|
int fan_speed = GetFanspeed();
|
|
|
|
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10);
|
2019-03-23 16:00:59 +00:00
|
|
|
Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality());
|
2018-12-06 14:03:42 +00:00
|
|
|
MqttPublish(domoticz_in_topic);
|
|
|
|
|
|
|
|
fan_debounce = millis();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DomoticzUpdateFanState()
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
2018-12-06 14:03:42 +00:00
|
|
|
if (domoticz_update_flag) {
|
|
|
|
MqttPublishDomoticzFanState();
|
|
|
|
}
|
|
|
|
domoticz_update_flag = 1;
|
|
|
|
}
|
2018-12-06 09:49:49 +00:00
|
|
|
|
2019-01-28 13:08:33 +00:00
|
|
|
void MqttPublishDomoticzPowerState(uint8_t device)
|
2018-12-06 14:03:42 +00:00
|
|
|
{
|
2018-12-06 09:49:49 +00:00
|
|
|
if (Settings.flag.mqtt_enabled) {
|
|
|
|
if ((device < 1) || (device > devices_present)) { device = 1; }
|
2018-12-06 14:03:42 +00:00
|
|
|
if (Settings.domoticz_relay_idx[device -1]) {
|
2019-02-11 18:21:49 +00:00
|
|
|
if ((SONOFF_IFAN02 == my_module_type) && (device > 1)) {
|
2018-12-06 14:03:42 +00:00
|
|
|
// Fan handled by MqttPublishDomoticzFanState
|
|
|
|
} else {
|
|
|
|
char svalue[8]; // Dimmer value
|
|
|
|
|
|
|
|
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer);
|
2019-03-23 16:00:59 +00:00
|
|
|
Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality());
|
2018-12-06 09:49:49 +00:00
|
|
|
MqttPublish(domoticz_in_topic);
|
|
|
|
}
|
|
|
|
}
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-28 13:08:33 +00:00
|
|
|
void DomoticzUpdatePowerState(uint8_t device)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
2017-07-15 14:07:30 +01:00
|
|
|
if (domoticz_update_flag) {
|
2017-10-18 17:22:34 +01:00
|
|
|
MqttPublishDomoticzPowerState(device);
|
2017-07-15 14:07:30 +01:00
|
|
|
}
|
|
|
|
domoticz_update_flag = 1;
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
|
|
|
|
2018-11-14 13:32:09 +00:00
|
|
|
void DomoticzMqttUpdate(void)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
2017-10-18 17:22:34 +01:00
|
|
|
if (domoticz_subscribe && (Settings.domoticz_update_timer || domoticz_update_timer)) {
|
2017-01-28 13:41:01 +00:00
|
|
|
domoticz_update_timer--;
|
|
|
|
if (domoticz_update_timer <= 0) {
|
2017-10-18 17:22:34 +01:00
|
|
|
domoticz_update_timer = Settings.domoticz_update_timer;
|
2019-06-30 15:44:36 +01:00
|
|
|
for (uint32_t i = 1; i <= devices_present; i++) {
|
2019-02-11 18:21:49 +00:00
|
|
|
if ((SONOFF_IFAN02 == my_module_type) && (i > 1)) {
|
2018-12-06 14:03:42 +00:00
|
|
|
MqttPublishDomoticzFanState();
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
MqttPublishDomoticzPowerState(i);
|
|
|
|
}
|
2017-04-25 17:24:42 +01:00
|
|
|
}
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-14 13:32:09 +00:00
|
|
|
void DomoticzMqttSubscribe(void)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
2017-10-18 17:22:34 +01:00
|
|
|
uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present;
|
2019-06-30 15:44:36 +01:00
|
|
|
for (uint32_t i = 0; i < maxdev; i++) {
|
2017-10-18 17:22:34 +01:00
|
|
|
if (Settings.domoticz_relay_idx[i]) {
|
2017-05-19 15:09:25 +01:00
|
|
|
domoticz_subscribe = true;
|
|
|
|
}
|
|
|
|
}
|
2017-06-06 22:23:23 +01:00
|
|
|
if (domoticz_subscribe) {
|
2017-01-28 13:41:01 +00:00
|
|
|
char stopic[TOPSZ];
|
2017-06-06 22:23:23 +01:00
|
|
|
snprintf_P(stopic, sizeof(stopic), PSTR("%s/#"), domoticz_out_topic); // domoticz topic
|
2017-10-18 17:22:34 +01:00
|
|
|
MqttSubscribe(stopic);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-17 16:18:41 +00:00
|
|
|
/*
|
|
|
|
* ArduinoJSON Domoticz Switch entry used to calculate jsonBuf: JSON_OBJECT_SIZE(11) + 129 = 313
|
|
|
|
{
|
|
|
|
"Battery" : 255,
|
|
|
|
"RSSI" : 12,
|
|
|
|
"dtype" : "Light/Switch",
|
|
|
|
"id" : "000140E7",
|
|
|
|
"idx" : 159,
|
|
|
|
"name" : "Sonoff1",
|
|
|
|
"nvalue" : 1,
|
|
|
|
"stype" : "Switch",
|
|
|
|
"svalue1" : "0",
|
|
|
|
"switchType" : "Dimmer",
|
|
|
|
"unit" : 1
|
2018-10-04 10:01:50 +01:00
|
|
|
}
|
|
|
|
* Fail on this one
|
|
|
|
{
|
|
|
|
"LastUpdate" : "2018-10-02 20:39:45",
|
|
|
|
"Name" : "Sfeerverlichting",
|
|
|
|
"Status" : "Off",
|
|
|
|
"Timers" : "true",
|
|
|
|
"Type" : "Group",
|
|
|
|
"idx" : "2"
|
2017-02-17 16:18:41 +00:00
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2019-01-28 13:08:33 +00:00
|
|
|
bool DomoticzMqttData(void)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
2017-04-25 17:24:42 +01:00
|
|
|
char stemp1[10];
|
2017-01-28 13:41:01 +00:00
|
|
|
unsigned long idx = 0;
|
2018-10-04 10:01:50 +01:00
|
|
|
int16_t nvalue = -1;
|
2017-04-25 17:24:42 +01:00
|
|
|
int16_t found = 0;
|
2017-09-02 13:37:02 +01:00
|
|
|
|
2017-01-28 13:41:01 +00:00
|
|
|
domoticz_update_flag = 1;
|
2018-01-05 11:26:19 +00:00
|
|
|
if (!strncmp(XdrvMailbox.topic, domoticz_out_topic, strlen(domoticz_out_topic))) {
|
|
|
|
if (XdrvMailbox.data_len < 20) {
|
2017-04-25 17:24:42 +01:00
|
|
|
return 1;
|
|
|
|
}
|
2017-02-17 16:18:41 +00:00
|
|
|
StaticJsonBuffer<400> jsonBuf;
|
2018-01-05 11:26:19 +00:00
|
|
|
JsonObject& domoticz = jsonBuf.parseObject(XdrvMailbox.data);
|
2017-04-25 17:24:42 +01:00
|
|
|
if (!domoticz.success()) {
|
|
|
|
return 1;
|
|
|
|
}
|
2017-04-29 13:40:53 +01:00
|
|
|
// if (strcmp_P(domoticz["dtype"],PSTR("Light/Switch"))) {
|
2017-04-25 17:24:42 +01:00
|
|
|
// return 1;
|
|
|
|
// }
|
2017-02-17 16:18:41 +00:00
|
|
|
idx = domoticz["idx"];
|
2018-10-04 10:01:50 +01:00
|
|
|
if (domoticz.containsKey("nvalue")) {
|
|
|
|
nvalue = domoticz["nvalue"];
|
|
|
|
}
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2019-03-08 14:15:42 +00:00
|
|
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ "idx %d, nvalue %d"), idx, nvalue);
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2018-08-23 22:53:44 +01:00
|
|
|
if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) {
|
2017-10-18 17:22:34 +01:00
|
|
|
uint8_t maxdev = (devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : devices_present;
|
2019-06-30 15:44:36 +01:00
|
|
|
for (uint32_t i = 0; i < maxdev; i++) {
|
2017-10-18 17:22:34 +01:00
|
|
|
if (idx == Settings.domoticz_relay_idx[i]) {
|
2018-08-23 22:53:44 +01:00
|
|
|
bool iscolordimmer = strcmp_P(domoticz["dtype"],PSTR("Color Switch")) == 0;
|
2017-01-28 13:41:01 +00:00
|
|
|
snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1);
|
2019-02-11 18:21:49 +00:00
|
|
|
if ((SONOFF_IFAN02 == my_module_type) && (1 == i)) { // Idx 2 is fanspeed
|
2018-12-06 14:03:42 +00:00
|
|
|
uint8_t svalue = 0;
|
2018-12-06 09:49:49 +00:00
|
|
|
if (domoticz.containsKey("svalue1")) {
|
|
|
|
svalue = domoticz["svalue1"];
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
2018-12-06 14:03:42 +00:00
|
|
|
svalue = (nvalue == 2) ? svalue / 10 : 0;
|
|
|
|
if (GetFanspeed() == svalue) {
|
|
|
|
return 1; // Stop loop as already set
|
|
|
|
}
|
|
|
|
if (TimePassedSince(fan_debounce) < 1000) {
|
|
|
|
return 1; // Stop loop if device in limbo
|
|
|
|
}
|
2018-12-06 09:49:49 +00:00
|
|
|
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_FANSPEED));
|
2018-12-06 14:03:42 +00:00
|
|
|
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), svalue);
|
2018-12-06 09:49:49 +00:00
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
else if (iscolordimmer && 10 == nvalue) { // Color_SetColor
|
2018-08-23 22:53:44 +01:00
|
|
|
JsonObject& color = domoticz["Color"];
|
|
|
|
uint16_t level = nvalue = domoticz["svalue1"];
|
|
|
|
uint16_t r = color["r"]; r = r * level / 100;
|
|
|
|
uint16_t g = color["g"]; g = g * level / 100;
|
|
|
|
uint16_t b = color["b"]; b = b * level / 100;
|
|
|
|
uint16_t cw = color["cw"]; cw = cw * level / 100;
|
|
|
|
uint16_t ww = color["ww"]; ww = ww * level / 100;
|
|
|
|
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);
|
|
|
|
found = 1;
|
2018-12-06 09:49:49 +00:00
|
|
|
}
|
|
|
|
else if ((!iscolordimmer && 2 == nvalue) || // gswitch_sSetLevel
|
|
|
|
(iscolordimmer && 15 == nvalue)) { // Color_SetBrightnessLevel
|
2018-10-04 10:01:50 +01:00
|
|
|
if (domoticz.containsKey("svalue1")) {
|
|
|
|
nvalue = domoticz["svalue1"];
|
|
|
|
} else {
|
|
|
|
return 1;
|
|
|
|
}
|
2017-10-26 15:33:33 +01:00
|
|
|
if (light_type && (Settings.light_dimmer == nvalue) && ((power >> i) &1)) {
|
2017-04-25 17:24:42 +01:00
|
|
|
return 1;
|
|
|
|
}
|
2018-01-05 11:26:19 +00:00
|
|
|
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER));
|
|
|
|
snprintf_P(XdrvMailbox.data, XdrvMailbox.data_len, PSTR("%d"), nvalue);
|
2017-01-28 13:41:01 +00:00
|
|
|
found = 1;
|
2018-12-06 09:49:49 +00:00
|
|
|
}
|
|
|
|
else if (1 == nvalue || 0 == nvalue) {
|
2018-02-03 22:25:05 +00:00
|
|
|
if (((power >> i) &1) == (power_t)nvalue) {
|
2018-12-06 14:03:42 +00:00
|
|
|
return 1; // Stop loop
|
2017-04-25 17:24:42 +01:00
|
|
|
}
|
2018-01-05 11:26:19 +00:00
|
|
|
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);
|
2017-01-28 13:41:01 +00:00
|
|
|
found = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-25 17:24:42 +01:00
|
|
|
if (!found) {
|
|
|
|
return 1;
|
|
|
|
}
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2019-03-08 14:15:42 +00:00
|
|
|
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_DOMOTICZ D_RECEIVED_TOPIC " %s, " D_DATA " %s"), XdrvMailbox.topic, XdrvMailbox.data);
|
2017-01-28 13:41:01 +00:00
|
|
|
|
|
|
|
domoticz_update_flag = 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************************************\
|
|
|
|
* Commands
|
|
|
|
\*********************************************************************************************/
|
|
|
|
|
2019-01-28 13:08:33 +00:00
|
|
|
bool DomoticzCommand(void)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
2017-10-29 17:18:46 +00:00
|
|
|
char command [CMDSZ];
|
2019-01-28 13:08:33 +00:00
|
|
|
bool serviced = true;
|
2017-09-02 13:37:02 +01:00
|
|
|
uint8_t dmtcz_len = strlen(D_CMND_DOMOTICZ); // Prep for string length change
|
|
|
|
|
2018-01-05 11:26:19 +00:00
|
|
|
if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_DOMOTICZ), dmtcz_len)) { // Prefix
|
|
|
|
int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic +dmtcz_len, kDomoticzCommands);
|
2018-05-09 09:49:43 +01:00
|
|
|
if (-1 == command_code) {
|
|
|
|
serviced = false; // Unknown command
|
|
|
|
}
|
|
|
|
else if ((CMND_IDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) {
|
2018-01-05 11:26:19 +00:00
|
|
|
if (XdrvMailbox.payload >= 0) {
|
|
|
|
Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
2017-10-18 17:22:34 +01:00
|
|
|
restart_flag = 2;
|
2017-04-03 15:38:15 +01:00
|
|
|
}
|
2019-03-23 16:00:59 +00:00
|
|
|
Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE, command, XdrvMailbox.index, Settings.domoticz_relay_idx[XdrvMailbox.index -1]);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2018-01-05 11:26:19 +00:00
|
|
|
else if ((CMND_KEYIDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) {
|
|
|
|
if (XdrvMailbox.payload >= 0) {
|
|
|
|
Settings.domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
2017-04-03 15:38:15 +01:00
|
|
|
}
|
2019-03-23 16:00:59 +00:00
|
|
|
Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE, command, XdrvMailbox.index, Settings.domoticz_key_idx[XdrvMailbox.index -1]);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2018-01-05 11:26:19 +00:00
|
|
|
else if ((CMND_SWITCHIDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) {
|
|
|
|
if (XdrvMailbox.payload >= 0) {
|
|
|
|
Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
2017-04-03 15:38:15 +01:00
|
|
|
}
|
2019-03-23 16:00:59 +00:00
|
|
|
Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_switch_idx[XdrvMailbox.index -1]);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2018-01-05 11:26:19 +00:00
|
|
|
else if ((CMND_SENSORIDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) {
|
|
|
|
if (XdrvMailbox.payload >= 0) {
|
|
|
|
Settings.domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
|
2017-04-03 15:38:15 +01:00
|
|
|
}
|
2019-03-23 16:00:59 +00:00
|
|
|
Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_sensor_idx[XdrvMailbox.index -1]);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2017-10-29 17:18:46 +00:00
|
|
|
else if (CMND_UPDATETIMER == command_code) {
|
2018-01-05 11:26:19 +00:00
|
|
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
|
|
|
Settings.domoticz_update_timer = XdrvMailbox.payload;
|
2017-04-03 15:38:15 +01:00
|
|
|
}
|
2019-03-23 16:00:59 +00:00
|
|
|
Response_P(PSTR("{\"" D_CMND_DOMOTICZ "%s\":%d}"), command, Settings.domoticz_update_timer);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2018-05-09 09:49:43 +01:00
|
|
|
else serviced = false; // Unknown command
|
2017-01-28 15:31:11 +00:00
|
|
|
}
|
2018-05-09 09:49:43 +01:00
|
|
|
else serviced = false; // Unknown command
|
2018-05-28 10:35:23 +01:00
|
|
|
|
2017-01-28 15:31:11 +00:00
|
|
|
return serviced;
|
|
|
|
}
|
|
|
|
|
2019-01-28 13:08:33 +00:00
|
|
|
bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
2019-01-28 13:08:33 +00:00
|
|
|
bool result = 0;
|
2018-07-12 13:24:17 +01:00
|
|
|
|
|
|
|
if (device <= MAX_DOMOTICZ_IDX) {
|
|
|
|
if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) {
|
2019-03-23 16:00:59 +00:00
|
|
|
Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"),
|
2018-07-12 13:24:17 +01:00
|
|
|
(key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (2 == state) ? "Toggle" : "On" : "Off");
|
|
|
|
MqttPublish(domoticz_in_topic);
|
|
|
|
result = 1;
|
|
|
|
}
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2018-07-12 13:24:17 +01:00
|
|
|
return result;
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************************************\
|
|
|
|
* Sensors
|
2017-12-22 13:55:24 +00:00
|
|
|
*
|
|
|
|
* Source : https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s
|
|
|
|
* https://www.domoticz.com/wiki/MQTT
|
|
|
|
*
|
|
|
|
* Percentage, Barometric, Air Quality:
|
|
|
|
* {\"idx\":%d,\"nvalue\":%s}, Idx, Value
|
|
|
|
*
|
|
|
|
* Humidity:
|
|
|
|
* {\"idx\":%d,\"nvalue\":%s,\"svalue\":\"%s\"}, Idx, Humidity, HumidityStatus
|
|
|
|
*
|
|
|
|
* All other:
|
|
|
|
* {\"idx\":%d,\"nvalue\":0,\"svalue\":\"%s\"}, Idx, Value(s)
|
|
|
|
*
|
2017-01-28 13:41:01 +00:00
|
|
|
\*********************************************************************************************/
|
|
|
|
|
2017-10-18 17:22:34 +01:00
|
|
|
uint8_t DomoticzHumidityState(char *hum)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
|
|
|
uint8_t h = atoi(hum);
|
|
|
|
return (!h) ? 0 : (h < 40) ? 2 : (h > 70) ? 3 : 1;
|
|
|
|
}
|
|
|
|
|
2019-01-28 13:08:33 +00:00
|
|
|
void DomoticzSensor(uint8_t idx, char *data)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
2017-10-18 17:22:34 +01:00
|
|
|
if (Settings.domoticz_sensor_idx[idx]) {
|
2019-03-23 16:00:59 +00:00
|
|
|
char dmess[100];
|
2017-09-13 13:19:34 +01:00
|
|
|
|
|
|
|
memcpy(dmess, mqtt_data, sizeof(dmess));
|
2017-12-22 13:55:24 +00:00
|
|
|
if (DZ_AIRQUALITY == idx) {
|
2019-03-23 16:00:59 +00:00
|
|
|
Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"),
|
2018-04-01 20:37:00 +01:00
|
|
|
Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality());
|
2017-12-22 13:55:24 +00:00
|
|
|
} else {
|
2019-03-23 16:00:59 +00:00
|
|
|
Response_P(DOMOTICZ_MESSAGE,
|
2018-04-01 20:37:00 +01:00
|
|
|
Settings.domoticz_sensor_idx[idx], 0, data, DomoticzBatteryQuality(), DomoticzRssiQuality());
|
2017-12-22 13:55:24 +00:00
|
|
|
}
|
2017-10-18 17:22:34 +01:00
|
|
|
MqttPublish(domoticz_in_topic);
|
2017-09-13 13:19:34 +01:00
|
|
|
memcpy(mqtt_data, dmess, sizeof(dmess));
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-28 13:08:33 +00:00
|
|
|
void DomoticzSensor(uint8_t idx, uint32_t value)
|
2017-10-02 15:45:03 +01:00
|
|
|
{
|
|
|
|
char data[16];
|
|
|
|
snprintf_P(data, sizeof(data), PSTR("%d"), value);
|
2017-10-18 17:22:34 +01:00
|
|
|
DomoticzSensor(idx, data);
|
2017-10-02 15:45:03 +01:00
|
|
|
}
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2017-10-18 17:22:34 +01:00
|
|
|
void DomoticzTempHumSensor(char *temp, char *hum)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
|
|
|
char data[16];
|
2017-10-18 17:22:34 +01:00
|
|
|
snprintf_P(data, sizeof(data), PSTR("%s;%s;%d"), temp, hum, DomoticzHumidityState(hum));
|
|
|
|
DomoticzSensor(DZ_TEMP_HUM, data);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
|
|
|
|
2017-10-18 17:22:34 +01:00
|
|
|
void DomoticzTempHumPressureSensor(char *temp, char *hum, char *baro)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
|
|
|
char data[32];
|
2017-10-18 17:22:34 +01:00
|
|
|
snprintf_P(data, sizeof(data), PSTR("%s;%s;%d;%s;5"), temp, hum, DomoticzHumidityState(hum), baro);
|
|
|
|
DomoticzSensor(DZ_TEMP_HUM_BARO, data);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
|
|
|
|
2018-08-19 12:00:27 +01:00
|
|
|
void DomoticzSensorPowerEnergy(int power, char *energy)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
|
|
|
char data[16];
|
|
|
|
snprintf_P(data, sizeof(data), PSTR("%d;%s"), power, energy);
|
2017-10-18 17:22:34 +01:00
|
|
|
DomoticzSensor(DZ_POWER_ENERGY, data);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************************************\
|
|
|
|
* Presentation
|
|
|
|
\*********************************************************************************************/
|
|
|
|
|
2017-02-06 09:08:40 +00:00
|
|
|
#ifdef USE_WEBSERVER
|
2018-10-10 21:21:44 +01:00
|
|
|
|
|
|
|
#define WEB_HANDLE_DOMOTICZ "dm"
|
|
|
|
|
2017-09-02 13:37:02 +01:00
|
|
|
const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ;
|
|
|
|
|
2018-10-10 21:21:44 +01:00
|
|
|
const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM =
|
2019-02-13 15:05:25 +00:00
|
|
|
"<p><form action='" WEB_HANDLE_DOMOTICZ "' method='get'><button>" D_CONFIGURE_DOMOTICZ "</button></form></p>";
|
2018-10-10 21:21:44 +01:00
|
|
|
|
|
|
|
const char HTTP_FORM_DOMOTICZ[] PROGMEM =
|
2019-02-13 15:05:25 +00:00
|
|
|
"<fieldset><legend><b> " D_DOMOTICZ_PARAMETERS " </b></legend>"
|
|
|
|
"<form method='post' action='" WEB_HANDLE_DOMOTICZ "'>"
|
|
|
|
"<table>";
|
2018-10-10 21:21:44 +01:00
|
|
|
const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM =
|
2019-05-31 18:51:24 +01:00
|
|
|
"<tr><td style='width:260px'><b>" D_DOMOTICZ_IDX " %d</b></td><td style='width:70px'><input id='r%d' placeholder='0' value='%d'></td></tr>"
|
|
|
|
"<tr><td style='width:260px'><b>" D_DOMOTICZ_KEY_IDX " %d</b></td><td style='width:70px'><input id='k%d' placeholder='0' value='%d'></td></tr>";
|
|
|
|
const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM =
|
|
|
|
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SWITCH_IDX " %d</b></td><td style='width:70px'><input id='s%d' placeholder='0' value='%d'></td></tr>";
|
2018-10-10 21:21:44 +01:00
|
|
|
const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM =
|
2019-05-31 18:51:24 +01:00
|
|
|
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SENSOR_IDX " %d</b> %s</td><td style='width:70px'><input id='l%d' placeholder='0' value='%d'></td></tr>";
|
2018-10-10 21:21:44 +01:00
|
|
|
const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM =
|
2019-05-31 18:51:24 +01:00
|
|
|
"<tr><td style='width:260px'><b>" D_DOMOTICZ_UPDATE_TIMER "</b> (" STR(DOMOTICZ_UPDATE_TIMER) ")</td><td style='width:70px'><input id='ut' placeholder='" STR(DOMOTICZ_UPDATE_TIMER) "' value='%d'></td></tr>";
|
2018-10-10 21:21:44 +01:00
|
|
|
|
2018-11-14 13:32:09 +00:00
|
|
|
void HandleDomoticzConfiguration(void)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
2019-01-10 11:57:42 +00:00
|
|
|
if (!HttpCheckPriviledgedAccess()) { return; }
|
|
|
|
|
2017-10-18 17:22:34 +01:00
|
|
|
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ);
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2018-10-10 21:21:44 +01:00
|
|
|
if (WebServer->hasArg("save")) {
|
|
|
|
DomoticzSaveSettings();
|
2018-10-12 10:42:52 +01:00
|
|
|
WebRestart(1);
|
2018-10-10 21:21:44 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-06-03 09:51:21 +01:00
|
|
|
char stemp[40];
|
2017-09-02 13:37:02 +01:00
|
|
|
|
2019-03-10 14:36:34 +00:00
|
|
|
WSContentStart_P(S_CONFIGURE_DOMOTICZ);
|
2019-03-04 17:16:07 +00:00
|
|
|
WSContentSendStyle();
|
2019-03-10 14:36:34 +00:00
|
|
|
WSContentSend_P(HTTP_FORM_DOMOTICZ);
|
2019-06-30 15:44:36 +01:00
|
|
|
for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) {
|
2017-10-18 17:22:34 +01:00
|
|
|
if (i < devices_present) {
|
2019-03-04 17:16:07 +00:00
|
|
|
WSContentSend_P(HTTP_FORM_DOMOTICZ_RELAY,
|
2019-06-03 15:36:24 +01:00
|
|
|
i +1, i, Settings.domoticz_relay_idx[i],
|
|
|
|
i +1, i, Settings.domoticz_key_idx[i]);
|
2017-04-03 15:38:15 +01:00
|
|
|
}
|
2018-08-25 12:08:06 +01:00
|
|
|
if (pin[GPIO_SWT1 +i] < 99) {
|
2019-03-04 17:16:07 +00:00
|
|
|
WSContentSend_P(HTTP_FORM_DOMOTICZ_SWITCH,
|
2019-06-03 15:36:24 +01:00
|
|
|
i +1, i, Settings.domoticz_switch_idx[i]);
|
2017-04-03 15:38:15 +01:00
|
|
|
}
|
2019-02-11 18:21:49 +00:00
|
|
|
if ((SONOFF_IFAN02 == my_module_type) && (1 == i)) { break; }
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2019-06-30 15:44:36 +01:00
|
|
|
for (uint32_t i = 0; i < DZ_MAX_SENSORS; i++) {
|
2019-03-04 17:16:07 +00:00
|
|
|
WSContentSend_P(HTTP_FORM_DOMOTICZ_SENSOR,
|
2019-06-03 15:36:24 +01:00
|
|
|
i +1, GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors), i, Settings.domoticz_sensor_idx[i]);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2019-03-04 17:16:07 +00:00
|
|
|
WSContentSend_P(HTTP_FORM_DOMOTICZ_TIMER, Settings.domoticz_update_timer);
|
2019-03-10 14:36:34 +00:00
|
|
|
WSContentSend_P(PSTR("</table>"));
|
|
|
|
WSContentSend_P(HTTP_FORM_END);
|
2019-03-11 09:38:41 +00:00
|
|
|
WSContentSpaceButton(BUTTON_CONFIGURATION);
|
2019-03-16 15:23:41 +00:00
|
|
|
WSContentStop();
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
|
|
|
|
2018-11-14 13:32:09 +00:00
|
|
|
void DomoticzSaveSettings(void)
|
2017-01-28 13:41:01 +00:00
|
|
|
{
|
2017-09-13 13:19:34 +01:00
|
|
|
char stemp[20];
|
2017-12-22 13:55:24 +00:00
|
|
|
char ssensor_indices[6 * MAX_DOMOTICZ_SNS_IDX];
|
2018-01-30 13:14:55 +00:00
|
|
|
char tmp[100];
|
2017-01-28 13:41:01 +00:00
|
|
|
|
2019-06-30 15:44:36 +01:00
|
|
|
for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) {
|
2019-03-04 17:16:07 +00:00
|
|
|
snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i);
|
2018-01-30 13:14:55 +00:00
|
|
|
WebGetArg(stemp, tmp, sizeof(tmp));
|
|
|
|
Settings.domoticz_relay_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp);
|
2019-03-04 17:16:07 +00:00
|
|
|
snprintf_P(stemp, sizeof(stemp), PSTR("k%d"), i);
|
2018-01-30 13:14:55 +00:00
|
|
|
WebGetArg(stemp, tmp, sizeof(tmp));
|
|
|
|
Settings.domoticz_key_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp);
|
2019-03-04 17:16:07 +00:00
|
|
|
snprintf_P(stemp, sizeof(stemp), PSTR("s%d"), i);
|
2018-01-30 13:14:55 +00:00
|
|
|
WebGetArg(stemp, tmp, sizeof(tmp));
|
|
|
|
Settings.domoticz_switch_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2017-12-22 13:55:24 +00:00
|
|
|
ssensor_indices[0] = '\0';
|
2019-06-30 15:44:36 +01:00
|
|
|
for (uint32_t i = 0; i < DZ_MAX_SENSORS; i++) {
|
2019-03-04 17:16:07 +00:00
|
|
|
snprintf_P(stemp, sizeof(stemp), PSTR("l%d"), i);
|
2018-01-30 13:14:55 +00:00
|
|
|
WebGetArg(stemp, tmp, sizeof(tmp));
|
|
|
|
Settings.domoticz_sensor_idx[i] = (!strlen(tmp)) ? 0 : atoi(tmp);
|
2017-12-22 13:55:24 +00:00
|
|
|
snprintf_P(ssensor_indices, sizeof(ssensor_indices), PSTR("%s%s%d"), ssensor_indices, (strlen(ssensor_indices)) ? "," : "", Settings.domoticz_sensor_idx[i]);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2018-01-30 13:14:55 +00:00
|
|
|
WebGetArg("ut", tmp, sizeof(tmp));
|
|
|
|
Settings.domoticz_update_timer = (!strlen(tmp)) ? DOMOTICZ_UPDATE_TIMER : atoi(tmp);
|
2017-12-22 13:55:24 +00:00
|
|
|
|
2019-03-08 14:15:42 +00:00
|
|
|
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_DOMOTICZ D_CMND_IDX " %d,%d,%d,%d, " D_CMND_KEYIDX " %d,%d,%d,%d, " D_CMND_SWITCHIDX " %d,%d,%d,%d, " D_CMND_SENSORIDX " %s, " D_CMND_UPDATETIMER " %d"),
|
2017-10-18 17:22:34 +01:00
|
|
|
Settings.domoticz_relay_idx[0], Settings.domoticz_relay_idx[1], Settings.domoticz_relay_idx[2], Settings.domoticz_relay_idx[3],
|
|
|
|
Settings.domoticz_key_idx[0], Settings.domoticz_key_idx[1], Settings.domoticz_key_idx[2], Settings.domoticz_key_idx[3],
|
|
|
|
Settings.domoticz_switch_idx[0], Settings.domoticz_switch_idx[1], Settings.domoticz_switch_idx[2], Settings.domoticz_switch_idx[3],
|
2017-12-22 13:55:24 +00:00
|
|
|
ssensor_indices, Settings.domoticz_update_timer);
|
2017-01-28 13:41:01 +00:00
|
|
|
}
|
2018-01-13 14:53:02 +00:00
|
|
|
#endif // USE_WEBSERVER
|
2018-01-05 11:26:19 +00:00
|
|
|
|
|
|
|
/*********************************************************************************************\
|
|
|
|
* Interface
|
|
|
|
\*********************************************************************************************/
|
|
|
|
|
2019-01-28 13:08:33 +00:00
|
|
|
bool Xdrv07(uint8_t function)
|
2018-01-05 11:26:19 +00:00
|
|
|
{
|
2019-01-28 13:08:33 +00:00
|
|
|
bool result = false;
|
2018-01-05 11:26:19 +00:00
|
|
|
|
|
|
|
if (Settings.flag.mqtt_enabled) {
|
|
|
|
switch (function) {
|
2018-10-10 21:21:44 +01:00
|
|
|
#ifdef USE_WEBSERVER
|
|
|
|
case FUNC_WEB_ADD_BUTTON:
|
2019-03-10 14:36:34 +00:00
|
|
|
WSContentSend_P(HTTP_BTN_MENU_DOMOTICZ);
|
2018-10-10 21:21:44 +01:00
|
|
|
break;
|
|
|
|
case FUNC_WEB_ADD_HANDLER:
|
|
|
|
WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration);
|
|
|
|
break;
|
|
|
|
#endif // USE_WEBSERVER
|
2018-01-05 11:26:19 +00:00
|
|
|
case FUNC_COMMAND:
|
|
|
|
result = DomoticzCommand();
|
|
|
|
break;
|
|
|
|
case FUNC_MQTT_SUBSCRIBE:
|
|
|
|
DomoticzMqttSubscribe();
|
|
|
|
break;
|
2018-01-18 15:19:28 +00:00
|
|
|
case FUNC_MQTT_INIT:
|
|
|
|
domoticz_update_timer = 2;
|
|
|
|
break;
|
2018-01-05 11:26:19 +00:00
|
|
|
case FUNC_MQTT_DATA:
|
|
|
|
result = DomoticzMqttData();
|
|
|
|
break;
|
|
|
|
case FUNC_EVERY_SECOND:
|
|
|
|
DomoticzMqttUpdate();
|
|
|
|
break;
|
|
|
|
case FUNC_SHOW_SENSOR:
|
|
|
|
// DomoticzSendSensor();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-01-28 13:41:01 +00:00
|
|
|
#endif // USE_DOMOTICZ
|