Compare commits
	
		
			6 Commits
		
	
	
		
			v1.3
			...
			cf32071ee0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cf32071ee0 | |||
| e4572cc31a | |||
| 57d0bc6481 | |||
| 1e745724e4 | |||
| 25ce7e419a | |||
| 15472ab36b | 
							
								
								
									
										15
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								README.md
									
									
									
									
									
								
							@@ -9,9 +9,10 @@ Gateway for data exchange between ESP-NOW devices and MQTT broker via WiFi/LAN.
 | 
			
		||||
3. Periodically transmission of system information to the MQTT broker (every 60 seconds), availability status to the ESP-NOW network and to the MQTT broker (every 10 seconds) and current date and time to the ESP-NOW network (every 10 seconds).
 | 
			
		||||
4. Automatically adds gateway configuration to Home Assistan via MQTT discovery as a binary_sensor.
 | 
			
		||||
5. Automatically adds supported ESP-NOW devices configurations to Home Assistan via MQTT discovery.
 | 
			
		||||
6. Possibility firmware update over OTA (at ESP_NOW_LAN mode via access point only).
 | 
			
		||||
7. Web interface for settings (at ESP_NOW_LAN mode via access point only).
 | 
			
		||||
8. 3 operating modes:
 | 
			
		||||
6. Automatically adds supported nRF24 devices configurations to Home Assistan via MQTT discovery.
 | 
			
		||||
7. Possibility firmware update over OTA (at ESP_NOW_LAN mode via access point only).
 | 
			
		||||
8. Web interface for settings (at ESP_NOW_LAN mode via access point only).
 | 
			
		||||
9. 3 operating modes:
 | 
			
		||||
 | 
			
		||||
```text
 | 
			
		||||
ESP_NOW       ESP-NOW node only. Default mode after flashing.
 | 
			
		||||
@@ -47,7 +48,7 @@ ESP32   (GPIO05 - CS, GPIO18 - SCK, GPIO19 - MISO, GPIO23 - MOSI).
 | 
			
		||||
 | 
			
		||||
## Supported devices
 | 
			
		||||
 | 
			
		||||
1. [RF Gateway](https://github.com/aZholtikov/RF-Gateway) (coming soon)
 | 
			
		||||
1. [RF Gateway](https://github.com/aZholtikov/RF-Gateway)
 | 
			
		||||
2. [ESP-NOW Switch](https://github.com/aZholtikov/ESP-NOW-Switch)
 | 
			
		||||
3. [ESP-NOW Light/Led Strip](https://github.com/aZholtikov/ESP-NOW-Light-Led-Strip)
 | 
			
		||||
4. [ESP-NOW Window/Door Sensor](https://github.com/aZholtikov/ESP-NOW-Window-Door-Sensor)
 | 
			
		||||
@@ -57,8 +58,8 @@ ESP32   (GPIO05 - CS, GPIO18 - SCK, GPIO19 - MISO, GPIO23 - MOSI).
 | 
			
		||||
 | 
			
		||||
- [X] Automatically add ESP-NOW devices configurations to Home Assistan via MQTT discovery.
 | 
			
		||||
- [X] LAN connection support.
 | 
			
		||||
- [ ] nRF24 device support (in current time uses "RF Gateway").
 | 
			
		||||
- [ ] BLE device support (for ESP32).
 | 
			
		||||
- [ ] LoRa device support.
 | 
			
		||||
- [X] nRF24 device support (via [RF Gateway](https://github.com/aZholtikov/RF-Gateway)).
 | 
			
		||||
- [ ] BLE device support (via BLE Gateway).
 | 
			
		||||
- [ ] LoRa device support (via LoRa Gateway).
 | 
			
		||||
 | 
			
		||||
Any feedback via [e-mail](mailto:github@zh.com.ru) would be appreciated. Or... [Buy me a coffee](https://paypal.me/aZholtikov).
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										93
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								src/main.cpp
									
									
									
									
									
								
							@@ -42,7 +42,7 @@ void checkMqttAvailability(void);
 | 
			
		||||
 | 
			
		||||
void mqttPublish(const char *topic, const char *payload, bool retained);
 | 
			
		||||
 | 
			
		||||
const String firmware{"1.3"};
 | 
			
		||||
const String firmware{"1.42"};
 | 
			
		||||
 | 
			
		||||
String espnowNetName{"DEFAULT"};
 | 
			
		||||
 | 
			
		||||
@@ -193,12 +193,12 @@ void setup()
 | 
			
		||||
 | 
			
		||||
void loop()
 | 
			
		||||
{
 | 
			
		||||
    if (mqttAvailabilityCheckTimerSemaphore)
 | 
			
		||||
        checkMqttAvailability();
 | 
			
		||||
    if (keepAliveMessageTimerSemaphore)
 | 
			
		||||
        sendKeepAliveMessage();
 | 
			
		||||
    if (attributesMessageTimerSemaphore)
 | 
			
		||||
        sendAttributesMessage();
 | 
			
		||||
    if (mqttAvailabilityCheckTimerSemaphore)
 | 
			
		||||
        checkMqttAvailability();
 | 
			
		||||
    if (workMode == ESP_NOW_WIFI)
 | 
			
		||||
        mqttWifiClient.loop();
 | 
			
		||||
    if (workMode == ESP_NOW_LAN)
 | 
			
		||||
@@ -228,7 +228,6 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
 | 
			
		||||
            StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
 | 
			
		||||
            deserializeJson(json, configData.message);
 | 
			
		||||
            uint8_t unit = json["unit"].as<uint8_t>();
 | 
			
		||||
            ha_component_type_t type = json["type"].as<ha_component_type_t>();
 | 
			
		||||
            StaticJsonDocument<2048> jsonConfig;
 | 
			
		||||
            jsonConfig["platform"] = "mqtt";
 | 
			
		||||
            jsonConfig["name"] = json["name"];
 | 
			
		||||
@@ -245,7 +244,7 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
 | 
			
		||||
            jsonConfig["retain"] = "true";
 | 
			
		||||
            char buffer[2048]{0};
 | 
			
		||||
            serializeJsonPretty(jsonConfig, buffer);
 | 
			
		||||
            mqttPublish((topicPrefix + "/" + getValueName(type) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
 | 
			
		||||
            mqttPublish((topicPrefix + "/" + getValueName(json["type"].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
 | 
			
		||||
        }
 | 
			
		||||
        if (incomingData.deviceType == ENDT_LED)
 | 
			
		||||
        {
 | 
			
		||||
@@ -254,7 +253,6 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
 | 
			
		||||
            StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
 | 
			
		||||
            deserializeJson(json, configData.message);
 | 
			
		||||
            uint8_t unit = json["unit"].as<uint8_t>();
 | 
			
		||||
            ha_component_type_t type = json["type"].as<ha_component_type_t>();
 | 
			
		||||
            esp_now_led_type_t ledClass = json["class"];
 | 
			
		||||
            StaticJsonDocument<2048> jsonConfig;
 | 
			
		||||
            jsonConfig["platform"] = "mqtt";
 | 
			
		||||
@@ -286,7 +284,7 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
 | 
			
		||||
            jsonConfig["retain"] = "true";
 | 
			
		||||
            char buffer[2048]{0};
 | 
			
		||||
            serializeJsonPretty(jsonConfig, buffer);
 | 
			
		||||
            mqttPublish((topicPrefix + "/" + getValueName(type) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
 | 
			
		||||
            mqttPublish((topicPrefix + "/" + getValueName(json["type"].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
 | 
			
		||||
        }
 | 
			
		||||
        if (incomingData.deviceType == ENDT_SENSOR)
 | 
			
		||||
        {
 | 
			
		||||
@@ -309,14 +307,78 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
 | 
			
		||||
                jsonConfig["device_class"] = getValueName(json["class"].as<ha_sensor_device_class_t>());
 | 
			
		||||
            if (type == HACT_BINARY_SENSOR)
 | 
			
		||||
            {
 | 
			
		||||
                jsonConfig["device_class"] = getValueName(json["class"].as<ha_binary_sensor_device_class_t>());
 | 
			
		||||
                jsonConfig["payload_on"] = json["payload_on"];
 | 
			
		||||
                ha_binary_sensor_device_class_t deviceClass = json["class"].as<ha_binary_sensor_device_class_t>();
 | 
			
		||||
                if (deviceClass == HABSDC_BATTERY || deviceClass == HABSDC_WINDOW || deviceClass == HABSDC_DOOR)
 | 
			
		||||
                    jsonConfig["payload_off"] = json["payload_off"];
 | 
			
		||||
                if (deviceClass == HABSDC_CONNECTIVITY)
 | 
			
		||||
                    jsonConfig["expire_after"] = json["expire_after"];
 | 
			
		||||
                jsonConfig["device_class"] = getValueName(deviceClass);
 | 
			
		||||
                jsonConfig["payload_on"] = json["payload_on"];
 | 
			
		||||
            }
 | 
			
		||||
            char buffer[2048]{0};
 | 
			
		||||
            serializeJsonPretty(jsonConfig, buffer);
 | 
			
		||||
            mqttPublish((topicPrefix + "/" + getValueName(type) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
 | 
			
		||||
        }
 | 
			
		||||
        if (incomingData.deviceType == ENDT_RF_SENSOR)
 | 
			
		||||
        {
 | 
			
		||||
            esp_now_payload_data_t configData;
 | 
			
		||||
            memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
 | 
			
		||||
            StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
 | 
			
		||||
            deserializeJson(json, configData.message);
 | 
			
		||||
            uint8_t unit = json["u"].as<uint8_t>();
 | 
			
		||||
            ha_component_type_t type = json["t"].as<ha_component_type_t>();
 | 
			
		||||
            rf_sensor_type_t rf = json["r"].as<rf_sensor_type_t>();
 | 
			
		||||
            uint16_t id = json["i"].as<uint16_t>();
 | 
			
		||||
            String tmp = json["v"].as<String>();
 | 
			
		||||
            StaticJsonDocument<2048> jsonConfig;
 | 
			
		||||
            jsonConfig["platform"] = "mqtt";
 | 
			
		||||
            jsonConfig["name"] = getValueName(rf) + " " + id + " " + tmp;
 | 
			
		||||
            jsonConfig["unique_id"] = String(id) + "-" + unit;
 | 
			
		||||
            jsonConfig["state_topic"] = topicPrefix + "/rf_sensor/" + getValueName(rf) + "/" + id + "/state";
 | 
			
		||||
            jsonConfig["value_template"] = "{{ value_json." + tmp + " }}";
 | 
			
		||||
            if (type == HACT_SENSOR)
 | 
			
		||||
            {
 | 
			
		||||
                jsonConfig["device_class"] = getValueName(json["h"].as<ha_sensor_device_class_t>());
 | 
			
		||||
                jsonConfig["unit_of_measurement"] = json["m"];
 | 
			
		||||
                jsonConfig["expire_after"] = json["e"];
 | 
			
		||||
            }
 | 
			
		||||
            if (type == HACT_BINARY_SENSOR)
 | 
			
		||||
            {
 | 
			
		||||
                ha_binary_sensor_device_class_t deviceClass = json["h"].as<ha_binary_sensor_device_class_t>();
 | 
			
		||||
                if (deviceClass == HABSDC_MOISTURE)
 | 
			
		||||
                    jsonConfig["expire_after"] = json["e"];
 | 
			
		||||
                jsonConfig["device_class"] = getValueName(deviceClass);
 | 
			
		||||
                jsonConfig["payload_on"] = json["o"];
 | 
			
		||||
                jsonConfig["payload_off"] = json["f"];
 | 
			
		||||
            }
 | 
			
		||||
            jsonConfig["force_update"] = "true";
 | 
			
		||||
            jsonConfig["retain"] = "true";
 | 
			
		||||
            char buffer[2048]{0};
 | 
			
		||||
            serializeJsonPretty(jsonConfig, buffer);
 | 
			
		||||
            mqttPublish((topicPrefix + "/" + getValueName(type) + "/" + id + "-" + unit + "/config").c_str(), buffer, true);
 | 
			
		||||
        }
 | 
			
		||||
        if (incomingData.deviceType == ENDT_RF_GATEWAY)
 | 
			
		||||
        {
 | 
			
		||||
            esp_now_payload_data_t configData;
 | 
			
		||||
            memcpy(&configData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
 | 
			
		||||
            StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
 | 
			
		||||
            deserializeJson(json, configData.message);
 | 
			
		||||
            uint8_t unit = json["unit"].as<uint8_t>();
 | 
			
		||||
            StaticJsonDocument<2048> jsonConfig;
 | 
			
		||||
            jsonConfig["platform"] = "mqtt";
 | 
			
		||||
            jsonConfig["name"] = json["name"];
 | 
			
		||||
            jsonConfig["unique_id"] = myNet.macToString(sender) + "-" + unit;
 | 
			
		||||
            jsonConfig["device_class"] = getValueName(json["class"].as<ha_binary_sensor_device_class_t>());
 | 
			
		||||
            jsonConfig["state_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/status";
 | 
			
		||||
            jsonConfig["json_attributes_topic"] = topicPrefix + "/" + getValueName(incomingData.deviceType) + "/" + myNet.macToString(sender) + "/attributes";
 | 
			
		||||
            jsonConfig["payload_on"] = json["payload_on"];
 | 
			
		||||
            jsonConfig["expire_after"] = json["expire_after"];
 | 
			
		||||
            jsonConfig["force_update"] = "true";
 | 
			
		||||
            jsonConfig["retain"] = "true";
 | 
			
		||||
            char buffer[2048]{0};
 | 
			
		||||
            serializeJsonPretty(jsonConfig, buffer);
 | 
			
		||||
            mqttPublish((topicPrefix + "/" + getValueName(json["type"].as<ha_component_type_t>()) + "/" + myNet.macToString(sender) + "-" + unit + "/config").c_str(), buffer, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (incomingData.payloadsType == ENPT_FORWARD)
 | 
			
		||||
    {
 | 
			
		||||
@@ -324,7 +386,8 @@ void onEspnowMessage(const char *data, const uint8_t *sender)
 | 
			
		||||
        memcpy(&forwardData.message, &incomingData.message, sizeof(esp_now_payload_data_t::message));
 | 
			
		||||
        StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
 | 
			
		||||
        deserializeJson(json, forwardData.message);
 | 
			
		||||
        mqttPublish((topicPrefix + "/rf_sensor/" + getValueName(json["type"].as<rf_sensor_type_t>()) + "/" + json["id"].as<uint16_t>()).c_str(), incomingData.message, false);
 | 
			
		||||
        if (incomingData.deviceType == ENDT_RF_GATEWAY)
 | 
			
		||||
            mqttPublish((topicPrefix + "/rf_sensor/" + getValueName(json["type"].as<rf_sensor_type_t>()) + "/" + json["id"].as<uint16_t>() + "/state").c_str(), incomingData.message, false);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -342,8 +405,6 @@ void onMqttMessage(char *topic, byte *payload, unsigned int length)
 | 
			
		||||
    StaticJsonDocument<sizeof(esp_now_payload_data_t::message)> json;
 | 
			
		||||
    if (message == "update" || message == "restart")
 | 
			
		||||
    {
 | 
			
		||||
        mqttPublish(topic, "", true);
 | 
			
		||||
        mqttPublish((String(topic) + "/status").c_str(), "offline", true);
 | 
			
		||||
        if (mac == myNet.getNodeMac() && message == "restart")
 | 
			
		||||
            ESP.restart();
 | 
			
		||||
        flag = true;
 | 
			
		||||
@@ -374,9 +435,7 @@ void onMqttMessage(char *topic, byte *payload, unsigned int length)
 | 
			
		||||
            outgoingData.payloadsType = ENPT_RESTART;
 | 
			
		||||
        else
 | 
			
		||||
            outgoingData.payloadsType = message == "update" ? ENPT_UPDATE : ENPT_SET;
 | 
			
		||||
        char buffer[sizeof(esp_now_payload_data_t::message)]{0};
 | 
			
		||||
        serializeJsonPretty(json, buffer);
 | 
			
		||||
        memcpy(&outgoingData.message, &buffer, sizeof(esp_now_payload_data_t::message));
 | 
			
		||||
        serializeJsonPretty(json, outgoingData.message);
 | 
			
		||||
        char temp[sizeof(esp_now_payload_data_t)]{0};
 | 
			
		||||
        memcpy(&temp, &outgoingData, sizeof(esp_now_payload_data_t));
 | 
			
		||||
        uint8_t target[6];
 | 
			
		||||
@@ -620,6 +679,8 @@ void checkMqttAvailability()
 | 
			
		||||
                    mqttWifiClient.subscribe((topicPrefix + "/espnow_led/#").c_str());
 | 
			
		||||
 | 
			
		||||
                    sendConfigMessage();
 | 
			
		||||
                    sendAttributesMessage();
 | 
			
		||||
                    sendKeepAliveMessage();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -637,6 +698,8 @@ void checkMqttAvailability()
 | 
			
		||||
                    mqttEthClient.subscribe((topicPrefix + "/espnow_led/#").c_str());
 | 
			
		||||
 | 
			
		||||
                    sendConfigMessage();
 | 
			
		||||
                    sendAttributesMessage();
 | 
			
		||||
                    sendKeepAliveMessage();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user