mirror of
https://github.com/wled/WLED.git
synced 2025-07-12 21:36:32 +00:00
commit
f0e4dd90ee
36
usermods/LD2410_v2/readme.md
Normal file
36
usermods/LD2410_v2/readme.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# BH1750 usermod
|
||||||
|
|
||||||
|
> This usermod requires a second UART and was only tested on the ESP32
|
||||||
|
|
||||||
|
|
||||||
|
This usermod will read from a LD2410 movement/presence sensor.
|
||||||
|
|
||||||
|
The movement and presence state are displayed in both the Info section of the web UI, as well as published to the `/movement` and `/stationary` MQTT topics respectively.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
- Libraries
|
||||||
|
- `ncmreynolds/ld2410@^0.1.3`
|
||||||
|
- This must be added under `lib_deps` in your `platformio.ini` (or `platformio_override.ini`).
|
||||||
|
- Data is published over MQTT - make sure you've enabled the MQTT sync interface.
|
||||||
|
|
||||||
|
## Compilation
|
||||||
|
|
||||||
|
To enable, compile with `USERMOD_LD2410` defined (e.g. in `platformio_override.ini`)
|
||||||
|
```ini
|
||||||
|
[env:usermod_USERMOD_LD2410_esp32dev]
|
||||||
|
extends = env:esp32dev
|
||||||
|
build_flags =
|
||||||
|
${common.build_flags_esp32}
|
||||||
|
-D USERMOD_LD2410
|
||||||
|
lib_deps =
|
||||||
|
${esp32.lib_deps}
|
||||||
|
ncmreynolds/ld2410@^0.1.3
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration Options
|
||||||
|
The Usermod screen allows you to:
|
||||||
|
- enable/disable the usermod
|
||||||
|
- Configure the RX/TX pins
|
||||||
|
|
||||||
|
## Change log
|
||||||
|
- 2024-06 Created by @wesleygas (https://github.com/wesleygas/)
|
237
usermods/LD2410_v2/usermod_ld2410.h
Normal file
237
usermods/LD2410_v2/usermod_ld2410.h
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
#warning **** Included USERMOD_LD2410 ****
|
||||||
|
|
||||||
|
#ifndef WLED_ENABLE_MQTT
|
||||||
|
#error "This user mod requires MQTT to be enabled."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wled.h"
|
||||||
|
#include <ld2410.h>
|
||||||
|
|
||||||
|
class LD2410Usermod : public Usermod {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool enabled = true;
|
||||||
|
bool initDone = false;
|
||||||
|
bool sensorFound = false;
|
||||||
|
unsigned long lastTime = 0;
|
||||||
|
unsigned long last_mqtt_sent = 0;
|
||||||
|
|
||||||
|
int8_t default_uart_rx = 19;
|
||||||
|
int8_t default_uart_tx = 18;
|
||||||
|
|
||||||
|
|
||||||
|
String mqttMovementTopic = F("");
|
||||||
|
String mqttStationaryTopic = F("");
|
||||||
|
bool mqttInitialized = false;
|
||||||
|
bool HomeAssistantDiscovery = true; // Publish Home Assistant Discovery messages
|
||||||
|
|
||||||
|
|
||||||
|
ld2410 radar;
|
||||||
|
bool stationary_detected = false;
|
||||||
|
bool last_stationary_state = false;
|
||||||
|
bool movement_detected = false;
|
||||||
|
bool last_movement_state = false;
|
||||||
|
|
||||||
|
// These config variables have defaults set inside readFromConfig()
|
||||||
|
int8_t uart_rx_pin;
|
||||||
|
int8_t uart_tx_pin;
|
||||||
|
|
||||||
|
// string that are used multiple time (this will save some flash memory)
|
||||||
|
static const char _name[];
|
||||||
|
static const char _enabled[];
|
||||||
|
|
||||||
|
void publishMqtt(const char* topic, const char* state, bool retain); // example for publishing MQTT message
|
||||||
|
|
||||||
|
void _mqttInitialize()
|
||||||
|
{
|
||||||
|
mqttMovementTopic = String(mqttDeviceTopic) + F("/ld2410/movement");
|
||||||
|
mqttStationaryTopic = String(mqttDeviceTopic) + F("/ld2410/stationary");
|
||||||
|
if (HomeAssistantDiscovery){
|
||||||
|
_createMqttSensor(F("Movement"), mqttMovementTopic, F("motion"), F(""));
|
||||||
|
_createMqttSensor(F("Stationary"), mqttStationaryTopic, F("occupancy"), F(""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an MQTT Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop.
|
||||||
|
void _createMqttSensor(const String &name, const String &topic, const String &deviceClass, const String &unitOfMeasurement)
|
||||||
|
{
|
||||||
|
String t = String(F("homeassistant/binary_sensor/")) + mqttClientID + F("/") + name + F("/config");
|
||||||
|
|
||||||
|
StaticJsonDocument<600> doc;
|
||||||
|
|
||||||
|
doc[F("name")] = String(serverDescription) + F(" Module");
|
||||||
|
doc[F("state_topic")] = topic;
|
||||||
|
doc[F("unique_id")] = String(mqttClientID) + name;
|
||||||
|
if (unitOfMeasurement != "")
|
||||||
|
doc[F("unit_of_measurement")] = unitOfMeasurement;
|
||||||
|
if (deviceClass != "")
|
||||||
|
doc[F("device_class")] = deviceClass;
|
||||||
|
doc[F("expire_after")] = 1800;
|
||||||
|
doc[F("payload_off")] = "OFF";
|
||||||
|
doc[F("payload_on")] = "ON";
|
||||||
|
|
||||||
|
JsonObject device = doc.createNestedObject(F("device")); // attach the sensor to the same device
|
||||||
|
device[F("name")] = serverDescription;
|
||||||
|
device[F("identifiers")] = "wled-sensor-" + String(mqttClientID);
|
||||||
|
device[F("manufacturer")] = F("WLED");
|
||||||
|
device[F("model")] = F("FOSS");
|
||||||
|
device[F("sw_version")] = versionString;
|
||||||
|
|
||||||
|
String temp;
|
||||||
|
serializeJson(doc, temp);
|
||||||
|
DEBUG_PRINTLN(t);
|
||||||
|
DEBUG_PRINTLN(temp);
|
||||||
|
|
||||||
|
mqtt->publish(t.c_str(), 0, true, temp.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
inline bool isEnabled() { return enabled; }
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial1.begin(256000, SERIAL_8N1, uart_rx_pin, uart_tx_pin);
|
||||||
|
Serial.print(F("\nLD2410 radar sensor initialising: "));
|
||||||
|
if(radar.begin(Serial1)){
|
||||||
|
Serial.println(F("OK"));
|
||||||
|
} else {
|
||||||
|
Serial.println(F("not connected"));
|
||||||
|
}
|
||||||
|
initDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
|
||||||
|
if (!enabled || strip.isUpdating()) return;
|
||||||
|
radar.read();
|
||||||
|
unsigned long curr_time = millis();
|
||||||
|
if(curr_time - lastTime > 1000) //Try to Report every 1000ms
|
||||||
|
{
|
||||||
|
lastTime = curr_time;
|
||||||
|
sensorFound = radar.isConnected();
|
||||||
|
if(!sensorFound) return;
|
||||||
|
stationary_detected = radar.presenceDetected();
|
||||||
|
if(stationary_detected != last_stationary_state){
|
||||||
|
if (WLED_MQTT_CONNECTED){
|
||||||
|
publishMqtt("/ld2410/stationary", stationary_detected ? "ON":"OFF", false);
|
||||||
|
last_stationary_state = stationary_detected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
movement_detected = radar.movingTargetDetected();
|
||||||
|
if(movement_detected != last_movement_state){
|
||||||
|
if (WLED_MQTT_CONNECTED){
|
||||||
|
publishMqtt("/ld2410/movement", movement_detected ? "ON":"OFF", false);
|
||||||
|
last_movement_state = movement_detected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If there hasn't been any activity, send current state to confirm sensor is alive
|
||||||
|
if(curr_time - last_mqtt_sent > 1000*60*5 && WLED_MQTT_CONNECTED){
|
||||||
|
publishMqtt("/ld2410/stationary", stationary_detected ? "ON":"OFF", false);
|
||||||
|
publishMqtt("/ld2410/movement", movement_detected ? "ON":"OFF", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void addToJsonInfo(JsonObject& root)
|
||||||
|
{
|
||||||
|
// if "u" object does not exist yet wee need to create it
|
||||||
|
JsonObject user = root[F("u")];
|
||||||
|
if (user.isNull()) user = root.createNestedObject(F("u"));
|
||||||
|
|
||||||
|
JsonArray ld2410_sta_json = user.createNestedArray(F("LD2410 Stationary"));
|
||||||
|
JsonArray ld2410_mov_json = user.createNestedArray(F("LD2410 Movement"));
|
||||||
|
if (!enabled){
|
||||||
|
ld2410_sta_json.add(F("disabled"));
|
||||||
|
ld2410_mov_json.add(F("disabled"));
|
||||||
|
} else if(!sensorFound){
|
||||||
|
ld2410_sta_json.add(F("LD2410"));
|
||||||
|
ld2410_sta_json.add(" Not Found");
|
||||||
|
} else {
|
||||||
|
ld2410_sta_json.add("Sta ");
|
||||||
|
ld2410_sta_json.add(stationary_detected ? "ON":"OFF");
|
||||||
|
ld2410_mov_json.add("Mov ");
|
||||||
|
ld2410_mov_json.add(movement_detected ? "ON":"OFF");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToConfig(JsonObject& root)
|
||||||
|
{
|
||||||
|
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||||||
|
top[FPSTR(_enabled)] = enabled;
|
||||||
|
//save these vars persistently whenever settings are saved
|
||||||
|
top["uart_rx_pin"] = default_uart_rx;
|
||||||
|
top["uart_tx_pin"] = default_uart_tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool readFromConfig(JsonObject& root)
|
||||||
|
{
|
||||||
|
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
|
||||||
|
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
|
||||||
|
|
||||||
|
JsonObject top = root[FPSTR(_name)];
|
||||||
|
|
||||||
|
bool configComplete = !top.isNull();
|
||||||
|
if (!configComplete)
|
||||||
|
{
|
||||||
|
DEBUG_PRINT(FPSTR(_name));
|
||||||
|
DEBUG_PRINT(F("LD2410"));
|
||||||
|
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
configComplete &= getJsonValue(top["uart_rx_pin"], uart_rx_pin, default_uart_rx);
|
||||||
|
configComplete &= getJsonValue(top["uart_tx_pin"], uart_tx_pin, default_uart_tx);
|
||||||
|
|
||||||
|
return configComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef WLED_DISABLE_MQTT
|
||||||
|
/**
|
||||||
|
* onMqttConnect() is called when MQTT connection is established
|
||||||
|
*/
|
||||||
|
void onMqttConnect(bool sessionPresent) {
|
||||||
|
// do any MQTT related initialisation here
|
||||||
|
if(!radar.isConnected()) return;
|
||||||
|
publishMqtt("/ld2410/status", "I am alive!", false);
|
||||||
|
if (!mqttInitialized)
|
||||||
|
{
|
||||||
|
_mqttInitialize();
|
||||||
|
mqttInitialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t getId()
|
||||||
|
{
|
||||||
|
return USERMOD_ID_LD2410;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// add more strings here to reduce flash memory usage
|
||||||
|
const char LD2410Usermod::_name[] PROGMEM = "LD2410Usermod";
|
||||||
|
const char LD2410Usermod::_enabled[] PROGMEM = "enabled";
|
||||||
|
|
||||||
|
|
||||||
|
// implementation of non-inline member methods
|
||||||
|
|
||||||
|
void LD2410Usermod::publishMqtt(const char* topic, const char* state, bool retain)
|
||||||
|
{
|
||||||
|
#ifndef WLED_DISABLE_MQTT
|
||||||
|
//Check if MQTT Connected, otherwise it will crash
|
||||||
|
if (WLED_MQTT_CONNECTED) {
|
||||||
|
last_mqtt_sent = millis();
|
||||||
|
char subuf[64];
|
||||||
|
strcpy(subuf, mqttDeviceTopic);
|
||||||
|
strcat(subuf, topic);
|
||||||
|
mqtt->publish(subuf, 0, retain, state);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
@ -177,6 +177,7 @@
|
|||||||
#define USERMOD_ID_BME68X 49 //Usermod "usermod_bme68x.h
|
#define USERMOD_ID_BME68X 49 //Usermod "usermod_bme68x.h
|
||||||
#define USERMOD_ID_INA226 50 //Usermod "usermod_ina226.h"
|
#define USERMOD_ID_INA226 50 //Usermod "usermod_ina226.h"
|
||||||
#define USERMOD_ID_AHT10 51 //Usermod "usermod_aht10.h"
|
#define USERMOD_ID_AHT10 51 //Usermod "usermod_aht10.h"
|
||||||
|
#define USERMOD_ID_LD2410 52 //Usermod "usermod_ld2410.h"
|
||||||
|
|
||||||
//Access point behavior
|
//Access point behavior
|
||||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||||
|
@ -230,6 +230,10 @@
|
|||||||
#include "../usermods/INA226_v2/usermod_ina226.h"
|
#include "../usermods/INA226_v2/usermod_ina226.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMOD_LD2410
|
||||||
|
#include "../usermods/LD2410_v2/usermod_ld2410.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void registerUsermods()
|
void registerUsermods()
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -446,4 +450,8 @@ void registerUsermods()
|
|||||||
#ifdef USERMOD_INA226
|
#ifdef USERMOD_INA226
|
||||||
usermods.add(new UsermodINA226());
|
usermods.add(new UsermodINA226());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USERMOD_LD2410
|
||||||
|
usermods.add(new LD2410Usermod());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user