<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 構建基于CoAP協議的物聯網系統 ## 17.1 CoAP: 嵌入式系統的REST 引自維基百科上的介紹,用的是谷歌翻譯。。。 > 受約束的應用協議(COAP)是一種軟件協議旨在以非常簡單的電子設備,使他們能夠在互聯網上進行交互式通信中使用。它特別針對小型低功率傳感器,開關,閥門和需要被控制或監督遠程,通過標準的Internet網絡類似的組件。 COAP是一個應用層協議,該協議是用于在資源受限的網絡連接設備,例如無線傳感器網絡節點使用。 COAP被設計為容易地轉換為HTTP與Web簡化集成,同時也能滿足特殊的要求,例如多播支持,非常低的開銷,和簡單性。多播,低開銷,以及簡單性是因特網極其重要物聯網(IOT)和機器對機器(M2M)設備,這往往是積重難返,有太多的內存和電源,比傳統的互聯網設備有。因此,效率是非常重要的。 COAP可以在支持UDP或UDP的模擬大多數設備上運行。 簡單地來說,CoAP是簡化了HTTP協議的RESTful API,因而也只提供了REST的四個方法,即PUT,GET,POST和DELETE。對于微小的資源受限,在資源受限的通信的IP的網絡,HTTP不是一種可行的選擇。它占用了太多的資源和太多的帶寬。而對于物聯網這種嵌入式設備來說,關于資源與帶寬,是我們需要優先考慮的內容。 * CoAP采用了二進制報頭,而不是文本報頭(text header) * CoAP降低了頭的可用選項的數量。 * CoAP減少了一些HTTP的方法 * CoAP可以支持檢測裝置 ## 17.2 CoAP 命令行工具 為了測試測試我們的代碼是否是正確工作,我們需要一個CoAP的命令行工具。目前有兩個不錯的工具可以使用。 * CoAP-cli,一個基于NodeJS的CoAP命令行工具,其核心是基于Node-CoAP庫。 * libcooap,一個用C寫的CoAP命令行工具。 * FireFox Copper, 一個Firefox的插件。 ### 17.2.1 Node CoAP CLI 安裝命令如下 ~~~ npm install coap-cli -g ~~~ #### 17.2.1.1 CoAP命令行 在coap-cli中,一共有四個方法。分別表示REST的四種不同的方式: ~~~ Commands: get performs a GET request put performs a PUT request post performs a POST request delete performs a DELETE request ~~~ 在這里,我們用[coap://vs0.inf.ethz.ch/](coap://vs0.inf.ethz.ch/)來作一個簡單的測試 ~~~ coap get coap://vs0.inf.ethz.ch/ (2.05) ************************************************************ I-D ~~~ 測試一下現在的最小的物聯網系統CoAP版 ~~~ coap get coap://iot-coap.phodal.com/id/1 (2.05) [{"id":1,"value":"is id 1","sensors1":19,"sensors2":20}] ~~~ ### 17.2.2 libcoap #### 17.2.2.1 mac os libcoap安裝 Mac OS下可以直接用 ~~~ brew install libcoap ~~~ #### 17.2.2.2 Ubuntu libcoap安裝 Ubuntu GNU/Linux下 #### 17.2.2.3 Windows libcoap安裝 Windows 下 安裝完libcoap,我們可以直接用自帶的兩個命令 ~~~ coap-client coap-server ~~~ 1.用coap-server啟一個CoAP服務 ~~~ coap-server ~~~ 2.客戶端獲取數據 ~~~ coap-client -m get coap://localhost ~~~ 返回結果 ~~~ v:1 t:0 tkl:0 c:1 id:37109 This is a test server made with libcoap (see http://libcoap.sf.net) Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org> ~~~ ### 17.2.3 Firefox Copper 為了能訪問[coap://localhost/](coap://localhost/),于是我們便需要安裝一個Firefox并安裝一個名為Copper的插件。 1. 下載地址:?[https://addons.mozilla.org/en-US/firefox/addon/copper-270430/](https://addons.mozilla.org/en-US/firefox/addon/copper-270430/) 2. 作為測試我們同樣可以訪問?[coap://vs0.inf.ethz.ch:5683/](coap://vs0.inf.ethz.ch:5683/) ## 17.3 CoAP Hello,World 接著我們便開始試試做一個簡單的CoAP協議的應用: 這里用到的是一個Nodejs的擴展Node-CoAP > node-coap is a client and server library for CoAP modelled after the http module. Node-CoAP是一個客戶端和服務端的庫用于CoAP的模塊建模。創建一個package.json文件,添加這個庫 ~~~ { "dependencies":{ "coap": "0.7.2" } } ~~~ 接著執行 ~~~ npm install ~~~ 就可以安裝好這個庫。如果遇到權限問題,請用 ~~~ sudo npm install ~~~ 接著,創建這樣一個app.js ~~~ const coap = require('coap') , server = coap.createServer() server.on('request', function(req, res) { res.end('Hello ' + req.url.split('/')[1] + '\n') }) server.listen(function() { console.log('server started') }) ~~~ 執行 ~~~ node app.js ~~~ 便可以在瀏覽器上訪問了,因為現在什么也沒有,所以什么也不會返回。 接著下來再創建一個client端的js,并運行之 ~~~ const coap = require('coap') , req = coap.request('coap://localhost/World') req.on('response', function(res) { res.pipe(process.stdout) }) req.end() ~~~ 就可以在console上輸出 ~~~ Hello World ~~~ 也就達到了我們的目的,用CoAP協議創建一個服務,接著我們應該用它創建更多的東西,如產生JSON數據,以及RESTful。和HTTP版的最小物聯網系統一樣,CoAP版的最小物聯網系統也是要返回JSON的。 ## 17.3 CoAP 數據庫查詢 ### 17.3.1 Node Module 這說里NodeJS Module的意義是因為我們需要在別的地方引用到db_helper這個庫,也就是下一小節要的講的內容。 這樣我們就可以在server.js類似于這樣去引用這個js庫。 ~~~ var DBHelper = require('./db_helper.js'); DBHelper.initDB(); ~~~ 而這樣調用的前提是我們需要去聲明這樣的module,為了方便地導出函數功能調用。 ~~~ function DBHelper(){ } DBHelper.initDB = function(){}; module.exports = DBHelper; ~~~ ### 17.3.2 Node-Sqlite3 這次我們用的是SQLite3(你可以用MySQL,出于安全考慮用SQLite3,SQLite3產生的是一個文件)。一個簡單的initDB函數 ~~~ var db = new sqlite3.Database(config["db_name"]); var create_table = 'create table if not exists basic (' + config["db_table"] + ');'; db.serialize(function() { db.run(create_table); _.each(config["init_table"], function(insert_data) { db.run(insert_data); }); }); db.close(); ~~~ 首先從配置中讀取db_name,接著創建table,然后調用underscore的each方法,創建幾個數據。配置如下所示 ~~~ config = { "db_name": "iot.db", "db_table": "id integer primary key, value text, sensors1 float, sensors2 float", "init_table":[ "insert or replace into basic (id,value,sensors1,sensors2) VALUES (1, 'is id 1', 19, 20);", "insert or replace into basic (id,value,sensors1,sensors2) VALUES (2, 'is id 2', 20, 21);" ], "query_table":"select * from basic;" }; ~~~ 而之前所提到的url查詢所做的事情便是 ~~~ DBHelper.urlQueryData = function (url, callback) { var db = new sqlite3.Database("iot.db"); var result = []; console.log("SELECT * FROM basic where " + url.split('/')[1] + "=" + url.split('/')[2]); db.all("SELECT * FROM basic where " + url.split('/')[1] + "=" + url.split('/')[2], function(err, rows) { db.close(); callback(JSON.stringify(rows)); }); }; ~~~ 將URL傳進來,便解析這個參數,接著再放到數據庫中查詢,再回調回結果。這樣我們就可以構成之前所說的查詢功能,而我們所謂的post功能似乎也可以用同樣的方法加進去。 ### 17.3.3 查詢數據 簡單地記錄一下在IoT-CoAP中一次獲取數據地過程。 先看看在示例中的Get.js的代碼,這關乎在后面server端的代碼。 ~~~ const coap = require('coap') ,requestURI = 'coap://localhost/' ,url = require('url').parse(requestURI + 'id/1/') ,req = coap.request(url) ,bl = require('bl'); req.setHeader("Accept", "application/json"); req.on('response', function(res) { res.pipe(bl(function(err, data) { var json = JSON.parse(data); console.log(json); })); }); req.end(); ~~~ const定義數據的方法,和我們在其他語言中有點像。只是這的const主要是為了程序的健壯型,減少程序出錯,當然這不是javascript的用法。 我們構建了一個請求的URL ~~~ coap://localhost/id/1/ ~~~ 我們對我們的請求添加了一個Header,內容是Accept,值是'application/json'也就是JSON格式。接著,便是等待請求回來,再處理返回的內容。 **判斷請求的方法** 在這里先把一些無關的代碼刪除掉,并保證其能工作,so,下面就是簡要的邏輯代碼。 ~~~ var coap = require('coap'); var server = coap.createServer({}); var request_handler = require('./request_handler.js'); server.on('request', function(req, res) { switch(req.method){ case "GET": request_handler.getHandler(req, res); break; } }); server.listen(function() { console.log('server started'); }); ~~~ 創建一個CoAP服務,判斷req.method,也就是請求的方法,如果是GET的話,就調用request_handler.getHandler(req, res)。而在getHandler里,判斷了下請求的Accept ~~~ request_helper.getHandler = function(req, res) { switch (req.headers['Accept']) { case "application/json": qh.returnJSON(req, res); break; case "application/xml": qh.returnXML(req, res); break; } }; ~~~ 如果是json剛調用returnJSON, **Database與回調** 而這里為了處理回調函數剛分為了兩部分 ~~~ query_helper.returnJSON = function(req, res) { DBHelper.urlQueryData(req.url, function (result) { QueryData.returnJSON(result, res); }); }; ~~~ 而這里只是調用了 ~~~ DBHelper.urlQueryData = function (url, callback) { var db = new sqlite3.Database(config["db_name"]); console.log("SELECT * FROM basic where " + url.split('/')[1] + "=" + url.split('/')[2]); db.all("SELECT * FROM basic where " + url.split('/')[1] + "=" + url.split('/')[2], function(err, rows) { db.close(); callback(JSON.stringify(rows)); }); }; ~~~ 這里調用了node sqlite3去查詢對應id的數據,用回調處理了數據無法到外部的問題,而上面的returnJSON則只是返回最后的結果,code以及其他的內容。 ~~~ QueryData.returnJSON = function(result, res) { if (result.length == 2) { res.code = '4.04'; res.end(JSON.stringify({ error: "Not Found" })); } else { res.code = '2.05'; res.end(result); } }; ~~~ 當resulst的結果為空時,返回一個404,因為沒有數據。這樣我們就構成了整個的鏈,再一步步返回結果。 在[IoT-CoAP](https://github.com/phodal/iot-coap)中我們使用到了一個Block2的東西,于是便整理相關的一些資料,作一個簡單的介紹,以及在代碼中的使用。 ## 17.4 CoAP Block CoAP是一個RESTful傳輸協議用于受限設備的節點和網絡。基本的CoAP消息是一個不錯的選擇對于小型載荷如 * 溫度傳感器 * 燈光開關 * 樓宇自動化設備 然而,有時我們的應用需要傳輸更大的有效載荷,如——更新固件。與HTTP,TCP做繁重工作將大型有效載荷分成多個數據包,并確保他們所有到達并以正確的順序被處理。 CoAP是同UDP與DLTS一樣是基于數據報傳輸的,這限制了資源表示(resource representation)的最大大小,使得傳輸不需要太多的分割。雖然UDP支持通過IP分片傳輸更大的有效載荷,且僅限于64KiB,更重要的是,并沒有真正很好地約束應用和網絡。 而不是依賴于IP分片,這種規范基本COAP了對“塊”選項,用于傳輸信息從多個資源區塊的請求 - 響應對。在許多重要的情況下,阻止使服務器能夠真正無狀態:服務器可以處理每塊分開傳輸,而無需建立連接以前的數據塊傳輸的其他服務器端內存。 綜上所述,塊(Block)選項提供了傳送一個最小的在分塊的方式更大的陳述。 ### 17.4.1 CoAP POST 看看在IoT CoAP中的post示例。 ~~~ const coap = require('coap') ,request = coap.request ,bl = require('bl') ,req = request({hostname: 'localhost',port:5683,pathname: '',method: 'POST'}); req.setOption('Block2', [new Buffer('1'),new Buffer("'must'"), new Buffer('23'), new Buffer('12')]); req.setHeader("Accept", "application/json"); req.on('response', function(res) { res.pipe(bl(function(err, data) { console.log(data); process.exit(0); })); }); req.end(); ~~~ Block2中一共有四個數據,相應的數據結果應該是 ~~~ { name: 'Block2', value: <Buffer 31> } { name: 'Block2', value: <Buffer 27 6d 75 73 74 27> } { name: 'Block2', value: <Buffer 32 33> } { name: 'Block2', value: <Buffer 31 32> } ~~~ 這是沒有解析的Block2,簡單地可以用 ~~~ _.values(e).toString() ~~~ 將結果轉換為 Block2,1 Block2,'must' Block2,23 Block2,12 接著按","分開, ~~~ _.values(e).toString().split(',')[1] ~~~ 就有 ~~~ [ '1', '\'must\'', '23', '12' ] ~~~ 便可以很愉快地將其post到數據庫中了, 在做IoT-CoAP的過程中只支持JSON,查閱CoAP的草稿時發現支持了諸多的Content Types。 ### 17.4.2 CoAP Content Types 以下文字來自谷歌翻譯: > 互聯網媒體類型是通過HTTP字符串標識,如“application/xml”。該字符串是由一個頂層的類型“applicaion”和子類型的“XML”。為了盡量減少使用這些類型的媒體類型來表示的開銷消息有效載荷,COAP定義一個標識符編碼方案互聯網媒體類型的子集。預計這桌將可擴展標識符的值的IANA維護。內容類型選項被格式化為一個8位無符號整數。初始映射到一個合適的互聯網媒體類型標識符表所示。復合型高層次類型(multipart和不支持消息)。標識符值是從201-255保留的特定于供應商的,應用程序特定的或實驗使用和不由IANA。 下面是HTTP的標識符及類型 | Internet media type | Identifier | | --- | --- | | text/plain (UTF-8) | 0 | | text/xml (UTF-8) | 1 | | text/csv (UTF-8) | 2 | | text/html (UTF-8) | 3 | | image/gif | 21 | | image/jpeg | 22 | | image/png | 23 | | image/tiff | 24 | | audio/raw | 25 | | video/raw | 26 | | application/link-format [I-D.ietf-core-link-format] | 40 | | application/xml | 41 | | application/octet-stream | 42 | | application/rdf+xml | 43 | | application/soap+xml | 44 | | application/atom+xml | 45 | | application/xmpp+xml | 46 | | application/exi | 47 | | application/x-bxml | 48 | | application/fastinfoset | 49 | | application/soap+fastinfoset | 50 | | application/json | 51 | 而在CoAP中只有簡單地幾個 | Media type | Encoding | Id. | Reference | | --- | --- | --- | --- | | text/plain; | - | 0 | [RFC2046][RFC3676][RFC5147] | | charset=utf-8 | | | | | application/ | - | 40 | [RFC6690] | | link-format | | | | | application/xml | - | 41 | [RFC3023] | | application/ | - | 42 | [RFC2045][RFC2046] | | octet-stream | | | | | application/exi | - | 47 | [EXIMIME] | | application/json | - | 50 | [RFC4627] | 簡單地說就是: `諸如application/json的Content Types在CoAP中應該是50`。如上表所示的結果是其對應的結果,這樣的話可以減少傳遞的信息量。 ## 17.5 CoAP JSON 于是在一開始的時候首先支持的便是"application/json"這樣的類型。 首先判斷請求的header ~~~ request_helper.getHandler = function(req, res) { switch (req.headers['Accept']) { case "application/json": qh.returnJSON(req, res); break; case "application/xml": qh.returnXML(req, res); break; } }; ~~~ 再轉至相應的函數處理,而判斷的依據則是Accept是不是"application/json"。 ~~~ registerFormat('text/plain', 0) registerFormat('application/link-format', 40) registerFormat('application/xml', 41) registerFormat('application/octet-stream', 42) registerFormat('application/exi', 47) registerFormat('application/json', 50) ~~~ 對應地我們需要在一發出請求的時候設置好Accept,要不就沒有辦法返回我們需要的結果。 ~~~ req.setHeader("Accept", "application/json"); ~~~ **返回JSON** 在給IoT CoAP添加了JSON支持之后,變得非常有意思,至少我們可以獲得我們想要的結果。在上一篇中我們介紹了一些常用的工具——[CoAP 命令行工具集](http://www.phodal.com/blog/coap-command-line-tools-set/)。 **CoAP客戶端代碼** 開始之前我們需要有一個客戶端代碼,以便我們的服務端可以返回正確的數據并解析 ~~~ var coap = require('coap'); var requestURI = 'coap://localhost/'; var url = require('url').parse(requestURI + 'id/1/'); console.log("Request URL: " + url.href); var req = coap.request(url); var bl = require('bl'); req.setHeader("Accept", "application/json"); req.on('response', function(res) { res.pipe(bl(function(err, data) { var json = JSON.parse(data); console.log(json); })); }); req.end(); ~~~ 代碼有點長內容也有點多,但是核心是這句話: ~~~ req.setHeader("Accept", "application/json"); ~~~ 這樣的話,我們只需要在我們的服務端一判斷, ~~~ if(req.headers['Accept'] == 'application/json') { //do something }; ~~~ 這樣就可以返回數據了 **CoAP Server端代碼** Server端的代碼比較簡單,判斷一下 ~~~ if (req.headers['Accept'] == 'application/json') { parse_url(req.url, function(result){ res.end(result); }); res.code = '2.05'; } ~~~ 請求的是否是JSON格式,再返回一個205,也就是Content,只是這時設計是請求一個URL返回對應的數據。如 ~~~ coap://localhost/id/1/ ~~~ 這時應該請求的是ID為1的數據,即 ~~~ [ { id: 1, value: 'is id 1', sensors1: 19, sensors2: 20 }] ~~~ 而parse_url只是從數據庫從讀取相應的數據。 ~~~ function parse_url(url ,callback) { var db = new sqlite3.Database(config["db_name"]); var result = []; db.all("SELECT * FROM basic;", function(err, rows) { callback(JSON.stringify(rows)); }) } ~~~ 并且全部都顯示出來,設計得真是有點不行,不過現在已經差不多了。 ## 17.6 使用IoT-CoAP構建物聯網 (`注意`:windows系統npm install失敗時,需要自己建立一個C:\Documents and Settings[USERNAME]\Application Data\npm 文件) ~~~ npm install iot-coap ~~~ 1.新建**index.js** `注意`: 如果已經存在一個index.js文件,請將下面內容添加到文件末尾(create index.js, and add) ~~~ var iotcoap = require('iot-coap'); iotcoap.run(); iotcoap.rest.run(); ~~~ `注意`:在db配置可以選擇mongodb和sqlite3,替換所需要的數據庫即可。(you can choice db on iot.js with 'sqlite' or 'mongodb') 2.創建**iot.js** ~~~ exports.config = { "db_name": "iot.db", "mongodb_name": "iot", "mongodb_documents": "iot", "db": "mongodb", "table_name": "basic", "keys":[ "id", "value", "sensors1", "sensors2" ], "db_table": "id integer primary key, value text, sensors1 float, sensors2 float", "mongodb_init":[ { id: 1, value: "is id 1", sensors1: 19, sensors2: 20 }, { id: 2, value: "is id 2", sensors1: 20, sensors2: 21 } ], "init_table":[ "insert or replace into basic (id,value,sensors1,sensors2) VALUES (1, 'is id 1', 19, 20);", "insert or replace into basic (id,value,sensors1,sensors2) VALUES (2, 'is id 2', 20, 21);" ], "query_table":"select * from basic;", "rest_url": "/id/:id", "rest_post_url": "/", "rest_port": 8848 }; ~~~ 3.運行(run) ~~~ node index.js ~~~ show: ~~~ coap listening at coap://0.0.0.0:5683 restify listening at http://0.0.0.0:8848 ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看