├── .gitignore ├── AM_Series ├── AM102 │ ├── AM102.png │ ├── AM102L.png │ ├── AM102_Decoder.js │ └── README.md ├── AM103 │ ├── AM103.png │ ├── AM103L.png │ ├── AM103_Decoder.js │ └── README.md ├── AM104 │ ├── AM104.png │ ├── AM104_Decoder.js │ └── README.md ├── AM107 │ ├── AM107.png │ ├── AM107.py │ ├── AM107_Decoder.js │ └── README.md ├── AM300 │ ├── AM300L.png │ ├── AM300_Decoder.js │ ├── AM307.png │ ├── AM319.png │ └── README.md └── AM300_v2 │ ├── AM300L.png │ ├── AM307.png │ ├── AM307_v2_Decoder.js │ ├── AM307_v2_Encoder.js │ ├── AM308_v2_Decoder.js │ ├── AM308_v2_Encoder.js │ ├── AM319.png │ ├── AM319_hcho_v2_Decoder.js │ ├── AM319_hcho_v2_Encoder.js │ ├── AM319_o3_v2_Decoder.js │ ├── AM319_o3_v2_Encoder.js │ └── README.md ├── AT_Series └── AT101 │ ├── AT101.png │ ├── AT101.py │ ├── AT101_Decoder.js │ └── README.md ├── CT_Series ├── CT10x │ ├── CT101_CT103.png │ ├── CT105.png │ ├── CT10x_Decoder.js │ ├── CT10x_Encoder.js │ └── README.md └── CT3xx │ ├── CT303_CT305.png │ ├── CT310.png │ ├── CT3xx_Decoder.js │ ├── CT3xx_Encoder.js │ └── README.md ├── DS_Series └── DS3604 │ ├── DS3604.png │ ├── DS3604_Decoder.js │ ├── DS3604_Encoder.js │ └── README.md ├── EM_Series ├── EM300_Series │ ├── EM300-CL │ │ ├── EM300-CL.png │ │ ├── EM300-CL_Decoder.js │ │ ├── EM300-CL_Encoder.js │ │ └── README.md │ ├── EM300-DI │ │ ├── EM300-DI.png │ │ ├── EM300-DI.py │ │ ├── EM300-DI_Decoder.js │ │ └── README.md │ ├── EM300-DI_Hall │ │ ├── EM300-DI.png │ │ ├── EM300-DI.py │ │ ├── EM300-DI_Hall_Decoder.js │ │ └── README.md │ ├── EM300-MCS │ │ ├── EM300-MCS.png │ │ ├── EM300-MCS_Cellular.js │ │ ├── EM300-MCS_Decoder.js │ │ └── README.md │ ├── EM300-MLD │ │ ├── EM300-MLD.png │ │ ├── EM300-MLD_Decoder.js │ │ └── README.md │ ├── EM300-SLD │ │ ├── EM300-SLD.png │ │ ├── EM300-SLD_Cellular.js │ │ ├── EM300-SLD_Decoder.js │ │ ├── EM300-SLD_Encoder.js │ │ ├── EM300-ZLD.png │ │ └── README.md │ ├── EM300-TH │ │ ├── EM300-TH.png │ │ ├── EM300-TH_Cellular.js │ │ ├── EM300-TH_Decoder.js │ │ └── README.md │ ├── EM310-TILT │ │ ├── EM310-TILT.png │ │ ├── EM310-TILT_Decoder.js │ │ └── README.md │ ├── EM310-UDL │ │ ├── EM310-UDL.png │ │ ├── EM310-UDL_Decoder.js │ │ ├── EM310-UDL_Encoder.js │ │ └── README.md │ ├── EM320-TH │ │ ├── EM320-TH.png │ │ ├── EM320-TH.py │ │ ├── EM320-TH_Decoder.js │ │ ├── EM320-TH_Encoder.js │ │ └── README.md │ └── EM320-TILT │ │ ├── EM320-TILT.png │ │ ├── EM320-TILT.py │ │ ├── EM320-TILT_Decoder.js │ │ └── README.md ├── EM400_Series │ ├── EM400-MUD │ │ ├── EM400-MUD.png │ │ ├── EM400-MUD_Cellular.js │ │ ├── EM400-MUD_Decoder.js │ │ └── README.md │ ├── EM400-TLD │ │ ├── EM400-TLD.png │ │ ├── EM400-TLD_Cellular.js │ │ ├── EM400-TLD_Decoder.js │ │ └── README.md │ ├── EM400-UDL │ │ ├── EM400-UDL.png │ │ ├── EM400-UDL_Cellular.js │ │ ├── EM400-UDL_Decoder.js │ │ └── README.md │ └── EM410-RDL │ │ ├── EM410-RDL.png │ │ ├── EM410-RDL_Cellular.js │ │ ├── EM410-RDL_Decoder.js │ │ ├── EM410-RDL_Encoder.js │ │ └── README.md └── EM500_Series │ ├── EM500-CO2 │ ├── EM500-CO2.png │ ├── EM500-CO2_Decoder.js │ ├── EM500-CO2_Encoder.js │ └── README.md │ ├── EM500-LGT │ ├── EM500-LGT.png │ ├── EM500-LGT_Decoder.js │ ├── EM500-LGT_Encoder.js │ └── README.md │ ├── EM500-PP │ ├── EM500-PP.png │ ├── EM500-PP_Decoder.js │ └── README.md │ ├── EM500-PT100 │ ├── EM500-PT100.png │ ├── EM500-PT100_Decoder.js │ └── README.md │ ├── EM500-SMTC │ ├── EM500-SMTC.png │ ├── EM500-SMTC_Decoder.js │ └── README.md │ ├── EM500-SWL │ ├── EM500-SWL.png │ ├── EM500-SWL_Decoder.js │ └── README.md │ └── EM500-UDL │ ├── EM500-UDL.png │ ├── EM500-UDL_Decoder.js │ ├── EM500-UDL_Encoder.js │ └── README.md ├── FT_Series └── FT101 │ ├── FT101.png │ ├── FT101_Decoder.js │ └── README.md ├── GS_Series ├── GS101 │ ├── GS101.png │ ├── GS101_Decoder.js │ ├── GS101_Encoder.js │ └── README.md ├── GS301 │ ├── GS301.png │ ├── GS301_Decoder.js │ ├── GS301_Encoder.js │ └── README.md ├── GS524N │ ├── GS524N.png │ ├── GS524N_Decoder.js │ └── README.md └── GS601 │ ├── GS601.png │ ├── GS601_Decoder.js │ ├── GS601_Decoder_pack.js │ ├── GS601_Encoder.js │ ├── GS601_Encoder_pack.js │ └── README.md ├── LICENSE.md ├── LoRaObject.md ├── README.md ├── TS_Series ├── TS101 │ ├── README.md │ ├── TS101.png │ └── TS101_Decoder.js ├── TS201 │ ├── README.md │ ├── TS201.png │ ├── TS201_Decoder.js │ └── TS201_Encoder.js ├── TS201_v2 │ ├── README.md │ ├── TS201_v2.png │ ├── TS201_v2_Decoder.js │ └── TS201_v2_Encoder.js └── TS30x │ ├── README.md │ ├── TS301.png │ ├── TS302.png │ ├── TS30x_Decoder.js │ └── TS30x_Encoder.js ├── UC_Series ├── UC100 │ ├── README.md │ ├── UC100.png │ └── UC100_Decoder.js ├── UC11-N1 │ └── UC11-N1_Decoder.js ├── UC11-T1 │ └── UC11-T1_Decoder.js ├── UC11XX │ ├── UC11.png │ └── UC11XX_Decoder.js ├── UC300 │ ├── README.md │ ├── UC300.png │ ├── UC300.py │ ├── UC300_Cellular.js │ ├── UC300_Decoder.js │ └── UC300_Encoder.js ├── UC3XXX │ └── UC3XXX_Cellular.js ├── UC50x │ ├── README.md │ ├── UC501_v3.png │ ├── UC502_v3.png │ ├── UC50x_Cellular.js │ ├── UC50x_Decoder.js │ └── UC50x_Encoder.js ├── UC51X │ ├── README.md │ ├── UC511_v3.png │ ├── UC512_v3.png │ ├── UC51x_Cellular.js │ ├── UC51x_Decoder.js │ └── UC51x_Encoder.js └── UC521 │ ├── README.md │ ├── UC521.png │ ├── UC521_Decoder.js │ └── UC521_Encoder.js ├── VS_Series ├── VS121 │ ├── README.md │ ├── VS121.png │ └── VS121_Decoder.js ├── VS132 │ ├── README.md │ ├── VS132.png │ ├── VS132.py │ └── VS132_Decoder.js ├── VS13x │ ├── README.md │ ├── VS133.png │ ├── VS135.png │ ├── VS13x_Decoder.js │ └── VS13x_Encoder.js ├── VS330 │ ├── README.md │ ├── VS330.png │ ├── VS330.py │ ├── VS330_Decoder.js │ └── VS330_Encoder.js ├── VS340 │ ├── README.md │ ├── VS340.png │ ├── VS340.py │ ├── VS340_Decoder.js │ └── VS341.png ├── VS350 │ ├── README.md │ ├── VS350.png │ ├── VS350_Decoder.js │ └── VS350_Encoder.js ├── VS351 │ ├── README.md │ ├── VS351.png │ ├── VS351_Battery.png │ └── VS351_Decoder.js ├── VS360 │ ├── README.md │ ├── VS360.png │ ├── VS360_Decoder.js │ └── VS360_Encoder.js ├── VS370 │ ├── README.md │ ├── VS370.png │ ├── VS370_Decoder.js │ └── VS370_Encoder.js └── VS373 │ ├── README.md │ ├── VS373.png │ ├── VS373_Decoder.js │ └── VS373_Encoder.js ├── WS_Series ├── WS101 │ ├── README.md │ ├── WS101.png │ ├── WS101_Decoder.js │ └── WS101_SOS.png ├── WS136&WS156 │ ├── README.md │ ├── WS136.png │ ├── WS136_WS156_Decoder.js │ └── WS156.png ├── WS201 │ ├── README.md │ ├── WS201.png │ ├── WS201_Decoder.js │ └── WS201_Encoder.js ├── WS202 │ ├── README.md │ ├── WS202.png │ ├── WS202_Decoder.js │ └── WS202_Encoder.js ├── WS203 │ ├── README.md │ ├── WS203.png │ └── WS203_Decoder.js ├── WS301 │ ├── README.md │ ├── WS301.png │ └── WS301_Decoder.js ├── WS302 │ ├── README.md │ ├── WS302.png │ ├── WS302_Decoder.js │ └── WS302_Encoder.js ├── WS303 │ ├── README.md │ ├── WS303.png │ ├── WS303.py │ └── WS303_Decoder.js ├── WS50x │ ├── README.md │ ├── WS501_Decoder.js │ ├── WS501_Encoder.js │ ├── WS502_Decoder.js │ ├── WS502_Encoder.js │ ├── WS503_Decoder.js │ ├── WS503_Encoder.js │ └── WS50x.png ├── WS50x_CN │ ├── README.md │ ├── WS501_CN_Decoder.js │ ├── WS501_CN_Encoder.js │ ├── WS502_CN_Decoder.js │ ├── WS502_CN_Encoder.js │ ├── WS503_CN_Decoder.js │ ├── WS503_CN_Encoder.js │ └── WS50x_CN.png ├── WS50x_EU │ ├── README.md │ ├── WS501_EU_Decoder.js │ ├── WS501_EU_Encoder.js │ ├── WS502_EU_Decoder.js │ ├── WS502_EU_Encoder.js │ └── WS50x_EU.png ├── WS50x_US │ ├── README.md │ ├── WS501_US_Decoder.js │ ├── WS501_US_Encoder.js │ └── WS50x_US.png ├── WS51x │ ├── README.md │ ├── WS513.png │ ├── WS513_EU.png │ ├── WS515.png │ ├── WS51x_Decoder.js │ └── WS51x_Encoder.js ├── WS52x │ ├── README.md │ ├── WS523_AU.png │ ├── WS523_CN_16A.png │ ├── WS523_EU.png │ ├── WS523_UK.png │ ├── WS523_US.png │ ├── WS525_CN_10A.png │ ├── WS52x_Decoder.js │ └── WS52x_Encoder.js └── WS558 │ ├── README.md │ ├── WS558.png │ ├── WS558LN.png │ ├── WS558_Decoder.js │ └── WS558_Encoder.js ├── WTS_series ├── README.md ├── WTS305&WTS506_Decoder.js ├── WTS305.png ├── WTS505.png ├── WTS506.png └── WTS_Decoder.js ├── WT_Series ├── WT101 │ ├── README.md │ ├── WT101.png │ ├── WT101_Decoder.js │ └── WT101_Encoder.js ├── WT201 │ ├── README.md │ ├── WT201.png │ ├── WT201_Decoder.js │ └── WT201_Encoder.js ├── WT201_v2 │ ├── README.md │ ├── WT201_v2.png │ ├── WT201_v2_Decoder.js │ └── WT201_v2_Encoder.js └── WT30x │ ├── README.md │ ├── WT30x.png │ ├── WT30x_Decoder.js │ └── WT30x_Encoder.js └── Z_AWS_IoT_Core ├── Lambda-Node18x.js ├── Lambda.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | -------------------------------------------------------------------------------- /AM_Series/AM102/AM102.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM102/AM102.png -------------------------------------------------------------------------------- /AM_Series/AM102/AM102L.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM102/AM102L.png -------------------------------------------------------------------------------- /AM_Series/AM102/AM102_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product AM102 / AM102L 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // TEMPERATURE 36 | else if (channel_id === 0x03 && channel_type === 0x67) { 37 | // ℃ 38 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 39 | i += 2; 40 | 41 | // ℉ 42 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 43 | // i +=2; 44 | } 45 | // HUMIDITY 46 | else if (channel_id === 0x04 && channel_type === 0x68) { 47 | decoded.humidity = bytes[i] / 2; 48 | i += 1; 49 | } 50 | // HISTORY DATA 51 | else if (channel_id === 0x20 && channel_type === 0xce) { 52 | var data = {}; 53 | data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 54 | data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; 55 | data.humidity = bytes[i + 6] / 2; 56 | i += 7; 57 | 58 | decoded.history = decoded.history || []; 59 | decoded.history.push(data); 60 | } else { 61 | break; 62 | } 63 | } 64 | 65 | return decoded; 66 | } 67 | 68 | /* ****************************************** 69 | * bytes to number 70 | ********************************************/ 71 | function readUInt16LE(bytes) { 72 | var value = (bytes[1] << 8) + bytes[0]; 73 | return value & 0xffff; 74 | } 75 | 76 | function readInt16LE(bytes) { 77 | var ref = readUInt16LE(bytes); 78 | return ref > 0x7fff ? ref - 0x10000 : ref; 79 | } 80 | 81 | function readUInt32LE(bytes) { 82 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 83 | return (value & 0xffffffff) >>> 0; 84 | } 85 | 86 | function readInt32LE(bytes) { 87 | var ref = readUInt32LE(bytes); 88 | return ref > 0x7fffffff ? ref - 0x100000000 : ref; 89 | } 90 | -------------------------------------------------------------------------------- /AM_Series/AM102/README.md: -------------------------------------------------------------------------------- 1 | # Ambience Monitoring Sensors - Milesight IoT 2 | 3 | The payload decoder function is applicable to AM102, AM102L 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | | AM102 | AM102L | 8 | | :-----------------: | :-------------------: | 9 | | ![AM102](AM102.png) | ![AM102L](AM102L.png) | 10 | 11 | ## Payload Definition 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :-------------: | :--: | :--: | :----: | ---------------------------------------------- | 15 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 16 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 17 | | Humidity | 0x04 | 0x68 | 1 | humidity(1B)
humidity, unit: %RH | 18 | | Historical Data | 0x20 | 0xCE | 7 | timestamp(4B) + temperature(2B) + humidity(1B) | 19 | 20 | ## Example 21 | 22 | ```json 23 | // 017564 03671801 04686D 24 | { 25 | "battery": 100, 26 | "temperature": 28, 27 | "humidity": 54.5 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /AM_Series/AM103/AM103.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM103/AM103.png -------------------------------------------------------------------------------- /AM_Series/AM103/AM103L.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM103/AM103L.png -------------------------------------------------------------------------------- /AM_Series/AM103/AM103_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product AM103 / AM103L 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // TEMPERATURE 36 | else if (channel_id === 0x03 && channel_type === 0x67) { 37 | // ℃ 38 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 39 | i += 2; 40 | 41 | // ℉ 42 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 43 | // i +=2; 44 | } 45 | // HUMIDITY 46 | else if (channel_id === 0x04 && channel_type === 0x68) { 47 | decoded.humidity = bytes[i] / 2; 48 | i += 1; 49 | } 50 | // CO2 51 | else if (channel_id === 0x07 && channel_type === 0x7d) { 52 | decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); 53 | i += 2; 54 | } 55 | // HISTORY DATA 56 | else if (channel_id === 0x20 && channel_type === 0xce) { 57 | var data = {}; 58 | data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 59 | data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; 60 | data.humidity = bytes[i + 6] / 2; 61 | data.co2 = readUInt16LE(bytes.slice(i + 7, i + 9)); 62 | i += 9; 63 | 64 | decoded.history = decoded.history || []; 65 | decoded.history.push(data); 66 | } else { 67 | break; 68 | } 69 | } 70 | 71 | return decoded; 72 | } 73 | 74 | /* ****************************************** 75 | * bytes to number 76 | ********************************************/ 77 | function readUInt16LE(bytes) { 78 | var value = (bytes[1] << 8) + bytes[0]; 79 | return value & 0xffff; 80 | } 81 | 82 | function readInt16LE(bytes) { 83 | var ref = readUInt16LE(bytes); 84 | return ref > 0x7fff ? ref - 0x10000 : ref; 85 | } 86 | 87 | function readUInt32LE(bytes) { 88 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 89 | return (value & 0xffffffff) >>> 0; 90 | } 91 | 92 | function readInt32LE(bytes) { 93 | var ref = readUInt32LE(bytes); 94 | return ref > 0x7fffffff ? ref - 0x100000000 : ref; 95 | } 96 | -------------------------------------------------------------------------------- /AM_Series/AM103/README.md: -------------------------------------------------------------------------------- 1 | # Ambience Monitoring Sensors - Milesight IoT 2 | 3 | The payload decoder function is applicable to AM103, AM103L 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | | AM103 | AM103L | 8 | | :-----------------: | :-------------------: | 9 | | ![AM103](AM103.png) | ![AM103L](AM103L.png) | 10 | 11 | ## Payload Definition 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :-------------: | :--: | :--: | :----: | -------------------------------------------------------- | 15 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 16 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 17 | | Humidity | 0x04 | 0x68 | 1 | humidity(1B)
humidity, unit: %RH | 18 | | CO2 | 0x07 | 0x7D | 2 | co2(2B)
co2, unit: ppm | 19 | | Historical Data | 0x20 | 0xCE | 9 | timestamp(4B) + temperature(2B) + humidity(1B) + co2(2B) | 20 | 21 | ## Example 22 | 23 | ```json 24 | // 017564 03671801 04686D 077DC501 25 | { 26 | "battery": 100, 27 | "co2": 453, 28 | "temperature": 28, 29 | "humidity": 54.5 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /AM_Series/AM104/AM104.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM104/AM104.png -------------------------------------------------------------------------------- /AM_Series/AM104/AM104_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product AM104 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // TEMPERATURE 36 | else if (channel_id === 0x03 && channel_type === 0x67) { 37 | // ℃ 38 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 39 | i += 2; 40 | 41 | // ℉ 42 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 43 | // i +=2; 44 | } 45 | // HUMIDITY 46 | else if (channel_id === 0x04 && channel_type === 0x68) { 47 | decoded.humidity = bytes[i] / 2; 48 | i += 1; 49 | } 50 | // PIR 51 | else if (channel_id === 0x05 && channel_type === 0x6a) { 52 | decoded.activity = readUInt16LE(bytes.slice(i, i + 2)); 53 | i += 2; 54 | } 55 | // LIGHT 56 | else if (channel_id === 0x06 && channel_type === 0x65) { 57 | decoded.illumination = readUInt16LE(bytes.slice(i, i + 2)); 58 | decoded.infrared_and_visible = readUInt16LE(bytes.slice(i + 2, i + 4)); 59 | decoded.infrared = readUInt16LE(bytes.slice(i + 4, i + 6)); 60 | i += 6; 61 | } else { 62 | break; 63 | } 64 | } 65 | 66 | return decoded; 67 | } 68 | 69 | /* ****************************************** 70 | * bytes to number 71 | ********************************************/ 72 | function readUInt16LE(bytes) { 73 | var value = (bytes[1] << 8) + bytes[0]; 74 | return value & 0xffff; 75 | } 76 | 77 | function readInt16LE(bytes) { 78 | var ref = readUInt16LE(bytes); 79 | return ref > 0x7fff ? ref - 0x10000 : ref; 80 | } 81 | -------------------------------------------------------------------------------- /AM_Series/AM104/README.md: -------------------------------------------------------------------------------- 1 | # Ambience Monitoring Sensors - Milesight IoT 2 | 3 | The payload decoder function is applicable to AM104 (AM100). 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![AM104](AM104.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :----------: | :--: | :--: | :----: | -------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 15 | | Humidity | 0x04 | 0x68 | 1 | humidity(1B)
humidity, unit: %RH | 16 | | Activity | 0x05 | 0x6A | 2 | activity(2B) | 17 | | Illumination | 0x06 | 0x65 | 6 | illumination(6B)
illumination, unit: lux | 18 | 19 | ## Example 20 | 21 | ```json 22 | // 01755C 03673401 046865 056A4900 06651C0079001400 23 | { 24 | "battery": 92, 25 | "temperature": 30.8, 26 | "humidity": 50.5, 27 | "activity": 73, 28 | "illumination": 28, 29 | "infrared": 20, 30 | "infrared_and_visible": 121 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /AM_Series/AM107/AM107.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM107/AM107.png -------------------------------------------------------------------------------- /AM_Series/AM107/AM107.py: -------------------------------------------------------------------------------- 1 | #Function to parse the Payload, typedata is the digits designing the data, size the length of the value to retrieve 2 | def decode_payload(payload, typedata , size): 3 | 4 | position=payload.find(typedata) 5 | 6 | if position==-1: 7 | return None 8 | 9 | index =position + len(typedata) # len(obj) 10 | data = payload[index:index+(size*2)] 11 | chunks = [data[i-2:i]for i in range(len(data),0, -2)] 12 | result="" 13 | for hex in chunks: 14 | result+=hex 15 | return result 16 | 17 | 18 | #Function to retrieve all the values of the Sensor 19 | def data_payload(payload): 20 | if len(payload)<56: 21 | 22 | return None 23 | 24 | battery=decode_payload(payload,"0175",1) 25 | 26 | if battery!=None: 27 | battery=int(battery,16) 28 | 29 | hum = int(decode_payload(payload,"0468",1), 16) 30 | temp = int(decode_payload(payload,"0367",2), 16) 31 | co2 = int(decode_payload(payload,"077d",2),16) 32 | activity =int(decode_payload(payload,"056a",2),16) 33 | illumination=decode_payload(payload,"0665",6) 34 | lum,vis,infra = illumination[0:4], illumination[4:8] ,illumination[8:] 35 | lum,vis,infra = int(lum, 16),int(vis,16),int(infra,16) 36 | tvoc=int(decode_payload(payload,"087d",2),16) 37 | barometric=int(decode_payload(payload,"0973",2),16) 38 | 39 | return battery, int(temp*0.1),int(hum*0.5),co2,activity, lum, vis,infra,tvoc,barometric*0.1 40 | 41 | 42 | 43 | #Payload sans Batterie 44 | payload = "03671f0104686206658a003f025b00056a0000077dc402087d100209736f27" 45 | 46 | #Payload avec Batterie 47 | #payload = "01754b03671c010468550665a602370a5401056a1c00077d8001087dbd0009735927" 48 | 49 | battery, temp,hum,co2, activity,lum, vis,infra,tvoc, barometric = data_payload(payload) 50 | 51 | print(battery,temp,hum,co2,activity,lum, vis,infra, tvoc ,barometric) -------------------------------------------------------------------------------- /AM_Series/AM107/AM107_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product AM107 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // TEMPERATURE 36 | else if (channel_id === 0x03 && channel_type === 0x67) { 37 | // ℃ 38 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 39 | i += 2; 40 | 41 | // ℉ 42 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 43 | // i +=2; 44 | } 45 | // HUMIDITY 46 | else if (channel_id === 0x04 && channel_type === 0x68) { 47 | decoded.humidity = bytes[i] / 2; 48 | i += 1; 49 | } 50 | // PIR 51 | else if (channel_id === 0x05 && channel_type === 0x6a) { 52 | decoded.activity = readUInt16LE(bytes.slice(i, i + 2)); 53 | i += 2; 54 | } 55 | // LIGHT 56 | else if (channel_id === 0x06 && channel_type === 0x65) { 57 | decoded.illumination = readUInt16LE(bytes.slice(i, i + 2)); 58 | decoded.infrared_and_visible = readUInt16LE(bytes.slice(i + 2, i + 4)); 59 | decoded.infrared = readUInt16LE(bytes.slice(i + 4, i + 6)); 60 | i += 6; 61 | } 62 | // CO2 63 | else if (channel_id === 0x07 && channel_type === 0x7d) { 64 | decoded.co2 = readUInt16LE(bytes.slice(i, i + 2)); 65 | i += 2; 66 | } 67 | // TVOC 68 | else if (channel_id === 0x08 && channel_type === 0x7d) { 69 | decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2)); 70 | i += 2; 71 | } 72 | // PRESSURE 73 | else if (channel_id === 0x09 && channel_type === 0x73) { 74 | decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; 75 | i += 2; 76 | } else { 77 | break; 78 | } 79 | } 80 | 81 | return decoded; 82 | } 83 | 84 | /* ****************************************** 85 | * bytes to number 86 | ********************************************/ 87 | function readUInt16LE(bytes) { 88 | var value = (bytes[1] << 8) + bytes[0]; 89 | return value & 0xffff; 90 | } 91 | 92 | function readInt16LE(bytes) { 93 | var ref = readUInt16LE(bytes); 94 | return ref > 0x7fff ? ref - 0x10000 : ref; 95 | } 96 | -------------------------------------------------------------------------------- /AM_Series/AM107/README.md: -------------------------------------------------------------------------------- 1 | # Ambience Monitoring Sensors - Milesight IoT 2 | 3 | The payload decoder function is applicable toAM107(AM102). 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![AM107](AM107.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :----------: | :--: | :--: | :----: | -------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 15 | | Humidity | 0x04 | 0x68 | 1 | humidity(1B)
humidity, unit: %RH | 16 | | Activity | 0x05 | 0x6A | 2 | activity(2B) | 17 | | Illumination | 0x06 | 0x65 | 6 | illumination(6B)
illumination, unit: lux | 18 | | CO2 | 0x07 | 0x7D | 2 | co2(2B)
co2, unit: ppm | 19 | | tVOC | 0x08 | 0x7D | 2 | tvoc(2B)
tvoc, unit: ppb | 20 | | Pressure | 0x09 | 0x73 | 2 | pressure(2B)
pressure, unit: hPa | 21 | 22 | ## Example 23 | 24 | ```json 25 | // 01755C 03673401 046865 056A4900 06651C0079001400 077DE704 087D0700 09733F27 26 | { 27 | "battery": 92, 28 | "temperature": 30.8, 29 | "humidity": 50.5, 30 | "activity": 73, 31 | "illumination": 28, 32 | "infrared": 20, 33 | "infrared_and_visible": 121, 34 | "co2": 1255, 35 | "tvoc": 7, 36 | "pressure": 1004.7 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /AM_Series/AM300/AM300L.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM300/AM300L.png -------------------------------------------------------------------------------- /AM_Series/AM300/AM307.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM300/AM307.png -------------------------------------------------------------------------------- /AM_Series/AM300/AM319.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM300/AM319.png -------------------------------------------------------------------------------- /AM_Series/AM300_v2/AM300L.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM300_v2/AM300L.png -------------------------------------------------------------------------------- /AM_Series/AM300_v2/AM307.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM300_v2/AM307.png -------------------------------------------------------------------------------- /AM_Series/AM300_v2/AM319.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AM_Series/AM300_v2/AM319.png -------------------------------------------------------------------------------- /AT_Series/AT101/AT101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/AT_Series/AT101/AT101.png -------------------------------------------------------------------------------- /AT_Series/AT101/AT101.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | def decodeBytes(bytes): 5 | print("bytes:", bytes.hex()) 6 | decoded = {} 7 | 8 | i = 0 9 | while i < len(bytes): 10 | channel_id = bytes[i] 11 | channel_type = bytes[i + 1] 12 | i += 2 13 | 14 | # BATTERY 15 | if channel_id == 0x01 and channel_type == 0x75: 16 | decoded["battery"] = bytes[i] 17 | i += 1 18 | # TEMPERATURE 19 | elif channel_id == 0x03 and channel_type == 0x67: 20 | decoded["temperature"] = int.from_bytes(bytes[i : i + 2], "little", signed=False) / 10 21 | i += 2 22 | # LOCATION 23 | elif (channel_id == 0x04 or channel_id == 0x84) and channel_type == 0x88: 24 | decoded["latitude"] = int.from_bytes(bytes[i : i + 4], "little", signed=True) / 1000000 25 | decoded["longitude"] = int.from_bytes(bytes[i + 4 : i + 8], "little", signed=True) / 1000000 26 | status = bytes[i + 8] 27 | decoded["motion_status"] = ["unknown", "start", "moving", "stop"][status & 0x0F] 28 | decoded["geofence_status"] = ["inside", "outside", "unset", "unknown"][status >> 4] 29 | i += 9 30 | # POSITION 31 | elif channel_id == 0x05 and channel_type == 0x00: 32 | decoded["longitude"] = "normal" if bytes[i] == 0 else "tilt" 33 | i += 1 34 | # Wi-Fi SCAN RESULT 35 | elif channel_id == 0x06 and channel_type == 0xD9: 36 | wifi = {} 37 | wifi["frame"] = bytes[i] 38 | wifi["mac"] = ":".join([hex(x)[2:].zfill(2) for x in bytes[i + 1 : i + 7]]) 39 | wifi["rssi"] = (bytes[i + 7] ^ 128) - 128 40 | i += 8 41 | 42 | if decoded.get("wifi") is None: 43 | decoded["wifi"] = [] 44 | decoded["wifi"].append(wifi) 45 | # TAMPER STATUS 46 | elif channel_id == 0x07 and channel_type == 0x00: 47 | decoded["tamper_status"] = "install" if bytes[i] == 0 else "uninstall" 48 | i += 1 49 | # TEMPERATURE WITH ABNORMAL 50 | elif channel_id == 0x83 and channel_type == 0x67: 51 | decoded["temperature"] = int.from_bytes(bytes[i : i + 2], "little", signed=False) / 10 52 | decoded["temperature_abnormal"] = "normal" if bytes[i + 2] == 0 else "abnormal" 53 | i += 3 54 | # HISTORICAL LOCATION 55 | elif channel_id == 0x20 and channel_type == 0xCE: 56 | data = {} 57 | data["timestamp"] = int.from_bytes(bytes[i : i + 4], "little", signed=False) 58 | data["longitude"] = int.from_bytes(bytes[i + 4 : i + 8], "little", signed=True) / 1000000 59 | data["latitude"] = int.from_bytes(bytes[i + 8 : i + 12], "little", signed=True) / 1000000 60 | i += 12 61 | 62 | if decoded.get("history") is None: 63 | decoded["history"] = [] 64 | decoded["history"].append(data) 65 | else: 66 | break 67 | 68 | print(decoded) 69 | return decoded 70 | 71 | 72 | def decodePayload(payload, encoded="base64"): 73 | if encoded == "base64": 74 | bytes = binascii.a2b_base64(payload) 75 | elif encoded == "hex": 76 | bytes = binascii.a2b_hex(payload) 77 | else: 78 | print("unsupport encode type") 79 | 80 | return decodeBytes(bytes) 81 | 82 | 83 | if __name__ == "__main__": 84 | decodePayload("AXUBA2cGAQUAAQSIJrgDGQISAAAA", "base64") 85 | decodePayload("01756403671b01050000048836bf7701f000090722", "hex") 86 | -------------------------------------------------------------------------------- /AT_Series/AT101/README.md: -------------------------------------------------------------------------------- 1 | # Outdoor Asset Tracker - Milesight IoT 2 | 3 | The payload decoder function is applicable to AT101. 4 | 5 | For more detailed information, please visit [Milesight official website](https://www.milesight-iot.com). 6 | 7 | ![AT101](AT101.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :------------------: | :--: | :--: | :----: | ----------------------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 15 | | Location | 0x04 | 0x88 | 9 | latitude(4B) + longitude(4B) + motion_status(1B) | 16 | | Position | 0x05 | 0x00 | 1 | position(1B)
position, values: (0: normal, 1: tilt) | 17 | | Wifi Scan | 0x06 | 0xD9 | 9 | ID(1B) + MAC(6B) + RSSI(1B) + motion_status(1B) | 18 | | Tamper Status | 0x07 | 0x00 | 1 | tamper_status(1B)
tamper_status, values: (0: install, 1: uninstall) | 19 | | Temperature Abnormal | 0x83 | 0x67 | 3 | temperature(2B) + temperature_abnormal(1B) | 20 | | History Data | 0x20 | 0xCE | 12 | timestamp(4B) + longitude(4B) + latitude(4B) | 21 | 22 | motion_status 23 | 24 | | BITS | 7 - 4 | 3 - 0 | 25 | | :---------: | :------------------------------------------------------------- | :---------------------------------------------------------------------- | 26 | | DESCRIPTION | Geofence Status, (0: inside, 1: outside, 2: unset, 3: unknown) | Motion Status, (0: unknown, 1: start moving, 2: moving, 3: stop moving) | 27 | 28 | ## Example 29 | 30 | ```json 31 | // 017564 03671B01 050000 048836BF7701F000090722 32 | { 33 | "battery": 100, 34 | "geofence_status": "unset", 35 | "longitude": 118.030576, 36 | "latitude": 24.62495, 37 | "motion_status": "moving", 38 | "position": "normal", 39 | "temperature": 28.3 40 | } 41 | 42 | // 017564 03671B01 050001 06D9081CC316222DF9C302 06D90824E124F6A667B602 06D90824E124F54DE3BC02 06D90824E124F57971B202 06D90824E124F319A8C802 43 | { 44 | "battery": 100, 45 | "motion_status": "moving", 46 | "position": "tilt", 47 | "temperature": 28.3, 48 | "wifi": [ 49 | { 50 | "group": 8, 51 | "mac": "1c:c3:16:22:2d:f9", 52 | "motion_status": "moving", 53 | "rssi": -61 54 | }, 55 | { 56 | "group": 8, 57 | "mac": "24:e1:24:f6:a6:67", 58 | "motion_status": "moving", 59 | "rssi": -74 60 | }, 61 | { 62 | "group": 8, 63 | "mac": "24:e1:24:f5:4d:e3", 64 | "motion_status": "moving", 65 | "rssi": -68 66 | }, 67 | { 68 | "group": 8, 69 | "mac": "24:e1:24:f5:79:71", 70 | "motion_status": "moving", 71 | "rssi": -78 72 | }, 73 | { 74 | "group": 8, 75 | "mac": "24:e1:24:f3:19:a8", 76 | "motion_status": "moving", 77 | "rssi": -56 78 | } 79 | ], 80 | "wifi_scan_result": "finish" 81 | } 82 | ``` 83 | -------------------------------------------------------------------------------- /CT_Series/CT10x/CT101_CT103.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/CT_Series/CT10x/CT101_CT103.png -------------------------------------------------------------------------------- /CT_Series/CT10x/CT105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/CT_Series/CT10x/CT105.png -------------------------------------------------------------------------------- /CT_Series/CT10x/README.md: -------------------------------------------------------------------------------- 1 | # Smart Current Transformer - Milesight IoT 2 | 3 | The payload decoder function is applicable to CT101 / CT103 / CT105. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/ct10x). 6 | 7 | | CT101 / CT103 | CT105 | 8 | | :-----------------------------: | :-----------------: | 9 | | ![CT101_CT103](CT101_CT103.png) | ![CT105](CT105.png) | 10 | 11 | ## Payload Definition 12 | 13 | ### Attributes 14 | 15 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 16 | | :--------------: | :--: | :--: | :----: | -------------------- | 17 | | IPSO Version | 0xFF | 0x01 | 1 | ipso_version(1B) | 18 | | Device Status | 0xFF | 0x0B | 1 | device_status(1B) | 19 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 20 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 21 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 22 | | LoRaWAN Class | 0xFF | 0x0F | 1 | lorawan_class(1B) | 23 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 24 | | Reset Event | 0xFF | 0xFE | 1 | reset_event(1B) | 25 | 26 | ### Telemetry 27 | 28 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 29 | | :---------------: | :--: | :--: | :----: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 30 | | Total Current | 0x03 | 0x97 | 4 | total_ah(4B)
total_ah, read: uint32/100, unit: Ah | 31 | | Current | 0x04 | 0x98 | 2 | current(2B)
current, read: uint16/100, unit: A | 32 | | Temperature | 0x09 | 0x67 | 2 | temperature(2B)
temperature, read: int16/10, unit: ℃ | 33 | | Current Alarm | 0x84 | 0x98 | 7 | current_max(2B) + current_min(2B) + current(2B) + alarm(1B)
alarm, values: (1: threshold alarm, 2: threshold alarm release, 4: over range alarm, 8: over range alarm release) | 34 | | Temperature Alarm | 0x89 | 0x67 | 3 | temperature(2B) + temperature_alarm(1B)
temperature, read: int16/10, unit: ℃
temperature_alarm, values: (0: threshold alarm release, 1: threshold alarm) | 35 | 36 | ## Example 37 | 38 | ```json 39 | // FF0BFF FF0101 FF166746D38802580000 FF090100 FF0A0101 FF0F00 40 | { 41 | "device_status": "on", 42 | "firmware_version": "v1.1", 43 | "hardware_version": "v1.0", 44 | "ipso_version": "v0.1", 45 | "lorawan_class": "Class A", 46 | "sn": "6746d38802580000" 47 | } 48 | 49 | // 039710270000 50 | { 51 | "total_current": 100 52 | } 53 | 54 | // 0498B80B00000000 55 | { 56 | "current": 30 57 | } 58 | 59 | // 0498FFFF 60 | { 61 | "current_sensor_status": "read failed" 62 | } 63 | 64 | // 8498B80BD007C40905 65 | { 66 | "current": 25, 67 | "current_alarm": { 68 | "current_over_range_alarm": "yes", 69 | "current_over_range_alarm_release": "no", 70 | "current_threshold_alarm": "yes", 71 | "current_threshold_alarm_release": "no" 72 | }, 73 | "current_max": 30, 74 | "current_min": 20 75 | } 76 | ``` 77 | -------------------------------------------------------------------------------- /CT_Series/CT3xx/CT303_CT305.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/CT_Series/CT3xx/CT303_CT305.png -------------------------------------------------------------------------------- /CT_Series/CT3xx/CT310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/CT_Series/CT3xx/CT310.png -------------------------------------------------------------------------------- /DS_Series/DS3604/DS3604.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/DS_Series/DS3604/DS3604.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-CL/EM300-CL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM300-CL/EM300-CL.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-CL/README.md: -------------------------------------------------------------------------------- 1 | # Capacitive Level Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM300-CL. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM300-CL](EM300-CL.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :--------------: | :--: | :--: | :----: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Liquid Status | 0x03 | 0xED | 1 | liquid(1B)
liquid, values: (0: uncalibrated, 1: full, 2: critical liquid level alert, 0xff: error) | 15 | | Calibrate Result | 0x04 | 0xEE | 1 | calibrate_result(1B)
calibrate_result, values: (0: failed, 1: success) | 16 | | Liquid Alarm | 0x83 | 0xED | 2 | liquid(1B) + alarm(1B)
liquid, values: (0: uncalibrated, 1: full, 2: critical liquid level alert, 0xff: error)
alarm: (0: critical liquid level alarm release, 1: critical liquid level alarm ) | 17 | 18 | ## Example 19 | 20 | ```json 21 | // 017564 03ED00 22 | { 23 | "battery": 100, 24 | "liquid": "uncalibrated" 25 | } 26 | 27 | // 03ED01 28 | { 29 | "liquid": "full" 30 | } 31 | 32 | // 03ED02 33 | { 34 | "liquid": "critical liquid level alert" 35 | } 36 | 37 | // 03EDFF 38 | { 39 | "liquid": "error" 40 | } 41 | 42 | // 83ED0100 43 | { 44 | "liquid": "full", 45 | "liquid_alarm": "critical liquid level alarm release" 46 | } 47 | 48 | // 83ED0201 49 | { 50 | "liquid": "critical liquid level alert", 51 | "liquid_alarm": "critical liquid level alarm" 52 | } 53 | 54 | // 04EE01 55 | { 56 | "calibration_result": "success" 57 | } 58 | 59 | // 04EE00 60 | { 61 | "calibration_result": "failed" 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-DI/EM300-DI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM300-DI/EM300-DI.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-DI/EM300-DI.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | def decodeBytes(bytes): 5 | print("bytes:", bytes.hex()) 6 | decoded = {} 7 | 8 | i = 0 9 | while i < len(bytes): 10 | channel_id = bytes[i] 11 | channel_type = bytes[i+1] 12 | i += 2 13 | 14 | # BATTERY 15 | if channel_id == 0x01 and channel_type == 0x75: 16 | decoded['battery'] = bytes[i] 17 | i += 1 18 | # TEMPERATURE 19 | elif channel_id == 0x03 and channel_type == 0x67: 20 | # ℃ 21 | decoded['temperature'] = int.from_bytes(bytes[i: i + 2], 'little', signed=True) / 10 22 | i += 2 23 | 24 | # ℉ 25 | # decoded['temperature'] = int.from_bytes(bytes[i: i + 2], 'little', signed=True) / 10 * 1.8 + 32 26 | # i +=2 27 | # HUMIDITY 28 | elif channel_id == 0x04 and channel_type == 0x68: 29 | decoded['humidity'] = bytes[i] / 2 30 | i += 1 31 | # GPIO 32 | elif channel_id == 0x05 and channel_type == 0x00: 33 | decoded['gpio'] = bytes[i] 34 | i += 1 35 | # PULSE COUNTER 36 | elif channel_id == 0x05 and channel_type == 0xc8: 37 | decoded['pulse'] = int.from_bytes(bytes[i: i + 4], 'False', signed=False) 38 | i += 4 39 | # HISTROY 40 | elif channel_id == 0x20 and channel_type == 0xce: 41 | # maybe not historical raw data 42 | if len(bytes[i:]) < 12: 43 | break 44 | 45 | point = {} 46 | point['timestamp'] = int.from_bytes(bytes[i: i + 4], 'little', signed=False) 47 | point['temperature'] = int.from_bytes(bytes[i + 4: i + 6], 'little', signed=True) / 10 48 | point['humidity'] = bytes[i + 6] / 2 49 | 50 | # GPIO or Pulse 51 | mode = bytes[i + 7] 52 | if mode == 1: 53 | point['gpio'] = bytes[i + 8] 54 | elif mode == 2: 55 | point['pulse'] = int.from_bytes(bytes[i + 9: i + 13], 'little', signed=False) 56 | 57 | if decoded.get('history') is None: 58 | decoded['history'] = [] 59 | 60 | decoded['history'].append(point) 61 | 62 | i += 13 63 | else: 64 | break 65 | 66 | print(decoded) 67 | return decoded 68 | 69 | 70 | def decodePayload(payload, encoded="base64"): 71 | if encoded == "base64": 72 | bytes = binascii.a2b_base64(payload) 73 | elif encoded == "hex": 74 | bytes = binascii.a2b_hex(payload) 75 | else: 76 | print("unsupport encode type") 77 | 78 | return decodeBytes(bytes) 79 | 80 | 81 | if __name__ == '__main__': 82 | decodePayload("AXVcA2c0AQRoZQ==", "base64") 83 | decodePayload("01755C0367340104686520CE9E74466310015D020000010000", "hex") 84 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-DI_Hall/EM300-DI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM300-DI_Hall/EM300-DI.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-DI_Hall/EM300-DI.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | def decodeBytes(bytes): 5 | print("bytes:", bytes.hex()) 6 | decoded = {} 7 | 8 | i = 0 9 | while i < len(bytes): 10 | channel_id = bytes[i] 11 | channel_type = bytes[i+1] 12 | i += 2 13 | 14 | # BATTERY 15 | if channel_id == 0x01 and channel_type == 0x75: 16 | decoded['battery'] = bytes[i] 17 | i += 1 18 | # TEMPERATURE 19 | elif channel_id == 0x03 and channel_type == 0x67: 20 | # ℃ 21 | decoded['temperature'] = int.from_bytes(bytes[i: i + 2], 'little', signed=True) / 10 22 | i += 2 23 | 24 | # ℉ 25 | # decoded['temperature'] = int.from_bytes(bytes[i: i + 2], 'little', signed=True) / 10 * 1.8 + 32 26 | # i +=2 27 | # HUMIDITY 28 | elif channel_id == 0x04 and channel_type == 0x68: 29 | decoded['humidity'] = bytes[i] / 2 30 | i += 1 31 | # GPIO 32 | elif channel_id == 0x05 and channel_type == 0x00: 33 | decoded['gpio'] = bytes[i] 34 | i += 1 35 | # PULSE COUNTER 36 | elif channel_id == 0x05 and channel_type == 0xc8: 37 | decoded['pulse'] = int.from_bytes(bytes[i: i + 4], 'False', signed=False) 38 | i += 4 39 | # HISTROY 40 | elif channel_id == 0x20 and channel_type == 0xce: 41 | # maybe not historical raw data 42 | if len(bytes[i:]) < 12: 43 | break 44 | 45 | point = {} 46 | point['timestamp'] = int.from_bytes(bytes[i: i + 4], 'little', signed=False) 47 | point['temperature'] = int.from_bytes(bytes[i + 4: i + 6], 'little', signed=True) / 10 48 | point['humidity'] = bytes[i + 6] / 2 49 | 50 | # GPIO or Pulse 51 | mode = bytes[i + 7] 52 | if mode == 1: 53 | point['gpio'] = bytes[i + 8] 54 | elif mode == 2: 55 | point['pulse'] = int.from_bytes(bytes[i + 9: i + 13], 'little', signed=False) 56 | 57 | if decoded.get('history') is None: 58 | decoded['history'] = [] 59 | 60 | decoded['history'].append(point) 61 | 62 | i += 13 63 | else: 64 | break 65 | 66 | print(decoded) 67 | return decoded 68 | 69 | 70 | def decodePayload(payload, encoded="base64"): 71 | if encoded == "base64": 72 | bytes = binascii.a2b_base64(payload) 73 | elif encoded == "hex": 74 | bytes = binascii.a2b_hex(payload) 75 | else: 76 | print("unsupport encode type") 77 | 78 | return decodeBytes(bytes) 79 | 80 | 81 | if __name__ == '__main__': 82 | decodePayload("AXVcA2c0AQRoZQ==", "base64") 83 | decodePayload("01755C0367340104686520CE9E74466310015D020000010000", "hex") 84 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-MCS/EM300-MCS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM300-MCS/EM300-MCS.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-MCS/EM300-MCS_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM300-MCS 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // TEMPERATURE 36 | else if (channel_id === 0x03 && channel_type === 0x67) { 37 | // ℃ 38 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 39 | i += 2; 40 | 41 | // ℉ 42 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 43 | // i +=2; 44 | } 45 | // HUMIDITY 46 | else if (channel_id === 0x04 && channel_type === 0x68) { 47 | decoded.humidity = bytes[i] / 2; 48 | i += 1; 49 | } 50 | // MAGNET STATUS 51 | else if (channel_id === 0x06 && channel_type === 0x00) { 52 | decoded.magnet_status = bytes[i] === 0 ? "close" : "open"; 53 | i += 1; 54 | } 55 | // TEMPERATURE、HUMIDITY & MAGNET STATUS HISTROY 56 | else if (channel_id === 0x20 && channel_type === 0xce) { 57 | var point = {}; 58 | point.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 59 | point.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; 60 | point.humidity = bytes[i + 6] / 2; 61 | point.magnet_status = bytes[i + 7] === 0 ? "close" : "open"; 62 | 63 | decoded.history = decoded.history || []; 64 | decoded.history.push(point); 65 | i += 8; 66 | } else { 67 | break; 68 | } 69 | } 70 | 71 | return decoded; 72 | } 73 | 74 | /* ****************************************** 75 | * bytes to number 76 | ********************************************/ 77 | function readUInt16LE(bytes) { 78 | var value = (bytes[1] << 8) + bytes[0]; 79 | return value & 0xffff; 80 | } 81 | 82 | function readInt16LE(bytes) { 83 | var ref = readUInt16LE(bytes); 84 | return ref > 0x7fff ? ref - 0x10000 : ref; 85 | } 86 | 87 | function readUInt32LE(bytes) { 88 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 89 | return value & 0xffffffff; 90 | } 91 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-MCS/README.md: -------------------------------------------------------------------------------- 1 | # Magnetic Contact Switch - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM300-MCS. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM300-MCS](EM300-MCS.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :-------------: | :--: | :--: | :----: | ------------------------------------------------------------------ | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery: unit: % | 14 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 15 | | Humidity | 0x04 | 0x68 | 1 | humidity(1B)
humidity, unit: %RH | 16 | | Magnet Status | 0x06 | 0x00 | 1 | magnet_status(1B)
magnet_status, values: (0: close, 1: open) | 17 | | Historical Data | 0x20 | 0XCE | 8 | timestamp(4B) + temperature(2B) + humidity(1B) + magnet_status(1B) | 18 | 19 | ## Example 20 | 21 | ```json 22 | // 01755C 03673401 046865 060001 23 | { 24 | "battery": 92, 25 | "temperature": 30.8, 26 | "humidity": 50.5, 27 | "magnet_status": "open" 28 | } 29 | 30 | // 20CE9E74466310015D01 31 | { 32 | "history": [ 33 | { 34 | "magnet_status": "open", 35 | "humidity": 46.5, 36 | "temperature": 27.2, 37 | "timestamp": 1665561758 38 | } 39 | ] 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-MLD/EM300-MLD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM300-MLD/EM300-MLD.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-MLD/EM300-MLD_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM300-MLD 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // LEAKAGE STATUS 36 | else if (channel_id === 0x05 && channel_type === 0x00) { 37 | decoded.leakage_status = bytes[i] === 0 ? "normal" : "leak"; 38 | i += 1; 39 | } 40 | // TEMPERATURE, HUMIDITY & LEAKAGE STATUS HISTROY 41 | else if (channel_id === 0x20 && channel_type === 0xce) { 42 | var point = {}; 43 | point.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 44 | point.leakage_status = bytes[i + 7] === 0 ? "normal" : "leak"; 45 | 46 | decoded.history = decoded.history || []; 47 | decoded.history.push(point); 48 | i += 8; 49 | } else { 50 | break; 51 | } 52 | } 53 | 54 | return decoded; 55 | } 56 | 57 | /* ****************************************** 58 | * bytes to number 59 | ********************************************/ 60 | function readUInt16LE(bytes) { 61 | var value = (bytes[1] << 8) + bytes[0]; 62 | return value & 0xffff; 63 | } 64 | 65 | function readInt16LE(bytes) { 66 | var ref = readUInt16LE(bytes); 67 | return ref > 0x7fff ? ref - 0x10000 : ref; 68 | } 69 | 70 | function readUInt32LE(bytes) { 71 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 72 | return (value & 0xffffffff) >>> 0; 73 | } 74 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-MLD/README.md: -------------------------------------------------------------------------------- 1 | # Membrane Leak Detection Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM300-MLD. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM300-MLD](EM300-MLD.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :-------------: | :--: | :--: | :----: | ------------------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Leakage Status | 0x06 | 0x00 | 1 | leakage_status(1B)
leakage_status, values:(0: normal, 1: leak) | 15 | | Historical Data | 0x20 | 0XCE | 8 | timestamp(4B) + temperature(2B) + humidity(1B) + leakage_status(1B) | 16 | 17 | ## Example 18 | 19 | ```json 20 | // 01755C 050000 21 | { 22 | "battery": 92, 23 | "leakage_status": "normal" 24 | } 25 | 26 | // 20CE9E74466300000001 27 | { 28 | "history": [ 29 | { 30 | "leakage_status": "leak", 31 | "timestamp": 1665561758 32 | } 33 | ] 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-SLD/EM300-SLD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM300-SLD/EM300-SLD.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-SLD/EM300-ZLD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM300-SLD/EM300-ZLD.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-SLD/README.md: -------------------------------------------------------------------------------- 1 | # Spot Leak Detection Sensor / Zone Leak Detection Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM300-SLD and EM300-ZLD. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | | EM300-SLD | EM300-ZLD | 8 | | :-------------------------: | :-------------------------: | 9 | | ![EM300-SLD](EM300-SLD.png) | ![EM300-ZLD](EM300-ZLD.png) | 10 | 11 | ## Payload Definition 12 | 13 | ### Attribute 14 | 15 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 16 | | :----------------: | :--: | :--: | :----: | -------------------- | 17 | | Protocol Version | 0xFF | 0x01 | 1 | protocol_version(1B) | 18 | | Power Status | 0xFF | 0x0B | 1 | power_status(1B) | 19 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 20 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 21 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 22 | | LoRaWAN Class Type | 0xFF | 0x0F | 1 | lorawan_class(1B) | 23 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 24 | 25 | ### Telemetry 26 | 27 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 28 | | :-------------: | :--: | :--: | :----: | -------------------------------------------------------------------- | 29 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 30 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 31 | | Humidity | 0x04 | 0x68 | 1 | humidity(1B)
humidity, unit: %RH | 32 | | Leakage Status | 0x05 | 0x00 | 1 | leakage_status(1B)
leakage_status, values: (0: normal, 1: leak) | 33 | | Historical Data | 0x20 | 0XCE | 8 | timestamp(4B) + temperature(2B) + humidity(1B) + leakage_status(1B) | 34 | 35 | ## Example 36 | 37 | ```json 38 | // 01755C 03673401 046865 050000 39 | { 40 | "battery": 92, 41 | "temperature": 30.8, 42 | "humidity": 50.5, 43 | "leakage_status": "normal" 44 | } 45 | 46 | // 20CE9E74466310015D01 47 | { 48 | "history": [ 49 | { 50 | "temperature": 27.2, 51 | "humidity": 46.5, 52 | "leakage_status": "leak", 53 | "timestamp": 1665561758 54 | } 55 | ] 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-TH/EM300-TH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM300-TH/EM300-TH.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-TH/EM300-TH_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM300-TH 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // TEMPERATURE 37 | else if (channel_id === 0x03 && channel_type === 0x67) { 38 | // ℃ 39 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 40 | i += 2; 41 | 42 | // ℉ 43 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 44 | // i +=2; 45 | } 46 | // HUMIDITY 47 | else if (channel_id === 0x04 && channel_type === 0x68) { 48 | decoded.humidity = bytes[i] / 2; 49 | i += 1; 50 | } 51 | // TEMPERATURE & HUMIDITY HISTROY 52 | else if (channel_id === 0x20 && channel_type === 0xce) { 53 | var point = {}; 54 | point.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 55 | point.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; 56 | point.humidity = bytes[i + 6] / 2; 57 | 58 | decoded.history = decoded.history || []; 59 | decoded.history.push(point); 60 | i += 8; 61 | } else { 62 | break; 63 | } 64 | } 65 | 66 | return decoded; 67 | } 68 | 69 | /* ****************************************** 70 | * bytes to number 71 | ********************************************/ 72 | function readUInt16LE(bytes) { 73 | var value = (bytes[1] << 8) + bytes[0]; 74 | return value & 0xffff; 75 | } 76 | 77 | function readInt16LE(bytes) { 78 | var ref = readUInt16LE(bytes); 79 | return ref > 0x7fff ? ref - 0x10000 : ref; 80 | } 81 | 82 | function readUInt32LE(bytes) { 83 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 84 | return value & 0xffffffff; 85 | } 86 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM300-TH/README.md: -------------------------------------------------------------------------------- 1 | # Temperature & Humidity Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM300-TH. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM300-TH](EM300-TH.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :-------------: | :--: | :--: | :----: | ----------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 15 | | Humidity | 0x04 | 0x68 | 1 | humidity(1B)
humidity, unit: %RH | 16 | | Historical Data | 0x20 | 0XCE | 8 | timestamp(4B) + temperature(2B) + humidity(1B) + status(1B) | 17 | 18 | ## Example 19 | 20 | ```json 21 | // 01755C 03673401 046865 22 | { 23 | "battery": 92, 24 | "temperature": 30.8, 25 | "humidity": 50.5 26 | } 27 | 28 | // 20CE9E74466310015D00 29 | { 30 | "history": [ 31 | { 32 | "humidity": 46.5, 33 | "temperature": 27.2, 34 | "timestamp": 1665561758 35 | } 36 | ] 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM310-TILT/EM310-TILT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM310-TILT/EM310-TILT.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM310-TILT/EM310-TILT_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM310-TILT 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // ANGLE 37 | else if (channel_id === 0x03 && channel_type === 0xcf) { 38 | decoded.angle_x = readInt16LE(bytes.slice(i, i + 2)) / 100; 39 | decoded.angle_y = readInt16LE(bytes.slice(i + 2, i + 4)) / 100; 40 | decoded.angle_z = readInt16LE(bytes.slice(i + 4, i + 6)) / 100; 41 | decoded.threshold_x = (bytes[i + 6] & 0x01) === 0x01 ? "trigger" : "normal"; 42 | decoded.threshold_y = (bytes[i + 6] & 0x02) === 0x02 ? "trigger" : "normal"; 43 | decoded.threshold_z = (bytes[i + 6] & 0x04) === 0x04 ? "trigger" : "normal"; 44 | i += 7; 45 | } else { 46 | break; 47 | } 48 | } 49 | 50 | return decoded; 51 | } 52 | 53 | /* ****************************************** 54 | * bytes to number 55 | ********************************************/ 56 | function readUInt16LE(bytes) { 57 | var value = (bytes[1] << 8) + bytes[0]; 58 | return value & 0xffff; 59 | } 60 | 61 | function readInt16LE(bytes) { 62 | var ref = readUInt16LE(bytes); 63 | return ref > 0x7fff ? ref - 0x10000 : ref; 64 | } 65 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM310-TILT/README.md: -------------------------------------------------------------------------------- 1 | # Tilt Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM310-TILT. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM310-TILT](EM310-TILT.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :---------: | :--: | :--: | :----: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Angle X/Y/Z | 0x03 | 0xCF | 7 | angle_x(2B) + angle_y(2B) + angle_z(2B) + status(1B)
angle_x, read: int16/100, unit: °
angle_y, read: int16/100, unit: °
angle_z, read: int16/100, unit: °
status, values: (bit0: angle_x threshold alarm, bit1: angle_y threshold alarm, bit2: angle_z threshold alarm) | 15 | 16 | ## Example 17 | 18 | ```json 19 | // 03CF00000000282307 20 | { 21 | "angle_x": 0, 22 | "angle_y": 0, 23 | "angle_z": 90, 24 | "threshold_x": "trigger", 25 | "threshold_y": "trigger", 26 | "threshold_z": "trigger" 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM310-UDL/EM310-UDL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM310-UDL/EM310-UDL.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM310-UDL/README.md: -------------------------------------------------------------------------------- 1 | # Ultrasonic Distance/Level Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM310-UDL. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM300-UDL](EM310-UDL.png) 8 | 9 | ## Payload Definition 10 | 11 | ### Attribute 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :----------------: | :---: | :---: | :----: | -------------------- | 15 | | Protocol Version | 0xFF | 0x01 | 1 | protocol_version(1B) | 16 | | Power Status | 0xFF | 0x0B | 1 | power_status(1B) | 17 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 18 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 19 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 20 | | LoRaWAN Class Type | 0xFF | 0x0F | 1 | lorawan_class(1B) | 21 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 22 | 23 | ### Telemetry 24 | 25 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 26 | | :------: | :---: | :---: | :----: | -------------------------------------------------------- | 27 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 28 | | Distance | 0x03 | 0x82 | 2 | distance(2B)
distance, unit: mm | 29 | | Position | 0x04 | 0x00 | 1 | position(1B)
position, values: (0: normal, 1: tilt) | 30 | 31 | ## Example 32 | 33 | ```json 34 | // 01755C 03824408 040001 35 | { 36 | "battery": 92, 37 | "distance": 2116, 38 | "position": "tilt" 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM320-TH/EM320-TH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM320-TH/EM320-TH.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM320-TH/EM320-TH.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | def decodeBytes(bytes): 5 | print("bytes:", bytes.hex()) 6 | decoded = {} 7 | 8 | i = 0 9 | while i < len(bytes): 10 | channel_id = bytes[i] 11 | channel_type = bytes[i+1] 12 | i += 2 13 | 14 | # BATTERY 15 | if channel_id == 0x01 and channel_type == 0x75: 16 | decoded['battery'] = bytes[i] 17 | i += 1 18 | # TEMPERATURE 19 | elif channel_id == 0x03 and channel_type == 0x67: 20 | # ℃ 21 | decoded['temperature'] = int.from_bytes(bytes[i: i + 2], 'little', signed=True) / 10 22 | i += 2 23 | 24 | # ℉ 25 | # decoded['temperature'] = int.from_bytes(bytes[i: i + 2], 'little', signed=True) / 10 * 1.8 + 32 26 | # i +=2 27 | # HUMIDITY 28 | elif channel_id == 0x04 and channel_type == 0x68: 29 | decoded['humidity'] = bytes[i] / 2 30 | i += 1 31 | # TEMPERATURE & HUMIDITY HISTROY 32 | elif channel_id == 0x20 and channel_type == 0XCE: 33 | point = {} 34 | point['timestamp'] = int.from_bytes(bytes[i: i + 4], 'little', signed=False) 35 | point['temperature'] = int.from_bytes(bytes[i + 4:i + 6], 'little', signed=True) / 10 36 | point['humidity'] = bytes[i + 6] / 2 37 | 38 | if decoded.get('history') is None: 39 | decoded['history'] = [] 40 | 41 | decoded['history'].append(point) 42 | i += 7 43 | else: 44 | break 45 | 46 | print(decoded) 47 | return decoded 48 | 49 | 50 | def decodePayload(payload, encoded="base64"): 51 | if encoded == "base64": 52 | bytes = binascii.a2b_base64(payload) 53 | elif encoded == "hex": 54 | bytes = binascii.a2b_hex(payload) 55 | else: 56 | print("unsupport encode type") 57 | 58 | return decodeBytes(bytes) 59 | 60 | 61 | if __name__ == '__main__': 62 | decodePayload("AXVcA2c0AQRoZQ==", "base64") 63 | decodePayload("01755C0367340104686520ce9e74466310015d", "hex") 64 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM320-TH/README.md: -------------------------------------------------------------------------------- 1 | # Temperature & Humidity Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM320-TH. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM320-TH](EM320-TH.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :-------------: | :--: | :--: | :----: | ---------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 15 | | Humidity | 0x04 | 0x68 | 1 | humidity(1B)
humidity, unit: %RH | 16 | | Historical Data | 0x20 | 0XCE | 7 | timestamp(4B) + temperature(2B) + humidity(1B) | 17 | 18 | ## Example 19 | 20 | ```json 21 | // 01755C 03673401 046865 22 | { 23 | "battery": 92, 24 | "humidity": 50.5, 25 | "temperature": 30.8 26 | } 27 | 28 | // 20CE9E74466310015D 29 | { 30 | "history": [ 31 | { 32 | "humidity": 46.5, 33 | "temperature": 27.2, 34 | "timestamp": 1665561758 35 | } 36 | ] 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM320-TILT/EM320-TILT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM300_Series/EM320-TILT/EM320-TILT.png -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM320-TILT/EM320-TILT.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | def decodeBytes(bytes): 5 | print("bytes:", bytes.hex()) 6 | decoded = {} 7 | 8 | i = 0 9 | while i < len(bytes): 10 | channel_id = bytes[i] 11 | channel_type = bytes[i+1] 12 | i += 2 13 | 14 | # BATTERY 15 | if channel_id == 0x01 and channel_type == 0x75: 16 | decoded['battery'] = bytes[i] 17 | i += 1 18 | # ANGLE 19 | elif channel_id == 0x03 and channel_type == 0xD4: 20 | decoded['angle_x'] = (int.from_bytes(bytes[i: i + 2], 'little', signed=True) >> 1) / 100 21 | decoded['angle_y'] = (int.from_bytes(bytes[i + 2: i + 4], 'little', signed=True) >> 1) / 100 22 | decoded['angle_z'] = (int.from_bytes(bytes[i + 4: i + 6], 'little', signed=True) >> 1) / 100 23 | decoded['threshold_x'] = "trigger" if (bytes[i] & 0x01) == 0x01 else "normal" 24 | decoded['threshold_y'] = "trigger" if (bytes[i + 2] & 0x01) == 0x01 else "normal" 25 | decoded['threshold_z'] = "trigger" if (bytes[i + 4] & 0x01) == 0x01 else "normal" 26 | i += 6 27 | else: 28 | break 29 | 30 | print(decoded) 31 | return decoded 32 | 33 | 34 | def decodePayload(payload, encoded="base64"): 35 | if encoded == "base64": 36 | bytes = binascii.a2b_base64(payload) 37 | elif encoded == "hex": 38 | bytes = binascii.a2b_hex(payload) 39 | else: 40 | print("unsupport encode type") 41 | 42 | return decodeBytes(bytes) 43 | 44 | 45 | if __name__ == '__main__': 46 | decodePayload("AXVkA9QAAAEAUEY=", "base64") 47 | decodePayload("c", "hex") 48 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM320-TILT/EM320-TILT_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM320-TILT 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // ANGLE 37 | else if (channel_id === 0x03 && channel_type === 0xd4) { 38 | decoded.angle_x = (readInt16LE(bytes.slice(i, i + 2)) >> 1) / 100; 39 | decoded.angle_y = (readInt16LE(bytes.slice(i + 2, i + 4)) >> 1) / 100; 40 | decoded.angle_z = (readInt16LE(bytes.slice(i + 4, i + 6)) >> 1) / 100; 41 | decoded.threshold_x = (bytes[i] & 0x01) === 0x01 ? "trigger" : "normal"; 42 | decoded.threshold_y = (bytes[i + 2] & 0x01) === 0x01 ? "trigger" : "normal"; 43 | decoded.threshold_z = (bytes[i + 4] & 0x01) === 0x01 ? "trigger" : "normal"; 44 | i += 6; 45 | } else { 46 | break; 47 | } 48 | } 49 | 50 | return decoded; 51 | } 52 | 53 | /* ****************************************** 54 | * bytes to number 55 | ********************************************/ 56 | function readUInt16LE(bytes) { 57 | var value = (bytes[1] << 8) + bytes[0]; 58 | return value & 0xffff; 59 | } 60 | 61 | function readInt16LE(bytes) { 62 | var ref = readUInt16LE(bytes); 63 | return ref > 0x7fff ? ref - 0x10000 : ref; 64 | } 65 | -------------------------------------------------------------------------------- /EM_Series/EM300_Series/EM320-TILT/README.md: -------------------------------------------------------------------------------- 1 | # Tilt Sensor - Milesight IoT 2 | 3 | ![EM320-TILT](EM320-TILT.png) 4 | 5 | The payload decoder function is applicable to EM320-TILT. 6 | 7 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :---------: | :--: | :--: | :----: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Angle X/Y/Z | 0x03 | 0xD4 | 6 | angle_x(2B) + angle_y(2B) + angle_z(2B)
angle_x, angle_x(15..1) + angle_x_threshold(0)
angle_y, angle_y(15..1) + angle_y_threshold(0)
angle_z, angle_z(15..1) + angle_z_threshold(0)
| 15 | 16 | ### Angle X/Y/Z Definition (bits) 17 | 18 | ``` 19 | +--------------------------------------------------------+ 20 | | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 21 | +--------------------------------------------------------+ 22 | | ANGLE DATA(1) | 23 | +--------------------------------------------------------+ 24 | | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 | 25 | +------------------------------------------------+-------+ 26 | | ANGLE DATA(0) | FLAG | 27 | +------------------------------------------------+-------+ 28 | 29 | NOTE: (FLAG: normal, 1: trigger) 30 | ``` 31 | 32 | ## Example 33 | 34 | ```json 35 | // 017564 03D4000001005046 36 | { 37 | "battery": 100, 38 | "angle_x": 0, 39 | "angle_y": 0, 40 | "angle_z": 90, 41 | "threshold_x": "normal", 42 | "threshold_y": "trigger", 43 | "threshold_z": "normal" 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /EM_Series/EM400_Series/EM400-MUD/EM400-MUD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM400_Series/EM400-MUD/EM400-MUD.png -------------------------------------------------------------------------------- /EM_Series/EM400_Series/EM400-MUD/EM400-MUD_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM400-MUD 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // TEMPERATURE 36 | else if (channel_id === 0x03 && channel_type === 0x67) { 37 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 38 | i += 2; 39 | } 40 | // DISTANCE 41 | else if (channel_id === 0x04 && channel_type === 0x82) { 42 | decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); 43 | i += 2; 44 | } 45 | // POSITION 46 | else if (channel_id === 0x05 && channel_type === 0x00) { 47 | decoded.position = bytes[i] === 0 ? "normal" : "tilt"; 48 | i += 1; 49 | } 50 | // TEMPERATURE WITH ABNORMAL 51 | else if (channel_id === 0x83 && channel_type === 0x67) { 52 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 53 | decoded.temperature_abnormal = bytes[i + 2] == 0 ? false : true; 54 | i += 3; 55 | } 56 | // DISTANCE WITH ALARMING 57 | else if (channel_id === 0x84 && channel_type === 0x82) { 58 | decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); 59 | decoded.distance_alarming = bytes[i + 2] == 0 ? false : true; 60 | i += 3; 61 | } else { 62 | break; 63 | } 64 | } 65 | 66 | return decoded; 67 | } 68 | 69 | /* ****************************************** 70 | * bytes to number 71 | ********************************************/ 72 | function readUInt16LE(bytes) { 73 | var value = (bytes[1] << 8) + bytes[0]; 74 | return value & 0xffff; 75 | } 76 | 77 | function readInt16LE(bytes) { 78 | var ref = readUInt16LE(bytes); 79 | return ref > 0x7fff ? ref - 0x10000 : ref; 80 | } 81 | -------------------------------------------------------------------------------- /EM_Series/EM400_Series/EM400-TLD/EM400-TLD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM400_Series/EM400-TLD/EM400-TLD.png -------------------------------------------------------------------------------- /EM_Series/EM400_Series/EM400-TLD/EM400-TLD_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM400-TLD 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // TEMPERATURE 36 | else if (channel_id === 0x03 && channel_type === 0x67) { 37 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 38 | i += 2; 39 | } 40 | // DISTANCE 41 | else if (channel_id === 0x04 && channel_type === 0x82) { 42 | decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); 43 | i += 2; 44 | } 45 | // POSITION 46 | else if (channel_id === 0x05 && channel_type === 0x00) { 47 | decoded.position = bytes[i] === 0 ? "normal" : "tilt"; 48 | i += 1; 49 | } 50 | // TEMPERATURE WITH ABNORMAL 51 | else if (channel_id === 0x83 && channel_type === 0x67) { 52 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 53 | decoded.temperature_abnormal = bytes[i + 2] == 0 ? false : true; 54 | i += 3; 55 | } 56 | // DISTANCE WITH ALARMING 57 | else if (channel_id === 0x84 && channel_type === 0x82) { 58 | decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); 59 | decoded.distance_alarming = bytes[i + 2] == 0 ? false : true; 60 | i += 3; 61 | } else { 62 | break; 63 | } 64 | } 65 | 66 | return decoded; 67 | } 68 | 69 | /* ****************************************** 70 | * bytes to number 71 | ********************************************/ 72 | function readUInt16LE(bytes) { 73 | var value = (bytes[1] << 8) + bytes[0]; 74 | return value & 0xffff; 75 | } 76 | 77 | function readInt16LE(bytes) { 78 | var ref = readUInt16LE(bytes); 79 | return ref > 0x7fff ? ref - 0x10000 : ref; 80 | } 81 | -------------------------------------------------------------------------------- /EM_Series/EM400_Series/EM400-UDL/EM400-UDL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM400_Series/EM400-UDL/EM400-UDL.png -------------------------------------------------------------------------------- /EM_Series/EM400_Series/EM400-UDL/EM400-UDL_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM400-UDL 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // TEMPERATURE 36 | else if (channel_id === 0x03 && channel_type === 0x67) { 37 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 38 | i += 2; 39 | } 40 | // DISTANCE 41 | else if (channel_id === 0x04 && channel_type === 0x82) { 42 | decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); 43 | i += 2; 44 | } 45 | // POSITION 46 | else if (channel_id === 0x05 && channel_type === 0x00) { 47 | decoded.position = bytes[i] === 0 ? "normal" : "tilt"; 48 | i += 1; 49 | } 50 | // TEMPERATURE WITH ABNORMAL 51 | else if (channel_id === 0x83 && channel_type === 0x67) { 52 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 53 | decoded.temperature_abnormal = bytes[i + 2] == 0 ? false : true; 54 | i += 3; 55 | } 56 | // DISTANCE WITH ALARMING 57 | else if (channel_id === 0x84 && channel_type === 0x82) { 58 | decoded.distance = readUInt16LE(bytes.slice(i, i + 2)); 59 | decoded.distance_alarming = bytes[i + 2] == 0 ? false : true; 60 | i += 3; 61 | } else { 62 | break; 63 | } 64 | } 65 | 66 | return decoded; 67 | } 68 | 69 | /* ****************************************** 70 | * bytes to number 71 | ********************************************/ 72 | function readUInt16LE(bytes) { 73 | var value = (bytes[1] << 8) + bytes[0]; 74 | return value & 0xffff; 75 | } 76 | 77 | function readInt16LE(bytes) { 78 | var ref = readUInt16LE(bytes); 79 | return ref > 0x7fff ? ref - 0x10000 : ref; 80 | } 81 | -------------------------------------------------------------------------------- /EM_Series/EM400_Series/EM410-RDL/EM410-RDL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM400_Series/EM410-RDL/EM410-RDL.png -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-CO2/EM500-CO2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM500_Series/EM500-CO2/EM500-CO2.png -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-CO2/README.md: -------------------------------------------------------------------------------- 1 | # CO2 Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM500-CO2. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/em500-co2). 6 | 7 | ![EM500-CO2](EM500-CO2.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :---------------: | :--: | :--: | :----: | ----------------------------------------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature,unit: ℃ | 15 | | Humidity | 0x04 | 0x68 | 1 | humidity(1B)
humidity, unit: %RH | 16 | | CO2 | 0x05 | 0x7D | 2 | co2(2B)
co2, unit: ppm | 17 | | Pressure | 0x06 | 0x73 | 2 | pressure(2B)
pressure, unit: hPa | 18 | | Temperature Alarm | 0x83 | 0xD7 | 5 | temperature(2B) + temperature_change(2B) + temperature_alarm(1B)
temperature, unit: ℃ | 19 | | Historical Data | 0x20 | 0XCE | 11 | timestamp(4B) + co2(2B) + pressure(2B) + temperature(2B) + humidity(1B) | 20 | 21 | ## Example 22 | 23 | ```json 24 | // 01756403671901 046873 057D6704 06736827 25 | { 26 | "battery": 100, 27 | "temperature": 28.1, 28 | "humidity": 57.5, 29 | "co2": 1127, 30 | "pressure": 1008.8 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-LGT/EM500-LGT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM500_Series/EM500-LGT/EM500-LGT.png -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-LGT/README.md: -------------------------------------------------------------------------------- 1 | # Light Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM500-LGT. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/em500-lgt). 6 | 7 | ![EM500-LGT](EM500-LGT.png) 8 | 9 | ## Payload Definition 10 | 11 | ### Attributes 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :----------------: | :--: | :--: | :----: | -------------------- | 15 | | Protocol Version | 0xFF | 0x01 | 1 | protocol_version(1B) | 16 | | Power Status | 0xFF | 0x0B | 1 | power_status(1B) | 17 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 18 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 19 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 20 | | LoRaWAN Class Type | 0xFF | 0x0F | 1 | lorawan_class(1B) | 21 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 22 | 23 | ### Telemetry 24 | 25 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 26 | | :-------------: | :--: | :--: | :----: | -------------------------------------------- | 27 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 28 | | Illumination | 0x03 | 0x94 | 4 | illumination(4B)
illumination, unit: lux | 29 | | Historical Data | 0x20 | 0XCE | 8 | timestamp(4B) + illumination(4B) | 30 | 31 | ## Example 32 | 33 | ```json 34 | // 017564 039450000000 35 | { 36 | "battery": 100, 37 | "illumination": 80 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-PP/EM500-PP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM500_Series/EM500-PP/EM500-PP.png -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-PP/EM500-PP_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM500-PP 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // PRESSURE 37 | else if (channel_id === 0x03 && channel_type === 0x7b) { 38 | decoded.pressure = readInt16LE(bytes.slice(i, i + 2)); 39 | i += 2; 40 | } 41 | // HISTROY DATA 42 | else if (channel_id === 0x20 && channel_type === 0xce) { 43 | var point = {}; 44 | point.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 45 | point.pressure = readInt16LE(bytes.slice(i + 4, i + 6)); 46 | 47 | decoded.history = decoded.history || []; 48 | decoded.history.push(point); 49 | i += 6; 50 | } else { 51 | break; 52 | } 53 | } 54 | 55 | return decoded; 56 | } 57 | 58 | /* ****************************************** 59 | * bytes to number 60 | ********************************************/ 61 | function readUInt16LE(bytes) { 62 | var value = (bytes[1] << 8) + bytes[0]; 63 | return value & 0xffff; 64 | } 65 | 66 | function readInt16LE(bytes) { 67 | var ref = readUInt16LE(bytes); 68 | return ref > 0x7fff ? ref - 0x10000 : ref; 69 | } 70 | 71 | function readUInt32LE(bytes) { 72 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 73 | return value & 0xffffffff; 74 | } 75 | -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-PP/README.md: -------------------------------------------------------------------------------- 1 | # Pipe Pressure Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM500-PP. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM500-PP](EM500-PP.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :------: | :--: | :--: | :----: | ------------------------------------ | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Pressure | 0x03 | 0x7B | 2 | pressure(2B)
pressure, unit: kPa | 15 | 16 | ## Example 17 | 18 | ```json 19 | // 017564 037B0A00 20 | { 21 | "battery": 100, 22 | "pressure": 10 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-PT100/EM500-PT100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM500_Series/EM500-PT100/EM500-PT100.png -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-PT100/EM500-PT100_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM500-PT100 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // TEMPERATURE 37 | else if (channel_id === 0x03 && channel_type === 0x67) { 38 | // ℃ 39 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 40 | i += 2; 41 | 42 | // ℉ 43 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 44 | // i +=2; 45 | } 46 | // TEMPERATURE CHANGE ALARM 47 | else if (channel_id === 0x83 && channel_type === 0xd7) { 48 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 49 | decoded.temperature_change = readInt16LE(bytes.slice(i + 2, i + 4)) / 10; 50 | decoded.temperature_alarm = readTemperatureAlarm(bytes[i + 4]); 51 | i += 5; 52 | } 53 | // HISTROY DATA 54 | else if (channel_id === 0x20 && channel_type === 0xce) { 55 | var data = {}; 56 | data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 57 | data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; 58 | i += 6; 59 | 60 | decoded.history = decoded.history || []; 61 | decoded.history.push(data); 62 | } else { 63 | break; 64 | } 65 | } 66 | 67 | return decoded; 68 | } 69 | 70 | /* ****************************************** 71 | * bytes to number 72 | ********************************************/ 73 | function readUInt16LE(bytes) { 74 | var value = (bytes[1] << 8) + bytes[0]; 75 | return value & 0xffff; 76 | } 77 | 78 | function readInt16LE(bytes) { 79 | var ref = readUInt16LE(bytes); 80 | return ref > 0x7fff ? ref - 0x10000 : ref; 81 | } 82 | 83 | function readUInt32LE(bytes) { 84 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 85 | return value & 0xffffffff; 86 | } 87 | 88 | function readTemperatureAlarm(type) { 89 | switch (type) { 90 | case 0: 91 | return "threshold alarm"; 92 | case 1: 93 | return "threshold alarm release"; 94 | case 2: 95 | return "mutation alarm"; 96 | default: 97 | return "unkown"; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-PT100/README.md: -------------------------------------------------------------------------------- 1 | # Industrial Temperature Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM500-PT100. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM500-PT100](EM500-PT100.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :---------------: | :--: | :--: | :----: | ----------------------------------------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 15 | | Temperature Alarm | 0x83 | 0xD7 | 5 | temperature(2B) + temperature_change(2B) + temperature_alarm(1B)
temperature, unit: ℃ | 16 | | Historical Data | 0x20 | 0XCE | 6 | timestamp(4B) + temperature(2B) | 17 | 18 | ## Example 19 | 20 | ```json 21 | // 017564 03671901 22 | { 23 | "battery": 100, 24 | "temperature": 28.1 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-SMTC/EM500-SMTC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM500_Series/EM500-SMTC/EM500-SMTC.png -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-SMTC/EM500-SMTC_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM500-SMTC 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // TEMPERATURE 37 | else if (channel_id === 0x03 && channel_type === 0x67) { 38 | // ℃ 39 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 40 | i += 2; 41 | 42 | // ℉ 43 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 44 | // i +=2; 45 | } 46 | // MOISTURE (old resolution 0.5) 47 | else if (channel_id === 0x04 && channel_type === 0x68) { 48 | decoded.moisture = bytes[i] / 2; 49 | i += 1; 50 | } 51 | // MOISTURE (new resolution 0.01) 52 | else if (channel_id === 0x04 && channel_type === 0xca) { 53 | decoded.moisture = readUInt16LE(bytes.slice(i, i + 2)) / 100; 54 | i += 2; 55 | } 56 | // EC 57 | else if (channel_id === 0x05 && channel_type === 0x7f) { 58 | decoded.ec = readUInt16LE(bytes.slice(i, i + 2)); 59 | i += 2; 60 | } 61 | // TEMPERATURE CHANGE ALARM 62 | else if (channel_id === 0x83 && channel_type === 0xd7) { 63 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 64 | decoded.temperature_change = readInt16LE(bytes.slice(i + 2, i + 4)) / 10; 65 | decoded.temperature_alarm = readTemperatureAlarm(bytes[i + 4]); 66 | i += 5; 67 | } 68 | // HISTROY 69 | else if (channel_id === 0x20 && channel_type === 0xce) { 70 | var data = {}; 71 | data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 72 | data.ec = readUInt16LE(bytes.slice(i + 4, i + 6)); 73 | data.temperature = readInt16LE(bytes.slice(i + 6, i + 8)) / 10; 74 | data.moisture = readUInt16LE(bytes.slice(i + 8, i + 10)) / 100; 75 | i += 10; 76 | 77 | decoded.history = decoded.history || []; 78 | decoded.history.push(data); 79 | } else { 80 | break; 81 | } 82 | } 83 | 84 | return decoded; 85 | } 86 | 87 | /* ****************************************** 88 | * bytes to number 89 | ********************************************/ 90 | function readUInt16LE(bytes) { 91 | var value = (bytes[1] << 8) + bytes[0]; 92 | return value & 0xffff; 93 | } 94 | 95 | function readInt16LE(bytes) { 96 | var ref = readUInt16LE(bytes); 97 | return ref > 0x7fff ? ref - 0x10000 : ref; 98 | } 99 | 100 | function readUInt32LE(bytes) { 101 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 102 | return value & 0xffffffff; 103 | } 104 | 105 | function readTemperatureAlarm(type) { 106 | switch (type) { 107 | case 0: 108 | return "threshold alarm"; 109 | case 1: 110 | return "threshold alarm release"; 111 | case 2: 112 | return "mutation alarm"; 113 | default: 114 | return "unkown"; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-SMTC/README.md: -------------------------------------------------------------------------------- 1 | # Soil Moisture, Temperature and Electrical Conductivity Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM500-SMTC. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM500-SMTC](EM500-SMTC.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :---------------: | :--: | :--: | :----: | ----------------------------------------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 15 | | Moisture | 0x04 | 0x68 | 1 | moisture(1B)
moisture, unit: %RH | 16 | | Moisture | 0x04 | 0xCA | 2 | moisture(2B)
moisture, unit: %RH | 17 | | EC | 0x05 | 0x7F | 2 | ec(2B)
ec, unit: µs/cm | 18 | | Temperature Alarm | 0x83 | 0xD7 | 5 | temperature(2B) + temperature_change(2B) + temperature_alarm(1B)
temperature, unit: ℃ | 19 | | Historical Data | 0x20 | 0XCE | 10 | timestamp(4B) + EC(2B) + temperature(2B) + moisture(2B) | 20 | 21 | ## Example 22 | 23 | ```json 24 | // 017564 03671901 046873 057FF000 25 | { 26 | "battery": 100, 27 | "temperature": 28.1, 28 | "moisture": 57.5, 29 | "ec": 240 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-SWL/EM500-SWL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM500_Series/EM500-SWL/EM500-SWL.png -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-SWL/EM500-SWL_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product EM500-SWL 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // WATER LEVEL 37 | else if (channel_id === 0x03 && channel_type === 0x77) { 38 | decoded.water_level = readUInt16LE(bytes.slice(i, i + 2)); 39 | i += 2; 40 | } 41 | // HISTROY DATA 42 | else if (channel_id === 0x20 && channel_type === 0xce) { 43 | var point = {}; 44 | point.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 45 | point.water_level = readUInt16LE(bytes.slice(i + 4, i + 6)); 46 | 47 | decoded.history = decoded.history || []; 48 | decoded.history.push(point); 49 | i += 6; 50 | } else { 51 | break; 52 | } 53 | } 54 | 55 | return decoded; 56 | } 57 | 58 | /* ****************************************** 59 | * bytes to number 60 | ********************************************/ 61 | function readUInt16LE(bytes) { 62 | var value = (bytes[1] << 8) + bytes[0]; 63 | return value & 0xffff; 64 | } 65 | 66 | function readInt16LE(bytes) { 67 | var ref = readUInt16LE(bytes); 68 | return ref > 0x7fff ? ref - 0x10000 : ref; 69 | } 70 | 71 | function readUInt32LE(bytes) { 72 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 73 | return value & 0xffffffff; 74 | } 75 | -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-SWL/README.md: -------------------------------------------------------------------------------- 1 | # Submersible Water Level Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM500-SWL. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![EM500-SWL](EM500-SWL.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :-------------: | :--: | :--: | :----: | ----------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Water Level | 0x03 | 0x77 | 2 | water_level(2B)
water_level, unit: cm | 15 | | Historical Data | 0x20 | 0XCE | 6 | timestamp(4B) + water_level(2B) | 16 | 17 | ## Example 18 | 19 | ```json 20 | // 017564 03770200 21 | { 22 | "battery": 100, 23 | "water_level": 2 24 | } 25 | ``` 26 | -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-UDL/EM500-UDL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/EM_Series/EM500_Series/EM500-UDL/EM500-UDL.png -------------------------------------------------------------------------------- /EM_Series/EM500_Series/EM500-UDL/README.md: -------------------------------------------------------------------------------- 1 | # Ultrasonic Distance/Level Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to EM500-UDL. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/em500-udl). 6 | 7 | ![EM500-UDL](EM500-UDL.png) 8 | 9 | ## Payload Definition 10 | 11 | ### Attributes 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :----------------: | :--: | :--: | :----: | -------------------- | 15 | | Protocol Version | 0xFF | 0x01 | 1 | protocol_version(1B) | 16 | | Power Status | 0xFF | 0x0B | 1 | power_status(1B) | 17 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 18 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 19 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 20 | | LoRaWAN Class Type | 0xFF | 0x0F | 1 | lorawan_class(1B) | 21 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 22 | 23 | ### Telemetry 24 | 25 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 26 | | :-------------: | :--: | :--: | :----: | --------------------------------------------------------- | 27 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 28 | | Distance | 0x03 | 0x82 | 2 | distance(2B)
distance, unit: mm | 29 | | Distance Alarm | 0x83 | 0xE9 | 5 | distance(2B) + distance_mutation(2B) + distance_alarm(1B) | 30 | | Historical Data | 0x20 | 0XCE | 6 | timestamp(4B) + distance(2B) | 31 | 32 | ## Example 33 | 34 | ```json 35 | // 017564 03821E00 36 | { 37 | "battery": 100, 38 | "distance": 30 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /FT_Series/FT101/FT101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/FT_Series/FT101/FT101.png -------------------------------------------------------------------------------- /FT_Series/FT101/README.md: -------------------------------------------------------------------------------- 1 | # Field Tester - Milesight IoT 2 | 3 | The payload decoder function is applicable to FT101. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com). 6 | 7 | ![FT101](FT101.png) 8 | 9 | ## Payload Definition 10 | 11 | ### ATTRIBUTES 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :--------------: | :--: | :--: | :----: | --------------------------------------------------------------------------------------------- | 15 | | Protocol Version | 0xFF | 0x01 | 1 | ipso_version(1B) | 16 | | Device Status | 0xFF | 0x0B | 1 | device_status(1B) | 17 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 18 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 19 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 20 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 21 | | LoRaWAN Class | 0xFF | 0x0F | 1 | lorawan_class(1B)
lorawan_class, values: (0: classA, 1: classB, 2: classC, 3: classCtoB) | 22 | 23 | ### TELEMETRY 24 | 25 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 26 | | :--------------: | :--: | :--: | :----: | ---------------------------- | 27 | | Location | 0x03 | 0xA1 | 8 | longitude(4B) + latitude(4B) | 28 | | Signal Strength | 0x04 | 0xA2 | 4 | rssi(2B) + snr(2B) | 29 | | Spreading Factor | 0x05 | 0xA3 | 1 | sf(1B) | 30 | | TX Power | 0x06 | 0xA4 | 2 | tx_power(2B) | 31 | 32 | ## Sample 33 | 34 | ```json 35 | 36 | 37 | ``` 38 | -------------------------------------------------------------------------------- /GS_Series/GS101/GS101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/GS_Series/GS101/GS101.png -------------------------------------------------------------------------------- /GS_Series/GS101/README.md: -------------------------------------------------------------------------------- 1 | # GAS Detector - Milesight IoT 2 | 3 | The payload decoder function is applicable to GS101. 4 | 5 | For more detailed information, please visit [Milesight Official Website (GS101)](https://www.milesight.com/iot/product/lorawan-sensor/gs101). 6 | 7 | ![GS101](GS101.png) 8 | 9 | ## Payload Definition 10 | 11 | ### Attributes 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :----------------: | :--: | :--: | :----: | -------------------- | 15 | | Protocol Version | 0xFF | 0x01 | 1 | protocol_version(1B) | 16 | | Power Status | 0xFF | 0x0B | 1 | power_status(1B) | 17 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 18 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 19 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 20 | | LoRaWAN Class Type | 0xFF | 0x0F | 1 | lorawan_class(1B) | 21 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 22 | 23 | ### Telemetry 24 | 25 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 26 | | :-----------------: | :--: | :--: | :----: | ------------------------------------------------------------------------------------------------------------------------------------------------------- | 27 | | GAS Status | 0x05 | 0x8E | 1 | gas_status(1B)
gas, values: (0: normal, 1: alarm) | 28 | | Valve Status | 0x06 | 0x01 | 1 | valve_status(1B)
valve, values: (0: off, 1: on) | 29 | | Relay Output Status | 0x07 | 0x01 | 1 | relay_output_status(1B)
relay_output_status, values: (0: off, 1: on) | 30 | | Life Remain | 0x08 | 0x90 | 4 | life_remain(4B)
life_remain, unit: s | 31 | | Alarm Report | 0xFF | 0x3F | 1 | alarm(1B)
alarm, values: (0: power off, 1: power on, 2: sensor fault, 3: sensor fault recovered, 4: sensor will be invalid soon, 5: device invalid) | 32 | -------------------------------------------------------------------------------- /GS_Series/GS301/GS301.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/GS_Series/GS301/GS301.png -------------------------------------------------------------------------------- /GS_Series/GS524N/GS524N.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/GS_Series/GS524N/GS524N.png -------------------------------------------------------------------------------- /GS_Series/GS524N/GS524N_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product GS524N 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | if (bytes.length != 6) { 28 | return decoded; 29 | } 30 | 31 | decoded.version = bytes[0] >>> 4; 32 | decoded.protocol = bytes[0] & 0x0f; 33 | decoded.type = getSensorType(bytes[1] >>> 4); 34 | decoded.event = getMessageType(bytes[1] & 0x0f); 35 | decoded.battery = bytes[2] & 0xff; 36 | decoded.concentration = bytes[3]; 37 | decoded.temperature = getTemperature(bytes[4]); 38 | 39 | return decoded; 40 | } 41 | 42 | function getSensorType(type) { 43 | return type === 1 ? "smoke sensor" : "unknown"; 44 | } 45 | 46 | function getMessageType(bytes) { 47 | switch (bytes) { 48 | case 0x01: 49 | return "alarm"; 50 | case 0x02: 51 | return "silent"; 52 | case 0x04: 53 | return "low battery"; 54 | case 0x05: 55 | return "failover"; 56 | case 0x07: 57 | return "normal"; 58 | case 0x0a: 59 | return "removed"; 60 | case 0x0b: 61 | return "installed"; 62 | case 0x0e: 63 | return "testing alarm with normal battery"; 64 | case 0x0f: 65 | return "testing alarm with low battery"; 66 | } 67 | } 68 | 69 | function getTemperature(bytes) { 70 | return readInt8(bytes); 71 | } 72 | 73 | function readUInt8(bytes) { 74 | return bytes & 0xff; 75 | } 76 | 77 | function readInt8(bytes) { 78 | var ref = readUInt8(bytes); 79 | return ref > 0x7f ? ref - 0x100 : ref; 80 | } 81 | -------------------------------------------------------------------------------- /GS_Series/GS524N/README.md: -------------------------------------------------------------------------------- 1 | # Smoke Detection Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to GS524N. 4 | 5 | For more detailed information, please visit [Milesight official website](https://www.milesight.cn). 6 | 7 | ![GS524N](GS524N.png) 8 | 9 | ## Payload Definition 10 | 11 | | BYTES | DESCRIPTION | 12 | | :---: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 13 | | 1 | protocol_version(0..3) + firmware_version(4..7)
firmware_version, range: [1, 15], current version: 2
protocol_version, range: [1, 15], current version: 2 | 14 | | 2 | message_type(0..3) + sensor_type(4..7)
message_type, values: (1: alarm, 2: silent, 4: low battery, 5: failover, 7: normal, 10: removed, 11: installed, 14: testing alarm with normal battery, 15: testing alarm with low battery)
sensor_type, values: (1: smoke detection sensor) | 15 | | 3 | battery(1B)
battery, uint: % | 16 | | 4 | concentration(1B)
concentration, uint: % | 17 | | 5 | temperature(1B)
temperature, range: [-20, 70], uint: ℃ | 18 | | 6 | crc(1B)
crc, calc: byte1 + byte2 + byte3 + byte4 + byte5 + byte6 = 0x00 | 19 | 20 | # Sample 21 | 22 | ```json 23 | // 221E64001C40 24 | { 25 | "version": 2, 26 | "protocol": 2, 27 | "type": "smoke sensor", 28 | "battery": 100, 29 | "concentration": 0, 30 | "temperature": 28, 31 | "event": "testing alarm with normal battery" 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /GS_Series/GS601/GS601.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/GS_Series/GS601/GS601.png -------------------------------------------------------------------------------- /LoRaObject.md: -------------------------------------------------------------------------------- 1 | # Extended usage of the decode function 2 | 3 | Get more information from [LoRaObject](#LoRaObject) variable. 4 | 5 | ## Example 6 | 7 | 8 | ``` javascript 9 | function Decode(fPort, bytes) { 10 | var decoder = {}; 11 | if (fPort == 85) { 12 | decoder.sensor = LoRaObject.devEUI; 13 | decoder.vendor = "Milesight-IoT"; 14 | decoder.time = LoRaObject.time; 15 | decoder.raw = bytes; 16 | } 17 | return decoder; 18 | } 19 | ``` 20 | 21 | Output Result 22 | ``` json 23 | { 24 | "sensor": "24e124136c191967", 25 | "vendor": "Milesight-IoT", 26 | "time": "2025-04-08T09:15:18.883491Z", 27 | "raw": "A2cfAQRoXg==" 28 | } 29 | ``` 30 | 31 | 32 | ## LoRaObject 33 | 34 | `LoRaObject` is global variable in javascript 35 | ```jsonc 36 | { 37 | "applicationID": 1, // application ID 38 | "applicationName": "cloud", // application name 39 | "deviceName": "EM300-TH", // device name 40 | "devEUI": "24e124136c191967", // device EUI 41 | "time": "2025-04-08T09:15:18.883491Z", // uplink receive time 42 | "rxInfo": [ // lorawan gateway information related to lora 43 | { 44 | "mac": "24e124fffef021be", // ID of the receiving gateway 45 | "rssi": -57, // signal strength (dBm) 46 | "loRaSNR": 10, // signal to noise ratio 47 | "name": "local_gateway", // name of the receiving gateway 48 | "latitude": 0, // latitude of the receiving gateway 49 | "longitude": 0, // longitude of the receiving gateway 50 | "altitude": 0, // altitude of the receiving gateway 51 | "time": "2025-04-08T09:15:18.883491Z" // uplink receive time 52 | } 53 | ], 54 | "txInfo": { // lorawan node tx info 55 | "frequency": 868300000, // frequency used for transmission 56 | "dataRate": { 57 | "modulation": "LORA", // LORA module 58 | "bandwidth": 125, // bandwidth used for transmission 59 | "spreadFactor": 7 // spreadFactor used for transmission 60 | }, 61 | "adr": false, // device ADR status 62 | "codeRate": "4/5" // code rate 63 | }, 64 | "fCnt": 0, // frame counter 65 | "fPort": 85, // application port 66 | "data": "A2cfAQRoXg==", // base64 encoded payload (decrypted) 67 | "cellularIP": "10.0.0.1", // cellular ip address 68 | "gatewayTime": "2025-04-08T10:15:19+01:00", // gateway time 69 | } 70 | ``` 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Codecs 2 | 3 | Sample Functions for Milesight IoT Device Encoders and Decoders 4 | 5 | ## The following platforms are supported 6 | - [The Things Network](https://www.thethingsnetwork.org) 7 | - [Chirpstack v3 / Chirpstack v4](https://www.chirpstack.io) 8 | - [Milesight Network Server](https://www.milesight.com/iot/#lorawan-gateway) 9 | -------------------------------------------------------------------------------- /TS_Series/TS101/README.md: -------------------------------------------------------------------------------- 1 | # Insertion Temperature Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to TS101. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | ![TS101](TS101.png) 7 | 8 | ## Payload Definition 9 | 10 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 11 | | :---------: | :--: | :--: | :----: | ---------------------------------------- | 12 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 13 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 14 | 15 | ## Example 16 | 17 | ```json 18 | // 017564 03670701 19 | { 20 | "battery": 100, 21 | "temperature": 26.3 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /TS_Series/TS101/TS101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/TS_Series/TS101/TS101.png -------------------------------------------------------------------------------- /TS_Series/TS101/TS101_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product TS101 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // TEMPERATURE 37 | else if (channel_id === 0x03 && channel_type === 0x67) { 38 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 39 | i += 2; 40 | } 41 | // TEMPERATURE ALARM 42 | else if (channel_id === 0x83 && channel_type === 0x67) { 43 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 44 | decoded.temperature_alarm = readTemperatureAlarm(bytes[i + 2]); 45 | i += 3; 46 | } 47 | // TEMPERATURE MUTATION ALERT 48 | else if (channel_id === 0x93 && channel_type === 0xd7) { 49 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 50 | decoded.temperature_change = readInt16LE(bytes.slice(i + 2, i + 4)) / 100; 51 | decoded.temperature_alarm = readTemperatureAlarm(bytes[i + 4]); 52 | i += 5; 53 | } 54 | // HISTORY 55 | else if (channel_id === 0x20 && channel_type === 0xce) { 56 | var data = {}; 57 | data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 58 | data.temperature = readInt16LE(bytes.slice(i + 4, i + 6)) / 10; 59 | i += 6; 60 | 61 | decoded.history = decoded.history || []; 62 | decoded.history.push(data); 63 | } else { 64 | break; 65 | } 66 | } 67 | 68 | return decoded; 69 | } 70 | 71 | function readUInt16LE(bytes) { 72 | var value = (bytes[1] << 8) + bytes[0]; 73 | return value & 0xffff; 74 | } 75 | 76 | function readInt16LE(bytes) { 77 | var ref = readUInt16LE(bytes); 78 | return ref > 0x7fff ? ref - 0x10000 : ref; 79 | } 80 | 81 | function readUInt32LE(bytes) { 82 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 83 | return (value & 0xffffffff) >>> 0; 84 | } 85 | 86 | function readTemperatureAlarm(type) { 87 | switch (type) { 88 | case 0: 89 | return "threshold alarm release"; 90 | case 1: 91 | return "threshold alarm"; 92 | case 2: 93 | return "mutation alarm"; 94 | default: 95 | return "unkown"; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /TS_Series/TS201/TS201.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/TS_Series/TS201/TS201.png -------------------------------------------------------------------------------- /TS_Series/TS201_v2/TS201_v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/TS_Series/TS201_v2/TS201_v2.png -------------------------------------------------------------------------------- /TS_Series/TS30x/TS301.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/TS_Series/TS30x/TS301.png -------------------------------------------------------------------------------- /TS_Series/TS30x/TS302.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/TS_Series/TS30x/TS302.png -------------------------------------------------------------------------------- /UC_Series/UC100/README.md: -------------------------------------------------------------------------------- 1 | # Controller - Milesight IoT 2 | 3 | The payload decoder function is applicable to UC100. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![UC100](UC100.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :--------------: | :--: | :--: | :----: | --------------------------------------------------------------------- | 13 | | Protocol Version | 0xFF | 0x01 | 1 | ipso_version(1B) | 14 | | Power Status | 0xFF | 0x0B | 1 | power(1B) | 15 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 16 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 17 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 18 | | MODBUS | 0xFF | 0x19 | N | modbus_chn_id(1B) + data_size(1B) + data_type(1B) + channel_value(MB) | 19 | | MODBUS ERROR | 0xFF | 0x15 | 1 | modbus_chn_id_alarm(1B) | 20 | -------------------------------------------------------------------------------- /UC_Series/UC100/UC100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/UC_Series/UC100/UC100.png -------------------------------------------------------------------------------- /UC_Series/UC11-T1/UC11-T1_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product UC11-T1 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id == 0x03 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // TEMPERATURE 37 | else if (channel_id == 0x01 && channel_type === 0x67) { 38 | // ℃ 39 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 40 | i += 2; 41 | 42 | // ℉ 43 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 44 | // i +=2; 45 | } 46 | // HUMIDITY 47 | else if (channel_id == 0x02 && channel_type === 0x68) { 48 | decoded.humidity = bytes[i] / 2; 49 | i += 1; 50 | } else { 51 | break; 52 | } 53 | } 54 | 55 | return decoded; 56 | } 57 | 58 | /* ****************************************** 59 | * bytes to number 60 | ********************************************/ 61 | function readUInt16LE(bytes) { 62 | var value = (bytes[1] << 8) + bytes[0]; 63 | return value & 0xffff; 64 | } 65 | 66 | function readInt16LE(bytes) { 67 | var ref = readUInt16LE(bytes); 68 | return ref > 0x7fff ? ref - 0x10000 : ref; 69 | } 70 | -------------------------------------------------------------------------------- /UC_Series/UC11XX/UC11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/UC_Series/UC11XX/UC11.png -------------------------------------------------------------------------------- /UC_Series/UC300/UC300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/UC_Series/UC300/UC300.png -------------------------------------------------------------------------------- /UC_Series/UC50x/UC501_v3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/UC_Series/UC50x/UC501_v3.png -------------------------------------------------------------------------------- /UC_Series/UC50x/UC502_v3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/UC_Series/UC50x/UC502_v3.png -------------------------------------------------------------------------------- /UC_Series/UC51X/UC511_v3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/UC_Series/UC51X/UC511_v3.png -------------------------------------------------------------------------------- /UC_Series/UC51X/UC512_v3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/UC_Series/UC51X/UC512_v3.png -------------------------------------------------------------------------------- /UC_Series/UC521/UC521.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/UC_Series/UC521/UC521.png -------------------------------------------------------------------------------- /VS_Series/VS121/VS121.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS121/VS121.png -------------------------------------------------------------------------------- /VS_Series/VS132/README.md: -------------------------------------------------------------------------------- 1 | # 3D ToF People Counting Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to VS132. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![VS132](VS132.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :--------------: | :--: | :--: | :----: | -------------------------------------------------- | 13 | | Protocol Version | 0xFF | 0x01 | 1 | protocol_version(1B) | 14 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 15 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 16 | | Firmware Version | 0xFF | 0x1F | 4 | firmware_version(4B) | 17 | | Total IN | 0x03 | 0xD2 | 4 | total_counter_in(4B) | 18 | | Total OUT | 0x04 | 0xD2 | 4 | total_counter_out(4B) | 19 | | Period IN/OUT | 0x05 | 0xCC | 4 | periodic_counter_in(2B) + periodic_counter_out(2B) | 20 | 21 | ## Example 22 | 23 | ```json 24 | // FF0101 FF166614C39694870000 FF090102 FF1F84010001 03D2BE000000 04D231010000 05CC00000000 25 | { 26 | "protocol_version": 1, 27 | "sn": "6614c39694870000", 28 | "hardware_version": "1.2", 29 | "firmware_version": "132.1.0.1", 30 | "total_counter_in": 190, 31 | "total_counter_out": 305, 32 | "periodic_counter_in": 0, 33 | "periodic_counter_out": 0 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /VS_Series/VS132/VS132.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS132/VS132.png -------------------------------------------------------------------------------- /VS_Series/VS132/VS132.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | def decodeBytes(bytes): 5 | print("bytes:", bytes.hex()) 6 | decoded = {} 7 | 8 | i = 0 9 | while i < len(bytes): 10 | channel_id = bytes[i] 11 | channel_type = bytes[i+1] 12 | i += 2 13 | 14 | # PROTOCOL VESION 15 | if channel_id == 0xFF and channel_type == 0x01: 16 | decoded['protocol_version'] = bytes[i] 17 | i += 1 18 | # SERIAL NUMBER 19 | elif channel_id == 0xFF and channel_type == 0x16: 20 | decoded['sn'] = bytes[i:i+8].hex() 21 | i += 8 22 | # HARDWARE VERSION 23 | elif channel_id == 0xFF and channel_type == 0x09: 24 | decoded['hardware_version'] = "{0}.{1}".format(bytes[i], bytes[i+1]) 25 | i += 2 26 | # FIRMWARE VERSION 27 | elif channel_id == 0xFF and channel_type == 0x1F: 28 | decoded['firmware_version'] = "{0}.{1}.{2}.{3}".format(bytes[i], bytes[i+1], bytes[i+2], bytes[i+3]) 29 | i += 4 30 | # TOTAL COUNTER IN 31 | elif channel_id == 0x03 and channel_type == 0xD2: 32 | decoded['total_counter_in'] = int.from_bytes(bytes[i:i+4], 'little', signed=False) 33 | i += 4 34 | # TOTAL COUNTER OUT 35 | elif channel_id == 0x04 and channel_type == 0xD2: 36 | decoded['total_counter_out'] = int.from_bytes(bytes[i:i+4], 'little', signed=False) 37 | i += 4 38 | # PERIODIC COUNTER 39 | elif channel_id == 0x05 and channel_type == 0xCC: 40 | decoded['periodic_counter_in'] = int.from_bytes(bytes[i:i+2], 'little', signed=False) 41 | decoded['periodic_counter_out'] = int.from_bytes(bytes[i+2:i+4], 'little', signed=False) 42 | i += 4 43 | else: 44 | break 45 | 46 | print(decoded) 47 | return decoded 48 | 49 | 50 | def decodePayload(payload, encoded="base64"): 51 | if encoded == "base64": 52 | bytes = binascii.a2b_base64(payload) 53 | elif encoded == "hex": 54 | bytes = binascii.a2b_hex(payload) 55 | else: 56 | print("unsupport encode type") 57 | 58 | return decodeBytes(bytes) 59 | 60 | 61 | if __name__ == '__main__': 62 | decodePayload("/wEB/xZmFMOWlIcAAP8JAQL/H4QBAAED0r4AAAAE0jEBAAAFzAAAAAA=", "base64") 63 | decodePayload("FF0101FF166614C39694870000FF090102FF1F8401000103D2BE00000004D23101000005CC00000000", "hex") 64 | -------------------------------------------------------------------------------- /VS_Series/VS132/VS132_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product VS132 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // PROTOCOL VESION 32 | if (channel_id === 0xff && channel_type === 0x01) { 33 | decoded.protocol_version = bytes[i]; 34 | i += 1; 35 | } 36 | // SERIAL NUMBER 37 | else if (channel_id === 0xff && channel_type === 0x16) { 38 | decoded.sn = readSerialNumber(bytes.slice(i, i + 8)); 39 | i += 8; 40 | } 41 | // HARDWARE VERSION 42 | else if (channel_id === 0xff && channel_type === 0x09) { 43 | decoded.hardware_version = readVersion(bytes.slice(i, i + 2)); 44 | i += 2; 45 | } 46 | // FIRMWARE VERSION 47 | else if (channel_id === 0xff && channel_type === 0x1f) { 48 | decoded.firmware_version = readVersion(bytes.slice(i, i + 4)); 49 | i += 4; 50 | } 51 | // TOTAL COUNTER IN 52 | else if (channel_id === 0x03 && channel_type === 0xd2) { 53 | decoded.total_counter_in = readUInt32LE(bytes.slice(i, i + 4)); 54 | i += 4; 55 | } 56 | // TOTAL COUNTER OUT 57 | else if (channel_id === 0x04 && channel_type === 0xd2) { 58 | decoded.total_counter_out = readUInt32LE(bytes.slice(i, i + 4)); 59 | i += 4; 60 | } 61 | // PERIODIC COUNTER 62 | else if (channel_id === 0x05 && channel_type === 0xcc) { 63 | decoded.periodic_counter_in = readUInt16LE(bytes.slice(i, i + 2)); 64 | decoded.periodic_counter_out = readUInt16LE(bytes.slice(i + 2, i + 4)); 65 | i += 4; 66 | } else { 67 | break; 68 | } 69 | } 70 | 71 | return decoded; 72 | } 73 | 74 | function readUInt16LE(bytes) { 75 | var value = (bytes[1] << 8) + bytes[0]; 76 | return value & 0xffff; 77 | } 78 | 79 | function readUInt32LE(bytes) { 80 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 81 | return (value & 0xffffffff) >>> 0; 82 | } 83 | 84 | function readVersion(bytes) { 85 | var temp = []; 86 | for (var idx = 0; idx < bytes.length; idx++) { 87 | temp.push((bytes[idx] & 0xff).toString(10)); 88 | } 89 | return temp.join("."); 90 | } 91 | 92 | function readSerialNumber(bytes) { 93 | var temp = []; 94 | for (var idx = 0; idx < bytes.length; idx++) { 95 | temp.push(("0" + (bytes[idx] & 0xff).toString(16)).slice(-2)); 96 | } 97 | return temp.join(""); 98 | } 99 | -------------------------------------------------------------------------------- /VS_Series/VS13x/README.md: -------------------------------------------------------------------------------- 1 | # AI ToF People Counting Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to VS133 / VS135. 4 | 5 | For more detailed information, please visit [Milesight official website](https://www.milesight-iot.com). 6 | 7 | | VS133 | VS135 | 8 | | :-----------------: | :-----------------: | 9 | | ![VS133](VS133.png) | ![VS135](VS135.png) | 10 | 11 | ## Payload Definition 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :-------------------------: | :--: | :--: | :----: | --------------------------------------------------------------------------------- | 15 | | Total In
(Line 1) | 0x03 | 0xD2 | 4 | line_1_total_in(4B) | 16 | | Total Out
(Line 1) | 0x04 | 0xD2 | 4 | line_1_total_out(4B) | 17 | | Period IN/OUT
(Line 1) | 0x05 | 0xCC | 4 | line_1_period_in(2B) + line_1_period_out(2B) | 18 | | Total In
(Line 2) | 0x06 | 0xD2 | 4 | line_2_total_in(4B) | 19 | | Total Out
(Line 2) | 0x07 | 0xD2 | 4 | line_2_total_out(4B) | 20 | | Period IN/OUT
(Line 2) | 0x08 | 0xCC | 4 | line_2_period_in(2B) + line_2_period_out(2B) | 21 | | Total In
(Line 3) | 0x09 | 0xD2 | 4 | line_3_total_in(4B) | 22 | | Total Out
(Line 3) | 0x0A | 0xD2 | 4 | line_3_total_out(4B) | 23 | | Period IN/OUT
(Line 3) | 0x0B | 0xCC | 4 | line_3_period_in(2B) + line_3_period_out(2B) | 24 | | Total In
(Line 4) | 0x0C | 0xD2 | 4 | line_4_total_in(4B) | 25 | | Total Out
(Line 4) | 0x0D | 0xD2 | 4 | line_4_total_out(4B) | 26 | | Period IN/OUT
(Line 4) | 0x0E | 0xCC | 4 | line_4_period_in(2B) + line_4_period_out(2B) | 27 | | Region Count | 0x0F | 0xE3 | 4 | region_1_count(1B) + region_2_count(1B) + region_3_count(1B) + region_4_count(1B) | 28 | | Dwell Time | 0x10 | 0xE4 | 5 | region(1B) + region_avg_dwell(2B) + region_max_dwell(2B) | 29 | 30 | ## Example 31 | 32 | ```json 33 | // 03D248000000 04D2C8000000 06D200000000 07D200000000 09D200000000 0AD200000000 0CD2B4140000 0DD28D1A0000 34 | { 35 | "line_1_total_in": 72, 36 | "line_1_total_out": 200, 37 | "line_2_total_in": 0, 38 | "line_2_total_out": 0, 39 | "line_3_total_in": 0, 40 | "line_3_total_out": 0, 41 | "line_4_total_in": 5300, 42 | "line_4_total_out": 6797 43 | } 44 | 45 | // 05CC00000000 08CC00000000 0BCC00000000 0ECC05000700 46 | { 47 | "line_1_period_in": 0, 48 | "line_1_period_out": 0, 49 | "line_2_period_in": 0, 50 | "line_2_period_out": 0, 51 | "line_3_period_in": 0, 52 | "line_3_period_out": 0, 53 | "line_4_period_in": 5, 54 | "line_4_period_out": 7 55 | } 56 | 57 | // 0FE302100709 58 | { 59 | "region_1_count": 2, 60 | "region_2_count": 16, 61 | "region_3_count": 7, 62 | "region_4_count": 9 63 | } 64 | 65 | // 10E40109101121 10E40275217533 10E40381212389 10E40476001387 66 | { 67 | "region_1_avg_dwell": 4105, 68 | "region_1_max_dwell": 8465, 69 | "region_2_avg_dwell": 8565, 70 | "region_2_max_dwell": 13173, 71 | "region_3_avg_dwell": 8577, 72 | "region_3_max_dwell": 35107, 73 | "region_4_avg_dwell": 118, 74 | "region_4_max_dwell": 34579 75 | } 76 | ``` 77 | -------------------------------------------------------------------------------- /VS_Series/VS13x/VS133.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS13x/VS133.png -------------------------------------------------------------------------------- /VS_Series/VS13x/VS135.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS13x/VS135.png -------------------------------------------------------------------------------- /VS_Series/VS330/README.md: -------------------------------------------------------------------------------- 1 | # Bathroom Occupancy Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to VS330. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/vs330). 6 | 7 | ![VS330](VS330.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :---------: | :--: | :--: | :----: | ------------------------------------------------------------------------------ | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Distance | 0x02 | 0x82 | 2 | distance(2B)
distance, unit: mm | 15 | | Occupancy | 0x03 | 0x8E | 1 | occupancy(1B)
occupancy, values: (0: vacant, 1: occupied) | 16 | | Calibration | 0x04 | 0x8E | 1 | calibration_status(1B)
calibration_status, values: (0: failed, 1: success) | 17 | 18 | ## Example 19 | 20 | ```json 21 | // 017562 02820F00 038E01 048E01 22 | 23 | { 24 | "battery": 98, 25 | "distance": 15, 26 | "occupancy": "occupied", 27 | "calibration_status": "success" 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /VS_Series/VS330/VS330.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS330/VS330.png -------------------------------------------------------------------------------- /VS_Series/VS330/VS330.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | def decodeBytes(bytes): 5 | print("bytes:", bytes.hex()) 6 | decoded = {} 7 | 8 | i = 0 9 | while i < len(bytes): 10 | channel_id = bytes[i] 11 | channel_type = bytes[i+1] 12 | i += 2 13 | 14 | # BATTERY 15 | if channel_id == 0x01 and channel_type == 0x75: 16 | decoded['battery'] = bytes[i] 17 | i += 1 18 | # DISTANCE 19 | elif channel_id == 0x02 and channel_type == 0x82: 20 | decoded['distance'] = int.from_bytes(bytes[i: i + 2], 'little', signed=False) 21 | i += 2 22 | # OCCUPANCY 23 | elif channel_id == 0x03 and channel_type == 0X8E: 24 | decoded['occupancy'] = 'vacant' if (bytes[i] == 0) else 'occupied' 25 | i += 1 26 | # CALIBRATION 27 | elif channel_id == 0x04 and channel_type == 0X8E: 28 | decoded['calibration'] = 'success' if (bytes[i] == 1) else 'failed' 29 | i += 1 30 | else: 31 | break 32 | 33 | print(decoded) 34 | return decoded 35 | 36 | 37 | def decodePayload(payload, encoded="base64"): 38 | if encoded == "base64": 39 | bytes = binascii.a2b_base64(payload) 40 | elif encoded == "hex": 41 | bytes = binascii.a2b_hex(payload) 42 | else: 43 | print("unsupport encode type") 44 | 45 | return decodeBytes(bytes) 46 | 47 | 48 | if __name__ == '__main__': 49 | decodePayload("AXViAoIPAAOOAQSOAQ==", "base64") 50 | decodePayload("01756202820F00038E01048E01", "hex") 51 | -------------------------------------------------------------------------------- /VS_Series/VS340/README.md: -------------------------------------------------------------------------------- 1 | # Desk & Seat Occupancy Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to VS340/VS341. 4 | For more detailed information, please visit [Milesight official website](https://www.milesight-iot.com). 5 | 6 | | VS340 | VS341 | 7 | | :-----------------: | :-----------------: | 8 | | ![VS340](VS340.png) | ![VS341](VS341.png) | 9 | 10 | ## Payload Definition 11 | 12 | | CHANNEL | ID | TYPE | LENGTH (bytes) | description | 13 | | :-------: | :--: | :--: | :------------: | ------------------------------------------------------------ | 14 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit:% | 15 | | Occupancy | 0x03 | 0x00 | 1 | occupancy(1B)
occupancy, values:(0: vacant, 1: occupied) | 16 | 17 | ## Example 18 | 19 | ```json 20 | // 017564 030000 21 | { 22 | "battery": 100, 23 | "occupancy": "vacant" 24 | } 25 | 26 | // 017564 030001 27 | { 28 | "battery": 100, 29 | "occupancy": "occupied" 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /VS_Series/VS340/VS340.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS340/VS340.png -------------------------------------------------------------------------------- /VS_Series/VS340/VS340.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | def decodeBytes(bytes): 5 | print("bytes:", bytes.hex()) 6 | decoded = {} 7 | 8 | i = 0 9 | while i < len(bytes): 10 | channel_id = bytes[i] 11 | channel_type = bytes[i+1] 12 | i += 2 13 | 14 | # BATTERY 15 | if channel_id == 0x01 and channel_type == 0x75: 16 | decoded['battery'] = bytes[i] 17 | i += 1 18 | # OCCUPANCY 19 | elif channel_id == 0x03 and channel_type == 0X00: 20 | decoded['occupancy'] = 'vacant' if (bytes[i] == 0) else 'occupied' 21 | i += 1 22 | else: 23 | break 24 | 25 | print(decoded) 26 | return decoded 27 | 28 | 29 | def decodePayload(payload, encoded="base64"): 30 | if encoded == "base64": 31 | bytes = binascii.a2b_base64(payload) 32 | elif encoded == "hex": 33 | bytes = binascii.a2b_hex(payload) 34 | else: 35 | print("unsupport encode type") 36 | 37 | return decodeBytes(bytes) 38 | 39 | 40 | if __name__ == '__main__': 41 | decodePayload("AXVkAwAA", "base64") 42 | decodePayload("017562030001", "hex") -------------------------------------------------------------------------------- /VS_Series/VS340/VS340_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product VS340 / VS341 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // OCCUPANCY 36 | else if (channel_id === 0x03 && channel_type === 0x00) { 37 | decoded.occupancy = bytes[i] === 0 ? "vacant" : "occupied"; 38 | i += 1; 39 | } else { 40 | break; 41 | } 42 | } 43 | 44 | return decoded; 45 | } 46 | -------------------------------------------------------------------------------- /VS_Series/VS340/VS341.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS340/VS341.png -------------------------------------------------------------------------------- /VS_Series/VS350/VS350.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS350/VS350.png -------------------------------------------------------------------------------- /VS_Series/VS351/VS351.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS351/VS351.png -------------------------------------------------------------------------------- /VS_Series/VS351/VS351_Battery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS351/VS351_Battery.png -------------------------------------------------------------------------------- /VS_Series/VS360/VS360.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS360/VS360.png -------------------------------------------------------------------------------- /VS_Series/VS370/README.md: -------------------------------------------------------------------------------- 1 | # Radar Human Presence Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to VS370. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/vs370). 6 | 7 | ![VS370](VS370.png) 8 | 9 | ## Payload Definition 10 | 11 | ### ATTRIBUTE 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :--------------- | :--: | :--: | :----: | :------------------------------------------------------------------------------------------------ | 15 | | Protocol Version | 0xFF | 0x01 | 1 | ipso_version(1B) | 16 | | Device Status | 0xFF | 0x0B | 1 | device_status(1B) | 17 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 18 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 19 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 20 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 21 | | LoRaWAN Class | 0xFF | 0x0F | 1 | lorawan_class(1B)
lorawan_class, values: (0: Class A, 1: Class B, 2: Class C, 3: Class CtoB) | 22 | 23 | ### TELEMETRY 24 | 25 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 26 | | :---------- | :--: | :--: | :----: | :--------------------------------------------------------------------------- | 27 | | Battery | 0x01 | 0x75 | 1 | battery(1B) | 28 | | Occupancy | 0x03 | 0x00 | 1 | occupancy(1B)
occupancy, values: (0: vacant, 1: occupied) | 29 | | Illuminance | 0x04 | 0x00 | 1 | illuminance(1B)
illuminance, values: (0: dim, 1: bright, 0xFE: disable) | 30 | 31 | # Sample 32 | 33 | ```json 34 | // 017564030001040000 35 | { 36 | "battery": 100, 37 | "illuminance": "dim", 38 | "occupancy": "occupied" 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /VS_Series/VS370/VS370.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS370/VS370.png -------------------------------------------------------------------------------- /VS_Series/VS373/README.md: -------------------------------------------------------------------------------- 1 | # Radar Fall Detection Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to VS373. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/vs373). 6 | 7 | ![VS373](VS373.png) 8 | 9 | ## Payload Definition 10 | 11 | ### ATTRIBUTES 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :--------------- | :--: | :--: | :----: | :-------------------------------------------------------------------------------------------- | 15 | | Protocol Version | 0xFF | 0x01 | 1 | ipso_version(1B) | 16 | | Device Status | 0xFF | 0x0B | 1 | device_status(1B) | 17 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 18 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 19 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 20 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 21 | | LoRaWAN Class | 0xFF | 0x0F | 1 | lorawan_class(1B)
lorawan_class, values: (0: classA, 1: classB, 2: classC, 3: classCtoB) | 22 | 23 | ### TELEMETRY 24 | 25 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 26 | | :--------------------- | :--: | :--: | :----: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 27 | | Room Detection | 0x03 | 0xF8 | 6 | detection_status(1B) + target_status(1B) + use_time_now(2B) + use_time_today(2B)
detection_status, values: (0: normal, 1: vacant, 2: in bed, 3: out of bed, 4: fall)
target_status, values: (0: normal, 1: motionless, 2: abnormal) | 28 | | Region Detection | 0x04 | 0xF9 | 4 | region_1_occupancy(1B) + region_2_occupancy(1B) + region_3_occupancy(1B) + region_4_occupancy(1B)
region_1_occupancy, values: (0: occupied, 1: vacant) | 29 | | Region Out of Bed Time | 0x05 | 0xFA | 8 | region_1_out_of_bed_time(2B) + region_2_out_of_bed_time(2B) + region_3_out_of_bed_time(2B) + region_4_out_of_bed_time(2B)
region_1_out_of_bed_time, unit: second | 30 | | Alarm Event | 0x06 | 0xFB | 5 | alarm_id(2B) + alarm_type(1B) + alarm_status(1B) + alarm_region_id(1B)
alarm_type, values: (0: normal, 1: motionless, 2: dwell, 3: out of bed, 4: occupied, 5: vacant)
alarm_status, values: (0: alarm triggered, 1: alarm deactivated, 2: alarm ignored) | 31 | | Historical Data | 0x20 | 0xCE | 9 | timestamp(4B) + alarm_id(2B) + alarm_type(1B) + alarm_status(1B) + alarm_region_id(1B) | 32 | 33 | # Sample 34 | 35 | ```json 36 | 37 | ``` 38 | -------------------------------------------------------------------------------- /VS_Series/VS373/VS373.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/VS_Series/VS373/VS373.png -------------------------------------------------------------------------------- /WS_Series/WS101/README.md: -------------------------------------------------------------------------------- 1 | # Smart Button - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS101. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | | WS101 | WS101 SOS | 8 | | :-----------------: | :-------------------------: | 9 | | ![WS101](WS101.png) | ![WS101_SOS](WS101_SOS.png) | 10 | 11 | ## Payload Definition 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :----------: | :--: | :--: | :----: | ----------------------------------------------------------- | 15 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 16 | | Button Press | 0xFF | 0x2E | 1 | press(1B)
press, values: (1: short, 2: long, 3: double) | 17 | 18 | ## Example 19 | 20 | ```json 21 | // 017510 FF2E01 22 | { 23 | "battery": 16, 24 | "press": "short" 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /WS_Series/WS101/WS101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS101/WS101.png -------------------------------------------------------------------------------- /WS_Series/WS101/WS101_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product WS101 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // PRESS STATE 36 | else if (channel_id === 0xff && channel_type === 0x2e) { 37 | var type = bytes[i]; 38 | i += 1; 39 | 40 | switch (type) { 41 | case 1: 42 | decoded.press = "short"; 43 | break; 44 | case 2: 45 | decoded.press = "long"; 46 | break; 47 | case 3: 48 | decoded.press = "double"; 49 | break; 50 | default: 51 | decoded.press = "unknown"; 52 | break; 53 | } 54 | } else { 55 | break; 56 | } 57 | } 58 | 59 | return decoded; 60 | } 61 | -------------------------------------------------------------------------------- /WS_Series/WS101/WS101_SOS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS101/WS101_SOS.png -------------------------------------------------------------------------------- /WS_Series/WS136&WS156/README.md: -------------------------------------------------------------------------------- 1 | # Smart Scene Panel - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS136 / WS156. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | | WS136 | WS156 | 8 | | :-----------------: | :-----------------: | 9 | | ![WS136](WS136.png) | ![WS156](WS156.png) | 10 | 11 | ## Payload Definition 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :----------: | :--: | :--: | :----: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 15 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 16 | | Button Press | 0xFF | 0x34 | 1 | id(1B) + button_id_mode(1B) + button_id_event(1B)
mode: values: (0: short_press, 1: short_press+double_press, 2: short_press+long_press, 3: short_press+double_press+long_press)
event, values: (1: short_press, 2: double_press, 3: long_press) | 17 | 18 | ## Example 19 | 20 | ```json 21 | // 017510 FF2E01 22 | { 23 | "battery": 16, 24 | "press": "short" 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /WS_Series/WS136&WS156/WS136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS136&WS156/WS136.png -------------------------------------------------------------------------------- /WS_Series/WS136&WS156/WS136_WS156_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product WS136 & WS156 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // PRESS STATE 37 | else if (channel_id === 0xff && channel_type === 0x34) { 38 | var id = bytes[i]; 39 | var btn_mode_name = "button_" + id + "_mode"; 40 | var btn_chn_event_name = "button_" + id + "_event"; 41 | switch (bytes[i + 1]) { 42 | case 0x00: 43 | decoded[btn_mode_name] = ["short_press"]; 44 | break; 45 | case 0x01: 46 | decoded[btn_mode_name] = ["short_press", "double_press"]; 47 | break; 48 | case 0x02: 49 | decoded[btn_mode_name] = ["short_press", "long_press"]; 50 | break; 51 | case 0x03: 52 | decoded[btn_mode_name] = ["short_press", "double_press", "long_press"]; 53 | break; 54 | default: 55 | decoded[btn_mode_name] = ["unknown"]; 56 | } 57 | switch (bytes[i + 2]) { 58 | case 0x00: 59 | decoded[btn_chn_event_name] = "short_press"; 60 | break; 61 | case 0x01: 62 | decoded[btn_chn_event_name] = "double_press"; 63 | break; 64 | case 0x02: 65 | decoded[btn_chn_event_name] = "long_press"; 66 | break; 67 | default: 68 | decoded[btn_chn_event_name] = "unknown"; 69 | } 70 | i += 3; 71 | } else { 72 | break; 73 | } 74 | } 75 | 76 | return decoded; 77 | } 78 | -------------------------------------------------------------------------------- /WS_Series/WS136&WS156/WS156.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS136&WS156/WS156.png -------------------------------------------------------------------------------- /WS_Series/WS201/README.md: -------------------------------------------------------------------------------- 1 | # Smart Fill Level Monitoring Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS201. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![WS201](WS201.png) 8 | 9 | ## Payload Definition 10 | 11 | ### Attribute 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :----------------: | :--: | :--: | :----: | -------------------- | 15 | | Protocol Version | 0xFF | 0x01 | 1 | protocol_version(1B) | 16 | | Power Status | 0xFF | 0x0B | 1 | power(1B) | 17 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 18 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 19 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 20 | | LoRaWAN Class Type | 0xFF | 0x0F | 1 | lorawan_class(1B) | 21 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 22 | 23 | ### Telemetry 24 | 25 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 26 | | :-------: | :--: | :--: | :----: | ------------------------------------- | 27 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 28 | | Distance | 0x03 | 0x82 | 2 | distance(2B)
distance, unit: mm | 29 | | Remaining | 0x04 | 0xD6 | 1 | remaining(1B)
remaining, unit: % | 30 | 31 | ## Example 32 | 33 | ```json 34 | // 017564 03823E00 04D645 35 | { 36 | "battery": 100, 37 | "distance": 62, 38 | "remaining": 69 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /WS_Series/WS201/WS201.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS201/WS201.png -------------------------------------------------------------------------------- /WS_Series/WS202/README.md: -------------------------------------------------------------------------------- 1 | # PIR & Light Sensor - Milesight IoT 2 | 3 | The payload decoder function applies to WS202. 4 | 5 | For more detailed information, please visit Milesight's [official website](https://www.milesight-iot.com). 6 | 7 | ![WS202](WS202.png) 8 | 9 | ## Payload Definition 10 | 11 | ### Attribute 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :----------------: | :--: | :--: | :----: | -------------------- | 15 | | Protocol Version | 0xFF | 0x01 | 1 | protocol_version(1B) | 16 | | Power Status | 0xFF | 0x0B | 1 | power_status(1B) | 17 | | Serial Number | 0xFF | 0x16 | 8 | sn(8B) | 18 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 19 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 20 | | LoRaWAN Class Type | 0xFF | 0x0F | 1 | lorawan_class(1B) | 21 | | TSL Version | 0xFF | 0xFF | 2 | tsl_version(2B) | 22 | 23 | ### Telemetry 24 | 25 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 26 | | :------: | :--: | :--: | :----: | ------------------------------------------------------- | 27 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 28 | | PIR | 0x03 | 0x00 | 1 | pir(1B)
pir, values: (0: normal, 1: trigger) | 29 | | Daylight | 0x04 | 0x00 | 1 | daylight(1B)
daylight, values: (0: dark, 1: light) | 30 | 31 | ## Example 32 | 33 | ```json 34 | // 017510 030001 040000 35 | { 36 | "battery": 16, 37 | "pir": "trigger", 38 | "daylight": "dark" 39 | } 40 | ``` 41 | -------------------------------------------------------------------------------- /WS_Series/WS202/WS202.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS202/WS202.png -------------------------------------------------------------------------------- /WS_Series/WS203/README.md: -------------------------------------------------------------------------------- 1 | # PIR & Temperature - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS203. 4 | 5 | For more detailed information, please visit [Milesight official website](https://www.milesight-iot.com). 6 | 7 | ![WS203](WS203.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :------------------: | :--: | :--: | :----: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Temperature | 0x03 | 0x67 | 2 | temperature(2B)
temperature, unit: ℃ | 15 | | Humidity | 0x04 | 0x68 | 1 | humidity(1B)
humidity, unit: %RH | 16 | | Occupancy | 0x05 | 0x00 | 1 | occupancy(1B)
occupancy, values(0: vacant, 1: occupied) | 17 | | Temperature Abnormal | 0x83 | 0x67 | 3 | temperature(2B) + temperature_abnormal(1B) | 18 | | Historical Data | 0x20 | 0xCE | 9 | timestamp(4B) + report_type(1B) + occupancy(1B) + temperature(2B) + humidity(1B)
report_type, values: (0: temperature resume, 1: temperature threshold, 2: pir ilde, 3: pir occupancy, 4: period) | 19 | 20 | ## Example 21 | 22 | ```json 23 | // 017564 03673401 046865 050000 24 | { 25 | "battery": 100, 26 | "humidity": 50.5, 27 | "occupancy": "vacant", 28 | "temperature": 30.8 29 | } 30 | 31 | // 8367220101 32 | { 33 | "temperature": 29, 34 | "temperature_abnormal": "abnormal" 35 | } 36 | 37 | // 20CEAE5BA6640400240165 20CE5C5CA6640301340165 38 | { 39 | "history": [ 40 | { 41 | "humidity": 50.5, 42 | "occupancy": "vacant", 43 | "report_type": "period", 44 | "temperature": 29.2, 45 | "timestamp": 1688624046 46 | }, 47 | { 48 | "humidity": 50.5, 49 | "occupancy": "occupied", 50 | "report_type": "pir occupancy", 51 | "temperature": 30.8, 52 | "timestamp": 1688624220 53 | } 54 | ] 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /WS_Series/WS203/WS203.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS203/WS203.png -------------------------------------------------------------------------------- /WS_Series/WS203/WS203_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product WS203 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // TEMPERATURE 36 | else if (channel_id === 0x03 && channel_type === 0x67) { 37 | // ℃ 38 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 39 | i += 2; 40 | 41 | // ℉ 42 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 43 | // i +=2; 44 | } 45 | // HUMIDITY 46 | else if (channel_id === 0x04 && channel_type === 0x68) { 47 | decoded.humidity = bytes[i] / 2; 48 | i += 1; 49 | } 50 | // OCCUPANCY 51 | else if (channel_id === 0x05 && channel_type === 0x00) { 52 | decoded.occupancy = bytes[i] === 0 ? "vacant" : "occupied"; 53 | i += 1; 54 | } 55 | // TEMPERATURE WITH ABNORMAL 56 | else if (channel_id === 0x83 && channel_type === 0x67) { 57 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 58 | decoded.temperature_abnormal = bytes[i + 2] === 0 ? "normal" : "abnormal"; 59 | i += 3; 60 | } 61 | // HISTORICAL DATA 62 | else if (channel_id === 0x20 && channel_type === 0xce) { 63 | var data = {}; 64 | data.timestamp = readUInt32LE(bytes.slice(i, i + 4)); 65 | var report_type = bytes[i + 4]; 66 | data.report_type = ["temperature resume", "temperature threshold", "pir idle", "pir occupancy", "period"][report_type & 0x07]; 67 | data.occupancy = bytes[i + 5] === 0 ? "vacant" : "occupied"; 68 | data.temperature = readInt16LE(bytes.slice(i + 6, i + 8)) / 10; 69 | data.humidity = bytes[i + 8] / 2; 70 | i += 9; 71 | 72 | decoded.history = decoded.history || []; 73 | decoded.history.push(data); 74 | } else { 75 | break; 76 | } 77 | } 78 | 79 | return decoded; 80 | } 81 | 82 | function readUInt8(bytes) { 83 | return bytes & 0xff; 84 | } 85 | 86 | function readInt8(bytes) { 87 | var ref = readUInt8(bytes); 88 | return ref > 0x7f ? ref - 0x100 : ref; 89 | } 90 | 91 | function readUInt16LE(bytes) { 92 | var value = (bytes[1] << 8) + bytes[0]; 93 | return value & 0xffff; 94 | } 95 | 96 | function readInt16LE(bytes) { 97 | var ref = readUInt16LE(bytes); 98 | return ref > 0x7fff ? ref - 0x10000 : ref; 99 | } 100 | 101 | function readUInt32LE(bytes) { 102 | var value = (bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]; 103 | return (value & 0xffffffff) >>> 0; 104 | } 105 | 106 | function readInt32LE(bytes) { 107 | var ref = readUInt32LE(bytes); 108 | return ref > 0x7fffffff ? ref - 0x100000000 : ref; 109 | } 110 | -------------------------------------------------------------------------------- /WS_Series/WS301/README.md: -------------------------------------------------------------------------------- 1 | # Magnetic Contact Switch - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS301. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![WS301](WS301.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :-----------: | :--: | :--: | :----: | --------------------------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Magnet Status | 0x03 | 0x00 | 1 | magnet_status(1B)
state, values: (0: close, 1: open) | 15 | | Tamper Status | 0x04 | 0x00 | 1 | tamper_status(1B)
tamper_status, values: (0: installed, 1: uninstalled) | 16 | 17 | ## Example 18 | 19 | ```json 20 | // 017564 030001 040001 21 | { 22 | "battery": 100, 23 | "magnet_status": "open", 24 | "tamper_status": "installed" 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /WS_Series/WS301/WS301.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS301/WS301.png -------------------------------------------------------------------------------- /WS_Series/WS301/WS301_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product WS301 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // DOOR / WINDOW STATE (0: close 1: open) 37 | else if (channel_id === 0x03 && channel_type === 0x00) { 38 | decoded.magnet_status = bytes[i] === 0 ? "close" : "open"; 39 | i += 1; 40 | } 41 | // INSTALL STATE (0: install 1: uninstall) 42 | else if (channel_id === 0x04 && channel_type === 0x00) { 43 | decoded.tamper_status = bytes[i] === 0 ? "installed" : "uninstalled"; 44 | i += 1; 45 | } else { 46 | break; 47 | } 48 | } 49 | 50 | return decoded; 51 | } 52 | -------------------------------------------------------------------------------- /WS_Series/WS302/README.md: -------------------------------------------------------------------------------- 1 | # Sound Contact Switch - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS302. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![WS302](WS302.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :---------: | :--: | :--: | :----: | -------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit: % | 14 | | Sound Level | 0x05 | 0x5B | 7 | wight(1B) + l(2B) + leq(2B) + lmax(2B) | 15 | 16 | ## Example 17 | 18 | ```json 19 | // 017564 055B053F02DA016A02 20 | { 21 | "battery": 100, 22 | "LAF": 57.5, 23 | "LAeq": 47.4, 24 | "LAFmax": 61.8 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /WS_Series/WS302/WS302.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS302/WS302.png -------------------------------------------------------------------------------- /WS_Series/WS302/WS302_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product WS302 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | 31 | // BATTERY 32 | if (channel_id === 0x01 && channel_type === 0x75) { 33 | decoded.battery = bytes[i]; 34 | i += 1; 35 | } 36 | // SOUND 37 | else if (channel_id === 0x05 && channel_type === 0x5b) { 38 | var weight = bytes[i]; 39 | var freq_weight = readFrequencyWeightType(weight & 0x03); 40 | var time_weight = readTimeWeightType((weight >> 2) & 0x03); 41 | 42 | sound_level_name = "L" + freq_weight + time_weight; 43 | sound_level_eq_name = "L" + freq_weight + "eq"; 44 | sound_level_max_name = "L" + freq_weight + time_weight + "max"; 45 | decoded[sound_level_name] = readUInt16LE(bytes.slice(i + 1, i + 3)) / 10; 46 | decoded[sound_level_eq_name] = readUInt16LE(bytes.slice(i + 3, i + 5)) / 10; 47 | decoded[sound_level_max_name] = readUInt16LE(bytes.slice(i + 5, i + 7)) / 10; 48 | i += 7; 49 | } 50 | // LoRaWAN Class Type 51 | else if (channel_id === 0xff && channel_type === 0x0f) { 52 | decoded.lorawan_class = readLoRaWANClass(bytes[i]); 53 | i += 1; 54 | } else { 55 | break; 56 | } 57 | } 58 | 59 | return decoded; 60 | } 61 | 62 | function readFrequencyWeightType(type) { 63 | switch (type) { 64 | case 0: 65 | return "Z"; 66 | case 1: 67 | return "A"; 68 | case 2: 69 | return "C"; 70 | } 71 | } 72 | 73 | function readTimeWeightType(type) { 74 | switch (type) { 75 | case 0: // impulse time weighting 76 | return "I"; 77 | case 1: // fast time weighting 78 | return "F"; 79 | case 2: // slow time weighting 80 | return "S"; 81 | } 82 | } 83 | 84 | function readUInt16LE(bytes) { 85 | var value = (bytes[1] << 8) + bytes[0]; 86 | return value & 0xffff; 87 | } 88 | 89 | function readInt16LE(bytes) { 90 | var ref = readUInt16LE(bytes); 91 | return ref > 0x7fff ? ref - 0x10000 : ref; 92 | } 93 | 94 | function readLoRaWANClass(type) { 95 | switch (type) { 96 | case 0: 97 | return "ClassA"; 98 | case 1: 99 | return "ClassB"; 100 | case 2: 101 | return "ClassC"; 102 | case 3: 103 | return "ClassCtoB"; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /WS_Series/WS303/README.md: -------------------------------------------------------------------------------- 1 | # Mini Leak Detection Sensor - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS303. 4 | 5 | For more detailed information, please visit [milesight official website](https://www.milesight-iot.com). 6 | 7 | ![WS303](WS303.png) 8 | 9 | ## Payload Definition 10 | 11 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 12 | | :------------: | :--: | :--: | :----: | ----------------------------------------------------------- | 13 | | Battery | 0x01 | 0x75 | 1 | battery(1B)
battery, unit:% | 14 | | Leakage Status | 0x03 | 0x00 | 1 | leakage_status(1B)
leakage_status: (0:normal, 1:leak) | 15 | 16 | ## Example 17 | 18 | ```json 19 | // 017564 030000 20 | { 21 | "battery": 100, 22 | "leakage_status": "normal" 23 | } 24 | 25 | // 017564 030001 26 | { 27 | "battery": 100, 28 | "leakage_status": "leak" 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /WS_Series/WS303/WS303.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS303/WS303.png -------------------------------------------------------------------------------- /WS_Series/WS303/WS303.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | 3 | 4 | def decodeBytes(bytes): 5 | print("bytes:", bytes.hex()) 6 | decoded = {} 7 | 8 | i = 0 9 | while i < len(bytes): 10 | channel_id = bytes[i] 11 | channel_type = bytes[i + 1] 12 | i += 2 13 | 14 | # BATTERY 15 | if channel_id == 0x01 and channel_type == 0x75: 16 | decoded["battery"] = bytes[i] 17 | i += 1 18 | # WATER LEAK DECTECT 19 | elif channel_id == 0x03 and channel_type == 0x00: 20 | decoded["leakage_status"] = "leak" if bytes[i] else "normal" 21 | i += 1 22 | else: 23 | break 24 | 25 | print(decoded) 26 | return decoded 27 | 28 | 29 | def decodePayload(payload, encoded="base64"): 30 | if encoded == "base64": 31 | bytes = binascii.a2b_base64(payload) 32 | elif encoded == "hex": 33 | bytes = binascii.a2b_hex(payload) 34 | else: 35 | print("unsupport encode type") 36 | 37 | return decodeBytes(bytes) 38 | 39 | 40 | if __name__ == "__main__": 41 | decodePayload("AXVkAwAA", "base64") 42 | decodePayload("017564030001", "hex") 43 | -------------------------------------------------------------------------------- /WS_Series/WS303/WS303_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product WS303 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // WATER LEAK 36 | else if (channel_id === 0x03 && channel_type === 0x00) { 37 | decoded.leakage_status = bytes[i] === 0 ? "normal" : "leak"; 38 | i += 1; 39 | } else { 40 | break; 41 | } 42 | } 43 | 44 | return decoded; 45 | } 46 | -------------------------------------------------------------------------------- /WS_Series/WS50x/README.md: -------------------------------------------------------------------------------- 1 | # Smart Wall Switch - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS501 / WS502 / WS503. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/ws50x). 6 | 7 | | WS50x | 8 | | :-----------------: | 9 | | ![WS50x](WS50x.png) | 10 | 11 | ## Payload Definition 12 | 13 | ### Attributes 14 | 15 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 16 | | :--------------: | :--: | :--: | :----: | -------------------- | 17 | | IPSO Version | 0xFF | 0x01 | 1 | ipso_version(1B) | 18 | | Hardware Version | 0xFF | 0x09 | 2 | hardware_version(2B) | 19 | | Firmware Version | 0xFF | 0x0A | 2 | firmware_version(2B) | 20 | | Serial Number | 0xFF | 0x08 | 6 | sn(6B) | 21 | | Lorawan Class | 0xFF | 0x0F | 1 | lorawan_class(1B) | 22 | 23 | ### Telemetry 24 | 25 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 26 | | :-----------: | :--: | :--: | :----: | ---------------------------- | 27 | | Switch Status | 0xFF | 0x29 | 1 | switch_1, switch_2, switch_3 | 28 | | Button Status | 0xFF | 0x2B | 1 | button_trigger(1B) | 29 | 30 | ### Status Definition 31 | 32 | | bits | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 33 | | :--: | :-: | :-------------: | :-------------: | :-------------: | :-: | :------: | :------: | :------: | 34 | | | - | switch_3_change | switch_2_change | switch_1_change | - | switch_3 | switch_2 | switch_1 | 35 | 36 | ## Example 37 | 38 | ```json 39 | // FF2931 40 | { 41 | "switch_1": "on", 42 | "switch_2": "off", 43 | "switch_3": "off", 44 | "switch_1_change": "yes", 45 | "switch_2_change": "yes", 46 | "switch_3_change": "no" 47 | } 48 | ``` 49 | -------------------------------------------------------------------------------- /WS_Series/WS50x/WS50x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS50x/WS50x.png -------------------------------------------------------------------------------- /WS_Series/WS50x_CN/README.md: -------------------------------------------------------------------------------- 1 | # Smart Wall Switch - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS501 / WS502 / WS503. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/ws50x). 6 | 7 | | WS50x | 8 | | :--------------------: | 9 | | ![WS50x](WS50x_CN.png) | 10 | 11 | ## Payload Definition 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :-----: | :--: | :--: | :----: | ----------- | 15 | | Switch | 0x08 | 0x29 | 1 | status(1B) | 16 | 17 | ### Status Definition 18 | 19 | | bits | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 20 | | :--: | :-: | :-------------: | :-------------: | :-------------: | :-: | :------: | :------: | :------: | 21 | | | - | switch_3_change | switch_2_change | switch_1_change | - | switch_3 | switch_2 | switch_1 | 22 | 23 | ## Example 24 | 25 | ```json 26 | // FF2931 27 | { 28 | "switch_1": "on", 29 | "switch_2": "off", 30 | "switch_3": "off", 31 | "switch_1_change": "yes", 32 | "switch_2_change": "yes", 33 | "switch_3_change": "no" 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /WS_Series/WS50x_CN/WS50x_CN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS50x_CN/WS50x_CN.png -------------------------------------------------------------------------------- /WS_Series/WS50x_EU/README.md: -------------------------------------------------------------------------------- 1 | # Smart Wall Switch - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS501 / WS502. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/ws50x). 6 | 7 | | WS50x | 8 | | :--------------------: | 9 | | ![WS50x](WS50x_EU.png) | 10 | 11 | ## Payload Definition 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :---------------: | :--: | :--: | :----: | ----------------------------------------------------- | 15 | | Voltage | 0x03 | 0x74 | 2 | voltage(2B)
voltage, read: uint16/10 | 16 | | Active Power | 0x04 | 0x80 | 4 | power(4B)
power, read: uint32, unit: W | 17 | | Active Factor | 0x05 | 0x81 | 1 | factor(1B)
factor, read: uint8, unit: % | 18 | | Power Consumption | 0x06 | 0x83 | 4 | power_sum(4B)
power_sum, read: uint32, unit: W\*h | 19 | | Current | 0x07 | 0xC9 | 2 | current(2B)
current, read: uint16, unit: mA | 20 | | Switch | 0x08 | 0x29 | 1 | status(1B) | 21 | 22 | ### Status Definition 23 | 24 | | bits | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 25 | | :--: | :-: | :-: | :-------------: | :-------------: | :-: | :-: | :------: | :------: | 26 | | | - | - | switch_2_change | switch_1_change | - | - | switch_2 | switch_1 | 27 | 28 | ## Example 29 | 30 | ```json 31 | // FF2931 32 | { 33 | "switch_1": "on", 34 | "switch_2": "off", 35 | "switch_1_change": "yes", 36 | "switch_2_change": "yes" 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /WS_Series/WS50x_EU/WS50x_EU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS50x_EU/WS50x_EU.png -------------------------------------------------------------------------------- /WS_Series/WS50x_US/README.md: -------------------------------------------------------------------------------- 1 | # Smart Wall Switch - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS501. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/ws50x). 6 | 7 | | WS50x | 8 | | :--------------------: | 9 | | ![WS50x](WS50x_US.png) | 10 | 11 | ## Payload Definition 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :---------------: | :--: | :--: | :----: | ----------------------------------------------------- | 15 | | Voltage | 0x03 | 0x74 | 2 | voltage(2B)
voltage, read: uint16/10 | 16 | | Active Power | 0x04 | 0x80 | 4 | power(4B)
power, read: uint32, unit: W | 17 | | Active Factor | 0x05 | 0x81 | 1 | factor(1B)
factor, read: uint8, unit: % | 18 | | Power Consumption | 0x06 | 0x83 | 4 | power_sum(4B)
power_sum, read: uint32, unit: W\*h | 19 | | Current | 0x07 | 0xC9 | 2 | current(2B)
current, read: uint16, unit: mA | 20 | | Switch | 0x08 | 0x29 | 1 | status(1B) | 21 | 22 | ### Status Definition 23 | 24 | | bits | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 25 | | :--: | :-: | :-: | :-: | :-------------: | :-: | :-: | :-: | :------: | 26 | | | - | - | - | switch_1_change | - | - | - | switch_1 | 27 | 28 | ## Example 29 | 30 | ```json 31 | // FF2931 32 | { 33 | "switch_1": "on", 34 | "switch_1_change": "yes" 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /WS_Series/WS50x_US/WS50x_US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS50x_US/WS50x_US.png -------------------------------------------------------------------------------- /WS_Series/WS51x/WS513.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS51x/WS513.png -------------------------------------------------------------------------------- /WS_Series/WS51x/WS513_EU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS51x/WS513_EU.png -------------------------------------------------------------------------------- /WS_Series/WS51x/WS515.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS51x/WS515.png -------------------------------------------------------------------------------- /WS_Series/WS52x/README.md: -------------------------------------------------------------------------------- 1 | # Smart Portable Socket - Milesight IoT 2 | 3 | The payload decoder function applies to WS52X. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/ws523). 6 | 7 | | WS523-CN-16A | WS525-CN-10A | WS523-UK | WS523-US | WS523-AU | WS523-EU | 8 | | :------------------------: | :------------------------: | :-----------------------: | :-----------------------: | :-----------------------: | :-----------------------: | 9 | | ![WS523](WS523_CN_16A.png) | ![WS525](WS525_CN_10A.png) | ![WS523-UK](WS523_UK.png) | ![WS523-US](WS523_US.png) | ![WS523-AU](WS523_AU.png) | ![WS523-EU](WS523_EU.png) | 10 | 11 | ## Payload Definition 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :---------------: | :--: | :--: | :----: | ---------------------------------------------------------------------- | 15 | | Voltage | 0x03 | 0x74 | 2 | voltage(2B)
voltage, read: uint16/10 | 16 | | Active Power | 0x04 | 0x80 | 4 | active_power(4B)
active_power, read: uint32, unit: W | 17 | | Power Factor | 0x05 | 0x81 | 1 | power_factor(1B)
power_factor, read: uint8 | 18 | | Power Consumption | 0x06 | 0x83 | 4 | power_consumption(4B)
power_consumption, read: uint32, unit: W\*h | 19 | | Current | 0x07 | 0xC9 | 2 | current(2B)
current, read: uint16, unit: mA | 20 | | Socket Status | 0x08 | 0x70 | 1 | socket_status(1B)
socket_status, values: (0: off, 1: on) | 21 | 22 | ## Example 23 | 24 | ```json 25 | // 087001 05812C 07C94A00 03743009 068309660000 048007000000 26 | { 27 | "active_power": 7, 28 | "current": 74, 29 | "power_consumption": 26121, 30 | "power_factor": 44, 31 | "socket_status": "on", 32 | "voltage": 235.2 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /WS_Series/WS52x/WS523_AU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS52x/WS523_AU.png -------------------------------------------------------------------------------- /WS_Series/WS52x/WS523_CN_16A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS52x/WS523_CN_16A.png -------------------------------------------------------------------------------- /WS_Series/WS52x/WS523_EU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS52x/WS523_EU.png -------------------------------------------------------------------------------- /WS_Series/WS52x/WS523_UK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS52x/WS523_UK.png -------------------------------------------------------------------------------- /WS_Series/WS52x/WS523_US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS52x/WS523_US.png -------------------------------------------------------------------------------- /WS_Series/WS52x/WS525_CN_10A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS52x/WS525_CN_10A.png -------------------------------------------------------------------------------- /WS_Series/WS558/README.md: -------------------------------------------------------------------------------- 1 | # Smart Light Controller - Milesight IoT 2 | 3 | The payload decoder function is applicable to WS558. 4 | 5 | For more detailed information, please visit [Milesight Official Website](https://www.milesight.com/iot/product/lorawan-sensor/ws558). 6 | 7 | | WS558 | WS558-LN | 8 | | :-----------------: | :---------------------: | 9 | | ![WS558](WS558.png) | ![WS558LN](WS558LN.png) | 10 | 11 | ## Payload Definition 12 | 13 | | CHANNEL | ID | TYPE | LENGTH | DESCRIPTION | 14 | | :---------------: | :--: | :--: | :----: | ------------------------------------------------------ | 15 | | Voltage | 0x03 | 0x74 | 2 | voltage(2B)
voltage, read: uint16/10 | 16 | | Active power | 0x04 | 0x80 | 4 | power(4B)
power, read: uint32, unit: W | 17 | | Active factor | 0x05 | 0x81 | 1 | factor(1B)
factor, read: uint8, unit: % | 18 | | Power Consumption | 0x06 | 0x83 | 4 | power_sum(4B)
power_sum, read: uint32, unit: W\*h | 19 | | Current | 0x07 | 0xC9 | 2 | current(2B)
current, read: uint16, unit: mA | 20 | | Switch | 0x08 | 0x31 | 2 | | 21 | 22 | ### Switch Value Definition 23 | 24 | ``` 25 | binary: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 26 | switch: 8 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1 27 | --------------- --------------- 28 | bitmask: change state 29 | ``` 30 | 31 | ## Example 32 | 33 | ```json 34 | // 08310001 058164 07C90200 0374B208 068301000000 048001000000 35 | { 36 | "voltage": 222.6, 37 | "active_power": 1, 38 | "power_factor": 100, 39 | "total_current": 2, 40 | "power_consumption": 1, 41 | "switch_1": "on", 42 | "switch_2": "off", 43 | "switch_3": "off", 44 | "switch_4": "off", 45 | "switch_5": "off", 46 | "switch_6": "off", 47 | "switch_7": "off", 48 | "switch_8": "off" 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /WS_Series/WS558/WS558.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS558/WS558.png -------------------------------------------------------------------------------- /WS_Series/WS558/WS558LN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WS_Series/WS558/WS558LN.png -------------------------------------------------------------------------------- /WTS_series/WTS305&WTS506_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product WTS305 / WTS506 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | 27 | for (var i = 0; i < bytes.length; ) { 28 | var channel_id = bytes[i++]; 29 | var channel_type = bytes[i++]; 30 | // BATTERY 31 | if (channel_id === 0x01 && channel_type === 0x75) { 32 | decoded.battery = bytes[i]; 33 | i += 1; 34 | } 35 | // TEMPERATURE 36 | else if (channel_id === 0x03 && channel_type === 0x67) { 37 | // ℃ 38 | decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10; 39 | i += 2; 40 | 41 | // ℉ 42 | // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32; 43 | // i +=2; 44 | } 45 | // HUMIDITY 46 | else if (channel_id === 0x04 && channel_type === 0x68) { 47 | decoded.humidity = bytes[i] / 2; 48 | i += 1; 49 | } 50 | // Wind Direction, unit degree 51 | else if (channel_id === 0x05 && channel_type === 0x84) { 52 | decoded.wind_direction = readInt16LE(bytes.slice(i, i + 2)) / 10; 53 | i += 2; 54 | } 55 | // Barometric Pressure, unit hPa 56 | else if (channel_id === 0x06 && channel_type === 0x73) { 57 | decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10; 58 | i += 2; 59 | } 60 | // Wind Speed, unit m/s 61 | else if (channel_id === 0x07 && channel_type === 0x92) { 62 | decoded.wind_speed = readUInt16LE(bytes.slice(i, i + 2)) / 10; 63 | i += 2; 64 | } 65 | // rainfall_total, unit mm, Frame counter to define whether device enters the new rainfall accumulation phase, it will plus 1 every upload, range: 0~255 66 | else if (channel_id === 0x08 && channel_type === 0x77) { 67 | decoded.rainfall_total = readUInt16LE(bytes.slice(i, i + 2)) / 100; 68 | decoded.rainfall_counter = bytes[i + 2]; 69 | i += 3; 70 | } else { 71 | break; 72 | } 73 | } 74 | 75 | return decoded; 76 | } 77 | 78 | /* ****************************************** 79 | * bytes to number 80 | ********************************************/ 81 | function readUInt16LE(bytes) { 82 | var value = (bytes[1] << 8) + bytes[0]; 83 | return value & 0xffff; 84 | } 85 | 86 | function readInt16LE(bytes) { 87 | var ref = readUInt16LE(bytes); 88 | return ref > 0x7fff ? ref - 0x10000 : ref; 89 | } 90 | -------------------------------------------------------------------------------- /WTS_series/WTS305.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WTS_series/WTS305.png -------------------------------------------------------------------------------- /WTS_series/WTS505.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WTS_series/WTS505.png -------------------------------------------------------------------------------- /WTS_series/WTS506.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WTS_series/WTS506.png -------------------------------------------------------------------------------- /WT_Series/WT101/WT101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WT_Series/WT101/WT101.png -------------------------------------------------------------------------------- /WT_Series/WT201/WT201.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WT_Series/WT201/WT201.png -------------------------------------------------------------------------------- /WT_Series/WT201_v2/WT201_v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WT_Series/WT201_v2/WT201_v2.png -------------------------------------------------------------------------------- /WT_Series/WT30x/README.md: -------------------------------------------------------------------------------- 1 | # Smart Fan Coil Thermostat - Milesight IoT 2 | 3 | The payload decoder function is applicable to WT30x. 4 | 5 | For more detailed information, please visit [Milesight official website](https://www.milesight-iot.com). 6 | 7 | ![WT30x](WT30x.png) 8 | -------------------------------------------------------------------------------- /WT_Series/WT30x/WT30x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Milesight-IoT/SensorDecoders/cb54e4e64e7c279c85fa1a826eb8548c89071152/WT_Series/WT30x/WT30x.png -------------------------------------------------------------------------------- /WT_Series/WT30x/WT30x_Decoder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Payload Decoder 3 | * 4 | * Copyright 2024 Milesight IoT 5 | * 6 | * @product WT30x 7 | */ 8 | // Chirpstack v4 9 | function decodeUplink(input) { 10 | var decoded = milesightDeviceDecode(input.bytes); 11 | return { data: decoded }; 12 | } 13 | 14 | // Chirpstack v3 15 | function Decode(fPort, bytes) { 16 | return milesightDeviceDecode(bytes); 17 | } 18 | 19 | // The Things Network 20 | function Decoder(bytes, port) { 21 | return milesightDeviceDecode(bytes); 22 | } 23 | 24 | function milesightDeviceDecode(bytes) { 25 | var decoded = {}; 26 | var i = 0; 27 | var head = bytes[i]; 28 | var command = ["", "control", "request"][bytes[i + 1]]; 29 | var data_length = readInt16BE(bytes.slice(i + 2, i + 4)); 30 | var type = ["thermostat_status", "btn_lock_enabled", "mode", "fan_speed", "temperature", "temperature_target", "card", "control_mode", "server_temperature", "all"][bytes[i + 4]]; 31 | var raw = bytes.slice(i + 5, i + 5 + data_length); 32 | var crc = bytes[i + 5 + data_length]; 33 | 34 | var data_id = bytes[i + 4]; 35 | switch (data_id) { 36 | case 0x01: 37 | decoded.thermostat_status = bytes[i + 5] === 1 ? "on" : "off"; 38 | break; 39 | case 0x02: 40 | decoded.btn_lock_enabled = bytes[i + 5] === 1 ? "enable" : "disable"; 41 | break; 42 | case 0x03: 43 | decoded.mode = ["cool", "heat", "fan"][bytes[i + 5]]; 44 | break; 45 | case 0x04: 46 | decoded.fan_speed = ["auto", "high", "medium", "low"][bytes[i + 5]]; 47 | break; 48 | case 0x05: 49 | decoded.temperature = bytes[i + 5] / 2; 50 | break; 51 | case 0x06: 52 | decoded.temperature_target = bytes[i + 5] / 2; 53 | break; 54 | case 0x07: 55 | decoded.card = bytes[i + 5] === 1 ? "insert" : "remove"; 56 | break; 57 | case 0x08: 58 | decoded.control_mode = ["auto", "manual"][bytes[i + 5]]; 59 | break; 60 | case 0x09: 61 | decoded.server_temperature = bytes[i + 5] / 2; 62 | break; 63 | case 0x0f: 64 | decoded.thermostat_status = bytes[i + 5] === 1 ? "on" : "off"; 65 | decoded.btn_lock_enabled = bytes[i + 6] === 1 ? "enable" : "disable"; 66 | decoded.mode = ["cool", "heat", "fan"][bytes[i + 7]]; 67 | decoded.fan_speed = ["auto", "high", "medium", "low"][bytes[i + 8]]; 68 | decoded.temperature = bytes[i + 9] / 2; 69 | decoded.temperature_target = bytes[i + 10] / 2; 70 | decoded.card = bytes[i + 11] === 1 ? "insert" : "remove"; 71 | decoded.control_mode = ["auto", "manual"][bytes[i + 12]]; 72 | decoded.server_temperature = bytes[i + 13] / 2; 73 | break; 74 | } 75 | 76 | return decoded; 77 | } 78 | 79 | function readUInt16BE(bytes) { 80 | var value = (bytes[0] << 8) + bytes[1]; 81 | return value & 0xffff; 82 | } 83 | 84 | function readInt16BE(bytes) { 85 | var ref = readUInt16BE(bytes); 86 | return ref > 0x7fff ? ref - 0x10000 : ref; 87 | } 88 | -------------------------------------------------------------------------------- /Z_AWS_IoT_Core/Lambda-Node18x.js: -------------------------------------------------------------------------------- 1 | import { IoTDataPlaneClient, PublishCommand } from "@aws-sdk/client-iot-data-plane"; // ES Modules import 2 | console.log('Loading function'); 3 | 4 | export const handler = async (event, context, callback) => { 5 | var data = Buffer.from(event.PayloadData, 'base64'); 6 | var chars = [...data]; 7 | 8 | var params = Decoder(chars, event.WirelessMetadata.LoRaWAN.FPort); 9 | const client = new IoTDataPlaneClient('xxxxxxxxxxxxxxx.iot.us-east-1.amazonaws.com'); 10 | 11 | const message = { 12 | topic: event.WirelessMetadata.LoRaWAN.DevEui.concat("/project/sensor/decoded"), 13 | payload: JSON.stringify(params), 14 | qos: 0 15 | }; 16 | 17 | const command = new PublishCommand(message); 18 | const response = await client.send(command); 19 | 20 | 21 | callback(null, { 22 | statusCode: 200, 23 | body: JSON.stringify(params) 24 | }); 25 | }; 26 | 27 | // paste your TTN Decoder here 28 | -------------------------------------------------------------------------------- /Z_AWS_IoT_Core/Lambda.js: -------------------------------------------------------------------------------- 1 | var AWS = require('aws-sdk'); 2 | console.log('Loading function'); 3 | 4 | exports.handler = (event, context, callback) => { 5 | var data = Buffer.from(event.PayloadData, 'base64'); 6 | var chars = [...data]; 7 | 8 | var params = Decoder(chars, event.WirelessMetadata.LoRaWAN.FPort); 9 | var iotdata = new AWS.IotData({ endpoint: 'xxxxxxxxxxxxx-ats.iot.us-east-1.amazonaws.com' }); 10 | 11 | var response = { 12 | topic: event.WirelessMetadata.LoRaWAN.DevEui.concat("/project/sensor/decoded"), 13 | payload: JSON.stringify(params), 14 | qos: 0 15 | }; 16 | 17 | iotdata.publish(response, function(err, data) { 18 | if (err) { 19 | console.log("ERROR => " + JSON.stringify(err)); 20 | } 21 | else { 22 | console.log("publish data: ", response); 23 | } 24 | }); 25 | 26 | callback(null, { 27 | statusCode: 200, 28 | body: JSON.stringify(params) 29 | }); 30 | }; 31 | 32 | // PASTE DECODER HERE 33 | -------------------------------------------------------------------------------- /Z_AWS_IoT_Core/README.md: -------------------------------------------------------------------------------- 1 | # Connecting Milesight IoT End devices to AWS IoT Core for LoRaWAN - Milesight IoT 2 | 3 | The header code is applicable to all Milesight IoT end-devices listed in this repository. 4 | 5 | For more detailed guide, please visit [milesight official knowledge base](https://support.milesight-iot.com/hc/en-us/articles/900007629603). 6 | 7 | 8 | ## How to Use the Header Code 9 | - Go to the AWS Lambda console. 10 | - Click on **Functions** in the navigation pane. 11 | - Click on **Create function**. 12 | - Select **Author from scratch**. Under Basic information, enter the function name “am100decoder” for instance and choose **Node.js 12.x**. from the drop-down under **Runtime**. 13 | - Click on **Create function**. 14 | - Click the function you created, Under **Code** tab, paste the Header Code, and under 15 | ``` 16 | // PASTE DECODER HERE 17 | ``` 18 | - Get the decoder for TTN from the model folder in this repository and paste it underneath. 19 | --------------------------------------------------------------------------------