如何取得 AirBox 的即時數據?

1. 本校 AirBox 即時資訊

2. 數據來源

3. 定時取得數據

  • 因為 CORS (Cross-origin_resource_sharing) 的限制,所以先使用簡單的程式將 JSON 資料取回自己的網域內。或是使用 YQL 直接取得。
# vim /opt/www/get_edimax_psi.sh
#/bin/sh
wget -q 'https://airbox.edimaxcloud.com/devices?token=EA81A1FA-8EDB-4CA0-B07B-A881C74B0401&id=74DA3895DF40' -O /var/www/edimax_psi.json
  • 定時自動更新數據,讓程式自動執行,設定 cron job 排程
# vim /etc/cron.d/psi
5,15,25,45       * * * * root /opt/www/get_tainan_psi.sh
5,15,25,35,45,55 * * * * root /opt/www/get_edimax_psi.sh

4. JSON 數據格式

欄位 用途說明
id 識別編號,AirBox 的 MAC
name 節點名稱
lat 緯度
lon 經度
pm25 PM2.5 數據
t 攝氏溫度
h 相對溼度
time 資料更新時間
org es 應該是 Elementary School
area tainan 應該是臺南市
type airbox
{
  "status":"ok",
  "devices":
  [
    {
        "id" : "74DA3895DF40",
      "name" : "臺南市市立進學國小",
       "lat" : 22.985,
       "lon" : 120.201,
      "pm25" : 29,
         "t" : 30,
         "h" : 61,
      "time" : "2016-09-22 18:12:18",
       "org" : "es",
      "area" : "tainan",
      "type" : "airbox"
    }
  ]
}

5. 使用 JavaScript 取得並顯示數據

  • 引用 jQuery,以 getJSON() 方式取得,再用 setInterval() 方式定時更新。
<script type="text/javascript" src="//bernii.github.io/gauge.js/dist/gauge.min.js"></script>
<script type="text/javascript">
var opts = {
	lines: 12, // The number of lines to draw
	angle: 0.15, // The length of each line
	lineWidth: 0.44, // The line thickness
	pointer: {
		length: 0.9, // The radius of the inner circle
		strokeWidth: 0.035, // The rotation offset
		color: '#000000' // Fill color
	},
	limitMax: 'false',   // If true, the pointer will not go past the end of the gauge
	colorStart: '#6FADCF',   // Colors
	colorStop: '#8FC0DA',    // just experiment with them
	strokeColor: '#E0E0E0',   // to see which ones work best for you
	generateGradient: true,
	percentColors: [[0.0, "#31cf00"], [0.36, "#31cf00"], [0.54, "#ff9a00"], [0.71, "#990000"], [1.0, "#ce30ff"]]
};
</script>
 
<div id="psi_edimax" class="dw-content text-center">
<p><span id="edimax_psi_status"></span></p>
<p style="font-size:1.5em;">
PM2.5數值:<span id="edimax_psi_value" style="color:blue;font-weight:bolder;font-size:1.5em;"></span> μg/m³</p>
<canvas id="pm25"></canvas><br>
<p>
溫度:<span id="edimax_psi_t" style="color:blue;font-weight:bolder;font-size:1.5em;"></span> °C,
溼度:<span id="edimax_psi_h" style="color:blue;font-weight:bolder;font-size:1.5em;"></span> %
</p>
最後更新時間:<span class="" id="edimax_psi_pt"></span>
<p><a href="//airbox.tainan.tw/" target="_blank">空氣盒子「進學國小監測站」</a></p>
</div>
 
<script language="javascript">
jQuery(function(){
	function get_psi_edimax() {
		var psi = '';
		var pt = '';
		var h = '';
		var t = '';
		var status = '';
		var img = '/dokuwiki/_media/psi:1.png';
 
		jQuery.getJSON('/edimax_psi.json', function(json) {
			if (json.hasOwnProperty('devices')) {
				jQuery.each(json['devices'], function(key, val) {
 
					if (val.hasOwnProperty('pm25')) {
						psi = parseInt(val['pm25']);
						var target = document.getElementById('pm25'); // your canvas element
						var gauge = new Gauge(target).setOptions(opts); // create sexy gauge!
						gauge.maxValue = 100; // set max gauge value
						gauge.animationSpeed = 32; // set animation speed (32 is default value)
						gauge.set(psi); // set actual value
 
						if (psi < 36) { // 低
							img = '/dokuwiki/_media/psi:1.png';
							status = '<span style="color:#31cf00">空品良好適合趴趴走</span>';
						} else if (psi < 54) { // 中
							img = '/dokuwiki/_media/psi:2.png';
							status = '<span style="color:#ff9a00">可正常戶外活動,若不適者請戴口罩</span>';
						} else if (psi < 71) { // 高
							img = '/dokuwiki/_media/psi:3.png';
							status = '<span style="color:#990000">不適者減少戶外活動,敏感族群建議戴口罩</span>';
						} else { // 非常高
							img = '/dokuwiki/_media/psi:4.png';
							status = '<span style="color:#ce30ff">不適者減少戶外活動,敏感族群避免外出</span>';
						}
					}
					if (val.hasOwnProperty('t')) {
						t = val['t'];
					}
					if (val.hasOwnProperty('h')) {
						h = val['h'];
					}
					if (val.hasOwnProperty('time')) {
						pt = val['time'];
					}
 
					jQuery('#psi_edimax img').attr('src', img);
					jQuery('#psi_edimax #edimax_psi_value').text(psi);
					jQuery('#psi_edimax #edimax_psi_t').text(t);
					jQuery('#psi_edimax #edimax_psi_h').text(h);
					jQuery('#psi_edimax #edimax_psi_pt').text(pt);
					jQuery('#psi_edimax #edimax_psi_status').html(status);
				});
			}
		});
	}
 
	get_psi_edimax();
	setInterval(get_psi_edimax, 1000*60*5);
});
</script>

6. 參考文件