mirror of
https://github.com/esphome/esphome.git
synced 2026-05-24 01:37:15 +08:00
[nextion] Expose custom protocol frames as automation triggers (#13248)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io>
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
|
||||
#include "nextion.h"
|
||||
|
||||
namespace esphome::nextion {
|
||||
|
||||
@@ -19,6 +19,10 @@ CONF_MAX_COMMANDS_PER_LOOP = "max_commands_per_loop"
|
||||
CONF_MAX_QUEUE_AGE = "max_queue_age"
|
||||
CONF_MAX_QUEUE_SIZE = "max_queue_size"
|
||||
CONF_ON_BUFFER_OVERFLOW = "on_buffer_overflow"
|
||||
CONF_ON_CUSTOM_BINARY_SENSOR = "on_custom_binary_sensor"
|
||||
CONF_ON_CUSTOM_SENSOR = "on_custom_sensor"
|
||||
CONF_ON_CUSTOM_SWITCH = "on_custom_switch"
|
||||
CONF_ON_CUSTOM_TEXT_SENSOR = "on_custom_text_sensor"
|
||||
CONF_ON_PAGE = "on_page"
|
||||
CONF_ON_SETUP = "on_setup"
|
||||
CONF_ON_SLEEP = "on_sleep"
|
||||
|
||||
@@ -20,6 +20,10 @@ from .base_component import (
|
||||
CONF_MAX_QUEUE_AGE,
|
||||
CONF_MAX_QUEUE_SIZE,
|
||||
CONF_ON_BUFFER_OVERFLOW,
|
||||
CONF_ON_CUSTOM_BINARY_SENSOR,
|
||||
CONF_ON_CUSTOM_SENSOR,
|
||||
CONF_ON_CUSTOM_SWITCH,
|
||||
CONF_ON_CUSTOM_TEXT_SENSOR,
|
||||
CONF_ON_PAGE,
|
||||
CONF_ON_SETUP,
|
||||
CONF_ON_SLEEP,
|
||||
@@ -88,6 +92,12 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.Optional(CONF_MAX_COMMANDS_PER_LOOP): cv.uint16_t,
|
||||
cv.Optional(CONF_MAX_QUEUE_SIZE): cv.positive_int,
|
||||
cv.Optional(CONF_ON_BUFFER_OVERFLOW): automation.validate_automation({}),
|
||||
cv.Optional(CONF_ON_CUSTOM_BINARY_SENSOR): automation.validate_automation(
|
||||
{}
|
||||
),
|
||||
cv.Optional(CONF_ON_CUSTOM_SENSOR): automation.validate_automation({}),
|
||||
cv.Optional(CONF_ON_CUSTOM_SWITCH): automation.validate_automation({}),
|
||||
cv.Optional(CONF_ON_CUSTOM_TEXT_SENSOR): automation.validate_automation({}),
|
||||
cv.Optional(CONF_ON_PAGE): automation.validate_automation({}),
|
||||
cv.Optional(CONF_ON_SETUP): automation.validate_automation({}),
|
||||
cv.Optional(CONF_ON_SLEEP): automation.validate_automation({}),
|
||||
@@ -163,8 +173,36 @@ _CALLBACK_AUTOMATIONS = (
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_BUFFER_OVERFLOW, "add_buffer_overflow_event_callback"
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_CUSTOM_BINARY_SENSOR,
|
||||
"add_custom_binary_sensor_callback",
|
||||
[(cg.StringRef, "key"), (cg.bool_, "value")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_CUSTOM_SENSOR,
|
||||
"add_custom_sensor_callback",
|
||||
[(cg.StringRef, "key"), (cg.int32, "value")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_CUSTOM_SWITCH,
|
||||
"add_custom_switch_callback",
|
||||
[(cg.StringRef, "key"), (cg.bool_, "value")],
|
||||
),
|
||||
automation.CallbackAutomation(
|
||||
CONF_ON_CUSTOM_TEXT_SENSOR,
|
||||
"add_custom_text_sensor_callback",
|
||||
[(cg.StringRef, "key"), (cg.StringRef, "value")],
|
||||
),
|
||||
)
|
||||
|
||||
# Map custom trigger config keys to their conditional defines
|
||||
_CUSTOM_TRIGGER_DEFINES = {
|
||||
CONF_ON_CUSTOM_BINARY_SENSOR: "USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR",
|
||||
CONF_ON_CUSTOM_SENSOR: "USE_NEXTION_TRIGGER_CUSTOM_SENSOR",
|
||||
CONF_ON_CUSTOM_SWITCH: "USE_NEXTION_TRIGGER_CUSTOM_SWITCH",
|
||||
CONF_ON_CUSTOM_TEXT_SENSOR: "USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR",
|
||||
}
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
@@ -253,5 +291,8 @@ async def to_code(config):
|
||||
cg.add(var.set_max_commands_per_loop(max_commands_per_loop))
|
||||
|
||||
await display.register_display(var, config)
|
||||
for conf_key, define_name in _CUSTOM_TRIGGER_DEFINES.items():
|
||||
if config.get(conf_key):
|
||||
cg.add_define(define_name)
|
||||
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include "nextion.h"
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
#include "esphome/core/util.h"
|
||||
|
||||
namespace esphome::nextion {
|
||||
@@ -715,6 +718,10 @@ void Nextion::process_nextion_commands_() {
|
||||
|
||||
ESP_LOGN(TAG, "Switch %s: %s", ONOFF(to_process[index] != 0), variable_name.c_str());
|
||||
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_SWITCH
|
||||
this->custom_switch_callback_.call(StringRef(variable_name), to_process[index] != 0);
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_SWITCH
|
||||
|
||||
for (auto *switchtype : this->switchtype_) {
|
||||
switchtype->process_bool(variable_name, to_process[index] != 0);
|
||||
}
|
||||
@@ -744,6 +751,10 @@ void Nextion::process_nextion_commands_() {
|
||||
|
||||
ESP_LOGN(TAG, "Sensor: %s=%d", variable_name.c_str(), value);
|
||||
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_SENSOR
|
||||
this->custom_sensor_callback_.call(StringRef(variable_name), value);
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_SENSOR
|
||||
|
||||
for (auto *sensor : this->sensortype_) {
|
||||
sensor->process_sensor(variable_name, value);
|
||||
}
|
||||
@@ -781,6 +792,11 @@ void Nextion::process_nextion_commands_() {
|
||||
// nq->variable_name = variable_name;
|
||||
// nq->state = text_value;
|
||||
// this->textsensorq_.push_back(nq);
|
||||
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR
|
||||
this->custom_text_sensor_callback_.call(StringRef(variable_name), StringRef(text_value));
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR
|
||||
|
||||
for (auto *textsensortype : this->textsensortype_) {
|
||||
textsensortype->process_text(variable_name, text_value);
|
||||
}
|
||||
@@ -808,6 +824,10 @@ void Nextion::process_nextion_commands_() {
|
||||
|
||||
ESP_LOGN(TAG, "Binary sensor: %s=%s", variable_name.c_str(), ONOFF(to_process[index] != 0));
|
||||
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR
|
||||
this->custom_binary_sensor_callback_.call(StringRef(variable_name), to_process[index] != 0);
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR
|
||||
|
||||
for (auto *binarysensortype : this->binarysensortype_) {
|
||||
binarysensortype->process_bool(&variable_name[0], to_process[index] != 0);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "esphome/components/display/display_color_utils.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
#include "esphome/core/time.h"
|
||||
|
||||
#ifdef USE_NEXTION_WAVEFORM
|
||||
@@ -1183,6 +1184,59 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
this->buffer_overflow_callback_.add(std::forward<F>(callback));
|
||||
}
|
||||
|
||||
// Callbacks for Nextion "custom protocol" frames (0x90..0x93)
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR
|
||||
/** Add a callback to be notified when Nextion sends a custom binary sensor protocol frame (0x93).
|
||||
*
|
||||
* This callback is invoked when a Nextion custom binary sensor frame is received,
|
||||
* providing the component name as the key and the decoded boolean value.
|
||||
*
|
||||
* @param callback The void(const StringRef &key, bool value) callback.
|
||||
*/
|
||||
template<typename F> void add_custom_binary_sensor_callback(F &&callback) {
|
||||
this->custom_binary_sensor_callback_.add(std::forward<F>(callback));
|
||||
}
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR
|
||||
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_SENSOR
|
||||
/** Add a callback to be notified when Nextion sends a custom sensor protocol frame (0x91).
|
||||
*
|
||||
* This callback is invoked when a Nextion custom sensor frame is received,
|
||||
* providing the component name as the key and the decoded integer value.
|
||||
*
|
||||
* @param callback The void(StringRef key, int32_t value) callback.
|
||||
*/
|
||||
template<typename F> void add_custom_sensor_callback(F &&callback) {
|
||||
this->custom_sensor_callback_.add(std::forward<F>(callback));
|
||||
}
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_SENSOR
|
||||
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_SWITCH
|
||||
/** Add a callback to be notified when Nextion sends a custom switch protocol frame (0x90).
|
||||
*
|
||||
* This callback is invoked when a Nextion custom switch frame is received,
|
||||
* providing the component name as the key and the decoded boolean value.
|
||||
*
|
||||
* @param callback The void(const StringRef &key, bool value) callback.
|
||||
*/
|
||||
template<typename F> void add_custom_switch_callback(F &&callback) {
|
||||
this->custom_switch_callback_.add(std::forward<F>(callback));
|
||||
}
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_SWITCH
|
||||
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR
|
||||
/** Add a callback to be notified when Nextion sends a custom text sensor protocol frame (0x92).
|
||||
*
|
||||
* This callback is invoked when a Nextion custom text sensor frame is received,
|
||||
* providing the component name as the key and the decoded text value.
|
||||
*
|
||||
* @param callback The void(const StringRef &key, const StringRef &value) callback.
|
||||
*/
|
||||
template<typename F> void add_custom_text_sensor_callback(F &&callback) {
|
||||
this->custom_text_sensor_callback_.add(std::forward<F>(callback));
|
||||
}
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR
|
||||
|
||||
void update_all_components();
|
||||
|
||||
/**
|
||||
@@ -1535,6 +1589,18 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
CallbackManager<void(uint8_t)> page_callback_{};
|
||||
CallbackManager<void(uint8_t, uint8_t, bool)> touch_callback_{};
|
||||
CallbackManager<void()> buffer_overflow_callback_{};
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR
|
||||
CallbackManager<void(StringRef, bool)> custom_binary_sensor_callback_{};
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_SENSOR
|
||||
CallbackManager<void(StringRef, int32_t)> custom_sensor_callback_{};
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_SENSOR
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_SWITCH
|
||||
CallbackManager<void(StringRef, bool)> custom_switch_callback_{};
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_SWITCH
|
||||
#ifdef USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR
|
||||
CallbackManager<void(StringRef, StringRef)> custom_text_sensor_callback_{};
|
||||
#endif // USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR
|
||||
|
||||
nextion_writer_t writer_;
|
||||
optional<float> brightness_;
|
||||
|
||||
@@ -123,6 +123,10 @@
|
||||
#define USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||
#define USE_NEXTION_MAX_QUEUE_SIZE
|
||||
#define USE_NEXTION_TFT_UPLOAD
|
||||
#define USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR
|
||||
#define USE_NEXTION_TRIGGER_CUSTOM_SENSOR
|
||||
#define USE_NEXTION_TRIGGER_CUSTOM_SWITCH
|
||||
#define USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR
|
||||
#define USE_NEXTION_WAVEFORM
|
||||
#define USE_NUMBER
|
||||
#define USE_OUTPUT
|
||||
|
||||
@@ -286,6 +286,31 @@ display:
|
||||
on_buffer_overflow:
|
||||
then:
|
||||
logger.log: "Nextion reported a buffer overflow!"
|
||||
on_custom_text_sensor:
|
||||
then:
|
||||
- lambda: |-
|
||||
// key: StringRef, value: StringRef
|
||||
if (key == "csv") {
|
||||
// parse value here, or forward to your own component
|
||||
ESP_LOGD("nextion.csv", "Got CSV: %s", value.c_str());
|
||||
}
|
||||
on_custom_sensor:
|
||||
then:
|
||||
- lambda: |-
|
||||
// key: StringRef, value: int32_t
|
||||
if (key == "temperature_raw") {
|
||||
ESP_LOGD("nextion.custom", "%s=%d", key.c_str(), value);
|
||||
}
|
||||
on_custom_binary_sensor:
|
||||
then:
|
||||
- lambda: |-
|
||||
if (key == "btn1") {
|
||||
ESP_LOGD("nextion.btn", "btn1=%s", ONOFF(value));
|
||||
}
|
||||
on_custom_switch:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("nextion.sw", "%s=%s", key.c_str(), ONOFF(value));
|
||||
on_page:
|
||||
then:
|
||||
lambda: 'ESP_LOGD("display","Display shows new page %u", x);'
|
||||
@@ -304,8 +329,8 @@ display:
|
||||
on_wake:
|
||||
then:
|
||||
lambda: 'ESP_LOGD("display","Display woke up");'
|
||||
update_interval: 5s
|
||||
start_up_page: 1
|
||||
startup_override_ms: 10000ms # Wait 10s for display ready
|
||||
touch_sleep_timeout: 3
|
||||
update_interval: 5s
|
||||
wake_up_page: 2
|
||||
|
||||
Reference in New Issue
Block a user