mirror of
https://github.com/esphome/esphome.git
synced 2025-07-28 14:16:40 +00:00
[nextion] Adds a command pacer with command_spacing
attribute (#7948)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
6f35d0ac88
commit
8bbc509b0b
@ -7,28 +7,29 @@ from esphome.const import CONF_BACKGROUND_COLOR, CONF_FOREGROUND_COLOR, CONF_VIS
|
||||
|
||||
from . import CONF_NEXTION_ID, Nextion
|
||||
|
||||
CONF_VARIABLE_NAME = "variable_name"
|
||||
CONF_AUTO_WAKE_ON_TOUCH = "auto_wake_on_touch"
|
||||
CONF_BACKGROUND_PRESSED_COLOR = "background_pressed_color"
|
||||
CONF_COMMAND_SPACING = "command_spacing"
|
||||
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_EXIT_REPARSE_ON_START = "exit_reparse_on_start"
|
||||
CONF_FONT_ID = "font_id"
|
||||
CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color"
|
||||
CONF_ON_BUFFER_OVERFLOW = "on_buffer_overflow"
|
||||
CONF_ON_PAGE = "on_page"
|
||||
CONF_ON_SETUP = "on_setup"
|
||||
CONF_ON_SLEEP = "on_sleep"
|
||||
CONF_ON_WAKE = "on_wake"
|
||||
CONF_ON_SETUP = "on_setup"
|
||||
CONF_ON_PAGE = "on_page"
|
||||
CONF_ON_BUFFER_OVERFLOW = "on_buffer_overflow"
|
||||
CONF_TOUCH_SLEEP_TIMEOUT = "touch_sleep_timeout"
|
||||
CONF_WAKE_UP_PAGE = "wake_up_page"
|
||||
CONF_START_UP_PAGE = "start_up_page"
|
||||
CONF_AUTO_WAKE_ON_TOUCH = "auto_wake_on_touch"
|
||||
CONF_WAVE_MAX_LENGTH = "wave_max_length"
|
||||
CONF_BACKGROUND_PRESSED_COLOR = "background_pressed_color"
|
||||
CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color"
|
||||
CONF_FONT_ID = "font_id"
|
||||
CONF_EXIT_REPARSE_ON_START = "exit_reparse_on_start"
|
||||
CONF_PRECISION = "precision"
|
||||
CONF_SKIP_CONNECTION_HANDSHAKE = "skip_connection_handshake"
|
||||
CONF_START_UP_PAGE = "start_up_page"
|
||||
CONF_TFT_URL = "tft_url"
|
||||
CONF_TOUCH_SLEEP_TIMEOUT = "touch_sleep_timeout"
|
||||
CONF_VARIABLE_NAME = "variable_name"
|
||||
CONF_WAKE_UP_PAGE = "wake_up_page"
|
||||
CONF_WAVE_CHANNEL_ID = "wave_channel_id"
|
||||
CONF_WAVE_MAX_LENGTH = "wave_max_length"
|
||||
CONF_WAVE_MAX_VALUE = "wave_max_value"
|
||||
CONF_WAVEFORM_SEND_LAST_VALUE = "waveform_send_last_value"
|
||||
|
||||
|
||||
def NextionName(value):
|
||||
|
@ -9,16 +9,17 @@ from esphome.const import (
|
||||
CONF_ON_TOUCH,
|
||||
CONF_TRIGGER_ID,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.core import CORE, TimePeriod
|
||||
|
||||
from . import Nextion, nextion_ns, nextion_ref
|
||||
from .base_component import (
|
||||
CONF_AUTO_WAKE_ON_TOUCH,
|
||||
CONF_COMMAND_SPACING,
|
||||
CONF_EXIT_REPARSE_ON_START,
|
||||
CONF_ON_BUFFER_OVERFLOW,
|
||||
CONF_ON_PAGE,
|
||||
CONF_ON_SETUP,
|
||||
CONF_ON_SLEEP,
|
||||
CONF_ON_PAGE,
|
||||
CONF_ON_WAKE,
|
||||
CONF_SKIP_CONNECTION_HANDSHAKE,
|
||||
CONF_START_UP_PAGE,
|
||||
@ -88,6 +89,10 @@ CONFIG_SCHEMA = (
|
||||
cv.Optional(CONF_AUTO_WAKE_ON_TOUCH, default=True): cv.boolean,
|
||||
cv.Optional(CONF_EXIT_REPARSE_ON_START, default=False): cv.boolean,
|
||||
cv.Optional(CONF_SKIP_CONNECTION_HANDSHAKE, default=False): cv.boolean,
|
||||
cv.Optional(CONF_COMMAND_SPACING): cv.All(
|
||||
cv.positive_time_period_milliseconds,
|
||||
cv.Range(max=TimePeriod(milliseconds=255)),
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("5s"))
|
||||
@ -120,6 +125,10 @@ async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await uart.register_uart_device(var, config)
|
||||
|
||||
if command_spacing := config.get(CONF_COMMAND_SPACING):
|
||||
cg.add_define("USE_NEXTION_COMMAND_SPACING")
|
||||
cg.add(var.set_command_spacing(command_spacing.total_milliseconds))
|
||||
|
||||
if CONF_BRIGHTNESS in config:
|
||||
cg.add(var.set_brightness(config[CONF_BRIGHTNESS]))
|
||||
|
||||
|
@ -31,11 +31,22 @@ bool Nextion::send_command_(const std::string &command) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
if (!this->ignore_is_setup_ && !this->command_pacer_.can_send()) {
|
||||
return false;
|
||||
}
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
ESP_LOGN(TAG, "send_command %s", command.c_str());
|
||||
|
||||
this->write_str(command.c_str());
|
||||
const uint8_t to_send[3] = {0xFF, 0xFF, 0xFF};
|
||||
this->write_array(to_send, sizeof(to_send));
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
this->command_pacer_.mark_sent();
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -158,6 +169,10 @@ void Nextion::dump_config() {
|
||||
if (this->start_up_page_ != -1) {
|
||||
ESP_LOGCONFIG(TAG, " Start Up Page: %" PRId16, this->start_up_page_);
|
||||
}
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
ESP_LOGCONFIG(TAG, " Command spacing: %" PRIu8 "ms", this->command_pacer_.get_spacing());
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
}
|
||||
|
||||
float Nextion::get_setup_priority() const { return setup_priority::DATA; }
|
||||
@ -312,6 +327,11 @@ bool Nextion::remove_from_q_(bool report_empty) {
|
||||
}
|
||||
|
||||
NextionQueue *nb = this->nextion_queue_.front();
|
||||
if (!nb || !nb->component) {
|
||||
ESP_LOGE(TAG, "Invalid queue entry!");
|
||||
this->nextion_queue_.pop_front();
|
||||
return false;
|
||||
}
|
||||
NextionComponentBase *component = nb->component;
|
||||
|
||||
ESP_LOGN(TAG, "Removing %s from the queue", component->get_variable_name().c_str());
|
||||
@ -341,6 +361,12 @@ void Nextion::process_nextion_commands_() {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
if (!this->command_pacer_.can_send()) {
|
||||
return; // Will try again in next loop iteration
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t to_process_length = 0;
|
||||
std::string to_process;
|
||||
|
||||
@ -380,7 +406,9 @@ void Nextion::process_nextion_commands_() {
|
||||
this->setup_callback_.call();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
this->command_pacer_.mark_sent(); // Here is where we should mark the command as sent
|
||||
#endif
|
||||
break;
|
||||
case 0x02: // invalid Component ID or name was used
|
||||
ESP_LOGW(TAG, "Nextion reported component ID or name invalid!");
|
||||
@ -524,6 +552,11 @@ void Nextion::process_nextion_commands_() {
|
||||
}
|
||||
|
||||
NextionQueue *nb = this->nextion_queue_.front();
|
||||
if (!nb || !nb->component) {
|
||||
ESP_LOGE(TAG, "Invalid queue entry!");
|
||||
this->nextion_queue_.pop_front();
|
||||
return;
|
||||
}
|
||||
NextionComponentBase *component = nb->component;
|
||||
|
||||
if (component->get_queue_type() != NextionQueueType::TEXT_SENSOR) {
|
||||
@ -564,6 +597,11 @@ void Nextion::process_nextion_commands_() {
|
||||
}
|
||||
|
||||
NextionQueue *nb = this->nextion_queue_.front();
|
||||
if (!nb || !nb->component) {
|
||||
ESP_LOGE(TAG, "Invalid queue entry!");
|
||||
this->nextion_queue_.pop_front();
|
||||
return;
|
||||
}
|
||||
NextionComponentBase *component = nb->component;
|
||||
|
||||
if (component->get_queue_type() != NextionQueueType::SENSOR &&
|
||||
|
@ -35,8 +35,54 @@ using nextion_writer_t = std::function<void(Nextion &)>;
|
||||
|
||||
static const std::string COMMAND_DELIMITER{static_cast<char>(255), static_cast<char>(255), static_cast<char>(255)};
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
class NextionCommandPacer {
|
||||
public:
|
||||
/**
|
||||
* @brief Creates command pacer with initial spacing
|
||||
* @param initial_spacing Initial time between commands in milliseconds
|
||||
*/
|
||||
explicit NextionCommandPacer(uint8_t initial_spacing = 0) : spacing_ms_(initial_spacing) {}
|
||||
|
||||
/**
|
||||
* @brief Set the minimum time between commands
|
||||
* @param spacing_ms Spacing in milliseconds
|
||||
*/
|
||||
void set_spacing(uint8_t spacing_ms) { spacing_ms_ = spacing_ms; }
|
||||
|
||||
/**
|
||||
* @brief Get current command spacing
|
||||
* @return Current spacing in milliseconds
|
||||
*/
|
||||
uint8_t get_spacing() const { return spacing_ms_; }
|
||||
|
||||
/**
|
||||
* @brief Check if enough time has passed to send next command
|
||||
* @return true if enough time has passed since last command
|
||||
*/
|
||||
bool can_send() const { return (millis() - last_command_time_) >= spacing_ms_; }
|
||||
|
||||
/**
|
||||
* @brief Mark a command as sent, updating the timing
|
||||
*/
|
||||
void mark_sent() { last_command_time_ = millis(); }
|
||||
|
||||
private:
|
||||
uint8_t spacing_ms_;
|
||||
uint32_t last_command_time_{0};
|
||||
};
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
class Nextion : public NextionBase, public PollingComponent, public uart::UARTDevice {
|
||||
public:
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
/**
|
||||
* @brief Set the command spacing for the display
|
||||
* @param spacing_ms Time in milliseconds between commands
|
||||
*/
|
||||
void set_command_spacing(uint32_t spacing_ms) { this->command_pacer_.set_spacing(spacing_ms); }
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
/**
|
||||
* Set the text of a component to a static string.
|
||||
* @param component The component name.
|
||||
@ -1227,6 +1273,9 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
bool is_connected() { return this->is_connected_; }
|
||||
|
||||
protected:
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
NextionCommandPacer command_pacer_{0};
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
std::deque<NextionQueue *> nextion_queue_;
|
||||
std::deque<NextionQueue *> waveform_queue_;
|
||||
uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag);
|
||||
@ -1360,5 +1409,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
uint32_t started_ms_ = 0;
|
||||
bool sent_setup_commands_ = false;
|
||||
};
|
||||
|
||||
} // namespace nextion
|
||||
} // namespace esphome
|
||||
|
@ -280,6 +280,7 @@ display:
|
||||
- platform: nextion
|
||||
id: main_lcd
|
||||
update_interval: 5s
|
||||
command_spacing: 5ms
|
||||
on_sleep:
|
||||
then:
|
||||
lambda: 'ESP_LOGD("display","Display went to sleep");'
|
||||
|
Loading…
x
Reference in New Issue
Block a user