esphome 2024.11.3__py3-none-any.whl → 2024.12.0b1__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.
Files changed (178) hide show
  1. esphome/components/adc/adc_sensor.h +7 -8
  2. esphome/components/adc/adc_sensor_common.cpp +24 -0
  3. esphome/components/adc/{adc_sensor.cpp → adc_sensor_esp32.cpp} +10 -179
  4. esphome/components/adc/adc_sensor_esp8266.cpp +58 -0
  5. esphome/components/adc/adc_sensor_rp2040.cpp +93 -0
  6. esphome/components/alarm_control_panel/alarm_control_panel_call.cpp +3 -4
  7. esphome/components/animation/__init__.py +1 -2
  8. esphome/components/apds9306/apds9306.cpp +2 -1
  9. esphome/components/audio/audio.h +1 -1
  10. esphome/components/bk72xx/__init__.py +1 -1
  11. esphome/components/cse7766/cse7766.cpp +1 -1
  12. esphome/components/deep_sleep/deep_sleep_esp32.cpp +2 -2
  13. esphome/components/dht/dht.cpp +2 -1
  14. esphome/components/display/display.cpp +10 -6
  15. esphome/components/display/display.h +14 -0
  16. esphome/components/display_menu_base/__init__.py +0 -2
  17. esphome/components/display_menu_base/display_menu_base.cpp +1 -1
  18. esphome/components/dsmr/dsmr.cpp +1 -1
  19. esphome/components/esp32/__init__.py +94 -12
  20. esphome/components/esp32/boards.py +222 -14
  21. esphome/components/esp32_ble/__init__.py +22 -2
  22. esphome/components/esp32_ble/ble.cpp +13 -5
  23. esphome/components/esp32_ble/ble.h +2 -0
  24. esphome/components/esp32_ble/ble_advertising.cpp +1 -1
  25. esphome/components/esp32_ble/ble_uuid.cpp +9 -10
  26. esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +4 -1
  27. esphome/components/esp32_camera_web_server/camera_web_server.h +1 -1
  28. esphome/components/esp32_rmt_led_strip/light.py +3 -3
  29. esphome/components/esp8266/__init__.py +5 -7
  30. esphome/components/ezo/ezo.cpp +14 -26
  31. esphome/components/font/__init__.py +5 -23
  32. esphome/components/font/font.cpp +5 -3
  33. esphome/components/graphical_display_menu/__init__.py +2 -0
  34. esphome/components/haier/hon_climate.cpp +79 -80
  35. esphome/components/hbridge/switch/__init__.py +44 -0
  36. esphome/components/hbridge/switch/hbridge_switch.cpp +95 -0
  37. esphome/components/hbridge/switch/hbridge_switch.h +50 -0
  38. esphome/components/hitachi_ac344/hitachi_ac344.cpp +4 -2
  39. esphome/components/hitachi_ac424/hitachi_ac424.cpp +4 -2
  40. esphome/components/homeassistant/number/homeassistant_number.cpp +3 -0
  41. esphome/components/hx711/hx711.cpp +1 -1
  42. esphome/components/hx711/hx711.h +1 -1
  43. esphome/components/i2c/i2c_bus_esp_idf.cpp +2 -2
  44. esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +61 -59
  45. esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +8 -17
  46. esphome/components/ili9xxx/display.py +1 -2
  47. esphome/components/ili9xxx/ili9xxx_display.cpp +3 -2
  48. esphome/components/image/__init__.py +1 -2
  49. esphome/components/logger/logger.cpp +1 -1
  50. esphome/components/ltr501/ltr501.cpp +1 -1
  51. esphome/components/lvgl/defines.py +8 -1
  52. esphome/components/lvgl/lv_validation.py +8 -3
  53. esphome/components/lvgl/lvgl_esphome.cpp +1 -1
  54. esphome/components/lvgl/lvgl_esphome.h +16 -0
  55. esphome/components/lvgl/widgets/animimg.py +12 -17
  56. esphome/components/lvgl/widgets/img.py +1 -3
  57. esphome/components/matrix_keypad/__init__.py +15 -3
  58. esphome/components/matrix_keypad/matrix_keypad.cpp +4 -0
  59. esphome/components/matrix_keypad/matrix_keypad.h +5 -0
  60. esphome/components/max31865/max31865.cpp +4 -2
  61. esphome/components/modbus_controller/modbus_controller.cpp +24 -24
  62. esphome/components/modbus_controller/modbus_controller.h +22 -22
  63. esphome/components/modbus_controller/number/modbus_number.cpp +8 -8
  64. esphome/components/modbus_controller/number/modbus_number.h +4 -4
  65. esphome/components/modbus_controller/output/modbus_output.cpp +7 -6
  66. esphome/components/modbus_controller/output/modbus_output.h +5 -5
  67. esphome/components/modbus_controller/select/modbus_select.cpp +4 -3
  68. esphome/components/modbus_controller/select/modbus_select.h +4 -4
  69. esphome/components/modbus_controller/switch/modbus_switch.cpp +5 -5
  70. esphome/components/modbus_controller/switch/modbus_switch.h +2 -2
  71. esphome/components/mqtt/__init__.py +4 -0
  72. esphome/components/mqtt/mqtt_alarm_control_panel.cpp +2 -5
  73. esphome/components/mqtt/mqtt_backend_esp32.cpp +3 -3
  74. esphome/components/mqtt/mqtt_client.cpp +4 -0
  75. esphome/components/mqtt/mqtt_client.h +6 -0
  76. esphome/components/mqtt/mqtt_climate.cpp +13 -3
  77. esphome/components/mqtt/mqtt_sensor.cpp +2 -0
  78. esphome/components/network/ip_address.h +1 -1
  79. esphome/components/nextion/__init__.py +2 -0
  80. esphome/components/nextion/automation.h +76 -0
  81. esphome/components/nextion/base_component.py +1 -0
  82. esphome/components/nextion/binary_sensor/__init__.py +43 -2
  83. esphome/components/nextion/display.py +15 -0
  84. esphome/components/nextion/nextion.cpp +8 -5
  85. esphome/components/nextion/nextion.h +7 -0
  86. esphome/components/nextion/nextion_upload_idf.cpp +2 -2
  87. esphome/components/nextion/sensor/__init__.py +38 -5
  88. esphome/components/nextion/switch/__init__.py +38 -2
  89. esphome/components/nextion/text_sensor/__init__.py +37 -2
  90. esphome/components/nfc/ndef_record.cpp +3 -3
  91. esphome/components/online_image/__init__.py +1 -0
  92. esphome/components/opentherm/opentherm.cpp +3 -3
  93. esphome/components/opentherm/opentherm.h +1 -1
  94. esphome/components/ota/automation.h +1 -1
  95. esphome/components/output/float_output.cpp +1 -1
  96. esphome/components/pca6416a/pca6416a.cpp +5 -3
  97. esphome/components/pca9554/pca9554.cpp +4 -4
  98. esphome/components/pipsolar/pipsolar.cpp +2 -2
  99. esphome/components/pipsolar/switch/pipsolar_switch.cpp +2 -2
  100. esphome/components/pn532/pn532_mifare_ultralight.cpp +2 -2
  101. esphome/components/pn7150/pn7150_mifare_ultralight.cpp +2 -2
  102. esphome/components/pn7160/pn7160_mifare_ultralight.cpp +2 -2
  103. esphome/components/qmc5883l/qmc5883l.cpp +45 -19
  104. esphome/components/qmc5883l/qmc5883l.h +1 -1
  105. esphome/components/qspi_dbi/qspi_dbi.cpp +2 -1
  106. esphome/components/remote_base/raw_protocol.cpp +1 -1
  107. esphome/components/rotary_encoder/rotary_encoder.cpp +3 -1
  108. esphome/components/rp2040/__init__.py +1 -1
  109. esphome/components/rtl87xx/__init__.py +1 -1
  110. esphome/components/safe_mode/automation.h +1 -1
  111. esphome/components/seeed_mr60bha2/__init__.py +41 -0
  112. esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +173 -0
  113. esphome/components/seeed_mr60bha2/seeed_mr60bha2.h +61 -0
  114. esphome/components/seeed_mr60bha2/sensor.py +57 -0
  115. esphome/components/seeed_mr60fda2/__init__.py +41 -0
  116. esphome/components/seeed_mr60fda2/binary_sensor.py +33 -0
  117. esphome/components/seeed_mr60fda2/button/__init__.py +45 -0
  118. esphome/components/seeed_mr60fda2/button/get_radar_parameters_button.cpp +9 -0
  119. esphome/components/seeed_mr60fda2/button/get_radar_parameters_button.h +18 -0
  120. esphome/components/seeed_mr60fda2/button/reset_radar_button.cpp +9 -0
  121. esphome/components/seeed_mr60fda2/button/reset_radar_button.h +18 -0
  122. esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +368 -0
  123. esphome/components/seeed_mr60fda2/seeed_mr60fda2.h +101 -0
  124. esphome/components/seeed_mr60fda2/select/__init__.py +59 -0
  125. esphome/components/seeed_mr60fda2/select/height_threshold_select.cpp +15 -0
  126. esphome/components/seeed_mr60fda2/select/height_threshold_select.h +18 -0
  127. esphome/components/seeed_mr60fda2/select/install_height_select.cpp +15 -0
  128. esphome/components/seeed_mr60fda2/select/install_height_select.h +18 -0
  129. esphome/components/seeed_mr60fda2/select/sensitivity_select.cpp +15 -0
  130. esphome/components/seeed_mr60fda2/select/sensitivity_select.h +18 -0
  131. esphome/components/sen5x/sensor.py +5 -6
  132. esphome/components/shelly_dimmer/shelly_dimmer.cpp +1 -1
  133. esphome/components/sim800l/sim800l.cpp +1 -1
  134. esphome/components/sntp/sntp_component.cpp +14 -20
  135. esphome/components/sntp/sntp_component.h +6 -9
  136. esphome/components/sntp/time.py +4 -7
  137. esphome/components/sprinkler/sprinkler.cpp +2 -2
  138. esphome/components/st7735/st7735.cpp +1 -1
  139. esphome/components/st7789v/st7789v.cpp +1 -1
  140. esphome/components/stepper/stepper.h +0 -1
  141. esphome/components/sun_gtil2/sun_gtil2.cpp +1 -1
  142. esphome/components/switch/binary_sensor/__init__.py +31 -0
  143. esphome/components/switch/binary_sensor/switch_binary_sensor.cpp +17 -0
  144. esphome/components/switch/binary_sensor/switch_binary_sensor.h +22 -0
  145. esphome/components/sx1509/sx1509_gpio_pin.cpp +2 -1
  146. esphome/components/sx1509/sx1509_gpio_pin.h +5 -5
  147. esphome/components/uart/uart.h +1 -1
  148. esphome/components/udp/udp_component.cpp +32 -16
  149. esphome/components/ufire_ec/sensor.py +4 -4
  150. esphome/components/uln2003/uln2003.cpp +4 -1
  151. esphome/components/waveshare_epaper/display.py +8 -0
  152. esphome/components/waveshare_epaper/waveshare_epaper.cpp +191 -0
  153. esphome/components/waveshare_epaper/waveshare_epaper.h +56 -0
  154. esphome/components/wiegand/__init__.py +3 -4
  155. esphome/components/wifi/__init__.py +42 -0
  156. esphome/components/wifi/wifi_component.cpp +2 -2
  157. esphome/components/wifi/wifi_component.h +82 -1
  158. esphome/components/wifi/wifi_component_esp32_arduino.cpp +1 -1
  159. esphome/components/wifi/wifi_component_esp8266.cpp +1 -1
  160. esphome/components/wifi/wifi_component_esp_idf.cpp +1 -1
  161. esphome/components/wifi/wifi_component_libretiny.cpp +1 -1
  162. esphome/components/wifi/wifi_component_pico_w.cpp +1 -1
  163. esphome/components/wireguard/wireguard.cpp +2 -2
  164. esphome/components/xiaomi_ble/xiaomi_ble.cpp +1 -1
  165. esphome/config_validation.py +15 -11
  166. esphome/const.py +7 -1
  167. esphome/core/component.cpp +1 -1
  168. esphome/core/config.py +1 -2
  169. esphome/core/defines.h +3 -1
  170. esphome/core/helpers.cpp +6 -1
  171. esphome/core/helpers.h +2 -1
  172. esphome/core/optional.h +2 -2
  173. {esphome-2024.11.3.dist-info → esphome-2024.12.0b1.dist-info}/METADATA +3 -3
  174. {esphome-2024.11.3.dist-info → esphome-2024.12.0b1.dist-info}/RECORD +178 -149
  175. {esphome-2024.11.3.dist-info → esphome-2024.12.0b1.dist-info}/LICENSE +0 -0
  176. {esphome-2024.11.3.dist-info → esphome-2024.12.0b1.dist-info}/WHEEL +0 -0
  177. {esphome-2024.11.3.dist-info → esphome-2024.12.0b1.dist-info}/entry_points.txt +0 -0
  178. {esphome-2024.11.3.dist-info → esphome-2024.12.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,9 @@
1
+ #include "reset_radar_button.h"
2
+
3
+ namespace esphome {
4
+ namespace seeed_mr60fda2 {
5
+
6
+ void ResetRadarButton::press_action() { this->parent_->factory_reset(); }
7
+
8
+ } // namespace seeed_mr60fda2
9
+ } // 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
@@ -0,0 +1,368 @@
1
+ #include "seeed_mr60fda2.h"
2
+ #include "esphome/core/log.h"
3
+
4
+ #include <cinttypes>
5
+ #include <utility>
6
+
7
+ namespace esphome {
8
+ namespace seeed_mr60fda2 {
9
+
10
+ static const char *const TAG = "seeed_mr60fda2";
11
+
12
+ // Prints the component's configuration data. dump_config() prints all of the component's configuration
13
+ // items in an easy-to-read format, including the configuration key-value pairs.
14
+ void MR60FDA2Component::dump_config() {
15
+ ESP_LOGCONFIG(TAG, "MR60FDA2:");
16
+ #ifdef USE_BINARY_SENSOR
17
+ LOG_BINARY_SENSOR(" ", "People Exist Binary Sensor", this->people_exist_binary_sensor_);
18
+ LOG_BINARY_SENSOR(" ", "Is Fall Binary Sensor", this->fall_detected_binary_sensor_);
19
+ #endif
20
+ #ifdef USE_BUTTON
21
+ LOG_BUTTON(" ", "Get Radar Parameters Button", this->get_radar_parameters_button_);
22
+ LOG_BUTTON(" ", "Reset Radar Button", this->factory_reset_button_);
23
+ #endif
24
+ #ifdef USE_SELECT
25
+ LOG_SELECT(" ", "Install Height Select", this->install_height_select_);
26
+ LOG_SELECT(" ", "Height Threshold Select", this->height_threshold_select_);
27
+ LOG_SELECT(" ", "Sensitivity Select", this->sensitivity_select_);
28
+ #endif
29
+ }
30
+
31
+ // Initialisation functions
32
+ void MR60FDA2Component::setup() {
33
+ ESP_LOGCONFIG(TAG, "Setting up MR60FDA2...");
34
+ this->check_uart_settings(115200);
35
+
36
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
37
+ this->current_frame_id_ = 0;
38
+ this->current_frame_len_ = 0;
39
+ this->current_data_frame_len_ = 0;
40
+ this->current_frame_type_ = 0;
41
+ this->get_radar_parameters();
42
+
43
+ memset(this->current_frame_buf_, 0, FRAME_BUF_MAX_SIZE);
44
+ memset(this->current_data_buf_, 0, DATA_BUF_MAX_SIZE);
45
+
46
+ ESP_LOGCONFIG(TAG, "Set up MR60FDA2 complete");
47
+ }
48
+
49
+ // main loop
50
+ void MR60FDA2Component::loop() {
51
+ uint8_t byte;
52
+
53
+ // Is there data on the serial port
54
+ while (this->available()) {
55
+ this->read_byte(&byte);
56
+ this->split_frame_(byte); // split data frame
57
+ }
58
+ }
59
+
60
+ /**
61
+ * @brief Calculate the checksum for a byte array.
62
+ *
63
+ * This function calculates the checksum for the provided byte array using an
64
+ * XOR-based checksum algorithm.
65
+ *
66
+ * @param data The byte array to calculate the checksum for.
67
+ * @param len The length of the byte array.
68
+ * @return The calculated checksum.
69
+ */
70
+ static uint8_t calculate_checksum(const uint8_t *data, size_t len) {
71
+ uint8_t checksum = 0;
72
+ for (size_t i = 0; i < len; i++) {
73
+ checksum ^= data[i];
74
+ }
75
+ checksum = ~checksum;
76
+ return checksum;
77
+ }
78
+
79
+ /**
80
+ * @brief Validate the checksum of a byte array.
81
+ *
82
+ * This function validates the checksum of the provided byte array by comparing
83
+ * it to the expected checksum.
84
+ *
85
+ * @param data The byte array to validate.
86
+ * @param len The length of the byte array.
87
+ * @param expected_checksum The expected checksum.
88
+ * @return True if the checksum is valid, false otherwise.
89
+ */
90
+ static bool validate_checksum(const uint8_t *data, size_t len, uint8_t expected_checksum) {
91
+ return calculate_checksum(data, len) == expected_checksum;
92
+ }
93
+
94
+ static uint8_t find_nearest_index(float value, const float *arr, int size) {
95
+ int nearest_index = 0;
96
+ float min_diff = std::abs(value - arr[0]);
97
+ for (int i = 1; i < size; ++i) {
98
+ float diff = std::abs(value - arr[i]);
99
+ if (diff < min_diff) {
100
+ min_diff = diff;
101
+ nearest_index = i;
102
+ }
103
+ }
104
+ return nearest_index;
105
+ }
106
+
107
+ /**
108
+ * @brief Convert a float value to a byte array.
109
+ *
110
+ * This function converts a float value to a byte array.
111
+ *
112
+ * @param value The float value to convert.
113
+ * @param bytes The byte array to store the converted value.
114
+ */
115
+ static void float_to_bytes(float value, unsigned char *bytes) {
116
+ union {
117
+ float float_value;
118
+ unsigned char byte_array[4];
119
+ } u;
120
+
121
+ u.float_value = value;
122
+ memcpy(bytes, u.byte_array, 4);
123
+ }
124
+
125
+ /**
126
+ * @brief Convert a 32-bit unsigned integer to a byte array.
127
+ *
128
+ * This function converts a 32-bit unsigned integer to a byte array.
129
+ *
130
+ * @param value The 32-bit unsigned integer to convert.
131
+ * @param bytes The byte array to store the converted value.
132
+ */
133
+ static void int_to_bytes(uint32_t value, unsigned char *bytes) {
134
+ bytes[0] = value & 0xFF;
135
+ bytes[1] = (value >> 8) & 0xFF;
136
+ bytes[2] = (value >> 16) & 0xFF;
137
+ bytes[3] = (value >> 24) & 0xFF;
138
+ }
139
+
140
+ void MR60FDA2Component::split_frame_(uint8_t buffer) {
141
+ switch (this->current_frame_locate_) {
142
+ case LOCATE_FRAME_HEADER: // starting buffer
143
+ if (buffer == FRAME_HEADER_BUFFER) {
144
+ this->current_frame_len_ = 1;
145
+ this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
146
+ this->current_frame_locate_++;
147
+ }
148
+ break;
149
+ case LOCATE_ID_FRAME1:
150
+ this->current_frame_id_ = buffer << 8;
151
+ this->current_frame_len_++;
152
+ this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
153
+ this->current_frame_locate_++;
154
+ break;
155
+ case LOCATE_ID_FRAME2:
156
+ this->current_frame_id_ += buffer;
157
+ this->current_frame_len_++;
158
+ this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
159
+ this->current_frame_locate_++;
160
+ break;
161
+ case LOCATE_LENGTH_FRAME_H:
162
+ this->current_data_frame_len_ = buffer << 8;
163
+ if (this->current_data_frame_len_ == 0x00) {
164
+ this->current_frame_len_++;
165
+ this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
166
+ this->current_frame_locate_++;
167
+ } else {
168
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
169
+ }
170
+ break;
171
+ case LOCATE_LENGTH_FRAME_L:
172
+ this->current_data_frame_len_ += buffer;
173
+ if (this->current_data_frame_len_ > DATA_BUF_MAX_SIZE) {
174
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
175
+ } else {
176
+ this->current_frame_len_++;
177
+ this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
178
+ this->current_frame_locate_++;
179
+ }
180
+ break;
181
+ case LOCATE_TYPE_FRAME1:
182
+ this->current_frame_type_ = buffer << 8;
183
+ this->current_frame_len_++;
184
+ this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
185
+ this->current_frame_locate_++;
186
+ break;
187
+ case LOCATE_TYPE_FRAME2:
188
+ this->current_frame_type_ += buffer;
189
+ if ((this->current_frame_type_ == IS_FALL_TYPE_BUFFER) ||
190
+ (this->current_frame_type_ == PEOPLE_EXIST_TYPE_BUFFER) ||
191
+ (this->current_frame_type_ == RESULT_INSTALL_HEIGHT) || (this->current_frame_type_ == RESULT_PARAMETERS) ||
192
+ (this->current_frame_type_ == RESULT_HEIGHT_THRESHOLD) || (this->current_frame_type_ == RESULT_SENSITIVITY)) {
193
+ this->current_frame_len_++;
194
+ this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
195
+ this->current_frame_locate_++;
196
+ } else {
197
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
198
+ }
199
+ break;
200
+ case LOCATE_HEAD_CKSUM_FRAME:
201
+ if (validate_checksum(this->current_frame_buf_, this->current_frame_len_, buffer)) {
202
+ this->current_frame_len_++;
203
+ this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
204
+ this->current_frame_locate_++;
205
+ } else {
206
+ ESP_LOGD(TAG, "HEAD_CKSUM_FRAME ERROR: 0x%02x", buffer);
207
+ ESP_LOGV(TAG, "CURRENT_FRAME: %s %s",
208
+ format_hex_pretty(this->current_frame_buf_, this->current_frame_len_).c_str(),
209
+ format_hex_pretty(&buffer, 1).c_str());
210
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
211
+ }
212
+ break;
213
+ case LOCATE_DATA_FRAME:
214
+ this->current_frame_len_++;
215
+ this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
216
+ this->current_data_buf_[this->current_frame_len_ - LEN_TO_DATA_FRAME] = buffer;
217
+ if (this->current_frame_len_ - LEN_TO_HEAD_CKSUM == this->current_data_frame_len_) {
218
+ this->current_frame_locate_++;
219
+ }
220
+ if (this->current_frame_len_ > FRAME_BUF_MAX_SIZE) {
221
+ ESP_LOGD(TAG, "PRACTICE_DATA_FRAME_LEN ERROR: %d", this->current_frame_len_ - LEN_TO_HEAD_CKSUM);
222
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
223
+ }
224
+ break;
225
+ case LOCATE_DATA_CKSUM_FRAME:
226
+ if (validate_checksum(this->current_data_buf_, this->current_data_frame_len_, buffer)) {
227
+ this->current_frame_len_++;
228
+ this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
229
+ this->current_frame_locate_++;
230
+ this->process_frame_();
231
+ } else {
232
+ ESP_LOGD(TAG, "DATA_CKSUM_FRAME ERROR: 0x%02x", buffer);
233
+ ESP_LOGV(TAG, "GET CURRENT_FRAME: %s %s",
234
+ format_hex_pretty(this->current_frame_buf_, this->current_frame_len_).c_str(),
235
+ format_hex_pretty(&buffer, 1).c_str());
236
+
237
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
238
+ }
239
+ break;
240
+ default:
241
+ break;
242
+ }
243
+ }
244
+
245
+ void MR60FDA2Component::process_frame_() {
246
+ switch (this->current_frame_type_) {
247
+ case IS_FALL_TYPE_BUFFER:
248
+ if (this->fall_detected_binary_sensor_ != nullptr) {
249
+ this->fall_detected_binary_sensor_->publish_state(this->current_frame_buf_[LEN_TO_HEAD_CKSUM]);
250
+ }
251
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
252
+ break;
253
+
254
+ case PEOPLE_EXIST_TYPE_BUFFER:
255
+ if (this->people_exist_binary_sensor_ != nullptr)
256
+ this->people_exist_binary_sensor_->publish_state(this->current_frame_buf_[LEN_TO_HEAD_CKSUM]);
257
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
258
+ break;
259
+
260
+ case RESULT_INSTALL_HEIGHT:
261
+ if (this->current_data_buf_[0]) {
262
+ ESP_LOGD(TAG, "Successfully set the mounting height");
263
+ } else {
264
+ ESP_LOGD(TAG, "Failed to set the mounting height");
265
+ }
266
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
267
+ break;
268
+
269
+ case RESULT_HEIGHT_THRESHOLD:
270
+ if (this->current_data_buf_[0]) {
271
+ ESP_LOGD(TAG, "Successfully set the height threshold");
272
+ } else {
273
+ ESP_LOGD(TAG, "Failed to set the height threshold");
274
+ }
275
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
276
+ break;
277
+
278
+ case RESULT_SENSITIVITY:
279
+ if (this->current_data_buf_[0]) {
280
+ ESP_LOGD(TAG, "Successfully set the sensitivity");
281
+ } else {
282
+ ESP_LOGD(TAG, "Failed to set the sensitivity");
283
+ }
284
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
285
+ break;
286
+
287
+ case RESULT_PARAMETERS: {
288
+ float install_height_float = 0;
289
+ float height_threshold_float = 0;
290
+ uint32_t current_sensitivity = 0;
291
+ if (this->install_height_select_ != nullptr) {
292
+ uint32_t current_install_height_int =
293
+ encode_uint32(current_data_buf_[3], current_data_buf_[2], current_data_buf_[1], current_data_buf_[0]);
294
+
295
+ install_height_float = bit_cast<float>(current_install_height_int);
296
+ uint32_t select_index = find_nearest_index(install_height_float, INSTALL_HEIGHT, 7);
297
+ this->install_height_select_->publish_state(this->install_height_select_->at(select_index).value());
298
+ }
299
+
300
+ if (this->height_threshold_select_ != nullptr) {
301
+ uint32_t current_height_threshold_int =
302
+ encode_uint32(current_data_buf_[7], current_data_buf_[6], current_data_buf_[5], current_data_buf_[4]);
303
+
304
+ height_threshold_float = bit_cast<float>(current_height_threshold_int);
305
+ size_t select_index = find_nearest_index(height_threshold_float, HEIGHT_THRESHOLD, 7);
306
+ this->height_threshold_select_->publish_state(this->height_threshold_select_->at(select_index).value());
307
+ }
308
+
309
+ if (this->sensitivity_select_ != nullptr) {
310
+ current_sensitivity =
311
+ encode_uint32(current_data_buf_[11], current_data_buf_[10], current_data_buf_[9], current_data_buf_[8]);
312
+
313
+ uint32_t select_index = find_nearest_index(current_sensitivity, SENSITIVITY, 3);
314
+ this->sensitivity_select_->publish_state(this->sensitivity_select_->at(select_index).value());
315
+ }
316
+
317
+ ESP_LOGD(TAG, "Mounting height: %.2f, Height threshold: %.2f, Sensitivity: %" PRIu32, install_height_float,
318
+ height_threshold_float, current_sensitivity);
319
+ this->current_frame_locate_ = LOCATE_FRAME_HEADER;
320
+ break;
321
+ }
322
+ default:
323
+ break;
324
+ }
325
+ }
326
+
327
+ // Send Heartbeat Packet Command
328
+ void MR60FDA2Component::set_install_height(uint8_t index) {
329
+ uint8_t send_data[13] = {0x01, 0x00, 0x00, 0x00, 0x04, 0x0E, 0x04, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00};
330
+ float_to_bytes(INSTALL_HEIGHT[index], &send_data[8]);
331
+ send_data[12] = calculate_checksum(send_data + 8, 4);
332
+ this->write_array(send_data, 13);
333
+ ESP_LOGV(TAG, "SEND INSTALL HEIGHT FRAME: %s", format_hex_pretty(send_data, 13).c_str());
334
+ }
335
+
336
+ void MR60FDA2Component::set_height_threshold(uint8_t index) {
337
+ uint8_t send_data[13] = {0x01, 0x00, 0x00, 0x00, 0x04, 0x0E, 0x08, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00};
338
+ float_to_bytes(INSTALL_HEIGHT[index], &send_data[8]);
339
+ send_data[12] = calculate_checksum(send_data + 8, 4);
340
+ this->write_array(send_data, 13);
341
+ ESP_LOGV(TAG, "SEND HEIGHT THRESHOLD: %s", format_hex_pretty(send_data, 13).c_str());
342
+ }
343
+
344
+ void MR60FDA2Component::set_sensitivity(uint8_t index) {
345
+ uint8_t send_data[13] = {0x01, 0x00, 0x00, 0x00, 0x04, 0x0E, 0x0A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00};
346
+
347
+ int_to_bytes(SENSITIVITY[index], &send_data[8]);
348
+
349
+ send_data[12] = calculate_checksum(send_data + 8, 4);
350
+ this->write_array(send_data, 13);
351
+ ESP_LOGV(TAG, "SEND SET SENSITIVITY: %s", format_hex_pretty(send_data, 13).c_str());
352
+ }
353
+
354
+ void MR60FDA2Component::get_radar_parameters() {
355
+ uint8_t send_data[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x06, 0xF6};
356
+ this->write_array(send_data, 8);
357
+ ESP_LOGV(TAG, "SEND GET PARAMETERS: %s", format_hex_pretty(send_data, 8).c_str());
358
+ }
359
+
360
+ void MR60FDA2Component::factory_reset() {
361
+ uint8_t send_data[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0xCF};
362
+ this->write_array(send_data, 8);
363
+ ESP_LOGV(TAG, "SEND RESET: %s", format_hex_pretty(send_data, 8).c_str());
364
+ this->get_radar_parameters();
365
+ }
366
+
367
+ } // namespace seeed_mr60fda2
368
+ } // namespace esphome
@@ -0,0 +1,101 @@
1
+ #pragma once
2
+ #include "esphome/core/component.h"
3
+ #include "esphome/core/defines.h"
4
+ #ifdef USE_BINARY_SENSOR
5
+ #include "esphome/components/binary_sensor/binary_sensor.h"
6
+ #endif
7
+ #ifdef USE_BUTTON
8
+ #include "esphome/components/button/button.h"
9
+ #endif
10
+ #ifdef USE_SELECT
11
+ #include "esphome/components/select/select.h"
12
+ #endif
13
+ #ifdef USE_TEXT_SENSOR
14
+ #include "esphome/components/text_sensor/text_sensor.h"
15
+ #endif
16
+ #include "esphome/components/uart/uart.h"
17
+ #include "esphome/core/automation.h"
18
+ #include "esphome/core/helpers.h"
19
+
20
+ #include <map>
21
+
22
+ namespace esphome {
23
+ namespace seeed_mr60fda2 {
24
+
25
+ static const uint8_t DATA_BUF_MAX_SIZE = 28;
26
+ static const uint8_t FRAME_BUF_MAX_SIZE = 37;
27
+ static const uint8_t LEN_TO_HEAD_CKSUM = 8;
28
+ static const uint8_t LEN_TO_DATA_FRAME = 9;
29
+
30
+ static const uint8_t FRAME_HEADER_BUFFER = 0x01;
31
+ static const uint16_t IS_FALL_TYPE_BUFFER = 0x0E02;
32
+ static const uint16_t PEOPLE_EXIST_TYPE_BUFFER = 0x0F09;
33
+ static const uint16_t RESULT_INSTALL_HEIGHT = 0x0E04;
34
+ static const uint16_t RESULT_PARAMETERS = 0x0E06;
35
+ static const uint16_t RESULT_HEIGHT_THRESHOLD = 0x0E08;
36
+ static const uint16_t RESULT_SENSITIVITY = 0x0E0A;
37
+
38
+ enum FrameLocation {
39
+ LOCATE_FRAME_HEADER,
40
+ LOCATE_ID_FRAME1,
41
+ LOCATE_ID_FRAME2,
42
+ LOCATE_LENGTH_FRAME_H,
43
+ LOCATE_LENGTH_FRAME_L,
44
+ LOCATE_TYPE_FRAME1,
45
+ LOCATE_TYPE_FRAME2,
46
+ LOCATE_HEAD_CKSUM_FRAME, // Header checksum: [from the first byte to the previous byte of the HEAD_CKSUM bit]
47
+ LOCATE_DATA_FRAME,
48
+ LOCATE_DATA_CKSUM_FRAME, // Data checksum: [from the first to the previous byte of the DATA_CKSUM bit]
49
+ LOCATE_PROCESS_FRAME,
50
+ };
51
+
52
+ static const float INSTALL_HEIGHT[7] = {2.4f, 2.5f, 2.6f, 2.7f, 2.8f, 2.9f, 3.0f};
53
+ static const float HEIGHT_THRESHOLD[7] = {0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f};
54
+ static const float SENSITIVITY[3] = {3, 15, 30};
55
+
56
+ static const char *const INSTALL_HEIGHT_STR[7] = {"2.4m", "2.5m", "2.6", "2.7m", "2.8", "2.9m", "3.0m"};
57
+ static const char *const HEIGHT_THRESHOLD_STR[7] = {"0.0m", "0.1m", "0.2m", "0.3m", "0.4m", "0.5m", "0.6m"};
58
+ static const char *const SENSITIVITY_STR[3] = {"1", "2", "3"};
59
+
60
+ class MR60FDA2Component : public Component,
61
+ public uart::UARTDevice { // The class name must be the name defined by text_sensor.py
62
+ #ifdef USE_BINARY_SENSOR
63
+ SUB_BINARY_SENSOR(people_exist)
64
+ SUB_BINARY_SENSOR(fall_detected)
65
+ #endif
66
+ #ifdef USE_BUTTON
67
+ SUB_BUTTON(get_radar_parameters)
68
+ SUB_BUTTON(factory_reset)
69
+ #endif
70
+ #ifdef USE_SELECT
71
+ SUB_SELECT(install_height)
72
+ SUB_SELECT(height_threshold)
73
+ SUB_SELECT(sensitivity)
74
+ #endif
75
+
76
+ protected:
77
+ uint8_t current_frame_locate_;
78
+ uint8_t current_frame_buf_[FRAME_BUF_MAX_SIZE];
79
+ uint8_t current_data_buf_[DATA_BUF_MAX_SIZE];
80
+ uint16_t current_frame_id_;
81
+ size_t current_frame_len_;
82
+ size_t current_data_frame_len_;
83
+ uint16_t current_frame_type_;
84
+
85
+ void split_frame_(uint8_t buffer);
86
+ void process_frame_();
87
+
88
+ public:
89
+ float get_setup_priority() const override { return esphome::setup_priority::LATE; }
90
+ void setup() override;
91
+ void dump_config() override;
92
+ void loop() override;
93
+ void set_install_height(uint8_t index);
94
+ void set_height_threshold(uint8_t index);
95
+ void set_sensitivity(uint8_t index);
96
+ void get_radar_parameters();
97
+ void factory_reset();
98
+ };
99
+
100
+ } // namespace seeed_mr60fda2
101
+ } // namespace esphome
@@ -0,0 +1,59 @@
1
+ import esphome.codegen as cg
2
+ from esphome.components import select
3
+ import esphome.config_validation as cv
4
+ from esphome.const import CONF_SENSITIVITY, ENTITY_CATEGORY_CONFIG, ICON_ACCELERATION_Z
5
+
6
+ from .. import CONF_MR60FDA2_ID, MR60FDA2Component, mr60fda2_ns
7
+
8
+
9
+ DEPENDENCIES = ["seeed_mr60fda2"]
10
+
11
+ InstallHeightSelect = mr60fda2_ns.class_("InstallHeightSelect", select.Select)
12
+ HeightThresholdSelect = mr60fda2_ns.class_("HeightThresholdSelect", select.Select)
13
+ SensitivitySelect = mr60fda2_ns.class_("SensitivitySelect", select.Select)
14
+
15
+ CONF_INSTALL_HEIGHT = "install_height"
16
+ CONF_HEIGHT_THRESHOLD = "height_threshold"
17
+
18
+ CONFIG_SCHEMA = {
19
+ cv.GenerateID(CONF_MR60FDA2_ID): cv.use_id(MR60FDA2Component),
20
+ cv.Optional(CONF_INSTALL_HEIGHT): select.select_schema(
21
+ InstallHeightSelect,
22
+ entity_category=ENTITY_CATEGORY_CONFIG,
23
+ icon=ICON_ACCELERATION_Z,
24
+ ),
25
+ cv.Optional(CONF_HEIGHT_THRESHOLD): select.select_schema(
26
+ HeightThresholdSelect,
27
+ entity_category=ENTITY_CATEGORY_CONFIG,
28
+ icon=ICON_ACCELERATION_Z,
29
+ ),
30
+ cv.Optional(CONF_SENSITIVITY): select.select_schema(
31
+ SensitivitySelect,
32
+ entity_category=ENTITY_CATEGORY_CONFIG,
33
+ ),
34
+ }
35
+
36
+
37
+ async def to_code(config):
38
+ mr60fda2_component = await cg.get_variable(config[CONF_MR60FDA2_ID])
39
+ if install_height_config := config.get(CONF_INSTALL_HEIGHT):
40
+ s = await select.new_select(
41
+ install_height_config,
42
+ options=["2.4m", "2.5m", "2.6m", "2.7m", "2.8m", "2.9m", "3.0m"],
43
+ )
44
+ await cg.register_parented(s, config[CONF_MR60FDA2_ID])
45
+ cg.add(mr60fda2_component.set_install_height_select(s))
46
+ if height_threshold_config := config.get(CONF_HEIGHT_THRESHOLD):
47
+ s = await select.new_select(
48
+ height_threshold_config,
49
+ options=["0.0m", "0.1m", "0.2m", "0.3m", "0.4m", "0.5m", "0.6m"],
50
+ )
51
+ await cg.register_parented(s, config[CONF_MR60FDA2_ID])
52
+ cg.add(mr60fda2_component.set_height_threshold_select(s))
53
+ if sensitivity_config := config.get(CONF_SENSITIVITY):
54
+ s = await select.new_select(
55
+ sensitivity_config,
56
+ options=["1", "2", "3"],
57
+ )
58
+ await cg.register_parented(s, config[CONF_MR60FDA2_ID])
59
+ cg.add(mr60fda2_component.set_sensitivity_select(s))
@@ -0,0 +1,15 @@
1
+ #include "height_threshold_select.h"
2
+
3
+ namespace esphome {
4
+ namespace seeed_mr60fda2 {
5
+
6
+ void HeightThresholdSelect::control(const std::string &value) {
7
+ this->publish_state(value);
8
+ auto index = this->index_of(value);
9
+ if (index.has_value()) {
10
+ this->parent_->set_height_threshold(index.value());
11
+ }
12
+ }
13
+
14
+ } // namespace seeed_mr60fda2
15
+ } // namespace esphome
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/select/select.h"
4
+ #include "../seeed_mr60fda2.h"
5
+
6
+ namespace esphome {
7
+ namespace seeed_mr60fda2 {
8
+
9
+ class HeightThresholdSelect : public select::Select, public Parented<MR60FDA2Component> {
10
+ public:
11
+ HeightThresholdSelect() = default;
12
+
13
+ protected:
14
+ void control(const std::string &value) override;
15
+ };
16
+
17
+ } // namespace seeed_mr60fda2
18
+ } // namespace esphome
@@ -0,0 +1,15 @@
1
+ #include "install_height_select.h"
2
+
3
+ namespace esphome {
4
+ namespace seeed_mr60fda2 {
5
+
6
+ void InstallHeightSelect::control(const std::string &value) {
7
+ this->publish_state(value);
8
+ auto index = this->index_of(value);
9
+ if (index.has_value()) {
10
+ this->parent_->set_install_height(index.value());
11
+ }
12
+ }
13
+
14
+ } // namespace seeed_mr60fda2
15
+ } // namespace esphome
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/select/select.h"
4
+ #include "../seeed_mr60fda2.h"
5
+
6
+ namespace esphome {
7
+ namespace seeed_mr60fda2 {
8
+
9
+ class InstallHeightSelect : public select::Select, public Parented<MR60FDA2Component> {
10
+ public:
11
+ InstallHeightSelect() = default;
12
+
13
+ protected:
14
+ void control(const std::string &value) override;
15
+ };
16
+
17
+ } // namespace seeed_mr60fda2
18
+ } // namespace esphome
@@ -0,0 +1,15 @@
1
+ #include "sensitivity_select.h"
2
+
3
+ namespace esphome {
4
+ namespace seeed_mr60fda2 {
5
+
6
+ void SensitivitySelect::control(const std::string &value) {
7
+ this->publish_state(value);
8
+ auto index = this->index_of(value);
9
+ if (index.has_value()) {
10
+ this->parent_->set_sensitivity(index.value());
11
+ }
12
+ }
13
+
14
+ } // namespace seeed_mr60fda2
15
+ } // namespace esphome
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include "esphome/components/select/select.h"
4
+ #include "../seeed_mr60fda2.h"
5
+
6
+ namespace esphome {
7
+ namespace seeed_mr60fda2 {
8
+
9
+ class SensitivitySelect : public select::Select, public Parented<MR60FDA2Component> {
10
+ public:
11
+ SensitivitySelect() = default;
12
+
13
+ protected:
14
+ void control(const std::string &value) override;
15
+ };
16
+
17
+ } // namespace seeed_mr60fda2
18
+ } // namespace esphome