最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

springboot+rabbitmq實現(xiàn)智能家居實例詳解

 更新時間:2022年07月23日 09:38:59   作者:程序員小富  
這篇文章主要為大家介紹了springboot+rabbitmq實現(xiàn)智能家居的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

前一段有幸參與到一個智能家居項目的開發(fā),由于之前都沒有過這方面的開發(fā)經驗,所以對智能硬件的開發(fā)模式和技術棧都頗為好奇。

智能可燃氣體報警器

產品是一款可燃氣體報警器,如果家中燃氣泄露濃度到達一定閾值,報警器檢測到并上傳氣體濃度值給后臺,后臺以電話、短信、微信等方式,提醒用戶家中可能有氣體泄漏。

用戶還可能向報警器發(fā)一些關閉報警、調整音量的指令等。整體功能還是比較簡單的,大致的邏輯如下圖所示:

但當我真正的參與其中開發(fā)時,其實有一點小小的失望,因為在整個研發(fā)過程中,并沒用到什么新的技術,還是常規(guī)的幾種中間件,只不過換個用法而已。

技術選型用rabbitmq 來做核心的組件,主要考慮到運維成本低,組內成員使用的熟練度比較高。

下面和小伙伴分享一下如何用 springboot + rabbitmq 搭建物聯(lián)網(wǎng)(IOT)平臺,其實智能硬件也沒想象的那么高不可攀!

很多小伙伴可能有點懵?rabbitmq 不是消息隊列嗎?怎么又能做智能硬件了

其實rabbitmq有兩種協(xié)議,我們平時接觸的消息隊列是用的AMQP協(xié)議,而用在智能硬件中的是MQTT協(xié)議。

一、什么是 MQTT協(xié)議?

MQTT 全稱(Message Queue Telemetry Transport):一種基于發(fā)布/訂閱(publish/subscribe)模式的輕量級通訊協(xié)議,通過訂閱相應的主題來獲取消息,是物聯(lián)網(wǎng)(Internet of Thing)中的一個標準傳輸協(xié)議。

該協(xié)議將消息的發(fā)布者(publisher)與訂閱者(subscriber)進行分離,因此可以在不可靠的網(wǎng)絡環(huán)境中,為遠程連接的設備提供可靠的消息服務,使用方式與傳統(tǒng)的MQ有點類似。

TCP協(xié)議位于傳輸層,MQTT 協(xié)議位于應用層,MQTT 協(xié)議構建于TCP/IP協(xié)議上,也就是說只要支持TCP/IP協(xié)議棧的地方,都可以使用MQTT協(xié)議。

二、為什么要用 MQTT協(xié)議?

MQTT協(xié)議為什么在物聯(lián)網(wǎng)(IOT)中如此受偏愛?而不是其它協(xié)議,比如我們更為熟悉的 HTTP協(xié)議呢?

  • 首先HTTP協(xié)議它是一種同步協(xié)議,客戶端請求后需要等待服務器的響應。而在物聯(lián)網(wǎng)(IOT)環(huán)境中,設備會很受制于環(huán)境的影響,比如帶寬低、網(wǎng)絡延遲高、網(wǎng)絡通信不穩(wěn)定等,顯然異步消息協(xié)議更為適合IOT應用程序。
  • HTTP是單向的,如果要獲取消息客戶端必須發(fā)起連接,而在物聯(lián)網(wǎng)(IOT)應用程序中,設備或傳感器往往都是客戶端,這意味著它們無法被動地接收來自網(wǎng)絡的命令。
  • 通常需要將一條命令或者消息,發(fā)送到網(wǎng)絡上的所有設備上。HTTP要實現(xiàn)這樣的功能不但很困難,而且成本極高。

三、MQTT協(xié)議介紹

前邊說過MQTT是一種輕量級的協(xié)議,它只專注于發(fā)消息, 所以此協(xié)議的結構也非常簡單。

MQTT數(shù)據(jù)包

MQTT協(xié)議中,一個MQTT數(shù)據(jù)包由:固定頭(Fixed header)、 可變頭(Variable header)、 消息體(payload)三部分構成。

  • 固定頭(Fixed header),所有數(shù)據(jù)包中都有固定頭,包含數(shù)據(jù)包類型及數(shù)據(jù)包的分組標識。
  • 可變頭(Variable header),部分數(shù)據(jù)包類型中有可變頭。
  • 內容消息體(Payload),存在于部分數(shù)據(jù)包類,是客戶端收到的具體消息內容。

在這里插入圖片描述

1、固定頭

固定頭部,使用兩個字節(jié),共16位:

(4-7)位表示消息類型,使用4位二進制表示,可代表如下的16種消息類型,不過 0 和 15位置屬于保留待用,所以共14種消息事件類型。

DUP Flag(重試標識)

DUP Flag:保證消息可靠傳輸,消息是否已送達的標識。默認為0,只占用一個字節(jié),表示第一次發(fā)送,當值為1時,表示當前消息先前已經被傳送過。

QoS Level(消息質量等級)

QoS Level:消息的質量等級,后邊會詳細介紹

RETAIN(持久化)

  • 值為1:表示發(fā)送的消息需要一直持久保存,而且不受服務器重啟影響,不但要發(fā)送給當前的訂閱者,且以后新加入的客戶端訂閱了此Topic,訂閱者也會馬上得到推送。注意:新加入的訂閱者,只會取出最新的一個RETAIN flag = 1的消息推送。
  • 值為0:僅為當前訂閱者推送此消息。

Remaining Length(剩余長度)

在當前消息中剩余的byte(字節(jié))數(shù),包含可變頭部和消息體payload。

2、可變頭

固定頭部僅定義了消息類型和一些標志位,一些消息的元數(shù)據(jù)需要放入可變頭部中??勺冾^部內容字節(jié)長度 + 消息體payload = 剩余長度。

可變頭部居于固定頭部和payload中間,包含了協(xié)議名稱,版本號,連接標志,用戶授權,心跳時間等內容。

可變頭存在于這些類型的消息:PUBLISH (QoS > 0)、PUBACK、PUBREC、PUBREL、PUBCOMP、SUBSCRIBE、SUBACK、UNSUBSCRIBE、UNSUBACK。

3、消息體payload

消息體payload只存在于CONNECT、PUBLISH、SUBSCRIBE、SUBACKUNSUBSCRIBE這幾種類型的消息:

  • CONNECT:包含客戶端的ClientId、訂閱的Topic、Message以及用戶名密碼。
  • PUBLISH:向對應主題發(fā)送消息。
  • SUBSCRIBE:要訂閱的主題以及QoS。
  • SUBACK:服務器對于SUBSCRIBE所申請的主題及QoS進行確認和回復。
  • UNSUBSCRIBE:取消要訂閱的主題。

消息質量(QoS )

消息質量(Quality of Service),即消息的發(fā)送質量,發(fā)布者(publisher)和訂閱者(subscriber)都可以指定qos等級,有QoS 0、QoS 1、QoS 2三個等級。

下邊分別說明一下這三個等級的區(qū)別。

1、Qos 0

Qos 0:At most once(至多一次)只發(fā)送一次消息,不保證消息是否成功送達,沒有確認機制,消息可能會丟失或重復。

圖片源于網(wǎng)絡,如有侵權聯(lián)系刪除

2、Qos 1

Qos 1:At least once(至少一次),相對于QoS 0而言Qos 1增加了ack確認機制,發(fā)送者(publisher)推送消息到MQTT代理(broker)時,兩者自身都會先持久化消息,只有當publisher 或者 Broker分別收到 PUBACK確認時,才會刪除自身持久化的消息,否則就會重發(fā)。

但有個問題,盡管我們可以通過確認來保證一定收到客戶端 或 服務器的message,可我們卻不能保證僅收到一次message,也就是當客戶端publisher沒收到Brokerpuback或者 Broker沒有收到subscriberpuback,那么就會一直重發(fā)。

publisher -> broker 大致流程:

publisher store msg -> publish ->broker (傳遞message)

broker -> puback -> publisher delete msg (確認傳遞成功)

圖片源于網(wǎng)絡,如有侵權聯(lián)系刪除

3、Qos 2

Qos 2:Exactly once(只有一次),相對于QoS 1,QoS 2升級實現(xiàn)了僅接受一次message,publisher 和 broker 同樣對消息進行持久化,其中 publisher 緩存了message和 對應的msgID,而 broker 緩存了 msgID,可以保證消息不重復,由于又增加了一個confirm 機制,整個流程變得復雜很多。

publisher -> broker 大致流程:

publisher store msg -> publish ->broker -> broker store

msgID(傳遞message) broker -> puberc (確認傳遞成功)

publisher -> pubrel ->broker delete msgID (告訴broker刪除msgID)

broker -> pubcomp -> publisher delete msg (告訴publisher刪除msg)

LWT(最后遺囑)

LWT 全稱為 Last Will and Testament,其實遺囑是一個由客戶端預先定義好的主題和對應消息,附加在CONNECT的數(shù)據(jù)包中,包括遺愿主題遺愿 QoS、遺愿消息等。

當MQTT代理 Broker 檢測到有客戶端client非正常斷開連接時,再由服務器主動發(fā)布此消息,然后相關的訂閱者會收到消息。

舉個栗子:聊天室中所有人都訂閱一個叫talk的主題 ,但小富由于網(wǎng)絡抖動突然斷開了鏈接,這時聊天室中所有訂閱主題 talk的客戶端都會收到一個 “小富離開聊天室” 的遺愿消息。

遺囑的相關參數(shù):

Will Flag:是否使用 LWT,1 開啟

Will Topic:遺愿主題名,不可使用通配符

Will Qos:發(fā)布遺愿消息時使用的 QoS

Will Retain:遺愿消息的 Retain 標識

Will Message:遺愿消息內容

那客戶端Client 有哪些場景是非正常斷開連接呢?

  • Broker 檢測到底層的 I/O 異常;
  • 客戶端 未能在心跳 Keep Alive 的間隔內和 Broker 進行消息交互;
  • 客戶端 在關閉底層 TCP 連接前沒有發(fā)送 DISCONNECT 數(shù)據(jù)包;
  • 客戶端 發(fā)送錯誤格式的數(shù)據(jù)包到 Broker,導致關閉和客戶端的連接等。

注意:當客戶端通過發(fā)布 DISCONNECT 數(shù)據(jù)包斷開連接時,屬于正常斷開連接,并不會觸發(fā) LWT 的機制,與此同時Broker 還會丟棄掉當前客戶端在連接時指定的相關 LWT 參數(shù)。

四、MQTT協(xié)議應用場景

MQTT協(xié)議廣泛應用于物聯(lián)網(wǎng)、移動互聯(lián)網(wǎng)、智能硬件、車聯(lián)網(wǎng)、電力能源等領域。使用的場景也是非常非常多,下邊列舉一些:

  • 物聯(lián)網(wǎng)M2M通信,物聯(lián)網(wǎng)大數(shù)據(jù)采集
  • Android消息推送,WEB消息推送
  • 移動即時消息,例如Facebook Messenger
  • 智能硬件、智能家具、智能電器
  • 車聯(lián)網(wǎng)通信,電動車站樁采集
  • 智慧城市、遠程醫(yī)療、遠程教育
  • 電力、石油與能源等行業(yè)市場

五、代碼實現(xiàn)

具體 rabbitmq 的環(huán)境搭建就不贅述了,網(wǎng)上教程比較多,有條件的用服務器,沒條件的像我搞個Windows版的也很快樂嘛。

在這里插入圖片描述

1、啟用 rabbitmq的mqtt協(xié)議

我們先開啟 rabbitmq 的 mqtt協(xié)議,因為默認安裝下是關閉的,命令如下:

rabbitmq-plugins?enable?rabbitmq_mqtt

2、mqtt 客戶端依賴包

上一步中安裝rabbitmq環(huán)境并開啟 mqtt協(xié)議后,實際上mqtt 消息代理服務就搭建好了,接下來要做的就是實現(xiàn)客戶端消息的推送和訂閱。

這里使用spring-integration-mqtt、org.eclipse.paho.client.mqttv3兩個工具包實現(xiàn)。

<!--mqtt依賴包-->
<dependency>
????<groupId>org.springframework.integration</groupId>
????<artifactId>spring-integration-mqtt</artifactId>
</dependency>
<dependency>
????<groupId>org.eclipse.paho</groupId>
???????<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
????<version>1.2.0</version>
</dependency>

3、消息發(fā)送者

消息的發(fā)送比較簡單,主要是應用到@ServiceActivator注解,需要注意messageHandler.setAsync屬性,如果設置成false,關閉異步模式發(fā)送消息時可能會阻塞。

@Configuration
public?class?IotMqttProducerConfig?{

????@Autowired
????private?MqttConfig?mqttConfig;

????@Bean
????public?MqttPahoClientFactory?mqttClientFactory()?{
????????DefaultMqttPahoClientFactory?factory?=?new?DefaultMqttPahoClientFactory();
????????factory.setServerURIs(mqttConfig.getServers());
????????return?factory;
????}

????@Bean
????public?MessageChannel?mqttOutboundChannel()?{
????????return?new?DirectChannel();
????}

????@Bean
????@ServiceActivator(inputChannel?=?"iotMqttInputChannel")
????public?MessageHandler?mqttOutbound()?{
????????MqttPahoMessageHandler?messageHandler?=?new?MqttPahoMessageHandler(mqttConfig.getServerClientId(),?mqttClientFactory());
????????messageHandler.setAsync(false);
????????messageHandler.setDefaultTopic(mqttConfig.getDefaultTopic());
????????return?messageHandler;
????}
}

MQTT 對外提供發(fā)送消息的API時,需要使用@MessagingGateway 注解,去提供一個消息網(wǎng)關代理,參數(shù)defaultRequestChannel 指定發(fā)送消息綁定的channel。

可以實現(xiàn)三種API接口,payload 為發(fā)送的消息,topic 發(fā)送消息的主題,qos 消息質量。

@MessagingGateway(defaultRequestChannel?=?"iotMqttInputChannel")
public?interface?IotMqttGateway?{

????//?向默認的?topic?發(fā)送消息
????void?sendMessage2Mqtt(String?payload);
????//?向指定的?topic?發(fā)送消息
????void?sendMessage2Mqtt(String?payload,@Header(MqttHeaders.TOPIC)?String?topic);
????//?向指定的?topic?發(fā)送消息,并指定服務質量參數(shù)
????void?sendMessage2Mqtt(@Header(MqttHeaders.TOPIC)?String?topic,?@Header(MqttHeaders.QOS)?int?qos,?String?payload);
}

4、消息訂閱

消息訂閱和我們平時用的MQ消息監(jiān)聽實現(xiàn)思路基本相似,@ServiceActivator注解表明當前方法用于處理MQTT消息,inputChannel 參數(shù)指定了用于接收消息的channel。

/**
?*?@Author:?xiaofu
?*?@Description:?消息訂閱配置
?*?@date?2020/6/8?18:24
?*/
@Configuration
public?class?IotMqttSubscriberConfig?{

????@Autowired
????private?MqttConfig?mqttConfig;

????@Bean
????public?MqttPahoClientFactory?mqttClientFactory()?{
????????DefaultMqttPahoClientFactory?factory?=?new?DefaultMqttPahoClientFactory();
????????factory.setServerURIs(mqttConfig.getServers());
????????return?factory;
????}

????@Bean
????public?MessageChannel?iotMqttInputChannel()?{
????????return?new?DirectChannel();
????}

????@Bean
????public?MessageProducer?inbound()?{
????????MqttPahoMessageDrivenChannelAdapter?adapter?=?new?MqttPahoMessageDrivenChannelAdapter(mqttConfig.getClientId(),?mqttClientFactory(),?mqttConfig.getDefaultTopic());
????????adapter.setCompletionTimeout(5000);
????????adapter.setConverter(new?DefaultPahoMessageConverter());
????????adapter.setQos(1);
????????adapter.setOutputChannel(iotMqttInputChannel());
????????return?adapter;
????}

????/**
?????*?@author?xiaofu
?????*?@description?消息訂閱
?????*?@date?2020/6/8?18:20
?????*/
????@Bean
????@ServiceActivator(inputChannel?=?"iotMqttInputChannel")
????public?MessageHandler?handlerTest()?{

????????return?message?->?{
????????????try?{
????????????????String?string?=?message.getPayload().toString();
????????????????System.out.println("接收到消息:"?+?string);
????????????}?catch?(MessagingException?ex)?{
????????????????//logger.info(ex.getMessage());
????????????}
????????};
????}
}

六、測試消息

額~ 由于本渣渣對硬件一竅不通,為了模擬硬件的發(fā)送消息,只能借助一下工具,其實硬件端實現(xiàn)MQTT協(xié)議,跟我們前邊的基本沒什么區(qū)別,只不過換種語言嵌入到硬件中而已。

這里選的測試工具為mqttbox,下載地址:http://workswithweb.com/mqttbox.html

1、測試消息發(fā)送

我們用先用mqttbox模擬向主題mqtt_test_topic發(fā)送消息,看后臺是否能成功接收到。

看到后臺成功拿到了向主題mqtt_test_topic發(fā)送的消息。

2、測試消息訂閱

mqttbox模擬訂閱主題mqtt_test_topic,在后臺向主題mqtt_test_topic發(fā)送一條消息,這里我簡單的寫了個controller調用API發(fā)送消息。

http://127.0.0.1:8080/fun/testMqtt?topic=mqtt_test_topic&message=我是后臺向主題 mqtt_test_topic 發(fā)送的消息

我們看mqttbox的訂閱消息,已經成功的接收到了后臺的消息,到此我們的MQTT通信環(huán)境就算搭建成功了。如果把mqttbox工具換成具體硬件設備,整個流程就是我們常說的智能家居了,其實真的沒那么難。

七、應用注意事項

在我們實際的生產環(huán)境中遇到過的問題,這里分享一下讓大家少踩坑。

clientId 要唯一

在客戶端connect連接的時,會有一個clientId 參數(shù),需要每個客戶端都保持唯一的。但我們在開發(fā)測試階段clientId直接在代碼中寫死了,而且服務都是單實例部署,并沒有暴露出什么問題。

MqttPahoMessageDrivenChannelAdapter(mqttConfig.getClientId(),?mqttClientFactory(),?mqttConfig.getDefaultTopic());

然而在生產環(huán)境內側的時候,由于服務是多實例集群部署,結果出現(xiàn)了下邊的奇怪問題。同一時間內只能有一個客戶端能拿到消息,其他客戶端不但不能消費消息,而且還在不斷的掉線重連:Lost connection: 已斷開連接; retrying...。

這就是由于clientId相同導致客戶端間相互競爭消費,最后將clientId獲取方式換成從發(fā)號器中拿,問題就好了,所以這個地方是需要特別注意的。

平時程序在開發(fā)環(huán)境沒問題,可偏偏到了生產環(huán)境就一大堆問題,很多都是因為服務部署方式不同導致的。所以多學習分布式還是很有必要的。

八、其他中間件

MQTT它只是一種協(xié)議,支持MQTT協(xié)議的消息中間件產品非常多,下邊的也只是其中的一部分

  • Mosquitto
  • Eclipse Paho
  • RabbitMQ
  • Apache ActiveMQ
  • HiveMQ
  • JoramMQ
  • ThingMQ
  • VerneMQ
  • Apache Apollo
  • emqttd Xively
  • IBM Websphere .....

總結

我也是第一次做和硬件相關的項目,之前聽到智能家居都會覺得好高大上,但實際上手開發(fā)后發(fā)現(xiàn),技術嘛萬變不離其宗,也只是換種用法而已。

以上就是springboot+rabbitmq實現(xiàn)智能家居實例詳解的詳細內容,更多關于springboot rabbitmq智能家居的資料請關注腳本之家其它相關文章!

相關文章

  • Java 如何調用long的最大值和最小值

    Java 如何調用long的最大值和最小值

    這篇文章主要介紹了Java 如何調用long的最大值和最小值的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • java實現(xiàn)簡單網(wǎng)絡象棋游戲

    java實現(xiàn)簡單網(wǎng)絡象棋游戲

    這篇文章主要為大家詳細介紹了java實現(xiàn)簡單網(wǎng)絡象棋游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Java線程池?ThreadPoolExecutor?詳解

    Java線程池?ThreadPoolExecutor?詳解

    這篇文章主要介紹了Java線程池?ThreadPoolExecutor,線程池包括線程集合、阻塞隊列、拒絕策略處理器,更多相關內容需要的朋友可以參考一下
    2022-07-07
  • java處理日期的工具類DateUtil

    java處理日期的工具類DateUtil

    這篇文章主要為大家詳細介紹了java處理日期的工具類DateUtil,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • 你所不知道的Spring自動注入詳解

    你所不知道的Spring自動注入詳解

    這篇文章主要給大家介紹了關于你所不知道的Spring自動注入的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • jdk源碼閱讀Collection詳解

    jdk源碼閱讀Collection詳解

    這篇文章主要介紹了jdk源碼閱讀Collection詳解,具有一定借鑒價值,需要的朋友可以參考下
    2017-12-12
  • Java編程中的equals方法使用全解

    Java編程中的equals方法使用全解

    這篇文章主要介紹了Java編程中的equals方法使用全解,是Java入門學習中的基礎知識,需要的朋友可以參考下
    2015-10-10
  • Mybatis-Plus將字段設置為null解決方法

    Mybatis-Plus將字段設置為null解決方法

    MyBatis-Plus是一個MyBatis的增強工具,在MyBatis的基礎上只做增 強不做改變,為簡化開發(fā)、提高效率而生,下面這篇文章主要給大家介紹了關于Mybatis-Plus將字段設置為null的解決方法的相關資料,需要的朋友可以參考下
    2023-04-04
  • @PropertySource 無法讀取配置文件的屬性值解決方案

    @PropertySource 無法讀取配置文件的屬性值解決方案

    這篇文章主要介紹了@PropertySource 無法讀取配置文件的屬性值解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 如何通過SpringBoot實現(xiàn)商城秒殺系統(tǒng)

    如何通過SpringBoot實現(xiàn)商城秒殺系統(tǒng)

    這篇文章主要介紹了如何通過SpringBoot實現(xiàn)商城秒殺系統(tǒng),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11

最新評論

定兴县| 嘉黎县| 邛崃市| 莆田市| 巴里| 新龙县| 璧山县| 大渡口区| 诏安县| 六枝特区| 喀什市| 会同县| 三穗县| 南漳县| 吉林市| 错那县| 内黄县| 弥渡县| 潜山县| 手游| 广平县| 五指山市| 南开区| 墨江| 星子县| 九龙县| 阿合奇县| 吉木萨尔县| 兴海县| 运城市| 阳西县| 凉城县| 江山市| 红安县| 乌兰浩特市| 桂东县| 娱乐| 江城| 饶平县| 大埔区| 肇东市|