mirror of
https://github.com/esphome/esphome.git
synced 2024-11-10 01:07:45 +01:00
Add Grow Fingerprint Reader (#1356)
This commit is contained in:
parent
cc6d1e85cc
commit
4d7c1ae143
8 changed files with 1176 additions and 0 deletions
|
@ -36,6 +36,7 @@ esphome/components/ds1307/* @badbadc0ffee
|
||||||
esphome/components/exposure_notifications/* @OttoWinter
|
esphome/components/exposure_notifications/* @OttoWinter
|
||||||
esphome/components/ezo/* @ssieb
|
esphome/components/ezo/* @ssieb
|
||||||
esphome/components/fastled_base/* @OttoWinter
|
esphome/components/fastled_base/* @OttoWinter
|
||||||
|
esphome/components/fingerprint_grow/* @OnFreund @loongyh
|
||||||
esphome/components/globals/* @esphome/core
|
esphome/components/globals/* @esphome/core
|
||||||
esphome/components/gpio/* @esphome/core
|
esphome/components/gpio/* @esphome/core
|
||||||
esphome/components/gps/* @coogle
|
esphome/components/gps/* @coogle
|
||||||
|
|
293
esphome/components/fingerprint_grow/__init__.py
Normal file
293
esphome/components/fingerprint_grow/__init__.py
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome import automation
|
||||||
|
from esphome import pins
|
||||||
|
from esphome.components import uart
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_COLOR,
|
||||||
|
CONF_COUNT,
|
||||||
|
CONF_FINGER_ID,
|
||||||
|
CONF_ID,
|
||||||
|
CONF_NEW_PASSWORD,
|
||||||
|
CONF_NUM_SCANS,
|
||||||
|
CONF_ON_ENROLLMENT_DONE,
|
||||||
|
CONF_ON_ENROLLMENT_FAILED,
|
||||||
|
CONF_ON_ENROLLMENT_SCAN,
|
||||||
|
CONF_ON_FINGER_SCAN_MATCHED,
|
||||||
|
CONF_ON_FINGER_SCAN_UNMATCHED,
|
||||||
|
CONF_PASSWORD,
|
||||||
|
CONF_SENSING_PIN,
|
||||||
|
CONF_SPEED,
|
||||||
|
CONF_STATE,
|
||||||
|
CONF_TRIGGER_ID,
|
||||||
|
)
|
||||||
|
|
||||||
|
CODEOWNERS = ["@OnFreund", "@loongyh"]
|
||||||
|
DEPENDENCIES = ["uart"]
|
||||||
|
AUTO_LOAD = ["binary_sensor", "sensor"]
|
||||||
|
MULTI_CONF = True
|
||||||
|
|
||||||
|
CONF_FINGERPRINT_GROW_ID = "fingerprint_grow_id"
|
||||||
|
|
||||||
|
fingerprint_grow_ns = cg.esphome_ns.namespace("fingerprint_grow")
|
||||||
|
FingerprintGrowComponent = fingerprint_grow_ns.class_(
|
||||||
|
"FingerprintGrowComponent", cg.PollingComponent, uart.UARTDevice
|
||||||
|
)
|
||||||
|
|
||||||
|
FingerScanMatchedTrigger = fingerprint_grow_ns.class_(
|
||||||
|
"FingerScanMatchedTrigger", automation.Trigger.template(cg.uint16, cg.uint16)
|
||||||
|
)
|
||||||
|
|
||||||
|
FingerScanUnmatchedTrigger = fingerprint_grow_ns.class_(
|
||||||
|
"FingerScanUnmatchedTrigger", automation.Trigger.template()
|
||||||
|
)
|
||||||
|
|
||||||
|
EnrollmentScanTrigger = fingerprint_grow_ns.class_(
|
||||||
|
"EnrollmentScanTrigger", automation.Trigger.template(cg.uint8, cg.uint16)
|
||||||
|
)
|
||||||
|
|
||||||
|
EnrollmentDoneTrigger = fingerprint_grow_ns.class_(
|
||||||
|
"EnrollmentDoneTrigger", automation.Trigger.template(cg.uint16)
|
||||||
|
)
|
||||||
|
|
||||||
|
EnrollmentFailedTrigger = fingerprint_grow_ns.class_(
|
||||||
|
"EnrollmentFailedTrigger", automation.Trigger.template(cg.uint16)
|
||||||
|
)
|
||||||
|
|
||||||
|
EnrollmentAction = fingerprint_grow_ns.class_("EnrollmentAction", automation.Action)
|
||||||
|
CancelEnrollmentAction = fingerprint_grow_ns.class_(
|
||||||
|
"CancelEnrollmentAction", automation.Action
|
||||||
|
)
|
||||||
|
DeleteAction = fingerprint_grow_ns.class_("DeleteAction", automation.Action)
|
||||||
|
DeleteAllAction = fingerprint_grow_ns.class_("DeleteAllAction", automation.Action)
|
||||||
|
LEDControlAction = fingerprint_grow_ns.class_("LEDControlAction", automation.Action)
|
||||||
|
AuraLEDControlAction = fingerprint_grow_ns.class_(
|
||||||
|
"AuraLEDControlAction", automation.Action
|
||||||
|
)
|
||||||
|
|
||||||
|
AuraLEDState = fingerprint_grow_ns.enum("GrowAuraLEDState", True)
|
||||||
|
AURA_LED_STATES = {
|
||||||
|
"BREATHING": AuraLEDState.BREATHING,
|
||||||
|
"FLASHING": AuraLEDState.FLASHING,
|
||||||
|
"ALWAYS_ON": AuraLEDState.ALWAYS_ON,
|
||||||
|
"ALWAYS_OFF": AuraLEDState.ALWAYS_OFF,
|
||||||
|
"GRADUAL_ON": AuraLEDState.GRADUAL_ON,
|
||||||
|
"GRADUAL_OFF": AuraLEDState.GRADUAL_OFF,
|
||||||
|
}
|
||||||
|
validate_aura_led_states = cv.enum(AURA_LED_STATES, upper=True)
|
||||||
|
AuraLEDColor = fingerprint_grow_ns.enum("GrowAuraLEDColor", True)
|
||||||
|
AURA_LED_COLORS = {
|
||||||
|
"RED": AuraLEDColor.RED,
|
||||||
|
"BLUE": AuraLEDColor.BLUE,
|
||||||
|
"PURPLE": AuraLEDColor.PURPLE,
|
||||||
|
}
|
||||||
|
validate_aura_led_colors = cv.enum(AURA_LED_COLORS, upper=True)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(FingerprintGrowComponent),
|
||||||
|
cv.Optional(CONF_SENSING_PIN): pins.gpio_input_pin_schema,
|
||||||
|
cv.Optional(CONF_PASSWORD): cv.uint32_t,
|
||||||
|
cv.Optional(CONF_NEW_PASSWORD): cv.uint32_t,
|
||||||
|
cv.Optional(CONF_ON_FINGER_SCAN_MATCHED): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
FingerScanMatchedTrigger
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ON_FINGER_SCAN_UNMATCHED): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
FingerScanUnmatchedTrigger
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ON_ENROLLMENT_SCAN): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
EnrollmentScanTrigger
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ON_ENROLLMENT_DONE): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
EnrollmentDoneTrigger
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_ON_ENROLLMENT_FAILED): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
EnrollmentFailedTrigger
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("500ms"))
|
||||||
|
.extend(uart.UART_DEVICE_SCHEMA)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
yield cg.register_component(var, config)
|
||||||
|
if CONF_PASSWORD in config:
|
||||||
|
password = config[CONF_PASSWORD]
|
||||||
|
cg.add(var.set_password(password))
|
||||||
|
yield uart.register_uart_device(var, config)
|
||||||
|
|
||||||
|
if CONF_NEW_PASSWORD in config:
|
||||||
|
new_password = config[CONF_NEW_PASSWORD]
|
||||||
|
cg.add(var.set_new_password(new_password))
|
||||||
|
|
||||||
|
if CONF_SENSING_PIN in config:
|
||||||
|
sensing_pin = yield cg.gpio_pin_expression(config[CONF_SENSING_PIN])
|
||||||
|
cg.add(var.set_sensing_pin(sensing_pin))
|
||||||
|
|
||||||
|
for conf in config.get(CONF_ON_FINGER_SCAN_MATCHED, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
yield automation.build_automation(
|
||||||
|
trigger, [(cg.uint16, "finger_id"), (cg.uint16, "confidence")], conf
|
||||||
|
)
|
||||||
|
|
||||||
|
for conf in config.get(CONF_ON_FINGER_SCAN_UNMATCHED, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
yield automation.build_automation(trigger, [], conf)
|
||||||
|
|
||||||
|
for conf in config.get(CONF_ON_ENROLLMENT_SCAN, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
yield automation.build_automation(
|
||||||
|
trigger, [(cg.uint8, "scan_num"), (cg.uint16, "finger_id")], conf
|
||||||
|
)
|
||||||
|
|
||||||
|
for conf in config.get(CONF_ON_ENROLLMENT_DONE, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
yield automation.build_automation(trigger, [(cg.uint16, "finger_id")], conf)
|
||||||
|
|
||||||
|
for conf in config.get(CONF_ON_ENROLLMENT_FAILED, []):
|
||||||
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
yield automation.build_automation(trigger, [(cg.uint16, "finger_id")], conf)
|
||||||
|
|
||||||
|
|
||||||
|
@automation.register_action(
|
||||||
|
"fingerprint_grow.enroll",
|
||||||
|
EnrollmentAction,
|
||||||
|
cv.maybe_simple_value(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.use_id(FingerprintGrowComponent),
|
||||||
|
cv.Required(CONF_FINGER_ID): cv.templatable(cv.uint16_t),
|
||||||
|
cv.Optional(CONF_NUM_SCANS): cv.templatable(cv.uint8_t),
|
||||||
|
},
|
||||||
|
key=CONF_FINGER_ID,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def fingerprint_grow_enroll_to_code(config, action_id, template_arg, args):
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg)
|
||||||
|
yield cg.register_parented(var, config[CONF_ID])
|
||||||
|
|
||||||
|
template_ = yield cg.templatable(config[CONF_FINGER_ID], args, cg.uint16)
|
||||||
|
cg.add(var.set_finger_id(template_))
|
||||||
|
if CONF_NUM_SCANS in config:
|
||||||
|
template_ = yield cg.templatable(config[CONF_NUM_SCANS], args, cg.uint8)
|
||||||
|
cg.add(var.set_num_scans(template_))
|
||||||
|
yield var
|
||||||
|
|
||||||
|
|
||||||
|
@automation.register_action(
|
||||||
|
"fingerprint_grow.cancel_enroll",
|
||||||
|
CancelEnrollmentAction,
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.use_id(FingerprintGrowComponent),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def fingerprint_grow_cancel_enroll_to_code(config, action_id, template_arg, args):
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg)
|
||||||
|
yield cg.register_parented(var, config[CONF_ID])
|
||||||
|
yield var
|
||||||
|
|
||||||
|
|
||||||
|
@automation.register_action(
|
||||||
|
"fingerprint_grow.delete",
|
||||||
|
DeleteAction,
|
||||||
|
cv.maybe_simple_value(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.use_id(FingerprintGrowComponent),
|
||||||
|
cv.Required(CONF_FINGER_ID): cv.templatable(cv.uint16_t),
|
||||||
|
},
|
||||||
|
key=CONF_FINGER_ID,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def fingerprint_grow_delete_to_code(config, action_id, template_arg, args):
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg)
|
||||||
|
yield cg.register_parented(var, config[CONF_ID])
|
||||||
|
|
||||||
|
template_ = yield cg.templatable(config[CONF_FINGER_ID], args, cg.uint16)
|
||||||
|
cg.add(var.set_finger_id(template_))
|
||||||
|
yield var
|
||||||
|
|
||||||
|
|
||||||
|
@automation.register_action(
|
||||||
|
"fingerprint_grow.delete_all",
|
||||||
|
DeleteAllAction,
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.use_id(FingerprintGrowComponent),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def fingerprint_grow_delete_all_to_code(config, action_id, template_arg, args):
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg)
|
||||||
|
yield cg.register_parented(var, config[CONF_ID])
|
||||||
|
yield var
|
||||||
|
|
||||||
|
|
||||||
|
FINGERPRINT_GROW_LED_CONTROL_ACTION_SCHEMA = cv.maybe_simple_value(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.use_id(FingerprintGrowComponent),
|
||||||
|
cv.Required(CONF_STATE): cv.templatable(cv.boolean),
|
||||||
|
},
|
||||||
|
key=CONF_STATE,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@automation.register_action(
|
||||||
|
"fingerprint_grow.led_control",
|
||||||
|
LEDControlAction,
|
||||||
|
FINGERPRINT_GROW_LED_CONTROL_ACTION_SCHEMA,
|
||||||
|
)
|
||||||
|
def fingerprint_grow_led_control_to_code(config, action_id, template_arg, args):
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg)
|
||||||
|
yield cg.register_parented(var, config[CONF_ID])
|
||||||
|
|
||||||
|
template_ = yield cg.templatable(config[CONF_STATE], args, cg.bool_)
|
||||||
|
cg.add(var.set_state(template_))
|
||||||
|
yield var
|
||||||
|
|
||||||
|
|
||||||
|
@automation.register_action(
|
||||||
|
"fingerprint_grow.aura_led_control",
|
||||||
|
AuraLEDControlAction,
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.use_id(FingerprintGrowComponent),
|
||||||
|
cv.Required(CONF_STATE): cv.templatable(validate_aura_led_states),
|
||||||
|
cv.Required(CONF_SPEED): cv.templatable(cv.uint8_t),
|
||||||
|
cv.Required(CONF_COLOR): cv.templatable(validate_aura_led_colors),
|
||||||
|
cv.Required(CONF_COUNT): cv.templatable(cv.uint8_t),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def fingerprint_grow_aura_led_control_to_code(config, action_id, template_arg, args):
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg)
|
||||||
|
yield cg.register_parented(var, config[CONF_ID])
|
||||||
|
|
||||||
|
for key in [CONF_STATE, CONF_SPEED, CONF_COLOR, CONF_COUNT]:
|
||||||
|
template_ = yield cg.templatable(config[key], args, cg.uint8)
|
||||||
|
cg.add(getattr(var, f"set_{key}")(template_))
|
||||||
|
yield var
|
20
esphome/components/fingerprint_grow/binary_sensor.py
Normal file
20
esphome/components/fingerprint_grow/binary_sensor.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import binary_sensor
|
||||||
|
from esphome.const import CONF_ICON, ICON_KEY_PLUS
|
||||||
|
from . import CONF_FINGERPRINT_GROW_ID, FingerprintGrowComponent
|
||||||
|
|
||||||
|
DEPENDENCIES = ["fingerprint_grow"]
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_FINGERPRINT_GROW_ID): cv.use_id(FingerprintGrowComponent),
|
||||||
|
cv.Optional(CONF_ICON, default=ICON_KEY_PLUS): cv.icon,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
hub = yield cg.get_variable(config[CONF_FINGERPRINT_GROW_ID])
|
||||||
|
var = yield binary_sensor.new_binary_sensor(config)
|
||||||
|
cg.add(hub.set_enrolling_binary_sensor(var))
|
434
esphome/components/fingerprint_grow/fingerprint_grow.cpp
Normal file
434
esphome/components/fingerprint_grow/fingerprint_grow.cpp
Normal file
|
@ -0,0 +1,434 @@
|
||||||
|
#include "fingerprint_grow.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace fingerprint_grow {
|
||||||
|
|
||||||
|
static const char* TAG = "fingerprint_grow";
|
||||||
|
|
||||||
|
// Based on Adafruit's library: https://github.com/adafruit/Adafruit-Fingerprint-Sensor-Library
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::update() {
|
||||||
|
if (this->enrollment_image_ > this->enrollment_buffers_) {
|
||||||
|
this->finish_enrollment(this->save_fingerprint_());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->sensing_pin_ != nullptr) {
|
||||||
|
if (this->sensing_pin_->digital_read() == HIGH) {
|
||||||
|
ESP_LOGV(TAG, "No touch sensing");
|
||||||
|
this->waiting_removal_ = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->waiting_removal_) {
|
||||||
|
if (this->scan_image_(1) == NO_FINGER) {
|
||||||
|
ESP_LOGD(TAG, "Finger removed");
|
||||||
|
this->waiting_removal_ = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->enrollment_image_ == 0) {
|
||||||
|
this->scan_and_match_();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t result = this->scan_image_(this->enrollment_image_);
|
||||||
|
if (result == NO_FINGER) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->waiting_removal_ = true;
|
||||||
|
if (result != OK) {
|
||||||
|
this->finish_enrollment(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->enrollment_scan_callback_.call(this->enrollment_image_, this->enrollment_slot_);
|
||||||
|
++this->enrollment_image_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::setup() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up Grow Fingerprint Reader...");
|
||||||
|
if (this->check_password_()) {
|
||||||
|
if (this->new_password_ != nullptr) {
|
||||||
|
if (this->set_password_())
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (this->get_parameters_())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->mark_failed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::enroll_fingerprint(uint16_t finger_id, uint8_t num_buffers) {
|
||||||
|
ESP_LOGI(TAG, "Starting enrollment in slot %d", finger_id);
|
||||||
|
if (this->enrolling_binary_sensor_ != nullptr) {
|
||||||
|
this->enrolling_binary_sensor_->publish_state(true);
|
||||||
|
}
|
||||||
|
this->enrollment_slot_ = finger_id;
|
||||||
|
this->enrollment_buffers_ = num_buffers;
|
||||||
|
this->enrollment_image_ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::finish_enrollment(uint8_t result) {
|
||||||
|
if (result == OK) {
|
||||||
|
this->enrollment_done_callback_.call(this->enrollment_slot_);
|
||||||
|
} else {
|
||||||
|
this->enrollment_failed_callback_.call(this->enrollment_slot_);
|
||||||
|
}
|
||||||
|
this->enrollment_image_ = 0;
|
||||||
|
this->enrollment_slot_ = 0;
|
||||||
|
if (this->enrolling_binary_sensor_ != nullptr) {
|
||||||
|
this->enrolling_binary_sensor_->publish_state(false);
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Finished enrollment");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::scan_and_match_() {
|
||||||
|
if (this->sensing_pin_ != nullptr) {
|
||||||
|
ESP_LOGD(TAG, "Scan and match");
|
||||||
|
} else {
|
||||||
|
ESP_LOGV(TAG, "Scan and match");
|
||||||
|
}
|
||||||
|
if (this->scan_image_(1) == OK) {
|
||||||
|
this->waiting_removal_ = true;
|
||||||
|
this->data_ = {SEARCH, 0x01, 0x00, 0x00, (uint8_t)(this->capacity_ >> 8), (uint8_t)(this->capacity_ & 0xFF)};
|
||||||
|
switch (this->send_command_()) {
|
||||||
|
case OK: {
|
||||||
|
ESP_LOGD(TAG, "Fingerprint matched");
|
||||||
|
uint16_t finger_id = ((uint16_t) this->data_[1] << 8) | this->data_[2];
|
||||||
|
uint16_t confidence = ((uint16_t) this->data_[3] << 8) | this->data_[4];
|
||||||
|
if (this->last_finger_id_sensor_ != nullptr) {
|
||||||
|
this->last_finger_id_sensor_->publish_state(finger_id);
|
||||||
|
}
|
||||||
|
if (this->last_confidence_sensor_ != nullptr) {
|
||||||
|
this->last_confidence_sensor_->publish_state(confidence);
|
||||||
|
}
|
||||||
|
this->finger_scan_matched_callback_.call(finger_id, confidence);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NOT_FOUND:
|
||||||
|
ESP_LOGD(TAG, "Fingerprint not matched to any saved slots");
|
||||||
|
this->finger_scan_unmatched_callback_.call();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t FingerprintGrowComponent::scan_image_(uint8_t buffer) {
|
||||||
|
if (this->sensing_pin_ != nullptr) {
|
||||||
|
ESP_LOGD(TAG, "Getting image %d", buffer);
|
||||||
|
} else {
|
||||||
|
ESP_LOGV(TAG, "Getting image %d", buffer);
|
||||||
|
}
|
||||||
|
this->data_ = {GET_IMAGE};
|
||||||
|
switch (this->send_command_()) {
|
||||||
|
case OK:
|
||||||
|
break;
|
||||||
|
case NO_FINGER:
|
||||||
|
if (this->sensing_pin_ != nullptr) {
|
||||||
|
ESP_LOGD(TAG, "No finger");
|
||||||
|
} else {
|
||||||
|
ESP_LOGV(TAG, "No finger");
|
||||||
|
}
|
||||||
|
return this->data_[0];
|
||||||
|
case IMAGE_FAIL:
|
||||||
|
ESP_LOGE(TAG, "Imaging error");
|
||||||
|
default:
|
||||||
|
return this->data_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Processing image %d", buffer);
|
||||||
|
this->data_ = {IMAGE_2_TZ, buffer};
|
||||||
|
switch (this->send_command_()) {
|
||||||
|
case OK:
|
||||||
|
ESP_LOGI(TAG, "Processed image %d", buffer);
|
||||||
|
break;
|
||||||
|
case IMAGE_MESS:
|
||||||
|
ESP_LOGE(TAG, "Image too messy");
|
||||||
|
break;
|
||||||
|
case FEATURE_FAIL:
|
||||||
|
case INVALID_IMAGE:
|
||||||
|
ESP_LOGE(TAG, "Could not find fingerprint features");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return this->data_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t FingerprintGrowComponent::save_fingerprint_() {
|
||||||
|
ESP_LOGI(TAG, "Creating model");
|
||||||
|
this->data_ = {REG_MODEL};
|
||||||
|
switch (this->send_command_()) {
|
||||||
|
case OK:
|
||||||
|
break;
|
||||||
|
case ENROLL_MISMATCH:
|
||||||
|
ESP_LOGE(TAG, "Scans do not match");
|
||||||
|
default:
|
||||||
|
return this->data_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Storing model");
|
||||||
|
this->data_ = {STORE, 0x01, (uint8_t)(this->enrollment_slot_ >> 8), (uint8_t)(this->enrollment_slot_ & 0xFF)};
|
||||||
|
switch (this->send_command_()) {
|
||||||
|
case OK:
|
||||||
|
ESP_LOGI(TAG, "Stored model");
|
||||||
|
break;
|
||||||
|
case BAD_LOCATION:
|
||||||
|
ESP_LOGE(TAG, "Invalid slot");
|
||||||
|
break;
|
||||||
|
case FLASH_ERR:
|
||||||
|
ESP_LOGE(TAG, "Error writing to flash");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return this->data_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FingerprintGrowComponent::check_password_() {
|
||||||
|
ESP_LOGD(TAG, "Checking password");
|
||||||
|
this->data_ = {VERIFY_PASSWORD, (uint8_t)(this->password_ >> 24), (uint8_t)(this->password_ >> 16),
|
||||||
|
(uint8_t)(this->password_ >> 8), (uint8_t)(this->password_ & 0xFF)};
|
||||||
|
switch (this->send_command_()) {
|
||||||
|
case OK:
|
||||||
|
ESP_LOGD(TAG, "Password verified");
|
||||||
|
return true;
|
||||||
|
case PASSWORD_FAIL:
|
||||||
|
ESP_LOGE(TAG, "Wrong password");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FingerprintGrowComponent::set_password_() {
|
||||||
|
ESP_LOGI(TAG, "Setting new password: %d", *this->new_password_);
|
||||||
|
this->data_ = {SET_PASSWORD, (uint8_t)(*this->new_password_ >> 24), (uint8_t)(*this->new_password_ >> 16),
|
||||||
|
(uint8_t)(*this->new_password_ >> 8), (uint8_t)(*this->new_password_ & 0xFF)};
|
||||||
|
if (this->send_command_() == OK) {
|
||||||
|
ESP_LOGI(TAG, "New password successfully set");
|
||||||
|
ESP_LOGI(TAG, "Define the new password in your configuration and reflash now");
|
||||||
|
ESP_LOGW(TAG, "!!!Forgetting the password will render your device unusable!!!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FingerprintGrowComponent::get_parameters_() {
|
||||||
|
ESP_LOGD(TAG, "Getting parameters");
|
||||||
|
this->data_ = {READ_SYS_PARAM};
|
||||||
|
if (this->send_command_() == OK) {
|
||||||
|
ESP_LOGD(TAG, "Got parameters");
|
||||||
|
if (this->status_sensor_ != nullptr) {
|
||||||
|
this->status_sensor_->publish_state(((uint16_t) this->data_[1] << 8) | this->data_[2]);
|
||||||
|
}
|
||||||
|
this->capacity_ = ((uint16_t) this->data_[5] << 8) | this->data_[6];
|
||||||
|
if (this->capacity_sensor_ != nullptr) {
|
||||||
|
this->capacity_sensor_->publish_state(this->capacity_);
|
||||||
|
}
|
||||||
|
if (this->security_level_sensor_ != nullptr) {
|
||||||
|
this->security_level_sensor_->publish_state(((uint16_t) this->data_[7] << 8) | this->data_[8]);
|
||||||
|
}
|
||||||
|
if (this->enrolling_binary_sensor_ != nullptr) {
|
||||||
|
this->enrolling_binary_sensor_->publish_state(false);
|
||||||
|
}
|
||||||
|
this->get_fingerprint_count_();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::get_fingerprint_count_() {
|
||||||
|
ESP_LOGD(TAG, "Getting fingerprint count");
|
||||||
|
this->data_ = {TEMPLATE_COUNT};
|
||||||
|
if (this->send_command_() == OK) {
|
||||||
|
ESP_LOGD(TAG, "Got fingerprint count");
|
||||||
|
if (this->fingerprint_count_sensor_ != nullptr)
|
||||||
|
this->fingerprint_count_sensor_->publish_state(((uint16_t) this->data_[1] << 8) | this->data_[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::delete_fingerprint(uint16_t finger_id) {
|
||||||
|
ESP_LOGI(TAG, "Deleting fingerprint in slot %d", finger_id);
|
||||||
|
this->data_ = {DELETE, (uint8_t)(finger_id >> 8), (uint8_t)(finger_id & 0xFF), 0x00, 0x01};
|
||||||
|
switch (this->send_command_()) {
|
||||||
|
case OK:
|
||||||
|
ESP_LOGI(TAG, "Deleted fingerprint");
|
||||||
|
this->get_fingerprint_count_();
|
||||||
|
break;
|
||||||
|
case DELETE_FAIL:
|
||||||
|
ESP_LOGE(TAG, "Reader failed to delete fingerprint");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::delete_all_fingerprints() {
|
||||||
|
ESP_LOGI(TAG, "Deleting all stored fingerprints");
|
||||||
|
this->data_ = {EMPTY};
|
||||||
|
switch (this->send_command_()) {
|
||||||
|
case OK:
|
||||||
|
ESP_LOGI(TAG, "Deleted all fingerprints");
|
||||||
|
this->get_fingerprint_count_();
|
||||||
|
break;
|
||||||
|
case DB_CLEAR_FAIL:
|
||||||
|
ESP_LOGE(TAG, "Reader failed to clear fingerprint library");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::led_control(bool state) {
|
||||||
|
ESP_LOGD(TAG, "Setting LED");
|
||||||
|
if (state)
|
||||||
|
this->data_ = {LED_ON};
|
||||||
|
else
|
||||||
|
this->data_ = {LED_OFF};
|
||||||
|
switch (this->send_command_()) {
|
||||||
|
case OK:
|
||||||
|
ESP_LOGD(TAG, "LED set");
|
||||||
|
break;
|
||||||
|
case PACKET_RCV_ERR:
|
||||||
|
case TIMEOUT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Try aura_led_control instead");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::aura_led_control(uint8_t state, uint8_t speed, uint8_t color, uint8_t count) {
|
||||||
|
const uint32_t now = millis();
|
||||||
|
const uint32_t elapsed = now - this->last_aura_led_control_;
|
||||||
|
if (elapsed < this->last_aura_led_duration_) {
|
||||||
|
delay(this->last_aura_led_duration_ - elapsed);
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, "Setting Aura LED");
|
||||||
|
this->data_ = {AURA_CONFIG, state, speed, color, count};
|
||||||
|
switch (this->send_command_()) {
|
||||||
|
case OK:
|
||||||
|
ESP_LOGD(TAG, "Aura LED set");
|
||||||
|
this->last_aura_led_control_ = millis();
|
||||||
|
this->last_aura_led_duration_ = 10 * speed * count;
|
||||||
|
break;
|
||||||
|
case PACKET_RCV_ERR:
|
||||||
|
case TIMEOUT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Try led_control instead");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t FingerprintGrowComponent::send_command_() {
|
||||||
|
this->write((uint8_t)(START_CODE >> 8));
|
||||||
|
this->write((uint8_t)(START_CODE & 0xFF));
|
||||||
|
this->write(this->address_[0]);
|
||||||
|
this->write(this->address_[1]);
|
||||||
|
this->write(this->address_[2]);
|
||||||
|
this->write(this->address_[3]);
|
||||||
|
this->write(COMMAND);
|
||||||
|
|
||||||
|
uint16_t wire_length = this->data_.size() + 2;
|
||||||
|
this->write((uint8_t)(wire_length >> 8));
|
||||||
|
this->write((uint8_t)(wire_length & 0xFF));
|
||||||
|
|
||||||
|
uint16_t sum = ((wire_length) >> 8) + ((wire_length) &0xFF) + COMMAND;
|
||||||
|
for (auto data : this->data_) {
|
||||||
|
this->write(data);
|
||||||
|
sum += data;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->write((uint8_t)(sum >> 8));
|
||||||
|
this->write((uint8_t)(sum & 0xFF));
|
||||||
|
|
||||||
|
this->data_.clear();
|
||||||
|
|
||||||
|
uint8_t byte;
|
||||||
|
uint16_t idx = 0, length = 0;
|
||||||
|
|
||||||
|
for (uint16_t timer = 0; timer < 1000; timer++) {
|
||||||
|
if (this->available() == 0) {
|
||||||
|
delay(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
byte = this->read();
|
||||||
|
switch (idx) {
|
||||||
|
case 0:
|
||||||
|
if (byte != (uint8_t)(START_CODE >> 8))
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (byte != (uint8_t)(START_CODE & 0xFF)) {
|
||||||
|
idx = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
if (byte != this->address_[idx - 2]) {
|
||||||
|
idx = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
if (byte != ACK) {
|
||||||
|
idx = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
length = (uint16_t) byte << 8;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
length |= byte;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this->data_.push_back(byte);
|
||||||
|
if ((idx - 8) == length) {
|
||||||
|
switch (this->data_[0]) {
|
||||||
|
case OK:
|
||||||
|
case NO_FINGER:
|
||||||
|
case IMAGE_FAIL:
|
||||||
|
case IMAGE_MESS:
|
||||||
|
case FEATURE_FAIL:
|
||||||
|
case NO_MATCH:
|
||||||
|
case NOT_FOUND:
|
||||||
|
case ENROLL_MISMATCH:
|
||||||
|
case BAD_LOCATION:
|
||||||
|
case DELETE_FAIL:
|
||||||
|
case DB_CLEAR_FAIL:
|
||||||
|
case PASSWORD_FAIL:
|
||||||
|
case INVALID_IMAGE:
|
||||||
|
case FLASH_ERR:
|
||||||
|
break;
|
||||||
|
case PACKET_RCV_ERR:
|
||||||
|
ESP_LOGE(TAG, "Reader failed to process request");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Unknown response received from reader: %d", this->data_[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return this->data_[0];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
ESP_LOGE(TAG, "No response received from reader");
|
||||||
|
this->data_[0] = TIMEOUT;
|
||||||
|
return TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FingerprintGrowComponent::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "GROW_FINGERPRINT_READER:");
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
LOG_SENSOR(" ", "Fingerprint Count", this->fingerprint_count_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Status", this->status_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Capacity", this->capacity_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Security Level", this->security_level_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Last Finger ID", this->last_finger_id_sensor_);
|
||||||
|
LOG_SENSOR(" ", "Last Confidence", this->last_confidence_sensor_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace fingerprint_grow
|
||||||
|
} // namespace esphome
|
276
esphome/components/fingerprint_grow/fingerprint_grow.h
Normal file
276
esphome/components/fingerprint_grow/fingerprint_grow.h
Normal file
|
@ -0,0 +1,276 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/automation.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
|
#include "esphome/components/uart/uart.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace fingerprint_grow {
|
||||||
|
|
||||||
|
static const uint16_t START_CODE = 0xEF01;
|
||||||
|
|
||||||
|
enum GrowPacketType {
|
||||||
|
COMMAND = 0x01,
|
||||||
|
DATA = 0x02,
|
||||||
|
ACK = 0x07,
|
||||||
|
END_DATA = 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GrowCommand {
|
||||||
|
GET_IMAGE = 0x01,
|
||||||
|
IMAGE_2_TZ = 0x02,
|
||||||
|
SEARCH = 0x04,
|
||||||
|
REG_MODEL = 0x05,
|
||||||
|
STORE = 0x06,
|
||||||
|
LOAD = 0x07,
|
||||||
|
UPLOAD = 0x08,
|
||||||
|
DELETE = 0x0C,
|
||||||
|
EMPTY = 0x0D,
|
||||||
|
READ_SYS_PARAM = 0x0F,
|
||||||
|
SET_PASSWORD = 0x12,
|
||||||
|
VERIFY_PASSWORD = 0x13,
|
||||||
|
HI_SPEED_SEARCH = 0x1B,
|
||||||
|
TEMPLATE_COUNT = 0x1D,
|
||||||
|
AURA_CONFIG = 0x35,
|
||||||
|
LED_ON = 0x50,
|
||||||
|
LED_OFF = 0x51,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GrowResponse {
|
||||||
|
OK = 0x00,
|
||||||
|
PACKET_RCV_ERR = 0x01,
|
||||||
|
NO_FINGER = 0x02,
|
||||||
|
IMAGE_FAIL = 0x03,
|
||||||
|
IMAGE_MESS = 0x06,
|
||||||
|
FEATURE_FAIL = 0x07,
|
||||||
|
NO_MATCH = 0x08,
|
||||||
|
NOT_FOUND = 0x09,
|
||||||
|
ENROLL_MISMATCH = 0x0A,
|
||||||
|
BAD_LOCATION = 0x0B,
|
||||||
|
DB_RANGE_FAIL = 0x0C,
|
||||||
|
UPLOAD_FEATURE_FAIL = 0x0D,
|
||||||
|
PACKET_RESPONSE_FAIL = 0x0E,
|
||||||
|
UPLOAD_FAIL = 0x0F,
|
||||||
|
DELETE_FAIL = 0x10,
|
||||||
|
DB_CLEAR_FAIL = 0x11,
|
||||||
|
PASSWORD_FAIL = 0x13,
|
||||||
|
INVALID_IMAGE = 0x15,
|
||||||
|
FLASH_ERR = 0x18,
|
||||||
|
INVALID_REG = 0x1A,
|
||||||
|
BAD_PACKET = 0xFE,
|
||||||
|
TIMEOUT = 0xFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GrowAuraLEDState {
|
||||||
|
BREATHING = 0x01,
|
||||||
|
FLASHING = 0x02,
|
||||||
|
ALWAYS_ON = 0x03,
|
||||||
|
ALWAYS_OFF = 0x04,
|
||||||
|
GRADUAL_ON = 0x05,
|
||||||
|
GRADUAL_OFF = 0x06,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GrowAuraLEDColor {
|
||||||
|
RED = 0x01,
|
||||||
|
BLUE = 0x02,
|
||||||
|
PURPLE = 0x03,
|
||||||
|
};
|
||||||
|
|
||||||
|
class FingerprintGrowComponent : public PollingComponent, public uart::UARTDevice {
|
||||||
|
public:
|
||||||
|
void update() override;
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
void set_address(uint32_t address) {
|
||||||
|
this->address_[0] = (uint8_t)(address >> 24);
|
||||||
|
this->address_[1] = (uint8_t)(address >> 16);
|
||||||
|
this->address_[2] = (uint8_t)(address >> 8);
|
||||||
|
this->address_[3] = (uint8_t)(address & 0xFF);
|
||||||
|
}
|
||||||
|
void set_sensing_pin(GPIOPin *sensing_pin) { this->sensing_pin_ = sensing_pin; }
|
||||||
|
void set_password(uint32_t password) { this->password_ = password; }
|
||||||
|
void set_new_password(uint32_t new_password) { this->new_password_ = &new_password; }
|
||||||
|
void set_fingerprint_count_sensor(sensor::Sensor *fingerprint_count_sensor) {
|
||||||
|
this->fingerprint_count_sensor_ = fingerprint_count_sensor;
|
||||||
|
}
|
||||||
|
void set_status_sensor(sensor::Sensor *status_sensor) { this->status_sensor_ = status_sensor; }
|
||||||
|
void set_capacity_sensor(sensor::Sensor *capacity_sensor) { this->capacity_sensor_ = capacity_sensor; }
|
||||||
|
void set_security_level_sensor(sensor::Sensor *security_level_sensor) {
|
||||||
|
this->security_level_sensor_ = security_level_sensor;
|
||||||
|
}
|
||||||
|
void set_last_finger_id_sensor(sensor::Sensor *last_finger_id_sensor) {
|
||||||
|
this->last_finger_id_sensor_ = last_finger_id_sensor;
|
||||||
|
}
|
||||||
|
void set_last_confidence_sensor(sensor::Sensor *last_confidence_sensor) {
|
||||||
|
this->last_confidence_sensor_ = last_confidence_sensor;
|
||||||
|
}
|
||||||
|
void set_enrolling_binary_sensor(binary_sensor::BinarySensor *enrolling_binary_sensor) {
|
||||||
|
this->enrolling_binary_sensor_ = enrolling_binary_sensor;
|
||||||
|
}
|
||||||
|
void add_on_finger_scan_matched_callback(std::function<void(uint16_t, uint16_t)> callback) {
|
||||||
|
this->finger_scan_matched_callback_.add(std::move(callback));
|
||||||
|
}
|
||||||
|
void add_on_finger_scan_unmatched_callback(std::function<void()> callback) {
|
||||||
|
this->finger_scan_unmatched_callback_.add(std::move(callback));
|
||||||
|
}
|
||||||
|
void add_on_enrollment_scan_callback(std::function<void(uint8_t, uint16_t)> callback) {
|
||||||
|
this->enrollment_scan_callback_.add(std::move(callback));
|
||||||
|
}
|
||||||
|
void add_on_enrollment_done_callback(std::function<void(uint16_t)> callback) {
|
||||||
|
this->enrollment_done_callback_.add(std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_on_enrollment_failed_callback(std::function<void(uint16_t)> callback) {
|
||||||
|
this->enrollment_failed_callback_.add(std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
void enroll_fingerprint(uint16_t finger_id, uint8_t num_buffers);
|
||||||
|
void finish_enrollment(uint8_t result);
|
||||||
|
void delete_fingerprint(uint16_t finger_id);
|
||||||
|
void delete_all_fingerprints();
|
||||||
|
|
||||||
|
void led_control(bool state);
|
||||||
|
void aura_led_control(uint8_t state, uint8_t speed, uint8_t color, uint8_t count);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void scan_and_match_();
|
||||||
|
uint8_t scan_image_(uint8_t buffer);
|
||||||
|
uint8_t save_fingerprint_();
|
||||||
|
bool check_password_();
|
||||||
|
bool set_password_();
|
||||||
|
bool get_parameters_();
|
||||||
|
void get_fingerprint_count_();
|
||||||
|
uint8_t send_command_();
|
||||||
|
|
||||||
|
std::vector<uint8_t> data_ = {};
|
||||||
|
uint8_t address_[4] = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
|
uint16_t capacity_ = 64;
|
||||||
|
uint32_t password_ = 0x0;
|
||||||
|
uint32_t *new_password_{nullptr};
|
||||||
|
GPIOPin *sensing_pin_{nullptr};
|
||||||
|
uint8_t enrollment_image_ = 0;
|
||||||
|
uint16_t enrollment_slot_ = 0;
|
||||||
|
uint8_t enrollment_buffers_ = 5;
|
||||||
|
bool waiting_removal_ = false;
|
||||||
|
uint32_t last_aura_led_control_ = 0;
|
||||||
|
uint16_t last_aura_led_duration_ = 0;
|
||||||
|
sensor::Sensor *fingerprint_count_sensor_{nullptr};
|
||||||
|
sensor::Sensor *status_sensor_{nullptr};
|
||||||
|
sensor::Sensor *capacity_sensor_{nullptr};
|
||||||
|
sensor::Sensor *security_level_sensor_{nullptr};
|
||||||
|
sensor::Sensor *last_finger_id_sensor_{nullptr};
|
||||||
|
sensor::Sensor *last_confidence_sensor_{nullptr};
|
||||||
|
binary_sensor::BinarySensor *enrolling_binary_sensor_{nullptr};
|
||||||
|
CallbackManager<void(uint16_t, uint16_t)> finger_scan_matched_callback_;
|
||||||
|
CallbackManager<void()> finger_scan_unmatched_callback_;
|
||||||
|
CallbackManager<void(uint8_t, uint16_t)> enrollment_scan_callback_;
|
||||||
|
CallbackManager<void(uint16_t)> enrollment_done_callback_;
|
||||||
|
CallbackManager<void(uint16_t)> enrollment_failed_callback_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FingerScanMatchedTrigger : public Trigger<uint16_t, uint16_t> {
|
||||||
|
public:
|
||||||
|
explicit FingerScanMatchedTrigger(FingerprintGrowComponent *parent) {
|
||||||
|
parent->add_on_finger_scan_matched_callback(
|
||||||
|
[this](uint16_t finger_id, uint16_t confidence) { this->trigger(finger_id, confidence); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FingerScanUnmatchedTrigger : public Trigger<> {
|
||||||
|
public:
|
||||||
|
explicit FingerScanUnmatchedTrigger(FingerprintGrowComponent *parent) {
|
||||||
|
parent->add_on_finger_scan_unmatched_callback([this]() { this->trigger(); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class EnrollmentScanTrigger : public Trigger<uint8_t, uint16_t> {
|
||||||
|
public:
|
||||||
|
explicit EnrollmentScanTrigger(FingerprintGrowComponent *parent) {
|
||||||
|
parent->add_on_enrollment_scan_callback(
|
||||||
|
[this](uint8_t scan_num, uint16_t finger_id) { this->trigger(scan_num, finger_id); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class EnrollmentDoneTrigger : public Trigger<uint16_t> {
|
||||||
|
public:
|
||||||
|
explicit EnrollmentDoneTrigger(FingerprintGrowComponent *parent) {
|
||||||
|
parent->add_on_enrollment_done_callback([this](uint16_t finger_id) { this->trigger(finger_id); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class EnrollmentFailedTrigger : public Trigger<uint16_t> {
|
||||||
|
public:
|
||||||
|
explicit EnrollmentFailedTrigger(FingerprintGrowComponent *parent) {
|
||||||
|
parent->add_on_enrollment_failed_callback([this](uint16_t finger_id) { this->trigger(finger_id); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class EnrollmentAction : public Action<Ts...>, public Parented<FingerprintGrowComponent> {
|
||||||
|
public:
|
||||||
|
TEMPLATABLE_VALUE(uint16_t, finger_id)
|
||||||
|
TEMPLATABLE_VALUE(uint8_t, num_scans)
|
||||||
|
|
||||||
|
void play(Ts... x) override {
|
||||||
|
auto finger_id = this->finger_id_.value(x...);
|
||||||
|
auto num_scans = this->num_scans_.value(x...);
|
||||||
|
if (num_scans) {
|
||||||
|
this->parent_->enroll_fingerprint(finger_id, num_scans);
|
||||||
|
} else {
|
||||||
|
this->parent_->enroll_fingerprint(finger_id, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
class CancelEnrollmentAction : public Action<Ts...>, public Parented<FingerprintGrowComponent> {
|
||||||
|
public:
|
||||||
|
void play(Ts... x) override { this->parent_->finish_enrollment(1); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class DeleteAction : public Action<Ts...>, public Parented<FingerprintGrowComponent> {
|
||||||
|
public:
|
||||||
|
TEMPLATABLE_VALUE(uint16_t, finger_id)
|
||||||
|
|
||||||
|
void play(Ts... x) override {
|
||||||
|
auto finger_id = this->finger_id_.value(x...);
|
||||||
|
this->parent_->delete_fingerprint(finger_id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class DeleteAllAction : public Action<Ts...>, public Parented<FingerprintGrowComponent> {
|
||||||
|
public:
|
||||||
|
void play(Ts... x) override { this->parent_->delete_all_fingerprints(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class LEDControlAction : public Action<Ts...>, public Parented<FingerprintGrowComponent> {
|
||||||
|
public:
|
||||||
|
TEMPLATABLE_VALUE(bool, state)
|
||||||
|
|
||||||
|
void play(Ts... x) override {
|
||||||
|
auto state = this->state_.value(x...);
|
||||||
|
this->parent_->led_control(state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class AuraLEDControlAction : public Action<Ts...>, public Parented<FingerprintGrowComponent> {
|
||||||
|
public:
|
||||||
|
TEMPLATABLE_VALUE(uint8_t, state)
|
||||||
|
TEMPLATABLE_VALUE(uint8_t, speed)
|
||||||
|
TEMPLATABLE_VALUE(uint8_t, color)
|
||||||
|
TEMPLATABLE_VALUE(uint8_t, count)
|
||||||
|
|
||||||
|
void play(Ts... x) override {
|
||||||
|
auto state = this->state_.value(x...);
|
||||||
|
auto speed = this->speed_.value(x...);
|
||||||
|
auto color = this->color_.value(x...);
|
||||||
|
auto count = this->count_.value(x...);
|
||||||
|
|
||||||
|
this->parent_->aura_led_control(state, speed, color, count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace fingerprint_grow
|
||||||
|
} // namespace esphome
|
64
esphome/components/fingerprint_grow/sensor.py
Normal file
64
esphome/components/fingerprint_grow/sensor.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import sensor
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_CAPACITY,
|
||||||
|
CONF_FINGERPRINT_COUNT,
|
||||||
|
CONF_LAST_CONFIDENCE,
|
||||||
|
CONF_LAST_FINGER_ID,
|
||||||
|
CONF_SECURITY_LEVEL,
|
||||||
|
CONF_STATUS,
|
||||||
|
DEVICE_CLASS_EMPTY,
|
||||||
|
ICON_ACCOUNT,
|
||||||
|
ICON_ACCOUNT_CHECK,
|
||||||
|
ICON_DATABASE,
|
||||||
|
ICON_EMPTY,
|
||||||
|
ICON_FINGERPRINT,
|
||||||
|
ICON_SECURITY,
|
||||||
|
UNIT_EMPTY,
|
||||||
|
)
|
||||||
|
from . import CONF_FINGERPRINT_GROW_ID, FingerprintGrowComponent
|
||||||
|
|
||||||
|
DEPENDENCIES = ["fingerprint_grow"]
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_FINGERPRINT_GROW_ID): cv.use_id(FingerprintGrowComponent),
|
||||||
|
cv.Optional(CONF_FINGERPRINT_COUNT): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY, ICON_FINGERPRINT, 0, DEVICE_CLASS_EMPTY
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_STATUS): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY, ICON_EMPTY, 0, DEVICE_CLASS_EMPTY
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CAPACITY): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY, ICON_DATABASE, 0, DEVICE_CLASS_EMPTY
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_SECURITY_LEVEL): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY, ICON_SECURITY, 0, DEVICE_CLASS_EMPTY
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_LAST_FINGER_ID): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY, ICON_ACCOUNT, 0, DEVICE_CLASS_EMPTY
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_LAST_CONFIDENCE): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY, ICON_ACCOUNT_CHECK, 0, DEVICE_CLASS_EMPTY
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def to_code(config):
|
||||||
|
hub = yield cg.get_variable(config[CONF_FINGERPRINT_GROW_ID])
|
||||||
|
|
||||||
|
for key in [
|
||||||
|
CONF_FINGERPRINT_COUNT,
|
||||||
|
CONF_STATUS,
|
||||||
|
CONF_CAPACITY,
|
||||||
|
CONF_SECURITY_LEVEL,
|
||||||
|
CONF_LAST_FINGER_ID,
|
||||||
|
CONF_LAST_CONFIDENCE,
|
||||||
|
]:
|
||||||
|
if key not in config:
|
||||||
|
continue
|
||||||
|
conf = config[key]
|
||||||
|
sens = yield sensor.new_sensor(conf)
|
||||||
|
cg.add(getattr(hub, f"set_{key}_sensor")(sens))
|
|
@ -97,6 +97,7 @@ CONF_BUSY_PIN = "busy_pin"
|
||||||
CONF_CALIBRATE_LINEAR = "calibrate_linear"
|
CONF_CALIBRATE_LINEAR = "calibrate_linear"
|
||||||
CONF_CALIBRATION = "calibration"
|
CONF_CALIBRATION = "calibration"
|
||||||
CONF_CAPACITANCE = "capacitance"
|
CONF_CAPACITANCE = "capacitance"
|
||||||
|
CONF_CAPACITY = "capacity"
|
||||||
CONF_CARRIER_DUTY_PERCENT = "carrier_duty_percent"
|
CONF_CARRIER_DUTY_PERCENT = "carrier_duty_percent"
|
||||||
CONF_CARRIER_FREQUENCY = "carrier_frequency"
|
CONF_CARRIER_FREQUENCY = "carrier_frequency"
|
||||||
CONF_CERTIFICATE = "certificate"
|
CONF_CERTIFICATE = "certificate"
|
||||||
|
@ -115,6 +116,7 @@ CONF_CO2 = "co2"
|
||||||
CONF_CODE = "code"
|
CONF_CODE = "code"
|
||||||
CONF_COLD_WHITE = "cold_white"
|
CONF_COLD_WHITE = "cold_white"
|
||||||
CONF_COLD_WHITE_COLOR_TEMPERATURE = "cold_white_color_temperature"
|
CONF_COLD_WHITE_COLOR_TEMPERATURE = "cold_white_color_temperature"
|
||||||
|
CONF_COLOR = "color"
|
||||||
CONF_COLOR_CORRECT = "color_correct"
|
CONF_COLOR_CORRECT = "color_correct"
|
||||||
CONF_COLOR_TEMPERATURE = "color_temperature"
|
CONF_COLOR_TEMPERATURE = "color_temperature"
|
||||||
CONF_COLORS = "colors"
|
CONF_COLORS = "colors"
|
||||||
|
@ -130,6 +132,7 @@ CONF_CONDUCTIVITY = "conductivity"
|
||||||
CONF_CONTRAST = "contrast"
|
CONF_CONTRAST = "contrast"
|
||||||
CONF_COOL_ACTION = "cool_action"
|
CONF_COOL_ACTION = "cool_action"
|
||||||
CONF_COOL_MODE = "cool_mode"
|
CONF_COOL_MODE = "cool_mode"
|
||||||
|
CONF_COUNT = "count"
|
||||||
CONF_COUNT_MODE = "count_mode"
|
CONF_COUNT_MODE = "count_mode"
|
||||||
CONF_COURSE = "course"
|
CONF_COURSE = "course"
|
||||||
CONF_CRON = "cron"
|
CONF_CRON = "cron"
|
||||||
|
@ -208,6 +211,8 @@ CONF_FILE = "file"
|
||||||
CONF_FILTER = "filter"
|
CONF_FILTER = "filter"
|
||||||
CONF_FILTER_OUT = "filter_out"
|
CONF_FILTER_OUT = "filter_out"
|
||||||
CONF_FILTERS = "filters"
|
CONF_FILTERS = "filters"
|
||||||
|
CONF_FINGER_ID = "finger_id"
|
||||||
|
CONF_FINGERPRINT_COUNT = "fingerprint_count"
|
||||||
CONF_FLASH_LENGTH = "flash_length"
|
CONF_FLASH_LENGTH = "flash_length"
|
||||||
CONF_FOR = "for"
|
CONF_FOR = "for"
|
||||||
CONF_FORCE_UPDATE = "force_update"
|
CONF_FORCE_UPDATE = "force_update"
|
||||||
|
@ -275,6 +280,8 @@ CONF_KEEP_ON_TIME = "keep_on_time"
|
||||||
CONF_KEEPALIVE = "keepalive"
|
CONF_KEEPALIVE = "keepalive"
|
||||||
CONF_KEY = "key"
|
CONF_KEY = "key"
|
||||||
CONF_LAMBDA = "lambda"
|
CONF_LAMBDA = "lambda"
|
||||||
|
CONF_LAST_CONFIDENCE = "last_confidence"
|
||||||
|
CONF_LAST_FINGER_ID = "last_finger_id"
|
||||||
CONF_LATITUDE = "latitude"
|
CONF_LATITUDE = "latitude"
|
||||||
CONF_LENGTH = "length"
|
CONF_LENGTH = "length"
|
||||||
CONF_LEVEL = "level"
|
CONF_LEVEL = "level"
|
||||||
|
@ -335,11 +342,13 @@ CONF_NAME = "name"
|
||||||
CONF_NBITS = "nbits"
|
CONF_NBITS = "nbits"
|
||||||
CONF_NEC = "nec"
|
CONF_NEC = "nec"
|
||||||
CONF_NETWORKS = "networks"
|
CONF_NETWORKS = "networks"
|
||||||
|
CONF_NEW_PASSWORD = "new_password"
|
||||||
CONF_NOISE_LEVEL = "noise_level"
|
CONF_NOISE_LEVEL = "noise_level"
|
||||||
CONF_NUM_ATTEMPTS = "num_attempts"
|
CONF_NUM_ATTEMPTS = "num_attempts"
|
||||||
CONF_NUM_CHANNELS = "num_channels"
|
CONF_NUM_CHANNELS = "num_channels"
|
||||||
CONF_NUM_CHIPS = "num_chips"
|
CONF_NUM_CHIPS = "num_chips"
|
||||||
CONF_NUM_LEDS = "num_leds"
|
CONF_NUM_LEDS = "num_leds"
|
||||||
|
CONF_NUM_SCANS = "num_scans"
|
||||||
CONF_NUMBER = "number"
|
CONF_NUMBER = "number"
|
||||||
CONF_OFF_MODE = "off_mode"
|
CONF_OFF_MODE = "off_mode"
|
||||||
CONF_OFFSET = "offset"
|
CONF_OFFSET = "offset"
|
||||||
|
@ -350,6 +359,11 @@ CONF_ON_BLE_SERVICE_DATA_ADVERTISE = "on_ble_service_data_advertise"
|
||||||
CONF_ON_BOOT = "on_boot"
|
CONF_ON_BOOT = "on_boot"
|
||||||
CONF_ON_CLICK = "on_click"
|
CONF_ON_CLICK = "on_click"
|
||||||
CONF_ON_DOUBLE_CLICK = "on_double_click"
|
CONF_ON_DOUBLE_CLICK = "on_double_click"
|
||||||
|
CONF_ON_ENROLLMENT_DONE = "on_enrollment_done"
|
||||||
|
CONF_ON_ENROLLMENT_FAILED = "on_enrollment_failed"
|
||||||
|
CONF_ON_ENROLLMENT_SCAN = "on_enrollment_scan"
|
||||||
|
CONF_ON_FINGER_SCAN_MATCHED = "on_finger_scan_matched"
|
||||||
|
CONF_ON_FINGER_SCAN_UNMATCHED = "on_finger_scan_unmatched"
|
||||||
CONF_ON_JSON_MESSAGE = "on_json_message"
|
CONF_ON_JSON_MESSAGE = "on_json_message"
|
||||||
CONF_ON_LOOP = "on_loop"
|
CONF_ON_LOOP = "on_loop"
|
||||||
CONF_ON_MESSAGE = "on_message"
|
CONF_ON_MESSAGE = "on_message"
|
||||||
|
@ -472,10 +486,12 @@ CONF_SDA = "sda"
|
||||||
CONF_SDO_PIN = "sdo_pin"
|
CONF_SDO_PIN = "sdo_pin"
|
||||||
CONF_SECOND = "second"
|
CONF_SECOND = "second"
|
||||||
CONF_SECONDS = "seconds"
|
CONF_SECONDS = "seconds"
|
||||||
|
CONF_SECURITY_LEVEL = "security_level"
|
||||||
CONF_SEGMENTS = "segments"
|
CONF_SEGMENTS = "segments"
|
||||||
CONF_SEL_PIN = "sel_pin"
|
CONF_SEL_PIN = "sel_pin"
|
||||||
CONF_SEND_EVERY = "send_every"
|
CONF_SEND_EVERY = "send_every"
|
||||||
CONF_SEND_FIRST_AT = "send_first_at"
|
CONF_SEND_FIRST_AT = "send_first_at"
|
||||||
|
CONF_SENSING_PIN = "sensing_pin"
|
||||||
CONF_SENSOR = "sensor"
|
CONF_SENSOR = "sensor"
|
||||||
CONF_SENSOR_ID = "sensor_id"
|
CONF_SENSOR_ID = "sensor_id"
|
||||||
CONF_SENSORS = "sensors"
|
CONF_SENSORS = "sensors"
|
||||||
|
@ -505,6 +521,7 @@ CONF_SSL_FINGERPRINTS = "ssl_fingerprints"
|
||||||
CONF_STATE = "state"
|
CONF_STATE = "state"
|
||||||
CONF_STATE_TOPIC = "state_topic"
|
CONF_STATE_TOPIC = "state_topic"
|
||||||
CONF_STATIC_IP = "static_ip"
|
CONF_STATIC_IP = "static_ip"
|
||||||
|
CONF_STATUS = "status"
|
||||||
CONF_STEP_MODE = "step_mode"
|
CONF_STEP_MODE = "step_mode"
|
||||||
CONF_STEP_PIN = "step_pin"
|
CONF_STEP_PIN = "step_pin"
|
||||||
CONF_STOP = "stop"
|
CONF_STOP = "stop"
|
||||||
|
@ -599,6 +616,8 @@ ICON_ACCELERATION = "mdi:axis-arrow"
|
||||||
ICON_ACCELERATION_X = "mdi:axis-x-arrow"
|
ICON_ACCELERATION_X = "mdi:axis-x-arrow"
|
||||||
ICON_ACCELERATION_Y = "mdi:axis-y-arrow"
|
ICON_ACCELERATION_Y = "mdi:axis-y-arrow"
|
||||||
ICON_ACCELERATION_Z = "mdi:axis-z-arrow"
|
ICON_ACCELERATION_Z = "mdi:axis-z-arrow"
|
||||||
|
ICON_ACCOUNT = "mdi:account"
|
||||||
|
ICON_ACCOUNT_CHECK = "mdi:account-check"
|
||||||
ICON_ARROW_EXPAND_VERTICAL = "mdi:arrow-expand-vertical"
|
ICON_ARROW_EXPAND_VERTICAL = "mdi:arrow-expand-vertical"
|
||||||
ICON_BATTERY = "mdi:battery"
|
ICON_BATTERY = "mdi:battery"
|
||||||
ICON_BRIEFCASE_DOWNLOAD = "mdi:briefcase-download"
|
ICON_BRIEFCASE_DOWNLOAD = "mdi:briefcase-download"
|
||||||
|
@ -608,7 +627,9 @@ ICON_CHECK_CIRCLE_OUTLINE = "mdi:check-circle-outline"
|
||||||
ICON_CHEMICAL_WEAPON = "mdi:chemical-weapon"
|
ICON_CHEMICAL_WEAPON = "mdi:chemical-weapon"
|
||||||
ICON_COUNTER = "mdi:counter"
|
ICON_COUNTER = "mdi:counter"
|
||||||
ICON_CURRENT_AC = "mdi:current-ac"
|
ICON_CURRENT_AC = "mdi:current-ac"
|
||||||
|
ICON_DATABASE = "mdi:database"
|
||||||
ICON_EMPTY = ""
|
ICON_EMPTY = ""
|
||||||
|
ICON_FINGERPRINT = "mdi:fingerprint"
|
||||||
ICON_FLASH = "mdi:flash"
|
ICON_FLASH = "mdi:flash"
|
||||||
ICON_FLASK = "mdi:flask"
|
ICON_FLASK = "mdi:flask"
|
||||||
ICON_FLASK_OUTLINE = "mdi:flask-outline"
|
ICON_FLASK_OUTLINE = "mdi:flask-outline"
|
||||||
|
@ -616,6 +637,7 @@ ICON_FLOWER = "mdi:flower"
|
||||||
ICON_GAS_CYLINDER = "mdi:gas-cylinder"
|
ICON_GAS_CYLINDER = "mdi:gas-cylinder"
|
||||||
ICON_GAUGE = "mdi:gauge"
|
ICON_GAUGE = "mdi:gauge"
|
||||||
ICON_GRAIN = "mdi:grain"
|
ICON_GRAIN = "mdi:grain"
|
||||||
|
ICON_KEY_PLUS = "mdi:key-plus"
|
||||||
ICON_LIGHTBULB = "mdi:lightbulb"
|
ICON_LIGHTBULB = "mdi:lightbulb"
|
||||||
ICON_MAGNET = "mdi:magnet"
|
ICON_MAGNET = "mdi:magnet"
|
||||||
ICON_MOLECULE_CO2 = "mdi:molecule-co2"
|
ICON_MOLECULE_CO2 = "mdi:molecule-co2"
|
||||||
|
@ -632,6 +654,7 @@ ICON_RULER = "mdi:ruler"
|
||||||
ICON_SCALE = "mdi:scale"
|
ICON_SCALE = "mdi:scale"
|
||||||
ICON_SCALE_BATHROOM = "mdi:scale-bathroom"
|
ICON_SCALE_BATHROOM = "mdi:scale-bathroom"
|
||||||
ICON_SCREEN_ROTATION = "mdi:screen-rotation"
|
ICON_SCREEN_ROTATION = "mdi:screen-rotation"
|
||||||
|
ICON_SECURITY = "mdi:security"
|
||||||
ICON_SIGN_DIRECTION = "mdi:sign-direction"
|
ICON_SIGN_DIRECTION = "mdi:sign-direction"
|
||||||
ICON_SIGNAL = "mdi:signal-distance-variant"
|
ICON_SIGNAL = "mdi:signal-distance-variant"
|
||||||
ICON_SIGNAL_DISTANCE_VARIANT = "mdi:signal"
|
ICON_SIGNAL_DISTANCE_VARIANT = "mdi:signal"
|
||||||
|
|
|
@ -177,6 +177,26 @@ api:
|
||||||
kp: 1.0
|
kp: 1.0
|
||||||
kd: 1.0
|
kd: 1.0
|
||||||
ki: 1.0
|
ki: 1.0
|
||||||
|
- service: fingerprint_grow_enroll
|
||||||
|
variables:
|
||||||
|
finger_id: int
|
||||||
|
num_scans: int
|
||||||
|
then:
|
||||||
|
- fingerprint_grow.enroll:
|
||||||
|
finger_id: !lambda 'return finger_id;'
|
||||||
|
num_scans: !lambda 'return num_scans;'
|
||||||
|
- service: fingerprint_grow_cancel_enroll
|
||||||
|
then:
|
||||||
|
- fingerprint_grow.cancel_enroll:
|
||||||
|
- service: fingerprint_grow_delete
|
||||||
|
variables:
|
||||||
|
finger_id: int
|
||||||
|
then:
|
||||||
|
- fingerprint_grow.delete:
|
||||||
|
finger_id: !lambda 'return finger_id;'
|
||||||
|
- service: fingerprint_grow_delete_all
|
||||||
|
then:
|
||||||
|
- fingerprint_grow.delete_all:
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: 'MySSID'
|
ssid: 'MySSID'
|
||||||
|
@ -424,6 +444,19 @@ sensor:
|
||||||
id: ph_ezo
|
id: ph_ezo
|
||||||
address: 99
|
address: 99
|
||||||
unit_of_measurement: 'pH'
|
unit_of_measurement: 'pH'
|
||||||
|
- platform: fingerprint_grow
|
||||||
|
fingerprint_count:
|
||||||
|
name: "Fingerprint Count"
|
||||||
|
status:
|
||||||
|
name: "Fingerprint Status"
|
||||||
|
capacity:
|
||||||
|
name: "Fingerprint Capacity"
|
||||||
|
security_level:
|
||||||
|
name: "Fingerprint Security Level"
|
||||||
|
last_finger_id:
|
||||||
|
name: "Fingerprint Last Finger ID"
|
||||||
|
last_confidence:
|
||||||
|
name: "Fingerprint Last Confidence"
|
||||||
|
|
||||||
time:
|
time:
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
|
@ -486,6 +519,8 @@ binary_sensor:
|
||||||
- platform: ttp229_bsf
|
- platform: ttp229_bsf
|
||||||
channel: 1
|
channel: 1
|
||||||
name: TTP229 BSF Test
|
name: TTP229 BSF Test
|
||||||
|
- platform: fingerprint_grow
|
||||||
|
name: "Fingerprint Enrolling"
|
||||||
- platform: custom
|
- platform: custom
|
||||||
lambda: |-
|
lambda: |-
|
||||||
auto s = new CustomBinarySensor();
|
auto s = new CustomBinarySensor();
|
||||||
|
@ -919,3 +954,33 @@ display:
|
||||||
http_request:
|
http_request:
|
||||||
useragent: esphome/device
|
useragent: esphome/device
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
|
|
||||||
|
fingerprint_grow:
|
||||||
|
sensing_pin: 4
|
||||||
|
password: 0x12FE37DC
|
||||||
|
new_password: 0xA65B9840
|
||||||
|
on_finger_scan_matched:
|
||||||
|
- homeassistant.event:
|
||||||
|
event: esphome.${devicename}_fingerprint_grow_finger_scan_matched
|
||||||
|
data:
|
||||||
|
finger_id: !lambda 'return finger_id;'
|
||||||
|
confidence: !lambda 'return confidence;'
|
||||||
|
on_finger_scan_unmatched:
|
||||||
|
- homeassistant.event:
|
||||||
|
event: esphome.${devicename}_fingerprint_grow_finger_scan_unmatched
|
||||||
|
on_enrollment_scan:
|
||||||
|
- homeassistant.event:
|
||||||
|
event: esphome.${devicename}_fingerprint_grow_enrollment_scan
|
||||||
|
data:
|
||||||
|
finger_id: !lambda 'return finger_id;'
|
||||||
|
scan_num: !lambda 'return scan_num;'
|
||||||
|
on_enrollment_done:
|
||||||
|
- homeassistant.event:
|
||||||
|
event: esphome.${devicename}_fingerprint_grow_node_enrollment_done
|
||||||
|
data:
|
||||||
|
finger_id: !lambda 'return finger_id;'
|
||||||
|
on_enrollment_failed:
|
||||||
|
- homeassistant.event:
|
||||||
|
event: esphome.${devicename}_fingerprint_grow_enrollment_failed
|
||||||
|
data:
|
||||||
|
finger_id: !lambda 'return finger_id;'
|
||||||
|
|
Loading…
Reference in a new issue