首先很是感謝,上篇文章中一些前輩的指導,其中一些意見讓我獲益匪淺!html
關於物聯網,我以爲靈魂仍是在軟件上,前端的各類硬件聯網標準一旦造成也就沒啥事了,更多的仍然是數據的存儲,分析。其實,物聯網說白了更是一種數據服務一條龍。從數據的採集到數據的傳送以及數據的存儲和處理。數據的傳送就不用說了,屬於通訊的範疇,屬於寬帶和三大運營商的領地,數據的的採集屬嵌入式的範疇,數據的存儲可能通常的程序員和DBA就能夠搞定,最有核心的部分就是數據的分析了,只惋惜作數據挖掘和大數據處理的,大都是博士和碩士級別的吧!因此作爲一名普通的二本畢業生,我準備將目標鎖定在嵌入式的方向,準確的說是嵌入式軟件開發工程師。前端
一直以來經常張口物聯網,閉口智能傢俱,終於在最後的時間裏,付出了實踐,作了一個基於嵌入式Linux的智能傢俱遠程控制系統,固然系統在不斷的完善,目前已經實現了遠程控制和環境信息實時上傳的功能。但願各路大牛,多拍板磚,多提指導性意見。java
本文的主要目標是展現系統的服務器,關於嵌入式環境搭建/驅動的編寫,不詳細說明。程序員
在實現智能家居控制系統以前,咱們須要搭建一我的機交互界面,這裏我主要採用了HTML頁面,也就是最終實現的目標是,人們能夠在有網絡的地方登錄位於家裏的嵌入式WEB服務器,而後經過這些網頁來進行用電器的操控,同時,也能夠將家裏的實時環境值傳送到HTML頁面,你能夠遠程查看居室內的環境信息,遠程爲家人打開空氣淨化器或者是空調。web
STEP 0:開發準備面試
宿主機:Ubuntu操做系統ajax
開發板:FriendlyARM mini2440編程
驅動程序:LED驅動,溫度傳感器驅動瀏覽器
相關技術準備:Socket編程/HTTP協議/JavaScript服務器
STEP 1:實現WEB服務器
嵌入式雖然小,但仍是有一批開源的服務器是可供選擇的,好比大名鼎鼎的boa,小巧強悍。我在最開始的時候也是選擇移植boa服務器做爲智能傢俱的服務器,可是後來在添加傢俱控制模塊和溫度傳輸模塊的時候以爲很不方便,因而呼就決定手動打造一個服務器,雖然和boa相差十萬裏,可是學到的東西也更多,並且對web的機理有了更深入的認識,覺的做爲一個學習者,值了。
在徒手開發服務器以前,你必需要知道,web底層的工做機理,說到這裏有一個段子,有一次我去面試,崗位是java web,boss問我你對web有什麼認識,我隨口一說:「其實web說到底就是socket和http」,後來在一次聚餐的時候boss給我說:「當聽到一個還未畢業的學生對web能有如此認識,感到很意外,因此即便你沒有經驗我也仍是會僱傭的。」看來,有時候吹牛逼真的很管用,哈哈。
雖然是吹牛逼,但web的實質的確是socket和http協議,瀏覽器端我不清楚也就不亂說了,可是我擦瀏覽器裏面必定有個socket來和咱們的服務器進行通訊。接下來詳細說說咱們的服務器端,服務器要想和瀏覽器取得通訊,首先須要創建一個socket,而後就是傳統的網絡編程,可是要注意,服務器和瀏覽器進行「對話時」,使用的是「HTTP」語言。也就是說web的實質是HTML+SOCKET+瀏覽器。然而socket又是tcp/ip協議的程序實現層,所以web的實質就是html+TCP/IP+瀏覽器。然而HTML的實質又是文件,所以web的實質又是 文件+TCP/IP+瀏覽器(文件翻譯器(特殊文件翻譯器))。關於瀏覽器我是在研究的很少,不敢亂說。
所以,總結成一句話就是:「WEB就是向一臺被稱爲服務器的計算機上請求文件,服務器將指定文件發送到瀏覽器,而後瀏覽器解析文件並展現的一個過程」。
server_sockfd=socket(AF_INET,SOCK_STREAM,0); if(server_sockfd<0) { printf("create socket failed!\n"); exit(EXIT_FAILURE); } memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family=AF_INET; server_addr.sin_port=htons(PORT); server_addr.sin_addr.s_addr=INADDR_ANY; if(bind(server_sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr))!=0){ printf("bind error!\n"); exit(EXIT_FAILURE); }
通過上面的操做,已經爲服務器建立了一個socket,也爲socket綁定ip地址和端口,這樣一來,就爲咱們的服務器在茫茫的網絡海洋中有了準確的定位。
關於socket和sockaddr_in,我一直是這樣理解的,一個socket至關於一部手機,若是你想別人可以打通你的手機,首先你要有一個SIM卡,而這個sockaddr_in則至關於sim卡,一旦和你手機綁定後,別人(客戶端)就能夠向你發起呼叫。
接下來就是socket編程的通常步驟,Listen和accpect,至關於你的手機裝上了SIM卡而且打開了手機,等待別人的呼叫。
client_sockfd=accept(server_sockfd,(struct sockaddr*)&client_addr,&addr_len);
accpect函數實現阻塞程序的繼續進行,直到有客戶端發起請求,當有客戶端發起請求的話,accpect函數返回這個連接的描述符號。返回的結果表明客戶端與服務器的連接描述,下面能夠直接用這個描述符來表明已經創建的連接關係。
進行到此時,比如一我的撥通了你的電話而且你接聽了電話,此刻大家的連接創建了。你能夠用耳朵貼在話筒上聽那人說了些什麼,在咱們的程序裏你一樣能夠用recv來接聽客戶端都發送了那些請求。
int recv_len=recv(client_sockfd,buffer,sizeof(buffer),0);
其中,buffer表明接收到客戶端請求信息以及該客戶端的相關信息。彷彿那人給你說的那些話。
關於buffer會是什麼內容,相信沒有接觸過的人都很好奇,我也同樣,因而乎打印了出來(前提是我在瀏覽器地址欄輸入了http:127.0.0.1:8000/main.html):
GET /main.html HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
接下來就發現了這些有意思的東西(不要笑我,我真的是小白),第一次看見這東西真的很驚奇。看到了這裏我瞬間明白了不少東西:
1 若是我又一個服務器,我能知道,那些ip訪問了個人服務器,訪問了多少次,地理位置在哪裏。
2 我知道了他用的什麼瀏覽器
3 我知道了他的主機是什麼系統,還有有關本次連接使用的語言/編碼方式/連接類型。。。
其實,咱們最關心的就是第一句,第一句是它(客戶端)想GET main.html;意思是瀏覽器想向服務器請求main.html。
好了,若是你想在瀏覽器成功展現出main.html,你須要將main.html整個文件發送給客戶端,可是請注意第一句「GET /main.html HTTP/1.1」,有沒有發現它們有着特殊的形式,這就是WEB的語言吧,暫且這樣稱呼它。若是咱們直接調用write函數將main.html發送給客戶端,客戶端會不會以爲太迷茫,它會以爲發了一坨什麼東西,所以在這裏服務器也要以相似的形式首先給瀏覽器發送一段相似的文字而後將整個main.html文件發送過去:
HTTP/1.1 200 OK\r\n
Conten-Type:html\r\n
發送main.html的完成代碼以下:
1 sprintf(buffer,"HTTP/1.1 200 OK\r\n"\ 2 "Conten-Type:%s\r\n"\ 3 "\r\n",mine_type); 4 int file_length=strlen(buffer); 5 do{ 6 if(write(socket_fd,buffer,file_length)<0){ 7 close(fd); 8 break; 9 } 10 }while((file_length=read(fd,buffer,sizeof(buffer)))>0);
其中mine_type爲文件的類型,好比jif,png,html等等。
至此,一個完整的會話就完成了,一個超級無敵簡易的網頁瀏覽器也就搞定了。
STEP2:智能傢俱控制模塊
嚴格的說,這是web服務器的擴展模塊,就是這個服務器不只可以提供網頁的文件資源,還能夠調用驅動來進行硬件的操做。
好比要進行燈光控制,在html頁面裏有一個燈泡的圖片按鈕,當點擊按鈕的時候,用JavaScript想後臺發送制定的請求內容,好比發送請求內容爲:「myled.cgi」,注意這裏的後綴不表明請求一個cgi的文件,由於服務器是本身的寫的本身解析的,想表明什麼本身說了算,就tm這麼任性和這麼爽!這裏我指定它表明燈光控制部分。
1 int recv_len=recv(client_sockfd,buffer,sizeof(buffer),0); 2 printf("*****%d bytes recved!***********\n",recv_len); 3 p_buffer=buffer; 4 if(0==strncmp("GET /myled.cgi",buffer,14)) 5 { 6 printf("hello,heat nan!\n"); 7 send_light_cmd(p_buffer,client_sockfd); 8 9 }
以上的代碼,我首先判斷它請求的操做是否爲燈光操做,若是是則將這些信息做爲參數傳遞給燈光模塊處理。
關於燈光模塊分爲兩個部分,一個部分是肯定對那個燈進行操做,第二個部分是執行硬件操做,若是是用電器的開關 ,則主要是設置與用電器綁定的IO口電平。
STEP3:實時環境信息模塊
關於實時環境信息模塊和智能傢俱控制模塊一模一樣,首先當用戶進入環境信息界面,ajax主動向服務器每10s發送一次溫度請求,服務器接受到指令後,立刻調用溫度傳感器驅動採集一次溫度,而後將溫度傳遞到前端的html頁面,如此讓用戶每隔10ms看到家裏的溫度一次,也算實時吧!至此,一個家居遠程控制系統就算完成了,不能叫系統吧!此時感受如此之小 ,叫個小demo吧!此時此刻,家裏的電器確實是連上網了,應該能夠叫作「物聯網了吧!」若是將採集的溫度值不斷的和設定喜愛溫度值做比較從而讓程序自動控制空調和地暖的開關,這應該叫「智能家居了吧!」。然而,這應該是現實的物聯網;理想的物聯網應該是這樣:你的空調會受到一個巨大的數據平臺作支持,這個數據平臺分別鏈接了最權威的健康機構,能夠提供不一樣時節/不一樣時間段最健康的溫度,你的空調會和你的手機相互通訊,手機會告訴空調,孩子主人距離家裏10千米,請你立馬工做。空調應當會有記憶功能,分別記住主人在不一樣時段,不一樣季節最喜好的溫度,你的空調應當和你的手環相連,當你在左手跟着右手一個慢動做的時候,手環會向空調發出指令,孩子主人心跳加速,體溫上升,速度降溫,從而不會讓你大汗淋漓。若是當這一天真的來臨,請叫他真正的物聯網時代吧!