├── .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 | |  |  |
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 | |  |  |
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 | 
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 | 
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 | 
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 | |  |  |
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 | 
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 | 
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 | 
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 | |  |  |
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | |  |  |
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 | 
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 | |  |  |
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 | 
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 | 
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 | |  |  |
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 | |  |  |
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | |  |
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 | |  |
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 | |  |
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 | |  |
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 | |  |  |  |  |  |  |
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 | |  |  |
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 | 
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 |
--------------------------------------------------------------------------------