Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DL-LID #121

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions VENDORS/Decentlab/DL-LID/ChirpStack/uplink/converter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "ChirpStack Uplink Decoder for Decentlab DL-LID",
"type": "UPLINK",
"debugMode": true,
"edgeTemplate": false,
"configuration": {
"scriptLang": "JS",
"updateOnlyKeys": [
"lora_frame_counter",
"lora_frame_port",
"lora_frequency",
"lora_spreading_factor",
"lora_rssi",
"lora_dev_eui",
"lora_snr"
],
"decoder": "const message = decodeToJson(payload);\nconst values = Object.assign(\n decodeDevicePayload(base64ToBytes(message.data)),\n extractNetworkTelemetry(message)\n);\n\nreturn {\n deviceName: String(values.device_id),\n deviceType: 'DL-LID',\n attributes: {\n lora_dev_eui: values.lora_dev_eui,\n protocol_version: values.protocol_version,\n },\n telemetry: [{\n ts: message.time,\n values: keepTelemetry(values)\n }]\n};\n\nfunction decodeDevicePayload(payload) {\n /* https://www.decentlab.com/products/laser-distance-level-sensor-for-lorawan */\n const decentlab_decoder = {\n PROTOCOL_VERSION: 2,\n SENSORS: [\n {length: 11,\n values: [{name: 'distance_average',\n displayName: 'Distance: average',\n convert: function (x) { return x[0]; },\n unit: 'mm'},\n {name: 'distance_minimum',\n displayName: 'Distance: minimum',\n convert: function (x) { return x[1]; },\n unit: 'mm'},\n {name: 'distance_maximum',\n displayName: 'Distance: maximum',\n convert: function (x) { return x[2]; },\n unit: 'mm'},\n {name: 'distance_median',\n displayName: 'Distance: median',\n convert: function (x) { return x[3]; },\n unit: 'mm'},\n {name: 'distance_10th_percentile',\n displayName: 'Distance: 10th percentile',\n convert: function (x) { return x[4]; },\n unit: 'mm'},\n {name: 'distance_25th_percentile',\n displayName: 'Distance: 25th percentile',\n convert: function (x) { return x[5]; },\n unit: 'mm'},\n {name: 'distance_75th_percentile',\n displayName: 'Distance: 75th percentile',\n convert: function (x) { return x[6]; },\n unit: 'mm'},\n {name: 'distance_90th_percentile',\n displayName: 'Distance: 90th percentile',\n convert: function (x) { return x[7]; },\n unit: 'mm'},\n {name: 'distance_most_frequent_value',\n displayName: 'Distance: most frequent value',\n convert: function (x) { return x[8]; },\n unit: 'mm'},\n {name: 'number_of_samples',\n displayName: 'Number of samples',\n convert: function (x) { return x[9]; }},\n {name: 'total_acquisition_time',\n displayName: 'Total acquisition time',\n convert: function (x) { return x[10] / 1.024; },\n unit: 'ms'}]},\n {length: 1,\n values: [{name: 'battery_voltage',\n displayName: 'Battery voltage',\n convert: function (x) { return x[0] / 1000; },\n unit: 'V'}]}\n ],\n read_int: function (bytes, pos) {\n return (bytes[pos] << 8) + bytes[pos + 1];\n },\n decode: function (msg) {\n var bytes = msg;\n var i, j;\n if (typeof msg === 'string') {\n bytes = [];\n for (i = 0; i < msg.length; i += 2) {\n bytes.push(parseInt(msg.substring(i, i + 2), 16));\n }\n }\n var version = bytes[0];\n if (version != this.PROTOCOL_VERSION) {\n return {error: \"protocol version \" + version + \" doesn't match v2\"};\n }\n var deviceId = this.read_int(bytes, 1);\n var flags = this.read_int(bytes, 3);\n var result = {'protocol_version': version, 'device_id': deviceId};\n // decode payload\n var pos = 5;\n for (i = 0; i < this.SENSORS.length; i++, flags >>= 1) {\n if ((flags & 1) !== 1)\n continue;\n var sensor = this.SENSORS[i];\n var x = [];\n // convert data to 16-bit integer array\n for (j = 0; j < sensor.length; j++) {\n x.push(this.read_int(bytes, pos));\n pos += 2;\n }\n // decode sensor values\n for (j = 0; j < sensor.values.length; j++) {\n var value = sensor.values[j];\n if ('convert' in value) {\n result[value.name] = {displayName: value.displayName,\n value: value.convert.bind(this)(x)};\n if ('unit' in value)\n result[value.name]['unit'] = value.unit;\n }\n }\n }\n return result;\n }\n };\n\n const decoded = decentlab_decoder.decode(payload);\n const result = {};\n for (var k in decoded) {\n if (typeof decoded[k] === \"object\") {\n result[k] = decoded[k].value;\n } else if (typeof decoded[k] === \"number\") {\n result[k] = decoded[k];\n }\n }\n return result;\n}\n\nfunction extractNetworkTelemetry(payload) {\n const result = {\n lora_frame_counter: message.fCnt,\n lora_frame_port: message.fPort,\n lora_frequency: message.txInfo.frequency,\n lora_spreading_factor:\n message?.txInfo?.modulation?.lora?.spreadingFactor ||\n message.txInfo.loRaModulationInfo.spreadingFactor,\n lora_dev_eui: (\n message?.deviceInfo?.devEui ||\n base64ToBytes(message.devEUI).reduce(\n (a, x) => a + (\"0\" + x.toString(16)).slice(-2),\n \"\",\n )\n ).toUpperCase(),\n };\n const gwi = message.rxInfo\n .map((x) => ({ lora_rssi: x.rssi, lora_snr: x.snr || x.loRaSNR }))\n .reduce((a, x) => (x.lora_rssi > a.lora_rssi ? x : a), {\n lora_rssi: -Number.MAX_VALUE,\n });\n return Object.assign(result, gwi);\n}\n\n// Helper functions\n\nfunction decodeToJson(payload) {\n const s = String.fromCharCode.apply(String, payload);\n return JSON.parse(s);\n}\n\nfunction parseDateToTimestamp(dateString) {\n var timestamp = -1;\n if (dateString != null) {\n timestamp = new Date(dateString).getTime();\n if (timestamp == -1) {\n var secondsSeparatorIndex = dateString.lastIndexOf('.') + 1;\n var millisecondsEndIndex = dateString.lastIndexOf('+');\n if (millisecondsEndIndex == -1) {\n millisecondsEndIndex = dateString.lastIndexOf('Z');\n }\n if (millisecondsEndIndex == -1) {\n millisecondsEndIndex = dateString.lastIndexOf('-');\n }\n if (millisecondsEndIndex == -1) {\n if (dateString.length >= secondsSeparatorIndex + 3) {\n dateString = dateString.substring(0, secondsSeparatorIndex + 3);\n }\n } else {\n dateString = dateString.substring(0, secondsSeparatorIndex + 3) +\n dateString.substring(millisecondsEndIndex, dateString.length);\n }\n timestamp = new Date(dateString).getTime();\n }\n }\n // If we cannot parse timestamp - we will use the current timestamp\n if (timestamp == -1) {\n timestamp = Date.now();\n }\n\n return timestamp;\n}\n\nfunction base64ToBytes(base64String) {\n if (typeof base64String === 'string') {\n return Uint8Array.from(atob(base64String), c => c.charCodeAt(0));\n }\n return [];\n}\n\nfunction keepTelemetry(telemetry) {\n const unwanted = ['protocol_version', 'device_id', 'lora_dev_eui'];\n return Object.fromEntries(\n Object.entries(telemetry).filter(\n (x) => !unwanted.includes(x[0])\n )\n );\n}"
}
}
4 changes: 4 additions & 0 deletions VENDORS/Decentlab/DL-LID/ChirpStack/uplink/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"integrationName": "ChirpStack integration",
"includeGatewayInfo": false
}
55 changes: 55 additions & 0 deletions VENDORS/Decentlab/DL-LID/ChirpStack/uplink/payload.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"adr": true,
"confirmed": false,
"data": "AhHJAAMRmxF2EbwRnhGKEZQRqBGoEZQAZAGZCr0=",
"deduplicationId": "ede7dfc1-a1f5-418c-b009-dc57ebcf0895",
"devAddr": "017d1f70",
"deviceInfo": {
"applicationId": "32dafeb5-0865-4edd-bf1c-3f8d9b07af52",
"applicationName": "MoDus-Sain",
"devEui": "70b3d57ba0003bb8",
"deviceClassEnabled": "CLASS_A",
"deviceName": "PM-15288",
"deviceProfileId": "7ec3de3f-7b87-49ae-8f32-330249122a50",
"deviceProfileName": "dev-prof-Decentlab",
"tags": {
"lts": "true"
},
"tenantId": "663cc43f-0bf2-48d4-afc6-ff27ba969f10",
"tenantName": "Friloranet"
},
"dr": 5,
"fCnt": 20,
"fPort": 1,
"rxInfo": [
{
"context": "AAAAAAAAAAAA/gADaoXb7A==",
"crcStatus": "CRC_OK",
"gatewayId": "fcc23dfffe2e72ed",
"gwTime": "2024-11-12T12:51:50+00:00",
"location": {
"latitude": 46.80179269386121,
"longitude": 7.1381521224975595
},
"metadata": {
"region_common_name": "EU868",
"region_config_id": "eu868"
},
"nsTime": "2024-11-12T12:51:50.819853185+00:00",
"rssi": -106,
"snr": 3.0,
"uplinkId": 3257702911
}
],
"time": "2024-11-10T12:51:50+00:00",
"txInfo": {
"frequency": 868300000,
"modulation": {
"lora": {
"bandwidth": 125000,
"codeRate": "CR_4_5",
"spreadingFactor": 7
}
}
}
}
55 changes: 55 additions & 0 deletions VENDORS/Decentlab/DL-LID/ChirpStack/uplink/payload_01.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"adr": true,
"confirmed": false,
"data": "AhHJAAIKvQ==",
"deduplicationId": "ede7dfc1-a1f5-418c-b009-dc57ebcf0895",
"devAddr": "017d1f70",
"deviceInfo": {
"applicationId": "32dafeb5-0865-4edd-bf1c-3f8d9b07af52",
"applicationName": "MoDus-Sain",
"devEui": "70b3d57ba0003bb8",
"deviceClassEnabled": "CLASS_A",
"deviceName": "PM-15288",
"deviceProfileId": "7ec3de3f-7b87-49ae-8f32-330249122a50",
"deviceProfileName": "dev-prof-Decentlab",
"tags": {
"lts": "true"
},
"tenantId": "663cc43f-0bf2-48d4-afc6-ff27ba969f10",
"tenantName": "Friloranet"
},
"dr": 5,
"fCnt": 20,
"fPort": 1,
"rxInfo": [
{
"context": "AAAAAAAAAAAA/gADaoXb7A==",
"crcStatus": "CRC_OK",
"gatewayId": "fcc23dfffe2e72ed",
"gwTime": "2024-11-12T12:51:50+00:00",
"location": {
"latitude": 46.80179269386121,
"longitude": 7.1381521224975595
},
"metadata": {
"region_common_name": "EU868",
"region_config_id": "eu868"
},
"nsTime": "2024-11-12T12:51:50.819853185+00:00",
"rssi": -106,
"snr": 3.0,
"uplinkId": 3257702911
}
],
"time": "2024-11-10T12:51:50+00:00",
"txInfo": {
"frequency": 868300000,
"modulation": {
"lora": {
"bandwidth": 125000,
"codeRate": "CR_4_5",
"spreadingFactor": 7
}
}
}
}
46 changes: 46 additions & 0 deletions VENDORS/Decentlab/DL-LID/ChirpStack/uplink/payload_02.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"applicationID": "123",
"applicationName": "temperature-sensor",
"deviceName": "garden-sensor",
"devEUI": "AgICAgICAgI=",
"rxInfo": [
{
"gatewayID": "AwMDAwMDAwM=",
"time": "2019-11-08T13:59:25.048445Z",
"timeSinceGPSEpoch": null,
"rssi": -48,
"loRaSNR": 9,
"channel": 5,
"rfChain": 0,
"board": 0,
"antenna": 0,
"location": {
"latitude": 52.3740364,
"longitude": 4.9144401,
"altitude": 10.5
},
"fineTimestampType": "NONE",
"context": "9u/uvA==",
"uplinkID": "jhMh8Gq6RAOChSKbi83RHQ=="
}
],
"txInfo": {
"frequency": 868100000,
"modulation": "LORA",
"loRaModulationInfo": {
"bandwidth": 125,
"spreadingFactor": 11,
"codeRate": "4/5",
"polarizationInversion": false
}
},
"adr": true,
"dr": 1,
"fCnt": 10,
"fPort": 5,
"data": "AhHJAAMRmxF2EbwRnhGKEZQRqBGoEZQAZAGZCr0=",
"objectJSON": "{\"temperatureSensor\":25,\"humiditySensor\":32}",
"tags": {
"key": "value"
}
}
46 changes: 46 additions & 0 deletions VENDORS/Decentlab/DL-LID/ChirpStack/uplink/payload_03.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"applicationID": "123",
"applicationName": "temperature-sensor",
"deviceName": "garden-sensor",
"devEUI": "AgICAgICAgI=",
"rxInfo": [
{
"gatewayID": "AwMDAwMDAwM=",
"time": "2019-11-08T13:59:25.048445Z",
"timeSinceGPSEpoch": null,
"rssi": -48,
"loRaSNR": 9,
"channel": 5,
"rfChain": 0,
"board": 0,
"antenna": 0,
"location": {
"latitude": 52.3740364,
"longitude": 4.9144401,
"altitude": 10.5
},
"fineTimestampType": "NONE",
"context": "9u/uvA==",
"uplinkID": "jhMh8Gq6RAOChSKbi83RHQ=="
}
],
"txInfo": {
"frequency": 868100000,
"modulation": "LORA",
"loRaModulationInfo": {
"bandwidth": 125,
"spreadingFactor": 11,
"codeRate": "4/5",
"polarizationInversion": false
}
},
"adr": true,
"dr": 1,
"fCnt": 10,
"fPort": 5,
"data": "AhHJAAIKvQ==",
"objectJSON": "{\"temperatureSensor\":25,\"humiditySensor\":32}",
"tags": {
"key": "value"
}
}
33 changes: 33 additions & 0 deletions VENDORS/Decentlab/DL-LID/ChirpStack/uplink/result.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"deviceName": "4553",
"deviceType": "DL-LID",
"attributes": {
"lora_dev_eui": "70B3D57BA0003BB8",
"protocol_version": 2
},
"telemetry": [
{
"ts": "2024-11-10T12:51:50+00:00",
"values": {
"distance_average": 4507,
"distance_minimum": 4470,
"distance_maximum": 4540,
"distance_median": 4510,
"distance_10th_percentile": 4490,
"distance_25th_percentile": 4500,
"distance_75th_percentile": 4520,
"distance_90th_percentile": 4520,
"distance_most_frequent_value": 4500,
"number_of_samples": 100,
"total_acquisition_time": 399.4140625,
"battery_voltage": 2.749,
"lora_frame_counter": 20,
"lora_frame_port": 1,
"lora_frequency": 868300000,
"lora_spreading_factor": 7,
"lora_rssi": -106,
"lora_snr": 3
}
}
]
}
22 changes: 22 additions & 0 deletions VENDORS/Decentlab/DL-LID/ChirpStack/uplink/result_01.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"deviceName": "4553",
"deviceType": "DL-LID",
"attributes": {
"lora_dev_eui": "70B3D57BA0003BB8",
"protocol_version": 2
},
"telemetry": [
{
"ts": "2024-11-10T12:51:50+00:00",
"values": {
"battery_voltage": 2.749,
"lora_frame_counter": 20,
"lora_frame_port": 1,
"lora_frequency": 868300000,
"lora_spreading_factor": 7,
"lora_rssi": -106,
"lora_snr": 3
}
}
]
}
32 changes: 32 additions & 0 deletions VENDORS/Decentlab/DL-LID/ChirpStack/uplink/result_02.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"deviceName": "4553",
"deviceType": "DL-LID",
"attributes": {
"lora_dev_eui": "0202020202020202",
"protocol_version": 2
},
"telemetry": [
{
"values": {
"distance_average": 4507,
"distance_minimum": 4470,
"distance_maximum": 4540,
"distance_median": 4510,
"distance_10th_percentile": 4490,
"distance_25th_percentile": 4500,
"distance_75th_percentile": 4520,
"distance_90th_percentile": 4520,
"distance_most_frequent_value": 4500,
"number_of_samples": 100,
"total_acquisition_time": 399.4140625,
"battery_voltage": 2.749,
"lora_frame_counter": 10,
"lora_frame_port": 5,
"lora_frequency": 868100000,
"lora_spreading_factor": 11,
"lora_rssi": -48,
"lora_snr": 9
}
}
]
}
21 changes: 21 additions & 0 deletions VENDORS/Decentlab/DL-LID/ChirpStack/uplink/result_03.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"deviceName": "4553",
"deviceType": "DL-LID",
"attributes": {
"lora_dev_eui": "0202020202020202",
"protocol_version": 2
},
"telemetry": [
{
"values": {
"battery_voltage": 2.749,
"lora_frame_counter": 10,
"lora_frame_port": 5,
"lora_frequency": 868100000,
"lora_spreading_factor": 11,
"lora_rssi": -48,
"lora_snr": 9
}
}
]
}
Loading