智能家居雲平臺設計

  javascript

智能家居是將來家居的發展方向,其利用先進的網絡技術、計算機技術和無線通訊技術等將家居中的各類電子電氣設備鏈接起來,統一管理、遠程監控和資源共享,實現了高效、便利的生活環境。近些年互聯網的迅猛發展,網絡的穩定性、安全性和網絡帶寬都有了長足的發展,由互聯網提供的各類服務已經深刻到人們生活的方方面面,所以將智能家居系統同互聯網結合起來,爲用戶提供遠程控制服務,延伸智能家居系統的使用空間,已經成爲智能家居系統發展的一種趨勢。php

基於此背景,本文設計了用於協做控制終端和智能家居網關實現智能家居遠程監控功能的雲平臺。論文首先闡述了智能家居的概念及發展趨勢,分析了智能家居雲平臺所涉及的關鍵技術。經過對無線智能家居系統結構的調研和了解,進行了智能家居雲平臺的需求分析。經過分析現有的較成熟的物聯網雲平臺,並結合智能家居網關和控制終端的特色,最終肯定了智能家居雲平臺的設計方案:採用應用層的HTTP協議做爲通訊協議,JSON格式做爲雲平臺響應數據格式,經過PHP編程,實現了雲平臺的基本功能和RESTful風格的API而後,結合設計方案,開始搭建系統開發環境,進行數據庫設計和系統環境配置。最終結合需求分析,在已搭建好的環境中,使用PHP完成智能家居雲平臺的功能設計。html

 

關鍵詞:智能家居,雲平臺,物聯網前端

 


 

Abstractjava

The Smart Home is the future direction of home life. It takes advantage of networking technology, computer technology and wireless communication technology to connect all kinds of electronic and electrical equipment at home to realize the unified management, remote monitoring and resource share, making the life more efficient and more convenient. With the rapid development of Internet in recent years, the stability of the internet and network bandwidth had great development, the Internet provide all kinds of service of all aspects of people's lives, so smart home system combined with the Internet, to provide remote control service, extend the smart home system, use the space, it has become a development trending of smart home system.mysql

Considering to this situation, the paper designs the smart home cloud platform used to assists control client and web control platform to implement the functionality of the remote control of smart home system. In this paper, we first introduce the basic concept and the development trending of Smart Home, and then analyze the related important technologies of the smart home cloud platform. By the research and understanding of the wireless smart home system, we execute the analysis of the demand of the smart home cloud platform. Through analyzing the stable cloud platform and combining the feature of smart home gateway and control client, we finally conclude the detailed design scheme of the platform: using HTTP protocol as communication protocol, JSON format as response data format, through PHP programming, implement all basic function of the Cloud Platform and RESTful style API. And combining the design scheme, we start building of the system development environment, designing the structure of the database and configuring the system. Finally, combining the analysis of the demand, in the built environment, use PHP to accomplish the functional design of the smart home cloud platform.nginx

 

Keywords: Smart Home, Cloud Platform, Internet of Thingsgit

 

 

  程序員

  ... Igithub

Abstract. II

1 緒論... 1

1.1 課題背景及來源... 1

1.2 智能家居概述及研究現狀... 1

1.3 智能家居雲平臺關鍵技術... 3

1.4 課題的研究目標與主要內容... 5

2 智能家居雲平臺設計方案與相關技術簡介... 7

2.1 需求分析... 7

2.2 通訊協議分析... 7

2.3 數據交互格式... 9

2.4 基本設計方案... 10

2.5 系統配置... 11

2.6 相關技術簡介... 12

3 智能家居雲平臺系統設計... 17

3.1 數據庫設計... 17

3.2 PHPRESTful API設計過程... 21

3.3 開發環境配置... 23

4. 智能家居雲平臺功能實現... 29

4.1 用戶類... 29

4.2 設備類... 31

4.3 傳感器類... 33

4.4 數據點類... 36

4.5 輔助接口... 40

5 系統測試及結果分析... 41

5.1 雲平臺系統測試要求... 41

5.2 雲平臺系統測試方法... 41

5.3 雲平臺請求和響應報文分析... 43

5.4 雲平臺測試結果... 45

5.5 雲平臺測試結果分析... 49

6 總結與展望... 50

6.1 工做過程總結... 50

6.2 不足及展望... 50

參考文獻... 53

 

 

 

1 緒論

1.1 課題背景及來源

網絡的普遍普及和通訊技術的高速度發展,給現在的社會帶來了數字化和信息化的改變。信息化從20世紀80年代開始就滲透到社會的各個領域並加快了各行各業的發展,現在科研、國防、商務、金融、企業管理和辦公都已經離不開網絡和信息技術。經過信息的傳遞實現社會、家居生活和人的融通,這是人們實現更高標準的生活的途徑,也是信息社會發展的必然。

近年來,物聯網成爲全球關注的熱點領域,被認爲是繼互聯網以後最重大的科技創新。物聯網經過射頻識別(RFID)、紅外感應器、全球定位系統、激光掃描器等信息傳感設備,按約定的協議把任何物品與互聯網鏈接起來進行信息交換和通信,以實現智能化識別、定位、跟蹤、監控和管理。

物聯網是互聯網的延伸,M2M是當前的主要應用。物聯網的遠景目標是把全部物品鏈接到互聯網,組成一個超大的智能網絡。通俗地說,物聯網是讓一切物品連上網絡,物品之間能夠直接對話和自動反應,這樣人們能夠在任什麼時候間、任何地點、任意地瞭解到任何物品的情況,而且能夠進行有效的控制。物聯網的發展爲智能家居引入了新的概念及發展空間,智能家居能夠被看做是物聯網的一種重要應用。

本課題來源於實際企業無線智能家居系統的需求。該系統致力於結合物聯網技術及其它無線傳輸技術(ZigbeeRFIDWIFI、藍牙),實現對智能家居設備的無線控制和智能管理。系統由智能家居設備、智能家居嵌入式網關、智能家居雲平臺、智能家居Web平臺和智能家居控制終端(手機等智能設備)組成。

其中智能家居雲平臺做爲數據存儲與交換的平臺,須要協同嵌入式網關和控制終端、Web平臺進行數據傳輸與通訊控制,實現對智能家居設備運行情況的記錄,並輔助控制終端和Web平臺完成對智能家居設備的遠程控制。

 

1.2 智能家居概述及研究現狀

智能家居概念的起源於20世紀80年代初,隨着大量採用電子技術的家用電器面市,住宅電子化開始實現;80年代中期,將家用電器、通訊設備與安全防範設備各自獨立的功能綜合爲一體,又造成了住宅自動化概念;至80年代末,因爲通訊與信息技術的發展,出現了經過總線技術對住宅中各類通訊、家電、安防設備進行監控與管理的商用系統,這在美國被稱爲Smart Home,也就是如今智能家居的原型。

當前的智能家居就是以住宅爲平臺,集網絡通訊、網絡系統和自動化控制於一體,經過互聯網技術將家庭設備聯繫成家庭網絡,實現遠程操控,爲人們提供了溫馨安全高效和便利的生活居住環境。

目前智能家居在歐美等發達國家獲得普遍應用。可是從嚴格意義上來講,智能家居仍是處於剛剛啓動的探索階段。美國的智能家居主要體如今追求溫馨、豪華感和享受上,它是以數字技術改造而展開的,但很是消耗能源。日本的智能家居主要體如今注重功能、以人爲本、環境保護與兼顧將來發展等幾個方面。並且日本的智能家居還注重施工過程的集團化與規模化,在設計施工中大量採用新技術新材抖。德國的智能家居體如今注重基本的功能性和追求專項功能的開發等方面。韓國的智能家居獲得政府的多項政策扶持,行政規定在首爾等大城市的新建的生活小區必須具有智能家居體系。中國智能家居的發展在經歷了很長時間的探索階段以後,國內的各具特色的智能家居系統也由各你們電巨頭生產商和通訊服務商紛紛推出。智能家居業獲得國內各大城市的政府部門的大力扶持,將智能家居體系包含到城市發展規劃中大大促進智能家居行業的發展。

智能家居行業熱點一波又一波,萬物互聯互通(即IOEinternet of everything)成了當下智能化的標準。互聯互通是指智能家居不受品牌,功能的約束,自動創建聯繫,收發數據信息,自動完成指令。實現這些功能的關鍵點是統一的雲平臺。雖然很早就有云平臺建設,部分企業亦投身到雲平臺建設,但一直沒有突破。

面對當下智能家居互聯互通的新趨勢,雲平臺做爲信息儲存傳輸的紐帶,扮演着重要角色。雲是物聯網的基礎,而統一的雲平臺可兼容各類先進技術,以知足客戶需求爲主,不受品牌的約束,集結各路優秀方案,在最短的時間內,使用戶獲得極致的體驗。智能家居做爲物聯網的重要分支,智能家居的雲平臺也是物聯網雲平臺的重要應用。

現今較成熟的物聯網雲平臺有「Yeelink雲平臺」、「飛比雲平臺」和「Ninja Platform」等。這些雲平臺將API公開給開發者,爲開發者提供數據處理和存儲服務。而開發者經過給定的API,用相應的方法將本身的設備信息傳遞到雲端進行處理,實現對設備的監控。

其中Ninja Platform以其自身的產品Ninja Block(智能家居網關)爲核心,將智能家居設備經過Ninja Block組成一個統一的總體,再鏈接到Ninja Platform實現遠程監控。Ninja Platform只支持本身的網關產品的接入,而且隱藏了網關與平臺鏈接的細節,只是簡單地提供一個接口用於鏈接。由於只支持本身的網關產品的接入,能夠實現不少複雜的控制細節,而且這些徹底由自身控制。所以,Ninja Platform在功能上顯得十分豐富,邏輯也十分合理,安全性也作的很好,更接近於一個完善的商業產品。而其開放API的意義在於,使用Ninja Block的用戶能夠經過使用這些API進行本身的控制終端的開發,用於實現一些本身但願的功能和擴展。

相比Ninja Platform,國內的Yeelink雲平臺的功能顯得有些簡陋。但Yeelink雲平臺的特色仍是很明顯的:他是一個幾乎徹底開放的物聯網雲平臺。雖然Yeelink雲平臺也有本身的設備提供,但它也支持其它設備的接入,這些接入的設備也不限制於家居網關。全部可以實現HTTP請求方法的設備,甚至一個實現HTTP請求的程序,均可以鏈接到Yeelink雲平臺,做爲被控對象。Yeelink雲平臺的API顯得更加抽象,全部具體的功能都抽象成對數據的操做。

 

1.3 智能家居雲平臺關鍵技術

雲計算(英語:Cloud Computing),是一種基於互聯網的計算方式,經過這種方式,共享的軟硬件資源和信息能夠按需求提供給計算機和其餘設備。目前關於雲計算系統沒有統一的定義,雲計算供應商根據本身企業業務推出相關的雲計算戰略。維基百科給雲計算下的定義爲:雲計算將IT相關的能力以服務的方式提供給用戶, 容許用戶在不瞭解提供服務的技術、沒有相關知識以及設備操做能力的狀況下,經過Internet獲取須要的服務[9]

雲計算的基本原理是,經過虛擬化技術使計算分佈在大量的分佈式計算機上,這使得企業可以將資源切換到須要的應用上,根據需求訪問計算機和存儲系統。

咱們能夠把實際環境中的「雲」提供的服務分爲三大類。它們是:

軟件即服務(Software as a serviceSaaS):SaaS應用是徹底在「雲」裏(也就是說,一個Internet服務提供商的服務器上)運行的。其戶內客戶端(on-premises client)一般是一個瀏覽器或其餘簡易客戶端。Salesforce多是當前最知名的SaaS應用,不過除此之外也有許多其餘應用。

附着服務(Attached services):每一個戶內應用(on-premises application)自身都有必定功能,它們能夠不時地訪問「雲」裏針對該應用提供的服務,以加強其功能。因爲這些服務僅能爲該特定應用所使用,因此能夠認爲它們是附着於該應用的。一個著名的消費級例子就是蘋果公司的iTunes:其桌面應用可用於播放音樂等等,而附着服務令用戶購買新的音頻或視頻內容成爲可能。微軟公司的Exchange託管服務是一個企業級例子,它能夠爲戶內Exchange服務器增長基於「雲」的垃圾郵件過濾、存檔等服務。

雲平臺(Cloud platforms):所謂雲平臺,通常理解爲雲計算平臺,爲用戶提供雲計算服務。這種平臺容許開發者們或是將寫好的程序放在「雲」裏運行,或是使用「雲」裏提供的服務,或兩者皆是。雲平臺提供基於「雲」的服務,供開發者建立應用時採用。你沒必要構建本身的基礎,你徹底能夠依靠雲平臺來建立新的SaaS應用。雲平臺的直接用戶是開發者,而不是最終用戶。

1.1 雲計算架構

 

物聯網被稱爲繼計算機、互聯網以後,世界信息產業的第三次浪潮。目前多個國家都在花巨資進行深刻研究,物聯網是由多項信息技術融合而成的新型技術體系。「物聯網」的概念於1999年由麻省理工學院的Auto-ID實驗室提出,將書籍、鞋、汽車部件等物體裝上微小的識別裝置,就能夠時刻知道物體的位置、狀態等信息,實現智能管理。

20051117日,在突尼斯舉行的信息社會世界峯會(WSIS)上,國際電信聯盟(ITU)發佈了《ITU互聯網報告2005:物聯網》,正式提出了「物聯網」的念。報告指出:無所不在的「物理網」通訊時代即未來臨,世界上全部的物體均可以經過互聯網主動進行信息交換。射頻識別技術(RFID)、無線傳感器網絡技術(WSN)、納米技術、智能嵌入技術將獲得更加普遍的應用。

能夠認爲,「物聯網」(Internet of Things)是指將各類信息傳感設備及系統,如傳感器網絡、射頻標籤閱讀裝置、條碼與二維碼設備、全球定位系統和其它基於物物通訊模式(M2M)的短距無線自組織網絡,經過各類接入網與互聯網結合起來而造成的一個巨大智能網絡。若是說互聯網實現了人與人之間的交流,那麼物聯網能夠實現人與物體的溝通和對話,也能夠實現物體與物體互相間的鏈接和交互。

1.2 物聯網概念模型

 

物聯網就是互聯網經過傳感網絡向物理世界的延伸,它的最終目標就是對物理世界進行智能化管理。物聯網的這一使命,也決定了它必然要由一個大規模的計算平臺做爲支撐。因爲雲計算從本質上來講就是一個用於海量數據處理的計算平臺,所以,雲計算技術是物聯網涵蓋的技術範疇之一。隨着物聯網的發展,將來的物聯網將勢必產生海量數據,而傳統的硬件架構服務器將很難知足數據管理和處理要求。若是將雲計算運用到物聯網的傳輸層與應用層,採用雲計算的物聯網,將會在很大程度上提升運行效率。能夠說,若是把物聯網看成一臺主機的話,雲計算就是它的CPU

雲計算與物聯網各自具有不少優點,若是把雲計算平臺與物聯網結合起來,就構形成物聯網雲平臺。該平臺經過物聯網技術將傳感器鏈接到一塊兒,再經過雲計算的技術對數據進行分佈式存儲與處理,由此能克服大規模的數據存儲與計算問題,完善了物聯網的構成。就本課題而言,智能家居雲平臺在功能上更接近於物聯網雲平臺。智能家居雲平臺將數據存儲和處理服務置於雲端,經過相應接口提供智能家居設備的相關監控服務。

 

1.4 課題的研究目標與主要內容

爲了實現智能家居的遠程控制,控制終端須要同家庭網關進行通訊,將控制命令發送給網關。然而,每一個家庭接入網絡的類型不盡相同,在中國的家庭用戶中則以ADSL技術爲主。並且,因爲ISP提供的接入服務也不盡相同,大多數家庭接入互聯網時,使用的是服務商提供的動態IP。因爲目標的IP地址動態變化,這會給控制終端同家庭網關的通訊形成了很大的不便。

本課題提出的目的之一,就是經過爲了創建雲平臺來克服這種不便,消除網絡接入方式的不一樣而形成的差別,實現智能家居設備的遠程管理和控制。

另外一方面,爲了智能家居Web控制平臺的實現,也須要智能家居雲平臺的建設。若是將數據存儲和處理置於智能家居網關內,或另外實現嵌入式服務器,毫無疑問將加大智能家居設備的成本,也加大了開發難度,不利於商業推廣。而創建雲平臺以後,不只利於Web平臺的實現,還能將功能集中,方便系統開發與服務升級。只要保證雲平臺基本API不變,雲平臺內部的功能能夠很方便的進行開發和升級。而對於嵌入式設備(智能家居網關等),一旦生產出來,因爲硬件方面的限制,只能進行有限的軟件更改;而一旦售出以後,更難進行全面系統的修正。

本課題中的智能家居雲平臺將結合HTTP協議使用PHP進行程序開發,實現最基本與核心的數據存儲和處理,並完成系統的測試。

 

 

 

2 智能家居雲平臺設計方案與相關技術簡介

2.1 需求分析

智能家居雲平臺是爲了實現智能家居系統的遠程監控而搭建的。智能家居網關必須接入互聯網,而且按照必定的格式將被控設備的狀態信息實時發送給雲平臺,才能保證信息的實時性。雲平臺處理數據以後,將之暫時保存在數據庫中。當終端訪問雲平臺時,雲平臺可以將設備的數據提供給終端,終端以可視化的形式展示給用戶。雲平臺要求能接受終端發出的控制命令,將之保存並轉發給家居網關,完成對設備的控制。

雖然該課題中的雲平臺並非直接面向用戶,但設計時也要爲考慮到用戶的需求,這樣才能保證方案的可行性。

雲平臺要實現的最終的功能是對智能家居設備的監控:

(1)     接受智能家居網關發送設備的狀態信息,並進行處理和存儲;

(2)     接受控制終端的請求,返回設備的狀態信息;

(3)     協調控制終端和智能家居網關之間控制命令的交互。

 

雲平臺更具體的功能則相似於通常的信息管理系統:

(1)     用戶認證:設備都有本身的歸屬,用戶只能控制本身的設備,只有經過認證以後才能查看和控制設備;

(2)     設備管理:應該容許用戶本身添加須要的設備,移除再也不須要的設備;

(3)     運行記錄(或稱歷史記錄):全部的監控系統都應該記錄設備的運行狀態。

對於開發者而言,爲了運行維護的方便,錯誤日誌功能是必須的。不管是記錄在數據庫中仍是以文件的形式保存,都要能將相應的錯誤時間和錯誤信息記錄下來,以供調試和測試時查看。

 

2.2 通訊協議分析

網絡協議是分層的,其中應用層協議主要是解決網絡中通訊雙方應採用哪一種數據傳輸規則來實現數據收發的,即定義了網絡中兩個通訊進程之間交互數據應遵循的規則。大部分的應用層協議都是爲了解決某一類具體應用而存在的。

在網絡數據通訊中,應用層常見的數據傳輸標準協議主要有:HTTPHypertext Transport Protocol,超文本傳輸協議),IMInstant Message,即時通訊)協議,FTPFile Transfer Protocol,文件傳輸協議)協議,SMTPSimple Mail Transfer Protocol,郵件傳輸協議),遠程登錄協議Telnet等。

文件傳輸協議FTP,主要用於解決異構網絡中文件資源的傳輸,可以提供可靠的文件傳輸,消除不一樣操做系統或者不一樣文件系統互不兼容的缺點,從而實現文件資源的共享。

郵件傳輸協議SMTP,是爲了解決實時通訊的不足而產生的,傳輸層採用的協議是TCP協議,採用的默認端口是25,郵件發送和接收整個過程須要用到的郵件傳送協議和POP3,其中前者主要完成將郵件上傳至服務器和在服務器之間傳送郵件,然後者主要完成接收端的接受任務。

遠程登陸協議Telnet主要用於實現本地用戶登陸遠程系統,採用半雙工的方式實現對遠程資源的訪問,本地客戶端實現對遠程主機的訪問必須作到下列要求:本地客戶端支持遠程登錄協議、正確輸入遠程主機系統的IP地址、正確輸入登陸主機名稱與登陸密碼。

即時通訊協議IM,可以實現網絡用戶的實時通訊,傳輸的數據包括文字、圖片、視頻、音頻等。通訊的過程是:客戶端要完成註冊並添加通訊另外一客戶端爲通訊好友,隨後才能進行雙方的通訊。比較著名的即時通訊協議有:IMPPSIMPLEJabber/XMPP

超文本文檔傳輸協議HTTP,定義了數據傳輸的格式和傳輸時應遵循的規則,傳輸層採用TCP面向無鏈接的方式進行數據傳輸的。該協議是經過請求應答機制來實現的,可以可靠的傳輸包括文檔、圖片、視頻等全部數據。該協議多用於瀏覽器與WEB服務器之間的交互,在某些客戶端軟件中也常用。

在智能家居系統中,直接負責對家居設備的控制的是家庭網關。雲平臺則是爲了實現控制的空間上的擴展而搭建,須要考慮的是怎麼把網關處理的設備的信息簡單高效的接收過來進行處理,又如何高效的將控制終端的控制命令簡單高效的發送給網關處理。

智能家居系統中的家庭網關大多爲嵌入式網關,而且已經移植TCP/IP協議,能經過發送HTTP報文與雲平臺進行通訊。而控制終端設定爲安卓手機,有專門的應用實現智能家居系統的監控,同雲平臺之間的通訊也能夠經過HTTP報文的實現。

這樣,雲平臺以WEB服務器的方式進行開發能夠帶來不少便利。在初期的開發時,只須要專一於數據的處理和傳輸便可,沒必要去設計專門的WEB頁面。雖然使用WEB技術實現用戶界面很簡單,但要使得界面交互良好,給用戶帶去完美的用戶體驗,則須要涉及不少網頁方面的技術,如JavaScriptCSS等。在本課題中,重點在於雲平臺功能的實現,因此不涉及頁面的設計。

雲平臺與控制終端和家庭網關之間的通訊還能夠經過socket編程來實現,並且在服務器實現socket通訊的方式也有不少選擇,JavaC語言均可以實現,甚至PHP也有socket的接口函數。使用socket,網關和終端與服務器之間創建的是長期的鏈接,實時性較好。

雲平臺以WEB服務的方式進行開發時,則能夠經過網關定時發送HTTP報文的方法來更新雲平臺上記錄的設備信息。經過調整改變發送報文的間隔,就能夠達到不一樣的實時性的要求了。

 

2.3 數據交互格式

對於本課題的雲平臺而言,須要一種結構化的描述語言做爲數據格式,用以承受結構明確的請求數據和返回數據。

經過調研現有的物聯網雲平臺的設計方案以及API設計,可以發現現有的幾個成熟的雲平臺都在使用JSON做爲數據交互格式。而且在移動端的應用中,JSON也是做爲數據交互格式被普遍使用。而XML一樣做爲一種功能強大的標記語言被普遍用在Web服務中,天然也是一種不錯的選擇。

 

JSONJavaScript Object Notation)是一種輕量級的數據交換格式。它是基於JavaScriptStandard ECMA-262 3rd Edition - December 1999)的一個子集。 JSON採用徹底獨立於語言的文本格式,可是也使用了相似於C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成爲理想的數據交換語言。易於人閱讀和編寫,同時也易於機器解析和生成。

JSON 語法是 JavaScript 對象表示法語法的子集。JSON 數據的書寫格式是:名稱/值對。

名稱/值對包括字段名稱(在雙引號中),後面寫一個冒號,而後是值:"firstName" : "John"。這很容易理解,等價於這條 JavaScript 語句:firstName = "John"

JSON簡單說就是JavaScript中的對象和數組,因此這兩種結構就是對象和數組兩種結構,經過這兩種結構能夠表示各類複雜的結構。

(1)     對象:對象在JavaScript中表示爲「{}」括起來的內容,數據結構爲 {keyvalue, keyvalue,...}的鍵值對的結構,在面向對象的語言中,key爲對象的屬性,value爲對應的屬性值,因此很容易理解,取值方法爲 對象.key 獲取屬性值,這個屬性值的類型能夠是數字、字符串、數組、對象幾種。

(2)     數組:數組在JavaScript中是中括號「[]」括起來的內容,數據結構爲 ["java","javascript","vb",...],取值方式和全部語言中同樣,使用索引獲取,字段值的類型能夠是 數字、字符串、數組、對象幾種。

 

XMLeXtensible Markup Language,可擴展標記語言,是一種標記語言。標記指計算機所能理解的信息符號,經過此種標記,計算機之間能夠處理包含各類信息的文章等。XML設計用來傳送及攜帶數據信息,不用來表現或展現數據,HTML語言則用來表現數據,因此XML用途的焦點是它說明數據是什麼,以及攜帶數據信息。

 

JSONXML的比較:

(1)     編碼難度:XML有豐富的編碼工具,好比Dom4jJDom等,JSON也有提供的工具。在沒有工具的狀況下,相信熟練的開發人員同樣能很快的寫出想要的XML文檔和JSON字符串,不過,XML文檔要多不少結構上的字符。

(2)     可讀性:XML有明顯的優點,畢竟人類的語言更貼近這樣的說明結構。JSON讀起來更像一個數據塊,讀起來就比較費解了。不過,咱們讀起來費解的語言,偏偏是適合機器閱讀。

(3)     有效數據率。JSON做爲數據包格式傳輸的時候具備更高的效率。這是由於JSON不像XML那樣須要有嚴格的閉合標籤,這就讓有效數據量與總數據包比大大提高,從而減小同等數據流量的狀況下,網絡的傳輸壓力。

 

本課題搭建的雲平臺的主要任務是完成數據的處理、存儲和轉發。雖然,PHPXMLJSON這兩種格式的數據都有支持,但在考慮數據傳輸效率的狀況下,包含大量冗餘標籤的XML明顯沒有JSON方便。顯然這也是其餘物聯網雲平臺選擇JSON格式做爲數據交互格式的重要緣由之一。

 

2.4 基本設計方案

經過以上雲平臺需求和通訊協議方面的分析,咱們初步肯定了如下的雲平臺設計方案:

(1)   智能家居網關和智能家居控制終端同雲平臺之間的通訊協議使用應用層的HTTP協議,使用HTTP請求來向雲平臺請求服務(包括保存數據和發出控制命令等)。

(2)   雲平臺僅實現純粹的數據處理服務,不涉及界面實現,提供統一的API接口,供智能家居網關、智能家居控制終端、智能家居Web控制平臺使用。

(3)   雲平臺將使用PHP語言進行開發,使用JSON做爲數據交互格式,來實現雲平臺各項功能。

 

以上設計方案的特色有:

(1)   對外而言,雲平臺提供的接口是一致的,訪問的方式也是相同的。所以,雲平臺能同時支持B/S(智能家居Web控制平臺)和C/S(智能家居遠程控制終端)架構的開發。

(2)   使用HTTP協議做爲通訊協議,使用HTTP基本方法(GETPOSTPUTDELETE等)進行服務請求,不一樣平臺訪問API的方法具備一致性。

(3)   雲平臺僅負責數據處理,不涉及界面實現,使得各個控制平臺都能根據本身的平臺特色進行界面開發,並且不影響功能的實現。

 

2.5 系統配置

雲平臺處於雲端,搭載於服務器中。現有的服務器爲阿里云云服務提供的雲服務器(ECS),操做系統爲CentOS 6.3 64位,其餘硬件配置略。服務器系統環境已經知足需求,不須要作任何更改。

根據以前肯定的基本方案,雲平臺以HTTP協議爲基礎,以Web服務的形式實現,PHP編程開發。那麼咱們首先須要選擇合適的Web服務器軟件。由於肯定了雲平臺的開發語言爲PHP,則Web服務器軟件只需從ApacheNginx之間選擇一個便可。雲平臺數據的管理方面,則能夠從OracleMySQL之間進行選擇。

Apache的優點在於開源、穩定、模塊豐富,缺點是有些臃腫,內存和CPU開銷大,性能上有損耗,不如輕量級的Nginx服務器高效。在靜態文件處理、PHP-CGI的支持、反向代理功能、前端Cache、維持鏈接等方面,Nginx都優於Apache。在Apache+PHPprefork)模式下,若是PHP處理慢或者前端壓力很大的狀況下,很容易出現Apache進程數飆升,從而拒絕服務的現象。Nginx處理請求是異步非阻塞的,而Apache則是阻塞型的,在高併發Nginx能保持低資源低消耗高性能。Nginx使用更少的資源,支持更多的併發鏈接,體現更高的效率,這點使 Nginx尤爲受到虛擬主機提供商的歡迎。

考慮到雲平臺的特色,低消耗、高併發的Nginx服務器是比較理想的選擇。

MySQL是一種關聯數據庫管理系統,關聯數據庫將數據保存在不一樣的表中,而不是將全部數據放在一個大倉庫內,這樣就增長了速度並提升了靈活性。MySQL所使用的SQL語言是用於訪問數據庫的最經常使用標準化語言。MySQL軟件採用了雙受權政策,它分爲社區版和商業版,因爲其體積小、速度快、整體擁有成本低,尤爲是開放源碼這一特色,通常中小型網站的開發都選擇MySQL做爲網站數據庫。因爲其社區版的性能卓越,搭配PHPApache可組成良好的開發環境。PHP中提供了一整套的MySQL函數,對MySQL進行了全方位的支持。

與其餘的大型數據庫例如OracleDB2SQL Server等相比,MySQL自有它的不足之處,可是這絲毫也沒有減小它受歡迎的程度。對於通常的我的使用者和中小型企業來講,MySQL提供的功能已經綽綽有餘,並且因爲MySQL是開放源碼軟件,所以能夠大大下降整體擁有成本。

由此,服務器軟件配置的肯定爲,Nginx做爲Web服務器,MySql做爲數據庫管理系統。

 

2.6 相關技術簡介

2.6.1 HTTP協議簡介

HTTPHypertext Transfer protocol,超文本傳輸協議)是在萬維網上進行通訊所使用的協議方案。HTTP 協議是應用層的協議,其著名的應用是用於Web瀏覽器和Web服務器之間的雙工通訊。

HTTP協議所提供的無鏈接是基於TCP的無鏈接,它要求客戶端在啓動一個請求時,須要先創建鏈接,等待服務器響應,請求完成之後,服務器不會繼續維護該鏈接,也就不用耗費資源來保存歷史記錄,能夠達到節約資源的目的。

HTTP協議具備較好的靈活性,處理速度可以知足超媒體系統的要求,由於它能夠傳輸任何類型的數據,用戶能夠根據須要本身定義數據類型,再加上HTTP協議是無狀態的協議,減小了HTTP冗餘的信息,提升了系統的運行效率,而且客戶端能夠在瀏覽器上處理大量的數據,因此在須要鏈接服務器時,只須要發送較少的信息,就能夠很快速的創建鏈接。

HTTP 協議是採用請求/響應模式的協議,它經過消息來實現客戶端與服務器之間的信息交互,請求消息是客戶端發送給服務器端用來請求發送數據的消息,響應消息是服務器接受到客戶端提出的請求後返回給客戶端的消息。

 

HTTP請求(request)的方法有GETPOSTPUTDELETEHEADTRACEOPTIONS。其中,GET方法一般用於請求服務器發送某個方法;HEAD方法與GET方法相似,但要求服務器只返回響應報文的首部(header);PUT方法一般用於添加一個新的資源或修改一個資源;POST方法起初用於向服務器輸入數據,服務器接收數據後如何處理視具體而定;DELETE方法用於請求服務器刪除某個資源;TRACE方法用於追蹤數據報文的轉發和修改;OPTIONS方法用於請求Web服務器告知其支持的方法。

HTTP響應(response)的內容是服務器接收客戶端的HTTP請求以後的響應信息,具體內容視具體的請求方法、請求內容和服務器的功能而定。

HTTP請求的方法的功能並非固定的,請求以後相應的內容也徹底由服務器控制,能夠根據服務器的功能自行設定,這正是HTTP協議靈活性的體現。

 

HTTP報文是簡單的格式化數據塊。每條報文都包含一條來自客戶端的請求,或者一條來自服務器的響應。報文由三個部分組成:對報文進行描述的起始行(start line),包含屬性的首部(header)塊,以及可選的、包含數據的主體(body)部分。

全部的HTTP報文均可以分爲兩類:請求報文(request message)和響應報文(response message)。請求報文會向服務器請求一個動做,響應報文會將請求的結果返回客戶端。請求和響應報文的基本報文結構相同,只有起始行的語法不一樣。

請求報文的格式:

<method> <request-URL> <version>

<headers>

<CR><LF>//空行

<entity-body>

響應報文的格式:

<version> <status> <reason-phrase>

<headers>

<CR><LF>//空行

<entity-body>

 

2.6.2 PHP語言簡介

PHP(全稱:PHPHypertext Preprocessor,即「PHP:超文本預處理器」),是一種被普遍應用的開源通用腳本語言,尤爲適用於 Web 開發並可嵌入 HTML 中去。它的語法利用了 CJava Perl,易於學習。該語言的主要目標是容許 web 開發人員快速編寫動態生成的 web 頁面,但 PHP 的用途遠不僅於此[22]

PHP的應用範圍至關普遍,尤爲是在網頁程序的開發上。通常來講PHP大多運行在網頁服務器上,經過運行PHP代碼來產生用戶瀏覽的網頁。PHP能夠在多數的服務器和操做系統上運行,並且使用PHP徹底是免費的。根據20074月的統計數據,PHP已經被安裝在超過2000萬個網站和100萬臺服務器上。

 

PHP源代碼是能夠直接讀取的,即便放到服務器上運行也是同樣。雖然讓PHP多了彈性,但相對的會形成安全危機和性能降低的問題。

經過PHP編碼器,能夠保護PHP的源代碼不被讀取(對商業軟件來講特別有需求),也能夠提高運行的性能。有許多公司或團體開發PHP的編碼器,將PHP程序編譯成字節碼(byte code),再經過服務器上安裝對應的程序來運行PHP腳本。

除了經過編碼器加速以外,PHP還能夠經過動態的高速緩存機制來提高速度,加速工具備商業版的,例如Zend Platform,也有開放源代碼的加速軟件如eAcceleratorAPCXCache

模板引擎讓PHP應用程序能夠作邏輯和使用界面上的分離,讓程序開發更容易進行,目前比較受歡迎的模板引擎是PHP官方開發的Smarty。不過模板引擎存在性能方面的爭議,由於PHP自己就是一個模板引擎,使用模板引擎反而變成「從新發明了輪子」(reinventing the wheel)。模板引擎最主要的好處就是讓不懂PHP代碼的人也能夠參與使用界面的開發,由於模板引擎的語言遠比PHP簡單。例如很是經典的MVC結構(模型-視圖-控制)便是對模板引擎的最好應用,讓PHP編程人員能夠和HTML前端程序員分工合做。

PHP能作任何事。PHP主要是用於服務端的腳本程序,所以能夠用PHP來完成任何其它的CGI程序可以完成的工做,例如收集表單數據,生成動態網頁,或者發送/接收Cookies。但PHP的功能遠不侷限於此。

PHP腳本主要用於如下三個領域:

(1)     服務端腳本。這是 PHP最傳統,也是最主要的目標領域。開展這項工做須要具有如下三點:PHP解析器(CGI或者服務器模塊)、web服務器和web瀏覽器。須要在運行web服務器時,安裝並配置PHP,而後,能夠用web瀏覽器來訪問PHP程序的輸出,即瀏覽服務端的PHP頁面。

(2)     命令行腳本。能夠編寫一段PHP腳本,而且不須要任何服務器或者瀏覽器來運行它。經過這種方式,僅僅只須要PHP解析器來執行。這種用法對於依賴cronUnix或者Linux環境)或者Task SchedulerWindows 環境)的平常運行的腳原本說是理想的選擇。這些腳本也能夠用來處理簡單的文本。

(3)     編寫桌面應用程序。對於有着圖形界面的桌面應用程序來講,PHP或許不是一種最好的語言,可是若是用戶很是精通PHP,而且但願在客戶端應用程序中使用PHP的一些高級特性,能夠利用PHP-GTK來編寫這些程序。用這種方法,還能夠編寫跨平臺的應用程序。

PHP可以在全部的主流操做系統上使用,包括 LinuxUnix的各類變種(包括 HP-UXSolarisOpenBSD)、Microsoft WindowsMac OS XRISC OS等。今天,PHP已經支持了大多數的web服務器,包括ApacheMicrosoft Internet Information ServerIIS)、Personal Web ServerPWS)、Netscape 以及iPlant serverOreilly Website Pro ServerCaudiumXitamiOmniHTTPd等。對於大多數的服務器,PHP提供了一個模塊;還有一些PHP支持CGI標準,使得PHP可以做爲CGI處理器來工做。

 

綜上所述,使用PHP,能夠自由地選擇操做系統和Web服務器。同時,還能夠在開發時選擇使用面對過程和麪對對象,或者二者混和的方式來開發。儘管PHP 4不支持OOP全部的標準,但不少代碼倉庫和大型的應用程序(包括PEAR庫)僅使用OOP代碼來開發。PHP 5彌補了PHP 4的這一弱點,引入了徹底的對象模型。

 

2.6.3 RESTful架構簡介

REST(英文:Representational State Transfer,中文:表現層狀態轉化)是Roy Fielding博士在2000年他的博士論文中提出來的一種軟件架構風格。

目前在三種主流的Web服務實現方案中,由於REST模式與複雜的SOAPXML-RPC相比更加簡潔,愈來愈多的web服務開始採用REST風格設計和實現。例如,Amazon.com提供接近REST風格的Web服務進行圖書查找;雅虎提供的Web服務也是REST風格的。

REST是設計風格而不是標準。REST一般基於使用HTTPURI,和XML以及HTML這些現有的普遍流行的協議和標準。若是一個架構符合REST原則,就稱它爲RESTful架構。

REST的名稱「表現層狀態轉化」中,省略了主語。「表現層」其實指的是「資源」(Resources)的「表現層」。

所謂「資源」,就是網絡上的一個實體,或者說是網絡上的一個具體信息。它能夠是一段文本、一張圖片、一首歌曲、一種服務,總之就是一個具體的實在。每種資源對應一個特定的URI。要獲取這個資源,訪問它的URI就能夠。所以URI就成了每個資源的地址或獨一無二的識別符。對資源的操做包括獲取、建立、修改和刪除資源,這些操做正好對應HTTP協議提供的GETPOSTPUTDELETE方法。

資源是一種信息實體,它能夠有不少種外在表現形式。咱們把資源具體呈現出來的形式,叫作它的表現層 URI只表明資源的實體,不表明它的形式。HTTP請求的頭信息中用AcceptContent-Type字段指定,這兩個字段纔是對表現層的描述。

經過操做資源的表現形式來操做資源。

互聯網通訊協議HTTP協議,是一個無狀態協議。這意味着,全部的狀態都保存在服務器端。所以,若是客戶端想要操做服務器,必須經過某種手段,讓服務器端發生"狀態轉化"State Transfer)。而這種轉化是創建在表現層之上的,因此就是"表現層狀態轉化"

客戶端用到的手段,只能是HTTP協議。具體來講,就是HTTP協議裏面,四個表示操做方式的動詞:GETPOSTPUTDELETE。它們分別對應四種基本操做:GET用來獲取資源,POST用來新建資源(也能夠用於更新資源),PUT用來更新資源,DELETE用來刪除資源。

綜合上面的解釋,總結RESTful架構的要點:

(1)     每個URI表明一種資源;

(2)     客戶端和服務器之間,傳遞這種資源的某種表現層;

(3)     客戶端經過四個HTTP方法,對服務器資源進行操做,實現「表現層狀態轉化」。

RESTful架構的優勢:

(1)     可更高效利用緩存來提升響應速度

(2)     通信自己的無狀態性可讓不一樣的服務器的處理一系列請求中的不一樣請求,提升服務器的擴展性

(3)     瀏覽器便可做爲客戶端,簡化軟件需求

(4)     相對於其餘疊加在HTTP協議之上的機制,REST的軟件依賴性更小

(5)     不須要額外的資源發現機制

(6)     在軟件技術演進中的長期的兼容性更好

 

在雲平臺設計過程當中,使用RESTful API能夠使接口的URI變得意義明確,結合HTTP方法來定義操做易於接受和理解,利於開發者對API的理解和使用,也方便本身後續的開發和修改。這也是大部分Web服務使用RESTful API的緣由。

 


 

3 智能家居雲平臺系統設計

3.1 數據庫設計

3.1.1 系統結構分析

對於實際的一個設備,能夠有多個傳感器,用來表示設備不一樣的狀態;也能夠有多個執行器,用來接受發出的控制命令。好比,對於無線智能家居系統中現有的可調顏色的RGB燈而言,它有一個開關型的傳感器來獲取燈的開關狀態,一個用於保存RGB值的傳感器來獲取RGB燈的顏色。固然,RGB燈的開關和RGB值都是可控的,因此須要有兩個執行器用於接受這兩個設定值。

對於傳感器而言,通常來講其值由智能家居網關獲取並上傳至雲平臺,而控制終端只有讀取的權限;對於執行器而言,在遠程控制時,通常由控制終端來上傳設定值,發送控制命令,由智能家居網關讀取值,執行控制命令。

由以上分析可知,對於傳感器和執行器,通常都只有一方(智能家居網關或控制終端)寫入數據,另外一方讀取數據。咱們能夠將傳感器和執行器統一爲傳感器,但爲之分配不一樣的類型,用來標記傳感器類型的差異,由智能家居網關和控制終端負責根據其類型,進行不一樣的處理。

這樣作的目的在於,做爲一個面向後續開發的系統,充分保證智能家居網關和控制終端的靈活性。同時也弱化雲平臺系統的特異性,儘可能使全部的操做統一,並退化爲對數據的操做,方便功能的擴展。固然,在後續的面對客戶的版本發佈時,應該完善這些操做方面的限制。

數據點應該由時間戳和數值組成,同時還要有個字段標記數據點所屬的傳感器。對於不一樣類型的傳感器,其值的類型和範圍都會有差異,爲了提升數據庫空間的利用效率,能夠將不一樣類型的傳感器的數據點保存在不一樣的表中。

 

由此,智能家居系統中的基本結構可肯定爲:一個具體設備(device)由多個傳感器(sensor)構成,每一個傳感器有本身的類型(type),每一個傳感器同時還有對應不一樣時間的多個數據點(datapoint)。每一個具體的設備屬於不一樣的用戶(user),特定的用戶只能操做屬於本身的設備。

 

3.1.2 數據庫E-R

通過初步的分析以及其它方面的補充,得出如下數據庫E-R圖:

3.1 數據庫E-R

 

3.1.3 數據庫表結構分析

數據類型說明(針對MySQL):

(1)     varchar(n):可變長度字符串,最長爲n

(2)     int:整型,佔4字節;

(3)     tinyint:整型(極小),佔11字節。

特殊要求說明:

(1)     PKPrimary Key,主鍵;

(2)     FKForeign Key,外鍵;

(3)     AIAuto-Increment,自動遞增;

(4)UNIQUE:惟一,在表中不能重複的值;

(5)     NOT NULL:非空。

 

(1)   用戶表(tb_user

用於保存用戶的基本信息。

4.1 用戶表(tb_user)屬性

列(column

數據類型

特殊要求

說明

id

int

PK, AI

用戶ID

username

varchar(20)

UNIQUE, NOT NULL

用戶名

password

varchar(100)

NOT NULL

密碼密文

email

varchar(50)

UNIQUE, NOT NULL

驗證郵箱

token

varchar(50)

NOT NULL

驗證令牌

token_exptime

int

NOT NULL

令牌失效時間

regtime

int

NOT NULL

註冊時間戳

status

tinylint

NOT NULL

狀態:激活與否

apikey

varchar(100)

NOT NULL

APIKEY,用於受權API操做

about

varchar(200)

 

描述

用戶密碼(password)採用密文存儲,採用不可逆的加密手段(MD5SHA1)進行加密。

驗證郵箱(email)、驗證令牌(token)、令牌失效時間(token_expire)、狀態(status)用於用戶註冊的驗證,該字段所涉及的功能主要用於Web控制平臺。其中驗證郵箱是惟一的,不能重複使用。

APIKEY用於API操做的受權,對API請求操做時必須在HTTP報文的首部(header)中設置相應的APIKEY,雲平臺纔會認定請求合法,返回正確的數據。使用APIKEY進行受權是一種簡單的方法,另外一種更嚴謹的受權方法見詳細的設計過程。

 

(2)   用戶令牌表(tb_user_token

用於保存用戶的令牌,該令牌在用戶每次登錄時從新生成,並確保惟一,必定時間後會自動失效,須要從新登錄。

4.2 用戶令牌表(tb_user_token)屬性

列(column

數據類型

特殊要求

說明

user_id

int

NOT NULL, FK

用戶ID

token

varchar(100)

NOT NULL, UNIQUE

用戶令牌

deadline

int

NOT NULL

截止時間、失效時間

 

用戶IDuser_id)是外鍵,引用用戶表(tb_user)中的用戶IDid)列。

用戶令牌(token)是根據登錄時間以及其它信息生成的惟一的令牌,用於API操做的受權。

截止時間(int)的格式是時間戳,採用int型存儲,爲該令牌的失效時間。

 

(3)   設備表(tb_device

用於保存無線智能家居系統設備信息。

4.3 設備表(tb_device)屬性

列(column

數據類型

特殊要求

說明

id

int

PK, AI

設備ID

name

varchar(50)

NOT NULL

設備名稱

tags

varchar(50)

 

設備標籤

locate

varchar(50)

 

設備位置

about

varchar(200)

 

描述

user_id

int

FK

用戶ID

create_time

int

NOT NULL

建立時間

last_active

int

NOT NULL

最後活動時間

status

tinyint

NOT NULL

狀態

建立時間(create_time)和最後活動時間(last_active)保存的都是時間戳

用戶ID是外鍵,引用用戶表(tb_user)中的用戶IDid)列。

狀態(status)列表徵設備的刪除狀態,1表明正常,0表明刪除。由於存在外鍵約束(來自傳感器表(tb_sensor)的約束),因此不能直接刪除。

 

(4)   傳感器表(tb_sensor

用於保存無線智能家居系統設備所包含的傳感器的信息,一個設備可能包含有多個傳感器。

4.4 傳感器表(tb_sensor)屬性

列(column

數據類型

特殊要求

說明

id

int

PK, AI

傳感器ID

name

varchar(50)

NOT NULL

傳感器名稱

tags

varchar(50)

 

傳感器標籤

type

int

FK

傳感器類型ID

about

varchar(200)

 

描述

device_id

int

FK

設備ID

last_update

int

NOT NULL

更新時間

last_data

varchar(100)

 

最新數據

status

tinyint

NOT NULL

狀態

 

更新時間(last_update)保存的是時間戳,表示最後一次上傳數據的時間(而非傳感器信息的修改時間);最新數據(last_data)保存的是最後一次上傳的數據。

設備ID是外鍵,引用用戶表(tb_device)中的設備IDid)列,表示傳感器屬於該設備。

傳感器類型ID是外鍵,引用傳感器類型表(tb_sensor_type)中的ID,代表該傳感器的類型必須是一個已經存在的類型。

狀態(status)列表徵設備的刪除狀態,1表明正常,0表明刪除。由於存在外鍵約束(來自數據點表(tb_datapoint)的約束),因此不能直接刪除。

 

(5)   傳感器類型表(tb_sensor_type

用於保存傳感器的類型及描述,建立該表的目的在於方便擴展傳感器類型。

4.5 傳感器類型表(tb_sensor_type)屬性

列(column

數據類型

特殊要求

說明

id

int

PK

傳感器類型ID

name

varchar(50)

NOT NULL, UNIQUE

類型名稱

description

varchar(255)

 

對該類型的描述

status

tinyint

NOT NULL

狀態

 

狀態(status)列表徵傳感器類型的停用狀態,1表明正常,0表明停用。由於存在外鍵約束(來自傳感器表(tb_sensor)的約束),因此不能直接刪除。

 

(6)   數據點表(tb_datapoint_lite

用於保存傳感器的數據,每一條記錄都是某個傳感器的某個時間點下的數據。

4.6 數據點表(tb_datapoint_lite)屬性

列(column

數據類型

特殊要求

說明

id

int

PK, AI

數據點ID

sensor_id

int

FK

傳感器ID

timestamp

int

NOT NULL

時間戳

value

varchar(255)

NOT NULL

數據值

 

傳感器IDsensor_id)是外鍵,引用傳感器表(tb_sensor)中的傳感器IDid)列。

數據值(value)採用可變字符串保存數據點的值,能夠存儲任何類型的數據,這樣能夠將不一樣類型的傳感器的數據點集中到一個表中。

 

3.2 PHPRESTful API設計過程

3.2.1 RESTful API請求和響應

全部的APIs都須要接收請求。對於一個RESTful API,須要一個定義好的URL規則。假定須要提供一個接口給網站上的用戶。系統的URL結構可能相似於這樣:api/users,或者api/users/[id],這取決於請求接口的操做類型。

同時,也須要考慮怎麼樣接收數據。近來一段時間,多使用JSON或者XML。從雲平臺的基本設計方案來看,系統已經肯定使用JSON做爲數據交互格式。JSON能夠很好的和Javascript進行交互操做,同時PHP也能夠很簡單的經過json_encodejson_decode兩個函數來對它進行編碼和解碼。

爲了使系統的接口真正強健,設計時應該經過識別請求的內容類型(好比application/json或者application/xml)同時容許接收兩種格式。可是,限制只接收一種類型的數據也是能夠很好的被接受。

一個RESTful的響應主要包括兩個主要部分:響應體和狀態碼。就像請求,大部分的REST響應一般是JSON或者XML格式,和請求相似,API使用者能夠經過設置HTTP規範首部的"Accept"選項來規定本身作但願接收到的響應數據類型。若是一個API使用者但願接收到XML響應,他們僅僅須要發送一個包含相似於「Accept: application/xml」這樣的頭信息請求。

和請求有關的錯誤和其餘重要的狀態信息經過使用HTTP的狀態碼(status-code)和緣由字段(reason-phrase)來輸出。好比:假如一個API使用者提交數據(POST)到/api/users,須要返回一個成功建立的消息,此時能夠簡單的發送一個201狀態碼(201=Created)。若是失敗了,服務器失敗就發送一個500500=內部服務器錯誤),若是請求中斷就發送一個400400=錯誤請求)。

 

在本課題的雲平臺設計方案中,默認使用而且暫時只支持JSON格式的響應數據,在使用API的時候仍然要將在HTTP請求報文的首部中設置「Accept: application/json」選項以確保之後雲平臺功能擴展時返回錯誤類型的響應數據。

雲平臺接受數據的形式根據HTTP請求方法不一樣略有差別。對於GETDELETE請求,附加參數附在URI後面,即經過GET方式傳遞的參數;對於POSTPUT請求,數據經過HTTP表單的形式傳遞過來,即「Content-Type: application/x-www-form-urlencoded」。

 

3.2.2 RESTful API URL及方法設置

如今初步定義RESTful API的功能,接口的功能和說明見下表4.6

4.6 API請求方法與功能定義

請求方法

URI/URL

功能

用戶接口

POST

/api/login

用戶登陸,用戶認證

GET

/api/user/<user_id>

獲取用戶的詳細信息

PUT

/api/user/<user_id>

更改用戶的詳細信息

設備接口

GET

/api/devices

獲取全部設備列表

POST

/api/devices

添加一個新的設備

GET

/api/device/<device_id>

獲取設備的詳細信息

PUT

/api/device/<device_id>

更改設備的詳細信息

DELETE

/api/device/<device_id>

刪除設備

傳感器接口

GET

/api/sensors/<device_id>

獲取指定設備下的全部傳感器

POST

/api/sensors/<device_id>

在指定設備下添加一個新的傳感器

GET

/api/sensor/<sensor_id>

獲取傳感器的詳細信息

PUT

/api/sensor/<sensor_id>

更改傳感器的詳細信息

DELETE

/api/sensor/<sensor_id>

刪除傳感器

數據點接口

GET

/api/datapoints/<sensor_id>

獲取指定傳感器的數據點(多個)

POST

/api/ datapoints/<sensor_id>

爲指定傳感器建立數據點(多個)

GET

/api/datapoint/<sensor_id>

獲取指定傳感器的最新數據

POST

/api/datapoint/<sensor_id>

爲指定傳感器建立單個數據點

DELETE

/api/datapoint/<dp_id>

刪除數據點(保留,暫不用)

 

3.2.3 肯定PHP下開發RESTful API的詳細方案

要使用PHP完成RESTful API的開發,須要完成如下幾個方面的功能:

(1)處理請求信息:肯定請求方法和請求參數;

(2)實現URL路由:根據請求的方法和URL,執行實現這個功能的函數;

(3)處理響應信息:控制HTTP響應報文的狀態碼、首部等信息,控制數據輸出爲指定的格式。

雖然只列出了三項,但其實這部份內容實現起來是很複雜且費時費力的。經過調研和分析,最終的出了比較快速高效的設計方案:

(1)使用基於MVC架構的PHP框架CodeIgniter來實現最基本的路由功能;

(2)使用框架內的第三方庫函數rest-server來實現更完整的RESTful API

(3)使用編程實現系統內部的處理邏輯,處理輸入,產生輸出。

 

3.3 開發環境配置

3.3.1 LinuxNginxPHP的配置

爲了在Nginx服務器中使用PHP,須要安裝PHP-FPMPHP Fastcgi Process Manager)。假定全部軟件都已經安裝完畢,接下來就須要開始配置NginxPHP的配置參數了。

對於PHP的配置,找到PHP的配置文件php.ini,開始配置:

(1)     找到時區設置選項,設置「date.timezone = PRC」

(2)     開啓MySql擴展庫支持,取消前面的分號註釋,即設置「extension=php_pdo_mysql.dll」

(3)     根據具體須要,開啓其它擴展庫。

對於PHP-FPM的配置,找到PHP-FPM的配置文件(根據安裝方式不一樣位置、名稱均可能不一樣)/etc/php-fpm.d/www.conf(默認安裝時),設置PHP-FPM監聽Unix Socket管道通訊(to listen on a unix socket),並設置socket文件的地址。例如,「listen = /tmp/php-fpm.sock」。而後重啓PHP-FPM便可。

對於Nginx的配置,能夠新建一個配置文件cloud-platform.conf,用於單獨保存雲平臺的配置,而後在Nginx的主配置中引入該配置文件(include)。

配置文件cloud-platform.conf示例及說明(使用#做爲行註釋):

server {
        listen       8000;#要使用的端口號
        server_name  cloud-platform;#若是沒有域名,則隨意設置,不然設置爲域名

        location / { 
            root   /tmp/cloud-platform; 
            index  index.php;
        }
#針對PHP的設置
        location ~ \.php($|/) {
#設置服務器根目錄,用於保存提供服務的頁面
            root           /tmp/cloud-platform;
#使用Unix管道與php-fpm進行進程通訊,使用以前在PHP-FPM中設置socket文件
            fastcgi_pass   unix:/tmp/php-fpm.sock;
            fastcgi_index  index.php;
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
#針對CodeIgniter框架的設置,能夠使得URL略去」index.php」
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /index.php/$1 last;
            break;
        }
}

配置完成以後,運行Nginx的檢測工具檢查配置文件是否有效合法,(假設如今工做目錄在Nginx的根目錄中)運行:「./sbin/nginx -t」。檢測經過以後,重啓Nginx,而後測試虛擬主機是否工做正常,PHP文件是否正確解析。

 

更詳細的配置選項,請查閱Nginx文檔[20]以及PHP手冊[22]

 

3.3.2 MySql開發配置

對於工程運用而言,雲平臺系統訪問數據庫都不會直接使用最高權限的root帳戶,所以咱們須要新建一個爲雲平臺專用的用戶,併爲它設置對應的權限。

(1)     在命令行下使用root賬戶登陸mysql,輸入:」mysql –u root –p」,再輸入root帳戶密碼便可登陸

(2)     建立新的用戶(以用戶名linpcloud,密碼1234爲例),輸入:「create user linpcloud identified by '1234';」

(3)     建立工程用的數據庫(以linpcloud爲例),輸入:「create database linpcloud;」

(4)     爲用戶linpcloud賦予數據庫linpcloud的權限,輸入:」grant all on linpcloud.* for 'linpcloud'@'%';」

(5)     使用如下指令查看用戶的權限,輸入:「show grants for linpcloud;」

 

在上面的配置中,咱們爲用戶linpcloud分配了數據庫linpcloud的全部權限。然而在工程開發完成以後,數據庫結構再也不變動時,整個工程對數據庫只有基本的增刪查改操做。從嚴格來說,咱們應該進一步限制這個帳戶的權限。但咱們處於開發階段,只要將該數據庫全部權限分配給它便可。

 

更具體的設置方法及說明,請參閱MySql參考手冊文檔[21]

 

3.3.3 PHP框架CodeIgniter的配置

CodeIgniter 是一套給 PHP 網站開發者使用的應用程序開發框架和工具包。它提供一套豐富的標準庫以及簡單的接口和邏輯結構,其目的是使開發人員更快速地進行項目開發。使用 CodeIgniter 能夠減小代碼的編寫量,並將你的精力投入到項目的創造性開發上。

CodeIgniter 生成的 URL 很是乾淨並且是對搜索引擎友好化的。不一樣於標準的「字符串查詢」方法,CodeIgniter使用了「基於段」的方法:」 example.com/news/article/345」

注意:「index.php 文件是被默認包含在 URL 中的,可是能夠經過更改 .htaccess 文件來改變這個設置(經過Web服務器的配置來更改)。

3.2說明了CodeIgniter中數據流如何貫穿整個系統:

CodeIgniter 應用程序流程圖

3.2 CodeIgniter數據流分析

(1)     index.php做爲前端控制器,初始化運行CodeIgniter所須要的基本資源。

(2)     Router檢查HTTP請求,以肯定誰來處理請求。

(3)     若是緩存(Cache)文件存在,它將繞過一般的系統執行順序,被直接發送給瀏覽器。

(4)     安全(Security)。應用程序控制器(Application Controller)裝載以前,HTTP 請求和任何用戶提交的數據將被過濾。

(5)     控制器(Controller)裝載模型、核心庫、輔助函數,以及任何處理特定請求所需的其它資源。

(6)     最終視圖(View)渲染髮送到Web瀏覽器中的內容。若是開啓緩存(Caching),視圖首先被緩存,因此將可用於之後的請求。

 

(1)   CodeIgniter的文件結構

解壓後的文件結構如圖3.3所示:

3.3 CodeIgniter的文件結構

其中,」index.php」CodeIgniter框架的入口文件。全部對系統的訪問,雖然HTTP請求URL不一樣,其實都指向」index.php」」index.php」文件中負責根據URL來肯定須要調用哪一個控制器、哪一個方法,即實現URL的路由功能(還包括系統的初始化)。

「system」文件夾是CodeIgniter的核心文件,咱們通常都不該該更改其中的文件內容(除非你打算修改框架)。「application」文件夾用於存放咱們的應用程序(對於本課題,保存雲平臺系統主體)。

 

(2)   CodeIgniter的文件佈局和系統配置

解壓框架文件,將」application」文件夾重命名爲」cloud-platform」,用於存放咱們的應用(雲平臺系統的主體),而後將該文件夾放到本身的開發目錄中去。

」index.php」文件複製到Nginx設置的虛擬主機根目錄下,並修改該文件。

3.4 CodeIgniter文件佈局的設置

將變量」$system_path」的值設定爲框架的「system」文件夾的位置,將變量」$application_folder」的值設定爲存放雲平臺的主體的文件夾「cloud-platform」的位置。

 

而後開始配置CodeIgniter中應用(application)的設置。

首先,將「rest-server」庫的文件複製到「cloud-platform」文件夾內指定的子文件夾中。

其次,配置「cloud-platform」「config」子目錄下的數據庫設置文件「database.php」配置文件,將之設定爲系統使用的數據庫鏈接。

最後,配置「rest-server」庫的變量。主要須要將返回數據的類型設定爲JSON格式(參考雲平臺基本設計方案),禁用不須要的HTTP請求方法(HEADTRACEOPTIONS)。

更具體的配置,參考CodeIgniter的用戶指引文檔[23]

 


 

4. 智能家居雲平臺功能實現

接下來介紹智能家居雲平臺具體功能的開發過程,以及逐個的RESTful API的實現過程。

4.1 用戶類

雲平臺核心功能的API請求都須要進行用戶權限的確認,才能容許進一步的操做。而HTTP請求屬於無鏈接、無狀態的,根據RESTful API的要求,咱們須要在HTTP報文中添加可以表示API用戶狀態的信息。

在雲平臺的數據庫設計已經考慮到了這方面的問題,而且在用戶表(tb_sensor)中添加了APIKEY字段(apikey),用來在HTTP報文中標識用戶的身份和權限。

顯然該字段在數據表中是惟一的(UNIQUE,數據庫設計時已經實現該限制),這樣才能標識某個特定的用戶,而不至於產生衝突。在用戶表(tb_sensor)中,還有兩個字段也是有惟一性約束的,即用戶IDid)和用戶名(username),顯然使用這兩個字段也能夠起到上述標識用戶的做用。那麼使用APIKEY的意義何在?

很顯然,用戶ID和用戶名都應該是靜態的,一經建立就不可以再更改了。那麼使用APIKEY的用意也就很明顯了:能夠從新生成新的APIKEY。考慮到安全問題,若是使用靜態的標識用來標識用戶,很容易會遇到經過僞造HTTP請求報文從而實現盜用他人用戶的情況。使用APIKEY的狀況下,在必定的程度內能避免上述安全問題的發生。

更加完善的方案則是使用令牌來受權API訪問權限:每次登陸都生成一個惟一的令牌(token),必定時期以後失效。經過使用動態的標識手段,來提升安全性。

在雲平臺系統的設計中,咱們保留了兩種設計方案,但爲了開發的方便,現階段主要使用APIKEY進行標識,這樣使用半靜態的標識能夠減小後期開發的麻煩。

HTTP報文首部中添加APIKEY字段,用來確認用戶狀態,進行API受權,如:」Apikey: 1a39ad4c87ba09ef861ead97f010df7b 「

 

(1)   用戶登陸

請求方法:POST

請求URI/api/login

響應內容:基本的用戶信息

設計方法:

使用基本的Web表單的形式將用戶名和密碼提交到雲平臺,由雲平臺查詢數據庫進行用戶認證;認證成功,返回基本的用戶信息(用戶ID、用戶名、APIKEY);認證失敗返回失敗提示信息。

 

(2)   用戶信息獲取

請求方法:GET

請求URI/api/user

響應內容:完整的用戶信息

設計方法:

經過獲取HTTP請求報文首部Apikey字段的值,確認用戶身份,獲取其信息,而後做爲響應將之返回。

 

(3)   更改用戶信息

請求方法:PUT

請求URI/api/user

響應內容:成功或失敗的提示性信息

設計方法:

經過獲取HTTP請求報文首部Apikey字段的值,確認用戶身份及權限。若是沒有權限,則直接返回錯誤信息。使用基本的Web表單的形式將用戶信息提交到雲平臺,由雲平臺更新數據庫內容,返回操做成功的提示信息。

 

(4)   從新生成APIKEY

請求方法:PUT

請求URI/api/apikeyr

響應內容:新的APIKEY

設計方法:

經過特定的函數生成新的APIKEY,並確保其惟一性,而後將之返回。生成新的APIKEY以後,原先的APIKEY將會失效。

生成新的APIKEY的算法:

$apikey = md5($user_id . time());

使用用戶ID和當前時間戳組合成字符串再求MD5,這首先保證了求MD5的字符串每次都是不一樣的,於是APIKEY相同的機率極小。若是出現了相同,數據庫設計時的惟一性約束會發生做用,致使APIKEY更新失敗,返回錯誤信息。

 

由於接下來的API都須要經過APIKEY進行API受權,纔能有操做權限。所以咱們在設計時,將經過Apikey獲取用戶信息的一系列操做統一爲一個共有函數,以簡化以後的處理流程。

function _check_apikey()
{
    $apikey = $this->input->get_request_header('Apikey');//從HTTP請求報文首部獲取APIKEY
    if ($apikey === FALSE)//簡單的判斷APIKEY是否設置
    {
        $this->response(array (
                'info' => 'http header `apikey` lost, please login agian'
        ), 400);
    }
$result = $this->user_model->get_info_by_apikey($apikey);//調用了用戶模型下的函數
//只是使用了MVC架構,將數據庫操做集中在了模型(Model)裏面了
//至關於執行SQL語句:」SELECT * FROM tb_user WHERE apikey=’$apikey’」
    if ($result === FALSE)//數據庫中沒有找到APIKEY的狀況
    {
        $this->response(array (
                'info' => '`apikey` not match, please login agian'
        ), 400);
    }
    return $result['id'];//返回用戶ID
}

 

這部分功能處理流程都很簡單,因此不過多說明。

 

4.2 設備類

設備和用戶屬於多對一的關係,即一個用戶能夠有多個設備,每一個設備必然歸屬於某一個用戶。所以在數據庫設計中,設備表中使用了外鍵約束,用戶IDuser_id)引用用戶表(tb_user)中的用戶IDid)欄。

對設備的操做都須要檢查用戶的權限:首先檢查HTTP請求報文中的APIKEY,而後再檢查操做的設備中的用戶ID是否與之對應。不對應,就認爲該設備不屬於該用戶,用戶沒法請求API進行操做。檢查設備歸屬的函數也是經常使用的共有函數,這裏給出其代碼和註釋:

function _check_device($device_id)
{
$user_id = $this->_check_apikey();
//首先調用已有的檢查APIKEY的函數,並獲取用戶的ID
    
    $result = $this->device_model->get($device_id);//調用模型的方法獲取設備信息
    if ($result === FALSE)//設備不存在的狀況
    {
        $this->response(array (
                'info' => "device `$device_id` not found"
        ), 400);
    }
    if ($result['user_id'] != $user_id)//判斷設備歸屬,若是不一樣返回錯誤信息
    {
        $this->response(array (
                'info' => "device `$device_id` out of your permission"
        ), 400);
    }
    return TRUE;//沒有出錯,返回TRUE
}

 

(1)   獲取設備列表

請求方法:GET

請求URI/api/devices

響應內容:返回JSON格式的對象數組

設計方法:

首先調用公有函數_check_apikey()檢查用戶狀態並獲取用戶ID,使用用戶ID在設備表(tb_device)中查詢全部屬於該用戶ID的設備,進行JSON編碼後返回數據給用戶。

 

(2)   添加新的設備

請求方法:POST

請求URI/api/devices

響應內容:成功或失敗的提示性信息

設計方法:

首先調用公有函數_check_apikey()檢查用戶狀態並獲取用戶ID。使用基本的Web表單的形式將設備信息提交到雲平臺,由雲平臺獲取表單數據,在結合已獲取的用戶ID,進行數據庫的插入操做,返回操做成功的提示信息。

 

(3)   獲取設備信息

請求方法:GET

請求URI/api/device/<device_id>

響應內容:設備詳細信息

設計方法:

首先調用公有函數_check_device()檢查設備的歸屬,而後直接使用URI中的參數在數據庫中查詢該設備的信息。

 

(4)   更改設備信息

請求方法:PUT

請求URI/api/device/<device_id>

響應內容:成功或失敗的提示信息

設計方法:

首先調用公有函數_check_device()檢查設備的歸屬(同時也會確認設備的存在性)。使用基本的Web表單的形式將新的設備信息提交到雲平臺,由雲平臺獲取表單數據,進行數據庫的更新操做,返回操做成功的提示信息。

 

(5)   刪除設備(停用設備)

請求方法:DELETE

請求URI/api/device/<device_id>

響應內容:成功或失敗的提示信息

設計方法:

首先調用公有函數_check_device()檢查設備的歸屬,再使用URI中的參數進行數據庫的更新操做,將設備表中符合要求的一條記錄的狀態(status)列設爲1,返回操做成功的提示信息。因爲存在外鍵約束,不能直接刪除設備。同時真正的系統中,對數據的刪除都應當心操做,由於一旦刪除沒法恢復。所以使用狀態(status)字段來表示設備的刪除狀態。所以,前面的API獲取設備列表和獲取設備信息功能中,查詢數據庫都要添加對狀態(status)字段的判斷。在用戶看來已被刪除(實際上在表中沒有刪除)的設備不該出如今列表中,也不能被獲取詳細信息,不能更改設備信息。

 

4.3 傳感器類

傳感器和設備屬於多對一的關係,即一個設備能夠包含多個傳感器,每一個傳感器必然屬於某一個設備。所以在數據庫設計中,傳感器表中也使用了外鍵約束,設備IDdevice_id)引用設備表(tb_device)中的設備IDid)欄。

建立傳感器時應該指定該傳感器所屬於的設備(建立設備時,自動設置所屬用戶爲API使用者),所以API雖大部分相似與設備類,但依舊有些許不一樣。

對於傳感器的操做,權限和歸屬的檢查同時也要深刻到傳感器的層次,同時也要檢查傳感器所屬設備的歸屬。

function _check_sensor($sensor_id, $device_id = FALSE)
{
    $result = $this->sensor_model->get($sensor_id);//獲取傳感器信息
    if ($result === FALSE)//傳感器不存在的狀況
    {
        $this->response(array (
                'info' => "sensor `$sensor_id` not found!"
        ), 400);
    }
    //參數設備ID不爲空時,判斷傳感器是否屬於設備
    if ($device_id !== FALSE && $device_id != $result['device_id'])
    {
        $this->response(array (
                'info' => "sensor `$sensor_id` do not belong to device `$device_id`!"
        ), 400);
    }
    //檢查傳感器所屬設備的權限,其中包含了對APIKEY的檢查
    $this->_check_device($result['device_id']);
    //返回傳感器的信息
    return $result;
}

 

(1)   獲取傳感器列表

請求方法:GET

請求URI/api/sensors/<device_id>

響應內容:返回JSON格式的對象數組

設計方法:

首先調用公有函數_check_device()檢查設備狀態,使用該設備ID在傳感器表(tb_sensor)中查詢全部屬於該設備ID的傳感器,進行JSON編碼後返回數據。

 

(2)   添加傳感器(向特定設備添加)

請求方法:POST

請求URI/api/sensors/<device_id>

響應內容:返回成功或失敗的信息

設計方法:

首先調用公有函數_check_device()檢查設備狀態。使用基本的Web表單的形式將傳感器信息提交到雲平臺,由雲平臺獲取表單數據,在結合已有的URI參數設備ID,進行數據庫的插入操做,返回操做成功的提示信息。

 

(3)   獲取傳感器信息

請求方法:GET

請求URI/api/sensor/<sensor_id>

響應內容:返回傳感器詳細信息

設計方法:

首先調用公有函數_check_sensor()檢查傳感器狀態,再直接查詢該傳感器的信息,並返回數據。

 

(4)   更改傳感器信息

請求方法:PUT

請求URI/api/sensor/<sensor_id>

響應內容:返回成功或失敗的信息

設計方法:

首先調用公有函數_check_sensor()檢查傳感器狀態。使用基本的Web表單的形式將傳感器信息提交到雲平臺,由雲平臺獲取表單數據,進行數據庫的更新操做,返回操做成功的提示信息。

 

(5)   刪除傳感器

請求方法:DELETE

請求URI/api/sensor/<sensor_id>

響應內容:返回成功或失敗的信息

設計方法:

首先調用公有函數_check_sensor()檢查傳感器的狀態,其它處理相似於設備的刪除操做,不直接刪除記錄,只是將記錄標記爲已刪除。

 

4.4 數據點類

數據點和傳感器屬於多對一的關係,即一個傳感器能夠有多個數據點,每一個數據必然歸屬於某一個傳感器。所以在數據庫設計中,數據點表中也使用了外鍵約束,傳感器IDsensor_id)引用傳感器表(tb_sensor)中的傳感器IDid)欄。

數據點的字段有四項:編號(id)、傳感器IDsensor_id)、時間戳(timestamp)、值(value)。

對於數據點的數據庫設計曾經有多種方案,最終暫時採起了最簡單、最直接的一種設計方案:只使用一個表保存不一樣類型數據傳感器的數據,而且使用可變長度字符串(varchar)直接保存數值。這樣設計的優勢在於,數據點的插入和查詢都比較簡單,而且數值的類型幾乎沒有限制,傳感器的值甚至能夠使用一個字符串(一句話)。但缺點也很明顯:首先,傳感器類型的區分就沒有太多意義了;存儲空間的使用效率可能會比較低。

MySql中,對於可變字符串(varchar)而言,真實佔用的空間爲字符串的實際長度n+1 Byte。對於開關量,以01表示的話,則每一個值須要佔用2 Bytes;對於整型數值,位數n越長,佔用Byte數就越多,爲n+1 Bytes;對於浮點數來講,以兩位整數、兩位小數爲例,須要佔6 Bytes

總的來講,只有在數值爲位數較少的整型時,才勉強佔用空間略小;其它狀況下,都多佔了不少的存儲空間。

 

另外一種設計方案則是爲每種數據類型的傳感器設計不一樣的表存儲數據。如開關量,將value列設爲布爾型;整型數值,將value列設爲int型;浮點型數值,將value列設爲float型。這樣的確充分利用了存儲空間,但在某些功能的設計時遇到了很大的麻煩,尤爲是批量上傳數據、批量獲取數據時。故而,這種數據庫設計方案被置爲保留方案,暫時使用最方便的方案。

 

(1)   建立數據點

請求方法:POST

請求URI/api/datapoint/<sensor_id>

響應內容:返回成功或失敗的信息

設計方法:

首先調用公有函數_check_sensor()檢查傳感器狀態和權限。使用基本的Web表單的形式將數據點信息提交到雲平臺,由雲平臺獲取表單數據,在結合已有的URI參數傳感器ID,進行數據庫的插入操做,返回操做成功的提示信息。

該功能的數據庫操做涉及3個表:數據點表(tb_datapoint_lite)、傳感器表(tb_sensor)、設備表(tb_device)。在建立數據點的時候,時間戳使用的是服務器自動生成的時間戳,不須要再單獨上傳。在爲傳感器建立數據點的時候,咱們認爲傳感器數據獲得更新,因而同時更新傳感器表(tb_sensor)中的最禁更新時間(last_update)和最近數據(last_data)爲數據點的時間戳和數據值。同時,咱們認爲設備是活動的,因而將設備表中的活動時間(last_acitve)設置爲當前時間戳。至此,建立數據點及其連帶的操做纔算完成。

 

(2)   獲取傳感器最新數據點

請求方法:GET

請求URI/api/datapoint/<sensor_id>

響應內容:返回時間戳和數據

設計方法:

首先調用公有函數_check_sensor()檢查傳感器狀態和權限,而後直接從傳感器表中讀出最近(最新)的數據和時間戳,並返回。

 

(3)   批量上傳數據點(網關用)

請求方法:POST

請求URI/api/datapoints/<device_id>

響應內容:成功或失敗的信息

設計方法:

該功能主要面向智能家居網關開發,用於批量上傳某個設備內全部傳感器的數據。這個操做只會修改URI中指定的設備的最後活動時間(不是根據傳感器再來判斷更新哪一個設備)。由於數據處理比較複雜,因此對網關上傳數據時有必定的要求:上傳時在URI中指定傳感器所屬設備,上傳數據的全部傳感器都應屬於該設備,不然不會爲它建立數據點;上傳數據時依然使用表單的形式,設置json值爲要提交的數據的JSON字符串(即將數據組織成JSON數據再經過表單傳遞過來)。

處理流程爲:

調用公有函數_check_device()檢查用戶權限。雲平臺接受經過表單傳遞過來的JSON數組,對之進行解析成PHP索引數組。遍歷數組每個元素,而後組織出兩個數組:一個用於批量更新傳感器表的數據,一個用於批量插入數據點。執行SQL語句,返回結果。

程序代碼以下:

public function datapoints_post($device_id = FALSE)
{
    if ($this->post('json') == FALSE)//獲取表單中的JSON字符串
    {
        $this->response(array (
                'info' => 'Field `json` required'
        ), 400);
    }
    if($device_id != FALSE)//更新設備的最後活動時間(last_active)
    {
        $time = time();
        $sql = "UPDATE tb_device SET last_active='$time' WHERE id='$device_id'";
        $this->db->query($sql);
    }
    //組織插入數據和更新數據
    $json_array = json_decode($this->post('json'), 'array');
    $insert_data = array();
    $update_data = array();
    foreach($json_array as $row)
    {//we should check every sensor_id in the further, validation and unique
        $insert_data[] = array(
                'sensor_id' => $row['sensor_id'],
                'timestamp' => time(),
                'value' => $row['value']
        );
        $update_data[] = array(
                'id' => $row['sensor_id'],
                'last_data' => $row['value'],
                'last_update' => time()
        );
    }
    
    $this->db->update_batch('tb_sensor', $update_data, 'id');//批量更新
    $this->db->insert_batch('tb_datapoint_lite', $insert_data);//批量插入
    
    $this->response(array (
            'info' => 'Datapoint created success'
    ), 200);
}

 

(4)   批量獲取數據

請求方法:GET

請求URI/api/datapoints/<type>/<id>

響應內容:JSON格式的對象數組

設計方法:

<type>=device時,<id>表明的是設備ID,該接口用於獲取某個設備下全部傳感器的最新數據;當<type>=sensor時,<id>表明的是傳感器ID,該接口用於獲取某個傳感器的歷史數據。

代碼以下:

public function datapoints_get($type, $id) {
    if(strtoupper($type) == 'DEVICE') { //獲取某個設備下全部傳感器的最新數據
        $this->_check_device($id);//檢查設備的狀態和權限
        $sql = "SELECT id, last_update, last_data FROM tb_sensor WHERE device_id = $id AND `status` = 1";
        $result = $this->db->query($sql);
        $data = $result->result_array();
        $this->response($data, 200);
    }
    else if(strtoupper($type) == 'SENSOR') { //獲取某個傳感器的歷史數據
        $this->_check_sensor($id); //檢查傳感器的狀態和權限
        $end = time();//結束時間,默認爲當前時間
        $start = $end - 60*60;//開始時間,默認爲當前時間的一小時前
        $interval = 60;//獲取數據的時間間隔

        if($this->get('start') != FALSE)//檢查參數(GET參數)
            $start = $this->get('start');
        if($this->get('end') != FALSE)
            $start = $this->get('end');
        if($this->get('interval') != FALSE)
            $start = $this->get('interval');
        $sql = "SELECT * FROM tb_datapoint_lite WHERE `sensor_id`=$id AND `timestamp` BETWEEN $start AND $end AND (`timestamp`-$start)%$interval<=30 ORDER BY `timestamp` ASC";//查詢語句
        $result = $this->db->query($sql);
        $data = $result->result_array();
        $this->response($data, 200);
    }
    else {
        $this->response(array (
                'info' => 'Lost parameter `$type`'
        ), 400);
    }
}

經過必定時間間隔獲取數據的SQL語句分析:

SELECT * FROM tb_datapoint_lite WHERE `sensor_id`=$id AND `timestamp` BETWEEN $start AND $end AND (`timestamp`-$start)%$interval<=30 ORDER BY `timestamp` ASC

 

核心在於,將數據點的時間戳減去開始時間,而後與時間間隔取餘,而後與系統要求的上傳數據的最小時間間隔(30s)比較。若是取餘以後,小於30s,則取出該記錄。加入採用默認的時間間隔60s,且數據上傳間隔正好是30s,那麼160s內,顯然取餘以後,只會有一個數據符合要求,達到60s取一個點的要求。對於時間間隔,若是小於30s,顯然全部的點都會被取出來。

 

4.5 輔助接口

該類接口主要提供一些輔助功能,包括提供雲平臺基本的測試接口。

現有的輔助接口及設計說明以下:

 

(1)   獲取MD5

請求方法:GET

請求URI/helper/md5/<string>

響應內容:JSON格式的對象,包括所求字符串的MD5

設計方法:

直接使用PHPMD5函數對參數進行求取MD5的運算,而後返回數據。

 

(2)   獲取時間戳

請求方法:GET

請求URI/helper/timestamp/<timestamp>

響應內容:JSON格式的對象數組,包括當前時間戳,和格式化以後的時間字符串

設計方法:

參數爲可選參數,若是不指定參數timstamp的值,則默認使用PHP函數time()獲取當前時間戳,再使用date()函數將之格式化,將兩個數據返回。

 


 

5 系統測試及結果分析

5.1 雲平臺系統測試要求

本課題中雲平臺的設計主要負責數據的存儲和處理,沒有涉及用戶界面的實現,咱們將結合設計方案,經過如下方面對雲平臺功能進行測試和評估:

(1)雲平臺響應報文結構和內容:訪問雲平臺API查看HTTP響應報文結構和內容是否符合設計時的要求(以JSON格式返回數據);

(2)雲平臺功能實現情況:訪問雲平臺指定功能的API,經過查看HTTP響應報文和對比數據庫記錄的變化評估系統功能實現結果;

(3)雲平臺權限控制:經過跨越權限的API操做,評估雲平臺的權限控制是否正常,錯誤信息輸出是否正常;

(4)雲平臺錯誤控制:經過大量的測試,檢查是否有遺漏的未捕捉的錯誤。

 

5.2 雲平臺系統測試方法

爲了完成雲平臺API的測試,須要一個可以快速高效組織HTTP請求報文,併發送HTTP請求的工具。經過調研,咱們選擇了使用GoogleChrome瀏覽器結合其擴展應用Postman – REST Client來進行測試,經過Chrome瀏覽器開發者工具獲取更詳細的HTTP請求報文(Request Message)和響應報文(Response Message)的具體內容。

 

下面是以雲平臺中用戶類的登陸API進行測試的實例。在示例中,咱們展現了使用Postman進行RESTful API測試的基本方法,以及使用Chrome瀏覽器開發者工具獲取完整的請求報文和響應報文的方法。

 

使用Wireshark能夠經過網卡從硬件底層捕捉HTTP請求報文,這些報文通常來講都會與經過瀏覽器開發者工具獲取的報文相同。雖然使用Wireshark能夠進行捕捉更加真實完整的報文(搭載HTTP報文的TCP報文、IP報文,甚至於以太網數據幀),但其使用可能就沒有使用瀏覽器工具那麼簡潔方便。但在非瀏覽器中(如Java程序或PHP-CLI模式的測試)測試雲平臺API時,就須要用到這個工具了,因此在這裏也進行了簡單的介紹。

5.1 Postman-REST Client界面

5.2 Google Chrome瀏覽器開發者工具

5.3 Wireshark抓包界面

5.3 雲平臺請求和響應報文分析

(1)     典型的無受權的API請求

適用於訪問輔助類API和用戶類的登陸API。這類API在使用時,不需設置自定義的首部「Apikey」

例如,用戶登陸的請求實例

請求報文:

POST /api/login HTTP/1.1
Host: 218.244.138.146:8000
Accept: application/json
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded

username=linpcloud&password=1234

(2)     帶有APIKEYAPI請求

適用於訪問全部須要進行權限斷定的API

例如,獲取用戶信息的請求實例

請求報文:

GET /api/user HTTP/1.1
Host: 218.244.138.146:8000
Accept: application/json
Apikey: 1a39ad4c87ba09ef861ead97f010df7b
Cache-Control: no-cache

(3)     帶有表單數據的API請求

適用於使用HTTP POSTPUT方法訪問須要提交數據的API。這類API在使用時,需設置的首部」 Content-Type: application/x-www-form-urlencoded」,並在請求正文中加入表單數據(鍵值對)。

例如,修改設備信息的請求實例

請求報文:

PUT /api/device/10003 HTTP/1.1
Host: 192.168.207.1
Accept: application/json
Apikey: 1a39ad4c87ba09ef861ead97f010df7b
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded

name=device+from+Postman&tags=any+tags%3F&locate=Wuhan&about=This+is+a+device+created+by+Postman&user_id=10000

(4)     正常的API響應

200爲狀態碼返回的HTTP響應,這標誌着該API工做正常,返回了正確的數據。

例如,登陸成功的響應實例。

響應報文:

HTTP/1.1 200 OK
Server: nginx/1.4.7
Date: Thu, 29 May 2014 15:38:02 GMT
Content-Type: application/json
Content-Length: 104
Connection: keep-alive
X-Powered-By: PHP/5.3.3

{"info":"Login Success","id":"10000","username":"linpcloud","apikey":"1a39ad4c87ba09ef861ead97f010df7b"}

(5)     已捕捉到錯誤的響應

適用於雲平臺系統設計時已經考慮到的可能出現的錯誤,而且進行了處理的狀況。在該狀況下,以400做爲狀態碼返回響應信息,並在響應主體中包含了錯誤信息。

例如,登陸時密碼錯誤的狀況的響應。

響應報文:

HTTP/1.1 400 Bad Request
Date: Thu, 29 May 2014 16:42:19 GMT
Server: Apache/2.4.9 (Win64) PHP/5.5.10
X-Powered-By: PHP/5.5.10
Content-Length: 53
Connection: close
Content-Type: application/json

{"info":"Login Fail: password or username incorrect"}

(6)     其它的錯誤響應

多是PHP程序致命錯誤致使的錯誤信息輸出,抑或CodeIgniter框架內部路由功能等環境出錯。因爲錯誤出如今雲平臺系統以外,雲平臺沒法控制其輸出。故而對於響應狀態碼不是200400的響應,咱們認定爲系統外的錯誤,雲平臺系統沒法給出具體的信息。

例如,rest-server庫沒法找到方法時的響應。

響應報文:

HTTP/1.1 404 Not Found
Date: Thu, 29 May 2014 16:47:49 GMT
Server: Apache/2.4.9 (Win64) PHP/5.5.10
X-Powered-By: PHP/5.5.10
Content-Length: 42
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json

{"status":false,"error":"Unknown method."}

5.4 雲平臺測試結果

雲平臺全部基本功能接口均已測試經過,但可能也存在遺漏的BUG,這須要在更多、更完善的測試以後纔可以發現並修正。

由於論文篇幅有限,不可能將全部的測試實例及測試結果都羅列出來,故只給出幾個重要模塊的測試結果。

 

(1)     登陸成功的響應結果

響應正文(格式化以後的JSON):

{
    "info": "Login Success",
    "id": "10000",
    "username": "linpcloud",
    "apikey": "1a39ad4c87ba09ef861ead97f010df7b"
}

 

(2)     獲取設備列表成功的響應結果

響應正文(格式化以後的JSON):對象數組。

結果相似的還有獲取傳感器列表成功時的響應。

[
    {
        "id": "10008",
        "name": "RGB Light",
        "tags": "none",
        "about": "帶顏色的LED燈,RGB顏色可調,亮度可調,附帶開關",
        "locate": "Wuhan",
        "user_id": "10000",
        "create_time": "1399861186",
        "last_active": "1399861186"
    },
    {
        "id": "10009",
        "name": "Normal Light",
        "tags": "none",
        "about": "Normal light with a switch only.",
        "locate": "武漢",
        "user_id": "10000",
        "create_time": "1399861676",
        "last_active": "1399861676",
        "status": "1"
    }

]

 

(3)     獲取單個設備信息的響應

響應正文(格式化以後的JSON):

{
    "id": "10008",
    "name": "RGB Light",
    "tags": "none",
    "about": "帶顏色的LED燈,RGB顏色可調,亮度可調,附帶開關",
    "locate": "Wuhan",
    "user_id": "10000",
    "create_time": "1399861186",
    "last_active": "1399861186",
    "status": "1"
}

(4)     建立設備成功的響應

響應正文:

{
    "info": "Create Device `10021` success",
    "device_id": 10021
}

(5)     刪除設備成功的響應

響應正文:

{
    "info": "Delete device `10021` success"
}

(6)     獲取單個設備全部傳感器數據的響應

響應正文:

[
    {
        "id": "100005",
        "last_update": "1400502382",
        "last_data": "ffffff"
    },
    {
        "id": "100006",
        "last_update": "1400502382",
        "last_data": "30%"
    },
    {
        "id": "100007",
        "last_update": "1400502382",
        "last_data": "1"
    },
    {
        "id": "100009",
        "last_update": "1400595887",
        "last_data": "hello world"
    }
]

 

(7)     獲取單個傳感器的歷史數據的響應

響應正文:

[
    {
        "id": "1017",
        "sensor_id": "100005",
        "timestamp": "1399906977",
        "value": "66ffcc"
    },
    {
        "id": "1023",
        "sensor_id": "100005",
        "timestamp": "1399907025",
        "value": "66ffcc"
    }
]

 

5.5 雲平臺測試結果分析

雲平臺的基本功能已經實現,而且具有了基礎的錯誤控制能力以及錯誤信息提示功能,可以以JSON格式返回請求的數據,而且完成對設備、傳感器的添加、查看、修改和刪除功能。

本課題中的雲平臺的設計方案中並無涉及界面的實現,並且就無線智能家居系統而言,控制界面的實現徹底由控制終端和Web控制平臺自主實現。該課題中的雲平臺僅負責完成數據的處理、存儲與請求,負責協調控制終端、Web控制平臺與智能家居網關之間的數據交互。因此,在雲平臺基礎功能測試經過,可以返回正確的數據以後,咱們認定該智能家居雲平臺基本方案設計已經完成。

對於無線智能家居系統而言,接下來須要智能家居網關、控制終端和Web平臺實現同雲平臺的數據提交和獲取,而後實例化設備,實現對實際設備的控制。

 


 

6 總結與展望

6.1 工做過程總結

本課題中智能家居雲平臺的設計更多地參考了Yeelink雲平臺的設計,將全部的操做抽象化爲對數據的操做,待到系統開發完成後再進行設備和功能的標準化和實例化。雲平臺面向的用戶羣爲開發者,爲無線智能家居系統後期開發服務,將提供詳細的API接口文檔及說明。課題中主要完成了如下工做:

(1)     經過對兩個較成熟的物聯網雲平臺(Ninja PlatformYeelink雲平臺)的API文檔的分析和解讀,並結合無線智能家居系統自身的需求,肯定了雲平臺的設計思想和基本設計方案:使用HTTP協議做爲通訊協議,JSON格式做爲數據交互格式(暫時只用作返回數據格式),PHP做爲編程語言,實現RESTful架構的API

(2)     肯定了基於PHP框架的RESTful API基本開發流程。經過現實中智能家居系統的結構分析,還有對物聯網雲平臺結構的研究,再配合雲平臺的需求分析、功能需求,完成了數據庫結構的設計,創建數據庫。而後依據PHPRESTful API的開發過程,結合PHP框架CodeIgniter和擴展庫rest-server完成雲平臺各功能及API的設計。

(3)     經過合理的測試方法對雲平臺API進行了系統的測試,修復雲平臺系統BUG,完善雲平臺系統結構,而且結合測試結果,編寫雲平臺API的說明文檔。

 

最終,咱們完成了智能家居雲平臺的設計,實現了論文中肯定的實現目標,獲得了一個用於支撐無線智能家居系統的遠程控制功能的數據處理平臺,編寫了雲平臺的API說明文檔,供給智能家居遠程控制終端和Web控制平臺使用。

 

6.2 不足及展望

雖然,本課題中的雲平臺已經設計完成,而且能正常運做。但由於雲平臺涉及內容很多,並且存在跨平臺的數據交互以及API請求,故而設計方案中還有部分功能沒有完善,並且測試案例也不夠全面,可能存在某些還沒有處理的BUG。這些問題須要在以後進行進一步的考慮和設計,才能獲得解決。現階段的工做完成以後,雲平臺已知的一些缺陷和不足有如下幾點:

(1)   數據的安全性

使用普通HTTP報文傳遞的數據是透明的,咱們經過抓包獲取了HTTP報文以後,就能夠獲取報文中傳遞的內容。例如登陸接口使用POST方法,用戶名與密碼都直接包含在請求報文內。爲了保證數據的安全性,通常來講會使用HTTPS協議。但由於涉及跨平臺的請求,我不肯定在網關、控制終端訪問使用HTTPS協議的接口時,是否會出現某些錯誤。

(2)   測試的侷限性

因爲無線智能家居系統沒有徹底實現,咱們沒有使用實際的設備來測試雲平臺的接口,雲平臺只測試了基本的數據提交和返回是否正確。也沒有對多併發的請求進行測試,所以在實際使用中,出現不少請求時,雲平臺系統的穩定性並無確切保證。

(3)   數據庫結構的優化

在設計過程當中,進行功能設計的時候,咱們結合具體功能的要求屢次修改了數據庫結構。爲了方便系統的實現,咱們優先採用了簡單有效的實現方法,數據庫結構也相對簡單。在下一步完善系統功能時,須要對數據庫結構進行修正與完善,確保結構的合理性和完備性。

 

總而言之,本課題的智能家居雲平臺設計雖已完成,但與成熟的物聯網雲平臺還有很大的差距,仍有許多待改進的方面。但云平臺最核心的功能已經完成,已經能夠使用其API進行控制終端和Web控制平臺的開發。

 


 參考文獻

[1] 張金家. 智能家居集成技術平臺系統分析[J]. 智能建築與城市信息, 2003(12): 22~25

[2] 李忠成. 智能倉儲物聯網的設計與實現[J]. 計算機系統應用, 2011(07): 16~18

[3] 查瓏瓏. 淺析物聯網智能家居發展[J]. 科技信息, 2012(25): 42~43

[4] 童曉渝, 房秉毅, 張雲勇. 物聯網智能家居發展分析[J]. 移動通訊, 2010(09): 16~20

[5] 鞏元鵬. 基於XMPP協議的智能家居遠程控制系統研究設計[D]. 中國海洋大學, 2012

[6] 王秀珍. 基於Web方式的智能家居遠程監控系統的設計與實現[D]. 南京郵電大學, 2012

[7] 魏振春, 韓江洪, 張建軍, 張利. 智能家居遠程控制系統的設計[J]. 合肥工業大學學報(天然科學版). 2005(07): 752~754

[8] 陳康, 鄭緯民. 雲計算:系統實例與研究現狀[J]. 軟件學報, 2009(05): 1337~1348

[9] 陳全, 鄧倩妮. 雲計算及其關鍵技術[J]. 計算機應用, 2009(09): 2562~2567

[10] 張建勳, 古志民, 鄭超. 雲計算研究進展綜述[J]. 計算機應用研究, 2010(02): 429~433

[11] 薛宏全, 楊琳. 嵌入式智能家居系統連入Internet的研究和實現[J]. 現代電子技術, 2007(13): 175~177

[12] Fielding R T. Architectural styles and the design of network-based software architectures[D]. University of California, 2000.

[13] Satio T, Tomoda I, Takabatake Y, et al. Home gateway architecture and its implementation. IEEE Transactions on Consumer Electronics. 2000

[14] 潘凱華. PHP從入門到精通[M]. 北京:清華大學出版社, 2010

[15] David Gourley, Brian Totty. HTTP權威指南[M]. 北京: 人民郵電出版社, 2012(09)

[16] W.Jason Gilmore. PHPMySQL 5程序設計[M]. 北京: 人民郵電出版社, 2007(01)

[17] Hypertext Transfer Protocol--HTTP/1.1. http://www.w3.org/Protocols/rfc2616/rfc2616.html

[18] Apache HttpClient 4.3.3 API. http://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/index.html

[19] Google Gson 2.2.4 API. http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/index.html

[20] Nginx Documentation. http://nginx.org/en/docs/index.html

[21] MySQL 5.6 Reference Manual. http://dev.mysql.com/doc/refman/5.7/en/

[22] PHP Manuel. http://www.php.net/manual/en/

[23] CodeIgniter User Guide Version 2.1.4. http://ellislab.com/codeigniter/user-guide/

[24] CodeIgniter Rest Server Introduction. https://github.com/philsturgeon/codeigniter-restserver

[25] Yeelink API文檔. http://www.yeelink.net/developer/api

[26] Ninja Blocks API. http://docs.ninja.is/

 





附件列表

相關文章
相關標籤/搜索