mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Add Seeed Studio mmWave Kit MR24HPC1 (#5761)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Peter Pan <twinkle-pirate@hotmail.com>
This commit is contained in:
		| @@ -290,6 +290,7 @@ esphome/components/scd4x/* @martgras @sjtrny | |||||||
| esphome/components/script/* @esphome/core | esphome/components/script/* @esphome/core | ||||||
| esphome/components/sdm_meter/* @jesserockz @polyfaces | esphome/components/sdm_meter/* @jesserockz @polyfaces | ||||||
| esphome/components/sdp3x/* @Azimath | esphome/components/sdp3x/* @Azimath | ||||||
|  | esphome/components/seeed_mr24hpc1/* @limengdu | ||||||
| esphome/components/selec_meter/* @sourabhjaiswal | esphome/components/selec_meter/* @sourabhjaiswal | ||||||
| esphome/components/select/* @esphome/core | esphome/components/select/* @esphome/core | ||||||
| esphome/components/sen0321/* @notjj | esphome/components/sen0321/* @notjj | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								esphome/components/seeed_mr24hpc1/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								esphome/components/seeed_mr24hpc1/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.components import uart | ||||||
|  | from esphome.const import CONF_ID | ||||||
|  |  | ||||||
|  | DEPENDENCIES = ["uart"] | ||||||
|  | # is the code owner of the relevant code base | ||||||
|  | CODEOWNERS = ["@limengdu"] | ||||||
|  | # The current component or platform can be configured or defined multiple times in the same configuration file. | ||||||
|  | MULTI_CONF = True | ||||||
|  |  | ||||||
|  | # This line of code creates a new namespace called mr24hpc1_ns. | ||||||
|  | # This namespace will be used as a prefix for all classes, functions and variables associated with the mr24hpc1_ns component, ensuring that they do not conflict with the names of other components. | ||||||
|  | mr24hpc1_ns = cg.esphome_ns.namespace("seeed_mr24hpc1") | ||||||
|  | # This MR24HPC1Component class will be a periodically polled UART device | ||||||
|  | MR24HPC1Component = mr24hpc1_ns.class_( | ||||||
|  |     "MR24HPC1Component", cg.Component, uart.UARTDevice | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | CONF_MR24HPC1_ID = "mr24hpc1_id" | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = ( | ||||||
|  |     cv.Schema( | ||||||
|  |         { | ||||||
|  |             cv.GenerateID(): cv.declare_id(MR24HPC1Component), | ||||||
|  |         } | ||||||
|  |     ) | ||||||
|  |     .extend(uart.UART_DEVICE_SCHEMA) | ||||||
|  |     .extend(cv.COMPONENT_SCHEMA) | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | # A verification mode was created to verify the configuration parameters of a UART device named "seeed_mr24hpc1". | ||||||
|  | # This authentication mode requires that the device must have transmit and receive functionality, a parity mode of "NONE", and a stop bit of one. | ||||||
|  | FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( | ||||||
|  |     "seeed_mr24hpc1", | ||||||
|  |     require_tx=True, | ||||||
|  |     require_rx=True, | ||||||
|  |     parity="NONE", | ||||||
|  |     stop_bits=1, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # The async def keyword is used to define a concurrent function. | ||||||
|  | # Concurrent functions are special functions designed to work with Python's asyncio library to support asynchronous I/O operations. | ||||||
|  | async def to_code(config): | ||||||
|  |     # This line of code creates a new Pvariable (a Python object representing a C++ variable) with the variable's ID taken from the configuration. | ||||||
|  |     var = cg.new_Pvariable(config[CONF_ID]) | ||||||
|  |     # This line of code registers the newly created Pvariable as a component so that ESPHome can manage it at runtime. | ||||||
|  |     await cg.register_component(var, config) | ||||||
|  |     # This line of code registers the newly created Pvariable as a device. | ||||||
|  |     await uart.register_uart_device(var, config) | ||||||
							
								
								
									
										23
									
								
								esphome/components/seeed_mr24hpc1/binary_sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								esphome/components/seeed_mr24hpc1/binary_sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components import binary_sensor | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import ( | ||||||
|  |     DEVICE_CLASS_OCCUPANCY, | ||||||
|  | ) | ||||||
|  | from . import CONF_MR24HPC1_ID, MR24HPC1Component | ||||||
|  |  | ||||||
|  | CONF_HAS_TARGET = "has_target" | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = { | ||||||
|  |     cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), | ||||||
|  |     cv.Optional(CONF_HAS_TARGET): binary_sensor.binary_sensor_schema( | ||||||
|  |         device_class=DEVICE_CLASS_OCCUPANCY, icon="mdi:motion-sensor" | ||||||
|  |     ), | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) | ||||||
|  |     if has_target_config := config.get(CONF_HAS_TARGET): | ||||||
|  |         sens = await binary_sensor.new_binary_sensor(has_target_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_has_target_binary_sensor(sens)) | ||||||
							
								
								
									
										42
									
								
								esphome/components/seeed_mr24hpc1/button/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								esphome/components/seeed_mr24hpc1/button/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components import button | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import ( | ||||||
|  |     DEVICE_CLASS_RESTART, | ||||||
|  |     ENTITY_CATEGORY_CONFIG, | ||||||
|  |     ICON_RESTART_ALERT, | ||||||
|  | ) | ||||||
|  | from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns | ||||||
|  |  | ||||||
|  | RestartButton = mr24hpc1_ns.class_("RestartButton", button.Button) | ||||||
|  | CustomSetEndButton = mr24hpc1_ns.class_("CustomSetEndButton", button.Button) | ||||||
|  |  | ||||||
|  | CONF_RESTART = "restart" | ||||||
|  | CONF_CUSTOM_SET_END = "custom_set_end" | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = { | ||||||
|  |     cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), | ||||||
|  |     cv.Optional(CONF_RESTART): button.button_schema( | ||||||
|  |         RestartButton, | ||||||
|  |         device_class=DEVICE_CLASS_RESTART, | ||||||
|  |         entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |         icon=ICON_RESTART_ALERT, | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_CUSTOM_SET_END): button.button_schema( | ||||||
|  |         CustomSetEndButton, | ||||||
|  |         entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |         icon="mdi:cog", | ||||||
|  |     ), | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) | ||||||
|  |     if restart_config := config.get(CONF_RESTART): | ||||||
|  |         b = await button.new_button(restart_config) | ||||||
|  |         await cg.register_parented(b, config[CONF_MR24HPC1_ID]) | ||||||
|  |         cg.add(mr24hpc1_component.set_restart_button(b)) | ||||||
|  |     if custom_set_end_config := config.get(CONF_CUSTOM_SET_END): | ||||||
|  |         b = await button.new_button(custom_set_end_config) | ||||||
|  |         await cg.register_parented(b, config[CONF_MR24HPC1_ID]) | ||||||
|  |         cg.add(mr24hpc1_component.set_custom_set_end_button(b)) | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | #include "custom_mode_end_button.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void CustomSetEndButton::press_action() { this->parent_->set_custom_end_mode(); } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/button/button.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class CustomSetEndButton : public button::Button, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   CustomSetEndButton() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void press_action() override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | #include "restart_button.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void RestartButton::press_action() { this->parent_->set_restart(); } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										18
									
								
								esphome/components/seeed_mr24hpc1/button/restart_button.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								esphome/components/seeed_mr24hpc1/button/restart_button.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/button/button.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class RestartButton : public button::Button, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   RestartButton() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void press_action() override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										132
									
								
								esphome/components/seeed_mr24hpc1/number/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								esphome/components/seeed_mr24hpc1/number/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components import number | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import ( | ||||||
|  |     ENTITY_CATEGORY_CONFIG, | ||||||
|  | ) | ||||||
|  | from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns | ||||||
|  |  | ||||||
|  | SensitivityNumber = mr24hpc1_ns.class_("SensitivityNumber", number.Number) | ||||||
|  | CustomModeNumber = mr24hpc1_ns.class_("CustomModeNumber", number.Number) | ||||||
|  | ExistenceThresholdNumber = mr24hpc1_ns.class_("ExistenceThresholdNumber", number.Number) | ||||||
|  | MotionThresholdNumber = mr24hpc1_ns.class_("MotionThresholdNumber", number.Number) | ||||||
|  | MotionTriggerTimeNumber = mr24hpc1_ns.class_("MotionTriggerTimeNumber", number.Number) | ||||||
|  | MotionToRestTimeNumber = mr24hpc1_ns.class_("MotionToRestTimeNumber", number.Number) | ||||||
|  | CustomUnmanTimeNumber = mr24hpc1_ns.class_("CustomUnmanTimeNumber", number.Number) | ||||||
|  |  | ||||||
|  | CONF_SENSITIVITY = "sensitivity" | ||||||
|  | CONF_CUSTOM_MODE = "custom_mode" | ||||||
|  | CONF_EXISTENCE_THRESHOLD = "existence_threshold" | ||||||
|  | CONF_MOTION_THRESHOLD = "motion_threshold" | ||||||
|  | CONF_MOTION_TRIGGER = "motion_trigger" | ||||||
|  | CONF_MOTION_TO_REST = "motion_to_rest" | ||||||
|  | CONF_CUSTOM_UNMAN_TIME = "custom_unman_time" | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = cv.Schema( | ||||||
|  |     { | ||||||
|  |         cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), | ||||||
|  |         cv.Optional(CONF_SENSITIVITY): number.number_schema( | ||||||
|  |             SensitivityNumber, | ||||||
|  |             entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |             icon="mdi:archive-check-outline", | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_CUSTOM_MODE): number.number_schema( | ||||||
|  |             CustomModeNumber, | ||||||
|  |             entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |             icon="mdi:cog", | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_EXISTENCE_THRESHOLD): number.number_schema( | ||||||
|  |             ExistenceThresholdNumber, | ||||||
|  |             entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_MOTION_THRESHOLD): number.number_schema( | ||||||
|  |             MotionThresholdNumber, | ||||||
|  |             entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_MOTION_TRIGGER): number.number_schema( | ||||||
|  |             MotionTriggerTimeNumber, | ||||||
|  |             entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |             icon="mdi:camera-timer", | ||||||
|  |             unit_of_measurement="ms", | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_MOTION_TO_REST): number.number_schema( | ||||||
|  |             MotionToRestTimeNumber, | ||||||
|  |             entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |             icon="mdi:camera-timer", | ||||||
|  |             unit_of_measurement="ms", | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_CUSTOM_UNMAN_TIME): number.number_schema( | ||||||
|  |             CustomUnmanTimeNumber, | ||||||
|  |             entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |             icon="mdi:camera-timer", | ||||||
|  |             unit_of_measurement="s", | ||||||
|  |         ), | ||||||
|  |     } | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) | ||||||
|  |     if sensitivity_config := config.get(CONF_SENSITIVITY): | ||||||
|  |         n = await number.new_number( | ||||||
|  |             sensitivity_config, | ||||||
|  |             min_value=0, | ||||||
|  |             max_value=3, | ||||||
|  |             step=1, | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(n, mr24hpc1_component) | ||||||
|  |         cg.add(mr24hpc1_component.set_sensitivity_number(n)) | ||||||
|  |     if custom_mode_config := config.get(CONF_CUSTOM_MODE): | ||||||
|  |         n = await number.new_number( | ||||||
|  |             custom_mode_config, | ||||||
|  |             min_value=0, | ||||||
|  |             max_value=4, | ||||||
|  |             step=1, | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(n, mr24hpc1_component) | ||||||
|  |         cg.add(mr24hpc1_component.set_custom_mode_number(n)) | ||||||
|  |     if existence_threshold_config := config.get(CONF_EXISTENCE_THRESHOLD): | ||||||
|  |         n = await number.new_number( | ||||||
|  |             existence_threshold_config, | ||||||
|  |             min_value=0, | ||||||
|  |             max_value=250, | ||||||
|  |             step=1, | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(n, mr24hpc1_component) | ||||||
|  |         cg.add(mr24hpc1_component.set_existence_threshold_number(n)) | ||||||
|  |     if motion_threshold_config := config.get(CONF_MOTION_THRESHOLD): | ||||||
|  |         n = await number.new_number( | ||||||
|  |             motion_threshold_config, | ||||||
|  |             min_value=0, | ||||||
|  |             max_value=250, | ||||||
|  |             step=1, | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(n, mr24hpc1_component) | ||||||
|  |         cg.add(mr24hpc1_component.set_motion_threshold_number(n)) | ||||||
|  |     if motion_trigger_config := config.get(CONF_MOTION_TRIGGER): | ||||||
|  |         n = await number.new_number( | ||||||
|  |             motion_trigger_config, | ||||||
|  |             min_value=0, | ||||||
|  |             max_value=150, | ||||||
|  |             step=1, | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(n, mr24hpc1_component) | ||||||
|  |         cg.add(mr24hpc1_component.set_motion_trigger_number(n)) | ||||||
|  |     if motion_to_rest_config := config.get(CONF_MOTION_TO_REST): | ||||||
|  |         n = await number.new_number( | ||||||
|  |             motion_to_rest_config, | ||||||
|  |             min_value=0, | ||||||
|  |             max_value=3000, | ||||||
|  |             step=1, | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(n, mr24hpc1_component) | ||||||
|  |         cg.add(mr24hpc1_component.set_motion_to_rest_number(n)) | ||||||
|  |     if custom_unman_time_config := config.get(CONF_CUSTOM_UNMAN_TIME): | ||||||
|  |         n = await number.new_number( | ||||||
|  |             custom_unman_time_config, | ||||||
|  |             min_value=0, | ||||||
|  |             max_value=3600, | ||||||
|  |             step=1, | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(n, mr24hpc1_component) | ||||||
|  |         cg.add(mr24hpc1_component.set_custom_unman_time_number(n)) | ||||||
| @@ -0,0 +1,12 @@ | |||||||
|  | #include "custom_mode_number.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void CustomModeNumber::control(float value) { | ||||||
|  |   this->publish_state(value); | ||||||
|  |   this->parent_->set_custom_mode(value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/number/number.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class CustomModeNumber : public number::Number, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   CustomModeNumber() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(float value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | #include "custom_unman_time_number.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void CustomUnmanTimeNumber::control(float value) { this->parent_->set_custom_unman_time(value); } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/number/number.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class CustomUnmanTimeNumber : public number::Number, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   CustomUnmanTimeNumber() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(float value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | #include "existence_threshold_number.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void ExistenceThresholdNumber::control(float value) { this->parent_->set_existence_threshold(value); } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/number/number.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class ExistenceThresholdNumber : public number::Number, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   ExistenceThresholdNumber() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(float value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | #include "motion_threshold_number.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void MotionThresholdNumber::control(float value) { this->parent_->set_motion_threshold(value); } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/number/number.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class MotionThresholdNumber : public number::Number, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   MotionThresholdNumber() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(float value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | #include "motion_trigger_time_number.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void MotionTriggerTimeNumber::control(float value) { this->parent_->set_motion_trigger_time(value); } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/number/number.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class MotionTriggerTimeNumber : public number::Number, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   MotionTriggerTimeNumber() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(float value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | #include "motiontorest_time_number.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void MotionToRestTimeNumber::control(float value) { this->parent_->set_motion_to_rest_time(value); } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/number/number.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class MotionToRestTimeNumber : public number::Number, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   MotionToRestTimeNumber() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(float value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | #include "sensitivity_number.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void SensitivityNumber::control(float value) { this->parent_->set_sensitivity(value); } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/number/number.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class SensitivityNumber : public number::Number, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   SensitivityNumber() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(float value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										890
									
								
								esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										890
									
								
								esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,890 @@ | |||||||
|  | #include "seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | #include <utility> | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "seeed_mr24hpc1"; | ||||||
|  |  | ||||||
|  | // Prints the component's configuration data. dump_config() prints all of the component's configuration | ||||||
|  | // items in an easy-to-read format, including the configuration key-value pairs. | ||||||
|  | void MR24HPC1Component::dump_config() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "MR24HPC1:"); | ||||||
|  | #ifdef USE_TEXT_SENSOR | ||||||
|  |   LOG_TEXT_SENSOR(" ", "Heartbeat Text Sensor", this->heartbeat_state_text_sensor_); | ||||||
|  |   LOG_TEXT_SENSOR(" ", "Product Model Text Sensor", this->product_model_text_sensor_); | ||||||
|  |   LOG_TEXT_SENSOR(" ", "Product ID Text Sensor", this->product_id_text_sensor_); | ||||||
|  |   LOG_TEXT_SENSOR(" ", "Hardware Model Text Sensor", this->hardware_model_text_sensor_); | ||||||
|  |   LOG_TEXT_SENSOR(" ", "Firware Verison Text Sensor", this->firware_version_text_sensor_); | ||||||
|  |   LOG_TEXT_SENSOR(" ", "Keep Away Text Sensor", this->keep_away_text_sensor_); | ||||||
|  |   LOG_TEXT_SENSOR(" ", "Motion Status Text Sensor", this->motion_status_text_sensor_); | ||||||
|  |   LOG_TEXT_SENSOR(" ", "Custom Mode End Text Sensor", this->custom_mode_end_text_sensor_); | ||||||
|  | #endif | ||||||
|  | #ifdef USE_BINARY_SENSOR | ||||||
|  |   LOG_BINARY_SENSOR(" ", "Has Target Binary Sensor", this->has_target_binary_sensor_); | ||||||
|  | #endif | ||||||
|  | #ifdef USE_SENSOR | ||||||
|  |   LOG_SENSOR(" ", "Custom Presence Of Detection Sensor", this->custom_presence_of_detection_sensor_); | ||||||
|  |   LOG_SENSOR(" ", "Movement Signs Sensor", this->movement_signs_sensor_); | ||||||
|  |   LOG_SENSOR(" ", "Custom Motion Distance Sensor", this->custom_motion_distance_sensor_); | ||||||
|  |   LOG_SENSOR(" ", "Custom Spatial Static Sensor", this->custom_spatial_static_value_sensor_); | ||||||
|  |   LOG_SENSOR(" ", "Custom Spatial Motion Sensor", this->custom_spatial_motion_value_sensor_); | ||||||
|  |   LOG_SENSOR(" ", "Custom Motion Speed Sensor", this->custom_motion_speed_sensor_); | ||||||
|  |   LOG_SENSOR(" ", "Custom Mode Num Sensor", this->custom_mode_num_sensor_); | ||||||
|  | #endif | ||||||
|  | #ifdef USE_SWITCH | ||||||
|  |   LOG_SWITCH(" ", "Underly Open Function Switch", this->underlying_open_function_switch_); | ||||||
|  | #endif | ||||||
|  | #ifdef USE_BUTTON | ||||||
|  |   LOG_BUTTON(" ", "Restart Button", this->restart_button_); | ||||||
|  |   LOG_BUTTON(" ", "Custom Set End Button", this->custom_set_end_button_); | ||||||
|  | #endif | ||||||
|  | #ifdef USE_SELECT | ||||||
|  |   LOG_SELECT(" ", "Scene Mode Select", this->scene_mode_select_); | ||||||
|  |   LOG_SELECT(" ", "Unman Time Select", this->unman_time_select_); | ||||||
|  |   LOG_SELECT(" ", "Existence Boundary Select", this->existence_boundary_select_); | ||||||
|  |   LOG_SELECT(" ", "Motion Boundary Select", this->motion_boundary_select_); | ||||||
|  | #endif | ||||||
|  | #ifdef USE_NUMBER | ||||||
|  |   LOG_NUMBER(" ", "Sensitivity Number", this->sensitivity_number_); | ||||||
|  |   LOG_NUMBER(" ", "Custom Mode Number", this->custom_mode_number_); | ||||||
|  |   LOG_NUMBER(" ", "Existence Threshold Number", this->existence_threshold_number_); | ||||||
|  |   LOG_NUMBER(" ", "Motion Threshold Number", this->motion_threshold_number_); | ||||||
|  |   LOG_NUMBER(" ", "Motion Trigger Time Number", this->motion_trigger_number_); | ||||||
|  |   LOG_NUMBER(" ", "Motion To Rest Time Number", this->motion_to_rest_number_); | ||||||
|  |   LOG_NUMBER(" ", "Custom Unman Time Number", this->custom_unman_time_number_); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Initialisation functions | ||||||
|  | void MR24HPC1Component::setup() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "Setting up MR24HPC1..."); | ||||||
|  |   this->check_uart_settings(115200); | ||||||
|  |  | ||||||
|  |   if (this->custom_mode_number_ != nullptr) { | ||||||
|  |     this->custom_mode_number_->publish_state(0);  // Zero out the custom mode | ||||||
|  |   } | ||||||
|  |   if (this->custom_mode_num_sensor_ != nullptr) { | ||||||
|  |     this->custom_mode_num_sensor_->publish_state(0); | ||||||
|  |   } | ||||||
|  |   if (this->custom_mode_end_text_sensor_ != nullptr) { | ||||||
|  |     this->custom_mode_end_text_sensor_->publish_state("Not in custom mode"); | ||||||
|  |   } | ||||||
|  |   this->set_custom_end_mode(); | ||||||
|  |   this->poll_time_base_func_check_ = true; | ||||||
|  |   this->check_dev_inf_sign_ = true; | ||||||
|  |   this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_PRODUCT_MODE; | ||||||
|  |   this->sg_data_len_ = 0; | ||||||
|  |   this->sg_frame_len_ = 0; | ||||||
|  |   this->sg_recv_data_state_ = FRAME_IDLE; | ||||||
|  |   this->s_output_info_switch_flag_ = OUTPUT_SWITCH_INIT; | ||||||
|  |  | ||||||
|  |   memset(this->c_product_mode_, 0, PRODUCT_BUF_MAX_SIZE); | ||||||
|  |   memset(this->c_product_id_, 0, PRODUCT_BUF_MAX_SIZE); | ||||||
|  |   memset(this->c_firmware_version_, 0, PRODUCT_BUF_MAX_SIZE); | ||||||
|  |   memset(this->c_hardware_model_, 0, PRODUCT_BUF_MAX_SIZE); | ||||||
|  |   memset(this->sg_frame_prase_buf_, 0, FRAME_BUF_MAX_SIZE); | ||||||
|  |   memset(this->sg_frame_buf_, 0, FRAME_BUF_MAX_SIZE); | ||||||
|  |  | ||||||
|  |   this->set_interval(8000, [this]() { this->update_(); }); | ||||||
|  |   ESP_LOGCONFIG(TAG, "Set up MR24HPC1 complete"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Timed polling of radar data | ||||||
|  | void MR24HPC1Component::update_() { | ||||||
|  |   this->get_radar_output_information_switch();  // Query the key status every so often | ||||||
|  |   this->poll_time_base_func_check_ = true;      // Query the base functionality information at regular intervals | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // main loop | ||||||
|  | void MR24HPC1Component::loop() { | ||||||
|  |   uint8_t byte; | ||||||
|  |  | ||||||
|  |   // Is there data on the serial port | ||||||
|  |   while (this->available()) { | ||||||
|  |     this->read_byte(&byte); | ||||||
|  |     this->r24_split_data_frame_(byte);  // split data frame | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if ((this->s_output_info_switch_flag_ == OUTPUT_SWTICH_OFF) && | ||||||
|  |       (this->sg_start_query_data_ > CUSTOM_FUNCTION_QUERY_TIME_OF_ENTER_UNMANNED) && (!this->check_dev_inf_sign_)) { | ||||||
|  |     this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_SCENE_MODE; | ||||||
|  |   } else if ((this->s_output_info_switch_flag_ == OUTPUT_SWITCH_ON) && | ||||||
|  |              (this->sg_start_query_data_ < CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY) && (!this->check_dev_inf_sign_)) { | ||||||
|  |     this->sg_start_query_data_ = CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY; | ||||||
|  |   } else if (this->check_dev_inf_sign_ && (this->sg_start_query_data_ > STANDARD_FUNCTION_QUERY_HARDWARE_MODE)) { | ||||||
|  |     // First time power up information polling | ||||||
|  |     this->sg_start_query_data_ = STANDARD_FUNCTION_QUERY_PRODUCT_MODE; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Polling Functions | ||||||
|  |   if (this->poll_time_base_func_check_) { | ||||||
|  |     switch (this->sg_start_query_data_) { | ||||||
|  |       case STANDARD_FUNCTION_QUERY_PRODUCT_MODE: | ||||||
|  |         this->get_product_mode(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_PRODUCT_ID: | ||||||
|  |         this->get_product_id(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_FIRMWARE_VERSION: | ||||||
|  |         this->get_product_mode(); | ||||||
|  |         this->get_product_id(); | ||||||
|  |         this->get_firmware_version(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_HARDWARE_MODE:  // Above is the equipment information | ||||||
|  |         this->get_product_mode(); | ||||||
|  |         this->get_product_id(); | ||||||
|  |         this->get_hardware_model(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         this->check_dev_inf_sign_ = false; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_SCENE_MODE: | ||||||
|  |         this->get_scene_mode(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_SENSITIVITY: | ||||||
|  |         this->get_sensitivity(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_UNMANNED_TIME: | ||||||
|  |         this->get_unmanned_time(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_HUMAN_STATUS: | ||||||
|  |         this->get_human_status(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_HUMAN_MOTION_INF: | ||||||
|  |         this->get_human_motion_info(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_BODY_MOVE_PARAMETER: | ||||||
|  |         this->get_body_motion_params(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_KEEPAWAY_STATUS:  // The above is the basic functional information | ||||||
|  |         this->get_keep_away(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_QUERY_CUSTOM_MODE: | ||||||
|  |         this->get_custom_mode(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case STANDARD_FUNCTION_QUERY_HEARTBEAT_STATE: | ||||||
|  |         this->get_heartbeat_packet(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY: | ||||||
|  |         this->get_existence_boundary(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case CUSTOM_FUNCTION_QUERY_MOTION_BOUNDARY: | ||||||
|  |         this->get_motion_boundary(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case CUSTOM_FUNCTION_QUERY_EXISTENCE_THRESHOLD: | ||||||
|  |         this->get_existence_threshold(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case CUSTOM_FUNCTION_QUERY_MOTION_THRESHOLD: | ||||||
|  |         this->get_motion_threshold(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case CUSTOM_FUNCTION_QUERY_MOTION_TRIGGER_TIME: | ||||||
|  |         this->get_motion_trigger_time(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case CUSTOM_FUNCTION_QUERY_MOTION_TO_REST_TIME: | ||||||
|  |         this->get_motion_to_rest_time(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case CUSTOM_FUNCTION_QUERY_TIME_OF_ENTER_UNMANNED: | ||||||
|  |         this->get_custom_unman_time(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         if (this->s_output_info_switch_flag_ == OUTPUT_SWTICH_OFF) { | ||||||
|  |           this->poll_time_base_func_check_ = false;  // Avoiding high-speed polling that can cause the device to jam | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |       case UNDERLY_FUNCTION_QUERY_HUMAN_STATUS: | ||||||
|  |         this->get_human_status(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case UNDERLY_FUNCTION_QUERY_SPATIAL_STATIC_VALUE: | ||||||
|  |         this->get_spatial_static_value(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case UNDERLY_FUNCTION_QUERY_SPATIAL_MOTION_VALUE: | ||||||
|  |         this->get_spatial_motion_value(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case UNDERLY_FUNCTION_QUERY_DISTANCE_OF_STATIC_OBJECT: | ||||||
|  |         this->get_distance_of_static_object(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case UNDERLY_FUNCTION_QUERY_DISTANCE_OF_MOVING_OBJECT: | ||||||
|  |         this->get_distance_of_moving_object(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         break; | ||||||
|  |       case UNDERLY_FUNCTION_QUERY_TARGET_MOVEMENT_SPEED: | ||||||
|  |         this->get_target_movement_speed(); | ||||||
|  |         this->sg_start_query_data_++; | ||||||
|  |         this->poll_time_base_func_check_ = false;  // Avoiding high-speed polling that can cause the device to jam | ||||||
|  |         break; | ||||||
|  |       default: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Calculate CRC check digit | ||||||
|  | static uint8_t get_frame_crc_sum(const uint8_t *data, int len) { | ||||||
|  |   unsigned int crc_sum = 0; | ||||||
|  |   for (int i = 0; i < len - 3; i++) { | ||||||
|  |     crc_sum += data[i]; | ||||||
|  |   } | ||||||
|  |   return crc_sum & 0xff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Check that the check digit is correct | ||||||
|  | static int get_frame_check_status(uint8_t *data, int len) { | ||||||
|  |   uint8_t crc_sum = get_frame_crc_sum(data, len); | ||||||
|  |   uint8_t verified = data[len - 3]; | ||||||
|  |   return (verified == crc_sum) ? 1 : 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // split data frame | ||||||
|  | void MR24HPC1Component::r24_split_data_frame_(uint8_t value) { | ||||||
|  |   switch (this->sg_recv_data_state_) { | ||||||
|  |     case FRAME_IDLE:  // starting value | ||||||
|  |       if (FRAME_HEADER1_VALUE == value) { | ||||||
|  |         this->sg_recv_data_state_ = FRAME_HEADER2; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case FRAME_HEADER2: | ||||||
|  |       if (FRAME_HEADER2_VALUE == value) { | ||||||
|  |         this->sg_frame_buf_[0] = FRAME_HEADER1_VALUE; | ||||||
|  |         this->sg_frame_buf_[1] = FRAME_HEADER2_VALUE; | ||||||
|  |         this->sg_recv_data_state_ = FRAME_CTL_WORD; | ||||||
|  |       } else { | ||||||
|  |         this->sg_recv_data_state_ = FRAME_IDLE; | ||||||
|  |         ESP_LOGD(TAG, "FRAME_IDLE ERROR value:%x", value); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case FRAME_CTL_WORD: | ||||||
|  |       this->sg_frame_buf_[2] = value; | ||||||
|  |       this->sg_recv_data_state_ = FRAME_CMD_WORD; | ||||||
|  |       break; | ||||||
|  |     case FRAME_CMD_WORD: | ||||||
|  |       this->sg_frame_buf_[3] = value; | ||||||
|  |       this->sg_recv_data_state_ = FRAME_DATA_LEN_H; | ||||||
|  |       break; | ||||||
|  |     case FRAME_DATA_LEN_H: | ||||||
|  |       if (value <= 4) { | ||||||
|  |         this->sg_data_len_ = value * 256; | ||||||
|  |         this->sg_frame_buf_[4] = value; | ||||||
|  |         this->sg_recv_data_state_ = FRAME_DATA_LEN_L; | ||||||
|  |       } else { | ||||||
|  |         this->sg_data_len_ = 0; | ||||||
|  |         this->sg_recv_data_state_ = FRAME_IDLE; | ||||||
|  |         ESP_LOGD(TAG, "FRAME_DATA_LEN_H ERROR value:%x", value); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case FRAME_DATA_LEN_L: | ||||||
|  |       this->sg_data_len_ += value; | ||||||
|  |       if (this->sg_data_len_ > 32) { | ||||||
|  |         ESP_LOGD(TAG, "len=%d, FRAME_DATA_LEN_L ERROR value:%x", this->sg_data_len_, value); | ||||||
|  |         this->sg_data_len_ = 0; | ||||||
|  |         this->sg_recv_data_state_ = FRAME_IDLE; | ||||||
|  |       } else { | ||||||
|  |         this->sg_frame_buf_[5] = value; | ||||||
|  |         this->sg_frame_len_ = 6; | ||||||
|  |         this->sg_recv_data_state_ = FRAME_DATA_BYTES; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case FRAME_DATA_BYTES: | ||||||
|  |       this->sg_data_len_ -= 1; | ||||||
|  |       this->sg_frame_buf_[this->sg_frame_len_++] = value; | ||||||
|  |       if (this->sg_data_len_ <= 0) { | ||||||
|  |         this->sg_recv_data_state_ = FRAME_DATA_CRC; | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case FRAME_DATA_CRC: | ||||||
|  |       this->sg_frame_buf_[this->sg_frame_len_++] = value; | ||||||
|  |       this->sg_recv_data_state_ = FRAME_TAIL1; | ||||||
|  |       break; | ||||||
|  |     case FRAME_TAIL1: | ||||||
|  |       if (FRAME_TAIL1_VALUE == value) { | ||||||
|  |         this->sg_recv_data_state_ = FRAME_TAIL2; | ||||||
|  |       } else { | ||||||
|  |         this->sg_recv_data_state_ = FRAME_IDLE; | ||||||
|  |         this->sg_frame_len_ = 0; | ||||||
|  |         this->sg_data_len_ = 0; | ||||||
|  |         ESP_LOGD(TAG, "FRAME_TAIL1 ERROR value:%x", value); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  |     case FRAME_TAIL2: | ||||||
|  |       if (FRAME_TAIL2_VALUE == value) { | ||||||
|  |         this->sg_frame_buf_[this->sg_frame_len_++] = FRAME_TAIL1_VALUE; | ||||||
|  |         this->sg_frame_buf_[this->sg_frame_len_++] = FRAME_TAIL2_VALUE; | ||||||
|  |         memcpy(this->sg_frame_prase_buf_, this->sg_frame_buf_, this->sg_frame_len_); | ||||||
|  |         if (get_frame_check_status(this->sg_frame_prase_buf_, this->sg_frame_len_)) { | ||||||
|  |           this->r24_parse_data_frame_(this->sg_frame_prase_buf_, this->sg_frame_len_); | ||||||
|  |         } else { | ||||||
|  |           ESP_LOGD(TAG, "frame check failer!"); | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         ESP_LOGD(TAG, "FRAME_TAIL2 ERROR value:%x", value); | ||||||
|  |       } | ||||||
|  |       memset(this->sg_frame_prase_buf_, 0, FRAME_BUF_MAX_SIZE); | ||||||
|  |       memset(this->sg_frame_buf_, 0, FRAME_BUF_MAX_SIZE); | ||||||
|  |       this->sg_frame_len_ = 0; | ||||||
|  |       this->sg_data_len_ = 0; | ||||||
|  |       this->sg_recv_data_state_ = FRAME_IDLE; | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       this->sg_recv_data_state_ = FRAME_IDLE; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Parses data frames related to product information | ||||||
|  | void MR24HPC1Component::r24_frame_parse_product_information_(uint8_t *data) { | ||||||
|  |   uint16_t product_len = encode_uint16(data[FRAME_COMMAND_WORD_INDEX + 1], data[FRAME_COMMAND_WORD_INDEX + 2]); | ||||||
|  |   if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_PRODUCT_MODE) { | ||||||
|  |     if ((this->product_model_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) { | ||||||
|  |       memset(this->c_product_mode_, 0, PRODUCT_BUF_MAX_SIZE); | ||||||
|  |       memcpy(this->c_product_mode_, &data[FRAME_DATA_INDEX], product_len); | ||||||
|  |       this->product_model_text_sensor_->publish_state(this->c_product_mode_); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGD(TAG, "Reply: get product_mode error!"); | ||||||
|  |     } | ||||||
|  |   } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_PRODUCT_ID) { | ||||||
|  |     if ((this->product_id_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) { | ||||||
|  |       memset(this->c_product_id_, 0, PRODUCT_BUF_MAX_SIZE); | ||||||
|  |       memcpy(this->c_product_id_, &data[FRAME_DATA_INDEX], product_len); | ||||||
|  |       this->product_id_text_sensor_->publish_state(this->c_product_id_); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGD(TAG, "Reply: get productId error!"); | ||||||
|  |     } | ||||||
|  |   } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_HARDWARE_MODEL) { | ||||||
|  |     if ((this->hardware_model_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) { | ||||||
|  |       memset(this->c_hardware_model_, 0, PRODUCT_BUF_MAX_SIZE); | ||||||
|  |       memcpy(this->c_hardware_model_, &data[FRAME_DATA_INDEX], product_len); | ||||||
|  |       this->hardware_model_text_sensor_->publish_state(this->c_hardware_model_); | ||||||
|  |       ESP_LOGD(TAG, "Reply: get hardware_model :%s", this->c_hardware_model_); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGD(TAG, "Reply: get hardwareModel error!"); | ||||||
|  |     } | ||||||
|  |   } else if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_FIRMWARE_VERSION) { | ||||||
|  |     if ((this->firware_version_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) { | ||||||
|  |       memset(this->c_firmware_version_, 0, PRODUCT_BUF_MAX_SIZE); | ||||||
|  |       memcpy(this->c_firmware_version_, &data[FRAME_DATA_INDEX], product_len); | ||||||
|  |       this->firware_version_text_sensor_->publish_state(this->c_firmware_version_); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGD(TAG, "Reply: get firmwareVersion error!"); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Parsing the underlying open parameters | ||||||
|  | void MR24HPC1Component::r24_frame_parse_open_underlying_information_(uint8_t *data) { | ||||||
|  |   if (data[FRAME_COMMAND_WORD_INDEX] == 0x00) { | ||||||
|  |     if (this->underlying_open_function_switch_ != nullptr) { | ||||||
|  |       this->underlying_open_function_switch_->publish_state( | ||||||
|  |           data[FRAME_DATA_INDEX]);  // Underlying Open Parameter Switch Status Updates | ||||||
|  |     } | ||||||
|  |     if (data[FRAME_DATA_INDEX]) { | ||||||
|  |       this->s_output_info_switch_flag_ = OUTPUT_SWITCH_ON; | ||||||
|  |     } else { | ||||||
|  |       this->s_output_info_switch_flag_ = OUTPUT_SWTICH_OFF; | ||||||
|  |     } | ||||||
|  |   } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x01) { | ||||||
|  |     if (this->custom_spatial_static_value_sensor_ != nullptr) { | ||||||
|  |       this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |     } | ||||||
|  |     if (this->custom_presence_of_detection_sensor_ != nullptr) { | ||||||
|  |       this->custom_presence_of_detection_sensor_->publish_state(data[FRAME_DATA_INDEX + 1] * 0.5f); | ||||||
|  |     } | ||||||
|  |     if (this->custom_spatial_motion_value_sensor_ != nullptr) { | ||||||
|  |       this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX + 2]); | ||||||
|  |     } | ||||||
|  |     if (this->custom_motion_distance_sensor_ != nullptr) { | ||||||
|  |       this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX + 3] * 0.5f); | ||||||
|  |     } | ||||||
|  |     if (this->custom_motion_speed_sensor_ != nullptr) { | ||||||
|  |       this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX + 4] - 10) * 0.5f); | ||||||
|  |     } | ||||||
|  |   } else if ((data[FRAME_COMMAND_WORD_INDEX] == 0x06) || (data[FRAME_COMMAND_WORD_INDEX] == 0x86)) { | ||||||
|  |     // none:0x00  close_to:0x01  far_away:0x02 | ||||||
|  |     if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) { | ||||||
|  |       this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]); | ||||||
|  |     } | ||||||
|  |   } else if ((this->movement_signs_sensor_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x07) || (data[FRAME_COMMAND_WORD_INDEX] == 0x87))) { | ||||||
|  |     this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |   } else if ((this->existence_threshold_number_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x08) || (data[FRAME_COMMAND_WORD_INDEX] == 0x88))) { | ||||||
|  |     this->existence_threshold_number_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |   } else if ((this->motion_threshold_number_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x09) || (data[FRAME_COMMAND_WORD_INDEX] == 0x89))) { | ||||||
|  |     this->motion_threshold_number_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |   } else if ((this->existence_boundary_select_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x0a) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8a))) { | ||||||
|  |     if (this->existence_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) { | ||||||
|  |       this->existence_boundary_select_->publish_state(S_BOUNDARY_STR[data[FRAME_DATA_INDEX] - 1]); | ||||||
|  |     } | ||||||
|  |   } else if ((this->motion_boundary_select_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x0b) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8b))) { | ||||||
|  |     if (this->motion_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) { | ||||||
|  |       this->motion_boundary_select_->publish_state(S_BOUNDARY_STR[data[FRAME_DATA_INDEX] - 1]); | ||||||
|  |     } | ||||||
|  |   } else if ((this->motion_trigger_number_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x0c) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8c))) { | ||||||
|  |     uint32_t motion_trigger_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], | ||||||
|  |                                                  data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); | ||||||
|  |     this->motion_trigger_number_->publish_state(motion_trigger_time); | ||||||
|  |   } else if ((this->motion_to_rest_number_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x0d) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8d))) { | ||||||
|  |     uint32_t move_to_rest_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], | ||||||
|  |                                                data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); | ||||||
|  |     this->motion_to_rest_number_->publish_state(move_to_rest_time); | ||||||
|  |   } else if ((this->custom_unman_time_number_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x0e) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8e))) { | ||||||
|  |     uint32_t enter_unmanned_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], | ||||||
|  |                                                  data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); | ||||||
|  |     float custom_unmanned_time = enter_unmanned_time / 1000.0; | ||||||
|  |     this->custom_unman_time_number_->publish_state(custom_unmanned_time); | ||||||
|  |   } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x80) { | ||||||
|  |     if (data[FRAME_DATA_INDEX]) { | ||||||
|  |       this->s_output_info_switch_flag_ = OUTPUT_SWITCH_ON; | ||||||
|  |     } else { | ||||||
|  |       this->s_output_info_switch_flag_ = OUTPUT_SWTICH_OFF; | ||||||
|  |     } | ||||||
|  |     if (this->underlying_open_function_switch_ != nullptr) { | ||||||
|  |       this->underlying_open_function_switch_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |     } | ||||||
|  |   } else if ((this->custom_spatial_static_value_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x81)) { | ||||||
|  |     this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |   } else if ((this->custom_spatial_motion_value_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x82)) { | ||||||
|  |     this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |   } else if ((this->custom_presence_of_detection_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x83)) { | ||||||
|  |     this->custom_presence_of_detection_sensor_->publish_state( | ||||||
|  |         S_PRESENCE_OF_DETECTION_RANGE_STR[data[FRAME_DATA_INDEX]]); | ||||||
|  |   } else if ((this->custom_motion_distance_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x84)) { | ||||||
|  |     this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX] * 0.5f); | ||||||
|  |   } else if ((this->custom_motion_speed_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x85)) { | ||||||
|  |     this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX] - 10) * 0.5f); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::r24_parse_data_frame_(uint8_t *data, uint8_t len) { | ||||||
|  |   switch (data[FRAME_CONTROL_WORD_INDEX]) { | ||||||
|  |     case 0x01: { | ||||||
|  |       if ((this->heartbeat_state_text_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x01)) { | ||||||
|  |         this->heartbeat_state_text_sensor_->publish_state("Equipment Normal"); | ||||||
|  |       } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x02) { | ||||||
|  |         ESP_LOGD(TAG, "Reply: query restart packet"); | ||||||
|  |       } else if (this->heartbeat_state_text_sensor_ != nullptr) { | ||||||
|  |         this->heartbeat_state_text_sensor_->publish_state("Equipment Abnormal"); | ||||||
|  |       } | ||||||
|  |     } break; | ||||||
|  |     case 0x02: { | ||||||
|  |       this->r24_frame_parse_product_information_(data); | ||||||
|  |     } break; | ||||||
|  |     case 0x05: { | ||||||
|  |       this->r24_frame_parse_work_status_(data); | ||||||
|  |     } break; | ||||||
|  |     case 0x08: { | ||||||
|  |       this->r24_frame_parse_open_underlying_information_(data); | ||||||
|  |     } break; | ||||||
|  |     case 0x80: { | ||||||
|  |       this->r24_frame_parse_human_information_(data); | ||||||
|  |     } break; | ||||||
|  |     default: | ||||||
|  |       ESP_LOGD(TAG, "control word:0x%02X not found", data[FRAME_CONTROL_WORD_INDEX]); | ||||||
|  |       break; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::r24_frame_parse_work_status_(uint8_t *data) { | ||||||
|  |   if (data[FRAME_COMMAND_WORD_INDEX] == 0x01) { | ||||||
|  |     ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]); | ||||||
|  |   } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x07) { | ||||||
|  |     if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) { | ||||||
|  |       this->scene_mode_select_->publish_state(S_SCENE_STR[data[FRAME_DATA_INDEX]]); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]); | ||||||
|  |     } | ||||||
|  |   } else if ((this->sensitivity_number_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x08) || (data[FRAME_COMMAND_WORD_INDEX] == 0x88))) { | ||||||
|  |     // 1-3 | ||||||
|  |     this->sensitivity_number_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |   } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x09) { | ||||||
|  |     // 1-4 | ||||||
|  |     if (this->custom_mode_num_sensor_ != nullptr) { | ||||||
|  |       this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |     } | ||||||
|  |     if (this->custom_mode_number_ != nullptr) { | ||||||
|  |       this->custom_mode_number_->publish_state(0); | ||||||
|  |     } | ||||||
|  |     if (this->custom_mode_end_text_sensor_ != nullptr) { | ||||||
|  |       this->custom_mode_end_text_sensor_->publish_state("Setup in progress..."); | ||||||
|  |     } | ||||||
|  |   } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x81) { | ||||||
|  |     ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]); | ||||||
|  |   } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x87) { | ||||||
|  |     if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) { | ||||||
|  |       this->scene_mode_select_->publish_state(S_SCENE_STR[data[FRAME_DATA_INDEX]]); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]); | ||||||
|  |     } | ||||||
|  |   } else if ((this->custom_mode_end_text_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x0A)) { | ||||||
|  |     this->custom_mode_end_text_sensor_->publish_state("Set Success!"); | ||||||
|  |   } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x89) { | ||||||
|  |     if (data[FRAME_DATA_INDEX] == 0) { | ||||||
|  |       if (this->custom_mode_end_text_sensor_ != nullptr) { | ||||||
|  |         this->custom_mode_end_text_sensor_->publish_state("Not in custom mode"); | ||||||
|  |       } | ||||||
|  |       if (this->custom_mode_number_ != nullptr) { | ||||||
|  |         this->custom_mode_number_->publish_state(0); | ||||||
|  |       } | ||||||
|  |       if (this->custom_mode_num_sensor_ != nullptr) { | ||||||
|  |         this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       if (this->custom_mode_num_sensor_ != nullptr) { | ||||||
|  |         this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } else { | ||||||
|  |     ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::r24_frame_parse_human_information_(uint8_t *data) { | ||||||
|  |   if ((this->has_target_binary_sensor_ != nullptr) && | ||||||
|  |       ((data[FRAME_COMMAND_WORD_INDEX] == 0x01) || (data[FRAME_COMMAND_WORD_INDEX] == 0x81))) { | ||||||
|  |     this->has_target_binary_sensor_->publish_state(S_SOMEONE_EXISTS_STR[data[FRAME_DATA_INDEX]]); | ||||||
|  |   } else if ((this->motion_status_text_sensor_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x02) || (data[FRAME_COMMAND_WORD_INDEX] == 0x82))) { | ||||||
|  |     if (data[FRAME_DATA_INDEX] < 3) { | ||||||
|  |       this->motion_status_text_sensor_->publish_state(S_MOTION_STATUS_STR[data[FRAME_DATA_INDEX]]); | ||||||
|  |     } | ||||||
|  |   } else if ((this->movement_signs_sensor_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x03) || (data[FRAME_COMMAND_WORD_INDEX] == 0x83))) { | ||||||
|  |     this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]); | ||||||
|  |   } else if ((this->unman_time_select_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x0A) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8A))) { | ||||||
|  |     // none:0x00  1s:0x01 30s:0x02 1min:0x03 2min:0x04 5min:0x05 10min:0x06 30min:0x07 1hour:0x08 | ||||||
|  |     if (data[FRAME_DATA_INDEX] < 9) { | ||||||
|  |       this->unman_time_select_->publish_state(S_UNMANNED_TIME_STR[data[FRAME_DATA_INDEX]]); | ||||||
|  |     } | ||||||
|  |   } else if ((this->keep_away_text_sensor_ != nullptr) && | ||||||
|  |              ((data[FRAME_COMMAND_WORD_INDEX] == 0x0B) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8B))) { | ||||||
|  |     // none:0x00  close_to:0x01  far_away:0x02 | ||||||
|  |     if (data[FRAME_DATA_INDEX] < 3) { | ||||||
|  |       this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]); | ||||||
|  |     } | ||||||
|  |   } else { | ||||||
|  |     ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Sending data frames | ||||||
|  | void MR24HPC1Component::send_query_(const uint8_t *query, size_t string_length) { | ||||||
|  |   this->write_array(query, string_length); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Send Heartbeat Packet Command | ||||||
|  | void MR24HPC1Component::get_heartbeat_packet() { this->send_query_(GET_HEARTBEAT, sizeof(GET_HEARTBEAT)); } | ||||||
|  |  | ||||||
|  | // Issuance of the underlying open parameter query command | ||||||
|  | void MR24HPC1Component::get_radar_output_information_switch() { | ||||||
|  |   this->send_query_(GET_RADAR_OUTPUT_INFORMATION_SWITCH, sizeof(GET_RADAR_OUTPUT_INFORMATION_SWITCH)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Issuance of product model orders | ||||||
|  | void MR24HPC1Component::get_product_mode() { this->send_query_(GET_PRODUCT_MODE, sizeof(GET_PRODUCT_MODE)); } | ||||||
|  |  | ||||||
|  | // Issuing the Get Product ID command | ||||||
|  | void MR24HPC1Component::get_product_id() { this->send_query_(GET_PRODUCT_ID, sizeof(GET_PRODUCT_ID)); } | ||||||
|  |  | ||||||
|  | // Issuing hardware model commands | ||||||
|  | void MR24HPC1Component::get_hardware_model() { this->send_query_(GET_HARDWARE_MODEL, sizeof(GET_HARDWARE_MODEL)); } | ||||||
|  |  | ||||||
|  | // Issuing software version commands | ||||||
|  | void MR24HPC1Component::get_firmware_version() { | ||||||
|  |   this->send_query_(GET_FIRMWARE_VERSION, sizeof(GET_FIRMWARE_VERSION)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_human_status() { this->send_query_(GET_HUMAN_STATUS, sizeof(GET_HUMAN_STATUS)); } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_human_motion_info() { | ||||||
|  |   this->send_query_(GET_HUMAN_MOTION_INFORMATION, sizeof(GET_HUMAN_MOTION_INFORMATION)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_body_motion_params() { | ||||||
|  |   this->send_query_(GET_BODY_MOTION_PARAMETERS, sizeof(GET_BODY_MOTION_PARAMETERS)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_keep_away() { this->send_query_(GET_KEEP_AWAY, sizeof(GET_KEEP_AWAY)); } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_scene_mode() { this->send_query_(GET_SCENE_MODE, sizeof(GET_SCENE_MODE)); } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_sensitivity() { this->send_query_(GET_SENSITIVITY, sizeof(GET_SENSITIVITY)); } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_unmanned_time() { this->send_query_(GET_UNMANNED_TIME, sizeof(GET_UNMANNED_TIME)); } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_custom_mode() { this->send_query_(GET_CUSTOM_MODE, sizeof(GET_CUSTOM_MODE)); } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_existence_boundary() { | ||||||
|  |   this->send_query_(GET_EXISTENCE_BOUNDARY, sizeof(GET_EXISTENCE_BOUNDARY)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_motion_boundary() { this->send_query_(GET_MOTION_BOUNDARY, sizeof(GET_MOTION_BOUNDARY)); } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_spatial_static_value() { | ||||||
|  |   this->send_query_(GET_SPATIAL_STATIC_VALUE, sizeof(GET_SPATIAL_STATIC_VALUE)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_spatial_motion_value() { | ||||||
|  |   this->send_query_(GET_SPATIAL_MOTION_VALUE, sizeof(GET_SPATIAL_MOTION_VALUE)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_distance_of_static_object() { | ||||||
|  |   this->send_query_(GET_DISTANCE_OF_STATIC_OBJECT, sizeof(GET_DISTANCE_OF_STATIC_OBJECT)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_distance_of_moving_object() { | ||||||
|  |   this->send_query_(GET_DISTANCE_OF_MOVING_OBJECT, sizeof(GET_DISTANCE_OF_MOVING_OBJECT)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_target_movement_speed() { | ||||||
|  |   this->send_query_(GET_TARGET_MOVEMENT_SPEED, sizeof(GET_TARGET_MOVEMENT_SPEED)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_existence_threshold() { | ||||||
|  |   this->send_query_(GET_EXISTENCE_THRESHOLD, sizeof(GET_EXISTENCE_THRESHOLD)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_motion_threshold() { | ||||||
|  |   this->send_query_(GET_MOTION_THRESHOLD, sizeof(GET_MOTION_THRESHOLD)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_motion_trigger_time() { | ||||||
|  |   this->send_query_(GET_MOTION_TRIGGER_TIME, sizeof(GET_MOTION_TRIGGER_TIME)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_motion_to_rest_time() { | ||||||
|  |   this->send_query_(GET_MOTION_TO_REST_TIME, sizeof(GET_MOTION_TO_REST_TIME)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::get_custom_unman_time() { | ||||||
|  |   this->send_query_(GET_CUSTOM_UNMAN_TIME, sizeof(GET_CUSTOM_UNMAN_TIME)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Logic of setting: After setting, query whether the setting is successful or not! | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_underlying_open_function(bool enable) { | ||||||
|  |   if (enable) { | ||||||
|  |     this->send_query_(UNDERLYING_SWITCH_ON, sizeof(UNDERLYING_SWITCH_ON)); | ||||||
|  |   } else { | ||||||
|  |     this->send_query_(UNDERLYING_SWITCH_OFF, sizeof(UNDERLYING_SWITCH_OFF)); | ||||||
|  |   } | ||||||
|  |   if (this->keep_away_text_sensor_ != nullptr) { | ||||||
|  |     this->keep_away_text_sensor_->publish_state(""); | ||||||
|  |   } | ||||||
|  |   if (this->motion_status_text_sensor_ != nullptr) { | ||||||
|  |     this->motion_status_text_sensor_->publish_state(""); | ||||||
|  |   } | ||||||
|  |   if (this->custom_spatial_static_value_sensor_ != nullptr) { | ||||||
|  |     this->custom_spatial_static_value_sensor_->publish_state(NAN); | ||||||
|  |   } | ||||||
|  |   if (this->custom_spatial_motion_value_sensor_ != nullptr) { | ||||||
|  |     this->custom_spatial_motion_value_sensor_->publish_state(NAN); | ||||||
|  |   } | ||||||
|  |   if (this->custom_motion_distance_sensor_ != nullptr) { | ||||||
|  |     this->custom_motion_distance_sensor_->publish_state(NAN); | ||||||
|  |   } | ||||||
|  |   if (this->custom_presence_of_detection_sensor_ != nullptr) { | ||||||
|  |     this->custom_presence_of_detection_sensor_->publish_state(NAN); | ||||||
|  |   } | ||||||
|  |   if (this->custom_motion_speed_sensor_ != nullptr) { | ||||||
|  |     this->custom_motion_speed_sensor_->publish_state(NAN); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_scene_mode(uint8_t value) { | ||||||
|  |   uint8_t send_data_len = 10; | ||||||
|  |   uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x07, 0x00, 0x01, value, 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[7] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   if (this->custom_mode_number_ != nullptr) { | ||||||
|  |     this->custom_mode_number_->publish_state(0); | ||||||
|  |   } | ||||||
|  |   if (this->custom_mode_num_sensor_ != nullptr) { | ||||||
|  |     this->custom_mode_num_sensor_->publish_state(0); | ||||||
|  |   } | ||||||
|  |   this->get_scene_mode(); | ||||||
|  |   this->get_sensitivity(); | ||||||
|  |   this->get_custom_mode(); | ||||||
|  |   this->get_existence_boundary(); | ||||||
|  |   this->get_motion_boundary(); | ||||||
|  |   this->get_existence_threshold(); | ||||||
|  |   this->get_motion_threshold(); | ||||||
|  |   this->get_motion_trigger_time(); | ||||||
|  |   this->get_motion_to_rest_time(); | ||||||
|  |   this->get_custom_unman_time(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_sensitivity(uint8_t value) { | ||||||
|  |   if (value == 0x00) | ||||||
|  |     return; | ||||||
|  |   uint8_t send_data_len = 10; | ||||||
|  |   uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x08, 0x00, 0x01, value, 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[7] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   this->get_scene_mode(); | ||||||
|  |   this->get_sensitivity(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_restart() { | ||||||
|  |   this->send_query_(SET_RESTART, sizeof(SET_RESTART)); | ||||||
|  |   this->check_dev_inf_sign_ = true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_unman_time(uint8_t value) { | ||||||
|  |   uint8_t send_data_len = 10; | ||||||
|  |   uint8_t send_data[10] = {0x53, 0x59, 0x80, 0x0a, 0x00, 0x01, value, 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[7] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   this->get_unmanned_time(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_custom_mode(uint8_t mode) { | ||||||
|  |   if (mode == 0) { | ||||||
|  |     this->set_custom_end_mode();  // Equivalent to end setting | ||||||
|  |     if (this->custom_mode_number_ != nullptr) { | ||||||
|  |       this->custom_mode_number_->publish_state(0); | ||||||
|  |     } | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   uint8_t send_data_len = 10; | ||||||
|  |   uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x09, 0x00, 0x01, mode, 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[7] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   this->get_existence_boundary(); | ||||||
|  |   this->get_motion_boundary(); | ||||||
|  |   this->get_existence_threshold(); | ||||||
|  |   this->get_motion_threshold(); | ||||||
|  |   this->get_motion_trigger_time(); | ||||||
|  |   this->get_motion_to_rest_time(); | ||||||
|  |   this->get_custom_unman_time(); | ||||||
|  |   this->get_custom_mode(); | ||||||
|  |   this->get_scene_mode(); | ||||||
|  |   this->get_sensitivity(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_custom_end_mode() { | ||||||
|  |   uint8_t send_data_len = 10; | ||||||
|  |   uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x0a, 0x00, 0x01, 0x0F, 0xCB, 0x54, 0x43}; | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   if (this->custom_mode_number_ != nullptr) { | ||||||
|  |     this->custom_mode_number_->publish_state(0);  // Clear setpoints | ||||||
|  |   } | ||||||
|  |   this->get_existence_boundary(); | ||||||
|  |   this->get_motion_boundary(); | ||||||
|  |   this->get_existence_threshold(); | ||||||
|  |   this->get_motion_threshold(); | ||||||
|  |   this->get_motion_trigger_time(); | ||||||
|  |   this->get_motion_to_rest_time(); | ||||||
|  |   this->get_custom_unman_time(); | ||||||
|  |   this->get_custom_mode(); | ||||||
|  |   this->get_scene_mode(); | ||||||
|  |   this->get_sensitivity(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_existence_boundary(uint8_t value) { | ||||||
|  |   if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) | ||||||
|  |     return;  // You'll have to check that you're in custom mode to set it up | ||||||
|  |   uint8_t send_data_len = 10; | ||||||
|  |   uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x0A, 0x00, 0x01, (uint8_t) (value + 1), 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[7] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   this->get_existence_boundary(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_motion_boundary(uint8_t value) { | ||||||
|  |   if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) | ||||||
|  |     return;  // You'll have to check that you're in custom mode to set it up | ||||||
|  |   uint8_t send_data_len = 10; | ||||||
|  |   uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x0B, 0x00, 0x01, (uint8_t) (value + 1), 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[7] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   this->get_motion_boundary(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_existence_threshold(uint8_t value) { | ||||||
|  |   if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) | ||||||
|  |     return;  // You'll have to check that you're in custom mode to set it up | ||||||
|  |   uint8_t send_data_len = 10; | ||||||
|  |   uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x08, 0x00, 0x01, value, 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[7] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   this->get_existence_threshold(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_motion_threshold(uint8_t value) { | ||||||
|  |   if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) | ||||||
|  |     return;  // You'll have to check that you're in custom mode to set it up | ||||||
|  |   uint8_t send_data_len = 10; | ||||||
|  |   uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x09, 0x00, 0x01, value, 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[7] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   this->get_motion_threshold(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_motion_trigger_time(uint8_t value) { | ||||||
|  |   if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) | ||||||
|  |     return;  // You'll have to check that you're in custom mode to set it up | ||||||
|  |   uint8_t send_data_len = 13; | ||||||
|  |   uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, value, 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[10] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   this->get_motion_trigger_time(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_motion_to_rest_time(uint16_t value) { | ||||||
|  |   if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) | ||||||
|  |     return;  // You'll have to check that you're in custom mode to set it up | ||||||
|  |   uint8_t h8_num = (value >> 8) & 0xff; | ||||||
|  |   uint8_t l8_num = value & 0xff; | ||||||
|  |   uint8_t send_data_len = 13; | ||||||
|  |   uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0D, 0x00, 0x04, 0x00, 0x00, h8_num, l8_num, 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[10] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   this->get_motion_to_rest_time(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MR24HPC1Component::set_custom_unman_time(uint16_t value) { | ||||||
|  |   if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) | ||||||
|  |     return;  // You'll have to check that you're in custom mode to set it up | ||||||
|  |   uint32_t value_ms = value * 1000; | ||||||
|  |   uint8_t h24_num = (value_ms >> 24) & 0xff; | ||||||
|  |   uint8_t h16_num = (value_ms >> 16) & 0xff; | ||||||
|  |   uint8_t h8_num = (value_ms >> 8) & 0xff; | ||||||
|  |   uint8_t l8_num = value_ms & 0xff; | ||||||
|  |   uint8_t send_data_len = 13; | ||||||
|  |   uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0E, 0x00, 0x04, h24_num, h16_num, h8_num, l8_num, 0x00, 0x54, 0x43}; | ||||||
|  |   send_data[10] = get_frame_crc_sum(send_data, send_data_len); | ||||||
|  |   this->send_query_(send_data, send_data_len); | ||||||
|  |   this->get_custom_unman_time(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										217
									
								
								esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,217 @@ | |||||||
|  | #pragma once | ||||||
|  | #include "esphome/core/component.h" | ||||||
|  | #include "esphome/core/defines.h" | ||||||
|  | #ifdef USE_BINARY_SENSOR | ||||||
|  | #include "esphome/components/binary_sensor/binary_sensor.h" | ||||||
|  | #endif | ||||||
|  | #ifdef USE_SENSOR | ||||||
|  | #include "esphome/components/sensor/sensor.h" | ||||||
|  | #endif | ||||||
|  | #ifdef USE_NUMBER | ||||||
|  | #include "esphome/components/number/number.h" | ||||||
|  | #endif | ||||||
|  | #ifdef USE_SWITCH | ||||||
|  | #include "esphome/components/switch/switch.h" | ||||||
|  | #endif | ||||||
|  | #ifdef USE_BUTTON | ||||||
|  | #include "esphome/components/button/button.h" | ||||||
|  | #endif | ||||||
|  | #ifdef USE_SELECT | ||||||
|  | #include "esphome/components/select/select.h" | ||||||
|  | #endif | ||||||
|  | #ifdef USE_TEXT_SENSOR | ||||||
|  | #include "esphome/components/text_sensor/text_sensor.h" | ||||||
|  | #endif | ||||||
|  | #include "esphome/components/uart/uart.h" | ||||||
|  | #include "esphome/core/automation.h" | ||||||
|  | #include "esphome/core/helpers.h" | ||||||
|  |  | ||||||
|  | #include "seeed_mr24hpc1_constants.h" | ||||||
|  |  | ||||||
|  | #include <map> | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | enum FrameState { | ||||||
|  |   FRAME_IDLE, | ||||||
|  |   FRAME_HEADER2, | ||||||
|  |   FRAME_CTL_WORD, | ||||||
|  |   FRAME_CMD_WORD, | ||||||
|  |   FRAME_DATA_LEN_H, | ||||||
|  |   FRAME_DATA_LEN_L, | ||||||
|  |   FRAME_DATA_BYTES, | ||||||
|  |   FRAME_DATA_CRC, | ||||||
|  |   FRAME_TAIL1, | ||||||
|  |   FRAME_TAIL2, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum PollingState { | ||||||
|  |   STANDARD_FUNCTION_QUERY_PRODUCT_MODE = 0, | ||||||
|  |   STANDARD_FUNCTION_QUERY_PRODUCT_ID, | ||||||
|  |   STANDARD_FUNCTION_QUERY_FIRMWARE_VERSION, | ||||||
|  |   STANDARD_FUNCTION_QUERY_HARDWARE_MODE,  // Above is the equipment information | ||||||
|  |   STANDARD_FUNCTION_QUERY_SCENE_MODE, | ||||||
|  |   STANDARD_FUNCTION_QUERY_SENSITIVITY, | ||||||
|  |   STANDARD_FUNCTION_QUERY_UNMANNED_TIME, | ||||||
|  |   STANDARD_FUNCTION_QUERY_HUMAN_STATUS, | ||||||
|  |   STANDARD_FUNCTION_QUERY_HUMAN_MOTION_INF, | ||||||
|  |   STANDARD_FUNCTION_QUERY_BODY_MOVE_PARAMETER, | ||||||
|  |   STANDARD_FUNCTION_QUERY_KEEPAWAY_STATUS, | ||||||
|  |   STANDARD_QUERY_CUSTOM_MODE, | ||||||
|  |   STANDARD_FUNCTION_QUERY_HEARTBEAT_STATE,  // Above is the basic function | ||||||
|  |  | ||||||
|  |   CUSTOM_FUNCTION_QUERY_EXISTENCE_BOUNDARY, | ||||||
|  |   CUSTOM_FUNCTION_QUERY_MOTION_BOUNDARY, | ||||||
|  |   CUSTOM_FUNCTION_QUERY_EXISTENCE_THRESHOLD, | ||||||
|  |   CUSTOM_FUNCTION_QUERY_MOTION_THRESHOLD, | ||||||
|  |   CUSTOM_FUNCTION_QUERY_MOTION_TRIGGER_TIME, | ||||||
|  |   CUSTOM_FUNCTION_QUERY_MOTION_TO_REST_TIME, | ||||||
|  |   CUSTOM_FUNCTION_QUERY_TIME_OF_ENTER_UNMANNED, | ||||||
|  |  | ||||||
|  |   UNDERLY_FUNCTION_QUERY_HUMAN_STATUS, | ||||||
|  |   UNDERLY_FUNCTION_QUERY_SPATIAL_STATIC_VALUE, | ||||||
|  |   UNDERLY_FUNCTION_QUERY_SPATIAL_MOTION_VALUE, | ||||||
|  |   UNDERLY_FUNCTION_QUERY_DISTANCE_OF_STATIC_OBJECT, | ||||||
|  |   UNDERLY_FUNCTION_QUERY_DISTANCE_OF_MOVING_OBJECT, | ||||||
|  |   UNDERLY_FUNCTION_QUERY_TARGET_MOVEMENT_SPEED, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum OutputSwitch { | ||||||
|  |   OUTPUT_SWITCH_INIT, | ||||||
|  |   OUTPUT_SWITCH_ON, | ||||||
|  |   OUTPUT_SWTICH_OFF, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const char *const S_SCENE_STR[5] = {"None", "Living Room", "Bedroom", "Washroom", "Area Detection"}; | ||||||
|  | static const bool S_SOMEONE_EXISTS_STR[2] = {false, true}; | ||||||
|  | static const char *const S_MOTION_STATUS_STR[3] = {"None", "Motionless", "Active"}; | ||||||
|  | static const char *const S_KEEP_AWAY_STR[3] = {"None", "Close", "Away"}; | ||||||
|  | static const char *const S_UNMANNED_TIME_STR[9] = {"None", "10s",   "30s",   "1min", "2min", | ||||||
|  |                                                    "5min", "10min", "30min", "60min"}; | ||||||
|  | static const char *const S_BOUNDARY_STR[10] = {"0.5m", "1.0m", "1.5m", "2.0m", "2.5m", | ||||||
|  |                                                "3.0m", "3.5m", "4.0m", "4.5m", "5.0m"};                // uint: m | ||||||
|  | static const float S_PRESENCE_OF_DETECTION_RANGE_STR[7] = {0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f};  // uint: m | ||||||
|  |  | ||||||
|  | class MR24HPC1Component : public Component, | ||||||
|  |                           public uart::UARTDevice {  // The class name must be the name defined by text_sensor.py | ||||||
|  | #ifdef USE_TEXT_SENSOR | ||||||
|  |   SUB_TEXT_SENSOR(heartbeat_state) | ||||||
|  |   SUB_TEXT_SENSOR(product_model) | ||||||
|  |   SUB_TEXT_SENSOR(product_id) | ||||||
|  |   SUB_TEXT_SENSOR(hardware_model) | ||||||
|  |   SUB_TEXT_SENSOR(firware_version) | ||||||
|  |   SUB_TEXT_SENSOR(keep_away) | ||||||
|  |   SUB_TEXT_SENSOR(motion_status) | ||||||
|  |   SUB_TEXT_SENSOR(custom_mode_end) | ||||||
|  | #endif | ||||||
|  | #ifdef USE_BINARY_SENSOR | ||||||
|  |   SUB_BINARY_SENSOR(has_target) | ||||||
|  | #endif | ||||||
|  | #ifdef USE_SENSOR | ||||||
|  |   SUB_SENSOR(custom_presence_of_detection) | ||||||
|  |   SUB_SENSOR(movement_signs) | ||||||
|  |   SUB_SENSOR(custom_motion_distance) | ||||||
|  |   SUB_SENSOR(custom_spatial_static_value) | ||||||
|  |   SUB_SENSOR(custom_spatial_motion_value) | ||||||
|  |   SUB_SENSOR(custom_motion_speed) | ||||||
|  |   SUB_SENSOR(custom_mode_num) | ||||||
|  | #endif | ||||||
|  | #ifdef USE_SWITCH | ||||||
|  |   SUB_SWITCH(underlying_open_function) | ||||||
|  | #endif | ||||||
|  | #ifdef USE_BUTTON | ||||||
|  |   SUB_BUTTON(restart) | ||||||
|  |   SUB_BUTTON(custom_set_end) | ||||||
|  | #endif | ||||||
|  | #ifdef USE_SELECT | ||||||
|  |   SUB_SELECT(scene_mode) | ||||||
|  |   SUB_SELECT(unman_time) | ||||||
|  |   SUB_SELECT(existence_boundary) | ||||||
|  |   SUB_SELECT(motion_boundary) | ||||||
|  | #endif | ||||||
|  | #ifdef USE_NUMBER | ||||||
|  |   SUB_NUMBER(sensitivity) | ||||||
|  |   SUB_NUMBER(custom_mode) | ||||||
|  |   SUB_NUMBER(existence_threshold) | ||||||
|  |   SUB_NUMBER(motion_threshold) | ||||||
|  |   SUB_NUMBER(motion_trigger) | ||||||
|  |   SUB_NUMBER(motion_to_rest) | ||||||
|  |   SUB_NUMBER(custom_unman_time) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   char c_product_mode_[PRODUCT_BUF_MAX_SIZE + 1]; | ||||||
|  |   char c_product_id_[PRODUCT_BUF_MAX_SIZE + 1]; | ||||||
|  |   char c_hardware_model_[PRODUCT_BUF_MAX_SIZE + 1]; | ||||||
|  |   char c_firmware_version_[PRODUCT_BUF_MAX_SIZE + 1]; | ||||||
|  |   uint8_t s_output_info_switch_flag_; | ||||||
|  |   uint8_t sg_recv_data_state_; | ||||||
|  |   uint8_t sg_frame_len_; | ||||||
|  |   uint8_t sg_data_len_; | ||||||
|  |   uint8_t sg_frame_buf_[FRAME_BUF_MAX_SIZE]; | ||||||
|  |   uint8_t sg_frame_prase_buf_[FRAME_BUF_MAX_SIZE]; | ||||||
|  |   int sg_start_query_data_; | ||||||
|  |   bool check_dev_inf_sign_; | ||||||
|  |   bool poll_time_base_func_check_; | ||||||
|  |  | ||||||
|  |   void update_(); | ||||||
|  |   void r24_split_data_frame_(uint8_t value); | ||||||
|  |   void r24_parse_data_frame_(uint8_t *data, uint8_t len); | ||||||
|  |   void r24_frame_parse_open_underlying_information_(uint8_t *data); | ||||||
|  |   void r24_frame_parse_work_status_(uint8_t *data); | ||||||
|  |   void r24_frame_parse_product_information_(uint8_t *data); | ||||||
|  |   void r24_frame_parse_human_information_(uint8_t *data); | ||||||
|  |   void send_query_(const uint8_t *query, size_t string_length); | ||||||
|  |  | ||||||
|  |  public: | ||||||
|  |   float get_setup_priority() const override { return esphome::setup_priority::LATE; } | ||||||
|  |   void setup() override; | ||||||
|  |   void dump_config() override; | ||||||
|  |   void loop() override; | ||||||
|  |  | ||||||
|  |   void get_heartbeat_packet(); | ||||||
|  |   void get_radar_output_information_switch(); | ||||||
|  |   void get_product_mode(); | ||||||
|  |   void get_product_id(); | ||||||
|  |   void get_hardware_model(); | ||||||
|  |   void get_firmware_version(); | ||||||
|  |   void get_human_status(); | ||||||
|  |   void get_human_motion_info(); | ||||||
|  |   void get_body_motion_params(); | ||||||
|  |   void get_keep_away(); | ||||||
|  |   void get_scene_mode(); | ||||||
|  |   void get_sensitivity(); | ||||||
|  |   void get_unmanned_time(); | ||||||
|  |   void get_custom_mode(); | ||||||
|  |   void get_existence_boundary(); | ||||||
|  |   void get_motion_boundary(); | ||||||
|  |   void get_spatial_static_value(); | ||||||
|  |   void get_spatial_motion_value(); | ||||||
|  |   void get_distance_of_static_object(); | ||||||
|  |   void get_distance_of_moving_object(); | ||||||
|  |   void get_target_movement_speed(); | ||||||
|  |   void get_existence_threshold(); | ||||||
|  |   void get_motion_threshold(); | ||||||
|  |   void get_motion_trigger_time(); | ||||||
|  |   void get_motion_to_rest_time(); | ||||||
|  |   void get_custom_unman_time(); | ||||||
|  |  | ||||||
|  |   void set_scene_mode(uint8_t value); | ||||||
|  |   void set_underlying_open_function(bool enable); | ||||||
|  |   void set_sensitivity(uint8_t value); | ||||||
|  |   void set_restart(); | ||||||
|  |   void set_unman_time(uint8_t value); | ||||||
|  |   void set_custom_mode(uint8_t mode); | ||||||
|  |   void set_custom_end_mode(); | ||||||
|  |   void set_existence_boundary(uint8_t value); | ||||||
|  |   void set_motion_boundary(uint8_t value); | ||||||
|  |   void set_existence_threshold(uint8_t value); | ||||||
|  |   void set_motion_threshold(uint8_t value); | ||||||
|  |   void set_motion_trigger_time(uint8_t value); | ||||||
|  |   void set_motion_to_rest_time(uint16_t value); | ||||||
|  |   void set_custom_unman_time(uint16_t value); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										173
									
								
								esphome/components/seeed_mr24hpc1/seeed_mr24hpc1_constants.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								esphome/components/seeed_mr24hpc1/seeed_mr24hpc1_constants.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <cstdint> | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | static const uint8_t FRAME_BUF_MAX_SIZE = 128; | ||||||
|  | static const uint8_t PRODUCT_BUF_MAX_SIZE = 32; | ||||||
|  |  | ||||||
|  | static const uint8_t FRAME_CONTROL_WORD_INDEX = 2; | ||||||
|  | static const uint8_t FRAME_COMMAND_WORD_INDEX = 3; | ||||||
|  | static const uint8_t FRAME_DATA_INDEX = 6; | ||||||
|  |  | ||||||
|  | static const uint8_t FRAME_HEADER1_VALUE = 0x53; | ||||||
|  | static const uint8_t FRAME_HEADER2_VALUE = 0x59; | ||||||
|  | static const uint8_t FRAME_TAIL1_VALUE = 0x54; | ||||||
|  | static const uint8_t FRAME_TAIL2_VALUE = 0x43; | ||||||
|  |  | ||||||
|  | static const uint8_t CONTROL_MAIN = 0x01; | ||||||
|  | static const uint8_t CONTROL_PRODUCT_INFORMATION = 0x02; | ||||||
|  | static const uint8_t CONTROL_WORK = 0x05; | ||||||
|  | static const uint8_t CONTROL_UNDERLYING_FUNCTION = 0x08; | ||||||
|  | static const uint8_t CONTROL_HUMAN_INFORMATION = 0x80; | ||||||
|  |  | ||||||
|  | static const uint8_t COMMAND_HEARTBEAT = 0x01; | ||||||
|  | static const uint8_t COMMAND_RESTART = 0x02; | ||||||
|  |  | ||||||
|  | static const uint8_t COMMAND_PRODUCT_MODE = 0xA1; | ||||||
|  | static const uint8_t COMMAND_PRODUCT_ID = 0xA2; | ||||||
|  | static const uint8_t COMMAND_HARDWARE_MODEL = 0xA3; | ||||||
|  | static const uint8_t COMMAND_FIRMWARE_VERSION = 0xA4; | ||||||
|  |  | ||||||
|  | static const uint8_t GET_HEARTBEAT[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_MAIN, COMMAND_HEARTBEAT, 0x00, 0x01, 0x0F, 0xBE, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t SET_RESTART[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_MAIN, COMMAND_RESTART, 0x00, 0x01, 0x0F, 0xBF, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const uint8_t GET_PRODUCT_MODE[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_PRODUCT_INFORMATION, COMMAND_PRODUCT_MODE, 0x00, 0x01, 0x0F, 0x5F, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_PRODUCT_ID[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_PRODUCT_INFORMATION, COMMAND_PRODUCT_ID, 0x00, 0x01, 0x0F, 0x60, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_HARDWARE_MODEL[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, | ||||||
|  |     FRAME_HEADER2_VALUE, | ||||||
|  |     CONTROL_PRODUCT_INFORMATION, | ||||||
|  |     COMMAND_HARDWARE_MODEL, | ||||||
|  |     0x00, | ||||||
|  |     0x01, | ||||||
|  |     0x0F, | ||||||
|  |     0x61, | ||||||
|  |     FRAME_TAIL1_VALUE, | ||||||
|  |     FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_FIRMWARE_VERSION[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, | ||||||
|  |     FRAME_HEADER2_VALUE, | ||||||
|  |     CONTROL_PRODUCT_INFORMATION, | ||||||
|  |     COMMAND_FIRMWARE_VERSION, | ||||||
|  |     0x00, | ||||||
|  |     0x01, | ||||||
|  |     0x0F, | ||||||
|  |     0x62, | ||||||
|  |     FRAME_TAIL1_VALUE, | ||||||
|  |     FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const uint8_t GET_SCENE_MODE[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_WORK, 0x87, 0x00, 0x01, 0x0F, 0x48, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_SENSITIVITY[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_WORK, 0x88, 0x00, 0x01, 0x0F, 0x49, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_CUSTOM_MODE[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_WORK, 0x89, 0x00, 0x01, 0x0F, 0x4A, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const uint8_t UNDERLYING_SWITCH_ON[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x00, 0x00, 0x01, 0x01, 0xB6, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t UNDERLYING_SWITCH_OFF[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x00, 0x00, 0x01, 0x00, 0xB5, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const uint8_t GET_RADAR_OUTPUT_INFORMATION_SWITCH[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x80, 0x00, 0x01, 0x0F, 0x44, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_SPATIAL_STATIC_VALUE[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x81, 0x00, 0x01, 0x0F, 0x45, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_SPATIAL_MOTION_VALUE[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x82, 0x00, 0x01, 0x0F, 0x46, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_DISTANCE_OF_STATIC_OBJECT[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x83, 0x00, 0x01, 0x0F, 0x47, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_DISTANCE_OF_MOVING_OBJECT[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x84, 0x00, 0x01, 0x0F, 0x48, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_TARGET_MOVEMENT_SPEED[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x85, 0x00, 0x01, 0x0F, 0x49, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_EXISTENCE_THRESHOLD[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x88, 0x00, 0x01, 0x0F, 0x4C, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_MOTION_THRESHOLD[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x89, 0x00, 0x01, 0x0F, 0x4D, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_EXISTENCE_BOUNDARY[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x8A, 0x00, 0x01, 0x0F, 0x4E, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_MOTION_BOUNDARY[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x8B, 0x00, 0x01, 0x0F, 0x4F, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_MOTION_TRIGGER_TIME[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x8C, 0x00, 0x01, 0x0F, 0x50, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_MOTION_TO_REST_TIME[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x8D, 0x00, 0x01, 0x0F, 0x51, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_CUSTOM_UNMAN_TIME[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_UNDERLYING_FUNCTION, 0x8E, 0x00, 0x01, 0x0F, 0x52, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static const uint8_t GET_HUMAN_STATUS[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_HUMAN_INFORMATION, 0x81, 0x00, 0x01, 0x0F, 0xBD, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_HUMAN_MOTION_INFORMATION[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_HUMAN_INFORMATION, 0x82, 0x00, 0x01, 0x0F, 0xBE, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_BODY_MOTION_PARAMETERS[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_HUMAN_INFORMATION, 0x83, 0x00, 0x01, 0x0F, 0xBF, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_UNMANNED_TIME[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_HUMAN_INFORMATION, 0x8A, 0x00, 0x01, 0x0F, 0xC6, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  | static const uint8_t GET_KEEP_AWAY[] = { | ||||||
|  |     FRAME_HEADER1_VALUE, FRAME_HEADER2_VALUE, CONTROL_HUMAN_INFORMATION, 0x8B, 0x00, 0x01, 0x0F, 0xC7, | ||||||
|  |     FRAME_TAIL1_VALUE,   FRAME_TAIL2_VALUE, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										103
									
								
								esphome/components/seeed_mr24hpc1/select/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								esphome/components/seeed_mr24hpc1/select/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components import select | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import ( | ||||||
|  |     ENTITY_CATEGORY_CONFIG, | ||||||
|  | ) | ||||||
|  | from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns | ||||||
|  |  | ||||||
|  | SceneModeSelect = mr24hpc1_ns.class_("SceneModeSelect", select.Select) | ||||||
|  | UnmanTimeSelect = mr24hpc1_ns.class_("UnmanTimeSelect", select.Select) | ||||||
|  | ExistenceBoundarySelect = mr24hpc1_ns.class_("ExistenceBoundarySelect", select.Select) | ||||||
|  | MotionBoundarySelect = mr24hpc1_ns.class_("MotionBoundarySelect", select.Select) | ||||||
|  |  | ||||||
|  | CONF_SCENE_MODE = "scene_mode" | ||||||
|  | CONF_UNMAN_TIME = "unman_time" | ||||||
|  | CONF_EXISTENCE_BOUNDARY = "existence_boundary" | ||||||
|  | CONF_MOTION_BOUNDARY = "motion_boundary" | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = { | ||||||
|  |     cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), | ||||||
|  |     cv.Optional(CONF_SCENE_MODE): select.select_schema( | ||||||
|  |         SceneModeSelect, | ||||||
|  |         entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |         icon="mdi:hoop-house", | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_UNMAN_TIME): select.select_schema( | ||||||
|  |         UnmanTimeSelect, | ||||||
|  |         entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |         icon="mdi:timeline-clock", | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_EXISTENCE_BOUNDARY): select.select_schema( | ||||||
|  |         ExistenceBoundarySelect, | ||||||
|  |         entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_MOTION_BOUNDARY): select.select_schema( | ||||||
|  |         MotionBoundarySelect, | ||||||
|  |         entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |     ), | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) | ||||||
|  |     if scenemode_config := config.get(CONF_SCENE_MODE): | ||||||
|  |         s = await select.new_select( | ||||||
|  |             scenemode_config, | ||||||
|  |             options=["None", "Living Room", "Bedroom", "Washroom", "Area Detection"], | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(s, config[CONF_MR24HPC1_ID]) | ||||||
|  |         cg.add(mr24hpc1_component.set_scene_mode_select(s)) | ||||||
|  |     if unmantime_config := config.get(CONF_UNMAN_TIME): | ||||||
|  |         s = await select.new_select( | ||||||
|  |             unmantime_config, | ||||||
|  |             options=[ | ||||||
|  |                 "None", | ||||||
|  |                 "10s", | ||||||
|  |                 "30s", | ||||||
|  |                 "1min", | ||||||
|  |                 "2min", | ||||||
|  |                 "5min", | ||||||
|  |                 "10min", | ||||||
|  |                 "30min", | ||||||
|  |                 "60min", | ||||||
|  |             ], | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(s, config[CONF_MR24HPC1_ID]) | ||||||
|  |         cg.add(mr24hpc1_component.set_unman_time_select(s)) | ||||||
|  |     if existence_boundary_config := config.get(CONF_EXISTENCE_BOUNDARY): | ||||||
|  |         s = await select.new_select( | ||||||
|  |             existence_boundary_config, | ||||||
|  |             options=[ | ||||||
|  |                 "0.5m", | ||||||
|  |                 "1.0m", | ||||||
|  |                 "1.5m", | ||||||
|  |                 "2.0m", | ||||||
|  |                 "2.5m", | ||||||
|  |                 "3.0m", | ||||||
|  |                 "3.5m", | ||||||
|  |                 "4.0m", | ||||||
|  |                 "4.5m", | ||||||
|  |                 "5.0m", | ||||||
|  |             ], | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(s, config[CONF_MR24HPC1_ID]) | ||||||
|  |         cg.add(mr24hpc1_component.set_existence_boundary_select(s)) | ||||||
|  |     if motion_boundary_config := config.get(CONF_MOTION_BOUNDARY): | ||||||
|  |         s = await select.new_select( | ||||||
|  |             motion_boundary_config, | ||||||
|  |             options=[ | ||||||
|  |                 "0.5m", | ||||||
|  |                 "1.0m", | ||||||
|  |                 "1.5m", | ||||||
|  |                 "2.0m", | ||||||
|  |                 "2.5m", | ||||||
|  |                 "3.0m", | ||||||
|  |                 "3.5m", | ||||||
|  |                 "4.0m", | ||||||
|  |                 "4.5m", | ||||||
|  |                 "5.0m", | ||||||
|  |             ], | ||||||
|  |         ) | ||||||
|  |         await cg.register_parented(s, config[CONF_MR24HPC1_ID]) | ||||||
|  |         cg.add(mr24hpc1_component.set_motion_boundary_select(s)) | ||||||
| @@ -0,0 +1,15 @@ | |||||||
|  | #include "existence_boundary_select.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void ExistenceBoundarySelect::control(const std::string &value) { | ||||||
|  |   this->publish_state(value); | ||||||
|  |   auto index = this->index_of(value); | ||||||
|  |   if (index.has_value()) { | ||||||
|  |     this->parent_->set_existence_boundary(index.value()); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/select/select.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class ExistenceBoundarySelect : public select::Select, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   ExistenceBoundarySelect() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(const std::string &value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,15 @@ | |||||||
|  | #include "motion_boundary_select.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void MotionBoundarySelect::control(const std::string &value) { | ||||||
|  |   this->publish_state(value); | ||||||
|  |   auto index = this->index_of(value); | ||||||
|  |   if (index.has_value()) { | ||||||
|  |     this->parent_->set_motion_boundary(index.value()); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/select/select.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class MotionBoundarySelect : public select::Select, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   MotionBoundarySelect() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(const std::string &value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,15 @@ | |||||||
|  | #include "scene_mode_select.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void SceneModeSelect::control(const std::string &value) { | ||||||
|  |   this->publish_state(value); | ||||||
|  |   auto index = this->index_of(value); | ||||||
|  |   if (index.has_value()) { | ||||||
|  |     this->parent_->set_scene_mode(index.value()); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										18
									
								
								esphome/components/seeed_mr24hpc1/select/scene_mode_select.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								esphome/components/seeed_mr24hpc1/select/scene_mode_select.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/select/select.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class SceneModeSelect : public select::Select, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   SceneModeSelect() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(const std::string &value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
| @@ -0,0 +1,15 @@ | |||||||
|  | #include "unman_time_select.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void UnmanTimeSelect::control(const std::string &value) { | ||||||
|  |   this->publish_state(value); | ||||||
|  |   auto index = this->index_of(value); | ||||||
|  |   if (index.has_value()) { | ||||||
|  |     this->parent_->set_unman_time(index.value()); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										18
									
								
								esphome/components/seeed_mr24hpc1/select/unman_time_select.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								esphome/components/seeed_mr24hpc1/select/unman_time_select.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/select/select.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class UnmanTimeSelect : public select::Select, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   UnmanTimeSelect() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void control(const std::string &value) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										82
									
								
								esphome/components/seeed_mr24hpc1/sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								esphome/components/seeed_mr24hpc1/sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components import sensor | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import ( | ||||||
|  |     DEVICE_CLASS_DISTANCE, | ||||||
|  |     DEVICE_CLASS_ENERGY, | ||||||
|  |     DEVICE_CLASS_SPEED, | ||||||
|  |     UNIT_METER, | ||||||
|  | ) | ||||||
|  | from . import CONF_MR24HPC1_ID, MR24HPC1Component | ||||||
|  |  | ||||||
|  | CONF_CUSTOM_PRESENCE_OF_DETECTION = "custom_presence_of_detection" | ||||||
|  | CONF_MOVEMENT_SIGNS = "movement_signs" | ||||||
|  | CONF_CUSTOM_MOTION_DISTANCE = "custom_motion_distance" | ||||||
|  | CONF_CUSTOM_SPATIAL_STATIC_VALUE = "custom_spatial_static_value" | ||||||
|  | CONF_CUSTOM_SPATIAL_MOTION_VALUE = "custom_spatial_motion_value" | ||||||
|  | CONF_CUSTOM_MOTION_SPEED = "custom_motion_speed" | ||||||
|  | CONF_CUSTOM_MODE_NUM = "custom_mode_num" | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = cv.Schema( | ||||||
|  |     { | ||||||
|  |         cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), | ||||||
|  |         cv.Optional(CONF_CUSTOM_PRESENCE_OF_DETECTION): sensor.sensor_schema( | ||||||
|  |             device_class=DEVICE_CLASS_DISTANCE, | ||||||
|  |             unit_of_measurement=UNIT_METER, | ||||||
|  |             accuracy_decimals=2,  # Specify the number of decimal places | ||||||
|  |             icon="mdi:signal-distance-variant", | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_MOVEMENT_SIGNS): sensor.sensor_schema( | ||||||
|  |             icon="mdi:human-greeting-variant", | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_CUSTOM_MOTION_DISTANCE): sensor.sensor_schema( | ||||||
|  |             unit_of_measurement=UNIT_METER, | ||||||
|  |             accuracy_decimals=2, | ||||||
|  |             icon="mdi:signal-distance-variant", | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_CUSTOM_SPATIAL_STATIC_VALUE): sensor.sensor_schema( | ||||||
|  |             device_class=DEVICE_CLASS_ENERGY, | ||||||
|  |             icon="mdi:counter", | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_CUSTOM_SPATIAL_MOTION_VALUE): sensor.sensor_schema( | ||||||
|  |             device_class=DEVICE_CLASS_ENERGY, | ||||||
|  |             icon="mdi:counter", | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_CUSTOM_MOTION_SPEED): sensor.sensor_schema( | ||||||
|  |             unit_of_measurement="m/s", | ||||||
|  |             device_class=DEVICE_CLASS_SPEED, | ||||||
|  |             accuracy_decimals=2, | ||||||
|  |             icon="mdi:run-fast", | ||||||
|  |         ), | ||||||
|  |         cv.Optional(CONF_CUSTOM_MODE_NUM): sensor.sensor_schema( | ||||||
|  |             icon="mdi:counter", | ||||||
|  |         ), | ||||||
|  |     } | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) | ||||||
|  |     if custompresenceofdetection_config := config.get( | ||||||
|  |         CONF_CUSTOM_PRESENCE_OF_DETECTION | ||||||
|  |     ): | ||||||
|  |         sens = await sensor.new_sensor(custompresenceofdetection_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_custom_presence_of_detection_sensor(sens)) | ||||||
|  |     if movementsigns_config := config.get(CONF_MOVEMENT_SIGNS): | ||||||
|  |         sens = await sensor.new_sensor(movementsigns_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_movement_signs_sensor(sens)) | ||||||
|  |     if custommotiondistance_config := config.get(CONF_CUSTOM_MOTION_DISTANCE): | ||||||
|  |         sens = await sensor.new_sensor(custommotiondistance_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_custom_motion_distance_sensor(sens)) | ||||||
|  |     if customspatialstaticvalue_config := config.get(CONF_CUSTOM_SPATIAL_STATIC_VALUE): | ||||||
|  |         sens = await sensor.new_sensor(customspatialstaticvalue_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_custom_spatial_static_value_sensor(sens)) | ||||||
|  |     if customspatialmotionvalue_config := config.get(CONF_CUSTOM_SPATIAL_MOTION_VALUE): | ||||||
|  |         sens = await sensor.new_sensor(customspatialmotionvalue_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_custom_spatial_motion_value_sensor(sens)) | ||||||
|  |     if custommotionspeed_config := config.get(CONF_CUSTOM_MOTION_SPEED): | ||||||
|  |         sens = await sensor.new_sensor(custommotionspeed_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_custom_motion_speed_sensor(sens)) | ||||||
|  |     if custommodenum_config := config.get(CONF_CUSTOM_MODE_NUM): | ||||||
|  |         sens = await sensor.new_sensor(custommodenum_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_custom_mode_num_sensor(sens)) | ||||||
							
								
								
									
										32
									
								
								esphome/components/seeed_mr24hpc1/switch/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								esphome/components/seeed_mr24hpc1/switch/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components import switch | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import ( | ||||||
|  |     DEVICE_CLASS_SWITCH, | ||||||
|  |     ENTITY_CATEGORY_CONFIG, | ||||||
|  | ) | ||||||
|  | from .. import CONF_MR24HPC1_ID, MR24HPC1Component, mr24hpc1_ns | ||||||
|  |  | ||||||
|  | UnderlyingOpenFuncSwitch = mr24hpc1_ns.class_( | ||||||
|  |     "UnderlyOpenFunctionSwitch", switch.Switch | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | CONF_UNDERLYING_OPEN_FUNCTION = "underlying_open_function" | ||||||
|  |  | ||||||
|  | CONFIG_SCHEMA = { | ||||||
|  |     cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), | ||||||
|  |     cv.Optional(CONF_UNDERLYING_OPEN_FUNCTION): switch.switch_schema( | ||||||
|  |         UnderlyingOpenFuncSwitch, | ||||||
|  |         device_class=DEVICE_CLASS_SWITCH, | ||||||
|  |         entity_category=ENTITY_CATEGORY_CONFIG, | ||||||
|  |         icon="mdi:electric-switch", | ||||||
|  |     ), | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) | ||||||
|  |     if underlying_open_function_config := config.get(CONF_UNDERLYING_OPEN_FUNCTION): | ||||||
|  |         s = await switch.new_switch(underlying_open_function_config) | ||||||
|  |         await cg.register_parented(s, config[CONF_MR24HPC1_ID]) | ||||||
|  |         cg.add(mr24hpc1_component.set_underlying_open_function_switch(s)) | ||||||
| @@ -0,0 +1,12 @@ | |||||||
|  | #include "underlyFuc_switch.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | void UnderlyOpenFunctionSwitch::write_state(bool state) { | ||||||
|  |   this->publish_state(state); | ||||||
|  |   this->parent_->set_underlying_open_function(state); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										18
									
								
								esphome/components/seeed_mr24hpc1/switch/underlyFuc_switch.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								esphome/components/seeed_mr24hpc1/switch/underlyFuc_switch.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/components/switch/switch.h" | ||||||
|  | #include "../seeed_mr24hpc1.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace seeed_mr24hpc1 { | ||||||
|  |  | ||||||
|  | class UnderlyOpenFunctionSwitch : public switch_::Switch, public Parented<MR24HPC1Component> { | ||||||
|  |  public: | ||||||
|  |   UnderlyOpenFunctionSwitch() = default; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   void write_state(bool state) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace seeed_mr24hpc1 | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										74
									
								
								esphome/components/seeed_mr24hpc1/text_sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								esphome/components/seeed_mr24hpc1/text_sensor.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | |||||||
|  | import esphome.codegen as cg | ||||||
|  | from esphome.components import text_sensor | ||||||
|  | import esphome.config_validation as cv | ||||||
|  | from esphome.const import ENTITY_CATEGORY_DIAGNOSTIC | ||||||
|  | from . import CONF_MR24HPC1_ID, MR24HPC1Component | ||||||
|  |  | ||||||
|  | CONF_HEART_BEAT = "heart_beat" | ||||||
|  | CONF_PRODUCT_MODEL = "product_model" | ||||||
|  | CONF_PRODUCT_ID = "product_id" | ||||||
|  | CONF_HARDWARE_MODEL = "hardware_model" | ||||||
|  | CONF_HARDWARE_VERSION = "hardware_version" | ||||||
|  |  | ||||||
|  | CONF_KEEP_AWAY = "keep_away" | ||||||
|  | CONF_MOTION_STATUS = "motion_status" | ||||||
|  |  | ||||||
|  | CONF_CUSTOM_MODE_END = "custom_mode_end" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # The entity category for read only diagnostic values, for example RSSI, uptime or MAC Address | ||||||
|  | CONFIG_SCHEMA = { | ||||||
|  |     cv.GenerateID(CONF_MR24HPC1_ID): cv.use_id(MR24HPC1Component), | ||||||
|  |     cv.Optional(CONF_HEART_BEAT): text_sensor.text_sensor_schema( | ||||||
|  |         entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:connection" | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_PRODUCT_MODEL): text_sensor.text_sensor_schema( | ||||||
|  |         entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:information-outline" | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_PRODUCT_ID): text_sensor.text_sensor_schema( | ||||||
|  |         entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:information-outline" | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_HARDWARE_MODEL): text_sensor.text_sensor_schema( | ||||||
|  |         entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:information-outline" | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_HARDWARE_VERSION): text_sensor.text_sensor_schema( | ||||||
|  |         entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:information-outline" | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_KEEP_AWAY): text_sensor.text_sensor_schema( | ||||||
|  |         entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:walk" | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_MOTION_STATUS): text_sensor.text_sensor_schema( | ||||||
|  |         entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:human-greeting" | ||||||
|  |     ), | ||||||
|  |     cv.Optional(CONF_CUSTOM_MODE_END): text_sensor.text_sensor_schema( | ||||||
|  |         entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon="mdi:account-check" | ||||||
|  |     ), | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | async def to_code(config): | ||||||
|  |     mr24hpc1_component = await cg.get_variable(config[CONF_MR24HPC1_ID]) | ||||||
|  |     if heartbeat_config := config.get(CONF_HEART_BEAT): | ||||||
|  |         sens = await text_sensor.new_text_sensor(heartbeat_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_heartbeat_state_text_sensor(sens)) | ||||||
|  |     if productmodel_config := config.get(CONF_PRODUCT_MODEL): | ||||||
|  |         sens = await text_sensor.new_text_sensor(productmodel_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_product_model_text_sensor(sens)) | ||||||
|  |     if productid_config := config.get(CONF_PRODUCT_ID): | ||||||
|  |         sens = await text_sensor.new_text_sensor(productid_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_product_id_text_sensor(sens)) | ||||||
|  |     if hardwaremodel_config := config.get(CONF_HARDWARE_MODEL): | ||||||
|  |         sens = await text_sensor.new_text_sensor(hardwaremodel_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_hardware_model_text_sensor(sens)) | ||||||
|  |     if firwareversion_config := config.get(CONF_HARDWARE_VERSION): | ||||||
|  |         sens = await text_sensor.new_text_sensor(firwareversion_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_firware_version_text_sensor(sens)) | ||||||
|  |     if keepaway_config := config.get(CONF_KEEP_AWAY): | ||||||
|  |         sens = await text_sensor.new_text_sensor(keepaway_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_keep_away_text_sensor(sens)) | ||||||
|  |     if motionstatus_config := config.get(CONF_MOTION_STATUS): | ||||||
|  |         sens = await text_sensor.new_text_sensor(motionstatus_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_motion_status_text_sensor(sens)) | ||||||
|  |     if custommodeend_config := config.get(CONF_CUSTOM_MODE_END): | ||||||
|  |         sens = await text_sensor.new_text_sensor(custommodeend_config) | ||||||
|  |         cg.add(mr24hpc1_component.set_custom_mode_end_text_sensor(sens)) | ||||||
							
								
								
									
										92
									
								
								tests/components/seeed_mr24hpc1/common.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								tests/components/seeed_mr24hpc1/common.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | |||||||
|  | uart: | ||||||
|  |   - id: seeed_mr24hpc1_uart | ||||||
|  |     tx_pin: ${uart_tx_pin} | ||||||
|  |     rx_pin: ${uart_rx_pin} | ||||||
|  |     baud_rate: 115200 | ||||||
|  |     parity: NONE | ||||||
|  |     stop_bits: 1 | ||||||
|  |  | ||||||
|  | seeed_mr24hpc1: | ||||||
|  |   id: my_seeed_mr24hpc1 | ||||||
|  |   uart_id: seeed_mr24hpc1_uart | ||||||
|  |  | ||||||
|  | sensor: | ||||||
|  |   - platform: seeed_mr24hpc1 | ||||||
|  |     custom_presence_of_detection: | ||||||
|  |       name: "Static Distance" | ||||||
|  |     movement_signs: | ||||||
|  |       name: "Body Movement Parameter" | ||||||
|  |     custom_motion_distance: | ||||||
|  |       name: "Motion Distance" | ||||||
|  |     custom_spatial_static_value: | ||||||
|  |       name: "Existence Energy" | ||||||
|  |     custom_spatial_motion_value: | ||||||
|  |       name: "Motion Energy" | ||||||
|  |     custom_motion_speed: | ||||||
|  |       name: "Motion Speed" | ||||||
|  |     custom_mode_num: | ||||||
|  |       name: "Current Custom Mode" | ||||||
|  |  | ||||||
|  | binary_sensor: | ||||||
|  |   - platform: seeed_mr24hpc1 | ||||||
|  |     has_target: | ||||||
|  |       name: "Presence Information" | ||||||
|  |  | ||||||
|  | switch: | ||||||
|  |   - platform: seeed_mr24hpc1 | ||||||
|  |     underlying_open_function: | ||||||
|  |       name: Underlying Open Function Info Output Switch | ||||||
|  |  | ||||||
|  | text_sensor: | ||||||
|  |   - platform: seeed_mr24hpc1 | ||||||
|  |     heart_beat: | ||||||
|  |       name: "Heartbeat" | ||||||
|  |     product_model: | ||||||
|  |       name: "Product Model" | ||||||
|  |     product_id: | ||||||
|  |       name: "Product ID" | ||||||
|  |     hardware_model: | ||||||
|  |       name: "Hardware Model" | ||||||
|  |     hardware_version: | ||||||
|  |       name: "Hardware Version" | ||||||
|  |     keep_away: | ||||||
|  |       name: "Active Reporting Of Proximity" | ||||||
|  |     motion_status: | ||||||
|  |       name: "Motion Information" | ||||||
|  |     custom_mode_end: | ||||||
|  |       name: "Custom Mode Status" | ||||||
|  |  | ||||||
|  | number: | ||||||
|  |   - platform: seeed_mr24hpc1 | ||||||
|  |     sensitivity: | ||||||
|  |       name: "Sensitivity" | ||||||
|  |     custom_mode: | ||||||
|  |       name: "Custom Mode" | ||||||
|  |     existence_threshold: | ||||||
|  |       name: "Existence Energy Threshold" | ||||||
|  |     motion_threshold: | ||||||
|  |       name: "Motion Energy Threshold" | ||||||
|  |     motion_trigger: | ||||||
|  |       name: "Motion Trigger Time" | ||||||
|  |     motion_to_rest: | ||||||
|  |       name: "Motion To Rest Time" | ||||||
|  |     custom_unman_time: | ||||||
|  |       name: "Time For Entering No Person State (Underlying Open Function)" | ||||||
|  |  | ||||||
|  | select: | ||||||
|  |   - platform: seeed_mr24hpc1 | ||||||
|  |     scene_mode: | ||||||
|  |       name: "Scene" | ||||||
|  |     unman_time: | ||||||
|  |       name: "Time For Entering No Person State (Standard Function)" | ||||||
|  |     existence_boundary: | ||||||
|  |       name: "Existence Boundary" | ||||||
|  |     motion_boundary: | ||||||
|  |       name: "Motion Boundary" | ||||||
|  |  | ||||||
|  | button: | ||||||
|  |   - platform: seeed_mr24hpc1 | ||||||
|  |     restart: | ||||||
|  |       name: "Module Restart" | ||||||
|  |     custom_set_end: | ||||||
|  |       name: "End Of Custom Mode Settings" | ||||||
							
								
								
									
										5
									
								
								tests/components/seeed_mr24hpc1/test.esp32-c3-idf.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/components/seeed_mr24hpc1/test.esp32-c3-idf.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | substitutions: | ||||||
|  |   uart_tx_pin: GPIO5 | ||||||
|  |   uart_rx_pin: GPIO4 | ||||||
|  |  | ||||||
|  | <<: !include common.yaml | ||||||
							
								
								
									
										5
									
								
								tests/components/seeed_mr24hpc1/test.esp32-c3.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tests/components/seeed_mr24hpc1/test.esp32-c3.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | substitutions: | ||||||
|  |   uart_tx_pin: GPIO5 | ||||||
|  |   uart_rx_pin: GPIO4 | ||||||
|  |  | ||||||
|  | <<: !include common.yaml | ||||||
		Reference in New Issue
	
	Block a user