| 
						
					 | 
					 | 
					@@ -18,11 +18,10 @@ namespace esphome {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					namespace ld2450 {
 | 
					 | 
					 | 
					 | 
					namespace ld2450 {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const char *const TAG = "ld2450";
 | 
					 | 
					 | 
					 | 
					static const char *const TAG = "ld2450";
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const char *const NO_MAC = "08:05:04:03:02:01";
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const char *const UNKNOWN_MAC = "unknown";
 | 
					 | 
					 | 
					 | 
					static const char *const UNKNOWN_MAC = "unknown";
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const char *const VERSION_FMT = "%u.%02X.%02X%02X%02X%02X";
 | 
					 | 
					 | 
					 | 
					static const char *const VERSION_FMT = "%u.%02X.%02X%02X%02X%02X";
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					enum BaudRateStructure : uint8_t {
 | 
					 | 
					 | 
					 | 
					enum BaudRate : uint8_t {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  BAUD_RATE_9600 = 1,
 | 
					 | 
					 | 
					 | 
					  BAUD_RATE_9600 = 1,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  BAUD_RATE_19200 = 2,
 | 
					 | 
					 | 
					 | 
					  BAUD_RATE_19200 = 2,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  BAUD_RATE_38400 = 3,
 | 
					 | 
					 | 
					 | 
					  BAUD_RATE_38400 = 3,
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -33,14 +32,13 @@ enum BaudRateStructure : uint8_t {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  BAUD_RATE_460800 = 8
 | 
					 | 
					 | 
					 | 
					  BAUD_RATE_460800 = 8
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Zone type struct
 | 
					 | 
					 | 
					 | 
					enum ZoneType : uint8_t {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					enum ZoneTypeStructure : uint8_t {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  ZONE_DISABLED = 0,
 | 
					 | 
					 | 
					 | 
					  ZONE_DISABLED = 0,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  ZONE_DETECTION = 1,
 | 
					 | 
					 | 
					 | 
					  ZONE_DETECTION = 1,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  ZONE_FILTER = 2,
 | 
					 | 
					 | 
					 | 
					  ZONE_FILTER = 2,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					enum PeriodicDataStructure : uint8_t {
 | 
					 | 
					 | 
					 | 
					enum PeriodicData : uint8_t {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  TARGET_X = 4,
 | 
					 | 
					 | 
					 | 
					  TARGET_X = 4,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  TARGET_Y = 6,
 | 
					 | 
					 | 
					 | 
					  TARGET_Y = 6,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  TARGET_SPEED = 8,
 | 
					 | 
					 | 
					 | 
					  TARGET_SPEED = 8,
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -48,12 +46,12 @@ enum PeriodicDataStructure : uint8_t {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					enum PeriodicDataValue : uint8_t {
 | 
					 | 
					 | 
					 | 
					enum PeriodicDataValue : uint8_t {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  HEAD = 0xAA,
 | 
					 | 
					 | 
					 | 
					  HEADER = 0xAA,
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  END = 0x55,
 | 
					 | 
					 | 
					 | 
					  FOOTER = 0x55,
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  CHECK = 0x00,
 | 
					 | 
					 | 
					 | 
					  CHECK = 0x00,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					enum AckDataStructure : uint8_t {
 | 
					 | 
					 | 
					 | 
					enum AckData : uint8_t {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  COMMAND = 6,
 | 
					 | 
					 | 
					 | 
					  COMMAND = 6,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  COMMAND_STATUS = 7,
 | 
					 | 
					 | 
					 | 
					  COMMAND_STATUS = 7,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -61,11 +59,11 @@ enum AckDataStructure : uint8_t {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Memory-efficient lookup tables
 | 
					 | 
					 | 
					 | 
					// Memory-efficient lookup tables
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					struct StringToUint8 {
 | 
					 | 
					 | 
					 | 
					struct StringToUint8 {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  const char *str;
 | 
					 | 
					 | 
					 | 
					  const char *str;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t value;
 | 
					 | 
					 | 
					 | 
					  const uint8_t value;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					struct Uint8ToString {
 | 
					 | 
					 | 
					 | 
					struct Uint8ToString {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t value;
 | 
					 | 
					 | 
					 | 
					  const uint8_t value;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  const char *str;
 | 
					 | 
					 | 
					 | 
					  const char *str;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -75,6 +73,13 @@ constexpr StringToUint8 BAUD_RATES_BY_STR[] = {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    {"256000", BAUD_RATE_256000}, {"460800", BAUD_RATE_460800},
 | 
					 | 
					 | 
					 | 
					    {"256000", BAUD_RATE_256000}, {"460800", BAUD_RATE_460800},
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					constexpr Uint8ToString DIRECTION_BY_UINT[] = {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    {DIRECTION_APPROACHING, "Approaching"},
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    {DIRECTION_MOVING_AWAY, "Moving away"},
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    {DIRECTION_STATIONARY, "Stationary"},
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    {DIRECTION_NA, "NA"},
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					constexpr Uint8ToString ZONE_TYPE_BY_UINT[] = {
 | 
					 | 
					 | 
					 | 
					constexpr Uint8ToString ZONE_TYPE_BY_UINT[] = {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    {ZONE_DISABLED, "Disabled"},
 | 
					 | 
					 | 
					 | 
					    {ZONE_DISABLED, "Disabled"},
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    {ZONE_DETECTION, "Detection"},
 | 
					 | 
					 | 
					 | 
					    {ZONE_DETECTION, "Detection"},
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -104,28 +109,35 @@ template<size_t N> const char *find_str(const Uint8ToString (&arr)[N], uint8_t v
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return "";  // Not found
 | 
					 | 
					 | 
					 | 
					  return "";  // Not found
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// LD2450 serial command header & footer
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_FRAME_HEADER[4] = {0xFD, 0xFC, 0xFB, 0xFA};
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_FRAME_END[4] = {0x04, 0x03, 0x02, 0x01};
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// LD2450 UART Serial Commands
 | 
					 | 
					 | 
					 | 
					// LD2450 UART Serial Commands
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_ENABLE_CONF = 0xFF;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_ENABLE_CONF = 0xFF;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_DISABLE_CONF = 0xFE;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_DISABLE_CONF = 0xFE;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_VERSION = 0xA0;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_QUERY_VERSION = 0xA0;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_MAC = 0xA5;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_QUERY_MAC_ADDRESS = 0xA5;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_RESET = 0xA2;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_RESET = 0xA2;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_RESTART = 0xA3;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_RESTART = 0xA3;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_BLUETOOTH = 0xA4;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_BLUETOOTH = 0xA4;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_SINGLE_TARGET_MODE = 0x80;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_SINGLE_TARGET_MODE = 0x80;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_MULTI_TARGET_MODE = 0x90;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_MULTI_TARGET_MODE = 0x90;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_QUERY_TARGET_MODE = 0x91;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_QUERY_TARGET_MODE = 0x91;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_SET_BAUD_RATE = 0xA1;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_SET_BAUD_RATE = 0xA1;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_QUERY_ZONE = 0xC1;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_QUERY_ZONE = 0xC1;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static const uint8_t CMD_SET_ZONE = 0xC2;
 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_SET_ZONE = 0xC2;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					// Header & Footer size
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t HEADER_FOOTER_SIZE = 4;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					// Command Header & Footer
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_FRAME_HEADER[HEADER_FOOTER_SIZE] = {0xFD, 0xFC, 0xFB, 0xFA};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t CMD_FRAME_FOOTER[HEADER_FOOTER_SIZE] = {0x04, 0x03, 0x02, 0x01};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					// Data Header & Footer
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t DATA_FRAME_HEADER[HEADER_FOOTER_SIZE] = {0xAA, 0xFF, 0x03, 0x00};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t DATA_FRAME_FOOTER[2] = {0x55, 0xCC};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					// MAC address the module uses when Bluetooth is disabled
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static constexpr uint8_t NO_MAC[] = {0x08, 0x05, 0x04, 0x03, 0x02, 0x01};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static inline uint16_t convert_seconds_to_ms(uint16_t value) { return value * 1000; };
 | 
					 | 
					 | 
					 | 
					static inline uint16_t convert_seconds_to_ms(uint16_t value) { return value * 1000; };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static inline void convert_int_values_to_hex(const int *values, uint8_t *bytes) {
 | 
					 | 
					 | 
					 | 
					static inline void convert_int_values_to_hex(const int *values, uint8_t *bytes) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (int i = 0; i < 4; i++) {
 | 
					 | 
					 | 
					 | 
					  for (uint8_t i = 0; i < 4; i++) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    uint16_t val = values[i] & 0xFFFF;
 | 
					 | 
					 | 
					 | 
					    uint16_t val = values[i] & 0xFFFF;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    bytes[i * 2] = val & 0xFF;             // Store low byte first (little-endian)
 | 
					 | 
					 | 
					 | 
					    bytes[i * 2] = val & 0xFF;             // Store low byte first (little-endian)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    bytes[i * 2 + 1] = (val >> 8) & 0xFF;  // Store high byte second
 | 
					 | 
					 | 
					 | 
					    bytes[i * 2 + 1] = (val >> 8) & 0xFF;  // Store high byte second
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -166,18 +178,13 @@ static inline float calculate_angle(float base, float hypotenuse) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return angle_degrees;
 | 
					 | 
					 | 
					 | 
					  return angle_degrees;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static inline std::string get_direction(int16_t speed) {
 | 
					 | 
					 | 
					 | 
					static bool validate_header_footer(const uint8_t *header_footer, const uint8_t *buffer) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  static const char *const APPROACHING = "Approaching";
 | 
					 | 
					 | 
					 | 
					  for (uint8_t i = 0; i < HEADER_FOOTER_SIZE; i++) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  static const char *const MOVING_AWAY = "Moving away";
 | 
					 | 
					 | 
					 | 
					    if (header_footer[i] != buffer[i]) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  static const char *const STATIONARY = "Stationary";
 | 
					 | 
					 | 
					 | 
					      return false;  // Mismatch in header/footer
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (speed > 0) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return MOVING_AWAY;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (speed < 0) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return APPROACHING;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return STATIONARY;
 | 
					 | 
					 | 
					 | 
					  return true;  // Valid header/footer
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::setup() {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::setup() {
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -192,84 +199,93 @@ void LD2450Component::setup() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::dump_config() {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::dump_config() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  ESP_LOGCONFIG(TAG, "LD2450:");
 | 
					 | 
					 | 
					 | 
					  std::string mac_str =
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      mac_address_is_valid(this->mac_address_) ? format_mac_address_pretty(this->mac_address_) : UNKNOWN_MAC;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  std::string version = str_sprintf(VERSION_FMT, this->version_[1], this->version_[0], this->version_[5],
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                                    this->version_[4], this->version_[3], this->version_[2]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  ESP_LOGCONFIG(TAG,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                "LD2450:\n"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                "  Firmware version: %s\n"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                "  MAC address: %s\n"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                "  Throttle: %u ms",
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                version.c_str(), mac_str.c_str(), this->throttle_);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_BINARY_SENSOR
 | 
					 | 
					 | 
					 | 
					#ifdef USE_BINARY_SENSOR
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_BINARY_SENSOR("  ", "TargetBinarySensor", this->target_binary_sensor_);
 | 
					 | 
					 | 
					 | 
					  ESP_LOGCONFIG(TAG, "Binary Sensors:");
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_BINARY_SENSOR("  ", "MovingTargetBinarySensor", this->moving_target_binary_sensor_);
 | 
					 | 
					 | 
					 | 
					  LOG_BINARY_SENSOR("  ", "MovingTarget", this->moving_target_binary_sensor_);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_BINARY_SENSOR("  ", "StillTargetBinarySensor", this->still_target_binary_sensor_);
 | 
					 | 
					 | 
					 | 
					  LOG_BINARY_SENSOR("  ", "StillTarget", this->still_target_binary_sensor_);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					  LOG_BINARY_SENSOR("  ", "Target", this->target_binary_sensor_);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_SWITCH
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_SWITCH("  ", "BluetoothSwitch", this->bluetooth_switch_);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_SWITCH("  ", "MultiTargetSwitch", this->multi_target_switch_);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_BUTTON
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_BUTTON("  ", "ResetButton", this->reset_button_);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_BUTTON("  ", "RestartButton", this->restart_button_);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_SENSOR
 | 
					 | 
					 | 
					 | 
					#ifdef USE_SENSOR
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_SENSOR("  ", "TargetCountSensor", this->target_count_sensor_);
 | 
					 | 
					 | 
					 | 
					  ESP_LOGCONFIG(TAG, "Sensors:");
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_SENSOR("  ", "StillTargetCountSensor", this->still_target_count_sensor_);
 | 
					 | 
					 | 
					 | 
					  LOG_SENSOR("  ", "MovingTargetCount", this->moving_target_count_sensor_);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_SENSOR("  ", "MovingTargetCountSensor", this->moving_target_count_sensor_);
 | 
					 | 
					 | 
					 | 
					  LOG_SENSOR("  ", "StillTargetCount", this->still_target_count_sensor_);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  LOG_SENSOR("  ", "TargetCount", this->target_count_sensor_);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_x_sensors_) {
 | 
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_x_sensors_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "NthTargetXSensor", s);
 | 
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "TargetX", s);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_y_sensors_) {
 | 
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_y_sensors_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "NthTargetYSensor", s);
 | 
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "TargetY", s);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_speed_sensors_) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "NthTargetSpeedSensor", s);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_angle_sensors_) {
 | 
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_angle_sensors_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "NthTargetAngleSensor", s);
 | 
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "TargetAngle", s);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_distance_sensors_) {
 | 
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_distance_sensors_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "NthTargetDistanceSensor", s);
 | 
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "TargetDistance", s);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_resolution_sensors_) {
 | 
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_resolution_sensors_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "NthTargetResolutionSensor", s);
 | 
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "TargetResolution", s);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->move_speed_sensors_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "TargetSpeed", s);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->zone_target_count_sensors_) {
 | 
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->zone_target_count_sensors_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "NthZoneTargetCountSensor", s);
 | 
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "ZoneTargetCount", s);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->zone_still_target_count_sensors_) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "NthZoneStillTargetCountSensor", s);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->zone_moving_target_count_sensors_) {
 | 
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->zone_moving_target_count_sensors_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "NthZoneMovingTargetCountSensor", s);
 | 
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "ZoneMovingTargetCount", s);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  for (sensor::Sensor *s : this->zone_still_target_count_sensors_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    LOG_SENSOR("  ", "ZoneStillTargetCount", s);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_TEXT_SENSOR
 | 
					 | 
					 | 
					 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_TEXT_SENSOR("  ", "VersionTextSensor", this->version_text_sensor_);
 | 
					 | 
					 | 
					 | 
					  ESP_LOGCONFIG(TAG, "Text Sensors:");
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_TEXT_SENSOR("  ", "MacTextSensor", this->mac_text_sensor_);
 | 
					 | 
					 | 
					 | 
					  LOG_TEXT_SENSOR("  ", "Version", this->version_text_sensor_);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  LOG_TEXT_SENSOR("  ", "Mac", this->mac_text_sensor_);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (text_sensor::TextSensor *s : this->direction_text_sensors_) {
 | 
					 | 
					 | 
					 | 
					  for (text_sensor::TextSensor *s : this->direction_text_sensors_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_TEXT_SENSOR("  ", "NthDirectionTextSensor", s);
 | 
					 | 
					 | 
					 | 
					    LOG_TEXT_SENSOR("  ", "Direction", s);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_NUMBER
 | 
					 | 
					 | 
					 | 
					#ifdef USE_NUMBER
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  ESP_LOGCONFIG(TAG, "Numbers:");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  LOG_NUMBER("  ", "PresenceTimeout", this->presence_timeout_number_);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (auto n : this->zone_numbers_) {
 | 
					 | 
					 | 
					 | 
					  for (auto n : this->zone_numbers_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_NUMBER("  ", "ZoneX1Number", n.x1);
 | 
					 | 
					 | 
					 | 
					    LOG_NUMBER("  ", "ZoneX1", n.x1);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_NUMBER("  ", "ZoneY1Number", n.y1);
 | 
					 | 
					 | 
					 | 
					    LOG_NUMBER("  ", "ZoneY1", n.y1);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_NUMBER("  ", "ZoneX2Number", n.x2);
 | 
					 | 
					 | 
					 | 
					    LOG_NUMBER("  ", "ZoneX2", n.x2);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    LOG_NUMBER("  ", "ZoneY2Number", n.y2);
 | 
					 | 
					 | 
					 | 
					    LOG_NUMBER("  ", "ZoneY2", n.y2);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_SELECT
 | 
					 | 
					 | 
					 | 
					#ifdef USE_SELECT
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_SELECT("  ", "BaudRateSelect", this->baud_rate_select_);
 | 
					 | 
					 | 
					 | 
					  ESP_LOGCONFIG(TAG, "Selects:");
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_SELECT("  ", "ZoneTypeSelect", this->zone_type_select_);
 | 
					 | 
					 | 
					 | 
					  LOG_SELECT("  ", "BaudRate", this->baud_rate_select_);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  LOG_SELECT("  ", "ZoneType", this->zone_type_select_);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_NUMBER
 | 
					 | 
					 | 
					 | 
					#ifdef USE_SWITCH
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  LOG_NUMBER("  ", "PresenceTimeoutNumber", this->presence_timeout_number_);
 | 
					 | 
					 | 
					 | 
					  ESP_LOGCONFIG(TAG, "Switches:");
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  LOG_SWITCH("  ", "Bluetooth", this->bluetooth_switch_);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  LOG_SWITCH("  ", "MultiTarget", this->multi_target_switch_);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#ifdef USE_BUTTON
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  ESP_LOGCONFIG(TAG, "Buttons:");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  LOG_BUTTON("  ", "FactoryReset", this->factory_reset_button_);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  LOG_BUTTON("  ", "Restart", this->restart_button_);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  ESP_LOGCONFIG(TAG,
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                "  Throttle: %ums\n"
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                "  MAC Address: %s\n"
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                "  Firmware version: %s",
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                this->throttle_, this->mac_ == NO_MAC ? UNKNOWN_MAC : this->mac_.c_str(), this->version_.c_str());
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::loop() {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::loop() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  while (this->available()) {
 | 
					 | 
					 | 
					 | 
					  while (this->available()) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->readline_(read(), this->buffer_data_, MAX_LINE_LENGTH);
 | 
					 | 
					 | 
					 | 
					    this->readline_(this->read());
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -304,7 +320,7 @@ void LD2450Component::set_radar_zone(int32_t zone_type, int32_t zone1_x1, int32_
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->zone_type_ = zone_type;
 | 
					 | 
					 | 
					 | 
					  this->zone_type_ = zone_type;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int zone_parameters[12] = {zone1_x1, zone1_y1, zone1_x2, zone1_y2, zone2_x1, zone2_y1,
 | 
					 | 
					 | 
					 | 
					  int zone_parameters[12] = {zone1_x1, zone1_y1, zone1_x2, zone1_y2, zone2_x1, zone2_y1,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                             zone2_x2, zone2_y2, zone3_x1, zone3_y1, zone3_x2, zone3_y2};
 | 
					 | 
					 | 
					 | 
					                             zone2_x2, zone2_y2, zone3_x1, zone3_y1, zone3_x2, zone3_y2};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (int i = 0; i < MAX_ZONES; i++) {
 | 
					 | 
					 | 
					 | 
					  for (uint8_t i = 0; i < MAX_ZONES; i++) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->zone_config_[i].x1 = zone_parameters[i * 4];
 | 
					 | 
					 | 
					 | 
					    this->zone_config_[i].x1 = zone_parameters[i * 4];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->zone_config_[i].y1 = zone_parameters[i * 4 + 1];
 | 
					 | 
					 | 
					 | 
					    this->zone_config_[i].y1 = zone_parameters[i * 4 + 1];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->zone_config_[i].x2 = zone_parameters[i * 4 + 2];
 | 
					 | 
					 | 
					 | 
					    this->zone_config_[i].x2 = zone_parameters[i * 4 + 2];
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -318,15 +334,15 @@ void LD2450Component::send_set_zone_command_() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t cmd_value[26] = {};
 | 
					 | 
					 | 
					 | 
					  uint8_t cmd_value[26] = {};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t zone_type_bytes[2] = {static_cast<uint8_t>(this->zone_type_), 0x00};
 | 
					 | 
					 | 
					 | 
					  uint8_t zone_type_bytes[2] = {static_cast<uint8_t>(this->zone_type_), 0x00};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t area_config[24] = {};
 | 
					 | 
					 | 
					 | 
					  uint8_t area_config[24] = {};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (int i = 0; i < MAX_ZONES; i++) {
 | 
					 | 
					 | 
					 | 
					  for (uint8_t i = 0; i < MAX_ZONES; i++) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    int values[4] = {this->zone_config_[i].x1, this->zone_config_[i].y1, this->zone_config_[i].x2,
 | 
					 | 
					 | 
					 | 
					    int values[4] = {this->zone_config_[i].x1, this->zone_config_[i].y1, this->zone_config_[i].x2,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                     this->zone_config_[i].y2};
 | 
					 | 
					 | 
					 | 
					                     this->zone_config_[i].y2};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ld2450::convert_int_values_to_hex(values, area_config + (i * 8));
 | 
					 | 
					 | 
					 | 
					    ld2450::convert_int_values_to_hex(values, area_config + (i * 8));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  std::memcpy(cmd_value, zone_type_bytes, 2);
 | 
					 | 
					 | 
					 | 
					  std::memcpy(cmd_value, zone_type_bytes, sizeof(zone_type_bytes));
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  std::memcpy(cmd_value + 2, area_config, 24);
 | 
					 | 
					 | 
					 | 
					  std::memcpy(cmd_value + 2, area_config, sizeof(area_config));
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->set_config_mode_(true);
 | 
					 | 
					 | 
					 | 
					  this->set_config_mode_(true);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->send_command_(CMD_SET_ZONE, cmd_value, 26);
 | 
					 | 
					 | 
					 | 
					  this->send_command_(CMD_SET_ZONE, cmd_value, sizeof(cmd_value));
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->set_config_mode_(false);
 | 
					 | 
					 | 
					 | 
					  this->set_config_mode_(false);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -342,14 +358,14 @@ bool LD2450Component::get_timeout_status_(uint32_t check_millis) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Extract, store and publish zone details LD2450 buffer
 | 
					 | 
					 | 
					 | 
					// Extract, store and publish zone details LD2450 buffer
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::process_zone_(uint8_t *buffer) {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::process_zone_() {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t index, start;
 | 
					 | 
					 | 
					 | 
					  uint8_t index, start;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  for (index = 0; index < MAX_ZONES; index++) {
 | 
					 | 
					 | 
					 | 
					  for (index = 0; index < MAX_ZONES; index++) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    start = 12 + index * 8;
 | 
					 | 
					 | 
					 | 
					    start = 12 + index * 8;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->zone_config_[index].x1 = ld2450::hex_to_signed_int(buffer, start);
 | 
					 | 
					 | 
					 | 
					    this->zone_config_[index].x1 = ld2450::hex_to_signed_int(this->buffer_data_, start);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->zone_config_[index].y1 = ld2450::hex_to_signed_int(buffer, start + 2);
 | 
					 | 
					 | 
					 | 
					    this->zone_config_[index].y1 = ld2450::hex_to_signed_int(this->buffer_data_, start + 2);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->zone_config_[index].x2 = ld2450::hex_to_signed_int(buffer, start + 4);
 | 
					 | 
					 | 
					 | 
					    this->zone_config_[index].x2 = ld2450::hex_to_signed_int(this->buffer_data_, start + 4);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->zone_config_[index].y2 = ld2450::hex_to_signed_int(buffer, start + 6);
 | 
					 | 
					 | 
					 | 
					    this->zone_config_[index].y2 = ld2450::hex_to_signed_int(this->buffer_data_, start + 6);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_NUMBER
 | 
					 | 
					 | 
					 | 
					#ifdef USE_NUMBER
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // only one null check as all coordinates are required for a single zone
 | 
					 | 
					 | 
					 | 
					    // only one null check as all coordinates are required for a single zone
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (this->zone_numbers_[index].x1 != nullptr) {
 | 
					 | 
					 | 
					 | 
					    if (this->zone_numbers_[index].x1 != nullptr) {
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -395,27 +411,25 @@ void LD2450Component::restart_and_read_all_info() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Send command with values to LD2450
 | 
					 | 
					 | 
					 | 
					// Send command with values to LD2450
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::send_command_(uint8_t command, const uint8_t *command_value, uint8_t command_value_len) {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::send_command_(uint8_t command, const uint8_t *command_value, uint8_t command_value_len) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  ESP_LOGV(TAG, "Sending command %02X", command);
 | 
					 | 
					 | 
					 | 
					  ESP_LOGV(TAG, "Sending COMMAND %02X", command);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // frame header
 | 
					 | 
					 | 
					 | 
					  // frame header bytes
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->write_array(CMD_FRAME_HEADER, 4);
 | 
					 | 
					 | 
					 | 
					  this->write_array(CMD_FRAME_HEADER, sizeof(CMD_FRAME_HEADER));
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // length bytes
 | 
					 | 
					 | 
					 | 
					  // length bytes
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int len = 2;
 | 
					 | 
					 | 
					 | 
					  uint8_t len = 2;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (command_value != nullptr) {
 | 
					 | 
					 | 
					 | 
					  if (command_value != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    len += command_value_len;
 | 
					 | 
					 | 
					 | 
					    len += command_value_len;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->write_byte(lowbyte(len));
 | 
					 | 
					 | 
					 | 
					  uint8_t len_cmd[] = {lowbyte(len), highbyte(len), command, 0x00};
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->write_byte(highbyte(len));
 | 
					 | 
					 | 
					 | 
					  this->write_array(len_cmd, sizeof(len_cmd));
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // command
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->write_byte(lowbyte(command));
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->write_byte(highbyte(command));
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // command value bytes
 | 
					 | 
					 | 
					 | 
					  // command value bytes
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (command_value != nullptr) {
 | 
					 | 
					 | 
					 | 
					  if (command_value != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    for (int i = 0; i < command_value_len; i++) {
 | 
					 | 
					 | 
					 | 
					    for (uint8_t i = 0; i < command_value_len; i++) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      this->write_byte(command_value[i]);
 | 
					 | 
					 | 
					 | 
					      this->write_byte(command_value[i]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // footer
 | 
					 | 
					 | 
					 | 
					  // frame footer bytes
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->write_array(CMD_FRAME_END, 4);
 | 
					 | 
					 | 
					 | 
					  this->write_array(CMD_FRAME_FOOTER, sizeof(CMD_FRAME_FOOTER));
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // FIXME to remove
 | 
					 | 
					 | 
					 | 
					  // FIXME to remove
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  delay(50);  // NOLINT
 | 
					 | 
					 | 
					 | 
					  delay(50);  // NOLINT
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -423,26 +437,23 @@ void LD2450Component::send_command_(uint8_t command, const uint8_t *command_valu
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// LD2450 Radar data message:
 | 
					 | 
					 | 
					 | 
					// LD2450 Radar data message:
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					//  [AA FF 03 00] [0E 03 B1 86 10 00 40 01] [00 00 00 00 00 00 00 00] [00 00 00 00 00 00 00 00] [55 CC]
 | 
					 | 
					 | 
					 | 
					//  [AA FF 03 00] [0E 03 B1 86 10 00 40 01] [00 00 00 00 00 00 00 00] [00 00 00 00 00 00 00 00] [55 CC]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					//   Header       Target 1                  Target 2                  Target 3                  End
 | 
					 | 
					 | 
					 | 
					//   Header       Target 1                  Target 2                  Target 3                  End
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::handle_periodic_data_() {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // Early throttle check - moved before any processing to save CPU cycles
 | 
					 | 
					 | 
					 | 
					  // Early throttle check - moved before any processing to save CPU cycles
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (App.get_loop_component_start_time() - this->last_periodic_millis_ < this->throttle_) {
 | 
					 | 
					 | 
					 | 
					  if (App.get_loop_component_start_time() - this->last_periodic_millis_ < this->throttle_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGV(TAG, "Throttling: %d", this->throttle_);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return;
 | 
					 | 
					 | 
					 | 
					    return;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (len < 29) {  // header (4 bytes) + 8 x 3 target data + footer (2 bytes)
 | 
					 | 
					 | 
					 | 
					  if (this->buffer_pos_ < 29) {  // header (4 bytes) + 8 x 3 target data + footer (2 bytes)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Invalid message length");
 | 
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Invalid length");
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return;
 | 
					 | 
					 | 
					 | 
					    return;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (buffer[0] != 0xAA || buffer[1] != 0xFF || buffer[2] != 0x03 || buffer[3] != 0x00) {  // header
 | 
					 | 
					 | 
					 | 
					  if (!ld2450::validate_header_footer(DATA_FRAME_HEADER, this->buffer_data_) ||
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Invalid message header");
 | 
					 | 
					 | 
					 | 
					      this->buffer_data_[this->buffer_pos_ - 2] != DATA_FRAME_FOOTER[0] ||
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      this->buffer_data_[this->buffer_pos_ - 1] != DATA_FRAME_FOOTER[1]) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Invalid header/footer");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return;
 | 
					 | 
					 | 
					 | 
					    return;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (buffer[len - 2] != 0x55 || buffer[len - 1] != 0xCC) {  // footer
 | 
					 | 
					 | 
					 | 
					  // Save the timestamp after validating the frame so, if invalid, we'll take the next frame immediately
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Invalid message footer");
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->last_periodic_millis_ = App.get_loop_component_start_time();
 | 
					 | 
					 | 
					 | 
					  this->last_periodic_millis_ = App.get_loop_component_start_time();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int16_t target_count = 0;
 | 
					 | 
					 | 
					 | 
					  int16_t target_count = 0;
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -450,13 +461,13 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int16_t moving_target_count = 0;
 | 
					 | 
					 | 
					 | 
					  int16_t moving_target_count = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int16_t start = 0;
 | 
					 | 
					 | 
					 | 
					  int16_t start = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int16_t val = 0;
 | 
					 | 
					 | 
					 | 
					  int16_t val = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t index = 0;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int16_t tx = 0;
 | 
					 | 
					 | 
					 | 
					  int16_t tx = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int16_t ty = 0;
 | 
					 | 
					 | 
					 | 
					  int16_t ty = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int16_t td = 0;
 | 
					 | 
					 | 
					 | 
					  int16_t td = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int16_t ts = 0;
 | 
					 | 
					 | 
					 | 
					  int16_t ts = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  int16_t angle = 0;
 | 
					 | 
					 | 
					 | 
					  int16_t angle = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  std::string direction{};
 | 
					 | 
					 | 
					 | 
					  uint8_t index = 0;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  Direction direction{DIRECTION_UNDEFINED};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  bool is_moving = false;
 | 
					 | 
					 | 
					 | 
					  bool is_moving = false;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#if defined(USE_BINARY_SENSOR) || defined(USE_SENSOR) || defined(USE_TEXT_SENSOR)
 | 
					 | 
					 | 
					 | 
					#if defined(USE_BINARY_SENSOR) || defined(USE_SENSOR) || defined(USE_TEXT_SENSOR)
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -468,7 +479,7 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    is_moving = false;
 | 
					 | 
					 | 
					 | 
					    is_moving = false;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sensor::Sensor *sx = this->move_x_sensors_[index];
 | 
					 | 
					 | 
					 | 
					    sensor::Sensor *sx = this->move_x_sensors_[index];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (sx != nullptr) {
 | 
					 | 
					 | 
					 | 
					    if (sx != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      val = ld2450::decode_coordinate(buffer[start], buffer[start + 1]);
 | 
					 | 
					 | 
					 | 
					      val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      tx = val;
 | 
					 | 
					 | 
					 | 
					      tx = val;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->cached_target_data_[index].x != val) {
 | 
					 | 
					 | 
					 | 
					      if (this->cached_target_data_[index].x != val) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        sx->publish_state(val);
 | 
					 | 
					 | 
					 | 
					        sx->publish_state(val);
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -479,7 +490,7 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    start = TARGET_Y + index * 8;
 | 
					 | 
					 | 
					 | 
					    start = TARGET_Y + index * 8;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sensor::Sensor *sy = this->move_y_sensors_[index];
 | 
					 | 
					 | 
					 | 
					    sensor::Sensor *sy = this->move_y_sensors_[index];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (sy != nullptr) {
 | 
					 | 
					 | 
					 | 
					    if (sy != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      val = ld2450::decode_coordinate(buffer[start], buffer[start + 1]);
 | 
					 | 
					 | 
					 | 
					      val = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ty = val;
 | 
					 | 
					 | 
					 | 
					      ty = val;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->cached_target_data_[index].y != val) {
 | 
					 | 
					 | 
					 | 
					      if (this->cached_target_data_[index].y != val) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        sy->publish_state(val);
 | 
					 | 
					 | 
					 | 
					        sy->publish_state(val);
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -490,7 +501,7 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    start = TARGET_RESOLUTION + index * 8;
 | 
					 | 
					 | 
					 | 
					    start = TARGET_RESOLUTION + index * 8;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sensor::Sensor *sr = this->move_resolution_sensors_[index];
 | 
					 | 
					 | 
					 | 
					    sensor::Sensor *sr = this->move_resolution_sensors_[index];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (sr != nullptr) {
 | 
					 | 
					 | 
					 | 
					    if (sr != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      val = (buffer[start + 1] << 8) | buffer[start];
 | 
					 | 
					 | 
					 | 
					      val = (this->buffer_data_[start + 1] << 8) | this->buffer_data_[start];
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->cached_target_data_[index].resolution != val) {
 | 
					 | 
					 | 
					 | 
					      if (this->cached_target_data_[index].resolution != val) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        sr->publish_state(val);
 | 
					 | 
					 | 
					 | 
					        sr->publish_state(val);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this->cached_target_data_[index].resolution = val;
 | 
					 | 
					 | 
					 | 
					        this->cached_target_data_[index].resolution = val;
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -499,7 +510,7 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // SPEED
 | 
					 | 
					 | 
					 | 
					    // SPEED
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    start = TARGET_SPEED + index * 8;
 | 
					 | 
					 | 
					 | 
					    start = TARGET_SPEED + index * 8;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    val = ld2450::decode_speed(buffer[start], buffer[start + 1]);
 | 
					 | 
					 | 
					 | 
					    val = ld2450::decode_speed(this->buffer_data_[start], this->buffer_data_[start + 1]);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ts = val;
 | 
					 | 
					 | 
					 | 
					    ts = val;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (val) {
 | 
					 | 
					 | 
					 | 
					    if (val) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      is_moving = true;
 | 
					 | 
					 | 
					 | 
					      is_moving = true;
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -532,7 +543,7 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // ANGLE
 | 
					 | 
					 | 
					 | 
					    // ANGLE
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    angle = calculate_angle(static_cast<float>(ty), static_cast<float>(td));
 | 
					 | 
					 | 
					 | 
					    angle = ld2450::calculate_angle(static_cast<float>(ty), static_cast<float>(td));
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (tx > 0) {
 | 
					 | 
					 | 
					 | 
					    if (tx > 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      angle = angle * -1;
 | 
					 | 
					 | 
					 | 
					      angle = angle * -1;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -547,14 +558,19 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_TEXT_SENSOR
 | 
					 | 
					 | 
					 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // DIRECTION
 | 
					 | 
					 | 
					 | 
					    // DIRECTION
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    direction = get_direction(ts);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (td == 0) {
 | 
					 | 
					 | 
					 | 
					    if (td == 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      direction = "NA";
 | 
					 | 
					 | 
					 | 
					      direction = DIRECTION_NA;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } else if (ts > 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      direction = DIRECTION_MOVING_AWAY;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } else if (ts < 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      direction = DIRECTION_APPROACHING;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      direction = DIRECTION_STATIONARY;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    text_sensor::TextSensor *tsd = this->direction_text_sensors_[index];
 | 
					 | 
					 | 
					 | 
					    text_sensor::TextSensor *tsd = this->direction_text_sensors_[index];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (tsd != nullptr) {
 | 
					 | 
					 | 
					 | 
					    if (tsd != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->cached_target_data_[index].direction != direction) {
 | 
					 | 
					 | 
					 | 
					      if (this->cached_target_data_[index].direction != direction) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        tsd->publish_state(direction);
 | 
					 | 
					 | 
					 | 
					        tsd->publish_state(find_str(ld2450::DIRECTION_BY_UINT, direction));
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this->cached_target_data_[index].direction = direction;
 | 
					 | 
					 | 
					 | 
					        this->cached_target_data_[index].direction = direction;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -678,117 +694,139 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
 | 
					 | 
					 | 
					 | 
					bool LD2450Component::handle_ack_data_() {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  ESP_LOGV(TAG, "Handling ack data for command %02X", buffer[COMMAND]);
 | 
					 | 
					 | 
					 | 
					  ESP_LOGV(TAG, "Handling ACK DATA for COMMAND %02X", this->buffer_data_[COMMAND]);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (len < 10) {
 | 
					 | 
					 | 
					 | 
					  if (this->buffer_pos_ < 10) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Invalid ack length");
 | 
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Invalid length");
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return true;
 | 
					 | 
					 | 
					 | 
					    return true;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (buffer[0] != 0xFD || buffer[1] != 0xFC || buffer[2] != 0xFB || buffer[3] != 0xFA) {  // frame header
 | 
					 | 
					 | 
					 | 
					  if (!ld2450::validate_header_footer(CMD_FRAME_HEADER, this->buffer_data_)) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Invalid ack header (command %02X)", buffer[COMMAND]);
 | 
					 | 
					 | 
					 | 
					    ESP_LOGW(TAG, "Invalid header: %s", format_hex_pretty(this->buffer_data_, HEADER_FOOTER_SIZE).c_str());
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return true;
 | 
					 | 
					 | 
					 | 
					    return true;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (buffer[COMMAND_STATUS] != 0x01) {
 | 
					 | 
					 | 
					 | 
					  if (this->buffer_data_[COMMAND_STATUS] != 0x01) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Invalid ack status");
 | 
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Invalid status");
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return true;
 | 
					 | 
					 | 
					 | 
					    return true;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (buffer[8] || buffer[9]) {
 | 
					 | 
					 | 
					 | 
					  if (this->buffer_data_[8] || this->buffer_data_[9]) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGE(TAG, "Last buffer was %u, %u", buffer[8], buffer[9]);
 | 
					 | 
					 | 
					 | 
					    ESP_LOGW(TAG, "Invalid command: %02X, %02X", this->buffer_data_[8], this->buffer_data_[9]);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return true;
 | 
					 | 
					 | 
					 | 
					    return true;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  switch (buffer[COMMAND]) {
 | 
					 | 
					 | 
					 | 
					  switch (this->buffer_data_[COMMAND]) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_ENABLE_CONF):
 | 
					 | 
					 | 
					 | 
					    case CMD_ENABLE_CONF:
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Enable conf command");
 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Enable conf");
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_DISABLE_CONF):
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Disable conf command");
 | 
					 | 
					 | 
					 | 
					    case CMD_DISABLE_CONF:
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Disabled conf");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_SET_BAUD_RATE):
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Baud rate change command");
 | 
					 | 
					 | 
					 | 
					    case CMD_SET_BAUD_RATE:
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Baud rate change");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_SELECT
 | 
					 | 
					 | 
					 | 
					#ifdef USE_SELECT
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->baud_rate_select_ != nullptr) {
 | 
					 | 
					 | 
					 | 
					      if (this->baud_rate_select_ != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ESP_LOGV(TAG, "Change baud rate to %s", this->baud_rate_select_->state.c_str());
 | 
					 | 
					 | 
					 | 
					        ESP_LOGE(TAG, "Change baud rate to %s and reinstall", this->baud_rate_select_->state.c_str());
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_VERSION):
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      this->version_ = str_sprintf(VERSION_FMT, buffer[13], buffer[12], buffer[17], buffer[16], buffer[15], buffer[14]);
 | 
					 | 
					 | 
					 | 
					    case CMD_QUERY_VERSION: {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Firmware version: %s", this->version_.c_str());
 | 
					 | 
					 | 
					 | 
					      std::memcpy(this->version_, &this->buffer_data_[12], sizeof(this->version_));
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      std::string version = str_sprintf(VERSION_FMT, this->version_[1], this->version_[0], this->version_[5],
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                                        this->version_[4], this->version_[3], this->version_[2]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Firmware version: %s", version.c_str());
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_TEXT_SENSOR
 | 
					 | 
					 | 
					 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->version_text_sensor_ != nullptr) {
 | 
					 | 
					 | 
					 | 
					      if (this->version_text_sensor_ != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this->version_text_sensor_->publish_state(this->version_);
 | 
					 | 
					 | 
					 | 
					        this->version_text_sensor_->publish_state(version);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_MAC):
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (len < 20) {
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    case CMD_QUERY_MAC_ADDRESS: {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (this->buffer_pos_ < 20) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        return false;
 | 
					 | 
					 | 
					 | 
					        return false;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      this->mac_ = format_mac_address_pretty(&buffer[10]);
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "MAC address: %s", this->mac_.c_str());
 | 
					 | 
					 | 
					 | 
					      this->bluetooth_on_ = std::memcmp(&this->buffer_data_[10], NO_MAC, sizeof(NO_MAC)) != 0;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (this->bluetooth_on_) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        std::memcpy(this->mac_address_, &this->buffer_data_[10], sizeof(this->mac_address_));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      std::string mac_str =
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          mac_address_is_valid(this->mac_address_) ? format_mac_address_pretty(this->mac_address_) : UNKNOWN_MAC;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "MAC address: %s", mac_str.c_str());
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_TEXT_SENSOR
 | 
					 | 
					 | 
					 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->mac_text_sensor_ != nullptr) {
 | 
					 | 
					 | 
					 | 
					      if (this->mac_text_sensor_ != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this->mac_text_sensor_->publish_state(this->mac_ == NO_MAC ? UNKNOWN_MAC : this->mac_);
 | 
					 | 
					 | 
					 | 
					        this->mac_text_sensor_->publish_state(mac_str);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_SWITCH
 | 
					 | 
					 | 
					 | 
					#ifdef USE_SWITCH
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->bluetooth_switch_ != nullptr) {
 | 
					 | 
					 | 
					 | 
					      if (this->bluetooth_switch_ != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this->bluetooth_switch_->publish_state(this->mac_ != NO_MAC);
 | 
					 | 
					 | 
					 | 
					        this->bluetooth_switch_->publish_state(this->bluetooth_on_);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_BLUETOOTH):
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Bluetooth command");
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    case CMD_BLUETOOTH:
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Bluetooth");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_SINGLE_TARGET_MODE):
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Single target conf command");
 | 
					 | 
					 | 
					 | 
					    case CMD_SINGLE_TARGET_MODE:
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Single target conf");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_SWITCH
 | 
					 | 
					 | 
					 | 
					#ifdef USE_SWITCH
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->multi_target_switch_ != nullptr) {
 | 
					 | 
					 | 
					 | 
					      if (this->multi_target_switch_ != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this->multi_target_switch_->publish_state(false);
 | 
					 | 
					 | 
					 | 
					        this->multi_target_switch_->publish_state(false);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_MULTI_TARGET_MODE):
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Multi target conf command");
 | 
					 | 
					 | 
					 | 
					    case CMD_MULTI_TARGET_MODE:
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Multi target conf");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_SWITCH
 | 
					 | 
					 | 
					 | 
					#ifdef USE_SWITCH
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->multi_target_switch_ != nullptr) {
 | 
					 | 
					 | 
					 | 
					      if (this->multi_target_switch_ != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this->multi_target_switch_->publish_state(true);
 | 
					 | 
					 | 
					 | 
					        this->multi_target_switch_->publish_state(true);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_QUERY_TARGET_MODE):
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Query target tracking mode command");
 | 
					 | 
					 | 
					 | 
					    case CMD_QUERY_TARGET_MODE:
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Query target tracking mode");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_SWITCH
 | 
					 | 
					 | 
					 | 
					#ifdef USE_SWITCH
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->multi_target_switch_ != nullptr) {
 | 
					 | 
					 | 
					 | 
					      if (this->multi_target_switch_ != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        this->multi_target_switch_->publish_state(buffer[10] == 0x02);
 | 
					 | 
					 | 
					 | 
					        this->multi_target_switch_->publish_state(this->buffer_data_[10] == 0x02);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_QUERY_ZONE):
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Query zone conf command");
 | 
					 | 
					 | 
					 | 
					    case CMD_QUERY_ZONE:
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      this->zone_type_ = std::stoi(std::to_string(buffer[10]), nullptr, 16);
 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Query zone conf");
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      this->zone_type_ = std::stoi(std::to_string(this->buffer_data_[10]), nullptr, 16);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      this->publish_zone_type();
 | 
					 | 
					 | 
					 | 
					      this->publish_zone_type();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#ifdef USE_SELECT
 | 
					 | 
					 | 
					 | 
					#ifdef USE_SELECT
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (this->zone_type_select_ != nullptr) {
 | 
					 | 
					 | 
					 | 
					      if (this->zone_type_select_ != nullptr) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ESP_LOGV(TAG, "Change zone type to: %s", this->zone_type_select_->state.c_str());
 | 
					 | 
					 | 
					 | 
					        ESP_LOGV(TAG, "Change zone type to: %s", this->zone_type_select_->state.c_str());
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#endif
 | 
					 | 
					 | 
					 | 
					#endif
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (buffer[10] == 0x00) {
 | 
					 | 
					 | 
					 | 
					      if (this->buffer_data_[10] == 0x00) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ESP_LOGV(TAG, "Zone: Disabled");
 | 
					 | 
					 | 
					 | 
					        ESP_LOGV(TAG, "Zone: Disabled");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (buffer[10] == 0x01) {
 | 
					 | 
					 | 
					 | 
					      if (this->buffer_data_[10] == 0x01) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ESP_LOGV(TAG, "Zone: Area detection");
 | 
					 | 
					 | 
					 | 
					        ESP_LOGV(TAG, "Zone: Area detection");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (buffer[10] == 0x02) {
 | 
					 | 
					 | 
					 | 
					      if (this->buffer_data_[10] == 0x02) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ESP_LOGV(TAG, "Zone: Area filter");
 | 
					 | 
					 | 
					 | 
					        ESP_LOGV(TAG, "Zone: Area filter");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      this->process_zone_(buffer);
 | 
					 | 
					 | 
					 | 
					      this->process_zone_();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    case lowbyte(CMD_SET_ZONE):
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Set zone conf command");
 | 
					 | 
					 | 
					 | 
					    case CMD_SET_ZONE:
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Set zone conf");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      this->query_zone_info();
 | 
					 | 
					 | 
					 | 
					      this->query_zone_info();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    default:
 | 
					 | 
					 | 
					 | 
					    default:
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      break;
 | 
					 | 
					 | 
					 | 
					      break;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -796,55 +834,57 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Read LD2450 buffer data
 | 
					 | 
					 | 
					 | 
					// Read LD2450 buffer data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::readline_(int readch, uint8_t *buffer, uint8_t len) {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::readline_(int readch) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (readch < 0) {
 | 
					 | 
					 | 
					 | 
					  if (readch < 0) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return;
 | 
					 | 
					 | 
					 | 
					    return;  // No data available
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (this->buffer_pos_ < len - 1) {
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    buffer[this->buffer_pos_++] = readch;
 | 
					 | 
					 | 
					 | 
					  if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    buffer[this->buffer_pos_] = 0;
 | 
					 | 
					 | 
					 | 
					    this->buffer_data_[this->buffer_pos_++] = readch;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    this->buffer_data_[this->buffer_pos_] = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } else {
 | 
					 | 
					 | 
					 | 
					  } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    // We should never get here, but just in case...
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    ESP_LOGW(TAG, "Max command length exceeded; ignoring");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->buffer_pos_ = 0;
 | 
					 | 
					 | 
					 | 
					    this->buffer_pos_ = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (this->buffer_pos_ < 4) {
 | 
					 | 
					 | 
					 | 
					  if (this->buffer_pos_ < 4) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return;
 | 
					 | 
					 | 
					 | 
					    return;  // Not enough data to process yet
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (buffer[this->buffer_pos_ - 2] == 0x55 && buffer[this->buffer_pos_ - 1] == 0xCC) {
 | 
					 | 
					 | 
					 | 
					  if (this->buffer_data_[this->buffer_pos_ - 2] == DATA_FRAME_FOOTER[0] &&
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGV(TAG, "Handle periodic radar data");
 | 
					 | 
					 | 
					 | 
					      this->buffer_data_[this->buffer_pos_ - 1] == DATA_FRAME_FOOTER[1]) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->handle_periodic_data_(buffer, this->buffer_pos_);
 | 
					 | 
					 | 
					 | 
					    ESP_LOGV(TAG, "Handling Periodic Data: %s", format_hex_pretty(this->buffer_data_, this->buffer_pos_).c_str());
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->buffer_pos_ = 0;  // Reset position index for next frame
 | 
					 | 
					 | 
					 | 
					    this->handle_periodic_data_();
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } else if (buffer[this->buffer_pos_ - 4] == 0x04 && buffer[this->buffer_pos_ - 3] == 0x03 &&
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					             buffer[this->buffer_pos_ - 2] == 0x02 && buffer[this->buffer_pos_ - 1] == 0x01) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGV(TAG, "Handle command ack data");
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (this->handle_ack_data_(buffer, this->buffer_pos_)) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    this->buffer_pos_ = 0;  // Reset position index for next frame
 | 
					 | 
					 | 
					 | 
					    this->buffer_pos_ = 0;  // Reset position index for next frame
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else if (ld2450::validate_header_footer(CMD_FRAME_FOOTER, &this->buffer_data_[this->buffer_pos_ - 4])) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    ESP_LOGV(TAG, "Handling Ack Data: %s", format_hex_pretty(this->buffer_data_, this->buffer_pos_).c_str());
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (this->handle_ack_data_()) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      this->buffer_pos_ = 0;  // Reset position index for next message
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } else {
 | 
					 | 
					 | 
					 | 
					    } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Command ack data invalid");
 | 
					 | 
					 | 
					 | 
					      ESP_LOGV(TAG, "Ack Data incomplete");
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Set Config Mode - Pre-requisite sending commands
 | 
					 | 
					 | 
					 | 
					// Set Config Mode - Pre-requisite sending commands
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::set_config_mode_(bool enable) {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::set_config_mode_(bool enable) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t cmd = enable ? CMD_ENABLE_CONF : CMD_DISABLE_CONF;
 | 
					 | 
					 | 
					 | 
					  const uint8_t cmd = enable ? CMD_ENABLE_CONF : CMD_DISABLE_CONF;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t cmd_value[2] = {0x01, 0x00};
 | 
					 | 
					 | 
					 | 
					  const uint8_t cmd_value[2] = {0x01, 0x00};
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->send_command_(cmd, enable ? cmd_value : nullptr, 2);
 | 
					 | 
					 | 
					 | 
					  this->send_command_(cmd, enable ? cmd_value : nullptr, sizeof(cmd_value));
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Set Bluetooth Enable/Disable
 | 
					 | 
					 | 
					 | 
					// Set Bluetooth Enable/Disable
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::set_bluetooth(bool enable) {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::set_bluetooth(bool enable) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->set_config_mode_(true);
 | 
					 | 
					 | 
					 | 
					  this->set_config_mode_(true);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t enable_cmd_value[2] = {0x01, 0x00};
 | 
					 | 
					 | 
					 | 
					  const uint8_t cmd_value[2] = {enable ? (uint8_t) 0x01 : (uint8_t) 0x00, 0x00};
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t disable_cmd_value[2] = {0x00, 0x00};
 | 
					 | 
					 | 
					 | 
					  this->send_command_(CMD_BLUETOOTH, cmd_value, sizeof(cmd_value));
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->send_command_(CMD_BLUETOOTH, enable ? enable_cmd_value : disable_cmd_value, 2);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
 | 
					 | 
					 | 
					 | 
					  this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Set Baud rate
 | 
					 | 
					 | 
					 | 
					// Set Baud rate
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::set_baud_rate(const std::string &state) {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::set_baud_rate(const std::string &state) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->set_config_mode_(true);
 | 
					 | 
					 | 
					 | 
					  this->set_config_mode_(true);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t cmd_value[2] = {find_uint8(BAUD_RATES_BY_STR, state), 0x00};
 | 
					 | 
					 | 
					 | 
					  const uint8_t cmd_value[2] = {find_uint8(BAUD_RATES_BY_STR, state), 0x00};
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->send_command_(CMD_SET_BAUD_RATE, cmd_value, 2);
 | 
					 | 
					 | 
					 | 
					  this->send_command_(CMD_SET_BAUD_RATE, cmd_value, sizeof(cmd_value));
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->set_timeout(200, [this]() { this->restart_(); });
 | 
					 | 
					 | 
					 | 
					  this->set_timeout(200, [this]() { this->restart_(); });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -885,12 +925,12 @@ void LD2450Component::factory_reset() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::restart_() { this->send_command_(CMD_RESTART, nullptr, 0); }
 | 
					 | 
					 | 
					 | 
					void LD2450Component::restart_() { this->send_command_(CMD_RESTART, nullptr, 0); }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Get LD2450 firmware version
 | 
					 | 
					 | 
					 | 
					// Get LD2450 firmware version
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::get_version_() { this->send_command_(CMD_VERSION, nullptr, 0); }
 | 
					 | 
					 | 
					 | 
					void LD2450Component::get_version_() { this->send_command_(CMD_QUERY_VERSION, nullptr, 0); }
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Get LD2450 mac address
 | 
					 | 
					 | 
					 | 
					// Get LD2450 mac address
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void LD2450Component::get_mac_() {
 | 
					 | 
					 | 
					 | 
					void LD2450Component::get_mac_() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  uint8_t cmd_value[2] = {0x01, 0x00};
 | 
					 | 
					 | 
					 | 
					  uint8_t cmd_value[2] = {0x01, 0x00};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  this->send_command_(CMD_MAC, cmd_value, 2);
 | 
					 | 
					 | 
					 | 
					  this->send_command_(CMD_QUERY_MAC_ADDRESS, cmd_value, 2);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// Query for target tracking mode
 | 
					 | 
					 | 
					 | 
					// Query for target tracking mode
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					 
 |