No Code AI(肉寇)AI自動化兩日精通|實體6小時+線上6小時
|

【Project】如何使用LinkIt 7697建立智慧溫度監控平台(下)

   

作者:曹建國

本篇是《如何使用LinkIt 7697建立智慧溫度監控平台》下篇:視覺化技術一直是物聯網中非常關鍵的核心技術,所以我們可以透過行動裝置,例如手機、平板等,輕易查詢任何物聯網裝置所監控的資訊,這樣的開發技術,在物聯網領域中的應用,將會是非常好的開發典範。本文要使用上篇文章中所開發的溫濕度裝置,透過LinkIt 7697 開發板強大的WiFi功能,來建立一個溫溼度監控網站,讓家庭中所有成員都可以透過網際網路來獲得快速、正確的溫溼度資訊。

使用Google Developer網路資源

由於網路技術本來就是眾多技術的綜合體,加上視覺化的技術,如果我們拋棄前人所建立的技術不用,重新練功重新開發,那無異是愚公移山;等到開發完成後,資訊演進將進步到何種領域,基於技術演進與WebService的概念,筆者將使用Google Developer網路資源,可按此下載,如下圖所示,我們可以看到Google Developer己經建立了非常完整的網路資源,因此不需要再行建立冗長的程式碼,就可以達到想要的視覺化效果。

Google Developer網路資源

使用Line Chart視覺化技術

本文將使用Line Chart的視覺化技術,請點選Line Chart圖形或按此進入,如下表所示,就可以看到視覺化Line Chart圖形的技術網頁(Developers, 2016a, 2016b)。

視覺化Line Chart的效果

使用Line Chart 網頁程式碼

如下圖所示,我們使用視覺化Line Chart之Curve Fitting的效果,來作為本文的主要展示技術。

視覺化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,獲得更多及時文章更新&活動資訊→

加入好友

曹永忠

訂閱MakerPRO知識充電報

與40000位開發者一同掌握科技創新的技術資訊!

Author: 曹永忠

國立中央大學資訊管理學系博士,目前在國立暨南國際大學電機工程學系兼任助理教授、國立高雄科技大學商務資訊應用系兼任助理教授自由作家,專注於軟體工程、軟體開發與設計、物件導向程式設計、物聯網系統開發、Arduino開發、嵌入式系統開發。長期投入資訊系統設計與開發、企業應用系統開發、軟體工程、物聯網系統開發、軟硬體技術整合等領域,並持續發表作品及相關專業著作,並通過台灣圖霸的專家認證。

Share This Post On
468 ad

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *