[{"id":"a66894fa.ff2ef8","type":"tab","label":"Sensors de Qualitat de l'Aire","disabled":false,"info":""},{"id":"f5dc9755.82df4","type":"function","z":"a66894fa.ff2ef8","name":"DecentLab DL-LP8P","func":"/* Device: https://www.decentlab.com/products/co2-temperature-humidity-and-barometric-pressure-sensor-for-lorawan */\n/* Decoder: https://raw.githubusercontent.com/decentlab/decentlab-decoders/master/DL-LP8P/DL-LP8P.js */\n\nvar decentlab_decoder = {\n PROTOCOL_VERSION: 2,\n SENSORS: [\n {length: 2,\n values: [{name: 'air_temperature',\n displayName: 'Air temperature',\n convert: function (x) { return 175.72 * x[0] / 65536 - 46.85; },\n unit: '°C'},\n {name: 'air_humidity',\n displayName: 'Air humidity',\n convert: function (x) { return 125 * x[1] / 65536 - 6; },\n unit: '%'}]},\n {length: 2,\n values: [{name: 'barometer_temperature',\n displayName: 'Barometer temperature',\n convert: function (x) { return (x[0] - 5000) / 100; },\n unit: '°C'},\n {name: 'barometric_pressure',\n displayName: 'Barometric pressure',\n convert: function (x) { return x[1] * 2; },\n unit: 'Pa'}]},\n {length: 8,\n values: [{name: 'co2_concentration',\n displayName: 'CO2 concentration',\n convert: function (x) { return x[0] - 32768; },\n unit: 'ppm'},\n {name: 'co2_concentration_lpf',\n displayName: 'CO2 concentration LPF',\n convert: function (x) { return x[1] - 32768; },\n unit: 'ppm'},\n {name: 'co2_sensor_temperature',\n displayName: 'CO2 sensor temperature',\n convert: function (x) { return (x[2] - 32768) / 100; },\n unit: '°C'},\n {name: 'capacitor_voltage_1',\n displayName: 'Capacitor voltage 1',\n convert: function (x) { return x[3] / 1000; },\n unit: 'V'},\n {name: 'capacitor_voltage_2',\n displayName: 'Capacitor voltage 2',\n convert: function (x) { return x[4] / 1000; },\n unit: 'V'},\n {name: 'co2_sensor_status',\n displayName: 'CO2 sensor status',\n convert: function (x) { return x[5]; }},\n {name: 'raw_ir_reading',\n displayName: 'Raw IR reading',\n convert: function (x) { return x[6]; }},\n {name: 'raw_ir_reading_lpf',\n displayName: 'Raw IR reading LPF',\n convert: function (x) { return x[7]; }}]},\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\n read_int: function (bytes, pos) {\n return (bytes[pos] << 8) + bytes[pos + 1];\n },\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\n var version = bytes[0];\n if (version != this.PROTOCOL_VERSION) {\n return {error: \"protocol version \" + version + \" doesn't match v2\"};\n }\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\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\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\nvar fields = decentlab_decoder.decode(msg.payload);\nvar output = {};\nObject.keys(fields).forEach(function(key) {\n output[key] = fields[key].value;\n})\nmsg.payload = output;\nreturn msg;\n","outputs":1,"noerr":0,"x":470,"y":560,"wires":[["46cfeaad.bb372c"]]},{"id":"e3480aa7.e0a33","type":"inject","z":"a66894fa.ff2ef8","name":"Mock DecentLab DL-LP8P","topic":"v3/${nom_ens}-co2-pm@ttn/devices/1951/up","payload":"{\"end_device_ids\":{\"device_id\":\"1951\",\"application_ids\":{\"application_id\":\"${nom_ens}-co2-pm\"},\"dev_eui\":\"70B3D57BA000079F\",\"join_eui\":\"70B3D57ED00006B2\",\"dev_addr\":\"260B37C7\"},\"correlation_ids\":[\"as:up:01G18N1FKKF072C8A901J29W39\",\"gs:conn:01G0Y5RQARCZ929QZAPJG9VQAX\",\"gs:up:host:01G0Y5RQX4T3CC2TMCPXKETQ7W\",\"gs:uplink:01G18N1FD2S8X4H4C95B1YPCGP\",\"ns:uplink:01G18N1FD390VX2GKF655WP841\",\"rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01G18N1FD37XAYDZ7MP8F8GHNQ\",\"rpc:/ttn.lorawan.v3.NsAs/HandleUplink:01G18N1FKK1FJMYRTN9TKYG6QH\"],\"received_at\":\"2022-04-22T12:48:07.795983071Z\",\"uplink_message\":{\"session_key_id\":\"AYA8t21TD27euQeIRyZRdA==\",\"f_port\":1,\"f_cnt\":576,\"frm_payload\":\"AgefAA9ir3yLG7bAzIGggZ6H9AvSC6wAAJrkmvULGA==\",\"rx_metadata\":[{\"gateway_ids\":{\"gateway_id\":\"ttncat-gw17-${nom_ens}-radio\",\"eui\":\"FCC23DFFFE0B6AF9\"},\"time\":\"2022-04-22T12:48:07.558240Z\",\"timestamp\":759654643,\"rssi\":-105,\"channel_rssi\":-105,\"snr\":7.2,\"location\":{\"latitude\":41.609244,\"longitude\":2.540364,\"altitude\":150,\"source\":\"SOURCE_REGISTRY\"},\"uplink_token\":\"${token_id}\",\"channel_index\":3}],\"settings\":{\"data_rate\":{\"lora\":{\"bandwidth\":125000,\"spreading_factor\":7}},\"coding_rate\":\"4/5\",\"frequency\":\"867100000\",\"timestamp\":759654643,\"time\":\"2022-04-22T12:48:07.558240Z\"},\"received_at\":\"2022-04-22T12:48:07.587856442Z\",\"consumed_airtime\":\"0.092416s\",\"network_ids\":{\"net_id\":\"000013\",\"tenant_id\":\"ttn\",\"cluster_id\":\"ttn-eu1\"}}}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":380,"wires":[["8bef343a.fc1f08"]]},{"id":"d64a9d96.c2bbb","type":"change","z":"a66894fa.ff2ef8","name":"raw","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.uplink_message.frm_payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":280,"wires":[["d1d32739.5957b"]]},{"id":"d1d32739.5957b","type":"base64","z":"a66894fa.ff2ef8","name":"","action":"","property":"payload","x":670,"y":280,"wires":[["8e289be3.db30a8"]]},{"id":"6bf0af12.4c2548","type":"publish","z":"a66894fa.ff2ef8","name":"${tenant_id}@decentlab (pre)","server":"814cdbb0.387ee","providerId":"${tenant_id}@decentlab","dataType":"data","identifier":"","obsValue":"","urlRaw":"/data/${tenant_id}@decentlab/","x":480,"y":1020,"wires":[]},{"id":"1087c1d.2b85fbe","type":"mqtt in","z":"a66894fa.ff2ef8","name":"${nom_ens}-co2-pm","topic":"v3/${nom_ens}-co2-pm@ttn/devices/+/up","qos":"2","datatype":"json","broker":"5b660b4f.33275c","x":160,"y":280,"wires":[["8bef343a.fc1f08"]]},{"id":"5e7377ed.3708f8","type":"inject","z":"a66894fa.ff2ef8","name":"","topic":"","payload":"{\"1951\":{\"CO2_frontalera_ajuntament\":\"co2_concentration\",\"CO2_oav_ajuntament_T\":\"air_temperature\",\"CO2_oav_ajuntament_HR\":\"air_humidity\"}}","payloadType":"json","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":130,"y":140,"wires":[["edd13908.9f749"]]},{"id":"332364ec.25324c","type":"change","z":"a66894fa.ff2ef8","name":"save","rules":[{"t":"set","p":"map","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":140,"wires":[[]]},{"id":"f41d6c6e.55fdf","type":"function","z":"a66894fa.ff2ef8","name":"map & process","func":"var map = flow.get(\"map\");\n\nif (msg.device_id in map) {\n \n var output = [];\n Object.keys(map[msg.device_id]['sensors']).forEach(function(key) {\n var element = map[msg.device_id]['sensors'][key];\n var field = element['field'];\n var decimals = element['decimals'] || 0;\n var multiplier = element['multiplier'] || 1.0;\n var value = (msg.payload[key] * multiplier).toFixed(decimals);\n output.push({\n 'key': key,\n 'field': field,\n 'value': value\n });\n })\n msg.payload = output;\n return msg;\n}\n\nreturn null;","outputs":1,"noerr":0,"x":220,"y":800,"wires":[["2ad24542.cc0232"]]},{"id":"edd13908.9f749","type":"function","z":"a66894fa.ff2ef8","name":"config","func":"var config = {\n \n \"1951\": {\n \"type\": \"DecentLab DL-LP8P\",\n \"provider\": \"${tenant_id}@decentlab\",\n \"sensors\": {\n \"co2_concentration\": {\n \"field\": \"CO2_frontalera_ajuntament\"\n },\n \"air_temperature\": {\n \"field\": \"CO2_oav_ajuntament_T\",\n \"decimals\": 2\n },\n \"air_humidity\": {\n \"field\": \"CO2_oav_ajuntament_HR\",\n \"decimals\": 1\n }\n }\n },\n\n \"8296\": {\n \"type\": \"DecentLab DL-PM\",\n \"provider\": \"${tenant_id}@decentlab\",\n \"sensors\": {\n \"typical_particle_size\": {\n \"field\": \"PM_frontalera_ajuntament_tipic\"\n },\n \"pm1_0_mass_concentration\": {\n \"field\": \"PM_1_mass_frontalera_ajuntament\"\n },\n \"pm2_5_mass_concentration\": {\n \"field\": \"PM_2_5_mass_frontalera_ajuntament\"\n },\n \"pm4_mass_concentration\": {\n \"field\": \"PM_4_mass_frontalera_ajuntament\"\n },\n \"pm10_mass_concentration\": {\n \"field\": \"PM_10_mass_frontalera_ajuntament\"\n },\n \"pm0_5_number_concentration\": {\n \"field\": \"PM_0_5_n_frontalera_ajuntament\"\n },\n \"pm1_0_number_concentration\": {\n \"field\": \"PM_1_n_frontalera_ajuntament\"\n },\n \"pm2_5_number_concentration\": {\n \"field\": \"PM_2_5_n_frontalera_ajuntament\"\n },\n \"pm4_number_concentration\": {\n \"field\": \"PM_4_n_frontalera_ajuntament\"\n },\n \"pm10_number_concentration\": {\n \"field\": \"PM_10_n_frontalera_ajuntament\"\n },\n \"air_temperature\": {\n \"field\": \"PM_frontalera_ajuntament_T\",\n \"decimals\": 2\n },\n \"air_humidity\": {\n \"field\": \"PM_frontalera_ajuntament_HR\",\n \"decimals\": 1\n },\n \"barometric_pressure\": {\n \"field\": \"PM_frontalera_ajuntament_P\"\n }\n }\n },\n\n \"eui-a8404151c182e751\": {\n \"type\": \"Dragino LAQ4\",\n \"provider\": \"${tenant_id}@dragino\",\n \"sensors\": {\n \"CO2_ppm\": {\n \"field\": \"CO2_oav_ajuntament\"\n },\n \"TempC_SHT\": {\n \"field\": \"CO2_oav_ajuntament_T\",\n \"decimals\": 1\n },\n \"Hum_SHT\": {\n \"field\": \"CO2_oav_ajuntament_HR\",\n \"decimals\": 1\n },\n \"TVOC_ppb\": {\n \"field\": \"CO2_oav_ajuntament_VOC\"\n },\n \"Bat_V\": {\n \"field\": \"CO2_oav_ajuntament_Bat\",\n \"decimals\": 3\n }\n }\n },\n \n \"eui-a8404184a182e74f\": {\n \"type\": \"Dragino LAQ4\",\n \"provider\": \"${tenant_id}@dragino\",\n \"sensors\": {\n \"CO2_ppm\": {\n \"field\": \"CO2_sala_municipal_ajuntament\"\n },\n \"TempC_SHT\": {\n \"field\": \"CO2_sala_municipal_ajuntament_T\",\n \"decimals\": 1\n },\n \"Hum_SHT\": {\n \"field\": \"CO2_sala_municipal_ajuntament_HR\",\n \"decimals\": 1\n },\n \"TVOC_ppb\": {\n \"field\": \"CO2_sala_municipal_ajuntament_VOC\"\n },\n \"Bat_V\": {\n \"field\": \"CO2_sala_municipal_ajuntament_Bat\",\n \"decimals\": 3\n }\n }\n },\n \n \"eui-a84041c68182e74e\": {\n \"type\": \"Dragino LAQ4\",\n \"provider\": \"${tenant_id}@dragino\",\n \"sensors\": {\n \"CO2_ppm\": {\n \"field\": \"CO2_mercat_municipal\"\n },\n \"TempC_SHT\": {\n \"field\": \"CO2_mercat_municipal_T\",\n \"decimals\": 1\n },\n \"Hum_SHT\": {\n \"field\": \"CO2_mercat_municipal_HR\",\n \"decimals\": 1\n },\n \"TVOC_ppb\": {\n \"field\": \"CO2_mercat_municipal_VOC\"\n },\n \"Bat_V\": {\n \"field\": \"CO2_mercat_municipal_Bat\",\n \"decimals\": 3\n }\n }\n },\n\n \"eui-a84041fb5182eb21\": {\n \"type\": \"Dragino LAQ4\",\n \"provider\": \"${tenant_id}@dragino\",\n \"sensors\": {\n \"CO2_ppm\": {\n \"field\": \"CO2_pavello_can_zariquei\"\n },\n \"TempC_SHT\": {\n \"field\": \"CO2_pavello_can_zariquei_T\",\n \"decimals\": 1\n },\n \"Hum_SHT\": {\n \"field\": \"CO2_pavello_can_zariquei_HR\",\n \"decimals\": 1\n },\n \"TVOC_ppb\": {\n \"field\": \"CO2_pavello_can_zariquei_VOC\"\n },\n \"Bat_V\": {\n \"field\": \"CO2_pavello_can_zariquei_Bat\",\n \"decimals\": 3\n }\n }\n },\n \n \"eui-a84041893182e749\": {\n \"type\": \"Dragino LAQ4\",\n \"provider\": \"${tenant_id}@dragino\",\n \"sensors\": {\n \"CO2_ppm\": {\n \"field\": \"CO2_sala_exposicions_municipal\"\n },\n \"TempC_SHT\": {\n \"field\": \"CO2_sala_exposicions_municipal_T\",\n \"decimals\": 1\n },\n \"Hum_SHT\": {\n \"field\": \"CO2_sala_exposicions_municipal_HR\",\n \"decimals\": 1\n },\n \"TVOC_ppb\": {\n \"field\": \"CO2_sala_exposicions_municipal_VOC\"\n },\n \"Bat_V\": {\n \"field\": \"CO2_sala_exposicions_municipal_Bat\",\n \"decimals\": 3\n }\n }\n }\n};\n\nreturn {'payload': config};","outputs":1,"noerr":0,"x":270,"y":140,"wires":[["332364ec.25324c"]]},{"id":"2ad24542.cc0232","type":"template","z":"a66894fa.ff2ef8","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\"sensors\":[\n {{ #payload }}\n {\n \"sensor\":\"{{ field }}\",\n \"observations\":[\n {\"value\": {{ value }}}\n ]\n },\n {{ /payload }}\n]}\n","output":"str","x":400,"y":800,"wires":[["e332164.f5e6ae8"]]},{"id":"e332164.f5e6ae8","type":"function","z":"a66894fa.ff2ef8","name":"sanityze","func":"msg.payload = msg.payload.replace(/},\\n]/,\"}\\n]\");\nreturn msg;","outputs":1,"noerr":0,"x":560,"y":800,"wires":[["6b3e1336.e7b894"]]},{"id":"8bef343a.fc1f08","type":"function","z":"a66894fa.ff2ef8","name":"filter","func":"var map = flow.get(\"map\");\nvar device_id = msg.payload.end_device_ids.device_id;\nif (device_id in map) {\n msg.device_id = device_id;\n msg.type = map[device_id]['type'];\n msg.provider = map[device_id]['provider'];\n return msg;\n}\nreturn null;","outputs":1,"noerr":0,"x":390,"y":280,"wires":[["d64a9d96.c2bbb"]]},{"id":"99c4ec88.9ebed8","type":"switch","z":"a66894fa.ff2ef8","name":"check sensor type","property":"type","propertyType":"msg","rules":[{"t":"eq","v":"DecentLab DL-LP8P","vt":"str"},{"t":"eq","v":"DecentLab DL-PM","vt":"str"},{"t":"eq","v":"Dragino LAQ4","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":230,"y":600,"wires":[["f5dc9755.82df4"],["46ac54d4.bd97d4"],["25221811.27004"]]},{"id":"3958b874.5b4ae8","type":"inject","z":"a66894fa.ff2ef8","name":"Mock DecentLab DL-PM","topic":"v3/${nom_ens}-co2-pm@ttn/devices/1951/up","payload":"{\"end_device_ids\":{\"device_id\":\"8296\",\"application_ids\":{\"application_id\":\"${nom_ens}-co2-pm\"},\"dev_eui\":\"70B3D57BA0002068\",\"join_eui\":\"70B3D57ED00006B2\",\"dev_addr\":\"260B688E\"},\"correlation_ids\":[\"as:up:01G19G1AERX71Z2G5K9W4A87FK\",\"gs:conn:01G0Y5RQARCZ929QZAPJG9VQAX\",\"gs:up:host:01G0Y5RQX4T3CC2TMCPXKETQ7W\",\"gs:uplink:01G19G1A82Q5RW27XHQ75WD5F7\",\"ns:uplink:01G19G1A86V8EH6YGM1Y08Q0FQ\",\"rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01G19G1A86TSTB2ZS6KBWSG20M\",\"rpc:/ttn.lorawan.v3.NsAs/HandleUplink:01G19G1AER42RB7MVQ3MA3TPA0\"],\"received_at\":\"2022-04-22T20:39:54.073063233Z\",\"uplink_message\":{\"session_key_id\":\"AYA7nSmuQCUY/IX5lR8eLA==\",\"f_port\":1,\"f_cnt\":654,\"frm_payload\":\"AiBoAA8LdQAqAC0ALQAtAfwBMAFXAVgBWAFYXPCBAMD2\",\"rx_metadata\":[{\"gateway_ids\":{\"gateway_id\":\"ttncat-gw17-${nom_ens}-radio\",\"eui\":\"FCC23DFFFE0B6AF9\"},\"time\":\"2022-04-22T20:39:53.821028Z\",\"timestamp\":3296090947,\"rssi\":-97,\"channel_rssi\":-97,\"snr\":9,\"location\":{\"latitude\":41.609244,\"longitude\":2.540364,\"altitude\":150,\"source\":\"SOURCE_REGISTRY\"},\"uplink_token\":\"${token_id}\",\"channel_index\":1}],\"settings\":{\"data_rate\":{\"lora\":{\"bandwidth\":125000,\"spreading_factor\":7}},\"coding_rate\":\"4/5\",\"frequency\":\"868300000\",\"timestamp\":3296090947,\"time\":\"2022-04-22T20:39:53.821028Z\"},\"received_at\":\"2022-04-22T20:39:53.862613473Z\",\"consumed_airtime\":\"0.092416s\",\"network_ids\":{\"net_id\":\"000013\",\"tenant_id\":\"ttn\",\"cluster_id\":\"ttn-eu1\"}}}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":340,"wires":[["8bef343a.fc1f08"]]},{"id":"46ac54d4.bd97d4","type":"function","z":"a66894fa.ff2ef8","name":"DecentLab DL-PM","func":"/* Sensor: https://www.decentlab.com/products/particulate-matter-temperature-humidity-and-barometric-pressure-sensor-for-lorawan */\n/* Decoder: https://github.com/decentlab/decentlab-decoders/blob/master/DL-PM/DL-PM.js */\n\nvar decentlab_decoder = {\n PROTOCOL_VERSION: 2,\n SENSORS: [\n {length: 1,\n values: [{name: 'battery_voltage',\n displayName: 'Battery voltage',\n convert: function (x) { return x[0] / 1000; },\n unit: 'V'}]},\n {length: 10,\n values: [{name: 'pm1_0_mass_concentration',\n displayName: 'PM1.0 mass concentration',\n convert: function (x) { return x[0] / 10; },\n unit: 'µg⋅m⁻³'},\n {name: 'pm2_5_mass_concentration',\n displayName: 'PM2.5 mass concentration',\n convert: function (x) { return x[1] / 10; },\n unit: 'µg⋅m⁻³'},\n {name: 'pm4_mass_concentration',\n displayName: 'PM4 mass concentration',\n convert: function (x) { return x[2] / 10; },\n unit: 'µg⋅m⁻³'},\n {name: 'pm10_mass_concentration',\n displayName: 'PM10 mass concentration',\n convert: function (x) { return x[3] / 10; },\n unit: 'µg⋅m⁻³'},\n {name: 'typical_particle_size',\n displayName: 'Typical particle size',\n convert: function (x) { return x[4]; },\n unit: 'nm'},\n {name: 'pm0_5_number_concentration',\n displayName: 'PM0.5 number concentration',\n convert: function (x) { return x[5] / 10; },\n unit: '1⋅cm⁻³'},\n {name: 'pm1_0_number_concentration',\n displayName: 'PM1.0 number concentration',\n convert: function (x) { return x[6] / 10; },\n unit: '1⋅cm⁻³'},\n {name: 'pm2_5_number_concentration',\n displayName: 'PM2.5 number concentration',\n convert: function (x) { return x[7] / 10; },\n unit: '1⋅cm⁻³'},\n {name: 'pm4_number_concentration',\n displayName: 'PM4 number concentration',\n convert: function (x) { return x[8] / 10; },\n unit: '1⋅cm⁻³'},\n {name: 'pm10_number_concentration',\n displayName: 'PM10 number concentration',\n convert: function (x) { return x[9] / 10; },\n unit: '1⋅cm⁻³'}]},\n {length: 2,\n values: [{name: 'air_temperature',\n displayName: 'Air temperature',\n convert: function (x) { return 175.72 * x[0] / 65536 - 46.85; },\n unit: '°C'},\n {name: 'air_humidity',\n displayName: 'Air humidity',\n convert: function (x) { return 125 * x[1] / 65536 - 6; },\n unit: '%'}]},\n {length: 1,\n values: [{name: 'barometric_pressure',\n displayName: 'Barometric pressure',\n convert: function (x) { return x[0] * 2; },\n unit: 'Pa'}]}\n ],\n\n read_int: function (bytes, pos) {\n return (bytes[pos] << 8) + bytes[pos + 1];\n },\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\n var version = bytes[0];\n if (version != this.PROTOCOL_VERSION) {\n return {error: \"protocol version \" + version + \" doesn't match v2\"};\n }\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\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\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\nvar fields = decentlab_decoder.decode(msg.payload);\nvar output = {};\nObject.keys(fields).forEach(function(key) {\n output[key] = fields[key].value;\n})\nmsg.payload = output;\nreturn msg;\n","outputs":1,"noerr":0,"x":460,"y":600,"wires":[["46cfeaad.bb372c"]]},{"id":"ff295494.0b273","type":"comment","z":"a66894fa.ff2ef8","name":"Configuració","info":"","x":130,"y":80,"wires":[]},{"id":"1d854fd0.b5a8f","type":"comment","z":"a66894fa.ff2ef8","name":"Entrada de dades","info":"","x":140,"y":220,"wires":[]},{"id":"c260684b.cf1948","type":"comment","z":"a66894fa.ff2ef8","name":"Decodificació","info":"","x":130,"y":500,"wires":[]},{"id":"db047611.bb60e8","type":"comment","z":"a66894fa.ff2ef8","name":"Mapeig","info":"","x":110,"y":740,"wires":[]},{"id":"8e289be3.db30a8","type":"link out","z":"a66894fa.ff2ef8","name":"data_output","links":["3319b786.99bd88"],"x":775,"y":280,"wires":[]},{"id":"3319b786.99bd88","type":"link in","z":"a66894fa.ff2ef8","name":"decoder_input","links":["8e289be3.db30a8"],"x":75,"y":600,"wires":[["99c4ec88.9ebed8","2af88822.c65638"]]},{"id":"46cfeaad.bb372c","type":"link out","z":"a66894fa.ff2ef8","name":"decoder_output","links":["8195d7c8.30423"],"x":635,"y":600,"wires":[]},{"id":"8195d7c8.30423","type":"link in","z":"a66894fa.ff2ef8","name":"mapping_input","links":["46cfeaad.bb372c"],"x":75,"y":800,"wires":[["f41d6c6e.55fdf","aa49fcb6.b3484"]]},{"id":"6b3e1336.e7b894","type":"json","z":"a66894fa.ff2ef8","name":"","property":"payload","action":"","pretty":false,"x":710,"y":800,"wires":[["c6baa2e4.8e33f"]]},{"id":"b79be256.74c27","type":"comment","z":"a66894fa.ff2ef8","name":"Ingesta","info":"","x":110,"y":960,"wires":[]},{"id":"c6baa2e4.8e33f","type":"link out","z":"a66894fa.ff2ef8","name":"mapping_output","links":["1190da7.c003626"],"x":815,"y":800,"wires":[]},{"id":"1190da7.c003626","type":"link in","z":"a66894fa.ff2ef8","name":"sentilo_input","links":["c6baa2e4.8e33f"],"x":75,"y":1060,"wires":[["d4700494.8d2868","7782d3a8.533464"]]},{"id":"d4700494.8d2868","type":"switch","z":"a66894fa.ff2ef8","name":"check provider","property":"provider","propertyType":"msg","rules":[{"t":"eq","v":"${tenant_id}@decentlab","vt":"str"},{"t":"eq","v":"${tenant_id}@dragino","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":220,"y":1060,"wires":[["6bf0af12.4c2548"],["a6c8175c.683c5"]]},{"id":"a6c8175c.683c5","type":"publish","z":"a66894fa.ff2ef8","name":"${tenant_id}@dragino (pre)","server":"814cdbb0.387ee","providerId":"${tenant_id}@dragino","dataType":"data","identifier":"","obsValue":"","urlRaw":"/data/${tenant_id}@dragino","x":470,"y":1100,"wires":[]},{"id":"afdc743e.2ebb4","type":"inject","z":"a66894fa.ff2ef8","name":"Mock Dragino LAQ4","topic":"v3/${nom_ens}-co2-pm@ttn/devices/eui-a8404151c182e751/up","payload":"{\"end_device_ids\":{\"device_id\":\"eui-a8404151c182e751\",\"application_ids\":{\"application_id\":\"${nom_ens}-co2-pm\"},\"dev_eui\":\"A8404151C182E751\",\"join_eui\":\"A000000000000100\",\"dev_addr\":\"260B6547\"},\"correlation_ids\":[\"as:up:01G19JFVK47RHW1X409MANAKSV\",\"gs:conn:01G0Y5RQARCZ929QZAPJG9VQAX\",\"gs:up:host:01G0Y5RQX4T3CC2TMCPXKETQ7W\",\"gs:uplink:01G19JFVCJHQ4395F1VCS1DVC8\",\"ns:uplink:01G19JFVCK6YB14MT9658CEC5J\",\"rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01G19JFVCKEGC1GSR4HTZP7TVQ\",\"rpc:/ttn.lorawan.v3.NsAs/HandleUplink:01G19JFVK4K4ZVCX6QA4AW4W2P\"],\"received_at\":\"2022-04-22T21:22:47.524893878Z\",\"uplink_message\":{\"session_key_id\":\"AXztwBJGOrIh4gHIsRuMig==\",\"f_port\":2,\"f_cnt\":12155,\"frm_payload\":\"DP4EAAABkADKAhI=\",\"decoded_payload\":{\"Alarm_status\":\"FALSE\",\"Bat_V\":3.326,\"CO2_ppm\":400,\"Hum_SHT\":53,\"TVOC_ppb\":0,\"TempC_SHT\":20.2,\"Work_mode\":\"CO2\"},\"rx_metadata\":[{\"gateway_ids\":{\"gateway_id\":\"ttncat-gw17-${nom_ens}-radio\",\"eui\":\"FCC23DFFFE0B6AF9\"},\"time\":\"2022-04-22T21:22:47.288236Z\",\"timestamp\":1574596899,\"rssi\":-111,\"channel_rssi\":-111,\"snr\":0.5,\"location\":{\"latitude\":41.609244,\"longitude\":2.540364,\"altitude\":150,\"source\":\"SOURCE_REGISTRY\"},\"uplink_token\":\"${token_id}\",\"channel_index\":1}],\"settings\":{\"data_rate\":{\"lora\":{\"bandwidth\":125000,\"spreading_factor\":7}},\"coding_rate\":\"4/5\",\"frequency\":\"868300000\",\"timestamp\":1574596899,\"time\":\"2022-04-22T21:22:47.288236Z\"},\"received_at\":\"2022-04-22T21:22:47.315606163Z\",\"consumed_airtime\":\"0.061696s\",\"network_ids\":{\"net_id\":\"000013\",\"tenant_id\":\"ttn\",\"cluster_id\":\"ttn-eu1\"}}}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":420,"wires":[["8bef343a.fc1f08"]]},{"id":"25221811.27004","type":"function","z":"a66894fa.ff2ef8","name":"Dragino LAQ4","func":"/* Sensor: https://www.dragino.com/products/lora-lorawan-end-node/item/174-laq4.html */\n/* Decoder: https://www.dragino.com/downloads/downloads/LoRa_End_Node/LAQ4/Decoder/LAQ4_Decoder_TTN */\n\nfunction Decoder(bytes, port) {\n var mode=(bytes[2] & 0x7C)>>2;\n var decode = {};\n decode.Bat_V=(bytes[0]<<8 | bytes[1])/1000; \n if(mode==1)\n {\n decode.Work_mode=\"CO2\";\n decode.Alarm_status=(bytes[2] & 0x01)? \"TRUE\":\"FALSE\"; \n decode.TVOC_ppb= bytes[3]<<8 | bytes[4]; \n decode.CO2_ppm= bytes[5]<<8 | bytes[6];\n decode.TempC_SHT=parseFloat(((bytes[7]<<24>>16 | bytes[8])/10).toFixed(2));\n decode.Hum_SHT=parseFloat(((bytes[9]<<8 | bytes[10])/10).toFixed(1)); \n }\n else if(mode==31)\n {\n decode.Work_mode=\"ALARM\";\n decode.SHTEMPMIN= bytes[3]<<24>>24;\n decode.SHTEMPMAX= bytes[4]<<24>>24; \n decode.SHTHUMMIN= bytes[5];\n decode.SHTHUMMAX= bytes[6]; \n decode.CO2MIN= bytes[7]<<8 | bytes[8]; \n decode.CO2MAX= bytes[9]<<8 | bytes[10]; \n }\n \n if(bytes.length==11)\n {\n return decode;\n }\n}\n\nmsg.payload = Decoder(msg.payload, 0);\nreturn msg;\n","outputs":1,"noerr":0,"x":450,"y":640,"wires":[["46cfeaad.bb372c"]]},{"id":"7782d3a8.533464","type":"debug","z":"a66894fa.ff2ef8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":190,"y":1120,"wires":[]},{"id":"aa49fcb6.b3484","type":"debug","z":"a66894fa.ff2ef8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":190,"y":860,"wires":[]},{"id":"2af88822.c65638","type":"debug","z":"a66894fa.ff2ef8","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":190,"y":660,"wires":[]},{"id":"814cdbb0.387ee","type":"server","z":"","alias":"pre-sentilo-${nom_ens}","host":"pre-api-sentilo.diba.cat"},{"id":"5b660b4f.33275c","type":"mqtt-broker","z":"","name":"${nom_ens}-co2-pm@ttn","broker":"eu1.cloud.thethings.network","port":"8883","tls":"","clientid":"","usetls":true,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]