From 481431bfbf1a0c3a139541e0000d3fe5d55a8b5d Mon Sep 17 00:00:00 2001 From: Michiel van Turnhout Date: Fri, 10 May 2019 10:24:37 +0200 Subject: [PATCH 1/5] add binary_sensor_map c code --- .../binary_sensor_map/binary_sensor_map.cpp | 69 +++++++++++++++++++ .../binary_sensor_map/binary_sensor_map.h | 60 ++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 esphome/components/binary_sensor_map/binary_sensor_map.cpp create mode 100644 esphome/components/binary_sensor_map/binary_sensor_map.h diff --git a/esphome/components/binary_sensor_map/binary_sensor_map.cpp b/esphome/components/binary_sensor_map/binary_sensor_map.cpp new file mode 100644 index 0000000000..a418066da1 --- /dev/null +++ b/esphome/components/binary_sensor_map/binary_sensor_map.cpp @@ -0,0 +1,69 @@ +#include "binary_sensor_map.h" +#include "esphome/core/log.h" + +namespace esphome { +namespace binary_sensor_map { + +static const char *TAG = "sensor.binary_sensor_map"; + +BinarySensorMap::BinarySensorMap(const std::string &name) : Sensor(name) {} + +void BinarySensorMap::dump_config() { LOG_SENSOR(" ", "binary_sensor_map", this); } + +void BinarySensorMap::loop() { + switch (this->sensor_type_) { + case BINARY_SENSOR_MAP_TYPE_GROUP: + this->process_group_(); + break; + } +} + +void BinarySensorMap::process_group_() { + float total_current_value = 0.0; + uint8_t num_active_sensors = 0; + bool any_active = false; + uint64_t mask = 0x00; + // check all binary_sensors for its state. when active add its value to total_current_value. + // create a bitmask for the binary_sensor status on all channels + for (size_t i = 0; i < this->sensors_.size(); i++) { + auto *bs = this->sensors_[i]; + if (bs->binary_sensor->state) { + any_active = true; + num_active_sensors++; + total_current_value += bs->sensor_value; + mask |= 1 << i; + } + } + // check if the sensor map was touched + if (any_active) { + // did the bit_mask change or is it a new sensor touch + if ((last_mask_ != mask) || !this->last_any_active_) { + this->last_any_active_ = true; + float publish_value = total_current_value / num_active_sensors; + ESP_LOGD(TAG, "%s - Publishing %.2f", this->name_.c_str(), publish_value); + this->publish_state(publish_value); + this->last_mask_ = mask; + } + } else { + // is this a new sensor release + if (this->last_any_active_) { + this->last_any_active_ = false; + ESP_LOGD(TAG, "%s - No binary sensor active, publishing NAN", this->name_.c_str()); + this->publish_state(NAN); + } + } +} + +float BinarySensorMap::get_setup_priority() const { return setup_priority::HARDWARE_LATE; } + +void BinarySensorMap::add_sensor(binary_sensor::BinarySensor *sensor, float value) { + BinarySensorMapChannel *sensor_channel = new BinarySensorMapChannel; + sensor_channel->binary_sensor = sensor; + sensor_channel->sensor_value = value; + this->sensors_.push_back(sensor_channel); +} + +void BinarySensorMap::set_sensor_type(BinarySensorMapType sensor_type) { this->sensor_type_ = sensor_type; } + +} // namespace binary_sensor_map +} // namespace esphome \ No newline at end of file diff --git a/esphome/components/binary_sensor_map/binary_sensor_map.h b/esphome/components/binary_sensor_map/binary_sensor_map.h new file mode 100644 index 0000000000..a140ff93ba --- /dev/null +++ b/esphome/components/binary_sensor_map/binary_sensor_map.h @@ -0,0 +1,60 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/binary_sensor/binary_sensor.h" +#include "esphome/components/sensor/sensor.h" + +namespace esphome { +namespace binary_sensor_map { + +enum BinarySensorMapType { + BINARY_SENSOR_MAP_TYPE_GROUP, +}; + +struct BinarySensorMapChannel { + binary_sensor::BinarySensor *binary_sensor; + float sensor_value = 0; +}; + +/** Class to group binary_sensors to one Sensor. + * + * Each binary sensor represents a float value in the group. + */ +class BinarySensorMap : public sensor::Sensor, public Component { + public: + BinarySensorMap(const std::string &name); + void dump_config() override; + /** + * The loop checks all binary_sensor states + * When the binary_sensor reports a true value for its state, then the float value it represents is added to the + * total_current_value + * + * Only when the total_current_value changed and at least one sensor reports an active state we publish the sensors + * average value. When the value changed and no sensors ar active we publish NAN. + * */ + void loop() override; + float get_setup_priority() const override; + /** Add binary_sensors to the group. + * Each binary_sensor represents a float value when its state is true + * + * @param *sensor The binary sensor. + * @param value The value this binary_sensor represents + */ + void add_sensor(binary_sensor::BinarySensor *sensor, float value); + void set_sensor_type(BinarySensorMapType sensor_type); + + protected: + std::vector sensors_{}; + BinarySensorMapType sensor_type_{BINARY_SENSOR_MAP_TYPE_GROUP}; + bool last_any_active_{false}; + // this gives max 46 channels per binary_sensor_map + uint64_t last_mask_{0x00}; + /** + * methods to process the types of binary_sensor_maps + * GROUP: process_group_() just map to a value + * */ + void process_group_(); +}; + +} // namespace binary_sensor_map +} // namespace esphome \ No newline at end of file From e8ccb84bea5f183eba59ebf3ca3cbec948484433 Mon Sep 17 00:00:00 2001 From: mvturnho Date: Fri, 10 May 2019 22:30:40 +0200 Subject: [PATCH 2/5] add python file --- .../binary_sensor_map/binary_sensor_map.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 esphome/components/binary_sensor_map/binary_sensor_map.py diff --git a/esphome/components/binary_sensor_map/binary_sensor_map.py b/esphome/components/binary_sensor_map/binary_sensor_map.py new file mode 100644 index 0000000000..d1222ba460 --- /dev/null +++ b/esphome/components/binary_sensor_map/binary_sensor_map.py @@ -0,0 +1,47 @@ +import voluptuous as vol + +from esphome.components import sensor, binary_sensor +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_NAME, CONF_CHANNELS, CONF_CHANNEL, CONF_VALUE, CONF_TYPE +from esphome.cpp_generator import Pvariable, get_variable, add +from esphome.cpp_types import App +from esphome.components.sensor import setup_sensor + +DEPENDENCIES = ['binary_sensor'] + +BinarySensorMap = sensor.sensor_ns.class_('BinarySensorMap', sensor.Sensor) + +SensorMapType = sensor.sensor_ns.enum('SensorMapType') +SENSOR_MAP_TYPES = { + 'GROUP': SensorMapType.BINARY_SENSOR_MAP_TYPE_GROUP, +} + +entry = { + vol.Required(CONF_CHANNEL): cv.use_variable_id(binary_sensor.BinarySensor), + vol.Required(CONF_VALUE): vol.All(cv.positive_int, vol.Range(min=0, max=255)), +} + +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(BinarySensorMap), + vol.Required(CONF_TYPE): cv.one_of(*SENSOR_MAP_TYPES, upper=True), + vol.Required(CONF_CHANNELS): cv.ensure_list(entry), +})) + + +def to_code(config): + rhs = App.make_binary_sensor_map(config[CONF_NAME]) + var = Pvariable(config[CONF_ID], rhs) + setup_sensor(var, config) + if CONF_TYPE in config: + constant = SENSOR_MAP_TYPES[config[CONF_TYPE]] + add(var.set_sensor_type(constant)) + + for ch in config[CONF_CHANNELS]: + for input_var in get_variable(ch[CONF_CHANNEL]): + yield + add(var.add_sensor(input_var, ch[CONF_VALUE])) + + add(App.register_sensor(var)) + + +BUILD_FLAGS = '-DUSE_BINARY_SENSOR_MAP' \ No newline at end of file From 2bf5353eaf29e19c5bf4a5e1924df36d67e3e460 Mon Sep 17 00:00:00 2001 From: Michiel van Turnhout Date: Thu, 16 May 2019 20:27:05 +0200 Subject: [PATCH 3/5] fixed python and C++ code for new framework --- .../components/binary_sensor_map/__init__.py | 0 .../binary_sensor_map/binary_sensor_map.cpp | 4 -- .../binary_sensor_map/binary_sensor_map.h | 3 +- .../binary_sensor_map/binary_sensor_map.py | 47 ------------------- .../components/binary_sensor_map/sensor.py | 38 +++++++++++++++ 5 files changed, 39 insertions(+), 53 deletions(-) create mode 100644 esphome/components/binary_sensor_map/__init__.py delete mode 100644 esphome/components/binary_sensor_map/binary_sensor_map.py create mode 100644 esphome/components/binary_sensor_map/sensor.py diff --git a/esphome/components/binary_sensor_map/__init__.py b/esphome/components/binary_sensor_map/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/binary_sensor_map/binary_sensor_map.cpp b/esphome/components/binary_sensor_map/binary_sensor_map.cpp index a418066da1..038cc2e5bb 100644 --- a/esphome/components/binary_sensor_map/binary_sensor_map.cpp +++ b/esphome/components/binary_sensor_map/binary_sensor_map.cpp @@ -6,8 +6,6 @@ namespace binary_sensor_map { static const char *TAG = "sensor.binary_sensor_map"; -BinarySensorMap::BinarySensorMap(const std::string &name) : Sensor(name) {} - void BinarySensorMap::dump_config() { LOG_SENSOR(" ", "binary_sensor_map", this); } void BinarySensorMap::loop() { @@ -54,8 +52,6 @@ void BinarySensorMap::process_group_() { } } -float BinarySensorMap::get_setup_priority() const { return setup_priority::HARDWARE_LATE; } - void BinarySensorMap::add_sensor(binary_sensor::BinarySensor *sensor, float value) { BinarySensorMapChannel *sensor_channel = new BinarySensorMapChannel; sensor_channel->binary_sensor = sensor; diff --git a/esphome/components/binary_sensor_map/binary_sensor_map.h b/esphome/components/binary_sensor_map/binary_sensor_map.h index a140ff93ba..5ac5c879a4 100644 --- a/esphome/components/binary_sensor_map/binary_sensor_map.h +++ b/esphome/components/binary_sensor_map/binary_sensor_map.h @@ -22,7 +22,6 @@ struct BinarySensorMapChannel { */ class BinarySensorMap : public sensor::Sensor, public Component { public: - BinarySensorMap(const std::string &name); void dump_config() override; /** * The loop checks all binary_sensor states @@ -33,7 +32,7 @@ class BinarySensorMap : public sensor::Sensor, public Component { * average value. When the value changed and no sensors ar active we publish NAN. * */ void loop() override; - float get_setup_priority() const override; + float get_setup_priority() const override { return setup_priority::LATE; } /** Add binary_sensors to the group. * Each binary_sensor represents a float value when its state is true * diff --git a/esphome/components/binary_sensor_map/binary_sensor_map.py b/esphome/components/binary_sensor_map/binary_sensor_map.py deleted file mode 100644 index d1222ba460..0000000000 --- a/esphome/components/binary_sensor_map/binary_sensor_map.py +++ /dev/null @@ -1,47 +0,0 @@ -import voluptuous as vol - -from esphome.components import sensor, binary_sensor -import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_NAME, CONF_CHANNELS, CONF_CHANNEL, CONF_VALUE, CONF_TYPE -from esphome.cpp_generator import Pvariable, get_variable, add -from esphome.cpp_types import App -from esphome.components.sensor import setup_sensor - -DEPENDENCIES = ['binary_sensor'] - -BinarySensorMap = sensor.sensor_ns.class_('BinarySensorMap', sensor.Sensor) - -SensorMapType = sensor.sensor_ns.enum('SensorMapType') -SENSOR_MAP_TYPES = { - 'GROUP': SensorMapType.BINARY_SENSOR_MAP_TYPE_GROUP, -} - -entry = { - vol.Required(CONF_CHANNEL): cv.use_variable_id(binary_sensor.BinarySensor), - vol.Required(CONF_VALUE): vol.All(cv.positive_int, vol.Range(min=0, max=255)), -} - -PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ - cv.GenerateID(): cv.declare_variable_id(BinarySensorMap), - vol.Required(CONF_TYPE): cv.one_of(*SENSOR_MAP_TYPES, upper=True), - vol.Required(CONF_CHANNELS): cv.ensure_list(entry), -})) - - -def to_code(config): - rhs = App.make_binary_sensor_map(config[CONF_NAME]) - var = Pvariable(config[CONF_ID], rhs) - setup_sensor(var, config) - if CONF_TYPE in config: - constant = SENSOR_MAP_TYPES[config[CONF_TYPE]] - add(var.set_sensor_type(constant)) - - for ch in config[CONF_CHANNELS]: - for input_var in get_variable(ch[CONF_CHANNEL]): - yield - add(var.add_sensor(input_var, ch[CONF_VALUE])) - - add(App.register_sensor(var)) - - -BUILD_FLAGS = '-DUSE_BINARY_SENSOR_MAP' \ No newline at end of file diff --git a/esphome/components/binary_sensor_map/sensor.py b/esphome/components/binary_sensor_map/sensor.py new file mode 100644 index 0000000000..2709e0df1c --- /dev/null +++ b/esphome/components/binary_sensor_map/sensor.py @@ -0,0 +1,38 @@ +import esphome.codegen as cg +import esphome.config_validation as cv + +from esphome.components import sensor, binary_sensor +from esphome.const import CONF_ID, CONF_NAME, CONF_CHANNELS, CONF_CHANNEL, CONF_VALUE, CONF_TYPE + +DEPENDENCIES = ['binary_sensor'] + +binary_sensor_map_ns = cg.esphome_ns.namespace('binary_sensor_map') +BinarySensorMap = binary_sensor_map_ns.class_('BinarySensorMap', cg.Component) +SensorMapType = binary_sensor_map_ns.enum('SensorMapType') +SENSOR_MAP_TYPES = { + 'GROUP': SensorMapType.BINARY_SENSOR_MAP_TYPE_GROUP, +} + +entry = { + cv.Required(CONF_CHANNEL): cv.use_id(binary_sensor.BinarySensor), + cv.Required(CONF_VALUE): cv.All(cv.positive_int, cv.Range(min=0, max=255)), +} + +CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend({ + cv.GenerateID(): cv.declare_id(BinarySensorMap), + cv.Required(CONF_TYPE): cv.one_of(*SENSOR_MAP_TYPES, upper=True), + cv.Required(CONF_CHANNELS): cv.ensure_list(entry), +}) + + +def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + yield cg.register_component(var, config) + yield sensor.register_sensor(var, config) + if CONF_TYPE in config: + constant = SENSOR_MAP_TYPES[config[CONF_TYPE]] + cg.add(var.set_sensor_type(constant)) + + for ch in config[CONF_CHANNELS]: + input_var = yield cg.get_variable(ch[CONF_CHANNEL]) + cg.add(var.add_sensor(input_var,ch[CONF_VALUE])) \ No newline at end of file From f31a9ad9efd780d3ab68ffda89504ab50e768c83 Mon Sep 17 00:00:00 2001 From: mvturnho Date: Fri, 17 May 2019 13:36:11 +0200 Subject: [PATCH 4/5] renamed add_sensor to add_channel --- esphome/components/binary_sensor_map/binary_sensor_map.cpp | 2 +- esphome/components/binary_sensor_map/binary_sensor_map.h | 2 +- esphome/components/binary_sensor_map/sensor.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/binary_sensor_map/binary_sensor_map.cpp b/esphome/components/binary_sensor_map/binary_sensor_map.cpp index 038cc2e5bb..ab02ae7a07 100644 --- a/esphome/components/binary_sensor_map/binary_sensor_map.cpp +++ b/esphome/components/binary_sensor_map/binary_sensor_map.cpp @@ -52,7 +52,7 @@ void BinarySensorMap::process_group_() { } } -void BinarySensorMap::add_sensor(binary_sensor::BinarySensor *sensor, float value) { +void BinarySensorMap::add_channel(binary_sensor::BinarySensor *sensor, float value) { BinarySensorMapChannel *sensor_channel = new BinarySensorMapChannel; sensor_channel->binary_sensor = sensor; sensor_channel->sensor_value = value; diff --git a/esphome/components/binary_sensor_map/binary_sensor_map.h b/esphome/components/binary_sensor_map/binary_sensor_map.h index 5ac5c879a4..4ca25d3b31 100644 --- a/esphome/components/binary_sensor_map/binary_sensor_map.h +++ b/esphome/components/binary_sensor_map/binary_sensor_map.h @@ -39,7 +39,7 @@ class BinarySensorMap : public sensor::Sensor, public Component { * @param *sensor The binary sensor. * @param value The value this binary_sensor represents */ - void add_sensor(binary_sensor::BinarySensor *sensor, float value); + void add_channel(binary_sensor::BinarySensor *sensor, float value); void set_sensor_type(BinarySensorMapType sensor_type); protected: diff --git a/esphome/components/binary_sensor_map/sensor.py b/esphome/components/binary_sensor_map/sensor.py index 2709e0df1c..9377ae6879 100644 --- a/esphome/components/binary_sensor_map/sensor.py +++ b/esphome/components/binary_sensor_map/sensor.py @@ -35,4 +35,4 @@ def to_code(config): for ch in config[CONF_CHANNELS]: input_var = yield cg.get_variable(ch[CONF_CHANNEL]) - cg.add(var.add_sensor(input_var,ch[CONF_VALUE])) \ No newline at end of file + cg.add(var.add_channel(input_var, ch[CONF_VALUE])) From 5b6f117f70f4cdf41b59f82abd35609ee9e1584b Mon Sep 17 00:00:00 2001 From: mvturnho Date: Fri, 17 May 2019 15:04:16 +0200 Subject: [PATCH 5/5] travis --- esphome/components/binary_sensor_map/binary_sensor_map.cpp | 2 +- esphome/components/binary_sensor_map/binary_sensor_map.h | 2 +- esphome/components/binary_sensor_map/sensor.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/binary_sensor_map/binary_sensor_map.cpp b/esphome/components/binary_sensor_map/binary_sensor_map.cpp index ab02ae7a07..9d5b95a68c 100644 --- a/esphome/components/binary_sensor_map/binary_sensor_map.cpp +++ b/esphome/components/binary_sensor_map/binary_sensor_map.cpp @@ -62,4 +62,4 @@ void BinarySensorMap::add_channel(binary_sensor::BinarySensor *sensor, float val void BinarySensorMap::set_sensor_type(BinarySensorMapType sensor_type) { this->sensor_type_ = sensor_type; } } // namespace binary_sensor_map -} // namespace esphome \ No newline at end of file +} // namespace esphome diff --git a/esphome/components/binary_sensor_map/binary_sensor_map.h b/esphome/components/binary_sensor_map/binary_sensor_map.h index 4ca25d3b31..b6c1dc17e5 100644 --- a/esphome/components/binary_sensor_map/binary_sensor_map.h +++ b/esphome/components/binary_sensor_map/binary_sensor_map.h @@ -56,4 +56,4 @@ class BinarySensorMap : public sensor::Sensor, public Component { }; } // namespace binary_sensor_map -} // namespace esphome \ No newline at end of file +} // namespace esphome diff --git a/esphome/components/binary_sensor_map/sensor.py b/esphome/components/binary_sensor_map/sensor.py index 9377ae6879..b48e2c4c2f 100644 --- a/esphome/components/binary_sensor_map/sensor.py +++ b/esphome/components/binary_sensor_map/sensor.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, binary_sensor -from esphome.const import CONF_ID, CONF_NAME, CONF_CHANNELS, CONF_CHANNEL, CONF_VALUE, CONF_TYPE +from esphome.const import CONF_ID, CONF_CHANNELS, CONF_CHANNEL, CONF_VALUE, CONF_TYPE DEPENDENCIES = ['binary_sensor']