Skip to content

Commit

Permalink
Merge pull request #25 from artem-barysh-dev/CT101_CT103
Browse files Browse the repository at this point in the history
CT101/103
  • Loading branch information
ashvayka authored Oct 31, 2024
2 parents 0f94706 + c635ed6 commit 19dd6fb
Show file tree
Hide file tree
Showing 51 changed files with 1,673 additions and 0 deletions.
35 changes: 35 additions & 0 deletions VENDORS/Milesight/CT101-CT103/ChirpStack/uplink/converter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "ChirpStack uplink converter for Milesight AT101/103",
"type": "UPLINK",
"debugMode": true,
"configuration": {
"scriptLang": "TBEL",
"decoder": null,
"tbelDecoder": "var data = decodeToJson(payload);\nvar deviceName = \"CT101/CT103 \" + data.deviceInfo.deviceName;\nvar deviceType = \"CT101/CT103\";\nvar groupName = null; // If groupName is not null - created device will be added to the entity group with such name.\nvar customerName = null; // If customerName is not null - created devices will be assigned to customer with such name. \n\n// use assetName and assetType instead of deviceName and deviceType\n// to automatically create assets instead of devices.\n// var assetName = 'Asset A';\n// var assetType = 'building';\n\n// If you want to parse incoming data somehow, you can add your code to this function.\n// input: bytes\n// expected output:\n// {\n// \"attributes\": {\"attributeKey\": \"attributeValue\"},\n// \"telemetry\": [{\"ts\": 1...1, \"values\": {\"telemetryKey\":\"telemetryValue\"}, {\"ts\": 1...2, \"values\": {\"telemetryKey\":\"telemetryValue\"}}]\n// }\n\nfunction decodePayload(input) {\n var output = {\n attributes: {},\n telemetry: []\n };\n \n // --- Decoding code --- //\n var decoded = {};\n for (var i = 0; i < input.length - 2;) {\n var channel_id = input[i++] & 0xff;\n var channel_type = input[i++] & 0xff;\n \n // POWER STATE\n if (channel_id === 0xff && channel_type === 0x0b) {\n decoded.power = \"on\";\n i += 1;\n }\n // IPSO VERSION\n if (channel_id === 0xff && channel_type === 0x01) {\n decoded.ipso_version = readProtocolVersion(input[i]);\n i += 1;\n }\n // PRODUCT SERIAL NUMBER\n if (channel_id === 0xff && channel_type === 0x16) {\n decoded.sn = bytesToHex(java.util.Arrays.copyOfRange(input, i, i + 8));\n i += 8;\n }\n // HARDWARE VERSION\n if (channel_id === 0xff && channel_type === 0x09) {\n decoded.hardware_version = readHardwareVersion(java.util.Arrays.copyOfRange(input, i, i + 2));\n i += 2;\n }\n // FIRMWARE VERSION\n if (channel_id === 0xff && channel_type === 0x0a) {\n decoded.firmware_version = readFirmwareVersion(java.util.Arrays.copyOfRange(input, i, i + 2));\n i += 2;\n }\n // TOTAL CURRENT\n if (channel_id === 0x03 && channel_type === 0x97) {\n decoded.total_current = parseBytesToInt(input, i, 4, false) / 100;\n i += 4;\n }\n // CURRENT\n if (channel_id === 0x04 && channel_type === 0x98) {\n var value = parseBytesToInt(input, i, 2, false);\n if (value === 0xffff) {\n decoded.alarm = \"read failed\";\n } else {\n decoded.current = value / 100;\n }\n i += 2;\n }\n // TEMPERATURE\n if (channel_id === 0x09 && channel_type === 0x67) {\n var temperature_value = parseBytesToInt(input, i, 2, false);\n if (temperature_value === 0xfffd) {\n decoded.temperature_exception = \"over range alarm\";\n } else if (temperature_value === 0xffff) {\n decoded.temperature_exception = \"read failed\";\n } else {\n decoded.temperature = parseBytesToInt(input, i, 2, false) / 10;\n }\n i += 2;\n }\n // CURRENT ALARM\n if (channel_id === 0x84 && channel_type === 0x98) {\n decoded.current_max = parseBytesToInt(input, i, 2, false) / 100;\n decoded.current_min = parseBytesToInt(input, i + 2, 2, false) / 100;\n decoded.current = parseBytesToInt(input, i + 4, 2, false) / 100;\n decoded.alarm = readCurrentAlarm(input[i + 6]);\n i += 7;\n }\n // TEMPERATURE ALARM\n if (channel_id === 0x89 && channel_type === 0x67) {\n decoded.temperature = parseBytesToInt(input, i, 2, false) / 10;\n decoded.temperature_alarm = readTemperatureAlarm(input[i + 2]);\n i += 3;\n }\n }\n\n output.telemetry = [{\n ts: timestamp,\n values: decoded\n }];\n \n // --- Decoding code --- //\n return output;\n}\n\n// --- attributes and telemetry objects ---\nvar telemetry = [];\nvar attributes = {};\n// --- attributes and telemetry objects ---\n\n// --- Timestamp parsing\nvar dateString = data.time;\ntimestamp = parseDateToTimestamp(dateString);\n// --- Timestamp parsing\n\n// Passing incoming bytes to decodePayload function, to get custom decoding\nvar customDecoding = decodePayload(base64ToBytes(data\n.data));\n\n\nattributes.eui = data.deviceInfo.devEui;\n\n// Collecting data to result\nif (customDecoding.?telemetry.size() > 0) {\n if (customDecoding.telemetry instanceof java.util.ArrayList) {\n foreach(telemetryObj: customDecoding.telemetry) {\n if (telemetryObj.ts != null && telemetryObj.values != null) {\n telemetry.add(telemetryObj);\n }\n }\n } else {\n telemetry.putAll(customDecoding.telemetry);\n }\n}\n\nif (customDecoding.?attributes.size() > 0) {\n attributes.putAll(customDecoding.attributes);\n}\n\n// You can add some keys manually to attributes or telemetry\nattributes.eui = data.deviceInfo.?devEui;\nattributes.devAddr = data.devAddr;\nattributes.fPort = data.fPort;\nattributes.applicationId = data.deviceInfo.?applicationId;\nattributes.applicationName = data.deviceInfo.?applicationName;\nattributes.tenantId = data.deviceInfo.?tenantId;\nattributes.tenantName = data.deviceInfo.?tenantName;\nattributes.deviceProfileId = data.deviceInfo.?deviceProfileId;\nattributes.deviceProfileName = data.deviceInfo.?deviceProfileName;\nattributes.frequency = data.txInfo.?frequency;\nattributes.bandwidth = data.txInfo.?modulation.?lora.?bandwidth;\nattributes.spreadingFactor = data.txInfo.?modulation.?lora.?spreadingFactor;\nattributes.codeRate = data.txInfo.?modulation.?lora.?codeRate;\n\nvar gatewayInfo = getGatewayInfo();\nvar addDataToTelemetry = {};\naddDataToTelemetry.snr = gatewayInfo.snr;\naddDataToTelemetry.rssi = gatewayInfo.rssi;\naddDataToTelemetry.channel = gatewayInfo.channel;\naddDataToTelemetry.rfChain = gatewayInfo.rfChain;\naddDataToTelemetry.fCnt = data.fCnt;\n\nvar isIncludeGatewayInfo = metadata[\"includeGatewayInfo\"];\nif(isIncludeGatewayInfo == true) {\n telemetry = processTelemetryData(telemetry, addDataToTelemetry);\n}\n\nvar result = {\n deviceName: deviceName,\n deviceType: deviceType,\n // assetName: assetName,\n // assetType: assetType,\n attributes: attributes,\n telemetry: telemetry\n};\n\naddAdditionalInfoForDeviceMsg(result, customerName, groupName);\n\nreturn result;\n\nfunction addAdditionalInfoForDeviceMsg(deviceInfo, customerName, groupName) {\n if (customerName != null) {\n deviceInfo.customerName = customerName;\n }\n if (groupName != null) {\n deviceInfo.groupName = groupName;\n }\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(\n '.') + 1;\n var millisecondsEndIndex = dateString.lastIndexOf(\n '+');\n if (millisecondsEndIndex == -1) {\n millisecondsEndIndex = dateString.lastIndexOf(\n 'Z');\n }\n if (millisecondsEndIndex == -1) {\n millisecondsEndIndex = dateString.lastIndexOf(\n '-');\n }\n if (millisecondsEndIndex == -1) {\n if (dateString.length >= secondsSeparatorIndex +\n 3) {\n dateString = dateString.substring(0,\n secondsSeparatorIndex + 3);\n }\n } else {\n dateString = dateString.substring(0,\n secondsSeparatorIndex + 3) +\n dateString.substring(millisecondsEndIndex,\n 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 getGatewayInfo() {\n var gatewayList = data.rxInfo;\n var maxRssi = Integer. MIN_VALUE;\n var gatewayInfo = {};\n \n foreach (gateway : gatewayList) {\n if(gateway.rssi > maxRssi) {\n maxRssi = gateway.rssi;\n gatewayInfo = gateway;\n }\n }\n \n return gatewayInfo;\n}\n\nfunction processTelemetryData(telemetry, addDataToTelemetry) {\n if (telemetry.size > 1) {\n telemetry = addDataToMultipleTelemetries(telemetry, addDataToTelemetry);\n }\n else if (telemetry.size == 1) {\n telemetry = addDataToSingleTelemetry(telemetry, addDataToTelemetry);\n }\n else {\n telemetry.add(addDataToTelemetry);\n }\n \n return telemetry;\n}\n\nfunction addDataToMultipleTelemetries(telemetry, addDataToTelemetry) {\n foreach(element : addDataToTelemetry.entrySet()) {\n if(!telemetry[0][\"values\"].keys.contains(element.key)) {\n telemetry[0][\"values\"][element.key] = element.value;\n }\n if (!telemetry[1][\"values\"].keys.contains(element.key)) {\n telemetry[1][\"values\"][element.key] = element.value;\n }\n }\n \n return telemetry;\n}\n\nfunction addDataToSingleTelemetry(telemetry, addDataToTelemetry) {\n foreach(element : addDataToTelemetry.entrySet()) {\n if(!telemetry[0][\"values\"].keys.contains(element.key)) {\n telemetry[0][\"values\"][element.key] = element.value;\n }\n }\n \n return telemetry;\n}\n\nfunction readProtocolVersion(bytes) {\n var major = (bytes & 0xf0) >> 4;\n var minor = bytes & 0x0f;\n return \"v\" + major + \".\" + minor;\n}\n\nfunction readHardwareVersion(bytes) {\n var major = bytes[0] & 0xff;\n var minor = (bytes[1] & 0xff) >> 4;\n return \"v\" + major + \".\" + minor;\n}\n\nfunction readFirmwareVersion(bytes) {\n var major = bytes[0] & 0xff;\n var minor = bytes[1] & 0xff;\n return \"v\" + major + \".\" + minor;\n}\n\nfunction readCurrentAlarm(type) {\n var alarm = [];\n if ((type >> 0 & 0x01) != 0) {\n alarm.add(\"threshold alarm\");\n }\n if ((type >> 1 & 0x01) != 0) {\n alarm.add(\"threshold alarm release\");\n }\n if ((type >> 2 & 0x01) != 0) {\n alarm.add(\"over range alarm\");\n }\n if ((type >> 3 & 0x01) != 0) {\n alarm.add(\"over range alarm release\");\n }\n \n return alarm;\n}\n\nfunction readTemperatureAlarm(type) {\n var alarms = [];\n \n if ((type & 0x01) != 0) {\n alarms.add(\"Threshold alarm\");\n }\n if ((type & 0x02) != 0) {\n alarms.add(\"Threshold alarm dismiss\");\n }\n\n return alarms;\n}",
"encoder": null,
"tbelEncoder": null,
"updateOnlyKeys": [
"tenantId",
"tenantName",
"applicationId",
"applicationName",
"deviceProfileId",
"deviceProfileName",
"devAddr",
"fPort",
"frequency",
"bandwidth",
"spreadingFactor",
"codeRate",
"battery",
"channel",
"rfChain",
"eui",
"beep"
]
},
"additionalInfo": {
"description": ""
},
"edgeTemplate": false
}
4 changes: 4 additions & 0 deletions VENDORS/Milesight/CT101-CT103/ChirpStack/uplink/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"integrationName": "ChirpStack integration",
"includeGatewayInfo": false
}
48 changes: 48 additions & 0 deletions VENDORS/Milesight/CT101-CT103/ChirpStack/uplink/payload_1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"deduplicationId": "57433366-50a6-4dc2-8145-2df1bbc70d9e",
"time": "2023-05-22T07:47:05.404859+00:00",
"deviceInfo": {
"tenantId": "52f14cd4-c6f1-4fbd-8f87-4025e1d49242",
"tenantName": "ChirpStack",
"applicationId": "ca739e26-7b67-4f14-b69e-d568c22a5a75",
"applicationName": "Chirpstack application",
"deviceProfileId": "605d08d4-65f5-4d2c-8a5a-3d2457662f79",
"deviceProfileName": "Chirpstack default device profile",
"deviceName": "Device name",
"devEui": "1000000000000001",
"tags": {}
},
"devAddr": "20000001",
"adr": true,
"dr": 5,
"fCnt": 4,
"fPort": 85,
"confirmed": false,
"data": "/wv//wEB/xZnRtOIAlgAAP8JAQD/CgEB/w8A",
"rxInfo": [{
"gatewayId": "6a7e111a10000000",
"uplinkId": 24022,
"time": "2023-05-22T07:47:05.404859+00:00",
"rssi": -35,
"snr": 11.5,
"channel": 2,
"rfChain": 1,
"location": {},
"context": "EFwMtA==",
"metadata": {
"region_common_name": "EU868",
"region_config_id": "eu868"
},
"crcStatus": "CRC_OK"
}],
"txInfo": {
"frequency": 868500000,
"modulation": {
"lora": {
"bandwidth": 125000,
"spreadingFactor": 7,
"codeRate": "CR_4_5"
}
}
}
}
48 changes: 48 additions & 0 deletions VENDORS/Milesight/CT101-CT103/ChirpStack/uplink/payload_2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"deduplicationId": "57433366-50a6-4dc2-8145-2df1bbc70d9e",
"time": "2023-05-22T07:47:05.404859+00:00",
"deviceInfo": {
"tenantId": "52f14cd4-c6f1-4fbd-8f87-4025e1d49242",
"tenantName": "ChirpStack",
"applicationId": "ca739e26-7b67-4f14-b69e-d568c22a5a75",
"applicationName": "Chirpstack application",
"deviceProfileId": "605d08d4-65f5-4d2c-8a5a-3d2457662f79",
"deviceProfileName": "Chirpstack default device profile",
"deviceName": "Device name",
"devEui": "1000000000000001",
"tags": {}
},
"devAddr": "20000001",
"adr": true,
"dr": 5,
"fCnt": 4,
"fPort": 85,
"confirmed": false,
"data": "A5cQJwAA",
"rxInfo": [{
"gatewayId": "6a7e111a10000000",
"uplinkId": 24022,
"time": "2023-05-22T07:47:05.404859+00:00",
"rssi": -35,
"snr": 11.5,
"channel": 2,
"rfChain": 1,
"location": {},
"context": "EFwMtA==",
"metadata": {
"region_common_name": "EU868",
"region_config_id": "eu868"
},
"crcStatus": "CRC_OK"
}],
"txInfo": {
"frequency": 868500000,
"modulation": {
"lora": {
"bandwidth": 125000,
"spreadingFactor": 7,
"codeRate": "CR_4_5"
}
}
}
}
48 changes: 48 additions & 0 deletions VENDORS/Milesight/CT101-CT103/ChirpStack/uplink/payload_3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"deduplicationId": "57433366-50a6-4dc2-8145-2df1bbc70d9e",
"time": "2023-05-22T07:47:05.404859+00:00",
"deviceInfo": {
"tenantId": "52f14cd4-c6f1-4fbd-8f87-4025e1d49242",
"tenantName": "ChirpStack",
"applicationId": "ca739e26-7b67-4f14-b69e-d568c22a5a75",
"applicationName": "Chirpstack application",
"deviceProfileId": "605d08d4-65f5-4d2c-8a5a-3d2457662f79",
"deviceProfileName": "Chirpstack default device profile",
"deviceName": "Device name",
"devEui": "1000000000000001",
"tags": {}
},
"devAddr": "20000001",
"adr": true,
"dr": 5,
"fCnt": 4,
"fPort": 85,
"confirmed": false,
"data": "BJi4CwAAAAA=",
"rxInfo": [{
"gatewayId": "6a7e111a10000000",
"uplinkId": 24022,
"time": "2023-05-22T07:47:05.404859+00:00",
"rssi": -35,
"snr": 11.5,
"channel": 2,
"rfChain": 1,
"location": {},
"context": "EFwMtA==",
"metadata": {
"region_common_name": "EU868",
"region_config_id": "eu868"
},
"crcStatus": "CRC_OK"
}],
"txInfo": {
"frequency": 868500000,
"modulation": {
"lora": {
"bandwidth": 125000,
"spreadingFactor": 7,
"codeRate": "CR_4_5"
}
}
}
}
48 changes: 48 additions & 0 deletions VENDORS/Milesight/CT101-CT103/ChirpStack/uplink/payload_4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"deduplicationId": "57433366-50a6-4dc2-8145-2df1bbc70d9e",
"time": "2023-05-22T07:47:05.404859+00:00",
"deviceInfo": {
"tenantId": "52f14cd4-c6f1-4fbd-8f87-4025e1d49242",
"tenantName": "ChirpStack",
"applicationId": "ca739e26-7b67-4f14-b69e-d568c22a5a75",
"applicationName": "Chirpstack application",
"deviceProfileId": "605d08d4-65f5-4d2c-8a5a-3d2457662f79",
"deviceProfileName": "Chirpstack default device profile",
"deviceName": "Device name",
"devEui": "1000000000000001",
"tags": {}
},
"devAddr": "20000001",
"adr": true,
"dr": 5,
"fCnt": 4,
"fPort": 85,
"confirmed": false,
"data": "BJj//w==",
"rxInfo": [{
"gatewayId": "6a7e111a10000000",
"uplinkId": 24022,
"time": "2023-05-22T07:47:05.404859+00:00",
"rssi": -35,
"snr": 11.5,
"channel": 2,
"rfChain": 1,
"location": {},
"context": "EFwMtA==",
"metadata": {
"region_common_name": "EU868",
"region_config_id": "eu868"
},
"crcStatus": "CRC_OK"
}],
"txInfo": {
"frequency": 868500000,
"modulation": {
"lora": {
"bandwidth": 125000,
"spreadingFactor": 7,
"codeRate": "CR_4_5"
}
}
}
}
48 changes: 48 additions & 0 deletions VENDORS/Milesight/CT101-CT103/ChirpStack/uplink/payload_5.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"deduplicationId": "57433366-50a6-4dc2-8145-2df1bbc70d9e",
"time": "2023-05-22T07:47:05.404859+00:00",
"deviceInfo": {
"tenantId": "52f14cd4-c6f1-4fbd-8f87-4025e1d49242",
"tenantName": "ChirpStack",
"applicationId": "ca739e26-7b67-4f14-b69e-d568c22a5a75",
"applicationName": "Chirpstack application",
"deviceProfileId": "605d08d4-65f5-4d2c-8a5a-3d2457662f79",
"deviceProfileName": "Chirpstack default device profile",
"deviceName": "Device name",
"devEui": "1000000000000001",
"tags": {}
},
"devAddr": "20000001",
"adr": true,
"dr": 5,
"fCnt": 4,
"fPort": 85,
"confirmed": false,
"data": "hJi4C9AHxAkF",
"rxInfo": [{
"gatewayId": "6a7e111a10000000",
"uplinkId": 24022,
"time": "2023-05-22T07:47:05.404859+00:00",
"rssi": -35,
"snr": 11.5,
"channel": 2,
"rfChain": 1,
"location": {},
"context": "EFwMtA==",
"metadata": {
"region_common_name": "EU868",
"region_config_id": "eu868"
},
"crcStatus": "CRC_OK"
}],
"txInfo": {
"frequency": 868500000,
"modulation": {
"lora": {
"bandwidth": 125000,
"spreadingFactor": 7,
"codeRate": "CR_4_5"
}
}
}
}
29 changes: 29 additions & 0 deletions VENDORS/Milesight/CT101-CT103/ChirpStack/uplink/result_1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"deviceName": "CT101/CT103 Device name",
"deviceType": "CT101/CT103",
"attributes": {
"eui": "1000000000000001",
"devAddr": "20000001",
"fPort": 85,
"applicationId": "ca739e26-7b67-4f14-b69e-d568c22a5a75",
"applicationName": "Chirpstack application",
"tenantId": "52f14cd4-c6f1-4fbd-8f87-4025e1d49242",
"tenantName": "ChirpStack",
"deviceProfileId": "605d08d4-65f5-4d2c-8a5a-3d2457662f79",
"deviceProfileName": "Chirpstack default device profile",
"frequency": 868500000,
"bandwidth": 125000,
"spreadingFactor": 7,
"codeRate": "CR_4_5"
},
"telemetry": [{
"ts": 1684741625404,
"values": {
"power": "on",
"ipso_version": "v0.1",
"sn": "6746D38802580000",
"hardware_version": "v1.0",
"firmware_version": "v1.1"
}
}]
}
25 changes: 25 additions & 0 deletions VENDORS/Milesight/CT101-CT103/ChirpStack/uplink/result_2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"deviceName": "CT101/CT103 Device name",
"deviceType": "CT101/CT103",
"attributes": {
"eui": "1000000000000001",
"devAddr": "20000001",
"fPort": 85,
"applicationId": "ca739e26-7b67-4f14-b69e-d568c22a5a75",
"applicationName": "Chirpstack application",
"tenantId": "52f14cd4-c6f1-4fbd-8f87-4025e1d49242",
"tenantName": "ChirpStack",
"deviceProfileId": "605d08d4-65f5-4d2c-8a5a-3d2457662f79",
"deviceProfileName": "Chirpstack default device profile",
"frequency": 868500000,
"bandwidth": 125000,
"spreadingFactor": 7,
"codeRate": "CR_4_5"
},
"telemetry": [{
"ts": 1684741625404,
"values": {
"total_current": 100.0
}
}]
}
Loading

0 comments on commit 19dd6fb

Please sign in to comment.