diff --git a/README.md b/README.md
index 65c3da5..5850b0d 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# ESP-NOW switch for ESP8266
-ESP-NOW based switch for ESP8266. Alternate firmware for Tuya/SmartLife WiFi switches.
+ESP-NOW based switch for ESP8266. Alternate firmware for Tuya/SmartLife/eWeLink WiFi switches.
## Features
@@ -10,6 +10,7 @@ ESP-NOW based switch for ESP8266. Alternate firmware for Tuya/SmartLife WiFi swi
4. Automatically adds switch configuration to Home Assistan via MQTT discovery as a switch.
5. Possibility firmware update over OTA (if is allows the size of the flash memory).
6. Web interface for settings.
+7. Optionally support one external one wire digital climate sensor (DS18B20, DHT11 or DHT22) with automatically added sensor configuration to Home Assistan via MQTT discovery as a sensor. Periodically transmission sensor status (every 300 seconds) to the gateway.
## Notes
@@ -27,4 +28,4 @@ See [here](https://github.com/aZholtikov/ESP-NOW-Switch/tree/main/hardware).
2. ESP-NOW network name must be set same of all another ESP-NOW devices in network.
3. If encryption is used, the key must be set same of all another ESP-NOW devices in network.
4. Upload the "data" folder (with web interface) into the filesystem before flashing.
-5. For using this firmware on Tuya/SmartLife WiFi switches, the WiFi module must be replaced with an ESP8266 compatible module (if necessary).
+5. For using this firmware on Tuya/SmartLife/eWeLink WiFi switches, the WiFi module must be replaced with an ESP8266 compatible module (if necessary).
diff --git a/data/function.js b/data/function.js
index a4acbd2..a078387 100755
--- a/data/function.js
+++ b/data/function.js
@@ -37,6 +37,8 @@ function loadBlock() {
setGpioValue('buttonPinTypeSelect', 'buttonPinType');
setGpioValue('extButtonPinSelect', 'extButtonPin');
setGpioValue('extButtonPinTypeSelect', 'extButtonPinType');
+ setGpioValue('sensorPinSelect', 'sensorPin');
+ setGpioValue('sensorTypeSelect', 'sensorType');
handleServerResponse();
}
@@ -67,7 +69,9 @@ function saveSetting(submit) {
+ "&buttonPin=" + getSelectValue('buttonPinSelect')
+ "&buttonPinType=" + getSelectValue('buttonPinTypeSelect')
+ "&extButtonPin=" + getSelectValue('extButtonPinSelect')
- + "&extButtonPinType=" + getSelectValue('extButtonPinTypeSelect');
+ + "&extButtonPinType=" + getSelectValue('extButtonPinTypeSelect')
+ + "&sensorPin=" + getSelectValue('sensorPinSelect')
+ + "&sensorType=" + getSelectValue('sensorTypeSelect');
sendRequest(submit, server);
alert("Please restart device for changes apply.");
}
diff --git a/data/index.htm b/data/index.htm
index be8d55d..333fd45 100644
--- a/data/index.htm
+++ b/data/index.htm
@@ -145,6 +145,37 @@
+
+
Ext sensor GPIO:
+
+
+
+ NONE
+ GPIO01
+ GPIO02
+ GPIO03
+ GPIO04
+ GPIO05
+ GPIO06
+ GPIO07
+ GPIO08
+ GPIO09
+ GPIO10
+ GPIO11
+ GPIO12
+ GPIO13
+ GPIO14
+ GPIO15
+ GPIO16
+
+
+ NONE
+ DS18B20
+ DHT11
+ DHT22
+
+
+
diff --git a/hardware/README.md b/hardware/README.md
index 47b5537..581414c 100644
--- a/hardware/README.md
+++ b/hardware/README.md
@@ -3,17 +3,27 @@
1. MOES 1CH 10A. Built on Tuya WiFi module WA2 (WB2S) (BK7231T chip). Replacement required. Performed replacement with ESP-02S (analogue of TYWE2S but with 2Mb flash). [Photo](https://github.com/aZholtikov/ESP-NOW-Switch/tree/main/hardware/MOES_1CH_10A).
```text
- Relay GPIO GPIO12 HIGH
- Led GPIO GPIO04 LOW
- Button GPIO GPIO13 RISING
+ Relay GPIO GPIO12 HIGH
+ Led GPIO GPIO04 LOW
+ Button GPIO GPIO13 RISING
```
2. MINI 1CH 16A. Built on Tuya WiFi module WB2S (BK7231T chip). Replacement required. Performed replacement with ESP-02S (analogue of TYWE2S but with 2Mb flash). [Photo](https://github.com/aZholtikov/ESP-NOW-Switch/tree/main/hardware/MINI_1CH_16A).
```text
- Relay GPIO GPIO13 HIGH
- Led GPIO GPIO04 LOW
- Button GPIO GPIO03 RISING
- Ext Button GPIO GPIO14 FALLING
+ Relay GPIO GPIO13 HIGH
+ Led GPIO GPIO04 LOW
+ Button GPIO GPIO03 RISING
+ Ext button GPIO GPIO14 FALLING
```
-3. LIGHT E27 SOCKET (Coming soon)
+
+3. TH 1CH 16A + SENSOR. Built on ITEAD WiFi module PSF-B85 (ESP8285 chip). Replacement not required. [Photo](https://github.com/aZholtikov/ESP-NOW-Switch/tree/main/hardware/TH_1CH_16A). Attention! Because the button is connected to GPIO00 and the firmware does not work with GPIO00 required connect GPIO00 to GPIO04 on the module.
+
+```text
+ Relay GPIO GPIO12 HIGH
+ Led GPIO GPIO13 LOW
+ Button GPIO GPIO04 RISING
+ Ext sensor GPIO GPIO14 DS18B20
+```
+
+4. LIGHT E27 SOCKET (Coming soon)
diff --git a/hardware/TH_1CH_16A/PSF-B85.pdf b/hardware/TH_1CH_16A/PSF-B85.pdf
new file mode 100644
index 0000000..70e0b6c
Binary files /dev/null and b/hardware/TH_1CH_16A/PSF-B85.pdf differ
diff --git a/hardware/TH_1CH_16A/inside1.jpeg b/hardware/TH_1CH_16A/inside1.jpeg
new file mode 100644
index 0000000..6e06104
Binary files /dev/null and b/hardware/TH_1CH_16A/inside1.jpeg differ
diff --git a/hardware/TH_1CH_16A/inside2.jpeg b/hardware/TH_1CH_16A/inside2.jpeg
new file mode 100644
index 0000000..7438af6
Binary files /dev/null and b/hardware/TH_1CH_16A/inside2.jpeg differ
diff --git a/hardware/TH_1CH_16A/inside3.jpeg b/hardware/TH_1CH_16A/inside3.jpeg
new file mode 100644
index 0000000..226a169
Binary files /dev/null and b/hardware/TH_1CH_16A/inside3.jpeg differ
diff --git a/hardware/TH_1CH_16A/inside4.jpeg b/hardware/TH_1CH_16A/inside4.jpeg
new file mode 100644
index 0000000..f2560ca
Binary files /dev/null and b/hardware/TH_1CH_16A/inside4.jpeg differ
diff --git a/hardware/TH_1CH_16A/main1.jpeg b/hardware/TH_1CH_16A/main1.jpeg
new file mode 100644
index 0000000..edc0b36
Binary files /dev/null and b/hardware/TH_1CH_16A/main1.jpeg differ
diff --git a/hardware/TH_1CH_16A/main2.jpeg b/hardware/TH_1CH_16A/main2.jpeg
new file mode 100644
index 0000000..f319585
Binary files /dev/null and b/hardware/TH_1CH_16A/main2.jpeg differ
diff --git a/hardware/TH_1CH_16A/pins.jpeg b/hardware/TH_1CH_16A/pins.jpeg
new file mode 100644
index 0000000..e7476a3
Binary files /dev/null and b/hardware/TH_1CH_16A/pins.jpeg differ
diff --git a/hardware/TH_1CH_16A/sensor.jpeg b/hardware/TH_1CH_16A/sensor.jpeg
new file mode 100644
index 0000000..c963eee
Binary files /dev/null and b/hardware/TH_1CH_16A/sensor.jpeg differ
diff --git a/hardware/TH_1CH_16A/sensor_pin.jpeg b/hardware/TH_1CH_16A/sensor_pin.jpeg
new file mode 100644
index 0000000..7fb2f7d
Binary files /dev/null and b/hardware/TH_1CH_16A/sensor_pin.jpeg differ
diff --git a/platformio.ini b/platformio.ini
index 795627e..45e9abe 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -2,46 +2,72 @@
platform = espressif8266
board = esp12e
framework = arduino
+board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.4m2m.ld
lib_deps =
https://github.com/aZholtikov/ZHNetwork
https://github.com/aZholtikov/ZHConfig
+ https://github.com/aZholtikov/Async-Web-Server
https://github.com/bblanchon/ArduinoJson
- https://github.com/me-no-dev/ESPAsyncWebServer
+ https://github.com/milesburton/Arduino-Temperature-Control-Library
+ https://github.com/beegee-tokyo/DHTesp
[env:ESP-12E-OTA]
platform = espressif8266
board = esp12e
framework = arduino
+board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.4m2m.ld
upload_port = 192.168.4.1
upload_protocol = espota
lib_deps =
https://github.com/aZholtikov/ZHNetwork
https://github.com/aZholtikov/ZHConfig
+ https://github.com/aZholtikov/Async-Web-Server
https://github.com/bblanchon/ArduinoJson
- https://github.com/me-no-dev/ESPAsyncWebServer
+ https://github.com/milesburton/Arduino-Temperature-Control-Library
+ https://github.com/beegee-tokyo/DHTesp
[env:ESP-02S]
platform = espressif8266
board = esp8285
framework = arduino
+board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.2m256.ld
lib_deps =
https://github.com/aZholtikov/ZHNetwork
https://github.com/aZholtikov/ZHConfig
+ https://github.com/aZholtikov/Async-Web-Server
https://github.com/bblanchon/ArduinoJson
- https://github.com/me-no-dev/ESPAsyncWebServer
+ https://github.com/milesburton/Arduino-Temperature-Control-Library
+ https://github.com/beegee-tokyo/DHTesp
[env:ESP-02S-OTA]
platform = espressif8266
board = esp8285
framework = arduino
+board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.2m256.ld
upload_port = 192.168.4.1
upload_protocol = espota
lib_deps =
https://github.com/aZholtikov/ZHNetwork
https://github.com/aZholtikov/ZHConfig
+ https://github.com/aZholtikov/Async-Web-Server
https://github.com/bblanchon/ArduinoJson
- https://github.com/me-no-dev/ESPAsyncWebServer
+ https://github.com/milesburton/Arduino-Temperature-Control-Library
+ https://github.com/beegee-tokyo/DHTesp
+
+[env:PSF-B85]
+platform = espressif8266
+board = esp8285
+framework = arduino
+board_build.filesystem = littlefs
+board_build.ldscript = eagle.flash.1m64.ld
+lib_deps =
+ https://github.com/aZholtikov/ZHNetwork
+ https://github.com/aZholtikov/ZHConfig
+ https://github.com/aZholtikov/Async-Web-Server
+ https://github.com/bblanchon/ArduinoJson
+ https://github.com/milesburton/Arduino-Temperature-Control-Library
+ https://github.com/beegee-tokyo/DHTesp
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 7acd53d..25daf78 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,7 +1,10 @@
#include "ArduinoJson.h"
#include "ArduinoOTA.h"
-#include "ESPAsyncWebServer.h"
+#include "ESPAsyncWebServer.h" // https://github.com/aZholtikov/Async-Web-Server
+#include "LittleFS.h"
#include "Ticker.h"
+#include "DallasTemperature.h"
+#include "DHTesp.h"
#include "ZHNetwork.h"
#include "ZHConfig.h"
@@ -16,10 +19,10 @@ void setupWebServer(void);
void buttonInterrupt(void);
void switchingRelay(void);
-void sendAttributesMessage(void);
+void sendAttributesMessage(const uint8_t type = ENST_NONE);
void sendKeepAliveMessage(void);
-void sendConfigMessage(void);
-void sendStatusMessage(void);
+void sendConfigMessage(const uint8_t type = ENST_NONE);
+void sendStatusMessage(const uint8_t type = ENST_NONE);
typedef struct
{
@@ -29,7 +32,7 @@ typedef struct
std::vector espnowMessage;
-const String firmware{"1.14"};
+const String firmware{"1.2"};
String espnowNetName{"DEFAULT"};
@@ -45,6 +48,9 @@ uint8_t extButtonPinType{0};
uint8_t ledPin{0};
uint8_t ledPinType{0};
+uint8_t sensorPin{0};
+uint8_t sensorType{0};
+
bool wasMqttAvailable{false};
uint8_t gatewayMAC[6]{0};
@@ -55,6 +61,11 @@ const String payloadOff{"OFF"};
ZHNetwork myNet;
AsyncWebServer webServer(80);
+OneWire oneWire;
+DallasTemperature ds18b20(&oneWire);
+
+DHTesp dht;
+
Ticker buttonInterruptTimer;
Ticker gatewayAvailabilityCheckTimer;
@@ -78,10 +89,18 @@ void statusMessageTimerCallback(void);
void setup()
{
- SPIFFS.begin();
+ LittleFS.begin();
loadConfig();
+ if (sensorPin)
+ {
+ if (sensorType == ENST_DS18B20)
+ oneWire.begin(sensorPin);
+ if (sensorType == ENST_DHT11 || sensorType == ENST_DHT22)
+ dht.setup(sensorPin, DHTesp::AUTO_DETECT);
+ }
+
if (relayPin)
{
pinMode(relayPin, OUTPUT);
@@ -121,11 +140,19 @@ void setup()
void loop()
{
if (attributesMessageTimerSemaphore)
+ {
sendAttributesMessage();
+ if (sensorPin)
+ sendAttributesMessage(sensorType);
+ }
if (keepAliveMessageTimerSemaphore)
sendKeepAliveMessage();
if (statusMessageTimerSemaphore)
+ {
sendStatusMessage();
+ if (sensorPin)
+ sendStatusMessage(sensorType);
+ }
myNet.maintenance();
ArduinoOTA.handle();
}
@@ -148,7 +175,11 @@ void onBroadcastReceiving(const char *data, const uint8_t *sender)
{
wasMqttAvailable = temp;
if (temp)
+ {
sendConfigMessage();
+ if (sensorPin)
+ sendConfigMessage(sensorType);
+ }
}
gatewayAvailabilityCheckTimer.once(15, gatewayAvailabilityCheckTimerCallback);
}
@@ -188,6 +219,7 @@ void onConfirmReceiving(const uint8_t *target, const uint16_t id, const bool sta
{
espnow_message_t message = espnowMessage[i];
if (message.id == id)
+ {
if (status)
espnowMessage.erase(espnowMessage.begin() + i);
else
@@ -195,14 +227,15 @@ void onConfirmReceiving(const uint8_t *target, const uint16_t id, const bool sta
message.id = myNet.sendUnicastMessage(message.message, gatewayMAC, true);
espnowMessage.at(i) = message;
}
+ }
}
}
void loadConfig()
{
- if (!SPIFFS.exists("/config.json"))
+ if (!LittleFS.exists("/config.json"))
saveConfig();
- File file = SPIFFS.open("/config.json", "r");
+ File file = LittleFS.open("/config.json", "r");
String jsonFile = file.readString();
StaticJsonDocument<512> json;
deserializeJson(json, jsonFile);
@@ -217,6 +250,8 @@ void loadConfig()
extButtonPinType = json["extButtonPinType"];
ledPin = json["ledPin"];
ledPinType = json["ledPinType"];
+ sensorPin = json["sensorPin"];
+ sensorType = json["sensorType"];
file.close();
}
@@ -235,8 +270,10 @@ void saveConfig()
json["extButtonPinType"] = extButtonPinType;
json["ledPin"] = ledPin;
json["ledPinType"] = ledPinType;
+ json["sensorPin"] = sensorPin;
+ json["sensorType"] = sensorType;
json["system"] = "empty";
- File file = SPIFFS.open("/config.json", "w");
+ File file = LittleFS.open("/config.json", "w");
serializeJsonPretty(json, file);
file.close();
}
@@ -244,7 +281,7 @@ void saveConfig()
void setupWebServer()
{
webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
- { request->send(SPIFFS, "/index.htm"); });
+ { request->send(LittleFS, "/index.htm"); });
webServer.on("/setting", HTTP_GET, [](AsyncWebServerRequest *request)
{
@@ -256,6 +293,8 @@ void setupWebServer()
extButtonPinType = request->getParam("extButtonPinType")->value().toInt();
ledPin = request->getParam("ledPin")->value().toInt();
ledPinType = request->getParam("ledPinType")->value().toInt();
+ sensorPin = request->getParam("sensorPin")->value().toInt();
+ sensorType = request->getParam("sensorType")->value().toInt();
deviceName = request->getParam("deviceName")->value();
espnowNetName = request->getParam("espnowNetName")->value();
request->send(200);
@@ -268,8 +307,8 @@ void setupWebServer()
webServer.onNotFound([](AsyncWebServerRequest *request)
{
- if (SPIFFS.exists(request->url()))
- request->send(SPIFFS, request->url());
+ if (LittleFS.exists(request->url()))
+ request->send(LittleFS, request->url());
else
{
request->send(404, "text/plain", "File Not Found");
@@ -296,7 +335,7 @@ void switchingRelay()
ETS_GPIO_INTR_ENABLE();
}
-void sendAttributesMessage()
+void sendAttributesMessage(const uint8_t type)
{
if (!isGatewayAvailable)
return;
@@ -308,7 +347,13 @@ void sendAttributesMessage()
esp_now_payload_data_t outgoingData{ENDT_SWITCH, ENPT_ATTRIBUTES};
espnow_message_t message;
StaticJsonDocument json;
- json["Type"] = "ESP-NOW switch";
+ if (type == ENST_NONE)
+ json["Type"] = "ESP-NOW switch";
+ else
+ {
+ outgoingData.deviceType = ENDT_SENSOR;
+ json["Type"] = getValueName(esp_now_sensor_type_t(type));
+ }
json["MCU"] = "ESP8266";
json["MAC"] = myNet.getNodeMac();
json["Firmware"] = firmware;
@@ -334,28 +379,56 @@ void sendKeepAliveMessage()
espnowMessage.push_back(message);
}
-void sendConfigMessage()
+void sendConfigMessage(const uint8_t type)
{
if (!isGatewayAvailable)
return;
esp_now_payload_data_t outgoingData{ENDT_SWITCH, ENPT_CONFIG};
espnow_message_t message;
StaticJsonDocument json;
- json["name"] = deviceName;
- json["unit"] = 1;
- json["type"] = HACT_SWITCH;
- json["class"] = HASWDC_SWITCH;
- json["template"] = "state";
- json["payload_on"] = payloadOn;
- json["payload_off"] = payloadOff;
+ if (type == ENST_NONE)
+ {
+ json["name"] = deviceName;
+ json["unit"] = 1;
+ json["type"] = HACT_SWITCH;
+ json["class"] = HASWDC_SWITCH;
+ json["template"] = "state";
+ json["payload_on"] = payloadOn;
+ json["payload_off"] = payloadOff;
+ }
+ if (type == ENST_DS18B20 || type == ENST_DHT11 || type == ENST_DHT22)
+ {
+ outgoingData.deviceType = ENDT_SENSOR;
+ json["name"] = deviceName + " temperature";
+ json["unit"] = 2;
+ json["type"] = HACT_SENSOR;
+ json["class"] = HASDC_TEMPERATURE;
+ json["template"] = "temperature";
+ }
serializeJsonPretty(json, outgoingData.message);
memcpy(&message.message, &outgoingData, sizeof(esp_now_payload_data_t));
message.id = myNet.sendUnicastMessage(message.message, gatewayMAC, true);
espnowMessage.push_back(message);
+
+ if (type == ENST_DHT11 || type == ENST_DHT22)
+ {
+ outgoingData.deviceType = ENDT_SENSOR;
+ json["name"] = deviceName + " humidity";
+ json["unit"] = 3;
+ json["type"] = HACT_SENSOR;
+ json["class"] = HASDC_HUMIDITY;
+ json["template"] = "humidity";
+
+ serializeJsonPretty(json, outgoingData.message);
+ memcpy(&message.message, &outgoingData, sizeof(esp_now_payload_data_t));
+ message.id = myNet.sendUnicastMessage(message.message, gatewayMAC, true);
+
+ espnowMessage.push_back(message);
+ }
}
-void sendStatusMessage()
+void sendStatusMessage(const uint8_t type)
{
if (!isGatewayAvailable)
return;
@@ -363,7 +436,20 @@ void sendStatusMessage()
esp_now_payload_data_t outgoingData{ENDT_SWITCH, ENPT_STATE};
espnow_message_t message;
StaticJsonDocument json;
- json["state"] = relayStatus ? payloadOn : payloadOff;
+ if (type == ENST_NONE)
+ json["state"] = relayStatus ? payloadOn : payloadOff;
+ if (type == ENST_DS18B20)
+ {
+ outgoingData.deviceType = ENDT_SENSOR;
+ ds18b20.requestTemperatures();
+ json["temperature"] = int8_t(ds18b20.getTempCByIndex(0));
+ }
+ if (type == ENST_DHT11 || type == ENST_DHT22)
+ {
+ outgoingData.deviceType = ENDT_SENSOR;
+ json["temperature"] = int8_t(dht.getTemperature());
+ json["humidity"] = int8_t(dht.getHumidity());
+ }
serializeJsonPretty(json, outgoingData.message);
memcpy(&message.message, &outgoingData, sizeof(esp_now_payload_data_t));
message.id = myNet.sendUnicastMessage(message.message, gatewayMAC, true);