一、項目功能介紹
當前基于MQTT協(xié)議設(shè)計了一個實時圖傳系統(tǒng),通過這個項目來演示,兩個MQTT設(shè)備如何互相訂閱,進行消息流轉(zhuǎn)。 在阿里云服務(wù)器上創(chuàng)建2個設(shè)備,分為為設(shè)備A和設(shè)備B;設(shè)備A負責采集本地攝像頭畫面上傳,設(shè)備B負責接收設(shè)備A上傳的數(shù)據(jù)然后解析顯示出來。在阿里云服務(wù)器上需要配置云產(chǎn)品流轉(zhuǎn),讓設(shè)備A的數(shù)據(jù)上傳后自動發(fā)送給設(shè)備B。這樣就完成了視頻畫面數(shù)據(jù)的流轉(zhuǎn)。不過因為阿里云的最大數(shù)據(jù)限制,每次最大發(fā)送10240字節(jié)的數(shù)據(jù)。
當前的項目是采用MQTT協(xié)議實現(xiàn),那么先來了解一下什么是MQTT協(xié)議。
軟件采用Qt設(shè)計,QT版本是5.12.6
設(shè)備A的功能:獲取攝像頭的數(shù)據(jù)---》縮放成240*320---》編碼成JPEG格式---》轉(zhuǎn)碼成base64---》組合成MQTT報文---》上傳到服務(wù)器。
設(shè)備B的功能:訂閱設(shè)備A上傳的數(shù)據(jù),得到數(shù)據(jù)后解析出源格式數(shù)據(jù)---》將圖像畫面渲染顯示出來。
軟件運行效果:
總結(jié)軟件運行的體驗效果:
(1) 非常流暢。兩個窗口肉眼感覺不到延遲。
(2)服務(wù)器不要錢。
這個方案驗證之后,可以衍生出很多實際的例子了: 比如, 單片機+攝像頭+MQTT協(xié)議 也可以做為圖傳發(fā)送端。 聯(lián)網(wǎng)可以使用:WIFI或者4G模塊、5G模塊。
1.1 MQTT協(xié)議
MQTT (Message Queuing Telemetry Transport)是一種輕量級的、基于發(fā)布/訂閱的消息傳輸協(xié)議,它可以在客戶端和服務(wù)器之間進行雙向通信。MQTT被設(shè)計為適用于低帶寬、不穩(wěn)定網(wǎng)絡(luò)連接的物聯(lián)網(wǎng)設(shè)備通信。
MQTT具有以下主要特點:
(1)發(fā)布/訂閱模型:客戶端可以選擇訂閱一個或多個主題(topic),并接收與這些主題相關(guān)的消息;同時,客戶端也可以發(fā)布消息到一個或多個主題上。
(2)輕量級:MQTT的協(xié)議頭非常小,最小只有2字節(jié),這使得它非常適合于傳輸數(shù)據(jù)量較小的IoT設(shè)備。
(3)QoS(服務(wù)質(zhì)量)支持:MQTT支持三種不同的QoS級別,分別是“至多一次”、“至少一次”和“恰好一次”,可以根據(jù)應(yīng)用場景的需要進行選擇。
(4)保留消息:MQTT服務(wù)器可以將最新的消息保留在主題中,并讓新的訂閱者能夠讀取先前發(fā)布的消息。
(5)遺囑消息:當客戶端與服務(wù)器連接異常斷開時,服務(wù)器可以向其他訂閱了該主題的客戶端發(fā)送遺囑消息,以實現(xiàn)更可靠的消息傳輸。
總之,MQTT是一種非常適合物聯(lián)網(wǎng)設(shè)備通信的協(xié)議,它具有輕量級、靈活性高、易于實現(xiàn)、可靠性強等優(yōu)點,已經(jīng)被廣泛地應(yīng)用于各種物聯(lián)網(wǎng)場景中。
1.2 MQTT協(xié)議載體
MQTT協(xié)議是基于TCP協(xié)議傳輸報文的。MQTT使用TCP/IP協(xié)議棧來實現(xiàn)通信,因此它具有TCP協(xié)議的一些特性,如可靠性、流控制和建立持久連接等特點。
在MQTT連接建立時,客戶端需要通過TCP連接到MQTT服務(wù)器,并進行握手協(xié)商,包括協(xié)議版本、客戶端標識符、遺囑消息、QoS級別等信息,以確保雙方能夠正確地交換數(shù)據(jù)。一旦握手成功,客戶端和服務(wù)器之間就建立了一個持久化的TCP連接,可以隨時進行消息傳輸。
由于TCP協(xié)議本身已經(jīng)提供了一定程度的可靠性保證,因此MQTT協(xié)議只需要在TCP的基礎(chǔ)上實現(xiàn)發(fā)布/訂閱機制、QoS級別控制、保留消息等特性即可,從而使得它成為一種輕量級且高效的物聯(lián)網(wǎng)通信協(xié)議。
1.3 JSON里如何保存圖片數(shù)據(jù)?
在JSON中保存圖片數(shù)據(jù)通常需要將圖片轉(zhuǎn)換為二進制數(shù)據(jù),并將其編碼成Base64字符串,然后將該字符串作為JSON對象的屬性值進行傳輸。
Base64編碼是一種將二進制數(shù)據(jù)轉(zhuǎn)換為ASCII字符的方法,它使用64個字符來表示任意序列的二進制數(shù)據(jù)。Base64編碼后的數(shù)據(jù)長度會比原始二進制數(shù)據(jù)略長,但可以方便地被轉(zhuǎn)換為文本格式并在網(wǎng)絡(luò)上進行傳輸。
以下是一個示例JSON對象,其中包含了一個Base64編碼后的圖片數(shù)據(jù):
{
"imageData": "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBD...",
"imageName": "my_image.png"
}
在這個示例中,imageData
屬性表示圖片數(shù)據(jù)的Base64編碼字符串,imageName
屬性表示圖片文件名。在接收到JSON對象后,可以通過解碼Base64字符串并將其保存為二進制數(shù)據(jù),再將其寫入磁盤或者顯示在應(yīng)用程序中。
需要注意的是,由于Base64編碼后的數(shù)據(jù)量相對較大,因此在實際應(yīng)用中,如果需要傳輸大量的圖片數(shù)據(jù),建議使用其他更適合的數(shù)據(jù)傳輸方式,如MQTT協(xié)議、WebSocket等。
1.4 MQTT協(xié)議最大能傳多少有效字節(jié)的數(shù)據(jù)?
MQTT協(xié)議本身沒有限制數(shù)據(jù)包的大小,但是它需要遵循底層傳輸協(xié)議(TCP/IP)的限制和約束。在實際應(yīng)用中,MQTT協(xié)議能夠傳輸?shù)挠行?shù)據(jù)量是受多種因素影響的,如網(wǎng)絡(luò)帶寬、QoS級別、MQTT消息頭部信息等。
一般來說,在默認情況下,MQTT協(xié)議對于單個消息的有效載荷有一個限制,即不超過256MB。這個限制主要由MQTT協(xié)議的消息長度字段決定,該字段的最大值是4字節(jié),因此最大能表示2^32-1個字節(jié)的消息長度,即約為4GB。然而,在實際應(yīng)用中,由于網(wǎng)絡(luò)帶寬和設(shè)備性能等方面的限制,很難實現(xiàn)傳輸如此巨大的消息。
另外,需要注意的是,如果使用較高級別的QoS,如“至少一次”或“恰好一次”,則MQTT協(xié)議會對每條消息進行確認和重傳,這可能會導(dǎo)致更多的網(wǎng)絡(luò)流量和延遲。因此,在選擇QoS級別時,需要根據(jù)應(yīng)用場景和網(wǎng)絡(luò)環(huán)境的實際情況進行優(yōu)化和調(diào)整,以充分利用MQTT協(xié)議的特點和優(yōu)勢。
三、阿里云服務(wù)器創(chuàng)建
官網(wǎng)地址: https://iot.console.aliyun.com/lk/summary/new
3.1 創(chuàng)建產(chǎn)品
3.2 添加設(shè)備
{
"ProductKey": "a12qAqNZg3i",
"DeviceName": "video_de1",
"DeviceSecret": "206a4bc03642930542a9bcb8925b9a0f"
}
創(chuàng)建完成。
3.3 創(chuàng)建自定義屬性
在產(chǎn)品頁面的,找到功能定義。
最大一次只能傳遞10KB。
3.4 MQTT服務(wù)器地址和端口
關(guān)于MQTT協(xié)議登錄所需要的參數(shù)官方說明文檔: https://help.aliyun.com/document_detail/140507.html?spm=a2c4g.11186623.6.571.1e417544OGPj2y
阿里云物聯(lián)網(wǎng)服務(wù)器的域名規(guī)則如下:
物聯(lián)網(wǎng)平臺的域名格式為:productKey.iot-as-mqtt.cn-shanghai.aliyuncs.com,其中productKey是您在物聯(lián)網(wǎng)平臺上創(chuàng)建的產(chǎn)品的標識符,cn-shanghai表示物聯(lián)網(wǎng)服務(wù)器所在的地區(qū)。
?
MQTT協(xié)議的域名格式為:productKey.iot-as-mqtt.cn-shanghai.aliyuncs.com,其中productKey是您在物聯(lián)網(wǎng)平臺上創(chuàng)建的產(chǎn)品的標識符,cn-shanghai表示物聯(lián)網(wǎng)服務(wù)器所在的地區(qū)。
?
HTTPS協(xié)議的域名格式為:productKey.iot-as-http.cn-shanghai.aliyuncs.com,其中productKey是您在物聯(lián)網(wǎng)平臺上創(chuàng)建的產(chǎn)品的標識符,cn-shanghai表示物聯(lián)網(wǎng)服務(wù)器所在的地區(qū)。
?
需要注意的是,以上的域名規(guī)則中,productKey需要替換成你在物聯(lián)網(wǎng)平臺上創(chuàng)建產(chǎn)品時生成的實際productKey。
下面是阿里云國內(nèi)的服務(wù)器地域和可用區(qū)詳情:
地域名稱 所在城市 Region ID 可用區(qū)數(shù)量
華北 1 青島 cn-qingdao 2
華北 2 北京 cn-beijing 10
華北 3 張家口 cn-zhangjiakou 3
華北 5 呼和浩特 cn-huhehaote 2
華北 6 烏蘭察布 cn-wulanchabu 3
華東 1 杭州 cn-hangzhou 8
華東 2 上海 cn-shanghai 8
華南 1 深圳 cn-shenzhen 6
華南 2 河源 cn-heyuan 2
華南 3 廣州 cn-guangzhou 2
西南 1 成都 cn-chengdu 2
?
端口號是:1883
?
我的設(shè)備參數(shù):
{
"ProductKey": "a12qAqNZg3i",
"DeviceName": "video_de1",
"DeviceSecret": "206a4bc03642930542a9bcb8925b9a0f"
}
?
經(jīng)過上面的格式解釋,我的阿里云服務(wù)器登錄的域名就是(選擇的是上海服務(wù)器):
a12qAqNZg3i.iot-as-mqtt.cn-shanghai.aliyuncs.com
?
解析域名對應(yīng)的IP地址:
Microsoft Windows [版本 10.0.19044.2604]
(c) Microsoft Corporation。保留所有權(quán)利。
?
C:Users11266>ping a12qAqNZg3i.iot-as-mqtt.cn-shanghai.aliyuncs.com
?
正在 Ping vpc-sh-prod.mqtt.iotgds.aliyuncs.com.gds.alibabadns.com [47.103.191.238] 具有 32 字節(jié)的數(shù)據(jù):
來自 47.103.191.238 的回復(fù): 字節(jié)=32 時間=40ms TTL=88
來自 47.103.191.238 的回復(fù): 字節(jié)=32 時間=40ms TTL=88
來自 47.103.191.238 的回復(fù): 字節(jié)=32 時間=40ms TTL=88
來自 47.103.191.238 的回復(fù): 字節(jié)=32 時間=40ms TTL=88
?
47.103.191.238 的 Ping 統(tǒng)計信息:
數(shù)據(jù)包: 已發(fā)送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計時間(以毫秒為單位):
最短 = 40ms,最長 = 40ms,平均 = 40ms
?
C:Users11266>
3.5 MQTT三元組格式
下載密碼生成小工具:https://help.aliyun.com/document_detail/292635.htm?spm=a2c4g.11186623.0.0.5aaf635b3zgveM#section-jx3-u57-pmm
打開密碼生成工具:
生成MQTT登錄的密匙: 填入的參數(shù)就是前面創(chuàng)建設(shè)備得到信息。
mqttClientId:
video_de1|securemode=2,signmethod=hmacsha1,timestamp=1678078910527|
?
username:
video_de1&a12qAqNZg3i
?
password:
02F7190BE8C33C1A8009EDBAF824BFDC6784FC67
?
3.6 主題發(fā)布與訂閱的格式
在產(chǎn)品頁面可以看到主題格式: https://iot.console.aliyun.com/product/productDetail/a1cMlEwEwjg/func?current=2
總結(jié):
發(fā)布主題:
/sys/a12qAqNZg3i/video_de1/thing/event/property/post
上報屬性消息的格式:
{"method":"thing.event.property.post","params":{"image":"1234567890"}}
?
訂閱主題:
/sys/a12qAqNZg3i/video_de1/thing/service/property/set
3.7 MQTT設(shè)備登錄
利用MQTT客戶端完成設(shè)備登錄測試。
IP地址:47.103.191.238
?
端口號:1883
?
mqttClientId: video_de1|securemode=2,signmethod=hmacsha1,timestamp=1678078910527|
?
username: video_de1&a12qAqNZg3i
?
password: 02F7190BE8C33C1A8009EDBAF824BFDC6784FC67
?
?
發(fā)布主題:
/sys/a12qAqNZg3i/video_de1/thing/event/property/post
上報屬性消息的格式:
{"method":"thing.event.property.post","params":{"image":"1234567890"}}
?
訂閱主題:
/sys/a12qAqNZg3i/video_de1/thing/service/property/set
對號入座填入?yún)?shù),測試主題訂閱,主題發(fā)布:
數(shù)據(jù)接收成功:
到此服務(wù)器創(chuàng)建成功。
3.8 繼續(xù)創(chuàng)建設(shè)備2
監(jiān)控設(shè)備有兩個,1個設(shè)備為攝像頭圖片發(fā)送端,一個設(shè)備是圖片接收顯示端。
{
"ProductKey": "a12qAqNZg3i",
"DeviceName": "video_dev2",
"DeviceSecret": "30ebb8ffc4316fbe957fcfb13bdaec01"
}
創(chuàng)建成功。
接下來生成設(shè)備2的MQTT三元組密匙,和前面一樣的方法。
mqttClientId:
video_dev2|securemode=2,signmethod=hmacsha1,timestamp=1678078910527|
username:
video_dev2&a12qAqNZg3i
password:
15D2C020586E165E6A35BB2FA4DEB9DD59F3E73E
參數(shù)總結(jié):
IP地址:47.103.191.238
端口號:1883
mqttClientId: video_dev2|securemode=2,signmethod=hmacsha1,timestamp=1678078910527|
username: video_dev2&a12qAqNZg3i
password: 15D2C020586E165E6A35BB2FA4DEB9DD59F3E73E
發(fā)布主題:
/sys/a12qAqNZg3i/video_dev2/thing/event/property/post
上報屬性消息的格式:
{"method":"thing.event.property.post","params":{"image":"abcdefg"}}
訂閱主題:
/sys/a12qAqNZg3i/video_dev2/thing/service/property/set
四、云產(chǎn)品流轉(zhuǎn)
4.1 創(chuàng)建解析器
創(chuàng)建完成。
4.2 創(chuàng)建規(guī)則
添加主題:
設(shè)置數(shù)據(jù)目的:
編寫解析器腳本:
幫助文檔地址:https://help.aliyun.com/document_detail/270937.html
下面編寫代碼,獲取設(shè)備1上傳的數(shù)據(jù),轉(zhuǎn)發(fā)給設(shè)備2。
//通過payload函數(shù),獲取設(shè)備上報的消息內(nèi)容,并按照JSON格式轉(zhuǎn)換。
var data = payload("json");
//直接流轉(zhuǎn)物模型上報數(shù)據(jù)。
writeIotTopic(1000, "/a12qAqNZg3i/video_dev2/user/get", data)
寫好解析器就發(fā)布。
在云產(chǎn)品流轉(zhuǎn)的首頁啟動解析器。
4.3 測試兩個設(shè)備的訂閱
設(shè)備1的參數(shù):
IP地址:47.103.191.238
端口號:1883
mqttClientId: video_de1|securemode=2,signmethod=hmacsha1,timestamp=1678078910527|
username: video_de1&a12qAqNZg3i
password: 02F7190BE8C33C1A8009EDBAF824BFDC6784FC67
設(shè)備1發(fā)布主題:
主題格式:/a12qAqNZg3i/video_de1/user/update
數(shù)據(jù)內(nèi)容:{"method":"thing.event.property.post","params":{"image":"1234567890"}}
設(shè)備2的參數(shù):
IP地址:47.103.191.238
端口號:1883
mqttClientId: video_dev2|securemode=2,signmethod=hmacsha1,timestamp=1678078910527|
username: video_dev2&a12qAqNZg3i
password: 15D2C020586E165E6A35BB2FA4DEB9DD59F3E73E
設(shè)備2訂閱主題:
主題格式:/a12qAqNZg3i/video_dev2/user/get
五、項目開發(fā)
5.1 base64編碼和解碼實現(xiàn)
攝像頭采集圖像數(shù)據(jù)之后會編碼 成base64格式的字符串,再通過MQTT協(xié)議上傳到物聯(lián)網(wǎng)服務(wù)器。 下面就是base64編碼和解碼的實現(xiàn)代碼。
const char * base64char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//進行base64編碼
//bindata:進行編碼的圖片數(shù)據(jù)
//base64:轉(zhuǎn)換后的base64編碼
//binlength:圖片大小
char * base64_encode( u8 * bindata, char * base64, u32 binlength )
{
u32 i, j;
u8 current;
for ( i = 0, j = 0 ; i < binlength ; i += 3 )
{
current = (bindata[i] >> 2) ;
current &= (u8)0x3F;
base64[j++] = base64char[(int)current];
current = ( (u8)(bindata[i] << 4 ) ) & ( (u8)0x30 ) ;
if ( i + 1 >= binlength )
{
base64[j++] = base64char[(int)current];
base64[j++] = '=';
base64[j++] = '=';
break;
}
current |= ( (u8)(bindata[i+1] >> 4) ) & ( (u8) 0x0F );
base64[j++] = base64char[(int)current];
current = ( (u8)(bindata[i+1] << 2) ) & ( (u8)0x3C ) ;
if ( i + 2 >= binlength )
{
base64[j++] = base64char[(int)current];
base64[j++] = '=';
break;
}
current |= ( (u8)(bindata[i+2] >> 6) ) & ( (u8) 0x03 );
base64[j++] = base64char[(int)current];
current = ( (u8)bindata[i+2] ) & ( (u8)0x3F ) ;
base64[j++] = base64char[(int)current];
}
base64[j] = '?';
return base64;
}
//解碼base64
//base64:base64編碼
//bindata:圖片數(shù)據(jù)
int base64_decode( const char * base64, u8 * bindata )
{
u32 i, j;
u8 k;
u8 temp[4];
for ( i = 0, j = 0; base64[i] != '?' ; i += 4 )
{
memset( temp, 0xFF, sizeof(temp) );
for ( k = 0 ; k < 64 ; k ++ )
{
if ( base64char[k] == base64[i] )
temp[0]= k;
}
for ( k = 0 ; k < 64 ; k ++ )
{
if ( base64char[k] == base64[i+1] )
temp[1]= k;
}
for ( k = 0 ; k < 64 ; k ++ )
{
if ( base64char[k] == base64[i+2] )
temp[2]= k;
}
for ( k = 0 ; k < 64 ; k ++ )
{
if ( base64char[k] == base64[i+3] )
temp[3]= k;
}
bindata[j++] = ((u8)(((u8)(temp[0] << 2))&0xFC)) |
((u8)((u8)(temp[1]>>4)&0x03));
if ( base64[i+2] == '=' )
break;
bindata[j++] = ((u8)(((u8)(temp[1] << 4))&0xF0)) |
((u8)((u8)(temp[2]>>2)&0x0F));
if ( base64[i+3] == '=' )
break;
bindata[j++] = ((u8)(((u8)(temp[2] << 6))&0xF0)) |
((u8)(temp[3]&0x3F));
}
return j;
}
5.3 軟件設(shè)計
5.4 運行效果
-
物聯(lián)網(wǎng)
+關(guān)注
關(guān)注
2909文章
44691瀏覽量
373836 -
服務(wù)器
+關(guān)注
關(guān)注
12文章
9191瀏覽量
85509 -
攝像頭
+關(guān)注
關(guān)注
60文章
4845瀏覽量
95780 -
阿里云
+關(guān)注
關(guān)注
3文章
957瀏覽量
43072 -
MQTT
+關(guān)注
關(guān)注
5文章
651瀏覽量
22531
發(fā)布評論請先 登錄
相關(guān)推薦
評論