Opendata 實作
可以利用一些網路服務來操控智慧插座之後,就來玩點比較進階的功能,這篇將會介紹在網頁裡常常使用的 Opendata ( 開放資料 ),並且使用這些 Opendata 來操控智慧插座。
取得 Opendata
基本上縣市政府網站,都有提供不少 Opendata 的資訊讓開發者使用,許多開發者喜歡到「政府資料開放平臺」上面去挖寶,或是「台北市政府資料開放平臺」,這兩個平台的開放資料都是相當完整且容易介接。
政府資料開放平臺:http://data.gov.tw/
台北市政府資料開放平臺:http://data.taipei/
而這篇文章將會使用政府資料開放平臺裡的「空氣品質即時污染指標」作為資料來源,因為手邊不見得隨時都會有空氣污染偵測器 ( 也不便宜 ),所以透過每個小時由氣象局偵測的資訊,也可作為基本的預警與提醒功能。
點選 JSON 的格式,這就是待會我要使用的。
此外,在這邊列出一些我覺得還滿實用,至少都是每小時更新的 Opendata,有興趣就可以參考我後面的做法自行做串接。
- 即時海水水位:http://data.gov.tw/node/35077
- 即時水位 ( 10min 更新 ):http://data.gov.tw/node/25768
- 即時雨量 ( 10 min 更新 ):http://data.gov.tw/node/7879
- 空氣品質指標 ( AQI ):http://data.gov.tw/node/40448
- 空氣品質即時污染指標:http://data.gov.tw/node/6074
- 高雄機場國內線即時到站航班:http://data.gov.tw/node/33649
- 紫外線即時監測資料:http://data.gov.tw/node/6076
- 曾文水庫即時水情資訊:http://data.gov.tw/node/32733
- 台北捷運列車到站:https://goo.gl/rNgG8B
使用 Opendata ( 網頁前端 )
要直接在「網頁前端」使用 Opendata,最快的做法大概就是使用 jQuery ,這邊用了 .get
的方法,只要三行,剛剛的 JSON 資料就全部進到網頁裡了。( 使用 console.log 顯示 )
$.get('http://opendata2.epa.gov.tw/AQX.json',function(e){
console.log(e);
});
因為資料是陣列的格式,所以藉由 forEach
就可以去判斷陣列每個元素的內容,然後指篩選出高雄市的資料。
$.get('http://opendata2.epa.gov.tw/AQX.json',function(e){
e.forEach(function(o){
if(o.County=='高雄市'){
console.log(o);
}
});
});
不過只有在 console.log 裡面顯示實在沒有很好閱讀,最終還是得呈現在網頁裡,所以我先在網頁裡放個 div 作為顯示區域,接著就可以透過 append
把資料加到網頁裡面。
var $content = $('#content');
$.get('http://opendata2.epa.gov.tw/AQX.json',function(e){
e.forEach(function(o){
if(o.County=='高雄市'){
console.log(o);
$content.append('< '+o.SiteName+' > PM2.5:'+o['PM2.5']+', PM10:'+o.PM10+'<br/>');
}
});
});
更進階一點,也可以做成下拉選單,選擇之後再呈現對應的資訊,當資料載入之後,透過 filter
做篩選,不然你可能會有十幾個「新北市」出現在選單裡,然後再根據選擇的縣市,把感測器所在的區域資料顯示在網頁裡。
var $content = $('#content');
var $select = $('#select');
var $btn = $('#btn');
var county = [];
var result;
$.get('http://opendata2.epa.gov.tw/AQX.json',function(data){
console.log(data);
data.forEach(function(e,i){
county[i] = e.County;
});
result=county.filter(function(element, index, arr){
return arr.indexOf(element)=== index;
});
//篩選出縣市名稱(不然會很多重複)
result.forEach(function(e){
$select.append('<option value="'+e+'">'+e+'</option>');
});
$btn.on('click',function(){
var s = $select.val();
$content.html(''); //清空內容
data.forEach(function(e,i){
//挑選對應的縣市顯示
if(e.County == s){
$content.append('< '+e.SiteName+' > PM2.5:'+e['PM2.5']+' , PM10: '+e.PM10+'<br/>');
}
});
});
});
使用 OpenData ( Node.js )
剛剛的範例是透過網頁前端運行,如果想要 24 小時偵測,可能就得依賴後端了,這邊介紹一個 Node.js 的套件「get-json」,就可以做到剛剛像網頁前端一樣的事情。 程式只要這樣寫,就可以每 10 秒抓一次氣象局的資料囉!
var getJSON = require('get-json')
_getJSON();
setInterval(function(){
_getJSON();
},10000);
function _getJSON(){
getJSON('http://opendata2.epa.gov.tw/AQX.json',function(error, response){
response.forEach(function(e,i){
if(e.SiteName=='前鎮'){
console.log('前鎮, PM2.5:'+e['PM2.5']+' , PM10:'+e.PM10);
};
});
});
}
Opendata + Webduino ( 網頁前端 )
知道如何獲取資料並且應用之後,就要來寫點判斷式,接著再對應的狀態下,透過 Webduino 點亮燈泡,首先看到 HTML 的部分,一開始先引入對應的 JavaScript,然後放入兩個下拉選單、一個顯示文字的區域用來顯示數值,最後就是一個提示文字,如果空污指數太高就會顯示,同時點亮燈泡。
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://webduino.io/components/webduino-js/dist/webduino-all.min.js"></script>
<script src="https://blockly.webduino.io/webduino-blockly.js"></script>
<script src="https://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>
<select id="county"></select>
<select id="sitename"></select>
<div id="content"></div>
<h1 id="h"></h1>
</body>
</html>
JavaScript 的部分一開始先宣告一些變數,還有一個設定檔,如果今天數值大於我們設定黨的數字,就會亮燈並顯示空屋提示。
var $content = $('#content'),
$county = $('#county'),
$sitename = $('#sitename'),
$h = $('#h'),
$btn = $('#btn');
var county = [];
var site = {};
var result, led;
var config = {
PM25 : 20,
PM10 : 40
};
再來就是抓取開放資料的 json 檔,接著對資料做一些轉換,篩選出主要縣市 ( 台北市、新北市...等 ) 以及每個縣市對應的區域 ( 永和、中和...等 ),然後再改變選單的時候,把對應的數值顯示出來,如果數值比較高,就會點亮燈泡以及秀出「空氣污染超標!」的文字
boardReady('你的開發板 ID', function(board) {
board.systemReset();
board.samplingInterval = 250;
led = getLed(board, 10);
$.get('http://opendata2.epa.gov.tw/AQX.json',function(data){
data.forEach(function(e,i){
county[i] = e.County;
});
//篩選出父選單縣市名稱(不然會重複)
result=county.filter(function(element, index, arr){
return arr.indexOf(element)=== index;
});
//初始化父選單
result.forEach(function(e){
$county.append('<option value="'+e+'">'+e+'</option>');
});
//初始化子選單
_select();
//當父選單改變時,對應子選單內容
$county.on('change',function(){
_select();
});
$sitename.on('change',function(){
_change();
});
function _select(){
$sitename.html(''); //一開始先清空子選單
data.forEach(function(e,i){
//挑選對應的地區顯示
if(e.County == $county.val()){
$sitename.append('<option value="'+e.SiteName+'">'+e.SiteName+'</option>');
}
site[e.SiteName] = [e['PM2.5'],e.PM10];
});
_change();
}
function _change(){
var name = site[$sitename.val()];
$content.html('< '+$sitename.val()+' > PM2.5 ('+name[0]+'), PM10 ('+name[1]+')<br/>');
if(name[0]>config.PM25 || name[1]>config.PM10){
$h.text('空氣污染超標!');
led.on();
}else{
$h.text('');
led.off();
}
}
});
});
Opendata + Webduino ( 後端 )
剛剛我們是使用前端的方法,繼續介紹 Webduino 後端的用法,如果你有印象,在「聊天室 ( 前後端實作 )」有介紹過 Webduino 後端的用法,首先你要先安裝對應的套件,這邊需要 get-json
、webduino-js
和 webduino-blockly
。
npm install webduino-js webduino-blockly get-json
如果你想要在啟動的當下,也有類似對話視窗可以一一輸入資訊的話,可以多安裝 inquirer
( https://www.npmjs.com/package/inquirer )。
npm install inquirer
再來就免不了要寫程式了,最主要跟前端一樣,先抓取對應的縣市 PM2.5 數值,當數值大於多少的時候就亮燈,比較不同的是你可以用一個 setInterval 間隔一段時間抓取一次資料,就可以 24 小時放著讓它自動監控了。
require("webduino-js");
require("webduino-blockly");
var getJSON = require('get-json');
var inquirer = require("inquirer");
var pm = function(a,b,c,d){
boardReady(a, function(board) {
board.systemReset();
board.samplingInterval = 250;
led = getLed(board, b);
console.log('裝置連線成功...');
_getJSON();
setInterval(function(){
_getJSON();
},10000);
});
function _getJSON(){
getJSON('http://opendata2.epa.gov.tw/AQX.json',function(error, response){
response.forEach(function(e,i){
if(e.SiteName==d){
console.log(d+', PM2.5:'+e['PM2.5']+' , PM10:'+e.PM10);
if(e['PM2.5']>c){
led.on();
}
};
});
});
}
};
var preguntas = [{
type: 'input',
name: 'device',
message: 'Device ID?',
default: '你的裝置 ID',
}, {
type: 'input',
name: 'led',
message: 'LED pin?',
default: '10'
}, {
type: 'input',
name: 'rate',
message: 'PM2.5?',
default: '20'
}, {
type: 'input',
name: 'site',
message: '縣市名稱',
default: '前鎮'
}];
inquirer.prompt(preguntas, function(answers) {
}).then(function(answers) {
console.log(answers.device + ',' + answers.led + ',' + answers.rate + ',' + answers.site);
pm(answers.device, answers.led * 1, answers.rate * 1, answers.site);
});
小結
以上就是拿 Opendata 來做物聯網應用的範例,雖然說只是點亮一個燈泡,但如果我們可以透過 Webduino 把各種裝置給虛擬化、網路化、變數化,就可以輕鬆地用網頁前端或後端來操控了。
聯絡我們
如果對於 Webduino 產品有興趣,歡迎透過下列方式購買:
個人線上購買:https://store.webduino.io/ ( 支援信用卡、超商取貨付款 )
企業&學校採購:來信 [email protected] 或來電 07-3388511。
如果對於這篇教學有任何問題或建議,歡迎透過下列方式聯繫我們:
Email:[email protected] ( 如對於產品有使用上的問題,建議透過 Email 附上照片或影片聯繫 )
Facebook 粉絲團:https://www.facebook.com/webduino/
Facebook 技術討論社團:https://www.facebook.com/groups/webduino/