Add esp-espnow_test_receiver.yaml
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
#:########################################################################################:#
|
||||
# ESP-NOW Test Receiver
|
||||
#:########################################################################################:#
|
||||
#
|
||||
# DEVICE:
|
||||
# ESP32 DevKit V1 / ESP-WROOM-32
|
||||
#
|
||||
# VERSION:
|
||||
# 1.0 - 2026-07-11
|
||||
# - Initial ESP-NOW receiver test build.
|
||||
# - Receives broadcast packets from ESP32-S3-Zero transmitter.
|
||||
# - Publishes last sender MAC, payload, RSSI, received count and duplicate count.
|
||||
# - Creates a short Home Assistant event pulse for each unique press_id.
|
||||
#
|
||||
# NOTES:
|
||||
# - This device is the powered receiver.
|
||||
# - The transmitter should send the same packet 2-3 times for reliability.
|
||||
# - This receiver de-duplicates repeated packets using the full payload string.
|
||||
# - Expected test payload format from transmitter:
|
||||
# REMOTE_A:BUTTON_1:123
|
||||
#
|
||||
#:########################################################################################:#
|
||||
|
||||
substitutions:
|
||||
device_name: espnow_test_receiver
|
||||
friendly_name: "ESPNow Test Receiver"
|
||||
area: "Test Bench"
|
||||
|
||||
packages:
|
||||
network: !include common/network_common_dhcp.yaml
|
||||
|
||||
esphome:
|
||||
name: ${device_name}
|
||||
friendly_name: ${friendly_name}
|
||||
area: ${area}
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
framework:
|
||||
type: arduino
|
||||
|
||||
#:########################################################################################:#
|
||||
# ESP-NOW Receiver
|
||||
#:########################################################################################:#
|
||||
#
|
||||
# Do not set channel here while using Wi-Fi.
|
||||
# The receiver's ESP-NOW channel follows the connected Wi-Fi channel.
|
||||
#
|
||||
|
||||
espnow:
|
||||
auto_add_peer: true
|
||||
|
||||
on_broadcast:
|
||||
- then:
|
||||
- lambda: |-
|
||||
char src_mac[18];
|
||||
snprintf(src_mac, sizeof(src_mac), "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
info.src_addr[0], info.src_addr[1], info.src_addr[2],
|
||||
info.src_addr[3], info.src_addr[4], info.src_addr[5]);
|
||||
|
||||
std::string payload(reinterpret_cast<const char *>(data), size);
|
||||
int rssi = info.rx_ctrl ? info.rx_ctrl->rssi : 0;
|
||||
|
||||
id(last_sender_mac).publish_state(src_mac);
|
||||
id(last_payload).publish_state(payload);
|
||||
id(last_rssi).publish_state(rssi);
|
||||
|
||||
id(received_count) += 1;
|
||||
id(received_count_sensor).publish_state(id(received_count));
|
||||
|
||||
ESP_LOGI("espnow_rx", "ESP-NOW broadcast from %s, RSSI %d dBm, payload: %s",
|
||||
src_mac, rssi, payload.c_str());
|
||||
|
||||
// Test payload format:
|
||||
// REMOTE_A:BUTTON_1:123
|
||||
//
|
||||
// For now, use the whole payload as the duplicate key.
|
||||
// This means the 2nd and 3rd repeated sends from one button press are ignored.
|
||||
if (payload == id(last_unique_payload)) {
|
||||
id(duplicate_count) += 1;
|
||||
id(duplicate_count_sensor).publish_state(id(duplicate_count));
|
||||
id(packet_is_unique) = false;
|
||||
|
||||
ESP_LOGD("espnow_rx", "Duplicate ESP-NOW payload ignored: %s", payload.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
id(last_unique_payload) = payload;
|
||||
id(packet_is_unique) = true;
|
||||
|
||||
// Split simple colon-delimited payload for HA visibility.
|
||||
size_t first_colon = payload.find(':');
|
||||
size_t second_colon = payload.find(':', first_colon + 1);
|
||||
|
||||
if (first_colon != std::string::npos && second_colon != std::string::npos) {
|
||||
std::string remote_id = payload.substr(0, first_colon);
|
||||
std::string button_id = payload.substr(first_colon + 1, second_colon - first_colon - 1);
|
||||
std::string press_id = payload.substr(second_colon + 1);
|
||||
|
||||
id(last_remote_id).publish_state(remote_id);
|
||||
id(last_button_id).publish_state(button_id);
|
||||
id(last_press_id).publish_state(press_id);
|
||||
|
||||
ESP_LOGI("espnow_rx", "Unique press: remote=%s button=%s press_id=%s",
|
||||
remote_id.c_str(), button_id.c_str(), press_id.c_str());
|
||||
} else {
|
||||
id(last_remote_id).publish_state("unknown");
|
||||
id(last_button_id).publish_state("unknown");
|
||||
id(last_press_id).publish_state("unknown");
|
||||
|
||||
ESP_LOGW("espnow_rx", "Payload did not match expected format: %s", payload.c_str());
|
||||
}
|
||||
|
||||
- if:
|
||||
condition:
|
||||
lambda: |-
|
||||
return id(packet_is_unique);
|
||||
then:
|
||||
- binary_sensor.template.publish:
|
||||
id: espnow_unique_press_event
|
||||
state: ON
|
||||
- script.execute: clear_unique_press_event
|
||||
|
||||
#:########################################################################################:#
|
||||
# Globals
|
||||
#:########################################################################################:#
|
||||
|
||||
globals:
|
||||
- id: received_count
|
||||
type: int
|
||||
restore_value: true
|
||||
initial_value: '0'
|
||||
|
||||
- id: duplicate_count
|
||||
type: int
|
||||
restore_value: true
|
||||
initial_value: '0'
|
||||
|
||||
- id: last_unique_payload
|
||||
type: std::string
|
||||
restore_value: true
|
||||
initial_value: '""'
|
||||
|
||||
- id: packet_is_unique
|
||||
type: bool
|
||||
restore_value: false
|
||||
initial_value: 'false'
|
||||
|
||||
#:########################################################################################:#
|
||||
# Scripts
|
||||
#:########################################################################################:#
|
||||
|
||||
script:
|
||||
- id: clear_unique_press_event
|
||||
mode: restart
|
||||
then:
|
||||
- delay: 500ms
|
||||
- binary_sensor.template.publish:
|
||||
id: espnow_unique_press_event
|
||||
state: OFF
|
||||
|
||||
#:########################################################################################:#
|
||||
# Home Assistant Entities
|
||||
#:########################################################################################:#
|
||||
|
||||
text_sensor:
|
||||
- platform: template
|
||||
name: "Last Sender MAC"
|
||||
id: last_sender_mac
|
||||
icon: mdi:access-point-network
|
||||
|
||||
- platform: template
|
||||
name: "Last Payload"
|
||||
id: last_payload
|
||||
icon: mdi:message-text
|
||||
|
||||
- platform: template
|
||||
name: "Last Remote ID"
|
||||
id: last_remote_id
|
||||
icon: mdi:remote
|
||||
|
||||
- platform: template
|
||||
name: "Last Button ID"
|
||||
id: last_button_id
|
||||
icon: mdi:gesture-tap-button
|
||||
|
||||
- platform: template
|
||||
name: "Last Press ID"
|
||||
id: last_press_id
|
||||
icon: mdi:identifier
|
||||
|
||||
sensor:
|
||||
- platform: template
|
||||
name: "Last RSSI"
|
||||
id: last_rssi
|
||||
unit_of_measurement: "dBm"
|
||||
accuracy_decimals: 0
|
||||
icon: mdi:wifi-strength-2
|
||||
|
||||
- platform: template
|
||||
name: "Received Count"
|
||||
id: received_count_sensor
|
||||
accuracy_decimals: 0
|
||||
icon: mdi:counter
|
||||
|
||||
- platform: template
|
||||
name: "Duplicate Count"
|
||||
id: duplicate_count_sensor
|
||||
accuracy_decimals: 0
|
||||
icon: mdi:counter
|
||||
|
||||
binary_sensor:
|
||||
- platform: template
|
||||
name: "Unique Press Event"
|
||||
id: espnow_unique_press_event
|
||||
icon: mdi:gesture-tap-button
|
||||
|
||||
button:
|
||||
- platform: template
|
||||
name: "Reset ESP-NOW Test Counts"
|
||||
icon: mdi:counter
|
||||
on_press:
|
||||
then:
|
||||
- lambda: |-
|
||||
id(received_count) = 0;
|
||||
id(duplicate_count) = 0;
|
||||
id(last_unique_payload) = "";
|
||||
id(received_count_sensor).publish_state(0);
|
||||
id(duplicate_count_sensor).publish_state(0);
|
||||
Reference in New Issue
Block a user