3.9.11 20170204
* Fix command I2Cscan
* Fix not allowed spaces in Topic, ButtonTopic and SwitchTopic
* Make all TELEMETRY, STATUS and COMMAND message topics unique (#4)
* Advertise command topic to be used by iobroker (#299)
* Fix butten (non)detection if no GPIO_KEY1 is defined (#13)
* Change WeMo serialnumber from 7 decimal chars to 8 hexadecimal chars
(#18)
* Update web page with Build Date/Time, Emulation and mDNS Discovery and
Advertise information (#21)
This commit is contained in:
arendst 2017-02-04 17:09:54 +01:00
parent 7d7d14ae38
commit 213e8d8095
18 changed files with 417 additions and 206 deletions

View File

@ -1,7 +1,7 @@
## Sonoff-Tasmota
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
Current version is **3.9.7** - See ```sonoff/_releasenotes.ino``` for change information.
Current version is **3.9.11** - See ```sonoff/_releasenotes.ino``` for change information.
- This version provides all (Sonoff) modules in one file and starts up with Sonoff Basic.
- Once uploaded select module using the configuration webpage or the commands ```Modules``` and ```Module```.
@ -11,7 +11,7 @@ Current version is **3.9.7** - See ```sonoff/_releasenotes.ino``` for change inf
See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for more information.<br />
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum and more user experience.
Starting with version 2.0.0 the following devices are supported:
The following devices are supported:
- [iTead Sonoff Basic](http://sonoff.itead.cc/en/products/sonoff/sonoff-basic)
- [iTead Sonoff RF](http://sonoff.itead.cc/en/products/sonoff/sonoff-rf)
- [iTead Sonoff SV](https://www.itead.cc/sonoff-sv.html)

Binary file not shown.

View File

@ -1,4 +1,24 @@
/* 3.9.7 20170129
/* 3.9.11 20170204
* Fix command I2Cscan
* Fix not allowed spaces in Topic, ButtonTopic and SwitchTopic
* Make all TELEMETRY, STATUS and COMMAND message topics unique (#4)
* Advertise command topic to be used by iobroker (#299)
* Fix butten (non)detection if no GPIO_KEY1 is defined (#13)
* Change WeMo serialnumber from 7 decimal chars to 8 hexadecimal chars (#18)
* Update web page with Build Date/Time, Emulation and mDNS Discovery and Advertise information (#21)
*
* 3.9.10 20170130
* Add WS2812 Color Type selection (RGB or GRB) to user_config.h (#7)
* Hue api changes to support HUE App(s) (#8)
*
* 3.9.9 20170130
* Add command status 10 showing sensor data
* Fix hlw status messages if hlw is disabled
*
* 3.9.8 20170130
* Remove GPIO07 and GPIO08 from user selectable (#5)
*
* 3.9.7 20170129
* Fix possible WS2812 exceptions when using emulation
* Add command Emulation to dynamic configure Belkin WeMo and Hue Bridge for Alexa
*

View File

@ -10,7 +10,7 @@
* ====================================================
*/
#define VERSION 0x03090700 // 3.9.7
#define VERSION 0x03090B00 // 3.9.11
enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
enum week_t {Last, First, Second, Third, Fourth};
@ -93,7 +93,7 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
#endif
#define APP_BAUDRATE 115200 // Default serial baudrate
#define MAX_STATUS 9
#define MAX_STATUS 10
enum butt_t {PRESSED, NOT_PRESSED};
@ -927,6 +927,15 @@ void mqtt_publish(const char* topic, const char* data)
mqtt_publish(topic, data, false);
}
void mqtt_publish_topic_P(uint8_t prefix, const char* subtopic, const char* data)
{
char romram[16], stopic[TOPSZ];
snprintf_P(romram, sizeof(romram), subtopic);
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/%s"), (prefix) ? PUB_PREFIX2 : PUB_PREFIX, sysCfg.mqtt_topic, romram);
mqtt_publish(stopic, data);
}
void mqtt_publishPowerState(byte device)
{
char stopic[TOPSZ], svalue[MESSZ], sdevice[10];
@ -943,14 +952,13 @@ void mqtt_publishPowerState(byte device)
void mqtt_publishPowerBlinkState(byte device)
{
char stopic[TOPSZ], svalue[MESSZ], sdevice[10];
char svalue[MESSZ], sdevice[10];
if ((device < 1) || (device > Maxdevice)) device = 1;
snprintf_P(sdevice, sizeof(sdevice), PSTR("%d"), device);
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/RESULT"), PUB_PREFIX, sysCfg.mqtt_topic);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"%s%s\":\"BLINK %s\"}"),
sysCfg.mqtt_subtopic, (Maxdevice > 1) ? sdevice : "", (blink_mask & (0x01 << (device -1))) ? MQTT_STATUS_ON : MQTT_STATUS_OFF);
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(0, PSTR("RESULT"), svalue);
}
void mqtt_connected()
@ -958,6 +966,12 @@ void mqtt_connected()
char stopic[TOPSZ], svalue[MESSZ];
if (sysCfg.mqtt_enabled) {
// Satisfy iobroker (#299)
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/POWER"), SUB_PREFIX, sysCfg.mqtt_topic);
svalue[0] ='\0';
mqtt_publish(stopic, svalue);
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/#"), SUB_PREFIX, sysCfg.mqtt_topic);
mqttClient.subscribe(stopic);
mqttClient.loop(); // Solve LmacRxBlk:1 messages
@ -973,24 +987,23 @@ void mqtt_connected()
}
if (mqttflag) {
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/RESULT"), PUB_PREFIX2, sysCfg.mqtt_topic);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Info1\":{\"Module\":\"%s\", \"Version\":\"%s\", \"FallbackTopic\":\"%s\", \"GroupTopic\":\"%s\"}}"),
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Module\":\"%s\", \"Version\":\"%s\", \"FallbackTopic\":\"%s\", \"GroupTopic\":\"%s\"}"),
my_module.name, Version, MQTTClient, sysCfg.mqtt_grptopic);
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(1, PSTR("INFO1"), svalue);
#ifdef USE_WEBSERVER
if (sysCfg.webserver) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Info2\":{\"WebserverMode\":\"%s\", \"Hostname\":\"%s\", \"IPaddress\":\"%s\"}}"),
snprintf_P(svalue, sizeof(svalue), PSTR("{\"WebserverMode\":\"%s\", \"Hostname\":\"%s\", \"IPaddress\":\"%s\"}"),
(sysCfg.webserver == 2) ? "Admin" : "User", Hostname, WiFi.localIP().toString().c_str());
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(1, PSTR("INFO2"), svalue);
}
#endif // USE_WEBSERVER
if (sysCfg.mqtt_enabled && (MQTT_MAX_PACKET_SIZE < (TOPSZ+MESSZ))) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Warning1\":\"Change MQTT_MAX_PACKET_SIZE in libraries/PubSubClient.h to at least %d\"}"), TOPSZ+MESSZ);
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(1, PSTR("WARNING1"), svalue);
}
if (!spiffsPresent()) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Warning2\":\"No persistent config. Please reflash with at least 16K SPIFFS\"}"));
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(1, PSTR("WARNING2"), svalue);
}
if (sysCfg.tele_period) tele_period = sysCfg.tele_period -9;
status_update_timer = 2;
@ -1106,13 +1119,9 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
index = 1;
if (type != NULL) {
for (i = 0; i < strlen(type); i++) {
type[i] = toupper(type[i]);
if (isdigit(type[i])) {
index = atoi(type +i);
break;
}
}
for (i = 0; i < strlen(type); i++) type[i] = toupper(type[i]);
while (isdigit(type[i-1])) i--;
if (i < strlen(type)) index = atoi(type +i);
type[i] = '\0';
}
@ -1122,7 +1131,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
mtopic, grpflg, index, type, dataBuf, dataBufUc);
addLog(LOG_LEVEL_DEBUG, svalue);
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/RESULT"), PUB_PREFIX, sysCfg.mqtt_topic);
// snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/RESULT"), PUB_PREFIX, sysCfg.mqtt_topic);
if (type != NULL) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Command\":\"Error\"}"));
if (sysCfg.ledstate &0x02) blinks++;
@ -1241,7 +1250,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("%s%s (%d)"), svalue, stemp1, i +1);
}
snprintf_P(svalue, sizeof(svalue), PSTR("%s\"}"), svalue);
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(0, PSTR("RESULT"), svalue);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Modules2\":\""), svalue);
jsflg = 0;
for (byte i = 11; i < MAXMODULE; i++) {
@ -1588,7 +1597,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
else if (sysCfg.mqtt_enabled && !grpflg && !strcmp(type,"TOPIC")) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_topic))) {
for(i = 0; i <= data_len; i++)
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#')) dataBuf[i] = '_';
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) dataBuf[i] = '_';
if (!strcmp(dataBuf, MQTTClient)) payload = 1;
strlcpy(sysCfg.mqtt_topic, (payload == 1) ? MQTT_TOPIC : dataBuf, sizeof(sysCfg.mqtt_topic));
restartflag = 2;
@ -1598,7 +1607,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
else if (sysCfg.mqtt_enabled && !grpflg && !strcmp(type,"BUTTONTOPIC")) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.button_topic))) {
for(i = 0; i <= data_len; i++)
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#')) dataBuf[i] = '_';
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) dataBuf[i] = '_';
if (!strcmp(dataBuf, MQTTClient)) payload = 1;
strlcpy(sysCfg.button_topic, (payload == 1) ? sysCfg.mqtt_topic : dataBuf, sizeof(sysCfg.button_topic));
}
@ -1607,7 +1616,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
else if (sysCfg.mqtt_enabled && !grpflg && !strcmp(type,"SWITCHTOPIC")) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.switch_topic))) {
for(i = 0; i <= data_len; i++)
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#')) dataBuf[i] = '_';
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) dataBuf[i] = '_';
if (!strcmp(dataBuf, MQTTClient)) payload = 1;
strlcpy(sysCfg.switch_topic, (payload == 1) ? sysCfg.mqtt_topic : dataBuf, sizeof(sysCfg.switch_topic));
}
@ -1672,17 +1681,17 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
}
if (type == NULL) {
blinks = 201;
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands\":\"Status, SaveData, SaveSate, Sleep, Upgrade, Otaurl, Restart, Reset, WifiConfig, Seriallog, Syslog, LogHost, LogPort, SSId1, SSId2, Password1, Password2, AP%s\"}"), (!grpflg) ? ", Hostname, Module, Modules, GPIO, GPIOs" : "");
mqtt_publish(stopic, svalue);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands1\":\"Status, SaveData, SaveSate, Sleep, Upgrade, Otaurl, Restart, Reset, WifiConfig, Seriallog, Syslog, LogHost, LogPort, SSId1, SSId2, Password1, Password2, AP%s\"}"), (!grpflg) ? ", Hostname, Module, Modules, GPIO, GPIOs" : "");
mqtt_publish_topic_P(0, PSTR("COMMANDS1"), svalue);
if (sysCfg.mqtt_enabled) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands\":\"Mqtt, MqttHost, MqttPort, MqttUser, MqttPassword%s, GroupTopic, Units, Timezone, LedState, LedPower, TelePeriod\"}"), (!grpflg) ? ", MqttClient, Topic, ButtonTopic, ButtonRetain, SwitchTopic, SwitchRetain, PowerRetain" : "");
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands2\":\"Mqtt, MqttHost, MqttPort, MqttUser, MqttPassword%s, GroupTopic, Units, Timezone, LedState, LedPower, TelePeriod\"}"), (!grpflg) ? ", MqttClient, Topic, ButtonTopic, ButtonRetain, SwitchTopic, SwitchRetain, PowerRetain" : "");
} else {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands\":\"Mqtt, Units, Timezone, LedState, LedPower, TelePeriod\"}"), (!grpflg) ? ", MqttClient" : "");
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands2\":\"Mqtt, Units, Timezone, LedState, LedPower, TelePeriod\"}"), (!grpflg) ? ", MqttClient" : "");
}
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(0, PSTR("COMMANDS2"), svalue);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands\":\"%s%s, PulseTime, BlinkTime, BlinkCount"), (Maxdevice == 1) ? "Power, Light" : "Power1, Power2, Light1 Light2", (sysCfg.module != MOTOR) ? ", PowerOnState" : "");
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands3\":\"%s%s, PulseTime, BlinkTime, BlinkCount"), (Maxdevice == 1) ? "Power, Light" : "Power1, Power2, Light1 Light2", (sysCfg.module != MOTOR) ? ", PowerOnState" : "");
#ifdef USE_WEBSERVER
snprintf_P(svalue, sizeof(svalue), PSTR("%s, Weblog, Webserver, Emulation"), svalue);
#endif
@ -1694,18 +1703,20 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
if (pin[GPIO_WS2812] < 99) snprintf_P(svalue, sizeof(svalue), PSTR("%s, Pixels, Led, Color, Dimmer, Scheme, Fade, Speed, Width, Wakeup, LedTable"), svalue);
#endif
snprintf_P(svalue, sizeof(svalue), PSTR("%s\"}"), svalue);
mqtt_publish_topic_P(0, PSTR("COMMANDS3"), svalue);
#ifdef USE_DOMOTICZ
mqtt_publish(stopic, svalue);
domoticz_commands(svalue, sizeof(svalue));
mqtt_publish_topic_P(0, PSTR("COMMANDS4"), svalue);
#endif // USE_DOMOTICZ
if (hlw_flg) {
mqtt_publish(stopic, svalue);
hlw_commands(svalue, sizeof(svalue));
mqtt_publish_topic_P(0, PSTR("COMMANDS5"), svalue);
}
} else {
mqtt_publish_topic_P(0, PSTR("RESULT"), svalue);
}
mqtt_publish(stopic, svalue);
}
/********************************************************************************************/
@ -1827,84 +1838,121 @@ void do_cmnd(char *cmnd)
void publish_status(uint8_t payload)
{
char stopic[TOPSZ], svalue[MESSZ], stemp1[TOPSZ], stemp2[10], stemp3[10];
char svalue[MESSZ], stemp1[TOPSZ], stemp2[10], stemp3[10];
float ped, pi, pc;
uint16_t pe, pw, pu;
uint8_t option = 0;
// Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/RESULT"),
(!strcmp(SUB_PREFIX,PUB_PREFIX) && (!payload)) ? PUB_PREFIX2 : PUB_PREFIX, sysCfg.mqtt_topic);
option = (!strcmp(SUB_PREFIX,PUB_PREFIX) && (!payload));
if ((!sysCfg.mqtt_enabled) && (payload == 6)) payload = 99;
if ((!hlw_flg) && ((payload == 8) || (payload == 9))) payload = 99;
if ((payload == 0) || (payload == 99)) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Status\":{\"Module\":%d, \"FriendlyName\":\"%s\", \"Topic\":\"%s\", \"ButtonTopic\":\"%s\", \"Subtopic\":\"%s\", \"Power\":%d, \"PowerOnState\":%d, \"LedState\":%d, \"SaveData\":%d, \"SaveState\":%d, \"ButtonRetain\":%d, \"PowerRetain\":%d}}"),
sysCfg.module +1, sysCfg.friendlyname[0], sysCfg.mqtt_topic, sysCfg.button_topic, sysCfg.mqtt_subtopic, power, sysCfg.poweronstate, sysCfg.ledstate, sysCfg.savedata, sysCfg.savestate, sysCfg.mqtt_button_retain, sysCfg.mqtt_power_retain);
if (payload == 0) mqtt_publish(stopic, svalue);
}
if (hlw_flg) {
if ((payload == 0) || (payload == 8)) {
hlw_readEnergy(0, ped, pe, pw, pu, pi, pc);
dtostrf(pi, 1, 3, stemp1);
dtostrf(ped, 1, 3, stemp2);
dtostrf(pc, 1, 2, stemp3);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusPWR\":{\"Voltage\":%d, \"Current\":\"%s\", \"Power\":%d, \"Today\":\"%s\", \"Factor\":\"%s\"}}"),
pu, stemp1, pw, stemp2, stemp3);
if (payload == 0) mqtt_publish(stopic, svalue);
}
if ((payload == 0) || (payload == 9)) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusPWRThreshold\":{\"PowerLow\":%d, \"PowerHigh\":%d, \"VoltageLow\":%d, \"VoltageHigh\":%d, \"CurrentLow\":%d, \"CurrentHigh\":%d}}"),
sysCfg.hlw_pmin, sysCfg.hlw_pmax, sysCfg.hlw_umin, sysCfg.hlw_umax, sysCfg.hlw_imin, sysCfg.hlw_imax);
if (payload == 0) mqtt_publish(stopic, svalue);
}
mqtt_publish_topic_P(option, PSTR("STATUS"), svalue);
}
if ((payload == 0) || (payload == 1)) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusPRM\":{\"Baudrate\":%d, \"GroupTopic\":\"%s\", \"OtaUrl\":\"%s\", \"Uptime\":%d, \"Sleep\":%d, \"BootCount\":%d, \"SaveCount\":%d}}"),
Baudrate, sysCfg.mqtt_grptopic, sysCfg.otaUrl, uptime, sysCfg.sleep, sysCfg.bootcount, sysCfg.saveFlag);
if (payload == 0) mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(option, PSTR("STATUS1"), svalue);
}
if ((payload == 0) || (payload == 2)) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusFWR\":{\"Program\":\"%s\", \"Boot\":%d, \"SDK\":\"%s\"}}"),
Version, ESP.getBootVersion(), ESP.getSdkVersion());
if (payload == 0) mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(option, PSTR("STATUS2"), svalue);
}
if ((payload == 0) || (payload == 3)) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusLOG\":{\"Seriallog\":%d, \"Weblog\":%d, \"Syslog\":%d, \"LogHost\":\"%s\", \"SSId1\":\"%s\", \"SSId2\":\"%s\", \"TelePeriod\":%d}}"),
sysCfg.seriallog_level, sysCfg.weblog_level, sysCfg.syslog_level, sysCfg.syslog_host, sysCfg.sta_ssid[0], sysCfg.sta_ssid[1], sysCfg.tele_period);
if (payload == 0) mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(option, PSTR("STATUS3"), svalue);
}
if ((payload == 0) || (payload == 4)) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusMEM\":{\"ProgramSize\":%d, \"Free\":%d, \"Heap\":%d, \"SpiffsStart\":%d, \"SpiffsSize\":%d, \"FlashSize\":%d, \"ProgramFlashSize\":%d}}"),
ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ((uint32_t)&_SPIFFS_start - 0x40200000)/1024,
(((uint32_t)&_SPIFFS_end - 0x40200000) - ((uint32_t)&_SPIFFS_start - 0x40200000))/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipSize()/1024);
if (payload == 0) mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(option, PSTR("STATUS4"), svalue);
}
if ((payload == 0) || (payload == 5)) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusNET\":{\"Host\":\"%s\", \"IP\":\"%s\", \"Gateway\":\"%s\", \"Subnetmask\":\"%s\", \"Mac\":\"%s\", \"Webserver\":%d, \"WifiConfig\":%d}}"),
Hostname, WiFi.localIP().toString().c_str(), WiFi.gatewayIP().toString().c_str(), WiFi.subnetMask().toString().c_str(),
WiFi.macAddress().c_str(), sysCfg.webserver, sysCfg.sta_config);
if (payload == 0) mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(option, PSTR("STATUS5"), svalue);
}
if (((payload == 0) || (payload == 6)) && sysCfg.mqtt_enabled) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusMQT\":{\"Host\":\"%s\", \"Port\":%d, \"ClientMask\":\"%s\", \"Client\":\"%s\", \"User\":\"%s\", \"MAX_PACKET_SIZE\":%d, \"KEEPALIVE\":%d}}"),
sysCfg.mqtt_host, sysCfg.mqtt_port, sysCfg.mqtt_client, MQTTClient, sysCfg.mqtt_user, MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE);
if (payload == 0) mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(option, PSTR("STATUS6"), svalue);
}
if ((payload == 0) || (payload == 7)) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusTIM\":{\"UTC\":\"%s\", \"Local\":\"%s\", \"StartDST\":\"%s\", \"EndDST\":\"%s\", \"Timezone\":%d}}"),
rtc_time(0).c_str(), rtc_time(1).c_str(), rtc_time(2).c_str(), rtc_time(3).c_str(), sysCfg.timezone);
mqtt_publish_topic_P(option, PSTR("STATUS7"), svalue);
}
mqtt_publish(stopic, svalue);
if (hlw_flg) {
if ((payload == 0) || (payload == 8)) {
hlw_mqttStatus(svalue, sizeof(svalue));
mqtt_publish_topic_P(option, PSTR("STATUS8"), svalue);
}
if ((payload == 0) || (payload == 9)) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusPTH\":{\"PowerLow\":%d, \"PowerHigh\":%d, \"VoltageLow\":%d, \"VoltageHigh\":%d, \"CurrentLow\":%d, \"CurrentHigh\":%d}}"),
sysCfg.hlw_pmin, sysCfg.hlw_pmax, sysCfg.hlw_umin, sysCfg.hlw_umax, sysCfg.hlw_imin, sysCfg.hlw_imax);
mqtt_publish_topic_P(option, PSTR("STATUS9"), svalue);
}
}
if ((payload == 0) || (payload == 10)) {
uint8_t djson = 0;
snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusSNS\":"));
sensors_mqttPresent(svalue, sizeof(svalue), &djson);
if (!djson) snprintf_P(svalue, sizeof(svalue), PSTR("%s}"), svalue);
mqtt_publish_topic_P(option, PSTR("STATUS10"), svalue);
}
}
void sensors_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
{
char stime[21];
snprintf_P(stime, sizeof(stime), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"),
rtcTime.Year, rtcTime.Month, rtcTime.Day, rtcTime.Hour, rtcTime.Minute, rtcTime.Second);
snprintf_P(svalue, ssvalue, PSTR("%s{\"Time\":\"%s\""), svalue, stime);
if (pin[GPIO_DSB] < 99) {
#ifdef USE_DS18B20
dsb_mqttPresent(svalue, ssvalue, djson);
#endif // USE_DS18B20
#ifdef USE_DS18x20
ds18x20_mqttPresent(svalue, ssvalue, djson);
#endif // USE_DS18x20
}
#if defined(USE_DHT) || defined(USE_DHT2)
if (dht_type) dht_mqttPresent(svalue, ssvalue, djson);
#endif // USE_DHT/2
#ifdef USE_I2C
if (i2c_flg) {
#ifdef USE_HTU
htu_mqttPresent(svalue, ssvalue, djson);
#endif // USE_HTU
#ifdef USE_BMP
bmp_mqttPresent(svalue, ssvalue, djson);
#endif // USE_BMP
#ifdef USE_BH1750
bh1750_mqttPresent(svalue, ssvalue, djson);
#endif // USE_BH1750
}
#endif // USE_I2C
snprintf_P(svalue, ssvalue, PSTR("%s}"), svalue);
}
/********************************************************************************************/
@ -1988,7 +2036,6 @@ void every_second()
if (tele_period >= sysCfg.tele_period) {
tele_period = 0;
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/TELEMETRY"), PUB_PREFIX2, sysCfg.mqtt_topic);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\", \"Uptime\":%d"), stime, uptime);
for (byte i = 0; i < Maxdevice; i++) {
if (Maxdevice == 1) { // Legacy
@ -2000,40 +2047,14 @@ void every_second()
}
snprintf_P(svalue, sizeof(svalue), PSTR("%s, \"Wifi\":{\"AP\":%d, \"SSID\":\"%s\", \"RSSI\":%d}}"),
svalue, sysCfg.sta_active +1, sysCfg.sta_ssid[sysCfg.sta_active], WIFI_getRSSIasQuality(WiFi.RSSI()));
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(1, PSTR("STATE"), svalue);
uint8_t djson = 0;
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\""), stime);
if (pin[GPIO_DSB] < 99) {
#ifdef USE_DS18B20
dsb_mqttPresent(svalue, sizeof(svalue), &djson, 0);
#endif // USE_DS18B20
#ifdef USE_DS18x20
ds18x20_mqttPresent(svalue, sizeof(svalue), &djson, 0);
#endif // USE_DS18x20
}
#if defined(USE_DHT) || defined(USE_DHT2)
if (dht_type) dht_mqttPresent(svalue, sizeof(svalue), &djson, 1);
#endif // USE_DHT/2
#ifdef USE_I2C
if (i2c_flg) {
#ifdef USE_HTU
htu_mqttPresent(svalue, sizeof(svalue), &djson, 1);
#endif // USE_HTU
#ifdef USE_BMP
bmp_mqttPresent(svalue, sizeof(svalue), &djson, 2);
#endif // USE_BMP
#ifdef USE_BH1750
bh1750_mqttPresent(svalue, sizeof(svalue), &djson, 3);
#endif // USE_BH1750
}
#endif // USE_I2C
if (djson) {
snprintf_P(svalue, sizeof(svalue), PSTR("%s}"), svalue);
mqtt_publish(stopic, svalue);
}
svalue[0] = '\0';
sensors_mqttPresent(svalue, sizeof(svalue), &djson);
if (djson) mqtt_publish_topic_P(1, PSTR("SENSOR"), svalue);
if (hlw_flg) hlw_mqttPresent(4);
if (hlw_flg) hlw_mqttPresent();
}
}
@ -2041,16 +2062,15 @@ void every_second()
if ((rtcTime.Minute == 2) && (rtcTime.Second == 30)) {
uptime++;
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/TELEMETRY"), PUB_PREFIX2, sysCfg.mqtt_topic);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\", \"Uptime\":%d}"), stime, uptime);
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(1, PSTR("UPTIME"), svalue);
}
}
void stateloop()
{
uint8_t button, flag, switchflag, power_now;
char scmnd[20], log[LOGSZ], stopic[TOPSZ], svalue[MESSZ];
uint8_t button = NOT_PRESSED, flag, switchflag, power_now;
char scmnd[20], log[LOGSZ], svalue[MESSZ];
timerxs = millis() + (1000 / STATES);
state++;
@ -2096,7 +2116,7 @@ void stateloop()
button = NOT_PRESSED;
}
} else {
button = digitalRead(pin[GPIO_KEY1]);
if (pin[GPIO_KEY1] < 99) button = digitalRead(pin[GPIO_KEY1]);
}
if ((button == PRESSED) && (lastbutton[0] == NOT_PRESSED)) {
multipress = (multiwindow) ? multipress +1 : 1;
@ -2225,14 +2245,13 @@ void stateloop()
}
if (otaflag == 10) { // Allow MQTT to reconnect
otaflag = 0;
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/UPGRADE"), PUB_PREFIX, sysCfg.mqtt_topic);
if (otaok) {
snprintf_P(svalue, sizeof(svalue), PSTR("Successful. Restarting"));
restartflag = 2;
} else {
snprintf_P(svalue, sizeof(svalue), PSTR("Failed %s"), ESPhttpUpdate.getLastErrorString().c_str());
}
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(0, PSTR("UPGRADE"), svalue);
}
}
break;
@ -2348,7 +2367,7 @@ void GPIO_init()
uint8_t mpin;
mytmplt def_module;
if (!sysCfg.module) sysCfg.module = SONOFF_BASIC; // Sonoff Basic
if (!sysCfg.module || (sysCfg.module >= MAXMODULE)) sysCfg.module = SONOFF_BASIC; // Sonoff Basic
memcpy_P(&def_module, &modules[sysCfg.module], sizeof(def_module));
strlcpy(my_module.name, def_module.name, sizeof(my_module.name));

View File

@ -149,12 +149,10 @@ const mytmplt modules[MAXMODULE] PROGMEM = {
GPIO_KEY1, // GPIO00 Button 1
0,
GPIO_USER, // GPIO02 Optional sensor
0,
GPIO_USER, // GPIO03 Serial TXD and Optional sensor
GPIO_REL3, // GPIO04 Sonoff 4CH Red Led and Relay 3 (0 = Off, 1 = On)
GPIO_REL2, // GPIO05 Sonoff 4CH Red Led and Relay 2 (0 = Off, 1 = On)
0,
GPIO_USER, // GPIO07 Optional sensor
GPIO_USER, // GPIO08 Optional sensor
0, 0, 0,
GPIO_KEY2, // GPIO09 Button 2
GPIO_KEY3, // GPIO10 Button 3
0,
@ -235,7 +233,8 @@ const mytmplt modules[MAXMODULE] PROGMEM = {
},
{ "User Test", // Sonoff Basic User Test
GPIO_KEY1, // GPIO00 Button
0, 0,
0,
GPIO_USER, // GPIO02 Optional sensor
GPIO_USER, // GPIO03 Serial TXD and Optional sensor
GPIO_USER, // GPIO04 Optional sensor
0, 0, 0, 0, 0, 0, 0,

View File

@ -127,6 +127,7 @@
#define USE_HTU // Add I2C code for HTU21 sensor
#define USE_WS2812 // WS2812 Led string support (+8k code, +1k mem)
#define USE_WS2812_CTYPE 1 // WS2812 Color type (0 - RGB, 1 - GRB)
// #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial TXD) (+1k mem)
// When USE_WS2812_DMA is enabled expect Exceptions on Pow

View File

@ -164,8 +164,8 @@ const char HTTP_FORM_OTHER2[] PROGMEM =
#ifdef USE_EMULATION
const char HTTP_FORM_OTHER3[] PROGMEM =
"<br/><fieldset><legend><b>&nbsp;Emulation&nbsp;</b></legend>"
"<br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='0'{r2}><b>None</b><br/>"
"<br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='1'{r3}><b>Belkin WeMo</b><br/>"
"<br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='0'{r2}><b>None</b>"
"<br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='1'{r3}><b>Belkin WeMo</b>"
"<br/><input style='width:10%;float:left' id='b2' name='b2' type='radio' value='2'{r4}><b>Hue Bridge</b><br/>";
#endif // USE_EMULATION
const char HTTP_FORM_END[] PROGMEM =
@ -288,6 +288,28 @@ const char HUE_LIGHT_STATUS_JSON[] PROGMEM =
"}";
const char HUE_LIGHT_RESPONSE_JSON[] PROGMEM =
"{\"success\":{\"{api}/{id}/{cmd}\":{res}}}";
const char HUE_CONFIG_RESPONSE_JSON[] PROGMEM =
"{\"name\":\"Philips hue\","
"\"mac\":\"{mac}\","
"\"dhcp\":true,"
"\"ipaddress\":\"{ip}\","
"\"netmask\":\"{mask}\","
"\"gateway\":\"{gw}\","
"\"proxyaddress\":\"\","
"\"proxyport\":0,"
"\"UTC\":\"{dt}\","
"\"whitelist\":{\"{id}\":{"
"\"last use date\":\"{dt}\","
"\"create date\":\"{dt}\","
"\"name\":\"Remote\"}},"
"\"swversion\":\"01036659\","
"\"apiversion\":\"1.16.0\","
"\"swupdate\":{\"updatestate\":0,\"url\":\"\",\"text\":\"\",\"notify\": false},"
"\"linkbutton\":false,"
"\"portalservices\":false"
"}";
const char HUE_NO_AUTH_JSON[] PROGMEM =
"[{\"error\":{\"type\":101,\"address\":\"/\",\"description\":\"link button not pressed\"}}]";
#endif // USE_EMULATION
#define DNS_PORT 53
@ -971,23 +993,23 @@ void handleUploadDone()
page.replace("{v}", "Info");
page += F("<div style='text-align:center;'><b>Upload ");
if (_uploaderror) {
page += F("<font color='red'>failed</font></b>");
page += F("<font color='red'>failed</font></b><br/><br/>");
if (_uploaderror == 1) {
page += F("<br/><br/>No file selected");
page += F("No file selected");
} else if (_uploaderror == 2) {
page += F("<br/><br/>File size is larger than available free space");
page += F("File size is larger than available free space");
} else if (_uploaderror == 3) {
page += F("<br/><br/>File magic header does not start with 0xE9");
page += F("File magic header does not start with 0xE9");
} else if (_uploaderror == 4) {
page += F("<br/><br/>File flash size is larger than device flash size");
page += F("File flash size is larger than device flash size");
} else if (_uploaderror == 5) {
page += F("<br/><br/>File upload buffer miscompare");
page += F("File upload buffer miscompare");
} else if (_uploaderror == 6) {
page += F("<br/><br/>Upload failed. Enable logging option 3 for more information");
page += F("Upload failed. Enable logging option 3 for more information");
} else if (_uploaderror == 7) {
page += F("<br/><br/>Upload aborted");
page += F("Upload aborted");
} else {
page += F("<br/><br/>Upload error code ");
page += F("Upload error code ");
page += String(_uploaderror);
}
if (Update.hasError()) {
@ -1205,52 +1227,86 @@ void handleInfo()
// page += F("<fieldset><legend><b>&nbsp;Information&nbsp;</b></legend>");
page += F("<style>td{padding:0px 5px;}</style>");
page += F("<table style'width:100%;'>");
page += F("<tr><td><b>Program version</b></td><td>"); page += Version; page += F("</td></tr>");
page += F("<tr><td><b>Core/SDK version</b></td><td>"); page += ESP.getCoreVersion(); page += F("/"); page += String(ESP.getSdkVersion()); page += F("</td></tr>");
// page += F("<tr><td><b>Boot version</b></td><td>"); page += String(ESP.getBootVersion()); page += F("</td></tr>");
page += F("<tr><td><b>Uptime</b></td><td>"); page += String(uptime); page += F(" Hours</td></tr>");
page += F("<tr><td><b>Flash write count</b></td><td>"); page += String(sysCfg.saveFlag); page += F("</td></tr>");
page += F("<tr><td><b>Boot count</b></td><td>"); page += String(sysCfg.bootcount); page += F("</td></tr>");
page += F("<tr><td><b>Reset reason</b></td><td>"); page += ESP.getResetReason(); page += F("</td></tr>");
page += F("<tr><th>Program version</th><td>"); page += Version; page += F("</td></tr>");
page += F("<tr><th>Build Date/Time</th><td>"); page += __DATE__;
page += F("/"); page += __TIME__ ; page += F("</td></tr>");
page += F("<tr><th>Core/SDK version</th><td>"); page += ESP.getCoreVersion(); page += F("/"); page += String(ESP.getSdkVersion()); page += F("</td></tr>");
// page += F("<tr><th>Boot version</th><td>"); page += String(ESP.getBootVersion()); page += F("</td></tr>");
page += F("<tr><th>Uptime</th><td>"); page += String(uptime); page += F(" Hours</td></tr>");
page += F("<tr><th>Flash write count</th><td>"); page += String(sysCfg.saveFlag); page += F("</td></tr>");
page += F("<tr><th>Boot count</th><td>"); page += String(sysCfg.bootcount); page += F("</td></tr>");
page += F("<tr><th>Reset reason</th><td>"); page += ESP.getResetReason(); page += F("</td></tr>");
for (byte i = 0; i < Maxdevice; i++) {
page += F("<tr><td><b>Friendly name ");
page += F("<tr><th>Friendly name ");
page += i +1;
page += F("</b></td><td>"); page += String(sysCfg.friendlyname[i]); page += F("</td></tr>");
page += F("</th><td>"); page += String(sysCfg.friendlyname[i]); page += F("</td></tr>");
}
page += F("<tr><td>&nbsp;</td></tr>");
// page += F("<tr><td><b>SSId (RSSI)</b></td><td>"); page += (sysCfg.sta_active)? sysCfg.sta_ssid2 : sysCfg.sta_ssid1; page += F(" ("); page += WIFI_getRSSIasQuality(WiFi.RSSI()); page += F("%)</td></tr>");
page += F("<tr><td><b>AP"); page += String(sysCfg.sta_active +1); page += F(" SSId (RSSI)</b></td><td>"); page += sysCfg.sta_ssid[sysCfg.sta_active]; page += F(" ("); page += WIFI_getRSSIasQuality(WiFi.RSSI()); page += F("%)</td></tr>");
page += F("<tr><td><b>Hostname</b></td><td>"); page += Hostname; page += F("</td></tr>");
// page += F("<tr><th>SSId (RSSI)</th><td>"); page += (sysCfg.sta_active)? sysCfg.sta_ssid2 : sysCfg.sta_ssid1; page += F(" ("); page += WIFI_getRSSIasQuality(WiFi.RSSI()); page += F("%)</td></tr>");
page += F("<tr><th>AP"); page += String(sysCfg.sta_active +1); page += F(" SSId (RSSI)</th><td>"); page += sysCfg.sta_ssid[sysCfg.sta_active]; page += F(" ("); page += WIFI_getRSSIasQuality(WiFi.RSSI()); page += F("%)</td></tr>");
page += F("<tr><th>Hostname</th><td>"); page += Hostname; page += F("</td></tr>");
if (static_cast<uint32_t>(WiFi.localIP()) != 0) {
page += F("<tr><td><b>IP address</b></td><td>"); page += WiFi.localIP().toString(); page += F("</td></tr>");
page += F("<tr><td><b>Gateway</b></td><td>"); page += WiFi.gatewayIP().toString(); page += F("</td></tr>");
page += F("<tr><td><b>MAC address</b></td><td>"); page += WiFi.macAddress(); page += F("</td></tr>");
page += F("<tr><th>IP address</th><td>"); page += WiFi.localIP().toString(); page += F("</td></tr>");
page += F("<tr><th>Gateway</th><td>"); page += WiFi.gatewayIP().toString(); page += F("</td></tr>");
page += F("<tr><th>MAC address</th><td>"); page += WiFi.macAddress(); page += F("</td></tr>");
}
if (static_cast<uint32_t>(WiFi.softAPIP()) != 0) {
page += F("<tr><td><b>AP IP address</b></td><td>"); page += WiFi.softAPIP().toString(); page += F("</td></tr>");
page += F("<tr><td><b>AP Gateway</b></td><td>"); page += WiFi.softAPIP().toString(); page += F("</td></tr>");
page += F("<tr><td><b>AP MAC address</b></td><td>"); page += WiFi.softAPmacAddress(); page += F("</td></tr>");
page += F("<tr><th>AP IP address</th><td>"); page += WiFi.softAPIP().toString(); page += F("</td></tr>");
page += F("<tr><th>AP Gateway</th><td>"); page += WiFi.softAPIP().toString(); page += F("</td></tr>");
page += F("<tr><th>AP MAC address</th><td>"); page += WiFi.softAPmacAddress(); page += F("</td></tr>");
}
page += F("<tr><td>&nbsp;</td></tr>");
if (sysCfg.mqtt_enabled) {
page += F("<tr><td><b>MQTT Host</b></td><td>"); page += sysCfg.mqtt_host; page += F("</td></tr>");
page += F("<tr><td><b>MQTT Port</b></td><td>"); page += String(sysCfg.mqtt_port); page += F("</td></tr>");
page += F("<tr><td><b>MQTT Client and<br/>&nbsp;Fallback Topic</b></td><td>"); page += MQTTClient; page += F("</td></tr>");
page += F("<tr><td><b>MQTT User</b></td><td>"); page += sysCfg.mqtt_user; page += F("</td></tr>");
// page += F("<tr><td><b>MQTT Password</b></td><td>"); page += sysCfg.mqtt_pwd; page += F("</td></tr>");
page += F("<tr><td><b>MQTT Topic</b></td><td>"); page += sysCfg.mqtt_topic; page += F("</td></tr>");
page += F("<tr><td><b>MQTT Group Topic</b></td><td>"); page += sysCfg.mqtt_grptopic; page += F("</td></tr>");
page += F("<tr><th>MQTT Host</th><td>"); page += sysCfg.mqtt_host; page += F("</td></tr>");
page += F("<tr><th>MQTT Port</th><td>"); page += String(sysCfg.mqtt_port); page += F("</td></tr>");
page += F("<tr><th>MQTT Client and<br/>&nbsp;Fallback Topic</th><td>"); page += MQTTClient; page += F("</td></tr>");
page += F("<tr><th>MQTT User</th><td>"); page += sysCfg.mqtt_user; page += F("</td></tr>");
// page += F("<tr><th>MQTT Password</th><td>"); page += sysCfg.mqtt_pwd; page += F("</td></tr>");
page += F("<tr><th>MQTT Topic</th><td>"); page += sysCfg.mqtt_topic; page += F("</td></tr>");
page += F("<tr><th>MQTT Group Topic</th><td>"); page += sysCfg.mqtt_grptopic; page += F("</td></tr>");
} else {
page += F("<tr><td><b>MQTT</b></td><td>Disabled</td></tr>");
page += F("<tr><th>MQTT</th><td>Disabled</td></tr>");
}
page += F("<tr><th>Emulation</th><td>");
#ifdef USE_EMULATION
if (sysCfg.emulation == EMUL_WEMO) {
page += F("Belkin WeMo");
}
else if (sysCfg.emulation == EMUL_HUE) {
page += F("Hue Bridge");
}
else {
page += F("None");
}
#else
page += F("Disabled");
#endif // USE_EMULATION
page += F("</td></tr>");
page += F("<tr><th>mDNS Discovery</th><td>");
#ifdef USE_DISCOVERY
page += F("Enabled");
page += F("</td></tr>");
page += F("<tr><th>mDNS Webserver Advertise</th><td>");
#ifdef WEBSERVER_ADVERTISE
page += F("Enabled");
#else
page += F("Disabled");
#endif // WEBSERVER_ADVERTISE
#else
page += F("Disabled");
#endif // USE_DISCOVERY
page += F("</td></tr>");
page += F("<tr><td>&nbsp;</td></tr>");
page += F("<tr><td><b>ESP Chip id</b></td><td>"); page += String(ESP.getChipId()); page += F("</td></tr>");
page += F("<tr><td><b>Flash Chip id</b></td><td>"); page += String(ESP.getFlashChipId()); page += F("</td></tr>");
page += F("<tr><td><b>Flash size</b></td><td>"); page += String(ESP.getFlashChipRealSize() / 1024); page += F("kB</td></tr>");
page += F("<tr><td><b>Program flash size</b></td><td>"); page += String(ESP.getFlashChipSize() / 1024); page += F("kB</td></tr>");
page += F("<tr><td><b>Program size</b></td><td>"); page += String(ESP.getSketchSize() / 1024); page += F("kB</td></tr>");
page += F("<tr><td><b>Free program space</b></td><td>"); page += String(ESP.getFreeSketchSpace() / 1024); page += F("kB</td></tr>");
page += F("<tr><td><b>Free memory</b></td><td>"); page += String(freeMem / 1024); page += F("kB</td></tr>");
page += F("<tr><th>ESP Chip id</th><td>"); page += String(ESP.getChipId()); page += F("</td></tr>");
page += F("<tr><th>Flash Chip id</th><td>"); page += String(ESP.getFlashChipId()); page += F("</td></tr>");
page += F("<tr><th>Flash size</th><td>"); page += String(ESP.getFlashChipRealSize() / 1024); page += F("kB</td></tr>");
page += F("<tr><th>Program flash size</th><td>"); page += String(ESP.getFlashChipSize() / 1024); page += F("kB</td></tr>");
page += F("<tr><th>Program size</th><td>"); page += String(ESP.getSketchSize() / 1024); page += F("kB</td></tr>");
page += F("<tr><th>Free program space</th><td>"); page += String(ESP.getFreeSketchSpace() / 1024); page += F("kB</td></tr>");
page += F("<tr><th>Free memory</th><td>"); page += String(freeMem / 1024); page += F("kB</td></tr>");
page += F("</table>");
// page += F("</fieldset>");
page += FPSTR(HTTP_BTN_MAIN);
@ -1286,8 +1342,8 @@ void handleUPnPevent()
addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Handle WeMo basic event"));
String request = webServer->arg(0);
if(request.indexOf("State>1</Binary") > 0) do_cmnd_power(1, 1);
if(request.indexOf("State>0</Binary") > 0) do_cmnd_power(1, 0);
if (request.indexOf("State>1</Binary") > 0) do_cmnd_power(1, 1);
if (request.indexOf("State>0</Binary") > 0) do_cmnd_power(1, 0);
webServer->send(200, "text/plain", "");
}
@ -1304,7 +1360,6 @@ void handleUPnPsetupWemo()
addLog_P(LOG_LEVEL_DEBUG, PSTR("HTTP: Handle WeMo setup"));
String setup_xml = FPSTR(WEMO_SETUP_XML);
// setup_xml.replace("{x1}", String(MQTTClient));
setup_xml.replace("{x1}", String(sysCfg.friendlyname[0]));
setup_xml.replace("{x2}", wemo_UUID());
setup_xml.replace("{x3}", wemo_serial());
@ -1339,6 +1394,76 @@ void hue_todo(String *path)
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
void hue_config_response(String *response)
{
char buffer[21];
*response += FPSTR(HUE_CONFIG_RESPONSE_JSON);
response->replace("{mac}", WiFi.macAddress());
response->replace("{ip}", WiFi.localIP().toString());
response->replace("{mask}", WiFi.subnetMask().toString());
response->replace("{gw}", WiFi.gatewayIP().toString());
snprintf_P(buffer, sizeof(buffer), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"),
rtcTime.Year, rtcTime.Month, rtcTime.Day, rtcTime.Hour, rtcTime.Minute, rtcTime.Second);
response->replace("{dt}", String(buffer));
}
void hue_global_cfg(String *path)
{
String response;
path->remove(0,1); // cut leading / to get <id>
response = "{\"lights\":{\"";
for (uint8_t i = 1; i <= Maxdevice; i++)
{
response += i;
response += "\":";
response += FPSTR(HUE_LIGHT_STATUS_JSON);
if (i < Maxdevice) response += ",\"";
response.replace("{state}", (power & (0x01 << (i-1))) ? "true" : "false");
response.replace("{j1}", sysCfg.friendlyname[i-1]);
response.replace("{j2}", hue_deviceId(i));
if (pin[GPIO_WS2812] < 99) {
#ifdef USE_WS2812
ws2812_replaceHSB(&response);
#endif // USE_WS2812
} else
{
response.replace("{h}", "0");
response.replace("{s}", "0");
response.replace("{b}", "0");
}
}
response += F("},\"groups\":{},\"schedules\":{},\"config\":");
hue_config_response(&response);
response.replace("{id}", *path);
response += "}";
webServer->send(200, "application/json", response);
}
void hue_auth(String *path)
{
String response;
char uid[7];
snprintf_P(uid, sizeof(uid), PSTR("%03x"), ESP.getChipId());
response="[{\"success\":{\"username\":\"";
response+=String(uid);
response+="\"}}]";
webServer->send(200, "application/json", response);
}
void hue_config(String *path)
{
String response = "";
path->remove(0,1); // cut leading / to get <id>
hue_config_response(&response);
response.replace("{id}", *path);
webServer->send(200, "application/json", response);
}
void hue_lights(String *path)
{
String response;
@ -1347,7 +1472,7 @@ void hue_lights(String *path)
uint8_t bri = 0;
char id[4];
path->remove(0,path->indexOf("/lights")); // Remove until /lights
path->remove(0,path->indexOf("/lights")); // Remove until /lights
if (path->endsWith("/lights")) // Got /lights
{
response = "{\"";
@ -1388,7 +1513,8 @@ void hue_lights(String *path)
if (webServer->args() == 1)
{
String json = webServer->arg(0);
// Serial.print("HUE API: POST "); Serial.println(json.c_str());
json.replace(" ",""); // remove blanks
if (json.indexOf("\"on\":") >= 0) // Got "on" command
{
if (json.indexOf("false") >= 0) // false -> turn device off
@ -1408,7 +1534,7 @@ void hue_lights(String *path)
}
#ifdef USE_WS2812
if ((pin[GPIO_WS2812] < 99) && ((pos=json.indexOf("\"bri\":")) >= 0)) {
bri=atoi(json.substring(pos+6).c_str());
bri = atoi(json.substring(pos+6).c_str());
ws2812_changeBrightness(bri);
response += ",";
response += FPSTR(HUE_LIGHT_RESPONSE_JSON);
@ -1456,22 +1582,34 @@ void handle_hue_api(String *path)
*/
char log[LOGSZ];
uint8_t args = 0;
path->remove(0, 4); // remove /api
snprintf_P(log, sizeof(log), PSTR("HTTP: Handle Hue API (%s)"), path->c_str());
addLog(LOG_LEVEL_DEBUG_MORE, log);
for (args = 0; args < webServer->args(); args++) {
String json = webServer->arg(args);
snprintf_P(log, sizeof(log), PSTR("HTTP: Hue POST args (%s)"), json.c_str());
addLog(LOG_LEVEL_DEBUG_MORE, log);
}
if (path->endsWith("/invalid/")) {} // Just ignore
else if (path->endsWith("/config")) hue_todo(path);
else if(path->indexOf("/lights") >= 0) hue_lights(path);
else if(path->endsWith("/groups")) hue_todo(path);
else if(path->endsWith("/schedules")) hue_todo(path);
else if(path->endsWith("/sensors")) hue_todo(path);
else if(path->endsWith("/scenes")) hue_todo(path);
else if(path->endsWith("/rules")) hue_todo(path);
else
else if (path->endsWith("/")) hue_auth(path); // New HUE App setup
else if (path->endsWith("/config")) hue_config(path);
else if (path->indexOf("/lights") >= 0) hue_lights(path);
else if (path->endsWith("/groups")) hue_todo(path);
else if (path->endsWith("/schedules")) hue_todo(path);
else if (path->endsWith("/sensors")) hue_todo(path);
else if (path->endsWith("/scenes")) hue_todo(path);
else if (path->endsWith("/rules")) hue_todo(path);
else hue_global_cfg(path);
/*
{
snprintf_P(log, sizeof(log), PSTR("HTTP: Handle Hue API (%s)"),path->c_str());
addLog(LOG_LEVEL_DEBUG_MORE, log);
webServer->send(406, "application/json", "{}");
}
*/
}
#endif // USE_EMULATION

View File

@ -239,7 +239,7 @@ boolean domoticz_command(char *type, uint16_t index, char *dataBuf, uint16_t dat
void domoticz_commands(char *svalue, uint16_t ssvalue)
{
snprintf_P(svalue, ssvalue, PSTR("{\"Commands\":\"DomoticzInTopic, DomoticzOutTopic, DomoticzIdx, DomoticzKeyIdx, DomoticzSwitchIdx, DomoticzSensorIdx, DomoticzUpdateTimer\"}"));
snprintf_P(svalue, ssvalue, PSTR("{\"Commands4\":\"DomoticzInTopic, DomoticzOutTopic, DomoticzIdx, DomoticzKeyIdx, DomoticzSwitchIdx, DomoticzSensorIdx, DomoticzUpdateTimer\"}"));
}
boolean domoticz_button(byte key, byte device, byte state, byte svalflg)

View File

@ -52,14 +52,14 @@ const char WEMO_MSEARCH[] PROGMEM =
String wemo_serial()
{
char serial[15];
snprintf_P(serial, sizeof(serial), PSTR("201612K%07d"), ESP.getChipId());
char serial[16];
snprintf_P(serial, sizeof(serial), PSTR("201612K%08X"), ESP.getChipId());
return String(serial);
}
String wemo_UUID()
{
char uuid[26];
char uuid[27];
snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), wemo_serial().c_str());
return String(uuid);
}
@ -138,7 +138,6 @@ void hue_respondToMSearch()
response.replace("{r3}", hue_UUID());
portUDP.write(response.c_str());
portUDP.endPacket();
snprintf_P(message, sizeof(message), PSTR("Response1 sent"));
// addLog(LOG_LEVEL_DEBUG_MORE, response.c_str());
response = FPSTR(HUE_RESPONSE);
@ -150,7 +149,6 @@ void hue_respondToMSearch()
response.replace("{r3}", hue_UUID());
portUDP.write(response.c_str());
portUDP.endPacket();
snprintf_P(message, sizeof(message), PSTR("Response2 sent"));
// addLog(LOG_LEVEL_DEBUG_MORE, response.c_str());
response = FPSTR(HUE_RESPONSE);
@ -161,7 +159,8 @@ void hue_respondToMSearch()
response.replace("{r3}", hue_UUID());
portUDP.write(response.c_str());
portUDP.endPacket();
snprintf_P(message, sizeof(message), PSTR("Response3 sent"));
snprintf_P(message, sizeof(message), PSTR("3 response packets sent"));
// addLog(LOG_LEVEL_DEBUG_MORE, response.c_str());
} else {

View File

@ -31,9 +31,17 @@ POSSIBILITY OF SUCH DAMAGE.
#include <NeoPixelBus.h>
#ifdef USE_WS2812_DMA
#if (USE_WS2812_CTYPE == 1)
NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> *strip = NULL;
#else
#else // USE_WS2812_CTYPE
NeoPixelBus<NeoRgbFeature, Neo800KbpsMethod> *strip = NULL;
#endif // USE_WS2812_CTYPE
#else // USE_WS2812_DMA
#if (USE_WS2812_CTYPE == 1)
NeoPixelBus<NeoGrbFeature, NeoEsp8266BitBang800KbpsMethod> *strip = NULL;
#else // USE_WS2812_CTYPE
NeoPixelBus<NeoRgbFeature, NeoEsp8266BitBang800KbpsMethod> *strip = NULL;
#endif // USE_WS2812_CTYPE
#endif // USE_WS2812_DMA
#define COLOR_SATURATION 254.0f
@ -457,9 +465,17 @@ void ws2812_pixels()
void ws2812_init()
{
#ifdef USE_WS2812_DMA
#if (USE_WS2812_CTYPE == 1)
strip = new NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod>(WS2812_MAX_LEDS); // For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use.
#else
#else // USE_WS2812_CTYPE
strip = new NeoPixelBus<NeoRgbFeature, Neo800KbpsMethod>(WS2812_MAX_LEDS); // For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use.
#endif // USE_WS2812_CTYPE
#else // USE_WS2812_DMA
#if (USE_WS2812_CTYPE == 1)
strip = new NeoPixelBus<NeoGrbFeature, NeoEsp8266BitBang800KbpsMethod>(WS2812_MAX_LEDS, pin[GPIO_WS2812]);
#else // USE_WS2812_CTYPE
strip = new NeoPixelBus<NeoRgbFeature, NeoEsp8266BitBang800KbpsMethod>(WS2812_MAX_LEDS, pin[GPIO_WS2812]);
#endif // USE_WS2812_CTYPE
#endif // USE_WS2812_DMA
strip->Begin();
ws2812_pixels();

View File

@ -82,7 +82,7 @@ boolean bh1750_detect()
* Presentation
\*********************************************************************************************/
void bh1750_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson, uint8_t domidx)
void bh1750_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
{
if (!bh1750type) return;

View File

@ -424,7 +424,7 @@ boolean bmp_detect()
* Presentation
\*********************************************************************************************/
void bmp_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson, uint8_t domidx)
void bmp_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
{
if (!bmptype) return;

View File

@ -178,7 +178,7 @@ void dht_init()
* Presentation
\*********************************************************************************************/
void dht_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson, uint8_t domidx)
void dht_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
{
char stemp1[10], stemp2[10];
float t, h;

View File

@ -57,7 +57,7 @@ void dht_init()
* Presentation
\*********************************************************************************************/
void dht_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson, uint8_t domidx)
void dht_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
{
char stemp1[10], stemp2[10];
float t, h;

View File

@ -172,7 +172,7 @@ boolean dsb_readTemp(bool S, float &t)
* Presentation
\*********************************************************************************************/
void dsb_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson, uint8_t domidx)
void dsb_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
{
char stemp1[10];
float t;

View File

@ -155,7 +155,7 @@ boolean ds18x20_read(uint8_t sensor, bool S, float &t)
* Presentation
\*********************************************************************************************/
void ds18x20_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson, uint8_t domidx)
void ds18x20_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
{
char stemp1[10], stemp2[10];
float t;

View File

@ -279,7 +279,7 @@ void hlw_setPowerSteadyCounter(byte value)
void hlw_margin_chk()
{
char log[LOGSZ], stopic[TOPSZ], svalue[MESSZ];
char log[LOGSZ], svalue[MESSZ];
float ped, pi, pc;
uint16_t uped, piv, pe, pw, pu;
byte flag, jsonflg;
@ -296,7 +296,6 @@ void hlw_margin_chk()
// snprintf_P(log, sizeof(log), PSTR("HLW: W %d, U %d, I %d"), pw, pu, piv);
// addLog(LOG_LEVEL_DEBUG, log);
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/TELEMETRY"), PUB_PREFIX2, sysCfg.mqtt_topic);
snprintf_P(svalue, sizeof(svalue), PSTR("{"));
jsonflg = 0;
if (hlw_margin(0, sysCfg.hlw_pmin, pw, flag, hlw_pminflg)) {
@ -325,12 +324,11 @@ void hlw_margin_chk()
}
if (jsonflg) {
snprintf_P(svalue, sizeof(svalue), PSTR("%s}"), svalue);
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(1, PSTR("MARGINS"), svalue);
}
}
#if FEATURE_POWER_LIMIT
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/RESULT"), PUB_PREFIX, sysCfg.mqtt_topic);
// Max Power
if (sysCfg.hlw_mpl) {
if (pw > sysCfg.hlw_mpl) {
@ -340,7 +338,7 @@ void hlw_margin_chk()
hlw_mplh_counter--;
if (!hlw_mplh_counter) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxPowerReached\":\"%d%s\"}"), pw, (sysCfg.value_units) ? " W" : "");
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(0, PSTR("WARNING"), svalue);
do_cmnd_power(1, 0);
if (!hlw_mplr_counter) hlw_mplr_counter = MAX_POWER_RETRY +1;
hlw_mplw_counter = sysCfg.hlw_mplw;
@ -359,12 +357,12 @@ void hlw_margin_chk()
if (hlw_mplr_counter) {
hlw_mplr_counter--;
if (hlw_mplr_counter) {
snprintf_P(svalue, sizeof(stopic), PSTR("{\"PowerMonitor\":\"%s\"}"), MQTT_STATUS_ON);
mqtt_publish(stopic, svalue);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"PowerMonitor\":\"%s\"}"), MQTT_STATUS_ON);
mqtt_publish_topic_P(0, PSTR("RESULT"), svalue);
do_cmnd_power(1, 1);
} else {
snprintf_P(svalue, sizeof(stopic), PSTR("{\"MaxPowerReachedRetry\":\"%s\"}"), MQTT_STATUS_OFF);
mqtt_publish(stopic, svalue);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxPowerReachedRetry\":\"%s\"}"), MQTT_STATUS_OFF);
mqtt_publish_topic_P(0, PSTR("WARNING"), svalue);
}
}
}
@ -376,15 +374,15 @@ void hlw_margin_chk()
uped = (uint16_t)(ped * 1000);
if (!hlw_mkwh_state && (rtcTime.Hour == sysCfg.hlw_mkwhs)) {
hlw_mkwh_state = 1;
snprintf_P(svalue, sizeof(stopic), PSTR("{\"EnergyMonitor\":\"%s\"}"), MQTT_STATUS_ON);
mqtt_publish(stopic, svalue);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"EnergyMonitor\":\"%s\"}"), MQTT_STATUS_ON);
mqtt_publish_topic_P(0, PSTR("RESULT"), svalue);
do_cmnd_power(1, 1);
}
else if ((hlw_mkwh_state == 1) && (uped >= sysCfg.hlw_mkwh)) {
hlw_mkwh_state = 2;
dtostrf(ped, 1, 3, svalue);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxEnergyReached\":\"%s%s\"}"), svalue, (sysCfg.value_units) ? " kWh" : "");
mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(0, PSTR("WARNING"), svalue);
do_cmnd_power(1, 0);
}
}
@ -512,7 +510,7 @@ boolean hlw_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len
void hlw_commands(char *svalue, uint16_t ssvalue)
{
snprintf_P(svalue, ssvalue, PSTR("{\"Commands\":\"PowerLow, PowerHigh, VoltageLow, VoltageHigh, CurrentLow, CurrentHigh, HlwPcal, HlwUcal, HlwIcal%s\"}"),
snprintf_P(svalue, ssvalue, PSTR("{\"Commands5\":\"PowerLow, PowerHigh, VoltageLow, VoltageHigh, CurrentLow, CurrentHigh, HlwPcal, HlwUcal, HlwIcal%s\"}"),
(FEATURE_POWER_LIMIT)?", SafePower, SafePowerHold, SafePowerWindow, MaxPower, MaxPowerHold, MaxPowerWindow, MaxEnergy, MaxEnergyStart":"");
}
@ -520,29 +518,50 @@ void hlw_commands(char *svalue, uint16_t ssvalue)
* Presentation
\*********************************************************************************************/
void hlw_mqttPresent(uint8_t domidx)
void hlw_mqttStat(byte option, char* svalue, uint16_t ssvalue)
{
char stopic[TOPSZ], svalue[MESSZ], stime[21], stemp0[10], stemp1[10], stemp2[10], stemp3[10];
char stemp0[10], stemp1[10], stemp2[10], stemp3[10], speriod[20];
float ped, pi, pc;
uint16_t pe, pw, pu;
snprintf_P(stime, sizeof(stime), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"),
rtcTime.Year, rtcTime.Month, rtcTime.Day, rtcTime.Hour, rtcTime.Minute, rtcTime.Second);
hlw_readEnergy(1, ped, pe, pw, pu, pi, pc);
hlw_readEnergy(option, ped, pe, pw, pu, pi, pc);
dtostrf((float)sysCfg.hlw_kWhyesterday / 100000000, 1, 3, stemp0);
dtostrf(ped, 1, 3, stemp1);
dtostrf(pc, 1, 2, stemp2);
dtostrf(pi, 1, 3, stemp3);
snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/TELEMETRY"), PUB_PREFIX2, sysCfg.mqtt_topic);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\", \"Energy\":{\"Yesterday\":\"%s\", \"Today\":\"%s\", \"Period\":%d, \"Power\":%d, \"Factor\":\"%s\", \"Voltage\":%d, \"Current\":\"%s\"}}"),
stime, stemp0, stemp1, pe, pw, stemp2, pu, stemp3);
mqtt_publish(stopic, svalue);
snprintf_P(speriod, sizeof(speriod), PSTR(", \"Period\":%d"), pe);
snprintf_P(svalue, ssvalue, PSTR("%s\"Yesterday\":\"%s\", \"Today\":\"%s\"%s, \"Power\":%d, \"Factor\":\"%s\", \"Voltage\":%d, \"Current\":\"%s\"}"),
svalue, stemp0, stemp1, (option) ? speriod : "", pw, stemp2, pu, stemp3);
#ifdef USE_DOMOTICZ
dtostrf(ped * 1000, 1, 1, stemp1);
domoticz_sensor4(pw, stemp1);
#endif // USE_DOMOTICZ
}
void hlw_mqttPresent()
{
// char stopic[TOPSZ], svalue[MESSZ], stime[21];
char svalue[MESSZ], stime[21];
snprintf_P(stime, sizeof(stime), PSTR("%04d-%02d-%02dT%02d:%02d:%02d"),
rtcTime.Year, rtcTime.Month, rtcTime.Day, rtcTime.Hour, rtcTime.Minute, rtcTime.Second);
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\", "), stime);
hlw_mqttStat(1, svalue, sizeof(svalue));
// snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/ENERGY"), PUB_PREFIX2, sysCfg.mqtt_topic);
// mqtt_publish(stopic, svalue);
mqtt_publish_topic_P(1, PSTR("ENERGY"), svalue);
}
void hlw_mqttStatus(char* svalue, uint16_t ssvalue)
{
snprintf_P(svalue, ssvalue, PSTR("{\"StatusPWR\":{"));
hlw_mqttStat(0, svalue, ssvalue);
snprintf_P(svalue, ssvalue, PSTR("%s}"), svalue);
}
#ifdef USE_WEBSERVER
String hlw_webPresent()
{

View File

@ -229,7 +229,7 @@ uint8_t htu_detect()
* Presentation
\*********************************************************************************************/
void htu_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson, uint8_t domidx)
void htu_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
{
if (!htutype) return;