Browse Source

Added multitouch to binary_sensor.

pull/17/head
Maurice Makaay 3 years ago
parent
commit
b4ac059492
2 changed files with 77 additions and 35 deletions
  1. +55
    -19
      binary_sensor/__init__.py
  2. +22
    -16
      binary_sensor/touch_binary_sensor.h

+ 55
- 19
binary_sensor/__init__.py View File

@ -1,7 +1,8 @@
import re
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import binary_sensor from esphome.components import binary_sensor
from esphome.const import CONF_ID
from esphome.const import CONF_ID, CONF_FOR
from .. import ( from .. import (
bslamp2_ns, CODEOWNERS, bslamp2_ns, CODEOWNERS,
CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL CONF_FRONT_PANEL_HAL_ID, FrontPanelHAL
@ -11,29 +12,63 @@ AUTO_LOAD = ["xiaomi_bslamp2"]
CONF_PART = "part" CONF_PART = "part"
# The identifier values match the bit values of the events as defined
# in ../front_panel_hal.h.
PARTS = { PARTS = {
"ANY" : 0,
"POWER_BUTTON" : 1,
"POWER" : 1,
"COLOR_BUTTON" : 2,
"COLOR" : 2,
"SLIDER" : 3,
"POWER_BUTTON" : 0b001 << 1,
"POWER" : 0b001 << 1,
"COLOR_BUTTON" : 0b010 << 1,
"COLOR" : 0b010 << 1,
"SLIDER" : 0b100 << 1,
} }
def validate_part(value):
value = cv.string(value)
return cv.enum(PARTS, upper=True, space='_')(value)
XiaomiBslamp2TouchBinarySensor = bslamp2_ns.class_( XiaomiBslamp2TouchBinarySensor = bslamp2_ns.class_(
"XiaomiBslamp2TouchBinarySensor", binary_sensor.BinarySensor, cg.Component) "XiaomiBslamp2TouchBinarySensor", binary_sensor.BinarySensor, cg.Component)
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(XiaomiBslamp2TouchBinarySensor),
cv.GenerateID(CONF_FRONT_PANEL_HAL_ID): cv.use_id(FrontPanelHAL),
cv.Optional(CONF_PART, default="ANY"): validate_part,
}
).extend(cv.COMPONENT_SCHEMA)
def get_part_id(value):
normalized = re.sub('\s+', '_', value.upper())
try:
return PARTS[normalized]
except KeyError:
raise cv.Invalid(f"[{value}] is not a valid part identifier")
def validate_for(value):
parts = set()
if isinstance(value, str):
parts.add(get_part_id(value))
elif isinstance(value, list):
for x in value:
parts.add(get_part_id(x))
else:
cv.Invalid("The value must be a single part identifier or a list of identifiers.")
return list(parts)
def validate_part(value):
return [ get_part_id(value) ]
def validate_binary_sensor(conf):
if CONF_PART in conf and CONF_FOR in conf:
raise cv.Invalid("Specify only one of [part] or [for]")
if CONF_PART in conf and not CONF_FOR in conf:
conf[CONF_FOR] = conf[CONF_PART]
if CONF_FOR not in conf:
raise cv.Invalid("'for' is a required option for [binary_sensor.xiaomi_bslamp2]")
return conf
CONFIG_SCHEMA = cv.All(
binary_sensor.BINARY_SENSOR_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(XiaomiBslamp2TouchBinarySensor),
cv.GenerateID(CONF_FRONT_PANEL_HAL_ID): cv.use_id(FrontPanelHAL),
# This option is not advertised in the documentation. It must be
# considered deprecated. I'm not announcing it as such yet. Not sure
# if it's useful to do so.
cv.Optional(CONF_PART): validate_part,
cv.Optional(CONF_FOR): validate_for,
}
).extend(cv.COMPONENT_SCHEMA),
validate_binary_sensor,
)
def to_code(config): def to_code(config):
var = cg.new_Pvariable(config[CONF_ID]) var = cg.new_Pvariable(config[CONF_ID])
@ -42,4 +77,5 @@ def to_code(config):
front_panel_hal_var = yield cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID]) front_panel_hal_var = yield cg.get_variable(config[CONF_FRONT_PANEL_HAL_ID])
cg.add(var.set_parent(front_panel_hal_var)) cg.add(var.set_parent(front_panel_hal_var))
cg.add(var.set_part(config[CONF_PART]))
for part_id in config[CONF_FOR]:
cg.add(var.include_part(part_id))

+ 22
- 16
binary_sensor/touch_binary_sensor.h View File

@ -18,38 +18,44 @@ public:
front_panel_ = front_panel; front_panel_ = front_panel;
} }
void set_part(int part) {
part_ = part;
void include_part(int part) {
match_ = match_ | part;
} }
void setup() { void setup() {
front_panel_->add_on_event_callback( front_panel_->add_on_event_callback(
[this](EVENT ev) { [this](EVENT ev) {
// Filter events by part, when requested.
if (part_ > 0) {
if ((ev & FLAG_PART_MASK) != (part_ << FLAG_PART_SHIFT)) {
return;
}
auto part = ev & FLAG_PART_MASK;
auto is_touch = (ev & FLAG_TYPE_MASK) == FLAG_TYPE_TOUCH;
if (is_touch) {
active_ = active_ | part;
} else {
active_ = active_ & ~part;
} }
// Publish the new state, based on the touch/release status..
auto on_or_off = (ev & FLAG_TYPE_MASK) == FLAG_TYPE_TOUCH;
this->publish_state(on_or_off);
this->publish_state(active_ == match_);
} }
); );
} }
void dump_config() { void dump_config() {
ESP_LOGCONFIG(TAG, "Front panel binary_sensor:"); ESP_LOGCONFIG(TAG, "Front panel binary_sensor:");
ESP_LOGCONFIG(TAG, " Part: %s (id %d)",
(part_ == 1 ? "power button" :
part_ == 2 ? "color button" :
part_ == 3 ? "slider" : "any"),
part_);
ESP_LOGCONFIG(TAG, " Part(s):");
if ((match_ & FLAG_PART_POWER) == FLAG_PART_POWER) {
ESP_LOGCONFIG(TAG, " - Power button");
}
if ((match_ & FLAG_PART_COLOR) == FLAG_PART_COLOR) {
ESP_LOGCONFIG(TAG, " - Color button");
}
if ((match_ & FLAG_PART_SLIDER) == FLAG_PART_SLIDER) {
ESP_LOGCONFIG(TAG, " - Slider");
}
} }
protected: protected:
FrontPanelHAL *front_panel_; FrontPanelHAL *front_panel_;
EVENT part_;
EVENT match_ = 0;
EVENT active_ = 0;
}; };
} // namespace bslamp2 } // namespace bslamp2


Loading…
Cancel
Save