Skip to content

Commit 4dcf64e

Browse files
authored
Merge pull request thingsboard#1442 from stitenko/04.2024/AM308-868M-device
Added AM308 to the Device Library
2 parents b9d9e74 + 92d5710 commit 4dcf64e

File tree

16 files changed

+2993
-3
lines changed

16 files changed

+2993
-3
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
var historyData = {};
2+
var decoded = {};
3+
decoded.hexString = bytesToHex(input);
4+
for (var i = 0; i < input.length; ) {
5+
var channel_id = input[i++];
6+
var channel_type = input[i++];
7+
// BATTERY
8+
if (channel_id === 0x01 && channel_type === 0x75) {
9+
decoded.battery = input[i];
10+
i += 1;
11+
}
12+
// TEMPERATURE
13+
if (channel_id === 0x03 && channel_type === 0x67) {
14+
// ℃
15+
decoded.temperature = parseBytesToInt(input, i, 2, false) / 10;
16+
i += 2;
17+
// ℉
18+
// decoded.temperature = parseBytesToInt(input, i, 2, false) / 10 * 1.8 + 32;
19+
// i +=2;
20+
}
21+
// HUMIDITY
22+
if (channel_id === 0x04 && channel_type === 0x68) {
23+
decoded.humidity = input[i] / 2;
24+
i += 1;
25+
}
26+
// PIR
27+
if (channel_id === 0x05 && channel_type === 0x00) {
28+
decoded.pir = input[i] === 1 ? "trigger" : "idle";
29+
i += 1;
30+
}
31+
// LIGHT
32+
if (channel_id == 0x06 && channel_type == -53) {
33+
decoded.light_level = input[i];
34+
i += 1;
35+
}
36+
// CO2
37+
if (channel_id === 0x07 && channel_type === 0x7d) {
38+
decoded.co2 = parseBytesToInt(input, i, 2, false);
39+
i += 2;
40+
}
41+
// TVOC
42+
if (channel_id === 0x08 && channel_type === 0x7d) {
43+
decoded.tvoc = parseBytesToInt(input, i, 2, false);
44+
i += 2;
45+
}
46+
// PRESSURE
47+
if (channel_id === 0x09 && channel_type === 0x73) {
48+
decoded.pressure = parseBytesToInt(input, i, 2, false) / 10;
49+
i += 2;
50+
}
51+
// HCHO
52+
if (channel_id === 0x0a && channel_type === 0x7d) {
53+
decoded.hcho = parseBytesToInt(input, i, 2, false) / 100;
54+
i += 2;
55+
}
56+
// PM2.5
57+
if (channel_id === 0x0b && channel_type === 0x7d) {
58+
decoded.pm2_5 = parseBytesToInt(input, i, 2, false);
59+
i += 2;
60+
}
61+
// PM10
62+
if (channel_id === 0x0c && channel_type === 0x7d) {
63+
decoded.pm10 = parseBytesToInt(input, i, 2, false);
64+
i += 2;
65+
}
66+
// O3
67+
if (channel_id === 0x0d && channel_type === 0x7d) {
68+
decoded.o3 = parseBytesToInt(input, i, 2, false) / 100;
69+
i += 2;
70+
}
71+
// BEEP
72+
if (channel_id === 0x0e && channel_type === 0x01) {
73+
decoded.beep = input[i] === 1 ? "yes" : "no";
74+
i += 1;
75+
76+
}
77+
// HISTORY DATA (AM307)
78+
if (channel_id === 32 && channel_type === 206) {
79+
historyData = {};
80+
historyData.timestamp = parseBytesToInt(input, i, 4, false);
81+
historyData.temperature = parseBytesToInt(input, i + 4, 2, false) / 10;
82+
historyData.humidity = parseBytesToInt(input, i + 6, 2, false) / 2;
83+
historyData.pir = input[i + 8] === 1 ? "trigger" : "idle";
84+
historyData.light_level = input[i + 9] === 1;
85+
historyData.co2 = parseBytesToInt(input, i + 10, 2, false);
86+
historyData.tvoc = parseBytesToInt(input, i + 12, 2, false);
87+
historyData.pressure = parseBytesToInt(input, i + 14, 2, false) / 10;
88+
i += 16;
89+
if (decoded.history == null) {
90+
decoded.history = [];
91+
}
92+
decoded.history.push(historyData);
93+
}
94+
// HISTORY DATA (AM308)
95+
if (channel_id === 32 && channel_type === 206) {
96+
historyData = {};
97+
historyData.timestamp = parseBytesToInt(input, i, 4, false);
98+
historyData.temperature = parseBytesToInt(input, i + 4, 2, false) / 10;
99+
historyData.humidity = parseBytesToInt(input, i + 6, 2, false) / 2;
100+
historyData.pir = input[i + 8] === 1 ? "trigger" : "idle";
101+
historyData.light_level = input[i + 9] === 1;
102+
historyData.co2 = parseBytesToInt(input, i + 10, 2, false);
103+
historyData.tvoc = parseBytesToInt(input, i + 12, 2, false);
104+
historyData.pressure = parseBytesToInt(input, i + 14, 2, false) / 10;
105+
historyData.pm2_5 = parseBytesToInt(input, i + 16, 2, false);
106+
historyData.pm10 = parseBytesToInt(input, i + 18, 2, false);
107+
i += 20;
108+
if (decoded.history == null) {
109+
decoded.history = [];
110+
}
111+
decoded.history.push(historyData);
112+
}
113+
// HISTORY DATA (AM319 CH2O)
114+
if (channel_id === 32 && channel_type === 206) {
115+
historyData = {};
116+
historyData.timestamp = parseBytesToInt(input, i, 4, false);
117+
historyData.temperature = parseBytesToInt(input, i + 4, 2, false) / 10;
118+
historyData.humidity = parseBytesToInt(input, i + 6, 2, false) / 2;
119+
historyData.pir = input[i + 8] === 1 ? "trigger" : "idle";
120+
historyData.light_level = input[i + 9] === 1;
121+
historyData.co2 = parseBytesToInt(input, i + 10, 2, false);
122+
historyData.tvoc = parseBytesToInt(input, i + 12, 2, false);
123+
historyData.pressure = parseBytesToInt(input, i + 14, 2, false) / 10;
124+
historyData.pm2_5 = parseBytesToInt(input, i + 16, 2, false);
125+
historyData.pm10 = parseBytesToInt(input, i + 18, 2, false);
126+
historyData.hcho = parseBytesToInt(input, i + 20, 2, false) / 100;
127+
i += 22;
128+
if (decoded.history == null) {
129+
decoded.history = [];
130+
}
131+
decoded.history.push(historyData);
132+
}
133+
// HISTORY historyData (AM319 O3)
134+
if (channel_id === 0x20 && channel_type === 0xce) {
135+
historyData = {};
136+
historyData.timestamp = parseBytesToInt(input, i, 4, false);
137+
historyData.temperature = parseBytesToInt(input, i + 4, 2, false) / 10;
138+
historyData.humidity = parseBytesToInt(input, i + 6, 2, false) / 2;
139+
historyData.pir = input[i + 8] === 1 ? "trigger" : "idle";
140+
historyData.light_level = input[i + 9] === 1;
141+
historyData.co2 = parseBytesToInt(input, i + 10, 2, false);
142+
historyData.tvoc = parseBytesToInt(input, i + 12, 2, false);
143+
historyData.pressure = parseBytesToInt(input, i + 14, 2, false) / 10;
144+
historyData.pm2_5 = parseBytesToInt(input, i + 16, 2, false);
145+
historyData.pm10 = parseBytesToInt(input, i + 18, 2, false);
146+
historyData.o3 = parseBytesToInt(input, i + 20, 2, false) / 100;
147+
i += 22;
148+
if (decoded.history == null) {
149+
decoded.history = [];
150+
}
151+
decoded.history.push(historyData);
152+
}
153+
}
154+
155+
output.telemetry = decoded;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
### Check data on ThingsBoard
2+
3+
So, the device was added and if it sends any data - it should appear in **Devices**.
4+
To check it you may open **Devices** page in **Entities** section.
5+
The device should be in devices list. You can check the data by click on it and open tab **Attributes** or **Latest telemetry**.
6+
7+
{% assign checkTelemetryOnDevice = '
8+
===
9+
image: /images/devices-library/ready-to-go-devices/am308/check-telemetry-on-device.png,
10+
title: Open "Devices" page in "Entities" section. The device should be in devices list. You can check the data by clicking the device and navigate to the "Attributes" or "Latest telemetry" tab.
11+
'
12+
%}
13+
14+
{% include images-gallery.liquid imageCollection=checkTelemetryOnDevice %}
15+
16+
<br>
17+
In order to get more user-friendly view - you can use [dashboards](/docs/pe/user-guide/dashboards){: target="_blank"}.
18+
You can download a simple dashboard for this device, it is configured to display a data from "pir", "light level", "beep", "battery level", "Temperature", "Humidity", "CO2", "Pressure", "TVOC", "PM2.5", "PM10" and "Signal strength" telemetry keys for device with name "eui-24e124538b223213".
19+
20+
{% include /docs/devices-library/blocks/basic/thingsboard-upload-example-dashboard.md exampleDashboardPath="/docs/devices-library/resources/dashboards/ready-to-go-devices/am308-device-dashboard.json" %}
21+
22+
{% include /docs/devices-library/blocks/basic/thingsboard-chenge-entity-alias-block.md exampleDashboardPath="/docs/devices-library/resources/dashboards/ready-to-go-devices/am308-device-dashboard.json" %}
23+
24+
Example of the dashboard with data:
25+
26+
{% assign dashboard = '
27+
===
28+
image: /images/devices-library/ready-to-go-devices/am308/am308-example-of-the-dashboard-pe.png,
29+
title: Example of the dashboard with data.
30+
'
31+
%}
32+
33+
{% include images-gallery.liquid imageCollection=dashboard %}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
### Device configuration
2+
3+
To connect and send data we should configure the device and network server.
4+
At first we are going to configure the device, and save required information for network server configuration.
5+
To add a device to network server and get information from it, we will need the following device parameters:
6+
- **Device EUI** - device identifier
7+
- **Application EUI** - Application identifier
8+
- **Application Key** - Application key to identify device. We recommend to use a generated key, not from the example!
9+
10+
The parameters above are required for connection.
11+
12+
Depending on the network server, you may also need to provide join type (OTAA), LoRaWAN version.
13+
14+
To configure device via NFC, you will need to hold your smartphone like on the picture below:
15+
16+
![NFC zone](/images/devices-library/ready-to-go-devices/am308/am308-connect.png)
17+
<br>
18+
19+
To read and write configuration on the device you may follow next steps on your smartphone:
20+
{% assign readWriteConfiguration = '
21+
===
22+
image: /images/devices-library/ready-to-go-devices/ws202-pir-and-light-sensor/toolbox-application.png,
23+
title: Open **ToolBox** application.
24+
===
25+
image: /images/devices-library/ready-to-go-devices/ws202-pir-and-light-sensor/toolbox-read-success.png,
26+
title: Click on **NFC Read** button and hold your smartphone near the device.
27+
===
28+
image: /images/devices-library/ready-to-go-devices/ws202-pir-and-light-sensor/toolbox-configuration.png,
29+
title: Go to tab **Setting**, set and save required fields and any other configuration that you need.
30+
===
31+
image: /images/devices-library/ready-to-go-devices/ws202-pir-and-light-sensor/toolbox-write-success.png,
32+
title: Press **Write** button and hold your smartphone near the device.
33+
'
34+
%}
35+
36+
{% include images-gallery.liquid showListImageTitles="true" imageCollection=readWriteConfiguration %}
37+
38+
The developer also provides the possibility of connecting through a computer if necessary:
39+
40+
![Device connect](/images/devices-library/ready-to-go-devices/am308/am308-connect-to-pc.png)
41+
42+
See the [manual](https://resource.milesight-iot.com/milesight/document/am300-series-user-guide-en.pdf){: target="_blank"} for details.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
2+
{% assign deviceName = page.title | remove: "How to connect " | remove: "to ThingsBoard?" %}
3+
{% assign deviceVendorLink = "https://www.milesight.com/iot/product/lorawan-sensor/am319" %}
4+
{% if page.docsPrefix == "pe/" or page.docsPrefix == "paas/" %}
5+
{% assign thingsboardHost = 'https://thingsboard.cloud' %}
6+
{% else %}
7+
{% assign thingsboardHost = 'https://demo.thingsboard.io' %}
8+
{% endif %}
9+
{% assign officialManualLink = "https://resource.milesight-iot.com/milesight/document/am300-series-user-guide-en.pdf" %}
10+
{% assign prerequisites = '
11+
- <a href="' | append: deviceVendorLink | append: '" target="_blank">' | append: deviceName | append: '</a>
12+
- [AM300-series-user-guide](' | append: officialManualLink | append: '){: target="_blank"}
13+
- Smartphone with NFC-enabled and Milesight ToolBox application ([Android](https://play.google.com/store/apps/details?id=com.ursalinknfc){: target="_blank"}/[iOS](https://itunes.apple.com/app/id1518748039){: target="_blank"})
14+
- LoRaWAN® gateway (in our case [UG56 LoRaWAN® Gateway](/docs/pe/devices-library/ug56-lorawan-gateway/){:target="_blank"})
15+
- Configured integration on networks server and ThingsBoard
16+
- [Network Server account](#device-connection)
17+
'
18+
%}
19+
20+
![{{deviceName}}](/images/devices-library/{{page.deviceImageFileName}}){: style="float: left; max-width: 200px; max-height: 200px; margin: 0px 10px 0px 0px"}
21+
[AM300 series]({{deviceVendorLink}}){: target="_blank"} is a compact indoor ambiance monitoring sensor for measurement of temperature, humidity, light, CO2 concentration, barometric pressure, PM2.5, PM10 and motion.
22+
The data will be shown on the E-ink screen in real-time, which helps to measure the indoor environment and comfort.
23+
AM300 series is widely used for offices, stores, classrooms, hospitals, etc. Sensor data is transmitted using LoRaWAN ® technology.
24+
Using Milesight LoRaWAN® gateway and ThingsBoard, users can manage all sensor data remotely and visually.
25+
26+
<br><br><br>
27+
Features of the AM300 series device:
28+
- Integrated with multiple sensors like humidity, temperature, CO2, level light, barometric pressure, PM2.5, PM10, etc. Multiple display modes and clear emoticons to easily understand the comfort levels via screen;
29+
- Support batteries or DC power supply;
30+
- Equipped with traffic light indicator and buzzer to indicate device status and threshold alarms;
31+
- Able to store locally more than 18, 000 records of 512 KB in total;
32+
- Compliant with standard LoRaWAN® gateways and network servers.
33+
34+
{% assign feature = "Platform Integrations" %}{% include templates/pe-feature-banner.md %}
35+
36+
## Prerequisites
37+
38+
To continue with this guide we will need the following:
39+
{{ prerequisites }}
40+
- [ThingsBoard account]({{ thingsboardHost }}){: target="_blank"}
41+
42+
## Device connection
43+
44+
According to the [official user manual]({{officialManualLink}}){: target="_blank"}, we need a smartphone with NFC enabled and the ToolBox application to connect the sensor.
45+
Since this device can only be operated using a LoRaWAN® gateway, we must first connect it to a network server that has an integration configured with ThingsBoard.
46+
Afterward, it can be provisioned to ThingsBoard.
47+
48+
{% if page.hasIntegrationDeviceConfiguration | downcase == "true"%}
49+
50+
{% assign articleFilename = page.name | replace: ".md", "" %}
51+
{% assign guideFilePath = "/docs/devices-library/blocks/ready-to-go-devices/" | append: articleFilename | append: "-configuration-block.md" %}
52+
53+
{% include {{ guideFilePath }} %}
54+
55+
{% endif %}
56+
57+
To configure the device we also need to add it to a network server, so select the network server your gateway is connected to:
58+
59+
{% assign targetIntegrationTypes = '
60+
ChirpStack,
61+
TheThingsStack,
62+
TheThingsIndustries,
63+
Loriot
64+
'%}
65+
66+
{% include /docs/devices-library/blocks/basic/thingsboard-add-lorawan-device-through-integration-block.liquid target-integration-types=targetIntegrationTypes %}
67+
68+
{% include /docs/devices-library/blocks/ready-to-go-devices/am308-sensor-check-data-block.md %}
69+
70+
## Conclusion
71+
72+
{% include /docs/devices-library/blocks/basic/conclusion-block.md %}

docs/devices-library/am308-sensor.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
layout: devices-library-article
3+
title: How to connect AM308 Lorawan 9-IN-1 lAQ Sensor
4+
category: Other devices
5+
connectivity: LoRaWAN®
6+
vendor: Milesight
7+
hasIntegrationDeviceConfiguration: true
8+
deviceImageFileName: am308.jpg
9+
docsPrefix: pe/
10+
---
11+
12+
* TOC
13+
{:toc}
14+
15+
{% include /docs/devices-library/guides/am308-sensor.md %}

0 commit comments

Comments
 (0)