266 lines
11 KiB
JavaScript
266 lines
11 KiB
JavaScript
// 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 = {};
|
|
if ((fPort === 17) || (fPort === 19) || (fPort === 21)) {
|
|
data.BoardLED = bytes[0] & 0x7F;
|
|
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_Motion_Detected = bytes[4] === 0 ? "No Motion" : "Motion Detected";
|
|
data.Sensor3_Emergency_Button = bytes[5] === 0 ? "Alarm Push Down" : "No Alarm, Released";
|
|
if (bytes.length > 6) {
|
|
data.Sensor4 = bytes[6] === 0 ? "No" : "Yes";
|
|
data.Distance_in_mm = (bytes[7] << 8 | bytes[8]);
|
|
data.MotionLevel = (bytes[9] << 8 | bytes[10]);
|
|
|
|
data.Unconcious_State = bytes[11];
|
|
switch (bytes[12]) {
|
|
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;
|
|
}
|
|
data.OverStay_Detected_State = (bytes[13] == 0x0) ? "No" : "Yes";
|
|
data.OverStay_Duration_in_Seconds = (bytes[14] << 8 | bytes[15]);
|
|
data.No_Movement_Duration_in_Seconds = (bytes[16] << 8 | bytes[17]);
|
|
data.Unconcious_Duration_in_Seconds = (bytes[16] << 8 | bytes[17]);
|
|
}
|
|
return { "Yunhorn_SmarToilets_data": data };
|
|
}
|
|
// Heart Beat
|
|
else if ((fPort === 20) || (fPort === 18)) {
|
|
var data = {};
|
|
data.led_state = (bytes[0] & 0x7f) === 0 ? "Off" : "On";
|
|
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) {
|
|
data.RFAC = "OK";
|
|
data.AC0 = bytes[0];
|
|
data.AC1 = bytes[1];
|
|
}
|
|
|
|
|
|
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.reserve4 = bytes[35];
|
|
|
|
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;
|
|
}
|
|
}
|
|
return { "Yunhorn_SmarToilets_data": data };
|
|
}
|
|
}
|