Радарный датчик Hi-Link HLK-LD2402 — это революция для мониторинга присутствия человека по цене до 100 р. Есть датчики лучше, но дороже.  Я использую этот датчик в детской. Дочка никогда не выключает свет и бороться с этим бесполезно. Но дело не только в этом, климатика, фильтр воздуха, работа гаджетов и т.д. В отличие от обычных PIR-датчиков, он определяет не просто движение, а фактическое присутствие человека, различая активные движения, микродвижения и полную неподвижность. Это делает его идеальным для контроля сна ребёнка — свет не погаснет, а климат-контроль не отключится, пока ребёнок в комнате. Подключив датчик к Home Assistant через ESP8266, я создал умную, надежную и ненавязчивую систему слежения.

Главное отличие: Датчик работает на частоте 24 ГГц и отслеживает три состояния: движение, микродвижение и статичное присутствие. Дальность обнаружения — до 8 метров для микродвижений. Главное его правильно настроить. Во вложении программа для настройки и калибровки.

Для интеграции я использовал Arduino IDE и MQTT в моем Home Assistant.

Вот конфигурация под HA:

mqtt:
  binary_sensor:
    - state_topic: "esp8266/alice_m"
      name: AlicePIR_new
      unique_id: alicepir_new
      qos: 0
      payload_off: "0"
      payload_on: "1"
      device_class: presence

Вот готовая программа под Arduino IDE:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266SSDP.h> 
#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>

// MQTT Broker
#include <PubSubClient.h>
const char *mqtt_broker = "192.168.1.26";
const char *topicM = "esp8266/alice_m";
const char *mqtt_username = "homeassistant";
const char *mqtt_password = "....................................";
const int mqtt_port = 1883;
WiFiClient espClient;
PubSubClient client(espClient);

// PIR Motion Sensor
#define MOTION_SENSOR_PIN 3  // GPIO3 (RX)
int motion_state = LOW;
int prev_motion_state = LOW;

extern "C" {
  #include "user_interface.h"
}

// Имя хоста
const char* host = "alice-disco1";
// WiFi параметры
const char* ssid = "ap";
const char* password = "password";

ESP8266WebServer server(80);

void setup() {
    SSDP.setDeviceType("upnp:rootdevice");
    SSDP.setSchemaURL("description.xml");
    SSDP.setHTTPPort(80);
    SSDP.setName("MainFrm Alice Disco1");
    SSDP.setSerialNumber("0001");
    SSDP.setURL("/");
    SSDP.setModelName("MainFrm esp8266");
    SSDP.setManufacturer("MFrm");
    SSDP.setManufacturerURL("http://it-board.ru");
    SSDP.begin();

    pinMode(MOTION_SENSOR_PIN, INPUT);
    wifi_set_sleep_type(NONE_SLEEP_T);

    // Подключение к WiFi
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    
    if(WiFi.waitForConnectResult() == WL_CONNECTED){
        server.on("/", HTTP_handleRoot);
        server.on("/description.xml", HTTP_GET, [](){
            SSDP.schema(server.client());
        });
        server.onNotFound(HTTP_handleRoot);
        server.begin();    

        ArduinoOTA.begin();
        client.setServer(mqtt_broker, mqtt_port);
        
        // Отправляем начальное состояние движения
        client.publish(topicM, "1");
    }
}

void loop() {
    ArduinoOTA.handle();
    server.handleClient();

    // Проверка датчика движения
    prev_motion_state = motion_state;
    motion_state = digitalRead(MOTION_SENSOR_PIN);

    if (prev_motion_state == LOW && motion_state == HIGH) {
        client.publish(topicM, "1");
    } 
    else if (prev_motion_state == HIGH && motion_state == LOW) {
        client.publish(topicM, "0");
    }

    // Подключение к MQTT брокеру
    while (!client.connected()) {
        String client_id = "esp8266-client-";
        client_id += String(WiFi.macAddress());
        if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
            // Можете подписаться на топики при необходимости
        } else {
            delay(500);
        }
    }

    client.loop();
    delay(50);
}

/*
 * Оработчик главной страницы сервера
 */
void HTTP_handleRoot(void) {
    long rssi = WiFi.RSSI();
    String levl = "[----]";
    rssi = rssi * -1;
    
    if (rssi < 83) levl = "[||||]";
    else if (rssi >= 83 && rssi < 87) levl = "[|||-]";
    else if (rssi >= 87 && rssi < 92) levl = "[||--]";
    else if (rssi >= 92) levl = "[|---]";

    String out = "";
    out += "<html><head>";
    out += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">";
    out += "<title>MainFrm Alice-Disco1 (id: ADSK1)</title>";
    out += "<style>";
    out += ".h4 {margin: 0px 0px;}";
    out += "body {color: #555; font-family: helvetica neue, helvetica, arial; font-size: 15px; line-height: 1em; text-align:center; }";
    out += "a { color: #473213; text-decoration: none; padding: 2px;}";
    out += "a:hover { text-decoration: none; }";
    out += ".img1{text-align:center}";
    out += ".box{width:245px;display:inline-block;}";
    out += ".container{margin:auto;overflow:hidden;width:750px}";
    out += "</style>";
    out += "</head><body>";
    
    out += "<p><a href=\"/\"><b><font size=\"4\" color=\"#FF0000\">M</font>ainFrm Alice Room Disco Control (<font color=\"#008000\">Sl: ";
    out += WiFi.RSSI();
    out += "dbi ";
    out += levl;
    out += "</font>)</b></a></p><hr size=\"1px\" width=\"75%\">";
    
    out += "<div class=\"container\">";
    out += "<h3>Датчики</h3>";
    out += "<p>Движение: ";
    out += motion_state ? "ОБНАРУЖЕНО" : "НЕТ ДВИЖЕНИЯ";
    out += "</p>";
    
    out += "<br><br><h4>Информация об устройстве</h4>";
    out += "<p>IP адрес: ";
    out += WiFi.localIP().toString();
    out += "</p>";
    out += "<p>MAC адрес: ";
    out += WiFi.macAddress();
    out += "</p>";
    out += "<p>Сигнал WiFi: ";
    out += WiFi.RSSI();
    out += " dBm ";
    out += levl;
    out += "</p>";
    
    out += "</div></body></html>";
    
    server.send(200, "text/html", out);
}
Вложения:
 HLK-LD2402_TOOL(v1.0.1.9_20250318).zip[ ]30928 КБ

Комментарии