2020年11月30日 星期一

Store IOT Data in SQLite Database in Node-Red

 Store IOT Data in SQLite Database  Node-Red

儲存物聯網資料使用SQLite資料庫節點元件


參考來源 http://www.steves-internet-guide.com/storing-iot-data-sql-database/


var n1 = Math.round( Math.random() *100)

var n2 = Math.round( Math.random() *100)

var n3 = Math.round( Math.random() *100)

var sensor="sensor"+n1;

msg="( timestamp,sensor,temperature,humidity) values(" + "\'"+ n1 +"\'"+",\'"+sensor +"\'" +",\'"+ n2 +"\'"+",\'" +n3 + "\'"+")";

var topic="INSERT INTO DATA " +msg;

var msg1={};

msg1.topic=topic;

return msg1;


JSON encoded data is also a text string and so can also be stored directly in the database, but more commonly you will want to extract parts of the data to use as database keys (column names).


The easiest way to see this is by doing an example. Let’s assume our incoming data payload looked like this:

sensor1,temperature,20,humidity,71

So what we have is a device called sensor1 and two key/value pairs:

temperature=20 and humidity=71

To store this data in a data base we first need a database and a table.

So lets create a database called test.db and a table called sensor_data.

Now a table consists of rows and columns. To create a row we need to add elements to the columns. To do that we need to assign names to the columns.

In our example we would need three columns called:

  • sensor
  • temperature
  • humidity

We also need to assign a data type to the values, in our case sensor would be TEXT and temperature and humidity would be Integers (INT)

When we add our data to the table the table would look like this:

SensorTemperatureHumidity
sensor12071

Note: Column names are not case sensitive.


The following code snippet shows how we do this:

var data="sensor1,temperature,20,humidity,71";
//extract elements from data
var sensor=data[0];
var temperature=data[3];
var humidity=data[5];

//create SQL command
msg="(sensor,temperature,humidity) values("+",\'"+sensor +"\'," + temperature + "," + humidity +")";
var topic="INSERT INTO DATA " +msg;
var msg1={}; //create new msg object
//The SQlite node expects the command in the topic field
msg1.topic=topic;
return msg1;

The interesting and most important point when  constructing the command is that text values need to be in quotes, and because we are constructing a string we need to escape them. So we have:

var n1 = Math.round( Math.random() *100)

var n2 = Math.round( Math.random() *100)

var n3 = Math.round( Math.random() *100)

var sensor="sensor"+n1;

msg="( timestamp,sensor,temperature,humidity) values(" + "\'"+ n1 +"\'"+",\'"+sensor +"\'" +",\'"+ n2 +"\'"+",\'" +n3 + "\'"+")";

var topic="INSERT INTO DATA " +msg;

var msg1={};

msg1.topic=topic;

return msg1;







[{"id":"64defb82.112a54","type":"inject","z":"4388b775.bc0d98","name":"新增資料表","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"CREATE TABLE data(TIMESTAMP INT PRIMARY KEY NOT NULL, SENSOR TEXT NOT NULL, TEMPERATURE INT NOT NULL, HUMIDITY INT NOT NULL)","payload":"","payloadType":"date","x":100,"y":160,"wires":[["4e4d5e15.d9b4e"]]},{"id":"61312ba3.11be74","type":"debug","z":"4388b775.bc0d98","name":"database_out","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":720,"y":160,"wires":[]},{"id":"f264f7ef.23e548","type":"inject","z":"4388b775.bc0d98","name":"新增資料(insert data)","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"6","crontab":"","once":false,"onceDelay":"","topic":"","payload":"","payloadType":"date","x":140,"y":420,"wires":[["3e0c60b7.f7233"]]},{"id":"1ccfef20.182591","type":"function","z":"4388b775.bc0d98","name":"Insert","func":"var newMsg = {\n \"topic\": \"INSERT INTO data ( timestamp,sensor,temperature,humidity) values(0,'sensor',20,66)\"\n};\n\nreturn newMsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":270,"y":360,"wires":[["4e4d5e15.d9b4e","bad7234c.4b05a"]]},{"id":"6903e50f.e8116c","type":"inject","z":"4388b775.bc0d98","name":"刪除記錄(Record)","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"DELETE FROM DATA WHERE TIMESTAMP>=0","payload":"","payloadType":"date","x":120,"y":220,"wires":[["4e4d5e15.d9b4e"]]},{"id":"e070472b.987f38","type":"inject","z":"4388b775.bc0d98","name":"檢視資料庫Records","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"30","crontab":"","once":true,"onceDelay":"","topic":"SELECT * FROM DATA ORDER BY TIMESTAMP DESC LIMIT 100","payload":"","payloadType":"date","x":140,"y":100,"wires":[["bab4327d.23b35"]]},{"id":"a4a93a5c.1110b8","type":"ui_template","z":"4388b775.bc0d98","group":"50aecc4e.588bc4","name":"UI Table","order":1,"width":"","height":"","format":"<style>\n.table\n{\n    height:400px;\n    width:550px;\n    background:blue;\n}\n</style>\n<div class=\"table\">\n<table style=\"width:100%\">\n  <tr>\n    <th>TIMESTAMP</th> \n    <th>SENSOR</th>\n    <th>TEMPERATURE</th> \n    <th>HUMIDITY</th>\n  \n  </tr>\n  <tr ng-repeat=\"x in msg.payload | limitTo:20\">\n    <td>{{msg.payload[$index].TIMESTAMP}}</td>\n    <td>{{msg.payload[$index].SENSOR}}</td>\n    <td>{{msg.payload[$index].TEMPERATURE}}</td> \n    <td>{{msg.payload[$index].HUMIDITY}}</td>\n\n  </tr>\n</table>\n</div>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":560,"y":100,"wires":[[]]},{"id":"4e4d5e15.d9b4e","type":"sqlite","z":"4388b775.bc0d98","mydb":"70b352c7.b98d9c","sqlquery":"msg.topic","sql":"","name":"","x":490,"y":160,"wires":[["61312ba3.11be74"]]},{"id":"93f32cf2.9a888","type":"inject","z":"4388b775.bc0d98","name":"測試資料","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":460,"wires":[["fcd54242.d9e77"]]},{"id":"fcd54242.d9e77","type":"function","z":"4388b775.bc0d98","name":"test data","func":"var count=context.get('count');\nvar timestamp=context.get('timestamp');\n\nif (count==undefined)\n{\n    count=1;\n    timestamp=1;\n}\nvar data1={\"sensor\":\"sensor1\",\"temperature\":21,\"humidity\":61};\n//var data2={\"sensor\":\"sensor2\",\"temperature\":22,\"humidity\":62};\n//var data3={\"sensor\":\"sensor3\",\"temperature\":23,\"humidity\":63};\nif (count%20==0)\n    count=-count;\ndata1.temperature+=(count*.25);\n//data2.temperature+=(count*.5);\n//data3.temperature+=(count*.75);\ndata1.humidity+=(count*.25);\n//data2.humidity+=(count*.5);\n//data3.humidity+=(count*.75);\nmsg.payload=[data1];\nvar msg1={};\nvar msg2={};\nvar msg3={};\n\ndata1.timestamp=timestamp;\n//timestamp+=1;\n//data2.timestamp=timestamp;\n//timestamp+=1;\n//data3.timestamp=timestamp;\n\nmsg1.payload=data1;\n//msg2.payload=data2;\n//msg3.payload=data3;\ntimestamp+=1;\ncount+=1;\ncontext.set('count',count);\ncontext.set('timestamp',timestamp);\nreturn msg1;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":260,"y":460,"wires":[["98dd95f0.5ebc48","474f6647.47b828"]]},{"id":"98dd95f0.5ebc48","type":"debug","z":"4388b775.bc0d98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":410,"y":500,"wires":[]},{"id":"474f6647.47b828","type":"function","z":"4388b775.bc0d98","name":"write query","func":"var timestamp=msg.payload.timestamp;\nvar sensor=msg.payload.sensor;\nvar temperature=msg.payload.temperature;\nvar humidity=msg.payload.humidity;\n//put data into json string\n\nmsg=\"( timestamp,sensor,temperature,humidity) values(\"+timestamp +\",\\'\"+sensor +\"\\',\" + temperature + \",\" + humidity +\")\";\nvar topic=\"INSERT INTO DATA \" +msg;\nvar msg1={};\nmsg1.topic=topic;\nmsg1.payload=timestamp;\nreturn msg1;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":430,"y":460,"wires":[["22d9a3fb.73a56c","e2c9013c.09a4e"]]},{"id":"22d9a3fb.73a56c","type":"debug","z":"4388b775.bc0d98","name":"sql out","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":590,"y":500,"wires":[]},{"id":"3e0c60b7.f7233","type":"function","z":"4388b775.bc0d98","name":"Insert using variable","func":"\nvar n1 = Math.round( Math.random() *100)\nvar n2 = Math.round( Math.random() *100)\nvar n3 = Math.round( Math.random() *100)\nvar sensor=\"sensor\"+n1;\n\nmsg=\"( timestamp,sensor,temperature,humidity) values(\" + \"\\'\"+ n1 +\"\\'\"+\",\\'\"+sensor +\"\\'\" +\",\\'\"+ n2 +\"\\'\"+\",\\'\" +n3 + \"\\'\"+\")\";\nvar topic=\"INSERT INTO DATA \" +msg;\nvar msg1={};\nmsg1.topic=topic;\n\nreturn msg1;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":360,"y":420,"wires":[["4e4d5e15.d9b4e","bad7234c.4b05a"]]},{"id":"bad7234c.4b05a","type":"debug","z":"4388b775.bc0d98","name":"insert","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":410,"y":360,"wires":[]},{"id":"bab4327d.23b35","type":"sqlite","z":"4388b775.bc0d98","mydb":"70b352c7.b98d9c","sqlquery":"msg.topic","sql":"","name":"","x":400,"y":100,"wires":[["a4a93a5c.1110b8"]]},{"id":"584b13cc.c4fd7c","type":"catch","z":"4388b775.bc0d98","name":"","scope":null,"uncaught":false,"x":110,"y":580,"wires":[["77d3ce1d.e3501","662fbf18.adeac"]]},{"id":"77d3ce1d.e3501","type":"debug","z":"4388b775.bc0d98","name":"error","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":270,"y":620,"wires":[]},{"id":"8ecc64f.df2bc98","type":"ui_text","z":"4388b775.bc0d98","group":"50aecc4e.588bc4","order":7,"width":0,"height":0,"name":"","label":"text","format":"{{msg.payload}}","layout":"row-spread","x":410,"y":580,"wires":[]},{"id":"e2c9013c.09a4e","type":"delay","z":"4388b775.bc0d98","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":600,"y":460,"wires":[["4e4d5e15.d9b4e"]]},{"id":"662fbf18.adeac","type":"function","z":"4388b775.bc0d98","name":"sql errors","func":"var payload=msg.error.message;\nmsg.payload = payload +\" timestamp \"+msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":280,"y":580,"wires":[["8ecc64f.df2bc98"]]},{"id":"a914a25c.3ba78","type":"inject","z":"4388b775.bc0d98","name":"刪除資料表(Drop Table)","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"","topic":"drop table data","payload":"","payloadType":"date","x":140,"y":280,"wires":[["4e4d5e15.d9b4e"]]},{"id":"bb56c0e9.201d7","type":"inject","z":"4388b775.bc0d98","name":"新增資料(Insert)","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":360,"wires":[["1ccfef20.182591"]]},{"id":"5e49b898.b95c88","type":"function","z":"4388b775.bc0d98","name":"Clear errors","func":"node.error(\"\",msg);//clear error\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":270,"y":520,"wires":[[]]},{"id":"9f876ef5.9140c","type":"inject","z":"4388b775.bc0d98","name":"清除錯誤","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":100,"y":520,"wires":[["5e49b898.b95c88"]]},{"id":"577e872e.08e478","type":"inject","z":"4388b775.bc0d98","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":1360,"wires":[["853a649c.0297e8"]]},{"id":"853a649c.0297e8","type":"function","z":"4388b775.bc0d98","name":"","func":"var data={};\ndata[\"temp\"]=20;\ndata[\"humidity\"]=50;\njson_out=JSON.stringify(data);\nreturn msg;","outputs":1,"noerr":0,"x":270,"y":1400,"wires":[[]]},{"id":"643da8f4.1170c8","type":"comment","z":"4388b775.bc0d98","name":"","info":"關係資料庫的層次結構可以分為四級:資料庫(Database)、表(Table)與視圖、記錄(Record)和欄位(Field)","x":70,"y":60,"wires":[]},{"id":"21f95e2a.98ba32","type":"comment","z":"4388b775.bc0d98","name":"","info":"Drop Table 刪除表定義及其所有的數據,索引,觸發器,約束和權限規範","x":70,"y":320,"wires":[]},{"id":"50aecc4e.588bc4","type":"ui_group","z":"","name":"Sensors","tab":"d4d6ffe9.c20be","order":1,"disp":true,"width":"12","collapse":false},{"id":"70b352c7.b98d9c","type":"sqlitedb","z":"","db":"test20201130.db","mode":"RWC"},{"id":"d4d6ffe9.c20be","type":"ui_tab","z":"","name":"Home","icon":"dashboard"}]

Node-Red SQLite 範例

 Node-Red  SQLite 範例

產生資料庫Create

CREATE TABLE RFID ( id INT PRIMARY KEY NOT NULL, current_time TEXT , uid_name TEXT)

插入資料庫的資料

msg.topic = "INSERT INTO RFID (id,current_time, uid_name) VALUES (?,?,?)";

var Today = new Date();

var yyyy = Today.getFullYear(); //年

var MM = Today.getMonth()+1;    //月

var dd = Today.getDate();       //日

var h = Today.getHours();       //時

var m = Today.getMinutes();     //分

var s = Today.getSeconds();     //秒

if(MM<10)

{

   MM = '0'+MM;

}

if(dd<10)

{

   dd = '0'+dd;

}

if(h<10)

{

   h = '0'+h;

}

if(m<10)

{

  m = '0' + m;

}

if(s<10)

{

  s = '0' + s;

}

var hms= yyyy + '/'+ MM + '/'+ dd + ' ' + h + ':' + m + ':' + s ;

var id= Date.now() ;

msg.payload = [id ,hms, msg.payload];

return msg;


檢視資料庫

SELECT * FROM RFID ORDER BY  id  DESC LIMIT 100;


顯示樣板

<table style="width:100%">

  <tr>

    <th>ID    </th> 

    <th>時 間 </th> 

    <th>卡 號 </th>

  </tr>

  <tr ng-repeat="x in msg.payload | limitTo:20">

    <td>{{$index}}</td>

    <td>{{msg.payload[$index].current_time}}</td>

    <td>{{msg.payload[$index].uid_name}}</td> 

  </tr>

</table>


檔案目錄 C:\Users\alex\AppData\Roaming\npm
SQLite檔案名稱 RFID2020_1130.db






// N0de-Red程式

[{"id":"1909ec67.e04a64","type":"debug","z":"18a9e5f7.6c481a","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":710,"y":120,"wires":[]},{"id":"e202150a.adf688","type":"sqlite","z":"18a9e5f7.6c481a","mydb":"e77b6c54.4f02","sqlquery":"msg.topic","sql":"","name":"SQLITE_Example","x":510,"y":120,"wires":[["1909ec67.e04a64"]]},{"id":"d853a446.d7ed78","type":"sqlite","z":"18a9e5f7.6c481a","mydb":"e77b6c54.4f02","sqlquery":"msg.topic","sql":"","name":"SQLITE_Example","x":450,"y":300,"wires":[["e8a8b129.c8ad6"]]},{"id":"697d90a6.eefc5","type":"ui_button","z":"18a9e5f7.6c481a","name":"","group":"b165cbf1.03d608","order":50,"width":"2","height":"2","passthru":false,"label":"新增 卡號1","tooltip":"","color":"","bgcolor":"","icon":"","payload":"Alex_test1","payloadType":"str","topic":"","x":150,"y":80,"wires":[["73137d5.4a9ce84"]]},{"id":"c36997b.25b3868","type":"ui_button","z":"18a9e5f7.6c481a","name":"","group":"b165cbf1.03d608","order":51,"width":"2","height":"2","passthru":false,"label":"新增 卡號2","tooltip":"","color":"","bgcolor":"blue","icon":"","payload":"RFIDAlex_test2","payloadType":"str","topic":"","x":150,"y":120,"wires":[["73137d5.4a9ce84"]]},{"id":"e12f3f08.e6d9a","type":"ui_button","z":"18a9e5f7.6c481a","name":"","group":"b165cbf1.03d608","order":8,"width":0,"height":0,"passthru":false,"label":"刪除所有的資料","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"DELETE from RFID","x":160,"y":180,"wires":[["e202150a.adf688"]]},{"id":"73137d5.4a9ce84","type":"function","z":"18a9e5f7.6c481a","name":"INSERT","func":"msg.topic = \"INSERT INTO RFID (id,current_time, uid_name) VALUES (?,?,?)\";\n\nvar Today = new Date();\nvar yyyy = Today.getFullYear(); //年\nvar MM = Today.getMonth()+1;    //月\nvar dd = Today.getDate();       //日\nvar h = Today.getHours();       //時\nvar m = Today.getMinutes();     //分\nvar s = Today.getSeconds();     //秒\n\nif(MM<10)\n{\n   MM = '0'+MM;\n}\n\nif(dd<10)\n{\n   dd = '0'+dd;\n}\n\nif(h<10)\n{\n   h = '0'+h;\n}\n\nif(m<10)\n{\n  m = '0' + m;\n}\n\nif(s<10)\n{\n  s = '0' + s;\n}\nvar hms= yyyy + '/'+ MM + '/'+ dd + ' ' + h + ':' + m + ':' + s ;\nvar id= Date.now() ;\nmsg.payload = [id ,hms, msg.payload];\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":320,"y":100,"wires":[["e202150a.adf688","8f7e0ad3.3163f8"]]},{"id":"8f7e0ad3.3163f8","type":"ui_text","z":"18a9e5f7.6c481a","group":"b165cbf1.03d608","order":10,"width":0,"height":0,"name":"","label":"資料表","format":"{{msg.payload}}","layout":"row-left","x":470,"y":60,"wires":[]},{"id":"f30e2ef6.8fa1b","type":"ui_button","z":"18a9e5f7.6c481a","name":"","group":"b165cbf1.03d608","order":10,"width":"2","height":"2","passthru":false,"label":"檢視資料庫","tooltip":"","color":"","bgcolor":"orange","icon":"","payload":"","payloadType":"str","topic":"SELECT * FROM RFID ORDER BY  id  DESC LIMIT 100;","x":150,"y":300,"wires":[["d853a446.d7ed78"]]},{"id":"e8a8b129.c8ad6","type":"ui_template","z":"18a9e5f7.6c481a","group":"b165cbf1.03d608","name":"","order":0,"width":"12","height":"4","format":"<table style=\"width:100%\">\n  <tr>\n    <th>ID    </th> \n    <th>時 間 </th> \n    <th>卡 號 </th>\n  </tr>\n  <tr ng-repeat=\"x in msg.payload | limitTo:20\">\n    <td>{{$index}}</td>\n    <td>{{msg.payload[$index].current_time}}</td>\n    <td>{{msg.payload[$index].uid_name}}</td> \n  </tr>\n</table>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":640,"y":300,"wires":[[]]},{"id":"ab89d10b.421d4","type":"ui_button","z":"18a9e5f7.6c481a","name":"","group":"b165cbf1.03d608","order":11,"width":"6","height":"2","passthru":false,"label":"建立資料庫(只能執行一次)","tooltip":"","color":"orange","bgcolor":" purple","icon":"","payload":"","payloadType":"str","topic":"CREATE TABLE RFID ( id INT PRIMARY KEY NOT NULL, current_time TEXT , uid_name TEXT)","x":190,"y":240,"wires":[["e202150a.adf688"]]},{"id":"e77b6c54.4f02","type":"sqlitedb","z":"","db":"RFID2020_1130.db","mode":"RWC"},{"id":"b165cbf1.03d608","type":"ui_group","z":"","name":"Data","tab":"7a15eb23.c05f34","order":3,"disp":true,"width":"6","collapse":false},{"id":"7a15eb23.c05f34","type":"ui_tab","z":"","name":"SQlite_2020_0720","icon":"dashboard","disabled":false,"hidden":false}]

2020年11月29日 星期日

Using SQLite with Node-RED on Windows

 Using SQLite with Node-RED on Windows

源自於 https://github.com/mpolinowski/nodered-sqlite

Installing SQLite

First scroll down to the newest pre-compiled version for your Operating System here and choose the bundle of command-line tools for managing SQLite database files, including the command-line shell program, the sqldiff.exe program, and the sqlite3_analyzer.exe program.

Unzip the folder, rename it something short - e.g. sqlite3 - and copy it to your C:\ partition. Now add the installation path to your system variables and run the sqlite3 command to see that it is working:

SQLite

To exit the SQLite Shell again, type .quit

Creating your first Database

Navigate to the directory you want to store your data and type sqlite3 mydb.db and .databases:

SQLite

To add a table, type in the following create table cameras (id INT primary key);. This will create a table named cameras with a single (primary) column with the name of id that expects an integer value.

Installing SQLite in Node-RED

Open the Manage Palette menu inside Node-RED, switch to the Install tab and search for node-red-node-sqlite. More information can be found here. A new node called sqlite should appear on the left under the storage tab. In this flow, you’re going to send 5 SQL queries (CREATE, INSERT, SELECT, DELETE and DROP) to your SQLite database:

SQLite

Doubleclick the SQLite Node press the Add new sqlitedb button and type in the absolute path to the SQLite Database we created earlier

SQLite

Configure your CREATE Inject Node as follows:

CREATE TABLE dhtreadings(id INTEGER PRIMARY KEY AUTOINCREMENT, temperature NUMERIC, humidity NUMERIC, currentdate DATE, currenttime TIME, device TEXT)

SQLite

Repeat this step to create the following :

INSERT inject node

INSERT INTO dhtreadings(temperature, humidity, currentdate, currenttime, device) values(22.4, 48, date('now'), time('now'), "manual")

SELECT inject node with

SELECT * FROM dhtreadings

DELETE inject node as follows

DELETE from dhtreadings

DROP inject node

DROP TABLE dhtreadings

To save your application, you need to click the Deploy button on the top right corner (You might have to restart Node-RED) and your application is saved and ready. Open the debug window and press the first inject node to trigger the CREATE SQL query:

SQLite

Visualizing Data from SQLite in Node-RED Dashboard

We are able to visualize the data by using the dashboard nodes.

Injecting SELECT * FROM dhtreadings into our SQLite node gives us an array of records in the response, we can simply use the ui template node to parse the information we want.

SQLite

For example, we would like to have a table showing the first 2 records, just simply connect the template UI node to the SQLite node:

SQLite

In the template node, enter the following code:

<table style="width:100%">
  <tr>
    <th>Time</th> 
    <th>Temp</th> 
    <th>Hum</th>
  </tr>
  <tr ng-repeat="x in msg.payload | limitTo:2">
    <td>{{msg.payload[$index].currenttime}}</td>
    <td>{{msg.payload[$index].temperature}}</td> 
    <td>{{msg.payload[$index].humidity}}</td>
  </tr>
</table>

SQLite

This code simply a table in HTML, and places the index, currenttime, temperature and humidity fields from msg.payload into the appropriate cells of the table using ng-repeat & limitTo. Once you deploy the nodes, the UI template node will update the table whenever SELECT * is sent to the SQLite node, and an array of records are returned from the SQLite node to the UI template node. The resulting table would look like this when you hit the URL http://192.168.1.112:1880/ui/:

SQLite

Database Administration

For the basic database administrative activities you can use web (php) based tools like phpLiteAdmin or go with an installable tool like SQLiteBrowser:

SQLite

SQLite

Flow Export

[{"id":"af8b3131.1b188","type":"tab","label":"sqlite","disabled":false,"info":""},{"id":"d7f0c96f.0d0588","type":"inject","z":"af8b3131.1b188","name":"CREATE","topic":"CREATE TABLE dhtreadings(id INTEGER PRIMARY KEY AUTOINCREMENT, temperature NUMERIC, humidity NUMERIC, currentdate DATE, currenttime TIME, device TEXT)","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":40,"wires":[["7f9d303d.adb45"]]},{"id":"522e8f98.ac3de","type":"inject","z":"af8b3131.1b188","name":"INSERT","topic":"INSERT INTO dhtreadings(temperature, humidity, currentdate, currenttime, device) values(22.4, 48, date('now'), time('now'), \"manual\")","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":100,"wires":[["7f9d303d.adb45"]]},{"id":"40fe756f.d7cd5c","type":"inject","z":"af8b3131.1b188","name":"SELECT","topic":"SELECT * FROM dhtreadings","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":160,"wires":[["7f9d303d.adb45"]]},{"id":"3b1c34a.1639acc","type":"inject","z":"af8b3131.1b188","name":"DELETE","topic":"DELETE from dhtreadings","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":220,"wires":[["7f9d303d.adb45"]]},{"id":"57370135.7daa1","type":"inject","z":"af8b3131.1b188","name":"DROP TABLE","topic":"DROP TABLE dhtreadings","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":280,"wires":[["7f9d303d.adb45"]]},{"id":"7f9d303d.adb45","type":"sqlite","z":"af8b3131.1b188","mydb":"4e71ffcc.32ba8","sqlquery":"msg.topic","sql":"","name":"SQLite","x":270,"y":160,"wires":[["593ed62b.495198"]]},{"id":"593ed62b.495198","type":"debug","z":"af8b3131.1b188","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":430,"y":160,"wires":[]},{"id":"3735b0c8.22ff","type":"sqlite","z":"af8b3131.1b188","mydb":"4e71ffcc.32ba8","sqlquery":"msg.topic","sql":"","name":"SQLite","x":370,"y":300,"wires":[["2f6afcf0.58e874"]]},{"id":"c8e55090.582db","type":"inject","z":"af8b3131.1b188","name":"View Records","topic":"SELECT * FROM dhtreadings","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":300,"y":240,"wires":[["3735b0c8.22ff"]]},{"id":"2f6afcf0.58e874","type":"ui_template","z":"af8b3131.1b188","group":"5be80bfc.629394","name":"UI Table","order":2,"width":"6","height":"3","format":"<table style=\"width:100%\">\n  <tr>\n    <th>Time</th> \n    <th>Temp</th> \n    <th>Hum</th>\n  </tr>\n  <tr ng-repeat=\"x in msg.payload | limitTo:2\">\n    <td>{{msg.payload[$index].currenttime}}</td>\n    <td>{{msg.payload[$index].temperature}}</td> \n    <td>{{msg.payload[$index].humidity}}</td>\n  </tr>\n</table>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":430,"y":360,"wires":[[]]},{"id":"4e71ffcc.32ba8","type":"sqlitedb","z":"","db":"C:\\Users\\INSTAR\\.node-red\\db\\mydb.db"},{"id":"5be80bfc.629394","type":"ui_group","z":"","name":"Data","tab":"da0180c5.64fa9","order":3,"disp":true,"width":"6","collapse":false},{"id":"da0180c5.64fa9","type":"ui_tab","z":"","name":"IP Camera","icon":"photo_camera"}]

Node-Red 擷取 空氣品質指數 AQI 數據

Node-Red 擷取 空氣品質指數 AQI 數據


https://opendata.epa.gov.tw/Data/Contents/AQI/


var loc= flow.get('Location');

flow.set("tempera",msg.payload);

var rawdata = flow.get("tempera");


var citynumber=rawdata.length;

var i;

var AQI,Status,PublishTime;


if (loc=== null) {

    loc='大里';

}



for (i=0; i<citynumber;i++)

{

    if (rawdata[i].SiteName===loc)

    {

        AQI=rawdata[i].AQI;

        Status=rawdata[i].Status;

        PublishTime=rawdata[i].PublishTime;

        break;

    }

}

msg.payload='地點 :' + loc +'空氣品質AQI='+ AQI+' , 空氣='+ Status + ' 發佈時間' +PublishTime ;

return msg;









[{"id":"1cb291e0.a2a27e","type":"inject","z":"72daf6a8.527e68","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":220,"wires":[["e9ce1e11.9cc13","e9cc41c8.708a1"]]},{"id":"e9ce1e11.9cc13","type":"http request","z":"72daf6a8.527e68","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"http://opendata.epa.gov.tw/webapi/Data/REWIQA/?$orderby=SiteName&$skip=0&$top=1000&format=json","tls":"","persist":false,"proxy":"","authType":"","x":340,"y":100,"wires":[["2ecdccd3.50a154","29732d61.7fd372"]]},{"id":"2ecdccd3.50a154","type":"DataIn","z":"72daf6a8.527e68","collection":"bc9b0fb0.43472","name":"","update":false,"topic":"/PM25Data","x":530,"y":120,"wires":[]},{"id":"a58b9e80.2d45f","type":"DataOut","z":"72daf6a8.527e68","collection":"bc9b0fb0.43472","name":"","topic":"/PM25Data","error":false,"x":490,"y":300,"wires":[["73d8e1b7.e2aec","732ba94e.6dd2a8","e10ae21d.73ccb","7f10b072.cb50e"]]},{"id":"e9cc41c8.708a1","type":"trigger","z":"72daf6a8.527e68","name":"","op1":"","op2":"1","op1type":"nul","op2type":"str","duration":"5","extend":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":330,"y":220,"wires":[["a58b9e80.2d45f"]]},{"id":"e34d884c.ed01f8","type":"function","z":"72daf6a8.527e68","name":"","func":"if (msg.payload === null)\n{\n    flow.set('Location','大里');\n}\nelse\n{\n    flow.set('Location',msg.payload);\n}\nnode.status({fill:\"green\",shape:\"dot\",text:msg.payload});\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":310,"y":300,"wires":[["a58b9e80.2d45f","70aea15c.5ec1b"]]},{"id":"5294ebd9.66fe94","type":"ui_dropdown","z":"72daf6a8.527e68","name":"","label":"選擇地點","tooltip":"","place":"Select option","group":"1cc27a89.bee075","order":63,"width":"3","height":"6","passthru":true,"multiple":false,"options":[{"label":"二林","value":"二林","type":"str"},{"label":"三義","value":"三義","type":"str"},{"label":"大里","value":"大里","type":"str"},{"label":"小港","value":"小港","type":"str"},{"label":"斗六","value":"斗六","type":"str"},{"label":"西屯","value":"西屯","type":"str"},{"label":"鳳山","value":"鳳山","type":"str"}],"payload":"","topic":"","x":140,"y":300,"wires":[["e34d884c.ed01f8"]]},{"id":"73d8e1b7.e2aec","type":"function","z":"72daf6a8.527e68","name":"","func":"var loc= flow.get('Location');\nflow.set(\"tempera\",msg.payload);\nvar rawdata = flow.get(\"tempera\");\n\nvar citynumber=rawdata.length;\nvar i;\nvar AQI,Status,PublishTime;\n\nif (loc=== null) {\n    loc='大里';\n}\n\n\nfor (i=0; i<citynumber;i++)\n{\n    if (rawdata[i].SiteName===loc)\n    {\n        AQI=rawdata[i].AQI;\n        Status=rawdata[i].Status;\n        PublishTime=rawdata[i].PublishTime;\n        break;\n    }\n}\n\nmsg.payload='地點 :' + loc +'空氣品質AQI='+ AQI+' , 空氣='+ Status + ' 發佈時間' +PublishTime ;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":640,"y":300,"wires":[["2c69af24.32335","1141aa83.c1d7c5"]]},{"id":"3aeed31e.00f38c","type":"ui_button","z":"72daf6a8.527e68","name":"","group":"1cc27a89.bee075","order":12,"width":"4","height":"1","passthru":false,"label":"取得AQI資料","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":140,"y":100,"wires":[["e9ce1e11.9cc13","e9cc41c8.708a1"]]},{"id":"1141aa83.c1d7c5","type":"ui_text","z":"72daf6a8.527e68","group":"1cc27a89.bee075","order":10,"width":"20","height":"1","name":"","label":"空氣品質指標(AQI)","format":"{{msg.payload}}","layout":"row-left","x":870,"y":300,"wires":[]},{"id":"8fce20e0.5cc7e","type":"ui_gauge","z":"72daf6a8.527e68","name":"","group":"1cc27a89.bee075","order":62,"width":"6","height":"6","gtype":"gage","title":"PM10微克/立方公尺(μg/m3) ","label":"units","format":"{{value}}","min":0,"max":"100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":900,"y":460,"wires":[]},{"id":"29732d61.7fd372","type":"debug","z":"72daf6a8.527e68","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":530,"y":80,"wires":[]},{"id":"70aea15c.5ec1b","type":"debug","z":"72daf6a8.527e68","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":310,"y":360,"wires":[]},{"id":"732ba94e.6dd2a8","type":"debug","z":"72daf6a8.527e68","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":670,"y":220,"wires":[]},{"id":"2c69af24.32335","type":"debug","z":"72daf6a8.527e68","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":850,"y":260,"wires":[]},{"id":"84a09e78.89fff","type":"debug","z":"72daf6a8.527e68","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":850,"y":340,"wires":[]},{"id":"ed62362c.491278","type":"debug","z":"72daf6a8.527e68","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":850,"y":420,"wires":[]},{"id":"c2dd4913.021288","type":"ui_gauge","z":"72daf6a8.527e68","name":"","group":"1cc27a89.bee075","order":14,"width":"6","height":"6","gtype":"gage","title":"AQI","label":"units","format":"{{value}}","min":0,"max":"100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":830,"y":380,"wires":[]},{"id":"e10ae21d.73ccb","type":"function","z":"72daf6a8.527e68","name":"","func":"var loc= flow.get('Location');\nflow.set(\"tempera\",msg.payload);\nvar rawdata = flow.get(\"tempera\");\n\nvar citynumber=rawdata.length;\nvar i;\nvar AQI,Status;\n\nif (loc=== null) {\n    loc='大里';\n}\n\n\nfor (i=0; i<citynumber;i++)\n{\n    if (rawdata[i].SiteName===loc)\n    {\n        AQI=rawdata[i].AQI;\n        Status=rawdata[i].Status;\n        break;\n    }\n}\n\nmsg.payload= AQI;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":640,"y":340,"wires":[["84a09e78.89fff","c2dd4913.021288"]]},{"id":"7f10b072.cb50e","type":"function","z":"72daf6a8.527e68","name":"","func":"var loc= flow.get('Location');\nflow.set(\"tempera\",msg.payload);\nvar rawdata = flow.get(\"tempera\");\n\nvar citynumber=rawdata.length;\nvar i;\nvar PM10;\n\nif (loc=== null) {\n    loc='大里';\n}\n\n\nfor (i=0; i<citynumber;i++)\n{\n    if (rawdata[i].SiteName===loc)\n    {\n        PM10=rawdata[i].PM10;\n        break;\n    }\n}\n\nmsg.payload= PM10;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":650,"y":420,"wires":[["ed62362c.491278","8fce20e0.5cc7e"]]},{"id":"bc9b0fb0.43472","type":"json-db-collection","z":"","name":"DATA","collection":"DATA","save":true},{"id":"1cc27a89.bee075","type":"ui_group","z":"","name":"Info","tab":"2e8eb9a2.9f45f6","order":1,"disp":true,"width":"24","collapse":false},{"id":"2e8eb9a2.9f45f6","type":"ui_tab","z":"","name":"Weather","icon":"Dashboard","disabled":false,"hidden":false}]


2020年11月28日 星期六

Node-Red 擷取 open data 即時天氣狀況暨溫濕度

 Node-Red 擷取 open data 即時天氣狀況暨溫濕度

https://opendata.epa.gov.tw/Data/Contents/ATM00698/

https://opendata.epa.gov.tw/webapi/api/rest/datastore/355000000I-000272?offset=0&limit=1000

http://opendata.epa.gov.tw/webapi/Data/ATM00698/?$skip=0&$top=1000&format=json













//==================================

flow.set("tempera",msg.payload);

var rawdata = flow.get("tempera");

var citynumber=rawdata.length;

var cityarray=[];

var i;

for (i=0; i<citynumber;i++)

{

    cityarray[i]=rawdata[i].SiteName;

}

msg.payload=cityarray;

flow.set("loname",cityarray);

return msg;

//==================================

flow.set("tempera",msg.payload);

var rawdata = flow.get("tempera");

var citynumber=rawdata.length;

var i;

var Temp;

var Mois;

var Weat;

var dataDate;

for (i=0; i<citynumber;i++)

{

    if (rawdata[i].SiteName==='臺中')

    {

        Temp=rawdata[i].Temperature;

        Mois=rawdata[i].Moisture;

        Weat=rawdata[i].Weather;

        dataDate=rawdata[i].DataCreationDate;

        break;

    }

}

msg.payload='溫度='+Temp+'°C , 濕度='+Mois+'% , 天氣'+ Weat+ ' , 發佈時間' + dataDate;

return msg;

//==================================

flow.set("tempera",msg.payload);

var rawdata = flow.get("tempera");

var citynumber=rawdata.length;

var i;

var Temp;

var Mois;

var Weat;

var dataDate;

for (i=0; i<citynumber;i++)

{

    if (rawdata[i].SiteName==='臺中')

    {

        Temp=rawdata[i].Temperature;

        Mois=rawdata[i].Moisture;

        Weat=rawdata[i].Weather;

        dataDate=rawdata[i].DataCreationDate;

        break;

    }

}

msg.payload= Mois;

return msg;

//=================================

flow.set("tempera",msg.payload);

var rawdata = flow.get("tempera");

var citynumber=rawdata.length;

var i;

var Temp;

var Mois;

var Weat;

var dataDate;


for (i=0; i<citynumber;i++)

{

    if (rawdata[i].SiteName==='臺中')

    {

        Temp=rawdata[i].Temperature;

        Mois=rawdata[i].Moisture;

        Weat=rawdata[i].Weather;

        dataDate=rawdata[i].DataCreationDate;

        break;

    }

}

msg.payload= Temp;

return msg;


//================================

[{"id":"7243489f.6a8558","type":"ui_button","z":"c1b84172.51787","name":"","group":"1cc27a89.bee075","order":2,"width":"0","height":"0","passthru":false,"label":"取得台中市天氣(等待約30秒以上)","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":240,"y":160,"wires":[["e76cbb94.d60f98","80baac1d.e7688"]]},{"id":"84ad41ed.d8693","type":"ui_gauge","z":"c1b84172.51787","name":"","group":"1cc27a89.bee075","order":3,"width":"4","height":"4","gtype":"gage","title":"溫度","label":"°C","format":"{{value}}","min":0,"max":"50","colors":["#00b395","#e6e600","#ca3838"],"seg1":"28","seg2":"38","x":810,"y":380,"wires":[]},{"id":"4a7a499d.a293c8","type":"ui_gauge","z":"c1b84172.51787","name":"","group":"1cc27a89.bee075","order":62,"width":"4","height":"4","gtype":"gage","title":"濕度","label":"%","format":"{{value}}","min":0,"max":"100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"35","seg2":"70","x":810,"y":300,"wires":[]},{"id":"913afbcc.1196b8","type":"inject","z":"c1b84172.51787","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":60,"wires":[["e76cbb94.d60f98"]]},{"id":"e76cbb94.d60f98","type":"http request","z":"c1b84172.51787","name":"temp request","method":"GET","ret":"txt","paytoqs":"ignore","url":"http://opendata.epa.gov.tw/webapi/Data/ATM00698/?$skip=0&$top=1000&format=json","tls":"","persist":false,"proxy":"","authType":"","x":310,"y":60,"wires":[["a47cf11c.57984"]]},{"id":"d73f973e.ef0298","type":"debug","z":"c1b84172.51787","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":60,"wires":[]},{"id":"a47cf11c.57984","type":"json","z":"c1b84172.51787","name":"","property":"payload","action":"","pretty":false,"x":470,"y":60,"wires":[["d73f973e.ef0298","87a5a900.ec7548","4bb9abf5.b29bf4","5a2d58c3.44eba8","1165f3d8.b0bf0c"]]},{"id":"87a5a900.ec7548","type":"function","z":"c1b84172.51787","name":"List locationname","func":"\nflow.set(\"tempera\",msg.payload);\nvar rawdata = flow.get(\"tempera\");\n\nvar citynumber=rawdata.length;\nvar cityarray=[];\nvar i;\nfor (i=0; i<citynumber;i++)\n{\n    cityarray[i]=rawdata[i].SiteName;\n}\n\nmsg.payload=cityarray;\nflow.set(\"loname\",cityarray);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":630,"y":120,"wires":[["9cf7ec6a.de0ec"]]},{"id":"9cf7ec6a.de0ec","type":"debug","z":"c1b84172.51787","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":810,"y":120,"wires":[]},{"id":"4bb9abf5.b29bf4","type":"function","z":"c1b84172.51787","name":"取得天氣溫濕度","func":"\nflow.set(\"tempera\",msg.payload);\nvar rawdata = flow.get(\"tempera\");\n\nvar citynumber=rawdata.length;\nvar i;\n\nvar Temp;\nvar Mois;\nvar Weat;\nvar dataDate;\n\nfor (i=0; i<citynumber;i++)\n{\n    if (rawdata[i].SiteName==='臺中')\n    {\n        Temp=rawdata[i].Temperature;\n        Mois=rawdata[i].Moisture;\n        Weat=rawdata[i].Weather;\n        dataDate=rawdata[i].DataCreationDate;\n        break;\n    }\n}\n\nmsg.payload='溫度='+Temp+'°C , 濕度='+Mois+'% , 天氣'+ Weat+ ' , 發佈時間' + dataDate;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":620,"y":180,"wires":[["bfd558bd.5f41e8","b3f9559b.085eb8"]]},{"id":"bfd558bd.5f41e8","type":"debug","z":"c1b84172.51787","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":830,"y":180,"wires":[]},{"id":"b3f9559b.085eb8","type":"ui_text","z":"c1b84172.51787","group":"1cc27a89.bee075","order":0,"width":"12","height":"2","name":"","label":"","format":"{{msg.payload}}","layout":"col-center","x":810,"y":220,"wires":[]},{"id":"80baac1d.e7688","type":"function","z":"c1b84172.51787","name":"清除","func":"msg.payload='  ';\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":380,"wires":[["b3f9559b.085eb8","4a7a499d.a293c8","84ad41ed.d8693"]]},{"id":"5a2d58c3.44eba8","type":"function","z":"c1b84172.51787","name":"濕度","func":"\nflow.set(\"tempera\",msg.payload);\nvar rawdata = flow.get(\"tempera\");\n\nvar citynumber=rawdata.length;\nvar i;\n\nvar Temp;\nvar Mois;\nvar Weat;\nvar dataDate;\n\nfor (i=0; i<citynumber;i++)\n{\n    if (rawdata[i].SiteName==='臺中')\n    {\n        Temp=rawdata[i].Temperature;\n        Mois=rawdata[i].Moisture;\n        Weat=rawdata[i].Weather;\n        dataDate=rawdata[i].DataCreationDate;\n        break;\n    }\n}\nmsg.payload= Mois;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":260,"wires":[["4a7a499d.a293c8","67014f63.76a22"]]},{"id":"67014f63.76a22","type":"debug","z":"c1b84172.51787","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":830,"y":260,"wires":[]},{"id":"1165f3d8.b0bf0c","type":"function","z":"c1b84172.51787","name":"溫度","func":"\nflow.set(\"tempera\",msg.payload);\nvar rawdata = flow.get(\"tempera\");\n\nvar citynumber=rawdata.length;\nvar i;\n\nvar Temp;\nvar Mois;\nvar Weat;\nvar dataDate;\n\nfor (i=0; i<citynumber;i++)\n{\n    if (rawdata[i].SiteName==='臺中')\n    {\n        Temp=rawdata[i].Temperature;\n        Mois=rawdata[i].Moisture;\n        Weat=rawdata[i].Weather;\n        dataDate=rawdata[i].DataCreationDate;\n        break;\n    }\n}\nmsg.payload= Temp;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":340,"wires":[["84ad41ed.d8693","47ae54e5.c08f6c"]]},{"id":"47ae54e5.c08f6c","type":"debug","z":"c1b84172.51787","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":830,"y":340,"wires":[]},{"id":"1cc27a89.bee075","type":"ui_group","z":"","name":"Info","tab":"2e8eb9a2.9f45f6","order":1,"disp":true,"width":"24","collapse":false},{"id":"2e8eb9a2.9f45f6","type":"ui_tab","z":"","name":"Weather","icon":"Dashboard","disabled":false,"hidden":false}]




今明36小時天氣預報

 今明36小時天氣預報


https://opendata.cwb.gov.tw/dataset/forecast/F-C0032-001


GET URL

https://opendata.cwb.gov.tw/fileapi/v1/opendataapi/F-C0032-001?Authorization=CWB-05C514C3-55CB-4E40-978B-171E440D6B9C&downloadType=WEB&format=XML

Format : XML 

//=========================================================

Listlocation :

//var rawdata=context.global.temp;

global.set("tempera",msg.payload); //global.set

var rawdata = global.get("tempera");

//flow.set("loname",rawdata.cwbopendata.dataset[0].location.locationName);

var location=rawdata.cwbopendata.dataset[0].location;

var citynumber=location.length;

var cityarray=[];

var i;

for (i=0; i<citynumber;i++)

{

cityarray[i]=location[i].locationName[0];

}


 msg.payload=cityarray;

flow.set("loname",cityarray);

return msg;

//=========================================================

//context.global.locationnumber=0;

//var rawdata=context.global.temp;

global.set("tempera",msg.payload); //global.set

var rawdata = global.get("tempera");

//flow.set("loname",rawdata.cwbopendata.dataset[0].location.locationName);

var location=rawdata.cwbopendata.dataset[0].location;

var loc=flow.get("locationnumber",3);  //臺中

var locationName=rawdata.cwbopendata.dataset[0].location[loc].locationName[0];

var period0max=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[1].time[0].parameter[0].parameterName[0];

var period0min=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[2].time[0].parameter[0].parameterName[0];

var period0start=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[1].time[0].startTime[0];

var period0end=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[1].time[0].endTime[0];

var  starthourtemp= period0start.split("T");

var  starthour=starthourtemp[1].split(":")[0];

var  endhourtemp= period0end.split("T");

var  endhour=endhourtemp[1].split(":")[0];

var  status1=locationName+starthour+"到"+endhour+"點 , 溫度最低"+period0min+"度最高"+period0max+"度";

//msg.payload=locationName+starthour+"到"+endhour+"點溫度最低"+period0min+"度最高"+period0max+"度";

msg.payload=status1;

return msg;

//=====================================================

//context.global.locationnumber=0;

//var rawdata=context.global.temp;

global.set("tempera",msg.payload); //global.set

var rawdata = global.get("tempera");

//flow.set("loname",rawdata.cwbopendata.dataset[0].location.locationName);

var location=rawdata.cwbopendata.dataset[0].location;

var loc=flow.get("locationnumber",3);  //臺中

var period0max=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[1].time[0].parameter[0].parameterName[0];

var period0min=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[2].time[0].parameter[0].parameterName[0];

msg.payload=period0max;

return msg;

//=====================================================

//context.global.locationnumber=0;

//var rawdata=context.global.temp;

global.set("tempera",msg.payload); //global.set

var rawdata = global.get("tempera");

//flow.set("loname",rawdata.cwbopendata.dataset[0].location.locationName);

var location=rawdata.cwbopendata.dataset[0].location;

var loc=flow.get("locationnumber",3);  //臺中

var period0max=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[1].time[0].parameter[0].parameterName[0];

var period0min=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[2].time[0].parameter[0].parameterName[0];

msg.payload=period0min;

return msg;

//=====================================================

//context.global.locationnumber=0;

//var rawdata=context.global.temp;

global.set("tempera",msg.payload); //global.set

var rawdata = global.get("tempera");

//flow.set("loname",rawdata.cwbopendata.dataset[0].location.locationName);

var location=rawdata.cwbopendata.dataset[0].location;

var loc=flow.get("locationnumber",3);  //臺中

var locationName=rawdata.cwbopendata.dataset[0].location[loc].locationName[0];

var period0status=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[0].time[0].parameter[0].parameterName[0];

var period0start=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[0].time[0].startTime[0];

var period0end=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[0].time[0].endTime[0];

var  starthourtemp= period0start.split("T");

var  starthour=starthourtemp[1].split(":")[0];

var  endhourtemp= period0end.split("T");

var  endhour=endhourtemp[1].split(":")[0];

var  status2 = locationName+starthour+"到"+endhour+"點 , 天氣狀況: "+period0status;

msg.payload=status2;

return msg;









[{"id":"e8ed80b3.a0afb","type":"http request","z":"c1b84172.51787","name":"temp request","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://opendata.cwb.gov.tw/fileapi/v1/opendataapi/F-C0032-001?Authorization=CWB-05C514C3-55CB-4E40-978B-171E440D6B9C&downloadType=WEB&format=XML","tls":"","persist":false,"proxy":"","authType":"","x":270,"y":80,"wires":[["3db0b988.a1c666"]]},{"id":"3db0b988.a1c666","type":"xml","z":"c1b84172.51787","name":"","property":"payload","attr":"","chr":"","x":410,"y":80,"wires":[["1c37b658.36caca","4db20add.e91c34","ccd207d6.87da38","eae9be49.b979a","9962f1bd.0013c","f160f17c.c98db"]]},{"id":"7243489f.6a8558","type":"ui_button","z":"c1b84172.51787","name":"","group":"1cc27a89.bee075","order":2,"width":"0","height":"0","passthru":false,"label":"取得台中市天氣","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":100,"y":140,"wires":[["e8ed80b3.a0afb","acede0e6.1a15d"]]},{"id":"8d3a0244.877ab","type":"inject","z":"c1b84172.51787","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":116,"y":68,"wires":[["e8ed80b3.a0afb"]]},{"id":"1c37b658.36caca","type":"debug","z":"c1b84172.51787","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":20,"wires":[]},{"id":"4db20add.e91c34","type":"function","z":"c1b84172.51787","name":"List locationname","func":"//var rawdata=context.global.temp;\nglobal.set(\"tempera\",msg.payload); //global.set\nvar rawdata = global.get(\"tempera\");\n//flow.set(\"loname\",rawdata.cwbopendata.dataset[0].location.locationName);\nvar location=rawdata.cwbopendata.dataset[0].location;\nvar citynumber=location.length;\nvar cityarray=[];\nvar i;\nfor (i=0; i<citynumber;i++)\n{\ncityarray[i]=location[i].locationName[0];\n}\n\n msg.payload=cityarray;\nflow.set(\"loname\",cityarray);\nreturn msg;\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":610,"y":60,"wires":[["cc762362.1472f"]]},{"id":"cc762362.1472f","type":"debug","z":"c1b84172.51787","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":790,"y":40,"wires":[]},{"id":"ccd207d6.87da38","type":"function","z":"c1b84172.51787","name":"report","func":"//context.global.locationnumber=0;\n//var rawdata=context.global.temp;\nglobal.set(\"tempera\",msg.payload); //global.set\nvar rawdata = global.get(\"tempera\");\n//flow.set(\"loname\",rawdata.cwbopendata.dataset[0].location.locationName);\nvar location=rawdata.cwbopendata.dataset[0].location;\nvar loc=flow.get(\"locationnumber\",3);  //臺中\n\n\nvar locationName=rawdata.cwbopendata.dataset[0].location[loc].locationName[0];\nvar period0max=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[1].time[0].parameter[0].parameterName[0];\nvar period0min=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[2].time[0].parameter[0].parameterName[0];\nvar period0start=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[1].time[0].startTime[0];\nvar period0end=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[1].time[0].endTime[0];\n\nvar  starthourtemp= period0start.split(\"T\");\nvar  starthour=starthourtemp[1].split(\":\")[0];\nvar  endhourtemp= period0end.split(\"T\");\nvar  endhour=endhourtemp[1].split(\":\")[0];\nvar  status1=locationName+starthour+\"到\"+endhour+\"點 , 溫度最低\"+period0min+\"度最高\"+period0max+\"度\";\n//msg.payload=locationName+starthour+\"到\"+endhour+\"點溫度最低\"+period0min+\"度最高\"+period0max+\"度\";\nmsg.payload=status1;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":120,"wires":[["b0d74e47.1b0c6","a92ba76.fb9fc58"]]},{"id":"b0d74e47.1b0c6","type":"ui_text","z":"c1b84172.51787","group":"1cc27a89.bee075","order":0,"width":"8","height":"3","name":"","label":"","format":"{{msg.payload}}","layout":"col-center","x":790,"y":140,"wires":[]},{"id":"a92ba76.fb9fc58","type":"debug","z":"c1b84172.51787","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":745,"y":100,"wires":[]},{"id":"acede0e6.1a15d","type":"function","z":"c1b84172.51787","name":"","func":"msg.payload='  ';\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":200,"wires":[["b0d74e47.1b0c6","4bc34091.be7b5","84ad41ed.d8693","4a7a499d.a293c8"]]},{"id":"4bc34091.be7b5","type":"ui_text","z":"c1b84172.51787","group":"1cc27a89.bee075","order":0,"width":"8","height":"3","name":"","label":"","format":"{{msg.payload}}","layout":"col-center","x":790,"y":280,"wires":[]},{"id":"eae9be49.b979a","type":"function","z":"c1b84172.51787","name":"report","func":"//context.global.locationnumber=0;\n//var rawdata=context.global.temp;\nglobal.set(\"tempera\",msg.payload); //global.set\nvar rawdata = global.get(\"tempera\");\n//flow.set(\"loname\",rawdata.cwbopendata.dataset[0].location.locationName);\nvar location=rawdata.cwbopendata.dataset[0].location;\nvar loc=flow.get(\"locationnumber\",3);  //臺中\n\n\nvar locationName=rawdata.cwbopendata.dataset[0].location[loc].locationName[0];\nvar period0status=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[0].time[0].parameter[0].parameterName[0];\nvar period0start=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[0].time[0].startTime[0];\nvar period0end=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[0].time[0].endTime[0];\n\nvar  starthourtemp= period0start.split(\"T\");\nvar  starthour=starthourtemp[1].split(\":\")[0];\nvar  endhourtemp= period0end.split(\"T\");\nvar  endhour=endhourtemp[1].split(\":\")[0];\n\nvar  status2 = locationName+starthour+\"到\"+endhour+\"點 , 天氣狀況: \"+period0status;\nmsg.payload=status2;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":320,"wires":[["4bc34091.be7b5","8ca19f33.836f3"]]},{"id":"8ca19f33.836f3","type":"debug","z":"c1b84172.51787","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":770,"y":340,"wires":[]},{"id":"84ad41ed.d8693","type":"ui_gauge","z":"c1b84172.51787","name":"","group":"1cc27a89.bee075","order":3,"width":"4","height":"4","gtype":"gage","title":"最高溫度","label":"units","format":"{{value}}","min":0,"max":"50","colors":["#00b500","#e6e600","#ca3838"],"seg1":"28","seg2":"38","x":800,"y":180,"wires":[]},{"id":"4a7a499d.a293c8","type":"ui_gauge","z":"c1b84172.51787","name":"","group":"1cc27a89.bee075","order":62,"width":"4","height":"4","gtype":"gage","title":"最低溫度","label":"units","format":"{{value}}","min":0,"max":"50","colors":["#00b500","#e6e600","#ca3838"],"seg1":"28","seg2":"38","x":800,"y":220,"wires":[]},{"id":"9962f1bd.0013c","type":"function","z":"c1b84172.51787","name":"","func":"//context.global.locationnumber=0;\n//var rawdata=context.global.temp;\nglobal.set(\"tempera\",msg.payload); //global.set\nvar rawdata = global.get(\"tempera\");\n//flow.set(\"loname\",rawdata.cwbopendata.dataset[0].location.locationName);\nvar location=rawdata.cwbopendata.dataset[0].location;\nvar loc=flow.get(\"locationnumber\",3);  //臺中\nvar period0max=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[1].time[0].parameter[0].parameterName[0];\nvar period0min=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[2].time[0].parameter[0].parameterName[0];\n\nmsg.payload=period0max;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":160,"wires":[["84ad41ed.d8693"]]},{"id":"f160f17c.c98db","type":"function","z":"c1b84172.51787","name":"","func":"//context.global.locationnumber=0;\n//var rawdata=context.global.temp;\nglobal.set(\"tempera\",msg.payload); //global.set\nvar rawdata = global.get(\"tempera\");\n//flow.set(\"loname\",rawdata.cwbopendata.dataset[0].location.locationName);\nvar location=rawdata.cwbopendata.dataset[0].location;\nvar loc=flow.get(\"locationnumber\",3);  //臺中\nvar period0max=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[1].time[0].parameter[0].parameterName[0];\nvar period0min=rawdata.cwbopendata.dataset[0].location[loc].weatherElement[2].time[0].parameter[0].parameterName[0];\n\nmsg.payload=period0min;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":590,"y":260,"wires":[["4a7a499d.a293c8"]]},{"id":"1cc27a89.bee075","type":"ui_group","z":"","name":"Info","tab":"2e8eb9a2.9f45f6","order":1,"disp":true,"width":"24","collapse":false},{"id":"2e8eb9a2.9f45f6","type":"ui_tab","z":"","name":"Weather","icon":"Dashboard","disabled":false,"hidden":false}]

  清除項目編譯快取 執行 flutter clean 重新取得套件依賴 執行 flutter pub get 完整重新編譯並執行 flutter run 1. 新增專案套件 (pubspec.yaml) 在 Flutter 專案根目錄下的 pubspec.yaml 中,新增 ...