[ { "id": "2c7df0f7dd6bd8a3", "type": "debug", "z": "0754510428690e69", "name": "debug 7", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 480, "y": 40, "wires": [] }, { "id": "d4812b02191b2b54", "type": "mqtt in", "z": "0754510428690e69", "name": "", "topic": "wifips01/scan", "qos": "2", "datatype": "auto-detect", "broker": "3cae847f35cb5147", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 130, "y": 100, "wires": [ [ "37b8b7c441bc1b60" ] ] }, { "id": "e9e02e8e7b72aa77", "type": "function", "z": "0754510428690e69", "name": "Collect", "func": "const start_new_array_time=10000;\n\nvar time=Date.now(); //in ms\nvar datalasttime = flow.get(msg.topic.split(\"/\")[0] + \"_time\");\nif (datalasttime == undefined) {\n datalasttime=0;\n}\n\nvar dataarray=flow.get(msg.topic.split(\"/\")[0]+\"_array\");\n\nif (dataarray == undefined) {\n dataarray=[];\n}\n\nif ((time - datalasttime) > start_new_array_time) {\n dataarray=[]; //start new\n}\n\ndataarray.push(msg.payload);\nflow.set(msg.topic.split(\"/\")[0] + \"_time\", time);\n\n\nflow.set(msg.topic.split(\"/\")[0]+\"_array\", dataarray);\n\nmsg.payload=dataarray;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 550, "y": 100, "wires": [ [ "1e526afed8f9fb99" ] ] }, { "id": "37b8b7c441bc1b60", "type": "function", "z": "0754510428690e69", "name": "reformat", "func": "var data=msg.payload; //\"a0:25:d7:47:58:c4;TheaterDo-ATD;-85\"\nvar arraydata=data.split(\";\"); //[\"a0:25:d7:47:58:c4\",\"TheaterDo-ATD\",\"-85\"]\n\nvar objectdata={\"mac\":arraydata[0],\"ssid\":arraydata[1],\"rssi\":parseFloat(arraydata[2])};\n\nmsg.payload=objectdata;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 320, "y": 100, "wires": [ [ "e9e02e8e7b72aa77", "2c7df0f7dd6bd8a3" ] ] }, { "id": "26af269e3cca8953", "type": "debug", "z": "0754510428690e69", "name": "locations", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 1200, "y": 220, "wires": [] }, { "id": "7cd84ff63059f5a7", "type": "inject", "z": "0754510428690e69", "name": "Save Location", "props": [ { "p": "name", "v": "testlocation", "vt": "str" }, { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "wifips01_array", "payloadType": "flow", "x": 150, "y": 220, "wires": [ [ "d662dc6b52df0cd7" ] ] }, { "id": "1e526afed8f9fb99", "type": "trigger", "z": "0754510428690e69", "name": "", "op1": "", "op2": "", "op1type": "nul", "op2type": "payl", "duration": "1", "extend": true, "overrideDelay": false, "units": "s", "reset": "", "bytopic": "all", "topic": "topic", "outputs": 1, "x": 740, "y": 100, "wires": [ [ "ef5d8fb91c816a0e", "99c62d285e31f27f", "8ef55cc4e9de3503", "681ab8ae4f3f4ed3" ] ] }, { "id": "ef5d8fb91c816a0e", "type": "debug", "z": "0754510428690e69", "name": "debug 9", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 940, "y": 140, "wires": [] }, { "id": "d3d51d62a551146f", "type": "function", "z": "0754510428690e69", "name": "find location", "func": "//Expects msg.payload = locations object\n//Expects msg.topic = start with basetopic of scan device\n\n\nvar locations=msg.payload;\n\n\nvar dataarray=flow.get(msg.topic.split(\"/\")[0]+\"_array\");\n\nif (dataarray == undefined) {\n return msg.payload=null;\n}\n\nvar resultlocations={}; //example {\"location1\":10.2,\"location2\":8.3}\n\nfor (const [key, value] of Object.entries(locations)) {\n var testlocation=key;\n var testAPs=value;\n\n var rssi_diff_sum=0;\n //var rssi_diff_count=0;\n var rssi_diff_count=Object.keys(locations).length;\n\n dataarray.forEach((item) => {\n var mac=item[\"mac\"];\n var rssi=item[\"rssi\"];\n\n var testrssi=-100; //if not found at this location use -100\n if (mac in testAPs){\n testrssi = testAPs[mac];\n }\n var rssi_diff=Math.abs(testrssi-rssi);\n //rssi_diff_count+=1;\n rssi_diff_sum+=rssi_diff;\n \n });\n\n var rssi_diff_mean=rssi_diff_sum*1.0/rssi_diff_count;\n if (rssi_diff_count<=0) { //no matches\n rssi_diff_mean=100; //set maximum difference\n }\n\n //resultlocations.push({testlocation:rssi_diff_mean});\n resultlocations[testlocation]=rssi_diff_mean;\n}\n\nlet sortedResultlocations = Object.fromEntries(\n Object.entries(resultlocations).sort(([, a], [, b]) => a - b)\n);\n\nmsg.payload=sortedResultlocations;\n\n//TODO: null rssi_diff_mean rausschmeissen\n\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 470, "y": 380, "wires": [ [ "9a767e8a9bf020ce", "13bb5ace41d6e07c", "aede3fb688284f9e" ] ] }, { "id": "847d66ccd2a10cb5", "type": "inject", "z": "0754510428690e69", "name": "", "props": [ { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "wifips01", "x": 140, "y": 380, "wires": [ [ "8ef55cc4e9de3503" ] ] }, { "id": "4505c1a56ce1d3a1", "type": "debug", "z": "0754510428690e69", "name": "Resultlocations", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 900, "y": 400, "wires": [] }, { "id": "d662dc6b52df0cd7", "type": "function", "z": "0754510428690e69", "name": "make Location", "func": "\n\nvar whitelistSSID=[\"TheaterDo-ATD\"];\n\nvar dataarray=msg.payload;\n\nif (dataarray == undefined) {\n node.payload=null;\n node.error=\"Dataarray is undefined\"\n return msg;\n}\n\n/*\nvar location3={\n \"a0:25:d7:49:2:e0\":-70,\n \"a0:25:d7:45:b1:a0\":-50,\n \"a0:25:d7:45:b1:a3\":-40\n};\n*/\n\n\nvar locationAPs={};\ndataarray.forEach((item) => {\n var mac=item[\"mac\"];\n var rssi=parseFloat(item[\"rssi\"]);\n var ssid=item[\"ssid\"];\n\n if (whitelistSSID.includes(ssid)){\n locationAPs[mac]=rssi;\n }\n});\nif (Object.keys(locationAPs).length<1){\n node.warn(\"not enough APs\");\n node.payload=null;\n node.error=\"not enough APs\"\n return msg;\n}\n\nmsg.payload=locationAPs;\n\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 700, "y": 220, "wires": [ [ "4c6c2d79f6190a56", "510a96a2854515e4", "1a81dd09df0e23f0" ] ] }, { "id": "510a96a2854515e4", "type": "function", "z": "0754510428690e69", "name": "save location", "func": "var newLocation=msg.payload;\nif (msg.name==undefined){\n node.warn(\"No name defined\");\n msg.payload=null;\n msg.error=\"No Name defined\";\n return msg;\n \n}\nvar locationname=msg.name;\n\nvar locations=flow.get(\"locations\");\nif (locations == undefined){\n locations={};\n}\n\n\n\n/*\nvar locations={\n \"location1\":location1,\n \"location2\":location2,\n \"location3\":location3\n};\n*/\n\n\nvar RSSIdifference=0;\nfor (const [key, value] of Object.entries(locations)) {\n var testLocation=value;\n for (const [newLocationMAC, newLocationRSSI] of Object.entries(newLocation)) {\n if (newLocationMAC in testLocation) {\n var testRSSI=testLocation[newLocationMAC];\n RSSIdifference+=Math.abs(parseFloat(newLocationRSSI)-parseFloat(testRSSI));\n }\n }\n}\nif (Object.keys(locations).length<=0){\n RSSIdifference=1000; //some high number, if no locations saved yet\n}\n\nnode.warn(\"Rssi Difference=\"+RSSIdifference);\n\nif (RSSIdifference>0) {\n locations[locationname]=newLocation;\n flow.set(\"locations\",locations);\n}else{\n msg.payload=null;\n msg.error=\"Location Data too similar\";\n return msg;\n}\nmsg.payload=locations;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 950, "y": 220, "wires": [ [ "26af269e3cca8953", "1a81dd09df0e23f0", "b4c7430835b6baf6" ] ] }, { "id": "4c6c2d79f6190a56", "type": "debug", "z": "0754510428690e69", "name": "newLocation", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 890, "y": 260, "wires": [] }, { "id": "b4c7430835b6baf6", "type": "change", "z": "0754510428690e69", "name": "get locations", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "locations", "tot": "flow" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 370, "y": 520, "wires": [ [ "648316b131e4ae5f" ] ] }, { "id": "d59f298d20f6d14e", "type": "inject", "z": "0754510428690e69", "name": "", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 200, "y": 520, "wires": [ [ "b4c7430835b6baf6" ] ] }, { "id": "efea694acc0f31b0", "type": "ui_text_input", "z": "0754510428690e69", "d": true, "name": "", "label": "Location Name", "tooltip": "", "group": "82f7d47b71734deb", "order": 0, "width": 0, "height": 0, "passthru": true, "mode": "text", "delay": 300, "topic": "topic", "sendOnBlur": true, "className": "", "topicType": "msg", "x": 160, "y": 140, "wires": [ [ "3aaad252441b8d5f" ] ] }, { "id": "3f671c86d55c26d7", "type": "change", "z": "0754510428690e69", "name": "", "rules": [ { "t": "set", "p": "name", "pt": "msg", "to": "payload", "tot": "msg" }, { "t": "set", "p": "payload", "pt": "msg", "to": "wifips01_array", "tot": "flow" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 440, "y": 200, "wires": [ [ "d662dc6b52df0cd7" ] ] }, { "id": "1a81dd09df0e23f0", "type": "switch", "z": "0754510428690e69", "name": "is error", "property": "error", "propertyType": "msg", "rules": [ { "t": "nempty" } ], "checkall": "true", "repair": false, "outputs": 1, "x": 1020, "y": 340, "wires": [ [ "0e156c51ae2b4932" ] ] }, { "id": "0e156c51ae2b4932", "type": "ui_text", "z": "0754510428690e69", "d": true, "group": "82f7d47b71734deb", "order": 1, "width": 0, "height": 0, "name": "", "label": "Error", "format": "{{msg.error}}", "layout": "row-spread", "className": "", "style": false, "font": "", "fontSize": 16, "color": "#000000", "x": 1170, "y": 340, "wires": [] }, { "id": "705e8749657f643d", "type": "ui_button", "z": "0754510428690e69", "d": true, "name": "", "group": "82f7d47b71734deb", "order": 2, "width": 0, "height": 0, "passthru": false, "label": "Save", "tooltip": "", "color": "", "bgcolor": "", "className": "", "icon": "", "payload": "locationnameEntered", "payloadType": "flow", "topic": "topic", "topicType": "msg", "x": 150, "y": 180, "wires": [ [ "3f671c86d55c26d7", "011bb9ba8559f5ad" ] ] }, { "id": "3aaad252441b8d5f", "type": "change", "z": "0754510428690e69", "name": "", "rules": [ { "t": "set", "p": "locationnameEntered", "pt": "flow", "to": "payload", "tot": "msg" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 470, "y": 160, "wires": [ [] ] }, { "id": "011bb9ba8559f5ad", "type": "change", "z": "0754510428690e69", "name": "empty", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "", "tot": "str" }, { "t": "set", "p": "error", "pt": "msg", "to": "No Error", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 410, "y": 240, "wires": [ [ "0e156c51ae2b4932" ] ] }, { "id": "648316b131e4ae5f", "type": "function", "z": "0754510428690e69", "name": "Format Locations", "func": "var output=[];\n\nfor (const [key, value] of Object.entries(msg.payload)) {\n \n output.push(key);\n}\nmsg.payload=\"\";\nmsg.options=output;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 510, "y": 580, "wires": [ [ "ba6deb9e533d3196" ] ] }, { "id": "ba6deb9e533d3196", "type": "ui_dropdown", "z": "0754510428690e69", "d": true, "name": "", "label": "", "tooltip": "", "place": "Saved Locations", "group": "82f7d47b71734deb", "order": 3, "width": 0, "height": 0, "passthru": true, "multiple": false, "options": [ { "label": "", "value": "", "type": "str" } ], "payload": "", "topic": "topic", "topicType": "msg", "className": "", "x": 740, "y": 580, "wires": [ [] ] }, { "id": "0a4d865955c17de8", "type": "ui_text", "z": "0754510428690e69", "group": "82f7d47b71734deb", "order": 4, "width": 0, "height": 0, "name": "", "label": "Last Scan", "format": "{{msg.payload}}", "layout": "row-spread", "className": "", "style": false, "font": "", "fontSize": 16, "color": "#000000", "x": 1320, "y": 100, "wires": [] }, { "id": "99c62d285e31f27f", "type": "function", "z": "0754510428690e69", "name": "get time", "func": "var datalasttime = flow.get(msg.topic.split(\"/\")[0] + \"_time\");\nif (datalasttime == undefined) {\n datalasttime=0;\n}\n\nvar date = new Date(datalasttime);\n\nvar year = date.getFullYear();\nvar month = date.getMonth()+1;\nvar day = date.getDate();\nvar hours = date.getHours();\nvar minutes = date.getMinutes();\nvar seconds = date.getSeconds();\n\n// Will display time in 10:30:23 format\nvar formattedTime = year+\"/\"+month+\"/\"+day+\" \"+hours + ':' + minutes + ':' + seconds;\n\nmsg.payload = formattedTime;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1020, "y": 100, "wires": [ [] ] }, { "id": "e023f59b1b8a3696", "type": "inject", "z": "0754510428690e69", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 180, "y": 460, "wires": [ [ "3e08e7a5bfc03e08" ] ] }, { "id": "3e08e7a5bfc03e08", "type": "change", "z": "0754510428690e69", "name": "empty locations", "rules": [ { "t": "set", "p": "locations", "pt": "flow", "to": "{}", "tot": "json" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 380, "y": 460, "wires": [ [ "b4c7430835b6baf6" ] ] }, { "id": "8ef55cc4e9de3503", "type": "change", "z": "0754510428690e69", "name": "get locations", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "locations", "tot": "flow" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 270, "y": 340, "wires": [ [ "d3d51d62a551146f", "97caaa1175e418f2" ] ] }, { "id": "9a767e8a9bf020ce", "type": "ui_text", "z": "0754510428690e69", "d": true, "group": "82f7d47b71734deb", "order": 7, "width": "6", "height": "3", "name": "", "label": "Result Location", "format": "{{msg.payload}}", "layout": "row-spread", "className": "", "style": false, "font": "", "fontSize": 16, "color": "#000000", "x": 1120, "y": 440, "wires": [] }, { "id": "13bb5ace41d6e07c", "type": "function", "z": "0754510428690e69", "name": "Format Result Locations", "func": "var output=\"\";\n\nvar resultsDisplay=3;\nvar first=true;\nfor (const [key, value] of Object.entries(msg.payload)) {\n if (resultsDisplay>0) {\n if (!first) {\n output+=\" >> \";\n }\n output+=key+\" : \"+Math.round(value*100)/100.0;\n resultsDisplay--;\n }\n first=false;\n}\nmsg.payload=output;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 670, "y": 440, "wires": [ [ "9a767e8a9bf020ce", "4505c1a56ce1d3a1" ] ] }, { "id": "1ec4ee6b1732adea", "type": "ui_dropdown", "z": "0754510428690e69", "name": "", "label": "", "tooltip": "", "place": "Result", "group": "82f7d47b71734deb", "order": 3, "width": 0, "height": 0, "passthru": true, "multiple": false, "options": [ { "label": "", "value": "", "type": "str" } ], "payload": "", "topic": "topic", "topicType": "msg", "className": "", "x": 960, "y": 480, "wires": [ [] ] }, { "id": "aede3fb688284f9e", "type": "function", "z": "0754510428690e69", "name": "Format Result Locations Options", "func": "var output=[];\nvar resultsDisplay=3;\n\nfor (const [key, value] of Object.entries(msg.payload)) {\n if (resultsDisplay>0) {\n output.push(key+\" <\"+(Math.round(value*100)/100.0)+\">\");\n }\n resultsDisplay--;\n}\nmsg.payload=output[0]; //preselect first entry\nmsg.options=output;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 700, "y": 480, "wires": [ [ "1ec4ee6b1732adea" ] ] }, { "id": "681ab8ae4f3f4ed3", "type": "function", "z": "0754510428690e69", "name": "get diff time", "func": "var datalasttime = flow.get(msg.topic.split(\"/\")[0] + \"_time\");\nif (datalasttime == undefined) {\n datalasttime=0;\n}\n\nvar now=Date.now();\n\nvar difftime=now-datalasttime;\n\nvar minutesago=Math.round(difftime/1000/60);\n\n\nmsg.payload = Math.floor(minutesago/60)+\"h \"+(minutesago%60)+\"m \" +\"ago\";\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1050, "y": 60, "wires": [ [ "0a4d865955c17de8", "a0d054c65b16ad37" ] ] }, { "id": "fab4563acee10bc2", "type": "inject", "z": "0754510428690e69", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "60", "crontab": "", "once": true, "onceDelay": "1", "topic": "wifips01", "payload": "", "payloadType": "date", "x": 860, "y": 40, "wires": [ [ "681ab8ae4f3f4ed3" ] ] }, { "id": "a0d054c65b16ad37", "type": "debug", "z": "0754510428690e69", "name": "debug 10", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 1180, "y": 140, "wires": [] }, { "id": "97caaa1175e418f2", "type": "debug", "z": "0754510428690e69", "name": "debug 11", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 480, "y": 320, "wires": [] }, { "id": "a745b7ae9493bfcb", "type": "mqtt in", "z": "0754510428690e69", "name": "", "topic": "wifips01/battery", "qos": "2", "datatype": "auto-detect", "broker": "3cae847f35cb5147", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 160, "y": 660, "wires": [ [ "ba12d18406c2e855" ] ] }, { "id": "ba12d18406c2e855", "type": "function", "z": "0754510428690e69", "name": "adc to Volt", "func": "var R1=4700;\nvar R2=10000;\nvar Value=msg.payload;\nmsg.payload=Value*(R1+R2)/(1024/3.3)/R2;\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 370, "y": 660, "wires": [ [ "d08d4cabd9adb21b" ] ] }, { "id": "d08d4cabd9adb21b", "type": "ui_chart", "z": "0754510428690e69", "name": "", "group": "82f7d47b71734deb", "order": 7, "width": 0, "height": 0, "label": "Battery Voltage", "chartType": "line", "legend": "false", "xformat": "dd HH:mm", "interpolate": "linear", "nodata": "", "dot": false, "ymin": "2", "ymax": "4", "removeOlder": "14", "removeOlderPoints": "", "removeOlderUnit": "86400", "cutout": 0, "useOneColor": false, "useUTC": false, "colors": [ "#1f77b4", "#aec7e8", "#ff7f0e", "#2ca02c", "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5" ], "outputs": 1, "useDifferentColor": false, "className": "", "x": 560, "y": 660, "wires": [ [] ] }, { "id": "3cae847f35cb5147", "type": "mqtt-broker", "name": "", "broker": "mqtt.atd.theaterdo.net", "port": "1883", "clientid": "", "autoConnect": true, "usetls": false, "protocolVersion": "4", "keepalive": "60", "cleansession": true, "autoUnsubscribe": true, "birthTopic": "", "birthQos": "0", "birthRetain": "false", "birthPayload": "", "birthMsg": {}, "closeTopic": "", "closeQos": "0", "closeRetain": "false", "closePayload": "", "closeMsg": {}, "willTopic": "", "willQos": "0", "willRetain": "false", "willPayload": "", "willMsg": {}, "userProps": "", "sessionExpiry": "" }, { "id": "82f7d47b71734deb", "type": "ui_group", "name": "Setup", "tab": "677681a63ac18322", "order": 1, "disp": true, "width": "6", "collapse": false, "className": "" }, { "id": "677681a63ac18322", "type": "ui_tab", "name": "WiFi Locations", "icon": "dashboard", "disabled": false, "hidden": true } ]