mirror of
https://github.com/esphome/esphome.git
synced 2024-12-01 03:04:12 +01:00
binary sensors
This commit is contained in:
parent
193a98bfb6
commit
71b0cfbd1f
4 changed files with 117 additions and 39 deletions
|
@ -1,18 +1,65 @@
|
|||
# import esphome.codegen as cg
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.const import (
|
||||
CONF_ACTIVE,
|
||||
CONF_NAME,
|
||||
DEVICE_CLASS_VIBRATION,
|
||||
ICON_VIBRATE,
|
||||
)
|
||||
from . import MSA3xxComponent, CONF_MSA3XX_ID
|
||||
|
||||
CODEOWNERS = ["@latonita"]
|
||||
DEPENDENCIES = ["msa3xx"]
|
||||
|
||||
CONF_TAP = "tap"
|
||||
CONF_DOUBLE_TAP = "double_tap"
|
||||
|
||||
ICON_TAP = "mdi:gesture-tap"
|
||||
ICON_DOUBLE_TAP = "mdi:gesture-double-tap"
|
||||
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_MSA3XX_ID): cv.use_id(MSA3xxComponent),
|
||||
cv.Optional(CONF_TAP): cv.maybe_simple_value(
|
||||
binary_sensor.binary_sensor_schema(
|
||||
device_class=DEVICE_CLASS_VIBRATION,
|
||||
icon=ICON_TAP,
|
||||
),
|
||||
key=CONF_NAME,
|
||||
),
|
||||
cv.Optional(CONF_DOUBLE_TAP): cv.maybe_simple_value(
|
||||
binary_sensor.binary_sensor_schema(
|
||||
device_class=DEVICE_CLASS_VIBRATION,
|
||||
icon=ICON_DOUBLE_TAP,
|
||||
),
|
||||
key=CONF_NAME,
|
||||
),
|
||||
cv.Optional(CONF_ACTIVE): cv.maybe_simple_value(
|
||||
binary_sensor.binary_sensor_schema(
|
||||
device_class=DEVICE_CLASS_VIBRATION,
|
||||
icon=ICON_VIBRATE,
|
||||
),
|
||||
key=CONF_NAME,
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
)
|
||||
|
||||
|
||||
# async def to_code(config):
|
||||
async def to_code(config):
|
||||
hub = await cg.get_variable(config[CONF_MSA3XX_ID])
|
||||
|
||||
if CONF_TAP in config:
|
||||
sens = await binary_sensor.new_binary_sensor(config[CONF_TAP])
|
||||
cg.add(hub.set_tap_binary_sensor(sens))
|
||||
|
||||
if CONF_DOUBLE_TAP in config:
|
||||
sens = await binary_sensor.new_binary_sensor(config[CONF_DOUBLE_TAP])
|
||||
cg.add(hub.set_double_tap_binary_sensor(sens))
|
||||
|
||||
if CONF_ACTIVE in config:
|
||||
sens = await binary_sensor.new_binary_sensor(config[CONF_ACTIVE])
|
||||
cg.add(hub.set_active_binary_sensor(sens))
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "msa3xx.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
namespace esphome {
|
||||
|
@ -16,6 +17,10 @@ const float G_OFFSET_MAX = 4.5f; // -127...127 LSB = +- 0.4953g = +- 4.857 m/s
|
|||
|
||||
const uint8_t RESOLUTION[] = {14, 12, 10, 8};
|
||||
|
||||
const uint32_t TAP_COOLDOWN_MS = 500;
|
||||
const uint32_t DOUBLE_TAP_COOLDOWN_MS = 500;
|
||||
const uint32_t ACTIVITY_COOLDOWN_MS = 500;
|
||||
|
||||
const char *model_to_string(Model model) {
|
||||
switch (model) {
|
||||
case Model::MSA301:
|
||||
|
@ -166,6 +171,12 @@ void MSA3xxComponent::dump_config() {
|
|||
YESNO(this->swap_.y_polarity), YESNO(this->swap_.z_polarity), YESNO(this->swap_.x_y_swap));
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
LOG_BINARY_SENSOR(" ", "Tap", this->tap_binary_sensor_);
|
||||
LOG_BINARY_SENSOR(" ", "Double Tap", this->double_tap_binary_sensor_);
|
||||
LOG_BINARY_SENSOR(" ", "Active", this->active_binary_sensor_);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
LOG_SENSOR(" ", "Acceleration X", this->acceleration_x_sensor_);
|
||||
LOG_SENSOR(" ", "Acceleration Y", this->acceleration_y_sensor_);
|
||||
|
@ -226,17 +237,14 @@ void MSA3xxComponent::loop() {
|
|||
return;
|
||||
}
|
||||
|
||||
RegMotionInterrupt old_motion_int = this->status_.motion_int;
|
||||
|
||||
if (!this->read_data_() || !this->read_motion_status_()) {
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
|
||||
// ESP_LOGVV(TAG, "Got raw data {x=%5d, y=%5d, z=%5d}, accel={x=%+1.3f m/s², y=%+1.3f m/s², z=%+1.3f m/s²}",
|
||||
// this->data_.lsb_x, this->data_.lsb_y, this->data_.lsb_z, this->data_.x, this->data_.y, this->data_.z);
|
||||
// ESP_LOGV(TAG, "Orientation XY(%s), Z(%s)", orientation_xy_to_string(this->status_.orientation.orient_xy),
|
||||
// orientation_z_to_string(this->status_.orientation.orient_z));
|
||||
|
||||
this->process_interrupts_();
|
||||
this->process_motions_(old_motion_int);
|
||||
}
|
||||
|
||||
void MSA3xxComponent::update() {
|
||||
|
@ -263,17 +271,18 @@ void MSA3xxComponent::update() {
|
|||
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
if (this->orientation_xy_text_sensor_ != nullptr &&
|
||||
this->status_.orientation.orient_xy != this->status_.orientation_old.orient_xy) {
|
||||
(this->status_.orientation.orient_xy != this->status_.orientation_old.orient_xy ||
|
||||
this->status_.never_published)) {
|
||||
this->orientation_xy_text_sensor_->publish_state(orientation_xy_to_string(this->status_.orientation.orient_xy));
|
||||
}
|
||||
if (this->orientation_z_text_sensor_ != nullptr &&
|
||||
this->status_.orientation.orient_z != this->status_.orientation_old.orient_z) {
|
||||
(this->status_.orientation.orient_z != this->status_.orientation_old.orient_z || this->status_.never_published)) {
|
||||
this->orientation_z_text_sensor_->publish_state(orientation_z_to_string(this->status_.orientation.orient_z));
|
||||
}
|
||||
this->status_.orientation_old = this->status_.orientation;
|
||||
|
||||
#endif
|
||||
|
||||
this->status_.never_published = false;
|
||||
this->status_clear_warning();
|
||||
}
|
||||
float MSA3xxComponent::get_setup_priority() const { return setup_priority::DATA; }
|
||||
|
@ -359,30 +368,37 @@ int64_t MSA3xxComponent::twos_complement_(uint64_t value, uint8_t bits) {
|
|||
}
|
||||
}
|
||||
|
||||
void MSA3xxComponent::process_interrupts_() {
|
||||
if (this->status_.motion_int.raw == 0) {
|
||||
return;
|
||||
void binary_event_debounce(bool state, bool old_state, uint32_t now, uint32_t &last_ms, Trigger<> &trigger,
|
||||
uint32_t cooldown_ms, binary_sensor::BinarySensor *bs, const char *desc) {
|
||||
if (state && now - last_ms > cooldown_ms) {
|
||||
ESP_LOGV(TAG, "%s detected", desc);
|
||||
trigger.trigger();
|
||||
last_ms = now;
|
||||
if (bs != nullptr) {
|
||||
bs->publish_state(true);
|
||||
}
|
||||
} else if (!state && now - last_ms > cooldown_ms && bs != nullptr) {
|
||||
bs->publish_state(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->status_.motion_int.single_tap_interrupt) {
|
||||
ESP_LOGW(TAG, "Single Tap detected");
|
||||
this->tap_trigger_.trigger();
|
||||
}
|
||||
void MSA3xxComponent::process_motions_(RegMotionInterrupt old) {
|
||||
uint32_t now = millis();
|
||||
|
||||
if (this->status_.motion_int.double_tap_interrupt) {
|
||||
ESP_LOGW(TAG, "Double Tap detected");
|
||||
this->double_tap_trigger_.trigger();
|
||||
}
|
||||
binary_event_debounce(this->status_.motion_int.single_tap_interrupt, old.single_tap_interrupt, now,
|
||||
this->status_.last_tap_ms, this->tap_trigger_, TAP_COOLDOWN_MS, this->tap_binary_sensor_,
|
||||
"Tap");
|
||||
binary_event_debounce(this->status_.motion_int.double_tap_interrupt, old.double_tap_interrupt, now,
|
||||
this->status_.last_double_tap_ms, this->double_tap_trigger_, DOUBLE_TAP_COOLDOWN_MS,
|
||||
this->double_tap_binary_sensor_, "Double Tap");
|
||||
binary_event_debounce(this->status_.motion_int.active_interrupt, old.active_interrupt, now,
|
||||
this->status_.last_action_ms, this->active_trigger_, ACTIVITY_COOLDOWN_MS,
|
||||
this->active_binary_sensor_, "Activity");
|
||||
|
||||
if (this->status_.motion_int.orientation_interrupt) {
|
||||
ESP_LOGW(TAG, "Orientation changed");
|
||||
ESP_LOGVV(TAG, "Orientation changed");
|
||||
this->orientation_trigger_.trigger();
|
||||
}
|
||||
|
||||
if (this->status_.motion_int.active_interrupt) {
|
||||
ESP_LOGW(TAG, "Activity detected");
|
||||
this->active_trigger_.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace msa3xx
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/text_sensor/text_sensor.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
@ -118,7 +119,7 @@ union Orientation {
|
|||
OrientationXY xy : 2;
|
||||
bool z : 1;
|
||||
uint8_t reserved : 5;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
uint8_t raw;
|
||||
};
|
||||
|
||||
|
@ -133,7 +134,7 @@ union RegMotionInterrupt {
|
|||
bool single_tap_interrupt : 1;
|
||||
bool orientation_interrupt : 1;
|
||||
bool reserved_7 : 1;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
uint8_t raw;
|
||||
};
|
||||
|
||||
|
@ -144,7 +145,7 @@ union RegOrientationStatus {
|
|||
OrientationXY orient_xy : 2;
|
||||
bool orient_z : 1;
|
||||
uint8_t reserved_7 : 1;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
uint8_t raw{0x00};
|
||||
};
|
||||
|
||||
|
@ -154,7 +155,7 @@ union RegRangeResolution {
|
|||
Range range : 2;
|
||||
Resolution resolution : 2;
|
||||
uint8_t reserved_2 : 4;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
uint8_t raw{0x00};
|
||||
};
|
||||
|
||||
|
@ -166,7 +167,7 @@ union RegOutputDataRate {
|
|||
bool z_axis_disable : 1;
|
||||
bool y_axis_disable : 1;
|
||||
bool x_axis_disable : 1;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
uint8_t raw{0xde};
|
||||
};
|
||||
|
||||
|
@ -177,7 +178,7 @@ union RegPowerModeBandwidth {
|
|||
Bandwidth low_power_bandwidth : 4;
|
||||
uint8_t reserved_5 : 1;
|
||||
PowerMode power_mode : 2;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
uint8_t raw{0xde};
|
||||
};
|
||||
|
||||
|
@ -189,7 +190,7 @@ union RegSwapPolarity {
|
|||
bool y_polarity : 1;
|
||||
bool x_polarity : 1;
|
||||
uint8_t reserved : 4;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
uint8_t raw{0};
|
||||
};
|
||||
|
||||
|
@ -200,7 +201,7 @@ union RegTapDuration {
|
|||
uint8_t reserved : 3;
|
||||
bool tap_shock : 1;
|
||||
bool tap_quiet : 1;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
uint8_t raw{0x04};
|
||||
};
|
||||
|
||||
|
@ -221,6 +222,12 @@ class MSA3xxComponent : public PollingComponent, public i2c::I2CDevice {
|
|||
void set_resolution(Resolution resolution) { this->resolution_ = resolution; }
|
||||
void set_transform(bool mirror_x, bool mirror_y, bool mirror_z, bool swap_xy);
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
SUB_BINARY_SENSOR(tap)
|
||||
SUB_BINARY_SENSOR(double_tap)
|
||||
SUB_BINARY_SENSOR(active)
|
||||
#endif
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
SUB_SENSOR(acceleration_x)
|
||||
SUB_SENSOR(acceleration_y)
|
||||
|
@ -263,6 +270,12 @@ class MSA3xxComponent : public PollingComponent, public i2c::I2CDevice {
|
|||
RegMotionInterrupt motion_int;
|
||||
RegOrientationStatus orientation;
|
||||
RegOrientationStatus orientation_old;
|
||||
|
||||
uint32_t last_tap_ms{0};
|
||||
uint32_t last_double_tap_ms{0};
|
||||
uint32_t last_action_ms{0};
|
||||
|
||||
bool never_published{true};
|
||||
} status_{};
|
||||
|
||||
void setup_odr_(DataRate rate);
|
||||
|
@ -284,7 +297,7 @@ class MSA3xxComponent : public PollingComponent, public i2c::I2CDevice {
|
|||
Trigger<> freefall_trigger_;
|
||||
Trigger<> active_trigger_;
|
||||
|
||||
void process_interrupts_();
|
||||
void process_motions_(RegMotionInterrupt old);
|
||||
};
|
||||
|
||||
} // namespace msa3xx
|
||||
|
|
|
@ -12,16 +12,18 @@ DEPENDENCIES = ["msa3xx"]
|
|||
CONF_ORIENTATION_XY = "orientation_xy"
|
||||
CONF_ORIENTATION_Z = "orientation_z"
|
||||
|
||||
ICON_SCREEN_ROTATION = "mdi:screen-rotation"
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_MSA3XX_ID): cv.use_id(MSA3xxComponent),
|
||||
cv.Optional(CONF_ORIENTATION_XY): cv.maybe_simple_value(
|
||||
text_sensor.text_sensor_schema(),
|
||||
text_sensor.text_sensor_schema(icon=ICON_SCREEN_ROTATION),
|
||||
key=CONF_NAME,
|
||||
),
|
||||
cv.Optional(CONF_ORIENTATION_Z): cv.maybe_simple_value(
|
||||
text_sensor.text_sensor_schema(),
|
||||
text_sensor.text_sensor_schema(icon=ICON_SCREEN_ROTATION),
|
||||
key=CONF_NAME,
|
||||
),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue