mirror of
https://github.com/esphome/esphome.git
synced 2025-10-03 10:32:21 +01:00
Nextion upload and sensors (#1464)
Co-authored-by: Senex Crenshaw <senexcrenshaw@gmail.com>
This commit is contained in:
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
|
Reference in New Issue
Block a user