mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 12:15:33 +01:00
add person sensor (SEN21231) from usefulsensors (#4454)
* add person sensor (SEN21231) from usefulsensors * add person sensor (SEN21231) from usefulsensors * change file mode * fix tests * fix tests * rollback un-intended changes * Update esphome/components/sen21231/sen21231.cpp Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sen21231.cpp Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sen21231.cpp Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sen21231.cpp Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sen21231.cpp Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sen21231.h Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sensor.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sensor.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sensor.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sensor.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * remove unused import * Update esphome/components/sen21231/sen21231.h Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sensor.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sensor.py Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sen21231.h Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * Update esphome/components/sen21231/sen21231.h Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> * remove unused import * Update sen21231.h * lint changes * linting * linting * Update sen21231.h * Update sen21231.cpp linting * linting fixes * fix codeowners --------- Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
8e1430243e
commit
91e037346b
@ -210,6 +210,7 @@ esphome/components/sdm_meter/* @jesserockz @polyfaces
|
||||
esphome/components/sdp3x/* @Azimath
|
||||
esphome/components/selec_meter/* @sourabhjaiswal
|
||||
esphome/components/select/* @esphome/core
|
||||
esphome/components/sen21231/* @shreyaskarnik
|
||||
esphome/components/sen5x/* @martgras
|
||||
esphome/components/sensirion_common/* @martgras
|
||||
esphome/components/sensor/* @esphome/core
|
||||
|
0
esphome/components/sen21231/__init__.py
Normal file
0
esphome/components/sen21231/__init__.py
Normal file
32
esphome/components/sen21231/sen21231.cpp
Normal file
32
esphome/components/sen21231/sen21231.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "sen21231.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sen21231_sensor {
|
||||
|
||||
static const char *const TAG = "sen21231_sensor.sensor";
|
||||
|
||||
void Sen21231Sensor::update() { this->read_data_(); }
|
||||
|
||||
void Sen21231Sensor::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "SEN21231:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Communication with SEN21231 failed!");
|
||||
}
|
||||
ESP_LOGI(TAG, "SEN21231: %s", this->is_failed() ? "FAILED" : "OK");
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
void Sen21231Sensor::read_data_() {
|
||||
person_sensor_results_t results;
|
||||
this->read_bytes(PERSON_SENSOR_I2C_ADDRESS, (uint8_t *) &results, sizeof(results));
|
||||
ESP_LOGD(TAG, "SEN21231: %d faces detected", results.num_faces);
|
||||
this->publish_state(results.num_faces);
|
||||
if (results.num_faces == 1) {
|
||||
ESP_LOGD(TAG, "SEN21231: is facing towards camera: %d", results.faces[0].is_facing);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sen21231_sensor
|
||||
} // namespace esphome
|
77
esphome/components/sen21231/sen21231.h
Normal file
77
esphome/components/sen21231/sen21231.h
Normal file
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
// ref:
|
||||
// https://github.com/usefulsensors/person_sensor_pico_c/blob/main/person_sensor.h
|
||||
|
||||
namespace esphome {
|
||||
namespace sen21231_sensor {
|
||||
// The I2C address of the person sensor board.
|
||||
static const uint8_t PERSON_SENSOR_I2C_ADDRESS = 0x62;
|
||||
static const uint8_t PERSON_SENSOR_REG_MODE = 0x01;
|
||||
static const uint8_t PERSON_SENSOR_REG_ENABLE_ID = 0x02;
|
||||
static const uint8_t PERSON_SENSOR_REG_SINGLE_SHOT = 0x03;
|
||||
static const uint8_t PERSON_SENSOR_REG_CALIBRATE_ID = 0x04;
|
||||
static const uint8_t PERSON_SENSOR_REG_PERSIST_IDS = 0x05;
|
||||
static const uint8_t PERSON_SENSOR_REG_ERASE_IDS = 0x06;
|
||||
static const uint8_t PERSON_SENSOR_REG_DEBUG_MODE = 0x07;
|
||||
|
||||
static const uint8_t PERSON_SENSOR_MAX_FACES_COUNT = 4;
|
||||
static const uint8_t PERSON_SENSOR_MAX_IDS_COUNT = 7;
|
||||
|
||||
// The results returned from the sensor have a short header providing
|
||||
// information about the length of the data packet:
|
||||
// reserved: Currently unused bytes.
|
||||
// data_size: Length of the entire packet, excluding the header and
|
||||
// checksum.
|
||||
// For version 1.0 of the sensor, this should be 40.
|
||||
using person_sensor_results_header_t = struct {
|
||||
uint8_t reserved[2]; // Bytes 0-1.
|
||||
uint16_t data_size; // Bytes 2-3.
|
||||
};
|
||||
|
||||
// Each face found has a set of information associated with it:
|
||||
// box_confidence: How certain we are we have found a face, from 0 to 255.
|
||||
// box_left: X coordinate of the left side of the box, from 0 to 255.
|
||||
// box_top: Y coordinate of the top edge of the box, from 0 to 255.
|
||||
// box_width: Width of the box, where 255 is the full view port size.
|
||||
// box_height: Height of the box, where 255 is the full view port size.
|
||||
// id_confidence: How sure the sensor is about the recognition result.
|
||||
// id: Numerical ID assigned to this face.
|
||||
// is_looking_at: Whether the person is facing the camera, 0 or 1.
|
||||
using person_sensor_face_t = struct __attribute__((__packed__)) {
|
||||
uint8_t box_confidence; // Byte 1.
|
||||
uint8_t box_left; // Byte 2.
|
||||
uint8_t box_top; // Byte 3.
|
||||
uint8_t box_right; // Byte 4.
|
||||
uint8_t box_bottom; // Byte 5.
|
||||
int8_t id_confidence; // Byte 6.
|
||||
int8_t id; // Byte 7
|
||||
uint8_t is_facing; // Byte 8.
|
||||
};
|
||||
|
||||
// This is the full structure of the packet returned over the wire from the
|
||||
// sensor when we do an I2C read from the peripheral address.
|
||||
// The checksum should be the CRC16 of bytes 0 to 38. You shouldn't need to
|
||||
// verify this in practice, but we found it useful during our own debugging.
|
||||
using person_sensor_results_t = struct __attribute__((__packed__)) {
|
||||
person_sensor_results_header_t header; // Bytes 0-4.
|
||||
int8_t num_faces; // Byte 5.
|
||||
person_sensor_face_t faces[PERSON_SENSOR_MAX_FACES_COUNT]; // Bytes 6-37.
|
||||
uint16_t checksum; // Bytes 38-39.
|
||||
};
|
||||
|
||||
class Sen21231Sensor : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice {
|
||||
public:
|
||||
void update() override;
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
void read_data_();
|
||||
};
|
||||
|
||||
} // namespace sen21231_sensor
|
||||
} // namespace esphome
|
24
esphome/components/sen21231/sensor.py
Normal file
24
esphome/components/sen21231/sensor.py
Normal file
@ -0,0 +1,24 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
from esphome.const import ICON_MOTION_SENSOR
|
||||
|
||||
CODEOWNERS = ["@shreyaskarnik"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
sen21231_sensor_ns = cg.esphome_ns.namespace("sen21231_sensor")
|
||||
Sen21231Sensor = sen21231_sensor_ns.class_(
|
||||
"Sen21231Sensor", cg.PollingComponent, i2c.I2CDevice
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
sensor.sensor_schema(Sen21231Sensor, icon=ICON_MOTION_SENSOR, accuracy_decimals=1)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
.extend(i2c.i2c_device_schema(0x62))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = await sensor.new_sensor(config)
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
@ -1221,7 +1221,9 @@ sensor:
|
||||
name: "Still Energy"
|
||||
detection_distance:
|
||||
name: "Distance Detection"
|
||||
|
||||
- platform: sen21231
|
||||
name: "Person Sensor"
|
||||
i2c_id: i2c_bus
|
||||
esp32_touch:
|
||||
setup_mode: false
|
||||
iir_filter: 10ms
|
||||
|
Loading…
Reference in New Issue
Block a user