Внимание! Перед прошивкой по USB-UART отключите AC питания sonoff
c:\documents and settings\USERNAME\local settings\application data\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\bits\stl_algobase.h:59:28: fatal error: bits/c++config.h: No such file or directory
#include <bits/c++config.h>
compilation terminated.
exit status 1
Flash Mode: QIO
Flash Frequency: 40MHz
Upload Using: Serial
CPU Frequency: 80MHz
Flash Size: 1M (64K SPIFFS)
Debug Port: Disabled
Debug Level: None
Reset Method: ck
Upload Speed: 115200
Port: Ваш COM-порт к которому подключен sonoff
#define PROJECT "sonoff"
// Wifi
#define STA_SSID ""
#define STA_PASS ""
#define SERIAL_LOG_LEVEL LOG_LEVEL_DEBUG_MORE
// Ota
#if (ARDUINO >= 168)
#define OTA_URL "http://192.168.0.102:80/api/arduino/"PROJECT".ino.bin"
#else
#define OTA_URL "http://192.168.0.102:80/api/arduino/"PROJECT".cpp.bin"
#endif
// MQTT
#define MQTT_HOST "192.168.0.102"
#define MQTT_PORT 1883
...
#define MQTT_USER ""
#define MQTT_PASS ""
RTC: sntp 0, Thu Jan 01 00:00:00 1970
APP: Multipress 1
MQTT: sonoff/LIGHT = 2
MQTT: Receive topic cmnd/sonoff/LIGHT, data 2
MQTT: DataCb Topic sonoff, Group 0, Type LIGHT, data 2 (2)
MQTT: sonoff/LIGHT = On
Config: Saved configuration to flash at F9 and count 38
Wifi: Check connection
MQTT: Receive topic cmnd/sonoff/LIGHT, data off
MQTT: DataCb Topic sonoff, Group 0, Type LIGHT, data off (OFF)
MQTT: sonoff/LIGHT = Off
RTC: sntp 0, Thu Jan 01 00:00:00 1970
/*
* Sonoff and Wkaku by Theo Arends
*
* ESP-12F connections (Wkaku)
* 3V3 5V
* |-------------------| |---------|
* | | ------------- | |1N4001| |Relay|
* | | -| Tx |- | |---------|
* | | -| Rx |- | /
* |-------------------| En |- |---| 1k|------|< BC547B
* | | -| |- \
* | | -| IO00 |------|Switch|------|
* | ---| IO12 IO02 |--- LED (ESP-12E/F) |
* |---| 1k|---|LED|---| IO13 IO15 |------|10k|---------|
* |-------------------| Vcc Gnd |--------------------|
* ------------- |
* | | | | | | Gnd
*/
#define PROJECT "sonoff"
#define VERSION 0x01000C00 // 1.0.12
#define CFG_HOLDER 0x20160520 // Change this value to load default configurations
// Wifi
#define STA_SSID ""
#define STA_PASS ""
#define WIFI_HOSTNAME "esp-%06x-%s"
// Syslog
#define LOG_LEVEL_NONE 0
#define LOG_LEVEL_ERROR 1
#define LOG_LEVEL_INFO 2
#define LOG_LEVEL_DEBUG 3
#define LOG_LEVEL_DEBUG_MORE 4
#define SYS_LOG_HOST "sidnas2"
#define SYS_LOG_PORT 514
#define SYS_LOG_LEVEL LOG_LEVEL_NONE
#define SERIAL_LOG_LEVEL LOG_LEVEL_DEBUG_MORE
// Ota
#if (ARDUINO >= 168)
#define OTA_URL "http://192.168.0.102:80/api/arduino/"PROJECT".ino.bin"
#else
#define OTA_URL "http://192.168.0.102:80/api/arduino/"PROJECT".cpp.bin"
#endif
// MQTT
#define MQTT_HOST ""
#define MQTT_PORT 1883
#define MQTT_CLIENT_ID "DVES_%06X" // Also fall back topic using Chip Id = last 6 characters of MAC address
#define MQTT_USER ""
#define MQTT_PASS ""
#define SUB_PREFIX "cmnd"
#define PUB_PREFIX "stat"
#define MQTT_GRPTOPIC PROJECT"s" // Group topic
#define MQTT_TOPIC PROJECT
// Application
#define MQTT_SUBTOPIC "POWER"
#define APP_TIMEZONE 1 // +1 hour (Amsterdam)
#define APP_POWER 0 // Saved power state Off
// End of user defines **************************************************************************
#define SERIAL_IO // Enable serial command line
#define STATES 10 // loops per second
#define MQTT_RETRY_SECS 10 // Seconds to retry MQTT connection
//#define LED_PIN 2 // GPIO 2 = Blue Led (0 = On, 1 = Off) - ESP-12
#define LED_PIN 13 // GPIO 13 = Green Led (0 = On, 1 = Off) - Sonoff
//#define LED_PIN 16 // NodeMCU
#define REL_PIN 12 // GPIO 12 = Red Led and Relay (0 = Off, 1 = On)
#define KEY_PIN 0 // GPIO 00 = Button
#define PRESSED 0
#define NOT_PRESSED 1
#define WIFI_STATUS 0
#define WIFI_SMARTCONFIG 1
#ifdef DEBUG_ESP_PORT
#define DEBUG_MSG(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ )
#else
#define DEBUG_MSG(...)
#endif
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266httpUpdate.h>
#include <PubSubClient.h>
#include <livolo.h>
extern "C" uint32_t _SPIFFS_start;
struct SYSCFG {
unsigned long cfg_holder;
unsigned long saveFlag;
unsigned long version;
byte seriallog_level;
byte syslog_level;
char syslog_host[32];
char sta_ssid[32];
char sta_pwd[64];
char otaUrl[80];
char mqtt_host[32];
char mqtt_grptopic[32];
char mqtt_topic[32];
char mqtt_topic2[32];
char mqtt_subtopic[32];
int8_t timezone;
uint8_t power;
} sysCfg;
struct TIME_T {
uint8_t Second;
uint8_t Minute;
uint8_t Hour;
uint8_t Wday; // day of week, sunday is day 1
uint8_t Day;
uint8_t Month;
char MonthName[4];
uint16_t Year;
unsigned long Valid;
} rtcTime;
char Version[16];
char Hostname[32];
uint8_t mqttcounter = 0;
unsigned long timerxs = 0, timersec = 0;
int state = 0;
int otaflag = 0;
int restartflag = 0;
int smartconfigflag = 0;
int heartbeatflag = 0;
int heartbeat = 0;
WiFiClient espClient;
PubSubClient mqttClient(espClient);
WiFiUDP portUDP; // syslog
int blinks = 1;
uint8_t blinkstate = 1;
uint8_t lastbutton = NOT_PRESSED;
uint8_t holdcount = 0;
uint8_t multiwindow = 0;
uint8_t multipress = 0;
/*********************************************************************************************\
* Livolo
\*********************************************************************************************/
Livolo livolo(14); // transmitter connected to pin #14
void sendCommand(String str) {
String sRemoteID, sKeyCode;
int curIndex = str.indexOf(',');
sRemoteID = str.substring(0, curIndex);
sKeyCode = str.substring(curIndex +1, -1);
if(sRemoteID.startsWith("RemoteID:")) {
sRemoteID = sRemoteID.substring(sRemoteID.lastIndexOf(':') +1,-1);
}
if(sKeyCode.startsWith("KeyCode:")) {
sKeyCode = sKeyCode.substring(sKeyCode.lastIndexOf(':') +1,-1);
}
int iRemoteID = sRemoteID.toInt();
int iKeyCode = sKeyCode.toInt();
livolo.sendButton(sRemoteID.toInt(), sKeyCode.toInt());
}
/*********************************************************************************************\
* Syslog
\*********************************************************************************************/
void syslog(const char *message)
{
char mess[168], str[200];
portUDP.beginPacket(sysCfg.syslog_host, SYS_LOG_PORT);
strncpy(mess, message, 167);
mess[168] = 0;
sprintf_P(str, PSTR("%s %s"), Hostname, mess);
portUDP.write(str);
portUDP.endPacket();
}
void addLog(byte loglevel, const char *line)
{
DEBUG_MSG("DebugMsg %s\n", line);
#ifdef SERIAL_IO
if (loglevel <= sysCfg.seriallog_level) Serial.println(line);
#endif
if ((WiFi.status() == WL_CONNECTED) && (loglevel <= sysCfg.syslog_level)) syslog(line);
}
void addLog(byte loglevel, String& string)
{
addLog(loglevel, string.c_str());
}
/********************************************************************************************/
void mqtt_publish(const char* topic, const char* data)
{
char log[300];
mqttClient.publish(topic, data);
sprintf_P(log, PSTR("MQTT: %s = %s"), strchr(topic,'/')+1, data); // Skip topic prefix
addLog(LOG_LEVEL_INFO, log);
mqttClient.loop(); // Solve LmacRxBlk:1 messages
blinks++;
}
void mqtt_connected()
{
char stopic[40], svalue[40];
sprintf_P(stopic, PSTR("%s/%s/#"), SUB_PREFIX, sysCfg.mqtt_topic);
mqttClient.subscribe(stopic);
mqttClient.loop(); // Solve LmacRxBlk:1 messages
sprintf_P(stopic, PSTR("%s/%s/#"), SUB_PREFIX, sysCfg.mqtt_grptopic);
mqttClient.subscribe(stopic);
mqttClient.loop(); // Solve LmacRxBlk:1 messages
sprintf_P(stopic, PSTR("%s/"MQTT_CLIENT_ID"/#"), SUB_PREFIX, ESP.getChipId()); // Fall back topic
mqttClient.subscribe(stopic);
mqttClient.loop(); // Solve LmacRxBlk:1 messages
sprintf_P(stopic, PSTR("%s/%s/NAME"), PUB_PREFIX, sysCfg.mqtt_topic);
sprintf_P(svalue, PSTR("Sonoff switch"));
mqtt_publish(stopic, svalue);
sprintf_P(stopic, PSTR("%s/%s/VERSION"), PUB_PREFIX, sysCfg.mqtt_topic);
sprintf_P(svalue, PSTR("%s"), Version);
mqtt_publish(stopic, svalue);
sprintf_P(stopic, PSTR("%s/%s/FALLBACKTOPIC"), PUB_PREFIX, sysCfg.mqtt_topic);
sprintf_P(svalue, PSTR(MQTT_CLIENT_ID), ESP.getChipId());
mqtt_publish(stopic, svalue);
}
void mqtt_reconnect()
{
char stopic[40], svalue[40], log[80];
mqttcounter = MQTT_RETRY_SECS;
addLog(LOG_LEVEL_INFO, "MQTT: Attempting connection");
sprintf(svalue, MQTT_CLIENT_ID, ESP.getChipId());
sprintf_P(stopic, PSTR("%s/%s/lwt"), PUB_PREFIX, sysCfg.mqtt_topic);
if (mqttClient.connect(svalue, MQTT_USER, MQTT_PASS, stopic, 0, 0, "offline")) {
addLog(LOG_LEVEL_INFO, "MQTT: Connected");
mqttcounter = 0;
mqtt_connected();
} else {
sprintf_P(log, PSTR("MQTT: Connect failed, rc %d. Retry in %d seconds"), mqttClient.state(), mqttcounter);
addLog(LOG_LEVEL_DEBUG, log);
}
}
void mqttDataCb(char* topic, byte* data, unsigned int data_len)
{
int i, grpflg = 0;
char *str, *p, *mtopic = NULL, *type = NULL;
char stopic[40], svalue[240];
int topic_len = strlen(topic);
char topicBuf[topic_len +1];
char dataBuf[data_len +1];
char dataBufUc[data_len +1];
memcpy(topicBuf, topic, topic_len);
topicBuf[topic_len] = 0;
memcpy(dataBuf, data, data_len);
dataBuf[data_len] = 0;
sprintf_P(svalue, PSTR("MQTT: Receive topic %s, data %s"), topicBuf, dataBuf);
addLog(LOG_LEVEL_DEBUG, svalue);
i = 0;
for (str = strtok_r(topicBuf, "/", &p); str && i < 3; str = strtok_r(NULL, "/", &p)) {
switch (i++) {
case 0: // cmnd
break;
case 1: // Topic / GroupTopic / DVES_123456
mtopic = str;
break;
case 2: // Text
type = str;
}
}
if (!strcmp(mtopic, sysCfg.mqtt_grptopic)) grpflg = 1;
if (type != NULL) for(i = 0; i < strlen(type); i++) type[i] = toupper(type[i]);
for(i = 0; i <= data_len; i++) dataBufUc[i] = toupper(dataBuf[i]);
sprintf_P(svalue, PSTR("MQTT: DataCb Topic %s, Group %d, Type %s, data %s (%s)"),
mtopic, grpflg, type, dataBuf, dataBufUc);
addLog(LOG_LEVEL_DEBUG, svalue);
if (type != NULL) {
sprintf_P(stopic, PSTR("%s/%s/%s"), PUB_PREFIX, sysCfg.mqtt_topic, type);
strcpy(svalue, "Error");
uint16_t payload = atoi(dataBuf);
if (!strcmp(dataBufUc,"OFF")) payload = 0;
if (!strcmp(dataBufUc,"ON")) payload = 1;
if (!strcmp(dataBufUc,"TOGGLE")) payload = 2;
if (!strcmp(type,"STATUS")) {
switch (payload) {
case 1:
sprintf_P(svalue, PSTR("%s, "MQTT_CLIENT_ID", %s, %s, %d, %d"),
sysCfg.mqtt_grptopic, ESP.getChipId(), sysCfg.otaUrl, sysCfg.mqtt_host, heartbeat, sysCfg.saveFlag);
break;
case 2:
sprintf_P(svalue, PSTR("Version %s, Boot %d, SDK %s"),
Version, ESP.getBootVersion(), ESP.getSdkVersion());
break;
case 3:
sprintf_P(svalue, PSTR("Seriallog %d, Syslog %d, LogHost %s, SSId %s, Password %s"),
sysCfg.seriallog_level, sysCfg.syslog_level, sysCfg.syslog_host, sysCfg.sta_ssid, sysCfg.sta_pwd);
break;
case 4:
sprintf_P(svalue, PSTR("Sketch size %d, Free %d (Heap %d), Spiffs start %d, Flash size %d (%d)"),
ESP.getSketchSize(), ESP.getFreeSketchSpace(), ESP.getFreeHeap(), (uint32_t)&_SPIFFS_start - 0x40200000,
ESP.getFlashChipRealSize(), ESP.getFlashChipSize());
break;
case 5: {
IPAddress ip = WiFi.localIP();
IPAddress gw = WiFi.gatewayIP();
IPAddress nm = WiFi.subnetMask();
sprintf_P(svalue, PSTR("Hostname %s, IP %u.%u.%u.%u, Gateway %u.%u.%u.%u, Subnetmask %u.%u.%u.%u"),
Hostname, ip[0], ip[1], ip[2], ip[3], gw[0], gw[1], gw[2], gw[3], nm[0], nm[1], nm[2], nm[3]);
break;
}
default:
sprintf_P(svalue, PSTR("%s, %s, %s, %s, %d, %d"),
Version, sysCfg.mqtt_topic, sysCfg.mqtt_topic2, sysCfg.mqtt_subtopic, sysCfg.power, sysCfg.timezone);
}
}
else if (!grpflg && !strcmp(type,"UPGRADE")) {
if ((data_len > 0) && (payload == 1)) {
otaflag = 3;
sprintf_P(svalue, PSTR("Upgrade %s"), Version);
}
else
sprintf_P(svalue, PSTR("1 to upgrade"));
}
else if (!grpflg && !strcmp(type,"OTAURL")) {
if ((data_len > 0) && (data_len < 80))
strcpy(sysCfg.otaUrl, (payload == 1) ? OTA_URL : dataBuf);
sprintf_P(svalue, PSTR("%s"), sysCfg.otaUrl);
}
else if (!strcmp(type,"SERIALLOG")) {
if ((data_len > 0) && (payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_DEBUG_MORE)) {
sysCfg.seriallog_level = payload;
}
sprintf_P(svalue, PSTR("%d"), sysCfg.seriallog_level);
}
else if (!strcmp(type,"SYSLOG")) {
if ((data_len > 0) && (payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_DEBUG_MORE)) {
sysCfg.syslog_level = payload;
}
sprintf_P(svalue, PSTR("%d"), sysCfg.syslog_level);
}
else if (!strcmp(type,"LOGHOST")) {
if ((data_len > 0) && (data_len < 32)) {
strcpy(sysCfg.syslog_host, (payload == 1) ? SYS_LOG_HOST : dataBuf);
restartflag = 2;
}
sprintf_P(svalue, PSTR("%s"), sysCfg.syslog_host);
}
else if (!grpflg && !strcmp(type,"SSID")) {
if ((data_len > 0) && (data_len < 32)) {
strcpy(sysCfg.sta_ssid, (payload == 1) ? STA_SSID : dataBuf);
restartflag = 2;
}
sprintf_P(svalue, PSTR("%s"), sysCfg.sta_ssid);
}
else if (!grpflg && !strcmp(type,"PASSWORD")) {
if ((data_len > 0) && (data_len < 64)) {
strcpy(sysCfg.sta_pwd, (payload == 1) ? STA_PASS : dataBuf);
restartflag = 2;
}
sprintf_P(svalue, PSTR("%s"), sysCfg.sta_pwd);
}
else if (!grpflg && !strcmp(type,"MQTTHOST")) {
if ((data_len > 0) && (data_len < 32)) {
strcpy(sysCfg.mqtt_host, (payload == 1) ? MQTT_HOST : dataBuf);
restartflag = 2;
}
sprintf_P(svalue, PSTR("%s"), sysCfg.mqtt_host);
}
else if (!strcmp(type,"GROUPTOPIC")) {
if ((data_len > 0) && (data_len < 32)) {
for(i = 0; i <= data_len; i++)
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#')) dataBuf[i] = '_';
sprintf_P(svalue, PSTR(MQTT_CLIENT_ID), ESP.getChipId());
if (!strcmp(dataBuf, svalue)) payload = 1;
strcpy(sysCfg.mqtt_grptopic, (payload == 1) ? MQTT_GRPTOPIC : dataBuf);
restartflag = 2;
}
sprintf_P(svalue, PSTR("%s"), sysCfg.mqtt_grptopic);
}
else if (!grpflg && !strcmp(type,"TOPIC")) {
if ((data_len > 0) && (data_len < 32)) {
for(i = 0; i <= data_len; i++)
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#')) dataBuf[i] = '_';
sprintf_P(svalue, PSTR(MQTT_CLIENT_ID), ESP.getChipId());
if (!strcmp(dataBuf, svalue)) payload = 1;
strcpy(sysCfg.mqtt_topic, (payload == 1) ? MQTT_TOPIC : dataBuf);
restartflag = 2;
}
sprintf_P(svalue, PSTR("%s"), sysCfg.mqtt_topic);
}
else if (!grpflg && !strcmp(type,"BUTTONTOPIC")) {
if ((data_len > 0) && (data_len < 32)) {
for(i = 0; i <= data_len; i++)
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#')) dataBuf[i] = '_';
sprintf_P(svalue, PSTR(MQTT_CLIENT_ID), ESP.getChipId());
if (!strcmp(dataBuf, svalue)) payload = 1;
strcpy(sysCfg.mqtt_topic2, (payload == 1) ? MQTT_TOPIC : dataBuf);
}
sprintf_P(svalue, PSTR("%s"), sysCfg.mqtt_topic2);
}
else if (!grpflg && !strcmp(type,"SMARTCONFIG")) {
if ((data_len > 0) && (payload == 1)) {
blinks = 1999;
smartconfigflag = 1;
sprintf_P(svalue, PSTR("Smartconfig started"));
} else
sprintf_P(svalue, PSTR("1 to start smartconfig"));
}
else if (!grpflg && !strcmp(type,"RESTART")) {
if ((data_len > 0) && (payload == 1)) {
restartflag = 2;
sprintf_P(svalue, PSTR("Restarting"));
} else
sprintf_P(svalue, PSTR("1 to restart"));
}
else if (!grpflg && !strcmp(type,"RESET")) {
switch (payload) {
case 1:
restartflag = 11;
sprintf_P(svalue, PSTR("Reset and Restarting"));
break;
case 2:
restartflag = 12;
sprintf_P(svalue, PSTR("Erase, Reset and Restarting"));
break;
default:
sprintf_P(svalue, PSTR("1 to reset"));
}
}
else if (!grpflg && !strcmp(type,"LIVOLO")) {
sprintf(sysCfg.mqtt_subtopic, "%s", type);
if ((data_len > 0) && (data_len < 32)) {
sendCommand((const char*)dataBuf);
sprintf_P(svalue, PSTR("Livolo send"));
} else
sprintf_P(svalue, PSTR("Livolo data wrong"));
}
if (!strcmp(type,"TIMEZONE")) {
if ((data_len > 0) && (payload >= -12) && (payload <= 12)) {
sysCfg.timezone = payload;
rtc_timezone(sysCfg.timezone);
}
sprintf_P(svalue, PSTR("%d"), sysCfg.timezone);
}
else if ((!strcmp(type,"LIGHT")) || (!strcmp(type,"POWER")) || (!strcmp(type,"LIVOLO"))) {
sprintf(sysCfg.mqtt_subtopic, "%s", type);
if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
switch (payload) {
case 0: // Off
case 1: // On
sysCfg.power = payload;
break;
case 2: // Toggle
sysCfg.power ^= 1;
break;
}
digitalWrite(REL_PIN, sysCfg.power);
}
strcpy(svalue, (sysCfg.power) ? "On" : "Off");
}
else {
type = NULL;
}
if (type == NULL) {
blinks = 1;
sprintf_P(stopic, PSTR("%s/%s/SYNTAX"), PUB_PREFIX, sysCfg.mqtt_topic);
if (!grpflg)
strcpy_P(svalue, PSTR("Status, Upgrade, Otaurl, Restart, Reset, Smartconfig, Seriallog, Syslog, LogHost, SSId, Password, MqttHost, GroupTopic, Topic, ButtonTopic, Timezone, Light, Power, Livolo"));
else
strcpy_P(svalue, PSTR("Status, GroupTopic, Timezone, Light, Power"));
}
mqtt_publish(stopic, svalue);
}
}
void send_button(char *cmnd)
{
char stopic[128], svalue[128];
char *token;
token = strtok(cmnd, " ");
if ((!strcmp(token,"light")) || (!strcmp(token,"power"))) strcpy(token, sysCfg.mqtt_subtopic);
sprintf_P(stopic, PSTR("%s/%s/%s"), SUB_PREFIX, sysCfg.mqtt_topic2, token);
token = strtok(NULL, "");
sprintf_P(svalue, PSTR("%s"), (token == NULL) ? "" : token);
mqtt_publish(stopic, svalue);
}
void do_cmnd(char *cmnd)
{
char stopic[128], svalue[128];
char *token;
token = strtok(cmnd, " ");
sprintf_P(stopic, PSTR("%s/%s/%s"), SUB_PREFIX, sysCfg.mqtt_topic, token);
token = strtok(NULL, "");
sprintf_P(svalue, PSTR("%s"), (token == NULL) ? "" : token);
mqttDataCb(stopic, (byte*)svalue, strlen(svalue));
}
void send_power()
{
char stopic[40], svalue[20];
sprintf_P(stopic, PSTR("%s/%s/%s"), PUB_PREFIX, sysCfg.mqtt_topic, sysCfg.mqtt_subtopic);
strcpy(svalue, (sysCfg.power == 0) ? "Off" : "On");
mqtt_publish(stopic, svalue);
}
void send_updateStatus(const char* svalue)
{
char stopic[40];
sprintf_P(stopic, PSTR("%s/%s/UPGRADE"), PUB_PREFIX, sysCfg.mqtt_topic);
mqtt_publish(stopic, svalue);
}
void every_second()
{
char stopic[40], svalue[20];
if (heartbeatflag) {
heartbeatflag = 0;
heartbeat++;
sprintf_P(stopic, PSTR("%s/%s/HEARTBEAT"), PUB_PREFIX, sysCfg.mqtt_topic);
sprintf_P(svalue, PSTR("%d"), heartbeat);
mqtt_publish(stopic, svalue);
}
}
const char commands[6][14] PROGMEM = {
{"reset 1"}, // Hold button for more than 4 seconds
{"light 2"}, // Press button once
{"light 2"}, // Press button twice
{"smartconfig 1"}, // Press button three times
{"upgrade 1"}, // Press button four times
{"restart 1"}}; // Press button five times
void stateloop()
{
uint8_t button;
char scmnd[20], log[30];
timerxs = millis() + (1000 / STATES);
state++;
if (state == STATES) { // Every second
state = 0;
every_second();
}
button = digitalRead(KEY_PIN);
if ((button == PRESSED) && (lastbutton == NOT_PRESSED)) {
multipress = (multiwindow) ? multipress +1 : 1;
sprintf_P(log, PSTR("APP: Multipress %d"), multipress);
addLog(LOG_LEVEL_DEBUG, log);
blinks = 1;
multiwindow = STATES /2; // 1/2 second multi press window
}
lastbutton = button;
if (button == NOT_PRESSED) {
holdcount = 0;
} else {
holdcount++;
if (holdcount == (STATES *4)) { // 4 seconds button hold
strcpy_P(scmnd, commands[0]);
multipress = 0;
do_cmnd(scmnd);
}
}
if (multiwindow) {
multiwindow--;
} else {
if ((!holdcount) && (multipress >= 1) && (multipress <= 5)) {
strcpy_P(scmnd, commands[multipress]);
if (strcmp(sysCfg.mqtt_topic2,"0") && (multipress == 1) && mqttClient.connected())
send_button(scmnd); // Execute command via MQTT using ButtonTopic to sync external clients
else
do_cmnd(scmnd); // Execute command internally
multipress = 0;
}
}
if ((blinks || restartflag || otaflag) && (!(state % ((STATES/10)*2)))) {
if (restartflag || otaflag)
blinkstate = 0; // Stay lit
else
blinkstate ^= 1; // Blink
digitalWrite(LED_PIN, blinkstate);
if (blinkstate) blinks--;
}
switch (state) {
case (STATES/10)*2:
if (otaflag) {
otaflag--;
if (otaflag <= 0) {
otaflag = 255;
ESPhttpUpdate.update(sysCfg.otaUrl);
send_updateStatus(ESPhttpUpdate.getLastErrorString().c_str());
restartflag = 2;
}
}
break;
case (STATES/10)*4:
CFG_Save();
if (restartflag) {
if (restartflag == 11) {
CFG_Default();
restartflag = 2;
}
if (restartflag == 12) {
CFG_Erase();
restartflag = 1;
}
restartflag--;
if (restartflag <= 0) ESP.restart();
}
break;
case (STATES/10)*6:
if (smartconfigflag) {
smartconfigflag = 0;
WIFI_Check(WIFI_SMARTCONFIG);
} else {
WIFI_Check(WIFI_STATUS);
}
break;
case (STATES/10)*8:
if ((WiFi.status() == WL_CONNECTED) && (!mqttClient.connected())) {
if (!mqttcounter)
mqtt_reconnect();
else
mqttcounter--;
}
break;
}
}
#ifdef SERIAL_IO
#define INPUT_BUFFER_SIZE 128
byte SerialInByte;
int SerialInByteCounter = 0;
char serialInBuf[INPUT_BUFFER_SIZE + 2];
void serial()
{
while (Serial.available())
{
yield();
SerialInByte = Serial.read();
if (SerialInByte > 127) // binary data...
{
Serial.flush();
SerialInByteCounter = 0;
return;
}
if (isprint(SerialInByte))
{
if (SerialInByteCounter < INPUT_BUFFER_SIZE) // add char to string if it still fits
serialInBuf[SerialInByteCounter++] = SerialInByte;
else
SerialInByteCounter = 0;
}
if (SerialInByte == '\n')
{
serialInBuf[SerialInByteCounter] = 0; // serial data completed
Serial.println(serialInBuf);
SerialInByteCounter = 0;
do_cmnd(serialInBuf);
}
}
}
#endif
void setup()
{
char log[128];
Serial.begin(115200);
delay(10);
Serial.println();
sprintf_P(Version, PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff);
if (VERSION & 0x1f) {
byte idx = strlen(Version);
Version[idx] = 96 + (VERSION & 0x1f);
Version[idx +1] = 0;
}
CFG_Load();
if (sysCfg.version != VERSION) { // Fix version dependent changes
sysCfg.version = VERSION;
}
sprintf_P(Hostname, PSTR(WIFI_HOSTNAME), ESP.getChipId(), sysCfg.mqtt_topic);
WIFI_Connect(Hostname);
mqttClient.setServer(sysCfg.mqtt_host, MQTT_PORT);
mqttClient.setCallback(mqttDataCb);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, blinkstate);
pinMode(REL_PIN, OUTPUT);
digitalWrite(REL_PIN, sysCfg.power);
pinMode(KEY_PIN, INPUT_PULLUP);
rtc_init(sysCfg.timezone);
sprintf_P(log, PSTR("App: Project %s (Topic %s, Fallback "MQTT_CLIENT_ID", GroupTopic %s) Version %s"),
PROJECT, sysCfg.mqtt_topic, ESP.getChipId(), sysCfg.mqtt_grptopic, Version);
addLog(LOG_LEVEL_INFO, log);
}
void loop()
{
if (millis() >= timersec) {
timersec = millis() + 1000;
rtc_second();
if ((rtcTime.Minute == 2) && (rtcTime.Second == 30)) heartbeatflag = 1;
}
if (millis() >= timerxs) stateloop();
mqttClient.loop();
#ifdef SERIAL_IO
if (Serial.available()) serial();
#endif
yield();
}
RemoteID:23801,KeyCode:8
+17 |
3654
102
|
Посылаем команду -> MQTT-сервер < — Sonoff по Wifi её считывает и отправляет по RF-> выключателю Livolo
Sonoff RF имеет на борту только RF-приемник, т.е. из коробки ничего передавать не может.
То, что РЕАЛЬНЫЙ статус в телефоне показывается цветом иконки это конечно радует, но не более. Не всегда можно постоянно смотреть статус, хотелось бы быть уверенным, что если включил (и электричество через минуту перемигнет), то устройство вернется в прежнее состояние. Вот например розетка Сяоми (по крайней мере 2я версия) помнит состояние.
P.S. Если кому интересно, доставка одного девайса до Новосибирска 4,61 бакса показывает. Четыре девайса 8,61$ доставка.
А запросить состояние у ливоло невозможно
Подскажите, а реально реализовать управление димером от Livolo?
github.com/arendst/Sonoff-MQTT-OTA-Arduino
Но ни слова про поддержку димера от Livolo.
Подскажите какая батарейка идет в пульт Sonoff?
А вопрос следующий.
Sonoff basic или RF например из коробки. Вот скажем задан цикличный таймер 20 минут включено/ 20 минут выключено.
А что будет, если интернет отрубится? Sonoff продолжит включать/выключать? Или нафиг все работать перестанет сразу, и просто будет состояние выключено?
Спасибо