物聯網時代 跟著Thingsboard學IOT架構-CoAP裝置協議

三升水發表於2019-07-26

thingsboard官網: https://thingsboard.io/

thingsboard GitHub: https://github.com/thingsboard/thingsboard

thingsboard提供的體驗地址: http://demo.thingsboard.io/

 

BY Thingsboard team

以下內容是在原文基礎上演繹的譯文。除非另行註明,頁面上所有內容採用知識共享-署名(CC BY 2.5 AU)協議共享。

原文地址: ThingsBoard API參考:CoAP裝置API


 

CoAP

協議介紹

CoAP是一種在物聯網世界的類web協議,它的詳細規範定義在RFC 7252。COAP名字翻譯來就是“受限應用協議”,顧名思義,使用在資源受限的物聯網裝置上。物聯網裝置的ram,rom都通常非常小,執行TCP和HTTP是不可以接受的。

 

協議特點

  1. CoAP協議網路傳輸層由TCP改為UDP。

  2. 它基於REST,server的資源地址和網際網路一樣也有類似url的格式,客戶端同樣有POST,GET,PUT,DELETE方法來訪問server,對HTTP做了簡化。

  3. COAP是二進位制格式的,HTTP是文字格式的,COAP比HTTP更加緊湊。

  4. 輕量化,COAP最小長度僅僅4B,一個HTTP的頭都幾十個B了。

  5. 支援可靠傳輸,資料重傳,塊傳輸。 確保資料可靠到達。

  6. 支援IP多播, 即可以同時向多個裝置傳送請求。

  7. 非長連線通訊,適用於低功耗物聯網場景。

客戶端庫設定

安裝

安裝node.js,然後執行以下命令:

 npm install coap-cli -g

 

用法

 Usage: coap [command] [options] url
 ​
 ​
   Commands:
 ​
     get      performs a GET request
     put      performs a PUT request
     post     performs a POST request
     delete   performs a DELETE request
 ​
   Options:
 ​
     -h, --help                    output usage information
     -V, --version                 output the version number
     -o, --observe                 Observe the given resource
     -n, --no-new-line             No new line at the end of the stream
     -p, --payload <payload>       The payload for POST and PUT requests
     -b, --block2 <option>         set the block2 size option
     -q, --quiet                   Do not print status codes of received packets
     -c, --non-confirmable         non-confirmable
     -t, --timeout <seconds>       The maximum send time in seconds
     -T, --show-timing             Print request time, handy for simple performance tests
     -O, --coap-option <key,value> Add COAP-Option to the request (repeatable)

 

PUT和POST

PUT和POST請求如下例所示

 echo -n 'hello world' | coap post coap://localhost/message

 


 

Thingsboard的CoAP傳輸協議架構

因為Thingsboard最新release,是基於微服務架構,不利用單獨理解程式碼。

Thingsboard CoAP裝置傳輸協議原始碼:https://github.com/thingsboard/thingsboard/tree/release-2.0/transport/coap

本文基於上面原始碼後,剔除相關的安全驗證和處理之後搭建簡易的講解專案:

https://github.com/sanshengshui/IOT-Technical-Guide/tree/master/IOT-Guide-Coap

 


CoAP框架

Thingsboard的CoAP裝置傳輸協議是基於Californium。Californium 是一款基於Java實現的Coap技術框架,該專案實現了Coap協議的各種請求響應定義,支援CON/NON不同的可靠性傳輸模式。 Californium 基於分層設計且高度可擴充套件,其內部模組設計及介面定義存在許多學習之處;

值得一提的是,在同型別的 Coap技術實現中,Californium的效能表現是比較突出的,如下圖:

更多的資料可以參考Californium-可擴充套件雲服務白皮書 本文以框架的原始碼分析為主,其他內容不做展開。

 

專案結構

 .
 └── main
     └── java
         ├── com
         │   └── sanshengshui
         │       └── coap
         │           ├── adaptors
         │           │   └── JsonCoapAdaptor.java
         │           ├── CoapTransportResource.java
         │           ├── common
         │           │   └── FeatureType.java
         │           └── session
         │               └── SessionMsgType.java
         └── IOTCoapServer.java
 

 

 

程式碼講解

IOTCoapServer

 1  public class IOTCoapServer {
 2  3      private static final String V1 = "v1";
 4      private static final String API = "api";
 5  6  7      private static String host = "127.0.0.1";
 8      private static Integer port = 5683;
 9      private static long timeout = 10000;
10 11      public static void main(String[] args) throws UnknownHostException {
12          CoapServer coapServer = new CoapServer();
13          CoapResource api = new CoapResource(API);
14          api.add(new CoapTransportResource(V1,timeout));
15          coapServer.add(api);
16          InetAddress addr = InetAddress.getByName(host);
17          InetSocketAddress sockAddr = new InetSocketAddress(addr, port);
18          coapServer.addEndpoint(new CoapEndpoint(sockAddr));
19          coapServer.start();
20 21      }
22 23  }

 

  • 第12行程式碼: CoapServer用作建立服務端。

  • 第12-15行: CoapResourceresource的基本實現,擴充套件這個類來編寫您自己的資源。通過向資源新增“v1”、"api"和超時時間的設定,則coap的基礎url為:coap://localhost:port/api/v1/

  • 第16-18行: Endpoint負責與網路進行通訊, 如果沒有一個Endpoint與CoapServer進行繫結,那就建立一個預設的Endpoint,預設就是ucp實現傳輸層。

  • 第19行,啟動CoAP服務。

 

以下圖片展示服務端的基礎架構:


 

CoapTransportResource

此類負責處理請求

GET
 
 @Override
     public void handleGET(CoapExchange exchange) {
         Optional<FeatureType> featureType = getFeatureType(exchange.advanced().getRequest());
         if (!featureType.isPresent()) {
         } else if (featureType.get() == FeatureType.TELEMETRY) {
             exchange.respond(CoAP.ResponseCode.BAD_REQUEST);
         }  else if (featureType.get() == FeatureType.ATTRIBUTES) {
             processRequest(exchange, SessionMsgType.GET_ATTRIBUTES_REQUEST);
         } else {
             exchange.respond(CoAP.ResponseCode.BAD_REQUEST);
         }
     }

 

  • 如果我們客戶端發起的是GET請求,那麼將會進入到handleGET(CoapExchange exchange)方法。

  • getFeatureType(Request request)判斷coap協議長度是否大於3。當大於等於3,獲取/api/v1/${param}param元素。

 public static final int FEATURE_TYPE_POSITION = 3;
 ​
 private Optional<FeatureType> getFeatureType(Request request) {
         List<String> uriPath = request.getOptions().getUriPath();
         try {
             if (uriPath.size() >= FEATURE_TYPE_POSITION) {
                 return Optional.of(FeatureType.valueOf(uriPath.get(FEATURE_TYPE_POSITION - 1).toUpperCase()));
             }
         } catch (RuntimeException e) {
         }
         return Optional.empty();
     }

 

  • 通過判斷param是否是temperature還是attributes進行相關的邏輯操作。

  • 當不是上述型別,回覆狀態為BAD_REQUEST的狀態碼。

 

POST
 
@Override
     public void handlePOST(CoapExchange exchange) {
         Optional<FeatureType> featureType = getFeatureType(exchange.advanced().getRequest());
         if (!featureType.isPresent()) {
             exchange.respond(CoAP.ResponseCode.BAD_REQUEST);
         } else {
             switch (featureType.get()) {
                 case ATTRIBUTES:
                     processRequest(exchange, SessionMsgType.POST_ATTRIBUTES_REQUEST);
                     break;
                 case TELEMETRY:
                     processRequest(exchange, SessionMsgType.POST_TELEMETRY_REQUEST);
                     break;
             }
         }
     }

 

  • 如果我們客戶端發起的是POST請求,那麼將會進入到handlePOST(CoapExchange exchange)方法。

  • 對獲取的uri的型別是temperature還是attributes來做相關的邏輯操作。

 

邏輯處理
 
private void processRequest(CoapExchange exchange, SessionMsgType type) {
         exchange.accept();
         Exchange advanced = exchange.advanced();
         Request request = advanced.getRequest();
 ​
         try {
             switch (type) {
                 case GET_ATTRIBUTES_REQUEST:
                 case POST_TELEMETRY_REQUEST:
                 case POST_ATTRIBUTES_REQUEST:
                     //這個類在之前的物模型博文中有所講解,大家可以翻看!
                     JsonCoapAdaptor.convertToMsg(type,request);
                     break;
                 default:
                     throw new IllegalArgumentException("Unsupported msg type: " + type);
             }
             exchange.respond("Data has been received");
         } catch (AdaptorException e){
             exchange.respond(CoAP.ResponseCode.BAD_REQUEST, e.getMessage());
         } catch (IllegalArgumentException  e) {
             exchange.respond(CoAP.ResponseCode.INTERNAL_SERVER_ERROR, e.getMessage());
         }
     }

 


 

專案演示

遙測上傳API

要將遙測資料釋出到伺服器節點,請將POST請求傳送到以下URL:

 
coap://host/api/v1/telemetry

 

最簡單的支援資料格式是:

 
{"key1":"value1", "key2":"value2"}

 

要麼

 
[{"key1":"value1"}, {"key2":"value2"}]

 

請注意,在這種情況下,伺服器端時間戳將分配給上傳的資料!

如果您的裝置能夠獲取客戶端時間戳,您可以使用以下格式:

 {"ts":1451649600512, "values":{"key1":"value1", "key2":"value2"}}

 

在上面的示例中,我們假設“1451649600512”是具有毫秒精度的unix時間戳。例如,值'1451649600512'對應於'Fri,2016年1月1日12:00:00.512 GMT'

例子:

 echo -n '{"size":21,"type":"device"}' | coap post coap://demo.thingsboard.io/api/v1/telemetry

 

結果:
 key= 1564105084015
 屬性名=size 屬性值=21
 屬性名=type 屬性值=device

 

屬性API

屬性API允許裝置

  • 將客戶端裝置屬性上載到伺服器。

  • 從伺服器請求客戶端和共享裝置屬性。

將屬性更新發布到伺服器

要將客戶端裝置屬性發布到ThingsBoard伺服器節點,請將POST請求傳送到以下URL:

 coap://host/api/v1/attributes

 

例子:

 echo -n '{"size":21,"type":"device","status":true}' | coap post coap://localhost:5683/api/v1/attributes

結果:

 
key= 1564105158573
 屬性名=size 屬性值=21
 屬性名=type 屬性值=device
 屬性名=status 屬性值=true
 
從伺服器請求屬性值

要向ThingsBoard伺服器節點請求客戶端或共享裝置屬性,請將GET請求傳送到以下URL:

 
coap://host/api/v1/attributes?clientKeys=attribute1,attribute2&sharedKeys=shared1,shared2

 

例子:

 coap get coap://localhost:5683/api/v1/attributes?clientKeys=attribute1,attribute2&sharedKeys=shared1,shared2

 

結果:

 (2.05)  Data has been received

 

到此,物聯網時代,相信大家對IOT架構下的CoAP協議有所瞭解了,感謝大家的閱讀!

 

相關文章