From 8a1baba7d06a59edfc4d87d8c05780be1bf10e12 Mon Sep 17 00:00:00 2001 From: YunHorn Technology Date: Tue, 15 Apr 2025 12:40:09 +0800 Subject: [PATCH] revised decoder js --- AS923_HK_CLASS_A_C.js | 1145 +++++++++++++++++++++++++++++++ AS923_HK_DECODER_o2o3o6v2023.js | 472 +++++++++++++ STM32CubeIDE/.project | 10 + 3 files changed, 1627 insertions(+) create mode 100644 AS923_HK_CLASS_A_C.js create mode 100644 AS923_HK_DECODER_o2o3o6v2023.js diff --git a/AS923_HK_CLASS_A_C.js b/AS923_HK_CLASS_A_C.js new file mode 100644 index 0000000..61b6704 --- /dev/null +++ b/AS923_HK_CLASS_A_C.js @@ -0,0 +1,1145 @@ +// Decode decodes an array of bytes into an object. +// - fPort contains the LoRaWAN fPort number +// - bytes is an array of bytes, e.g. [225, 230, 255, 0] +// - variables contains the device variables e.g. {"calibration": "3.5"} (both the key / value are of type string) +// The function must return an object, e.g. {"temperature": 22.5} +// +// Yunhorn SmarToilets Sensor R20250415R02 +// + +function Decode(fPort, data, variables) { + var data = {}; + data.length = bytes.length; + var code2color = { "0": "Dark", "1": "Green", "2": "Red", "3": "Blue", "4": "Yellow", "5": "Pink", "6": "Cyan", "7": "White" }; + var code2workmode = { "0": "Network_mode", "1": "Wired_mode", "2": "Hall_element_mode", "3": "Motion_detect_mode", "4": "Dual_mode", "5": "Uni_mode" }; + var code2state = { "0": "Not Occupied", "1": "Normal:Green", "2": "Warning:Yellow", "3": "Emegency:Red" }; + var code2fallstate = { "0": "Presence_Normal", "1": " Presence_Fall_Down", "2": " Presence_Rising_Up", "3": " Presence_LayDown", "4": " Presence_Unconcious", "5": " Presence_Stay_Still" }; + switch (fPort) { + // RESPOND PORT --- bottom of swith fport + // case 1: + + // break; + + // CMD DOWN LINK PORT + case 2: + + break; + + // STS-R5 (LEGACY, ULTRASONIC WASTE-BIN) + case 3: + break; + + // STS-O1/O2/O3/O5 REEDSWITCH, OCCUPANCY LED REPORT + case 4: + data.led_state = bytes[0] == 0x0 ? "Off" : "On"; + data.mtm_code_1 = bytes[1]; + data.mtm_code_2 = bytes[2]; + data.hw_code = bytes[3]; + data.battery_level = bytes[4] + "%"; + data.size_value = bytes[5]; + data.door_state = (bytes[6] === 0) ? "Door_Closed" : "Door_Open"; + + return { "Yunhorn_SmarToilets_data": data }; + break; + // HEART-BEAT FOR STS-O1/O2/O3/O5 REEDSWITCH, OCCUPANCY LED REPORT + case 5: + //data.led_state=(bytes[0] & 0x7f) === 0 ? "Off" : "On"; + data.BoardLED = ((bytes[0] & 0x7F) === 0x01) ? "ON" : "OFF"; + //data.battery_level = bytes[1] + " %"; + data.battery_level = bytes[1] * 100 + "mV"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + // STS-M1 water leakage sensor + case 6: + if (data.length === 2) { + data.led_state = bytes[0] == 0x0 ? "Off" : "On"; + data.battery_level = bytes[1] + "%"; + } else { + data.led_state = bytes[0] == 0x0 ? "Off" : "On"; + data.mtm_code_1 = bytes[1]; + data.mtm_code_2 = bytes[2]; + data.hw_code = bytes[3]; + //data.battery_level_mV= bytes[4]*100+" mV"; + data.battery_level = bytes[4] + " %"; + data.size_value = bytes[5]; + data.measure_tech = (bytes[6] === 0) ? "Weak Current" : "Other"; + data.liquid_level_event = (bytes[7] === 0x1) ? "Leakage Detected" : "No Leakage"; + } + return { "Yunhorn_SmarToilets_data": data }; + + break; + // temp heart-beat for STS-M1 + case 66: + if (data.length === 2) { + data.led_state = bytes[0] == 0x0 ? "Off" : "On"; + data.battery_level_mV = bytes[1] * 100 + " mV"; + return { "Yunhorn_SmarToilets_data": data }; + } + + break; + // R4 soap/sanitizer sensor + case 7: + data.led_state = bytes[0] == 0x0 ? "Off" : "On"; + data.mtm_code_1 = bytes[1]; + data.mtm_code_2 = bytes[2]; + data.hw_code = bytes[3]; + data.battery_level = bytes[4] + "%"; + data.size_value = bytes[5]; + data.measure_tech = (bytes[6] === 0) ? "Capacitive" : "Other"; + data.liquid_level_event = (bytes[7] === 0x1) ? "Liquid Detected" : "No Liquid"; + + return { "Yunhorn_SmarToilets_data": data }; + + break; + + // STS-R3 soap yes no + case 8: + //data.led_state=(bytes[0] & 0x7f) === 0 ? "Off" : "On"; + data.BoardLED = ((bytes[0] & 0x7F) === 0x01) ? "ON" : "OFF"; + //data.battery_level = bytes[1] + " %"; + data.battery_level = bytes[1] * 100 + "mV"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + // STS-M3 water tank or cistern level sensor Ultrasonic + case 9: + + break; + + // STS_O2_O6 V3 version 2023,pixel-network version + case 10: + data.LEDcolor = code2color[bytes[0]]; + data.cubicleOccupyStatus = code2state[bytes[0]]; + data.workmode = code2workmode[bytes[1]]; + + // select only one below + // For NC (Normal Closed states) + data.Sensor1_Door_Contact_Open = bytes[2] === 0 ? "Door Closed" : "Door Open"; + + // For NC (Normal Closed states) + // data.Sensor1_Door_Contact_Open = bytes[3]===1?"Door Closed":"Door Open"; + if (bytes[1] == 0x02) //Hall_element_mode + { + data.Sensor2_SOS_Pushed = bytes[3] === 0 ? "PushDown" : "RelaseUP"; + } else if (bytes[1] > 0x02) { + data.Sensor2_Motion_Detected = bytes[3] === 0 ? "No Motion" : "Motion Detected"; + } + + return { "Yunhorn_SmarToilets_data": data }; + break; + + // STS R5 waste bin + case 11: + data.LED_State = (bytes[0] === 0) ? "Off" : "On"; + data.mtm_code_1 = bytes[1]; + data.mtm_code_2 = bytes[2]; + data.hw_code = bytes[3]; + data.battery_level = bytes[4] + "%"; + // data.battery_level_mV = (bytes[4])*100 + " mV"; + data.size_value = bytes[5]; + data.distance_1_mm = bytes[6] << 8 | bytes[7]; + // data.distance_2_mm = bytes[8]<<8|bytes[9]; + // data.distance_3_mm = bytes[10]<<8|bytes[11]; + data.distance_unit = "mm"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + // STS-M4 water flow sensor + case 12: + //data.led_state=(bytes[0] & 0x7f) === 0 ? "Off" : "On"; + data.BoardLED = ((bytes[0] & 0x7F) === 0x01) ? "ON" : "OFF"; + //data.battery_level = bytes[1] + " %"; + data.battery_level = bytes[1] * 100 + "mV"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + // STS-M1A Water mark sensor thermal matrix + case 13: + break; + + // STS-M1A Water mark sensor thermal matrix, heart-beat + //case 14: + //break; + + + // STS-T6 O6T ToF Presence Detection + case 14: + data.LED_State = (bytes[0] & 0x7f === 0) ? "Off" : "On"; + data.MTM_Code_1 = bytes[1]; + data.MTM_Code_2 = bytes[2]; + data.HW_Code = bytes[3]; + data.Battery_Level = bytes[4] + " %"; + data.Payload_Size = bytes[5]; + data.Presence_State = (bytes[6] == 1) ? "Occupied" : "Vacant"; + data.Motion_state_PIR = (bytes[7] == 1) ? "Motion" : "Motionless"; v + data.Lamp_bar_color_code = bytes[8]; + data.Presence_Distance_cm = bytes[9] * 10 + " cm"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + // STS-T6 heart beat + case 15: + //data.led_state=(bytes[0] & 0x7f) === 0 ? "Off" : "On"; + data.BoardLED = ((bytes[0] & 0x7F) === 0x01) ? "ON" : "OFF"; + //data.battery_level = bytes[1] + " %"; + data.battery_level = bytes[1] * 100 + "mV"; + return { "Yunhorn_SmarToilets_data": data }; + break; + // Multi-Function Sensor for Hong Kong HA.gov.hk + case 16: + data.LED_State = (bytes[0] & 0x7f === 0) ? "Off" : "On"; + data.MTM_Code_1 = bytes[1]; + data.MTM_Code_2 = bytes[2]; + data.HW_Code = bytes[3]; + data.Battery_Level = bytes[4] + " %"; + data.Payload_Size = bytes[5]; + //data.Presence_State = (bytes[6]==1)? "Occupied":"Vacant"; + data.MF_Fall = bytes[6]; + data.MF_Human_Movement = bytes[7]; + data.MF_Occupancy = bytes[8]; + data.MF_SOS_Alarm = bytes[9]; + return { "Yunhorn_SmarToilets_data": data }; + + break; + + case 18: + //data.led_state=(bytes[0] & 0x7f) === 0 ? "Off" : "On"; + data.BoardLED = ((bytes[0] & 0x7F) === 0x01) ? "ON" : "OFF"; + //data.battery_level = bytes[1] + " %"; + data.battery_level = bytes[1] * 100 + "mV"; + return { "Yunhorn_SmarToilets_data": data }; + + break; + + case 19: + data.header_board_led = bytes[0] & 0x7f; + data.header_mtm1 = bytes[1]; + data.header_mtm2 = bytes[2]; + data.header_fw = bytes[3]; + data.header_battery_level = bytes[4] + " %"; + data.payload_size = bytes[5]; + data.payload_type = bytes[6]; + switch (bytes[6]) // fall/movement/occupancy/sos status + { + case 0x01: + data.fhmos_state_fall = bytes[7]; + data.fhmos_state_human_movement = bytes[8]; + data.fhmos_state_occupancy = bytes[9]; + data.fhmos_state_sosbutton = bytes[10]; + data.lamp_bar_color = bytes[11] + " - LED " + code2color[bytes[11]]; + data.sensor1_state = bytes[12] + " - Door: " + ((bytes[12] == 1) ? "Open" : "Closed"); + data.sensor2_state = bytes[13] + " - TOF: " + code2state[bytes[13]];; + data.sensor3_PIR_state = bytes[14] + " - PIR: " + ((bytes[14] == 1) ? "Motion" : "No Motion"); + break; + case 0x02: // fall gesture map + data.fhmos_gesture_head_height_cm = bytes[7]; + data.fhmos_gesture_head_x_y = bytes[8]; + data.fhmos_gesture_map1 = String.fromCharCode(bytes[9]); + data.fhmos_gesture_map2 = String.fromCharCode(bytes[10]); + data.fhmos_gesture_map3 = String.fromCharCode(bytes[11]); + data.fhmos_gesture_map4 = String.fromCharCode(bytes[12]); + data.fhmos_gesture_map5 = String.fromCharCode(bytes[13]); + data.fhmos_gesture_map6 = String.fromCharCode(bytes[14]); + data.fhmos_gesture_map7 = String.fromCharCode(bytes[15]); + data.fhmos_gesture_map8 = String.fromCharCode(bytes[16]); + var my_time_zone = 8 * 60 * 60; // (8*60*60) + data.fhmos_fall_event_utc_time = bytes[17] << 24 | bytes[18] << 16 | bytes[19] << 8 | bytes[20]; + data.fhmos_fall_event_time = data.fhmos_fall_event_utc_time + my_time_zone; + var dev_date = new Date(data.fhmos_fall_event_time * 1000); + data.fhmos_fall_event_time_stamp = dev_date.getHours() + ":" + dev_date.getMinutes(); + data.fhmos_fall_event_date_stamp = dev_date.getDate() + "." + (dev_date.getMonth() + 1) + "." + dev_date.getFullYear(); + + break; + case 0x03: // Background mask off map + data.fhmos_gesture_map1 = String.fromCharCode(bytes[7]); + data.fhmos_gesture_map2 = String.fromCharCode(bytes[8]); + data.fhmos_gesture_map3 = String.fromCharCode(bytes[9]); + data.fhmos_gesture_map4 = String.fromCharCode(bytes[10]); + data.fhmos_gesture_map5 = String.fromCharCode(bytes[11]); + data.fhmos_gesture_map6 = String.fromCharCode(bytes[12]); + data.fhmos_gesture_map7 = String.fromCharCode(bytes[13]); + data.fhmos_gesture_map8 = String.fromCharCode(bytes[14]); + break; + } + return { "Yunhorn_SmarToilets_data": data }; + + break; + + // Heart-beat for STS-O6 occupancy sensor + case 17: + // STS-O7 Fall detection sensor + + case 21: + { + data.BoardLED = ((bytes[0] & 0x7F) === 0x01) ? "ON" : "OFF"; + data.LEDcolor = code2color[bytes[1]]; + data.cubicleOccupyStatus = code2state[bytes[1]]; + data.workmode = code2state[bytes[2]]; + + // select only one below + // For NC(Normal Closed states + data.Sensor1_Door_Contact_Open = bytes[3] === 0 ? "Door Closed" : "Door Open"; + + // For NC(Normal Closed states + //data.Sensor1_Door_Contact_Open = bytes[3]===1?"Door Closed":"Door Open"; + data.Sensor2_Emergency_Button = bytes[4] === 0 ? "Alarm Push Down" : "No Alarm, Released"; + data.Sensor3_Motion_Detected = bytes[5] === 0 ? "No Motion" : "Motion Detected"; + + data.length = bytes.length; + if (data.length === 9) { + data.Over_stay_state = (bytes[6] === 0) ? "False" : "True"; + data.Over_Stay_duration_in_Seconds = (bytes[7] << 8 | bytes[8]); + + return { "Yunhorn_SmarToilets_data": data }; + } + else if (data.length > 9) { + data.Sensor4_ALARM_MUTE = (bytes[6] === 0) ? "Down Mute" : "No Mute"; + data.Sensor5_ALARM_RESET = (bytes[7] === 0) ? "Down RESET" : "NO Reset"; + data.Distance_in_mm = (bytes[8] << 8 | bytes[9]); + data.MotionLevel = (bytes[10] << 8 | bytes[11]); + data.Unconcious_State = (bytes[12] == 0) ? "False" : "True"; + data.Fall_Down_Detected_State = code2fallstate[bytes[13]]; + data.OverStay_Detected_State = (bytes[14] == 0x0) ? "False" : "True"; + data.OverStay_Duration_in_Seconds = (bytes[15] << 8 | bytes[16]); + data.No_Movement_Duration_in_Seconds = (bytes[17] << 8 | bytes[18]); + data.Unconcious_Duration_in_Seconds = (bytes[17] << 8 | bytes[18]); + data.Fall_Down_Speed_in_m_per_s = (bytes[19]); + data.Fall_Down_Gravity_in_g = (bytes[20]); + data.SOS_PushDown_Stamp = (bytes[21] << 24 | bytes[22] << 16 | bytes[23] << 8 | bytes[24]); + if (data.SOS_PushDown_Stamp != 0) { + var sos_start = new Date(1000 * data.SOS_PushDown_Stamp); + data.SOS_PushDown_Time = "[" + sos_start.getDate() + "." + (sos_start.getMonth() + 1) + "." + (sos_start.getFullYear()) + "] " + sos_start.getHours() + ":" + sos_start.getMinutes() + ":" + sos_start.getSeconds(); + } else data.SOS_PushDown_Time = "N/A"; + data.SOS_ReleaseUP_Stamp = (bytes[25] << 24 | bytes[26] << 16 | bytes[27] << 8 | bytes[28]); + if (data.SOS_ReleaseUP_Stamp != 0) { + var sos_stop = new Date(1000 * data.SOS_ReleaseUP_Stamp); + data.SOS_ReleaseUP_Time = "[" + sos_stop.getDate() + "." + (sos_stop.getMonth() + 1) + "." + (sos_stop.getFullYear()) + "] " + sos_stop.getHours() + ":" + sos_stop.getMinutes() + ":" + sos_stop.getSeconds(); + } else data.SOS_ReleaseUP_Time = "N/A"; + + data.Fall_Down_Stamp = (bytes[29] << 24 | bytes[30] << 16 | bytes[31] << 8 | bytes[32]); + if (data.Fall_Down_Stamp != 0) { + var fall_start = new Date(1000 * data.Fall_Down_Stamp); + data.Fall_Down_Time = "[" + fall_start.getDate() + "." + (fall_start.getMonth() + 1) + "." + (fall_start.getFullYear()) + "] " + fall_start.getHours() + ":" + fall_start.getMinutes() + ":" + fall_start.getSeconds(); + } else data.Fall_RiseUp_Stamp = "N/A"; + data.Fall_RiseUp_Stamp = (bytes[33] << 24 | bytes[34] << 16 | bytes[35] << 8 | bytes[36]); + if (data.Fall_RiseUp_Stamp != 0) { + var fall_stop = new Date(1000 * data.Fall_RiseUp_Stamp); + data.Fall_RiseUp_Time = "[" + fall_stop.getDate() + "." + (fall_stop.getMonth() + 1) + "." + (fall_stop.getFullYear()) + "] " + fall_stop.getHours() + ":" + fall_stop.getMinutes() + ":" + fall_stop.getSeconds(); + } else data.Fall_RiseUp_Time = "N/A"; + } + return { "Yunhorn_SmarToilets_data": data }; + } + + + + + break; + + + break; + + // STS-O6 occupancy sensor heart-beat + case 18: + //data.led_state=(bytes[0] & 0x7f) === 0 ? "Off" : "On"; + data.BoardLED = ((bytes[0] & 0x7F) === 0x01) ? "ON" : "OFF"; + //data.battery_level = bytes[1] + " %"; + data.battery_level = bytes[1] * 100 + "mV"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + // STS-O7 Fall detection sensor heart-beat + case 20: + break; + + // STS-M7 Vibration sensor + case 20: + break; + + // STS-R6 Weight Scale Sensor + case 27: + data.LED_State = (bytes[0] & 0x7f === 0) ? "Off" : "On"; + data.MTM_Code_1 = bytes[1]; + data.MTM_Code_2 = bytes[2]; + data.HW_Code = bytes[3]; + data.Battery_Level = bytes[4] + " %"; + data.Payload_Size = bytes[5]; + data.Weight_g = (bytes[6] << 24 | bytes[7]) << 16 | bytes[8] << 8 + bytes[9] + bytes[10]; + data.Weight_g = (bytes[6] << 24 | bytes[7]) << bytes[8] + bytes[9]; + return { "Yunhorn_SmarToilets_data": data }; + break; + + + + // STS R3 Soap Yes_No sensor + case 51: + data.LED_State = (bytes[0] === 0) ? "Off" : "On"; + data.mtm_code_1 = bytes[1]; + data.mtm_code_2 = bytes[2]; + data.hw_code = bytes[3]; + data.battery_level = bytes[4] + "%"; + // data.battery_level_mV = (bytes[4])*100 + " mV"; + data.size_value = bytes[5]; + data.Liquid_detected = bytes[6]; + data.Detect_method = (bytes[7] === 0) ? "Capacitive" : "ToF"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + // STS R2 Tissue paper sensor + case 52: + data.LED_State = (bytes[0] === 0) ? "Off" : "On"; + data.mtm_code_1 = bytes[1]; + data.mtm_code_2 = bytes[2]; + data.hw_code = bytes[3]; + data.battery_level = bytes[4] + "%"; + // data.battery_level_mV = (bytes[4])*100 + " mV"; + data.size_value = bytes[5]; + data.distance_1_mm = bytes[6] << 8 | bytes[7]; + // data.distance_2_mm = bytes[8]<<8|bytes[9]; + // data.distance_3_mm = bytes[10]<<8|bytes[11]; + data.distance_unit = "mm"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + + // STS-M8 QUEUE BAR SENSOR + case 55: + + // STS-O4 URINAL OCCUPANCY SENSOR + case 56: + + break; + + // R1D dual roll toilet paper sensor + case 57: + data.LED_State = (bytes[0] === 0) ? "Off" : "On"; + data.mtm_code_1 = bytes[1]; + data.mtm_code_2 = bytes[2]; + data.hw_code = bytes[3]; + data.battery_level = bytes[4] + "%"; + //data.battery_level_mV = (bytes[4])*100 + " mV"; + data.size_value = bytes[5]; + data.distance_1_mm = bytes[6] << 8 | bytes[7]; + data.distance_2_mm = bytes[8] << 8 | bytes[9]; + // data.distance_3_mm = bytes[10]<<8|bytes[11]; + data.distance_unit = "mm"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + // STS-R1 Single roll toilet paper sensor + case 58: + data.LED_State = (bytes[0] === 0) ? "Off" : "On"; + //data.mtm_code_1 = bytes[1]; + //data.mtm_code_2 = bytes[2]; + //data.hw_code = bytes[3]; + //data.battery_level = bytes[1]+"%"; + data.battery_level_mV = (bytes[1]) * 100 + " mV"; + //data.size_value = bytes[5]; + //data.distance_1_mm = bytes[6]<<8|bytes[7]; + //data.distance_2_mm = bytes[8]<<8|bytes[9]; + // data.distance_3_mm = bytes[10]<<8|bytes[11]; + //data.distance_unit = "mm"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + + // STS-M2 TOILET CLOGGING SENSOR + case 59: + + break; + + + // STS-E4 PTAQ, ODOR LEVEL Sensor 4-IN-1 + case 70: + + break; + + // STS-E6 PTAQ, ODOR LEVEL Sensor 6-IN-1 + case 72: + + break; + + // STS-E5 PTAQ, ODOR LEVEL Sensor 5-IN-1 + case 74: + + break; + + + // STS-E2 PTAQ, ODOR LEVEL Sensor 9-in-1 + case 101: + data.Temperature = ((bytes[0] & 0x01) ? "+" : "-") + (bytes[1] + (bytes[2] / 100)) + " C"; + data.Humidity = (bytes[3] + (bytes[4] / 100)) + " %RH"; + data.NH3 = (bytes[5] + (bytes[6] / 100)) + " ppm"; + data.H2S = (bytes[7] + bytes[8] / 100) + " ppm"; + data.CH2O = (bytes[9] + (bytes[10] / 100)) + " ug/m3"; + data.CO2 = (bytes[11] << 8 | bytes[12]) + " ppm"; + data.TVOC = (bytes[13] << 8 | bytes[14]) + " ppm"; + data.PM2_5 = ((bytes[15] << 8) | bytes[16]) + " ug/m3"; + data.PM10 = ((bytes[17] << 8) | bytes[18]) + " ug/m3"; + data.O3 = ((bytes[19] << 8) | bytes[20]) + " ppb"; + return { "Yunhorn_SmarToilets_data": data }; + + break; + + // STS-E1 Smoking Sensor + case 102: + + break; + + // STS-P1 QUEUEING SENSOR + case 104: + + break; + + // STS-M6 POWER RELAY SENSOR + case 105: + break; + + // STS-P2 IN-OUT PEOPLE COUNTING SENSOR + case 106: + { + var counting = {}; + var counting_today = {}; + // STS-P2 bi-directional people counting + data.LED_State = bytes[0] === 0 ? "Off" : "On"; + data.MTM_Code_1 = bytes[1]; + data.MTM_Code_2 = bytes[2]; + data.HW_Code = bytes[3]; + data.Battery_Level = bytes[4] + " %"; + data.Payload_Size = bytes[5]; + //data.Walk_In_People_Count = bytes[6] << 8 | bytes[7]; + //data.Walk_Out_People_Count = bytes[8] << 8 | bytes[9]; + //data.Walk_Around_People_Count = bytes[10] << 8 | bytes[11]; + counting.Walk_In_People_Count = bytes[6] << 8 | bytes[7]; + counting.Walk_Out_People_Count = bytes[8] << 8 | bytes[9]; + counting.Walk_Around_People_Count = bytes[10] << 8 | bytes[11]; + + data.Count_Period = bytes[12]; + data.Count_Period_Unit = String.fromCharCode(bytes[13]); + + //data.Sum_Day_Walk_In_People_Count = bytes[14] << 8 | bytes[15]; + //data.Sum_Day_Walk_Out_People_Count = bytes[16] << 8 | bytes[17]; + //data.Sum_Day_Walk_Around_People_Count = bytes[18] << 8 | bytes[19]; + counting_today.Sum_Day_Walk_In_People_Count = bytes[14] << 8 | bytes[15]; + counting_today.Sum_Day_Walk_Out_People_Count = bytes[16] << 8 | bytes[17]; + counting_today.Sum_Day_Walk_Around_People_Count = bytes[18] << 8 | bytes[19]; + + data.Count_Valid = (bytes[20] == 0x0) ? "Error" : "OK"; + + return { "Yunhorn_SmarToilets_data": data, "Couting_Now": counting, "Counting_today": counting_today }; + } + break; + + // HEART-BEAT FOR STS-P2 IN-OUT PEOPLE COUNTING SENSOR + case 107: + //data.led_state=(bytes[0] & 0x7f) === 0 ? "Off" : "On"; + data.BoardLED = ((bytes[0] & 0x7F) === 0x01) ? "ON" : "OFF"; + //data.battery_level = bytes[1] + " %"; + data.battery_level = bytes[1] * 100 + "mV"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + // TIME SYNC PORT + case 202: + data.TimeSyncReq = "True"; + return { "Yunhorn_SmarToilets_data": data }; + break; + + // respond port + case 1: + switch (bytes[0]) { + //AC CODE RESPONSE + case 0x41: + if ((bytes[1] == 0x43) && (data.length == 22)) + data.RFAC_RESULT = "SUCCESS"; + break; + + // RSS background center distance and motion noise 'B' + case 0x42: + if ((bytes[6] == 0x04)) { + data.background_result = "Motion Noise Measured"; + data.background_distance_center = (bytes[7] << 8 | bytes[8]) + " mm"; + data.background_motion_noise = (bytes[9] << 8 | bytes[10]) + " score"; + + } + break; + // NVM config 'C' + case 0x43: + // report current nvm config + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.sts_hw_ver = bytes[4]; + data.sts_uplink_interval = bytes[5]; + data.sts_uplink_interval_unit = String.fromCharCode(bytes[6]); + data.sts_sampling_interval = bytes[7]; + data.sts_sampling_interval_unit = String.fromCharCode(bytes[8]); + data.sts_work_mode = bytes[9]; + data.sts_service_mask = bytes[10]; + data.sts_reserve01 = bytes[11]; + data.sts_payload_length = bytes[12]; + data.rss_start_distance = bytes[13] * 0.1 + " meter"; + data.rss_range_length = bytes[14] * 0.1 + " meter"; + data.rss_threshold = bytes[15] * 0.1; + data.rss_receiving_gain = bytes[16] + " %"; + data.rss_profile = bytes[17]; + data.rss_rate_tracking = bytes[18]; + data.rss_rate_presence = bytes[19]; + data.rss_HWAAS = bytes[20]; + data.rss_nbr_removed_pc = bytes[21]; + data.rss_inter_frame_deviation_time_const = bytes[22] * 0.1; + data.rss_inter_frame_fast_cutoff = bytes[23]; + data.rss_inter_frame_slow_cutoff = bytes[24]; + data.rss_intra_frame_time_const = bytes[25]; + data.rss_intra_frame_weight = bytes[26] * 0.1; + data.rss_output_time_const = bytes[27] * 0.1; + data.rss_downsampling_factor = bytes[28]; + data.rss_power_saving_mode_active = bytes[29]; + data.rss_cfg_update_flag = bytes[30]; + data.rss_bg_noise_score = bytes[31] * 10; + data.rss_reserve04 = bytes[32]; + data.reserve2 = bytes[33]; + data.reserve3 = bytes[34]; + data.sensor_install_height = bytes[35] * 10 + " cm"; + + data.alarm_parameter05 = bytes[36]; + data.alarm_mute_expire_timer = bytes[37]; + data.alarm_lamp_bar_flashing_color = bytes[38]; + data.occupancy_overtime_threshold = bytes[39]; + + data.motionless_duration_threshold = bytes[40]; + data.unconcious_threshold = bytes[41]; + + data.fall_detection_acc_threshold = bytes[42]; + data.fall_detection_depth_threshold = bytes[43]; + data.fall_down_confirm_threshold = bytes[44]; + + break; + + // D DISTANCE , INSTALLATION HEIGHT REPORT + case 0x44: + // MEASURE INSTALLATION HEIGHT + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.sts_hw_ver = bytes[4]; + data.battery_level = bytes[5]; + data.payload_length = bytes[6]; + //data.Measure_Distance = String.fromCharCode(bytes[7]) + String.fromCharCode(bytes[8]) + String.fromCharCode(bytes[9]) + String.fromCharCode(bytes[10]); + // update on 2024-11-02 + data.Measure_Distance = bytes[7] << 8 | bytes[8]; + data.Distance_unit = "mm"; + + break; + // G Fall down Gesture bitmap REPORT + case 0x47: + data.head_level_cm = bytes[7]; + data.head_coordination = "X: " + bytes[8] / 8 + " Y:" + bytes[8] % 8; + var mmm = bytes[11]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix01 = matrix0; + mmm = bytes[12]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix02 = matrix0; + + mmm = bytes[13]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix03 = matrix0; + mmm = bytes[14]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix04 = matrix0; + + mmm = bytes[15]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix05 = matrix0; + + mmm = bytes[16]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix06 = matrix0; + + mmm = bytes[17]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix07 = matrix0; + + mmm = bytes[18]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix08 = matrix0; + + return + break; + // LoRa Class 'L' + case 0x4c: + // LoRaWAN Class A/B/C + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.LoRaWAN_Class = String.fromCharCode(bytes[4]); + break; + + // M 'M' for STS-P2 LOG DATA + case 0x4D: + data.sum_day_in = bytes[1] | bytes[2] << 8; + data.sum_day_out = bytes[3] | bytes[4] << 8; + data.sum_day_around = bytes[5] | bytes[6] << 8; + + data.sum_week_in = bytes[7] | bytes[8] << 8; + data.sum_week_out = bytes[9] | bytes[10] << 8; + data.sum_week_around = bytes[11] | bytes[12] << 8; + + data.sum_month_in = bytes[13] | bytes[14] << 8; + data.sum_month_out = bytes[15] | bytes[16] << 8; + data.sum_month_around = bytes[17] | bytes[18] << 8; + + data.sum_year_in = bytes[19] | bytes[20] << 8; + data.sum_year_out = bytes[21] | bytes[22] << 8; + data.sum_year_around = bytes[23] | bytes[24] << 8; + + data.sum_lifeCycle_in = bytes[25] | bytes[26] << 8; + data.sum_lifeCycle_out = bytes[27] | bytes[28] << 8; + data.sum_lifeCycle_around = bytes[29] | bytes[30] << 8; + + break; + // CONTROL COMMAND 'P' + case 0x50: + // P-CMD work mode change + switch (data.length) { + case 4: + if ((data.length === 4) && (bytes[1] === 0x31) && (bytes[2] === 0x31)) { + data.Work_Mode_Switch = "OK"; + data.workmode = code2workmode[bytes[3]-0x30]; + } + + break; + case 6: + data.P_cmd = "Change Lamp Bar color config"; + data.workmode = code2workmode[bytes[3] - 0x30]; + data.color_occupy = code2color[bytes[4] - 0x30]; + data.color_vacant = code2color[bytes[5] - 0x30]; + break; + case 7: + if (bytes[3] === 0x46) { + // F --- fall down & unconscious detection threshold + data.FALL_acceleration = (bytes[4] == 0x30 ? "Disabled" : ((bytes[4] - 0x30) * 10) + " mg/s2"); + data.FALL_depth_measure = (bytes[5] == 0x30 ? "Disabled" : ((bytes[5] - 0x30) * 10) + " cm"); + data.FALL_confirm_threshold = (bytes[6] == 0x30 ? "Disabled" : ((bytes[6] - 0x30) * 10) + " seconds"); + //data.FALL_reserved = (bytes[7]==0x0?"Disabled":((bytes[6]-0x30)*10)+" min"); + + } + + break; + case 8: + if (bytes[3] === 0x4f) { + // O -- over stay, onconscious, long stay + data.OMU_Motionless_duration_in_min = (bytes[4] == 0x30 ? "Disabled" : ((bytes[4] - 0x30)) + " Min"); + data.OMU_Long_Occupy_duration_in_Min = (bytes[5] == 0x30 ? "Disabled" : ((bytes[5] - 0x30) * 10) + " Min"); + data.OMU_Unconcious_Threshold = (bytes[6] == 0x30 ? "Disabled" : ((bytes[6] - 0x30) * 100) + "ml"); + data.OMU_Alarm_Mute_Reset_Timer = (bytes[7] == 0x30 ? "Disabled" : ((bytes[7] - 0x30) * 10) + " Seconds"); + } else if (bytes[3] === 0x46) { + // F --- fall down & unconscious detection threshold + data.FALL_acceleration = (bytes[4] == 0x30 ? "Disabled" : ((bytes[4] - 0x30) * 10) + " mg/s2"); + data.FALL_depth_measure = (bytes[5] == 0x30 ? "Disabled" : ((bytes[5] - 0x30) * 10) + " cm"); + data.FALL_confirm_threshold = (bytes[6] == 0x30 ? "Disabled" : ((bytes[6] - 0x30) * 10) + " seconds"); + data.FALL_reserved = (bytes[7] == 0x30 ? "Disabled" : ((bytes[6] - 0x30) * 10) + " min"); + } + break; + case 11: + // P 1108201365 + data.RSS_SIMPLE_Start = ((bytes[3] - 0x30) * 100 + (bytes[4] - 0x30) * 10) + " cm"; + data.RSS_SIMPLE_Length = ((bytes[5] - 0x30) * 100 + (bytes[6] - 0x030) * 10) + " cm"; + data.RSS_SIMPLE_Threshold = ((bytes[7] - 0x30) * 1000 + (bytes[8] - 0x30) * 100) + " ml"; + data.RSS_SIMPLE_Gain = ((bytes[9] - 0x30) * 10 + (bytes[10] - 0x30)) + " %"; + break; + case 33: + // P 11 + data.RSS_FULL_Start = ((bytes[3] - 0x30) * 100 + (bytes[4] - 0x30) * 10) + " cm"; + data.RSS_FULL_Length = ((bytes[5] - 0x30) * 100 + (bytes[6] - 0x30) * 10) + " cm"; + data.RSS_FULL_Threshold = ((bytes[7] - 0x30) * 1000 + (bytes[8] - 0x30) * 100) + " ml"; + data.RSS_FULL_Gain = ((bytes[9] - 0x30) * 10 + (bytes[10] - 0x30)) + " %"; + data.RSS_FULL_Profile = (bytes[11] - 0x30); + data.RSS_FULL_Rate_Tracking = ((bytes[12] - 0x30) * 10 + (bytes[13] - 0x30)); + data.RSS_FULL_Rate_Presence = ((bytes[14] - 0x30) * 10 + (bytes[15] - 0x30)); + data.RSS_FULL_HWAAS = ((bytes[16] - 0x30) * 10 + (bytes[17] - 0x30)); + data.RSS_FULL_Num_Removed_PC = (bytes[18] - 0x30); + data.RSS_FULL_Inter_Deviation_Time_Const_in_Sec = ((bytes[19] - 0x30) + (bytes[20] - 0x30) * 0.1); + data.RSS_FULL_Inter_Fast_Cut_Off = ((bytes[21] - 0x30) * 10 + (bytes[22] - 0x30)); + data.RSS_FULL_Inter_Slow_Cut_Off = ((bytes[23] - 0x30) * 0.1 + (bytes[24] - 0x30) * 0.001); + data.RSS_FULL_Inter_Time_Const_in_Sec = ((bytes[25] - 0x30) * 10 + (bytes[26] - 0x30)); + data.RSS_FULL_Inter_Weight = ((bytes[27] - 0x30) + (bytes[28] - 0x30) * 0.1); + data.RSS_FULL_Output_Time_Const_in_Sec = ((bytes[29] - 0x30) + (bytes[30] - 0x30) * 0.1); + data.RSS_FULL_DownSampling_factor = (bytes[31] - 0x30); + data.RSS_FULL_Power_Saving_mode = (bytes[32] - 0x30); + + break; + + default: + break; + + } + + + break; + + // CONTROL COMMAND 'R' + case 0x52: + if (bytes[1] === 0x46) { + data.RFAC_Process_Request = "OK"; + data.RFAC_Req = String.fromCharCode(bytes); + } + break; + + + // Self-Test function 'S' + case 0x53: + if ((bytes[1] == 0x54) && (bytes[2] == 0x53)) { + data.Yunhorn_PRD = "True"; + data.PRD_String = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6]); + } else { + + // SELF TEST FUNCTION + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.sts_hw_ver = bytes[4]; + data.battery_level = bytes[5]; + if ((bytes[6] === 0x0C) || (bytes[6] === 0x04)) { // report sensor install height and bitmap + data.sts_sensor_chip_model_type_ID = (bytes[7] << 8 | bytes[8]); + if ((bytes[7] === 0xF0) && (bytes[8] === 0x0C)) { + data.sts_sensor_chip_model_type = "VL53L8X"; + } + else if ((bytes[7] === 0xEA) & (bytes[8] === 0xCC)) { + data.sts_sensor_chip_model_type = "VL53L1X"; + } + else if ((bytes[7] === 0xEE) & (bytes[8] === 0xAA)) { + data.sts_sensor_chip_model_type = "VL53L0X"; + } + + data.sts_sensor_install_height = (bytes[9] << 8 | bytes[10]); + data.sts_sensor_install_height_unit = "mm"; + //data.maskoff_bitmap= String.fromCharCode(bytes[11])+String.fromCharCode(bytes[12])+String.fromCharCode(bytes[13])+String.fromCharCode(bytes[14])+String.fromCharCode(bytes[15])+String.fromCharCode(bytes[16])+String.fromCharCode(bytes[17])+String.fromCharCode(bytes[18]); + if (bytes[6] === 0x0c) { + var mmm = bytes[11]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix01 = matrix0; + mmm = bytes[12]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix02 = matrix0; + + mmm = bytes[13]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix03 = matrix0; + mmm = bytes[14]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix04 = matrix0; + + mmm = bytes[15]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix05 = matrix0; + + mmm = bytes[16]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix06 = matrix0; + + mmm = bytes[17]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix07 = matrix0; + + mmm = bytes[18]; + var con = 0x30; + var matrix0 = " [ "; + for (i = 0; i < 8; i++) { + con += ((mmm >> i) & 0x01); + matrix0 += (String.fromCharCode(con) + "__"); + con = 0x30; + } + data.matrix08 = matrix0; + } + + } + + else if ((bytes[6] === 0x58)) { + data.sts_Test_Result = "### Motion Sensor Not Detected ###"; + } else if ((bytes[6] === 0x78)) { + data.sts_Test_Result = "### Motion Sensor Detected, Yet Not Stable ###"; + } else if ((bytes[6] === 0x10)) //result length=16, 10 rss bytes, 2 distance bytes, 2 range bytes, 2 motion noise + { + data.sts_Test_Result = "Motion Sensor Test Result:"; + data.sts_test_result_length = bytes[6]; + data.sts_rss_sub_code1 = bytes[7]; + data.sts_rss_sub_code2 = bytes[8]; + data.sts_rss_sub_code3 = bytes[9]; + data.sts_rss_sub_code4 = bytes[10]; + data.sts_rss_sub_code5 = bytes[11]; + data.sts_rss_sub_code6 = bytes[12]; + data.sts_rss_sub_code7 = bytes[13]; + data.sts_rss_sub_code8 = bytes[14]; + data.sts_rss_sub_code9 = bytes[15]; + data.sts_rss_sub_code10 = bytes[16]; + data.sts_sensor_install_height = (bytes[17] << 8 | bytes[18]) + " mm"; + data.sts_rss_background_range_center = (bytes[19] << 8 | bytes[20]) + " mm"; + data.sts_rss_background_motion_noise = (bytes[21] << 8 | bytes[22]) + " score"; + } + } + + break; + + case 0x54: + //T: date & time + data.L_year = (bytes[1] << 8 | bytes[2]); + data.L_mon = bytes[3]; + data.L_day = bytes[4]; + data.L_hour = bytes[5]; + data.L_min = bytes[6]; + data.L_sec = bytes[7]; + data.LocalTime_UTC = "UTC: " + data.L_year + "/" + data.L_mon + "/" + data.L_day + " " + data.L_hour + ":" + data.L_min + ":" + data.L_sec; + + break; + + + // Firmware version 'V' + case 0x56: + // FIRMWARE VERSION + + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.sts_hw_ver = bytes[4]; + data.sts_major = bytes[5]; + data.sts_minor = bytes[6]; + data.subminor = bytes[7]; + + if (data.length === 15) { + data.L_year = (bytes[8] << 8 | bytes[9]); + data.L_mon = bytes[10]; + data.L_day = bytes[11]; + data.L_hour = bytes[12]; + data.L_min = bytes[13]; + data.L_sec = bytes[14]; + data.LocalTime_UTC = "UTC: " + data.L_year + "/" + data.L_mon + "/" + data.L_day + " " + data.L_hour + ":" + data.L_min + ":" + data.L_sec; + data.LocalTime_EST8 = "GMT+8: " + data.L_year + "/" + data.L_mon + "/" + data.L_day + " " + (data.L_hour + 8) + ":" + data.L_min + ":" + data.L_sec; + } + break; + + // Respond 'Y' + case 0x59: + + switch (bytes[1]) { + // Uplink Duration interval + case 0x44: + data.Uplink_interval = (bytes[2] - 0x30) * 10 + (bytes[3] - 0x30); + data.Uplink_interval_unit = String.fromCharCode(bytes[4]); + break; + + // Sampling interval or Heart-beat interval, 'YSaab', 'YLaab' + case 0x4C: + case 0x53: + data.Heart_Beat_interval = (bytes[2] - 0x30) * 10 + (bytes[3] - 0x30); + data.Heart_Beat_interval_unit = String.fromCharCode(bytes[4]); + // if sts_mtm1 == O6/O7 ....TODO XXXX + // data.Wakeup_sampling_interval = (bytes[2]-0x30)*10 + (bytes[3]-0x30); + // data.Unit = String.fromCharCode(bytes[4]); + break; + + } + + if (bytes[9] == 0x38) { + data.Yunhorn_PRD = "True"; + data.PRD_String = String.fromCharCode(bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15], bytes[16]); + } + + break; + + + default: + break; + + } + switch (data.length) { + // RFAC process + case 4: + if ((bytes[0] == 0x52) && (bytes[1] == 0x46)) { + data.RFAC_Process_Request = "OK"; + data.RFAC_Req = String.fromCharCode(bytes); + } else { + if ((bytes[0] === 0x50) && (bytes[1] === 0x31) && (bytes[2] === 0x31)) { + data.Work_Mode_Switch = "OK"; + data.workmode = code2workmode[bytes[3]-0x30]; + + } else if ((bytes[0] === 0x59) && (bytes[1] === 0x44)) //Duration interval + { + data.Uplink_interval = (bytes[2] - 0x30) * 10 + (bytes[3] - 0x30); + data.Uplink_interval_unit = String.fromCharCode(bytes[4]); + //data.Heart_beat_Duration = (bytes[2]-0x30)*10 + (bytes[3]-0x30); + //data.Unit = String.fromCharCode(bytes[4]); + } else if ((bytes[0] === 0x59) && (bytes[1] === 0x53)) //Sampling interval or Heart-beat interval + { + data.Heart_Beat_interval = (bytes[2] - 0x30) * 10 + (bytes[3] - 0x30); + data.Heart_Beat_interval_unit = String.fromCharCode(bytes[4]); + //data.Wakeup_sampling_interval = (bytes[2]-0x30)*10 + (bytes[3]-0x30); + //data.Unit = String.fromCharCode(bytes[4]); + } + } + break; + + // YUNHORN PRD MARK + case 10: + if ((bytes[0] == 0x59) && (bytes[9] == 0x38)) + data.Yunhorn_PRD = "True"; + data.PRD_String = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6]); + break; + + // YUNHORN NVM CONFIG LENGTH + case 44: + if (bytes[0] === 0x43) { // report current nvm config + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.sts_hw_ver = bytes[4]; + data.sts_uplink_interval = bytes[5]; + data.sts_uplink_interval_unit = String.fromCharCode(bytes[6]); + data.sts_sampling_interval = bytes[7]; + data.sts_sampling_interval_unit = String.fromCharCode(bytes[8]); + data.sts_work_mode = bytes[9]; + data.sts_service_mask = bytes[10]; + data.sts_reserve01 = bytes[11]; + data.sts_payload_length = bytes[12]; + data.rss_start_distance = bytes[13] * 0.1 + " meter"; + data.rss_range_length = bytes[14] * 0.1 + " meter"; + data.rss_threshold = bytes[15] * 0.1; + data.rss_receiving_gain = bytes[16] + " %"; + data.rss_profile = bytes[17]; + data.rss_rate_tracking = bytes[18]; + data.rss_rate_presence = bytes[19]; + data.rss_HWAAS = bytes[20]; + data.rss_nbr_removed_pc = bytes[21]; + data.rss_inter_frame_deviation_time_const = bytes[22] * 0.1; + data.rss_inter_frame_fast_cutoff = bytes[23]; + data.rss_inter_frame_slow_cutoff = bytes[24]; + data.rss_intra_frame_time_const = bytes[25]; + data.rss_intra_frame_weight = bytes[26] * 0.1; + data.rss_output_time_const = bytes[27] * 0.1; + data.rss_downsampling_factor = bytes[28]; + data.rss_power_saving_mode_active = bytes[29]; + data.rss_cfg_update_flag = bytes[30]; + data.rss_bg_motion_noise = bytes[31]*10; + data.rss_reserve04 = bytes[32]; + data.reserve2 = bytes[33]; + data.reserve3 = bytes[34]; + data.sensor_install_height = bytes[35] * 10 + " cm"; + + data.alarm_parameter05 = bytes[36]; + data.alarm_mute_expire_timer = bytes[37]; + data.alarm_lamp_bar_flashing_color = bytes[38]; + data.occupancy_overtime_threshold = bytes[39]; + + data.motionless_duration_threshold = bytes[40]; + data.unconcious_threshold = bytes[41]; + + data.fall_detection_acc_threshold = bytes[42]; + data.fall_detection_depth_threshold = bytes[43]; + data.fall_down_confirm_threshold = bytes[44]; + } + + break; + default: + break; + + } + + } + return { "Yunhorn_SmarToilets_data": data }; + +} + +// +// Yunhorn SmarToilets Sensor Decoder +// \ No newline at end of file diff --git a/AS923_HK_DECODER_o2o3o6v2023.js b/AS923_HK_DECODER_o2o3o6v2023.js new file mode 100644 index 0000000..a1ab8f1 --- /dev/null +++ b/AS923_HK_DECODER_o2o3o6v2023.js @@ -0,0 +1,472 @@ +// Decode decodes an array of bytes into an object. +// - fPort contains the LoRaWAN fPort number +// - bytes is an array of bytes, e.g. [225, 230, 255, 0] +// - variables contains the device variables e.g. {"calibration": "3.5"} (both the key / value are of type string) +// The function must return an object, e.g. {"temperature": 22.5} +// for Yunhorn SmarToilets STS-O7 Occupancy/Fall Detection/Over stay sensor +function Decode(fPort, data, variables) { + var data = {}; + data.length = bytes.length; + if ((fPort === 10)) { // STS_O2_O6 V3 version 2023,pixel-network version + switch (bytes[0]) { + case 0x00: + data.LEDcolor = "Dark"; + break; + case 0x01: + data.LEDcolor = "Green"; + data.cubicleOccupyStatus = "Vacant"; + break; + case 0x02: + data.LEDcolor = "Red"; + data.cubicleOccupyStatus = "Occupied"; + break; + case 0x03: + data.LEDcolor = "Blue"; + data.cubicleOccupyStatus = "Maintenance"; + break; + case 0x04: + data.LEDcolor = "Yellow"; + data.cubicleOccupyStatus = "TBD"; + break; + case 0x05: + data.LEDcolor = "Pink"; + data.cubicleOccupyStatus = "TBD"; + break; + case 0x06: + data.LEDcolor = "Cyan"; + data.cubicleOccupyStatus = "TBD"; + break; + case 0x07: + data.LEDcolor = "White"; + data.cubicleOccupyStatus = "TBD"; + break; + case 0x08: + data.LEDcolor = "Red_Blue"; + data.cubicleOccupyStatus = "EMERGENCY"; + break; + case 0x23: + data.LEDcolor = "Red_Blue"; + data.cubicleOccupyStatus = "EMERGENCY"; + break; + case 0x20: + data.LEDcolor = "Red_Flash"; + data.cubicleOccupyStatus = "EMERGENCY"; + break; + default: + data.LEDcolor = "TBD_COLOR"; + data.cubicleOccupyStatus = "TBD_status"; + break; + } + + switch (bytes[1]) { + case 0x0: + data.workmode = "Network_mode"; + break; + case 0x01: + data.workmode = "Wired_Mode"; + break; + case 0x02: + data.workmode = "Hall_element_mode"; + break; + case 0x03: + data.workmode = "MotionDetect_mode"; + break; + case 0x04: + data.workmode = "Dual_mode"; + break; + case 0x05: + data.workmode = "Uni_Mode"; + break; + default: + data.workmode = "Unknown Mode"; + break; + } + // select only one below + // For NC(Normal Closed states + data.Sensor1_Door_Contact_Open = bytes[2] === 0 ? "Door Closed" : "Door Open"; + + // For NC(Normal Closed states + //data.Sensor1_Door_Contact_Open = bytes[3]===1?"Door Closed":"Door Open"; + if (bytes[1] == 0x02) //Hall_element_mode + { + data.Sensor2_SOS_Pushed = bytes[3] === 0 ? "PushDown" : "RelaseUP"; + } else if (bytes[1] > 0x02) { + data.Sensor2_Motion_Detected = bytes[3] === 0 ? "No Motion" : "Motion Detected"; + } + + return { "Yunhorn_SmarToilets_data": data }; + } + else if ((fPort === 17) || (fPort === 19) || (fPort === 21)) { + data.BoardLED = ((bytes[0] & 0x7F) === 0x01) ? "ON" : "OFF"; + switch (bytes[1]) { + case 0x00: + data.LEDcolor = "Dark"; + break; + case 0x01: + data.LEDcolor = "Green"; + data.cubicleOccupyStatus = "Vacant"; + break; + case 0x02: + data.LEDcolor = "Red"; + data.cubicleOccupyStatus = "Occupied"; + break; + case 0x03: + data.LEDcolor = "Blue"; + data.cubicleOccupyStatus = "Maintenance"; + break; + case 0x04: + data.LEDcolor = "Yellow"; + data.cubicleOccupyStatus = "TBD"; + break; + case 0x05: + data.LEDcolor = "Pink"; + data.cubicleOccupyStatus = "TBD"; + break; + case 0x06: + data.LEDcolor = "Cyan"; + data.cubicleOccupyStatus = "TBD"; + break; + case 0x07: + data.LEDcolor = "White"; + data.cubicleOccupyStatus = "TBD"; + break; + case 0x08: + data.LEDcolor = "Red_Blue"; + data.cubicleOccupyStatus = "EMERGENCY"; + break; + case 0x23: + data.LEDcolor = "Red_Blue"; + data.cubicleOccupyStatus = "EMERGENCY"; + break; + case 0x20: + data.LEDcolor = "Red_Flash"; + data.cubicleOccupyStatus = "EMERGENCY"; + break; + default: + data.LEDcolor = "TBD_COLOR"; + data.cubicleOccupyStatus = "TBD_status"; + break; + } + + switch (bytes[2]) { + case 0x0: + data.workmode = "Network_mode"; + break; + case 0x01: + data.workmode = "Wired_Mode"; + break; + case 0x02: + data.workmode = "Hall_element_mode"; + break; + case 0x03: + data.workmode = "MotionDetect_mode"; + break; + case 0x04: + data.workmode = "Dual_mode"; + break; + case 0x05: + data.workmode = "Uni_Mode"; + break; + default: + data.workmode = "Unknown Mode"; + break; + } + // select only one below + // For NC(Normal Closed states + data.Sensor1_Door_Contact_Open = bytes[3] === 0 ? "Door Closed" : "Door Open"; + + // For NC(Normal Closed states + //data.Sensor1_Door_Contact_Open = bytes[3]===1?"Door Closed":"Door Open"; + data.Sensor2_Emergency_Button = bytes[4] === 0 ? "Alarm Push Down" : "No Alarm, Released"; + data.Sensor3_Motion_Detected = bytes[5] === 0 ? "No Motion" : "Motion Detected"; + + data.length = bytes.length; + if (data.length === 9) { + data.Over_stay_state = (bytes[6] === 0) ? "False" : "True"; + data.Over_Stay_duration_in_Seconds = (bytes[7] << 8 | bytes[8]); + + return { "Yunhorn_SmarToilets_data": data }; + } + else if (data.length > 9) { + data.Sensor4_ALARM_MUTE = (bytes[6] === 0) ? "Down Mute" : "No Mute"; + data.Sensor5_ALARM_RESET = (bytes[7] === 0) ? "Down RESET" : "NO Reset"; + data.Distance_in_mm = (bytes[8] << 8 | bytes[9]); + data.MotionLevel = (bytes[10] << 8 | bytes[11]); + + data.Unconcious_State = (bytes[12] == 0) ? "False" : "True"; + + switch (bytes[13]) { + case 0x0: + data.Fall_Down_Detected_State = "Presence_Normal"; + break; + case 0x01: + data.Fall_Down_Detected_State = "Presence_Fall_Down"; + break; + case 0x02: + data.Fall_Down_Detected_State = "Presence_Rising_Up"; + break; + case 0x03: + data.Fall_Down_Detected_State = "Presence_LayDown"; + break; + case 0x04: + data.Fall_Down_Detected_State = "Presence_Unconcious"; + break; + case 0x05: + data.Fall_Down_Detected_State = "Presence_Stay_Still"; + break; + default: + data.Fall_Down_Detected_State = "Presence_Normal"; + break; + } + data.OverStay_Detected_State = (bytes[14] == 0x0) ? "False" : "True"; + data.OverStay_Duration_in_Seconds = (bytes[15] << 8 | bytes[16]); + data.No_Movement_Duration_in_Seconds = (bytes[17] << 8 | bytes[18]); + data.Unconcious_Duration_in_Seconds = (bytes[17] << 8 | bytes[18]); + data.Fall_Down_Speed_in_m_per_s = (bytes[19]); + data.Fall_Down_Gravity_in_g = (bytes[20]); + data.SOS_PushDown_Stamp = (bytes[21] << 24 | bytes[22] << 16 | bytes[23] << 8 | bytes[24]); + if (data.SOS_PushDown_Stamp != 0) { + var sos_start = new Date(1000 * data.SOS_PushDown_Stamp); + data.SOS_PushDown_Time = "[" + sos_start.getDate() + "." + (sos_start.getMonth() + 1) + "." + (sos_start.getFullYear()) + "] " + sos_start.getHours() + ":" + sos_start.getMinutes() + ":" + sos_start.getSeconds(); + } else data.SOS_PushDown_Time = "N/A"; + data.SOS_ReleaseUP_Stamp = (bytes[25] << 24 | bytes[26] << 16 | bytes[27] << 8 | bytes[28]); + if (data.SOS_ReleaseUP_Stamp != 0) { + var sos_stop = new Date(1000 * data.SOS_ReleaseUP_Stamp); + data.SOS_ReleaseUP_Time = "[" + sos_stop.getDate() + "." + (sos_stop.getMonth() + 1) + "." + (sos_stop.getFullYear()) + "] " + sos_stop.getHours() + ":" + sos_stop.getMinutes() + ":" + sos_stop.getSeconds(); + } else data.SOS_ReleaseUP_Time = "N/A"; + + data.Fall_Down_Stamp = (bytes[29] << 24 | bytes[30] << 16 | bytes[31] << 8 | bytes[32]); + if (data.Fall_Down_Stamp != 0) { + var fall_start = new Date(1000 * data.Fall_Down_Stamp); + data.Fall_Down_Time = "[" + fall_start.getDate() + "." + (fall_start.getMonth() + 1) + "." + (fall_start.getFullYear()) + "] " + fall_start.getHours() + ":" + fall_start.getMinutes() + ":" + fall_start.getSeconds(); + } else data.Fall_RiseUp_Stamp = "N/A"; + data.Fall_RiseUp_Stamp = (bytes[33] << 24 | bytes[34] << 16 | bytes[35] << 8 | bytes[36]); + if (data.Fall_RiseUp_Stamp != 0) { + var fall_stop = new Date(1000 * data.Fall_RiseUp_Stamp); + data.Fall_RiseUp_Time = "[" + fall_stop.getDate() + "." + (fall_stop.getMonth() + 1) + "." + (fall_stop.getFullYear()) + "] " + fall_stop.getHours() + ":" + fall_stop.getMinutes() + ":" + fall_stop.getSeconds(); + } else data.Fall_RiseUp_Time = "N/A"; + } + return { "Yunhorn_SmarToilets_data": data }; + } + // Heart Beat + else if ((fPort === 20) || (fPort === 18) || (fPort === 5)) { + var data = {}; + //data.led_state=(bytes[0] & 0x7f) === 0 ? "Off" : "On"; + data.BoardLED = ((bytes[0] & 0x7F) === 0x01) ? "ON" : "OFF"; + data.battery_level = bytes[1] + " %"; + return { "Yunhorn_SmarToilets_data": data }; + } + + // UPLINK, RFAC + else if (fPort === 1) { + var data = {}; + data.length = bytes.length; + + if ((data.length === 4) && (bytes[0] == 0x52) && (bytes[1] = 0x46)) //RFAC + { + data.Request_Performed = "OK"; + data.RFAC = "OK"; + data.AC0 = bytes[0]; + data.AC1 = bytes[1]; + } + else if ((data.length === 4) && (bytes[0] === 0x50) && (bytes[1] === 0x31) && (bytes[2] === 0x31)) { + data.Work_Mode_Switch = "OK"; + switch (bytes[3] - 0x30) { + case 0x0: + data.workmode = "Network_mode"; + break; + case 0x01: + data.workmode = "Wired_Mode"; + break; + case 0x02: + data.workmode = "Hall_element_mode"; + break; + case 0x03: + data.workmode = "MotionDetect_mode"; + break; + case 0x04: + data.workmode = "Dual_mode"; + break; + case 0x05: + data.workmode = "Uni_Mode"; + break; + default: + data.workmode = "Unknown Mode"; + break; + } + } + + + if ((bytes[0] === 0x59) && (bytes[1] === 0x44)) //Duration interval + { + data.Heart_beat_Duration = (bytes[2] - 0x30) * 10 + (bytes[3] - 0x30); + data.Unit = String.fromCharCode(bytes[4]); + } + + else if ((bytes[0] === 0x59) && (bytes[1] === 0x53)) //Sampling interval or Heart-beat interval + { + data.Wakeup_sampling_interval = (bytes[2] - 0x30) * 10 + (bytes[3] - 0x30); + data.Unit = String.fromCharCode(bytes[4]); + } + + else if (bytes[0] === 0x43) { // report current nvm config + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.sts_hw_ver = bytes[4]; + data.sts_uplink_interval = bytes[5]; + data.sts_uplink_interval_unit = String.fromCharCode(bytes[6]); + data.sts_sampling_interval = bytes[7]; + data.sts_sampling_interval_unit = String.fromCharCode(bytes[8]); + data.sts_work_mode = bytes[9]; + data.sts_service_mask = bytes[10]; + data.sts_reserve01 = bytes[11]; + data.sts_payload_length = bytes[12]; + data.rss_start_distance = bytes[13] * 0.1 + " meter"; + data.rss_range_length = bytes[14] * 0.1 + " meter"; + data.rss_threshold = bytes[15] * 0.1; + data.rss_receiving_gain = bytes[16] + " %"; + data.rss_profile = bytes[17]; + data.rss_rate_tracking = bytes[18]; + data.rss_rate_presence = bytes[19]; + data.rss_HWAAS = bytes[20]; + data.rss_nbr_removed_pc = bytes[21]; + data.rss_inter_frame_deviation_time_const = bytes[22] * 0.1; + data.rss_inter_frame_fast_cutoff = bytes[23]; + data.rss_inter_frame_slow_cutoff = bytes[24]; + data.rss_intra_frame_time_const = bytes[25]; + data.rss_intra_frame_weight = bytes[26] * 0.1; + data.rss_output_time_const = bytes[27] * 0.1; + data.rss_downsampling_factor = bytes[28]; + data.rss_power_saving_mode_active = bytes[29]; + data.rss_reserve02 = bytes[30]; + data.rss_reserve03 = bytes[31]; + data.rss_reserve04 = bytes[32]; + data.reserve2 = bytes[33]; + data.reserve3 = bytes[34]; + data.sensor_install_height = bytes[35] * 10 + " cm"; + + data.alarm_parameter05 = bytes[36]; + data.alarm_mute_expire_timer = bytes[37]; + data.alarm_lamp_bar_flashing_color = bytes[38]; + data.occupancy_overtime_threshold = bytes[39]; + + data.motionless_duration_threshold = bytes[40]; + data.unconcious_threshold = bytes[41]; + + data.fall_detection_acc_threshold = bytes[42]; + data.fall_detection_depth_threshold = bytes[43]; + data.fall_down_confirm_threshold = bytes[44]; + } + else if (bytes[0] === 0x53) { // SELF TEST FUNCTION + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.sts_hw_ver = bytes[4]; + data.battery_level = bytes[5]; + data.sts_test_result_length = bytes[6]; + data.sts_rss_sub_code1 = bytes[7]; + data.sts_rss_sub_code2 = bytes[8]; + data.sts_rss_sub_code3 = bytes[9]; + data.sts_rss_sub_code4 = bytes[10]; + data.sts_rss_sub_code5 = bytes[11]; + data.sts_rss_sub_code6 = bytes[12]; + data.sts_rss_sub_code7 = bytes[13]; + data.sts_rss_sub_code8 = bytes[14]; + data.sts_rss_sub_code9 = bytes[15]; + data.sts_rss_sub_code10 = bytes[16]; + data.sts_sensor_install_height = String.fromCharCode(bytes[17]) + String.fromCharCode(bytes[18]) + String.fromCharCode(bytes[19]) + String.fromCharCode(bytes[20]) + " mm"; + } + else if (bytes[0] === 0x44) { // MEASURE INSTALLATION HEIGHT + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.sts_hw_ver = bytes[4]; + data.battery_level = bytes[5]; + data.payload_length = bytes[6]; + data.Measure_Distance = String.fromCharCode(bytes[7]) + String.fromCharCode(bytes[8]) + String.fromCharCode(bytes[9]) + String.fromCharCode(bytes[10]); + data.Distance_unit = "mm"; + } + else if (bytes[0] === 0x4c) { + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.LoRaWAN_Class = String.fromCharCode(bytes[4]); + } + else if (bytes[0] === 0x56) { // FIRMWARE VERSION + + data.mtm_code1 = bytes[1]; + data.mtm_code2 = bytes[2]; + data.sts_verion = bytes[3]; + data.sts_hw_ver = bytes[4]; + data.sts_major = bytes[5]; + data.sts_minor = bytes[6]; + data.subminor = bytes[7]; + + if (data.length === 15) { + data.L_year = (bytes[8] << 8 | bytes[9]); + data.L_mon = bytes[10]; + data.L_day = bytes[11]; + data.L_hour = bytes[12]; + data.L_min = bytes[13]; + data.L_sec = bytes[14]; + data.LocalTime_UTC = "UTC: " + data.L_year + "/" + data.L_mon + "/" + data.L_day + " " + data.L_hour + ":" + data.L_min + ":" + data.L_sec; + data.LocalTime_EST8 = "GMT+8: " + data.L_year + "/" + data.L_mon + "/" + data.L_day + " " + (data.L_hour + 8) + ":" + data.L_min + ":" + data.L_sec; + } + } + else if (bytes[0] === 0x50) { // P cmd report + if (data.length == 7) { + switch (bytes[3]) { + case 0x46: // F --- fall down & unconscious detection threshold + data.FALL_acceleration = (bytes[4] == 0x30 ? "Disabled" : ((bytes[4] - 0x30) * 10) + " mg/s2"); + data.FALL_depth_measure = (bytes[5] == 0x30 ? "Disabled" : ((bytes[5] - 0x30) * 10) + " cm"); + data.FALL_confirm_threshold = (bytes[6] == 0x30 ? "Disabled" : ((bytes[6] - 0x30) * 10) + " seconds"); + //data.FALL_reserved = (bytes[7]==0x0?"Disabled":((bytes[6]-0x30)*10)+" min"); + break; + } //switch + } + else if (data.length == 8) { + switch (bytes[3]) { + case 0x4f: // O -- over stay, onconscious, long stay + data.OMU_Motionless_duration_in_min = (bytes[4] == 0x30 ? "Disabled" : ((bytes[4] - 0x30)) + " Min"); + data.OMU_Long_Occupy_duration_in_Min = (bytes[5] == 0x30 ? "Disabled" : ((bytes[5] - 0x30) * 10) + " Min"); + data.OMU_Unconcious_Threshold = (bytes[6] == 0x30 ? "Disabled" : ((bytes[6] - 0x30) * 100) + "ml"); + data.OMU_Alarm_Mute_Reset_Timer = (bytes[7] == 0x30 ? "Disabled" : ((bytes[7] - 0x30) * 10) + " Seconds"); + break; + case 0x46: // F --- fall down & unconscious detection threshold + data.FALL_acceleration = (bytes[4] == 0x30 ? "Disabled" : ((bytes[4] - 0x30) * 10) + " mg/s2"); + data.FALL_depth_measure = (bytes[5] == 0x30 ? "Disabled" : ((bytes[5] - 0x30) * 10) + " cm"); + data.FALL_confirm_threshold = (bytes[6] == 0x30 ? "Disabled" : ((bytes[6] - 0x30) * 10) + " seconds"); + data.FALL_reserved = (bytes[7] == 0x30 ? "Disabled" : ((bytes[6] - 0x30) * 10) + " min"); + break; + } //switch + } else if (data.length == 11) { // P 1108201365 + data.RSS_SIMPLE_Start = ((bytes[3] - 0x30) * 100 + (bytes[4] - 0x30) * 10) + " cm"; + data.RSS_SIMPLE_Length = ((bytes[5] - 0x30) * 100 + (bytes[6] - 0x030) * 10) + " cm"; + data.RSS_SIMPLE_Threshold = ((bytes[7] - 0x30) * 1000 + (bytes[8] - 0x30) * 100) + " ml"; + data.RSS_SIMPLE_Gain = ((bytes[9] - 0x30) * 10 + (bytes[10] - 0x30)) + " %"; + } else if (data.length == 33) { // P 11 + data.RSS_FULL_Start = ((bytes[3] - 0x30) * 100 + (bytes[4] - 0x30) * 10) + " cm"; + data.RSS_FULL_Length = ((bytes[5] - 0x30) * 100 + (bytes[6] - 0x30) * 10) + " cm"; + data.RSS_FULL_Threshold = ((bytes[7] - 0x30) * 1000 + (bytes[8] - 0x30) * 100) + " ml"; + data.RSS_FULL_Gain = ((bytes[9] - 0x30) * 10 + (bytes[10] - 0x30)) + " %"; + data.RSS_FULL_Profile = (bytes[11] - 0x30); + data.RSS_FULL_Rate_Tracking = ((bytes[12] - 0x30) * 10 + (bytes[13] - 0x30)); + data.RSS_FULL_Rate_Presence = ((bytes[14] - 0x30) * 10 + (bytes[15] - 0x30)); + data.RSS_FULL_HWAAS = ((bytes[16] - 0x30) * 10 + (bytes[17] - 0x30)); + data.RSS_FULL_Num_Removed_PC = (bytes[18] - 0x30); + data.RSS_FULL_Inter_Deviation_Time_Const_in_Sec = ((bytes[19] - 0x30) + (bytes[20] - 0x30) * 0.1); + data.RSS_FULL_Inter_Fast_Cut_Off = ((bytes[21] - 0x30) * 10 + (bytes[22] - 0x30)); + data.RSS_FULL_Inter_Slow_Cut_Off = ((bytes[23] - 0x30) * 0.1 + (bytes[24] - 0x30) * 0.001); + data.RSS_FULL_Inter_Time_Const_in_Sec = ((bytes[25] - 0x30) * 10 + (bytes[26] - 0x30)); + data.RSS_FULL_Inter_Weight = ((bytes[27] - 0x30) + (bytes[28] - 0x30) * 0.1); + data.RSS_FULL_Output_Time_Const_in_Sec = ((bytes[29] - 0x30) + (bytes[30] - 0x30) * 0.1); + data.RSS_FULL_DownSampling_factor = (bytes[31] - 0x30); + data.RSS_FULL_Power_Saving_mode = (bytes[32] - 0x30); + + + } + } + return { "Yunhorn_SmarToilets_data": data }; + } +} \ No newline at end of file diff --git a/STM32CubeIDE/.project b/STM32CubeIDE/.project index d8cf060..51e7136 100644 --- a/STM32CubeIDE/.project +++ b/STM32CubeIDE/.project @@ -32,11 +32,21 @@ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + Doc/AS923_HK_CLASS_A_C.js + 1 + PARENT-1-PROJECT_LOC/AS923_HK_CLASS_A_C.js + Doc/AS923_HK_DECODER.js 1 copy_PARENT/AS923_HK_DECODER.js + + Doc/AS923_HK_DECODER_o2o3o6v2023.js + 1 + PARENT-1-PROJECT_LOC/AS923_HK_DECODER_o2o3o6v2023.js + Doc/YUNHORN-STS-O7.pdf 1