{ "name": "Things Stack Industries Uplink Converter for MClimate CO2 Display Lite", "type": "UPLINK", "integrationType": "TTI", "debugMode": false, "debugSettings": { "failuresEnabled": true, "allEnabled": false, "allEnabledUntil": 0 }, "configuration": { "scriptLang": "TBEL", "decoder": "// Decode an uplink message from a buffer\n// payload - array of bytes\n// metadata - key/value object\n\n/** Decoder **/\n\n// decode payload to string\nvar payloadStr = decodeToString(payload);\n\n// decode payload to JSON\n// var data = decodeToJson(payload);\n\nvar deviceName = 'Device A';\nvar deviceType = 'thermostat';\nvar customerName = 'Customer C';\nvar groupName = 'thermostat devices';\nvar manufacturer = 'Example corporation';\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// Result object with device/asset attributes/telemetry data\nvar result = {\n// Use deviceName and deviceType or assetName and assetType, but not both.\n deviceName: deviceName,\n deviceType: deviceType,\n// assetName: assetName,\n// assetType: assetType,\n// customerName: customerName,\n groupName: groupName,\n attributes: {\n model: 'Model A',\n serialNumber: 'SN111',\n integrationName: metadata['integrationName'],\n manufacturer: manufacturer\n },\n telemetry: {\n temperature: 42,\n humidity: 80,\n rawData: payloadStr\n }\n};\n\n/** Helper functions **/\n\nfunction decodeToString(payload) {\n return String.fromCharCode.apply(String, payload);\n}\n\nfunction decodeToJson(payload) {\n // covert payload to string.\n var str = decodeToString(payload);\n\n // parse string to JSON\n var data = JSON.parse(str);\n return data;\n}\n\nreturn result;", "tbelDecoder": "function decodePayload(input) {\n var result = { attributes: {}, telemetry: {} };\n var timestamp = metadata.ts;\n var values = {};\n if (parseBytesToInt(input, 0, 1) == 1) {\n values = handleKeepalive(input, values);\n } else {\n values = handleResponse(input, values);\n var tail = input.subList(input.size() - 10, input.size());\n values = handleKeepalive(tail, values);\n }\n result.telemetry = { ts: timestamp, values: values };\n return result;\n}\n\nfunction handleKeepalive(bytes, data) {\n var tempRaw = parseBytesToInt(bytes, 1, 2);\n data.sensorTemperature = (tempRaw - 400) / 10;\n data.relativeHumidity = toFixed(parseBytesToInt(bytes, 3, 1) * 100 / 256, 2);\n var battRaw = parseBytesToInt(bytes, 4, 2);\n data.batteryVoltage = battRaw / 1000;\n var low = parseBytesToInt(bytes, 6, 1);\n var b7 = parseBytesToInt(bytes, 7, 1);\n var high = (b7 & 0xF8) >> 3;\n data.CO2 = high * 256 + low;\n data.powerSourceStatus = b7 & 0x07;\n data.lux = parseBytesToInt(bytes, 8, 2);\n return data;\n}\n\nfunction handleResponse(bytes, data) {\n var commands = [];\n foreach(b : bytes) {\n commands.add(bytesToHex([b]));\n }\n var resp = commands.subList(0, commands.size() - 8);\n var i = 0;\n while (i < resp.size()) {\n var cmd = resp.get(i);\n if (cmd == '04') {\n data.deviceVersions = {\n hardware: parseInt(resp.get(i+1), 16),\n software: parseInt(resp.get(i+2), 16)\n };\n i += 3;\n } else if (cmd == '12') {\n data.keepAliveTime = parseInt(resp.get(i+1), 16);\n i += 2;\n } else if (cmd == '14') {\n data.childLock = (parseInt(resp.get(i+1), 16) == 1);\n i += 2;\n } else if (cmd == '19') {\n data.joinRetryPeriod = parseInt(resp.get(i+1), 16) * 5 / 60;\n i += 2;\n } else if (cmd == '1b') {\n data.uplinkType = parseInt(resp.get(i+1), 16);\n i += 2;\n } else if (cmd == '1f') {\n var gm = parseInt(resp.get(i+1) + resp.get(i+2), 16);\n var mb = parseInt(resp.get(i+3) + resp.get(i+4), 16);\n data.boundaryLevels = { good_medium: gm, medium_bad: mb };\n i += 5;\n } else if (cmd == '1d') {\n var dka = 5;\n var wdpC = (resp.get(i+1) == '00') ? false : (parseInt(resp.get(i+1), 16) * dka + 7);\n var wdpUc= (resp.get(i+2) == '00') ? false : parseInt(resp.get(i+2), 16);\n data.watchDogParams = { wdpC: wdpC, wdpUc: wdpUc };\n i += 3;\n } else if (cmd == '21') {\n data.autoZeroValue = parseInt(resp.get(i+1) + resp.get(i+2), 16);\n i += 3;\n } else if (cmd == '25') {\n data.measurementPeriod = {\n good_zone: parseInt(resp.get(i+1), 16),\n medium_zone: parseInt(resp.get(i+2), 16),\n bad_zone: parseInt(resp.get(i+3), 16)\n };\n i += 4;\n } else if (cmd == '2b') {\n data.autoZeroPeriod = parseInt(resp.get(i+1), 16);\n i += 2;\n } else if (cmd == '34') {\n data.displayRefreshPeriod = parseInt(resp.get(i+1), 16);\n i += 2;\n } else if (cmd == '41') {\n data.currentTemperatureVisibility = parseInt(resp.get(i+1), 16);\n i += 2;\n } else if (cmd == '43') {\n data.humidityVisibility = parseInt(resp.get(i+1), 16);\n i += 2;\n } else if (cmd == '45') {\n data.lightIntensityVisibility = parseInt(resp.get(i+1), 16);\n i += 2;\n } else if (cmd == '80') {\n data.measurementBlindTime = parseInt(resp.get(i+1), 16);\n i += 2;\n } else {\n i += 1;\n }\n }\n return data;\n}\n\nvar result = decodePayload(payload);\nreturn result;", "encoder": null, "tbelEncoder": null, "updateOnlyKeys": [ "eui", "devAddr", "fPort", "bandwidth", "spreadingFactor", "codeRate", "frequency", "tenantId" ], "type": "DEVICE", "name": "CO2 Display Lite $eui", "profile": "$applicationId", "label": "$deviceId", "customer": "", "group": "", "telemetry": null, "attributes": [ "eui", "devAddr", "fPort", "bandwidth", "codeRate", "frequency", "tenantId", "applicationId", "spreadingFactor", "deviceId", "joinEui", "netId", "clusterId", "clusterAddress" ] }, "additionalInfo": { "description": "" }, "edgeTemplate": false, "converterVersion": 2 }