Всем привет! Внесу свои 5 копеек.
Ремонт закончен. Естественно в подрозетнике выключателя два провода в разрыв фазы, выключатель обычный одноклавишный. Сделал из того что нашлось быстро:
1. исполнительное устройство [ac/dc 5в 700мА->WemosD1mini+RelayShild]. LED люстра подключена к нормально разомкнутым контактам реле. По сути, выключатель включает устройство, которое включает люстру. Модуль живет под натяжным потолком.
2. В МД объект типа Relay со свойством status.
Логика работы:
1. Включаем выключатель, esp загружается, запрашивает текущий статус у МД, выставляет реле в актуальное состояние.
2. Если связи с МД нет - включает реле. Можно проще - подключить люстру к нормально замкнутым контактам реле, в этом случае код упрощается, но при статусе 0 в МД необходимо будет включить реле. Это мне кажется немного неправильным, т.к. свет горит меньшую часть суток, а все остальное время реле будет с притянутым якорем.
3. Далее управляется из МД по сценариям/кнопкам методом HTTP GET. Причем статус объекта в МД устанавливает устройство отсылкой GET запроса к свойству объекта (реализация обратной связи. Статус в МД не изменится, если не получен ответ).
4. Доступность устройства проверяется через "устройства онлайн", напоминает, чтобы вернул выключатель во вкл.
Почему так и без MQTT:
1 и основное - ремонт, блин, закончен ))) Думал про умный дом, но в тонкости не вникал, а зря ((
2. Хочется сохранить возможность управления исполнительными устройствами в случае падения МД или умирания роутера. В случае падения МД задачи отправки GET запроса можно реализовать с помощью таскера или appinvertor'а. В тел на этот случай создается резервное приложение прямого управления устройствами. В случае умирания роутера - работает как обычный выключатель, устанавливая реле в 1 при отсутвии связи.
Из минусов - нарабатывание нового навыка не щелкать выключателям выходя из комнаты ))) + тщательная проработка сценариев, чтобы срабатывало когда надо. В остальном, на мой взгляд, резервирование достаточное. Без света не останешься, если компы подведут.
Повторюсь - такие сложности всего лишь из-за того, что не заложил доп провод в штробы, учту на будущее обязательно )))
Управление модулем:
http://ip/status/1 - вкл,
http://ip/status/0 - выкл.
Код прошивки Wemos прилагаю, шил через Arduino IDE. На чистоту кода не претендую, т.к. не программист далеко, но работает

.
Код: Выделить всё
#include <ESP8266WiFi.h>
const char* ssid = "***";
const char* password = "***"; // имя и пароль wifi
#define RPin D1 // пин реле
WiFiServer server(80); //заготовки для сервера и клиента (порт)
WiFiClient client;
IPAddress MDIP(192,168,1,114); //Majordomo (MD) IP
// переподключение wifi при потери связи
void WiFiReconnect(){
WiFi.disconnect();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
}
// выполняется при загрузке один раз
void setup() {
Serial.begin(115200);
delay(10);
// подготовка пина реле
pinMode(RPin, OUTPUT);
digitalWrite(RPin, 0);
// Подключение к wifi
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Print the IP address
Serial.println(WiFi.localIP());
delay(500);
// запрос состояния у мажордома
client.connect(MDIP, 80);
delay (500);
if (client.connected()) {
client.print("GET /objects/?object=HallLamp&op=m&m=refresh& HTTP/1.1\r\n"); //вызов метода refresh объекта HallLamp
client.print("Host: 192.168.1.114\r\n");
client.print("User-Agent: HallLamp\r\n");
client.print("Connection: close\r\n\r\n");
Serial.println("connected");
}
else {
// если МД не отвечает
Serial.println("connection failed");
digitalWrite(RPin, 1); // включаем реле
}
client.stop();
// запуск http сервера для приема команд управления
server.begin();
Serial.println("Server started");
}
// основной цикл
void loop() {
if (WiFi.status() != WL_CONNECTED) {WiFiReconnect;} // Если пропал вайфай - переподключение
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}
// Wait until the client sends some data
Serial.println("new client");
while(!client.available()){
delay(1);
}
// Read the first line of the request
String req = client.readStringUntil('\r');
Serial.println(req);
client.flush();
// Match the request
int val;
if (req.indexOf("/status/0") != -1)
val = 0;
else if (req.indexOf("/status/1") != -1)
val = 1;
else {
Serial.println("invalid request");
client.stop();
return;
}
// устанавливаем состояние реле
digitalWrite(RPin, val);
client.flush();
// ответ МД-му
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nGPIO is now ";
s += (val)?"On":"Off";
s += "</html>\n";
// Send the response to the client
client.print(s);
delay(1);
Serial.println("Client disonnected, send status");
client.connect(MDIP, 80);
client.print("GET /objects/?op=set&object=HallLamp&p=status&v="); //установка статуса объекта HallLamp
client.print(val);
client.print(" HTTP/1.1\r\n");
client.print("Host: 192.168.1.114\r\n");
client.print("User-Agent: HallLamp\r\n");
client.print("Connection: close\r\n\r\n");
Serial.println("connected");
client.stop();
}