diff --git a/fire-cloud/index.js b/fire-cloud/index.js index 5d8a221..87ec01f 100644 --- a/fire-cloud/index.js +++ b/fire-cloud/index.js @@ -91,12 +91,13 @@ async function connectAndSubscribe() { const humidity = messageJson.humidity; const airQualityPpm = messageJson.air; const flameSensorValue = messageJson.flame; + const utcTimestamp = convertEpochToUTC(messageJson.timestamp); const { data, error } = await supabase .from("firecloud") .insert({ node_id: messageJson.id, - timestamp: convertEpochToUTC(messageJson.timestamp), + timestamp: utcTimestamp, temperature: temperature, humidity: humidity, air_quality_ppm: airQualityPpm, @@ -110,7 +111,13 @@ async function connectAndSubscribe() { //invoke lambda function to calculate fire probability and update database const rowId = data[0].id; - const lambdaRes = await invokeAnalytics(nodeId, rowId, temperature, flameSensorValue); + const lambdaRes = await invokeAnalytics( + nodeId, + rowId, + temperature, + flameSensorValue, + utcTimestamp + ); const fireProbability = lambdaRes.fire_probability; @@ -131,21 +138,25 @@ async function validateAndPublishFireMessage(nodeId, fireProbability) { fireStatuses[nodeId] = 1; } - //if fire is dying down - if (fireStatuses[nodeId] === 1 && fireProbability < fireProbabilityThreshold) { - if (noFireDurations[nodeId] === null) { - noFireDurations[nodeId] = new Date().getTime(); - } else { - const currentTime = new Date().getTime(); - const timeDiff = currentTime - noFireDurations[nodeId]; - const timeDiffInMinutes = timeDiff / 60000; - - // if status has been 0 for more than 5 minutes -> there is no more fire -> publish status 0 - if (timeDiffInMinutes > 5) { - await updateAndPublishFireMessage(FLAME_PRESENCE_TOPIC, 0); - fireStatuses[nodeId] = 0; - noFireDurations[nodeId] = null; + //if fire is dying down aa + if (fireStatuses[nodeId] === 1) { + if (fireProbability < fireProbabilityThreshold) { + if (noFireDurations[nodeId] === null) { + noFireDurations[nodeId] = new Date().getTime(); + } else { + const currentTime = new Date().getTime(); + const timeDiff = currentTime - noFireDurations[nodeId]; + const timeDiffInMinutes = timeDiff / 60000; + + // if status has been 0 for more than 5 minutes -> there is no more fire -> publish status 0 + if (timeDiffInMinutes > 5) { + await updateAndPublishFireMessage(FLAME_PRESENCE_TOPIC, 0); + fireStatuses[nodeId] = 0; + noFireDurations[nodeId] = null; + } } + } else { + noFireDurations[nodeId] = null; } } } @@ -176,7 +187,7 @@ async function publishMessage(topic, message) { } // Function to invoke the Analytics lambda function to calculate the fire probability and update the database -async function invokeAnalytics(nodeId, rowId, temp, flameValue) { +async function invokeAnalytics(nodeId, rowId, temp, flameValue, utcDatetime) { console.log("Invoking lambda function..."); const command = new InvokeCommand({ FunctionName: "greendot-analytics", @@ -186,12 +197,13 @@ async function invokeAnalytics(nodeId, rowId, temp, flameValue) { rowId: rowId, temp: temp, flame: flameValue, + utc_datetime_string: utcDatetime, }), }); const { Payload } = await lambdaClient.send(command); let result = Buffer.from(Payload).toString(); - result = JSON.parse(result) + result = JSON.parse(result); return JSON.parse(result.body); } diff --git a/grafana.json b/grafana.json new file mode 100644 index 0000000..9f67525 --- /dev/null +++ b/grafana.json @@ -0,0 +1,1430 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "fdcddc6a-cd72-4e41-b7a7-3bbc5cccd401" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "node_0" + }, + "properties": [ + { + "id": "displayName", + "value": "Node 0" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "node_1" + }, + "properties": [ + { + "id": "displayName", + "value": "Node 1" + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT \"timestamp\", fire_probability AS node_0 FROM firecloud WHERE node_id = 0 order by\n timestamp desc", + "refId": "Node 0 Probability", + "sql": { + "columns": [ + { + "parameters": [ + { + "name": "\"timestamp\"", + "type": "functionParameter" + } + ], + "type": "function" + }, + { + "parameters": [ + { + "name": "fire_probability", + "type": "functionParameter" + } + ], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50, + "whereJsonTree": { + "children1": [ + { + "id": "8989ba8a-89ab-4cde-b012-318c10ba722f", + "properties": { + "field": "node_id", + "fieldSrc": "field", + "operator": "equal", + "value": [0], + "valueSrc": ["value"], + "valueType": ["number"] + }, + "type": "rule" + } + ], + "id": "8aa8aab9-89ab-4cde-b012-318c10b67cbe", + "type": "group" + }, + "whereString": "node_id = 0" + }, + "table": "firecloud" + }, + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "hide": false, + "rawQuery": true, + "rawSql": "SELECT \"timestamp\", fire_probability AS node_1 FROM firecloud WHERE node_id = 1 order by\n timestamp desc", + "refId": "Node 1 Probability", + "sql": { + "columns": [ + { + "parameters": [ + { + "name": "\"timestamp\"", + "type": "functionParameter" + } + ], + "type": "function" + }, + { + "parameters": [ + { + "name": "fire_probability", + "type": "functionParameter" + } + ], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50, + "whereJsonTree": { + "children1": [ + { + "id": "ba8889ab-cdef-4012-b456-718c10be5f72", + "properties": { + "field": "node_id", + "fieldSrc": "field", + "operator": "equal", + "value": [1], + "valueSrc": ["value"], + "valueType": ["number"] + }, + "type": "rule" + } + ], + "id": "8aa8aab9-89ab-4cde-b012-318c10b67cbe", + "type": "group" + }, + "whereString": "node_id = 1" + }, + "table": "firecloud" + } + ], + "title": "Probability", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "fdcddc6a-cd72-4e41-b7a7-3bbc5cccd401" + }, + "description": "Current Flame Sensor Value", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "false", + "result": { + "color": "green", + "index": 0, + "text": "Normal" + } + }, + "type": "special" + }, + { + "options": { + "match": "true", + "result": { + "color": "red", + "index": 1, + "text": "High Alert" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 1, + "y": 13 + }, + "id": 18, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "/^has_fire$/", + "values": false + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT has_fire FROM fire_status WHERE id = 1", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [ + { + "name": "has_fire", + "type": "functionParameter" + } + ], + "type": "function" + } + ], + "groupBy": [], + "limit": 50 + }, + "table": "fire_status" + } + ], + "title": "Alert Status", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 11, + "panels": [], + "title": "Node 1", + "type": "row" + }, + { + "datasource": {}, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 1, + "min": 0, + "noValue": "null", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0.3 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 8, + "x": 0, + "y": 20 + }, + "id": 12, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": true, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT\n fire_probability,\n timestamp\nFROM\n firecloud\nwhere\n node_id = 1\nORDER BY\n timestamp DESC\nLIMIT\n 1\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [ + { + "name": "has_fire", + "type": "functionParameter" + } + ], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + }, + "table": "fire_status" + } + ], + "title": "Probability of Fire", + "type": "gauge" + }, + { + "datasource": { + "type": "postgres", + "uid": "fdcddc6a-cd72-4e41-b7a7-3bbc5cccd401" + }, + "description": "Current Flame Sensor Value", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "green", + "index": 0, + "text": "No Flame" + }, + "1": { + "color": "red", + "index": 1, + "text": "Flame Detected" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 8, + "y": 20 + }, + "id": 5, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "select\n flame_sensor_value\nfrom\n firecloud\nwhere\n node_id = 1\norder by\n timestamp desc\nlimit\n 1;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Flame Sensor", + "type": "stat" + }, + { + "datasource": {}, + "description": "Current Humidity Level", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "fieldMinMax": false, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "#EAB839", + "value": 40 + }, + { + "color": "green", + "value": 65 + } + ] + }, + "unit": "humidity" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 12, + "y": 20 + }, + "id": 16, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "select\n humidity\nfrom\n firecloud\nwhere\n node_id = 1\norder by\n timestamp desc\nlimit\n 1;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + }, + "table": "firecloud" + } + ], + "title": "Humidity", + "type": "gauge" + }, + { + "datasource": {}, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 43, + "min": 15, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 39 + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 16, + "y": 20 + }, + "id": 17, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "select\n temperature\nfrom\n firecloud\nwhere\n node_id = 1\norder by\n timestamp desc\nlimit\n 1;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Temperature", + "type": "gauge" + }, + { + "datasource": {}, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 1, + "min": -1.5, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "green", + "value": -1.18 + }, + { + "color": "red", + "value": -0.89 + }, + { + "color": "green", + "value": -0.6 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 8, + "y": 26 + }, + "id": 14, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "select\n r_value\nfrom\n firecloud\nwhere\n node_id = 1\norder by\n timestamp desc\nlimit\n 1;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Temperature & Humidity R-value", + "type": "gauge" + }, + { + "datasource": {}, + "description": "Current Presence of CO2 in Air (ppm)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 547, + "min": 10, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 350 + } + ] + }, + "unit": "ppm" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 13, + "y": 26 + }, + "id": 15, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "select\n air_quality_ppm\nfrom\n firecloud\nwhere\n node_id = 1\norder by\n timestamp desc\nlimit\n 1;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Air Quality Sensor", + "type": "gauge" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 1, + "panels": [], + "title": "Node 0", + "type": "row" + }, + { + "datasource": {}, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 1, + "min": 0, + "noValue": "null", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 0.3 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 8, + "x": 0, + "y": 33 + }, + "id": 3, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": true, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "SELECT\n fire_probability,\n timestamp\nFROM\n firecloud\nwhere\n node_id = 0\nORDER BY\n timestamp DESC\nLIMIT\n 1\n", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [ + { + "name": "has_fire", + "type": "functionParameter" + } + ], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + }, + "table": "fire_status" + } + ], + "title": "Probability of Fire", + "type": "gauge" + }, + { + "datasource": {}, + "description": "Current Flame Sensor Value", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "color": "green", + "index": 0, + "text": "No Flame" + }, + "1": { + "color": "red", + "index": 1, + "text": "Flame Detected" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 8, + "y": 33 + }, + "id": 13, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "select\n flame_sensor_value\nfrom\n firecloud\nwhere\n node_id = 0\norder by\n timestamp desc\nlimit\n 1;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Flame Sensor", + "type": "stat" + }, + { + "datasource": {}, + "description": "Current Humidity Level", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "fieldMinMax": false, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "#EAB839", + "value": 40 + }, + { + "color": "green", + "value": 65 + } + ] + }, + "unit": "humidity" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 12, + "y": 33 + }, + "id": 4, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "select\n humidity\nfrom\n firecloud\nwhere\n node_id = 0\norder by\n timestamp desc\nlimit\n 1;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + }, + "table": "firecloud" + } + ], + "title": "Humidity", + "type": "gauge" + }, + { + "datasource": {}, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 43, + "min": 15, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 39 + } + ] + }, + "unit": "celsius" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 16, + "y": 33 + }, + "id": 2, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "select\n temperature\nfrom\n firecloud\nwhere\n node_id = 0\norder by\n timestamp desc\nlimit\n 1;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Temperature", + "type": "gauge" + }, + { + "datasource": {}, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 1, + "min": -1.5, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "green", + "value": -1.18 + }, + { + "color": "red", + "value": -0.89 + }, + { + "color": "green", + "value": -0.6 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 8, + "y": 39 + }, + "id": 7, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "select\n r_value\nfrom\n firecloud\nwhere\n node_id = 0\norder by\n timestamp desc\nlimit\n 1;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Temperature & Humidity R-value", + "type": "gauge" + }, + { + "datasource": {}, + "description": "Current Presence of CO2 in Air (ppm)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "max": 547, + "min": 10, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 350 + } + ] + }, + "unit": "ppm" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 13, + "y": 39 + }, + "id": 6, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "auto", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.2.2", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "b5236ea3-0347-4e2b-a627-0fbbe68b1304" + }, + "editorMode": "code", + "format": "table", + "rawQuery": true, + "rawSql": "select\n air_quality_ppm\nfrom\n firecloud\nwhere\n node_id = 0\norder by\n timestamp desc\nlimit\n 1;", + "refId": "A", + "sql": { + "columns": [ + { + "parameters": [], + "type": "function" + } + ], + "groupBy": [ + { + "property": { + "type": "string" + }, + "type": "groupBy" + } + ], + "limit": 50 + } + } + ], + "title": "Air Quality Sensor", + "type": "gauge" + } + ], + "refresh": "5s", + "schemaVersion": 38, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": ["5s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] + }, + "timezone": "", + "title": "GreenDot Dashboard", + "uid": "f3bbb846-51ad-47ed-b928-40d06727f5ad", + "version": 23, + "weekStart": "" +} diff --git a/lambda/lambda_function.py b/lambda/lambda_function.py index 32fd6a1..ec485a0 100644 --- a/lambda/lambda_function.py +++ b/lambda/lambda_function.py @@ -8,18 +8,20 @@ SUPABASE_KEY = os.environ.get("SUPABASE_KEY") supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY) -PAST_RECORDS_DURATION = 3 # in minutes TODO: change such that we can sample >= 25 past records (e.g. sampling interval * 25) def lambda_handler(event, context): nodeId = event.get('nodeId') rowId = event.get('rowId') temp = event.get('temp') flame = event.get('flame') + utc_datatime = event.get('utc_datetime_string') # get past records from supabase temp_hum_aq_res = None try: - temp_hum_aq_res = supabase.rpc("get_past_records", {"interval_string": f"{PAST_RECORDS_DURATION} minutes", "node_id": nodeId}).execute() + temp_hum_aq_res = supabase.rpc("get_past_records", { + "node_id": nodeId, + "utc_datetime_string": utc_datatime}).execute() except Exception as e: print(f"Error getting past records supabase: {e}") @@ -36,7 +38,7 @@ def lambda_handler(event, context): humidity_arr = [] if temp_hum_aq_data.get("all_humidity", None) is None else temp_hum_aq_data.get("all_humidity") aq_arr = [] if temp_hum_aq_data.get("all_air_quality_ppm", None) is None else temp_hum_aq_data.get("all_air_quality_ppm") - r_value = None + r_value = 0 fire_probability = 0 if len(temp_arr) >= 25 and len(humidity_arr) >= 25: @@ -66,10 +68,8 @@ def lambda_handler(event, context): }) } - if len(aq_arr) != 0 and r_value != None: - fire_probability = get_fire_probability(temp, aq_arr, flame, r_value) + fire_probability = get_fire_probability(temp, aq_arr, flame, r_value) - # TODO: update row in supabase table with r_value and fire_probability try: supabase.table('firecloud') \ .update({ @@ -107,11 +107,14 @@ def get_air_quality_probability(air_quality_arr): if (len(air_quality_arr) == 0): return 0 - # if every value in the array is above threshold, return 1 - if (all(air_quality > air_quality_threshold for air_quality in air_quality_arr)): - return 1 - else: - return 0 + # check if at least 10 hits above threshold demo: 3 hits + hits_above_threshold = 0 + for air_quality in air_quality_arr: + if (air_quality > air_quality_threshold): + hits_above_threshold += 1 + if (hits_above_threshold >= 3): + return 1 + return 0 def get_temp_probability(temp): temp_threshold = 40 # highest in sg: 37 + 3 = 40 deg (3 for threshold) @@ -133,17 +136,9 @@ def get_temp_humidity_probability(r_value): return r_ratio def get_r_value(temp_arr, humidity_arr): + if np.std(temp_arr) == 0 or np.std(humidity_arr) == 0: + return 0 + r_corrcoef = np.corrcoef(temp_arr, humidity_arr, rowvar=False) r_actual = r_corrcoef[0][1] - return r_actual - -# # #TODO: DONT PUSH THIS REMOVE IT BEFORE PUSHING -# if __name__ == "__main__": -# x = lambda_handler({ -# "rowId": 646, -# "temp": 30.9, -# "humidity": 72.4, -# "flame": 0, -# "airQuality": 526.858 -# }, None) -# print(x) \ No newline at end of file + return r_actual \ No newline at end of file