Add map filter for text sensors (#2761)

This commit is contained in:
Oxan van Leeuwen 2021-11-25 21:35:33 +01:00 committed by GitHub
parent d50bdf619f
commit b5f660398c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 17 deletions

View File

@ -49,6 +49,7 @@ ToLowerFilter = text_sensor_ns.class_("ToLowerFilter", Filter)
AppendFilter = text_sensor_ns.class_("AppendFilter", Filter)
PrependFilter = text_sensor_ns.class_("PrependFilter", Filter)
SubstituteFilter = text_sensor_ns.class_("SubstituteFilter", Filter)
MapFilter = text_sensor_ns.class_("MapFilter", Filter)
@FILTER_REGISTRY.register("lambda", LambdaFilter, cv.returning_lambda)
@ -79,26 +80,21 @@ async def prepend_filter_to_code(config, filter_id):
return cg.new_Pvariable(filter_id, config)
def validate_substitute(value):
if isinstance(value, dict):
return cv.Schema(
{
cv.Required(CONF_FROM): cv.string,
cv.Required(CONF_TO): cv.string,
}
)(value)
value = cv.string(value)
if "->" not in value:
raise cv.Invalid("Substitute mapping must contain '->'")
a, b = value.split("->", 1)
a, b = a.strip(), b.strip()
return validate_substitute({CONF_FROM: cv.string(a), CONF_TO: cv.string(b)})
def validate_mapping(value):
if not isinstance(value, dict):
value = cv.string(value)
if "->" not in value:
raise cv.Invalid("Mapping must contain '->'")
a, b = value.split("->", 1)
value = {CONF_FROM: a.strip(), CONF_TO: b.strip()}
return cv.Schema(
{cv.Required(CONF_FROM): cv.string, cv.Required(CONF_TO): cv.string}
)(value)
@FILTER_REGISTRY.register(
"substitute",
SubstituteFilter,
cv.All(cv.ensure_list(validate_substitute), cv.Length(min=2)),
"substitute", SubstituteFilter, cv.ensure_list(validate_mapping)
)
async def substitute_filter_to_code(config, filter_id):
from_strings = [conf[CONF_FROM] for conf in config]
@ -106,6 +102,14 @@ async def substitute_filter_to_code(config, filter_id):
return cg.new_Pvariable(filter_id, from_strings, to_strings)
@FILTER_REGISTRY.register("map", MapFilter, cv.ensure_list(validate_mapping))
async def map_filter_to_code(config, filter_id):
map_ = cg.std_ns.class_("map").template(cg.std_string, cg.std_string)
return cg.new_Pvariable(
filter_id, map_([(item[CONF_FROM], item[CONF_TO]) for item in config])
)
icon = cv.icon

View File

@ -70,5 +70,11 @@ optional<std::string> SubstituteFilter::new_value(std::string value) {
return value;
}
// Map
optional<std::string> MapFilter::new_value(std::string value) {
auto item = mappings_.find(value);
return item == mappings_.end() ? value : item->second;
}
} // namespace text_sensor
} // namespace esphome

View File

@ -4,6 +4,7 @@
#include "esphome/core/helpers.h"
#include <queue>
#include <utility>
#include <map>
namespace esphome {
namespace text_sensor {
@ -108,5 +109,15 @@ class SubstituteFilter : public Filter {
std::vector<std::string> to_strings_;
};
/// A filter that maps values from one set to another
class MapFilter : public Filter {
public:
MapFilter(std::map<std::string, std::string> mappings) : mappings_(std::move(mappings)) {}
optional<std::string> new_value(std::string value) override;
protected:
std::map<std::string, std::string> mappings_;
};
} // namespace text_sensor
} // namespace esphome

View File

@ -458,6 +458,16 @@ text_sensor:
name: 'Template Text Sensor'
lambda: |-
return {"Hello World"};
filters:
- to_upper:
- to_lower:
- append: "xyz"
- prepend: "abcd"
- substitute:
- Hello -> Goodbye
- map:
- red -> green
- lambda: return {"1234"};
- platform: homeassistant
entity_id: sensor.hello_world2
id: ha_hello_world2