9 Commits

Author SHA1 Message Date
71ec165aca Version 1.32
Minor changes.
2023-02-19 12:23:25 +03:00
d1ddd9ecbb Minor changes 2023-02-19 11:03:13 +03:00
5d023b13c1 Minor changes 2023-02-19 09:59:58 +03:00
551866b040 Version 1.31
Fixed one minor bug.
2023-02-18 10:07:15 +03:00
b940f325f2 Minor changes 2023-02-17 17:01:52 +03:00
0b603489fd Version 1.3
Added relay work modes.
2023-02-17 09:28:23 +03:00
dc17e39ff6 Version 1.21
Minor changes.
2023-02-12 18:33:42 +03:00
e1d74e98eb Minor changes 2023-02-11 08:41:56 +03:00
4ece7281d3 Minor changes 2023-02-09 21:30:13 +03:00
6 changed files with 73 additions and 23 deletions

View File

@ -11,6 +11,7 @@ ESP-NOW based switch for ESP8266. Alternate firmware for Tuya/SmartLife/eWeLink
5. Possibility firmware update over OTA (if is allows the size of the flash memory). 5. Possibility firmware update over OTA (if is allows the size of the flash memory).
6. Web interface for settings. 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. 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.
8. Normal or reverse relay mode (normal by default).
## Notes ## Notes
@ -29,3 +30,5 @@ See [here](https://github.com/aZholtikov/ESP-NOW-Switch/tree/main/hardware).
3. If encryption is used, the key 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. 4. Upload the "data" folder (with web interface) into the filesystem before flashing.
5. For using this firmware on Tuya/SmartLife/eWeLink 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).
Any feedback via [e-mail](mailto:github@zh.com.ru) would be appreciated. Or... [Buy me a coffee](https://paypal.me/aZholtikov).

View File

@ -29,6 +29,7 @@ function loadBlock() {
} }
document.getElementsByTagName('body')[0].innerHTML = newString; document.getElementsByTagName('body')[0].innerHTML = newString;
setFirmvareValue('version', 'firmware'); setFirmvareValue('version', 'firmware');
setGpioValue('workModeSelect', 'workMode');
setGpioValue('relayPinSelect', 'relayPin'); setGpioValue('relayPinSelect', 'relayPin');
setGpioValue('relayPinTypeSelect', 'relayPinType'); setGpioValue('relayPinTypeSelect', 'relayPinType');
setGpioValue('ledPinSelect', 'ledPin'); setGpioValue('ledPinSelect', 'ledPin');
@ -71,7 +72,8 @@ function saveSetting(submit) {
+ "&extButtonPin=" + getSelectValue('extButtonPinSelect') + "&extButtonPin=" + getSelectValue('extButtonPinSelect')
+ "&extButtonPinType=" + getSelectValue('extButtonPinTypeSelect') + "&extButtonPinType=" + getSelectValue('extButtonPinTypeSelect')
+ "&sensorPin=" + getSelectValue('sensorPinSelect') + "&sensorPin=" + getSelectValue('sensorPinSelect')
+ "&sensorType=" + getSelectValue('sensorTypeSelect'); + "&sensorType=" + getSelectValue('sensorTypeSelect')
+ "&workMode=" + getSelectValue('workModeSelect');
sendRequest(submit, server); sendRequest(submit, server);
alert("Please restart device for changes apply."); alert("Please restart device for changes apply.");
} }

View File

@ -29,6 +29,15 @@
title="ESP-NOW network name (1 to 20 characters)" /> title="ESP-NOW network name (1 to 20 characters)" />
</div> </div>
<div class="wrapper">
<p class="text-select">Work mode:</p>
<input id="workMode" value="{{workMode}}" hidden />
<p><select id="workModeSelect">
<option value="0">NORMAL</option>
<option value="1">REVERSE</option>
</select></p>
</div>
<div class="wrapper"> <div class="wrapper">
<p class="text-select">Relay GPIO:</p> <p class="text-select">Relay GPIO:</p>
<input id="relayPin" value="{{relayPin}}" hidden /> <input id="relayPin" value="{{relayPin}}" hidden />

View File

@ -21,7 +21,6 @@
```text ```text
Relay GPIO GPIO12 HIGH Relay GPIO GPIO12 HIGH
Led GPIO GPIO13 LOW
Button GPIO GPIO04 RISING Button GPIO GPIO04 RISING
Ext sensor GPIO GPIO14 DS18B20 Ext sensor GPIO GPIO14 DS18B20
``` ```

View File

@ -3,7 +3,7 @@ platform = espressif8266
board = esp12e board = esp12e
framework = arduino framework = arduino
board_build.filesystem = littlefs board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.4m2m.ld board_build.ldscript = eagle.flash.4m1m.ld
lib_deps = lib_deps =
https://github.com/aZholtikov/ZHNetwork https://github.com/aZholtikov/ZHNetwork
https://github.com/aZholtikov/ZHConfig https://github.com/aZholtikov/ZHConfig
@ -17,7 +17,7 @@ platform = espressif8266
board = esp12e board = esp12e
framework = arduino framework = arduino
board_build.filesystem = littlefs board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.4m2m.ld board_build.ldscript = eagle.flash.4m1m.ld
upload_port = 192.168.4.1 upload_port = 192.168.4.1
upload_protocol = espota upload_protocol = espota
lib_deps = lib_deps =
@ -33,7 +33,7 @@ platform = espressif8266
board = esp8285 board = esp8285
framework = arduino framework = arduino
board_build.filesystem = littlefs board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.2m256.ld board_build.ldscript = eagle.flash.2m64.ld
lib_deps = lib_deps =
https://github.com/aZholtikov/ZHNetwork https://github.com/aZholtikov/ZHNetwork
https://github.com/aZholtikov/ZHConfig https://github.com/aZholtikov/ZHConfig
@ -47,7 +47,7 @@ platform = espressif8266
board = esp8285 board = esp8285
framework = arduino framework = arduino
board_build.filesystem = littlefs board_build.filesystem = littlefs
board_build.ldscript = eagle.flash.2m256.ld board_build.ldscript = eagle.flash.2m64.ld
upload_port = 192.168.4.1 upload_port = 192.168.4.1
upload_protocol = espota upload_protocol = espota
lib_deps = lib_deps =

View File

@ -32,10 +32,12 @@ typedef struct
std::vector<espnow_message_t> espnowMessage; std::vector<espnow_message_t> espnowMessage;
const String firmware{"1.2"}; const String firmware{"1.32"};
String espnowNetName{"DEFAULT"}; String espnowNetName{"DEFAULT"};
uint8_t workMode{0};
String deviceName = "ESP-NOW switch " + String(ESP.getChipId(), HEX); String deviceName = "ESP-NOW switch " + String(ESP.getChipId(), HEX);
bool relayStatus{false}; bool relayStatus{false};
@ -100,10 +102,12 @@ void setup()
if (sensorType == ENST_DHT11 || sensorType == ENST_DHT22) if (sensorType == ENST_DHT11 || sensorType == ENST_DHT22)
dht.setup(sensorPin, DHTesp::AUTO_DETECT); dht.setup(sensorPin, DHTesp::AUTO_DETECT);
} }
if (relayPin) if (relayPin)
{ {
pinMode(relayPin, OUTPUT); pinMode(relayPin, OUTPUT);
if (workMode)
digitalWrite(relayPin, relayPinType ? !relayStatus : relayStatus);
else
digitalWrite(relayPin, relayPinType ? relayStatus : !relayStatus); digitalWrite(relayPin, relayPinType ? relayStatus : !relayStatus);
} }
if (ledPin) if (ledPin)
@ -179,6 +183,12 @@ void onBroadcastReceiving(const char *data, const uint8_t *sender)
sendConfigMessage(); sendConfigMessage();
if (sensorPin) if (sensorPin)
sendConfigMessage(sensorType); sendConfigMessage(sensorType);
sendAttributesMessage();
if (sensorPin)
sendAttributesMessage(sensorType);
sendStatusMessage();
if (sensorPin)
sendStatusMessage(sensorType);
} }
} }
gatewayAvailabilityCheckTimer.once(15, gatewayAvailabilityCheckTimerCallback); gatewayAvailabilityCheckTimer.once(15, gatewayAvailabilityCheckTimerCallback);
@ -197,9 +207,19 @@ void onUnicastReceiving(const char *data, const uint8_t *sender)
deserializeJson(json, incomingData.message); deserializeJson(json, incomingData.message);
relayStatus = json["set"] == payloadOn ? true : false; relayStatus = json["set"] == payloadOn ? true : false;
if (relayPin) if (relayPin)
{
if (workMode)
digitalWrite(relayPin, relayPinType ? !relayStatus : relayStatus);
else
digitalWrite(relayPin, relayPinType ? relayStatus : !relayStatus); digitalWrite(relayPin, relayPinType ? relayStatus : !relayStatus);
}
if (ledPin) if (ledPin)
{
if (workMode)
digitalWrite(ledPin, ledPinType ? !relayStatus : relayStatus);
else
digitalWrite(ledPin, ledPinType ? relayStatus : !relayStatus); digitalWrite(ledPin, ledPinType ? relayStatus : !relayStatus);
}
saveConfig(); saveConfig();
sendStatusMessage(); sendStatusMessage();
} }
@ -252,6 +272,7 @@ void loadConfig()
ledPinType = json["ledPinType"]; ledPinType = json["ledPinType"];
sensorPin = json["sensorPin"]; sensorPin = json["sensorPin"];
sensorType = json["sensorType"]; sensorType = json["sensorType"];
workMode = json["workMode"];
file.close(); file.close();
} }
@ -272,6 +293,7 @@ void saveConfig()
json["ledPinType"] = ledPinType; json["ledPinType"] = ledPinType;
json["sensorPin"] = sensorPin; json["sensorPin"] = sensorPin;
json["sensorType"] = sensorType; json["sensorType"] = sensorType;
json["workMode"] = workMode;
json["system"] = "empty"; json["system"] = "empty";
File file = LittleFS.open("/config.json", "w"); File file = LittleFS.open("/config.json", "w");
serializeJsonPretty(json, file); serializeJsonPretty(json, file);
@ -295,6 +317,7 @@ void setupWebServer()
ledPinType = request->getParam("ledPinType")->value().toInt(); ledPinType = request->getParam("ledPinType")->value().toInt();
sensorPin = request->getParam("sensorPin")->value().toInt(); sensorPin = request->getParam("sensorPin")->value().toInt();
sensorType = request->getParam("sensorType")->value().toInt(); sensorType = request->getParam("sensorType")->value().toInt();
workMode = request->getParam("workMode")->value().toInt();
deviceName = request->getParam("deviceName")->value(); deviceName = request->getParam("deviceName")->value();
espnowNetName = request->getParam("espnowNetName")->value(); espnowNetName = request->getParam("espnowNetName")->value();
request->send(200); request->send(200);
@ -320,16 +343,26 @@ void setupWebServer()
void IRAM_ATTR buttonInterrupt() void IRAM_ATTR buttonInterrupt()
{ {
ETS_GPIO_INTR_DISABLE(); ETS_GPIO_INTR_DISABLE();
buttonInterruptTimer.once_ms(100, switchingRelay); // For prevent contact chatter. buttonInterruptTimer.once_ms(500, switchingRelay); // For prevent contact chatter.
} }
void switchingRelay() void switchingRelay()
{ {
relayStatus = !relayStatus; relayStatus = !relayStatus;
if (relayPin) if (relayPin)
{
if (workMode)
digitalWrite(relayPin, relayPinType ? !relayStatus : relayStatus);
else
digitalWrite(relayPin, relayPinType ? relayStatus : !relayStatus); digitalWrite(relayPin, relayPinType ? relayStatus : !relayStatus);
}
if (ledPin) if (ledPin)
{
if (workMode)
digitalWrite(ledPin, ledPinType ? !relayStatus : relayStatus);
else
digitalWrite(ledPin, ledPinType ? relayStatus : !relayStatus); digitalWrite(ledPin, ledPinType ? relayStatus : !relayStatus);
}
saveConfig(); saveConfig();
sendStatusMessage(); sendStatusMessage();
ETS_GPIO_INTR_ENABLE(); ETS_GPIO_INTR_ENABLE();
@ -390,9 +423,9 @@ void sendConfigMessage(const uint8_t type)
{ {
json["name"] = deviceName; json["name"] = deviceName;
json["unit"] = 1; json["unit"] = 1;
json["type"] = HACT_SWITCH; json["type"] = HACT_SWITCH; // ha_component_type_t
json["class"] = HASWDC_SWITCH; json["class"] = HASWDC_SWITCH; // ha_switch_device_class_t
json["template"] = "state"; json["template"] = "state"; // value_template
json["payload_on"] = payloadOn; json["payload_on"] = payloadOn;
json["payload_off"] = payloadOff; json["payload_off"] = payloadOff;
} }
@ -401,9 +434,11 @@ void sendConfigMessage(const uint8_t type)
outgoingData.deviceType = ENDT_SENSOR; outgoingData.deviceType = ENDT_SENSOR;
json["name"] = deviceName + " temperature"; json["name"] = deviceName + " temperature";
json["unit"] = 2; json["unit"] = 2;
json["type"] = HACT_SENSOR; json["type"] = HACT_SENSOR; // ha_component_type_t
json["class"] = HASDC_TEMPERATURE; json["class"] = HASDC_TEMPERATURE; // ha_sensor_device_class_t
json["template"] = "temperature"; json["template"] = "temperature"; // value_template
json["meas"] = "°C"; // unit_of_measurement
json["time"] = 180; // expire_after
} }
serializeJsonPretty(json, outgoingData.message); serializeJsonPretty(json, outgoingData.message);
memcpy(&message.message, &outgoingData, sizeof(esp_now_payload_data_t)); memcpy(&message.message, &outgoingData, sizeof(esp_now_payload_data_t));
@ -416,9 +451,11 @@ void sendConfigMessage(const uint8_t type)
outgoingData.deviceType = ENDT_SENSOR; outgoingData.deviceType = ENDT_SENSOR;
json["name"] = deviceName + " humidity"; json["name"] = deviceName + " humidity";
json["unit"] = 3; json["unit"] = 3;
json["type"] = HACT_SENSOR; json["type"] = HACT_SENSOR; // ha_component_type_t
json["class"] = HASDC_HUMIDITY; json["class"] = HASDC_HUMIDITY; // ha_sensor_device_class_t
json["template"] = "humidity"; json["template"] = "humidity"; // value_template
json["meas"] = "%"; // unit_of_measurement
json["time"] = 180; // expire_after
serializeJsonPretty(json, outgoingData.message); serializeJsonPretty(json, outgoingData.message);
memcpy(&message.message, &outgoingData, sizeof(esp_now_payload_data_t)); memcpy(&message.message, &outgoingData, sizeof(esp_now_payload_data_t));