diff --git a/tasmota/tasmota_xsns_sensor/xsns_102_ld2402.ino b/tasmota/tasmota_xsns_sensor/xsns_102_ld2402.ino index 0a91aa428..8f5373e4f 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_102_ld2402.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_102_ld2402.ino @@ -23,7 +23,6 @@ */ #ifdef USE_LD2402 - /*********************************************************************************************\ * HLK-LD2402 24GHz smart wave motion sensor * @@ -37,6 +36,7 @@ * LD2402_SetMotion n,n1..n16 - set motion threshold values (16) * LD2402_SetMicro n,n1..n16 - set micro threshold values (16) * LD2402_Mode 0/1 - set device output mode 0-normal, 1-engineering + * LD2402_Save - save the internal device motion/micro thresholds * LD2402_AutoUpdate 3.0,2.0,3.0 - start autoupdate trigger,keep,micro magnification factor * LD2402_Follow 0/n - reports every n seconds * @@ -367,13 +367,19 @@ void Ld2402SendCommand(uint8_t command, uint32_t val_len = 0); void Ld2402SendCommand(uint8_t command, uint32_t val_len) { uint8_t buffer[20] = LD2402_config_header_a; - buffer[4] = val_len + 2; - buffer[6] = command; if (val_len) { memcpy(buffer+8,LD2402.cmnd_param,val_len); + } else if (LD2402_CMND_START_CONFIGURATION == command) { + const uint8_t start_cmnd[2] = {0x01, 0x00}; + memcpy(buffer+8, start_cmnd, 2); + val_len = 2; } + + buffer[4] = val_len + 2; + buffer[6] = command; memcpy(buffer+8+val_len, LD2402_config_footer_a, sizeof(LD2402_config_footer_a)); + DEBUG_SENSOR_LOG(PSTR(D_LD2402_LOG_PREFIX "Send %*_H"), val_len + 12, buffer); LD2402.sent_ack = command; LD2402Serial->setReadChunkMode(1); // Enable chunk mode introducing possible Hardware Watchdogs LD2402Serial->flush(); @@ -421,11 +427,11 @@ void Ld2402WriteThresholds(uint8_t *thresholds, uint32_t cmnd_param) { } char strbuf[24]; float param; - uint32_t i = 0; + uint32_t i = 0, val; for (uint32_t j = 0; j < LD2402_NUM_GATES; j++) { ArgV(strbuf, j+1); - param = CharToFloat(strbuf); - uint32_t val = exp10(param > 95.00f ? 95.00f : param); + param = CharToFloat(strbuf) / 10.0f; + val = exp10(param > 9.5f ? 9.5f : param); thresholds[i++] = val & 0x000000FF; thresholds[i++] = val >> 8 & 0x000000FF; thresholds[i++] = val >> 16 & 0x000000FF; @@ -450,9 +456,9 @@ void Ld2402ResponseAppendGates(uint8_t *energies) { void Ld2402ResponseAppendReport() { if (3 == LD2402.report_type) { - ResponseAppend_P(PSTR("\"AutoUpdate\":\"%1d%%\"}"), LD2402.auto_upd_progress); + ResponseAppend_P(PSTR("\"AutoUpdate\":\"%1d%%\""), LD2402.auto_upd_progress); } else if (0 == LD2402.report_type) { - ResponseAppend_P(PSTR("\"Error\":\"Disconnected\"}")); + ResponseAppend_P(PSTR("\"Error\":\"Disconnected\"")); } else { ResponseAppend_P(PSTR("\"" D_JSON_DISTANCE "\":%d"), LD2402.detect_distance); if (1 == LD2402.report_type) { @@ -464,7 +470,7 @@ void Ld2402ResponseAppendReport() { Ld2402ResponseAppendGates(LD2402.motion_energy); ResponseAppend_P(PSTR("],\"MicroEnergies\":[")); Ld2402ResponseAppendGates(LD2402.micro_energy); - ResponseAppend_P(PSTR("]}")); + ResponseAppend_P(PSTR("]")); } } } @@ -497,6 +503,7 @@ void Ld2402OnDemand(uint32_t ack_rcvd) { return; case LD2402_CMND_SAVE_PARAM>>4: + LD2402.step = LD2402_CMND_END_CONFIGURATION; return; case LD2402_CMND_AUTO_THRESHOLD>>4: @@ -575,6 +582,7 @@ void Ld2402OnDemand(uint32_t ack_rcvd) { LD2402.cmnd_param[0] = LD2402_CMND_PARAM_MOTION_START; if (2 == LD2402.pwr_interf) { LD2402.step = LD2402_CMND_AUTO_INTERFERENCE; + return; } break; @@ -583,15 +591,7 @@ void Ld2402OnDemand(uint32_t ack_rcvd) { break; case LD2402_CMND_PARAM_MICRO_END: - if (LD2402.initializing) { - // clear LD2402_CMND_READ_PARAM param - LD2402.cmnd_param[0] = 0x00; - LD2402.cmnd_param[2] = 0x04; - LD2402.step = LD2402_CMND_MODE; - Ld2402EveryXMSecond(); - } else { - LD2402.step = LD2402_CMND_END_CONFIGURATION; - } + LD2402.step = LD2402_CMND_END_CONFIGURATION; return; default: @@ -626,8 +626,7 @@ void Ld2402EveryXMSecond(void) { break; case LD2402_CMND_START_CONFIGURATION: - LD2402.cmnd_param[0] = 0x01; - Ld2402SendCommand(command, 2); + Ld2402SendCommand(command); if (LD2402.initializing) { LD2402.step = LD2402_CMND_START_CONFIGURATION+CMD_LD2402_BOOT_DELAY; return; @@ -715,18 +714,19 @@ void Ld2402Detect(void) { #define D_CMD_SETCOMMON "SetCommon" #define D_CMD_SETMOTION "SetMotion" #define D_CMD_SETMICRO "SetMicro" +#define D_CMD_SAVE "Save" #define D_CMD_HELP "Help" #define D_CMD_REREAD "ReRead" #define D_CMD_FOLLOW "Follow" const char kLd2402Commands[] PROGMEM = D_LD2402 "_|" // Prefix D_CMD_MODE "|" D_CMD_AUTOUPDATE "|" D_CMD_STATUS "|" D_CMD_SETCOMMON "|" - D_CMD_SETMOTION "|" D_CMD_SETMICRO "|" D_CMD_HELP "|" D_CMD_REREAD "|" + D_CMD_SETMOTION "|" D_CMD_SETMICRO "|" D_CMD_SAVE "|" D_CMD_HELP "|" D_CMD_REREAD "|" D_CMD_FOLLOW; void (* const Ld2402Command[])(void) PROGMEM = { &CmndLd2402Mode, &CmndLd2402AutoUpdate, &CmndLd2402Status, &CmndLd2402Common, - &CmndLd2402Motion, &CmndLd2402Micro, &CmndLd2402Help, &CmndLd2402ReRead, + &CmndLd2402Motion, &CmndLd2402Micro, &CmndLd2402Save, &CmndLd2402Help, &CmndLd2402ReRead, &CmndLd2402Follow }; void CmndLd2402Help(void) { @@ -737,6 +737,7 @@ void CmndLd2402Help(void) { ResponseAppend_P(PSTR(D_LD2402 "_" D_CMD_SETCOMMON", ")); ResponseAppend_P(PSTR(D_LD2402 "_" D_CMD_SETMOTION", ")); ResponseAppend_P(PSTR(D_LD2402 "_" D_CMD_SETMICRO", ")); + ResponseAppend_P(PSTR(D_LD2402 "_" D_CMD_SAVE", ")); ResponseAppend_P(PSTR(D_LD2402 "_" D_CMD_HELP", ")); ResponseAppend_P(PSTR(D_LD2402 "_" D_CMD_REREAD", ")); ResponseAppend_P(PSTR(D_LD2402 "_" D_CMD_FOLLOW"\"}")); @@ -770,17 +771,20 @@ void CmndLd2402Status(void) { if (1 == status_type) { ResponseAppend_P(PSTR("SNS\":{")); Ld2402ResponseAppendReport(); + ResponseJsonEnd(); } else if (2 == status_type) { ResponseAppend_P(PSTR("FWR\":{\"Version\":\"%s\","),LD2402.version); - ResponseAppend_P(PSTR("\"SerialNumber\":\"%s\"}}"),LD2402.serial_number); + ResponseAppend_P(PSTR("\"SerialNumber\":\"%s\"}"),LD2402.serial_number); } else { ResponseAppend_P(PSTR("\":{\"MaximumDistance\":%d,"), LD2402.max_distance); ResponseAppend_P(PSTR("\"DisappearenceDelay\":%d,"), LD2402.disp_delay); ResponseAppend_P(PSTR("\"MotionThresholds\":[")); Ld2402ResponseAppendGates(LD2402.motion_threshold); + ResponseAppend_P(PSTR("],\"MicroThresholds\":[")); Ld2402ResponseAppendGates(LD2402.micro_threshold); - ResponseAppend_P(PSTR("]}}")); + ResponseAppend_P(PSTR("]}")); } + ResponseJsonEnd(); } void CmndLd2402ReRead(void) { @@ -832,7 +836,7 @@ void CmndLd2402Mode(void) { ArgV(Argument,1); memset(LD2402.cmnd_param, 0x00, 6); LD2402.cmnd_param[2] = atoi(Argument) ? 0x04 : 0x64; - Response_P(PSTR(D_COMMAND_PREFIX_JSON"%d}"), D_CMD_FOLLOW, (0x04 == LD2402.cmnd_param[2])); + Response_P(PSTR(D_COMMAND_PREFIX_JSON "%d}"), D_CMD_MODE, (0x04 == LD2402.cmnd_param[2])); Ld2402ExecConfigCmnd(LD2402_CMND_MODE); } @@ -853,7 +857,20 @@ void CmndLd2402AutoUpdate(void) { LD2402.cmnd_param[(i-1)*2] = (param < 1.0f) ? 10.0f : (param > 20.0f ? 200.0f : param * 10.0f); } Ld2402ExecConfigCmnd(LD2402_CMND_AUTO_THRESHOLD); - Response_P(PSTR(D_COMMAND_HELP_MSG), D_CMD_REREAD, "Updating ..."); + Response_P(PSTR(D_COMMAND_HELP_MSG), D_CMD_AUTOUPDATE, "Updating ..."); +} + +void CmndLd2402Save(void) { + if (LD2402.busy) { + Response_P(PSTR(D_BUSY_MSG)); + return; + } + if (ArgC()) { + Response_P(PSTR(D_COMMAND_HELP_MSG), D_CMD_SAVE, "No Args: Saves configuration parameters in case of power failure (v3.3.2 and above)"); + return; + } + Ld2402ExecConfigCmnd(LD2402_CMND_SAVE_PARAM); + Response_P(PSTR(D_COMMAND_HELP_MSG), D_CMD_SAVE, "Saving ..."); } void CmndLd2402Motion(void) { @@ -894,6 +911,7 @@ void Ld2402Web(void) { void Ld2402Show(void) { ResponseAppend_P(PSTR(",\"" D_LD2402 "\":{")); Ld2402ResponseAppendReport(); + ResponseJsonEnd(); } /*********************************************************************************************\