mirror of
https://github.com/arendst/Tasmota.git
synced 2025-04-24 23:07:17 +00:00
6.2.1.14 Rewrite Webserver
6.2.1.14 20181010 * Rewrite Webserver page handler for easier extension (thx to Adrian Scillato)
This commit is contained in:
parent
b75c4359dc
commit
b3039de1b6
@ -1,4 +1,7 @@
|
||||
/* 6.2.1.13 20181008
|
||||
/* 6.2.1.14 20181010
|
||||
* Rewrite Webserver page handler for easier extension (thx to Adrian Scillato)
|
||||
*
|
||||
* 6.2.1.13 20181008
|
||||
* Change default Mqtt client library from PubSubClient to non-blocking ArduinoMqtt by Joel Gaehwiler
|
||||
* Add command WebRefresh 1000..10000 to control web page refresh in milliseconds. Default is 2345
|
||||
*
|
||||
|
@ -539,7 +539,6 @@ const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION;
|
||||
const char S_CONFIGURE_MODULE[] PROGMEM = D_CONFIGURE_MODULE;
|
||||
const char S_CONFIGURE_WIFI[] PROGMEM = D_CONFIGURE_WIFI;
|
||||
const char S_NO_NETWORKS_FOUND[] PROGMEM = D_NO_NETWORKS_FOUND;
|
||||
const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT;
|
||||
const char S_CONFIGURE_LOGGING[] PROGMEM = D_CONFIGURE_LOGGING;
|
||||
const char S_CONFIGURE_OTHER[] PROGMEM = D_CONFIGURE_OTHER;
|
||||
const char S_SAVE_CONFIGURATION[] PROGMEM = D_SAVE_CONFIGURATION;
|
||||
|
@ -214,7 +214,7 @@ enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MA
|
||||
|
||||
enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD,
|
||||
FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR,
|
||||
FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM};
|
||||
FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_HANDLER};
|
||||
|
||||
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#ifndef _SONOFF_VERSION_H_
|
||||
#define _SONOFF_VERSION_H_
|
||||
|
||||
#define VERSION 0x0602010D
|
||||
#define VERSION 0x0602010E
|
||||
|
||||
#define D_PROGRAMNAME "Sonoff-Tasmota"
|
||||
#define D_AUTHOR "Theo Arends"
|
||||
|
2003
sonoff/xdrv_01_webserver.ino
Normal file
2003
sonoff/xdrv_01_webserver.ino
Normal file
File diff suppressed because it is too large
Load Diff
903
sonoff/xdrv_02_mqtt.ino
Normal file
903
sonoff/xdrv_02_mqtt.ino
Normal file
@ -0,0 +1,903 @@
|
||||
/*
|
||||
xdrv_02_mqtt.ino - mqtt support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 Theo Arends
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Select ONE of possible MQTT library types below
|
||||
\*********************************************************************************************/
|
||||
// Default MQTT driver for both non-TLS and TLS connections. Blocks network if MQTT server is unavailable.
|
||||
//#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library
|
||||
// Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support
|
||||
//#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 (core 2.3.0), +14k4 (core 2.4.2 lwip2) code, +4k mem) - non-TLS only
|
||||
// Alternative MQTT driver does not block network when MQTT server is unavailable. TLS should work but needs to be tested.
|
||||
//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem)
|
||||
|
||||
#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO) // Obsolete as of v6.2.1.11
|
||||
#undef MQTT_LIBRARY_TYPE
|
||||
#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT
|
||||
#endif
|
||||
|
||||
/*
|
||||
#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT)
|
||||
#undef MQTT_LIBRARY_TYPE
|
||||
#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Obsolete in near future
|
||||
#endif
|
||||
*/
|
||||
|
||||
#ifdef USE_MQTT_TLS
|
||||
|
||||
#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT)
|
||||
#undef MQTT_LIBRARY_TYPE
|
||||
#endif
|
||||
|
||||
#ifndef MQTT_LIBRARY_TYPE
|
||||
#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library as it only supports TLS
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
enum MqttCommands {
|
||||
CMND_MQTTHOST, CMND_MQTTPORT, CMND_MQTTRETRY, CMND_STATETEXT, CMND_MQTTFINGERPRINT, CMND_MQTTCLIENT,
|
||||
CMND_MQTTUSER, CMND_MQTTPASSWORD, CMND_FULLTOPIC, CMND_PREFIX, CMND_GROUPTOPIC, CMND_TOPIC, CMND_PUBLISH,
|
||||
CMND_BUTTONTOPIC, CMND_SWITCHTOPIC, CMND_BUTTONRETAIN, CMND_SWITCHRETAIN, CMND_POWERRETAIN, CMND_SENSORRETAIN };
|
||||
const char kMqttCommands[] PROGMEM =
|
||||
D_CMND_MQTTHOST "|" D_CMND_MQTTPORT "|" D_CMND_MQTTRETRY "|" D_CMND_STATETEXT "|" D_CMND_MQTTFINGERPRINT "|" D_CMND_MQTTCLIENT "|"
|
||||
D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|"
|
||||
D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ;
|
||||
|
||||
uint8_t mqtt_retry_counter = 1; // MQTT connection retry counter
|
||||
uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state
|
||||
bool mqtt_connected = false; // MQTT virtual connection status
|
||||
|
||||
/*********************************************************************************************\
|
||||
* MQTT driver specific code need to provide the following functions:
|
||||
*
|
||||
* bool MqttIsConnected()
|
||||
* void MqttDisconnect()
|
||||
* void MqttSubscribeLib(char *topic)
|
||||
* bool MqttPublishLib(const char* topic, boolean retained)
|
||||
* void MqttLoop()
|
||||
\*********************************************************************************************/
|
||||
|
||||
#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT) /***********************************************/
|
||||
|
||||
#include <PubSubClient.h>
|
||||
|
||||
// Max message size calculated by PubSubClient is (MQTT_MAX_PACKET_SIZE < 5 + 2 + strlen(topic) + plength)
|
||||
#if (MQTT_MAX_PACKET_SIZE -TOPSZ -7) < MIN_MESSZ // If the max message size is too small, throw an error at compile time. See PubSubClient.cpp line 359
|
||||
#error "MQTT_MAX_PACKET_SIZE is too small in libraries/PubSubClient/src/PubSubClient.h, increase it to at least 1000"
|
||||
#endif
|
||||
|
||||
PubSubClient MqttClient(EspClient);
|
||||
|
||||
bool MqttIsConnected()
|
||||
{
|
||||
return MqttClient.connected();
|
||||
}
|
||||
|
||||
void MqttDisconnect()
|
||||
{
|
||||
MqttClient.disconnect();
|
||||
}
|
||||
|
||||
void MqttSubscribeLib(char *topic)
|
||||
{
|
||||
MqttClient.subscribe(topic);
|
||||
MqttClient.loop(); // Solve LmacRxBlk:1 messages
|
||||
}
|
||||
|
||||
bool MqttPublishLib(const char* topic, boolean retained)
|
||||
{
|
||||
bool result = MqttClient.publish(topic, mqtt_data, retained);
|
||||
yield(); // #3313
|
||||
return result;
|
||||
}
|
||||
|
||||
void MqttLoop()
|
||||
{
|
||||
MqttClient.loop();
|
||||
}
|
||||
|
||||
#elif (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT) /**********************************************/
|
||||
|
||||
#include <TasmotaMqtt.h>
|
||||
TasmotaMqtt MqttClient;
|
||||
|
||||
bool MqttIsConnected()
|
||||
{
|
||||
return MqttClient.Connected();
|
||||
}
|
||||
|
||||
void MqttDisconnect()
|
||||
{
|
||||
MqttClient.Disconnect();
|
||||
}
|
||||
|
||||
void MqttDisconnectedCb()
|
||||
{
|
||||
MqttDisconnected(MqttClient.State()); // status codes are documented in file mqtt.h as tConnState
|
||||
}
|
||||
|
||||
void MqttSubscribeLib(char *topic)
|
||||
{
|
||||
MqttClient.Subscribe(topic, 0);
|
||||
}
|
||||
|
||||
bool MqttPublishLib(const char* topic, boolean retained)
|
||||
{
|
||||
return MqttClient.Publish(topic, mqtt_data, strlen(mqtt_data), 0, retained);
|
||||
}
|
||||
|
||||
void MqttLoop()
|
||||
{
|
||||
}
|
||||
|
||||
#elif (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT) /**********************************************/
|
||||
|
||||
#include <MQTTClient.h>
|
||||
MQTTClient MqttClient(MQTT_MAX_PACKET_SIZE);
|
||||
|
||||
bool MqttIsConnected()
|
||||
{
|
||||
return MqttClient.connected();
|
||||
}
|
||||
|
||||
void MqttDisconnect()
|
||||
{
|
||||
MqttClient.disconnect();
|
||||
}
|
||||
|
||||
/*
|
||||
void MqttMyDataCb(MQTTClient* client, char* topic, char* data, int data_len)
|
||||
//void MqttMyDataCb(MQTTClient *client, char topic[], char data[], int data_len)
|
||||
{
|
||||
// MqttDataHandler((char*)topic, (byte*)data, data_len);
|
||||
}
|
||||
*/
|
||||
|
||||
void MqttMyDataCb(String &topic, String &data)
|
||||
{
|
||||
MqttDataHandler((char*)topic.c_str(), (byte*)data.c_str(), data.length());
|
||||
}
|
||||
|
||||
void MqttSubscribeLib(char *topic)
|
||||
{
|
||||
MqttClient.subscribe(topic, 0);
|
||||
}
|
||||
|
||||
bool MqttPublishLib(const char* topic, boolean retained)
|
||||
{
|
||||
return MqttClient.publish(topic, mqtt_data, strlen(mqtt_data), retained, 0);
|
||||
}
|
||||
|
||||
void MqttLoop()
|
||||
{
|
||||
MqttClient.loop();
|
||||
// delay(10);
|
||||
}
|
||||
|
||||
#endif // MQTT_LIBRARY_TYPE
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
int MqttLibraryType()
|
||||
{
|
||||
return (int)MQTT_LIBRARY_TYPE;
|
||||
}
|
||||
|
||||
void MqttRetryCounter(uint8_t value)
|
||||
{
|
||||
mqtt_retry_counter = value;
|
||||
}
|
||||
|
||||
void MqttSubscribe(char *topic)
|
||||
{
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_SUBSCRIBE_TO " %s"), topic);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
MqttSubscribeLib(topic);
|
||||
}
|
||||
|
||||
void MqttPublishDirect(const char* topic, boolean retained)
|
||||
{
|
||||
char sretained[CMDSZ];
|
||||
char slog_type[10];
|
||||
|
||||
ShowFreeMem(PSTR("MqttPublishDirect"));
|
||||
|
||||
sretained[0] = '\0';
|
||||
snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_RESULT));
|
||||
|
||||
if (Settings.flag.mqtt_enabled) {
|
||||
if (MqttIsConnected()) {
|
||||
if (MqttPublishLib(topic, retained)) {
|
||||
snprintf_P(slog_type, sizeof(slog_type), PSTR(D_LOG_MQTT));
|
||||
if (retained) {
|
||||
snprintf_P(sretained, sizeof(sretained), PSTR(" (" D_RETAINED ")"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s%s = %s"), slog_type, (Settings.flag.mqtt_enabled) ? topic : strrchr(topic,'/')+1, mqtt_data);
|
||||
if (strlen(log_data) >= (sizeof(log_data) - strlen(sretained) -1)) {
|
||||
log_data[sizeof(log_data) - strlen(sretained) -5] = '\0';
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s ..."), log_data);
|
||||
}
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s%s"), log_data, sretained);
|
||||
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
if (Settings.ledstate &0x04) {
|
||||
blinks++;
|
||||
}
|
||||
}
|
||||
|
||||
void MqttPublish(const char* topic, boolean retained)
|
||||
{
|
||||
char *me;
|
||||
|
||||
if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1])) {
|
||||
me = strstr(topic,Settings.mqtt_prefix[0]);
|
||||
if (me == topic) {
|
||||
mqtt_cmnd_publish += 3;
|
||||
}
|
||||
}
|
||||
MqttPublishDirect(topic, retained);
|
||||
}
|
||||
|
||||
void MqttPublish(const char* topic)
|
||||
{
|
||||
MqttPublish(topic, false);
|
||||
}
|
||||
|
||||
void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic, boolean retained)
|
||||
{
|
||||
/* prefix 0 = cmnd using subtopic
|
||||
* prefix 1 = stat using subtopic
|
||||
* prefix 2 = tele using subtopic
|
||||
* prefix 4 = cmnd using subtopic or RESULT
|
||||
* prefix 5 = stat using subtopic or RESULT
|
||||
* prefix 6 = tele using subtopic or RESULT
|
||||
*/
|
||||
char romram[33];
|
||||
char stopic[TOPSZ];
|
||||
|
||||
snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings.flag.mqtt_response) ? S_RSLT_RESULT : subtopic);
|
||||
for (byte i = 0; i < strlen(romram); i++) {
|
||||
romram[i] = toupper(romram[i]);
|
||||
}
|
||||
prefix &= 3;
|
||||
GetTopic_P(stopic, prefix, mqtt_topic, romram);
|
||||
MqttPublish(stopic, retained);
|
||||
}
|
||||
|
||||
void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic)
|
||||
{
|
||||
MqttPublishPrefixTopic_P(prefix, subtopic, false);
|
||||
}
|
||||
|
||||
void MqttPublishPowerState(byte device)
|
||||
{
|
||||
char stopic[TOPSZ];
|
||||
char scommand[33];
|
||||
|
||||
if ((device < 1) || (device > devices_present)) { device = 1; }
|
||||
|
||||
if ((SONOFF_IFAN02 == Settings.module) && (device > 1)) {
|
||||
if (GetFanspeed() < 4) { // 4 occurs when fanspeed is 3 and RC button 2 is pressed
|
||||
snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED));
|
||||
GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, scommand, GetFanspeed());
|
||||
MqttPublish(stopic);
|
||||
}
|
||||
} else {
|
||||
GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable);
|
||||
GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(power, device -1)));
|
||||
MqttPublish(stopic);
|
||||
|
||||
GetTopic_P(stopic, STAT, mqtt_topic, scommand);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(bitRead(power, device -1)));
|
||||
MqttPublish(stopic, Settings.flag.mqtt_power_retain);
|
||||
}
|
||||
}
|
||||
|
||||
void MqttPublishPowerBlinkState(byte device)
|
||||
{
|
||||
char scommand[33];
|
||||
|
||||
if ((device < 1) || (device > devices_present)) {
|
||||
device = 1;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_JSON_BLINK " %s\"}"),
|
||||
GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable), GetStateText(bitRead(blink_mask, device -1)));
|
||||
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, S_RSLT_POWER);
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void MqttDisconnected(int state)
|
||||
{
|
||||
mqtt_connected = false;
|
||||
mqtt_retry_counter = Settings.mqtt_retry;
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND),
|
||||
Settings.mqtt_host, Settings.mqtt_port, state, mqtt_retry_counter);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
rules_flag.mqtt_disconnected = 1;
|
||||
}
|
||||
|
||||
void MqttConnected()
|
||||
{
|
||||
char stopic[TOPSZ];
|
||||
|
||||
if (Settings.flag.mqtt_enabled) {
|
||||
AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_CONNECTED));
|
||||
mqtt_connected = true;
|
||||
mqtt_retry_counter = 0;
|
||||
|
||||
GetTopic_P(stopic, TELE, mqtt_topic, S_LWT);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_ONLINE));
|
||||
MqttPublish(stopic, true);
|
||||
|
||||
// Satisfy iobroker (#299)
|
||||
mqtt_data[0] = '\0';
|
||||
MqttPublishPrefixTopic_P(CMND, S_RSLT_POWER);
|
||||
|
||||
GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#"));
|
||||
MqttSubscribe(stopic);
|
||||
if (strstr(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != NULL) {
|
||||
GetTopic_P(stopic, CMND, Settings.mqtt_grptopic, PSTR("#"));
|
||||
MqttSubscribe(stopic);
|
||||
fallback_topic_flag = 1;
|
||||
GetTopic_P(stopic, CMND, mqtt_client, PSTR("#"));
|
||||
fallback_topic_flag = 0;
|
||||
MqttSubscribe(stopic);
|
||||
}
|
||||
|
||||
XdrvCall(FUNC_MQTT_SUBSCRIBE);
|
||||
}
|
||||
|
||||
if (mqtt_initial_connection_state) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"),
|
||||
my_module.name, my_version, mqtt_client, Settings.mqtt_grptopic);
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1"));
|
||||
#ifdef USE_WEBSERVER
|
||||
if (Settings.webserver) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"),
|
||||
(2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str());
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2"));
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"),
|
||||
(GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str());
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3"));
|
||||
for (byte i = 1; i <= devices_present; i++) {
|
||||
MqttPublishPowerState(i);
|
||||
if (SONOFF_IFAN02 == Settings.module) { break; } // Only report status of light relay
|
||||
}
|
||||
if (Settings.tele_period) { tele_period = Settings.tele_period -9; } // Enable TelePeriod in 9 seconds
|
||||
rules_flag.system_boot = 1;
|
||||
XdrvCall(FUNC_MQTT_INIT);
|
||||
}
|
||||
mqtt_initial_connection_state = 0;
|
||||
rules_flag.mqtt_connected = 1;
|
||||
global_state.mqtt_down = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_MQTT_TLS
|
||||
boolean MqttCheckTls()
|
||||
{
|
||||
char fingerprint1[60];
|
||||
char fingerprint2[60];
|
||||
boolean result = false;
|
||||
|
||||
fingerprint1[0] = '\0';
|
||||
fingerprint2[0] = '\0';
|
||||
for (byte i = 0; i < sizeof(Settings.mqtt_fingerprint[0]); i++) {
|
||||
snprintf_P(fingerprint1, sizeof(fingerprint1), PSTR("%s%s%02X"), fingerprint1, (i) ? " " : "", Settings.mqtt_fingerprint[0][i]);
|
||||
snprintf_P(fingerprint2, sizeof(fingerprint2), PSTR("%s%s%02X"), fingerprint2, (i) ? " " : "", Settings.mqtt_fingerprint[1][i]);
|
||||
}
|
||||
|
||||
AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_FINGERPRINT));
|
||||
|
||||
//#ifdef ARDUINO_ESP8266_RELEASE_2_4_1
|
||||
EspClient = WiFiClientSecure(); // Wifi Secure Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497)
|
||||
//#endif
|
||||
|
||||
if (!EspClient.connect(Settings.mqtt_host, Settings.mqtt_port)) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_TLS_CONNECT_FAILED_TO " %s:%d. " D_RETRY_IN " %d " D_UNIT_SECOND),
|
||||
Settings.mqtt_host, Settings.mqtt_port, mqtt_retry_counter);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
} else {
|
||||
if (EspClient.verify(fingerprint1, Settings.mqtt_host)) {
|
||||
AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "1"));
|
||||
result = true;
|
||||
}
|
||||
else if (EspClient.verify(fingerprint2, Settings.mqtt_host)) {
|
||||
AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_VERIFIED "2"));
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
if (!result) AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_FAILED));
|
||||
EspClient.stop();
|
||||
yield();
|
||||
return result;
|
||||
}
|
||||
#endif // USE_MQTT_TLS
|
||||
|
||||
void MqttReconnect()
|
||||
{
|
||||
char stopic[TOPSZ];
|
||||
|
||||
if (!Settings.flag.mqtt_enabled) {
|
||||
MqttConnected();
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(USE_WEBSERVER) && defined(USE_EMULATION)
|
||||
UdpDisconnect();
|
||||
#endif // USE_EMULATION
|
||||
|
||||
AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION));
|
||||
|
||||
mqtt_connected = false;
|
||||
mqtt_retry_counter = Settings.mqtt_retry;
|
||||
global_state.mqtt_down = 1;
|
||||
|
||||
#ifndef USE_MQTT_TLS
|
||||
#ifdef USE_DISCOVERY
|
||||
#ifdef MQTT_HOST_DISCOVERY
|
||||
if (!strlen(Settings.mqtt_host)) {
|
||||
MdnsDiscoverMqttServer();
|
||||
}
|
||||
#endif // MQTT_HOST_DISCOVERY
|
||||
#endif // USE_DISCOVERY
|
||||
#endif // USE_MQTT_TLS
|
||||
|
||||
char *mqtt_user = NULL;
|
||||
char *mqtt_pwd = NULL;
|
||||
if (strlen(Settings.mqtt_user) > 0) mqtt_user = Settings.mqtt_user;
|
||||
if (strlen(Settings.mqtt_pwd) > 0) mqtt_pwd = Settings.mqtt_pwd;
|
||||
|
||||
GetTopic_P(stopic, TELE, mqtt_topic, S_LWT);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_OFFLINE);
|
||||
|
||||
//#ifdef ARDUINO_ESP8266_RELEASE_2_4_1
|
||||
#ifdef USE_MQTT_TLS
|
||||
EspClient = WiFiClientSecure(); // Wifi Secure Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497)
|
||||
#else
|
||||
EspClient = WiFiClient(); // Wifi Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497)
|
||||
#endif
|
||||
//#endif
|
||||
|
||||
if (2 == mqtt_initial_connection_state) { // Executed once just after power on and wifi is connected
|
||||
#ifdef USE_MQTT_TLS
|
||||
if (!MqttCheckTls()) return;
|
||||
#endif // USE_MQTT_TLS
|
||||
|
||||
#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT)
|
||||
MqttClient.InitConnection(Settings.mqtt_host, Settings.mqtt_port);
|
||||
MqttClient.InitClient(mqtt_client, mqtt_user, mqtt_pwd, MQTT_KEEPALIVE);
|
||||
MqttClient.InitLWT(stopic, mqtt_data, 1, true);
|
||||
MqttClient.OnConnected(MqttConnected);
|
||||
MqttClient.OnDisconnected(MqttDisconnectedCb);
|
||||
MqttClient.OnData(MqttDataHandler);
|
||||
#elif (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT)
|
||||
MqttClient.begin(Settings.mqtt_host, Settings.mqtt_port, EspClient);
|
||||
MqttClient.setWill(stopic, mqtt_data, true, 1);
|
||||
MqttClient.setOptions(MQTT_KEEPALIVE, true, MQTT_TIMEOUT);
|
||||
// MqttClient.onMessageAdvanced(MqttMyDataCb);
|
||||
MqttClient.onMessage(MqttMyDataCb);
|
||||
#endif
|
||||
|
||||
mqtt_initial_connection_state = 1;
|
||||
}
|
||||
|
||||
#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT)
|
||||
MqttClient.setCallback(MqttDataHandler);
|
||||
MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port);
|
||||
if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data)) {
|
||||
MqttConnected();
|
||||
} else {
|
||||
MqttDisconnected(MqttClient.state()); // status codes are documented here http://pubsubclient.knolleary.net/api.html#state
|
||||
}
|
||||
#elif (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT)
|
||||
MqttClient.Connect();
|
||||
#elif (MQTT_LIBRARY_TYPE == MQTT_ARDUINOMQTT)
|
||||
if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd)) {
|
||||
MqttConnected();
|
||||
} else {
|
||||
MqttDisconnected(MqttClient.lastError()); // status codes are documented here https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L11
|
||||
}
|
||||
#endif // MQTT_LIBRARY_TYPE
|
||||
}
|
||||
|
||||
void MqttCheck()
|
||||
{
|
||||
if (Settings.flag.mqtt_enabled) {
|
||||
if (!MqttIsConnected()) {
|
||||
global_state.mqtt_down = 1;
|
||||
if (!mqtt_retry_counter) {
|
||||
MqttReconnect();
|
||||
} else {
|
||||
mqtt_retry_counter--;
|
||||
}
|
||||
} else {
|
||||
global_state.mqtt_down = 0;
|
||||
}
|
||||
} else {
|
||||
global_state.mqtt_down = 0;
|
||||
if (mqtt_initial_connection_state) MqttReconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
bool MqttCommand()
|
||||
{
|
||||
char command [CMDSZ];
|
||||
bool serviced = true;
|
||||
char stemp1[TOPSZ];
|
||||
char scommand[CMDSZ];
|
||||
uint16_t i;
|
||||
|
||||
uint16_t index = XdrvMailbox.index;
|
||||
uint16_t data_len = XdrvMailbox.data_len;
|
||||
uint16_t payload16 = XdrvMailbox.payload16;
|
||||
int16_t payload = XdrvMailbox.payload;
|
||||
uint8_t grpflg = XdrvMailbox.grpflg;
|
||||
char *type = XdrvMailbox.topic;
|
||||
char *dataBuf = XdrvMailbox.data;
|
||||
|
||||
int command_code = GetCommandCode(command, sizeof(command), type, kMqttCommands);
|
||||
if (-1 == command_code) {
|
||||
serviced = false; // Unknown command
|
||||
}
|
||||
else if (CMND_MQTTHOST == command_code) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_host))) {
|
||||
strlcpy(Settings.mqtt_host, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_HOST : dataBuf, sizeof(Settings.mqtt_host));
|
||||
restart_flag = 2;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_host);
|
||||
}
|
||||
else if (CMND_MQTTPORT == command_code) {
|
||||
if (payload16 > 0) {
|
||||
Settings.mqtt_port = (1 == payload16) ? MQTT_PORT : payload16;
|
||||
restart_flag = 2;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.mqtt_port);
|
||||
}
|
||||
else if (CMND_MQTTRETRY == command_code) {
|
||||
if ((payload >= MQTT_RETRY_SECS) && (payload < 32001)) {
|
||||
Settings.mqtt_retry = payload;
|
||||
mqtt_retry_counter = Settings.mqtt_retry;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.mqtt_retry);
|
||||
}
|
||||
else if ((CMND_STATETEXT == command_code) && (index > 0) && (index <= 4)) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.state_text[0]))) {
|
||||
for(i = 0; i <= data_len; i++) {
|
||||
if (dataBuf[i] == ' ') dataBuf[i] = '_';
|
||||
}
|
||||
strlcpy(Settings.state_text[index -1], dataBuf, sizeof(Settings.state_text[0]));
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1));
|
||||
}
|
||||
#ifdef USE_MQTT_TLS
|
||||
else if ((CMND_MQTTFINGERPRINT == command_code) && (index > 0) && (index <= 2)) {
|
||||
char fingerprint[60];
|
||||
if ((data_len > 0) && (data_len < sizeof(fingerprint))) {
|
||||
strlcpy(fingerprint, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? (1 == index) ? MQTT_FINGERPRINT1 : MQTT_FINGERPRINT2 : dataBuf, sizeof(fingerprint));
|
||||
char *p = fingerprint;
|
||||
for (byte i = 0; i < 20; i++) {
|
||||
Settings.mqtt_fingerprint[index -1][i] = strtol(p, &p, 16);
|
||||
}
|
||||
restart_flag = 2;
|
||||
}
|
||||
fingerprint[0] = '\0';
|
||||
for (byte i = 0; i < sizeof(Settings.mqtt_fingerprint[index -1]); i++) {
|
||||
snprintf_P(fingerprint, sizeof(fingerprint), PSTR("%s%s%02X"), fingerprint, (i) ? " " : "", Settings.mqtt_fingerprint[index -1][i]);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, fingerprint);
|
||||
}
|
||||
#endif
|
||||
else if ((CMND_MQTTCLIENT == command_code) && !grpflg) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_client))) {
|
||||
strlcpy(Settings.mqtt_client, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_CLIENT_ID : dataBuf, sizeof(Settings.mqtt_client));
|
||||
restart_flag = 2;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_client);
|
||||
}
|
||||
else if (CMND_MQTTUSER == command_code) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_user))) {
|
||||
strlcpy(Settings.mqtt_user, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_USER : dataBuf, sizeof(Settings.mqtt_user));
|
||||
restart_flag = 2;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_user);
|
||||
}
|
||||
else if (CMND_MQTTPASSWORD == command_code) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_pwd))) {
|
||||
strlcpy(Settings.mqtt_pwd, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_PASS : dataBuf, sizeof(Settings.mqtt_pwd));
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_pwd);
|
||||
restart_flag = 2;
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_ASTERIX, command);
|
||||
}
|
||||
}
|
||||
else if (CMND_FULLTOPIC == command_code) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_fulltopic))) {
|
||||
MakeValidMqtt(1, dataBuf);
|
||||
if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT);
|
||||
strlcpy(stemp1, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_FULLTOPIC : dataBuf, sizeof(stemp1));
|
||||
if (strcmp(stemp1, Settings.mqtt_fulltopic)) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : "");
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic
|
||||
strlcpy(Settings.mqtt_fulltopic, stemp1, sizeof(Settings.mqtt_fulltopic));
|
||||
restart_flag = 2;
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_fulltopic);
|
||||
}
|
||||
else if ((CMND_PREFIX == command_code) && (index > 0) && (index <= 3)) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_prefix[0]))) {
|
||||
MakeValidMqtt(0, dataBuf);
|
||||
strlcpy(Settings.mqtt_prefix[index -1], (SC_DEFAULT == Shortcut(dataBuf)) ? (1==index)?SUB_PREFIX:(2==index)?PUB_PREFIX:PUB_PREFIX2 : dataBuf, sizeof(Settings.mqtt_prefix[0]));
|
||||
// if (Settings.mqtt_prefix[index -1][strlen(Settings.mqtt_prefix[index -1])] == '/') Settings.mqtt_prefix[index -1][strlen(Settings.mqtt_prefix[index -1])] = 0;
|
||||
restart_flag = 2;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mqtt_prefix[index -1]);
|
||||
}
|
||||
else if (CMND_PUBLISH == command_code) {
|
||||
if (data_len > 0) {
|
||||
char *mqtt_part = strtok(dataBuf, " ");
|
||||
if (mqtt_part) {
|
||||
snprintf(stemp1, sizeof(stemp1), mqtt_part);
|
||||
mqtt_part = strtok(NULL, " ");
|
||||
if (mqtt_part) {
|
||||
snprintf(mqtt_data, sizeof(mqtt_data), mqtt_part);
|
||||
} else {
|
||||
mqtt_data[0] = '\0';
|
||||
}
|
||||
MqttPublishDirect(stemp1, (index == 2));
|
||||
// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
|
||||
mqtt_data[0] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (CMND_GROUPTOPIC == command_code) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_grptopic))) {
|
||||
MakeValidMqtt(0, dataBuf);
|
||||
if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT);
|
||||
strlcpy(Settings.mqtt_grptopic, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_GRPTOPIC : dataBuf, sizeof(Settings.mqtt_grptopic));
|
||||
restart_flag = 2;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_grptopic);
|
||||
}
|
||||
else if ((CMND_TOPIC == command_code) && !grpflg) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_topic))) {
|
||||
MakeValidMqtt(0, dataBuf);
|
||||
if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT);
|
||||
strlcpy(stemp1, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_TOPIC : dataBuf, sizeof(stemp1));
|
||||
if (strcmp(stemp1, Settings.mqtt_topic)) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : "");
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic
|
||||
strlcpy(Settings.mqtt_topic, stemp1, sizeof(Settings.mqtt_topic));
|
||||
restart_flag = 2;
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_topic);
|
||||
}
|
||||
else if ((CMND_BUTTONTOPIC == command_code) && !grpflg) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.button_topic))) {
|
||||
MakeValidMqtt(0, dataBuf);
|
||||
if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT);
|
||||
switch (Shortcut(dataBuf)) {
|
||||
case SC_CLEAR: strlcpy(Settings.button_topic, "", sizeof(Settings.button_topic)); break;
|
||||
case SC_DEFAULT: strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic)); break;
|
||||
case SC_USER: strlcpy(Settings.button_topic, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic)); break;
|
||||
default: strlcpy(Settings.button_topic, dataBuf, sizeof(Settings.button_topic));
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.button_topic);
|
||||
}
|
||||
else if (CMND_SWITCHTOPIC == command_code) {
|
||||
if ((data_len > 0) && (data_len < sizeof(Settings.switch_topic))) {
|
||||
MakeValidMqtt(0, dataBuf);
|
||||
if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT);
|
||||
switch (Shortcut(dataBuf)) {
|
||||
case SC_CLEAR: strlcpy(Settings.switch_topic, "", sizeof(Settings.switch_topic)); break;
|
||||
case SC_DEFAULT: strlcpy(Settings.switch_topic, mqtt_topic, sizeof(Settings.switch_topic)); break;
|
||||
case SC_USER: strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic)); break;
|
||||
default: strlcpy(Settings.switch_topic, dataBuf, sizeof(Settings.switch_topic));
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.switch_topic);
|
||||
}
|
||||
else if (CMND_BUTTONRETAIN == command_code) {
|
||||
if ((payload >= 0) && (payload <= 1)) {
|
||||
if (!payload) {
|
||||
for(i = 1; i <= MAX_KEYS; i++) {
|
||||
SendKey(0, i, 9); // Clear MQTT retain in broker
|
||||
}
|
||||
}
|
||||
Settings.flag.mqtt_button_retain = payload;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_button_retain));
|
||||
}
|
||||
else if (CMND_SWITCHRETAIN == command_code) {
|
||||
if ((payload >= 0) && (payload <= 1)) {
|
||||
if (!payload) {
|
||||
for(i = 1; i <= MAX_SWITCHES; i++) {
|
||||
SendKey(1, i, 9); // Clear MQTT retain in broker
|
||||
}
|
||||
}
|
||||
Settings.flag.mqtt_switch_retain = payload;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_switch_retain));
|
||||
}
|
||||
else if (CMND_POWERRETAIN == command_code) {
|
||||
if ((payload >= 0) && (payload <= 1)) {
|
||||
if (!payload) {
|
||||
for(i = 1; i <= devices_present; i++) { // Clear MQTT retain in broker
|
||||
GetTopic_P(stemp1, STAT, mqtt_topic, GetPowerDevice(scommand, i, sizeof(scommand), Settings.flag.device_index_enable));
|
||||
mqtt_data[0] = '\0';
|
||||
MqttPublish(stemp1, Settings.flag.mqtt_power_retain);
|
||||
}
|
||||
}
|
||||
Settings.flag.mqtt_power_retain = payload;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_power_retain));
|
||||
}
|
||||
else if (CMND_SENSORRETAIN == command_code) {
|
||||
if ((payload >= 0) && (payload <= 1)) {
|
||||
if (!payload) {
|
||||
mqtt_data[0] = '\0';
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain);
|
||||
}
|
||||
Settings.flag.mqtt_sensor_retain = payload;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_sensor_retain));
|
||||
}
|
||||
else serviced = false; // Unknown command
|
||||
|
||||
return serviced;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
|
||||
#define WEB_HANDLE_MQTT "mq"
|
||||
|
||||
const char S_CONFIGURE_MQTT[] PROGMEM = D_CONFIGURE_MQTT;
|
||||
|
||||
const char HTTP_BTN_MENU_MQTT[] PROGMEM =
|
||||
"<br/><form action='" WEB_HANDLE_MQTT "' method='get'><button>" D_CONFIGURE_MQTT "</button></form>";
|
||||
|
||||
const char HTTP_FORM_MQTT[] PROGMEM =
|
||||
"<fieldset><legend><b> " D_MQTT_PARAMETERS " </b></legend><form method='get' action='" WEB_HANDLE_MQTT "'>"
|
||||
"<br/><b>" D_HOST "</b> (" MQTT_HOST ")<br/><input id='mh' name='mh' placeholder='" MQTT_HOST" ' value='{m1'><br/>"
|
||||
"<br/><b>" D_PORT "</b> (" STR(MQTT_PORT) ")<br/><input id='ml' name='ml' placeholder='" STR(MQTT_PORT) "' value='{m2'><br/>"
|
||||
"<br/><b>" D_CLIENT "</b> ({m0)<br/><input id='mc' name='mc' placeholder='" MQTT_CLIENT_ID "' value='{m3'><br/>"
|
||||
"<br/><b>" D_USER "</b> (" MQTT_USER ")<br/><input id='mu' name='mu' placeholder='" MQTT_USER "' value='{m4'><br/>"
|
||||
"<br/><b>" D_PASSWORD "</b><br/><input id='mp' name='mp' type='password' placeholder='" MQTT_PASS "' value='{m5'><br/>"
|
||||
"<br/><b>" D_TOPIC "</b> = %topic% (" MQTT_TOPIC ")<br/><input id='mt' name='mt' placeholder='" MQTT_TOPIC" ' value='{m6'><br/>"
|
||||
"<br/><b>" D_FULL_TOPIC "</b> (" MQTT_FULLTOPIC ")<br/><input id='mf' name='mf' placeholder='" MQTT_FULLTOPIC" ' value='{m7'><br/>";
|
||||
|
||||
void HandleMqttConfiguration()
|
||||
{
|
||||
if (HttpUser()) { return; }
|
||||
if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
|
||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_MQTT);
|
||||
|
||||
if (WebServer->hasArg("save")) {
|
||||
MqttSaveSettings();
|
||||
WaitForRestart("");
|
||||
return;
|
||||
}
|
||||
|
||||
String page = FPSTR(HTTP_HEAD);
|
||||
page.replace(F("{v}"), FPSTR(S_CONFIGURE_MQTT));
|
||||
page += FPSTR(HTTP_HEAD_STYLE);
|
||||
|
||||
page += FPSTR(HTTP_FORM_MQTT);
|
||||
char str[sizeof(Settings.mqtt_client)];
|
||||
page.replace(F("{m0"), Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)));
|
||||
page.replace(F("{m1"), Settings.mqtt_host);
|
||||
page.replace(F("{m2"), String(Settings.mqtt_port));
|
||||
page.replace(F("{m3"), Settings.mqtt_client);
|
||||
page.replace(F("{m4"), (Settings.mqtt_user[0] == '\0')?"0":Settings.mqtt_user);
|
||||
page.replace(F("{m5"), (Settings.mqtt_pwd[0] == '\0')?"0":Settings.mqtt_pwd);
|
||||
page.replace(F("{m6"), Settings.mqtt_topic);
|
||||
page.replace(F("{m7"), Settings.mqtt_fulltopic);
|
||||
|
||||
page += FPSTR(HTTP_FORM_END);
|
||||
page += FPSTR(HTTP_BTN_CONF);
|
||||
ShowPage(page);
|
||||
}
|
||||
|
||||
void MqttSaveSettings()
|
||||
{
|
||||
char tmp[100];
|
||||
char stemp[TOPSZ];
|
||||
char stemp2[TOPSZ];
|
||||
|
||||
WebGetArg("mt", tmp, sizeof(tmp));
|
||||
strlcpy(stemp, (!strlen(tmp)) ? MQTT_TOPIC : tmp, sizeof(stemp));
|
||||
MakeValidMqtt(0, stemp);
|
||||
WebGetArg("mf", tmp, sizeof(tmp));
|
||||
strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2));
|
||||
MakeValidMqtt(1,stemp2);
|
||||
if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : "");
|
||||
MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic
|
||||
}
|
||||
strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic));
|
||||
strlcpy(Settings.mqtt_fulltopic, stemp2, sizeof(Settings.mqtt_fulltopic));
|
||||
WebGetArg("mh", tmp, sizeof(tmp));
|
||||
strlcpy(Settings.mqtt_host, (!strlen(tmp)) ? MQTT_HOST : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_host));
|
||||
WebGetArg("ml", tmp, sizeof(tmp));
|
||||
Settings.mqtt_port = (!strlen(tmp)) ? MQTT_PORT : atoi(tmp);
|
||||
WebGetArg("mc", tmp, sizeof(tmp));
|
||||
strlcpy(Settings.mqtt_client, (!strlen(tmp)) ? MQTT_CLIENT_ID : tmp, sizeof(Settings.mqtt_client));
|
||||
WebGetArg("mu", tmp, sizeof(tmp));
|
||||
strlcpy(Settings.mqtt_user, (!strlen(tmp)) ? MQTT_USER : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_user));
|
||||
WebGetArg("mp", tmp, sizeof(tmp));
|
||||
strlcpy(Settings.mqtt_pwd, (!strlen(tmp)) ? MQTT_PASS : (!strcmp(tmp,"0")) ? "" : tmp, sizeof(Settings.mqtt_pwd));
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CMND_MQTTHOST " %s, " D_CMND_MQTTPORT " %d, " D_CMND_MQTTCLIENT " %s, " D_CMND_MQTTUSER " %s, " D_CMND_MQTTPASSWORD " %s, " D_CMND_TOPIC " %s, " D_CMND_FULLTOPIC " %s"),
|
||||
Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, Settings.mqtt_user, Settings.mqtt_pwd, Settings.mqtt_topic, Settings.mqtt_fulltopic);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XDRV_02
|
||||
|
||||
boolean Xdrv02(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (Settings.flag.mqtt_enabled) {
|
||||
switch (function) {
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_ADD_BUTTON:
|
||||
strncat_P(mqtt_data, HTTP_BTN_MENU_MQTT, sizeof(mqtt_data));
|
||||
break;
|
||||
case FUNC_WEB_ADD_HANDLER:
|
||||
WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
case FUNC_LOOP:
|
||||
MqttLoop();
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = MqttCommand();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
@ -19,22 +19,6 @@
|
||||
|
||||
#ifdef USE_DOMOTICZ
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_FORM_DOMOTICZ[] PROGMEM =
|
||||
"<fieldset><legend><b> " D_DOMOTICZ_PARAMETERS " </b></legend><form method='post' action='sv'>"
|
||||
"<input id='w' name='w' value='4,1' hidden>"
|
||||
"<br/><table>";
|
||||
const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM =
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_IDX " {1</b></td><td style='width:70px'><input id='r{1' name='r{1' placeholder='0' value='{2'></td></tr>"
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_KEY_IDX " {1</b></td><td style='width:70px'><input id='k{1' name='k{1' placeholder='0' value='{3'></td></tr>";
|
||||
const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM =
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SWITCH_IDX " {1</b></td><td style='width:70px'><input id='s{1' name='s{1' placeholder='0' value='{4'></td></tr>";
|
||||
const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM =
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SENSOR_IDX " {1</b> {2</td><td style='width:70px'><input id='l{1' name='l{1' placeholder='0' value='{5'></td></tr>";
|
||||
const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM =
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_UPDATE_TIMER "</b> (" STR(DOMOTICZ_UPDATE_TIMER) ")</td><td style='width:70px'><input id='ut' name='ut' placeholder='" STR(DOMOTICZ_UPDATE_TIMER) "' value='{6'</td></tr>";
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}";
|
||||
|
||||
enum DomoticzCommands { CMND_IDX, CMND_KEYIDX, CMND_SWITCHIDX, CMND_SENSORIDX, CMND_UPDATETIMER };
|
||||
@ -386,14 +370,39 @@ void DomoticzSensorPowerEnergy(int power, char *energy)
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
|
||||
#define WEB_HANDLE_DOMOTICZ "dm"
|
||||
|
||||
const char S_CONFIGURE_DOMOTICZ[] PROGMEM = D_CONFIGURE_DOMOTICZ;
|
||||
|
||||
const char HTTP_BTN_MENU_DOMOTICZ[] PROGMEM =
|
||||
"<br/><form action='" WEB_HANDLE_DOMOTICZ "' method='get'><button>" D_CONFIGURE_DOMOTICZ "</button></form>";
|
||||
|
||||
const char HTTP_FORM_DOMOTICZ[] PROGMEM =
|
||||
"<fieldset><legend><b> " D_DOMOTICZ_PARAMETERS " </b></legend><form method='post' action='" WEB_HANDLE_DOMOTICZ "'>"
|
||||
"<br/><table>";
|
||||
const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM =
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_IDX " {1</b></td><td style='width:70px'><input id='r{1' name='r{1' placeholder='0' value='{2'></td></tr>"
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_KEY_IDX " {1</b></td><td style='width:70px'><input id='k{1' name='k{1' placeholder='0' value='{3'></td></tr>";
|
||||
const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM =
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SWITCH_IDX " {1</b></td><td style='width:70px'><input id='s{1' name='s{1' placeholder='0' value='{4'></td></tr>";
|
||||
const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM =
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_SENSOR_IDX " {1</b> {2</td><td style='width:70px'><input id='l{1' name='l{1' placeholder='0' value='{5'></td></tr>";
|
||||
const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM =
|
||||
"<tr><td style='width:260px'><b>" D_DOMOTICZ_UPDATE_TIMER "</b> (" STR(DOMOTICZ_UPDATE_TIMER) ")</td><td style='width:70px'><input id='ut' name='ut' placeholder='" STR(DOMOTICZ_UPDATE_TIMER) "' value='{6'</td></tr>";
|
||||
|
||||
void HandleDomoticzConfiguration()
|
||||
{
|
||||
if (HttpUser()) { return; }
|
||||
if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
|
||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_DOMOTICZ);
|
||||
|
||||
if (WebServer->hasArg("save")) {
|
||||
DomoticzSaveSettings();
|
||||
WaitForRestart("");
|
||||
return;
|
||||
}
|
||||
|
||||
char stemp[32];
|
||||
|
||||
String page = FPSTR(HTTP_HEAD);
|
||||
@ -474,6 +483,14 @@ boolean Xdrv07(byte function)
|
||||
|
||||
if (Settings.flag.mqtt_enabled) {
|
||||
switch (function) {
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_ADD_BUTTON:
|
||||
strncat_P(mqtt_data, HTTP_BTN_MENU_DOMOTICZ, sizeof(mqtt_data));
|
||||
break;
|
||||
case FUNC_WEB_ADD_HANDLER:
|
||||
WebServer->on("/" WEB_HANDLE_DOMOTICZ, HandleDomoticzConfiguration);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
case FUNC_COMMAND:
|
||||
result = DomoticzCommand();
|
||||
break;
|
||||
|
@ -510,6 +510,14 @@ boolean TimerCommand()
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
#ifdef USE_TIMERS_WEB
|
||||
|
||||
#define WEB_HANDLE_TIMER "tm"
|
||||
|
||||
const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER;
|
||||
|
||||
const char HTTP_BTN_MENU_TIMER[] PROGMEM =
|
||||
"<br/><form action='" WEB_HANDLE_TIMER "' method='get'><button>" D_CONFIGURE_TIMER "</button></form>";
|
||||
|
||||
const char HTTP_TIMER_SCRIPT[] PROGMEM =
|
||||
"var pt=[],ct=99;"
|
||||
"function qs(s){" // Alias to save code space
|
||||
@ -639,8 +647,7 @@ const char HTTP_TIMER_STYLE[] PROGMEM =
|
||||
#endif
|
||||
"</style>";
|
||||
const char HTTP_FORM_TIMER[] PROGMEM =
|
||||
"<fieldset style='min-width:470px;text-align:center;'><legend style='text-align:left;'><b> " D_TIMER_PARAMETERS " </b></legend><form method='post' action='sv'>"
|
||||
"<input id='w' name='w' value='7,0' hidden>"
|
||||
"<fieldset style='min-width:470px;text-align:center;'><legend style='text-align:left;'><b> " D_TIMER_PARAMETERS " </b></legend><form method='post' action='" WEB_HANDLE_TIMER "'>"
|
||||
"<br/><input style='width:5%;' id='e0' name='e0' type='checkbox'{e0><b>" D_TIMER_ENABLE "</b><br/><br/><hr/>"
|
||||
"<input id='t0' name='t0' value='";
|
||||
const char HTTP_FORM_TIMER1[] PROGMEM =
|
||||
@ -672,14 +679,18 @@ const char HTTP_FORM_TIMER1[] PROGMEM =
|
||||
const char HTTP_FORM_TIMER2[] PROGMEM =
|
||||
"type='submit' onclick='st();this.form.submit();'";
|
||||
|
||||
const char S_CONFIGURE_TIMER[] PROGMEM = D_CONFIGURE_TIMER;
|
||||
|
||||
void HandleTimerConfiguration()
|
||||
{
|
||||
if (HttpUser()) { return; }
|
||||
if (!WebAuthenticate()) { return WebServer->requestAuthentication(); }
|
||||
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_TIMER);
|
||||
|
||||
if (WebServer->hasArg("save")) {
|
||||
TimerSaveSettings();
|
||||
HandleConfiguration();
|
||||
return;
|
||||
}
|
||||
|
||||
String page = FPSTR(HTTP_HEAD);
|
||||
page.replace(F("{v}"), FPSTR(S_CONFIGURE_TIMER));
|
||||
page += FPSTR(HTTP_TIMER_SCRIPT);
|
||||
@ -743,6 +754,20 @@ boolean Xdrv09(byte function)
|
||||
case FUNC_PRE_INIT:
|
||||
TimerSetRandomWindows();
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
#ifdef USE_TIMERS_WEB
|
||||
case FUNC_WEB_ADD_BUTTON:
|
||||
#ifdef USE_RULES
|
||||
strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data));
|
||||
#else
|
||||
if (devices_present) { strncat_P(mqtt_data, HTTP_BTN_MENU_TIMER, sizeof(mqtt_data)); }
|
||||
#endif // USE_RULES
|
||||
break;
|
||||
case FUNC_WEB_ADD_HANDLER:
|
||||
WebServer->on("/" WEB_HANDLE_TIMER, HandleTimerConfiguration);
|
||||
break;
|
||||
#endif // USE_TIMERS_WEB
|
||||
#endif // USE_WEBSERVER
|
||||
case FUNC_EVERY_SECOND:
|
||||
TimerEverySecond();
|
||||
break;
|
||||
|
@ -749,6 +749,9 @@ void KnxSensor(byte sensor_type, float value)
|
||||
#ifdef USE_KNX_WEB_MENU
|
||||
const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX;
|
||||
|
||||
const char HTTP_BTN_MENU_KNX[] PROGMEM =
|
||||
"<br/><form action='kn' method='get'><button>" D_CONFIGURE_KNX "</button></form>";
|
||||
|
||||
const char HTTP_FORM_KNX[] PROGMEM =
|
||||
"<fieldset><legend style='text-align:left;'><b> " D_KNX_PARAMETERS " </b></legend><form method='post' action='kn'>"
|
||||
"<br/><center>"
|
||||
@ -784,7 +787,6 @@ const char HTTP_FORM_KNX_ADD_BTN[] PROGMEM =
|
||||
|
||||
const char HTTP_FORM_KNX_ADD_TABLE_ROW[] PROGMEM =
|
||||
"<tr><td><b>{optex} -> GAfnum / GAarea / GAfdef </b></td>"
|
||||
// "<td><button type='submit' name='btn_del_ga' value='{opval}' style='background-color: #eb1e1e;'> " D_DELETE " </button></td></tr>";
|
||||
"<td><button type='submit' name='btn_del_ga' value='{opval}' class='button bred'> " D_DELETE " </button></td></tr>";
|
||||
|
||||
const char HTTP_FORM_KNX3[] PROGMEM =
|
||||
@ -797,10 +799,8 @@ const char HTTP_FORM_KNX4[] PROGMEM =
|
||||
|
||||
const char HTTP_FORM_KNX_ADD_TABLE_ROW2[] PROGMEM =
|
||||
"<tr><td><b>GAfnum / GAarea / GAfdef -> {optex}</b></td>"
|
||||
// "<td><button type='submit' name='btn_del_cb' value='{opval}' style='background-color: #eb1e1e;'> " D_DELETE " </button></td></tr>";
|
||||
"<td><button type='submit' name='btn_del_cb' value='{opval}' class='button bred'> " D_DELETE " </button></td></tr>";
|
||||
|
||||
|
||||
void HandleKNXConfiguration()
|
||||
{
|
||||
if (HttpUser()) { return; }
|
||||
@ -971,7 +971,7 @@ void HandleKNXConfiguration()
|
||||
}
|
||||
}
|
||||
page += F("</table></center></fieldset>");
|
||||
page += F("<br/><button name='save' type='submit'>" D_SAVE "</button></form></fieldset>");
|
||||
page += F("<br/><button name='save' type='submit' class='button bgrn'>" D_SAVE "</button></form></fieldset>");
|
||||
page += FPSTR(HTTP_BTN_CONF);
|
||||
|
||||
page.replace( F("</script>"),
|
||||
@ -1295,6 +1295,16 @@ boolean Xdrv11(byte function)
|
||||
case FUNC_PRE_INIT:
|
||||
KNX_INIT();
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
#ifdef USE_KNX_WEB_MENU
|
||||
case FUNC_WEB_ADD_BUTTON:
|
||||
strncat_P(mqtt_data, HTTP_BTN_MENU_KNX, sizeof(mqtt_data));
|
||||
break;
|
||||
case FUNC_WEB_ADD_HANDLER:
|
||||
WebServer->on("/kn", HandleKNXConfiguration);
|
||||
break;
|
||||
#endif // USE_KNX_WEB_MENU
|
||||
#endif // USE_WEBSERVER
|
||||
case FUNC_LOOP:
|
||||
knx.loop(); // Process knx events
|
||||
break;
|
||||
|
@ -835,4 +835,18 @@ void HandleHueApi(String *path)
|
||||
else if (path->endsWith("/rules")) HueNotImplemented(path);
|
||||
else HueGlobalConfig(path);
|
||||
}
|
||||
|
||||
void HueWemoAddHandlers()
|
||||
{
|
||||
if (EMUL_WEMO == Settings.flag2.emulation) {
|
||||
WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent);
|
||||
WebServer->on("/eventservice.xml", HandleUpnpService);
|
||||
WebServer->on("/metainfoservice.xml", HandleUpnpMetaService);
|
||||
WebServer->on("/setup.xml", HandleUpnpSetupWemo);
|
||||
}
|
||||
if (EMUL_HUE == Settings.flag2.emulation) {
|
||||
WebServer->on("/description.xml", HandleUpnpSetupHue);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_WEBSERVER && USE_EMULATION
|
||||
|
Loading…
x
Reference in New Issue
Block a user