Implement 'round to nearest multiple' filter (#7142)

This commit is contained in:
Björn Ebbinghaus 2024-08-02 01:58:59 +02:00 committed by GitHub
parent aedfb32482
commit 4a7570770b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 38 additions and 0 deletions

View file

@ -17,6 +17,7 @@ from esphome.const import (
CONF_ICON, CONF_ICON,
CONF_ID, CONF_ID,
CONF_IGNORE_OUT_OF_RANGE, CONF_IGNORE_OUT_OF_RANGE,
CONF_MULTIPLE,
CONF_ON_RAW_VALUE, CONF_ON_RAW_VALUE,
CONF_ON_VALUE, CONF_ON_VALUE,
CONF_ON_VALUE_RANGE, CONF_ON_VALUE_RANGE,
@ -249,6 +250,7 @@ CalibratePolynomialFilter = sensor_ns.class_("CalibratePolynomialFilter", Filter
SensorInRangeCondition = sensor_ns.class_("SensorInRangeCondition", Filter) SensorInRangeCondition = sensor_ns.class_("SensorInRangeCondition", Filter)
ClampFilter = sensor_ns.class_("ClampFilter", Filter) ClampFilter = sensor_ns.class_("ClampFilter", Filter)
RoundFilter = sensor_ns.class_("RoundFilter", Filter) RoundFilter = sensor_ns.class_("RoundFilter", Filter)
RoundMultipleFilter = sensor_ns.class_("RoundMultipleFilter", Filter)
validate_unit_of_measurement = cv.string_strict validate_unit_of_measurement = cv.string_strict
validate_accuracy_decimals = cv.int_ validate_accuracy_decimals = cv.int_
@ -734,6 +736,23 @@ async def round_filter_to_code(config, filter_id):
) )
@FILTER_REGISTRY.register(
"round_to_multiple_of",
RoundMultipleFilter,
cv.maybe_simple_value(
{
cv.Required(CONF_MULTIPLE): cv.positive_not_null_float,
},
key=CONF_MULTIPLE,
),
)
async def round_multiple_filter_to_code(config, filter_id):
return cg.new_Pvariable(
filter_id,
config[CONF_MULTIPLE],
)
async def build_filters(config): async def build_filters(config):
return await cg.build_registry_list(FILTER_REGISTRY, config) return await cg.build_registry_list(FILTER_REGISTRY, config)

View file

@ -472,5 +472,13 @@ optional<float> RoundFilter::new_value(float value) {
return value; return value;
} }
RoundMultipleFilter::RoundMultipleFilter(float multiple) : multiple_(multiple) {}
optional<float> RoundMultipleFilter::new_value(float value) {
if (std::isfinite(value)) {
return value - remainderf(value, this->multiple_);
}
return value;
}
} // namespace sensor } // namespace sensor
} // namespace esphome } // namespace esphome

View file

@ -431,5 +431,14 @@ class RoundFilter : public Filter {
uint8_t precision_; uint8_t precision_;
}; };
class RoundMultipleFilter : public Filter {
public:
explicit RoundMultipleFilter(float multiple);
optional<float> new_value(float value) override;
protected:
float multiple_;
};
} // namespace sensor } // namespace sensor
} // namespace esphome } // namespace esphome

View file

@ -464,6 +464,7 @@ zero_to_one_float = float_range(min=0, max=1)
negative_one_to_one_float = float_range(min=-1, max=1) negative_one_to_one_float = float_range(min=-1, max=1)
positive_int = int_range(min=0) positive_int = int_range(min=0)
positive_not_null_int = int_range(min=0, min_included=False) positive_not_null_int = int_range(min=0, min_included=False)
positive_not_null_float = float_range(min=0, min_included=False)
def validate_id_name(value): def validate_id_name(value):

View file

@ -503,6 +503,7 @@ CONF_MOTION = "motion"
CONF_MOVEMENT_COUNTER = "movement_counter" CONF_MOVEMENT_COUNTER = "movement_counter"
CONF_MQTT = "mqtt" CONF_MQTT = "mqtt"
CONF_MQTT_ID = "mqtt_id" CONF_MQTT_ID = "mqtt_id"
CONF_MULTIPLE = "multiple"
CONF_MULTIPLEXER = "multiplexer" CONF_MULTIPLEXER = "multiplexer"
CONF_MULTIPLY = "multiply" CONF_MULTIPLY = "multiply"
CONF_NAME = "name" CONF_NAME = "name"