diff --git a/milesight-iot-am307l/plugin.json b/milesight-iot-am307l/plugin.json index a2f9d3e3..155672f4 100644 --- a/milesight-iot-am307l/plugin.json +++ b/milesight-iot-am307l/plugin.json @@ -1,1105 +1,1109 @@ { - "name": "milesight_iot_am307l", - "version": "1.0.0", - "description": "Milesight am307l collects various indoor ambience conditions through 7 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC. It features a tri-c", - "author": "Thinger.io", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/thinger-io/plugins.git", - "directory": "milesight-iot-am307l" - }, - "metadata": { - "name": "Milesight-Iot AM307L", - "description": "Milesight am307l collects various indoor ambience conditions through 7 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC. It features a tri-c", - "image": "assets/am307l.png", - "category": "devices", - "vendor": "milesight-iot" - }, - "resources": { - "products": [ - { - "description": "Milesight am307l collects various indoor ambience conditions through 7 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC. It features a tri-c", - "enabled": true, + "name": "milesight-iot-am307l", + "version": "1.0.0", + "description": "Milesight am307l collects various indoor ambience conditions through 7 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC.", + "author": "Thinger.io", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/thinger-io/plugins.git", + "directory": "milesight-iot-am307l" + }, + "metadata": { "name": "Milesight-Iot AM307L", - "product": "milesight_iot_am307l", - "profile": { - "api": { - "downlink": { - "enabled": true, - "handle_connectivity": false, - "request": { - "data": { - "path": "/downlink", - "payload": "{\r\n \"data\" : \"{{payload.data=\"\"}}\",\r\n \"port\" : {{payload.port=2}},\r\n \"priority\": {{payload.priority=3}},\r\n \"confirmed\" : {{payload.confirmed=false}},\r\n \"uplink\" : {{property.uplink}} \r\n}", - "payload_function": "", - "payload_type": "", - "plugin": "{{property.uplink.source}}", - "target": "plugin_endpoint" - } - } - }, - "uplink": { - "enabled": true, - "handle_connectivity": true, - "request": { - "data": { - "payload": "{{payload}}", - "payload_function": "", - "payload_type": "source_payload", - "resource_stream": "uplink", - "target": "resource_stream" - } - } - } - }, - "autoprovisions": { - "device_autoprovisioning": { - "config": { - "mode": "pattern", - "pattern": "am307l_.*" - }, - "enabled": true - } - }, - "buckets": { - "milesight_am307l_data": { - "backend": "mongodb", - "data": { - "payload": "{{payload}}", - "payload_function": "", - "resource_stream": "uplink_decoded", - "target": "resource_stream" - }, - "enabled": true, - "retention": { - "period": 3, - "unit": "months" - }, - "tags": [] - } - }, - "code": { - "code": "function decodeThingerUplink(thingerData) {\n // 0. If data has already been decoded, we will return it\n if (thingerData.decodedPayload) return thingerData.decodedPayload;\n \n // 1. Extract and Validate Input\n // We need 'payload' (hex string) and 'fPort' (integer)\n const hexPayload = thingerData.payload || \"\";\n const port = thingerData.fPort || 1;\n\n // 2. Convert Hex String to Byte Array\n const bytes = [];\n for (let i = 0; i < hexPayload.length; i += 2) {\n bytes.push(parseInt(hexPayload.substr(i, 2), 16));\n }\n\n // 3. Dynamic Function Detection and Execution\n \n // CASE A: (The Things Stack v3)\n if (typeof decodeUplink === 'function') {\n try {\n const input = {\n bytes: bytes,\n fPort: port\n };\n var result = decodeUplink(input);\n \n if (result.data) return result.data;\n\n return result; \n } catch (e) {\n console.error(\"Error inside decodeUplink:\", e);\n throw e;\n }\n }\n\n // CASE B: Legacy TTN (v2)\n else if (typeof Decoder === 'function') {\n try {\n return Decoder(bytes, port);\n } catch (e) {\n console.error(\"Error inside Decoder:\", e);\n throw e;\n }\n }\n\n // CASE C: No decoder found\n else {\n throw new Error(\"No compatible TTN decoder function (decodeUplink or Decoder) found in scope.\");\n }\n}\n\n\n// TTN decoder\nfunction decodeUplink(input) {\n var res = Decoder(input.bytes, input.fPort);\n if (res.error) {\n return {\n errors: [res.error],\n };\n }\n return {\n data: res,\n };\n}\n/**\n * Payload Decoder for The Things Network\n * \n * Copyright 2021 Milesight IoT\n * \n * @product AM307 / AM319\n */\nfunction Decoder(bytes, port) {\n var decoded = {};\n\n for (var i = 0; i < bytes.length;) {\n var channel_id = bytes[i++];\n var channel_type = bytes[i++];\n // BATTERY\n if (channel_id === 0x01 && channel_type === 0x75) {\n decoded.battery = bytes[i];\n i += 1;\n }\n // TEMPERATURE\n else if (channel_id === 0x03 && channel_type === 0x67) {\n // ℃\n decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10;\n i += 2;\n\n // ℉\n // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32;\n // i +=2;\n }\n // HUMIDITY\n else if (channel_id === 0x04 && channel_type === 0x68) {\n decoded.humidity = bytes[i] / 2;\n i += 1;\n }\n // PIR\n else if (channel_id === 0x05 && channel_type === 0x00) {\n decoded.pir = bytes[i] === 1 ? \"trigger\" : \"idle\";\n i += 1;\n }\n // LIGHT\n else if (channel_id === 0x06 && channel_type === 0xCB) {\n decoded.light_level = bytes[i];\n i += 1;\n }\n // CO2\n else if (channel_id === 0x07 && channel_type === 0x7D) {\n decoded.co2 = readUInt16LE(bytes.slice(i, i + 2));\n i += 2;\n }\n // TVOC\n else if (channel_id === 0x08 && channel_type === 0x7D) {\n decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2));\n i += 2;\n }\n // PRESSURE\n else if (channel_id === 0x09 && channel_type === 0x73) {\n decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10;\n i += 2;\n }\n // HCHO\n else if (channel_id === 0x0A && channel_type === 0x7D) {\n decoded.hcho = readUInt16LE(bytes.slice(i, i + 2)) / 100;\n i += 2;\n }\n // PM2.5\n else if (channel_id === 0x0B && channel_type === 0x7D) {\n decoded.pm2_5 = readUInt16LE(bytes.slice(i, i + 2));\n i += 2;\n }\n // PM10\n else if (channel_id === 0x0C && channel_type === 0x7D) {\n decoded.pm10 = readUInt16LE(bytes.slice(i, i + 2));\n i += 2;\n }\n // O3\n else if (channel_id === 0x0D && channel_type === 0x7D) {\n decoded.o3 = readUInt16LE(bytes.slice(i, i + 2)) / 100;\n i += 2;\n }\n // BEEP\n else if (channel_id === 0x0E && channel_type === 0x01) {\n decoded.beep = bytes[i] === 1 ? \"yes\" : \"no\";\n i += 1;\n } else {\n break;\n }\n }\n\n return decoded;\n}\n\n/* ******************************************\n * bytes to number\n ********************************************/\nfunction readUInt16LE(bytes) {\n var value = (bytes[1] << 8) + bytes[0];\n return value & 0xffff;\n}\n\nfunction readInt16LE(bytes) {\n var ref = readUInt16LE(bytes);\n return ref > 0x7fff ? ref - 0x10000 : ref;\n}", - "environment": "javascript", - "storage": "", - "version": "1.0" - }, - "flows": { - "milesight_am307l_decoder": { - "data": { - "payload": "{{payload}}", - "payload_function": "decodeThingerUplink", - "payload_type": "source_payload", - "resource": "uplink", - "source": "resource", - "update": "events" - }, - "enabled": true, - "sink": { - "payload": "{{payload}}", - "payload_function": "", - "payload_type": "source_payload", - "resource_stream": "uplink_decoded", - "target": "resource_stream" - }, - "split_data": false - } - }, - "properties": { - "uplink": { - "data": { - "payload": "{{payload}}", - "payload_function": "", - "payload_type": "source_payload", - "resource": "uplink", - "source": "resource", - "update": "events" - }, - "default": { - "source": "value" - }, - "enabled": true - } - } - }, - "_resources": { - "properties": [ + "description": "Milesight am307l collects various indoor ambience conditions through 7 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC.", + "image": "assets/am307l.png", + "category": "devices", + "vendor": "milesight-iot" + }, + "resources": { + "products": [ { - "property": "dashboard", - "value": { - "tabs": [ - { - "name": "Overview", - "widgets": [ - { - "layout": { - "col": 0, - "row": 0, - "sizeX": 2, - "sizeY": 4 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Temperature" - }, - "properties": { - "decimalPlaces": 1, - "textAlign": "center", - "textColor": "#d1311f", - "textSize": "60px", - "textWeight": "font-light", - "unit": "°C", - "unitSize": "18px" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "temperature", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#d1311f", - "name": "Temperature", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 2, - "row": 0, - "sizeX": 2, - "sizeY": 4 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Humidity" - }, - "properties": { - "decimalPlaces": 1, - "textAlign": "center", - "textColor": "#329fcd", - "textSize": "60px", - "textWeight": "font-light", - "unit": "%", - "unitSize": "18px" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "humidity", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#329fcd", - "name": "Humidity", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 4, - "row": 0, - "sizeX": 2, - "sizeY": 4 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "CO2" - }, - "properties": { - "decimalPlaces": 0, - "textAlign": "center", - "textColor": "#f39c12", - "textSize": "60px", - "textWeight": "font-light", - "unit": "ppm", - "unitSize": "18px" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "co2", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#f39c12", - "name": "CO2", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 0, - "row": 4, - "sizeX": 2, - "sizeY": 4 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "TVOC" - }, - "properties": { - "decimalPlaces": 0, - "textAlign": "center", - "textColor": "#9b59b6", - "textSize": "60px", - "textWeight": "font-light", - "unit": "ppb", - "unitSize": "18px" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "tvoc", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#9b59b6", - "name": "TVOC", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 2, - "row": 4, - "sizeX": 2, - "sizeY": 4 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "PM2.5" - }, - "properties": { - "decimalPlaces": 0, - "textAlign": "center", - "textColor": "#e74c3c", - "textSize": "60px", - "textWeight": "font-light", - "unit": "µg/m³", - "unitSize": "18px" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "pm2_5", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#e74c3c", - "name": "PM2.5", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 4, - "row": 4, - "sizeX": 2, - "sizeY": 4 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Pressure" - }, - "properties": { - "decimalPlaces": 1, - "textAlign": "center", - "textColor": "#16a085", - "textSize": "60px", - "textWeight": "font-light", - "unit": "hPa", - "unitSize": "18px" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "pressure", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#16a085", - "name": "Pressure", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 0, - "row": 8, - "sizeX": 2, - "sizeY": 5 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Battery" - }, - "properties": { - "color": "#2ebd59", - "gradient": false, - "max": 100, - "min": 0, - "unit": "%" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "battery", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#2ebd59", - "name": "Battery", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "gauge" - }, - { - "layout": { - "col": 2, - "row": 8, - "sizeX": 2, - "sizeY": 5 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Light Level" - }, - "properties": { - "decimalPlaces": 0, - "textAlign": "center", - "textColor": "#f1c40f", - "textSize": "60px", - "textWeight": "font-light", - "unit": "", - "unitSize": "18px" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "light_level", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#f1c40f", - "name": "Light", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 4, - "row": 8, - "sizeX": 2, - "sizeY": 5 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "PIR Motion" - }, - "properties": { - "textAlign": "center", - "textColor": "#3498db", - "textSize": "40px", - "textWeight": "font-light" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "pir", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#3498db", - "name": "PIR", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 0, - "row": 13, - "sizeX": 6, - "sizeY": 10 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Temperature & Humidity (24h)" - }, - "properties": { - "alignTimeSeries": false, - "dataAppend": false, - "options": "var options = {\n chart: {\n type: 'area',\n stacked: false\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: [\n {\n title: { text: 'Temperature (°C)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(1);\n }\n }\n },\n {\n opposite: true,\n title: { text: 'Humidity (%)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(1);\n }\n }\n }\n ],\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", - "realTimeUpdate": true - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "temperature", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#d1311f", - "name": "Temperature", - "source": "bucket", - "timespan": { - "magnitude": "hour", - "mode": "relative", - "period": "latest", - "value": 24 - } - }, - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "humidity", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#329fcd", - "name": "Humidity", - "source": "bucket", - "timespan": { - "magnitude": "hour", - "mode": "relative", - "period": "latest", - "value": 24 - } - } - ], - "type": "apex_charts" - }, - { - "layout": { - "col": 0, - "row": 23, - "sizeX": 6, - "sizeY": 10 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Air Quality - CO2 & TVOC (24h)" - }, - "properties": { - "alignTimeSeries": false, - "dataAppend": false, - "options": "var options = {\n chart: {\n type: 'line',\n stacked: false\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: [\n {\n title: { text: 'CO2 (ppm)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(0);\n }\n }\n },\n {\n opposite: true,\n title: { text: 'TVOC (ppb)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(0);\n }\n }\n }\n ],\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", - "realTimeUpdate": true - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "co2", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#f39c12", - "name": "CO2", - "source": "bucket", - "timespan": { - "magnitude": "hour", - "mode": "relative", - "period": "latest", - "value": 24 - } - }, - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "tvoc", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#9b59b6", - "name": "TVOC", - "source": "bucket", - "timespan": { - "magnitude": "hour", - "mode": "relative", - "period": "latest", - "value": 24 + "config": { + "icons": [] + }, + "description": "Milesight am307l collects various indoor ambience conditions through 7 built-in sensors and delivers the data to the mobile App and its 4.2-inch E-ink screen. It supports batteries or DC power supply and can be easily equipped via NFC.", + "enabled": true, + "name": "Milesight-Iot AM307L", + "product": "milesight_iot_am307l", + "profile": { + "api": { + "downlink": { + "enabled": true, + "handle_connectivity": false, + "request": { + "data": { + "path": "/downlink", + "payload": "{\r\n \"data\" : \"{{payload.data=\"\"}}\",\r\n \"port\" : {{payload.port=2}},\r\n \"priority\": {{payload.priority=3}},\r\n \"confirmed\" : {{payload.confirmed=false}},\r\n \"uplink\" : {{property.uplink}} \r\n}", + "payload_function": "", + "payload_type": "", + "plugin": "{{property.uplink.source}}", + "target": "plugin_endpoint" + } } - } - ], - "type": "apex_charts" - }, - { - "layout": { - "col": 0, - "row": 33, - "sizeX": 6, - "sizeY": 10 }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Particulate Matter - PM2.5 & PM10 (24h)" - }, - "properties": { - "alignTimeSeries": false, - "dataAppend": false, - "options": "var options = {\n chart: {\n type: 'area',\n stacked: false\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'PM (µg/m³)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(0);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", - "realTimeUpdate": true - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "pm2_5", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#e74c3c", - "name": "PM2.5", - "source": "bucket", - "timespan": { - "magnitude": "hour", - "mode": "relative", - "period": "latest", - "value": 24 + "uplink": { + "enabled": true, + "handle_connectivity": true, + "request": { + "data": { + "payload": "{{payload}}", + "payload_function": "", + "payload_type": "source_payload", + "resource_stream": "uplink", + "target": "resource_stream" + } } - }, - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "pm10", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#c0392b", - "name": "PM10", - "source": "bucket", - "timespan": { - "magnitude": "hour", - "mode": "relative", - "period": "latest", - "value": 24 - } - } - ], - "type": "apex_charts" - } - ] - }, - { - "name": "Advanced", - "widgets": [ - { - "layout": { - "col": 0, - "row": 0, - "sizeX": 2, - "sizeY": 4 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "HCHO (Formaldehyde)" - }, - "properties": { - "decimalPlaces": 2, - "textAlign": "center", - "textColor": "#e67e22", - "textSize": "60px", - "textWeight": "font-light", - "unit": "mg/m³", - "unitSize": "18px" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "hcho", - "tags": { - "device": [], - "group": [] - } - }, - "color": "#e67e22", - "name": "HCHO", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 2, - "row": 0, - "sizeX": 2, - "sizeY": 4 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "PM10" - }, - "properties": { - "decimalPlaces": 0, - "textAlign": "center", - "textColor": "#c0392b", - "textSize": "60px", - "textWeight": "font-light", - "unit": "µg/m³", - "unitSize": "18px" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "pm10", - "tags": { - "device": [], - "group": [] - } + } + }, + "autoprovisions": { + "device_autoprovisioning": { + "config": { + "mode": "pattern", + "pattern": "am307l_.*" }, - "color": "#c0392b", - "name": "PM10", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 4, - "row": 0, - "sizeX": 2, - "sizeY": 4 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "O3 (Ozone)" - }, - "properties": { - "decimalPlaces": 2, - "textAlign": "center", - "textColor": "#27ae60", - "textSize": "60px", - "textWeight": "font-light", - "unit": "ppm", - "unitSize": "18px" - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "o3", - "tags": { - "device": [], - "group": [] - } + "enabled": true + } + }, + "buckets": { + "milesight_am307l_data": { + "backend": "mongodb", + "data": { + "payload": "{{payload}}", + "payload_function": "", + "payload_type": "source_payload", + "resource_stream": "uplink_decoded", + "source": "resource_stream" }, - "color": "#27ae60", - "name": "O3", - "source": "bucket", - "timespan": { - "mode": "latest" - } - } - ], - "type": "text" - }, - { - "layout": { - "col": 0, - "row": 4, - "sizeX": 6, - "sizeY": 10 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Atmospheric Pressure (24h)" - }, - "properties": { - "alignTimeSeries": false, - "dataAppend": false, - "options": "var options = {\n chart: {\n type: 'line'\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'Pressure (hPa)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(1);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", - "realTimeUpdate": true - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "pressure", - "tags": { - "device": [], - "group": [] - } + "enabled": true, + "retention": { + "period": 3, + "unit": "months" }, - "color": "#16a085", - "name": "Pressure", - "source": "bucket", - "timespan": { - "magnitude": "hour", - "mode": "relative", - "period": "latest", - "value": 24 - } - } - ], - "type": "apex_charts" - }, - { - "layout": { - "col": 0, - "row": 14, - "sizeX": 6, - "sizeY": 10 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Formaldehyde (HCHO) (24h)" - }, - "properties": { - "alignTimeSeries": false, - "dataAppend": false, - "options": "var options = {\n chart: {\n type: 'area'\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'HCHO (mg/m³)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(2);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", - "realTimeUpdate": true - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "hcho", - "tags": { - "device": [], - "group": [] - } + "tags": [] + } + }, + "code": { + "code": "function decodeThingerUplink(thingerData) {\n // 0. If data has already been decoded, we will return it\n if (thingerData.decodedPayload) return thingerData.decodedPayload;\n \n // 1. Extract and Validate Input\n // We need 'payload' (hex string) and 'fPort' (integer)\n const hexPayload = thingerData.payload || \"\";\n const port = thingerData.fPort || 1;\n\n // 2. Convert Hex String to Byte Array\n const bytes = [];\n for (let i = 0; i < hexPayload.length; i += 2) {\n bytes.push(parseInt(hexPayload.substr(i, 2), 16));\n }\n\n // 3. Dynamic Function Detection and Execution\n \n // CASE A: (The Things Stack v3)\n if (typeof decodeUplink === 'function') {\n try {\n const input = {\n bytes: bytes,\n fPort: port\n };\n var result = decodeUplink(input);\n \n if (result.data) return result.data;\n\n return result; \n } catch (e) {\n console.error(\"Error inside decodeUplink:\", e);\n throw e;\n }\n }\n\n // CASE B: Legacy TTN (v2)\n else if (typeof Decoder === 'function') {\n try {\n return Decoder(bytes, port);\n } catch (e) {\n console.error(\"Error inside Decoder:\", e);\n throw e;\n }\n }\n\n // CASE C: No decoder found\n else {\n throw new Error(\"No compatible TTN decoder function (decodeUplink or Decoder) found in scope.\");\n }\n}\n\n\n// TTN decoder\nfunction decodeUplink(input) {\n var res = Decoder(input.bytes, input.fPort);\n if (res.error) {\n return {\n errors: [res.error],\n };\n }\n return {\n data: res,\n };\n}\n/**\n * Payload Decoder for The Things Network\n * \n * Copyright 2021 Milesight IoT\n * \n * @product AM307 / AM319\n */\nfunction Decoder(bytes, port) {\n var decoded = {};\n\n for (var i = 0; i < bytes.length;) {\n var channel_id = bytes[i++];\n var channel_type = bytes[i++];\n // BATTERY\n if (channel_id === 0x01 && channel_type === 0x75) {\n decoded.battery = bytes[i];\n i += 1;\n }\n // TEMPERATURE\n else if (channel_id === 0x03 && channel_type === 0x67) {\n // ℃\n decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10;\n i += 2;\n\n // ℉\n // decoded.temperature = readInt16LE(bytes.slice(i, i + 2)) / 10 * 1.8 + 32;\n // i +=2;\n }\n // HUMIDITY\n else if (channel_id === 0x04 && channel_type === 0x68) {\n decoded.humidity = bytes[i] / 2;\n i += 1;\n }\n // PIR\n else if (channel_id === 0x05 && channel_type === 0x00) {\n decoded.pir = bytes[i] === 1 ? \"trigger\" : \"idle\";\n i += 1;\n }\n // LIGHT\n else if (channel_id === 0x06 && channel_type === 0xCB) {\n decoded.light_level = bytes[i];\n i += 1;\n }\n // CO2\n else if (channel_id === 0x07 && channel_type === 0x7D) {\n decoded.co2 = readUInt16LE(bytes.slice(i, i + 2));\n i += 2;\n }\n // TVOC\n else if (channel_id === 0x08 && channel_type === 0x7D) {\n decoded.tvoc = readUInt16LE(bytes.slice(i, i + 2));\n i += 2;\n }\n // PRESSURE\n else if (channel_id === 0x09 && channel_type === 0x73) {\n decoded.pressure = readUInt16LE(bytes.slice(i, i + 2)) / 10;\n i += 2;\n }\n // HCHO\n else if (channel_id === 0x0A && channel_type === 0x7D) {\n decoded.hcho = readUInt16LE(bytes.slice(i, i + 2)) / 100;\n i += 2;\n }\n // PM2.5\n else if (channel_id === 0x0B && channel_type === 0x7D) {\n decoded.pm2_5 = readUInt16LE(bytes.slice(i, i + 2));\n i += 2;\n }\n // PM10\n else if (channel_id === 0x0C && channel_type === 0x7D) {\n decoded.pm10 = readUInt16LE(bytes.slice(i, i + 2));\n i += 2;\n }\n // O3\n else if (channel_id === 0x0D && channel_type === 0x7D) {\n decoded.o3 = readUInt16LE(bytes.slice(i, i + 2)) / 100;\n i += 2;\n }\n // BEEP\n else if (channel_id === 0x0E && channel_type === 0x01) {\n decoded.beep = bytes[i] === 1 ? \"yes\" : \"no\";\n i += 1;\n } else {\n break;\n }\n }\n\n return decoded;\n}\n\n/* ******************************************\n * bytes to number\n ********************************************/\nfunction readUInt16LE(bytes) {\n var value = (bytes[1] << 8) + bytes[0];\n return value & 0xffff;\n}\n\nfunction readInt16LE(bytes) {\n var ref = readUInt16LE(bytes);\n return ref > 0x7fff ? ref - 0x10000 : ref;\n}", + "environment": "javascript", + "storage": "", + "version": "1.0" + }, + "flows": { + "milesight_am307l_decoder": { + "data": { + "payload": "{{payload}}", + "payload_function": "decodeThingerUplink", + "payload_type": "source_payload", + "resource": "uplink", + "source": "resource", + "update": "events" }, - "color": "#e67e22", - "name": "HCHO", - "source": "bucket", - "timespan": { - "magnitude": "hour", - "mode": "relative", - "period": "latest", - "value": 24 - } - } - ], - "type": "apex_charts" - }, - { - "layout": { - "col": 0, - "row": 24, - "sizeX": 6, - "sizeY": 10 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Ozone (O3) (24h)" - }, - "properties": { - "alignTimeSeries": false, - "dataAppend": false, - "options": "var options = {\n chart: {\n type: 'area'\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'O3 (ppm)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(2);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", - "realTimeUpdate": true - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "o3", - "tags": { - "device": [], - "group": [] - } + "enabled": true, + "sink": { + "payload": "{{payload}}", + "payload_function": "", + "payload_type": "source_payload", + "resource_stream": "uplink_decoded", + "target": "resource_stream" }, - "color": "#27ae60", - "name": "O3", - "source": "bucket", - "timespan": { - "magnitude": "hour", - "mode": "relative", - "period": "latest", - "value": 24 - } - } - ], - "type": "apex_charts" - }, - { - "layout": { - "col": 0, - "row": 34, - "sizeX": 6, - "sizeY": 10 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Light Level (24h)" - }, - "properties": { - "alignTimeSeries": false, - "dataAppend": false, - "options": "var options = {\n chart: {\n type: 'area'\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'Light Level' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(0);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", - "realTimeUpdate": true - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "light_level", - "tags": { - "device": [], - "group": [] - } + "split_data": false + } + }, + "properties": { + "uplink": { + "data": { + "payload": "{{payload}}", + "payload_function": "", + "payload_type": "source_payload", + "resource": "uplink", + "source": "resource", + "update": "events" }, - "color": "#f1c40f", - "name": "Light", - "source": "bucket", - "timespan": { - "magnitude": "hour", - "mode": "relative", - "period": "latest", - "value": 24 - } - } - ], - "type": "apex_charts" - }, - { - "layout": { - "col": 0, - "row": 44, - "sizeX": 6, - "sizeY": 8 - }, - "panel": { - "color": "#ffffff", - "currentColor": "#ffffff", - "showOffline": { - "type": "none" - }, - "title": "Battery Level (7 days)" - }, - "properties": { - "alignTimeSeries": false, - "dataAppend": false, - "options": "var options = {\n chart: {\n type: 'line'\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'Battery (%)' },\n min: 0,\n max: 100,\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(0);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", - "realTimeUpdate": true - }, - "sources": [ - { - "bucket": { - "backend": "mongodb", - "id": "milesight_am307l_data", - "mapping": "battery", - "tags": { - "device": [], - "group": [] - } + "default": { + "source": "value" }, - "color": "#2ebd59", - "name": "Battery", - "source": "bucket", - "timespan": { - "magnitude": "day", - "mode": "relative", - "period": "latest", - "value": 7 + "enabled": true + } + } + }, + "_resources": { + "properties": [ + { + "property": "dashboard", + "value": { + "tabs": [ + { + "name": "Overview", + "widgets": [ + { + "layout": { + "col": 0, + "row": 0, + "sizeX": 2, + "sizeY": 4 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Temperature" + }, + "properties": { + "decimalPlaces": 1, + "textAlign": "center", + "textColor": "#d1311f", + "textSize": "60px", + "textWeight": "font-light", + "unit": "°C", + "unitSize": "18px" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "temperature", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#d1311f", + "name": "Temperature", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 2, + "row": 0, + "sizeX": 2, + "sizeY": 4 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Humidity" + }, + "properties": { + "decimalPlaces": 1, + "textAlign": "center", + "textColor": "#329fcd", + "textSize": "60px", + "textWeight": "font-light", + "unit": "%", + "unitSize": "18px" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "humidity", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#329fcd", + "name": "Humidity", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 4, + "row": 0, + "sizeX": 2, + "sizeY": 4 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "CO2" + }, + "properties": { + "decimalPlaces": 0, + "textAlign": "center", + "textColor": "#f39c12", + "textSize": "60px", + "textWeight": "font-light", + "unit": "ppm", + "unitSize": "18px" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "co2", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#f39c12", + "name": "CO2", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 0, + "row": 4, + "sizeX": 2, + "sizeY": 4 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "TVOC" + }, + "properties": { + "decimalPlaces": 0, + "textAlign": "center", + "textColor": "#9b59b6", + "textSize": "60px", + "textWeight": "font-light", + "unit": "ppb", + "unitSize": "18px" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "tvoc", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#9b59b6", + "name": "TVOC", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 2, + "row": 4, + "sizeX": 2, + "sizeY": 4 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "PM2.5" + }, + "properties": { + "decimalPlaces": 0, + "textAlign": "center", + "textColor": "#e74c3c", + "textSize": "60px", + "textWeight": "font-light", + "unit": "µg/m³", + "unitSize": "18px" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "pm2_5", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#e74c3c", + "name": "PM2.5", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 4, + "row": 4, + "sizeX": 2, + "sizeY": 4 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Pressure" + }, + "properties": { + "decimalPlaces": 1, + "textAlign": "center", + "textColor": "#16a085", + "textSize": "60px", + "textWeight": "font-light", + "unit": "hPa", + "unitSize": "18px" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "pressure", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#16a085", + "name": "Pressure", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 0, + "row": 8, + "sizeX": 2, + "sizeY": 5 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Battery" + }, + "properties": { + "color": "#2ebd59", + "gradient": false, + "max": 100, + "min": 0, + "unit": "%" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "battery", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#2ebd59", + "name": "Battery", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "gauge" + }, + { + "layout": { + "col": 2, + "row": 8, + "sizeX": 2, + "sizeY": 5 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Light Level" + }, + "properties": { + "decimalPlaces": 0, + "textAlign": "center", + "textColor": "#f1c40f", + "textSize": "60px", + "textWeight": "font-light", + "unit": "", + "unitSize": "18px" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "light_level", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#f1c40f", + "name": "Light", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 4, + "row": 8, + "sizeX": 2, + "sizeY": 5 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "PIR Motion" + }, + "properties": { + "textAlign": "center", + "textColor": "#3498db", + "textSize": "40px", + "textWeight": "font-light" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "pir", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#3498db", + "name": "PIR", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 0, + "row": 13, + "sizeX": 6, + "sizeY": 10 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Temperature & Humidity (24h)" + }, + "properties": { + "alignTimeSeries": false, + "dataAppend": false, + "options": "var options = {\n chart: {\n type: 'area',\n stacked: false\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: [\n {\n title: { text: 'Temperature (°C)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(1);\n }\n }\n },\n {\n opposite: true,\n title: { text: 'Humidity (%)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(1);\n }\n }\n }\n ],\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", + "realTimeUpdate": true + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "temperature", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#d1311f", + "name": "Temperature", + "source": "bucket", + "timespan": { + "magnitude": "hour", + "mode": "relative", + "period": "latest", + "value": 24 + } + }, + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "humidity", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#329fcd", + "name": "Humidity", + "source": "bucket", + "timespan": { + "magnitude": "hour", + "mode": "relative", + "period": "latest", + "value": 24 + } + } + ], + "type": "apex_charts" + }, + { + "layout": { + "col": 0, + "row": 23, + "sizeX": 6, + "sizeY": 10 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Air Quality - CO2 & TVOC (24h)" + }, + "properties": { + "alignTimeSeries": false, + "dataAppend": false, + "options": "var options = {\n chart: {\n type: 'line',\n stacked: false\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: [\n {\n title: { text: 'CO2 (ppm)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(0);\n }\n }\n },\n {\n opposite: true,\n title: { text: 'TVOC (ppb)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(0);\n }\n }\n }\n ],\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", + "realTimeUpdate": true + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "co2", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#f39c12", + "name": "CO2", + "source": "bucket", + "timespan": { + "magnitude": "hour", + "mode": "relative", + "period": "latest", + "value": 24 + } + }, + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "tvoc", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#9b59b6", + "name": "TVOC", + "source": "bucket", + "timespan": { + "magnitude": "hour", + "mode": "relative", + "period": "latest", + "value": 24 + } + } + ], + "type": "apex_charts" + }, + { + "layout": { + "col": 0, + "row": 33, + "sizeX": 6, + "sizeY": 10 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Particulate Matter - PM2.5 & PM10 (24h)" + }, + "properties": { + "alignTimeSeries": false, + "dataAppend": false, + "options": "var options = {\n chart: {\n type: 'area',\n stacked: false\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'PM (µg/m³)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(0);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", + "realTimeUpdate": true + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "pm2_5", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#e74c3c", + "name": "PM2.5", + "source": "bucket", + "timespan": { + "magnitude": "hour", + "mode": "relative", + "period": "latest", + "value": 24 + } + }, + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "pm10", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#c0392b", + "name": "PM10", + "source": "bucket", + "timespan": { + "magnitude": "hour", + "mode": "relative", + "period": "latest", + "value": 24 + } + } + ], + "type": "apex_charts" + } + ] + }, + { + "name": "Advanced", + "widgets": [ + { + "layout": { + "col": 0, + "row": 0, + "sizeX": 2, + "sizeY": 4 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "HCHO (Formaldehyde)" + }, + "properties": { + "decimalPlaces": 2, + "textAlign": "center", + "textColor": "#e67e22", + "textSize": "60px", + "textWeight": "font-light", + "unit": "mg/m³", + "unitSize": "18px" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "hcho", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#e67e22", + "name": "HCHO", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 2, + "row": 0, + "sizeX": 2, + "sizeY": 4 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "PM10" + }, + "properties": { + "decimalPlaces": 0, + "textAlign": "center", + "textColor": "#c0392b", + "textSize": "60px", + "textWeight": "font-light", + "unit": "µg/m³", + "unitSize": "18px" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "pm10", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#c0392b", + "name": "PM10", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 4, + "row": 0, + "sizeX": 2, + "sizeY": 4 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "O3 (Ozone)" + }, + "properties": { + "decimalPlaces": 2, + "textAlign": "center", + "textColor": "#27ae60", + "textSize": "60px", + "textWeight": "font-light", + "unit": "ppm", + "unitSize": "18px" + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "o3", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#27ae60", + "name": "O3", + "source": "bucket", + "timespan": { + "mode": "latest" + } + } + ], + "type": "text" + }, + { + "layout": { + "col": 0, + "row": 4, + "sizeX": 6, + "sizeY": 10 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Atmospheric Pressure (24h)" + }, + "properties": { + "alignTimeSeries": false, + "dataAppend": false, + "options": "var options = {\n chart: {\n type: 'line'\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'Pressure (hPa)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(1);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", + "realTimeUpdate": true + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "pressure", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#16a085", + "name": "Pressure", + "source": "bucket", + "timespan": { + "magnitude": "hour", + "mode": "relative", + "period": "latest", + "value": 24 + } + } + ], + "type": "apex_charts" + }, + { + "layout": { + "col": 0, + "row": 14, + "sizeX": 6, + "sizeY": 10 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Formaldehyde (HCHO) (24h)" + }, + "properties": { + "alignTimeSeries": false, + "dataAppend": false, + "options": "var options = {\n chart: {\n type: 'area'\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'HCHO (mg/m³)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(2);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", + "realTimeUpdate": true + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "hcho", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#e67e22", + "name": "HCHO", + "source": "bucket", + "timespan": { + "magnitude": "hour", + "mode": "relative", + "period": "latest", + "value": 24 + } + } + ], + "type": "apex_charts" + }, + { + "layout": { + "col": 0, + "row": 24, + "sizeX": 6, + "sizeY": 10 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Ozone (O3) (24h)" + }, + "properties": { + "alignTimeSeries": false, + "dataAppend": false, + "options": "var options = {\n chart: {\n type: 'area'\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'O3 (ppm)' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(2);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", + "realTimeUpdate": true + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "o3", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#27ae60", + "name": "O3", + "source": "bucket", + "timespan": { + "magnitude": "hour", + "mode": "relative", + "period": "latest", + "value": 24 + } + } + ], + "type": "apex_charts" + }, + { + "layout": { + "col": 0, + "row": 34, + "sizeX": 6, + "sizeY": 10 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Light Level (24h)" + }, + "properties": { + "alignTimeSeries": false, + "dataAppend": false, + "options": "var options = {\n chart: {\n type: 'area'\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'Light Level' },\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(0);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", + "realTimeUpdate": true + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "light_level", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#f1c40f", + "name": "Light", + "source": "bucket", + "timespan": { + "magnitude": "hour", + "mode": "relative", + "period": "latest", + "value": 24 + } + } + ], + "type": "apex_charts" + }, + { + "layout": { + "col": 0, + "row": 44, + "sizeX": 6, + "sizeY": 8 + }, + "panel": { + "color": "#ffffff", + "currentColor": "#ffffff", + "showOffline": { + "type": "none" + }, + "title": "Battery Level (7 days)" + }, + "properties": { + "alignTimeSeries": false, + "dataAppend": false, + "options": "var options = {\n chart: {\n type: 'line'\n },\n dataLabels: {\n enabled: false\n },\n stroke: {\n curve: 'smooth',\n width: 2\n },\n xaxis: {\n type: 'datetime',\n labels: {\n datetimeUTC: false\n },\n tooltip: {\n enabled: false\n }\n },\n yaxis: {\n title: { text: 'Battery (%)' },\n min: 0,\n max: 100,\n labels: {\n formatter: function (val) {\n if (val !== null && typeof val !== 'undefined')\n return val.toFixed(0);\n }\n }\n },\n tooltip: {\n x: {\n format: 'dd/MM/yyyy HH:mm:ss'\n }\n }\n};\n", + "realTimeUpdate": true + }, + "sources": [ + { + "bucket": { + "backend": "mongodb", + "id": "milesight_am307l_data", + "mapping": "battery", + "tags": { + "device": [], + "group": [] + } + }, + "color": "#2ebd59", + "name": "Battery", + "source": "bucket", + "timespan": { + "magnitude": "day", + "mode": "relative", + "period": "latest", + "value": 7 + } + } + ], + "type": "apex_charts" + } + ] + } + ] } - } - ], - "type": "apex_charts" - } + } ] - } - ] - } + } } - ] - } - } - ] - } -} \ No newline at end of file + ] + } +}