From e41101ebb7c48009c7e9af6af88f4fe56b37402a Mon Sep 17 00:00:00 2001 From: Charles-Milesight Date: Wed, 18 Sep 2024 22:09:39 +0800 Subject: [PATCH 1/2] Create ts302 --- vendor/milesight-iot/ts302 | 218 +++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 vendor/milesight-iot/ts302 diff --git a/vendor/milesight-iot/ts302 b/vendor/milesight-iot/ts302 new file mode 100644 index 0000000000..390bf5638e --- /dev/null +++ b/vendor/milesight-iot/ts302 @@ -0,0 +1,218 @@ +/** + * Payload Decoder + * + * Copyright 2024 Milesight IoT + * + * @product TS302 + */ +// Chirpstack v4 +function decodeUplink(input) { + var decoded = milesightDeviceDecode(input.bytes); + return { data: decoded }; +} + +// Chirpstack v3 +function Decode(fPort, bytes) { + return milesightDeviceDecode(bytes); +} + +// The Things Network +function Decoder(bytes, port) { + return milesightDeviceDecode(bytes); +} + +function milesight(bytes) { + var decoded = {}; + + for (var i = 0; i < bytes.length; ) { + var channel_id = bytes[i++]; + var channel_type = bytes[i++]; + // IPSO VERSION + if (channel_id === 0xff && channel_type === 0x01) { + decoded.ipso_version = readProtocolVersion(bytes[i]); + i += 1; + } + // HARDWARE VERSION + else if (channel_id === 0xff && channel_type === 0x09) { + decoded.hardware_version = readHardwareVersion(bytes.slice(i, i + 2)); + i += 2; + } + // FIRMWARE VERSION + else if (channel_id === 0xff && channel_type === 0x0a) { + decoded.firmware_version = readFirmwareVersion(bytes.slice(i, i + 2)); + i += 2; + } + // DEVICE STATUS + else if (channel_id === 0xff && channel_type === 0x0b) { + decoded.device_status = 1; + i += 1; + } + // LORAWAN CLASS TYPE + else if (channel_id === 0xff && channel_type === 0x0f) { + decoded.lorawan_class = bytes[i]; + i += 1; + } + // SERIAL NUMBER + else if (channel_id === 0xff && channel_type === 0x16) { + decoded.sn = readSerialNumber(bytes.slice(i, i + 8)); + i += 8; + } + // BATTERY + else if (channel_id === 0x01 && channel_type === 0x75) { + decoded.battery = bytes[i]; + i += 1; + } + // TEMPERATURE (CHANNEL 1) + else if (channel_id === 0x03 && channel_type === 0x67) { + decoded.temperature_chn1 = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // MAGNET STATUS (CHANNEL 1) + else if (channel_id === 0x03 && channel_type === 0x00) { + decoded.magnet_chn1 = bytes[i]; + i += 1; + } + // TEMPERATURE (CHANNEL 2) + else if (channel_id === 0x04 && channel_type === 0x67) { + decoded.temperature_chn2 = readInt16LE(bytes.slice(i, i + 2)) / 10; + i += 2; + } + // MAGNET STATUS (CHANNEL 2) + else if (channel_id === 0x04 && channel_type === 0x00) { + decoded.magnet_chn2 = bytes[i]; + i += 1; + } + // TEMPERATURE ALARM (CHANNEL 1) + else if (channel_id === 0x83 && channel_type === 0x67) { + decoded.temperature_chn1 = readInt16LE(bytes.slice(i, i + 2)) / 10; + decoded.temperature_alarm_chn1 = bytes[i + 2]; + i += 3; + } + // TEMPERATURE ALARM (CHANNEL 2) + else if (channel_id === 0x84 && channel_type === 0x67) { + decoded.temperature_chn2 = readInt16LE(bytes.slice(i, i + 2)) / 10; + decoded.temperature_alarm_chn2 = bytes[i + 2]; + i += 3; + } + // TEMPERATURE ALARM (CHANNEL 1) + else if (channel_id === 0x93 && channel_type === 0xd7) { + decoded.temperature_chn1 = readInt16LE(bytes.slice(i, i + 2)) / 10; + decoded.temperature_change_chn1 = readInt16LE(bytes.slice(i + 2, i + 4)) / 100; + decoded.temperature_alarm_chn1 = bytes[i + 4]; + i += 5; + } + // TEMPERATURE ALARM (CHANNEL 2) + else if (channel_id === 0x94 && channel_type === 0xd7) { + decoded.temperature_chn2 = readInt16LE(bytes.slice(i, i + 2)) / 10; + decoded.temperature_change_chn2 = readInt16LE(bytes.slice(i + 2, i + 4)) / 100; + decoded.temperature_alarm_chn2 = bytes[i + 4]; + i += 5; + } + // HISTORY + else if (channel_id === 0x20 && channel_type === 0xce) { + var timestamp = readUInt32LE(bytes.slice(i, i + 4)); + var mask = bytes[i + 4]; + i += 5; + + var data = { timestamp: timestamp }; + var chn1_event = mask >>> 4; + var chn2_event = mask & 0x0f; + switch (chn1_event) { + case 0x01: + case 0x02: + case 0x03: + case 0x04: + data.temperature_chn1 = readInt16LE(bytes.slice(i, i + 2)) / 10; + data.report_event_chn1 = chn1_event; + break; + case 0x05: + case 0x06: + data.magnet_chn1 = readInt16LE(bytes.slice(i, i + 2)); + data.report_event_chn1 = chn1_event; + break; + default: + break; + } + i += 2; + + switch (chn2_event) { + case 0x01: + case 0x02: + case 0x03: + case 0x04: + data.temperature_chn2 = readInt16LE(bytes.slice(i, i + 2)) / 10; + data.report_event_chn2 = chn2_event; + break; + case 0x05: + case 0x06: + data.magnet_chn2 = readInt16LE(bytes.slice(i, i + 2)); + data.report_event_chn2 = chn2_event; + break; + default: + break; + } + i += 2; + + decoded.history = decoded.history || []; + decoded.history.push(data); + } else { + break; + } + } + + return decoded; +} + +function readUInt16LE(bytes) { + var value = (bytes[1] << 8) + bytes[0]; + return value & 0xffff; +} + +function readInt16LE(bytes) { + var ref = readUInt16LE(bytes); + return ref > 0x7fff ? ref - 0x10000 : ref; +} + +function readUInt32LE(bytes) { + var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; + return (value & 0xffffffff) >>> 0; +} + +function readProtocolVersion(bytes) { + var major = (bytes & 0xf0) >> 4; + var minor = bytes & 0x0f; + return "v" + major + "." + minor; +} + +function readHardwareVersion(bytes) { + var major = bytes[0] & 0xff; + var minor = (bytes[1] & 0xff) >> 4; + return "v" + major + "." + minor; +} + +function readFirmwareVersion(bytes) { + var major = bytes[0] & 0xff; + var minor = bytes[1] & 0xff; + return "v" + major + "." + minor; +} + +function readSerialNumber(bytes) { + var temp = []; + for (var idx = 0; idx < bytes.length; idx++) { + temp.push(("0" + (bytes[idx] & 0xff).toString(16)).slice(-2)); + } + return temp.join(""); +} + +function readAlarmType(type) { + switch (type) { + case 0: + return "threshold release"; + case 1: + return "threshold"; + case 2: + return "mutation"; + default: + return "unkown"; + } +} From be02f0d67fff4c04d666ae9546da7ebc4eb72e84 Mon Sep 17 00:00:00 2001 From: Charles-Milesight Date: Thu, 19 Sep 2024 17:18:41 +0800 Subject: [PATCH 2/2] Rename ts302 to ts302.js --- vendor/milesight-iot/{ts302 => ts302.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename vendor/milesight-iot/{ts302 => ts302.js} (100%) diff --git a/vendor/milesight-iot/ts302 b/vendor/milesight-iot/ts302.js similarity index 100% rename from vendor/milesight-iot/ts302 rename to vendor/milesight-iot/ts302.js