mirror of
https://github.com/esphome/esphome.git
synced 2024-11-26 08:55:22 +01:00
Number enhancement (#3429)
Co-authored-by: Maurice Makaay <mmakaay1@xs4all.net> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
44b68f140e
commit
d9caab4108
9 changed files with 380 additions and 88 deletions
|
@ -14,6 +14,8 @@ from esphome.const import (
|
||||||
CONF_UNIT_OF_MEASUREMENT,
|
CONF_UNIT_OF_MEASUREMENT,
|
||||||
CONF_MQTT_ID,
|
CONF_MQTT_ID,
|
||||||
CONF_VALUE,
|
CONF_VALUE,
|
||||||
|
CONF_OPERATION,
|
||||||
|
CONF_CYCLE,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
from esphome.core import CORE, coroutine_with_priority
|
||||||
from esphome.cpp_helpers import setup_entity
|
from esphome.cpp_helpers import setup_entity
|
||||||
|
@ -35,6 +37,7 @@ ValueRangeTrigger = number_ns.class_(
|
||||||
|
|
||||||
# Actions
|
# Actions
|
||||||
NumberSetAction = number_ns.class_("NumberSetAction", automation.Action)
|
NumberSetAction = number_ns.class_("NumberSetAction", automation.Action)
|
||||||
|
NumberOperationAction = number_ns.class_("NumberOperationAction", automation.Action)
|
||||||
|
|
||||||
# Conditions
|
# Conditions
|
||||||
NumberInRangeCondition = number_ns.class_(
|
NumberInRangeCondition = number_ns.class_(
|
||||||
|
@ -49,6 +52,15 @@ NUMBER_MODES = {
|
||||||
"SLIDER": NumberMode.NUMBER_MODE_SLIDER,
|
"SLIDER": NumberMode.NUMBER_MODE_SLIDER,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NumberOperation = number_ns.enum("NumberOperation")
|
||||||
|
|
||||||
|
NUMBER_OPERATION_OPTIONS = {
|
||||||
|
"INCREMENT": NumberOperation.NUMBER_OP_INCREMENT,
|
||||||
|
"DECREMENT": NumberOperation.NUMBER_OP_DECREMENT,
|
||||||
|
"TO_MIN": NumberOperation.NUMBER_OP_TO_MIN,
|
||||||
|
"TO_MAX": NumberOperation.NUMBER_OP_TO_MAX,
|
||||||
|
}
|
||||||
|
|
||||||
icon = cv.icon
|
icon = cv.icon
|
||||||
|
|
||||||
NUMBER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend(
|
NUMBER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA).extend(
|
||||||
|
@ -159,12 +171,18 @@ async def to_code(config):
|
||||||
cg.add_global(number_ns.using)
|
cg.add_global(number_ns.using)
|
||||||
|
|
||||||
|
|
||||||
|
OPERATION_BASE_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_ID): cv.use_id(Number),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@automation.register_action(
|
@automation.register_action(
|
||||||
"number.set",
|
"number.set",
|
||||||
NumberSetAction,
|
NumberSetAction,
|
||||||
cv.Schema(
|
OPERATION_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_ID): cv.use_id(Number),
|
|
||||||
cv.Required(CONF_VALUE): cv.templatable(cv.float_),
|
cv.Required(CONF_VALUE): cv.templatable(cv.float_),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
|
@ -175,3 +193,85 @@ async def number_set_to_code(config, action_id, template_arg, args):
|
||||||
template_ = await cg.templatable(config[CONF_VALUE], args, float)
|
template_ = await cg.templatable(config[CONF_VALUE], args, float)
|
||||||
cg.add(var.set_value(template_))
|
cg.add(var.set_value(template_))
|
||||||
return var
|
return var
|
||||||
|
|
||||||
|
|
||||||
|
@automation.register_action(
|
||||||
|
"number.increment",
|
||||||
|
NumberOperationAction,
|
||||||
|
automation.maybe_simple_id(
|
||||||
|
OPERATION_BASE_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_MODE, default="INCREMENT"): cv.one_of(
|
||||||
|
"INCREMENT", upper=True
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CYCLE, default=True): cv.boolean,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@automation.register_action(
|
||||||
|
"number.decrement",
|
||||||
|
NumberOperationAction,
|
||||||
|
automation.maybe_simple_id(
|
||||||
|
OPERATION_BASE_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_MODE, default="DECREMENT"): cv.one_of(
|
||||||
|
"DECREMENT", upper=True
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CYCLE, default=True): cv.boolean,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@automation.register_action(
|
||||||
|
"number.to_min",
|
||||||
|
NumberOperationAction,
|
||||||
|
automation.maybe_simple_id(
|
||||||
|
OPERATION_BASE_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_MODE, default="TO_MIN"): cv.one_of(
|
||||||
|
"TO_MIN", upper=True
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@automation.register_action(
|
||||||
|
"number.to_max",
|
||||||
|
NumberOperationAction,
|
||||||
|
automation.maybe_simple_id(
|
||||||
|
OPERATION_BASE_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_MODE, default="TO_MAX"): cv.one_of(
|
||||||
|
"TO_MAX", upper=True
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
)
|
||||||
|
@automation.register_action(
|
||||||
|
"number.operation",
|
||||||
|
NumberOperationAction,
|
||||||
|
OPERATION_BASE_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_OPERATION): cv.templatable(
|
||||||
|
cv.enum(NUMBER_OPERATION_OPTIONS, upper=True)
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CYCLE, default=True): cv.templatable(cv.boolean),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
async def number_to_to_code(config, action_id, template_arg, args):
|
||||||
|
paren = await cg.get_variable(config[CONF_ID])
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg, paren)
|
||||||
|
if CONF_OPERATION in config:
|
||||||
|
to_ = await cg.templatable(config[CONF_OPERATION], args, NumberOperation)
|
||||||
|
cg.add(var.set_operation(to_))
|
||||||
|
if CONF_CYCLE in config:
|
||||||
|
cycle_ = await cg.templatable(config[CONF_CYCLE], args, bool)
|
||||||
|
cg.add(var.set_cycle(cycle_))
|
||||||
|
if CONF_MODE in config:
|
||||||
|
cg.add(var.set_operation(NUMBER_OPERATION_OPTIONS[config[CONF_MODE]]))
|
||||||
|
if CONF_CYCLE in config:
|
||||||
|
cg.add(var.set_cycle(config[CONF_CYCLE]))
|
||||||
|
return var
|
||||||
|
|
|
@ -29,6 +29,25 @@ template<typename... Ts> class NumberSetAction : public Action<Ts...> {
|
||||||
Number *number_;
|
Number *number_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class NumberOperationAction : public Action<Ts...> {
|
||||||
|
public:
|
||||||
|
explicit NumberOperationAction(Number *number) : number_(number) {}
|
||||||
|
TEMPLATABLE_VALUE(NumberOperation, operation)
|
||||||
|
TEMPLATABLE_VALUE(bool, cycle)
|
||||||
|
|
||||||
|
void play(Ts... x) override {
|
||||||
|
auto call = this->number_->make_call();
|
||||||
|
call.with_operation(this->operation_.value(x...));
|
||||||
|
if (this->cycle_.has_value()) {
|
||||||
|
call.with_cycle(this->cycle_.value(x...));
|
||||||
|
}
|
||||||
|
call.perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Number *number_;
|
||||||
|
};
|
||||||
|
|
||||||
class ValueRangeTrigger : public Trigger<float>, public Component {
|
class ValueRangeTrigger : public Trigger<float>, public Component {
|
||||||
public:
|
public:
|
||||||
explicit ValueRangeTrigger(Number *parent) : parent_(parent) {}
|
explicit ValueRangeTrigger(Number *parent) : parent_(parent) {}
|
||||||
|
|
|
@ -6,30 +6,6 @@ namespace number {
|
||||||
|
|
||||||
static const char *const TAG = "number";
|
static const char *const TAG = "number";
|
||||||
|
|
||||||
void NumberCall::perform() {
|
|
||||||
ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
|
||||||
if (!this->value_.has_value() || std::isnan(*this->value_)) {
|
|
||||||
ESP_LOGW(TAG, "No value set for NumberCall");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &traits = this->parent_->traits;
|
|
||||||
auto value = *this->value_;
|
|
||||||
|
|
||||||
float min_value = traits.get_min_value();
|
|
||||||
if (value < min_value) {
|
|
||||||
ESP_LOGW(TAG, " Value %f must not be less than minimum %f", value, min_value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
float max_value = traits.get_max_value();
|
|
||||||
if (value > max_value) {
|
|
||||||
ESP_LOGW(TAG, " Value %f must not be greater than maximum %f", value, max_value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ESP_LOGD(TAG, " Value: %f", *this->value_);
|
|
||||||
this->parent_->control(*this->value_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Number::publish_state(float state) {
|
void Number::publish_state(float state) {
|
||||||
this->has_state_ = true;
|
this->has_state_ = true;
|
||||||
this->state = state;
|
this->state = state;
|
||||||
|
@ -41,15 +17,6 @@ void Number::add_on_state_callback(std::function<void(float)> &&callback) {
|
||||||
this->state_callback_.add(std::move(callback));
|
this->state_callback_.add(std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NumberTraits::get_unit_of_measurement() {
|
|
||||||
if (this->unit_of_measurement_.has_value())
|
|
||||||
return *this->unit_of_measurement_;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
void NumberTraits::set_unit_of_measurement(const std::string &unit_of_measurement) {
|
|
||||||
this->unit_of_measurement_ = unit_of_measurement;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Number::hash_base() { return 2282307003UL; }
|
uint32_t Number::hash_base() { return 2282307003UL; }
|
||||||
|
|
||||||
} // namespace number
|
} // namespace number
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/entity_base.h"
|
#include "esphome/core/entity_base.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
#include "number_call.h"
|
||||||
|
#include "number_traits.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace number {
|
namespace number {
|
||||||
|
@ -20,54 +22,6 @@ namespace number {
|
||||||
|
|
||||||
class Number;
|
class Number;
|
||||||
|
|
||||||
class NumberCall {
|
|
||||||
public:
|
|
||||||
explicit NumberCall(Number *parent) : parent_(parent) {}
|
|
||||||
void perform();
|
|
||||||
|
|
||||||
NumberCall &set_value(float value) {
|
|
||||||
value_ = value;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
const optional<float> &get_value() const { return value_; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Number *const parent_;
|
|
||||||
optional<float> value_;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum NumberMode : uint8_t {
|
|
||||||
NUMBER_MODE_AUTO = 0,
|
|
||||||
NUMBER_MODE_BOX = 1,
|
|
||||||
NUMBER_MODE_SLIDER = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
class NumberTraits {
|
|
||||||
public:
|
|
||||||
void set_min_value(float min_value) { min_value_ = min_value; }
|
|
||||||
float get_min_value() const { return min_value_; }
|
|
||||||
void set_max_value(float max_value) { max_value_ = max_value; }
|
|
||||||
float get_max_value() const { return max_value_; }
|
|
||||||
void set_step(float step) { step_ = step; }
|
|
||||||
float get_step() const { return step_; }
|
|
||||||
|
|
||||||
/// Get the unit of measurement, using the manual override if set.
|
|
||||||
std::string get_unit_of_measurement();
|
|
||||||
/// Manually set the unit of measurement.
|
|
||||||
void set_unit_of_measurement(const std::string &unit_of_measurement);
|
|
||||||
|
|
||||||
// Get/set the frontend mode.
|
|
||||||
NumberMode get_mode() const { return this->mode_; }
|
|
||||||
void set_mode(NumberMode mode) { this->mode_ = mode; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
float min_value_ = NAN;
|
|
||||||
float max_value_ = NAN;
|
|
||||||
float step_ = NAN;
|
|
||||||
optional<std::string> unit_of_measurement_; ///< Unit of measurement override
|
|
||||||
NumberMode mode_{NUMBER_MODE_AUTO};
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Base-class for all numbers.
|
/** Base-class for all numbers.
|
||||||
*
|
*
|
||||||
* A number can use publish_state to send out a new value.
|
* A number can use publish_state to send out a new value.
|
||||||
|
|
118
esphome/components/number/number_call.cpp
Normal file
118
esphome/components/number/number_call.cpp
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
#include "number_call.h"
|
||||||
|
#include "number.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace number {
|
||||||
|
|
||||||
|
static const char *const TAG = "number";
|
||||||
|
|
||||||
|
NumberCall &NumberCall::set_value(float value) { return this->with_operation(NUMBER_OP_SET).with_value(value); }
|
||||||
|
|
||||||
|
NumberCall &NumberCall::number_increment(bool cycle) {
|
||||||
|
return this->with_operation(NUMBER_OP_INCREMENT).with_cycle(cycle);
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberCall &NumberCall::number_decrement(bool cycle) {
|
||||||
|
return this->with_operation(NUMBER_OP_DECREMENT).with_cycle(cycle);
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberCall &NumberCall::number_to_min() { return this->with_operation(NUMBER_OP_TO_MIN); }
|
||||||
|
|
||||||
|
NumberCall &NumberCall::number_to_max() { return this->with_operation(NUMBER_OP_TO_MAX); }
|
||||||
|
|
||||||
|
NumberCall &NumberCall::with_operation(NumberOperation operation) {
|
||||||
|
this->operation_ = operation;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberCall &NumberCall::with_value(float value) {
|
||||||
|
this->value_ = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberCall &NumberCall::with_cycle(bool cycle) {
|
||||||
|
this->cycle_ = cycle;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NumberCall::perform() {
|
||||||
|
auto *parent = this->parent_;
|
||||||
|
const auto *name = parent->get_name().c_str();
|
||||||
|
const auto &traits = parent->traits;
|
||||||
|
|
||||||
|
if (this->operation_ == NUMBER_OP_NONE) {
|
||||||
|
ESP_LOGW(TAG, "'%s' - NumberCall performed without selecting an operation", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float target_value = NAN;
|
||||||
|
float min_value = traits.get_min_value();
|
||||||
|
float max_value = traits.get_max_value();
|
||||||
|
|
||||||
|
if (this->operation_ == NUMBER_OP_SET) {
|
||||||
|
ESP_LOGD(TAG, "'%s' - Setting number value", name);
|
||||||
|
if (!this->value_.has_value() || std::isnan(*this->value_)) {
|
||||||
|
ESP_LOGW(TAG, "'%s' - No value set for NumberCall", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
target_value = this->value_.value();
|
||||||
|
} else if (this->operation_ == NUMBER_OP_TO_MIN) {
|
||||||
|
if (std::isnan(min_value)) {
|
||||||
|
ESP_LOGW(TAG, "'%s' - Can't set to min value through NumberCall: no min_value defined", name);
|
||||||
|
} else {
|
||||||
|
target_value = min_value;
|
||||||
|
}
|
||||||
|
} else if (this->operation_ == NUMBER_OP_TO_MAX) {
|
||||||
|
if (std::isnan(max_value)) {
|
||||||
|
ESP_LOGW(TAG, "'%s' - Can't set to max value through NumberCall: no max_value defined", name);
|
||||||
|
} else {
|
||||||
|
target_value = max_value;
|
||||||
|
}
|
||||||
|
} else if (this->operation_ == NUMBER_OP_INCREMENT) {
|
||||||
|
ESP_LOGD(TAG, "'%s' - Increment number, with%s cycling", name, this->cycle_ ? "" : "out");
|
||||||
|
if (!parent->has_state()) {
|
||||||
|
ESP_LOGW(TAG, "'%s' - Can't increment number through NumberCall: no active state to modify", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto step = traits.get_step();
|
||||||
|
target_value = parent->state + (std::isnan(step) ? 1 : step);
|
||||||
|
if (target_value > max_value) {
|
||||||
|
if (this->cycle_ && !std::isnan(min_value)) {
|
||||||
|
target_value = min_value;
|
||||||
|
} else {
|
||||||
|
target_value = max_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (this->operation_ == NUMBER_OP_DECREMENT) {
|
||||||
|
ESP_LOGD(TAG, "'%s' - Decrement number, with%s cycling", name, this->cycle_ ? "" : "out");
|
||||||
|
if (!parent->has_state()) {
|
||||||
|
ESP_LOGW(TAG, "'%s' - Can't decrement number through NumberCall: no active state to modify", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto step = traits.get_step();
|
||||||
|
target_value = parent->state - (std::isnan(step) ? 1 : step);
|
||||||
|
if (target_value < min_value) {
|
||||||
|
if (this->cycle_ && !std::isnan(max_value)) {
|
||||||
|
target_value = max_value;
|
||||||
|
} else {
|
||||||
|
target_value = min_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target_value < min_value) {
|
||||||
|
ESP_LOGW(TAG, "'%s' - Value %f must not be less than minimum %f", name, target_value, min_value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (target_value > max_value) {
|
||||||
|
ESP_LOGW(TAG, "'%s' - Value %f must not be greater than maximum %f", name, target_value, max_value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, " New number value: %f", target_value);
|
||||||
|
this->parent_->control(target_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace number
|
||||||
|
} // namespace esphome
|
45
esphome/components/number/number_call.h
Normal file
45
esphome/components/number/number_call.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
|
#include "number_traits.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace number {
|
||||||
|
|
||||||
|
class Number;
|
||||||
|
|
||||||
|
enum NumberOperation {
|
||||||
|
NUMBER_OP_NONE,
|
||||||
|
NUMBER_OP_SET,
|
||||||
|
NUMBER_OP_INCREMENT,
|
||||||
|
NUMBER_OP_DECREMENT,
|
||||||
|
NUMBER_OP_TO_MIN,
|
||||||
|
NUMBER_OP_TO_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
class NumberCall {
|
||||||
|
public:
|
||||||
|
explicit NumberCall(Number *parent) : parent_(parent) {}
|
||||||
|
void perform();
|
||||||
|
|
||||||
|
NumberCall &set_value(float value);
|
||||||
|
const optional<float> &get_value() const { return value_; }
|
||||||
|
|
||||||
|
NumberCall &number_increment(bool cycle);
|
||||||
|
NumberCall &number_decrement(bool cycle);
|
||||||
|
NumberCall &number_to_min();
|
||||||
|
NumberCall &number_to_max();
|
||||||
|
|
||||||
|
NumberCall &with_operation(NumberOperation operation);
|
||||||
|
NumberCall &with_value(float value);
|
||||||
|
NumberCall &with_cycle(bool cycle);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Number *const parent_;
|
||||||
|
NumberOperation operation_{NUMBER_OP_NONE};
|
||||||
|
optional<float> value_;
|
||||||
|
bool cycle_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace number
|
||||||
|
} // namespace esphome
|
20
esphome/components/number/number_traits.cpp
Normal file
20
esphome/components/number/number_traits.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "number_traits.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace number {
|
||||||
|
|
||||||
|
static const char *const TAG = "number";
|
||||||
|
|
||||||
|
void NumberTraits::set_unit_of_measurement(const std::string &unit_of_measurement) {
|
||||||
|
this->unit_of_measurement_ = unit_of_measurement;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string NumberTraits::get_unit_of_measurement() {
|
||||||
|
if (this->unit_of_measurement_.has_value())
|
||||||
|
return *this->unit_of_measurement_;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace number
|
||||||
|
} // namespace esphome
|
44
esphome/components/number/number_traits.h
Normal file
44
esphome/components/number/number_traits.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace number {
|
||||||
|
|
||||||
|
enum NumberMode : uint8_t {
|
||||||
|
NUMBER_MODE_AUTO = 0,
|
||||||
|
NUMBER_MODE_BOX = 1,
|
||||||
|
NUMBER_MODE_SLIDER = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
class NumberTraits {
|
||||||
|
public:
|
||||||
|
// Set/get the number value boundaries.
|
||||||
|
void set_min_value(float min_value) { min_value_ = min_value; }
|
||||||
|
float get_min_value() const { return min_value_; }
|
||||||
|
void set_max_value(float max_value) { max_value_ = max_value; }
|
||||||
|
float get_max_value() const { return max_value_; }
|
||||||
|
|
||||||
|
// Set/get the step size for incrementing or decrementing the number value.
|
||||||
|
void set_step(float step) { step_ = step; }
|
||||||
|
float get_step() const { return step_; }
|
||||||
|
|
||||||
|
/// Manually set the unit of measurement.
|
||||||
|
void set_unit_of_measurement(const std::string &unit_of_measurement);
|
||||||
|
/// Get the unit of measurement, using the manual override if set.
|
||||||
|
std::string get_unit_of_measurement();
|
||||||
|
|
||||||
|
// Set/get the frontend mode.
|
||||||
|
void set_mode(NumberMode mode) { this->mode_ = mode; }
|
||||||
|
NumberMode get_mode() const { return this->mode_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
float min_value_ = NAN;
|
||||||
|
float max_value_ = NAN;
|
||||||
|
float step_ = NAN;
|
||||||
|
optional<std::string> unit_of_measurement_; ///< Unit of measurement override
|
||||||
|
NumberMode mode_{NUMBER_MODE_AUTO};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace number
|
||||||
|
} // namespace esphome
|
|
@ -120,6 +120,11 @@ number:
|
||||||
name: My template number
|
name: My template number
|
||||||
id: template_number_id
|
id: template_number_id
|
||||||
optimistic: true
|
optimistic: true
|
||||||
|
max_value: 100
|
||||||
|
min_value: 0
|
||||||
|
step: 5
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
mode: slider
|
||||||
on_value:
|
on_value:
|
||||||
- logger.log:
|
- logger.log:
|
||||||
format: "Number changed to %f"
|
format: "Number changed to %f"
|
||||||
|
@ -128,11 +133,31 @@ number:
|
||||||
- logger.log:
|
- logger.log:
|
||||||
format: "Template Number set to %f"
|
format: "Template Number set to %f"
|
||||||
args: ["x"]
|
args: ["x"]
|
||||||
max_value: 100
|
- number.set:
|
||||||
min_value: 0
|
id: template_number_id
|
||||||
step: 5
|
value: 50
|
||||||
unit_of_measurement: "%"
|
- number.to_min: template_number_id
|
||||||
mode: slider
|
- number.to_min:
|
||||||
|
id: template_number_id
|
||||||
|
- number.to_max: template_number_id
|
||||||
|
- number.to_max:
|
||||||
|
id: template_number_id
|
||||||
|
- number.increment: template_number_id
|
||||||
|
- number.increment:
|
||||||
|
id: template_number_id
|
||||||
|
cycle: false
|
||||||
|
- number.decrement: template_number_id
|
||||||
|
- number.decrement:
|
||||||
|
id: template_number_id
|
||||||
|
cycle: false
|
||||||
|
- number.operation:
|
||||||
|
id: template_number_id
|
||||||
|
operation: Increment
|
||||||
|
cycle: false
|
||||||
|
- number.operation:
|
||||||
|
id: template_number_id
|
||||||
|
operation: !lambda "return NUMBER_OP_INCREMENT;"
|
||||||
|
cycle: !lambda "return false;"
|
||||||
|
|
||||||
- id: modbus_numbertest
|
- id: modbus_numbertest
|
||||||
platform: modbus_controller
|
platform: modbus_controller
|
||||||
|
|
Loading…
Reference in a new issue