@lifefinder/vsm-mqtt-client-open-source 0.0.57 → 0.0.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/integrations/chirpstack3.js +22 -1
- package/integrations/chirpstack4.js +33 -2
- package/merge-and-publish.sh +35 -18
- package/package.json +2 -2
- package/vsm-mqtt-client.js +4 -3
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
const mqtt = require('mqtt')
|
|
2
2
|
const { isDate } = require('util/types');
|
|
3
3
|
|
|
4
|
+
const extractLoraInfo = (obj) => {
|
|
5
|
+
const info = {};
|
|
6
|
+
if (obj.rxInfo && obj.rxInfo.length > 0) {
|
|
7
|
+
const best = obj.rxInfo.reduce((a, b) => ((b.rssi || -999) > (a.rssi || -999) ? b : a), obj.rxInfo[0]);
|
|
8
|
+
if (typeof best.rssi === 'number') info.rssi = best.rssi;
|
|
9
|
+
if (typeof best.loRaSNR === 'number') info.snr = best.loRaSNR;
|
|
10
|
+
info.gatewayCount = obj.rxInfo.length;
|
|
11
|
+
}
|
|
12
|
+
if (obj.txInfo) {
|
|
13
|
+
if (obj.txInfo.frequency) info.frequency = obj.txInfo.frequency;
|
|
14
|
+
if (Number.isInteger(obj.txInfo.dr)) info.dataRate = obj.txInfo.dr;
|
|
15
|
+
if (obj.txInfo.loRaModulationInfo) {
|
|
16
|
+
const mi = obj.txInfo.loRaModulationInfo;
|
|
17
|
+
if (mi.spreadingFactor) info.spreadingFactor = mi.spreadingFactor;
|
|
18
|
+
if (mi.bandwidth) info.bandwidth = mi.bandwidth;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
info.timestamp = new Date().toISOString();
|
|
22
|
+
return info;
|
|
23
|
+
};
|
|
24
|
+
|
|
4
25
|
const printUsageAndExit = (info) => {
|
|
5
26
|
console.log(info);
|
|
6
27
|
process.exit(1);
|
|
@@ -109,7 +130,7 @@ module.exports.api = {
|
|
|
109
130
|
if (! (date && isDate(date)))
|
|
110
131
|
date = new Date()
|
|
111
132
|
|
|
112
|
-
await onUplinkDevicePortBufferDateLatLng(client, id, port, data, date, lat, lng, maxSize);
|
|
133
|
+
await onUplinkDevicePortBufferDateLatLng(client, id, port, data, date, lat, lng, maxSize, extractLoraInfo(obj));
|
|
113
134
|
});
|
|
114
135
|
return client;
|
|
115
136
|
} catch (e) {
|
|
@@ -1,6 +1,29 @@
|
|
|
1
|
+
// Copyright (C) 2026, Lifefinder Systems International AB, all rights reserved.
|
|
2
|
+
// ChirpStack v4 MQTT integration. Supports plain-password auth via CS4_* env vars.
|
|
1
3
|
const mqtt = require('mqtt')
|
|
2
4
|
const { isDate } = require('util/types');
|
|
3
5
|
|
|
6
|
+
const extractLoraInfo = (obj) => {
|
|
7
|
+
const info = {};
|
|
8
|
+
if (obj.rxInfo && obj.rxInfo.length > 0) {
|
|
9
|
+
const best = obj.rxInfo.reduce((a, b) => ((b.rssi || -999) > (a.rssi || -999) ? b : a), obj.rxInfo[0]);
|
|
10
|
+
if (typeof best.rssi === 'number') info.rssi = best.rssi;
|
|
11
|
+
if (typeof best.snr === 'number') info.snr = best.snr;
|
|
12
|
+
info.gatewayCount = obj.rxInfo.length;
|
|
13
|
+
}
|
|
14
|
+
if (obj.txInfo) {
|
|
15
|
+
if (obj.txInfo.frequency) info.frequency = obj.txInfo.frequency;
|
|
16
|
+
if (obj.txInfo.modulation && obj.txInfo.modulation.lora) {
|
|
17
|
+
const lora = obj.txInfo.modulation.lora;
|
|
18
|
+
if (lora.spreadingFactor) info.spreadingFactor = lora.spreadingFactor;
|
|
19
|
+
if (lora.bandwidth) info.bandwidth = lora.bandwidth;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (Number.isInteger(obj.dr)) info.dataRate = obj.dr;
|
|
23
|
+
info.timestamp = new Date().toISOString();
|
|
24
|
+
return info;
|
|
25
|
+
};
|
|
26
|
+
|
|
4
27
|
const printUsageAndExit = (info) => {
|
|
5
28
|
console.log(info);
|
|
6
29
|
process.exit(1);
|
|
@@ -29,7 +52,15 @@ module.exports.api = {
|
|
|
29
52
|
connectAndSubscribe: async (args, devices, onUplinkDevicePortBufferDateLatLng) => {
|
|
30
53
|
args.v && console.log("Trying to connect to " + args.s + " with application " + args.a);
|
|
31
54
|
try {
|
|
32
|
-
|
|
55
|
+
// Build connect options — auth required for mosquitto plain-password auth (CS4).
|
|
56
|
+
// Credentials read from env so the integration file stays config-free.
|
|
57
|
+
const mqttOpts = {};
|
|
58
|
+
if (process.env.CS4_USERNAME) {
|
|
59
|
+
mqttOpts.clientId = process.env.CS4_CLIENTID || 'vsm-mqtt-client-v4';
|
|
60
|
+
mqttOpts.username = process.env.CS4_USERNAME;
|
|
61
|
+
mqttOpts.password = process.env.CS4_PASSWORD;
|
|
62
|
+
}
|
|
63
|
+
const client = mqtt.connect(args.s, mqttOpts);
|
|
33
64
|
|
|
34
65
|
client.on('connect', () => {
|
|
35
66
|
args.v && console.log("Connected to chirpstack server");
|
|
@@ -94,7 +125,7 @@ module.exports.api = {
|
|
|
94
125
|
if (! (date && isDate(date)))
|
|
95
126
|
date = new Date()
|
|
96
127
|
|
|
97
|
-
await onUplinkDevicePortBufferDateLatLng(client, id, port, data, date, lat, lng, maxSize);
|
|
128
|
+
await onUplinkDevicePortBufferDateLatLng(client, id, port, data, date, lat, lng, maxSize, extractLoraInfo(obj));
|
|
98
129
|
});
|
|
99
130
|
return client;
|
|
100
131
|
} catch (e) {
|
package/merge-and-publish.sh
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
+
merged_main=false
|
|
5
|
+
dep_updated=false
|
|
6
|
+
|
|
4
7
|
# Merge main if there are changes, but keep our package.json
|
|
5
8
|
git fetch origin main
|
|
6
9
|
if ! git diff --quiet HEAD...origin/main; then
|
|
@@ -8,27 +11,41 @@ if ! git diff --quiet HEAD...origin/main; then
|
|
|
8
11
|
git checkout --ours package.json
|
|
9
12
|
git add package.json
|
|
10
13
|
git diff --cached --quiet || git commit -m "Merge origin/main, keeping local package.json"
|
|
14
|
+
merged_main=true
|
|
15
|
+
echo "Merged changes from main"
|
|
11
16
|
fi
|
|
12
17
|
|
|
13
|
-
#
|
|
14
|
-
current_version=$(node -p "require('./package.json').version")
|
|
15
|
-
new_version=$(echo "$current_version" | awk -F. '{print $1"."$2"."$3+1}')
|
|
16
|
-
sed -i "s/\"version\": \"$current_version\"/\"version\": \"$new_version\"/" package.json
|
|
17
|
-
|
|
18
|
-
# Bump dependency version
|
|
18
|
+
# Check dependency version against npm
|
|
19
19
|
current_dep=$(node -p "require('./package.json').dependencies['@lifefinder/vsm-translator-open-source']")
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
echo "
|
|
24
|
-
|
|
20
|
+
current_dep_stripped=$(echo "$current_dep" | sed 's/^[\^~]//')
|
|
21
|
+
new_dep=$(npm view @lifefinder/vsm-translator-open-source version 2>/dev/null)
|
|
22
|
+
if [ -z "$new_dep" ]; then
|
|
23
|
+
echo "Error: Could not fetch latest version of @lifefinder/vsm-translator-open-source from npm"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
if [ "$current_dep_stripped" != "$new_dep" ]; then
|
|
27
|
+
sed -i "s|\"@lifefinder/vsm-translator-open-source\": \"$current_dep\"|\"@lifefinder/vsm-translator-open-source\": \"$new_dep\"|" package.json
|
|
28
|
+
dep_updated=true
|
|
29
|
+
echo "Bumped dependency: $current_dep -> $new_dep"
|
|
30
|
+
else
|
|
31
|
+
echo "Dependency already at latest: $current_dep"
|
|
32
|
+
fi
|
|
25
33
|
|
|
26
|
-
#
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
# Only bump version if there were changes
|
|
35
|
+
if [ "$merged_main" = true ] || [ "$dep_updated" = true ]; then
|
|
36
|
+
current_version=$(node -p "require('./package.json').version")
|
|
37
|
+
new_version=$(echo "$current_version" | awk -F. '{print $1"."$2"."$3+1}')
|
|
38
|
+
sed -i "s/\"version\": \"$current_version\"/\"version\": \"$new_version\"/" package.json
|
|
39
|
+
echo "Bumped version: $current_version -> $new_version"
|
|
29
40
|
|
|
30
|
-
#
|
|
31
|
-
git
|
|
41
|
+
# Commit and push
|
|
42
|
+
git add package.json
|
|
43
|
+
git commit -m "Bump version to $new_version"
|
|
44
|
+
git push
|
|
32
45
|
|
|
33
|
-
echo ""
|
|
34
|
-
echo "Done! Now run: npm publish"
|
|
46
|
+
echo ""
|
|
47
|
+
echo "Done! Now run: npm publish"
|
|
48
|
+
else
|
|
49
|
+
echo ""
|
|
50
|
+
echo "No changes to publish (no merge from main, dependency already current)"
|
|
51
|
+
fi
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifefinder/vsm-mqtt-client-open-source",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.60",
|
|
4
4
|
"description": "MQTT client for vsm sensors",
|
|
5
5
|
"main": "vsm-mqtt-client.js",
|
|
6
6
|
"author": "Lars Mats",
|
|
@@ -14,6 +14,6 @@
|
|
|
14
14
|
"mongodb": "6.3.0",
|
|
15
15
|
"mqtt": "4.3.7",
|
|
16
16
|
"node-fetch": "3.3.1",
|
|
17
|
-
"@lifefinder/vsm-translator-open-source": "
|
|
17
|
+
"@lifefinder/vsm-translator-open-source": "0.2.169"
|
|
18
18
|
}
|
|
19
19
|
}
|
package/vsm-mqtt-client.js
CHANGED
|
@@ -211,7 +211,7 @@ const run = async () => {
|
|
|
211
211
|
console.log('Series Processor: ', seriesProcessor.getName());
|
|
212
212
|
|
|
213
213
|
// Function to handle uplinks for a device id on a port with binary data in buffer
|
|
214
|
-
const onUplinkDevicePortBufferDateLatLng = async (client, deviceid, port, buffer, date, lat, lng, maxSize) => {
|
|
214
|
+
const onUplinkDevicePortBufferDateLatLng = async (client, deviceid, port, buffer, date, lat, lng, maxSize, loraInfo) => {
|
|
215
215
|
if (!(typeof(deviceid) == "string" && isFinite(port) && Buffer.isBuffer(buffer))) {
|
|
216
216
|
console.log(`Integration error: Bad parameter to onUplinkDevicePortBufferDateLatLng:
|
|
217
217
|
typeof(deviceid):${typeof(deviceid)} (expect string), typeof(port)=${typeof(port)} (expect number), Buffer.isBuffer(buffer)=${Buffer.isBuffer(buffer)}`);
|
|
@@ -240,13 +240,14 @@ const run = async () => {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
// Run translation
|
|
243
|
-
let iotnode = { ...previous,
|
|
243
|
+
let iotnode = { ...previous,
|
|
244
244
|
encodedData : {
|
|
245
245
|
port : port,
|
|
246
246
|
hexEncoded : buffer.toString('hex'),
|
|
247
247
|
timestamp: date, // TBD if this should be given by the integration instead?
|
|
248
248
|
maxSize: maxSize,
|
|
249
|
-
}
|
|
249
|
+
},
|
|
250
|
+
...(loraInfo && { lora: loraInfo }),
|
|
250
251
|
}
|
|
251
252
|
let result = {}
|
|
252
253
|
try {
|