zoukankan      html  css  js  c++  java
  • MQTT详解以及在IoT中的应用

    MQTT定义:

    MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和制动器的通信协议。

    MQTT简介:

    MQTT是基于客户端/服务器的二进制的发布、订阅编程模式的消息协议,由于规范简单,非常适用于带宽低,低功耗的iot场景,比如:遥感、M2M、智慧城市、智能家居、医疗医护等。由于物联网的环境非常的特别,所以MQTT有他的设计规范:

    • 精简,不添加可有可无的功能
    • 发布、订阅模式,方便消息在传感器之间传递
    • 允许用户动态创建主题,零运维成本
    • 把传输量降到最低提高传输效率
    • 考虑地带宽、高延迟、不稳定的网络因素
    • 充分理解客户端羸弱的计算能力
    • 支持连续会话
    • 提供服务质量管理。(Qos:至少一次、至多一次、只有一次)
    • 假设数据不可知,不强求数据的类型和格式,保持灵活性

    mqtt发布订阅模式:

    和传统的http的请求/应答模式不一样(request/response),发布订阅模式解耦了发布者和订阅者之间的关系,这意味着发布者和订阅者不需要直接联系,由代理进行转发,什么意思呢?打个比方你打电话给你的女朋友翟小树,需要等翟小树接听电话之后你们才可以交流,这个就是http的请求响应模式,试想你是一个大明星,胡大橙和翟小树都关注了你的微博,当你发布一条微博的时候,微博服务器就是转发给他们两个的好友动态,此时你就是发布者(publisher),他们就是订阅者(subscribe),就这事典型的异步发布订阅模式。发布订阅模式带来了一些好处:

    • 发布者和订阅者不必彼此了解,多个订阅者之间也不需要彼此了解,只需要认识同一个消息代理
    • 发布者和订阅者不需要同时在线
    • 发布者和订阅者不需要进行任何的交互

    为了满足不同的场景,mqtt支持三种不同的服务质量(Qos)

    • 最多一次 (基于tcp/ip,发布者会想尽办法发布,但是遇到意外不会重试,使用场景比如传感器上报数据某次丢失但是过几秒就会另一次上报,对数据的要求不是那么的精确就可以设置这种)
    • 至少一次 (如果订阅者没有收到,发布者会重复的发送,确保消息达到,但是这种会存在一种问题就是重复的接收消息)
    • 只有一次(缺点是减少了并发或者增加了延时,但是如果消息重复或者丢失都不可接收的时候,这种最合适)。

    MQTT协议原理:

    实现mqtt协议需要客户端和服务端,这个流程有三个角色,发布者(publish)、订阅者(subscribe)、代理,其中发布者可以是某个topic的发布者,也可以是另一个topic的订阅者。

    mqtt的消息分为两个部分:主题(topic)、负载(payload)。

    • topic:消息的类型,订阅者订阅了该消息之后就会收到代理转发的消息。
    • payload:消息的内容。

    MQTT客户端:

    • 发布订阅者可能订阅的消息
    • 订阅其他客户端可能发布的消息
    • 退订或删除应用程序的消息
    • 断开与服务器的连接

    MQTT服务端:

    • 接收来自客户端的连接
    • 接收客户端发布的消息
    • 转发订阅对应topic的消息给订阅者
    • 处理来自客户端的订阅和退订请求

    MQTT协议中的一些方法:

    • connect:与服务端进行连接

    • disconnect 等客户端完成所有工作后断开与服务器的tcp/ip连接 

    • publish 客户端发布消息

    • subscribe 客户端订阅主题(异步过程)

    • unsubscribe 等待服务器取消客户端的一个或多个订阅的topic(异步过程)

    MQTT在IoT中的实践

    这是一张典型的MQTT在IoT中的应用,其中app作为客户端,智能网关也作为客户端(实际上在我们公司的V6云平台也是作为客户端),物联网云服务作为统一的服务端负责收发,app和V6云订阅同一个主题,app和网关订阅另一个主题,当每次需要发送mqtt命令时首先判断是账号登录(V6云)还是网关登录,于此publish对应的topic和payload,物联网云服务收到mqtt消息后转发给订阅同一个topic主题的客户端(V6云或者网关),然后通过再由网关发送对应的指令去控制低功耗设备(比如门锁的开关,灯泡的开关)。这个时候可以看出topic的重要性,合理的定义topic可以实现不同业务功能。先说一下我们公司的topic的定义,由于初期没有考虑周到,只是针对V6云和网关定义了两个不同的topic,导致后面有一项业务功能是给分享的账号发一些mqtt消息时导致V6云需要做大量的过滤,完全没有体现出topic的优势,接下来先讲一下topic主题设计。

    Topic主题设计

    主题层级分隔符:“/”   主题层级分隔符是的主题十分结构化

    • china/jiangsu/nanjing
    • shanghuang/xiadayu
    • shanghuang/huxiangli/81hao

    多层通配符:"#’  是用于匹配主题中任意层级的通配符。多层通配符表示它的父级和任意数量的子层级。多层通配符必须位于它自己的层级或者跟在主题层级分隔符后面。不管哪种情况,它都必须是主题过滤器的最后一个字符 .比如你订阅了一个jiangsu/nanjing/*,你会收到如下的主题的消息

    • jiangsu/nanjing
    • jiangsu/nanjing/jiangning
    • jiangsu/nanjing/qixia/nanjingdaxue

    定阅主题示例

    • jiangsu/#                 //也单独匹配“江苏”,因为#包括他的父级。
    • #                             //有效,会收到所有的topic的消息
    • jiangsu/nanjing/*    //有效
    • jiangsu/nanjing*     //无效
    • jiangsu/#/nanjing   //无效,必须是主题过滤器的最后一个字符

    单层通配符 “+”  只能用于单个层级匹配的通配符,在主题过滤器的任意层级都可以使用单层通配符,包括第一个和最后一个层级。然而它必须占据过滤器的整个层级 。可以在主题过滤器中的多个层级中使用它,也可以和多层通配符起使用。举个栗子:

    • china/+ 只能匹配china/jiangsu
    • china/+/+/zhaixiaoshu  可以匹配 china/xianlin/nanda/zhaixiaoshu 或者china/shanghuang/xiadayu/zhaixiaoshu

    总结一下

    • 所有的主题名和主题过滤器必须至少包含一个字符
    • 主题名或主题过滤器以前置或后置斜杠 “/” 区分
    • 只包含斜杠 “/” 的主题名或主题过滤器是合法的
    • 主题名和主题过滤器是 UTF-8 编码字符串, 它们不能超过 65535 字节
    • 主题名和主题过滤器是区分大小写的

    从上可以看出合理的topic订阅能够实现花样的功能,就比如当初设计分享的用户的时候完全可以用通配符去设计,可以大大的减小计算和筛选量。

  • 相关阅读:
    5-1 Leetcode中和链表相关的问题
    4-7 带有尾指针的链表:使用链表实现队列
    4.6 使用链表实现栈
    4.5 链表元素的删除
    4.4 链表的遍历、查询和修改
    4.3 为链表设置虚拟头结点dummyhead
    4.2在链表中添加元素
    4.1链表
    mybatis 力量操作参数为List的非空校验
    linux 运行和停止jar的shell 脚本
  • 原文地址:https://www.cnblogs.com/hxchaoshuai/p/9044632.html
Copyright © 2011-2022 走看看