NB-IoT 學習開發和應用 第四講

NB-IoT 學習開發和應用 第四講

阿里雲物聯網平臺中的CoAP協議學習和分析

CoAP協議:CoAP協議的底層協議是 UDP (比喻:打電話,單方通信,無需保持鏈接)
應用範圍: NB-IoT、超低功耗應用、野外數據採集監控系統、遠程抄表等
特點 :只能數據上報(注:在CoAP協議的定義中,非底層的UDP協議),服務器無法對數據進行下發控制指令。

CoAP協議報文(一共只有4個)
分別是:
1、CON報文(連接請求報文),給服務器發報文,並且發送完以後,服務器必須要發送ACK報文給設備端(即響應報文)
2、NON報文(發送給服務器,服務器無需回覆)
3、ACK報文 (響應報文)
4、RST報文(代表數據發送錯誤,提醒用戶重新發送正確的數據給服務區)

注:且在阿里雲物聯網平臺中的的CoAP協議中,只支持 CON報文的數據類型。其他數據格式或者協議,服務器均不支持。
同時,在阿里雲物聯網服務器中,上傳的數據有兩種形式(CON的兩種形式)
1、設備認證報文
2、數據上傳報文

CoAP協議報文的格式組成形式:
Ver+T+TKL+Code+Messige ID+Token+Options+0xff(分隔字符)+Payload

拆分分析:
Ver : 版本號 2bit
T : 報文類型 2bit (CON : 00 NON : 01 ACK : 10 RST : 11 )
TKL : 表示標識符(Token)的長度 4bit,Token在報文種是非必須的
Code :功能響應碼 (共有四種 GET、POST、 PUSH、 DELETE)8bit
                                                    0.01     0.02       0.03           0.04
注:Code一個是8個bit(一個字節),前三位表示整數,後五位表示小數。
Message ID:報文編號消息編號,一般來說,每發一次Message ID加1.(數據標記)
Token    :(可不要,在阿里雲中我們默認不添加Token報文)
Options   :數據選擇模式
0xff          : 間隔符(用於分離上傳格式和數據)
Pyload     :上傳的數據

在上述講解之前需要在此之前創建設備,獲取阿里雲的三元組

阿里雲平臺下的設備的三個基本參數:
{
  "ProductKey": "a125zR8hwQq",
  "DeviceName": "D001",
  "DeviceSecret": "TmRnTWVOWjTPgqNIsVwcLqRInIQ9NFvn"
}

在阿里雲物聯網的開發文檔中詳細講解了CoAP協議中上報數據的格式(注:這裏使用使用對稱加密自主接入(軟件加密),阿里雲物聯網平臺還有一種硬件加密(叫:DTLS加密)形式。)
在:阿里雲物聯網CoAP協議說明
同時,可以看到有以下兩種報文的上傳的數據格式
分別是:

1、阿里雲設備認證請求報文:
格式數據如下

POST /auth
Host: ${YourProductKey}.coap.cn-shanghai.link.aliyuncs.com
Port: 5682
Accept: application/json or application/cbor
Content-Format: application/json or application/cbor
payload: {"productKey":"a1NUjcV****","deviceName":"ff1a11e7c08d4b3db2b1500d8e0e55","clientId":"a1NUjcV****&ff1a11e7c08d4b3db2b1500d8e0e55","sign":"F9FD53EE0CD010FCA40D14A9FE******", "seq":"10"}

所以我們在終端需要構建上述的報文格式(我們構建報文的形式是以CoAP協議的數據格式進行構建,這樣在雲服務器就能夠解析我們發送的數據)
我們在構建是需要以:
CoAP協議報文的格式組和形式:
Ver+T+TKL+Code+Messige ID+Token+Options+0xff(分隔字符)+Payload
(注:以上的每個代表的含義在上方已經定義,可往上進行閱覽)
首先是:
Ver : 01
T :00 (CON : 00 NON : 01 ACK : 10 RST : 11 )
TKL : 0000 (默認不用Token數據,所以數據長度爲0)
Code : 000.00010 (GET:0.01 POST:0.02 PUSH:0.03 DELETE : 0.04)
Message ID ;0x?? 0x??(消息編號,建議,可以從0x00 0x00 開始,沒上傳(post)一條報文(消息)就加1 )
Token :可以省略不寫(無數據)

  • 這樣上面轉換成16進制就是 : 0x40 0x02 0x01 0x01

接下來就是Options的數據組成形式:
在阿里雲阿里雲設備認證請求報文中:即

POST /auth
Host: ${YourProductKey}.coap.cn-shanghai.link.aliyuncs.com
Port: 5682
Accept: application/json or application/cbor
Content-Format: application/json or application/cbor
payload: {"productKey":"a1NUjcV****","deviceName":"ff1a11e7c08d4b3db2b1500d8e0e55","clientId":"a1NUjcV****&ff1a11e7c08d4b3db2b1500d8e0e55","sign":"F9FD53EE0CD010FCA40D14A9FE******", "seq":"10"}

除了payload以外,以上的全是在options中進行數據的組合
Options : 由option-delta (4個bit) 和option length(4個bit 或者再增加一個字節到兩個字節來表示後面字符的長度)
options : 0011 ???(表示後續字節的長度),如果單獨用4bit位來表示長度,那麼最大位1100(十進制的12),如果是(1101)(十進制的13)則代表的是後面再擴展一個字節來表示數據的長度,後面的那個字節的長度=實際長度-13
如果是(1110)(十進制的14)則代表的是後面再擴展2個字節來表示數據的長度,後面的那個字節的長度=實際長度-14-255 (用兩個字節來表示剩餘長度)

首先是:
Host: ${YourProductKey}.coap.cn-shanghai.link.aliyuncs.com (HOST 指令是用3來表示)

option delta 表示發送的option的增量,(因爲每一個指令有不同的序列號來表示),代表的是不同的數據增量。
options : 0011 ???(表示後續字節的長度),如果單獨用4bit位來表示長度,那麼最大位1100(十進制的12),如果是(1101)(十進制的13)則代表的是後面再擴展一個字節來表示數據的長度,後面的那個字節的長度=實際長度-13
如果是(1110)(十進制的14)則代表的是後面再擴展2個字節來表示數據的長度,後面的那個字節的長度=實際長度-14-255 (用兩個字節來表示剩餘長度)

首先是:
Host: a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com (HOST 指令是用3來表示,這是第一個指令,所以delta=3-0=3)
所以:0011 ???(注:4個問號代表的是後面數據長度,即" a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com "的長度是46,所以需要額外增加一個字節的長度,這樣 ????=1101=D(16進制),後面跟的字節=46-13=33=0x21)
總的第一個字節就是 : 0x3D
後面的1個字節是: 0x21
最後的字節是:(a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com)的16進制數
總的後面的字節是:
0x3D 0x21 +(a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com)16進制

接下來是
Port : 5682 (前面的Host 是指令3 Port 是指令 7 ,所以delta=7-3=4)

所以: 0100 ???? (5682的十六進制是兩個字節,固????= 0010)
總的第一個字節就是 : 0x42
後面的兩個字節是: 0x16 0x32(5682的16進制=0x1632)
總的後面字節是:
0x42 0x16 0x32

隨後是:
POST /auth (前面的Port是指令7 Path(也就是post) 是指令 11 ,所以delta=11-7=4)
所以: 0100 ????(auth就是4個字節,????=0100)
總的第一個字節就是 : 0x44
後面的4個字節是: 0x61 0x75 0x74 0x68("auth"的16進制,注:斜槓不屬(不計入)於字符)
總的字節是:
0x44 + 0x61 0x75 0x74 0x68("auth"的16進制,注:斜槓不屬(不計入)於字符)

在後來是:
Content-Format: application/json or application/cbor
(前面的POST是指令1 Content-Format是指令 12 ,所以delta=12-11=1)
所以: 0001 ????(application/json or application/cbor在CoAP中有對應的指令爲,所以這裏????=0001 ,因爲50的十六進制是0x32,也就是後面的長度是1)
總的第一個字節就是 : 0x11
後面的1個字節是: 0x32
總的字節是: 0x11 0x32

Accept: application/json or application/cbor
(前面的Content-Format是指令12 Accept是指令 17 ,所以delta=17-12=5)
所以: 0101 ????(application/json or application/cbor在CoAP中有對應的指令爲,所以這裏????=0001 ,因爲50的十六進制是0x32,也就是後面的長度是1)
總的第一個字節就是 : 0x51
後面的1個字節是: 0x32

這樣options的參數就全部完成了,接下來則還剩下分隔符和payload的數據了

分隔符 :(隔離)
0xff

payload:{“productKey”:“a125zR8hwQq”,“deviceName”:“ff1a11e7c08d4b3db2b1500d8e0e55”,“clientId”:“a125zR8hwQq&ff1a11e7c08d4b3db2b1500d8e0e55”,“sign”:“F9FD53EE0CD010FCA40D14A9FE******”, “seq”:“10”} (調試發送時,變成16進制便於發送)

{
“ProductKey”: “a125zR8hwQq”,
“DeviceName”: “D001”,
“DeviceSecret”: “TmRnTWVOWjTPgqNIsVwcLqRInIQ9NFvn”
}

返回數據:

{"random":"ad2b3a5eb51d6****","seqOffset":1,"token":"MZ8m37hp01w1SSqoDFzo001050****.ad2b"}

但是在16進制中看到的數據時這樣的

發送後會得到回覆數據:
0x60  0x45  (表示接收的是正確請求,否則出現錯誤)
0xff

0x?? ... (一堆的加密的密鑰等其他數據,就是上述{random:“xxx...."等這些數據)

由上面即可得到:上述這些即可實現設備認證請求。

2、阿里雲數據上報數據請求:
數據格式如下:

POST /topic/${topic}
Host: ${YourProductKey}.coap.cn-shanghai.link.aliyuncs.com
Port: 5682
Accept: application/json or application/cbor
Content-Format: application/json or application/cbor
payload: ${your_data}
CustomOptions: number:2088(標識token), 2089(seq)

替換更改後的數據是:

POST /topic//sys/a1P71zSMssS/D001/thing/event/property/post
Host: a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com
Port: 5682
Accept: application/json or application/cbor
Content-Format: application/json or application/cbor
payload: ${your_data}
CustomOptions: number:2088(標識token), 2089(seq)

開始構建數據上傳報文:
CoAP協議報文的格式組和形式:
Ver+T+TKL+Code+Messige ID+Token+Options+0xff(分隔字符)+Payload
(注:以上的每個代表的含義在上方已經定義,可往上進行閱覽)

首先是:
Ver : 01
T :00 (CON : 00 NON : 01 ACK : 10 RST : 11 ,注:阿里雲CoAP協議中只支持 CON 格式)
TKL : 0000 (默認不用Token數據,所以數據長度爲0)
Code : 000.00010 (GET:0.01 POST:0.02 PUSH:0.03 DELETE : 0.04)
Message ID ;0x?? 0x??(消息編號,建議,可以從0x00 0x00 開始,沒上傳(post)一條報文(消息)就加1 )
Token :可以省略不寫(無數據)

  • 這樣上面轉換成16進制就是 : 0x40 0x02 0x01 0x01

首先是:
Host: a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com (HOST 指令是用3來表示,這是第一個指令,所以delta=3-0=3)
所以:0011 ???(注:4個問號代表的是後面數據長度,即" a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com "的長度是46,所以需要額外增加一個字節的長度,這樣 ????=1101=D(16進制),後面跟的字節=46-13=33=0x21)
總的第一個字節就是 : 0x3D
後面的1個字節是: 0x21
最後的字節是:(a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com)的16進制數
總的後面的字節是:
0x3D 0x21 +(a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com)16進制

接下來是
Port : 5682 (前面的Host 是指令3 Port 是指令 7 ,所以delta=7-3=4)

所以: 0100 ???? (5682的十六進制是兩個字節,固????= 0010)
總的第一個字節就是 : 0x42
後面的兩個字節是: 0x16 0x32(5682的16進制=0x1632)
總的後面字節是:
0x42 0x16 0x32

接下來就是Options的數據組成形式:
在阿里雲阿里雲設備認證請求報文中:即

POST /topic//sys/a1P71zSMssS/D001/thing/event/property/post
Host: a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com
Port: 5682
Accept: application/json or application/cbor
Content-Format: application/json or application/cbor
payload: ${your_data}
CustomOptions: number:2088(標識token), 2089(seq)

除了payload以外,以上的全是在options中進行數據的組合
Options : 由option-delta (4個bit) 和option length(4個bit 或者再增加一個字節到兩個字節來表示後面字符的長度)
options : 0011 ???(表示後續字節的長度),如果單獨用4bit位來表示長度,那麼最大位1100(十進制的12),如果是(1101)(十進制的13)則代表的是後面再擴展一個字節來表示數據的長度,後面的那個字節的長度=實際長度-13
如果是(1110)(十進制的14)則代表的是後面再擴展2個字節來表示數據的長度,後面的那個字節的長度=實際長度-14-255 (用兩個字節來表示剩餘長度)

首先是:
Host: a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com (HOST 指令是用3來表示,這是第一個指令,所以delta=3-0=3)
所以:0011 ???(注:4個問號代表的是後面數據長度,即" a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com "的長度是46,所以需要額外增加一個字節的長度,這樣 ????=1101=D(16進制),後面跟的字節=46-13=33=0x21)
總的第一個字節就是 : 0x3D
後面的1個字節是: 0x21
最後的字節是:(a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com)的16進制數
總的後面的字節是:
0x3D 0x21 +(a125zR8hwQq.coap.cn-shanghai.link.aliyuncs.com)16進制

接下來是
Port : 5682 (前面的Host 是指令3 Port 是指令 7 ,所以delta=7-3=4)

所以: 0100 ???? (5682的十六進制是兩個字節,固????= 0010)
總的第一個字節就是 : 0x42
後面的兩個字節是: 0x16 0x32(5682的16進制=0x1632)
總的後面字節是:
0x42 0x16 0x32
(注:在設備認證和數據上傳中,以上是通用的數據模型)

POST /topic/topicPort7Path(post)11delta=117=40100????auth4????=0100/topic/{topic} (前面的Port是指令7 Path(也就是post) 是指令 11 ,所以delta=11-7=4) 所以: 0100 ????(auth就是4個字節,????=0100) /topic/{topic} 中的${topic}替換爲 /sys/a1P71zSMssS/D001/thing/event/property/post
替換後的是: /topic /sys/a1P71zSMssS/D001/thing/event/property/post
又因爲後面一共將路徑分成了多個小節,在CoAP協議中需要單獨的進行統計來計算
故:
對於第一個字符串 topic 後的表示
的第一個字節是 :0x45 (前面的Port是指令7 Path(也就是post) 是指令 11 ,所以delta=11-7=4)
總的後面跟隨的5個字節就是 : 74 6F 70 69 63 ("topic"的16進制)

對於第2個字符串 sys後的表示
的第一個字節是 :0x03 (前面的Path是指令11 Path(也就是post)也 是指令 11 ,所以delta=11-11=0)
總的後面跟隨的3個字節就是 : 73 79 73 ("sys"的16進制)

對於第3個字符串 a1P71zSMssS後的表示
的第一個字節是 :0x0B (前面的Path是指令11 Path(也就是post)也 是指令 11 ,所以delta=11-11=0)
總的後面跟隨的11個字節就是 :61 31 50 37 31 7A 53 4D 73 73 53 ("a1P71zSMssS"的16進制)

對於第4個字符串 D001後的表示
的第一個字節是 :0x04 (前面的Path是指令11 Path(也就是post)也 是指令 11 ,所以delta=11-11=0)
總的後面跟隨的4個字節就是 :44 30 30 31 ("D001"的16進制)

對於第5個字符串 thing後的表示
的第一個字節是 :0x05 (前面的Path是指令11 Path(也就是post)也 是指令 11 ,所以delta=11-11=0)
後面的5個字節是: 74 68 69 6E 67 ("thing"的16進制,注:斜槓不屬(不計入)於字符)

對於第6個字符串 event後的表示
的第一個字節是 :0x05 (前面的Path是指令11 Path(也就是post)也 是指令 11 ,所以delta=11-11=0)
後面的5個字節是: 65 76 65 6E 74 ("event"的16進制,注:斜槓不屬(不計入)於字符)

對於第7個字符串 property後的表示
的第一個字節是 :0x08 (前面的Path是指令11 Path(也就是post)也 是指令 11 ,所以delta=11-11=0)
後面的8個字節是: 70 72 6F 70 65 72 74 79 ("property"的16進制,注:斜槓不屬(不計入)於字符)

對於第8個字符串 post後的表示
的第一個字節是 :0x04 (前面的Path是指令11 Path(也就是post)也 是指令 11 ,所以delta=11-11=0)
後面的4個字節是: 70 6F 73 74 ("post"的16進制,注:斜槓不屬(不計入)於字符)

接下來是:
Content-Format: application/json or application/cbor
(前面的POST是指令1 Content-Format是指令 12 ,所以delta=12-11=1)
所以: 0001 ????(application/json or application/cbor在CoAP中有對應的指令爲,所以這裏????=0001 ,因爲50的十六進制是0x32,也就是後面的長度是1)
總的第一個字節就是 : 0x11
後面的1個字節是: 0x32

Accept: application/json or application/cbor
(前面的Content-Format是指令12 Accept是指令 17 ,所以delta=17-12=5)
所以: 0101 ????(application/json or application/cbor在CoAP中有對應的指令爲,所以這裏????=0001 ,因爲50的十六進制是0x32,也就是後面的長度是1)
總的第一個字節就是 : 0x51
後面的1個字節是: 0x32

最後是:
CustomOptions: number:2088(標識token), 2089(seq)
(前面的Accep是指令17 CustomOptions(阿里雲定義的)是指令 2088 ,所以delta=2088-17=2071)
所以: 1110 ????(0xE?,這裏的0xD? 中的D是14,所以需要兩個字節來表示指令的增量,所以後面兩個字節的=2088-17-14-255==0x07 0x0A)
在這後面還跟了設備認證後下發的字符串(token字符串),一共31個字節,所以前面的0XE?中的 ?是D,後面接了31個token認證的字符串 是31-13=18,也就是0x12)
0x?? 。。。(31個)

總的就是: 0xDE 0X07 0X0A 0x12
0x?? …("hUJL2bcEHxkPvRwKR5Pq000100.3a2d"31個字符的16進制)

CustomOptions: number:2088(標識token), 2089(seq)
(前面 的CustomOptions(阿里雲定義的)是指令 2088 CustomOptions(阿里雲定義的)是指令 2089(seq),所以delta=2089-2088=1)
所以: 0001 1101(0x1D,注:後面seq加密後字符串長度是固定的16個,所以後面還需要一個字節來表示長度16-13=3 )
即:0x03
最後 : 0x??(一共16個)

這樣options的參數就全部完成了,接下來則還剩下分隔符和payload的數據了

分隔符 :(隔離)
0xff

payload:{“productKey”:“a125zR8hwQq”,“deviceName”:“ff1a11e7c08d4b3db2b1500d8e0e55”,“clientId”:“a125zR8hwQq&ff1a11e7c08d4b3db2b1500d8e0e55”,“sign”:“F9FD53EE0CD010FCA40D14A9FE******”, “seq”:“10”} (調試發送時,變成16進制便於發送)

這樣就完成了數據上報了
三元組
{
“ProductKey”: “a1P71zSMssS”,
“DeviceName”: “D001”,
“DeviceSecret”: “gWRyTGu2gmgUuylSwT0Z53IA8fWqsRSE”
}
{ “random”:“8894acb651b09d67”,“seq0ffest”:“2”,“token”:“hUJL2bcEHxkPvRwKR5Pq000100.3a2d”}

最後:對於
2089(AES加密項)
1)構建明文: DeviceSecret,+第一步認證時返回的random字符串
eg: gWRyTGu2gmgUuylSwT0Z53IA8fWqsRSE,8894acb651b09d67
2) 對 明文進行 SHA256編碼,得到的結果時32個字節(字符),去掉前面8個,去掉後面8個,保留中間的16個。
4c 70 8a 88 9e 62 0b 60 (捨去)
98 ab dc 1f 61 5a bc 11 a6 62 49 18 3d 4a 18 (實際用的密鑰)
6b ad a0 21 60 bc b7 1c (捨去)
3)進行AES加密,加密的初始向量是 : 35343379686A79393761653766796667

明文: 33(和seq0ffest中獲取的值要不一致,且要比該數字要大)
4)使用AES加密工具得到AES的結果放置在2089報文的後面

5)Payload 的數據也要作爲明文進行加密後放到0xff(分隔符)後面

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章