|
[{"id":"38387c2e.5b3764","type":"tab","label":"Charger Test","disabled":false,"info":"![enter image description here](https://notenoughtech.com/wp-content/uploads/2017/08/thumbnail.jpg)\nThis project measures charging speeds of various chargers and draws curves of the charge profiles. It gathers information via Tasker and uses Dashboard to display it.\n\n - [Complete instructions](https://notenoughtech.com/tasker/tasker-total-charging-time-project-test-chargers/)\n\n**Features**:\n- **charging curves**\n- **total charge time**\n- **charger score**\n- **multiple chargers and phones supported**\n- **record managment: draw/delete/clear**\n\n\n## Requirements\n\n - node-red-contrib-dashboard\n - node-red-node-ui-table\n - Tasker installed on Android device\n\n\n# Settings\n\n - **CT_PhoneData** set details of your phone and HTTP credentials in this Tasker task first.\n \n ## More about me:\n\nIf you want to get the latest updates to this project you can follow me via your preferred social media:\n\n- [Facebook](https://www.facebook.com/NotEnoughTECH/)\n- [Twitter](https://twitter.com/NotEnoughTECH)\n- [Instagram](https://www.instagram.com/notenoughtech/)\n- [YouTube](https://www.youtube.com/user/Polepositionpage)\n\nAnd if you feeling like buying me a coffee or supporting me in a more continuous way:\n\n- [Paypal](https://www.paypal.me/notenoughtech)\n- [Patreon](https://www.patreon.com/NotEnoughTECH)\n\nI hope you have enjoyed the project!"},{"id":"1bf473a9.3af3ac","type":"group","z":"38387c2e.5b3764","name":"User Interface","style":{"label":true,"fill":"#e3f3d3"},"nodes":["de692c8e.7149a","8133fc9.5e72f","95c3ba63.9dec88","3d6b873b.ca1068","7cafb6b9.9bd0c8","b893e3e6.12b0f","92f413cb.4ee0c","6c60ed5b.2f5d84","64fc809.a7a668","432f0b9f.1ca2f4","3fc6112e.a6179e","c3fefe14.c14cc","d9effcb1.b4df3","68395b1.30f2ca4","7ccf6d01.ee9204","df4b776e.135918","8574e056.c70bc","441bea06.bd51e4","68cd8d36.b48dd4","ea7409af.c4a988","a3ced19.7d6763"],"x":594,"y":119,"w":762,"h":342},{"id":"4f94bc50.0a5624","type":"http in","z":"38387c2e.5b3764","name":"","url":"/charger","method":"post","upload":false,"swaggerDoc":"","x":110,"y":320,"wires":[["cf74b415.1f1338","ee4db074.fce2e","adc24b7b.0f9b88"]]},{"id":"cf74b415.1f1338","type":"http response","z":"38387c2e.5b3764","name":"","statusCode":"","headers":{},"x":330,"y":260,"wires":[]},{"id":"ee4db074.fce2e","type":"function","z":"38387c2e.5b3764","name":"Chart format","func":"function sec2min(ms){\n sec = Math.floor(ms /1000)\n let min = Math.floor(sec/60);\n let s = sec%60;\n if(s < 10){s = \"0\"+s;}\n time = min + \":\" + s;\n return time;\n}\n\n// add new data to the array\nvar ChargeData = flow.get(\"ChargeData\");\nvar data = msg.payload;\nChargeData.push(data);\nflow.set(\"ChargeData\", ChargeData);\n\nvar dataSeries =[]; \nvar dataLabels=[];\nvar dataData =[];\nvar array = {};\nvar arrayTime = [];\nvar arrayLevel = [];\n\nfor(var x in data.timestamp){\n let level = data.level[x];\n let time = sec2min(data.timestamp[x]-data.chargeStart);\n arrayLevel.push(level);\n arrayTime.push(time);\n}\n dataSeries.push(data.name);\n dataData.push(arrayLevel);\n dataLabels = arrayTime;\n\n\n\n// chart formated data\narray.series = dataSeries; // topic chargers names\narray.data = dataData; // levels of the battery\narray.labels = dataLabels; //time time \n\n\n\nreturn {payload:[array]};\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":350,"y":300,"wires":[["c76721c3.9c31e"]]},{"id":"adc24b7b.0f9b88","type":"function","z":"38387c2e.5b3764","name":"Table format","func":"var chargers = flow.get(\"chargers\");\n\nif(chargers === undefined){\n chargers = [];\n}\n\n//delete and update the table\nif(msg.topic === \"delete\"){\n msg.payload = chargers;\n flow.set(\"chargers\", chargers);\n return msg;\n}\n// add new record to the table\n\nvar data = msg.payload;\nvar update = { \"Charger name\": data.name,\n \"Phone name\": data.phone,\n \"charging protocol\": data.proto,\n \"battery (mAh)\": data.battery ,\n \"charge time\": data.chargeDelta,\n \"score (mAh/min)\": data.score\n };\n\nchargers.push(update);\nflow.set(\"chargers\", chargers);\nvar msg1 = {payload: []};\nvar msg2 = {payload: chargers};\n\nreturn [[msg1,msg2]];\n\n \n","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is deployed.\n\nvar array = [];\nvar x = flow.get(\"chargers\");\nif (x === undefined){\n flow.set(\"chargers\", array); \n}\n \nvar array2 = [];\nvar y = flow.get(\"ChargeData\");\nif (y === undefined){\n flow.set(\"ChargeData\", array2);\n}\n\nvar array3 = [];\nvar z = flow.get(\"selection\");\nif (z === undefined){\n flow.set(\"selection\", array3);\n}\n ","finalize":"","x":350,"y":340,"wires":[["5ba2af25.252dd"]]},{"id":"c3fefe14.c14cc","type":"change","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"str"},{"t":"set","p":"selection","pt":"flow","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1180,"y":420,"wires":[["7ccf6d01.ee9204"]]},{"id":"de692c8e.7149a","type":"ui_dropdown","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","label":"","tooltip":"","place":"Select dataset","group":"3d9e45e.bcd50ba","order":2,"width":0,"height":0,"passthru":false,"multiple":true,"options":[],"payload":"","topic":"topic","topicType":"msg","x":980,"y":280,"wires":[["3fc6112e.a6179e"]]},{"id":"8133fc9.5e72f","type":"inject","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":690,"y":280,"wires":[["95c3ba63.9dec88"]]},{"id":"95c3ba63.9dec88","type":"function","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"Make list","func":"var chargedata = flow.get(\"ChargeData\");\nvar data =[];\n\n\nfor(let x =0; x < chargedata.length; x++ ){\n let y = chargedata[x].name;\n let z = {};\n z[y] = x;\n data.push(z);\n}\n\nmsg.options = data;\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":840,"y":280,"wires":[["de692c8e.7149a"]]},{"id":"3d6b873b.ca1068","type":"function","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"Send data","func":"var action = msg.payload;\nvar selection = flow.get(\"selection\");\nvar data = flow.get(\"ChargeData\");\nvar dataChargers = flow.get(\"chargers\");\n\nfunction sec2min(ms){\n sec = Math.floor(ms /1000)\n let min = Math.floor(sec/60);\n let s = sec%60;\n if(s < 10){s = \"0\"+s;}\n time = min + \":\" + s;\n return time;\n}\n\n// if selection is valid and action is to display chart (true)\nif(selection.length > 0){\n if(action === true){\n \n var index = selection;\n var dataSeries =[]; \n var dataLabels=[];\n var dataData =[];\n var array = {};\n \n for(var i =0; i<index.length; i++){\n var datatimestamp = data[index[i]].timestamp;\n var datalevel = data[index[i]].level;\n var labels = data[index[i]].name;\n var arrayTime = [];\n var arrayLevel = [];\n \n for(var x in datatimestamp){\n let level = datalevel[x];\n let time = sec2min(datatimestamp[x]-data[index[i]].chargeStart);\n arrayLevel.push(level);\n arrayTime.push(time);\n }\n dataSeries.push(data[index[i]].name);\n dataData.push(arrayLevel);\n dataLabels = arrayTime;\n }\n array.series = dataSeries; // topic chargers names\n array.data = dataData; // levels of the battery\n array.labels = dataLabels; //time time \n \n return [{payload:[array]}, null];\n }\n if(action === false) {\n for( var r = 0; r < selection.length; r++){\n //remove and squash chargedata\n delete data[selection[r]];\n var squash1 = data.filter(function (el) {return el != null;});\n flow.set(\"ChargeData\", squash1);\n //remove and squash charger info\n delete dataChargers[selection[r]];\n var squash2 = dataChargers.filter(function (el) {return el != null;});\n flow.set(\"chargers\", squash2);\n msg.topic = \"delete\";\n }\n return[null, msg];\n }\n}\n\n\n\nvar filtered = array.filter(function (el) {\n return el != null;\n});","outputs":2,"noerr":0,"initialize":"","finalize":"","x":1170,"y":320,"wires":[["a3ced19.7d6763"],["68395b1.30f2ca4"]]},{"id":"7cafb6b9.9bd0c8","type":"ui_chart","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","group":"3d9e45e.bcd50ba","order":1,"width":0,"height":0,"label":"Charging curve","chartType":"line","legend":"true","xformat":"mm:ss","interpolate":"bezier","nodata":"Select Charging data","dot":false,"ymin":"","ymax":"110","removeOlder":"0","removeOlderPoints":"1000","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"x":1220,"y":160,"wires":[[]]},{"id":"b893e3e6.12b0f","type":"ui_button","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","group":"3d9e45e.bcd50ba","order":6,"width":4,"height":1,"passthru":false,"label":"Clear Chart","tooltip":"","color":"","bgcolor":"pink","icon":"","payload":"[]","payloadType":"json","topic":"topic","topicType":"msg","x":810,"y":160,"wires":[["441bea06.bd51e4"]]},{"id":"92f413cb.4ee0c","type":"ui_table","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","group":"3d9e45e.bcd50ba","name":"","order":7,"width":12,"height":5,"columns":[],"outputs":0,"cts":false,"x":1190,"y":200,"wires":[]},{"id":"6c60ed5b.2f5d84","type":"ui_button","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","group":"3d9e45e.bcd50ba","order":8,"width":7,"height":1,"passthru":false,"label":"Clear Whole Table","tooltip":"","color":"","bgcolor":"pink","icon":"","payload":"[]","payloadType":"json","topic":"topic","topicType":"msg","x":790,"y":200,"wires":[["68cd8d36.b48dd4"]]},{"id":"64fc809.a7a668","type":"ui_button","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","group":"3d9e45e.bcd50ba","order":5,"width":8,"height":1,"passthru":false,"label":"Add to Chart","tooltip":"","color":"","bgcolor":"green","icon":"","payload":"true","payloadType":"bool","topic":"topic","topicType":"msg","x":970,"y":340,"wires":[["3d6b873b.ca1068"]]},{"id":"432f0b9f.1ca2f4","type":"ui_button","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","group":"3d9e45e.bcd50ba","order":9,"width":5,"height":1,"passthru":false,"label":"Remove Selected Records","tooltip":"","color":"","bgcolor":"red","icon":"","payload":"false","payloadType":"bool","topic":"topic","topicType":"msg","x":920,"y":380,"wires":[["3d6b873b.ca1068"]]},{"id":"3fc6112e.a6179e","type":"function","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"Save selection","func":"flow.set(\"selection\", msg.payload);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1180,"y":280,"wires":[[]]},{"id":"d9effcb1.b4df3","type":"link in","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","links":["68395b1.30f2ca4"],"x":1015,"y":420,"wires":[["c3fefe14.c14cc"]]},{"id":"68395b1.30f2ca4","type":"link out","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","links":["d9effcb1.b4df3","ff8d0b6e.1c3a58"],"x":1315,"y":360,"wires":[]},{"id":"df4b776e.135918","type":"link in","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","links":["7ccf6d01.ee9204","c76721c3.9c31e"],"x":715,"y":340,"wires":[["95c3ba63.9dec88"]]},{"id":"7ccf6d01.ee9204","type":"link out","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","links":["df4b776e.135918"],"x":1315,"y":420,"wires":[]},{"id":"ff8d0b6e.1c3a58","type":"link in","z":"38387c2e.5b3764","name":"","links":["68395b1.30f2ca4"],"x":215,"y":380,"wires":[["adc24b7b.0f9b88"]]},{"id":"c76721c3.9c31e","type":"link out","z":"38387c2e.5b3764","name":"","links":["8574e056.c70bc","df4b776e.135918"],"x":475,"y":300,"wires":[]},{"id":"8574e056.c70bc","type":"link in","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","links":["c76721c3.9c31e","441bea06.bd51e4","a3ced19.7d6763"],"x":1035,"y":160,"wires":[["7cafb6b9.9bd0c8"]]},{"id":"441bea06.bd51e4","type":"link out","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","links":["8574e056.c70bc"],"x":935,"y":160,"wires":[]},{"id":"ea7409af.c4a988","type":"link in","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","links":["68cd8d36.b48dd4","5ba2af25.252dd"],"x":1035,"y":200,"wires":[["92f413cb.4ee0c"]]},{"id":"68cd8d36.b48dd4","type":"link out","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","links":["ea7409af.c4a988"],"x":935,"y":200,"wires":[]},{"id":"5ba2af25.252dd","type":"link out","z":"38387c2e.5b3764","name":"","links":["ea7409af.c4a988"],"x":475,"y":340,"wires":[]},{"id":"a3ced19.7d6763","type":"link out","z":"38387c2e.5b3764","g":"1bf473a9.3af3ac","name":"","links":["8574e056.c70bc"],"x":1315,"y":300,"wires":[]},{"id":"3d9e45e.bcd50ba","type":"ui_group","name":"Charging Stats","tab":"f484a0a.6c67a6","order":1,"disp":true,"width":"12","collapse":false},{"id":"f484a0a.6c67a6","type":"ui_tab","name":"Charging Profiles","icon":"dashboard","disabled":false,"hidden":false}] |
Updated flow to keep the persistent data across the reboots of the server