From 30f64d3c42cad544eb8b6a1ced9057628c2b3066 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 26 Nov 2022 10:52:42 +0100 Subject: [PATCH] POC HLK-LD2410 --- .../TasmotaSerial-3.5.0/src/TasmotaSerial.cpp | 4 +- tasmota/language/af_AF.h | 3 + tasmota/language/bg_BG.h | 3 + tasmota/language/ca_AD.h | 3 + tasmota/language/cs_CZ.h | 3 + tasmota/language/de_DE.h | 3 + tasmota/language/el_GR.h | 3 + tasmota/language/en_GB.h | 3 + tasmota/language/es_ES.h | 3 + tasmota/language/fr_FR.h | 3 + tasmota/language/fy_NL.h | 3 + tasmota/language/he_HE.h | 3 + tasmota/language/hu_HU.h | 3 + tasmota/language/it_IT.h | 3 + tasmota/language/ko_KO.h | 3 + tasmota/language/nl_NL.h | 3 + tasmota/language/pl_PL.h | 3 + tasmota/language/pt_BR.h | 3 + tasmota/language/pt_PT.h | 3 + tasmota/language/ro_RO.h | 3 + tasmota/language/ru_RU.h | 3 + tasmota/language/sk_SK.h | 3 + tasmota/language/sv_SE.h | 3 + tasmota/language/tr_TR.h | 3 + tasmota/language/uk_UA.h | 3 + tasmota/language/vi_VN.h | 3 + tasmota/language/zh_CN.h | 3 + tasmota/language/zh_TW.h | 3 + .../tasmota_xsns_sensor/xsns_102_ld2410.ino | 381 ++++++++++++++++++ 29 files changed, 464 insertions(+), 2 deletions(-) create mode 100644 tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino diff --git a/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.cpp b/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.cpp index 43077ad38..82fce4934 100644 --- a/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.cpp +++ b/lib/default/TasmotaSerial-3.5.0/src/TasmotaSerial.cpp @@ -426,8 +426,8 @@ void IRAM_ATTR TasmotaSerial::rxRead(void) { m_buffer[m_in_pos] = rec; m_in_pos = next; } else { - // Buffer overrun - prep to exit and fix Hardware Watchdog in case of high speed flooding - loop_read = 0; + // Buffer overrun - exit and fix Hardware Watchdog in case of high speed flooding + break; } TM_SERIAL_WAIT_RCV_LOOP; // wait for stop bit diff --git a/tasmota/language/af_AF.h b/tasmota/language/af_AF.h index b8121b087..fc00c5a2e 100644 --- a/tasmota/language/af_AF.h +++ b/tasmota/language/af_AF.h @@ -83,6 +83,9 @@ #define D_DEBUG "Ontfout" #define D_DEWPOINT "Dou punt" #define D_DISABLED "Gedeaktiveer" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Afstand" #define D_DNS_SERVER "DNS" #define D_DO "Opgeloste suurstof" diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index cd0012e8a..dc00fa439 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -83,6 +83,9 @@ #define D_DEBUG "Дебъгване" #define D_DEWPOINT "Температура на оросяване" #define D_DISABLED "Забранено" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Разстояние" #define D_DNS_SERVER "Сървър на DNS" #define D_DO "Разтворен кислород" diff --git a/tasmota/language/ca_AD.h b/tasmota/language/ca_AD.h index 7afb11656..1c36c117a 100644 --- a/tasmota/language/ca_AD.h +++ b/tasmota/language/ca_AD.h @@ -83,6 +83,9 @@ #define D_DEBUG "Depuració" #define D_DEWPOINT "Punt de rossada" #define D_DISABLED "Deshabilitat" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distancia" #define D_DNS_SERVER "Servidor DNS" #define D_DO "Oxígen dissolt" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index d5e5e0a61..80fca7baf 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Dew point" #define D_DISABLED "Zablokováno" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distance" #define D_DNS_SERVER "Server DNS" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index 1986407ab..2d487f112 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -83,6 +83,9 @@ #define D_DEBUG "debug" #define D_DEWPOINT "Taupunkt" #define D_DISABLED "deaktiviert" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Abstand" #define D_DNS_SERVER "DNS-Server" #define D_DO "gelöster Sauerstoff" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index 6357e1973..eb60cecf9 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Dew point" #define D_DISABLED "Ανενεργό" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Απόσταση" #define D_DNS_SERVER "Διακομιστής DNS" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 7fadc258f..2e8b4af21 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Dew point" #define D_DISABLED "Disabled" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distance" #define D_DNS_SERVER "DNS Server" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index 178f62a53..dd86ba6eb 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Punto de Rocío" #define D_DISABLED "Deshabilitado" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distancia" #define D_DNS_SERVER "Servidor DNS" #define D_DO "Oxígeno Disuelto" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index ad2d32073..6dd0eb7ab 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Point de rosée" #define D_DISABLED "Désactivé" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distance" #define D_DNS_SERVER "Serveur DNS" #define D_DO "Oxygène dissout" diff --git a/tasmota/language/fy_NL.h b/tasmota/language/fy_NL.h index ce6adbaa3..7753d6f13 100644 --- a/tasmota/language/fy_NL.h +++ b/tasmota/language/fy_NL.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debugearje" #define D_DEWPOINT "Dauwpunt" #define D_DISABLED "Útsetten" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Ôfstân" #define D_DNS_SERVER "DNS Server" #define D_DO "Oploste soerstof" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index b1306fff1..783890999 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -83,6 +83,9 @@ #define D_DEBUG "באגים" #define D_DEWPOINT "Dew point" #define D_DISABLED "מבוטל" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "מרחק" #define D_DNS_SERVER "DNS שרת" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index ddebe1d65..149095171 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Harmatpont" #define D_DISABLED "Letiltva" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Távolság" #define D_DNS_SERVER "DNS szerver" #define D_DO "Oldott oxygén" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 3def3f42b..65a356b8f 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Punto rugiada" // #define D_DISABLED "Disabilitato/a" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distanza" #define D_DNS_SERVER "Server DNS" #define D_DO "Ossigeno dissolto" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 5d459a85f..8ff8b12d4 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -83,6 +83,9 @@ #define D_DEBUG "디버그" #define D_DEWPOINT "Dew point" #define D_DISABLED "사용안함" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "거리" #define D_DNS_SERVER "DNS 서버" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 134d862eb..28e55258a 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Dauwpunt" #define D_DISABLED "Uitgeschakeld" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Afstand" #define D_DNS_SERVER "DNS Server" #define D_DO "Opgelost zuurstof" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index 0944dff76..8b0735959 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Punkt rosy" #define D_DISABLED "Wyłączony" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Odległość" #define D_DNS_SERVER "Serwer DNS" #define D_DO "Rozpuszczalność tlenu" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 080d22e97..25800a0b4 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -83,6 +83,9 @@ #define D_DEBUG "Depurar" #define D_DEWPOINT "Ponto de orvalho" #define D_DISABLED "Desabilitado" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distância" #define D_DNS_SERVER "Servidor DNS" #define D_DO "Oxigênio dissolvido" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index 967f16b32..1d36075ea 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -83,6 +83,9 @@ #define D_DEBUG "Depurar" #define D_DEWPOINT "Ponto de Condensação" #define D_DISABLED "Disabilitado" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distância" #define D_DNS_SERVER "Servidor DNS" #define D_DO "Oxigénio Dissolvido" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index efbd4e48f..2bd887f0f 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -83,6 +83,9 @@ #define D_DEBUG "Depanare" #define D_DEWPOINT "Punct de rouă" #define D_DISABLED "Dezactivat" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distanță" #define D_DNS_SERVER "Server DNS" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index 981f4db35..4adf8ef54 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -83,6 +83,9 @@ #define D_DEBUG "Отладка" #define D_DEWPOINT "Dew point" #define D_DISABLED "Блокирован" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distance" #define D_DNS_SERVER "DNS Сервер" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index 9ca297d7a..29ad8e8f3 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -84,6 +84,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Dew point" #define D_DISABLED "Zablokované" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Vzdialenosť" #define D_DNS_SERVER "Server DNS" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 9ed5ea3e1..6d7d4afd5 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -83,6 +83,9 @@ #define D_DEBUG "Debug" #define D_DEWPOINT "Dew point" #define D_DISABLED "Inaktiverad" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Distans" #define D_DNS_SERVER "DNS-server" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index d94922d38..0213accba 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -83,6 +83,9 @@ #define D_DEBUG "Hata Ayıklama" #define D_DEWPOINT "Dew point" #define D_DISABLED "Etkin Değil" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Mesage" #define D_DNS_SERVER "DNS Sunucu" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index b3162de1b..abe179c74 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -83,6 +83,9 @@ #define D_DEBUG "Налагодження" #define D_DEWPOINT "Tочка роси" #define D_DISABLED "Вимкнено" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Відстань" #define D_DNS_SERVER "Сервер DNS" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/vi_VN.h b/tasmota/language/vi_VN.h index 99fa37575..6eaa39736 100644 --- a/tasmota/language/vi_VN.h +++ b/tasmota/language/vi_VN.h @@ -83,6 +83,9 @@ #define D_DEBUG "Tìm lỗi" #define D_DEWPOINT "Điểm sương" #define D_DISABLED "Vô hiệu hóa" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "Khoảng cách" #define D_DNS_SERVER "Máy chủ DNS" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index 6b4948b9e..f603c7f55 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -83,6 +83,9 @@ #define D_DEBUG "调试" #define D_DEWPOINT "Dew point" #define D_DISABLED "禁用" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "距离" #define D_DNS_SERVER "DNS服务器" #define D_DO "Disolved Oxygen" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index 1d828e7a0..53172c1aa 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -83,6 +83,9 @@ #define D_DEBUG "偵錯" #define D_DEWPOINT "Dew point" #define D_DISABLED "已停用" +#define D_MOVING_DISTANCE "Moving Distance" +#define D_STATIC_DISTANCE "Static Distance" +#define D_DETECT_DISTANCE "Detect Distance" #define D_DISTANCE "距離" #define D_DNS_SERVER "DNS伺服器" #define D_DO "Disolved Oxygen" diff --git a/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino b/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino new file mode 100644 index 000000000..144b434bf --- /dev/null +++ b/tasmota/tasmota_xsns_sensor/xsns_102_ld2410.ino @@ -0,0 +1,381 @@ +/* + xsns_102_ld2410.ino - HLK-LD2410 24GHz smart wave motion sensor support for Tasmota + + SPDX-FileCopyrightText: 2022 Theo Arends + + SPDX-License-Identifier: GPL-3.0-only +*/ + +#ifdef USE_LD2410 +/*********************************************************************************************\ + * HLK-LD2410 24GHz smart wave motion sensor + * + * Inspiration: + * https://community.home-assistant.io/t/mmwave-wars-one-sensor-module-to-rule-them-all/453260/2 + * Resources: + * https://drive.google.com/drive/folders/1p4dhbEJA3YubyIjIIC7wwVsSo8x29Fq-?spm=a2g0o.detail.1000023.17.93465697yFwVxH + * + * Basic comms using Serial Bridge: + * sbaudrate 256000 + * serialdelimiter 254 + * sserialsend5 FDFCFBFA0400FF00010004030201 -> {"SSerialReceived":"FDFCFBFA0800FF0100000100400004030201"} + * sserialsend5 FDFCFBFA0200610004030201 -> {"SSerialReceived":"FDFCFBFA1C0061010000AA0808083232281E140F0F0F0F000028281E1E141414050004030201"} + * sserialsend5 FDFCFBFA0200A00004030201 -> {"SSerialReceived":"FDFCFBFA0C00A0010000000107011615092204030201"} +\*********************************************************************************************/ + +#define XSNS_102 102 + +#define LD2410_CMND_START_CONFIGURATION 0xFF +#define LD2410_CMND_END_CONFIGURATION 0xFE +#define LD2410_CMND_SET_DISTANCE 0x60 +#define LD2410_CMND_READ_PARAMETERS 0x61 +#define LD2410_CMND_START_ENGINEERING 0x62 +#define LD2410_CMND_END_ENGINEERING 0x63 +#define LD2410_CMND_SET_SENSITIVITY 0x64 +#define LD2410_CMND_GET_FIRMWARE 0xA0 +#define LD2410_CMND_SET_BAUDRATE 0xA1 +#define LD2410_CMND_FACTORY_RESET 0xA2 +#define LD2410_CMND_REBOOT 0xA3 + +const uint8_t LD2410_config_header[4] = {0xFD, 0xFC, 0xFB, 0xFA}; +const uint8_t LD2410_config_footer[4] = {0x04, 0x03, 0x02, 0x01}; +const uint8_t LD2410_target_header[4] = {0xF4, 0xF3, 0xF2, 0xF1}; +const uint8_t LD2410_target_footer[4] = {0xF8, 0xF7, 0xF6, 0xF5}; + +#include +TasmotaSerial *LD2410Serial = nullptr; + +struct { + uint8_t *buffer; + uint16_t moving_distance; + uint16_t static_distance; + uint16_t detect_distance; + uint8_t moving_energy; + uint8_t static_energy; + uint8_t init_step; + uint8_t init_retry; + uint8_t byte_counter; + bool valid_response; +} LD2410; + +/********************************************************************************************/ + +uint32_t ToBcd(uint32_t value) { + return ((value >> 4) * 10) + (value & 0xF); +} + +/********************************************************************************************/ + +void Ld1410HandleTargetData(void) { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 + // F4 F3 F2 F1 0D 00 02 AA 00 00 00 00 00 00 37 00 00 55 00 F8 F7 F6 F5 - No target + // F4 F3 F2 F1 0D 00 02 AA 00 45 00 3E 00 00 3A 00 00 55 00 F8 F7 F6 F5 - No target + // F4 F3 F2 F1 0D 00 02 AA 03 46 00 34 00 00 3C 00 00 55 00 F8 F7 F6 F5 - Movement and Stationary target + // F4 F3 F2 F1 0D 00 02 AA 02 54 00 00 00 00 64 00 00 55 00 F8 F7 F6 F5 - Stationary target + // F4 F3 F2 F1 0D 00 02 AA 02 96 00 00 00 00 36 00 00 55 00 F8 F7 F6 F5 - Stationary target + // F4 F3 F2 F1 0D 00 02 AA 03 2A 00 64 00 00 64 00 00 55 00 F8 F7 F6 F5 - Movement and Stationary target + // header |len |dt|hd|st|movin|me|stati|se|detec|tr|ck|trailer + if (LD2410.buffer[8] != 0x00) { // Movement and/or Stationary target + LD2410.moving_distance = LD2410.buffer[10] << 8 | LD2410.buffer[9]; + LD2410.moving_energy = LD2410.buffer[11]; + LD2410.static_distance = LD2410.buffer[13] << 8 | LD2410.buffer[12]; + LD2410.static_energy = LD2410.buffer[14]; + LD2410.detect_distance = LD2410.buffer[16] << 8 | LD2410.buffer[15]; + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Type %d, State %d, Moving %d/%d%%, Static %d/%d%%, Detect %d"), + LD2410.buffer[6], LD2410.buffer[8], + LD2410.moving_distance, LD2410.moving_energy, + LD2410.static_distance, LD2410.static_energy, + LD2410.detect_distance); + + if (0x01 == LD2410.buffer[6]) { // Engineering mode data + // Adds 22 extra bytes of data + + } + } else { + LD2410.moving_distance = 0; + LD2410.moving_energy = 0; + LD2410.static_distance = 0; + LD2410.static_energy = 0; + LD2410.detect_distance = 0; + } +} + +void Ld1410HandleConfigData(void) { + if (LD2410_CMND_READ_PARAMETERS == LD2410.buffer[6]) { // 0x61 + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 + // FD FC FB FA 1C 00 61 01 00 00 AA 08 08 08 32 32 28 1E 14 0F 0F 0F 0F 00 00 28 28 1E 1E 14 14 14 05 00 04 03 02 01 - Default + // header |len |cw cv|ack |hd|dd|md|sd|moving sensitivity 0..8 |static sensitivity 0..8 |timed|trailer + // | 28| | 0| | 8| 8| 8|50 50 40 30 20 15 15 15 15| 0 0 40 40 30 30 20 20 20| 5| + + + } + else if (LD2410_CMND_START_CONFIGURATION == LD2410.buffer[6]) { // 0xFF + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + // FD FC FB FA 08 00 FF 01 00 00 01 00 40 00 04 03 02 01 + // header |len |ty |ack |protv|bsize|trailer + // | 8| | 0| 1| 64| + LD2410.valid_response = true; + } + else if (LD2410_CMND_GET_FIRMWARE == LD2410.buffer[6]) { // 0xA0 + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 + // FD FC FB FA 0C 00 A0 01 00 00 00 01 07 01 16 15 09 22 04 03 02 01 + // header |len |ty|hd|ack |ftype|major|minor |trailer + // | 12| | 1| 0| 256| 1.7| 22091516| + AddLog(LOG_LEVEL_DEBUG, PSTR("LD2: Firmware version V%d.%02d.%02d%02d%02d%02d"), // Firmware version V1.07.22091516 + ToBcd(LD2410.buffer[13]), ToBcd(LD2410.buffer[12]), + ToBcd(LD2410.buffer[17]), ToBcd(LD2410.buffer[16]), ToBcd(LD2410.buffer[15]), ToBcd(LD2410.buffer[14])); + } +} + +bool Ld2410Match(const uint8_t *header, uint32_t offset) { + for (uint32_t i = 0; i < 4; i++) { + if (LD2410.buffer[offset +i] != header[i]) { return false; } + } + return true; +} + +void Ld2410Input(void) { + while (LD2410Serial->available()) { + yield(); // Fix watchdogs + + LD2410.buffer[LD2410.byte_counter++] = LD2410Serial->read(); + if (LD2410.byte_counter < 4) { continue; } // Need first four header bytes + + uint32_t header_start = LD2410.byte_counter -4; // Fix interrupted header transmits + bool target_header = (Ld2410Match(LD2410_target_header, header_start)); // F4F3F2F1 + bool config_header = (Ld2410Match(LD2410_config_header, header_start)); // FDFCFBFA + if ((target_header || config_header) && (header_start != 0)) { + memmove(LD2410.buffer, LD2410.buffer + header_start, 4); // Sync buffer with header + LD2410.byte_counter = 4; + } + if (LD2410.byte_counter < 6) { continue; } // Need packet size bytes + + target_header = (Ld2410Match(LD2410_target_header, 0)); // F4F3F2F1 + config_header = (Ld2410Match(LD2410_config_header, 0)); // FDFCFBFA + if (target_header || config_header) { + uint32_t len = LD2410.buffer[4] +10; // Total packet size + if (len > TM_SERIAL_BUFFER_SIZE) { len = TM_SERIAL_BUFFER_SIZE; } + if (LD2410.byte_counter < len) { continue; } // Need complete packet + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Rcvd %*_H"), len, LD2410.buffer); + + if (target_header) { // F4F3F2F1 + if (Ld2410Match(LD2410_target_footer, len -4)) { // F8F7F6F5 + Ld1410HandleTargetData(); + } + } + else if (config_header) { // FDFCFBFA + if (Ld2410Match(LD2410_config_footer, len -4)) { // 04030201 + Ld1410HandleConfigData(); + } + } + } + LD2410.byte_counter = 0; + } +} + +void Ld2410SendCommand(uint32_t command, uint8_t *val = nullptr, uint32_t val_len = 0); +void Ld2410SendCommand(uint32_t command, uint8_t *val, uint32_t val_len) { + uint32_t len = val_len +12; + uint8_t buffer[len]; + buffer[0] = 0xFD; + buffer[1] = 0xFC; + buffer[2] = 0xFB; + buffer[3] = 0xFA; + buffer[4] = val_len +2; + buffer[5] = 0x00; + buffer[6] = command; + buffer[7] = 0x00; + if (val) { + for (uint32_t i = 0; i < val_len; i++) { + buffer[8 +i] = val[i]; + } + } + buffer[8 +val_len] = 0x04; + buffer[9 +val_len] = 0x03; + buffer[10 +val_len] = 0x02; + buffer[11 +val_len] = 0x01; + + AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LD2: Send %*_H"), len, buffer); + + LD2410Serial->flush(); + LD2410Serial->write(buffer, len); +// LD2410Serial->flush(); +} + +void Ld2410SetConfigMode(bool state) { + if (state) { + uint8_t value[2] = { 0x01, 0x00 }; + Ld2410SendCommand(LD2410_CMND_START_CONFIGURATION, value, sizeof(value)); + } else { + Ld2410SendCommand(LD2410_CMND_END_CONFIGURATION, nullptr, 0); + } +} + +void Ld2410SetBaudrate(uint32_t index) { + uint8_t value[2] = { (uint8_t)index, 0x00 }; + Ld2410SendCommand(LD2410_CMND_SET_BAUDRATE, value, sizeof(value)); +} + +void Ld2410SetAllSensitivity(uint32_t sensitivity) { + // 00 00 FF FF 00 00 01 00 28 00 00 00 02 00 28 00 00 00 + // gates|all gates |motio|sensitivity|stati|sensitivity + uint8_t lsb = sensitivity & 0xFF; + uint8_t msb = (sensitivity >> 8) & 0xFF; + uint8_t value[18] = { 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, lsb, msb, 0x00, 0x00, 0x02, 0x00, lsb, msb, 0x00, 0x00 }; + Ld2410SendCommand(LD2410_CMND_SET_SENSITIVITY, value, sizeof(value)); +} + +/********************************************************************************************/ + +void Ld2410Every250MSecond(void) { + if (LD2410.init_step) { + LD2410.init_step--; + switch (LD2410.init_step) { +/* + // POC using 57600 bps instead of default 256000 bps + case 20: + AddLog(LOG_LEVEL_DEBUG, PSTR("LD2: Switch to 57600 bps")); + LD2410Serial->flush(); + LD2410Serial->begin(256000); + break; + case 19: + Ld2410SetConfigMode(1); // Stop running mode + break; + case 16: + Ld2410SetBaudrate(4); // 57600 bps + break; + case 14: + Ld2410SendCommand(LD2410_CMND_REBOOT, nullptr, 0); + LD2410Serial->flush(); + LD2410Serial->begin(57600); + break; +*/ + case 10: + Ld2410SetConfigMode(1); // Stop running mode + break; + case 7: + if (!LD2410.valid_response && LD2410.init_retry) { + LD2410.init_retry--; + if (LD2410.init_retry) { +// LD2410.init_step = 21; // Change baudrate + LD2410.init_step = 13; // Retry + } else { + LD2410.init_step = 0; + AddLog(LOG_LEVEL_DEBUG, PSTR("LD2: Not detected")); + } + } else { + Ld2410SendCommand(LD2410_CMND_GET_FIRMWARE); + } + break; + case 4: + Ld2410SendCommand(LD2410_CMND_READ_PARAMETERS); + break; + case 1: + Ld2410SetConfigMode(0); + break; + } + } else { +/* + // Four times a second might be too much to handle by rules + if (LD2410.moving_energy) { + // Send state change to be captured by rules + // {"Time":"2022-11-26T10:48:16","Switch1":"ON","LD2410":{"Distance":[125.0,0.0,0.0],"Energy":[0,100]}} + MqttPublishSensor(); + } +*/ + } +} + +void Ld2410EverySecond(void) { + if (LD2410.moving_energy) { + // Send state change to be captured by rules + // {"Time":"2022-11-26T10:48:16","Switch1":"ON","LD2410":{"Distance":[125.0,0.0,0.0],"Energy":[0,100]}} + MqttPublishSensor(); + } +} + +void Ld2410Detect(void) { + if (PinUsed(GPIO_LD2410_RX) && PinUsed(GPIO_LD2410_TX)) { + LD2410.buffer = (uint8_t*)malloc(TM_SERIAL_BUFFER_SIZE); + if (!LD2410.buffer) { return; } + LD2410Serial = new TasmotaSerial(Pin(GPIO_LD2410_RX), Pin(GPIO_LD2410_TX), 2); // Default TM_SERIAL_BUFFER_SIZE (=64) size + if (LD2410Serial->begin(256000)) { + if (LD2410Serial->hardwareSerial()) { ClaimSerial(); } + + LD2410.init_retry = 5; + LD2410.init_step = 13; + } + } +} + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + + + + +/*********************************************************************************************\ + * Presentation +\*********************************************************************************************/ + +#ifdef USE_WEBSERVER +const char HTTP_SNS_LD2410_CM[] PROGMEM = + "{s}LD2410 " D_MOVING_DISTANCE "{m}%1_f " D_UNIT_CENTIMETER "{e}" + "{s}LD2410 " D_STATIC_DISTANCE "{m}%1_f " D_UNIT_CENTIMETER "{e}" + "{s}LD2410 " D_DETECT_DISTANCE "{m}%1_f " D_UNIT_CENTIMETER "{e}"; +#endif + +void Ld2410Show(bool json) { + float moving_distance = LD2410.moving_distance; + float static_distance = LD2410.static_distance; + float detect_distance = LD2410.detect_distance; + if (json) { + // cm cm cm % % + ResponseAppend_P(PSTR(",\"LD2410\":{\"" D_JSON_DISTANCE "\":[%1_f,%1_f,%1_f],\"" D_JSON_ENERGY "\":[%d,%d]}"), + &moving_distance, &static_distance, &detect_distance, LD2410.moving_energy, LD2410.static_energy); +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_LD2410_CM, &moving_distance, &static_distance, &detect_distance); +#endif + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns102(uint32_t function) { + bool result = false; + + if (FUNC_INIT == function) { + Ld2410Detect(); + } + else if (LD2410Serial) { + switch (function) { + case FUNC_LOOP: + case FUNC_SLEEP_LOOP: + Ld2410Input(); + break; + case FUNC_EVERY_250_MSECOND: + Ld2410Every250MSecond(); + break; + case FUNC_EVERY_SECOND: + Ld2410EverySecond(); + break; + case FUNC_JSON_APPEND: + Ld2410Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Ld2410Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_LD2410