esphome 2024.11.2__py3-none-any.whl → 2024.12.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esphome/__main__.py +1 -1
- esphome/components/adc/adc_sensor.h +7 -8
- esphome/components/adc/adc_sensor_common.cpp +24 -0
- esphome/components/adc/{adc_sensor.cpp → adc_sensor_esp32.cpp} +10 -179
- esphome/components/adc/adc_sensor_esp8266.cpp +58 -0
- esphome/components/adc/adc_sensor_libretiny.cpp +48 -0
- esphome/components/adc/adc_sensor_rp2040.cpp +93 -0
- esphome/components/alarm_control_panel/alarm_control_panel_call.cpp +3 -4
- esphome/components/animation/__init__.py +1 -2
- esphome/components/apds9306/apds9306.cpp +2 -1
- esphome/components/audio/audio.h +1 -1
- esphome/components/bk72xx/__init__.py +1 -1
- esphome/components/cse7766/cse7766.cpp +1 -1
- esphome/components/datetime/datetime_entity.cpp +1 -3
- esphome/components/deep_sleep/deep_sleep_esp32.cpp +2 -2
- esphome/components/dht/dht.cpp +2 -1
- esphome/components/display/display.cpp +10 -6
- esphome/components/display/display.h +14 -0
- esphome/components/display_menu_base/__init__.py +0 -2
- esphome/components/display_menu_base/display_menu_base.cpp +1 -1
- esphome/components/dsmr/dsmr.cpp +1 -1
- esphome/components/esp32/__init__.py +100 -22
- esphome/components/esp32/boards.py +222 -14
- esphome/components/esp32_ble/__init__.py +22 -2
- esphome/components/esp32_ble/ble.cpp +39 -12
- esphome/components/esp32_ble/ble.h +2 -0
- esphome/components/esp32_ble/ble_advertising.cpp +1 -1
- esphome/components/esp32_ble/ble_uuid.cpp +9 -10
- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +4 -1
- esphome/components/esp32_camera_web_server/camera_web_server.h +1 -1
- esphome/components/esp32_rmt_led_strip/light.py +3 -3
- esphome/components/esp8266/__init__.py +5 -7
- esphome/components/ezo/ezo.cpp +14 -26
- esphome/components/font/__init__.py +10 -25
- esphome/components/font/font.cpp +5 -3
- esphome/components/graphical_display_menu/__init__.py +2 -0
- esphome/components/haier/hon_climate.cpp +79 -80
- esphome/components/hbridge/switch/__init__.py +44 -0
- esphome/components/hbridge/switch/hbridge_switch.cpp +95 -0
- esphome/components/hbridge/switch/hbridge_switch.h +50 -0
- esphome/components/hitachi_ac344/hitachi_ac344.cpp +4 -2
- esphome/components/hitachi_ac424/hitachi_ac424.cpp +4 -2
- esphome/components/homeassistant/number/homeassistant_number.cpp +3 -0
- esphome/components/hx711/hx711.cpp +1 -1
- esphome/components/hx711/hx711.h +1 -1
- esphome/components/i2c/i2c_bus_esp_idf.cpp +2 -2
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +61 -59
- esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -17
- esphome/components/ili9xxx/display.py +1 -2
- esphome/components/ili9xxx/ili9xxx_display.cpp +3 -2
- esphome/components/image/__init__.py +1 -2
- esphome/components/logger/logger.cpp +1 -1
- esphome/components/ltr501/ltr501.cpp +1 -1
- esphome/components/lvgl/defines.py +9 -2
- esphome/components/lvgl/lv_validation.py +8 -3
- esphome/components/lvgl/lvgl_esphome.cpp +1 -1
- esphome/components/lvgl/lvgl_esphome.h +19 -0
- esphome/components/lvgl/widgets/animimg.py +12 -17
- esphome/components/lvgl/widgets/img.py +1 -3
- esphome/components/lvgl/widgets/line.py +6 -0
- esphome/components/lvgl/widgets/msgbox.py +2 -1
- esphome/components/matrix_keypad/__init__.py +15 -3
- esphome/components/matrix_keypad/matrix_keypad.cpp +4 -0
- esphome/components/matrix_keypad/matrix_keypad.h +5 -0
- esphome/components/max31865/max31865.cpp +4 -2
- esphome/components/modbus_controller/modbus_controller.cpp +24 -24
- esphome/components/modbus_controller/modbus_controller.h +22 -22
- esphome/components/modbus_controller/number/modbus_number.cpp +8 -8
- esphome/components/modbus_controller/number/modbus_number.h +4 -4
- esphome/components/modbus_controller/output/modbus_output.cpp +7 -6
- esphome/components/modbus_controller/output/modbus_output.h +5 -5
- esphome/components/modbus_controller/select/modbus_select.cpp +4 -3
- esphome/components/modbus_controller/select/modbus_select.h +4 -4
- esphome/components/modbus_controller/switch/modbus_switch.cpp +5 -5
- esphome/components/modbus_controller/switch/modbus_switch.h +2 -2
- esphome/components/mqtt/__init__.py +4 -0
- esphome/components/mqtt/mqtt_alarm_control_panel.cpp +2 -5
- esphome/components/mqtt/mqtt_backend_esp32.cpp +3 -3
- esphome/components/mqtt/mqtt_client.cpp +4 -0
- esphome/components/mqtt/mqtt_client.h +6 -0
- esphome/components/mqtt/mqtt_climate.cpp +13 -3
- esphome/components/mqtt/mqtt_sensor.cpp +2 -0
- esphome/components/network/ip_address.h +1 -1
- esphome/components/nextion/__init__.py +2 -0
- esphome/components/nextion/automation.h +76 -0
- esphome/components/nextion/base_component.py +1 -0
- esphome/components/nextion/binary_sensor/__init__.py +43 -2
- esphome/components/nextion/display.py +15 -0
- esphome/components/nextion/nextion.cpp +8 -5
- esphome/components/nextion/nextion.h +7 -0
- esphome/components/nextion/nextion_upload_idf.cpp +2 -2
- esphome/components/nextion/sensor/__init__.py +38 -5
- esphome/components/nextion/switch/__init__.py +38 -2
- esphome/components/nextion/text_sensor/__init__.py +37 -2
- esphome/components/nfc/ndef_record.cpp +3 -3
- esphome/components/online_image/__init__.py +1 -0
- esphome/components/online_image/png_image.cpp +4 -0
- esphome/components/opentherm/hub.cpp +6 -7
- esphome/components/opentherm/opentherm.cpp +18 -34
- esphome/components/opentherm/opentherm.h +4 -5
- esphome/components/ota/automation.h +1 -1
- esphome/components/output/float_output.cpp +1 -1
- esphome/components/pca6416a/pca6416a.cpp +5 -3
- esphome/components/pca9554/pca9554.cpp +4 -4
- esphome/components/pipsolar/pipsolar.cpp +2 -2
- esphome/components/pipsolar/switch/pipsolar_switch.cpp +2 -2
- esphome/components/pn532/pn532_mifare_ultralight.cpp +2 -2
- esphome/components/pn7150/pn7150_mifare_ultralight.cpp +2 -2
- esphome/components/pn7160/pn7160_mifare_ultralight.cpp +2 -2
- esphome/components/qmc5883l/qmc5883l.cpp +45 -19
- esphome/components/qmc5883l/qmc5883l.h +1 -1
- esphome/components/qspi_dbi/qspi_dbi.cpp +2 -1
- esphome/components/remote_base/raw_protocol.cpp +1 -1
- esphome/components/remote_receiver/__init__.py +5 -6
- esphome/components/rotary_encoder/rotary_encoder.cpp +3 -1
- esphome/components/rp2040/__init__.py +1 -1
- esphome/components/rtl87xx/__init__.py +1 -1
- esphome/components/safe_mode/automation.h +1 -1
- esphome/components/seeed_mr60bha2/__init__.py +41 -0
- esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +173 -0
- esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +61 -0
- esphome/components/seeed_mr60bha2/sensor.py +57 -0
- esphome/components/seeed_mr60fda2/__init__.py +41 -0
- esphome/components/seeed_mr60fda2/binary_sensor.py +33 -0
- esphome/components/seeed_mr60fda2/button/__init__.py +45 -0
- esphome/components/seeed_mr60fda2/button/get_radar_parameters_button.cpp +9 -0
- esphome/components/seeed_mr60fda2/button/get_radar_parameters_button.h +18 -0
- esphome/components/seeed_mr60fda2/button/reset_radar_button.cpp +9 -0
- esphome/components/seeed_mr60fda2/button/reset_radar_button.h +18 -0
- esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +368 -0
- esphome/components/seeed_mr60fda2/seeed_mr60fda2.h +101 -0
- esphome/components/seeed_mr60fda2/select/__init__.py +59 -0
- esphome/components/seeed_mr60fda2/select/height_threshold_select.cpp +15 -0
- esphome/components/seeed_mr60fda2/select/height_threshold_select.h +18 -0
- esphome/components/seeed_mr60fda2/select/install_height_select.cpp +15 -0
- esphome/components/seeed_mr60fda2/select/install_height_select.h +18 -0
- esphome/components/seeed_mr60fda2/select/sensitivity_select.cpp +15 -0
- esphome/components/seeed_mr60fda2/select/sensitivity_select.h +18 -0
- esphome/components/sen5x/sensor.py +5 -6
- esphome/components/sgp30/sensor.py +8 -9
- esphome/components/sgp30/sgp30.cpp +2 -6
- esphome/components/shelly_dimmer/shelly_dimmer.cpp +1 -1
- esphome/components/sim800l/sim800l.cpp +1 -1
- esphome/components/sntp/sntp_component.cpp +14 -20
- esphome/components/sntp/sntp_component.h +6 -9
- esphome/components/sntp/time.py +4 -7
- esphome/components/sprinkler/sprinkler.cpp +2 -2
- esphome/components/st7735/st7735.cpp +1 -1
- esphome/components/st7789v/st7789v.cpp +1 -1
- esphome/components/st7920/st7920.cpp +2 -3
- esphome/components/stepper/stepper.h +0 -1
- esphome/components/sun_gtil2/sun_gtil2.cpp +1 -1
- esphome/components/switch/binary_sensor/__init__.py +31 -0
- esphome/components/switch/binary_sensor/switch_binary_sensor.cpp +17 -0
- esphome/components/switch/binary_sensor/switch_binary_sensor.h +22 -0
- esphome/components/sx1509/sx1509_gpio_pin.cpp +2 -1
- esphome/components/sx1509/sx1509_gpio_pin.h +5 -5
- esphome/components/uart/uart.h +1 -1
- esphome/components/udp/udp_component.cpp +32 -16
- esphome/components/ufire_ec/sensor.py +4 -4
- esphome/components/uln2003/uln2003.cpp +4 -1
- esphome/components/waveshare_epaper/display.py +8 -0
- esphome/components/waveshare_epaper/waveshare_epaper.cpp +191 -0
- esphome/components/waveshare_epaper/waveshare_epaper.h +56 -0
- esphome/components/wiegand/__init__.py +3 -4
- esphome/components/wifi/__init__.py +42 -0
- esphome/components/wifi/wifi_component.cpp +2 -2
- esphome/components/wifi/wifi_component.h +82 -1
- esphome/components/wifi/wifi_component_esp32_arduino.cpp +1 -1
- esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
- esphome/components/wifi/wifi_component_esp_idf.cpp +1 -1
- esphome/components/wifi/wifi_component_libretiny.cpp +1 -1
- esphome/components/wifi/wifi_component_pico_w.cpp +1 -1
- esphome/components/wireguard/wireguard.cpp +2 -2
- esphome/components/xiaomi_ble/xiaomi_ble.cpp +1 -1
- esphome/config_validation.py +15 -11
- esphome/const.py +11 -1
- esphome/core/component.cpp +1 -1
- esphome/core/config.py +1 -2
- esphome/core/defines.h +3 -1
- esphome/core/helpers.cpp +20 -2
- esphome/core/helpers.h +10 -1
- esphome/core/optional.h +2 -2
- esphome/core/time.cpp +19 -15
- esphome/core/time.h +1 -3
- esphome/dashboard/web_server.py +6 -0
- {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/METADATA +4 -4
- {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/RECORD +192 -162
- {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/LICENSE +0 -0
- {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/WHEEL +0 -0
- {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/entry_points.txt +0 -0
- {esphome-2024.11.2.dist-info → esphome-2024.12.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
from esphome.components import uart
|
3
|
+
import esphome.config_validation as cv
|
4
|
+
from esphome.const import CONF_ID
|
5
|
+
|
6
|
+
CODEOWNERS = ["@limengdu"]
|
7
|
+
DEPENDENCIES = ["uart"]
|
8
|
+
MULTI_CONF = True
|
9
|
+
|
10
|
+
mr60bha2_ns = cg.esphome_ns.namespace("seeed_mr60bha2")
|
11
|
+
|
12
|
+
MR60BHA2Component = mr60bha2_ns.class_(
|
13
|
+
"MR60BHA2Component", cg.Component, uart.UARTDevice
|
14
|
+
)
|
15
|
+
|
16
|
+
CONF_MR60BHA2_ID = "mr60bha2_id"
|
17
|
+
|
18
|
+
CONFIG_SCHEMA = (
|
19
|
+
cv.Schema(
|
20
|
+
{
|
21
|
+
cv.GenerateID(): cv.declare_id(MR60BHA2Component),
|
22
|
+
}
|
23
|
+
)
|
24
|
+
.extend(uart.UART_DEVICE_SCHEMA)
|
25
|
+
.extend(cv.COMPONENT_SCHEMA)
|
26
|
+
)
|
27
|
+
|
28
|
+
FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
|
29
|
+
"seeed_mr60bha2",
|
30
|
+
require_tx=True,
|
31
|
+
require_rx=True,
|
32
|
+
baud_rate=115200,
|
33
|
+
parity="NONE",
|
34
|
+
stop_bits=1,
|
35
|
+
)
|
36
|
+
|
37
|
+
|
38
|
+
async def to_code(config):
|
39
|
+
var = cg.new_Pvariable(config[CONF_ID])
|
40
|
+
await cg.register_component(var, config)
|
41
|
+
await uart.register_uart_device(var, config)
|
@@ -0,0 +1,173 @@
|
|
1
|
+
#include "seeed_mr60bha2.h"
|
2
|
+
#include "esphome/core/log.h"
|
3
|
+
|
4
|
+
#include <utility>
|
5
|
+
|
6
|
+
namespace esphome {
|
7
|
+
namespace seeed_mr60bha2 {
|
8
|
+
|
9
|
+
static const char *const TAG = "seeed_mr60bha2";
|
10
|
+
|
11
|
+
// Prints the component's configuration data. dump_config() prints all of the component's configuration
|
12
|
+
// items in an easy-to-read format, including the configuration key-value pairs.
|
13
|
+
void MR60BHA2Component::dump_config() {
|
14
|
+
ESP_LOGCONFIG(TAG, "MR60BHA2:");
|
15
|
+
#ifdef USE_SENSOR
|
16
|
+
LOG_SENSOR(" ", "Breath Rate Sensor", this->breath_rate_sensor_);
|
17
|
+
LOG_SENSOR(" ", "Heart Rate Sensor", this->heart_rate_sensor_);
|
18
|
+
LOG_SENSOR(" ", "Distance Sensor", this->distance_sensor_);
|
19
|
+
#endif
|
20
|
+
}
|
21
|
+
|
22
|
+
// main loop
|
23
|
+
void MR60BHA2Component::loop() {
|
24
|
+
uint8_t byte;
|
25
|
+
|
26
|
+
// Is there data on the serial port
|
27
|
+
while (this->available()) {
|
28
|
+
this->read_byte(&byte);
|
29
|
+
this->rx_message_.push_back(byte);
|
30
|
+
if (!this->validate_message_()) {
|
31
|
+
this->rx_message_.clear();
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
/**
|
37
|
+
* @brief Calculate the checksum for a byte array.
|
38
|
+
*
|
39
|
+
* This function calculates the checksum for the provided byte array using an
|
40
|
+
* XOR-based checksum algorithm.
|
41
|
+
*
|
42
|
+
* @param data The byte array to calculate the checksum for.
|
43
|
+
* @param len The length of the byte array.
|
44
|
+
* @return The calculated checksum.
|
45
|
+
*/
|
46
|
+
static uint8_t calculate_checksum(const uint8_t *data, size_t len) {
|
47
|
+
uint8_t checksum = 0;
|
48
|
+
for (size_t i = 0; i < len; i++) {
|
49
|
+
checksum ^= data[i];
|
50
|
+
}
|
51
|
+
checksum = ~checksum;
|
52
|
+
return checksum;
|
53
|
+
}
|
54
|
+
|
55
|
+
/**
|
56
|
+
* @brief Validate the checksum of a byte array.
|
57
|
+
*
|
58
|
+
* This function validates the checksum of the provided byte array by comparing
|
59
|
+
* it to the expected checksum.
|
60
|
+
*
|
61
|
+
* @param data The byte array to validate.
|
62
|
+
* @param len The length of the byte array.
|
63
|
+
* @param expected_checksum The expected checksum.
|
64
|
+
* @return True if the checksum is valid, false otherwise.
|
65
|
+
*/
|
66
|
+
static bool validate_checksum(const uint8_t *data, size_t len, uint8_t expected_checksum) {
|
67
|
+
return calculate_checksum(data, len) == expected_checksum;
|
68
|
+
}
|
69
|
+
|
70
|
+
bool MR60BHA2Component::validate_message_() {
|
71
|
+
size_t at = this->rx_message_.size() - 1;
|
72
|
+
auto *data = &this->rx_message_[0];
|
73
|
+
uint8_t new_byte = data[at];
|
74
|
+
|
75
|
+
if (at == 0) {
|
76
|
+
return new_byte == FRAME_HEADER_BUFFER;
|
77
|
+
}
|
78
|
+
|
79
|
+
if (at <= 2) {
|
80
|
+
return true;
|
81
|
+
}
|
82
|
+
uint16_t frame_id = encode_uint16(data[1], data[2]);
|
83
|
+
|
84
|
+
if (at <= 4) {
|
85
|
+
return true;
|
86
|
+
}
|
87
|
+
|
88
|
+
uint16_t length = encode_uint16(data[3], data[4]);
|
89
|
+
|
90
|
+
if (at <= 6) {
|
91
|
+
return true;
|
92
|
+
}
|
93
|
+
|
94
|
+
uint16_t frame_type = encode_uint16(data[5], data[6]);
|
95
|
+
|
96
|
+
if (frame_type != BREATH_RATE_TYPE_BUFFER && frame_type != HEART_RATE_TYPE_BUFFER &&
|
97
|
+
frame_type != DISTANCE_TYPE_BUFFER) {
|
98
|
+
return false;
|
99
|
+
}
|
100
|
+
|
101
|
+
uint8_t header_checksum = new_byte;
|
102
|
+
|
103
|
+
if (at == 7) {
|
104
|
+
if (!validate_checksum(data, 7, header_checksum)) {
|
105
|
+
ESP_LOGE(TAG, "HEAD_CKSUM_FRAME ERROR: 0x%02x", header_checksum);
|
106
|
+
ESP_LOGV(TAG, "GET FRAME: %s", format_hex_pretty(data, 8).c_str());
|
107
|
+
return false;
|
108
|
+
}
|
109
|
+
return true;
|
110
|
+
}
|
111
|
+
|
112
|
+
// Wait until all data is read
|
113
|
+
if (at - 8 < length) {
|
114
|
+
return true;
|
115
|
+
}
|
116
|
+
|
117
|
+
uint8_t data_checksum = new_byte;
|
118
|
+
if (at == 8 + length) {
|
119
|
+
if (!validate_checksum(data + 8, length, data_checksum)) {
|
120
|
+
ESP_LOGE(TAG, "DATA_CKSUM_FRAME ERROR: 0x%02x", data_checksum);
|
121
|
+
ESP_LOGV(TAG, "GET FRAME: %s", format_hex_pretty(data, 8 + length).c_str());
|
122
|
+
return false;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
const uint8_t *frame_data = data + 8;
|
127
|
+
ESP_LOGV(TAG, "Received Frame: ID: 0x%04x, Type: 0x%04x, Data: [%s] Raw Data: [%s]", frame_id, frame_type,
|
128
|
+
format_hex_pretty(frame_data, length).c_str(), format_hex_pretty(this->rx_message_).c_str());
|
129
|
+
this->process_frame_(frame_id, frame_type, data + 8, length);
|
130
|
+
|
131
|
+
// Return false to reset rx buffer
|
132
|
+
return false;
|
133
|
+
}
|
134
|
+
|
135
|
+
void MR60BHA2Component::process_frame_(uint16_t frame_id, uint16_t frame_type, const uint8_t *data, size_t length) {
|
136
|
+
switch (frame_type) {
|
137
|
+
case BREATH_RATE_TYPE_BUFFER:
|
138
|
+
if (this->breath_rate_sensor_ != nullptr && length >= 4) {
|
139
|
+
uint32_t current_breath_rate_int = encode_uint32(data[3], data[2], data[1], data[0]);
|
140
|
+
if (current_breath_rate_int != 0) {
|
141
|
+
float breath_rate_float;
|
142
|
+
memcpy(&breath_rate_float, ¤t_breath_rate_int, sizeof(float));
|
143
|
+
this->breath_rate_sensor_->publish_state(breath_rate_float);
|
144
|
+
}
|
145
|
+
}
|
146
|
+
break;
|
147
|
+
case HEART_RATE_TYPE_BUFFER:
|
148
|
+
if (this->heart_rate_sensor_ != nullptr && length >= 4) {
|
149
|
+
uint32_t current_heart_rate_int = encode_uint32(data[3], data[2], data[1], data[0]);
|
150
|
+
if (current_heart_rate_int != 0) {
|
151
|
+
float heart_rate_float;
|
152
|
+
memcpy(&heart_rate_float, ¤t_heart_rate_int, sizeof(float));
|
153
|
+
this->heart_rate_sensor_->publish_state(heart_rate_float);
|
154
|
+
}
|
155
|
+
}
|
156
|
+
break;
|
157
|
+
case DISTANCE_TYPE_BUFFER:
|
158
|
+
if (!data[0]) {
|
159
|
+
if (this->distance_sensor_ != nullptr && length >= 8) {
|
160
|
+
uint32_t current_distance_int = encode_uint32(data[7], data[6], data[5], data[4]);
|
161
|
+
float distance_float;
|
162
|
+
memcpy(&distance_float, ¤t_distance_int, sizeof(float));
|
163
|
+
this->distance_sensor_->publish_state(distance_float);
|
164
|
+
}
|
165
|
+
}
|
166
|
+
break;
|
167
|
+
default:
|
168
|
+
break;
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
} // namespace seeed_mr60bha2
|
173
|
+
} // namespace esphome
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#pragma once
|
2
|
+
#include "esphome/core/component.h"
|
3
|
+
#include "esphome/core/defines.h"
|
4
|
+
#ifdef USE_SENSOR
|
5
|
+
#include "esphome/components/sensor/sensor.h"
|
6
|
+
#endif
|
7
|
+
#include "esphome/components/uart/uart.h"
|
8
|
+
#include "esphome/core/automation.h"
|
9
|
+
#include "esphome/core/helpers.h"
|
10
|
+
|
11
|
+
#include <map>
|
12
|
+
|
13
|
+
namespace esphome {
|
14
|
+
namespace seeed_mr60bha2 {
|
15
|
+
|
16
|
+
static const uint8_t DATA_BUF_MAX_SIZE = 12;
|
17
|
+
static const uint8_t FRAME_BUF_MAX_SIZE = 21;
|
18
|
+
static const uint8_t LEN_TO_HEAD_CKSUM = 8;
|
19
|
+
static const uint8_t LEN_TO_DATA_FRAME = 9;
|
20
|
+
|
21
|
+
static const uint8_t FRAME_HEADER_BUFFER = 0x01;
|
22
|
+
static const uint16_t BREATH_RATE_TYPE_BUFFER = 0x0A14;
|
23
|
+
static const uint16_t HEART_RATE_TYPE_BUFFER = 0x0A15;
|
24
|
+
static const uint16_t DISTANCE_TYPE_BUFFER = 0x0A16;
|
25
|
+
|
26
|
+
enum FrameLocation {
|
27
|
+
LOCATE_FRAME_HEADER,
|
28
|
+
LOCATE_ID_FRAME1,
|
29
|
+
LOCATE_ID_FRAME2,
|
30
|
+
LOCATE_LENGTH_FRAME_H,
|
31
|
+
LOCATE_LENGTH_FRAME_L,
|
32
|
+
LOCATE_TYPE_FRAME1,
|
33
|
+
LOCATE_TYPE_FRAME2,
|
34
|
+
LOCATE_HEAD_CKSUM_FRAME, // Header checksum: [from the first byte to the previous byte of the HEAD_CKSUM bit]
|
35
|
+
LOCATE_DATA_FRAME,
|
36
|
+
LOCATE_DATA_CKSUM_FRAME, // Data checksum: [from the first to the previous byte of the DATA_CKSUM bit]
|
37
|
+
LOCATE_PROCESS_FRAME,
|
38
|
+
};
|
39
|
+
|
40
|
+
class MR60BHA2Component : public Component,
|
41
|
+
public uart::UARTDevice { // The class name must be the name defined by text_sensor.py
|
42
|
+
#ifdef USE_SENSOR
|
43
|
+
SUB_SENSOR(breath_rate);
|
44
|
+
SUB_SENSOR(heart_rate);
|
45
|
+
SUB_SENSOR(distance);
|
46
|
+
#endif
|
47
|
+
|
48
|
+
public:
|
49
|
+
float get_setup_priority() const override { return esphome::setup_priority::LATE; }
|
50
|
+
void dump_config() override;
|
51
|
+
void loop() override;
|
52
|
+
|
53
|
+
protected:
|
54
|
+
bool validate_message_();
|
55
|
+
void process_frame_(uint16_t frame_id, uint16_t frame_type, const uint8_t *data, size_t length);
|
56
|
+
|
57
|
+
std::vector<uint8_t> rx_message_;
|
58
|
+
};
|
59
|
+
|
60
|
+
} // namespace seeed_mr60bha2
|
61
|
+
} // namespace esphome
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
from esphome.components import sensor
|
3
|
+
import esphome.config_validation as cv
|
4
|
+
from esphome.const import (
|
5
|
+
CONF_DISTANCE,
|
6
|
+
DEVICE_CLASS_DISTANCE,
|
7
|
+
ICON_HEART_PULSE,
|
8
|
+
ICON_PULSE,
|
9
|
+
ICON_SIGNAL,
|
10
|
+
STATE_CLASS_MEASUREMENT,
|
11
|
+
UNIT_BEATS_PER_MINUTE,
|
12
|
+
UNIT_CENTIMETER,
|
13
|
+
)
|
14
|
+
|
15
|
+
from . import CONF_MR60BHA2_ID, MR60BHA2Component
|
16
|
+
|
17
|
+
DEPENDENCIES = ["seeed_mr60bha2"]
|
18
|
+
|
19
|
+
CONF_BREATH_RATE = "breath_rate"
|
20
|
+
CONF_HEART_RATE = "heart_rate"
|
21
|
+
|
22
|
+
CONFIG_SCHEMA = cv.Schema(
|
23
|
+
{
|
24
|
+
cv.GenerateID(CONF_MR60BHA2_ID): cv.use_id(MR60BHA2Component),
|
25
|
+
cv.Optional(CONF_BREATH_RATE): sensor.sensor_schema(
|
26
|
+
accuracy_decimals=2,
|
27
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
28
|
+
icon=ICON_PULSE,
|
29
|
+
),
|
30
|
+
cv.Optional(CONF_HEART_RATE): sensor.sensor_schema(
|
31
|
+
accuracy_decimals=0,
|
32
|
+
icon=ICON_HEART_PULSE,
|
33
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
34
|
+
unit_of_measurement=UNIT_BEATS_PER_MINUTE,
|
35
|
+
),
|
36
|
+
cv.Optional(CONF_DISTANCE): sensor.sensor_schema(
|
37
|
+
device_class=DEVICE_CLASS_DISTANCE,
|
38
|
+
state_class=STATE_CLASS_MEASUREMENT,
|
39
|
+
unit_of_measurement=UNIT_CENTIMETER,
|
40
|
+
accuracy_decimals=2,
|
41
|
+
icon=ICON_SIGNAL,
|
42
|
+
),
|
43
|
+
}
|
44
|
+
)
|
45
|
+
|
46
|
+
|
47
|
+
async def to_code(config):
|
48
|
+
mr60bha2_component = await cg.get_variable(config[CONF_MR60BHA2_ID])
|
49
|
+
if breath_rate_config := config.get(CONF_BREATH_RATE):
|
50
|
+
sens = await sensor.new_sensor(breath_rate_config)
|
51
|
+
cg.add(mr60bha2_component.set_breath_rate_sensor(sens))
|
52
|
+
if heart_rate_config := config.get(CONF_HEART_RATE):
|
53
|
+
sens = await sensor.new_sensor(heart_rate_config)
|
54
|
+
cg.add(mr60bha2_component.set_heart_rate_sensor(sens))
|
55
|
+
if distance_config := config.get(CONF_DISTANCE):
|
56
|
+
sens = await sensor.new_sensor(distance_config)
|
57
|
+
cg.add(mr60bha2_component.set_distance_sensor(sens))
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
from esphome.components import uart
|
3
|
+
import esphome.config_validation as cv
|
4
|
+
from esphome.const import CONF_ID
|
5
|
+
|
6
|
+
CODEOWNERS = ["@limengdu"]
|
7
|
+
DEPENDENCIES = ["uart"]
|
8
|
+
MULTI_CONF = True
|
9
|
+
|
10
|
+
mr60fda2_ns = cg.esphome_ns.namespace("seeed_mr60fda2")
|
11
|
+
|
12
|
+
MR60FDA2Component = mr60fda2_ns.class_(
|
13
|
+
"MR60FDA2Component", cg.Component, uart.UARTDevice
|
14
|
+
)
|
15
|
+
|
16
|
+
CONF_MR60FDA2_ID = "mr60fda2_id"
|
17
|
+
|
18
|
+
CONFIG_SCHEMA = (
|
19
|
+
cv.Schema(
|
20
|
+
{
|
21
|
+
cv.GenerateID(): cv.declare_id(MR60FDA2Component),
|
22
|
+
}
|
23
|
+
)
|
24
|
+
.extend(uart.UART_DEVICE_SCHEMA)
|
25
|
+
.extend(cv.COMPONENT_SCHEMA)
|
26
|
+
)
|
27
|
+
|
28
|
+
FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
|
29
|
+
"seeed_mr60fda2",
|
30
|
+
require_tx=True,
|
31
|
+
require_rx=True,
|
32
|
+
baud_rate=115200,
|
33
|
+
parity="NONE",
|
34
|
+
stop_bits=1,
|
35
|
+
)
|
36
|
+
|
37
|
+
|
38
|
+
async def to_code(config):
|
39
|
+
var = cg.new_Pvariable(config[CONF_ID])
|
40
|
+
await cg.register_component(var, config)
|
41
|
+
await uart.register_uart_device(var, config)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
from esphome.components import binary_sensor
|
3
|
+
import esphome.config_validation as cv
|
4
|
+
from esphome.const import DEVICE_CLASS_OCCUPANCY, DEVICE_CLASS_SAFETY
|
5
|
+
|
6
|
+
from . import CONF_MR60FDA2_ID, MR60FDA2Component
|
7
|
+
|
8
|
+
DEPENDENCIES = ["seeed_mr60fda2"]
|
9
|
+
|
10
|
+
CONF_PEOPLE_EXIST = "people_exist"
|
11
|
+
CONF_FALL_DETECTED = "fall_detected"
|
12
|
+
|
13
|
+
CONFIG_SCHEMA = {
|
14
|
+
cv.GenerateID(CONF_MR60FDA2_ID): cv.use_id(MR60FDA2Component),
|
15
|
+
cv.Optional(CONF_PEOPLE_EXIST): binary_sensor.binary_sensor_schema(
|
16
|
+
device_class=DEVICE_CLASS_OCCUPANCY, icon="mdi:motion-sensor"
|
17
|
+
),
|
18
|
+
cv.Optional(CONF_FALL_DETECTED): binary_sensor.binary_sensor_schema(
|
19
|
+
device_class=DEVICE_CLASS_SAFETY, icon="mdi:emergency"
|
20
|
+
),
|
21
|
+
}
|
22
|
+
|
23
|
+
|
24
|
+
async def to_code(config):
|
25
|
+
mr60fda2_component = await cg.get_variable(config[CONF_MR60FDA2_ID])
|
26
|
+
|
27
|
+
if people_exist_config := config.get(CONF_PEOPLE_EXIST):
|
28
|
+
sens = await binary_sensor.new_binary_sensor(people_exist_config)
|
29
|
+
cg.add(mr60fda2_component.set_people_exist_binary_sensor(sens))
|
30
|
+
|
31
|
+
if is_fall_config := config.get(CONF_FALL_DETECTED):
|
32
|
+
sens = await binary_sensor.new_binary_sensor(is_fall_config)
|
33
|
+
cg.add(mr60fda2_component.set_fall_detected_binary_sensor(sens))
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import esphome.codegen as cg
|
2
|
+
from esphome.components import button
|
3
|
+
import esphome.config_validation as cv
|
4
|
+
from esphome.const import (
|
5
|
+
DEVICE_CLASS_RESTART,
|
6
|
+
DEVICE_CLASS_UPDATE,
|
7
|
+
ENTITY_CATEGORY_DIAGNOSTIC,
|
8
|
+
ENTITY_CATEGORY_NONE,
|
9
|
+
CONF_FACTORY_RESET,
|
10
|
+
)
|
11
|
+
|
12
|
+
from .. import CONF_MR60FDA2_ID, MR60FDA2Component, mr60fda2_ns
|
13
|
+
|
14
|
+
DEPENDENCIES = ["seeed_mr60fda2"]
|
15
|
+
|
16
|
+
GetRadarParametersButton = mr60fda2_ns.class_("GetRadarParametersButton", button.Button)
|
17
|
+
ResetRadarButton = mr60fda2_ns.class_("ResetRadarButton", button.Button)
|
18
|
+
|
19
|
+
CONF_GET_RADAR_PARAMETERS = "get_radar_parameters"
|
20
|
+
|
21
|
+
CONFIG_SCHEMA = {
|
22
|
+
cv.GenerateID(CONF_MR60FDA2_ID): cv.use_id(MR60FDA2Component),
|
23
|
+
cv.Optional(CONF_GET_RADAR_PARAMETERS): button.button_schema(
|
24
|
+
GetRadarParametersButton,
|
25
|
+
device_class=DEVICE_CLASS_UPDATE,
|
26
|
+
entity_category=ENTITY_CATEGORY_NONE,
|
27
|
+
),
|
28
|
+
cv.Optional(CONF_FACTORY_RESET): button.button_schema(
|
29
|
+
ResetRadarButton,
|
30
|
+
device_class=DEVICE_CLASS_RESTART,
|
31
|
+
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
32
|
+
),
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
async def to_code(config):
|
37
|
+
mr60fda2_component = await cg.get_variable(config[CONF_MR60FDA2_ID])
|
38
|
+
if get_radar_parameters_config := config.get(CONF_GET_RADAR_PARAMETERS):
|
39
|
+
b = await button.new_button(get_radar_parameters_config)
|
40
|
+
await cg.register_parented(b, config[CONF_MR60FDA2_ID])
|
41
|
+
cg.add(mr60fda2_component.set_get_radar_parameters_button(b))
|
42
|
+
if factory_reset_config := config.get(CONF_FACTORY_RESET):
|
43
|
+
b = await button.new_button(factory_reset_config)
|
44
|
+
await cg.register_parented(b, config[CONF_MR60FDA2_ID])
|
45
|
+
cg.add(mr60fda2_component.set_factory_reset_button(b))
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "esphome/components/button/button.h"
|
4
|
+
#include "../seeed_mr60fda2.h"
|
5
|
+
|
6
|
+
namespace esphome {
|
7
|
+
namespace seeed_mr60fda2 {
|
8
|
+
|
9
|
+
class GetRadarParametersButton : public button::Button, public Parented<MR60FDA2Component> {
|
10
|
+
public:
|
11
|
+
GetRadarParametersButton() = default;
|
12
|
+
|
13
|
+
protected:
|
14
|
+
void press_action() override;
|
15
|
+
};
|
16
|
+
|
17
|
+
} // namespace seeed_mr60fda2
|
18
|
+
} // namespace esphome
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include "esphome/components/button/button.h"
|
4
|
+
#include "../seeed_mr60fda2.h"
|
5
|
+
|
6
|
+
namespace esphome {
|
7
|
+
namespace seeed_mr60fda2 {
|
8
|
+
|
9
|
+
class ResetRadarButton : public button::Button, public Parented<MR60FDA2Component> {
|
10
|
+
public:
|
11
|
+
ResetRadarButton() = default;
|
12
|
+
|
13
|
+
protected:
|
14
|
+
void press_action() override;
|
15
|
+
};
|
16
|
+
|
17
|
+
} // namespace seeed_mr60fda2
|
18
|
+
} // namespace esphome
|