作者:曹建國
本篇是《如何使用LinkIt 7697建立智慧溫度監控平台》下篇:視覺化技術一直是物聯網中非常關鍵的核心技術,所以我們可以透過行動裝置,例如手機、平板等,輕易查詢任何物聯網裝置所監控的資訊,這樣的開發技術,在物聯網領域中的應用,將會是非常好的開發典範。本文要使用上篇文章中所開發的溫濕度裝置,透過LinkIt 7697 開發板強大的WiFi功能,來建立一個溫溼度監控網站,讓家庭中所有成員都可以透過網際網路來獲得快速、正確的溫溼度資訊。
使用Google Developer網路資源
由於網路技術本來就是眾多技術的綜合體,加上視覺化的技術,如果我們拋棄前人所建立的技術不用,重新練功重新開發,那無異是愚公移山;等到開發完成後,資訊演進將進步到何種領域,基於技術演進與WebService的概念,筆者將使用Google Developer網路資源,可按此下載,如下圖所示,我們可以看到Google Developer己經建立了非常完整的網路資源,因此不需要再行建立冗長的程式碼,就可以達到想要的視覺化效果。
使用Line Chart視覺化技術
本文將使用Line Chart的視覺化技術,請點選Line Chart圖形或按此進入,如下表所示,就可以看到視覺化Line Chart圖形的技術網頁(Developers, 2016a, 2016b)。
使用Line Chart 網頁程式碼
如下圖所示,我們使用視覺化Line Chart之Curve Fitting的效果,來作為本文的主要展示技術。
如下表所示,我們只要將這些HTML Code存成LineChart.htm,在使用者端,使用瀏覽器來觀看LineChart.htm的內容,就可以輕易看到視覺化Line Chart圖形的效果。
視覺化Line Chart之HTML程式碼:
<html>
<head>
<script type=”text/javascript” src=”https://www.gstatic.com/charts/loader.js”></script>
<script type=”text/javascript”>
google.charts.load(‘current’, {‘packages’:[‘corechart’]});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
[‘Year’, ‘Sales’, ‘Expenses’],
[‘2004’, 1000, 400],
[‘2005’, 1170, 460],
[‘2006’, 660, 1120],
[‘2007’, 1030, 540]
]);
var options = {
title: ‘Company Performance’,
curveType: ‘function’,
legend: { position: ‘bottom’ }
};
var chart = new google.visualization.LineChart(document.getElementById(‘curve_chart’));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id=”curve_chart” style=”width: 900px; height: 500px”></div>
</body>
</html>
(資料來源:Google Developer)
解析Line Chart 網頁程式碼( HTML Code)
由下表所示,我們可以了解,必須將這裡的Google 網路元件的資源載入。
使用Google 資源:
<html>
<head>
<script type=”text/javascript” src=”https://www.gstatic.com/charts/loader.js”></script>
<script type=”text/javascript”>
google.charts.load(‘current’, {‘packages’:[‘corechart’]});
google.charts.setOnLoadCallback(drawChart);
由下表所示,我們可以了解要顯示Google Line Chart元件,必須將Line Chart的值給予Google Line Chart元件。
設定顯示資料:
function drawChart() {
var data = google.visualization.arrayToDataTable([
[‘Year’, ‘Sales’, ‘Expenses’],
[‘2004’, 1000, 400],
[‘2005’, 1170, 460],
[‘2006’, 660, 1120],
[‘2007’, 1030, 540]
]);
由上表所示,我們可以了解,[‘Year’, ‘Sales’, ‘Expenses’]為資料標題,第二列的[‘2004’, 1000, 400] 為資料的第一筆,而前面為資料名稱,後面是資料內容。
Line chart的值解析:
[‘Year’, ‘Sales’, ‘Expenses’]是資料標題
第二列的[‘2004’, 1000, 400] 為資料第一筆,
前面為資料名稱,後面為資料內容
由下表所示,我們必須設定Google Line Chart元件大小(寬度與高度),在Google Line Chart元件上,還有圖示標題的設定。
Line Chart的大小設定與警示區域設定:
var options = {
title: ‘Company Performance’,
curveType: ‘function’,
legend: { position: ‘bottom’ }
};
由上表所示,我們可以了解width: & height 為每一個Line Chart圖形的寬與高,而title: ‘Company Performance’則Line Chart圖形的標題內容。
由下表所示,我們可以了解產生一個Line Chart元件,並顯示在curve_chart的區域之中。
產生一個Line Chart元件:
var chart = new google.visualization.LineChart(document.getElementById(‘curve_chart’));
chart.draw(data, options);
由上表所示,我們可以了解new google.visualization.LineChart(document.getElementById(‘curve_chart’)); 就是產生Line Chart元件,而chart.draw(data, options)則會畫出Line Chart圖形。
由下表所示,我們可以了解,真正產生瀏覽器動作的區域是在<body>…</body>之間,所以真正產生圖形的內容為<div id=”curve_chart” style=”width: 900px; height: 500px”></div>。
真正產生瀏覽器動作命令:
<body>
<div id=”curve_chart” style=”width: 900px; height: 500px”></div>
</body>
由上表所示,我們可以了解,真正產生圖形的內容為<div id=”curve_chart” style=”width: 900px; height: 500px”></div>,為了設定產生圖形的大小,需要一些參數,所以width: 900px為繪圖空間寬度,height: 500px 繪圖空間高度。
Line Chart元件之瀏覽器動作命令:
<div id=”curve_chart” style=”width: 900px; height: 500px”></div> 產生叫” curve_chart的 繪圖空間
width: 900px 繪圖空間寬度
height: 500px;繪圖空間高度
視覺化溫度資訊
由於原來視覺化的Google Line Chart顯示二個維度資料,但是我們只需要顯示一個維度資訊,所以我們修改Line Chart的視覺化物件,可參考這裡;我們將原來HTML程式碼,修改為到下表所示的一個維度資訊之視覺化Line Chart之HTML程式碼。
我們先打開Arduino開發板的開發工具:Sketch IDE整合開發軟體(請按此下載;安裝Linkit 7697 SDK的方法請參考官網。)安裝驅動程式與Linkit 7697 SDK後,撰寫一段程式,也就是如下表所示之智慧溫度監控平台程式,我們就能透過WiFi連線,建立智慧溫度監控平台。
智慧溫度監控平台程式:
(程式碼可按此下載)
//this program is written by Bruce Tsao as Link 7697 Platform use
#include <LWiFi.h>
#define delaytime 4000
#include “DHT.h”
#define DHTPIN 8 // what digital pin we’re connected to
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);
char ssid[] = “IOT”; // your network SSID (name)
char pass[] = “iot12345”; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio’s status
IPAddress Meip , Megateway , Mesubnet ;
String MacAddress ;
uint8_t MacData[6];
WiFiServer server(80);
//—–end of wifi use
// store Temperature data as array
#define MaxData 20
float tempdata1[20] ;
float tempdata2[20] ;
int dataCount = 0 ;
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
Serial.println(“DHTxx test!”);
dht.begin();
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
MacAddress = GetWifiMac() ; // get MacAddress
ShowMac() ; //Show Mac Address
// attempt to connect to Wifi network:
initializeWiFi();
server.begin();
// you’re connected now, so print out the status:
ShowInternetStatus();
}// END Setup
static int count = 0;
void loop() {
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds ‘old’ (its a very slow sensor)
float h = dht.readHumidity();
// Read temperature as Celsius (the default)
float t = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
float f = dht.readTemperature(true);
tempdata1[dataCount] = t ;
dataCount++ ;
if (dataCount >= MaxData)
{
floatArrayCopy(tempdata1,tempdata2,MaxData) ;
dataCount = 0 ;
// data is fulled and copy into showarray
}
// wifi code here>=
// listen for incoming clients
WiFiClient client = server.available();
if (client)
{
Serial.println(“Now Someone Access WebServer”);
Serial.println(“new client”);
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected())
{
if (client.available())
{
char c = client.read();
Serial.write(c);
// if you’ve gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == ‘\n’ && currentLineIsBlank)
{
// send a standard http response header
client.println(“HTTP/1.1 200 OK”);
client.println(“Content-Type: text/html”);
client.println(“Connection: close”); // the connection will be closed after completion of the response
client.println(“Refresh: 5”); // refresh the page automatically every 5 sec
client.println();
client.println(“<!DOCTYPE HTML>”);
client.println(“<html>”);
// output the value of each analog input pin
client.println(” <head>”);
client.println(” <script type=’text/javascript’ src=’https://www.gstatic.com/charts/loader.js’></script>”);
client.println(” <script type=’text/javascript’>”);
client.println(“google.charts.load(‘current’, {‘packages’:[‘corechart’]});”);
client.println(“google.charts.setOnLoadCallback(drawChart);”);
client.println(” function drawChart() {“);
client.print(“var data = google.visualization.arrayToDataTable([[‘Time’, ‘Temperature’],” );
for (int i = 0 ; i <MaxData; i++)
{
client.print(“[‘”) ;
client.print(i);
client.print(“‘,”) ;
client.print(tempdata2[i]);
client.print(“]”) ;
if (i < (MaxData -1))
{
client.print(“,”) ;
}
}
client.println(“]);”);
client.println(” var options = {title: ‘目前溫度’,curveType: ‘function’,legend: { position: ‘bottom’ }};”);
client.println(“var chart = new google.visualization.LineChart(document.getElementById(‘curve_chart’));”);
client.println(“chart.draw(data, options);”);
client.println(“}”);
client.println(“</script>”);
client.println(“</head>”);
client.println(“<meta charset=’utf-8′>”);
client.println(“<body>”);
client.println(“<div id=’curve_chart’ style=’width: 1200px; height: 500px’></div>”);
client.println(“Now(“) ;
client.println(dataCount) ;
client.println(” )<br> “) ;
for (int i=0 ; i <MaxData ; i++)
{
client.println(i) ;
client.println(“/”) ;
client.println(tempdata1[i]) ;
client.println(” , “) ;
}
client.println(“</body>”);
client.println(“</html>”);
break;
}
if (c == ‘\n’)
{
// you’re starting a new line
currentLineIsBlank = true;
} else if (c != ‘\r’)
{
// you’ve gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println(“client disonnected”);
}
delay(delaytime) ;
} // END Loop
void printWifiData() {
// print your WiFi shield’s IP address:
IPAddress ip = WiFi.localIP();
Serial.print(“IP Address: “);
Serial.println(ip);
Serial.println(ip);
// print your MAC address:
WiFi.macAddress(MacData);
Serial.print(“MAC address: “);
Serial.print(MacData[0], HEX);
Serial.print(“:”);
Serial.print(MacData[1], HEX);
Serial.print(“:”);
Serial.print(MacData[2], HEX);
Serial.print(“:”);
Serial.print(MacData[3], HEX);
Serial.print(“:”);
Serial.print(MacData[4], HEX);
Serial.print(“:”);
Serial.println(MacData[5], HEX);
}
void initializeWiFi() {
while (status != WL_CONNECTED) {
Serial.print(“Attempting to connect to SSID: “);
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// status = WiFi.begin(ssid);
// wait 10 seconds for connection:
delay(10000);
}
Serial.print(“\n Success to connect AP:”) ;
Serial.print(ssid) ;
Serial.print(“\n”) ;
}
void printCurrentNet() {
// print the SSID of the network you’re attached to:
Serial.print(“SSID: “);
Serial.println(WiFi.SSID());
// print the MAC address of the router you’re attached to:
byte bssid[6];
WiFi.BSSID(bssid);
Serial.print(“BSSID: “);
Serial.print(bssid[5], HEX);
Serial.print(“:”);
Serial.print(bssid[4], HEX);
Serial.print(“:”);
Serial.print(bssid[3], HEX);
Serial.print(“:”);
Serial.print(bssid[2], HEX);
Serial.print(“:”);
Serial.print(bssid[1], HEX);
Serial.print(“:”);
Serial.println(bssid[0], HEX);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print(“signal strength (RSSI):”);
Serial.println(rssi);
// print the encryption type:
byte encryption = WiFi.encryptionType();
Serial.print(“Encryption Type:”);
Serial.println(encryption, HEX);
Serial.println();
}
void ShowInternetStatus()
{
if (WiFi.status())
{
Meip = WiFi.localIP();
Serial.print(“Get IP is:”);
Serial.print(Meip);
Serial.print(“\n”);
// print your subnet mask:
Mesubnet = WiFi.subnetMask();
Serial.print(“NetMask: “);
Serial.println(Mesubnet);
// print your gateway address:
Megateway = WiFi.gatewayIP();
Serial.print(“Gateway: “);
Serial.println(Megateway);
}
else
{
Serial.print(“DisConnected:”);
Serial.print(“\n”);
}
}
void ShowMac()
{
Serial.print(“MAC:”);
Serial.print(MacAddress);
Serial.print(“\n”);
}
String GetWifiMac()
{
String tt ;
String t1, t2, t3, t4, t5, t6 ;
WiFi.status(); //this method must be used for get MAC
WiFi.macAddress(MacData);
Serial.print(“Mac:”);
Serial.print(MacData[0], HEX) ;
Serial.print(“/”);
Serial.print(MacData[1], HEX) ;
Serial.print(“/”);
Serial.print(MacData[2], HEX) ;
Serial.print(“/”);
Serial.print(MacData[3], HEX) ;
Serial.print(“/”);
Serial.print(MacData[4], HEX) ;
Serial.print(“/”);
Serial.print(MacData[5], HEX) ;
Serial.print(“~”);
t1 = print2HEX((int)MacData[0]);
t2 = print2HEX((int)MacData[1]);
t3 = print2HEX((int)MacData[2]);
t4 = print2HEX((int)MacData[3]);
t5 = print2HEX((int)MacData[4]);
t6 = print2HEX((int)MacData[5]);
tt = (t1 + t2 + t3 + t4 + t5 + t6) ;
Serial.print(tt);
Serial.print(“\n”);
return tt ;
}
String print2HEX(int number) {
String ttt ;
if (number >= 0 && number < 16)
{
ttt = String(“0”) + String(number, HEX);
}
else
{
ttt = String(number, HEX);
}
return ttt ;
}
void floatArrayCopy(float *d1 , float *d2, int cnt)
{
for (int i= 0 ; i < cnt; i++)
{
*(d2+i) = *(d1+i) ;
}
如下圖所示,我們可以看到監控視窗之智慧溫度監控平台程式結果畫面。
由上圖所示,我們得知用LinkIt 7697 開發板建立的網頁伺服器,其網址由智慧溫度監控平台程式結果畫面取得,我們使用瀏覽器,輸入網址:192.168.88.106,這裡請各位讀者注意,讀者與筆者的網路環境差異很大,所以請大家參考在自己的開發環境中,實際取得的IP位址,用瀏覽器輸的正確的IP位址,才能看到正確的瀏覽器畫面。
網際網路實體智慧溫度監控平台
由於本文介紹智慧溫度監控平台之開發,對於網站平台之建置,需要網際網路上實體網址與合法的網域名稱,這部分技術並非本文主旨,請讀者參閱其他網站建站之相關文章與書籍,詳加閱讀之,必定可以完整建立網際網路上專屬的智慧溫度監控平台;本文則是使用開發環境中的虛擬網址,還請讀者們注意這個差異。
小結
本篇主要告訴讀者,在物聯網開發之中,運用聯發科技創意實驗室開發的「LinkIt 7697」開發板所建立的物聯網溫溼度感測裝置,並運用Google Developer網路資源與Web Service的技術,建立智慧家居中,可以隨時監控家居溫溼度的機制,讓家庭中所有成員都可以透過網際網路來獲得快速、正確的溫溼度資訊,未來筆者還會進階將此技術應用於更廣泛的物聯網開發之中。
(責任編輯:賴芳如)
◎加入我們的Line,獲得更多及時文章更新&活動資訊→
- 【大氣監控站台開發案例(下)】環境監控即時監控看板 - 2021/11/25
- 【大氣監控站台開發案例(中)】環境監控雲端平台系統介紹 - 2021/11/02
- 【大氣監控站台開發案例(上)】 大氣監控站建置實例介紹 - 2021/10/18
訂閱MakerPRO知識充電報
與40000位開發者一同掌握科技創新的技術資訊!