Skip to content

Commit b9d9e74

Browse files
authored
Merge pull request thingsboard#1439 from stitenko/04.2024/Milesight-VS-121
Added VS121 to the Device Library
2 parents 0a4dd93 + 93251dc commit b9d9e74

File tree

19 files changed

+1615
-0
lines changed

19 files changed

+1615
-0
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
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+1];
7+
8+
i += 2;
9+
10+
// PROTOCOL VERSION
11+
if (channel_id == -1 && channel_type == 1) {
12+
decoded.protocol_version = input[i];
13+
i += 1;
14+
}
15+
// SERIAL NUMBER
16+
else if (channel_id == -1 && channel_type == 8) {
17+
var temp = [];
18+
var last_index_sn = i + 6;
19+
for (var idxsn = i; idxsn < last_index_sn; idxsn++) {
20+
temp.push(bytesToHex([input[idxsn] & 0xff]));
21+
}
22+
decoded.serialNumber = temp.join("");
23+
i += 6;
24+
}
25+
// HARDWARE VERSION
26+
else if (channel_id == -1 && channel_type == 9) {
27+
var temphv = [];
28+
var last_index_hv = i + 2;
29+
for (var idxhv = i; idxhv < last_index_hv; idxhv++) {
30+
temphv.push((input[idxhv] & 0xff).toString());
31+
}
32+
decoded.hardwareVersion = temphv.join(".");
33+
i += 2;
34+
}
35+
// FIRMWARE VERSION
36+
else if (channel_id == -1 && channel_type == 31) {
37+
var tempfv = [];
38+
var last_index_fv = i + 4;
39+
for (var idxfv = i; idxfv < last_index_fv; idxfv++) {
40+
tempfv.push((input[idxfv] & 0xff).toString());
41+
}
42+
decoded.firmwareVersion = tempfv.join(".");
43+
i += 4;
44+
}
45+
// PEOPLE COUNTER
46+
else if (channel_id == 4 && channel_type == -55) {
47+
decoded.peopleCountAll = input[i];
48+
decoded.regionCount = input[i + 1];
49+
var region = parseBytesToInt(input, i + 2, 2, false);
50+
for (var idxpc = 0; idxpc < decoded.regionCount; idxpc++) {
51+
var tmp = "region" + (idxpc + 1);
52+
decoded[tmp] = (region >> idxpc) & 1;
53+
}
54+
i += 4;
55+
}
56+
// PEOPLE IN/OUT
57+
else if (channel_id == 5 && channel_type == -52) {
58+
decoded.peopleIn = parseBytesToInt(input, i, 2, false);
59+
decoded.peopleOut = parseBytesToInt(input, i + 2, 2, false);
60+
i += 4;
61+
}
62+
// PEOPLE MAX
63+
else if (channel_id == 6 && channel_type == -51) {
64+
decoded.peopleCountMax = input[i];
65+
i += 1;
66+
}
67+
// REGION COUNTER
68+
else if (channel_id == 7 && channel_type == -43) {
69+
decoded.region1Count = input[i];
70+
decoded.region2Count = input[i + 1];
71+
decoded.region3Count = input[i + 2];
72+
decoded.region4Count = input[i + 3];
73+
decoded.region5Count = input[i + 4];
74+
decoded.region6Count = input[i + 5];
75+
decoded.region7Count = input[i + 6];
76+
decoded.region8Count = input[i + 7];
77+
i += 8;
78+
}
79+
// REGION COUNTER
80+
else if (channel_id == 8 && channel_type == -43) {
81+
decoded.region9Count = input[i];
82+
decoded.region10Count = input[i + 1];
83+
decoded.region11Count = input[i + 2];
84+
decoded.region12Count = input[i + 3];
85+
decoded.region13Count = input[i + 4];
86+
decoded.region14Count = input[i + 5];
87+
decoded.region15Count = input[i + 6];
88+
decoded.region16Count = input[i + 7];
89+
i += 8;
90+
}
91+
// A FLOW
92+
else if (channel_id == 9 && channel_type == -38) {
93+
decoded.aToA = parseBytesToInt(input, i, 2, false);
94+
decoded.aToB = parseBytesToInt(input, i + 2, 2, false);
95+
decoded.aToC = parseBytesToInt(input, i + 4, 2, false);
96+
decoded.aToD = parseBytesToInt(input, i + 6, 2, false);
97+
i += 8;
98+
}
99+
// B FLOW
100+
else if (channel_id == 10 && channel_type == -38) {
101+
decoded.bToA = parseBytesToInt(input, i, 2, false);
102+
decoded.bToB = parseBytesToInt(input, i + 2, 2, false);
103+
decoded.bToC = parseBytesToInt(input, i + 4, 2, false);
104+
decoded.bToD = parseBytesToInt(input, i + 6, 2, false);
105+
i += 8;
106+
}
107+
// C FLOW
108+
else if (channel_id == 11 && channel_type == -38) {
109+
decoded.cToA = parseBytesToInt(input, i, 2, false);
110+
decoded.cToB = parseBytesToInt(input, i + 2, 2, false);
111+
decoded.cToC = parseBytesToInt(input, i + 4, 2, false);
112+
decoded.cToD = parseBytesToInt(input, i + 6, 2, false);
113+
i += 8;
114+
}
115+
// D FLOW
116+
else if (channel_id == 12 && channel_type == -38) {
117+
decoded.dToA = parseBytesToInt(input, i, 2, false);
118+
decoded.dToB = parseBytesToInt(input, i + 2, 2, false);
119+
decoded.dToC = parseBytesToInt(input, i + 4, 2, false);
120+
decoded.dToD = parseBytesToInt(input, i + 6, 2, false);
121+
i += 8;
122+
}
123+
// TOTAL IN/OUT
124+
else if (channel_id == 13 && channel_type == -52) {
125+
decoded.peopleTotalIn = parseBytesToInt(input, i, 2, false);
126+
decoded.peopleTotalOut = parseBytesToInt(input, i + 2, 2, false);
127+
i += 4;
128+
}
129+
// DWELL TIME
130+
else if (channel_id == 14 && channel_type == -28) {
131+
var region1 = input[i];
132+
decoded.region = region1;
133+
decoded.dwellTimeAvg = parseBytesToInt(input, i + 1, 2, false);
134+
decoded.dwellTimeMax = parseBytesToInt(input, i + 3, 2, false);
135+
i += 5;
136+
}
137+
// TIMESTAMP
138+
else if (channel_id == 15 && channel_type == -123) {
139+
decoded.timestamp = parseBytesToInt(input, i, 4, false);
140+
i += 4;
141+
} else {
142+
break;
143+
}
144+
}
145+
146+
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 clicking the device and navigate to the "**Attributes**" or "**Latest telemetry**" tab.
6+
7+
{% assign checkTelemetryOnDevice = '
8+
===
9+
image: /images/devices-library/ready-to-go-devices/vs121-device/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 [dashboard](/docs/pe/user-guide/dashboards){: target="_blank"}.
18+
Download a simple dashboard for this device. It is configured to display a data from "Count people all", "Max count people", "Signal strength", "Region count" and "Occupancy" timeseries keys of 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/vs-121-sensor-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/vs-121-sensor-dashboard.json" %}
23+
24+
Example of the dashboard with data:
25+
26+
{% assign dashboard = '
27+
===
28+
image: /images/devices-library/ready-to-go-devices/vs121-device/vs121-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: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
### Device configuration
2+
3+
To connect and send data we should configure the device and network server.
4+
Firstly, 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+
7+
- **Device EUI** - device identifier
8+
- **Application EUI** - Application identifier
9+
- **Application Key** - Application key to identify device. We recommend to use a generated key, not from the example!
10+
11+
Depending on the network server, you may also need to provide join type (OTAA), LoRaWAN version.
12+
13+
VS121 sensor provides user-friendly web GUI for configuration and users can access it via Wi-Fi connection. Default SSID device: Workplace Sensor.
14+
15+
Follow the steps below:
16+
1. Power on the device over Type-C Power Port;
17+
2. Enable the Wireless Network Connection on your computer and the corresponding access point, then connect computer to this access point;
18+
3. Open the Browser and type 192.168.1.1 to access the web GUI (you must be in the one subnetwork);
19+
4. Users need to set the password when using the device for the first time. Additionally three security questions can also be set optionally;
20+
5. After configuration, use username (admin) and custom password to log in to the sensor.
21+
22+
{% assign milesightLogin = '
23+
===
24+
image: /images/devices-library/ready-to-go-devices/vs121-device/milesight-login.png,
25+
title: Use username (admin) and custom password to log in to the sensor web GUI.
26+
'
27+
%}
28+
29+
{% include images-gallery.liquid imageCollection=milesightLogin %}
30+
31+
To obtain the necessary parameters, follow these steps:
32+
- Go to the **IoT** page in the left panel and navigate to the **LoRa** tab;
33+
- Make a note of **Device EUI** and **App EUI**;
34+
- Generate and enter a new password in hexadecimal format in the **Application Key** field and note it;
35+
- Scroll down and click on the **Save** button.
36+
37+
{% assign milesightInterface = '
38+
===
39+
image: /images/devices-library/ready-to-go-devices/vs121-device/milesight-interface-1.png,
40+
title: Go to the **IoT** page in the left panel and navigate to the **LoRa** tab. Make a note of **Device EUI** and **App EUI**. Generate and enter a new password in hexadecimal format in the **Application Key** field and note it;
41+
===
42+
image: /images/devices-library/ready-to-go-devices/vs121-device/milesight-interface-2.png,
43+
title: Scroll down and click on the **Save** button.
44+
'
45+
%}
46+
47+
{% include images-gallery.liquid imageCollection=milesightInterface %}
48+
49+
The parameters above are required for connection.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
{% assign deviceName = page.title | remove: "How to connect " | remove: "to ThingsBoard?" %}
3+
{% assign deviceVendorLink = "https://www.milesight.com/iot/product/lorawan-sensor/vs121" %}
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.com/milesight/iot/document/vs121-user-guide-en.pdf" %}
10+
{% assign prerequisites = '
11+
- <a href="' | append: deviceVendorLink | append: '" target="_blank">' | append: deviceName | append: '</a>
12+
- [VS121 Device user manual](' | append: officialManualLink | append: '){: target="_blank"}
13+
- Computer with Wi-Fi
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+
## Introduction
21+
22+
![{{deviceName}}](/images/devices-library/{{page.deviceImageFileName}}){: style="float: left; max-width: 200px; max-height: 200px; margin: 0px 10px 0px 0px"}
23+
[Milesight VS121]({{deviceVendorLink}}){: target="_blank"}, is an AI workplace sensor designed to monitor occupancy and utilization in modern workspaces, which can reach up to 98% recognition rate based on its AI algorithm.
24+
Milesight VS121 is available in dual versions that transmit data through LoRaWAN® or Ethernet for different applications.Based on standard Lorawan protocol, VS121 can work with the Milesight gateway.
25+
It is equipped with WI-FI for easy configuration without the need for any additional configuration tools. By connecting this device to the ThingsBoard, you can get improved visualization and data management capabilities.
26+
27+
<br>
28+
{% assign feature = "Platform Integrations" %}{% include templates/pe-feature-banner.md %}
29+
30+
## Prerequisites
31+
32+
To continue with this guide we will need the following:
33+
{{ prerequisites }}
34+
- [ThingsBoard account]({{ thingsboardHost }}){: target="_blank"}
35+
36+
## Device connection
37+
38+
According to the [official user manual]({{officialManualLink}}){: target="_blank"} and this guide, you can connect the device to the network and get access to the Web UI via wireless connection.
39+
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.
40+
41+
{% if page.hasIntegrationDeviceConfiguration | downcase == "true"%}
42+
43+
{% assign articleFilename = page.name | replace: ".md", "" %}
44+
{% assign guideFilePath = "/docs/devices-library/blocks/ready-to-go-devices/" | append: articleFilename | append: "-configuration-block.md" %}
45+
46+
{% include {{ guideFilePath }} %}
47+
48+
{% endif %}
49+
50+
To configure the device we also need to add it to a network server, so select the network server your gateway is connected to:
51+
52+
{% assign targetIntegrationTypes = '
53+
ChirpStack,
54+
TheThingsStack,
55+
TheThingsIndustries,
56+
Loriot
57+
'%}
58+
59+
{% include /docs/devices-library/blocks/basic/thingsboard-add-lorawan-device-through-integration-block.liquid target-integration-types=targetIntegrationTypes %}
60+
61+
{% include /docs/devices-library/blocks/ready-to-go-devices/vs-121-check-data-block.md %}
62+
63+
## Conclusion
64+
65+
{% include /docs/devices-library/blocks/basic/conclusion-block.md %}

0 commit comments

Comments
 (0)