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