[ld2410s] Use Apply entities for the select and numbers

This commit is contained in:
J. Nick Koston committed 2026-10-26 07:19:24 -10:00
1 parent d7e8efa03f
commit 18076d0d64
6 files changed
+52 -81

No files matched your search

+27 -2
View File
@@ -1,5 +1,4 @@
#include "ld2410s.h"
#include "ld2410s_number.h"
#include <cstring>
#include "esphome/core/application.h"
#include "esphome/core/hal.h"
@@ -40,6 +39,11 @@ static constexpr uint8_t CMD_FRAME_MAX_SIZE = LONG_PAYLOAD_POS + 2 + PARAMETERS_
#ifdef USE_LD2410S_PARAMETERS
static constexpr uint16_t PARAMETER_KEYS[] PROGMEM = {0x0005, 0x000A, 0x0006, 0x0002, 0x000C, 0x000B};
static_assert(sizeof(PARAMETER_KEYS) / sizeof(PARAMETER_KEYS[0]) == PARAMETER_COUNT, "one key per parameter");
#ifdef USE_NUMBER
// Module units to number units: 0.7 m gates, seconds, tenths of a hertz (number.py uses the same)
static constexpr float PARAMETER_SCALES[] PROGMEM = {0.7f, 0.7f, 1.0f, 0.1f, 0.1f, 1.0f};
static_assert(sizeof(PARAMETER_SCALES) / sizeof(PARAMETER_SCALES[0]) == PARAMETER_COUNT, "one scale per parameter");
#endif
#endif
// The version answer: 4 bytes device type, then major, minor and patch as 16-bit words
static constexpr uint8_t VERSION_TYPE_SIZE = 4;
@@ -136,6 +140,27 @@ bool LD2410SComponent::set_parameter(Parameter parameter, uint8_t value) {
this->parameters_dirty_ = true; // written by loop() once no sequence is running
return true;
}
#ifdef USE_NUMBER
void LD2410SComponent::control_number(number::Number *number, float value) {
for (uint8_t i = 0; i < PARAMETER_COUNT; i++) {
if (this->numbers_[i] != number)
continue;
// Show the step the module got, not a value between two steps
const uint8_t raw = lroundf(value / PARAMETER_SCALES[i]); // the schema keeps every parameter within a byte
if (this->set_parameter(static_cast<Parameter>(i), raw))
number->publish_state(raw * PARAMETER_SCALES[i]);
return;
}
}
#endif
#ifdef USE_SELECT
void LD2410SComponent::control_response_speed(size_t index) {
if (this->set_parameter(Parameter::PARAMETER_RESPONSE_SPEED, progmem_read_byte(&RESPONSE_SPEEDS[index])))
this->response_speed_select_->publish_state(index);
}
#endif
#endif
void LD2410SComponent::restart_init_(uint32_t at) {
@@ -502,7 +527,7 @@ void LD2410SComponent::publish_parameters_() {
#ifdef USE_NUMBER
for (uint8_t i = 0; i < PARAMETER_COUNT; i++) {
if (this->numbers_[i] != nullptr) {
this->numbers_[i]->publish_raw(this->parameters_[i]);
this->numbers_[i]->publish_state(this->parameters_[i] * PARAMETER_SCALES[i]);
}
}
#endif
+10 -6
View File
@@ -14,6 +14,9 @@
#ifdef USE_LD2410S_VERSION
#include "esphome/components/text_sensor/text_sensor.h"
#endif
#if defined(USE_NUMBER) && defined(USE_LD2410S_PARAMETERS)
#include "esphome/components/number/number.h"
#endif
#if defined(USE_SELECT) && defined(USE_LD2410S_PARAMETERS)
#include "esphome/components/select/select.h"
#endif
@@ -39,10 +42,6 @@ static constexpr uint8_t PARAMETER_COUNT = static_cast<uint8_t>(Parameter::PARAM
static constexpr uint8_t RESPONSE_SPEEDS[] PROGMEM = {5, 10};
static constexpr uint8_t RESPONSE_SPEED_COUNT = sizeof(RESPONSE_SPEEDS);
#if defined(USE_NUMBER) && defined(USE_LD2410S_PARAMETERS)
class LD2410SNumber;
#endif
class LD2410SComponent final : public Component, public uart::UARTDevice {
#ifdef USE_BINARY_SENSOR
SUB_BINARY_SENSOR(target)
@@ -67,9 +66,14 @@ class LD2410SComponent final : public Component, public uart::UARTDevice {
#ifdef USE_LD2410S_PARAMETERS
bool set_parameter(Parameter parameter, uint8_t value);
#ifdef USE_NUMBER
void set_number(Parameter parameter, LD2410SNumber *number) {
void set_number(Parameter parameter, number::Number *number) {
this->numbers_[static_cast<uint8_t>(parameter)] = number;
}
/// Writes the number's parameter and publishes the step the module got.
void control_number(number::Number *number, float value);
#endif
#ifdef USE_SELECT
void control_response_speed(size_t index);
#endif
#endif
@@ -109,7 +113,7 @@ class LD2410SComponent final : public Component, public uart::UARTDevice {
#endif
#if defined(USE_NUMBER) && defined(USE_LD2410S_PARAMETERS)
LD2410SNumber *numbers_[PARAMETER_COUNT]{}; // null for parameters without a number
number::Number *numbers_[PARAMETER_COUNT]{}; // null for parameters without a number
#endif
const uint16_t *sequence_{nullptr}; // PROGMEM; null while nothing is being sent
@@ -1,32 +0,0 @@
#pragma once
#include "esphome/core/defines.h"
#if defined(USE_NUMBER) && defined(USE_LD2410S_PARAMETERS)
#include "ld2410s.h"
#include "esphome/components/number/number.h"
namespace esphome::ld2410s {
/// Edits one common parameter; scale converts the module's units to the number's.
class LD2410SNumber final : public number::Number, public Parented<LD2410SComponent> {
public:
LD2410SNumber(Parameter parameter, float scale) : parameter_(parameter), scale_(scale) {}
void publish_raw(uint8_t raw) { this->publish_state(raw * this->scale_); }
protected:
void control(float value) override {
// Show the step the module got, not a value between two steps
const uint8_t raw = lroundf(value / this->scale_); // the schema keeps every parameter within a byte
if (this->parent_->set_parameter(this->parameter_, raw))
this->publish_raw(raw);
}
const Parameter parameter_;
const float scale_;
};
} // namespace esphome::ld2410s
#endif // USE_NUMBER && USE_LD2410S_PARAMETERS
@@ -1,21 +0,0 @@
#pragma once
#include "esphome/core/defines.h"
#if defined(USE_SELECT) && defined(USE_LD2410S_PARAMETERS)
#include "ld2410s.h"
#include "esphome/components/select/select.h"
namespace esphome::ld2410s {
class LD2410SSelect final : public select::Select, public Parented<LD2410SComponent> {
protected:
void control(size_t index) override {
if (this->parent_->set_parameter(Parameter::PARAMETER_RESPONSE_SPEED, progmem_read_byte(&RESPONSE_SPEEDS[index])))
this->publish_state(index);
}
};
} // namespace esphome::ld2410s
#endif // USE_SELECT && USE_LD2410S_PARAMETERS
+9 -15
View File
@@ -16,7 +16,7 @@ from esphome.const import (
)
from esphome.types import ConfigType
from . import CONF_LD2410S_ID, LD2410SComponent, Parameter, ld2410s_ns
from . import CONF_LD2410S_ID, LD2410SComponent, Parameter
DEPENDENCIES = ["ld2410s"]
@@ -26,9 +26,8 @@ CONF_MIN_DISTANCE = "min_distance"
CONF_NO_DELAY = "no_delay"
CONF_STATUS_REPORTING_FREQUENCY = "status_reporting_frequency"
LD2410SNumber = ld2410s_ns.class_("LD2410SNumber", number.Number)
# The module counts distances in 0.7 m gates and frequencies in tenths of a hertz
# The module counts distances in 0.7 m gates and frequencies in tenths of a hertz;
# PARAMETER_SCALES in ld2410s.cpp converts with the same factors
GATE_WIDTH_M = 0.7
FREQUENCY_SCALE = 0.1
_DISTANCE_RANGE = {"min_value": 0, "max_value": 16 * GATE_WIDTH_M, "step": GATE_WIDTH_M}
@@ -37,7 +36,7 @@ _FREQUENCY_RANGE = {"min_value": 0.5, "max_value": 8, "step": 0.5}
def _number_schema(device_class: str, unit: str, icon: str) -> cv.Schema:
return number.number_schema(
LD2410SNumber,
number.ApplyNumber,
device_class=device_class,
entity_category=ENTITY_CATEGORY_CONFIG,
unit_of_measurement=unit,
@@ -72,22 +71,19 @@ async def to_code(config: ConfigType) -> None:
await numbers(
CONF_MAX_DISTANCE,
partial(hub.set_number, Parameter.PARAMETER_MAX_DISTANCE),
Parameter.PARAMETER_MAX_DISTANCE,
GATE_WIDTH_M,
apply="control_number(entity, value)",
**_DISTANCE_RANGE,
)
await numbers(
CONF_MIN_DISTANCE,
partial(hub.set_number, Parameter.PARAMETER_MIN_DISTANCE),
Parameter.PARAMETER_MIN_DISTANCE,
GATE_WIDTH_M,
apply="control_number(entity, value)",
**_DISTANCE_RANGE,
)
await numbers(
CONF_NO_DELAY,
partial(hub.set_number, Parameter.PARAMETER_NO_DELAY),
Parameter.PARAMETER_NO_DELAY,
1,
apply="control_number(entity, value)",
min_value=1,
max_value=120,
step=1,
@@ -95,14 +91,12 @@ async def to_code(config: ConfigType) -> None:
await numbers(
CONF_STATUS_REPORTING_FREQUENCY,
partial(hub.set_number, Parameter.PARAMETER_STATUS_FREQUENCY),
Parameter.PARAMETER_STATUS_FREQUENCY,
FREQUENCY_SCALE,
apply="control_number(entity, value)",
**_FREQUENCY_RANGE,
)
await numbers(
CONF_DISTANCE_REPORTING_FREQUENCY,
partial(hub.set_number, Parameter.PARAMETER_DISTANCE_FREQUENCY),
Parameter.PARAMETER_DISTANCE_FREQUENCY,
FREQUENCY_SCALE,
apply="control_number(entity, value)",
**_FREQUENCY_RANGE,
)
+6 -5
View File
@@ -4,18 +4,16 @@ import esphome.config_validation as cv
from esphome.const import ENTITY_CATEGORY_CONFIG
from esphome.types import ConfigType
from . import CONF_LD2410S_ID, LD2410SComponent, ld2410s_ns
from . import CONF_LD2410S_ID, LD2410SComponent
DEPENDENCIES = ["ld2410s"]
CONF_RESPONSE_SPEED = "response_speed"
LD2410SSelect = ld2410s_ns.class_("LD2410SSelect", select.Select)
CONFIG_SCHEMA = {
cv.GenerateID(CONF_LD2410S_ID): cv.use_id(LD2410SComponent),
cv.Required(CONF_RESPONSE_SPEED): select.select_schema(
LD2410SSelect,
select.ApplySelect,
entity_category=ENTITY_CATEGORY_CONFIG,
icon="mdi:speedometer",
),
@@ -27,5 +25,8 @@ async def to_code(config: ConfigType) -> None:
hub = await cg.get_variable(config[CONF_LD2410S_ID])
selects = select.sub_selects(config, parent=hub)
await selects(
CONF_RESPONSE_SPEED, hub.set_response_speed_select, options=["Normal", "Fast"]
CONF_RESPONSE_SPEED,
hub.set_response_speed_select,
options=["Normal", "Fast"],
apply="control_response_speed(index)",
)