mirror of
https://github.com/esphome/esphome.git
synced 2024-11-23 07:28:10 +01:00
Nextion upload and sensors (#1464)
Co-authored-by: Senex Crenshaw <senexcrenshaw@gmail.com>
This commit is contained in:
parent
f30b8f6b3c
commit
4dbf1c521e
30 changed files with 3295 additions and 263 deletions
|
@ -73,6 +73,11 @@ esphome/components/midea_ac/* @dudanov
|
||||||
esphome/components/midea_dongle/* @dudanov
|
esphome/components/midea_dongle/* @dudanov
|
||||||
esphome/components/mitsubishi/* @RubyBailey
|
esphome/components/mitsubishi/* @RubyBailey
|
||||||
esphome/components/network/* @esphome/core
|
esphome/components/network/* @esphome/core
|
||||||
|
esphome/components/nextion/* @senexcrenshaw
|
||||||
|
esphome/components/nextion/binary_sensor/* @senexcrenshaw
|
||||||
|
esphome/components/nextion/sensor/* @senexcrenshaw
|
||||||
|
esphome/components/nextion/switch/* @senexcrenshaw
|
||||||
|
esphome/components/nextion/text_sensor/* @senexcrenshaw
|
||||||
esphome/components/nfc/* @jesserockz
|
esphome/components/nfc/* @jesserockz
|
||||||
esphome/components/number/* @esphome/core
|
esphome/components/number/* @esphome/core
|
||||||
esphome/components/ota/* @esphome/core
|
esphome/components/ota/* @esphome/core
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import uart
|
||||||
|
|
||||||
nextion_ns = cg.esphome_ns.namespace("nextion")
|
nextion_ns = cg.esphome_ns.namespace("nextion")
|
||||||
|
Nextion = nextion_ns.class_("Nextion", cg.PollingComponent, uart.UARTDevice)
|
||||||
|
nextion_ref = Nextion.operator("ref")
|
||||||
|
|
||||||
|
CONF_NEXTION_ID = "nextion_id"
|
||||||
|
|
30
esphome/components/nextion/automation.h
Normal file
30
esphome/components/nextion/automation.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
#include "esphome/core/automation.h"
|
||||||
|
#include "nextion.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
|
||||||
|
class SetupTrigger : public Trigger<> {
|
||||||
|
public:
|
||||||
|
explicit SetupTrigger(Nextion *nextion) {
|
||||||
|
nextion->add_setup_state_callback([this]() { this->trigger(); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SleepTrigger : public Trigger<> {
|
||||||
|
public:
|
||||||
|
explicit SleepTrigger(Nextion *nextion) {
|
||||||
|
nextion->add_sleep_state_callback([this]() { this->trigger(); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WakeTrigger : public Trigger<> {
|
||||||
|
public:
|
||||||
|
explicit WakeTrigger(Nextion *nextion) {
|
||||||
|
nextion->add_wake_state_callback([this]() { this->trigger(); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
126
esphome/components/nextion/base_component.py
Normal file
126
esphome/components/nextion/base_component.py
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
from string import ascii_letters, digits
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import color
|
||||||
|
|
||||||
|
from . import CONF_NEXTION_ID
|
||||||
|
from . import Nextion
|
||||||
|
|
||||||
|
CONF_VARIABLE_NAME = "variable_name"
|
||||||
|
CONF_COMPONENT_NAME = "component_name"
|
||||||
|
CONF_WAVE_CHANNEL_ID = "wave_channel_id"
|
||||||
|
CONF_WAVE_MAX_VALUE = "wave_max_value"
|
||||||
|
CONF_PRECISION = "precision"
|
||||||
|
CONF_WAVEFORM_SEND_LAST_VALUE = "waveform_send_last_value"
|
||||||
|
CONF_TFT_URL = "tft_url"
|
||||||
|
CONF_ON_SLEEP = "on_sleep"
|
||||||
|
CONF_ON_WAKE = "on_wake"
|
||||||
|
CONF_ON_SETUP = "on_setup"
|
||||||
|
CONF_TOUCH_SLEEP_TIMEOUT = "touch_sleep_timeout"
|
||||||
|
CONF_WAKE_UP_PAGE = "wake_up_page"
|
||||||
|
CONF_AUTO_WAKE_ON_TOUCH = "auto_wake_on_touch"
|
||||||
|
CONF_WAVE_MAX_LENGTH = "wave_max_length"
|
||||||
|
CONF_BACKGROUND_COLOR = "background_color"
|
||||||
|
CONF_BACKGROUND_PRESSED_COLOR = "background_pressed_color"
|
||||||
|
CONF_FOREGROUND_COLOR = "foreground_color"
|
||||||
|
CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color"
|
||||||
|
CONF_FONT_ID = "font_id"
|
||||||
|
CONF_VISIBLE = "visible"
|
||||||
|
|
||||||
|
|
||||||
|
def NextionName(value):
|
||||||
|
valid_chars = ascii_letters + digits + "."
|
||||||
|
if not isinstance(value, str) or len(value) > 29:
|
||||||
|
raise cv.Invalid("Must be a string less than 29 characters")
|
||||||
|
|
||||||
|
for char in value:
|
||||||
|
if char not in valid_chars:
|
||||||
|
raise cv.Invalid(
|
||||||
|
"Must only consist of upper/lowercase characters, numbers and the period '.'. The character '{}' cannot be used.".format(
|
||||||
|
char
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_BASE_COMPONENT_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_NEXTION_ID): cv.use_id(Nextion),
|
||||||
|
cv.Optional(CONF_BACKGROUND_COLOR): cv.use_id(color),
|
||||||
|
cv.Optional(CONF_FOREGROUND_COLOR): cv.use_id(color),
|
||||||
|
cv.Optional(CONF_VISIBLE, default=True): cv.boolean,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_TEXT_COMPONENT_SCHEMA = CONFIG_BASE_COMPONENT_SCHEMA.extend(
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_COMPONENT_NAME): NextionName,
|
||||||
|
cv.Optional(CONF_FONT_ID): cv.int_range(min=0, max=255),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
CONFIG_BINARY_SENSOR_SCHEMA = CONFIG_BASE_COMPONENT_SCHEMA.extend(
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_COMPONENT_NAME): NextionName,
|
||||||
|
cv.Optional(CONF_VARIABLE_NAME): NextionName,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
CONFIG_SENSOR_COMPONENT_SCHEMA = CONFIG_BINARY_SENSOR_SCHEMA.extend(
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_FONT_ID): cv.int_range(min=0, max=255),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SWITCH_COMPONENT_SCHEMA = CONFIG_SENSOR_COMPONENT_SCHEMA.extend(
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_FOREGROUND_PRESSED_COLOR): cv.use_id(color),
|
||||||
|
cv.Optional(CONF_BACKGROUND_PRESSED_COLOR): cv.use_id(color),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_component_core_(var, config, arg):
|
||||||
|
|
||||||
|
if CONF_VARIABLE_NAME in config:
|
||||||
|
cg.add(var.set_variable_name(config[CONF_VARIABLE_NAME]))
|
||||||
|
elif CONF_COMPONENT_NAME in config:
|
||||||
|
cg.add(
|
||||||
|
var.set_variable_name(
|
||||||
|
config[CONF_COMPONENT_NAME],
|
||||||
|
config[CONF_COMPONENT_NAME] + arg,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if CONF_BACKGROUND_COLOR in config:
|
||||||
|
color_component = await cg.get_variable(config[CONF_BACKGROUND_COLOR])
|
||||||
|
cg.add(var.set_background_color(color_component))
|
||||||
|
|
||||||
|
if CONF_BACKGROUND_PRESSED_COLOR in config:
|
||||||
|
color_component = await cg.get_variable(config[CONF_BACKGROUND_PRESSED_COLOR])
|
||||||
|
cg.add(var.set_background_pressed_color(color_component))
|
||||||
|
|
||||||
|
if CONF_FOREGROUND_COLOR in config:
|
||||||
|
color_component = await cg.get_variable(config[CONF_FOREGROUND_COLOR])
|
||||||
|
cg.add(var.set_foreground_color(color_component))
|
||||||
|
|
||||||
|
if CONF_FOREGROUND_PRESSED_COLOR in config:
|
||||||
|
color_component = await cg.get_variable(config[CONF_FOREGROUND_PRESSED_COLOR])
|
||||||
|
cg.add(var.set_foreground_pressed_color(color_component))
|
||||||
|
|
||||||
|
if CONF_FONT_ID in config:
|
||||||
|
cg.add(var.set_font_id(config[CONF_FONT_ID]))
|
||||||
|
|
||||||
|
if CONF_VISIBLE in config:
|
||||||
|
cg.add(var.set_visible(config[CONF_VISIBLE]))
|
|
@ -1,34 +0,0 @@
|
||||||
import esphome.codegen as cg
|
|
||||||
import esphome.config_validation as cv
|
|
||||||
from esphome.components import binary_sensor
|
|
||||||
from esphome.const import CONF_COMPONENT_ID, CONF_PAGE_ID, CONF_ID
|
|
||||||
from . import nextion_ns
|
|
||||||
from .display import Nextion
|
|
||||||
|
|
||||||
DEPENDENCIES = ["display"]
|
|
||||||
|
|
||||||
CONF_NEXTION_ID = "nextion_id"
|
|
||||||
|
|
||||||
NextionTouchComponent = nextion_ns.class_(
|
|
||||||
"NextionTouchComponent", binary_sensor.BinarySensor
|
|
||||||
)
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
|
|
||||||
{
|
|
||||||
cv.GenerateID(): cv.declare_id(NextionTouchComponent),
|
|
||||||
cv.GenerateID(CONF_NEXTION_ID): cv.use_id(Nextion),
|
|
||||||
cv.Required(CONF_PAGE_ID): cv.uint8_t,
|
|
||||||
cv.Required(CONF_COMPONENT_ID): cv.uint8_t,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def to_code(config):
|
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
|
||||||
await binary_sensor.register_binary_sensor(var, config)
|
|
||||||
|
|
||||||
hub = await cg.get_variable(config[CONF_NEXTION_ID])
|
|
||||||
cg.add(hub.register_touch_component(var))
|
|
||||||
|
|
||||||
cg.add(var.set_component_id(config[CONF_COMPONENT_ID]))
|
|
||||||
cg.add(var.set_page_id(config[CONF_PAGE_ID]))
|
|
54
esphome/components/nextion/binary_sensor/__init__.py
Normal file
54
esphome/components/nextion/binary_sensor/__init__.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import binary_sensor
|
||||||
|
|
||||||
|
from esphome.const import CONF_COMPONENT_ID, CONF_PAGE_ID, CONF_ID
|
||||||
|
from .. import nextion_ns, CONF_NEXTION_ID
|
||||||
|
|
||||||
|
|
||||||
|
from ..base_component import (
|
||||||
|
setup_component_core_,
|
||||||
|
CONFIG_BINARY_SENSOR_SCHEMA,
|
||||||
|
CONF_VARIABLE_NAME,
|
||||||
|
CONF_COMPONENT_NAME,
|
||||||
|
)
|
||||||
|
|
||||||
|
CODEOWNERS = ["@senexcrenshaw"]
|
||||||
|
|
||||||
|
NextionBinarySensor = nextion_ns.class_(
|
||||||
|
"NextionBinarySensor", binary_sensor.BinarySensor, cg.PollingComponent
|
||||||
|
)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
binary_sensor.BINARY_SENSOR_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(NextionBinarySensor),
|
||||||
|
cv.Optional(CONF_PAGE_ID): cv.uint8_t,
|
||||||
|
cv.Optional(CONF_COMPONENT_ID): cv.uint8_t,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(CONFIG_BINARY_SENSOR_SCHEMA)
|
||||||
|
.extend(cv.polling_component_schema("never")),
|
||||||
|
cv.has_at_least_one_key(
|
||||||
|
CONF_PAGE_ID,
|
||||||
|
CONF_COMPONENT_ID,
|
||||||
|
CONF_COMPONENT_NAME,
|
||||||
|
CONF_VARIABLE_NAME,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
hub = await cg.get_variable(config[CONF_NEXTION_ID])
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID], hub)
|
||||||
|
await binary_sensor.register_binary_sensor(var, config)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
|
if config.keys() >= {CONF_PAGE_ID, CONF_COMPONENT_ID}:
|
||||||
|
cg.add(hub.register_touch_component(var))
|
||||||
|
cg.add(var.set_component_id(config[CONF_COMPONENT_ID]))
|
||||||
|
cg.add(var.set_page_id(config[CONF_PAGE_ID]))
|
||||||
|
|
||||||
|
if CONF_COMPONENT_NAME in config or CONF_VARIABLE_NAME in config:
|
||||||
|
await setup_component_core_(var, config, ".val")
|
||||||
|
cg.add(hub.register_binarysensor_component(var))
|
|
@ -0,0 +1,69 @@
|
||||||
|
#include "nextion_binarysensor.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
|
||||||
|
static const char *const TAG = "nextion_binarysensor";
|
||||||
|
|
||||||
|
void NextionBinarySensor::process_bool(const std::string &variable_name, bool state) {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->variable_name_.empty()) // This is a touch component
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->variable_name_ == variable_name) {
|
||||||
|
this->publish_state(state);
|
||||||
|
ESP_LOGD(TAG, "Processed binarysensor \"%s\" state %s", variable_name.c_str(), state ? "ON" : "OFF");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionBinarySensor::process_touch(uint8_t page_id, uint8_t component_id, bool state) {
|
||||||
|
if (this->page_id_ == page_id && this->component_id_ == component_id) {
|
||||||
|
this->publish_state(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionBinarySensor::update() {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->variable_name_.empty()) // This is a touch component
|
||||||
|
return;
|
||||||
|
|
||||||
|
this->nextion_->add_to_get_queue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionBinarySensor::set_state(bool state, bool publish, bool send_to_nextion) {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->component_id_ == 0) // This is a legacy touch component
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (send_to_nextion) {
|
||||||
|
if (this->nextion_->is_sleeping() || !this->visible_) {
|
||||||
|
this->needs_to_send_update_ = true;
|
||||||
|
} else {
|
||||||
|
this->needs_to_send_update_ = false;
|
||||||
|
this->nextion_->add_no_result_to_queue_with_set(this, (int) state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publish) {
|
||||||
|
this->publish_state(state);
|
||||||
|
} else {
|
||||||
|
this->state = state;
|
||||||
|
this->has_state_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->update_component_settings();
|
||||||
|
|
||||||
|
ESP_LOGN(TAG, "Wrote state for sensor \"%s\" state %s", this->variable_name_.c_str(),
|
||||||
|
ONOFF(this->variable_name_.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
|
#include "../nextion_component.h"
|
||||||
|
#include "../nextion_base.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
class NextionBinarySensor;
|
||||||
|
|
||||||
|
class NextionBinarySensor : public NextionComponent,
|
||||||
|
public binary_sensor::BinarySensorInitiallyOff,
|
||||||
|
public PollingComponent {
|
||||||
|
public:
|
||||||
|
NextionBinarySensor(NextionBase *nextion) { this->nextion_ = nextion; }
|
||||||
|
|
||||||
|
void update_component() override { this->update(); }
|
||||||
|
void update() override;
|
||||||
|
void send_state_to_nextion() override { this->set_state(this->state, false); };
|
||||||
|
void process_bool(const std::string &variable_name, bool state) override;
|
||||||
|
void process_touch(uint8_t page_id, uint8_t component_id, bool state) override;
|
||||||
|
|
||||||
|
// Set the components page id for Nextion Touch Component
|
||||||
|
void set_page_id(uint8_t page_id) { page_id_ = page_id; }
|
||||||
|
// Set the components component id for Nextion Touch Component
|
||||||
|
void set_component_id(uint8_t component_id) { component_id_ = component_id; }
|
||||||
|
|
||||||
|
void set_state(bool state) override { this->set_state(state, true, true); }
|
||||||
|
void set_state(bool state, bool publish) override { this->set_state(state, publish, true); }
|
||||||
|
void set_state(bool state, bool publish, bool send_to_nextion) override;
|
||||||
|
|
||||||
|
NextionQueueType get_queue_type() override { return NextionQueueType::BINARY_SENSOR; }
|
||||||
|
void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion) override {}
|
||||||
|
void set_state_from_int(int state_value, bool publish, bool send_to_nextion) override {
|
||||||
|
this->set_state(state_value != 0, publish, send_to_nextion);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t page_id_;
|
||||||
|
};
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
|
@ -1,20 +1,58 @@
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
|
from esphome import automation
|
||||||
from esphome.components import display, uart
|
from esphome.components import display, uart
|
||||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_BRIGHTNESS
|
from esphome.const import (
|
||||||
from . import nextion_ns
|
CONF_ID,
|
||||||
|
CONF_LAMBDA,
|
||||||
|
CONF_BRIGHTNESS,
|
||||||
|
CONF_TRIGGER_ID,
|
||||||
|
)
|
||||||
|
|
||||||
|
from . import Nextion, nextion_ns, nextion_ref
|
||||||
|
from .base_component import (
|
||||||
|
CONF_ON_SLEEP,
|
||||||
|
CONF_ON_WAKE,
|
||||||
|
CONF_ON_SETUP,
|
||||||
|
CONF_TFT_URL,
|
||||||
|
CONF_TOUCH_SLEEP_TIMEOUT,
|
||||||
|
CONF_WAKE_UP_PAGE,
|
||||||
|
CONF_AUTO_WAKE_ON_TOUCH,
|
||||||
|
)
|
||||||
|
|
||||||
|
CODEOWNERS = ["@senexcrenshaw"]
|
||||||
|
|
||||||
DEPENDENCIES = ["uart"]
|
DEPENDENCIES = ["uart"]
|
||||||
AUTO_LOAD = ["binary_sensor"]
|
AUTO_LOAD = ["binary_sensor", "switch", "sensor", "text_sensor"]
|
||||||
|
|
||||||
Nextion = nextion_ns.class_("Nextion", cg.PollingComponent, uart.UARTDevice)
|
SetupTrigger = nextion_ns.class_("SetupTrigger", automation.Trigger.template())
|
||||||
NextionRef = Nextion.operator("ref")
|
SleepTrigger = nextion_ns.class_("SleepTrigger", automation.Trigger.template())
|
||||||
|
WakeTrigger = nextion_ns.class_("WakeTrigger", automation.Trigger.template())
|
||||||
|
|
||||||
CONFIG_SCHEMA = (
|
CONFIG_SCHEMA = (
|
||||||
display.BASIC_DISPLAY_SCHEMA.extend(
|
display.BASIC_DISPLAY_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(Nextion),
|
cv.GenerateID(): cv.declare_id(Nextion),
|
||||||
|
cv.Optional(CONF_TFT_URL): cv.string,
|
||||||
cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage,
|
cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage,
|
||||||
|
cv.Optional(CONF_ON_SETUP): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SetupTrigger),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ON_SLEEP): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SleepTrigger),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ON_WAKE): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(WakeTrigger),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_TOUCH_SLEEP_TIMEOUT): cv.int_range(min=3, max=65535),
|
||||||
|
cv.Optional(CONF_WAKE_UP_PAGE): cv.positive_int,
|
||||||
|
cv.Optional(CONF_AUTO_WAKE_ON_TOUCH, default=True): cv.boolean,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(cv.polling_component_schema("5s"))
|
.extend(cv.polling_component_schema("5s"))
|
||||||
|
@ -31,8 +69,33 @@ async def to_code(config):
|
||||||
cg.add(var.set_brightness(config[CONF_BRIGHTNESS]))
|
cg.add(var.set_brightness(config[CONF_BRIGHTNESS]))
|
||||||
if CONF_LAMBDA in config:
|
if CONF_LAMBDA in config:
|
||||||
lambda_ = await cg.process_lambda(
|
lambda_ = await cg.process_lambda(
|
||||||
config[CONF_LAMBDA], [(NextionRef, "it")], return_type=cg.void
|
config[CONF_LAMBDA], [(nextion_ref, "it")], return_type=cg.void
|
||||||
)
|
)
|
||||||
cg.add(var.set_writer(lambda_))
|
cg.add(var.set_writer(lambda_))
|
||||||
|
|
||||||
|
if CONF_TFT_URL in config:
|
||||||
|
cg.add_define("USE_TFT_UPLOAD")
|
||||||
|
cg.add(var.set_tft_url(config[CONF_TFT_URL]))
|
||||||
|
|
||||||
|
if CONF_TOUCH_SLEEP_TIMEOUT in config:
|
||||||
|
cg.add(var.set_touch_sleep_timeout_internal(config[CONF_TOUCH_SLEEP_TIMEOUT]))
|
||||||
|
|
||||||
|
if CONF_WAKE_UP_PAGE in config:
|
||||||
|
cg.add(var.set_wake_up_page_internal(config[CONF_WAKE_UP_PAGE]))
|
||||||
|
|
||||||
|
if CONF_AUTO_WAKE_ON_TOUCH in config:
|
||||||
|
cg.add(var.set_auto_wake_on_touch_internal(config[CONF_AUTO_WAKE_ON_TOUCH]))
|
||||||
|
|
||||||
await display.register_display(var, config)
|
await display.register_display(var, config)
|
||||||
|
|
||||||
|
for conf in config.get(CONF_ON_SETUP, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
await automation.build_automation(trigger, [], conf)
|
||||||
|
|
||||||
|
for conf in config.get(CONF_ON_SLEEP, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
await automation.build_automation(trigger, [], conf)
|
||||||
|
|
||||||
|
for conf in config.get(CONF_ON_WAKE, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
await automation.build_automation(trigger, [], conf)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "esphome/core/component.h"
|
#include <deque>
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/components/uart/uart.h"
|
#include "esphome/components/uart/uart.h"
|
||||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
#include "nextion_base.h"
|
||||||
|
#include "nextion_component.h"
|
||||||
|
#include "esphome/components/display/display_color_utils.h"
|
||||||
|
|
||||||
|
#if defined(USE_ETHERNET) || defined(USE_WIFI)
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
#include <HTTPClient.h>
|
||||||
|
#endif
|
||||||
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
#include <ESP8266HTTPClient.h>
|
||||||
|
#include <WiFiClientSecure.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_TIME
|
#ifdef USE_TIME
|
||||||
#include "esphome/components/time/real_time_clock.h"
|
#include "esphome/components/time/real_time_clock.h"
|
||||||
|
@ -12,12 +24,14 @@
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace nextion {
|
namespace nextion {
|
||||||
|
|
||||||
class NextionTouchComponent;
|
|
||||||
class Nextion;
|
class Nextion;
|
||||||
|
class NextionComponentBase;
|
||||||
|
|
||||||
using nextion_writer_t = std::function<void(Nextion &)>;
|
using nextion_writer_t = std::function<void(Nextion &)>;
|
||||||
|
|
||||||
class Nextion : public PollingComponent, public uart::UARTDevice {
|
static const std::string COMMAND_DELIMITER{static_cast<char>(255), static_cast<char>(255), static_cast<char>(255)};
|
||||||
|
|
||||||
|
class Nextion : public NextionBase, public PollingComponent, public uart::UARTDevice {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Set the text of a component to a static string.
|
* Set the text of a component to a static string.
|
||||||
|
@ -73,9 +87,20 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
*
|
*
|
||||||
* This will change the image of the component `pic` to the image with ID `4`.
|
* This will change the image of the component `pic` to the image with ID `4`.
|
||||||
*/
|
*/
|
||||||
void set_component_picture(const char *component, const char *picture) {
|
void set_component_picture(const char *component, const char *picture);
|
||||||
this->send_command_printf("%s.val=%s", component, picture);
|
/**
|
||||||
}
|
* Set the background color of a component.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param color The color (as a uint32_t).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_background_color("button", 0xFF0000);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the background color of the component `button` to red.
|
||||||
|
*/
|
||||||
|
void set_component_background_color(const char *component, uint32_t color);
|
||||||
/**
|
/**
|
||||||
* Set the background color of a component.
|
* Set the background color of a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
@ -83,7 +108,7 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* ```cpp
|
* ```cpp
|
||||||
* it.set_component_background_color("button", "17013");
|
* it.set_component_background_color("button", "RED");
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This will change the background color of the component `button` to blue.
|
* This will change the background color of the component `button` to blue.
|
||||||
|
@ -91,6 +116,33 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* Nextion HMI colors.
|
* Nextion HMI colors.
|
||||||
*/
|
*/
|
||||||
void set_component_background_color(const char *component, const char *color);
|
void set_component_background_color(const char *component, const char *color);
|
||||||
|
/**
|
||||||
|
* Set the background color of a component.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param color The color (as Color).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_background_color("button", color);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the background color of the component `button` to what color contains.
|
||||||
|
*/
|
||||||
|
void set_component_background_color(const char *component, Color color) override;
|
||||||
|
/**
|
||||||
|
* Set the pressed background color of a component.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param color The color (as a int).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_pressed_background_color("button", 0xFF0000 );
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the pressed background color of the component `button` to red. This is the background color that
|
||||||
|
* is shown when the component is pressed.
|
||||||
|
*/
|
||||||
|
void set_component_pressed_background_color(const char *component, uint32_t color);
|
||||||
/**
|
/**
|
||||||
* Set the pressed background color of a component.
|
* Set the pressed background color of a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
@ -98,7 +150,7 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* ```cpp
|
* ```cpp
|
||||||
* it.set_component_pressed_background_color("button", "17013");
|
* it.set_component_pressed_background_color("button", "RED");
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This will change the pressed background color of the component `button` to blue. This is the background color that
|
* This will change the pressed background color of the component `button` to blue. This is the background color that
|
||||||
|
@ -107,6 +159,63 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* colors.
|
* colors.
|
||||||
*/
|
*/
|
||||||
void set_component_pressed_background_color(const char *component, const char *color);
|
void set_component_pressed_background_color(const char *component, const char *color);
|
||||||
|
/**
|
||||||
|
* Set the pressed background color of a component.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param color The color (as Color).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_pressed_background_color("button", color);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the pressed background color of the component `button` to blue. This is the background color that
|
||||||
|
* is shown when the component is pressed. Use this [color
|
||||||
|
* picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to Nextion HMI
|
||||||
|
* colors.
|
||||||
|
*/
|
||||||
|
void set_component_pressed_background_color(const char *component, Color color) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the picture id of a component.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param pic_id The picture ID.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_pic("textview", 1);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the picture id of the component `textview`.
|
||||||
|
*/
|
||||||
|
void set_component_pic(const char *component, uint8_t pic_id);
|
||||||
|
/**
|
||||||
|
* Set the background picture id of component.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param pic_id The picture ID.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_picc("textview", 1);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the background picture id of the component `textview`.
|
||||||
|
*/
|
||||||
|
void set_component_picc(const char *component, uint8_t pic_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the font color of a component.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param color The color (as a uint32_t ).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_font_color("textview", 0xFF0000);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the font color of the component `textview` to a red color.
|
||||||
|
*/
|
||||||
|
void set_component_font_color(const char *component, uint32_t color);
|
||||||
/**
|
/**
|
||||||
* Set the font color of a component.
|
* Set the font color of a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
@ -114,7 +223,7 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* ```cpp
|
* ```cpp
|
||||||
* it.set_component_font_color("textview", "17013");
|
* it.set_component_font_color("textview", "RED");
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This will change the font color of the component `textview` to a blue color.
|
* This will change the font color of the component `textview` to a blue color.
|
||||||
|
@ -122,6 +231,34 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* Nextion HMI colors.
|
* Nextion HMI colors.
|
||||||
*/
|
*/
|
||||||
void set_component_font_color(const char *component, const char *color);
|
void set_component_font_color(const char *component, const char *color);
|
||||||
|
/**
|
||||||
|
* Set the font color of a component.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param color The color (as Color).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_font_color("textview", color);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the font color of the component `textview` to a blue color.
|
||||||
|
* Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to
|
||||||
|
* Nextion HMI colors.
|
||||||
|
*/
|
||||||
|
void set_component_font_color(const char *component, Color color) override;
|
||||||
|
/**
|
||||||
|
* Set the pressed font color of a component.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param color The color (as a uint32_t).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_pressed_font_color("button", 0xFF0000);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the pressed font color of the component `button` to a red.
|
||||||
|
*/
|
||||||
|
void set_component_pressed_font_color(const char *component, uint32_t color);
|
||||||
/**
|
/**
|
||||||
* Set the pressed font color of a component.
|
* Set the pressed font color of a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
@ -129,7 +266,7 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* ```cpp
|
* ```cpp
|
||||||
* it.set_component_pressed_font_color("button", "17013");
|
* it.set_component_pressed_font_color("button", "RED");
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* This will change the pressed font color of the component `button` to a blue color.
|
* This will change the pressed font color of the component `button` to a blue color.
|
||||||
|
@ -137,6 +274,21 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* Nextion HMI colors.
|
* Nextion HMI colors.
|
||||||
*/
|
*/
|
||||||
void set_component_pressed_font_color(const char *component, const char *color);
|
void set_component_pressed_font_color(const char *component, const char *color);
|
||||||
|
/**
|
||||||
|
* Set the pressed font color of a component.
|
||||||
|
* @param component The component name.
|
||||||
|
* @param color The color (as Color).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_component_pressed_font_color("button", color);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This will change the pressed font color of the component `button` to a blue color.
|
||||||
|
* Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to
|
||||||
|
* Nextion HMI colors.
|
||||||
|
*/
|
||||||
|
void set_component_pressed_font_color(const char *component, Color color) override;
|
||||||
/**
|
/**
|
||||||
* Set the coordinates of a component on screen.
|
* Set the coordinates of a component on screen.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
@ -163,7 +315,7 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
*
|
*
|
||||||
* Changes the font of the component named `textveiw`. Font IDs are set in the Nextion Editor.
|
* Changes the font of the component named `textveiw`. Font IDs are set in the Nextion Editor.
|
||||||
*/
|
*/
|
||||||
void set_component_font(const char *component, uint8_t font_id);
|
void set_component_font(const char *component, uint8_t font_id) override;
|
||||||
#ifdef USE_TIME
|
#ifdef USE_TIME
|
||||||
/**
|
/**
|
||||||
* Send the current time to the nextion display.
|
* Send the current time to the nextion display.
|
||||||
|
@ -195,7 +347,7 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
*
|
*
|
||||||
* Hides the component named `button`.
|
* Hides the component named `button`.
|
||||||
*/
|
*/
|
||||||
void hide_component(const char *component);
|
void hide_component(const char *component) override;
|
||||||
/**
|
/**
|
||||||
* Show a component.
|
* Show a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
@ -207,7 +359,7 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
*
|
*
|
||||||
* Shows the component named `button`.
|
* Shows the component named `button`.
|
||||||
*/
|
*/
|
||||||
void show_component(const char *component);
|
void show_component(const char *component) override;
|
||||||
/**
|
/**
|
||||||
* Enable touch for a component.
|
* Enable touch for a component.
|
||||||
* @param component The component name.
|
* @param component The component name.
|
||||||
|
@ -239,6 +391,7 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* @param value The value to write.
|
* @param value The value to write.
|
||||||
*/
|
*/
|
||||||
void add_waveform_data(int component_id, uint8_t channel_number, uint8_t value);
|
void add_waveform_data(int component_id, uint8_t channel_number, uint8_t value);
|
||||||
|
void open_waveform_channel(int component_id, uint8_t channel_number, uint8_t value);
|
||||||
/**
|
/**
|
||||||
* Display a picture at coordinates.
|
* Display a picture at coordinates.
|
||||||
* @param picture_id The picture id.
|
* @param picture_id The picture id.
|
||||||
|
@ -263,7 +416,7 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* ```cpp
|
* ```cpp
|
||||||
* fill_area(50, 50, 100, 100, "17013");
|
* fill_area(50, 50, 100, 100, "RED");
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Fills an area that starts at x coordiante `50` and y coordinate `50` with a height of `100` and width of `100` with
|
* Fills an area that starts at x coordiante `50` and y coordinate `50` with a height of `100` and width of `100` with
|
||||||
|
@ -271,6 +424,24 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* convert color codes to Nextion HMI colors
|
* convert color codes to Nextion HMI colors
|
||||||
*/
|
*/
|
||||||
void fill_area(int x1, int y1, int width, int height, const char *color);
|
void fill_area(int x1, int y1, int width, int height, const char *color);
|
||||||
|
/**
|
||||||
|
* Fill a rectangle with a color.
|
||||||
|
* @param x1 The starting x coordinate.
|
||||||
|
* @param y1 The starting y coordinate.
|
||||||
|
* @param width The width to draw.
|
||||||
|
* @param height The height to draw.
|
||||||
|
* @param color The color to draw with (as Color).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* fill_area(50, 50, 100, 100, color);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Fills an area that starts at x coordiante `50` and y coordinate `50` with a height of `100` and width of `100` with
|
||||||
|
* the color of blue. Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to
|
||||||
|
* convert color codes to Nextion HMI colors
|
||||||
|
*/
|
||||||
|
void fill_area(int x1, int y1, int width, int height, Color color);
|
||||||
/**
|
/**
|
||||||
* Draw a line on the screen.
|
* Draw a line on the screen.
|
||||||
* @param x1 The starting x coordinate.
|
* @param x1 The starting x coordinate.
|
||||||
|
@ -290,6 +461,25 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* colors.
|
* colors.
|
||||||
*/
|
*/
|
||||||
void line(int x1, int y1, int x2, int y2, const char *color);
|
void line(int x1, int y1, int x2, int y2, const char *color);
|
||||||
|
/**
|
||||||
|
* Draw a line on the screen.
|
||||||
|
* @param x1 The starting x coordinate.
|
||||||
|
* @param y1 The starting y coordinate.
|
||||||
|
* @param x2 The ending x coordinate.
|
||||||
|
* @param y2 The ending y coordinate.
|
||||||
|
* @param color The color to draw with (as Color).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.line(50, 50, 75, 75, "17013");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Makes a line that starts at x coordinate `50` and y coordinate `50` and ends at x coordinate `75` and y coordinate
|
||||||
|
* `75` with the color of blue. Use this [color
|
||||||
|
* picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to Nextion HMI
|
||||||
|
* colors.
|
||||||
|
*/
|
||||||
|
void line(int x1, int y1, int x2, int y2, Color color);
|
||||||
/**
|
/**
|
||||||
* Draw a rectangle outline.
|
* Draw a rectangle outline.
|
||||||
* @param x1 The starting x coordinate.
|
* @param x1 The starting x coordinate.
|
||||||
|
@ -309,6 +499,25 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* colors.
|
* colors.
|
||||||
*/
|
*/
|
||||||
void rectangle(int x1, int y1, int width, int height, const char *color);
|
void rectangle(int x1, int y1, int width, int height, const char *color);
|
||||||
|
/**
|
||||||
|
* Draw a rectangle outline.
|
||||||
|
* @param x1 The starting x coordinate.
|
||||||
|
* @param y1 The starting y coordinate.
|
||||||
|
* @param width The width of the rectangle.
|
||||||
|
* @param height The height of the rectangle.
|
||||||
|
* @param color The color to draw with (as Color).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.rectangle(25, 35, 40, 50, "17013");
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Makes a outline of a rectangle that starts at x coordinate `25` and y coordinate `35` and has a width of `40` and a
|
||||||
|
* length of `50` with color of blue. Use this [color
|
||||||
|
* picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to Nextion HMI
|
||||||
|
* colors.
|
||||||
|
*/
|
||||||
|
void rectangle(int x1, int y1, int width, int height, Color color);
|
||||||
/**
|
/**
|
||||||
* Draw a circle outline
|
* Draw a circle outline
|
||||||
* @param center_x The center x coordinate.
|
* @param center_x The center x coordinate.
|
||||||
|
@ -317,6 +526,14 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* @param color The color to draw with (as a string).
|
* @param color The color to draw with (as a string).
|
||||||
*/
|
*/
|
||||||
void circle(int center_x, int center_y, int radius, const char *color);
|
void circle(int center_x, int center_y, int radius, const char *color);
|
||||||
|
/**
|
||||||
|
* Draw a circle outline
|
||||||
|
* @param center_x The center x coordinate.
|
||||||
|
* @param center_y The center y coordinate.
|
||||||
|
* @param radius The circle radius.
|
||||||
|
* @param color The color to draw with (as Color).
|
||||||
|
*/
|
||||||
|
void circle(int center_x, int center_y, int radius, Color color);
|
||||||
/**
|
/**
|
||||||
* Draw a filled circled.
|
* Draw a filled circled.
|
||||||
* @param center_x The center x coordinate.
|
* @param center_x The center x coordinate.
|
||||||
|
@ -334,19 +551,36 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* Nextion HMI colors.
|
* Nextion HMI colors.
|
||||||
*/
|
*/
|
||||||
void filled_circle(int center_x, int center_y, int radius, const char *color);
|
void filled_circle(int center_x, int center_y, int radius, const char *color);
|
||||||
|
/**
|
||||||
/** Set the brightness of the backlight.
|
* Draw a filled circled.
|
||||||
*
|
* @param center_x The center x coordinate.
|
||||||
* @param brightness The brightness, from 0 to 100.
|
* @param center_y The center y coordinate.
|
||||||
|
* @param radius The circle radius.
|
||||||
|
* @param color The color to draw with (as Color).
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* ```cpp
|
* ```cpp
|
||||||
* it.set_backlight_brightness(30);
|
* it.filled_cricle(25, 25, 10, color);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Makes a filled circle at the x cordinates `25` and y coordinate `25` with a radius of `10` with a color of blue.
|
||||||
|
* Use this [color picker](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to convert color codes to
|
||||||
|
* Nextion HMI colors.
|
||||||
|
*/
|
||||||
|
void filled_circle(int center_x, int center_y, int radius, Color color);
|
||||||
|
|
||||||
|
/** Set the brightness of the backlight.
|
||||||
|
*
|
||||||
|
* @param brightness The brightness percentage from 0 to 1.0.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_backlight_brightness(.3);
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Changes the brightness of the display to 30%.
|
* Changes the brightness of the display to 30%.
|
||||||
*/
|
*/
|
||||||
void set_backlight_brightness(uint8_t brightness);
|
void set_backlight_brightness(float brightness);
|
||||||
/**
|
/**
|
||||||
* Set the touch sleep timeout of the display.
|
* Set the touch sleep timeout of the display.
|
||||||
* @param timeout Timeout in seconds.
|
* @param timeout Timeout in seconds.
|
||||||
|
@ -360,10 +594,46 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
* `thup`.
|
* `thup`.
|
||||||
*/
|
*/
|
||||||
void set_touch_sleep_timeout(uint16_t timeout);
|
void set_touch_sleep_timeout(uint16_t timeout);
|
||||||
|
/**
|
||||||
|
* Sets which page Nextion loads when exiting sleep mode. Note this can be set even when Nextion is in sleep mode.
|
||||||
|
* @param page_id The page id, from 0 to the lage page in Nextion. Set 255 (not set to any existing page) to
|
||||||
|
* wakes up to current page.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_wake_up_page(2);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The display will wake up to page 2.
|
||||||
|
*/
|
||||||
|
void set_wake_up_page(uint8_t page_id = 255);
|
||||||
|
/**
|
||||||
|
* Sets if Nextion should auto-wake from sleep when touch press occurs.
|
||||||
|
* @param auto_wake True or false. When auto_wake is true and Nextion is in sleep mode,
|
||||||
|
* the first touch will only trigger the auto wake mode and not trigger a Touch Event.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```cpp
|
||||||
|
* it.set_auto_wake_on_touch(true);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The display will wake up by touch.
|
||||||
|
*/
|
||||||
|
void set_auto_wake_on_touch(bool auto_wake);
|
||||||
|
/**
|
||||||
|
* Sets Nextion mode between sleep and awake
|
||||||
|
* @param True or false. Sleep=true to enter sleep mode or sleep=false to exit sleep mode.
|
||||||
|
*/
|
||||||
|
void sleep(bool sleep);
|
||||||
|
|
||||||
// ========== INTERNAL METHODS ==========
|
// ========== INTERNAL METHODS ==========
|
||||||
// (In most use cases you won't need these)
|
// (In most use cases you won't need these)
|
||||||
void register_touch_component(NextionTouchComponent *obj) { this->touch_.push_back(obj); }
|
void register_touch_component(NextionComponentBase *obj) { this->touch_.push_back(obj); }
|
||||||
|
void register_switch_component(NextionComponentBase *obj) { this->switchtype_.push_back(obj); }
|
||||||
|
void register_binarysensor_component(NextionComponentBase *obj) { this->binarysensortype_.push_back(obj); }
|
||||||
|
void register_sensor_component(NextionComponentBase *obj) { this->sensortype_.push_back(obj); }
|
||||||
|
void register_textsensor_component(NextionComponentBase *obj) { this->textsensortype_.push_back(obj); }
|
||||||
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void set_brightness(float brightness) { this->brightness_ = brightness; }
|
void set_brightness(float brightness) { this->brightness_ = brightness; }
|
||||||
float get_setup_priority() const override;
|
float get_setup_priority() const override;
|
||||||
|
@ -371,11 +641,9 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
void loop() override;
|
void loop() override;
|
||||||
void set_writer(const nextion_writer_t &writer);
|
void set_writer(const nextion_writer_t &writer);
|
||||||
|
|
||||||
/**
|
// This function has been deprecated
|
||||||
* Manually send a raw command to the display and don't wait for an acknowledgement packet.
|
void set_wait_for_ack(bool wait_for_ack);
|
||||||
* @param command The command to write, for example "vis b0,0".
|
|
||||||
*/
|
|
||||||
void send_command_no_ack(const char *command);
|
|
||||||
/**
|
/**
|
||||||
* Manually send a raw formatted command to the display.
|
* Manually send a raw formatted command to the display.
|
||||||
* @param format The printf-style command format, like "vis %s,0"
|
* @param format The printf-style command format, like "vis %s,0"
|
||||||
|
@ -384,28 +652,199 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||||
*/
|
*/
|
||||||
bool send_command_printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
|
bool send_command_printf(const char *format, ...) __attribute__((format(printf, 2, 3)));
|
||||||
|
|
||||||
void set_wait_for_ack(bool wait_for_ack);
|
#ifdef USE_TFT_UPLOAD
|
||||||
|
/**
|
||||||
|
* Set the tft file URL. https seems problamtic with arduino..
|
||||||
|
*/
|
||||||
|
void set_tft_url(const std::string &tft_url) { this->tft_url_ = tft_url; }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload the tft file and softreset the Nextion
|
||||||
|
*/
|
||||||
|
void upload_tft();
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Softreset the Nextion
|
||||||
|
*/
|
||||||
|
void soft_reset();
|
||||||
|
|
||||||
|
/** Add a callback to be notified of sleep state changes.
|
||||||
|
*
|
||||||
|
* @param callback The void() callback.
|
||||||
|
*/
|
||||||
|
void add_sleep_state_callback(std::function<void()> &&callback);
|
||||||
|
|
||||||
|
/** Add a callback to be notified of wake state changes.
|
||||||
|
*
|
||||||
|
* @param callback The void() callback.
|
||||||
|
*/
|
||||||
|
void add_wake_state_callback(std::function<void()> &&callback);
|
||||||
|
|
||||||
|
/** Add a callback to be notified when the nextion completes its initialize setup.
|
||||||
|
*
|
||||||
|
* @param callback The void() callback.
|
||||||
|
*/
|
||||||
|
void add_setup_state_callback(std::function<void()> &&callback);
|
||||||
|
|
||||||
|
void update_all_components();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the nextion sensor state object.
|
||||||
|
*
|
||||||
|
* @param[in] queue_type
|
||||||
|
* Index of NextionQueueType.
|
||||||
|
*
|
||||||
|
* @param[in] name
|
||||||
|
* Component/variable name.
|
||||||
|
*
|
||||||
|
* @param[in] state
|
||||||
|
* State to set.
|
||||||
|
*/
|
||||||
|
void set_nextion_sensor_state(int queue_type, const std::string &name, float state);
|
||||||
|
void set_nextion_sensor_state(NextionQueueType queue_type, const std::string &name, float state);
|
||||||
|
void set_nextion_text_state(const std::string &name, const std::string &state);
|
||||||
|
|
||||||
|
void add_no_result_to_queue_with_set(NextionComponentBase *component, int state_value) override;
|
||||||
|
void add_no_result_to_queue_with_set(const std::string &variable_name, const std::string &variable_name_to_send,
|
||||||
|
int state_value) override;
|
||||||
|
|
||||||
|
void add_no_result_to_queue_with_set(NextionComponentBase *component, const std::string &state_value) override;
|
||||||
|
void add_no_result_to_queue_with_set(const std::string &variable_name, const std::string &variable_name_to_send,
|
||||||
|
const std::string &state_value) override;
|
||||||
|
|
||||||
|
void add_to_get_queue(NextionComponentBase *component) override;
|
||||||
|
|
||||||
|
void add_addt_command_to_queue(NextionComponentBase *component) override;
|
||||||
|
|
||||||
|
void update_components_by_prefix(const std::string &prefix);
|
||||||
|
|
||||||
|
void set_touch_sleep_timeout_internal(uint32_t touch_sleep_timeout) {
|
||||||
|
this->touch_sleep_timeout_ = touch_sleep_timeout;
|
||||||
|
}
|
||||||
|
void set_wake_up_page_internal(uint8_t wake_up_page) { this->wake_up_page_ = wake_up_page; }
|
||||||
|
void set_auto_wake_on_touch_internal(bool auto_wake_on_touch) { this->auto_wake_on_touch_ = auto_wake_on_touch; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool ack_();
|
std::deque<NextionQueue *> nextion_queue_;
|
||||||
bool read_until_ack_();
|
uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag);
|
||||||
|
void all_components_send_state_(bool force_update = false);
|
||||||
|
uint64_t comok_sent_ = 0;
|
||||||
|
bool remove_from_q_(bool report_empty = true);
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Sends commands ignoring of the Nextion has been setup.
|
||||||
|
*/
|
||||||
|
bool ignore_is_setup_ = false;
|
||||||
|
bool nextion_reports_is_setup_ = false;
|
||||||
|
uint8_t nextion_event_;
|
||||||
|
|
||||||
|
void process_nextion_commands_();
|
||||||
|
void process_serial_();
|
||||||
|
bool is_updating_ = false;
|
||||||
|
uint32_t touch_sleep_timeout_ = 0;
|
||||||
|
int wake_up_page_ = -1;
|
||||||
|
bool auto_wake_on_touch_ = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manually send a raw command to the display and don't wait for an acknowledgement packet.
|
||||||
|
* @param command The command to write, for example "vis b0,0".
|
||||||
|
*/
|
||||||
|
bool send_command_(const std::string &command);
|
||||||
|
void add_no_result_to_queue_(const std::string &variable_name);
|
||||||
|
bool add_no_result_to_queue_with_ignore_sleep_printf_(const std::string &variable_name, const char *format, ...)
|
||||||
|
__attribute__((format(printf, 3, 4)));
|
||||||
|
void add_no_result_to_queue_with_command_(const std::string &variable_name, const std::string &command);
|
||||||
|
|
||||||
|
bool add_no_result_to_queue_with_printf_(const std::string &variable_name, const char *format, ...)
|
||||||
|
__attribute__((format(printf, 3, 4)));
|
||||||
|
|
||||||
|
void add_no_result_to_queue_with_set_internal_(const std::string &variable_name,
|
||||||
|
const std::string &variable_name_to_send, int state_value,
|
||||||
|
bool is_sleep_safe = false);
|
||||||
|
|
||||||
|
void add_no_result_to_queue_with_set_internal_(const std::string &variable_name,
|
||||||
|
const std::string &variable_name_to_send,
|
||||||
|
const std::string &state_value, bool is_sleep_safe = false);
|
||||||
|
|
||||||
|
#ifdef USE_TFT_UPLOAD
|
||||||
|
#if defined(USE_ETHERNET) || defined(USE_WIFI)
|
||||||
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
WiFiClient *wifi_client_{nullptr};
|
||||||
|
BearSSL::WiFiClientSecure *wifi_client_secure_{nullptr};
|
||||||
|
WiFiClient *get_wifi_client_();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* will request chunk_size chunks from the web server
|
||||||
|
* and send each to the nextion
|
||||||
|
* @param int contentLength Total size of the file
|
||||||
|
* @param uint32_t chunk_size
|
||||||
|
* @return true if success, false for failure.
|
||||||
|
*/
|
||||||
|
int content_length_ = 0;
|
||||||
|
int tft_size_ = 0;
|
||||||
|
int upload_by_chunks_(HTTPClient *http, int range_start);
|
||||||
|
|
||||||
|
bool upload_with_range_(uint32_t range_start, uint32_t range_end);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start update tft file to nextion.
|
||||||
|
*
|
||||||
|
* @param const uint8_t *file_buf
|
||||||
|
* @param size_t buf_size
|
||||||
|
* @return true if success, false for failure.
|
||||||
|
*/
|
||||||
|
bool upload_from_buffer_(const uint8_t *file_buf, size_t buf_size);
|
||||||
|
void upload_end_();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool get_is_connected_() { return this->is_connected_; }
|
||||||
|
|
||||||
|
bool check_connect_();
|
||||||
|
|
||||||
|
std::vector<NextionComponentBase *> touch_;
|
||||||
|
std::vector<NextionComponentBase *> switchtype_;
|
||||||
|
std::vector<NextionComponentBase *> sensortype_;
|
||||||
|
std::vector<NextionComponentBase *> textsensortype_;
|
||||||
|
std::vector<NextionComponentBase *> binarysensortype_;
|
||||||
|
CallbackManager<void()> setup_callback_{};
|
||||||
|
CallbackManager<void()> sleep_callback_{};
|
||||||
|
CallbackManager<void()> wake_callback_{};
|
||||||
|
|
||||||
std::vector<NextionTouchComponent *> touch_;
|
|
||||||
optional<nextion_writer_t> writer_;
|
optional<nextion_writer_t> writer_;
|
||||||
bool wait_for_ack_{true};
|
|
||||||
float brightness_{1.0};
|
float brightness_{1.0};
|
||||||
|
|
||||||
|
std::string device_model_;
|
||||||
|
std::string firmware_version_;
|
||||||
|
std::string serial_number_;
|
||||||
|
std::string flash_size_;
|
||||||
|
|
||||||
|
void remove_front_no_sensors_();
|
||||||
|
|
||||||
|
#ifdef USE_TFT_UPLOAD
|
||||||
|
std::string tft_url_;
|
||||||
|
uint8_t *transfer_buffer_{nullptr};
|
||||||
|
size_t transfer_buffer_size_;
|
||||||
|
bool upload_first_chunk_sent_ = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NEXTION_PROTOCOL_LOG
|
||||||
|
void print_queue_members_();
|
||||||
|
#endif
|
||||||
|
void reset_(bool reset_nextion = true);
|
||||||
|
|
||||||
|
std::string command_data_;
|
||||||
|
bool is_connected_ = false;
|
||||||
|
uint32_t startup_override_ms_ = 8000;
|
||||||
|
uint32_t max_q_age_ms_ = 8000;
|
||||||
|
uint32_t started_ms_ = 0;
|
||||||
|
bool sent_setup_commands_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NextionTouchComponent : public binary_sensor::BinarySensorInitiallyOff {
|
|
||||||
public:
|
|
||||||
void set_page_id(uint8_t page_id) { page_id_ = page_id; }
|
|
||||||
void set_component_id(uint8_t component_id) { component_id_ = component_id; }
|
|
||||||
void process(uint8_t page_id, uint8_t component_id, bool on);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
uint8_t page_id_;
|
|
||||||
uint8_t component_id_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace nextion
|
} // namespace nextion
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
58
esphome/components/nextion/nextion_base.h
Normal file
58
esphome/components/nextion/nextion_base.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#pragma once
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
#include "esphome/core/color.h"
|
||||||
|
#include "nextion_component_base.h"
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
|
||||||
|
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
|
||||||
|
#define NEXTION_PROTOCOL_LOG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NEXTION_PROTOCOL_LOG
|
||||||
|
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
|
||||||
|
#define ESP_LOGN(tag, ...) ESP_LOGVV(tag, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define ESP_LOGN(tag, ...) ESP_LOGD(tag, __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define ESP_LOGN(tag, ...) \
|
||||||
|
{}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class NextionBase;
|
||||||
|
|
||||||
|
class NextionBase {
|
||||||
|
public:
|
||||||
|
virtual void add_no_result_to_queue_with_set(NextionComponentBase *component, int state_value) = 0;
|
||||||
|
virtual void add_no_result_to_queue_with_set(const std::string &variable_name,
|
||||||
|
const std::string &variable_name_to_send, int state_value) = 0;
|
||||||
|
|
||||||
|
virtual void add_no_result_to_queue_with_set(NextionComponentBase *component, const std::string &state_value) = 0;
|
||||||
|
virtual void add_no_result_to_queue_with_set(const std::string &variable_name,
|
||||||
|
const std::string &variable_name_to_send,
|
||||||
|
const std::string &state_value) = 0;
|
||||||
|
|
||||||
|
virtual void add_addt_command_to_queue(NextionComponentBase *component) = 0;
|
||||||
|
|
||||||
|
virtual void add_to_get_queue(NextionComponentBase *component) = 0;
|
||||||
|
|
||||||
|
virtual void set_component_background_color(const char *component, Color color) = 0;
|
||||||
|
virtual void set_component_pressed_background_color(const char *component, Color color) = 0;
|
||||||
|
virtual void set_component_font_color(const char *component, Color color) = 0;
|
||||||
|
virtual void set_component_pressed_font_color(const char *component, Color color) = 0;
|
||||||
|
virtual void set_component_font(const char *component, uint8_t font_id) = 0;
|
||||||
|
|
||||||
|
virtual void show_component(const char *component) = 0;
|
||||||
|
virtual void hide_component(const char *component) = 0;
|
||||||
|
|
||||||
|
bool is_sleeping() { return this->is_sleeping_; }
|
||||||
|
bool is_setup() { return this->is_setup_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool is_setup_ = false;
|
||||||
|
bool is_sleeping_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
234
esphome/components/nextion/nextion_commands.cpp
Normal file
234
esphome/components/nextion/nextion_commands.cpp
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
#include "nextion.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
static const char *const TAG = "nextion";
|
||||||
|
|
||||||
|
// Sleep safe commands
|
||||||
|
void Nextion::soft_reset() { this->send_command_("rest"); }
|
||||||
|
|
||||||
|
void Nextion::set_wake_up_page(uint8_t page_id) {
|
||||||
|
if (page_id > 255) {
|
||||||
|
ESP_LOGD(TAG, "Wake up page of bounds, range 0-255");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->add_no_result_to_queue_with_set_internal_("wake_up_page", "wup", page_id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_touch_sleep_timeout(uint16_t timeout) {
|
||||||
|
if (timeout < 3 || timeout > 65535) {
|
||||||
|
ESP_LOGD(TAG, "Sleep timeout out of bounds, range 3-65535");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->add_no_result_to_queue_with_set_internal_("touch_sleep_timeout", "thsp", timeout, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::sleep(bool sleep) {
|
||||||
|
if (sleep) { // Set sleep
|
||||||
|
this->is_sleeping_ = true;
|
||||||
|
this->add_no_result_to_queue_with_set_internal_("sleep", "sleep", 1, true);
|
||||||
|
} else { // Turn off sleep. Wait for a sleep_wake return before setting sleep off
|
||||||
|
this->add_no_result_to_queue_with_set_internal_("sleep_wake", "sleep", 0, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// End sleep safe commands
|
||||||
|
|
||||||
|
// Set Colors
|
||||||
|
void Nextion::set_component_background_color(const char *component, uint32_t color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_background_color", "%s.bco=%d", component, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_background_color(const char *component, const char *color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_background_color", "%s.bco=%s", component, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_background_color(const char *component, Color color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_background_color", "%s.bco=%d", component,
|
||||||
|
display::ColorUtil::color_to_565(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_pressed_background_color(const char *component, uint32_t color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_pressed_background_color", "%s.bco2=%d", component, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_pressed_background_color(const char *component, const char *color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_pressed_background_color", "%s.bco2=%s", component, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_pressed_background_color(const char *component, Color color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_pressed_background_color", "%s.bco2=%d", component,
|
||||||
|
display::ColorUtil::color_to_565(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_pic(const char *component, uint8_t pic_id) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_pic", "%s.pic=%d", component, pic_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_picc(const char *component, uint8_t pic_id) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_pic", "%s.picc=%d", component, pic_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_font_color(const char *component, uint32_t color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_font_color", "%s.pco=%d", component, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_font_color(const char *component, const char *color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_font_color", "%s.pco=%s", component, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_font_color(const char *component, Color color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_font_color", "%s.pco=%d", component,
|
||||||
|
display::ColorUtil::color_to_565(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_pressed_font_color(const char *component, uint32_t color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_pressed_font_color", "%s.pco2=%d", component, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_pressed_font_color(const char *component, const char *color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_pressed_font_color", " %s.pco2=%s", component, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_pressed_font_color(const char *component, Color color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_pressed_font_color", "%s.pco2=%d", component,
|
||||||
|
display::ColorUtil::color_to_565(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_text_printf(const char *component, const char *format, ...) {
|
||||||
|
va_list arg;
|
||||||
|
va_start(arg, format);
|
||||||
|
char buffer[256];
|
||||||
|
int ret = vsnprintf(buffer, sizeof(buffer), format, arg);
|
||||||
|
va_end(arg);
|
||||||
|
if (ret > 0)
|
||||||
|
this->set_component_text(component, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// General Nextion
|
||||||
|
void Nextion::goto_page(const char *page) { this->add_no_result_to_queue_with_printf_("goto_page", "page %s", page); }
|
||||||
|
|
||||||
|
void Nextion::set_backlight_brightness(float brightness) {
|
||||||
|
if (brightness < 0 || brightness > 1.0) {
|
||||||
|
ESP_LOGD(TAG, "Brightness out of bounds, percentage range 0-1.0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->add_no_result_to_queue_with_set("backlight_brightness", "dim", static_cast<int>(brightness * 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_auto_wake_on_touch(bool auto_wake) {
|
||||||
|
this->add_no_result_to_queue_with_set("auto_wake_on_touch", "thup", auto_wake ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// General Component
|
||||||
|
void Nextion::set_component_font(const char *component, uint8_t font_id) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_font", "%s.font=%d", component, font_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::hide_component(const char *component) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("hide_component", "vis %s,0", component);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::show_component(const char *component) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("show_component", "vis %s,1", component);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::enable_component_touch(const char *component) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("enable_component_touch", "tsw %s,1", component);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::disable_component_touch(const char *component) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("disable_component_touch", "tsw %s,0", component);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_picture(const char *component, const char *picture) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_picture", "%s.val=%s", component, picture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_text(const char *component, const char *text) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_text", "%s.txt=\"%s\"", component, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_value(const char *component, int value) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_value", "%s.val=%d", component, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::add_waveform_data(int component_id, uint8_t channel_number, uint8_t value) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("add_waveform_data", "add %d,%u,%u", component_id, channel_number, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::open_waveform_channel(int component_id, uint8_t channel_number, uint8_t value) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("open_waveform_channel", "addt %d,%u,%u", component_id, channel_number,
|
||||||
|
value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::set_component_coordinates(const char *component, int x, int y) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_coordinates command 1", "%s.xcen=%d", component, x);
|
||||||
|
this->add_no_result_to_queue_with_printf_("set_component_coordinates command 2", "%s.ycen=%d", component, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drawing
|
||||||
|
void Nextion::display_picture(int picture_id, int x_start, int y_start) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("display_picture", "pic %d %d %d", x_start, y_start, picture_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::fill_area(int x1, int y1, int width, int height, const char *color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("fill_area", "fill %d,%d,%d,%d,%s", x1, y1, width, height, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::fill_area(int x1, int y1, int width, int height, Color color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("fill_area", "fill %d,%d,%d,%d,%d", x1, y1, width, height,
|
||||||
|
display::ColorUtil::color_to_565(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::line(int x1, int y1, int x2, int y2, const char *color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("line", "line %d,%d,%d,%d,%s", x1, y1, x2, y2, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::line(int x1, int y1, int x2, int y2, Color color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("line", "line %d,%d,%d,%d,%d", x1, y1, x2, y2,
|
||||||
|
display::ColorUtil::color_to_565(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::rectangle(int x1, int y1, int width, int height, const char *color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("draw", "draw %d,%d,%d,%d,%s", x1, y1, x1 + width, y1 + height, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::rectangle(int x1, int y1, int width, int height, Color color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("draw", "draw %d,%d,%d,%d,%d", x1, y1, x1 + width, y1 + height,
|
||||||
|
display::ColorUtil::color_to_565(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::circle(int center_x, int center_y, int radius, const char *color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("cir", "cir %d,%d,%d,%s", center_x, center_y, radius, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::circle(int center_x, int center_y, int radius, Color color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("cir", "cir %d,%d,%d,%d", center_x, center_y, radius,
|
||||||
|
display::ColorUtil::color_to_565(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::filled_circle(int center_x, int center_y, int radius, const char *color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("cirs", "cirs %d,%d,%d,%s", center_x, center_y, radius, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::filled_circle(int center_x, int center_y, int radius, Color color) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("cirs", "cirs %d,%d,%d,%d", center_x, center_y, radius,
|
||||||
|
display::ColorUtil::color_to_565(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_TIME
|
||||||
|
void Nextion::set_nextion_rtc_time(time::ESPTime time) {
|
||||||
|
this->add_no_result_to_queue_with_printf_("rtc0", "rtc0=%u", time.year);
|
||||||
|
this->add_no_result_to_queue_with_printf_("rtc1", "rtc1=%u", time.month);
|
||||||
|
this->add_no_result_to_queue_with_printf_("rtc2", "rtc2=%u", time.day_of_month);
|
||||||
|
this->add_no_result_to_queue_with_printf_("rtc3", "rtc3=%u", time.hour);
|
||||||
|
this->add_no_result_to_queue_with_printf_("rtc4", "rtc4=%u", time.minute);
|
||||||
|
this->add_no_result_to_queue_with_printf_("rtc5", "rtc5=%u", time.second);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
116
esphome/components/nextion/nextion_component.cpp
Normal file
116
esphome/components/nextion/nextion_component.cpp
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#include "nextion_component.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
|
||||||
|
void NextionComponent::set_background_color(Color bco) {
|
||||||
|
if (this->variable_name_ == this->variable_name_to_send_) {
|
||||||
|
return; // This is a variable. no need to set color
|
||||||
|
}
|
||||||
|
this->bco_ = bco;
|
||||||
|
this->bco_needs_update_ = true;
|
||||||
|
this->bco_is_set_ = true;
|
||||||
|
this->update_component_settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionComponent::set_background_pressed_color(Color bco2) {
|
||||||
|
if (this->variable_name_ == this->variable_name_to_send_) {
|
||||||
|
return; // This is a variable. no need to set color
|
||||||
|
}
|
||||||
|
|
||||||
|
this->bco2_ = bco2;
|
||||||
|
this->bco2_needs_update_ = true;
|
||||||
|
this->bco2_is_set_ = true;
|
||||||
|
this->update_component_settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionComponent::set_foreground_color(Color pco) {
|
||||||
|
if (this->variable_name_ == this->variable_name_to_send_) {
|
||||||
|
return; // This is a variable. no need to set color
|
||||||
|
}
|
||||||
|
this->pco_ = pco;
|
||||||
|
this->pco_needs_update_ = true;
|
||||||
|
this->pco_is_set_ = true;
|
||||||
|
this->update_component_settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionComponent::set_foreground_pressed_color(Color pco2) {
|
||||||
|
if (this->variable_name_ == this->variable_name_to_send_) {
|
||||||
|
return; // This is a variable. no need to set color
|
||||||
|
}
|
||||||
|
this->pco2_ = pco2;
|
||||||
|
this->pco2_needs_update_ = true;
|
||||||
|
this->pco2_is_set_ = true;
|
||||||
|
this->update_component_settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionComponent::set_font_id(uint8_t font_id) {
|
||||||
|
if (this->variable_name_ == this->variable_name_to_send_) {
|
||||||
|
return; // This is a variable. no need to set color
|
||||||
|
}
|
||||||
|
this->font_id_ = font_id;
|
||||||
|
this->font_id_needs_update_ = true;
|
||||||
|
this->font_id_is_set_ = true;
|
||||||
|
this->update_component_settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionComponent::set_visible(bool visible) {
|
||||||
|
if (this->variable_name_ == this->variable_name_to_send_) {
|
||||||
|
return; // This is a variable. no need to set color
|
||||||
|
}
|
||||||
|
this->visible_ = visible;
|
||||||
|
this->visible_needs_update_ = true;
|
||||||
|
this->visible_is_set_ = true;
|
||||||
|
this->update_component_settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionComponent::update_component_settings(bool force_update) {
|
||||||
|
if (this->nextion_->is_sleeping() || !this->nextion_->is_setup() || !this->visible_is_set_ ||
|
||||||
|
(!this->visible_needs_update_ && !this->visible_)) {
|
||||||
|
this->needs_to_send_update_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->visible_needs_update_ || (force_update && this->visible_is_set_)) {
|
||||||
|
std::string name_to_send = this->variable_name_;
|
||||||
|
|
||||||
|
size_t pos = name_to_send.find_last_of('.');
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
name_to_send = name_to_send.substr(pos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->visible_needs_update_ = false;
|
||||||
|
|
||||||
|
if (this->visible_) {
|
||||||
|
this->nextion_->show_component(name_to_send.c_str());
|
||||||
|
this->send_state_to_nextion();
|
||||||
|
} else {
|
||||||
|
this->nextion_->hide_component(name_to_send.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->bco_needs_update_ || (force_update && this->bco2_is_set_)) {
|
||||||
|
this->nextion_->set_component_background_color(this->variable_name_.c_str(), this->bco_);
|
||||||
|
this->bco_needs_update_ = false;
|
||||||
|
}
|
||||||
|
if (this->bco2_needs_update_ || (force_update && this->bco2_is_set_)) {
|
||||||
|
this->nextion_->set_component_pressed_background_color(this->variable_name_.c_str(), this->bco2_);
|
||||||
|
this->bco2_needs_update_ = false;
|
||||||
|
}
|
||||||
|
if (this->pco_needs_update_ || (force_update && this->pco_is_set_)) {
|
||||||
|
this->nextion_->set_component_font_color(this->variable_name_.c_str(), this->pco_);
|
||||||
|
this->pco_needs_update_ = false;
|
||||||
|
}
|
||||||
|
if (this->pco2_needs_update_ || (force_update && this->pco2_is_set_)) {
|
||||||
|
this->nextion_->set_component_pressed_font_color(this->variable_name_.c_str(), this->pco2_);
|
||||||
|
this->pco2_needs_update_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->font_id_needs_update_ || (force_update && this->font_id_is_set_)) {
|
||||||
|
this->nextion_->set_component_font(this->variable_name_.c_str(), this->font_id_);
|
||||||
|
this->font_id_needs_update_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
49
esphome/components/nextion/nextion_component.h
Normal file
49
esphome/components/nextion/nextion_component.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
#include "esphome/core/color.h"
|
||||||
|
#include "nextion_base.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
class NextionComponent;
|
||||||
|
|
||||||
|
class NextionComponent : public NextionComponentBase {
|
||||||
|
public:
|
||||||
|
void update_component_settings() override { this->update_component_settings(false); };
|
||||||
|
|
||||||
|
void update_component_settings(bool force_update) override;
|
||||||
|
|
||||||
|
void set_background_color(Color bco);
|
||||||
|
void set_background_pressed_color(Color bco2);
|
||||||
|
void set_foreground_color(Color pco);
|
||||||
|
void set_foreground_pressed_color(Color pco2);
|
||||||
|
void set_font_id(uint8_t font_id);
|
||||||
|
void set_visible(bool visible);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
NextionBase *nextion_;
|
||||||
|
|
||||||
|
bool bco_needs_update_ = false;
|
||||||
|
bool bco_is_set_ = false;
|
||||||
|
Color bco_;
|
||||||
|
bool bco2_needs_update_ = false;
|
||||||
|
bool bco2_is_set_ = false;
|
||||||
|
Color bco2_;
|
||||||
|
bool pco_needs_update_ = false;
|
||||||
|
bool pco_is_set_ = false;
|
||||||
|
Color pco_;
|
||||||
|
bool pco2_needs_update_ = false;
|
||||||
|
bool pco2_is_set_ = false;
|
||||||
|
Color pco2_;
|
||||||
|
uint8_t font_id_ = 0;
|
||||||
|
bool font_id_needs_update_ = false;
|
||||||
|
bool font_id_is_set_ = false;
|
||||||
|
|
||||||
|
bool visible_ = true;
|
||||||
|
bool visible_needs_update_ = false;
|
||||||
|
bool visible_is_set_ = false;
|
||||||
|
|
||||||
|
// void send_state_to_nextion() = 0;
|
||||||
|
};
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
95
esphome/components/nextion/nextion_component_base.h
Normal file
95
esphome/components/nextion/nextion_component_base.h
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
#pragma once
|
||||||
|
#include <utility>
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
|
||||||
|
enum NextionQueueType {
|
||||||
|
NO_RESULT = 0,
|
||||||
|
SENSOR = 1,
|
||||||
|
BINARY_SENSOR = 2,
|
||||||
|
SWITCH = 3,
|
||||||
|
TEXT_SENSOR = 4,
|
||||||
|
WAVEFORM_SENSOR = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *const NEXTION_QUEUE_TYPE_STRINGS[] = {"NO_RESULT", "SENSOR", "BINARY_SENSOR",
|
||||||
|
"SWITCH", "TEXT_SENSOR", "WAVEFORM_SENSOR"};
|
||||||
|
|
||||||
|
class NextionComponentBase;
|
||||||
|
|
||||||
|
class NextionQueue {
|
||||||
|
public:
|
||||||
|
virtual ~NextionQueue() = default;
|
||||||
|
NextionComponentBase *component;
|
||||||
|
uint32_t queue_time = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NextionComponentBase {
|
||||||
|
public:
|
||||||
|
virtual ~NextionComponentBase() = default;
|
||||||
|
|
||||||
|
void set_variable_name(const std::string &variable_name, const std::string &variable_name_to_send = "") {
|
||||||
|
variable_name_ = variable_name;
|
||||||
|
if (variable_name_to_send.empty()) {
|
||||||
|
variable_name_to_send_ = variable_name;
|
||||||
|
} else {
|
||||||
|
variable_name_to_send_ = variable_name_to_send;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void update_component_settings(){};
|
||||||
|
virtual void update_component_settings(bool force_update){};
|
||||||
|
|
||||||
|
virtual void update_component(){};
|
||||||
|
virtual void process_sensor(const std::string &variable_name, int state){};
|
||||||
|
virtual void process_touch(uint8_t page_id, uint8_t component_id, bool on){};
|
||||||
|
virtual void process_text(const std::string &variable_name, const std::string &text_value){};
|
||||||
|
virtual void process_bool(const std::string &variable_name, bool on){};
|
||||||
|
|
||||||
|
virtual void set_state(float state){};
|
||||||
|
virtual void set_state(float state, bool publish){};
|
||||||
|
virtual void set_state(float state, bool publish, bool send_to_nextion){};
|
||||||
|
|
||||||
|
virtual void set_state(bool state){};
|
||||||
|
virtual void set_state(bool state, bool publish){};
|
||||||
|
virtual void set_state(bool state, bool publish, bool send_to_nextion){};
|
||||||
|
|
||||||
|
virtual void set_state(const std::string &state) {}
|
||||||
|
virtual void set_state(const std::string &state, bool publish) {}
|
||||||
|
virtual void set_state(const std::string &state, bool publish, bool send_to_nextion){};
|
||||||
|
|
||||||
|
uint8_t get_component_id() { return this->component_id_; }
|
||||||
|
void set_component_id(uint8_t component_id) { component_id_ = component_id; }
|
||||||
|
|
||||||
|
uint8_t get_wave_channel_id() { return this->wave_chan_id_; }
|
||||||
|
void set_wave_channel_id(uint8_t wave_chan_id) { this->wave_chan_id_ = wave_chan_id; }
|
||||||
|
|
||||||
|
std::vector<uint8_t> get_wave_buffer() { return this->wave_buffer_; }
|
||||||
|
size_t get_wave_buffer_size() { return this->wave_buffer_.size(); }
|
||||||
|
|
||||||
|
std::string get_variable_name() { return this->variable_name_; }
|
||||||
|
std::string get_variable_name_to_send() { return this->variable_name_to_send_; }
|
||||||
|
virtual NextionQueueType get_queue_type() { return NextionQueueType::NO_RESULT; }
|
||||||
|
virtual std::string get_queue_type_string() { return NEXTION_QUEUE_TYPE_STRINGS[this->get_queue_type()]; }
|
||||||
|
virtual void set_state_from_int(int state_value, bool publish, bool send_to_nextion){};
|
||||||
|
virtual void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion){};
|
||||||
|
virtual void send_state_to_nextion(){};
|
||||||
|
bool get_needs_to_send_update() { return this->needs_to_send_update_; }
|
||||||
|
uint8_t get_wave_chan_id() { return this->wave_chan_id_; }
|
||||||
|
void set_wave_max_length(int wave_max_length) { this->wave_max_length_ = wave_max_length; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string variable_name_;
|
||||||
|
std::string variable_name_to_send_;
|
||||||
|
|
||||||
|
uint8_t component_id_ = 0;
|
||||||
|
uint8_t wave_chan_id_ = UINT8_MAX;
|
||||||
|
std::vector<uint8_t> wave_buffer_;
|
||||||
|
int wave_max_length_ = 255;
|
||||||
|
|
||||||
|
bool needs_to_send_update_;
|
||||||
|
};
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
343
esphome/components/nextion/nextion_upload.cpp
Normal file
343
esphome/components/nextion/nextion_upload.cpp
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
|
||||||
|
#include "nextion.h"
|
||||||
|
#include "esphome/core/application.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
static const char *const TAG = "nextion_upload";
|
||||||
|
|
||||||
|
#if defined(USE_TFT_UPLOAD) && (defined(USE_ETHERNET) || defined(USE_WIFI))
|
||||||
|
|
||||||
|
// Followed guide
|
||||||
|
// https://unofficialnextion.com/t/nextion-upload-protocol-v1-2-the-fast-one/1044/2
|
||||||
|
|
||||||
|
int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) {
|
||||||
|
int range_end = 0;
|
||||||
|
|
||||||
|
if (range_start == 0 && this->transfer_buffer_size_ > 16384) { // Start small at the first run in case of a big skip
|
||||||
|
range_end = 16384 - 1;
|
||||||
|
} else {
|
||||||
|
range_end = range_start + this->transfer_buffer_size_ - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (range_end > this->tft_size_)
|
||||||
|
range_end = this->tft_size_;
|
||||||
|
|
||||||
|
bool begin_status = false;
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
begin_status = http->begin(this->tft_url_.c_str());
|
||||||
|
#endif
|
||||||
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
#ifndef CLANG_TIDY
|
||||||
|
http->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||||
|
http->setRedirectLimit(3);
|
||||||
|
begin_status = http->begin(*this->get_wifi_client_(), this->tft_url_.c_str());
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char range_header[64];
|
||||||
|
sprintf(range_header, "bytes=%d-%d", range_start, range_end);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Requesting range: %s", range_header);
|
||||||
|
|
||||||
|
int tries = 1;
|
||||||
|
int code = 0;
|
||||||
|
while (tries <= 5) {
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
begin_status = http->begin(this->tft_url_.c_str());
|
||||||
|
#endif
|
||||||
|
#ifndef CLANG_TIDY
|
||||||
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
begin_status = http->begin(*this->get_wifi_client_(), this->tft_url_.c_str());
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
++tries;
|
||||||
|
if (!begin_status) {
|
||||||
|
ESP_LOGD(TAG, "upload_by_chunks_: connection failed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
http->addHeader("Range", range_header);
|
||||||
|
|
||||||
|
code = http->GET();
|
||||||
|
if (code == 200 || code == 206) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s, retries(%d/5)", this->tft_url_.c_str(),
|
||||||
|
HTTPClient::errorToString(code).c_str(), tries);
|
||||||
|
http->end();
|
||||||
|
App.feed_wdt();
|
||||||
|
delay(500); // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tries > 5) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string recv_string;
|
||||||
|
size_t size = 0;
|
||||||
|
int sent = 0;
|
||||||
|
int range = range_end - range_start;
|
||||||
|
|
||||||
|
while (sent < range) {
|
||||||
|
size = http->getStreamPtr()->available();
|
||||||
|
if (!size) {
|
||||||
|
App.feed_wdt();
|
||||||
|
delay(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int c = http->getStreamPtr()->readBytes(
|
||||||
|
&this->transfer_buffer_[sent], ((size > this->transfer_buffer_size_) ? this->transfer_buffer_size_ : size));
|
||||||
|
sent += c;
|
||||||
|
}
|
||||||
|
http->end();
|
||||||
|
ESP_LOGN(TAG, "this->content_length_ %d sent %d", this->content_length_, sent);
|
||||||
|
for (uint32_t i = 0; i < range; i += 4096) {
|
||||||
|
this->write_array(&this->transfer_buffer_[i], 4096);
|
||||||
|
this->content_length_ -= 4096;
|
||||||
|
ESP_LOGN(TAG, "this->content_length_ %d range %d range_end %d range_start %d", this->content_length_, range,
|
||||||
|
range_end, range_start);
|
||||||
|
|
||||||
|
if (!this->upload_first_chunk_sent_) {
|
||||||
|
this->upload_first_chunk_sent_ = true;
|
||||||
|
delay(500); // NOLINT
|
||||||
|
App.feed_wdt();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->recv_ret_string_(recv_string, 2048, true);
|
||||||
|
if (recv_string[0] == 0x08) {
|
||||||
|
uint32_t result = 0;
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
result += static_cast<uint8_t>(recv_string[i + 1]) << (8 * i);
|
||||||
|
}
|
||||||
|
if (result > 0) {
|
||||||
|
ESP_LOGD(TAG, "Nextion reported new range %d", result);
|
||||||
|
this->content_length_ = this->tft_size_ - result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recv_string.clear();
|
||||||
|
}
|
||||||
|
return range_end + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::upload_tft() {
|
||||||
|
if (this->is_updating_) {
|
||||||
|
ESP_LOGD(TAG, "Currently updating");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!network_is_connected()) {
|
||||||
|
ESP_LOGD(TAG, "network is not connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->is_updating_ = true;
|
||||||
|
|
||||||
|
HTTPClient http;
|
||||||
|
http.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along
|
||||||
|
bool begin_status = false;
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
begin_status = http.begin(this->tft_url_.c_str());
|
||||||
|
#endif
|
||||||
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
#ifndef CLANG_TIDY
|
||||||
|
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||||
|
http.setRedirectLimit(3);
|
||||||
|
begin_status = http.begin(*this->get_wifi_client_(), this->tft_url_.c_str());
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!begin_status) {
|
||||||
|
this->is_updating_ = false;
|
||||||
|
ESP_LOGD(TAG, "connection failed");
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
if (psramFound())
|
||||||
|
free(this->transfer_buffer_);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
delete this->transfer_buffer_;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
ESP_LOGD(TAG, "Connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
http.addHeader("Range", "bytes=0-255");
|
||||||
|
const char *header_names[] = {"Content-Range"};
|
||||||
|
http.collectHeaders(header_names, 1);
|
||||||
|
ESP_LOGD(TAG, "Requesting URL: %s", this->tft_url_.c_str());
|
||||||
|
|
||||||
|
http.setReuse(true);
|
||||||
|
// try up to 5 times. DNS sometimes needs a second try or so
|
||||||
|
int tries = 1;
|
||||||
|
int code = http.GET();
|
||||||
|
delay(100); // NOLINT
|
||||||
|
|
||||||
|
App.feed_wdt();
|
||||||
|
while (code != 200 && code != 206 && tries <= 5) {
|
||||||
|
ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s, retrying (%d/5)", this->tft_url_.c_str(),
|
||||||
|
HTTPClient::errorToString(code).c_str(), tries);
|
||||||
|
|
||||||
|
delay(250); // NOLINT
|
||||||
|
App.feed_wdt();
|
||||||
|
code = http.GET();
|
||||||
|
++tries;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((code != 200 && code != 206) || tries > 5) {
|
||||||
|
this->upload_end_();
|
||||||
|
}
|
||||||
|
|
||||||
|
String content_range_string = http.header("Content-Range");
|
||||||
|
content_range_string.remove(0, 12);
|
||||||
|
this->content_length_ = content_range_string.toInt();
|
||||||
|
this->tft_size_ = content_length_;
|
||||||
|
http.end();
|
||||||
|
|
||||||
|
if (this->content_length_ < 4096) {
|
||||||
|
ESP_LOGE(TAG, "Failed to get file size");
|
||||||
|
this->upload_end_();
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Updating Nextion %s...", this->device_model_.c_str());
|
||||||
|
// The Nextion will ignore the update command if it is sleeping
|
||||||
|
|
||||||
|
this->send_command_("sleep=0");
|
||||||
|
this->set_backlight_brightness(1.0);
|
||||||
|
delay(250); // NOLINT
|
||||||
|
|
||||||
|
App.feed_wdt();
|
||||||
|
|
||||||
|
char command[128];
|
||||||
|
// Tells the Nextion the content length of the tft file and baud rate it will be sent at
|
||||||
|
// Once the Nextion accepts the command it will wait until the file is successfully uploaded
|
||||||
|
// If it fails for any reason a power cycle of the display will be needed
|
||||||
|
sprintf(command, "whmi-wris %d,%d,1", this->content_length_, this->parent_->get_baud_rate());
|
||||||
|
|
||||||
|
// Clear serial receive buffer
|
||||||
|
uint8_t d;
|
||||||
|
while (this->available()) {
|
||||||
|
this->read_byte(&d);
|
||||||
|
};
|
||||||
|
|
||||||
|
this->send_command_(command);
|
||||||
|
|
||||||
|
App.feed_wdt();
|
||||||
|
|
||||||
|
std::string response;
|
||||||
|
ESP_LOGD(TAG, "Waiting for upgrade response");
|
||||||
|
this->recv_ret_string_(response, 2000, true); // This can take some time to return
|
||||||
|
|
||||||
|
// The Nextion display will, if it's ready to accept data, send a 0x05 byte.
|
||||||
|
ESP_LOGD(TAG, "Upgrade response is %s %zu", response.c_str(), response.length());
|
||||||
|
|
||||||
|
for (int i = 0; i < response.length(); i++) {
|
||||||
|
ESP_LOGD(TAG, "Available %d : 0x%02X", i, response[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.find(0x05) != std::string::npos) {
|
||||||
|
ESP_LOGD(TAG, "preparation for tft update done");
|
||||||
|
} else {
|
||||||
|
ESP_LOGD(TAG, "preparation for tft update failed %d \"%s\"", response[0], response.c_str());
|
||||||
|
this->upload_end_();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nextion wants 4096 bytes at a time. Make chunk_size a multiple of 4096
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
uint32_t chunk_size = 8192;
|
||||||
|
if (psramFound()) {
|
||||||
|
chunk_size = this->content_length_;
|
||||||
|
} else {
|
||||||
|
if (ESP.getFreeHeap() > 40960) { // 32K to keep on hand
|
||||||
|
int chunk = int((ESP.getFreeHeap() - 32768) / 4096);
|
||||||
|
chunk_size = chunk * 4096;
|
||||||
|
chunk_size = chunk_size > 65536 ? 65536 : chunk_size;
|
||||||
|
} else if (ESP.getFreeHeap() < 10240) {
|
||||||
|
chunk_size = 4096;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
uint32_t chunk_size = ESP.getFreeHeap() < 10240 ? 4096 : 8192;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (this->transfer_buffer_ == nullptr) {
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
if (psramFound()) {
|
||||||
|
ESP_LOGD(TAG, "Allocating PSRAM buffer size %d, Free PSRAM size is %u", chunk_size, ESP.getFreePsram());
|
||||||
|
this->transfer_buffer_ = (uint8_t *) ps_malloc(chunk_size);
|
||||||
|
if (this->transfer_buffer_ == nullptr) {
|
||||||
|
ESP_LOGE(TAG, "Could not allocate buffer size %d!", chunk_size);
|
||||||
|
this->upload_end_();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
ESP_LOGD(TAG, "Allocating buffer size %d, Heap size is %u", chunk_size, ESP.getFreeHeap());
|
||||||
|
this->transfer_buffer_ = new uint8_t[chunk_size];
|
||||||
|
if (!this->transfer_buffer_) { // Try a smaller size
|
||||||
|
ESP_LOGD(TAG, "Could not allocate buffer size: %d trying 4096 instead", chunk_size);
|
||||||
|
chunk_size = 4096;
|
||||||
|
ESP_LOGD(TAG, "Allocating %d buffer", chunk_size);
|
||||||
|
this->transfer_buffer_ = new uint8_t[chunk_size];
|
||||||
|
|
||||||
|
if (!this->transfer_buffer_)
|
||||||
|
this->upload_end_();
|
||||||
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
this->transfer_buffer_size_ = chunk_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Updating tft from \"%s\" with a file size of %d using %zu chunksize, Heap Size %d",
|
||||||
|
this->tft_url_.c_str(), this->content_length_, this->transfer_buffer_size_, ESP.getFreeHeap());
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
while (this->content_length_ > 0) {
|
||||||
|
result = this->upload_by_chunks_(&http, result);
|
||||||
|
if (result < 0) {
|
||||||
|
ESP_LOGD(TAG, "Error updating Nextion!");
|
||||||
|
this->upload_end_();
|
||||||
|
}
|
||||||
|
App.feed_wdt();
|
||||||
|
ESP_LOGD(TAG, "Heap Size %d, Bytes left %d", ESP.getFreeHeap(), this->content_length_);
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, "Succesfully updated Nextion!");
|
||||||
|
|
||||||
|
this->upload_end_();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nextion::upload_end_() {
|
||||||
|
ESP_LOGD(TAG, "Restarting Nextion");
|
||||||
|
this->soft_reset();
|
||||||
|
delay(1500); // NOLINT
|
||||||
|
ESP_LOGD(TAG, "Restarting esphome");
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
WiFiClient *Nextion::get_wifi_client_() {
|
||||||
|
if (this->tft_url_.compare(0, 6, "https:") == 0) {
|
||||||
|
if (this->wifi_client_secure_ == nullptr) {
|
||||||
|
this->wifi_client_secure_ = new BearSSL::WiFiClientSecure();
|
||||||
|
this->wifi_client_secure_->setInsecure();
|
||||||
|
this->wifi_client_secure_->setBufferSizes(512, 512);
|
||||||
|
}
|
||||||
|
return this->wifi_client_secure_;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->wifi_client_ == nullptr) {
|
||||||
|
this->wifi_client_ = new WiFiClient();
|
||||||
|
}
|
||||||
|
return this->wifi_client_;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
void Nextion::upload_tft() { ESP_LOGW(TAG, "tft_url, WIFI or Ethernet components are needed. Cannot upload."); }
|
||||||
|
#endif
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
99
esphome/components/nextion/sensor/__init__.py
Normal file
99
esphome/components/nextion/sensor/__init__.py
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import sensor
|
||||||
|
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_ID,
|
||||||
|
UNIT_EMPTY,
|
||||||
|
ICON_EMPTY,
|
||||||
|
CONF_COMPONENT_ID,
|
||||||
|
DEVICE_CLASS_EMPTY,
|
||||||
|
)
|
||||||
|
from .. import nextion_ns, CONF_NEXTION_ID
|
||||||
|
|
||||||
|
from ..base_component import (
|
||||||
|
setup_component_core_,
|
||||||
|
CONFIG_SENSOR_COMPONENT_SCHEMA,
|
||||||
|
CONF_VARIABLE_NAME,
|
||||||
|
CONF_COMPONENT_NAME,
|
||||||
|
CONF_PRECISION,
|
||||||
|
CONF_WAVE_CHANNEL_ID,
|
||||||
|
CONF_WAVE_MAX_VALUE,
|
||||||
|
CONF_WAVEFORM_SEND_LAST_VALUE,
|
||||||
|
CONF_WAVE_MAX_LENGTH,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
CODEOWNERS = ["@senexcrenshaw"]
|
||||||
|
|
||||||
|
NextionSensor = nextion_ns.class_("NextionSensor", sensor.Sensor, cg.PollingComponent)
|
||||||
|
|
||||||
|
|
||||||
|
def CheckWaveID(value):
|
||||||
|
value = cv.int_(value)
|
||||||
|
if value < 0 or value > 3:
|
||||||
|
raise cv.Invalid(f"Valid range for {CONF_WAVE_CHANNEL_ID} is 0-3")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def _validate(config):
|
||||||
|
if CONF_WAVE_CHANNEL_ID in config and CONF_COMPONENT_ID not in config:
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"{CONF_COMPONENT_ID} is required when {CONF_WAVE_CHANNEL_ID} is set"
|
||||||
|
)
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 2, DEVICE_CLASS_EMPTY)
|
||||||
|
.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(NextionSensor),
|
||||||
|
cv.Optional(CONF_PRECISION, default=0): cv.int_range(min=0, max=8),
|
||||||
|
cv.Optional(CONF_WAVE_CHANNEL_ID): CheckWaveID,
|
||||||
|
cv.Optional(CONF_COMPONENT_ID): cv.uint8_t,
|
||||||
|
cv.Optional(CONF_WAVE_MAX_LENGTH, default=255): cv.int_range(
|
||||||
|
min=1, max=1024
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_WAVE_MAX_VALUE, default=100): cv.int_range(
|
||||||
|
min=1, max=1024
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_WAVEFORM_SEND_LAST_VALUE, default=True): cv.boolean,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(CONFIG_SENSOR_COMPONENT_SCHEMA)
|
||||||
|
.extend(cv.polling_component_schema("never")),
|
||||||
|
cv.has_exactly_one_key(CONF_COMPONENT_ID, CONF_COMPONENT_NAME, CONF_VARIABLE_NAME),
|
||||||
|
_validate,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
|
||||||
|
hub = await cg.get_variable(config[CONF_NEXTION_ID])
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID], hub)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await sensor.register_sensor(var, config)
|
||||||
|
|
||||||
|
cg.add(hub.register_sensor_component(var))
|
||||||
|
|
||||||
|
await setup_component_core_(var, config, ".val")
|
||||||
|
|
||||||
|
if CONF_PRECISION in config:
|
||||||
|
cg.add(var.set_precision(config[CONF_PRECISION]))
|
||||||
|
|
||||||
|
if CONF_COMPONENT_ID in config:
|
||||||
|
cg.add(var.set_component_id(config[CONF_COMPONENT_ID]))
|
||||||
|
|
||||||
|
if CONF_WAVE_CHANNEL_ID in config:
|
||||||
|
cg.add(var.set_wave_channel_id(config[CONF_WAVE_CHANNEL_ID]))
|
||||||
|
|
||||||
|
if CONF_WAVEFORM_SEND_LAST_VALUE in config:
|
||||||
|
cg.add(var.set_waveform_send_last_value(config[CONF_WAVEFORM_SEND_LAST_VALUE]))
|
||||||
|
|
||||||
|
if CONF_WAVE_MAX_VALUE in config:
|
||||||
|
cg.add(var.set_wave_max_value(config[CONF_WAVE_MAX_VALUE]))
|
||||||
|
|
||||||
|
if CONF_WAVE_MAX_LENGTH in config:
|
||||||
|
cg.add(var.set_wave_max_length(config[CONF_WAVE_MAX_LENGTH]))
|
110
esphome/components/nextion/sensor/nextion_sensor.cpp
Normal file
110
esphome/components/nextion/sensor/nextion_sensor.cpp
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
#include "nextion_sensor.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
|
||||||
|
static const char *const TAG = "nextion_sensor";
|
||||||
|
|
||||||
|
void NextionSensor::process_sensor(const std::string &variable_name, int state) {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->wave_chan_id_ == UINT8_MAX && this->variable_name_ == variable_name) {
|
||||||
|
this->publish_state(state);
|
||||||
|
ESP_LOGD(TAG, "Processed sensor \"%s\" state %d", variable_name.c_str(), state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionSensor::add_to_wave_buffer(float state) {
|
||||||
|
this->needs_to_send_update_ = true;
|
||||||
|
|
||||||
|
int wave_state = (int) ((state / (float) this->wave_maxvalue_) * 100);
|
||||||
|
|
||||||
|
wave_buffer_.push_back(wave_state);
|
||||||
|
|
||||||
|
if (this->wave_buffer_.size() > this->wave_max_length_) {
|
||||||
|
this->wave_buffer_.erase(this->wave_buffer_.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionSensor::update() {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->wave_chan_id_ == UINT8_MAX) {
|
||||||
|
this->nextion_->add_to_get_queue(this);
|
||||||
|
} else {
|
||||||
|
if (this->send_last_value_) {
|
||||||
|
this->add_to_wave_buffer(this->last_value_);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->wave_update_();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionSensor::set_state(float state, bool publish, bool send_to_nextion) {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isnan(state))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (this->wave_chan_id_ == UINT8_MAX) {
|
||||||
|
if (send_to_nextion) {
|
||||||
|
if (this->nextion_->is_sleeping() || !this->visible_) {
|
||||||
|
this->needs_to_send_update_ = true;
|
||||||
|
} else {
|
||||||
|
this->needs_to_send_update_ = false;
|
||||||
|
|
||||||
|
if (this->precision_ > 0) {
|
||||||
|
double to_multiply = pow(10, this->precision_);
|
||||||
|
int state_value = (int) (state * to_multiply);
|
||||||
|
|
||||||
|
this->nextion_->add_no_result_to_queue_with_set(this, (int) state_value);
|
||||||
|
} else {
|
||||||
|
this->nextion_->add_no_result_to_queue_with_set(this, (int) state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this->send_last_value_) {
|
||||||
|
this->last_value_ = state; // Update will handle setting the buffer
|
||||||
|
} else {
|
||||||
|
this->add_to_wave_buffer(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->wave_chan_id_ == UINT8_MAX) {
|
||||||
|
if (publish) {
|
||||||
|
this->publish_state(state);
|
||||||
|
} else {
|
||||||
|
this->raw_state = state;
|
||||||
|
this->state = state;
|
||||||
|
this->has_state_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->update_component_settings();
|
||||||
|
|
||||||
|
ESP_LOGN(TAG, "Wrote state for sensor \"%s\" state %lf", this->variable_name_.c_str(), state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionSensor::wave_update_() {
|
||||||
|
if (this->nextion_->is_sleeping() || this->wave_buffer_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NEXTION_PROTOCOL_LOG
|
||||||
|
size_t buffer_to_send =
|
||||||
|
this->wave_buffer_.size() < 255 ? this->wave_buffer_.size() : 255; // ADDT command can only send 255
|
||||||
|
|
||||||
|
ESP_LOGN(TAG, "wave_update send %zu of %zu value(s) to wave nextion component id %d and wave channel id %d",
|
||||||
|
buffer_to_send, this->wave_buffer_.size(), this->component_id_, this->wave_chan_id_);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
this->nextion_->add_addt_command_to_queue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
49
esphome/components/nextion/sensor/nextion_sensor.h
Normal file
49
esphome/components/nextion/sensor/nextion_sensor.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "../nextion_component.h"
|
||||||
|
#include "../nextion_base.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
class NextionSensor;
|
||||||
|
|
||||||
|
class NextionSensor : public NextionComponent, public sensor::Sensor, public PollingComponent {
|
||||||
|
public:
|
||||||
|
NextionSensor(NextionBase *nextion) { this->nextion_ = nextion; }
|
||||||
|
void send_state_to_nextion() override { this->set_state(this->state, false, true); };
|
||||||
|
|
||||||
|
void update_component() override { this->update(); }
|
||||||
|
void update() override;
|
||||||
|
void add_to_wave_buffer(float state);
|
||||||
|
void set_precision(uint8_t precision) { this->precision_ = precision; }
|
||||||
|
void set_component_id(uint8_t component_id) { component_id_ = component_id; }
|
||||||
|
void set_wave_channel_id(uint8_t wave_chan_id) { this->wave_chan_id_ = wave_chan_id; }
|
||||||
|
void set_wave_max_value(uint32_t wave_maxvalue) { this->wave_maxvalue_ = wave_maxvalue; }
|
||||||
|
void process_sensor(const std::string &variable_name, int state) override;
|
||||||
|
|
||||||
|
void set_state(float state) override { this->set_state(state, true, true); }
|
||||||
|
void set_state(float state, bool publish) override { this->set_state(state, publish, true); }
|
||||||
|
void set_state(float state, bool publish, bool send_to_nextion) override;
|
||||||
|
|
||||||
|
void set_waveform_send_last_value(bool send_last_value) { this->send_last_value_ = send_last_value; }
|
||||||
|
uint8_t get_wave_chan_id() { return this->wave_chan_id_; }
|
||||||
|
void set_wave_max_length(int wave_max_length) { this->wave_max_length_ = wave_max_length; }
|
||||||
|
NextionQueueType get_queue_type() override {
|
||||||
|
return this->wave_chan_id_ == UINT8_MAX ? NextionQueueType::SENSOR : NextionQueueType::WAVEFORM_SENSOR;
|
||||||
|
}
|
||||||
|
void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion) override {}
|
||||||
|
void set_state_from_int(int state_value, bool publish, bool send_to_nextion) override {
|
||||||
|
this->set_state(state_value, publish, send_to_nextion);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t precision_ = 0;
|
||||||
|
uint32_t wave_maxvalue_ = 255;
|
||||||
|
|
||||||
|
float last_value_ = 0;
|
||||||
|
bool send_last_value_ = true;
|
||||||
|
void wave_update_();
|
||||||
|
};
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
39
esphome/components/nextion/switch/__init__.py
Normal file
39
esphome/components/nextion/switch/__init__.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import switch
|
||||||
|
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
from .. import nextion_ns, CONF_NEXTION_ID
|
||||||
|
|
||||||
|
from ..base_component import (
|
||||||
|
setup_component_core_,
|
||||||
|
CONF_COMPONENT_NAME,
|
||||||
|
CONF_VARIABLE_NAME,
|
||||||
|
CONFIG_SWITCH_COMPONENT_SCHEMA,
|
||||||
|
)
|
||||||
|
|
||||||
|
CODEOWNERS = ["@senexcrenshaw"]
|
||||||
|
|
||||||
|
NextionSwitch = nextion_ns.class_("NextionSwitch", switch.Switch, cg.PollingComponent)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
switch.SWITCH_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(NextionSwitch),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(CONFIG_SWITCH_COMPONENT_SCHEMA)
|
||||||
|
.extend(cv.polling_component_schema("never")),
|
||||||
|
cv.has_exactly_one_key(CONF_COMPONENT_NAME, CONF_VARIABLE_NAME),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
hub = await cg.get_variable(config[CONF_NEXTION_ID])
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID], hub)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await switch.register_switch(var, config)
|
||||||
|
|
||||||
|
cg.add(hub.register_switch_component(var))
|
||||||
|
|
||||||
|
await setup_component_core_(var, config, ".val")
|
52
esphome/components/nextion/switch/nextion_switch.cpp
Normal file
52
esphome/components/nextion/switch/nextion_switch.cpp
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#include "nextion_switch.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
|
||||||
|
static const char *const TAG = "nextion_switch";
|
||||||
|
|
||||||
|
void NextionSwitch::process_bool(const std::string &variable_name, bool on) {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
if (this->variable_name_ == variable_name) {
|
||||||
|
this->publish_state(on);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Processed switch \"%s\" state %s", variable_name.c_str(), state ? "ON" : "OFF");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionSwitch::update() {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
this->nextion_->add_to_get_queue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionSwitch::set_state(bool state, bool publish, bool send_to_nextion) {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (send_to_nextion) {
|
||||||
|
if (this->nextion_->is_sleeping() || !this->visible_) {
|
||||||
|
this->needs_to_send_update_ = true;
|
||||||
|
} else {
|
||||||
|
this->needs_to_send_update_ = false;
|
||||||
|
this->nextion_->add_no_result_to_queue_with_set(this, (int) state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (publish) {
|
||||||
|
this->publish_state(state);
|
||||||
|
} else {
|
||||||
|
this->state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->update_component_settings();
|
||||||
|
|
||||||
|
ESP_LOGN(TAG, "Updated switch \"%s\" state %s", this->variable_name_.c_str(), ONOFF(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionSwitch::write_state(bool state) { this->set_state(state); }
|
||||||
|
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
34
esphome/components/nextion/switch/nextion_switch.h
Normal file
34
esphome/components/nextion/switch/nextion_switch.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/switch/switch.h"
|
||||||
|
#include "../nextion_component.h"
|
||||||
|
#include "../nextion_base.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
class NextionSwitch;
|
||||||
|
|
||||||
|
class NextionSwitch : public NextionComponent, public switch_::Switch, public PollingComponent {
|
||||||
|
public:
|
||||||
|
NextionSwitch(NextionBase *nextion) { this->nextion_ = nextion; }
|
||||||
|
|
||||||
|
void update() override;
|
||||||
|
void update_component() override { this->update(); }
|
||||||
|
void process_bool(const std::string &variable_name, bool on) override;
|
||||||
|
|
||||||
|
void set_state(bool state) override { this->set_state(state, true, true); }
|
||||||
|
void set_state(bool state, bool publish) override { this->set_state(state, publish, true); }
|
||||||
|
void set_state(bool state, bool publish, bool send_to_nextion) override;
|
||||||
|
|
||||||
|
void send_state_to_nextion() override { this->set_state(this->state, false, true); };
|
||||||
|
NextionQueueType get_queue_type() override { return NextionQueueType::SWITCH; }
|
||||||
|
void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion) override {}
|
||||||
|
void set_state_from_int(int state_value, bool publish, bool send_to_nextion) override {
|
||||||
|
this->set_state(state_value != 0, publish, send_to_nextion);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void write_state(bool state) override;
|
||||||
|
};
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
38
esphome/components/nextion/text_sensor/__init__.py
Normal file
38
esphome/components/nextion/text_sensor/__init__.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
from esphome.components import text_sensor
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
import esphome.codegen as cg
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
|
from .. import nextion_ns, CONF_NEXTION_ID
|
||||||
|
|
||||||
|
from ..base_component import (
|
||||||
|
setup_component_core_,
|
||||||
|
CONFIG_TEXT_COMPONENT_SCHEMA,
|
||||||
|
)
|
||||||
|
|
||||||
|
CODEOWNERS = ["@senexcrenshaw"]
|
||||||
|
|
||||||
|
NextionTextSensor = nextion_ns.class_(
|
||||||
|
"NextionTextSensor", text_sensor.TextSensor, cg.PollingComponent
|
||||||
|
)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
text_sensor.TEXT_SENSOR_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(NextionTextSensor),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(CONFIG_TEXT_COMPONENT_SCHEMA)
|
||||||
|
.extend(cv.polling_component_schema("never"))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
hub = await cg.get_variable(config[CONF_NEXTION_ID])
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID], hub)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await text_sensor.register_text_sensor(var, config)
|
||||||
|
|
||||||
|
cg.add(hub.register_textsensor_component(var))
|
||||||
|
|
||||||
|
await setup_component_core_(var, config, ".txt")
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include "nextion_textsensor.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
static const char *const TAG = "nextion_textsensor";
|
||||||
|
|
||||||
|
void NextionTextSensor::process_text(const std::string &variable_name, const std::string &text_value) {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
if (this->variable_name_ == variable_name) {
|
||||||
|
this->publish_state(text_value);
|
||||||
|
ESP_LOGD(TAG, "Processed text_sensor \"%s\" state \"%s\"", variable_name.c_str(), text_value.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionTextSensor::update() {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
this->nextion_->add_to_get_queue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextionTextSensor::set_state(const std::string &state, bool publish, bool send_to_nextion) {
|
||||||
|
if (!this->nextion_->is_setup())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (send_to_nextion) {
|
||||||
|
if (this->nextion_->is_sleeping() || !this->visible_) {
|
||||||
|
this->needs_to_send_update_ = true;
|
||||||
|
} else {
|
||||||
|
this->nextion_->add_no_result_to_queue_with_set(this, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publish) {
|
||||||
|
this->publish_state(state);
|
||||||
|
} else {
|
||||||
|
this->state = state;
|
||||||
|
this->has_state_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->update_component_settings();
|
||||||
|
|
||||||
|
ESP_LOGN(TAG, "Wrote state for text_sensor \"%s\" state \"%s\"", this->variable_name_.c_str(), state.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
32
esphome/components/nextion/text_sensor/nextion_textsensor.h
Normal file
32
esphome/components/nextion/text_sensor/nextion_textsensor.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#pragma once
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/text_sensor/text_sensor.h"
|
||||||
|
#include "../nextion_component.h"
|
||||||
|
#include "../nextion_base.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nextion {
|
||||||
|
class NextionTextSensor;
|
||||||
|
|
||||||
|
class NextionTextSensor : public NextionComponent, public text_sensor::TextSensor, public PollingComponent {
|
||||||
|
public:
|
||||||
|
NextionTextSensor(NextionBase *nextion) { this->nextion_ = nextion; }
|
||||||
|
void update() override;
|
||||||
|
void update_component() override { this->update(); }
|
||||||
|
void on_state_changed(const std::string &state);
|
||||||
|
|
||||||
|
void process_text(const std::string &variable_name, const std::string &text_value) override;
|
||||||
|
|
||||||
|
void set_state(const std::string &state, bool publish) override { this->set_state(state, publish, true); }
|
||||||
|
void set_state(const std::string &state) override { this->set_state(state, true, true); }
|
||||||
|
void set_state(const std::string &state, bool publish, bool send_to_nextion) override;
|
||||||
|
|
||||||
|
void send_state_to_nextion() override { this->set_state(this->state, false, true); };
|
||||||
|
NextionQueueType get_queue_type() override { return NextionQueueType::TEXT_SENSOR; }
|
||||||
|
void set_state_from_int(int state_value, bool publish, bool send_to_nextion) override {}
|
||||||
|
void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion) override {
|
||||||
|
this->set_state(state_value, publish, send_to_nextion);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace nextion
|
||||||
|
} // namespace esphome
|
|
@ -56,6 +56,7 @@ class ESP8266SoftwareSerial {
|
||||||
class UARTComponent : public Component, public Stream {
|
class UARTComponent : public Component, public Stream {
|
||||||
public:
|
public:
|
||||||
void set_baud_rate(uint32_t baud_rate) { baud_rate_ = baud_rate; }
|
void set_baud_rate(uint32_t baud_rate) { baud_rate_ = baud_rate; }
|
||||||
|
uint32_t get_baud_rate() const { return baud_rate_; }
|
||||||
|
|
||||||
uint32_t get_config();
|
uint32_t get_config();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from helpers import git_ls_files, filter_changed
|
||||||
import codecs
|
import codecs
|
||||||
import collections
|
import collections
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
@ -12,7 +13,6 @@ import functools
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
sys.path.append(os.path.dirname(__file__))
|
sys.path.append(os.path.dirname(__file__))
|
||||||
from helpers import git_ls_files, filter_changed
|
|
||||||
|
|
||||||
|
|
||||||
def find_all(a_str, sub):
|
def find_all(a_str, sub):
|
||||||
|
@ -562,6 +562,7 @@ def lint_inclusive_language(fname, match):
|
||||||
"esphome/components/number/number.h",
|
"esphome/components/number/number.h",
|
||||||
"esphome/components/output/binary_output.h",
|
"esphome/components/output/binary_output.h",
|
||||||
"esphome/components/output/float_output.h",
|
"esphome/components/output/float_output.h",
|
||||||
|
"esphome/components/nextion/nextion_base.h",
|
||||||
"esphome/components/sensor/sensor.h",
|
"esphome/components/sensor/sensor.h",
|
||||||
"esphome/components/stepper/stepper.h",
|
"esphome/components/stepper/stepper.h",
|
||||||
"esphome/components/switch/switch.h",
|
"esphome/components/switch/switch.h",
|
||||||
|
|
|
@ -1055,10 +1055,6 @@ binary_sensor:
|
||||||
pin: GPIO27
|
pin: GPIO27
|
||||||
threshold: 1000
|
threshold: 1000
|
||||||
id: btn_left
|
id: btn_left
|
||||||
- platform: nextion
|
|
||||||
page_id: 0
|
|
||||||
component_id: 2
|
|
||||||
name: 'Nextion Component 2 Touch'
|
|
||||||
- platform: template
|
- platform: template
|
||||||
name: 'Garage Door Open'
|
name: 'Garage Door Open'
|
||||||
id: garage_door
|
id: garage_door
|
||||||
|
@ -1882,11 +1878,6 @@ display:
|
||||||
intensity: 3
|
intensity: 3
|
||||||
lambda: |-
|
lambda: |-
|
||||||
it.print("1234");
|
it.print("1234");
|
||||||
- platform: nextion
|
|
||||||
uart_id: uart0
|
|
||||||
lambda: |-
|
|
||||||
it.set_component_value("gauge", 50);
|
|
||||||
it.set_component_text("textview", "Hello World!");
|
|
||||||
- platform: pcd8544
|
- platform: pcd8544
|
||||||
cs_pin: GPIO23
|
cs_pin: GPIO23
|
||||||
dc_pin: GPIO23
|
dc_pin: GPIO23
|
||||||
|
|
|
@ -269,6 +269,7 @@ wled:
|
||||||
|
|
||||||
adalight:
|
adalight:
|
||||||
|
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: apds9960
|
- platform: apds9960
|
||||||
type: proximity
|
type: proximity
|
||||||
|
@ -534,6 +535,15 @@ sensor:
|
||||||
export_reactive_energy:
|
export_reactive_energy:
|
||||||
name: 'Export Reactive Energy'
|
name: 'Export Reactive Energy'
|
||||||
|
|
||||||
|
- platform: nextion
|
||||||
|
id: testnumber
|
||||||
|
name: 'testnumber'
|
||||||
|
variable_name: testnumber
|
||||||
|
- platform: nextion
|
||||||
|
id: testwave
|
||||||
|
name: 'testwave'
|
||||||
|
component_id: 2
|
||||||
|
wave_channel_id: 1
|
||||||
time:
|
time:
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
|
|
||||||
|
@ -605,7 +615,14 @@ binary_sensor:
|
||||||
binary_sensors:
|
binary_sensors:
|
||||||
- id: custom_binary_sensor
|
- id: custom_binary_sensor
|
||||||
name: Custom Binary Sensor
|
name: Custom Binary Sensor
|
||||||
|
- platform: nextion
|
||||||
|
page_id: 0
|
||||||
|
component_id: 2
|
||||||
|
name: 'Nextion Component 2 Touch'
|
||||||
|
- platform: nextion
|
||||||
|
id: r0_sensor
|
||||||
|
name: 'R0 Sensor'
|
||||||
|
component_name: page0.r0
|
||||||
globals:
|
globals:
|
||||||
- id: my_global_string
|
- id: my_global_string
|
||||||
type: std::string
|
type: std::string
|
||||||
|
@ -653,6 +670,11 @@ text_sensor:
|
||||||
text_sensors:
|
text_sensors:
|
||||||
- id: custom_text_sensor
|
- id: custom_text_sensor
|
||||||
name: Custom Text Sensor
|
name: Custom Text Sensor
|
||||||
|
- platform: nextion
|
||||||
|
name: text0
|
||||||
|
id: text0
|
||||||
|
update_interval: 4s
|
||||||
|
component_name: text0
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- id: my_script
|
- id: my_script
|
||||||
|
@ -704,6 +726,10 @@ switch:
|
||||||
switches:
|
switches:
|
||||||
- id: custom_switch
|
- id: custom_switch
|
||||||
name: Custom Switch
|
name: Custom Switch
|
||||||
|
- platform: nextion
|
||||||
|
id: r0
|
||||||
|
name: 'R0 Switch'
|
||||||
|
component_name: page0.r0
|
||||||
|
|
||||||
custom_component:
|
custom_component:
|
||||||
lambda: |-
|
lambda: |-
|
||||||
|
@ -1086,6 +1112,16 @@ display:
|
||||||
id: my_matrix
|
id: my_matrix
|
||||||
lambda: |-
|
lambda: |-
|
||||||
it.printdigit("hello");
|
it.printdigit("hello");
|
||||||
|
- platform: nextion
|
||||||
|
uart_id: uart1
|
||||||
|
tft_url: 'http://esphome.io/default35.tft'
|
||||||
|
update_interval: 5s
|
||||||
|
on_sleep:
|
||||||
|
then:
|
||||||
|
lambda: 'ESP_LOGD("display","Display went to sleep");'
|
||||||
|
on_wake:
|
||||||
|
then:
|
||||||
|
lambda: 'ESP_LOGD("display","Display woke up");'
|
||||||
|
|
||||||
http_request:
|
http_request:
|
||||||
useragent: esphome/device
|
useragent: esphome/device
|
||||||
|
|
Loading…
Reference in a new issue