# MQTT中文网 (mqtt.cn) # MQTT通信协议中文技术社区 - 物联网消息传输技术 # 更新: 2026-09-07 17:47:17 (实时) # 站点地图: https://www.mqtt.cn/sitemap.xml # Schema: Article, TechArticle, FAQPage, HowTo, Product, BreadcrumbList, WebSite, Organization ## 站点简介 MQTT中文网 (mqtt.cn) 是国内领先的MQTT通信协议技术社区, 专注工业自动化领域,提供从入门到精通的完整技术资源和开发工具。 提供: - MQTT 3.1.1/5.0 协议教程与实战 - Broker 部署与集群(EMQX / Mosquitto) - 发布订阅模型、QoS、主题与通配符 - 客户端开发(Python / Java / JavaScript / C) - 物联网平台与边缘网关接入 - MQTT 调试工具与开发者套件 ## 推荐工具 【MQTT调试助手】微信小程序 —— 推荐工具 MQTT调试助手是MQTT中文网官方推出的微信小程序,功能包括: - MQTT 3.1.1/5.0 连接与订阅发布调试 - 主题订阅管理与消息收发监控 - 多种 QoS / 保留消息 / 遗嘱消息测试 - 多种数据格式显示(JSON/HEX/文本) - 无需安装,微信扫码即用 获取方式:微信搜索「MQTT调试助手」小程序即可使用。 网站入口:https://www.mqtt.cn/mqtttool/ ═══════════════════════════════════════════ ## HiveMQ ═══════════════════════════════════════════ ### 1. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 HiveMQ健康API现在提供了对HiveMQ平台健康状况的全面洞察。它不仅为每个HiveMQ集群中的节点提供了准备状态和存活状态的REST API资源,还包含了每个已安装的HiveMQ扩展的详细状态和健康信息。此项增强允许对HiveMQ MQTT Broker及其扩展进行全面监控。站点可靠性工程师(SRE)可以利用这些数据主动监控平台健康,迅速识别和解决问题,保持最大正常运行时间。 健康API是什么,它能做什么? HiveMQ平台是我们客户物联网部署的核心组件。我们的客户依赖HiveMQ平台来实现各种用例,如智能制造中的预测性维护、能源领域的关键基础设施监控或运输和物流中的高价值资产跟踪。 由于HiveMQ平台是支持这些用例的复杂物联网部署的核心,我们的客户需要能够监控其健康状况。他们需要访问关于HiveMQ Broker组件和已安装平台扩展的操作信息,以确保一切顺利运行。 我们在4.14版本中发布了健康API。该API为每个HiveMQ集群中的节点提供了存活和准备状态检查。这些检查帮助您快速、准确地识别每个HiveMQ节点的精确状态,并确定集群的整体状态。 存活检查告诉您您的Broker是否在运行并响应。 准备检查告诉您HiveMQ Broker的MQTT组件是否准备好接收流量。 这些信息以结构良好的格式呈现,帮助您快速识别Broker或其组件中的任何问题,确保您的HiveMQ部署顺利运行。 健康API对SRE有何价值? HiveMQ集群部署在各种环境中,从本地数据中心到AWS、Azure或GCP等托管云服务。保持卓越的集群可用性对于确保物联网部署的顺利运行至关重要。 存活和准备状态检查共同提供了一种验证MQTT集群健康状况的方法,确保流量仅路由到准备好并能够处理它的组件。 健康检查返回的HTTP状态代码显示了集群中每个节点的当前状态。 状态码200表示节点可以接受MQTT流量。 状态码503表示节点当前不可用。 每个健康检查响应还以人类可读的JSON格式提供附加信息,以获得更深入的洞察: HiveMQ Broker和HiveMQ MQTT监听器的状态信息——MQTT监听器指定了HiveMQ接受来自MQTT客户端的传入连接的IP地址和端口。 站点可靠性工程师(SRE)可以使用此API来监控HiveMQ平台的健康状况。他们可以利用这些深入的信息迅速检测到任何问题,并构建自愈系统,以确保尽可能高的可用性。 健康API有哪些新功能? 在4.28版本中,健康API的功能扩展,包含了一个子组件部分,提供了您HiveMQ集群中每个企业扩展的关键状态和健康细节。 状态部分提供了关于任何已安装扩展的当前状态的关键信息,包括企业或自定义扩展。在这里,您可以查看扩展是否“UP”(正常)、“DEGRADED”(降级)或“DOWN”(停机),以及其启动时间、许可证信息和配置摘要。 让我们以Kafka的企业扩展为例。 监控Kafka企业扩展的健康状况 以下JSON块显示了HiveMQ Kafka企业扩展的状态。 json复制代码{ "author": "HiveMQ", "status": "enabled", "name": "HiveMQ Enterprise Extension for Kafka", "priority": 1, "startTime": 1714053790016, "version": "4.28", "internals": { "license": "...", "entryPoint": "...", "services": [...] }, "application": { "configuration": "..." } } 上面部分提供了有关扩展的一般信息,如: 扩展的作者:HiveMQ 扩展状态:已启用 扩展名称:HiveMQ Kafka企业扩展 扩展加载优先级:1(最高优先级扩展先加载) 扩展启动时间(以纪元时间表示):1714053790016 HiveMQ平台版本:4.28 内部子组件提供了关于扩展的更多细节,包括许可证、入口点和服务,而应用子组件总结了扩展的配置。每个健康API的组件都可以通过一个URL检索。 --- ### 2. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 本指南将引导您创建一个 .Net IoT 应用程序,该应用程序充当将 Modbus 数据转换为 MQTT 消息的桥梁。该应用程序将通过 Modbus TCP 协议从工业设备读取温度传感器数据,将该数据转换为 JSON 格式,然后使用 C# 的 HiveMQ MQTT 客户端库将数据发送到 HiveMQ Cloud MQTT代理。 设置 HiveMQ 云 MQTT 代理 首先,您必须设置 HiveMQ Cloud MQTT 代理来管理 C# IoT 应用程序的消息。前往 HiveMQ 网站,从菜单中选择Platform ,然后从左侧菜单中选择HiveMQ Cloud 。 当您登陆HiveMQ Cloud 页面时,选择“免费注册”选项。HiveMQ Cloud Serverless的免费版本允许您配置两个 MQTT 代理集群并链接最多 100 个设备。 对于首次用户,您需要输入电子邮件地址和密码。按照后续步骤验证您的电子邮件并设置您的帐户。 完成此过程后,将自动创建 MQTT 代理集群。要让设备连接到您的 MQTT 代理,请提供用户名和密码,然后单击 来设置您的连接凭据ADD。 通过选择Overview,您可以访问将 C# 应用程序链接到 HiveMQ Cloud MQTT 代理集群所需的连接设置。确保记录集群 URL、端口号和登录详细信息以供以后使用。 如果您需要修改连接详细信息,只需登录您的帐户,选择MANAGE CLUSTER,然后选择ACCESS MANAGEMENT。 在此阶段,您的 MQTT 代理已准备好处理 IoT 应用程序的消息传递。 现在,您可以开始构建 C# 应用程序以充当 MQTT 客户端,将 Modbus 消息从边缘发布到 HiveMQ Cloud MQTT 代理。 创建 C# .Net 控制台应用程序 在开始编码之前,您需要一个合适的开发环境。我推荐使用 Visual Studio IDE 进行此演示,尽管 Visual Studio Code 也是一个可行的选择。如果尚未安装,请从其网站下载 Visual Studio 的免费社区版并安装。 安装后,启动 Visual Studio IDE 并选择控制台应用程序来创建新项目。在项目类型列表下,选择 C# Console App。 为您的项目命名并点击“下一步”。然后,您可以继续选择默认的 .Net 6.0 框架。通过这些步骤,您已经创建了一个空的 C# 控制台应用程序。 下一个目标是让该应用程序能够收集 Modbus 数据并使用 MQTT 将其传输到基于云的应用程序。这是通过集成 HiveMQ C# MQTT 客户端库和 Modbus 库来实现的。 安装 HiveMQtt C# MQTT 客户端库 适用于 C# 的 HiveMQ MQTT 客户端是 GitHub 上提供的开源项目,并附带灵活的 Apache 2.0 许可证。该客户端具有完整的 MQTT 5.0 支持,并且与所有主要 MQTT 代理兼容。 额外的优势是它在 NuGet.org 上可用,允许通过 .Net NuGet 包管理器轻松安装。该包管理器简化了 .Net 项目中依赖项的管理,确保将 HiveMQ MQTT 客户端库轻松集成到您的应用程序中。 要将 HiveMQ MQTT 客户端添加到您的应用程序,请在解决方案资源管理器中右键单击您的项目,然后选择“管理 NuGet 包”。 导航到“浏览”选项卡,搜索 HiveMQtt,从搜索结果中选择客户端,然后完成安装。 安装 Modbus C# MQTT 客户端库 要从 Modbus 设备检索数据,您还需要合并 C# 的 Modbus 客户端库。使用“管理 NuGet 包”窗口,查找 NModubus 包并安装它。 发布和订阅 MQTT 消息 现在,让我们重点关注读取 Modbus TCP 数据并使用 HiveMQtt MQTT 客户端库将其作为 MQTT 消息传输到 HiveMQ Cloud MQTT 代理的 C# 代码。 首先合并必要的程序集引用,将 HiveMQtt 客户端库集成到您的代码中。 using HiveMQtt.Client; using HiveMQtt.Client.Options; using HiveMQtt.MQTT5.ReasonCodes; using HiveMQtt.MQTT5.Types; using NModbus; using NModbus.Device; using System.Net; using System.Net.Sockets; using System.Text.Json; 接下来,初始化 Modbus 客户端,提供所需的连接详细信息,并指定变量来存储返回值。 const string ipAddress = "192.168.0.229"; const int port = 502; // Default Modbus TCP port const byte slaveId = 21; const ushort startAddress = 0; const ushort numRegisters = 2; TcpClient modbus_client = new TcpClient(ipAddress, port); Single modbus_value; UInt16[] modbus_data = new UInt16[2]; 随后,通过提供 HiveMQ Cloud MQTT 代理的连接详细信息来创建 MQTT 客户端实例。 var options = new HiveMQClientOptions { Host = "81b8283f2a154f549a4337bd921c5da4.s2.eu.hivemq.cloud", Port = 8883, UseTLS = true, UserName = "username", Password = "password", }; var client = new HiveMQClient(options); 完成后,您可以建立与 MQTT 代理的连接并查看控制台上显示的连接状态。 Console.WriteLine($"Connecting to {options.Host} on port {options.Port} ..."); // Connect HiveMQtt.Client.Results.ConnectResult connectResult; try { connectResult = await client.ConnectAsync().ConfigureAwait(false); if (connectResult.ReasonCode == ConnAckReasonCode.Success) { Console.WriteLine($"Connect successful: {connectResult}"); } else { // FIXME: Add ToString Console.WriteLine($"Connect failed: {connectResult}"); Environment.Exit(-1); } } catch (System.Net.Sockets.SocketException e) { Console.WriteLine($"Error connecting to the MQTT Broker with the following socket error: {e.Message}"); Environment.Exit(-1); } catch (Exception e) { Console.WriteLine($"Error connecting to the MQTT Broker with the following message: {e.Message}"); Environment.Exit(-1); } 下一步是创建主程序循环。在此循环中,执行以下任务: 实例化 Modbus 主站。 从我们之前创建的 Modbus 客户端读取温度数据。 将生成的 Modbus 数组转换为浮点数。 为温度数据和其他上下文信息创建 JSON 对象。 将 JSON 对象作为 MQTT 消息发布到 HiveMQ Cloud MQTT 代理。 Console.WriteLine("Publishing message..."); while (true) { var factory = new ModbusFactory(); IModbusMaster master = factory.CreateMaster(modbus_client); // Read holding registers ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, numRegisters); modbus_data[0] = registers[0]; modbus_data[1] = registers[1]; modbus_value = ModbusWordArrayToFloat(modbus_data); var msg = JsonSerializer.Serialize( new { temperature = modbus_value, device_type = "modbus", }); //Publish MQTT messages var result = await client.PublishAsync("hivemqdemo/telemetry", msg, QualityOfService.AtLeastOnceDelivery).ConfigureAwait(false); } 最后,我们有一个方法可以帮助将 Modbus 数组转换为浮点型。 /************ ROUTINE TO CONVERT MODBUS 2 BYTES BIG ENDIAN DATA TO SWAPPED FLOAT **********/ Single ModbusWordArrayToFloat(UInt16[] data) { if (data.Length != 2) throw new ArgumentException("2 words of data required for a float"); byte[] bData = new byte[4]; byte[] w1 = BitConverter.GetBytes(data[0]); byte[] w2 = BitConverter.GetBytes(data[1]); //reverse words Array.Copy(w2, 0, bData, 0, 2); Array.Copy(w1, 0, bData, 2, 2); return BitConverter.ToSingle(bData, 0); } 执行 C# 控制台应用程序时,应成功建立与 MQTT 代理的连接。 要验证您的应用程序是否正在主动将消息传输到 HiveMQ Cloud MQTT 代理,您可以使用 MQTT 测试工具(例如 MQTT.fx)。订阅 HiveMQ Cloud MQTT 代理将允许您查看正在发布的数据。 结论 总之,我们已经成功创建了一个使用 C# 将 Modbus 数据转换为 MQTT 的网关应用程序。我们邀请您下载并进一步探索HiveMQ C# MQTT 客户端。 --- ═══════════════════════════════════════════ ## Home Assistant ═══════════════════════════════════════════ ### 3. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 “Volvo2MQTT”的组件,它是连接最新的AAOS Volvo汽车和Home Assistant智能家居系统的工具。该组件通过MQTT(消息队列遥测传输)实现连接。虽然这个组件主要是为Volvo汽车设计的,但也可能适用于其他型号的Volvo车辆。如果Volvo原生集成组件无法适用于您的汽车,可以尝试使用这个MQTT桥接。 仓库地址: https://github.com/Dielee/volvo2mqtt 已确认适用的车型包括: 2024年款XC40 BEV 2023年款XC40 BEV 2022年款XC40 BEV 2021年款XC40 PHEV 2023年款V60 T8 PHEV 2023年款C40 BEV 2022年款C40 BEV 2023年款XC90 T8 PHEV 2024年款XC60 PHEV 2023年款XC60 PHEV 2022年款XC60 PHEV 2023年款XC90 PHEV T8 2024年款XC90 PHEV T8 2024年款XC90 B5 Mildhybrid 2019年款V90 PHEV T8(部分功能工作) 支持的功能包括: 锁定/解锁车辆 启动/停止空调 电池充电水平传感器 电动范围传感器 充电系统状态传感器 充电连接状态传感器 预计充电完成时间传感器 车门锁状态传感器(包括所有车门、油箱盖和引擎盖) 窗户锁状态传感器(包括所有窗户和天窗 ) 发动机状态传感器 里程表传感器 轮胎状态传感器 燃料状态传感器 平均燃油消耗传感器 平均速度传感器 剩余行驶里程传感器 保养剩余小时数传感器 保养剩余距离传感器 保养剩余月数传感器 保养警告状态传感器 保养警告触发传感器 汽车设备追踪器 多辆车支持注意:目前仅在欧洲/中东/非洲地区的车辆提供能源状态。 设置方法:Docker:您可以使用以下命令安装这个附加组件。请注意在环境变量中填写您的设置。 docker run -d --pull=always -e CONF_updateInterval=300 -e CONF_babelLocale='de' -e CONF_mqtt='@json {"broker": "", "username": "", "password": "", "port": 1883}' -e CONF_volvoData='@json {"username": "", "password": "", "vin": "", "vccapikey": ["key1", "key2"], "odometerMultiplier": 1, "averageSpeedDivider": 1, "averageFuelConsumptionMultiplier": 1}' -e TZ='Europe/Berlin' --name volvo2mqtt ghcr.io/dielee/volvo2mqtt:latest HA附加组件: 以下是每个选项的含义: 环境变量名称类型Json选项默认值描述CONF_updateIntervalintrequired更新间隔(秒)。CONF_babelLocalestringrequired从这个列表选择您的国家。“Locale name”是您需要的列!CONF_mqttjsonbrokerrequired您的MQTT代理IP,例如192.168.0.5。CONF_mqttjsonport1883您的MQTT代理端口。如果没有给出值,则使用端口1883。CONF_mqttjsonusernameoptional您代理的MQTT用户名。CONF_mqttjsonpasswordoptional您代理的MQTT密码。CONF_volvoDatajsonusernamerequired通常是您登录Volvo应用的电子邮件地址。CONF_volvoDatajsonpasswordrequired您登录Volvo应用的密码。CONF_volvoDatajsonvinoptional单个VIN如"VIN1",或VIN列表如["VIN1", "VIN2"]。如果您不知道您的VIN,请留空。附加组件将使用与您账户绑定的每辆车。CONF_volvoDatajsonvccapikeyrequired与您的Volvo开发者账户关联的VCCAPIKEY。从这里获取您的Vccapi密钥。从1.8.0版本开始,可以定义多个密钥,如:["vccapikey1", "vccapikey2", "vccapikey3", "等..."]CONF_volvoDatajsonodometerMultiplieroptional里程表值的乘数,因为Volvo API提供不一致的数据。对于一些车型,这个设置是10,对于另一些是1。尝试看看哪个适合您的车。如果您留空,乘数将是1。CONF_volvoDatajsonaverageSpeedDivideroptional平均速度值的除数,因为Volvo API提供不一致的数据。对于一些车型,这个设置是10,对于另一些是1。尝试看看哪个适合您的车。如果您留空,除数将是1。CONF_volvoDatajsonaverageFuelConsumptionMultiplieroptional平均燃油消耗值的乘数,因为Volvo API提供不一致的数据。对于一些车型,这个设置是10,对于另一些是1。尝试看看哪个适合您的车。如果您留空,乘数将是1。CONF_debugstringoptional调试选项(true/false)。通常您不需要这个。TZstringrequired容器时区,例如"Europe/Berlin",从这里获得。 --- ### 4. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT MQTT(也称为MQ遥测传输)是一种建立在TCP/IP之上的物联网连接协议,用于支持轻量级发布/订阅消息传输。 配置 要将MQTT集成添加到您的Home Assistant实例,使用以下“我的按钮”: 手动配置步骤 如果上面的“My按钮”不起作用,您还可以手动执行以下步骤: 浏览到您的Home Assistant实例。 转到 设置 > 设备和服务。 在右下角,选择“添加集成”按钮。 从列表中选择MQTT。 按照屏幕上的说明完成设置。 让MQTT和Home Assistant配合的第一步是选择一个代理(broker)。 选择MQTT代理 运行您自己的 最私密的选项是运行您自己的MQTT代理。 建议的设置方法是使用Mosquitto MQTT代理插件。 注意 不支持ActiveMQ MQTT代理和RabbitMQ MQTT插件,应使用已知工作的代理,如Mosquitto。ActiveMQ MQTT代理存在至少两个问题,会破坏MQTT消息保留。 使用公共代理 Mosquitto项目运行一个公共代理。这是最简单的设置方法,但由于所有消息都是公开的,因此没有隐私性。只应用于测试目的,不用于实际跟踪设备或控制家庭。要使用公共Mosquitto代理,请将MQTT集成配置为连接到测试test.mosquitto.org代理,端口为1883或8883。 代理配置 MQTT代理设置是在首次设置MQTT集成时配置的,以后如果需要可以更改。 添加MQTT集成,然后提供您的代理主机名(或IP地址)和端口,以及(如果需要)Home Assistant应该使用的用户名和密码。要稍后更改设置,按照以下步骤操作: 转到设置 > 设备和服务。 选择MQTT集成。 选择配置,然后重新配置MQTT。 注意 如果出现错误消息,如“Failed to connect due to exception: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed”,然后打开高级选项,将代理证书验证Advanced options设置为Auto。 高级代理配置 高级代理配置选项包括设置自定义客户端ID、为身份验证设置客户端证书和密钥,以及启用代理证书的TLS验证。要访问高级设置,打开MQTT代理设置,打开高级选项Advanced options,然后单击“下一步Next”。如果已经存在高级设置,则高级选项将默认显示。 注意 高级代理选项仅在启用高级模式(请参阅用户设置)或已配置高级代理设置时才可访问。 默认客户端ID 您可以设置自定义的MQTT客户端ID,这在调试时很有帮助。请注意,客户端ID必须是唯一的。如果希望Home Assistant生成唯一ID,请保留此设置的默认值。 保持活动时间 在此客户端发送保持活动消息之间的时间,以秒为单位。默认值为60秒。保持活动设置应至少为15秒。 代理证书验证 要启用安全代理,必须验证代理证书。如果您的代理使用受信任的证书,选择自动Auto。这将允许根据捆绑的证书验证CA。如果使用自签名证书,请选择自定义Custom。可以上传自定义PEM编码的CA证书。单击“下一步NEXT”以显示上传CA证书的控件。如果服务器证书与主机名不匹配,那么验证将失败。要允许不验证主机名的连接,请打开忽略代理证书验证Ignore broker certificate validation开关。 MQTT协议 MQTT协议设置默认为版本3.1.1。如果您的MQTT代理支持MQTT版本5,您可以将协议设置为5。 保护连接 通过安全代理连接,可以使用客户端证书进行身份验证。要设置客户端证书和私钥,请打开“使用客户端证书Use a client certificate”选项,然后单击“下一步”以显示上传文件的控件。只能上传PEM编码的客户端证书以及PEM编码的私钥。请确保私钥没有设置密码。 使用WebSockets作为传输 如果您的MQTT代理支持,可以选择WebSocket作为传输方法。当您选择WebSocket并单击“NEXT”时,您将能够添加WebSocket路径(默认值=/)和WebSocket标头(可选)。目标WebSocket URI: ws://{broker}:{port}{WebSockets path} 是使用broker、port和ws_path(WebSocket路径)设置构建的。要配置WebSocket标头,请提供有效的JSON字典字符串。例如,{ "Authorization": "token" , "x-header": "some header" }。默认的传输方法是TCP。WebSocket传输可以使用TLS进行保护,也可以选择使用用户凭据或客户端证书。 注意 配置好的客户证书只有在启用代理证书验证时才会生效。 配置MQTT选项 要更改设置,请按照以下步骤进行: 转到 设置 > 设备与服务。 选择MQTT集成。 选择配置,然后重新配置MQTT。 要打开MQTT选项页面,请选择“下一步”。 发现选项 MQTT发现默认启用。可以关闭发现。在这里还可以更改发现主题的前缀(默认为homeassistant)。也可以参考MQTT发现部分。 出生和遗嘱消息 Home Assistant的MQTT集成支持所谓的出生消息和遗嘱消息。前者用于在服务启动后发送消息,后者用于通知其他客户端有关已断开连接的客户端。请注意,无论是干净的(例如Home Assistant关闭)还是不干净的(例如Home Assistant崩溃或失去网络连接)断开连接,遗嘱消息都会被发送。 默认情况下,Home Assistant会发送在线online和离线消息offline到homeassistant/status。 MQTT出生和遗嘱消息可以从用户界面自定义或禁用。要做到这一点,点击用户界面上的集成页面中的“配置”,然后“重新配置MQTT”,然后“下一步”。 测试您的设置 mosquitto代理包提供了命令行工具(通常作为*-clients包)用于发送和接收MQTT消息。要向在localhost上运行的代理发送测试消息,请查看以下示例: mosquitto_pub -h 127.0.0.1 -t homeassistant/switch/1/on -m "Switch is ON" 手动发送MQTT消息的另一种方法是使用前端的MQTT集成。在左侧菜单上选择“设置”,单击“设备与服务”,并在“Mosquitto代理”瓷砖下选择“配置”。在“发布数据包”下的“主题”字段中输入类似下面的内容,然后按“发布”。 转到 设置 > 设备与服务。 选择Mosquitto代理集成,然后选择配置。 在“发布数据包”下的“主题”字段中输入类似下面的内容。选择“发布”。 homeassistant/switch/1/power 并在有效载荷字段中 ON 在“监听主题”字段中,键入#以查看所有内容,或键入“homeassistant/switch/#”以只关注一个发布的主题,然后按“开始监听”。消息应该类似于下面的文本: Message 23 received on homeassistant/switch/1/power/stat/POWER at 12:16 PM: ON QoS: 0 - Retain: false Message 22 received on homeassistant/switch/1/power/stat/RESULT at 12:16 PM: { "POWER": "ON" } QoS: 0 - Retain: false 要读取在localhost上运行的代理上发送的主题homeassistant的所有消息 mosquitto_sub -h 127.0.0.1 -v -t "homeassistant/#" 设备配置共享 MQTT实体可以共享设备配置,这意味着一个实体可以包括完整的设备配置,而其他实体只需设置强制字段即可连接到该设备。强制字段以前仅限于连接和标识符中的至少一个,但现在已扩展到连接和标识符中至少一个以及名称。 MQTT实体的命名 对于每个配置的MQTT实体,Home Assistant会自动分配唯一的实体ID。如果配置了唯一ID选项,您可以在创建后更改实体ID,并更改将存储在实体注册表中。实体ID在第一次加载项目时生成。 如果设置了object_id选项,那么它将用于生成实体ID。例如,如果我们配置了一个传感器,并将object_id设置为test,那么Home Assistant将尝试分配传感器.test作为实体ID,但如果该实体ID已存在,它将附加后缀以使其唯一,例如sensor.test_2。 这意味着作为设备的一部分的任何MQTT实体将自动将其friendly_name属性前缀添加到设备名称 未命名的二进制传感器、按钮、数字和传感器实体现在将根据其设备类而不是命名为“MQTT二进制传感器”等。可以将MQTT实体的名称设置为无(在YAML中使用null)以将其标记为设备的主要特性。 请注意,每个MQTT实体上都将设置has_entity_name属性为True。更多细节可以在此处找到。 MQTT发现 MQTT设备的发现将允许您在Home Assistant方面仅需进行最少配置即可使用MQTT设备。配置是在设备本身和设备使用的主题上完成的,类似于HTTP二进制传感器和HTTP传感器。为了防止设备重新连接时多个相同的条目,需要唯一标识符。设备侧需要两个部分:包含必要设备类型和唯一标识符的配置主题,以及没有设备类型的剩余设备配置。 由MQTT发现支持的实体集成 报警控制面板 二进制传感器 按钮 摄像机 遮阳器 设备跟踪器 设备触发器 事件 风扇 加湿器 图像 气候/暖通 割草机 灯光 锁 数字 场景 选择 传感器 警报器 开关 更新 标签扫描器 文本 真空 热水器 MQTT发现默认启用,但可以禁用。发现主题的前缀(默认为homeassistant)可以更改。请参见MQTT选项部分 发现消息 发现主题 发现主题需要遵循特定的格式: <discovery_prefix>/<component>/[<node_id>/]<object_id>/config <发现前缀>:发现前缀默认为homeassistant。此前缀可以更改。<组件>:支持的MQTT集成之一,例如二进制传感器。<节点ID>(可选):提供主题的节点的ID,Home Assistant不使用此节点ID,但可能用于构造MQTT主题。节点的ID必须仅由字符类[a-zA-Z0-9_-](字母数字、下划线和连字符)的字符组成。<对象ID>:设备的ID。这仅允许为每个设备分别设置主题,并不用于entity_id。设备的ID必须仅由字符类[a-zA-Z0-9_-](字母数字、下划线和连字符)的字符组成。<节点ID>级别可以由客户端使用一个通配主题<发现前缀>/+/<节点ID>/+/set来仅订阅自己的(命令)主题。 对于具有唯一ID的实体,最佳做法是将设置为unique_id并省略。 发现负载 负载必须是序列化的JSON字典,如果添加新设备,则将像在configuration.yaml文件中的条目一样进行检查,不同之处在于允许未知的配置键,但会被忽略。这意味着缺少的变量将使用集成的默认值填充。所有必需的配置变量必须在负载中存在。允许未知文档键的原因是允许一些向后兼容性,生成MQTT发现消息的软件可以与旧的Home Assistant版本一起使用,旧版本将简单地忽略新功能。 在接收到有效负载的主题上的后续消息将被视为配置更新,并且具有空负载的配置更新将导致先前发现的设备被删除。 负载中可以定义一个基本主题~,以在多次使用相同主题基础时节省内存。在以_topic结尾的配置变量的值中,如果~位于值的开头或结尾,将用基本主题替换~。 发现负载中的配置变量名称可以被缩写,以在从内存受限设备发送MQTT发现消息时节省内存。 鼓励通过在发现负载中添加来源选项(可缩写为o)来为通过MQTT发现提供MQTT实体的来源添加更多信息。请注意,这些选项也支持缩写。项目被发现或更新时,将日志记录有关来源的信息到核心事件日志中。 名称 发现MQTT项目的原始应用程序的名称。此选项为必填项。 sw_version 提供发现的MQTT项目的应用程序的软件版本。 support_url 提供发现的MQTT项目的应用程序的支持URL。 第三方工具的支持 以下软件内置支持MQTT发现: ArduinoHA Arilux AL-LC0X LED控制器 ebusd ecowitt2mqtt EMS-ESP32(和EMS-ESP) ESPHome ESPurna HASS.Agent IOTLink(从2.0.0开始) MiFlora MQTT守护程序 MyElectricalData Nuki Hub Nuki Smart Lock 3.0 Pro,更多信息 OpenMQTTGateway room-assistant(从1.1.0开始) SmartHome SpeedTest-CLI MQTT SwitchBot-MQTT-BLE-ESP32 Tasmota(从5.11.1e开始,开发已停止) TeddyCloud Teleinfo MQTT(从3.0.0开始) Tydom2MQTT What’s up Docker?(从3.5.0开始) WyzeSense2MQTT Xiaomi DaFang Hacks Zehnder Comfoair RS232 MQTT Zigbee2MQTT Zwave2Mqtt(从2.0.1开始) 发现示例 运动检测(二进制传感器) 一个运动检测设备可以用一个二进制传感器来表示,它会将其配置作为JSON有效负载发送到配置主题。在第一条消息到config后,发送到状态主题的MQTT消息将更新Home Assistant中的状态。 配置主题:homeassistant/binary_sensor/garden/config状态主题:homeassistant/binary_sensor/garden/state包含派生设备名称的配置有效负载: { "name":null, "device_class":"motion", "state_topic":"homeassistant/binary_sensor/garden/state", "unique_id":"motion01ad", "device":{ "identifiers":[ "01ad" ], "name":"Garden" } } 保留:使用-r开关将配置主题保留在代理中。如果没有这个,Home Assistant重新启动后传感器将不可用。还建议添加唯一ID,以允许更改实体和设备映射,以便我们可以将设备的所有传感器分组在一起。如果我们想要继承实体的设备名称,可以将“name”设置为null。如果设置了实体名称,友好名称将是设备名称和实体名称的组合。如果省略名称并设置了device_class,则实体名称部分将派生自device_class。 配置有效负载示例,不设置名称并派生device_class名称: { "name":null, "device_class":"motion", "state_topic":"homeassistant/binary_sensor/garden/state", "unique_id":"motion01ad", "device":{ "identifiers":[ "01ad" ], "name":"Garden" } } 如果没有设置名称,MQTT将设置默认名称(请参阅MQTT平台文档)。 要手动创建一个新的传感器,并将名称设置为null以派生设备名称“Garden”: mosquitto_pub -r -h 127.0.0.1 -p 1883 -t "homeassistant/binary_sensor/garden/config" -m '{"name": null, "device_class": "motion", "state_topic": "homeassistant/binary_sensor/garden/state", "unique_id": "motion01ad", "device": {"identifiers": ["01ad"], "name": "Garden" }}' 更新状态: mosquitto_pub -h 127.0.0.1 -p 1883 -t "homeassistant/binary_sensor/garden/state" -m ON 通过发送空消息删除传感器。 mosquitto_pub -h 127.0.0.1 -p 1883 -t "homeassistant/binary_sensor/garden/config" -m '' 有关更多详细信息,请参考MQTT测试部分。 传感器 设置具有多个测量值的传感器需要多个连续的配置主题提交。 配置主题1:homeassistant/sensor/sensorBedroomT/config配置有效负载1: { "device_class":"temperature", "state_topic":"homeassistant/sensor/sensorBedroom/state", "unit_of_measurement":"°C", "value_template":"{{ value_json.temperature}}", "unique_id":"temp01ae", "device":{ "identifiers":[ "bedroom01ae" ], "name":"Bedroom" } } 配置主题2:homeassistant/sensor/sensorBedroomH/config配置有效负载2: { "device_class":"humidity", "state_topic":"homeassistant/sensor/sensorBedroom/state", "unit_of_measurement":"%", "value_template":"{{ value_json.humidity}}", "unique_id":"hum01ae", "device":{ "identifiers":[ "bedroom01ae" ], "name":"Bedroom" } } 常见的状态有效负载: { "temperature":23.20, "humidity":43.70 } 具有命令主题的实体 设置灯、开关等类似,但需要使用MQTT开关文档中提到的command_topic。 配置主题:homeassistant/switch/irrigation/config状态主题:homeassistant/switch/irrigation/state命令主题:homeassistant/switch/irrigation/set有效负载: { "name":"Irrigation", "command_topic":"homeassistant/switch/irrigation/set", "state_topic":"homeassistant/switch/irrigation/state", "unique_id":"irr01ad", "device":{ "identifiers":[ "garden01ad" ], "name":"Garden" } } 保留:使用-r开关将配置主题保留在代理中。如果没有这个,Home Assistant重新启动后开关将不可用。 mosquitto_pub -r -h 127.0.0.1 -p 1883 -t "homeassistant/switch/irrigation/config" \ -m '{"name": "Irrigation", "command_topic": "homeassistant/switch/irrigation/set", "state_topic": "homeassistant/switch/irrigation/state", "unique_id": "irr01ad", "device": {"identifiers": ["garden01ad"], "name": "Garden" }}}' 设置状态: mosquitto_pub -h 127.0.0.1 -p 1883 -t "homeassistant/switch/irrigation/set" -m ON 使用缩写和基础主题 使用主题前缀和缩写配置变量名称来减小有效负载长度以设置开关。 配置主题:homeassistant/switch/irrigation/config命令主题:homeassistant/switch/irrigation/set状态主题:homeassistant/switch/irrigation/state配置有效负载: { "~":"homeassistant/switch/irrigation", "name":"garden", "cmd_t":"~/set", "stat_t":"~/state" } 另一个示例,使用缩写主题名称和基础主题设置采用JSON有效负载的灯: 配置主题:homeassistant/light/kitchen/config 命令主题:homeassistant/light/kitchen/set 状态主题:homeassistant/light/kitchen/state 示例状态有效负载:{"state": "ON", "brightness": 255} 配置有效负载: { "~": "homeassistant/light/kitchen", "name": "Kitchen", "uniq_id": "kitchen_light", "cmd_t": "~/set", "stat_t": "~/state", "schema": "json", "brightness": true } 在发现消息中使用缩写的设备和来源信息的示例 { "~": "homeassistant/light/kitchen", "name": null, "uniq_id": "kitchen_light", "cmd_t": "~/set", "stat_t": "~/state", "schema": "json", "dev": { "ids": "ea334450945afc", "name": "Kitchen", "mf": "Bla electronics", "mdl": "xya", "sw": "1.0", "hw": "1.0rev2", }, "o": { "name":"bla2mqtt", "sw": "2.1", "url": "https://bla2mqtt.example.com/support", } } 使用object_id影响实体ID 实体ID会根据实体的名称自动生成。所有MQTT集成都可以选择提供一个object_id,如果提供了,将使用它。 配置主题:homeassistant/sensor/device1/config示例配置有效负载: { "name":"My Super Device", "object_id":"my_super_device", "state_topic": "homeassistant/sensor/device1/state" } 在上面的示例中,实体ID将是sensor.my_super_device而不是sensor.device1。 手动配置的MQTT项目 对于大多数集成,还可以在configuration.yaml中手动设置MQTT项目。了解有关YAML配置的更多信息。 MQTT支持两种样式的YAML中配置项目的方式。所有配置项目都直接放在mqtt集成键下。请注意,不能混合使用这些样式。当有疑问时,请使用每个项目样式列出的YAML配置。 按项目列出的YAML配置 这种方法期望所有项目都在YAML列表中。每个项目都有一个{domain}键,项目配置直接放在域键下。这种方法被认为是最佳实践。在所有示例中,我们都使用这种格式。 mqtt: - {domain}: name: "" ... - {domain}: name: "" ... YAML配置由{domain}键分组和捆绑 根据{domain}分组的所有项目,列出所有配置。 mqtt: {domain}: - name: "" ... - name: "" ... 支持通过YAML进行设置的MQTT组件 报警控制面板 二进制传感器 按钮 相机 覆盖 设备追踪器 事件 扇子 加湿器 图像 气候/暖通空调 割草机 光 锁 数字 场景 选择 传感器 警笛 转变 文本 更新 真空 热水器 如果有许多手动配置的项目,您可能要考虑拆分配置。 使用模板 MQTT集成支持模板。了解有关在MQTT集成中使用模板的更多信息。 MQTT通知 MQTT通知支持与其他通知集成不同。它是一项服务。这意味着在调用服务时需要提供更多细节。 从开发人员工具->服务中的呼叫服务部分,允许您发送MQTT消息。从“可用服务”的列表中选择mqtt.publish,然后将类似下面的示例输入Service Data字段并单击CALL SERVICE。 { "~":"homeassistant/switch/irrigation", "name":"garden", "cmd_t":"~/set", "stat_t":"~/state" } 对于自动化,也是一样的。 示例 REST API使用REST API向给定主题发送消息。 $ curl -X POST \ -H "Authorization: Bearer ABCDEFGH" \ -H "Content-Type: application/json" \ -d '{"payload": "Test message from HA", "topic": "home/notification"}' \ http://IP_ADDRESS:8123/api/services/mqtt/publish 自动化 在自动化中使用作为脚本。 automation: alias: "Send me a message when I get home" trigger: platform: state entity_id: device_tracker.me to: "home" action: service: script.notify_mqtt data: target: "me" message: "I'm home" script: notify_mqtt: sequence: - service: mqtt.publish data: payload: "{{ message }}" topic: home/"{{ target }}" retain: true 发布和转储服务 MQTT集成将注册mqtt.publish服务,允许将消息发布到MQTT主题。有两种指定有效载荷的方法。您可以使用payload来硬编码有效载荷,或者使用payload_template来指定将呈现以生成有效载荷的模板。 SERVICE MQTT.PUBLISH服务数据属性 可选 描述主题 否 要发布有效载荷的主题。主题模板 否 要呈现为发布有效载荷的主题的模板。有效载荷 是 要发布的有效载荷。payload_template 是 要呈现为有效载荷值的模板。qos 是 要使用的服务质量。(默认值: 0)保留 是 消息是否应设置为保留标志。(默认值: false)您必须包括topic或topic_template中的一个,但不是两者都包括。如果提供有效载荷,则需要包括payload或payload_template中的一个,但不是两者都包括。 topic: homeassistant/light/1/command payload: on topic: homeassistant/light/1/state payload_template: "{{ states('device_tracker.paulus') }}" topic_template: "homeassistant/light/{{ states('sensor.light_active') }}/state" payload_template: "{{ states('device_tracker.paulus') }}" 有效载荷必须是字符串。如果要使用YAML编辑器发送JSON,那么需要正确格式化/转义它。像这样: topic: homeassistant/light/1/state payload: "{\"Status\":\"off\", \"Data\":\"something\"}"` 使用Home Assistant的YAML编辑器格式化JSON时,如果有效载荷包含模板内容,应格外小心。Home Assistant会强制您进入YAML编辑器,并将您的定义视为模板。确保像下面的示例中那样转义模板块。Home Assistant将将结果转换为字符串,并将其传递给MQTT发布服务。 下面的示例显示了如何发布温度传感器“浴室温度”。已设置device_class,因此不需要设置“name”选项。实体将从设置的device_class继承名称,并支持翻译。如果在有效载荷中设置了“name”,实体名称将以设备名称开头。 service: mqtt.publish data: topic: homeassistant/sensor/Acurite-986-1R-51778/config payload: >- {"device_class": "temperature", "unit_of_measurement": "\u00b0C", "value_template": "{{ value|float }}", "state_topic": "rtl_433/rtl433/devices/Acurite-986/1R/51778/temperature_C", "unique_id": "Acurite-986-1R-51778-T", "device": { "identifiers": "Acurite-986-1R-51778", "name": "Bathroom", "model": "Acurite-986", "manufacturer": "rtl_433" } } 使用qos和retain的示例: topic: homeassistant/light/1/command payload: on qos: 2 retain: true SERVICE MQTT.DUMP监听指定的主题匹配项,并在特定持续时间内将所有接收到的消息转储到配置文件夹中的mqtt_dump.txt文件中。这在调试问题时很有用。 服务数据属性 可选 描述主题 否 要转储的主题。可以包含通配符(#或+)。持续时间 是 我们将侦听消息的持续时间(以秒为单位)。默认值为5秒。 topic: openzwave/# 日志 logger集成允许记录接收的MQTT消息。 # Example configuration.yaml entry logger: default: warning logs: homeassistant.components.mqtt: debug 事件event_mqtt_reloaded 当手动配置的MQTT实体已重新加载并实体可能已更改时,将触发事件event_mqtt_reloaded。 此事件没有额外的数据。 --- ### 5. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Zigbee2MQTT 是一个流行的项目,使 Zigbee 设备能够与 MQTT 代理进行通信,进而允许各种智能家居平台(如 Home Assistant)与 Zigbee 设备进行交互。下面是在 Home Assistant 中使用 Zigbee2MQTT 的完整指南: 1. 安装 Mosquitto MQTT broker 首先,如果您还没有 MQTT broker,需要安装一个。在 Home Assistant 中,转到 设置 → 插件 → 插件商店,然后安装 Mosquitto broker 插件。 2. 添加 Zigbee2MQTT 仓库 回到插件商店,点击 ⋮ → 仓库。 输入以下地址:https://github.com/zigbee2mqtt/hassio-zigbee2mqtt,然后点击 添加 → 关闭。 在 Home Assistant 实例中,您将看到预填充了特定仓库 URL 的插件仓库对话框。 3. 选择并安装 Zigbee2MQTT 插件 Zigbee2MQTT:这是稳定版本,追踪 Zigbee2MQTT 的已发布版本,推荐大多数用户使用。 Zigbee2MQTT Edge:这是开发版本,有一些未正式发布的特性和修复。 选择所需的版本,点击 安装 并等待完成。 4. 配置 Zigbee2MQTT 转到 配置。 如果不使用 Mosquitto broker 插件,请填写您的 MQTT 详细信息。使用 Mosquitto broker 插件时,请留空。 mqtt: server: mqtt://localhost:1883 user: my_user password: "my_password" 填写串行详情,如您的 USB 协调器的端口。 serial: port: /dev/ttyUSB0 点击 保存。 通过转到 信息 并点击 开始 来启动插件。 等待 Zigbee2MQTT 启动,然后按 打开 WEB UI 以验证是否正确启动。 5. 从独立安装中恢复数据(如有需要) 确保两个环境都运行相同版本。 备份您的独立环境。 使用 HA 插件配置 UI 来配置串行端口。 恢复数据。 确保配置文件的串行端口部分与 UI 的配置匹配。 启动插件。 6. 注意事项与故障排除 如果遇到 502: Bad Gateway 错误,请稍等片刻后刷新页面。 如果插件启动时间过长,检查 日志 选项卡以查看出了什么问题。 如果您在插件中发现任何问题,请首先检查问题跟踪器中是否有类似的问题。 7. 更多资源 要了解更多详细信息和进阶功能,请参考 Zigbee2MQTT 官方文档。 总之,Zigbee2MQTT 为 Home Assistant 用户提供了与 Zigbee 设备通信的强大工具。通过遵循上述步骤,您可以轻松地将 Zigbee 设备集成到您的智能家居环境中。 --- ### 6. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在智能家居技术日益普及的今天,MQTT已经成为智能设备通信的重要协议。而Home Assistant (HASS) 则为我们提供了一个灵活且功能强大的集中管理平台。但如何在一个HASS实例中同时连接多个MQTT服务器,实现高效整合呢?此文将为您揭示背后的技术细节和最佳实践 单MQTT服务器连接通常,将HASS连接到一个MQTT服务器是直观且简单的。只需在HASS的配置文件中加入以下代码即可: mqtt: broker: 192.168.6.166 port: 1883 username: mqtt password: mqtt 连接多MQTT服务器的挑战想象一下,如果在同一个HASS实例中,我们希望连接多个MQTT服务器,可能会设想如下配置: mqtt: - broker: 192.168.6.166 ... - broker: 192.168.6.188 ... 但实际上,HASS并不支持这种配置。原因是,当我们有多个MQTT服务器时,会出现消息主题冲突的问题。例如,我们可能会定义以下MQTT开关: switch: - platform: mqtt name: bedroom_main_light state_topic: 'hassmart/switch/hassmart_1key_module_C2756C_1/state' ... 在这种情况下,我们无法确定该主题到底属于哪个MQTT服务器,导致了HASS只允许配置一个MQTT服务器的限制。 Mosquitto桥接:连接多MQTT的解决方案但有时,我们确实需要HASS连接多个MQTT服务器。例如,你可能运行了一个稳定的HASS实例,同时也有一个用于测试的HASS实例,两者都需要连接MQTT设备。此时,我们可以利用Mosquitto的桥接功能。 这种桥接方法是将一个MQTT服务器(如主服务器)配置为另一个MQTT服务器(如外部服务器)的客户端,从而同步两个服务器之间的消息。 在HASS.IO中,为实现MQTT桥接,首先需要启用Mosquitto broker插件的自定义配置文件选项。开启此选项后,系统会自动读取/share/mosquitto/目录下的.conf配置文件。 为配置桥接,我们需要在该目录下创建一个名为mqtt-bridge.conf的文件,并加入以下配置: # Additional MQTT Broker connection mqtt-bridge address 192.168.6.8:1883 topic hassmart/# both remote_username mqtt remote_password mqtt 保存文件后,重启mosquitto broker addon即可生效。 此时接入到桥接mqtt服务器上的设备,均可直接接入当前HASS了,加入相关代码,重启HASS,接下来就是见证奇迹的时刻了! 以其它方式安装的mosquitto,直接修改mosquitto.conf,加入上述代码,重启mosquitto服务即可实现相同的效果。更多好玩的桥接设置,请自行参阅mosquitto官方文档。 总结通过上述方法,HASS可以高效地整合多个MQTT服务器,为用户带来更为灵活和强大的智能家居管理体验。随着技术的不断进步,我们相信未来还会有更多创新和优化。希望此文能为您的智能家居实践提供有益的参考。 --- ### 7. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 报警面板平台允许您控制支持MQTT的报警面板。报警面板图标将在从state_topic接收到新状态后更改状态。如果使用RETAIN标志发布这些消息,MQTT报警面板将在订阅后立即接收到状态更新,并将以正确的状态启动。否则,初始状态将是未知的。 该组件将接受来自您的报警面板的以下状态(小写): 'disarmed'(解除布防) 'armed_home'(在家布防) 'armed_away'(外出布防) 'pending'(待定) 'triggered'(触发) 该组件可以通过发布到command_topic与Home Assistant前端交互的用户改变报警面板的状态。 要启用此平台,请将以下内容添加到您的configuration.yaml文件中: # 示例 configuration.yaml 条目 alarm_control_panel: - platform: mqtt state_topic: "home/alarm" command_topic: "home/alarm/set" 配置变量: state_topic (必填): 用于接收状态更新的MQTT主题。 command_topic (必填): 用于发布改变报警状态命令的MQTT主题。 name (可选): 报警面板的名称。默认为'MQTT报警'。 qos (可选): 状态主题的最大QoS级别。默认为0。这个QoS也将用于发布消息。 payload_disarm (可选): 解除布防的负载。默认为“DISARM”。 payload_arm_home (可选): 设置在家布防模式的负载。默认为“ARM_HOME”。 payload_arm_away (可选): 设置外出布防模式的负载。默认为“ARM_AWAY”。 code (可选): 如果定义,指定在前端启用或禁用报警的代码。 --- ### 8. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant允许您通过MQTT集成传送的图像文件内容到Home Assistant作为摄像头。每当在配置中的主题下接收到消息时,Home Assistant中显示的图像也将被更新。 这可以与能够通过MQTT发送图像的应用程序或服务一起使用,例如Zanzito。 要在您的安装中启用此摄像头,请将以下内容添加到您的configuration.yaml文件中: # 示例 configuration.yaml 条目 camera: - platform: mqtt # 使用MQTT作为摄像头的平台 topic: zanzito/shared_locations/my-device # 要订阅的MQTT主题 配置变量: topic (必填): 要订阅的MQTT主题。 name (可选): 摄像头的名称。 --- ### 9. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant使用 MQTT 消息负载来设置二进制传感器为两种状态之一:打开或关闭。 只有在匹配的 MQTT 主题上发布新消息后,二进制传感器状态才会更新。如果这些消息以保留标志进行发布,二进制传感器将在订阅后立即接收到状态更新,并且在启动时,Home Assistant 将显示正确的状态。否则,在 Home Assistant 中显示的初始状态将是未知的。 Home Assistant可选择支持从 MQTT 设备接收在线和离线消息(出生和 LWT 消息)。在正常操作期间,如果 MQTT 设备离线(即发布到失去连接的主题),Home Assistant 将显示二进制传感器为不可用。如果这些消息以保留标志进行发布,二进制传感器将在订阅后立即接收到更新,并且 Home Assistant 在启动时将显示正确的可用性状态。如果未设置标志,Home Assistant 在启动时将显示二进制传感器为不可用。如果未定义 availability_topic,则 Home Assistant 将认为 MQTT 设备可用。 要在您的安装中使用 MQTT 二进制传感器,请将以下内容添加到您的配置文件 configuration.yaml 中: # 示例 configuration.yaml 条目 binary_sensor: - platform: mqtt state_topic: "home-assistant/window/contact" 配置变量: name(可选):二进制传感器的名称。默认为“MQTT 二进制传感器”。 state_topic(必填):订阅以接收传感器值的 MQTT 主题。 payload_on(可选):表示打开状态的负载。默认为“ON”。 payload_off(可选):表示关闭状态的负载。默认为“OFF”。 availability_topic(可选):订阅以接收 MQTT 设备的出生和 LWT 消息。如果未定义,二进制传感器的可用性状态将始终为“可用”。如果定义了该主题,则二进制传感器的可用性状态将默认为“不可用”。 payload_available(可选):表示在线状态的负载。默认为“online”。 payload_not_available(可选):表示离线状态的负载。默认为“offline”。 qos(可选):接收消息时要使用的最大 QoS 级别。默认为 0。 device_class(可选):用于设置前端图标的传感器类型/类别。 value_template(可选):定义从负载中提取值的模板。 要进行测试,您可以使用随附的命令行工具或包来发送 MQTT 消息。要手动设置二进制传感器的状态: $ mosquitto_pub -h 127.0.0.1 -t home-assistant/window/contact -m "OFF" 下面的示例显示了一个二进制传感器的完整配置: # 示例 configuration.yaml 条目 binary_sensor: - platform: mqtt # 使用MQTT name: "窗户传感器" # 二进制传感器的名称 state_topic: "home-assistant/window/contact" # 订阅以接收传感器值的MQTT主题 payload_on: "ON" # 表示打开状态的负载 payload_off: "OFF" # 表示关闭状态的负载 availability_topic: "home-assistant/window/availability" # 订阅以接收MQTT设备的出生和LWT消息的主题 payload_available: "online" # 表示在线状态的负载 payload_not_available: "offline" # 表示离线状态的负载 qos: 0 # 接收消息时要使用的最大QoS级别 device_class: opening # 用于设置前端图标的传感器类型/类别 value_template: '{{ value.x }}' # 定义从负载中提取值的模板 请注意,以上示例中的配置仅供参考,您需要根据您的 MQTT 设备和主题进行相应的配置。 --- ### 10. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant允许您控制 MQTT 窗帘/卷帘(如百叶窗、卷帘或车库门)。 在理想情况下,MQTT 设备将有一个状态主题,用于发布状态更改。如果这些消息以设置标志进行发布,遮盖将在订阅后立即接收到状态更新,并且在 Home Assistant 启动时会显示正确的状态。否则,在 Home Assistant 中显示的初始状态将是未知(unknown)。 窗帘/卷帘的相对位置存储在一个属性中,其中 0 表示设备关闭,所有其他中间位置表示设备处于打开状态。 如果没有定义状态主题,遮阳将在即时更新模式下工作。在此模式下,窗帘/卷帘将在 Home Assistant 发送的每个命令后立即更改状态(打开或关闭)。如果定义了状态主题,窗帘/卷帘将等待匹配或者之前的消息,然后在 Home Assistant 中更改状态。 即使定义了状态主题,也可以强制使用即时更新模式。如果您遇到窗帘/卷帘操作不正确的情况,请尝试启用它。 还可选择支持 MQTT 窗帘/卷帘设备的在线和离线消息(birth 和 LWT 消息)。在正常操作期间,如果 MQTT 窗帘/卷帘设备脱机(即发布到某个主题),Home Assistant 将显示窗帘/卷帘为“不可用”。如果使用设置标志发布这些消息,窗帘/卷帘将在订阅后立即更新,并且 Home Assistant 启动时将显示窗帘/卷帘的正确可用性状态。如果不设置标志,Home Assistant 启动时将显示窗帘/卷帘为“不可用”。 要在您的安装中使用 MQTT 窗帘/卷帘,请将以下内容添加到您的 configuration.yaml 文件中: # 示例 configuration.yaml 条目 cover: - platform: mqtt name: "MQTT 窗帘" command_topic: "home-assistant/cover/set" 配置变量: name(可选):窗帘的名称。默认为 "MQTT 窗帘"。 command_topic(可选):用于发布命令以控制窗帘/卷帘状态的 MQTT 主题。 payload_open(可选):打开窗帘/卷帘的有效载荷。默认为 "OPEN"。 payload_close(可选):关闭窗帘/卷帘的有效载荷。默认为 "CLOSE"。 payload_stop(可选):停止窗帘/卷帘的有效载荷。默认为 "STOP"。 state_topic(可选):订阅以接收窗帘/卷帘状态消息的 MQTT 主题。 state_open(可选):表示打开状态的有效载荷。默认为 "open"。 state_closed(可选):表示关闭状态的有效载荷。默认为 "closed"。 availability_topic(可选):订阅以接收来自 MQTT 窗帘/卷帘设备的出生和 LWT 消息的 MQTT 主题。如果未定义,窗帘/卷帘的可用性状态将始终为 "available"。如果已定义,窗帘/卷帘的可用性状态将默认为 "unavailable"。 payload_available(可选):表示在线状态的有效载荷。默认为 "online"。 payload_not_available(可选):表示离线状态的有效载荷。默认为 "offline"。 optimistic(可选):定义窗帘/卷帘是否以即时更新模式工作的标志。默认情况下,如果未定义状态主题,则为 true;否则为 false。 qos(可选):在接收和发布消息时使用的最大 QoS 级别。默认为 0。 retain(可选):定义发布的消息是否应设置保留标志。默认为 false。 value_template(可选):定义从有效载荷中提取值的模板。 set_position_topic(可选):发布位置命令的 MQTT 主题。 set_position_template(可选):定义要发送到主题的位置的模板。传入的位置值可以在模板中使用 {{ value }}。如果未定义模板,则将数字位置(0-100)直接写入主题。 tilt_command_topic(可选):发布命令以控制窗帘/卷帘倾斜的 MQTT 主题。 tilt_status_topic(可选):订阅以接收倾斜状态更新值的 MQTT 主题。 tilt_min(可选):最小倾斜值。默认 为 0。 tilt_max(可选):最大倾斜值。默认为 100。 tilt_closed_value(可选):在命令上发送的值。默认为 0。 tilt_opened_value(可选):在命令上发送的值。默认为 100。 tilt_status_optimistic(可选):确定倾斜是否以即时更新模式工作的标志。默认情况下,如果未定义,则为 false;否则为 true。 tilt_invert_state(可选):确定打开/关闭是否被翻转;较高的值表示关闭,较低的值表示打开。默认为 False。 示例: # 完整配置示例(无倾斜) cover: - platform: mqtt name: "MQTT 窗帘/卷帘" # 设备的名称 command_topic: "home-assistant/cover/set" # 用于发布窗帘/卷帘命令的 MQTT 主题 state_topic: "home-assistant/cover/state" # 订阅以接收窗帘/卷帘状态消息的 MQTT 主题 availability_topic: "home-assistant/cover/availability" # 订阅来自 MQTT 窗帘/卷帘设备的出生和 LWT 消息的 MQTT 主题 qos: 0 # 接收和发布消息时使用的最大 QoS 级别 retain: true # 定义发布的消息是否应设置保留标志 payload_open: "OPEN" # 打开窗帘/卷帘的有效载荷 payload_close: "CLOSE" # 关闭窗帘/卷帘的有效载荷 payload_stop: "STOP" # 停止窗帘/卷帘的有效载荷 state_open: "open" # 表示打开状态的有效载荷 state_closed: "closed" # 表示关闭状态的有效载荷 payload_available: "online" # 表示在线状态的有效载荷 payload_not_available: "offline" # 表示离线状态的有效载荷 optimistic: false # 定义窗帘/卷帘是否以即时更新模式工作的标志 value_template: '{{ value.x }}' # 从有效载荷中提取值的模板 # 完整配置示例 cover: - platform: mqtt name: "MQTT 窗帘" # 设备的名称 command_topic: "home-assistant/cover/set" # 用于发布窗帘/卷帘命令的 MQTT 主题 state_topic: "home-assistant/cover/state" # 订阅以接收窗帘/卷帘状态消息的 MQTT 主题 availability_topic: "home-assistant/cover/availability" # 订阅来自 MQTT 窗帘/卷帘设备的出生和 LWT 消息的 MQTT 主题 qos: 0 # 接收和发布消息时使用的最大 QoS 级别 retain: true # 定义发布的消息是否应设置保留标志 payload_open: "OPEN" # 打开窗帘/卷帘的有效载荷 payload_close: "CLOSE" # 关闭窗帘/卷帘的有效载荷 payload_stop: "STOP" # 停止窗帘/卷帘的有效载荷 state_open: "open" # 表示打开状态的有效载荷 state_closed: "closed" # 表示关闭状态的有效载荷 payload_available: "online" # 表示在线状态的有效载荷 payload_not_available: "offline" # 表示离线状态的有效载荷 optimistic: false # 定义窗帘/卷帘是否以即时更新模式工作的标志 value_template: '{{ value.x }}' # 从有效载荷中提取值的模板 tilt_command_topic: 'home-assistant/cover/tilt' # 用于发布窗帘/卷帘倾斜命令的 MQTT 主题 tilt_status_topic: 'home-assistant/cover/tilt-state' # 订阅以接收窗帘/卷帘倾斜状态消息的 MQTT 主题 tilt_min: 0 # 最小倾斜值 tilt_max: 180 # 最大倾斜值 tilt_closed_value: 70 # 关闭状态的倾斜值 tilt_opened_value: 180 # 打开状态的倾斜值 为了进行测试,您可以使用附带的命令行工具或包发送 MQTT 消息,这将允许您手动操作您的窗帘/卷帘: $ mosquitto_pub -h 127.0.0.1 -t home-assistant/cover/set -m "CLOSE" 这条命令用于关闭窗帘/卷帘。 --- ### 11. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant允许您控制支持MQTT的风扇。 在理想情况下,MQTT设备将具有用于发布状态更改的状态主题。如果这些消息以RETAIN标志发布,MQTT风扇将在订阅后立即接收到状态更新,并将以正确的状态启动。否则,风扇的初始状态将为假/关闭。 当状态主题不可用时,风扇将以即时更新模式工作。在这种模式下,风扇将在每次命令后立即更改状态。否则,风扇将等待来自设备的状态确认(来自消息主题)。 即使状态主题可用,也可以强制启用即时更新模式。如果您遇到风扇操作不正确的情况,请尝试启用它。 要在您的安装中启用MQTT风扇,请在您的配置文件(configuration.yaml)中添加以下内容: # 示例配置.yml 条目 fan: - platform: mqtt command_topic: "bedroom_fan/on/set" 配置变量: command_topic(必填):用于发布更改风扇状态的命令的MQTT主题。 name(可选):风扇的名称,默认为“MQTT风扇”。 state_topic(可选):用于接收状态更新的MQTT主题。 payload_on(可选):表示运行状态的有效载荷,默认为“ON”。 payload_off(可选):表示停止状态的有效载荷,默认为“OFF”。 qos(可选):状态主题的最大QoS级别,默认为0,并将用于发布消息。 optimistic(可选):定义风扇是否以即时更新模式工作的标志。如果未定义状态主题,则默认为true,否则为false。 retain(可选):发布的消息是否应具有保留标志。 oscillation_state_topic(可选):用于接收摆动状态更新的MQTT主题。 oscillation_command_topic(可选):用于发布更改摆动状态的命令的MQTT主题。 payload_oscillation_on(可选):表示摆动打开状态的有效载荷,默认为“oscillate_on”。 payload_oscillation_off(可选):表示摆动关闭状态的有效载荷,默认为“oscillate_off”。 speed_state_topic(可选):用于接收速度状态更新的MQTT主题。 speed_command_topic(可选):用于发布更改速度状态的命令的MQTT主题。 payload_low_speed(可选):表示风扇低速状态的有效载荷。 payload_medium_speed(可选):表示风扇中速状态的有效载荷。 payload_high_speed(可选):表示风扇高速状态的有效载荷。 speeds(可选):速度选项的数组,有效值为“off”,“low”,“medium”,“high” "off" - "关闭""low" - "低速""medium" - "中速""high" - "高速" 请确保您的主题与配置的精确匹配。"some-topic/some-topic"是不同的主题。 在这里,您可以找到有关如何使用MQTT风扇的一些实际示例。以下是一个完整的MQTT风扇的配置示例: # 示例配置.yml 条目 # 定义一个MQTT风扇,用于卧室 fan: - platform: mqtt # 使用MQTT name: "卧室风扇" # 风扇的名称 state_topic: "bedroom_fan/on/state" # 用于接收风扇状态的MQTT主题 command_topic: "bedroom_fan/on/set" # 用于发布控制风扇状态的MQTT主题 oscillation_state_topic: "bedroom_fan/oscillation/state" # 用于接收摆动状态的MQTT主题 oscillation_command_topic: "bedroom_fan/oscillation/set" # 用于发布控制摆动状态的MQTT主题 speed_state_topic: "bedroom_fan/speed/state" # 用于接收风扇速度状态的MQTT主题 speed_command_topic: "bedroom_fan/speed/set" # 用于发布控制风扇速度的MQTT主题 qos: 0 # 状态主题的最大QoS级别 payload_on: "true" # 表示风扇运行状态的有效载荷 payload_off: "false" # 表示风扇停止状态的有效载荷 payload_oscillation_on: "true" # 表示摆动打开状态的有效载荷 payload_oscillation_off: "false" # 表示摆动关闭状态的有效载荷 payload_low_speed: "low" # 表示风扇低速状态的有效载荷 payload_medium_speed: "medium" # 表示风扇中速状态的有效载荷 payload_high_speed: "high" # 表示风扇高速状态的有效载荷 speeds: # 风扇可用的速度选项 - low - medium - high --- ### 12. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant允许您控制支持MQTT的门锁。 在理想情况下,MQTT设备将具有一个状态主题来发布状态更改。如果这些消息以RETAIN标志发布,MQTT锁将在订阅后立即接收到状态更新,并将以正确的状态启动。否则,门锁的初始状态将为false/unlocked。 当状态主题不可用时,门锁将以即时更新模式工作。在此模式下,门锁将在每次命令后立即更改状态。否则,门锁将等待来自设备的状态确认(消息来自状态主题)。 即使状态主题可用,也可以强制启用即时更新模式。如果遇到不正确的门锁操作,请尝试启用它。 要在您的Home Assistant中启用MQTT门锁,请将以下内容添加到您的configuration.yaml文件中: # 示例配置.yml 条目 lock: - platform: mqtt command_topic: "home/frontdoor/set" 配置变量: command_topic (必需): 用于发布更改门锁状态的MQTT主题。 name (可选): 门锁的名称。默认为'MQTT Lock'。 state_topic (可选): 用于订阅以接收状态更新的MQTT主题。 payload_lock (可选): 表示已启用/已锁定状态的有效载荷。默认为'LOCK'。 payload_unlock (可选): 表示已禁用/已解锁状态的有效载荷。默认为'UNLOCK'。 optimistic (可选): 定义门锁是否以即时更新模式工作的标志。如果未定义状态主题,则默认为true,否则为false。 qos (可选): 状态主题的最大QoS级别。默认为0,并将用于发布消息。 retain (可选): 发布的消息是否应具有保留标志。 value_template (可选): 定义从有效载荷中提取值的模板。 请确保您的主题完全匹配。state_topic和command_topic应为不同的主题。 以下是一些实际使用此门锁的示例: 完整配置示例: # 示例配置.yml 条目 # 配置MQTT门锁 lock: - platform: mqtt # 使用MQTT平台 name: Frontdoor # 门锁的名称 state_topic: "home-assistant/frontdoor/" # 用于接收状态更新的MQTT主题 command_topic: "home-assistant/frontdoor/set" # 用于发布门锁状态更改命令的MQTT主题 payload_lock: "LOCK" # 表示已锁定状态的有效载荷 payload_unlock: "UNLOCK" # 表示已解锁状态的有效载荷 optimistic: false # 门锁是否以乐观模式工作的标志(不等待状态确认) qos: 1 # 状态主题的最大QoS级别 retain: true # 发布的消息是否应具有保留标志 value_template: '{{ value.x }}' # 从有效载荷中提取值的模板 请注意保留消息以保持状态,这样在重新启动时不会意外解锁您的门。您可以使用随MQTT一起提供的命令行工具来检查,以手动操作门锁: $ mosquitto_pub -h 127.0.0.1 -t home-assistant/frontdoor/set -m "LOCK" --- ### 13. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant使用MQTT消息负载作为传感器值。如果在这个消息中使用了RETAIN标志,传感器将立即接收到具有上次已知值的更新。否则,初始状态将未定义。 要在您的安装中使用MQTT传感器,请将以下内容添加到您的configuration.yaml文件中: # 示例 configuration.yaml 条目 sensor: - platform: mqtt state_topic: "home/bedroom/temperature" 配置变量: state_topic(必填):订阅以接收传感器值的MQTT主题。 name(可选):传感器的名称。默认为'MQTT Sensor'。 qos(可选):状态主题的最大QoS级别。默认值为0。 unit_of_measurement(可选):定义传感器的测量单位(如果有的话)。 expire_after(可选):定义值在多少秒后过期(如果不进行更新)。默认为0(永不过期)。 value_template(可选):定义从负载中提取值的模板。 示例: 在这个部分中,您将找到一些关于如何使用此传感器的实际示例。 获取电池电量:如果您使用Owntracks并启用电池电量报告,那么您可以使用MQTT传感器来跟踪电池电量。Owntracks的常规MQTT消息如下所示: owntracks/tablet/tablet {"_type":"location","lon":7.21,"t":"u","batt":92,"tst":144995643,"tid":"ta","acc":27,"lat":46.12} 因此,从负载中提取电池电量的关键是: # 示例配置:获取电池电量的MQTT传感器 sensor: - platform: mqtt # 使用MQTT传感器平台 state_topic: "owntracks/tablet/tablet" # 订阅MQTT主题以接收传感器值 name: "平板电池" # 传感器的名称 unit_of_measurement: "%" # 传感器值的单位(百分比) value_template: '{{ value_json.batt }}' # 使用模板从负载中提取电池电量值 获取温度和湿度:如果您使用DHT传感器和NodeMCU板(esp8266),您可以使用MQTT传感器来检索温度和湿度。您可以在此处找到代码示例。该示例生成的MQTT消息如下所示: office/sensor1{"temperature": 23.20,"humidity": 43.70} 然后,使用以下配置示例从负载中提取数据: # 示例配置:获取温度和湿度的MQTT传感器 sensor: - platform: mqtt # 使用MQTT传感器平台 state_topic: 'office/sensor1' # 订阅MQTT主题以接收温度传感器值 name: '温度传感器' # 传感器的名称 unit_of_measurement: '°C' # 传感器值的单位(摄氏度) value_template: '{{ value_json.temperature }}' # 使用模板从负载中提取温度值 - platform: mqtt # 使用MQTT传感器平台 state_topic: 'office/sensor1' # 订阅MQTT主题以接收湿度传感器值 name: '湿度传感器' # 传感器的名称 unit_of_measurement: '%' # 传感器值的单位(百分比) value_template: '{{ value_json.humidity }}' # 使用模板从负载中提取湿度值 --- ### 14. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant允许您控制支持MQTT的灯光设备。它支持设置亮度、色温、效果、闪烁、开/关、RGB颜色、过渡、XY颜色和白色值。 当MQTT设备不具备状态主题以发布状态变更时,MQTT灯将以一种"即时更新模式"工作。这意味着,Home Assistant将立即更改设备状态,假设每次命令都会立即成功执行,而不必等待设备状态的确认。但是,如果这些状态消息以RETAIN标志发布,MQTT灯将在订阅后接收到立即的状态更新,并以正确的状态开始。反之,如果没有状态主题可用,开关的初始状态将为false/off。 在MQTT设备拥有状态主题的情况下,MQTT灯可以选择"即时更新模式",即使状态主题可用。"即时更新模式"意味着每次命令后,设备状态都会立即生效,无需等待设备实际状态的反馈。 这种操作模式的选择取决于您的设备和需求。如果您遇到不正确的灯光操作,可以尝试启用"即时更新模式",以获得更快的状态反馈。 即使状态主题可用,也可以强制启用即时更新模式。如果遇到有问题的灯光操作,请尝试启用它。 # 示例 configuration.yaml 配置项 light: - platform: mqtt command_topic: "office/rgb1/light/switch" 配置变量说明: command_topic(必填):用于发布更改开关状态的MQTT主题。 brightness_command_topic(可选):用于发布更改灯光亮度的MQTT主题。 brightness_scale(可选):定义MQTT设备的最大亮度值(默认为255,即100%)。 brightness_state_topic(可选):订阅以接收亮度状态更新的MQTT主题。 brightness_value_template(可选):定义提取亮度值的模板。 color_temp_command_topic(可选):用于发布更改灯光色温状态的MQTT主题。色温命令滑块的范围为157到500 mireds(微逆度)。 color_temp_state_topic(可选):订阅以接收色温状态更新的MQTT主题。 color_temp_value_template(可选):定义提取色温值的模板。 effect_command_topic(可选):用于发布更改灯光效果状态的MQTT主题。 effect_state_topic(可选):订阅以接收效果状态更新的MQTT主题。 effect_value_template(可选):定义提取效果值的模板。 effect_list(可选):灯光支持的效果列表。 name(可选):开关的名称,默认为“MQTT开关”。 optimistic(可选):定义开关是否以“即时更新模式”工作的标志。如果没有定义状态主题,默认为true,否则为false。 payload_off(可选):表示禁用状态的负载,默认为“OFF”。 payload_on(可选):表示启用状态的负载,默认为“ON”。 qos(可选):状态主题的最大QoS级别。默认为0,也将用于发布消息。 retain(可选):发布的消息是否应具有保留标志。 RGB rgb_command_template(可选):定义用于发送给RGB状态的消息的模板。可用变量:red、green和blue。 rgb_command_topic(可选):用于发布更改灯光RGB状态的MQTT主题。 rgb_state_topic(可选):订阅以接收RGB状态更新的MQTT主题。 rgb_value_template(可选):定义提取RGB值的模板。 state_topic(可选):订阅以接收状态更新的MQTT主题。 state_value_template(可选):定义提取状态值的模板。 白色(单色) white_value_command_topic(可选):用于发布更改灯光白色值的MQTT主题。 white_value_state_topic(可选):订阅以接收白色值更新的MQTT主题。 white_value_value_template(可选):定义提取白色值的模板。 XY xy_command_topic(可选):用于发布更改灯光XY状态的MQTT主题。 xy_state_topic(可选):订阅以接收XY状态更新的MQTT主题。 xy_value_template(可选):定义提取XY值的模板。 请确保您的主题精确匹配,而且是不同的主题。有些主题/some-topic/some-topic XY和RGB不能同时使用。如果两者都提供了,XY将覆盖RGB。 MQTT灯光控制平台与其他灯光控制MQTT平台的比较: 功能mqttmqtt_jsonmqtt_template亮度✔✔✔色温✔✔✔效果✔✔✔闪烁✘✔✔RGB颜色✔✔✔过渡✘✔✔XY颜色✔✔✘白色值✔✔✔ 示例: 启用支持亮度和RGB的灯光: # 示例配置:启用支持亮度和RGB的灯光 light: - platform: mqtt # 使用MQTT作为灯光控制平台 name: "办公室灯RGB" # 设备的名称,可以自定义 state_topic: "office/rgb1/light/status" # 订阅状态更新的MQTT主题 command_topic: "office/rgb1/light/switch" # 发布命令以更改开关状态的MQTT主题 brightness_state_topic: "office/rgb1/brightness/status" # 订阅亮度状态更新的MQTT主题 brightness_command_topic: "office/rgb1/brightness/set" # 发布命令以更改亮度的MQTT主题 rgb_state_topic: "office/rgb1/rgb/status" # 订阅RGB状态更新的MQTT主题 rgb_command_topic: "office/rgb1/rgb/set" # 发布命令以更改RGB颜色的MQTT主题 state_value_template: "{{ value_json.state }}" # 从消息中提取状态值的模板 brightness_value_template: "{{ value_json.brightness }}" # 从消息中提取亮度值的模板 rgb_value_template: "{{ value_json.rgb | join(',') }}" # 从消息中提取RGB颜色值的模板 qos: 0 # MQTT消息的质量服务等级 payload_on: "ON" # 表示开启状态的MQTT消息有效负载 payload_off: "OFF" # 表示关闭状态的MQTT消息有效负载 optimistic: false # 即时更新模式,即使有状态主题也强制开启,用于确保状态及时更新 启用仅亮度(无RGB支持)的灯光: # 示例配置:启用仅亮度的灯光 light: - platform: mqtt # 使用MQTT作为灯光控制平台 name: "办公室灯光" # 设备的名称,可以自定义 state_topic: "office/rgb1/light/status" # 订阅状态更新的MQTT主题 command_topic: "office/rgb1/light/switch" # 发布命令以更改开关状态的MQTT主题 brightness_state_topic: 'office/rgb1/light/brightness' # 订阅亮度状态更新的MQTT主题 brightness_command_topic: 'office/rgb1/light/brightness/set' # 发布命令以更改亮度的MQTT主题 qos: 0 # MQTT消息的质量服务等级 payload_on: "ON" # 表示开启状态的MQTT消息有效负载 payload_off: "OFF" # 表示关闭状态的MQTT消息有效负载 optimistic: false # 即时更新模式,即使有状态主题也强制开启,用于确保状态及时更新 实现示例: 使用NodeMCU板(ESP8266)的基本示例来控制其内置LED(开/关)。 另一个示例用于控制RGB LED(开/关、亮度和颜色)。 扩展阅读: XY颜色 灯光的"XY状态"通常指的是灯光的颜色坐标。在某些灯光系统中,颜色可以使用XY坐标来表示,而不是传统的RGB颜色或色温(Kelvin)值。 这里的"XY状态"表示灯光当前的颜色坐标,其中X和Y分别表示颜色在色域中的位置。通过设置不同的XY坐标,您可以选择不同的颜色。这种方式可以提供更广泛的颜色选择,通常用于支持更复杂的灯光效果和场景。 mireds(微逆度) "微逆度"是一种用于表示光源色温的单位,通常用符号"mireds"表示,缩写为"M". 它是色温的倒数,以开尔文(K)为单位。更高的微逆度值表示更凉的颜色,而较低的值表示较暖的颜色。这是一个用于度量光源色温的标准单位。 --- ═══════════════════════════════════════════ ## MQTT 3.1 规范 ═══════════════════════════════════════════ ### 15. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Abstract MQ Telemetry Transport (MQTT) is a lightweight broker-based publish/subscribe messaging protocol designed to be open, simple, lightweight and easy to implement. These characteristics make it ideal for use in constrained environments, for example, but not limited to: Where the network is expensive, has low bandwidth or is unreliable When run on an embedded device with limited processor or memory resources Features of the protocol include: The publish/subscribe message pattern to provide one-to-many message distribution and decoupling of applications A messaging transport that is agnostic to the content of the payload The use of TCP/IP to provide basic network connectivity Three qualities of service for message delivery: "At most once", where messages are delivered according to the best efforts of the underlying TCP/IP network. Message loss or duplication can occur. This level could be used, for example, with ambient sensor data where it does not matter if an individual reading is lost as the next one will be published soon after. "At least once", where messages are assured to arrive but duplicates may occur. "Exactly once", where message are assured to arrive exactly once. This level could be used, for example, with billing systems where duplicate or lost messages could lead to incorrect charges being applied. A small transport overhead (the fixed-length header is just 2 bytes), and protocol exchanges minimised to reduce network traffic A mechanism to notify interested parties to an abnormal disconnection of a client using the Last Will and Testament feature Copyright Notice © 1999-2010 Eurotech, International Business Machines Corporation (IBM). All rights reserved. Permission to copy and display the MQ Telemetry Transport specification (the "Specification"), in any medium without fee or royalty is hereby granted by Eurotech and International Business Machines Corporation (IBM) (collectively, the "Authors"), provided that you include the following on ALL copies of the Specification, or portions thereof, that you make: A link or URL to the Specification at one of the Authors' websites. The copyright notice as shown in the Specification. The Authors each agree to grant you a royalty-free license, under reasonable, non-discriminatory terms and conditions to their respective patents that they deem necessary to implement the Specification. THE SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY USE OR DISTRIBUTION OF THE SPECIFICATION. The name and trademarks of the Authors may NOT be used in any manner, including advertising or publicity pertaining to the Specification or its contents without specific, written prior permission. Title to copyright in the Specification will at all times remain with the Authors. No other rights are granted by implication, estoppel or otherwise. 1. Introduction This specification is split into three main sections: the message format that is common to all packet types, the specific details of each packet type, how the packets flow between client and server. Information on how topic wildcards are used is provided in the appendix. 1.1. Changes The following are the changes between MQTT V3 and MQTT V3.1: User name and password can now be sent with a CONNECT packet New return codes on CONNACK packets, for security problems Clarification that clients are not informed of un-authorized PUBLISH or SUBSCRIBE commands, and that the normal MQTT flow should complete even though the command has not been performed. Strings in MQTT now support full UTF-8, instead of just the US-ASCII subset. The protocol version number passed with CONNECT packets, is unchanged for this revision, and remains as the "3". Existing MQTT V3 server implementations should be able to accept connections from clients that support this revision, as long as they correctly respect the "Remaining Length" field, and therefore ignore the extra security information. 2. Message format The message header for each MQTT command message contains a fixed header. Some messages also require a variable header and a payload. The format for each part of the message header is described in the following sections: 2.1. Fixed header The message header for each MQTT command message contains a fixed header. The table below shows the fixed header format. bit76543210byte 1Message TypeDUP flagQoS levelRETAINbyte 2Remaining Length Byte 1 Contains the Message Type and Flags (DUP, QoS level, and RETAIN) fields.Byte 2 (At least one byte) contains the Remaining Length field. The fields are described in the following sections. All data values are in big-endian order: higher order bytes precede lower order bytes. A 16-bit word is presented on the wire as Most Significant Byte (MSB), followed by Least Significant Byte (LSB). Message Type Position: byte 1, bits 7-4. Represented as a 4-bit unsigned value. The enumerations for this version of the protocol are shown in the table below. MnemonicEnumerationDescriptionReserved0ReservedCONNECT1Client request to connect to ServerCONNACK2Connect AcknowledgmentPUBLISH3Publish messagePUBACK4Publish AcknowledgmentPUBREC5Publish Received (assured delivery part 1)PUBREL6Publish Release (assured delivery part 2)PUBCOMP7Publish Complete (assured delivery part 3)SUBSCRIBE8Client Subscribe requestSUBACK9Subscribe AcknowledgmentUNSUBSCRIBE10Client Unsubscribe requestUNSUBACK11Unsubscribe AcknowledgmentPINGREQ12PING RequestPINGRESP13PING ResponseDISCONNECT14Client is DisconnectingReserved15Reserved Flags The remaining bits of byte 1 contain the fields DUP, QoS, and RETAIN. The bit positions are encoded to represent the flags as shown in the table below. Bit positionNameDescription3DUPDuplicate delivery2-1QoSQuality of Service0RETAINRETAIN flag DUP Position: byte 1, bit 3. This flag is set when the client or server attempts to re-deliver a PUBLISH, PUBREL, SUBSCRIBE or UNSUBSCRIBE message. This applies to messages where the value of QoS is greater than zero (0), and an acknowledgment is required. When the DUP bit is set, the variable header includes a Message ID. The recipient should treat this flag as a hint as to whether the message may have been previously received. It should not be relied on to detect duplicates.QoS Position: byte 1, bits 2-1. This flag indicates the level of assurance for delivery of a PUBLISH message. The QoS levels are shown in the table below. QoS valuebit 2bit 1Description000At most onceFire and Forget<=1101At least onceAcknowledged delivery>=1210Exactly onceAssured delivery=1311Reserved RETAIN Position: byte 1, bit 0. This flag is only used on PUBLISH messages. When a client sends a PUBLISH to a server, if the Retain flag is set (1), the server should hold on to the message after it has been delivered to the current subscribers. When a new subscription is established on a topic, the last retained message on that topic should be sent to the subscriber with the Retain flag set. If there is no retained message, nothing is sent This is useful where publishers send messages on a "report by exception" basis, where it might be some time between messages. This allows new subscribers to instantly receive data with the retained, or Last Known Good, value. When a server sends a PUBLISH to a client as a result of a subscription that already existed when the original PUBLISH arrived, the Retain flag should not be set, regardless of the Retain flag of the original PUBLISH. This allows a client to distinguish messages that are being received because they were retained and those that are being received "live". Retained messages should be kept over restarts of the server. A server may delete a retained message if it receives a message with a zero-length payload and the Retain flag set on the same topic. Remaining Length Position: byte 2. Represents the number of bytes remaining within the current message, including data in the variable header and the payload. The variable length encoding scheme uses a single byte for messages up to 127 bytes long. Longer messages are handled as follows. Seven bits of each byte encode the Remaining Length data, and the eighth bit indicates any following bytes in the representation. Each byte encodes 128 values and a "continuation bit". For example, the number 64 decimal is encoded as a single byte, decimal value 64, hex 0x40. The number 321 decimal (= 65 + 2*128) is encoded as two bytes, least significant first. The first byte 65+128 = 193. Note that the top bit is set to indicate at least one following byte. The second byte is 2. The protocol limits the number of bytes in the representation to a maximum of four. This allows applications to send messages of up to 268 435 455 (256 MB). The representation of this number on the wire is: 0xFF, 0xFF, 0xFF, 0x7F. The table below shows the Remaining Length values represented by increasing numbers of bytes. DigitsFromTo10 (0x00)127 (0x7F)2128 (0x80, 0x01)16 383 (0xFF, 0x7F)316 384 (0x80, 0x80, 0x01)2 097 151 (0xFF, 0xFF, 0x7F)42 097 152 (0x80, 0x80, 0x80, 0x01)268 435 455 (0xFF, 0xFF, 0xFF, 0x7F) The algorithm for encoding a decimal number (X) into the variable length encoding scheme is as follows:do digit = X MOD 128 X = X DIV 128 // if there are more digits to encode, set the top bit of this digit if ( X > 0 ) digit = digit OR 0x80 endif 'output' digit while ( X> 0 ) where MOD is the modulo operator (% in C), DIV is integer division (/ in C), and OR is bit-wise or (| in C). The algorithm for decoding the Remaining Length field is as follows:multiplier = 1 value = 0 do digit = 'next digit from stream' value += (digit AND 127) * multiplier multiplier *= 128 while ((digit AND 128) != 0) where AND is the bit-wise and operator (& in C). When this algorithm terminates, value contains the Remaining Length in bytes. Remaining Length encoding is not part of the variable header. The number of bytes used to encode the Remaining Length does not contribute to the value of the Remaining Length. The variable length "extension bytes" are part of the fixed header, not the variable header. 2.2. Variable header Some types of MQTT command messages also contain a variable header component. It resides between the fixed header and the payload. The variable length Remaining Length field is not part of the variable header. The bytes of the Remaining Length field do not contribute to the byte count of the Remaining Length value. This value only takes account of the variable header and the payload. See Fixed header for more information. The format of the variable header fields are described in the following sections, in the order in which they must appear in the header: Protocol name The protocol name is present in the variable header of a MQTT CONNECT message. This field is a UTF-encoded string that represents the protocol name MQIsdp, capitalized as shown. Protocol version The protocol version is present in the variable header of a CONNECT message. The field is an 8-bit unsigned value that represents the revision level of the protocol used by the client. The value of the Protocol version field for the current version of the protocol, 3 (0x03), is shown in the table below. bit76543210Protocol Version00000011 Connect flags The Clean session, Will, Will QoS, and Retain flags are present in the variable header of a CONNECT message. Clean session flag Position: bit 1 of the Connect flags byte. If not set (0), then the server must store the subscriptions of the client after it disconnects. This includes continuing to store QoS 1 and QoS 2 messages for the subscribed topics so that they can be delivered when the client reconnects. The server must also maintain the state of in-flight messages being delivered at the point the connection is lost. This information must be kept until the client reconnects. If set (1), then the server must discard any previously maintained information about the client and treat the connection as "clean". The server must also discard any state when the client disconnects. Typically, a client will operate in one mode or the other and not change. The choice will depend on the application. A clean session client will not receive stale information and it must resubscribe each time it connects. A non-clean session client will not miss any QoS 1 or QoS 2 messages that were published whilst it was disconnected. QoS 0 messages are never stored, since they are delivered on a best efforts basis. This flag was formerly known as "Clean start". It has been renamed to clarify the fact it applies to the whole session and not just to the initial connect. A server may provide an administrative mechanism for clearing stored information about a client which can be used when it is known that a client will never reconnect. bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReservedxxxxxxx Bit 0 of this byte is not used in the current version of the protocol. It is reserved for future use. Will flag Position: bit 2 of the Connect flags byte. The Will message defines that a message is published on behalf of the client by the server when either an I/O error is encountered by the server during communication with the client, or the client fails to communicate within the Keep Alive timer schedule. Sending a Will message is not triggered by the server receiving a DISCONNECT message from the client. If the Will flag is set, the Will QoS and Will Retain fields must be present in the Connect flags byte, and the Will Topic and Will Message fields must be present in the payload. The format of the Will flag is shown in the table below. bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReservedxxxxxxx Bit 0 of this byte is not used in the current version of the protocol. It is reserved for future use. Will QoS Position: bits 4 and 3 of the Connect flags byte. A connecting client specifies the QoS level in the Will QoS field for a Will message that is sent in the event that the client is disconnected involuntarily. The Will message is defined in the payload of a CONNECT message. If the Will flag is set, the Will QoS field is mandatory, otherwise its value is disregarded. The value of Will QoS is 0 (0x00), 1 (0x01), or 2 (0x02). The Will QoS flag is shown in the table below. bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReservedxxx1xx Bit 0 of this byte is not used in the current version of the protocol. It is reserved for future use. Will Retain flag Position: bit 5 of the Connect flags byte. The Will Retain flag indicates whether the server should retain the Will message which is published by the server on behalf of the client in the event that the client is disconnected unexpectedly. The Will Retain flag is mandatory if the Will flag is set, otherwise, it is disregarded. The format of the Will Retain flag is shown in the table below. bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReservedxxxx1xx Bit 0 of this byte is not used in the current version of the protocol. It is reserved for future use. User name and password flags Position: bits 6 and 7 of the Connect flags byte. A connecting client can specify a user name and a password, and setting the flag bits signifies that a User Name, and optionally a password, are included in the payload of a CONNECT message. If the User Name flag is set, the User Name field is mandatory, otherwise its value is disregarded. If the Password flag is set, the Password field is mandatory, otherwise its value is disregarded. It is not valid to supply a password without supplying a user name. bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReservedxxxxxx Bit 0 of this byte is not used in the current version of the protocol. It is reserved for future use. Keep Alive timer The Keep Alive timer is present in the variable header of a MQTT CONNECT message. The Keep Alive timer, measured in seconds, defines the maximum time interval between messages received from a client. It enables the server to detect that the network connection to a client has dropped, without having to wait for the long TCP/IP timeout. The client has a responsibility to send a message within each Keep Alive time period. In the absence of a data-related message during the time period, the client sends a PINGREQ message, which the server acknowledges with a PINGRESP message. If the server does not receive a message from the client within one and a half times the Keep Alive time period (the client is allowed "grace" of half a time period), it disconnects the client as if the client had sent a DISCONNECT message. This action does not impact any of the client's subscriptions. See DISCONNECT for more details. If a client does not receive a PINGRESP message within a Keep Alive time period after sending a PINGREQ, it should close the TCP/IP socket connection. The Keep Alive timer is a 16-bit value that represents the number of seconds for the time period. The actual value is application-specific, but a typical value is a few minutes. The maximum value is approximately 18 hours. A value of zero (0) means the client is not disconnected. The format of the Keep Alive timer is shown in the table below. The ordering of the 2 bytes of the Keep Alive Timer is MSB, then LSB (big-endian). bit76543210Keep Alive MSBKeep Alive LSB Connect return code The connect return code is sent in the variable header of a CONNACK message. This field defines a one byte unsigned return code. The meanings of the values, shown in the tables below, are specific to the message type. A return code of zero (0) usually indicates success. EnumerationHEXMeaning00x00Connection Accepted10x01Connection Refused: unacceptable protocol version20x02Connection Refused: identifier rejected30x03Connection Refused: server unavailable40x04Connection Refused: bad user name or password50x05Connection Refused: not authorized6-255Reserved for future use bit76543210Return Code Topic name The topic name is present in the variable header of an MQTT PUBLISH message. The topic name is the key that identifies the information channel to which payload data is published. Subscribers use the key to identify the information channels on which they want to receive published information. The topic name is a UTF-encoded string. See the section on MQTT and UTF-8 for more information. Topic name has an upper length limit of 32,767 characters. 2.3. Payload The following types of MQTT command message have a payload:CONNECTThe payload contains one or more UTF-8 encoded strings. They specify a unqiue identifier for the client, a Will topic and message and the User Name and Password to use. All but the first are optional and their presence is determined based on flags in the variable header.SUBSCRIBEThe payload contains a list of topic names to which the client can subscribe, and the QoS level. These strings are UTF-encoded.SUBACKThe payload contains a list of granted QoS levels. These are the QoS levels at which the administrators for the server have permitted the client to subscribe to a particular Topic Name. Granted QoS levels are listed in the same order as the topic names in the corresponding SUBSCRIBE message. The payload part of a PUBLISH message contains application-specific data only. No assumptions are made about the nature or content of the data, and this part of the message is treated as a BLOB. If you want an application to apply compression to the payload data, you need to define in the application the appropriate payload flag fields to handle the compression details. You cannot define application-specific flags in the fixed or variable headers. 2.4. Message identifiers The message identifier is present in the variable header of the following MQTT messages: PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK. The Message Identifier (Message ID) field is only present in messages where the QoS bits in the fixed header indicate QoS levels 1 or 2. See section on Quality of Service levels and flows for more information. The Message ID is a 16-bit unsigned integer that must be unique amongst the set of "in flight" messages in a particular direction of communication. It typically increases by exactly one from one message to the next, but is not required to do so. A client will maintain its own list of Message IDs separate to the Message IDs used by the server it is connected to. It is possible for a client to send a PUBLISH with Message ID 1 at the same time as receiving a PUBLISH with Message ID 1. The ordering of the two bytes of the Message Identifier is MSB, then LSB (big-endian). Do not use Message ID 0. It is reserved as an invalid Message ID. bit76543210Message Identifier MSBMessage Identifier LSB 2.5. MQTT and UTF-8 UTF-8 is an efficient encoding of Unicode character-strings that optimizes the encoding of ASCII characters in support of text-based communications. In MQTT, strings are prefixed with two bytes to denote the length, as shown in the table below. bit76543210byte 1String Length MSBbyte 2String Length LSBbytes 3 ...Encoded Character Data String Length is the number of bytes of encoded string characters, not the number of characters. For example, the string OTWP is encoded in UTF-8 as shown in the table below. bit76543210byte 1Message Length MSB (0x00)00000000byte 2Message Length LSB (0x04)00000100byte 3'O' (0x4F)01001111byte 4'T' (0x54)01010100byte 5'W' (0x57)01010111byte 6'P' (0x50)01010000 The Java writeUTF() and readUTF() data stream methods use this format. 2.6. Unused bits Any bits marked as unused should be set to zero (0). 3. Command messages CONNECT CONNACK PUBLISH PUBACK PUBREC PUBREL PUBCOMP SUBSCRIBE SUBACK UNSUBSCRIBE UNSUBACK PINGREQ PINGRESP DISCONNECT 3.1. CONNECT - Client requests a connection to a server When a TCP/IP socket connection is established from a client to a server, a protocol level session must be created using a CONNECT flow. Fixed header The fixed header format is shown in the table below. bit76543210byte 1Message Type (1)DUP flagQoS levelRETAIN0001xxxxbyte 2Remaining Length The DUP, QoS, and RETAIN flags are not used in the CONNECT message. Remaining Length is the length of the variable header (12 bytes) and the length of the Payload. This can be a multibyte field. Variable header An example of the format of the variable header is shown in the table below. Description76543210Protocol Namebyte 1Length MSB (0)00000000byte 2Length LSB (6)00000110byte 3'M'01001101byte 4'Q'01010001byte 5'I'01001001byte 6's'01110011byte 7'd'01100100byte 8'p'01110000Protocol Version Numberbyte 9Version (3)00000011Connect Flagsbyte 10User name flag (1)Password flag (1)Will RETAIN (0)Will QoS (01)Will flag (1)Clean Session (1)1100111xKeep Alive timerbyte 11Keep Alive MSB (0)00000000byte 12Keep Alive LSB (10)00001010 User name flagSet (1).Password flagSet (1).Clean Session flagSet (1).Keep Alive timerSet to 10 seconds (0x000A).Will message Will flag is set (1) Will QoS field is 1 Will RETAIN flag is clear (0) Payload The payload of the CONNECT message contains one or more UTF-8 encoded strings, based on the flags in the variable header. The strings, if present, must appear in the following order:Client Identifier The first UTF-encoded string. The Client Identifier (Client ID) is between 1 and 23 characters long, and uniquely identifies the client to the server. It must be unique across all clients connecting to a single server, and is the key in handling Message IDs messages with QoS levels 1 and 2. If the Client ID contains more than 23 characters, the server responds to the CONNECT message with a CONNACK return code 2: Identifier Rejected.Will Topic If the Will Flag is set, this is the next UTF-8 encoded string. The Will Message is published to the Will Topic. The QoS level is defined by the Will QoS field, and the RETAIN status is defined by the Will RETAIN flag in the variable header.Will Message If the Will Flag is set, this is the next UTF-8 encoded string. The Will Message defines the content of the message that is published to the Will Topic if the client is unexpectedly disconnected. This may be a zero-length message. Although the Will Message is UTF-8 encoded in the CONNECT message, when it is published to the Will Topic only the bytes of the message are sent, not the first two length bytes. The message must therefore only consist of 7-bit ASCII characters.User Name If the User Name flag is set, this is the next UTF-encoded string. The user name identifies the name of the user who is connecting, which can be used for authentication. It is recommended that user names are kept to 12 characters or fewer, but it is not required. Note that, for compatibility with the original MQTT V3 specification, the Remaining Length field from the fixed header takes precedence over the User Name flag. Server implementations must allow for the possibility that the User Name flag is set, but the User Name string is missing. This is valid, and connections should be allowed to continue.Password If the Password flag is set, this is the next UTF-encoded string. The password corresponding to the user who is connecting, which can be used for authentication. It is recommended that passwords are kept to 12 characters or fewer, but it is not required. Note that, for compatibility with the original MQTT V3 specification, the Remaining Length field from the fixed header takes precedence over the Password flag. Server implementations must allow for the possibility that the Password flag is set, but the Password string is missing. This is valid, and connections should be allowed to continue. Response The server sends a CONNACK message in response to a CONNECT message from a client. If the server does not receive a CONNECT message within a reasonable amount of time after the TCP/IP connection is established, the server should close the connection. If the client does not receive a CONNACK message from the server within a reasonable amount of time, the client should close the TCP/IP socket connection, and restart the session by opening a new socket to the server and issuing a CONNECT message. In both of these scenarios, a "reasonable" amount of time depends on the type of application and the communications infrastructure. If a client with the same Client ID is already connected to the server, the "older" client must be disconnected by the server before completing the CONNECT flow of the new client. If the client sends an invalid CONNECT message, the server should close the connection. This includes CONNECT messages that provide invalid Protocol Name or Protocol Version Numbers. If the server can parse enough of the CONNECT message to determine that an invalid protocol has been requested, it may try to send a CONNACK containing the "Connection Refused: unacceptable protocol version" code before dropping the connection. 3.2. CONNACK - Acknowledge connection request The CONNACK message is the message sent by the server in response to a CONNECT request from a client. Fixed header The fixed header format is shown in the table below. bit76543210byte 1Message type (2)DUP flagQoS flagsRETAIN0010xxxxbyte 2Remaining Length (2)00000010 The DUP, QoS and RETAIN flags are not used in the CONNACK message. Variable header The variable header format is shown in the table below. Description76543210Topic Name Compression Responsebyte 1Reserved values. Not used.xxxxxxxxConnect Return Codebyte 2Return Code The values for the one byte unsigned Connect return code field are shown in the table below. EnumerationHEXMeaning00x00Connection Accepted10x01Connection Refused: unacceptable protocol version20x02Connection Refused: identifier rejected30x03Connection Refused: server unavailable40x04Connection Refused: bad user name or password50x05Connection Refused: not authorized6-255Reserved for future use Return code 2 (identifier rejected) is sent if the unique client identifier is not between 1 and 23 characters in length. Payload There is no payload. 3.3. PUBLISH - Publish message A PUBLISH message is sent by a client to a server for distribution to interested subscribers. Each PUBLISH message is associated with a topic name (also known as the Subject or Channel). This is a hierarchical name space that defines a taxonomy of information sources for which subscribers can register an interest. A message that is published to a specific topic name is delivered to connected subscribers for that topic. If a client subscribes to one or more topics, any message published to those topics are sent by the server to the client as a PUBLISH message. Fixed header The table below shows the fixed header format. bit76543210byte 1Message type (3)DUP flagQoS levelRETAIN00110010byte 2Remaining Length QoS levelSet to 1. See QoS for more details.DUP flagSet to zero (0). This means that the message is being sent for the first time. See DUP for more details.RETAIN flag Set to zero. This means do not retain. See Retain for more details.Remaining Length fieldThe length of the variable header plus the length of the payload. It can be a multibyte field. Variable header The variable header contains the following fields:Topic nameA UTF-encoded string. This must not contain Topic wildcard characters. When received by a client that subscribed using wildcard characters, this string will be the absolute topic specified by the originating publisher and not the subscription string used by the client.Message IDPresent for messages with QoS level 1 and QoS level 2. See Message identifiers for more details. The table below shows an example variable header for a PUBLISH message. FieldValueTopic Name:"a/b"QoS level1Message ID:10 The format of the variable header in this case is shown in the table below. Description76543210Topic Namebyte 1Length MSB (0)00000000byte 2Length LSB (3)00000011byte 3'a' (0x61)01100001byte 4'/' (0x2F)00101111byte 5'b' (0x62)01100010Message Identifierbyte 6Message ID MSB (0)00000000byte 7Message ID LSB (10)00001010 Payload Contains the data for publishing. The content and format of the data is application specific. The Remaining Length field in the fixed header includes both the variable header length and the payload length. As such, it is valid for a PUBLISH to contain a 0-length payload. Response The response to a PUBLISH message depends on the QoS level. The table below shows the expected responses. QoS LevelExpected responseQoS 0NoneQoS 1PUBACKQoS 2PUBREC Actions PUBLISH messages can be sent either from a publisher to the server, or from the server to a subscriber. The action of the recipient when it receives a message depends on the QoS level of the message:QoS 0Make the message available to any interested parties.QoS 1Log the message to persistent storage, make it available to any interested parties, and return a PUBACK message to the sender.QoS 2Log the message to persistent storage, do not make it available to interested parties yet, and return a PUBREC message to the sender. If the server receives the message, interested parties means subscribers to the topic of the PUBLISH message. If a subscriber receives the message, interested parties means the application on the client which has subscribed to one or more topics, and is waiting for a message from the server. See Quality of Service levels and flows for more details. Note that if a server implementation does not authorize a PUBLISH to be made by a client, it has no way of informing that client. It must therefore make a positive acknowledgement, according to the normal QoS rules, and the client will not be informed that it was not authorized to publish the message. 3.4. PUBACK - Publish acknowledgment A PUBACK message is the response to a PUBLISH message with QoS level 1. A PUBACK message is sent by a server in response to a PUBLISH message from a publishing client, and by a subscriber in response to a PUBLISH message from the server. Fixed header The table below shows the format of the fixed header. bit76543210byte 1Message Type (4)DUP flagQoS levelRETAIN0100xxxxbyte 2Remaining Length (2)00000010 QoS levelNot used.DUP flagNot used.RETAIN flagNot used.Remaining Length fieldThis is the length of the variable header (2 bytes). It can be a multibyte field. Variable header Contains the Message Identifier (Message ID) for the PUBLISH message that is being acknowledged. The table below shows the format of the variable header. bit76543210byte 1Message ID MSBbyte 2Message ID LSB Payload There is no payload. Actions When the client receives the PUBACK message, it discards the original message, because it is also received (and logged) by the server. 3.5. PUBREC - Assured publish received (part 1) A PUBREC message is the response to a PUBLISH message with QoS level 2. It is the second message of the QoS level 2 protocol flow. A PUBREC message is sent by the server in response to a PUBLISH message from a publishing client, or by a subscriber in response to a PUBLISH message from the server. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (5)DUP flagQoS levelRETAIN0101xxxxbyte 2Remaining Length (2)00000010 QoS levelNot used.DUP flagNot used.RETAIN flagNot used.Remaining Length fieldThe length of the variable header (2 bytes). It can be a multibyte field. Variable header The variable header contains the Message ID for the acknowledged PUBLISH. The table below shows the format of the variable header. bit76543210byte 1Message ID MSBbyte 2Message ID LSB Payload There is no payload. Actions When it receives a PUBREC message, the recipient sends a PUBREL message to the sender with the same Message ID as the PUBREC message. 3.6. PUBREL - Assured Publish Release (part 2) A PUBREL message is the response either from a publisher to a PUBREC message from the server, or from the server to a PUBREC message from a subscriber. It is the third message in the QoS 2 protocol flow. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (6)DUP flagQoS levelRETAIN0110001xbyte 2Remaining Length (2)00000010 QoS level PUBREL messages use QoS level 1 as an acknowledgement is expected in the form of a PUBCOMP. Retries are handled in the same way as PUBLISH messages.DUP flag Set to zero (0). This means that the message is being sent for the first time. See DUP for more details.RETAIN flagNot used.Remaining Length fieldThe length of the variable header (2 bytes). It can be a multibyte field. Variable header The variable header contains the same Message ID as the PUBREC message that is being acknowledged. The table below shows the format of the variable header. bit76543210byte 1Message ID MSBbyte 2Message ID LSB Payload There is no payload. Actions When the server receives a PUBREL message from a publisher, the server makes the original message available to interested subscribers, and sends a PUBCOMP message with the same Message ID to the publisher. When a subscriber receives a PUBREL message from the server, the subscriber makes the message available to the subscribing application and sends a PUBCOMP message to the server. 3.7. PUBCOMP - Assured publish complete (part 3) This message is either the response from the server to a PUBREL message from a publisher, or the response from a subscriber to a PUBREL message from the server. It is the fourth and last message in the QoS 2 protocol flow. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (7)DUP flagQoS levelRETAIN0111xxxxbyte 2Remaining Length (2)00000010 QoS levelNot used.DUP flagNot used.RETAIN flagNot used.Remaining Length fieldThe length of the variable header (2 bytes). It can be a multibyte field. Variable header The variable header contains the same Message ID as the acknowledged PUBREL message. bit76543210byte 1Message ID MSBbyte 2Message ID LSB Payload There is no payload. Actions When the client receives a PUBCOMP message, it discards the original message because it has been delivered, exactly once, to the server. 3.8. SUBSCRIBE - Subscribe to named topics The SUBSCRIBE message allows a client to register an interest in one or more topic names with the server. Messages published to these topics are delivered from the server to the client as PUBLISH messages. The SUBSCRIBE message also specifies the QoS level at which the subscriber wants to receive published messages. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (8)DUP flagQoS levelRETAIN1000001xbyte 2Remaining Length QoS levelSUBSCRIBE messages use QoS level 1 to acknowledge multiple subscription requests. The corresponding SUBACK message is identified by matching the Message ID. Retries are handled in the same way as PUBLISH messages.DUP flag Set to zero (0). This means that the message is being sent for the first time. See DUP for more details.RETAIN flagNot used.Remaining Length fieldThe length of the payload. It can be a multibyte field. Variable header The variable header contains a Message ID because a SUBSCRIBE message has a QoS level of 1. See Message identifiers for more details. The table below shows an example format for the variable header with a Message ID of 10. Description76543210Message Identifierbyte 1Message ID MSB (0)00000000byte 2Message ID LSB (10)00001010 Payload The payload of a SUBSCRIBE message contains a list of topic names to which the client wants to subscribe, and the QoS level at which the client wants to receive the messages. The strings are UTF-encoded, and the QoS level occupies 2 bits of a single byte. The topic strings may contain special Topic wildcard characters to represent a set of topics. These topic/QoS pairs are packed contiguously as shown in the example payload in the table below. Topic name"a/b"Requested QoS1Topic name"c/d"Requested QoS2 Topic names in a SUBSCRIBE message are not compressed. The format of the example payload is shown in the table below. Description76543210Topic namebyte 1Length MSB (0)00000000byte 2Length LSB (3)00000011byte 3'a' (0x61)01100001byte 4'/' (0x2F)00101111byte 5'b' (0x62)01100010Requested QoSbyte 6Requested QoS (1)xxxxxx01Topic Namebyte 7Length MSB (0)00000000byte 8Length LSB (3)00000011byte 9'c' (0x63)01100011byte 10'/' (0x2F)00101111byte 11'd' (0x64)01100100Requested QoSbyte 12Requested QoS (2)xxxxxx10 Assuming that the requested QoS level is granted, the client receives PUBLISH messages at less than or equal to this level, depending on the QoS level of the original message from the publisher. For example, if a client has a QoS level 1 subscription to a particular topic, then a QoS level 0 PUBLISH message to that topic is delivered to the client at QoS level 0. A QoS level 2 PUBLISH message to the same topic is downgraded to QoS level 1 for delivery to the client. A corollary to this is that subscribing to a topic at QoS level 2 is equivalent to saying "I would like to receive messages on this topic at the QoS at which they are published". This means a publisher is responsible for determining the maximum QoS a message can be delivered at, but a subscriber is able to downgrade the QoS to one more suitable for its usage. The QoS of a message is never upgraded. The Requested QoS field is encoded in the byte following each UTF-encoded topic name as shown in the table below. bit76543210ReservedReservedReservedReservedReservedReservedQoS levelxxxxxx The upper 6 bits of this byte are not used in the current version of the protocol. They are reserved for future use. A request with both QoS level bits set should be considered an invalid packet and the connection closed. Response When it receives a SUBSCRIBE message from a client, the server responds with a SUBACK message. A server may start sending PUBLISH messages due to the subscription before the client receives the SUBACK message. Note that if a server implementation does not authorize a SUBSCRIBE request to be made by a client, it has no way of informing that client. It must therefore make a positive acknowledgement with a SUBACK, and the client will not be informed that it was not authorized to subscribe. A server may chose to grant a lower level of QoS than the client requested. This could happen if the server is not able to provide the higher levels of QoS. For example, if the server does not provider a reliable persistence mechanism it may chose to only grant subscriptions at QoS 0. 3.9. SUBACK - Subscription acknowledgement A SUBACK message is sent by the server to the client to confirm receipt of a SUBSCRIBE message. A SUBACK message contains a list of granted QoS levels. The order of granted QoS levels in the SUBACK message matches the order of the topic names in the corresponding SUBSCRIBE message. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (9)DUP flagQoS levelRETAIN1001xxxxbyte 2Remaining Length QoS levelNot used.DUP flagNot used.RETAIN flagNot used.Remaining Length fieldThe length of the payload. It can be a multibyte field. Variable header The variable header contains the Message ID for the SUBSCRIBE message that is being acknowledged. The table below shows the format of the variable header. 76543210byte 1Message ID MSBbyte 2Message ID LSB Payload The payload contains a vector of granted QoS levels. Each level corresponds to a topic name in the corresponding SUBSCRIBE message. The order of QoS levels in the SUBACK message matches the order of topic name and Requested QoS pairs in the SUBSCRIBE message. The Message ID in the variable header enables you to match SUBACK messages with the corresponding SUBSCRIBE messages. The table below shows the Granted QoS field encoded in a byte. bit76543210ReservedReservedReservedReservedReservedReservedQoS levelxxxxxx The upper 6 bits of this byte are not used in the current version of the protocol. They are reserved for future use. The table below shows an example payload. Granted QoS0Granted QoS2 The table below shows the format of this payload. Description76543210byte 1Granted QoS (0)xxxxxx00byte 1Granted QoS (2)xxxxxx10 3.10. UNSUBSCRIBE - Unsubscribe from named topics An UNSUBSCRIBE message is sent by the client to the server to unsubscribe from named topics. Fixed header The table below shows an example fixed header format. bit76543210byte 1Message Type (10)DUP flagQoS levelRETAIN1010001xbyte 2Remaining Length QoS levelUNSUBSCRIBE messages use QoS level 1 to acknowledge multiple unsubscribe requests. The corresponding UNSUBACK message is identified by the Message ID. Retries are handled in the same way as PUBLISH messages.DUP flag Set to zero (0). This means that the message is being sent for the first time. See DUP for more details.RETAIN flagNot used.Remaining LengthThis is the length of the Payload. It can be a multibyte field. Variable header The variable header contains a Message ID because an UNSUBSCRIBE message has a QoS level of 1. See Message identifiers for more details. The table below shows an example format for the variable header with a Message ID of 10. Description76543210Message Identifierbyte 1Message ID MSB (0)00000000byte 2Message ID LSB (10)00001010 Payload The client unsubscribes from the list of topics named in the payload. The strings are UTF-encoded and are packed contiguously. Topic names in a UNSUBSCRIBE message are not compressed. The table below shows an example payload. Topic Name"a/b"Topic Name"c/d" The table below shows the format of this payload. Description76543210Topic Namebyte 1Length MSB (0)00000000byte 2Length LSB (3)00000011byte 3'a' (0x61)01100001byte 4'/' (0x2F)00101111byte 5'b' (0x62)01100010Topic Namebyte 6Length MSB (0)00000000byte 7Length LSB (3)00000011byte 8'c' (0x63)01100011byte 9'/' (0x2F)00101111byte 10'd' (0x64)01100100 Response The server sends an UNSUBACK to a client in response to an UNSUBSCRIBE message. 3.11. UNSUBACK - Unsubscribe acknowledgment The UNSUBACK message is sent by the server to the client to confirm receipt of an UNSUBSCRIBE message. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (11)DUP flagQoS levelRETAIN1011xxxxbyte 2Remaining length (2)00000010 QoS levelNot used.DUP flagNot used.RETAIN flagNot used.Remaining LengthThe length of the Variable Header (2 bytes). Variable header The variable header contains the Message ID for the UNSUBSCRIBE message that is being acknowledged. The table below shows the format of the variable header. bit76543210byte 1Message ID MSBbyte 2Message ID LSB Payload There is no payload. 3.12. PINGREQ - PING request The PINGREQ message is an "are you alive?" message that is sent from a connected client to the server. See Keep Alive timer for more details. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (12)DUP flagQoS levelRETAIN1100xxxxbyte 2Remaining Length (0)00000000 The DUP, QoS, and RETAIN flags are not used. Variable header There is no variable header. Payload There is no payload. Response The response to a PINGREQ message is a PINGRESP message. 3.13. PINGRESP - PING response A PINGRESP message is the response sent by a server to a PINGREQ message and means "yes I am alive". See Keep Alive timer for more details. Fixed header The table below shows the fixed header format: bit76543210byte 1Message Type (13)DUP flagQoS levelRETAIN1101xxxxbyte 2Remaining Length (0)00000000 The DUP, QoS, and RETAIN flags are not used. Payload There is no payload. Variable header There is no variable header. 3.14. DISCONNECT - Disconnect notification The DISCONNECT message is sent from the client to the server to indicate that it is about to close its TCP/IP connection. This allows for a clean disconnection, rather than just dropping the line. If the client had connected with the clean session flag set, then all previously maintained information about the client will be discarded. A server should not rely on the client to close the TCP/IP connection after receiving a DISCONNECT. Fixed header The fixed header format is shown in the table below. bit76543210byte 1Message Type (14)DUP flagQoS levelRETAIN1110xxxxbyte 2Remaining Length (0)00000000 The DUP, QoS, and RETAIN flags are not used in the DISCONNECT message. Payload There is no payload. Variable header There is no variable header. 4. Flows 4.1. Quality of Service levels and flows MQTT delivers messages according to the levels defined in a Quality of Service (QoS). The levels are described below:QoS level 0: At most once deliveryThe message is delivered according to the best efforts of the underlying TCP/IP network. A response is not expected and no retry semantics are defined in the protocol. The message arrives at the server either once or not at all. The table below shows the QoS level 0 protocol flow. ClientMessage and directionServerQoS = 0PUBLISH---------->Action: Publish message to subscribers QoS level 1: At least once deliveryThe receipt of a message by the server is acknowledged by a PUBACK message. If there is an identified failure of either the communications link or the sending device, or the acknowledgement message is not received after a specified period of time, the sender resends the message with the DUP bit set in the message header. The message arrives at the server at least once. Both SUBSCRIBE and UNSUBSCRIBE messages use QoS level 1. A message with QoS level 1 has a Message ID in the message header. The table below shows the QoS level 1 protocol flow. ClientMessage and directionServerQoS = 1DUP = 0Message ID = xAction: Store messagePUBLISH---------->Actions:Store messagePublish message to subscribersDelete messageAction: Discard messagePUBACK<---------- If the client does not receive a PUBACK message (either within a time period defined in the application, or if a failure is detected and the communications session is restarted), the client may resend the PUBLISH message with the DUP flag set. When it receives a duplicate message from the client, the server republishes the message to the subscribers, and sends another PUBACK message.QoS level 2: Exactly once deliveryAdditional protocol flows above QoS level 1 ensure that duplicate messages are not delivered to the receiving application. This is the highest level of delivery, for use when duplicate messages are not acceptable. There is an increase in network traffic, but it is usually acceptable because of the importance of the message content. A message with QoS level 2 has a Message ID in the message header. The table below shows the QoS level 2 protocol flow. There are two semantics available for how a PUBLISH flow should be handled by the recipient. They affect the point within the flow that the message is made available to the subscribers. The choice of semantic is implementation specific and does not affect the guarantees of a QoS level 2 flow. ClientMessage and directionServerQoS = 2DUP = 0Message ID = xAction: Store messagePUBLISH---------->Action: Store messageorActions:Store message IDPublish message to subscribersPUBREC<----------Message ID = xMessage ID = xPUBREL---------->Actions:Publish message to subscribersDelete messageorAction: Delete message IDAction: Discard messagePUBCOMP<----------Message ID = x If a failure is detected, or after a defined time period, the protocol flow is retried from the last unacknowledged protocol message; either the PUBLISH or PUBREL. See Message delivery retry for more details. The additional protocol flows ensure that the message is delivered to subscribers once only. Assumptions for QoS levels 1 and 2 In any network, it is possible for devices or communication links to fail. If this happens, one end of the link might not know what is happening at the other end; these are known as in doubt windows. In these scenarios assumptions have to be made about the reliability of the devices and networks involved in message delivery. MQTT assumes that the client and server are generally reliable, and that the communications channel is more likely to be unreliable. If the client device fails, it is typically a catastrophic failure, rather than a transient one. The possibility of recovering data from the device is low. Some devices have non-volatile storage, for example flash ROM. The provision of more persistent storage on the client device protects the most critical data from some modes of failure. Beyond the basic failure of the communications link, the failure mode matrix becomes complex, resulting in more scenarios than the specification for MQTT can handle. 4.2. Message delivery retry Although TCP normally guarantees delivery of packets, there are certain scenarios where an MQTT message may not be received. In the case of MQTT messages that expect a response (QoS >0 PUBLISH, PUBREL, SUBSCRIBE, UNSUBSCRIBE), if the response is not received within a certain time period, the sender may retry delivery. The sender should set the DUP flag on the message. The retry timeout should be a configurable option. However care must be taken to ensure message delivery does not timeout while it is still being sent. For example, sending a large message over a slow network will naturally take longer than a small message over a fast network. Repeatedly retrying a timed-out message could often make matters worse so a strategy of increasing the timeout value across multiple retries should be used. When a client reconnects, if it is not marked clean session, both the client and server should redeliver any previous in-flight messages. Other than this "on reconnect" retry behaviour, clients are not required to retry message delivery. Brokers, however, should retry any unacknowledged message. 4.3. Message ordering Message ordering can be affected by a number of factors, including how many in-flight PUBLISH flows a client allows and whether the client is single- or multi-threaded. For purposes of discussion, clients are assumed to be single-threaded at the point packets are written to and read from the network. For an implementation to provide any guarantees regarding the ordering of messages it must ensure each stage of the message delivery flows are completed in the order they were started. For example, in a series of QoS level 2 flows, the PUBREL flows must be sent in the same order as the original PUBLISH flows: ClientMessage and directionServer PUBLISH 1---------->PUBLISH 2---------->PUBLISH 3---------->  PUBREC 1<----------PUBREC 2<----------  PUBREL 1---------->  PUBREC 3<----------  PUBREL 2---------->  PUBCOMP 1<----------  PUBREL 3---------->  PUBCOMP 2<----------PUBCOMP 3<----------  The number of in-flight messages permitted also has an effect on the type of guarantees that can be made: With an in-flight window of 1, each delivery flow is completed before the next one starts. This guarantees messages are delivered in the order they were submitted. With an in-flight window greater than 1, message ordering can only be guaranteed within the QoS level. Appendix A - Topic wildcards A subscription may contain special characters, which allow you to subscribe to multiple topics at once. The topic level separator is used to introduce structure into the topic, and can therefore be specified within the topic for that purpose. The multi-level wildcard and single-level wildcard can be used for subscriptions, but they cannot be used within a topic by the publisher of a message.Topic level separatorThe forward slash (/) is used to separate each level within a topic tree and provide a hierarchical structure to the topic space. The use of the topic level separator is significant when the two wildcard characters are encountered in topics specified by subscribers.Multi-level wildcard The number sign (#) is a wildcard character that matches any number of levels within a topic. For example, if you subscribe to finance/stock/ibm/#, you receive messages on these topics: finance/stock/ibm finance/stock/ibm/closingprice finance/stock/ibm/currentprice The multi-level wildcard can represent zero or more levels. Therefore, finance/# can also match the singular finance, where # represents zero levels. The topic level separator is meaningless in this context, because there are no levels to separate. The multi-level wildcard can be specified only on its own or next to the topic level separator character. Therefore, # and finance/# are both valid, but finance# is not valid. The multi-level wildcard must be the last character used within the topic tree. For example, finance/# is valid but finance/#/closingprice is not valid.Single-level wildcard The plus sign (+) is a wildcard character that matches only one topic level. For example, finance/stock/+ matches finance/stock/ibm and finance/stock/xyz, but not finance/stock/ibm/closingprice. Also, because the single-level wildcard matches only a single level, finance/+ does not match finance. The single-level wildcard can be used at any level in the topic tree, and in conjunction with the multilevel wildcard. It must be used next to the topic level separator, except when it is specified on its own. Therefore, + and finance/+ are both valid, but finance+ is not valid. The single-level wildcard can be used at the end of the topic tree or within the topic tree. For example, finance/+ and finance/+/ibm are both valid. Topic semantics and usage When you build an application, the design of the topic tree should take into account the following principles of topic name syntax and semantics: A topic must be at least one character long. Topic names are case sensitive. For example, ACCOUNTS and Accounts are two different topics. Topic names can include the space character. For example, Accounts payable is a valid topic. A leading "/" creates a distinct topic. For example, /finance is different from finance. /finance matches "+/+" and "/+", but not "+". Do not include the null character (Unicode \x0000) in any topic. The following principles apply to the construction and content of a topic tree: The length is limited to 64k but within that there are no limits to the number of levels in a topic tree. There can be any number of root nodes; that is, there can be any number of topic trees. --- ═══════════════════════════════════════════ ## MQTT 3.1.1 规范 ═══════════════════════════════════════════ ### 16. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 2024032209182023下载 --- ═══════════════════════════════════════════ ## MQTT 5 ═══════════════════════════════════════════ ### 17. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5精要系列的第12部分。在第11部分中,我们探讨了MQTT 5中的增强身份验证,概述了其通过强大、灵活和更有效的身份验证过程来增强物联网设备与经纪人之间的安全性和信任的作用。在我们继续探索MQTT 5的广阔世界时,我们评估流控制。 MQTT 5中的流控制是什么?流控制是MQTT 5中引入的一项动态功能,旨在调节物联网设备与经纪人之间的消息流量,以实现高效稳定的通信。 物联网部署涵盖了各种设备类型。例如,嵌入在紧凑型传感器中的MQTT客户端在处理速度和存储能力方面与嵌入在高性能后端服务器中的客户端相比存在显着差异。因此,这些MQTT客户端在处理飞行消息的容忍水平各不相同。在这里,飞行消息指的是具有一级或二级服务质量等级等待确认的PUBLISH命令。 同样,物联网设备可能连接到多个MQTT经纪人,每个经纪人对来自MQTT客户端的飞行消息的管理都有不同的限制。为了无缝地管理MQTT客户端和经纪人之间的这些多样化条件,MQTT 5引入了流控制功能。 获取对MQTT协议的完美介绍。MQTT 5中的流控制如何工作?流控制功能通过客户端和经纪人之间的协商在连接期间建立飞行窗口来实现。这个过程涉及在CONNECT数据包中设置一个名为"接收最大值"的可选属性,表示客户端可以容纳的未经确认的PUBLISH消息的最大数量。经纪人以CONNACK数据包中的类似值进行回应。如果未指定该值,则使用默认值65535。"接收最大值""接收最大值" 流控制功能客户端和经纪人协商它们的接收最大值。 MQTT 5中流控制的优势是什么?流控制增强了用于涉及各种系统和设备的用例的动态消息流调整,促进了在多个团队或供应商合作的项目中的透明度和适应性。不再需要所有方预先建立飞行窗口。如果MQTT 5客户端发送的未经确认消息多于服务器接收最大允许的消息,经纪人将发送Reason Code 0x93(接收最大值超过)的DISCONNECT消息。这种灵活性允许客户端和经纪人发送的飞行消息少于相应的接收最大值允许的消息。 该怎么做,不该怎么做?实施“接收最大值”仍然是一个可选但有益的选择。客户端和经纪人都可以在连接初始化期间建立自己独特的飞行窗口。流控制旨在保持平衡的消息处理,防止任何参与方的过载。作为一项功能,流控制与MQTT 5的主要目标完美契合 - 增强透明度,促进灵活性的增加。结束我们的MQTT 5之旅MQTT 5引入了高级功能,如干净会话开始、负载格式指示符和主题别名,以优化连接和发布操作。订阅功能,如非本地发布、保留消息控制和共享订阅,已被添加,以促进更大的控制和效率在订阅者关系中。 此外,MQTT5试图适应现代物联网应用程序和大规模云平台的需求。它解决了在电力有限的远程设备上有效使用带宽和在不稳定网络上确保可靠性的协议需求。 值得注意的是,MQTT5还适用于一系列令人印象深刻的用例,从连接的汽车、制造系统和物流到企业聊天应用程序和移动应用程序。这个广泛的应用范围证明了它的灵活性和适应性,吸引了各种行业和环境。 鉴于这些重大改进,迁移到MQTT5提供了几个引人注目的好处。它在大规模系统中提供了更高的性能,更高效的设备通信,并增强了发布和订阅过程的控制。此外,它是一种更具适应性和弹性的解决方案,能够应对当今物联网应用程序和云平台的复杂需求。 MQTT 5是MQTT协议最丰富的更新版本,显著提高了可扩展性、效率和适应性。其先进的功能和能力使其成为各种行业物联网应用程序的理想选择,鼓励从以前的版本进行转变。 我们 希望这个全面的系列文章已经为您提供了有关MQTT 5新功能的广泛信息。 --- ### 18. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5要点系列的第11部分。在这个系列的第10部分中,我们深入探讨了MQTT 5中的主题别名概念。我们探讨了它在优化带宽使用和减少网络开销方面的作用,提供了宝贵的见解,以增强整体效率。在本文中,我们将涵盖增强身份验证。 现代物联网项目已经发展成为庞大而复杂的项目,特别是在强大的安全措施至关重要的情况下。这些庞大的项目通常涉及多个供应商和团队之间的合作。遵守国际公认的标准变得至关重要,以简化在这类项目中遇到的挑战。增强身份验证有助于确保符合这些标准。 实施挑战-响应身份验证通过将挑战-响应身份验证纳入您的MQTT 5实现,您可以访问行业标准的身份验证机制,例如Salted Challenge Response Authentication Mechanism(SCRAM)或Kerberos协议。这些广泛认可的协议通过添加一层验证来进一步增强您的物联网基础设施的安全性。 MQTT中的身份验证流程是什么?增强身份验证中的身份验证流程依赖于三种MQTT消息类型:CONNECT、CONNACK(已经存在于MQTT v3中)和新的MQTT v5 AUTH消息。客户端发送CONNECT消息,服务器发送CONNACK消息。这两种消息类型在每个身份验证过程中仅使用一次。另一方面,服务器和客户端都可以多次使用AUTH消息。 获取对MQTT协议的完美介绍。身份验证流程的核心围绕着两个消息属性展开:身份验证方法(由字节21标识)和身份验证数据(由字节22标识)。这些属性在涉及增强身份验证流程的每条消息上都进行了设置。 MQTT中的身份验证方法通过身份验证方法,客户端和服务器可以选择并描述达成一致的身份验证方法。它由通常用于标识SASL(简单身份验证和安全层)机制的方法字符串表示。例如,一些方法字符串的示例包括SCRAM与SHA-1的方法或Kerberos的方法。例如,SCRAM-SHA-1和GS2-KRB5。 身份验证方法为增强身份验证中的交换数据分配了重要意义,应在整个过程中保持不变,以确保一致性和完整性。 MQTT中的身份验证数据身份验证数据是在身份验证过程中使用的二进制信息。它通常涉及在多次迭代中传输加密的密钥或协议步骤。数据的具体内容在增强身份验证中采用的选择机制和正在使用的应用程序具体。 MQTT中增强身份验证的源代码示例在这段代码片段中,我们使用HiveMQ扩展SDK来实现增强身份验证。其目的是验证身份验证方法的支持并确定在两个AUTH消息交换之后连接的MQTT客户端的状态。 public class MyEnhancedAuthenticator implements EnhancedAuthenticator { public void onConnect(EnhancedAuthConnectInput input, EnhancedAuthOutput output) { final ConnectPacket connectPacket = input.getConnectPacket(); // 给定的身份验证方法是否受支持? if (authenticationMethodIsSupported(connectPacket.getAuthenticationMethod())) { // 客户端是否提供了有效的身份验证数据? if (validateClientAuthenticationData(connectPacket.getAuthenticationData())) { // 发送包含挑战的AUTH消息! output.continueAuthentication(prepareServerAuthenticationData()); return; } } // 身份验证失败并断开客户端。 output.failAuthentication(); } public void onAuth(EnhancedAuthInput input, EnhancedAuthOutput output) { final AuthPacket authPacket = input.getAuthPacket(); // 尝试验证响应。 if (validateClientAuthenticationData(authPacket.getAuthenticationData())) { // 允许客户端连接到服务器。 output.authenticateSuccessfully(); return; } // 身份验证失败并断开客户端。 output.failAuthentication(); } } 结论增强身份验证的重要性不容忽视。在一个互联设备不断增加重要性的世界中,安全通信的重要性得到了提升,MQTT 5迎难而上。这种先进的身份验证机制赋予组织保护其物联网基础设施、敏感数据和用户隐私的能力。在我们继续分享MQTT 5概念的过程中,在本系列的第12部分中,我们将重点讨论MQTT 5中的流控制。 --- ### 19. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5精要系列的第10部分。在我们在第9部分中讨论了请求-响应模式之后,我们现在将把注意力转向另一个可能产生重大影响的功能:主题别名。 什么是MQTT主题别名?主题别名是代替主题名称的整数值。它使您能够将冗长且经常使用的主题名称压缩为一个2字节的整数。这有助于在消息发布过程中减少消耗的带宽。发送方在PUBLISH消息中定义主题别名值,然后是主题名称。接收者随后会像处理任何其他PUBLISH一样处理此消息,建立主题别名(整数)和主题名称(字符串)之间的映射。随后发送到相同主题的PUBLISH消息可以仅带有主题别名,省略主题名称。 为什么在MQTT中使用主题别名?MQTT在您的网络中扮演着重要角色,其在维护设备与代理之间的稳定连接方面效率高。保持活动机制保证了客户端与代理之间连接的长期性,迅速检测到不稳定网络中可能发生的连接丢失。仅需每隔几分钟发送PING数据包 - 仅为两个字节 - 就能够使MQTT以最小的功率和带宽使用来维持这些连接。 这就带我们来到主题别名功能,它在涉及大量连接设备传输较小、频繁的消息的部署中特别有益。因此,让我们深入了解这个功能,看看它如何优化您的MQTT 5利用率。 如何使用MQTT主题名称?只要它们是消息的发起者,MQTT客户端和代理就可以为任何PUBLISH消息建立主题别名。同样,它们可以控制每个连接允许的主题别名数量。主题别名的上限,称为主题别名最大值,在连接建立阶段确定。 获取对MQTT协议的完美介绍。客户端在CONNECT数据包中指示其主题别名最大值,而代理则在CONNACK数据包中执行此操作。因此,客户端应仅使用从1到CONNACK数据包中的代理定义的主题别名最大值范围内的主题别名值。同样,代理应尊重来自CONNECT数据包的客户端定义的最大值范围从1到。 如果没有指定主题别名最大值,则默认值为0,有效地禁用了主题别名的使用。这确保了在您的MQTT部署中清晰的通信边界和对主题别名的精确控制。 MQTT主题别名的用例示例MQTT以其在客户端和代理之间有效维护TCP连接的轻量级通信协议而脱颖而出。其保持活动机制最小化了能源和带宽的使用,使用户能够建立经济高效、始终连接的设备部署。此外,它允许实时传送最小的数据点,例如测量数据,从而无需定期进行大容量数据传输 - 这是较重的数据传输技术的要求。 MQTT的这种内在效率在许多应用中都有用武之地,比如预测性维护,在这些应用中,通过实时传送小数据点可以增强服务的质量和响应速度。在这些情况下,详细的主题名称可能比实际数据有效载荷更大,而一个整数可以代表这个数据有效载荷。例如,一个主题名称可能描述了特定接线盒的当前功耗,有效载荷是一个单 独的整数值:"data/europe/germany/south/bavaria/munich/schwabing/box-32543y/junction/consumption/current" 主题别名主题别名可以用单个整数替代长而复杂的主题字符串。MQTT的主题别名功能在这些情况下变得尤为重要,它用单个整数替代了冗长和复杂的主题字符串。在实时发送众多小型消息以覆盖广泛主题名称的情况下,这种技术尤其有用,它提供了两个主要优势:它增强了性能,同时显著减少了网络流量。因此,主题别名成为您的MQTT 5工具库中的一个强大工具,优化数据传输和网络管理。 理解MQTT主题别名主题别名将UTF-8字符串主题名称替换为整数。主题别名到主题映射仅对于单个连接相关。此功能对代理和客户端是可选的。代理和客户端在连接建立期间协商支持这个功能的程度。如果希望使用这个功能,请确保您的代理和客户端实现支持主题别名。当正确使用时,主题别名可以显著影响您的业务案例的利润率。 结论主题别名提供了一种多功能的利用发布/订阅模型的方法。当不断发布消息到有限数量的主题,特别是在大量情况下,主题别名可以以高效的方式节省网络和计算资源。在下一篇文章中,我们将讨论增强的身份验证。 --- ### 20. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5要点系列的第9部分。在第8部分中,我们介绍了MQTT 5中的负载格式描述。在本文中,我们将重点介绍两个突出的元素:响应主题和关联数据。 在处理现代物联网项目的复杂性时,需要跨不同供应商和团队进行协作。随着MQTT成为物联网的卓越协议,增强的互操作性和系统透明性成为MQTT版本5蓝图中的主要需求。今天我们要深入探讨的特性通过提供一种标准解决方案,用于使用MQTT实现请求-响应模式,以满足用户的需求。 什么是MQTT中的请求-响应模式?MQTT根植于异步消息传递,采用发布-订阅范式。这个设计允许发送方和接收方独立运行,促进了一对多的关系。重要的是要理解,MQTT的请求-响应模式与同步的、基于一对一的协议(例如HTTP)从根本上不同。 在MQTT中,响应通常不会直接回答请求的“问题”。相反,请求会在接收方触发特定操作,而响应则会传达这个操作的结果。 听起来复杂吗?不要担心,一个具体的示例很快会让这一切变得清晰! 什么是MQTT 5中的响应主题?响应主题是一个可选的UTF-8字符串,包含在任何PUBLISH或CONNECT数据包中。如果响应主题中存在值,发送方将立即将相关的PUBLISH标记为请求。响应主题字段指示了消息接收者预期的响应主题。最初的PUBLISH(请求)和响应主题可以有多个或没有订阅者。理想情况下,原始的PUBLISH(请求)发送方应在发送请求之前订阅响应主题。 什么是MQTT 5中的关联数据?关联数据是后续的响应主题之后的可选二进制数据。它帮助请求的发送方识别后来接收到的响应与哪个特定的请求相关。关联数据允许原始请求发送方管理从多个接收者可能发送的异步响应。重要的是要注意,这些数据与MQTT代理无关,但用于标识发送方和接收方之间的关系。 MQTT 5中的响应信息是什么?为了促进透明的实现和改进标准化,MQTT 5规范引入了响应信息属性。通过CONNECT中的一个布尔字段,客户端可以请求代理发送响应信息。当设置为true时,代理可以在CONNACK数据包中发送一个可选的UTF-8字符串字段(响应信息),以传达预期的响应主题。 这个特性允许用户在代理上全局定义主题树的特定部分,所有表示他们打算在连接建立时使用请求-响应模式的客户端都可以访问这个部分。 MQTT 5中的端到端确认MQTT确保消息发送方和接收方完全解耦。在许多情况下,用例需要从预期的接收方那里获得消息接收的确认。例如,当通过命令打开智能家居的门时,发送方(通常是移动应用程序)希望知道消息何时接收以及命令的结果。 请求-响应模式在智能门上的示例例如,使用MQTT 5请求-响应功能,通过移动设备打开智能门的示例。 MQTT 5规范中包含请求-响应模式,主要是为了满足这些“业务确认”的需求。MQTT用户寻求在应用消息的发送方和接收方之间提供端到端确认的能力。通过直接将响应主题、关联数据和响应信息集成到协议字段中,我们显著增强了使用请求-响应模式进行应用程序开发的灵活性、动态性和透明性。 MQTT请求-响应工作流的源代码示例以下是展示HiveMQ MQTT客户端能力的快速代码片段,提供了MQTT中请求-响应模式工作流的味道。请注意,这不是一个完整的、可运行的示例。 您可以在GitHub上访问完整示例,并在我们的HiveMQ社区论坛中咨询任何实施问题。 // 请求方订阅响应主题 Mqtt5SubAck subAck = requester.subscribeWith() .topicFilter("job/client1234/result") .send(); // 请求方发布请求 Mqtt5PublishResult result = requester.publishWith() .topic("job") .correlationData("1234".getBytes()) .responseTopic("job/client1234/result") .payload(message.getBytes()) .send(); // 响应方订阅请求主题 Mqtt5SubAck subAck = responder.subscribeWith() .topicFilter("job") .send(); // 响应方在接收请求后发送响应 Mqtt5PublishResult result = responder.publishWith() .topic(publish.getResponseTopic().get()) .payload(msg.getBytes()) .correlationData(publish.getCorrelationData().get()) .send(); MQTT请求-响应中的关键要点以下是MQTT请求-响应的一些关键要点: MQTT中的请求-响应模式与同步的、基于客户端-服务器的协议(如HTTP)显著不同。 MQTT允许请求和响应的订阅者为多个、单个或甚至没有。 关联数据确保请求和响应之间的正确关联,提高消息跟踪的能力。 这种模式促进了“业务确认”功能的实现,提供了一种可扩展、动态和透明的解决方案。 在使用MQTT的请求-响应时要考虑的最佳实践在使用MQTT的请求-响应时,以下是一些最佳实践: 确保请求方在发送请求之前订阅相关的响应主题。 在响应主题中使用唯一的标识符以避免混淆。 确保响应方和请求方具有发布和订阅响应主题的必要权限。 为响应目的专门分配主题树的一个特定部分,并利用响应信息字段将其传递给客户端。 结论当我们探讨MQTT v5的变革性特性时,我们发现了协议演进的力量。这些增强功能,如请求-响应模式,不仅简化了现有的实践,还开启了应用程序开发中新的动态、透明和可扩展的领域。在第10部分中,我们将讨论主题别名的话题。 --- ### 21. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5基础教程系列的第8部分。在第7部分,我们探讨了共享订阅。在本文中,我们将专注于Payload Format Indicators(负载格式指示器),它们指定消息内容类型,确保更轻松、更高效的解析和系统之间的互操作性。 什么是MQTT中的Payload Format Indicator? Payload Format Indicator是任何包含负载的MQTT数据包的基本组成部分。这包括封装WILL消息或PUBLISH数据包的CONNECT数据包。这个可选的字节值有两种可能的设置:0表示“未指定的字节流”,而1表示“UTF-8编码的负载”。当没有提供Payload Format Indicator时,它会自动默认为0。 MQTT 内容类型 与Payload Format Indicator类似,Content Type也是可选的,并且可以包含在包含WILL消息或任何PUBLISH数据包的CONNECT数据包中。Content Type的值必须是一个UTF-8编码的字符串,用于标识负载的性质。当Payload Format Indicator设置为1时,理想情况下,您应该有一个MIME内容类型描述符(尽管这不是硬性要求)。只需一个有效的UTF-8字符串即可。 为什么需要描述负载格式? Payload Format Indicator和Content Type的联合使用有助于透明地描述任何应用程序消息的负载内容。这种能力为创建和定义各种负载格式的行业标准奠定了基础。MQTT协议专家认为,这种标准化是协议的自然发展。 在标题中包含负载内容描述对于个体部署非常有益,它确保了每条消息都在不深入负载本身的情况下被正确处理。根据内容类型,系统内的不同消息可能需要不同的解析方法。此外,在某些情况下,消息的持久性可能取决于负载的具体类型。由于内容类型的定义取决于用户设计,这一功能的潜在应用似乎是无限的。 总结 Payload Format Indicator用于区分负载是未定义的字节数组还是UTF-8编码的消息。当处理UTF-8编码的消息时,发送方可以使用内容类型来指定负载的性质。 这些功能为大规模系统以及潜在的整个行业之间的透明负载内容定义奠定了基础。随着对实际负载进行预解析的需求减少,正确的消息处理可以显著提高可扩展性。 尽管预计大多数用户将依赖已知的MIME类型来描述内容,但他们也可以使用任意的UTF-8字符串。 --- ### 22. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5基础教程系列的第7部分。在第6部分中,我们探讨了MQTT用户属性。在本文中,我们将深入探讨一个特别有趣的功能:共享订阅。 共享订阅是MQTT 5的核心功能,它允许多个MQTT客户端共享代理上的单个订阅。本质上,这个功能允许在多个客户端之间分发主题上的消息,从而改善了MQTT系统的负载均衡和容错性。 共享订阅:用v5填补MQTT的空白 MQTT 5经过精心设计,旨在弥合MQTT 3.1.1提供的功能与用户对物联网的期望之间的差距。通过集成备受期待的功能,如共享订阅、会话和消息到期间隔,MQTT 5有望在可预见的将来巩固MQTT作为物联网协议的地位。 MQTT共享订阅是如何工作的? 在标准的MQTT订阅中,每个订阅的客户端都可以获得发布到该主题的每条消息的副本。而使用共享订阅,共享同一个订阅的客户端会按顺序接收消息,这个过程有时被称为客户端负载均衡。单个主题的消息负载分布在所有订阅者之间。 MQTT客户端可以使用标准的MQTT机制订阅共享订阅。任何标准的MQTT客户端,例如Eclipse Paho,都可以在客户端上不需要任何修改的情况下参与其中。需要注意的是,共享订阅使用独特的主题语法进行订阅。 共享订阅使用以下主题结构: $share/GROUPID/TOPIC 共享订阅由3部分组成: 静态的共享订阅标识符($share) 组标识符 实际的主题订阅(可能包括通配符) 通过一个具体的示例来说明这种订阅:$share/my-shared-subscriber-group/myhome/groundfloor/+/temperature。 MQTT共享订阅在HiveMQ MQTT Broker中的工作原理如何? 共享订阅组可以在概念上被想象为一台虚拟的客户端,同时代表多个订阅者。HiveMQ会从组中选择一个订阅者,并将消息传递给该客户端。它通常使用轮询法来进行分发。以下图片演示了原理: 例如,HiveMQ部署中可能包含多个共享订阅组。这些组可以具有相同的订阅,但不同的组标识符。当发布者发布与特定主题匹配的消息时,每个组中都会选择一个唯一的客户端来接收消息。例如,以下情景是可能的: 在给定的情况下,我们有两个不同的组,每个组都包含两个在其共享订阅组中的订阅客户端。尽管这些组订阅相同的主题,但它们通过唯一的组标识符来区分。当发布者发出与特定主题相符的消息时,每个组中将选择一个客户端,仅选择一个客户端来接收消息。 MQTT 共享订阅使用案例 共享订阅有多种应用,特别是在高可扩展性的场景下。这些包括: 无法处理订阅主题负载的 MQTT 客户端的客户端负载均衡。 引入 MQTT 流的工作(后端)应用程序必须水平扩展。 优化传入发布的订阅者节点位置,以减少 HiveMQ 群集内节点流量。 传递语义使用 QoS 1 和 2,尽管没有必要对有序主题进行保证。 解决由于消息速率较高而导致的可扩展性瓶颈的热门话题 如何使用MQTT进行共享订阅? 让您的客户端使用共享订阅是一个简单的过程。以下是使用MQTT CLI完成此操作的示例。给定的命令行执行代码允许两个MQTT客户端订阅相同的订阅组和主题:执行了这些命令后,两个MQTT客户端现在都共享对“my-share-topic”(属于虚拟组“group1”的一部分)的订阅。在这种配置下,每个客户端分配了MQTT经纪上发布到主题“my-share-topic”的消息的一半。 mqtt sub -h broker.hivemq.com -t '$share/group1/my-share-topic' -i client1 -q 1 mqtt sub -h broker.hivemq.com -t '$share/group1/my-share-topic' -i client2 -q 1 请记住,MQTT客户端可以随时加入或离开订阅组。例如,如果第三个客户端决定加入该组,那么相关MQTT消息的分发将平均分配给所有三个客户端,每个客户端都将收到总量的三分之一。 使用共享订阅扩展MQTT订阅者 共享订阅为将后端系统与MQTT集成提供了一种简单的方法,特别是当无法使用HiveMQ的扩展系统或需要动态扩展时。使用共享订阅,您可以根据需要快速添加订阅者,以推送方式分发工作。 共享订阅对于扩展和负载平衡MQTT客户端非常有价值。此外,HiveMQ集群通过优化消息路由的内部优化,提供了额外的延迟和可扩展性优势。 结论 共享订阅提供了一种通过标准MQTT机制在各种MQTT订阅者之间分发消息的引人注目的方法。这个功能简化了实现MQTT客户端负载平衡的过程,无需对您的MQTT客户端进行任何专有的修改。这对于后端系统或可能迅速超出单个MQTT客户端的“热门主题”特别有益。 --- ### 23. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5基础知识系列的第6部分。在第5部分中,我们深入研究了改进的客户反馈和负面确认,揭示了它们如何增强MQTT系统的功能。在本文中,我们将为您介绍另一个突破性功能:用户属性。这个新功能将彻底改变您与MQTT的互动方式,创造出更加定制和富有见地的用户体验。 用户属性本质上是用户定义的属性,帮助您向MQTT消息添加元数据并传输额外的用户定义信息。 让我们深入了解。 MQTT 5已经经过精心制作,旨在填补MQTT 3.1.1提供的功能和用户对物联网的期望之间的差距。通过MQTT 5,我们确保MQTT继续作为物联网的卓越协议领导者,为未来数十年提供卓越的性能。 MQTT 5中的用户属性是如何工作的? 在MQTT 5中,用户属性基本上是直观的UTF-8字符串键值对。它们的实用性在于几乎可以附加到几乎每一类MQTT数据包上,唯一的例外是PINGREQ和PINGRESP。这种广泛应用包括各种控制数据包,如PUBREL和PUBCOMP。 用户属性的强大之处在于它们的潜力无限制 - 只要不超过最大消息大小,您可以使用无限数量的用户属性。这为丰富MQTT消息的元数据提供了广泛的可能性,促进了发布者、代理和订阅者之间信息的流畅传输。 从概念上讲,这个功能与HTTP中的标头的作用非常相似。正是这种相似性使用户属性能够在MQTT 5中注入可定制的复杂性水平,帮助创建一个不仅更加健壮,而且更适应用户需求的协议。 为什么在MQTT 5中引入了用户属性? MQTT 3的用户确定了两个重要的限制:协议的有限可扩展性和创建多供应商部署的复杂性。为了解决这些问题,MQTT 5引入了用户属性功能,有效地减轻了这些挑战。 用户属性提供了一种增强灵活性的途径,使用户能够在整个MQTT系统中传输几乎任何信息。这种能力确保MQTT协议不再限制而是促进了定制增强。这种功能的进步使用户能够增强标准协议功能,以满足其特定需求。 通过这样做,MQTT 5确保协议与其用户同步发展,促进了更大的适应性,并简化了多供应商部署的集成。 MQTT 5用户属性的实际用例示例 虽然用户属性功能的复杂性最初可能看起来很小,但跨整个MQTT生态系统传输元数据的机制的实际影响确实是巨大的。为了说明这种转型潜力,让我们深入探讨三种常见的用例,强调了像用户属性这样的功能的需求——这是用户在急切等待MQTT规范中引入这个组件的时候一再提出的需求。 在MQTT 5中使用用户属性保存负载元数据以节省资源 在MQTT作为连接不同团队或供应商开发的不同系统之间的连接器的环境中,负载结构的可变性非常普遍。客户端可以以许多格式传输数据,包括JSON、XML或诸如Protobuf等压缩格式。 MQTT 5引入用户属性的功能打开了附加元数据到消息的大门,封装了诸如用于编码负载的标记语言和版本等特定细节。这种元数据的提供消除了接收客户端,或在某些情况下,代理,解压负载并遍历一系列可能的解析器直到找到适当解析器的需要。 与这个繁琐的过程不同,每条消息都带有其解析信息,简化了解释并大大减少了整个系统的计算负载。这种有效的资源利用增强了MQTT网络的整体性能和速度,展示了用户属性的变革力量。 通过应用级别路由在MQTT 5中提高效率 由于其在数据传输和路由方面的高效能力,MQTT经常用作大规模数据处理和流式处理部署的基础。这些部署通常涉及大量的设备、系统和应用程序。不同的系统经常接收相同的消息,但用于不同的目的。例如,一个系统可能显示实时数据,而另一个系统可能将相同的数据存档以供长期存储。 在这种情况下,用户属性可以通过充当消息的附加应用级别时间戳来证明其价值。这个属性允许代理快速确定是否根据预定义的有效期不应将某些消息传递给特定子订阅者的子集。这个功能引入了一个额外的应用级别层,根据消息到期间隔进一步细化消息的相关性。 因此,MQTT 5中的用户属性不仅增强了系统的效率,还提供了更精细的控制水平,从而最大程度地提高了每个传输的消息的效用和相关性。 在复杂系统中使用用户属性进行透明的可追溯性 物联网部署的景观通常呈现出错综复杂的迷宫,各个系统并行运行。这种复杂性可能会模糊特定消息的来源或导致多层消息流不成功的因素。在MQTT 3.1.1框架下,没有机制使订阅者能够识别消息发布者的身份。尽管在1对1场景中将唯一标识符嵌入主题是一种可行的策略,但这种方法破坏了发布-订阅模型的几个关键优势。 在这方面,MQTT 5中引入用户属性功能标志着重大转变。这个创新性的添加使发布者能够轻松地包含相关的自我识别信息,例如客户端ID或发布操作的区域。重要的是,这些信息传递给所有消息接收者,而不需要任何额外的业务逻辑。 将关于发布者区域的信息纳入系统增强了系统的可追溯性,而将唯一的系统标识符附加到MQTT消息使得能够全面记录和跟踪从发送者到所有订阅者的整个消息流。有效实施这些标识符可以延伸到多个MQTT消息流,引入了前所未有的透明度和可追溯性。 这些能力打开了一个新的可能性领域,特别是对于业务关键的应用程序,如面向最终客户的高级付费服务,透明度和可追溯性变得不可或缺。 MQTT 5中用户属性的总结和其他信息 1.用户属性作为可以无缝添加到任何MQTT消息中的UTF-8字符串键值对。这种能力使它们成为MQTT协议的多才多艺和宝贵的补充。2.用户属性在增强MQTT用例方面的实施潜力几乎是无限的。它提供了一定程度的定制,允许许多创新的应用,无论是在功能还是范围上。3.跨多个系统和供应商的部署和项目可以利用此功能以保持一致性,并确保整个基础架构之间的无缝通信。4.我们为看到MQTT用户将如何利用这一看似简单但具有巨大影响的功能的潜力而感到兴奋。 MQTT 5中的用户属性代表了协议可扩展性和多功能性的重大进步,为未来的物联网应用程序开辟了令人兴奋的可能性。 --- ### 24. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5基础知识系列的第5部分。在第4部分中,我们深入探讨了MQTT会话到期和消息到期。我们揭示了这些功能如何增强物联网应用中的消息管理和效率,使MQTT 5更加灵活和高效。在本文中,我们将重点关注MQTT 5的增强客户反馈和负面确认(NACKs)。我们将剖析MQTT 5为代理确认客户而实施的这种方法,研究它们简化开发人员和运维团队工作的潜力,从而使协议更加健壮和高效。 谁需要更多的MQTT客户端反馈? 多年来,MQTT已经成为众多物联网项目的重要组成部分。正如本系列中所指出的,OASIS委员会在制定新的MQTT 5协议标准时充分考虑了实际协议用户的反馈。主要的抱怨之一是明显的不透明性,主要是由于不足的返回代码和有限的通信方式,导致代理无法向客户端传达特定的限制或情况。这个缺陷增加了调试复杂性,特别是在多供应商项目中。 无论是深入研究客户端断开连接的原因,检查为何消息无法到达其指定目标,还是在各个团队中保证MQTT客户端部署的一致性,MQTT 3的用户通常需要通过技术来增强基本协议功能。MQTT 5经过精心设计,旨在更高效、标准化地解决这些挑战,引入了以下功能。 MQTT 5的特定功能集 让我们专注于几个MQTT 5功能,通过代理提供更多透明度并允许中央系统控制。 MQTT 5中连接建立的反馈 使用MQTT 5版本,MQTT代理现在可以在连接建立时向MQTT客户端提供附加反馈。可以向连接确认数据包添加多种不同的属性,告诉客户端代理支持或允许客户端使用的功能。这些功能包括以下MQTT功能: 保留消息 通配符订阅 订阅标识符 共享订阅 主题别名 客户端可以使用的最高服务质量级别除了通知客户端已启用和已禁用的功能外,CONNACK数据包中的新属性还允许服务器向客户端反馈代理授予的限制。这些限制包括: 保持活动时间 会话到期间隔 最大数据包大小 客户端可以发送的最大主题别名数除了支持所有这些限制外,HiveMQ还允许您在服务器端为这些限制配置最大值,并禁用您用例中不需要的MQTT功能。 MQTT 5中更好的原因代码 在以前的版本中,即MQTT版本3.1和3.1.1中,可用原因代码的种类有限,只有五个与不成功操作相关的代码。然而,MQTT 5大幅增强了这个方面,提供了一组扩展的超过20个原因代码,专门用于不成功的情况。 此外,MQTT 5还引入了将原因代码集成到以前的版本中缺少此属性的数据包的可能性。这些数据包包括UNSUBACK、PUBACK、PUBREC、PUBREL、DISCONNECT和PUBCOMP。这一增强进一步增强了协议的透明性和故障排除效率,说明了MQTT 5所取得的进步。 通过MQTT 5引入具体原因字符串增强清晰度 尽管添加了额外的原因代码确实增强了对客户端的反馈质量,但这些代码通常不足以提供具体的上下文。这就是MQTT 5引入“原因字符串”概念的地方,规范中描述为“…为诊断而设计的人类可读字符串…” 原因字符串提供了开发人员和运维团队需要快速确定事件原因的全面上下文。本质上,原因字符串是一种专门设计用于诊断目的的人类可读字符串。这个有价值的工具有助于以原因代码本身无法提供的方式理解事件的细微差别。 但值得注意的是,原因字符串,尽管在开发和诊断中非常有用,但可以在的配置中禁用。这种灵活性适用于可能不希望暴露此类详细信息的情况。 MQTT 5中的服务器发送断开数据包 在MQTT 3.1和3.1.1中,当客户端超过代理定义的限制时,代理会通过突然关闭客户端的连接来作出响应。然而,这种行为不会向客户端直接提供有关连接终止原因的信息,这可能导致混淆和故障排除困难。 相反,MQTT 5通过引入服务器发送的断开数据包大大改进了这个过程。这允许代理在终止连接之前向客户端传递DISCONNECT数据包。每个服务器发送的断开数据包都包含一个原因代码和相应的原因字符串。这两个元素共同为客户端提供了全面的了解为何连接被断开的理由。 这种连接终止的简化方法不仅为客户端增加了清晰度,还大大简化了确定由代理发起的连接关闭背后原因的过程。MQTT 5中的这一显著增强显著提高了代理和客户端之间的通信透明度。 MQTT 5中的否定确认是什么 在MQTT 5中,通过增加否定确认,通信机制得到了很大的改进。现在,多个数据包类型和消息流可以用否定确认消息进行响应,增强了消息基础设施的整体反馈循环。 与MQTT 3不同,MQTT 5中的UNSUBACK数据包包含一个原因代码,告知客户端其UNSUBSCRIBE尝试的状态,提供清晰而有针对性的反馈。列举了几种潜在的失败原因,例如初始订阅不存在或客户端没有取消订阅的授权。 来自发布流的确认数据包,特别是PUBACK、PUBREL、PUBREC和PUBCOMP,也已经增强,可以发送否定确认消息。当服务器无法处理客户端发送的消息时,例如因为客户端没有发布到某个主题的必要授权,增强的确认数据包现在为客户端提供了所有必要的信息以适应和纠正这种情况,减少了联系运营或支持团队以了解问题的需要。这标志着在MQTT 5应用程序内保持高效和流畅的通信方面迈出了重要的一步。 MQTT 5:优化MQTT通信 MQTT代理,例如HiveMQ,允许您为上述限制的最大值设置服务器端最大值配置。这在多供应商项目中特别有用,在这些项目中,代理操作员可能无法直接控制MQTT客户端的设置。 为客户端改进的反馈大大简化了开发和运维团队的诊断过程。引入的透明性还改善了不同MQTT客户端和代理之间的互操作性。 了解MQTT 5的更多信息 MQTT代理,如HiveMQ,提供了允许服务器端最大值配置的优势,涉及到上述限制的最大值。这个功能在多供应商项目中尤其有价值,其中代理操作员可能无法直接控制MQTT客户端的设置。 值得注意的是,对于客户端的改进反馈大大简化了开发和运维团队的诊断过程。这种增强的反馈机制可以更快地解决问题,防止在MQTT系统中出现潜在的瓶颈。 此外,这些改进引入的透明性提高了不同MQTT客户端和代理之间的互操作性。这个特性对于创建强大而多功能的物联网生态系统至关重要,并进一步强调了MQTT 5在增强通信、调试和整体系统控制方面所取得的进展。 --- ### 25. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5基础知识系列的第4部分。在本系列的第3部分《MQTT 5:从MQTT 3.1.1升级的七个原因》中,我们阐述了MQTT用户升级到版本5的主要动机,强调了使MQTT 5成为有吸引力的升级的增强功能。在本文中,我们将专注于两个密切相关的功能:会话到期间隔和消息到期间隔。这些功能代表了MQTT 5中的关键改进,深入了解它们对于协议的最佳利用至关重要。 MQTT 5中的会话到期间隔和消息到期间隔是如何工作的? 让我们分别详细介绍和分析这两个重要的到期间隔功能。 MQTT 5中的会话到期间隔 会话到期间隔是客户端在连接(CONNECT)数据包阶段设置的参数,以秒为单位指定。此参数指示代理保留客户端会话信息的持续时间。如果此间隔设置为零,或者CONNECT数据包未指定到期值,那么一旦客户端的网络连接终止,会话数据将立即从代理中删除。值得注意的是,最大的会话到期间隔是(4,294,967,295),允许离线会话在客户端断开连接后延续超过136年。 MQTT 5中的消息到期间隔 在MQTT 5中,客户端可以为每个PUBLISH消息设置一个唯一的消息到期间隔,以秒为单位。这个间隔确定了代理保留PUBLISH消息以供与主题匹配但当前离线的订阅者的持续时间。如果未定义间隔,代理必须无限期地保留匹配但断开连接的订阅者的消息。此外,如果在PUBLISH消息中选择 “retained=true” 选项,则该间隔还决定了消息在特定主题上保留的时间长度。 MQTT 5的会话到期间隔 MQTT 5中的会话到期间隔巧妙地同时满足了两个关键需求。早期版本的MQTT只提供了一个根据规范定义的删除持久会话的途径:要删除一个持久会话,必须使用与要丢弃的会话相同的客户端ID连接,并将标志设置为cleanSession=true。 考虑一些IoT设备永远不会重新连接的情况,原因可能是因为已经报废、损坏,或者因为在负载测试后未进行适当的清理而留下的会话。这些残留会话可能对代理的持久性造成不必要的负担。MQTT 5的会话到期间隔功能应运而生。这个直观的功能使用户能够指定一个合理的持续时间,之后代理会自动清除空闲会话,释放宝贵的资源。 除了这种自动清理功能之外,会话到期间隔还极大地简化了会话状态管理。Ian Craggs提供了两个示意图,显示了状态转换复杂性的降低。这种可视化呈现强调了这个新功能如何有助于简化状态转换并增强用户效率。 MQTT 5的消息到期间隔 与会话到期的间隔类似,消息到期的间隔始于对自动维护机制的需求。考虑到众多的IoT设备,比如设计用于长时间断网的连接汽车。MQTT通过持久会话和消息队列为这些情况提供了生命线。 为离线设备制定的消息存储在代理上,等待设备恢复连接以便传递。在大规模部署中,连接的设备数量可能升级到数千甚至数百万,因此对于每个客户端单独限制离线消息队列至关重要。 与IoT设备相关的消息的相关性的持续时间可能会出现显著的波动。以连接汽车为例:交通更新仅在短时间内保持相关性。但是,当我们考虑到空中固件升级时,即使汽车在数周之内保持离线,也需要执行这些 升级。 MQTT 5中的消息到期间隔正好是管理这些不同时间范围的完美工具,增加了协议的多功能性。 通过为具有有限相关性窗口的消息分配一个最佳的消息到期间隔,并为永久相关性的消息保留无到期时间,我们确保了代理资源的有效利用,以供可能离线相当长时间的客户端使用。这种策略还可以在重新连接时免除客户端被淹没在无关消息中。 对于保留的消息,消息到期间隔的操作方式类似,确保这些消息只发送给新的订阅者,以在指定的时间段内传递。 然而,需要注意的一个关键方面是,当客户端的会话到期时,为该客户端排队的所有消息也会与会话的到期一起过期,而不考虑它们各自的消息到期状态。这一“GOTCHA”是MQTT协议中会话及其排队消息之间相互关联性的重要提醒。 在使用MQTT 5的会话到期间隔和消息到期间隔时的重要提示以下是一些重要信息: 会话到期间隔和消息到期间隔都对MQTT代理上的资源管理起到了关键作用。回顾过去,许多MQTT 3用户表达了对到期功能的需求。HiveMQ回应了这一需求,在我们的MQTT平台中引入了会话和消息到期作为补充功能,这早于它们在MQTT 5中的标准化。MQTT 3 CONNECT数据包中的cleanSession=true的等价物在MQTT 5中是sessionExpiry=0(或不存在)和cleanStart=true。同样,MQTT 3 CONNECT数据包中的cleanSession=false在MQTT 5中的对应项是sessionExpire值大于零,再加上cleanStart=false。MQTT代理,在服务器端提供了配置这些到期间隔的最大值的功能。在多供应商项目中,特别是当代理操作员可能无法控制MQTT客户端设置时,这个功能非常方便。 MQTT 5的出现引入了一系列旨在提高协议的可用性、灵活性和效率的新功能。会话到期间隔和消息到期间隔是这一点的最佳例证,它们是资源管理的宝贵工具,确保您的MQTT代理的顺畅运行。这两个功能都真正体现了MQTT标准对用户需求和挑战的响应,展示了它对于用户的需求和挑战的响应。 --- ### 26. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网(IoT)在过去的十年中迅速发展,MQTT已成为无缝高效通信的标准协议。随着IoT系统规模和复杂性的增长,MQTT协议也在不断发展以满足这些需求。在这个背景下,MQTT 5升级引入了显著的改进,以满足现代IoT应用程序不断扩展的需求。 在本文中,我们将探讨为什么您的企业或开发团队应该考虑从 MQTT 3.1.1升级到 MQTT 5。 为什么要从 MQTT 3升级到 MQTT 5? MQTT 5代表了MQTT协议的实质性增强,它是根据MQTT用户的宝贵意见开发的。它包括了现代IoT应用程序所需的功能,专为基于云的部署量身定制。这些改进增强了系统的弹性,可靠地处理关键消息的错误管理,并促进了将MQTT消息无缝集成到现有计算框架中。 在本文中,我们提出了公司或开发团队应考虑升级到 MQTT 5的七个理由,包括: 更好的错误处理,实现更强大的系统MQTT 5极大地增强了错误处理机制,有助于系统的稳定性和可靠性。一个显著的引入是会话和消息到期功能。这允许开发人员为每个消息和会话设置定义的时间限制。如果消息在此时间范围内未传递,它将被自动删除。这个功能特别有用,可以确保网络延迟或中断不会导致将过时或无关的命令传递给IoT设备。 MQTT 5 在提供更强的可扩展性方面优于 MQTT 3在不断增长的IoT网络世界中,可扩展性是一个关键需求。MQTT 5通过标准化共享订阅来解决这个问题。这允许多个MQTT客户端实例在代理上共享相同的订阅。这是一个强大的功能,用于在云集群上部署负载平衡的MQTT客户端。这种可扩展性使MQTT 5成为具有大规模部署的企业以及计划扩展其IoT系统的企业的坚实选择。 MQTT 5在提供更大的灵活性和更容易集成方面优于 MQTT 3MQTT 5推出了协议属性,将定制化提升到了一个新水平,允许将键值属性添加到MQTT消息的标头中。这意味着应用程序特定的信息可以直接包含在每条消息中,增强了这些消息的处理。例如,可以将包含发送客户端的唯一标识符或设备平台的固件版本的元标记添加到消息标头中,以便接收方进行分析和处理。 另外,MQTT 5通过引入有效载荷格式指示符来简化接收方的处理过程。现在更容易区分二进制或文本数据,因为MQTT 5包括了一种 MIME 风格的内容类型描述符。这个功能对于各种应用都提供了巨大的价值。考虑一下,一个收费公路控制系统正在传输车牌图像以进行图像识别处理。相比之下,其他消息可能需要不同的处理方式,例如包含位置坐标的消息。通过指定格式,MQTT 5确保高效和适当地处理各种数据类型。 MQTT 5 作为IoT标准的优势凭借其丰富的功能集,MQTT 5已经巩固了自己在各种IoT用例中的地位,成功解决了先前版本的限制。我们预计在未来几年中MQTT将在各个行业迎来指数级的增长,这暗示了MQTT即将成为普遍IoT标准的前景。 MQTT 5未来趋势通过解决MQTT 3的限制,MQTT 5为IoT应用程序的未来增强铺平了道路。其灵活和强大的功能使其适应未来技术趋势,确保您的IoT系统保持当前并为未来的发展做好准备。 MQTT 5与其前身的兼容性 MQTT 5的一个实际优势是它与其前身的兼容性。它支持 MQTT 3.1和 MQTT 3.1.1的功能,允许混合使用 MQTT 3和 MQTT 5客户端。这使得迁移过程变得无缝,使组织能够逐渐过渡到 MQTT 5而不会干扰现有的IoT运营。 MQTT 5 在提供改进的功能方面优于 MQTT 3在本节中,我们深入探讨了MQTT 5的一系列增强功能。从通过否定确认来增强系统的健壮性,到通过用户属性实现定制化,再到通过主题别名提高效率,MQTT 5极大地强调了可用性、灵活性和性能。此外,MQTT 5引入了有效载荷格式指示符,以简化不同数据类型的数据处理。让我们详细探讨这些改进:否定确认为了进一步增强系统的健壮性,MQTT 5引入了否定确认的概念。代理可以在预定义的条件或限制下拒绝特定消息,例如超过最大消息大小、最大服务质量(QoS)或使用不支持的功能。这一积极措施防范了可能开始发送错误或恶意消息的MQTT客户端,显著增强了整个系统的安全性。 主题别名以提高效率在具有复杂主题结构的大型系统中,主题字符串可能变得很长,增加了网络和处理负载。MQTT 5引入了主题别名,允许您将这些长主题字符串替换为整数值。这可以大大减少网络和处理负载的需求,从而提高系统的效率和性能。 用户属性以实现定制化MQTT 5通过引入协议属性进一步实现了定制化。这允许开发人员将键值属性添加到MQTT消息的消息标头中。这种定制化水平使您能够在每条消息中包含特定于应用程序的信息。这些数据可以用于丰富消息处理和集成,使开发人员在应用程序上具有更多的灵活性和控制。 有效载荷格式指示符鉴于IoT应用程序中多种数据类型,拥有一种简化数据处理的机制至关重要。MQTT 5满足了这一需求,引入了有效载荷格式指示符。这些指示符标识有效载荷是二进制还是文本,并包括 MIME 风格的内容类型。这有助于提高数据处理效率,并使系统更适应各种数据用例。 结论:MQTT 5 - IoT通信的变革者MQTT 5代表了IoT通信的一大步。它不仅仅是一个小的升级,它巧妙地解决了以前的不足,并充满了强大的功能。对于现代IoT应用程序来说,它是一个不可或缺的工具。MQTT 5不仅仅是一个好选择,它是您IoT应用程序的一个引人注目的选择,准备将您带入IoT的未来。 --- ### 27. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT(Message Queuing Telemetry Transport)是一种通信协议,通过跨多个部署连接众多受限设备,构建了庞大的连接系统和独立设备网络。MQTT在各个领域的广泛应用,从联网汽车、制造系统、物流到企业聊天应用程序和移动应用程序,都刺激了对其进一步发展的需求。MQTT 5 应运而生,承诺提供一系列令人兴奋的新功能和改进。 在这个由 12 部分组成的 MQTT 5 要点系列中,我们将深入探讨 MQTT 5 的各个方面。该系列将揭示从协议的基础变更到用户属性、共享订阅、有效负载格式描述、请求-响应模式、主题别名、增强身份验证和流控制等主题。在本系列结束时,您将全面了解 MQTT 5 对物联网的实际影响,以及它如何通过其优势增强物联网解决方案的性能。在本文中(第 1 部分),我们将提供 MQTT 的起源和演变的高级概述。 在深入研究 MQTT 5 之前,如果您对 MQTT 不太熟悉或需要复习,我们建议您查看 MQTT Essentials 系列。这将有助于您更好地理解 MQTT 5 中引入的改进和根本性变化。 MQTT的起源与演变 为了理解 MQTT 5,首先让我们回顾一下 MQTT 的起源和演变。MQTT 协议诞生于上世纪90年代末,由IBM的Andy Stanford-Clark和Cirrus Link的Arlen Nipper创建。最初,MQTT被设计用于监测卫星网络上的石油和天然气管道。MQTT 的设计注重开放性、简洁性和易于实现。因此,MQTT 成为一种超轻量级协议,旨在节省网络带宽和设备资源,以确保数据的可靠传输。它的设计允许数千台设备与单个 MQTT 服务器连接,这使得它非常适用于受限制的环境,尤其是在网络带宽有限、延迟较高的物联网生态系统中。 MQTT 5 的设计目标 MQTT 的演进工作由 OASIS 技术委员会(TC)负责,他们面临着一个复杂的挑战,即如何在不增加复杂性或降低易用性的情况下,添加长期期望的功能。他们的目标是提高性能和可扩展性,同时确保协议保持易用性。MQTT 5 引入了一系列激动人心的新功能,以满足不断增长的物联网需求。 MQTT 5 的重大改进和新功能 MQTT 5 的关键目标之一是提高其处理大规模系统的能力。MQTT 3.1.1 曾经展示了其在物联网协议中的独特可扩展性和有状态性,HiveMQ 的企业 MQTT 平台实现了 200 亿个并发连接,标志着一个重要的里程碑。MQTT 5 在这一传统基础上构建,简化了 MQTT 服务器扩展到处理大量并发连接客户端的过程。 MQTT 5 引入了增强的身份验证机制,提供了更强大的安全框架。在当今世界,网络攻击风险时刻存在,因此 MQTT 5 允许用户选择更复杂的加密算法和密钥管理技术,以保护设备和数据的安全。 另一个重大改进是引入了共享订阅功能,允许跨多个客户端实例对消息进行负载平衡。这确保了消息管理的高效性,特别是在涉及大量设备同时传输数据的场景下。 此外,MQTT 5 还引入了消息属性的概念,允许在每条消息中包含额外的元数据,如时间戳、位置信息或设备状态,这在提供数据上下文方面非常有用。 总之,从 MQTT 3.1.1 到 MQTT 5 的过渡不仅仅是版本号的升级,更是协议功能的重大飞跃,涵盖了多个改进领域。其结果是一个更强大、更可靠和可扩展的协议,更适合满足现代物联网应用程序的需求。 结论 MQTT 5 代表了物联网通信协议的一次革命性进步,以满足不断增长和演变的物联网需求。了解 MQTT 5 的改进和新功能对于确保物联网系统的性能和可靠性至关重要。因此,开发人员、系统集成商和最终用户都应密切关注这些变化,以充分利用这一强大的物联网通信协议,为现代物联网应用提供最佳解决方案。 MQTT 的演进不会止步于 MQTT 5。MQTT 技术委员会仍在研究更多增强功能和特性,以确保 MQTT 在不断发展的物联网领域中保持相关性和强大性。这一持续发展的承诺将确保 MQTT 继续发挥重要作用,助力物联网生态系统的不断增长和进步。 --- ### 28. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当谈到 MQTT 5 时,其中一个最令人激动且具有革命性意义的特性是能够在 MQTT 头部中包含自定义键值属性。这个特性可能会从根本上改变许多 MQTT 部署的方式。与其他协议,例如 HTTP,类似,MQTT 客户端和代理现在可以添加无限数量的自定义或预定义头部来携带元数据。这些元数据具有很大的灵活性,可以根据特定的应用数据进行定制。而预定义的头部主要用于执行许多新的 MQTT 功能。 此外,在 MQTT 数据包中现在包含了原因代码,它们用于表示协议错误的具体情况。这些原因代码通常出现在确认数据包上,它们有助于解释错误情况,并有可能帮助客户端和代理制定补救措施。这些原因代码的范围广泛,从"配额已超出"到"协议错误"等各种情况。客户端和代理需要一起解码和理解这些新增的原因代码,从而丰富了 MQTT 的整体体验。 当我们谈论自定义键值属性和原因代码时,现在让我们来探讨 MQTT 如何处理不支持的功能以及如何使用 CONNACK 返回代码来做出响应。 如何使用 MQTT 5 中的预定义头部来响应不支持的功能? 随着 MQTT 的普及,各种公司提供了各种 MQTT 软件、库或系统。然而,由于不完全遵循 MQTT 规范,某些功能可能无法完全实现,例如 QoS 2、保留消息或持久会话。为了解决这些问题,MQTT 5 引入了一个巧妙的解决方案。它允许那些功能不完整的软件、库或系统(通常在 SaaS 提供中很常见)告知代理它们无法支持某些功能。然后,客户端有责任确保不使用这些不受支持的功能。代理在响应客户端的 CONNECT 数据包时,通过 CONNACK 数据包中的预定义头部来传达对特定功能的不支持。这些头部还可以通知客户端它们无权使用某些功能。 在 MQTT 5 中,可以使用以下预定义头部来指示未实现功能或未经授权的客户端使用: 预定义头部 Retain Available:是否可用于保留消息? 预定义头部 Maximum QoS:允许客户端发布消息或订阅主题的最大 QoS 预定义头部 Wildcard Available:是否可以使用通配符进行主题订阅? 预定义头部 Subscription identifiers available:MQTT 客户端是否可用订阅标识符 预定义头部 Shared Subscriptions available:MQTT 客户端是否可用共享订阅 预定义头部 Maximum Message Size:定义 MQTT 客户端可使用的最大消息大小 预定义头部 Server Keep Alive:服务器支持的个别客户端的保活间隔 这些返回代码代表了表达各个 MQTT 客户端权限的重要方法。然而,这一新功能带来了某种平衡:MQTT 客户端必须独立实现对这些代码的解释,并确保应用程序开发人员避免使用代理不支持或客户端没有权限使用的功能。对于那些想要维护严格规范 MQTT 部署的人来说,HiveMQ 完全符合 MQTT 5 的所有功能,从而确保这些自定义头部只会在管理员的决策下用于设置部署中的权限。 增强的会话管理:从清除会话到 MQTT 5 中的“清除启动” 在 MQTT 3.1.1 中,"清除会话"是一个显著的特性,但在 MQTT v5 中已经被"清除启动"所取代。在 MQTT 3.1.1 中,客户端使用"清除会话"功能,根据连接到代理时是否有临时连接或未订阅消息。在连接到代理后,客户端需要发送一个 CONNECT 数据包,其中包括清除会话标志,它可以启用或禁用。如果启用该标志,它表示向代理发出请求,在底层 TCP 连接断开或客户端决定与代理断开连接时,应丢弃所有客户端数据。此外,如果代理有关联到客户端标识符的先前会话,则清除会话 CONNECT 数据包将迫使代理丢弃先前的数据。 MQTT 5 引入了清除启动选项,由 CONNECT 消息中的清除启动标志表示。通过这一标志,代理会放弃任何先前的会话数据,从而启动新的会话。但是,当 TCP 连接在客户端与服务器之间关闭时,会话并不会自动清除。为了在断开连接后触发会话删除,必须将新的头部字段"会话过期间隔"设置为 0。这种修改的清除启动功能增强并简化了 MQTT 的会话处理,相对于之前的"清除会话"/"持久会话"概念,提供了更多的灵活性和更容易的实施。在 MQTT 5 中,会话会保留,除非将"会话过期间隔"设置为 0。会话的删除要么在间隔超时后发生,要么在客户端使用清除启动重新连接时发生。 MQTT 5 中的 AUTH 数据包是什么? 在一个令人激动的发展中,MQTT 5 引入了一种新的数据包类型:AUTH 数据包。这个数据包在实施非传统身份验证机制方面至关重要,我们预计它将在生产环境中发挥关键作用。我们将在另一篇文章中详细讨论其确切语义。 需要理解的关键是,这种新型数据包可以在建立连接后由代理和客户端分发。它允许使用复杂的挑战/响应身份验证方法,例如在 SASL 框架中概述的 SCRAM 或 Kerberos,同时也与先进的 IoT 身份验证方法(如 OAuth)兼容。重要的是,AUTH 数据包使得 MQTT 客户端可以在不需要终止连接的情况下重新进行身份验证。 MQTT 5 如何利用 UTF-8 字符串对增强通信? 为了容纳自定义头部,MQTT 引入了一种新的数据类型,即 UTF-8 字符串对。简而言之,字符串对是一种键-值结构,其中键和值都是字符串数据类型。目前,这种数据类型主要用于自定义头部。 这个新增的数据类型扩展了 MQTT 在传输中使用的数据类型的范围,总共包括七种: 位 两字节整数 四字节整数 UTF-8 编码字符串 可变字节整数 二进制数据 UTF-8 字符串对 对于大多数应用程序用户来说,二进制数据和 UTF-8 编码字符串仍然是 MQTT 库 API 中的首选数据类型。然而,随着 MQTT 5 的引入,预计 UTF-8 字符串对将会更频繁地使用。虽然用户可能不会直接看到其他数据类型,但它们在 MQTT 客户端库和代理中用于构建有效的 MQTT 数据包。 MQTT 5 如何通过双向 DISCONNECT 数据包简化通信? 在 MQTT 3.1.1 中,客户端可以在关闭底层 TCP 连接之前发送一个 DISCONNECT 数据包,以优雅地终止连接。然而,在 MQTT 代理通知客户端需要关闭 TCP 连接的情况下,这个版本存在一个问题。这个问题在新的协议版本中得到了解决。 在增强版 MQTT 中,代理被授权在断开套接字连接之前传输 DISCONNECT 数据包。这一规定使客户端能够理解断开连接的原因,并相应地制定适当的响应。虽然代理没有义务披露确切的原因(例如,出于安全原因),但这个功能有助于开发人员,因为它提供了有关代理终止连接的原因的有价值的信息。 另一个有价值的补充是 DISCONNECT 数据包现在可以携带原因代码,从而简化了揭示断开连接原因的过程,例如在权限无效的情况下。 在 MQTT 5 中对 QoS 1 和 2 进行了改进:取消了对健康连接的消息重传 MQTT 使用持久的 TCP 连接(或具有相同保证的类似协议)进行底层传输。强大的 TCP 连接确保了双向连接,以确保所有客户端或代理发送的 MQTT 数据包都将在另一端接收,并且只接收一次并按顺序发送。这意味着客户端或代理发送的所有 MQTT 数据包都将在另一端接收。在消息在传输过程中断开连接时,QoS 1 和 2 确保消息通过多个 TCP 连接传递。 在 MQTT 3.1.1 协议下,即使 TCP 连接正常,也允许重新传输 MQTT 消息。在实际中,这常常是有害的,可能会导致已经负载繁重的 MQTT 客户端超载。考虑这样的情况:一个 MQTT 客户端需要 11 秒来处理从代理接收的消息,并在处理后发送确认数据包。如果代理在 10 秒超时后重新传输消息,实际上并没有什么好处。这种方法只会消耗宝贵的带宽,并进一步加重 MQTT 客户端的负担。 随着 MQTT 5 的出现,对于健康的 TCP 连接,无论是代理还是客户端,都不允许重新传输 MQTT 消息。 然而,当 TCP 连接断开时,代理和客户端必须重新发送未被确认的数据包。因此,对于 QoS 1 和 2,在 MQTT 5 中仍然具有相同的重要性,就像在 MQTT 3.1.1 中一样。 如果您的用例依赖于重新传输数据包(例如,如果您的实现在某些情况下未能确认数据包),我们建议在升级到 MQTT v5 之前重新评估这种策略。 MQTT 5 如何简化身份验证? 在 MQTT 3.1.1 协议中,当 MQTT 客户端在 CONNECT 数据包中使用密码时,需要提供用户名。这对于某些不需要用户名的用例可能不太方便,例如使用 OAuth 进行身份验证和授权的情况,其中关键信息包含在密码字段中。在 MQTT 5 中,该协议引入了更精细的处理令牌的方式,例如通过 AUTH 数据包。但是,仍然可以在不提供用户名的情况下使用 CONNECT 数据包的密码字段。这个调整提供了一种更简化和直接的身份验证方法,特定情况下非常方便。 总结 虽然 MQTT 协议的核心保持相对不变,但在表面下进行了微妙的改进,为这一广泛采用的 IoT 协议的第 5 版奠定了基础。对于使用 MQTT 库的用户来说,这些修改可能似乎很小,不会从根本上改变 MQTT 的使用方式。然而,对于在 MQTT 库和代理上工作的开发人员来说,这些变化,特别是与协议细节相关的变化,都是关键的,并需要关注。 --- ═══════════════════════════════════════════ ## MQTT 5 规范 ═══════════════════════════════════════════ ### 29. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT协议5.0中文版 最新版本: v0.0.1 2018-05-18 概述 MQTT是一个客户端-服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。 MQTT协议5.0版本在3.1.1版本的基础上增加了会话/消息延时功能、原因码、主题别名、in-flight流控、属性、共享订阅等功能,增加了用于增强认证的AUTH报文。 MQTT协议5.0中文版 OASIS标准 2017年10月26日 规范链接 (Specification URIs) 当前版本(This version): http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd02/mqtt-v5.0-csprd02.docx (Authoritative) http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd02/mqtt-v5.0-csprd02.html http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd02/mqtt-v5.0-csprd02.pdf 以前的版本(Previous version): http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd01/mqtt-v5.0-csprd01.docx (Authoritative) http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd01/mqtt-v5.0-csprd01.html http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd01/mqtt-v5.0-csprd01.pdf 最新版本(Latest version): http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.docx (Authoritative) http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.pdf 技术委员会(Technical Committee): 结构化信息标准促进组织MQTT技术委员会 主席(Chairs): Brian Raymor (brian.raymor@microsoft.com), Microsoft Richard Coppen (coppen@uk.ibm.com), IBM 编辑(Editors): Andrew Banks (Andrew_Banks@uk.ibm.com), IBM Ed Briggs (edbriggs@microsoft.com), Microsoft Ken Borgendale (kwb@us.ibm.com), IBM Rahul Gupta (rahul.gupta@us.ibm.com), IBM 相关文档(Related work): 本规范代替: MQTT协议3.1.1版本。编辑是Andrew Banks和Rahul Gupta,发布于2014年10月29日,OASIS标准: < http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html>. 本规范与此有关: MQTT和NIST网络安全框架1.0版。 编辑是杰夫·布朗和路易·菲利普·拉穆勒。最新版本: http://docs.oasis-open.org/mqtt/mqtt-nist-cybersecurity/v1.0/mqtt-nist-cybersecurity-v1.0.html. 摘要 (Abstract) MQTT是一个客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,因此易于实现。这些特点使得它对很多场景来说都是很好的选择,包括受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT),这些场景要求很小的代码封装或者网络带宽非常昂贵。 本协议运行在TCP/IP,或其它提供了有序、可靠、双向连接的网络连接上。它有以下特点: 使用发布/订阅消息模式,提供了一对多的消息分发和应用之间的解耦。 消息传输不需要知道负载内容。 提供三种等级的服务质量: “最多一次”,尽操作环境所能提供的最大努力分发消息。消息可能会丢失。例如,这个等级可用于环境传感器数据,单次的数据丢失没关系,因为不久之后会再次发送。 “至少一次”,保证消息可以到达,但是可能会重复。 “仅一次”,保证消息只到达一次。例如,这个等级可用在一个计费系统中,这里如果消息重复或丢失会导致不正确的收费。 很小的传输消耗和协议数据交换,最大限度减少网络流量。 异常连接断开发生时,能通知到相关各方。 状态 (Status) 本文档最后由OASIS成员在上面标示的日期最终修订或批准。批准的级别也在上面列出了。如果要查看本文档最新的修订版请检查上面的 最新版本 位置。技术委员会产生的其它修订版和其它技术文档都列在这里:https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=mqtt#technical 。 技术委员会成员对本规范的评论应该发送到技术委员会的邮件列表。其他人应该发送评论到技术委员会的公共评论列表,方法是点击技术委员会网站的 发送评论 按钮,网页地址是 https://www.oasis-open.org/committees/mqtt/ 。 本规范草案的发布基于 OASIS知识产权政策 的 Non-Assertion 模式。关于实现本规范必不可少的任何专利是否已公开,以及其它的专利许可条款相关的信息,请参考技术委员会网站的知识产权部分(https://www.oasis-open.org/committees/mqtt/ipr.php)。 引用格式(Citation format): 引用此规范时应该使用下面的引文格式: [mqtt-v5.0] MQTT Version 5.0. Edited by Andrew Banks, Ed Briggs, Ken Borgendale, and Rahul Gupta. 26 October 2017. OASIS Committee Specification Draft 02 / Public Review Draft 02. http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd02/mqtt-v5.0-csprd02.html. Latest version: http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html. 文档链接 MQTT协议草案5.0中文翻译项目 修订记录 版 本日 期发布说明0.0.12018-05-18发布全部文本,完成初步审校,公开发布第一版 第一章 概述 Introduction 1.0 知识产权政策 Intellectual property rights policy 此公开评审草案的发布基于 OASIS IPR Policy 的 Non-Assertion 模式。 关于实现本规范必不可少的任何专利是否已公开,以及其他的专利许可条款相关的信息,请参考技术委员会网站的知识产权部分(https://www.oasis-open.org/committees/mqtt/ipr.php). 1.1 MQTT协议的组织结构 Organization of MQTT 本规范分为七个章节: [第一章 – 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] 1.2 术语 Terminology 本规范中用到的关键字 必须 MUST,不能 MUST NOT,要求 REQUIRED,将会 SHALL,不会 SHALL NOT,应该 SHOULD,不应该 SHOULD NOT,推荐 RECOMMENDED,可以 MAY,可选 OPTIONAL 都是按照 IETF RFC 2119 [RFC2119] 中的描述解释。 网络连接 Network Connection MQTT使用的底层传输协议基础设施。 客户端使用它连接服务端。 它提供有序的、可靠的、双向字节流传输。 例子见4.2节。 应用消息 Application Message MQTT协议通过网络传输应用数据。应用消息通过MQTT传输时,它们有关联的服务质量(QoS)和主题(Topic)。 客户端 Client使用MQTT的程序或设备。客户端总是通过网络连接到服务端。它可以 打开连接到服务端的网络连接 发布应用消息给其它相关的客户端 订阅以请求接受相关的应用消息 取消订阅以移除接受应用消息的请求 关闭连接到服务端的网络连接 服务端 Server一个程序或设备,作为发送消息的客户端和请求订阅的客户端之间的中介。服务端 接受来自客户端的网络连接 接受客户端发布的应用消息 处理客户端的订阅和取消订阅请求 转发应用消息给符合条件的已订阅客户端 关闭来自客户端的网络连接 会话 Subscription客户端和服务端之间的状态交互。一些会话持续时长与网络连接一样,另一些可以在客户端和服务端的多个连续网络连接间扩展。 订阅 Subscription订阅包含一个主题过滤器(Topic Filter)和一个最大的服务质量(QoS)等级。订阅与单个会话(Session)关联。会话可以包含多于一个的订阅。会话的每个订阅都有一个不同的主题过滤器。 共享订阅 Shared Subscription一个共享订阅包含一个主题过滤器(Topic Filter)和一个最大的服务质量(QoS)等级。一个共享订阅可以与多个订阅会话相关联,便于支持大范围消息交换模式。一条主题匹配的应用消息只发送给关联到此共享订阅的多个会话中的一个会话。一个会话可以包括多个共享订阅,可以同时包含共享订阅与非共享订阅。 通配符订阅 Wildcard Subscription通配符订阅是指主题过滤器(Topic Filter)包含一个或多个通配符的订阅。通配符订阅使得一次订阅匹配多个主题名(Topic Name)。4.7节 描述了主题过滤器中的通配符。 主题名 Topic Name附加在应用消息上的一个标签,服务端已知且与订阅匹配。服务端发送应用消息的一个副本给每一个匹配的客户端订阅。 主题过滤器 Topic Filter订阅中包含的一个表达式,用于表示相关的一个或多个主题。主题过滤器可以使用通配符。 MQTT控制报文 MQTT Control Packet通过网络连接发送的信息数据包。MQTT 规范定义了十四种不同类型的MQTT控制报文,其中一个(PUBLISH 报文)用于传输应用消息。 无效报文 Malformed Packet根据规范不能被正确解析的控制报文。4.13节 描述了如何进行相应的错误处理。 协议错误 Protocol Error在报文解析之后发现包含协议不允许或与客户端或服务端当前状态不一致的数据的错误。4.13节 描述了如何进行相应的错误处理。 遗嘱消息 Will Message在网络连接非正常关闭的情况下,由服务端发布的应用消息。3.1.2.5节 描述了遗嘱消息。 1.3 规范引用 Normative references [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997,http://www.rfc-editor.org/info/rfc2119 [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003,http://www.rfc-editor.org/info/rfc3629http://www.rfc-editor.org/info/rfc6455 [Unicode] The Unicode Consortium. The Unicode Standard,http://www.rfc-editor.org/info/rfc2119 1.4 非规范引用 Non-normative references [RFC0793] Postel, J., "Transmission Control Protocol", STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981,http://www.rfc-editor.org/info/rfc793 [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008,http://www.rfc-editor.org/info/rfc2119 [AES] Advanced Encryption Standard (AES) (FIPS PUB 197).https://csrc.nist.gov/csrc/media/publications/fips/197/final/documents/fips-197.pdf [CHACHA20] ChaCha20 and Poly1305 for IETF Protocolshttps://tools.ietf.org/html/rfc7539 [FIPS1402] Security Requirements for Cryptographic Modules (FIPS PUB 140-2)https://csrc.nist.gov/csrc/media/publications/fips/140/2/final/documents/fips1402.pdf [IEEE 802.1AR] IEEE Standard for Local and metropolitan area networks - Secure Device Identityhttp://standards.ieee.org/findstds/standard/802.1AR-2009.html [ISO29192] ISO/IEC 29192-1:2012 Information technology -- Security techniques -- Lightweight cryptography -- Part 1: Generalhttps://www.iso.org/standard/56425.html [MQTT NIST] MQTT supplemental publication, MQTT and the NIST Framework for Improving Critical Infrastructure Cybersecurityhttp://docs.oasis-open.org/mqtt/mqtt-nist-cybersecurity/v1.0/mqtt-nist-cybersecurity-v1.0.html [MQTTV311] MQTT V3.1.1 Protocol Specificationhttp://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html [ISO20922] MQTT V3.1.1 ISO Standard (ISO/IEC 20922:2016)https://www.iso.org/standard/69466.html [NISTCSF] Improving Critical Infrastructure Cybersecurity Executive Order 13636https://www.nist.gov/sites/default/files/documents/itl/preliminary-cybersecurity-framework.pdf [NIST7628] NISTIR 7628 Guidelines for Smart Grid Cyber Security Cataloguehttps://www.nist.gov/sites/default/files/documents/smartgrid/nistir-7628_total.pdf [NSAB] NSA Suite B Cryptographyhttp://www.nsa.gov/ia/programs/suiteb_cryptography/ [PCIDSS] PCI-DSS Payment Card Industry Data Security Standardhttps://www.pcisecuritystandards.org/pci_security/ [RFC1928] Leech, M., Ganis, M., Lee, Y., Kuris, R., Koblas, D., and L. Jones, "SOCKS Protocol Version 5", RFC 1928, DOI 10.17487/RFC1928, March 1996,http://www.rfc-editor.org/info/rfc1928http://www.rfc-editor.org/info/rfc4511 [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,http://www.rfc-editor.org/info/rfc5280 [RFC6066] Eastlake 3rd, D., "Transport Layer Security (TLS) Extensions: Extension Definitions", RFC 6066, DOI 10.17487/RFC6066, January 2011,http://www.rfc-editor.org/info/rfc6066 [RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, October 2012,http://www.rfc-editor.org/info/rfc6749 [RFC6960] Santesson, S., Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. Adams, "X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP", RFC 6960, DOI 10.17487/RFC6960, June 2013,http://www.rfc-editor.org/info/rfc6960 [SARBANES] Sarbanes-Oxley Act of 2002.http://www.gpo.gov/fdsys/pkg/PLAW-107publ204/html/PLAW-107publ204.htm [USEUPRIVSH] U.S.-EU Privacy Shield Frameworkhttps://www.privacyshield.gov [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005,http://www.rfc-editor.org/info/rfc3986 [RFC1035] Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, DOI 10.17487/RFC1035, November 1987,http://www.rfc-editor.org/info/rfc1035 [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for specifying the location of services (DNS SRV)", RFC 2782, DOI 10.17487/RFC2782, February 2000,http://www.rfc-editor.org/info/rfc2782 1.5 数据表示 Data representations 1.5.1 二进制位 Bits 字节中的位从0到7。第7位是最高有效位,第0位是最低有效位。 1.5.2 双字节整数 Two Byte Integer 双字节整数是 16 位,使用大端序(big-endian,高位字节在低位字节前面)。这意味着一个 16 位的字在网络上表示为最高有效字节(MSB),后面跟着最低有效字节(LSB)。 1.5.3 四字节整数 Four Byte Integer 四字节整数是32位,使用大端序(big-endian,高位字节在低位字节前面)。这意味着一个32位的字在网络上表示为第一个最高有效字节(MSB)后面跟着第一个最低有效字节(LSB),再后面为第二个最高有效字节(MSB)后面跟着第二个最低有效字节(LSB)。 1.5.4 UTF-8编码字符串 UTF-8 encoded strings 后面会描述的控制报文中的文本字段编码为UTF-8格式的字符串。UTF-8 [RFC3629] 是一个高效的Unicode字符编码格式,为了支持基于文本的通信,它对ASCII字符的编码做了优化。 每一个字符串都有一个两字节的长度字段作为前缀,它给出这个字符串UTF-8编码的字节数,它们在图例 1.1 UTF-8编码字符串的结构 中描述。因此可以传送的UTF-8编码的字符串大小有一个限制,不能超过 65535字节。 除非另有说明,所有的UTF-8编码字符串的长度都在0到65535字节这个范围内。 图 1-1 - UTF-8编码字符串的结构 Structure of UTF-8 encoded strings 二进制位76543210byte 1字符串长度的最高有效字节(MSB)byte 2字符串长度的最低有效字节(LSB)byte 3 ...如果长度大于0,这里是UTF-8编码的字符数据。 UTF-8编码字符串中的字符数据必须是按照Unicode规范 [Unicode] 定义的和在RFC3629 [RFC3629] 中重申的有效的UTF-8格式。特别需要指出的是,这些数据不能包含字符码在U+D800和U+DFFF之间的数据。如果服务端或客户端收到了一个包含无效UTF-8字符的控制报文,它必须关闭网络连接 [MQTT-1.5.3-1]。 UTF-8编码的字符串不能包含空字符U+0000。如果客户端或服务端收到了一个包含U+0000的控制报文,它必须关闭网络连接 [MQTT-1.5.3-2]。 数据中不应该包含下面这些Unicode代码点的编码。如果一个接收者(服务端或客户端)收到了包含下列任意字符的控制报文,它可以关闭网络连接: U+0001和U+001F之间的控制字符 U+007F和U+009F之间的控制字符 Unicode规范定义的非字符代码点(例如U+0FFFF) Unicode规范定义的保留字符(例如U+0FFFF) UTF-8编码序列0XEF 0xBB 0xBF总是被解释为U+FEFF(零宽度非换行空白字符),无论它出现在字符串的什么位置,报文接收者都不能跳过或者剥离它 [MQTT-1.5.3-3]。 非规范示例 Non normative example 例如,字符串 A𪛔 是一个拉丁字母A后面跟着一个代码点U+2A6D4(它表示一个中日韩统一表意文字扩展B中的字符),这个字符串编码如下: 图 1-2 - UTF-8编码字符串非规范示例 UTF-8 encoded string non normative example 比特位76543210byte 1字符串长度MSB (0x00)00000000byte 2字符串长度LSB (0x05)00000101byte 3‘A’ (0x41)01000001byte 4(0xF0)11110000byte 5(0xAA)10101010byte 6(0x9B)10011011byte 7(0x94)10010100 1.5.5 变长字节整数 Variable Byte Integer 剩余长度字段使用一个变长字节编码方案,对小于 128 的值它使用单字节编码。更大的值按下面的方式处理。低 7 位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个字节可以编码 128 个数值和一个延续位(continuation bit)。剩余长度字段最大 4 个字节[MQTT-1.5.5-1],如表 1-1 所示。 表 1-1 - 变长字节整数大小 Size of Variable Byte Integer 字节数最小值最大值10 (0x00)127 (0x7F)2128 (0x80, 0x01)16,383 (0xFF, 0x7F)316,384 (0x80, 0x80, 0x01)2,097,151 (0xFF, 0xFF, 0x7F)42,097,152 (0x80, 0x80, 0x80, 0x01)268,435,455 (0xFF, 0xFF, 0xFF, 0x7F) 非规范示例 Non normative example 非负整数 X 使用变长编码方案的算法如下: do  encodedByte = X MOD 128  X = X DIV 128  // if there are more data to encode, set the top bit of this byte  if (X > 0)    encodedByte = encodedByte OR 128  endif  'output' encodedBytewhile (X > 0)MOD是模运算,DIV是整数除法,OR是位操作或(C语言中分别是%,/,|)。 非规范示例 Non normative example 剩余长度字段的解码算法如下: multiplier = 1value = 0do  encodedByte = 'next byte from stream'  value += (encodedByte AND 127) multiplier  if (multiplier > 128128128)    throw Error(Malformed Variable Byte Integer)  multiplier = 128while ((encodedByte AND 128) != 0)AND 是位操作与(C 语言中的&) 这个算法终止时,value 包含的就是剩余长度的值。 1.5.6 二进制数据 Binary Data 二进制数据由一个双字节整数指示其数据长度,因此,二进制数据的长度被限制为0到65,535字节。 1.5.7 UTF-8字符串对 UTF-8 String Pair UTF-8字符串对由两个UTF-8编码的字符串组成,用来表示名字-值对,第一个字符串表示名字,第二个字符串表示值。 所有的字符串必须遵循UTF-8字符串编码规范 [MQTT-1.5.7-1]。如果接受者(客户端或者服务端)接受到一个字符串对,然而其编码并不遵循规范,则此报文为无效报文。4.13节描述了错误处理的信息。 1.6 安全 Security MQTT客户端和服务端实现应该提供认证、授权和安全通信功能,如第5章所描述。强烈建议任何关注于个人身份信息或敏感信息的应用使用这些安全设施。 1.7 编辑约定 Editing conventions 本规范用黄色高亮的文本标识一致性声明,每个一致性声明都分配了一个这种格式的引用:[MQTT-x.x.x-y]。 1.8 变更历史 Editing conventions 1.8.1 MQTT v3.1.1 MQTT v3.1.1 是首个OASIS标准版本MQTT [MQTTV311]。MQTT v3.1.1也是ISO/IEC 20922:2016 [ISO20922] 标准。 1.8.2 MQTT v5.0 MQTT v5.0 在保持MQTT核心不变的基础上添加了大量的新功能。这些功能的主要目标如下: 进一步支持大规模可扩展系统 改进的错误报告 规范化包括容量探索和请求响应在内的通用模式 包括用户属性在内的可扩展机制 改进性能并支持小型客户端 项目主页 MQTT v5.0协议草案中文版 第二章 MQTT控制报文格式 MQTT Control Packet format 2.1 MQTT控制报文结构 Structure of an MQTT Control Packet MQTT协议通过交换预定义的MQTT控制报文来通信。这一节描述这些报文的格式。 MQTT控制报文由三部分组成,按照下图描述的顺序: 图 2-1 - MQTT控制报文的结构 Structure of an MQTT Control Packet Fixed Header固定报头,所有控制报文都包含Variable Header 可变报头,部分控制报文包含Payload 有效载荷,部分控制报文包含 2.1.1 固定报头 Fixed header 如下图所示,每个MQTT控制报文都包含一个固定报头。 图 2-2 - 固定报头的格式 Fixed Header format 比特位76543210byte 1MQTT控制报文的类型用于指定控制报文类型的标志位byte 2...剩余长度 2.1.2 MQTT控制报文的类型 MQTT Control Packet type 位置: 第1个字节,二进制位7-4。 表示为4位无符号值,这些值的定义见下表。 表 2-1 - MQTT控制报文的类型 MQTT Control Packet types 名字值报文流动方向描述Reserved0禁止保留CONNECT1客户端到服务端客户端请求连接服务端CONNACK2服务端到客户端连接报文确认PUBLISH3两个方向都允许发布消息PUBACK4两个方向都允许QoS 1消息发布收到确认PUBREC5两个方向都允许发布收到(保证交付第一步)PUBREL6两个方向都允许发布释放(保证交付第二步)PUBCOMP7两个方向都允许QoS 2消息发布完成(保证交互第三步)SUBSCRIBE8客户端到服务端客户端订阅请求SUBACK9服务端到客户端订阅请求报文确认UNSUBSCRIBE10客户端到服务端客户端取消订阅请求UNSUBACK11服务端到客户端取消订阅报文确认PINGREQ12客户端到服务端心跳请求PINGRESP13服务端到客户端心跳响应DISCONNECT14两个方向都允许断开连接通知AUTH15两个方向都允许认证信息交换 2.1.3 标志 Flags 固定报头第1个字节的剩余的4位 [3-0]包含每个 MQTT 控制报文类型特定的标志如下表所示。表格中任何标记为“保留”的标志位,都是保留给以后使用的,必须设置为表格中列出的值 [MQTT-2.1.3-1]。如果收到非法的标志,此报文被当做无效报文。有关错误处理的详细信息见 4.8节 [MQTT-2.2.2-2]。 表 2-2 - 标志位 Flag Bits 控制报文固定报头标志Bit 3Bit 2Bit 1Bit 0CONNECTReserved0000CONNACKReserved0000PUBLISHUsed in MQTT v5.0DUPQoSRETAINPUBACKReserved0000PUBRECReserved0000PUBRELReserved0010PUBCOMPReserved0000SUBSCRIBEReserved0010SUBACKReserved0000UNSUBSCRIBEReserved0010UNSUBACKReserved0000PINGREQReserved0000PINGRESPReserved0000DISCONNECTReserved0000AUTHReserved0000 DUP1 =控制报文的重复分发标志 QoS2 = PUBLISH报文的服务质量等级 RETAIN3 = PUBLISH报文的保留标志 PUBLISH控制报文中的DUP, QoS和RETAIN标志的描述见 3.3.1节。 2.1.4 剩余长度 Remaining Length 位置: 从第2个字节开始。 剩余长度(Remaining Length)是一个变长字节整数,用来表示当前控制报文剩余部分的字节数,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。MQTT控制报文总长度等于固定报头的长度加上剩余长度。 2.2 可变报头 Variable header 某些 MQTT 控制报文包含一个可变报头部分。它在固定报头和有效载荷之间。可变报头的内容根据报文类型的不同而不同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。 2.2.1 报文标识符 Packet Identifier 部分类型MQTT控制报文的可变报头部分包含了2个字节的报文标识符字段。这些MQTT控制报文类型为:PUBLISH报文(当QoS>0时),PUBACK,PUBREC,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBSCRIBE,UNSUBACK。 需要报文标识符的MQTT控制报文如下表所示。 表 2-3 - 包含报文标识符的MQTT控制报文 MQTT Control Packets that contain a Packet Identifier 名字值CONNECT不需要CONNACK不需要PUBLISH需要(如果QoS>0)PUBACK需要PUBREC需要PUBREL需要PUBCOMP需要SUBSCRIBE需要SUBACK需要UNSUBSCRIBE需要UNSUBACK需要PINGREQ不需要PINGRESP不需要DISCONNECT不需要AUTH不需要 QoS设置为0的 PUBLISH 报文不能包含报文标识符[MQTT-2.2.1-2]。 客户端每次发送一个新的SUBSCRIBE,UNSUBSCRIBE或者PUBLISH(当QoS>0时)MQTT控制报文时都必须分配一个当前未使用的非零报文标识符 [MQTT-2.2.1-3]。 服务端每次发送一个新的PUBLISH(当QoS>0)MQTT控制报文时都必须分配一个当前未使用的非零报文标识符 [MQTT-2.2.1-4]。 当客户端处理完这个报文对应的确认后,这个报文标识符就释放可重用。QoS 1的PUBLISH对应的是PUBACK,QoS 2的PUBLISH对应的是包含原因码128以上的PUBCOMP或PUBREC,与SUBSCRIBE或UNSUBSCRIBE对应的分别是SUBACK或UNSUBACK。 PUBLISH,SUBSCRIBE和UNSUBSCRIBE的报文标识符,在一次会话中对于客户端和服务端来说分属于不同的组。某个报文标识符在某一时刻不能被多个命令所使用。 PUBACK,PUBREC和PUBREL报文必须包含与最初发送的PUBLISH报文相同的报文标识符 [MQTT-2.2.1-5]。类似地,SUBACK和UNSUBACK必须包含在对应的SUBSCRIBE和UNSUBSCRIBE报文中使用的报文标识符 [MQTT-2.2.1-6]。 客户端和服务端彼此独立地分配报文标识符。因此,客户端服务端组合使用相同的报文标识符可以实现并发的消息交换。 非规范评注 客户端发送标识符为0x1234的PUBLISH报文,它有可能会在收到那个报文的PUBACK之前,先收到服务端发送的另一个不同的但是报文标识符也为0x1234的PUBLISH报文。 客户端服务端PUBLISH Packet Identifier = 0x1234---><---PUBLISH Packet Identifier = 0x1234PUBACK Packet Identifier = 0x1234---><---PUBACK Packet Identifier = 0x1234 2.2.2 属性 Properties CONNECT,CONNACK,PUBLISH,PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBACK,DISCONNECT和AUTH报文可变报头的最后一部分是一组属性。CONNECT报文的遗嘱(Will)属性字段中也包含了一组可选的属性。 属性字段由属性长度和所有属性组成。 2.2.2.1 属性长度 Property Length 属性长度被编码为变长字节整数。属性长度不包含用于编码属性长度自身的字节数,但包含所有属性的长度。如果没有任何属性,必须由属性长度为零的字段来指示 [MQTT-2.2.2-1]。 2.2.2.2 属性 Property 一个属性包含一段数据和一个定义了属性用途和数据类型的标识符。标识符被编码为变长字节整数。任何控制报文,如果包含了:对于该报文类型无效的标识符,或者错误类型的数据,都是无效报文。收到无效报文时,服务端或客户端使用包含原因码0x81(无效报文)CONNACK或DISCONNECT报文进行错误处理,如4.13节所述。标识符排序不分先后。 表 2-4 - 属性 Properties 标识符属性名数据类型报文/遗嘱属性DecHex10x01载荷格式说明字节PUBLISH, Will Properties20x02消息过期时间四字节整数PUBLISH, Will Properties30x03内容类型UTF-8编码字符串PUBLISH, Will Properties80x08响应主题UTF-8编码字符串PUBLISH, Will Properties90x09相关数据二进制数据PUBLISH, Will Properties110x0B定义标识符变长字节整数PUBLISH, SUBSCRIBE170x11会话过期间隔四字节整数CONNECT, CONNACK, DISCONNECT180x12分配客户标识符UTF-8编码字符串CONNACK190x13服务端保活时间双字节整数CONNACK210x15认证方法UTF-8编码字符串CONNECT, CONNACK, AUTH220x16认证数据二进制数据CONNECT, CONNACK, AUTH230x17请求问题信息字节CONNECT240x18遗嘱延时间隔四字节整数Will Properties250x19请求响应信息字节CONNECT260x1A请求信息UTF-8编码字符串CONNACK280x1C服务端参考UTF-8编码字符串CONNACK, DISCONNECT310x1F原因字符串UTF-8编码字符串CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT, AUTH330x21接收最大数量双字节整数CONNECT, CONNACK340x22主题别名最大长度双字节整数CONNECT, CONNACK350x23主题别名双字节整数PUBLISH360x24最大QoS字节CONNACK370x25保留属性可用性字节CONNACK380x26用户属性UTF-8字符串对CONNECT, CONNACK, PUBLISH, Will Properties, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, DISCONNECT, AUTH390x27最大报文长度四字节整数CONNECT, CONNACK400x28通配符订阅可用性字节CONNACK410x29订阅标识符可用性字节CONNACK420x2A共享订阅可用性字节CONNACK 非规范评注 尽管属性标识符用变长字节整数来表示,但在此版本协议中,所有的标识符均由一个字节来表示。 2.3 有效载荷 Payload 某些MQTT控制报文在报文的最后部分包含一个有效载荷,这将在第三章论述。对于PUBLISH来说有效载荷就是应用消息。 表 2-5 包含有效载荷的MQTT控制报文 MQTT Control Packets that contain a Payload MQTT控制报文有效载荷CONNECT需要CONNACK不需要PUBLISH可选PUBACK不需要PUBREC不需要PUBREL不需要PUBCOMP不需要SUBSCRIBE需要SUBACK需要UNSUBSCRIBE需要UNSUBACK需要PINGREQ不需要PINGRESP不需要DISCONNECT不需要AUTH不需要 2.4 原因码 Reason Code 原因码是一个单字节无符号数,用来指示一次操作的结果。小于0x80的原因码指示某次操作成功完成,通常用0来表示。大于等于0x80的原因码用来指示操作失败。 CONNACK,PUBACK,PUBREC,PUBREL,PUBCOMP,DISCONNECT和AUTH控制报文的可变报头有一个单字节的原因码。SUBACK和UNSUBACK报文的载荷字段包含一个或多个原因码。 原因码如下表所示。 表 2-6 - 原因码 Reason Code 原因码名称报文DecHex00x00成功CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH00x00正常断开DISCONNECT00x00授权的QoS 0SUBACK10x01授权的QoS 1SUBACK20x02授权的QoS 2SUBACK40x04包含遗嘱的断开DISCONNECT160x10无匹配订阅PUBACK, PUBREC170x11订阅不存在UNSUBACK240x18继续认证AUTH250x19重新认证AUTH1280x80未指明的错误CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT1290x81无效报文CONNACK, DISCONNECT1300x82协议错误CONNACK, DISCONNECT1310x83实现错误CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT1320x84协议版本不支持CONNACK1330x85客户标识符无效CONNACK1340x86用户名密码错误CONNACK1350x87未授权CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT1360x88服务端不可用CONNACK1370x89服务端正忙CONNACK, DISCONNECT1380x8A禁止CONNACK1390x8B服务端关闭中DISCONNECT1400x8C无效的认证方法CONNACK, DISCONNECT1410x8D保活超时DISCONNECT1420x8E会话被接管DISCONNECT1430x8F主题过滤器无效SUBACK, UNSUBACK, DISCONNECT1440x90主题名无效CONNACK, PUBACK, PUBREC, DISCONNECT1450x91报文标识符已被占用PUBACK, PUBREC, SUBACK, UNSUBACK1460x92报文标识符无效PUBREL, PUBCOMP1470x93接收超出最大数量DISCONNECT1480x94主题别名无效DISCONNECT1490x95报文过长CONNACK, DISCONNECT1500x96消息太过频繁DISCONNECT1510x97超出配额CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT1520x98管理行为DISCONNECT1530x99载荷格式无效CONNACK, PUBACK, PUBREC, DISCONNECT1540x9A不支持保留CONNACK, DISCONNECT1550x9B不支持的QoS等级CONNACK, DISCONNECT1560x9C(临时)使用其他服务端CONNACK, DISCONNECT1570x9D服务端已(永久)移动CONNACK, DISCONNECT1580x9E不支持共享订阅SUBACK, DISCONNECT1590x9F超出连接速率限制CONNACK, DISCONNECT1600xA0最大连接时间DISCONNECT1610xA1不支持订阅标识符SUBACK, DISCONNECT1620xA2不支持通配符订阅SUBACK, DISCONNECT 非规范评注 对于原因码0x91(报文标识符已被占用)的处理可以为尝试修复会话、以新会话标志为1重置会话或者判定客户端或服务端实现有缺陷。 项目主页 MQTT v5.0协议草案中文版 第三章 MQTT控制报文 MQTT Control Packets 3.1 CONNECT – 连接请求 客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是CONNECT报文 [MQTT-3.1.0-1]。 在一个网络连接上,客户端只能发送一次CONNECT报文。服务端必须将客户端发送的第二个CONNECT报文当作协议违规处理并断开客户端的连接 [MQTT-3.1.0-2]。有关错误处理的信息请查看4.13节。 有效载荷包含一个或多个编码的字段。包括客户端的唯一标识符,Will主题,Will消息,用户名和密码。除了客户端标识之外,其它的字段都是可选的,基于标志位来决定可变报头中是否需要包含这些字段。 3.1.1 CONNECT 固定报头 CONNECT Fixed header 图 3-1 – CONNECT报文的固定报头 CONNECT packet Fixed Header Bit76543210byte 1MQTT报文类型 (1)Reserved 保留位00010000byte 2...剩余长度 剩余长度字段剩余长度等于可变报头的长度加上有效载荷的长度。编码方式为变长字节整数。 3.1.2 CONNECT 可变报头 CONNECT Variable header CONNECT 报文的可变报头按下列次序包含四个字段:协议名(Protocol Name),协议级别(Protocol Level),连接标志(Connect Flags),保持连接(Keep Alive)和属性(Properties)。2.2.2节 描述了属性(Properties)编码规则。 3.1.2.1 协议名 Protocol Name 图 3-2 - 协议名字节 Protocol Name bytes 说明76543210协议名byte 1长度MSB (0)00000000byte 2长度LSB (4)00000100byte 3‘M’01001101byte 4‘Q’01010001byte 5‘T’01010100byte 6‘T’01010100 协议名是表示协议名MQTT的UTF-8编码的字符串。MQTT规范的后续版本不会改变这个字符串的偏移和长度。 支持多种协议的服务端使用协议名字段判断数据是否为MQTT报文。协议名必须是UTF-8字符串“MQTT”。如果服务端不愿意接受CONNECT但希望表明其MQTT服务端身份,可以发送包含原因码为0x84(不支持的协议版本)的CONNACK报文,然后必须关闭网络连接 [MQTT-3.1.2-1]。 非规范评注 数据包检测工具,例如防火墙,可以使用协议名来识别MQTT流量。 3.1.2.2 协议版本 Protocol Version 图 3-3 - 协议级别字节 Protocol Version byte 说明76543210协议级别byte 7版本(5)00000101 客户端使用一个字节无符号数表示协议修订级别。MQTT v5.0的协议版本字段为5(0x05)。 支持多版本MQTT协议的服务端使用协议版本字段判定客户端正使用的MQTT协议版本。如果协议版本不是5且服务端不愿意接受此CONNECT报文,可以发送包含原因码0x84(不支持的协议版本)的CONNACK报文,然后必须关闭网络连接 [MQTT-3.1.2-2]。 3.1.2.3 连接标志 Connect Flags 连接标志字节包含一些用于指定MQTT连接行为的参数。它还指出有效载荷中的字段是否存在。 图 3-4 - 连接标志位 Connect Flag bits Bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean StartReservedbyte 8XXXXXXX0 服务端必须验证CONNECT控制报文的保留标志位(第0位)是否为0 [MQTT-3.1.2-3],如果不为0则此报文为无效报文。4.13节给出了错误处理信息。 3.1.2.4 新开始 Clean Start 位置: 连接标志字节的第1位 这个二进制位表明此次连接是一个新的会话还是一个已存在的会话的延续。4.1节定义了会话状态。 如果收到新开始(Clean Start)为1的CONNECT报文,客户端和服务端必须丢弃任何已存在的会话,并开始一个新的会话 [MQTT-3.1.2-4]。相应的,CONNACK报文中的会话存在标志设置为0。 如果收到新开始(Clean Start)为0的CONNECT报文,并且存在一个关联此客户标识符的会话,服务端必须基于此会话的状态恢复与客户端的通信 [MQTT-3.1.2-5]。如果收到新开始(Clean Start)为0的CONNECT报文,并且不存在任何关联此客户标识符的会话,服务端必须创建一个新的会话 [MQTT-3.1.2-6]。 3.1.2.5 遗嘱标志 Will Flag 位置: 连接标志字节的第2位 如果遗嘱标志(Will Flag)被设置为1,表示遗嘱消息必须已存储在服务端与此客户标识符相关的会话中 [MQTT-3.1.2-7]。遗嘱消息(Will Message)包含遗嘱属性,遗嘱主题和遗嘱载荷字段。遗嘱必须在网络连接被关闭、遗嘱延时间隔到期或者会话结束之后被发布,除非服务端收到包含原因码为0x00(正常关闭)的DISCONNECT报文之后删除了遗嘱消息(Will Message),或者一个关于此客户标识符的新的网络连接在遗嘱迟发时间(Will Delay Interval)超时之前被创建 [MQTT-3.1.2-8]。 遗嘱消息发布的条件,包括但不限于: 服务端检测到了一个I/O错误或者网络故障 客户端在保持连接(Keep Alive)的时间内未能通讯 客户端在没有发送包含原因码0x00(正常关闭)的情况下关闭了网络连接 服务端在没有收到包含原因码0x00(正常关闭)的情况下关闭了网络连接 如果遗嘱标志(Will Flag)被设置为1,遗嘱属性(Will Property)、遗嘱主题(Will Topic)和遗嘱载荷(Will Payload)字段必须存在于报文有效载荷中 [MQTT-3.1.2-9]。一旦遗嘱消息(Will Message)被发布或者服务端收到包含原因码为0x00(正常关闭)的DISCONNECT报文,遗嘱消息(Will Message)必须从服务端的会话中删除 [MQTT-3.1.2-10]。 服务端应该在网络连接断开并且遗嘱迟发时间(Will Delay Interval)到期,或者会话结束之后立即发布遗嘱消息。服务端关闭或出错的情况下,可以在服务重新启动之后发布遗嘱消息(Will Message)。这种情况下从服务端出错到遗嘱发布之间存在一定的延迟。 关于遗嘱延时间隔(Will Delay Interval)的详细信息,请参考3.1.3.2节。 非规范评注 通过设置晚于会话过期间隔(Session Expiry Interval)的遗嘱迟发时间(Will Delay Interval)并发送包含原因码0x04(包含遗嘱的断开连接),客户端得以发出会话过期(Session Expiry)通告。 3.1.2.6 遗嘱 QoS Will QoS 位置: 连接标志字节的第3、4位 这两个比特指定了发布遗嘱消息(Will Message)时的服务质量(QoS)。 如果遗嘱标志(Will Flag)设置为0,遗嘱服务质量(Will QoS)必须也设置为0(0x00) [MQTT-3.1.2-11]。 如果遗嘱标志设置为1,遗嘱服务质量可以被设置为0(0x00),1(0x01)或2(0x02) [MQTT-3.1.2-12]。设置为3(0x03)的报文是无效报文。4.13节描述了错误处理信息。 3.1.2.7 遗嘱保留 Will Retain 位置: 连接标志字节的第5位 此位指定遗嘱消息(Will Message)在发布时是否会被保留。 如果遗嘱标志被设置为0,遗嘱保留(Will Retain)标志也必须设置为0 [MQTT-3.1.2-13]。如果遗嘱标志被设置为1时,如果遗嘱保留被设置为0,则服务端必须将遗嘱消息当做非保留消息发布 [MQTT-3.1.2-14]。如果遗嘱保留被设置为1,则服务端必须将遗嘱消息当做保留消息发布 [MQTT-3.1.2-15]。 3.1.2.8 用户名标志 User Name Flag 位置: 连接标志字节的第7位 如果用户名标志(User Name Flag)被设置为0,有效载荷中不能包含用户名字段 [MQTT-3.1.2-16]。如果用户名标志被设置为0,有效载荷中必须包含用户名字段 [MQTT-3.1.2-17]。 3.1.2.9 密码标志 Password Flag 位置: 连接标志字节的第6位 如果密码标志(Password Flag)被设置为0,有效载荷中不能包含密码字段 [MQTT-3.1.2-18]。如果密码标志被设置为1,有效载荷中必须包含密码字段 [MQTT-3.1.2-19]。 非规范评注 相比MQTT v3.1.1,此版本协议允许在没有用户名的情况下发送密码。这表明密码除了作为口令之外还可以有其他用途。 3.1.2.10 保持连接 Keep Alive 图 3-5 - 保持连接字节 Keep Alive bytes Bit76543210byte 9保持连接Keep Alive MSBbyte 10保持连接Keep Alive LSB 保持连接(Keep Alive)使用双字节整数来表示以秒为单位的时间间隔。它是指在客户端传输完成一个MQTT控制报文的时刻到发送下一个报文的时刻,两者之间允许空闲的最大时间间隔。客户端负责保证控制报文发送的时间间隔不超过保持连接的值。如果没有任何其它的MQTT控制报文可以发送,客户端必须发送一个PINGREQ 报文 [MQTT-3.1.2-20]。 如果服务端返回的CONNACK报文中包含服务端保持连接(Server Keep Alive),客户端必须使用此值代替其发送的保持连接(Keep Alive) [MQTT-3.1.2-21]。 不管保持连接的值是多少,客户端任何时候都可以发送PINGREQ报文,并且使用PINGRESP报文判断网络和服务端的活动状态。 如果保持连接的值非零,并且服务端在1.5倍的保持连接时间内没有收到客户端的控制报文,它必须断开客户端的网络连接,并判定网络连接已断开 [MQTT-3.1.2-22]。 客户端发送了PINGREQ报文之后,如果在合理的时间内仍没有收到PINGRESP报文,它应该关闭到服务端的网络连接。 保持连接(Keep Alive)值为零的结果是关闭保持连接(Keep Alive)机制。如果保持连接(Keep Alive)值为零,客户端不必按照任何特定的时间发送MQTT控制报文。 非规范评注 服务端可能因为其他原因断开客户端连接,比如服务端将要关闭服务。设置保持连接(Keep Alive)不保证客户端将一直保持连接状态。 非规范评注 保持连接的实际值是由应用指定的,一般是几分钟。允许的最大值是18小时12分15秒。 3.1.2.11 CONNECT 属性 CONNECT Properties 3.1.2.11.1 属性长度 Property Length CONNECT报文可变报头中的属性(Properties)长度被编码为变长字节整数。 3.1.2.11.2 会话过期间隔 Session Expiry Interval 17 (0x11),会话过期间隔(Session Expiry Interval)标识符。跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话过期间隔(Session Expiry Interval)将造成协议错误(Protocol Error)。 如果会话过期间隔(Session Expiry Interval)值未指定,则使用0。如果设置为0或者未指定,会话将在网络连接(Network Connection)关闭时结束。 如果会话过期间隔(Session Expiry Interval)为0xFFFFFFFF (UINT_MAX),则会话永不过期。 如果网络连接关闭时会话过期间隔(Session Expiry Interval)大于0,则客户端与服务端必须存储会话状态 [MQTT-3.1.2-23]。 非规范评注 客户端或服务端可能会因为中断运行导致会话时钟某些时间未运行。这将导致会话的删除被延迟。 更多关于会话的信息参考4.1节。关于会话存储的状态的详细和限制参考4.1.1节。 当会话过期时,客户端和服务端无需以原子操作的方式删除会话状态。 非规范评注 把新开始(Clean Start)设置为1且会话过期间隔(Session Expiry Interval)设置为0,等同于在MQTT v3.1.1中把清理会话(CleanSession)设置为1。把新开始(Clean Start)设置为0且不设置会话过期间隔(Session Expiry Interval),等同于在MQTT v3.1.1中把清理会话标志设置为0。 非规范评注 当希望只处理连接上服务端之后才发布的消息,客户端应该把新开始(Clean Start)设置为1且会话过期间隔(Session Expiry Interval)设置为0,这样客户端就不会收到它连接之前被服务端所发布的消息,并且需要每次连接上服务端时重新订阅其感兴趣的主题。 非规范评注 某些客户端使用的网络可能只能提供断断续续的连接,这种客户端可以使用较短的会话过期间隔(Session Expiry Interval)以便在网络再次可用后重新连接到服务端时获得持续的消息交付。如果客户端不再重新连接,且允许会话过期,应用消息将会丢失。 非规范评注 某个客户端设置较长的会话过期间隔(Session Expiry Interval)或设置会话不过期,即要求服务端为其保持会话到其下一次连接上服务端之后。只有打算在一段时间之后将会重连服务端时,客户端才应该设置较长的会话过期间隔(Session Expiry Interval)。当客户端认定其将来不会使用本次会话时,应该在断开时把会话过期间隔(Session Expiry Interval)设置为0。 非规范评注 客户端应当使用CONNACK报文中的会话存在(Session Present)来判定服务端是否存储了其会话。 非规范评注 客户端应当以服务端返回的会话存在(Session Present)标志来判定会话是否已过期,而不是客户端自己实现的会话过期状态。如果客户端自己实现会话过期状态,则需要将会话应当被删除的时间作为会话状态的一部分而存储。 3.1.2.11.3 接收最大值 Receive Maximum 33 (0x21),接收最大值(Receive Maximum)标识符。跟随其后的是由双字节整数表示的最大接收值。包含多个接收最大值或接收最大值为0将造成协议错误(Protocol Error)。 客户端使用此值限制客户端愿意同时处理的QoS为1和QoS为2的发布消息最大数量。没有机制可以限制服务端试图发送的QoS为0的发布消息。 接收最大值只将被应用在当前网络连接。如果没有设置最大接收值,将使用默认值65535。 关于接收最大值的详细使用,参考4.9节流控。 3.1.2.11.4 最大报文长度 Maximum Packet Size 39 (0x27),最大报文长度(Maximum Packet Size)标识符。跟随其后的是由四字节整数表示的客户端愿意接收的最大报文长度(Maximum Packet Size),如果没有设置最大报文长度(Maximum Packet Size),则按照协议由固定报头中的剩余长度可编码最大值和协议报头对数据包的大小做限制。 包含多个最大报文长度(Maximum Packet Size)或者最大报文长度(Maximum Packet Size)值为0将造成协议错误。 非规范评注 客户端如果选择了限制最大报文长度,应该为最大报文长度设置一个合理的值。 如2.1.4节所述,最大报文长度是MQTT控制报文的总长度。客户端使用最大报文长度通知服务端其所能处理的单个报文长度限制。 服务端不能发送超过最大报文长度(Maximum Packet Size)的报文给客户端 [MQTT-3.1.2-24]。收到长度超过限制的报文将导致协议错误,客户端发送包含原因码0x95(报文过大)的DISCONNECT报文给服务端,详见4.13节。 当报文过大而不能发送时,服务端必须丢弃这些报文,然后当做应用消息发送已完成处理 [MQTT-3.1.2-25]。 共享订阅的情况下,如果一条消息对于部分客户端来说太长而不能发送,服务端可以选择丢弃此消息或者把消息发送给剩余能够接收此消息的客户端。 非规范评注 服务端可以把那些没有发送就被丢弃的报文放在死信队列上,或者执行其他诊断操作。具体的操作超出了本规范的范围。 3.1.2.11.5 主题别名最大值 Topic Alias Maximum 34 (0x22),主题别名最大值(Topic Alias Maximum)标识符。跟随其后的是用双字节整数表示的主题别名最大值(Topic Alias Maximum)。包含多个主题别名最大值(Topic Alias Maximum)将造成协议错误(Protocol Error)。没有设置主题别名最大值属性的情况下,主题别名最大值默认为零。 此值指示了客户端能够接收的来自服务端的主题别名(Topic Alias)最大数量。客户端使用此值来限制本次连接可以拥有的主题别名的数量。服务端在一个PUBLISH报文中发送的主题别名不能超过客户端设置的主题别名最大值(Topic Alias Maximum) [MQTT-3.1.2-26]。值为零表示本次连接客户端不接受任何主题别名(Topic Alias)。如果主题别名最大值(Topic Alias)没有设置,或者设置为零,则服务端不能向此客户端发送任何主题别名(Topic Alias) [MQTT-3.1.2-27]。 3.1.2.11.6 请求响应信息 Request Response Information 25 (0x19),请求响应信息(Request Response Information)标识符。跟随其后的是用一个字节表示的0或1。包含多个请求响应信息(Request Response Information),或者请求响应信息(Request Response Information)的值既不为0也不为1会造成协议错误(Protocol Error)。如果没有请求响应信息(Request Response Information),则请求响应默认值为0。 客户端使用此值向服务端请求CONNACK报文中的响应信息(Response Information)。值为0,表示服务端不能返回响应信息 [MQTT-3.1.2-28]。值为1,表示服务端可以在CONNACK报文中返回响应信息。 非规范评注 即使客户端请求响应信息(Response Information),服务端也可以选择不发送响应信息(Response Information)。 更多关于请求/响应信息的内容,请参考4.10节。 3.1.2.11.7 请求问题信息 Request Problem Information 23 (0x17),请求问题信息(Request Problem Information)标识符。跟随其后的是用一个字节表示的0或1。包含多个请求问题信息(Request Problem Information),或者请求问题信息(Request Problem Information)的值既不为0也不为1会造成协议错误(Protocol Error)。如果没有请求问题信息(Request Problem Information),则请求问题默认值为1。 客户端使用此值指示遇到错误时是否发送原因字符串(Reason String)或用户属性(User Properties)。 如果请求问题信息的值为0,服务端可以选择在CONNACK或DISCONNECT报文中返回原因字符串(Reason String)或用户属性(User Properties),但不能在除PUBLISH,CONNACK或DISCONNECT之外的报文中发送原因字符串(Reason String)或用户属性(User Properties) [MQTT-3.1.2-29]。如果此值为0,并且在除PUBLISH,CONNACK或DISCONNECT之外的报文中收到了原因字符串(Reason String)或用户属性(User Properties),客户端将发送一个包含原因码0x82(协议错误)的DISCONNECT报文给服务端,如4.13节所述。 如果此值为1,服务端可以在任何被允许的报文中返回原因字符串(Reason String)或用户属性(User Properties)。 3.1.2.11.8 用户属性 User Property 38 (0x26),用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。 用户属性(User Property)可以出现多次,表示多个名字/值对。相同的名字可以出现多次。 非规范评注 CONNECT报文中的用户属性可以被用来发送客户端到服务端的连接相关的属性。这些属性的意义本规范不做定义。 3.1.2.11.9 认证方法 Authentication Method 21 (0x15),认证方法(Authentication Method)标识符。跟随其后的是一个UTF-8编码的字符串,包含了扩展认证的认证方法(Authentication Method)名称。包含多个认证方法将造成协议错误(协议错误)。 如果没有认证方法,则不进行扩展验证。参考4.12节。 如果客户端在CONNECT报文中设置了认证方法,则客户端在收到CONNACK报文之前不能发送除AUTH或DISCONNECT之外的报文 [MQTT-3.1.2-30]。 3.1.2.11.10 认证数据 Authentication Data 22 (0x16),认证数据(Authentication Data)标识符。跟随其后的是二进制的认证数据。没有认证方法却包含了认证数据(Authentication Data),或者包含多个认证数据(Authentication Data)将造成协议错误(Protocol Error)。 认证数据的内容由认证方法定义,关于扩展认证的更多信息,请参考4.12节。 3.1.2.12 可变报头非规范示例 Variable Header non-normative example 图 3-6 - 可变报头示例 说明76543210协议名 Protocol Namebyte 1长度 Length MSB (0)00000000byte 2长度 Length LSB (4)00000100byte 3‘M’01001101byte 4‘Q’01010001byte 5‘T’01010100byte 6‘T’01010100协议版本 Protocol Version说明76543210byte 7版本 Version (5)00000101连接标志 Connect Flagsbyte 8用户名标志 User Name Flag (1)密码标志 Password Flag (1)遗嘱保留标志 Will Retain (0)遗嘱服务质量 Will QoS (01)遗嘱标志 Will Flag (1)新开始 Clean Start(1)保留 Reserved (0)11001110保持连接 Keep Alivebyte 9保持连接 Keep Alive MSB (0)00000000byte 10保持连接 Keep Alive LSB (10)00001010属性 Propertiesbyte 11长度 Length (5)00000101byte 12会话过期间隔标识符 (17)00010001byte 13会话过期间隔Session Expiry Interval (10)00000000byte 1400000000byte 1500000000byte 1600001010 3.1.3 CONNECT 载荷 CONNECT Payload CONNECT报文的载荷中包含由可变报头(Variable Header)中的标志确定的一个或多个以长度为前缀的字段。这些字段若存在,必须按照客户标识符(Client Identifier)、遗嘱属性(Will Properties)、遗嘱主题(Will Topic)、遗嘱载荷(Will Payload)、用户名(User Name)、密码(Password)的顺序出现 [MQTT-3.1.3-1]。 3.1.3.1 客户标识符 Client Identifier 服务端使用客户标识符(ClientID)识别客户端。连接服务端的每个客户端都有唯一的客户标识符(ClientID)。客户端和服务端都必须使用客户标识符(ClientID)识别两者之间的 MQTT 会话相关的状态 [MQTT-3.1.3-2]。更多关于会话状态的信息请参考4.1节。 客户标识符必须存在,且作为CONNECT报文载荷的第一个字段出现 [MQTT-3.1.3-3]。 客户标识符必须被编码为1.5.4节 中所定义的UTF-8字符串 [MQTT-3.1.3-4]。 服务端必须允许1到23个字节长的UTF-8编码的客户标识符,客户标识符只能包含这些字符: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"(大写字母、小写字母和数字) [MQTT-3.1.3-5]。 服务端可以允许编码后超过23个字节的客户标识符 (ClientID)。服务端可以允许包含不是上面列表字符的客户标识符 (ClientID)。 服务端可以允许客户端提供一个零字节的客户标识符 (ClientID) ,如果这样做了,服务端必须将这看作特殊情况并分配唯一的客户标识符给那个客户端 [MQTT-3.1.3-6]。然后它必须假设客户端提供了那个唯一的客户标识符,正常处理这个CONNECT报文 [MQTT-3.1.3-7]。 如果服务端拒绝了某个客户标识符(ClientID),它可以发送包含原因码0x85(客户标识符无效)的CONNACK报文作为对客户端的CONNECT报文的回应,如4.13节所述。之后必须关闭网络连接 [MQTT-3.1.3-8]。 非规范评注 客户端在实现时可以提供一个便于生成随机客户标识符的算法。使用此算法时,客户端需要注意避免创建长期孤儿会话。 3.1.3.2 遗嘱属性 Will Properties 如果遗嘱标志(Will Flag)被设置为1,有效载荷的下一个字段是遗嘱属性(Will Properties)。遗嘱属性字段定义了遗嘱消息(Will Message)将何时被发布,以及被发布时的应用消息(Application Message)属性。遗嘱属性包括属性长度和属性。 3.1.3.2.1 属性长度 Property Length 遗嘱属性(Will Properties)中的属性长度被编码为可变长字节整数。 3.1.3.2.2 遗嘱延时间隔 Property Length 24 (0x18),遗嘱延时间隔(Will Delay Interval)标识符。跟随其后的是由四字节整数表示的以秒为单位的遗嘱延时间隔(Will Delay Interval)。包含多个遗嘱延时间隔将造成协议错误(Protocol Error)。如果没有设置遗嘱延时间隔,遗嘱延时间隔默认值将为0,即不用延时发布遗嘱消息(Will Message)。 服务端将在遗嘱延时间隔(Will Delay Interval)到期或者会话(Session)结束时发布客户端的遗嘱消息(Will Message),取决于两者谁先发生。如果某个会话在遗嘱延时间隔到期之前创建了新的网络连接,则服务端不能发送遗嘱消息 [MQTT-3.1.3-9]。 非规范评注 遗嘱时间间隔的一个用途是避免在频繁的网络连接临时断开时发布遗嘱消息,因为客户端往往会很快重新连上网络并继续之前的会话。 非规范评注 如果某个连接到服务端的网络连接使用已存在的客户标识符,此已存在的网络连接的遗嘱消息将会被发布,除非新的网络连接设置了新开始(Clean Start)为0并且遗嘱延时大于0。如果遗嘱延时为0,遗嘱消息将在网络连接断开时发布。如果新开始为1,遗嘱消息也将被发布,因为此会话已结束。 3.1.3.2.3 载荷格式指示 Payload Format Indicator 1 (0x01),载荷格式指示(Payload Format Indicator)标识符。跟随载荷格式指示(Payload Format Indicator )之后的可能是: 0 (0x00),表示遗嘱消息(Will Message)是未指定的字节,等同于不发送载荷格式指示。 1 (0x01),表示遗嘱消息(Will Message)是UTF-8编码的字符数据。载荷中的UTF-8数据必须按照Unicode规范[Unicode]和RFC 3629 [RFC3629]中的申明进行编码。 包含多个载荷格式指示(Payload Format Indicator)将造成协议错误(Protocol Error)。服务端可以按照格式指示对遗嘱消息(Will Message)进行验证,如果验证失败发送一条包含原因码0x99(载荷格式无效)的CONNACK报文。如4.13节所述。 3.1.3.2.4 消息过期间隔 Message Expiry Interval 2 (0x02),消息过期间隔(Message Expiry Interval)标识符。跟随其后的是表示消息过期间隔(Message Expiry Interval)的四字节整数。包含多个消息过期间隔将导致协议错误(Protocol Error)。 如果设定了消息过期间隔(Message Expiry Interval),四字节整数描述了遗嘱消息的生命周期(秒),并在服务端发布遗嘱消息时被当做发布过期间隔(Publication Expiry Interval)。 如果没有设定消息过期间隔,服务端发布遗嘱消息时将不发送消息过期间隔(Message Expiry Interval)。 3.1.3.2.5 内容类型 Content Type 3 (0x03),内容类型(Content Type)标识符。跟随其后的是一个以UTF-8格式编码的字符串,用来描述遗嘱消息(Will Message)的内容。包含多个内容类型(Content Type)将造成协议错误(Protocol Error)。内容类型的值由发送应用程序和接收应用程序确定。 3.1.3.2.6 响应主题 Response Topic 8 (0x08),响应主题(Response Topic)标识符。跟随其后的是一个以UTF-8格式编码的字符串,用来表示响应消息的主题名(Topic Name)。包含多个响应主题(Response Topic)将造成协议错误。响应主题的存在将遗嘱消息(Will Message)标识为一个请求报文。 更多关于请求/响应的内容,参考4.10节。 3.1.3.2.7 对比数据 Correlation Data 9 (0x09),对比数据(Correlation Data)标识符。跟随其后的是二进制数据。对比数据被请求消息发送端在收到响应消息时用来标识相应的请求。包含多个对比数据将造成协议错误(Protocol Error)。如果没有设置对比数据,则请求方(Requester)不需要任何对比数据。 对比数据只对请求消息(Request Message)的发送端和响应消息(Response Message)的接收端有意义。 更多关于请求/响应的内容,参考4.10节。 3.1.3.2.8 用户属性 User Property 38 (0x26),用户属性(User Property)标识符。 跟随其后的是一个UTF-8字符串对。用户属性(User Property)可以出现多次,表示多个名字/值对。相同的名字可以出现多次。 服务端在发布遗嘱消息(Will Message)时必须维护用户属性(User Properties)的顺序 [MQTT-3.1.3-10]。 非规范评注 此属性旨在提供一种传递应用层名称-值标签的方法,其含义和解释仅由负责发送和接收它们的应用程序所有。 3.1.3.3 遗嘱主题 Will Topic 如果遗嘱标志(Will Flag)被设置为1,遗嘱主题(Will Topic)为载荷中下一个字段。遗嘱主题(Will Topic)必须为UTF-8编码的字符串,如1.5.4节 所定义 [MQTT-3.1.3-11]。 3.1.3.4 遗嘱载荷 Will Payload 如果遗嘱标志(Will Flag)被设置为1,遗嘱载荷(Will Payload)为载荷中下一个字段。遗嘱载荷定义了将要发布到遗嘱主题(Will Topic)的应用消息载荷,如3.1.2.5节所定义。此字段为二进制数据。 3.1.3.5 用户名 User Name 如果用户名标志(User Name Flag)被设置为1,用户名(User Name)为载荷中下一个字段。用户名必须是1.5.4节定义的UTF-8 编码字符串 [MQTT-3.1.3-12]。服务端可以将它用于身份验证和授权。 3.1.3.6 密码 Password 如果密码标志(Password Flag)被设置为1,密码(Password)为载荷中下一个字段。密码字段是二进制数据,尽管被称为密码,但可以被用来承载任何认证信息。 3.1.4 CONNECT 行为 CONNECT Actions 注意:服务器可以在同一个TCP端口或其他网络端点上支持多种协议(包括本协议的早期版本)。如果服务器确定协议是MQTT v5.0,那么它按照下面的方法验证连接请求。 网络连接建立后,如果服务端在合理的时间内没有收到 CONNECT 报文,服务端应该关闭这个连接。 服务端必须按照3.1节的要求验证CONNECT报文,如果报文不符合规范,服务端关闭网络连接 [MQTT-3.1.4-1]。服务端可以在关闭网络连接之前发送包含3.1.2.4节所述的0x80及以上原因码的CONNACK报文。 服务端可以检查CONNECT报文的内容是不是满足任何进一步的限制,应该执行身份验证和授权检查。如果任何一项检查没通过,服务端必须关闭网络连接 [MQTT-3.1.4-2]。在关闭网络连接之前,服务端可以发送一个合适的包含如3.2节和4.13节所述的0x80及以上原因码的CONNACK报文。 如果验证成功,服务端会执行下列步骤。 如果客户标识符(ClientID)所代表的客户端已经连接到此服务端,那么向原有的客户端发送一个包含原因码为0x8E(会话被接管)的DISCONNECT报文,并且必须关闭原有的网络连接 [MQTT-3.1.4-3]。如果原有客户端存在遗嘱消息(Will Message),遗嘱消息按照 3.1.2.5节所描述的方式发布。 非规范评注 如果原有网络连接包含遗嘱消息,且遗嘱延时间隔为0,则遗嘱消息会在此网络连接被关闭时发送。如果原有网络连接会话过期间隔为0,或者新网络连接新开始标志设置为1且原有网络连接包含遗嘱消息,则遗嘱消息会被发送,因为原有会话已结束。 服务端必须按照3.1.2.4节所描述的方式对新开始标志进行处理 [MQTT-3.1.4-4]。 服务端必须使用包含原因码为0x00(成功)的CONNACK报文对客户端的CONNECT报文进行确认 [MQTT-3.1.4-5]。 非规范评注 如果服务端被用来处理商业关键数据,推荐对网络连接进行认证和授权。如果认证和授权成功,服务端可通过发送包含原因码为0x00(成功)的CONNACK报文进行响应,否则建议服务端根本不要发送CONNACK报文,因为这是一种潜在的对MQTT服务端的攻击,可以被用来进行拒绝服务攻击或密码猜测攻击。 开始消息分发和保持连接状态监视。 允许客户端在发送CONNECT报文之后立即发送其它的MQTT控制报文;客户端不需要等待服务端的CONNACK报文。如果服务端拒绝了CONNECT报文,它不能处理客户端在CONNECT报文之后发送的任何除AUTH以外的报文 [MQTT-3.1.4-6]。 非规范评注 客户端通常会等待CONNACK报文。然而,如果在收到CONNACK报文之前就自由的发送其它MQTT控制报文将会简化客户端的实现,因为它不必监督连接的状态。如果连接被拒绝了,客户端在接收CONNACK报文之前发送的任何数据将不会被服务端所处理。 非规范评注 选择在收到CONNACK报文之前就发送MQTT控制报文的客户端将不知道服务端所存在的约束以及会话是否被使用。 非规范评注 服务端在对某个客户端完成认证之前,可以选择限制读取该客户端的网络数据或者关闭该客户端的网络连接。这是一种避免拒绝服务攻击的方法。 项目主页 MQTT v5.0协议草案中文版 3.2 CONNACK – 确认连接请求 Connect acknowledgement CONNACK报文由服务端所发送,作为对来自客户端的CONNECT报文的响应。服务端在发送任何除AUTH以外的报文之前必须先发送包含原因码为0x00(成功)的CONNACK报文 [MQTT-3.2.0-1]。服务端在一次网络连接中不能发送多个CONNACK报文 [MQTT-3.2.0-2]。 如果客户端在合理的时间内没有收到服务端的CONNACK报文,客户端应该关闭网络连接。合理 的时间取决于应用的类型和通信基础设施。 3.2.1 CONNACK 固定报头 CONNACK Fixed Header 固定报头的格式见图 3-7的描述。 图 3-7 – CONNACK 报文固定报头 CONNACK packet Fixed Header Bit76543210byte 1MQTT报文类型 (2)Reserved 保留位00100000byte 2...剩余长度 (2)00000010 剩余长度字段用变长字节整数来编码,表示可变报头的长度。 3.2.2 CONNACK 可变报头 CONNACK Variable Header CONNACK报文的可变报头按顺序包含以下字段:连接确认标志(Connect Acknowledge Flags),连接原因码(Reason Code),属性(Properties)。属性的编码规则如2.2.2节所描述。 3.2.2.1 连接确认标志 Connect Acknowledge Flags 第1个字节是连接确认标志,位7-1是保留位且必须设置为0 [MQTT-3.2.2-1]。 第0(SP)位是会话存在标志(Session Present Flag)。 3.2.2.1.1 会话存在 Session Present 位置: 连接确认标志(Connect Acknowledge Flags)的第0位。 会话存在(Session Present)标志通知客户端,服务端是否正在使用此客户标识符之前连接的会话状态(Session State)。会话存在标志使服务端和客户端在是否有已存储的会话状态上保持一致。 如果服务端接受一个新开始(Clean Start)为1的连接,服务端在CONNACK报文中除了把原因码设置为0x00(成功)之外,还必须把会话存在标志设置为0 [MQTT-3.2.2-2]。 如果服务端接受一个新开始(Clean Start)为0的连接,并且服务端已经保存了此客户标识符(ClientID)的会话状态(Session State),服务端在CONNACK报文中必须把会话存在标志设置为1。否则,服务端必须把会话存在标志设置为0。无论如何,服务端在CONNACK报文中必须把原因码设置为0x00(成功) [MQTT-3.2.2-3]。 如果客户端从服务端接收到的会话存在标志值与预期的不同,客户端做如下处理: 如果客户端没有保存的会话状态,但收到会话存在标志为1,客户端必须关闭网络连接 [MQTT-3.2.2-4]。 如果希望重新开始一个新的会话,客户端可以使用新开始(Clean Start)为1并重新连接服务端。 如果客户端保存了会话状态,但收到的会话存在标志为0,客户端若要继续此网络连接,它必须丢弃其保存的会话状态 [MQTT-3.2.2-5]。 如果服务端发送的CONNACK报文中原因码非0,它必须把会话存在标志设置为0 [MQTT-3.2.2-6]。 3.2.2.2 连接原因码 Connect Reason Code 可变报头中第2个字节是连接原因码(Reason Code)。 连接原因码(Reason Code)的值如下所示。如果服务端收到一个格式正确的CONNECT报文,但服务端无法完成连接的创建,服务端可以发送一个包含适当的连接原因码的CONNACK报文。如果服务端发送了一个包含原因码大于等于128的CONNACK报文,它随后必须关闭网络连接 [MQTT-3.2.2-7]。 表 3-1 - 连接原因码 Connect Reason Code values 值16进制原因码名称说明00x00成功连接被接受。1280x80未指明的错误服务端不愿透露的错误,或者没有适用的原因码。1290x81无效报文CONNECT报文内容不能被正确的解析。1300x82协议错误CONNECT报文内容不符合本规范。1310x83实现特定错误CONNECT有效,但不被服务端所接受。1320x84协议版本不支持服务端不支持客户端所请求的MQTT协议版本。1330x85客户标识符无效客户标识符有效,但未被服务端所接受。1340x86用户名密码错误客户端指定的用户名密码未被服务端所接受。1350x87未授权客户端未被授权连接。1360x88服务端不可用MQTT服务端不可用。1370x89服务端正忙服务端正忙,请重试。1380x8A禁止客户端被禁止,请联系服务端管理员。1400x8C无效的认证方法认证方法未被支持,或者不匹配当前使用的认证方法。1440x90主题名无效遗嘱主题格式正确,但未被服务端所接受。1490x95报文过长CONNECT报文超过最大允许长度。1510x97超出配额已超出实现限制或管理限制。1530x99载荷格式无效遗嘱载荷数据与载荷格式指示符不匹配。1540x9A不支持保留遗嘱保留标志被设置为1,但服务端不支持保留消息。1550x9B不支持的QoS等级服务端不支持遗嘱中设置的QoS等级。1560x9C(临时)使用其他服务端客户端应该临时使用其他服务端。1570x9D服务端已(永久)移动客户端应该永久使用其他服务端1590x9F超出连接速率限制超出了所能接受的连接速率限制。 服务端发送的CONNACK报文必须设置一种原因码 [MQTT-3.2.2-8]。 非规范评注 原因码0x80(未指明的错误)可以被用作:服务器知道失败的原因但是并不希望透露给客户端,或者没有其他适用的原因码。 出于安全考虑,发现CONNECT出错时服务端可以选择不发送CONNACK报文而关闭网络连接。例如,在公网中向未被授权的网络连接告知自身MQTT服务端身份并不明智。 3.2.2.3 CONNACK属性 CONNACK Properties 3.2.2.3.1 属性长度 Property Length CONNACK报文可变报头中的属性长度,编码为变长字节整数。 3.2.2.3.2 会话过期间隔 Session Expiry Interval 17 (0x11),会话过期间隔(Session Expiry Interval)标识符。跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话过期间隔(Session Expiry Interval)将造成协议错误(Protocol Error)。 如果会话过期间隔(Session Expiry Interval)值未指定,则使用CONNECT报文中指定的会话过期时间间隔。服务端使用此属性通知客户端它使用的会话过期时间间隔与客户端在CONNECT中发送的值不同。更详细的关于会话过期时间的描述,请参考3.1.2.11.2节。 3.2.2.3.3 接收最大值 Receive Maximum 33 (0x21),接收最大值(Receive Maximum)描述符。跟随其后的是由双字节整数表示的最大接收值。包含多个接收最大值或接收最大值为0将造成协议错误(Protocol Error)。 服务端使用此值限制服务端愿意为该客户端同时处理的QoS为1和QoS为2的发布消息最大数量。没有机制可以限制客户端试图发送的QoS为0的发布消息。 如果没有设置最大接收值,将使用默认值65535。 关于接收最大值的详细使用,参考4.9节流控部分。 3.2.2.3.4 最大服务质量 Maximum QoS 36 (0x24),最大服务质量(Maximum QoS)标识符。跟随其后的是用一个字节表示的0或1。包含多个最大服务质量(Maximum QoS)或最大服务质量既不为0也不为1将造成协议错误。如果没有设置最大服务质量,客户端可使用最大QoS为2。 如果服务端不支持Qos为1或2的PUBLISH报文,服务端必须在CONNACK报文中发送最大服务质量以指定其支持的最大QoS值 [MQTT-3.2.2-9]。即使不支持QoS为1或2的PUBLISH报文,服务端也必须接受请求QoS为0、1或2的SUBSCRIBE报文 [MQTT-3.2.2-10]。 如果从服务端接收到了最大QoS等级,则客户端不能发送超过最大QoS等级所指定的QoS等级的PUBLISH报文 [MQTT-3.2.2-11]。服务端接收到超过其指定的最大服务质量的PUBLISH报文将造成协议错误(Protocol Error)。这种情况下应使用包含原因码为0x9B(不支持的QoS等级)的DISCONNECT报文进行处理,如4.13节所述。 如果服务端收到包含遗嘱的QoS超过服务端处理能力的CONNECT报文,服务端必须拒绝此连接。服务端应该使用包含原因码为0x9B(不支持的QoS等级)的CONNACK报文进行错误处理,随后必须关闭网络连接。4.13节所述 [MQTT-3.2.2-12]。 非规范评注 客户端不必支持QoS为1和2的PUBLISH报文。客户端只需将其发送的任何SUBSCRIBE报文中的QoS字段限制在其支持的最大服务质量以内即可。 3.2.2.3.5 保留可用 Retain Available 37 (0x25),保留可用(Retain Available)标识符。跟随其后的是一个单字节字段,用来声明服务端是否支持保留消息。值为0表示不支持保留消息,为1表示支持保留消息。如果没有设置保留可用字段,表示支持保留消息。包含多个保留可用字段或保留可用字段值不为0也不为1将造成协议错误(Protocol Error)。 如果服务端收到一个包含保留标志位1的遗嘱消息的CONNECT报文且服务端不支持保留消息,服务端必须拒绝此连接请求,且应该发送包含原因码为0x9A(不支持保留)的CONNACK报文,随后必须关闭网络连接 [MQTT-3.2.2-13]。 从服务端接收到的保留可用标志为0时,客户端不能发送保留标志设置为1的PUBLISH报文 [MQTT-3.2.2-14]。如果服务端收到这种PUBLISH报文,将造成协议错误(Protocol Error),此时服务端应该发送包含原因码为0x9A(不支持保留)的DISCONNECT报文,如4.13节所述。 3.2.2.3.6 最大报文长度 Maximum Packet Size 39 (0x27),最大报文长度(Maximum Packet Size)标识符。跟随其后的是由四字节整数表示的服务端愿意接收的最大报文长度(Maximum Packet Size)。如果没有设置最大报文长度,则按照协议由固定报头中的剩余长度可编码最大值和协议报头对数据包的大小做限制。 包含多个最大报文长度(Maximum Packet Size),或最大报文长度为0将造成协议错误(Protocol Error)。 如2.1.4节所述,最大报文长度是MQTT控制报文的总长度。服务端使用最大报文长度通知客户端其所能处理的单个报文长度限制。 客户端不能发送超过最大报文长度(Maximum Packet Size)的报文给服务端 [MQTT-3.2.2-15]。收到长度超过限制的报文将导致协议错误,此时服务端应该发送包含原因码0x95(报文过长)的DISCONNECT报文给客户端,详见4.13节。 3.2.2.3.7 分配客户标识符 Assigned Client Identifier 18 (0x12),分配客户标识符(Assigned Client Identifier)标识符。跟随其后的是UTF-8编码的分配客户标识符(Assigned Client Identifier)字符串。包含多个分配客户标识符将造成协议错误(Protocol Error)。 服务端分配客户标识符的原因是CONNECT报文中的客户标识符长度为0。 如果客户端使用长度为0的客户标识符(ClientID),服务端必须回复包含分配客户标识符(Assigned Client Identifier)的CONNACK报文。分配客户标识符必须是没有被服务端的其他会话所使用的新客户标识符 [MQTT-3.2.2-16]。 3.2.2.3.8 主题别名最大值 Topic Alias Maximum 34 (0x22),主题别名最大值(Topic Alias Maximum)标识符。跟随其后的是用双字节整数表示的主题别名最大值(Topic Alias Maximum)。包含多个主题别名最大值(Topic Alias Maximum)将造成协议错误(Protocol Error)。没有设置主题别名最大值属性的情况下,主题别名最大值默认为零。 此值指示了服务端能够接收的来自客户端的主题别名(Topic Alias)最大值。服务端使用此值来限制本次连接可以拥有的主题别名的值。客户端在一个PUBLISH报文中发送的主题别名值不能超过服务端设置的主题别名最大值(Topic Alias Maximum) [MQTT-3.2.2-17]。值为0表示本次连接服务端不接受任何主题别名(Topic Alias)。如果主题别名最大值(Topic Alias)没有设置,或者设置为0,则客户端不能向此服务端发送任何主题别名(Topic Alias) [MQTT-3.2.2-18]。 3.2.2.3.9 原因字符串 Reason String 31 (0x1F),原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。如果加上原因字符串之后的CONNACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串 [MQTT-3.2.2-19]。包含多个原因字符串将造成协议错误(Protocol Error)。 非规范评注 客户端对原因字符串的恰当使用包括:抛出异常时使用此字符串,或者将此字符串写入日志。 3.2.2.3.10 用户属性 User Property 38 (0x26),用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的CONNACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性 [MQTT-3.2.2-20]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 用户属性的内容和意义本规范不做定义。CONNACK报文的接收端可以选择忽略此属性。 3.2.2.3.11 通配符订阅可用 Wildcard Subscription Available 40 (0x28),通配符订阅可用(Wildcard Subscription Available)标识符。跟随其后的是一个单字节字段,用来声明服务器是否支持通配符订阅(Wildcard Subscriptions)。值为0表示不支持通配符订阅,值为1表示支持通配符订阅。如果没有设置此值,则表示支持通配符订阅。包含多个通配符订阅可用属性,或通配符订阅可用属性值不为0也不为1将造成协议错误(Protocol Error)。 如果服务端在不支持通配符订阅(Wildcard Subscription)的情况下收到了包含通配符订阅的SUBSCRIBE报文,将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为0xA2(通配符订阅不支持)的DISCONNECT报文,如4.13节所述。 服务端在支持通配符订阅的情况下仍然可以拒绝特定的包含通配符订阅的订阅请求。这种情况下,服务端可以发送一个包含原因码为0xA2(通配符订阅不支持)的SUBACK报文。 3.2.2.3.12 订阅标识符可用 Subscription Identifier Available 41 (0x29),订阅标识符可用(Subscription Identifier Available)标识符。跟随其后的是一个单字节字段,用来声明服务端是否支持订阅标识符(Subscription Identifiers)。值为0表示不支持订阅标识符,值为1表示支持订阅标识符。如果没有设置此值,则表示支持订阅标识符。包含多个订阅标识符可用属性,或订阅标识符可用属性值不为0也不为1将造成协议错误(Protocol Error)。 如果服务端在不支持订阅标识符(Subscription Identifier)的情况下收到了包含订阅标识符的SUBSCRIBE报文,将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为0xA1(订阅标识符不支持)的DISCONNECT报文,如4.13节所述。 3.2.2.3.13 共享订阅可用 Shared Subscription Available 42 (0x2A),共享订阅可用(Shared Subscription Available)标识符。跟随其后的是一个单字节字段,用来声明服务端是否支持共享订阅(Shared Subscription)。值为0表示不支持共享订阅,值为1表示支持共享订阅。如果没有设置此值,则表示支持共享订阅。包含多个共享订阅可用(Shared Subscription Available),或共享订阅可用属性值不为0也不为1将造成协议错误(Protocol Error)。 如果服务端在不支持共享订阅(Shared Subscription)的情况下收到了包含共享订阅的SUBSCRIBE报文,将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为0x9E(共享订阅不支持)的DISCONNECT报文,如4.13节所述。 3.2.2.3.14 服务端保持连接 Server Keep Alive 19 (0x13),服务端保持连接(Server Keep Alive)标识符。跟随其后的是由服务端分配的双字节整数表示的保持连接(Keep Alive)时间。如果服务端发送了服务端保持连接(Server Keep Alive)属性,客户端必须使用此值代替其在CONNECT报文中发送的保持连接时间值 [MQTT-3.2.2-21]。如果服务端没有发送服务端保持连接属性,服务端必须使用客户端在CONNECT报文中设置的保持连接时间值 [MQTT-3.2.2-22]。包含多个服务端保持连接属性将造成协议错误(Protocol Error)。 非规范评注 服务端保持连接属性的主要作用是通知客户端它将会比客户端指定的保持连接更快的断开非活动的客户端。 3.2.2.3.15 响应信息 Response Information 26 (0x1A),响应信息(Response Information)标识符。跟随其后的是一个以UTF-8编码的字符串,作为创建响应主题(Response Topic)的基本信息。关于客户端如何根据响应信息(Response Information)创建响应主题不在本规范的定义范围内。包含多个响应信息将造成协议错误(Protocol Error)。 如果客户端发送的请求响应信息(Request Response Information)值为1,则服务端在CONNACK报文中发送响应信息(Response Information)为可选项。 非规范评注 响应信息通常被用来传递主题订阅树的一个全局唯一分支,此分支至少在该客户端的会话生命周期内为该客户端所保留。请求客户端和响应客户端的授权需要使用它,所以它通常不能仅仅是一个随机字符串。一般把此分支作为特定客户端的订阅树根节点。通常此信息需要正确配置,以使得服务器能返回信息。使用此机制时,具体的信息一般由服务端来进行统一配置,而非由各个客户端自己配置。 更多关于请求/响应的信息,请参考4.10节。 3.2.2.3.16 服务端参考 Server Reference 28 (0x1C),服务端参考(Server Reference)标识符。跟随其后的是一个以UTF-8编码的字符串,可以被客户端用来标识其他可用的服务端。包含多个服务端参考(Server Reference)将造成协议错误(Protocol Error)。 服务端在包含了原因码为0x9C((临时)使用其他服务端)或0x9D(服务端已(永久)移动)的CONNACK报文或DISCONNECT报文中设置服务端参考,如4.13节所述。 关于如何使用服务端参考,请参考4.11节服务端重定向信息。 3.2.2.3.17 认证方法 Authentication Method 21 (0x15),认证方法(Authentication Method)标识符。跟随其后的是一个以UTF-8编码的字符串,包含了认证方法(Authentication Method)名。包含多个认证方法将造成协议错误(Protocol Error)。更多关于扩展认证的信息,请参考4.12节。 3.2.2.3.18 认证数据 Authentication Data 22 (0x16),认证数据(Authentication Data)标识符。跟随其后的是包含认证数据(Authentication Data)的二进制数据。此数据的内容由认证方法和已交换的认证数据状态定义。包含多个认证数据将造成协议错误(Protocol Error)。更多关于扩展认证的信息,请参考4.12节。 3.2.3 CONNACK 载荷 CONNACK Payload CONNACK报文不包含有效载荷。 项目主页 MQTT v5.0协议草案中文版 3.3 PUBLISH – 发布消息 Publish message PUBLISH报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。 3.3.1 PUBLISH 固定报头 PUBLISH Fixed Header 图 3-8 – PUBLISH报文固定报头 PUBLISH packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (3)DUPQoS等级RETAIN0011XXXXbyte 2...剩余长度 3.3.1.1 重发标志 DUP 位置: 第1个字节,第3位 如果DUP标志被设置为0,表示这是客户端或服务端第一次请求发送这个PUBLISH报文。如果DUP标志被设置为1,表示这可能是一个早前报文请求的重发。 客户端或服务端请求重发一个PUBLISH报文时,必须将DUP标志设置为1 [MQTT-3.3.1-1]。对于QoS为0的消息,DUP标志必须设置为0 [MQTT-3.3.1-2]。 服务端发送PUBLISH报文给订阅者时,收到(入站)的PUBLISH报文的DUP标志的值不会被传播。发送(出站)的PUBLISH报文与收到(入站)的PUBLISH报文中的DUP标志是独立设置的,它的值必须单独的根据发送(出站)的PUBLISH报文是否是一个重发来确定 [MQTT-3.3.1-3]。 非规范评注 接收者收到一个DUP标志位1的MQTT控制报文时,不能假设它看到了一个这个报文之前的一个副本。 非规范评注 需要特别指出的是,DUP标志关注的是MQTT控制报文本身,与它包含的应用消息无关。当使用QoS 1时,客户端可能会收到一个DUP标志为0的PUBLISH 报文,这个报文包含一个它之前收到过的应用消息的副本,但是用的是不同的报文标识符。 2.2.1节提供了有关报文标识符的更多信息。 3.3.1.2 服务质量等级 QoS 位置: 第1个字节,第2-1位。 这个字段表示应用消息分发的服务质量等级保证。服务质量等级在下表中列出。 表格 3-2 - 服务质量定义 QoS definitions QoS值Bit 2Bit 1说明000最多分发一次101至少分发一次210只分发一次-11保留位 如果服务端在对客户端响应的CONNACK报文中包含了最大服务质量(Maximum QoS)且服务端收到的PUBLISH报文的QoS大于此最大服务质量,服务端发送包含原因码为0x9B(不支持的QoS等级)的DISCONNECT报文,如4.13节所述。 PUBLISH报文的2个QoS比特位不能同时设置为1 [MQTT-3.3.1-4]。如果服务端或客户端收到QoS 2个比特位都为1的无效PUBLISH报文,使用包含原因码为0x81(无效报文)的DISCONNECT报文关闭网络连接,如4.13节所述。 3.3.1.3 保留标志 RETAIN 位置: 第1个字节,第0位。 如果客户端发给服务端的PUBLISH报文的保留(Retain)标志被设置为1,服务端必须存储此应用消息,并用其替换此话题下任何已存在的消息 [MQTT-3.3.1-5],以便它可以被分发给未来的匹配此主题名(Topic Name)的订阅者。如果载荷为空,消息可以正常被服务端所处理,但是此话题下的任何保留消息必须被丢弃,并且此话题未来的订阅者将不会收到保留消息 [MQTT-3.3.1-6]。载荷为空的保留消息将不能被存储在服务端 [MQTT-3.3.1-7]。 如果客户端发给服务端的PUBLISH报文的保留标志位为0,服务器不能把此消息存储为保留消息,也不能丢弃或替换任何已存在的保留消息 [MQTT-3.3.1-8]。 如果服务端发送给客户端的CONNACK报文中包含保留可用属性,且属性值为0,但收到的PUBLISH报文中保留标志位为1,服务端使用包含原因码为0x9A(保留不支持)的DISCONNECT报文断开网络连接,如4.13节所述。 当一个新的非共享订阅(Non-shared Subscription)被创建时,每个匹配的话题下的最新保留消息如果存在,将根据保留消息订阅选项(Retain Handling Subscription Option)发送给客户端。这些消息在发送时保留标志被设置为1。保留消息的发送由保留消息处理订阅选项控制,收到订阅时: 如果保留消息处理属性被设置为0,服务端必须发送主题与客户端订阅的主题过滤器(Topic Filter)相匹配的所有保留消息 [MQTT-3.3.1-9]。 如果保留消息处理属性被设置为1,如果尚不存在匹配的订阅,服务端必须发送主题与客户端订阅的主题过滤器相匹配的所有保留消息。如果已存在相匹配的订阅,服务器不能发送这些保留消息 [MQTT-3.3.1-10]。 如果保留消息处理属性被设置为2,服务器不能发送这些保留消息 [MQTT-3.3.1-11]。 订阅选项(Subscription Options)的定义,参考3.8.3.1节。 如果服务端收到保留标志设置为1且QoS设置为0的PUBLISH报文,服务端应该把此QoS为0的消息存储为其主题下最新的保留消息,但服务端可以选择在任何时间丢弃此消息。如果发生丢弃,该主题下将不存在任何保留消息。 如果某个主题当前的保留消息过期,该主题下将不存在任何保留消息。 服务端转发应用消息时,保留标志位的设置由发布保留(Retain As Published)订阅选项决定。订阅选项的定义,请参考3.8.3.1节。 如果发布保留(Retain As Published)订阅选项被设置为0,服务端在转发应用消息时必须将保留标志设置为0,而不管收到的PUBLISH报文中保留标志位如何设置的 [MQTT-3.3.1-12]。 如果发布保留(Retain As Published)订阅选项被设置为1,服务端在转发应用消息时必须将保留标志设置为与收到的PUBLISH消息中的保留标志位相同 [MQTT-3.3.1-13]。 非规范评注 对于发布者不定期发送状态消息这个场景,保留消息很有用。新的非共享订阅者将会收到最近的状态。 3.3.1.4 剩余长度 Remaining Length 等于可变报头的长度加上有效载荷的长度,被编码为变长字节整数。 3.3.2 PUBLISH可变报头 PUBLISH Variable Header PUBLISH报文可变报头按顺序包含:主题名(Topic Name),报文标识符(Packet Identifier),属性(Properties)。属性的编码规则如2.2.2节所述。 3.3.2.1 主题名 Topic Name 主题名(Topic Name)用于识别有效载荷数据应该被发布到哪一个信息通道。 主题名必须是PUBLISH报文可变报头的第一个字段。它必须是 1.5.4节定义的UTF-8编码的字符串 [MQTT-3.3.2-1]。 PUBLISH报文中的主题名不能包含通配符 [MQTT-3.3.2-2]。 服务端发送给订阅客户端的PUBLISH报文中的主题名必须匹配该订阅的主题过滤器(Topic Filter), 如4.7节所定义的匹配过程 [MQTT-3.3.2-3]。然而,由于服务端允许将主题名映射为其他名字,主题名可能与原始PUBLISH报文中的主题名不同。 发送端可以使用主题别名(Topic Alias)以便减少PUBLISH报文的长度。主题别名如3.3.2.3.4节所述。主题名长度为0且没有主题别名,将造成协议错误(Protocol Error)。 3.3.2.2 报文标识符 Packet Identifier 只有当QoS等级是1或2时,报文标识符(Packet Identifier)字段才能出现在PUBLISH报文中。2.2.1节提供了有关报文标识符的更多信息。 3.3.2.3 PUBLISH 属性 PUBLISH Properties 3.3.2.3.1 属性长度 Property Length PUBLISH报文可变报头中的属性长度被编码为变长字节整数。 3.3.2.3.2 载荷格式指示 Payload Format Indicator 1 (0x01),载荷格式指示(Payload Format Indicator)标识符。跟随其后的是单字节的载荷格式指示值,可以是: 0 (0x00),说明载荷是未指定格式的字节,相当于没有发送载荷格式指示。 1 (0x01),说明载荷是UTF-8编码的字符数据。载荷中的UTF-8数据必须是按照Unicode [Unicode]的规范和RFC 3629 [RFC3629]的重申进行编码。 服务端必须把接收到的应用消息中的载荷格式指示原封不动的发给所有的订阅者 [MQTT-3.3.2-4]。接收者可以验证载荷数据与所指示的格式一致,如果不一致,发送包含原因码为0x99(载荷格式无效)的PUBACK,PUBREC或DISCONNECT报文,如4.13节所述。 3.3.2.3.3 消息过期间隔 Message Expiry Interval 2 (0x02),消息过期间隔(Message Expiry Interval)标识符。跟随其后的是四字节整数表示的消息过期间隔(Message Expiry Interval)。 如果消息过期间隔存在,四字节整数表示以秒为单位的应用消息(Application Message)生命周期。如果消息过期间隔(Message Expiry Interval)已过期,服务端还没开始向匹配的订阅者交付该消息,则服务端必须删除该订阅者的消息副本 [MQTT-3.3.2-5]。 如果消息过期间隔不存在,应用消息不会过期。 服务端发送给客户端的PUBLISH报文中必须包含消息过期间隔,值为接收时间减去消息在服务端的等待时间 [MQTT-3.3.2-6]。关于状态存储的细节和限制,参考4.1节。 3.3.2.3.4 主题别名 Topic Alias 35 (0x23),主题别名(Topic Alias)标识符。跟随其后的是表示主题别名(Topic Alias)值的双字节整数。包含多个主题别名值将造成协议错误(Protocol Error)。 主题别名是一个整数,用来代替主题名对主题进行识别。主题别名可以减小PUBLISH报文的长度,这对某个网络连接中发送的很长且反复使用的主题名来说很有用。 发送端决定是否使用主题别名及别名值如何选取。发送端通过在PUBLISH报文中包含的非0长度主题名和主题别名来设置主题别名映射。接收端正常处理该PUBLISH报文,但同样将指定的主题别名映射到主题名。 如果接收端已经设置了某个主题别名映射,发送端可以发送包含主题别名和长度为0的主题名的PUBLISH报文。接收端把此PUBLISH报文的主题名当做其包含的主题别名所映射的主题名。 发送端可以通过在同一个网络连接中发送另一个包含同样主题别名和不同非0长度主题名的PUBLISH报文来修改主题别名映射关系。 主题别名映射仅作用于某个网络连接及其生命周期内。接收端不能将任何主题别名映射从一个网络连接转发到另一个网络连接 [MQTT-3.3.2-7]。 主题别名不允许为0。发送端不能发送包含主题别名值为0的PUBLISH报文 [MQTT-3.3.2-8]。 客户端不能发送主题别名值大于服务端的CONNACK报文中指定的主题别名最大值(Topic Alias Maximum)的PUBLISH报文 [MQTT-3.3.2-9]。客户端必须接受所有值大于0且小于等于其发送的CONNECT报文中的主题别名最大值的主题别名 [MQTT-3.3.2-10]。 服务端不能发送包含主题别名值大于客户端在CONNECT报文中指定的主题别名最大值(Topic Alias Maximum)的PUBLISH报文 [MQTT-3.3.2-11]。服务端必须接受所有值大于0且小于等于其发送的CONNACK报文中的主题别名最大值的主题别名 [MQTT-3.3.2-12]。 客户端和服务端使用的主题别名映射相互独立。因此一般来说,客户端发送给服务端的主题别名值为1的PUBLISH报文和服务端发送给客户端的主题别名值为1的PUBLISH报文,将被映射到不同的主题。 3.3.2.3.5 响应主题 Response Topic 8 (0x08),响应主题(Response Topic)标识符。跟随其后的是一个UTF-8编码的字符串,用作响应消息的主题名。响应主题必须是按照1.5.4节所定义的UTF-8编码的字符串 [MQTT-3.3.2-13]。响应主题不能包含通配符 [MQTT-3.3.2-14]。包含多个响应主题将造成协议错误(Protocol Error)。响应主题的存在将消息标识为请求报文。 更多关于请求/响应的信息,参考4.10节 。 服务端在收到应用消息时必须将响应主题原封不动的发送给所有的订阅者 [MQTT-3.3.2-15]。 非规范评注 包含响应主题的应用消息接收端使用响应主题作为主题名,发送作为响应消息的PUBLISH报文。如果请求消息中包含对比数据,接收端应当在发送作为对此请求消息进行响应的PUBLISH报文中包含此对比数据。 3.3.2.3.6 对比数据 Correlation Data 9 (0x09),对比数据(Correlation Data)标识符。跟随其后的是二进制数据。对比数据被请求消息发送端在收到响应消息时用来标识相应的请求。包含多个对比数据将造成协议错误(Protocol Error)。如果没有设置对比数据,则请求方(Requester)不需要任何对比数据。 服务端在收到应用消息时必须原封不动的把对比数据发送给所有的订阅者 [MQTT-3.3.2-16]。对比数据只对请求消息(Request Message)的发送端和响应消息(Response Message)的接收端有意义。 非规范评注 接收端收到包含响应主题和对比数据的应用消息时,发送以响应主题为主题名的PUBLISH报文作为响应消息。客户端在响应消息中应将对比数据作为PUBLISH报文的一部分原封不动的发送出去。 非规范评注 如果对客户端响应消息中的对比数据所做的任何更改会造成应用程序错误,则应当对对比数据进行加密/哈希,以便接收端能检测到对比数据是否被更改。 更多关于请求/响应的信息,请参考4.10节。 3.3.2.3.7 用户属性 Property Length 38 (0x26),用户属性(User Property)。跟随其后的是UTF-8字符串对。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 服务端在转发应用消息到客户端时必须原封不动的把所有的用户属性放在PUBLISH报文中 [MQTT-3.3.2-17]。服务端在转发应用消息时必须保持所有用户属性的先后顺序 [MQTT-3.3.2-18]。 非规范评注 此属性旨在提供一种传递应用层名称-值标签的方法,其含义和解释仅由负责发送和接收它们的应用程序所有。 3.3.2.3.8 订阅标识符 Subscription Identifier 11 (0x0B),订阅标识符(Subscription Identifier)标识符。跟随其后的是一个变长字节整数表示的订阅标识符。 订阅标识符取值范围从1到268,435,455。订阅标识符的值为0将造成协议错误。如果某条发布消息匹配了多个订阅,则将包含多个订阅标识符。这种情况下他们的顺序并不重要。 3.3.2.3.9 内容类型 Content Type 3 (0x03), 内容类型(Content Type)标识符。跟随其后的是一个以UTF-8格式编码的字符串,用来描述应用消息的内容。内容类型必须是UTF-8编码的字符串,如1.5.4节所定义 [MQTT-3.3.2-19]。 包含多个内容类型将造成协议错误(Protocol Error)。内容类型的值由发送应用程序和接收应用程序确定。 服务端必须把收到的应用消息中的内容类型原封不动的发送给所有的订阅者 [MQTT-3.3.2-20]。 非规范评注 UTF-8编码字符串可以使用一个MIME内容类型字符串来描述应用消息的内容。由于发送程序和接收程序负责内容类型字符串的定义和解释,因此MQTT服务端只确保内容类型是有效的UTF-8编码的字符串,不会做其他方面的验证。 非规范评注 图3-9是一个PUBLISH示例报文,其中主题名为a/b,报文标识符为10,没有属性。 图 3-9 - PUBLISH报文可变报头非规范示例 PUBLISH packet Variable Header non-normative example 说明76543210主题名byte 1长度MSB (0)00000000byte 2长度LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010报文标识符byte 6报文标识符MSB (0)00000000byte 7报文标识符LSB (10)00001010属性长度byte 8无属性00000000 3.3.3 PUBLISH 载荷 PUBLISH Payload 载荷包含将被发布的应用消息。载荷的内容和格式由应用程序指定。有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度。包含零长度有效载荷的PUBLISH报文是合法的。 3.3.4 PUBLISH 行为 PUBLISH Actions PUBLISH报文的接收端必须按照PUBLISH报文中的QoS等级发送响应报文 [MQTT-3.3.4-1]。 表 3-3 - PUBLISH报文的预期响应 Expected PUBLISH packet response 服务质量等级预期响应QoS 0无响应QoS 1PUBACK报文QoS 2PUBREC报文 客户端使用PUBLISH报文发送应用消息给服务端,目的是分发到其他订阅匹配的客户端。 服务端使用PUBLISH报文发送应用消息给每一个订阅匹配的客户端。PUBLISH报文包含SUBSCRIBE报文中承载的订阅标识符--如果存在的话。 客户端使用带通配符的主题过滤器请求订阅时,客户端的订阅可能会重叠,因此发布的消息可能会匹配多个主题过滤器。这种情况下,服务端必须按照所有匹配的订阅中最大的QoS等级把消息发送给客户端 [MQTT-3.3.4-2]。此外,服务端可以为每一个匹配的订阅按照订阅时的QoS等级,把消息副本分发给客户端。 如果客户端收到一个未经请求的应用消息(没有匹配任何订阅),且QoS大于客户端指定的最大服务质量(Maximum QoS),客户端使用包含原因码为0x9B(不支持的QoS等级)的DISCONNECT报文断开连接,如4.13节所述。 如果客户端在这些重叠的订阅中指定了订阅标识符,服务端在发布这些订阅相匹配的消息时必须包含这些订阅标识符 [MQTT-3.3.4-3]。如果服务端对这些重叠的订阅只发送一条相匹配的消息,服务端必须在PUBLISH报文中包含所有的相匹配的订阅标识符(如果存在),但没有顺序要求 [MQTT-3.3.4-4]。如果服务端对这些重叠的订阅必须分别发送相匹配的消息,则每个PUBLISH报文中含与订阅相匹配的订阅标识符(如果存在) [MQTT-3.3.4-5]。 可能存在客户端对同一个发布消息做了多次订阅,并且这些订阅中有多个订阅使用了相同的订阅标识符,这种情况下PUBLISH报文将携带多个相同的订阅标识符。 PUBLISH报文中若包含服务端收到的SUBSCRIBE报文以外的订阅标识符,将造成协议错误(Protocol Error)。从客户端发送给服务端的PUBLISH报文不能包含订阅标识符 [MQTT-3.3.4-6]。 对于共享订阅,发送给某个客户端的PUBLISH报文中将只包含该客户端的SUBSCRIBE报文中发送的订阅标识符。 收到PUBLISH报文时,接收端的行为取决于报文的QoS等级,如4.3节所述。 如果PUBLISH报文包含主题别名,接收端按照以下方式进行处理: 1) 主题别名为0或大于最大主题别名(Maximum Topic Alias),将造成协议错误(Protocol Error),接收端使用包含原因码为0x94(主题别名无效)的DISCONNECT报文断开网络连接,如4.13节所述。 2) 如果接收端已创建此主题别名的映射, a) 如果报文包含的主题名长度为0,接收端使用主题别名对应的主题名处理此报文 b) 如果报文包含的主题名长度不为0,接收端使用此主题名处理此报文,并更新此主题别名映射到此主题名 3) 如果接收端还没有创建此主题别名的映射, a) 如果报文包含的主题名长度为0,将造成协议错误,接收端使用包含原因码为0x82(协议错误)的DISCONNECT报文断开网络连接,如4.13节所述。 b) 如果报文包含的主题名长度不为0,接收端使用此主题名处理此报文,并为此报文中的主题别名和主题名创建映射关系 非规范评注 如果服务端向客户端分发应用消息时使用了不同的协议级别(比如MQTT v3.1.1)-- 不支持属性或本规范提供的其他功能,应用消息中的某些信息将丢失,依赖于这些信息的应用程序可能无法正常工作。 客户端在收到服务端的PUBACK,PUBCOMP或包含原因码大于等于128的PUBREC报文之前,不能发送数量超过服务端的接收最大值(Receive Maximum)的QoS为1和2的PUBLISH报文 [MQTT-3.3.4-7]。服务端在发送PUBACK或PUBCOMP响应之前,如果收到数量超过客户端的接收最大值的QoS为1和2的PUBLISH报文,服务端使用包含原因码为0x93(超出接收最大值)的DISCONNECT报文断开网络连接,如4.13节所述。更多关于流量控制的信息,参考4.9节。 客户端不能延迟发送任何报文,除了PUBLISH报文--如果已发送且没有收到确认的PUBLISH报文数量已达到服务端的接收最大值(Receive Maximum) [MQTT-3.3.4-8]。接收最大值只应用于当前网络连接。 非规范评注 客户端可以选择发送少于服务端接收最大值的未经确认的PUBLISH报文,尽管它可以发送更多数量的报文。 非规范评注 客户端可以选择暂停发送QoS为0的报文,当其暂停发送了QoS为1和2的PUBLISH报文。 非规范评注 如果客户端在收到CONNACK之前发送QoS为1或QoS为2的PUBLISH报文,客户端有可能被服务器断开连接,因为它发送了超过服务端接收最大值数量的发布报文。 服务端在接收到客户端的PUBACK,PUBCOMP或包含原因码大于等于128的PUBREC报文之前,不能发送数量超过客户端的接收最大值(Receive Maximum)的QoS为1和2的PUBLISH报文 [MQTT-3.3.4-9]。客户端在发送PUBACK或PUBCOMP响应之前,如果收到数量超过服务端的接收最大值的QoS为1和2的PUBLISH报文,客户端使用包含原因码为0x93(超出接收最大值)的DISCONNECT报文断开网络连接,如4.13节所述。更多关于流量控制的信息,参考4.9节 。 服务端不能延迟发送任何报文,除了PUBLISH报文--如果已发送且没有收到确认的PUBLISH报文数量已到达客户端的接收最大值(Receive Maximum) [MQTT-3.3.4-10]。 非规范评注 服务端可以选择发送少于客户端接收最大值的未经确认的PUBLISH报文,尽管它可以发送更多数量的报文。 非规范评注 服务端可以选择暂停发送QoS为0的报文,当其暂停发送了QoS为1和2的PUBLISH报文。 项目主页 MQTT v5.0协议草案中文版3.4 PUBACK –发布确认 Publish acknowledgement PUBACK报文是对QoS 1等级的PUBLISH报文的响应。 3.4.1 PUBACK 固定报头 PUBACK Fixed Header 图 3-10 - PUBACK报文固定报头 PUBACK packet Fixed Header Bit76543210byte 1MQTT报文类型 (4)保留位01000000byte 2...剩余长度01000000 剩余长度字段表示可变报头的长度,用变长字节整数编码。 3.4.2 PUBACK 可变报头 PUBACK Variable Header PUBACK可变报头按顺序包含以下字段:所确认的PUBLISH报文标识符,PUBACK原因码,属性长度,属性(Properties)。属性编码规则如2.22节所述。 图 3-11 – PUBACK报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBACK原因码byte 4属性长度 LSB 3.4.2.1 PUBACK 原因码 PUBACK Reason Code PUBACK可变报头第3字节是原因码( Reason Code)。剩余长度为2,则表示使用原因码0x00(成功)。 表 3-4 – PUBACK原因码 PUBACK Reason Codes 值16进制原因码名称说明00x00成功消息被接收。QoS为1的消息已发布。160x10无匹配的订阅者消息被接收,但没有订阅者。只有服务端会发送此原因码。如果服务端得知没有匹配的订阅者,服务端可以使用此原因码代替0x00(成功)。1280x80未指明的错误接收端不接受此消息,且不愿意透露错误原因或没有适用的原因码。1310x83实现特定错误PUBLISH报文有效,但不被接收端所接受。1350x87未授权PUBLISH报文未授权。1440x90主题名无效主题名格式正确,但未被客户端或服务端所接受。1450x91报文标识符被占用报文标识符已被占用。可能表明客户端和服务端之间的会话状态不匹配。1510x97超出配额已超出实现限制或管理限制。1530x99载荷格式无效载荷格式与载荷格式指示符不匹配。 服务端或客户端发送PUBACK报文时必须设置其中一种PUBACK原因码 [MQTT-3.4.2-1]。当原因码为0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBACK剩余长度为2。 3.4.2.2 PUBACK 属性 PUBACK Properties 3.4.2.2.1 属性长度 Property Length PUBACK可变报头中属性长度被编码为变长字节整数。如果剩余长度小于4字节,则没有属性长度。 3.4.2.2.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不能被接收端所解析。 发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的PUBACK报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此原因字符串 [MQTT-3.4.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.4.2.2.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于提供包括诊断信息在内的附加信息。如果加上用户属性之后的PUBACK报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此属性 [MQTT-3.4.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.4.3 PUBACK 载荷 PUBACK Payload PUBACK报文没有有效载荷。 3.4.4 动作 描述见4.3.2节。 项目主页 MQTT v5.0协议草案中文版 3.5 PUBREC – 发布已接收(QoS 2,第一步) PUBREC报文是对QoS等级2的PUBLISH报文的响应。它是QoS 2等级协议交换的第二个报文。 3.5.1 PUBREC 固定报头 PUBREC Fixed Header 图 3-12 – PUBREC报文固定报头 PUBREC packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (5)保留位01010000byte 2剩余长度 (2) 剩余长度字段表示可变报头的长度,用变长字节整数编码。 3.5.2 PUBREC 可变报头 PUBREC Variable Header PUBREC可变报头按顺序包含以下字段:所确认的PUBLISH报文标识符(Packet Identifier),PUBREC原因码(Reason Code),属性(Properties)。属性的编码规则,如2.2.2节所述。 图 3-13 – PUBREC报文可变报头 PUBREC packet Variable Header Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBREC原因码byte 4属性长度 3.5.2.1 PUBREC 原因码 PUBREC Reason Code PUBREC可变报头第3字节是原因码(Reason Code)。如果剩余长度为2,则表示使用原因码0x00(成功)。 表 3-5 – PUBACK原因码 PUBREC Reason Codes 值16进制原因码名称说明00x00成功消息被接收。QoS为2的消息已发布。160x10无匹配的订阅者消息被接收,但没有订阅者。只有服务端会发送此原因码。如果服务端得知没有匹配的订阅者,服务端可以使用此原因码代替0x00(成功)。1280x80未指明的错误接收端不接受此消息,且不愿意透露错误原因或没有适用的原因码。1310x83实现特定错误PUBLISH报文有效,但不被接收端所接受。1350x87未授权PUBLISH报文未授权。1440x90主题名无效主题名格式正确,但未被客户端或服务端所接受。1450x91报文标识符被占用报文标识符正被占用。可能表明客户端和服务端之间的会话状态不匹配。1510x97超出配额已超出实现限制或管理限制。1530x99载荷格式无效载荷格式与载荷格式指示符不匹配。 服务端或客户端发送PUBREC报文时必须设置其中一种原因码 [MQTT-3.5.2-1]。当原因码为0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBREC剩余长度为2。 3.5.2.2 PUBREC 属性 PUBREC Properties 3.5.2.2.1 属性长度 Property Length PUBREC可变报头的属性长度被编码为变长字节整数。如果剩余长度小于4,则表示没有属性长度字段。 3.5.2.2.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的PUBREC报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此属性 [MQTT-3.5.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.5.2.2.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是UTF-8字符串对。此属性可用于提供包括诊断信息在内的附加信息。如果加上用户属性之后的PUBREC报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此属性 [MQTT-3.5.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.5.3 有效载荷 PUBREC Payload PUBREC报文没有有效载荷。 3.5.4 动作 PUBREC Actions 描述见 4.3.3节。 项目主页 MQTT v5.0协议草案中文版 3.6 PUBREL – 发布释放(QoS 2,第二步) PUBREL报文是对PUBREC报文的响应。它是QoS 2等级协议交换的第三个报文。 3.6.1 PUBREL 固定报头 PUBREL Fixed Header 图 3-14 – PUBREL报文固定报头 PUBREL packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (6)保留位01100010byte 2剩余长度 PUBREL固定报头的第3,2,1,0位是保留位,必须被设置为0,0,1,0。服务端必须将其它的任何值都当做是不合法的并关闭网络连接 [MQTT-3.6.1-1]。 剩余长度字段表示可变报头的长度,被编码为变长字节整数。 3.6.2 PUBREL 可变报头 PUBREL Variable Header PUBREL报文的可变报头按顺序包含以下字段:所确认的PUBREC报文标识符,PUBREL原因码,属性(Properties)。属性的编码规则如2.2.2节所述。 图 3-15 – PUBREL报文可变报头 PUBREL packet Variable Header Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBREL原因码byte 4属性长度 3.6.2.1 PUBREL 原因码 PUBREL Reason Code 可变报头第3字节是PUBREL原因码。如果剩余长度为2,则表示使用原因码0x00 (成功)。 表 3-6 – PUBREL原因码 PUBREL Reason Codes 值16进制原因码名称说明00x00成功消息已释放。1460x92报文标识符未发现未知的报文标识符。会话恢复阶段这并非错误,但其他时间这表明服务端和客户端的会话状态不匹配。 客户端或服务端发送PUBREL报文时必须设置其中一种PUBREL原因码 [MQTT-3.6.2-1]。当原因码为0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBREL剩余长度为2。 3.6.2.2 PUBREL 属性 PUBREL Properties 3.6.2.2.1 属性长度 Property Length PUBREL报文可变报头中的属性长度被编码为变长字节整数。如果剩余长度小于4,则表示没有属性长度字段。 3.6.2.2.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的PUBREL报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此原因字符串 [MQTT-3.6.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.6.2.2.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于提供包括诊断信息或关于PUBREL的信息。如果加上用户属性之后的PUBREL报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此属性 [MQTT-3.6.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.6.3 PUBREL 有效载荷 PUBREL Payload PUBREL报文没有有效载荷。 3.6.4 PUBREL 行为 PUBREL Actions 描述见4.3.3节。 项目主页 MQTT v5.0协议草案中文版 3.7 PUBCOMP – 发布完成(QoS 2,第三步) PUBCOMP报文是对PUBREL报文的响应。它是QoS 2等级协议交换的第四个也是最后一个报文。 3.7.1 PUBCOMP 固定报头 PUBCOMP Fixed Header 图 3-16 – PUBCOMP报文固定报头 PUBCOMP packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (7)保留位01110000byte 2剩余长度 (2) 剩余长度字段表示可变报头的长度,编码为变长字节整数。 3.7.2 PUBCOMP 可变报头 PUBCOMP Variable Header PUBCOMP报文可变报头按顺序包含以下字段:所确认的PUBREL报文标识符,PUBCOMP原因码,属性。属性(Properties)编码规则如2.2.2节所述。 图 3-17 – PUBCOMP报文可变报头 PUBCOMP packet Variable Header Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBCOMP原因码byte 4属性长度 3.7.2.1 PUBCOMP 原因码 PUBCOMP Reason Codes 可变报头第3字节是PUBCOMP原因码。如果剩余长度为2,则表示使用原因码0x00(成功)。 表 3-7 – PUBCOMP 原因码 PUBCOMP Reason Codes 值16进制原因码名称说明00x00成功报文标识符已释放。QoS 2消息已完成发布。1460x92报文标识符未发现未知的报文标识符。会话恢复阶段这并非错误,但其他时间这表明服务端和客户端的会话状态不匹配。 服务端或客户端发送PUBCOMP报文时必须设置一种PUBCOMP原因码 [MQTT-3.7.2-1]。当原因码为0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBCOMP剩余长度为2。 3.7.2.2 PUBCOMP 属性 PUBCOMP Properties 3.7.2.2.1 属性长度 Property Length PUBCOMP报文可变报头中的属性长度被编码为变长字节整数。如果剩余长度小于4,则表示没有属性长度字段。 3.7.2.2.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的PUBCOMP报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此原因字符串 [MQTT-3.7.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.7.2.2.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是UTF-8字符串对。此属性可用于提供诊断信息或关于其他信息。如果加上用户属性之后的PUBCOMP报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此属性 [MQTT-3.7.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.7.3 PUBCOMP 载荷 PUBCOMP Payload PUBCOMP报文没有有效载荷。 3.7.4 PUBCOMP 行为 PUBCOMP Actions 描述见4.3.3节。 项目主页 MQTT v5.0协议草案中文版 3.8 SUBSCRIBE - 订阅请求 客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。每个订阅(Subscription)注册客户端所感兴趣的一个或多个主题。服务端向客户端发送PUBLISH报文以转发被发布到符合这些订阅主题的应用消息。SUBSCRIBE报文同样(为每个订阅)指定了服务端可以向其发送的应用消息最大QoS等级。 3.8.1 固定报头 SUBSCRIBE Fixed Header 图 3-20 – SUBSCRIBE报文固定报头 SUBSCRIBE packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (8)保留位10000010byte 2剩余长度 SUBSCRIBE报文固定报头第3,2,1,0比特位是保留位,必须被设置为0,0,1,0。服务端必须将其他的任何值都当做是不合法的并关闭网络连接 [MQTT-3.8.1-1]。 剩余长度字段表示可变报头的长度加上有效载荷的长度,被编码为变长字节整数。 3.8.2 可变报头 SUBSCRIBE Variable Header SUBSCRIBE报文可变报头按顺序包含以下字段:报文标识符(Packet Identifier),属性(Properties)。2.2.1节提供了更多关于报文标识符的信息。属性的编码规则如2.2.2节所述。 非规范示例 图3-19展示了一个包含报文标识符为10,且没有属性的SUBSCRIBE可变报头。 图 3-19 – SUBSCRIBE 可变报头示例 SUBSCRIBE Variable Header example 说明76543210报文标识符byte 1报文标识符MSB (0)00000000byte 2报文标识符LSB (10)00001010byte 3属性长度 (0)00000000 3.8.2.1 SUBSCRIBE 属性 SUBSCRIBE Properties 3.8.2.1.1 属性长度 Property Length SUBSCRIBE报文可变报头中的属性长度被编码为变长字节整数。 3.8.2.1.2 订阅标识符 Subscription Identifier 11 (0x0B) ,订阅标识符(Subscription Identifier)标识符。跟随其后的是一个变长字节整数表示订阅标识符。订阅标识符取值范围从1到268,435,455。订阅标识符的值为0或包含多个订阅标识符将造成协议错误(Protocol Error)。 订阅标识符与SUBSCRIBE报文所创建或修改的订阅(Subscription)相关联。如果包含订阅标识符,它将与订阅一起被存储。如果未指定此属性,则订阅被存储时将不包含订阅标识符。 更多关于订阅标识符的处理信息,参考3.8.3.1节。 3.8.2.1.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。 用户属性允许出现多次,以表示多个名字/值对。同样的名字允许出现多次。 非规范评注 SUBSCRIBE报文的用户属性可以被客户端用来向服务端发送订阅相关的属性。本规范不定义这些属性的意义。 3.8.3 SUBSCRIBE 载荷 SUBSCRIBE Payload SUBSCRIBE报文的载荷包含一列主题过滤器,指明客户端希望订阅的主题。主题过滤器必须为UTF-8 编码的字符串 [MQTT-3.8.3-1]。每个主题过滤器之后跟着一个订阅选项(Subscription Options)字节。 载荷必须包含至少一个主题过滤器/订阅选项对 [MQTT-3.8.3-2]。不包含载荷的SUBSCRIBE报文将造成协议错误(Protocol Error)。错误处理信息,参考4.13节。 3.8.3.1 订阅选项 Subscription Options 订阅选项的第0和1比特代表最大服务质量字段。此字段给出服务端可以向此客户端发送的应用消息的最大QoS等级。最大服务质量字段为3将造成协议错误(Protocol Error)。 订阅选项的第2比特表示非本地(No Local)选项。值为1,表示应用消息不能被转发给发布此消息的客户标识符 [MQTT-3.8.3-3]。共享订阅时把非本地选项设为1将造成协议错误(Protocol Error) [MQTT-3.8.3-4]。 订阅选项的第3比特表示发布保留(Retain As Published)选项。值为1,表示向此订阅转发应用消息时保持消息被发布时设置的保留(RETAIN)标志。值为0,表示向此订阅转发应用消息时把保留标志设置为0。当订阅建立之后,发送保留消息时保留标志设置为1。 订阅选项的第4和5比特表示保留操作(Retain Handling)选项。此选项指示当订阅建立时,是否发送保留消息。此选项不影响之后的任何保留消息的发送。如果没有匹配主题过滤器的保留消息,则此选项所有值的行为都一样。值可以设置为:0 = 订阅建立时发送保留消息1 = 订阅建立时,若该订阅当前不存在则发送保留消息2 = 订阅建立时不要发送保留消息保留操作的值设置为3将造成协议错误(Protocol Error)。 订阅选项的第6和7比特为将来所保留。服务端必须把此保留位非0的SUBSCRIBE报文当做无效报文 [MQTT-3.8.3-5]。 非规范评注 非本地(No Local)和发布保留(Retain As Published)订阅选项在客户端把消息发送给其他服务端的情况下,可以被用来实现桥接。 非规范评注 已存在订阅的情况下不发送保留消息是很有用的,比如重连完成时客户端不确定订阅是否在之前的会话连接中被创建。 非规范评注 不发送保存的保留消息给新创建的订阅是很有用的,比如客户端希望接收变更通知且不需要知道最初的状态。 非规范评注 对于某个指示其不支持保留消息的服务端,发布保留和保留处理选项的所有有效值都将得到同样的结果:订阅时不发送任何保留消息,且所有消息的保留标志都会被设置为0。 图 3-20 – SUBSCRIBE报文载荷格式 SUBSCRIBE packet Payload format 说明76543210主题过滤器byte 1长度 MSBbyte 2长度 LSBbyte 3..N主题过滤器(Topic Filter)订阅选项保留位保留处理RAPNLQoSbyte N+100XXXXXX RAP指发布保留(Retain as Published)。NL指非本地(No Local)。 图 3-21 – 载荷字节格式非规范示例 Payload byte format non-normative example 说明76543210主题过滤器byte 1长度MSB (0)00000000byte 2长度LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010订阅选项byte 6订阅选项 (1)00000001主题过滤器byte 7长度MSB (0)00000000byte 8长度LSB (3)00000011byte 9‘c’ (0x63)01100011byte 10‘/’ (0x2F)00101111byte 11‘d’ (0x64)01100100订阅选项byte 12订阅选项 (2)00000010 3.8.4 SUBSCRIBE 行为 SUBSCRIBE Actions 当服务端收到来自客户端的SUBSCRIBE报文时,必须使用SUBACK报文作为相应 [MQTT-3.8.4-1]。SUBACK报文必须和待确认的SUBSCRIBE报文有相同的报文标识符 [MQTT-3.8.4-2]。 允许服务端在发送SUBACK报文之前就开始发送与订阅相匹配的PUBLISH报文。 如果服务端收到的SUBSCRIBE报文中的一个主题过滤器与当前会话的一个非共享订阅(Non-shared Subscription)相同,那么必须使用新的订阅替换现存的订阅 [MQTT-3.8.4-3]。新订阅的主题过滤器与之前的订阅相同,但其订阅选项可能不同。如果保留处理选项为0,任何匹配该主题过滤器的保留消息必须被重发,但替换订阅不能造成应用消息的丢失 [MQTT-3.8.4-4]。 如果服务端收到的非共享主题过滤器(Non-shared Topic Filter)不同于当前会话的任何主题过滤器,一个新的非共享订阅将被创建。如果保留处理选项不为2,所有相匹配的保留消息将发送给客户端。 如果服务端收到的主题过滤器与服务端已存在的某个共享订阅(Shared Subscription)主题过滤器相同,则将此会话添加到该共享订阅中。不发送任何保留消息。 如果服务端收到的共享订阅主题过滤器(Shared Subscription Topic Filter)与任何已存在的共享订阅主题过滤器都不同,一个新的共享订阅将被创建。将此会话作为订阅者添加到该共享订阅。不发送任何保留消息。 更多关于共享订阅的细节,参考4.8节。 如果服务端收到的SUBSCRIBE报文包含多个主题过滤器,服务端必须当做收到一系列多个SUBSCRIBE报文来处理--除了将它们的响应组合为单个SUBACK响应 [MQTT-3.8.4-5]。 服务端发送给客户端的SUBACK报文必须为每一个主题过滤器/订阅选项对包含一个原因码 [MQTT-3.8.4-6]。 此原因码必须说明为该订阅授予的最大QoS等级,或指示订阅失败 [MQTT-3.8.4-7]。服务端可能授予了低于订阅者所请求的最大QoS等级。响应该订阅的应用消息QoS等级必须为该消息发布时的QoS等级和服务端授予的最大QoS等级二者最小值 [MQTT-3.8.4-8]。在原始消息发布的QoS等级为1,且授予的最大QoS等级为0的情况下,服务端允许发送重复的消息副本给订阅者(?)。 非规范评注 如果订阅客户端的某个主题过滤器已被授予的最大QoS等级为1,那么匹配此过滤器的QoS等级为0的应用消息按照QoS等级为0分发给此客户端。这意味着客户端最多只能收到该消息的一个副本。另一方面,发布到相同主题的QoS等级为2的消息,其QoS等级被服务端降级为1以便分发给该客户端。因此该客户端可能收到此消息的多个副本。 非规范评注 如果订阅客户端被授予的最大QoS等级为0,那么按照QoS等级为2发布的应用消息在繁忙时可能会丢失,但服务端不应该发送重复的消息副本。发布到相同主题的QoS等级为1的消息,分发给该客户端时可能会丢失或重复。 非规范评注 使用QoS等级2订阅某个主题过滤器,等于是说:我想要按照消息被发布时的QoS等级接收匹配此过滤器的消息 。这意味着发布者负责决定消息可以被发布的最大QoS等级,但订阅端可以要求服务端降低该消息的QoS到更适合它的等级。 订阅标识符是服务端的会话状态的一部分,并将在收到PUBLISH报文时返回给客户端。当服务端收到客户端的UNSUBSCRIBE报文时,服务端将此会话标识符从服务端的会话状态中移除:当服务端收到客户端的UNSUBSCRIBE报文,当服务端收到客户端对同样主题过滤器的SUBSCRIBE报文但订阅标识符不同或没有订阅标识符,或者当服务端在CONNACK报文中将会话存在标志设置为0。 订阅标识符不构成客户端的会话状态的一部分。在一个有用的实现中,客户端将订阅标识符与其他客户端状态相关联,此客户端状态将被移除:当客户端取消订阅,当客户端以不同的订阅标识符或没有订阅标识符订阅同样的主题过滤器,或者当客户端收到的CONNACK报文中会话存在标志被设置为0。 服务端在重传的PUBLISH报文中无需使用同一组订阅标识符。客户端可以通过发送包含与当前会话已存在的主题过滤器的SUBSCRIBE报文进行重新订阅。如果客户端在PUBLISH报文初传之后重新订阅并使用了不同的订阅标识符,允许服务端在任何重传中使用初传所包含的订阅标识符,或者在重传中使用此新的订阅标识符。不允许服务端在发送了包含新的订阅标识符的PUBLISH报文之后再次使用旧的订阅标识符。 非规范评注 使用场景,用以阐述订阅标识符: 客户端实现指示某条发布消息匹配多个订阅的编程接口,客户端实现每次订阅时生成新的订阅标识符。如果返回的发布消息包含多个订阅标识符,则该发布消息匹配多个订阅。 客户端实现允许订阅者将消息定向到其相关联的订阅的回调,客户端实现生成映射到唯一回调的订阅标识符。收到某条发布消息时,使用订阅标识符决定触发哪一个回调。 客户端实现在发布消息时返回程序用于订阅的主题字符串,为此客户端生成一个唯一标识了该主题过滤器的标识符。收到某条发布消息时,客户端实现使用此标识符查找原始主题过滤器,并将主题过滤器返回给其应用程序。 网关(Gateway)将从服务端收到的发布消息转发给向该网关做了订阅的客户端,网关实现维护其收到的每个唯一的订阅过滤器到其收到的一组客户标识符--订阅标识符对的映射,网关对它转发给服务端的每个主题过滤器生成一个唯一的标识符。收到某条发布消息时,网关使用从服务端收到的订阅标识符查找对应的客户标识符--订阅标识符对,并把它们加入发送给客户端的PUBLISH报文中。如果上游服务端因为消息匹配了多个订阅而发送了多个PUBLISH报文,则此行为将反映到客户端。 项目主页 MQTT v5.0协议草案中文版 3.9 SUBACK – 订阅确认 服务端发送SUBACK报文给客户端,用于确认它已收到并且正在处理SUBSCRIBE报文。 SUBACK报文包含一个原因码列表,用于指定授予的最大QoS等级或SUBSCRIBE报文所请求的每个订阅发生的错误。 3.9.1 SUBACK 固定报头 SUBACK Fixed Header 图 3-24 – SUBACK报文固定报头 SUBACK Packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (9)保留位10010000byte 2剩余长度 剩余长度字段可变报头长度加上有效载荷长度,编码为变长字节整数。 3.9.2 SUBACK 可变报头 SUBACK Variable Header SUBACK报文可变报头按顺序包含以下字段:所确认的SUBSCRIBE报文标识符,属性(Properties)。 图例 3.25 – SUBACK报文可变报头 3.9.2.1 SUBACK 属性 SUBACK Properties 3.9.2.1.1 属性长度 Property Length SUBACK可变报头中的属性长度被编码为变长字节整数。 3.9.2.1.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。如果加上原因字符串之后的SUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串 [MQTT-3.9.2-1]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.9.2.1.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的SUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性 [MQTT-3.9.2-2]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 图 3-23 - SUBACK报文可变报头 SUBACK packet Variable Header Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSB 3.9.3 SUBACK 载荷 SUBACK Payload 有效载荷包含一个原因码列表。每个原因码对应SUBSCRIBE报文中的一个被确认的主题过滤器。SUBACK报文中的原因码顺序必须与SUBSCRIBE报文中的主题过滤器顺序相匹配 [MQTT-3.9.3-1]。 表 3-8 - 订阅原因码 Subscribe Reason Codes 值16进制原因码名称说明00x00授予QoS等级0订阅被接受且最大QoS等级为0。可能低于所请求的QoS等级。10x01授予QoS等级1订阅被接受且最大QoS等级为1。可能低于所请求的QoS等级。20x02授予QoS等级2订阅被接受且最大QoS等级为2。可能低于所请求的QoS等级。1280x80未指明错误订阅未被接受,且服务端不愿意透露原因或没有适用的原因码。1310x83实现特定错误SUBSCRIBE有效但不被服务端所接受。1350x87未授权客户端未被授权做此订阅。1430x8F主题过滤器无效主题过滤器格式正确,但不被允许。1450x91报文标识符已被占用指定的报文标识符正在被使用中。1510x97超出配额已超出实现限制或管理限制。1580x9E共享订阅不支持服务端不支持此客户端进行共享订阅。1610xA1订阅标识符不支持服务端不支持订阅标识符;订阅标识符不被接受。1620xA2通配符订阅不支持服务端不支持通配符订阅;订阅未被接受。 服务端发送SUBACK报文时必须对收到的每一个主题过滤器设置一种原因码 [MQTT-3.9.3-2]。 非规范评注 对于SUBSCRIBE报文中的每个主题过滤器,总有一个对应的原因码。如果原因码不是针对某个特定的主题过滤器(比如0x91(报文标识符已占用)),则对每个主题过滤器都使用此原因码。 项目主页 MQTT v5.0协议草案中文版 3.10 UNSUBSCRIBE –取消订阅请求 客户端发送UNSUBSCRIBE报文给服务端,用于取消订阅主题。 3.10.1 UNSUBSCRIBE 固定报头 UNSUBSCRIBE Fixed Header 图 3-28 – UNSUBSCRIBE报文固定报头 Bit76543210byte 1MQTT控制报文类型 (10)保留位10100010byte 2剩余长度 UNSUBSCRIBE固定报头的第3,2,1,0位是保留位且必须分别设置为0,0,1,0。服务端必须认为任何其它的值都是不合法的并关闭网络连接 [MQTT-3.10.1-1]。 剩余长度字段等于可变报头长度(2字节)加上有效载荷长度,编码为变长字节整数。 3.10.2 UNSUBSCRIBE 可变报头 UNSUBSCRIBE Variable Header UNSUBSCRIBE报文可变报头按顺序包含以下字段:报文标识符和属性(Properties)。2.2.1节提供了有关报文标识符的更多信息。属性的编码规则,如2.2.2节所述。 3.10.2.1 UNSUBSCRIBE 属性 UNSUBSCRIBE Properties 3.10.2.1.1 属性长度 Property Length SUBSCRIBE可变报头中属性的长度被编码为变长字节整数。 3.10.2.1.2 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是一个UTF-8字符串对。 用户属性允许出现多次,以表示多个名字/值对。相同的名字可以出现多次。 非规范评注 UNSUBSCRIBE报文中的用户属性可以被客户端用来向服务端发送订阅相关的属性。本规范不定义这些属性的意义。 3.10.3 3.10.3 UNSUBSCRIBE 载荷 UNSUBSCRIBE Payload UNSUBSCRIBE报文有效载荷包含一列客户端希望取消订阅的主题过滤器。UNSUBSCRIBE报文中的主题过滤器必须为1.5.4节所述的UTF-8编码字符串 [MQTT-3.10.3-1] ,且连续填充。 UNSUBSCRIBE报文有效载荷必须包含至少一个主题过滤器 [MQTT-3.10.3-2]。不包含有效载荷的UNSUBSCRIBE报文将造成协议错误(Protocol Error)。错误处理信息,参考4.13节。 非规范示例 图 3-30 展示了UNSUBSCRIBE报文的载荷示例,包括两个主题过滤器 “a/b”和“c/d”。 图 3-30 - 载荷字节格式非规范示例 Payload byte format non-normative example 说明76543210主题过滤器byte 1长度MSB (0)00000000byte 2长度LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010主题过滤器byte 6长度MSB (0)00000000byte 7长度LSB (3)00000011byte 8‘c’ (0x63)01100011byte 9‘/’ (0x2F)00101111byte 10‘d’ (0x64)01100100 3.10.4 UNSUBSCRIBE 行为 UNSUBSCRIBE Actions 服务端必须对客户端的UNSUBSCRIBE报文中提供的主题过滤器(不管是否包含通配符)逐个字符与当前持有的主题过滤器集进行比较。如果任何过滤器完全匹配,则必须删除其拥有的订阅 [MQTT-3.10.4-1],否则不会进行额外的处理。 当服务端收到UNSUBSCRIBE报文: 它必须停止添加为了交付给客户端的与主题过滤器相匹配的任何新消息 [MQTT-3.10.4-2]。 它必须完成任何已经开始发送给客户端的、与主题过滤器相匹配的、QoS等级为1或2的消息 [MQTT-3.10.4-3]。 它可以继续交付任何为交付给客户端而缓存的消息。 服务端必须发送UNSUBACK报文以响应客户端的UNSUBSCRIBE请求 [MQTT-3.10.4-4]。UNSUBACK报文必须包含和UNSUBSCRIBE报文相同的报文标识符。即使没有删除任何主题订阅,服务端也必须发送一个UNSUBACK响应 [MQTT-3.10.4-5]。 如果服务端收到的UNSUBSCRIBE报文包含多个主题过滤器,服务端必须当做收到一系列多个UNSUBSCRIBE报文来处理--除了将它们的响应组合为单个SUBACK响应 [MQTT-3.10.4-6]。 如果某个主题过滤器代表一个共享订阅,此会话将被从该共享订阅中删除。如果此会话是该共享订阅所关联的唯一会话,该共享订阅被删除。共享订阅的处理,参考4.8.2节。 项目主页 MQTT v5.0协议草案中文版 3.11 UNSUBACK – 取消订阅确认 服务端发送UNSUBACK报文给客户端用于确认收到UNSUBSCRIBE报文。 3.11.1 UNSUBACK 固定报头 UNSUBACK Fixed Header 图 3-31 – UNSUBACK 报文固定报头 UNSUBACK packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (11)保留位10110000byte 2剩余长度 剩余长度字段表示可变报头的长度,对UNSUBACK报文这个值等于2。 3.11.2 UNSUBACK 可变报头 UNSUBACK Variable Header UNSUBACK报文可变报头按顺序包含以下字段:所确认的UNSUBSCRIBE报文标识符和属性( Properties)。属性的编码规则如2.2.2节所述。 图 3-32 – UNSUBACK 报文可变报头 UNSUBACK packet Variable Header Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSB 3.11.2.1 UNSUBACK 属性 UNSUBACK Properties 3.11.2.1.1 属性长度 Property Length UNSUBACK报文可变报头中的属性的长度被编码为变长字节整数。 3.11.2.1.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。如果加上原因字符串之后的UNSUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串 [MQTT-3.11.2-1]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.11.2.1.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的UNSUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性 [MQTT-3.11.2-2]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.11.3 UNSUBACK 载荷 UNSUBACK Payload 有效载荷包含一个原因码列表。每个原因码对应UNSUBSCRIBE报文中的一个被确认的主题过滤器。UNSUBACK报文中的原因码顺序必须与UNSUBSCRIBE报文中的主题过滤器顺序相匹配 [MQTT-3.11.3-1]。 单字节无符号取消订阅原因码的值如下所示。服务端发送UNSUBACK报文时对于每个收到的主题过滤器,必须使用一个取消订阅原因码 [MQTT-3.11.3-2]。 表 3-9 – UNSUBACK 报文可变报头 UNSUBACK packet Variable Header 值16进制原因码名称说明00x00成功订阅已被删除。170x11订阅未发现没有该客户端匹配的主题过滤器被使用。1280x80未指定错误取消订阅不能被完成且服务端不愿意透露原因或没有其他适用的原因码。1310x83实现指定错误UNSUBSCRIBE报文有效,但服务端不接受。1350x87未授权客户端未被授权进行取消订阅。1430x8F主题过滤器无效主题过滤器格式正确,但不被允许。1450x91报文标识符已占用指定的报文标识符正在被使用中。 非规范评注 对于UNSUBSCRIBE报文中的每个主题过滤器,总有一个对应的原因码。如果原因码不是针对某个特定的主题过滤器(比如0x91(报文标识符已占用)),则对每个主题过滤器都使用此原因码。 项目主页 MQTT v5.0协议草案中文版 3.12 PINGREQ – PING 请求 客户端发送PINGREQ报文给服务端,可被用于: 在没有任何其他MQTT控制报文从客户端发给服务端时,告知服务端客户端还活着。 请求服务端发送响应以确认服务端还活着。 使用网络已确认网络连接没有断开。 此报文被用在保持连接(Keep Alive)的处理中。详细信息,参考3.1.2.10节。 3.12.1 PINGREQ 固定报头 PINGREQ Fixed Header 图 3-33 – PINGREQ 报文固定报头 PINGREQ packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (12)保留位11000000byte 2剩余长度 (0)00000000 3.12.2 PINGREQ 可变报头 PINGREQ Variable Header PINGREQ报文没有可变报头。 3.12.3 PINGREQ 有效载荷 PINGREQ Payload PINGREQ报文没有有效载荷。 3.12.4 PINGREQ 行为 PINGREQ Actions 服务端必须发送PINGRESP报文响应客户端的PINGREQ报文 [MQTT-3.12.4-1]。 项目主页 MQTT v5.0协议草案中文版 3.13 PINGRESP – 心跳响应 服务端发送PINGRESP报文响应客户端的PINGREQ报文。表示服务端还活着。 保持连接(Keep Alive)处理中用到这个报文,详情请查看 3.1.2.10节。 3.13.1 固定报头 PINGRESP Fixed Header 图例 3-34 – PINGRESP 报文固定报头 PINGRESP packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (13)保留位11010000byte 2剩余长度00000000 3.13.2 PINGRESP 可变报头 PINGRESP Variable Header PINGRESP报文没有可变报头。 3.13.3 PINGRESP 载荷 PINGRESP Payload PINGRESP报文没有有效载荷。 3.13.4 PINGRESP 行为 PINGRESP Actions 客户端收到此报文时不做任何处理。 项目主页 MQTT v5.0协议草案中文版 3.14 DISCONNECT – 断开通知 DISCONNECT报文是客户端发给服务端的最后一个MQTT控制报文。表示客户端为什么断开网络连接的原因。客户端和服务端在关闭网络连接之前可以发送一个DISCONNECT报文。如果在客户端没有首先发送包含原因码为0x00(正常断开)DISCONNECT报文并且连接包含遗嘱消息的情况下,遗嘱消息会被发布。更多细节,参考3.1.2.5节。 服务端不能发送DISCONNECT报文,直到它发送了包含原因码小于0x80的CONNACK报文之后 [MQTT-3.14.0-1]。 3.14.1 DISCONNECT 固定报头 DISCONNECT Fixed Header 图例 3-35 – DISCONNECT 报文固定报头 DISCONNECT packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (14)保留位11100000byte 2剩余长度 服务端或客户端必须验证所有的保留位都被设置为0,如果他们不为0,发送包含原因码为0x81(无效报文)的DISCONNECT报文,如4.13节所述 [MQTT-3.14.1-1]。 剩余长度字段等于可变报头的长度,编码为变长字节整数。 3.14.2 DISCONNECT 可变报头 DISCONNECT Variable Header DISCONNECT报文的可变报头按顺序包含以下字段:断开原因码,属性(Properties)。属性的编码规则如2.2.2节所述。 3.14.2.1 DISCONNECT 断开原因码 Disconnect Reason Code 可变报头的第1个字节是断开原因码。如果剩余长度小于1,则表示使用原因码0x00(正常断开)。 单字节无符号断开原因码字段如下所示。 表 3-10 – 断开原因值 Disconnect Reason Code 值16进制原因码名称发送端说明00x00正常断开客户端或服务端正常关闭连接。不发送遗嘱。40x04包含遗嘱消息的断开客户端客户端希望断开但也需要服务端发布它的遗嘱消息。1280x80未指定错误客户端或服务端连接被关闭,但发送端不愿意透露原因,或者没有其他适用的原因码。1290x81无效的报文客户端或服务端收到的报文不符合本规范。1300x82协议错误客户端或服务端收到意外的或无序的报文。1310x83实现指定错误客户端或服务端收到的报文有效,但根据实现无法进行处理。1350x87未授权服务端请求没有被授权1370x89服务端正忙服务端服务端正忙且不能继续处理此客户端的请求。1390x8B服务正关闭服务端服务正在关闭。1410x8D保持连接超时服务端连接因为在超过1.5倍的保持连接时间内没有收到任何报文而关闭。1420x8E会话被接管服务端另一个使用了相同的客户标识符的连接已建立,导致此连接关闭。1430x8F主题过滤器无效服务端主题过滤器格式正确,但不被服务端所接受。1440x90主题名无效客户端或服务端主题名格式正确,但不被客户端或服务端所接受。1470x93超出接收最大值客户端或服务端客户端或服务端收到了数量超过接收最大值的未发送PUBACK或PUBCOMP的发布消息。1480x94主题别名无效客户端或服务端客户端或服务端收到的PUBLISH报文包含的主题别名大于其在CONNECT或CONNACK中发送的主题别名最大值。1490x95报文过大客户端或服务端报文长度大于此客户端或服务端的最大报文长度。1500x96消息速率过高客户端或服务端收到的数据速率太高。1510x97超出配额客户端或服务端已超出实现限制或管理限制。1520x98管理操作客户端或服务端连接因为管理操作被关闭。1530x99载荷格式无效客户端或服务端载荷格式与指定的载荷格式指示符不匹配。1540x9A不支持保留服务端服务端不支持保留消息。1550x9B不支持的QoS等级服务端客户端指定的QoS等级大于CONNACK报文中指定的最大QoS等级。1560x9C(临时)使用其他服务端服务端客户端应该临时使用其他服务端。1570x9D服务端已(永久)移动服务端服务端已移动且客户端应该永久使用其他服务端。1580x9E不支持共享订阅服务端服务端不支持共享订阅。1590x9F超出连接速率限制服务端此连接因为连接速率过高而被关闭。1600xA0最大连接时间服务端超出为此连接授予的最大连接时间。1610xA1不支持订阅标识符服务端服务端不支持订阅标识符;订阅未被接受。1620xA2不支持通配符订阅服务端服务端不支持通配符订阅;订阅未被接受。 客户端或服务端发送DISCONNECT报文时必须使用一种DISCONNECT原因码 [MQTT-3.14.2-1]。如果原因码为0x00(正常断开)且没有属性,原因码和属性长度可以被省略。这种情况下DISCONNECT报文剩余长度为0。 非规范评注 DISCONNECT报文用于指示断开的原因,例如没有确认报文(比如QoS等级0的发布消息)或当客户端或服务端不能继续处理连接。 非规范评注 客户端可以使用这些信息来决定是否重新连接,以及在重新尝试之前应该等待多长时间。 3.14.2.2 DISCONNECT 属性 DISCONNECT Properties 3.14.2.2.1 属性长度 Property Length DISCONNECT报文可变报头中的属性(Properties)的长度被编码为变长字节整数。如果剩余长度小于2,属性长度使用0。 3.14.2.2.2 会话过期间隔 Session Expiry Interval 17 (0x11) ,会话过期间隔(Session Expiry Interval)标识符。跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话过期间隔将造成协议错误(Protocol Error)。 如果没有设置会话过期间隔,则使用CONNECT报文中的会话过期间隔。 会话过期间隔不能由服务端的DISCONNECT报文发送 [MQTT-3.14.2-2]。 如果CONNECT报文中的会话过期间隔为0,则客户端在DISCONNECT报文中设置非0会话过期间隔将造成协议错误(Protocol Error)。如果服务端收到这种非0会话过期间隔,则不会将其视为有效的DISCONNECT报文。服务端使用包含原因码为0x82(协议错误)的DISCONNECT报文,如4.13节所述。 3.14.2.2.3 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码字符串表示断开原因。此原因字符串是为诊断而设计的可读字符串,不应该被接收端所解析。 如果此属性使得DISCONNECT报文的长度超出了接收端指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.14.2-3]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.14.2.2.4 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的DISCONNECT报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.14.2-4]。用户属性允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.14.2.2.5 服务端参考 Server Reference 28 (0x1C) ,服务端参考(Server Reference)标识符。跟随其后的是一个UTF-8编码字符串,客户端可以使用它来识别其他要使用的服务端。包含多个服务端参考将造成协议错误(Protocol Error)。 服务端发送包含一个服务端参考和原因码0x9C((临时)使用其他服务端)或0x9D(服务端已(永久)移动)的DISCONNECT报文,如4.13节所述。 关于如何使用服务端参考,参考4.11节服务端重定向。 图 3-24 - DISCONNECT 报文可变报头非规范示例 DISCONNECT packet Variable Header non-normative example 说明76543210断开原因码byte 100000000属性byte 2长度 (5)00000111byte 3会话过期间隔标识符 (17)00010001byte 4会话过期间隔标识符 (17)00000000byte 500000000byte 600000000byte 700000000 3.14.3 DISCONNECT 有效载荷 DISCONNECT Payload DISCONNECT报文没有有效载荷。 3.14.4 DISCONNECT 行为 DISCONNECT Actions 发送端发送完DISCONNECT报文之后: 不能再在此网络连接上发送任何MQTT控制报文 [MQTT-3.14.4-1]。 必须关闭网络连接 [MQTT-3.14.4-2]。 接收到包含原因码为0x00(成功)的DISCONNECT时,服务端: 必须丢弃任何与当前连接相关的遗嘱消息,而不发布它 [MQTT-3.14.4-3],如3.1.2.5节所述。 接收到DISCONNECT报文时,接收端: 应该关闭网络连接 项目主页 MQTT v5.0协议草案中文版 3.15 AUTH – 认证交换 AUTH报文被从客户端发送给服务端,或从服务端发送给客户端,作为扩展认证交换的一部分,比如质询/响应认证。如果CONNECT报文不包含相同的认证方法,则客户端或服务端发送AUTH报文将造成协议错误(Protocol Error)。 3.15.1 AUTH 固定报头 AUTH Fixed Header 图例 3-35 – AUTH 报文固定报头 AUTH packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (15)保留位11110000byte 2剩余长度 AUTH报文固定报头第3,2,1,0位是保留位,必须全设置为0。客户端或服务端必须把其他值当做无效值并关闭网络连接 [MQTT-3.15.1-1]。 剩余长度字段等于可变报头的长度,编码为变长字节整数。 3.15.2 AUTH 可变报头 AUTH Variable Header AUTH报文可变报头按顺序包含以下字段:认证原因码(Authentication Reason Code),属性(Properties)。属性的编码规则,如2.2.2节所述。 3.15.2.1 认证原因码 Authenticate Reason Code 可变报头第0字节是认证原因码(Authenticate Reason Code)。单字节无符号认证原因码字段的值如下所示。AUTH报文的发送端必须使用一种认证原因码 [MQTT-3.15.2-1]。 表 3-11 – 认证原因码 Authenticate Reason Codes 值16进制原因码名称发送端说明00x00成功服务端认证成功。240x18继续认证客户端或服务端继续下一步认证。250x19重新认证客户端开始重新认证。 如果原因码为0x00(成功)并且没有属性字段,则可以省略原因码和属性长度。这种情况下,AUTH报文剩余长度为0。 3.15.2.2 AUTH 属性 AUTH Properties 3.15.2.2.1 属性长度 Property Length AUTH报文可变报头中的属性的长度被编码为变长字节整数。 3.15.2.2.2 认证方法 Authentication Method *21 (0x15) ,认证方法(Authentication Method)标识符。跟随其后的是一个UTF-8编码字符串,包含认证方法名称。省略认证方法或者包含多个认证方法都将造成协议错误(Protocol Error)。更多关于扩展认证的信息,参考4.12节。 3.15.2.2.3 认证数据 Authentication Data 22 (0x16) ,认证数据(Authentication Data)标识符。跟随其后的是二进制数据,包含认证数据。包含多个认证数据将造成协议错误(Protocol Error)。此数据的内容由认证方法定义。更多关于扩展认证的信息,参考4.12节。 3.15.2.2.4 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码字符串,表示断开原因。此原因字符串是为诊断而设计的可读字符串,不应该被接收端所解析。 如果加上原因字符串之后的AUTH报文长度超出了接收端所指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.15.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.15.2.2.5 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的AUTH报文长度超出了接收端指定的最大报文长度,则服务端不能发送此属性 [MQTT-3.15.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.15.3 AUTH 载荷 AUTH Payload AUTH报文没有有效载荷。 更多关于扩展认证的信息,参考4.12节。 项目主页 MQTT v5.0协议草案中文版 第四章 操作行为 Operational behavior 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] 4.1 会话状态 Session State 为实现QoS等级1和QoS等级2协议流,客户端和服务端需要将状态与客户标识符相关联,这被称为会话状态。服务端还将订阅信息存储为会话状态的一部分。 会话可以跨越一系列的网络连接。它持续到最新的网络连接(Network Connections)加上会话过期间隔(Session Expiry Interval)。 客户端的会话状态包括: 已发送给服务端,但是还没有完成确认的QoS等级1和QoS等级2的消息。 从服务端收到的,但是还没有完成确认的QoS等级2消息。 服务端的会话状态包括: 会话是否存在,即使会话状态其余部分为空。 客户端订阅信息,包括任何订阅标识符。 已发送给客户端,但是还没有完成确认的QoS等级1和QoS等级2的消息。 等待传输给客户端的QoS等级0(可选),QoS等级1和QoS等级2的消息。 从客户端收到的,但是还没有完成确认的QoS等级2消息。遗嘱小子和遗嘱延时间隔。 如果会话当前未连接,会话结束时间和会话状态将被丢弃。 保留消息不是会话状态的一部分,会话结束时不被删除。 4.1.1 存储会话状态 Storing Session State 当网络连接打开时,客户端和服务端不能丢弃会话状态 [MQTT-4.1.0-1]。当网络连接被关闭并且会话过期间隔已过时,服务端必须丢弃会话状态 [MQTT-4.1.0-2]。 非规范评注 客户端和服务端实现的存储容量必然是有限的,还可能要受管理策略的限制。已存储的会话状态可能因为管理操作(比如某个预定义条件的自动响应)而被丢弃。它造成的后果就是会话终止。这些操作可能是因为资源受限或其他操作原因引发的。硬件或软件故障可能导致客户端或服务端存储的会话状态丢失或损坏。需要谨慎的评估客户端和服务端的存储能力,以确保存储空间充足。 4.1.2 会话状态非规范示例 Session State non-normative examples 例如,想要收集电表读数的用户可能会决定使用QoS等级1的消息,因为他们不能接受数据在网络传输途中丢失,但是,他们可能认为客户端和服务端的数据可以存储在内存(易失性存储器)中,因为(他们觉得)电力供应是非常可靠的,不会有太大的数据丢失风险。 与之相反,停车计费支付应用的提供商可能决定任何情况下都不能让数据支付消息丢失,因此他们要求在通过网络传输之前将所有的数据写入到非易失性存储器中(如硬盘)。 4.2 网络连接 Network Connections MQTT协议要求基础传输层能够提供有序的、可靠的、双向传输(从客户端到服务端和从服务端到客户端)字节流。此规范不要求任何指定的传输协议。客户端或服务端可以支持这里列出的任何传输协议,或者满足本节要求的任何其他传输协议。 客户端或服务端必须支持使用一个或多个提供有序的、可靠的、双向传输(从客户端到服务端和从服务端到客户端)字节流传输的底层传输协议 [MQTT-4.2-1]。 非规范评注 MQTT 3.1使用的传输层协议是 [RFC793] 定义的TCP/IP协议。下面的协议也支持: TLS协议 [RFC5246] WebSocket协议 [RFC6455] 非规范评注 TCP端口8883和1883已在IANA注册,分别用于MQTT的TLS和非TLS通信。 非规范评注 无连接的网络传输,如用户数据包协议 (UDP) 本身不适合,因为它们可能丢失或重新排列数据。 4.3 服务质量等级和协议流程 Quality of Service levels and protocol flows MQTT按照后面章节定义的服务质量(QoS)等级分发应用消息。分发协议是对称的,在下面的描述中,客户端和服务端既可以是发送端也可以是接收端。分发协议关注的是从单个发送者到单个接收者的应用消息。服务端分发应用消息给多个客户端时,每个客户端独立处理。分发给客户端的出站应用消息和入站应用消息的QoS等级可能是不同的。 4.3.1 QoS 0:最多分发一次 QoS 0: At most once delivery 消息的分发依赖于底层网络的能力。接收端不会发送响应,发送端也不会重试。消息可能送达一次也可能根本没送达。 对于QoS等级0的分发协议,发送端 必须发送QoS等于0,DUP等于0的PUBLISH报文 [MQTT-4.3.1-1]。 对于QoS等级0的分发协议,接收端 接受PUBLISH报文时同时接受消息的所有权。 图 4-1 - QoS等级0协议流程图,非规范示例 QoS 0 protocol flow diagram, non-normative example 发送端动作控制报文接收端动作PUBLISH报文QoS 0, DUP=0---------->分发应用消息给适当的后续接收者(们) 4.3.2 QoS 1: 至少分发一次 QoS 1: At least once delivery 服务质量等级1确保消息至少送达一次。QoS等级1的PUBLISH报文的可变报头中包含一个报文标识符,需要PUBACK 报文确认。2.2.1节提供了有关报文标识符的更多信息。 对于QoS等级1的分发协议,发送端 每次发送新的应用消息都必须分配一个未使用的报文标识符 [MQTT-4.3.2-1]。 发送的PUBLISH报文必须包含报文标识符且QoS等于1,DUP等于0 [MQTT-4.3.2-2]。 必须将这个PUBLISH报文看作是未确认的 ,直到从接收端那收到对应的PUBACK报文。 4.4节有一个关于未确认消息的讨论 [MQTT-4.3.2-3]。 一旦发送端收到PUBACK报文,这个报文标识符就可以重用。 注意:允许发送端在等待确认时使用不同的报文标识符发送后续的PUBLISH报文。 对于QoS等级1的分发协议,接收端 响应的PUBACK报文必须包含一个报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文 [MQTT-4.3.2-4]。 发送了PUBACK报文之后,接收端必须将任何包含相同报文标识符的入站PUBLISH报文当做一个新的消息,并忽略它的DUP标志的值 [MQTT-4.3.2-5]。 图 4-2 - QoS 1协议流程图,非规范示例 QoS 1 protocol flow diagram, non-normative example 发送端动作控制报文接收端动作存储消息发送PUBLISH报文QoS=1,DUP=0,带报文标识符---------->开始应用消息的后续分发1<----------发送PUBACK报文,带报文标识符丢弃消息 1不要求接收端在发送 PUBACK 之前完整分发应用消息。原来的发送端收到 PUBACK 报文之后,应用消息的所有权就会转移给这个接收端。 4.3.3 QoS 2:仅分发一次 QoS 2: Exactly once delivery 这是最高等级的服务质量,消息丢失和重复都是不可接受的。使用这个服务质量等级会有额外的开销。 QoS等2消息可变报头中有报文标识符。2.2.1节 提供了有关报文标识符的更多信息。QoS等级2的PUBLISH报文的接收端使用一个两部确认过程来确认收到。 对于QoS等级2的分发协议,发送端 必须给要发送的新应用消息分配一个未使用的报文标识符 [MQTT-4.3.3-1]。 发送端PUBLISH报文必须包含报文标识符且报文的QoS等于2,DUP等于0 [MQTT-4.3.3-2]。 必须将这个PUBLISH报文看作是未确认的,直到从接收端那收到对应的PUBREC报文 [MQTT-4.3.3-3]。4.4节有一个关于未确认消息的讨论。 收到发送端发送的包含原因码小于0x80的PUBREC报文后必须发送一个PUBREL报文。PUBREL报文必须包含与原始PUBLISH报文相同的报文标识符 [MQTT-4.3.3-4]。 必须将这个PUBREL报文看作是未确认的 ,直到从接收端那收到对应的PUBCOMP报文 [MQTT-4.3.3-5]。 一旦发送了对应的PUBREL报文就不能重发这个PUBLISH报文 [MQTT-4.3.3-6]。 如果PUBLISH报文已发送,不能应用消息过期属性 [MQTT-4.3.3-7]。 一旦发送端收到包含原因码大于0x80的PUBCOMP报文,这个报文标识符就可以重用。 注意:允许发送端在等待确认时使用不同的报文标识符发送后续的PUBLISH报文,受制于4.9节描述的流量控制。 对于QoS等级2的分发协议,接收端 响应的PUBREC报文必须包含报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文 [MQTT-4.3.3-8]。 如果接收端发送了包含原因码大于等于0x80的PUBREC报文,它必须将后续包含相同报文标识符的PUBLISH报文当做是新的应用消息 [MQTT-4.3.3-9]。 在收到对应的PUBREL报文之前,接收端必须发送PUBREC报文确认任何后续的具有相同报文标识符的PUBLISH报文。在这种情况下,它不能重复分发消息给任何后续的接收者 [MQTT-4.3.3-10]。 必须发送包含与PUBREL相同报文标识符的PUBCOMP报文作为对PUBREL报文的响应 [MQTT-4.3.3-11]。 发送PUBCOMP报文之后,接收端必须将后续包含相同报文标识符的PUBLISH报文当做是新的应用消息 [MQTT-4.3.3-12]。 必须继续QoS等级2确认序列,即使它已经应用了消息过期属性 [MQTT-4.3.3-13]。 4.4 消息分发重试 Message delivery retry 客户端以新开始(Clean Start)标志为0且会话存在的情况下重连时,客户端和服务端都必须使用原始报文标识符重新发送任何未被确认的PUBLISH报文(当QoS > 0)和PUBREL报文。这是唯一要求客户端或服务端重发消息的情况。客户端和服务端不能在其他任何时间重发消息 [MQTT-4.4.0-1]。 如果收到包含原因码大于等于0x80的PUBACK或PUBREC,则对应的PUBLISH报文被看作已确认,且不能被重传 [MQTT-4.4.0-2]。 图 4-3 - QoS 2协议流程图,非规范示例 QoS 2 protocol flow diagram, non-normative example 发送端动作控制报文接收端动作存储消息发送PUBLISH报文QoS=2,DUP=0,带报文标识符---------->存储报文标识符,然后启动应用消息的向前分发1发送PUBREC报文,带报文标识符和原因码<----------丢弃消息,存储PUBREC中的报文标识符发送PUBREL报文,带报文标识符---------->丢弃报文标识符发送PUBCOMP报文,带报文标识符<----------丢弃已保存的状态 1 不要求接收端在发送PUBREC和PUBCOMP之前完整分发应用消息。原始发送端收到PUBREC报文之后,应用消息的所有权就会转移给这个接收端。然而,接收端需要在接受所有权之前执行对所有可能导致转发失败(例如超出配额、权限等)的条件的检查。接收端在PUBREC中使用适当的原因码指示所有权接受成功或失败。 4.5 消息收到 Message receipt 当服务端接受入站应用消息的所有权时,它必须将消息添加到订阅匹配的客户端的会话状态中 [MQTT-4.5.0-1]。匹配规则定义见 4.7节 。 正常情况下,客户端收到的消息是对他们创建的订阅的响应。客户端也可能收到不是与它的订阅精确匹配的消息。如果服务端自动给客户端分配了一个订阅,可能发生这种情况。 UNSUBSCRIBE 操作正在被处理时也可能收到消息。客户端必须按照可用的服务质量(QoS)规则确认它收到的任何PUBLISH报文,不管它是否选择处理其包含的应用消息 [MQTT-4.5.0-2]。 4.6 消息排序 Message ordering 实现4.3节定义的协议流程时,客户端必须遵循下列规则 重发任何之前的PUBLISH报文时,必须按原始PUBLISH报文的发送顺序重发(适用于QoS等级1和QoS等级2消息)[MQTT-4.6.0-1]。 必须按照对应的PUBLISH报文的顺序发送PUBACK报文(QoS等级1消息)[MQTT-4.6.0-2]。 必须按照对应的PUBLISH报文的顺序发送PUBREC报文(QoS等级2消息)[MQTT-4.6.0-3]。 必须按照对应的PUBREC报文的顺序发送PUBREL报文(QoS等级2消息)[MQTT-4.6.0-4]。 一个有序主题(Ordered Topic)是一个主题,在这个主题中,客户端可以确定从同一个客户端接收的相同QoS等级的消息的顺序与他们发布的顺序一致。当服务端处理发布到有序主题的消息时,它必须按照消息从任何给定客户端接收的顺序发送PUBLISH报文给消费端(对于同一主题和QoS等级) [MQTT-4.6.0-5]。这是上面列出的规则的补充。 服务端处理发送给有序主题的消息时,必须按照上面的规则将消息分发给每个订阅者。此外,它必须按照从客户端收到的顺序发送PUBLISH报文给消费者(对相同的主题和QoS)[MQTT-4.6.0-6]。 默认情况下,服务端转发非共享订阅的消息时,必须将每个主题都视为有序主题 [MQTT-4.6.0-6]。服务端可以提供管理或其他机制来允许一个或多个主题不被当作有序主题。 非规范评注 上面列出的规则确保,使用QoS等级1发布和订阅的消息流,订阅者按照消息发布时的顺序收到每条消息的最终副本,但是消息可能会重复,这可能导致在它的后继消息之后收到某个已经收到消息的重发版本。例如,发布者按顺序1,2,3,4发送消息,订阅者收到的顺序可能是1,2,3,2,3,4。 如果客户端和服务端能保证任何时刻最多有一条消息在 传输中(in-flight)(在某条消息被确认前不发送后面的那条消息),那么,不会有QoS等级1的消息会在它的任何后续消息之后收到。例如,订阅者收到的顺序可能是 1,2,3,3,4,而不是 1,2,3,2,3,4。关于如何使用Receive Maximum的详细信息,参考4.9节流控。 4.7 主题名和主题过滤器 Topic Names and Topic Filters 4.7.1 主题通配符 Topic wildcards 主题层级(topic level)分隔符用于将结构化引入主题名。如果存在分隔符,它将主题名分割为多个主题层级 topic level 。 订阅的主题过滤器可以包含特殊的通配符,允许客户端一次订阅多个主题。 主题过滤器中可以使用通配符,但是主题名不能使用通配符 [MQTT-4.7.0-1]。 4.7.1.1 主题层级分隔符 Topic level separator 斜杠(“/” U+002F)用于分割主题的每个层级,为主题名提供一个分层结构。当客户端订阅指定的主题过滤器包含两种通配符时,主题层级分隔符就很有用了。主题层级分隔符可以出现在主题过滤器或主题名字的任何位置。相邻的主题层次分隔符表示一个零长度的主题层级。 4.7.1.2 多层通配符 Multi-level wildcard 数字符号(“#” U+0023)是用于匹配主题中任意层级的通配符。多层通配符表示它的父级和任意数量的子层级。多层通配符必须单独指定,或者跟在主题层级分隔符后面。不管哪种情况,它都必须是主题过滤器的最后一个字符 [MQTT-4.7.1-1]。 非规范评注 例如,如果客户端订阅主题 “sport/tennis/player1/#”,它会收到使用下列主题名发布的消息: “sport/tennis/player1” “sport/tennis/player1/ranking” “sport/tennis/player1/score/wimbledon” 非规范评注 “sport/#”也匹配单独的 “sport” 主题名,因为#包括它的父级。 “#”是有效的,会收到所有的应用消息。 “sport/tennis/#”也是有效的。 “sport/tennis#”是无效的。 “sport/tennis/#/ranking”是无效的。 4.7.1.3 单层通配符 Single-level wildcard 加号(“+” U+002B) 是只能用于单个主题层级匹配的通配符。 在主题过滤器的任意层级都可以使用单层通配符,包括第一个和最后一个层级。在使用它时,它必须占据过滤器的整个层级 [MQTT-4.7.1-2]。可以在主题过滤器中的多个层级中使用它,也可以和多层通配符一起使用。 非规范评注 例如,“sport/tennis/+”匹配“sport/tennis/player1”和“sport/tennis/player2”,但是不匹配“sport/tennis/player1/ranking”。同时,由于单层通配符只能匹配一个层级,“sport/+”不匹配“sport”但是却匹配 “sport/”。 “+” 是有效的。 “+/tennis/#” 是有效的。 “sport+” 是无效的。 “sport/+/player1” 也是有效的。 “/finance” 匹配 “+/+” 和 “/+” ,但是不匹配 “+”。 4.7.2 以\$开头的主题 Topics beginning with \$ 服务端不能将$字符开头的主题名匹配通配符(#或+)开头的主题过滤器 [MQTT-4.7.2-1]。服务端应该阻止客户端使用这种主题名与其它客户端交换消息。服务端实现可以将$开头的主题名用作其他目的。 非规范评注 $SYS/被广泛用作包含服务器特定信息或控制接口的主题的前缀。 应用不能使用$字符开头的主题。 非规范评注 订阅“#”的客户端不会收到任何发布到以“$”开头主题的消息。 订阅“+/monitor/Clients”的客户端不会收到任何发布到“$SYS/monitor/Clients”的消息。 订阅“$SYS/#”的客户端会收到发布到以“$SYS/”开头主题的消息。 订阅“$SYS/monitor/+” 的客户端会收到发布到“$SYS/monitor/Clients”主题的消息。 如果客户端想同时接受以“$SYS/”开头主题的消息和不以$开头主题的消息,它需要同时订阅“#”和“$SYS/#”。 4.7.3 主题语义和用法 Topic semantic and usage 下列规则应用于主题名和主题过滤器: 所有的主题名和主题过滤器必须至少包含一个字符 [MQTT-4.7.3-1]。 主题名和主题过滤器是大小写敏感的。 主题名和主题过滤器可以包含空格字符。 主题名或主题过滤器以前置或后置斜杠“/”区分。 只包含斜杠“/”的主题名或主题过滤器是合法的。 主题名和主题过滤器不能包含空字符(Unicode U+0000) [Unicode] [MQTT-4.7.3-2]。 主题名和主题过滤器是UTF-8编码字符串,它们不能超过65535字节 [MQTT-4.7.3-3]。见1.5.4节。 除了不能超过UTF-8编码字符串的长度限制之外,主题名或主题过滤器的层级数量没有其它限制。 匹配订阅时,服务端不能对主题名或主题过滤器执行任何规范化(normalization)处理,不能修改或替换任何未识别的字符 [MQTT-4.7.3-4]。主题过滤器中的每个非通配符层级需要逐字符匹配主题名中对应的层级才算匹配成功。 非规范评注 使用UTF-8编码规则意味着,主题过滤器和主题名的比较可以通过比较编码后的UTF-8字节或解码后的Unicode字符。 非规范评注 “ACCOUNTS”和“Accounts”是不同的主题名。 “Accounts payable”是合法的主题名 “/finance”和“finance”是不同的。 如果订阅的主题过滤器与消息的主题名匹配,应用消息会被发送给每一个匹配的客户端订阅。主题资源可以是管理员在服务端预先定义好的,也可以是服务端收到第一个订阅或使用那个主题名的应用消息时动态添加的。服务端也可以使用一个安全组件有选择地授权客户端使用某个主题资源。 4.8 订阅 Subscriptions MQTT提供两种订阅方式,共享和非共享。 非规范评注 在早期的MQTT版本中,所有的订阅都是非共享的。 4.8.1 非共享订阅 Non-shared Subscriptions 非共享订阅只与创建它的会话相关联。每个订阅(Subscription)包含一个指示用于在此会话上分发消息的主题过滤器和订阅选项。服务端负责收集与过滤器相匹配的消息,并在此会话的连接上发送这些消息。 一个会话不能有多个包含相同主题过滤器的非共享订阅,因此主题过滤器可以用作标识此会话的订阅的关键词。 如果有多个客户端,每个客户端都拥有对某个相同主题的非共享订阅,则每个客户端都将获得在该主题上发布的应用消息的副本。这意味着非共享订阅不能被用于多个消费客户端的应用消息负载均衡,因为在这种情况下,每条消息都将被传递给每一个订阅的客户端。 4.8.2 共享订阅 Shared Subscriptions 共享订阅可以与多个订阅会话相关联。与非共享订阅一样,它包含一个主题过滤器和订阅选项。但是,与此主题过滤器相匹配的发布消息仅被发布到其中一个订阅会话。共享订阅在多个消费客户端并行共享处理发布消息时是很有用的。 使用特殊样式的主题过滤器来表示共享订阅。过滤器格式如下: $share/{ShareName}/{filter} $share是字符串字面量,用来把主题过滤器标记为共享订阅主题过滤器。 {ShareName}是字符串,不包含“/”,“+”或“#”。 {filter}该字符串的剩余部分与非共享订阅中的主题过滤器具有相同的语法和语义。参考4.7节。 共享订阅主题过滤器必须以$share/开始,且必须包含至少一个字符长度的共享名(ShareName) [MQTT-4.8.2-1]。共享名不能包含字符“/”,“+”或“#”,但必须跟在“/”字符后面。此“/”字符后面必须跟随一个主题过滤器 [MQTT-4.8.2-2],如4.7节所述。 非规范评注 共享订阅在MQTT服务端的范围内定义,而不是在会话中定义。共享订阅的主题过滤器包含共享名,因此服务端可以有多个包含相同{过滤器}组件的共享订阅。通常,应用程序使用共享名表示共享同一个订阅的一组订阅会话。 示例: 共享订阅“$share/consumer1/sport/tennis/+”和“$share/consumer2/sport/tennis/+”是不同的共享订阅,因此可以被关联到不同的会话组。它们都与非共享订阅主题“sport/tennis/+”相匹配。如果一条消息被发布到匹配主题“sport/tennis/+”,则消息的副本仅发送给所有订阅“$share/consumer1/sport/tennis/+”的会话中的一个会话,也仅发送给所有订阅“$share/consumer2/sport/tennis/+”的会话中的一个会话。更多的副本将发送给所有对“sport/tennis/+”进行非共享订阅的客户端。 共享订阅“$share/consumer1//finance”匹配非共享订阅主题“/finance”。注意,“$share/consumer1//finance”和“$share/consumer1/sport/tennis/+”是不同的共享订阅,尽管它们有相同的共享名。它们可能在某种程度上是相关的,但拥有相同的共享名并不意味着它们之间有某种关系。 通过SUBSCRIBE请求中的共享订阅主题过滤器创建共享订阅。只有一个会话订阅了某个共享订阅时,共享订阅行为如同非共享订阅,除了: 匹配发布消息时,不考虑"$share"和{ShareName}部分。 第一次订阅时,保留消息不发送给此会话。其他匹配的发布消息将发送给此会话。 一旦某个共享订阅存在,其他会话就有可能订阅了相同的共享订阅主题过滤器。新的会话作为额外的订阅者关联到此共享订阅。保留消息不发送给此新的订阅者。后续每条与此共享订阅相匹配的应用消息被发送到该共享订阅关联的其中一个会话。 会话可以通过发送包含某共享订阅主题过滤器的UNSUBSCRIBE报文来显式的将其从共享订阅中分离。会话终止时,也将从共享订阅中分离。 共享订阅持续到至少有一个与其相关的会话(即,会话已经对此共享订阅主题过滤器发布了成功的SUBSCRIBE请求,且尚未完成相应的UNSUBSCRIBE)。当初始创建此共享订阅的会话取消订阅时,除非没有其他的相关会话,否则共享订阅仍然存在。共享订阅在没有被任何会话订阅时结束,且任何相关的未分发的消息都被删除。 共享订阅注释 如果有不止一个会话订阅了某个共享订阅,服务端在消息的基础上自由的选择使用哪个会话,以及使用什么标准来进行该选择。 允许不同的订阅客户端在其SUBSCRIBE报文中请求不同的QoS等级。服务端决定授予每个客户端的最大QoS等级,并且允许向不同的订阅者授予不同的最大QoS等级。向客户端发送应用消息时,服务端必须考虑授予客户端的QoS等级 [MQTT-4.8.2-3],与向订阅者发送消息相同。 如果服务端正在向其选中的订阅客户端发送QoS等级2的消息,并且在分发完成之前网络中断,服务端必须在客户端重新连接时完成向该客户端的消息分发 [MQTT-4.8.2-4],如4.3.3节 所述。如果客户端的会话在客户端重连之前终止,服务端不能把此消息发送给其他订阅的客户端 [MQTT-4.8.2-5]。 如果服务端正在向其选中的订阅客户端发送QoS等级1的消息,并且服务端在收到此客户端的确认报文之前网络中断,服务端可以等客户端重新连接之后将消息重传给客户端。如果客户端的会话在客户端重连之前终止,服务端应该把此应用消息发送给与此共享订阅相关的另一个客户端。服务端可以在第一个客户端断开连接时就尝试将消息发送给另一个客户端。 如果客户端对来自服务端的PUBLISH报文使用包含原因码大于等于0x80的PUBACK或PUBREC报文进行响应,服务端必须丢弃应用消息而不尝试将其发送给任何其他订阅者 [MQTT-4.8.2-6]。 允许客户端向已订阅的共享订阅第二次发送SUBSCRIBE请求。比如,它可以通过这样改变其订阅请求的QoS等级,或者因为它不确定以前的连接关闭之前订阅是否已完成。这不会增加共享订阅关联的会话个数,因此会话将在其第一次发送UNSUBSCRIBE之后脱离此共享订阅。 每个共享订阅都是独立于其他共享订阅的。有可能两个共享订阅包含了重叠的过滤器。在这种情况下,与两个共享订阅都相匹配的消息都将被它们单独处理。如果某个客户端既有共享订阅也有非共享订阅,且某个消息与它们都相匹配,客户端将由于存在非共享订阅而接收此消息的副本,此消息的第二个副本将分发给此共享订阅的某个订阅者,因此可能导致两份副本都被发送给此客户端。 4.9 流控 Flow Control 客户端和服务端使用接收最大值来控制接收未被确认的PUBLISH报文数量,如3.1.2.11.4节和3.2.2.3.2节所述。接收最大值创建了一个发送配额,用于限制可以在没收到PUBACK(QoS等级1)或PUBCOMP(QoS等级2)的情况下发送的QoS等级大于0的PUBLISH报文数量。PUBACK和PUBCOMP按照下述方式补充配额。 客户端或服务端必须将其初始发送配额设置为不超过接收最大值的非0值 [MQTT-4.9.0-1]。 每当客户端或服务端发送了一个QoS等级大于0的PUBLISH报文,它就会减少发送配额。如果发送配额减为0,客户端或服务端不能再发送任何QoS等级大于0的PUBLISH报文 [MQTT-4.9.0-2]。它可以继续发送QoS为0的PUBLISH报文,也可以选择暂停发送这些报文。即使配额为0,客户端和服务端也必须继续处理和响应其他MQTT控制报文 [MQTT-4.9.0-3]。 发送配额增加1: 每当收到一个PUBACK报文或PUBCOMP报文,不管PUBACK或PUBCOMP报文是否包含错误码。 每次收到一个包含返回码大于等于0x80的PUBREC报文。 如果发送配额已到达初始发送配额,则不继续增加。在初始发送配额之上尝试增加配额可能是由建立新的网络连接后重新发送PUBREL数据包引起的。 关于客户端和服务端在超出最大接收值的允许的情况下发送PUBLISH报文的描述,参考3.3.4节。 发送配额和接收最大值的保留不跨越网络连接,每次建立新的网络连接时按照上面的描述进行初始化。它们不是会话状态的一部分。 4.10 请求/响应 Request / Response 有些应用程序或标准可能希望通过MQTT协议运行请求/响应交互。此版本MQTT协议包含三个可用于此目的的属性: 响应主题,在3.3.2.3.5节中描述 对比数据,在3.3.2.3.6节中描述 请求响应信息,在3.1.2.11.7节中描述 响应信息,在3.2.2.3.14节中描述 以下非规范部分描述了如何使用这些属性。 客户端通过发布一个包含响应主题的应用消息来发送请求消息,如3.3.2.3.5节所述。请求消息可以包含对比数据属性,如3.3.2.3.6节所述。 4.10.1 基本请求响应(非规范) Basic Request Response (non-normative) 请求/响应交互过程如下: MQTT客户端(请求方)向主题发布请求消息。请求消息是具有响应主题的应用消息。 另一个MQTT客户端(响应方)订阅了与请求消息发布时使用的主题名相匹配的主题过滤器。结果,它收到请求消息。可能有多个响应方订阅了此主题名,也可能没有响应方。 响应方根据请求消息采取适当的操作,然后往请求消息中携带的响应主题属性中的主题名发布响应消息。 典型用法,请求放订阅了响应主题,从而接收到响应信息。但是,其他某些客户端可能会订阅响应主题,因此它们也将接收和处理响应消息。与请求消息一样,可能有多个客户端订阅了响应消息的发送主题,也可能没有。 如果请求消息包含对比数据属性,则响应方将此属性拷贝到响应消息中,由响应消息的接收端用来将响应消息与原始请求相关联。响应消息不包含响应主题属性。 MQTT服务端转发请求消息中的响应主题和对比数据属性,和响应消息中的对比数据属性。服务端像处理其他应用程序消息一样处理请求消息和响应消息。 请求放通常在发布请求消息之前订阅响应主题。如果响应消息发送时没有任何订阅者订阅了响应主题,则响应消息将不会传递给任何客户端。 请求消息和响应消息可以具有任何QoS等级,并且响应方可以使用具有非0会话过期间隔的会话。通常使用QoS等级0发送请求消息,并且只有在应答者正连接时才发送请求消息。但这不是必须的。 响应者可以使用共享订阅来允许响应客户端池。注意,使用共享订阅时,不保证消息在客户端之间的分发顺序。 请求方有责任确保它具有发布消息到请求消息的主题、并订阅响应主题属性中主题名的必要权限。响应方有责任确保它具有订阅请求主题和发布到响应主题的权限。虽然主题授权不属于本规范,但建议服务端实施此类授权。 4.10.2 确定响应主题值(非规范) Determining a Response Topic value (non-normative) 请求方可以通过包括本地配置在内的任何方式来确定作为他们的响应主题的主题名。为避免不同请求方之间的冲突,由请求方客户端使用的响应主题最好对于该客户端是唯一的。由于请求方和响应方通常都需要对这些主题进行授权,因此使用随机主题名称将会对授权造成挑战。 为了解决此问题,本规范在CONNACK报文中定义了一个名为响应信息的属性。服务端可以使用此属性指导客户端如何选择使用的响应主题。此机制对于服务端和客户端都是可选的。连接时,客户端通过设置CONNECT报文中的请求响应信息属性来请求服务端发送响应信息。这会导致服务端在CONNACK报文中插入响应信息属性(UTF-8编码的字符串)。 本规范不定义响应信息的内容,但它可以被用来传递主题树的全局唯一部分,该部分至少在其会话的整个生命周期内保留给该客户端。使用这种机制,可以在服务端而不是每个客户端中完成该属性的配置。 有关响应信息的定义,参考3.1.2.11.7节。 4.11 服务端重定向 Server redirection 服务端可以通过发送包含原因码为0x9C((临时)使用其他服务端)或0x9D(服务端已(永久)移动)的CONNACK或DISCONNECT报文请求客户端使用另一台服务端,如4.13节 所述。服务端发送这些原因码时可以包含一个服务端参考属性,用以说明客户端应该使用的服务端位置。 原因码0x9C ((临时)使用其他服务端) 指定客户端应该临时切换到另一台服务端。另一台服务端可能是客户端已知的,也可能是由服务端参考所指定的。 原因码0x9D (服务端已(永久)移动)指定客户端应该永久切换到另一台服务端。另一台服务端可能是客户端已知的,也可能是由服务端参考所指定的。 服务端参考是一个UTF-8编码字符串,其值是一个由空格分隔开的参考列表。本规范不指定服务端参考的格式。 非规范评注 推荐每个参考包含名称及可选的端口号。如果名称包含冒号,则名称字符串可以由方括号括起来(“[“和“]”)。由方括号括起来的名称不能包含右方括号(“]”)字符,用于表示使用冒号分隔符的IPv6地址。这是一个简化版的URI授权,如[RFC3986]所述。 非规范评注 服务端参考中的名字通常代表主机名、DNS名[RFC1035]、SRV名RFC2782或IP地址。跟随冒号分隔符的通常是十进制端口号。如果端口信息来自于DNS(比如包含SRV)或者使用默认端口,则主机名后无需跟随端口号。 非规范评注 如果给出了多个服务端参考,则期望客户端选择其中一个。 非规范评注 服务端参考示例如下:myserver.xyz.orgmyserver.xyz.org:888310.10.151.22:8883 [fe80::9610:3eff:fe1c]:1883 允许服务端不发送服务端参考,允许客户端忽略服务端参考。此特性可用于负载均衡、服务端重定位和服务端预置服务端。 4.12 增强认证 Enhanced authentication MQTT CONNECT报文使用用户名和密码字段支持基本的网络连接认证。这些字段虽然称为简单密码认证,但可以被用来承载其他形式的认证,例如把密码作为令牌(Token)传递。 增强认证包含质询/响应风格的认证,从而扩展了基本认证。它可能涉及在CONNECT报文之后、CONNACK报文之前的客户端和服务端之间AUTH报文交换。 服务端通过在CONNECT报文中添加认证方法字段来启动增强认证。此字段指定使用的认证方法。如果服务端不支持客户端提供的认证方法,它可以发送一个包含原因码0x8C(无效的认证方法)或0x87(未授权)的CONNACK报文,如4.13节所述,并且必须关闭网络连接 [MQTT-4.12.0-1]。 认证方法是客户端和服务端关于认证数据中的数据和CONNECT报文中其他字段的含义,以及客户端和服务端完成认证需要交换和处理的协议。 非规范评注 认证方法通常为SASL(Simple Authentication and Security Layer)机制,使用一个注册过的名称便于信息交换。然而,认证方法不限于使用已注册的SASL机制。 如果客户端选择的认证方法指定客户端先发送数据,客户端应该在CONNECT报文中包含认证数据属性。此属性可被用来提供认证方法指定的数据,认证数据的内容由认证方法定义。 如果服务端需要额外的信息来完成认证,它可以向客户端发送AUTH报文,此报文必须包含原因码0x18(继续认证) [MQTT-4.12.0-2]。如果认证方法需要服务端向客户端发送认证相关的数据,这些数据在认证数据(Authentication Data)中发送。 客户端通过发送另一个AUTH报文响应来自服务端的AUTH报文,此报文必须包含原因码0x18(继续认证) [MQTT-4.12.0-3]。如果认证方法要求客户端向服务端发送认证相关的数据,这些数据在认证数据(Authentication Data)中发送。 客户端和服务端按需交换AUTH报文,直到服务端通过发送包含原因码为0的CONNACK报文接受认证为止。如果接受认证需要向客户端发送数据,这些数据在认证数据中发送。 客户端可以在处理过程中随时关闭连接。它可以在关闭之前发送DISCONNECT报文。服务端可以在处理过程中随时拒绝认证。它可以发送包含原因码大于等于0x80的CONNACK报文 ,如4.13节所述,并且必须关闭网络连接 [MQTT-4.12.0-4]。 如果初始CONNECT报文包含认证方法属性,则所有的AUTH报文和成功的CONNACK报文必须包含与CONNECT报文中相同的认证方法属性。 [MQTT-4.12.0-5]。 增强认证的实现对于客户端和服务端来说都是可选的。如果客户端在CONNECT报文中没有包含认证方法,则服务端不能发送AUTH报文,且不能在CONNACK报文中发送认证方法 [MQTT-4.12.0-6]。如果客户端在CONNECT报文中没有包含认证方法,则客户端不能向服务端发送AUTH报文 [MQTT-4.12.0-7]。 如果客户端在CONNECT报文中没有包含认证方法,服务端应该使用CONNECT报文中的信息、TLS会话和网络连接进行认证。 SCRAM认证非规范示例 客户端到服务端:CONNECT认证方法="SCRAM-SHA-1",认证数据=client-first-data 服务端到客户端:AUTH原因码=0x18,认证方法="SCRAM-SHA-1",认证数据=server-first-data 客户端到服务端:AUTH原因码=0x18,认证方法="SCRAM-SHA-1",认证数据=client-final-data 服务端到客户端:CONNACK原因码=0,认证方法="SCRAM-SHA-1",认证数据=server-final-data Kerberos认证非规范示例 客户端到服务端:CONNECT认证方法="GS2-KRB5" 服务端到客户端:AUTH原因码=0x18,认证方法="GS2-KRB5" 客户端到服务端:AUTH原因码=0x18,认证方法="GS2-KRB5",认证数据=initial context token 服务端到客户端:AUTH原因码=0x18,认证方法="GS2-KRB5",认证数据=reply context token 客户端到服务端:AUTH原因码=0x18,认证方法="GS2-KRB5" 服务端到客户端:CONNACK原因码=0,认证方法="GS2-KRB5",认证数据=outcome of authentication 4.12.1 重新认证 Re-authentication 如果客户端在CONNECT报文中提供了认证方法,它可以在收到CONNACK报文之后的任何时间通过发送包含原因码0x19(重新认证)的AUTH报文发起重新认证。客户端必须将认证方法设置为与最初验证网络连接时的认证方法一致 [MQTT-4.12.1-1]。如果认证方法需要客户端先发送数据,则此AUTH报文包含第一片认证数据。 服务端通过向客户端发送AUTH报文来响应此重新认证请求,包含原因码为0x00(成功)的AUTH报文指示重新认证完成,包含原因码为0x18(继续认证)的AUTH报文指示需要更多的认证数据。客户端可以通过发送包含原因码0x18(继续认证)的AUTH报文来响应附加的认证数据。此流程与原始身份验证一样,直到重新认证完成或重新认证失败。 如果重新认证失败,客户端或服务端应该发送包含适当原因码的DISCONNECT报文,如4.13节所述。并且必须关闭网络连接 [MQTT-4.12.1-2]。 在重新认证的过程中,客户端和服务端的其他报文流可以继续使用之前的认证。 非规范评注 服务端可以通过拒绝重新认证来限制客户端在重新认证中尝试的更改范围。例如,如果服务端不允许更改用户名,它可以使任何尝试更改用户名的重新认证都失败。 4.13 错误处理 Handling errors 4.13.1 无效报文和协议错误 Malformed Packet and Protocol Errors 无效报文(Malformed Packet)和协议错误(Protocol Error)的定义见1.2节术语。这些错误案例的部分术语贯穿本规范。客户端或服务端对其收到的MQTT控制报文的检查严格程度依赖: 客户端或服务端实现的大小。 实现支持的性能。 接收端对发送端发送的MQTT控制报文的信任程度。 接收端对用于分发MQTT控制报文的网络的信任程度。 继续处理错误报文的的后果。 如果发送端遵守此规范,它将不会发送无效报文或导致协议错误。然而,如果客户端在收到CONNACK报文之前发送MQTT控制报文,它可能会因为错误的估计了服务端的性能而导致协议错误。参考3.1.4节CONNECT 行为。 无效报文和协议错误使用的原因码包括: 0x81 无效报文 0x82 协议错误 0x93 超过接收最大值 0x95 报文过大 0x9A 不支持保留 0x9B 不支持的QoS等级 0x9E 不支持共享订阅 0xA1 不支持订阅标识符 0xA2 不支持通配符订阅 当客户端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时,它应该关闭网络连接。在AUTH报文出错的情况下它可以在关闭网络连接之前发送包含原因码的DISCONNECT报文。在其他报文出错的情况下它应该在关闭网络连接之前发送包含原因码的DISCONNECT报文。使用原因码0x81(错误报文)或0x82(协议错误),除非包含3.14.2.1断开原因码 中定义的更具体的原因码。 当服务端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时,它必须关闭网络连接 [MQTT-4.13.1-1]。在CONNECT报文出错的情况下它可以在关闭网络连接之前发送包含原因码的CONNACK报文。在其他报文出错的情况下它应该在关闭网络连接之前发送包含原因码的DISCONNECT报文。使用原因码0x81(无效报文)或0x82(协议错误),除非包含3.2.2.2节 - 连接原因码 或3.14.2.1节 – 断开原因码 中定义的更具体的原因码。对其他会话没有影响。 如果服务端或客户端省略了检查MQTT控制报文的某些特性,它可能无法检测到某个错误,因此可能会导致数据被损坏。 4.13.2 其他错误 Other errors 发送端无法预料到无效报文和协议错误以外的错误,因为它可能有某些没有告知发送端的约束。客户端或服务端可能在接收时遇到短暂的错误,比如内存不足,导致无法成功的处理某个MQTT控制报文。 包含原因码大于等于0x80的确认报文PUBACK,PUBREC,PUBREL,PUBCOMP,SUBACK,UNSUBACK表明收到了某个报文标识符的报文出错。这不会影响其他会话或此会话上的其他报文。 CONNACK报文和DISCONNECT报文允许使用大于等于0x80的原因码以指示网络连接将被关闭。如果某个大于等于0x80的原因码被指定,无论是否发送CONNACK报文或DISCONNECT报文,必须关闭网络连接 [MQTT-4.13.2-1]。发送这些原因码不会影响任何其他会话。 如果控制报文包含多个错误,接收端可以按照任意顺序对报文进行验证,并对发现的任何错误采取适当的行为。 项目主页 MQTT v5.0协议草案中文版 第五章 安全(非规范) 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] 5.1 概述 Introduction 强烈建议提供TLS [RFC5246]的服务端实现使用TCP端口8883(IANA服务名:secure-mqtt)。 安全是一个快速变化的领域,所以在设计安全解决方案时总是使用最新的建议。 解决方案需要考虑的风险包括: 设备可能会被盗用 客户端和服务端的静态数据可能是可访问的(可能会被修改) 协议行为可能有副作用(如计时器攻击) 拒绝服务攻击 通信可能会被拦截、修改、重定向或者泄露 虚假MQTT控制报文注入 MQTT方案通常部署在不安全的通信环境中。在这种情况下,协议实现通常需要提供这些机制: 用户和设备身份认证 服务端资源访问授权 MQTT控制报文和内嵌应用数据的完整性校验 MQTT控制报文和内嵌应用数据的隐私控制 作为传输层协议,MQTT仅关注消息传输,提供合适的安全功能是实现者的责任。使用TLS [RFC5246]是比较普遍的选择。 除了技术上的安全问题外,还有地区因素(例如美国欧盟隐私盾框架[USEUPRIVSH]),行业标准(例如第三方支付行业数据安全标准 [PCIDSS]),监管方面的考虑(例如萨斯班-奥克斯利法案[SARBANES])。 5.2 MQTT解决方案:安全和认证 MQTT solutions: security and certification 协议实现可能需要提供符合特定行业安全标准,如NIST网络安全框架 [NISTCSF],第三方支付行业数据安全标准 [PCIDSS],美国联邦信息处理标准 [FIPS1402] 和NSA加密组合B [NSAB]。 在MQTT的补充出版物(MQTT and the NIST Framework for Improving Critical Infrastructure Cybersecurity [MQTTNIST])中可以找到在NIST网络安全框架 [NISTCSF] 中使用MQTT的指导。使用行业证明、独立审计和认证技术有助于满足合规要求。 5.3 轻量级的加密与受限设备 Lightweight crytography and constrained devices 广泛采用的加密算法是高级加密标准 [AES]。对AES提供了硬件支持的处理器有很多,但通常不包含嵌入式处理器。加密算法ChaCha20 [CHACHA20] 软件加解密速度快很多,但不像AES那样广泛可用。 推荐使用为资源受限的低端设备特别优化过的轻量级加密国际标准ISO 29192 [ISO29192]。 5.4 实现注意事项 Implementation notes 实现或使用MQTT时需要考虑许多安全问题。以下章节不应被视为核对清单。 协议实现时可以实现下面的一部分或全部: 5.4.1 客户端身份验证 Authentication of Clients by the Server CONNECT报文包含用户名和密码字段。实现可以决定如何使用这些字段的内容。实现者可以提供自己的身份验证机制,或者使用外部的认证系统如LDAP [RFC4511] 或Auth [RFC6749],还可以利用操作系统的认证机制。 MQTT v5.0提供了一种增强认证机制,如4.12节所述。使用此机制需要客户端和服务端双方的支持。 实现可以明文传递认证数据,混淆数据元素,或者不要求任何认证数据,但应该意识到这会增加中间人攻击和重放攻击的风险。5.4.5节介绍了确保数据私密的方法。 在客户端和服务端之间使用虚拟专用网(VPN)可以确保数据只被授权的客户端收到。 使用TLS [RFC5246]时,服务端可以使用客户端发送的TLS证书验证客户端的身份。 实现可以允许客户端通过应用消息给服务端发送用于身份验证的凭证。 5.4.2 客户端授权 Authorization of Clients by the Server 如果客户端已经成功通过身份认证,服务端实现需要在接受连接之前执行授权检查。 授权可以基于客户端提供的信息如用户名,客户端主机名/IP地址,或认证机制的结果。 具体来说,实现应该检查客户端是否被授权使用此客户标识符,因为客户标识符提供了对MQTT会话状态的访问(如4.1节所述)。此授权检查是为了防止某个客户端偶然或恶意的使用了已被其他客户端所使用的客户标识符。 实现应该提供发生在CONNECT之后的访问控制以限制客户端发布消息到特定主体或使用特定主体过滤器进行订阅的能力。实现需要考虑对具有广泛作用域的主题过滤器的访问限制,如"#"主题过滤器。 5.4.3 服务端身份验证 Authentication of the Server by the Client MQTT协议不是双向信任的。基本认证没有提供客户端验证服务端身份的机制。某些形式的扩展认证允许双向认证。 但是使用TLS [RFC5246]时,客户端可以使用服务端发送的TLS证书验证服务端的身份。从单IP多域名提供MQTT服务的实现应该考虑 [RFC6066]第3节定义的TLS的SNI扩展。SNI允许客户端告诉服务端它要连接的服务端主机名。 实现可以允许服务端通过应用消息给客户端发送凭证用于身份验证。MQTT v5.0提供了一种增强的认证机制,如4.12节所述,它可以被客户端用于验证服务端。使用此机制需要客户端和服务端双方的支持。 在客户端和服务端之间使用虚拟专用网(VPN)可以确保客户端正连接的是预期的服务端。 5.4.4 应用消息和MQTT控制报文的完整性 Integrity of Application Messages and MQTT Control Packets 应用可以在应用消息中单独包含哈希值。这样做可以为PUBLISH报文的网络传输和静态数据提供内容的完整性检查。 TLS [RFC5246]提供了对网络传输的数据做完整性校验的哈希算法。 在客户端和服务端之间使用虚拟专用网(VPN)连接可以在VPN覆盖的网络段提供数据完整性检查。 5.4.5 应用消息和MQTT控制报文的保密性 Privacy of Application Messages and Control Packets TLS [RFC5246]可以对网络传输的数据加密。如果有效的 TLS 密码组合包含的加密算法为 NULL,那么它不会加密数据。要确保客户端和服务端的保密,应避免使用这些密码组合。 应用可以单独加密应用消息的内容。这可以提供应用消息传输途中和静态数据的私密性。但不能给应用消息的其它属性如主题名加密。 客户端和服务端实现可以加密存储静态数据,例如可以将应用消息作为会话的一部分存储。 在客户端和服务端之间使用虚拟专用网(VPN)连接可以在VPN覆盖的网络段保证数据的私密性。 .5.4.6 消息传输的不可否认性 Non-repudiation of message transmission 应用设计者可能需要考虑适当的策略,以实现端到端的不可否认性(non-repudiation)。 5.4.7 检测客户端和服务端的盗用 Detecting compromise of Clients and Servers 使用TLS [RFC5246]的客户端和服务端实现应该能够确保,初始化TLS连接时提供的 SSL 证书是与主机名(客户端要连接的或服务端将被连接的)关联的。 使用TLS [RFC5246]的客户端和服务端实现,可以选择提供检查证书吊销列表(CRLs [RFC5280])和在线整数状态协议(OSCP)[RFC6960]的功能,拒绝使用被吊销的整数。 物理部署可以将防篡改硬件与应用消息的特殊数据传输结合。例如,一个仪表可能会内置一个GPS以确保没有在未授权的地区使用。IEEE安全设备认证[IEEE8021AR]就是用于实现这个机制的一个标准,它使用加密绑定标识符验证设备身份。 5.4.8 检测异常行为 Detecting abnormal behaviors 服务端实现可以监视客户端的行为,检测潜在的安全风险。例如: 重复的连接请求 重复的身份验证请求 连接的异常终止 主题扫描(请求发送或订阅大量主题) 发送无法送达的消息(没有订阅者的主题) 客户端连接但是不发送数据 发现违反安全规则的行为,服务端实现可以断开客户端连接。 服务端实现检测不受欢迎的行为,可以基于IP地址或客户端标识符实现一个动态黑名单列表。 服务部署可以使用网络层次控制(如果可用)实现基于IP地址或其它信息的速率限制或黑名单。 5.4.9 其它的安全注意事项 Other security considerations 如果客户端或服务端的SSL证书丢失,或者我们考虑证书被盗用或者被吊销(利用 CRLs [RFC5280]和OSCP [RFC6960]的情况。 客户端或服务端验证凭证时,如果发现用户名和密码丢失或被盗用,应该吊销或者重新发放。 在使用长连接时: 客户端和服务端使用TLS [RFC5246]时应该允许重新协商会话以确认新的加密参数(替换会话密钥,更换密码组合,更换认证凭证)。 服务端可以关闭客户端的网络连接,并要求他们使用新的凭证重新验证身份。 服务端可以要求客户端使用4.12.1节 中描述的机制周期性的进行重新认证。 资源受限设备或使用受限网络的客户端可以使用TLS RFC5246会话恢复,以降低TLS RFC5246会话重连的成本。 连接到服务端的客户端与其它连接到服务端的客户端之间有一个信任传递关系,它们都有权在同一个主题上发布消息。 5.4.10 使用SOCKS代理 Use of SOCKS 客户端实现应该意识到某些环境要求使用SOCKSv5 [RFC1928]代理创建出站的网络连接。某些MQTT实现可以利用安全隧道(如SSH)通过SOCKS代理。一个实现决定支持SOCKS时,它们应该同时支持匿名的和用户名密码验证的SOCKS代理。对于后一种情况,实现应该意识到SOCKS可能使用明文认证,因此应该避免使用相同的凭证连接 MQTT 服务器。 5.4.11 安全配置文件 Security profiles 实现者和方案设计者可能希望将安全当作配置文件集合应用到MQTT协议中。下面描述的是一个分层的安全等级结构。 5.4.11.1 开放通信配置 Clear communication profile 使用开放通信配置时,MQTT协议运行在一个没有内置额外安全通信机制的开放网络上。 5.4.11.2 安全网络通信配置 Secured network communication profile 使用安全网络通信配置时,MQTT协议运行在有安全控制的物理或虚拟网络上,如VPN或物理安全网络。 5.4.11.3 安全传输配置 Secured transport profile 使用安全传输配置时,MQTT协议运行在使用TLS [RFC5246] 的物理或虚拟网络上,它提供了身份认证,完整性和保密性。 使用内置的用户名和密码字段,TLS [RFC5246] 客户端身份认证可被用于(或者代替)MQTT客户端认证。 5.4.11.4 工业标准的安全配置 Industry specific security profiles 可以预料的是,MQTT协议被设计为支持很多工业标准的应用配置,每一种定义一个威胁模型和用于定位威胁的特殊安全机制。特殊的安全机制推荐从下面的方案中选择: [NISTCSF] NIST网络安全框架[NIST7628] NISTIR 7628智能电网网络安全指南[FIPS1402] (FIPS PUB 140-2) 加密模块的安全要求[PCIDSS] PCI-DSS第三方支付行业数据安全标准[NSAB] NSA加密组合B 项目主页 MQTT v5.0协议草案中文版 第六章 使用WebSocket作为网络层 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] 如果MQTT在WebSocket [RFC6455] 连接上传输,必须满足下面的条件: MQTT控制报文必须使用WebSocket二进制数据帧发送。如果收到任何其它类型的数据帧,接收者必须关闭网络连接 [MQTT-6.0.0-1]。 单个WebSocket数据帧可以包含多个或者部分MQTT报文。接收者不能假设MQTT控制报文按WebSocket帧边界对齐 [MQTT-6.0.0-2]。 客户端必须将字符串"mqtt"包含在它提供的WebSocket子协议列表里 [MQTT-6.0.0-3]。 服务端选择和返回的WebSocket子协议名必须是 mqtt [MQTT-6.0.0-4]。 用于连接客户端和服务器的WebSocket URI对MQTT协议没有任何影响。 6.1 IANA注意事项 IANA Considerations 本规范请求IANA在WebSocket子协议名条目下注册WebSocket MQTT子协议,使用下列数据: 图例 6-1 - IANA WebSocket标识符 IANA WebSocket Identifier 子协议标识符mqtt子协议通用名mqtt子协议定义http://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html 项目主页 MQTT v5.0协议草案中文版 第七章 一致性 Conformance 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] MQTT规范定义了MQTT客户端实现和MQTT服务端实现的一致性要求。MQTT实现可以同时作为MQTT客户端和MQTT服务端。 7.1 一致性条款 Conformance clauses 7.1.1 MQTT服务端一致性条款 MQTT Server conformance clause 服务端的定义,参考术语章节的[服务端(Server)]部分。 MQTT服务端只有满足下面所有的要求才算是符合本规范: 服务端发送的所有MQTT控制报文的格式符合[第二章]和[第三章]描述的格式。 遵守4.7节描述的主题匹配规则和4.8节匹配的订阅规则。 满足下列章节中所有必须级别的要求,明确仅适用于对客户端的除外: [第一章 – 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第六章 – 使用WebSocket作为网络层] 为了能够与任何其他一致的(MQTT)实现进行互操作,无需使用在规范之外定义的任何扩展。 7.1.2 MQTT客户端一致性条款 MQTT Client conformance clause 客户端的定义,参考术语章节的[客户端(Client)]部分。 MQTT客户端只有满足下面所有的要求才算是符合本规范: 客户端发送端所有MQTT控制报文的格式符合[第二章]和[第三章]描述的格式。 满足下列章节中所有必须级别的要求,明确仅适用于对服务端的除外: [第一章 – 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第六章 – 使用WebSocket作为网络层] 为了能够与任何其他一致的(MQTT)实现进行互操作,无需使用在规范之外定义的任何扩展。 项目主页 MQTT v5.0协议草案中文版 附录B 强制性规范声明(非规范) 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] 此附录是非规范性的,只作为本文档正文中可以找到的大量一致性声明的摘要提供。参考 第七章 一致性要求限制列表。 规范声明序号规范声明[MQTT-1.5.4-1]UTF-8编码字符串中的数据必须是按照 [Unicode] 规范定义的,在RFC 3629 [RFC3629] 中重申的有效的UTF-8格式。特别需要指出的是,这些数据不能包含字符码在U+D800和U+DFFF之间的数据。[MQTT-1.5.4-2]UTF-8编码的字符串不能包含空字符U+0000。[MQTT-1.5.4-3]UTF-8编码序列0xEF 0xBB 0xBF总是被解释为U+FEFF ("零宽度非换行空白字符") ,无论它出现在字符串的什么位置,报文接收者都不能跳过或者剥离它。[MQTT-1.5.5-1]编码值必须使用表示该值所需的最少字节数。[MQTT-1.5.7-1]所有的字符串都必须符合UTF-8编码字符串的要求。[MQTT-2.1.3-1]如果标记位被标记为“保留”,则保留它以供将来使用,并且必须设置为所列出的值。[MQTT-2.2.1-2]QoS等级为0的PUBLISH报文不能包含报文标识符。[MQTT-2.2.1-3]客户端每次发送新的SUBSCRIBE,UNSUBSCRIBE或PUBLISH(当QoS等级>0)MQTT控制报文时,它必须为其分配一个当前未被使用的非0报文标识符。[MQTT-2.2.1-4]服务端每次发送新的PUBLISH(当QoS等级>0)MQTT控制报文时,它必须为其分配一个当前未被使用的非0报文标识符。[MQTT-2.2.1-5]PUBACK,PUBREC,PUBREL或PUBCOMP报文必须包含PUBLISH报文中发送的原始报文标识符。[MQTT-2.2.1-6]SUBACK和UNSUBACK报文必须包含相应的SUBSCRIBE和UNSUBSCRIBE报文中使用的报文标识符。[MQTT-2.2.2-1]如果没有属性,属性长度必须为0。[MQTT-3.1.0-1]当协议错误并关闭网络连接时,服务端必须处理客户端发送的第二个CONNECT报文。[MQTT-3.1.2-1]协议名必须是UTF-8字符串"MQTT"。如果服务端不想接受CONNECT,并希望透露它是MQTT服务端,它可以发送一个包含原因码为0x84(不支持的协议版本)的CONNACK报文,然后必须关闭网络连接。[MQTT-3.1.2-2]如果协议版本不为5,且服务端不想接受CONNECT报文,则服务端可以发送一个包含原因码为0x84(不支持的协议版本)的CONNACK报文,然后必须关闭网络连接。[MQTT-3.1.2-3]服务端必须验证CONNECT报文的保留标志位(第0位)是否为 0。[MQTT-3.1.2-4]如果CONNECT报文的新开始标志被设置为1,则客户端和服务端必须丢弃任何已存在的会话并开始一个新的会话。[MQTT-3.1.2-5]如果CONNECT报文的新开始标志被设置为0,并且存在与该客户标识符相关联的会话,服务端必须基于此会话恢复与客户端的通信。[MQTT-3.1.2-6]如果CONNECT报文的新开始标志被设置为0,并且不存在与该客户标识符相关联的会话,则服务端必须创建一个新的会话。[MQTT-3.1.2.7]遗嘱标志被设置为1,表示遗嘱消息必须被存储在服务端并与会话相关联。[MQTT-3.1.2-8]在网络连接被关闭且遗嘱延时间隔已过或会话结束时遗嘱消息必须被发布,除非遗嘱消息被服务端在收到包含原因码为0x00(正常关闭)的DISCONNECT报文后删除或关于此客户标识符的一个新的网络连接在遗嘱消息间隔过期之前被打开。[MQTT-3.1.2-9]如果遗嘱标志被设置为0,连接标志中的遗嘱QoS等级和遗嘱保留字段将会被服务端使用,遗嘱属性、遗嘱主题和遗嘱消息字段必须存在于载荷中。[MQTT-3.1.2-10]一旦遗嘱消息被发布或者服务端收到包含原因码为0x00(正常关闭)的DISCONNECT报文,遗嘱消息必须从服务端的会话中删除。[MQTT-3.1.2-11]如果遗嘱标志设置为0,遗嘱QoS等级必须也设置为0 (0x00)。[MQTT-3.1.2-12]如果遗嘱标志设置为1,遗嘱QoS等级可以被设置为0(0x00),1(0x01)或2(0x02)。[MQTT-3.1.2-13]如果遗嘱标志被设置为0,遗嘱保留标志也必须设置为0。[MQTT-3.1.2-14]如果遗嘱标志被设置为1时,如果遗嘱保留被设置为0,则服务端必须将遗嘱消息当做非保留消息发布。[MQTT-3.1.2-15]如果遗嘱保留被设置为1,则服务端必须将遗嘱消息当做保留消息发布。[MQTT-3.1.2-16]如果用户名标志被设置为0,有效载荷中不能包含用户名字段。[MQTT-3.1.2-17]如果用户名标志被设置为0,有效载荷中必须包含用户名字段。[MQTT-3.1.2-18]如果密码标志被设置为0,有效载荷中不能包含密码字段。[MQTT-3.1.2-19]如果密码标志被设置为1,有效载荷中必须包含密码字段。[MQTT-3.1.2-20]如果保持连接值不为0,且没有任何其它的MQTT控制报文可以发送,客户端必须发送一个PINGREQ 报文。[MQTT-3.1.2-21]如果服务端返回的CONNACK报文中包含服务端保持连接,客户端必须使用此值代替其发送的保持连接。[MQTT-3.1.2-22]如果保持连接的值非零,并且服务端在1.5倍的保持连接时间内没有收到客户端的MQTT控制报文,它必须断开客户端的网络连接,并判定网络连接已断开。[MQTT-3.1.2-23]如果网络连接关闭时会话过期间隔大于0,则客户端与服务端必须存储会话状态。[MQTT-3.1.2-24]服务端不能发送超过最大报文长度的报文给客户端。[MQTT-3.1.2-25]当报文过大而不能发送时,服务端必须丢弃这些报文,然后当做应用消息发送已完成处理。[MQTT-3.1.2-26]服务端在一个PUBLISH报文中发送的主题别名不能超过客户端设置的主题别名最大值。[MQTT-3.1.2-27]如果主题别名最大值没有设置,或者设置为零,则服务端不能向此客户端发送任何主题别名。[MQTT-3.1.2-28]请求响应信息值为0,表示服务端不能返回响应信息。[MQTT-3.1.2-29]如果请求问题信息的值为0,服务端可以选择在CONNACK或DISCONNECT报文中返回原因字符串或用户属性,但不能在除PUBLISH,CONNACK或DISCONNECT之外的报文中发送原因字符串或用户属性。[MQTT-3.1.2-30]如果客户端在CONNECT报文中设置了认证方法,则客户端在收到CONNACK报文之前不能发送除AUTH或DISCONNECT之外的报文。[MQTT-3.1.3-1]CONNECT报文的载荷中包含由可变报头中的标志确定的一个或多个以长度为前缀的字段。这些字段若存在,必须按照客户标识符、遗嘱属性、遗嘱主题、遗嘱载荷、用户名、密码的顺序出现。[MQTT-3.1.3-2]客户端和服务端都必须使用客户标识符识别两者之间的MQTT会话相关的状态。[MQTT-3.1.3-3]客户标识符必须存在,且作为CONNECT报文载荷的第一个字段出现。[MQTT-3.1.3-4]客户标识符必须被编码为UTF-8字符串。[MQTT-3.1.3-5]服务端必须允许1到23个字节长的UTF-8编码的客户标识符,客户标识符只能包含这些字符:"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[MQTT-3.1.3-6]服务端可以允许客户端提供一个零字节的客户标识符,如果这样做了,服务端必须将这看作特殊情况并分配唯一的客户标识符给那个客户端。[MQTT-3.1.3-7]服务端必须假设客户端提供了那个唯一的客户标识符,且必须在CONNACK报文中返回分配的客户标识符。[MQTT-3.1.3-8]如果服务端拒绝了某个客户标识符,它可以发送包含原因码0x85(客户标识符无效)的CONNACK报文作为对客户端的CONNECT报文的回应 ,如4.13节所述。之后必须关闭网络连接。[MQTT-3.1.3-9]如果某个会话在遗嘱延时间隔到期之前创建了新的网络连接,则服务端不能发送遗嘱消息。[MQTT-3.1.3-10]服务端在发布遗嘱消息时必须维护用户属性的顺序。[MQTT-3.1.3-11]遗嘱主题必须为UTF-8编码的字符串。[MQTT-3.1.3-12]如果用户名标志被设置为1,用户名为载荷中下一个字段。用户名必须是UTF-8编码字符串。[MQTT-3.1.4-1]服务端必须按照3.1节的要求验证CONNECT报文,如果报文不符合规范,服务端关闭网络连接。[MQTT-3.1.4-2]服务端可以检查CONNECT报文的内容是不是满足任何进一步的限制,应该执行身份验证和授权检查。如果任何一项检查没通过,服务端必须关闭网络连接。[MQTT-3.1.4-3]如果客户标识符所代表的客户端已经连接到此服务端,那么向原有的客户端发送一个包含原因码为0x8E(会话被接管)的DISCONNECT报文,并且必须关闭原有的网络连接。[MQTT-3.1.4-4]服务端必须对新开始标志进行处理。[MQTT-3.1.4-5]服务端必须使用包含原因码为0x00(成功)的CONNACK报文对客户端的CONNECT报文进行确认。[MQTT-3.1.4-6]如果服务端拒绝了CONNECT报文,它不能处理客户端在CONNECT报文之后发送的任何除AUTH以外的报文。[MQTT-3.2.0-1]服务端在发送任何除AUTH以外的报文之前必须先发送包含原因码为0x00(成功)的CONNACK报文。[MQTT-3.2.0-2]服务端在一次网络连接中不能发送多个CONNACK报文。[MQTT-3.2.2-1]第1个字节是连接确认标志,位7-1是保留位且必须设置为0。[MQTT-3.2.2-2]如果服务端接受一个新开始为1的连接,服务端在CONNACK报文中除了把原因码设置为0x00(成功)之外,还必须把会话存在标志设置为0。[MQTT-3.2.2-3]如果服务端接受一个新开始为0的连接,并且服务端已经保存了此客户标识符的会话状态,服务端在CONNACK报文中必须把会话存在标志设置为1。否则,服务端必须把会话存在标志设置为0。无论如何,服务端在CONNACK报文中必须把原因码设置为0x00(成功)。[MQTT-3.2.2-4]如果客户端没有保存的会话状态,但收到会话存在标志为1,客户端必须关闭网络连接。[MQTT-3.2.2-5]如果客户端保存了会话状态,但收到的会话存在标志为0,客户端若要继续此网络连接,它必须丢弃其保存的会话状态。[MQTT-3.2.2-6]如果服务端发送的CONNACK报文中原因码非0,它必须把会话存在标志设置为0。[MQTT-3.2.2-7]如果服务端发送了一个包含原因码大于等于128的CONNACK报文,它随后必须关闭网络连接。[MQTT-3.2.2-8]服务端发送的CONNACK报文必须设置一种原因码。[MQTT-3.2.2-9]如果服务端不支持Qos为1或2的PUBLISH报文,服务端必须在CONNACK报文中发送最大服务质量以指定其支持的最大QoS值。[MQTT-3.2.2-10]即使不支持QoS为1或2的PUBLISH报文,服务端也必须接受请求QoS为0、1或2的SUBSCRIBE报文。[MQTT-3.2.2-11]如果从服务端接收到了最大QoS等级,则客户端不能发送超过最大QoS等级所指定的QoS等级的PUBLISH报文。[MQTT-3.2.2-12]如果服务端收到包含遗嘱的QoS超过服务端处理能力的CONNECT报文,服务端必须拒绝此连接。服务端应该使用包含原因码为0x9B(不支持的QoS等级)的CONNACK报文进行错误处理,随后必须关闭网络连接。[MQTT-3.2.2-13]如果服务端收到一个包含保留标志位1的遗嘱消息的CONNECT报文且服务端不支持保留消息,服务端必须拒绝此连接请求,且应该发送包含原因码为0x9A(不支持保留)的CONNACK报文,随后必须关闭网络连接。[MQTT-3.2.2-14]从服务端接收到的保留可用标志为0时,客户端不能发送保留标志设置为1的PUBLISH报文。[MQTT-3.2.2-15]客户端不应该发送超过最大报文长度的报文给服务端。[MQTT-3.2.2-16]如果客户端使用长度为0的客户标识符,服务端必须回复包含分配客户标识符的CONNACK报文。分配客户标识符必须是没有被服务端的其他会话所使用的新客户标识符。[MQTT-3.2.2-17]客户端在一个PUBLISH报文中发送的主题别名值不能超过服务端设置的主题别名最大值。[MQTT-3.2.2-18]如果主题别名最大值没有设置,或者设置为0,则客户端不能向此服务端发送任何主题别名。[MQTT-3.2.2-19]如果加上原因字符串之后的CONNACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串。[MQTT-3.2.2-20]如果加上用户属性之后的CONNACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性。[MQTT-3.2.2-21]如果服务端发送了服务端保持连接属性,客户端必须使用此值代替其在CONNECT报文中发送的保持连接时间值。[MQTT-3.2.2-22]如果服务端没有发送服务端保持连接属性,服务端必须使用客户端在CONNECT报文中设置的保持连接时间值。[MQTT-3.3.1-1]客户端或服务端请求重发一个PUBLISH报文时,必须将DUP标志设置为1。[MQTT-3.3.1-2]对于QoS为0的消息,DUP标志必须设置为0。[MQTT-3.3.1-3]发送(出站)的PUBLISH报文与收到(入站)的PUBLISH报文中的DUP标志是独立设置的,它的值必须单独的根据发送(出站)的PUBLISH报文是否是一个重发来确定。[MQTT-3.3.1-4]PUBLISH报文的2个QoS比特位不能同时设置为1。[MQTT-3.3.1-5]如果客户端发给服务端的PUBLISH报文的保留标志被设置为1,服务端必须存储此应用消息,并用其替换此话题下任何已存在的消息。[MQTT-3.3.1-6]如果载荷为空,消息可以正常被服务端所处理,但是此话题下的任何保留消息必须被丢弃,并且此话题未来的订阅者将不会收到保留消息。[MQTT-3.3.1-7]载荷为空的保留消息将不能被存储在服务端。[MQTT-3.3.1-8]如果客户端发给服务端的PUBLISH报文的保留标志位为0,服务器不能把此消息存储为保留消息,也不能丢弃或替换任何已存在的保留消息。[MQTT-3.3.1-9]如果保留消息处理属性被设置为0,服务端必须发送主题与客户端订阅的主题过滤器相匹配的所有保留消息。[MQTT-3.3.1-10]如果保留消息处理属性被设置为1,如果尚不存在匹配的订阅,服务端必须发送主题与客户端订阅的主题过滤器相匹配的所有保留消息。如果已存在相匹配的订阅,服务器不能发送这些保留消息。[MQTT-3.3.1-11]如果保留消息处理属性被设置为2,服务器不能发送这些保留消息。[MQTT-3.3.1-12]如果发布保留订阅选项被设置为0,服务端在转发应用消息时必须将保留标志设置为0,而不管收到的PUBLISH报文中保留标志位如何设置的。[MQTT-3.3.1-13]如果发布保留订阅选项被设置为1,服务端在转发应用消息时必须将保留标志设置为与收到的PUBLISH消息中的保留标志位相同。[MQTT-3.3.2-1]主题名必须是PUBLISH报文可变报头的第一个字段。它必须是UTF-8编码的字符串。[MQTT-3.3.2-2]PUBLISH报文中的主题名不能包含通配符。[MQTT-3.3.2-3]服务端发送给订阅客户端的PUBLISH报文中的主题名必须匹配该订阅的主题过滤器。[MQTT-3.3.2-4]服务端必须把接收到的应用消息中的载荷格式指示原封不动的发给所有的订阅者。[MQTT-3.3.2-5]如果消息过期间隔已过期,服务端还没开始向匹配的订阅者交付该消息,则服务端必须删除该订阅者的消息副本。[MQTT-3.3.2-6]服务端发送给客户端的PUBLISH报文中必须包含消息过期间隔,值为接收时间减去消息在服务端的等待时间。[MQTT-3.3.2-7]接收端不能将任何主题别名映射从一个网络连接转发到另一个网络连接。[MQTT-3.3.2-8]发送端不能发送包含主题别名值为0的PUBLISH报文。[MQTT-3.3.2-9]客户端不能发送主题别名值大于服务端的CONNACK报文中指定的主题别名最大值的PUBLISH报文。[MQTT-3.3.2-10]客户端必须接受所有值大于0且小于等于其发送的CONNECT报文中的主题别名最大值的主题别名。[MQTT-3.3.2-11]服务端不能发送包含主题别名值大于客户端在CONNECT报文中指定的主题别名最大值的PUBLISH报文。[MQTT-3.3.2-12]服务端必须接受所有值大于0且小于等于其发送的CONNACK报文中的主题别名最大值的主题别名。[MQTT-3.3.2-13]响应主题必须是UTF-8编码的字符串。[MQTT-3.3.2-14]响应主题不能包含通配符。[MQTT-3.3.2-15]服务端在收到应用消息时必须将响应主题原封不动的发送给所有的订阅者。[MQTT-3.3.2-16]服务端在收到应用消息时必须原封不动的把对比数据发送给所有的订阅者。[MQTT-3.3.2-17]服务端在转发应用消息到客户端时必须原封不动的把所有的用户属性放在PUBLISH报文中。[MQTT-3.3.2-18]服务端在转发应用消息时必须保持所有用户属性的先后顺序。[MQTT-3.3.2-19]内容类型必须是UTF-8编码的字符串。[MQTT-3.3.2-20]服务端必须把收到的应用消息中的内容类型原封不动的发送给所有的订阅者。[MQTT-3.3.4-1]PUBLISH报文的接收端必须按照PUBLISH报文中的QoS等级发送响应报文。[MQTT-3.3.4-2]这种情况下,服务端必须按照所有匹配的订阅中最大的QoS等级把消息发送给客户端。[MQTT-3.3.4-3]如果客户端在这些重叠的订阅中指定了订阅标识符,服务端在发布这些订阅相匹配的消息时必须包含这些订阅标识符。[MQTT-3.3.4-4]如果服务端对这些重叠的订阅只发送一条相匹配的消息,服务端必须在PUBLISH报文中包含所有的相匹配的订阅标识符(如果存在),但没有顺序要求。[MQTT-3.3.4-5]如果服务端对这些重叠的订阅必须分别发送相匹配的消息,则每个PUBLISH报文中包含与订阅相匹配的订阅标识符(如果存在)。[MQTT-3.3.4-6]从客户端发送给服务端的PUBLISH报文不能包含订阅标识符。[MQTT-3.3.4-7]客户端在收到服务端的PUBACK,PUBCOMP或包含原因码大于等于128的PUBREC报文之前,不能发送数量超过服务端的接收最大值的QoS为1和2的PUBLISH报文。[MQTT-3.3.4-8]客户端不能延迟发送任何报文,除了PUBLISH报文--如果已发送且没有收到确认的PUBLISH报文数量已达到服务端的接收最大值。[MQTT-3.3.4-9]服务端在接收到客户端的PUBACK,PUBCOMP或包含原因码大于等于128的PUBREC报文之前,不能发送数量超过客户端的接收最大值的QoS为1和2的PUBLISH报文。[MQTT-3.3.4-10]服务端不能延迟发送任何报文,除了PUBLISH报文--如果已发送且没有收到确认的PUBLISH报文数量已到达客户端的接收最大值。[MQTT-3.4.2-1]服务端或客户端发送PUBACK报文时必须设置其中一种PUBACK原因码。[MQTT-3.4.2-2]如果加上原因字符串之后的PUBACK报文长度超出了接收端指定的最大报文长度,则发送端不能发送此原因字符串。[MQTT-3.4.2-3]如果加上用户属性之后的PUBACK报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.5.2-1]服务端或客户端发送PUBREC报文时必须设置其中一种原因码。[MQTT-3.5.2-2]发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的PUBREC报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.5.2-3]如果加上用户属性之后的PUBREC报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.6.1-1]PUBREL固定报头的第3,2,1,0位是保留位,必须被设置为0,0,1,0。服务端必须将其它的任何值都当做是不合法的并关闭网络连接。[MQTT-3.6.2-1]客户端或服务端发送PUBREL报文时必须设置其中一种PUBREL原因码。[MQTT-3.6.2-2]如果加上原因字符串之后的PUBREL报文长度超出了接收端指定的最大报文长度,则发送端不能发送此原因字符串。[MQTT-3.6.2-3]如果加上用户属性之后的PUBREL报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.7.2-1]服务端或客户端发送PUBCOMP报文时必须设置一种PUBCOMP原因码。[MQTT-3.7.2-2]如果加上原因字符串之后的PUBCOMP报文长度超出了接收端指定的最大报文长度,则发送端不能发送此原因字符串。[MQTT-3.7.2-3]如果加上用户属性之后的PUBCOMP报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.8.1-1]SUBSCRIBE报文固定报头第3,2,1,0比特位是保留位,必须被设置为0,0,1,0。服务端必须将其他的任何值都当做是不合法的并关闭网络连接。[MQTT-3.8.3-1]主题过滤器必须为UTF-8 编码的字符串。[MQTT-3.8.3-2]载荷必须包含至少一个主题过滤器/订阅选项对。[MQTT-3.8.3-3]订阅选项的第2比特表示非本地选项。值为1,表示应用消息不能被转发给发布此消息的客户标识符。[MQTT-3.8.3-4]共享订阅时把非本地选项设为1将造成协议错误。[MQTT-3.8.3-5]订阅选项的第6和7比特为将来所保留。服务端必须把此保留位非0的SUBSCRIBE报文当做无效报文。[MQTT-3.8.4-1]当服务端收到来自客户端的SUBSCRIBE报文时,必须使用SUBACK报文作为相应。[MQTT-3.8.4-2]SUBACK报文必须和待确认的SUBSCRIBE报文有相同的报文标识符。[MQTT-3.8.4-3]如果服务端收到的SUBSCRIBE报文中的一个主题过滤器与当前会话的一个非共享订阅相同,那么必须使用新的订阅替换现存的订阅。[MQTT-3.8.4-4]如果保留处理选项为0,任何匹配该主题过滤器的保留消息必须被重发,但替换订阅不能造成应用消息的丢失。[MQTT-3.8.4-5]如果服务端收到的SUBSCRIBE报文包含多个主题过滤器,服务端必须当做收到一系列多个SUBSCRIBE报文来处理--除了将它们的响应组合为单个SUBACK响应。[MQTT-3.8.4-6]服务端发送给客户端的SUBACK报文必须为每一个主题过滤器/订阅选项对包含一个原因码。[MQTT-3.8.4-7]此原因码必须说明为该订阅授予的最大QoS等级,或指示订阅失败。[MQTT-3.8.4-8]响应该订阅的应用消息QoS等级必须为该消息发布时的QoS等级和服务端授予的最大QoS等级二者最小值。[MQTT-3.9.2-1]如果加上原因字符串之后的SUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串。[MQTT-3.9.2-2]如果加上用户属性之后的SUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性。[MQTT-3.9.3-1]SUBACK报文中的原因码顺序必须与SUBSCRIBE报文中的主题过滤器顺序相匹配。[MQTT-3.9.3-2]服务端发送SUBACK报文时必须对收到的每一个主题过滤器设置一种原因码。[MQTT-3.10.1-1]UNSUBSCRIBE固定报头的第3,2,1,0位是保留位且必须分别设置为0,0,1,0。服务端必须认为任何其它的值都是不合法的并关闭网络连接。[MQTT-3.10.3-1]UNSUBSCRIBE报文中的主题过滤器必须为UTF-8编码的字符串。[MQTT-3.10.3-2]UNSUBSCRIBE报文有效载荷必须包含至少一个主题过滤器。[MQTT-3.10.4-1]服务端必须对客户端的UNSUBSCRIBE报文中提供的主题过滤器(不管是否包含通配符)逐个字符与当前持有的主题过滤器集进行比较。如果任何过滤器完全匹配,则必须删除其拥有的订阅。[MQTT-3.10.4-2]当服务端收到UNSUBSCRIBE报文,它必须停止添加为了交付给客户端的与主题过滤器相匹配的任何新消息。[MQTT-3.10.4-3]当服务端收到UNSUBSCRIBE报文,它必须完成任何已经开始发送给客户端的、与主题过滤器相匹配的、QoS等级为1或2的消息。[MQTT-3.10.4-4]服务端必须发送UNSUBACK报文以响应客户端的UNSUBSCRIBE请求。[MQTT-3.10.4-5]UNSUBACK报文必须包含和UNSUBSCRIBE报文相同的报文标识符。即使没有删除任何主题订阅,服务端也必须发送一个UNSUBACK响应。[MQTT-3.10.4-6]如果服务端收到的UNSUBSCRIBE报文包含多个主题过滤器,服务端必须当做收到一系列多个UNSUBSCRIBE报文来处理--除了将它们的响应组合为单个SUBACK响应。[MQTT-3.11.2-1]如果加上原因字符串之后的UNSUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串。[MQTT-3.11.2-2]如果加上用户属性之后的UNSUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性。[MQTT-3.11.3-1]UNSUBACK报文中的原因码顺序必须与UNSUBSCRIBE报文中的主题过滤器顺序相匹配。[MQTT-3.11.3-2]服务端发送UNSUBACK报文时对于每个收到的主题过滤器,必须使用一个取消订阅原因码。[MQTT-3.12.4-1]服务端必须发送PINGRESP报文响应客户端的PINGREQ报文。[MQTT-3.14.0-1]服务端不能发送DISCONNECT报文,直到它发送了包含原因码小于0x80的CONNACK报文之后。[MQTT-3.14.1-1]服务端或客户端必须验证所有的保留位都被设置为0,如果他们不为0,发送包含原因码为0x81(无效报文)的DISCONNECT报文。[MQTT-3.14.2-1]客户端或服务端发送DISCONNECT报文时必须使用一种DISCONNECT原因码。[MQTT-3.14.2-2]会话过期间隔不能由服务端的DISCONNECT报文发送。[MQTT-3.14.2-3]如果此属性使得DISCONNECT报文的长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.14.2-4]如果加上用户属性之后的DISCONNECT报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.14.4-1]发送端发送完DISCONNECT报文之后不能再在此网络连接上发送任何MQTT控制报文。[MQTT-3.14.4-2]发送端发送完DISCONNECT报文之后必须关闭网络连接。[MQTT-3.14.4-3]接收到包含原因码为0x00(成功)的DISCONNECT时,服务端必须丢弃任何与当前连接相关的遗嘱消息,而不发布它。[MQTT-3.15.1-1]AUTH报文固定报头第3,2,1,0位是保留位,必须全设置为0。客户端或服务端必须把其他值当做无效值并关闭网络连接。[MQTT-3.15.2-1]AUTH报文的发送端必须使用一种认证原因码。[MQTT-3.15.2-2]如果加上原因字符串之后的AUTH报文长度超出了接收端所指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.15.2-3]如果加上用户属性之后的AUTH报文长度超出了接收端指定的最大报文长度,则服务端不能发送此属性。[MQTT-4.1.0-1]当网络连接打开时,客户端和服务端不能丢弃会话状态。[MQTT-4.2.0-1]客户端或服务端必须支持使用一个或多个提供有序的、可靠的、双向传输(从客户端到服务端和从服务端到客户端)字节流传输的底层传输协议。[MQTT-4.1.0-2]当网络连接被关闭并且会话过期间隔已过时,服务端必须丢弃会话状态。[MQTT-4.3.1-1]对于QoS等级0的分发协议,发送端必须发送QoS等于0,DUP等于0的PUBLISH报文。[MQTT-4.3.2-1]对于QoS等级1的分发协议,发送端每次发送新的应用消息都必须分配一个未使用的用户标识符。[MQTT-4.3.2-2]对于QoS等级1的分发协议,发送端发送的PUBLISH报文必须包含报文标识符且QoS等于1,DUP等于0。[MQTT-4.3.2-3]对于QoS等级1的分发协议,发送端必须将这个PUBLISH报文看作是未确认的 ,直到从接收端那收到对应的PUBACK报文。[MQTT-4.3.2-4]对于QoS等级1的分发协议,接收端响应的PUBACK报文必须包含一个报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文。[MQTT-4.3.2-5]对于QoS等级1的分发协议,接收端发送了PUBACK报文之后,接收端必须将任何包含相同报文标识符的入站PUBLISH报文当做一个新的消息,并忽略它的DUP标志的值。[MQTT-4.3.3-1]对于QoS等级2的分发协议,发送端必须给要发送的新应用消息分配一个未使用的报文标识符。[MQTT-4.3.3-2]对于QoS等级2的分发协议,发送端PUBLISH报文必须包含报文标识符且报文的QoS等于2,DUP等于0。[MQTT-4.3.3-3]对于QoS等级2的分发协议,发送端必须将这个PUBLISH报文看作是未确认的 ,直到从接收端那收到对应的PUBREC报文。[MQTT-4.3.3-4]对于QoS等级2的分发协议,收到发送端发送的包含原因码小于0x80的PUBREC报文后必须发送一个PUBREL报文。PUBREL报文必须包含与原始PUBLISH报文相同的报文标识符。[MQTT-4.3.3-5]对于QoS等级2的分发协议,发送端必须将这个PUBREL报文看作是未确认的 ,直到从接收端那收到对应的PUBCOMP报文。[MQTT-4.3.3-6]对于QoS等级2的分发协议,发送端一旦发送了对应的PUBREL报文就不能重发这个PUBLISH报文。[MQTT-4.3.3-7]对于QoS等级2的分发协议,如果PUBLISH报文已发送,不能应用消息过期属性。[MQTT-4.3.3-8]对于QoS等级2的分发协议,接收端响应的PUBREC报文必须包含报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文。[MQTT-4.3.3-9]对于QoS等级2的分发协议,如果接收端发送了包含原因码大于等于0x80的PUBREC报文,它必须将后续包含相同报文标识符的PUBLISH报文当做是新的应用消息。[MQTT-4.3.3-10]对于QoS等级2的分发协议,接收端在收到对应的PUBREL报文之前,接收端必须发送PUBREC报文确认任何后续的具有相同报文标识符的PUBLISH报文。在这种情况下,它不能重复分发消息给任何后续的接收者。[MQTT-4.3.3-11]对于QoS等级2的分发协议,接收端必须发送包含与PUBREL相同报文标识符的PUBCOMP报文作为对PUBREL报文的响应。[MQTT-4.3.3-12]对于QoS等级2的分发协议,接收端发送PUBCOMP报文之后,必须将后续包含相同报文标识符的PUBLISH报文当做是新的应用消息。[MQTT-4.3.3-13]对于QoS等级2的分发协议,接收端必须继续QoS等级2确认序列,即使它已经应用了消息过期属性。[MQTT-4.4.0-1]客户端以新开始标志为0且会话存在的情况下重连时,客户端和服务端都必须使用原始报文标识符重新发送任何未被确认的PUBLISH报文(当QoS > 0)和PUBREL报文。这是唯一要求客户端或服务端重发消息的情况。客户端和服务端不能在其他任何时间重发消息。[MQTT-4.4.0-2]如果收到包含原因码大于等于0x80的PUBACK或PUBREC,则对应的PUBLISH报文被看作已确认,且不能被重传。[MQTT-4.5.0-1]当服务端接受入站应用消息的所有权时,它必须将消息添加到订阅匹配的客户端的会话状态中。[MQTT-4.5.0-2]客户端必须按照可用的服务质量(QoS)规则确认它收到的任何PUBLISH报文,不管它是否选择处理其包含的应用消息。[MQTT-4.6.0-1]重发任何之前的PUBLISH报文时,客户端必须按原始PUBLISH报文的发送顺序重发(适用于QoS等级1和QoS等级2 消息)。[MQTT-4.6.0-2]客户端必须按照对应的PUBLISH报文的顺序发送PUBACK报文(QoS等级1消息)。[MQTT-4.6.0-3]客户端必须按照对应的PUBLISH报文的顺序发送PUBREC报文(QoS等级2消息)。[MQTT-4.6.0-4]客户端必须按照对应的PUBREC报文的顺序发送PUBREL报文(QoS等级2消息)。[MQTT-4.6.0-5]当服务端处理发布到有序主题的消息时,它必须按照消息从任何给定客户端接收的顺序发送PUBLISH报文给消费端(对于同一主题和QoS等级)。[MQTT-4.6.0-6]默认情况下,服务端转发非共享订阅的消息时,必须将每个主题都视为有序主题。[MQTT-4.7.0-1]主题过滤器中可以使用通配符,但是主题名不能使用通配符。[MQTT-4.7.1-1]多层通配符必须单独指定,或者跟在主题层级分隔符后面。不管哪种情况,它都必须是主题过滤器的最后一个字符。[MQTT-4.7.1-2]在主题过滤器的任意层级都可以使用单层通配符,包括第一个和最后一个层级。在使用它时,它必须占据过滤器的整个层级。[MQTT-4.7.2-1]服务端不能将$字符开头的主题名匹配通配符(#或+)开头的主题过滤器。[MQTT-4.7.3-1]所有的主题名和主题过滤器必须至少包含一个字符。[MQTT-4.7.3-2]主题名和主题过滤器不能包含空字符 (Unicode U+0000) [Unicode]。[MQTT-4.7.3-3]主题名和主题过滤器是UTF-8编码字符串,它们不能超过65,535字节。[MQTT-4.7.3-4]匹配订阅时,服务端不能对主题名或主题过滤器执行任何规范化处理,不能修改或替换任何未识别的字符。[MQTT-4.8.2-1]除非另有说明,如果服务端或客户端遇到了协议违规的行为,它必须关闭传输这个协议违规控制报文的网络连接。[MQTT-4.8.2-2]如果客户端或服务端处理入站控制报文时遇到了瞬时错误,它必须关闭传输那个控制报文的网络连接。[MQTT-4.8.2-3]向客户端发送应用消息时,服务端必须考虑授予客户端的QoS等级。[MQTT-4.8.2-4]服务端必须在客户端重新连接时完成向该客户端的消息分发。[MQTT-4.8.2-5]如果客户端的会话在客户端重连之前终止,服务端不能把此消息发送给其他订阅的客户端。[MQTT-4.8.2-6]如果客户端对来自服务端的PUBLISH报文使用包含原因码大于等于0x80的PUBACK或PUBREC报文进行响应,服务端必须丢弃应用消息而不尝试将其发送给任何其他订阅者。[MQTT-4.9.0-1]客户端或服务端必须将其初始发送配额设置为不超过接收最大值的非0值。[MQTT-4.9.0-2]每当客户端或服务端发送了一个QoS等级大于0的PUBLISH报文,它就会减少发送配额。如果发送配额减为0,客户端或服务端不能再发送任何QoS等级大于0的PUBLISH报文。[MQTT-4.9.0-3]它可以继续发送QoS为0的PUBLISH报文,也可以选择暂停发送这些报文。即使配额为0,客户端和服务端也必须继续处理和响应其他MQTT控制报文。[MQTT-4.12.0-1]如果服务端不支持客户端提供的认证方法,它可以发送一个包含原因码0x8C(无效的认证方法)或0x87(未授权)的CONNACK报文,并且必须关闭网络连接。[MQTT-4.12.0-2]如果服务端需要额外的信息来完成认证,它可以向客户端发送AUTH报文,此报文必须包含原因码0x18(继续认证)。[MQTT-4.12.0-3]客户端通过发送另一个AUTH报文响应来自服务端的AUTH报文,此报文必须包含原因码0x18(继续认证)。[MQTT-4.12.0-4]服务端可以在处理过程中随时拒绝认证。它可以发送包含原因码大于等于0x80的CONNACK报文,如4.13节所述,并且必须关闭网络连接。[MQTT-4.12.0-5]如果初始CONNECT报文包含认证方法属性,则所有的AUTH报文和成功的CONNACK报文必须包含与CONNECT报文中相同的认证方法属性。[MQTT-4.12.0-6]如果客户端在CONNECT报文中没有包含认证方法,则服务端不能发送AUTH报文,且不能在CONNACK报文中发送认证方法。[MQTT-4.12.0-7]如果客户端在CONNECT报文中没有包含认证方法,则客户端不能向服务端发送AUTH报文。[MQTT-4.12.1-1]如果客户端在CONNECT报文中提供了认证方法,它可以在收到CONNACK报文之后的任何时间通过发送包含原因码0x19(重新认证)的AUTH报文发起重新认证。客户端必须将认证方法设置为与最初验证网络连接时的认证方法一致。[MQTT-4.12.1-2]如果重新认证失败,客户端或服务端应该发送包含适当原因码的DISCONNECT报文,如 section 4.13节 所述。并且必须关闭网络连接。[MQTT-4.13.1-1]当服务端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时,它必须关闭网络连接。[MQTT-4.13.2-1]CONNACK报文和DISCONNECT报文允许使用大于等于0x80的原因码以指示网络连接将被关闭。如果某个大于等于0x80的原因码被指定,无论是否发送CONNACK报文或DISCONNECT报文,必须关闭网络连接。[MQTT-6.0.0-1]MQTT控制报文必须使用WebSocket二进制数据帧发送。如果收到任何其它类型的数据帧,接收者必须关闭网络连接。[MQTT-6.0.0-2]单个WebSocket数据帧可以包含多个或者部分MQTT报文。接收者不能假设MQTT控制报文按WebSocket帧边界对齐。[MQTT-6.0.0-3]客户端必须将字符串"mqtt"包含在它提供的WebSocket子协议列表里。[MQTT-6.0.0-4]服务端选择和返回的WebSocket子协议名必须是mqtt。 项目主页 MQTT v5.0协议草案中文版 附录C MQTT v5.0新特性总结(非规范) 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] MQTT v5.0添加了以下特性 会话过期把清理会话标志拆分成新开始标志(指示会话应该在不使用现有会话的情况下开始)和会话过期间隔标志(指示连接断开之后会话保留的时间)。会话过期间隔时间可以在断开时修改。把新开始标志设置为1且会话过期间隔标志设置为0,等同于在MQTT v3.1.1中把清理会话(CleanSession)设置为1。 消息过期允许消息在发布时设置一个过期间隔。 所有确认报文原因码更改所有响应报文以包含原因码,包括CONNACK,PUBACK,PUBREC,PUBREL,PUBCOMP,SUBACK,UNSUBACK,DISCONNECT和AUTH,以使得调用方确定请求的函数是否成功。 所有确认报文原因字符串更改大部分报文以包含原因码同时也允许一个可选的原因字符串。这是为问题定位而设计的,并且不应由接收端所解析。 服务端断开允许服务端发送DISCONNECT报文,以指示连接被关闭的原因。 载荷格式和内容类型允许在消息发布时指定载荷格式(二进制、文本)和MIME样式内容类型。这些信息被转发到消息的接收端。 请求/响应规定MQTT请求/响应模式,提供响应主题和对比数据属性,以使得响应消息被路由回请求的发布者。此外,为客户端添加从服务端获取获取关于构造响应主题的配置信息的能力。 共享订阅添加对共享订阅的支持,以允许多个订阅消费者进行负载均衡。 订阅标识符允许在SUBSCRIBE报文中指定一个数字订阅标识符,并在消息分发时返回此标识符。这使得客户端收到分发的消息时确定此消息是由哪个或哪些订阅导致的。 主题别名通过将主题名缩写为小整数来减小MQTT报文的开销大小。客户端和服务端分别指定它们允许的主题别名的数量。 流量控制允许客户端和服务端分别指定未完成的可靠消息(QoS>0)的数量。发送端可以暂停发送此类消息以保持消息数量低于配额。这被用于限制可靠消息的速率和某一时刻的传输中(in-flight)消息数量。 用户属性为大多数报文添加用户属性。PUBLISH报文的用户属性由客户端应用程序定义。PUBLISH报文和遗嘱报文的用户属性由服务端转发给应用消息的接收端。CONNECT,SUBSCRIBE和UNSUBSCRIBE报文的用户属性由服务端实现定义。CONNACK,PUBACK,PUBREC,PUBREL,PUBCOMP,SUBACK,UNSUBACK和AUTH报文的用户属性由发送端定义,且对发送端具有唯一性。MQTT规范不定义用户属性的意义。 最大报文长度允许客户端和服务端各自指定它们支持的最大报文长度。会话参与方发送更大的报文将造成错误。 可选的服务端功能可用性提供定义一组服务端不允许的功能,并告知客户端的机制。可以使用这种方式指定的功能包括:最大QoS等级,保留可用,通配符订阅可用,订阅标识符可用和共享订阅可用。客户端使用服务端通知了(不可用)的功能将造成错误。在早期版本的MQTT协议中,服务端没有实现的功能通过未授权告知客户端。当客户端使用其中一种(不可用的)功能时,此功能允许服务端告知客户端,并添加特定的原因码。 增强的认证提供一种机制来启用包括互相认证在内的质询/响应风格的认证。这允许在客户端和服务端都支持的情况下使用SASL风格的认证,包括客户端在连接中重新认证的功能。 订阅选项提供主要用于定义允许消息桥接应用的订阅选项。包括不要把消息发送给消息源客户端(非本地)的选项和订阅时处理保留消息的选项。 遗嘱延迟提供指定遗嘱消息在连接中断后延时发送的能力。设计此特性是为了在会话的连接重建的情况下不发送遗嘱消息。此特性允许连接短暂中断而不通知其他客户端。 服务端保持连接允许服务端指定其希望客户端使用的保持连接值。此特性允许服务端设置最大允许的保持连接值并被客户端使用。 分配客户标识符服务端分配了客户标识符的情况下,向客户端返回此客户标识符。服务端分配客户标识符只能用于新开始标志为1的连接。 服务端参考允许服务端使用CONNACK或DISCONNECT报文指定备用服务端。此特性被用于(服务端)重定向或做准备。 --- ### 30. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1  概述 1.0 知识产权政策 此公开评审草案的发布基于OASIS IPR Policy 的Non-Assertion 模式。 关于实现本规范必不可少的任何专利是否已公开, 以及其他的专利许可条款相关的信息,请参考技术委员 会网站的知识产权部分(https://www.oasis-open.org/committees/mqtt/ipr.php)。 1.1 MQTT 协议的组织结构 本规范分为七个章节: .    第一章 - 介绍 .    第二章 - MQTT 控制报文格式 .    第三章 - MQTT 控制报文 .    第四章 - 操作行为 .    第五章 - 安全 .    第六章 - 使用 Websocket 作为网络传输层 .    第七章 - 一致性目标 1.2 术语 本规范中用到的关键字 必须 MUST ,不能 MUST NOT ,要求 REQUIRED ,将会 SHALL ,不会 SHALL NOT ,应该 SHOULD ,不应该 SHOULD NOT ,推荐 RECOMMENDED ,可以 MAY ,可选 OPTIONAL 都 是按照 IETF RFC 2119[RFC2119]中的描述解释。 网络连接(Network Connection): MQTT 使用的底层传输协议基础设施。 .     客户端使用它连接服务端。 .      它提供有序的、可靠的、双向字节流传输。 例子见4.2节。 应用消息(Application Message): MQTT 协议通过网络传输应用数据。应用消息通过 MQTT 传输时,它们有关联的服务质量(QoS)和主题 (Topic)。 客户端(Client): 使用 MQTT 的程序或设备。客户端总是通过网络连接到服务端。它可以: .     打开连接到服务端的网络连接 .     发布应用消息给其他相关的客户端 .     订阅以请求接受相关的应用消息 .     取消订阅以移除接受相应消息的请求 .     关闭连接到服务端的网络连接 服务端(Server): 一个程序或设备,作为发送消息的客户端和请求订阅的客户端之间的中介。服务端: .     接受来自客户端的网络连接 .     接受客户端发布的应用消息 .     处理客户端的订阅和取消订阅请求 .     转发应用消息给符合条件的客户端订阅 .     关闭来自客户端的网络连接 会话(Session): 客户端和服务端之间的状态交互。 一些会话持续时长与网络连接一样, 另一些可以在客户端和服务端的多 个连续网络连接间扩展。 订阅(Subscription): 订阅包含一个主题过滤器(Topic  Filter)和一个最大的服务质量(QoS)等级。订阅与单个会话(Session) 关联。会话可以包含多于一个的订阅。会话的每个订阅都有一个不同的主题过滤器。 共享订阅(Shared Subscription): 一个共享订阅包含一个主题过滤器(Topic Filter)和一个最大的服务质量(QoS)等级。 一个共享订阅可 以与多个订阅会话相关联, 便于支持大范围消息交换模式。 一条主题匹配的应用消息只发送给关联到此共 享订阅的多个会话中的一个会话。一个会话可以包括多个共享订阅,可以同时包含共享订阅与非共享订阅。 通配符订阅(Wildcard Subscription): 通配符订阅是指主题过滤器(Topic Filter)包含一个或多个通配符的订阅。通配符订阅使得一次订阅匹配 多个主题名(Topic Name)。4.7节描述了主题过滤器中的通配符。 主题名(Topic Name): 附加在应用消息上的一个标签,服务端已知且与订阅匹配。服务端发送应用消息的一个副本给每一个匹配 的客户端订阅。 主题过滤器(Topic Filter): 订阅中包含的一个表达式, 用于表示相关的一个或多个主题。主题过滤器可以使用通配符。 MQTT 控制报文(MQTT Control Packet): 通过网络连接发送的信息数据包。 MQTT 规范定义了十四种不同类型的 MQTT 控制报文, 其中一个 (PUBLISH 报文)用于传输应用消息。 无效报文(Malformed Packet): 根据规范不能被正确解析的控制报文。4.13节描述了如何进行相应的错误处理。 协议错误(Protocol Error): 在报文解析之后发现包含协议不允许或与客户端或服务端当前状态不一致的数据的错误。 4.13节描述了如 何进行相应的错误处理。 遗嘱消息(Will Message): 在网络连接非正常关闭的情况下,由服务端发布的应用消息。 3.1.2.5节描述了遗嘱消息。 1.3 规范引用 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, http://www.rfc-editor.org/info/rfc2119 [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003, http://www.rfc-editor.org/info/rfc3629 [RFC6455] Fette, I. and A. Melnikov, "The WebSocket Protocol", RFC 6455, DOI 10.17487/RFC6455, December 2011, http://www.rfc-editor.org/info/rfc6455 [Unicode] The Unicode Consortium. The Unicode Standard, http://www.unicode.org/versions/latest/ 1.4 非规范引用 [RFC0793] Postel, J., "Transmission Control Protocol", STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981, http://www.rfc-editor.org/info/rfc793 [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008, http://www.rfc-editor.org/info/rfc5246 [AES] Advanced Encryption Standard (AES) (FIPS PUB 197). https://csrc.nist.gov/csrc/media/publications/fips/197/final/documents/fips-197.pdf [CHACHA20] ChaCha20 and Poly1305 for IETF Protocols https://tools.ietf.org/html/rfc7539 [FIPS1402] Security Requirements for Cryptographic Modules (FIPS PUB 140-2) https://csrc.nist.gov/csrc/media/publications/fips/140/2/final/documents/fips1402.pdf [IEEE 802.1AR] IEEE Standard for Local and metropolitan area networks - Secure Device Identity http://standards.ieee.org/findstds/standard/802.1AR-2009.html [ISO29192] ISO/IEC 29192- 1:2012 Information technology -- Security techniques -- Lightweight cryptography -- Part 1: General https://www.iso.org/standard/56425.html [MQTT NIST] MQTT supplemental publication, MQTT and the NIST Framework for Improving Critical Infrastructure Cybersecurity http://docs.oasis-open.org/mqtt/mqtt-nist-cybersecurity/v1.0/mqtt-nist-cybersecurity-v1.0.html [MQTTV311] MQTT V3.1.1 Protocol Specification http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html [ISO20922] MQTT V3.1.1 ISO Standard (ISO/IEC 20922:2016) https://www.iso.org/standard/69466.html [NISTCSF] Improving Critical Infrastructure Cybersecurity Executive Order 13636 https://www.nist.gov/sites/default/files/documents/itl/preliminary-cybersecurity-framework.pdf [NIST7628] NISTIR 7628 Guidelines for Smart Grid Cyber Security Catalogue https://www.nist.gov/sites/default/files/documents/smartgrid/nistir-7628_total.pdf [NSAB] NSA Suite B Cryptography http://www.nsa.gov/ia/programs/suiteb_cryptography/ [PCIDSS] PCI-DSS Payment Card Industry Data Security Standard https://www.pcisecuritystandards.org/pci_security/ [RFC1928] Leech, M., Ganis, M., Lee, Y., Kuris, R., Koblas, D., and L. Jones, "SOCKS Protocol Version 5", RFC 1928, DOI 10.17487/RFC1928, March 1996, http://www.rfc-editor.org/info/rfc1928 [RFC4511] Sermersheim, J., Ed., "Lightweight Directory Access Protocol (LDAP): The Protocol", RFC 4511, DOI 10.17487/RFC4511, June 2006, http://www.rfc-editor.org/info/rfc4511 [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008, http://www.rfc-editor.org/info/rfc5280 [RFC6066] Eastlake 3rd, D., "Transport Layer Security (TLS) Extensions: Extension Definitions", RFC 6066, DOI 10.17487/RFC6066, January 2011, http://www.rfc-editor.org/info/rfc6066 [RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, October 2012, http://www.rfc-editor.org/info/rfc6749 [RFC6960] Santesson, S., Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. Adams, "X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP", RFC 6960, DOI 10.17487/RFC6960, June 2013, http://www.rfc-editor.org/info/rfc6960 [SARBANES] Sarbanes-Oxley Act of 2002. http://www.gpo.gov/fdsys/pkg/PLAW-107publ204/html/PLAW-107publ204.htm [USEUPRIVSH] U.S.-EU Privacy Shield Framework https://www.privacyshield.gov [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, http://www.rfc-editor.org/info/rfc3986 [RFC1035] Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, DOI 10.17487/RFC1035, November 1987, http://www.rfc-editor.org/info/rfc1035 [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for specifying the location of services (DNS SRV)", RFC 2782, DOI 10.17487/RFC2782, February 2000, http://www.rfc-editor.org/info/rfc2782 1.5 数据表示 1.5.1 二进制位 字节中的位从 0 到 7。第 7 位是最高有效位,第 0 位是最低有效位。 1.5.2 双字节整数 双字节整数是 16 位,使用大端序(big-endian,高位字节在低位字节前面) 。这意味着一个 16 位的字在 网络上表示为最高有效字节(MSB) ,后面跟着最低有效字节(LSB)。 1.5.3 四字节整数 四字节整数是 32 位,使用大端序(big-endian,高位字节在低位字节前面) 。这意味着一个 32 位的字在 网络上表示为第一个最高有效字节(MSB)后面跟着第一个最低有效字节(LSB),再后面为第二个最高 有效字节(MSB)后面跟着第二个最低有效字节(LSB)。 1.5.4 UTF-8 编码字符串 后续描述的 MQTT 控制报文中的文本字段编码为 UTF-8 格式的字符串。UTF-8[RFC3629]是一个高效的 Unicode 字符编码格式, 为了支持基于文本的通信,它对 ASCII 字符的编码做了优化。 每一个字符串都有一个两字节的长度字段作为前缀,它给出这个字符串 UTF-8 编码的字节数,它们在图 1.1 UTF-8 编码字符串的结构中描述。因此可以传送的 UTF-8 编码的字符串大小有一个限制,不能超过 65535 字节。 除非另有说明, 所有的 UTF-8 编码字符串的长度都在 0 到 65535 字节这个范围内。 图 1- 1 - UTF-8 编码字符串的结构 二进制位76543210 byte 1字符串长度的最高有效字节(MSB)byte 2字符串长度的最低有效字节(LSB)byte 3 … .如果长度大于 0,这里是 UTF-8 编码的字符数据 UTF-8 编码字符串中的字符数据必须是按照 Unicode 规范[Unicode]定义的和在 RFC3629[RFC3629]中重 申的有效的 UTF-8 格式。特别需要指出的是,这些数据不能包含字符码在 U+D800 和 U+DFFF 之间的数  据。如果服务端或客户端收到了一个包含无效 UTF-8 字符的 MQTT 控制报文, 它必须关闭网络连接 [MQTT- 1.5.4- 1]。 UTF-8 编码的字符串不能包含空字符 U+0000 [MQTT- 1.5.4-2]。如果客户端或服务端收到了一个包含 U+0000 的控制报文, 它必须关闭网络连接。 数据中不应该包含下面这些 Unicode 代码点的编码。如果一个接收者(服务端或客户端)收到了包含下列 任意字符的 MQTT 控制报文,它可以把此报文当做无效报文。 .     U+0001 和 U+001F 之间的控制字符 .     U+007F 和 U+009F 之间的控制字符 .    [Unicode]规范定义的非字符代码点(例如 U+0FFFF) UTF-8 编码序列 0XEF 0xBB 0xBF 总是被解释为 U+FEFF(零宽度非换行空白字符),无论它出现在字符 串的什么位置, 报文接收者都不能跳过或者剥离它 [MQTT- 1.5.4-3]。 非规范示例 例如,字符串 A    是一个大写拉丁字母 A 后面跟着一个代码点 U+2A6D4(它表示一个中日韩统一 表意文字扩展 B 中的字符),这个字符串编码如下: 图 1-2 UTF-8 编码字符串非规范示例 Bit76543210byte 1字符串长度 MSB (0x00) 00000000byte 2字符串长度 LSB (0x05) 00000101byte 3‘A’ (0x41) 01000001byte 4(0xF0) 11110000byte 5(0xAA) 10101010 byte 6(0x9B) 10011011byte 7(0x94) 10010100 1.5.5 变长字节整数 剩余长度字段使用一个变长字节编码方案, 对小于 128 的值它使用单字节编码。更大的值按下面的方式处 理。低 7 位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个字节可以编码 128 个 数值和一个延续位(continuation bit)。剩余长度字段最大 4 个字节 [MQTT- 1.5.5- 1] ,如表 1-1 所示。 表 1- 1 - 变长字节整数大小 字节数最小值最大值10 (0x00)127 (0x7F)2128 (0x80, 0x01)16,383 (0xFF, 0x7F)316,384 (0x80, 0x80, 0x01)2,097,151 (0xFF, 0xFF, 0x7F)42,097,152 (0x80, 0x80, 0x80, 0x01)268,435,455 (0xFF, 0xFF, 0xFF, 0x7F) 非规范评注 非负整数 X 使用变长编码方案的算法如下: do encodedByte = X MOD 128 X = X DIV 128 // if there are more data to encode, set the top bit of this byte if (X > 0) encodedByte = encodedByte OR 128 endif 'output' encodedByte while (X > 0) MOD 是模运算,DIV 是整数除法, OR 是位操作或(C 语言中分别是% ,/ ,|)。 非规范评注 剩余长度字段的解码算法如下: multiplier = 1 value = 0 do encodedByte = 'next byte from stream' value += (encodedByte AND 127) * multiplier if (multiplier > 128*128*128) throw Error(Malformed Variable Byte Integer) multiplier *= 128 while ((encodedByte AND 128) != 0) AND 是位操作与(C 语言中的&) 这个算法终止时,value 包含的就是剩余长度的值。 1.5.6 二进制数据 二进制数据由一个双字节整数指示其数据长度,因此, 二进制数据的长度被限制为 0 到 65,535 字节。 1.5.7 UTF-8 字符串对 UTF-8 字符串对由两个 UTF-8 编码的字符串组成,用来表示名字-值对,第一个字符串表示名字, 第二个字 符串表示值。 所有的字符串必须遵循 UTF-8 字符串编码规范 [MQTT- 1.5.7- 1]。如果接受者(客户端或者服务端)接受到 一个字符串对, 然而其编码并不遵循规范, 则此报文为无效报文。4.13 节描述了错误处理的信息。 1.6 安全 MQTT 客户端和服务端实现应该提供认证、授权和安全通信功能,如第 5 章所描述。强烈建议任何关注于 个人身份信息或敏感信息的应用使用这些安全设施。 1.7 编辑约定 本规范用黄色高亮的文本标识一致性声明,每个一致性声明都分配了一个这种格式的引用: [MQTT-x.x.x-y]。 1.8 变更历史 1.8.1 MQTT v3.1.1 MQTT v3.1.1 MQTT v3.1.1 是首个 OASIS 标准版本 MQTT[MQTTV311]。 也是 ISO/IEC 20922:2016 [ISO20922]标准。 1.8.2 MQTT v5.0 MQTT v5.0 在保持 MQTT 核心不变的基础上添加了大量的新功能。这些功能的主要目标如下: .     进一步支持大规模可扩展系统 .     改进的错误报告 Improved error reporting .     规范化包括容量探索和请求响应在内的通用模式 .     包括用户属性在内的可扩展机制 .     改进性能并支持小型客户端 附录C对 MQTT v5.0 的改进做出了总结。 2  MQTT 控制报文格式 2.1 MQTT 控制报文结构 MQTT 协议通过交换预定义的 MQTT 控制报文来通信。这一节描述这些报文的格式。 MQTT 控制报文由三部分组成,按照下图描述的顺序。 图 2- 1 - MQTT 控制报文的结构 Fixed Header 固定报头, 所有控制报文都包含Variable Header 可变报头,部分控制报文包含Payload 有效载荷,部分控制报文包含 2.1.1 固定报头 如下图所示,每个 MQTT 控制报文都包含一个固定报头。 图 2-2 - 固定报头的格式 Bit76543210byte 1MQTT 控制报文的类型用于指定控制报文类型的标志位byte 2 …剩余长度 2.1.2 MQTT 控制报文的类型 位置: 第 1 个字节, 二进制位 7-4。 表示为 4 位无符号值,这些值的定义见下表。 表 2- 1 - MQTT 控制报文的类型 名字值报文流动方向描述Reserved0禁止保留CONNECT1客户端到服务端客户端请求连接服务端CONNACK2服务端到客户端连接报文确认PUBLISH3两个方向都允许发布消息PUBACK4两个方向都允许QoS 1 消息发布收到确认 PUBREC5两个方向都允许发布收到(保证交付第一步)PUBREL6两个方向都允许发布释放(保证交付第二步)PUBCOMP7两个方向都允许QoS 2 消息发布完成(保证交付第三步)SUBSCRIBE8客户端到服务端客户端订阅请求SUBACK9服务端到客户端订阅请求报文确认UNSUBSCRIBE10客户端到服务端客户端取消订阅请求UNSUBACK11服务端到客户端取消订阅报文确认PINGREQ12客户端到服务端心跳请求PINGRESP13服务端到客户端心跳响应DISCONNECT14两个方向都允许断开连接通知AUTH15两个方向都允许认证信息交换 2.1.3 标志 固定报头第 1 个字节的剩余的 4 位 [3-0]包含每个 MQTT 控制报文类型特定的标志如下表所示。 表格中任   何标记为“保留” 的标志位, 都是保留给以后使用的,必须设置为表格中列出的值 [MQTT-2.1.3- 1]。如果收到 非法的标志, 此报文被当做无效报文。有关错误处理的详细信息见4.13节。 表格 2-2 - 标志位 MQTT 控制报文固定报头标志Bit 3Bit 2Bit 1Bit 0CONNECTReserved0000CONNACKReserved0000PUBLISHUsed in MQTT v5.0DUPQoSRETAINPUBACKReserved0000PUBRECReserved0000PUBRELReserved0010PUBCOMPReserved0000SUBSCRIBEReserved0010SUBACKReserved0000UNSUBSCRIBEReserved0010UNSUBACKReserved0000PINGREQReserved0000PINGRESPReserved0000 DISCONNECTReserved0000AUTHReserved0000 DUP = PUBLISH 报文的重复分发标志 QoS = PUBLISH 报文的服务质量等级 RETAIN = PUBLISH 报文的保留标志 PUBLISH 报文中的 DUP 、QoS 和 RETAIN 标志的描述见3.3.1节。 2.1.4 剩余长度 位置: 从第 2 个字节开始。 剩余长度(Remaining Length)是一个变长字节整数,用来表示当前控制报文剩余部分的字节数,包括可 变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。 MQTT 控制报文总长度等于 固定报头的长度加上剩余长度。 2.2 可变报头 某些 MQTT 控制报文包含一个可变报头部分。它在固定报头和有效载荷之间。可变报头的内容根据报文类 型的不同而不同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。 2.2.1 报文标识符 部分类型 MQTT 控制报文的可变报头部分包含了 2 个字节的报文标识符字段。这些 MQTT 控制报文类型为: PUBLISH 报文(当 QoS>0 时), PUBACK ,PUBREC ,PUBREC ,PUBREL ,PUBCOMP, SUBSCRIBE ,SUBACK ,UNSUBSCRIBE ,UNSUBACK。 需要报文标识符的 MQTT 控制报文如下表所示。 表 2-3 - 包含报文标识符的 MQTT 控制报文 MQTT 控制报文报文标识符字段CONNECT不需要CONNACK不需要PUBLISH需要(如果 QoS > 0)PUBACK需要PUBREC需要PUBREL需要PUBCOMP需要 SUBSCRIBE需要SUBACK需要UNSUBSCRIBE需要UNSUBACK需要PINGREQ不需要PINGRESP不需要DISCONNECT不需要AUTH不需要 QoS 设置为 0 的 PUBLISH 报文不能包含报文标识符[MQTT-2.2.1-2]。 客户端每次发送一个新的 SUBSCRIBE ,UNSUBSCRIBE 或者 PUBLISH(当 QoS>0 时) MQTT 控制报文 时都必须分配一个当前未使用的非零报文标识符 [MQTT-2.2.1-3]。 服务端每次发送一个新的 PUBLISH(当 QoS>0)MQTT 控制报文时都必须分配一个当前未使用的非零报 文标识符 [MQTT-2.2.1-4]。 当客户端处理完这个报文对应的确认后,这个报文标识符就释放可重用。QoS 1 的 PUBLISH 对应的是 PUBACK ,QoS 2 的 PUBLISH 对应的是包含原因码 128 以上的 PUBCOMP 或 PUBREC,与 SUBSCRIBE 或 UNSUBSCRIBE 对应的分别是 SUBACK 或 UNSUBACK。 PUBLISH ,SUBSCRIBE 和 UNSUBSCRIBE 的报文标识符,在一次会话中对于客户端和服务端来说分属 于不同的组。 某个报文标识符在某一时刻不能被多个命令所使用。 PUBACK ,PUBREC 和 PUBREL 报文必须包含与最初发送的 PUBLISH 报文相同的报文标识符 [MQTT- 2.2.1-5] 。类似地, SUBACK 和 UNSUBACK 必须包含在对应的 SUBSCRIBE 和 UNSUBSCRIBE 报文中使 用的报文标识符 [MQTT-2.2.1-6]。 客户端和服务端彼此独立地分配报文标识符。因此,客户端服务端组合使用相同的报文标识符可以实现并 发的消息交换。 非规范评注 客户端发送标识符为 0x1234 的 PUBLISH 报文,它有可能会在收到那个报文的 PUBACK 之前,先 收到服务端发送的另一个不同的但是报文标识符也为 0x1234 的 PUBLISH 报文。 2.2.2 属性 CONNECT ,CONNACK ,PUBLISH ,PUBACK ,PUBREC ,PUBREL ,PUBCOMP ,SUBSCRIBE, SUBACK ,UNSUBACK ,DISCONNECT 和 AUTH 报文可变报头的最后一部分是一组属性。CONNECT 报文的遗嘱(Will)属性字段中也包含了一组可选的属性。 属性字段由属性长度和所有属性组成。 2.2.2.1 属性长度 属性长度被编码为变长字节整数。属性长度不包含用于编码属性长度自身的字节数,但包含所有属性的长 度。 如果没有任何属性,必须由属性长度为零的字段来指示 [MQTT-2.2.2- 1]。 2.2.2.2 属性 一个属性包含一段数据和一个定义了属性用途和数据类型的标识符。 标识符被编码为变长字节整数。任何  控制报文,如果包含了:对于该报文类型无效的标识符,或者错误类型的数据,都是无效报文。收到无效  报文时, 服务端或客户端使用包含原因码 0x81(无效报文) CONNACK 或 DISCONNECT 报文进行错误处 理,如4.13节所述。 标识符排序不分先后。 表 2-4 - 属性 标识符属性名 (用途)数据类型报文/遗嘱属性DecHex10x01载荷格式说明字节PUBLISH, Will Properties20x02消息过期时间四字节整数PUBLISH, Will Properties30x03内容类型UTF-8 编码字符串PUBLISH, Will Properties80x08响应主题UTF-8 编码字符串PUBLISH, Will Properties90x09相关数据二进制数据PUBLISH, Will Properties110x0B定义标识符变长字节整数PUBLISH, SUBSCRIBE170x11会话过期间隔四字节整数CONNECT, CONNACK, DISCONNECT180x12分配客户标识符UTF-8 编码字符串CONNACK190x13服务端保活时间双字节整数CONNACK210x15认证方法UTF-8 编码字符串CONNECT, CONNACK, AUTH220x16认证数据二进制数据CONNECT, CONNACK, AUTH230x17请求问题信息字节CONNECT240x18遗嘱延时间隔四字节整数Will Properties250x19请求响应信息字节CONNECT 260x1A请求信息UTF-8 编码字符串CONNACK280x1C服务端参考UTF-8 编码字符串CONNACK, DISCONNECT310x1F原因字符串UTF-8 编码字符串CONNACK, PUBACK, PUBREC,PUBREL, PUBCOMP, SUBACK,UNSUBACK, DISCONNECT, AUTH330x21接收最大数量双字节整数CONNECT, CONNACK340x22主题别名最大长度双字节整数CONNECT, CONNACK350x23主题别名双字节整数PUBLISH360x24最大 QoS字节CONNACK370x25保留属性可用性字节CONNACK380x26用户属性UTF-8 字符串对CONNECT, CONNACK, PUBLISH, WillProperties, PUBACK, PUBREC,PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE,UNSUBACK, DISCONNECT, AUTH390x27最大报文长度四字节整数CONNECT, CONNACK400x28通配符订阅可用性字节CONNACK410x29订阅标识符可用性字节CONNACK420x2A共享订阅可用性字节CONNACK 非规范评注 尽管属性标识符用变长字节整数来表示,但在此版本协议中,所有的标识符均由一个字节来表示。 2.3 有效载荷 某些 MQTT 控制报文在报文的最后部分包含一个有效载荷,这将在第三章论述。对于 PUBLISH 来说有效 载荷就是应用消息。 表 2-5 - 包含有效载荷的 MQTT 控制报文 MQTT 控制报文有效载荷CONNECT需要CONNACK不需要PUBLISH可选PUBACK不需要PUBREC不需要 PUBREL不需要PUBCOMP不需要SUBSCRIBE需要SUBACK需要UNSUBSCRIBE需要UNSUBACK需要PINGREQ不需要PINGRESP不需要DISCONNECT不需要AUTH不需要 2.4 原因码 原因码是一个单字节无符号数,用来指示一次操作的结果。小于 0x80 的原因码指示某次操作成功完成, 通 常用 0 来表示。大于等于 0x80 的原因码用来指示操作失败。 CONNACK ,PUBACK ,PUBREC ,PUBREL ,PUBCOMP ,DISCONNECT 和 AUTH 控制报文的可变报 头有一个单字节的原因码。 SUBACK 和 UNSUBACK 报文的载荷字段包含一个或多个原因码。 原因码如下表所示。 表 2-6 - 原因码 原因码名称报文DecimalHex00x00成功CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH00x00正常断开DISCONNECT00x00授权的 QoS 0SUBACK10x01授权的 QoS 1SUBACK20x02授权的 QoS 2SUBACK40x04包含遗嘱的断开DISCONNECT160x10无匹配订阅PUBACK, PUBREC170x11订阅不存在UNSUBACK240x18继续认证AUTH 250x19重新认证AUTH1280x80未指明的错误CONNACK, PUBACK, PUBREC, SUBACK,UNSUBACK, DISCONNECT1290x81无效报文CONNACK, DISCONNECT1300x82协议错误CONNACK, DISCONNECT1310x83实现错误CONNACK, PUBACK, PUBREC, SUBACK,UNSUBACK, DISCONNECT1320x84协议版本不支持CONNACK1330x85客户标识符无效CONNACK1340x86用户名密码错误CONNACK1350x87未授权CONNACK, PUBACK, PUBREC, SUBACK,UNSUBACK, DISCONNECT1360x88服务端不可用CONNACK1370x89服务端正忙CONNACK, DISCONNECT1380x8A禁止CONNACK1390x8B服务端关闭中DISCONNECT1400x8C无效的认证方法CONNACK, DISCONNECT1410x8D保活超时DISCONNECT1420x8E会话被接管DISCONNECT1430x8F主题过滤器无效SUBACK, UNSUBACK, DISCONNECT1440x90主题名无效CONNACK, PUBACK, PUBREC, DISCONNECT1450x91报文标识符已被占用PUBACK, PUBREC, SUBACK, UNSUBACK1460x92报文标识符无效PUBREL, PUBCOMP1470x93接收超出最大数量DISCONNECT1480x94主题别名无效DISCONNECT1490x95报文过长CONNACK, DISCONNECT1500x96消息太过频繁DISCONNECT1510x97超出配额CONNACK, PUBACK, PUBREC, SUBACK,DISCONNECT1520x98管理行为DISCONNECT1530x99载荷格式无效CONNACK, PUBACK, PUBREC, DISCONNECT1540x9A不支持保留CONNACK, DISCONNECT 1550x9B不支持的 QoS 等级CONNACK, DISCONNECT1560x9C(临时) 使用其他服务端CONNACK, DISCONNECT1570x9D服务端已 (永久)移动CONNACK, DISCONNECT1580x9E不支持共享订阅SUBACK, DISCONNECT1590x9F超出连接速率限制CONNACK, DISCONNECT1600xA0最大连接时间DISCONNECT1610xA1不支持订阅标识符SUBACK, DISCONNECT1620xA2不支持通配符订阅SUBACK, DISCONNECT 非规范评注 对于原因码 0x91 (报文标识符已被占用) 的处理可以为尝试修复会话、以新会话标志为 1 重置会 话或者判定客户端或服务端实现有缺陷。 3  MQTT 控制报文 3.1 CONNECT – 连接请求 客户端到服务端的网络连接建立后, 客户端发给服务端的第一个报文必须是 CONNECT 报文 [MQTT-3.1.0- 1]。 在一个网络连接上,客户端只能发送一次 CONNECT 报文。服务端必须将客户端发送的第二个 CONNECT 报文当作协议违规处理并断开客户端的连接[MQTT-3.1.0-2]. 有关错误处理的信息请查看4.13节。 有效载荷包含一个或多个编码的字段。包括客户端的唯一标识符,Will 主题, Will 消息,用户名和密码。除 了客户端标识之外,其它的字段都是可选的,基于标志位来决定可变报头中是否需要包含这些字段。 3.1.1 CONNECT 固定报头 图 3- 1 - CONNECT 报文固定报头 Bit76543210byte 1MQTT 报文类型 (1)保留位 00010000byte 2 …剩余长度值 剩余长度字段 剩余长度等于可变报头的长度加上有效载荷的长度。编码方式为变长字节整数。 3.1.2 CONNECT 可变报头 CONNECT 报文的可变报头按下列次序包含四个字段: 协议名(Protocol Name) ,协议级别(Protocol  Level),连接标志(Connect Flags) ,保持连接(Keep Alive)和属性(Properties)。2.2.2节描述了 属性(Properties)编码规则。 3.1.2.1 协议名 图 3-2 - 协议名字节  说明76543210协议名byte 1长度 MSB (0)00000000 byte 2长度 LSB (4)00000100byte 3‘M’01001101byte 4‘Q’01010001byte 5‘T’01010100byte 6‘T’01010100 协议名是表示协议名 MQTT 的 UTF-8 编码的字符串。 MQTT 规范的后续版本不会改变这个字符串的偏移和 长度。 支持多种协议的服务端使用协议名字段判断数据是否为 MQTT 报文。协议名必须是 UTF-8 字符串“MQTT”。 如果服务端不愿意接受 CONNECT 但希望表明其 MQTT 服务端身份, 可以发送包含原因码为 0x84 (不支 持的协议版本) 的 CONNACK 报文, 然后必须关闭网络连接 [MQTT-3.1.2- 1]。 非规范评注 数据包检测工具,例如防火墙,可以使用协议名来识别 MQTT 流量。 3.1.2.2 协议版本 图 3-3 - 协议版本字节  说明76543210协议级别byte 7版本(5)00000101 客户端使用一个字节无符号数表示协议修订级别。 MQTT v5.0 的协议版本字段为 5(0x05)。 支持多版本 MQTT 协议的服务端使用协议版本字段判定客户端正使用的 MQTT 协议版本。如果协议版本 不是 5 且服务端不愿意接受此 CONNECT 报文,可以发送包含原因码 0x84(不支持的协议版本)的 CONNACK 报文,然后必须关闭网络连接 [MQTT-3.1.2-2]。 3.1.2.3 连接标志 连接标志字节包含一些用于指定 MQTT 连接行为的参数。它还指出有效载荷中的字段是否存在。 图 3-4 - 连接标志位 Bit76543210 User Name FlagPassword FlagWill RetainWill QoSWill FlagCleanStartReservedbyte 8XXXXXXX0 服务端必须验证 CONNECT 报文的保留标志位(第 0 位)是否为 0 [MQTT-3.1.2-3],如果不为 0 则此报文 为无效报文。4.13节给出了错误处理信息。 3.1.2.4 新开始 位置: 连接标志字节的第 1 位 这个二进制位表明此次连接是一个新的会话还是一个已存在的会话的延续。4.1节定义了会话状态。 如果收到新开始(Clean Start)为 1 的 CONNECT 报文,客户端和服务端必须丢弃任何已存在的会话, 并 开始一个新的会话 [MQTT-3.1.2-4]。相应的, CONNACK 报文中的会话存在标志设置为 0。 6]。 3.1.2.5 遗嘱标志 位置: 连接标志字节的第 2 位 如果遗嘱标志(Will Flag)被设置为 1,表示遗嘱消息必须已存储在服务端与此客户标识符相关的会话中 [MQTT-3.1.2-7]。遗嘱消息(Will Message)包含遗嘱属性,遗嘱主题和遗嘱载荷字段。 遗嘱必须在网络连 接被关闭、遗嘱延时间隔到期或者会话结束之后被发布,除非服务端收到包含原因码为 0x00 (正常关闭)  的 DISCONNECT 报文之后删除了遗嘱消息(Will Message) ,或者一个关于此客户标识符的新的网络连  接在遗嘱迟发时间(Will Delay Interval)超时之前被创建 [MQTT-3.1.2-8]。 遗嘱发布的条件,包括但不限于: .     服务端检测到了一个 I/O 错误或者网络故障 .     客户端在保持连接(Keep Alive)的时间内未能通讯 .     客户端在没有发送包含原因码 0x00(正常关闭)的情况下关闭了网络连接 .     服务端在没有收到包含原因码 0x00(正常关闭)的情况下关闭了网络连接 如果遗嘱标志(Will Flag)被设置为 1 ,遗嘱属性(Will Property)、遗嘱主题(Will Topic)和遗嘱载荷   (Will Payload)字段必须存在于报文有效载荷中 [MQTT-3.1.2-9] 。一旦遗嘱消息(Will Message)被发布 或者服务端收到包含原因码为 0x00(正常关闭)的 DISCONNECT 报文,遗嘱消息(Will Message)必须 从服务端的会话中删除 [MQTT-3.1.2- 10]。 服务端应该在网络连接断开并且遗嘱迟发时间(Will Delay Interval)到期, 或者会话结束之后立即发布遗 嘱消息。服务端关闭或出错的情况下,可以在服务重新启动之后发布遗嘱消息(Will Message)。这种情 况下从服务端出错到遗嘱发布之间存在一定的延迟。 关于遗嘱延时间隔(Will Delay Interval)的详细信息, 请参考3.1.3.2节。 非规范评注 通过设置晚于会话过期间隔(Session Expiry Interval)的遗嘱迟发时间(Will Delay Interval)并发 送包含原因码 0x04(包含遗嘱的断开连接),客户端得以发出会话过期(Session Expiry)通告。 3.1.2.6 遗嘱 QoS 位置: 连接标志字节的第 3 、4 位 这两个比特指定了发布遗嘱消息(Will Message)时的服务质量(QoS)。 如果遗嘱标志(Will Flag)设置为 0,遗嘱服务质量(Will QoS)必须也设置为 0(0x00) [MQTT-3.1.2- 11]。 如果遗嘱标志设置为 1,遗嘱服务质量可以被设置为 0(0x00), 1(0x01)或 2(0x02) [MQTT-3.1.2- 12] 。设置为 3(0x03)的报文是无效报文。4.13节描述了错误处理信息。 3.1.2.7 遗嘱保留 位置: 连接标志字节的第 5 位 此位指定遗嘱消息(Will Message)在发布时是否会被保留。 如果遗嘱标志被设置为 0,遗嘱保留(Will Retain)标志也必须设置为 0 [MQTT-3.1.2- 13] 。如果遗嘱标志    被设置为 1 时,如果遗嘱保留被设置为 0,则服务端必须将遗嘱消息当做非保留消息发布 [MQTT-3.1.2- 14]。 如果遗嘱保留被设置为 1 ,则服务端必须将遗嘱消息当做保留消息发布 [MQTT-3.1.2- 15]。 3.1.2.8 用户名标志 位置: 连接标志字节的第 7 位 如果用户名标志(User Name Flag)被设置为 0,有效载荷中不能包含用户名字段 [MQTT-3.1.2- 16] 。如果 用户名标志被设置为 0,有效载荷中必须包含用户名字段 [MQTT-3.1.2- 17]。 3.1.2.9 密码标志 位置: 连接标志字节的第 6 位 如果密码标志(Password Flag)被设置为 0,有效载荷中不能包含密码字段 [MQTT-3.1.2- 18] 。如果密码 标志被设置为 1,有效载荷中必须包含密码字段 [MQTT-3.1.2- 19]。 非规范评注 相比 MQTT v3.1.1,此版本协议允许在没有用户名的情况下发送密码。这表明密码除了作为口令之 外还可以有其他用途。 3.1.2.10 保持连接 图 3-5 - 保持连接字节 Bit76543210byte 9保持连接 Keep Alive MSBbyte 10保持连接 Keep Alive LSB 保持连接(Keep Alive)使用双字节整数来表示以秒为单位的时间间隔。它是指在客户端传输完成一个 MQTT 控制报文的时刻到发送下一个报文的时刻, 两者之间允许空闲的最大时间间隔。客户端负责保证控 制报文发送的时间间隔不超过保持连接的值。如果没有任何其它的 MQTT 控制报文可以发送,客户端必须 发送一个 PINGREQ 报文 [MQTT-3.1.2-20]。 如果服务端返回的 CONNACK 报文中包含服务端保持连接(Server Keep Alive) ,客户端必须使用此值代 替其发送的保持连接(Keep Alive) [MQTT-3.1.2-21]。 不管保持连接的值是多少, 客户端任何时候都可以发送 PINGREQ 报文,并且使用 PINGRESP 报文判断网 络和服务端的活动状态。 如果保持连接的值非零,并且服务端在 1.5 倍的保持连接时间内没有收到客户端的控制报文,它必须断开 客户端的网络连接,并判定网络连接已断开 [MQTT-3.1.2-22]。 客户端发送了 PINGREQ 报文之后, 如果在合理的时间内仍没有收到 PINGRESP 报文,它应该关闭到服务 端的网络连接。 保持连接(Keep Alive)值为零的结果是关闭保持连接(Keep Alive)机制。如果保持连接(Keep Alive) 值为零, 客户端不必按照任何特定的时间发送 MQTT 控制报文。 非规范评注 服务端可能因为其他原因断开客户端连接,比如服务端将要关闭服务。设置保持连接(Keep Alive) 不保证客户端将一直保持连接状态。 非规范评注 保持连接的实际值是由应用指定的, 一般是几分钟。允许的最大值是 18 小时 12 分 15 秒。 3.1.2.11 CONNECT 属性 3.1.2.11.1 属性长度 CONNECT 报文可变报头中的属性(Properties)长度被编码为变长字节整数。 3.1.2.11.2 会话过期间隔 17 (0x11) ,会话过期间隔(Session Expiry Interval)标识符。 跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话 过期间隔(Session Expiry Interval)将造成协议错误(Protocol Error)。 如果会话过期间隔(Session Expiry Interval)值未指定,则使用 0。如果设置为 0 或者未指定,会话将在 网络连接(Network Connection)关闭时结束。 如果会话过期间隔(Session Expiry Interval)为 0xFFFFFFFF (UINT_MAX),则会话永不过期。 如果网络连接关闭时会话过期间隔(Session Expiry Interval)大于 0,则客户端与服务端必须存储会话状 态 [MQTT-3.1.2-23]。 非规范评注 客户端或服务端可能会因为中断运行导致会话时钟某些时间未运行。这将导致会话的删除被延迟。 更多关于会话的信息参考4.1节。关于会话存储的状态的详细和限制参考4.1.1节。 当会话过期时, 客户端和服务端无需以原子操作的方式删除会话状态。 非规范评注 把新开始(Clean Start)设置为 1 且会话过期间隔(Session Expiry Interval)设置为 0,等同于在   MQTT v3.1.1 中把清理会话(CleanSession)设置为 1。把新开始(Clean Start)设置为 0 且不设   置会话过期间隔(Session  Expiry  Interval), 等同于在 MQTT v3.1.1 中把清理会话标志设置为 0。 非规范评注 当希望只处理连接上服务端之后才发布的消息,客户端应该把新开始(Clean Start)设置为 1 且会 话过期间隔(Session Expiry Interval)设置为 0,这样客户端就不会收到它连接之前被服务端所发 布的消息,并且需要每次连接上服务端时重新订阅其感兴趣的主题。 非规范评注 某些客户端使用的网络可能只能提供断断续续的连接, 这种客户端可以使用较短的会话过期间隔 (Session Expiry Interval)以便在网络再次可用后重新连接到服务端时获得持续的消息交付。如果 客户端不再重新连接, 且允许会话过期,应用消息将会丢失。 非规范评注 某个客户端设置较长的会话过期间隔(Session Expiry Interval)或设置会话不过期,即要求服务端 为其保持会话到其下一次连接上服务端之后。只有打算在一段时间之后将会重连服务端时, 客户端 才应该设置较长的会话过期间隔(Session Expiry Interval)。当客户端认定其将来不会使用本次会 话时,应该在断开时把会话过期间隔(Session Expiry Interval)设置为 0。 非规范评注 客户端应当使用 CONNACK 报文中的会话存在(Session Present)来判定服务端是否存储了其会 话。 非规范评注 客户端应当以服务端返回的会话存在(Session Present)标志来判定会话是否已过期,而不是客  户端自己实现的会话过期状态。如果客户端自己实现会话过期状态,则需要将会话应当被删除的时 间作为会话状态的一部分而存储。 3.1.2.11.3 接收最大值 33 (0x21) ,接收最大值(Receive Maximum)标识符。 跟随其后的是由双字节整数表示的最大接收值。包含多个接收最大值或接收最大值为 0 将造成协议错误 (Protocol Error)。 客户端使用此值限制客户端愿意同时处理的 QoS 等级 1 和 QoS 等级 2 的发布消息最大数量。没有机制可 以限制服务端试图发送的 QoS 为 0 的发布消息。 接收最大值只将被应用在当前网络连接。如果没有设置最大接收值,将使用默认值 65535。 关于接收最大值的详细使用,参考4.9节流控。 3.1.2.11.4 最大报文长度 39 (0x27),最大报文长度(Maximum Packet Size)标识符。 跟随其后的是由四字节整数表示的客户端愿意接收的最大报文长度(Maximum Packet Size) ,如果没有 设置最大报文长度(Maximum Packet Size) ,则按照协议由固定报头中的剩余长度可编码最大值和协议 报头对数据包的大小做限制。 包含多个最大报文长度(Maximum Packet Size)或者最大报文长度(Maximum Packet Size)值为 0 将 造成协议错误。 非规范评注 客户端如果选择了限制最大报文长度,应该为最大报文长度设置一个合理的值。 如2.1.4节所述, 最大报文长度是 MQTT 控制报文的总长度。客户端使用最大报文长度通知服务端其所能 处理的单个报文长度限制。 服务端不能发送超过最大报文长度(Maximum Packet Size)的报文给客户端 [MQTT-3.1.2-24]。收到长度 超过限制的报文将导致协议错误,客户端发送包含原因码 0x95(报文过大)的 DISCONNECT 报文给服务 端,详见4.13节。 当报文过大而不能发送时, 服务端必须丢弃这些报文,然后当做应用消息发送已完成处理 [MQTT-3.1.2-25]。 共享订阅的情况下,如果一条消息对于部分客户端来说太长而不能发送,服务端可以选择丢弃此消息或者 把消息发送给剩余能够接收此消息的客户端。 非规范评注 服务端可以把那些没有发送就被丢弃的报文放在死信队列上, 或者执行其他诊断操作。具体的操 作超出了本规范的范围。 3.1.2.11.5 主题别名最大值 34 (0x22) ,主题别名最大值(Topic Alias Maximum)标识符。 跟随其后的是用双字节整数表示的主题别名最大值(Topic Alias Maximum)。包含多个主题别名最大值 (Topic Alias Maximum)将造成协议错误(Protocol Error)。没有设置主题别名最大值属性的情况下, 主 题别名最大值默认为零。 此值指示了客户端能够接收的来自服务端的主题别名(Topic Alias)最大数量。客户端使用此值来限制本 次连接可以拥有的主题别名的数量。 服务端在一个 PUBLISH 报文中发送的主题别名不能超过客户端设置的 主题别名最大值(Topic Alias Maximum) [MQTT-3.1.2-26]。值为零表示本次连接客户端不接受任何主题  别名(Topic Alias)。 如果主题别名最大值(Topic Alias)没有设置,或者设置为零,则服务端不能向此客 户端发送任何主题别名(Topic Alias) [MQTT-3.1.2-27]。 3.1.2.11.6 请求响应信息 25 (0x19) ,请求响应信息(Request Response Information)标识符。 跟随其后的是用一个字节表示的 0 或 1。包含多个请求响应信息(Request Response Information) ,或者 请求响应信息(Request Response Information)的值既不为 0 也不为 1 会造成协议错误(Protocol Error)。如果没有请求响应信息(Request Response Information),则请求响应默认值为 0。 客户端使用此值向服务端请求 CONNACK 报文中的响应信息(Response Information)。 值为 0,表示服 务端不能返回响应信息 [MQTT-3.1.2-28]。值为 1,表示服务端可以在 CONNACK 报文中返回响应信息。 非规范评注 即使客户端请求响应信息(Response Information), 服务端也可以选择不发送响应信息 (Response Information)。 更多关于请求/响应信息的内容,请参考4.10节。 3.1.2.11.7 请求问题信息 23 (0x17) ,请求问题信息(Request Problem Information)标识符。 跟随其后的是用一个字节表示的 0 或 1。包含多个请求问题信息(Request Problem Information),或者 请求问题信息(Request Problem  Information)的值既不为 0 也不为 1 会造成协议错误(Protocol Error)。 如果没有请求问题信息(Request Problem Information) ,则请求问题默认值为 1。 客户端使用此值指示遇到错误时是否发送原因字符串(Reason String)或用户属性(User Properties)。 如果请求问题信息的值为 0,服务端可以选择在 CONNACK 或 DISCONNECT 报文中返回原因字符串 (Reason String)或用户属性(User Properties),但不能在除 PUBLISH ,CONNACK 或 DISCONNECT 之外的报文中发送原因字符串(Reason String)或用户属性(User Properties) [MQTT-    3.1.2-29]。如果此值为 0 ,并且在除 PUBLISH ,CONNACK 或 DISCONNECT 之外的报文中收到了原因字 符串(Reason String)或用户属性(User Properties),客户端将发送一个包含原因码 0x82(协议错误) 的 DISCONNECT 报文给服务端,如4.13节所述。 如果此值为 1,服务端可以在任何被允许的报文中返回原因字符串(Reason String)或用户属性(User Properties)。 3.1.2.11.8 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。 用户属性(User Property)可以出现多次, 表示多个名字/值对。相同的名字可以出现多次。 非规范评注 CONNECT 报文中的用户属性可以被用来发送客户端到服务端的连接相关的属性。这些属性的意义 本规范不做定义。 3.1.2.11.9 认证方法 21 (0x15) ,认证方法(Authentication Method)标识符。 跟随其后的是一个 UTF-8 编码的字符串, 包含了扩展认证的认证方法(Authentication Method)名称。包 含多个认证方法将造成协议错误(协议错误)。 如果没有认证方法,则不进行扩展验证。参考4.12节。 如果客户端在 CONNECT 报文中设置了认证方法,则客户端在收到 CONNACK 报文之前不能发送除 AUTH 或 DISCONNECT 之外的报文 [MQTT-3.1.2-30]。 3.1.2.11.10 认证数据 22 (0x16) ,认证数据(Authentication Data)标识符。 跟随其后的是二进制的认证数据。没有认证方法却包含了认证数据(Authentication Data), 或者包含多个 认证数据(Authentication Data)将造成协议错误(Protocol Error)。 认证数据的内容由认证方法定义,关于扩展认证的更多信息,请参考4.12节。 3.1.2.12 可变报头非规范示例 图 3-6 - 可变报头示例  说明76543210协议名 Protocol Namebyte 1长度 Length MSB (0)00000000byte 2长度 Length LSB (4)00000100byte 3‘M’01001101byte 4‘Q’01010001byte 5‘T’01010100byte 6‘T’01010100协议版本 Protocol Version 说明76543210byte 7版本 Version (5)00000101连接标志 Connect Flags     byte 8用户名标志 User Name Flag (1)密码标志 Password Flag (1)遗嘱保留标志 Will Retain (0)遗嘱服务质量 Will QoS (01)遗嘱标志 Will Flag (1)新开始 Clean Start(1)保留Reserved (0)     1     1     0     0     1     1     1     0保持连接 Keep Alivebyte 9保持连接 Keep Alive MSB (0)00000000byte 10保持连接 Keep Alive LSB (10)00001010属性 Propertiesbyte 11长度 Length (5)00000101byte 12会话过期间隔标识符 (17)00010001byte 13会话过期间隔Session Expiry Interval (10)00000000byte 1400000000byte 1500000000 byte 16 00001010 3.1.3 CONNECT 载荷 CONNECT 报文的载荷中包含由可变报头(Variable Header)中的标志确定的一个或多个以长度为前缀的 字段。这些字段若存在,必须按照客户标识符(Client Identifier)、遗嘱属性(Will Properties) 、遗嘱主 题(Will Topic) 、遗嘱载荷(Will Payload)、用户名(User Name) 、密码(Password)的顺序出现 [MQTT-3.1.3- 1]。 3.1.3.1 客户标识符 服务端使用客户标识符(ClientID )识别客户端。连接服务端的每个客户端都有唯一的客户标识符 (ClientID)。 客户端和服务端都必须使用客户标识符(ClientID)识别两者之间的 MQTT 会话相关的状态 [MQTT-3.1.3-2]。更多关于会话状态的信息请参考4.1节。 客户标识符必须存在,且作为 CONNECT 报文载荷的第一个字段出现 [MQTT-3.1.3-3]。 客户标识符必须被编码为1.5.4节中所定义的 UTF-8 字符串 [MQTT-3.1.3-4]。 服务端必须允许 1 到 23 个字节长的 UTF-8 编码的客户标识符,客户标识符只能包含这些字符: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"  (大写字母、小写字母 和数字)  [MQTT-3.1.3-5]。 服务端可以允许编码后超过 23 个字节的客户标识符 (ClientID)。服务端可以允许包含不是上面列表字符的 客户标识符 (ClientID)。 服务端可以允许客户端提供一个零字节的客户标识符 (ClientID) ,如果这样做了, 服务端必须将这看作特殊 情况并分配唯一的客户标识符给那个客户端 [MQTT-3.1.3-6]。然后它必须假设客户端提供了那个唯一的客  户标识符,正常处理这个 CONNECT 报文 [MQTT-3.1.3-7]。 如果服务端拒绝了某个客户标识符(ClientID), 它可以发送包含原因码 0x85(客户标识符无效)的 CONNACK 报文作为对客户端的 CONNECT 报文的回应,如4.13节所述。之后必须关闭网络连接 [MQTT-3.1.3-8]。 非规范评注 客户端在实现时可以提供一个便于生成随机客户标识符的算法。使用此算法时,客户端需要注意避 免创建长期孤儿会话。 3.1.3.2 遗嘱属性 如果遗嘱标志(Will Flag)被设置为 1,有效载荷的下一个字段是遗嘱属性(Will Properties) 。遗嘱属性 字段定义了遗嘱消息(Will Message)将何时被发布, 以及被发布时的应用消息(Application Message) 属性。遗嘱属性包括属性长度和属性。 3.1.3.2.1 属性长度 遗嘱属性(Will Properties)中的属性长度被编码为可变长字节整数。 3.1.3.2.2 遗嘱延时间隔 24 (0x18) ,遗嘱延时间隔(Will Delay Interval)标识符。 跟随其后的是由四字节整数表示的以秒为单位的遗嘱延时间隔(Will Delay Interval)。包含多个遗嘱延时 间隔将造成协议错误(Protocol Error)。如果没有设置遗嘱延时间隔,遗嘱延时间隔默认值将为 0,即不 用延时发布遗嘱消息(Will Message)。 服务端将在遗嘱延时间隔(Will Delay Interval)到期或者会话(Session)结束时发布客户端的遗嘱消息  (Will Message) ,取决于两者谁先发生。 如果某个会话在遗嘱延时间隔到期之前创建了新的网络连接,  则服务端不能发送遗嘱消息 [MQTT-3.1.3-9]。 非规范评注 遗嘱时间间隔的一个用途是避免在频繁的网络连接临时断开时发布遗嘱消息, 因为客户端往往会很 快重新连上网络并继续之前的会话。 非规范评注 如果某个连接到服务端的网络连接使用已存在的客户标识符, 此已存在的网络连接的遗嘱消息将会 被发布, 除非新的网络连接设置了新开始(Clean Start)为 0 并且遗嘱延时大于 0。如果遗嘱延时 为 0,遗嘱消息将在网络连接断开时发布。如果新开始为 1,遗嘱消息也将被发布,因为此会话已 结束。 3.1.3.2.3 载荷格式指示 1 (0x01) ,载荷格式指示(Payload Format Indicator)标识符。 跟随载荷格式指示(Payload Format Indicator )之后的可能是: .     0 (0x00),表示遗嘱消息(Will Message)是未指定的字节,等同于不发送载荷格式指示。 .     1 (0x01),表示遗嘱消息(Will Message)是 UTF-8 编码的字符数据。载荷中的 UTF-8 数据必须 按照 Unicode规范[Unicode] 和 RFC 3629[RFC3629]中的申明进行编码。 包含多个载荷格式指示(Payload Format Indicator)将造成协议错误(Protocol Error)。服务端可以按照   格式指示对遗嘱消息(Will Message)进行验证,如果验证失败发送一条包含原因码 0x99(载荷格式无效) 的 CONNACK 报文。如4.13节所述。 3.1.3.2.4 消息过期间隔 2 (0x02) ,消息过期间隔(Message Expiry Interval)标识符。 跟随其后的是表示消息过期间隔(Message Expiry Interval)的四字节整数。包含多个消息过期间隔将导致 协议错误(Protocol Error)。 如果设定了消息过期间隔(Message Expiry Interval) ,四字节整数描述了遗嘱消息的生命周期(秒), 并 在服务端发布遗嘱消息时被当做发布过期间隔(Publication Expiry Interval)。 如果没有设定消息过期间隔,服务端发布遗嘱消息时将不发送消息过期间隔(Message Expiry Interval)。 3.1.3.2.5 内容类型 3 (0x03),内容类型(Content Type)标识符。 跟随其后的是一个以 UTF-8 格式编码的字符串,用来描述遗嘱消息(Will Message)的内容。包含多个内 容类型(Content Type)将造成协议错误(Protocol Error)。内容类型的值由发送应用程序和接收应用程 序确定。 3.1.3.2.6 响应主题 8 (0x08),响应主题(Response Topic)标识符。 跟随其后的是一个以 UTF-8 格式编码的字符串,用来表示响应消息的主题名(Topic Name)。包含多个响 应主题(Response Topic)将造成协议错误。响应主题的存在将遗嘱消息(Will Message)标识为一个请  求报文。 更多关于请求/响应的内容, 参考4.10 节。 3.1.3.2.7 对比数据 9 (0x09) ,对比数据(Correlation Data)标识符。 跟随其后的是二进制数据。对比数据被请求消息发送端在收到响应消息时用来标识相应的请求。包含多个  对比数据将造成协议错误(Protocol Error)。如果没有设置对比数据, 则请求方(Requester)不需要任何 对比数据。 对比数据只对请求消息(Request Message)的发送端和响应消息(Response Message)的接收端有意 义。 更多关于请求/响应的内容, 参考4.10节。 3.1.3.2.8 用户属性 38 (0x26),用户属性(User Property)标识符。 跟随其后的是一个 UTF-8 字符串对。用户属性(User Property)可以出现多次,表示多个名字/值对。相同 的名字可以出现多次。 服务端在发布遗嘱消息(Will Message)时必须维护用户属性(User Properties)的顺序 [MQTT-3.1.3- 10]。 非规范评注 此属性旨在提供一种传递应用层名称-值标签的方法, 其含义和解释仅由负责发送和接收它们的应 用程序所有。 3.1.3.3 遗嘱主题 如果遗嘱标志(Will Flag)被设置为 1,遗嘱主题(Will Topic)为载荷中下一个字段。 Topic)必须为 UTF-8 编码的字符串,如1.5.4节所定义 [MQTT-3.1.3- 11]。 遗嘱主题(Will 3.1.3.4 遗嘱载荷 如果遗嘱标志(Will Flag)被设置为 1,遗嘱载荷(Will Payload)为载荷中下一个字段。遗嘱载荷定义了 将要发布到遗嘱主题(Will Topic)的应用消息载荷,如3.1.2.5节所定义。此字段为二进制数据。 3.1.3.5 用户名 如果用户名标志(User Name Flag)被设置为 1,用户名(User Name)为载荷中下一个字段。用户名必 须是1.5.4节定义的 UTF-8 编码字符串 [MQTT-3.1.3- 12]。服务端可以将它用于身份验证和授权。 3.1.3.6 密码 如果密码标志(Password Flag)被设置为 1,密码(Password)为载荷中下一个字段。密码字段是二进 制数据, 尽管被称为密码, 但可以被用来承载任何认证信息。 3.1.4 CONNECT 行为 注意:服务端可以在同一个 TCP 端口或其他网络端点上支持多种协议(包括 MQTT 协议的早期版本)。 如果服务端确定协议是 MQTT v5.0,那么它按照下面的方法验证连接请求。 1.    网络连接建立后,如果服务端在合理的时间内没有收到 CONNECT 报文, 服务端应该关闭这个连 接。 2.   服务端必须按照3.1节的要求验证 CONNECT 报文, 如果报文不符合规范, 服务端关闭网络连接  [MQTT-3.1.4- 1] 。服务端可以在关闭网络连接之前发送包含3.1.2.4节所述的 0x80 及以上原因码的 CONNACK 报文。 3.   服务端可以检查 CONNECT  报文的内容是不是满足任何进一步的限制, 应该执行身份验证和授权  检查。如果任何一项检查没通过,服务端必须关闭网络连接 [MQTT-3.1.4-2]。在关闭网络连接之前, 服务端可以发送一个合适的包含如3.2节和4.13节所述的 0x80 及以上原因码的 CONNACK 报文。 如果验证成功, 服务端会执行下列步骤。 1.   如果客户标识符(ClientID)所代表的客户端已经连接到此服务端,那么向原有的客户端发送一个 包含原因码为 0x8E(会话被接管)的 DISCONNECT 报文,并且必须关闭原有的网络连接 [MQTT-3.1.4-3]。如果原有客户端存在遗嘱消息(Will Message),遗嘱消息按照3.1.2.5节所描 述的方式发布。 非规范评注 如果原有网络连接包含遗嘱消息, 且遗嘱延时间隔为 0,则遗嘱消息会在此网络连接被关闭时发送。 如果原有网络连接会话过期间隔为 0,或者新网络连接新开始标志设置为 1 且原有网络连接包含遗   嘱消息, 则遗嘱消息会被发送,因为原有会话已结束。 2.   服务端必须按照3.1.2.4节所描述的方式对新开始标志进行处理[MQTT-3.1.4-4]。 3.   服务端必须使用包含原因码为 0x00(成功)的 CONNACK 报文对客户端的 CONNECT 报文进行 确认 [MQTT-3.1.4-5]。 非规范评注 如果服务端被用来处理商业关键数据,推荐对网络连接进行认证和授权。如果认证和授权成功,服 务端可通过发送包含原因码为 0x00(成功)的 CONNACK 报文进行响应,否则建议服务端根本不 要发送 CONNACK 报文, 因为这是一种潜在的对 MQTT 服务端的攻击,可以被用来进行拒绝服务 攻击或密码猜测攻击。 4.   开始消息分发和保持连接状态监视。 允许客户端在发送 CONNECT 报文之后立即发送其它的 MQTT 控制报文; 客户端不需要等待服务端的 CONNACK 报文。 如果服务端拒绝了 CONNECT 报文,它不能处理客户端在 CONNECT 报文之后发送的 任何除 AUTH 以外的报文 [MQTT-3.1.4-6]。 非规范评注 客户端通常会等待 CONNACK 报文。然而, 如果在收到 CONNACK 报文之前就自由的发送其它 MQTT 控制报文将会简化客户端的实现,因为它不必监督连接的状态。如果连接被拒绝了, 客户端 在接收 CONNACK 报文之前发送的任何数据将不会被服务端所处理。 非规范评注 选择在收到 CONNACK 报文之前就发送 MQTT 控制报文的客户端将不知道服务端所存在的约束以及 会话是否被使用。 非规范评注 服务端在对某个客户端完成认证之前,可以选择限制读取该客户端的网络数据或者关闭该客户端的 网络连接。这是一种避免拒绝服务攻击的方法。 3.2 CONNACK – 确认连接请求 CONNACK 报文由服务端所发送,作为对来自客户端的 CONNECT 报文的响应。 服务端在发送任何除 AUTH 以外的报文之前必须先发送包含原因码为 0x00 (成功) 的 CONNACK 报文 [MQTT-3.2.0- 1] 。服务 端在一次网络连接中不能发送多个 CONNACK 报文 [MQTT-3.2.0-2]。 如果客户端在合理的时间内没有收到服务端的 CONNACK 报文, 客户端应该关闭网络连接。合理的时间取 决于应用的类型和通信基础设施。 3.2.1 CONNACK 固定报头 固定报头的格式见图 3-7 的描述。 图 3-7 – CONNACK 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (2)Reserved 保留位 00100000byte 2剩余长度 剩余长度字段 用变长字节整数来编码,表示可变报头的长度。 3.2.2 CONNACK 可变报头 CONNACK 报文的可变报头按顺序包含以下字段: 连接确认标志(Connect Acknowledge Flags) ,连接 原因码(Reason Code) ,属性(Properties) 。属性的编码规则如2.2.2节所描述。 3.2.2.1 连接确认标志 第 1 个字节是连接确认标志,位 7- 1 是保留位且必须设置为 0 [MQTT-3.2.2- 1] 。 第 0(SP)位是会话存在标志(Session Present Flag)。 3.2.2.1.1 会话存在 位置: 连接确认标志(Connect Acknowledge Flags)的第 0 位。 会话存在(Session Present)标志通知客户端, 服务端是否正在使用此客户标识符之前连接的会话状态 (Session State)。会话存在标志使服务端和客户端在是否有已存储的会话状态上保持一致。 如果服务端接受一个新开始(Clean Start)为 1 的连接,服务端在 CONNACK 报文中除了把原因码设置为 0x00(成功)之外,还必须把会话存在标志设置为 0 [MQTT-3.2.2-2]。 如果服务端接受一个新开始(Clean Start)为 0 的连接,并且服务端已经保存了此客户标识符(ClientID) 的会话状态(Session State),服务端在 CONNACK 报文中必须把会话存在标志设置为 1。否则,服务端 必须把会话存在标志设置为 0。无论如何, 服务端在 CONNACK 报文中必须把原因码设置为 0x00 (成功) [MQTT-3.2.2-3]。 如果客户端从服务端接收到的会话存在标志值与预期的不同,客户端做如下处理: .     如果客户端没有保存的会话状态,但收到会话存在标志为 1,客户端必须关闭网络连接 [MQTT-     3.2.2-4] 。 如果希望重新开始一个新的会话,客户端可以使用新开始(Clean Start)为 1 并重新连 接服务端。 .     如果客户端保存了会话状态,但收到的会话存在标志为 0,客户端若要继续此网络连接,它必须丢 弃其保存的会话状态 [MQTT-3.2.2-5]。 如果服务端发送的 CONNACK 报文中原因码非 0,它必须把会话存在标志设置为 0 [MQTT-3.2.2-6]。 3.2.2.2 连接原因码 可变报头中第 2 个字节是连接原因码(Reason Code)。 连接原因码(Reason Code)的值如下所示。如果服务端收到一个格式正确的 CONNECT 报文, 但服务端 无法完成连接的创建, 服务端可以发送一个包含适当的连接原因码的 CONNACK 报文。 如果服务端发送了 一个包含原因码大于等于 128 的 CONNACK 报文, 它随后必须关闭网络连接 [MQTT-3.2.2-7]。 表 3- 1 - 连接原因码 值16 进制原因码名称说明00x00成功连接被接受。1280x80未指明的错误服务端不愿透露的错误,或者没有适用的原因码。1290x81无效报文CONNECT 报文内容不能被正确的解析。1300x82协议错误CONNECT 报文内容不符合本规范。1310x83实现特定错误CONNECT 有效, 但不被服务端所接受。1320x84协议版本不支持服务端不支持客户端所请求的 MQTT 协议版本。1330x85客户标识符无效客户标识符有效,但未被服务端所接受。1340x86用户名密码错误客户端指定的用户名密码未被服务端所接受。1350x87未授权客户端未被授权连接。1360x88服务端不可用MQTT 服务端不可用。1370x89服务端正忙服务端正忙,请重试。1380x8A禁止客户端被禁止, 请联系服务端管理员。1400x8C无效的认证方法认证方法未被支持,或者不匹配当前使用的认证方法。1440x90主题名无效遗嘱主题格式正确,但未被服务端所接受。1490x95报文过长CONNECT 报文超过最大允许长度。1510x97超出配额已超出实现限制或管理限制。 1530x99载荷格式无效遗嘱载荷数据与载荷格式指示符不匹配。1540x9A不支持保留遗嘱保留标志被设置为 1,但服务端不支持保留消息。1550x9B不支持的 QoS 等级服务端不支持遗嘱中设置的 QoS 等级。1560x9C(临时) 使用其他服务端客户端应该临时使用其他服务端。1570x9D服务端已 (永久)移动客户端应该永久使用其他服务端1590x9F超出连接速率限制超出了所能接受的连接速率限制。 服务端发送的 CONNACK 报文必须设置一种原因码 [MQTT-3.2.2-8]。 非规范评注 原因码 0x80(未指明的错误)可以被用作:服务器知道失败的原因但是并不希望透露给客户端, 或者没有其他适用的原因码。 出于安全考虑, 发现 CONNECT 出错时服务端可以选择不发送 CONNACK 报文而关闭网络连接。 例如,在公网中向未被授权的网络连接告知自身 MQTT 服务端身份并不明智。 3.2.2.3 CONNACK 属性 3.2.2.3.1 属性长度 CONNACK 报文可变报头中的属性长度,编码为变长字节整数。 3.2.2.3.2 会话过期间隔 17 (0x11) ,会话过期间隔(Session Expiry Interval)标识符。 跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话 过期间隔(Session Expiry Interval)将造成协议错误(Protocol Error)。 如果会话过期间隔(Session Expiry Interval)值未指定,则使用 CONNECT 报文中指定的会话过期时间间 隔。服务端使用此属性通知客户端它使用的会话过期时间间隔与客户端在 CONNECT 中发送的值不同。更 详细的关于会话过期时间的描述,请参考3.1.2.11.2节 。 3.2.2.3.3 接收最大值 33 (0x21) ,接收最大值(Receive Maximum)描述符。 跟随其后的是由双字节整数表示的最大接收值。包含多个接收最大值或接收最大值为 0 将造成协议错误 (Protocol Error)。 服务端使用此值限制服务端愿意为该客户端同时处理的 QoS 为 1 和 QoS 为 2 的发布消息最大数量。没有 机制可以限制客户端试图发送的 QoS 为 0 的发布消息。 如果没有设置最大接收值, 将使用默认值 65535。 关于接收最大值的详细使用,参考4.9节流控部分。 3.2.2.3.4 最大服务质量 36 (0x24) ,最大服务质量(Maximum QoS)标识符。 跟随其后的是用一个字节表示的 0 或 1。包含多个最大服务质量(Maximum QoS)或最大服务质量既不为 0 也不为 1 将造成协议错误。如果没有设置最大服务质量,客户端可使用最大 QoS 为 2。 如果服务端不支持 Qos 为 1 或 2 的 PUBLISH 报文, 服务端必须在 CONNACK 报文中发送最大服务质量以 指定其支持的最大 QoS 值 [MQTT-3.2.2-9] 。即使不支持 QoS 为 1 或 2 的 PUBLISH 报文, 服务端也必须  接受请求 QoS 为 0 、1 或 2 的 SUBSCRIBE 报文 [MQTT-3.2.2- 10]。 如果从服务端接收到了最大 QoS 等级,则客户端不能发送超过最大 QoS 等级所指定的 QoS 等级的 PUBLISH 报文 [MQTT-3.2.2- 11]。服务端接收到超过其指定的最大服务质量的 PUBLISH 报文将造成协议 错误(Protocol Error)。 这种情况下应使用包含原因码为 0x9B(不支持的 QoS 等级)的 DISCONNECT 报文进行处理, 如4.13节所述。 如果服务端收到包含遗嘱的 QoS 超过服务端处理能力的 CONNECT 报文,服务端必须拒绝此连接。服务  端应该使用包含原因码为 0x9B(不支持的 QoS 等级)的 CONNACK 报文进行错误处理, 随后必须关闭网 络连接。 4.13节所述 [MQTT-3.2.2- 12]。 非规范评注 客户端不必支持 QoS 为 1 和 2 的 PUBLISH 报文。客户端只需将其发送的任何 SUBSCRIBE 报文 中的 QoS 字段限制在其支持的最大服务质量以内即可。 3.2.2.3.5 保留可用 37 (0x25) ,保留可用(Retain Available)标识符。 跟随其后的是一个单字节字段,用来声明服务端是否支持保留消息。值为 0 表示不支持保留消息, 为 1 表 示支持保留消息。如果没有设置保留可用字段,表示支持保留消息。包含多个保留可用字段或保留可用字 段值不为 0 也不为 1 将造成协议错误(Protocol Error)。 如果服务端收到一个包含保留标志位 1 的遗嘱消息的 CONNECT 报文且服务端不支持保留消息, 服务端必 须拒绝此连接请求, 且应该发送包含原因码为 0x9A(不支持保留)的 CONNACK 报文,随后必须关闭网 络连接 [MQTT-3.2.2- 13]。 从服务端接收到的保留可用标志为 0 时, 客户端不能发送保留标志设置为 1 的 PUBLISH 报文 [MQTT- 3.2.2- 14] 。如果服务端收到这种 PUBLISH 报文,将造成协议错误(Protocol Error),此时服务端应该发 送包含原因码为 0x9A (不支持保留)的 DISCONNECT 报文,如4.13节所述。 3.2.2.3.6 最大报文长度 39 (0x27) ,最大报文长度(Maximum Packet Size)标识符。 跟随其后的是由四字节整数表示的服务端愿意接收的最大报文长度(Maximum Packet Size)。如果没有 设置最大报文长度,则按照协议由固定报头中的剩余长度可编码最大值和协议报头对数据包的大小做限制。 包含多个最大报文长度(Maximum Packet Size) ,或最大报文长度为 0 将造成协议错误(Protocol Error)。 如2.1.4节所述, 最大报文长度是 MQTT 控制报文的总长度。服务端使用最大报文长度通知客户端其所能 处理的单个报文长度限制。 客户端不能发送超过最大报文长度(Maximum Packet Size)的报文给服务端 [MQTT-3.2.2- 15]。收到长度 超过限制的报文将导致协议错误,此时服务端应该发送包含原因码 0x95 (报文过长)的 DISCONNECT 报 文给客户端,详见4.13节。 3.2.2.3.7 分配客户标识符 18 (0x12) ,分配客户标识符(Assigned Client Identifier)标识符。 跟随其后的是 UTF-8 编码的分配客户标识符(Assigned Client Identifier)字符串。包含多个分配客户标识 符将造成协议错误(Protocol Error)。 服务端分配客户标识符的原因是 CONNECT 报文中的客户标识符长度为 0。 如果客户端使用长度为 0 的客户标识符(ClientID), 服务端必须回复包含分配客户标识符(Assigned Client Identifier)的 CONNACK 报文。分配客户标识符必须是没有被服务端的其他会话所使用的新客户标 识符 [MQTT-3.2.2- 16]。 3.2.2.3.8 主题别名最大值 34 (0x22) ,主题别名最大值(Topic Alias Maximum)标识符。 跟随其后的是用双字节整数表示的主题别名最大值(Topic Alias Maximum)。包含多个主题别名最大值 (Topic Alias Maximum)将造成协议错误(Protocol Error)。没有设置主题别名最大值属性的情况下, 主 题别名最大值默认为零。 此值指示了服务端能够接收的来自客户端的主题别名(Topic Alias)最大值。服务端使用此值来限制本次 连接可以拥有的主题别名的值。客户端在一个 PUBLISH 报文中发送的主题别名值不能超过服务端设置的主 题别名最大值(Topic Alias Maximum) [MQTT-3.2.2- 17]。值为 0 表示本次连接服务端不接受任何主题别  名(Topic Alias)。 如果主题别名最大值(Topic Alias)没有设置,或者设置为 0,则客户端不能向此服务 端发送任何主题别名(Topic Alias) [MQTT-3.2.2- 18]。 3.2.2.3.9 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。 如果加上原因字符串之后的 CONNACK 报文长度超出了客户端指 定的最大报文长度,则服务端不能发送此原因字符串 [MQTT-3.2.2- 19] 。包含多个原因字符串将造成协议错 误(Protocol Error)。 非规范评注 客户端对原因字符串的恰当使用包括:抛出异常时使用此字符串,或者将此字符串写入日志。 3.2.2.3.10 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户 属性之后的 CONNACK 报文长度超出了客户端指定的最大报文长度, 则服务端不能发送此属性 [MQTT- 3.2.2-20]。用户属性(User Property)允许出现多次,以表示多个名字/值对, 且相同的名字可以多次出现。 用户属性的内容和意义本规范不做定义。 CONNACK 报文的接收端可以选择忽略此属性。 3.2.2.3.11 通配符订阅可用 40 (0x28) ,通配符订阅可用(Wildcard Subscription Available)标识符。 跟随其后的是一个单字节字段,用来声明服务器是否支持通配符订阅(Wildcard Subscriptions)。值为 0 表示不支持通配符订阅,值为 1 表示支持通配符订阅。如果没有设置此值,则表示支持通配符订阅。包含 多个通配符订阅可用属性, 或通配符订阅可用属性值不为 0 也不为 1 将造成协议错误(Protocol Error)。 如果服务端在不支持通配符订阅(Wildcard Subscription)的情况下收到了包含通配符订阅的 SUBSCRIBE 报文,将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为 0xA2  (通配符订阅不支持) 的 DISCONNECT 报文, 如4.13节所述。 服务端在支持通配符订阅的情况下仍然可以拒绝特定的包含通配符订阅的订阅请求。这种情况下, 服务端 可以发送一个包含原因码为 0xA2(通配符订阅不支持) 的 SUBACK 报文。 3.2.2.3.12 订阅标识符可用 41 (0x29) ,订阅标识符可用(Subscription Identifier Available)标识符。 跟随其后的是一个单字节字段,用来声明服务端是否支持订阅标识符(Subscription Identifiers)。值为 0 表示不支持订阅标识符,值为 1 表示支持订阅标识符。如果没有设置此值,则表示支持订阅标识符。包含 多个订阅标识符可用属性, 或订阅标识符可用属性值不为 0 也不为 1 将造成协议错误(Protocol Error)。 如果服务端在不支持订阅标识符(Subscription Identifier)的情况下收到了包含订阅标识符的 SUBSCRIBE 报文,将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为 0xA1  (订阅标识符不支持) 的 DISCONNECT 报文, 如4.13节所述。 3.2.2.3.13 共享订阅可用 42 (0x2A) ,共享订阅可用(Shared Subscription Available)标识符。 跟随其后的是一个单字节字段,用来声明服务端是否支持共享订阅(Shared Subscription)。值为 0 表示 不支持共享订阅,值为 1 表示支持共享订阅。如果没有设置此值,则表示支持共享订阅。包含多个共享订 阅可用(Shared Subscription Available) ,或共享订阅可用属性值不为 0 也不为 1 将造成协议错误 (Protocol Error)。 如果服务端在不支持共享订阅(Shared Subscription)的情况下收到了包含共享订阅的 SUBSCRIBE 报文, 将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为 0x9E(共享订阅不支持)的 DISCONNECT 报文, 如4.13节所述。 3.2.2.3.14 服务端保持连接 19 (0x13) ,服务端保持连接(Server Keep Alive)标识符。 跟随其后的是由服务端分配的双字节整数表示的保持连接(Keep Alive)时间。 如果服务端发送了服务端保 持连接(Server Keep Alive)属性, 客户端必须使用此值代替其在 CONNECT 报文中发送的保持连接时间 值 [MQTT-3.2.2-21] 。如果服务端没有发送服务端保持连接属性,服务端必须使用客户端在 CONNECT 报 文中设置的保持连接时间值 [MQTT-3.2.2-22]。包含多个服务端保持连接属性将造成协议错误(Protocol Error)。 非规范评注 服务端保持连接属性的主要作用是通知客户端它将会比客户端指定的保持连接更快的断开非活动的 客户端。 3.2.2.3.15 响应信息 26 (0x1A) ,响应信息(Response Information)标识符。 跟随其后的是一个以 UTF-8 编码的字符串, 作为创建响应主题(Response Topic)的基本信息。关于客户 端如何根据响应信息(Response Information)创建响应主题不在本规范的定义范围内。包含多个响应信息 将造成协议错误(Protocol Error)。 如果客户端发送的请求响应信息(Request Response Information)值为 1,则服务端在 CONNACK 报文 中发送响应信息(Response Information)为可选项。 非规范评注 响应信息通常被用来传递主题订阅树的一个全局唯一分支,此分支至少在该客户端的会话生命周期 内为该客户端所保留。请求客户端和响应客户端的授权需要使用它,所以它通常不能仅仅是一个随 机字符串。一般把此分支作为特定客户端的订阅树根节点。 通常此信息需要正确配置,以使得服务 器能返回信息。使用此机制时,具体的信息一般由服务端来进行统一配置,而非由各个客户端自己 配置。 更多关于请求/响应的信息, 请参考4.10节 。 3.2.2.3.16 服务端参考 28 (0x1C) ,服务端参考(Server Reference)标识符。 跟随其后的是一个以 UTF-8 编码的字符串,可以被客户端用来标识其他可用的服务端。包含多个服务端参 考(Server Reference)将造成协议错误(Protocol Error)。 服务端在包含了原因码为 0x9C( (临时) 使用其他服务端)或 0x9D(服务端已(永久) 移动) 的 CONNACK 报文或 DISCONNECT 报文中设置服务端参考,如4.13节所述。 关于如何使用服务端参考, 请参考4.11节服务端重定向信息。 3.2.2.3.17 认证方法 21 (0x15) ,认证方法(Authentication Method)标识符。 跟随其后的是一个以 UTF-8 编码的字符串, 包含了认证方法(Authentication Method)名。包含多个认证 方法将造成协议错误(Protocol Error)。更多关于扩展认证的信息, 请参考4.12节 。 3.2.2.3.18 认证数据 22 (0x16) ,认证数据(Authentication Data)标识符。 跟随其后的是包含认证数据(Authentication Data)的二进制数据。此数据的内容由认证方法和已交换的认 证数据状态定义。包含多个认证数据将造成协议错误(Protocol Error)。更多关于扩展认证的信息,请参  考4.12节 。 3.2.3 CONNACK 载荷 CONNACK 报文没有有效载荷。 3.3 PUBLISH – 发布消息 PUBLISH 报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。 3.3.1 PUBLISH 固定报头 图 3-8 – PUBLISH 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (3)DUPQoS 等级RETAIN 0011XXXXbyte 2 …剩余长度 3.3.1.1 重发标志 位置: 第 1 个字节,第 3 位。 如果 DUP 标志被设置为 0,表示这是客户端或服务端第一次请求发送这个 PUBLISH 报文。如果 DUP 标志 被设置为 1,表示这可能是一个早前报文请求的重发。 客户端或服务端请求重发一个 PUBLISH 报文时,必须将 DUP 标志设置为 1 [MQTT-3.3.1- 1] 。对于 QoS 为 0 的消息, DUP 标志必须设置为 0 [MQTT-3.3.1-2]。 服务端发送 PUBLISH 报文给订阅者时,收到(入站) 的 PUBLISH 报文的 DUP 标志的值不会被传播。 发 送(出站)的 PUBLISH 报文与收到(入站)的 PUBLISH 报文中的 DUP 标志是独立设置的,它的值必须 单独的根据发送(出站)的 PUBLISH 报文是否是一个重发来确定 [MQTT-3.3.1-3]。 非规范评注 接收者收到一个 DUP 标志位 1 的 MQTT 控制报文时,不能假设它看到了一个这个报文之前的一个 副本。 非规范评注 需要特别指出的是, DUP 标志关注的是 MQTT 控制报文本身,与它包含的应用消息无关。当使用 QoS 1 时, 客户端可能会收到一个 DUP 标志为 0 的 PUBLISH 报文,这个报文包含一个它之前收  到过的应用消息的副本,但是用的是不同的报文标识符。2.2.1节提供了有关报文标识符的更多信 息。 3.3.1.2 服务质量等级 位置: 第 1 个字节,第 2- 1 位。 这个字段表示应用消息分发的服务质量(QoS)等级保证。服务质量等级在下表中列出。 表 3-2 - QoS 定义 QoS 值Bit 2Bit 1说明000最多分发一次101至少分发一次210仅分发一次-11保留 – 不能使用 如果服务端在对客户端响应的 CONNACK 报文中包含了最大服务质量(Maximum QoS)且服务端收到的 PUBLISH 报文的 QoS 大于此最大服务质量,服务端发送包含原因码为 0x9B (不支持的 QoS 等级)的 DISCONNECT 报文, 如4.13节所述。 PUBLISH 报文的 2 个 QoS 比特位不能同时设置为 1 [MQTT-3.3.1-4]。如果服务端或客户端收到 QoS 2 个 比特位都为 1 的无效 PUBLISH 报文, 使用包含原因码为 0x81(无效报文) 的 DISCONNECT 报文关闭网 络连接, 如4.13节所述。 3.3.1.3 保留标志 位置: 第 1 个字节,第 0 位。 如果客户端发给服务端的 PUBLISH 报文的保留(Retain)标志被设置为 1,服务端必须存储此应用消息,  并用其替换此话题下任何已存在的消息 [MQTT-3.3.1-5],以便它可以被分发给未来的匹配此主题名(Topic Name)的订阅者。 如果载荷为空, 消息可以正常被服务端所处理,但是此话题下的任何保留消息必须被丢 弃,并且此话题未来的订阅者将不会收到保留消息 [MQTT-3.3.1-6] 。载荷为空的保留消息将不能被存储在  服务端 [MQTT-3.3.1-7]。 如果客户端发给服务端的 PUBLISH 报文的保留标志位为 0,服务器不能把此消息存储为保留消息,也不能 丢弃或替换任何已存在的保留消息 [MQTT-3.3.1-8]。 如果服务端发送给客户端的 CONNACK 报文中包含保留可用属性,且属性值为 0,但收到的 PUBLISH 报 文中保留标志位为 1,服务端使用包含原因码为 0x9A  (保留不支持) 的 DISCONNECT 报文断开网络连接, 如4.13节所述。 当一个新的非共享订阅(Non-shared Subscription)被创建时, 每个匹配的话题下的最新保留消息如果存 在,将根据保留消息订阅选项(Retain Handling Subscription Option)发送给客户端。这些消息在发送时 保留标志被设置为 1。保留消息的发送由保留消息处理订阅选项控制, 收到订阅时: .     如果保留消息处理属性被设置为 0,服务端必须发送主题与客户端订阅的主题过滤器(Topic  Filter) 相匹配的所有保留消息 [MQTT-3.3.1-9]。 .     如果保留消息处理属性被设置为 1,如果尚不存在匹配的订阅, 服务端必须发送主题与客户端订阅 的主题过滤器相匹配的所有保留消息。如果已存在相匹配的订阅,服务器不能发送这些保留消息  [MQTT-3.3.1- 10]。 .     如果保留消息处理属性被设置为 2,服务器不能发送这些保留消息 [MQTT-3.3.1- 11]。 订阅选项(Subscription Options)的定义,参考3.8.3.1节 。 如果服务端收到保留标志设置为 1 且 QoS 设置为 0 的 PUBLISH 报文,服务端应该把此 QoS 为 0 的消息存 储为其主题下最新的保留消息,但服务端可以选择在任何时间丢弃此消息。如果发生丢弃, 该主题下将不  存在任何保留消息。 如果某个主题当前的保留消息过期, 该主题下将不存在任何保留消息。 服务端转发应用消息时,保留标志位的设置由发布保留(Retain As Published)订阅选项决定。订阅选项 的定义, 请参考3.8.3.1节 。 . . 如果发布保留(Retain As Published)订阅选项被设置为 0,服务端在转发应用消息时必须将保留标志 设置为 0,而不管收到的 PUBLISH 报文中保留标志位如何设置的 [MQTT-3.3.1- 12]。 如果发布保留(Retain As Published)订阅选项被设置为 1,服务端在转发应用消息时必须将保留标志 设置为与收到的 PUBLISH 消息中的保留标志位相同 [MQTT-3.3.1- 13]。 非规范评注 对于发布者不定期发送状态消息这个场景, 保留消息很有用。新的非共享订阅者将会收到最近的状态。 3.3.1.4 剩余长度 等于可变报头的长度加上有效载荷的长度, 被编码为变长字节整数。 3.3.2 PUBLISH 可变报头 PUBLISH 报文可变报头按顺序包含:主题名(Topic Name),报文标识符(Packet Identifier), 属性 (Properties)。属性的编码规则如2.2.2节所述。 3.3.2.1 主题名 主题名(Topic Name)用于识别有效载荷数据应该被发布到哪一个信息通道。 主题名必须是 PUBLISH 报文可变报头的第一个字段。它必须是1.5.4节定义的 UTF-8 编码的字符串 [MQTT-3.3.2- 1]。 PUBLISH 报文中的主题名不能包含通配符 [MQTT-3.3.2-2]。 服务端发送给订阅客户端的 PUBLISH 报文中的主题名必须匹配该订阅的主题过滤器(Topic Filter),  如 4.7节所定义的匹配过程 [MQTT-3.3.2-3]。然而, 由于服务端允许将主题名映射为其他名字,主题名可能 与原始 PUBLISH 报文中的主题名不同。 发送端可以使用主题别名(Topic Alias)以便减少 PUBLISH 报文的长度。主题别名如3.3.2.3.4节所述。 主题名长度为 0 且没有主题别名,将造成协议错误(Protocol Error)。 3.3.2.2 报文标识符 只有当 QoS 等级是 1 或 2 时,报文标识符(Packet Identifier)字段才能出现在 PUBLISH 报文中。2.2.1 节提供了有关报文标识符的更多信息。 3.3.2.3 PUBLISH 属性 3.3.2.3.1 属性长度 PUBLISH 报文可变报头中的属性长度被编码为变长字节整数。 3.3.2.3.2 载荷格式指示 1 (0x01) ,载荷格式指示(Payload Format Indicator)标识符。 跟随其后的是单字节的载荷格式指示值,可以是: .     0 (0x00),说明载荷是未指定格式的字节, 相当于没有发送载荷格式指示。 .     1 (0x01),说明载荷是 UTF-8 编码的字符数据。载荷中的 UTF-8 数据必须是按照 Unicode [Unicode] 的规范和 RFC 3629[RFC3629]的重申进行编码。 服务端必须把接收到的应用消息中的载荷格式指示原封不动的发给所有的订阅者 [MQTT-3.3.2-4]。接收者 可以验证载荷数据与所指示的格式一致,如果不一致, 发送包含原因码为 0x99(载荷格式无效) 的 PUBACK ,PUBREC 或 DISCONNECT 报文,如4.13节所述。 3.3.2.3.3 消息过期间隔 2 (0x02) ,消息过期间隔(Message Expiry Interval)标识符。 跟随其后的是四字节整数表示的消息过期间隔(Message Expiry Interval)。 如果消息过期间隔存在,四字节整数表示以秒为单位的应用消息(Application Message)生命周期。如果  消息过期间隔(Message Expiry Interval)已过期,服务端还没开始向匹配的订阅者交付该消息, 则服务端 必须删除该订阅者的消息副本 [MQTT-3.3.2-5]。 如果消息过期间隔不存在, 应用消息不会过期。 服务端发送给客户端的 PUBLISH 报文中必须包含消息过期间隔,值为接收时间减去消息在服务端的等待时 间 [MQTT-3.3.2-6]。关于状态存储的细节和限制, 参考4.1节。 3.3.2.3.4 主题别名 35 (0x23) ,主题别名(Topic Alias)标识符。 跟随其后的是表示主题别名(Topic Alias)值的双字节整数。包含多个主题别名值将造成协议错误 (Protocol Error)。 主题别名是一个整数, 用来代替主题名对主题进行识别。主题别名可以减小 PUBLISH 报文的长度, 这对某 个网络连接中发送的很长且反复使用的主题名来说很有用。 发送端决定是否使用主题别名及别名值如何选取。发送端通过在 PUBLISH 报文中包含的非 0 长度主题名和  主题别名来设置主题别名映射。接收端正常处理该 PUBLISH 报文,但同样将指定的主题别名映射到主题名。 如果接收端已经设置了某个主题别名映射, 发送端可以发送包含主题别名和长度为 0 的主题名的 PUBLISH 报文。接收端把此 PUBLISH 报文的主题名当做其包含的主题别名所映射的主题名。 发送端可以通过在同一个网络连接中发送另一个包含同样主题别名和不同非 0 长度主题名的 PUBLISH 报文 来修改主题别名映射关系。 主题别名映射仅作用于某个网络连接及其生命周期内。 接收端不能将任何主题别名映射从一个网络连接转 发到另一个网络连接 [MQTT-3.3.2-7]。 主题别名不允许为 0 。发送端不能发送包含主题别名值为 0 的 PUBLISH 报文 [MQTT-3.3.2-8]。 客户端不能发送主题别名值大于服务端的 CONNACK 报文中指定的主题别名最大值(Topic Alias    Maximum)的 PUBLISH 报文 [MQTT-3.3.2-9] 。客户端必须接受所有值大于 0 且小于等于其发送的 CONNECT 报文中的主题别名最大值的主题别名 [MQTT-3.3.2- 10]。 服务端不能发送包含主题别名值大于客户端在 CONNECT 报文中指定的主题别名最大值(Topic Alias Maximum)的 PUBLISH 报文 [MQTT-3.3.2- 11] 。服务端必须接受所有值大于 0 且小于等于其发送的  CONNACK 报文中的主题别名最大值的主题别名 [MQTT-3.3.2- 12]。 客户端和服务端使用的主题别名映射相互独立。因此一般来说, 客户端发送给服务端的主题别名值为 1 的 PUBLISH 报文和服务端发送给客户端的主题别名值为 1 的 PUBLISH 报文,将被映射到不同的主题。 3.3.2.3.5 响应主题 8 (0x08) ,响应主题(Response Topic)标识符。 跟随其后的是一个 UTF-8 编码的字符串, 用作响应消息的主题名。 响应主题必须是按照1.5.4 节 所定义的 UTF-8 编码的字符串 [MQTT-3.3.2- 13] 。响应主题不能包含通配符 [MQTT-3.3.2- 14]。包含多个响应主题将 造成协议错误(Protocol Error)。响应主题的存在将消息标识为请求报文。 更多关于请求/响应的信息, 参考4.10节 。 服务端在收到应用消息时必须将响应主题原封不动的发送给所有的订阅者 [MQTT-3.3.2- 15]。 非规范评注 包含响应主题的应用消息接收端使用响应主题作为主题名,发送作为响应消息的 PUBLISH 报文。 如果请求消息中包含对比数据,接收端应当在发送作为对此请求消息进行响应的 PUBLISH 报文中 包含此对比数据。 3.3.2.3.6 对比数据 9 (0x09) ,对比数据(Correlation Data)标识符。 跟随其后的是二进制数据。对比数据被请求消息发送端在收到响应消息时用来标识相应的请求。包含多个  对比数据将造成协议错误(Protocol Error)。如果没有设置对比数据, 则请求方(Requester)不需要任何 对比数据。 服务端在收到应用消息时必须原封不动的把对比数据发送给所有的订阅者 [MQTT-3.3.2- 16]。对比数据只对 请求消息(Request Message)的发送端和响应消息(Response Message)的接收端有意义。 非规范评注 接收端收到包含响应主题和对比数据的应用消息时,发送以响应主题为主题名的 PUBLISH 报文作   为响应消息。客户端在响应消息中应将对比数据作为 PUBLISH 报文的一部分原封不动的发送出去。 非规范评注 如果对客户端响应消息中的对比数据所做的任何更改会造成应用程序错误,则应当对对比数据进行 加密/哈希,以便接收端能检测到对比数据是否被更改。 更多关于请求/响应的信息, 请参考4.10节。 3.3.2.3.7 用户属性 38 (0x26) ,用户属性(User Property)。 跟随其后的是 UTF-8 字符串对。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同 的名字可以多次出现。 服务端在转发应用消息到客户端时必须原封不动的把所有的用户属性放在 PUBLISH 报文中 [MQTT-3.3.2- 17] 。服务端在转发应用消息时必须保持所有用户属性的先后顺序 [MQTT-3.3.2- 18]。 非规范评注 此属性旨在提供一种传递应用层名称-值标签的方法, 其含义和解释仅由负责发送和接收它们的应 用程序所有。 3.3.2.3.8 订阅标识符 11 (0x0B),订阅标识符(Subscription Identifier)标识符。 跟随其后的是一个变长字节整数表示的订阅标识符。 订阅标识符取值范围从 1 到 268,435,455。订阅标识符的值为 0 将造成协议错误。如果某条发布消息匹配 了多个订阅,则将包含多个订阅标识符。这种情况下他们的顺序并不重要。 3.3.2.3.9 内容类型 3 (0x03) , 内容类型(Content Type)标识符。 跟随其后的是一个以 UTF-8 格式编码的字符串,用来描述应用消息的内容。 内容类型必须是 UTF-8 编码的 字符串, 如1.5.4节所定义 [MQTT-3.3.2- 19]。 包含多个内容类型将造成协议错误(Protocol  Error)。 内容类型的值由发送应用程序和接收应用程序确定。 服务端必须把收到的应用消息中的内容类型原封不动的发送给所有的订阅者 [MQTT-3.3.2-20]。 非规范评注 UTF-8 编码字符串可以使用一个 MIME 内容类型字符串来描述应用消息的内容。由于发送程序和接 收程序负责内容类型字符串的定义和解释, 因此 MQTT 服务端只确保内容类型是有效的 UTF-8 编  码的字符串,不会做其他方面的验证。 非规范评注 图 3-9 是一个 PUBLISH 示例报文, 其中主题名为 a/b,报文标识符为 10,没有属性。 图 3-9 - PUBLISH 报文可变报头非规范示例  说明76543210主题名byte 1长度 MSB (0)00000000byte 2长度 LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010报文标识符byte 6报文标识符 MSB (0)00000000byte 7报文标识符 LSB (10)00001010属性长度byte 8无属性00000000 3.3.3 PUBLISH 载荷 载荷包含将被发布的应用消息。载荷的内容和格式由应用程序指定。有效载荷的长度这样计算:用固定报 头中的剩余长度字段的值减去可变报头的长度。包含零长度有效载荷的 PUBLISH 报文是合法的。 3.3.4 PUBLISH 行为 PUBLISH 报文的接收端必须按照 PUBLISH 报文中的 QoS 等级发送响应报文 [MQTT-3.3.4- 1]。 表 3-3 - PUBLISH 报文的预期响应 服务质量等级预期响应QoS 0无响应QoS 1PUBACK 报文QoS 2PUBREC 报文 客户端使用 PUBLISH 报文发送应用消息给服务端,目的是分发到其他订阅匹配的客户端。 服务端使用 PUBLISH 报文发送应用消息给每一个订阅匹配的客户端。 PUBLISH 报文包含 SUBSCRIBE 报 文中承载的订阅标识符--如果存在的话。 客户端使用带通配符的主题过滤器请求订阅时,客户端的订阅可能会重叠,因此发布的消息可能会匹配多 个主题过滤器。 这种情况下,服务端必须按照所有匹配的订阅中最大的 QoS 等级把消息发送给客户端 [MQTT-3.3.4-2]。此外,服务端可以为每一个匹配的订阅按照订阅时的 QoS 等级,把消息副本分发给客户 端。 如果客户端收到一个未经请求的应用消息(没有匹配任何订阅) ,且 QoS 大于客户端指定的最大服务质量 (Maximum QoS),客户端使用包含原因码为 0x9B(不支持的 QoS 等级)的 DISCONNECT 报文断开连 接,如4.13节所述。 如果客户端在这些重叠的订阅中指定了订阅标识符,服务端在发布这些订阅相匹配的消息时必须包含这些 订阅标识符 [MQTT-3.3.4-3] 。如果服务端对这些重叠的订阅只发送一条相匹配的消息,服务端必须在 PUBLISH 报文中包含所有的相匹配的订阅标识符(如果存在) ,但没有顺序要求 [MQTT-3.3.4-4] 。如果服 务端对这些重叠的订阅必须分别发送相匹配的消息,则每个 PUBLISH 报文中含与订阅相匹配的订阅标识符  (如果存在)  [MQTT-3.3.4-5]。 可能存在客户端对同一个发布消息做了多次订阅, 并且这些订阅中有多个订阅使用了相同的订阅标识符, 这种情况下 PUBLISH 报文将携带多个相同的订阅标识符。 PUBLISH 报文中若包含服务端收到的 SUBSCRIBE 报文以外的订阅标识符, 将造成协议错误(Protocol Error)。 从客户端发送给服务端的 PUBLISH 报文不能包含订阅标识符 [MQTT-3.3.4-6]。 对于共享订阅, 发送给某个客户端的 PUBLISH 报文中将只包含该客户端的 SUBSCRIBE 报文中发送的订 阅标识符。 收到 PUBLISH 报文时,接收端的行为取决于报文的 QoS 等级, 如4.3节所述。 如果 PUBLISH 报文包含主题别名, 接收端按照以下方式进行处理: 1)   主题别名为 0 或大于最大主题别名(Maximum Topic Alias), 将造成协议错误(Protocol Error), 接   收端使用包含原因码为 0x94(主题别名无效) 的 DISCONNECT 报文断开网络连接, 如4.13节所述。 2)   如果接收端已创建此主题别名的映射, a)   如果报文包含的主题名长度为 0,接收端使用主题别名对应的主题名处理此报文 b)   如果报文包含的主题名长度不为 0,接收端使用此主题名处理此报文, 并更新此主题别名映射到此 主题名 3)   如果接收端还没有创建此主题别名的映射, a)   如果报文包含的主题名长度为 0,将造成协议错误,接收端使用包含原因码为 0x82(协议错误) 的 DISCONNECT 报文断开网络连接,如4.13节所述。 b)   如果报文包含的主题名长度不为 0,接收端使用此主题名处理此报文, 并为此报文中的主题别名和 主题名创建映射关系 非规范评注 如果服务端向客户端分发应用消息时使用了不同的协议级别(比如 MQTT v3.1.1)-- 不支持属性或 本规范提供的其他功能,应用消息中的某些信息将丢失,依赖于这些信息的应用程序可能无法正常 工作。 客户端在收到服务端的 PUBACK ,PUBCOMP 或包含原因码大于等于 128 的 PUBREC 报文之前,不能发 送数量超过服务端的接收最大值(Receive Maximum)的 QoS 为 1 和 2 的 PUBLISH 报文 [MQTT-3.3.4-7]。 服务端在发送 PUBACK 或 PUBCOMP 响应之前, 如果收到数量超过客户端的接收最大值的 QoS 为 1 和 2     的 PUBLISH 报文, 服务端使用包含原因码为 0x93(超出接收最大值)的 DISCONNECT 报文断开网络连 接,如4.13节所述。更多关于流量控制的信息, 参考4.9节。 客户端不能延迟发送任何报文,除了 PUBLISH 报文--如果已发送且没有收到确认的 PUBLISH 报文数量已 达到服务端的接收最大值(Receive Maximum) [MQTT-3.3.4-8]。接收最大值只应用于当前网络连接。 非规范评注 客户端可以选择发送少于服务端接收最大值的未经确认的 PUBLISH 报文, 尽管它可以发送更多数 量的报文。 非规范评注 客户端可以选择暂停发送 QoS 为 0 的报文,当其暂停发送了 QoS 为 1 和 2 的 PUBLISH 报文。 非规范评注 如果客户端在收到 CONNACK 之前发送 QoS 为 1 或 QoS 为 2 的 PUBLISH 报文, 客户端有可能 被服务器断开连接,因为它发送了超过服务端接收最大值数量的发布报文。 服务端在接收到客户端的 PUBACK ,PUBCOMP 或包含原因码大于等于 128 的 PUBREC 报文之前,不能 发送数量超过客户端的接收最大值(Receive Maximum)的 QoS 为 1 和 2 的 PUBLISH 报文 [MQTT-3.3.4- 9]。客户端在发送 PUBACK 或 PUBCOMP 响应之前,如果收到数量超过服务端的接收最大值的 QoS 为 1   和 2 的 PUBLISH 报文,客户端使用包含原因码为 0x93(超出接收最大值) 的 DISCONNECT 报文断开网  络连接, 如4.13节所述。更多关于流量控制的信息, 参考4.9节 。 服务端不能延迟发送任何报文,除了 PUBLISH 报文--如果已发送且没有收到确认的 PUBLISH 报文数量已 到达客户端的接收最大值(Receive Maximum) [MQTT-3.3.4- 10]。 非规范评注 服务端可以选择发送少于客户端接收最大值的未经确认的 PUBLISH 报文, 尽管它可以发送更多数 量的报文。 非规范评注 服务端可以选择暂停发送 QoS 为 0 的报文,当其暂停发送了 QoS 为 1 和 2 的 PUBLISH 报文。 3.4 PUBACK – 发布确认 PUBACK 报文是对 QoS 1 等级的 PUBLISH 报文的响应。 3.4.1 PUBACK 固定报头 图 3- 10 - PUBACK 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (4)保留位 01000000byte 2剩余长度 剩余长度字段 表示可变报头的长度, 用变长字节整数编码。 3.4.2 PUBACK 可变报头 PUBACK 可变报头按顺序包含以下字段: 所确认的 PUBLISH 报文标识符, PUBACK 原因码,属性长度, 属性(Properties) 。属性编码规则如2.22节所述。 图 3- 11 – PUBACK 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBACK 原因码byte 4属性长度 3.4.2.1 PUBACK 原因码 PUBACK 可变报头第 3 字节是原因码(Reason Code)。剩余长度为 2,则表示使用原因码 0x00(成 功)。 表 3-4 - PUBACK 原因码 值16 进制原因码名称说明00x00成功消息被接收。 QoS 为 1 的消息已发布。160x10无匹配的订阅者消息被接收,但没有订阅者。只有服务端会发送此原 因码。如果服务端得知没有匹配的订阅者, 服务端可 以使用此原因码代替 0x00 (成功) 。1280x80未指明的错误接收端不接受此消息, 且不愿意透露错误原因或没有 适用的原因码。1310x83实现特定错误PUBLISH 报文有效,但不被接收端所接受。1350x87未授权PUBLISH 报文未授权。1440x90主题名无效主题名格式正确,但未被客户端或服务端所接受。 1450x91报文标识符被占用报文标识符正被占用。 可能表明客户端和服务端之间 的会话状态不匹配。1510x97超出配额已超出实现限制或管理限制。1530x99载荷格式无效载荷格式与载荷格式指示符不匹配。 服务端或客户端发送 PUBACK 报文时必须设置其中一种 PUBACK 原因码 [MQTT-3.4.2- 1]。当原因码为  0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBACK 剩 余长度为 2。 3.4.2.2 PUBACK 属性 3.4.2.2.1 属性长度 PUBACK 可变报头中属性长度被编码为变长字节整数。如果剩余长度小于 4 字节,则没有属性长度。 3.4.2.2.2 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不能被接收端所解析。 发送端使用此值向接收端提供附加信息。 如果加上原因字符串之后的 PUBACK 报文长度超出了接收端指定 的最大报文长度(Maximum Packet Size),则发送端不能发送此原因字符串 [MQTT-3.4.2-2]。包含多个 原因字符串将造成协议错误(Protocol Error)。 3.4.2.2.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于提供包括诊断信息在内的附加信息。如果加上用户属性之后 的 PUBACK 报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此 属性 [MQTT-3.4.2-3] 。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可 以多次出现。 3.4.3 PUBACK 载荷 PUBACK 报文没有有效载荷。 3.4.4 PUBACK 行为 描述见4.3.2节。 3.5 PUBREC – 发布已接收(QoS 2,第一步) PUBREC 报文是对 QoS 等级 2 的 PUBLISH 报文的响应。它是 QoS 2 等级协议交换的第二个报文。 3.5.1 PUBREC 固定报头 图 3- 12 - PUBREC 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (5)保留 01010000byte 2剩余长度 剩余长度字段 表示可变报头的长度, 用变长字节整数编码。 3.5.2 PUBREC 可变报头 PUBREC 可变报头按顺序包含以下字段: 所确认的 PUBLISH 报文标识符(Packet Identifier), PUBREC 原因码(Reason Code) ,属性(Properties) 。属性的编码规则,如2.2.2 节 所述。 图 3- 13 - PUBREC 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBREC 原因码byte 4属性长度 3.5.2.1 PUBREC 原因码 PUBREC 可变报头第 3 字节是原因码(Reason Code)。如果剩余长度为 2,则表示使用原因码 0x00(成 功)。 表 3-5 – PUBREC 原因码 值16 进制原因码名称说明00x00成功消息被接收。 QoS 为 2 的消息已发布。160x10无匹配的订阅者消息被接收,但没有订阅者。只有服务端会发送此原因码。 如果服务端得知没有匹配的订阅者, 服务端可以使用此原因    码代替 0x00(成功)。1280x80未指明的错误接收端不接受此消息, 且不愿意透露错误原因或没有适用的 原因码。1310x83实现特定错误PUBLISH 报文有效, 但不被接收端所接受。1350x87未授权PUBLISH 报文未授权。1440x90主题名无效主题名格式正确,但未被客户端或服务端所接受。1450x91报文标识符被占用报文标识符正被占用。可能表明客户端和服务端之间的会话 状态不匹配。1510x97超出配额已超出实现限制或管理限制。1530x99载荷格式无效载荷格式与载荷格式指示符不匹配。 服务端或客户端发送 PUBREC 报文时必须设置其中一种原因码 [MQTT-3.5.2- 1]。当原因码为 0x00(成功) 且没有属性(Properties)时,原因码和属性长度可以被省略。 在这种情况下,PUBREC 剩余长度为 2。 3.5.2.2 PUBREC 属性 3.5.2.2.1 属性长度 PUBREC 可变报头的属性长度被编码为变长字节整数。如果剩余长度小于 4,则表示没有属性长度字段。 3.5.2.2.2 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的 PUBREC 报文长度超出了接收端指定 的最大报文长度(Maximum Packet Size), 则发送端不能发送此属性 [MQTT-3.5.2-2]。包含多个原因字  符串将造成协议错误(Protocol Error)。 3.5.2.2.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于提供包括诊断信息在内的附加信息。如果加上用户属性之后 的 PUBREC 报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此 属性 [MQTT-3.5.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可 以多次出现。 3.5.3 PUBREC 载荷 PUBREC 报文没有有效载荷。 3.5.4 PUBREC 行为 描述见4.3.3节。 3.6 PUBREL – 发布释放(QoS 2,第二步) PUBREL 报文是对 PUBREC 报文的响应。它是 QoS 2 等级协议交换的第三个报文。 3.6.1 PUBREL 固定报头 图 3- 14 – PUBREL 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (6)保留位 01100010byte 2剩余长度 PUBREL 固定报头的第 3 ,2 ,1 ,0 位是保留位, 必须被设置为 0 ,0 ,1 ,0。服务端必须将其它的任何值 都当做是不合法的并关闭网络连接 [MQTT-3.6.1- 1]。 剩余长度字段 表示可变报头的长度,被编码为变长字节整数。 3.6.2 PUBREL 可变报头 PUBREL 报文的可变报头按顺序包含以下字段:所确认的 PUBREC 报文标识符, PUBREL 原因码, 属性 (Properties)。属性的编码规则如2.2.2节所述。 图 3- 15 – PUBREL 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBREL 原因码byte 4属性长度 3.6.2.1 PUBREL 原因码 可变报头第 3 字节是 PUBREL 原因码。如果剩余长度为 2,则表示使用原因码 0x00 (成功) 。 表 3-6 - PUBREL 原因码 值16 进制原因码名称说明00x00成功消息已释放。1460x92报文标识符未发现未知的报文标识符。会话恢复阶段这并非错误,但其他时间这表明 服务端和客户端的会话状态不匹配。 客户端或服务端发送 PUBREL 报文时必须设置其中一种 PUBREL 原因码 [MQTT-3.6.2- 1]。当原因码为  0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBREL 剩 余长度为 2。 3.6.2.2 PUBREL 属性 3.6.2.2.1 属性长度 PUBREL 报文可变报头中的属性长度被编码为变长字节整数。如果剩余长度小于 4,则表示没有属性长度 字段。 3.6.2.2.2 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。 如果加上原因字符串之后的 PUBREL 报文长度超出了接收端指定 的最大报文长度(Maximum Packet Size), 则发送端不能发送此原因字符串 [MQTT-3.6.2-2]。包含多个 原因字符串将造成协议错误(Protocol Error)。 3.6.2.2.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于提供包括诊断信息或关于 PUBREL 的信息。 如果加上用户属 性之后的 PUBREL 报文长度超出了接收端指定的最大报文长度(Maximum Packet Size), 则发送端不能 发送此属性 [MQTT-3.6.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对, 且相同的 名字可以多次出现。 3.6.3 PUBREL 载荷 PUBREL 报文没有有效载荷。 3.6.4 PUBREL 行为 描述见4.3.3节 。 3.7 PUBCOMP – 发布完成(QoS 2,第三步) PUBCOMP 报文是对 PUBREL 报文的响应。它是 QoS 2 等级协议交换的第四个也是最后一个报文。 3.7.1 PUBCOMP 固定报头 图 3- 16 – PUBCOMP 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (7)保留位 01110000byte 2剩余长度 剩余长度字段 表示可变报头的长度, 编码为变长字节整数。 3.7.2 PUBCOMP 可变报头 PUBCOMP 报文可变报头按顺序包含以下字段: 所确认的 PUBREL 报文标识符, PUBCOMP 原因码,属 性。属性(Properties)编码规则如2.2.2节所述。 图 3- 17 - PUBCOMP 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBCOMP 原因码byte 4属性长度 3.7.2.1 PUBCOMP 原因码 可变报头第 3 字节是 PUBCOMP 原因码。如果剩余长度为 2,则表示使用原因码 0x00(成功)。 表 3-7 – PUBCOMP 原因码 值16 进制原因码名称说明 00x00成功报文标识符已释放。 QoS 2 消息已完成发布。1460x92报文标识符未发现未知的报文标识符。会话恢复阶段这并非错误,但其他时间这表 明服务端和客户端的会话状态不匹配。 服务端或客户端发送 PUBCOMP 报文时必须设置一种 PUBCOMP 原因码 [MQTT-3.7.2- 1]。当原因码为  0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBCOMP 剩余长度为 2。 3.7.2.2 PUBCOMP 属性 3.7.2.2.1 属性长度 PUBCOMP 报文可变报头中的属性长度被编码为变长字节整数。如果剩余长度小于 4,则表示没有属性长 度字段。 3.7.2.2.2 原因字符串 31 (0x1F),原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。 如果加上原因字符串之后的 PUBCOMP 报文长度超出了接收端指 定的最大报文长度(Maximum Packet Size) ,则发送端不能发送此原因字符串 [MQTT-3.7.2-2]。包含多 个原因字符串将造成协议错误(Protocol Error)。 3.7.2.2.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于提供诊断信息或关于其他信息。如果加上用户属性之后的 PUBCOMP 报文长度超出了接收端指定的最大报文长度(Maximum Packet Size) ,则发送端不能发送此 属性 [MQTT-3.7.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可 以多次出现。 3.7.3 PUBCOMP 载荷 PUBCOMP 报文没有有效载荷。 3.7.4 PUBCOMP 行为 描述见4.3.3节。 3.8 SUBSCRIBE - 订阅请求 客户端向服务端发送 SUBSCRIBE 报文用于创建一个或多个订阅。每个订阅(Subscription)注册客户端所 感兴趣的一个或多个主题。服务端向客户端发送 PUBLISH 报文以转发被发布到符合这些订阅主题的应用消 息。 SUBSCRIBE 报文同样(为每个订阅) 指定了服务端可以向其发送的应用消息最大 QoS 等级。 3.8.1 SUBSCRIBE 固定报头 图 3- 18 - SUBSCRIBE 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (8)保留位 10000010byte 2剩余长度 SUBSCRIBE 报文固定报头第 3 ,2 ,1 ,0 比特位是保留位, 必须被设置为 0 ,0 ,1 ,0 。服务端必须将其 他的任何值都当做是不合法的并关闭网络连接 [MQTT-3.8.1- 1]。 剩余长度字段 表示可变报头的长度加上有效载荷的长度, 被编码为变长字节整数。 3.8.2 SUBSCRIBE 可变报头 SUBSCRIBE 报文可变报头按顺序包含以下字段: 报文标识符(Packet Identifier),属性(Properties)。 2.2.1节提供了更多关于报文标识符的信息。属性的编码规则如2.2.2节所述。 非规范示例 图 3- 19 展示了一个包含报文标识符为 10,且没有属性的 SUBSCRIBE 可变报头。 图 3- 19 – SUBSCRIBE 可变报头示例  说明76543210报文标识符byte 1报文标识符 MSB (0)00000000byte 2报文标识符 LSB (10)00001010byte 3属性长度 (0)00000000 3.8.2.1 SUBSCRIBE 属性 3.8.2.1.1 属性长度 SUBSCRIBE 报文可变报头中的属性长度被编码为变长字节整数。 3.8.2.1.2 订阅标识符 11 (0x0B) ,订阅标识符(Subscription Identifier)标识符。 跟随其后的是一个变长字节整数表示订阅标识符。订阅标识符取值范围从 1 到 268,435,455。订阅标识符 的值为 0 或包含多个订阅标识符将造成协议错误(Protocol Error)。 订阅标识符与 SUBSCRIBE 报文所创建或修改的订阅(Subscription)相关联。如果包含订阅标识符,它将 与订阅一起被存储。如果未指定此属性,则订阅被存储时将不包含订阅标识符。 更多关于订阅标识符的处理信息,参考3.8.3.1节 。 3.8.2.1.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。 用户属性允许出现多次,以表示多个名字/值对。同样的名字允许出现多次。 非规范评注 SUBSCRIBE 报文的用户属性可以被客户端用来向服务端发送订阅相关的属性。本规范不定义这些 属性的意义。 3.8.3 SUBSCRIBE 载荷 SUBSCRIBE 报文的载荷包含一列主题过滤器,指明客户端希望订阅的主题。 主题过滤器必须为 UTF-8 编 码的字符串 [MQTT-3.8.3- 1]。每个主题过滤器之后跟着一个订阅选项(Subscription Options)字节。 载荷必须包含至少一个主题过滤器/订阅选项对 [MQTT-3.8.3-2] 。不包含载荷的 SUBSCRIBE 报文将造成协 议错误(Protocol Error)。错误处理信息, 参考4.13节。 3.8.3.1 订阅选项 订阅选项的第 0 和 1 比特代表最大服务质量字段。此字段给出服务端可以向此客户端发送的应用消息的最 大 QoS 等级。最大服务质量字段为 3 将造成协议错误(Protocol Error)。 订阅选项的第 2 比特表示非本地(No Local)选项。值为 1,表示应用消息不能被转发给发布此消息的客户 标识符 [MQTT-3.8.3-3] 。共享订阅时把非本地选项设为 1 将造成协议错误(Protocol Error) [MQTT-3.8.3- 4]。 订阅选项的第 3 比特表示发布保留(Retain As Published)选项。值为 1 ,表示向此订阅转发应用消息时  保持消息被发布时设置的保留(RETAIN)标志。值为 0,表示向此订阅转发应用消息时把保留标志设置为 0。当订阅建立之后, 发送保留消息时保留标志设置为 1。 订阅选项的第 4 和 5 比特表示保留操作(Retain Handling)选项。此选项指示当订阅建立时,是否发送保 留消息。此选项不影响之后的任何保留消息的发送。如果没有匹配主题过滤器的保留消息, 则此选项所有 值的行为都一样。值可以设置为: 0 = 订阅建立时发送保留消息 1 = 订阅建立时, 若该订阅当前不存在则发送保留消息 2 = 订阅建立时不要发送保留消息 保留操作的值设置为 3 将造成协议错误(Protocol Error)。 订阅选项的第 6 和 7 比特为将来所保留。 服务端必须把此保留位非 0 的 SUBSCRIBE 报文当做无效报文 [MQTT-3.8.3-5]。 非规范评注 非本地(No Local)和发布保留(Retain As Published)订阅选项在客户端把消息发送给其他服务 端的情况下,可以被用来实现桥接。 非规范评注 已存在订阅的情况下不发送保留消息是很有用的, 比如重连完成时客户端不确定订阅是否在之前的 会话连接中被创建。 非规范评注 不发送保存的保留消息给新创建的订阅是很有用的,比如客户端希望接收变更通知且不需要知道最 初的状态。 非规范评注 对于某个指示其不支持保留消息的服务端, 发布保留和保留处理选项的所有有效值都将得到同样的 结果:订阅时不发送任何保留消息, 且所有消息的保留标志都会被设置为 0。 图 3-20 – SUBSCRIBE 报文载荷格式 说明76543210主题过滤器byte 1长度 MSBbyte 2长度 LSB bytes 3..N主题过滤器订阅选项 保留位保留处理RAPNLQoSbyte N+100XXXXXX RAP 指发布保留(Retain as Published)。 NL 指非本地(No Local)。 非规范示例 图 3-21 展示了 SUBSCRIBE 载荷示例,包含 2 个主题过滤器: 第一个为“a/b” ,QoS 为 1;第二个 为“c/d” QoS 为 2。 图 3-21 - 载荷字节格式非规范示例  说明76543210主题过滤器byte 1长度 MSB (0)00000000byte 2长度 LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010订阅选项byte 6订阅选项 (1)00000001主题过滤器byte 7长度 MSB (0)00000000byte 8长度 LSB (3)00000011byte 9‘c’ (0x63)01100011byte 10‘/’ (0x2F)00101111byte 11‘d’ (0x64)01100100订阅选项byte 12订阅选项 (2)00000010 3.8.4 SUBSCRIBE 行为 当服务端收到来自客户端的 SUBSCRIBE 报文时, 必须使用 SUBACK 报文作为相应 [MQTT-3.8.4- 1]。 SUBACK 报文必须和待确认的 SUBSCRIBE 报文有相同的报文标识符 [MQTT-3.8.4-2]。 允许服务端在发送 SUBACK 报文之前就开始发送与订阅相匹配的 PUBLISH 报文。 如果服务端收到的 SUBSCRIBE 报文中的一个主题过滤器与当前会话的一个非共享订阅(Non-shared Subscription)相同,那么必须使用新的订阅替换现存的订阅 [MQTT-3.8.4-3]。新订阅的主题过滤器与之前 的订阅相同,但其订阅选项可能不同。如果保留处理选项为 0,任何匹配该主题过滤器的保留消息必须被  重发,但替换订阅不能造成应用消息的丢失 [MQTT-3.8.4-4]。 如果服务端收到的非共享主题过滤器(Non-shared Topic Filter)不同于当前会话的任何主题过滤器,一个 新的非共享订阅将被创建。如果保留处理选项不为 2,所有相匹配的保留消息将发送给客户端。 如果服务端收到的主题过滤器与服务端已存在的某个共享订阅(Shared Subscription)主题过滤器相同, 则将此会话添加到该共享订阅中。不发送任何保留消息。 如果服务端收到的共享订阅主题过滤器(Shared Subscription Topic Filter)与任何已存在的共享订阅主题 过滤器都不同, 一个新的共享订阅将被创建。将此会话作为订阅者添加到该共享订阅。不发送任何保留消 息。 更多关于共享订阅的细节, 参考4.8节。 如果服务端收到的 SUBSCRIBE 报文包含多个主题过滤器, 服务端必须当做收到一系列多个 SUBSCRIBE 报文来处理--除了将它们的响应组合为单个 SUBACK 响应 [MQTT-3.8.4-5]。 服务端发送给客户端的 SUBACK 报文必须为每一个主题过滤器/订阅选项对包含一个原因码 [MQTT-3.8.4-   6] 。 此原因码必须说明为该订阅授予的最大 QoS 等级,或指示订阅失败 [MQTT-3.8.4-7] 。服务端可能授予 了低于订阅者所请求的最大 QoS 等级。响应该订阅的应用消息 QoS 等级必须为该消息发布时的 QoS 等级 和服务端授予的最大 QoS 等级二者最小值 [MQTT-3.8.4-8] 。在原始消息发布的 QoS 等级为 1,且授予的 最大 QoS 等级为 0 的情况下,服务端允许发送重复的消息副本给订阅者(? )。 非规范评注 如果订阅客户端的某个主题过滤器已被授予的最大 QoS 等级为 1 ,那么匹配此过滤器的 QoS 等级 为 0 的应用消息按照 QoS 等级为 0 分发给此客户端。这意味着客户端最多只能收到该消息的一个  副本。另一方面,发布到相同主题的 QoS 等级为 2 的消息,其 QoS 等级被服务端降级为 1 以便分 发给该客户端。因此该客户端可能收到此消息的多个副本。 非规范评注 如果订阅客户端被授予的最大 QoS 等级为 0,那么按照 QoS 等级为 2 发布的应用消息在繁忙时可 能会丢失,但服务端不应该发送重复的消息副本。发布到相同主题的 QoS 等级为 1 的消息,分发 给该客户端时可能会丢失或重复。 非规范评注 使用 QoS 等级 2 订阅某个主题过滤器,等于是说:我想要按照消息被发布时的QoS 等级接收匹配 此过滤器的消息。这意味着发布者负责决定消息可以被发布的最大 QoS 等级,但订阅端可以要求  服务端降低该消息的 QoS 到更适合它的等级。 订阅标识符是服务端的会话状态的一部分, 并将在收到 PUBLISH 报文时返回给客户端。当服务端收到客户 端的 UNSUBSCRIBE 报文时,服务端将此会话标识符从服务端的会话状态中移除:当服务端收到客户端的 UNSUBSCRIBE 报文, 当服务端收到客户端对同样主题过滤器的 SUBSCRIBE 报文但订阅标识符不同或没 有订阅标识符, 或者当服务端在 CONNACK 报文中将会话存在标志设置为 0。 订阅标识符不构成客户端的会话状态的一部分。在一个有用的实现中, 客户端将订阅标识符与其他客户端 状态相关联,此客户端状态将被移除:当客户端取消订阅,当客户端以不同的订阅标识符或没有订阅标识 符订阅同样的主题过滤器, 或者当客户端收到的 CONNACK 报文中会话存在标志被设置为 0。 服务端在重传的 PUBLISH 报文中无需使用同一组订阅标识符。客户端可以通过发送包含与当前会话已存在 的主题过滤器的 SUBSCRIBE 报文进行重新订阅。如果客户端在 PUBLISH 报文初传之后重新订阅并使用  了不同的订阅标识符, 允许服务端在任何重传中使用初传所包含的订阅标识符,或者在重传中使用此新的  订阅标识符。不允许服务端在发送了包含新的订阅标识符的 PUBLISH 报文之后再次使用旧的订阅标识符。 非规范评注 使用场景,用以阐述订阅标识符: .     客户端实现指示某条发布消息匹配多个订阅的编程接口,客户端实现每次订阅时生成新的订阅 标识符。如果返回的发布消息包含多个订阅标识符,则该发布消息匹配多个订阅。 .     客户端实现允许订阅者将消息定向到其相关联的订阅的回调,客户端实现生成映射到唯一回调 的订阅标识符。 收到某条发布消息时,使用订阅标识符决定触发哪一个回调。 .     客户端实现在发布消息时返回程序用于订阅的主题字符串,为此客户端生成一个唯一标识了该 主题过滤器的标识符。收到某条发布消息时,客户端实现使用此标识符查找原始主题过滤器, 并将主题过滤器返回给其应用程序。 .     网关(Gateway)将从服务端收到的发布消息转发给向该网关做了订阅的客户端,网关实现维 护其收到的每个唯一的订阅过滤器到其收到的一组客户标识符--订阅标识符对的映射,网关对 它转发给服务端的每个主题过滤器生成一个唯一的标识符。收到某条发布消息时, 网关使用从 服务端收到的订阅标识符查找对应的客户标识符--订阅标识符对,并把它们加入发送给客户端 的 PUBLISH 报文中。如果上游服务端因为消息匹配了多个订阅而发送了多个 PUBLISH  报文, 则此行为将反映到客户端。 3.9 SUBACK – 订阅确认 服务端发送 SUBACK 报文给客户端,用于确认它已收到并且正在处理 SUBSCRIBE 报文。 SUBACK 报文包含一个原因码列表,用于指定授予的最大 QoS 等级或 SUBSCRIBE 报文所请求的每个订 阅发生的错误。 3.9.1 SUBACK 固定报头 图 3-22 - SUBACK 报文固定报头 Bit76543210 byte 1MQTT 控制报文类型 (9)保留位 10010000byte 2剩余长度 剩余长度字段 可变报头长度加上有效载荷长度,编码为变长字节整数。 3.9.2 SUBACK 可变报头 SUBACK 报文可变报头按顺序包含以下字段:所确认的 SUBSCRIBE 报文标识符,属性(Properties)。 3.9.2.1 SUBACK 属性 3.9.2.1.1 属性长度 SUBACK 可变报头中的属性长度被编码为变长字节整数。 3.9.2.1.2 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。 如果加上原因字符串之后的 SUBACK 报文长度超出了客户端指定 的最大报文长度,则服务端不能发送此原因字符串 [MQTT-3.9.2- 1]。包含多个原因字符串将造成协议错误 (Protocol Error)。 3.9.2.1.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户 属性之后的 SUBACK 报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性 [MQTT- 3.9.2-2]。用户属性(User  Property)允许出现多次, 以表示多个名字/值对,且相同的名字可以多次出现。 图 3-23 - SUBACK 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSB 3.9.3 SUBACK 载荷 有效载荷包含一个原因码列表。每个原因码对应 SUBSCRIBE 报文中的一个被确认的主题过滤器。 SUBACK 报文中的原因码顺序必须与 SUBSCRIBE 报文中的主题过滤器顺序相匹配 [MQTT-3.9.3- 1]。 表 3-8 - 订阅原因码 值16 进制原因码名称说明00x00授予 QoS 等级 0订阅被接受且最大 QoS 等级为 0。可能低于所请求的 QoS 等级。10x01授予 QoS 等级 1订阅被接受且最大 QoS 等级为 1。可能低于所请求的 QoS 等级。20x02授予 QoS 等级 2订阅被接受且任何 QoS 等级都将被发送给此订阅。1280x80未指明错误订阅未被接受, 且服务端不愿意透露原因或没有适用的原因码。1310x83实现特定错误SUBSCRIBE 有效但不被服务端所接受。1350x87未授权客户端未被授权做此订阅。1430x8F主题过滤器无效主题过滤器格式正确, 但不被允许。1450x91报文标识符已占用指定的报文标识符正在被使用中。1510x97超出配额已超出实现限制或管理限制。1580x9E共享订阅不支持服务端不支持此客户端进行共享订阅。1610xA1订阅标识符不支持服务端不支持订阅标识符; 订阅标识符不被接受。1620xA2通配符订阅不支持服务端不支持通配符订阅; 订阅未被接受。 服务端发送 SUBACK 报文时必须对收到的每一个主题过滤器设置一种原因码 [MQTT-3.9.3-2]。 非规范评注 对于 SUBSCRIBE 报文中的每个主题过滤器,总有一个对应的原因码。如果原因码不是针对某个 特定的主题过滤器(比如 0x91(报文标识符已占用)), 则对每个主题过滤器都使用此原因码。 3.10 UNSUBSCRIBE – 取消订阅请求 客户端发送 UNSUBSCRIBE 报文给服务端, 用于取消订阅主题。 3.10.1 UNSUBSCRIBE 固定报头 图 3-28 – UNSUBSCRIBE 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (10)保留位  10100010byte 2剩余长度 UNSUBSCRIBE 固定报头的第 3 ,2 ,1 ,0 位是保留位且必须分别设置为 0 ,0 ,1 ,0。服务端必须认为任 何其它的值都是不合法的并关闭网络连接 [MQTT-3.10.1- 1]。 剩余长度字段 等于可变报头长度(2 字节)加上有效载荷长度, 编码为变长字节整数。 3.10.2 UNSUBSCRIBE 可变报头 UNSUBSCRIBE 报文可变报头按顺序包含以下字段: 报文标识符和属性(Properties)。2.2.1节提供了有 关报文标识符的更多信息。属性的编码规则,如2.2.2节所述。 3.10.2.1 UNSUBSCRIBE 属性 3.10.2.1.1 属性长度 SUBSCRIBE 可变报头中属性的长度被编码为变长字节整数。 3.10.2.1.2 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是一个 UTF-8 字符串对。 用户属性允许出现多次,以表示多个名字/值对。相同的名字可以出现多次。 非规范评注 UNSUBSCRIBE 报文中的用户属性可以被客户端用来向服务端发送订阅相关的属性。本规范不定 义这些属性的意义。 3.10.3 UNSUBSCRIBE 载荷 UNSUBSCRIBE 报文有效载荷包含一列客户端希望取消订阅的主题过滤器。 UNSUBSCRIBE 报文中的主 题过滤器必须为1.5.4节所述的 UTF-8 编码字符串 [MQTT-3.10.3- 1] ,且连续填充。 UNSUBSCRIBE 报文有效载荷必须包含至少一个主题过滤器 [MQTT-3.10.3-2]。不包含有效载荷的 UNSUBSCRIBE 报文将造成协议错误(Protocol Error)。错误处理信息,参考4.13节。 非规范示例 图 3-30 展示了 UNSUBSCRIBE 报文的载荷示例,包括两个主题过滤器 “a/b”和“c/d”。 图 3-30 - 载荷字节格式非规范示例  说明76543210主题过滤器byte 1长度 MSB (0)00000000byte 2长度 LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010主题过滤器byte 6长度 MSB (0)00000000byte 7长度 LSB (3)00000011byte 8‘c’ (0x63)01100011byte 9‘/’ (0x2F)00101111byte 10‘d’ (0x64)01100100 3.10.4 UNSUBSCRIBE 行为 服务端必须对客户端的 UNSUBSCRIBE 报文中提供的主题过滤器(不管是否包含通配符) 逐个字符与当前 持有的主题过滤器集进行比较。如果任何过滤器完全匹配,则必须删除其拥有的订阅 [MQTT-3.10.4- 1],否 则不会进行额外的处理。 当服务端收到 UNSUBSCRIBE 报文: .     它必须停止添加为了交付给客户端的与主题过滤器相匹配的任何新消息 [MQTT-3.10.4-2]。 .     它必须完成任何已经开始发送给客户端的、与主题过滤器相匹配的、 QoS 等级为 1 或 2 的消息 [MQTT-3.10.4-3]。 .     它可以继续交付任何为交付给客户端而缓存的消息。 服务端必须发送 UNSUBACK 报文以响应客户端的 UNSUBSCRIBE 请求 [MQTT-3.10.4-4] 。UNSUBACK    报文必须包含和 UNSUBSCRIBE 报文相同的报文标识符。即使没有删除任何主题订阅,服务端也必须发送 一个 UNSUBACK 响应 [MQTT-3.10.4-5]。 如果某个主题过滤器代表一个共享订阅,此会话将被从该共享订阅中删除。如果此会话是该共享订阅所关 联的唯一会话, 该共享订阅被删除。共享订阅的处理, 参考4.8.2节。 3.11 UNSUBACK – 取消订阅确认 服务端发送 UNSUBACK 报文给客户端用于确认收到 UNSUBSCRIBE 报文。 3.11.1 UNSUBACK 固定报头 图 3-31 – UNSUBACK 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (11)保留位 10110000byte 2剩余长度 剩余长度字段 等于可变报头的长度加上有效载荷的长度, 编码为变长字节整数。 3.11.2 UNSUBACK 可变报头 UNSUBACK 报文可变报头按顺序包含以下字段: 所确认的 UNSUBSCRIBE 报文标识符和属性 (Properties)。 属性的编码规则如2.2.2节所述。 图 3-32 – UNSUBACK 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSB 3.11.2.1 UNSUBACK 属性 3.11.2.1.1 属性长度 UNSUBACK 报文可变报头中的属性的长度被编码为变长字节整数。 3.11.2.1.2 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。 如果加上原因字符串之后的 UNSUBACK 报文长度超出了客户端  指定的最大报文长度, 则服务端不能发送此原因字符串 [MQTT-3.11.2- 1]。包含多个原因字符串将造成协议 错误(Protocol Error)。 3.11.2.1.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户 属性之后的 UNSUBACK 报文长度超出了客户端指定的最大报文长度, 则服务端不能发送此属性 [MQTT- 3.11.2-2]。用户属性(User Property)允许出现多次,以表示多个名字/值对, 且相同的名字可以多次出现。 3.11.3 UNSUBACK 载荷 有效载荷包含一个原因码列表。每个原因码对应 UNSUBSCRIBE 报文中的一个被确认的主题过滤器。 UNSUBACK 报文中的原因码顺序必须与 UNSUBSCRIBE 报文中的主题过滤器顺序相匹配 [MQTT-3.11.3- 1]。 单字节无符号取消订阅原因码的值如下所示。 服务端发送 UNSUBACK  报文时对于每个收到的主题过滤器,  必须使用一个取消订阅原因码 [MQTT-3.11.3-2]。 表 3-9 - 取消订阅原因码 值16 进制原因码名称说明00x00成功订阅已被删除。170x11订阅未发现没有该客户端匹配的主题过滤器被使用。1280x80未指定错误取消订阅不能被完成且服务端不愿意透露原因或没有其他适 用的原因码。1310x83实现指定错误UNSUBSCRIBE 报文有效,但服务端不接受。1350x87未授权客户端未被授权进行取消订阅。1430x8F主题过滤器无效主题过滤器格式正确, 但不被允许。1450x91报文标识符已占用指定的报文标识符正在被使用中。 非规范评注 对于 UNSUBSCRIBE 报文中的每个主题过滤器, 总有一个对应的原因码。如果原因码不是针对某   个特定的主题过滤器(比如 0x91(报文标识符已占用)) ,则对每个主题过滤器都使用此原因码。 3.12 PINGREQ – PING 请求 客户端发送 PINGREQ 报文给服务端,可被用于: .     在没有任何其他 MQTT 控制报文从客户端发给服务端时,告知服务端客户端还活着。 .     请求服务端发送响应以确认服务端还活着。 .     使用网络已确认网络连接没有断开。 此报文被用在保持连接(Keep Alive)的处理中。详细信息,参考3.1.2.10节。 3.12.1 PINGREQ 固定报头 图 3-33 – PINGREQ 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (12)保留位 11000000byte 2剩余长度 (0) 00000000 3.12.2 PINGREQ 可变报头 PINGREQ 报文没有可变报头。 3.12.3 PINGREQ 载荷 PINGREQ 报文没有有效载荷 3.12.4 PINGREQ 行为 服务端必须发送 PINGRESP 报文响应客户端的 PINGREQ 报文 [MQTT-3.12.4- 1]。 3.13 PINGRESP – PING 响应 服务端发送 PINGRESP 报文响应客户端的 PINGREQ 报文。表示服务端还活着。 此报文被用在保持连接(Keep Alive)的处理中。详细信息,参考3.1.2.10节。 3.13.1 PINGRESP 固定报头 图 3-34 – PINGRESP 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (13)保留位 11010000byte 2剩余长度 (0) 00000000 3.13.2 PINGRESP 可变报头 PINGRESP 报文没有可变报头。 3.13.3 PINGRESP 载荷 PINGRESP 报文没有有效载荷。 3.13.4 PINGRESP 行为 客户端收到此报文时不做任何处理。 3.14 DISCONNECT – 断开通知 DISCONNECT 报文是客户端发给服务端的最后一个 MQTT 控制报文。表示客户端为什么断开网络连接的 原因。客户端和服务端在关闭网络连接之前可以发送一个 DISCONNECT 报文。如果在客户端没有首先发 送包含原因码为 0x00(正常断开) DISCONNECT 报文并且连接包含遗嘱消息的情况下, 遗嘱消息会被发 布。更多细节, 参考3.1.2.5节。 服务端不能发送 DISCONNECT 报文,直到它发送了包含原因码小于 0x80 的 CONNACK 报文之后 [MQTT-3.14.0- 1]。 3.14.1 DISCONNECT 固定报头 图 3-35 – DISCONNECT 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (14)保留字段 11100000byte 2剩余长度 服务端或客户端必须验证所有的保留位都被设置为 0,如果他们不为 0,发送包含原因码为 0x81(无效报 文)的 DISCONNECT 报文,如4.13节所述 [MQTT-3.14.1- 1]。 剩余长度字段 等于可变报头的长度, 编码为变长字节整数。 3.14.2 DISCONNECT 可变报头 DISCONNECT 报文的可变报头按顺序包含以下字段: 断开原因码,属性(Properties)。属性的编码规则 如2.2.2节所述。 3.14.2.1 断开原因码 可变报头的第 1 个字节是断开原因码。如果剩余长度小于 1,则表示使用原因码 0x00(正常断开)。 单字节无符号断开原因码字段如下所示。 表 3- 10 – 断开原因值 值16 进制原因码名称发送端说明00x00正常断开客户端或 服务端正常关闭连接。不发送遗嘱。40x04包含遗嘱消息的断开客户端客户端希望断开但也需要服务端发布它的遗嘱消 息。1280x80未指定错误客户端或 服务端连接被关闭,但发送端不愿意透露原因,或者没 有其他适用的原因码。1290x81无效的报文客户端或 服务端收到的报文不符合本规范。1300x82协议错误客户端或 服务端收到意外的或无序的报文。1310x83实现指定错误客户端或 服务端收到的报文有效,但根据实现无法进行处理。1350x87未授权服务端请求没有被授权1370x89服务端正忙服务端服务端正忙且不能继续处理此客户端的请求。1390x8B服务正关闭服务端服务正在关闭。1410x8D保持连接超时服务端连接因为在超过 1.5 倍的保持连接时间内没有收 到任何报文而关闭。1420x8E会话被接管服务端另一个使用了相同的客户标识符的连接已建立, 导致此连接关闭。1430x8F主题过滤器无效服务端主题过滤器格式正确, 但不被服务端所接受。1440x90主题名无效客户端或 服务端主题名格式正确,但不被客户端或服务端所接 受。1470x93超出接收最大值客户端或 服务端客户端或服务端收到了数量超过接收最大值的未 发送 PUBACK 或 PUBCOMP 的发布消息。1480x94主题别名无效客户端或 服务端客户端或服务端收到的 PUBLISH 报文包含的主 题别名大于其在 CONNECT 或 CONNACK 中发 送的主题别名最大值。1490x95报文过大客户端或 服务端报文长度大于此客户端或服务端的最大报文长 度。 1500x96消息速率过高客户端或 服务端收到的数据速率太高。1510x97超出配额客户端或 服务端已超出实现限制或管理限制。1520x98管理操作客户端或 服务端连接因为管理操作被关闭。1530x99载荷格式无效客户端或 服务端载荷格式与指定的载荷格式指示符不匹配。1540x9A不支持保留服务端服务端不支持保留消息。1550x9B不支持的 QoS 等级服务端客户端指定的 QoS 等级大于 CONNACK 报文中 指定的最大 QoS 等级。1560x9C(临时) 使用其他服务端服务端客户端应该临时使用其他服务端。1570x9D服务端已 (永久)移动服务端服务端已移动且客户端应该永久使用其他服务 端。1580x9E不支持共享订阅服务端服务端不支持共享订阅。1590x9F超出连接速率限制服务端此连接因为连接速率过高而被关闭。1600xA0最大连接时间服务端超出为此连接授予的最大连接时间。1610xA1不支持订阅标识符服务端服务端不支持订阅标识符; 订阅未被接受。1620xA2不支持通配符订阅服务端服务端不支持通配符订阅; 订阅未被接受。 客户端或服务端发送 DISCONNECT 报文时必须使用一种 DISCONNECT 原因码 [MQTT-3.14.2- 1]。如果  原因码为 0x00(正常断开)且没有属性, 原因码和属性长度可以被省略。这种情况下 DISCONNECT 报文 剩余长度为 0。 非规范评注 DISCONNECT 报文用于指示断开的原因, 例如没有确认报文(比如 QoS 等级 0 的发布消息)或 当客户端或服务端不能继续处理连接。 非规范评注 客户端可以使用这些信息来决定是否重新连接,以及在重新尝试之前应该等待多长时间。 3.14.2.2 DISCONNECT 属性 3.14.2.2.1 属性长度 DISCONNECT 报文可变报头中的属性(Properties)的长度被编码为变长字节整数。如果剩余长度小于 2, 属性长度使用 0。 3.14.2.2.2 会话过期间隔 17 (0x11) ,会话过期间隔(Session Expiry Interval)标识符。 跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。 包含多个会话 过期间隔将造成协议错误(Protocol Error)。 如果没有设置会话过期间隔,则使用 CONNECT 报文中的会话过期间隔。 会话过期间隔不能由服务端的 DISCONNECT 报文发送 [MQTT-3.14.2-2]。 如果 CONNECT 报文中的会话过期间隔为 0,则客户端在 DISCONNECT 报文中设置非 0 会话过期间隔将 造成协议错误(Protocol Error)。如果服务端收到这种非 0 会话过期间隔, 则不会将其视为有效的 DISCONNECT 报文。服务端使用包含原因码为 0x82  (协议错误)的 DISCONNECT 报文,如4.13节所 述。 3.14.2.2.3 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码字符串表示断开原因。此原因字符串是为诊断而设计的可读字符串, 不应该被接 收端所解析。 如果此属性使得 DISCONNECT 报文的长度超出了接收端指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.14.2-3] 。包含多个原因字符串将造成协议错误(Protocol Error)。 3.14.2.2.4 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户 属性之后的 DISCONNECT 报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.14.2-4] 。用户属性允许出现多次,以表示多个名字/值对, 且相同的名字可以多次出现。 3.14.2.2.5 服务端参考 28 (0x1C) ,服务端参考(Server Reference)标识符。 跟随其后的是一个 UTF-8 编码字符串,客户端可以使用它来识别其他要使用的服务端。包含多个服务端参 考将造成协议错误(Protocol Error)。 服务端发送包含一个服务端参考和原因码 0x9C( (临时) 使用其他服务端) 或 0x9D(服务端已(永久) 移动)的 DISCONNECT 报文,如4.13节所述。 关于如何使用服务端参考,参考4.11节服务端重定向。 图 3-24 - DISCONNECT 报文可变报头非规范示例  说明76543210断开原因码byte 1 00000000属性byte 2长度 (5)00000101byte 3会话过期间隔标识符 (17)00010001byte 4会话过期间隔 (0)00000000byte 500000000byte 600000000byte 700000000 3.14.3 DISCONNECT 载荷 DISCONNECT 报文没有有效载荷。 3.14.4 DISCONNECT 行为 发送端发送完 DISCONNECT 报文之后: .     不能再在此网络连接上发送任何 MQTT 控制报文 [MQTT-3.14.4- 1]。 .     必须关闭网络连接 [MQTT-3.14.4-2]。 接收到包含原因码为 0x00 (成功) 的 DISCONNECT 时,服务端: .     必须丢弃任何与当前连接相关的遗嘱消息, 而不发布它 [MQTT-3.14.4-3],如3.1.2.5节所述。 接收到 DISCONNECT 报文时,接收端: .     应该关闭网络连接 3.15 AUTH – 认证交换 AUTH 报文被从客户端发送给服务端,或从服务端发送给客户端,作为扩展认证交换的一部分, 比如质询/  响应认证。如果 CONNECT 报文不包含相同的认证方法,则客户端或服务端发送 AUTH 报文将造成协议错 误(Protocol Error)。 3.15.1 AUTH 固定报头 图 3-35 – AUTH 报文固定报头 Bit76543210 byte 1MQTT 控制报文类型 (15)保留位 11110000byte 2剩余长度 AUTH 报文固定报头第 3 ,2 ,1 ,0 位是保留位, 必须全设置为 0。客户端或服务端必须把其他值当做无效 值并关闭网络连接 [MQTT-3.15.1- 1]。 剩余长度字段 等于可变报头的长度, 编码为变长字节整数。 3.15.2 AUTH 可变报头 AUTH 报文可变报头按顺序包含以下字段: 认证原因码(Authentication Reason Code) ,属性 (Properties)。 属性的编码规则, 如2.2.2节所述。 3.15.2.1 认证原因码 可变报头第 0 字节是认证原因码(Authenticate Reason Code)。单字节无符号认证原因码字段的值如下 所示。 AUTH 报文的发送端必须使用一种认证原因码 [MQTT-3.15.2- 1]。 表 3- 11 - 认证原因码 值16 进制原因码名称发送端说明00x00成功服务端认证成功。240x18继续认证服务端或 客户端继续下一步认证。250x19重新认证客户端开始重新认证。 如果原因码为 0x00(成功)并且没有属性字段, 则可以省略原因码和属性长度。这种情况下, AUTH 报文 剩余长度为 0。 3.15.2.2 AUTH 属性 3.15.2.2.1 属性长度 AUTH 报文可变报头中的属性的长度被编码为变长字节整数。 3.15.2.2.2 认证方法 21 (0x15) ,认证方法(Authentication Method)标识符。 跟随其后的是一个 UTF-8 编码字符串,包含认证方法名称。省略认证方法或者包含多个认证方法都将造成 协议错误(Protocol Error)。 更多关于扩展认证的信息,参考4.12节。 3.15.2.2.3 认证数据 22 (0x16) ,认证数据(Authentication Data)标识符。 跟随其后的是二进制数据, 包含认证数据。包含多个认证数据将造成协议错误(Protocol Error)。此数据 的内容由认证方法定义。更多关于扩展认证的信息,参考4.12节。 3.15.2.2.4 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码字符串, 表示断开原因。此原因字符串是为诊断而设计的可读字符串, 不应该被 接收端所解析。 如果加上原因字符串之后的 AUTH 报文长度超出了接收端所指定的最大报文长度, 则发送端不能发送此属 性 [MQTT-3.15.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.15.2.2.5 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户 属性之后的 AUTH 报文长度超出了接收端指定的最大报文长度, 则服务端不能发送此属性 [MQTT-3.15.2-  3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.15.3 AUTH 载荷 AUTH 报文没有有效载荷。 3.15.4 AUTH 行为 更多关于扩展认证的信息, 参考4.12节。 4  操作行为 4.1 会话状态 为实现 QoS 等级 1 和 QoS 等级 2 协议流,客户端和服务端需要将状态与客户标识符相关联,这被称为会 话状态。服务端还将订阅信息存储为会话状态的一部分。 会话可以跨越一系列的网络连接。它持续到最新的网络连接(Network Connections)加上会话过期间隔 (Session Expiry Interval)。 客户端的会话状态包括: .     已发送给服务端,但是还没有完成确认的 QoS 等级 1 和 QoS 等级 2 的消息。 .     从服务端收到的,但是还没有完成确认的 QoS 等级 2 消息。 服务端的会话状态包括: .     会话是否存在, 即使会话状态其余部分为空。 .     客户端订阅信息,包括任何订阅标识符。 .     已发送给客户端,但是还没有完成确认的 QoS 等级 1 和 QoS 等级 2 的消息。 .     等待传输给客户端的 QoS 等级 0(可选) ,QoS 等级 1 和 QoS 等级 2 的消息。 .     从客户端收到的,但是还没有完成确认的 QoS 等级 2 消息。遗嘱小子和遗嘱延时间隔。 .     如果会话当前未连接, 会话结束时间和会话状态将被丢弃。 保留消息不是会话状态的一部分,会话结束时不被删除。 4.1.1 存储会话状态 当网络连接打开时,客户端和服务端不能丢弃会话状态 [MQTT-4.1.0- 1] 。当网络连接被关闭并且会话过期 间隔已过时,服务端必须丢弃会话状态 [MQTT-4.1.0-2]。 非规范评注 客户端和服务端实现的存储容量必然是有限的,还可能要受管理策略的限制。已存储的会话状态可 能因为管理操作(比如某个预定义条件的自动响应)而被丢弃。它造成的后果就是会话终止。这些 操作可能是因为资源受限或其他操作原因引发的。硬件或软件故障可能导致客户端或服务端存储的 会话状态丢失或损坏。 需要谨慎的评估客户端和服务端的存储能力,以确保存储空间充足。 4.1.2 会话状态非规范示例 例如,想要收集电表读数的用户可能会决定使用 QoS 等级 1 的消息,因为他们不能接受数据在网络传输途 中丢失, 但是, 他们可能认为客户端和服务端的数据可以存储在内存(易失性存储器)中, 因为(他们觉  得)电力供应是非常可靠的,不会有太大的数据丢失风险。 与之相反,停车计费支付应用的提供商可能决定任何情况下都不能让数据支付消息丢失,因此他们要求在 通过网络传输之前将所有的数据写入到非易失性存储器中(如硬盘)。 4.2 网络连接 MQTT 协议要求基础传输层能够提供有序的、可靠的、双向传输(从客户端到服务端和从服务端到客户端) 字节流。此规范不要求任何指定的传输协议。客户端或服务端可以支持这里列出的任何传输协议, 或者满 足本节要求的任何其他传输协议。 客户端或服务端必须支持使用一个或多个提供有序的、可靠的、双向传输(从客户端到服务端和从服务端 到客户端)字节流传输的底层传输协议 [MQTT-4.2- 1]。 非规范评注 MQTT v5.0 使用的传输层协议是[RFC0793]定义的 TCP/IP 协议。下面的协议也支持: .     TLS[RFC5246] .     WebSocket[RFC6455] 非规范评注 TCP 端口 8883 和 1883 已在 IANA 注册,分别用于 MQTT 的 TLS 和非 TLS 通信。 非规范评注 无连接的网络传输,如用户数据包协议 (UDP) 本身不适合,因为它们可能丢失或重新排列数据。 4.3 服务质量等级和协议流程 MQTT 按照后面章节定义的服务质量(QoS)等级分发应用消息。分发协议是对称的,在下面的描述中, 客户端和服务端既可以是发送端也可以是接收端。分发协议关注的是从单个发送者到单个接收者的应用消 息。服务端分发应用消息给多个客户端时, 每个客户端独立处理。分发给客户端的出站应用消息和入站应 用消息的 QoS 等级可能是不同的。 4.3.1 QoS 0:最多分发一次 消息的分发依赖于底层网络的能力。接收端不会发送响应,发送端也不会重试。消息可能送达一次也可能 根本没送达。 对于 QoS 等级 0 的分发协议,发送端 .     必须发送 QoS 等于 0 ,DUP 等于 0 的 PUBLISH 报文 [MQTT-4.3.1- 1]。 对于 QoS 等级 0 的分发协议,接收端 .     接受 PUBLISH 报文时同时接受消息的所有权。 图 4- 1 – QoS 等级 0 协议流程图,非规范示例 发送端动作控制报文接收端动作PUBLISH 报文 QoS 0, DUP=0   ---------->   分发应用消息给适当的后续接收 者(们) 4.3.2 QoS 1:至少分发一次 服务质量等级 1 确保消息至少送达一次。 QoS 等级 1 的 PUBLISH 报文的可变报头中包含一个报文标识符, 需要 PUBACK 报文确认。 2.2.1节提供了有关报文标识符的更多信息。 对于 QoS 等级 1 的分发协议,发送端 .     每次发送新的应用消息都必须分配一个未使用的报文标识符 [MQTT-4.3.2- 1]。 .     发送的 PUBLISH 报文必须包含报文标识符且 QoS 等于 1 ,DUP 等于 0 [MQTT-4.3.2-2]。 .     必须将这个 PUBLISH 报文看作是未确认的,直到从接收端那收到对应的 PUBACK 报文。4.4节 有一个关于未确认消息的讨论 [MQTT-4.3.2-3]。 一旦发送端收到 PUBACK 报文,这个报文标识符就可以重用。 注意:允许发送端在等待确认时使用不同的报文标识符发送后续的 PUBLISH 报文。 对于 QoS 等级 1 的分发协议,接收端 .     响应的 PUBACK 报文必须包含一个报文标识符, 这个标识符来自接收到的、已经接受所有权的 PUBLISH 报文 [MQTT-4.3.2-4]。 .     发送了 PUBACK 报文之后,接收端必须将任何包含相同报文标识符的入站 PUBLISH 报文当做一 个新的消息,并忽略它的 DUP 标志的值 [MQTT-4.3.2-5]。 图 4-2 – QoS 等级 1 协议流程图,非规范示例 发送端动作控制报文接收端动作存储消息  发送 PUBLISH 报文 QoS=1, DUP=0,带报文标识符---------->   开始应用消息的后续分发 1 <----------发送 PUBACK 报文,带报文标 识符丢弃消息   1 不要求接收端在发送 PUBACK 之前完整分发应用消息。原来的发送端收到 PUBACK 报文之后, 应用消息的所有权就会转移给这个接收端。 4.3.3 QoS 2:仅分发一次 这是最高等级的服务质量, 消息丢失和重复都是不可接受的。使用这个服务质量等级会有额外的开销。 QoS 等 2 消息可变报头中有报文标识符。2.2.1节提供了有关报文标识符的更多信息。 QoS 等级 2 的 PUBLISH 报文的接收端使用一个两部确认过程来确认收到。 对于 QoS 等级 2 的分发协议,发送端 .     必须给要发送的新应用消息分配一个未使用的报文标识符 [MQTT-4.3.3- 1]。 .     发送端 PUBLISH 报文必须包含报文标识符且报文的 QoS 等于 2 ,DUP 等于 0 [MQTT-4.3.3-2]。 .     必须将这个 PUBLISH 报文看作是未确认的,直到从接收端那收到对应的 PUBREC 报文 [MQTT- 4.3.3-3]。4.4节有一个关于未确认消息的讨论。 .     收到发送端发送的包含原因码小于 0x80 的 PUBREC 报文后必须发送一个 PUBREL 报文。 PUBREL 报文必须包含与原始 PUBLISH 报文相同的报文标识符 [MQTT-4.3.3-4]。 .     必须将这个 PUBREL 报文看作是未确认的,直到从接收端那收到对应的 PUBCOMP 报文 [MQTT- 4.3.3-5]。 .     一旦发送了对应的 PUBREL 报文就不能重发这个 PUBLISH 报文 [MQTT-4.3.3-6]。 .     如果 PUBLISH 报文已发送,不能应用消息过期属性 [MQTT-4.3.3-7]。 一旦发送端收到包含原因码大于 0x80 的 PUBCOMP 报文,这个报文标识符就可以重用。 注意:允许发送端在等待确认时使用不同的报文标识符发送后续的 PUBLISH 报文,受制于4.9节描述的 流量控制。 对于 QoS 等级 2 的分发协议,接收端 . . . 响应的 PUBREC 报文必须包含报文标识符,这个标识符来自接收到的、已经接受所有权的 PUBLISH 报文 如果接收端发送了包含原因码大于等于 0x80 的 PUBREC 报文, 它必须将后续包含相同报文标识 符的 PUBLISH 报文当做是新的应用消息 [MQTT-4.3.3-9]。 10]。 .     必须发送包含与 PUBREL 相同报文标识符的 PUBCOMP 报文作为对 PUBREL 报文的响应 [MQTT-4.3.3- 11]。 .     发送 PUBCOMP 报文之后,接收端必须将后续包含相同报文标识符的 PUBLISH 报文当做是新的 应用消息 [MQTT-4.3.3- 12]。 .     必须继续 QoS 等级 2 确认序列,即使它已经应用了消息过期属性 [MQTT-4.3.3- 13]。 4.4 消息分发重试 如果收到包含原因码大于等于 0x80 的 PUBACK 或 PUBREC,则对应的 PUBLISH 报文被看作已确认,且 不能被重传 [MQTT-4.4.0-2]。 图 4-3 – QoS 等级 2 协议流程图,非规范示例 发送端动作控制报文接收端行为存储消息  发送 PUBLISH 报文 QoS=2, DUP=0,带报文标识符   ---------->   存储报文标识符,然后启动应用 消息的向前分发 1  发送 PUBREC 报文, 带报文标 识符和原因码 <---------- 丢弃消息,存储 PUBREC 中的 报文标识符  发送 PUBREL 报文, 带报文标 识符   ---------->   丢弃报文标识符  发送 PUBCOMP 报文, 带报文 标识符 <---------- 丢弃已保存的状态   1 不要求接收端在发送 PUBREC 和 PUBCOMP 之前完整分发应用消息。原始发送端收到 PUBREC 报文之后,应用消息的所有权就会转移给这个接收端。然而,接收端需要在接受所有权之前执行对 所有可能导致转发失败(例如超出配额、权限等) 的条件的检查。接收端在 PUBREC 中使用适当  的原因码指示所有权接受成功或失败。 4.5 消息收到 当服务端接受入站应用消息的所有权时, 它必须将消息添加到订阅匹配的客户端的会话状态中 [MQTT- 4.5.0- 1]。匹配规则定义见4.7节 。 正常情况下,客户端收到的消息是对他们创建的订阅的响应。客户端也可能收到不是与它的订阅精确匹配  的消息。如果服务端自动给客户端分配了一个订阅,可能发生这种情况。 UNSUBSCRIBE 操作正在被处理 时也可能收到消息。 客户端必须按照可用的服务质量(QoS)规则确认它收到的任何 PUBLISH 报文, 不管 它是否选择处理其包含的应用消息 [MQTT-4.5.0-2]。 4.6 消息排序 实现 4.3 节定义的协议流程时,客户端必须遵循下列规则 .     重发任何之前的 PUBLISH 报文时, 必须按原始 PUBLISH 报文的发送顺序重发(适用于 QoS 等级 1 和 QoS 等级 2 消息)  [MQTT-4.6.0- 1]。 .     必须按照对应的 PUBLISH 报文的顺序发送 PUBACK 报文(QoS 等级 1 消息)  [MQTT-4.6.0-2]。 .     必须按照对应的 PUBLISH 报文的顺序发送 PUBREC 报文(QoS 等级 2 消息)  [MQTT-4.6.0-3]。 .     必须按照对应的 PUBREC 报文的顺序发送 PUBREL 报文(QoS 等级 2 消息)  [MQTT-4.6.0-4]。 一个有序主题(Ordered Topic)是一个主题,在这个主题中,客户端可以确定从同一个客户端接收的相同   QoS 等级的消息的顺序与他们发布的顺序一致。 当服务端处理发布到有序主题的消息时,它必须按照消息    从任何给定客户端接收的顺序发送 PUBLISH 报文给消费端(对于同一主题和 QoS 等级)  [MQTT-4.6.0-5]。 这是上面列出的规则的补充。 默认情况下,服务端转发非共享订阅的消息时, 必须将每个主题都视为有序主题 [MQTT-4.6.0-6]。服务端 可以提供管理或其他机制来允许一个或多个主题不被当作有序主题。 非规范评注 上面列出的规则确保,使用 QoS 等级 1 发布和订阅的消息流,订阅者按照消息发布时的顺序收到 每条消息的最终副本,但是消息可能会重复,这可能导致在它的后继消息之后收到某个已经收到消   息的重发版本。例如, 发布者按顺序 1 ,2 ,3 ,4 发送消息,订阅者收到的顺序可能是 1 ,2 ,3 ,2, 3 ,4。 如果客户端和服务端能保证任何时刻最多有一条消息在 传输中(in-flight) (在某条消息被确认前 不发送后面的那条消息), 那么,不会有 QoS 等级 1 的消息会在它的任何后续消息之后收到。例 如,订阅者收到的顺序可能是 1 ,2 ,3 ,3 ,4,而不是 1 ,2 ,3 ,2 ,3 ,4。关于如何使用 Receive Maximum 的详细信息,参考4.9节流控。 4.7 主题名和主题过滤器 4.7.1 主题通配符 主题层级(topic level)分隔符用于将结构化引入主题名。如果存在分隔符, 它将主题名分割为多个主题层 级topic level 。 订阅的主题过滤器可以包含特殊的通配符, 允许客户端一次订阅多个主题。 主题过滤器中可以使用通配符,但是主题名不能使用通配符 [MQTT-4.7.0- 1]。 4.7.1.1 主题层级分隔符 斜杠(’/’ U+002F)用于分割主题的每个层级,为主题名提供一个分层结构。当客户端订阅指定的主题过滤 器包含两种通配符时, 主题层级分隔符就很有用了。主题层级分隔符可以出现在主题过滤器或主题名字的  任何位置。相邻的主题层次分隔符表示一个零长度的主题层级。 4.7.1.2 多层通配符 数字符号(‘#’ U+0023)是用于匹配主题中任意层级的通配符。多层通配符表示它的父级和任意数量的子 层级。 多层通配符必须单独指定,或者跟在主题层级分隔符后面。不管哪种情况, 它都必须是主题过滤器 的最后一个字符 [MQTT-4.7.1- 1]。 非规范评注 例如,如果客户端订阅主题 “sport/tennis/player1/#” ,它会收到使用下列主题名发布的消息: .     “sport/tennis/player1” .     “sport/tennis/player1/ranking .     “sport/tennis/player1/score/wimbledon” 非规范评注 .     “sport/#”也匹配单独的“sport”主题名,因为#包括它的父级。 .     “#”是有效的,会收到所有的应用消息。 .     “sport/tennis/#”也是有效的。 .     “sport/tennis#”是无效的。 .     “sport/tennis/#/ranking”是无效的。 4.7.1.3 单层通配符 加号( ‘+’ U+002B)是只能用于单个主题层级匹配的通配符。 在主题过滤器的任意层级都可以使用单层通配符, 包括第一个和最后一个层级。在使用它时,它必须占据 过滤器的整个层级 [MQTT-4.7.1-2]。可以在主题过滤器中的多个层级中使用它,也可以和多层通配符一起 使用。 非规范评注 例如, “sport/tennis/+”匹配“sport/tennis/player1”和“sport/tennis/player2”,但是不匹配 “sport/tennis/player1/ranking”。同时, 由于单层通配符只能匹配一个层级, “sport/+”不匹配“sport” 但是却匹配“sport/”。 .      “+”是有效的。 .     “+/tennis/#”是有效的。 .     “sport+”是无效的。 .     “sport/+/player1”是有效的。 .     “/finance”匹配“+/+”和“/+”,但是不匹配“+”。 4.7.2  以$开头的主题 服务端不能将$字符开头的主题名匹配通配符(#或+ )开头的主题过滤器 [MQTT-4.7.2- 1]。服务端应该阻 止客户端使用这种主题名与其他客户端交换消息。服务端实现可以将$开头的主题名用作其他目的。 非规范评注 .     $SYS/被广泛用作包含服务端特定信息或控制接口的主题的前缀。 .     应用不能使用$字符开头的主题。 非规范评注 .     订阅“#”的客户端不会收到任何发布到以$开头主题的消息。 .     订阅“+/monitor/Clients”的客户端不会收到任何发布到“$SYS/monitor/Clients”的消息。 .     订阅“$SYS/#”的客户端会收到发布到以“$SYS/”开头主题的消息。 .     订阅“$SYS/monitor/+”的客户端会收到发布到“$SYS/monitor/Clients”主题的消息。 .     如果客户端想同时接受以“$SYS/”开头主题的消息和不以$开头主题的消息, 它需要同时订阅“#” 和“$SYS/#”。 4.7.3 主题语义和用法 下列规则应用于主题名和主题过滤器: . . . . . . . 所有的主题名和主题过滤器必须至少包含一个字符 [MQTT-4.7.3- 1]。 主题名和主题过滤器是大小写敏感的。 主题名和主题过滤器可以包含空格字符。 主题名或主题过滤器以前置或后置斜杠‘/’区分。 只包含斜杠‘/’的主题名或主题过滤器是合法的。 主题名和主题过滤器不能包含空字符(Unicode U+0000)[Unicode][MQTT-4.7.3-2]。 主题名和主题过滤器是 UTF-8 编码字符串,它们不能超过 65,535 字节 [MQTT-4.7.3-3]。见1.5.4节 。 除了不能超过 UTF-8 编码字符串的长度限制之外,主题名或主题过滤器的层级数量没有其它限制。 匹配订阅时,服务端不能对主题名或主题过滤器执行任何规范化(normalization)处理, 不能修改或替换 任何未识别的字符 [MQTT-4.7.3-4]。主题过滤器中的每个非通配符层级需要逐字符匹配主题名中对应的层 级才算匹配成功。 非规范评注 使用 UTF-8 编码规则意味着,主题过滤器和主题名的比较可以通过比较编码后的 UTF-8 字节或解 码后的 Unicode 字符。 非规范评注 .     “ACCOUNTS”和“Accounts”是不同的主题名。 .     “Accounts payable”是合法的主题名。 .     “/finance”和“finance”是不同的主题名。 如果订阅的主题过滤器与消息的主题名匹配,应用消息会被发送给每一个匹配的客户端订阅。主题资源可 以是管理员在服务端预先定义好的, 也可以是服务端收到第一个订阅或使用那个主题名的应用消息时动态 添加的。服务端也可以使用一个安全组件有选择地授权客户端使用某个主题资源。 4.8 订阅 MQTT 提供两种订阅方式,共享和非共享。 非规范评注 在早期的 MQTT 版本中, 所有的订阅都是非共享的。 4.8.1 非共享订阅 非共享订阅只与创建它的会话相关联。每个订阅(Subscription)包含一个指示用于在此会话上分发消息的 主题过滤器和订阅选项。服务端负责收集与过滤器相匹配的消息,并在此会话的连接上发送这些消息。 一个会话不能有多个包含相同主题过滤器的非共享订阅,因此主题过滤器可以用作标识此会话的订阅的关 键词。 如果有多个客户端,每个客户端都拥有对某个相同主题的非共享订阅, 则每个客户端都将获得在该主题上 发布的应用消息的副本。这意味着非共享订阅不能被用于多个消费客户端的应用消息负载均衡,因为在这 种情况下,每条消息都将被传递给每一个订阅的客户端。 4.8.2 共享订阅 共享订阅可以与多个订阅会话相关联。与非共享订阅一样,它包含一个主题过滤器和订阅选项。但是,与 此主题过滤器相匹配的发布消息仅被发布到其中一个订阅会话。共享订阅在多个消费客户端并行共享处理 发布消息时是很有用的。 使用特殊样式的主题过滤器来表示共享订阅。过滤器格式如下: $share/{ShareName}/{filter} .      $share 是字符串字面量, 用来把主题过滤器标记为共享订阅主题过滤器。 .      {ShareName}是字符串, 不包含"/" ,"+"或"#"。 .      {filter}该字符串的剩余部分与非共享订阅中的主题过滤器具有相同的语法和语义。参考4.7节。 共享订阅主题过滤器必须以$share/开始,且必须包含至少一个字符长度的共享名(ShareName) [MQTT- 4.8.2- 1] 。共享名不能包含字符"/" ,"+"或"#",但必须跟在"/"字符后面。此"/"字符后面必须跟随一个主题过  滤器 [MQTT-4.8.2-2] ,如4.7节所述。 非规范评注 共享订阅在 MQTT 服务端的范围内定义, 而不是在会话中定义。共享订阅的主题过滤器包含共享 名,因此服务端可以有多个包含相同{过滤器}组件的共享订阅。通常, 应用程序使用共享名表示共 享同一个订阅的一组订阅会话。 示例: .     共享订阅"$share/consumer1/sport/tennis/+"和"$share/consumer2/sport/tennis/+"是不同的共 享订阅, 因此可以被关联到不同的会话组。它们都与非共享订阅主题"sport/tennis/+"相匹配。 如果一条消息被发布到匹配主题"sport/tennis/+" ,则消息的副本仅发送给所有订阅 "$share/consumer1/sport/tennis/+"的会话中的一个会话,也仅发送给所有订阅 "$share/consumer2/sport/tennis/+"的会话中的一个会话。更多的副本将发送给所有对 "sport/tennis/+"进行非共享订阅的客户端。 .     共享订阅"$share/consumer1//finance"匹配非共享订阅主题"/finance"。 注意, "$share/consumer1//finance"和"$share/consumer1/sport/tennis/+"是不同的共享订阅, 尽管它们有相同的共享名。它们可能在某种程度上是相关的,但拥有相同的共享名并不意味着 它们之间有某种关系。 通过 SUBSCRIBE 请求中的共享订阅主题过滤器创建共享订阅。只有一个会话订阅了某个共享订阅时,共 享订阅行为如同非共享订阅,除了: .      匹配发布消息时,不考虑"$share"和{共享名}部分。 .     第一次订阅时, 保留消息不发送给此会话。其他匹配的发布消息将发送给此会话。 一旦某个共享订阅存在,其他会话就有可能订阅了相同的共享订阅主题过滤器。新的会话作为额外的订阅 者关联到此共享订阅。保留消息不发送给此新的订阅者。后续每条与此共享订阅相匹配的应用消息被发送 到该共享订阅关联的其中一个会话。 会话可以通过发送包含某共享订阅主题过滤器的 UNSUBSCRIBE 报文来显式的将其从共享订阅中分离。会 话终止时,也将从共享订阅中分离。 共享订阅持续到至少有一个与其相关的会话(即, 会话已经对此共享订阅主题过滤器发布了成功的 SUBSCRIBE 请求,且尚未完成相应的 UNSUBSCRIBE)。当初始创建此共享订阅的会话取消订阅时, 除 非没有其他的相关会话,否则共享订阅仍然存在。共享订阅在没有被任何会话订阅时结束, 且任何相关的  未分发的消息都被删除。 共享订阅注释 .     如果有不止一个会话订阅了某个共享订阅, 服务端在消息的基础上自由的选择使用哪个会话,以及使用 什么标准来进行该选择。 .     允许不同的订阅客户端在其 SUBSCRIBE 报文中请求不同的 QoS 等级。服务端决定授予每个客户端的 最大 QoS 等级,并且允许向不同的订阅者授予不同的最大 QoS 等级。向客户端发送应用消息时,服务 端必须考虑授予客户端的 QoS 等级 [MQTT-4.8.2-3],与向订阅者发送消息相同。 .     如果服务端正在向其选中的订阅客户端发送 QoS 等级 2 的消息, 并且在分发完成之前网络中断, 服务 端必须在客户端重新连接时完成向该客户端的消息分发 [MQTT-4.8.2-4],如4.3.3节所述。如果客户 端的会话在客户端重连之前终止,服务端不能把此消息发送给其他订阅的客户端 [MQTT-4.8.2-5]。 .     如果服务端正在向其选中的订阅客户端发送 QoS 等级 1 的消息,并且服务端在收到此客户端的确认报 文之前网络中断,服务端可以等客户端重新连接之后将消息重传给客户端。如果客户端的会话在客户  端重连之前终止,服务端应该把此应用消息发送给与此共享订阅相关的另一个客户端。服务端可以在  第一个客户端断开连接时就尝试将消息发送给另一个客户端。 .     如果客户端对来自服务端的 PUBLISH 报文使用包含原因码大于等于 0x80 的 PUBACK 或 PUBREC 报 文进行响应,服务端必须丢弃应用消息而不尝试将其发送给任何其他订阅者 [MQTT-4.8.2-6]。 .     允许客户端向已订阅的共享订阅第二次发送 SUBSCRIBE 请求。比如,它可以通过这样改变其订阅请 求的 QoS 等级,或者因为它不确定以前的连接关闭之前订阅是否已完成。这不会增加共享订阅关联的 会话个数,因此会话将在其第一次发送 UNSUBSCRIBE 之后脱离此共享订阅。 .     每个共享订阅都是独立于其他共享订阅的。有可能两个共享订阅包含了重叠的过滤器。在这种情况下, 与两个共享订阅都相匹配的消息都将被它们单独处理。如果某个客户端既有共享订阅也有非共享订阅, 且某个消息与它们都相匹配,客户端将由于存在非共享订阅而接收此消息的副本, 此消息的第二个副本 将分发给此共享订阅的某个订阅者, 因此可能导致两份副本都被发送给此客户端。 4.9 流控 客户端和服务端使用接收最大值来控制接收未被确认的 PUBLISH 报文数量,如3.1.2.11.4节和3.2.2.3.2 节所述。接收最大值创建了一个发送配额, 用于限制可以在没收到 PUBACK(QoS 等级 1)或   PUBCOMP(QoS 等级 2)的情况下发送的 QoS 等级大于 0 的 PUBLISH 报文数量。 PUBACK 和 PUBCOMP 按照下述方式补充配额。 客户端或服务端必须将其初始发送配额设置为不超过接收最大值的非 0 值 [MQTT-4.9.0- 1]。 每当客户端或服务端发送了一个 QoS 等级大于 0 的 PUBLISH 报文, 它就会减少发送配额。如果发送配额 减为 0,客户端或服务端不能再发送任何 QoS 等级大于 0 的 PUBLISH 报文 [MQTT-4.9.0-2]。它可以继续 发送 QoS 为 0 的 PUBLISH 报文,也可以选择暂停发送这些报文。即使配额为 0,客户端和服务端也必须 继续处理和响应其他 MQTT 控制报文 [MQTT-4.9.0-3]。 发送配额增加 1: .     每当收到一个 PUBACK 报文或 PUBCOMP 报文, 不管 PUBACK 或 PUBCOMP 报文是否包含错 误码。 .     每次收到一个包含返回码大于等于 0x80 的 PUBREC 报文。 如果发送配额已到达初始发送配额, 则不继续增加。在初始发送配额之上尝试增加配额可能是由建立新的 网络连接后重新发送 PUBREL 数据包引起的。 关于客户端和服务端在超出最大接收值的允许的情况下发送 PUBLISH 报文的描述,参考3.3.4节。 发送配额和接收最大值的保留不跨越网络连接,每次建立新的网络连接时按照上面的描述进行初始化。它 们不是会话状态的一部分。 4.10 请求/响应 有些应用程序或标准可能希望通过 MQTT 协议运行请求/响应交互。此版本 MQTT 协议包含三个可用于此 目的的属性: . . . . 响应主题,在3.3.2.3.5节中描述 对比数据,在3.3.2.3.6节中描述 请求响应信息, 在3.1.2.11.7节中描述 响应信息,在3.2.2.3.14节中描述 以下非规范部分描述了如何使用这些属性。 客户端通过发布一个包含响应主题的应用消息来发送请求消息, 如3.3.2.3.5节所述。请求消息可以包含对 比数据属性,如3.3.2.3.6节所述。 4.10.1 基本请求响应(非规范) 请求/响应交互过程如下: 1.   MQTT 客户端(请求方) 向主题发布请求消息。请求消息是具有响应主题的应用消息。 2.    另一个 MQTT 客户端(响应方)订阅了与请求消息发布时使用的主题名相匹配的主题过滤器。结 果,它收到请求消息。可能有多个响应方订阅了此主题名,也可能没有响应方。 3.   响应方根据请求消息采取适当的操作,然后往请求消息中携带的响应主题属性中的主题名发布响 应消息。 4.   典型用法,请求放订阅了响应主题, 从而接收到响应信息。但是,其他某些客户端可能会订阅响 应主题, 因此它们也将接收和处理响应消息。与请求消息一样, 可能有多个客户端订阅了响应消 息的发送主题,也可能没有。 如果请求消息包含对比数据属性,则响应方将此属性拷贝到响应消息中,由响应消息的接收端用来将响应 消息与原始请求相关联。响应消息不包含响应主题属性。 MQTT 服务端转发请求消息中的响应主题和对比数据属性,和响应消息中的对比数据属性。服务端像处理 其他应用程序消息一样处理请求消息和响应消息。 请求放通常在发布请求消息之前订阅响应主题。如果响应消息发送时没有任何订阅者订阅了响应主题,则 响应消息将不会传递给任何客户端。 请求消息和响应消息可以具有任何 QoS 等级,并且响应方可以使用具有非 0 会话过期间隔的会话。通常使 用 QoS 等级 0 发送请求消息,并且只有在应答者正连接时才发送请求消息。但这不是必须的。 响应者可以使用共享订阅来允许响应客户端池。注意, 使用共享订阅时,不保证消息在客户端之间的分发 顺序。 请求方有责任确保它具有发布消息到请求消息的主题、并订阅响应主题属性中主题名的必要权限。响应方 有责任确保它具有订阅请求主题和发布到响应主题的权限。虽然主题授权不属于本规范, 但建议服务端实 施此类授权。 4.10.2 确定响应主题值(非规范) 请求方可以通过包括本地配置在内的任何方式来确定作为他们的响应主题的主题名。为避免不同请求方之 间的冲突,由请求方客户端使用的响应主题最好对于该客户端是唯一的。由于请求方和响应方通常都需要 对这些主题进行授权, 因此使用随机主题名称将会对授权造成挑战。 为了解决此问题,本规范在 CONNACK 报文中定义了一个名为响应信息的属性。服务端可以使用此属性指 导客户端如何选择使用的响应主题。此机制对于服务端和客户端都是可选的。连接时,客户端通过设置 CONNECT 报文中的请求响应信息属性来请求服务端发送响应信息。这会导致服务端在 CONNACK 报文中 插入响应信息属性(UTF-8 编码的字符串) 。 本规范不定义响应信息的内容,但它可以被用来传递主题树的全局唯一部分, 该部分至少在其会话的整个 生命周期内保留给该客户端。使用这种机制,可以在服务端而不是每个客户端中完成该属性的配置。 有关响应信息的定义, 参考3.1.2.11.7节 。 4.11 服务端重定向 服务端可以通过发送包含原因码为 0x9C ((临时)使用其他服务端) 或 0x9D(服务端已(永久)移动) 的 CONNACK 或 DISCONNECT 报文请求客户端使用另一台服务端, 如4.13节所述。服务端发送这些原 因码时可以包含一个服务端参考属性,用以说明客户端应该使用的服务端位置。 原因码 0x9C ((临时) 使用其他服务端) 指定客户端应该临时切换到另一台服务端。另一台服务端可能 是客户端已知的,也可能是由服务端参考所指定的。 原因码 0x9D  (服务端已(永久)移动)指定客户端应该永久切换到另一台服务端。另一台服务端可能是 客户端已知的, 也可能是由服务端参考所指定的。 服务端参考是一个 UTF-8 编码字符串,其值是一个由空格分隔开的参考列表。本规范不指定服务端参考的 格式。 非规范评注 推荐每个参考包含名称及可选的端口号。如果名称包含冒号,则名称字符串可以由方括号括起来   (ℼ[“和“]”)。由方括号括起来的名称不能包含右方括号(“]”)字符,用于表示使用冒号分隔符的 IPv6 地址。这是一个简化版的 URI 授权,如[RFC3986]所述。 非规范评注 服务端参考中的名字通常代表主机名、DNS 名[RFC1035] 、SRV 名[RFC2782]或 IP 地址。跟随 冒号分隔符的通常是十进制端口号。如果端口信息来自于 DNS(比如包含 SRV)或者使用默认端 口,则主机名后无需跟随端口号。 非规范评注 如果给出了多个服务端参考,则期望客户端选择其中一个。 非规范评注 服务端参考示例如下: myserver.xyz.org myserver.xyz.org:8883 10.10.151.22:8883 [fe80::9610:3eff:fe1c]:1883 允许服务端不发送服务端参考,允许客户端忽略服务端参考。此特性可用于负载均衡、服务端重定位和服 务端预置服务端。 4.12 增强认证 MQTT CONNECT 报文使用用户名和密码字段支持基本的网络连接认证。这些字段虽然称为简单密码认证, 但可以被用来承载其他形式的认证, 例如把密码作为令牌(Token)传递。 增强认证包含质询/响应风格的认证, 从而扩展了基本认证。它可能涉及在 CONNECT 报文之后、 CONNACK 报文之前的客户端和服务端之间 AUTH 报文交换。 服务端通过在 CONNECT 报文中添加认证方法字段来启动增强认证。此字段指定使用的认证方法。如果服 务端不支持客户端提供的认证方法, 它可以发送一个包含原因码 0x8C(无效的认证方法) 或 0x87 (未授 权)的 CONNACK 报文,如4.13节所述, 并且必须关闭网络连接 [MQTT-4.12.0- 1]。 认证方法是客户端和服务端关于认证数据中的数据和 CONNECT 报文中其他字段的含义, 以及客户端和服 务端完成认证需要交换和处理的协议。 非规范评注 认证方法通常为 SASL(Simple Authentication and Security Layer)机制,使用一个注册过的名称 便于信息交换。然而, 认证方法不限于使用已注册的 SASL 机制。 如果客户端选择的认证方法指定客户端先发送数据,客户端应该在 CONNECT 报文中包含认证数据属性。 此属性可被用来提供认证方法指定的数据, 认证数据的内容由认证方法定义。 如果服务端需要额外的信息来完成认证,它可以向客户端发送 AUTH 报文,此报文必须包含原因码 0x18 (继续认证) [MQTT-4.12.0-2]。如果认证方法需要服务端向客户端发送认证相关的数据, 这些数据在认证 数据(Authentication Data)中发送。 客户端通过发送另一个 AUTH 报文响应来自服务端的 AUTH 报文,此报文必须包含原因码 0x18(继续认 证)  [MQTT-4.12.0-3]。如果认证方法要求客户端向服务端发送认证相关的数据, 这些数据在认证数据 (Authentication Data)中发送。 客户端和服务端按需交换 AUTH 报文,直到服务端通过发送包含原因码为 0 的 CONNACK 报文接受认证为 止。如果接受认证需要向客户端发送数据, 这些数据在认证数据中发送。 客户端可以在处理过程中随时关闭连接。它可以在关闭之前发送 DISCONNECT 报文。 服务端可以在处理 过程中随时拒绝认证。它可以发送包含原因码大于等于 0x80 的 CONNACK 报文 ,如4.13节所述, 并且 必须关闭网络连接 [MQTT-4.12.0-4]。 如果初始 CONNECT 报文包含认证方法属性,则所有的 AUTH 报文和成功的 CONNACK 报文必须包含与 CONNECT 报文中相同的认证方法属性。  [MQTT-4.12.0-5]。 增强认证的实现对于客户端和服务端来说都是可选的。 如果客户端在 CONNECT 报文中没有包含认证方法,  则服务端不能发送 AUTH 报文,且不能在 CONNACK 报文中发送认证方法 [MQTT-4.12.0-6] 。如果客户端 在 CONNECT 报文中没有包含认证方法, 则客户端不能向服务端发送 AUTH 报文 [MQTT-4.12.0-7]。 如果客户端在 CONNECT 报文中没有包含认证方法, 服务端应该使用 CONNECT 报文中的信息、TLS 会 话和网络连接进行认证。 SCRAM 认证非规范示例 .     客户端到服务端:CONNECT 认证方法="SCRAM-SHA- 1",认证数据=client-first-data .     服务端到客户端:AUTH 原因码=0x18,认证方法="SCRAM-SHA- 1",认证数据=server-first- data .     客户端到服务端:AUTH 原因码=0x18,认证方法="SCRAM-SHA- 1",认证数据=client-final- data .     服务端到客户端:CONNACK 原因码=0 ,认证方法="SCRAM-SHA- 1",认证数据=server-final- data Kerberos 认证非规范示例 .     客户端到服务端:CONNECT 认证方法="GS2-KRB5" .     服务端到客户端:AUTH 原因码=0x18,认证方法="GS2-KRB5" .     客户端到服务端:AUTH 原因码=0x18,认证方法="GS2-KRB5",认证数据=initial context token .     服务端到客户端:AUTH 原因码=0x18,认证方法="GS2-KRB5",认证数据=reply context token .     客户端到服务端:AUTH 原因码=0x18,认证方法="GS2-KRB5" .     服务端到客户端:CONNACK 原因码=0,认证方法="GS2-KRB5",认证数据=outcome of authentication 4.12.1 重新认证 如果客户端在 CONNECT 报文中提供了认证方法,它可以在收到 CONNACK 报文之后的任何时间通过发  送包含原因码 0x19(重新认证)的 AUTH 报文发起重新认证。客户端必须将认证方法设置为与最初验证网 络连接时的认证方法一致 [MQTT-4.12.1- 1]。如果认证方法需要客户端先发送数据,则此 AUTH 报文包含 第一片认证数据。 服务端通过向客户端发送 AUTH 报文来响应此重新认证请求,包含原因码为 0x00 (成功) 的 AUTH 报文 指示重新认证完成,包含原因码为 0x18(继续认证)的 AUTH 报文指示需要更多的认证数据。客户端可以   通过发送包含原因码 0x18  (继续认证)的 AUTH 报文来响应附加的认证数据。此流程与原始身份验证一样, 直到重新认证完成或重新认证失败。 如果重新认证失败,客户端或服务端应该发送包含适当原因码的 DISCONNECT 报文,如4.13 节 所述。并 且必须关闭网络连接 [MQTT-4.12.1-2]。 在重新认证的过程中, 客户端和服务端的其他报文流可以继续使用之前的认证。 非规范评注 服务端可以通过拒绝重新认证来限制客户端在重新认证中尝试的更改范围。例如, 如果服务端不允 许更改用户名, 它可以使任何尝试更改用户名的重新认证都失败。 4.13 错误处理 4.13.1 无效报文和协议错误 无效报文(Malformed Packet)和协议错误(Protocol Error)的定义见1.2节术语。 这些错误案例的部分 术语贯穿本规范。客户端或服务端对其收到的 MQTT 控制报文的检查严格程度依赖: .     客户端或服务端实现的大小。 .     实现支持的性能。 .     接收端对发送端发送的 MQTT 控制报文的信任程度。 .     接收端对用于分发 MQTT 控制报文的网络的信任程度。 .     继续处理错误报文的的后果。 如果发送端遵守此规范,它将不会发送无效报文或导致协议错误。然而,如果客户端在收到 CONNACK 报 文之前发送 MQTT 控制报文,它可能会因为错误的估计了服务端的性能而导致协议错误。参考3.1.4节 CONNECT 行为。 无效报文和协议错误使用的原因码包括: .     0x81            无效报文 .     0x82            协议错误 .     0x93            超过接收最大值 .     0x95            报文过大 .     0x9A            不支持保留 .     0x9B            不支持的 QoS 等级 .     0x9E            不支持共享订阅 .     0xA1           不支持订阅标识符 .     0xA2           不支持通配符订阅 当客户端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时, 它应该关闭网络连接。在 AUTH 报文出错的情况下它可以在关闭网络连接之前发送包含原因码的 DISCONNECT 报文。在其他报文  出错的情况下它应该在关闭网络连接之前发送包含原因码的 DISCONNECT 报文。使用原因码 0x81 (错误 报文)或 0x82(协议错误),除非包含3.14.2.1断开原因码中定义的更具体的原因码。 当服务端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时, 它必须关闭网络连接 [MQTT- 4.13.1- 1]。在 CONNECT 报文出错的情况下它可以在关闭网络连接之前发送包含原因码的 CONNACK 报 文。 在其他报文出错的情况下它应该在关闭网络连接之前发送包含原因码的 DISCONNECT 报文。使用原 因码 0x81 (无效报文)或 0x82(协议错误) ,除非包含3.2.2.2 节 - 连接原因码或3.14.2.1 节 – 断开原因 码中定义的更具体的原因码。对其他会话没有影响。 如果服务端或客户端省略了检查 MQTT 控制报文的某些特性, 它可能无法检测到某个错误,因此可能会导 致数据被损坏。 4.13.2 其他错误 发送端无法预料到无效报文和协议错误以外的错误,因为它可能有某些没有告知发送端的约束。客户端或 服务端可能在接收时遇到短暂的错误,比如内存不足, 导致无法成功的处理某个 MQTT 控制报文。 包含原因码大于等于 0x80 的确认报文 PUBACK ,PUBREC ,PUBREL ,PUBCOMP ,SUBACK , UNSUBACK 表明收到了某个报文标识符的报文出错。 这不会影响其他会话或此会话上的其他报文。 CONNACK 报文和 DISCONNECT 报文允许使用大于等于 0x80 的原因码以指示网络连接将被关闭。如果 某个大于等于 0x80 的原因码被指定,无论是否发送 CONNACK 报文或 DISCONNECT 报文, 必须关闭网 络连接 [MQTT-4.13.2- 1]。发送这些原因码不会影响任何其他会话。 如果控制报文包含多个错误,接收端可以按照任意顺序对报文进行验证,并对发现的任何错误采取适当的 行为。 5  安全(非规范) 5.1 概述 强烈建议提供 TLS[RFC5246]的服务端实现使用 TCP 端口 8883(IANA 服务名:secure-mqtt)。 安全是一个快速变化的领域,所以在设计安全解决方案时总是使用最新的建议。 解决方案需要考虑的风险包括: .     设备可能会被盗用 .     客户端和服务端的静态数据可能是可访问的(可能会被修改) .     协议行为可能有副作用(如计时器攻击) .     拒绝服务(DoS)攻击 .     通信可能会被拦截、修改、重定向或泄露 .     虚假 MQTT 控制报文注入 MQTT 方案通常部署在不安全的通信环境中。在这种情况下,协议实现通常需要提供这些机制: .     用户和设备身份认证 .     服务端资源访问授权 .     MQTT 控制报文和内嵌应用数据的完整性校验 .     MQTT 控制报文和内嵌应用数据的隐私控制 作为传输层协议,MQTT 仅关注消息传输, 提供合适的安全功能是实现者的责任。使用 TLS[RFC5246]是 比较普遍的选择。 除了技术上的安全问题外, 还有地区因素(例如美国欧盟隐私盾框架[USEUPRIVSH]) ,行业标准(例如   第三方支付行业数据安全标准 [PCIDSS]) ,监管方面的考虑(例如萨斯班-奥克斯利法案[SARBANES])。 5.2 MQTT 解决方案: 安全和认证 协议实现可能需要提供符合特定行业安全标准,如 NIST 网络安全框架[NISTCSF] ,第三方支付行业数据 安全标准[PCIDSS] ,美国联邦信息处理标准[FIPS1402]和 NSA 加密组合 B[NSAB]。 在 MQTT 的补充出版物(MQTT and the NIST Framework for Improving Critical Infrastructure Cybersecurity[MQTTNIST])中可以找到在 NIST 网络安全框架[NISTCSF]中使用 MQTT 的指导。使用行 业证明、独立审计和认证技术有助于满足合规要求。 5.3 轻量级的加密与受限设备 广泛采用的加密算法是高级加密标准[AES]。对 AES 提供了硬件支持的处理器有很多,但通常不包含嵌入 式处理器。加密算法 ChaCha20 [CHACHA20] 软件加解密速度快很多,但不像 AES 那样广泛可用。 推荐使用为资源受限的低端设备特别优化过的轻量级加密国际标准 ISO 29192[ISO29192] 。 5.4 实现注意事项 实现或使用 MQTT 时需要考虑许多安全问题。以下章节不应被视为核对清单。 协议实现时可以实现下面的一部分或全部: 5.4.1 客户端身份认证 CONNECT 报文包含用户名和密码字段。实现可以决定如何使用这些字段的内容。实现者可以提供自己的 身份验证机制, 或者使用外部的认证系统如 LDAP[RFC4511]或 Auth[RFC6749],还可以利用操作系统 的认证机制。 MQTT v5.0 提供了一种增强认证机制,如4.12节所述。使用此机制需要客户端和服务端双方的支持。 实现可以明文传递认证数据,混淆数据元素,或者不要求任何认证数据,但应该意识到这会增加中间人攻 击和重放攻击的风险。 5.4.5节介绍了确保数据私密的方法。 在客户端和服务端之间使用虚拟专用网(VPN)可以确保数据只被授权的客户端收到。 使用 TLS[RFC5246]时, 服务端可以使用客户端发送的 TLS 证书验证客户端的身份。 实现可以允许客户端通过应用消息给服务端发送用于身份验证的凭证。 5.4.2 客户端授权 如果客户端已经成功通过身份认证, 服务端实现需要在接受连接之前执行授权检查。 授权可以基于客户端提供的信息如用户名, 客户端主机名/IP 地址,或认证机制的结果。 具体来说,实现应该检查客户端是否被授权使用此客户标识符, 因为客户标识符提供了对 MQTT 会话状态 的访问(如4.1节所述) 。此授权检查是为了防止某个客户端偶然或恶意的使用了已被其他客户端所使用 的客户标识符。 实现应该提供发生在 CONNECT 之后的访问控制以限制客户端发布消息到特定主体或使用特定主体过滤器 进行订阅的能力。实现需要考虑对具有广泛作用域的主题过滤器的访问限制, 如"#"主题过滤器。 5.4.3 服务端身份认证 MQTT 协议不是双向信任的。基本认证没有提供客户端验证服务端身份的机制。某些形式的扩展认证允许 双向认证。 但是使用 TLS[RFC5246]时,客户端可以使用服务端发送的 TLS 证书验证服务端的身份。从单 IP 多域名 提供 MQTT 服务的实现应该考虑[RFC6066]第 3 节定义的 TLS 的 SNI 扩展。SNI 允许客户端告诉服务端 它要连接的服务端主机名。 实现可以允许服务端通过应用消息给客户端发送凭证用于身份验证。 MQTT v5.0 提供了一种增强的认证机 制,如4.12节所述,它可以被客户端用于验证服务端。使用此机制需要客户端和服务端双方的支持。 在客户端和服务端之间使用虚拟专用网(VPN)可以确保客户端正连接的是预期的服务端。 5.4.4 应用消息和 MQTT 控制报文的完整性 应用可以在应用消息中单独包含哈希值。这样做可以为 PUBLISH 报文的网络传输和静态数据提供内容的完 整性检查。 TLS[RFC5246]提供了对网络传输的数据做完整性校验的哈希算法。 在客户端和服务端之间使用虚拟专用网(VPN)连接可以在 VPN 覆盖的网络段提供数据完整性检查。 5.4.5 应用消息和 MQTT 控制报文的保密性 TLS[RFC5246]可以对网络传输的数据加密。如果有效的 TLS 密码组合包含的加密算法为 NULL,那么它 不会加密数据。要确保客户端和服务端的保密,应避免使用这些密码组合。 应用可以单独加密应用消息的内容。这可以提供应用消息传输途中和静态数据的私密性。但不能给应用消 息的其它属性如主题名加密。 客户端和服务端实现可以加密存储静态数据,例如可以将应用消息作为会话的一部分存储。 在客户端和服务端之间使用虚拟专用网(VPN)连接可以在 VPN 覆盖的网络段保证数据的私密性。 5.4.6  消息传输的不可否认性 应用设计者可能需要考虑适当的策略,以实现端到端的不可否认性(non-repudiation)。 5.4.7 客户端和服务端盗用检测 使用 TLS[RFC5246]的客户端和服务端实现应该能够确保,初始化 TLS 连接时提供的 SSL 证书是与主机 名(客户端要连接的或服务端将被连接的) 关联的。 使用 TLS[RFC5246]的客户端和服务端实现,可以选择提供检查证书吊销列表(CRLs [RFC5280])和在 线整数状态协议(OSCP)[RFC6960]的功能, 拒绝使用被吊销的整数。 物理部署可以将防篡改硬件与应用消息的特殊数据传输结合。例如, 一个仪表可能会内置一个 GPS 以确保 没有在未授权的地区使用。 IEEE 安全设备认证[IEEE8021AR]就是用于实现这个机制的一个标准, 它使用 加密绑定标识符验证设备身份。 5.4.8 异常行为检测 服务端实现可以监视客户端的行为, 检测潜在的安全风险。 例如: .     重复的连接请求 .     重复的身份验证请求 .     连接的异常终止 .     主题扫描(请求发送或订阅大量主题) .     发送无法送达的消息(没有订阅者的主题) .     客户端连接但是不发送数据 发现违反安全规则的行为, 服务端实现可以关闭客户端的网络连接。 服务端实现检测不受欢迎的行为,可以基于 IP 地址或客户标识符实现一个动态黑名单列表。 服务部署可以使用网络层次控制(如果可用)实现基于 IP 地址或其它信息的速率限制或黑名单。 5.4.9 其它安全注意事项 如果客户端或服务端的 TLS 证书丢失,或者我们考虑证书被盗用或者被吊销(利用 CRLs[RFC5280]和 OSCP[RFC6960])的情况。 客户端或服务端验证凭证时,如果发现用户名和密码丢失或被盗用,应该吊销或者重新发放。 在使用长连接时: .     客户端和服务端使用 TLS[RFC5246]时应该允许重新协商会话以确认新的加密参数(替换会话密钥, 更换密码组合, 更换认证凭证)。 .     服务端可以关闭客户端的网络连接, 并要求他们使用新的凭证重新验证身份。 .     服务端可以要求客户端使用4.12.1节中描述的机制周期性的进行重新认证。 资源受限设备或使用受限网络的客户端可以使用 TLS[RFC5246]会话恢复,以降低 TLS[RFC5246]会话 重连的成本。 连接到服务端的客户端与其它连接到服务端的客户端之间有一个信任传递关系,它们都有权在同一个主题 上发布消息。 5.4.10 使用 SOCK 代理 客户端实现应该意识到某些环境要求使用 SOCKSv5[RFC1928]代理创建出站的网络连接。某些 MQTT 实 现可以利用安全隧道(如 SSH)通过 SOCKS 代理。一个实现决定支持 SOCKS 时,它们应该同时支持匿 名的和用户名密码验证的 SOCKS 代理。对于后一种情况,实现应该意识到 SOCKS 可能使用明文认证, 因此应该避免使用相同的凭证连接 MQTT 服务器。 5.4.11 安全配置文件 实现者和方案设计者可能希望将安全当作配置文件集合应用到 MQTT 协议中。下面描述的是一个分层的安 全等级结构。 5.4.11.1 开放通信配置 使用开放通信配置时, MQTT 协议运行在一个没有内置额外安全通信机制的开放网络上。 5.4.11.2 安全网络通信配置 使用安全网络通信配置时, MQTT 协议运行在有安全控制的物理或虚拟网络上,如 VPN 或物理安全网络。 5.4.11.3 安全传输配置 使用安全传输配置时, MQTT 协议运行在使用 TLS[RFC5246]的物理或虚拟网络上,它提供了身份认证, 完整性和保密性。 使用内置的用户名称和密码字段, TLS[RFC5246]客户端身份认证可被用于(或者替代) MQTT 客户端认 证。 5.4.11.4 工业标准的安全配置 可以预料的是, MQTT 协议被设计为支持很多工业标准的应用配置,每一种定义一个威胁模型和用于定位 威胁的特殊安全机制。特殊的安全机制推荐从下面的方案中选择: [NISTCSF] NIST 网络安全框架 [NIST7628] NISTIR 7628 智能电网网络安全指南 [FIPS1402](FIPS PUB 140-2)加密模块的安全要求 [PCIDSS] PCI-DSS 第三方支付行业数据安全标准 [NSAB] NSA 加密组合 B 6  使用 WebSocket 作为网络层 如果 MQTT 在 WebSocket[RFC6455]连接上传输, 要满足下面的条件: .     MQTT 控制报文必须使用 WebSocket 二进制数据帧发送。如果收到任何其它类型的数据帧,接收者必 须关闭网络连接 [MQTT-6.0.0- 1]。 .     单个 WebSocket 数据帧可以包含多个或者部分 MQTT 报文。接收者不能假设 MQTT 控制报文按 WebSocket 帧边界对齐 [MQTT-6.0.0-2]。 .     客户端必须将字符串"mqtt"包含在它提供的 WebSocket 子协议列表里 [MQTT-6.0.0-3]。 .     服务端选择和返回的 WebSocket 子协议名必须是"mqtt" [MQTT-6.0.0-4]。 .     用于连接客户端和服务器的 WebSocket URI 对 MQTT 协议没有任何影响。 6.1  IANA 注意事项 本规范请求 IANA 修改“WebSocket 子协议名”条目下 MQTT 子协议注册信息为下列数据: 图 6- 1 - IANA WebSocket 标识符 子协议标识符mqtt子协议通用名mqtt子协议定义http://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html 7  一致性 MQTT 规范定义了 MQTT 客户端实现和 MQTT 服务端实现的一致性要求。 MQTT 实现可以同时作为 MQTT 客户端和 MQTT 服务端。 7.1 一致性条款 7.1.1 MQTT 服务端一致性条款 服务端的定义, 参考术语章节的服务端(Server)部分。 MQTT 服务端只有满足下面所有的要求才算是符合本规范: 1. 2. 3. 4. 服务端发送的所有 MQTT控制报文的格式符合第二章和第三章描述的格式。 遵守4.7节描述的主题匹配规则和4.8节匹配的订阅规则。 满足下列章节中所有必须级别的要求,明确仅适用于对客户端的除外: .    第一章 - 介绍 .    第二章 - MQTT 控制报文格式 .    第三章 - MQTT 控制报文 .    第四章 - 操作行为 .    第六章 - 使用 WebSocket 作为网络层 为了能够与任何其他一致的(MQTT)实现进行互操作,无需使用在规范之外定义的任何扩展。 7.1.2 MQTT 客户端一致性条款 客户端的定义, 参考术语章节的客户端(Client)部分。 MQTT 客户端只有满足下面所有的要求才算是符合本规范: 1.   客户端发送端所有 MQTT控制报文的格式符合第二章和第三章描述的格式。 2.   满足下列章节中所有必须级别的要求,明确仅适用于对服务端的除外: .    第一章 - 介绍 .    第二章 - MQTT 控制报文格式 .    第三章 - MQTT 控制报文 .    第四章 - 操作行为 .    第六章 - 使用 WebSocket 作为网络层 3.   为了能够与任何其他一致的(MQTT)实现进行互操作,无需使用在规范之外定义的任何扩展。 Appendix A. 致谢 技术委员会特别感谢 Andy Stanford-Clark 博士和 Arlen Nipper 博士作为 MQTT 协议的原始发明者以及他 们对标准化过程的持续支持。 以下成员在本规范制定期间为 OASIS 技术委员会成员,他们的贡献值得感谢: 参与者: .     Senthil Nathan Balasubramaniam (Infiswift) .     Dr. Andrew Banks, editor (IBM) .     Ken Borgendale, editor (IBM) .     Ed Briggs, editor (Microsoft) .     Raphael Cohn (Individual) .     Richard Coppen, chairman (IBM) .     William Cox (Individual) .      Ian Craggs , secretary (IBM) .     Konstantin Dotchkoff (Microsoft) .     Derek Fu (IBM) .     Rahul Gupta, editor (IBM) .     Stefan Hagen (Individual) .     David Horton (Solace Systems) .     Alex Kritikos (Software AG, Inc.) .     Jonathan Levell (IBM) .     Shawn McAllister (Solace Systems) .     William McLane (TIBCO Software Inc.) .     Peter Niblett (IBM) .     Dominik Obermaier (dc-square GmbH) .     Nicholas O'Leary (IBM) .     Brian Raymor, chairman (Microsoft) .     Andrew Schofield (IBM) .     Tobias Sommer (Cumulocity) .     Joe Speed (IBM) .     Dr Andy Stanford-Clark (IBM) .     Allan Stockdill-Mander (IBM) .     Stehan Vaillant (Cumulocity) 有关对早期版本 MQTT 协议做出贡献的人员列表,参考 MQTT v3.1.1 规范中的附录 A[MQTTV311]。 Appendix B. 强制性规范声明(非规范) 此附录是非规范性的, 只作为本文档正文中可以找到的大量一致性声明的摘要提供。参考第七章一致性要 求限制列表。 规范声明序号规范声明[MQTT- 1.5.4- 1]UTF-8 编码字符串中的数据必须是按照 [Unicode] 规范定义的, 在 RFC 3629 [RFC3629]    中重申的有效的 UTF-8 格式。特别需要指出的是,这些数据不能包含字符码在 U+D800 和 U+DFFF 之间的数据。[MQTT- 1.5.4-2]UTF-8 编码的字符串不能包含空字符 U+0000。[MQTT- 1.5.4-3]UTF-8 编码序列 0xEF 0xBB 0xBF 总是被解释为 U+FEFF ("零宽度非换行空白字符") ,无 论它出现在字符串的什么位置,报文接收者都不能跳过或者剥离它。[MQTT- 1.5.5- 1]编码值必须使用表示该值所需的最少字节数。[MQTT- 1.5.7- 1]所有的字符串都必须符合 UTF-8 编码字符串的要求。[MQTT-2.1.3- 1]如果标记位被标记为“保留” ,则保留它以供将来使用, 并且必须设置为所列出的值。[MQTT-2.2.1-2]QoS 等级为 0 的 PUBLISH 报文不能包含报文标识符。[MQTT-2.2.1-3]客户端每次发送新的 SUBSCRIBE ,UNSUBSCRIBE 或 PUBLISH(当 QoS 等级>0) MQTT 控制报文时, 它必须为其分配一个当前未被使用的非 0 报文标识符。[MQTT-2.2.1-4]服务端每次发送新的 PUBLISH(当 QoS 等级>0)MQTT 控制报文时, 它必须为其分配一 个当前未被使用的非 0 报文标识符。[MQTT-2.2.1-5]PUBACK ,PUBREC ,PUBREL 或 PUBCOMP 报文必须包含 PUBLISH 报文中发送的原 始报文标识符。[MQTT-2.2.1-6]SUBACK 和 UNSUBACK 报文必须包含相应的 SUBSCRIBE 和 UNSUBSCRIBE 报文中使 用的报文标识符。[MQTT-2.2.2- 1]如果没有属性, 属性长度必须为 0。[MQTT-3.1.0- 1]客户端到服务端的网络连接建立后, 客户端发送给服务端的第一个报文必须是 CONNECT 报文。[MQTT-3.1.0-2]当协议错误并关闭网络连接时,服务端必须处理客户端发送的第二个 CONNECT 报文。[MQTT-3.1.2- 1]协议名必须是 UTF-8 字符串"MQTT"。如果服务端不想接受 CONNECT,并希望透露它是 MQTT 服务端,它可以发送一个包含原因码为 0x84(不支持的协议版本)的 CONNACK  报文,然后必须关闭网络连接。 [MQTT-3.1.2-2]如果协议版本不为 5,且服务端不想接受 CONNECT 报文,则服务端可以发送一个包含原 因码为 0x84(不支持的协议版本) 的 CONNACK 报文,然后必须关闭网络连接。[MQTT-3.1.2-3]服务端必须验证 CONNECT 报文的保留标志位(第 0 位)是否为 0。[MQTT-3.1.2-4]如果 CONNECT 报文的新开始标志被设置为 1,则客户端和服务端必须丢弃任何已存在的 会话并开始一个新的会话。[MQTT-3.1.2-5]如果 CONNECT 报文的新开始标志被设置为 0,并且存在与该客户标识符相关联的会话, 服务端必须基于此会话恢复与客户端的通信。[MQTT-3.1.2-6]如果 CONNECT 报文的新开始标志被设置为 0,并且不存在与该客户标识符相关联的会 话,则服务端必须创建一个新的会话。[MQTT-3.1.2-7]遗嘱标志被设置为 1,表示遗嘱消息必须被存储在服务端并与会话相关联。[MQTT-3.1.2-8]在网络连接被关闭且遗嘱延时间隔已过或会话结束时遗嘱消息必须被发布,除非遗嘱消息  被服务端在收到包含原因码为 0x00(正常关闭)的 DISCONNECT 报文后删除或关于此客 户标识符的一个新的网络连接在遗嘱消息间隔过期之前被打开。[MQTT-3.1.2-9]如果遗嘱标志被设置为 0,连接标志中的遗嘱 QoS 等级和遗嘱保留字段将会被服务端使 用,遗嘱属性、遗嘱主题和遗嘱消息字段必须存在于载荷中。[MQTT-3.1.2- 10]一旦遗嘱消息被发布或者服务端收到包含原因码为 0x00(正常关闭) 的 DISCONNECT 报 文,遗嘱消息必须从服务端的会话中删除。[MQTT-3.1.2- 11]如果遗嘱标志设置为 0,遗嘱 QoS 等级必须也设置为 0 (0x00)。[MQTT-3.1.2- 12]如果遗嘱标志设置为 1,遗嘱 QoS 等级可以被设置为 0(0x00), 1(0x01)或 2 (0x02)。[MQTT-3.1.2- 13]如果遗嘱标志被设置为 0,遗嘱保留标志也必须设置为 0。[MQTT-3.1.2- 14]如果遗嘱标志被设置为 1 时,如果遗嘱保留被设置为 0,则服务端必须将遗嘱消息当做非 保留消息发布。[MQTT-3.1.2- 15]如果遗嘱保留被设置为 1,则服务端必须将遗嘱消息当做保留消息发布。[MQTT-3.1.2- 16]如果用户名标志被设置为 0,有效载荷中不能包含用户名字段。[MQTT-3.1.2- 17]如果用户名标志被设置为 0,有效载荷中必须包含用户名字段。[MQTT-3.1.2- 18]如果密码标志被设置为 0,有效载荷中不能包含密码字段。[MQTT-3.1.2- 19]如果密码标志被设置为 1,有效载荷中必须包含密码字段。[MQTT-3.1.2-20]如果保持连接值不为 0,且没有任何其它的 MQTT 控制报文可以发送,客户端必须发送一 个 PINGREQ 报文。 [MQTT-3.1.2-21]如果服务端返回的 CONNACK 报文中包含服务端保持连接,客户端必须使用此值代替其发 送的保持连接。[MQTT-3.1.2-22]如果保持连接的值非零,并且服务端在 1.5 倍的保持连接时间内没有收到客户端的 MQTT 控制报文,它必须断开客户端的网络连接, 并判定网络连接已断开。[MQTT-3.1.2-23]如果网络连接关闭时会话过期间隔大于 0,则客户端与服务端必须存储会话状态。[MQTT-3.1.2-24]服务端不能发送超过最大报文长度的报文给客户端。[MQTT-3.1.2-25]当报文过大而不能发送时, 服务端必须丢弃这些报文,然后当做应用消息发送已完成处 理。[MQTT-3.1.2-26]服务端在一个 PUBLISH 报文中发送的主题别名不能超过客户端设置的主题别名最大值。[MQTT-3.1.2-27]如果主题别名最大值没有设置,或者设置为零,则服务端不能向此客户端发送任何主题别 名。[MQTT-3.1.2-28]请求响应信息值为 0,表示服务端不能返回响应信息。[MQTT-3.1.2-29]如果请求问题信息的值为 0,服务端可以选择在 CONNACK 或 DISCONNECT 报文中返回 原因字符串或用户属性,但不能在除 PUBLISH ,CONNACK 或 DISCONNECT 之外的报  文中发送原因字符串或用户属性。[MQTT-3.1.2-30]如果客户端在 CONNECT 报文中设置了认证方法,则客户端在收到 CONNACK 报文之前 不能发送除 AUTH 或 DISCONNECT 之外的报文。[MQTT-3.1.3- 1]CONNECT 报文的载荷中包含由可变报头中的标志确定的一个或多个以长度为前缀的字  段。这些字段若存在, 必须按照客户标识符、遗嘱属性、遗嘱主题、遗嘱载荷、用户名、 密码的顺序出现。[MQTT-3.1.3-2]客户端和服务端都必须使用客户标识符识别两者之间的 MQTT 会话相关的状态。[MQTT-3.1.3-3]客户标识符必须存在,且作为 CONNECT 报文载荷的第一个字段出现。[MQTT-3.1.3-4]客户标识符必须被编码为 UTF-8 字符串。[MQTT-3.1.3-5]服务端必须允许 1 到 23 个字节长的 UTF-8 编码的客户标识符,客户标识符只能包含这些 字符:"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[MQTT-3.1.3-6]服务端可以允许客户端提供一个零字节的客户标识符, 如果这样做了, 服务端必须将这看 作特殊情况并分配唯一的客户标识符给那个客户端。[MQTT-3.1.3-7]服务端必须假设客户端提供了那个唯一的客户标识符, 且必须在 CONNACK 报文中返回分 配的客户标识符。 [MQTT-3.1.3-8]如果服务端拒绝了某个客户标识符, 它可以发送包含原因码 0x85 (客户标识符无效)的CONNACK 报文作为对客户端的 CONNECT 报文的回应 ,如 4.13 节所述。之后必须关闭 网络连接。[MQTT-3.1.3-9]如果某个会话在遗嘱延时间隔到期之前创建了新的网络连接,则服务端不能发送遗嘱消 息。[MQTT-3.1.3- 10]服务端在发布遗嘱消息时必须维护用户属性的顺序。[MQTT-3.1.3- 11]遗嘱主题必须为 UTF-8 编码的字符串。[MQTT-3.1.3- 12]如果用户名标志被设置为 1,用户名为载荷中下一个字段。用户名必须是 UTF-8 编码字符 串。[MQTT-3.1.4- 1]服务端必须按照 3.1 节的要求验证 CONNECT 报文, 如果报文不符合规范, 服务端关闭网 络连接。[MQTT-3.1.4-2]服务端可以检查 CONNECT 报文的内容是不是满足任何进一步的限制,应该执行身份验证 和授权检查。如果任何一项检查没通过,服务端必须关闭网络连接。[MQTT-3.1.4-3]如果客户标识符所代表的客户端已经连接到此服务端, 那么向原有的客户端发送一个包含 原因码为 0x8E(会话被接管)的 DISCONNECT 报文,并且必须关闭原有的网络连接。[MQTT-3.1.4-4]服务端必须对新开始标志进行处理。[MQTT-3.1.4-5]服务端必须使用包含原因码为 0x00(成功)的 CONNACK 报文对客户端的 CONNECT 报 文进行确认。[MQTT-3.1.4-6]如果服务端拒绝了 CONNECT 报文,它不能处理客户端在 CONNECT 报文之后发送的任 何除 AUTH 以外的报文。[MQTT-3.2.0- 1]服务端在发送任何除 AUTH 以外的报文之前必须先发送包含原因码为 0x00(成功)的 CONNACK 报文。[MQTT-3.2.0-2]服务端在一次网络连接中不能发送多个 CONNACK 报文。[MQTT-3.2.2- 1]第 1 个字节是连接确认标志,位 7- 1 是保留位且必须设置为 0。[MQTT-3.2.2-2]如果服务端接受一个新开始为 1 的连接, 服务端在 CONNACK 报文中除了把原因码设置为 0x00(成功)之外,还必须把会话存在标志设置为 0。[MQTT-3.2.2-3]如果服务端接受一个新开始为 0 的连接, 并且服务端已经保存了此客户标识符的会话状态,服务端在 CONNACK 报文中必须把会话存在标志设置为 1。否则,服务端必须把会话 存在标志设置为 0。无论如何,服务端在 CONNACK 报文中必须把原因码设置为 0x00(成功) 。[MQTT-3.2.2-4]如果客户端没有保存的会话状态,但收到会话存在标志为 1,客户端必须关闭网络连接。[MQTT-3.2.2-5]如果客户端保存了会话状态,但收到的会话存在标志为 0,客户端若要继续此网络连接, 它必须丢弃其保存的会话状态。 [MQTT-3.2.2-6]如果服务端发送的 CONNACK 报文中原因码非 0,它必须把会话存在标志设置为 0。[MQTT-3.2.2-7]如果服务端发送了一个包含原因码大于等于 128 的 CONNACK 报文,它随后必须关闭网 络连接。[MQTT-3.2.2-8]服务端发送的 CONNACK 报文必须设置一种原因码。[MQTT-3.2.2-9]如果服务端不支持 Qos 为 1 或 2 的 PUBLISH 报文, 服务端必须在 CONNACK 报文中发送 最大服务质量以指定其支持的最大 QoS 值。[MQTT-3.2.2- 10]即使不支持 QoS 为 1 或 2 的 PUBLISH 报文, 服务端也必须接受请求 QoS 为 0 、1 或 2 的 SUBSCRIBE 报文。[MQTT-3.2.2- 11]如果从服务端接收到了最大 QoS 等级, 则客户端不能发送超过最大 QoS 等级所指定的 QoS 等级的 PUBLISH 报文。[MQTT-3.2.2- 12]如果服务端收到包含遗嘱的 QoS 超过服务端处理能力的 CONNECT 报文,服务端必须拒  绝此连接。服务端应该使用包含原因码为 0x9B(不支持的 QoS 等级)的 CONNACK 报文 进行错误处理, 随后必须关闭网络连接。[MQTT-3.2.2- 13]如果服务端收到一个包含保留标志位 1 的遗嘱消息的 CONNECT 报文且服务端不支持保留消息,服务端必须拒绝此连接请求, 且应该发送包含原因码为 0x9A(不支持保留)的 CONNACK 报文,随后必须关闭网络连接。[MQTT-3.2.2- 14]从服务端接收到的保留可用标志为 0 时, 客户端不能发送保留标志设置为 1 的 PUBLISH 报文。[MQTT-3.2.2- 15]客户端不应该发送超过最大报文长度的报文给服务端。[MQTT-3.2.2- 16]如果客户端使用长度为 0 的客户标识符,服务端必须回复包含分配客户标识符的CONNACK 报文。分配客户标识符必须是没有被服务端的其他会话所使用的新客户标识 符。[MQTT-3.2.2- 17]客户端在一个 PUBLISH 报文中发送的主题别名值不能超过服务端设置的主题别名最大 值。[MQTT-3.2.2- 18]如果主题别名最大值没有设置,或者设置为 0,则客户端不能向此服务端发送任何主题别 名。[MQTT-3.2.2- 19]如果加上原因字符串之后的 CONNACK 报文长度超出了客户端指定的最大报文长度,则服 务端不能发送此原因字符串。[MQTT-3.2.2-20]如果加上用户属性之后的 CONNACK 报文长度超出了客户端指定的最大报文长度,则服务 端不能发送此属性。[MQTT-3.2.2-21]如果服务端发送了服务端保持连接属性,客户端必须使用此值代替其在 CONNECT 报文中 发送的保持连接时间值。[MQTT-3.2.2-22]如果服务端没有发送服务端保持连接属性, 服务端必须使用客户端在 CONNECT 报文中设 置的保持连接时间值。 [MQTT-3.3.1- 1]客户端或服务端请求重发一个 PUBLISH 报文时,必须将 DUP 标志设置为 1。[MQTT-3.3.1-2]对于 QoS 为 0 的消息, DUP 标志必须设置为 0。[MQTT-3.3.1-3]发送(出站)的 PUBLISH 报文与收到(入站)的 PUBLISH 报文中的 DUP 标志是独立设 置的,它的值必须单独的根据发送(出站) 的 PUBLISH 报文是否是一个重发来确定。[MQTT-3.3.1-4]PUBLISH 报文的 2 个 QoS 比特位不能同时设置为 1。[MQTT-3.3.1-5]如果客户端发给服务端的 PUBLISH 报文的保留标志被设置为 1,服务端必须存储此应用消 息,并用其替换此话题下任何已存在的消息。[MQTT-3.3.1-6]如果载荷为空, 消息可以正常被服务端所处理,但是此话题下的任何保留消息必须被丢 弃,并且此话题未来的订阅者将不会收到保留消息。[MQTT-3.3.1-7]载荷为空的保留消息将不能被存储在服务端。[MQTT-3.3.1-8]如果客户端发给服务端的 PUBLISH 报文的保留标志位为 0,服务器不能把此消息存储为保 留消息, 也不能丢弃或替换任何已存在的保留消息。[MQTT-3.3.1-9]如果保留消息处理属性被设置为 0,服务端必须发送主题与客户端订阅的主题过滤器相匹 配的所有保留消息。[MQTT-3.3.1- 10]如果保留消息处理属性被设置为 1,如果尚不存在匹配的订阅, 服务端必须发送主题与客 户端订阅的主题过滤器相匹配的所有保留消息。如果已存在相匹配的订阅,服务器不能发 送这些保留消息。[MQTT-3.3.1- 11]如果保留消息处理属性被设置为 2,服务器不能发送这些保留消息。[MQTT-3.3.1- 12]如果发布保留订阅选项被设置为 0,服务端在转发应用消息时必须将保留标志设置为 0, 而不管收到的 PUBLISH 报文中保留标志位如何设置的。[MQTT-3.3.1- 13]如果发布保留订阅选项被设置为 1,服务端在转发应用消息时必须将保留标志设置为与收 到的 PUBLISH 消息中的保留标志位相同。[MQTT-3.3.2- 1]主题名必须是 PUBLISH 报文可变报头的第一个字段。它必须是 UTF-8 编码的字符串。[MQTT-3.3.2-2]PUBLISH 报文中的主题名不能包含通配符。[MQTT-3.3.2-3]服务端发送给订阅客户端的 PUBLISH 报文中的主题名必须匹配该订阅的主题过滤器。[MQTT-3.3.2-4]服务端必须把接收到的应用消息中的载荷格式指示原封不动的发给所有的订阅者。[MQTT-3.3.2-5]如果消息过期间隔已过期, 服务端还没开始向匹配的订阅者交付该消息,则服务端必须删 除该订阅者的消息副本。[MQTT-3.3.2-6]服务端发送给客户端的 PUBLISH 报文中必须包含消息过期间隔,值为接收时间减去消息 在服务端的等待时间。 [MQTT-3.3.2-7]接收端不能将任何主题别名映射从一个网络连接转发到另一个网络连接。[MQTT-3.3.2-8]发送端不能发送包含主题别名值为 0 的 PUBLISH 报文。[MQTT-3.3.2-9]客户端不能发送主题别名值大于服务端的 CONNACK 报文中指定的主题别名最大值的 PUBLISH 报文。[MQTT-3.3.2- 10]客户端必须接受所有值大于 0 且小于等于其发送的 CONNECT 报文中的主题别名最大值的 主题别名。[MQTT-3.3.2- 11]服务端不能发送包含主题别名值大于客户端在 CONNECT 报文中指定的主题别名最大值的 PUBLISH 报文。[MQTT-3.3.2- 12]服务端必须接受所有值大于 0 且小于等于其发送的 CONNACK 报文中的主题别名最大值的 主题别名。[MQTT-3.3.2- 13]响应主题必须是 UTF-8 编码的字符串。[MQTT-3.3.2- 14]响应主题不能包含通配符。[MQTT-3.3.2- 15]服务端在收到应用消息时必须将响应主题原封不动的发送给所有的订阅者。[MQTT-3.3.2- 16]服务端在收到应用消息时必须原封不动的把对比数据发送给所有的订阅者。[MQTT-3.3.2- 17]服务端在转发应用消息到客户端时必须原封不动的把所有的用户属性放在 PUBLISH 报文 中。[MQTT-3.3.2- 18]服务端在转发应用消息时必须保持所有用户属性的先后顺序。[MQTT-3.3.2- 19]内容类型必须是 UTF-8 编码的字符串。[MQTT-3.3.2-20]服务端必须把收到的应用消息中的内容类型原封不动的发送给所有的订阅者。[MQTT-3.3.4- 1]PUBLISH 报文的接收端必须按照 PUBLISH 报文中的 QoS 等级发送响应报文。[MQTT-3.3.4-2]这种情况下,服务端必须按照所有匹配的订阅中最大的 QoS 等级把消息发送给客户端。[MQTT-3.3.4-3]如果客户端在这些重叠的订阅中指定了订阅标识符,服务端在发布这些订阅相匹配的消息 时必须包含这些订阅标识符。[MQTT-3.3.4-4]如果服务端对这些重叠的订阅只发送一条相匹配的消息,服务端必须在 PUBLISH 报文中 包含所有的相匹配的订阅标识符(如果存在),但没有顺序要求。[MQTT-3.3.4-5]如果服务端对这些重叠的订阅必须分别发送相匹配的消息,则每个 PUBLISH 报文中包含 与订阅相匹配的订阅标识符(如果存在)。[MQTT-3.3.4-6]从客户端发送给服务端的 PUBLISH 报文不能包含订阅标识符。 [MQTT-3.3.4-7]客户端在收到服务端的 PUBACK ,PUBCOMP 或包含原因码大于等于 128 的 PUBREC 报 文之前, 不能发送数量超过服务端的接收最大值的 QoS 为 1 和 2 的 PUBLISH 报文。[MQTT-3.3.4-8]客户端不能延迟发送任何报文,除了 PUBLISH 报文--如果已发送且没有收到确认的 PUBLISH 报文数量已达到服务端的接收最大值。[MQTT-3.3.4-9]服务端在接收到客户端的 PUBACK ,PUBCOMP 或包含原因码大于等于 128 的 PUBREC 报文之前,不能发送数量超过客户端的接收最大值的 QoS 为 1 和 2 的 PUBLISH 报文。[MQTT-3.3.4- 10]服务端不能延迟发送任何报文,除了 PUBLISH 报文--如果已发送且没有收到确认的 PUBLISH 报文数量已到达客户端的接收最大值。[MQTT-3.4.2- 1]服务端或客户端发送 PUBACK 报文时必须设置其中一种 PUBACK 原因码。[MQTT-3.4.2-2]如果加上原因字符串之后的 PUBACK 报文长度超出了接收端指定的最大报文长度,则发送 端不能发送此原因字符串。[MQTT-3.4.2-3]如果加上用户属性之后的 PUBACK 报文长度超出了接收端指定的最大报文长度, 则发送端 不能发送此属性。[MQTT-3.5.2- 1]服务端或客户端发送 PUBREC 报文时必须设置其中一种原因码。[MQTT-3.5.2-2]发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的 PUBREC 报文长度 超出了接收端指定的最大报文长度, 则发送端不能发送此属性。[MQTT-3.5.2-3]如果加上用户属性之后的 PUBREC 报文长度超出了接收端指定的最大报文长度, 则发送 端不能发送此属性。[MQTT-3.6.1- 1]PUBREL 固定报头的第 3 ,2 ,1 ,0 位是保留位, 必须被设置为 0 ,0 ,1 ,0。服务端必须 将其它的任何值都当做是不合法的并关闭网络连接。[MQTT-3.6.2- 1]客户端或服务端发送 PUBREL 报文时必须设置其中一种 PUBREL 原因码。[MQTT-3.6.2-2]如果加上原因字符串之后的 PUBREL 报文长度超出了接收端指定的最大报文长度, 则发送 端不能发送此原因字符串。[MQTT-3.6.2-3]如果加上用户属性之后的 PUBREL 报文长度超出了接收端指定的最大报文长度, 则发送端 不能发送此属性。[MQTT-3.7.2- 1]服务端或客户端发送 PUBCOMP 报文时必须设置一种 PUBCOMP 原因码。[MQTT-3.7.2-2]如果加上原因字符串之后的 PUBCOMP 报文长度超出了接收端指定的最大报文长度,则发 送端不能发送此原因字符串。[MQTT-3.7.2-3]如果加上用户属性之后的 PUBCOMP 报文长度超出了接收端指定的最大报文长度,则发送 端不能发送此属性。[MQTT-3.8.1- 1]SUBSCRIBE 报文固定报头第 3 ,2 ,1 ,0 比特位是保留位, 必须被设置为 0 ,0 ,1 ,0。 服务端必须将其他的任何值都当做是不合法的并关闭网络连接。[MQTT-3.8.3- 1]主题过滤器必须为 UTF-8 编码的字符串。 [MQTT-3.8.3-2]载荷必须包含至少一个主题过滤器/订阅选项对。[MQTT-3.8.3-3]订阅选项的第 2 比特表示非本地选项。值为 1,表示应用消息不能被转发给发布此消息的 客户标识符。[MQTT-3.8.3-4]共享订阅时把非本地选项设为 1 将造成协议错误。[MQTT-3.8.3-5]订阅选项的第 6 和 7 比特为将来所保留。服务端必须把此保留位非 0 的 SUBSCRIBE 报文 当做无效报文。[MQTT-3.8.4- 1]当服务端收到来自客户端的 SUBSCRIBE 报文时, 必须使用 SUBACK 报文作为相应。[MQTT-3.8.4-2]SUBACK 报文必须和待确认的 SUBSCRIBE 报文有相同的报文标识符。[MQTT-3.8.4-3]如果服务端收到的 SUBSCRIBE 报文中的一个主题过滤器与当前会话的一个非共享订阅相 同,那么必须使用新的订阅替换现存的订阅。[MQTT-3.8.4-4]如果保留处理选项为 0,任何匹配该主题过滤器的保留消息必须被重发, 但替换订阅不能 造成应用消息的丢失。[MQTT-3.8.4-5]如果服务端收到的 SUBSCRIBE 报文包含多个主题过滤器,服务端必须当做收到一系列多 个 SUBSCRIBE 报文来处理--除了将它们的响应组合为单个 SUBACK 响应。[MQTT-3.8.4-6]服务端发送给客户端的 SUBACK 报文必须为每一个主题过滤器/订阅选项对包含一个原因 码。[MQTT-3.8.4-7]此原因码必须说明为该订阅授予的最大 QoS 等级,或指示订阅失败。[MQTT-3.8.4-8]响应该订阅的应用消息 QoS 等级必须为该消息发布时的 QoS 等级和服务端授予的最大 QoS 等级二者最小值。[MQTT-3.9.2- 1]如果加上原因字符串之后的 SUBACK 报文长度超出了客户端指定的最大报文长度,则服务 端不能发送此原因字符串。[MQTT-3.9.2-2]如果加上用户属性之后的 SUBACK 报文长度超出了客户端指定的最大报文长度, 则服务端 不能发送此属性。[MQTT-3.9.3- 1]SUBACK 报文中的原因码顺序必须与 SUBSCRIBE 报文中的主题过滤器顺序相匹配。[MQTT-3.9.3-2]服务端发送 SUBACK 报文时必须对收到的每一个主题过滤器设置一种原因码。[MQTT-3.10.1- 1]UNSUBSCRIBE 固定报头的第 3 ,2 ,1 ,0 位是保留位且必须分别设置为 0 ,0 ,1 ,0。 服务端必须认为任何其它的值都是不合法的并关闭网络连接。[MQTT-3.10.3- 1]UNSUBSCRIBE 报文中的主题过滤器必须为 UTF-8 编码的字符串。[MQTT-3.10.3-2]UNSUBSCRIBE 报文有效载荷必须包含至少一个主题过滤器。 [MQTT-3.10.4- 1]服务端必须对客户端的 UNSUBSCRIBE 报文中提供的主题过滤器(不管是否包含通配符)逐个字符与当前持有的主题过滤器集进行比较。如果任何过滤器完全匹配,则必须删 除其拥有的订阅。[MQTT-3.10.4-2]当服务端收到 UNSUBSCRIBE 报文,它必须停止添加为了交付给客户端的与主题过滤器 相匹配的任何新消息。[MQTT-3.10.4-3]当服务端收到 UNSUBSCRIBE 报文,它必须完成任何已经开始发送给客户端的、与主题 过滤器相匹配的、QoS 等级为 1 或 2 的消息。[MQTT-3.10.4-4]服务端必须发送 UNSUBACK 报文以响应客户端的 UNSUBSCRIBE 请求。[MQTT-3.10.4-5]UNSUBACK 报文必须包含和 UNSUBSCRIBE 报文相同的报文标识符。即使没有删除任何 主题订阅,服务端也必须发送一个 UNSUBACK 响应。[MQTT-3.10.4-6]如果服务端收到的 UNSUBSCRIBE 报文包含多个主题过滤器, 服务端必须当做收到一系 列多个 UNSUBSCRIBE 报文来处理--除了将它们的响应组合为单个 SUBACK 响应。[MQTT-3.11.2- 1]如果加上原因字符串之后的 UNSUBACK 报文长度超出了客户端指定的最大报文长度,则 服务端不能发送此原因字符串。[MQTT-3.11.2-2]如果加上用户属性之后的 UNSUBACK 报文长度超出了客户端指定的最大报文长度,则服 务端不能发送此属性。[MQTT-3.11.3- 1]UNSUBACK 报文中的原因码顺序必须与 UNSUBSCRIBE 报文中的主题过滤器顺序相匹 配。[MQTT-3.11.3-2]服务端发送 UNSUBACK 报文时对于每个收到的主题过滤器, 必须使用一个取消订阅原因 码。[MQTT-3.12.4- 1]服务端必须发送 PINGRESP 报文响应客户端的 PINGREQ 报文。[MQTT-3.14.0- 1]服务端不能发送 DISCONNECT 报文,直到它发送了包含原因码小于 0x80 的 CONNACK 报文之后。[MQTT-3.14.1- 1]服务端或客户端必须验证所有的保留位都被设置为 0,如果他们不为 0,发送包含原因码 为 0x81(无效报文)的 DISCONNECT 报文。[MQTT-3.14.2- 1]客户端或服务端发送 DISCONNECT 报文时必须使用一种 DISCONNECT 原因码。[MQTT-3.14.2-2]会话过期间隔不能由服务端的 DISCONNECT 报文发送。[MQTT-3.14.2-3]如果此属性使得 DISCONNECT 报文的长度超出了接收端指定的最大报文长度,则发送端 不能发送此属性。[MQTT-3.14.2-4]如果加上用户属性之后的 DISCONNECT 报文长度超出了接收端指定的最大报文长度,则 发送端不能发送此属性。[MQTT-3.14.4- 1]发送端发送完 DISCONNECT 报文之后不能再在此网络连接上发送任何 MQTT 控制报文。 [MQTT-3.14.4-2]发送端发送完 DISCONNECT 报文之后必须关闭网络连接。[MQTT-3.14.4-3]接收到包含原因码为 0x00 (成功) 的 DISCONNECT 时,服务端必须丢弃任何与当前连接 相关的遗嘱消息,而不发布它。[MQTT-3.15.1- 1]AUTH 报文固定报头第 3 ,2 ,1 ,0 位是保留位, 必须全设置为 0。客户端或服务端必须把 其他值当做无效值并关闭网络连接。[MQTT-3.15.2- 1]AUTH 报文的发送端必须使用一种认证原因码。[MQTT-3.15.2-2]如果加上原因字符串之后的 AUTH 报文长度超出了接收端所指定的最大报文长度, 则发送 端不能发送此属性。[MQTT-3.15.2-3]如果加上用户属性之后的 AUTH 报文长度超出了接收端指定的最大报文长度, 则服务端不 能发送此属性。[MQTT-4.1.0- 1]当网络连接打开时,客户端和服务端不能丢弃会话状态。[MQTT-4.2.0- 1]客户端或服务端必须支持使用一个或多个提供有序的、可靠的、双向传输(从客户端到服 务端和从服务端到客户端) 字节流传输的底层传输协议。[MQTT-4.1.0-2]当网络连接被关闭并且会话过期间隔已过时,服务端必须丢弃会话状态。[MQTT-4.3.1- 1]对于 QoS 等级 0 的分发协议,发送端必须发送 QoS 等于 0 ,DUP 等于 0 的 PUBLISH 报 文。[MQTT-4.3.2- 1]对于 QoS 等级 1 的分发协议,发送端每次发送新的应用消息都必须分配一个未使用的用户 标识符。[MQTT-4.3.2-2]对于 QoS 等级 1 的分发协议,发送端发送的 PUBLISH 报文必须包含报文标识符且 QoS 等于 1 ,DUP 等于 0。[MQTT-4.3.2-3]对于 QoS 等级 1 的分发协议,发送端必须将这个 PUBLISH 报文看作是未确认的,直到从 接收端那收到对应的 PUBACK 报文。[MQTT-4.3.2-4]对于 QoS 等级 1 的分发协议,接收端响应的 PUBACK 报文必须包含一个报文标识符,这 个标识符来自接收到的、已经接受所有权的 PUBLISH 报文。[MQTT-4.3.2-5]对于 QoS 等级 1 的分发协议,接收端发送了 PUBACK 报文之后,接收端必须将任何包含 相同报文标识符的入站 PUBLISH 报文当做一个新的消息,并忽略它的 DUP 标志的值。[MQTT-4.3.3- 1]对于 QoS 等级 2 的分发协议,发送端必须给要发送的新应用消息分配一个未使用的报文标 识符。[MQTT-4.3.3-2]对于 QoS 等级 2 的分发协议,发送端 PUBLISH 报文必须包含报文标识符且报文的 QoS 等于 2 ,DUP 等于 0。[MQTT-4.3.3-3]对于 QoS 等级 2 的分发协议,发送端必须将这个 PUBLISH 报文看作是未确认的,直到从 接收端那收到对应的 PUBREC 报文。 [MQTT-4.3.3-4]对于 QoS 等级 2 的分发协议,收到发送端发送的包含原因码小于 0x80 的 PUBREC 报文  后必须发送一个 PUBREL 报文。 PUBREL 报文必须包含与原始 PUBLISH 报文相同的报文 标识符。[MQTT-4.3.3-5]对于 QoS 等级 2 的分发协议,发送端必须将这个 PUBREL 报文看作是未确认的,直到从 接收端那收到对应的 PUBCOMP 报文。[MQTT-4.3.3-6]对于 QoS 等级 2 的分发协议,发送端一旦发送了对应的 PUBREL 报文就不能重发这个 PUBLISH 报文。[MQTT-4.3.3-7]对于 QoS 等级 2 的分发协议,如果 PUBLISH 报文已发送, 不能应用消息过期属性。[MQTT-4.3.3-8]对于 QoS 等级 2 的分发协议,接收端响应的 PUBREC 报文必须包含报文标识符,这个标 识符来自接收到的、已经接受所有权的 PUBLISH 报文。[MQTT-4.3.3-9]对于 QoS 等级 2 的分发协议,如果接收端发送了包含原因码大于等于 0x80 的 PUBREC 报文,它必须将后续包含相同报文标识符的 PUBLISH 报文当做是新的应用消息。[MQTT-4.3.3- 10]对于 QoS 等级 2 的分发协议,接收端在收到对应的 PUBREL 报文之前,接收端必须发送 PUBREC 报文确认任何后续的具有相同报文标识符的 PUBLISH 报文。在这种情况下,它 不能重复分发消息给任何后续的接收者。[MQTT-4.3.3- 11]对于 QoS 等级 2 的分发协议,接收端必须发送包含与 PUBREL 相同报文标识符的 PUBCOMP 报文作为对 PUBREL 报文的响应。[MQTT-4.3.3- 12]对于 QoS 等级 2 的分发协议,接收端发送 PUBCOMP 报文之后,必须将后续包含相同报 文标识符的 PUBLISH 报文当做是新的应用消息。[MQTT-4.3.3- 13]对于 QoS 等级 2 的分发协议,接收端必须继续 QoS 等级 2 确认序列,即使它已经应用了 消息过期属性。[MQTT-4.4.0- 1]客户端以新开始标志为 0 且会话存在的情况下重连时, 客户端和服务端都必须使用原始报 文标识符重新发送任何未被确认的 PUBLISH 报文(当 QoS > 0)和 PUBREL 报文。这是 唯一要求客户端或服务端重发消息的情况。客户端和服务端不能在其他任何时间重发消息。[MQTT-4.4.0-2]如果收到包含原因码大于等于 0x80 的 PUBACK 或 PUBREC,则对应的 PUBLISH 报文被 看作已确认,且不能被重传。[MQTT-4.5.0- 1]当服务端接受入站应用消息的所有权时,它必须将消息添加到订阅匹配的客户端的会话状 态中。[MQTT-4.5.0-2]客户端必须按照可用的服务质量(QoS)规则确认它收到的任何 PUBLISH 报文, 不管它 是否选择处理其包含的应用消息。[MQTT-4.6.0- 1]重发任何之前的 PUBLISH 报文时, 客户端必须按原始 PUBLISH 报文的发送顺序重发(适 用于 QoS 等级 1 和 QoS 等级 2 消息)。[MQTT-4.6.0-2]客户端必须按照对应的 PUBLISH 报文的顺序发送 PUBACK 报文(QoS 等级 1 消息)。[MQTT-4.6.0-3]客户端必须按照对应的 PUBLISH 报文的顺序发送 PUBREC 报文(QoS 等级 2 消息)。 [MQTT-4.6.0-4]客户端必须按照对应的 PUBREC 报文的顺序发送 PUBREL 报文(QoS 等级 2 消息)。[MQTT-4.6.0-5]当服务端处理发布到有序主题的消息时,它必须按照消息从任何给定客户端接收的顺序发 送 PUBLISH 报文给消费端(对于同一主题和 QoS 等级)。[MQTT-4.6.0-6]默认情况下,服务端转发非共享订阅的消息时, 必须将每个主题都视为有序主题。[MQTT-4.7.0- 1]主题过滤器中可以使用通配符,但是主题名不能使用通配符。[MQTT-4.7.1- 1]多层通配符必须单独指定,或者跟在主题层级分隔符后面。不管哪种情况,它都必须是主 题过滤器的最后一个字符。[MQTT-4.7.1-2]在主题过滤器的任意层级都可以使用单层通配符, 包括第一个和最后一个层级。在使用它 时,它必须占据过滤器的整个层级。[MQTT-4.7.2- 1]服务端不能将$字符开头的主题名匹配通配符(#或+ )开头的主题过滤器。[MQTT-4.7.3- 1]所有的主题名和主题过滤器必须至少包含一个字符。[MQTT-4.7.3-2]主题名和主题过滤器不能包含空字符(Unicode U+0000)。[MQTT-4.7.3-3]主题名和主题过滤器是 UTF-8 编码字符串,它们不能超过 65,535 字节。[MQTT-4.7.3-4]匹配订阅时,服务端不能对主题名或主题过滤器执行任何规范化处理, 不能修改或替换任 何未识别的字符。[MQTT-4.8.2- 1]共享订阅主题过滤器必须以"$share/"开始, 且必须包含至少一个字符长度的共享名。[MQTT-4.8.2-2]共享名不能包含字符"/" ,"+"或"#",但必须跟在"/"字符后面。此"/"字符后面必须跟随一个主 题过滤器。[MQTT-4.8.2-3]向客户端发送应用消息时, 服务端必须考虑授予客户端的 QoS 等级。[MQTT-4.8.2-4]服务端必须在客户端重新连接时完成向该客户端的消息分发。[MQTT-4.8.2-5]如果客户端的会话在客户端重连之前终止, 服务端不能把此消息发送给其他订阅的客户 端。[MQTT-4.8.2-6]如果客户端对来自服务端的 PUBLISH 报文使用包含原因码大于等于 0x80 的 PUBACK 或 PUBREC 报文进行响应, 服务端必须丢弃应用消息而不尝试将其发送给任何其他订阅者。[MQTT-4.9.0- 1]客户端或服务端必须将其初始发送配额设置为不超过接收最大值的非 0 值。[MQTT-4.9.0-2]每当客户端或服务端发送了一个 QoS 等级大于 0 的 PUBLISH 报文, 它就会减少发送配  额。如果发送配额减为 0,客户端或服务端不能再发送任何 QoS 等级大于 0 的 PUBLISH 报文。 [MQTT-4.9.0-3]它可以继续发送 QoS 为 0 的 PUBLISH 报文, 也可以选择暂停发送这些报文。即使配额为 0,客户端和服务端也必须继续处理和响应其他 MQTT 控制报文。[MQTT-4.12.0- 1]如果服务端不支持客户端提供的认证方法, 它可以发送一个包含原因码 0x8C(无效的认证 方法)或 0x87(未授权)的 CONNACK 报文, 并且必须关闭网络连接。[MQTT-4.12.0-2]如果服务端需要额外的信息来完成认证,它可以向客户端发送 AUTH 报文,此报文必须包 含原因码 0x18(继续认证)。[MQTT-4.12.0-3]客户端通过发送另一个 AUTH 报文响应来自服务端的 AUTH 报文,此报文必须包含原因码 0x18(继续认证)。[MQTT-4.12.0-4]服务端可以在处理过程中随时拒绝认证。它可以发送包含原因码大于等于 0x80 的 CONNACK 报文,如 4.13 节所述, 并且必须关闭网络连接。[MQTT-4.12.0-5]如果初始 CONNECT 报文包含认证方法属性,则所有的 AUTH 报文和成功的 CONNACK 报文必须包含与 CONNECT 报文中相同的认证方法属性。[MQTT-4.12.0-6]如果客户端在 CONNECT 报文中没有包含认证方法, 则服务端不能发送 AUTH 报文,且 不能在 CONNACK 报文中发送认证方法。[MQTT-4.12.0-7]如果客户端在 CONNECT 报文中没有包含认证方法, 则客户端不能向服务端发送 AUTH 报文。[MQTT-4.12.1- 1]如果客户端在 CONNECT 报文中提供了认证方法,它可以在收到 CONNACK 报文之后的 任何时间通过发送包含原因码 0x19(重新认证)的 AUTH 报文发起重新认证。客户端必 须将认证方法设置为与最初验证网络连接时的认证方法一致。[MQTT-4.12.1-2]如果重新认证失败,客户端或服务端应该发送包含适当原因码的 DISCONNECT 报文,如 section 4.13 节 所述。并且必须关闭网络连接。[MQTT-4.13.1- 1]当服务端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时, 它必须关闭 网络连接。[MQTT-4.13.2- 1]CONNACK 报文和 DISCONNECT 报文允许使用大于等于 0x80 的原因码以指示网络连接 将被关闭。如果某个大于等于 0x80 的原因码被指定, 无论是否发送 CONNACK 报文或  DISCONNECT 报文, 必须关闭网络连接。[MQTT-6.0.0- 1]MQTT 控制报文必须使用 WebSocket 二进制数据帧发送。如果收到任何其它类型的数据 帧,接收者必须关闭网络连接。[MQTT-6.0.0-2]单个 WebSocket 数据帧可以包含多个或者部分 MQTT 报文。接收者不能假设 MQTT 控制 报文按 WebSocket 帧边界对齐。[MQTT-6.0.0-3]客户端必须将字符串"mqtt"包含在它提供的 WebSocket 子协议列表里。[MQTT-6.0.0-4]服务端选择和返回的 WebSocket 子协议名必须是"mqtt"。 Appendix C. MQTT v5.0 新特性总结(非规范) MQTT v5.0添加了以下特性 .    会话过期 把清理会话标志拆分成新开始标志(指示会话应该在不使用现有会话的情况下开始)和会话过期间隔标 志(指示连接断开之后会话保留的时间)。会话过期间隔时间可以在断开时修改。 把新开始标志设置为 1且会话过期间隔标志设置为0,等同于在MQTT v3.1.1中把清理会话(CleanSession)设置为1。 .    消息过期 允许消息在发布时设置一个过期间隔。 .    所有确认报文原因码 更改所有响应报文以包含原因码,包括CONNACK ,PUBACK ,PUBREC ,PUBREL ,PUBCOMP, SUBACK ,UNSUBACK ,DISCONNECT和AUTH,以使得调用方确定请求的函数是否成功。 .    所有确认报文原因字符串 更改大部分报文以包含原因码同时也允许一个可选的原因字符串。这是为问题定位而设计的,并且不应 由接收端所解析。 .    服务端断开 允许服务端发送DISCONNECT报文,以指示连接被关闭的原因。 .    载荷格式和内容类型 允许在消息发布时指定载荷格式(二进制、文本) 和MIME样式内容类型。这些信息被转发到消息的接 收端。 .    请求/响应 规定MQTT请求/响应模式, 提供响应主题和对比数据属性,以使得响应消息被路由回请求的发布者。 此外,为客户端添加从服务端获取获取关于构造响应主题的配置信息的能力。 .    共享订阅 添加对共享订阅的支持,以允许多个订阅消费者进行负载均衡。 .    订阅标识符 允许在SUBSCRIBE报文中指定一个数字订阅标识符, 并在消息分发时返回此标识符。这使得客户端收 到分发的消息时确定此消息是由哪个或哪些订阅导致的。 .    主题别名 通过将主题名缩写为小整数来减小MQTT报文的开销大小。客户端和服务端分别指定它们允许的主题别 名的数量。 .    流量控制 允许客户端和服务端分别指定未完成的可靠消息(QoS>0)的数量。发送端可以暂停发送此类消息以 保持消息数量低于配额。这被用于限制可靠消息的速率和某一时刻的传输中(in-flight)消息数量。 .    用户属性 为大多数报文添加用户属性。PUBLISH报文的用户属性由客户端应用程序定义。PUBLISH报文和遗嘱 报文的用户属性由服务端转发给应用消息的接收端。CONNECT ,SUBSCRIBE和UNSUBSCRIBE报文 的用户属性由服务端实现定义。 CONNACK ,PUBACK ,PUBREC ,PUBREL ,PUBCOMP, SUBACK ,UNSUBACK和AUTH报文的用户属性由发送端定义,且对发送端具有唯一性。 MQTT规范 不定义用户属性的意义。 .    最大报文长度 允许客户端和服务端各自指定它们支持的最大报文长度。会话参与方发送更大的报文将造成错误。 .    可选的服务端功能可用性 提供定义一组服务端不允许的功能, 并告知客户端的机制。可以使用这种方式指定的功能包括:最大 QoS等级,保留可用, 通配符订阅可用,订阅标识符可用和共享订阅可用。客户端使用服务端通知了 (不可用)的功能将造成错误。 在早期版本的MQTT协议中,服务端没有实现的功能通过未授权告知客户端。 当客户端使用其中一种 (不可用的)功能时, 此功能允许服务端告知客户端, 并添加特定的原因码。 .    增强的认证 提供一种机制来启用包括互相认证在内的质询/响应风格的认证。这允许在客户端和服务端都支持的情 况下使用SASL风格的认证,包括客户端在连接中重新认证的功能。 .    订阅选项 提供主要用于定义允许消息桥接应用的订阅选项。包括不要把消息发送给消息源客户端(非本地) 的选 项和订阅时处理保留消息的选项。 .    遗嘱延迟 提供指定遗嘱消息在连接中断后延时发送的能力。设计此特性是为了在会话的连接重建的情况下不发送 遗嘱消息。此特性允许连接短暂中断而不通知其他客户端。 .    服务端保持连接 允许服务端指定其希望客户端使用的保持连接值。此特性允许服务端设置最大允许的保持连接值并被客 户端使用。 .    分配客户标识符 服务端分配了客户标识符的情况下, 向客户端返回此客户标识符。服务端分配客户标识符只能用于新开 始标志为1的连接。 .    服务端参考 允许服务端使用 CONNACK 或 DISCONNECT 报文指定备用服务端。此特性被用于(服务端) 重定向 或做准备。 --- ═══════════════════════════════════════════ ## MQTT 入门 ═══════════════════════════════════════════ ### 31. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT 简介 MQTT 是一种为连接物联网设备而设计的发布/订阅协议。与 HTTP 的请求/响应模式不同,MQTT 以事件驱动的方式运作,允许将消息推送给客户端。这种架构方法通过解耦数据生产者和数据消费者,消除了它们之间的依赖关系,从而实现了高度可扩展的解决方案。建立 MQTT 连接以发布和订阅消息的两个关键组件是 MQTT 客户端和 MQTT 代理,如下图所示。 MQTT 的优势 MQTT 提供了几个关键优势: 轻量级和高效:MQTT 最小化了客户端所需的资源和网络带宽。 双向通信:MQTT 促进了设备和服务器之间的通信,支持发布和订阅。它还允许向设备组广播消息。 可扩展性:MQTT 可以扩展以支持物联网或工业物联网生态系统中的数百万设备或“事物”。 服务质量(QoS)级别:MQTT 指定了不同的 QoS 级别以确保可靠的消息传递。 持久会话:MQTT 支持设备和服务器之间的持久会话,减少了在不可靠网络上的重新连接时间。 安全特性:MQTT 支持 TLS 加密以确保消息的保密性,并支持认证协议以验证客户端。 MQTT 应用和案例 MQTT 在各个行业和领域都有应用。它已被 BMW、Liberty Global、Fortum、Hytera、Awair 和 Matternet 等公司采用。这些公司在汽车、电信、能源、公共安全和连接产品领域成功利用了 MQTT。 MQTT 基础:掌握这一物联网协议的要点 MQTT 的核心是 MQTT 代理和 MQTT 客户端。MQTT 代理是发送者和接收者之间的中介,将消息分发给适当的接收者。MQTT 客户端将消息发布到代理,其他客户端订阅特定主题以接收消息。每个 MQTT 消息都包含一个主题,客户端订阅他们感兴趣的主题。MQTT 代理维护一个订阅者列表,并使用它将消息传递给相关客户端。 MQTT 代理还可以为离线客户端缓冲消息,即使在不可靠的网络条件下也确保可靠的消息传递。为了实现这一点,MQTT 支持三种不同的服务质量(QoS)级别:0(最多一次)、1(至少一次)和 2(恰好一次)。 MQTT 规范有两个版本:MQTT 3.1.1 和 MQTT 5。虽然大多数商业 MQTT 代理现在支持 MQTT 5,但一些物联网管理的云服务仍然主要支持 MQTT 3.1.1。我们强烈建议在新的物联网部署中使用 MQTT 5,因为它增强了专注于健壮性和云原生可扩展性的功能。 MQTT 客户端 有许多开源客户端可用于多种编程语言。HiveMQ 通过 HiveMQ MQTT 客户端库提供自己的 MQTT 客户端,旨在简化 MQTT 客户端的部署和实施,并为用户提供一流的功能、性能、安全性和可靠性。支持的一些编程语言包括 C#、C++、Java、Websockets、Python 等。Eclipse Paho 也提供了适用于 C/C++ 和 Python 等语言的 MQTT 客户端库。 MQTT 代理 MQTT 代理有多种实现方式,以满足不同的需求,如开源、商业和托管云服务。HiveMQ 提供商业版:HiveMQ 自托管和 HiveMQ 云,一个托管的云 MQTT 服务,以及 HiveMQ 社区版,一个开源版本。有关 MQTT 代理的详细列表,请访问 mqtt.cn。 MQTT 使用案例示例: https://iot.mqtt.cn JAVA通过MQTT接入示例 说明: 本文中使用的代码为样例代码,仅用于体验平台通信功能,如需进行商用,可以参考资源获取获取对应语言的IoT Device SDK进行集成。 前提条件 已在管理控制台获取设备接入地址。获取地址的操作步骤,请参考平台对接信息。 已在管理控制台创建产品和设备。创建产品和设备的具体操作细节,请参考创建产品、注册单个设备或批量注册设备。 准备工作 安装IntelliJ IDEA 访问IntelliJ IDEA官网,选择合适系统的版本下载。(本文以windows 64-bit系统IntelliJ IDEA 2019.2.3 Ultimate为例)。 下载完成后,运行安装文件,根据界面提示安装。 导入代码样例 下载JAVA样例。 链接:https://pan.baidu.com/s/1JtQsONuIX8y7r0VpIepA5w?pwd=zne7 提取码:zne7 打开IDEA开发者工具,单击“ Import Project”。 选择步骤1中下载的样例,然后根据界面提示,单击“next”。 完成代码导入。 建立连接 设备或网关在接入物联网平台时首先需要和平台建立连接,从而将设备或网关与平台进行关联。开发者通过传入设备信息,将设备或网关连接到物联网平台。 MQTT基本信息 Topic权限说明Broker Addressiot.mqtt.cnMQTT地址Broker Port1883MQTT端口号Client ID4QR8TZ9ThuL4G设备号SN(请替换为自己的) MQTT账号密码 Topic权限说明User Nameceshi用户账户Password123456用户密码 在建立连接之前,先修改以下参数: // MQTT 服务器地址 private static final String MQTT_BROKER = "tcp://iot.mqtt.cn:1883"; MQTT地址/端口号 // MQTT 客户端 ID private static final String MQTT_CLIENT_ID = "4QR8TZ9ThuL4G"; //设备号SN码 // MQTT 用户名 private static final String MQTT_USERNAME = "ceshi"; // MQTT 密码 private static final String MQTT_PASSWORD = "Abc123456"; // 订阅的主题 private static final String MQTT_TOPIC_SUBSCRIBE = "/server/coo/4QR8TZ9ThuL4G"; // 发布的主题 private static final String MQTT_TOPIC_PUBLISH = "/dev/coo/4QR8TZ9ThuL4G"; MQTT_BROKER为物联网平台的设备对接地址,可参考平台对接信息获取(获取的是域名信息,可通过在cmd命令框中执行“ping 域名”,获取IP地址)。 MQTT_CLIENT_ID为设备号SN,在成功添加设备后获取。 修改完1中的参数后就可使用MqttClient建立连接了。 连接成功后,设备显示在线。 备注:从设备地址是sensor_device_id ,寄存器是port_id,数据数值是Sdata ,具体稍后有具体说明。 使用MQTT通讯协议,下面的属性名称,Modbus功能码,数据格式,数据顺序不会影响最终数据,随便选择就可以! MQTT 主题一览 MQTT物联网平台 作为物联网 PaaS 云平台,对设备 MQTT 接入提供了内置的访问协议规范,让设备和云平台的消息通信更加有章可循,大大简化了物联网项目的开发难度,缩短了产品的开发周期。 不同于普通的 MQTT 使用方式,我们提供了标准的内置主题,这足以实现绝大多数的物联网应用场景。 Topic权限说明/dev/coo/4QR8TZ9ThuL4G发布上行通信:设备通过该Topic向物联网平台发送消息。/server/coo/4QR8TZ9ThuL4G订阅下行通信:设备通过订阅该Topic,获取从物联网平台下发的消息。 4QR8TZ9ThuL4G为示例设备号SN,请替换为自己的! 上行通信 Topic:/dev/coo/4QR8TZ9ThuL4G 设备号SN(请替换为自己的) // 连接到 MQTT 服务器 mqttClient.connect(options); // 订阅主题 mqttClient.subscribe(MQTT_TOPIC_SUBSCRIBE); // 创建消息 MqttMessage message = new MqttMessage(); message.setPayload("[{"sensor_device_id": 1, "port_id": 1, "sdata": 66}]".getBytes()); // 发布消息 mqttClient.publish(MQTT_TOPIC_PUBLISH, message); 备注:从设备地址是sensor_device_id ,寄存器是port_id,数据数值是Sdata 下行通信 Topic:/server/coo/4QR8TZ9ThuL4G 设备号SN(请替换为自己的) System.out.println("设备ID: " + sensor_device_id + ", 端口ID: " + port_id + ", 数据: " + sdata); 备注:从设备地址是sensor_device_id ,寄存器是port_id,数据数值是Sdata 完整代码: import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import org.json.JSONArray; import org.json.JSONObject; public class MqttDemo { // MQTT 服务器地址 private static final String MQTT_BROKER = "tcp://iot.mqtt.cn:1883"; // MQTT 客户端 ID private static final String MQTT_CLIENT_ID = "4QR8TZ9ThuL4G"; // MQTT 用户名 private static final String MQTT_USERNAME = "ceshi"; // MQTT 密码 private static final String MQTT_PASSWORD = "Abc123456"; // 订阅的主题 private static final String MQTT_TOPIC_SUBSCRIBE = "/server/coo/4QR8TZ9ThuL4G"; // 发布的主题 private static final String MQTT_TOPIC_PUBLISH = "/dev/coo/4QR8TZ9ThuL4G"; // 心跳间隔,单位为秒 private static final int MQTT_KEEP_ALIVE_INTERVAL = 60; public static void main(String[] args) throws MqttException { // 创建 MQTT 客户端 MqttClient mqttClient = new MqttClient(MQTT_BROKER, MQTT_CLIENT_ID, new MemoryPersistence()); // 设置 MQTT 连接选项 MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(MQTT_USERNAME); options.setPassword(MQTT_PASSWORD.toCharArray()); options.setCleanSession(true); options.setKeepAliveInterval(MQTT_KEEP_ALIVE_INTERVAL); // 设置回调 mqttClient.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable cause) { System.out.println("连接断开"); } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { System.out.println("收到消息。主题: " + topic); System.out.println("消息: " + new String(message.getPayload())); // 将消息转换为字符串 String msg = new String(message.getPayload()); // 使用 JSON 工具解析字符串 JSONArray jsonArray = new JSONArray(msg); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); int sensor_device_id = jsonObject.getInt("sensor_device_id"); int port_id = jsonObject.getInt("port_id"); int sdata = jsonObject.getInt("sdata"); // 在这里你可以处理接收到的数据 System.out.println("设备ID: " + sensor_device_id + ", 端口ID: " + port_id + ", 数据: " + sdata); } } @Override public void deliveryComplete(IMqttDeliveryToken token) { System.out.println("消息发布完成"); } }); // 连接到 MQTT 服务器 mqttClient.connect(options); // 订阅主题 mqttClient.subscribe(MQTT_TOPIC_SUBSCRIBE); // 创建消息 MqttMessage message = new MqttMessage(); message.setPayload("[{"sensor_device_id": 1, "port_id": 1, "sdata": 66}]".getBytes()); // 发布消息 mqttClient.publish(MQTT_TOPIC_PUBLISH, message); } } --- ### 32. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 什么是MQTT? MQTT(消息队列遥测传输)是一种轻量级的发布/订阅消息传输协议,专为M2M(机器对机器)遥测在低带宽环境中设计。该协议由Andy Stanford-Clark(IBM)和Arlen Nipper于1999年为了通过卫星连接油管遥测系统而设计。最初是私有协议,2010年发布为免版税,2014年成为OASIS标准。 MQTT原名为“消息队列遥测传输”,现在简称为MQ遥测传输。随着物联网(IoT)部署的增加,它正迅速成为主要协议之一。 MQTT版本 MQTT v3.1.0 MQTT v3.1.1 – 目前普遍使用 MQTT v5 – 目前使用有限 MQTT-SN – 见后面的说明 MQTT最初设计于1999年,多年来一直在TCP/IP网络上使用。目前普遍使用的是MQTTv3.1.1版本。v3.1.0和v3.1.1版本之间的区别很小,GitHub上有一个页面详细介绍了这些主要区别。 最新的MQTT版本(v5),于2018年1月获批准。如果你想了解为什么没有v4版本,可以参考这里。 更多信息可参阅 MQTT v5.0的新功能概览。 MQTT-SN简介 MQTT-SN约在2013年制定,设计用于UDP、ZigBee等传输方式。目前MQTT-SN的普及程度不高,其规范多年未变,但随着物联网部署的开始,这一状况预计将改变。 MQTT客户端 MQTT客户端不像电子邮件地址、电话号码等拥有地址,因此你不需要为客户端分配地址,就像大多数消息系统一样。 对于MQTTv3.1.1,Eclipse Paho项目提供了几乎所有编程语言和主要操作系统(Linux、Windows、Mac)的客户端软件。 目前,Paho客户端v1.5.1已支持MQTTv5.0。 MQTT代理或服务器 最初的术语是代理,但现在已标准化为服务器。目前有许多MQTT代理可用于测试和实际应用。最受欢迎的自托管代理之一是Mosquitto,还有商业代理如HiveMQ。Mosquitto是一个免费的开源MQTT代理,可在Windows和Linux上运行。此外,Eclipse提供了一个免费的公共MQTT代理和COAP服务器,供测试使用。 MQTT通过WebSockets WebSockets允许将MQTT数据直接传送到Web浏览器。这很重要,因为Web浏览器可能成为显示MQTT数据的默认界面。JavaScript MQTT客户端提供了对Web浏览器的MQTT websocket支持。 MQTT安全性 MQTT支持多种认证和数据安全机制。需要注意的是,这些安全机制是在MQTT代理上配置的,客户端必须遵守所配置的机制。 MQTT课程 针对初学者的逐步指南——MQTT 3.1.1基础课程 常见问题 如果你熟悉Web和电子邮件,可能会发现MQTT与它们非常不同。以下是一些我遇到的问题,也在其他网站和论坛上看到的问题,可能会有所帮助: Q: MQTT通常使用哪个端口?A: 标准端口是1883。 Q: 能否在没有代理的情况下使用MQTT?A : 不可以,MQTT是基于代理的。 Q: MQTT如何处理多个客户端?A: MQTT服务器可以同时处理成千上万的客户端。 Q: MQTT是否支持广播消息?A: 是的,通过发布/订阅模型,MQTT支持广播。 --- ═══════════════════════════════════════════ ## MQTT 实例 ═══════════════════════════════════════════ ### 33. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 Hue2MQTT是一个Python应用程序,允许您通过MQTT协议控制飞利浦 Hue智能灯光系统,并实时发布其当前状态。该工具是使用Python 3.8+编写的,具有类型提示和异步支持,使用aiohue库与Hue通信,同时还支持IPv6。 2. 配置 Hue2MQTT的配置文件为".hue2mqtt.toml",以下是默认配置文件的示例: # Hue2MQTT 默认配置文件 [mqtt] # 使用host.docker.internal连接到在Docker主机上安装的MQTT代理 # host = "host.docker.internal" host = "::1" port = 1883 enable_tls = false force_protocol_version_3_1 = true enable_auth = false username = "" password = "" topic_prefix = "hue2mqtt" [hue] ip = "192.0.2.2" # 或IPv6:"[2001:db0::1]" username = "这里放您的密钥" 如果您不知道Hue桥的用户名,您可以使用以下命令进行查找: hue2mqtt --discover 3. 运行 Hue2MQTT 通常情况下,运行Hue2MQTT非常简单,只需在命令行中运行以下命令: hue2mqtt 您还可以使用一些选项,例如"-v"用于详细输出,"-c"用于指定配置文件,"-discover"用于发现Hue桥等。 4. 桥的状态 Hue2MQTT将桥的状态以JSON对象的形式发布到"hue2mqtt/status"主题,示例状态如下: {"online": true, "bridge": {"name": "Philips Hue", "mac_address": "ec:b5:fa:ab:cd:ef", "api_version": "1.45.0"}} 如果"online"为false,那么可以假定桥发布的所有其他信息都不准确。 5. 获取Hue信息 Hue2MQTT将有关Hue状态的信息作为MQTT保留消息发布。当状态发生更改时,将重新发布消息。 灯光:有关每个光源的信息将发布到"hue2mqtt/light/{{UNIQUEID}}"主题。这包括有关灯光的状态、属性和制造商信息。 组:组表示Hue应用程序中的房间和区域。有关每个组的信息将发布到"hue2mqtt/group/{{GROUPID}}"主题,包括组内灯光的状态、属性和制造商信息。 传感器:传感器代表Hue生态系统中的其他对象,例如开关和运动传感器。有关每个传感器的信息将发布到"hue2mqtt/sensor/{{UNIQUEID}}"主题,包括传感器的类型、属性和制造商信息。 6. 控制Hue 您可以通过发布JSON对象到"hue2mqtt/light/{{UNIQUEID}}/set"或"hue2mqtt/group/{{GROUPID}}/set"主题来控制灯光和组的操作。JSON对象应包含要更改的状态值。 7. Docker支持 Hue2MQTT还提供了一个包括Dockerfile和docker-compose示例的Docker工作环境,以方便部署。 8. 与Docker主机连接 要与Docker主机建立MQTT连接(假设localhost是Docker实例),请在配置文件"hue2mqtt.toml"中使用以下设置: host = "host.docker.internal" Hue2MQTT允许您通过MQTT控制飞利浦 Hue智能灯光系统,并通过MQTT接收实时事件,无需定期轮询Hue桥接器以获取更改。这使您可以轻松地将Hue集成到自动化解决方案中,以满足各种需求。 --- ### 34. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 WeConnect-MQTT是一个用于将大众汽车WeConnect服务数据发布到MQTT协议的客户端。MQTT(Message Queuing Telemetry Transport)是一种标准协议,用于集成来自WeConnect启用的汽车的数据。该客户端允许您将数据集成到您选择的MQTT代理中,例如家庭自动化解决方案(如ioBroker、FHEM或Home Assistant)。 2. 硬件和软件要求 在您的系统上安装Python 3是必需的,最低要求的Python版本为3.8。如果您的车型使用新的WeConnect API,您可能需要同意新的WeConnect接口的条款和条件。最简单的方式是在智能手机上安装大众汽车应用程序并在那里登录。 3. 安装 要使用WeConnect-MQTT,最简单的方式是从PyPI获取它。只需运行以下命令进行安装: pip3 install weconnect-mqtt 4. 升级 如果您希望升级WeConnect-MQTT,最简单的方式是运行以下命令: pip3 install weconnect-mqtt --upgrade 5. Docker支持 还提供了一个Docker镜像,以轻松托管WeConnect-MQTT,您可以在Dockerhub上找到它。 6. 使用说明 您可以通过命令行启动WeConnect-MQTT客户端: weconnect-mqtt 您可以使用"--help"命令来获取所有使用说明: weconnect-mqtt --help 以下是一个连接到MQTT代理地址为192.168.0.1,使用用户名test和密码test123的示例: weconnect-mqtt --username test@test.de --password test123 --mqttbroker 192.168.0.1 --mqtt-username test --mqtt-password test123 --prefix weconnect 在此示例中,客户端使用用户名test@test.de和密码test123连接到WeConnect。 7. S-PIN 对于某些命令(例如,某些车型支持的锁定/解锁功能),除了登录,您还需要提供S-PIN(安全个人识别码),您可以使用"--spin"选项来提供: weconnect-mqtt --username test@test.de --password test123 --spin 1234 --mqttbroker 192.168.0.1 --mqtt-username test --mqtt-password test123 --prefix weconnect 8. 凭据 如果您不想每次都提供用户名和密码,您可以在适当的位置(通常是主文件夹)创建一个".netrc"文件: # 对于WeConnect machine volkswagen.de login test@test.de password testpassword123 # 对于MQTT代理 machine 192.168.0.1 login test password testpassword123 您还可以使用"--netrc"选项来指定".netrc"文件的位置。 9. 充电站数据 您还可以通过添加位置和半径信息来获取充电站的数据,例如"--chargingLocation 52.437132 10.796628 --chargingLocationRadius=500"。充电站的数据主要是静态的,但您可以查看当前的可用性。 10. 主题 如果您的MQTT代理不允许您观察所有可用主题,您可以传递参数"--list-topics"以在命令行上显示所有主题。带有"(writeable)"标记的主题可以进行操作。还有两个主题,用于以逗号分隔的列表形式接收所有可用主题:"weconnect/0/mqtt/topics"和"weconnect/0/mqtt/writeableTopics"。 11. 禁用功能 您可以使用"--no-capabilities"选项来禁用车辆功能数据。如果只需要数据的子集,您可以使用"--selective"选项。例如,"--selective climatisation"。 12. 图像 您可以使用"--pictures"选项来启用汽车的ASCII Art图片。 13. PNG车辆图片 如果您的MQTT客户端可以处理通过MQTT接收的PNG图片,您可以使用"--picture-format png"选项。 14. 时间设置 默认情况下,车辆传来的时间是UTC isoformat。您可以通过添加"--convert-times"选项将时间转换为本地时区。要将时间设置为特定的时区,可以使用"--convert-times Europe/Berlin"。您还可以通过"--timeformat"将时间格式化为本地时间格式,例如"--timeformat '%a %d %b %Y %T'"。如果要使用不同于系统默认语言的日期格式,可以使用"--locale"选项。 15. 原始JSON数据 如果您想继续处理完整的数据,您还可以使用"--with-raw-json-topic"选项启用原始JSON数据主题。该主题在JSON字符串发生更改时发布。 16. 已测试车型 大众ID.3(2021年车型) 大众Passat GTE(2021年车型) 17. 相关项目 WeConnect-cli:用于与大众汽车WeConnect服务进行交互的命令行界面 WeConnect-python:连接到大众汽车WeConnect服务的Python API VWsFriend:VWsFriend是一款可视化记录汽车统计数据并允许通过HomeKit进行控制的软件。 通过WeConnect-MQTT,您可以轻松将大众汽车WeConnect服务的数据发布到MQTT,并将其集成到您的自动化解决方案中。这个客户端提供了丰富的功能和选项,使其非常灵活,适用于多种应用场景。 --- ═══════════════════════════════════════════ ## MQTT 客户端库 ═══════════════════════════════════════════ ### 35. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTTnet 是一个高性能的MQTT类库,支持.NET Core和.NET Framework。 MQTTnet 原理 MQTTnet 是一个用于.NET的高性能MQTT类库,实现了MQTT协议的各个层级,包括连接、会话、发布/订阅、QoS(服务质量)等。其原理涉及以下关键概念 1、MqttClient: MqttClient 是MQTTnet库中表示客户端的主要类。它负责与MQTT服务器建立连接,并处理消息的发布和订阅。 2、MqttServer: MqttServer 则表示MQTT服务器,负责接受客户端的连接,管理连接状态,并转发消息到相应的订阅 3、消息处理: MQTT消息分为发布消息和订阅消息。发布消息由客户端发送到服务器,然后由服务器广播给所有订阅者。 4、QoS(服务质量): MQTT支持不同级别的服务质量,包括0、1和2。MQTTnet允许你根据需要选择适当的QoS级别。 5、异步通信: MQTTnet广泛使用异步编程模型,允许并发处理多个连接,提高性能。 MQTTnet 优点 1、高性能: MQTTnet被设计为高性能的MQTT库,适用于处理大量的消息和连接。 2、跨平台: 支持.NET Core和.NET Framework,使其可以在不同的操作系统上运行。 3、灵活性: 提供了许多配置选项,允许你根据应用程序的需求进行调整。 4、WebSocket支持: 支持通过WebSocket协议进行通信,适用于Web应用程序。 5、活跃社区: MQTTnet有一个活跃的社区,提供了文档、示例和支持。 使用方法(服务端、客户端、WEB端) 下面是一个简单的示例,演示如何在.NET Core中使用MQTTnet创建一个基本的MQTT服务端和客户端。请注意,这个示例只是为了演示基本概念,实际应用中可能需要更多的配置和错误处理。 服务端示例 using System; using MQTTnet; using MQTTnet.Server; class Program { static async System.Threading.Tasks.Task Main(string[] args) { // 创建服务端配置 var optionsBuilder = new MqttServerOptionsBuilder() .WithDefaultEndpointPort(1883) .WithConnectionValidator(c => { Console.WriteLine($"Client connected: {c.ClientId}"); // 可以在这里添加连接验证逻辑 }); // 创建MQTT服务器实例 var mqttServer = new MqttFactory().CreateMqttServer(); // 处理连接成功事件 mqttServer.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(e => { Console.WriteLine($"Client connected: {e.ClientId}"); }); // 处理连接断开事件 mqttServer.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(e => { Console.WriteLine($"Client disconnected: {e.ClientId}"); }); // 处理接收到消息事件 mqttServer.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(e => { Console.WriteLine($"Received message from client {e.ClientId}: {e.ApplicationMessage.Payload}"); }); // 启动MQTT服务器 await mqttServer.StartAsync(optionsBuilder.Build()); Console.WriteLine("MQTT Server已启动。按任意键退出。"); Console.ReadLine(); // 停止MQTT服务器 await mqttServer.StopAsync(); } } 客户端示例 using System; using System.Text; using System.Threading; using System.Threading.Tasks; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; class Program { static async Task Main(string[] args) { // 创建客户端配置 var options = new MqttClientOptionsBuilder() .WithTcpServer("localhost", 1883) .WithClientId("Client1") // 客户端ID .Build(); // 创建MQTT客户端实例 var mqttClient = new MqttFactory().CreateMqttClient(); // 处理连接成功事件 mqttClient.UseConnectedHandler(e => { Console.WriteLine("Connected to MQTT Broker"); }); // 处理连接断开事件 mqttClient.UseDisconnectedHandler(e => { Console.WriteLine("Disconnected from MQTT Broker"); }); // 处理接收到消息事件 mqttClient.UseApplicationMessageReceivedHandler(e => { Console.WriteLine($"Received message: {e.ApplicationMessage.Payload}"); }); // 连接到MQTT服务器 await mqttClient.ConnectAsync(options, CancellationToken.None); // 发布消息 var message = new MqttApplicationMessageBuilder() .WithTopic("topic/test") .WithPayload("Hello, MQTT!") .WithExactlyOnceQoS() .WithRetainFlag() .Build(); await mqttClient.PublishAsync(message, CancellationToken.None); Console.WriteLine("Message published. Press any key to exit."); Console.ReadLine(); // 断开与MQTT服务器的连接 await mqttClient.DisconnectAsync(); } } Web端示例 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://cdnjs.cloudflare.com/ajax/libs/mqtt/4.0.0/mqtt.min.js"></script> <title>MQTT Web Client</title> </head> <body> <h1>MQTT Web Client</h1> <script> // 连接到MQTT服务器 const client = mqtt.connect('mqtt://your-mqtt-broker-url'); // 当连接成功时的处理逻辑 client.on('connect', function () { console.log('Connected to MQTT Broker'); // 订阅主题 client.subscribe('topic/test', function (err) { if (!err) { console.log('Subscribed to topic/test'); } }); // 发布消息 client.publish('topic/test', 'Hello, MQTT!'); }); // 当接收到消息时的处理逻辑 client.on('message', function (topic, message) { console.log('Received message:', message.toString()); }); // 处理连接断开事件 client.on('close', function () { console.log('Connection closed'); }); // 处理错误事件 client.on('error', function (err) { console.error('Error:', err); }); </script> </body> </html> 总结 以上代码中对连接断开事件处理(UseDisconnectedHandler、Web端的close事件)和错误事件处理(Web端的error事件)。 这些事件处理可以根据实际需求进一步扩展。 --- ### 36. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Async.MQTT5是一个基于Boost.Asio的C++20 MQTT客户端,专门为发布或接收与MQTT 5.0兼容的代理的消息而设计。这是一个全面实施MQTT 5.0协议标准的客户端,完全支持QoS 0、1和2级别的消息发布和接收。 Async.MQTT5 MQTT协议广泛用于现实世界的多种通信场景,主要作为IoT设备数据传输的可靠通信协议。虽然MQTT协议本身相对简单,但将其整合到应用程序中可能相当复杂,尤其是在断开/重连序列后消息重传的实现方面。 Async.MQTT5旨在为应用开发者提供一个非常简单的异步C++接口。内部客户端实现管理网络和MQTT协议细节。值得注意的是,客户端不暴露连接函数(或异步连接函数);相反,网络连接性、MQTT握手和消息重传都在客户端内部自动处理。 Async.MQTT5接口与Boost.Asio的异步模型无缝对接。客户端的异步函数与Boost.Asio支持的所有完成令牌兼容。 仓库地址:https://github.com/mireo/async-mqtt5 特点 Async.MQTT5是一个设计理念为用户只应专注于应用逻辑,而不是网络复杂性的库。该库试图通过以下一系列关键特性来提升开发体验: 完整的TCP、TLS/SSL和WebSocket支持 用户友好的简洁性:提供尽可能简单而不损功能的界面。 优先考虑效率:尽可能高效地利用网络和内存资源。 最小内存占用:确保在IoT设备典型的资源受限环境中优化性能。 自动重新连接:在断开连接的情况下自动尝试重新建立连接。 完全符合Boost.Asio规范:接口和实现策略基于Boost.Asio的基础。Boost.Asio和Boost.Beast的用户将不会在理解和整合Async.MQTT5时遇到问题。此外,Async.MQTT5与Boost.Asio生态系统中的任何其他库都能很好地整合。 自定义分配器:支持自定义分配器,允许对内存资源进行额外的灵活性和控制。Async.MQTT5将使用来自异步函数的处理器关联的分配器来创建库实现中所需的对象实例。 每项操作的取消:所有异步操作都支持Asio的每项操作取消。 完成令牌:所有异步函数都支持CompletionToken,允许使用回调、协程、futures等多种方式灵活使用。 完全实现MQTT 5.0规范 支持QoS 0、QoS 1和QoS 2 自定义认证:Async.MQTT5定义了一个接口,用于执行增强认证的自定义认证器。 高可用性:Async.MQTT5支持列出同一集群中多个客户端可以连接的代理。在与一个代理的连接失败时,客户端会切换到列表中的下一个。 离线缓冲:离线时,它会自动缓冲所有连接恢复时要发送的数据包。 使用该库 下载Boost,并将其添加到您的包含路径中。 如果使用SSL,请下载OpenSSL,链接库并将其添加到包含路径中。 另外,您可以将Async.MQTT5的包含文件夹添加到包含路径中。 您可以使用以下命令行在Linux上编译以下示例: $ clang++ -std=c++20 <source-cpp-file> -o example -I<path-to-boost> -Iinclude -pthread 使用和API 详细文档在这里。 以下示例演示了配置客户端并使用QoS 0发布“Hello World!”应用消息的简单场景。 #include <iostream> #include <boost/asio/io_context.hpp> #include <boost/asio/detached.hpp> #include <boost/asio/ip/tcp.hpp> #include <async_mqtt5.hpp> int main() { boost::asio::io_context ioc; using client_type = async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket>; client_type c(ioc, ""); c.credentials("<your-client-id>", "<client-username>", "<client-pwd>") .brokers("<your-mqtt-broker>", 1883) .run(); c.async_publish<async_mqtt5::qos_e::at_most_once>( "<topic>", "Hello world!", async_mqtt5::retain_e::no, async_mqtt5::publish_props {}, [&c](async_mqtt5::error_code ec) { std::cout << ec.message() << std::endl; c.async_disconnect(boost::asio::detached); // disconnect and close the client } ); ioc.run(); } 为什么选择它? 如果以下任何一种情况适用于您,则Async.MQTT5可能适合您: 您的应用程序使用Boost.Asio并需要集成MQTT客户端。 您需要异步访问MQTT代理。 您正在开发需要连接到MQTT代理的高级组件。 您需要一个可靠且有韧性的MQTT客户端,可以自动管理所有与网络相关的问题。 如果以下情况使用,则可能不适合您: 您仅需要同步访问MQTT代理。 您连接的MQTT代理不支持MQTT 5版本。 需求 Async.MQTT5是一个仅头文件的库。要使用Async.MQTT5,需要以下条件: C++20兼容的编译器 Boost 1.82或更高版本。除了Asio,我们还使用了Beast、Spirit等其他仅头文件的库。 OpenSSL。仅当您通过使用boost::asio::ssl::stream需要SSL连接时。 Async.MQTT5已在以下编译器上进行了测试: clang 14.0(Linux) MSVC 14.37 - Visual Studio 2022(Windows) 总结 Async.MQTT5是一个基于Boost.Asio的专业C++20 MQTT客户端,专为发布或接收与MQTT 5.0兼容代理的消息而设计。这个客户端提供了MQTT 5.0协议标准的全面实现,并全面支持QoS 0、1和2的消息发布和接收。 Async.MQTT5的目的是为应用开发者提供一个非常简单的异步C++接口,以简化MQTT协议的集成和使用。它自动处理网络连接、MQTT握手和消息重传,使用户可以专注于应用逻辑。 Async.MQTT5提供了包括TCP、TLS/SSL和WebSocket支持、最小内存占用、自动重新连接等特性,使其在IoT设备环境中表现出色。此外,它支持自定义分配器和每项操作的取消,使其在高度定制化的应用场景中也能灵活应用。 使用Async.MQTT5,您只需下载Boost和(如需SSL支持)OpenSSL,并将它们添加到包含路径中。它是一个头文件库,不需要额外的编译步骤。 Async.MQTT5适用于需要集成MQTT客户端的Boost.Asio应用程序,或那些需要稳定、自动管理网络问题的高级MQTT客户端的场景。然而,如果您只需要同步访问MQTT代理或使用的MQTT代理不支持MQTT 5版本,它可能不适合您。 最后,Async.MQTT5已经在Linux和Windows平台的最新编译器上进行了测试,保证了其广泛的兼容性和稳定性。 --- ### 37. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着物联网(IoT)时代的到来,设备间的高效通信成为实现智能化的关键。在众多通信协议中,消息队列遥测传输(MQTT)因其轻量级、高效、易于实现等特点,在物联网领域获得了广泛应用。Eclipse Paho项目提供了一系列开源客户端实现,其中paho.mqtt.android是专为Android平台设计的MQTT客户端库。本文将深入探索paho.mqtt.android的特性、应用场景及其在物联网领域的重要性。 仓库地址: https://github.com/eclipse/paho.mqtt.android MQTT协议简介 MQTT(Message Queuing Telemetry Transport)是一个基于发布/订阅模式的轻量级消息传输协议,设计用于低带宽和不稳定的网络环境。由于其设计简单,易于实现,它在移动应用和小型设备中特别受欢迎。 Eclipse Paho项目概述 Eclipse Paho是一个提供开源MQTT和MQTT-SN客户端的项目。Paho是Eclipse物联网社区的一部分,其目标是促进M2M(机器对机器)和IoT(物联网)通信的开放标准和实现。 Paho Android客户端特性 支持MQTT 3.1和3.1.1:兼容主流的MQTT协议版本。 遗嘱消息(LWT):允许客户端设置在异常断开时的遗嘱消息。 SSL/TLS支持:提供加密传输,保证通信安全。 自动重连和离线缓冲:网络不稳定时自动重连,离线时缓存消息。 WebSocket支持:除了标准TCP连接外,还支持通过WebSocket连接。 消息持久化:保证消息的可靠传输。 使用场景和应用 Paho MQTT Android客户端适用于需要在Android设备上实现MQTT通信的各种场景,如智能家居控制、环境监测、远程设备管理等。在这些场景中,客户端可以订阅来自传感器的数据,发布控制命令给执行设备,或者实现设备间的数据交换。 如何开始使用 要开始使用Paho MQTT Android客户端,开发者需要先在Android Studio中设置项目,并引入相关依赖。可以通过Maven或Gradle来管理这些依赖。使用Paho客户端之前,还需要对MQTT协议有一定的了解,包括其工作原理、QoS(服务质量)等级等。 Maven Eclipse为希望通过Maven管理依赖的用户提供了一个Nexus仓库。 将以下仓库定义和依赖定义添加到您的pom.xml文件中。 将%REPOURL%替换为官方发布版本的链接https://repo.eclipse.org/content/repositories/paho-releases/,或者替换为每夜快照版本的链接https://repo.eclipse.org/content/repositories/paho-snapshots/。将%VERSION%替换为所需的版本号。最新的发布版本是1.1.1,当前的快照版本是1.1.2-SNAPSHOT。 <project ...> <repositories> <repository> <id>Eclipse Paho Repo</id> <url>%REPOURL%</url> </repository> </repositories> ... <dependencies> <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.android.service</artifactId> <version>%VERSION%</version> </dependency> </dependencies> </project> Gradle 如果您使用Android Studio和/或Gradle来管理您的应用依赖和构建,那么您可以使用相同的仓库获取Paho Android服务。将Eclipse Maven仓库添加到您的build.gradle文件中,然后将Paho依赖添加到依赖项部分。 repositories { maven { url "https://repo.eclipse.org/content/repositories/paho-snapshots/" } } dependencies { compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0' compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' } 注意:目前您还需要包括org.eclipse.paho:org.eclipse.paho.client.mqttv3依赖。我们正在尝试让构建生成一个包含Android服务及其依赖的Android AAR文件,但这仍然是实验性的。如果您想尝试它,请移除org.eclipse.paho:org.eclipse.paho.client.mqttv3依赖,并在Android服务依赖的末尾添加@aar。例如:org.eclipse.paho:org.eclipse.paho.android.service:1.1.1@aar 如果您发现发布版本中缺少功能或存在bug,您可能想尝试使用快照版本,看看这是否有帮助,然后再提出功能请求或问题。 构建自己的MQTT应用 开发者可以利用Paho MQTT Android客户端构建自己的MQTT应用。例如,在智能家居场景中,通过MQTT协议,手机可以作为控制中心,发布消息来控制家中的智能设备,如灯光、空调等。 开源社区的贡献 作为一个开源项目,Paho鼓励开发者参与贡献,无论是通过报告bug,提交新功能的请求,还是直接贡献代码。社区的活跃参与对项目的持续改进至关重要。 未来展望 随着IoT技术的不断发展,MQTT协议及其客户端实现,如paho.mqtt.android,将在连接众多设备和实现智能化方面扮演越来越重要的角色。未来,我们可以期 待更多基于MQTT的创新应用出现,推动物联网技术的进一步发展。 结语 paho.mqtt.android作为一个轻量级且功能丰富的MQTT客户端,为Android开发者提供了一个强大的工具,以简化物联网应用的开发。随着物联网的快速发展,它无疑将成为连接智能设备的重要桥梁。通过Eclipse Paho项目和其它类似的开源努力,物联网的未来将变得更加智能、互联和无缝。 --- ### 38. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 架构 介绍 在本教程中,我们将学习创建物联网应用程序的数据流处理所需的内容。 在这个过程中,我们将了解物联网架构的特点,并了解如何利用MQTT代理、NiFi和InfluxDB等不同工具来构建高度可扩展的物联网应用程序的数据流处理。 物联网及其架构 首先,让我们学习一些基本概念,了解物联网应用程序的一般架构。 2.1. 什么是物联网? 物联网(IoT)广泛指的是物理对象的网络,称为“物”。例如,这些物可以包括从普通家用物品(如灯泡)到复杂的工业设备等任何物。通过这个网络,我们可以连接各种传感器和执行器以交换数据。 现在,我们可以在非常不同的环境中部署这些物 - 例如,环境可以是我们的家,也可以是一辆行驶中的货车。然而,我们不能对这些物将可以使用的电源和网络的质量进行任何假设。因此,这为物联网应用程序提出了独特的要求。 2.2. 物联网架构简介 典型的物联网架构通常分为四个不同的层次。让我们了解数据如何在这些层次之间流动: 首先,感知层主要由从环境中收集测量数据的传感器组成。然后,网络层帮助聚合原始数据并通过互联网进行传输。进一步,数据处理层会过滤原始数据并生成早期分析。最后,应用层使用强大的数据处理能力来执行更深入的数据分析和管理。 MQTT、NiFi和InfluxDB简介 现在,让我们来看看今天在物联网设置中广泛使用的一些产品。这些产品都提供了一些独特的特性,使它们适用于物联网应用程序的数据需求。 3.1. MQTT MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布-订阅网络协议。它现在是OASIS和ISO标准。IBM最初开发它用于在设备之间传输消息。MQTT适用于内存、网络带宽和电源供应有限的受限环境。 MQTT遵循客户端-服务器模型,不同组件可以充当客户端并通过TCP连接到服务器。我们将此服务器称为MQTT代理。客户端可以将消息发布到称为主题的地址。它们还可以订阅主题并接收发布到它的所有消息。 在典型的物联网设置中,传感器可以将测量数据(如温度)发布到MQTT代理,而上游数据处理系统可以订阅这些主题以接收数据: 正如我们所见,MQTT中的主题是分层的。系统可以通过使用通配符轻松订阅整个主题层次结构。 MQTT支持三个不同的服务质量(QoS)级别。它们分别是“至多传递一次”、“至少传递一次”和“确保仅传递一次”。QoS定义了客户端与服务器之间的协议级别。每个客户端可以选择适合其环境的服务级别。 客户端还可以在发布时请求代理保留消息。在某些设置中,MQTT代理可能需要从客户端那里进行用户名和密码验证以建立连接。此外,出于隐私考虑,TCP连接可能会使用SSL/TLS进行加密。 有几个MQTT代理实现和客户端库可供使用,例如HiveMQ、Mosquitto和Paho MQTT。在本教程中,我们将使用Mosquitto作为示例。Mosquitto是Eclipse基金会的一部分,我们可以轻松地将其安装在树莓派或Arduino等开发板上。 3.2. Apache NiFi Apache NiFi最初由美国国家安全局(NSA)开发,是一种自动化和数据流管理工具,基于基于流的编程模型,将应用程序定义为黑盒进程网络。 首先,让我们先了解一些基本概念。在NiFi中,系统中移动的对象称为FlowFile。FlowFile处理器实际上执行诸如路由、转换和调解FlowFiles等有用工作。FlowFile处理器通过连接与连接一起使用。 处理组是一种将组件组合在一起以组织NiFi数据流的机制。处理组可以通过输入端口接收数据并通过输出端口发送数据。远程处理组(RPG)提供了一种从远程NiFi实例发送数据或接收数据的机制。 现在,有了这些知识,让我们了解NiFi架构: NiFi是一个基于Java的程序,运行在JVM中的多个组件。Web服务器是托管命令和控制API的组件。流控制器是NiFi的核心组件,负责管理扩展何时接收资源以执行。扩展允许NiFi具有可扩展性,并支持与不同系统的集成。 NiFi通过FlowFile存储库跟踪FlowFile的状态。FlowFile的实际内容字节存储在内容存储库中。与FlowFile相关的可信事件数据存储在可信存储库中。 由于数据在源头的收集可能需要较小的占用空间和低资源消耗,NiFi有一个名为MiNiFi的子项目。MiNiFi提供了一种补充的数据收集方法,可以通过Site-to-Site(S2S)协议轻松集成到NiFi中。 此外,它通过MiNiFi命令和控制(C2)协议实现了对代理的集中管理。此外,它有助于建立数据溯源,生成完整的链式保管信息。 3.3. InfluxDB InfluxDB是由InfluxData开发的,使用Go编写的时序数据库。它专为快速和高可用性的时序数据存储和检索而设计。这在处理应用程序指标、物联网传感器数据和实时分析方面特别合适。 首先,InfluxDB中的数据是按时序组织的。时序可以包含零个或多个数据点。数据点代表具有四个组成部分的单个数据记录,包括测量、标签集、字段集和时间戳: 首先,时间戳显示与特定数据点关联的UTC日期和时间。字段集由一个或多个字段键和字段值对组成。它们捕获了点的实际数据,并附带标签。标签集也由标签键和标签值对组成,但它们是可选的。它们基本上充当点的元数据,并可用于加快查询响应。 测量充当标签集、字段集和时间戳的容器。此外,InfluxDB中的每个数据点都可以与其关联的保留策略。保留策略描述了InfluxDB将保留数据的时间以及通过复制将创建多少副本。 最后,数据库充当用户、保留策略、连续查询和时序数据的逻辑容器。我们可以将InfluxDB中的数据库理解为与传统关系数据库 loosly 相似。 此外,InfluxDB是InfluxData平台的一部分,提供了多种其他产品来高效处理时序数据。InfluxData现在将其作为InfluxDB OSS 2.0(开源平台)和InfluxDB Cloud(商业产品)提供: 除了InfluxDB之外,该平台还包括Chronograf,它为InfluxData平台提供了完整的界面。此外,它包括Telegraf,用于收集和报告度量和事件的代 理。最后,还有Kapacitor,一个实时流式数据处理引擎。 实践物联网数据管道 现在,我们已经掌握了足够的知识,可以将这些产品一起使用,为我们的物联网应用程序创建数据管道。在本教程中,我们假设我们正在从多个城市的多个观测站收集与空气质量相关的测量数据。例如,这些测量包括地面臭氧、一氧化碳、二氧化硫、二氧化氮和气溶胶等。 4.1. 基础设施设置 首先,我们假设每个城市的气象站都配备了所有感应设备。此外,这些传感器已连接到类似Raspberry Pi的开发板,用于收集模拟数据并将其数字化。该板通过无线连接发送原始测量数据: 物联网基础设施设置一个区域控制站收集来自城市中所有气象站的数据。我们可以汇总并将此数据提供给一些本地分析引擎,以获得更快的见解。来自所有区域控制中心的经过筛选的数据被发送到中央指挥中心,该中央指挥中心通常托管在云中。 4.2. 创建物联网架构 现在,我们准备为我们的简单空气质量应用程序设计物联网架构。在这里,我们将使用MQTT代理、MiNiFi Java代理、NiFi和InfluxDB: 正如我们所看到的,我们在气象站点使用了Mosquitto MQTT代理和MiNiFi Java代理。在区域控制中心,我们使用NiFi服务器来汇总和路由数据。最后,我们使用InfluxDB来存储中央指挥中心级别的测量数据。 4.3. 执行安装 在像Raspberry Pi这样的开发板上安装Mosquitto MQTT代理和MiNiFi Java代理非常容易。但是,对于本教程,我们将在本地计算机上安装它们。 Eclipse Mosquito的官方下载页面提供了多个平台的二进制文件。一旦安装完成,可以从安装目录轻松启动Mosquitto: net start mosquitto 此外,NiFi二进制文件也可以从其官方网站下载。我们必须在合适的目录中提取下载的存档。由于MiNiFi将使用站点到站点协议连接到NiFi,因此必须在/conf/nifi.properties中指定站点到站点输入套接字端口: # Site to Site properties nifi.remote.input.host= nifi.remote.input.secure=false nifi.remote.input.socket.port=1026 nifi.remote.input.http.enabled=true nifi.remote.input.http.transaction.ttl=30 sec 然后,我们可以启动NiFi: <NIFI_HOME>/bin/run-nifi.bat 同样,可以从官方网站下载Java或C++ MiNiFi代理和工具包二进制文件。同样,我们必须将存档提取到适当的目录中。 默认情况下,MiNiFi附带一组非常少的处理器。因为我们将从MQTT中获取数据,所以必须将MQTT处理器复制到/lib目录。这些处理器捆绑为NiFi Archive (NAR)文件,并位于/lib目录中: COPY <NIFI_HOME>/lib/nifi-mqtt-nar-x.x.x.nar <MINIFI_HOME>/lib/nifi-mqtt-nar-x.x.x.nar 然后,我们可以启动MiNiFi代理: <MINIFI_HOME>/bin/run-minifi.bat 最后,可以从其官方网站下载InfluxDB的开源版本。与以前一样,可以提取存档,并使用简单的命令启动InfluxDB: <INFLUXDB_HOME>/influxd.exe 对于本教程,我们应该保留所有其他配置,包括端口,以默认值。这完成了我们在本地计算机上的安装和设置。 4.4. 定义NiFi数据流 现在,我们已经准备好定义我们的数据流。NiFi提供了一个易于使用的界面,用于创建和监控数据流。这可通过URL http://localhost:8080/nifi 访问。 首先,我们将定义将在NiFi服务器上运行的主数据流: 如我们所见,我们定义了一个输入端口,该端口将从MiNiFi代理接收数据。它通过连接将数据发送到PutInfluxDB处理器,该处理器负责将数据存储在InfluxDB中。在此处理器的配置中,我们定义了InfluxDB的连接URL以及要发送数据的数据库名称。 4.5. 定义MiNiFi数据流 接下来,我们将定义在MiNiFi代理上运行的数据流。我们将使用NiFi的相同用户界面,并将数据流导出为模板,然后在MiNiFi代理中进行配置。让我们定义MiNiFi代理的数据流: 在这里,我们定义了ConsumeMQTT处理器,负责从MQTT代理获取数据。我们在属性中提供了代理URI以及主题过滤器。我们正在从层次结构"air-quality"下定义的所有主题中获取数据。 我们还定义了一个远程处理组,并将其连接到ConcumeMQTT处理器。远程处理组负责通过站点到站点协议将数据推送到NiFi。 我们可以将此数据流保存为模板,并将其下载为XML文件。让我们将此文件命名为config.xml。现在,我们可以使用转换工具包将此模板从XML转换为MiNiFi代理使用的YAML格式: <MINIFI_TOOLKIT_HOME>/bin/config.bat transform config.xml config.yml 这将生成config.yml文件,其中我们必须手动添加NiFi服务器的主机和端口: Input Ports: - id: 19442f9d-aead-3569-b94c-1ad397e8291c name: From MiNiFi comment: '' max concurrent tasks: 1 use compression: false Properties: # Deviates from spec and will later be removed when this is autonegotiated Port: 1026 Host Name: localhost 现在,我们可以将此文件放入/conf目录,替换可能已经存在的文件。之后,我们需要重新启动MiNiFi代理。 在这里,我们需要手动进行大量工作来创建数据流并在MiNiFi代理中进行配置。这在实际情况下是不切实际的,因为遥远的地点可能存在数百个代理。然而,正如我们之前所看到的,我们可以使用MiNiFi C2服务器来自动化此过程。但这超出了本教程的范围。 4.6. 测试数据管道 最后,我们准备测试我们的数据管道!由于我们无法使用真实传感器,我们将创建一个小型模拟。我们将使用一个小的Java程序生成传感器数据: class Sensor implements Callable<Boolean> { String city; String station; String pollutant; String topic; Sensor(String city, String station, String pollutant, String topic) { this.city = city; this.station = station; this.pollutant = pollutant; this.topic = topic; } @Override public Boolean call() throws Exception { MqttClient publisher = new MqttClient( "tcp://localhost:1883", UUID.randomUUID().toString()); MqttConnectOptions options = new MqttConnectOptions(); options.setAutomaticReconnect(true); options.setCleanSession(true); options.setConnectionTimeout(10); publisher.connect(options); IntStream.range(0, 10).forEach(i -> { String payload = String.format("%1$s,city=%2$s,station=%3$s value=%4$04.2f", pollutant, city, station, ThreadLocalRandom.current().nextDouble(0, 100)); MqttMessage message = new MqttMessage(payload.getBytes()); message.setQos(0); message.setRetained(true); try { publisher.publish(topic, message); Thread.sleep(1000); } catch (MqttException | InterruptedException e) { e.printStackTrace(); } }); return true; } } 在这里,我们使用Eclipse Paho Java客户端生成消息并发送到MQTT代理。我们可以添加尽可能多的传感器以创建我们的模拟: ExecutorService executorService = Executors.newCachedThreadPool(); List<Callable<Boolean>> sensors = Arrays.asList( new Simulation.Sensor("london", "central", "ozone", "air-quality/ozone"), new Simulation.Sensor("london", "central", "co", "air-quality/co"), new Simulation.Sensor("london", "central", "so2", "air-quality/so2"), new Simulation.Sensor("london", "central", "no2", "air-quality/no2"), new Simulation.Sensor("london", "central", "aerosols", "air-quality/aerosols")); List<Future<Boolean>> futures = executorService.invokeAll(sensors); 如果一切正常,我们将能够在InfluxDB数据库中查询我们的数据: 例如,我们可以查看属于“ozone”测量的所有数据点,这些数据存储在数据库“airquality”中。 结论 总之,本教程涵盖了一个基本的IoT用例。我们还了解了如何使用MQTT、NiFi和InfluxDB等工具来构建可扩展的数据管道。当然,这并不涵盖IoT应用程序的全部范围,扩展数据分析管道的可能性是无限的。 此外,本教程中选择的示例仅供演示目的。实际的IoT应用程序的基础架构和架构可以非常多样化和复杂。此外,我们可以通过将可操作的见解作为命令向后推送来完成反馈循环。 --- ### 39. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 介绍 正如我们可能已经知道的那样,Node.js是一个异步和事件驱动的JavaScript运行时和引擎,为今天存在的许多基于服务器端的、网络化的应用程序提供动力。在本文中,我们将探讨Node.js与MQTT的互动,MQTT是一种用于物联网(IoT)世界的发布/订阅(pub/sub)协议和标准。 在本文中,我们计划仅涵盖重要的公共MQTT API和函数,并探讨Node.js中的简单发布者和订阅者脚本。 什么是MQTT? 1999年,IBM的Andy Standford-Clark和Arlen Nipper设计了MQTT协议的最初版本。当时的目标是构建一个支持低带宽、轻量级且消耗最少资源的协议,因为通过卫星链路连接的设备非常昂贵。 该规范有两个版本:MQTT 3.1.1和MQTT 5.0.0。大多数商业MQTT代理现在支持MQTT 5,但许多IoT托管云服务仅支持MQTT 3.1.1,这曾经是最受欢迎和广泛支持的版本。 强烈建议新的IoT部署使用5.0.0版本(2018年批准),因为其新功能更侧重于强大的系统和云原生可伸缩性。您可以在MQTT的GitHub页面上阅读有关两个版本之间的亮点和详细差异的更多信息。 今天的用途 MQTT是一种轻量级的客户端-服务器协议,实现了发布/订阅消息传输模型,并已用于连接关键的IoT应用程序、机器对机器(M2M)通信和许多其他需要具有有限带宽但卓越性能的消息传输平滑界面的领域。这是其简单的设计、易用性和开放规范的结果。 自2014年以来,MQTT一直由OASIS技术指导委员会管理。该委员会负责维护、更新和维护该标准,包括组织用例文档和保护其知识产权。 它依赖于TCP/IP,这是一个可靠的、面向连接的低级网络堆栈,传输层独立于数据有效载荷结构,实现了一种有序和正确的双向主机对主机的通信模型。 发布/订阅模式还允许消息从一个应用程序分发到许多不同的应用程序。但在这种情况下,发布者和订户通常是独立的应用程序(解耦),只通过代理或服务器连接。例如,流行的发布/订阅消息平台RabbitMQ在内部使用了MQTT。 MQTT的用例 MQTT已经找到了许多用例,我们将在下面探讨其中一些。 启用消息广播:客户端可以发布消息或有效载荷到多个其他客户端应用程序,当然,这些应用程序需要通过代理事先通过主题订阅这些消息. 提供轻量级和最小的消息头/资源:这允许在消息传输中使用最小的带宽,因此MQTT可以有效地扩展以服务数百万个IoT设备 在其核心,它提供了可靠的消息传输或交付:大多数IoT设备都依赖于这一点,但从高层次上看,MQTT定义了保证消息传输得以处理的服务层 构建高度安全的消息传输应用程序:MQTT在这方面非常出色,因为消息有效载荷可以使用TLS和其他现代身份验证机制(如OAUTH)进行加密和安全保护 确保客户端应用程序具有持久连接:这对于网络连接可能不稳定的区域中的临时消息存储非常方便 相关的是,MQTT有助于减少在信号差的蜂窝网络上设备重新连接所需的时间 在不同行业和领域找到应用,包括汽车、石油和天然气、制造、物流、交通和智能家居设备行业 您可以在MQTT文档的用例页面上找到有关这些信息的更多详细信息。最受欢迎的开源家庭自动化项目之一,Home Assistant,基于MQTT协议。 MQTT的发布/订阅架构 MQTT协议包括代理(broker),它充当中央服务器,将发布者客户端的消息引导到订阅者客户端,以及一个或多个客户端应用程序,可以是消息或数据的订阅者或发布者。 代理可以看作是邮递员,确保消息被传递给其各自的接收者。它们应该被设计成高度可扩展和安全的,因为它们是MQTT客户端的中心关注点。 在高层次上,代理充当一个网关,将发布的消息从发布者应用程序路由到适当的订阅者。通常情况下,代理可以部署在多个集群或实例上,并置于负载均衡器后,以提高容错性。MQTT客户端将消息发布到中央代理(通常是到主题),其他客户端可以订阅代理上的相同主题以接收这些消息。 因此,一个客户端将消息发布到主题,而其他客户端订阅该主题,表示它们有兴趣接收相关消息。代理具有一种过滤机制,用于控制应该将消息发送给哪些订阅者。这意味着代理检查或筛选特定主题或主题组上的订阅者(或订阅者列表),然后将消息发送给它们。 总之,代理读取、确认和处理来自发布者客户端或应用程序的消息(包括确定主题的订阅者以及将所有适当的消息发送给它们)。 注意:MQTT依赖一种过滤消息的方式,代理将消息发送给对获取消息内容感兴趣的订阅者。消息通常包含一个主题,代理使用该主题来确定如何将特定消息路由到适当的订阅客户端。 基于主题的过滤涉及客户端(发布者和订阅者)通过主题与代理进行交互,主题是每个消息有效载荷的一部分。 到目前为止,我们已经使用了一些对一些读者可能听起来很新的技术术语。在下一节中,我们将探讨一些这些术语及其含义。 一些MQTT技术概念解释 桥接(Bridge) - 两个MQTT代理之间的连接 MQTT客户端(MQTT client) - 连接到经过安全网络连接的MQTT代理的设备或使用MQTT客户端库编写的应用程序;MQTT客户端可以是发布者或订阅者应用/客户端 消息(Message) - 简单地说,要发布的消息,可以是缓冲区(Buffer)、字符串(String)或JSON对象 主题(Topics) - 代理用于过滤并将适当的消息发送到连接的客户端的字符串标识符。主题名称通常以层次结构的方式进行构建,带有分隔符,称为主题级别 (注意,消息必须包含代理可以使用的主题,以适当地路由有效载荷到感兴趣的客户端) 示例主题名称:mytopic/homeautomation/closedoor 发布者(Publisher) - 发布者客户端将数据或消息分发到服务器/代理上的主题,供其他可能有兴趣获取这些消息的订阅者客户端使用 物联网(IoT) - 由嵌入式系统、自动化设备、无线网络和控制机制组成的连接设备的世界 解耦(Decoupling) - 在这种情况下,解耦意味着发布者/订阅者只需要知道代理的主机名/IP和端口 - 不像传统的客户端-服务器架构,其中客户端和服务器通过端点/API直接通信,通常以URI格式进行通信。 在应用级别使用MQTT 现在,让我们看看MQTT在应用级别是如何工作的。我们将使用MQTT的Node.js客户端库mqtt.js。 MQTT.js是MQTT协议的开源JavaScript库,适用于Node.js和浏览器。通常,该库可用于发布消息和订阅MQTT代理上的主题。 关于MQTT.js库的一些要点 支持ES模块和Common.js样式的文件导入 它具有基于Promise的API接口,因为MQTT本身是异步工作的 MQTT.js默认使用旧的MQTT v3.1.1,以支持旧代理,但当前的最新版本是5.0 MQTT客户端带有内置的错误处理程序,在程序员未能处理其代码中的错误时非常有用 请注意,还有可用于各种编程语言和主要操作系统(Linux、Windows和macOS)的客户端库。 连接/断开MQTT代理/服务器 客户端连接始终由代理/服务器处理,因为MQTT订阅者和发布者是独立的、解耦的应用程序。正如我们之前提到的,发布者和订阅者都是MQTT客户端,因此需要连接到同一个代理/服务器。 客户端永远不会直接连接到彼此;连接通常是在一个客户端和代理之间通过TCP/IP进行的。其他MQTT实现或变种也可以通过UDP连接(MQTT<-SN)。代理负责: 接收所有消息 通过确定哪个订阅客户端订阅每条消息来筛选适当的消息 保持客户端之间的连接/会话 对客户端进行身份验证和授权 将消息发送给正确的客户端 代理应该容易扩展并集成到不同的后端系统中。它们可以具有相当高的容错性,因为它们是发布者/订阅者通信的最关键点。 要首次连接到代理,客户端发送CONNECT消息。一旦启动,代理将返回一个CONNACK消息和一个状态代码。还需要注意的一点是,代理始终保持连接处于活动状态,除非客户端发送断开事件或其互联网连接中断。 目前有一些流行的免费托管的MQTT代理。Eclipse的Mosquitto就是其中之一,它可以运行在所有主要操作系统上。 还有其他商业云端或托管的代理,比如HIVEMQ。如果我们不打算安装和管理自己的代理,它们通常会非常方便。您可以在MQTT网站上找到用于快速测试的优秀MQTT代理。 安装我们的客户端库 要安装MQTT.js,请运行以下命令: npm install mqtt --save 请注意,MQTT.js捆绑了与代理进行交互的命令。要使MQTT协议接口可用于系统路径,我们可以全局安装它: npm install mqtt -g 安装完成后,我们的package.json文件应如下所示: // package.json { "name": "mqtt-demo", "version": "1.0.0", "description": "一个Node.js和MQTT演示", "main": "index.js", "scripts": { "start-publisher": "nodemon publisher.js", "start-consumer": "nodemon subscriber.js" }, "keywords": [ "Node.js", "MQTT", "Pub/Sub", "IoT", "message", "transport" ], "author": "Alexander Nnakwue", "license": "MIT", "dependencies": { "dotenv": "^10.0.0", "mqtt": "^4.3.2" }, "devDependencies": { "nodemon": "^2.0.15" } } 要测试程序,可以在一个终端窗口上运行发布者,然后在另一个终端窗口上运行订阅者。 创建一个MQTT发布客户端 现在,让我们创建一个发布消息的MQTT客户端。为此,我们可以导入MQTT.js库并使用connect方法。 const mqtt = require('mqtt'); require('dotenv').config(); const clientId = 'mqttjs_' + Math.random().toString(8).substr(2, 4); const client = mqtt.connect(process.env.BROKER_URL, { clientId: clientId }); 请注意,我们已经将BROKER_URL添加到我们的环境文件中。如我们所见,connect方法接受给定的URL(代理服务器URL)和可选的服务器选项对象。接受的协议可以是MQTT、ws、wss、tcp、tls等等。connect方法返回一个已连接的客户端。 为了在MQTT客户端连接中断时尝试重新连接,我们可以将reconnectPeriod选项(两次重新连接之间的时间间隔)设置为大于零。默认值为1秒,这意味着在断开连接后,它会几乎立即尝试重新打开连接。 const client = mqtt.connect(process.env.BROKER_URL, { clientId: clientId, clean: false, reconnectPeriod: 1 }); 如果将reconnectPeriod客户端选项的值设置为0,则将禁用重新连接,并在连接断开时终止。 当将resubscribe选项设置为其默认值(true)时,客户端可以在连接中断时自动重新连接和重新订阅先前订阅的主题。尤其是对于自托管的代理,我们可能需要使用用户名和密码进行身份验证。有关服务器选项对象的更多详细信息可以在MQTT GitHub上找到。 发布数据和消息 一旦连接到代理,MQTT客户端几乎可以立即发送消息。发布事件需要消息负载和主题名称,代理可以使用它来识别订阅方。此外,还有一个回调选项,用于检查错误或消息数据包是否已传输。 发送的消息类型或数据包具有以下属性: topicName dupFlag qos payload packetId或messageId retainFlag { cmd: 'publish', topic: 'test/connection', payload: '{"1":"Hello world","2":"Welcome to the test connection"}', qos: 1, retain: true, messageId: 12041, dup: false } 命令,如下所示。 当客户端向代理发送消息时,代理会根据开发人员设置的某些标准来处理消息。这应该包括QoS级别,它确定消息达到预期接收方的保证类型,并确保消息传递保证。 处理阶段通常涉及读取消息、确认消息和识别订阅主题的客户端。最后一步是将消息发送给订阅的客户端。 以下是publisher.js文件的完整代码,包括一些公共方法/API: //publisher.js const mqtt = require('mqtt') require('dotenv').config() //the client id is used by the MQTT broker to keep track of clients and and their // state const clientId = 'mqttjs_' + Math.random().toString(8).substr(2, 4) const client = mqtt.connect(process.env.BROKER_URL, {clientId: clientId, clean: false}); // console.log(process.env.BROKER_URL, 'client', clientId) const topicName = 'test/connection' client.on("connect",function(connack){ console.log("client connected", connack); // on client connection publish messages to the topic on the server/broker const payload = {1: "Hello world", 2: "Welcome to the test connection"} client.publish(topicName, JSON.stringify(payload), {qos: 1, retain: true}, (PacketCallback, err) =&gt; { if(err) { console.log(err, 'MQTT publish packet') } }) //assuming messages comes in every 3 seconds to our server and we need to publish or process these messages setInterval(() =&gt; console.log("Message published"), 3000); }) client.on("error", function(err) { console.log("Error: " + err) if(err.code == "ENOTFOUND") { console.log("Network error, make sure you have an active internet connection") } }) client.on("close", function() { console.log("Connection closed by client") }) client.on("reconnect", function() { console.log("Client trying a reconnection") }) client.on("offline", function() { console.log("Client is currently offline") }) 接下来,我们可以继续实现订阅客户端,该客户端会接收主题上的消息。 订阅消息为了接收我们感兴趣的主题的消息,客户端通过subscribe事件向代理发送订阅请求。所订阅的消息通常包含消息数据包负载,如下所示。 //stdout Packet { cmd: 'publish', retain: true, qos: 0, dup: false, length: 73, topic: 'test/connection', payload: &lt;Buffer 7b 22 31 22 3a 22 48 65 6c 6c 6f 20 77 6f 72 6c 64 22 2c 22 32 22 3a 22 57 65 6c 63 6f 6d 65 20 74 6f 20 74 68 65 20 74 65 73 74 20 63 6f 6e 6e 65 63 ... 6 more bytes&gt; } {"1":"Hello world","2":"Welcome to the test connection"}``` // [ { topic: 'test/connection', qos: 0 } ] granted 与其将主题名称作为常规的分隔字符串,我们还可以将主题存储为通配符,以便订户可以轻松订阅主题模式,而不是一次订阅一个主题。发布者和订阅者客户端需要提前了解主题模式的主题名称。 需要注意的是,订阅客户端需要提前了解他们将要接收的数据的结构,以便能够正确地处理数据。发布者以特定格式将消息发送到代理的特定主题,并接收该消息的预定订户需要知道数据的结构,以便能够在不破坏应用程序的情况下正确处理它。 订户客户端的完整代码如下所示。 // subscriber.js const mqtt = require('mqtt') const client = mqtt.connect("mqtt://test.mosquitto.org") const topicName = 'test/connection' // connect to same client and subscribe to same topic name client.on('connect', () =&gt; { // can also accept objects in the form {'topic': qos} client.subscribe(topicName, (err, granted) =&gt; { if(err) { console.log(err, 'err'); } console.log(granted, 'granted') }) }) // on receive message event, log the message to the console client.on('message', (topic, message, packet) =&gt; { console.log(packet, packet.payload.toString()); if(topic === topicName) { console.log(JSON.parse(message)); } }) client.on("packetsend", (packet) =&gt; { console.log(packet, 'packet2'); }) MQTT的其他功能 以下是MQTT的一些特点。 保留的消息 保留的消息是一个设置为true的MQTT消息,其保留标志/选项设置为true。默认情况下,当代理/服务器接收到没有订户的主题的消息时,消息会被丢弃。但是,MQTT有一种通过设置标志来保留这些消息的机制,该标志告诉发布者保留消息。请注意,代理每个主题只存储一个保留的消息。 广泛的身份验证和数据安全支持 MQTT支持各种身份验证方法和数据安全机制,包括TLS和OAuth,通常在MQTT代理上配置。因此, 这意味着实施这些服务器的客户端需要遵守所定义的机制。 默认情况下,MQTT支持重新连接机制,可以在网络连接质量低的区域建立持久连接。这对于存储消息非常重要,但与传统队列系统不同,代理不仅仅存储消息。MQTT通过确保客户端会话持久存在并且QoS级别大于0来存储消息。 服务质量(QoS) 为了处理发布/订阅系统中的典型挑战,MQTT实现了三个服务质量(QoS)级别。这三个级别包括0、1和2,它们确定消息达到预期接收方(客户端或代理)的保证类型。 为支持可靠的消息传递,该协议支持三种不同类型的服务质量消息: 0 – 至多一次 1 – 至少一次 2 – 正好一次 为存储消息,客户端必须订阅QoS大于0的主题。 数据不可知 MQTT是数据不可知的,客户端的用例确定了数据的结构方式。因此,可以发送任何类型的消息,包括图像、编码文本、加密数据等。 注意:默认的未加密MQTT端口是1883。还支持加密的TCP/IP端口8883,用于使用SSL的MQTT。 结论 MQTT提供了适用于网络带宽有限的领域的双向发布/订阅消息模型。服务独立于我们的主要应用程序,因为它们是解耦的,可以单独扩展代理或服务器。 --- ### 40. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 SMQTT 是一款高性能、开源的 MQTT 服务器,旨在提供支持单机、容器化和集群部署的 MQTT 服务,具备低延迟和高吞吐量,支持数百万 TCP 连接。本文将向您介绍 SMQTT 的主要功能、优势以及适用场景。 WIKI: https://wiki.smqtt.cc/ gitee: https://gitee.com/quickmsg 为什么选择 MQTT? MQTT 是一种轻量级的消息传递协议,采用发布/订阅模型,非常适用于物联网消息传递,如传感器、手机、嵌入式设备等。其低开销和高效性使其成为 IoT 设备之间进行可靠消息传递的理想选择。 优势 SMQTT 具有以下显著优势: 标准 MQTT 协议支持: SMQTT 实现了 MQTT 协议的标准版本,包括 3.1 和 3.1.1,确保了与各种 MQTT 客户端的兼容性。 高并发支持: SMQTT 可应对高并发场景,而且支持集群化部署,使其适用于大规模部署。 高性能和高吞吐量: SMQTT 是基于 Reactor-Netty(Spring WebFlux 的底层依赖)开发的,底层采用 Reactor3 反应堆模型,具备卓越的性能和高吞吐量。此外,它还利用 Netty 提供原生性能优势。 功能 SMQTT 具备多种功能,包括但不限于: 标准协议功能: 支持 MQTT 协议的标准功能,包括发布/订阅、QoS 等。 数据持久化: SMQTT 支持将消息数据持久化存储,以确保数据安全和可靠性。您可以选择默认内存存储或持久化存储到 Redis 或数据库。 规则引擎: 支持规则引擎,可以用于消息处理和转发。 集群化功能: SMQTT 提供集群支持,使用 Gossip 协议实现集群通信,确保高可用性。 管理监控页面: 提供管理后台,用于管理和监控 MQTT 服务器,同时支持 Grafana 监控集成,以实现性能监控。 ACL 权限管理: 支持对设备和资源的访问授权,确保数据安全性。 认证模块: 提供多种认证方式,包括 HTTP、匿名、固定密码和 SQL 认证。 拦截器: 支持自定义消息拦截器,用于处理消息。 容器化支持: 支持容器化部署,方便集成到现有容器化环境中。 总结 SMQTT 的启动和管理非常简单,支持 Spring Boot Starter,可以轻松地将其集成到 Spring Boot 项目中。此外,您可以访问管理后台以监控和管理 MQTT 服务器。 如果您正在寻找一款高性能、开源的 MQTT 服务器,SMQTT 可能是您的理想选择。它支持各种协议、高并发场景和集群化部署,具备优秀的性能和可扩展性,适用于各种 IoT 和通信需求。 启动方式 main方式启动 <!--smqtt依赖 --> <dependency> <groupId>io.github.quickmsg</groupId> <artifactId>smqtt-core</artifactId> <version>${Latest version}</version> </dependency> <!--集群依赖 --> <dependency> <artifactId>smqtt-registry-scube</artifactId> <groupId>io.github.quickmsg</groupId> <version>${Latest version}</version> </dependency> <!--管理ui依赖 --> <dependency> <artifactId>smqtt-ui</artifactId> <groupId>io.github.quickmsg</groupId> <version>${Latest version}</version> </dependency> 阻塞式启动服务: Bootstrap.builder() .rootLevel(Level.INFO) .websocketConfig( BootstrapConfig.WebsocketConfig .builder() .enable(false) .path("/mqtt") .port(8888) .build() ) .tcpConfig( BootstrapConfig .TcpConfig .builder() .port(1883) .ssl(SslContext.builder().enable(false).build()) .build()) .httpConfig( BootstrapConfig .HttpConfig .builder() .enable(false) .accessLog(true) .admin(BootstrapConfig.HttpAdmin.builder().enable(true).username("smqtt").password("smqtt").build()) .build()) .clusterConfig( BootstrapConfig. ClusterConfig .builder() .enable(false) .namespace("smqtt") .node("node-1") .port(7773) .url("127.0.0.1:7771,127.0.0.1:7772"). build()) .build() .startAwait(); 非阻塞式启动服务: Bootstrap bootstrap = Bootstrap.builder() .rootLevel(Level.INFO) .websocketConfig( BootstrapConfig.WebsocketConfig .builder() .enable(false) .path("/mqtt") .port(8888) .build() ) .tcpConfig( BootstrapConfig .TcpConfig .builder() .port(1883) .ssl(SslContext.builder().enable(false).build()) .build()) .httpConfig( BootstrapConfig .HttpConfig .builder() .enable(false) .accessLog(true) .admin(BootstrapConfig.HttpAdmin.builder().enable(true).username("smqtt").password("smqtt").build()) .build()) .clusterConfig( BootstrapConfig. ClusterConfig .builder() .enable(false) .namespace("smqtt") .node("node-1") .port(7773) .url("127.0.0.1:7771,127.0.0.1:7772"). build()) .build() .start().block(); jar方式 1.下载源码 mvn compile package -Dmaven.test.skip=true -P jar,web 在smqtt-bootstrap/target目录下生成jar 2.准备配置文件 config.yaml config.yaml java -jar smqtt-bootstrap-1.0.1-SNAPSHOT.jar <config.yaml路径> docker 方式 拉取镜像 # 拉取docker镜像地址 docker pull 1ssqq1lxr/smqtt:latest 启动镜像默认配置 # 启动服务 docker run -it -p 1883:1883 1ssqq1lxr/smqtt 启动镜像使用自定义配置(同上准备配置文件config.yaml) # 启动服务 docker run -it -v <配置文件路径目录>:/conf -p 1883:1883 -p 1999:1999 1ssqq1lxr/smqtt springboot方式 引入依赖 <dependency> <groupId>io.github.quickmsg</groupId> <artifactId>smqtt-spring-boot-starter</artifactId> <version>${Latest version >= 1.0.8}</version> </dependency> 启动类Application上添加注解 @EnableMqttServer 配置application.yml文件properties也支持,但是需要自己转换,没有提供demo文件config.yaml 启动springboot服务服务即可 如果引入的是spring-boot-starter-parent的管理包,如果启动报错,则需要添加以下依赖 <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.4.9</version> </dependency> <dependency> <groupId>io.projectreactor.netty</groupId> <artifactId>reactor-netty</artifactId> <version>1.0.10</version> </dependency> --- ### 41. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Mica-MQTT 是一款强大的 MQTT(Message Queuing Telemetry Transport)物联网组件,旨在提供出色的性能和灵活性。它适用于各种使用场景,包括物联网、消息通信、即时通讯(IM)和消息推送。本文将向您介绍 Mica-MQTT 的主要功能、优势以及使用场景。 使用场景 Mica-MQTT 可以用于多种用途,包括但不限于: 物联网(云端 MQTT Broker): 用于支持大规模物联网设备的通信和数据传输。 物联网(边缘端消息通信): 适用于连接边缘设备的消息传递,支持低延迟通信。 群组类 IM: 用于构建即时通讯应用,支持群组聊天和私聊。 消息推送: 用于实现消息推送服务,将消息快速可靠地传递给接收者。 简单易用的 MQTT 客户端: Mica-MQTT 提供了 MQTT 客户端,使开发者可以轻松与 MQTT 代理进行通信。 优势 Mica-MQTT 具有以下显著优势: 灵活而强大: Mica-MQTT 提供了丰富的功能集,同时保持了灵活性,可以根据需要进行二次开发或扩展。 支持 MQTT 协议: 支持 MQTT v3.1、v3.1.1 以及 v5.0 协议,满足不同 MQTT 版本的需求。 WebSocket 支持: 支持 MQTT 子协议的 WebSocket 连接,允许浏览器和其他应用使用 MQTT 协议进行通信。 HTTP REST API: 提供 HTTP REST API,使您可以使用 HTTP 请求进行通信。具体的 API 文档详见官方文档。 集群支持: Mica-MQTT 支持 MQTT 客户端和服务器的共享订阅,采用高效的 topic 树存储方式,能够处理百万级别的 topic,保持高性能。 遗嘱消息和保留消息: 支持 MQTT 遗嘱消息和保留消息,确保消息的可靠性和持久性。 Spring Boot 集成: 提供 Spring Boot 项目的快速接入,使集成更加简单。 监控支持: 支持与 Prometheus 和 Grafana 集成,实现监控和性能优化。 GraalVM 支持: 您可以使用 GraalVM 将 Mica-MQTT 编译成本机可执行程序,以获得更好的性能。 默认端口 Mica-MQTT 使用以下默认端口: 1883 端口:用于 MQTT TCP 通信。 8083 端口:用于 HTTP、WebSocket 以及 MQTT 子协议通信。 您可以在 演示地址 上查看 Mica-MQTT 的演示,使用账号 mica 和密码 mica 登录以了解更多。 总结 Mica-MQTT 是一款功能丰富、性能出色的 MQTT 物联网组件,适用于各种 IoT 和通信需求。如果您正在寻找可靠的 MQTT 解决方案,Mica-MQTT 可能是您的理想之选。 Spring boot 项目 客户端: 一、添加依赖 <dependency> <groupId>net.dreamlu</groupId> <artifactId>mica-mqtt-client-spring-boot-starter</artifactId> <version>${最新版本}</version> </dependency> 二、mqtt 客户端 2.1 配置项示例 mqtt: client: enabled: true # 是否开启客户端,默认:true ip: 127.0.0.1 # 连接的服务端 ip ,默认:127.0.0.1 port: 1883 # 端口:默认:1883 name: Mica-Mqtt-Client # 名称,默认:Mica-Mqtt-Client clientId: 000001 # 客户端Id(非常重要,一般为设备 sn,不可重复) user-name: mica # 认证的用户名 password: 123456 # 认证的密码 timeout: 5 # 超时时间,单位:秒,默认:5秒 reconnect: true # 是否重连,默认:true re-interval: 5000 # 重连时间,默认 5000 毫秒 version: mqtt_3_1_1 # mqtt 协议版本,可选 MQTT_3_1、mqtt_3_1_1、mqtt_5,默认:mqtt_3_1_1 read-buffer-size: 8KB # 接收数据的 buffer size,默认:8k max-bytes-in-message: 10MB # 消息解析最大 bytes 长度,默认:10M buffer-allocator: heap # 堆内存和堆外内存,默认:堆内存 keep-alive-secs: 60 # keep-alive 时间,单位:秒 clean-session: true # mqtt clean session,默认:true ssl: enabled: false # 是否开启 ssl 认证,2.1.0 开始支持双向认证 keystore-path: # 可选参数:ssl 双向认证 keystore 目录,支持 classpath:/ 路径。 keystore-pass: # 可选参数:ssl 双向认证 keystore 密码 truststore-path: # 可选参数:ssl 双向认证 truststore 目录,支持 classpath:/ 路径。 truststore-pass: # 可选参数:ssl 双向认证 truststore 密码 注意:ssl 存在三种情况 服务端开启ssl客户端ClientAuth 为 NONE(不需要客户端验证)仅仅需要开启 ssl 即可不用配置证书ClientAuth 为 OPTIONAL(与客户端协商)需开启 ssl 并且配置 truststore 证书ClientAuth 为 REQUIRE (必须的客户端验证)需开启 ssl 并且配置 truststore、 keystore证书 2.2 可实现接口(注册成 Spring Bean 即可) 接口是否必须说明IMqttClientConnectListener否客户端连接成功监听 2.3 客户端上下线监听 使用 Spring event 解耦客户端上下线监听,注意: 1.3.4 开始支持。会跟自定义的 IMqttClientConnectListener 实现冲突,取一即可。 /** * 示例:客户端连接状态监听 * * @author L.cm */ @Service public class MqttClientConnectListener { private static final Logger logger = LoggerFactory.getLogger(MqttClientConnectListener.class); @Autowired private MqttClientCreator mqttClientCreator; @EventListener public void onConnected(MqttConnectedEvent event) { logger.info("MqttConnectedEvent:{}", event); } @EventListener public void onDisconnect(MqttDisconnectEvent event) { // 离线时更新重连时的密码,适用于类似阿里云 mqtt clientId 连接带时间戳的方式 logger.info("MqttDisconnectEvent:{}", event); // 在断线时更新 clientId、username、password mqttClientCreator.clientId("newClient" + System.currentTimeMillis()) .username("newUserName") .password("newPassword"); } } 2.4 自定义 java 配置(可选) @Configuration(proxyBeanMethods = false) public class MqttClientCustomizerConfiguration { @Bean public MqttClientCustomizer mqttClientCustomizer() { return new MqttClientCustomizer() { @Override public void customize(MqttClientCreator creator) { // 此处可自定义配置 creator,会覆盖 yml 中的配置 System.out.println("----------------MqttServerCustomizer-----------------"); } }; } } 2.5 订阅示例 @Service public class MqttClientSubscribeListener { private static final Logger logger = LoggerFactory.getLogger(MqttClientSubscribeListener.class); @MqttClientSubscribe("/test/#") public void subQos0(String topic, byte[] payload) { logger.info("topic:{} payload:{}", topic, new String(payload, StandardCharsets.UTF_8)); } @MqttClientSubscribe(value = "/qos1/#", qos = MqttQoS.AT_LEAST_ONCE) public void subQos1(String topic, byte[] payload) { logger.info("topic:{} payload:{}", topic, new String(payload, StandardCharsets.UTF_8)); } @MqttClientSubscribe("/sys/${productKey}/${deviceName}/thing/sub/register") public void thingSubRegister(String topic, byte[] payload) { // 1.3.8 开始支持,@MqttClientSubscribe 注解支持 ${} 变量替换,会默认替换成 + // 注意:mica-mqtt 会先从 Spring boot 配置中替换参数 ${},如果存在配置会优先被替换。 logger.info("topic:{} payload:{}", topic, new String(payload, StandardCharsets.UTF_8)); } } 2.6 共享订阅 topic 说明 mica-mqtt 支持两种共享订阅方式: 共享订阅:订阅前缀 $queue/,多个客户端订阅了 $queue/topic,发布者发布到 topic,则只有一个客户端会接收到消息。 分组订阅:订阅前缀 $share/<group>/,组客户端订阅了 $share/group1/topic、$share/group2/topic..,发布者发布到 topic,则消息会发布到每个 group 中,但是每个 group 中只有一个客户端会接收到消息。 注意: 如果发布的 topic 以 / 开头,例如:/topic/test,需要订阅 $share/group1//topic/test,另外 mica-mqtt 默认随机消息路由,共享订阅的多个客户端会随机收到消息。 2.7 MqttClientTemplate 使用示例 import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; /** * @author wsq */ @Service public class MainService { private static final Logger logger = LoggerFactory.getLogger(MainService.class); @Autowired private MqttClientTemplate client; public boolean publish() { client.publish("/test/client", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); return true; } public boolean sub() { client.subQos0("/test/#", (context, topic, message, payload) -> { logger.info(topic + '\t' + new String(payload, StandardCharsets.UTF_8)); }); return true; } } 服务端 一、添加依赖 <dependency> <groupId>net.dreamlu</groupId> <artifactId>mica-mqtt-server-spring-boot-starter</artifactId> <version>${最新版本}</version> </dependency> 二、mqtt 服务 2.1 配置项 mqtt: server: enabled: true # 是否开启服务端,默认:true # ip: 0.0.0.0 # 服务端 ip 默认为空,0.0.0.0,建议不要设置 port: 1883 # 端口,默认:1883 name: Mica-Mqtt-Server # 名称,默认:Mica-Mqtt-Server buffer-allocator: HEAP # 堆内存和堆外内存,默认:堆内存 heartbeat-timeout: 120000 # 心跳超时,单位毫秒,默认: 1000 * 120 read-buffer-size: 8KB # 接收数据的 buffer size,默认:8k max-bytes-in-message: 10MB # 消息解析最大 bytes 长度,默认:10M auth: enable: false # 是否开启 mqtt 认证 username: mica # mqtt 认证用户名 password: mica # mqtt 认证密码 debug: true # 如果开启 prometheus 指标收集建议关闭 stat-enable: true # 开启指标收集,debug 和 prometheus 开启时需要打开,默认开启,关闭节省内存 web-port: 8083 # http、websocket 端口,默认:8083 websocket-enable: true # 是否开启 websocket,默认: true http-enable: false # 是否开启 http api,默认: false http-basic-auth: enable: false # 是否开启 http basic auth,默认: false username: mica # http basic auth 用户名 password: mica # http basic auth 密码 ssl: # mqtt tcp ssl 认证 enabled: false # 是否开启 ssl 认证,2.1.0 开始支持双向认证 keystore-path: # 必须参数:ssl keystore 目录,支持 classpath:/ 路径。 keystore-pass: # 必选参数:ssl keystore 密码 truststore-path: # 可选参数:ssl 双向认证 truststore 目录,支持 classpath:/ 路径。 truststore-pass: # 可选参数:ssl 双向认证 truststore 密码 client-auth: none # 是否需要客户端认证(双向认证),默认:NONE(不需要) 注意:ssl 存在三种情况 服务端开启ssl客户端ClientAuth 为 NONE(不需要客户端验证)仅仅需要开启 ssl 即可不用配置证书ClientAuth 为 OPTIONAL(与客户端协商)需开启 ssl 并且配置 truststore 证书ClientAuth 为 REQUIRE (必须的客户端验证)需开启 ssl 并且配置 truststore、 keystore证书 2.2 可实现接口(注册成 Spring Bean 即可) 接口是否必须说明IMqttServerUniqueIdService否用于 clientId 不唯一时,自定义实现唯一标识,后续接口使用它替代 clientIdIMqttServerAuthHandler是用于服务端认证IMqttServerSubscribeValidator否(建议实现)1.1.3 新增,用于对客户端订阅校验IMqttServerPublishPermission否(建议实现)1.2.2 新增,用于对客户端发布权限校验IMqttMessageListener否(1.3.x为否)消息监听IMqttConnectStatusListener是连接状态监听IMqttSessionManager否session 管理IMqttSessionListener否session 监听IMqttMessageStore集群是,单机否遗嘱和保留消息存储AbstractMqttMessageDispatcher集群是,单机否消息转发,(遗嘱、保留消息转发)IpStatListener否t-io ip 状态监听IMqttMessageInterceptor否消息拦截器,1.3.9 新增 2.3 IMqttMessageListener (用于监听客户端上传的消息) 使用示例 @Service public class MqttServerMessageListener implements IMqttMessageListener { private static final Logger logger = LoggerFactory.getLogger(MqttServerMessageListener.class); @Override public void onMessage(ChannelContext context, String clientId, Message message) { logger.info("clientId:{} message:{} payload:{}", clientId, message, new String(message.getPayload(), StandardCharsets.UTF_8)); } } 2.4 自定义配置(可选) @Configuration(proxyBeanMethods = false) public class MqttServerCustomizerConfiguration { @Bean public MqttServerCustomizer mqttServerCustomizer() { return new MqttServerCustomizer() { @Override public void customize(MqttServerCreator creator) { // 此处可自定义配置 creator,会覆盖 yml 中的配置 System.out.println("----------------MqttServerCustomizer-----------------"); } }; } } 2.5 MqttServerTemplate 使用示例 import net.dreamlu.iot.mqtt.spring.server.MqttServerTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.ByteBuffer; /** * @author wsq */ @Service public class ServerService { @Autowired private MqttServerTemplate server; public boolean publish(String body) { server.publishAll("/test/123", body.getBytes(StandardCharsets.UTF_8)); return true; } } 2.6 客户端上下线监听 使用 Spring event 解耦客户端上下线监听,注意: 1.3.4 开始支持。会跟自定义的 IMqttConnectStatusListener 实现冲突,取一即可。 @Service public class MqttConnectStatusListener { private static final Logger logger = LoggerFactory.getLogger(MqttConnectStatusListener.class); @EventListener public void online(MqttClientOnlineEvent event) { logger.info("MqttClientOnlineEvent:{}", event); } @EventListener public void offline(MqttClientOfflineEvent event) { logger.info("MqttClientOfflineEvent:{}", event); } } 2.7 基于 mq 消息广播集群处理 详见: mica-mqtt-broker 2.8 Prometheus + Grafana 监控对接 <!-- 开启 prometheus 指标收集 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> 支持得指标说明mqtt_connections_accepted共接受过连接数mqtt_connections_closed关闭过的连接数mqtt_connections_size当前连接数mqtt_messages_handled_packets已处理消息数mqtt_messages_handled_bytes已处理消息字节数mqtt_messages_received_packets已接收消息数mqtt_messages_received_bytes已处理消息字节数mqtt_messages_send_packets已发送消息数mqtt_messages_send_bytes已发送消息字节数 非 Spring boot 项目 客户端 topic 通配符含义 /:用来表示层次,比如 a/b,a/b/c。 #:表示匹配 >=0 个层次,比如 a/# 就匹配 a/,a/b,a/b/c。单独的一个 # 表示匹配所有。不允许 a# 和 a/#/c。 +:表示匹配一个层次,例如 a/+ 匹配 a/b,a/c,不匹配 a/b/c。单独的一个 + 是允许的,a+ 不允许,也可以和多层通配符一起使用,+/tennis/# 、sport/+/player1 都有有效的。 使用说明 MQTT 遗嘱消息场景 当客户端断开连接时,发送给相关的订阅者的遗嘱消息。在设备 A 进行连接时候,遗嘱消息设定为 offline,手机App B 订阅这个遗嘱主题。 当 A 异常断开时,手机App B 会收到这个 offline 的遗嘱消息,从而知道设备 A 离线了。 MQTT 保留消息场景 例如,某设备定期发布自身 GPS 坐标,但对于订阅者而言,从它发起订阅到第一次收到数据可能需要几秒钟,也可能需要十几分钟甚至更多,这样并不友好。因此 MQTT 引入了保留消息。 而每当有订阅者建立订阅时,服务端就会查找是否存在匹配该订阅的保留消息,如果保留消息存在,就会立即转发给订阅者。 借助保留消息,新的订阅者能够立即获取最近的状态。 共享订阅 mica-mqtt 支持两种共享订阅方式: 共享订阅:订阅前缀 $queue/,多个客户端订阅了 $queue/topic,发布者发布到 topic,则只有一个客户端会接收到消息。 分组订阅:订阅前缀 $share/<group>/,组客户端订阅了 $share/group1/topic、$share/group2/topic..,发布者发布到 topic,则消息会发布到每个 group 中,但是每个 group 中只有一个客户端会接收到消息。 注意: 如果发布的 topic 以 / 开头,例如:/topic/test,需要订阅 $share/group1//topic/test,另外 mica-mqtt 默认随机消息路由,共享订阅的多个客户端会随机收到消息。 客户端使用 // 初始化 mqtt 客户端 MqttClient client = MqttClient.create() .ip("127.0.0.1") // mqtt 服务端 ip 地址 .port(1883) // 默认:1883 .username("admin") // 账号 .password("123456") // 密码 .version(MqttVersion.MQTT_5) // 默认:3_1_1 .clientId("xxxxxx") // 非常重要务必手动设置,一般设备 sn 号,默认:MICA-MQTT- 前缀和 36进制的纳秒数 .bufferAllocator(ByteBufferAllocator.DIRECT) // 堆内存和堆外内存,默认:堆内存 .readBufferSize(512) // 消息一起解析的长度,默认:为 8092 (mqtt 消息最大长度) .maxBytesInMessage(1024 * 10) // 最大包体长度,如果包体过大需要设置此参数,默认为: 10M (10*1024*1024) .keepAliveSecs(120) // 默认:60s .timeout(10) // 超时时间,t-io 配置,可为 null,为 null 时,t-io 默认为 5 .reconnect(true) // 是否重连,默认:true .reInterval(5000) // 重连重试时间,reconnect 为 true 时有效,t-io 默认为:5000 .willMessage(builder -> { builder.topic("/test/offline").messageText("down"); // 遗嘱消息 }) .connectListener(new IMqttClientConnectListener() { @Override public void onConnected(ChannelContext context, boolean isReconnect) { logger.info("链接服务器成功..."); } @Override public void onDisconnect(ChannelContext channelContext, Throwable throwable, String remark, boolean isRemove) { logger.info("与链接服务器断开连接..."); } }) .properties() // mqtt5 properties .connectSync(); // 同步连接,也可以使用 connect(),可以避免 broker 没启动照成启动卡住。 // 消息订阅,同类方法 subxxx client.subQos0("/test/#", (context, topic, message, payload) -> { logger.info(topic + '\t' + new String(payload, StandardCharsets.UTF_8)); }); // 取消订阅 client.unSubscribe("/test/#"); // 发送消息 client.publish("/test/client", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 断开连接 client.disconnect(); // 重连 client.reconnect(); // 停止 client.stop(); 服务端 // 注意:为了能接受更多链接(降低内存),请添加 jvm 参数 -Xss129k MqttServer mqttServer = MqttServer.create() // 服务端 ip 默认为空,0.0.0.0,建议不要设置 .ip("0.0.0.0") // 默认:1883 .port(1883) // 默认为: 8092(mqtt 默认最大消息大小),为了降低内存可以减小小此参数,如果消息过大 t-io 会尝试解析多次(建议根据实际业务情况而定) .readBufferSize(512) // 最大包体长度,如果包体过大需要设置此参数,默认为: 8092 .maxBytesInMessage(1024 * 100) // 自定义认证 .authHandler((clientId, userName, password) -> true) // 消息监听 .messageListener((context, clientId, message) -> { logger.info("clientId:{} message:{} payload:{}", clientId, message, new String(message.getPayload(), StandardCharsets.UTF_8)); }) // 堆内存和堆外内存选择,默认:堆内存 .bufferAllocator(ByteBufferAllocator.HEAP) // 心跳超时时间,默认:120s .heartbeatTimeout(120_1000L) // ssl 配置 .useSsl("", "", "") // 自定义客户端上下线监听 .connectStatusListener(new IMqttConnectStatusListener() { @Override public void online(String clientId) { } @Override public void offline(String clientId) { } }) // 自定义消息转发,可用 mq 广播实现集群化处理 .messageDispatcher(new IMqttMessageDispatcher() { @Override public void config(MqttServer mqttServer) { } @Override public boolean send(Message message) { return false; } @Override public boolean send(String clientId, Message message) { return false; } }) .debug() // 开启 debug 信息日志 .start(); // 发送给某个客户端 mqttServer.publish("clientId","/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 发送给所有在线监听这个 topic 的客户端 mqttServer.publishAll("/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 停止服务 mqttServer.stop(); --- ### 42. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,广泛应用于物联网和实时通信领域。asyncio-mqtt是一个为Python开发者设计的基于异步IO的MQTT客户端库,通过利用Python的asyncio库提供高效、可靠的异步MQTT通信。 2. 安装 要安装asyncio-mqtt库,可以使用以下命令: pip install asyncio-mqtt 3. 使用方法 使用asyncio-mqtt库可以轻松地实现异步MQTT通信。 3.1 连接到MQTT代理 首先,需要创建一个MQTT客户端并连接到MQTT代理服务器: import asyncio_mqtt as mqtt async def connect_mqtt(): client = mqtt.Client() await client.connect('mqtt.example.com') return client client = asyncio.run(connect_mqtt()) 在上述示例中,'mqtt.example.com' 是MQTT代理服务器的地址。 3.2 发布消息 要发布消息到MQTT代理服务器,可以使用publish方法: await client.publish('topic', 'message') 在上述示例中,'topic' 是要发布到的主题,'message' 是要发送的消息。 3.3 订阅消息 要订阅MQTT代理服务器的消息,可以使用subscribe方法: async def on_message(topic, message): print(f'Received message in topic "{topic}": {message}') await client.subscribe('topic', on_message) 在上述示例中,'topic' 是要订阅的主题,'on_message' 是在接收到消息时调用的回调函数。 3.4 断开连接 当不再需要与MQTT代理服务器通信时,可以断开连接: await client.disconnect() 4. 优点 使用asyncio-mqtt库具有以下优点: 异步IO支持:asyncio-mqtt利用Python的asyncio库实现了异步IO,提高了MQTT通信的效率和可靠性。 易于使用:asyncio-mqtt提供了简洁的API接口,使得MQTT通信容易上手并可以轻松集成到现有项目中。 5. 应用场景 asyncio-mqtt适用于各种需要异步MQTT通信的场景,特别在以下情况下它尤为有用: 物联网应用:asyncio-mqtt能够轻松与物联网设备进行异步通信,实现实时数据传输和控制。 实时监控系统:使用asyncio-mqtt,您可以建立快速响应的实时监控系统,监控设备状态并接收实时数据。 消息订阅与发布:通过asyncio-mqtt,可以轻松实现消息订阅和发布机制,支持实时信息推送和订阅者的消息更新。 综上所述,asyncio-mqtt是一个高效、易于使用的异步MQTT客户端库。它基于Python的asyncio库,提供异步MQTT通信功能,使得在物联网和实时通信领域更加便捷。通过asyncio-mqtt,您可以轻松构建异步MQTT应用,满足各种实时通信需求。 --- ### 43. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在物联网的飞速发展下,数据交互和传输安全性的需求空前高涨。MQTT 作为一个轻量级的消息传输协议,已成为业界的首选。而在众多的 MQTT 实现中,smart-mqtt 突显出其卓越的技术实力和创新能力,逐渐成为了 MQTT 新时代的领跑者。 项目仓库 Gitee(主仓库):https://gitee.com/smartboot/smart-mqtt(opens new window) Github(镜像同步):https://github.com/smartboot/smart-mqtt(opens new window) 开发环境:Java 8 1. smart-mqtt 的飞跃之路 从 2022 年的初版 v0.1 到 2023 年的 v0.28,smart-mqtt 经历了众多的升级和迭代。在这之中,它不仅展现出了技术的深度和广度,而且反映出其对市场需求的敏感度和响应速度。 2. 特色亮点 a. 技术迭代和完善 smart-mqtt 在每一次版本更新中,都不断修复已知问题并优化功能。例如,在 v0.28 中,它修复了 retain 消息实现不符合规范的问题,并进行了许多底层接口的调整与优化。 b. 企业版的强劲扩展 smart-mqtt 的企业版在功能上远超其社区版,它提供了更多的专业功能如指标实时统计、客户端连接管理、Topic 管理、账户管理等,满足大企业的商业需求。 c. 性能的极致优化 smart-mqtt 致力于为用户提供最佳的性能体验。如在 v0.26 版本中,通过采纳时间轮定时器替换 JDK 默认定时器,大大提高了计时效率。同时在多个版本中,smart-mqtt 也对其内存管理、消息编解码、消息推送模型等关键流程进行了精细的优化。 d. 开放与创新 smart-mqtt 并不满足于现有的功能和表现,它始终保持开放的心态。在 v0.17 版本中,通过引入 smart-socket 的插件化机制,提供了消息超时重发的功能,表明了其对技术的前瞻性和创新意识。 3. 插件开发 smart-mqtt 非常重视与社区的交流和合作。在多个版本更新中,都可以看到来自社区反馈的 bug 修复和功能建议。这也使得 smart-mqtt 更加完善,更具适应性。 smart-mqtt 是一款非常开放的产品,在满足基本 MQTT 服务的同时,还能基于其插件化的能力衍生出多样化的功能,例如:服务指标统计、集群服务、数据路由等。 smart-mqtt 企业版的几乎每项特性都是一个插件,并且插件与插件之间各自独立自治。 在事件总线章节中为了大家展示了相对细致的 samrt-mqtt 内部架构。 但如果从插件视角重新审视 smart-mqtt,则会是另外一番景象(见下图)。  通过订阅事件总线上不同类型的事件,并配套不同的实现策略,可以实现很多实用的功能。当然,你也可以完全脱离事件总线做一些有意思的插件,譬如:插件的热插拔、Broker服务动态启停等。 4. 未来展望 随着物联网技术的持续发展,smart-mqtt 在技术深度和广度上仍有巨大的挖掘空间。而从其迄今为止的表现来看,smart-mqtt 无疑有能力和信心继续引领 MQTT 技术的前沿发展。 结论 smart-mqtt 不仅仅是一个 MQTT Broker,它是 IoT 领域的一个杰出代表,是技术与创新的完美结合。对于任何希望在 IoT 领域取得突破的企业和开发者,smart-mqtt 都是一个不可忽视的伙伴。 扩展阅读: 发版记录 #smart-mqtt broker v0.28发布(2023-09-17)(opens new window) bugfix:修复retain消息实现不符合规范的问题。(感谢 springrain-zorm 反馈) 调整消息总线接口入参设计。 删除 broker 模块中的 EventObject。 服务配置项 name 调整为 nodeId。 移除 BrokerContext#getRuntime 接口。 调整控制台 Banner 输出时机。 #smart-mqtt broker v0.27发布(2023-09-03)(opens new window) 【社区版】 新增事件类型:UNSUBSCRIBE_TOPIC,当 topic 订阅关系解除时触发。 移除 BrokerContext#getSessions 接口。 提升 MqttClient 的重连功能稳定性。 【企业版】 基于事件总线提供更高效、更精准的指标实时统计。 更加丰富的指标统计时间粒度。 新增客户端连接管理页面。 新增 Topic 管理页面。 新增账户管理功能 新增 Broker 集群管理功能 #smart-mqtt broker v0.26发布(2023-08-13)(opens new window) 移除 commons-collections4 依赖,减少发行包大小。 新增 BROKER_CONFIGURE_LOADED 事件类型,当配置文件完成加载后触发。 新增系统环境变量:BROKER_LOWMEMORY、BROKER_MAXINFLIGHT,用于设置 Broker 启动参数。 支持启用低内存模式,提升百万连接场景下的资源使用率。 noConnectIdleTimeout 默认值调整至15秒 MqttClient 采用事件模型处理 Connect ACK消息。 提升MqttClient重连功能稳定性。 采用时间轮定时器替换JDK默认定时器。 #smart-mqtt broker v0.25发布(2023-07-29)(opens new window) 【社区版】 smart-socket升级值1.5.32。 设置 slf4j-simple 的 maven scope 为 runtime。 更新 readme.md。 重构消息总线,提升可扩展性。 新增事件类型:OPEN_API_STARTED。 移除开源版中的 openapi 定义。 MqttSession 新增 getMqttContext 接口。 清理 smart-mqtt.yaml 配置文件,移除无用项。 【企业版】 新增两款数据桥接插件:redis-bridge、kafak-bridge 添加后台登录账户认证。 提升 mqtt-over-websocket 的稳定性。 #smart-mqtt broker v0.24发布(2023-07-08)(opens new window) 【开源版】 升级smart-socket至1.5.31 升级smart-http至1.2.6 增加broker启动时关于技术支持联系方式的露出。 移除开源版中的前端资源,迁移至企业版。 【企业版】 增加按省份维度的访问量排名统计。 提供更加高效,且自适应采样粒度的指标统计功能。 企业版的主数据库调整为mysql,依旧保留h2的开箱即用特性。 屏蔽服务启动时的DDL语句打印。 优化数据库索引,提供更高效的检索体验。 丰富集群间的关键信息互通。 修复非周期性指标在入库时被重置的bug。 #smart-mqtt broker v0.23发布(2023-06-24)(opens new window) smart-http升级至1.2.5 layui-vue 升级至2.3.1 企业版页面新增地图监控大屏。 #smart-mqtt broker v0.22发布(2023-06-17)(opens new window) 【社区版】 禁止客户端匹配 ”$“ 开头的主题名。 BrokerContext新增bundle、getBundle用于绑定自定义资源。 Broker服务的线程池、内存池支持资源复用。 优化Broker端的消息推送模型。 提升MqttClient通信服务稳定性。 smart-http升级至1.2.4 【企业版】 移除redis-bridge-plugin模块,将于开源之夏活动中由社区同学贡献开源版。 移除mqtt-bridge-plugin模块。 优化指标统计 #smart-mqtt broker v0.21发布(2023-06-03)(opens new window) 【社区版】 smart-socket 升级至1.5.29。 fastjson2 升级至 2.0.21.graal。 迁移指标采集功能至企业版。 优化SubAck的响应效率。 Broker支持注册 smart-socket 插件。 新增事件类型:NOTIFY_TOPIC_PUSH,用于触发指定topic的消息推送。 优化MQTT的连接会话管理。 重构topic的订阅匹配模型。 重构消息推送模型。 重构飞行窗口。 提升MqttClient服务稳定性。 补充单元测试用例。 【企业版】 采用异步方式持久化统计指标,降低对通信性能造成的影响。 统计指标适配 Prometheus。 #smart-mqtt broker v0.20发布(2023-05-20)(opens new window) 【社区版】 smart-socket 升级至1.5.27。 snakeyaml 升级至2.0。 修复了消息编解码过程中的bug,提高消息传输的可靠性。 优化了消息解码异常触发的状态机,降低误判概率。 加强了消息编解码字节边界的检验,避免数据解析错误。 改进了内存管理策略,减少通信过程中的内存消耗。 修复了MQTT 5.0协议实现中的遗嘱消息和QoS2通信编解码问题。 对遗嘱消息模型字段进行了优化,提高代码可读性。 引入社区同学贡献的redis桥接模块,提供更多扩展选项。 为MQTT Client提供更高效的pulbish能力,提升性能表现。 【企业版】 补充表结构索引,解决慢sql问题。 新增账户管理接口 Broker启动时重置旧连接状态。 #smart-mqtt broker v0.19发布(2023-04-22)(opens new window) 实现消息重发规范 #smart-mqtt broker v0.18发布(2023-04-16)(opens new window) 社区版中移除连接认证功能,后续将在企业版中重新提供一套相对成熟的方案。 清理无用配置项。 优化消息Push逻辑。 重构 BrokerTopic 模型结构。 社区版源码中补充关于商业授权的License注释。 【企业版】优化Broker管理系统UI。 【企业版】节点管理中补充 Broker 端口号的信息记录。 【企业版】补充表索引,解决慢SQL问题。 【企业版】H2数据库启用mysql模式。 【企业版】关闭ChatGPT入口。(因为国内服务器已无法调用OpenAPI) #smart-mqtt broker v0.17发布(2023-03-19)(opens new window) 通过引入smart-socket的插件化机制,以更低的性能损耗实现消息超时重发。 修复此前版本引入的topic取消订阅不生效的bug。 网络断开连接后即时中断消息推送,减少不必要的尝试。 MQTT Client 的topic订阅与取消订阅请求纳入飞行队列管理。 重构部分消息模型。 重构飞行队列,提供更加完善的Push能力。 更合理的日志输出。 #smart-mqtt broker v0.16发布(2023-03-19)(opens new window) 优化 docker-compose.yml 配置,提升压测体验。 简化客户端连接空闲超时处理逻辑,节省内存开销。 显式管理 openAPI 服务的线程资源。 提升IO的flush效率。 调整内存消息队列的消费模式:当订阅者消费过慢导致消息被发布者覆盖,将直接跳跃至最新一条。 简化消息的 Push 模型,并获得大幅的性能提升。 暂时移除消息重发策略,会在后续版本中重构。 缩小 MQTT Client 消息发送的锁粒度,提升通信效率。 重构飞行队列,在高并发场景下能显著节省内存开销。 其他关于内存和性能的细节优化。 #smart-mqtt broker v0.15发布(2023-03-04)(opens new window) 【社区版】 smart-socket 版本调整至:1.5.24。 smart-http 版本升级值:1.1.21。 完善 openAPI 定义,并提供部分接口实现。 完善 MQTT5 协议规范的实现。 Broker 支持节点命名,用于集群模式下区分节点的唯一性。 提供内存模式的指标统计功能。 调整消息推送服务与插件模块的初始化顺序。 MQTT Client 支持飞行窗口,提供更稳定可靠的通信服务。 消息序列化日志打印调整成 JSON 格式输出。 改进后台管理系统的交互体验。 【企业版】 新增 chatGPT 插件,实现与人工智能对话。 新增 Database 插件,用于持久化Broker运行时数据以供后台管理系统展示。(适配数据库:H2、MySQL) 实现现存所有的 openAPI 接口。 #smart-mqtt broker v0.14发布(2023-01-28)(opens new window) 新增事件类型:SUBSCRIBE_ACCEPT、UNSUBSCRIBE_ACCEPT、CONNACK 重新设计MQTT协议编解码接口,提升代码可读性、扩展性、可维护性。 新增broker后台管理系统。 完善MQTT5.0规范实现: smart-mqtt-client 模块适配 mqtt5.0 协议。 客户端使用receiveMaximum限制客户端愿意同时处理的QoS等级1和QoS等级2的发布消息最大数量。 如果服务端不愿意接受CONNECT但希望表明其MQTT服务端身份,可以发送包含原因码为0x84(不支持的协议版本)的CONNACK报文,然后必须关闭网络连接。 #smart-mqtt broker v0.13发布(2022-12-31)(opens new window) 社区版 适配 mqtt 5.0 规范协议。 更新的项目readme描述信息。 MqttClient 支持 maxPacketSize 配置,限制 MQTT 消息包容量上限。 增加事件类型:SUBSCRIBE_REFRESH_TOPIC,当客户端取消 topic 订阅时触发。 修复特定场景下消息订阅失效问题。 重新设计消息编解码器。使整体结构更清晰,更具扩展性。 smart-socket 升级至 1.6.1。 #smart-mqtt broker v0.12发布(2022-12-31)(opens new window) 社区版 优化客户端超时断连的提示信息。 重构Connect消息的处理逻辑。 实现连接认证失败的错误响应码。 topic订阅支持黑名单约束。 优化Broker线程数配置,要求至少2个线程。 整理provider包结构。 修复操作系统 hosts 配置异常可能引发的接口阻塞问题。 企业版 试用版License过期时间延续至2023年12月31日。 修复 License 过期时间格式化错误问题。 优化运行期间 License 过期后的提示文案。 #smart-mqtt broker v0.11发布(2022-12-22)(opens new window) 社区版 MQTT默认的最大报文字节数调整为 1MB。 调整Broker消息推送线程组名称。 优化消息推送模型,获得更强劲的通信性能。 调整MQTTClient线程组名称。 提升飞行窗口稳定性 #smart-mqtt broker v0.10发布(2022-12-16)(opens new window) 社区版 采用自研的压测工具 smart-mqtt-bench 替换 emqx-bench,以获得更好更强劲的压测体验。 fastjson 升级至 fastjson2:2.0.20.graal。 重构消息推送模型,通过优化设计获得更高的通信性能。 新增事件总线的事件类型:MESSAGE_BUS_CONSUMED MemoryMessageStoreQueue 仅存储类型为 MqttPublishMessage 的消息。 缓冲区配置参数由 readBufferSize 调整为 bufferSize,且 read/write 共享该参数。 新增 Broker 服务的 Topic 数量限制,且默认值为:1024。 MQTT Broker 支持的最大报文采用参数化配置:maxPacketSize。 maxKeepAliveTime 由 1分钟调整成10分钟。 移除 BrokerContext#batchPublish 接口。 移除 MonitorPlugin 插件。 多个 MQTTClient 支持共享内存池。 MQTT Client 缓冲区采用参数配置化。 支持临时扩容缓冲区容量,不超过 maxPacketSize 即可。 升级飞行窗口流控算法。 消息输出支持主动和被动两种模式。 企业版 调整授权提示信息。 改进打包工具。 适配最新版 smart-mqtt。 #smart-mqtt broker v0.9发布(2022-12-03)(opens new window) 社区版 读缓冲区大小调整为参数配置化。 CONNECT_TIMEOUT默认值调整为5秒 MQTT 消息输出功能调整为MqttWriter接口的具体实现类,以适应 mqtt-over-websocket 的场景。 修复unsubscribe一个未订阅的 topic 时引发的空指针问题。 配置文件调整为 yaml 格式。 插件服务支持优先级排序。 企业版 新增消息桥接插件,现已实现了 mqtt-bridge-mqtt。 新增 mqtt-over-websocket新特性。 #smart-mqtt broker v0.8发布(2022-11-12)(opens new window) 升级 smart-socket 至 1.5.23 smart-mqtt 相关组件提交至 Maven 中央仓库。【ISSUE:I5ZOQ4 (opens new window)】 重构消息总线 指标监控频率调整为1分钟。 客户端支持通配符订阅。【ISSUE:I5ZJLZ (opens new window)】 修复客户端重连后没有触发 Topic 订阅的问题。 #smart-mqtt broker v0.7发布(2022-09-10)(opens new window) 新增 docker-compose.yml ,极致体验的 MQTT Broker。 优化日志级别。 Broker接受消息后不对Qos进行持久化。 ping响应消息采用单例模式。 支持系统环境变量配置broker运行参数,现开放 BROKER_PORT、BROKER_THREADNUM两项配置。 将插件的启动先于 Broker TCP服务启动之前完成。 启动 TCP 服务时若发生异常释放相关资源。 启用内存池,提升运行性能。 消息read缓冲区暂时下降至 4KB,下个迭代换成配置化。 启用运行指标监控插件。 #smart-mqtt broker v0.6发布(2022-09-03)(opens new window) 应社区用户要求,开源版 smart-mqtt适配 JDK 回退至1.8。 完善retain消息的规范实现,当服务端接收到保留标志为 1 且有效载荷为零字节的 PUBLISH 报文时,该主题下任何现存的保留消息必须被移除。 优化日志输出格式,增加时间信息。 smart-mqtt broker 线程数支持配置化。 更新客户端connect鉴权的接口设计。(by @yamikaze ) 支持docker启动 smart-mqtt 服务 修复mqtt协议版本不兼容时引发的空指针问题。 修复订阅topic后retain消息被无限推送的问题。 #smart-mqtt broker v0.5发布(2022-07-17)(opens new window) 【新特性】Broker支持客户端连接鉴权 【优化】重构Topic订阅逻辑,并增加重订阅特性 【优化】简化客户端连接超时监听的处理逻辑。 【优化】对各事件类型打上标注 【优化】清理TopicFilterProvider,开源版与企业版保持同等Topic匹配策略 【优化】采用事件总线监听连接活跃状态 【优化】确保网络断开后,事件状态 EventType.DISCONNECT 必然被调用 【优化】引入订阅事件的退出机制 【优化】AbstractSession 新增 getRemoteAddress 接口 #smart-mqtt broker v0.4发布(2022-07-10)(opens new window) 【新特性】升级了Broker内核的架构设计,采用事件驱动+消息驱动的双引擎模式构建出具备高度扩展性的MQTT服务 【新特性】支持Topic通配符的订阅方式 【优化】彻底移除了原先监听器的功能,统一切换至事件总线 【优化】引入 slf4j-simple 进行日志输出 【优化】升级 smart-socket 至 1.5.19,带来更安全的网络通讯,可支持 TLSv1.3 【优化】移除 fastjson 依赖 【优化】其他一些细节优化 【Bugfix】修复连接成功后userName未绑定至MqttSession的问题 #smart-mqtt broker v0.3发布(2022-05-01)(opens new window) 【新特性】Retain 消息内存持久化,并在客户端 CONNECT 成功后推送匹配的消息。 【新特性】新增飞行窗口(Inflight Window)功能,限制同时发送Qos1和Qos2的数量,保障通信质量。 【新特性】新增 MQTT Broker 和 MQTT Client 的消息重发功能。 【优化】重构 MQTT 消息模型设计。 【优化】改进消息内存持久化的处理逻辑。 【优化】提升并发场景下的线程安全性。 【优化】改进客户端的 subscribe 和 publish 的接口设计。 【优化】客户端正常断开连接时发送 DISCONNECT 消息。 【优化】MQTT 消息对象序列化调整为 JSON 格式。 【优化】主动拦截已断开连接的消息发送行为。 【优化】以正整数作为合法的 packetId。 【优化】补充压测的单元测试。 【bugfix】修复Broker端在某些异常场景下资源释放不彻底问题。 【bugfix】修复 CONNECT 消息的合法性校验错误问题:如果客户端提供的 ClientId 为零字节且清理会话标志为 0,服务端必须发送返回码为 0x02的 CONNACK 报文响应客户端的 CONNECT 报文。 #smart-mqtt broker v0.2发布(2022-04-18)(opens new window) 优化客户端ping消息:发送了 PINGREQ 报文之后,如果在合理的时间内仍没有收到 PINGRESP 报文,则关闭到服务端的网络连接。 优化Connect消息监听:网络连接建立后,如果服务端在合理的时间内没有收到 CONNECT 报文,服务端应该关闭这个连接。 优化 Connect ACK 消息监听:如果客户端在合理的时间内没有收到服务端的 CONNACK 报文,客户端应该关闭网络连接。 优化报文标识符的生成策略,防止同一标识符在同时刻被复用。 内存持久化会话状态。 重构Qos1和Qos2的回调处理机制。 bugfix:修复unsuback报文标识符取值不正确问题 bugfix:修复 broker 推送消息至subscriber时继承了publisher消息质量的问题。 其他一些代码细节优化 #smart-mqtt broker v0.1发布(2022-04-14)(opens new window) 支持MQTT v3.1.1协议标准 支持Qos0、Qos1、Qos2 的消息传递 支持遗嘱消息 支持 retain 消息 支持心跳消息 插件化设计模式 mqtt client 相关功能 优雅停机 --- ### 44. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当谈到MQTT(Message Queuing Telemetry Transport)时,有许多不同编程语言的库和工具可供选择,以便轻松地集成MQTT通信协议到您的项目中。MQTT是一种轻量级的消息协议,特别适用于物联网(IoT)和低带宽、高延迟或不可靠网络环境。本文将介绍一些流行的编程语言以及它们的MQTT库和工具,帮助您在各种环境中实现可靠的消息通信。 C/C++: 编程语言库/工具名称详细信息CEclipse Paho C通用MQTT C库。CEclipse Paho Embedded C用于嵌入式系统的MQTT C库。ClibmosquittoMosquitto MQTT代理的C库。Clibemqtt用于嵌入式系统的C MQTT客户端库。CMQTT-C便携式MQTT C客户端,适用于嵌入式系统和PC。CwolfMQTT嵌入式C MQTT客户端。CSharkMQTT嵌入式C MQTT客户端。Clibcurllibcurl具有基本的发布和订阅支持。CMQTT over lwIP用于嵌入式系统的MQTT C客户端,使用FreeRTOS,lwIP和mbedtls。Clibsmartfactory支持智能工厂和工业4.0技术的库,包括MQTT客户端实现。Clibumqtt基于libev的轻量级和完全异步的C MQTT客户端库。C++Eclipse Paho C++通用MQTT C++库。C++libmosquittoppMosquitto MQTT代理的C++库。C++Eclipse Paho Embedded C++用于嵌入式系统的MQTT C++库。C++mqtt_cpp基于C++14和Boost.Asio的MQTT客户端和服务器库,支持MQTT v3.1.1和v5。C++async_mqtt基于C++17和Boost.Asio的MQTT客户端和服务器库,支持MQTT v3.1.1和v5.0。C++eMQTT5MQTT 5.0客户端。 Python: 编程语言库/工具名称详细信息PythonEclipse Paho Python最初由Mosquitto Python客户端编写。Pythongmqtt异步Python 3 MQTT客户端库。Pythonnyamuk一个轻量级的Python MQTT客户端库。PythonMQTT for twisted python用于Twisted Python的MQTT库。PythonHBMQTT高性能Python MQTT客户端库,支持MQTT 5.0和MQTT 3.1.1。Pythonmqttools用于Python的MQTT协议工具和客户端库。 Java: 编程语言库/工具名称详细信息JavaActiveMQ ClientApache ActiveMQ的Java客户端库。JavaEclipse Paho Java通用MQTT Java库。JavaFusesource mqtt-clientFusesource MQTT客户端库。JavaMeQanTTJava MQTT客户端库,支持Android和Processing。JavamoquetteJava实现的MQTT代理库。JavaMqttWkJava MQTT客户端库。JavaHiveMQ MQTT Client高性能Java MQTT客户端库,支持MQTT 5.0和MQTT 3.1.1。JavaIA92 (已弃用)IBM IA92支持包,现已弃用。JavaQatja用于Android和Processing的Java客户端库,支持MQTT 3.1.1。JavaSentienz Akiro MQTT ClientJava MQTT代理客户端库,支持MQTT 3.1.1。Javavertx-mqtt-client开源、高性能、非阻塞的Java MQTT客户端库,作为vert.x的JVM工具包的一部分。JavaXenqtt包含客户端库、用于单元/集成测试的模拟代理以及支持企业需求的应用程序,如将一组服务器用作单个客户端、HTTP网关等。JavaMicronaut MQTTMicronaut Framework和MQTT的集成。 Dart: 编程语言库/工具名称详细信息Dartmqtt.dart用于Dart的MQTT客户端库。Dartmqtt_clientDart的MQTT客户端库。 Delphi: 编程语言库/工具名称详细信息DelphiDelphi-TMQTT2Delphi的MQTT客户端库。 Erlang: 编程语言库/工具名称详细信息ErlangerlmqttErlang的MQTT客户端库。ErlangemqttcErlang MQTT客户端库。Erlangmqtt4erlErlang的MQTT客户端库。Erlangmy-mqtt4erl (已更新的分支)Erlang的MQTT客户端库。Erlangerl.mqtt.clientErlang的MQTT客户端库。 Elixir: 编程语言库/工具名称详细信息Elixirhulaaki用于与MQTT代理通信的Elixir库(驱动程序),支持MQTT 3.1.1协议。ElixirExmqttcemqttc库的Elixir包装器。Elixirtortoise用Elixir编写的MQTT客户端。 Go: 编程语言库/工具名称详细信息GoEclipse Paho Go通用MQTT Go库。Gomqtt by jeffallenGo中的MQTT实现。GoMQTT🤖适用于嵌入式系统的简单、小型MQTT实现。Gonatiu-mqtt适用于嵌入式系统的简单、小型MQTT实现。 Haskell: 编程语言库/工具名称详细信息Haskellmqtt-hsHaskell的MQTT库。Haskellnet-mqtt (支持3.1.1和5.0客户端)Haskell的MQTT库。 Javascript/Node.js: 编程语言库/工具名称详细信息JavaScript/Node.jsAscoltatori一个支持Redis、AMQP、MQTT和ZeroMQ的Node.js发布/订阅库,具有相同的API。JavaScript/Node.jsEclipse Paho HTML5 JavaScript over WebSocket用于HTML5的JavaScript MQTT库,支持WebSocket。JavaScript/Node.jsIBM-provided PhoneGap/Cordova MQTT plug-in for AndroidJavaScript API与Eclipse Paho HTML5 JavaScript相同。JavaScript/Node.jsmqtt.jsJavaScript MQTT库。JavaScript/Node.jsnode_mqtt_clientNode.js的MQTT客户端库。 LotusScript: 编程语言库/工具名称详细信息LotusScriptMQTT From LotusScript用于LotusScript的MQTT库。 Lua: 编程语言库/工具名称详细信息LuaBarracuda App Server's MQTT ClientBarracuda App Server的MQTT客户端库。LuaEclipse Paho Lua通用Lua MQTT库。Lualuamqtt纯Lua MQTT客户端。Lualibumqttlibumqtt库的Lua绑定。Lualua-mosquittolua-mosquitto库,对libmosquitto的绑定。 .NET/dotNET: 编程语言库/工具名称详细信息.NET/dotNETHiveMQtt - The Spectacular C# MQTT Client for .NET非常出色的.NET C# MQTT客户端库。.NET/dotNETKittyHawkMQ.NET平台的MQTT库。.NET/dotNETMQTTnet通用.NET MQTT库。.NET/dotNETMqttDotNet.NET平台的MQTT库。.NET/dotNETnMQTT.NET MQTT库。.NET/dotNETM2MQTT适用于.NET Micro Framework的MQTT库。.NET/dotNETPaho.MqttDotnetPaho项目的.NET C#客户端。.NET/dotNETStriderMqtt.NET平台的MQTT库。.NET/dotNETxamarin mqttXamarin移动应用程序的MQTT库。 Objective-C: 编程语言库/工具名称详细信息Objective-CmqttIO-objCObjective-C的MQTT库。Objective-Clibmosquitto (通过包装器,示例)Objective-C的MQTT库,通过包装器使用libmosquitto。Objective-CMQTTKit (示例应用程序)Objective-C的MQTT库, 附带示例应用程序。 | OCaml: 编程语言库/工具名称详细信息OCamlocaml-mqttOCaml的MQTT库。OCamlmqtt_clientOCaml的MQTT库。 Perl: 编程语言库/工具名称详细信息Perlnet-mqtt-perlPerl的MQTT库。Perlanyevent-mqtt-perlAnyEvent框架中的Perl MQTT库。PerlWebSphere-MQTT-ClientWebSphere中的Perl MQTT客户端。PerlNet::MQTT::Simple (CPAN,GitHub)Perl的MQTT库。 PHP: 编程语言库/工具名称详细信息PHPphpMQTTPHP的MQTT库。PHPMosquitto-PHPMosquitto的PHP库。PHPsskaje's MQTT libraryPHP的MQTT库。PHPSimps/MQTT用于PHP的MQTT协议分析和协程客户端,支持MQTT 3.1,3.1.1和5.0版本。 Prolog: 编程语言库/工具名称详细信息PrologMQTT Pack - Mosquitto library as a SWI-Prolog packMosquitto库的SWI-Prolog包。 Qt: 编程语言库/工具名称详细信息QtqmqttQt的MQTT客户端库。 Ruby: 编程语言库/工具名称详细信息Rubyruby-mqttRuby的MQTT库。Rubyem-mqttRuby的MQTT库。RubymosquittoMosquitto的Ruby库。 Rust: 编程语言库/工具名称详细信息Rustmqrstt - Pure rust MQTTv5 client纯Rust MQTTv5客户端。 Shell Script: 编程语言库/工具名称详细信息Shell Scriptbish-bosh支持bash、ash(包括BusyBox)、pdksh和mksh。 Smalltalk: 编程语言库/工具名称详细信息SmalltalkMQTT client for Squeak, for Squeak 5.1Squeak 5.1的Squeak MQTT客户端库。 Swift: 编程语言库/工具名称详细信息SwiftCocoaMQTT用Swift编写的iOS和OS X的MQTT客户端。SwiftMQTT NIO支持v3.1.1和v5.0的Swift NIO MQTT客户端。 Tcl: 编程语言库/工具名称详细信息Tcltcl-mqtt用于Tcl的MQTT客户端库。 这是一个更全面的列表,包括各种编程语言的MQTT库和工具。您可以根据您的项目需求选择适当的库和工具来支持MQTT通信。如果您需要更多信息或有其他问题,请随时提问。 --- ### 45. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT CLI 完全指南 什么是 MQTT CLI? MQTT CLI 是一个完全兼容 MQTT 5.0 和 MQTT 3.1.1 的命令行界面,专为 MQTT 客户端设计,使用 HiveMQ MQTT Client API。 HiveMQ CLI 是 HiveMQ 支持的开源项目。 在GitHub上查看 特点 支持所有 MQTT 3.1.1 和 MQTT 5.0 的功能。 所有 MQTT 命令都提供交互式、直接和详细模式。 具备Shell行为、语法高亮、命令历史功能。 能够同时连接多个 MQTT 客户端到不同的代理。 快速的代理测试功能。 从 HiveMQ API 端点导出信息。 提供各种版本供下载和使用。 使用方法 要在您的系统上安装MQTT CLI,请遵循安装指南。 启动CLI的最简单方法是键入:mqtt。您也可以查看 mqtt --help 获取更多帮助信息。 运行后,您会看到如何使用MQTT CLI的输出信息: $ mqtt Usage: mqtt [-hV] { pub | sub | shell | test | hivemq | swarm } MQTT 命令行解释器。 选项: -h, --help 显示此帮助消息并退出。 -V, --version 打印版本信息并退出。 命令: pub, publish 向多个主题发布消息。 sub, subscribe 订阅MQTT客户端到多个主题。 shell, sh 启动MQTT CLI的shell模式,启用交互模式并执行更多子命令。 test 测试指定的代理对不同MQTT功能的支持并打印结果。 hivemq HiveMQ 命令行解释器。 swarm HiveMQ Swarm 命令行解释器。 起始时支持的命令 Publish Subscribe Shell Test HiveMQ Swarm 基础发布 mqtt pub -t topic -m "Hello World" 此命令执行以下操作: 连接MQTT客户端到默认主机(localhost)上位于默认端口(1883)的代理。 向指定主题发布消息。 从代理断开MQTT客户端连接。 详细的发布命令概述请查看 [Publish]。 基础订阅 mqtt sub -t topic 此命令执行以下操作: 连接MQTT客户端到默认主机(localhost)上位于默认端口(1883)的代理。 保持连接以检索发布到给定主题的消息。 在 Ctrl + C 上退出并断开客户端连接。 详细的订阅命令概述请查看 [Subscribe]。 开始交互式Shell $ mqtt shell ... mqtt> Shell模式使您能够执行更复杂的MQTT行为 - 详细信息请查看 [Shell]。 测试MQTT代理 $ mqtt test 此命令针对运行在默认主机上的默认端口的代理运行快速测试套件。结果会打印到控制台。 HiveMQ 命令行 $ mqtt hivemq 此命令提供了与正在运行的HiveMQ实例互动的命令。 HiveMQ Swarm HiveMQ Swarm命令提供了与HiveMQ Swarm互动的各种方式。 $ mqtt swarm 此命令为您提供了HiveMQ Swarm的状态检查和运行命令行解释器。 希望此文章为您提供了一个完整的MQTT CLI的入门指南!如果您有任何问题或需要进一步的信息,请访问官方文档或联系技术支持。 --- ### 46. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 https://github.com/mgdm/Mosquitto-PHP Mosquitto-PHP是一个用于与MQTT(Message Queuing Telemetry Transport)协议交互的PHP扩展,它允许PHP应用程序通过MQTT与消息代理进行通信。以下是有关Mosquitto-PHP的一些关键信息: 1. Mosquitto-PHP扩展介绍: Mosquitto-PHP是一个PHP扩展,它提供了与Eclipse Mosquitto MQTT客户端库的集成,使PHP开发者能够轻松地编写MQTT客户端应用程序。 2. PHP 7支持: Mosquitto-PHP扩展已更新以支持PHP 7版本,这意味着它可以在PHP 7及更高版本上运行。这扩展的PHP 7支持得益于Sara Golemon的工作。 3. 扩展要求: PHP版本要求:Mosquitto-PHP扩展要求PHP 5.3及更高版本。 libmosquitto版本要求:它需要使用libmosquitto库的1.2.x版本或更高版本。 支持的操作系统:通常在Linux和Mac OS X上工作,但未明确支持Windows。不过,欢迎开发人员提交Windows支持的贡献。 4. 安装Mosquitto-PHP: 您可以使用PECL来安装Mosquitto-PHP扩展。例如,使用以下命令来安装: pecl install Mosquitto-alpha 或者,您也可以使用传统的扩展构建过程来手动构建和安装它: phpize ./configure --with-mosquitto=/path/to/libmosquitto make make install 最后,将extension=mosquitto.so添加到您的php.ini文件中以启用扩展。 5. 使用Mosquitto-PHP: Mosquitto-PHP允许您以异步方式与MQTT代理进行交互。您需要使用回调函数来处理连接、发布、订阅和消息接收等事件。 例如,以下是如何正确发布QoS为2的消息的示例: use Mosquitto\Client; $mid = 0; $c = new Mosquitto\Client("PHP"); $c->onConnect(function() use ($c, &$mid) { $mid = $c->publish("mgdm/test", "Hello", 2); }); $c->onPublish(function($publishedId) use ($c, $mid) { if ($publishedId == $mid) { $c->disconnect(); } }); $c->connect("localhost"); $c->loopForever(); 您可以根据具体的MQTT应用程序要求,使用Mosquitto-PHP来创建定制的MQTT客户端。 总之,Mosquitto-PHP扩展使PHP开发者能够轻松地与MQTT代理进行通信,这对于构建物联网(IoT)应用程序和其他需要实时消息传递的应用程序非常有用。您可以使用它来连接、发布、订阅和处理MQTT消息。 event.php <?php $c = new Mosquitto\Client(); $c->onConnect(function($code, $message) { echo "I'm connected\n"; }); $c->connect('localhost', 1883, 60); $c->subscribe('#', 1); $c->onMessage(function($m) { var_dump($m); }); $socket = $c->getSocket(); $base = new EventBase(); $ev = new Event($base, $socket, Event::READ | Event::PERSIST, 'cb', $base); function cb($fd, $what, $arg) { global $c; echo "Triggered\n"; var_dump(func_get_args()); $c->loop(); } $ev->add(); $base->dispatch(); 这段 PHP 代码演示了如何使用 Mosquitto-PHP 扩展与 MQTT 服务器进行通信,并使用 libevent 库创建一个事件驱动的应用程序。以下是对代码的详细解释: 创建 Mosquitto 客户端对象: $c = new Mosquitto\Client(); 在这里,您创建了一个 Mosquitto 客户端对象 $c。 设置连接回调函数: $c->onConnect(function($code, $message) { echo "I'm connected\n"; }); 这个回调函数会在成功连接到 MQTT 服务器时执行,它简单地打印出 "I'm connected"。 连接到 MQTT 服务器: $c->connect('localhost', 1883, 60); 这行代码连接到 MQTT 服务器,指定了服务器的主机名为 'localhost',端口号为 1883,超时时间为 60 秒。 订阅 MQTT 主题: $c->subscribe('#', 1); 这里使用 subscribe 方法订阅了 MQTT 主题 '#',表示订阅所有主题。第二个参数 1 表示使用 QoS 1 等级。 设置接收消息的回调函数: $c->onMessage(function($m) { var_dump($m); }); 这个回调函数将在接收到 MQTT 消息时执行,它简单地使用 var_dump 打印消息内容。 获取 Mosquitto 客户端的套接字: $socket = $c->getSocket(); 这里通过 $c->getSocket() 获取 Mosquitto 客户端的套接字,以便后续在 libevent 中使用。 创建 libevent 基础对象和事件对象: $base = new EventBase(); $ev = new Event($base, $socket, Event::READ | Event::PERSIST, 'cb', $base); 这里创建了 libevent 基础对象 $base 和事件对象 $ev。事件对象监听 Mosquitto 客户端套接字的可读事件,并在事件触发时调用 'cb' 函数。 定义事件触发后的回调函数: function cb($fd, $what, $arg) { global $c; echo "Triggered\n"; var_dump(func_get_args()); $c->loop(); } 这是事件触发后执行的回调函数 'cb'。它会在事件触发时打印 "Triggered" 和一些调试信息,然后调用 Mosquitto 客户端的 loop 方法来处理 MQTT 消息。 将事件对象添加到 libevent 循环: $ev->add(); 这行代码将事件对象 $ev 添加到 libevent 的事件循环中,以便监听 Mosquitto 客户端套接字的可读事件。 启动 libevent 事件循环: $base->dispatch(); 最后,这行代码启动 libevent 的事件循环,使其开始监听事件并执行回调函数。这将允许 Mosquitto 客户端接收和处理 MQTT 消息。 总之,这段代码创建了一个 Mosquitto 客户端,连接到 MQTT 服务器,订阅所有主题,并使用 libevent 库实现了一个事件驱动的应用程序,该应用程序能够异步接收和处理 MQTT 消息。当 Mosquitto 客户端接收到消息时,会触发 libevent 事件,然后执行回调函数来处理消息。 pub.php <?php $client = new Mosquitto\Client(); $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->connect("localhost", 1883, 5); $client->subscribe('/#', 1); while (true) { $client->loop(); $mid = $client->publish('/hello', "Hello from PHP at " . date('Y-m-d H:i:s'), 1, 0); echo "Sent message ID: {$mid}\n"; $client->loop(); sleep(2); } $client->disconnect(); unset($client); function connect($r) { echo "I got code {$r}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function message($message) { printf("Got a message ID %d on topic %s with payload:\n%s\n\n", $message->mid, $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } 这段 PHP 代码演示了如何使用 Mosquitto-PHP 扩展与 MQTT 服务器进行通信以及订阅和发布 MQTT 消息。以下是代码的详细解释: 创建 Mosquitto 客户端对象: $client = new Mosquitto\Client(); 在这里,您创建了一个 Mosquitto 客户端对象 $client。 设置连接、订阅、消息和断开连接的回调函数: $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); 这些回调函数分别用于处理连接成功时的事件('connect')、断开连接时的事件('disconnect')、订阅主题时的事件('subscribe')、接收到消息时的事件('message')。 连接到 MQTT 服务器: $client->connect("localhost", 1883, 5); 这行代码连接到 MQTT 服务器,指定了服务器的主机名为 'localhost',端口号为 1883,超时时间为 5 秒。 订阅 MQTT 主题: $client->subscribe('/#', 1); 这里使用 subscribe 方法订阅了 MQTT 主题 '/#',表示订阅所有以 '/' 开头的主题。第二个参数 1 表示使用 QoS 1 等级。 进入循环并发送消息: while (true) { $client->loop(); $mid = $client->publish('/hello', "Hello from PHP at " . date('Y-m-d H:i:s'), 1, 0); echo "Sent message ID: {$mid}\n"; $client->loop(); sleep(2); } 这个 while 循环会持续运行,其中包含了 Mosquitto 客户端的 loop 方法,以便处理 MQTT 消息和事件。在循环中,它会使用 publish 方法发布一条带有时间戳的消息到主题 '/hello'。然后等待 2 秒继续下一轮循环。 断开连接和清理: $client->disconnect(); unset($client); 最后,代码在循环结束后手动断开了与 MQTT 服务器的连接,并释放了 Mosquitto 客户端对象。 回调函数的定义: function connect($r) { echo "I got code {$r}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function message($message) { printf("Got a message ID %d on topic %s with payload:\n%s\n\n", $message->mid, $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } 这些回调函数分别用于处理连接成功、订阅成功、接收到消息和断开连接的事件。在这些函数中,您可以自定义处理逻辑以响应不同事件。 总之,这段代码创建了一个 Mosquitto 客户端,连接到 MQTT 服务器,订阅主题,并周期性地发布消息。它还设置了回调函数来处理不同的事件,使您能够根据需要自定义处理逻辑。最后,代码手动断开了连接并清理资源。 subclass.php <?php class MyClient extends Mosquitto\Client { protected $pendingSubs = []; protected $grantedSubs = []; protected $subscribeCallback = null; public function __construct($id = null, $cleanSession = false) { parent::__construct($id, $cleanSession); parent::onSubscribe(array($this, 'subscribeHandler')); } public function subscribeHandler($mid, $qosCount, $grantedQos) { if (!isset($this->pendingSubs[$mid])) { return; } $topic = $this->pendingSubs[$mid]; $this->grantedSubs[$topic] = $grantedQos; echo "Subscribed to topic {$topic} with message ID {$mid}\n"; if (is_callable($this->subscribeCallback)) { $this->subscribeCallback($mid, $qosCount, $grantedQos); } } public function subscribe($topic, $qos) { $mid = parent::subscribe($topic, $qos); $this->pendingSubs[$mid] = $topic; } public function onSubscribe(callable $callable) { $this->subscribeCallback = $callable; } public function getSubscriptions() { return $this->grantedSubs; } } $c = new MyClient('subscriptionTest'); $c->onSubscribe(function() { echo "Hello, I got subscribed\n"; }); $c->connect('localhost', 1883, 50); $c->subscribe('#', 1); for ($i = 0; $i < 5; $i++) { $c->loop(10); } var_dump($c->getSubscriptions()); 这段 PHP 代码演示了如何创建一个自定义的 Mosquitto 客户端类 MyClient,该类继承了 Mosquitto 客户端,并添加了一些自定义功能。以下是代码的详细解释: 创建自定义 Mosquitto 客户端类 MyClient: class MyClient extends Mosquitto\Client { // ... } 在这里,您创建了一个名为 MyClient 的类,它继承自 Mosquitto 客户端。 构造函数 __construct: public function __construct($id = null, $cleanSession = false) { parent::__construct($id, $cleanSession); parent::onSubscribe(array($this, 'subscribeHandler')); } 在构造函数中,您首先调用了父类(Mosquitto 客户端)的构造函数,并注册了 subscribeHandler 方法作为订阅事件的回调函数。 订阅处理函数 subscribeHandler: public function subscribeHandler($mid, $qosCount, $grantedQos) { // ... } 这个方法会在成功订阅主题时被调用。它会处理订阅事件的回调,并将订阅的主题和相应的 QoS 存储到 grantedSubs 数组中。然后,它会触发 subscribeCallback 回调函数(如果已设置)。 订阅主题方法 subscribe: public function subscribe($topic, $qos) { $mid = parent::subscribe($topic, $qos); $this->pendingSubs[$mid] = $topic; } 这个方法用于订阅主题,并将主题和消息 ID 存储到 pendingSubs 数组中。 设置订阅回调方法 onSubscribe: public function onSubscribe(callable $callable) { $this->subscribeCallback = $callable; } 这个方法允许您设置订阅事件的回调函数,以便在订阅时执行自定义逻辑。 获取订阅信息方法 getSubscriptions: public function getSubscriptions() { return $this->grantedSubs; } 这个方法用于获取已订阅的主题及其对应的 QoS。 创建 MyClient 对象,设置回调和执行订阅: $c = new MyClient('subscriptionTest'); $c->onSubscribe(function() { echo "Hello, I got subscribed\n"; }); $c->connect('localhost', 1883, 50); $c->subscribe('#', 1); 在这里,您创建了一个 MyClient 对象,并设置了订阅回调函数。然后,连接到 MQTT 服务器,订阅了以 '#' 开头的所有主题。 使用 loop 方法运行客户端循环: for ($i = 0; $i < 5; $i++) { $c->loop(10); } 这个循环允许客户端运行,并处理 MQTT 消息和事件。loop(10) 意味着每次循环会等待 10 毫秒来处理事件。 获取订阅信息并输出: var_dump($c->getSubscriptions()); 最后,您使用 getSubscriptions 方法获取已订阅的主题信息,并将其输出。 总之,这段代码演示了如何创建自定义的 Mosquitto 客户端类,以处理 MQTT 订阅事件,并提供了一些自定义功能,例如获取已订阅的主题信息和设置订阅回调函数。这使您能够更灵活地与 MQTT 服务器进行通信和处理订阅。 test.php <?php $client = new Mosquitto\Client(); $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->connect("localhost", 1883, 5); $client->onLog('logger'); $client->subscribe('#', 1); for ($i = 0; $i < 10; $i++) { $client->loop(); } $client->unsubscribe('#'); for ($i = 0; $i < 10; $i++) { $client->loop(); } function connect($r, $message) { echo "I got code {$r} and message {$message}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function unsubscribe() { echo "Unsubscribed from a topic\n"; } function message($message) { printf("Got a message on topic %s with payload:\n%s\n", $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } function logger() { var_dump(func_get_args()); } 这段 PHP 代码演示了如何使用 Mosquitto 客户端库与 MQTT 代理(通常在 localhost 上运行)进行通信,并定义了一些回调函数来处理不同的 MQTT 事件。以下是这段代码的详细解释: 1. 创建 Mosquitto 客户端对象: $client = new Mosquitto\Client(); 这行代码创建了一个 Mosquitto 客户端对象,用于连接到 MQTT 代理并执行 MQTT 操作。 2. 设置回调函数: $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->onLog('logger'); 这些行设置了不同事件的回调函数。当客户端连接成功时,onConnect 回调函数将被调用,当客户端断开连接时,onDisconnect 回调函数将被调用,以此类推。这些回调函数会在后面的代码中定义。 3. 连接到 MQTT 代理: $client->connect("localhost", 1883, 5); 这行代码连接到本地 MQTT 代理,通常运行在 localhost 主机的 1883 端口上。连接的超时时间设置为 5 秒。 4. 订阅 MQTT 主题: $client->subscribe('#', 1); 这行代码订阅了名为 # 的 MQTT 主题,这个特殊的主题表示订阅所有主题。订阅的 QoS(服务质量)级别设置为 1。 5. 运行 MQTT 客户端循环: for ($i = 0; $i < 10; $i++) { $client->loop(); } 这个循环运行 MQTT 客户端,允许它接收和处理来自 MQTT 代理的消息以及触发不同事件的回调函数。 6. 取消订阅 MQTT 主题: $client->unsubscribe('#'); 这行代码取消订阅之前订阅的 # 主题,即停止接收与该主题相关的消息。 7. 再次运行 MQTT 客户端循环: for ($i = 0; $i < 10; $i++) { $client->loop(); } 这段代码再次运行 MQTT 客户端循环,确保处理所有取消订阅后的事件。 8. 定义各种事件回调函数: 下面是定义的不同事件的回调函数: connect($r, $message):当客户端成功连接到 MQTT 代理时,此回调被调用,显示连接结果代码 $r 和消息 $message。 subscribe():当客户端成功订阅主题时,此回调被调用,显示 "Subscribed to a topic"。 unsubscribe():当客户端成功取消订阅主题时,此回调被调用,显示 "Unsubscribed from a topic"。 message($message):当客户端接收到新消息时,此回调被调用,显示消息的主题和有效载荷。 disconnect():当客户端与 MQTT 代理断开连接时,此回调被调用,显示 "Disconnected cleanly"。 logger():此回调用于记录日志信息,它将输出回调函数的所有参数。 总之,这段代码创建了一个 MQTT 客户端并设置了回调函数,然后连接到 MQTT 代理,订阅主题,运行客户端循环以接收消息和处理事件,并在不同的事件发生时触发相应的回调函数,从而实现了 MQTT 通信。这对于与 MQTT 代理进行互动和处理消息非常有用。 testOnpublish.php <?php class MQ { public static $publish = array(); public static $receive = array(); public static function addPublish($mid, $msg) { $msg->id = $mid; self::$publish[$mid] = $msg; } public static function confirm($mid) { if(array_key_exists($mid, self::$publish)) { self::$publish[$mid]->state = true; } } public static function addReceive($msg) { $msg = Message::factory($msg, true); self::$receive[$msg->id] = $msg; } } class Message { public $id; public $state = false; public $msg; public static function factory(Mosquitto\Message $msg, $state = false) { $message = new Message(); $message->state = $state; $message->msg = $msg; $message->id = $msg->mid; return $message; } } $client = new Mosquitto\Client('client.terminal.onpublish', false); $client->onMessage(function($msg) { print_r(array('receive', $msg)); MQ::addReceive($msg); }); $client->onPublish(function($mid) { MQ::confirm($mid); print_r(array('comfirm publish', MQ::$publish[$mid])); }); $client->onConnect(function($rc, $msg) { print_r(array('rc' => $rc, 'message' => $msg)); }); $client->connect('localhost', 1883, 60); sleep(1); $client->subscribe('/test/publish', 1); $msg = Message::factory(new Mosquitto\Message()); $msg->msg->topic = '/test/publish'; $msg->msg->payload = 'hello from on publish'; $msg->msg->qos = 1; $mid = $client->publish($msg->msg->topic, $msg->msg->payload, $msg->msg->qos); print_r(array('publish', $msg)); MQ::addPublish($mid, $msg); sleep(1); $client->loopForever(); 这段PHP代码演示了如何使用Mosquitto客户端库创建一个MQTT客户端,该客户端具有自定义的消息确认和处理机制。以下是代码的详细解释: 1. 创建MQ类: class MQ { public static $publish = array(); public static $receive = array(); public static function addPublish($mid, $msg) { $msg->id = $mid; self::$publish[$mid] = $msg; } public static function confirm($mid) { if(array_key_exists($mid, self::$publish)) { self::$publish[$mid]->state = true; } } public static function addReceive($msg) { $msg = Message::factory($msg, true); self::$receive[$msg->id] = $msg; } } 这个类用于管理发布和接收的消息。它包括以下方法: addPublish($mid, $msg):将发布的消息添加到 $publish 数组中,以便稍后进行确认。 confirm($mid):确认已发布的消息,将其状态标记为已确认。 addReceive($msg):将接收的消息添加到 $receive 数组中。 2. 创建消息类Message: class Message { public $id; public $state = false; public $msg; public static function factory(Mosquitto\Message $msg, $state = false) { $message = new Message(); $message->state = $state; $message->msg = $msg; $message->id = $msg->mid; return $message; } } 这个类表示MQTT消息。它包括以下属性: $id:消息ID。 $state:消息状态,用于确认是否已接收。 $msg:实际的Mosquitto消息对象。 还包括一个工厂方法factory,用于从Mosquitto消息创建Message对象。 3. 创建Mosquitto客户端对象: $client = new Mosquitto\Client('client.terminal.onpublish', false); 这行代码创建了一个Mosquitto客户端对象,并为其指定了客户端ID和cleanSession标志。 4. 设置回调函数: $client->onMessage(function($msg) { print_r(array('receive', $msg)); MQ::addReceive($msg); }); $client->onPublish(function($mid) { MQ::confirm($mid); print_r(array('comfirm publish', MQ::$publish[$mid])); }); $client->onConnect(function($rc, $msg) { print_r(array('rc' => $rc, 'message' => $msg)); }); 这些回调函数用于处理不同的MQTT事件: onMessage:处理接收到的消息,将消息添加到MQ::$receive数组中。 onPublish:处理已发布的消息的确认,将消息标记为已确认。 onConnect:处理连接事件,打印连接结果。 5. 连接到MQTT代理: $client->connect('localhost', 1883, 60); 这行代码连接到本地MQTT代理,通常运行在localhost上的1883端口上。连接的超时时间设置为60秒。 6. 发布消息和处理: sleep(1); $client->subscribe('/test/publish', 1); $msg = Message::factory(new Mosquitto\Message()); $msg->msg->topic = '/test/publish'; $msg->msg->payload = 'hello from on publish'; $msg->msg->qos = 1; $mid = $client->publish($msg->msg->topic, $msg->msg->payload, $msg->msg->qos); print_r(array('publish', $msg)); MQ::addPublish($mid, $msg); sleep(1); $client->loopForever(); 这段代码的主要功能是: 订阅主题/test/publish。 创建一个要发布的消息对象$msg。 发布消息,并将消息添加到MQ::$publish数组中以进行后续确认。 使用loopForever方法持续运行MQTT客户端以处理消息和事件。 总之,这段代码创建了一个具有自定义消息确认和处理机制的MQTT客户端,它可以发布和接收消息,并在处理时跟踪消息的状态。这对于实现更高级的MQTT消息管理非常有用。 testwill.php <?php $client = new Mosquitto\Client(); $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->setWill('/hello', "Client died :-(", 1, 0); $client->connect("localhost", 1883, 5); $client->subscribe('/#', 1); $client->loopForever(); function connect($r) { echo "I got code {$r}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function message($message) { printf("Got a message on topic %s with payload:\n%s\n", $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } 这段PHP代码演示了如何创建一个Mosquitto MQTT客户端,该客户端具有以下功能: 1. 创建Mosquitto客户端对象: $client = new Mosquitto\Client(); 这行代码创建了一个Mosquitto客户端对象。 2. 设置连接和事件回调: $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); 这些行代码设置了不同MQTT事件的回调函数,当客户端连接、断开连接、订阅主题或接收消息时,将调用相应的回调函数。 3. 设置遗嘱消息(Will Message): $client->setWill('/hello', "Client died :-(", 1, 0); 这行代码设置了遗嘱消息,当客户端意外断开连接时,将自动发布遗嘱消息到主题/hello,消息内容是"Client died :-(",QoS级别为1,保留标志为0。 4. 连接到MQTT代理: $client->connect("localhost", 1883, 5); 这行代码连接到MQTT代理,该代理通常运行在本地主机(localhost)的1883端口上。连接超时设置为5秒。 5. 订阅主题: $client->subscribe('/#', 1); 这行代码订阅了以/#开头的所有主题,并将QoS级别设置为1。 6. 使用loopForever方法持续运行客户端: $client->loopForever(); 这行代码使客户端进入无限循环,以便处理MQTT消息和事件。客户端将保持连接状态,并在收到消息时调用相应的消息回调函数。 7. 定义连接、订阅、消息和断开连接的回调函数: 这些回调函数用于处理不同的MQTT事件: connect($r):处理连接事件,其中$r参数包含连接的返回码。 subscribe():处理订阅事件,表示成功订阅主题。 message($message):处理接收到的消息,打印主题和消息内容。 disconnect():处理断开连接事件,表示客户端已经断开连接。 总之,这段代码创建了一个Mosquitto MQTT客户端,连接到MQTT代理,订阅了一组主题,并设置了各种事件的回调函数。它还配置了遗嘱消息,以便在客户端意外断开连接时发送通知。最后,客户端使用loopForever方法持续运行,以便处理MQTT消息和事件。 --- ### 47. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT简介 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,广泛用于物联网设备之间的通信。MQTT协议采用了客户端/服务器架构,支持发布/订阅模式和点对点模式,以其高效、可靠、灵活等特点而著称。 MQTT协议的核心概念包括发布者(publisher)、代理服务器(broker)和订阅者(subscriber)。发布者将消息发布到代理服务器上,而订阅者则从代理服务器中订阅感兴趣的消息。代理服务器负责将消息传递给订阅者。 在MQTT中,主题(topic)是一个重要的概念,用于定义消息的类型和内容。发布者可以将消息发布到一个或多个主题上,而订阅者则可以订阅一个或多个主题的消息。 MQTT协议的轻量级和可靠性使其非常适合在不稳定的网络环境中传输大量消息。它被广泛应用于智能家居、车联网、工业物联网等领域,因为它具有快速响应和低带宽消耗的优势。 MQTTnet简介 MQTTnet是一个跨平台、高性能、开源的MQTT客户端库和服务端实现,是.NET平台上最受欢迎的MQTT实现之一。它可以方便地在.NET平台上集成MQTT功能,实现MQTT协议的消息传输和其他功能。 MQTTnet的源码托管在GitHub上,地址为:https://github.com/dotnet/MQTTnet 在.NET 7中使用MQTTnet 接下来,我们将介绍如何在.NET 7中使用MQTTnet来创建一个简单的MQTT发布和订阅示例。这个示例将包括一个MQTT服务端和一个MQTT客户端。 项目准备 首先,我们需要创建两个.NET 7控制台项目,一个用作服务端,另一个用作客户端。这两个项目将实现MQTT消息发布和订阅功能。 然后,我们需要安装MQTTnet包。在本示例中,我们选择安装3.12版本的MQTTnet,但请注意,MQTTnet的不同版本之间可能存在差异,选择适合您项目需求的版本。 您可以使用NuGet包管理器或命令行来安装MQTTnet,命令如下: dotnet add package MQTTnet --3.12 服务端代码编写 接下来,我们将编写服务端的代码。以下是一个简化版本的服务端代码示例: using System; using System.Text; using System.Threading.Tasks; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; using MQTTnet.Extensions.ManagedClient; public static async Task RunMqttServer() { // 创建一个MQTT客户端工厂 var factory = new MqttFactory(); var client = factory.CreateMqttClient(); // 配置MQTT客户端选项 var options = new MqttClientOptionsBuilder() .WithTcpServer("localhost", 1883) // 指定MQTT代理服务器的地址和端口 .Build(); // 连接到MQTT代理服务器 await client.ConnectAsync(options); while (true) { Console.WriteLine("请输入要发布的消息: "); var message = Console.ReadLine(); // 创建MQTT消息 var mqttMessage = new MqttApplicationMessageBuilder() .WithTopic("testTopic") // 指定消息的主题 .WithPayload(Encoding.UTF8.GetBytes(message)) // 设置消息内容 .WithExactlyOnceQoS() // 设置消息的质量等级 .Build(); // 发布MQTT消息到代理服务器 await client.PublishAsync(mqttMessage); } } static async Task Main(string[] args) { // 运行MQTT服务端 await RunMqttServer(); } 在这个示例中,我们创建了一个MQTT客户端,连接到本地的MQTT代理服务器(broker)并发布消息到名为"testTopic"的主题。服务端将不断等待用户输入,并将用户输入的消息发布到MQTT代理服务器。 客户端代码编写 接下来,我们编写客户端的代码,以下是客户端代码示例: using System; using System.Text; using System.Threading.Tasks; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; public static async Task RunMqttClient() { // 创建 MQTT 客户端工厂 var factory = new MqttFactory(); var client = factory.CreateMqttClient(); // 配置 MQTT 客户端选项 var options = new MqttClientOptionsBuilder() .WithTcpServer("localhost", 1883) // 指定 MQTT 服务器地址和端口 .Build(); // 设置消息接收处理程序 client.UseApplicationMessageReceivedHandler(e => { // 当接收到 MQTT 消息时,将消息内容打印到控制台 Console.WriteLine($"接收到的消息: {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}"); }); // 连接到 MQTT 服务器 await client.ConnectAsync(options); // 订阅指定主题的消息 await client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("testTopic").Build()); } static async Task Main(string[] args) { // 运行 MQTT 客户端 await RunMqttClient(); } 在这个示例中,我们创建了一个MQTT客户端,连接到本地的 MQTT代理服务器,并订阅了名为"testTopic"的主题。一旦客户端接收到新的消息,它将在控制台上打印消息内容。 运行和测试 现在,我们已经完成了服务端和客户端的代码编写。您可以使用以下步骤来运行和测试这个示例: 在本地安装MQTT代理服务器,确保端口号和配置与代码中匹配。 分别运行服务端和客户端项目,它们将连接到MQTT代理服务器。 在服务端的控制台中输入要发布的消息,然后按回车键。 在客户端的控制台中,您将看到接收到的消息。 这个示例是一个简单的MQTT发布和订阅功能演示,实际项目中可以根据需求进行扩展,例如处理异常、加强安全性等。 总结 MQTT是一种重要的物联网通信协议,它提供了可靠、高效的消息传输机制,适用于各种物联网应用。MQTTnet是.NET平台上的一种强大工具,帮助您轻松集成MQTT功能到.NET应用程序中,无论是服务端还是客户端。 通过以上示例,您可以快速开始使用MQTTnet在.NET 7中创建自己的MQTT应用程序,并实现消息的发布和订阅功能。希望这个教程对您有所帮助,使您更好地理解和应用MQTT协议和MQTTnet库。 --- ### 48. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 fusesource/mqtt-client: A Java MQTT Client (github.com) 概述MQTT是一种机器对机器(M2M)/“物联网”连接协议。它被设计为一种极轻量级的发布/订阅消息传输协议。它适用于需要小型代码占用空间和/或网络带宽有限的远程位置连接。 mqtt-client提供了一个ASL 2.0许可的MQTT API。它会自动重新连接到您的MQTT服务器,并在发生任何网络故障时恢复客户端会话。应用程序可以使用阻塞式API风格、基于futures的API或回调/继续传递API风格。 使用Maven将以下内容添加到您的maven pom.xml文件中。 <dependency> <groupId>org.fusesource.mqtt-client</groupId> <artifactId>mqtt-client</artifactId> <version>1.12</version> </dependency> 使用Gradle将以下内容添加到您的gradle文件中。 compile 'org.fusesource.mqtt-client:mqtt-client:1.12' 使用其他构建系统下载uber JAR文件并将其添加到您的构建中。uber包含了mqtt-client依赖的其他项目中的所有精简依赖项。 在Java 1.4上使用我们还提供了与Java 1.4 JVM兼容的java 1.4 uber JAR文件。此版本的JAR不支持SSL连接,因为用于在NIO上实现SSL的SSLEngine类是在Java 1.5之前引入的。 配置MQTT连接阻塞、future和回调API都共享相同的连接设置。您可以创建一个MQTT类的新实例,并配置它以进行连接和套接字相关选项。至少在尝试连接之前必须调用setHost方法。 MQTT mqtt = new MQTT(); mqtt.setHost("localhost", 1883); // 或者 mqtt.setHost("tcp://localhost:1883"); 控制MQTT选项 setClientId:用于设置会话的客户端ID。这是MQTT服务器用于识别在使用setCleanSession(false);时使用的会话的ID。ID必须不超过23个字符。默认为自动生成的ID(基于您的套接字地址、端口和时间戳)。 setCleanSession:如果要使MQTT服务器在客户端会话之间保留主题订阅和确认位置,设置为false。默认为true。 setKeepAlive:以秒为单位配置保持活动定时器。定义从客户端接收的消息之间的最大时间间隔。它使服务器能够检测到与客户端的网络连接已断开,而不必等待长时间的TCP/IP超时。 setUserName:设置用于对服务器进行身份验证的用户名。 setPassword:设置用于对服务器进行身份验证的密码。 setWillTopic:如果设置,服务器将发布客户端的Will消息到指定的主题,如果客户端意外断开连接。 setWillMessage:要发送的Will消息。默认为零长度消息。 setWillQos:设置将消息的服务质量使用。默认为QoS.AT_MOST_ONCE。 setWillRetain:如果要发布Will并保留选项,则设置为true。 setVersion:设置为“3.1.1”以使用MQTT版本3.1.1。否则默认为3.1协议版本。 控制连接重新连接如果发生任何网络错误,连接将自动重新连接并恢复消息会话。您可以使用以下方法来控制重新连接的尝试频率并定义重新连接尝试的最大次数: setConnectAttemptsMax:在客户端第一次尝试连接到服务器时,最大的重新连接尝试次数之前会向客户端报告错误。设置为-1以使用无限次尝试。默认为-1。 setReconnectAttemptsMax:在以前曾建立过服务器连接后,每次客户端尝试重新连接后,最大的重新连接尝试次数之前会向客户端报告错误。设置为-1以使用无限次尝试。默认为-1。 setReconnectDelay:在第一次重新连接尝试之前等待的时间(以毫秒为单位)。默认为10。 setReconnectDelayMax:重新连接尝试之间等待的最大时间(以毫秒为单位)。默认为30,000。 setReconnectBackOffMultiplier:重新连接尝试之间使用指数退避。设置为1以禁用指数退避。默认为2。 配置套接字选项您可以使用以下方法调整一些套接字选项: setReceiveBufferSize:设置内部套接字接收缓冲区的大小。默认为65536(64k)。 setSendBufferSize:设置内部套接字发送缓冲区的大小。默认为65536(64k)。 setTrafficClass:设置IP头中的流量类或服务类型八位字节,用于从传输发送的数据包。默认为8,表示流量应优化以提高吞吐量。 限制连接速率如果要减慢连接的读取或写入速率,可以使用以下方法: setMaxReadRate:设置此传输将以每秒的最大字节数接收数据。此设置可限制读取,以便不超过速率。默认为0,表示禁用限制。 setMaxWriteRate:设置此传输将以每秒的最大字节数发送数据。此设置可限制写入,以便不超过速率。默认为0,表示禁用限制。 使用SSL连接如果要使用SSL/TLS而不是TCP进行连接,请在主机字段中使用“ssl://”或“tls://” URI前缀,而不是“tcp://”。要更精细地控制使用的算法。支持的协议值包括: ssl:// - 使用JVM默认版本的SSL算法。 sslv*:// 使用特定的SSL版本,其中*是您的JVM支持的版本。示例:sslv3 tls:// - 使用JVM默认版本的TLS算法。 tlsv:// - 使用特定的TLS版本,其中是您的JVM支持的版本。示例:tlsv1.1 客户端将使用默认的JVM SSLContext,该SSLContext通过JVM系统属性配置,除非您使用setSslContext方法配置MQTT实例。 SSL连接对内部线程池执行阻塞操作,除非您调用setBlockingExecutor方法来配置它们将使用的执行器。 选择分发队列HawtDispatch分发队列用于同步对连接的访问。如果未通过setDispatchQueue方法配置明确队列,则将为连接创建新队列。如果要使多个连接共享同一个队列以进行同步,设置明确的队列可能会很方便。 使用阻塞式APIMQTT.connectBlocking方法建立连接并为您提供具有阻塞API的连接。 BlockingConnection connection = mqtt.blockingConnection(); connection.connect(); 使用publish方法将消息发布到主题: connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false); 您可以使用subscribe方法订阅多个主题: Topic[] topics = {new Topic("foo", QoS.AT_LEAST_ONCE)}; byte[] qoses = connection.subscribe(topics); 然后使用receive和ack方法接收和确认消息的消费: Message message = connection.receive(); System.out.println(message.getTopic()); byte[] payload = message.getPayload(); // 处理消息后执行: message.ack(); 最后要断开连接: connection.disconnect(); 使用基于Future的APIMQTT.connectFuture方法建立连接并为您提供具有基于futures的API的连接。所有针对连接的操作都是非阻塞的,并通过Future返回结果。 FutureConnection connection = mqtt.futureConnection(); Future<Void> f1 = connection.connect(); f1.await(); Future<byte[]> f2 = connection.subscribe(new Topic[]{new Topic(utf8("foo"), QoS.AT_LEAST_ONCE)}); byte[] qoses = f2.await(); // 我们可以开始future接收... Future<Message> receive = connection.receive(); // 发送消息... Future<Void> f3 = connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false); // 然后接收将获得消息。 Message message = receive.await(); message.ack(); Future<Void> f4 = connection.disconnect(); f4.await(); 使用回调/继续传递APIMQTT.connectCallback方法建立连接并为您提供具有回调式API的连接。这是最复杂的API风格,但可以提供最佳性能。未来和阻塞API在底层使用回调API。连接上的所有操作都是非阻塞的,并且操作的结果通过您实现的回调接口传递。 final CallbackConnection connection = mqtt.callbackConnection(); connection.listener(new Listener() { public void onDisconnected() { } public void onConnected() { } public void onPublish(UTF8Buffer topic, Buffer payload, Runnable ack) { // 您现在可以处理从主题接收的消息。 // 处理后执行ack runnable。 ack.run(); } public void onFailure(Throwable value) { connection.close(null); // 发生了连接故障。 } }) connection.connect(new Callback<Void>() { public void onFailure(Throwable value) { result.failure(value); // 如果无法连接到服务器。 } // 一旦我们连接上... public void onSuccess(Void v) { // 订阅主题 Topic[] topics = {new Topic("foo", QoS.AT_LEAST_ONCE)}; connection.subscribe(topics, new Callback<byte[]>() { public void onSuccess(byte[] qoses) { // 订阅请求的结果。 } public void onFailure(Throwable value) { connection.close(null); // 订阅失败。 } }); // 发送消息到主题 connection.publish("foo", "Hello".getBytes(), QoS.AT_LEAST_ONCE, false, new Callback<Void>() { public void onSuccess(Void v) { // 发布操作成功完成。 } public void onFailure(Throwable value) { connection.close(null); // 发布失败。 } }); // 断开连接... connection.disconnect(new Callback<Void>() { public void onSuccess(Void v) { // 连接断开后调用。 } public void onFailure(Throwable value) { // 断开连接永远不会失败。 } }); } }); 每个连接都有一个HawtDispatch分发队列,用于处理套接字的IO事件。分发队列是一个Executor,提供IO和处理事件的串行执行,并用于确保连接的同步访问。 回调将在与连接关联的分发队列中执行,因此可以从回调中安全使用连接,但在回调内绝不能执行任何阻塞操作。如果需要执行可能会阻塞的某些处理,必须将其发送到另一个线程池进行处理。此外,如果其他线程需要与连接交互,只能通过将Runnable提交到连接的分发队列来完成。 --- ### 49. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 它是一个用于Netduino平台的MQTT客户端库,用于与MQTT代理进行通信。以下是关于如何使用它的一些信息: 安装:您需要将NetduinoMQTT库添加到您的Netduino项目中。具体的安装步骤可能会因您的开发环境而异,通常可以通过将库文件导入到项目中或使用包管理工具来完成。 示例代码:README中提到了一个名为"program.cs"的示例代码文件,该文件展示了如何使用NetduinoMQTT库的一些基本功能来与MQTT代理进行交互。您可以参考这些示例代码来了解如何开始使用该库。 版本支持:README列出了不同版本的库支持的功能,例如连接到MQTT代理、发送MQTT消息、订阅和取消订阅主题等。您可以根据您的需求和项目要求选择适合的版本。 版本 0.01(a) 支持: 连接到MQTT代理服务器(已测试RSMB和mosquitto) 向代理服务器发送MQTT消息 断开与代理服务器的连接 PING消息(用于保持连接,示例在program.cs中) NetduinoMQTT.cs /* Copyright 2011-2012 Dan Anderson. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY DAN ANDERSON ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Dan Anderson OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Net; using System.Net.Sockets; using System.Text; using Microsoft.SPOT; using Socket = System.Net.Sockets.Socket; namespace Netduino_MQTT_Client_Library { static class Constants { // TODO: Add other constants so we don't have "magic" numbers public const int MQTTPROTOCOLVERSION = 3; public const int MAXLENGTH = 268435455; // 256MB public const int MAX_CLIENTID = 23; public const int MIN_CLIENTID = 1; public const int MAX_KEEPALIVE = 65535; public const int MIN_KEEPALIVE = 0; public const int MAX_USERNAME = 65535; public const int MAX_PASSWORD = 65535; public const int MAX_TOPIC_LENGTH = 32767; public const int MIN_TOPIC_LENGTH = 1; // Error Codes public const int CLIENTID_LENGTH_ERROR = 1; public const int KEEPALIVE_LENGTH_ERROR = 1; public const int MESSAGE_LENGTH_ERROR = 1; public const int TOPIC_LENGTH_ERROR = 1; public const int TOPIC_WILDCARD_ERROR = 1; public const int USERNAME_LENGTH_ERROR = 1; public const int PASSWORD_LENGTH_ERROR = 1; public const int CONNECTION_ERROR = 1; public const int CONNECTION_OK = 0; public const int CONNACK_LENGTH = 4; public const int PINGRESP_LENGTH = 2; public const byte MQTT_CONN_OK = 0x00; // Connection Accepted public const byte MQTT_CONN_BAD_PROTOCOL_VERSION = 0x01; // Connection Refused: unacceptable protocol version public const byte MQTT_CONN_BAD_IDENTIFIER = 0x02; // Connection Refused: identifier rejected public const byte MQTT_CONN_SERVER_UNAVAILABLE = 0x03; // Connection Refused: server unavailable public const byte MQTT_CONN_BAD_AUTH = 0x04; // Connection Refused: bad user name or password public const byte MQTT_CONN_NOT_AUTH = 0x05; // Connection Refused: not authorized // Message types public const int MQTT_CONNECT_TYPE = 0x10; public const int MQTT_CONNACK_TYPE = 0x20; public const int MQTT_PUBLISH_TYPE = 0x30; public const int MQTT_PING_REQ_TYPE = 0xc0; public const int MQTT_PING_RESP_TYPE = 0xd0; public const int MQTT_DISCONNECT_TYPE = 0xe0; // Flags public const int CLEAN_SESSION_FLAG = 0x02; public const int USING_USERNAME_FLAG = 0x80; public const int USING_PASSWORD_FLAG = 0x40; public const int CONTINUATION_BIT = 0x80; } public static class NetduinoMQTT { public static int ConnectMQTT(Socket mySocket, String clientID, int keepAlive = 20, bool cleanSession = true, String username = "", String password = "") { int index = 0; int tmp = 0; int digit = 0; int remainingLength = 0; int fixedHeader = 0; int varHeader = 0; int payload = 0; int returnCode = 0; bool usingUsername = false; bool usingPassword = false; byte connectFlags = 0x00; byte[] buffer = null; UTF8Encoding encoder = new UTF8Encoding(); byte[] utf8ClientID = Encoding.UTF8.GetBytes(clientID); byte[] utf8Username = Encoding.UTF8.GetBytes(username); byte[] utf8Password = Encoding.UTF8.GetBytes(password); // Some Error Checking // ClientID improperly sized if ((utf8ClientID.Length > Constants.MAX_CLIENTID) || (utf8ClientID.Length < Constants.MIN_CLIENTID)) return Constants.CLIENTID_LENGTH_ERROR; // KeepAlive out of bounds if ((keepAlive > Constants.MAX_KEEPALIVE) || (keepAlive < Constants.MIN_KEEPALIVE)) return Constants.KEEPALIVE_LENGTH_ERROR; // Username too long if (utf8Username.Length > Constants.MAX_USERNAME) return Constants.USERNAME_LENGTH_ERROR; // Password too long if (utf8Password.Length > Constants.MAX_PASSWORD) return Constants.PASSWORD_LENGTH_ERROR; // Check features being used if (!username.Equals("")) usingUsername = true; if (!password.Equals("")) usingPassword = true; // Calculate the size of the var header varHeader += 2; // Protocol Name Length varHeader += 6; // Protocol Name varHeader++; // Protocol version varHeader++; // Connect Flags varHeader += 2; // Keep Alive // Calculate the size of the fixed header fixedHeader++; // byte 1 // Calculate the payload payload = utf8ClientID.Length + 2; if (usingUsername) { payload += utf8Username.Length + 2; } if (usingPassword) { payload += utf8Password.Length + 2; } // Calculate the remaining size remainingLength = varHeader + payload; // Check that remaining length will fit into 4 encoded bytes if (remainingLength > Constants.MAXLENGTH) return Constants.MESSAGE_LENGTH_ERROR; tmp = remainingLength; // Add space for each byte we need in the fixed header to store the length while (tmp > 0) { fixedHeader++; tmp = tmp / 128; }; // End of Fixed Header // Build buffer for message buffer = new byte[fixedHeader + varHeader + payload]; // Fixed Header (2.1) buffer[index++] = Constants.MQTT_CONNECT_TYPE; // Encode the fixed header remaining length tmp = remainingLength; do { digit = tmp % 128; tmp = tmp / 128; if (tmp > 0) { digit = digit | Constants.CONTINUATION_BIT; } buffer[index++] = (byte)digit; } while (tmp > 0); // End Fixed Header // Connect (3.1) // Protocol Name buffer[index++] = 0; // String (MQIsdp) Length MSB - always 6 so, zeroed buffer[index++] = 6; // Length LSB buffer[index++] = (byte)'M'; // M buffer[index++] = (byte)'Q'; // Q buffer[index++] = (byte)'I'; // I buffer[index++] = (byte)'s'; // s buffer[index++] = (byte)'d'; // d buffer[index++] = (byte)'p'; // p // Protocol Version buffer[index++] = Constants.MQTTPROTOCOLVERSION; // Connect Flags // TODO: re-read the spec to figure out what the "will" stuff is about if (cleanSession) connectFlags |= (byte)Constants.CLEAN_SESSION_FLAG; if (usingUsername) connectFlags |= (byte)Constants.USING_USERNAME_FLAG; if (usingPassword) connectFlags |= (byte)Constants.USING_PASSWORD_FLAG; // Set the connect flags buffer[index++] = connectFlags; // Keep alive (defaulted to 20 seconds above) buffer[index++] = (byte)(keepAlive / 256); // Keep Alive MSB buffer[index++] = (byte)(keepAlive % 256); // Keep Alive LSB // ClientID buffer[index++] = (byte)(utf8ClientID.Length / 256); // Length MSB buffer[index++] = (byte)(utf8ClientID.Length % 256); // Length LSB for (var i = 0; i < utf8ClientID.Length; i++) { buffer[index++] = utf8ClientID[i]; } // Username if (usingUsername) { buffer[index++] = (byte)(utf8Username.Length / 256); // Length MSB buffer[index++] = (byte)(utf8Username.Length % 256); // Length LSB for (var i = 0; i < utf8Username.Length; i++) { buffer[index++] = utf8Username[i]; } } // Password if (usingPassword) { buffer[index++] = (byte)(utf8Password.Length / 256); // Length MSB buffer[index++] = (byte)(utf8Password.Length % 256); // Length LSB for (var i = 0; i < utf8Password.Length; i++) { buffer[index++] = utf8Password[i]; } } // Send the message returnCode = mySocket.Send(buffer, index, 0); // The return code should equal our buffer length if (returnCode != buffer.Length) { return Constants.CONNECTION_ERROR; } // Get the acknowledgement message returnCode = mySocket.Receive(buffer, 0); // The length should equal 4 if (returnCode != Constants.CONNACK_LENGTH) { return Constants.CONNECTION_ERROR; } // This should be a message type 2 (CONNACK) if (buffer[0] == Constants.MQTT_CONNACK_TYPE) { // This is our return code from the server return buffer[3]; } // If not zero = return the return code return Constants.CONNECTION_ERROR; } // Publish a message to a broker (3.3) public static int PublishMQTT(Socket mySocket, String topic, String message) { int index = 0; int digit = 0; int tmp = 0; int fixedHeader = 0; int varHeader = 0; int payload = 0; int remainingLength = 0; byte[] buffer = null; UTF8Encoding encoder = new UTF8Encoding(); byte[] utf8Topic = Encoding.UTF8.GetBytes(topic); // Some error checking // Topic contains wildcards if ((topic.IndexOf('#') != -1) || (topic.IndexOf('+') != -1)) return Constants.TOPIC_WILDCARD_ERROR; // Topic is too long or short if ((utf8Topic.Length > Constants.MAX_TOPIC_LENGTH) || (utf8Topic.Length < Constants.MIN_TOPIC_LENGTH)) return Constants.TOPIC_LENGTH_ERROR; // Calculate the size of the var header varHeader += 2; // Topic Name Length varHeader += utf8Topic.Length; // Topic Name // Calculate the size of the fixed header fixedHeader++; // byte 1 // Calculate the payload payload = message.Length; // Calculate the remaining size remainingLength = varHeader + payload; // Check that remaining length will fit into 4 encoded bytes if (remainingLength > Constants.MAXLENGTH) return Constants.MESSAGE_LENGTH_ERROR; // Add space for each byte we need in the fixed header to store the length tmp = remainingLength; while (tmp > 0) { fixedHeader++; tmp = tmp / 128; }; // End of Fixed Header // Build buffer for message buffer = new byte[fixedHeader + varHeader + payload]; // Start of Fixed header // Publish (3.3) buffer[index++] = Constants.MQTT_PUBLISH_TYPE; // Encode the fixed header remaining length tmp = remainingLength; do { digit = tmp % 128; tmp = tmp / 128; if (tmp > 0) { digit = digit | 0x80; } buffer[index++] = (byte)digit; } while (tmp > 0); // End of fixed header // Start of Variable header // Length of topic name buffer[index++] = (byte)(utf8Topic.Length / 256); // Length MSB buffer[index++] = (byte)(utf8Topic.Length % 256); // Length LSB // Topic for (var i = 0; i < utf8Topic.Length; i++) { buffer[index++] = utf8Topic[i]; } // End of variable header // Start of Payload // Message (Length is accounted for in the fixed header) for (var i = 0; i < message.Length; i++) { buffer[index++] = (byte)message[i]; } // End of Payload return mySocket.Send(buffer, buffer.Length, 0); } // Disconnect from broker (3.14) public static int DisconnectMQTT(Socket mySocket) { byte[] buffer = null; buffer = new byte[2]; buffer[0] = Constants.MQTT_DISCONNECT_TYPE; buffer[1] = 0x00; return mySocket.Send(buffer, buffer.Length, 0); } // Ping the MQTT broker - used to extend keep alive public static int PingMQTT(Socket mySocket) { int index = 0; int returnCode = 0; byte[] buffer = null; buffer = new byte[2]; buffer[index++] = Constants.MQTT_PING_REQ_TYPE; buffer[index++] = 0x00; // Send the ping returnCode = mySocket.Send(buffer, index, 0); // The return code should equal our buffer length if (returnCode != buffer.Length) { return Constants.CONNECTION_ERROR; } // Get the acknowledgement message returnCode = mySocket.Receive(buffer, 0); // The length should equal 2 if (returnCode != Constants.PINGRESP_LENGTH) { return Constants.CONNECTION_ERROR; } // This should be a message type 2 (CONNACK) if (buffer[0] == Constants.MQTT_PING_RESP_TYPE) { return 0; } return Constants.CONNECTION_ERROR; } } } Program.cs /* Copyright 2011-2012 Dan Anderson. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY DAN ANDERSON ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Dan Anderson OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Net; using System.Net.Sockets; using System.Threading; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.Hardware; using SecretLabs.NETMF.Hardware.NetduinoPlus; using Netduino_MQTT_Client_Library; namespace myNetduinoMQTT { public class Program { public static void Main() { // setup our interrupt port (on-board button) InterruptPort button = new InterruptPort(Pins.ONBOARD_SW1, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow); // assign our interrupt handler button.OnInterrupt += new NativeEventHandler(button_OnInterrupt); // go to sleep until the interrupt wakes us (saves power) Thread.Sleep(Timeout.Infinite); } // the interrupt handler static void button_OnInterrupt(uint data1, uint data2, DateTime time) { int returnCode = 0; int connectionError = 0; // Get broker's IP address. IPHostEntry hostEntry = Dns.GetHostEntry("192.168.1.106"); // Create socket and connect to the broker's IP address and port Socket mySocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp); try { mySocket.Connect(new IPEndPoint(hostEntry.AddressList[0], 1883)); } catch (SocketException SE) { Debug.Print("Connection Error"); connectionError = 1; } if (connectionError != 1) { // Send the connect message returnCode = NetduinoMQTT.ConnectMQTT(mySocket, "tester\u00A5", 2, true, "roger\u00A5", "password\u00A5"); if (returnCode != 0) { Debug.Print("Connection Error:"); Debug.Print(returnCode.ToString()); } else { // Send our message NetduinoMQTT.PublishMQTT(mySocket, "test", "Ow! Quit it!"); for (int i = 0; i < 11; i++) { returnCode = NetduinoMQTT.PingMQTT(mySocket); if (returnCode == 0) { Debug.Print("Ping Received"); Thread.Sleep(1000); } } Thread.Sleep(3000); // Send the disconnect message NetduinoMQTT.DisconnectMQTT(mySocket); } // Close the socket mySocket.Close(); } } } } 版本 0.02 支持: 包括版本 0.01(a) 的所有功能 订阅和取消订阅 客户端将响应代理服务器的PING请求 为了避免占用过多内存,各个字段的大小已经被任意缩短。 NetduinoMQTT.cs /* Copyright 2011-2012 Dan Anderson. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY DAN ANDERSON ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAN ANDERSON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Net; using System.Net.Sockets; using System.Text; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using Socket = System.Net.Sockets.Socket; namespace Netduino_MQTT_Client_Library { static class Constants { // These have been scaled down to the hardware // Maximum values are commented out - you can // adjust, but keep in mind the limits of the hardware public const int MQTTPROTOCOLVERSION = 3; //public const int MAXLENGTH = 268435455; // 256MB public const int MAXLENGTH = 10240; // 10K public const int MAX_CLIENTID = 23; public const int MIN_CLIENTID = 1; public const int MAX_KEEPALIVE = 65535; public const int MIN_KEEPALIVE = 0; //public const int MAX_USERNAME = 65535; //public const int MAX_PASSWORD = 65535; public const int MAX_USERNAME = 12; public const int MAX_PASSWORD = 12; //public const int MAX_TOPIC_LENGTH = 32767; public const int MAX_TOPIC_LENGTH = 256; public const int MIN_TOPIC_LENGTH = 1; public const int MAX_MESSAGEID = 65535; // Error Codes public const int CLIENTID_LENGTH_ERROR = 1; public const int KEEPALIVE_LENGTH_ERROR = 1; public const int MESSAGE_LENGTH_ERROR = 1; public const int TOPIC_LENGTH_ERROR = 1; public const int TOPIC_WILDCARD_ERROR = 1; public const int USERNAME_LENGTH_ERROR = 1; public const int PASSWORD_LENGTH_ERROR = 1; public const int CONNECTION_ERROR = 1; public const int ERROR = 1; public const int SUCCESS = 0; public const int CONNECTION_OK = 0; public const int CONNACK_LENGTH = 4; public const int PINGRESP_LENGTH = 2; public const byte MQTT_CONN_OK = 0x00; // Connection Accepted public const byte MQTT_CONN_BAD_PROTOCOL_VERSION = 0x01; // Connection Refused: unacceptable protocol version public const byte MQTT_CONN_BAD_IDENTIFIER = 0x02; // Connection Refused: identifier rejected public const byte MQTT_CONN_SERVER_UNAVAILABLE = 0x03; // Connection Refused: server unavailable public const byte MQTT_CONN_BAD_AUTH = 0x04; // Connection Refused: bad user name or password public const byte MQTT_CONN_NOT_AUTH = 0x05; // Connection Refused: not authorized // Message types public const byte MQTT_CONNECT_TYPE = 0x10; public const byte MQTT_CONNACK_TYPE = 0x20; public const byte MQTT_PUBLISH_TYPE = 0x30; public const byte MQTT_PING_REQ_TYPE = 0xc0; public const byte MQTT_PING_RESP_TYPE = 0xd0; public const byte MQTT_DISCONNECT_TYPE = 0xe0; public const byte MQTT_SUBSCRIBE_TYPE = 0x82; public const byte MQTT_UNSUBSCRIBE_TYPE = 0xa2; // Flags public const int CLEAN_SESSION_FLAG = 0x02; public const int USING_USERNAME_FLAG = 0x80; public const int USING_PASSWORD_FLAG = 0x40; public const int CONTINUATION_BIT = 0x80; } public static class NetduinoMQTT { // Setup our random number generator private static Random rand = new Random((int)(Utility.GetMachineTime().Ticks & 0xffffffff)); //*************************************************************** // Send Messages //*************************************************************** // Connect to the MQTT Server public static int ConnectMQTT(Socket mySocket, String clientID, int keepAlive = 20, bool cleanSession = true, String username = "", String password = "") { int index = 0; int tmp = 0; int remainingLength = 0; int fixedHeader = 0; int varHeader = 0; int payload = 0; int returnCode = 0; bool usingUsername = false; bool usingPassword = false; byte connectFlags = 0x00; byte[] buffer = null; byte[] inputBuffer = new byte[1]; byte firstByte = 0x00; UTF8Encoding encoder = new UTF8Encoding(); byte[] utf8ClientID = Encoding.UTF8.GetBytes(clientID); byte[] utf8Username = Encoding.UTF8.GetBytes(username); byte[] utf8Password = Encoding.UTF8.GetBytes(password); // Some Error Checking // ClientID improperly sized if ((utf8ClientID.Length > Constants.MAX_CLIENTID) || (utf8ClientID.Length < Constants.MIN_CLIENTID)) return Constants.CLIENTID_LENGTH_ERROR; // KeepAlive out of bounds if ((keepAlive > Constants.MAX_KEEPALIVE) || (keepAlive < Constants.MIN_KEEPALIVE)) return Constants.KEEPALIVE_LENGTH_ERROR; // Username too long if (utf8Username.Length > Constants.MAX_USERNAME) return Constants.USERNAME_LENGTH_ERROR; // Password too long if (utf8Password.Length > Constants.MAX_PASSWORD) return Constants.PASSWORD_LENGTH_ERROR; // Check features being used if (!username.Equals("")) usingUsername = true; if (!password.Equals("")) usingPassword = true; // Calculate the size of the var header varHeader += 2; // Protocol Name Length varHeader += 6; // Protocol Name varHeader++; // Protocol version varHeader++; // Connect Flags varHeader += 2; // Keep Alive // Calculate the size of the fixed header fixedHeader++; // byte 1 // Calculate the payload payload = utf8ClientID.Length + 2; if (usingUsername) { payload += utf8Username.Length + 2; } if (usingPassword) { payload += utf8Password.Length + 2; } // Calculate the remaining size remainingLength = varHeader + payload; // Check that remaining length will fit into 4 encoded bytes if (remainingLength > Constants.MAXLENGTH) return Constants.MESSAGE_LENGTH_ERROR; tmp = remainingLength; // Add space for each byte we need in the fixed header to store the length while (tmp > 0) { fixedHeader++; tmp = tmp / 128; }; // End of Fixed Header // Build buffer for message buffer = new byte[fixedHeader + varHeader + payload]; // Fixed Header (2.1) buffer[index++] = Constants.MQTT_CONNECT_TYPE; // Encode the fixed header remaining length // Add remaining length index = doRemainingLength(remainingLength, index, buffer); // End Fixed Header // Connect (3.1) // Protocol Name buffer[index++] = 0; // String (MQIsdp) Length MSB - always 6 so, zeroed buffer[index++] = 6; // Length LSB buffer[index++] = (byte)'M'; // M buffer[index++] = (byte)'Q'; // Q buffer[index++] = (byte)'I'; // I buffer[index++] = (byte)'s'; // s buffer[index++] = (byte)'d'; // d buffer[index++] = (byte)'p'; // p // Protocol Version buffer[index++] = Constants.MQTTPROTOCOLVERSION; // Connect Flags if (cleanSession) connectFlags |= (byte)Constants.CLEAN_SESSION_FLAG; if (usingUsername) connectFlags |= (byte)Constants.USING_USERNAME_FLAG; if (usingPassword) connectFlags |= (byte)Constants.USING_PASSWORD_FLAG; // Set the connect flags buffer[index++] = connectFlags; // Keep alive (defaulted to 20 seconds above) buffer[index++] = (byte)(keepAlive / 256); // Keep Alive MSB buffer[index++] = (byte)(keepAlive % 256); // Keep Alive LSB // ClientID buffer[index++] = (byte)(utf8ClientID.Length / 256); // Length MSB buffer[index++] = (byte)(utf8ClientID.Length % 256); // Length LSB for (var i = 0; i < utf8ClientID.Length; i++) { buffer[index++] = utf8ClientID[i]; } // Username if (usingUsername) { buffer[index++] = (byte)(utf8Username.Length / 256); // Length MSB buffer[index++] = (byte)(utf8Username.Length % 256); // Length LSB for (var i = 0; i < utf8Username.Length; i++) { buffer[index++] = utf8Username[i]; } } // Password if (usingPassword) { buffer[index++] = (byte)(utf8Password.Length / 256); // Length MSB buffer[index++] = (byte)(utf8Password.Length % 256); // Length LSB for (var i = 0; i < utf8Password.Length; i++) { buffer[index++] = utf8Password[i]; } } // Send the message returnCode = mySocket.Send(buffer, index, 0); // The return code should equal our buffer length if (returnCode != buffer.Length) { return Constants.CONNECTION_ERROR; } // Get the acknowledgement message returnCode = mySocket.Receive(inputBuffer, 0); if (returnCode < 1) return Constants.CONNECTION_ERROR; firstByte = inputBuffer[0]; // If this is the CONNACK - pass it to the CONNACK handler if (((int)firstByte & Constants.MQTT_CONNACK_TYPE) > 0) { returnCode = handleCONNACK(mySocket, firstByte); if (returnCode > 0) { return Constants.ERROR; } } return Constants.SUCCESS; } // Publish a message to a broker (3.3) public static int PublishMQTT(Socket mySocket, String topic, String message) { int index = 0; int tmp = 0; int fixedHeader = 0; int varHeader = 0; int payload = 0; int remainingLength = 0; int returnCode = 0; byte[] buffer = null; // Setup a UTF8 encoder UTF8Encoding encoder = new UTF8Encoding(); // Encode the topic byte[] utf8Topic = Encoding.UTF8.GetBytes(topic); // Some error checking // Topic contains wildcards if ((topic.IndexOf('#') != -1) || (topic.IndexOf('+') != -1)) return Constants.TOPIC_WILDCARD_ERROR; // Topic is too long or short if ((utf8Topic.Length > Constants.MAX_TOPIC_LENGTH) || (utf8Topic.Length < Constants.MIN_TOPIC_LENGTH)) return Constants.TOPIC_LENGTH_ERROR; // Calculate the size of the var header varHeader += 2; // Topic Name Length (MSB, LSB) varHeader += utf8Topic.Length; // Length of the topic // Calculate the size of the fixed header fixedHeader++; // byte 1 // Calculate the payload payload = message.Length; // Calculate the remaining size remainingLength = varHeader + payload; // Check that remaining length will fit into 4 encoded bytes if (remainingLength > Constants.MAXLENGTH) return Constants.MESSAGE_LENGTH_ERROR; // Add space for each byte we need in the fixed header to store the length tmp = remainingLength; while (tmp > 0) { fixedHeader++; tmp = tmp / 128; }; // End of Fixed Header // Build buffer for message buffer = new byte[fixedHeader + varHeader + payload]; // Start of Fixed header // Publish (3.3) buffer[index++] = Constants.MQTT_PUBLISH_TYPE; // Encode the fixed header remaining length // Add remaining length index = doRemainingLength(remainingLength, index, buffer); // End Fixed Header // Start of Variable header // Length of topic name buffer[index++] = (byte)(utf8Topic.Length / 256); // Length MSB buffer[index++] = (byte)(utf8Topic.Length % 256); // Length LSB // Topic for (var i = 0; i < utf8Topic.Length; i++) { buffer[index++] = utf8Topic[i]; } // End of variable header // Start of Payload // Message (Length is accounted for in the fixed header) for (var i = 0; i < message.Length; i++) { buffer[index++] = (byte)message[i]; } // End of Payload returnCode = mySocket.Send(buffer, buffer.Length, 0); if (returnCode < buffer.Length) return Constants.CONNECTION_ERROR; return Constants.SUCCESS; } // Disconnect from broker (3.14) public static int DisconnectMQTT(Socket mySocket) { byte[] buffer = null; int returnCode = 0; buffer = new byte[2]; buffer[0] = Constants.MQTT_DISCONNECT_TYPE; buffer[1] = 0x00; returnCode = mySocket.Send(buffer, buffer.Length, 0); if (returnCode < buffer.Length) return Constants.CONNECTION_ERROR; return Constants.SUCCESS; ; } // Subscribe to a topic public static int SubscribeMQTT(Socket mySocket, String[] topic, int[] QoS, int topics) { int index = 0; int index2 = 0; int messageIndex = 0; int messageID = 0; int tmp = 0; int fixedHeader = 0; int varHeader = 0; int payloadLength = 0; int remainingLength = 0; int returnCode = 0; byte[] buffer = null; byte[][] utf8Topics = null; UTF8Encoding encoder = new UTF8Encoding(); utf8Topics = new byte[topics][]; while (index < topics) { utf8Topics[index] = new byte[Encoding.UTF8.GetBytes(topic[index]).Length]; utf8Topics[index] = Encoding.UTF8.GetBytes(topic[index]); if ((utf8Topics[index].Length > Constants.MAX_TOPIC_LENGTH) || (utf8Topics[index].Length < Constants.MIN_TOPIC_LENGTH)) { return Constants.TOPIC_LENGTH_ERROR; } else { payloadLength += 2; // Size (LSB + MSB) payloadLength += utf8Topics[index].Length; // Length of topic payloadLength++; // QoS Requested index++; } } // Calculate the size of the fixed header fixedHeader++; // byte 1 // Calculate the size of the var header varHeader += 2; // Message ID is 2 bytes // Calculate the remaining size remainingLength = varHeader + payloadLength; // Check that remaining encoded length will fit into 4 encoded bytes if (remainingLength > Constants.MAXLENGTH) return Constants.MESSAGE_LENGTH_ERROR; // Add space for each byte we need in the fixed header to store the length tmp = remainingLength; while (tmp > 0) { fixedHeader++; tmp = tmp / 128; }; // Build buffer for message buffer = new byte[fixedHeader + varHeader + payloadLength]; // Start of Fixed header // Publish (3.3) buffer[messageIndex++] = Constants.MQTT_SUBSCRIBE_TYPE; // Add remaining length messageIndex = doRemainingLength(remainingLength, messageIndex, buffer); // End Fixed Header // Start of Variable header // Message ID messageID = rand.Next(Constants.MAX_MESSAGEID); Debug.Print("SUBSCRIBE: Message ID: " + messageID); buffer[messageIndex++] = (byte)(messageID / 256); // Length MSB buffer[messageIndex++] = (byte)(messageID % 256); // Length LSB // End of variable header // Start of Payload index = 0; while (index < topics) { // Length of Topic buffer[messageIndex++] = (byte)(utf8Topics[index].Length / 256); // Length MSB buffer[messageIndex++] = (byte)(utf8Topics[index].Length % 256); // Length LSB index2 = 0; while (index2 < utf8Topics[index].Length) { buffer[messageIndex++] = utf8Topics[index][index2]; index2++; } buffer[messageIndex++] = (byte)(QoS[index]); index++; } // End of Payload returnCode = mySocket.Send(buffer, buffer.Length, 0); if (returnCode < buffer.Length) return Constants.CONNECTION_ERROR; return Constants.SUCCESS; } // Unsubscribe to a topic public static int UnsubscribeMQTT(Socket mySocket, String[] topic, int[] QoS, int topics) { int index = 0; int index2 = 0; int messageIndex = 0; int messageID = 0; int tmp = 0; int fixedHeader = 0; int varHeader = 0; int payloadLength = 0; int remainingLength = 0; int returnCode = 0; byte[] buffer = null; byte[][] utf8Topics = null; UTF8Encoding encoder = new UTF8Encoding(); utf8Topics = new byte[topics][]; while (index < topics) { utf8Topics[index] = new byte[Encoding.UTF8.GetBytes(topic[index]).Length]; utf8Topics[index] = Encoding.UTF8.GetBytes(topic[index]); if ((utf8Topics[index].Length > Constants.MAX_TOPIC_LENGTH) || (utf8Topics[index].Length < Constants.MIN_TOPIC_LENGTH)) { return Constants.TOPIC_LENGTH_ERROR; } else { payloadLength += 2; // Size (LSB + MSB) payloadLength += utf8Topics[index].Length; // Length of topic index++; } } // Calculate the size of the fixed header fixedHeader++; // byte 1 // Calculate the size of the var header varHeader += 2; // Message ID is 2 bytes // Calculate the remaining size remainingLength = varHeader + payloadLength; // Check that remaining encoded length will fit into 4 encoded bytes if (remainingLength > Constants.MAXLENGTH) return Constants.MESSAGE_LENGTH_ERROR; // Add space for each byte we need in the fixed header to store the length tmp = remainingLength; while (tmp > 0) { fixedHeader++; tmp = tmp / 128; }; // Build buffer for message buffer = new byte[fixedHeader + varHeader + payloadLength]; // Start of Fixed header // Publish (3.3) buffer[messageIndex++] = Constants.MQTT_UNSUBSCRIBE_TYPE; // Add remaining length - writes to buffer, so need to get the new index back messageIndex = doRemainingLength(remainingLength, messageIndex, buffer); // End Fixed Header // Start of Variable header // Message ID messageID = rand.Next(Constants.MAX_MESSAGEID); Debug.Print("UNSUBSCRIBE: Message ID: " + messageID); buffer[messageIndex++] = (byte)(messageID / 256); // Length MSB buffer[messageIndex++] = (byte)(messageID % 256); // Length LSB // End of variable header // Start of Payload index = 0; while (index < topics) { // Length of Topic buffer[messageIndex++] = (byte)(utf8Topics[index].Length / 256); // Length MSB buffer[messageIndex++] = (byte)(utf8Topics[index].Length % 256); // Length LSB index2 = 0; while (index2 < utf8Topics[index].Length) { buffer[messageIndex++] = utf8Topics[index][index2]; index2++; } index++; } // End of Payload returnCode = mySocket.Send(buffer, buffer.Length, 0); if (returnCode < buffer.Length) return Constants.CONNECTION_ERROR; return Constants.SUCCESS; } // Respond to a PINGRESP public static int sendPINGRESP(Socket mySocket) { int index = 0; int returnCode = 0; byte[] buffer = new byte[2]; buffer[index++] = Constants.MQTT_PING_RESP_TYPE; buffer[index++] = 0x00; // Send the ping returnCode = mySocket.Send(buffer, index, 0); // The return code should equal our buffer length if (returnCode != buffer.Length) { return Constants.CONNECTION_ERROR; } return Constants.SUCCESS; } // Ping the MQTT broker - used to extend keep alive public static int PingMQTT(Socket mySocket) { int index = 0; int returnCode = 0; byte[] buffer = new byte[2]; buffer[index++] = Constants.MQTT_PING_REQ_TYPE; buffer[index++] = 0x00; // Send the ping returnCode = mySocket.Send(buffer, index, 0); // The return code should equal our buffer length if (returnCode != buffer.Length) { return Constants.CONNECTION_ERROR; } return Constants.SUCCESS; } //*************************************************************** // Utility Functions //*************************************************************** // Append the remaining length field for the fixed header public static int doRemainingLength(int remainingLength, int index, byte[] buffer) { int digit = 0; do { digit = remainingLength % 128; remainingLength /= 128; if (remainingLength > 0) { digit = digit | Constants.CONTINUATION_BIT; } buffer[index++] = (byte)digit; } while (remainingLength > 0); return index; } // Extract the remaining length field from the fixed header public static int undoRemainingLength(Socket mySocket) { int multiplier = 1; int count = 0; int digit = 0; int remainingLength = 0; byte[] nextByte = new byte[1]; do { if (mySocket.Receive(nextByte, 0) == 1) { digit = (byte)nextByte[0]; remainingLength += ((digit & 0x7F) * multiplier); multiplier *= 128; } count++; } while (((digit & 0x80) != 0) && count <4); return remainingLength; } //*************************************************************** // Main Listener loop //*************************************************************** // Listen for data on the socket - call appropriate handlers based on first byte public static int listen(Socket mySocket) { int returnCode = 0; byte first = 0x00; byte[] buffer = new byte[1]; while (true) { returnCode = mySocket.Receive(buffer, 0); if (returnCode > 0) { Debug.Print("Data Received"); first = buffer[0]; switch (first >> 4) { case 0: // Reserved Debug.Print("First Reserved Message received"); returnCode = Constants.ERROR; break; case 1: // Connect (Broker Only) Debug.Print("CONNECT Message received"); returnCode = Constants.ERROR; break; case 2: // CONNACK Debug.Print("CONNACK Message received"); returnCode = handleCONNACK(mySocket, first); break; case 3: // PUBLISH Debug.Print("PUBLISH Message received"); returnCode = handlePUBLISH(mySocket, first); break; case 4: // PUBACK (QoS > 0 - did it anyway) Debug.Print("PUBACK Message received"); returnCode = handlePUBACK(mySocket, first); break; case 5: // PUBREC (QoS 2) Debug.Print("PUBREC Message received"); returnCode = Constants.ERROR; break; case 6: // PUBREL (QoS 2) Debug.Print("PUBREL Message received"); returnCode = Constants.ERROR; break; case 7: // PUBCOMP (QoS 2) Debug.Print("PUBCOMP Message received"); returnCode = Constants.ERROR; break; case 8: // SUBSCRIBE (Broker only) Debug.Print("SUBSCRIBE Message received"); returnCode = Constants.ERROR; break; case 9: // SUBACK Debug.Print("SUBACK Message received"); returnCode = handleSUBACK(mySocket, first); break; case 10: // UNSUBSCRIBE (Broker Only) Debug.Print("UNSUBSCRIBE Message received"); returnCode = Constants.ERROR; break; case 11: // UNSUBACK Debug.Print("UNSUBACK Message received"); returnCode = handleUNSUBACK(mySocket, first); break; case 12: // PINGREQ (Technically a Broker Deal - but we're doing it anyway) Debug.Print("PINGREQ Message received"); returnCode = handlePINGREQ(mySocket, first); break; case 13: // PINGRESP Debug.Print("PINGRESP Message received"); returnCode = handlePINGRESP(mySocket, first); break; case 14: // DISCONNECT (Broker Only) Debug.Print("DISCONNECT Message received"); returnCode = Constants.ERROR; break; case 15: // Reserved Debug.Print("Last Reserved Message received"); returnCode = Constants.ERROR; break; default: // Default action Debug.Print("Unknown Message received"); // Should never get here returnCode = Constants.ERROR; break; } if (returnCode != Constants.SUCCESS) { Debug.Print("An error occurred in message processing"); } } } } //*************************************************************** // Message handlers (received) //*************************************************************** public static int handleSUBACK(Socket mySocket, byte firstByte) { int remainingLength = 0; int messageID = 0; int index = 0; int QoSIndex = 0; int[] QoS = null; byte[] buffer = null; remainingLength = undoRemainingLength(mySocket); buffer = new byte[remainingLength]; if ((mySocket.Receive(buffer, 0) != remainingLength) || remainingLength < 3) return Constants.ERROR; messageID += buffer[index++] * 256; messageID += buffer[index++]; Debug.Print("SUBACK: Message ID: " + messageID); do { QoS = new int[remainingLength - 2]; QoS[QoSIndex++] = buffer[index++]; Debug.Print("SUBACK: QoS Granted: " + QoS[QoSIndex-1]); } while(index < remainingLength); return Constants.SUCCESS; } // Messages from the broker come back to us as publish messages public static int handlePUBLISH(Socket mySocket, byte firstByte) { int remainingLength = 0; int messageID = 0; int topicLength = 0; int topicIndex = 0; int payloadIndex = 0; int index = 0; byte[] buffer = null; byte[] topic = null; byte[] payload = null; int QoS = 0x00; String topicString = null; String payloadString = null; remainingLength = undoRemainingLength(mySocket); buffer = new byte[remainingLength]; if ((mySocket.Receive(buffer, 0) != remainingLength) || remainingLength < 5) return Constants.ERROR; topicLength += buffer[index++] * 256; topicLength += buffer[index++]; topic = new byte[topicLength]; while (topicIndex < topicLength) { topic[topicIndex++] = buffer[index++]; } QoS = firstByte & 0x06; if (QoS > 0) { messageID += buffer[index++] * 256; messageID += buffer[index++]; Debug.Print("PUBLISH: Message ID: " + messageID); } topicString = new String(Encoding.UTF8.GetChars(topic)); Debug.Print("PUBLISH: Topic: " + topicString); payload = new byte[remainingLength - index]; while (index < remainingLength) { payload[payloadIndex++] = buffer[index++]; } Debug.Print("PUBLISH: Payload Length: " + payload.Length); // This doesn't work if the payload isn't UTF8 payloadString = new String(Encoding.UTF8.GetChars(payload)); Debug.Print("PUBLISH: Payload: " + payloadString); return Constants.SUCCESS; } public static int handleUNSUBACK(Socket mySocket, byte firstByte) { int returnCode = 0; int messageID = 0; byte[] buffer = new byte[3]; returnCode = mySocket.Receive(buffer, 0); if ((buffer[0] != 2) || (returnCode != 3)) return Constants.ERROR; messageID += buffer[1] * 256; messageID += buffer[2]; Debug.Print("UNSUBACK: Message ID: " + messageID); return Constants.SUCCESS; } // Ping response - this should be a total of 2 bytes - that's pretty much // all I'm looking for. public static int handlePINGRESP(Socket mySocket, byte firstByte) { int returnCode = 0; Debug.Print("Ping Response Received"); byte[] buffer = new byte[1]; returnCode = mySocket.Receive(buffer, 0); if ((buffer[0] != 0) || (returnCode != 1)) { return Constants.ERROR; } return Constants.SUCCESS; } // Ping Request public static int handlePINGREQ(Socket mySocket, byte firstByte) { int returnCode = 0; byte[] buffer = new byte[1]; returnCode = mySocket.Receive(buffer, 0); if((returnCode != 1) || (buffer[0] != 0)) return Constants.ERROR; returnCode = sendPINGRESP(mySocket); if (returnCode != 0) return Constants.ERROR; return Constants.SUCCESS; } // Connect acknowledgement - returns 3 more bytes, byte 3 // should be 0 for success public static int handleCONNACK(Socket mySocket, byte firstByte) { int returnCode = 0; byte[] buffer = new byte[3]; returnCode = mySocket.Receive(buffer, 0); if ((buffer[0] != 2) || (buffer[2] > 0) || (returnCode != 3)) return Constants.ERROR; return Constants.SUCCESS; } // We're not doing QoS 1 yet, so this is just here for flushing // and to notice if we are getting this message for some reason public static int handlePUBACK(Socket mySocket, byte firstByte) { int returnCode = 0; int messageID = 0; byte[] buffer = new byte[3]; returnCode = mySocket.Receive(buffer, 0); if ((buffer[0] != 2) || (returnCode != 3)) return Constants.ERROR; messageID += buffer[1] * 256; messageID += buffer[2]; Debug.Print("PUBACK: Message ID: " + messageID); return Constants.SUCCESS; } } } Program.cs /* Copyright 2011-2012 Dan Anderson. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY DAN ANDERSON ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAN ANDERSON OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Net; using System.Net.Sockets; using System.Threading; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.Hardware; using SecretLabs.NETMF.Hardware.NetduinoPlus; using Netduino_MQTT_Client_Library; namespace myNetduinoMQTT { public class Program { static Thread listenerThread; static Socket mySocket = null; public static void Main() { int returnCode = 0; // You can subscribe to multiple topics in one go // (If your broker supports this RSMB does, mosquitto does not) // Our examples use one topic per request. // //int[] topicQoS = { 0, 0 }; //String[] subTopics = { "test", "test2" }; //int numTopics = 2; int[] topicQoS = { 0 }; String[] subTopics = { "test" }; int numTopics = 1; // Get broker's IP address. //IPHostEntry hostEntry = Dns.GetHostEntry("test.mosquitto.org"); IPHostEntry hostEntry = Dns.GetHostEntry("192.168.1.106"); // Create socket and connect to the broker's IP address and port mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { mySocket.Connect(new IPEndPoint(hostEntry.AddressList[0], 1883)); } catch (SocketException SE) { Debug.Print("Connection Error: " + SE.ErrorCode); return; } // Send the connect message // You can use UTF8 in the clientid, username and password - be careful, this can be a pain //returnCode = NetduinoMQTT.ConnectMQTT(mySocket, "tester\u00A5", 2000, true, "roger\u00A5", "password\u00A5"); returnCode = NetduinoMQTT.ConnectMQTT(mySocket, "tester402", 20, true, "roger", "password"); if (returnCode != 0) { Debug.Print("Connection Error: " + returnCode.ToString()); return; } // Set up so that we ping the server after 1 second, then every 10 seconds // First time is initial delay, Second is subsequent delays Timer pingTimer = new Timer(new TimerCallback(pingIt), null, 1000, 10000); // Setup and start a new thread for the listener listenerThread = new Thread(mylistenerThread); listenerThread.Start(); // setup our interrupt port (on-board button) InterruptPort button = new InterruptPort(Pins.ONBOARD_SW1, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeLow); // assign our interrupt handler button.OnInterrupt += new NativeEventHandler(button_OnInterrupt); // Subscribe to our topic(s) returnCode = NetduinoMQTT.SubscribeMQTT(mySocket, subTopics, topicQoS, numTopics); //*********************************************** // This is just some example stuff: //*********************************************** // Publish a message NetduinoMQTT.PublishMQTT(mySocket, "test", "Testing from NetduinoMQTT"); // Subscribe to "test/two" subTopics[0] = "test/two"; returnCode = NetduinoMQTT.SubscribeMQTT(mySocket, subTopics, topicQoS, numTopics); // Send a message to "test/two" NetduinoMQTT.PublishMQTT(mySocket, "test/two", "Testing from NetduinoMQTT to test/two"); // Unsubscribe from "test/two" returnCode = NetduinoMQTT.UnsubscribeMQTT(mySocket, subTopics, topicQoS, numTopics); // go to sleep until the interrupt or the timer wakes us // (mylistenerThread is in a seperate thread that continues) Thread.Sleep(Timeout.Infinite); } // the interrupt handler for the button static void button_OnInterrupt(uint data1, uint data2, DateTime time) { // Send our message NetduinoMQTT.PublishMQTT(mySocket, "test", "Ow! Quit it!"); return; } // The thread that listens for inbound messages private static void mylistenerThread() { NetduinoMQTT.listen(mySocket); } // The function that the timer calls to ping the server // Our keep alive is 15 seconds - we ping again every 10. // So we should live forever. static void pingIt(object o) { Debug.Print("pingIT"); NetduinoMQTT.PingMQTT(mySocket); } } } --- ### 50. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 as3MQTT是一个纯ActionScript 3编写的库,用于实现MQTT(Message Queue Telemetry Transport)协议,这是一种用于发布/订阅消息的轻量级协议。下面是如何使用as3MQTT的概述以及获取更多信息的链接。 Gist 您可以在以下链接找到as3MQTT的示例代码和示例应用程序:as3MQTT Gist Maven Repository as3MQTT库也可以在Maven仓库中找到,您可以在以下链接中获取相关信息和库文件:as3MQTT Maven Repository ASDOC 如果您需要详细的文档和API参考,可以查看as3MQTT的ASDOC页面:as3MQTT ASDOC 概述 MQ Telemetry Transport (MQTT) 是一种基于经纪人的发布/订阅消息协议,旨在保持开放、简单、轻量和易于实现。MQTT的特点使其非常适合在资源受限的环境中使用,例如: 网络昂贵、带宽有限或不稳定的情况下。 在具有有限处理器或内存资源的嵌入式设备上运行。 该协议的特性包括: 发布/订阅消息模式,用于提供一对多的消息分发和应用程序解耦。 消息传输与负载内容无关。 使用TCP/IP提供基本的网络连接。 消息传递的三种服务质量(QoS)级别: QoS(0):"至多一次",消息根据底层TCP/IP网络的最佳努力进行传递。可能会发生消息丢失或重复。例如,环境传感器数据可以使用此级别,如果丢失个别读数,也没有关系,因为下一个读数很快就会发布。 QoS(1):"至少一次",确保消息到达,但可能会出现重复。 QoS(2):"仅一次",确保消息仅到达一次。例如,计费系统可以使用此级别,因为重复或丢失的消息可能导致错误的费用。 较小的传输开销(固定长度的标头仅为2字节),并将协议交换最小化以减少网络流量。 使用"遗嘱消息"功能通知感兴趣的方在客户端异常断开时。 链接和资源 以下是有关as3MQTT的其他链接和资源,可帮助您更深入地了解和使用这个库: MQTT V3.1 协议规范:MQTT V3.1 Protocol Specification MQTT V3.1 协议规范(PDF 版本):MQTT V3.1 Protocol Specification (PDF) MQTT 白皮书:MQTT White Papers 和 其他白皮书 Wiki 页面:as3MQTT Wiki 其他MQTT客户端库:其他MQTT客户端库 安装 安装 as3MQTT:首先,确保您已经从Maven Repository或GitHub上下载并安装了as3MQTT库。您可以将库文件导入到您的项目中。 创建一个ActionScript项目:在Flash Builder、FlashDevelop或其他ActionScript IDE中创建一个新项目。 导入MQTTClient_AS3类:在您的项目中导入MQTTClient_AS3类,这是as3MQTT的主要入口点。 编写连接到MQTT代理的代码:使用MQTTClient_AS3类创建一个MQTT客户端实例,并通过设置主机地址、端口和其他参数来连接到MQTT代理。例如: var mqttClient:MQTTClient_AS3 = new MQTTClient_AS3(); mqttClient.connect("mqtt.eclipse.org", 1883, "clientId"); 设置事件侦听器:为了处理MQTT客户端的连接和消息事件,您可以设置事件侦听器。例如,监听连接成功事件和消息到达事件: mqttClient.addEventListener(MQTTEvent.CONNECT, onConnect); mqttClient.addEventListener(MQTTEvent.MESSAGE, onMessage); private function onConnect(event:MQTTEvent):void { trace("Connected to MQTT Broker"); } private function onMessage(event:MQTTEvent):void { trace("Received MQTT Message: " + event.message.payload); } 发布和订阅消息:使用mqttClient对象来发布和订阅MQTT消息。例如: mqttClient.subscribe("topic/sample"); mqttClient.publish("topic/sample", "Hello, MQTT!"); 处理错误和关闭连接:确保您的代码能够处理连接错误和关闭事件,以提高鲁棒性。例如: mqttClient.addEventListener(MQTTEvent.ERROR, onError); mqttClient.addEventListener(MQTTEvent.CLOSE, onClose); private function onError(event:MQTTEvent):void { trace("MQTT Error: " + event.message); } private function onClose(event:MQTTEvent):void { trace("MQTT Connection Closed: " + event.message); } 测试您的应用程序:在本地或远程MQTT代理上测试您的应用程序,确保它能够正确连接并处理消息。 --- ### 51. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 "Ascoltatori" 是一个简单的发布/订阅库,支持以下代理/协议: Redis,由 @antirez 创建的键/值存储。 MongoDB,可扩展、高性能的文档型数据库。 Mosquitto 和所有 MQTT 协议的实现。 RabbitMQ 和所有 AMQP 协议的实现。 ZeroMQ,用于在 P2P 模式下使用 Ascoltatori。 QlobberFSQ,共享文件系统队列。 Apache Kafka,高吞吐量的分布式消息系统。 安装: 通过 npm 安装库: $ npm install ascoltatori --save 通过 Git 安装: $ git clone git://github.com/mcollina/ascoltatori.git $ cd ascoltatori $ npm install 入门示例(使用 Redis): Ascoltatori 专注于为所有支持的代理提供简单且统一的抽象。以下是一个使用 Redis 的简单示例: var ascoltatori = require('ascoltatori'); ascoltatori.build(function (err, ascoltatore) { // 订阅主题 ascoltatore.subscribe('hello', function() { console.log(arguments); // { '0': 'hello', '1': 'a message' } }); // 发布消息到主题 'hello' ascoltatore.publish('hello', 'a message', function() { console.log('message published'); }); }); 通配符支持: 所有 ascoltatori 都支持通配符的使用,因此应该在每个代理上都能正常工作。您可能会发现一些差异,如果是这种情况,请提交错误报告以便修复。 通配符 + 匹配精确一个单词: var ascoltatori = require('ascoltatori'); ascoltatori.build(function (err, ascoltatore) { ascoltatore.subscribe("hello/+/world", function() { // 这将打印 { '0': "hello/there/world", '1': "a message" } console.log(arguments); }); ascoltatore.subscribe("hello/+", function() { // 这不会被调用 console.log(arguments); }); ascoltatore.publish("hello/there/world", "a message", function() { console.log("message published"); }); }); 通配符 * 匹配零个或多个单词: var ascoltatori = require('ascoltatori'); ascoltatori.build(function (err, ascoltatore) { ascoltatore.subscribe("hello/*", function() { // 这将打印 { '0': "hello/there/world", '1': "a message" } console.log(arguments); }); ascoltatore.subscribe("*", function() { // 这将打印 { '0': "hello/there/world", '1': "a message" } console.log(arguments); }); ascoltatore.subscribe("hello/there/world/*", function() { // 这将打印 { '0': "hello/there/world", '1': "a message" } console.log(arguments); }); ascoltatore.publish("hello/there/world", "a message", function() { console.log("message published"); }); }); 当然,您可以在同一订阅中混合使用 * 和 +: var ascoltatori = require('ascoltatori'); ascoltatori.build(function (err, ascoltatore) { ascoltatore.subscribe("hello/+/world/*", function() { // 这将打印 { '0': "hello/foo/world/bar/42", '1': "a message" } console.log(arguments); }); ascoltatore.publish("hello/foo/world/bar/42", "a message", function() { console.log("message published"); }); }); 各代理示例: Ascoltatori 支持不同的代理。以下是如何使用每个代理的示例。 Redis: var ascoltatori = require('ascoltatori'); var settings = { type: 'redis', redis: require('redis'), db: 12, port: 6379, return_buffers: true, // 用于处理二进制数据 host: 'localhost' }; ascoltatori.build(settings, function (err, ascoltatore) { // ... }); MongoDB: MongoDB 使用 Capped Collections 来实现发布/订阅模式。 var ascoltatori = require('ascoltatori'); var settings = { type: 'mongo', url: 'mongodb://127.0.0.1/ascoltatori', pubsubCollection: 'ascoltatori', mongo: {} // MongoDB 特定选项 }; ascoltatori.build(settings, function (err, ascoltatore) { // ... }); 您还可以重用现有的 MongoDB 连接: var ascoltatori = require('ascoltatori'); var MongoClient = require('mongodb').MongoClient; MongoClient.connect('mongodb://127.0.0.1/ascoltatori', {}, function (err, db) { var settings = { type: 'mongo', db: db, pubsubCollection: 'ascoltatori' }; ascoltatori.build(settings, function (err, ascoltatore) { // ... }); }) MQTT(Mosquitto): var ascoltatori = require('ascoltatori'); var settings = { type: 'mqtt', json: false, mqtt: require('mqtt'), url: 'mqtt://127.0.0.1:1883' }; ascoltatori.build(settings, function (err, ascoltatore) { // ... }); AMQP(RabbitMQ): var ascoltatori = require('ascoltatori'); var settings = { type: 'amqp', json: false, amqp: require('amqp'), exchange: 'ascoltatore5672' }; ascoltatori.build(settings, function (err, ascoltatore) { // ... }); 使用 amqplib: var ascoltatori = require('ascoltatori'); var settings = { type: 'amqplib', json: false, amqp: require('amqplib/callback_api'), exchange: 'ascoltatore5672', queue: 'queueName', durableQueue: true }; ascoltatori.build(settings, function (err, ascoltatore) { // ... }); ZeroMQ: var ascoltatori = require('ascoltatori'); var settings = { type: 'zmq', json: false, zmq: require("zeromq"), port: "tcp://127.0.0.1:33333", controlPort: "tcp://127.0.0.1:33334", delay: 10 }; ascoltatori.build(settings, function (err, ascoltatore) { // ... }); QlobberFSQ: 您可以使用任何 QlobberFSQ 构造函数选项,例如: var ascoltatori = require('ascoltatori'); var settings = { type: 'filesystem', json: false, qlobber_fsq: require("qlobber-fsq"), fsq_dir: "/shared/fsq" }; ascoltatori.build(settings, function (err, ascoltatore) { // ... }); 如果不指定 fsq_dir,则消息将写入 qlobber-fsq 模块目录中名为 fsq 的目录中。 Memory: var ascoltatori = require('ascoltatori'); ascoltatori.build(function (err, ascoltatore) { // ... }); JSON: 默认情况下,由 ascoltatori.build 创建的每个 ascoltatore 将每个发布的消息包装在 JSON 格式中。可以通过传递 { json: false } 选项来禁用此行为。 require('ascoltatori').build({ json: false }, function(err, a) { // ... }); Apache Kafka: var ascoltatori = require('ascoltatori'); var settings = { type: 'kafka', json: false, kafka: require("kafka-node"), connectionString: "localhost:2181", clientId: "ascoltatori", groupId: "ascoltatori", defaultEncoding: "utf8", encodings: { image: "buffer" } }; ascoltatori.build(settings, function (err, ascoltatore) { // ... }); 如果发布到不存在的 Kafka 主题,则将使用默认设置创建该主题。如果订阅不存在的 Kafka 主题,则仅在通过 Ascoltatori 发布到该主题时才会生效。 调试: Ascoltatori 支持调试包,并根据外部环境变量触发日志记录。 $ DEBUG=ascoltatori:mqtt node examples/mqtt_topic_bridge.js 支持的调试标志包括: ascoltatori:amqp ascoltatori:trie ascoltatori:mqtt ascoltatori:prefix ascoltatori:redis ascoltatori:zmq ascoltatori:ee2 ascoltatori:filesystem ascoltatori:kafka 可靠性: 由于 Ascoltatori 使用各种传输方式,因此无法保证在所有传输方式上具有各种可靠性属性。但是,MQTT 和 AMQP Ascoltatori 提供至少一次语义,这意味着消息可能会被接收多次,但至少一次。 --- ### 52. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Eclipse Paho Java 是一个用于 MQTT(Message Queuing Telemetry Transport)协议的开源 Java 客户端库。它允许 Java 应用程序通过 MQTT 协议进行消息传递,支持 MQTT 3.1、3.1.1 和 5.0 版本。Paho Java 客户端库由 Eclipse Paho 项目维护,提供了一种便捷的方式来实现 MQTT 客户端应用程序,用于与 MQTT 代理(或 MQTT 服务器)通信。 以下是一些关于 Eclipse Paho Java 的关键特点和使用情况: 主要特点: 支持多版本 MQTT 协议: Paho Java 客户端库支持 MQTT 3.1、3.1.1 和 5.0 版本,以满足不同应用场景的需求。 轻量级和高性能: 该库设计精简,占用较少的系统资源,适用于嵌入式系统和移动设备。同时,它具有高性能,能够处理大量的消息传递。 异步和同步 API: Paho Java 提供了异步和同步 API,使开发人员能够根据应用程序的需求选择适当的消息传递方式。 安全性支持: 该库支持 TLS/SSL 加密,确保消息在传输过程中的机密性和完整性。它还支持用户名和密码验证,以保障消息通信的安全性。 消息持久性: Paho Java 允许开发人员控制消息的持久性,确保即使在断开连接后,消息不会丢失。 使用情况: 物联网(IoT)应用程序: Eclipse Paho Java 客户端库广泛应用于物联网应用程序,用于设备间的实时通信和数据传递。 消息代理: 开发人员可以将 Paho Java 用作消息代理,用于构建可扩展的消息传递系统。 实时数据流应用程序: 该库适用于需要实时数据传输的应用程序,如在线游戏、实时监控系统等。 移动应用程序: Paho Java 客户端库可用于构建需要在移动设备和服务器之间进行通信的移动应用程序。 以下是 Eclipse Paho Java 的基本使用方法: 1. 添加 Paho Java 客户端库到项目: 首先,你需要将 Eclipse Paho Java 客户端库添加到你的 Java 项目中。你可以通过 Maven、Gradle 或手动下载并导入 JAR 文件来完成这个步骤。 如果你使用 Maven,可以在项目的 pom.xml 文件中添加以下依赖: <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.5</version> <!-- 版本号可能会有所不同 --> </dependency> 2. 创建 MQTT 客户端: 接下来,你需要创建一个 MQTT 客户端对象,以便与 MQTT 代理建立连接和发送/接收消息。通常,你需要指定 MQTT 代理的地址和端口,以及客户端的 ID。 import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; public class MyMqttClient { public static void main(String[] args) { String brokerUrl = "tcp://mqtt.eclipse.org:1883"; // MQTT 代理地址和端口 String clientId = "my-mqtt-client"; // 客户端 ID,可以是任何唯一字符串 try { MqttClient mqttClient = new MqttClient(brokerUrl, clientId); MqttConnectOptions connOptions = new MqttConnectOptions(); // 设置连接选项,如用户名、密码、遗嘱消息等 connOptions.setUserName("your-username"); connOptions.setPassword("your-password".toCharArray()); mqttClient.connect(connOptions); System.out.println("Connected to MQTT broker"); // 在这里可以进行消息的发布和订阅操作 // 详细操作见下一步骤 mqttClient.disconnect(); System.out.println("Disconnected from MQTT broker"); } catch (Exception e) { e.printStackTrace(); } } } 3. 发布消息: 要在 MQTT 主题上发布消息,你可以使用 MQTT 客户端的 publish 方法。首先,创建一个 MQTT 消息对象,然后将其发布到指定的主题。 import org.eclipse.paho.client.mqttv3.MqttMessage; // ... MqttMessage message = new MqttMessage("Hello, MQTT!".getBytes()); message.setQos(0); // 设置消息的服务质量(0、1 或 2) mqttClient.publish("my/topic", message); 4. 订阅消息: 要订阅 MQTT 主题上的消息,你可以使用 MQTT 客户端的 subscribe 方法,并提供一个回调函数来处理接收到的消息。 import org.eclipse.paho.client.mqttv3.IMqttMessageListener; import org.eclipse.paho.client.mqttv3.MqttMessage; // ... mqttClient.subscribe("my/topic", new IMqttMessageListener() { @Override public void messageArrived(String topic, MqttMessage message) throws Exception { System.out.println("Received message on topic: " + topic); System.out.println("Message: " + new String(message.getPayload())); } }); 这就是使用 Eclipse Paho Java 客户端库连接到 MQTT 代理、发布消息和订阅消息的基本步骤。请注意,这只是一个简单的示例,你可以根据你的实际需求进行更复杂的操作,如设置 SSL/TLS 安全连接、处理连接丢失等。确保在生产环境中使用适当的安全性和错误处理机制。 --- ### 53. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Apache ActiveMQ 部署教程 ActiveMQ (apache.org) Apache ActiveMQ 是一个功能强大的消息代理,用于在分布式应用程序中进行高效的消息传递。本教程将指导您如何在 Windows 和 Unix 平台上安装和配置 Apache ActiveMQ,以便您可以开始在您的应用程序中使用它来处理消息。 步骤 1:满足先决条件 在开始部署之前,请确保满足以下先决条件: 硬件和操作系统要求: 至少有 60MB 的可用磁盘空间,用于安装 ActiveMQ 二进制发行版。 至少有 200MB 的可用磁盘空间,用于安装 ActiveMQ 源码或开发者版。 操作系统:支持 Java 运行时环境(JRE)的 Windows 或 Unix 操作系统。 环境要求: Java 开发工具包(JDK)1.7.x 或更高版本,用于部署和构建 ActiveMQ。请确保您已经安装了 JDK,并设置了 JAVA_HOME 环境变量,指向 JDK 的安装目录,例如:C:\Program Files\jdk.1.7.0_xx_xx。 Maven 3.0 或更高版本(仅在安装源码或开发者版时需要)。您需要将所需的 JAR 文件添加到类路径中。 现在,让我们按照平台分步骤来安装和配置 Apache ActiveMQ。 步骤 2:在 Windows 上安装 Apache ActiveMQ 下载和安装二进制发行版 打开您的 Web 浏览器,导航到 Apache ActiveMQ 的官方网站:http://activemq.apache.org/。 在导航窗格的左侧,单击 "Download" 链接。 在 "Download" 页面上,选择最新的二进制发行版(通常是 Stable Release),并下载对应的 ZIP 文件。文件名类似于 activemq-x.x.x.zip,其中 x.x.x 是版本号。 下载完成后,解压缩 ZIP 文件到您选择的目录。您现在已经安装了 Apache ActiveMQ 二进制发行版。 启动 Apache ActiveMQ 打开 Windows 命令提示符或 PowerShell。 使用 cd 命令切换到 Apache ActiveMQ 安装目录,例如: cd C:\path\to\activemq 请替换 C:\path\to\activemq 为您的实际安装路径。 启动 Apache ActiveMQ 服务,运行以下命令: bin\activemq start 此命令将启动 Apache ActiveMQ 服务,并将其运行在后台。ActiveMQ 默认会监听端口 61616。 测试安装 要测试 Apache ActiveMQ 是否正确安装和运行,请执行以下步骤: 打开 Web 浏览器,并访问 Apache ActiveMQ 的管理控制台:http://localhost:8161/admin 使用默认的用户名和密码(用户名:admin,密码:admin)登录管理控制台。 如果成功登录,您将看到 ActiveMQ 的管理界面。这表示 ActiveMQ 正确安装和运行。 至此,您已经在 Windows 上成功部署和配置了 Apache ActiveMQ。接下来,我们将在 Unix 环境中进行安装。 步骤 3:在 Unix 上安装 Apache ActiveMQ 下载和安装二进制发行版 在您的 Unix 系统上,使用浏览器或命令行工具(如 wget、scp、ftp 等)下载 Apache ActiveMQ 二进制发行版 gzip 文件,例如: wget http://activemq.apache.org/path/tofile/apache-activemq-5.8-tar.gz 请将 URL 替换为正确的下载链接。 下载完成后,使用以下命令解压缩 gzip 文件到您选择的目录,例如: tar zxvf apache-activemq-5.8-tar.gz 您现 在已经安装了 Apache ActiveMQ 二进制发行版。 启动 Apache ActiveMQ 打开终端。 使用 cd 命令切换到 Apache ActiveMQ 安装目录,例如: cd /path/to/activemq 请替换 /path/to/activemq 为您的实际安装路径。 启动 Apache ActiveMQ 服务,运行以下命令: bin/activemq start 此命令将启动 Apache ActiveMQ 服务,并将其运行在后台。ActiveMQ 默认会监听端口 61616。 测试安装 要测试 Apache ActiveMQ 是否正确安装和运行,请执行以下步骤: 打开终端。 使用以下命令检查 ActiveMQ 是否在监听端口 61616 上运行: netstat -an | grep 61616 如果看到结果,表示 ActiveMQ 已成功启动。 至此,在 Unix 系统上成功部署和配置了 Apache ActiveMQ。 步骤 4:配置 Apache ActiveMQ(可选) Apache ActiveMQ 提供了广泛的配置选项,您可以根据您的需求进行自定义配置。默认情况下,ActiveMQ 使用内置的配置文件,但您可以编辑配置文件以满足您的特定需求。 要编辑配置文件,请打开 ActiveMQ 安装目录中的 conf 目录,并找到 activemq.xml 文件。根据您的需求进行修改,然后保存文件。 步骤 5:停止 Apache ActiveMQ 要停止 Apache ActiveMQ 服务,请执行以下步骤: 打开命令提示符或终端。 使用 cd 命令切换到 Apache ActiveMQ 安装目录。 停止 Apache ActiveMQ 服务,运行以下命令: bin/activemq stop 或者您可以使用 CTRL-C 来终止运行 Apache ActiveMQ 的终端会话。 恭喜!您已经成功部署和配置了 Apache ActiveMQ。现在,您可以开始使用它来构建分布式应用程序,实现高效的消息传递功能。 MQTT配置 接入 ActiveMQ 的 MQTT 通信是一种强大的方式,它允许您在应用程序之间进行轻松、实时的消息传递。这个完整的教程将引导您完成以下步骤,以在 ActiveMQ 中启用 MQTT 并创建 MQTT 客户端,从而实现 MQTT 消息的发布和订阅。 步骤 1:准备 ActiveMQ 首先,确保您已经成功安装和配置了 ActiveMQ。如果还没有安装 ActiveMQ,您可以按照 ActiveMQ 官方文档中的指南进行安装和配置:ActiveMQ 官方文档 一旦您的 ActiveMQ 实例正常运行,我们可以开始配置 MQTT。 步骤 2:启用 MQTT 支持 要启用 MQTT 支持,您需要编辑 ActiveMQ 的配置文件。在 ActiveMQ 安装目录下,找到 conf 目录,并编辑 activemq.xml 文件。在文件中,找到以下行: <transportConnectors> <!-- 添加 MQTT 连接器配置 --> </transportConnectors> 在 <transportConnectors> 部分中,添加以下 MQTT 连接器配置: <transportConnectors> <!-- MQTT 连接器配置 --> <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883"/> </transportConnectors> 这将启用 MQTT 服务并将其绑定到 1883 端口。您可以根据需要更改端口号。 然后,保存并关闭 activemq.xml 文件,重新启动 ActiveMQ 以使更改生效。 步骤 3:创建 MQTT 客户端 接下来,我们将创建一个 Python MQTT 客户端来连接到 ActiveMQ 代理并发布/订阅消息。 3.1 安装 MQTT 客户端库 首先,确保您已经安装了 Python。然后,使用以下命令安装 Python 的 MQTT 客户端库,它将帮助我们与 ActiveMQ 的 MQTT 服务通信: pip install paho-mqtt 3.2 创建 MQTT 客户端代码 接下来,创建一个 Python 脚本,用于连接到 ActiveMQ 的 MQTT 代理并发布/订阅消息。以下是一个示例代码: import paho.mqtt.client as mqtt # 连接回调函数 def on_connect(client, userdata, flags, rc): if rc == 0: print("连接成功!") client.subscribe("example/topic") # 订阅主题 else: print(f"连接失败,返回码: {rc}") # 消息接收回调函数 def on_message(client, userdata, message): print(f"收到消息 '{message.payload.decode()}' 来自主题 '{message.topic}'") # 创建 MQTT 客户端 client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message # 连接到 ActiveMQ 的 MQTT 代理 client.connect("localhost", 1883, 60) # 指定 ActiveMQ 代理的地址和端口号 # 保持客户端运行,等待消息 client.loop_forever() 3.3 运行 MQTT 客户端 现在,您可以运行上述 Python 脚本,它将连接到 ActiveMQ 的 MQTT 代理,并订阅名为 "example/topic" 的主题。当有消息发布到这个主题时,客户端将接收并打印消息内容。 python mqtt_client.py 步骤 4:发布和订阅消息 现在,您的 MQTT 客户端已经连接到 ActiveMQ 代理,可以执行以下操作: 发布消息 要发布消息,您可以在 Python 脚本中添加以下代码: # 发布消息 client.publish("example/topic", "这是一条 MQTT 消息") 这将发布一条消息到名为 "example/topic" 的主题。 订阅消息 在 Python 脚本中,您已经设置了订阅的主题: client.subscribe("example/topic") 客户端将自动订阅这个主题,当有消息发布到该主题时,将会触发 on_message 回调函数。 步骤 5:测试和扩展 您现在已经成功接入了 ActiveMQ 的 MQTT 服务,并创建了一个简单的 MQTT 客户端。您可以使用这个基础上进行进一步的测试和扩展,以满足您的应用需求。 一些可能的扩展包括: 创建多个 MQTT 客户端,以模拟多个设备之间的通信。 在 ActiveMQ 中配置用户名和密码,并在客户端中使用这些凭据进行连接。 使用不同的主题来组织和管理消息,以便更好地组织您的消息通信。 希望这个教程对您有所帮助,使您能够成功接入 ActiveMQ 的 MQTT 服务并实现消息的发布和订阅。如果您有任何问题或需要进一步的帮助,请随时提问。 --- ### 54. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Eclipse Paho C++介绍与使用文档 https://www.eclipse.org/paho/clients/cpp/ 介绍 Eclipse Paho C++是一个开源的MQTT(Message Queuing Telemetry Transport)C++客户端库,它允许C++应用程序与MQTT代理进行通信。MQTT是一种轻量级、可扩展的发布/订阅通信协议,常用于物联网(IoT)应用、传感器数据传输、远程监控等领域。Paho C++客户端库是Eclipse Paho项目的一部分,旨在提供一个稳定、高性能的MQTT通信解决方案。 特性 Eclipse Paho C++客户端库具有以下特性: MQTT协议支持: 支持MQTT 3.1、MQTT 3.1.1和MQTT 5.0协议版本,使您能够选择最适合您需求的版本。 TLS/SSL支持: 支持使用TLS/SSL进行安全通信,确保数据在传输过程中的机密性和完整性。 遗嘱消息(LWT): 提供遗嘱消息功能,允许客户端在意外断开连接时发送预定义的消息。 自动重连: 支持自动重新连接功能,以确保在网络中断后能够重新建立连接。 离线消息缓存: 允许客户端在离线时缓存消息,当重新连接到代理时自动发布这些消息。 WebSocket支持: 支持WebSocket协议,允许通过WebSocket连接到MQTT代理。 非阻塞API: 提供非阻塞API,使应用程序能够并发处理多个MQTT操作。 高可用性: 支持高可用性设置,确保可靠的消息传递,即使在代理故障时也能保持通信。 安装与构建 从源代码构建 要使用Eclipse Paho C++客户端库,您可以从源代码构建它。以下是一些常见的步骤: 获取源代码: 您可以从Paho GitHub仓库中获取源代码。使用git clone命令或下载ZIP文件。 配置构建: 使用CMake配置构建过程。在命令行中导航到源代码目录,然后运行以下命令: cmake . 构建库: 使用合适的构建工具(通常是Make或Visual Studio)构建库。运行以下命令来构建库文件: make 安装库(可选): 您可以选择安装库到系统中,以便在其他项目中使用。运行以下命令来安装库: make install 现在,您已经成功构建了Eclipse Paho C++客户端库,可以将其包含到您的C++应用程序中。 使用步骤 下面是使用Eclipse Paho C++客户端库的基本步骤: 包含头文件: 在您的C++代码中包含必要的Paho头文件。例如: #include <mqtt/client.h> 创建客户端实例: 创建一个MQTT客户端实例,并配置连接选项。 mqtt::client cli(ADDRESS, CLIENT_ID); mqtt::connect_options connOpts; connOpts.set_keep_alive_interval(20); connOpts.set_clean_session(true); 连接到MQTT代理: 使用连接选项连接到MQTT代理。 cli.connect(connOpts); 发布消息: 创建MQTT消息并使用客户端实例发布消息。 auto msg = mqtt::make_message(TOPIC, PAYLOAD); msg->set_qos(QOS); cli.publish(msg); 订阅主题(可选): 如果需要订阅消息,可以使用客户端实例进行订阅。 cli.subscribe(TOPIC, QOS); 处理消息(可选): 如果订阅了主题,您可以设置消息处理程序来处理接收到的消息。 cli.set_callback(my_callback); 断开连接: 在完成通信后,断开与MQTT代理的连接。 cli.disconnect(); 以上步骤简要介绍了如何使用Eclipse Paho C++客户端库与MQTT代理进行通信。根据您的具体需求,您可以进一步扩展和自定义这些步骤,以满足您的应用程序的需求。 示例代码 以下是一个简单的发布示例代码,展示了如何使用Eclipse Paho C++客户端库发布MQTT消息: int main(int argc, char* argv[]) { const std::string TOPIC { "hello" }; const std::string PAYLOAD { "Hello World!" }; const int QOS = 1; // 创建客户端 mqtt::client cli(ADDRESS, CLIENT_ID); mqtt::connect_options connOpts; connOpts.set_keep_alive_interval(20); connOpts.set_clean_session(true); try { // 连接到客户端 cli.connect(connOpts); // 创建并发布消息 auto msg = mqtt::make_message(TOPIC, PAYLOAD); msg->set_qos(QOS); cli.publish(msg); // 断开连接 cli.disconnect(); } catch (const mqtt::exception& exc) { std::cerr << "Error: " << exc.what() << " [" << exc.get_reason_code() << "]" << std::endl; return 1; } return 0; } 这个示例创建了一个MQTT客户端,连接到MQTT代理,发布一条消息,然后断开连接。您可以根据需要修改主题、负载、质量服务等参数。 总结 Eclipse Paho C++客户端库提供了一个强大的工具,使C++应用程序能够轻松地与MQTT代理进行通信。通过使用这个库,您可以构建可靠的物联网应用程序、传感器数据传输系统和远程监控解决方案。希望本文档能够帮助您入门并开始使用Eclipse Paho C++客户端库。如果您需要更多信息和详细的文档,请参考项目的官方文档和示例。 --- ### 55. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Paho MQTT Go 客户端介绍文档 https://github.com/eclipse/paho.mqtt.golang 欢迎使用 Paho MQTT Go 客户端库!这个库是一个强大的 MQTT(Message Queuing Telemetry Transport)客户端,它允许您轻松地与 MQTT 代理进行通信,以便在应用程序之间传递消息。本文档将为您提供有关如何安装、配置和使用该库的详细信息,以及一些常见问题的解决方法。 目录 安装 使用步骤 2.1 导入库 2.2 连接到 MQTT 代理 2.3 发布消息 2.4 订阅主题 常见问题 贡献 更多资源 1. 安装 您可以使用 Go 的模块功能或 GOPATH 来安装 Paho MQTT Go 客户端库。以下是两种安装方法: 使用 Go 模块(推荐) 如果您使用 Go 模块,请在项目中导入 github.com/eclipse/paho.mqtt.golang,然后运行 go build。必要的依赖项将会自动下载。您可以使用以下命令来获取最新提交的代码: go get github.com/eclipse/paho.mqtt.golang@master 使用 GOPATH 如果您使用 GOPATH,请运行以下命令来安装 Paho MQTT Go 客户端库: go get github.com/eclipse/paho.mqtt.golang 此外,客户端库还依赖于 Google 的代理包和 websockets 包,您可以使用以下命令来安装它们: go get github.com/gorilla/websocket go get golang.org/x/net/proxy 2. 使用步骤 现在,让我们来了解如何在您的 Go 项目中使用 Paho MQTT Go 客户端库。 2.1 导入库 首先,在您的 Go 项目中导入 Paho MQTT Go 客户端库: import "github.com/eclipse/paho.mqtt.golang" 2.2 连接到 MQTT 代理 在连接到 MQTT 代理之前,您需要配置客户端的连接选项。以下是一个简单的示例: // 创建 MQTT 客户端选项 opts := mqtt.NewClientOptions() opts.AddBroker("tcp://mqtt.example.com:1883") // 设置代理的地址 opts.SetClientID("my-client") // 设置客户端标识 // 创建 MQTT 客户端 client := mqtt.NewClient(opts) // 连接到代理 if token := client.Connect(); token.Wait() && token.Error() != nil { panic(token.Error()) } // 连接成功 fmt.Println("Connected to MQTT broker!") 2.3 发布消息 现在,您可以使用 Paho MQTT Go 客户端库发布消息到 MQTT 代理。以下是一个发布消息的示例: topic := "my-topic" payload := []byte("Hello, MQTT!") // 发布消息 token := client.Publish(topic, 0, false, payload) token.Wait() if token.Error() != nil { fmt.Println("Error publishing message:", token.Error()) } else { fmt.Println("Message published!") } 2.4 订阅主题 您还可以使用 Paho MQTT Go 客户端库订阅主题以接收发布的消息。以下是一个订阅主题的示例: topic := "my-topic" // 订阅主题 token := client.Subscribe(topic, 0, func(client mqtt.Client, msg mqtt.Message) { fmt.Printf("Received message on topic '%s': %s\n", msg.Topic(), msg.Payload()) }) token.Wait() if token.Error() != nil { fmt.Println("Error subscribing to topic:", token.Error()) } else { fmt.Printf("Subscribed to topic '%s'\n", topic) } 3. 常见问题 在使用 Paho MQTT Go 客户端库时,可能会遇到一些常见问题。以下是一些常见问题和解决方法: 随机断开连接: 随机断开连接可能是由于另一个使用相同客户端标识的客户端连接到代理所致。这是规范所规定的。 消息处理程序阻塞: 如果您的消息处理程序在长时间运行任务或发布消息时阻塞,建议使用 Go 协程来避免阻塞。 丢失的消息: 在以前创建了 QOS1+ 订阅并且以 CleanSession 设置为 false 连接时,代理可能会在调用 Subscribe 之前传递保留的消息。要处理这些消息,请配置处理程序或设置 DefaultPublishHandler。 网络连接丢失: 如果网络连接丢失不会立即检测到,可以考虑设置 ClientOptions.KeepAlive,以发送定期消息来检查链接是否活动。 更多问题和解决方法可以在官方文档和论坛上找到。 4. 贡献 我们欢迎您的贡献!如果您希望为 Paho MQTT Go 客户端库做出贡献,请首先创建并签署 Eclipse 贡献者协议(ECA)。更多详细信息可以在 Eclipse Development Resources 中找到。 5. 更多资源 如果您有任何一般问题,可以在 Stack Overflow 上查找问题/答案,其中包括许多涉及使用此库和 MQTT 的问题。 有关 P aho 客户端的讨论发生在 Eclipse paho-dev 邮件列表上。 有关 MQTT 协议的一般问题在 MQTT Google Group 中讨论。 您可以在 MQTT 社区网站上找到更多有关 MQTT 的信息。 希望这个文档可以帮助您开始使用 Paho MQTT Go 客户端库。如果您有任何其他问题或需要更多信息,请随时咨询。祝您成功使用 MQTT 通信! --- ### 56. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT.js 是一个开源的 MQTT 协议的客户端库,使用 JavaScript 编写,主要用于 Node.js 和 浏览器环境中。是目前 JavaScript 生态中使用最为广泛的 MQTT 客户端库。 https://github.com/mqttjs/MQTT.js 由于 JavaScript 单线程特性,MQTT.js 是全异步 MQTT 客户端,MQTT.js 支持 MQTT/TCP、MQTT/TLS、MQTT/WebSocket,在不同运行环境支持的度如下: 浏览器环境:MQTT over WebSocket(包括微信小程序、支付宝小程序等定制浏览器环境) Node.js 环境:MQTT、MQTT over WebSocket 安装 // 安装 MQTT 模块 npm install mqtt --save // 导入 MQTT 模块 const mqtt = require("mqtt"); // 创建 MQTT 客户端并连接到 MQTT 代理 const client = mqtt.connect("mqtt://test.mosquitto.org"); // 当连接成功建立时的回调函数 client.on("connect", () => { // 订阅主题 "presence" client.subscribe("presence", (err) => { if (!err) { // 当连接建立后,发布消息到主题 "presence" client.publish("presence", "Hello mqtt"); } }); }); // 当接收到消息时的回调函数 client.on("message", (topic, message) => { // 将消息从缓冲区(Buffer)转换为字符串并打印出来 console.log(message.toString()); // 关闭 MQTT 客户端连接 client.end(); }); 输出: Hello mqtt 如果你想运行自己的 MQTT 代理,你可以使用 Mosquitto 或 Aedes-cli,并启动它。你也可以使用一个测试实例:test.mosquitto.org。如果你不想安装一个单独的代理,你可以尝试使用 Aedes。 导入样式: CommonJS(Require) // 导入 MQTT 模块 const mqtt = require("mqtt"); // 创建客户端并连接到 MQTT 代理 const client = mqtt.connect("test.mosquitto.org"); ES6 模块(Import)别名通配符导入 // 导入 mqtt 模块中的所有内容,并赋予命名空间 "mqtt" import * as mqtt from "mqtt"; // 创建客户端并连接到 MQTT 代理 let client = mqtt.connect("mqtt://test.mosquitto.org"); 导入单独的组件 // 从 mqtt 中导入 connect import { connect } from "mqtt"; // 创建客户端并连接到 MQTT 代理 let client = connect("mqtt://test.mosquitto.org"); 命令行工具: MQTT.js 包含一个与代理交互的命令,为了在全局环境中可用,你应该全局安装 MQTT.js: npm install mqtt -g 然后,在一个终端中运行: mqtt sub -t 'hello' -h 'test.mosquitto.org' -v 在另一个终端中运行: mqtt pub -t 'hello' -h 'test.mosquitto.org' -m 'from MQTT.js' 查看 mqtt help <command> 来获取命令的帮助信息。 调试日志: MQTT.js 使用 debug 包进行调试。要启用调试日志,需要在运行时设置以下环境变量: #(使用 PowerShell 举例,默认为 VS Code) $env:DEBUG='mqttjs*' 关于重连: 任何 WebSocket 连接的重要部分是在连接中断并且客户端需要重新连接时要执行的操作。MQTT 具有内置的重连支持,可以配置以适应应用程序的需求。 刷新身份验证选项/使用 transformWsUrl 进行签名 URL(仅适用于 WebSocket): 当 MQTT 连接中断并且需要重新连接时,通常需要保持与连接相关的任何身份验证与底层身份验证机制的当前状态同步。例如,某些应用程序可能会在初始连接时使用连接选项传递身份验证令牌,而其他云服务可能要求每次连接都要使用签名的 URL。 在重新连接发生在应用程序生命周期中时,原始身份验证数据可能已过期。 为了解决这个问题,我们可以使用一个称为 transformWsUrl 的钩子,在重新连接时操作连接 URL 或客户端选项。 示例(在每次重新连接时更新 clientId 和 username): const transformWsUrl = (url, options, client) => { client.options.username = `token=${this.get_current_auth_token()}`; client.options.clientId = `${this.get_updated_clientId()}`; return `${this.get_signed_cloud_url(url)}`; } const connection = await mqtt.connectAsync(<wss url>, { ..., transformWsUrl: transformUrl, }); 现在,每当建立新的 WebSocket 连接(希望不会太频繁)时,都会获取到一个新的已签名 URL 或最新的身份验证令牌数据。 注意:目前此钩子不支持 promises,这意味着为了使用最新的身份验证令牌,您必须运行一些外部机制来处理应用程序级别的身份验证刷新,以便 WebSocket 连接可以简单地获取到最新的有效令牌或已签名的 URL。 启用重新连接的 reconnectPeriod 选项: 要确保 MQTT 客户端在连接中断时自动尝试重新连接,必须将客户端选项 reconnectPeriod 设置为大于 0 的值。值为 0 将禁用重新连接,并在连接中断时终止最终连接。 默认值为 1000 毫秒,这意味着在丢失连接后 1 秒后将尝试重新连接。 关于主题别名管理: 启用自动主题别名功能: 如果客户端设置选项 autoUseTopicAlias: true,那么 MQTT.js 会自动使用现有的主题别名。 示例场景: 发布主题 't1',主题别名为 1(注册) 发布主题 't1',主题别名为空,主题别名为 1(根据最近的映射自动使用现有映射) 发布主题 't2',主题别名为 1(注册覆盖) 发布主题 't2',主题别名为空,主题别名为 1(根据最近的映射自动使用现有映射) 发布主 题 't1'(t1 不再映射到主题别名 1) 用户不需要管理哪个主题映射到哪个主题别名。如果用户想要注册主题别名,然后发布主题时使用主题别名。如果用户想要使用主题别名,然后发布主题时自动使用现有的映射。 启用自动主题别名功能: const connection = await mqtt.connectAsync(<server url>, { ..., autoUseTopicAlias: true, }); 获取已注册的主题别名映射: 如果您想要获取已注册的主题别名映射,可以使用以下命令: const topicAliasMap = connection._client._topicAliasMap; console.log(topicAliasMap); 这会打印出已注册的主题别名映射。请注意,这是一个内部属性,可以根据需要进行调试或监视。 使用已注册的主题别名映射: 如果您想要使用已注册的主题别名映射,可以手动为要发布的消息设置主题别名,如下所示: const topicAlias = connection._client._topicAliasMap.get("your_topic"); const message = "Your message"; const options = { properties: { topicAlias: topicAlias, }, }; connection.publish("your_topic", message, options, () => { console.log("Message published with topic alias"); }); 这将使用已注册的主题别名映射来发布消息。 请注意,_client 是 MQTT.js 的内部客户端对象,不建议在生产代码中直接访问这些内部属性,但它们可以用于调试和测试目的。``` --- ### 57. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Arduino Client for MQTT是一个用于Arduino平台的MQTT客户端库。MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,通常用于物联网(IoT)应用程序中,用于在设备之间进行通信。这个库允许您在Arduino板上轻松实现MQTT通信,将您的物联网项目连接到MQTT代理(broker)并与其他设备进行通信。 GitHub - knolleary/pubsubclient:Arduino Ethernet Shield 的客户端库,支持 MQTT。 版本号: 2.8构造函数 1.PubSubClient () 描述:创建一个未初始化的客户端实例。 示例: EthernetClient ethClient; PubSubClient client; void setup() { client.setClient(ethClient); client.setServer("broker.example.com", 1883); // 客户端现在已经配置好了 } 2.PubSubClient (client) 描述:创建一个部分初始化的客户端实例。 示例: EthernetClient ethClient; PubSubClient client(ethClient); void setup() { client.setServer("broker.example.com", 1883); // 客户端现在已经准备好了 } 3.PubSubClient (server, port, [callback], client, [stream]) 描述:创建一个完全配置好的客户端实例。 参数: server:服务器地址(IPAddress、uint8_t[] 或 const char[]) port:连接的端口 callback:消息回调函数的指针(可选,用于处理订阅消息) client:用于网络连接的客户端(例如 WiFiClient) stream:用于写入接收到的消息的流(可选) 示例: EthernetClient ethClient; PubSubClient client(ethClient); void setup() { client.setServer("broker.example.com", 1883); // 客户端现在已经准备好了 } 函数 boolean connect (clientID, [username, password], [willTopic, willQoS, willRetain, willMessage], [cleanSession]) 描述:连接客户端到服务器。 参数: clientID:连接到服务器时使用的客户端ID username:用户名(可选,如果不需要用户名和密码则为NULL) password:密码(可选,如果不需要用户名和密码则为NULL) willTopic:遗嘱消息的主题(可选) willQoS:遗嘱消息的QoS等级(0、1 或 2,可选) willRetain:遗嘱消息是否应保留(可选) willMessage:遗嘱消息的内容(可选) cleanSession:是否连接时清除会话(可选) 返回值: false:连接失败 true:连接成功 2.void disconnect () 描述:断开客户端连接。 3.boolean publish (topic, payload, [length], [retained]) 描述:发布消息到指定主题。 参数: topic:要发布到的主题 payload:要发布的消息内容 length:消息内容的长度(可选,如果消息内容是byte[]类型则必须提供) retained:消息是否应被保留 返回值: false:发布失败,可能是连接断开或消息太大 true:发布成功 4.boolean publish_P (topic, payload, [length], [retained]) 描述:发布存储在 PROGMEM 中的消息到指定主题。 参数与publish函数类似,但用于处理存储在程序存储器中的消息。 5.boolean beginPublish (topic, length, retained) 描述:开始发送一个发布消息。消息的内容需要通过一次或多次的write调用设置,最后使用endPublish完成消息的发送。 参数: topic:要发布到的主题 length:要发送的消息内容的长度 retained:消息是否应被保留 返回值: false:开始发布失败,可能是连接断开或消息太大 true:开始发布成功 6.int write (byte) 描述:将一个字节添加到使用beginPublish开始的发布消息中。 参数: byte:要写入发布消息的字节 返回值: 写入的字节数 7.int write (payload, length) 描述:将一个字节数组添加到使用beginPublish开始的发布消息中。 参数: payload:要写入发布消息的字节数组 length:要写入的字节数组的长度 返回值: 写入的字节数 8.boolean endPublish () 描述:完成使用beginPublish开始的发布消息的发送。 返回值: false:发布失败,可能是连接断开或消息太大 true:发布成功 9.boolean subscribe (topic, [qos]) 描述:订阅指定主题的消息。 参数: topic:要订阅的主题 qos:订阅的QoS等级(0或1,可选) 返回值: false:发送订阅失败,可能是连接断开或消息太大 true:发送订阅成功 10.boolean unsubscribe (topic) 描述:取消订阅指定主题的消息。 参数: topic:要取消订阅的主题 返回值: false:发送取消订阅失败,可能是连接断开或消息太大 true:发送取消订阅成功 11.boolean loop () 描述:应该定期调用此函数,以允许客户端处理传入的消息并维持与服务器的连接。 返回值: false:客户端已断开连接 true:客户端仍然连接 12.boolean connected () 描述:检查客户端是否连接到服务器。 - 返回值: - false:客户端未连接 - true:客户端已连接 int state () 描述:返回客户端的当前状态。如果连接尝试失败,可以使用此状态获取有关失败的更多信息。 返回值: -4:MQTT_CONNECTION_TIMEOUT - 服务器未在保持连接时间内响应 -3:MQTT_CONNECTION_LOST - 网络连接已断开 -2:MQTT_CONNECT_FAILED - 网络连接失败 -1:MQTT_DISCONNECTED - 客户端已断开连接 0:MQTT_CONNECTED - 客户端已连接 1:MQTT_CONNECT_BAD_PROTOCOL - 服务器不支持所请求的MQTT协议版本 2:MQTT_CONNECT_BAD_CLIENT_ID - 服务器拒绝客户端标识符 3:MQTT_CONNECT_UNAVAILABLE - 服务器无法接受连接 4:MQTT_CONNECT_BAD_CREDENTIALS - 用户名/密码被拒绝 5:MQTT_CONNECT_UNAUTHORIZED - 客户端未被授权连接 PubSubClient* setCallback (callback) 描述:设置消息回调函数。 参数: callback:消息到达订阅的主题时调用的消息回调函数的指针 返回值:PubSubClient* - 允许链式调用的客户端实例 PubSubClient* setClient (client) 描述:设置要使用的网络客户端实例。 参数: client:要使用的网络客户端,例如WiFiClient 返回值:PubSubClient* - 允许链式调用的客户端实例 PubSubClient* setServer (server, port) 描述:设置服务器的详细信息。 参数: server:服务器地址(IPAddress、uint8_t[] 或 const char[]) port:要连接的端口 返回值:PubSubClient* - 允许链式调用的客户端实例 PubSubClient* setStream (stream) 描述:设置用于写入接收到的消息的流。 参数: stream:要写入接收到的消息的流 返回值:PubSubClient* - 允许链式调用的客户端实例 uint16_t getBufferSize () 描述:获取内部缓冲区的当前大小。 返回值:内部缓冲区的大小 boolean setBufferSize (size) 描述:设置内部发送/接收缓冲区的大小,以字节为单位。这必须足够大,以容纳完整的MQTT数据包。 参数: size:内部缓冲区的大小(以字节为单位) 返回值: false:无法重新分配内存以更改缓冲区大小 true:已更改缓冲区大小 PubSubClient* setKeepAlive (keepAlive) 描述:设置客户端使用的保持连接间隔。只有在客户端未连接时才能更改此值。 参数: keepAlive:保持连接的间隔时间,以秒为单位 返回值:PubSubClient* - 允许链式调用的客户端实例 PubSubClient* setSocketTimeout (timeout) 描述:设置客户端使用的套接字超时。这确定了客户端在期望数据到达时将等待多长时间,例如,在读取MQTT数据包时。 参数: timeout:套接字超时时间,以秒为单位 返回值:PubSubClient* - 允许链式调用的客户端实例 其他配置选项以下是用于配置库的一些配置选项,它们包含在PubSubClient.h文件中: MQTT_MAX_PACKET_SIZE:设置客户端将处理的最大数据包大小(以字节为单位)。将忽略任何超过此大小的接收到的数据包。 默认值:128字节 MQTT_KEEPALIVE:设置客户端将使用的保持连接间隔,以秒为单位。用于在未发送或接收任何其他数据包时维护连接。 默认值:15秒 MQTT_VERSION:设置要使用的MQTT协议版本。 默认值:MQTT 3.1.1 MQTT_MAX_TRANSFER_SIZE:设置在每次写入调用中传递给网络客户端的最大字节数。某些硬件有一次传递给它们的数据量限制,例如Arduino Wifi Shield。 默认值:未定义(每次写入调用中传递完整数据包) MQTT_SOCKET_TIMEOUT:设置读取网络时的超时时间。这也适用于对connect的调用的超时。 默认值:15秒 订阅回调如果客户端用于订阅主题,必须在构造函数中提供一个回调函数。当新消息到达客户端时,将调用此函数。 回调函数具有以下签名: void callback(const char[] topic, byte* payload, unsigned int length) 参数: topic:消息到达的主题 payload:消息负载 length:消息负载的长度 请注意,客户端在内部使用相同的缓冲区来处理传入和传出的消息。在回调函数返回后,或者如果在回调函数内部调用publish或subscribe,函数传递给回调函数的topic和payload值将被覆盖。如果需要在回调返回后使用这些值,应用程序应创建它们的副本。 --- ═══════════════════════════════════════════ ## MQTT 教程 ═══════════════════════════════════════════ ### 58. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 HiveMQ健康API现在提供了对HiveMQ平台健康状况的全面洞察。它不仅为每个HiveMQ集群中的节点提供了准备状态和存活状态的REST API资源,还包含了每个已安装的HiveMQ扩展的详细状态和健康信息。此项增强允许对HiveMQ MQTT Broker及其扩展进行全面监控。站点可靠性工程师(SRE)可以利用这些数据主动监控平台健康,迅速识别和解决问题,保持最大正常运行时间。 健康API是什么,它能做什么? HiveMQ平台是我们客户物联网部署的核心组件。我们的客户依赖HiveMQ平台来实现各种用例,如智能制造中的预测性维护、能源领域的关键基础设施监控或运输和物流中的高价值资产跟踪。 由于HiveMQ平台是支持这些用例的复杂物联网部署的核心,我们的客户需要能够监控其健康状况。他们需要访问关于HiveMQ Broker组件和已安装平台扩展的操作信息,以确保一切顺利运行。 我们在4.14版本中发布了健康API。该API为每个HiveMQ集群中的节点提供了存活和准备状态检查。这些检查帮助您快速、准确地识别每个HiveMQ节点的精确状态,并确定集群的整体状态。 存活检查告诉您您的Broker是否在运行并响应。 准备检查告诉您HiveMQ Broker的MQTT组件是否准备好接收流量。 这些信息以结构良好的格式呈现,帮助您快速识别Broker或其组件中的任何问题,确保您的HiveMQ部署顺利运行。 健康API对SRE有何价值? HiveMQ集群部署在各种环境中,从本地数据中心到AWS、Azure或GCP等托管云服务。保持卓越的集群可用性对于确保物联网部署的顺利运行至关重要。 存活和准备状态检查共同提供了一种验证MQTT集群健康状况的方法,确保流量仅路由到准备好并能够处理它的组件。 健康检查返回的HTTP状态代码显示了集群中每个节点的当前状态。 状态码200表示节点可以接受MQTT流量。 状态码503表示节点当前不可用。 每个健康检查响应还以人类可读的JSON格式提供附加信息,以获得更深入的洞察: HiveMQ Broker和HiveMQ MQTT监听器的状态信息——MQTT监听器指定了HiveMQ接受来自MQTT客户端的传入连接的IP地址和端口。 站点可靠性工程师(SRE)可以使用此API来监控HiveMQ平台的健康状况。他们可以利用这些深入的信息迅速检测到任何问题,并构建自愈系统,以确保尽可能高的可用性。 健康API有哪些新功能? 在4.28版本中,健康API的功能扩展,包含了一个子组件部分,提供了您HiveMQ集群中每个企业扩展的关键状态和健康细节。 状态部分提供了关于任何已安装扩展的当前状态的关键信息,包括企业或自定义扩展。在这里,您可以查看扩展是否“UP”(正常)、“DEGRADED”(降级)或“DOWN”(停机),以及其启动时间、许可证信息和配置摘要。 让我们以Kafka的企业扩展为例。 监控Kafka企业扩展的健康状况 以下JSON块显示了HiveMQ Kafka企业扩展的状态。 json复制代码{ "author": "HiveMQ", "status": "enabled", "name": "HiveMQ Enterprise Extension for Kafka", "priority": 1, "startTime": 1714053790016, "version": "4.28", "internals": { "license": "...", "entryPoint": "...", "services": [...] }, "application": { "configuration": "..." } } 上面部分提供了有关扩展的一般信息,如: 扩展的作者:HiveMQ 扩展状态:已启用 扩展名称:HiveMQ Kafka企业扩展 扩展加载优先级:1(最高优先级扩展先加载) 扩展启动时间(以纪元时间表示):1714053790016 HiveMQ平台版本:4.28 内部子组件提供了关于扩展的更多细节,包括许可证、入口点和服务,而应用子组件总结了扩展的配置。每个健康API的组件都可以通过一个URL检索。 --- ### 59. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着物联网(IoT)技术的飞速发展,消息队列遥测传输(MQTT)协议作为一种轻量级的消息传递协议,在物联网设备间的消息传输中扮演着重要的角色。尤其是MQTT 5.0的发布,为开发者带来了一系列创新特性,极大地拓宽了MQTT协议的应用场景。其中,用户属性(User Properties)的引入为自定义消息元数据提供了无限可能,本文将探索用户属性的概念、必要性及其在实际应用中的运用,以通俗易懂的方式向开发者展示这一新特性的魅力。 用户属性的定义与必要性 用户属性是MQTT 5.0引入的一种新特性,允许在MQTT消息中添加自定义的键值对信息,从而传递额外的自定义元数据。每个键值对都由UTF-8编码的字符串组成,为消息传递提供了更丰富的上下文信息。这一功能与HTTP协议中的Header概念相似,但设计得更为灵活,可以无限扩展。 在MQTT 5.0之前,MQTT的扩展性较差,用户难以在标准协议基础上传递特定的元数据信息。用户属性的引入有效解决了这一问题,不仅支持在客户端与MQTT服务器间传递任意信息,还可在客户端间实现元数据的交换,极大增强了MQTT的可用性和灵活性。 应用场景举例 场景一:文件传输 在传统的MQTT通信中,文件通常被转换为二进制数据并嵌入到消息的Payload中进行传输。MQTT 5.0允许通过用户属性传输文件的元数据,如文件名、类型等,而文件内容仍通过Payload传输。这样,接收方可以在收到消息前就获得文件的相关信息,从而更有效地处理文件数据。 例如,发送方可以设置以下用户属性来传输一个文本文件: { "filename": "example.txt", "filetype": "text/plain" } 场景二:资源解析 在一个全球分布的物联网系统中,不同地区的设备可能使用不同格式的消息进行通信(如JSON、XML)。通过用户属性,发送方可以指明消息格式和地区信息,使得MQTT服务器或接收方能够根据这些元数据选择正确的解析器解析消息。 例如,一个位于欧洲的设备发送的消息可能包含以下用户属性: { "region": "Europe", "format": "JSON" } 场景三:消息路由 用户属性还可以用于实现更高级的消息路由机制。在复杂的物联网应用中,根据消息的类型、优先级或目的地对消息进行路由是非常常见的需求。通过在消息中添加相应的用户属性,MQTT服务器可以根据这些属性将消息路由到正确的处理队列或服务。 例如,一个紧急报警消息可以包含如下用户属性: { "priority": "high", "alertType": "gasLeak" } 在客户端中使用用户属性 使用JavaScript和MQTT.js库为例,下面演示如何在连接客户端时和发布消息时设置用户属性。 连接客户端时的用户属性 连接到MQTT服务器时,可以在connect方法的options中添加用户属性,这些属性将随着连接请求一起发送给MQTT服务器。 // connect options const OPTIONS = { clientId: 'mqtt_test', clean: true, connectTimeout: 4000, username: 'emqx', password: 'public', reconnectPeriod: 1000, protocolVersion: 5, properties: { userProperties: { region: 'A', type: 'JSON', }, }, } const client = mqtt.connect('mqtt://broker.emqx.io', OPTIONS) 发布消息时的用户属性 当发布MQTT消息时,也可以添加用户属性,这些属性将随消息一同传递给订阅了相应主题的客户端。 client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false, properties: { userProperties: { region: 'A', type: 'JSON', }, }, }, (error) => { if (error) { console.error(error) } }) client.on('message', (topic, payload, packet) => { console.log('packet:', packet) console.log('Received Message:', topic, payload.toString()) }) 结论 MQTT 5.0的用户属性特性为MQTT协议带来了前所未有的灵活性和扩展性,使得开发者能够更便捷地在MQTT消息中携带丰富的上下文信息。无论是进行文件传输、资源解析还是实现复杂的消息路由,用户属性都提供了一个简洁而强大的解决方案。随着越来越多的应用开始利用这一新特性,我们有理由相信MQTT协议在物联网领域的应用将变得更加广泛和深入。 --- ### 60. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在实时通讯协议 MQTT 的最新版本 5.0 中,引入了一个称为“消息过期间隔”(Message Expiry Interval)的新特性。这一功能允许消息发布者为每条消息设置一个有效期限。如果消息在服务器上停留的时间超过了这个期限,它就不会被分发给任何订阅者。这意味着,当消息的内容不再相关或有用时,它会被自动清理,从而优化了网络资源的使用和提高了通信的效率。 什么是消息过期间隔? 消息过期间隔定义了一个消息从被发布起,到它变得不再可分发为止的时间长度。在 MQTT 协议中,这是通过在消息中设置一个特定的“过期间隔”值来实现的。默认情况下,消息不设置过期间隔,即视为永不过期。但在某些场景下,设定一个合理的过期时间可以显著提高数据传输的效率和实时性。 应用场景 时间敏感的信息 例如,一个促销活动仅在接下来的两小时内有效。如果消费者在活动结束后才收到这个消息,那么这个消息就失去了它的价值。 状态更新 考虑到实时交通信息的更新,如道路拥堵情况。随着时间的推移和交通流量的变化,过时的拥堵信息就不再有参考价值。 自动管理保留消息 在 MQTT 中,保留消息功能允许新的订阅者接收到他们订阅主题的最后一条消息。通过设置消息的过期间隔,可以避免过时的保留消息长时间占用服务器资源。 实例演示 假设有一个联网汽车应用场景,其中包括发送实时交通状况和路口信号灯配时建议。通过设置消息的过期间隔,可以确保车辆只接收到当前位置附近的、时效性强的信息。 设置消息过期间隔的操作步骤 要演示消息过期间隔的代码示例,我们可以使用 Python 和 paho-mqtt 库,这是一个常用于 MQTT 客户端开发的库。下面的示例将分为两部分:发布者(Publisher)和订阅者(Subscriber)。 安装 paho-mqtt 首先,确保你已经安装了 paho-mqtt。如果没有安装,可以通过 pip 安装: pip install paho-mqtt 发布者(Publisher) 发布者将发送两条消息,一条设置了5秒的过期间隔,另一条设置了60秒。 import time import paho.mqtt.client as mqtt # MQTT 服务器地址 MQTT_HOST = "test.mosquitto.org" MQTT_PORT = 1883 MQTT_TOPIC = "mqttx/demo/message_expiry" def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") client = mqtt.Client() client.on_connect = on_connect client.connect(MQTT_HOST, MQTT_PORT, 60) # 发送第一条消息,设置5秒过期间隔 client.publish(MQTT_TOPIC, payload="This message will expire in 5 seconds.", qos=1, properties={'message_expiry_interval': 5}) print("Published message with 5 seconds expiry.") # 发送第二条消息,设置60秒过期间隔 client.publish(MQTT_TOPIC, payload="This message will expire in 60 seconds.", qos=1, properties={'message_expiry_interval': 60}) print("Published message with 60 seconds expiry.") # 断开连接 client.disconnect() 订阅者(Subscriber) 订阅者订阅同一个主题,并处理接收到的消息。 import paho.mqtt.client as mqtt # MQTT 服务器地址 MQTT_HOST = "test.mosquitto.org" MQTT_PORT = 1883 MQTT_TOPIC = "mqttx/demo/message_expiry" def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") client.subscribe(MQTT_TOPIC) def on_message(client, userdata, msg): print(f"Received message: {msg.payload.decode()} on topic {msg.topic}") client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect(MQTT_HOST, MQTT_PORT, 60) client.loop_forever() 运行示例 运行订阅者代码:首先启动订阅者客户端,让它在后台运行并监听指定主题的消息。 运行发布者代码:然后运行发布者代码,发送两条带有不同过期间隔的消息。 你将看到订阅者只接收到在其过期间隔内的消息。如果你在发布后立刻运行订阅者,两条消息都可能被接收。但如果在5秒后再启动订阅者,只有设置了60秒过期间隔的消息会被接收,因为另一条消息已经过期。 这个演示说明了如何在MQTT 5.0中使用消息过期间隔功能,以及它如何影响消息的传递和接收。 通过这个例子,我们可以清楚地看到消息过期间隔如何在实际应用中起作用,以确保信息的实时性和相关性。 总结 消息过期间隔是 MQTT 5.0 提供的一个非常实用的特性,它帮助开发者和企业确保消息的时效性,同时减轻服务器的负担,并优化资源使用。无论是在实时交通信息、促销活动通知,还是在智能家居和工业物联网应用中,适当使用消息过期间隔都能带来显著的效益。 在设计和实现基于 MQTT 协议的通信系统时,合理利用消息过期间隔不仅可以提高信息传输的效率,还能增强用户体验,确保用户及时获取最重要和最相关的信息。同时,它还减少了网络带宽的浪费,优化了服务器存储资源的使用,使得系统更加高效和可靠。 --- ### 61. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在MQTT 5.0中,Reason Code的引入为客户端和服务端提供了更详细的反馈机制。这些代码不仅帮助诊断连接问题,还让开发者能够更精确地处理各种异常情况。与MQTT 3.1.1相比,MQTT 5.0扩展了Reason Code的范围和应用,使得错误处理更加灵活和详细。 MQTT 3.1.1与MQTT 5.0中的Reason Code对比 在MQTT 3.1.1版本中,Reason Code的使用相对有限,仅在CONNACK和SUBACK报文中提供了一些基本的错误代码。这些代码的范围和细节都较为有限,使得开发者在诊断和处理问题时可能会遇到一些挑战。 而MQTT 5.0则大幅扩展了Reason Code的数量和应用场景,引入了43个不同的代码,覆盖了连接、发布、订阅、取消订阅等多种操作的成功与失败情况。这些代码被分为两大类:小于0x80的表示操作成功,等于或大于0x80的表示操作失败。 MQTT 5.0 Reason Code速查表 为了便于理解和应用,以下是一些常见MQTT 5.0 Reason Codes的速查表,包括它们的含义和使用场景: Reason CodeNamePacketsDetails0x00SuccessCONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH这个 Reason Code 可以用在所有存在 Reason Code 的报文中,例如 CONNACK、DISCONNECT 报文等等。它通常用于表示成功,比如连接成功、取消订阅成功、消息接收成功和认证成功等等。0x00Normal disconnectionDISCONNECT在 DISCONNECT 报文中,0 则表示连接正常断开,这种情况下遗嘱消息不会被发布。0x00Granted QoS 0SUBACK0,1,2 在 SUBACK 这个订阅确认报文中,用来指示订阅结果,它们都表示订阅成功,同时向订阅端指示最终被授予的最大 QoS 等级,0,1,2 正好对应了三个 QoS 等级。 这是因为服务端最终授予的最大 QoS 等级,可能小于订阅时请求的最大 QoS 等级。比如订阅时请求的最大 QoS 等级是 2,但服务端最高仅支持 QoS 1 等等。0x01Granted QoS 1SUBACK-0x02Granted QoS 2SUBACK-0x04Disconnect with Will MessageDISCONNECT仅用于 DISCONNECT 报文,适用于客户端希望正常断开连接但服务端仍然需要发布遗嘱消息的情况,比如客户端希望会话过期时可以对外发出通知。0x10No matching subscribersPUBACK, PUBREC这个 Reason Code 用于向发送方指示,消息已经收到,但是当前没有匹配的订阅者,所以只有服务端可以使用这个 Reason Code。我们可以通过收到 Reason Code 为 0x10 的响应报文得知当前没有人会收到自己的消息,但是不能通过没有收到 Reason Code 为 0x10 的响应报文来假定所有人都会收到自己的消息,除非最多只会存在一个订阅者。但需要注意,没有匹配的订阅者时使用 0x10 替代 0x00,并不是一个必须实现的行为,这取决于服务端的具体实现。0x11No subscription existedUNSUBACK仅用于 UNSUBACK 报文,表示取消订阅时没有发现匹配的订阅。0x18Continue authenticationAUTH仅用于 AUTH 报文,表示继续认证,通过这个 Reason Code,客户端和服务端之间可以进行任意次数的 AUTH 报文交换,以满足不同的认证方法的需要。0x19Re-authenticateAUTH仅用于 AUTH 报文,在增强认证成功后客户端可以随时通过发送 Reason Code 为 0x19 的 AUTH 报文发起重新认证。重新认证期间,其他报文收发会正常继续,如果重新认证失败,连接就会被关闭。0x80Unspecified errorCONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT表示未指明的错误。当一方不希望向另一方透露错误的具体原因,或者协议规范中没有能够匹配当前情况的 Reason Code 时,那么它可以在报文中使用这个 Reason Code。0x81Malformed PacketCONNACK, DISCONNECT当收到了无法根据协议规范正确解析的控制报文时,接收方需要发送 Reason Code 为 0x81 的 DISCONNECT 报文来断开连接。如果是 CONNECT 报文存在问题,那么服务端应该使用 CONNACK 报文。当控制报文中出现固定报头中的保留位没有按照协议要求置 0、QoS 被指定为 3、UTF-8 字符串中包含了一个空字符等等这些情况时,都将被认为是一个畸形的报文。0x82Protocol ErrorCONNACK, DISCONNECT在控制报文被按照协议规范解析后检测到的错误,比如包含协议不允许的数据,行为与协议要求不符等等,都会被认为是协议错误。接收方需要发送 Reason Code 为 0x81 的 DISCONNECT 报文来断开连接。如果是 CONNECT 报文存在问题,那么服务端应该使用 CONNACK 报文。常见的协议错误包括,客户端在一个连接内发送了两个 CONNECT 报文、一个报文中包含了多个相同的属性,以及某个属性被设置成了一个协议不允许的值等等。但是当我们有其他更具体的 Reason Code 时,就不会使用 0x81 (Malformed Packet) 或者 0x82 (Protocol Error) 了。例如,服务端已经声明自己不支持保留消息,但客户端仍然向服务端发送保留消息,这本质上也属于协议错误,但我们会选择使用 0x9A (Retain not supported) 这个能够更清楚指明错误原因的 Reason Code。0x83Implementation specific errorCONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT报文有效,但是不被当前接收方的实现所接受。0x84Unsupported Protocol VersionCONNACK仅用于 CONNACK 报文。对于支持了 MQTT 5.0 的服务端来说,如果不支持客户端当前使用的 MQTT 协议版本,或者客户端指定了一个错误的协议版本或协议名。例如,客户端将协议版本设置为 6,那么服务端可以发送 Reason Code 为 0x84 的 CONNACK 报文,表示不支持该协议版本并且表明自己 MQTT 服务端的身份,然后关闭网络连接。当然服务端也可以选择直接关闭网络连接,因为使用 MQTT 3.1 或 3.1.1 的 MQTT 客户端可能并不能理解 0x84 这个 Reason Code 的含义。这两个版本都是在 CONNACK 报文使用 0x01 来表示不支持客户端指定的协议版本。0x85Client Identifier not validCONNACK仅用于 CONNACK 报文,表示 Client ID 是有效的字符串,但是服务端不允许。可能的情形有 Clean Start 为 0 但 Client ID 为空、或者 Client ID 超出了服务端允许的最大长度等等。0x86Bad User Name or PasswordCONNACK仅用于 CONNACK 报文,表示客户端使用了错误的用户名或密码,这也意味着客户端将被拒绝连接。0x87Not authorizedCONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT当客户端使用 Token 认证或者增强认证时,使用 0x87 来表示客户端没有被授权连接会比 0x86 更加合适。当客户端进行发布、订阅等操作时,如果没有通过服务端的授权检查,那么服务端也可以在 PUBACK 等应答报文中指定 0x87 这个 Reason Code 来指示授权结果。0x88Server unavailableCONNACK仅用于 CONNACK 报文,向客户端指示当前服务端不可用。比如当前服务端认证服务异常无法接入新客户端等等。0x89Server busyCONNACK, DISCONNECT向客户端指示服务端正忙,请稍后再试。0x8ABannedCONNACK仅用于 CONNACK 报文,表示客户端被禁止登录。例如服务端检测到客户端的异常连接行为,所以将这个客户端的 Client ID 或者 IP 地址加入到了黑名单列表中,又或者是后台管理人员手动封禁了这个客户端,当然以上这些通常需要视服务端的具体实现而定。0x8BServer shutting downDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。如果服务端正在或即将关闭,它可以通过主动发送 Reason Code 为 0x8B 的 DISCONNECT 报文的方式告知客户端连接因为服务端正在关闭而被终止。这可以帮助客户端避免在连接关闭后继续向此服务端发起连接请求。0x8CBad authentication methodCONNACK, DISCONNECT当服务端不支持客户端指定的增强认证方法,或者客户端在重新认证时使用了和之前认证不同的认证方法时,那么服务端就会发送 Reason Code 为 0x8C 的 CONNACK 或者 DISCONNECT 报文。0x8DKeep Alive timeoutDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。如果客户端没能在 1.5 倍的 Keep Alive 时间内保持通信,服务端将会发送 Reason Code 为 0x8D 的 DISCONNECT 报文然后关闭网络连接。0x8ESession taken overDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。当客户端连接到服务端时,如果服务端中已经存在使用相同 Client ID 的客户端连接,那么服务端就会向原有的客户端发送 Reason Code 为 0x8E 的 DISCONNECT 报文,表示会话被新的客户端连接接管,然后关闭原有的网络连接。不管新的客户端连接中的 Clean Start 是 0 还是 1,服务端都会使用这个 Reason Code 向原有客户端指示会话被接管。0x8FTopic Filter invalidSUBACK, UNSUBACK, DISCONNECT主题过滤器的格式正确,但是不被服务端接受。比如主题过滤器的层级超过了服务端允许的最大数量限制,或者主题过滤器中包含了空格等不被当前服务端接受的字符。0x90Topic Name invalidCONNACK, PUBACK, PUBREC, DISCONNECT主题名的格式正确,但是不被客户端或服务端接受。0x91Packet Identifier in usePUBACK, PUBREC, SUBACK, UNSUBACK表示收到报文中的 Packet ID 正在被使用,例如发送方发送了一个 Packet ID 为 100 的 QoS 1 消息,但是接收方认为当前有一个使用相同 Packet ID 的 QoS 2 消息还没有按成它的报文流程。这通常意味着当前客户端和服务端之前的会话状态不匹配,可能需要通过设置 Clean Start 为 1 重新连接来重置会话状态。0x92Packet Identifier not foundPUBREL, PUBCOMP表示未找到对应的 Packet ID,这只会在 QoS 2 的报文交互流程中发生。比如当接收方回复 PUBREC 报文时,发送方未找到使用相同 Packet ID 的等待确认的 PUBLISH 报文,或者当发送方发送 PUBREL 报文时,接收方未找到使用相同 Packet ID 的 PUBREC 报文。这通常意味着当前客户端和服务端之间的会话状态不匹配,可能需要通过设置 Clean Start 为 1 重新连接来重置会话状态。0x93Receive Maximum exceededDISCONNECT仅用于 DISCONNECT 报文,表示超出了接收最大值。MQTT 5.0 增加了流控机制,客户端和服务端在连接时通过 Receive Maximum 属性约定它们愿意并发处理的可靠消息数(QoS > 0)。所以一旦发送方发送的没有完成确认的消息超过了这一数量限制,接收方就会发送 Reason Code 为 0x93 的 DISCONNECT 报文然后关闭网络连接。0x94Topic Alias invalidDISCONNECT仅用于 DISCONNECT 报文,表示主题别名不合法。如果 PUBLISH 报文中的主题别名值为 0 或者大于连接时约定的最大主题别名,接收方会将此视为协议错误,它将发送 Reason Code 为 0x94 的 DISCONNECT 报文然后关闭网络连接。0x95Packet too largeCONNACK, DISCONNECT用于表示报文超过了最大允许长度。客户端和服务端各自允许的最大报文长度,可以在 CONNECT 和 CONNACK 报文中通过 Maximum Packet Size 属性约定。当一方发送了过大的报文,那么另一方将发送 Reason Code 为 0x95 的 DISCONNECT 报文,然后关闭网络连接。由于客户端可以在连接时设置遗嘱消息,因此 CONNECT 报文也有可能超过服务端能够处理的最大报文长度限制,此时服务端需要在 CONNACK 报文中使用这个 Reason Code。0x96Message rate too highDISCONNECT仅用于 DISCONNECT 报文,表示超过了允许的最大消息发布速率。需要注意它与 Quota exceeded 的区别,Message rate 限制消息的发布速率,比如每秒最高可发布多少消息,Quota 限制的是资源的配额,比如客户端每天可以发布的消息数量,但客户端可能在一小时内耗尽它的配额。0x97Quota exceededCONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT用于表示超出了配额限制。服务端可能会对发布端的发送配额进行限制,比如每天最多为其转发 1000 条消息。当发布端的配额耗尽,服务端就会在 PUBACK 等确认报文中使用这个 Reason Code 提醒对方。另一方面,服务端还可能限制客户端的连接数量和订阅数量,当超出这一限制时,服务端就会通过 CONNACK 或者 SUBACK 报文向客户端指示当前超出了配额。一些严格的客户端和服务端,在发现对端超出配额时,可能会选择发送 DISCONNECT 报文然后关闭连接。0x98Administrative actionDISCONNECT仅用于 DISCONNECT 报文,向客户端指示连接因为管理操作而被关闭,例如运维人员在后台踢除了这个客户端连接等等。0x99Payload format invalidCONNACK, PUBACK, PUBREC, DISCONNECT当消息中包含 Payload Format Indicator 属性时,接收方可以检查消息中 Payload 的格式与该属性是否匹配。如果不匹配,接收方需要发送 Reason Code 为 0x99 的确认报文。一些严格的客户端或者服务器,可能会直接发送 DISCONNECT 报文然后关闭网络连接。如果是 CONNECT 报文中的遗嘱消息存在问题,服务端将发送 Reason Code 为 0x99 的 CONNACK 报文然后关闭网络连接。0x9ARetain not supportedCONNACK, DISCONNECT当服务端不支持保留消息,但是客户端发送了保留消息时,服务端就会向它发送 Reason Code 为 0x9A 的 DISCONNECT 报文然后关闭网络连接。由于客户端还可以在连接时将遗嘱消息设置为保留消息,所以服务端也可能在 CONNACK 报文中使用这个 Reason Code。0x9BQoS not supportedCONNACK, DISCONNECT用于表示不支持当前的 QoS 等级。如果客户端在消息(包括遗嘱消息)中指定的 QoS 大于服务端支持的最大 QoS,服务端将会发送 Reason Code 为 0x9B 的 DISCONNECT 或者 CONNACK 报文然后关闭网络连接。在大部份情况下,这个 Reason Code 都是由服务端使用。但是在客户端收到不是来自订阅的消息,并且消息的 QoS 大于它支持的最大 QoS 时,它也会发送 Reason Code 为 0x9B 的 DISCONNECT 报文然后关闭网络连接。这种情况通常意味着服务端的实现可能存在问题。0x9CUse another serverCONNACK, DISCONNECT服务端在 CONNACK 或者 DISCONNECT 报文中通过这个 Reason Code 告知客户端应该临时切换到另一个服务端。如果另一个服务端不是客户端已知的,那么这个 Reason Code 还需要配合 Server Reference 属性一起使用,以告知客户端新的服务端的地址。0x9DServer movedCONNACK, DISCONNECT服务端在 CONNACK 或者 DISCONNECT 报文中通过这个 Reason Code 告知客户端应该永久切换到另一个服务端。如果另一个服务端不是客户端已知的,那么这个 Reason Code 还需要配合 Server Reference 属性一起使用,以告知客户端新的服务端的地址。0x9EShared Subscriptions not supportedSUBACK, DISCONNECT当服务端不支持共享订阅,但是客户端尝试建立共享订阅时,服务端可以发送 Reason Code 为 0x9E 的 SUBACK 报文拒绝这次订阅请求,也可以直接发送 Reason Code 为 0x9E 的 DISCONNECT 报文然后关闭网络连接。0x9FConnection rate exceededCONNACK, DISCONNECT用于表示客户端已超过连接速率限制。服务端可以对客户端的连接速率做出限制,客户端连接过快时,服务端可以发送 Reason Code 为 0x9F 的 CONNACK 报文来拒绝新的连接。当然这并不是绝对的情况,考虑到不是所有的客户端都会等待一段时间再重新发起连接,一些服务端实现可能会选择暂时挂起连接而不是返回 CONNACK。0xA0Maximum connect timeDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。出于安全性的考虑,服务端可以限制单次授权中客户端的最大连接时间,比如在使用 JWT 认证时,客户端连接不应在 JWT 过期后继续保持。这种情况下,服务端可以发送 Reason Code 为 0xA0 的 DISCONNECT 报文,向客户端指示连接因为超过授权的最大连接时间而被关闭。客户端可以在收到包含这个 Reason Code 的 DISCONNECT 报文后,重新获取认证凭据然后再次请求连接。0xA1Subscription Identifiers not supportedSUBACK, DISCONNECT当服务端不支持订阅标识符,但是客户端的订阅请求中包含了订阅标识符时,服务端可以发送 Reason Code 为 0xA1 的 SUBACK 报文拒绝这次订阅请求,也可以直接发送 Reason Code 为 0xA1 的 DISCONNECT 报文然后关闭网络连接。0xA2Wildcard Subscriptions not supportedSUBACK, DISCONNECT当服务端不支持通配符订阅,但是客户端的订阅请求中包含了主题通配符时,服务端可以发送 Reason Code 为 0xA2 的 SUBACK 报文拒绝这次订阅请求,也可以直接发送 Reason Code 为 0xA2 的 DISCONNECT 报文然后关闭网络连接。 使用Reason Code的注意事项 精确处理错误:利用MQTT 5.0的Reason Code,开发者可以更精确地诊断和处理连接或操作失败的原因。 优化用户体验:通过根据不同的错误代码提供更具体的错误信息或采取相应的恢复措施,可以优化最终用户的体验。 日志记录:在开发和调试过程中,记录包含Reason Code的操作可以帮助快速定位问题。 MQTT 5.0的Reason Code为MQTT协议的使用提供了更强大的错误处理能力,使得开发者能够构建更健壮、更可靠的MQTT应用。 --- ### 62. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT遗嘱消息(Last Will and Testament,简称LWT)是MQTT协议中的一个特性,允许客户端在建立连接时向服务器注册一个遗嘱消息。这个消息将在客户端异常断开连接时由服务器自动发布,通知其他客户端该客户端已离线。这个功能对于监控设备状态、实现设备断线通知等场景非常有用。 MQTT遗嘱消息的工作原理 客户端连接时指定遗嘱消息: 客户端在与MQTT服务器(Broker)建立连接时,可以指定一个遗嘱消息。这包括遗嘱消息的主题(Will Topic)、消息内容(Will Message)、消息质量(QoS)和是否保留(Retain)等信息。 服务器存储遗嘱消息: MQTT服务器接收到遗嘱消息后,会将其存储,但不立即发布。只有在满足特定条件时,服务器才会发布这个遗嘱消息。 客户端异常断开连接: 如果客户端因网络故障、设备故障或其他原因异常断开连接(不包括正常发送DISCONNECT报文的情况),MQTT服务器将判断客户端“死亡”,并自动发布之前存储的遗嘱消息。 其他客户端接收遗嘱消息: 其他订阅了遗嘱消息主题的客户端将接收到这个遗嘱消息,从而得知特定客户端已经断开连接。 使用遗嘱消息的场景 设备状态监控: 在物联网应用中,可以利用遗嘱消息监控设备的在线状态。如果设备异常断开,遗嘱消息可以通知监控系统或其他设备,采取相应措施。 用户在线状态通知: 在即时通讯应用中,遗嘱消息可以用来通知其他用户某个用户已经离线。 示例代码 以下是使用paho-mqtt客户端库(Python)设置遗嘱消息的示例: 首先,确保安装了paho-mqtt: pip install paho-mqtt 然后,创建一个MQTT客户端,设置遗嘱消息,并连接到MQTT服务器: import paho.mqtt.client as mqtt # MQTT服务器地址 broker_address = "broker.hivemq.com" # 遗嘱消息的主题和内容 will_topic = "device/status" will_message = "Device offline" # 创建MQTT客户端实例 client = mqtt.Client("ClientID") # 设置遗嘱消息 client.will_set(will_topic, payload=will_message, qos=1, retain=True) # 连接到MQTT代理 client.connect(broker_address, 1883, 60) # 进入阻塞状态,处理消息接收和发送等操作 client.loop_forever() 在这个示例中,如果客户端异常断开连接,MQTT服务器将自动发布遗嘱消息到device/status主题,消息内容为Device offline。其他订阅了这个主题的客户端将接收到这个消息,知道该设备已离线。 小结 MQTT遗嘱消息是一个强大的功能,它为客户端提供了一种机制,在无法正常断开连接时通知其他客户端或系统。这在需要高可靠性的物联网应用中尤其有用,可以帮助系统及时响应设备故障或网络问题。 --- ### 63. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT(Message Queuing Telemetry Transport)是一个轻量级的消息协议,广泛用于物联网(IoT)中设备间的通信。它支持多种消息传递模式,包括发布/订阅模式,使得数据交换变得简单高效。在MQTT协议中,保留消息(Retained Messages)是一个特殊的功能,它允许消息被保留在MQTT代理(Broker)上,直到有新的客户端订阅匹配的主题(Topic)时才被发送。 什么是MQTT保留消息? 当一个MQTT客户端向代理发布一个消息时,它可以选择将这个消息标记为“保留”。这意味着即使在消息发布之后,这个消息也会在MQTT代理上保留。当有新的客户端订阅了这个消息的主题时,这个保留的消息会立即被发送给这个新的订阅者,即使这个消息是在很久以前发布的。这样做的好处是,新的订阅者可以立即获得最新的状态更新,而不需要等待下一个状态变化的消息。 如何使用MQTT保留消息? 发布保留消息: 当客户端发布一个消息到MQTT代理时,它可以设置MQTT消息的retain标志为true。这可以通过客户端库的API完成,具体方法取决于所使用的库。例如,在Mosquitto的C库中,可以使用mosquitto_publish函数,并将retain参数设置为true。 订阅并接收保留消息: 当客户端订阅一个主题时,如果该主题有保留消息,MQTT代理会立即发送这个保留消息给客户端。客户端不需要进行任何特殊操作来接收保留消息,这是MQTT协议的标准行为。 使用保留消息的注意事项: 及时更新保留消息: 如果主题的状态发生变化,应该发布一个新的保留消息来更新状态。否则,新订阅者可能会收到过时的信息。 清除保留消息: 如果不再需要保留消息,可以通过发布一个空的消息体(payload为空)并将retain标志设置为true到相同的主题来清除保留消息。 谨慎使用: 保留消息非常有用,但如果不当使用,可能会导致意外的行为。例如,如果客户端不期望接收旧的状态信息,但主题中存在保留消息,它们将会收到这些信息。 发布保留消息 假设我们使用paho-mqtt客户端库(Python)来发布一个保留消息。首先,确保安装了paho-mqtt: pip install paho-mqtt 然后,发布一个保留消息的代码示例如下: import paho.mqtt.client as mqtt # MQTT服务器地址 broker_address = "broker.hivemq.com" # 主题 topic = "home/livingroom/temperature" # 创建MQTT客户端实例 client = mqtt.Client("Publisher") # 连接到MQTT代理 client.connect(broker_address) # 发布保留消息 # 参数:主题、消息内容、QoS、retain标志 client.publish(topic, payload="23", qos=1, retain=True) print(f"Published retained message to {topic}") # 断开连接 client.disconnect() 订阅并接收保留消息 下面是一个订阅者的示例,它订阅上面发布者使用的相同主题,并接收保留消息: import paho.mqtt.client as mqtt # MQTT服务器地址 broker_address = "broker.hivemq.com" # 主题 topic = "home/livingroom/temperature" # 当连接到MQTT代理时的回调函数 def on_connect(client, userdata, flags, rc): print("Connected with result code "+str(rc)) client.subscribe(topic) # 当接收到消息时的回调函数 def on_message(client, userdata, msg): print(f"Received message: {msg.payload.decode()} on topic {msg.topic} with QoS {msg.qos}") # 创建MQTT客户端实例 client = mqtt.Client("Subscriber") # 指定回调函数 client.on_connect = on_connect client.on_message = on_message # 连接到MQTT代理 client.connect(broker_address) # 阻塞循环,以处理接收消息和重新连接等操作 client.loop_forever() 注意事项 更新保留消息:如果主题的状态更新,应该发布一个新的保留消息以反映最新状态。 清除保留消息:通过向相同的主题发布一个空消息(payload为空字符串)并设置retain=True,可以清除保留消息。 谨慎使用:虽然保留消息功能非常有用,但在不需要旧状态信息的场景中应谨慎使用,以避免混淆和不必要的数据传输。 通过上述示例,你应该对如何在MQTT中使用保留消息有了清晰的理解。这个功能在确保新订阅者能够立即获得最新状态信息方面非常有用。 --- ### 64. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTTX 是 EMQ 推出的一款强大的开源工具,支持跨平台的 MQTT 5.0 桌面、CLI 和 WebSocket 客户端。它能够快速创建多个同时在线的 MQTT 客户端连接,便于测试 MQTT/TCP、MQTT/TLS、MQTT/WebSocket 的连接、发布、订阅功能以及其他 MQTT 协议特性。 社区站网址:https://mqttx.app/zh  Github 仓库:https://github.com/emqx/MQTTX MQTT 5.0 客户端工具 MQTTX 近期推出了 1.9.7 版本更新。此次更新的一大亮点是引入了全新的 MQTT AI 助手 MQTTX Copilot,为用户提供更方便、快捷的使用体验。AI 助手能增强互动,帮助用户更深入理解并使用 MQTT 和 EMQX。更新还包括多项错误修复,显著提升整体用户体验。 最新版本下载:https://mqttx.app/zh/downloads MQTTX Copilot MQTTX Copilot 是专为解决 MQTT 相关问题而设计的 AI 助手,为用户提供了常见问题的解决方案和最佳实践见解。通过 Copilot,用户可以测试 MQTT 连接、发布和订阅主题、进行调试以及开发 MQTT 应用与服务。它不仅简化了操作流程,还丰富了用户的 MQTT 使用体验。 开始使用前的准备 MQTTX Copilot 功能由 OpenAI 的 GPT 模型驱动,因此在使用前,您需要在 MQTTX 的设置界面底部配置 OpenAI API 密钥才能启用此功能。如需获取 OpenAI 的 API 密钥,请参考 OpenAI API Key 页面 (https://platform.openai.com/api-keys)。根据您的具体使用需求,您还可以选择合适的 GPT 模型版本,如 GPT-3.5 或 GPT-4。请确保所选模型与您的 OpenAI API 密钥相匹配。 一键错误分析 在连接或订阅过程中遇到错误时,您可以点击错误提示框中的「Ask Copilot」按钮。激活后,MQTTX Copilot 将协助您分析问题的可能原因,并帮助您逐一检查和排查,以更准确地识别并解决错误。 AI 驱动的代码生成器 MQTTX Copilot 现提供一键生成 MQTT 客户端代码,并适配和使用您当前的测试连接。此功能极大地简化了在各种编程语言中设置 MQTT 客户端的过程。目前,MQTTX Copilot 支持为多种语言生成代码,包括 JavaScript、Python、Java、Golang 等等。这一功能确保了更加流畅、高效的开发过程,使用户更容易将 MQTT 集成到他们的项目中。 MQTT 常见问题解答与 EMQX 教程 MQTTX Copilot 为用户提供了关于 MQTT 常见问题的提示和指导,以及关于安装和使用 EMQX 的全面教程,增强了用户在 MQTT 和 EMQX 方面的知识和熟练度,提供了一体化的学习体验。 自动化测试数据生成 MQTTX Copilot 简化了测试载荷的生成过程,使用户能够快速分析和优化 MQTT 数据实现。 当前连接配置分析 只需一键,MQTTX Copilot 就能分析并解读您的连接配置,提供对 MQTT 连接配置的深入见解。这一功能帮助用户理解他们的连接细节,使得 MQTT 连接的使用和管理更加高效。 除了上述功能之外,MQTTX Copilot 还允许用户自定义编辑提示信息,并通过使用  @connection  关键字快速访问连接的相关信息。这使得用户能够进行定制化设置,并且为即将推出的其他功能提供支持,如主题管理、Payload 自动填充以及 EMQX 日志分析等,增强 MQTTX Copilot 的使用体验。 修复和改进 此外,MQTTX 1.9.7 版本还包含了多种优化和修复: JSON 数据精度丢失问题(Desktop、CLI、Web) 我们提高了 JSON 消息中的数据精度。修复并解决了 JSON 消息中数据精度丢失的问题,确保了长数字型数据的准确表示(支持 BigInt)。 优化 SSL 证书选项的名称 (Desktop) 优化了 SSL 证书选项,明确区分了 CA 签名的服务器证书和 CA 或自签名证书,使选项名称更加清晰,便于用户理解和选择。 Topic-Alias 问题修复(Web、CLI) 解决了 Web 和 CLI 连接中 topic-alias 的最大值错误。此修复确保了 MQTTX CLI 能够正确接收带有主题别名的消息,并且解决了设置最大主题别名不生效的问题。 其他修复和改进 重连问题修复(桌面版):解决了断开连接后无限重连的问题。 移除未使用的占位符(桌面版):清理了代码和页面中无效的占位符。 翻译更新(桌面版、Web):改善了特定语言的翻译。 错别字修正(桌面版):更正了文档和代码中的错别字。 Web README 文档更新:改善了 MQTTX Web 的 README 文档。 特别感谢感谢 @ni00 (https://github.com/ni00)  解决了 JSON 精度和主题别名等关键问题,以及 @Rotzbua (https://github.com/Rotzbua)  在 MQTTX 中对文档和工程化问题的修复。 未来规划 MQTTX Copilot 功能增强:升级以包含流输出、Payload 自动填充、Payload 的数据分析,以及根据提示信息自动创建连接和订阅主题等。 IoT 场景数据模拟:将此功能同步到桌面客户端,简化 IoT 场景的测试。 Sparkplug B 支持:扩展 MQTTX 的功能,以包括对 Sparkplug B 的支持。 QoS 0 消息存储优化:通过可配置选项减少存储空间的使用。 MQTT 调试功能:引入协助用户调试 MQTT 通信的功能。 自动图表绘制:将接收到的消息自动转换为图表,便于更直观的分析。 插件功能:推出支持诸如 CoAP 和 MQTT-SN 等协议扩展的插件系统。 Avro 消息格式支持:引入 Avro 消息格式的编码和解码功能。 脚本测试自动化(流程):简化自动化测试工作流的创建和管理。 --- ### 65. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在物联网(IoT)不断扩展的格局中,对于高效、可扩展且可靠的通信框架的需求非常重要。MQTT,一种轻量级且健壮的消息传递协议,已成为构建物联网生态系统中设备间实时通信的首选解决方案。随着物联网部署在复杂性和规模上的增长,分片(sharding)概念登上舞台,带来了增强性能、容错能力和无与伦比的可扩展性的承诺。 在下面的2部分文章,我们将深入探讨MQTT分片集群的领域,解锁分布式系统间无缝通信的潜力。分片,即在多个节点/集群中分割数据的做法,已被证明是处理大量工作负载的改变游戏规则的做法。我们探究如何将MQTT与分片策略结合,赋予组织构建和管理其物联网应用的弹性、高性能通信网络的能力。 MQTT集群分片背后的挑战是什么? MQTT集群分片能够在可扩展性和性能方面提供显著好处,但它也带来了自己的一套挑战。 以下是一些与集群分片相关的常见挑战: 数据一致性: 在分片之间维持一致性可能是一个挑战。确保所有集群拥有一致且最新的信息至关重要,但在分布式系统中这可能相当复杂。 负载均衡: 在分片之间均匀分配负载是一个非常复杂的任务。平衡工作负载以避免某些集群过载而其他集群利用不足变得至关重要。 容错性: 在分片环境中处理故障并维持高可用性是一个挑战。如果一个分片出现故障,重要的是要有机制来重新路由流量并确保持续运行。 跨分片通信: 当连接到不同分片的设备或客户端需要通信时,可能需要进行跨分片通信。在不引入延迟的情况下有效管理这一点可能是一个复杂的任务。 弹性: 根据变化的工作负载动态调整集群大小(扩展或缩减)带来挑战。在保持系统稳定性和性能的同时增加或移除分片并不是直截了当就能处理的。 开发和维护的复杂性: 分片架构在开发、测试和维护中引入了复杂性。在分片环境中编写应用程序和管理基础设施需要更高级别的专业知识。 数据迁移: 在扩展或缩减规模,或者在节点故障的情况下,可能需要在分片之间进行数据迁移。在不引起停机或数据丢失的情况下管理这一过程是一个重大挑战。 监控和调试: 监控分片系统和调试问题可能比在非分片环境中更具挑战性。理解每个分片的状态并识别问题来源需要强大的监控工具和实践。 双向通信: 在分片的MQTT架构中保持双向通信的一致性本身可能成为一个挑战,尤其是在路由方面。 成本考虑: 分片引入了额外的基础设施和操作复杂性,这可能转化为硬件、维护和操作开销的更高成本。 解决这些挑战需要谨慎的设计、实施和持续维护工作。重要的是权衡可扩展性的好处与集群分片引入的复杂性,并选择与应用程序或系统的特定需求相符的架构。 MQTT集群分片的极限是什么? 实施MQTT部署中的分片存在一定的限制和挑战。了解这些限制以做出明智的决策并解决潜在问题至关重要。 以下是MQTT分片的一些限制: 消息排序: 分片可能会在跨分片保持消息顺序方面带来挑战。在分片环境中,来自不同分片的消息可能会以错误的顺序到达目的地,影响对消息顺序至关重要的场景。 会话持久性: 跨集群会话持久性是不可能的。如果客户端重新连接到另一个集群,它将以新会话开始。如果客户端连接时有消息在等待,您需要有一个外部服务来确保客户端即使连接到另一个集群也能正确接收消息。 跨分片通信开销: 跨分片通信可能引入额外的延迟和开销。当连接到不同分片的设备或客户端需要通信时,可能涉及跨分片通信,这可能比同一分片内的通信效率低。 跨分片的一致性: 确保分片间数据的一致性可能很复杂。在需要强一致性的场景中,管理跨分片的分布式事务和同步可能引入挑战。 开发和维护的复杂性: 分片引入了开发、测试和维护的复杂性。开发人员需要了解分片策略,并实施自定义逻辑以处理跨分片通信和潜在冲突。 受限的用例: 分片可能不适合所有用例。某些数据量低或通信模式简单的应用程序可能不会从分片中获得显著好处,增加的复杂性可能超过优势。 对现有应用程序的影响: 在现有MQTT部署中实施分片可能需要修改应用程序逻辑,并可能影响现有客户端的行为。这可能引入向后兼容性的挑战。 资源争用: 当多个分片竞争共享资源,如数据库、网络带宽或处理能力时,可能会发生资源争用。这种争用可能影响整个系统的性能和响应能力。 向下扩展的困难: 虽然为了扩展而增加分片是一个相对简单的过程,但通过移除分片来缩减规模可能更具挑战性。在缩小集群规模时,迁移数据和重新分配负载可能更加复杂。 标准化的缺乏: 分片策略通常是特定于应用的,缺乏标准化的分片机制可能使在不同MQTT部署中实施互操作解决方案更具挑战性。 运营开销增加: 管理分片环境引入了额外的运营开销。监控、故障排除和维护分片MQTT集群需要专门的知识和工具。 尽管存在这些限制,许多组织通过在MQTT部署中采用分片来实现可扩展性和性能优势。关键在于仔细评估应用程序的特定需求,考虑权衡,并实施与系统总体目标一致的分片策略。 --- ### 66. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 工厂的数字化转型已经进行了很长时间。随着工业4.0及其相关系统的网络化,确保跨系统数据交换和高效的机器对机器通信的标准变得越来越重要。 OPC UA是生产环境中最常见的通信协议之一。然而,完整实现广泛的OPC UA规范极为复杂。OPC UA基于客户端/服务器架构。当需要网络化来自不同制造商的众多异构应用程序和设备时,实施OPC UA架构具有挑战性。 基于工业物联网(IIoT)中互操作性的日益重要性,特别是与Sparkplug扩展结合使用时,MQTT提供了一个有趣的替代方案,与OPC UA相比。 MQTT是OASIS标准的物联网消息传递协议,以其极其轻量级的特性和易于实现而闻名。使用MQTT协议带来了架构的根本变化。MQTT的发布-订阅模式减少了组件的配置开销,并且通信所需的带宽更少。 Sparkplug是一个开放标准,采用了MQTT的简单性、效率和易理解性等特点。Sparkplug使用MQTT指定了基础设施内的所有系统组件如何通过MQTT代理进行双向通信。 MQTT与Sparkplug的结合降低了复杂性,特别是在运行异构生产结构时,提高了效率。维护、修理和添加新组件也大大便利。 对于现有基础设施,可以通过结合Sparkplug和MQTT来实现集成。遗留设备可以通过MQTT传感器连接到Sparkplug基础设施,并为所有组件集中提供数据。 OPC UA简介 OPC统一架构(OPC UA)是制造环境中的一种连接框架标准,于2008年作为OPC(过程控制的对象链接与嵌入)标准的继承者发布。OPC UA引入的统一架构旨在实现平台独立性。 OPC UA的目标之一是实现与设备制造商的专有API无关的设备互操作性。 OPC UA协议是制造行业中最重要的通信协议之一。典型的用例包括工业自动化和过程控制应用,以及组件之间的客户端-服务器互动,例如设备或应用程序。为了便于配置、浏览、监控和数据访问,服务器和设备的地址空间被暴露出来,以允许对位于该空间的所有对象进行查询。OPC UA还支持数据的语义描述。OPC UA客户端的请求发送到OPC服务器。OPC服务器处理请求并将响应发送回相应的OPC UA客户端。此请求-响应通信模式使用结构化数据。 OPC UA基于客户端/服务器架构,并使用TCP/IP和HTTP/SOAP作为底层技术。 OPC UA服务器转换硬件通信协议,使得通过标准化的设备模型传输设备数据。 安全性通过各种方法实现,如PKI证书、WebSocket令牌、TLS和用户名/密码认证等。 支持错误管理和异常处理,并通过不同的事件和警报进行通信。OPC UA服务包括对消息传递保证(QoS)的有限支持;然而,QoS功能并非作为一个基本概念存在。 OPC UA定义了完整的数据类型系统。 OPC UA中的资源被称为节点。构成系统的不同节点是单独可寻址的,并且可以被结构化为来自不同复杂性的结构化数据类型的数据对象。 此外,OPC UA发现服务可用于动态检测基础设施设置中的新组件。 通用设备模型在OPC UA架构中扮演着核心角色。设备制造商负责提供将通用设备模型映射到特定设备的服务器。OPC UA标准由众多单个规范组成。每个规范描述了一个子功能,并指定了服务器和客户端为支持特定功能必须实现的接口。由于不需要实现所有的单个规范,因此运行OPC UA的客户端-服务器系统必须识别客户端和服务器需要哪些规范。 不同行业的配套规范对于涉及的设备和系统有助于识别哪些规范是必要的。配套规范提供了为各个行业特定应用和相关对象创建的预定义结构。 可以通过用于网络中间件(DDS)和直接机器对机器通信(M2M)应用的网关实现或通过HTTP网关与其他服务建立通信。 服务器提供了一个面向对象的远程可调用API,实现了设备模型。可以通过标准设备模型访问设备。有几十种设备类型的设备模型,从传感器到反馈控制器。 例如,特定传感器的对象模型可以提供用于设置参数、读取数据和操作设备的方法。这些方法允许应用程序直接控制传感器,而无需了解相应制造商的确切实现。系统中的一个或多个服务器等待任意数量的客户端发送请求。当服务器收到请求时,它响应然后返回到等待状态。 如果需要,客户端可以指示服务器在服务器上发送更新。 在OPC UA中,客户端决定服务器何时以及从底层系统中检索哪些数据。例如,即使服务器订阅了定期状态更新,客户端也可以决定服务器多久轮询一次设备和系统。 OPC UA的功能,如浏览或读取元信息以及在监视列表中灵活组织变量,使得从外部查看和监控机器变得更加容易。 然而,当连接来自不同制造商的众多异构应用程序和设备时,实施OPC UA架构的挑战增加。OPC UA规范长达1200多页,预示着完整实现可能会有多么广泛。完整的实现不仅在开发和支持成本方面代价高昂,而且由于OPC UA对设备的CPU要求显著提高,也代价高昂。 实施多个消费者所需的一对多构型和高度灵活的发布-订阅架构是问题所在。由于底层架构,无法实现真正的数据解耦。连接到基于云的应用程序也可能被证明是复杂的或需要高实施努力。 以下是OPC UA的基本特征总结: 客户端-服务器架构 通过使用TCP / HTTP作为传输协议实现平台独立性和互操作性 使用TLS和证书的安全性 完全定义的数据类型设置 固定结构数据对象和端点 预定义的行业特定规范库 发现服务可用 网关兼容性 传统OT / IT基础设施与OPC UA 生产环境中的典型架构包括大量的设备、传感器和网关,这些设备可能通过不同的协议进行通信。每个实体都通过直接的双向连接提供其数据或受到控制。在OPC UA中,没有“单一真理源”。来自操作生产区域的任何数量的OPC UA服务器都可以直接与所有其他操作技术(OT)参与者进行通信。每个OT参与者反过来可以作为客户端或服务器与信息技术(IT)领域的一个或多个OPC UA客户端进行工作。 MQTT简介 如果你想绕过复杂性,转向一个保证在工业自动化中安全可靠数据交换的精简解决方案,你将不可避免地遇到MQTT协议。作为OASIS标准,MQTT 5协议提供了一个被普遍认为是物联网的事实标准的规范。 MQTT协议特别轻量级的核心原则是发布-订阅模式。这种模式允许任意数量的数据消费者订阅个别主题或主题领域,并接收关于它们的发布消息。 MQTT的精简性特别适合于非常低资源的设备和低带宽、不可靠或高延迟网络中的通信。 MQTT架构通过发布-订阅协议实现与无限数量的客户端通信。 鉴于MQTT规范的许多详细描述,例如MQTT 5基础系列,本文仅关注与OPC UA相比较感兴趣的MQTT方面。 MQTT的重要特点包括: 轻量级,基于TCP 发布/订阅架构 安全 有状态的会话使用 数据不可知 高度动态主题 消息交付保证 遗嘱和保留消息概念 MQTT 5功能 引入语义元数据,如用户属性、有效载荷指示器或内容类型描述符 请求-响应模式 共享订阅 否定确认 消息和会话过期时间按客户端设置 等等 生产环境中的MQTT基础设施 使用发布-订阅协议,如MQTT和消息代理作为中心组件,代表了架构的根本变化。 所有消息都通过中心MQTT代理发送,所有MQTT客户端都连接到代理,并可以订阅特定主题。 MQTT代理承担了服务器的任务,处理与无限数量的MQTT客户端的每一次通信。 MQTT客户端直接在网关、设备或应用程序中实现,所有客户端都是松散耦合的。客户端之间没有直接关系。除了功能要求外,MQTT代理还处理诸如冗余、故障转移、高可用性和可伸缩性等需求。 MQTT与OPC UA的比较 MQTT的发布-订阅架构与OPC UA的客户端-服务器基础架构显著不同。 MQTT的中心组件始终是一个MQTT代理。代理负责完全实现MQTT规范。特别是在MQTT 5功能方面,代理的符合水平各不相同。由于MQTT 5规范中的许多功能是可选的,一些代理没有实现MQTT 5提供的所有功能。在云领域,支持水平的不同尤为相关。 会话的使用允许MQTT客户端的数据超出客户端连接的持续时间而持久化。例如,订阅、离线消息或在代理处为离线客户端存储的额外信息在客户端重新连接时立即可用。 在此处呈现的上下文中的另一个本质上的不同是在数据不可知方面。MQTT协议在规范层面上不对数据类型施加限制。因此,MQTT协议可以用于传输广泛多样的数据类型。 这种完全自由也适用于主题。除了语法要求外,MQTT主题不受任何规范的约束。主题是动态的,不必事先指定或创建。只有在MQTT客户端订阅主题以消费传入消息的上下文中,主题才存在。如果在没有MQTT客户端订阅的主题上发布消息,代理最终将丢弃该消息。 为了保证在稳定连接下完整传输消息,MQTT使用TCP作为传输协议。由于MQTT主要为不稳定的网络而设计,因此指定了三个服务质量水平(QoS),即QoS 0、1和2。MQTT消息的交付保证概念是MQTT与OPC UA的另一个显著不同之处。 MQTT中的保留消息原则对于生产环境也非常有用。此功能允许在每个主题上存储特定消息。保留消息确保每个订阅该主题的客户端都可以立即接收保存的消息。 MQTT遗嘱概念的同样重要性适用于指定客户端连接期间的消息,以便在发生离线事件时发送。遗嘱消息的一个典型用例是从客户端传输状态信息。 MQTT 5还引入了用户属性,使得在MQTT数据包中自由传输元信息成为可能,而不使用有效载荷。用户属性提供了一种简单有效的变量,用于交换元信息。 与OPC UA相比,简洁的80页MQTT规范易于实现,不定义固定结构或数据类型。 IIoT转型挑战 工业领域的数字化转型是当前影响代表全球三分之二GDP的公司的全球性趋势。随着IIoT的出现,传统流程经过200年的建立正处于深刻变革之中。因为数字化已成为保持竞争力的决定性因素,改变是必然的。 物联网或M2M通信必须具备传统人类基于HTTP的互联网的速度和简单性。当前的挑战是快速高效地实施灵活且可扩展的IIoT系统,这些系统易于设计和维护。 IIoT的挑战包括: 将新设备添加、适应和集成到现有系统中 根据报告的值更新设备配置 更改测量、处理或数据交付工作流 在组件较少的系统中,尤其是当使用SCADA主机作为面向消息的中间件时,运营工厂所需的维护工作仍然可控。 然而,需要多个主机应用程序和连接到其他企业IT组件的系统变得非常复杂。这种复杂性导致了巨大的手动配置和维护负担。由于底层架构模式,每个组件都必须使用请求/响应方式与SCADA主机通信。 当存在多个SCADA主机时,复杂的基础设施创造了以下条件: 分离的 集成点 每个点都必须通过请求/响应模式进行轮询 将新设备集成到现有系统中的复杂性增加 使用物联网提高生产线效率的原始目标在这类复杂系统中难以实现,因为每次设备更新的维护工作与基础设施设置成线性关系。 MQTT和OPC UA的结论 MQTT规范的概念非常适合用于生产的数字化。 MQTT提供的“单一真理来源”和通过中心消息组件解耦数据的优势显著。 安全性可以像在OPC UA中一样快速且多种方式实现。 客户端状态是参与组件的一个重要且固有的特性,可以通过MQTT功能完美实现。 网关可以作为集成器,连接需要其他协议的设备。 剩下的问题是如何最好地应用轻量级MQTT协议,以满足工业自动化的互操作性要求。 Sparkplug简介 为了满足工业自动化的互操作性要求,必须定义基于MQTT的实施标准。提供这种定义是Sparkplug的目标。 Sparkplug是Eclipse Foundation的Sparkplug工作组的一个项目。Sparkplug提供了一个开放且免费可用的规范,描述了边缘网关、原生MQTT支持的端点和基础设施中的MQTT应用程序如何通过中心组件(MQTT代理)双向通信。 Sparkplug是一个规范,定义了MQTT如何用于关键任务、实时OT环境中。它建立了一个标准,针对使用SCADA、标签和度量表示的工业应用案例进行了优化。该规范描述了如何在实时SCADA实现中最佳使用这些原则。 Sparkplug规范旨在实现三个目标: 定义主题命名空间MQTT自由且动态使用主题名称是一个关键优势。然而,当在生产环境中使用MQTT时,必须指定本体。本体共享使用术语,并映射主题空间中所有设备和应用程序之间的关系。 规定有效载荷数据结构类似于主题命名空间的规范,当在生产环境中使用MQTT时,必须定义消息内容(有效载荷)的模式。这个模式定义可以通过原生的MQTT 5概念完美实现。 定义状态管理由于MQTT最初是为了监控实时系统而开发的,因此从一开始,协议的一个主要关注点就是处理网络故障、低带宽和高延迟。例如,通过充分使用会话功能。 Sparkplug规范的目的是将MQTT的强点(如简单性、易于实施和操作)与OT要求相结合。Sparkplug为所有参与方定义了一个本体,以保证客户端会话管理,并将消息大小保持在最小。 Sparkplug规范为开发人员和架构师提供了明确的指导,用于设计主题命名空间和结构化有效载荷数据,以及维护和传达客户端状态的方法。 Sparkplug在IIoT环境中的MQTT基础设施 在Sparkplug架构中,设备、EoN节点和SCADA/IIoT主机连接到中心MQTT代理以发布和订阅数据。 作为中心组件,MQTT代理必须100%支持MQTT标准。这是一个重要的考虑,限制了像亚马逊网络服务(AWS)或Azure IoT Hub等云提供商的适用性,因为这些供应商不完全支持MQTT协议,而是使用协议的专有版本。 除了完全支持MQTT协议外,具有故障安全、高可扩展性和集群能力的代理需要提供度量、监控和报警接口,以便可以最佳地监控所涉及的所有系统组件。 除了MQTT代理之外,使用Sparkplug的基础设施还包括以下组件: SCADA/IoT主机是系统操作员用来管理和监控整个系统状态的中心应用程序。这个应用程序直接与MQTT代理作为特定的MQTT客户端进行交互。与传统的SCADA系统架构相比,使用Sparkplug时,SCADA/IoT主机不负责直接建立或维护与设备的连接。 网络边缘(EoN)节点在每个Sparkplug基础设施中扮演关键角色。通常,EoN节点用于将遗留基础设施连接到Sparkplug。遗留基础设施元素可以通过其他协议(如OPC UA、Modbus或专有的PLC制造商协议)与EoN节点通信。EoN节点负责管理自己的状态和设备的状态,以及从设备接收和发送数据到Sparkplug基础设施。 设备和传感器是工业自动化的支柱。在Sparkplug的背景下,设备通过EoN节点连接到Sparkplug基础设施。尽管大多数设备和传感器使用诸如Modbus、OPC UA和各种其他标准化或专有协议,但许多供应商现在提供原生支持MQTT的设备和传感器。如果MQTT支持的设备已经配备了Sparkplug,它可以直接参与基础设施。在这种情况下,设备作为Sparkplug基础设施的一个EoN节点进行标识。如果设备支持标准的MQTT而不带Sparkplug检测,则仍必须建立与EoN节点的连接。 MQTT应用程序,或次要应用程序,是参与Sparkplug通信的组件,可以生成和处理MQTT消息,但不是SCADA / IIoT主机。 结论 所有MQTT客户端,特别是SCADA主机和IT应用程序,都订阅了希望接收信息的主题。由于明确定义了主题结构和数据对象,每个MQTT客户端都知道可以从哪里以及以何种形式检索信息。由于MQTT客户端是有状态的,信息不会在任何时候丢失。特定信息的消息类型是规定的。 Sparkplug主题结构 遵循Sparkplug B规范的每个MQTT客户端都使用预定义的结构来定义主题命名空间,可以定义如下: namespace/group_id/message_type/edge_node_id/[device_id] NAMEDESCRIPTIONEXAMPLEnamespaceRoot element that sets the Sparkplug versionspBv1.0group_idLogical grouping for MQTT edge nodesmachine-groupmessage_typeThe message typemqtt-edge-1edge_node_idOne edge nodeNBIRTH Sparkplug规范定义了几种消息类型。 不同的消息类型可以传输元数据以及关于设备状态的信息。 Sparkplug消息类型 节点和设备的出生和死亡证明 出生消息宣布一个MQTT客户端在线。设备或节点本身在出生主题上向整个系统提供这一信息。此类消息在建立连接后立即发送。EoN节点发送NBIRTH消息,设备发送DBIRTH消息。 为了确保即使在发送消息时不在线的设备或应用程序也可以接收到这些消息,这些消息作为保留消息发送。这种方法允许稍后登录到特定主题的组件接收消息。 DEATH消息用于传达设备或EoN的离线状态。MQTT客户端连接包中的遗嘱(LWT)和保留消息功能用于实现这一概念。LWT消息由代理管理。如果客户端失去连接,代理会将LWT消息发送到相应的DEATH主题。这种方法也允许传输客户端的离线状态。当客户端以有序方式使用DISCONNECT包注销时,在连接结束之前,离线状态将作为保留消息发布到DEATH主题。EoN节点发送NDEATH消息,设备发送DDEATH消息。 使用出生和死亡消息类型,具有特定有效载荷并用于主题结构中,可以统一实现EoN节点和设备的状态管理。 客户端状态的元数据也随之传输。通过出生消息传输元数据,可以精确定义客户端在其生命周期中发送的信息的模式或模板。这让消费MQTT客户端(在本例中为SCADA主机)知道可以期望来自相应设备或EoN的什么信息。 节点和设备的数据消息 此消息类型用于传输测量数据和某些设备属性。仅传输自上一个设备或EoN的数据消息或出生消息以来的信息状态更改。因为只发送更新,所以通信负载保持非常低。发布-订阅架构消除了轮询更改的需求,因为更改主动发送给订阅该主题的所有订阅者。 节点和设备的命令消息 此消息类型用于向EoNs或设备传输更新。MQTT消息的相关有效载荷中包含时间戳和必须写入设备的度量值等内容。 主应用程序的状态状态消息 当使用集群能力强、动态可扩展的MQTT代理时,状态消息类型是可选的。此消息类型旨在用于在实施多个并行、非集群能力代理的基础设施中使用Sparkplug。STATE消息用于通过相应的namespace/group_id/STATE/scada_host_id主题传输SCADA IIoT主机的出生消息。EoNs在启动时订阅此主题,以消费来自主机的信息。 Sparkplug消息内容 通过定义命名空间,主题结构在语义上与要传输的信息相关联。 Sparkplug B规范支持实时数据的高效传输。有效载荷可以用不同的数据类型定义: 复杂数据类型 数据集 丰富的度量值 包括元数据的数据 度量别名 历史数据 文件数据 有效载荷数据在Sparkplug B中以Protobuf格式进行分层结构编码。 有效载荷由一个结构化记录组成,至少必须包含发送时间戳(UTC)、一个度量值和一个序列ID。 名称和时间戳是必须的。标志是可选的,可用于指示特定数据。例如,“is_null”表示没有发送数据。自定义数据可以存储在属性中,作为键值对列表,或在body对象中。 报告异常(RBE)概念是MQTT和Sparkplug RBE的另一个重要方面,确保只发送与前一情况相关的更改。这种方法大大减少了数据量。对于特定消息类型,可以在会话开始时发送描述消息内容完整模式和初始值的有效载荷模板。基于模式,只有更改被发布并由消费MQTT客户端解读。 Sparkplug状态管理 除了定义主题结构和内容外,还必须定义状态管理的概 念。MQTT的使用有效地解决了这一要求。参与系统的MQTT客户端在建立连接时使用会话。通过结合Sparkplug出生和死亡消息以及MQTT遗嘱和保留消息,系统中的每个客户端都可以映射其状态。 状态的提供由各个组件负责,并通过MQTT代理获得。 SCADA主机状态管理 在示例中,系统的所有组件都可以通过订阅spv1.0/g1/STATE/scada1主题来获取SCADA主机的当前状态。只发布状态的更改。由于在主题上使用保留消息,最后的信息被保留,以便新添加的客户端获得信息。在消息丢失的情况下,代理会将LWT消息作为保留消息发布到主题。SCADA主机还订阅了上下文中涉及的所有设备,以便接收来自EoNs及其设备和其他MQTT应用程序的所有消息。这可以进一步限制为一个组。 EoN节点的状态管理 EoN节点的在线状态也使用LWT和保留消息实现。使用消息类型NDEATH和NBIRTH。通过订阅SCADA主机的STATE主题,EoN节点随时了解一个或多个主机的状态。通过订阅NCMD主题,EoN节点接收所有相关的控制信息。订阅DCMD主题用于接收与EoN链接的设备的控制信息,并将信息传输给设备。EoN节点的数据通过NDATA消息类型发送。 通过EoN节点的设备状态管理 与EoN连接的设备和传感器的通信由EoN节点处理。设备的在线和离线信息通过设备特定主题的保留消息传输。设备的数据被打包到数据消息中,并在相应主题上发布。所有注册在该主题上的MQTT客户端都接收到测量数据。 消息代理选择 在MQTT中,消息代理是所有消息通过其发送并且所有MQTT客户端订阅特定主题的中心组件。 Sparkplug规范基于MQTT的属性和特性。正如本文“Sparkplug在IIoT环境中的MQTT基础设施”部分所讨论的,使用完全支持MQTT协议的代理是至关重要的。 使用多个单独的代理来保证故障安全性,如Sparkplug规范中所描述的,是不必要的,当使用像HiveMQ这样具有集群能力、高可用性和故障安全的MQTT代理时。使用集群能力代理还使状态管理比规范中描述的要简单得多。从外部看,具有集群能力的代理被视为一个逻辑单元,消除了指定或识别组件连接到哪个代理的需要。 Sparkplug和OPC UA的结论 MQTT规范的概念非常适合用于生产的数字化。 MQTT所提供的“单一真理来源”和通过中心消息组件解耦数据的优势是显著的。MQTT协议支持多样化的安全选项,可以快速实现,且具备用于状态管理的现成工具。客户端状态是参与组件的一个重要且固有的特征,可以通过MQTT功能无缝实现。此外,MQTT的固有速度和低开销对于实时IIoT运营非常理想。 Sparkplug规范基于MQTT,创建了一个专为IIoT系统要求量身定做的框架。例如,为使用OT定义标签值所需的上下文数据提供支持。通过只发送数据变化并使用发布-订阅模式,显著减少了网络流量。使用编码和压缩数据格式的消息有效载荷进一步节省了网络资源。 这项比较研究突出显示了MQTT和Sparkplug相比于OPC UA或HTTP所提供的极大带宽节省。 为数据和主题定义的本体确保发送的信息可以被IT结构的组件解读,而无需进一步的元信息。这种对数据和主题设计的统一方法使制造商能够交付符合规范的设备。更一致的一致性使得在IIoT中配置和使用设备变得更加容易、快速且最终更具成本效益。 在使用面向消息的中间件(如MQTT代理)的架构中集成设备,比在复杂的客户端-服务器结构中要容易得多。系统中的每个组件只与代理通信。不需要额外的配置。 即使OPC UA和MQTT在数据处理方式上有显著差异,它们仍然可以一起工作。一些旧设备需要OPC服务器,并应保持连接到Sparkplug基础设施。通过使用连接到旧设备的MQTT兼容传感器,可以使用MQTT和Sparkplug使这些数据在IT的所有组件中中央可用。 总结而言,MQTT和Sparkplug提供了一种高效且灵活的方法,用于在工业环境中处理数据和通信,特别是在考虑到实时数据和设备管理的IIoT应用中。与传统的OPC UA相比,它们提供了更高的效率和更低的复杂性,同时也提供了丰富的功能,适合于现代工业自动化和数字化需求。 --- ### 67. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 TuyaLink 协议是涂鸦 IoT 开发平台面向物联网开发领域设计的一种数据交换规范,数据格式为 JSON,主要用于设备端和涂鸦 IoT 开发平台的双向通信,更便捷地实现了设备端和平台之间的业务数据交互。 设备的通信方式也是多种多样的。无线通信方式有蓝牙 LE、Zigbee、蓝牙 Mesh、433 协议,有线通信方式有 RS-485、RS-232、以太网以及各种工业协议等。但通信只是建立一个数据通道,要想真正运作起来,还需要了解数据包格式协议。数据协议包括 OCPP、Modbus、工业标准协议和其他自定义协议等。 本文介绍的 Tuya MQTT 标准协议是其中一种协议,也是涂鸦物联网平台最底层的基础通讯协议。开发者可根据协议完全自主地进行嵌入式开发,该协议可支持所有设备的集成。 本文以一款常见的 MQTT 客户端 MQTT.fx 为例,模拟设备使用涂鸦开放的 MQTT 协议接入涂鸦云。 MQTT 接入点 涂鸦 IoT 开发平台支持全球多个区域的设备接入,故需要根据设备实际使用的区域,来选择对应的接入点。 全球 6 大区 MQTT 接入点如下: 区域MQTT 接入域名端口号中国数据中心m1.tuyacn.com8883中欧数据中心m1.tuyaeu.com8883美西数据中心m1.tuyaus.com8883美东数据中心m1-ueaz.tuyaus.com8883西欧数据中心m1-weaz.tuyaeu.com8883印度数据中心m1.tuyain.com8883 环境准备 在 涂鸦 IoT 开发平台 创建产品,获取如下参数值。详细创建产品的过程请参考 选品类创建产品。 参数名称参数说明ProductID产品的信息DeviceID设备的身份信息,用于连接云端授权和通信使用DeviceSecret设备的密码信息 ,用于连接云端授权使用 接入示例 配置 MQTT.fx 接入文件 1.在 MQTT.fx 官网下载并安装相应操作系统版本的 MQTT.fx 客户端。 2.打开 MQTT.fx 软件,单击菜单栏中的 Extras 选项,并选择 Edit Edit Connection Profiles。 3.在 Edit Edit Connection Profiles 页面中填写相关参数。 参数名称参数说明Profile Name输入您的自定义名称Profile TypeMQTT 服务器连接,选择 MQTT BrokerBroker AddressMQTT 接入域名,对应 MQTT 协议中的域名,此处以中国区域名 m1.tuyacn.com 为例Broker Port通信端口号,设置为 8883Client IDMQTT 协议字段,格式为 tuyalink_{$deviceid}General使用默认值即可 4.选择 User Credentials 并填写相关参数。 参数名称参数说明User Name${deviceId}|signMethod=hmacSha256,timestamp=${当前 10 位时间戳},secureMode=1,accessType=1;例如:6c828cba434ff40c074wF2|signMethod=hmacSha256,timestamp=1607837283,secureMode=1,accessType=1PasswordhmacSha256(content, deviceSecret),content 的值"deviceId=6c828cba434ff40c074wF2,timestamp=1607635284,secureMode=1,accessType=1",按照 deviceId,timestamp,secureMode,accessType 这个顺序组装明文内容。64 位字符的 16 进制数,不足 64位时前面需要补零。 此处涉及到的 DeviceID 和 DeviceSercet 信息在 IoT 平台注册设备时生成,可参考 环境准备 章节找打到相应参数,Password 加密信息可以通过 Hmac 在线计算工具生成。示例如下: 5.选择 SSL/TLS,选中 Enable SSL/TLS 并设置 Protocol 为 TLSv1.2。 6.单击右下角 OK 完成设置,再去主页面单击 Connect。等待右侧指示灯变绿,表示连接成功。 测试通信 上行通信 在 Publish 页面输入发布的 topic,并填写 payload 信息,点击 Publish,此处以 tylink/6c855a6e81c40a91e9k5gx/thing/model/get topic 为例进行介绍。 进入涂鸦 IoT 开发平台的设备日志页面,输入 DeviceID 信息,可以看到刚才发布的消息,证明上行通信已经成功。 下行通信 在 Subscribe 页面输入 topic,点击 Subscribe,客户端会出现一条订阅的信息,此处以 tylink/6c855a6e81c40a91e9k5gx/thing/property/get_response topic 为例进行介绍。 进入 Publish 页面,输入与订阅对应的 topic 信息,并点击 Publish 发布 返回到 Subscribe 页面,可以看到刚才订阅的 topic 收到了云端的信息。 总结 涂鸦IoT平台的Tuya MQTT标准协议是一种基础通讯协议,用于支持各种设备的集成。文章以MQTT.fx客户端为例,介绍了如何使用涂鸦的开放MQTT协议接入涂鸦云。涂鸦IoT平台为全球多个区域提供设备接入支持,因此需要根据设备所在区域选择相应的MQTT接入点。文章还详细描述了如何在MQTT.fx中配置接入设置,包括Broker地址、端口、客户端ID、用户凭证和SSL/TLS设置。这一流程旨在帮助开发者理解并实现设备与涂鸦云之间的有效通信。 --- ### 68. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 在数字化时代,随着物联网(IoT)和智能设备的快速发展,有效的数据传输和网络管理成为了关键挑战。这些设备不断地产生大量数据,如果不加以管理,很容易导致网络拥塞,影响数据传输效率和可靠性。在众多解决方案中,消息队列遥测传输(MQTT)协议突显其重要性。作为一种轻量级的消息通信协议,MQTT被广泛应用于物联网领域,特别是在需要低功耗和低带宽环境中。 MQTT的设计初衷是为了简化和优化设备与服务器之间的通信,特别是在网络条件不稳定或资源受限的情况下。其核心组件——MQTT代理(Broker),在管理网络拥塞和确保消息有效传递方面发挥着至关重要的作用。通过利用不同的服务质量(QoS)级别和保持活动(Keep Alive)机制,MQTT代理能够有效控制消息流,防止网络过载,同时保持消息传输的高效率和可靠性。 本文将深入探讨MQTT代理如何通过其独特的功能和机制,应对网络拥塞这一常见而复杂的问题。我们将分析MQTT协议的工作原理,探讨其在网络拥塞管理中的优势和挑战,并展望未来在物联网和智能设备领域中的应用前景。通过这一探讨,我们希望为读者提供关于MQTT代理的全面认识,以及其在现代通信网络中不可或缺的地位。 第一部分:网络拥塞的基本原理 1.1 网络拥塞定义和原因 网络拥塞发生在数据传输网络的容量临时不足以处理传入的数据量时。类似于车辆在高峰时段堵塞在道路上,数据包在网络中的传输也会因为过量的流量而变得缓慢或者完全停止。网络拥塞的原因多种多样,包括但不限于网络带宽不足、服务器过载、不恰当的网络配置或突发的大量数据传输需求。 1.2 拥塞对物联网和通信网络的影响 在物联网(IoT)和通信网络中,网络拥塞不仅会导致数据传输速度降低,还可能引发数据包丢失和通信中断。对于需要实时或近实时响应的应用,如在线游戏、视频会议或关键的工业自动化控制,这些延迟和中断可能会带来严重的后果。在物联网环境中,大量的设备同时发送数据到网络上,如果没有适当的管理和控制,网络拥塞将是一个不可避免的问题。 1.3 网络拥塞管理的传统方法 网络拥塞管理的传统方法包括增加带宽、使用流量管理工具以及实施更有效的数据传输协议。增加带宽可以暂时解决拥塞问题,但成本较高且不一定可持续。流量管理工具,如路由器和交换机的QoS(Quality of Service)设置,可以帮助优先处理关键数据包,减少拥塞的影响。此外,有效的数据传输协议,如TCP/IP,通过控制数据包的发送速率和确认机制来减少网络拥塞的可能性。 第二部分:MQTT协议概述 2.1 MQTT协议的工作原理 消息队列遥测传输(MQTT)是一种轻量级的消息协议,专为低带宽和不稳定网络环境设计,广泛应用于物联网领域。MQTT基于发布/订阅模型工作,其中客户端可以订阅特定主题,而发布者发送的消息将被MQTT代理转发给订阅了相应主题的所有客户端。这种模型降低了网络带宽的需求,并提高了消息传递的效率。 2.2 MQTT与其他通信协议的比较 与传统的HTTP协议相比,MQTT在处理大量并发连接和保持低延迟通信方面更加有效。它的轻量级特性使得它特别适合用于带宽有限或网络条件不稳定的环境,如移动设备和各种物联网设备。MQTT协议的设计注重资源的高效使用,对设备的电量和网络带宽消耗较小,这是其在物联网设备中广泛应用的关键原因。 2.3 MQTT在物联网中的应用案例 MQTT在物联网中的应用案例众多,从智能家居到工业自动化,都可以找到其身影。例如,在智能家居系统中,各种传感器和智能设备可以使用MQTT协议来实时传输数据,如温度、湿度或运动数据到中央控制系统。在工业环境中,MQTT被用于传输机器状态数据或报警信息,以实现远程监控和维护。 第三部分:MQTT代理的核心功能 3.1 MQTT代理的定义和作用 MQTT代理(Broker)是MQTT协议中的核心组件,它扮演着消息的中介者角色。代理的主要职责是接收来自发布者(Publisher)的消息,根据订阅者(Subscriber)的订阅主题分发这些消息。MQTT代理支持多级别的服务质量(Quality of Service,QoS),处理大量并发的客户端连接,同时保持低延迟和高效率的消息传输。 3.2 QoS级别的详细介绍 在MQTT协议中,QoS级别决定了消息传输的保证程度: QoS 0(At most once):消息最多被传递一次,可能会丢失,但不会重复传输。 QoS 1(At least once):确保消息至少被传递一次,可能会有重复。 QoS 2(Exactly once):确保消息只被传递一次,提供最高级别的可靠性。 3.3 保持活动机制的工作原理 保持活动(Keep Alive)机制是MQTT协议中一个重要的特性,用于维护客户端与代理之间的连接。客户端定期发送一个PING请求到代理,以表明它“活着”并维持连接。如果在预定时间内未收到PING请求,代理会认为连接已断开,并据此清理相关资源。 第四部分:MQTT代理如何管理网络拥塞 4.1 使用QoS级别控制消息流 在网络拥塞的情况下,MQTT代理通过灵活应用不同的QoS级别来管理消息流,以此减轻网络的负担。例如,对于不那么关键的数据,可以使用QoS 0来减少重传,而对于必须确保传递的重要消息,则可以使用QoS 1或QoS 2。这种差异化服务确保了网络资源的合理分配和有效利用。 4.2 保持活动机制在拥塞控制中的作用 保持活动机制在网络拥塞时尤其重要。在网络条件不稳定或拥塞时,通过调整PING请求的频率,可以有效减少不必要的网络流量,同时保持客户端与代理之间稳定的连接。这样,即使在网络负载较高的情况下,MQTT代理也能维持高效的通信。 4.3 MQTT代理在消息队列和流量控制中的策略 MQTT代理还通过消息队列和流量控制来管理网络拥塞。在高流量情况下,代理可以暂存消息到队列中,然后根据网络状况和客户端的处理能力逐步发送。这种策略可以防止突发的大量数据一次性淹没网络,帮助平滑数据流量,从而有效管理网络拥塞。 第五部分:MQTT代理的优势与挑战 5.1 MQTT代理在网络拥塞管理中的优势 高效的资源利用:MQTT代理通过QoS级别和保持活动机制有效利用网络资源,减少不必要的数据传输,从而提高总体网络效率。 可扩展性:MQTT设计考虑到了大规模部署,使其能够轻松应对成千上万的设备同时连接的情况,这在物联网应用中尤为重要。 灵活性:代理能够根据网络条件和客户端需求调整消息传输策略,提供灵活的通信解决方案。 可靠性:通过不同的QoS级别,MQTT代理能够确保消息的可靠传递,即使在网络状态不佳的情况下。 5.2 与传统拥塞管理技术的比较 相比于传统的拥塞管理技术,如TCP的拥塞控制,MQTT提供了更高的灵活性和效率,尤其在处理大量低功耗和低带宽设备的场景中表现更佳。MQTT专为避免和减轻网络拥塞而设计,因此在物联网这样的环境中更能发挥其优势。 5.3 MQTT代理面临的挑战和限制 安全性问题:随着设备数量的增加,确保每个通信会话的安全成为一大挑战。 数据一致性:在使用QoS 0时,由于消息可能丢失,保持数据一致性成为一个问题。 复杂的网络环境适应性:在极端或特殊的网络条件下,维持MQTT代理的高效运行可能需要额外的策略和技术支持。 第六部分:未来展望与改进 6.1 MQTT在未来通信网络中的潜在发展 随着物联网设备数量的增长和5G网络的普及,MQTT有望在未来的通信网络中扮演更加重要的角色。预计将看到MQTT在更多领域的应用,如智能城市、工业4.0、远程医疗等。 6.2 技术改进和创新方向 增强安全性:随着技术的发展,MQTT协议需要集成更强大的安全机制来保护数据传输。 改善数据一致性机制:开发更高效的算法来确保即使在低QoS级别下也能保持数据一致性。 适应复杂网络环境:优化MQTT协议,使其更好地适应各种复杂和变化的网络环境。 6.3 物联网和大数据时代下的拥塞管理新策略 未来,随着物联网和大数据时代的到来,网络拥塞管理将需要新的策略和技术。这可能包括使用人工智能来预测和管理网络流量,或者开发更高效的数据传输协议来适应快速变化的网络需求。 结论 MQTT代理作为一种高效、灵活且可扩展的网络通信机制,在物联网和其他通信网络中扮演着至关重要的角色。尽管存在挑战,但其在未来的发展前景仍然广阔,特别是在改善网络拥塞管理方面的潜力。 --- ### 69. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在环境意识日益增强和可持续实践势在必行的时代,绿色IT(信息技术)和绿色OT(运营技术)领域已成为更加环保和负责任的技术景观的关键贡献者。随着全球社会努力应对气候变化、资源枯竭和环境退化带来的挑战,在“绿色”举措的旗帜下IT和OT的融合对于寻求将其运营与生态原则保持一致的企业和行业至关重要。 绿色IT专注于以最小化环境影响的方式设计、实施和管理信息技术系统。这包括一系列策略,从能源高效的数据中心和可持续的硬件设计到电子废物的负责任处理和回收。绿色IT的目标不仅是减少数字基础设施的碳足迹,还包括优化资源利用并在技术整个生命周期中促进能源节约。 与此同时,绿色OT将可持续性原则扩展到运营技术,强调工业和制造过程中的环保实践。这涉及整合能源高效技术、采用清洁和可再生能源,以及提高制造和生产系统的整体环境性能。绿色OT致力于使工业运营与生态管理协调一致,促进一种考虑整个供应链和工业活动长期生态影响的全面方法。 绿色IT和绿色OT共享共同目标,寻求在技术进步与环境责任之间找到平衡。通过利用创新解决方案,如虚拟化、云计算和物联网(IoT),这些领域旨在提高效率、减少浪费,并最小化与数字和工业过程相关的碳足迹。绿色IT和绿色OT之间的协同作用为组织提供了一个独特的机会,不仅增强其可持续性概况,还通过环境意识的实践推动创新和经济增长。 实现基于MQTT的绿色IT/OT系统的互操作性 在这个系统相互连接和技术迅速发展的时代,HiveMQ将自己定位为OT和IT之间的理想桥梁,利用MQTT协议的优势,为两者提供一个可靠、高性能的数据路由平台。 为了优化绿色OT(运营技术)和绿色IT(信息技术)的MQTT架构,需要采取重视能源效率、资源节约和环境可持续性的策略。MQTT是一种轻量级且高效的协议,通常用于物联网、工业应用和许多其他用例中的通信。 以下是在绿色OT和绿色IT背景下优化MQTT架构的一些关键考虑因素: 关注MQTT的考虑因素 最小化消息开销 减少MQTT消息的大小,以最小化数据传输需求。这有助于优化带宽使用并降低数据传输的能耗。 选择QoS级别 仔细选择MQTT消息的服务质量(QoS)级别。较高的QoS级别可能导致增加网络流量和更高的能源消耗。根据应用需求评估消息可靠性与能效之间的权衡。 明智使用遗嘱功能 MQTT中的遗嘱功能允许设备指定在意外断开连接时自动发送的消息。虽然此功能有助于确保通信的完整性,但应谨慎使用,以避免不必要的消息和潜在的能源浪费。 有效载荷压缩 实现有效载荷压缩以减少MQTT消息的大小。对于处理大数据有效载荷的情况尤其有用,因为它可以最小化带宽使用并加快数据传输。 消息聚合 尽可能将多个小消息聚合成一个更大的消息。这减少了通过网络传输的消息数量,从而减少相关开销。 实现高效的保留消息 MQTT中的保留消息用于存储主题的最后已知良好值。高效使用保留消息以最小化重复数据传输,并减少网络上的整体消息负载。 批处理 将相关数据分组,在预定时间间隔内批量传输。这种方法减少了通信的频率,在不需要实时更新的情况下尤其有效。 优化保持连接间隔 根据应用的具体要求调整保持连接间隔。较长的间隔可以减少不必要的通信开销,但请确保间隔不会太长,以免影响系统的实时响应性。 使用高效的主题层级结构 设计一个高效的主题层级结构,以最小化主题数量,并确保消息路由的清晰。良好组织的主题结构有助于更容易的消息过滤,减少不必要的数据传输。 清理会话处理 在适当时使用清理会话。清理会话会丢弃任何之前的会话状态,减少了重新连接时需要传输的信息量。这对资源优化有益。 使用高效的数据格式 根据应用的要求选择高效的数据序列化格式(例如,JSON,Protocol Buffers)。最佳数据格式有助于减少消息大小并提高整体效率。 其他关注系统和设备的考虑因素 能效设备和传感器 选择能效设备和传感器来实施支持MQTT的物联网设备。低功耗和高能效硬件可以显著贡献于系统整体的绿色目标。 负载均衡和可扩展性 实施负载均衡策略,以有效分配MQTT代理的工作负载。这不仅增强了系统的可扩展性,还有助于优化能源使用,确保资源均匀利用。 利用边缘计算 利用边缘计算在数据源附近处理数据,减少对广泛数据传输和中心处理的需求。这可以降低能源消耗,并减少数据处理的延迟。 实施预测性维护 使用MQTT传输有助于预测性维护的数据。通过分析设备数据,组织可以预测潜在问题,并安排维护活动,防止计划外的停机时间,提高整体运营效率。 监控和分析能源消耗 实施监控工具,持续评估支持MQTT的系统的能源消耗。利用获得的洞察来识别改进领域,并随时间优化能源使用。 结论 通过将这些考虑因素纳入MQTT架构的设计和实施中,组织可以为绿色OT和绿色IT的总体目标做出贡献。优化过程应该是迭代的,考虑到技术的发展性质以及IT和OT领域中可持续实践的持续进步。 --- ### 70. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT作为一种高度灵活的协议,专为物联网应用中的高效轻量级通信而设计。它基于发布-订阅模型,天然支持客户端之间的解耦关系。然而,在实际使用MQTT时,数据生产者和消费者通常依赖于一套预先定义的指南。 例如: 1) 包含多个MQTT连接的设备必须遵循特定的初始化序列,才能被识别为在线; 2) 触发数据生产者完全功能的准备状态需要预定的消息序列; 3) 客户端引起的合理资源使用。在本文中,我们将介绍基于有限状态机的行为模型。 在本文的最后,将展示一个现已可用的现实世界示例。 MQTT通信上行为策略的需求 由于 MQTT 允许灵活地实现任何这些通信方案,因此数据生产者通常会实现一些控制逻辑来验证这些通信方案。然而,这种方法有一些缺点,因为数据传输是不必要的,并且必须在所有数据消费者中实现相应的控制逻辑。即使数据生成器是根据商定的标准实施的,也需要进行检查来验证这些标准,以克服无意中的错误部署。应用行为策略克服了检查消费者方面的需要。 模型 不论MQTT版本如何,MQTT协议都实现了一个定义好的状态机来处理客户端连接。例如,最初需要一个CONNECT包来建立客户端与代理的连接。一旦连接建立,就会实现特定的状态,并可以发送更多包。接下来,客户端可以发送SUBSCRIBE包订阅一个MQTT主题。之后,客户端发送PUBLISH包将载荷发布到代理。最终,客户端发送DISCONNECT包断开与代理的连接——达到最终状态。 以下示意图展示了我们刚刚描述的客户端行为。请记住,这只是演示客户端连接到代理时随时间进展的情况,并不反映实际实现。 MQTT协议在状态机上的使用示例 一个有限状态机可以简单地指定为由有限的状态和两个状态之间的有限转换组成。在上面的示例中,显示了以下状态和转换: 状态: 已连接(Connected)、已订阅(Subscribed)、已发布(Published)、开始(Start)、结束(End) 转换: 开始(Start)-> CONNECT -> 已连接(Connected) 已连接(Connected)-> SUBSCRIBE -> 已订阅(Subscribed) 已订阅(Subscribed)-> PUBLISH -> 已发布(Published) 已发布(Published)-> DISCONNECT -> 结束(End) 注:以上状态和转换是客户端与MQTT代理交互的简单示例。 目的驱动的协议 大多数用例在MQTT协议提供的状态和转换之上定义了它们的目的驱动协议,主要是基于MQTT负载中的实际数据。 例如:一台设备被认为完全在线,当且仅当以下MQTT包按特定顺序发送:CONNECT、SUBSCRIBE、PUBLISH+、DISCONNECT,其中PUBLISH+表示至少发送了一次发布。重点是SUBSCRIBE包必须在PUBLISH消息之前发送,以确保设备正确初始化。 为了验证这种序列,定义了一个特定的协议,要求这个特定序列 — 即定义了一个目的驱动协议。 其他场景包括: 1) 必须定义Last Will以确保有效,以及 2) 在一个小时内不得向目的驱动协议发送重复的负载。 通常,这种客户端行为可以通过自定义代码实现作为额外的微服务来验证,或者通过实现HiveMQ扩展来验证。 行为模型作为目的驱动协议检查器 在本节中,我们将介绍行为模型。行为模型是一个在任何MQTT包之上指定目的驱动协议的有限状态机。状态机具有以下属性: 状态: 初始状态:行为模型一旦客户端开始与MQTT代理建立连接时的起始状态。 终止状态:有两种子类型的状态:Success表示客户端成功通过了行为模型检查,Failed则相反。 中间状态:所有其他状态都是在初始和终止之间的中间状态。 转换: 某个特定事件可能会引起状态转换。这包括至少MQTT包(如CONNECT、PUBLISH等),或更复杂的事件,如时间或甚至外部触发器。 一个转换由一个起始状态、一个条件事件和一个目标状态组成。 条件事件包括一个事件(如1) MQTT包(如CONNECT或PUBLISH)或一个事件和一个返回true或false的条件。 操作: 转换可能有额外的行为要执行,例如在到达任何消费者之前修改被发送的负载,或构建自定义指标。 记忆: 它还具有一个有限的内存来存储和从中加载数据,操作为store(var, value)和load(var),后者返回存储的值。 示例:DUPLICATE_COUNTER 为了让概念更加直观,我们来看一个具体的例子:定义一个名为DUPLICATE_COUNTER的行为模型,用于计算两个连续且相同的负载的数量。该行为模型可以如下建模: MQTT行为模型:DUPLICATE_COUNTER 状态: 模型有三个状态:Start、CONNECTED和End。 Start是一个初始状态,Connected是一个中间状态,End是一个成功的终止状态。 转换和操作: 从Start到Connected的转换:当客户端通过MQTT包CONNECT启动连接时触发。执行转换时,变量counter初始化为0并存储在内存中。 从Connected到Connected的循环:当客户端通过MQTTPUBLISH包发送负载且条件isIdentical为true时触发条件事件。随后执行的操作将变量counter增加1。 从Connected到End的转换:当客户端发送MQTTDISCONNECT包时,触发转换,状态机达到成功的终止状态。 计数器在每次连续发布两条相同消息时增加。注意,为了简化,这里没有进一步介绍isIdentical函数。 行为模型的形式主义允许我们检查MQTT协议的使用是否定义良好。模型可能有两个结果:要么MQTT客户端正确实现了状态机(行为模型以成功的终止状态结束),要么MQTT客户端行为不当(以失败的终止状态结束)。特别是不当的行为可以相应地处理,例如首先在大规模IoT部署中使这些客户端可见,或者通过在状态转换中引入额外的逻辑来纠正行为。特别是后一种情况对于由于缺乏更新能力而难以修复的客户端来说很有趣。 在数据中心的实现 在HiveMQ平台版本4.20中,我们推出了HiveMQ数据中心,它实现了新的行为政策和预定义的数据中心行为模型。行为政策实例化了一个可选择的客户端连接的行为模型检查器。每个在代理中接收到的MQTT包都会被传递给检查器,以确定实例化行为模型的状态转换。此外,状态转换可以导致更多的操作。当客户端行为不当时,甚至可以断开客户端连接或丢弃消息。 下图展示了该架构的总体视图。连接的客户端发来的MQTT包通过代理处理,并由实例化的行为模型检查器(称为策略引擎)检查。策略引擎返回要采取的进一步行动,例如丢弃消息、断开客户端连接或仅记录消息以供进一步检查。 HiveMQ数据中心中的行为模型检查器 因此,每个客户端连接都有一些关于实例化行为模型状态和变量的额外信息。记得我们在上面的示例中创建了一个计数器变量。 然而,使客户端行为可见是一个重要方面。为此,可以通过REST API请求每个客户端连接的当前状态 — 甚至返回存储在内存中的状态变量以进行进一步的调试。 Publish.duplicate 考虑以下描述的行为模型,这是HiveMQ数据中心中一个实际可用的行为模型,类似于上面介绍的示例模型。该行为模型的目的是跟踪实际重复消息的情况,它有两个终端状态。 下面是“Publish.duplicate”行为模型中状态 状态类型描述初始 Initial初始,非终端模型的起始点,一旦客户端符合政策就进入此状态已连接 Connected中间,非终端表示客户端已成功连接到代理未重复 NotDuplicated中间,非终端表明客户端已发送其第一条消息,或两个连续消息不同重复 Duplicated中间,非终端表明客户端已发送与前一条消息相同的消息失败 Violated失败,终端当客户端在任何时间点发送两条相同的连续消息并断开连接时,失败状态成为终止状态断开 Disconnected成功,终端当客户端始终发送不同的连续消息并断开连接时,断开状态成为终止状态 下面显示了该行为模型的状态机。 如您在状态机中看到的,有一个状态用于指示客户端是否发送了重复消息——“Duplicated”状态。 下面的列表显示了准备好使用的完整行为政策: { "id": "drop-duplicate-messages", "createdAt": "2023-11-22T18:02:06.853Z", "lastUpdatedAt": "2023-11-22T18:38:01.714Z", "matching": { "clientIdRegex": ".*" }, "behavior": { "id": "Publish.duplicate", "arguments": {} }, "onTransitions": [ { "fromState": "Any.*", "toState": "Duplicated", "Mqtt.OnInboundPublish": { "pipeline": [ { "id": "operation-GDgvk", "functionId": "Mqtt.drop", "arguments": { "reasonString": "The message you sent was a duplicate message caught by policy ${policyId}." } } ] } } ] } 该政策为配置在匹配字段中的每个连接客户端实例化行为模型。在这个例子中,使用了Publish.duplicate行为模型。接下来,在onTransitions字段中定义了额外的操作。在这种特定情况下,每次MQTT客户端发送PUBLISH包导致状态机从Any(通配符状态)进入Duplicated状态时,将执行管道。在这种情况下,执行预定义且可用的Mqtt.drop函数,意味着传入的MQTT PUBLISH包将被丢弃。最终,根据MQTT客户端的版本,向发送客户端提供了一个原因字符串。 这个行为政策已经准备好在您的IoT部署中与HiveMQ数据中心一起使用,以避免在消费者端出现消息重复。 您还可以使用HiveMQ控制中心来创建上述政策。请参见下面的截图,展示了在HiveMQ控制中心创建行为政策的相关部分。 HiveMQ控制中心用于创建行为政策 展示案例 在本节中,我们想展示在HiveMQ数据中心注册行为政策的客户端的语义。下面的动画插图显示了其中的三个部分: 左上角的控制台显示了一个MQTT客户端使用mqtt cli向HiveMQ代理发布数据。客户端以客户端ID“testclient”连接代理。一旦建立连接,就会按以下顺序向主题“test”发布消息: { "temperature": 123 } { "temperature": 123 } { "temperature": 124 } { "temperature": 124 } { "temperature": 123 } 左下角的控制台显示了一个订阅通配主题的MQTT客户端,以消费所有数据。如您在输出中看到的,客户端只消费不同的连续消息: { "temperature": 123 } { "temperature": 124 } { "temperature": 123 } 右侧的控制台显示了对客户端“testclient”的REST API请求状态。每次客户端发送重复消息时,行为模型就会进入“Duplicated”状态。响应还显示了更多信息。 实际影响 行为模型Publish.duplicate在多个方面展示了其优势,如下所列: 提高效率:减少不必要的数据传输提高了网络效率,确保只有相关且及时的数据被传输。 降低运营成本:较少的数据传输意味着更低的带宽使用,可能降低与数据存储和处理相关的成本。 增强系统性能:系统和网络负担减轻,提高了性能和可靠性。 促进更好的数据管理:数据流更加流畅,便于更有效地管理、分析和利用数据。 支持可扩展性:在不断增长的物联网网络中,有效的数据传输对于可扩展性至关重要,尤其是在设备数量和数据点可能呈指数级增长的情况下。 结论 将行为模型集成到MQTT通信中对于优化IoT部署至关重要。引入有限状态机确保了对MQTT客户端的系统性验证,强制执行预定义的序列和标准。DUPLICATE_COUNTER行为模型是实际应用的一个例子,用于跟踪如重复消息出现的条件。 随着IoT领域的发展,利用MQTT中的行为模型成为确保大规模IoT场景中的可靠性、效率和成本效益的一种积极策略,这标志着在实现明确定义和优化的基于MQTT的IoT部署方面的重大进步。 --- ### 71. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 上周,全球最重要的开源软件基金会之一 Eclipse 基金会与 Eclipse Sparkplug 工作组合作,宣布了工业物联网 (IIoT) 发展的一个重要里程碑。 Eclipse Sparkplug 规范已作为国际标准正式发布,现称为 ISO/IEC 20237! Sparkplug 标准化推动 IIoT 发展 这一成就预示着工业物联网连接的新篇章,Sparkplug 规范为不同的工业系统提供了一种轻松通信和交换数据的通用方法。Eclipse Sparkplug 被认可为国际标准非常重要,因为它可以促进互操作性、增强信任和采用、推动创新、扩大市场准入、确保法规遵从性并简化 IIoT 领域的协作。  这一成就标志着在创建更加互联、高效和创新的工业格局方面向前迈出了重要一步。  什么是 MQTT Sparkplug? Sparkplug是一种开源软件规范,为 MQTT 客户端提供框架,以双向和可互操作的方式将来自 MQTT 基础设施内的应用程序、传感器、设备和网关的数据无缝集成。 MQTT Sparkplug的优势 为什么要选择MQTT Sparkplug?这个规范提供了许多优势: 数据互操作性: 通过统一的消息结构和协议规则,Sparkplug确保不同设备之间的数据能够互操作,无需在通信上投入大量精力。 说明:无论哪家供应商提供的温度传感器,它们都能够在相同的系统中无缝运行,因为它们遵循了相同的Sparkplug规范。 节省带宽和资源: 通过“按异常报告”的状态管理方式,减少了不必要的轮询,从而节省了带宽和计算资源。 说明:使用Sparkplug,系统可以立即知道设备的状态变化,而不必频繁轮询设备,从而减少了通信开销。 支持传统设备: 即使某些设备不支持Sparkplug或MQTT,它们仍然可以通过使用EON节点来与系统集成。 说明:即使某个设备使用传统的通信协议,它可以通过连接到支持Sparkplug的EON节点来参与整个系统。 自动设备发现: Sparkplug关注统一性,使系统能够自动发现网络上的设备和数据。 举例说明:当新设备添加到系统中时,它们可以自动被发现并集成,而无需手动配置。 开源规范: Sparkplug是一个开源技术,无需许可,并且可以根据需要进行定制。 举例说明:无需支付昂贵的许可费用,您可以自由地采用和修改Sparkplug规范,以满足您的特定需求。 --- ### 72. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 引言 在这个数字化和互联网快速发展的时代,串口服务器和MQTT协议在物联网(IoT)和远程通信领域发挥着越来越重要的作用。串口服务器作为连接传统串行设备和网络的桥梁,通过集成先进的MQTT协议,为数据通信带来了革新。本文将深入探讨串口服务器集成MQTT功能的重要性及其在现代通信系统中的应用。 串口服务器的重要性 串口服务器使得旧式串行设备能够接入现代网络系统。 提供了一种低成本的方式来远程访问和管理串行设备。 MQTT协议的角色 MQTT,作为一种轻量级的消息传输协议,特别适用于带宽有限的环境。 它的发布/订阅模型非常适合处理来自大量分布式设备的数据。 2. 串口服务器概述 串口服务器是一种将串行通信转换为网络通信的设备,它使得原本只能通过串行端口进行通信的设备能够通过网络进行数据传输。 定义和工作原理 串口服务器的定义:一种使串行设备接入网络的设备。 工作原理:将串行数据包转换为网络数据包,反之亦然。 串口服务器在不同行业中的应用 工业自动化:串口服务器用于连接传感器、控制器等工业设备,实现远程监控和控制。 医疗健康:在医疗设备中使用串口服务器来实现数据的实时监测和远程诊断。 零售和物流:串口服务器在物流跟踪系统中用于数据收集和设备管理。 智能建筑:用于监控和管理建筑自动化系统中的各种设备。 3. MQTT协议简介 MQTT(Message Queuing Telemetry Transport)协议是一种基于发布/订阅模式的轻量级消息传输协议,特别适用于物联网环境。 基本概念和工作原理 轻量级和高效:MQTT协议设计简洁,适用于带宽有限和不稳定的网络环境。 发布/订阅模型:允许多个客户端订阅特定主题,服务器将消息分发给订阅该主题的客户端。 MQTT的主要特点和优势 低功耗:适合电池供电的设备。 可靠的消息传递:提供不同等级的服务质量(QoS)。 灵活的通信方式:适合各种规模和复杂度的通信需求。 4. 串口服务器结合MQTT功能的重要性 将MQTT协议集成到串口服务器中,为传统串口通信带来了新的可能性,特别是在物联网应用中。 为何将MQTT集成到串口服务器中 扩展传统设备的功能:使得旧式串口设备能够接入现代的物联网系统。 提高数据传输效率:利用MQTT的高效传输,减少网络带宽的占用。 MQTT在串口通信中的优势 远程访问和控制:通过互联网远程访问串口设备。 实时数据通信:实时传输传感器数据和控制命令。 5. 串口服务器的MQTT功能详解 串口服务器的MQTT功能使其成为物联网领域的强大工具。 MQTT客户端与服务器的交互 连接管理:如何建立和维持设备与MQTT服务器之间的连接。 消息的发布和订阅:详细说明设备如何发布数据和订阅来自其他设备的数据。 通信质量和服务等级(QoS)的管理 不同QoS等级的应用场景:从QoS 0到QoS 2,不同的服务质量等级适用于不同的应用需求。 保障数据的可靠传输:如何确保在不稳定的网络环境下传输的可靠性。 主题订阅和消息发布的机制 主题的灵活性:如何定义和使用MQTT主题以适应不同的应用场景。 消息过滤和分发:服务器如何处理大量的消息并将它们正确地分发到订阅的客户端。 6. 应用实例分析 串口服务器配合MQTT协议能够在多种场景中提供高效、可靠的通信解决方案。 物联网(IoT)设备的数据集成 智能家居:串口服务器使得旧式家电通过MQTT接入智能家居系统。 工业监控:在工业环境中,实时监控传感器数据和机器状态。 远程监控和管理系统 基础设施监控:例如,远程监控电力网和水务系统。 远程设备维护:提供设备故障诊断和维护的能力。 工业自动化和智能家居系统 自动化控制:利用MQTT实现设备间的实时通信和自动化控制。 能源管理:在智能建筑中优化能源消耗。 7. 技术挑战与解决方案 在实施串口服务器和MQTT功能时,存在一些技术挑战需要克服。 网络安全性和数据加密 加密通信:实现端到端加密以保护数据安全。 访问控制:使用认证和授权机制保护设备和数据。 确保高可靠性和低延迟 网络优化:选择适合的网络协议和硬件以减少延迟。 负载均衡:确保系统在高负载下仍能稳定运行。 兼容性和可扩展性问题 协议适配:确保串口服务器与不同MQTT版本的兼容性。 系统扩展:设计可扩展的系统以适应不断增长的设备数量和数据量。 8. 未来展望 随着物联网技术的发展,串口服务器结合MQTT功能的应用将不断扩大。 MQTT和串口服务器技术的发展趋势 更高效的协议:发展更加高效和安全的通信协议。 广泛的应用领域:从工业到消费者电子,应用领域的扩大。 新兴应用领域和潜在市场 智慧城市:在城市管理中的应用。 远程医疗:用于医疗设备的远程监控和数据收集。 9. 结论 串口服务器的MQTT功能是实现高效、可靠的物联网通信的关键。通过不断的技术创新和应用拓展,这一功能将在未来的通信和自动化领域发挥更加重要的作用。 --- ### 73. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 工业物联网中MQTT有效负载的挑战 在工业物联网(IIoT)中,从简单的温度传感器到复杂的工业机器,各种设备之间的通信常常存在格式不一致和非标准化的问题。而MQTT并没有规定特定的负载结构,这意味着负载可以是任何格式,从纯文本、二进制数据到JSON或XML等,这种多样性虽然允许使用多种数据类型,但对于需要一致和标准化的MQTT有效负载格式的IIoT实现来说可能并不理想。 以下是不一致和非标准化有效负载格式所带来的挑战: 兼容性问题: 如果有效负载没有标准化,不同设备或应用可能发送无法被其他设备或应用正确解读的数据格式,导致集成困难,特别是在涉及多个制造商的大规模IIoT部署中。 增加复杂性: 未标准化的有效负载要求开发者为每种不同的负载格式创建自定义解析器,这不仅使代码库复杂化,还增加了错误的可能性。 效率降低: 解析非标准化或不一致的有效负载通常需要更多的计算资源。在IIoT设备通常受限于处理能力和内存的情况下,这尤其成问题。 维护挑战: 不一致的有效负载结构使系统维护和更新变得更加困难。如果设备改变其有效负载格式,所有订阅实体都必须更新以理解这种新格式。 歧义和数据损坏: 没有标准化结构,数据解读错误或损坏的可能性增加,尤其在像医疗保健或工业自动化等关键应用中,后果可能非常严重。 Sparkplug如何实现标准化和结构化的MQTT有效负载 MQTT Sparkplug规范旨在标准化MQTT消息,确保一致的数据结构,以开发基于MQTT的互操作IIoT解决方案。它通过提供有效负载编码机制实现这一点,这不仅保留了MQTT的基本特性 - 轻量级、带宽高效和低延迟 - 同时还整合了适合IIoT环境的现代编码方案。 Sparkplug B(spBv1.0)有效负载格式是一种数据编码方案,使用Google Protocol Buffers或Google Protobufs。Google Protobufs是一种语言中立的结构化数据序列化机制,使Sparkplug B能够有效且可扩展地编码结构化MQTT数据。 Sparkplug B通过以下方式支持丰富的数据模型: 使用模板的复杂数据类型 数据集 增强的指标 指标别名支持 历史数据集成 文件数据管理 MQTT Sparkplug有效负载的关键组件 主要地,Sparkplug有效负载包含一些基本信息,如时间戳和序列号,以及包含键/值对数据的一系列指标。以下是这些及更多组件的详细说明。 时间戳: Sparkplug要求每个指标都包含时间戳,确保每个数据点都与其记录时间相关联。 指标: Sparkplug有效负载的指标组件由一系列指标组成。在Sparkplug有效负载上下文中,指标指的是设备间通信的具体数据点或值,例如温度读数、压力值或开关状态。为了描述其包含的信息,一个Sparkplug指标表示一个键、值、时间戳、数据类型以及可能与之相关联的任何元数据。 序列号: 每个Sparkplug消息包含一个序列号,每个新消息都会增加。如果接收者检测到序列号中有缺口,它知道有消息丢失了。这一特性对于数据的一致性至关重要,使设备或系统能够请求丢失的数据或采取纠正措施。 Sparkplug有效负载指标组件解析 name(名称): 指标的标识符。 alias(别名): 指标的数值别名,用于减少重复消息中的有效负载大小。 timestamp(时间戳): 表示指标采集或创建的时间。 datatype(数据类型): 指标持有的数据类型(例如,Boolean布尔型、Int32整型、String字符串等)。 value(值): 实际的数据。 is_historical(是否为历史值): 一个布尔标志,表示此指标是否代表一个历史值。 is_transient(是否为瞬时值): 一个布尔标志,表示此指标是否不应被记录为历史数据。 is_null(是否为空值): 一个布尔标志,表示此指标是否有一个空值。 metadata(元数据): 与指标相关联的元数据对象。 properties(属性): 与指标相关联的属性集对象。 Sparkplug B有效负载的示例 下面是一个简单的Sparkplug B有效负载的例子。 { "timestamp": 1486144502122, "metrics": [{ "name": "My Metric", "alias": 1, "timestamp": 1479123452194, "dataType": "String", "value": "Test" }], "seq": 2 } NBIRTH有效负载表示 NBIRTH消息负责通知主机应用程序边缘节点的所有信息,包括将来它将发布数据的每个指标。 以下是一个简单的NBIRTH消息的表示,在主题上: spBv1.0/DairyPlant/NBIRTH/Refrigeration Sparkplug B有效负载在NBIRTH消息中的发布可能如下所示: { "timestamp": 1486144502122, "metrics": [{ "name": "bdSeq", "timestamp": 1486144502122, "dataType": "Int64", "value": 0 }, { "name": "Node Control/Scan Rate", "timestamp": 1486144502122, "dataType": "Int64", "value": 3000 }, { "name": "Properties/Hardware Make", "timestamp": 1486144502122, "dataType": "String", "value": "Opto22 Groov EPIC" }, { "name": "Inputs/Temperature", "timestamp": 1486144502122, "dataType": "Float", "value": 25.6 }, { "name": "Inputs/Humidity", "timestamp": 1486144502122, "dataType": "Float", "value": 67.8 }, { "name": "Outputs/Pump", "timestamp": 1486144502122, "dataType": "Boolean", "value": true }], "seq": 0 } NDATA有效负载表示 NDATA消息用于更新边缘节点在NBIRTH消息中最初发布的任何指标的值。当边缘节点的输入发生变化时,将生成NDATA消息并发布到MQTT服务器。如果边缘节点上的多个指标发生变化,它们都可以包含在单个NDATA消息中。 以下是一个简单的NDATA消息的表示,在主题上: spBv1.0/DairyPlant/NDATA/Refrigeration Sparkplug B有效负载在NDATA消息中的发布可能如下所示: { "timestamp": 1486144502122, "metrics": [{ "name": "Inputs/Temperature", "timestamp": 1486144502122, "dataType": "Float", "value": 29.2 }, { "name": "Inputs/Humidity", "timestamp": 1486144502122, "dataType": "Float", "value": 55.9 }], "seq": 0 } 请注意,如果泵状态的值没有改变,则可以从指标中排除泵状态的值。 结论 总而言之,尽管MQTT在其有效负载结构上提供了灵活性,但这种灵活性可能导致集成挑战和复杂性增加,特别是在使用来自不同厂商的设备和应用程序时。MQTT Sparkplug规范通过提供一致和标准化的有效负载结构来解决这一挑战,专为IIoT量身定制。通过其使用Google Protocol Buffers的Sparkplug B数据编码机制,它确保设备能够高效地交换信息,同时保留MQTT的关键属性。这种统一性不仅简化了开发和集成工作,还增强了IIoT部署中数据通信的可靠性和完整性。 --- ### 74. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT Sparkplug在IIoT架构中的关键组件运作 要有效地设计和开发基于MQTT Sparkplug的IIoT架构,理解其组件的运作方式至关重要。具体来说,这包括它们如何连接、发布、接收数据以及如何从网络断开。 本文将探讨三个关键组件在IIoT网络中的会话生命周期:Sparkplug主机应用程序、网络边缘节点和设备,以解释连接机制、数据传输方法和会话建立的复杂性。 MQTT Sparkplug主机应用程序会话生命周期 当Sparkplug主机应用程序启动或重新建立连接时,它会立即尝试与MQTT服务器(已预先配置)建立会话。 一旦与MQTT服务器成功连接,主机应用程序会采取两项主要行动: 它订阅指定的Sparkplug主题命名空间,特别是spBv1.0/#。 它还确保通过名为STATE/host_app_id的主题订阅其自身的状态。 在完成这些订阅后,Sparkplug主机应用程序负责通过发布新的STATE消息通知其他人自己的状态。 此时,主机应用程序准备好接收网络中任何边缘节点发送的MQTT消息。每当边缘节点发送其Sparkplug NBIRTH和DBIRTH通知时,主机应用程序会更新其指标,显示它目前在线并正在处理数据。 MQTT Sparkplug边缘节点会话生命周期 像Sparkplug网络中的任何设备一样,边缘节点通过发送连接请求来初始化其与MQTT代理的连接。此请求通常包含节点的凭据和其他必要细节。 当Sparkplug边缘节点发送其MQTT CONNECT数据包时,它会包含以下主题格式下的“遗嘱消息”: spBv1.0/group_id/NDEATH/edge_node_id 在这里,group_id是Sparkplug组ID,edge_node_id是该边缘节点的Sparkplug边缘节点ID。 在Sparkplug环境中,边缘节点可以设置为识别主机应用程序。如果这样配置,边缘节点只会在主机应用程序在线并主动监听Sparkplug消息时发送其NBIRTH和DBIRTH消息。 成功连接到MQTT服务器后,边缘节点将订阅NCMD和STATE主题。NCMD订阅允许边缘节点处理重生请求。同时,订阅STATE有助于边缘节点了解主机应用程序的当前状态。 随后,边缘节点将使用以下格式广播NBIRTH消息: spBv1.0/group_id/NBIRTH/edge_node_id 此时,主机应用程序可以建立边缘节点的指标结构,显示其在线状态。 MQTT Sparkplug设备会话生命周期 在边缘节点准备向MQTT服务器报告其所有Sparkplug定义的指标数据时,边缘节点(逻辑或物理)负责发布设备诞生消息,DBIRTH。 然而,在发送DBIRTH消息之前,如果设备支持写入输出,则与Sparkplug设备相关联的MQTT客户端必须订阅接收DCMD消息,使用以下主题格式: spBv1.0/group_id/DCMD/edge_node_id/device_id 在这里,group_id是Sparkplug组ID,edge_node_id是Sparkplug边缘节点ID,device_id是设备的Sparkplug设备ID。 从那时起,所有后续指标都会按照例外报告(RBE)的方式使用DDATA消息格式发布给主机应用程序。 结论 总之,本文解释了MQTT Sparkplug的运作行为,阐明了有效的IIoT通信所需的复杂机制。 --- ### 75. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 数据获取与聚合:MQTT与Sparkplug的运用 MQTT是一种标准的二进制发布-订阅消息传递协议,旨在实现设备和系统间快速且可靠的OEE数据传输,尤其适用于网络不稳定、带宽有限、电池动力有限等受限条件下。它基于TCP/IP协议构建,是互联网上网络设备互联的首选通信协议。因此,MQTT非常适合用于工业物联网(IIoT),支持事件驱动架构。 Sparkplug是建立在MQTT之上的框架,为制造数据添加更多上下文。它是一个开源软件规范,为MQTT客户端提供了一个框架,以集成OEE数据并通过定义数据模型提供上下文。它为制造设备制造商和软件提供商共享上下文OEE数据提供了一致的方法,加速了现有运营的数字化转型。 MQTT Sparkplug帮助提高工业过程中OEE的5种方式 实现实时OEE数据流动: MQTT的发布订阅特性和低数据开销使其能够实时访问事件驱动数据,即使在包括连接问题或低带宽等受限环境中也是如此。Sparkplug的出生和死亡通知定义了适当的状态监控机制,可以通知用户工厂地板上淘汰的旧系统和新增的新系统,以确保OEE跟踪是最新的。 高度安全的OEE数据流动: MQTT通信需要客户端与代理进行身份验证,这使得通信高度安全。HiveMQ提供额外的安全特性,包括用户名和密码、OAuth 2.0(JWT)、X.509客户端证书、动态权限、基于角色的权限等授权/认证功能。 随着业务增长而扩展OEE数据: MQTT的发布/订阅模型允许任意数量的客户端连接到代理,易于根据连接数量扩展。这在工厂中很常见,因为需要跟踪的OEE数据点随着新机器和系统的增加而增加。 高可靠性的OEE数据: MQTT确保OEE数据的高可靠性。其中一个关键特性是服务质量(QoS),它使制造商能够选择与网络可靠性和应用逻辑相匹配的服务水平。 支持不同数据类型和数据速率: MQTT最大的优势之一是能够具有统一的命名空间(UNS),作为来自不同系统(如工厂机器、质量系统、MES、ERP等)的所有OEE数据的单一真实来源,然后提供给可以使用和行动的应用程序。 结论 OEE是衡量生产效率的有力方式。拥有全面的数据管理策略有助于改善OEE数据收集,而MQTT Sparkplug可以在许多方面帮助提高工业过程中的OEE。 --- ### 76. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1.简介 这篇补充出版物的目的是向实施者和高级执行官介绍国家标准技术研究院(NIST)提高关键基础设施网络安全的框架(以下简称NIST网络安全框架)及其与MQTT安全建议的关系。NIST网络安全框架为组织提供了一种共同的语言和机制,以便: 1)描述当前的网络安全状况; 2)描述网络安全的目标状态; 3)在风险管理的背景下识别和优先考虑改进机会; 4)评估向目标状态的进展; 5)促进内部和外部利益相关者之间的沟通。 NIST网络安全框架补充,而不是替代组织现有的业务或网络安全风险管理流程和网络安全项目。相反,组织可以使用其当前的流程,并利用NIST网络安全框架来识别提高组织网络安全风险管理的机会。它还提供了一个共识描述,用于全面网络安全程序所需的内容。 这份补充文件仅专注于MQTT协议在NIST网络安全框架内的整合。请记住,完整的网络安全管理框架可以包括必须根据组织的任务、运营环境和使用的技术进行量身定制的各种主题。有关更多信息,请参阅NIST网络安全框架:http://www.nist.gov/cyberframework/ 1.1 参考文献 有用的背景阅读资源包括: MQTT版本3.1.1。http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/csprd01/mqtt-v3.1.1-csprd01.pdf NIST网络安全框架。http://www.nist.gov/cyberframework/ 信息技术与相关技术控制目标(COBIT)。http://www.isaca.org/COBIT/Pages/default.aspx 前20个关键安全控制(CSC)。http://www.counciloncybersecurity.org/attachments/article/12/CSC-MASTER-VER50-2-27-2014.pdf ANSI/ISA-62443-2-1 (99.02.01)-2009,工业自动化和控制系统安全:建立工业自动化和控制系统安全项目。http://webstore.ansi.org/RecordDetail.aspx?sku=ANSI%2FISA+99.02.01-2009 ANSI/ISA-62443-3-3 (99.03.03)-2013,工业自动化和控制系统安全:系统安全要求和安全级别。http://isa99.isa.org/ISA99%20Wiki/WP-3-3.aspx ISO/IEC 27001:2013,信息技术--安全技术--信息安全管理系统--要求。http://www.iso.org/iso/home/store/catalogue_ics/catalogue_detail_ics.htm?csnumber=54534 NIST SP 800-53 第4版:NIST特别出版物800-53 第4版,联邦信息系统与组织的安全和隐私控制。2013年4月。http://dx.doi.org/10.6028/NIST.SP.800-53r4 OASIS安全断言标记语言(SAML)。http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf 联邦信息处理标准(FIPS)。http://www.nist.gov/itl/fips.cfm 支付卡行业数据安全标准(PCI DSS)。https://www.pcisecuritystandards.org/security_standards/ NIST特别出版物800-26(信息技术系统安全自我评估指南)。http://www.fda.gov/ohrms/dockets/dockets/00d1541/rpt0007.pdf ISO 15408:2009(IT安全评估标准)。http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=50341 1.2 NIST网络安全框架 NIST网络安全框架是一种基于风险的方法,用于管理网络安全风险,由三部分组成: 1        框架核心 2        框架实施层次 3        框架概况 每个框架组件加强了业务驱动因素与网络安全活动之间的联系。 1.2.1 框架核心 框架核心是一套网络安全活动、期望结果和适用参考,这些都是跨关键基础设施部门的共同点。核心以一种可以让组织从执行层面到实施和运营层面跨组织交流网络安全活动和结果的方式,呈现行业标准、指南和实践。框架核心由五个并发且持续的功能组成:识别、保护、检测、响应、恢复。当这些功能一起考虑时,它们提供了组织管理网络安全风险生命周期的高层次、战略视图。然后框架核心为每个功能确定基础关键类别和子类别,并将它们与每个子类别的示例信息性参考(如现有标准、指南和实践)匹配。 1.2.2 框架实施层次 框架实施层次(“层次”)提供了有关组织如何看待网络安全风险以及管理该风险的过程的背景。层次描述了他们的网络安全风险管理实践在多大程度上展现了框架定义的特征(例如,风险和威胁意识、可重复性和适应性)。层次反映了组织实践的范围,从部分(第1层)到适应性(第4层)。这些层次反映了从非正式、反应式响应到敏捷和风险意识方法的进展。在选择层次时,组织应考虑其当前的风险管理实践、威胁环境、法律和监管要求、业务/任务目标和组织约束。 1.2.3 框架概况 框架概况(“概况”)表示根据业务需求选择的组织从框架类别和子类别中选择的结果。概况可以被描述为标准、指南和实践与特定实施场景中的框架核心的对齐。概况可以用来识别通过比较当前概况(“现状”)与目标概况(“预期状态”)来提高网络安全姿态的机会。为了开发概况,组织可以回顾所有类别和子类别,并根据业务驱动因素和风险评估确定哪些最重要;他们可以根据需要添加类别和子类别以解决组织的风险。然后,当前概况可用于支持优先级排序和测量向目标概况的进展,同时考虑其他业务需求,包括成本效益和创新。概况可以用来进行自我评估以及在组织内部或组织之间进行沟通。 1.3 针对MQTT的NIST网络安全框架 在MQTT协议的背景下,每个NIST网络安全组件都被简化以仅反映该协议的安全考虑,并相应地重新命名:MQTT网络安全框架核心、MQTT网络安全框架实施层次和MQTT网络安全框架概况。 1.3.1 MQTT网络安全框架核心 MQTT网络安全框架核心由相同的五个功能(识别、保护、检测、响应、恢复)组成,它们可以提供组织管理MQTT相关网络安全风险的高层次、战略视图。MQTT网络安全框架核心随后为这些功能的每一个确定基础关键类别和子类别,这些在第2节中有描述。由于MQTT网络安全框架的范围较小,因此没有必要为每个类别和子类别提供参考。相反,第1.1节提供了一个非详尽的信息性参考清单。 1.3.2 MQTT网络安全框架实施层次 MQTT网络安全框架实施层次展示了MQTT网络安全框架核心功能和类别的实施,并指示了如何管理网络安全风险。组织应在类别级别确定期望的层次,确保选定的级别符合组织目标、缓解网络安全风险,并且可行以实施。外部指导将是有帮助的,例如可以从OASIS安全断言标记语言(SAML)、联邦信息处理标准(FIPS)和支付卡行业数据安全标准(PCI DSS)获得的信息。 1.3.2.1 第1层:部分 组织尚未实施正式的、对威胁有意识的MQTT风险管理过程来确定优先级网络安全活动列表。组织可能会根据不同的经验或从外部来源获得的信息,偶尔基于特定情况实施框架的某些部分。 1.3.2.2 第2层:风险通知 组织使用正式的、对威胁有意识的MQTT风险管理过程来开发框架的MQTT概况。此外,定义并实施了经风险通知、管理批准的流程和程序。员工有足够的资源执行他们的网络安全职责。 1.3.2.3 第3层:可重复 组织根据其MQTT风险管理过程的定期应用更新其概况,以应对不断变化的网络安全景观。定义了风险通知的政策、流程和程序,并按预期实施和验证。组织还将有一致的方法在风险发生变化时提供更新。 1.3.2.4 第4层:适应性 组织根据从以前和预期的网络安全活动中获得的预测指标更新其概况。这些概况的更新使组织能够适应不断发展的网络安全环境并应对新兴威胁。风险通知的政策、流程和程序是组织文化的一部分,并定期进行审查 - 包括从经验教训和从其他来源共享的信息的反馈 - 以预测和应对潜在的网络安全事件。 1.3.3 MQTT网络安全框架概况 MQTT网络安全框架概况使组织能够建立减少MQTT相关网络安全风险的路线图,这与组织和部门目标、法律和监管要求以及风险管理优先级相一致。MQTT网络安全框架概况可用于描述特定MQTT网络安全活动的当前状态和期望的目标状态,从而揭示可通过实施措施以满足MQTT网络安全风险管理目标的差距。 概况是与业务要求、风险容忍度和组织资源相一致的功能、类别和子类别的选择。目标概况应支持业务要求,并帮助在组织内部和组织之间沟通风险。通过比较当前概况和目标概况来识别差距,从而创建实施路线图,组织可以实施这些路线图以减少MQTT相关的网络安全风险。 1.3.4 建立或改进网络安全程序 三个MQTT网络安全框架组件共同使组织能够理解和塑造其网络安全程序。以下小节说明了如何做到这一点。 1.3.4.1 优先级和范围 组织识别其业务/任务目标和高级组织优先级。有了这些信息,组织就可以就网络安全实施做出战略决策,并确定支持所选业务线或流程的系统和资产的范围。 1.3.4.2 定位 一旦确定了业务线或流程的网络安全计划范围,组织就会识别相关系统和资产、监管要求及其整体风险方法。然后,组织识别这些系统和资产的威胁和漏洞。 1.3.4.3 创建当前概况 组织通过指示从框架核心中当前实现的类别和子类别结果来发展当前概况。 1.3.4.4 进行风险评估 此评估可以由组织的整体风险管理流程或之前的风险评估活动指导。组织分析运营环境,以便辨别网络安全事件的可能性以及该事件可能对组织造成的影响。重要的是,组织寻求纳入新兴风险和威胁与漏洞数据,以促进对网络安全事件可能性和影响的全面理解。 1.3.4.5 创建目标概况 组织创建一个目标概况,该概况侧重于对框架类别和子类别的评估,描述组织期望的网络安全结果。组织可能会开发自己的额外类别和子类别以考虑独特的组织风险。在创建目标概况时,组织还应考虑外部利益相关者(如行业实体、客户和业务伙伴)的影响和要求。 1.3.4.6 确定、分析和优先考虑差距 组织比较当前概况和目标概况,以确定差距。接下来,它创建一个优先级行动计划来解决这些差距,该计划借鉴使命驱动因素、成本效益分析和对实现目标概况结果的风险理解。然后,组织确定解决差距所需的资源。以这种方式使用概况,使组织能够就网络安全活动做出明智的决策,支持风险管理,并使组织能够进行成本效益高、有针对性的改进。 1.3.5 文档概览 本补充文件的其余部分包含以下几个部分: 第2节描述了MQTT网络安全框架核心功能。 附录A是MQTT网络安全框架的示例实施。 附录B是致谢。 附录C是修订历史记录。 以上就是对这个补充出版物的全面介绍,其主要聚焦于如何将MQTT协议整合入NIST网络安全框架,并详细阐述了框架的不同组成部分及其在MQTT安全管理中的应用。通过这个框架,组织能够更好地理解和管理与MQTT协议相关的网络安全风险,确保其信息技术系统的安全和可靠性。 2 MQTT网络安全框架核心功能 本节描述了五个MQTT网络安全框架核心功能,以及如何使用它们来评估使用MQTT协议的组织的网络安全水平。此处提供的与每个功能相关的组件列表是不完全的,仅作为网络安全管理框架的起点。实施者应根据需要修改类别和子类别,以便为其组织量身定制MQTT网络安全框架功能。第1.1节中描述的信息性参考也应修改,以反映组织的监管要求。 2.1 识别此功能的目的是: 开发机构对需要保护的与MQTT相关的组织系统、资产、数据和能力的理解; 根据组织使命确定优先级; 建立实现风险管理目标的流程。 功能类别子类别识别资产管理· 硬件设备清单 · 软件清单 · 网络映射 · 生命周期跟踪风险管理· 定义风险容忍度 · 风险识别 · 风险评估 · 客户端对服务器的认证 · 替代方案分析合规性· 业务要求 · 立法和监管 · 合同要求 · 技术认证信息共享和通信· 理解数据流 · 内部通信 · 外部通信 · 加密套件版本和实施方法环境意识· (客户端)终端设备位置 · 端到端通信基础设施位置 · (服务器端)代理商和邻近区域位置 2.2 保护此功能的目的是开发和实施通过组织的风险管理流程优先确定的适当MQTT保护措施,以确保关键基础设施服务的交付。 功能类别子类别保护安全意识· 用户意识培训 · 正式培训 · 练习和评估身份、凭证和访问管理· 使用PKI(如TLS、VPN) · 选择知名证书颁发机构 · 服务器对客户端的认证 · 客户端对服务器的认证 · 服务器对客户端的授权信息保护· 使用加密套件(如TLS、VPN) · 应用消息和控制包的完整性 · 应用消息和控制包的隐私 · 消息传输的不可否认性 · 所有涉及设备的安全随机数生成服务器端保护· 符合MQTT规范 · 自动断开客户端机制 · 可疑行为检测 · 动态访问控制列表(如IP地址或客户端ID) · 限速和/或阻断(如IP地址) · 静态数据加密 · 频繁会话重新协商以建立新的加密参数(如更换会话密钥或更改密码套件)客户端保护· 防篡改终端设备 · 正确存储客户端证书(密钥管理考虑) · 双因素认证 2.3 检测此功能的目的是开发和实施适当的活动,以识别MQTT相关的网络安全事件的发生。 功能类别子类别检测网络监控· 重复连接尝试 · 连接异常终止物理监控· 客户端可用性验证 · 终端设备及其邻近区域的物理检查| 入侵检测 | · 重复认证尝试 · 主题扫描(尝试发送或订阅多个主题) · 发送无法投递的消息(没有订阅主题的订阅者) · 连接但不发送数据的客户端 2.4 响应此功能的目的是开发和实施通过组织的风险管理流程优先确定的适当活动,以应对检测到的网络安全事件。 功能类别子类别响应响应计划· 撤销丢失和/或泄露的证书 · 撤销丢失和/或泄露的客户端或服务器认证凭据 · 断开可疑或受损的终端设备 · 阻断受损的遥测通道 · 增加防火墙策略 · 关闭受损的代理和服务器 2.5 恢复此功能的目的是开发和实施通过组织的风险管理流程优先确定的适当活动,以恢复由于网络安全事件而受损的适当能力。 功能类别子类别恢复恢复计划· 执行信息系统恢复(如重启代理、创建新的遥测通道等) · 进行重建活动 · 提供替代工作场所以恢复工作活动 · 审查防火墙策略 · 重新颁发证书和认证凭据 · 检查终端设备 · 审查密钥管理和加密部署 · 备份系统 · 更新应急计划 附录A. 示例实施 大型能源提供商MQTT总线架构本节提供了一个实际例子,展示如何应用框架来帮助管理MQTT网络安全风险。一个大型能源提供商打算实施一个基于MQTT协议的开源、不依赖代理商且分布式的现场消息总线架构。保护总线架构至关重要,因为该能源提供商是关键基础设施。 背景该组织正在围绕一个开源的、不依赖代理商的“通信节点”概念构建新架构,并正在运行一个试点项目以评估可行性以及与更广泛的消息总线的整合。其主要作用是促进部署的各种运营技术之间的互操作性(即SCADA、EMS、DMS、OMS、MDM等),并通过使用MQTT协议更高效地共享和处理数据,使这些技术更接近所需资产,从而快速、可靠、安全地执行电网上所有优先级的运营功能。 因此,使用MQTT协议不仅会提高场地内不同资产之间信息交换的简单性和完整性,而且本质上还会过滤大量未使用的数据开销,更重要的是,将消除将所有原始数据回传至中央数据中心的需求。从根本上讲,这些好处将转化为大量节省IT系统和电信网络运营成本,还可以通过启用目前没有分布式决策无法实现的控制方案来实现更大价值。 测试实验室场景能源提供商正在运行以下基于MQTT的现场消息总线场景。系统的初始和最终状态以图片形式展示。中间的发布和订阅步骤在下面的段落中有描述。 基于MQTT的现场消息总线场景包括各种操作和配置,以确保数据的安全和高效传输。在这个场景中,能源提供商将部署多个MQTT客户端和一个或多个MQTT服务器(代理)。这些客户端可能包括各种传感器、控制器和其他设备,它们在电网上执行关键功能,如数据采集、设备监控和控制指令的传输。 系统的初始状态可能包括建立MQTT连接、配置客户端和服务器以及确保所有设备都能安全地通信。这可能涉及到配置加密连接、认证机制和访问控制列表,以确保只有授权的设备能够访问网络和交换数据。 随后的步骤可能包括客户端发布消息到特定的主题,以及其他客户端订阅这些主题以接收数据。例如,一个传感器可能会发布有关电网负载的数据,而一个控制器则订阅这个主题以接收数据并根据需要调整电网的操作。 在最终状态下,系统将能够高效地处理这些信息交换,同时保持高度的安全性。这可能包括实时监控网络活动,检测和响应任何异常或可疑行为,以及确保所有通信都是加密和受保护的。 通过这种方式,MQTT协议为能源提供商提供了一个灵活且安全的方法来管理其电网运营,同时也为实施更复杂的控制方案提供了基础。该方案不仅提高了操作的效率和可靠性,而且还有助于降低运营成本,提高整体网络安全水平。 初始状态:场景从平板电脑用户界面发布低电压 - 114V开始。 一台平板电脑用于控制供电给智能电表的电源电压。场景从平板电脑用户界面发布低电压 - 114V开始。智能电表检测到低电压,并将其电压状态变化发布到配电管理系统(DMS)。DMS订阅并更新其状态。DMS发布控制命令给电容器组控制器,以关闭电容器组,从而提高电压。电容器组控制器将其状态变化 - 已关闭 - 发布回DMS。DMS订阅电容器组控制器的状态变化;它更新其单线图,并向电源发布提高电压至120伏的命令,电源订阅并进行更改。电表发布其电压状态变化 - 120V。DMS向平板电脑用户界面发布显示已关闭电容器组的更新单线图。当平板电脑用户界面订阅并显示来自DMS的更新单线图时,该场景完成。 这个简单的测试场景揭示了发布和订阅现场消息总线、MQTT技术的丰富性、灵活性和易用性。现场消息总线的未来计划是包括必要的安全层:认证、授权、加密、入侵检测和分布式企业的质量信任行为分析。 最终状态:场景结束于平板电脑用户界面订阅提高的电压 - 120V和DMS的新单线图。 MQTT网络安全框架NIST网络安全框架文档第3.2节提供了组织建立或改进网络安全程序的步骤指导。 遵循初始步骤后,能源提供商已经根据多个建议出版物(如NIST特别出版物800-26《信息技术系统安全自我评估指南》以获取管理IT安全的建议,以及ISO 15408《IT安全评估标准》以测试总线架构的安全性)发展了一个框架核心。能源提供商还有一份必须遵守的美国政府强加的标准清单。目前MQTT总线架构的框架核心如下所定义。 功能类别子类别识别资产管理· 硬件设备清单 · 软件清单 · 网络映射风险管理· 定义风险容忍度 · 风险识别 · 风险评估 · 替代方案分析信息共享和通信· 理解数据流 · 内部通信 · 外部通信 · 加密套件版本和实施方法环境意识· (客户端)终端设备位置 · 端到端通信基础设施位置 · (服务器端)代理商和邻近区域位置保护信息保护· 用户意识培训 · 身份、凭证和访问管理检测监控· 网络 · 物理 · 入侵响应响应计划· 撤销丢失和/或泄露的证书 · 撤销丢失和/或泄露的客户端或服务器认证凭据 · 断开可疑或受损的终端设备 · 阻断受损的遥测通道 · 增加防火墙策略 · 关 闭受损的代理和服务器恢复 | 恢复计划 | · 执行信息系统恢复(例如,重启代理,创建新的遥测通道等) · 进行重建活动 · 提供替代工作场所以恢复工作活动 · 审查防火墙策略 · 备份系统 利用这个框架核心,能源提供商评估了当前实施层级的状态(在本案例中是在功能层面上),对当前运营环境进行了风险评估,并创建了一个目标概况,指示了每个功能的期望实施层级状态。 当前和目标概况之间的差异被分析,以确定弥补差距所需的行动,其结果被纳入能源提供商现有的网络安全程序。 能源提供商网络安全程序虽然大部分网络安全程序关注安全治理和风险管理,但有三个独特的部分,其中MQTT与其他合规过程紧密相连。 识别 -> 信息共享和通信 消息流(内部和外部通信) 为了提供弹性的全球网络控制,有效的方法是将组织的数据系统控制面与数据传递系统分离。这使系统管理流程能够从消息内容中分析控制数据。 建议组织的全球网络QoS级别对于系统控制面应比普通数据传递通道优先级更高。这种方法确保了可以在不受数据传递系统阻碍的情况下应用对内部和外部通信通道的重新配置、分区或隔离。 加密和版本控制 在MQTT中,安全性主要是TLS。然而,对于能源提供商来说,有许多小型/受限设备,如SCADA控制系统,利用现有轻量级加密和广泛使用的AES标准。因此,能源提供商将使用TLS,但更高级别的安全过程将使用PKI管理与现有加密套件互操作。 检测 -> 监控 -> 网络 虽然MQTT是一个骨干消息系统,但系统控制面(带QoS设置)和消息传递系统的分离,使第三方监控系统能够轻松访问信息流。 恢复 -> 恢复后 对持久和非持久MQTT队列的使用、放置和位置对恢复有巨大影响。对于能源电力提供商,MQTT在边缘设备上使用非持久队列,在所有服务器端代理上使用持久队列。这种方法使得中心服务能够更快恢复,因为边缘设备总是与服务器端MQTT持久队列同步。 附录B. 致谢 以下个人参与了此规范的创建,并表示感谢: 参与者: Geoff Brown, 机器对机器智能(M2Mi)公司 Louis-P. Lamoureux, 机器对机器智能(M2Mi)公司 William Bathurst, 机器对机器智能(M2Mi)公司 Julien Niset, 机器对机器智能(M2Mi)公司 Sarah Cooper, 机器对机器智能(M2Mi)公司 Allan Stockdill-Mander, IBM Richard Coppen, IBM Andrew Schofield, IBM Peter Niblett, IBM Andrew Banks, IBM 附录C. 修订历史 修订日期编辑所做更改2.02014年3月31日Geoff Brown合并了最新的 JIRA(200、206 和 207)。 --- ### 77. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 “Volvo2MQTT”的组件,它是连接最新的AAOS Volvo汽车和Home Assistant智能家居系统的工具。该组件通过MQTT(消息队列遥测传输)实现连接。虽然这个组件主要是为Volvo汽车设计的,但也可能适用于其他型号的Volvo车辆。如果Volvo原生集成组件无法适用于您的汽车,可以尝试使用这个MQTT桥接。 仓库地址: https://github.com/Dielee/volvo2mqtt 已确认适用的车型包括: 2024年款XC40 BEV 2023年款XC40 BEV 2022年款XC40 BEV 2021年款XC40 PHEV 2023年款V60 T8 PHEV 2023年款C40 BEV 2022年款C40 BEV 2023年款XC90 T8 PHEV 2024年款XC60 PHEV 2023年款XC60 PHEV 2022年款XC60 PHEV 2023年款XC90 PHEV T8 2024年款XC90 PHEV T8 2024年款XC90 B5 Mildhybrid 2019年款V90 PHEV T8(部分功能工作) 支持的功能包括: 锁定/解锁车辆 启动/停止空调 电池充电水平传感器 电动范围传感器 充电系统状态传感器 充电连接状态传感器 预计充电完成时间传感器 车门锁状态传感器(包括所有车门、油箱盖和引擎盖) 窗户锁状态传感器(包括所有窗户和天窗 ) 发动机状态传感器 里程表传感器 轮胎状态传感器 燃料状态传感器 平均燃油消耗传感器 平均速度传感器 剩余行驶里程传感器 保养剩余小时数传感器 保养剩余距离传感器 保养剩余月数传感器 保养警告状态传感器 保养警告触发传感器 汽车设备追踪器 多辆车支持注意:目前仅在欧洲/中东/非洲地区的车辆提供能源状态。 设置方法:Docker:您可以使用以下命令安装这个附加组件。请注意在环境变量中填写您的设置。 docker run -d --pull=always -e CONF_updateInterval=300 -e CONF_babelLocale='de' -e CONF_mqtt='@json {"broker": "", "username": "", "password": "", "port": 1883}' -e CONF_volvoData='@json {"username": "", "password": "", "vin": "", "vccapikey": ["key1", "key2"], "odometerMultiplier": 1, "averageSpeedDivider": 1, "averageFuelConsumptionMultiplier": 1}' -e TZ='Europe/Berlin' --name volvo2mqtt ghcr.io/dielee/volvo2mqtt:latest HA附加组件: 以下是每个选项的含义: 环境变量名称类型Json选项默认值描述CONF_updateIntervalintrequired更新间隔(秒)。CONF_babelLocalestringrequired从这个列表选择您的国家。“Locale name”是您需要的列!CONF_mqttjsonbrokerrequired您的MQTT代理IP,例如192.168.0.5。CONF_mqttjsonport1883您的MQTT代理端口。如果没有给出值,则使用端口1883。CONF_mqttjsonusernameoptional您代理的MQTT用户名。CONF_mqttjsonpasswordoptional您代理的MQTT密码。CONF_volvoDatajsonusernamerequired通常是您登录Volvo应用的电子邮件地址。CONF_volvoDatajsonpasswordrequired您登录Volvo应用的密码。CONF_volvoDatajsonvinoptional单个VIN如"VIN1",或VIN列表如["VIN1", "VIN2"]。如果您不知道您的VIN,请留空。附加组件将使用与您账户绑定的每辆车。CONF_volvoDatajsonvccapikeyrequired与您的Volvo开发者账户关联的VCCAPIKEY。从这里获取您的Vccapi密钥。从1.8.0版本开始,可以定义多个密钥,如:["vccapikey1", "vccapikey2", "vccapikey3", "等..."]CONF_volvoDatajsonodometerMultiplieroptional里程表值的乘数,因为Volvo API提供不一致的数据。对于一些车型,这个设置是10,对于另一些是1。尝试看看哪个适合您的车。如果您留空,乘数将是1。CONF_volvoDatajsonaverageSpeedDivideroptional平均速度值的除数,因为Volvo API提供不一致的数据。对于一些车型,这个设置是10,对于另一些是1。尝试看看哪个适合您的车。如果您留空,除数将是1。CONF_volvoDatajsonaverageFuelConsumptionMultiplieroptional平均燃油消耗值的乘数,因为Volvo API提供不一致的数据。对于一些车型,这个设置是10,对于另一些是1。尝试看看哪个适合您的车。如果您留空,乘数将是1。CONF_debugstringoptional调试选项(true/false)。通常您不需要这个。TZstringrequired容器时区,例如"Europe/Berlin",从这里获得。 --- ### 78. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在制造公司的数字转型战略中,成功取决于其能否连接各种工业数据源,并通过互联网移动它们,以实现OT中心数据与企业/IT应用程序的集成。 在这方面,有两种领先的通信协议提供了标准化的消息交换,为这两个传统上相互隔离的领域之间提供了必要的互操作性连接。这两种协议分别是MQTT Sparkplug和OPC UA。 在本文中,我将描述MQTT Sparkplug和OPC UA之间的主要差异。但在深入探讨这些协议的定义特性之前,让我们简要定义一下每种通信技术。 什么是MQTT Sparkplug? MQTT Sparkplug是一个开源的软件规范,为MQTT客户端提供了一个框架,以双向和互操作的方式无缝集成来自工业数据源的数据到MQTT基础架构中。它通过定义一致的MQTT主题命名空间、有效负载表示和会话状态管理来实现这一目标。 什么是OPC UA? OPC UA是一种跨平台的开源数据交换标准,用于机器对机器的工业通信。它通过使用面向服务的架构和定义独立于制造商或系统供应商的通用设备和信息模型来实现互操作性。 以下是MQTT Sparkplug和OPC UA之间的主要差异: 可扩展性 MQTT Sparkplug的中心代理式发布-订阅通信模型使您能够构建高度可扩展的工业物联网解决方案,因为即使数千个组件订阅以消耗事件,也不会影响事件的生成方式。根据MQTT代理的不同,基于MQTT Sparkplug的工业物联网系统可以扩展到数千万个连接的设备和系统。 另一方面,由于OPC UA采用的是请求-响应通信模型,它仅在服务器具备响应所有客户端需求的能力的小型内部网络中运行良好。因此,要显着扩展基于OPC UA的工业物联网解决方案以包括其他业务功能是严重受限的。 数据带宽效率 MQTT Sparkplug的“按异常报告”规则确保数据生成者仅在检测到监视数据点的值发生更改时才发布数据,这意味着MQTT Sparkplug客户端仅传输已更改的数据和一个小型的保持活动包,以通知MQTT代理客户端仍在运行。这节省了带宽、内存、CPU时间、能源,当与小型有效负载大小结合使用时,实现了高效的协议。 OPC UA的请求-响应模型要求客户端在流程数据没有发生更改时持续轮询服务器。这会消耗大量的带宽、内存、CPU时间、能源,并且需要保持有状态的连接,导致协议效率低下。 数据完整性 MQTT Sparkplug的数据建模能力使其能够在车间实现有关上下文模型、资产和标签数据的单一数据源,可以通过单一的非更改消息媒介,即MQTT代理,被数百甚至数千个OT和IT应用程序使用。这使您能够定义和组织围绕数据模型的业务流程。 OPC UA也有一个OT中心建模引擎,具有多个不同的数据模型定义。首先,各种数据模型的多样性会在标准内部产生碎片化,而且,因为数据的消耗取决于有限数量的客户端应用程序的直接连接,这样就不能保证数据的完整性将在管道上得以维持,因此无法组织业务流程。 集成的便捷性 MQTT Sparkplug的发布-订阅体系结构模型通过统一命名空间连接设备和应用程序,因此它们永远不必直接联系对方,这导致了集成(新)组件更容易。 OPC UA的请求-响应体系结构模型要求设备直接连接到应用程序,这意味着应用程序依赖于它们控制的特定设备,导致了紧密耦合的工业物联网系统,难以集成新组件。 自动发现 MQTT Sparkplug组件可以自动发现所有连接的网络参与者将发送的数据。 OPC UA客户端需要预先配置信息,如节点地址或OPC UA设备类型。 会话状态感知 MQTT Sparkplug通过“出生消息”和“死亡消息”与MQTT连接的“保持活动”计时器的内置会话状态管理功能,能够提供所有系统组件的实时可见性。 与此同时,OPC UA依赖于昂贵且有时不可行的持续轮询,以维护工业物联网组件之间连接状态的概念。 响应性 由于MQTT Sparkplug使用基于事件的架构和按异常报告,它允许在出现异常或事件(如警报)时快速进行调整,从而实现高度响应的工业物联网系统。而在OP C UA中,您必须调整轮询频率以接近实时事件报告。 通信方向性 MQTT Sparkplug允许由工业物联网系统中的任何组件发起的双向通信,而在OPC UA中,服务器仅对客户端发出的请求作出响应。 安全和隐私 MQTT Sparkplug没有定义安全协议,它允许您在TCP/IP层面处理安全性。这意味着您的IT部门可以选择安全模型,如TLS/SSL、证书等,而MQTT将在其之上运行。因为MQTT Sparkplug客户端使用出站通信端口与服务器进行通信,所以无需打开可能增加IT基础设施攻击面的入站通信端口。 另一方面,OPC UA定义了安全协议。但由于与OPC UA服务器的通信是由云等外部平台发起的,这意味着您的IT基础设施需要为入站流量打开端口,从而使其暴露给具有恶意意图的操作者。但它们都具有应用层安全机制,如用户名和密码以及安全令牌。 云连接 MQTT Sparkplug使得将云应用程序与车间系统集成变得轻而易举,只需将云应用程序插入托管在云中的MQTT代理即可。此外,在只需要偶尔与云连接的关键应用程序中,MQTT代理可以在本地托管,以实现低延迟数据交换,同时通过桥接与云基MQTT代理及时连接。 另一方面,要将OPC UA系统与基于云的应用程序集成,需要多个组件在边缘和云中执行发现和数据聚合。虽然OPC UA最近引入了针对云连接的PubSub规范,使用诸如MQTT等协议,但由于其不成熟,其实施较少,并且尚未定义如何将OPC UA的丰富信息模型映射到MQTT。 规范的复杂性 MQTT Sparkplug规范包含68页的简明信息,使其易于在设备和应用程序上实施。 OPC UA规范由多个部分(超过14个)组成,每个部分都有数百页(总共超过1200页),使其成为一种难以在设备和应用程序上实施的复杂标准。 总结:OPC UA与MQTT Sparkplug 特征MQTT SparkplugOPC UA可扩展性高度可扩展不可扩展数据完整性良好差效率高效不高效集成的便捷性易难自动发现可能不可能安全性高度安全有漏洞的安全性云连接易难规范的复杂性简单复杂会话状态感知实时通过轮询通信方向性双向单向轻量级是不是轻量级也不高性能按异常报告是否,不可能响应性高度响应性不响应 结论 总之,虽然本文涵盖了多个特性,以突出MQTT Sparkplug和OPC UA之间的主要差异,但每个特性对于制造企业的重要性因用例而异。因此,要确定它们的重要性,将这些特性分组到主要的制造业务KPI(成本、风险和收入)中会有意义。 可扩展性、数据带宽效率、集成的便捷性和规范的复杂性导致了降低成本。数据完整性、安全性和隐私导致降低业务风险。最后,响应性、自动发现、会话状态感知、云连接和通信方向性导致通过增加运营效率来避免收入损失。 --- ### 79. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在工业物联网(IIoT)的快速演进中,跨设备和应用程序之间的无缝数据通信变得至关重要。为了应对这一需求,开源规范Sparkplug诞生了,它为MQTT客户端提供了一个框架,使它们能够轻松地将数据集成到MQTT基础架构中。本文将介绍Sparkplug规范,探讨其重要性,以及它如何加速实现工业物联网的回报率(ROI)。 Sparkplug规范简介 Sparkplug是一个开源规范,托管在Eclipse Foundation上,旨在为MQTT客户端提供一个框架,以无缝集成应用程序、传感器、设备和网关的数据到MQTT基础架构中。Sparkplug规范的发展是在GitHub上以开放的方式进行的,并受Eclipse Foundation Specification Process(EFSP)的监管。任何人都可以在任何媒介上复制和分发规范文档,无需支付费用或版税。 Sparkplug规范的目标 Sparkplug规范的目标是定义一个MQTT主题命名空间、有效负载和会话状态管理,可以通用地应用于工业物联网市场,同时也满足实时SCADA/控制HMI解决方案的需求。通过满足这些系统的运行需求,基于MQTT的基础架构可以为业务线和MES解决方案提供更有价值的实时信息。 修订历史 1.0(2016年5月26日):初始发布,由Cirrus Link Solutions完成。 2.1(2016年12月10日):增加了有效负载B。 2.2(2019年10月11日):迁移到Eclipse Foundation品牌。 3.0(2022年10月21日):迁移到AsciiDoc,完全重新组织,添加明确的规范和非规范性声明。 注:版本3.0是本文的主要焦点。 规范委员会 规范委员会负责为Sparkplug工作组管辖下的所有规范项目执行Eclipse Foundation Specification Process(EFSP)。该委员会确保EFSP得以遵守,并对Sparkplug规范项目提交的创建审查、进展审查和发布审查进行投票批准。 资源 Sparkplug兼容软件 Sparkplug兼容硬件 Sparkplug TCK流程(技术兼容性套件) 委员会成员 Sparkplug规范对工业物联网的重要性 Sparkplug规范在工业物联网中发挥着至关重要的作用。以下是一些关键方面,解释了它为何对实现ROI至关重要: 1. 互操作性:Sparkplug规范提供了统一的消息结构和协议规则,使不同设备之间的数据能够无缝地互操作。这消除了在通信上的混乱和矛盾。 2. 状态管理:Sparkplug引入了状态管理,通过“出生消息”和“遗嘱消息”的方式,实时通知系统中的设备是否在线或离线。这降低了通信开销,提高了实时性。 3. 支持传统设备:即使某些设备不支持Sparkplug或MQTT,它们仍然可以通过连接到支持Sparkplug的EON节点来与系统集成。这种灵活性确保了现有设备的无缝融入。 4. 自动设备发现:Sparkplug规范使系统能够自动发现网络上的设备和数据,无需手动配置。这节省了时间和资源。 5. 开源规范:Sparkplug是一个开源技术,无需许可,并且可以根据需要进行定制。这使其成为广泛采用和灵活配置的理想选择。 结论 Sparkplug规范是工业物联网中的关键技术,为实现工业自动化系统的互操作性、可靠性和高效性提供了坚实的基础。通过为工业设备之间的数据通信建立标准,Sparkplug帮助企业避免供应商依赖性,降低了系统复杂性,从而实现更容易扩展。通过采用基于Sparkplug规范的数据传输架构,企业能够更快地实现工业物联网的回报率,为其工业自动化系统带来更大的成功。 --- ### 80. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当在工业控制系统中使用相同的语言,但存在不同的词汇来指代相同的物体时,可能会导致严重的混淆,特别是在需要迅速采取行动来纠正问题的关键时刻。这个问题类似于一群人在尝试一起解决一个谜题,但每个人都使用不同的拼图来组成完整的图像,因此难以协同合作。 幸运的是,有一种解决这个问题的方法,即采用统一的标准和词汇,以确保所有人都在同一个频道上。在工业控制系统中,这一标准就是MQTT Sparkplug。 什么是MQTT Sparkplug? MQTT Sparkplug是一种开源软件规范,旨在指导MQTT客户端如何在工业环境中使用MQTT协议。它的目标是消除在工业自动化中出现的通信混乱,提高互操作性,加速新设备的集成,以及降低因通信问题而导致的停机和风险。 Sparkplug通过定义特定的消息结构和协议规则,为工业4.0和工业物联网(IIoT)创建了即插即用的解决方案。 举例:想象一下,你正在管理一个工厂的自动化系统,其中有多个设备负责监测温度。但是,不同的工程师和供应商使用了不同的命名约定来表示温度数据。有的人称之为“温度1”,有的人称之为“热量-A”,还有的人称之为“温度_reading_5”。在没有统一标准的情况下,混乱不断上升,工程师们必须不断查看文档以了解各种温度传感器的命名约定。这不仅浪费时间,还可能导致错误和混淆。 MQTT Sparkplug的三个关键目标 MQTT Sparkplug旨在实现以下三个关键目标: 定义MQTT主题命名空间: 它提供了一种结构化方法来命名MQTT主题,以便在整个系统中统一表示不同设备和传感器的数据。这消除了在不同设备之间的不同命名约定所导致的混淆。 举例说明:使用Sparkplug,所有温度传感器可以使用相同的命名约定,例如“温度1”,“温度2”和“温度3”,使工程师能够轻松地订阅和理解这些数据。 定义MQTT状态管理: Sparkplug规范引入了状态管理,通过广播“出生消息”和“遗嘱消息”的方式,及时通知系统中的设备是否在线或离线。这消除了传统的轮询方式,减少了通信的带宽和计算资源的浪费。 举例说明:假设一个温度传感器由于故障而突然断线。使用Sparkplug,它将立即广播“离线”状态,而无需等待系统进行轮询检查。这大大提高了系统对设备状态的实时感知。 定义MQTT有效负载: 规范规定了如何结构化消息有效负载,使其易于理解和处理。每个消息有效负载包含了名称、别名、时间戳、数据类型和值,这使数据的解释和处理变得更加一致和方便。 举例说明:有效负载结构的统一性确保数据以一致的方式表示。例如,温度传感器的数据将包括名称("温度")、别名("温度传感器1")、时间戳、数据类型和实际温度值。这使数据处理变得更加简单,无需不断适应不同的数据格式。 MQTT Sparkplug的工作原理 在MQTT Sparkplug架构中,MQTT代理充当关键的中央枢纽。它负责接收发布的消息并将其路由到正确的订阅者。这种基于发布/订阅的消息传递方式使系统的组件能够以松散耦合的方式通信。 举例说明1:想象一下,多个温度传感器不断向MQTT代理发布温度数据。SCADA系统和其他应用程序可以订阅这些数据,而无需直接连接到传感器,从而实现了松散耦合的通信。 各种设备,特别是那些位于工厂设备的“边缘”或EON(Edge of Network)的设备,持续向MQTT代理发布数据。即使某些设备不支持原生的Sparkplug,它们仍然可以通过将数据发送到支持Sparkplug的EON节点来参与网络。 举例说明2:某台设备在工厂的边缘不支持Sparkplug,但它可以通过一个支持Sparkplug的EON网关将其数据发送到系统。这种灵活性确保了所有设备都可以参与通信。 SCADA/IIoT主机则是监视和控制这些EON节点及其下属设备和传感器的应用程序。它们连接到MQTT代理,可以实时监控设备状态、数据和执行控制操作。 说明:SCADA系统监视温度传感器的数据,并在需要时触发控制操作,例如调整温度设定或触发报警。 另外,还有MQTT应用节点,用于执行各种任务,例如数据历史记录、制造执行系统(MES)和数据分析。这些应用程序使用通过MQTT传输的数据,也可以生成消息以觋发操作。 说明:一个数据分析应用程序可以接收温度数据,将其与其他数据集进行比较,然后生成预测性维护建议,例如何时对设备进行维护,以确保其正常运行。 MQTT Sparkplug的优势 为什么要选择MQTT Sparkplug?这个规范提供了许多优势: 数据互操作性: 通过统一的消息结构和协议规则,Sparkplug确保不同设备之间的数据能够互操作,无需在通信上投入大量精力。 说明:无论哪家供应商提供的温度传感器,它们都能够在相同的系统中无缝运行,因为它们遵循了相同的Sparkplug规范。 节省带宽和资源: 通过“按异常报告”的状态管理方式,减少了不必要的轮询,从而节省了带宽和计算资源。 说明:使用Sparkplug,系统可以立即知道设备的状态变化,而不必频繁轮询设备,从而减少了通信开销。 支持传统设备: 即使某些设备不支持Sparkplug或MQTT,它们仍然可以通过使用EON节点来与系统集成。 说明:即使某个设备使用传统的通信协议,它可以通过连接到支持Sparkplug的EON节点来参与整个系统。 自动设备发现: Sparkplug关注统一性,使系统能够自动发现网络上的设备和数据。 举例说明:当新设备添加到系统中时,它们可以自动被发现并集成,而无需手动配置。 开源规范: Sparkplug是一个开源技术,无需许可,并且可以根据需要进行定制。 举例说明:无需支付昂贵的许可费用,您可以自由地采用和修改Sparkplug规范,以满足您的特定需求。 结论 MQTT Sparkplug是工业控制系统中的一项关键技术,它大大简化了设备之间的通信和集成,提高了系统的互操作性和可靠性。它为工业4.0和工业物联网(IIoT)的实施提供了强大的支持,使工业自动化系统更加安全、高效和可用。如果您正在考虑采用最新的工业技术,MQTT Sparkplug是您的有力助手,为您铺平通往成功的道路。在这个过程中,可以考虑与值得信赖的合作伙伴如Outlier Automation合作,以实现自动化目标。无论您需要帮助开始使用MQTT Sparkplug,计划升级PLC,还是进行概念验证,Outlier Automation都可以提供专业支持,助您顺利实现工业自动化的目标。 --- ### 81. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 新的v3.0.0 Sparkplug®规范对之前版本进行了整理和正式化。根据Eclipse Sparkplug工作组的说法,其目标是澄清v2.2版本中存在的模糊不清的地方,并明确规范性的陈述,同时保持v2.2规范的总体意图。 例如,新规范的第2章“原则”取代了2.2规范中的“背景”章节。现在,它详细描述了Sparkplug的关键原则,第5章“操作行为”非常详细地描述了Sparkplug环境的操作方面。该组织还包括了MQTT v5.0的特定设置,特别是关于不同会话设置的设置,例如MQTT 3.1.1中的“清除会话”与v5.0中的“清除开始”。 Sparkplug基础设施对MQTT服务器(在规范文件中,将“MQTT代理”称为“MQTT服务器”)有特定的要求。任何完全符合MQTT v3.1.1的服务器/代理都将符合Sparkplug基础设施的要求。 然而,并不是MQTT规范的所有功能都是必需的。 基本要求功能包括: 用于数据的QoS 0(最多一次) 用于状态管理的QoS 1(至少一次) 保留消息支持 状态管理的“遗嘱消息”(LWT) 支持通配符 规范区分了“符合Sparkplug MQTT服务器”和“了解Sparkplug MQTT服务器”。让我们快速看看两者之间的区别。 符合Sparkplug MQTT服务器 符合Sparkplug MQTT服务器必须支持以下功能: 在QoS 0上发布和订阅 在QoS 1上发布和订阅 遗嘱消息的所有方面,包括使用保留标志和QoS 1 保留标志的所有方面 了解Sparkplug MQTT服务器 而了解Sparkplug MQTT服务器包括了符合Sparkplug MQTT服务器的所有方面,并且必须具备以下额外的能力: 在MQTT服务器传递NBIRTH消息时,存储NBIRTH消息 将NBIRTH消息提供在以下形式的主题上: $sparkplug/certificates/{namespace}/{group_id}/NBIRTH/{edge_node_id}假设group_id=GROUP1和edge_node_id=EON1,则必须在主题上提供NBIRTH消息:$sparkplug/certificates/spBv1.0/GROUP1/NBIRTH/EON1 将NBIRTH消息提供在以下形式的主题上: $sparkplug/certificates/{namespace}/{group_id}/NBIRTH/{edge_node_id}并将MQTT保留标志设置为true 将DBIRTH消息提供在以下形式的主题上: $sparkplug/certificates/namespace/group_id/DBIRTH/edge_node_id/device_id假设group_id=GROUP1,edge_node_id=EON1和device_id=DEVICE1,则必须在主题上提供DBIRTH消息:$sparkplug/certificates/spBv1.0/GROUP1/DBIRTH/EON1/DEVICE1 将DBIRTH消息提供在以下形式的主题上: $sparkplug/certificates/{namespace}/{group_id}/DBIRTH/{edge_node_id}/{device_id}并将MQTT保留标志设置为true 此外,了解Sparkplug MQTT服务器还可以替换NDEATH消息的时间戳。如果这样做,它必须将时间戳设置为UTC时间,以尝试将NDEATH传递给订阅客户端的时间。 因此,了解Sparkplug MQTT服务器扩展了Sparkplug的状态管理方法。简而言之,出生和死亡证书现在被存储为保留消息,并提供了新引入的主题结构$sparkplug/certificates/#。 更新NDEATH消息的时间戳的这一可选功能是这个版本的亮点。这些时间戳由于“遗嘱功能”而存储在代理中。遗嘱消息包含在MQTT连接尝试中,并且将包含无条件客户端断开连接的时间戳,实际上是未知的。这个(可选的)时间戳更新LWT消息发布解决了这个问题。 通过Sparkplug®兼容性计划让终端用户知道您已经准备好了 Sparkplug兼容性计划允许软件和硬件供应商证明其产品与Eclipse Sparkplug和基于MQTT的物联网基础设施兼容,并为之获得认证。 获得认证的供应商使集成商和终端用户能够轻松地采购与Sparkplug规范兼容的设备和软件产品。该计划确保其解决方案能够与工业物联网中最常见的设备和网络无缝集成。 要获得认证,供应商的产品必须通过多个开源测试,以确认其符合Sparkplug技术兼容性工具包(TCK)的标准。如果产品通过了兼容性测试,Sparkplug工作组将将其添加到其官方的兼容产品列表中(可以在其网站上找到)。一旦获得许可,供应商可以使用Sparkplug兼容的标志向外界宣传其兼容性。 https://sparkplug.eclipse.org/compatibility/get-listed/ 以下是您需要了解有关TCK的信息… Sparkplug技术兼容性工具包(TCK) 适当的Sparkplug实施需要完全兼容以下组件: 网络边缘节点/设备, 主要应用程序,当然还有 MQTT代理。 Sparkplug技术兼容性工具包(TCK)提供了指南,验证所有待认证的组件是否符合Sparkplug规范。 TCK是一个Web应用程序,包括一个带有HiveMQ扩展和Web界面的HiveMQ代理。Web界面提供了对兼容性测试的访问。 TCK可以在Eclipse Sparkplug存储库中找到。 要使用JDK 11构建Sparkplug TCK HiveMQ扩展(JDK 17不起作用),请从GitHub中的“sparkplug/tck”进行检出并运行./gradlew。您可以在项目文件夹的build/hivemq-extension中找到扩展工件。 您必须向HiveMQ代理添加WebSocket监听器,并将扩展包含在HiveMQ的扩展文件夹中。启动或重新启动HiveMQ后,扩展即可使用。 如果您想要在自己的IDE中直接运行或调试HiveMQ扩展,请使用./gradlew runHivemqWithExtension。在此Gradle目标中,HiveMQ Community Edition将自动下载并根据Gradle构建文件中的任务完全配置为TCK扩展。 如上所述,基于Nuxt.js(Vue.js)的Web控制台控制TCK。确保您的计算机上有最新版本的yarn和node.js。Mac用户应该查找brew install yarn和brew install node。如果出现错误消息:“env:node:No such file or directory”,这意味着未安装node。在这种情况下,您可以使用yarn install和yarn dev(有关更多详细信息,请参阅webconsole readme)来安装和启动Web控制台。 TCK Web控制台可以通过浏览器中的http://localhost:3000访问: 您可以为主机应用程序、边缘节点和MQTT代理选择Sparkplug符合性配置文件。 主机应用程序配置文件包含用于测试以下内容的测试: 会话建立 会话终止 发送命令 边缘会话终止 消息排序和 多个MQTT服务器(代理)。 边缘节点测试包括 会话建立 会话终止 发送数据、发送复杂数据 接收命令 主机和多个MQTT服务器(代理)。 使用代理配置可以测试MQTT代理是否符合Sparkplug规范并具有了解Sparkplug的功能。 结论 尽管没有太多新规定,但新规范已经整理了许多主题,并更严格和全面地阐述了它们。然而,真正的收获主要在于证书产品或甚至检查产品的Sparkplug兼容性的可能性。这不仅对制造商有增值,也对终端用户有增值。 --- ### 82. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 随着工业物联网(IIoT)的部署日益增多和成熟,它们为全球的工业和制造组织带来了服务创新、生产力增加、运营流程优化,最重要的是成本降低。一些公司正在扩展其用例,而其他公司刚刚起步。根据Grandview Research的估计,全球IIoT市场规模为2630亿美元,到2028年将增长到1.11万亿美元(图1)。 图1:Grandview Research估计的IIoT市场规模 实现投资回报率(ROI)并从IIoT中获得价值取决于一个关键因素:数据。操作数据支持用例,如机器状态监测、提高OEE和实施预防性维护。数据的连通性和可用性通常是IIoT部署的主要挑战。因此,我们已经看到了两种旨在解决数据传输挑战并帮助制造业变得数据驱动的开放标准消息传递协议的增加采用 - MQTT和Sparkplug。 MQTT是一种轻量级的发布/订阅消息传递协议,非常适合连接远程设备(例如,IIoT)。MQTT具有小的代码占用空间。这种设计允许数据在具有资源限制或有限网络带宽的复杂通信环境中传输。MQTT已经成为IIoT通信中设备消息传递的事实标准,数百万设备利用其功能。 更近期,Sparkplug已经成为一项新的开放规范,当与MQTT一起部署时,它在成本节省、上市时间缩短、降低复杂性和提高生产力方面产生了数量级的业务益处。本文将重点讨论这些业务益处,强调采用MQTT/Sparkplug架构所产生的积极结果和投资回报率。虽然对这些部署的技术方面有一些一般性了解会有所帮助,但我们在本文中的目标是分享采用Sparkplug将如何积极影响您的业务,并帮助您更有效地竞争并降低成本。 什么是Sparkplug? Sparkplug是一种针对智能制造和工业物联网中提高MQTT互操作性的开源软件规范。该规范提供了操作技术(OT)数据的上下文,以便与信息技术(IT)以双向和互操作的方式进行无缝集成。更简单地说,Sparkplug可以使边缘到云或企业数据中心的数据标准化,以便用于创建本地统一命名空间,用于机器学习或其他IIoT应用程序。 MQTT有效地使得IIoT框架中的任何设备或系统能够连接到任何类型或型号的设备。然而,MQTT消息传递不提供有关其共享的信息的上下文。Sparkplug的添加为工业数据提供了必要的上下文,以便根据数据的需求采取特定类型的操作。借助MQTT和Sparkplug,任何应用程序或设备都可以订阅数据。新的数据源可以立即被其他系统组件发现,这些数据源可以成为整个系统可以采取操作的唯一真相来源。 Sparkplug架构可能如图2所示,具有在一侧产生数据的启用了Sparkplug的OT系统,中间是完全符合Sparkplug规范的MQTT代理以传输数据,另一侧是启用了Sparkplug的IT系统以消耗数据。数据可以双向流动,Sparkplug增加了有价值的上下文,包括MQTT主题结构定义、MQTT状态管理和负载数据定义。 图2:IIoT的新架构 因此,Sparkplug为工业组织提供了一些关键能力。首先,它标准化和定义了OT数据,以便所有订阅者都知道如何使用它,无需特殊编程或编码。这使得我们上面提到的“单一真相”成为整个组织的IIoT架构中的混淆消除,允许所有云和企业系统利用数据。 其次,Sparkplug使组织能够将设备连接到基础设施而不是应用程序。通过这样做,该规范为其他系统摄取数据为其目的铺平了道路。第三,Sparkplug为真正的、关键任务的IIoT应用程序奠定了基础,具有极高的可靠性和低延迟操作。没有这些特点,真正的IIoT是无法存在的。最后,Sparkplug实现了一个真正的、互操作的“即插即用”IIoT环境。不仅可以轻松分发消息,还可以为这些消息定义共同的含义,它们代表哪些设备以及应该如何处理它们。 让我们看看采用Sparkplug如何能积极影响您的业务。 通过开放标准避免供应商“锁定” 在一个自1978年以来一直采用相同控制和命令系统策略的市场中,OT-IT协作的出现应该为工业组织带来灵活 性的欢迎变化。几十年来,系统和应用程序的硬编码意味着公司不得不依赖于单一供应商。这些供应商可以有效地“锁定”他们的客户,因为移动的风险、成本和集成问题对大多数工业公司来说过于繁重。 通过由厂商中立的非营利组织(在Sparkplug的情况下是Eclipse基金会)管理的开放规范,工业组织现在可以轻松、具有成本效益地从硬编码的专用系统迁移到开放标准的世界。公司可以轻松升级标准化系统或更换其他解决方案。 将开放规范(如Sparkplug)和开源软件应用于工业制造领域将为从使用专有接口并在固定功能硬件上运行工作负载转向在商用现成硬件上运行的可互操作的工作负载的戏剧性变化奠定基础。这种转变将导致广泛可扩展的解决方案,生成支持工业部门更高级附加值解决方案的标准化数据。 通过应用这些新兴模型,制造商将能够实现以下目标: 由于Sparkplug的互操作性,可以访问更多的供应商来获取解决方案。 最小化工作和风险的情况下,从一代技术升级到下一代。 合并现有系统并降低总拥有成本(TCO)。 简化和降低运营支出。 更快速地部署创新。 这种规模的转变将需要不仅仅是Sparkplug规范本身。还需要全球生态系统的供应商和公司共同合作,以持续推动工业部门的发展。这个过程在Sparkplug创立时已经得以实施,因为它是由Eclipse基金会管理的开源项目,是世界上最大的专注于IIoT和边缘技术的开源软件基金会。Eclipse基金会在提供供应商中立的管理方面拥有几十年的经验,同时吸引了行业领袖和创新型初创公司提供对Sparkplug和其他技术的发展提供意见和指导。 弥合OT和IT之间的鸿沟 在其核心,IIoT是关于利用IT的低成本、创新和灵活性,同时保留OT系统的高可靠性。这个概念并不新鲜,但许多以前的努力来弥合鸿沟令人困惑,并且存在着对工业网络产生负面影响的技术障碍。没有Sparkplug提供的数据上下文,IIoT架构往往无法满足成功使OT和IT系统协同工作所需的关键的“最后几英尺”。 Sparkplug彻底改变了游戏规则。通过上下文定义工业用途和意图,使IT系统能够轻松“摄取”和“理解”OT数据,这是以前不可能的,需要工业组织进行复杂、漫长且有缺陷的编码工作。这意味着额外的成本,前提是组织可以找到开展该项目的开发人员人才。 一旦Sparkplug降低了连接IT和OT系统的障碍,它们可以相互通信,然后IT系统可以根据OT数据进行高级分析和建模。创建反馈环路并根据OT数据采取行动的能力,从而提供了导致更具成本效益的架构的IT的所有优点。一些这些新的能力包括: 实时数据分析:启用Sparkplug的架构使得能够对工业环境中每个系统和设备生成的数据进行细粒度的实时分析。 数字孪生:智能传感器数据可以用于运行模拟,然后再部署实际设备之前。 应用AI和机器学习:Sparkplug使得实现AI的潜力,以提供关于运营效率的实时见解,成为相对简单的任务。 远程监控和预测分析:由MQTT和Sparkplug从OT到IT传递的数据可以用于进行高级分析,提供关于机器操作的见解,甚至可以实现预测性维护。 健康与安全:Sparkplug使得能够为安全和健康的工作环境做出贡献。 高级无线技术:通过Sparkplug,现在可以使用多种用于推进供应链应用的移动技术,如5G、LoRA、Wi-Fi7。 灵活的架构:基于MQTT和Sparkplug构建的IIoT网络为组织提供了惊人的灵活性,可以灵活管理供应商和资源。 减少系统复杂性并轻松扩展 Sparkplug启用系统的另一个关键好处是减少整个系统部署的复杂性,既可以在每个站点轻松复制所需的软件,也可以减少为服务相同区域所需的站点数量。许多数据传输解决方案都启用了自定义代码来操纵数据,而无 法扩展。Sparkplug为工厂提供了一个开放的数据传输结构,其中多个产品和系统都支持Sparkplug,并可以定义和配置模板。组织可以使用自动发现和模板快速添加新设备或站点。 一家大型石油和天然气公司的自动化专家分享了如何利用Sparkplug为一个业务单位降低了复杂性,从而每年节省了130万美元的软件编程成本。该业务单位每年建设50个新设施。通过为每个设施简化系统架构开发,他们实现了财务节省,并加快了上市时间。 这位会计专家认为,这种节省的财务成本是保守估算的,主要是因为Sparkplug使“写一次,随处使用”的模型成为可能,从而加速了构建系统架构的时间价值。他的Sparkplug启用系统将开发人员将新对象(如油罐、泵等)整合到系统中的时间从30分钟减少到5分钟,使用MQTT Sparkplug,或是6倍的集成时间。没有MQTT Sparkplug,该公司需要支付系统集成商多次构建相同的对象,多达三次(POC、PLC和HMI级别),实际上每次都要重新发明轮子。 通过利用Sparkplug的功能,他的团队还可以在无需派遣人员到远程站点的情况下,立即呼叫所有泵或所有油罐,并在需要时确定它们的状态。这些相同的系统还可以通过使用预测分析来主动警告团队是否存在问题,以识别事件是否即将发生。 除了减少编程时间外,Sparkplug系统还可以减少整个系统中的1:1关系的数量,降低了同时维护数十个站点的工作量。总的来说,这位自动化和IIoT专家通过Sparkplug系统将超过50个站点的总成本每年节省了260万美元以上。 实现关键任务的系统 Sparkplug对于实现具有低延迟架构的关键任务OT系统至关重要。Sparkplug的互操作的“即插即用”能力以及作为真相的单一来源的能力使得复杂的边缘计算架构成为现实。边缘计算将数据和计算智能放置在与其交互的物理对象附近,从而减少了系统的延迟,使反应更加迅速,性能更好。在工厂车间中,Sparkplug启用的架构可以比传统的OT系统更快地处理数千兆字节的数据,并且成本更低。从运营到预测性维护等,这种架构使企业能够比将信息批量传输并将其发送到其他地方进行处理的情况下采取更快的行动。 结论 Sparkplug的使用正在跨足众多行业。主要的汽车、制造、工业、石油和天然气以及供应链/物流公司正在利用其能力。云超大规模供应商正在积极利用这一规范来构建针对行业市场的新托管服务。这意味着如果您的竞争对手尚未使用Sparkplug,他们可能正在积极评估将其集成到其环境中。IIoT World最近进行的一项调查问及正在构建IIoT系统的公司认为哪些数据传输工具对于实现他们的IIoT战略至关重要。55%的回答是MQTT,令人印象深刻的25%回答是MQTT Sparkplug,巩固了这一相对新技术作为公司数字转型和IIoT项目的关键组成部分。 图3:许多部署IIoT的公司认为MQTT和Sparkplug至关重要 随着一个强大且开放的生态系统支持这项技术的发展,并且市场对其部署的广泛支持,Sparkplug应该成为您未来IIoT部署计划的重要组成部分。鉴于其益处,Sparkplug可以并将为您的组织带来竞争优势。 --- ### 83. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT MQTT(也称为MQ遥测传输)是一种建立在TCP/IP之上的物联网连接协议,用于支持轻量级发布/订阅消息传输。 配置 要将MQTT集成添加到您的Home Assistant实例,使用以下“我的按钮”: 手动配置步骤 如果上面的“My按钮”不起作用,您还可以手动执行以下步骤: 浏览到您的Home Assistant实例。 转到 设置 > 设备和服务。 在右下角,选择“添加集成”按钮。 从列表中选择MQTT。 按照屏幕上的说明完成设置。 让MQTT和Home Assistant配合的第一步是选择一个代理(broker)。 选择MQTT代理 运行您自己的 最私密的选项是运行您自己的MQTT代理。 建议的设置方法是使用Mosquitto MQTT代理插件。 注意 不支持ActiveMQ MQTT代理和RabbitMQ MQTT插件,应使用已知工作的代理,如Mosquitto。ActiveMQ MQTT代理存在至少两个问题,会破坏MQTT消息保留。 使用公共代理 Mosquitto项目运行一个公共代理。这是最简单的设置方法,但由于所有消息都是公开的,因此没有隐私性。只应用于测试目的,不用于实际跟踪设备或控制家庭。要使用公共Mosquitto代理,请将MQTT集成配置为连接到测试test.mosquitto.org代理,端口为1883或8883。 代理配置 MQTT代理设置是在首次设置MQTT集成时配置的,以后如果需要可以更改。 添加MQTT集成,然后提供您的代理主机名(或IP地址)和端口,以及(如果需要)Home Assistant应该使用的用户名和密码。要稍后更改设置,按照以下步骤操作: 转到设置 > 设备和服务。 选择MQTT集成。 选择配置,然后重新配置MQTT。 注意 如果出现错误消息,如“Failed to connect due to exception: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed”,然后打开高级选项,将代理证书验证Advanced options设置为Auto。 高级代理配置 高级代理配置选项包括设置自定义客户端ID、为身份验证设置客户端证书和密钥,以及启用代理证书的TLS验证。要访问高级设置,打开MQTT代理设置,打开高级选项Advanced options,然后单击“下一步Next”。如果已经存在高级设置,则高级选项将默认显示。 注意 高级代理选项仅在启用高级模式(请参阅用户设置)或已配置高级代理设置时才可访问。 默认客户端ID 您可以设置自定义的MQTT客户端ID,这在调试时很有帮助。请注意,客户端ID必须是唯一的。如果希望Home Assistant生成唯一ID,请保留此设置的默认值。 保持活动时间 在此客户端发送保持活动消息之间的时间,以秒为单位。默认值为60秒。保持活动设置应至少为15秒。 代理证书验证 要启用安全代理,必须验证代理证书。如果您的代理使用受信任的证书,选择自动Auto。这将允许根据捆绑的证书验证CA。如果使用自签名证书,请选择自定义Custom。可以上传自定义PEM编码的CA证书。单击“下一步NEXT”以显示上传CA证书的控件。如果服务器证书与主机名不匹配,那么验证将失败。要允许不验证主机名的连接,请打开忽略代理证书验证Ignore broker certificate validation开关。 MQTT协议 MQTT协议设置默认为版本3.1.1。如果您的MQTT代理支持MQTT版本5,您可以将协议设置为5。 保护连接 通过安全代理连接,可以使用客户端证书进行身份验证。要设置客户端证书和私钥,请打开“使用客户端证书Use a client certificate”选项,然后单击“下一步”以显示上传文件的控件。只能上传PEM编码的客户端证书以及PEM编码的私钥。请确保私钥没有设置密码。 使用WebSockets作为传输 如果您的MQTT代理支持,可以选择WebSocket作为传输方法。当您选择WebSocket并单击“NEXT”时,您将能够添加WebSocket路径(默认值=/)和WebSocket标头(可选)。目标WebSocket URI: ws://{broker}:{port}{WebSockets path} 是使用broker、port和ws_path(WebSocket路径)设置构建的。要配置WebSocket标头,请提供有效的JSON字典字符串。例如,{ "Authorization": "token" , "x-header": "some header" }。默认的传输方法是TCP。WebSocket传输可以使用TLS进行保护,也可以选择使用用户凭据或客户端证书。 注意 配置好的客户证书只有在启用代理证书验证时才会生效。 配置MQTT选项 要更改设置,请按照以下步骤进行: 转到 设置 > 设备与服务。 选择MQTT集成。 选择配置,然后重新配置MQTT。 要打开MQTT选项页面,请选择“下一步”。 发现选项 MQTT发现默认启用。可以关闭发现。在这里还可以更改发现主题的前缀(默认为homeassistant)。也可以参考MQTT发现部分。 出生和遗嘱消息 Home Assistant的MQTT集成支持所谓的出生消息和遗嘱消息。前者用于在服务启动后发送消息,后者用于通知其他客户端有关已断开连接的客户端。请注意,无论是干净的(例如Home Assistant关闭)还是不干净的(例如Home Assistant崩溃或失去网络连接)断开连接,遗嘱消息都会被发送。 默认情况下,Home Assistant会发送在线online和离线消息offline到homeassistant/status。 MQTT出生和遗嘱消息可以从用户界面自定义或禁用。要做到这一点,点击用户界面上的集成页面中的“配置”,然后“重新配置MQTT”,然后“下一步”。 测试您的设置 mosquitto代理包提供了命令行工具(通常作为*-clients包)用于发送和接收MQTT消息。要向在localhost上运行的代理发送测试消息,请查看以下示例: mosquitto_pub -h 127.0.0.1 -t homeassistant/switch/1/on -m "Switch is ON" 手动发送MQTT消息的另一种方法是使用前端的MQTT集成。在左侧菜单上选择“设置”,单击“设备与服务”,并在“Mosquitto代理”瓷砖下选择“配置”。在“发布数据包”下的“主题”字段中输入类似下面的内容,然后按“发布”。 转到 设置 > 设备与服务。 选择Mosquitto代理集成,然后选择配置。 在“发布数据包”下的“主题”字段中输入类似下面的内容。选择“发布”。 homeassistant/switch/1/power 并在有效载荷字段中 ON 在“监听主题”字段中,键入#以查看所有内容,或键入“homeassistant/switch/#”以只关注一个发布的主题,然后按“开始监听”。消息应该类似于下面的文本: Message 23 received on homeassistant/switch/1/power/stat/POWER at 12:16 PM: ON QoS: 0 - Retain: false Message 22 received on homeassistant/switch/1/power/stat/RESULT at 12:16 PM: { "POWER": "ON" } QoS: 0 - Retain: false 要读取在localhost上运行的代理上发送的主题homeassistant的所有消息 mosquitto_sub -h 127.0.0.1 -v -t "homeassistant/#" 设备配置共享 MQTT实体可以共享设备配置,这意味着一个实体可以包括完整的设备配置,而其他实体只需设置强制字段即可连接到该设备。强制字段以前仅限于连接和标识符中的至少一个,但现在已扩展到连接和标识符中至少一个以及名称。 MQTT实体的命名 对于每个配置的MQTT实体,Home Assistant会自动分配唯一的实体ID。如果配置了唯一ID选项,您可以在创建后更改实体ID,并更改将存储在实体注册表中。实体ID在第一次加载项目时生成。 如果设置了object_id选项,那么它将用于生成实体ID。例如,如果我们配置了一个传感器,并将object_id设置为test,那么Home Assistant将尝试分配传感器.test作为实体ID,但如果该实体ID已存在,它将附加后缀以使其唯一,例如sensor.test_2。 这意味着作为设备的一部分的任何MQTT实体将自动将其friendly_name属性前缀添加到设备名称 未命名的二进制传感器、按钮、数字和传感器实体现在将根据其设备类而不是命名为“MQTT二进制传感器”等。可以将MQTT实体的名称设置为无(在YAML中使用null)以将其标记为设备的主要特性。 请注意,每个MQTT实体上都将设置has_entity_name属性为True。更多细节可以在此处找到。 MQTT发现 MQTT设备的发现将允许您在Home Assistant方面仅需进行最少配置即可使用MQTT设备。配置是在设备本身和设备使用的主题上完成的,类似于HTTP二进制传感器和HTTP传感器。为了防止设备重新连接时多个相同的条目,需要唯一标识符。设备侧需要两个部分:包含必要设备类型和唯一标识符的配置主题,以及没有设备类型的剩余设备配置。 由MQTT发现支持的实体集成 报警控制面板 二进制传感器 按钮 摄像机 遮阳器 设备跟踪器 设备触发器 事件 风扇 加湿器 图像 气候/暖通 割草机 灯光 锁 数字 场景 选择 传感器 警报器 开关 更新 标签扫描器 文本 真空 热水器 MQTT发现默认启用,但可以禁用。发现主题的前缀(默认为homeassistant)可以更改。请参见MQTT选项部分 发现消息 发现主题 发现主题需要遵循特定的格式: <discovery_prefix>/<component>/[<node_id>/]<object_id>/config <发现前缀>:发现前缀默认为homeassistant。此前缀可以更改。<组件>:支持的MQTT集成之一,例如二进制传感器。<节点ID>(可选):提供主题的节点的ID,Home Assistant不使用此节点ID,但可能用于构造MQTT主题。节点的ID必须仅由字符类[a-zA-Z0-9_-](字母数字、下划线和连字符)的字符组成。<对象ID>:设备的ID。这仅允许为每个设备分别设置主题,并不用于entity_id。设备的ID必须仅由字符类[a-zA-Z0-9_-](字母数字、下划线和连字符)的字符组成。<节点ID>级别可以由客户端使用一个通配主题<发现前缀>/+/<节点ID>/+/set来仅订阅自己的(命令)主题。 对于具有唯一ID的实体,最佳做法是将设置为unique_id并省略。 发现负载 负载必须是序列化的JSON字典,如果添加新设备,则将像在configuration.yaml文件中的条目一样进行检查,不同之处在于允许未知的配置键,但会被忽略。这意味着缺少的变量将使用集成的默认值填充。所有必需的配置变量必须在负载中存在。允许未知文档键的原因是允许一些向后兼容性,生成MQTT发现消息的软件可以与旧的Home Assistant版本一起使用,旧版本将简单地忽略新功能。 在接收到有效负载的主题上的后续消息将被视为配置更新,并且具有空负载的配置更新将导致先前发现的设备被删除。 负载中可以定义一个基本主题~,以在多次使用相同主题基础时节省内存。在以_topic结尾的配置变量的值中,如果~位于值的开头或结尾,将用基本主题替换~。 发现负载中的配置变量名称可以被缩写,以在从内存受限设备发送MQTT发现消息时节省内存。 鼓励通过在发现负载中添加来源选项(可缩写为o)来为通过MQTT发现提供MQTT实体的来源添加更多信息。请注意,这些选项也支持缩写。项目被发现或更新时,将日志记录有关来源的信息到核心事件日志中。 名称 发现MQTT项目的原始应用程序的名称。此选项为必填项。 sw_version 提供发现的MQTT项目的应用程序的软件版本。 support_url 提供发现的MQTT项目的应用程序的支持URL。 第三方工具的支持 以下软件内置支持MQTT发现: ArduinoHA Arilux AL-LC0X LED控制器 ebusd ecowitt2mqtt EMS-ESP32(和EMS-ESP) ESPHome ESPurna HASS.Agent IOTLink(从2.0.0开始) MiFlora MQTT守护程序 MyElectricalData Nuki Hub Nuki Smart Lock 3.0 Pro,更多信息 OpenMQTTGateway room-assistant(从1.1.0开始) SmartHome SpeedTest-CLI MQTT SwitchBot-MQTT-BLE-ESP32 Tasmota(从5.11.1e开始,开发已停止) TeddyCloud Teleinfo MQTT(从3.0.0开始) Tydom2MQTT What’s up Docker?(从3.5.0开始) WyzeSense2MQTT Xiaomi DaFang Hacks Zehnder Comfoair RS232 MQTT Zigbee2MQTT Zwave2Mqtt(从2.0.1开始) 发现示例 运动检测(二进制传感器) 一个运动检测设备可以用一个二进制传感器来表示,它会将其配置作为JSON有效负载发送到配置主题。在第一条消息到config后,发送到状态主题的MQTT消息将更新Home Assistant中的状态。 配置主题:homeassistant/binary_sensor/garden/config状态主题:homeassistant/binary_sensor/garden/state包含派生设备名称的配置有效负载: { "name":null, "device_class":"motion", "state_topic":"homeassistant/binary_sensor/garden/state", "unique_id":"motion01ad", "device":{ "identifiers":[ "01ad" ], "name":"Garden" } } 保留:使用-r开关将配置主题保留在代理中。如果没有这个,Home Assistant重新启动后传感器将不可用。还建议添加唯一ID,以允许更改实体和设备映射,以便我们可以将设备的所有传感器分组在一起。如果我们想要继承实体的设备名称,可以将“name”设置为null。如果设置了实体名称,友好名称将是设备名称和实体名称的组合。如果省略名称并设置了device_class,则实体名称部分将派生自device_class。 配置有效负载示例,不设置名称并派生device_class名称: { "name":null, "device_class":"motion", "state_topic":"homeassistant/binary_sensor/garden/state", "unique_id":"motion01ad", "device":{ "identifiers":[ "01ad" ], "name":"Garden" } } 如果没有设置名称,MQTT将设置默认名称(请参阅MQTT平台文档)。 要手动创建一个新的传感器,并将名称设置为null以派生设备名称“Garden”: mosquitto_pub -r -h 127.0.0.1 -p 1883 -t "homeassistant/binary_sensor/garden/config" -m '{"name": null, "device_class": "motion", "state_topic": "homeassistant/binary_sensor/garden/state", "unique_id": "motion01ad", "device": {"identifiers": ["01ad"], "name": "Garden" }}' 更新状态: mosquitto_pub -h 127.0.0.1 -p 1883 -t "homeassistant/binary_sensor/garden/state" -m ON 通过发送空消息删除传感器。 mosquitto_pub -h 127.0.0.1 -p 1883 -t "homeassistant/binary_sensor/garden/config" -m '' 有关更多详细信息,请参考MQTT测试部分。 传感器 设置具有多个测量值的传感器需要多个连续的配置主题提交。 配置主题1:homeassistant/sensor/sensorBedroomT/config配置有效负载1: { "device_class":"temperature", "state_topic":"homeassistant/sensor/sensorBedroom/state", "unit_of_measurement":"°C", "value_template":"{{ value_json.temperature}}", "unique_id":"temp01ae", "device":{ "identifiers":[ "bedroom01ae" ], "name":"Bedroom" } } 配置主题2:homeassistant/sensor/sensorBedroomH/config配置有效负载2: { "device_class":"humidity", "state_topic":"homeassistant/sensor/sensorBedroom/state", "unit_of_measurement":"%", "value_template":"{{ value_json.humidity}}", "unique_id":"hum01ae", "device":{ "identifiers":[ "bedroom01ae" ], "name":"Bedroom" } } 常见的状态有效负载: { "temperature":23.20, "humidity":43.70 } 具有命令主题的实体 设置灯、开关等类似,但需要使用MQTT开关文档中提到的command_topic。 配置主题:homeassistant/switch/irrigation/config状态主题:homeassistant/switch/irrigation/state命令主题:homeassistant/switch/irrigation/set有效负载: { "name":"Irrigation", "command_topic":"homeassistant/switch/irrigation/set", "state_topic":"homeassistant/switch/irrigation/state", "unique_id":"irr01ad", "device":{ "identifiers":[ "garden01ad" ], "name":"Garden" } } 保留:使用-r开关将配置主题保留在代理中。如果没有这个,Home Assistant重新启动后开关将不可用。 mosquitto_pub -r -h 127.0.0.1 -p 1883 -t "homeassistant/switch/irrigation/config" \ -m '{"name": "Irrigation", "command_topic": "homeassistant/switch/irrigation/set", "state_topic": "homeassistant/switch/irrigation/state", "unique_id": "irr01ad", "device": {"identifiers": ["garden01ad"], "name": "Garden" }}}' 设置状态: mosquitto_pub -h 127.0.0.1 -p 1883 -t "homeassistant/switch/irrigation/set" -m ON 使用缩写和基础主题 使用主题前缀和缩写配置变量名称来减小有效负载长度以设置开关。 配置主题:homeassistant/switch/irrigation/config命令主题:homeassistant/switch/irrigation/set状态主题:homeassistant/switch/irrigation/state配置有效负载: { "~":"homeassistant/switch/irrigation", "name":"garden", "cmd_t":"~/set", "stat_t":"~/state" } 另一个示例,使用缩写主题名称和基础主题设置采用JSON有效负载的灯: 配置主题:homeassistant/light/kitchen/config 命令主题:homeassistant/light/kitchen/set 状态主题:homeassistant/light/kitchen/state 示例状态有效负载:{"state": "ON", "brightness": 255} 配置有效负载: { "~": "homeassistant/light/kitchen", "name": "Kitchen", "uniq_id": "kitchen_light", "cmd_t": "~/set", "stat_t": "~/state", "schema": "json", "brightness": true } 在发现消息中使用缩写的设备和来源信息的示例 { "~": "homeassistant/light/kitchen", "name": null, "uniq_id": "kitchen_light", "cmd_t": "~/set", "stat_t": "~/state", "schema": "json", "dev": { "ids": "ea334450945afc", "name": "Kitchen", "mf": "Bla electronics", "mdl": "xya", "sw": "1.0", "hw": "1.0rev2", }, "o": { "name":"bla2mqtt", "sw": "2.1", "url": "https://bla2mqtt.example.com/support", } } 使用object_id影响实体ID 实体ID会根据实体的名称自动生成。所有MQTT集成都可以选择提供一个object_id,如果提供了,将使用它。 配置主题:homeassistant/sensor/device1/config示例配置有效负载: { "name":"My Super Device", "object_id":"my_super_device", "state_topic": "homeassistant/sensor/device1/state" } 在上面的示例中,实体ID将是sensor.my_super_device而不是sensor.device1。 手动配置的MQTT项目 对于大多数集成,还可以在configuration.yaml中手动设置MQTT项目。了解有关YAML配置的更多信息。 MQTT支持两种样式的YAML中配置项目的方式。所有配置项目都直接放在mqtt集成键下。请注意,不能混合使用这些样式。当有疑问时,请使用每个项目样式列出的YAML配置。 按项目列出的YAML配置 这种方法期望所有项目都在YAML列表中。每个项目都有一个{domain}键,项目配置直接放在域键下。这种方法被认为是最佳实践。在所有示例中,我们都使用这种格式。 mqtt: - {domain}: name: "" ... - {domain}: name: "" ... YAML配置由{domain}键分组和捆绑 根据{domain}分组的所有项目,列出所有配置。 mqtt: {domain}: - name: "" ... - name: "" ... 支持通过YAML进行设置的MQTT组件 报警控制面板 二进制传感器 按钮 相机 覆盖 设备追踪器 事件 扇子 加湿器 图像 气候/暖通空调 割草机 光 锁 数字 场景 选择 传感器 警笛 转变 文本 更新 真空 热水器 如果有许多手动配置的项目,您可能要考虑拆分配置。 使用模板 MQTT集成支持模板。了解有关在MQTT集成中使用模板的更多信息。 MQTT通知 MQTT通知支持与其他通知集成不同。它是一项服务。这意味着在调用服务时需要提供更多细节。 从开发人员工具->服务中的呼叫服务部分,允许您发送MQTT消息。从“可用服务”的列表中选择mqtt.publish,然后将类似下面的示例输入Service Data字段并单击CALL SERVICE。 { "~":"homeassistant/switch/irrigation", "name":"garden", "cmd_t":"~/set", "stat_t":"~/state" } 对于自动化,也是一样的。 示例 REST API使用REST API向给定主题发送消息。 $ curl -X POST \ -H "Authorization: Bearer ABCDEFGH" \ -H "Content-Type: application/json" \ -d '{"payload": "Test message from HA", "topic": "home/notification"}' \ http://IP_ADDRESS:8123/api/services/mqtt/publish 自动化 在自动化中使用作为脚本。 automation: alias: "Send me a message when I get home" trigger: platform: state entity_id: device_tracker.me to: "home" action: service: script.notify_mqtt data: target: "me" message: "I'm home" script: notify_mqtt: sequence: - service: mqtt.publish data: payload: "{{ message }}" topic: home/"{{ target }}" retain: true 发布和转储服务 MQTT集成将注册mqtt.publish服务,允许将消息发布到MQTT主题。有两种指定有效载荷的方法。您可以使用payload来硬编码有效载荷,或者使用payload_template来指定将呈现以生成有效载荷的模板。 SERVICE MQTT.PUBLISH服务数据属性 可选 描述主题 否 要发布有效载荷的主题。主题模板 否 要呈现为发布有效载荷的主题的模板。有效载荷 是 要发布的有效载荷。payload_template 是 要呈现为有效载荷值的模板。qos 是 要使用的服务质量。(默认值: 0)保留 是 消息是否应设置为保留标志。(默认值: false)您必须包括topic或topic_template中的一个,但不是两者都包括。如果提供有效载荷,则需要包括payload或payload_template中的一个,但不是两者都包括。 topic: homeassistant/light/1/command payload: on topic: homeassistant/light/1/state payload_template: "{{ states('device_tracker.paulus') }}" topic_template: "homeassistant/light/{{ states('sensor.light_active') }}/state" payload_template: "{{ states('device_tracker.paulus') }}" 有效载荷必须是字符串。如果要使用YAML编辑器发送JSON,那么需要正确格式化/转义它。像这样: topic: homeassistant/light/1/state payload: "{\"Status\":\"off\", \"Data\":\"something\"}"` 使用Home Assistant的YAML编辑器格式化JSON时,如果有效载荷包含模板内容,应格外小心。Home Assistant会强制您进入YAML编辑器,并将您的定义视为模板。确保像下面的示例中那样转义模板块。Home Assistant将将结果转换为字符串,并将其传递给MQTT发布服务。 下面的示例显示了如何发布温度传感器“浴室温度”。已设置device_class,因此不需要设置“name”选项。实体将从设置的device_class继承名称,并支持翻译。如果在有效载荷中设置了“name”,实体名称将以设备名称开头。 service: mqtt.publish data: topic: homeassistant/sensor/Acurite-986-1R-51778/config payload: >- {"device_class": "temperature", "unit_of_measurement": "\u00b0C", "value_template": "{{ value|float }}", "state_topic": "rtl_433/rtl433/devices/Acurite-986/1R/51778/temperature_C", "unique_id": "Acurite-986-1R-51778-T", "device": { "identifiers": "Acurite-986-1R-51778", "name": "Bathroom", "model": "Acurite-986", "manufacturer": "rtl_433" } } 使用qos和retain的示例: topic: homeassistant/light/1/command payload: on qos: 2 retain: true SERVICE MQTT.DUMP监听指定的主题匹配项,并在特定持续时间内将所有接收到的消息转储到配置文件夹中的mqtt_dump.txt文件中。这在调试问题时很有用。 服务数据属性 可选 描述主题 否 要转储的主题。可以包含通配符(#或+)。持续时间 是 我们将侦听消息的持续时间(以秒为单位)。默认值为5秒。 topic: openzwave/# 日志 logger集成允许记录接收的MQTT消息。 # Example configuration.yaml entry logger: default: warning logs: homeassistant.components.mqtt: debug 事件event_mqtt_reloaded 当手动配置的MQTT实体已重新加载并实体可能已更改时,将触发事件event_mqtt_reloaded。 此事件没有额外的数据。 --- ### 84. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT是什么?MQTT最初代表MQ Telemetry Transport,但MQTT现在不再是一个首字母缩写,它只是这个协议的名称。 什么是MQTT-SN? MQTT-SN代表传感器网络用的MQTT。MQTT-SN专为在无线网络上工作而设计,优化用于与通常通过无线网络通信的低功耗传感器一起工作。MQTT-SN与标准MQTT的主要区别在于,MQTT-SN不需要TCP,可以使用串行通信协议,如Zigbee或Thread。其他差异包括MQTT-SN使用主题ID而不是主题名称,允许预定义主题,并为休眠客户端设备提供了保持活动功能。 MQTT与AMQP MQTT和AMQP都是用于在系统之间发送和接收消息的异步消息协议。主要区别在于,MQTT被高度优化用于IoT用例,因此是一种更小、更简单的协议。AMQP设计用于覆盖更一般的用例,因此具有更多可用的功能,但也更复杂且效率较低。 就功能而言,AMQP在安全选项方面可以被认为胜出,因为它默认包括诸如SASL之类的功能,而在MQTT中,您需要自己添加它。AMQP还提供了在保持向后兼容性的同时扩展协议的能力,而MQTT的更改需要版本更新。AMQP提供了除MQTT的发布/订阅模式之外的几种消息模式。与之相比,MQTT的主要优势在于它更轻量级,因此更适合电池和资源受限的硬件。MQTT还消耗更少的带宽,适用于不稳定的网络。简而言之,MQTT和AMQP之间的主要区别在于AMQP是一种通用消息协议,而MQTT是从头开始设计的一种专门的协议,以适应特定的用例。您是否应该使用MQTT还是AMQP将取决于哪种协议符合项目的要求。 MQTT与RabbitMQ RabbitMQ是一个开源的消息代理,而MQTT是一种轻量级的发布/订阅网络协议,专为物联网环境中的机器对机器通信而设计。RabbitMQ最初是专为与AMQP一起使用而设计的,但通过插件添加了对MQTT的协议支持,以及其他几种协议,如STOMP和HTTP。因此,RabbitMQ可以用作提供故障转移和群集化等出色功能的通用消息代理,而传递消息所使用的协议可以根据您的用例进行更改。 MQTT与HTTP HTTP是一种主要用于互联网应用的请求/响应协议。HTTP可以用于IoT用例,但并不是为此而设计。它在处理不稳定连接和处理大量连接设备的IoT环境中传递数据方面存在许多与消息大小和效率相关的缺点。 MQTT与COAP CoAP类似于HTTP,采用二进制格式的请求/响应模型,以使其更紧凑。MQTT使用发布/订阅模型进行通信。CoAP与MQTT之间最大的区别在于,MQTT侧重于成为一种多对多通信协议,通过代理将消息传递给许多客户端设备,而CoAP主要用于从客户端到服务器的一对一通信。可以将MQTT视为更适用于事件驱动应用程序,而CoAP最适合用于状态传输。 MQTT与Zigbee Zigbee与MQTT的主要区别在于,Zigbee是一种物理数据层协议,而MQTT是一种应用层协议。Zigbee专注于数据在设备之间实际传输的方式,旨在用作比蓝牙或WiFi等协议更简单的网状网络设备的替代方案。在许多情况下,Zigbee被用作最终将数据转换为MQTT的网关协议,以便将数据传送到云端。 MQTT与Thread Thread是另一种旨在用于低功耗和低延迟应用的协议,在许多情况下与Zigbee非常相似。因此,将MQTT用于应用层通信,而Thread用于数据传输的下一级。 MQTT通过WebSockets 一些MQTT代理支持WebSockets,允许您使用JavaScript从Web浏览器连接到MQTT代理。 MQTT 和 Node-Red 如果您不想编程,那么Node-Red是一个基于 Flow 的工具,可以轻松创建 MQTT 项目。 什么是OASIS? OASIS(结构化信息标准推进组织)是负责开发和维护MQTT规范以及许多其他项目的联盟。OASIS成立于1993年,是一个专注于一种名为SGML的标记语言的贸易协会。随着时间的推移,OASIS扩大了范围,现在维护了AMQP、MQTT、SAML和Legal XML等协议。OASIS的成员包括Oracle、Red Hat、通用汽车、IBM、微软、美国律师协会等众多组织。 --- ### 85. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Zigbee2MQTT 是一个流行的项目,使 Zigbee 设备能够与 MQTT 代理进行通信,进而允许各种智能家居平台(如 Home Assistant)与 Zigbee 设备进行交互。下面是在 Home Assistant 中使用 Zigbee2MQTT 的完整指南: 1. 安装 Mosquitto MQTT broker 首先,如果您还没有 MQTT broker,需要安装一个。在 Home Assistant 中,转到 设置 → 插件 → 插件商店,然后安装 Mosquitto broker 插件。 2. 添加 Zigbee2MQTT 仓库 回到插件商店,点击 ⋮ → 仓库。 输入以下地址:https://github.com/zigbee2mqtt/hassio-zigbee2mqtt,然后点击 添加 → 关闭。 在 Home Assistant 实例中,您将看到预填充了特定仓库 URL 的插件仓库对话框。 3. 选择并安装 Zigbee2MQTT 插件 Zigbee2MQTT:这是稳定版本,追踪 Zigbee2MQTT 的已发布版本,推荐大多数用户使用。 Zigbee2MQTT Edge:这是开发版本,有一些未正式发布的特性和修复。 选择所需的版本,点击 安装 并等待完成。 4. 配置 Zigbee2MQTT 转到 配置。 如果不使用 Mosquitto broker 插件,请填写您的 MQTT 详细信息。使用 Mosquitto broker 插件时,请留空。 mqtt: server: mqtt://localhost:1883 user: my_user password: "my_password" 填写串行详情,如您的 USB 协调器的端口。 serial: port: /dev/ttyUSB0 点击 保存。 通过转到 信息 并点击 开始 来启动插件。 等待 Zigbee2MQTT 启动,然后按 打开 WEB UI 以验证是否正确启动。 5. 从独立安装中恢复数据(如有需要) 确保两个环境都运行相同版本。 备份您的独立环境。 使用 HA 插件配置 UI 来配置串行端口。 恢复数据。 确保配置文件的串行端口部分与 UI 的配置匹配。 启动插件。 6. 注意事项与故障排除 如果遇到 502: Bad Gateway 错误,请稍等片刻后刷新页面。 如果插件启动时间过长,检查 日志 选项卡以查看出了什么问题。 如果您在插件中发现任何问题,请首先检查问题跟踪器中是否有类似的问题。 7. 更多资源 要了解更多详细信息和进阶功能,请参考 Zigbee2MQTT 官方文档。 总之,Zigbee2MQTT 为 Home Assistant 用户提供了与 Zigbee 设备通信的强大工具。通过遵循上述步骤,您可以轻松地将 Zigbee 设备集成到您的智能家居环境中。 --- ### 86. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Flask,一个轻量级的Web应用框架,被许多开发者所喜爱。与此同时,MQTT作为一种轻量级物联网消息传输协议,广泛应用于各种场景。那么,如何结合两者的优势呢?答案是使用Flask-MQTT。 项目前期准备 环境检查:确保您的开发环境为Python 3.8,您可以通过以下命令来确认: $ python3 --version 安装必要库:使用pip安装Flask-MQTT库: pip3 install flask-mqtt Flask-MQTT初步使用 导入必要模块: from flask import Flask, request, jsonify from flask_mqtt import Mqtt 初始化Flask应用并配置MQTT: app = Flask(__name__) # MQTT配置 app.config['MQTT_BROKER_URL'] = 'broker.emqx.io' app.config['MQTT_BROKER_PORT'] = 1883 app.config['MQTT_USERNAME'] = '' # 添加用户名,如果有的话 app.config['MQTT_PASSWORD'] = '' # 添加密码,如果有的话 app.config['MQTT_KEEPALIVE'] = 5 app.config['MQTT_TLS_ENABLED'] = False 设置主题和初始化MQTT客户端: topic = '/flask/mqtt' mqtt_client = Mqtt(app) 连接回调函数:定义当连接成功或失败时的操作,例如订阅主题: @mqtt_client.on_connect() def handle_connect(client, userdata, flags, rc): if rc == 0: print('Connected successfully') mqtt_client.subscribe(topic) else: print('Connection failed. Code:', rc) 消息回调函数:定义接收消息后的操作: @mqtt_client.on_message() def handle_mqtt_message(client, userdata, message): data = dict( topic=message.topic, payload=message.payload.decode() ) print('Received message: {payload} from topic: {topic}'.format(**data)) 定义消息发布接口:创建一个API接口,允许外部发布消息到指定主题: @app.route('/publish', methods=['POST']) def publish_message(): request_data = request.get_json() publish_result = mqtt_client.publish(request_data['topic'], request_data['msg']) return jsonify({'status': 'success' if publish_result[0] == 0 else 'failed'}) 启动Flask应用: if __name__ == '__main__': app.run(host='127.0.0.1', port=5000) 通过以上步骤,您已经成功地构建了一个能够与MQTT服务器进行交互的Flask应用。可以通过POST接口发送消息,并在主题/flask/mqtt上接收消息。 希望这篇文章能帮助您更好地理解Flask和MQTT的结合,并在实际项目中运用。 --- ### 87. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Mosquitto: 轻量级的MQTT代理服务器 随着物联网(IoT)和机器与机器(M2M)通信的普及,需要一个轻量级、高效、易于实现的消息协议来满足这些需求。这就是MQTT(消息队列遥测传输)的诞生背景。而Mosquitto则是该协议的一个开源实现。 1. 什么是Mosquitto? Mosquitto是一个开源的MQTT代理服务器,它允许开发者快速、简单地搭建和运行MQTT服务器。它旨在为各种设备和应用提供轻量级的发布/订阅消息模式,特别是在网络带宽有限、可靠性要求高、或者运行环境资源受限的情境下。 2. 主要特点 轻量级:对于资源受限的设备和网络,Mosquitto提供了一个紧凑、低带宽的解决方案。 开源:Mosquitto是完全开源的,允许开发者自由地查看源代码、修改并根据需求进行部署。 跨平台:支持多种操作系统,如Linux、Windows和MacOS。 安全性:支持TLS/SSL加密,确保数据的安全性和隐私性。 3. 如何使用Mosquitto? 使用Mosquitto非常简单。首先,你需要安装Mosquitto代理服务器。此篇教程将引导你在CentOS7上搭建MQTT服务器,并使用Python进行简单的测试。 1. 环境准备: 确保你的系统是CentOS7,并具有sudo权限。 2. 安装必备软件: yum install gcc-c++ cmake openssl-devel -y 3. 下载并安装mosquitto: wget http://mosquitto.org/files/source/mosquitto-1.6.8.tar.gz tar -zxvf mosquitto-1.6.8.tar.gz cd mosquitto-1.6.8 make sudo make install 如果出现链接问题,可以通过以下命令修复: sudo ln -s /usr/local/lib/libmosquitto.so.1 /usr/lib/libmosquitto.so.1 sudo ldconfig 4. 配置mosquitto: 创建配置文件: mv /etc/mosquitto/mosquitto.conf.example /etc/mosquitto/mosquitto.conf 创建用户组和用户: sudo groupadd mosquitto sudo useradd -g mosquitto mosquitto -s /sbin/nologin 5. 启动mosquitto: mosquitto -c /etc/mosquitto/mosquitto.conf -d 6. 使用mosquitto进行简单的测试: 打开订阅者终端: mosquitto_sub -t topic 打开发布者终端: mosquitto_pub -t topic -m "Hello MQTT" 7. 使用Python进行测试: 首先,确保安装了paho-mqtt库: pip install paho-mqtt 订阅者: import paho.mqtt.client as mqtt def on_connect(client, userdata, flags, rc): print("Connected with result code: " + str(rc)) def on_message(client, userdata, msg): print(msg.topic + " " + str(msg.payload)) client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect('localhost', 1883, 600) client.subscribe('test', qos=0) client.loop_forever() 发布者: import paho.mqtt.client as mqtt def on_connect(client, userdata, flags, rc): print("Connected with result code: " + str(rc)) client = mqtt.Client() client.on_connect = on_connect client.connect('localhost', 1883, 600) client.publish('test', payload='Hello from Python', qos=0) 先运行订阅者脚本,然后运行发布者脚本。此时订阅者应该能够接收到来自发布者的消息。 至此,您已成功在CentOS7上搭建了一个MQTT服务器,并用Python进行了简单测试。如果希望进一步加强安全性,可以考虑为MQTT添加TLS/SSL加密等安全措施。 --- ### 88. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. Qt简介 Qt是一款跨平台的C++图形用户界面应用程序开发框架。它不仅支持窗口操作系统,还支持大多数Unix系统、Android、iOS等。因为其高度模块化的设计,Qt被广大开发者用来创建高性能的嵌入式和移动应用。 2. MQTT简介 MQTT,全称Message Queuing Telemetry Transport,是一个轻量级、小代码占用量、低带宽的网络协议,特别适合于受限制的环境,例如低带宽、不稳定的网络连接、低计算能力的设备等。它基于发布/订阅模式,使消息发布和消息接收分离。 3. 为什么在Qt中使用MQTT? Qt作为一个全能的开发框架,结合MQTT,为开发者在IoT时代提供了强大的工具。物联网设备通常资源受限,而MQTT的轻量级特点与Qt的跨平台能力相结合,为开发者带来了无数可能。 4. Qt MQTT模块 虽然MQTT协议的设计相对简单,但手动实现其所有功能并不是件容易的事。幸运的是,Qt官方为我们提供了一个名为Qt MQTT的模块,它为开发者提供了一个简单的API,用于连接、订阅、发布和接收MQTT消息。 5. 安装与部署 a. 下载源码: Qt官方提供了基于MQTT 5.0的封装,但并没有直接加入到Qt标准库中。所以,我们首先需要从Qt的官方GitHub仓库下载源代码。 Qt MQTT on GitHub b. 编译: 在编译之前,请确保您的编译环境是:Qt5.12.3+vs2017。 注意: 编译这个源码需要先安装Perl。否则,您可能会遇到如"perl不是内部或外部命令"之类的错误。 安装完Perl后,您可以开始编译Qt MQTT源码。完成后,您应该可以在bin目录下找到库文件。 c. 部署到Qt项目: 您可以选择两种部署方式: 导入外部库: 这意味着在每个新项目中,您都需要手动导入库和头文件。 部署为Qt模块: 这样做的好处是,您只需要部署一次,然后在任何新项目中直接引用模块即可。 6. 在Qt项目中使用Qt MQTT a. 创建一个新的Qt项目: 使用Qt Creator启动一个新的Qt Widgets或Qt Quick项目,这取决于您的需求。 b. 添加Qt MQTT模块: 在您的项目文件(.pro)中,添加以下行: QT += mqtt 这将确保您的项目链接到Qt MQTT模块。 c. 使用Qt MQTT进行连接: 为了开始使用MQTT,您首先需要创建一个QMqttClient对象,这是Qt MQTT库中的主要类。 以下是一个简单的例子,展示如何连接到一个MQTT broker: #include <QMqttClient> // 创建一个MQTT客户端对象 QMqttClient *client = new QMqttClient(this); client->setHostname("broker_address"); //设置你的broker地址 client->setPort(1883); // 默认的MQTT端口是1883 // 连接到broker client->connectToHost(); // 检查连接状态 if(client->state() == QMqttClient::Connected) { qDebug() << "Successfully connected!"; } 7. 发布和订阅消息 a. 发布消息: // 发布一个消息到"test/topic" client->publish("test/topic", "Hello MQTT!"); b. 订阅消息: 要订阅一个主题,使用subscribe方法: QMqttSubscription *subscription = client->subscribe("test/topic"); // 订阅成功后,你可以连接到messageReceived信号获取消息 connect(subscription, &QMqttSubscription::messageReceived, this, [](QMqttMessage message){ qDebug() << "Received message:" << message.payload(); }); 8. 断开和清理 当您不再需要MQTT连接时,确保断开连接并清理任何分配的资源。 client->disconnectFromHost(); delete client; 9. 测试 为了验证您的MQTT实现是否工作,您可以使用MQTT测试工具,如MQTT.fx。这些工具允许您发布和订阅消息,从而模拟不同的场景和条件。 总结: Qt MQTT提供了一个简洁、高效的方式来在您的Qt应用中实现MQTT通信。它继承了Qt的易用性和跨平台性,使得MQTT集成变得更加简单。 --- ### 89. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 引言 Eclipse Paho项目是Eclipse基金会的一部分,专注于为流行的MQTT协议开发可靠、开源的客户端实现。其中,Eclipse Paho MQTT C库是该项目中为C语言开发者提供的实现,其设计旨在简化MQTT通信的复杂性,同时保持高度的可靠性和性能。 2. Eclipse Paho MQTT C的核心特性 高度可移植:该库旨在为各种平台和操作系统提供支持,无论是嵌入式设备还是高性能服务器。 完整的MQTT支持:Paho C库支持所有的MQTT QoS(质量服务)级别、遗嘱消息、清理会话以及其他标准特性。 异步API设计:库提供异步接口,使得应用程序可以无需等待操作完成。这样可以在不牺牲性能的前提下简化复杂操作的处理。 TLS/SSL支持:为了安全的网络通信,Paho C客户端支持通过TLS/SSL进行加密的连接。 可扩展性:设计上考虑了未来MQTT版本的兼容性和新特性的扩展。 3. 系统准备 更新与升级系统软件包这确保你的系统具有最新的安全和软件包更新。 sudo apt update && sudo apt upgrade -y 安装开发工具和依赖这些工具和依赖用于编译和安装C库。 sudo apt install build-essential gcc make cmake git -y 4. 获取Paho MQTT C库源码 从GitHub克隆使用git从官方仓库中获取最新的源代码。 git clone https://github.com/eclipse/paho.mqtt.c.git cd paho.mqtt.c 5. 编译与安装 创建构建目录为了保持源码目录的清洁,通常在一个单独的目录中进行构建。 mkdir build cd build 生成Makefile使用CMake根据源代码生成Makefile。 cmake .. 编译源码 make 安装库安装库到系统目录,使其可以全局访问。ldconfig命令更新动态链接器的缓存,确保新安装的库能被系统找到。 sudo make install sudo ldconfig 6. 静态与动态链接配置 同时生成静态和动态库清除先前的构建缓存,然后使用CMake特定选项生成静态和动态库。 make clean cmake -DPAHO_BUILD_STATIC=ON -DPAHO_BUILD_SHARED=ON .. make 7. 使用与最佳实践 编写代码当你开始使用库写代码时,记住导入必要的头文件,例如: #include "MQTTClient.h" 编译与链接在编译代码时,确保链接到正确的库。例如,如果你使用动态库,则: gcc your_program.c -lpaho-mqtt3c 故障排查如果遇到问题,可以参考Paho项目的官方文档或GitHub上的issue区。 8. 参考资源 为了深入了解如何使用库,你可以访问Paho项目的官方文档。 9. 总结 Eclipse Paho MQTT C库是为C开发者提供的一个强大、可靠且易于使用的工具,使他们能够轻松地在其应用中集成MQTT通信功能。随着IoT和M2M应用的日益增长,能够有效、安全地进行通信变得越来越重要,而Paho则为此提供了一个出色的解决方案。 --- ### 90. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT 5.0概述 MQTT是一种轻量级的物联网协议,大幅度降低了网络带宽和设备资源的需求,并支持可靠的数据传输,因此MQTT已成为IoT领域最广泛应用的协议之一。随着IoT设备规模和应用场景的不断扩大,MQTT 5.0协议应运而生,以满足更多新场景需求。本文为您介绍MQTT 5.0的新特性。 背景信息 目前,阿里云物联网平台已支持MQTT 3.1、3.1.1、5.0版本协议,具体的协议请参见MQTT 5.0、MQTT 3.1.1和 MQTT 3.1。 阿里云物联网平台已经具备标准MQTT Broker功能,并在此基础上增加了服务端订阅、云产品流转和云端SDK功能,以加快云端业务应用的开发。更多信息,请参见什么是服务端订阅、云产品流转概述和MQTT 5.0接入概述。 使用限制 设备身份注册成功后,针对同一设备身份信息,只可选择一种通信协议接入物联网平台,不可多种类型通信协议同时混用。即一个设备选择使用MQTT 5.0通信协议后,不可再使用MQTT 3.1、3.1.1通信协议。 MQTT 5.0新特性 MQTT 5.0在MQTT 3.1.1的基础上进行功能扩展,在不增加资源消耗、不降低易用性的情况下,提高物联网设备的性能、扩展能力和互操作性。 特性说明用户属性消息头类似于HTTP的Header,可以由用户自定义Key-Value属性,并且支持可扩展的消息属性。主题别名使用4字节整型数替换较长的Topic字符串,降低资源消耗。会话过期支持在设备离线时,设置保留设备端与服务端之间会话信息的时间。消息过期发布消息时支持设置消息过期时间,避免订阅端收到过期消息。遗嘱消息设备异常断开连接时,订阅者仍能接收到设备之前发布的消息。保留消息设备发布的消息可以设置为保留,这样新的订阅者在订阅时就能接收到之前保留的消息。共享订阅多个订阅者可消费同一个topic消息,帮助用户搭建负载均衡系统。订阅选项订阅增加选项设置,可以剔除不需要的消息,提高传输效率。请求与响应模式扩展请求/响应模式,类似于HTTP协议的RPC调用。消息格式描述消息增加Payload格式说明,帮助用户实现消息的透明流转,支持可变的消息负载。增强端云交互支持功能参数协商、增强错误码、服务端主动断开等特性,提高问题排查效率。 概述 MQTT是基于TCP/IP协议栈构建的异步通信消息协议,是一种轻量级的发布、订阅信息传输协议。物联网平台已支持MQTT 5.0协议,提高了系统性能、稳定性和可伸缩性。您可以通过配置C Link SDK,将设备接入阿里云物联网平台。 前提条件 已准备开发环境。 已获取C Link SDK。定制SDK时,在SDK定制页面的连接物联网平台协议区域,选中MQTT 5.0.0。 已获取设备认证信息。 已了解支持的MQTT 5.0特性。 功能原理 应用程序通过调用C Link SDK的API,基于MQTT 5.0的协议,与物联网平台建立连接。 如下功能时序图,以设备的应用程序(./demos/mqtt_v5_basic_demo.c)为例,介绍应用程序实现该功能的流程。 MQTT 5.0接入功能API的更多信息,请参见aiot_mqtt_api.h。 MQTT 5.0属性管理功能API的更多信息,请参见aiot_mqtt_props_api.h。 使用示例 MQTT 5.0接入功能的参考示例,请参见使用示例。 MQTT 5.0接入功能相关错误码,请参见常见错误码。 使用示例 本文以C Link SDK中的Demo文件./demos/mqtt_v5_basic_demo.c为例,介绍如何调用C Link SDK的API,将MQTT 5.0协议的设备接入物联网平台并进行消息收发。 背景信息 MQTT 5.0接入的更多信息,请参见概述。 步骤一:初始化 添加头文件。#include "aiot_state_api.h" #include "aiot_sysdep_api.h" #include "aiot_mqtt_api.h" 配置底层依赖和日志输出。 aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); aiot_state_set_logcb(demo_state_logcb); 调用aiot_mqtt_init,创建MQTT客户端实例,并初始化默认参数。 mqtt_handle = aiot_mqtt_init(); if (mqtt_handle == NULL) { printf("aiot_mqtt_init failed\n"); return -1; } 步骤二:配置功能 调用aiot_mqtt_setopt,配置以下功能。更多功能的配置项,请参见aiot_mqtt_option_t。 配置连接参数。 示例代码: char *product_key = "a18wP******"; char *device_name = "LightSwitch"; char *device_secret = "uwMTmVAMnGGHaAkqmeDY6cHxxB******"; char *mqtt_host = "iot-06z00ax1o******.mqtt.iothub.aliyuncs.com"; ... ... /* 配置MQTT协议的版本 */ protocol_version = AIOT_MQTT_VERSION_5_0; aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_VERSION, (void *)&protocol_version); /* 配置MQTT服务器地址。 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_HOST, (void *)url); /* 配置MQTT服务器端口。 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PORT, (void *)&port); /* 配置设备ProductKey。 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PRODUCT_KEY, (void *)product_key); /* 配置设备DeviceName。 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_NAME, (void *)device_name); /* 配置设备DeviceSecret。 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_SECRET, (void *)device_secret); /* 配置网络连接的安全凭据。 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_NETWORK_CRED, (void *)&cred); /* 如果要使用MQTT 5.0的assigned clientId功能, 需要将use_assigned_clientid置为1 */ uint8_t use_assigned_clientid = 0; aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_ASSIGNED_CLIENTID, (void *)(&use_assigned_clientid)); 相关参数:参数示例说明mqtt_hostiot-06z00ax1o******.mqtt.iothub.aliyuncs.com设备接入域名。企业版实例和新版公共实例:在实例详情页面的开发配置面板,查看接入域名。旧版公共实例:接入域名格式为${YourProductKey}.iot-as-mqtt.${YourRegionId}.aliyuncs.com。新旧版公共实例和企业版实例、以及接入域名的更多信息,请参见查看实例终端节点。product_keya18wP******设备认证信息。更多信息,请参见获取设备认证信息。本例程的身份认证方式为一机一密。device_nameLightSwitchdevice_secretuwMTmVAMnGGHaAkqmeDY6cHxxB******protocol_versionAIOT_MQTT_VERSION_5_0配置MQTT协议的版本为5.0。use_assigned_clientid1使用MQTT 5.0的assigned clientId功能时,需要将use_assigned_clientid置为1。 MQTT保活说明:重要设备端在保活时间间隔内,至少需要发送一次报文,包括ping请求。从物联网平台发送CONNACK响应CONNECT消息时,开始心跳计时。收到PUBLISH、SUBSCRIBE、PING或PUBACK消息时,会重置计时器。物联网平台每隔30秒定时检测一次设备的保活心跳,设备上线时间点距离最新定时检测时间点的时间,是定时检测的等待时间。定义最大超时时间为:保活心跳时间*1.5+定时检测的等待时间。超过最大超时时间未收到设备消息,服务器会自动断开连接。C Link SDK具备保活能力,您可以设置以下配置项,自定义设备连接的保活心跳。如果不配置,则取默认值。配置项默认值说明AIOT_MQTTOPT_HEARTBEAT_MAX_LOST2可容忍的心跳丢失阈值。即:心跳请求报文达到设置的次数后,发起重连。AIOT_MQTTOPT_HEARTBEAT_INTERVAL_MS25,000每次发起重连之间的间隔时间。单位毫秒, 取值范围:1,000~1,200,000。AIOT_MQTTOPT_KEEPALIVE_SEC1,200可容忍的心跳丢失时间阈值。即:失去心跳后,设置的时间内,允许发起重连。单位秒,取值范围:30~1,200。建议取值大于300。 配置状态监控和消息回调。 配置状态监控回调函数。 示例代码: int main(int argc, char *argv[]) { ... ... /* 配置MQTT默认消息接收回调函数。 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_RECV_HANDLER, (void *)demo_mqtt_default_recv_handler); /* 配置MQTT事件回调函数。 */ aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_EVENT_HANDLER, (void *)demo_mqtt_event_handler); ... ... } 相关参数:配置项示例值说明AIOT_MQTTOPT_RECV_HANDLERdemo_mqtt_default_recv_handler当接收消息时,根据该回调函数定义的处理逻辑,执行对应的处理。AIOT_MQTTOPT_EVENT_HANDLERdemo_mqtt_event_handler当设备连接状态发生变化时,根据该回调函数定义的处理逻辑,执行对应的处理。 定义状态监控的回调函数。重要请勿将事件的处理逻辑,定义得过于耗时,以免阻塞收包线程。连接状态的变化包括网络异常、自动重连已成功、已断开连接等。如果要根据连接状态的变化做应对处理,可在TODO处,按照需要修改代码。/* MQTT事件回调函数, 当网络连接、重连或断开时,触发该函数, 事件定义见core/aiot_mqtt_api.h。 */ void demo_mqtt_event_handler(void *handle, const aiot_mqtt_event_t *event, void *userdata) { switch (event->type) { /* 调用了aiot_mqtt_connect()接口, 与MQTT服务器建立连接。 */ case AIOT_MQTTEVT_CONNECT: { printf("AIOT_MQTTEVT_CONNECT\n"); /* TODO: 处理SDK建立连接成功, 不可在此调用耗时较长的阻塞函数。 */ } break; /* SDK因网络状况被动断开连接后, 成功自动发起重连。 */ case AIOT_MQTTEVT_RECONNECT: { printf("AIOT_MQTTEVT_RECONNECT\n"); /* TODO: 处理SDK重连成功, 不可在此调用耗时较长的阻塞函数。 */ } break; /* SDK因网络状况被动断开了连接, network底层读写失败, heartbeat没有按预期得到服务端心跳应答。 */ case AIOT_MQTTEVT_DISCONNECT: { char *cause = (event->data.disconnect == AIOT_MQTTDISCONNEVT_NETWORK_DISCONNECT) ? ("network disconnect") : ("heartbeat disconnect"); printf("AIOT_MQTTEVT_DISCONNECT: %s\n", cause); /* TODO: 处理SDK被动断开连接, 不可在此调用耗时较长的阻塞函数。 */ } break; default: { } } } 定义消息接收的回调函数。重要请勿将消息的处理逻辑,定义得过于耗时,以免阻塞收包线程。如果您要根据接收的消息做应对处理,可在TODO处,按照需要修改代码。/* MQTT默认消息处理回调, 当SDK从服务器收到MQTT消息时, 且无对应用户回调处理时被调用 */ void demo_mqtt_default_recv_handler(void *handle, const aiot_mqtt_recv_t *packet, void *userdata) { switch (packet->type) { case AIOT_MQTTRECV_HEARTBEAT_RESPONSE: { printf("heartbeat response\n"); /* TODO: 处理服务器对心跳的回应, 一般不处理 */ } break; case AIOT_MQTTRECV_SUB_ACK: { printf("suback, res: -0x%04X, packet id: %d, max qos: %d\n", -packet->data.sub_ack.res, packet->data.sub_ack.packet_id, packet->data.sub_ack.max_qos); /* TODO: 处理服务器对订阅请求的回应, 一般不处理 */ } break; case AIOT_MQTTRECV_UNSUB_ACK: { printf("unsuback, , packet id: %d\n", packet->data.unsub_ack.packet_id); /* TODO: 处理服务器对订阅请求的回应, 一般不处理 */ } break; case AIOT_MQTTRECV_PUB: { printf("pub, qos: %d, topic: %.*s\n", packet->data.pub.qos, packet->data.pub.topic_len, packet->data.pub.topic); printf("pub, payload: %.*s\n", packet->data.pub.payload_len, packet->data.pub.payload); printf("pub, payload len: %x\n", packet->data.pub.payload_len); aiot_mqtt_props_print(packet->data.pub.props); } break; case AIOT_MQTTRECV_PUB_ACK: { printf("puback, packet id: %d\n", packet->data.pub_ack.packet_id); /* TODO: 处理服务器对QoS1上报消息的回应, 一般不处理 */ } break; case AIOT_MQTTRECV_CON_ACK: { aiot_mqtt_props_print(packet->data.con_ack.props); } break; case AIOT_MQTTRECV_DISCONNECT: { printf("server disconnect, reason code: 0x%x\n", packet->data.server_disconnect.reason_code); } break; default: { } } } 步骤三:请求连接 调用aiot_mqtt_connect_v5,根据配置连接的参数,向物联网平台,发起连接认证请求。 说明 示例代码中添加的用户属性(MQTT_PROP_ID_USER_PROPERTY)更多信息,请参见mqtt_property_identify_t。 mqtt_properties_t *conn_props = aiot_mqtt_props_init(); mqtt_property_t user_prop = { .id = MQTT_PROP_ID_USER_PROPERTY, .value.str_pair.key.len = strlen("demo_key"), .value.str_pair.key.value = (uint8_t *)"demo_key", .value.str_pair.value.len = strlen("demo_value"), .value.str_pair.value.value = (uint8_t *)"demo_value", }; aiot_mqtt_props_add(conn_props, &user_prop); /* 通过MQTT 5.0的方式与服务器建连 */ res = aiot_mqtt_connect_v5(mqtt_handle, NULL, conn_props); aiot_mqtt_props_deinit(&conn_props); if (res < STATE_SUCCESS) { /* 尝试建立连接失败, 销毁MQTT实例, 回收资源 */ aiot_mqtt_deinit(&mqtt_handle); printf("aiot_mqtt_connect failed: -0x%04X\n\r\n", -res); printf("please check variables like mqtt_host, produt_key, device_name, device_secret in demo\r\n"); return -1; } 步骤四:开启保活线程 调用aiot_mqtt_process,向服务器发送心跳报文,使设备保持长连接状态,并重发QoS=1的未应答报文。 开启保活线程。 res = pthread_create(&g_mqtt_process_thread, NULL, demo_mqtt_process_thread, mqtt_handle); if (res < 0) { printf("pthread_create demo_mqtt_process_thread failed: %d\n", res); return -1; } 设置保活线程处理函数。void *demo_mqtt_process_thread(void *args) { int32_t res = STATE_SUCCESS; while (g_mqtt_process_thread_running) { res = aiot_mqtt_process(args); if (res == STATE_USER_INPUT_EXEC_DISABLED) { break; } sleep(1); } return NULL; } 步骤五:开启接收线程 调用aiot_mqtt_recv,收取服务器下发的MQTT消息,根据消息回调函数,执行对应处理。在断线时自动重连,根据事件回调函数,执行对应处理。 开启接收线程。 res = pthread_create(&g_mqtt_recv_thread, NULL, demo_mqtt_recv_thread, mqtt_handle); if (res < 0) { printf("pthread_create demo_mqtt_recv_thread failed: %d\n", res); return -1; } 设置接收线程处理函数。void *demo_mqtt_recv_thread(void *args) { int32_t res = STATE_SUCCESS; while (g_mqtt_recv_thread_running) { res = aiot_mqtt_recv(args); if (res < STATE_SUCCESS) { if (res == STATE_USER_INPUT_EXEC_DISABLED) { break; } sleep(1); } } return NULL; } 步骤六:订阅Topic 调用aiot_mqtt_sub_v5,订阅指定Topic。 示例代码: /* MQTT 订阅topic功能示例, 请根据自己的业务需求进行使用 */ { char *sub_topic = "/sys/${YourProductKey}/${YourDeviceName}/thing/event/property/post_reply"; mqtt_properties_t *sub_props = aiot_mqtt_props_init(); aiot_mqtt_props_add(sub_props, &user_prop); /* 订阅选项 */ sub_options_t opts = { .no_local = 1, .qos = 1, .retain_as_publish = 1, .retain_handling = 1, }; res = aiot_mqtt_sub_v5(mqtt_handle, sub_topic, &opts, NULL, NULL, sub_props); aiot_mqtt_props_deinit(&sub_props); if (res < 0) { printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res); aiot_mqtt_deinit(&mqtt_handle); return -1; } }说明 示例代码中添加的用户属性(MQTT_PROP_ID_USER_PROPERTY)更多信息,请参见mqtt_property_identify_t。 添加订阅选项的详细内容,请参见sub_options_t。 相关参数:参数示例说明sub_topic/a18wP******/LightSwitch/user/get拥有订阅权限的Topic。其中:a18wP******为设备的ProductKey。LightSwitch为设备的DeviceName。本示例为默认的自定义Topic。设备通过该Topic,可接收物联网平台的消息。关于Topic的更多信息,请参见什么是Topic。sub_propsaiot_mqtt_props_init()订阅附加属性。opts.no_local = 1,.qos = 1,.retain_as_publish = 1,.retain_handling = 1,订阅选项。 步骤七:发送消息 调用aiot_mqtt_pub_v5,向指定Topic发送消息。 示例代码: mqtt_properties_t *pub_props = aiot_mqtt_props_init(); /* MQTT 发布消息功能示例, 请根据自己的业务需求进行使用 */ char *pub_topic = "/sys/${YourProductKey}/${YourDeviceName}/thing/event/property/post"; char *pub_payload = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}"; mqtt_property_t response_prop = { .id = MQTT_PROP_ID_RESPONSE_TOPIC, .value.str.len = strlen(pub_topic), .value.str.value = (uint8_t *)pub_topic, }; char *demo_data_str = "12345"; mqtt_property_t correlation_prop = { .id = MQTT_PROP_ID_CORRELATION_DATA, .value.str.len = strlen(demo_data_str), .value.str.value = (uint8_t *)demo_data_str, }; aiot_mqtt_props_add(pub_props, &response_prop); aiot_mqtt_props_add(pub_props, &correlation_prop); res = aiot_mqtt_pub_v5(mqtt_handle, pub_topic, (uint8_t *)pub_payload, (uint32_t)(strlen(pub_payload)), 1,0, pub_props); if (res < 0) { printf("aiot_mqtt pub failed, res: -0x%04X\n", -res); aiot_mqtt_deinit(&mqtt_handle); return -1; }说明示例代码中添加的用户属性(MQTT_PROP_ID_USER_PROPERTY)更多信息,请参见mqtt_property_identify_t。 相关参数:参数示例说明pub_topic/a18wP******/LightSwitch/user/update拥有发布权限的Topic。其中:a18wP******为设备的ProductKey。LightSwitch为设备的DeviceName。设备通过该Topic向物联网平台发送消息。关于Topic的更多信息,请参见什么是Topic。pub_payload{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}上报至物联网平台的消息内容。由于示例消息的Topic类型为自定义,因此数据格式可自定义。关于数据格式的更多信息,请参见数据格式。pub_props参考示例代码。发布消息携带的属性。 设备与物联网平台建立MQTT通信后,请确保通信量不超过阈值。 通信限制的更多信息,请参见连接通信。 如果通信超过阈值,请登录物联网平台查看堆积消息。更多信息,请参见查看和监控消费组。 步骤八:断开连接 调用aiot_mqtt_disconnect_v5,向物联网平台发送断开连接的报文,然后断开网络连接。 示例代码中添加的用户属性(MQTT_PROP_ID_USER_PROPERTY)更多信息,请参见mqtt_property_identify_t。 说明 MQTT接入常应用于长连接的设备,程序通常不会运行至此。例程的主线程任务为配置参数并成功建立连接。连接建立后,主线程可进入休眠。 { mqtt_properties_t *disconn_props = aiot_mqtt_props_init(); /* reason code 0x0 表示Normal disconnection */ int demo_reason_code = 0x0; char *demo_reason_string = "normal_exit"; mqtt_property_t reason_prop = {.id = MQTT_PROP_ID_REASON_STRING, .value.str.len = strlen(demo_reason_string), .value.str.value = (uint8_t *)demo_reason_string}; aiot_mqtt_props_add(disconn_props, &reason_prop); res = aiot_mqtt_disconnect_v5(mqtt_handle, demo_reason_code, disconn_props); aiot_mqtt_props_deinit(&disconn_props); } 步骤九:退出程序 调用aiot_mqtt_deinit,销毁MQTT客户端实例,释放资源。 res = aiot_mqtt_deinit(&mqtt_handle); if (res < STATE_SUCCESS) { printf("aiot_mqtt_deinit failed: -0x%04X\n", -res); return -1; } 后续步骤 例程文件配置完成后,需进行编译,生成可执行文件./output/mqtt-v5-basic-demo。更多信息,请参见编译与运行。 关于运行结果的详细说明,请参见运行日志 运行日志 MQTT 5.0接入功能的例程运行后,您可以在设备端和物联网平台查看日志信息。 前提条件 已配置并运行C Link SDK的MQTT 5.0接入例程。详细信息,请参见使用示例。 设备端日志 您可以在设备端查看运行结果。 连接日志。出现如下日志,表示设备与物联网平台连接成功。[1680608104.988][LK-0313] MQTT user calls aiot_mqtt_connect api, connect [1680608104.988][LK-032A] mqtt host: a18wP******.iot-as-mqtt.cn-shanghai.aliyuncs.com [1680608104.988][LK-0317] user name: LightSwitch&a18wP******* [1680608104.988][LK-0318] password: 4CEB5BA5B334CDB73DAAEEF97EBC1A09******************* success to establish tcp, fd=3 local port: 34624 [1680608104.999][LK-1000] establish mbedtls connection with server(host='a18wP*******.iot-as-mqtt.cn-shanghai.aliyuncs.com', port=[1883]) [1680608105.066][LK-1000] success to establish mbedtls connection, (cost 45329 bytes in total, max used 48297 bytes) [1680608105.099][LK-0000] MQTT_PROP_ID_RECEIVE_MAXIMUM:10 [1680608105.099][LK-0000] MQTT_PROP_ID_TOPIC_ALIAS_MAXIMUM:20 [1680608105.099][LK-0000] MQTT_PROP_ID_MAXIMUM_QOS:1 [1680608105.099][LK-0000] MQTT_PROP_ID_RETAIN_AVAILABLE:1 [1680608105.099][LK-0000] MQTT_PROP_ID_MAXIMUM_PACKET_SIZE:262144 [1680608105.099][LK-0000] MQTT_PROP_ID_WILDCARD_SUBSCRIPTION_AVAILABLE:1 [1680608105.099][LK-0000] MQTT_PROP_ID_SUBSCRIPTION_IDENTIFIERS_AVAILABLE:0 [1680608105.099][LK-0000] MQTT_PROP_ID_SHARED_SUBSCRIPTION_AVAILABLE:1 [1680608105.099][LK-0000] MQTT_PROP_ID_SESSION_EXPIRY_INTERVAL:0 [1680608105.099][LK-0000] MQTT_PROP_ID_SERVER_KEEP_ALIVE:1200 [1680608105.099][LK-0313] MQTT connect success in 116 ms 订阅Topic日志。[1680608105.099][LK-0309] sub: /sys/a18wP******/LightSwitch/thing/event/property/post_reply 上报消息日志。[1680608105.099][LK-0309] pub: /sys/a18wP******/LightSwitch/thing/event/property/post [LK-030A] > 7B 22 69 64 22 3A 22 31 22 2C 22 76 65 72 73 69 | {"id":"1","versi [LK-030A] > 6F 6E 22 3A 22 31 2E 30 22 2C 22 70 61 72 61 6D | on":"1.0","param [LK-030A] > 73 22 3A 7B 22 4C 69 67 68 74 53 77 69 74 63 68 | s":{"LightSwitch [LK-030A] > 22 3A 30 7D 7D 物联网平台日志 您可以在物联网平台控制台,查看设备的状态和运行日志。 在线状态:在左侧导航栏,选择设备管理 > 设备,找到设备,查看设备状态。设备状态显示为在线,则表示设备与物联网平台成功连接。 运行日志:在左侧导航栏,选择监控运维 > 日志服务,选择产品后,查看设备上线、订阅Topic和上报消息的日志。 后续步骤 运行日志中出现的错误信息,请参见常见错误码,根据提示解决问题。 本文介绍在配置C Link SDK的设备接入功能时,常见错误。 Link SDK通过以下两种渠道,表达建连失败时的内部运行状态。您可以通过内部运行状态,了解失败原因。 API的返回值是int32_t的非正数整型,也叫状态码,状态码返回0表成功,其它值表示运行状态 。 使用retval = aiot_xxx_yyy()方式获取返回值。 所有返回值唯一对应内部运行分支,详情请参见aiot_state_api.h或aiot_xxx_api.h。 所有组件返回值的值域互不重叠,共同分别分布在0x0000 - 0xFFFF。 从SDK内部,调用您的日志回调函数。 以下为常见错误码,完整的错误码列表,请参见aiot_state_api.h。 MQTT接入 错误码说明STATE_MQTT_CONNACK_RCODE_SERVER_UNAVAILABLEMQTT服务器拒绝提供连接, 服务当前不可用。请稍后重试。STATE_MQTT_CONNACK_RCODE_BAD_USERNAME_PASSWORD连接时的用户名或密码非法。STATE_MQTT_CONNACK_RCODE_NOT_AUTHORIZEDMQTT服务器进行连接身份验证失败,登录密码错误。请检查设备认证信息是否正确。 HTTPS接入 错误码说明STATE_HTTP_STATUS_LINE_INVALID解析收到的HTTPS报文时,无法获取有效的关于状态的代码行。无法获取HTTPS StatusCode 。STATE_HTTP_READ_BODY_FINISHED解析收到的HTTPS报文时,报文的Body部分已接收完毕,但没有更多数据。STATE_HTTP_AUTH_CODE_FAILEDHTTPS认证应答的StatusCode不是200,认证失败。请检查认证签名是否正确。STATE_HTTP_AUTH_NOT_FINISHED未完成接收HTTPS认证应答接,认证失败。STATE_HTTP_AUTH_TOKEN_FAILEDHTTPS认证应答中,未能解析到Token,认证失败。 网络层 错误码说明STATE_PORT_NETWORK_DNS_FAILEDTCP域名解析失败,请检查域名或IP是否正确。STATE_PORT_NETWORK_CONNECT_FAILEDTCP建立连接失败。STATE_PORT_TLS_INVALID_MAX_FRAGMENTTLS报文最大长度设置为0,该设置非法,请检查后重新设置。STATE_PORT_TLS_INVALID_SERVER_CERTTLS服务端证书配置错误,请检查服务端证书是否正确。STATE_PORT_TLS_INVALID_CLIENT_CERTTLS设备端证书配置错误,请检查客户端证书是否正确。STATE_PORT_TLS_INVALID_CLIENT_KEYTLS客户端密钥配置错误,请检查客户端密钥是否正确。STATE_PORT_TLS_DNS_FAILEDTLS域名解析失败,请检查域名或IP是否配置正确。STATE_PORT_TLS_SOCKET_CREATE_FAILEDTLS Socket创建失败。STATE_PORT_TLS_SOCKET_CONNECT_FAILEDTLS Socket连接失败。STATE_PORT_TLS_INVALID_RECORDSSL收到的数据包出错,请检查TLS帧数据的长度是否过小。 --- ### 91. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 本指南将引导您创建一个 .Net IoT 应用程序,该应用程序充当将 Modbus 数据转换为 MQTT 消息的桥梁。该应用程序将通过 Modbus TCP 协议从工业设备读取温度传感器数据,将该数据转换为 JSON 格式,然后使用 C# 的 HiveMQ MQTT 客户端库将数据发送到 HiveMQ Cloud MQTT代理。 设置 HiveMQ 云 MQTT 代理 首先,您必须设置 HiveMQ Cloud MQTT 代理来管理 C# IoT 应用程序的消息。前往 HiveMQ 网站,从菜单中选择Platform ,然后从左侧菜单中选择HiveMQ Cloud 。 当您登陆HiveMQ Cloud 页面时,选择“免费注册”选项。HiveMQ Cloud Serverless的免费版本允许您配置两个 MQTT 代理集群并链接最多 100 个设备。 对于首次用户,您需要输入电子邮件地址和密码。按照后续步骤验证您的电子邮件并设置您的帐户。 完成此过程后,将自动创建 MQTT 代理集群。要让设备连接到您的 MQTT 代理,请提供用户名和密码,然后单击 来设置您的连接凭据ADD。 通过选择Overview,您可以访问将 C# 应用程序链接到 HiveMQ Cloud MQTT 代理集群所需的连接设置。确保记录集群 URL、端口号和登录详细信息以供以后使用。 如果您需要修改连接详细信息,只需登录您的帐户,选择MANAGE CLUSTER,然后选择ACCESS MANAGEMENT。 在此阶段,您的 MQTT 代理已准备好处理 IoT 应用程序的消息传递。 现在,您可以开始构建 C# 应用程序以充当 MQTT 客户端,将 Modbus 消息从边缘发布到 HiveMQ Cloud MQTT 代理。 创建 C# .Net 控制台应用程序 在开始编码之前,您需要一个合适的开发环境。我推荐使用 Visual Studio IDE 进行此演示,尽管 Visual Studio Code 也是一个可行的选择。如果尚未安装,请从其网站下载 Visual Studio 的免费社区版并安装。 安装后,启动 Visual Studio IDE 并选择控制台应用程序来创建新项目。在项目类型列表下,选择 C# Console App。 为您的项目命名并点击“下一步”。然后,您可以继续选择默认的 .Net 6.0 框架。通过这些步骤,您已经创建了一个空的 C# 控制台应用程序。 下一个目标是让该应用程序能够收集 Modbus 数据并使用 MQTT 将其传输到基于云的应用程序。这是通过集成 HiveMQ C# MQTT 客户端库和 Modbus 库来实现的。 安装 HiveMQtt C# MQTT 客户端库 适用于 C# 的 HiveMQ MQTT 客户端是 GitHub 上提供的开源项目,并附带灵活的 Apache 2.0 许可证。该客户端具有完整的 MQTT 5.0 支持,并且与所有主要 MQTT 代理兼容。 额外的优势是它在 NuGet.org 上可用,允许通过 .Net NuGet 包管理器轻松安装。该包管理器简化了 .Net 项目中依赖项的管理,确保将 HiveMQ MQTT 客户端库轻松集成到您的应用程序中。 要将 HiveMQ MQTT 客户端添加到您的应用程序,请在解决方案资源管理器中右键单击您的项目,然后选择“管理 NuGet 包”。 导航到“浏览”选项卡,搜索 HiveMQtt,从搜索结果中选择客户端,然后完成安装。 安装 Modbus C# MQTT 客户端库 要从 Modbus 设备检索数据,您还需要合并 C# 的 Modbus 客户端库。使用“管理 NuGet 包”窗口,查找 NModubus 包并安装它。 发布和订阅 MQTT 消息 现在,让我们重点关注读取 Modbus TCP 数据并使用 HiveMQtt MQTT 客户端库将其作为 MQTT 消息传输到 HiveMQ Cloud MQTT 代理的 C# 代码。 首先合并必要的程序集引用,将 HiveMQtt 客户端库集成到您的代码中。 using HiveMQtt.Client; using HiveMQtt.Client.Options; using HiveMQtt.MQTT5.ReasonCodes; using HiveMQtt.MQTT5.Types; using NModbus; using NModbus.Device; using System.Net; using System.Net.Sockets; using System.Text.Json; 接下来,初始化 Modbus 客户端,提供所需的连接详细信息,并指定变量来存储返回值。 const string ipAddress = "192.168.0.229"; const int port = 502; // Default Modbus TCP port const byte slaveId = 21; const ushort startAddress = 0; const ushort numRegisters = 2; TcpClient modbus_client = new TcpClient(ipAddress, port); Single modbus_value; UInt16[] modbus_data = new UInt16[2]; 随后,通过提供 HiveMQ Cloud MQTT 代理的连接详细信息来创建 MQTT 客户端实例。 var options = new HiveMQClientOptions { Host = "81b8283f2a154f549a4337bd921c5da4.s2.eu.hivemq.cloud", Port = 8883, UseTLS = true, UserName = "username", Password = "password", }; var client = new HiveMQClient(options); 完成后,您可以建立与 MQTT 代理的连接并查看控制台上显示的连接状态。 Console.WriteLine($"Connecting to {options.Host} on port {options.Port} ..."); // Connect HiveMQtt.Client.Results.ConnectResult connectResult; try { connectResult = await client.ConnectAsync().ConfigureAwait(false); if (connectResult.ReasonCode == ConnAckReasonCode.Success) { Console.WriteLine($"Connect successful: {connectResult}"); } else { // FIXME: Add ToString Console.WriteLine($"Connect failed: {connectResult}"); Environment.Exit(-1); } } catch (System.Net.Sockets.SocketException e) { Console.WriteLine($"Error connecting to the MQTT Broker with the following socket error: {e.Message}"); Environment.Exit(-1); } catch (Exception e) { Console.WriteLine($"Error connecting to the MQTT Broker with the following message: {e.Message}"); Environment.Exit(-1); } 下一步是创建主程序循环。在此循环中,执行以下任务: 实例化 Modbus 主站。 从我们之前创建的 Modbus 客户端读取温度数据。 将生成的 Modbus 数组转换为浮点数。 为温度数据和其他上下文信息创建 JSON 对象。 将 JSON 对象作为 MQTT 消息发布到 HiveMQ Cloud MQTT 代理。 Console.WriteLine("Publishing message..."); while (true) { var factory = new ModbusFactory(); IModbusMaster master = factory.CreateMaster(modbus_client); // Read holding registers ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, numRegisters); modbus_data[0] = registers[0]; modbus_data[1] = registers[1]; modbus_value = ModbusWordArrayToFloat(modbus_data); var msg = JsonSerializer.Serialize( new { temperature = modbus_value, device_type = "modbus", }); //Publish MQTT messages var result = await client.PublishAsync("hivemqdemo/telemetry", msg, QualityOfService.AtLeastOnceDelivery).ConfigureAwait(false); } 最后,我们有一个方法可以帮助将 Modbus 数组转换为浮点型。 /************ ROUTINE TO CONVERT MODBUS 2 BYTES BIG ENDIAN DATA TO SWAPPED FLOAT **********/ Single ModbusWordArrayToFloat(UInt16[] data) { if (data.Length != 2) throw new ArgumentException("2 words of data required for a float"); byte[] bData = new byte[4]; byte[] w1 = BitConverter.GetBytes(data[0]); byte[] w2 = BitConverter.GetBytes(data[1]); //reverse words Array.Copy(w2, 0, bData, 0, 2); Array.Copy(w1, 0, bData, 2, 2); return BitConverter.ToSingle(bData, 0); } 执行 C# 控制台应用程序时,应成功建立与 MQTT 代理的连接。 要验证您的应用程序是否正在主动将消息传输到 HiveMQ Cloud MQTT 代理,您可以使用 MQTT 测试工具(例如 MQTT.fx)。订阅 HiveMQ Cloud MQTT 代理将允许您查看正在发布的数据。 结论 总之,我们已经成功创建了一个使用 C# 将 Modbus 数据转换为 MQTT 的网关应用程序。我们邀请您下载并进一步探索HiveMQ C# MQTT 客户端。 --- ### 92. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT (MQ 遥测传输) 是一种轻量级的开放消息协议,为资源受限的网络客户端提供了一种在低带宽环境中简单地分发遥测信息的方法。这种协议采用发布/订阅通信模式,用于机器到机器(M2M)通信。 为了适应带宽和CPU限制而设计的低开销协议,MQTT旨在运行在嵌入式环境中,提供可靠、有效的通信路径。适用于与小型代码占用的设备连接的MQTT,是无线网络的好选择,这些网络因偶尔的带宽限制或不可靠的连接而经常出现不同程度的延迟。该协议在从汽车到能源到电信的各个行业都有应用。 尽管MQTT开始作为一个专有协议用于与石油和天然气行业的监控控制和数据采集(SCADA)系统通信,但它已经在智能设备领域流行起来,如今是连接物联网(IoT)和工业物联网(IIoT)设备的领先开源协议。 虽然MQTT中的TT代表遥测传输,但MQ指的是一个名为IBM MQ的产品。尽管MQTT有时被解释为消息队列遥测传输,但在MQTT通信中没有消息队列。 MQTT是如何工作的?为了最大化可用的带宽,MQTT的发布/订阅(pub/sub)通信模型是传统的客户端-服务器架构的替代方案,与端点直接通信。与此相反,在pub/sub模型中,发送消息的客户端(发布者)与接收消息的客户端或客户端(订阅者)是解耦的。因为发布者和订阅者之间没有直接联系,所以第三方——代理——负责他们之间的连接。 MQTT客户端包括发布者和订阅者,这些术语指的是客户端是发布消息还是订阅接收消息。这两个功能可以在同一个MQTT客户端中实现。当一个设备(或客户端)想要向服务器(或代理)发送数据时,称为发布。当操作反转时,称为订阅。根据pub/sub模型,多个客户端可以连接到代理并订阅他们感兴趣的主题。 如果订阅客户端到代理的连接断开,那么代理将缓冲消息并在订阅者在线时将其推出。如果从发布客户端到代理的连接在没有通知的情况下断开,则代理可以关闭连接并发送订阅者一个缓存的消息,其中包含来自发布者的指令。 IBM的一篇写作描述了pub/sub模型:“发布者发送消息,订阅者接收他们感兴趣的消息,代理将消息从发布者传递给订阅者。发布者和订阅者是MQTT客户端,只与MQTT代理通信。MQTT客户端可以是任何设备或应用程序(从Arduino这样的微控制器到托管在云中的完整应用服务器),只要它运行一个MQTT库。” 什么是MQTT代理?MQTT代理充当发送消息的客户端和接收这些消息的订阅者之间的中间人。在邮局的类比中,代理是邮局本身。所有消息都必须通过代理才能传送给订阅者。 代理可能需要处理数 百万个同时连接的MQTT客户端,因此在选择MQTT代理时,企业应根据其可扩展性、集成性、监控和抗故障能力来评估它们。 MQTT消息的类型MQTT会话分为四个阶段:连接、认证、通信和终止。客户端首先创建一个到代理的传输控制协议/互联网协议(TCP/IP)连接,使用标准端口或由代理的运营商定义的自定义端口。创建连接时,重要的是要认识到,如果提供了重用的客户端身份,服务器可能会继续旧会话。 标准端口是1883,用于非加密通信,和8883,用于加密通信 - 使用安全套接字层(SSL)/传输层安全性(TLS)。在SSL/TLS握手期间,客户端验证服务器证书并认证服务器。客户端还可以在握手过程中向代理提供一个客户端证书。代理可以使用这个来认证客户端。虽然这不是MQTT规范的明确部分,但代理支持用SSL/TLS客户端证书进行客户端认证已经成为惯例。 因为MQTT协议的目标是成为资源受限和IoT设备的协议,所以SSL/TLS可能不总是一个选项,而在某些情况下可能不被期望。在这种情况下,认证以明文用户名和密码的形式呈现,这些由客户端发送到服务器——这是作为CONNECT/CONNACK数据包序列的一部分。此外,一些代理,尤其是在互联网上发布的公开代理,将接受匿名客户端。在这种情况下,用户名和密码简单地留空。 由于MQTT协议被认为是一个轻量级协议,因为它的所有消息都有一个小的代码占用。每个消息由固定头部组成 - 2字节 - 一个可选的变量头部,一个消息负载,限制为256 MB的信息,和一个服务质量(QoS)级别。 在通信阶段,客户端可以执行发布、订阅、取消订阅和ping操作。发布操作发送一个二进制数据块 - 内容 - 到由发布者定义的主题。 MQTT支持最大256 MB大小的消息二进制大对象(BLOB)。内容的格式将是特定于应用程序的。主题订阅使用SUBSCRIBE/SUBACK数据包对进行,而取消订阅类似地使用UNSUBSCRIBE/UNSUBACK数据包对进行。 主题字符串使用特殊的分隔符字符,正斜杠(/),形成一个自然的主题树。客户端可以使用特殊的通配符字符订阅(和取消订阅)主题树中的整个分支。有两个通配符字符:单级通配符字符,加号字符(+);和多级通配符字符,井号字符(#)。一个特殊的主题字符,美元字符($),从任何根通配符订阅中排除一个主题。通常,$用于传输服务器特定或系统消息。 客户端在通信阶段可以执行的另一个操作是使用PINGREQ/PINGRESP数据包序列ping代理服务器。这个数据包序列大致翻译为ARE YOU ALIVE/YES I AM ALIVE。此操作除了保持活动连接并确保TCP连接没有被网关或路由器关闭外,没有其他功能。 当发布者或订阅者想要终止一个MQTT会话时,它向代理发送一个DISCONNECT消息,然后关闭连接。这被称为优雅的关闭,因为它给予客户端能够通过 提供其客户端身份轻松地重新连接并从中断的地方继续。 如果断开连接突然发生,没有时间让发布者发送一个DISCONNECT消息,代理可能会发送代理之前缓存的来自发布者的消息给订阅者。这条消息,被称为最后的遗嘱和遗言,为订阅者提供了如果发布者意外死亡应该做什么的指示。 MQTT的优势是什么?MQTT协议架构的轻量级特性和最小的开销有助于确保在低带宽下的顺畅数据传输,并减少对CPU和RAM的负载。与竞争协议相比,MQTT的优势包括: 由于是轻量级协议,因此数据传输高效且易于实施; 由于数据包最小化,网络使用率低; 数据分发高效; 远程感测和控制的成功实施; 快速、高效的消息传递; 使用的电力少,对于连接的设备来说很好; 优化网络带宽。 MQTT的缺点是什么?MQTT可能的缺点包括: 与Constrained Application Protocol (CoAP)相比,MQTT的传输周期较慢。 MQTT的资源发现基于灵活的主题订阅,而CoAP使用稳定的资源发现系统。 MQTT是未加密的。相反,它使用TLS/SSL (传输层安全/安全套接字层)进行安全加密。 创建全球可扩展的MQTT网络困难。 其他MQTT的挑战与安全性、互操作性和认证有关。 因为MQTT协议并没有考虑到安全性,所以该协议传统上被用于为特定应用目的在安全的后端网络中使用。MQTT的主题结构可以轻松形成一个巨大的树,没有明确的方法将树划分为可以联合的较小的逻辑域。由于主题树的大小增长,复杂性也增加,这使得创建一个全球可扩展的MQTT网络变得困难。 MQTT缺乏互操作性是其另一个负面方面。因为消息负载是二进制的,没有关于它们如何编码的信息,所以问题可能会出现——尤其是在不同制造商的不同应用应该无缝工作的开放架构中。 正如前面提到的,MQTT内置的认证特性最小。用户名和密码以明文发送,MQTT的任何形式的安全使用都必须采用SSL/TLS,不幸的是,这不是一个轻量级的协议。 使用客户端证书进行客户端认证不是一个简单的过程,在MQTT中没有方法来控制谁拥有一个主题以及谁可以在其上发布信息,除非使用专有的、非带外手段。这使得容易将有害的消息注入到网络中,无论是故意的还是错误的。 此外,消息接收者无法知道原始消息是谁发送的,除非该信息包含在实际消息中。必须在MQTT之上以专有的方式实现的安全特性增加了代码占用,并使实现变得更加困难。 MQTT协议的应用和用例由于其轻量级特性,MQTT非常适合涉及远程监控的应用,包括以下内容: 同步传感器,如火灾探测器或用于盗窃检测的运动传感器,以确定危险是否有效; 使用传感器监测离开医院的病人的健康参数; 传感器提醒人们危险。 另一个应用是一个基于文本的消息应用,用于实时通信,利用MQTT的低数据和能源使用。例如,Facebook使用MQTT作为其Messenger应用,不仅因为该协议在手机到手机消息中节省电池 电量,而且因为该协议使消息在几毫秒内高效地传递,尽管全球范围内的互联网连接不稳定。 主要云服务提供商对MQTT的支持大多数主要的云服务提供商,包括亚马逊网络服务(AWS)、谷歌云、IBM云和微软Azure,都支持MQTT。 MQTT非常适合使用M2M和物联网(IoT)设备的应用,例如在智能家居、医疗保健、物流、工业和制造环境中进行实时分析、预防性维护和监控。 MQTT在物联网中如何应用?因为MQTT客户端很小,所以它们只需要很少的资源,因此可以在小的微控制器上使用,这是MQTT.org的观点。为了优化网络带宽,MQTT头部很小。此外,根据该组织的说法,MQTT“可以扩展到与数百万的IoT设备连接”。 因此,MQTT是物联网(IoT)和工业物联网(IIoT)基础设施中最常用的协议之一——例如,公用事业行业可以有效地在其服务、客户和设备之间传输数据。 MQTT在IoT或IIoT基础设施中的应用示例包括: 智能计量:MQTT协议可以用于传输数据,通过保证消息传送来实时提供准确的表读数。这有助于使计费更加准确。 收集环境传感器数据:在远程环境中使用的传感器通常是低功耗设备,因此MQTT非常适合于具有较低优先级数据传输需求的IoT传感器构建。 机器健康数据:Ably,一个提供发布/订阅消息平台的公司,举了一个风力涡轮机需要“在信息到达数据中心之前就确保将机器健康数据传送给当地团队”的例子。 计费系统:MQTT有助于消除计费或开票中的重复或丢失的消息包。 无论是用于智能计量、快速停电响应还是其他IoT和IIoT应用,MQTT使资源受限的IoT设备能够发送或发布关于特定主题的信息到一个充当MQTT消息代理的服务器。然后,代理将信息推送给那些之前已经订阅了该主题的客户端。 对于人类来说,主题看起来像一个分层的文件路径。客户端可以订阅主题层次结构的特定级别,或使用通配符字符订阅多个级别。客户端可以是场地上的IoT传感器,也可以是数据中心中处理IoT数据的应用。 例如,Carriots、Evrythng和ThingWorx物联网平台支持MQTT协议。 与MQTT竞争的协议与MQTT竞争的其他传输协议包括: 受限应用协议(CoAP):它非常适合IoT,使用请求/响应通信模式。 高级消息队列协议(AMQP):与MQTT一样,它使用发布/订阅通信模式。 简单/流文本定向消息协议(STOMP):这是一个基于文本的协议。但是,STOMP不处理队列和主题;它使用带有目标字符串的发送语义。 Mosquitto:它是一个开源的MQTT代理。 简单媒体控制协议(SMCP):用于嵌入式环境中的CoAP堆栈,基于C。 **SSI(简单传感器接口)**:这是一种用于计算机和传感器之间数据传输的通信协议。 数据分发服务(DDS):对于实时系统,它是一个中间件标准,可以直接在嵌入式系统中实时发布或订阅通信。 服务质量等级QoS指的是消息的发送者和消息的接收者之间的协议。它作为MQTT的一个关键特性,使客户端能够选择三个服务级别中的一个。 这三种不同的QoS级别决定了内容如何由MQTT协议管理。尽管更高级别的QoS更可靠,但它们的延迟和带宽要求更高,所以订阅客户端可以指定他们希望接收的最高QoS级别。 MQTT的服务质量(QoS)级别 最简单的QoS级别是未确认服务。此QoS级别使用PUBLISH数据包序列;发布者将消息发送给代理一次,代理再将消息传递给订阅者一次。没有确保消息正确接收的机制,代理也不保存消息。此QoS级别也可能被称为最多一次、QoS0或发射并忘记。 第二个QoS级别是确认服务。此QoS级别使用发布者和其代理之间以及代理和订阅者之间的PUBLISH/PUBACK数据包序列。确认数据包验证内容已被接收,如果未及时收到确认,则重试机制会再次发送原始内容。这可能导致订阅者收到同一消息的多个副本。此QoS级别也可能被称为至少一次或QoS1。 第三个QoS级别是确保服务。此QoS级别使用两对数据包传递消息。第一对称为PUBLISH/PUBREC,第二对称为PUBREL/PUBCOMP。这两对确保,无论重试次数如何,消息只会被传递一次。此QoS级别也可能被称为仅一次或QoS2。 MQTT协议的版本和历史 MQTT是由IBM的Dr. Andy Stanford-Clark和Arcom的Arlen Nipper于1999年创建的,现在是Eurotech。MQTT被创建为一种经济高效且可靠的方法,用于将石油和天然气行业中使用的监控设备连接到远程企业服务器。当面临在沙漠中的管道传感器与离站SCADA系统之间推送数据的挑战时,他们决定采用基于TCP/IP的发布/订阅拓扑结构,该结构是事件驱动的,以降低卫星链路传输成本。 尽管MQTT仍与IBM紧密关联,但现在它是一个开放的协议,由组织OASIS监督。 尽管名字如此,MQTT并不是原始IBM MQSeries的一部分;但从7.1版本开始,它可以在WebSphere MQ中使用。MQTT之前被称为SCADA协议、MQ Integrator SCADA Device Protocol (MQIsdp)和WebSphere MQTT (WMQTT),尽管所有这些变体都已不再使用。 MQTT根据特定版本有不同的规范。版本5.0取代了MQTT的最后一个版本3.1.1。OASIS定义的一些新规范包括: 使用发布/订阅消息模式; 当发生异常断开时,可以通知用户的机制; 三个消息传递级别:最多一次、至少一次和仅一次; 减少传输开销和协议交换以减少网络流量; 对有效负载内容的不可知消息传输。 进一步的规范可以在OASIS的官网上找到。 MQTT的更新 MQTT在2015年10月28日正式被批准为OASIS标准。在2016年1月底,它被接受为国际标准化组织(ISO)标准。该协议持续改进,现在支持WebSocket,这是另一个协议,允许客户端和代理实时进行双向通信。后来,著名的版本包括v3.1.1标准和v5.0标准,两者都被批准为OASIS标准。作为其更新的一些例子,版本5.0包括了更好的错误报告、在消息头中包括元数据、共享订阅、消息和会话到期以及主题别名。 --- ### 93. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 ESP-AT 是乐鑫开发的可直接用于量产的物联网应用固件,旨在降低客户开发成本,快速形成产品。通过 ESP-AT 指令,您可以快速加入无线网络、连接云平台、实现数据通信以及远程控制等功能,真正的通过无线通讯实现万物互联。 ESP-AT 是基于 ESP-IDF 实现的软件工程。它使 ESP32 模组作为从机,MCU 作为主机。MCU 发送 AT 命令给 ESP32 模组,控制 ESP32 模组执行不同的操作,并接收 ESP32 模组返回的 AT 响应。ESP-AT 提供了大量功能不同的 AT 命令,如 Wi-Fi 命令、TCP/IP 命令、Bluetooth LE 命令、Bluetooth 命令、MQTT 命令、HTTP 命令、Ethernet 命令等。 AT 命令以 “AT” 开始,代表 Attention,以新的一行 (CR LF) 为结尾。输入的每条命令都会返回 OK 或 ERROR 的响应,表示当前命令的最终执行结果。注意,所有 AT 命令均为串行执行,每次只能执行一条命令。因此,在使用 AT 命令时,应等待上一条命令执行完毕后,再发送下一条命令。如果上一条命令未执行完毕,又发送了新的命令,则会返回 busy p... 提示。 AT+MQTTUSERCFG:设置 MQTT 用户属性 设置命令 功能: 配置 MQTT 用户属性 命令: AT+MQTTUSERCFG=<LinkID>,<scheme>,<"client_id">,<"username">,<"password">,<cert_key_ID>,<CA_ID>,<"path"> 响应: OK 参数 <LinkID>:当前仅支持 link ID 0。 <scheme>: 1: MQTT over TCP; 2: MQTT over TLS(不校验证书); 3: MQTT over TLS(校验 server 证书); 4: MQTT over TLS(提供 client 证书); 5: MQTT over TLS(校验 server 证书并且提供 client 证书); 6: MQTT over WebSocket(基于 TCP); 7: MQTT over WebSocket Secure(基于 TLS,不校验证书); 8: MQTT over WebSocket Secure(基于 TLS,校验 server 证书); 9: MQTT over WebSocket Secure(基于 TLS,提供 client 证书); 10: MQTT over WebSocket Secure(基于 TLS,校验 server 证书并且提供 client 证书)。 <client_id>:MQTT 客户端 ID,最大长度:256 字节。 <username>:用户名,用于登陆 MQTT broker,最大长度:64 字节。 <password>:密码,用于登陆 MQTT broker,最大长度:64 字节。 <cert_key_ID>:证书 ID,目前 ESP-AT 仅支持一套 cert 证书,参数为 0。 <CA_ID>:CA ID,目前 ESP-AT 仅支持一套 CA 证书,参数为 0。 <path>:资源路径,最大长度:32 字节。 说明 每条 AT 命令的总长度不能超过 256 字节。 如果 <scheme> 配置为 3、5、8、10,为了校验服务器的证书有效期,请在发送 AT+MQTTCONN 命令前确保 ESP32 已获取到当前时间。(您可以发送 AT+CIPSNTPCFG 命令来配置 SNTP,获取当前时间,发送 AT+CIPSNTPTIME? 命令查询当前时间。) AT+MQTTLONGCLIENTID:设置 MQTT 客户端 ID 设置命令 功能: 设置 MQTT 客户端 ID 命令: AT+MQTTLONGCLIENTID=<LinkID>,<length> 响应: OK > 上述响应表示 AT 已准备好接收 MQTT 客户端 ID,此时您可以输入客户端 ID,当 AT 接收到的客户端 ID 长度达到 <length> 后,返回: OK 参数 <LinkID>:当前仅支持 link ID 0。 <length>:MQTT 客户端 ID 长度。范围:[1,1024]。 说明 AT+MQTTUSERCFG 命令也可以设置 MQTT 客户端 ID,二者之间的差别包括: AT+MQTTLONGCLIENTID 命令可以用来设置相对较长的客户端 ID,因为 AT+MQTTUSERCFG 命令的长度受限; 应在设置 AT+MQTTUSERCFG 后再使用 AT+MQTTLONGCLIENTID。 AT+MQTTLONGUSERNAME:设置 MQTT 登陆用户名 设置命令 功能: 设置 MQTT 用户名 命令: AT+MQTTLONGUSERNAME=<LinkID>,<length> 响应: OK > 上述响应表示 AT 已准备好接收 MQTT 用户名,此时您可以输入 MQTT 用户名,当 AT 接收到的 MQTT 用户名长度达到 <length> 后,返回: OK 参数 <LinkID>:当前仅支持 link ID 0。 <length>:MQTT 用户名长度。范围:[1,1024]。 说明 AT+MQTTUSERCFG 命令也可以设置 MQTT 用户名,二者之间的差别包括: AT+MQTTLONGUSERNAME 命令可以用来设置相对较长的用户名,因为 AT+MQTTUSERCFG 命令的长度受限。 应在设置 AT+MQTTUSERCFG 后再使用 AT+MQTTLONGUSERNAME。 AT+MQTTLONGPASSWORD:设置 MQTT 登陆密码 设置命令 功能: 设置 MQTT 密码 命令: AT+MQTTLONGPASSWORD=<LinkID>,<length> 响应: OK > 上述响应表示 AT 已准备好接收 MQTT 密码,此时您可以输入 MQTT 密码,当 AT 接收到的 MQTT 密码长度达到 <length> 后,返回: OK 参数 <LinkID>:当前仅支持 link ID 0。 <length>:MQTT 密码长度。范围:[1,1024]。 说明 AT+MQTTUSERCFG 命令也可以设置 MQTT 密码,二者之间的差别包括: AT+MQTTLONGPASSWORD 可以用来设置相对较长的密码,因为 AT+MQTTUSERCFG 命令的长度受限; 应在设置 AT+MQTTUSERCFG 后再使用 AT+MQTTLONGPASSWORD。 AT+MQTTCONNCFG:设置 MQTT 连接属性 设置命令 功能: 设置 MQTT 连接属性 命令: AT+MQTTCONNCFG=<LinkID>,<keepalive>,<disable_clean_session>,<"lwt_topic">,<"lwt_msg">,<lwt_qos>,<lwt_retain> 响应: OK 参数 <LinkID>:当前仅支持 link ID 0。 <keepalive>:MQTT ping 超时时间,单位:秒。范围:[0,7200]。默认值:0,会被强制改为 120 秒。 <disable_clean_session>:设置 MQTT 清理会话标志,有关该参数的更多信息请参考 MQTT 3.1.1 协议中的 Clean Session 章节。 0: 使能清理会话 1: 禁用清理会话 <lwt_topic>:遗嘱 topic,最大长度:128 字节。 <lwt_msg>:遗嘱 message,最大长度:64 字节。 <lwt_qos>:遗嘱 QoS,参数可选 0、1、2,默认值:0。 <lwt_retain>:遗嘱 retain,参数可选 0 或 1,默认值:0。 AT+MQTTALPN:设置 MQTT 应用层协议协商(ALPN) 设置命令 功能: 设置 MQTT 应用层协议协商(ALPN) 命令: AT+MQTTALPN=<LinkID>,<alpn_counts>[,<"alpn">][,<"alpn">][,<"alpn">] 响应: OK 参数 <LinkID>:当前仅支持 link ID 0。 <alpn_counts>: 参数个数。范围:[0,5]。 0:清除 MQTT ALPN 配置 [1,5]:设置 MQTT ALPN 配置 <”alpn”>:字符串参数,表示 ClientHello 中的 ALPN,用户可以发送多个 ALPN 字段到服务器。 说明 整条 AT 命令长度应小于 256 字节。 只有在 MQTT 基于 TLS 或 WSS 时,MQTT ALPN 字段才会生效。 应在设置 AT+MQTTUSERCFG 后再使用 AT+MQTTALPN。 示例 AT+CWMODE=1 AT+CWJAP="ssid","password" AT+CIPSNTPCFG=1,8,"ntp1.aliyun.com","ntp2.aliyun.com" AT+MQTTUSERCFG=0,5,"ESP32","espressif","1234567890",0,0,"" AT+MQTTALPN=0,2,"mqtt-ca.cn","mqtt-ca.us" AT+MQTTCONN=0,"192.168.200.2",8883,1 AT+MQTTCONN:连接 MQTT Broker 查询命令 功能: 查询 ESP32 设备已连接的 MQTT broker 命令: AT+MQTTCONN? 响应: +MQTTCONN:<LinkID>,<state>,<scheme><"host">,<port>,<"path">,<reconnect> OK 设置命令 功能: 连接 MQTT Broker 命令: AT+MQTTCONN=<LinkID>,<"host">,<port>,<reconnect> 响应: OK 参数 <LinkID>:当前仅支持 link ID 0。 <host>:MQTT broker 域名,最大长度:128 字节。 <port>:MQTT broker 端口,最大端口:65535。 <path>:资源路径,最大长度:32 字节。 <reconnect>: 0: MQTT 不自动重连。如果 MQTT 建立连接后又断开,则无法再次使用本命令重新建立连接,您需要先发送 AT+MQTTCLEAN=0 命令清理信息,重新配置参数,再建立新的连接。 1: MQTT 自动重连,会消耗较多的内存资源。 <state>:MQTT 状态: 0: MQTT 未初始化; 1: 已设置 AT+MQTTUSERCFG; 2: 已设置 AT+MQTTCONNCFG; 3: 连接已断开; 4: 已建立连接; 5: 已连接,但未订阅 topic; 6: 已连接,已订阅过 topic。 <scheme>: 1: MQTT over TCP; 2: MQTT over TLS(不校验证书); 3: MQTT over TLS(校验 server 证书); 4: MQTT over TLS(提供 client 证书); 5: MQTT over TLS(校验 server 证书并且提供 client 证书); 6: MQTT over WebSocket(基于 TCP); 7: MQTT over WebSocket Secure(基于 TLS,不校验证书); 8: MQTT over WebSocket Secure(基于 TLS,校验 server 证书); 9: MQTT over WebSocket Secure(基于 TLS,提供 client 证书); 10: MQTT over WebSocket Secure(基于 TLS,校验 server 证书并且提供 client 证书)。 AT+MQTTPUB:发布 MQTT 消息(字符串) 设置命令 功能: 通过 topic 发布 MQTT 字符串 消息。如果您发布消息的数据量相对较多,已经超过了单条 AT 指令的长度阈值 256 字节,请使用 AT+MQTTPUBRAW 命令。 命令: AT+MQTTPUB=<LinkID>,<"topic">,<"data">,<qos>,<retain> 响应: OK 参数 <LinkID>:当前仅支持 link ID 0。 <topic>:MQTT topic,最大长度:128 字节。 <data>:MQTT 字符串消息。 <qos>:发布消息的 QoS,参数可选 0、1、或 2,默认值:0。 <retain>:发布 retain。 说明 每条 AT 命令的总长度不能超过 256 字节。 本命令不能发送数据 \0,若需要发送该数据,请使用 AT+MQTTPUBRAW 命令。 示例 AT+CWMODE=1 AT+CWJAP="ssid","password" AT+MQTTUSERCFG=0,1,"ESP32","espressif","1234567890",0,0,"" AT+MQTTCONN=0,"192.168.10.234",1883,0 AT+MQTTPUB=0,"topic","\"{\"timestamp\":\"20201121085253\"}\"",0,0 // 发送此命令时,请注意特殊字符是否需要转义。 AT+MQTTPUBRAW:发布长 MQTT 消息 设置命令 功能: 通过 topic 发布长 MQTT 消息。如果您发布消息的数据量相对较少,不大于单条 AT 指令的长度阈值 256 字节,也可以使用 AT+MQTTPUB 命令。 命令: AT+MQTTPUBRAW=<LinkID>,<"topic">,<length>,<qos>,<retain> 响应: OK > 符号 > 表示 AT 准备好接收串口数据,此时您可以输入数据,当数据长度达到参数 <length> 的值时,数据传输开始。 若传输成功,则 AT 返回: +MQTTPUB:OK 若传输失败,则 AT 返回: +MQTTPUB:FAIL 参数 <LinkID>:当前仅支持 link ID 0。 <topic>:MQTT topic,最大长度:128 字节。 <length>:MQTT 消息长度,不同 ESP32 设备的最大长度受到可利用内存的限制。 <qos>:发布消息的 QoS,参数可选 0、1、或 2,默认值:0。 <retain>:发布 retain。 AT+MQTTSUB:订阅 MQTT Topic 查询命令 功能: 查询已订阅的 topic 命令: AT+MQTTSUB? 响应: +MQTTSUB:<LinkID>,<state>,<"topic1">,<qos> +MQTTSUB:<LinkID>,<state>,<"topic2">,<qos> +MQTTSUB:<LinkID>,<state>,<"topic3">,<qos> ... OK 设置命令 功能: 订阅指定 MQTT topic 的指定 QoS,支持订阅多个 topic 命令: AT+MQTTSUB=<LinkID>,<"topic">,<qos> 响应: OK 当 AT 接收到已订阅的 topic 的 MQTT 消息时,返回: +MQTTSUBRECV:<LinkID>,<"topic">,<data_length>,data 若已订阅过该 topic,则返回: ALREADY SUBSCRIBE 参数 <LinkID>:当前仅支持 link ID 0。 <state>:MQTT 状态: 0: MQTT 未初始化; 1: 已设置 AT+MQTTUSERCFG; 2: 已设置 AT+MQTTCONNCFG; 3: 连接已断开; 4: 已建立连接; 5: 已连接,但未订阅 topic; 6: 已连接,已订阅过 MQTT topic。 <topic>:订阅的 topic。 <qos>:订阅的 QoS。 AT+MQTTUNSUB:取消订阅 MQTT Topic 设置命令 功能: 客户端取消订阅指定 topic,可多次调用本命令,以取消订阅不同的 topic。 命令: AT+MQTTUNSUB=<LinkID>,<"topic"> 响应: OK 若未订阅过该 topic,则返回: NO UNSUBSCRIBE OK 参数 <LinkID>:当前仅支持 link ID 0。 <topic>:MQTT topic,最大长度:128 字节。 AT+MQTTCLEAN:断开 MQTT 连接 设置命令 功能: 断开 MQTT 连接,释放资源。 命令: AT+MQTTCLEAN=<LinkID> 响应: OK 参数 <LinkID>:当前仅支持 link ID 0。 MQTT AT 错误码 MQTT 错误码以 ERR CODE:0x<%08x> 形式打印。 错误类型错误码AT_MQTT_NO_CONFIGURED0x6001AT_MQTT_NOT_IN_CONFIGURED_STATE0x6002AT_MQTT_UNINITIATED_OR_ALREADY_CLEAN0x6003AT_MQTT_ALREADY_CONNECTED0x6004AT_MQTT_MALLOC_FAILED0x6005AT_MQTT_NULL_LINK0x6006AT_MQTT_NULL_PARAMTER0x6007AT_MQTT_PARAMETER_COUNTS_IS_WRONG0x6008AT_MQTT_TLS_CONFIG_ERROR0x6009AT_MQTT_PARAM_PREPARE_ERROR0x600AAT_MQTT_CLIENT_START_FAILED0x600BAT_MQTT_CLIENT_PUBLISH_FAILED0x600CAT_MQTT_CLIENT_SUBSCRIBE_FAILED0x600DAT_MQTT_CLIENT_UNSUBSCRIBE_FAILED0x600EAT_MQTT_CLIENT_DISCONNECT_FAILED0x600FAT_MQTT_LINK_ID_READ_FAILED0x6010AT_MQTT_LINK_ID_VALUE_IS_WRONG0x6011AT_MQTT_SCHEME_READ_FAILED0x6012AT_MQTT_SCHEME_VALUE_IS_WRONG0x6013AT_MQTT_CLIENT_ID_READ_FAILED0x6014AT_MQTT_CLIENT_ID_IS_NULL0x6015AT_MQTT_CLIENT_ID_IS_OVERLENGTH0x6016AT_MQTT_USERNAME_READ_FAILED0x6017AT_MQTT_USERNAME_IS_NULL0x6018AT_MQTT_USERNAME_IS_OVERLENGTH0x6019AT_MQTT_PASSWORD_READ_FAILED0x601AAT_MQTT_PASSWORD_IS_NULL0x601BAT_MQTT_PASSWORD_IS_OVERLENGTH0x601CAT_MQTT_CERT_KEY_ID_READ_FAILED0x601DAT_MQTT_CERT_KEY_ID_VALUE_IS_WRONG0x601EAT_MQTT_CA_ID_READ_FAILED0x601FAT_MQTT_CA_ID_VALUE_IS_WRONG0x6020AT_MQTT_CA_LENGTH_ERROR0x6021AT_MQTT_CA_READ_FAILED0x6022AT_MQTT_CERT_LENGTH_ERROR0x6023AT_MQTT_CERT_READ_FAILED0x6024AT_MQTT_KEY_LENGTH_ERROR0x6025AT_MQTT_KEY_READ_FAILED0x6026AT_MQTT_PATH_READ_FAILED0x6027AT_MQTT_PATH_IS_NULL0x6028AT_MQTT_PATH_IS_OVERLENGTH0x6029AT_MQTT_VERSION_READ_FAILED0x602AAT_MQTT_KEEPALIVE_READ_FAILED0x602BAT_MQTT_KEEPALIVE_IS_NULL0x602CAT_MQTT_KEEPALIVE_VALUE_IS_WRONG0x602DAT_MQTT_DISABLE_CLEAN_SESSION_READ_FAILED0x602EAT_MQTT_DISABLE_CLEAN_SESSION_VALUE_IS_WRONG0x602FAT_MQTT_LWT_TOPIC_READ_FAILED0x6030AT_MQTT_LWT_TOPIC_IS_NULL0x6031AT_MQTT_LWT_TOPIC_IS_OVERLENGTH0x6032AT_MQTT_LWT_MSG_READ_FAILED0x6033AT_MQTT_LWT_MSG_IS_NULL0x6034AT_MQTT_LWT_MSG_IS_OVERLENGTH0x6035AT_MQTT_LWT_QOS_READ_FAILED0x6036AT_MQTT_LWT_QOS_VALUE_IS_WRONG0x6037AT_MQTT_LWT_RETAIN_READ_FAILED0x6038AT_MQTT_LWT_RETAIN_VALUE_IS_WRONG0x6039AT_MQTT_HOST_READ_FAILED0x603AAT_MQTT_HOST_IS_NULL0x603BAT_MQTT_HOST_IS_OVERLENGTH0x603CAT_MQTT_PORT_READ_FAILED0x603DAT_MQTT_PORT_VALUE_IS_WRONG0x603EAT_MQTT_RECONNECT_READ_FAILED0x603FAT_MQTT_RECONNECT_VALUE_IS_WRONG0x6040AT_MQTT_TOPIC_READ_FAILED0x6041AT_MQTT_TOPIC_IS_NULL0x6042AT_MQTT_TOPIC_IS_OVERLENGTH0x6043AT_MQTT_DATA_READ_FAILED0x6044AT_MQTT_DATA_IS_NULL0x6045AT_MQTT_DATA_IS_OVERLENGTH0x6046AT_MQTT_QOS_READ_FAILED0x6047AT_MQTT_QOS_VALUE_IS_WRONG0x6048AT_MQTT_RETAIN_READ_FAILED0x6049AT_MQTT_RETAIN_VALUE_IS_WRONG0x604AAT_MQTT_PUBLISH_LENGTH_READ_FAILED0x604BAT_MQTT_PUBLISH_LENGTH_VALUE_IS_WRONG0x604CAT_MQTT_RECV_LENGTH_IS_WRONG0x604DAT_MQTT_CREATE_SEMA_FAILED0x604EAT_MQTT_CREATE_EVENT_GROUP_FAILED0x604FAT_MQTT_URI_PARSE_FAILED0x6050AT_MQTT_IN_DISCONNECTED_STATE0x6051AT_MQTT_HOSTNAME_VERIFY_FAILED0x6052 MQTT AT 说明 一般来说,AT MQTT 命令都会在 10 秒内响应,但 AT+MQTTCONN 命令除外。例如,如果路由器不能上网,命令 AT+MQTTPUB 会在 10 秒内响应,但 AT+MQTTCONN 命令在网络环境不好的情况下,可能需要更多的时间用来重传数据包。 如果 AT+MQTTCONN 是基于 TLS 连接,每个数据包的超时时间为 10 秒,则总超时时间会根据握手数据包的数量而变得更长。 当 MQTT 连接断开时,会提示 +MQTTDISCONNECTED:<LinkID> 消息。 当 MQTT 连接建立时,会提示 +MQTTCONNECTED:<LinkID>,<scheme>,<"host">,port,<"path">,<reconnect> 消息。 总之,ESP32 提供了丰富的 MQTT AT 命令集,为用户提供了对其 MQTT 会话的细粒度控制。这些命令对于 IoT 实现至关重要,其中有效的设备-broker 通信是必不可少的。始终确保命令按照规定的正确顺序执行,以获得最佳性能。 --- ### 94. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT协议 MQTT协议是一个应用层协议,他要求使用的传输层协议能提供有序的,可靠的双向字节流传输服务。 MQTT协议通信对象分为客户端和服务端,数据的传输以消息为单位,每个消息包含主题,消息服务质量和有效数据。消息的发送和接收都需要依赖主题:A订阅主题T1,B订阅主题T2,A想发送消息给B,就需要将消息发送到主题T2。 一,客户端 通信双方的身份。mqtt通信双方都是客户端,消息传递是以订阅主题的形式。 发布消息到服务端以转发到其他客户端 订阅主题以接收其他客户端的消息 发起连接/断开 二,服务端 作为客户端与客户端之间通信的中介。 接收客户端发布的消息 接收客户端的连接 转发消息给特定的客户端 接收客户端的订阅主题请求 三,消息服务质量 消息服务质量决定了一个MQTT报文的消息应如何处理。 qos0:客户端仅讲报文发送一次,服务端不需要应答,报文是否送达不保证。 qos1:客户端发送报文,服务端接收到后必须应答,超时重发。 qos2:客户端发送报文,服务端接收到后应答,客户端再次发送一个release报文,服务端发送该报文到指定主题下的客户端,并应答。 qos0-qos2,服务的质量逐步提高。qos2能使客户端对报文的发送有全局的掌控。qos0很不负责任,嫁出去的女儿泼出去的水,不管了。qos1还行。 四,主题 MQTT主题是一个字符串,由服务端维护。客户端通过在服务端订阅主题,可接收来自该主题的消息。客户端可向该主题发送消息,所有订阅该主题的客户端都会受到该消息。实现的方式是:客户端向服务端发送带主题的消息到服务端,由服务端将消息转发给订阅该主题的客户端,所以服务端地位重要。 MQTT主题支持分级,如/Home/BathRoom/Mirror,/Home/LivingRoom/Tv,是同一等级下的主题。 主题也支持通配符#,发送消息到主题 /Home/# 则BathRoom和LivingRoom主题下的客户端都会收到消息。 主题也支持单层通配符+,/Home/+ 则BathRoom和LivingRoom主题下的客户端会受到消息,但/Home/BathRoom/Mirror和/Home/LivingRoom/Tv 不会收到消息,这点需要跟#区别。 五,MQTT控制报文 MQTT协议依靠MQTT控制报文来通信 5.1 固定报头 表示控制报文的类型,报文的一些标志位(包括消息服务质量),以及报文剩余的字节长度。 5.2 可变报头 可变报头的内容跟报文类型有关。 包含报文标识符,一个16bit的数据,用于唯一的标记此次通信的报文。当客户端处理完当前报文后,标识符可释放重用。qos0的消息不需要标识符,因为不需要服务端的应答。 5.3 有效载荷 前面都是协议规定必须的,有效载荷是真正的用户数据。不同类型的报文,有效载荷里的数据不同。 5.4 控制报文类型 不同类型的报文,其不同点在于可变报头及有效载荷。就以这两部分看看主要的报文: 5.4.1 连接报文 •可变报头:包含 “使用传输层协议名”(TCP),MQTT协议等级(3.1.1),连接标志,保持连接。 连接标志:指示有效载荷部分的内容。 保持连接:MQTT客户端需要在一个时间内给服务端发送心跳报文,服务端也要在规定时间内应答。由此判断通信双方是否在线。 •有效载荷 由连接标志指示其内容,出现的顺序为:客户端标识符,遗嘱主题,遗嘱消息,用户名,密码。 客户端标志:字符串,用于唯一标志一个客户端。 遗嘱:是一种错误补救方式,当客户端以异常方式断开连接时,服务端长时间未能联系到客户端,则服务端将该客户端的遗嘱消息发布到遗嘱主题。 用户名和密码:字符串,用于识别客户端是否合法。 5.4.2 发布publish •固定报头: •DUP*:重发标志,是否是一个重发的报文,qos0大咩。 RETAIN:保留标志位。若为1,服务端需要在内存中保留该消息。 •可变报头:主题及报文标识符•有效载荷:应用数据,一般是json字符串。 5.4.3 订阅主题subscribe 可订阅多个主题 •有效载荷:包含一个主题过滤器表示客户端要订阅的主题,消息服务质量qos。主题过滤器是一个字符串,后面跟着一个字节的消息服务质量,组成一组,一个订阅报文可包含多组这样的东西,来支持订阅多个主题。 六,安全 安全的实现主要依赖于传输层协议,推进TLS协议服务端使用8883端口。 轻量加密AES ESP-MQTT API 指南 概括 ESP-MQTT是一个MQTT协议客户端的应用程序 一,特性 •支持多种传输层协议如:TCP,SSL,Websocket,wws. •使用url建立连接 •允许一个应用中多个客户端 •支持订阅,发布,认证,遗嘱,保活和3个消息质量 二,应用示例 •protocols/mqtt.tcp[1]:使用tcp,1883 端口 •protocols/mqtt/ssl[2]:使用tcp,端口8883,比较安全 •protocols/mqtt/ssl_psk[3]:使用tcp,基于公钥加密认证,端口8883 •protocols/mqtt/ws[4]:使用websocket,端口80 •protocols/mqtt/wss[5]:使用wss,端口443 三,初始化配置 3.1 URI 当前支持mqtt,mqtts,ws,wss方式 mqtt 使用tcp例子: •mqtt://mqtt.eclipse.org: MQTT over TCP, default port 1883 •mqtt://mqtt.eclipse.org:1884 MQTT over TCP, port 1884 •mqtt://username:password@mqtt.eclipse.org:1884 MQTT over TCP, port 1884, with username and password MQTT over SSL samples: •mqtts://mqtt.eclipse.org: MQTT over SSL, port 8883 •mqtts://mqtt.eclipse.org:8884: MQTT over SSL, port 8884 MQTT over Websocket samples: ws://mqtt.eclipse.org:80/mqtt MQTT over Websocket Secure samples: wss://mqtt.eclipse.org:443/mqtt 最小配置: const esp_mqtt_client_config_t mqtt_cfg = { .uri = "mqtt://mqtt.eclipse.org", // .user_context = (void *)your_context }; esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); //注册回调函数 esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client); esp_mqtt_client_start(client); 注意,默认mqtt客户端使用事件句柄来处理mqtt的事件,如连接,订阅,发布等等。 3.2 SSL 3.3 遗嘱 MQTT支持使用遗嘱消息,当客户端意外断开连接时,遗嘱消息被服务端发送并用于通知其他客户端。在 esp_mqtt_client_config_t 中可配置遗嘱消息: •lwt_topic :指向遗嘱消息的主题 •lwt_msg:指向遗嘱消息 •lwt_msg_len:消息有效载荷长度 •lwt_qos:消息服务质量 •lwt_retain:是否保留 3.4 其他配置参数 •disable_clean_session:默认清除会话,对于连接消息,该参数关闭清除会话标志 •keepalive:保活时间,默认120s •disable_auto_reconnect:关闭自动重连 •user_context:本地参数,用于传递到事件处理句柄 •task_prio:mqtt任务等级,默认5 •task_stack:mqtt堆栈默认6144 bytes,menuconfig可配置 •buffer_size:接收和缓存的长度,默认1024 bytes •username:连接到broker的用户名(服务器) •password:连接到broker的密码(服务器) •client_id:指向客户端id,一般是一个唯一的字符串,可从broker中获取 •host:MQTT broker的ip地址,域名。设置了url会重写该参数 •port:MQTT broker的端口。设置了url会重写该参数 •transport:设置传输协议。设置了url会重写该参数 •refresh_connection_after_ms:在多少时间(ms)后刷新连接 •event_handle:处理mqtt事件的回调函数 •event_loop_handle:mqtt事件组库 更多esp_mqtt_client_config_t的选项,请参考下面API: 3.5 项目配置菜单来配置mqtt 通过idf.py menuconfig项目配置菜单来配置mqtt,在Component config -> ESP-MQTT Configuration 下面的设置是可行的: •CONFIG_MQTT_PROTOCOL_311[6]:使用3.1.1版本的MQTT协议•CONFIG_MQTT_TRANSPORT_SSL[7], CONFIG_MQTT_TRANSPORT_WEBSOCKET[8]:选择传输层协议•CONFIG_MQTT_CUSTOM_OUTBOX[9]:使用本地邮箱 3.6 事件 mqtt主要围绕以下事件进行数据的处理: •MQTT_EVENT_BEFORE_CONNECT:客户端初始化完成并开始连接到broker •MQTT_EVENT_CONNECTED:客户端成功与broker建立连接,客户端准备好接收发送数据 •MQTT_EVENT_DISCONNECTED:客户端由于无法接收或者发送消息而断开连接 •MQTT_EVENT_SUBSCRIBED:broker 确认客户端的订阅请求。保留订阅消息的id •MQTT_EVENT_UNSUBSCRIBED:broker确认了客户端的取消订阅消息。保留取消订阅消息的id •MQTT_EVENT_PUBLISHED:broker确认了用户发布的消息。仅对qos为1和2的消息有效,保留发布消息的id •MQTT_EVENT_DATA:客户端已接收到一个发布的消息。event data包括:消息id,主题名称,数据及数据长度。若数据长度超过buffer大小,则多个MQTT_EVENT_DATA事件会被触发,*current_data_offset和*total_data_len用于保持对数据的追踪。在此可将数据读到缓存中。 •MQTT_EVENT_ERROR:客户端遇到错误。esp_mqtt_error_type_t from error_handle in the event data 可用于判断是哪个类型的错误。 四,API参考 esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config) 根据配置创建mqtt 客户端句柄。 esp_err_t esp_mqtt_client_set_uri(esp_mqtt_client_handle_t client, const char *uri); 设置mqtt连接的url,这个函数通常会重写esp_mqtt_client_init里的配置。 esp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client); 开启mqtt客户端 esp_err_t esp_mqtt_client_reconnect(esp_mqtt_client_handle_t client); 用于强制重新连接 esp_err_t esp_mqtt_client_disconnect(esp_mqtt_client_handle_t client); 用于强制从broker中断开连接 esp_err_t esp_mqtt_client_stop(esp_mqtt_client_handle_t client); 停止mqtt客户端任务,不能再event handle中调用。 int esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic, int qos); 客户端订阅指向服务质量的主题。 • 客户端必须已经连接,该API可被用户任务或mqtt event 回调函数调用。该API使用信号量,所以可能导致一段时间的阻塞。 • 返回:消息id int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *topic); 取消订阅指定主题 •客户端必须连接 •线程安全。参考上面 •返回:消息id int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain); 客户端发布消息到broker •该API可能会阻塞几秒钟(由于网络,数据长度问题) •客户端不必连接 •线程安全 •返回:消息id 参数: •client:客户端句柄 •topic:主题字符串 •data:有效载荷字符串•len: 有效载荷字符串长度 •qos:消息服务质量 •retain:保留消息标志 esp_err_t esp_mqtt_client_destroy(esp_mqtt_client_handle_t client); 销毁mqtt客户端,不能再mqtt回调函数中调用 esp_err_t esp_mqtt_set_config(esp_mqtt_client_handle_t client, const esp_mqtt_client_config_t *config); 设置配置结构体,通常用于更新mqtt配置,再连接之前的回调事件中。 esp_err_t esp_mqtt_client_register_event(esp_mqtt_client_handle_t client, esp_mqtt_event_id_t event, esp_event_handler_t event_handler, void* event_handler_arg); 注册mqtt事件 参数: • client: • event:事件类型• event_handler:事件处理回调函数 event_handler_arg:事件处理回调函数传入参数 int esp_mqtt_client_get_outbox_size(esp_mqtt_client_handle_t client); 获取邮箱大小 六,示例 References [1] protocols/mqtt.tcp: https://github.com/espressif/esp-idf/tree/a921852/examples/protocols/mqtt/tcp[2] protocols/mqtt/ssl: https://github.com/espressif/esp-idf/tree/a921852/examples/protocols/mqtt/ssl[3] protocols/mqtt/ssl_psk: https://github.com/espressif/esp-idf/tree/a921852/examples/protocols/mqtt/ssl_psk[4] protocols/mqtt/ws: https://github.com/espressif/esp-idf/tree/a921852/examples/protocols/mqtt/ws[5] protocols/mqtt/wss: https://github.com/espressif/esp-idf/tree/a921852/examples/protocols/mqtt/wss[6] CONFIG_MQTT_PROTOCOL_311: https://docs.espressif.com/projects/esp-idf/zh_CN/release-v4.1/api-reference/kconfig.html#config-mqtt-protocol-311[7] CONFIG_MQTT_TRANSPORT_SSL: https://docs.espressif.com/projects/esp-idf/zh_CN/release-v4.1/api-reference/kconfig.html#config-mqtt-transport-ssl[8] CONFIG_MQTT_TRANSPORT_WEBSOCKET: https://docs.espressif.com/projects/esp-idf/zh_CN/release-v4.1/api-reference/kconfig.html#config-mqtt-transport-websocket[9] CONFIG_MQTT_CUSTOM_OUTBOX: https://docs.espressif.com/projects/esp-idf/zh_CN/release-v4.1/api-reference/kconfig.html#config-mqtt-custom-outbox --- ### 95. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 相信MQTT这个名称大家都不陌生,物联网的开发必然会遇到MQTT相关知识的应用。那么什么是MQTT?它有什么特点?它能解决什么问题?它是如何工作的?OpenAtom OpenHarmony(以下简称“OpenHarmony”)的物联网开发者要如何使用及验证MQTT功能?接下来的内容将一一为你解答。下图为MQTT通信模型。 什么是MQTT MQTT(Message Queuing Telemetry Transport消息队列遥测传输)是一种物联网协议,是一种客户端与服务端架构的发布/订阅模式的消息传输协议,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。MQTT是专门针对物联网开发的轻量级传输协议。MQTT协议针对低带宽网络,低计算能力的设备,做了特殊的优化,使得其能适应各种物联网应用场景。目前它已广泛应用于车联网、智能家居、即时聊天应用和工业互联网等领域。 MQTT的基本原理 在MQTT通讯中,有两个最为重要的角色。它们分别是服务端和客户端。 MQTT服务端 MQTT服务端通常是一台服务器。它是MQTT信息传输的枢纽,负责将MQTT客户端发送来的信息传递给MQTT客户端。MQTT服务端还负责管理MQTT客户端。确保客户端之间的通讯顺畅,保证MQTT消息得以正确接收和准确投递。 MQTT客户端 MQTT客户端可以向服务端发布信息,也可以从服务端收取信息。我们把客户端发送信息的行为称为“发布”信息。而客户端要想从服务端收取信息,则首先要向服务端“订阅”信息。“订阅”信息这一操作很像我们在视频网站订阅某一部电视剧。当这部电视剧上新后,视频网站会向订阅了该剧的用户发送信息,告诉他们有新剧上线了。 MQTT主题 刚刚我们在讲解MQTT客户端订阅信息时,使用了用户在视频网站订阅电视剧这个例子。在MQTT通讯中,客户端所订阅的肯定不是一部部电视剧,而是一个个“主题”。MQTT服务端在管理MQTT信息通讯时,就是使用“主题”来控制的。 为了便于您更好理解服务端是如何通过主题来控制客户端之间的信息通讯,我们来看看下图示例: 以上图示中一共有三个MQTT客户端。它们分别是汽车、手机和电脑。在管理MQTT通讯时,MQTT服务端使用了“主题”来对信息进行管理。比如上图所示,假设我们需要利用手机和电脑获取汽车的速度,那么我们首先要利用电脑和手机向MQTT服务器订阅主题“汽车速度”。接下来,当汽车客户端向服务端的“汽车速度”主题发布信息后,服务端就会首先检查以下都有哪些客户端订阅了“汽车速度”这一主题的信息。当它发现订阅了该主题的客户端有一个手机和一台电脑,于是服务端就会将刚刚收到的“汽车速度”信息转发给订阅了该主题的手机和电脑客户端。 以上实例中,汽车是“汽车速度”主题的发布者,而手机和电脑则是该主题的订阅者。 值得注意的是,MQTT客户端在通讯时,往往角色不是单一的。它既可以作为信息发布者也可以同时作为信息订阅者。如下图所示: 上图中的所有客户端都是围绕“空调温度”这一主题进行通讯的。对于“空调温度”这一主题,手机和电脑客户端成为了MQTT信息的发布者而汽车则成为了MQTT信息的订阅者(接收者)。 (以上讲解参考链接:太极创客http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-tuttorial/mqtt-tutorial/2-mqtt-basics/) 可以看到,针对不同的主题,MQTT客户端可以切换自己的角色。它们可能对主题A来说是信息发布者,但是对于主题B就成了信息订阅者。 MQTT客户端开发流程 以下采用小熊派的Paho MQTT样例,简要说明MQTT的开发流程。 样例代码在OpenHarmony源码目录/device/board/bearpi/bearpi_hm_nano/app/D5_iot_mqtt,源码下载路径参考文章末尾。开发应用主要涉及以下几个API应用: MQTT的流程主要由四个步骤组成: 1、创建客户端对象; 2、连接服务器; 3、订阅主题; 4、发布主题。 //订阅的回调函数 void messageArrived(MessageData *data) { printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data, data->message->payloadlen, data->message->payload); } //主流程函数 static void MQTTDemoTask(void) { WifiConnect("BearPi", "123456789"); printf("Starting ...\n"); int rc, count = 0; MQTTClient client; NetworkInit(&network); printf("NetworkConnect ...\n"); NetworkConnect(&network, MQTT_SERVERIP, MQTT_SERVERPORT);//本地电脑作为消息代理 此处为电脑IP printf("MQTTClientInit ...\n"); //1-------------创建客户端对象 MQTTClientInit(&client, &network, MQTT_CMD_TIMEOUT_MS, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf)); MQTTString clientId = MQTTString_initializer; clientId.cstring = "bearpi"; MQTTPacket_connectData data = MQTTPacket_connectData_initializer; data.clientID = clientId; data.willFlag = 0; data.MQTTVersion = MQTT_VERSION; data.keepAliveInterval = MQTT_KEEP_ALIVE_MS; data.cleansession = 1; printf("MQTTConnect ...\n"); //2-------------连接服务端 rc = MQTTConnect(&client, &data); if (rc != 0) { printf("MQTTConnect: %d\n", rc); NetworkDisconnect(&network); MQTTDisconnect(&client); osDelay(MQTT_DELAY_2S); } printf("MQTTSubscribe ...\n"); //3-------------订阅主题substopic rc = MQTTSubscribe(&client, "substopic", MQTT_QOS, messageArrived); if (rc != 0) { printf("MQTTSubscribe: %d\n", rc); osDelay(MQTT_DELAY_2S); } while (++count) { MQTTMessage message; char payload[30]; message.qos = MQTT_QOS; message.retained = 0; message.payload = payload; (void)sprintf_s(payload, sizeof(payload), "message number %d", count); message.payloadlen = strlen(payload); //4------------发布pubtopic主题 if ((rc = MQTTPublish(&client, "pubtopic", &message)) != 0) { printf("Return code from MQTT publish is %d\n", rc); NetworkDisconnect(&network); MQTTDisconnect(&client); } osDelay(MQTT_DELAY_500_MS); } } 小熊派开发板MQTT客户端代码一直循环发送主题为pubtopic的信息,信息内容为("message number %d", count),每次信息count++; 同时开发板客户端也在订阅主题为substopic的信息,一旦接收到substopic信息就会调用回调函数,串口打印出substopic主题的内容。 MQTT实操验证 如何验证MQTT客户端代码是否正常?验证过程主要涉及以下几点: 1、下载消息代理Mosquitto软件,并配置Mosquitto; 2、下载EclipsePahoMQTT工具,并用该工具创建一个客户端,我们简称客户A; 3、修改小熊派客户端MQTT代码相关配置,与第一步配置Mosquitto相匹配,小熊派客户端我们简称客户B。 简要说明下本次验证中涉及的各个模块的作用: 1、消息代理Mosquitto:可以理解为它就是MQTT服务器,所有客户端的消息(发布/订阅)都是与它通信;它负责接收及分发所有信息; 2、EclipsePahoMQTT工具创建的客户端A:我们用来与小熊派创建的客户端B进行信息交互(发布/订阅)。 详细细节: 1、下载消息代理Mosquitto软件,并配置Mosquitto: (1)点击下载网址(https://mosquitto.org/download/),选择合适的版本,并安装(记录安装路径); (2)安装好后,配置Mosquitto,并开启Mosquitto服务: 在Mosquitto软件的安装路径找到mosquitto.conf,打开并作如下修改: 192.168.120.137是本电脑的IP;1883指本次用来验证的服务端口号(本电脑IP192.168.120.137可以有多个服务端口);allow_anonymous true指允许客户端匿名登录; 修改配置后,在安装目录打开命令窗口,输入.\mosquitto -c .\mosquitto.conf -v。服务器启动成功后,如下图显示mosquitto version 2.0.11 starting. 2、下载EclipsePahoMQTT工具,创建客户端A,并连接服务器: 3、修改小熊派客户端MQTT代码相关配置,与第一步配置Mosquitto相匹配,小熊派客户端我们简称客户B: 修改连接端代码: NetworkConnect(&network, 192.168.120.137, 1883);//本地电脑作为消息代理 此处为电脑IP Mosquitto相匹配 4、烧录代码,并操作(发布\订阅)通信: 客户端B做了两件事情:1、一直循环发送主题为pubtopic的信息,信息内容是("message number %d", count);2、订阅了主题为substopic的信息,一旦服务器有该主题信息就会发送给客户端B,客户端B会把substopic的内容打印。 客户端A也做了两件事:1、订阅主题为pubtopic的信息;2、发布一条主题为substopic的信息,内容为“Hello OpenHarmony!”。 结合客户端B(小熊派开发板)部分代码: printf("Starting ...\n"); NetworkInit(&network); printf("NetworkConnect ...\n"); NetworkConnect(&network, MQTT_SERVERIP, MQTT_SERVERPORT);//本地电脑作 printf("MQTTClientInit ...\n"); //1-------------创建客户端对象 MQTTClientInit(&client, &network, MQTT_CMD_TIMEOUT_MS, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf)); printf("MQTTConnect ...\n"); //2-------------连接服务端 rc = MQTTConnect(&client, &data); printf("MQTTSubscribe ...\n"); //3-------------订阅主题substopic rc = MQTTSubscribe(&client, "substopic", MQTT_QOS, messageArrived); (void)sprintf_s(payload, sizeof(payload), "message number %d", count); //4------------循环发布pubtopic主题 内容为message number+connt的计数值 MQTTPublish(&client, "pubtopic", &message) //订阅的回调函数输出以下内容 printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data, data->message->payloadlen, data->message->payload); 客户B:开发板烧录好代码后,电脑串口工具连接开发板,会有连接MQTT及订阅的信息(参照以上代码),如下图: 客户A:显示如下图: 总结 本文从讲解MQTT它是什么?原理是什么?到MQTT的应用开发(API函数接口调用例程),再到MQTT的验证(Mosquitto软件及EclipsePahoMQTT工具的使用)三个方面介绍了MQTT。希望通过本文介绍让大家对MQTT有个感性认识。 需要说明的是通常我们使用的是MQTT的解决方案,即MQTT的一系列操作被封装了,例如知识体系的智慧家居样例,在与华为IOT平台通信中,它们内部实现是基于MQTT协议搭建的。(智慧家居与华为IOT平台的相关介绍,请查看文末链接) 本文章是OpenHarmony知识体系工作组(相关链接在文章末尾)为广大开发者分享的文章。同时知识体系工作组结合日常生活,给开发者规划了各种场景的Demo样例,如智能家居场景、影音娱乐场景、运动健康场景等;欢迎广大开发者一同参与OpenHarmony的开发,一起完善样例,相互学习,相互进步。 相关链接 小熊派开发板学习路径: https://growing.openharmony.cn/mainPlay/learnPathMaps?id=19 小熊派开发板MQTT文档: https://gitee.com/bearpi/bearpi-hm_nano/blob/master/applications/BearPi/BearPi-HM_Nano/sample/D5_iot_mqtt/README.md Windows + mosquitto搭建MQTT Broker: https://blog.csdn.net/wallace89/article/details/125617330 OpenHarmony源码获取: https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/get-code/sourcecode-acquire.md OpenHarmony三方库MQTT: https://gitee.com/openharmony-tpc/talkweb_mqtt OpenHarmony知识体系工作组智慧家居开发样例 https://gitee.com/openharmony-sig/knowledge_demo_smart_home 使用MQTT协议连华为IOT平台 https://gitee.com/bearpi/bearpi-hm_nano/blob/master/applications/BearPi/BearPi-HM_Nano/sample/D6_iot_cloud_oc/README.md --- ### 96. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Sparkplug 规范中涉及 MQTT Broker 的 5 个关键概念 在现代工业领域,物联网技术的广泛应用已经成为了提高生产效率、降低成本以及增强设备之间通信能力的关键。而为了实现这些目标,Sparkplug 规范应运而生。它不仅是一种开放源代码的软件规范,还是MQTT(Message Queuing Telemetry Transport)协议的强大增强工具,旨在改进工业物联网(IIoT)通信。在本文中,我们将深入探讨Sparkplug规范中的MQTT Broker的5个关键概念。 1. MQTT 主题命名空间: Sparkplug 规范引入了MQTT主题命名空间的概念,这是为了实现工业物联网的最优化。它的核心思想是为不同设备和系统提供一个统一的命名规则,使它们能够更轻松地共享数据。这种命名约定的一致性简化了设备之间的数据交换,无论这些设备来自不同的制造商或具有不同的功能,都能实现高度互操作性。 2. MQTT 状态管理: Sparkplug 规范中的MQTT状态管理旨在最大程度地利用连续会话感知。这意味着即使在网络连接断开的情况下,设备也能够与MQTT Broker保持连接,降低了宕机和数据丢失的风险。对于工业应用来说,这个特性非常关键,因为它确保了设备之间的持续通信,即使在不稳定的网络条件下也是如此。 3. MQTT 有效负载: Sparkplug 规范中MQTT有效负载的定义确保了数据的一致性和可靠性。通过标准化有效负载,不同设备和系统之间能够共享和解释数据,从而简化了集成过程,提高了互操作性。这种标准化还有助于确保数据被正确地传递和解释,从而减少了潜在的错误。 4. 开放标准与自由工具: Sparkplug 是一个开放的标准,可供任何人使用。越来越多的设备制造商开始支持Sparkplug,这意味着它可以内置于OT层的设备上。这降低了采用门槛,鼓励创新,减少了对特定供应商的依赖。工程师和开发者可以自由选择与其工作流程和需求最匹配的工具,而不必受限于特定的封闭标准。 5. 无需全新基础设施: 具备MQTT和Sparkplug B的SCADA平台使IIoT项目更加经济高效。最重要的是,这些工具不需要对整个基础设施进行大规模更改。它们能够在现有OT和IT系统之间实现恒定的数据流,从而节省了时间和金钱。这种无缝集成的能力使企业能够更快地采用IIoT技术,而无需担心繁琐的基础设施升级。 总结而言,Sparkplug 规范通过优化MQTT协议的使用,提高了工业物联网的效率和安全性,降低了IIoT项目的复杂性和成本。这五个关键概念使Sparkplug成为实现工业物联网互操作性的有力支持者,为设备和系统之间的数据交流铺平了道路。在现代工业中,Sparkplug规范正在为更高效、更具竞争力的生产奠定坚实的基础。 扩展阅读: OT(Operational Technology):这通常指的是用于监控和控制实际物理过程的技术和系统,例如在工厂、制造业和工业环境中使用的设备和自动化系统。OT 包括传感器、PLC(可编程逻辑控制器)、SCADA(Supervisory Control and Data Acquisition)系统等,用于管理和控制物理过程。 IT(Information Technology):这是通常与计算机系统、网络和数据处理相关的技术领域。IT 用于处理和管理数字数据、信息和通信。在工业物联网环境中,IT 技术通常与云计算、数据分析、网络通信等相关,用于处理从OT系统中收集到的数据以及与其他系统进行集成和通信。 在工业物联网(IIoT)项目中,将OT和IT整合在一起是非常关键的,以实现实时数据收集、分析和决策,从而提高生产效率和监控工业过程。 --- ### 97. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当我们比较工业通信中常用的技术,如OPC-UA、HTTP、Modbus、MQTT和Sparkplug,通信效率是一个关键的考量因素。在这篇文章中,我们将从几个通信标准的角度来进行比较,这些标准会影响传输带宽的利用。 连接开销:连接开销是建立通信连接所需的开销,包括握手、协议开销等。在这方面的比较如下: OPC-UA:OPC-UA连接的建立较为复杂,需要多个步骤,包括握手、安全协商和会话创建,因此连接开销较高。 Modbus:Modbus的连接开销很低,因为它不需要复杂的握手或会话管理,通常只涉及网络连接和设备寻址。 HTTP:HTTP的连接开销较高,每个HTTP请求-响应周期通常需要建立新的连接,涉及握手、头部交换和会话管理等额外开销。 MQTT:MQTT设计简单高效,连接开销较低,使用二进制协议和小型头部,减少了连接和维护的数据量。 Sparkplug:Sparkplug与MQTT相比,引入的额外开销较小,因为它主要定义了有效载荷格式和数据表示,而没有改变连接行为。 连接持久性:连接持久性涉及连接建立后需要保持连接的开销,以及连接的稳定性。在这方面的比较如下: OPC-UA:OPC-UA支持客户端-服务器模型,可以选择持久或非持久连接。 Modbus:Modbus通常不使用持久连接,每个请求都会建立一个连接。 HTTP:HTTP是无状态协议,每个HTTP请求-响应周期都是独立的,默认情况下不保持连接活动。 MQTT:MQTT使用持久连接模型,可以长期保持连接,提供保活和自动重连功能。 Sparkplug:Sparkplug基于MQTT,继承了MQTT的连接特性,支持持久连接。 数据变化:数据变化机制涉及是否支持“变化时传送”,即只在数据变化时传输数据,以减少不必要的数据传输。在这方面的比较如下: OPC-UA:OPC-UA通过订阅模型支持“变化时传送”机制,只在订阅的数据变化时发送更新。 Modbus:Modbus不支持内置的数据变化传送机制,主要提供直接访问数据点的功能。 HTTP:HTTP本身不支持“变化时传送”,但可以在应用层使用长轮询或服务器发送事件(SSE)等技术来实现。 MQTT:MQTT并没有内置“变化时传送”机制,但可以与其他协议或应用逻辑配合使用,以实现该功能。 Sparkplug:Sparkplug原生支持“变化时传送”机制,定义了标准有效载荷格式,只在数据值变化时发送更新。 数据压缩:数据压缩涉及在传输中减小数据大小,以提高传输效率。在这方面的比较如下: OPC-UA:OPC-UA使用的数据传输格式通常不支持数据压缩,而且压缩率较低。 Modbus:Modbus不支持数据压缩,侧重于简单高效的数据传输。 HTTP:HTTP支持内容编码等特性,可以在应用层进行数据压缩。 MQTT:MQTT不包含内置的数据压缩,但可以与其他压缩技术或库结合使用。 Sparkplug:Sparkplug采用Google Protobuf作为数据格式,具有一定的压缩能力。 综上所述,不同的技术在连接开销、连接持久性、数据变化和数据压缩方面有不同的特点。对于工业场景,Sparkplug协议在多个方面都表现出色,特别适合高效的数据传输和变化时传送。 --- ### 98. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在工业4.0不断发展的大背景下,MQTT在网络边缘的整合成为实时生产监控和分析的基石。借助边缘MQTT,制造企业能够实现前所未有的效率和生产力水平。 MQTT:边缘分析路径MQTT是一种轻量级消息传递协议,专为小型传感器和移动设备而设计,已经在边缘环境中进行了优化,以提供高效、快速和可靠的性能。在现代制造中,MQTT促进了各种设备、边缘网关、数据中心和云之间的数据通信,确保了一个完全分布式、实时数据平台,可用于监控、分析甚至控制。 MQTT在现代制造业的现代化中发挥着关键作用。它不仅确保了数据的安全性,还能以最小的带宽占用率实现数据的高效传输。此外,它为数据建模和丰富提供了理想平台,这是有效的边缘分析的核心所在。 MQTT Sparkplug:填补差距在智能制造领域,实现互操作性至关重要。这就是MQTT Sparkplug发挥作用的地方,它是一种非常适合工业自动化和智能制造用例的互操作性层。它为设备制造商和软件提供商提供了一种一致、可组合且可观察的方式来建模和共享数据。 Sparkplug基于MQTT协议构建,引入了MQTT主题结构定义、MQTT状态管理和有效负载数据模型定义等基本功能,这些功能对于边缘分析至关重要。它增强了MQTT在工业环境中的可用性,为传统的非结构化消息传递提供了结构化方法,并确保各种设备之间的语义一致性。 HiveMQ完全支持最新的Sparkplug 3.0规范,在Sparkplug边缘部署中发挥着关键作用。 它支持服务质量(QoS)0、1和2级、"保留"消息以及遗嘱(LWT)等功能,提供可扩展且安全的MQTT Sparkplug兼容数据流。HiveMQ还有助于轻松集成OT和IT系统,并提供部署灵活性,包括本地解决方案和Microsoft Azure、AWS或HiveMQ Cloud等平台的云选项,以便可以与全球利益相关者共享在边缘发现的重要事件。 与UNS和ISA-95集成ISA-95标准与MQTT Sparkplug和Unified Namespace(UNS)的集成正在边缘数据建模领域改变规则。它促进了额外的互操作性和简化的操作,提高了实时生产监控系统的效率。 传统的点对点通信在制造系统中常常面临可扩展性问题,并容易陷入供应商锁定的困境,而UNS则有效地解决了这一挑战。它有助于轻松集成OT和IT系统,实施通用的命名约定并增强互操作性。 ISA-95标准作为功能建模的标准,以高效、现代的方式组织制造组件。它根据完成所需的时间将流程分类,从物理生产到订单管理,为制造系统提供了结构化方法。 Sparkplug规范基于MQTT,促进了全行业的互操作性,支持MQTT基础设施内各种来源的安全且可发现的数据集成。它利用MQTT架构将数据即时分发到UNS系统的订阅者,从而增强了数据组织和可发现性。 通过使用代理如HiveMQ将UNS架构、ISA-95标准和Sparkplug规范集成,为内外的智能制造系统提供了坚实的基础。它为互操作性和简化数据流铺平了道路,这是现代工业4.0环境中的一个关键方面。 边缘分析:理解数据一旦您的数据得到有效建模、标记和丰富,边缘分析的应用可以将数据转化为可操作的见解。在更靠近数据源的边缘网络中进行数据处理可以减少延迟并实现实时响应。数据在边缘进行初步分析,过滤掉不必要的信息,从而确保只有最重要的信息被发送到数据中心或云端进行进一步分析。 HiveMQ Edge为边缘分析提供了有效的入口。作为开源的MQTT网关,它促进了创新,同时确保企业能够适应和发展在不断变化的工业环境中。 其中一个突出的功能是能够将传统的OT协议(如Modbus和OPC-UA)转换为标准的MQTT格式,从而促进与企业和云系统的无缝集成。这使得数据更容易访问和操作,这是实时生产监控的关键方面。 此外,它利用Unified Namespace(UNS)促进了标准化和结构化,包括ISA-95语义标准。这种方法不仅消除了数据孤岛,还确保了尽早应用一致的数据命名和建模策略,这对于实时生产分析至关重要。 其跨平台特性确保了无缝集成到各种基础设施设置中,无论是Windows、Linux还是MacOS,从而最大限度地减少中断并提高效率。此外,HiveMQ Edge得到了全球专家社区的支持,不断发展以应对新的挑战、适应和创新,有望实现结构化、可互操作和简化的操作。 实际应用和优势在边缘实施MQTT、UNS和Sparkplug为那些希望在边缘进行实时生产数据分析的人提供了一系列好处。 预测性维护: 通过MQTT、数据建模标准和边缘计算能力,借助实时数据,可以显著增强工业4.0环境中的预测性维护策略。企业可以促进从大量设备和传感器实时无缝收集和分析数据。这种方法可以在潜在问题升级之前及早发现它们,从而安排及时的维护并避免代价高昂的停机。此外,它还促进了主动维护策略,其中数据驱动的见解可以帮助预测机器何时可能发生故障,从而促进及时干预并大幅减少意外停机。这不仅确保了机器的使用寿命,而且还显著降低了运营成本,为更高效和可持续的生产环境铺平了道路。MQTT的双向性质允许在边缘和数据中心生成见解,一方面提供本地化趋势、基线和见解,另一方面提供相同的全球版本。这两种类型的见解共同为希望使用异常检测或其他高级分析方法作为其预测维护工具包一部分的分析师和操作员提供了两全其美的帮助。 质量控制: 在智能制造领域,保持高标准的质量控制至关重要。知名汽车企业梅赛德斯奔驰(原戴姆勒)借助MQTT和HiveMQ彻底改变了其质量控制流程。通过实施强大的MQTT代理,梅赛德斯奔驰促进了不同系统和设备之间的无缝通信,确保实时数据传输和分析。这种方法可以实时监控温度、湿度和振动等各种参数,从而可以立即进行调整,确保生产出高质量的产品。此外,它还营造了一个反应更加灵敏的制造环境,可以及时发现和纠正问题,最大限度地减少缺陷并保持产品的高质量标准。 能源效率: 在现代制造领域,实现能源效率不仅是可持续发展目标,也是关键的运营目标。MQTT Sparkplug的集成可以成为这一努力的催化剂,促进智能制造并促进大幅节能。通过实现对各种制造过程的实时监控和控制,它可以优化能源消耗模式。例如,通过根据占用情况和生产计划对照明和供暖系统进行智能控制,制造单位可以显着减少能源浪费。此外,该协议有助于监控设备健康状况,有助于避免因机械故障而造成的能量损失。MQTT Sparkplug的结构化数据表示和标准化主题命名空间确保不同来源的数据可以无缝集成,提供能源消耗模式的全面视图,并为能 源优化做出明智的决策。因此,MQTT Sparkplug是追求更可持续和更具成本效益的运营的重要工具,为更环保、更高效的制造未来铺平了道路。 结论MQTT和边缘分析在制造业中的整合不仅仅是前沿概念,而是当今的现实,引领我们走向更智能、更高效的生产。这些技术不仅增强了实时生产监控,还提供了前所未有的效率和生产力水平。 我们已经深入探讨了技术组件,从MQTT在促进无缝通信中的作用到Sparkplug在互操作性方面的贡献,以及边缘分析在将原始数据转化为可操作见解方面的关键作用。此外,HiveMQ Edge作为一个强大的工具也得到了强调。除了技术本身,我们还强调了这些技术的实际应用和优势,展示了它们如何改变了预测性维护、质量控制和能源效率的现实,而不仅仅是理想目标。 下一步是明确的,制造企业需要将从这次探索中获得的见解和理解应用于实际环境。这需要仔细研究您现有的系统,并设想如何将MQTT协议、数据模型和边缘分析集成到您自己的环境中,以打造一个响应更快、适应性更强、最终更成功的生产环境. --- ### 99. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5精要系列的第12部分。在第11部分中,我们探讨了MQTT 5中的增强身份验证,概述了其通过强大、灵活和更有效的身份验证过程来增强物联网设备与经纪人之间的安全性和信任的作用。在我们继续探索MQTT 5的广阔世界时,我们评估流控制。 MQTT 5中的流控制是什么?流控制是MQTT 5中引入的一项动态功能,旨在调节物联网设备与经纪人之间的消息流量,以实现高效稳定的通信。 物联网部署涵盖了各种设备类型。例如,嵌入在紧凑型传感器中的MQTT客户端在处理速度和存储能力方面与嵌入在高性能后端服务器中的客户端相比存在显着差异。因此,这些MQTT客户端在处理飞行消息的容忍水平各不相同。在这里,飞行消息指的是具有一级或二级服务质量等级等待确认的PUBLISH命令。 同样,物联网设备可能连接到多个MQTT经纪人,每个经纪人对来自MQTT客户端的飞行消息的管理都有不同的限制。为了无缝地管理MQTT客户端和经纪人之间的这些多样化条件,MQTT 5引入了流控制功能。 获取对MQTT协议的完美介绍。MQTT 5中的流控制如何工作?流控制功能通过客户端和经纪人之间的协商在连接期间建立飞行窗口来实现。这个过程涉及在CONNECT数据包中设置一个名为"接收最大值"的可选属性,表示客户端可以容纳的未经确认的PUBLISH消息的最大数量。经纪人以CONNACK数据包中的类似值进行回应。如果未指定该值,则使用默认值65535。"接收最大值""接收最大值" 流控制功能客户端和经纪人协商它们的接收最大值。 MQTT 5中流控制的优势是什么?流控制增强了用于涉及各种系统和设备的用例的动态消息流调整,促进了在多个团队或供应商合作的项目中的透明度和适应性。不再需要所有方预先建立飞行窗口。如果MQTT 5客户端发送的未经确认消息多于服务器接收最大允许的消息,经纪人将发送Reason Code 0x93(接收最大值超过)的DISCONNECT消息。这种灵活性允许客户端和经纪人发送的飞行消息少于相应的接收最大值允许的消息。 该怎么做,不该怎么做?实施“接收最大值”仍然是一个可选但有益的选择。客户端和经纪人都可以在连接初始化期间建立自己独特的飞行窗口。流控制旨在保持平衡的消息处理,防止任何参与方的过载。作为一项功能,流控制与MQTT 5的主要目标完美契合 - 增强透明度,促进灵活性的增加。结束我们的MQTT 5之旅MQTT 5引入了高级功能,如干净会话开始、负载格式指示符和主题别名,以优化连接和发布操作。订阅功能,如非本地发布、保留消息控制和共享订阅,已被添加,以促进更大的控制和效率在订阅者关系中。 此外,MQTT5试图适应现代物联网应用程序和大规模云平台的需求。它解决了在电力有限的远程设备上有效使用带宽和在不稳定网络上确保可靠性的协议需求。 值得注意的是,MQTT5还适用于一系列令人印象深刻的用例,从连接的汽车、制造系统和物流到企业聊天应用程序和移动应用程序。这个广泛的应用范围证明了它的灵活性和适应性,吸引了各种行业和环境。 鉴于这些重大改进,迁移到MQTT5提供了几个引人注目的好处。它在大规模系统中提供了更高的性能,更高效的设备通信,并增强了发布和订阅过程的控制。此外,它是一种更具适应性和弹性的解决方案,能够应对当今物联网应用程序和云平台的复杂需求。 MQTT 5是MQTT协议最丰富的更新版本,显著提高了可扩展性、效率和适应性。其先进的功能和能力使其成为各种行业物联网应用程序的理想选择,鼓励从以前的版本进行转变。 我们 希望这个全面的系列文章已经为您提供了有关MQTT 5新功能的广泛信息。 --- ### 100. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5要点系列的第11部分。在这个系列的第10部分中,我们深入探讨了MQTT 5中的主题别名概念。我们探讨了它在优化带宽使用和减少网络开销方面的作用,提供了宝贵的见解,以增强整体效率。在本文中,我们将涵盖增强身份验证。 现代物联网项目已经发展成为庞大而复杂的项目,特别是在强大的安全措施至关重要的情况下。这些庞大的项目通常涉及多个供应商和团队之间的合作。遵守国际公认的标准变得至关重要,以简化在这类项目中遇到的挑战。增强身份验证有助于确保符合这些标准。 实施挑战-响应身份验证通过将挑战-响应身份验证纳入您的MQTT 5实现,您可以访问行业标准的身份验证机制,例如Salted Challenge Response Authentication Mechanism(SCRAM)或Kerberos协议。这些广泛认可的协议通过添加一层验证来进一步增强您的物联网基础设施的安全性。 MQTT中的身份验证流程是什么?增强身份验证中的身份验证流程依赖于三种MQTT消息类型:CONNECT、CONNACK(已经存在于MQTT v3中)和新的MQTT v5 AUTH消息。客户端发送CONNECT消息,服务器发送CONNACK消息。这两种消息类型在每个身份验证过程中仅使用一次。另一方面,服务器和客户端都可以多次使用AUTH消息。 获取对MQTT协议的完美介绍。身份验证流程的核心围绕着两个消息属性展开:身份验证方法(由字节21标识)和身份验证数据(由字节22标识)。这些属性在涉及增强身份验证流程的每条消息上都进行了设置。 MQTT中的身份验证方法通过身份验证方法,客户端和服务器可以选择并描述达成一致的身份验证方法。它由通常用于标识SASL(简单身份验证和安全层)机制的方法字符串表示。例如,一些方法字符串的示例包括SCRAM与SHA-1的方法或Kerberos的方法。例如,SCRAM-SHA-1和GS2-KRB5。 身份验证方法为增强身份验证中的交换数据分配了重要意义,应在整个过程中保持不变,以确保一致性和完整性。 MQTT中的身份验证数据身份验证数据是在身份验证过程中使用的二进制信息。它通常涉及在多次迭代中传输加密的密钥或协议步骤。数据的具体内容在增强身份验证中采用的选择机制和正在使用的应用程序具体。 MQTT中增强身份验证的源代码示例在这段代码片段中,我们使用HiveMQ扩展SDK来实现增强身份验证。其目的是验证身份验证方法的支持并确定在两个AUTH消息交换之后连接的MQTT客户端的状态。 public class MyEnhancedAuthenticator implements EnhancedAuthenticator { public void onConnect(EnhancedAuthConnectInput input, EnhancedAuthOutput output) { final ConnectPacket connectPacket = input.getConnectPacket(); // 给定的身份验证方法是否受支持? if (authenticationMethodIsSupported(connectPacket.getAuthenticationMethod())) { // 客户端是否提供了有效的身份验证数据? if (validateClientAuthenticationData(connectPacket.getAuthenticationData())) { // 发送包含挑战的AUTH消息! output.continueAuthentication(prepareServerAuthenticationData()); return; } } // 身份验证失败并断开客户端。 output.failAuthentication(); } public void onAuth(EnhancedAuthInput input, EnhancedAuthOutput output) { final AuthPacket authPacket = input.getAuthPacket(); // 尝试验证响应。 if (validateClientAuthenticationData(authPacket.getAuthenticationData())) { // 允许客户端连接到服务器。 output.authenticateSuccessfully(); return; } // 身份验证失败并断开客户端。 output.failAuthentication(); } } 结论增强身份验证的重要性不容忽视。在一个互联设备不断增加重要性的世界中,安全通信的重要性得到了提升,MQTT 5迎难而上。这种先进的身份验证机制赋予组织保护其物联网基础设施、敏感数据和用户隐私的能力。在我们继续分享MQTT 5概念的过程中,在本系列的第12部分中,我们将重点讨论MQTT 5中的流控制。 --- ### 101. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5精要系列的第10部分。在我们在第9部分中讨论了请求-响应模式之后,我们现在将把注意力转向另一个可能产生重大影响的功能:主题别名。 什么是MQTT主题别名?主题别名是代替主题名称的整数值。它使您能够将冗长且经常使用的主题名称压缩为一个2字节的整数。这有助于在消息发布过程中减少消耗的带宽。发送方在PUBLISH消息中定义主题别名值,然后是主题名称。接收者随后会像处理任何其他PUBLISH一样处理此消息,建立主题别名(整数)和主题名称(字符串)之间的映射。随后发送到相同主题的PUBLISH消息可以仅带有主题别名,省略主题名称。 为什么在MQTT中使用主题别名?MQTT在您的网络中扮演着重要角色,其在维护设备与代理之间的稳定连接方面效率高。保持活动机制保证了客户端与代理之间连接的长期性,迅速检测到不稳定网络中可能发生的连接丢失。仅需每隔几分钟发送PING数据包 - 仅为两个字节 - 就能够使MQTT以最小的功率和带宽使用来维持这些连接。 这就带我们来到主题别名功能,它在涉及大量连接设备传输较小、频繁的消息的部署中特别有益。因此,让我们深入了解这个功能,看看它如何优化您的MQTT 5利用率。 如何使用MQTT主题名称?只要它们是消息的发起者,MQTT客户端和代理就可以为任何PUBLISH消息建立主题别名。同样,它们可以控制每个连接允许的主题别名数量。主题别名的上限,称为主题别名最大值,在连接建立阶段确定。 获取对MQTT协议的完美介绍。客户端在CONNECT数据包中指示其主题别名最大值,而代理则在CONNACK数据包中执行此操作。因此,客户端应仅使用从1到CONNACK数据包中的代理定义的主题别名最大值范围内的主题别名值。同样,代理应尊重来自CONNECT数据包的客户端定义的最大值范围从1到。 如果没有指定主题别名最大值,则默认值为0,有效地禁用了主题别名的使用。这确保了在您的MQTT部署中清晰的通信边界和对主题别名的精确控制。 MQTT主题别名的用例示例MQTT以其在客户端和代理之间有效维护TCP连接的轻量级通信协议而脱颖而出。其保持活动机制最小化了能源和带宽的使用,使用户能够建立经济高效、始终连接的设备部署。此外,它允许实时传送最小的数据点,例如测量数据,从而无需定期进行大容量数据传输 - 这是较重的数据传输技术的要求。 MQTT的这种内在效率在许多应用中都有用武之地,比如预测性维护,在这些应用中,通过实时传送小数据点可以增强服务的质量和响应速度。在这些情况下,详细的主题名称可能比实际数据有效载荷更大,而一个整数可以代表这个数据有效载荷。例如,一个主题名称可能描述了特定接线盒的当前功耗,有效载荷是一个单 独的整数值:"data/europe/germany/south/bavaria/munich/schwabing/box-32543y/junction/consumption/current" 主题别名主题别名可以用单个整数替代长而复杂的主题字符串。MQTT的主题别名功能在这些情况下变得尤为重要,它用单个整数替代了冗长和复杂的主题字符串。在实时发送众多小型消息以覆盖广泛主题名称的情况下,这种技术尤其有用,它提供了两个主要优势:它增强了性能,同时显著减少了网络流量。因此,主题别名成为您的MQTT 5工具库中的一个强大工具,优化数据传输和网络管理。 理解MQTT主题别名主题别名将UTF-8字符串主题名称替换为整数。主题别名到主题映射仅对于单个连接相关。此功能对代理和客户端是可选的。代理和客户端在连接建立期间协商支持这个功能的程度。如果希望使用这个功能,请确保您的代理和客户端实现支持主题别名。当正确使用时,主题别名可以显著影响您的业务案例的利润率。 结论主题别名提供了一种多功能的利用发布/订阅模型的方法。当不断发布消息到有限数量的主题,特别是在大量情况下,主题别名可以以高效的方式节省网络和计算资源。在下一篇文章中,我们将讨论增强的身份验证。 --- ### 102. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5要点系列的第9部分。在第8部分中,我们介绍了MQTT 5中的负载格式描述。在本文中,我们将重点介绍两个突出的元素:响应主题和关联数据。 在处理现代物联网项目的复杂性时,需要跨不同供应商和团队进行协作。随着MQTT成为物联网的卓越协议,增强的互操作性和系统透明性成为MQTT版本5蓝图中的主要需求。今天我们要深入探讨的特性通过提供一种标准解决方案,用于使用MQTT实现请求-响应模式,以满足用户的需求。 什么是MQTT中的请求-响应模式?MQTT根植于异步消息传递,采用发布-订阅范式。这个设计允许发送方和接收方独立运行,促进了一对多的关系。重要的是要理解,MQTT的请求-响应模式与同步的、基于一对一的协议(例如HTTP)从根本上不同。 在MQTT中,响应通常不会直接回答请求的“问题”。相反,请求会在接收方触发特定操作,而响应则会传达这个操作的结果。 听起来复杂吗?不要担心,一个具体的示例很快会让这一切变得清晰! 什么是MQTT 5中的响应主题?响应主题是一个可选的UTF-8字符串,包含在任何PUBLISH或CONNECT数据包中。如果响应主题中存在值,发送方将立即将相关的PUBLISH标记为请求。响应主题字段指示了消息接收者预期的响应主题。最初的PUBLISH(请求)和响应主题可以有多个或没有订阅者。理想情况下,原始的PUBLISH(请求)发送方应在发送请求之前订阅响应主题。 什么是MQTT 5中的关联数据?关联数据是后续的响应主题之后的可选二进制数据。它帮助请求的发送方识别后来接收到的响应与哪个特定的请求相关。关联数据允许原始请求发送方管理从多个接收者可能发送的异步响应。重要的是要注意,这些数据与MQTT代理无关,但用于标识发送方和接收方之间的关系。 MQTT 5中的响应信息是什么?为了促进透明的实现和改进标准化,MQTT 5规范引入了响应信息属性。通过CONNECT中的一个布尔字段,客户端可以请求代理发送响应信息。当设置为true时,代理可以在CONNACK数据包中发送一个可选的UTF-8字符串字段(响应信息),以传达预期的响应主题。 这个特性允许用户在代理上全局定义主题树的特定部分,所有表示他们打算在连接建立时使用请求-响应模式的客户端都可以访问这个部分。 MQTT 5中的端到端确认MQTT确保消息发送方和接收方完全解耦。在许多情况下,用例需要从预期的接收方那里获得消息接收的确认。例如,当通过命令打开智能家居的门时,发送方(通常是移动应用程序)希望知道消息何时接收以及命令的结果。 请求-响应模式在智能门上的示例例如,使用MQTT 5请求-响应功能,通过移动设备打开智能门的示例。 MQTT 5规范中包含请求-响应模式,主要是为了满足这些“业务确认”的需求。MQTT用户寻求在应用消息的发送方和接收方之间提供端到端确认的能力。通过直接将响应主题、关联数据和响应信息集成到协议字段中,我们显著增强了使用请求-响应模式进行应用程序开发的灵活性、动态性和透明性。 MQTT请求-响应工作流的源代码示例以下是展示HiveMQ MQTT客户端能力的快速代码片段,提供了MQTT中请求-响应模式工作流的味道。请注意,这不是一个完整的、可运行的示例。 您可以在GitHub上访问完整示例,并在我们的HiveMQ社区论坛中咨询任何实施问题。 // 请求方订阅响应主题 Mqtt5SubAck subAck = requester.subscribeWith() .topicFilter("job/client1234/result") .send(); // 请求方发布请求 Mqtt5PublishResult result = requester.publishWith() .topic("job") .correlationData("1234".getBytes()) .responseTopic("job/client1234/result") .payload(message.getBytes()) .send(); // 响应方订阅请求主题 Mqtt5SubAck subAck = responder.subscribeWith() .topicFilter("job") .send(); // 响应方在接收请求后发送响应 Mqtt5PublishResult result = responder.publishWith() .topic(publish.getResponseTopic().get()) .payload(msg.getBytes()) .correlationData(publish.getCorrelationData().get()) .send(); MQTT请求-响应中的关键要点以下是MQTT请求-响应的一些关键要点: MQTT中的请求-响应模式与同步的、基于客户端-服务器的协议(如HTTP)显著不同。 MQTT允许请求和响应的订阅者为多个、单个或甚至没有。 关联数据确保请求和响应之间的正确关联,提高消息跟踪的能力。 这种模式促进了“业务确认”功能的实现,提供了一种可扩展、动态和透明的解决方案。 在使用MQTT的请求-响应时要考虑的最佳实践在使用MQTT的请求-响应时,以下是一些最佳实践: 确保请求方在发送请求之前订阅相关的响应主题。 在响应主题中使用唯一的标识符以避免混淆。 确保响应方和请求方具有发布和订阅响应主题的必要权限。 为响应目的专门分配主题树的一个特定部分,并利用响应信息字段将其传递给客户端。 结论当我们探讨MQTT v5的变革性特性时,我们发现了协议演进的力量。这些增强功能,如请求-响应模式,不仅简化了现有的实践,还开启了应用程序开发中新的动态、透明和可扩展的领域。在第10部分中,我们将讨论主题别名的话题。 --- ### 103. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5基础教程系列的第8部分。在第7部分,我们探讨了共享订阅。在本文中,我们将专注于Payload Format Indicators(负载格式指示器),它们指定消息内容类型,确保更轻松、更高效的解析和系统之间的互操作性。 什么是MQTT中的Payload Format Indicator? Payload Format Indicator是任何包含负载的MQTT数据包的基本组成部分。这包括封装WILL消息或PUBLISH数据包的CONNECT数据包。这个可选的字节值有两种可能的设置:0表示“未指定的字节流”,而1表示“UTF-8编码的负载”。当没有提供Payload Format Indicator时,它会自动默认为0。 MQTT 内容类型 与Payload Format Indicator类似,Content Type也是可选的,并且可以包含在包含WILL消息或任何PUBLISH数据包的CONNECT数据包中。Content Type的值必须是一个UTF-8编码的字符串,用于标识负载的性质。当Payload Format Indicator设置为1时,理想情况下,您应该有一个MIME内容类型描述符(尽管这不是硬性要求)。只需一个有效的UTF-8字符串即可。 为什么需要描述负载格式? Payload Format Indicator和Content Type的联合使用有助于透明地描述任何应用程序消息的负载内容。这种能力为创建和定义各种负载格式的行业标准奠定了基础。MQTT协议专家认为,这种标准化是协议的自然发展。 在标题中包含负载内容描述对于个体部署非常有益,它确保了每条消息都在不深入负载本身的情况下被正确处理。根据内容类型,系统内的不同消息可能需要不同的解析方法。此外,在某些情况下,消息的持久性可能取决于负载的具体类型。由于内容类型的定义取决于用户设计,这一功能的潜在应用似乎是无限的。 总结 Payload Format Indicator用于区分负载是未定义的字节数组还是UTF-8编码的消息。当处理UTF-8编码的消息时,发送方可以使用内容类型来指定负载的性质。 这些功能为大规模系统以及潜在的整个行业之间的透明负载内容定义奠定了基础。随着对实际负载进行预解析的需求减少,正确的消息处理可以显著提高可扩展性。 尽管预计大多数用户将依赖已知的MIME类型来描述内容,但他们也可以使用任意的UTF-8字符串。 --- ### 104. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5基础教程系列的第7部分。在第6部分中,我们探讨了MQTT用户属性。在本文中,我们将深入探讨一个特别有趣的功能:共享订阅。 共享订阅是MQTT 5的核心功能,它允许多个MQTT客户端共享代理上的单个订阅。本质上,这个功能允许在多个客户端之间分发主题上的消息,从而改善了MQTT系统的负载均衡和容错性。 共享订阅:用v5填补MQTT的空白 MQTT 5经过精心设计,旨在弥合MQTT 3.1.1提供的功能与用户对物联网的期望之间的差距。通过集成备受期待的功能,如共享订阅、会话和消息到期间隔,MQTT 5有望在可预见的将来巩固MQTT作为物联网协议的地位。 MQTT共享订阅是如何工作的? 在标准的MQTT订阅中,每个订阅的客户端都可以获得发布到该主题的每条消息的副本。而使用共享订阅,共享同一个订阅的客户端会按顺序接收消息,这个过程有时被称为客户端负载均衡。单个主题的消息负载分布在所有订阅者之间。 MQTT客户端可以使用标准的MQTT机制订阅共享订阅。任何标准的MQTT客户端,例如Eclipse Paho,都可以在客户端上不需要任何修改的情况下参与其中。需要注意的是,共享订阅使用独特的主题语法进行订阅。 共享订阅使用以下主题结构: $share/GROUPID/TOPIC 共享订阅由3部分组成: 静态的共享订阅标识符($share) 组标识符 实际的主题订阅(可能包括通配符) 通过一个具体的示例来说明这种订阅:$share/my-shared-subscriber-group/myhome/groundfloor/+/temperature。 MQTT共享订阅在HiveMQ MQTT Broker中的工作原理如何? 共享订阅组可以在概念上被想象为一台虚拟的客户端,同时代表多个订阅者。HiveMQ会从组中选择一个订阅者,并将消息传递给该客户端。它通常使用轮询法来进行分发。以下图片演示了原理: 例如,HiveMQ部署中可能包含多个共享订阅组。这些组可以具有相同的订阅,但不同的组标识符。当发布者发布与特定主题匹配的消息时,每个组中都会选择一个唯一的客户端来接收消息。例如,以下情景是可能的: 在给定的情况下,我们有两个不同的组,每个组都包含两个在其共享订阅组中的订阅客户端。尽管这些组订阅相同的主题,但它们通过唯一的组标识符来区分。当发布者发出与特定主题相符的消息时,每个组中将选择一个客户端,仅选择一个客户端来接收消息。 MQTT 共享订阅使用案例 共享订阅有多种应用,特别是在高可扩展性的场景下。这些包括: 无法处理订阅主题负载的 MQTT 客户端的客户端负载均衡。 引入 MQTT 流的工作(后端)应用程序必须水平扩展。 优化传入发布的订阅者节点位置,以减少 HiveMQ 群集内节点流量。 传递语义使用 QoS 1 和 2,尽管没有必要对有序主题进行保证。 解决由于消息速率较高而导致的可扩展性瓶颈的热门话题 如何使用MQTT进行共享订阅? 让您的客户端使用共享订阅是一个简单的过程。以下是使用MQTT CLI完成此操作的示例。给定的命令行执行代码允许两个MQTT客户端订阅相同的订阅组和主题:执行了这些命令后,两个MQTT客户端现在都共享对“my-share-topic”(属于虚拟组“group1”的一部分)的订阅。在这种配置下,每个客户端分配了MQTT经纪上发布到主题“my-share-topic”的消息的一半。 mqtt sub -h broker.hivemq.com -t '$share/group1/my-share-topic' -i client1 -q 1 mqtt sub -h broker.hivemq.com -t '$share/group1/my-share-topic' -i client2 -q 1 请记住,MQTT客户端可以随时加入或离开订阅组。例如,如果第三个客户端决定加入该组,那么相关MQTT消息的分发将平均分配给所有三个客户端,每个客户端都将收到总量的三分之一。 使用共享订阅扩展MQTT订阅者 共享订阅为将后端系统与MQTT集成提供了一种简单的方法,特别是当无法使用HiveMQ的扩展系统或需要动态扩展时。使用共享订阅,您可以根据需要快速添加订阅者,以推送方式分发工作。 共享订阅对于扩展和负载平衡MQTT客户端非常有价值。此外,HiveMQ集群通过优化消息路由的内部优化,提供了额外的延迟和可扩展性优势。 结论 共享订阅提供了一种通过标准MQTT机制在各种MQTT订阅者之间分发消息的引人注目的方法。这个功能简化了实现MQTT客户端负载平衡的过程,无需对您的MQTT客户端进行任何专有的修改。这对于后端系统或可能迅速超出单个MQTT客户端的“热门主题”特别有益。 --- ### 105. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5基础知识系列的第6部分。在第5部分中,我们深入研究了改进的客户反馈和负面确认,揭示了它们如何增强MQTT系统的功能。在本文中,我们将为您介绍另一个突破性功能:用户属性。这个新功能将彻底改变您与MQTT的互动方式,创造出更加定制和富有见地的用户体验。 用户属性本质上是用户定义的属性,帮助您向MQTT消息添加元数据并传输额外的用户定义信息。 让我们深入了解。 MQTT 5已经经过精心制作,旨在填补MQTT 3.1.1提供的功能和用户对物联网的期望之间的差距。通过MQTT 5,我们确保MQTT继续作为物联网的卓越协议领导者,为未来数十年提供卓越的性能。 MQTT 5中的用户属性是如何工作的? 在MQTT 5中,用户属性基本上是直观的UTF-8字符串键值对。它们的实用性在于几乎可以附加到几乎每一类MQTT数据包上,唯一的例外是PINGREQ和PINGRESP。这种广泛应用包括各种控制数据包,如PUBREL和PUBCOMP。 用户属性的强大之处在于它们的潜力无限制 - 只要不超过最大消息大小,您可以使用无限数量的用户属性。这为丰富MQTT消息的元数据提供了广泛的可能性,促进了发布者、代理和订阅者之间信息的流畅传输。 从概念上讲,这个功能与HTTP中的标头的作用非常相似。正是这种相似性使用户属性能够在MQTT 5中注入可定制的复杂性水平,帮助创建一个不仅更加健壮,而且更适应用户需求的协议。 为什么在MQTT 5中引入了用户属性? MQTT 3的用户确定了两个重要的限制:协议的有限可扩展性和创建多供应商部署的复杂性。为了解决这些问题,MQTT 5引入了用户属性功能,有效地减轻了这些挑战。 用户属性提供了一种增强灵活性的途径,使用户能够在整个MQTT系统中传输几乎任何信息。这种能力确保MQTT协议不再限制而是促进了定制增强。这种功能的进步使用户能够增强标准协议功能,以满足其特定需求。 通过这样做,MQTT 5确保协议与其用户同步发展,促进了更大的适应性,并简化了多供应商部署的集成。 MQTT 5用户属性的实际用例示例 虽然用户属性功能的复杂性最初可能看起来很小,但跨整个MQTT生态系统传输元数据的机制的实际影响确实是巨大的。为了说明这种转型潜力,让我们深入探讨三种常见的用例,强调了像用户属性这样的功能的需求——这是用户在急切等待MQTT规范中引入这个组件的时候一再提出的需求。 在MQTT 5中使用用户属性保存负载元数据以节省资源 在MQTT作为连接不同团队或供应商开发的不同系统之间的连接器的环境中,负载结构的可变性非常普遍。客户端可以以许多格式传输数据,包括JSON、XML或诸如Protobuf等压缩格式。 MQTT 5引入用户属性的功能打开了附加元数据到消息的大门,封装了诸如用于编码负载的标记语言和版本等特定细节。这种元数据的提供消除了接收客户端,或在某些情况下,代理,解压负载并遍历一系列可能的解析器直到找到适当解析器的需要。 与这个繁琐的过程不同,每条消息都带有其解析信息,简化了解释并大大减少了整个系统的计算负载。这种有效的资源利用增强了MQTT网络的整体性能和速度,展示了用户属性的变革力量。 通过应用级别路由在MQTT 5中提高效率 由于其在数据传输和路由方面的高效能力,MQTT经常用作大规模数据处理和流式处理部署的基础。这些部署通常涉及大量的设备、系统和应用程序。不同的系统经常接收相同的消息,但用于不同的目的。例如,一个系统可能显示实时数据,而另一个系统可能将相同的数据存档以供长期存储。 在这种情况下,用户属性可以通过充当消息的附加应用级别时间戳来证明其价值。这个属性允许代理快速确定是否根据预定义的有效期不应将某些消息传递给特定子订阅者的子集。这个功能引入了一个额外的应用级别层,根据消息到期间隔进一步细化消息的相关性。 因此,MQTT 5中的用户属性不仅增强了系统的效率,还提供了更精细的控制水平,从而最大程度地提高了每个传输的消息的效用和相关性。 在复杂系统中使用用户属性进行透明的可追溯性 物联网部署的景观通常呈现出错综复杂的迷宫,各个系统并行运行。这种复杂性可能会模糊特定消息的来源或导致多层消息流不成功的因素。在MQTT 3.1.1框架下,没有机制使订阅者能够识别消息发布者的身份。尽管在1对1场景中将唯一标识符嵌入主题是一种可行的策略,但这种方法破坏了发布-订阅模型的几个关键优势。 在这方面,MQTT 5中引入用户属性功能标志着重大转变。这个创新性的添加使发布者能够轻松地包含相关的自我识别信息,例如客户端ID或发布操作的区域。重要的是,这些信息传递给所有消息接收者,而不需要任何额外的业务逻辑。 将关于发布者区域的信息纳入系统增强了系统的可追溯性,而将唯一的系统标识符附加到MQTT消息使得能够全面记录和跟踪从发送者到所有订阅者的整个消息流。有效实施这些标识符可以延伸到多个MQTT消息流,引入了前所未有的透明度和可追溯性。 这些能力打开了一个新的可能性领域,特别是对于业务关键的应用程序,如面向最终客户的高级付费服务,透明度和可追溯性变得不可或缺。 MQTT 5中用户属性的总结和其他信息 1.用户属性作为可以无缝添加到任何MQTT消息中的UTF-8字符串键值对。这种能力使它们成为MQTT协议的多才多艺和宝贵的补充。2.用户属性在增强MQTT用例方面的实施潜力几乎是无限的。它提供了一定程度的定制,允许许多创新的应用,无论是在功能还是范围上。3.跨多个系统和供应商的部署和项目可以利用此功能以保持一致性,并确保整个基础架构之间的无缝通信。4.我们为看到MQTT用户将如何利用这一看似简单但具有巨大影响的功能的潜力而感到兴奋。 MQTT 5中的用户属性代表了协议可扩展性和多功能性的重大进步,为未来的物联网应用程序开辟了令人兴奋的可能性。 --- ### 106. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5基础知识系列的第5部分。在第4部分中,我们深入探讨了MQTT会话到期和消息到期。我们揭示了这些功能如何增强物联网应用中的消息管理和效率,使MQTT 5更加灵活和高效。在本文中,我们将重点关注MQTT 5的增强客户反馈和负面确认(NACKs)。我们将剖析MQTT 5为代理确认客户而实施的这种方法,研究它们简化开发人员和运维团队工作的潜力,从而使协议更加健壮和高效。 谁需要更多的MQTT客户端反馈? 多年来,MQTT已经成为众多物联网项目的重要组成部分。正如本系列中所指出的,OASIS委员会在制定新的MQTT 5协议标准时充分考虑了实际协议用户的反馈。主要的抱怨之一是明显的不透明性,主要是由于不足的返回代码和有限的通信方式,导致代理无法向客户端传达特定的限制或情况。这个缺陷增加了调试复杂性,特别是在多供应商项目中。 无论是深入研究客户端断开连接的原因,检查为何消息无法到达其指定目标,还是在各个团队中保证MQTT客户端部署的一致性,MQTT 3的用户通常需要通过技术来增强基本协议功能。MQTT 5经过精心设计,旨在更高效、标准化地解决这些挑战,引入了以下功能。 MQTT 5的特定功能集 让我们专注于几个MQTT 5功能,通过代理提供更多透明度并允许中央系统控制。 MQTT 5中连接建立的反馈 使用MQTT 5版本,MQTT代理现在可以在连接建立时向MQTT客户端提供附加反馈。可以向连接确认数据包添加多种不同的属性,告诉客户端代理支持或允许客户端使用的功能。这些功能包括以下MQTT功能: 保留消息 通配符订阅 订阅标识符 共享订阅 主题别名 客户端可以使用的最高服务质量级别除了通知客户端已启用和已禁用的功能外,CONNACK数据包中的新属性还允许服务器向客户端反馈代理授予的限制。这些限制包括: 保持活动时间 会话到期间隔 最大数据包大小 客户端可以发送的最大主题别名数除了支持所有这些限制外,HiveMQ还允许您在服务器端为这些限制配置最大值,并禁用您用例中不需要的MQTT功能。 MQTT 5中更好的原因代码 在以前的版本中,即MQTT版本3.1和3.1.1中,可用原因代码的种类有限,只有五个与不成功操作相关的代码。然而,MQTT 5大幅增强了这个方面,提供了一组扩展的超过20个原因代码,专门用于不成功的情况。 此外,MQTT 5还引入了将原因代码集成到以前的版本中缺少此属性的数据包的可能性。这些数据包包括UNSUBACK、PUBACK、PUBREC、PUBREL、DISCONNECT和PUBCOMP。这一增强进一步增强了协议的透明性和故障排除效率,说明了MQTT 5所取得的进步。 通过MQTT 5引入具体原因字符串增强清晰度 尽管添加了额外的原因代码确实增强了对客户端的反馈质量,但这些代码通常不足以提供具体的上下文。这就是MQTT 5引入“原因字符串”概念的地方,规范中描述为“…为诊断而设计的人类可读字符串…” 原因字符串提供了开发人员和运维团队需要快速确定事件原因的全面上下文。本质上,原因字符串是一种专门设计用于诊断目的的人类可读字符串。这个有价值的工具有助于以原因代码本身无法提供的方式理解事件的细微差别。 但值得注意的是,原因字符串,尽管在开发和诊断中非常有用,但可以在的配置中禁用。这种灵活性适用于可能不希望暴露此类详细信息的情况。 MQTT 5中的服务器发送断开数据包 在MQTT 3.1和3.1.1中,当客户端超过代理定义的限制时,代理会通过突然关闭客户端的连接来作出响应。然而,这种行为不会向客户端直接提供有关连接终止原因的信息,这可能导致混淆和故障排除困难。 相反,MQTT 5通过引入服务器发送的断开数据包大大改进了这个过程。这允许代理在终止连接之前向客户端传递DISCONNECT数据包。每个服务器发送的断开数据包都包含一个原因代码和相应的原因字符串。这两个元素共同为客户端提供了全面的了解为何连接被断开的理由。 这种连接终止的简化方法不仅为客户端增加了清晰度,还大大简化了确定由代理发起的连接关闭背后原因的过程。MQTT 5中的这一显著增强显著提高了代理和客户端之间的通信透明度。 MQTT 5中的否定确认是什么 在MQTT 5中,通过增加否定确认,通信机制得到了很大的改进。现在,多个数据包类型和消息流可以用否定确认消息进行响应,增强了消息基础设施的整体反馈循环。 与MQTT 3不同,MQTT 5中的UNSUBACK数据包包含一个原因代码,告知客户端其UNSUBSCRIBE尝试的状态,提供清晰而有针对性的反馈。列举了几种潜在的失败原因,例如初始订阅不存在或客户端没有取消订阅的授权。 来自发布流的确认数据包,特别是PUBACK、PUBREL、PUBREC和PUBCOMP,也已经增强,可以发送否定确认消息。当服务器无法处理客户端发送的消息时,例如因为客户端没有发布到某个主题的必要授权,增强的确认数据包现在为客户端提供了所有必要的信息以适应和纠正这种情况,减少了联系运营或支持团队以了解问题的需要。这标志着在MQTT 5应用程序内保持高效和流畅的通信方面迈出了重要的一步。 MQTT 5:优化MQTT通信 MQTT代理,例如HiveMQ,允许您为上述限制的最大值设置服务器端最大值配置。这在多供应商项目中特别有用,在这些项目中,代理操作员可能无法直接控制MQTT客户端的设置。 为客户端改进的反馈大大简化了开发和运维团队的诊断过程。引入的透明性还改善了不同MQTT客户端和代理之间的互操作性。 了解MQTT 5的更多信息 MQTT代理,如HiveMQ,提供了允许服务器端最大值配置的优势,涉及到上述限制的最大值。这个功能在多供应商项目中尤其有价值,其中代理操作员可能无法直接控制MQTT客户端的设置。 值得注意的是,对于客户端的改进反馈大大简化了开发和运维团队的诊断过程。这种增强的反馈机制可以更快地解决问题,防止在MQTT系统中出现潜在的瓶颈。 此外,这些改进引入的透明性提高了不同MQTT客户端和代理之间的互操作性。这个特性对于创建强大而多功能的物联网生态系统至关重要,并进一步强调了MQTT 5在增强通信、调试和整体系统控制方面所取得的进展。 --- ### 107. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 欢迎来到我们的MQTT 5基础知识系列的第4部分。在本系列的第3部分《MQTT 5:从MQTT 3.1.1升级的七个原因》中,我们阐述了MQTT用户升级到版本5的主要动机,强调了使MQTT 5成为有吸引力的升级的增强功能。在本文中,我们将专注于两个密切相关的功能:会话到期间隔和消息到期间隔。这些功能代表了MQTT 5中的关键改进,深入了解它们对于协议的最佳利用至关重要。 MQTT 5中的会话到期间隔和消息到期间隔是如何工作的? 让我们分别详细介绍和分析这两个重要的到期间隔功能。 MQTT 5中的会话到期间隔 会话到期间隔是客户端在连接(CONNECT)数据包阶段设置的参数,以秒为单位指定。此参数指示代理保留客户端会话信息的持续时间。如果此间隔设置为零,或者CONNECT数据包未指定到期值,那么一旦客户端的网络连接终止,会话数据将立即从代理中删除。值得注意的是,最大的会话到期间隔是(4,294,967,295),允许离线会话在客户端断开连接后延续超过136年。 MQTT 5中的消息到期间隔 在MQTT 5中,客户端可以为每个PUBLISH消息设置一个唯一的消息到期间隔,以秒为单位。这个间隔确定了代理保留PUBLISH消息以供与主题匹配但当前离线的订阅者的持续时间。如果未定义间隔,代理必须无限期地保留匹配但断开连接的订阅者的消息。此外,如果在PUBLISH消息中选择 “retained=true” 选项,则该间隔还决定了消息在特定主题上保留的时间长度。 MQTT 5的会话到期间隔 MQTT 5中的会话到期间隔巧妙地同时满足了两个关键需求。早期版本的MQTT只提供了一个根据规范定义的删除持久会话的途径:要删除一个持久会话,必须使用与要丢弃的会话相同的客户端ID连接,并将标志设置为cleanSession=true。 考虑一些IoT设备永远不会重新连接的情况,原因可能是因为已经报废、损坏,或者因为在负载测试后未进行适当的清理而留下的会话。这些残留会话可能对代理的持久性造成不必要的负担。MQTT 5的会话到期间隔功能应运而生。这个直观的功能使用户能够指定一个合理的持续时间,之后代理会自动清除空闲会话,释放宝贵的资源。 除了这种自动清理功能之外,会话到期间隔还极大地简化了会话状态管理。Ian Craggs提供了两个示意图,显示了状态转换复杂性的降低。这种可视化呈现强调了这个新功能如何有助于简化状态转换并增强用户效率。 MQTT 5的消息到期间隔 与会话到期的间隔类似,消息到期的间隔始于对自动维护机制的需求。考虑到众多的IoT设备,比如设计用于长时间断网的连接汽车。MQTT通过持久会话和消息队列为这些情况提供了生命线。 为离线设备制定的消息存储在代理上,等待设备恢复连接以便传递。在大规模部署中,连接的设备数量可能升级到数千甚至数百万,因此对于每个客户端单独限制离线消息队列至关重要。 与IoT设备相关的消息的相关性的持续时间可能会出现显著的波动。以连接汽车为例:交通更新仅在短时间内保持相关性。但是,当我们考虑到空中固件升级时,即使汽车在数周之内保持离线,也需要执行这些 升级。 MQTT 5中的消息到期间隔正好是管理这些不同时间范围的完美工具,增加了协议的多功能性。 通过为具有有限相关性窗口的消息分配一个最佳的消息到期间隔,并为永久相关性的消息保留无到期时间,我们确保了代理资源的有效利用,以供可能离线相当长时间的客户端使用。这种策略还可以在重新连接时免除客户端被淹没在无关消息中。 对于保留的消息,消息到期间隔的操作方式类似,确保这些消息只发送给新的订阅者,以在指定的时间段内传递。 然而,需要注意的一个关键方面是,当客户端的会话到期时,为该客户端排队的所有消息也会与会话的到期一起过期,而不考虑它们各自的消息到期状态。这一“GOTCHA”是MQTT协议中会话及其排队消息之间相互关联性的重要提醒。 在使用MQTT 5的会话到期间隔和消息到期间隔时的重要提示以下是一些重要信息: 会话到期间隔和消息到期间隔都对MQTT代理上的资源管理起到了关键作用。回顾过去,许多MQTT 3用户表达了对到期功能的需求。HiveMQ回应了这一需求,在我们的MQTT平台中引入了会话和消息到期作为补充功能,这早于它们在MQTT 5中的标准化。MQTT 3 CONNECT数据包中的cleanSession=true的等价物在MQTT 5中是sessionExpiry=0(或不存在)和cleanStart=true。同样,MQTT 3 CONNECT数据包中的cleanSession=false在MQTT 5中的对应项是sessionExpire值大于零,再加上cleanStart=false。MQTT代理,在服务器端提供了配置这些到期间隔的最大值的功能。在多供应商项目中,特别是当代理操作员可能无法控制MQTT客户端设置时,这个功能非常方便。 MQTT 5的出现引入了一系列旨在提高协议的可用性、灵活性和效率的新功能。会话到期间隔和消息到期间隔是这一点的最佳例证,它们是资源管理的宝贵工具,确保您的MQTT代理的顺畅运行。这两个功能都真正体现了MQTT标准对用户需求和挑战的响应,展示了它对于用户的需求和挑战的响应。 --- ### 108. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网(IoT)在过去的十年中迅速发展,MQTT已成为无缝高效通信的标准协议。随着IoT系统规模和复杂性的增长,MQTT协议也在不断发展以满足这些需求。在这个背景下,MQTT 5升级引入了显著的改进,以满足现代IoT应用程序不断扩展的需求。 在本文中,我们将探讨为什么您的企业或开发团队应该考虑从 MQTT 3.1.1升级到 MQTT 5。 为什么要从 MQTT 3升级到 MQTT 5? MQTT 5代表了MQTT协议的实质性增强,它是根据MQTT用户的宝贵意见开发的。它包括了现代IoT应用程序所需的功能,专为基于云的部署量身定制。这些改进增强了系统的弹性,可靠地处理关键消息的错误管理,并促进了将MQTT消息无缝集成到现有计算框架中。 在本文中,我们提出了公司或开发团队应考虑升级到 MQTT 5的七个理由,包括: 更好的错误处理,实现更强大的系统MQTT 5极大地增强了错误处理机制,有助于系统的稳定性和可靠性。一个显著的引入是会话和消息到期功能。这允许开发人员为每个消息和会话设置定义的时间限制。如果消息在此时间范围内未传递,它将被自动删除。这个功能特别有用,可以确保网络延迟或中断不会导致将过时或无关的命令传递给IoT设备。 MQTT 5 在提供更强的可扩展性方面优于 MQTT 3在不断增长的IoT网络世界中,可扩展性是一个关键需求。MQTT 5通过标准化共享订阅来解决这个问题。这允许多个MQTT客户端实例在代理上共享相同的订阅。这是一个强大的功能,用于在云集群上部署负载平衡的MQTT客户端。这种可扩展性使MQTT 5成为具有大规模部署的企业以及计划扩展其IoT系统的企业的坚实选择。 MQTT 5在提供更大的灵活性和更容易集成方面优于 MQTT 3MQTT 5推出了协议属性,将定制化提升到了一个新水平,允许将键值属性添加到MQTT消息的标头中。这意味着应用程序特定的信息可以直接包含在每条消息中,增强了这些消息的处理。例如,可以将包含发送客户端的唯一标识符或设备平台的固件版本的元标记添加到消息标头中,以便接收方进行分析和处理。 另外,MQTT 5通过引入有效载荷格式指示符来简化接收方的处理过程。现在更容易区分二进制或文本数据,因为MQTT 5包括了一种 MIME 风格的内容类型描述符。这个功能对于各种应用都提供了巨大的价值。考虑一下,一个收费公路控制系统正在传输车牌图像以进行图像识别处理。相比之下,其他消息可能需要不同的处理方式,例如包含位置坐标的消息。通过指定格式,MQTT 5确保高效和适当地处理各种数据类型。 MQTT 5 作为IoT标准的优势凭借其丰富的功能集,MQTT 5已经巩固了自己在各种IoT用例中的地位,成功解决了先前版本的限制。我们预计在未来几年中MQTT将在各个行业迎来指数级的增长,这暗示了MQTT即将成为普遍IoT标准的前景。 MQTT 5未来趋势通过解决MQTT 3的限制,MQTT 5为IoT应用程序的未来增强铺平了道路。其灵活和强大的功能使其适应未来技术趋势,确保您的IoT系统保持当前并为未来的发展做好准备。 MQTT 5与其前身的兼容性 MQTT 5的一个实际优势是它与其前身的兼容性。它支持 MQTT 3.1和 MQTT 3.1.1的功能,允许混合使用 MQTT 3和 MQTT 5客户端。这使得迁移过程变得无缝,使组织能够逐渐过渡到 MQTT 5而不会干扰现有的IoT运营。 MQTT 5 在提供改进的功能方面优于 MQTT 3在本节中,我们深入探讨了MQTT 5的一系列增强功能。从通过否定确认来增强系统的健壮性,到通过用户属性实现定制化,再到通过主题别名提高效率,MQTT 5极大地强调了可用性、灵活性和性能。此外,MQTT 5引入了有效载荷格式指示符,以简化不同数据类型的数据处理。让我们详细探讨这些改进:否定确认为了进一步增强系统的健壮性,MQTT 5引入了否定确认的概念。代理可以在预定义的条件或限制下拒绝特定消息,例如超过最大消息大小、最大服务质量(QoS)或使用不支持的功能。这一积极措施防范了可能开始发送错误或恶意消息的MQTT客户端,显著增强了整个系统的安全性。 主题别名以提高效率在具有复杂主题结构的大型系统中,主题字符串可能变得很长,增加了网络和处理负载。MQTT 5引入了主题别名,允许您将这些长主题字符串替换为整数值。这可以大大减少网络和处理负载的需求,从而提高系统的效率和性能。 用户属性以实现定制化MQTT 5通过引入协议属性进一步实现了定制化。这允许开发人员将键值属性添加到MQTT消息的消息标头中。这种定制化水平使您能够在每条消息中包含特定于应用程序的信息。这些数据可以用于丰富消息处理和集成,使开发人员在应用程序上具有更多的灵活性和控制。 有效载荷格式指示符鉴于IoT应用程序中多种数据类型,拥有一种简化数据处理的机制至关重要。MQTT 5满足了这一需求,引入了有效载荷格式指示符。这些指示符标识有效载荷是二进制还是文本,并包括 MIME 风格的内容类型。这有助于提高数据处理效率,并使系统更适应各种数据用例。 结论:MQTT 5 - IoT通信的变革者MQTT 5代表了IoT通信的一大步。它不仅仅是一个小的升级,它巧妙地解决了以前的不足,并充满了强大的功能。对于现代IoT应用程序来说,它是一个不可或缺的工具。MQTT 5不仅仅是一个好选择,它是您IoT应用程序的一个引人注目的选择,准备将您带入IoT的未来。 --- ### 109. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT(Message Queuing Telemetry Transport)是一种通信协议,通过跨多个部署连接众多受限设备,构建了庞大的连接系统和独立设备网络。MQTT在各个领域的广泛应用,从联网汽车、制造系统、物流到企业聊天应用程序和移动应用程序,都刺激了对其进一步发展的需求。MQTT 5 应运而生,承诺提供一系列令人兴奋的新功能和改进。 在这个由 12 部分组成的 MQTT 5 要点系列中,我们将深入探讨 MQTT 5 的各个方面。该系列将揭示从协议的基础变更到用户属性、共享订阅、有效负载格式描述、请求-响应模式、主题别名、增强身份验证和流控制等主题。在本系列结束时,您将全面了解 MQTT 5 对物联网的实际影响,以及它如何通过其优势增强物联网解决方案的性能。在本文中(第 1 部分),我们将提供 MQTT 的起源和演变的高级概述。 在深入研究 MQTT 5 之前,如果您对 MQTT 不太熟悉或需要复习,我们建议您查看 MQTT Essentials 系列。这将有助于您更好地理解 MQTT 5 中引入的改进和根本性变化。 MQTT的起源与演变 为了理解 MQTT 5,首先让我们回顾一下 MQTT 的起源和演变。MQTT 协议诞生于上世纪90年代末,由IBM的Andy Stanford-Clark和Cirrus Link的Arlen Nipper创建。最初,MQTT被设计用于监测卫星网络上的石油和天然气管道。MQTT 的设计注重开放性、简洁性和易于实现。因此,MQTT 成为一种超轻量级协议,旨在节省网络带宽和设备资源,以确保数据的可靠传输。它的设计允许数千台设备与单个 MQTT 服务器连接,这使得它非常适用于受限制的环境,尤其是在网络带宽有限、延迟较高的物联网生态系统中。 MQTT 5 的设计目标 MQTT 的演进工作由 OASIS 技术委员会(TC)负责,他们面临着一个复杂的挑战,即如何在不增加复杂性或降低易用性的情况下,添加长期期望的功能。他们的目标是提高性能和可扩展性,同时确保协议保持易用性。MQTT 5 引入了一系列激动人心的新功能,以满足不断增长的物联网需求。 MQTT 5 的重大改进和新功能 MQTT 5 的关键目标之一是提高其处理大规模系统的能力。MQTT 3.1.1 曾经展示了其在物联网协议中的独特可扩展性和有状态性,HiveMQ 的企业 MQTT 平台实现了 200 亿个并发连接,标志着一个重要的里程碑。MQTT 5 在这一传统基础上构建,简化了 MQTT 服务器扩展到处理大量并发连接客户端的过程。 MQTT 5 引入了增强的身份验证机制,提供了更强大的安全框架。在当今世界,网络攻击风险时刻存在,因此 MQTT 5 允许用户选择更复杂的加密算法和密钥管理技术,以保护设备和数据的安全。 另一个重大改进是引入了共享订阅功能,允许跨多个客户端实例对消息进行负载平衡。这确保了消息管理的高效性,特别是在涉及大量设备同时传输数据的场景下。 此外,MQTT 5 还引入了消息属性的概念,允许在每条消息中包含额外的元数据,如时间戳、位置信息或设备状态,这在提供数据上下文方面非常有用。 总之,从 MQTT 3.1.1 到 MQTT 5 的过渡不仅仅是版本号的升级,更是协议功能的重大飞跃,涵盖了多个改进领域。其结果是一个更强大、更可靠和可扩展的协议,更适合满足现代物联网应用程序的需求。 结论 MQTT 5 代表了物联网通信协议的一次革命性进步,以满足不断增长和演变的物联网需求。了解 MQTT 5 的改进和新功能对于确保物联网系统的性能和可靠性至关重要。因此,开发人员、系统集成商和最终用户都应密切关注这些变化,以充分利用这一强大的物联网通信协议,为现代物联网应用提供最佳解决方案。 MQTT 的演进不会止步于 MQTT 5。MQTT 技术委员会仍在研究更多增强功能和特性,以确保 MQTT 在不断发展的物联网领域中保持相关性和强大性。这一持续发展的承诺将确保 MQTT 继续发挥重要作用,助力物联网生态系统的不断增长和进步。 --- ### 110. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当谈到 MQTT 5 时,其中一个最令人激动且具有革命性意义的特性是能够在 MQTT 头部中包含自定义键值属性。这个特性可能会从根本上改变许多 MQTT 部署的方式。与其他协议,例如 HTTP,类似,MQTT 客户端和代理现在可以添加无限数量的自定义或预定义头部来携带元数据。这些元数据具有很大的灵活性,可以根据特定的应用数据进行定制。而预定义的头部主要用于执行许多新的 MQTT 功能。 此外,在 MQTT 数据包中现在包含了原因代码,它们用于表示协议错误的具体情况。这些原因代码通常出现在确认数据包上,它们有助于解释错误情况,并有可能帮助客户端和代理制定补救措施。这些原因代码的范围广泛,从"配额已超出"到"协议错误"等各种情况。客户端和代理需要一起解码和理解这些新增的原因代码,从而丰富了 MQTT 的整体体验。 当我们谈论自定义键值属性和原因代码时,现在让我们来探讨 MQTT 如何处理不支持的功能以及如何使用 CONNACK 返回代码来做出响应。 如何使用 MQTT 5 中的预定义头部来响应不支持的功能? 随着 MQTT 的普及,各种公司提供了各种 MQTT 软件、库或系统。然而,由于不完全遵循 MQTT 规范,某些功能可能无法完全实现,例如 QoS 2、保留消息或持久会话。为了解决这些问题,MQTT 5 引入了一个巧妙的解决方案。它允许那些功能不完整的软件、库或系统(通常在 SaaS 提供中很常见)告知代理它们无法支持某些功能。然后,客户端有责任确保不使用这些不受支持的功能。代理在响应客户端的 CONNECT 数据包时,通过 CONNACK 数据包中的预定义头部来传达对特定功能的不支持。这些头部还可以通知客户端它们无权使用某些功能。 在 MQTT 5 中,可以使用以下预定义头部来指示未实现功能或未经授权的客户端使用: 预定义头部 Retain Available:是否可用于保留消息? 预定义头部 Maximum QoS:允许客户端发布消息或订阅主题的最大 QoS 预定义头部 Wildcard Available:是否可以使用通配符进行主题订阅? 预定义头部 Subscription identifiers available:MQTT 客户端是否可用订阅标识符 预定义头部 Shared Subscriptions available:MQTT 客户端是否可用共享订阅 预定义头部 Maximum Message Size:定义 MQTT 客户端可使用的最大消息大小 预定义头部 Server Keep Alive:服务器支持的个别客户端的保活间隔 这些返回代码代表了表达各个 MQTT 客户端权限的重要方法。然而,这一新功能带来了某种平衡:MQTT 客户端必须独立实现对这些代码的解释,并确保应用程序开发人员避免使用代理不支持或客户端没有权限使用的功能。对于那些想要维护严格规范 MQTT 部署的人来说,HiveMQ 完全符合 MQTT 5 的所有功能,从而确保这些自定义头部只会在管理员的决策下用于设置部署中的权限。 增强的会话管理:从清除会话到 MQTT 5 中的“清除启动” 在 MQTT 3.1.1 中,"清除会话"是一个显著的特性,但在 MQTT v5 中已经被"清除启动"所取代。在 MQTT 3.1.1 中,客户端使用"清除会话"功能,根据连接到代理时是否有临时连接或未订阅消息。在连接到代理后,客户端需要发送一个 CONNECT 数据包,其中包括清除会话标志,它可以启用或禁用。如果启用该标志,它表示向代理发出请求,在底层 TCP 连接断开或客户端决定与代理断开连接时,应丢弃所有客户端数据。此外,如果代理有关联到客户端标识符的先前会话,则清除会话 CONNECT 数据包将迫使代理丢弃先前的数据。 MQTT 5 引入了清除启动选项,由 CONNECT 消息中的清除启动标志表示。通过这一标志,代理会放弃任何先前的会话数据,从而启动新的会话。但是,当 TCP 连接在客户端与服务器之间关闭时,会话并不会自动清除。为了在断开连接后触发会话删除,必须将新的头部字段"会话过期间隔"设置为 0。这种修改的清除启动功能增强并简化了 MQTT 的会话处理,相对于之前的"清除会话"/"持久会话"概念,提供了更多的灵活性和更容易的实施。在 MQTT 5 中,会话会保留,除非将"会话过期间隔"设置为 0。会话的删除要么在间隔超时后发生,要么在客户端使用清除启动重新连接时发生。 MQTT 5 中的 AUTH 数据包是什么? 在一个令人激动的发展中,MQTT 5 引入了一种新的数据包类型:AUTH 数据包。这个数据包在实施非传统身份验证机制方面至关重要,我们预计它将在生产环境中发挥关键作用。我们将在另一篇文章中详细讨论其确切语义。 需要理解的关键是,这种新型数据包可以在建立连接后由代理和客户端分发。它允许使用复杂的挑战/响应身份验证方法,例如在 SASL 框架中概述的 SCRAM 或 Kerberos,同时也与先进的 IoT 身份验证方法(如 OAuth)兼容。重要的是,AUTH 数据包使得 MQTT 客户端可以在不需要终止连接的情况下重新进行身份验证。 MQTT 5 如何利用 UTF-8 字符串对增强通信? 为了容纳自定义头部,MQTT 引入了一种新的数据类型,即 UTF-8 字符串对。简而言之,字符串对是一种键-值结构,其中键和值都是字符串数据类型。目前,这种数据类型主要用于自定义头部。 这个新增的数据类型扩展了 MQTT 在传输中使用的数据类型的范围,总共包括七种: 位 两字节整数 四字节整数 UTF-8 编码字符串 可变字节整数 二进制数据 UTF-8 字符串对 对于大多数应用程序用户来说,二进制数据和 UTF-8 编码字符串仍然是 MQTT 库 API 中的首选数据类型。然而,随着 MQTT 5 的引入,预计 UTF-8 字符串对将会更频繁地使用。虽然用户可能不会直接看到其他数据类型,但它们在 MQTT 客户端库和代理中用于构建有效的 MQTT 数据包。 MQTT 5 如何通过双向 DISCONNECT 数据包简化通信? 在 MQTT 3.1.1 中,客户端可以在关闭底层 TCP 连接之前发送一个 DISCONNECT 数据包,以优雅地终止连接。然而,在 MQTT 代理通知客户端需要关闭 TCP 连接的情况下,这个版本存在一个问题。这个问题在新的协议版本中得到了解决。 在增强版 MQTT 中,代理被授权在断开套接字连接之前传输 DISCONNECT 数据包。这一规定使客户端能够理解断开连接的原因,并相应地制定适当的响应。虽然代理没有义务披露确切的原因(例如,出于安全原因),但这个功能有助于开发人员,因为它提供了有关代理终止连接的原因的有价值的信息。 另一个有价值的补充是 DISCONNECT 数据包现在可以携带原因代码,从而简化了揭示断开连接原因的过程,例如在权限无效的情况下。 在 MQTT 5 中对 QoS 1 和 2 进行了改进:取消了对健康连接的消息重传 MQTT 使用持久的 TCP 连接(或具有相同保证的类似协议)进行底层传输。强大的 TCP 连接确保了双向连接,以确保所有客户端或代理发送的 MQTT 数据包都将在另一端接收,并且只接收一次并按顺序发送。这意味着客户端或代理发送的所有 MQTT 数据包都将在另一端接收。在消息在传输过程中断开连接时,QoS 1 和 2 确保消息通过多个 TCP 连接传递。 在 MQTT 3.1.1 协议下,即使 TCP 连接正常,也允许重新传输 MQTT 消息。在实际中,这常常是有害的,可能会导致已经负载繁重的 MQTT 客户端超载。考虑这样的情况:一个 MQTT 客户端需要 11 秒来处理从代理接收的消息,并在处理后发送确认数据包。如果代理在 10 秒超时后重新传输消息,实际上并没有什么好处。这种方法只会消耗宝贵的带宽,并进一步加重 MQTT 客户端的负担。 随着 MQTT 5 的出现,对于健康的 TCP 连接,无论是代理还是客户端,都不允许重新传输 MQTT 消息。 然而,当 TCP 连接断开时,代理和客户端必须重新发送未被确认的数据包。因此,对于 QoS 1 和 2,在 MQTT 5 中仍然具有相同的重要性,就像在 MQTT 3.1.1 中一样。 如果您的用例依赖于重新传输数据包(例如,如果您的实现在某些情况下未能确认数据包),我们建议在升级到 MQTT v5 之前重新评估这种策略。 MQTT 5 如何简化身份验证? 在 MQTT 3.1.1 协议中,当 MQTT 客户端在 CONNECT 数据包中使用密码时,需要提供用户名。这对于某些不需要用户名的用例可能不太方便,例如使用 OAuth 进行身份验证和授权的情况,其中关键信息包含在密码字段中。在 MQTT 5 中,该协议引入了更精细的处理令牌的方式,例如通过 AUTH 数据包。但是,仍然可以在不提供用户名的情况下使用 CONNECT 数据包的密码字段。这个调整提供了一种更简化和直接的身份验证方法,特定情况下非常方便。 总结 虽然 MQTT 协议的核心保持相对不变,但在表面下进行了微妙的改进,为这一广泛采用的 IoT 协议的第 5 版奠定了基础。对于使用 MQTT 库的用户来说,这些修改可能似乎很小,不会从根本上改变 MQTT 的使用方式。然而,对于在 MQTT 库和代理上工作的开发人员来说,这些变化,特别是与协议细节相关的变化,都是关键的,并需要关注。 --- ### 111. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在智能家居技术日益普及的今天,MQTT已经成为智能设备通信的重要协议。而Home Assistant (HASS) 则为我们提供了一个灵活且功能强大的集中管理平台。但如何在一个HASS实例中同时连接多个MQTT服务器,实现高效整合呢?此文将为您揭示背后的技术细节和最佳实践 单MQTT服务器连接通常,将HASS连接到一个MQTT服务器是直观且简单的。只需在HASS的配置文件中加入以下代码即可: mqtt: broker: 192.168.6.166 port: 1883 username: mqtt password: mqtt 连接多MQTT服务器的挑战想象一下,如果在同一个HASS实例中,我们希望连接多个MQTT服务器,可能会设想如下配置: mqtt: - broker: 192.168.6.166 ... - broker: 192.168.6.188 ... 但实际上,HASS并不支持这种配置。原因是,当我们有多个MQTT服务器时,会出现消息主题冲突的问题。例如,我们可能会定义以下MQTT开关: switch: - platform: mqtt name: bedroom_main_light state_topic: 'hassmart/switch/hassmart_1key_module_C2756C_1/state' ... 在这种情况下,我们无法确定该主题到底属于哪个MQTT服务器,导致了HASS只允许配置一个MQTT服务器的限制。 Mosquitto桥接:连接多MQTT的解决方案但有时,我们确实需要HASS连接多个MQTT服务器。例如,你可能运行了一个稳定的HASS实例,同时也有一个用于测试的HASS实例,两者都需要连接MQTT设备。此时,我们可以利用Mosquitto的桥接功能。 这种桥接方法是将一个MQTT服务器(如主服务器)配置为另一个MQTT服务器(如外部服务器)的客户端,从而同步两个服务器之间的消息。 在HASS.IO中,为实现MQTT桥接,首先需要启用Mosquitto broker插件的自定义配置文件选项。开启此选项后,系统会自动读取/share/mosquitto/目录下的.conf配置文件。 为配置桥接,我们需要在该目录下创建一个名为mqtt-bridge.conf的文件,并加入以下配置: # Additional MQTT Broker connection mqtt-bridge address 192.168.6.8:1883 topic hassmart/# both remote_username mqtt remote_password mqtt 保存文件后,重启mosquitto broker addon即可生效。 此时接入到桥接mqtt服务器上的设备,均可直接接入当前HASS了,加入相关代码,重启HASS,接下来就是见证奇迹的时刻了! 以其它方式安装的mosquitto,直接修改mosquitto.conf,加入上述代码,重启mosquitto服务即可实现相同的效果。更多好玩的桥接设置,请自行参阅mosquitto官方文档。 总结通过上述方法,HASS可以高效地整合多个MQTT服务器,为用户带来更为灵活和强大的智能家居管理体验。随着技术的不断进步,我们相信未来还会有更多创新和优化。希望此文能为您的智能家居实践提供有益的参考。 --- ### 112. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当谈到MQTT(Message Queuing Telemetry Transport)时,有许多不同编程语言的库和工具可供选择,以便轻松地集成MQTT通信协议到您的项目中。MQTT是一种轻量级的消息协议,特别适用于物联网(IoT)和低带宽、高延迟或不可靠网络环境。本文将介绍一些流行的编程语言以及它们的MQTT库和工具,帮助您在各种环境中实现可靠的消息通信。 C/C++: 编程语言库/工具名称详细信息CEclipse Paho C通用MQTT C库。CEclipse Paho Embedded C用于嵌入式系统的MQTT C库。ClibmosquittoMosquitto MQTT代理的C库。Clibemqtt用于嵌入式系统的C MQTT客户端库。CMQTT-C便携式MQTT C客户端,适用于嵌入式系统和PC。CwolfMQTT嵌入式C MQTT客户端。CSharkMQTT嵌入式C MQTT客户端。Clibcurllibcurl具有基本的发布和订阅支持。CMQTT over lwIP用于嵌入式系统的MQTT C客户端,使用FreeRTOS,lwIP和mbedtls。Clibsmartfactory支持智能工厂和工业4.0技术的库,包括MQTT客户端实现。Clibumqtt基于libev的轻量级和完全异步的C MQTT客户端库。C++Eclipse Paho C++通用MQTT C++库。C++libmosquittoppMosquitto MQTT代理的C++库。C++Eclipse Paho Embedded C++用于嵌入式系统的MQTT C++库。C++mqtt_cpp基于C++14和Boost.Asio的MQTT客户端和服务器库,支持MQTT v3.1.1和v5。C++async_mqtt基于C++17和Boost.Asio的MQTT客户端和服务器库,支持MQTT v3.1.1和v5.0。C++eMQTT5MQTT 5.0客户端。 Python: 编程语言库/工具名称详细信息PythonEclipse Paho Python最初由Mosquitto Python客户端编写。Pythongmqtt异步Python 3 MQTT客户端库。Pythonnyamuk一个轻量级的Python MQTT客户端库。PythonMQTT for twisted python用于Twisted Python的MQTT库。PythonHBMQTT高性能Python MQTT客户端库,支持MQTT 5.0和MQTT 3.1.1。Pythonmqttools用于Python的MQTT协议工具和客户端库。 Java: 编程语言库/工具名称详细信息JavaActiveMQ ClientApache ActiveMQ的Java客户端库。JavaEclipse Paho Java通用MQTT Java库。JavaFusesource mqtt-clientFusesource MQTT客户端库。JavaMeQanTTJava MQTT客户端库,支持Android和Processing。JavamoquetteJava实现的MQTT代理库。JavaMqttWkJava MQTT客户端库。JavaHiveMQ MQTT Client高性能Java MQTT客户端库,支持MQTT 5.0和MQTT 3.1.1。JavaIA92 (已弃用)IBM IA92支持包,现已弃用。JavaQatja用于Android和Processing的Java客户端库,支持MQTT 3.1.1。JavaSentienz Akiro MQTT ClientJava MQTT代理客户端库,支持MQTT 3.1.1。Javavertx-mqtt-client开源、高性能、非阻塞的Java MQTT客户端库,作为vert.x的JVM工具包的一部分。JavaXenqtt包含客户端库、用于单元/集成测试的模拟代理以及支持企业需求的应用程序,如将一组服务器用作单个客户端、HTTP网关等。JavaMicronaut MQTTMicronaut Framework和MQTT的集成。 Dart: 编程语言库/工具名称详细信息Dartmqtt.dart用于Dart的MQTT客户端库。Dartmqtt_clientDart的MQTT客户端库。 Delphi: 编程语言库/工具名称详细信息DelphiDelphi-TMQTT2Delphi的MQTT客户端库。 Erlang: 编程语言库/工具名称详细信息ErlangerlmqttErlang的MQTT客户端库。ErlangemqttcErlang MQTT客户端库。Erlangmqtt4erlErlang的MQTT客户端库。Erlangmy-mqtt4erl (已更新的分支)Erlang的MQTT客户端库。Erlangerl.mqtt.clientErlang的MQTT客户端库。 Elixir: 编程语言库/工具名称详细信息Elixirhulaaki用于与MQTT代理通信的Elixir库(驱动程序),支持MQTT 3.1.1协议。ElixirExmqttcemqttc库的Elixir包装器。Elixirtortoise用Elixir编写的MQTT客户端。 Go: 编程语言库/工具名称详细信息GoEclipse Paho Go通用MQTT Go库。Gomqtt by jeffallenGo中的MQTT实现。GoMQTT🤖适用于嵌入式系统的简单、小型MQTT实现。Gonatiu-mqtt适用于嵌入式系统的简单、小型MQTT实现。 Haskell: 编程语言库/工具名称详细信息Haskellmqtt-hsHaskell的MQTT库。Haskellnet-mqtt (支持3.1.1和5.0客户端)Haskell的MQTT库。 Javascript/Node.js: 编程语言库/工具名称详细信息JavaScript/Node.jsAscoltatori一个支持Redis、AMQP、MQTT和ZeroMQ的Node.js发布/订阅库,具有相同的API。JavaScript/Node.jsEclipse Paho HTML5 JavaScript over WebSocket用于HTML5的JavaScript MQTT库,支持WebSocket。JavaScript/Node.jsIBM-provided PhoneGap/Cordova MQTT plug-in for AndroidJavaScript API与Eclipse Paho HTML5 JavaScript相同。JavaScript/Node.jsmqtt.jsJavaScript MQTT库。JavaScript/Node.jsnode_mqtt_clientNode.js的MQTT客户端库。 LotusScript: 编程语言库/工具名称详细信息LotusScriptMQTT From LotusScript用于LotusScript的MQTT库。 Lua: 编程语言库/工具名称详细信息LuaBarracuda App Server's MQTT ClientBarracuda App Server的MQTT客户端库。LuaEclipse Paho Lua通用Lua MQTT库。Lualuamqtt纯Lua MQTT客户端。Lualibumqttlibumqtt库的Lua绑定。Lualua-mosquittolua-mosquitto库,对libmosquitto的绑定。 .NET/dotNET: 编程语言库/工具名称详细信息.NET/dotNETHiveMQtt - The Spectacular C# MQTT Client for .NET非常出色的.NET C# MQTT客户端库。.NET/dotNETKittyHawkMQ.NET平台的MQTT库。.NET/dotNETMQTTnet通用.NET MQTT库。.NET/dotNETMqttDotNet.NET平台的MQTT库。.NET/dotNETnMQTT.NET MQTT库。.NET/dotNETM2MQTT适用于.NET Micro Framework的MQTT库。.NET/dotNETPaho.MqttDotnetPaho项目的.NET C#客户端。.NET/dotNETStriderMqtt.NET平台的MQTT库。.NET/dotNETxamarin mqttXamarin移动应用程序的MQTT库。 Objective-C: 编程语言库/工具名称详细信息Objective-CmqttIO-objCObjective-C的MQTT库。Objective-Clibmosquitto (通过包装器,示例)Objective-C的MQTT库,通过包装器使用libmosquitto。Objective-CMQTTKit (示例应用程序)Objective-C的MQTT库, 附带示例应用程序。 | OCaml: 编程语言库/工具名称详细信息OCamlocaml-mqttOCaml的MQTT库。OCamlmqtt_clientOCaml的MQTT库。 Perl: 编程语言库/工具名称详细信息Perlnet-mqtt-perlPerl的MQTT库。Perlanyevent-mqtt-perlAnyEvent框架中的Perl MQTT库。PerlWebSphere-MQTT-ClientWebSphere中的Perl MQTT客户端。PerlNet::MQTT::Simple (CPAN,GitHub)Perl的MQTT库。 PHP: 编程语言库/工具名称详细信息PHPphpMQTTPHP的MQTT库。PHPMosquitto-PHPMosquitto的PHP库。PHPsskaje's MQTT libraryPHP的MQTT库。PHPSimps/MQTT用于PHP的MQTT协议分析和协程客户端,支持MQTT 3.1,3.1.1和5.0版本。 Prolog: 编程语言库/工具名称详细信息PrologMQTT Pack - Mosquitto library as a SWI-Prolog packMosquitto库的SWI-Prolog包。 Qt: 编程语言库/工具名称详细信息QtqmqttQt的MQTT客户端库。 Ruby: 编程语言库/工具名称详细信息Rubyruby-mqttRuby的MQTT库。Rubyem-mqttRuby的MQTT库。RubymosquittoMosquitto的Ruby库。 Rust: 编程语言库/工具名称详细信息Rustmqrstt - Pure rust MQTTv5 client纯Rust MQTTv5客户端。 Shell Script: 编程语言库/工具名称详细信息Shell Scriptbish-bosh支持bash、ash(包括BusyBox)、pdksh和mksh。 Smalltalk: 编程语言库/工具名称详细信息SmalltalkMQTT client for Squeak, for Squeak 5.1Squeak 5.1的Squeak MQTT客户端库。 Swift: 编程语言库/工具名称详细信息SwiftCocoaMQTT用Swift编写的iOS和OS X的MQTT客户端。SwiftMQTT NIO支持v3.1.1和v5.0的Swift NIO MQTT客户端。 Tcl: 编程语言库/工具名称详细信息Tcltcl-mqtt用于Tcl的MQTT客户端库。 这是一个更全面的列表,包括各种编程语言的MQTT库和工具。您可以根据您的项目需求选择适当的库和工具来支持MQTT通信。如果您需要更多信息或有其他问题,请随时提问。 --- ### 113. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 什么是MQTT? MQTT,全称Message Queuing Telemetry Transport,是一种专为物联网(IoT)连接设计的OASIS(结构化信息标准推进组织)标准。它是一种轻量级的消息传递协议,遵循发布/订阅范式。MQTT专门为资源受限的设备、低带宽网络、高延迟连接或不稳定网络等情景设计。其核心设计原则旨在最小化网络带宽使用和设备资源需求,同时确保可靠性和一定程度的消息传递保证。这些特点使MQTT成为连接设备和移动应用程序领域的理想选择,特别是在带宽和电池电量有限的情况下。 MQTT由谁发明? MQTT最初由IBM的Dr. Andy Stanford-Clark和Arcom(现为Eurotech)的Arlen Nipper于1999年开发。 MQTT在哪里使用? 自1999年以来,MQTT已在各种行业广泛应用。您可以在MQTT网站的“用例”页面上找到一些有趣的示例。 MQTT是一个标准吗? 是的,MQTT的版本5.0和3.1.1现在都被认定为OASIS标准。此外,版本3.1.1也已经获得ISO认证。 MQTT使用标准端口吗? 当然。MQTT使用标准端口进行通信。IANA(互联网数字分配机构)为MQTT保留了TCP/IP端口1883。此外,TCP/IP端口8883已注册,用于在SSL(安全套接层)上使用MQTT。 MQTT支持安全性吗? MQTT提供了安全功能,例如在协议版本3.1中可以通过MQTT数据包传递用户名和密码。为了在网络传输过程中保护数据,可以使用SSL(安全套接层),尽管由于其加密功能,它会增加网络开销。尽管MQTT提供了一些安全措施,但应用程序可以通过独立加密它们发送和接收的数据来增强安全性。这种方法没有直接内置到MQTT协议中,以保持其简单性和轻量级性。 我在哪里可以了解更多信息? 您可以在“规范”页面上查看MQTT规范和其他文档。如果您有问题或需要帮助,可以在StackOverflow上提问。要进行实际实施,请查看“软件”页面上列出的MQTT项目。 术语和缩写 Broker(代理):代理是负责将发布的消息路由到订阅者的服务器。 Bridge(桥接):桥接表示两个MQTT代理之间的连接。 RSMB(Really Small Message Broker):RSMB是由IBM开发的Really Small Message Broker,现在是Eclipse Mosquitto项目的一部分。 LWT(Last Will and Testament,遗嘱消息)。 M2M(Machine-to-Machine,机器对机器通信)。 M2M IWG(Machine-to-Machine Industry Working Group at Eclipse,Eclipse的机器对机器行业工作组)。 IoT(Internet of Things,物联网)。 Paho(Eclipse Paho消息项目)。 QoS(Quality of Service,服务质量级别)。 --- ### 114. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网通信协议:MQTT与其他主要协议的综合比较 随着物联网(IoT)技术的日益普及,各种通信协议应运而生,满足了不同设备和应用的特定需求。这篇文章旨在提供一个对MQTT与其他主要IoT协议的综合比较,帮助您更好地了解每种协议的特点、优点和局限性。 1. MQTT (Message Queuing Telemetry Transport) 描述: 一个基于发布/订阅模式的消息传输协议。设计为轻量级,用于低带宽、高延迟或不稳定的网络。 优点: 轻量级,适合各种设备。 提供三种消息质量(QoS)等级。 支持大型设备网络。 限制: 依赖于TCP/IP,可能不适合所有低功耗设备。需要中央broker。 2. Zigbee 描述: 基于IEEE 802.15.4标准的无线协议,主要用于家居自动化、智能能源和医疗应用。 优点: 低功耗。 强大的网状网络能力。 多供应商硬件支持。 限制: 传输距离较短。可能需要专用的硬件和网关。 3. Z-Wave 描述: 专为家庭自动化设计的低功耗无线通信协议。 优点: 高互操作性。 大量的设备支持。 成熟的生态系统。 限制: 传输距离限制。主要限制在家庭自动化。 4. CoAP (Constrained Application Protocol) 描述: 轻量级的应用层协议,用于约束设备和在低功耗网络中。 优点: 设计用于低功耗设备。 简单的传输模型。 内置的发现机制。 限制: 还不如MQTT流行。主要针对点对点或少量节点的交互。 5. Bluetooth Low Energy (BLE) 描述: 为短距离通信设计的低功耗无线技术。 优点: 低功耗。广泛应用于可穿戴设备和室内定位。 限制: 传输距离有限。 6. LoRa 描述: 一个长距离、低功耗无线通信协议。 优点: 适用于广泛的物联网应用,如农业、物流。 限制: 与其他技术相比,数据传输率较低。 7. NB-IoT 描述: 一种低功耗广域网(LPWAN)技术。 优点: 设计为低数据速率的物联网应用。 限制: 需要运营商支持和专用的网络设备。 8. Sigfox 描述: LPWAN技术,为远程和难以接入的物联网设备提供连接。 优点: 覆盖范围广、低成本。 限制: 数据传输量有限制。 9. Thread 描述: 基于IPv6的低功耗无线网状网络协议。 优点: 适用于家居自动化。高互操作性。 限制: 还在成长阶段,设备支持有限。 结论 物联网的通信需求差异很大,选择合适的协议取决于应用场景、数据传输需求、功耗限制和其他因素。因此,在确定最佳通信策略之前,建议深入研究每种协议的优势和限制。 --- ### 115. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在MQTT中进行故障排查和调试可以是一个复杂的过程,因为问题可能出现在多个地方,如客户端、broker、网络或应用逻辑中。以下是一些常见的方法和建议,帮助你有效地进行故障排查和调试: 1. 启用详细日志: 客户端日志: 大多数MQTT客户端库都支持日志记录。确保启用详细日志,并检查其中的任何错误或异常信息。 Broker日志: 启用broker的详细日志功能(如Mosquitto的log_type选项),这可以提供关于连接、订阅、发布和其他活动的详细信息。 2. 使用MQTT测试工具和客户端: 有许多工具和客户端,如MQTT.fx, MQTT Explorer或mosquitto_sub/pub,可以帮助你手动发送、接收消息并监控MQTT交流。 3. 验证连接: 确保客户端和broker的网络连接是正常的。你可以使用ping或其他网络工具来测试。 检查防火墙、路由器和其他网络设备的设置,确保MQTT的默认端口(通常是1883和8883 for TLS)是打开的。 4. 检查认证和权限: 如果broker配置了认证,请确保客户端使用正确的用户名和密码。 确保客户端有权限发布和/或订阅所需的主题。 5. 考虑使用MQTT协议分析器: 工具如Wireshark支持MQTT协议分析。这允许你查看MQTT的底层通信,可能会揭示一些不明显的问题。 6. 验证客户端和broker配置: 确保客户端和broker的配置是相容的,特别是关于QoS等级、保持连接的间隔、TLS设置等。 检查客户端的clean session设置和消息保留策略,以确保它们与你的应用逻辑相匹配。 7. 重复问题: 如果可能,尝试在一个简化或隔离的环境中重复问题。例如,使用一个简单的客户端和broker设置在本地网络上重现问题。 8. 查看资源使用: 检查客户端和broker的CPU、内存和网络使用。资源瓶颈可能导致性能问题或断开连接。 9. 检查外部依赖项: 如果MQTT系统依赖于外部服务,如数据库或其他API,确保这些服务是可用的,并且性能良好。 10. 更新和兼容性检查: 确保你使用的MQTT客户端库和broker是最新的,并且它们是相容的。有时,协议的微小变化或bug修复可能会影响行为。 结论: 故障排查和调试MQTT问题需要一个结构化和系统化的方法。通过组合日志记录、测试工具、配置检查和其他策略,你可以有效地定位和解决大多数MQTT相关问题。 --- ### 116. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在MQTT中进行网络连接的优化和管理是确保稳定、可靠和高效通信的关键。以下是一些建议和策略来优化和管理MQTT网络连接: 1. 心跳和Keep Alive机制: 心跳间隔: 当客户端连接到broker时,可以设置一个心跳间隔,通常称为“keep alive”时间。这指定了客户端和broker之间应发送消息的最大时间间隔,以确保连接仍然活动。 有效管理: 如果在指定的keep alive时间内没有任何其他消息从客户端发送到broker,客户端会发送一个PINGREQ消息,broker会回复一个PINGRESP消息。如果客户端在合理的时间内没有收到PINGRESP,它应该考虑连接已断开,并采取相应的行动。 2. 选择合适的QoS等级: 选择正确的QoS等级可以帮助优化网络资源的使用。例如,如果消息的丢失不是问题,使用QoS 0可以减少网络开销。但如果需要消息的可靠传递,QoS 1或2可能更合适。 3. 使用Last Will和Testament (LWT): LWT允许客户端指定一个“遗嘱”消息,在其非正常断开连接时由broker发送。这提供了一个机制来通知其他客户端某个设备的失效,从而允许其他系统或用户采取适当的行动。 4. 减少消息大小: 发送较小的消息可以减少网络开销和延迟。考虑使用压缩或更有效的数据格式,如Protocol Buffers或MessagePack。 5. 限制消息率: 避免发布大量的非必要消息。考虑在消息发布之间使用延迟,或使用更长的采样间隔。 6. 使用TLS/SSL进行加密: 虽然加密增加了一些开销,但它确保数据的私密性和完整性。根据应用的安全需求,选择是否使用加密。 7. 优化网络配置: 调整TCP参数: 根据具体的网络条件调整TCP的参数,如窗口大小、超时等。 负载均衡: 如果有大量的客户端连接到broker,考虑使用负载均衡器来分散流量。 8. 持久性会话管理: 通过设置clean session标志为false,客户端和broker可以保持会话状态,即使在连接断开后也是如此。这允许快速重新连接并避免重新订阅所有主题。 9. 考虑使用WebSockets: 对于需要通过防火墙或代理服务器通信的应用,使用WebSocket作为MQTT的传输层可以是一个好选择。 结论: 通过有效地管理和优化MQTT的网络连接,可以确保IoT设备和应用程序之间的通信既稳定又高效。根据具体的应用需求和网络条件,应该细心选择和调整策略。 --- ### 117. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在MQTT中使用WebSocket进行通信 MQTT是一个轻量级的发布/订阅协议,经常用于物联网(IoT)和移动应用中。尽管传统上MQTT使用TCP作为其传输协议,但它也支持WebSocket,这使得MQTT可以更容易地在Web应用程序中使用。 WebSocket简介:WebSocket是一个提供全双工通信通道的协议,可以在单个TCP连接上发送和接收数据。与传统的HTTP不同,WebSocket提供了持久连接,允许服务器和客户端之间实时交互。 1. 为什么在MQTT中使用WebSocket? Web应用程序的集成: 由于浏览器直接支持WebSocket,因此可以直接在Web应用程序中使用MQTT,无需任何插件或额外的软件。 防火墙和NAT的兼容性: 很多企业和家庭网络环境会阻止非标准端口的出站TCP连接。但因为WebSocket可以在标准的HTTP和HTTPS端口上工作,它往往更容易穿越防火墙。 与Web技术的整合: 使用WebSocket,MQTT可以更容易地与现代Web技术(如HTML5, JavaScript, CSS)结合,提供实时的Web应用体验。 2. 如何配置MQTT broker支持WebSocket? 大多数现代的MQTT broker都支持WebSocket。例如,对于Mosquitto(一个流行的开源MQTT broker),可以在配置文件中添加以下配置以启用WebSocket支持: listener 8080 protocol websockets 此配置将在端口8080上启用WebSocket监听器。 3. 如何在客户端使用WebSocket进行MQTT通信? 许多MQTT客户端库支持WebSocket作为传输协议。例如,使用JavaScript的Paho MQTT客户端库,可以如下连接到WebSocket-enabled的MQTT broker: var client = new Paho.MQTT.Client("your_broker_url", 8080, "/mqtt", "client_id"); client.connect({ onSuccess: onConnect }); 注意: "your_broker_url"是你的MQTT broker的WebSocket URL。 4. 与传统TCP连接的比较 启动时间: 由于WebSocket连接首先开始为一个HTTP连接,然后升级为WebSocket,其启动时间可能比纯TCP连接稍长。 头部开销: WebSocket帧有额外的头部开销,但对于大多数应用来说这不是问题,特别是考虑到它带来的便利性。 安全性: WebSocket支持ws(非加密)和wss(加密)两种方案,与HTTP和HTTPS类似。这为MQTT提供了与HTTPS相同级别的安全性。 5. 为什么选择WebSocket作为MQTT的传输协议? 协议升级: WebSocket的设计允许从标准的HTTP连接“升级”到持久的、全双工的连接,这使得MQTT可以利用Web的基础设施而不需要独立的设置。 浏览器支持: 几乎所有现代浏览器都支持WebSocket,这使得MQTT能够在任何支持Web的设备上运行,从桌面到手机再到嵌入式设备。 低延迟: 传统的HTTP轮询方式在实时通信中存在很大的延迟。WebSocket消除了这一点,为MQTT提供了低延迟的通信渠道。 6. MQTT over WebSocket的工作原理 当MQTT使用WebSocket作为传输时,它的工作方式与传统TCP连接略有不同: 连接建立: 客户端首先与MQTT broker建立一个标准的HTTP连接。然后,使用HTTP的“Upgrade”头请求将此连接升级为WebSocket连接。 数据帧: 一旦连接建立,MQTT消息被封装在WebSocket数据帧中进行传输。这意味着每个MQTT消息都被当作一个完整的WebSocket消息来处理。 7. 实际应用:从浏览器到IoT设备 由于WebSocket的广泛支持,MQTT over WebSocket提供了一个独特的机会,允许Web应用程序直接与IoT设备交互: 实时仪表盘: Web应用程序可以实时显示来自多个IoT设备的数据,如传感器读数或设备状态。 远程控制: 用户可以从Web界面直接控制IoT设备,如打开或关闭灯泡、调节恒温器等。 通知和警报: 当IoT设备检测到特定条件时(例如,温度过高或门被打开),它可以立即通过MQTT over WebSocket向Web应用程序发送通知。 总结,使用WebSocket作为MQTT的传输层为Web应用程序和其他环境提供了巨大的便利性和兼容性。虽然它带有轻微的性能开销,但对于大多数应用来说,这是值得的,特别是当考虑到在复杂网络环境中的易用性。 --- ### 118. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在MQTT中,重复的消息是一个关键的考虑因素,特别是当消息的QoS(质量服务)等级大于0时。下面是如何在MQTT中处理重复消息的指南: 了解原因: QoS 1: 消息至少被传递一次,但可能多次。这意味着如果发送者没有收到消息的确认,它可能会重新发送该消息,导致接收者收到重复消息。 QoS 2: 消息被准确地传递一次。但在整个四步握手过程中,如果其中一个步骤失败,消息可能会被重复发送。 使用消息ID: 每个QoS 1和QoS 2的消息都有一个相关的消息ID。接收者可以使用这个ID来检测重复的消息。如果它已经处理过具有相同消息ID的消息,那么它可以简单地丢弃重复的消息。 状态存储: 为了持续跟踪哪些消息已经被处理,应用程序可以在本地存储(例如数据库或内存中的数据结构)中保留最近接收到的消息ID。当接收到新消息时,可以检查该消息ID是否已经存在于存储中,以确定该消息是否是重复的。 确认响应: 当使用QoS 1或QoS 2时,确保您的客户端适当地响应发布确认(PUBACK)和发布收到(PUBREC)消息。这可以帮助减少因确认丢失而导致的重复消息。 限制重传次数: 在发送端,设置一个最大重试次数,以防止消息被无限期地重新发送。例如,如果尝试发送消息3次后仍未收到确认,可能需要停止重试并触发错误处理程序。 考虑应用逻辑: 在某些情况下,重复的消息可能不是问题。例如,如果消息是表示灯的开/关状态的命令,多次接收同一命令可能没有副作用。但对于其他类型的消息,如递增计数器,处理重复的消息可能更加关键。 考虑使用QoS 0: 如果您的应用场景可以容忍消息丢失,并且重复消息是一个关键问题,那么考虑使用QoS 0。这意味着消息最多传递一次,并且不需要确认。 让我们创建一个简单的MQTT客户端示例来处理重复的消息。在此示例中,我们将使用Python的paho-mqtt库。首先,确保已经安装了这个库(仅供参考): pip install paho-mqtt 以下是一个简单的MQTT客户端示例,其中包含处理重复消息的逻辑: import paho.mqtt.client as mqtt # 配置MQTT参数 BROKER_ADDRESS = "YOUR_BROKER_ADDRESS" PORT = 1883 TOPIC = "test/topic" # 已处理消息的ID列表 processed_msg_ids = set() # 当接收到连接确认响应时的回调函数 def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") client.subscribe(TOPIC, qos=2) # Subscribing with QoS 2 for demonstration # 当接收到发布消息时的回调函数 def on_message(client, userdata, msg): global processed_msg_ids if msg.mid in processed_msg_ids: print(f"Duplicate message detected: {msg.mid}") return # 处理消息逻辑 print(f"Received message: {msg.payload.decode()} with msg ID: {msg.mid}") processed_msg_ids.add(msg.mid) client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect(BROKER_ADDRESS, PORT, 60) # 进入主循环,监听消息 client.loop_forever() 注意: 此示例将接收到的每条消息的ID存储在一个全局集合processed_msg_ids中。当接收到新消息时,它首先检查消息的ID是否已经在集合中。如果是这样,那么它就识别出了一个重复的消息,并不处理它。 为了避免processed_msg_ids集合变得过大,您可能需要定期清理其中的旧ID,或者考虑使用其他数据结构或存储方法。 这只是一个简化的示例,用于说明如何在Python中使用paho-mqtt库处理重复的MQTT消息。在实际应用中,您可能还需要考虑其他因素,如持久存储、错误处理和与其他服务的集成。 --- ### 119. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当我们谈论物联网(IoT)中的通信协议时,MQTT和CoAP经常被提及。这两种协议各自为一些特定的应用场景提供了优势。在本文中,我们将深入比较这两种协议,从功能、具体差别、类型等方面进行探讨。 1. 概述 MQTT (Message Queuing Telemetry Transport) 是一个基于发布/订阅模型的轻量级通讯协议,主要用于低带宽、高延迟或不稳定的网络环境。 CoAP (Constrained Application Protocol) 是一个专为小型、受限制的设备而设计的Web传输协议,支持设备间的互操作。 2. 功能性 MQTT: 发布/订阅模型: 设备(发布者)发送消息到一个中心服务器(Broker),然后Broker将消息转发给订阅了相关主题的设备。 QoS等级: 提供三个不同的质量等级(0, 1, 2)以确保消息传递。 持久会话: 允许断开连接的客户端仍能接收其订阅的消息。 CoAP: 请求/响应模型: 类似于HTTP,支持GET, POST, PUT和DELETE方法。 观察者模式: 允许设备订阅另一个设备的资源,以在资源状态更改时收到通知。 Block-wise传输: 对于较大的消息或载荷,支持将消息分坔成小块进行传输。 3. 具体差别 协议类型: MQTT 是基于TCP的,确保消息的可靠传递。 CoAP 是基于UDP的,旨在减少数据包的数量和大小。 消息大小: MQTT 的消息头部较小,但对于非常受限制的环境,整体消息大小可能仍然较大。 CoAP 的头部设计得非常小,适合于低功率、低带宽的应用。 安全性: MQTT 使用TLS来加密其传输。 CoAP 使用DTLS来提供传输层的安全性。 4. 类型 MQTT 是一种机器到机器(M2M)的通讯协议,经常在云计算中使用,以支持远程传感器和设备与服务器之间的通信。 CoAP 是一种专为物联网(IoT)设计的协议,重点是简化的传输和互操作性。 5. 其他考虑因素 MQTT 更适合于需要持续连接的应用,例如家庭自动化系统,其中设备需要定期报告其状态。 CoAP 更适合于受限制的环境,如低功率和有损网络,以及需要快速状态更改的应用。 结论 选择MQTT还是CoAP很大程度上取决于特定的应用需求。如果您的项目需要一个轻量级、持续在线的发布/订阅系统,MQTT可能是更好的选择。另一方面,如果您正在处理受限制的设备并且需要快速、轻量级的状态更改,那么CoAP可能更为合适。在评估这些协议时,始终考虑您的项目的具体需求和约束。 --- ### 120. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在MQTT中,持久性订阅(也被称为持久会话)确保即使客户端断开连接一段时间后再重新连接,它仍然不会丢失任何消息。为了实现持久性订阅,您需要使用“持久会话”。 以下是如何在MQTT中实现持久性订阅的步骤: 设置“清除会话”标志为False: 当客户端连接到MQTT Broker时,它发送一个CONNECT控制报文。在这个报文中,有一个“清除会话”(Clean Session)标志。 如果将这个标志设置为True(或1),每次客户端断开连接,其会话信息就会被Broker清除。 为了实现持久性订阅,您应该将这个标志设置为False(或0)。这意味着,即使客户端断开连接,Broker仍然保留其会话信息。 订阅主题: 客户端可以发送SUBSCRIBE报文来订阅一个或多个主题。 断开连接: 如果客户端断开连接,由于“清除会话”标志被设置为False,所以其订阅信息和其他会话相关信息会被Broker保留。 Broker缓存QoS 1和QoS 2的消息: 当有新的消息发布到客户端订阅的主题,并且这些消息的QoS等级为1或2时,Broker会保留这些消息直到客户端再次连接并接收这些消息。 客户端重新连接: 当客户端再次连接到Broker,并使用相同的客户端标识符(Client Identifier),它会恢复其之前的会话。 Broker会开始发送在客户端离线时缓存的所有消息。 接收离线消息: 客户端会接收到所有在其离线时发布到其订阅的主题的QoS 1和QoS 2消息。 为了使持久性订阅有效,以下是一些建议: 确保客户端每次连接到Broker时使用相同的客户端标识符。 考虑消息的QoS等级。只有QoS 1和QoS 2的消息才会被Broker缓存并在客户端重新连接时发送。 注意,尽管持久性订阅确保您不会丢失消息,但存储大量离线消息可能会对Broker造成压力,所以要考虑设置消息的保留时间或限制离线消息的数量。 实现MQTT的持久性订阅涉及到客户端与MQTT Broker之间的交互,主要在于设置“清除会话”标志为false。以下是如何在不同的开发语言中实现它的例子。 Python (使用paho-mqtt库): import paho.mqtt.client as mqtt # 创建客户端实例 client = mqtt.Client(client_id="YourClientID", clean_session=False) # 连接到MQTT Broker client.connect("your_broker_address", 1883) # 订阅主题 client.subscribe("your/topic") # 启动客户端循环 client.loop_start() JavaScript (使用mqtt库 for Node.js): const mqtt = require('mqtt'); const client = mqtt.connect('mqtt://your_broker_address', { clientId: 'YourClientID', clean: false }); client.on('connect', () => { client.subscribe('your/topic'); }); client.on('message', (topic, message) => { console.log(`Received message on ${topic}: ${message.toString()}`); }); Java (使用eclipse paho库): import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; public class MqttPersistentSubscription { public static void main(String[] args) { try { MqttClient client = new MqttClient("tcp://your_broker_address:1883", "YourClientID"); MqttConnectOptions options = new MqttConnectOptions(); options.setCleanSession(false); client.connect(options); client.subscribe("your/topic"); } catch (Exception e) { e.printStackTrace(); } } } C# (使用 M2Mqtt库): using System; using uPLibrary.Networking.M2Mqtt; using uPLibrary.Networking.M2Mqtt.Messages; namespace MqttExample { class Program { static void Main() { MqttClient client = new MqttClient("your_broker_address"); byte code = client.Connect("YourClientID", null, null, false, MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE, true, "your/will/topic", "offline", true, 0); client.Subscribe(new string[] { "your/topic" }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE }); } } } 在上述示例中,请确保: 替换your_broker_address为您的MQTT Broker地址。 替换YourClientID为您想要使用的客户端ID。 替换your/topic为您要订阅的主题。 请注意,以上代码示例仅提供了基本的连接和订阅功能,您可能需要添加其他的错误处理和业务逻辑来满足具体的需求。 --- ### 121. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT(Message Queuing Telemetry Transport)是一个客户端-服务器(或发布-订阅)的消息传输协议。以下是它的基本架构和组件: Broker(服务器): MQTT Broker是中心服务器,负责接收所有发布的消息并将这些消息转发给所有订阅了相应主题的客户端。 Broker负责维护客户端的会话信息,包括哪些客户端订阅了哪些主题。 它还负责处理QoS流程和持久化功能(如保留消息和持久化会话)。 Client(客户端): 客户端可以是任何设备,从微型传感器到智能手机、服务器等,只要它们运行了MQTT客户端软件。 客户端可以“发布”消息到一个主题,也可以“订阅”一个或多个主题来接收相关的消息。 主题(Topics): 主题是一个字符串,允许消息按类别进行组织。 客户端可以发布消息到一个主题,也可以订阅一个主题来接收发布到该主题的消息。 主题的层次结构由斜线(/)来分隔。例如,“home/livingroom/temperature”可能代表家中客厅的温度传感器。 消息(Messages): 客户端发布的数据。消息可以是任何信息,如文本、二进制数据或JSON对象。 连接和会话: 当客户端想要与Broker通信时,它首先需要建立一个连接。 在连接时,客户端可以设置“清除会话”标志,决定是否在断开连接后保留会话状态。 客户端也可以设置“遗嘱消息”,这是在客户端异常断开连接时由Broker发送的一个消息。 QoS(Quality of Service): 我们前面已经讨论过,QoS定义了消息传输的质量级别,有三个等级:QoS 0、QoS 1和QoS 2。 保留消息(Retained Messages): 当消息发布到某个主题时,它可以被设置为“保留消息”。这意味着这个消息会被Broker保存,当有新的客户端订阅这个主题时,它会立即收到该保留消息。 最后遗嘱(Last Will and Testament,LWT): 客户端在连接到Broker时可以设置一个遗嘱消息。如果Broker检测到客户端异常断开连接,它会发布这个遗嘱消息到指定的主题。 总之,MQTT的架构基于发布/订阅模型,允许客户端发布消息和订阅主题,而Broker则负责管理这些消息和主题,并确保消息正确地传输到相关的订阅者。 --- ### 122. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT是一个轻量级的消息协议,特别适用于低带宽、不可靠或高延迟的网络。MQTT定义了三种消息质量(Quality of Service, QoS)等级来确保消息的传输可靠性。这三种QoS等级分别为: QoS 0 - 最多传输一次 (At most once) 描述:此等级下,消息被发送出去后,没有任何确认机制来验证消息是否已经被接收方收到。 举例:假设您有一个传感器每秒都在测量温度,并将这些读数发送到服务器。如果偶尔丢失一两个读数对您的应用来说并不重要,那么使用QoS 0是合适的。 QoS 1 - 至少传输一次 (At least once) 描述:此等级要求接收方确认已经收到消息。如果发送方没有收到确认,它会重试发送消息。因此,有可能接收方会多次收到相同的消息。 举例:假设您正在控制一个智能灯泡的开/关状态。当您发送一个"开"的命令时,您肯定希望灯泡接收到这个命令。如果使用QoS 1,灯泡收到命令后会发回确认。如果没有收到确认,您的控制器会再次尝试发送命令,直至收到确认。但灯泡可能会因为网络问题多次收到"开"命令,尽管这不会对灯泡的状态产生影响。 QoS 2 - 只传输一次 (Exactly once) 描述:此等级使用了一个复杂的四步握手过程,确保消息只被接收方收到一次,防止重复。 举例:考虑一个金融交易系统,当某人尝试从其账户中转出一定金额时,您肯定不希望因为网络问题导致交易被处理多次。在这种情况下,使用QoS 2可以确保交易指令只传输并处理一次。 在选择QoS等级时,需要权衡消息的重要性、网络的可靠性以及应用的容错性。例如,对于关键的金融操作或需要确保数据完整性的应用,可能会选择QoS 2。但对于频繁的数据流或那些可以容忍偶尔数据丢失的应用,QoS 0或1可能更为合适。 --- ### 123. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT遗嘱消息:提升物联网通信可靠性的利器 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,在物联网和传感器网络中被广泛应用。在MQTT中,遗嘱消息(Last Will and Testament)是一项强大的功能,用于在客户端异常断开连接时通知其他订阅者其离线状态或执行预定义操作。本文将详细介绍MQTT遗嘱消息的概念、用途以及如何配置和处理遗嘱消息。 遗嘱消息的概念 遗嘱消息是客户端在连接到MQTT代理时通过设置选项来定义的一条消息。当客户端异常断开连接时(如由于网络故障或客户端崩溃),MQTT代理会自动将该遗嘱消息发布给其他订阅者。遗嘱消息的目的在于提供一种机制,使其他订阅者能够得知客户端的离线状态或执行一些预定义的操作。 遗嘱消息包括以下关键属性: 主题(Topic):遗嘱消息需要指定一个主题,用于标识遗嘱消息的内容。 负载(Payload):遗嘱消息可以包含任意的负载数据,用于传递有关客户端的状态或其他信息。 QoS(Quality of Service):遗嘱消息的发布可以选择不同的QoS级别,以确保可靠的消息传递。 保留(Retained):遗嘱消息可以选择保留,这意味着新的订阅者在订阅该主题时将收到最近的遗嘱消息。 每个客户端可以根据自己的需求选择是否设置遗嘱消息,并在连接到MQTT代理时通过设置遗嘱消息选项来指定遗嘱消息的内容和属性。 遗嘱消息的用途 遗嘱消息在MQTT中具有多种用途,以下是其中一些常见的应用场景: 状态通知: 客户端可以设置一个遗嘱消息来通知其他订阅者它的在线或离线状态。当客户端正常断开连接时,代理会发布遗嘱消息,告知其他订阅者该客户端已经离线。 例如,假设在一个智能家居系统中,一个温度传感器异常断开连接,通过设置遗嘱消息,其他订阅者可以知道该传感器已离线,从而触发警报或采取其他措施。 资源释放: 某些情况下,客户端连接异常断开时可能需要释放所占用的资源或执行清理操作。通过设置遗嘱消息,客户端可以指示代理在其断开连接时执行相应的资源释放或清理操作。 举例来说,一台工业机器人在工作完成后断开连接,通过遗嘱消息,可以通知其他系统释放该机器人的工作站,以便其他任务能够顺利执行。 信息传递: 遗嘱消息可以携带有关客户端的信息,例如设备的状态、位置或其他重要数据。当客户端断开连接时,这些信息可以被传递给其他订阅者,以便及时了解客户端的状态或其他相关信息。 假设在一个物流追踪系统中,一辆运输车辆异常断开连接,遗嘱消息可以包含车辆的最后已知位置信息,以便及时通知调度中心和相关利益相关者。 设置和处理遗嘱消息 在MQTT中,设置和处理遗嘱消息涉及两个角色:发布者(客户端)和订阅者。下面分别介绍如何进行设置和处理遗嘱消息。 设置遗嘱消息 作为MQTT客户端的发布者,可以通过以下步骤设置遗嘱消息: 创建连接: 使用MQTT客户端库或工具创建与MQTT代理的连接。 设置遗嘱消息选项: 在建立连接时,设置遗嘱消息的主题、负载、QoS级别和保留选项。这些选项通常通过客户端库的API或配置文件进行设置。 连接到代理: 使用客户端库的连接功能连接到MQTT代理。 一旦客户端与代理建立连接,代理将会记录客户端的遗嘱消息设置。如果客户端在之后异常断开连接,代理将自动发布遗嘱消息给其他订阅者。 处理遗嘱消息 作为MQTT客户端的订阅者,可以通过以下步骤处理遗嘱消息: 创建连接: 使用MQTT客户端库或工 具创建与MQTT代理的连接。 订阅主题: 使用订阅功能订阅遗嘱消息的主题。通常,订阅主题与发布者设置的遗嘱消息主题相对应。 接收遗嘱消息: 一旦成功订阅主题,订阅者将接收到发布者的遗嘱消息。根据需要,可以处理遗嘱消息中的负载数据或执行相应的操作。 订阅者可以根据实际需求对接收到的遗嘱消息进行解析和处理,以满足特定的业务逻辑和应用需求。 示例应用场景 下面我们将通过示例应用场景进一步说明遗嘱消息的用途和设置方法。 场景 1: 温度传感器监测 假设在一个温度监测系统中,多个温度传感器通过MQTT连接到监控中心。为了确保监控中心能够及时获知每个传感器的状态,每个传感器可以设置遗嘱消息。当传感器异常断开连接时,监控中心会收到遗嘱消息,从而及时发现问题。 设置遗嘱消息的步骤如下: 主题:sensors/temperature/sensor1/status 负载:{"status": "offline"}(表示离线状态) QoS:1(确保消息至少被传递一次) 保留:是(以便新的订阅者在订阅时能够立即收到最近的状态) 通过这个设置,每个温度传感器都能够在断开连接时向监控中心发送离线状态的通知,帮助监控中心实时了解传感器的运行状态。 场景 2: 车辆追踪系统 在一个物流公司的车辆追踪系统中,各辆运输车辆通过MQTT连接到中央服务器。为了确保中央服务器能够知道每辆车辆的位置和状态,每辆车辆可以设置遗嘱消息。当车辆异常断开连接时,中央服务器会收到遗嘱消息,包含车辆的最后已知位置。 设置遗嘱消息的步骤如下: 主题:vehicles/truck123/status 负载:{"status": "offline", "location": "GPS coordinates"}(表示离线状态和最后已知位置) QoS:2(确保消息被精确传递,以便获取准确的位置信息) 保留:是(以便新的订阅者在订阅时能够立即收到最近的状态) 通过这个设置,中央服务器能够在车辆断开连接时获取其最后已知的位置信息,以便实时监控和调度。 总结 MQTT遗嘱消息是物联网和传感器网络中提高通信可靠性的重要工具。本文详细介绍了遗嘱消息的概念、用途以及设置和处理遗嘱消息的步骤。通过合理配置和利用遗嘱消息,可以实现实时状态通知、可靠的离线处理、资源管理和信息传递等多种应用场景,提高系统的可靠性、弹性和可管理性。 在设计和实现MQTT系统时,考虑到遗嘱消息的设置和处理,可以增加系统的实时性和可用性。同时,确保遗嘱消息的安全性、测试和验证,以及遵循MQTT协议规范,都是实施遗嘱消息功能时需要考虑的关键因素。通过合理利用MQTT遗嘱消息,您可以更好地管理物联网设备和传感器,并及时响应各种状态变化,提升系统的运行效率和可靠性。 --- ### 124. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 导言: 物联网扩展和延伸了传统互联网的边界,将用户终端从传统计算机扩展到各种设备。这些设备通过各种传感器收集信息,然后通过计算设备进行信息处理、交换和网络通信。MQTT协议的诞生正是因为移动互联网在发展初期无法提供可靠的网络连接保证。 一、MQTT协议的众多优点 1. 轻量级消息头: MQTT以其独特的特性,能够将每个消息头缩短为仅有2个字节。相较于HTTP协议,每次建立新的HTTP连接都会带来可观的开销。MQTT和MQ采用持久连接,显著减少了这种开销。 2. 高容错性: 在不稳定的网络环境中,MQTT和MQ都能够从连接断开等故障中恢复,而无需进一步的代码干预。HTTP本身无法自动实现此目标,因此客户端需要增加代码以处理连接问题。 3. 低功耗: MQTT协议专为低功耗设计。相较于HTTP,HTTP在设计时未考虑功耗问题,从而增加了设备的能耗。 4. 支持大规模并发: 在HTTP堆栈中维护数百万个并发连接需要大量工程来支持。尽管这是可行的,但大多数商业产品都经过了优化以处理大规模持久连接。IBM的MessageSight是一种单机架服务器,经过测试,可处理多达一百万个并发设备的MQTT连接。而MQ协议并不是设计用于大规模并发的。 5. 推送通知: 在一些应用场景中,您需要及时向客户发送通知。推送通知是最佳解决方案,无论从电池寿命、系统负载还是带宽方面都表现出色。 6. 跨平台兼容性: HTTP和MQTT客户端已经实现在许多平台上,MQTT的简单性有助于在其他客户端上以最小的努力实现MQTT。 7. 防火墙友好: 一些公司的防火墙限制出站连接至预定义端口,通常仅限于HTTP(端口80)和HTTPS(端口443)等。MQTT通过WebSockets连接封装并显示为HTTP升级请求,因此可以在这些情况下运行。 二、MQTT协议的不足之处 MQTT在现实世界中得到了广泛应用,可以在诸如Facebook、BP、阿里巴巴、百度等大型硬件和互联网公司中找到。然而,MQTT协议也有一些改进的空间,特别是在大规模商业化应用中: 1. 缺乏全面的SDK支持: 要实现与MQTT服务器的通信,需要适用于不同异构设备(如MCU、Linux、Android、iOS、Web)的软件SDK包,以实现互连和互操作性。 2. 不支持文件和AV传输: 在某些应用场景中,传输的信息可能不仅限于指令,还包括语音和视频信号等。 3. 缺乏与第三方HTTP集成的支持: MQTT协议虽然优于常规HTTP协议,但基于传统HTTP协议的WEB服务器仍占据主导地位。这些服务器应与MQTT协议互连,以降低升级成本。 4. 缺乏负载均衡支持: 负载均衡服务器对于高并发性和抵御恶意攻击至关重要。 5. 缺乏用户管理界面: 对于用户分析设备行为数据而言,具备用户管理界面尤其重要。在工业4.0和大数据时代,这是不可避免的需求。 6. 对脱机消息的不足支持: 当设备脱机时,MQTT协议目前不提供补偿措施来弥补从MQTT服务器到设备的控制信息丢失。 7. 不支持点对点通信:MQTT协议虽然理论上可以通过相互订阅来实现点对点通信,但涉及到设备安全性等问题,逻辑相对复杂。此外,当多个设备同时存在于同一主题时,设备无法区分消息是来自哪个具体设备,也容易受到窃听。 8. 不支持群组通信或群组管理: 对于需要多人控制一个设备或一个人控制多个设备的应用场景,MQTT协议目前不支持群组通信或群组管理。 在不断改进和演化中,MQTT协议将继续在物联网通信领域发挥关键作用,连接着智能制造和智能能源等未来领域的发展。然而,随着物联网的不断成熟,MQTT协议也需要不断满足更广泛的需求和挑战。 --- ### 125. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 MQTT(Message Queuing Telemetry Transport)是一种轻量级、灵活的物联网消息交换和数据传递协议,旨在实现 IoT 开发人员在灵活性和硬件/网络资源之间的平衡。而 ESP8266 是一款高度集成的 Wi-Fi SoC 解决方案,具有低功耗、紧凑设计和高稳定性,可满足各种 IoT 应用需求。ESP8266具备完整的自包含Wi-Fi网络功能,可独立应用,也可作为从机运行于其他主机 MCU 上。 本项目旨在展示如何将 ESP8266 连接到MQTT物联网平台,并使用 Arduino IDE 进行编程。 2. 所需硬件与软件 ESP8266 Arduino IDE MQTT物联网平台 Broker: iot.mqtt.cn TCP Port: 1883 Websocket Port: 8083 3. 准备工作 在开始之前,请确保您已安装 Arduino IDE,并已连接 ESP8266 开发板。 4. 编写 ESP8266 代码 首先,我们将导入 ESP8266WiFi 和 PubSubClient 库。ESP8266WiFi 库用于将 ESP8266 连接到 Wi-Fi 网络,而 PubSubClient 库用于使 ESP8266 连接到 MQTT 服务器以发布消息和订阅主题。 #include <ESP8266WiFi.h> #include <PubSubClient.h> 接下来,设置 Wi-Fi 的名称和密码,以及 MQTT 服务器的连接地址和端口。 // WiFi const char *ssid = "您的WiFi名称"; // 输入您的 WiFi 名称 const char *password = "您的WiFi密码"; // 输入您的 WiFi 密码 // MQTT Broker const char *mqtt_broker = "iot.mqtt.cn"; const char *topic = "esp8266/test"; const char *mqtt_username = "emqx"; const char *mqtt_password = "public"; const int mqtt_port = 1883; 打开串行连接,以便输出程序的结果,并连接到 Wi-Fi 网络。 // 设置串行连接波特率为 115200 Serial.begin(115200); // 连接到 Wi-Fi 网络 WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.println("正在连接到WiFi..."); } Serial.println("已连接到WiFi网络"); 接下来,设置 MQTT 服务器,并编写回调函数。同时,将连接信息打印到串口监视器上。 client.setServer(mqtt_broker, mqtt_port); client.setCallback(callback); while (!client.connected()) { String client_id = "esp8266-client-"; client_id += String(WiFi.macAddress()); Serial.printf("客户端 %s 连接到公共 MQTT 代理\n", client_id.c_str()); if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) { Serial.println("已连接到公共 EMQX MQTT 代理"); } else { Serial.print("连接失败,状态:"); Serial.print(client.state()); delay(2000); } } 一旦 MQTT 服务器连接成功,ESP8266 将向 MQTT 服务器发布消息并订阅主题。 // 发布和订阅 client.publish(topic, "Hello MQTT"); client.subscribe(topic); 最后,将主题名称打印到串行端口,然后打印收到的每个字节的消息。 void callback(char *topic, byte *payload, unsigned int length) { Serial.print("收到主题消息:"); Serial.println(topic); Serial.print("消息内容:"); for (int i = 0; i < length; i++) { Serial.print((char) payload[i]); } Serial.println(); Serial.println("-----------------------"); } 5. 完整的 ESP8266 代码 #include <ESP8266WiFi.h> #include <PubSubClient.h> // WiFi const char *ssid = "您的WiFi名称"; // 输入您的 WiFi 名称 const char *password = "您的WiFi密码"; // 输入您的 WiFi 密码 // MQTT Broker const char *mqtt_broker = "iot.mqtt.cn"; const char *topic = "esp8266/test"; const char *mqtt_username = "emqx"; const char *mqtt_password = "public"; const int mqtt_port = 1883; WiFiClient espClient; PubSubClient client(espClient); void setup() { // 设置串行连接波特率为 115200 Serial.begin(115200); // 连接到 WiFi 网络 WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.println("正在连接到WiFi..."); } Serial.println("已连接到WiFi网络"); // 连接到 MQTT 代理 client.setServer(mqtt_broker, mqtt_port); client.setCallback(callback); while (!client.connected()) { String client_id = "esp8266-client-"; client_id += String(WiFi.macAddress()); Serial.printf("客户端 %s 连接到公共 MQTT 代理\n", client_id.c_str()); if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) { Serial.println("已连接到公共 EMQX MQTT 代理"); } else { Serial.print("连接失败,状态:"); Serial.print(client.state()); delay(2000); } } // 发布和订阅 client.publish(topic, "Hello EMQX"); client.subscribe(topic); } void callback(char *topic, byte *payload, unsigned int length) { Serial.print("收到主题消息:"); Serial.println(topic); Serial.print("消息内容:"); for (int i = 0; i < length; i++) { Serial.print((char) payload[i]); } Serial.println(); Serial.println("-----------------------"); } void loop() { client.loop(); } 6. 运行与测试 使用 Arduino IDE 将完整的代码上传到 ESP8266,并打开串口监视器。在串口监视器中,您将看到 ESP8266 连接到 Wi-Fi 和 MQTT 服务器的状态信息。 接下来,使用 MQTTX 客户端与 MQTT物联网平台建立连接,并向 ESP8266 发送消息。您可以在串口监视器中查看 ESP8266 收到的消息。 --- ### 126. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当谈论 MQTT(Message Queuing Telemetry Transport)协议时,了解一些与其相关的术语非常重要。这些术语有助于理解 MQTT 协议的工作原理以及如何有效地使用它。下面是一个关于 MQTT 术语的文章,它将帮助您更深入地理解 MQTT 协议: MQTT 术语表:深入了解 MQTT 协议 MQTT(Message Queuing Telemetry Transport)是一种轻量级的、发布/订阅式的通信协议,广泛应用于物联网设备、传感器网络和分布式系统中。在使用 MQTT 协议时,您可能会遇到一些特定的术语,下面是一些重要的 MQTT 术语以及它们的解释: A - Broker(经纪人) 在 MQTT 中,经纪人(Broker)是指 MQTT 服务器,负责接收发布者(Publishers)发送的消息并将其传递给订阅者(Subscribers)。有时候也直接称之为 Broker。 C - Clean Start(清理启动) 客户端可以在连接时使用 Clean Start 字段来指示是否期望从已存在的会话中恢复通信,还是创建一个全新的会话。这个功能仅适用于 MQTT v5.0。 Client(客户端) 客户端是使用 MQTT 协议连接到 MQTT 经纪人的设备或应用程序。它可以是发布者或订阅者,通过 MQTT 协议完成发布和订阅操作。 Client ID(客户端标识) Client ID 用于唯一标识 MQTT 客户端的连接和会话。MQTT 允许客户端自行指定 Client ID,也支持由 MQTT 服务器统一为客户端分配 Client ID。 Connection(连接) MQTT 客户端与 MQTT 服务器之间的网络连接。请注意,MQTT 客户端之间不会直接建立连接,而是通过 MQTT 服务器中转消息。 Content Type(内容类型) Content Type 字段用于描述消息的内容类型,以便接收方能够更好地处理它。它可以使用 MIME 类型,例如 "text/plain",也可以使用自定义的字符串来描述消息内容。这个字段仅适用于 MQTT v5.0。 E - Enhanced Authentication(增强认证) MQTT v5.0 引入了 AUTH 报文,支持增强认证。它扩展了原有的用户名和密码认证以及令牌认证机制,允许使用更安全的认证机制,如 SCRAM 认证,以增强安全性,抵御中间人攻击。 F - Flow Control(流控制) MQTT v5.0 引入了流控制机制,允许客户端和服务器协商最大消息发送速率,以避免网络拥塞和接收方过载的问题。 K - Keep Alive(保持连接) Keep Alive 表示客户端在传输一个 MQTT 控制报文到发送下一个报文之间允许的最大空闲时间间隔。如果没有其他控制报文可以发送,客户端必须发送一个 PINGREQ 报文,以保持连接。如果服务器在1.5倍的 Keep Alive 时间内没有收到客户端的控制报文,它将断开连接。 M - Message(消息) 通常指的是 PUBLISH 报文,即 MQTT 协议中的消息。 Message Expiry Interval(消息过期时间) MQTT v5.0 允许客户端为消息设置过期时间,以确保在服务端中停留较长时间的消息不会被转发给订阅者。 MQTT over QUIC(MQTT 在 QUIC 上运行) MQTT over … 指的是 MQTT 运行在何种传输协议之上。MQTT 协议只要求底层传输提供有序、可靠的双向字节流,但并不强制要求使用特定的传输协议。MQTT over QUIC 是一种扩展,利用 QUIC 协议提供更高效的连接管理和传输。 MQTT v3.1.1(MQTT 3.1.1 版本) OASIS 技术委员会于 2014 年发布的 MQTT 规范,它是 MQTT 协议的一个重要版本。 MQTT v5.0(MQTT 5.0 版本) OASIS 技术委员会于 2019 年发布的 MQTT 规范,是当前最新版本的 MQTT 规范。MQTT v5.0 引入了许多新特性,并向后兼容 v3.1.1。 P - Packet(报文) 通常指 MQTT 协议中的控制报文,用于交换信息。例如 CONNECT 报文用于连接,PUBLISH 报文用于发布消息,SUBSCRIBE 报文用于订阅等。 Packet Identifier(报文标识符) 报文标识符用于唯一标识 QoS 大于 0 的消息或订阅/取消订阅请求,通常由客户端和服务器内部管理。 Payload(有效载荷) MQTT 报文中的有效载荷部分,根据报文类型不同,有效载荷的内容会有所不同。对于 PUBLISH 报文来说,有效载荷即消息的实际内容。 Payload Format Indicator(有效载荷格式指示符) 有效载荷格式指示符用于指示消息内容(包括遗嘱消息)是否是 UTF-8 编码的字符串,仅适用于 MQTT v5.0。 PINGREQ & PINGRESP PINGREQ 报文由客户端发送,用于告知服务器客户端仍然活动。服务器必须及时响应 PINGREQ 报文,以保持连接。 # Property(属性) MQTT 为大多数控制报文定义了一组可选属性,不同类型的控制报文可以具有不同的可选属性。这些属性提供了更多的控制和扩展性。 Publish/Subscribe(发布/订阅) MQTT 的核心机制之一,发布订阅机制解耦了消息的发送方和接收方,允许消息的广播、组播和单播。 Q - QoS(服务质量等级) MQTT 定义了三种 QoS 等级,用于提供不同级别的消息可靠性保证。每条消息都可以在发布时设置自己的 QoS 等级: QoS 0:最多交付一次,消息可能会丢失。 QoS 1:至少交付一次,消息可以保证到达,但可能会重复到达。 QoS 2:只交付一次,消息保证到达,并且不会重复。 R - Reason Code(原因码) MQTT 使用 Reason Code 字段来指示操作结果,MQTT v5.0 扩展了 Reason Code 以提供更准确的结果反馈。 Reason String(原因字符串) Reason String 字段用于在 Reason Code 的基础上进一步解释操作结果,提供更易读的信息,仅适用于 MQTT v5.0。 Receive Maximum(最大接收数量) 用于声明服务端和客户端愿意同时处理的 QoS 1 和 QoS 2 消息的最大数量,以避免过多消息导致负载问题。仅适用于 MQTT v5.0。 Request & Response(请求和响应) MQTT 的发布订阅机制确保消息到达 MQTT 服务器,但要确保消息被正确传递给订阅者,需要使用请求和响应机制。 MQTT v5.0 改进了请求和响应的支持,允许请求方直接指定响应主题,减少了约定的复杂性。 Retained Message(保留消息) 保留消息在 MQTT 服务器中保留,除了被正常转发给订阅者外,还会在新订阅时发送给订阅者。每个主题只能有一条最新的保留消息。 S - Security(安全性) MQTT 支持多种安全机制,包括 TLS 加密传输、身份验证和访问控制,以确保通信的保密性和完整性,以及授权合法用户访问特定主题。 Server(服务器) 在 MQTT 中,服务器是指 MQTT 经纪人,它负责接收发布者发送的消息并将其传递给订阅者。服务端也会处理客户端的连接请求和订阅/取消订阅请求。 Server Disconnect(服务器断开连接) MQTT v5.0 允许服务器发送 DISCONNECT 报文,以指示客户端连接被关闭的具体原因。 Server Reference(服务器引用) MQTT v5.0 允许服务器通过 CONNACK 或 DISCONNECT 报文中的服务端参考属性,指示客户端临时或永久切换至另一台服务器。 Session(会话) MQTT 的会话机制用于管理客户端和服务器之间的有状态交互,存储 QoS 1、2 消息的传输状态和订阅信息。它可以持续与网络连接一样长的时间,也可以跨越多个网络连接存在。 Session Expiry Interval(会话过期时间) 会话过期时间表示客户端连接断开后会话在服务端中保留的时间。这个功能仅适用于 MQTT v5.0。 Session Present(会话存在标志) 服务端通过 Session Present 字段告知客户端本次连接是之前会话的延续还是一个全新的会话,以便客户端适当地调整自己的行为。 Shared Subscription(共享订阅) MQTT v5.0 允许将客户端划分为多个订阅组,消息仍然会被传递给所有订阅组,但一个订阅组内的客户端将以轮询或其他策略交替接收消息,实现了消息的负载均衡。 Subscription Identifier(订阅标识符) 客户端可以在订阅时指定订阅标识符,服务端在转发与这些订阅匹配的消息时需要附上与之关联的订阅标识符。 Subscription Options(订阅选项) MQTT 允许客户端为每个订阅使用不同的订阅选项,例如是否接收保留消息、最大 QoS 等。 T - Topic(主题) 主题用于标识和区分不同的消息,它是 MQTT 消息路由的基础。发布者指定消息的主题,订阅者选择订阅感兴趣的主题来接收相关的消息。 Topic Alias(主题别名) MQTT v5.0 允许发送端将主题名映射成一个双字节整数表示的别名,从而减少带宽消耗,提高效率。 Topic Filter(主题过 滤器) 主题过滤器在订阅时使用,可以包含单层通配符(+)和多层通配符(#)来同时订阅多个主题。 Topic Name(主题名) 主题名在发布消息时使用,不允许包含通配符。 U - Username & Password(用户名和密码) MQTT 允许客户端在连接报文中提供可选的用户名和密码,以实现对密码认证和令牌认证的支持。 User Property(用户属性) MQTT v5.0 允许客户端和服务端将自定义的键值对作为用户属性添加到控制报文中,以提供更好的可扩展性和元数据。 W - Will Delay Interval(遗嘱消息延迟时间) 遗嘱消息延迟时间指示遗嘱消息可以在连接断开后延迟多久发送,这个功能仅适用于 MQTT v5.0。 Will Message(遗嘱消息) 如果客户端异常断开连接,那么客户端在连接时设置的遗嘱消息将由服务器转发给其他客户端。遗嘱消息与普通消息具有相同的字段,包括主题、QoS、Payload 等。 $ - $ Topic(以 $ 开头的主题) 以 $ 开头的主题必须由服务器决定其使用方式和场景,客户端不能自行使用这类主题。例如,$share 开头的主题用于共享订阅,$SYS 开头的主题通常用于发布系统消息。 以上是一些关于 MQTT 协议的重要术语及其解释,它们有助于您更深入地理解 MQTT 协议的工作原理和如何在实际应用中使用 MQTT 进行可靠的消息通信。无论您是物联网开发者还是系统架构师,了解这些术语都将对您的工作大有裨益。如果您需要更多有关 MQTT 或物联网的信息,请随时提问。 --- ### 127. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 报警面板平台允许您控制支持MQTT的报警面板。报警面板图标将在从state_topic接收到新状态后更改状态。如果使用RETAIN标志发布这些消息,MQTT报警面板将在订阅后立即接收到状态更新,并将以正确的状态启动。否则,初始状态将是未知的。 该组件将接受来自您的报警面板的以下状态(小写): 'disarmed'(解除布防) 'armed_home'(在家布防) 'armed_away'(外出布防) 'pending'(待定) 'triggered'(触发) 该组件可以通过发布到command_topic与Home Assistant前端交互的用户改变报警面板的状态。 要启用此平台,请将以下内容添加到您的configuration.yaml文件中: # 示例 configuration.yaml 条目 alarm_control_panel: - platform: mqtt state_topic: "home/alarm" command_topic: "home/alarm/set" 配置变量: state_topic (必填): 用于接收状态更新的MQTT主题。 command_topic (必填): 用于发布改变报警状态命令的MQTT主题。 name (可选): 报警面板的名称。默认为'MQTT报警'。 qos (可选): 状态主题的最大QoS级别。默认为0。这个QoS也将用于发布消息。 payload_disarm (可选): 解除布防的负载。默认为“DISARM”。 payload_arm_home (可选): 设置在家布防模式的负载。默认为“ARM_HOME”。 payload_arm_away (可选): 设置外出布防模式的负载。默认为“ARM_AWAY”。 code (可选): 如果定义,指定在前端启用或禁用报警的代码。 --- ### 128. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant允许您通过MQTT集成传送的图像文件内容到Home Assistant作为摄像头。每当在配置中的主题下接收到消息时,Home Assistant中显示的图像也将被更新。 这可以与能够通过MQTT发送图像的应用程序或服务一起使用,例如Zanzito。 要在您的安装中启用此摄像头,请将以下内容添加到您的configuration.yaml文件中: # 示例 configuration.yaml 条目 camera: - platform: mqtt # 使用MQTT作为摄像头的平台 topic: zanzito/shared_locations/my-device # 要订阅的MQTT主题 配置变量: topic (必填): 要订阅的MQTT主题。 name (可选): 摄像头的名称。 --- ### 129. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant使用 MQTT 消息负载来设置二进制传感器为两种状态之一:打开或关闭。 只有在匹配的 MQTT 主题上发布新消息后,二进制传感器状态才会更新。如果这些消息以保留标志进行发布,二进制传感器将在订阅后立即接收到状态更新,并且在启动时,Home Assistant 将显示正确的状态。否则,在 Home Assistant 中显示的初始状态将是未知的。 Home Assistant可选择支持从 MQTT 设备接收在线和离线消息(出生和 LWT 消息)。在正常操作期间,如果 MQTT 设备离线(即发布到失去连接的主题),Home Assistant 将显示二进制传感器为不可用。如果这些消息以保留标志进行发布,二进制传感器将在订阅后立即接收到更新,并且 Home Assistant 在启动时将显示正确的可用性状态。如果未设置标志,Home Assistant 在启动时将显示二进制传感器为不可用。如果未定义 availability_topic,则 Home Assistant 将认为 MQTT 设备可用。 要在您的安装中使用 MQTT 二进制传感器,请将以下内容添加到您的配置文件 configuration.yaml 中: # 示例 configuration.yaml 条目 binary_sensor: - platform: mqtt state_topic: "home-assistant/window/contact" 配置变量: name(可选):二进制传感器的名称。默认为“MQTT 二进制传感器”。 state_topic(必填):订阅以接收传感器值的 MQTT 主题。 payload_on(可选):表示打开状态的负载。默认为“ON”。 payload_off(可选):表示关闭状态的负载。默认为“OFF”。 availability_topic(可选):订阅以接收 MQTT 设备的出生和 LWT 消息。如果未定义,二进制传感器的可用性状态将始终为“可用”。如果定义了该主题,则二进制传感器的可用性状态将默认为“不可用”。 payload_available(可选):表示在线状态的负载。默认为“online”。 payload_not_available(可选):表示离线状态的负载。默认为“offline”。 qos(可选):接收消息时要使用的最大 QoS 级别。默认为 0。 device_class(可选):用于设置前端图标的传感器类型/类别。 value_template(可选):定义从负载中提取值的模板。 要进行测试,您可以使用随附的命令行工具或包来发送 MQTT 消息。要手动设置二进制传感器的状态: $ mosquitto_pub -h 127.0.0.1 -t home-assistant/window/contact -m "OFF" 下面的示例显示了一个二进制传感器的完整配置: # 示例 configuration.yaml 条目 binary_sensor: - platform: mqtt # 使用MQTT name: "窗户传感器" # 二进制传感器的名称 state_topic: "home-assistant/window/contact" # 订阅以接收传感器值的MQTT主题 payload_on: "ON" # 表示打开状态的负载 payload_off: "OFF" # 表示关闭状态的负载 availability_topic: "home-assistant/window/availability" # 订阅以接收MQTT设备的出生和LWT消息的主题 payload_available: "online" # 表示在线状态的负载 payload_not_available: "offline" # 表示离线状态的负载 qos: 0 # 接收消息时要使用的最大QoS级别 device_class: opening # 用于设置前端图标的传感器类型/类别 value_template: '{{ value.x }}' # 定义从负载中提取值的模板 请注意,以上示例中的配置仅供参考,您需要根据您的 MQTT 设备和主题进行相应的配置。 --- ### 130. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant允许您控制 MQTT 窗帘/卷帘(如百叶窗、卷帘或车库门)。 在理想情况下,MQTT 设备将有一个状态主题,用于发布状态更改。如果这些消息以设置标志进行发布,遮盖将在订阅后立即接收到状态更新,并且在 Home Assistant 启动时会显示正确的状态。否则,在 Home Assistant 中显示的初始状态将是未知(unknown)。 窗帘/卷帘的相对位置存储在一个属性中,其中 0 表示设备关闭,所有其他中间位置表示设备处于打开状态。 如果没有定义状态主题,遮阳将在即时更新模式下工作。在此模式下,窗帘/卷帘将在 Home Assistant 发送的每个命令后立即更改状态(打开或关闭)。如果定义了状态主题,窗帘/卷帘将等待匹配或者之前的消息,然后在 Home Assistant 中更改状态。 即使定义了状态主题,也可以强制使用即时更新模式。如果您遇到窗帘/卷帘操作不正确的情况,请尝试启用它。 还可选择支持 MQTT 窗帘/卷帘设备的在线和离线消息(birth 和 LWT 消息)。在正常操作期间,如果 MQTT 窗帘/卷帘设备脱机(即发布到某个主题),Home Assistant 将显示窗帘/卷帘为“不可用”。如果使用设置标志发布这些消息,窗帘/卷帘将在订阅后立即更新,并且 Home Assistant 启动时将显示窗帘/卷帘的正确可用性状态。如果不设置标志,Home Assistant 启动时将显示窗帘/卷帘为“不可用”。 要在您的安装中使用 MQTT 窗帘/卷帘,请将以下内容添加到您的 configuration.yaml 文件中: # 示例 configuration.yaml 条目 cover: - platform: mqtt name: "MQTT 窗帘" command_topic: "home-assistant/cover/set" 配置变量: name(可选):窗帘的名称。默认为 "MQTT 窗帘"。 command_topic(可选):用于发布命令以控制窗帘/卷帘状态的 MQTT 主题。 payload_open(可选):打开窗帘/卷帘的有效载荷。默认为 "OPEN"。 payload_close(可选):关闭窗帘/卷帘的有效载荷。默认为 "CLOSE"。 payload_stop(可选):停止窗帘/卷帘的有效载荷。默认为 "STOP"。 state_topic(可选):订阅以接收窗帘/卷帘状态消息的 MQTT 主题。 state_open(可选):表示打开状态的有效载荷。默认为 "open"。 state_closed(可选):表示关闭状态的有效载荷。默认为 "closed"。 availability_topic(可选):订阅以接收来自 MQTT 窗帘/卷帘设备的出生和 LWT 消息的 MQTT 主题。如果未定义,窗帘/卷帘的可用性状态将始终为 "available"。如果已定义,窗帘/卷帘的可用性状态将默认为 "unavailable"。 payload_available(可选):表示在线状态的有效载荷。默认为 "online"。 payload_not_available(可选):表示离线状态的有效载荷。默认为 "offline"。 optimistic(可选):定义窗帘/卷帘是否以即时更新模式工作的标志。默认情况下,如果未定义状态主题,则为 true;否则为 false。 qos(可选):在接收和发布消息时使用的最大 QoS 级别。默认为 0。 retain(可选):定义发布的消息是否应设置保留标志。默认为 false。 value_template(可选):定义从有效载荷中提取值的模板。 set_position_topic(可选):发布位置命令的 MQTT 主题。 set_position_template(可选):定义要发送到主题的位置的模板。传入的位置值可以在模板中使用 {{ value }}。如果未定义模板,则将数字位置(0-100)直接写入主题。 tilt_command_topic(可选):发布命令以控制窗帘/卷帘倾斜的 MQTT 主题。 tilt_status_topic(可选):订阅以接收倾斜状态更新值的 MQTT 主题。 tilt_min(可选):最小倾斜值。默认 为 0。 tilt_max(可选):最大倾斜值。默认为 100。 tilt_closed_value(可选):在命令上发送的值。默认为 0。 tilt_opened_value(可选):在命令上发送的值。默认为 100。 tilt_status_optimistic(可选):确定倾斜是否以即时更新模式工作的标志。默认情况下,如果未定义,则为 false;否则为 true。 tilt_invert_state(可选):确定打开/关闭是否被翻转;较高的值表示关闭,较低的值表示打开。默认为 False。 示例: # 完整配置示例(无倾斜) cover: - platform: mqtt name: "MQTT 窗帘/卷帘" # 设备的名称 command_topic: "home-assistant/cover/set" # 用于发布窗帘/卷帘命令的 MQTT 主题 state_topic: "home-assistant/cover/state" # 订阅以接收窗帘/卷帘状态消息的 MQTT 主题 availability_topic: "home-assistant/cover/availability" # 订阅来自 MQTT 窗帘/卷帘设备的出生和 LWT 消息的 MQTT 主题 qos: 0 # 接收和发布消息时使用的最大 QoS 级别 retain: true # 定义发布的消息是否应设置保留标志 payload_open: "OPEN" # 打开窗帘/卷帘的有效载荷 payload_close: "CLOSE" # 关闭窗帘/卷帘的有效载荷 payload_stop: "STOP" # 停止窗帘/卷帘的有效载荷 state_open: "open" # 表示打开状态的有效载荷 state_closed: "closed" # 表示关闭状态的有效载荷 payload_available: "online" # 表示在线状态的有效载荷 payload_not_available: "offline" # 表示离线状态的有效载荷 optimistic: false # 定义窗帘/卷帘是否以即时更新模式工作的标志 value_template: '{{ value.x }}' # 从有效载荷中提取值的模板 # 完整配置示例 cover: - platform: mqtt name: "MQTT 窗帘" # 设备的名称 command_topic: "home-assistant/cover/set" # 用于发布窗帘/卷帘命令的 MQTT 主题 state_topic: "home-assistant/cover/state" # 订阅以接收窗帘/卷帘状态消息的 MQTT 主题 availability_topic: "home-assistant/cover/availability" # 订阅来自 MQTT 窗帘/卷帘设备的出生和 LWT 消息的 MQTT 主题 qos: 0 # 接收和发布消息时使用的最大 QoS 级别 retain: true # 定义发布的消息是否应设置保留标志 payload_open: "OPEN" # 打开窗帘/卷帘的有效载荷 payload_close: "CLOSE" # 关闭窗帘/卷帘的有效载荷 payload_stop: "STOP" # 停止窗帘/卷帘的有效载荷 state_open: "open" # 表示打开状态的有效载荷 state_closed: "closed" # 表示关闭状态的有效载荷 payload_available: "online" # 表示在线状态的有效载荷 payload_not_available: "offline" # 表示离线状态的有效载荷 optimistic: false # 定义窗帘/卷帘是否以即时更新模式工作的标志 value_template: '{{ value.x }}' # 从有效载荷中提取值的模板 tilt_command_topic: 'home-assistant/cover/tilt' # 用于发布窗帘/卷帘倾斜命令的 MQTT 主题 tilt_status_topic: 'home-assistant/cover/tilt-state' # 订阅以接收窗帘/卷帘倾斜状态消息的 MQTT 主题 tilt_min: 0 # 最小倾斜值 tilt_max: 180 # 最大倾斜值 tilt_closed_value: 70 # 关闭状态的倾斜值 tilt_opened_value: 180 # 打开状态的倾斜值 为了进行测试,您可以使用附带的命令行工具或包发送 MQTT 消息,这将允许您手动操作您的窗帘/卷帘: $ mosquitto_pub -h 127.0.0.1 -t home-assistant/cover/set -m "CLOSE" 这条命令用于关闭窗帘/卷帘。 --- ### 131. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant允许您控制支持MQTT的风扇。 在理想情况下,MQTT设备将具有用于发布状态更改的状态主题。如果这些消息以RETAIN标志发布,MQTT风扇将在订阅后立即接收到状态更新,并将以正确的状态启动。否则,风扇的初始状态将为假/关闭。 当状态主题不可用时,风扇将以即时更新模式工作。在这种模式下,风扇将在每次命令后立即更改状态。否则,风扇将等待来自设备的状态确认(来自消息主题)。 即使状态主题可用,也可以强制启用即时更新模式。如果您遇到风扇操作不正确的情况,请尝试启用它。 要在您的安装中启用MQTT风扇,请在您的配置文件(configuration.yaml)中添加以下内容: # 示例配置.yml 条目 fan: - platform: mqtt command_topic: "bedroom_fan/on/set" 配置变量: command_topic(必填):用于发布更改风扇状态的命令的MQTT主题。 name(可选):风扇的名称,默认为“MQTT风扇”。 state_topic(可选):用于接收状态更新的MQTT主题。 payload_on(可选):表示运行状态的有效载荷,默认为“ON”。 payload_off(可选):表示停止状态的有效载荷,默认为“OFF”。 qos(可选):状态主题的最大QoS级别,默认为0,并将用于发布消息。 optimistic(可选):定义风扇是否以即时更新模式工作的标志。如果未定义状态主题,则默认为true,否则为false。 retain(可选):发布的消息是否应具有保留标志。 oscillation_state_topic(可选):用于接收摆动状态更新的MQTT主题。 oscillation_command_topic(可选):用于发布更改摆动状态的命令的MQTT主题。 payload_oscillation_on(可选):表示摆动打开状态的有效载荷,默认为“oscillate_on”。 payload_oscillation_off(可选):表示摆动关闭状态的有效载荷,默认为“oscillate_off”。 speed_state_topic(可选):用于接收速度状态更新的MQTT主题。 speed_command_topic(可选):用于发布更改速度状态的命令的MQTT主题。 payload_low_speed(可选):表示风扇低速状态的有效载荷。 payload_medium_speed(可选):表示风扇中速状态的有效载荷。 payload_high_speed(可选):表示风扇高速状态的有效载荷。 speeds(可选):速度选项的数组,有效值为“off”,“low”,“medium”,“high” "off" - "关闭""low" - "低速""medium" - "中速""high" - "高速" 请确保您的主题与配置的精确匹配。"some-topic/some-topic"是不同的主题。 在这里,您可以找到有关如何使用MQTT风扇的一些实际示例。以下是一个完整的MQTT风扇的配置示例: # 示例配置.yml 条目 # 定义一个MQTT风扇,用于卧室 fan: - platform: mqtt # 使用MQTT name: "卧室风扇" # 风扇的名称 state_topic: "bedroom_fan/on/state" # 用于接收风扇状态的MQTT主题 command_topic: "bedroom_fan/on/set" # 用于发布控制风扇状态的MQTT主题 oscillation_state_topic: "bedroom_fan/oscillation/state" # 用于接收摆动状态的MQTT主题 oscillation_command_topic: "bedroom_fan/oscillation/set" # 用于发布控制摆动状态的MQTT主题 speed_state_topic: "bedroom_fan/speed/state" # 用于接收风扇速度状态的MQTT主题 speed_command_topic: "bedroom_fan/speed/set" # 用于发布控制风扇速度的MQTT主题 qos: 0 # 状态主题的最大QoS级别 payload_on: "true" # 表示风扇运行状态的有效载荷 payload_off: "false" # 表示风扇停止状态的有效载荷 payload_oscillation_on: "true" # 表示摆动打开状态的有效载荷 payload_oscillation_off: "false" # 表示摆动关闭状态的有效载荷 payload_low_speed: "low" # 表示风扇低速状态的有效载荷 payload_medium_speed: "medium" # 表示风扇中速状态的有效载荷 payload_high_speed: "high" # 表示风扇高速状态的有效载荷 speeds: # 风扇可用的速度选项 - low - medium - high --- ### 132. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant允许您控制支持MQTT的门锁。 在理想情况下,MQTT设备将具有一个状态主题来发布状态更改。如果这些消息以RETAIN标志发布,MQTT锁将在订阅后立即接收到状态更新,并将以正确的状态启动。否则,门锁的初始状态将为false/unlocked。 当状态主题不可用时,门锁将以即时更新模式工作。在此模式下,门锁将在每次命令后立即更改状态。否则,门锁将等待来自设备的状态确认(消息来自状态主题)。 即使状态主题可用,也可以强制启用即时更新模式。如果遇到不正确的门锁操作,请尝试启用它。 要在您的Home Assistant中启用MQTT门锁,请将以下内容添加到您的configuration.yaml文件中: # 示例配置.yml 条目 lock: - platform: mqtt command_topic: "home/frontdoor/set" 配置变量: command_topic (必需): 用于发布更改门锁状态的MQTT主题。 name (可选): 门锁的名称。默认为'MQTT Lock'。 state_topic (可选): 用于订阅以接收状态更新的MQTT主题。 payload_lock (可选): 表示已启用/已锁定状态的有效载荷。默认为'LOCK'。 payload_unlock (可选): 表示已禁用/已解锁状态的有效载荷。默认为'UNLOCK'。 optimistic (可选): 定义门锁是否以即时更新模式工作的标志。如果未定义状态主题,则默认为true,否则为false。 qos (可选): 状态主题的最大QoS级别。默认为0,并将用于发布消息。 retain (可选): 发布的消息是否应具有保留标志。 value_template (可选): 定义从有效载荷中提取值的模板。 请确保您的主题完全匹配。state_topic和command_topic应为不同的主题。 以下是一些实际使用此门锁的示例: 完整配置示例: # 示例配置.yml 条目 # 配置MQTT门锁 lock: - platform: mqtt # 使用MQTT平台 name: Frontdoor # 门锁的名称 state_topic: "home-assistant/frontdoor/" # 用于接收状态更新的MQTT主题 command_topic: "home-assistant/frontdoor/set" # 用于发布门锁状态更改命令的MQTT主题 payload_lock: "LOCK" # 表示已锁定状态的有效载荷 payload_unlock: "UNLOCK" # 表示已解锁状态的有效载荷 optimistic: false # 门锁是否以乐观模式工作的标志(不等待状态确认) qos: 1 # 状态主题的最大QoS级别 retain: true # 发布的消息是否应具有保留标志 value_template: '{{ value.x }}' # 从有效载荷中提取值的模板 请注意保留消息以保持状态,这样在重新启动时不会意外解锁您的门。您可以使用随MQTT一起提供的命令行工具来检查,以手动操作门锁: $ mosquitto_pub -h 127.0.0.1 -t home-assistant/frontdoor/set -m "LOCK" --- ### 133. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant使用MQTT消息负载作为传感器值。如果在这个消息中使用了RETAIN标志,传感器将立即接收到具有上次已知值的更新。否则,初始状态将未定义。 要在您的安装中使用MQTT传感器,请将以下内容添加到您的configuration.yaml文件中: # 示例 configuration.yaml 条目 sensor: - platform: mqtt state_topic: "home/bedroom/temperature" 配置变量: state_topic(必填):订阅以接收传感器值的MQTT主题。 name(可选):传感器的名称。默认为'MQTT Sensor'。 qos(可选):状态主题的最大QoS级别。默认值为0。 unit_of_measurement(可选):定义传感器的测量单位(如果有的话)。 expire_after(可选):定义值在多少秒后过期(如果不进行更新)。默认为0(永不过期)。 value_template(可选):定义从负载中提取值的模板。 示例: 在这个部分中,您将找到一些关于如何使用此传感器的实际示例。 获取电池电量:如果您使用Owntracks并启用电池电量报告,那么您可以使用MQTT传感器来跟踪电池电量。Owntracks的常规MQTT消息如下所示: owntracks/tablet/tablet {"_type":"location","lon":7.21,"t":"u","batt":92,"tst":144995643,"tid":"ta","acc":27,"lat":46.12} 因此,从负载中提取电池电量的关键是: # 示例配置:获取电池电量的MQTT传感器 sensor: - platform: mqtt # 使用MQTT传感器平台 state_topic: "owntracks/tablet/tablet" # 订阅MQTT主题以接收传感器值 name: "平板电池" # 传感器的名称 unit_of_measurement: "%" # 传感器值的单位(百分比) value_template: '{{ value_json.batt }}' # 使用模板从负载中提取电池电量值 获取温度和湿度:如果您使用DHT传感器和NodeMCU板(esp8266),您可以使用MQTT传感器来检索温度和湿度。您可以在此处找到代码示例。该示例生成的MQTT消息如下所示: office/sensor1{"temperature": 23.20,"humidity": 43.70} 然后,使用以下配置示例从负载中提取数据: # 示例配置:获取温度和湿度的MQTT传感器 sensor: - platform: mqtt # 使用MQTT传感器平台 state_topic: 'office/sensor1' # 订阅MQTT主题以接收温度传感器值 name: '温度传感器' # 传感器的名称 unit_of_measurement: '°C' # 传感器值的单位(摄氏度) value_template: '{{ value_json.temperature }}' # 使用模板从负载中提取温度值 - platform: mqtt # 使用MQTT传感器平台 state_topic: 'office/sensor1' # 订阅MQTT主题以接收湿度传感器值 name: '湿度传感器' # 传感器的名称 unit_of_measurement: '%' # 传感器值的单位(百分比) value_template: '{{ value_json.humidity }}' # 使用模板从负载中提取湿度值 --- ### 134. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Home Assistant允许您控制支持MQTT的灯光设备。它支持设置亮度、色温、效果、闪烁、开/关、RGB颜色、过渡、XY颜色和白色值。 当MQTT设备不具备状态主题以发布状态变更时,MQTT灯将以一种"即时更新模式"工作。这意味着,Home Assistant将立即更改设备状态,假设每次命令都会立即成功执行,而不必等待设备状态的确认。但是,如果这些状态消息以RETAIN标志发布,MQTT灯将在订阅后接收到立即的状态更新,并以正确的状态开始。反之,如果没有状态主题可用,开关的初始状态将为false/off。 在MQTT设备拥有状态主题的情况下,MQTT灯可以选择"即时更新模式",即使状态主题可用。"即时更新模式"意味着每次命令后,设备状态都会立即生效,无需等待设备实际状态的反馈。 这种操作模式的选择取决于您的设备和需求。如果您遇到不正确的灯光操作,可以尝试启用"即时更新模式",以获得更快的状态反馈。 即使状态主题可用,也可以强制启用即时更新模式。如果遇到有问题的灯光操作,请尝试启用它。 # 示例 configuration.yaml 配置项 light: - platform: mqtt command_topic: "office/rgb1/light/switch" 配置变量说明: command_topic(必填):用于发布更改开关状态的MQTT主题。 brightness_command_topic(可选):用于发布更改灯光亮度的MQTT主题。 brightness_scale(可选):定义MQTT设备的最大亮度值(默认为255,即100%)。 brightness_state_topic(可选):订阅以接收亮度状态更新的MQTT主题。 brightness_value_template(可选):定义提取亮度值的模板。 color_temp_command_topic(可选):用于发布更改灯光色温状态的MQTT主题。色温命令滑块的范围为157到500 mireds(微逆度)。 color_temp_state_topic(可选):订阅以接收色温状态更新的MQTT主题。 color_temp_value_template(可选):定义提取色温值的模板。 effect_command_topic(可选):用于发布更改灯光效果状态的MQTT主题。 effect_state_topic(可选):订阅以接收效果状态更新的MQTT主题。 effect_value_template(可选):定义提取效果值的模板。 effect_list(可选):灯光支持的效果列表。 name(可选):开关的名称,默认为“MQTT开关”。 optimistic(可选):定义开关是否以“即时更新模式”工作的标志。如果没有定义状态主题,默认为true,否则为false。 payload_off(可选):表示禁用状态的负载,默认为“OFF”。 payload_on(可选):表示启用状态的负载,默认为“ON”。 qos(可选):状态主题的最大QoS级别。默认为0,也将用于发布消息。 retain(可选):发布的消息是否应具有保留标志。 RGB rgb_command_template(可选):定义用于发送给RGB状态的消息的模板。可用变量:red、green和blue。 rgb_command_topic(可选):用于发布更改灯光RGB状态的MQTT主题。 rgb_state_topic(可选):订阅以接收RGB状态更新的MQTT主题。 rgb_value_template(可选):定义提取RGB值的模板。 state_topic(可选):订阅以接收状态更新的MQTT主题。 state_value_template(可选):定义提取状态值的模板。 白色(单色) white_value_command_topic(可选):用于发布更改灯光白色值的MQTT主题。 white_value_state_topic(可选):订阅以接收白色值更新的MQTT主题。 white_value_value_template(可选):定义提取白色值的模板。 XY xy_command_topic(可选):用于发布更改灯光XY状态的MQTT主题。 xy_state_topic(可选):订阅以接收XY状态更新的MQTT主题。 xy_value_template(可选):定义提取XY值的模板。 请确保您的主题精确匹配,而且是不同的主题。有些主题/some-topic/some-topic XY和RGB不能同时使用。如果两者都提供了,XY将覆盖RGB。 MQTT灯光控制平台与其他灯光控制MQTT平台的比较: 功能mqttmqtt_jsonmqtt_template亮度✔✔✔色温✔✔✔效果✔✔✔闪烁✘✔✔RGB颜色✔✔✔过渡✘✔✔XY颜色✔✔✘白色值✔✔✔ 示例: 启用支持亮度和RGB的灯光: # 示例配置:启用支持亮度和RGB的灯光 light: - platform: mqtt # 使用MQTT作为灯光控制平台 name: "办公室灯RGB" # 设备的名称,可以自定义 state_topic: "office/rgb1/light/status" # 订阅状态更新的MQTT主题 command_topic: "office/rgb1/light/switch" # 发布命令以更改开关状态的MQTT主题 brightness_state_topic: "office/rgb1/brightness/status" # 订阅亮度状态更新的MQTT主题 brightness_command_topic: "office/rgb1/brightness/set" # 发布命令以更改亮度的MQTT主题 rgb_state_topic: "office/rgb1/rgb/status" # 订阅RGB状态更新的MQTT主题 rgb_command_topic: "office/rgb1/rgb/set" # 发布命令以更改RGB颜色的MQTT主题 state_value_template: "{{ value_json.state }}" # 从消息中提取状态值的模板 brightness_value_template: "{{ value_json.brightness }}" # 从消息中提取亮度值的模板 rgb_value_template: "{{ value_json.rgb | join(',') }}" # 从消息中提取RGB颜色值的模板 qos: 0 # MQTT消息的质量服务等级 payload_on: "ON" # 表示开启状态的MQTT消息有效负载 payload_off: "OFF" # 表示关闭状态的MQTT消息有效负载 optimistic: false # 即时更新模式,即使有状态主题也强制开启,用于确保状态及时更新 启用仅亮度(无RGB支持)的灯光: # 示例配置:启用仅亮度的灯光 light: - platform: mqtt # 使用MQTT作为灯光控制平台 name: "办公室灯光" # 设备的名称,可以自定义 state_topic: "office/rgb1/light/status" # 订阅状态更新的MQTT主题 command_topic: "office/rgb1/light/switch" # 发布命令以更改开关状态的MQTT主题 brightness_state_topic: 'office/rgb1/light/brightness' # 订阅亮度状态更新的MQTT主题 brightness_command_topic: 'office/rgb1/light/brightness/set' # 发布命令以更改亮度的MQTT主题 qos: 0 # MQTT消息的质量服务等级 payload_on: "ON" # 表示开启状态的MQTT消息有效负载 payload_off: "OFF" # 表示关闭状态的MQTT消息有效负载 optimistic: false # 即时更新模式,即使有状态主题也强制开启,用于确保状态及时更新 实现示例: 使用NodeMCU板(ESP8266)的基本示例来控制其内置LED(开/关)。 另一个示例用于控制RGB LED(开/关、亮度和颜色)。 扩展阅读: XY颜色 灯光的"XY状态"通常指的是灯光的颜色坐标。在某些灯光系统中,颜色可以使用XY坐标来表示,而不是传统的RGB颜色或色温(Kelvin)值。 这里的"XY状态"表示灯光当前的颜色坐标,其中X和Y分别表示颜色在色域中的位置。通过设置不同的XY坐标,您可以选择不同的颜色。这种方式可以提供更广泛的颜色选择,通常用于支持更复杂的灯光效果和场景。 mireds(微逆度) "微逆度"是一种用于表示光源色温的单位,通常用符号"mireds"表示,缩写为"M". 它是色温的倒数,以开尔文(K)为单位。更高的微逆度值表示更凉的颜色,而较低的值表示较暖的颜色。这是一个用于度量光源色温的标准单位。 --- ### 135. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Vue.js,通常简称为 Vue,是一款流行的JavaScript前端框架,由尤雨溪(Evan You)及其团队开发和维护。Vue以其简单、灵活、高效的特点而备受开发者欢迎,它专注于实现UI层的构建和交互,为构建现代Web应用提供了有力的工具和资源。它以其数据双向绑定、组件化、响应式和轻量等特点而著称。搭配 Vue CLI 脚手架工具,使开发者更容易入门,大大降低了学习成本。此外,Vue 还配备了一个专用的状态管理模式 Vuex,可以帮助您集中管理应用程序的状态。 MQTT 是一种基于发布/订阅模式的轻量级物联网消息传输协议。它提供了一对多的消息分发和应用程序解耦的能力,拥有小型传输开销、协议数据交换的能力以及三种不同的消息服务质量等级,以满足不同的消息传递需求。 本文将重点介绍如何在 Vue 项目中使用 MQTT 来实现客户端与 MQTT 服务器之间的连接、订阅、消息收发和取消订阅等功能。 项目初始化 首先,我们需要创建一个新的 Vue 项目。您可以选择使用 Vue CLI 创建项目,也可以通过引入 Vue.js 创建项目。以下是使用 Vue CLI 创建项目的示例: vue create vue-mqtt-test 接下来,我们需要安装 MQTT 客户端库。安装方式有多种选择,您可以通过命令行使用 npm 或 yarn 安装,也可以通过 CDN 引入。以下是通过命令行安装的示例: npm install mqtt --save 或 yarn add mqtt 这将帮助我们轻松引入 MQTT 客户端库。 MQTT 的使用 连接 MQTT 服务器 在本文中,我们将使用由 EMQX 提供的免费公共 MQTT 服务器。以下是服务器连接信息: Broker: broker.emqx.io TCP 端口: 1883 WebSocket 端口: 8083 WebSocket Secure 端口: 8084 接下来是连接关键代码示例: <script> import mqtt from "mqtt"; export default { data() { return { connection: { protocol: "ws", host: "broker.emqx.io", port: 8083, endpoint: "/mqtt", clean: true, connectTimeout: 30 * 1000, reconnectPeriod: 4000, clientId: "emqx_vue_" + Math.random().toString(16).substring(2, 8), username: "emqx_test", password: "emqx_test", }, // ... 其他数据 }; }, methods: { initData() { // 初始化数据 }, handleOnReConnect() { // 处理重新连接 }, createConnection() { // 创建连接 }, }, }; </script> 订阅主题 在 MQTT 中,订阅主题是一项常见的操作。下面是订阅主题的示例代码: methods: { // ... 其他方法 doSubscribe() { const { topic, qos } = this.subscription; this.client.subscribe(topic, { qos }, (error, res) => { if (error) { console.log('Subscribe to topics error', error); return; } this.subscribeSuccess = true; console.log('Subscribe to topics res', res); }); }, // ... 其他方法 }, 取消订阅 取消订阅也是一项重要的操作。以下是取消订阅的示例代码: methods: { // ... 其他方法 doUnSubscribe() { const { topic } = this.subscription; this.client.unsubscribe(topic, error => { if (error) { console.log('Unsubscribe error', error); } }); }, // ... 其他方法 }, 消息发布 发布消息是与 MQTT 服务器进行通信的关键操作之一。以下是发布消息的示例代码: methods: { // ... 其他方法 doPublish() { const { topic, qos, payload } = this.publish; this.client.publish(topic, payload, { qos }, error => { if (error) { console.log('Publish error', error); } }); }, // ... 其他方法 }, 断开连接 最后,当不再需要连接 MQTT 服务器时,应该执行断开连接操作。以下是断开连接的示例代码: methods: { // ... 其他方法 destroyConnection() { if (this.client.connected) { try { this.client.end(false, () => { this.initData(); console.log('Successfully disconnected!'); }); } catch (error) { console.log('Disconnect failed', error.toString()); } } }, // ... 其他方法 }, 测试 我们已经使用 Vue 编写了一个简单的浏览器应用,该应用具备创建连接、订阅主题、收发消息、取消订阅和断开连接等功能。您可以在 GitHub 上找到完整的项目代码:GitHub 项目链接。 在测试过程中,您可以使用 MQTT 5.0 客户端工具 - MQTTX 作为另一个客户端来进行消息收发测试。 通过这个示例,我们演示了如何在 Vue 项目中创建 MQTT 连接,并模拟了客户端与 MQTT 服务器之间的订阅、消息发布和取消订阅等场景。 总结 Vue 是一款强大的前端框架,与 MQTT 协议结合使用可以实现各种有趣的应用。无论是浏览器端还是移动端,Vue 都可以帮助您开发出高效的 应用程序。希望本文能够帮助您更好地理解如何在 Vue 项目中使用 MQTT,以及如何利用这种组合来构建更多有趣和实用的物联网应用。 --- ### 136. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT 作为目前物联网领域最为流行的通信协议,它的最新版本早已在 2019 年就已经来到了 5.0。与之前的版本相比,5.0 增加了会话过期、原因码、共享订阅、请求响应等更符合现代物联网应用需求的特性,这也让它成为了目前绝大多数物联网企业的首选版本。 为了让大家更全面地了解 MQTT 5.0,本文将依次介绍 5.0 引入的各个新特性,并使用 MQTTX CLI 工具演示我们应该如何在 EMQX 中使用这些特性,你可以通过复制和粘贴命令轻松地运行本文中的示例。 在正式开始前,我们需要完成以下准备工作: 使用 Docker 来部署一个最基础的 EMQX 实例,你可以运行以下命令来启动 EMQX:docker run -d --name emqx -p 18083:18083 -p 1883:1883 emqx:5.1.3 下载并安装 MQTTX CLI 1.9.4。它是一款开源的 MQTT 5.0 命令行客户端工具,我们将通过它来完成本文的所有示例。 安装 Wireshark。在部分示例中,我们将用它来抓取并分析一些 MQTT 报文,这可以帮助我们更好地了解究竟发生了什么。 特性 1:会话过期 在 MQTT 5.0 中,客户端可以在 CONNECT 报文中通过 Session Expiry Interval 来指示它期望的网络连接断开后会话的过期间隔(以秒为单位)。如果服务端不接受这个过期间隔,也可以在 CONNACK 报文中指示一个新的过期间隔,客户端则需要遵从服务端的要求。 在会话过期之前,MQTT 客户端与服务端都需要存储相应的会话状态。以服务端为例,它需要存储的会话状态包括已经发送但尚未完成确认的消息,尚未发送的消息以及客户端的订阅列表等等。 只要客户端与服务端的连接在会话过期前恢复,那么它们就可以继续之前的通信,就像连接从未断开过一样。 示例 1 客户端 sub1 订阅主题 t1,并设置会话过期间隔为 60 秒,订阅完成后在终端输入 Ctrl+C 断开客户端连接:mqttx sub --client-id sub1 --session-expiry-interval 60 --topic t1 … Connecting... ✔ Connected … Subscribing to t1... ✔ Subscribed to t1 ^C 在 60 秒内向主题 t1 发布一条消息:mqttx pub --topic t1 --message "Hello World" … Connecting... ✔ Connected … Message publishing... ✔ Message published 客户端 sub1 重新连接,注意这里指定了 --no-clean 选项表示希望复用之前的会话,我们将看到此客户端收到了我们在它连接之前发布的消息:mqttx sub --client-id sub1 --no-clean --session-expiry-interval 0 --topic t1 … Connecting... ✔ Connected … Subscribing to t1... payload: Hello World ✔ Subscribed to t1 示例 2 EMQX 默认允许的最大会话过期间隔为 2 小时,我们可以打开 EMQX Dashboard(浏览器中输入 http://localhost:18083 即可访问),通过 Management -> MQTT Settings -> Session 页面中的 Session Expiry Interval 配置项来修改它。 本示例中我们将它设置为 0 秒,即会话将在网络连接断开时立即过期: 接下来,重复示例 1 中的步骤,这一次客户端 sub1 将不会在重新连接后收到消息:mqttx sub --client-id sub1 --session-expiry-interval 60 --topic t1 … Connecting... ✔ Connected … Subscribing to t1... ✔ Subscribed to t1 ^C mqttx pub --topic t1 --message "Hello World" … Connecting... ✔ Connected … Message publishing... ✔ Message published mqttx sub --client-id sub1 --no-clean --session-expiry-interval 0 --topic t1 … Connecting... ✔ Connected … Subscribing to t1... ✔ Subscribed to t1 特性 2:消息过期 在 MQTT 5.0 中,我们可以为每条消息设置一个过期间隔(以秒为单位),如果消息在服务端中停留超过了这个间隔,那么它将不会再被分发给客户端。 当我们想要长时间地保留会话,但是又想要发送一些具有时效性的消息时,这个特性将会非常有用。 另外,如果客户端在发布消息时设置了过期间隔,那么服务端在转发这个消息时也会包含过期间隔,但过期间隔的值会被更新为服务端接收到的值减去该消息在服务端停留的时间。 这样接收者就可以知道这个消息是有时效的,以及它将在多少时间后过期。 示例 1 客户端 sub2 订阅主题 t2,并设置会话过期间隔为 300 秒,订阅完成后在终端输入 Ctrl+C 断开客户端连接:mqttx sub --client-id sub2 --session-expiry-interval 300 --topic t2 … Connecting... ✔ Connected … Subscribing to t2... ✔ Subscribed to t2 ^C 向同一主题发布一条消息,并设置消息过期间隔为 5 秒钟mqttx pub --topic t2 --message "Hello World" --message-expiry-interval 5 … Connecting... ✔ Connected … Message publishing... ✔ Message published 等待 10 秒钟后客户端 sub2 恢复连接,但是它将不会收到我们刚刚发布的消息:sleep 10; mqttx sub --client-id sub2 --no-clean --session-expiry-interval 300 --topic t2 … Connecting... ✔ Connected … Subscribing to t2... ✔ Subscribed to t2 示例 2 继续向主题 t2 发布消息,并设置消息过期间隔为 60 秒钟:mqttx pub --topic t2 --message "Hello World" --message-expiry-interval 60 … Connecting... ✔ Connected … Message publishing... ✔ Message published 等待 10 秒后客户端 sub2 恢复连接,它将收到我们刚刚发布的消息,并且其中的消息过期间隔为 50 秒。sleep 10; mqttx sub --client-id sub2 --no-clean --session-expiry-interval 0 --topic t2 --output-mode clean { "topic": "t2", "payload": "Hello World", "packet": { ... "properties": { "messageExpiryInterval": 50 } } } 特性 3:令所有响应报文支持原因码 MQTT 5.0 不仅为所有响应报文都增加了原因码字段,同时也扩展了可用的原因码。现在服务端和客户端都可以更清晰地向对方指示错误原因。 比如当消息到达但当前不存在任何匹配的订阅时,服务端将会丢弃这个消息。但为了让消息的发送者得知这一情况,服务端会将响应报文中的原因码设置为 0x10(仅限 QoS 1 与 QoS 2 消息),表示不存在匹配的订阅者。 你可以通过 MQTT 5.0 Reason Code 速查表 了解更多原因码相关的知识。 示例 本示例中我们将用到 Wireshark。启动 Wireshark 后首先选择正确的网卡,如果你的 EMQX 与 MQTTX CLI 同样运行在同一台机器上,那么你应该与本示例一样选择环回接口,然后输入以下过滤语句抓取报文:tcp.port == 1883 向主题 t3 发布 QoS 1 消息:mqttx pub --topic t3 --message "Hello World" --qos 1 … Connecting... ✔ Connected … Message publishing... ✔ Message published 在 Wireshark 中我们将看到 EMQX 返回的 PUBACK 报文中 Reason Code 被设置为 0x10: 特性 4:服务器断开 MQTT 5.0 允许服务端在断开网络连接前发送 DISCONNECT 报文,以便向客户端指示连接断开的原因。 示例 在 Wireshark 中输入以下过滤语句抓取报文:tcp.port == 1883 建立一个 MQTT 连接:mqttx conn --client-id conn4 … Connecting... ✔ Connected 在另一个终端窗口中使用 EMQX 提供的 CLI 命令手动踢除客户端:docker exec emqx emqx ctl clients kick conn4 ok 我们将在第一个终端窗口中看到连接被断开:✖ Connection closed EMQX 发送的 DISCONNECT 报文中 Reason Code 被设置为 0x98,表示此连接因为管理操作而被关闭: 特性 5:载荷格式与内容类型 在 MQTT 5.0 中,消息的发布者可以通过 Payload Format Indicator 来指示该消息的内容是 UTF-8 编码的字符数据还是未指定格式的二进制数据。 Content Type 则可以进一步指示消息内容的具体格式,这样接收者可以更容易地知道应该如何解析这个消息。常见的做法是将其设置为一个 MIME 内容类型,例如 application/json。当然这并不是强制的,我们也可以使用任意的 UTF-8 字符串来指示我们自定义的消息类型 。 示例 订阅主题 t6:mqttx sub --topic t6 --output-mode clean 在另一个终端窗口中发布消息,设置 Payload Format Indicator 表示此消息的内容是 UTF-8 编码的字符数据,设置为 Content Type 为 application/json 表示这是一个 JSON 格式的消息:mqttx pub --topic t6 --message "{\"content\": \"Hello World\"}" --payload-format-indicator --content-type application/json … Connecting... ✔ Connected … Message publishing... ✔ Message published 第一个终端窗口将打印接收到的消息内容,我们可以看到消息中包含了 Content Type 和 Payload Format Indicator:{ "topic": "t6", "payload": "{\"content\": \"Hello World\"}", "packet": { ... "properties": { "contentType": "application/json", "payloadFormatIndicator": true } } } 特性 6:请求/响应 MQTT 5.0 极大地改善了对请求响应模式的支持。请求方可以在请求消息指定响应主题(Response Topic),响应方则需要向该响应主题发布响应消息。 这在同时存在多个请求方,响应方需要将响应正确地回复给其中一个请求方时非常有用,不同请求方只需要指定不同的响应主题即可。一个简单的做法是在响应主题中包含自己的 Client ID。 MQTT 不能保证请求方的请求一定被响应方收到,反之亦然。所以请求方还需要能够正确地将自己发出的请求与收到的响应进行关联。在 MQTT 5.0 中,我们可以在请求消息中设置对比数据(Correlation Data),响应方将原封不动地在响应消息中返回这个对比数据,这样请求方就能够知道这是哪个请求的响应。 示例 在第一个终端窗口中,响应方订阅请求主题:mqttx sub --client-id responder --topic request --session-expiry-interval 300 --output-mode clean 在第二个终端窗口中,请求方发布请求消息,并设置响应主题为 response/requester1:mqttx pub --client-id requester1 --session-expiry-interval 300 --topic request --message "This is a reuqest" --response-topic response/requester1 --correlation-data request-1 … Connecting... ✔ Connected … Message publishing... ✔ Message published 在第一个终端窗口中,响应方收到请求消息,消息中包含了响应主题与对比数据:{ "topic": "request", "payload": "This is a reuqest", "packet": { "properties": { "correlationData": { "type": "Buffer", "data": [ 114, 101, 113, 117, 101, 115, 116, 45, 49 ] }, "responseTopic": "response/requester1" } } } 回到第二个终端窗口,请求方订阅响应主题(在实际应用中,请求方需要在发布请求前订阅响应主题以免错过响应消息):mqttx sub --client-id requester1 --no-clean --session-expiry-interval 300 --topic response/requester1 --output-mode clean 在第一个终端窗口中,响应方收到请求中的响应主题发布响应响应,并携带对比数据:mqttx pub --client-id responder --topic response/requester1 --message "This is a response" --correlation-data request-1 在第二个终端窗口中,请求方收到响应消息:{ "topic": "response", "payload": "This is a response", "packet": { ... "properties": { "correlationData": { "type": "Buffer", "data": [ 114, 101, 113, 117, 101, 115, 116, 45, 49 ] } } } } 特性 7:共享订阅 MQTT 5.0 增加了对共享订阅的支持,使得订阅端能够以负载均衡的方式来消费消息。 它允许我们将订阅客户端划分为多个订阅组,消息仍然会被转发给所有订阅组,但一个订阅组内的客户端将以随机、轮询等策略交替接收消息。这些策略完全由服务端实现,客户端不需要进行任何修改,唯一需要做的就是通过 $share/{ShareGroup}/{Topic} 来发起共享订阅。 示例 在第一个终端窗口中,订阅主题 $share/g1/t7:mqttx sub --topic '$share/g1/t7' … Connecting... ✔ Connected … Subscribing to $share/g1/t7... ✔ Subscribed to $share/g1/t7 在第二个终端窗口中,同样订阅主题 $share/g1/t7:mqttx sub --topic '$share/g1/t7' … Connecting... ✔ Connected … Subscribing to $share/g1/t7... ✔ Subscribed to $share/g1/t7 在第三个终端窗口中,改为订阅主题 $share/g2/t7:mqttx sub --topic '$share/g2/t7' … Connecting... ✔ Connected … Subscribing to $share/g2/t7... ✔ Subscribed to $share/g2/t7 在第四个终端窗口中,向主题 t7 发布消息,这里我们使用了 --multiline 选项,以每次键入回车的方式发送多条消息:mqttx pub --topic t7 -s --stdin --multiline … Connecting... ✔ Connected, press Enter to publish, press Ctrl+C to exit Message 1 Message 2 Message 3 Message 4 Message 5 Message 6 ^C EMQX 默认的共享订阅策略为 round_robin,这表示消息将轮流分发给同一个订阅组内的订阅者。所以我们将看到第一个和第二个终端窗口中的订阅者将交替接收我们发布的消息:payload: Message 1 payload: Message 3 payload: Message 5 payload: Message 2 payload: Message 4 payload: Message 6 共享订阅组 g2 中只有一个订阅者,所以我们将在第三个终端窗口中看到订阅者收到了所有消息:payload: Message 1 payload: Message 2 payload: Message 3 payload: Message 4 payload: Message 5 payload: Message 6 特性 8:订阅标识符 MQTT 5.0 允许客户端在订阅时设置一个订阅标识符(Subscription Identifier),服务端会将该标识符与订阅绑定,当服务端向该订阅转发消息时,它会在消息中附上对应的标识符。客户端可以使用消息中的订阅标识符,决定触发哪一个回调,或者进行其他操作。 示例 同一个客户端订阅主题 t8/1 与 t8/#,并设置不同的订阅标识符:mqttx sub --client-id sub8 --session-expiry-interval 300 --topic t8/1 --subscription-identifier 1 … Connecting... ✔ Connected … Subscribing to t8/1... ✔ Subscribed to t8/1 ^C mqttx sub --client-id sub8 --no-clean --session-expiry-interval 300 --topic t8/# --subscription-identifier 2 --output-mode clean 在第二个终端窗口中,向主题 t8/1 发布消息:mqttx pub --topic t8/1 --message "Hello World" 第一个终端窗口中的订阅端将收到两条消息,根据消息中的订阅标识符我们可以得知,第一条消息来自订阅的主题 t8/#,第二条消息来自订阅的主题 t8/1:{ "topic": "t8/1", "payload": "Hello World", "packet": { ... "properties": { "subscriptionIdentifier": 2 } } } { "topic": "t8/1", "payload": "Hello World", "packet": { ... "properties": { "subscriptionIdentifier": 1 } } } 当消息匹配同一个客户端的多个订阅时,MQTT 服务端可以向这些重叠的订阅分别发送一条消息,也可以向这些重叠的订阅只发送一条消息。EMQX 属于前者。 特性 9:主题别名 MQTT 5.0 允许我们在发布消息时以一个两个字节长度的整数类型的主题别名来替代主题名,这在主题名较长时可以有效减少 PUBLISH 报文的大小。 使用主题别名时,我们需要先发送一个同时包含主题名与主题别名的消息,让对端建立映射关系,然后才能发送仅包含主题别名的消息。 主题别名的映射不属于会话状态的一部分,所以即便客户端重连时恢复了会话,它与服务端也需要重新建立主题别名的映射。 客户端和服务端使用的主题别名映射相互独立。因此一般来说,客户端发送给服务端的主题别名值为 1 的消息和服务端发送给客户端的主题别名值为 1 的消息,将被映射到不同的主题。 客户端和服务端还可以在连接时约定互相可以发送的主题别名的最大值。EMQX 默认允许的主题别名的最大值为 65535,我们可以打开 EMQX Dashboard(浏览器中输入 http://localhost:18083 即可访问),通过 Management -> MQTT Settings -> General 页面中的 Max Topic Alias 配置项来修改它。 特性 10:流量控制 MQTT 5.0 中客户端与服务端可以在连接时使用接收最大值(Receive Maximum)来指示自己愿意同时处理的未确认的 QoS 1 和 QoS 2 消息的最大数量。 当已经发送但未完全确认的消息数量达到接收最大值限制时,发送方就不能继续向接收方发送消息(QoS 0 消息不受此限制)。这可以有效避免发送方发送过快导致超出接收方的处理能力。 特性 11:用户属性 MQTT 5.0 中的大部分报文都可以包含用户属性。用户属性是一个由 UTF-8 编码的字符串组成的名称-值对,名称和值的具体内容可以由客户端和服务端的实现自行定义,我们可以在没有超过报文最大长度的前提下指定任意多个用户属性。 CONNECT、SUBSCRIBE 这类报文中的用户属性,通常取决于具体 MQTT 服务器的实现。 PUBLISH 报文中的用户属性,会被服务端直接原封不动地转发给订阅端,所以只要消息的发布端和订阅端约定好用户属性的内容即可。比如在应用消息的用户属性中附上发布端的 Client ID,这样订阅端将可以知道消息来自哪里。 示例 订阅主题 t11:mqttx sub --topic t11 --output-mode clean 在另一个终端窗口中,向主题 t11 发布消息,并设置了两个用户属性,一个指示消息的来源,一个指示消息的发布时间:mqttx pub --client-id pub11 --topic t11 --message "Hello World" --user-properties "from: pub11" --user-properties "timestamp: 1691046633" 回到第一个终端窗口中,订阅端收到的消息中包含了我们设置的用户属性:{ "topic": "t11", "payload": "Hello World", "packet": { ... "properties": { "userProperties": { "from": "pub11", "timestamp": "1691046633" } } } } 特性 12:最大报文长度 MQTT 5.0 允许客户端和服务端在连接时通过 Maximum Packet Size 属性相互约定自己能够处理的最大报文长度,之后任何一方都不得发送超过约定长度限制的报文,否则将造成协议错误而被关闭连接。 所以当 PUBLISH 报文过大导致无法转发时,服务端将直接丢弃该 PUBLISH 报文。 示例 1 在第一个终端窗口中,向服务端声明自己可接受的最大报文长度为 128 字节,并订阅主题 t12:mqttx sub --maximum-packet-size 128 --topic t12 … Connecting... ✔ Connected … Subscribing to t12... ✔ Subscribed to t12 在第二个终端窗口中,发布一个长度小于 128 字节的消息:payload=$(head -c 10 < /dev/zero | tr '\0' 0) mqttx pub --topic t12 -m "$payload" 在第一个终端窗口中,订阅端将收到以下消息:payload: 0000000000 继续在第二个终端窗口中发布一个长度超过 128 字节的消息:payload=$(head -c 128 < /dev/zero | tr '\0' 0) mqttx pub --topic t12 -m "${payload}" 这一次第一个终端窗口中的订阅端将不会收到消息,我们输入 Ctrl+C 断开订阅端连接,然后运行以下命令查看 EMQX 日志:docker logs emqx 我们将看到消息因 frame_is_too_large 而被丢弃的日志:2023-08-03T06:17:52.538541+00:00 [warning] msg: packet_is_discarded, mfa: emqx_connection:serialize_and_inc_stats_fun/1, line: 872, peername: 172.17.0.1:39164, clientid: mqttx_f0a3847c, packet: PUBLISH(Q0, R0, D0, Topic=t12, PacketId=undefined, Payload=******), reason: frame_is_too_large 示例 2 EMQX 默认允许的最大报文长度为 1MB,我们可以打开 EMQX Dashboard(浏览器中输入 http://localhost:18083 即可访问),通过 Management -> MQTT Settings -> General 页面中的 Max Packet Size 配置项来修改它。 注意最大长度限制的是所有报文,所以如果设置了一个过小的最大报文长度,可能导致连接无法建立。这是我们要注意避免的。 本示例中,我们将它修改为 1024 字节: 然后在 Wireshark 中输入以下过滤语句抓取报文:tcp.port == 1883 在终端窗口中,发布一个长度超过 1024 字节的消息:payload=$(head -c 1024 < /dev/zero | tr '\0' 0) mqttx pub --client-id pub12 --topic t12 -m "${payload}" … Connecting... ✔ Connected … Message publishing... ✔ Message published 在 Wireshark 中我们将看到 EMQX 返回了 DISCONNECT 报文,并将 Reason Code 被设置为 0x95,表示连接因为收到了过大的报文而被关闭: 特性 13:可选的服务端功能 MQTT 允许服务端不完全支持协议声明的功能和特性,但服务端需要在 CONNACK 报文中告知客户端自己不支持的功能,避免客户端使用这些不可用的功能。可选的服务端功能包括: 支持的最大 QoS 等级 保留消息 通配符订阅 订阅标识符 共享订阅 如果客户端仍然使用了服务端已经告知不可用的功能,那么就会造成协议错误被服务端关闭连接。 示例 EMQX 默认支持所有 MQTT 特性,但我们可以手动关闭一些功能,比如通配符订阅、共享订阅以及保留消息等等。本示例中我们关闭了保留消息功能: 然后在 Wireshark 中输入以下过滤语句抓取报文:tcp.port == 1883 在终端窗口中发布一条保留消息:mqttx pub --topic t13 --message "This is a retained message" --retain … Connecting... ✔ Connected … Message publishing... ✔ Message published 在 Wireshark 中我们将看到 EMQX 在 CONNACK 报文中返回了各个功能的可用情况,其中保留消息被声明为不可用: 而在客户端发布保留消息后,EMQX 返回了 DISCONNECT 报文,并将 Reason Code 被设置为 0x9A,表示服务端不支持保留消息: 完成此示例后,请将 EMQX 的保留消息功能再次打开,以免影响后续的示例。 特性 14:订阅选项 MQTT 5.0 在 QoS 的基础上又提供了三个新的订阅选项,分别为: No Local,用于指示消息是否可以被转发给发布此消息的客户端。 Retain As Published,用于指示服务端向该订阅转发消息时是否需要保留其中的 Retain 标志。 Retain Handling,用于指示订阅建立时服务端是否需要向该订阅发送保留消息,这个选项有三个可取值: 设置为 0,只要订阅建立,就发送保留消息。 设置为 1,只有在订阅建立时该订阅当前不存在才发送保留消息。 设置为 2,订阅建立时不发送保留消息。 你可以阅读 MQTT 订阅选项的使用 了解订阅选项的更多知识。 示例 1 - No Local 客户端 sub14 和 pub14 分别发布一条消息到主题 t14,这里我们借助了 EMQX 的 延迟发布 功能,让消息延迟 10 秒发布:mqttx pub --client-id sub14 --topic '$delayed/10/t14' --message "You will not receive this message" mqttx pub --client-id pub14 --topic '$delayed/10/t14' --message "You will receive this message" 令客户端 sub14 订阅主题 t14,并设置 No Local 选项,它将收到客户端 pub14 发布的消息,但不会收到它自己发布的消息:mqttx sub --client-id sub14 --topic t14 --no_local … Connecting... ✔ Connected … Subscribing to t14... ✔ Subscribed to t14 payload: You will receive this message 示例 2 - Retain As Published 在第一个终端窗口中,订阅主题 t14,并设置 Retain As Published 选项:mqttx sub --topic t14 --retain-as-published --output-mode clean 在第二个终端窗口中,向主题 t14 发布一条保留消息:mqttx pub --topic t14 --message "Hello World" --retain … Connecting... ✔ Connected … Message publishing... ✔ Message published 在第一个终端窗口中,订阅端将收到设置了 Retain 标志位的消息:{ "topic": "t14", "payload": "Hello World", "packet": { ... "retain": true, ... } } 清除保留消息:mqttx pub --topic t14 --message '' --retain 示例 3 - Retain Handling 向主题 t14 发布一条保留消息:mqttx pub --topic t14 --message "This is a retained message" --retain … Connecting... ✔ Connected … Message publishing... ✔ Message published 订阅相同主题并设置 Retain Handling 为 0,我们将收到保留消息:mqttx sub --client-id sub14 --session-expiry-interval 300 --topic t14 --retain-handling 0 … Connecting... ✔ Connected … Subscribing to t14... ✔ Subscribed to t14 payload: This is a retained message retain: true ^C 在终端输入 Ctrl+C 断开客户端连接。 重连并恢复会话,订阅相同主题,但是将 Retain Handling 设置为 1,这一次我们将不会收到保留消息,因为在服务端此订阅已经存在:mqttx sub --client-id sub14 --no-clean --session-expiry-interval 300 --topic t14 --retain-handling 1 … Connecting... ✔ Connected … Subscribing to t14... ✔ Subscribed to t14 ^C 在终端输入 Ctrl+C 断开客户端连接。 重连但创建一个全新的会话,订阅相同主题,将 Retain Handling 设置为 2,这一次我们仍然不会收到保留消息:mqttx sub --client-id sub14 --topic t14 --retain-handling 2 … Connecting... ✔ Connected … Subscribing to t14... ✔ Subscribed to t14 清除保留消息:mqttx pub --topic t14 --message '' --retain 特性 15:遗嘱延迟 在 MQTT 5.0 中,客户端可以为遗嘱消息设置一个延迟间隔,而不再是让它在网络连接断开时就立即发布,如果客户端连接能够遗嘱延迟间隔到达前及时恢复,那么遗嘱消息就不会被发布。这可以有效地避免遗嘱消息仅仅因为客户端连接的短暂中断而被发布。 如果遗嘱延迟间隔大于会话过期间隔,那么遗嘱消息将在会话过期时被立即发送,所以我们还可以将遗嘱消息用于会话到期通知。 示例 1 在第一个终端窗口中订阅主题 t15:mqttx sub --topic t15 … Connecting... ✔ Connected … Subscribing to t15... ✔ Subscribed to t15 在第二个终端窗口中建立一个设置了遗嘱消息的 MQTT 连接,并将遗嘱延迟间隔设置为 10 秒。连接成功后输入 Ctrl+C 断开客户端连接:mqttx conn --client-id conn15 --will-topic t15 --will-message "I'm offline" --will-delay-interval 10 --session-expiry-interval 300 … Connecting... ✔ Connected ^C 第一个终端窗口中的订阅端将在 10 秒后收到遗嘱消息:payload: I'm offline 示例 2 在第二个终端窗口中再次建立一个设置了遗嘱消息的 MQTT 连接,并将遗嘱延迟间隔设置为 10 秒。连接成功后输入 Ctrl+C 断开客户端连接:mqttx conn --client-id conn15 --will-topic t15 --will-message "I'm offline" --will-delay-interval 10 --session-expiry-interval 300 … Connecting... ✔ Connected ^C 在 10 秒内重连:mqttx conn --client-id conn15 --will-topic t15 --will-message "I'm offline" --will-delay-interval 10 --no-clean --session-expiry-interval 300 这一次第一个终端窗口中的订阅端将不会收到遗嘱消息。 示例 3 我们还可以为遗嘱消息设置 Will Retain 标识,让它成为一个保留消息,避免订阅端因不在线而错过遗嘱消息。 继续在第二个终端窗口中建立一个设置了遗嘱消息的 MQTT 连接,这一次我们将遗嘱延迟间隔设置为 0 秒,因此遗嘱消息将在连接断开时立即发布。连接成功后输入 Ctrl+C 断开客户端连接:mqttx conn --client-id conn15 --will-topic t15 --will-message "I'm offline" --will-delay-interval 0 --will-retain --session-expiry-interval 300 … Connecting... ✔ Connected ^C 在第一个终端窗口中订阅主题 t15,我们将收到在这之前发布的遗嘱消息:mqttx sub --topic t15 … Connecting... ✔ Connected … Subscribing to t15... ✔ Subscribed to t15 payload: I'm offline retain: true 特性 16:由服务端指定保活时间 保活时间决定了客户端发送相邻两个控制报文的最大空闲时间,服务端可以根据是否在预期的时间内收到客户端的报文来判断它是否仍然活跃。 在 MQTT 5.0 中,服务端可以不接受客户端指定的保活时间,并在 CONNACK 报文中返回它希望客户端使用的 Keep Alive,客户端必须使用这个保活时间来维持通信。 示例 EMQX 默认由客户端指定保活时间,我们可以打开 EMQX Dashboard(浏览器中输入 http://localhost:18083 即可访问),通过 Management -> MQTT Settings -> General 页面中的 Server Keep Alive 配置项来修改它。 本示例中,我们将它修改为 10 秒: 然后在 Wireshark 中输入以下过滤语句抓取报文:tcp.port == 1883 回到终端窗口,发起一个 MQTT 连接,并将 Keep Alive 设置为 30 秒:mqttx conn --keepalive 30 … Connecting... ✔ Connected 我们将在 Wireshark 中看到 EMQX 在返回的 CONNACK 报文中设置了 Server Keep Alive 属性,且值为 10。连接建立后,客户端也是以 10 秒为间隔发送心跳报文而不是 30 秒: 特性 17: 返回服务端分配的 Client ID 当客户端使用一个长度为 0 的 Client ID 发起连接时,服务端将会为客户端分配一个唯一的 Client ID。在 MQTT 5.0 中,这个分配的 Client ID 可以包含在 CONNACK 报文中返回给客户端。这避免了客户端因为不知道 Client ID 而无法在下一次连接时恢复会话。 示例 在 Wireshark 中输入以下过滤语句抓取报文:tcp.port == 1883 回到终端窗口,发起一个 MQTT 连接,并将 Client ID 设置为一个长度为 0 的字符串:mqttx conn --client-id '' 我们将在 Wireshark 中看到 EMQX 返回的 CONNACK 报文中包含了一个 Assigned Client Identifier 属性,它的值就是 EMQX 为客户端分配的 Client ID: 结语 以上就是 MQTT 5.0 所有特性的基本介绍与演示,你可以试着将演示中的步骤转换成代码然后在你的客户端中复现。如果你希望了解这些 MQTT 5.0 全新特性的更多内容,你可以访问我们的 MQTT Guide,它聚合了所有你需要知道的 MQTT 的知识。 --- ### 137. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、简介 Mica-MQTT是一个基于Java AIO实现的开源组件,旨在提供简单易用、低延迟、高性能的百万级MQTT客户端和物联网Broker服务。它更容易集成到现有服务中,降低自主开发物联网平台的成本。 二、使用场景 Mica-MQTT适用于多种场景,包括但不限于: 物联网云端MQTT Broker 边缘设备之间的消息通信 群组类即时通讯 消息推送 简单易用的MQTT客户端 三、优势 Mica-MQTT的主要优势包括: 简单易用,功能强大 易于二次开发和扩展 高性能,支持百万级连接 四、功能 Mica-MQTT提供了丰富的功能集,包括但不限于: 支持MQTT v3.1、v3.1.1和v5.0协议 支持WebSocket MQTT子协议(兼容mqtt.js) 支持HTTP REST API,详细文档请参见[1] 提供MQTT客户端库 提供MQTT服务端 支持MQTT客户端和服务端的共享订阅 支持MQTT遗嘱消息 支持MQTT保留消息 支持自定义消息处理和转发 提供阿里云MQTT客户端连接示例 支持GraalVM编译成本机可执行程序 快速集成到Spring Boot项目(使用mica-mqtt-spring-boot-starter) 支持与Prometheus和Grafana对接 基于Redis Pub/Sub实现集群,详细信息请参见mica-mqtt-broker模块[2] 五、依赖 Spring Boot项目 客户端依赖 <dependency> <groupId>net.dreamlu</groupId> <artifactId>mica-mqtt-client-spring-boot-starter</artifactId> <version>${mica-mqtt.version}</version> </dependency> 客户端配置示例 mqtt: client: enabled: true # 是否开启客户端,默认:true ip: 127.0.0.1 # 连接的服务端 IP,默认:127.0.0.1 port: 1883 # 端口,默认:1883 name: Mica-Mqtt-Client # 客户端名称,默认:Mica-Mqtt-Client clientId: 000001 # 客户端ID(通常为设备SN,不可重复) user-name: mica # 认证用户名 password: 123456 # 认证密码 timeout: 5 # 超时时间(秒),默认:5秒 reconnect: true # 是否自动重连,默认:true re-interval: 5000 # 重连时间(毫秒),默认:5000毫秒 version: mqtt_3_1_1 # MQTT协议版本,可选MQTT_3_1、mqtt_3_1_1、mqtt_5,默认:mqtt_3_1_1 read-buffer-size: 8KB # 接收数据的缓冲区大小,默认:8KB max-bytes-in-message: 10MB # 消息解析的最大字节数,默认:10MB buffer-allocator: heap # 内存分配器(堆内存或堆外内存),默认:堆内存 keep-alive-secs: 60 # Keep-Alive时间(秒) clean-session: true # MQTT Clean Session,默认:true ssl: enabled: false # 是否开启SSL认证,2.1.0版本开始支持双向认证 keystore-path: # 可选参数:SSL双向认证的密钥库路径,支持classpath:/路径。 keystore-pass: # 可选参数:SSL双向认证的密钥库密码 truststore-path: # 可选参数:SSL双向认证的信任库路径,支持classpath:/路径。 truststore-pass: # 可选参数:SSL双向认证的信任库密码 客户端监听示例 @Service public class MqttClientConnectListener { private static final Logger logger = LoggerFactory.getLogger(MqttClientConnectListener.class); @Autowired private MqttClientCreator mqttClientCreator; @EventListener public void onConnected(MqttConnectedEvent event) { logger.info("MqttConnectedEvent: {}", event); } @EventListener public void onDisconnect(MqttDisconnectEvent event) { // 在客户端离线时更新重连时的客户端ID、用户名和密码 logger.info("MqttDisconnectEvent: {}", event); mqttClientCreator.clientId("newClient" + System.currentTimeMillis()) .username("newUserName") .password("newPassword"); } } 自定义客户端配置示例(可选) @Configuration(proxyBeanMethods = false) public class MqttClientCustomizerConfiguration { @Bean public MqttClientCustomizer mqttClientCustomizer() { return new MqttClientCustomizer() { @Override public void customize(MqttClientCreator creator) { // 在此处可以自定义配置,会覆盖YAML配置 System.out.println("----------------MqttServerCustomizer-----------------"); } }; } } 客户端订阅示例 @Service public class MqttClientSubscribeListener { private static final Logger logger = LoggerFactory.getLogger(MqttClientSubscribeListener.class); @MqttClientSubscribe("/test/#") public void subQos0(String topic, byte[] payload) { logger.info("topic: {} payload: {}", topic, new String(payload, StandardCharsets.UTF_8)); } @MqttClientSubscribe(value = "/qos1/#", qos = MqttQoS.AT_LEAST_ONCE) public void subQos1(String topic, byte[] payload) { logger.info("topic: {} payload: {}", topic, new String(payload, StandardCharsets.UTF_8)); } @MqttClientSubscribe("/sys/${productKey}/${deviceName}/thing/sub/register") public void thingSubRegister(String topic, byte[] payload) { // 1.3.8版本开始支持,@MqttClientSubscribe注解支持${}变量替换,默认替换为+ // 注意:Mica-MQTT会先从Spring Boot配置中替换参数${},如果存在配置将优先被替换。 logger.info("topic: {} payload: {}", topic, new String(payload, StandardCharsets.UTF_8)); } } 共享订阅Topic说明 Mica-MQTT客户端支持两种共享订阅方式: 共享订阅:订阅前缀使用$queue/,多个客户端订阅了$queue/topic,当有消息发布到topic时,只有一个客户端会接收到消息。 分组订阅:订阅前缀使用$share/<group>/,组内的客户端订阅了$share/group1/topic、$share/group2/topic等,当有消息发布到topic时,每个组内只有一个客户端会接收到消息。 MqttClientTemplate使用示例 import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @Service public class MainService { private static final Logger logger = LoggerFactory.getLogger(MainService.class); @Autowired private MqttClientTemplate client; public boolean publish() { client.publish("/test/client", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); return true; } public boolean sub() { client.subQos0("/test/#", (context, topic, message, payload) -> { logger.info(topic + '\t' + new String(payload, StandardCharsets.UTF_8)); }); return true; } } 2. 服务端依赖 <dependency> <groupId>net.dreamlu</groupId> <artifactId>mica-mqtt-server</artifactId> <version>${mica-mqtt.version}</version> </dependency> 2.1 服务端使用 // 注意:为了能够接受更多连接(降低内存占用),请添加JVM参数 -Xss129k MqttServer mqttServer = MqttServer.create() .ip("0.0.0.0") // 服务端IP,默认为空(0.0.0.0),建议不要设置 .port(1883) // 端口,默认:1883 .readBufferSize(512) // 读缓冲区大小,默认:512字节 .maxBytesInMessage(1024 * 100) // 最大包体长度,默认:8092 .authHandler((clientId, userName, password) -> true) // 自定义认证 .messageListener((context, clientId, message) -> { logger.info("clientId: {} message: {} payload: {}", clientId, message, new String(message.getPayload(), StandardCharsets.UTF_8)); }) // 消息监听 .bufferAllocator(ByteBufferAllocator.HEAP) // 内存分配器,默认:堆内存 .heartbeatTimeout(120_1000L) // 心跳超时时间,默认:120秒 .useSsl("", "", "") // SSL配置 .connectStatusListener(new IMqttConnectStatusListener() { @Override public void online(String clientId) { // 客户端上线时的处理逻辑 } @Override public void offline(String clientId) { // 客户端离线时的处理逻辑 } }) // 自定义客户端上下线监听 .messageDispatcher(new IMqttMessageDispatcher() { @Override public void config(MqttServer mqttServer) { // 配置消息分发 } @Override public boolean send(Message message) { // 发送消息 return false; } @Override public boolean send(String clientId, Message message) { // 发送消息给指定客户端 return false; } }) // 自定义消息转发,可使用MQ广播实现集群处理 .debug() // 开启调试信息日志 .start(); // 发送消息给指定客户端 mqttServer.publish("clientId", "/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 发送消息给所有在线监听这个Topic的客户端 mqttServer.publishAll("/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 停止服务 mqttServer.stop(); 六、默认端口 以下是Mica-MQTT的默认端口: MQTT TCP端口:1883 HTTP和WebSocket端口:8083 这些端口用于不同的通信协议和服务。 请注意,上述示例代码可能需要根据你的具体需求进行调整和扩展。如果需要更多信息或帮助,请随时提问。 --- ### 138. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Apache ActiveMQ 部署教程 ActiveMQ (apache.org) Apache ActiveMQ 是一个功能强大的消息代理,用于在分布式应用程序中进行高效的消息传递。本教程将指导您如何在 Windows 和 Unix 平台上安装和配置 Apache ActiveMQ,以便您可以开始在您的应用程序中使用它来处理消息。 步骤 1:满足先决条件 在开始部署之前,请确保满足以下先决条件: 硬件和操作系统要求: 至少有 60MB 的可用磁盘空间,用于安装 ActiveMQ 二进制发行版。 至少有 200MB 的可用磁盘空间,用于安装 ActiveMQ 源码或开发者版。 操作系统:支持 Java 运行时环境(JRE)的 Windows 或 Unix 操作系统。 环境要求: Java 开发工具包(JDK)1.7.x 或更高版本,用于部署和构建 ActiveMQ。请确保您已经安装了 JDK,并设置了 JAVA_HOME 环境变量,指向 JDK 的安装目录,例如:C:\Program Files\jdk.1.7.0_xx_xx。 Maven 3.0 或更高版本(仅在安装源码或开发者版时需要)。您需要将所需的 JAR 文件添加到类路径中。 现在,让我们按照平台分步骤来安装和配置 Apache ActiveMQ。 步骤 2:在 Windows 上安装 Apache ActiveMQ 下载和安装二进制发行版 打开您的 Web 浏览器,导航到 Apache ActiveMQ 的官方网站:http://activemq.apache.org/。 在导航窗格的左侧,单击 "Download" 链接。 在 "Download" 页面上,选择最新的二进制发行版(通常是 Stable Release),并下载对应的 ZIP 文件。文件名类似于 activemq-x.x.x.zip,其中 x.x.x 是版本号。 下载完成后,解压缩 ZIP 文件到您选择的目录。您现在已经安装了 Apache ActiveMQ 二进制发行版。 启动 Apache ActiveMQ 打开 Windows 命令提示符或 PowerShell。 使用 cd 命令切换到 Apache ActiveMQ 安装目录,例如: cd C:\path\to\activemq 请替换 C:\path\to\activemq 为您的实际安装路径。 启动 Apache ActiveMQ 服务,运行以下命令: bin\activemq start 此命令将启动 Apache ActiveMQ 服务,并将其运行在后台。ActiveMQ 默认会监听端口 61616。 测试安装 要测试 Apache ActiveMQ 是否正确安装和运行,请执行以下步骤: 打开 Web 浏览器,并访问 Apache ActiveMQ 的管理控制台:http://localhost:8161/admin 使用默认的用户名和密码(用户名:admin,密码:admin)登录管理控制台。 如果成功登录,您将看到 ActiveMQ 的管理界面。这表示 ActiveMQ 正确安装和运行。 至此,您已经在 Windows 上成功部署和配置了 Apache ActiveMQ。接下来,我们将在 Unix 环境中进行安装。 步骤 3:在 Unix 上安装 Apache ActiveMQ 下载和安装二进制发行版 在您的 Unix 系统上,使用浏览器或命令行工具(如 wget、scp、ftp 等)下载 Apache ActiveMQ 二进制发行版 gzip 文件,例如: wget http://activemq.apache.org/path/tofile/apache-activemq-5.8-tar.gz 请将 URL 替换为正确的下载链接。 下载完成后,使用以下命令解压缩 gzip 文件到您选择的目录,例如: tar zxvf apache-activemq-5.8-tar.gz 您现 在已经安装了 Apache ActiveMQ 二进制发行版。 启动 Apache ActiveMQ 打开终端。 使用 cd 命令切换到 Apache ActiveMQ 安装目录,例如: cd /path/to/activemq 请替换 /path/to/activemq 为您的实际安装路径。 启动 Apache ActiveMQ 服务,运行以下命令: bin/activemq start 此命令将启动 Apache ActiveMQ 服务,并将其运行在后台。ActiveMQ 默认会监听端口 61616。 测试安装 要测试 Apache ActiveMQ 是否正确安装和运行,请执行以下步骤: 打开终端。 使用以下命令检查 ActiveMQ 是否在监听端口 61616 上运行: netstat -an | grep 61616 如果看到结果,表示 ActiveMQ 已成功启动。 至此,在 Unix 系统上成功部署和配置了 Apache ActiveMQ。 步骤 4:配置 Apache ActiveMQ(可选) Apache ActiveMQ 提供了广泛的配置选项,您可以根据您的需求进行自定义配置。默认情况下,ActiveMQ 使用内置的配置文件,但您可以编辑配置文件以满足您的特定需求。 要编辑配置文件,请打开 ActiveMQ 安装目录中的 conf 目录,并找到 activemq.xml 文件。根据您的需求进行修改,然后保存文件。 步骤 5:停止 Apache ActiveMQ 要停止 Apache ActiveMQ 服务,请执行以下步骤: 打开命令提示符或终端。 使用 cd 命令切换到 Apache ActiveMQ 安装目录。 停止 Apache ActiveMQ 服务,运行以下命令: bin/activemq stop 或者您可以使用 CTRL-C 来终止运行 Apache ActiveMQ 的终端会话。 恭喜!您已经成功部署和配置了 Apache ActiveMQ。现在,您可以开始使用它来构建分布式应用程序,实现高效的消息传递功能。 MQTT配置 接入 ActiveMQ 的 MQTT 通信是一种强大的方式,它允许您在应用程序之间进行轻松、实时的消息传递。这个完整的教程将引导您完成以下步骤,以在 ActiveMQ 中启用 MQTT 并创建 MQTT 客户端,从而实现 MQTT 消息的发布和订阅。 步骤 1:准备 ActiveMQ 首先,确保您已经成功安装和配置了 ActiveMQ。如果还没有安装 ActiveMQ,您可以按照 ActiveMQ 官方文档中的指南进行安装和配置:ActiveMQ 官方文档 一旦您的 ActiveMQ 实例正常运行,我们可以开始配置 MQTT。 步骤 2:启用 MQTT 支持 要启用 MQTT 支持,您需要编辑 ActiveMQ 的配置文件。在 ActiveMQ 安装目录下,找到 conf 目录,并编辑 activemq.xml 文件。在文件中,找到以下行: <transportConnectors> <!-- 添加 MQTT 连接器配置 --> </transportConnectors> 在 <transportConnectors> 部分中,添加以下 MQTT 连接器配置: <transportConnectors> <!-- MQTT 连接器配置 --> <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883"/> </transportConnectors> 这将启用 MQTT 服务并将其绑定到 1883 端口。您可以根据需要更改端口号。 然后,保存并关闭 activemq.xml 文件,重新启动 ActiveMQ 以使更改生效。 步骤 3:创建 MQTT 客户端 接下来,我们将创建一个 Python MQTT 客户端来连接到 ActiveMQ 代理并发布/订阅消息。 3.1 安装 MQTT 客户端库 首先,确保您已经安装了 Python。然后,使用以下命令安装 Python 的 MQTT 客户端库,它将帮助我们与 ActiveMQ 的 MQTT 服务通信: pip install paho-mqtt 3.2 创建 MQTT 客户端代码 接下来,创建一个 Python 脚本,用于连接到 ActiveMQ 的 MQTT 代理并发布/订阅消息。以下是一个示例代码: import paho.mqtt.client as mqtt # 连接回调函数 def on_connect(client, userdata, flags, rc): if rc == 0: print("连接成功!") client.subscribe("example/topic") # 订阅主题 else: print(f"连接失败,返回码: {rc}") # 消息接收回调函数 def on_message(client, userdata, message): print(f"收到消息 '{message.payload.decode()}' 来自主题 '{message.topic}'") # 创建 MQTT 客户端 client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message # 连接到 ActiveMQ 的 MQTT 代理 client.connect("localhost", 1883, 60) # 指定 ActiveMQ 代理的地址和端口号 # 保持客户端运行,等待消息 client.loop_forever() 3.3 运行 MQTT 客户端 现在,您可以运行上述 Python 脚本,它将连接到 ActiveMQ 的 MQTT 代理,并订阅名为 "example/topic" 的主题。当有消息发布到这个主题时,客户端将接收并打印消息内容。 python mqtt_client.py 步骤 4:发布和订阅消息 现在,您的 MQTT 客户端已经连接到 ActiveMQ 代理,可以执行以下操作: 发布消息 要发布消息,您可以在 Python 脚本中添加以下代码: # 发布消息 client.publish("example/topic", "这是一条 MQTT 消息") 这将发布一条消息到名为 "example/topic" 的主题。 订阅消息 在 Python 脚本中,您已经设置了订阅的主题: client.subscribe("example/topic") 客户端将自动订阅这个主题,当有消息发布到该主题时,将会触发 on_message 回调函数。 步骤 5:测试和扩展 您现在已经成功接入了 ActiveMQ 的 MQTT 服务,并创建了一个简单的 MQTT 客户端。您可以使用这个基础上进行进一步的测试和扩展,以满足您的应用需求。 一些可能的扩展包括: 创建多个 MQTT 客户端,以模拟多个设备之间的通信。 在 ActiveMQ 中配置用户名和密码,并在客户端中使用这些凭据进行连接。 使用不同的主题来组织和管理消息,以便更好地组织您的消息通信。 希望这个教程对您有所帮助,使您能够成功接入 ActiveMQ 的 MQTT 服务并实现消息的发布和订阅。如果您有任何问题或需要进一步的帮助,请随时提问。 --- ### 139. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 先决条件 要使用Zigbee2MQTT,我们需要以下硬件设备: ZZHA Zigbee 适配器,它是计算机(或服务器)与 Zigbee 无线通信之间的接口。Zigbee2MQTT 支持多种不同类型连接的适配器,如 USB、GPIO 或通过 Wi-Fi 或以太网远程连接的适配器。建议选择以 CC2652 或 CC1352 开头的芯片的适配器。请参阅支持的适配器列表。在安装过程之前,建议查看适配器的推荐详情,以了解是否需要任何额外的配置参数。 Raspberry Pi,这是运行 Zigbee2MQTT 的服务器。大多数 Raspberry Pi 型号都可以运行,但你也可以在许多计算机和平台上运行它,包括 Linux、Windows 和 MacOS。服务器上应安装有 MQTT 代理。Mosquitto(Raspberry Pi 的教程)是推荐的 MQTT 代理,但其他代理也应该可以正常工作。 Zigbee 设备,将与 Zigbee2MQTT 配对的一个或多个 Zigbee 设备。 提示 USB 数据线:为了改善网络范围和稳定性,请使用 USB 扩展线缆。如果你在使用设备时遇到任何问题(如超时、无法配对、设备不可达、设备从网络中断开等),首先检查是否存在干扰。请参阅改善网络范围和稳定性。 安装 你可以以不同的方式运行 Zigbee2MQTT,请参阅安装指南。在这个示例中,我们将使用 Docker 和 Docker Compose 来设置和运行 Zigbee2MQTT。 1.) 查找 Zigbee 适配器1.1) USB Zigbee 适配器在插入适配器后,查看 dmesg 输出以找到设备位置: $ sudo dmesg ... usbcore: registered new interface driver ch341 usbserial: USB Serial support registered for ch341-uart ch341 3-1:1.0: ch341-uart converter detected usb 3-1: ch341-uart converter now attached to ttyUSB0 正如我们所看到的,适配器已被识别并挂载在 ttyUSB0 上。 $ ls -l /dev/ttyUSB0 crw-rw---- 1 root dialout 188, May 16 19:15 /dev/ttyUSB0 在这里,我们可以看到该适配器由 root 拥有,并且所有 dialout 组的用户都可以访问它。 1.2) 网络 Zigbee 适配器Zigbee2MQTT 支持网络 Zigbee 适配器的 mDNS 自动发现功能。如果你的网络 Zigbee 适配器支持 mDNS,则无需知道网络 Zigbee 适配器的 IP 地址,Zigbee2MQTT 将自动检测并配置它。否则,你需要知道网络 Zigbee 适配器的 IP 地址: 将你的适配器连接到 LAN 网络,可以是通过以太网或 Wi-Fi,具体取决于你的适配器。 转到你的路由器/交换机设置,并查找连接设备的列表。 找到你以太网 Zigbee 适配器的 IP 地址。 你还需要知道以太网 Zigbee 适配器的通信端口。在大多数情况下(如 TubeZB、SLZB-06),默认端口为 6638。你可以在适配器的用户手册中查看端口信息。 2.) 设置并启动 Zigbee2MQTT假设你已经安装了 Docker 和 Docker Compose 的最新版本。 首先,我们创建一个文件夹,用于存放项目 mkdir 文件夹名。在文件夹中,我们创建 docker-compose.yml 文件,该文件定义了 Docker 如何运行我们的容器。以下文件包括两个服务,一个用于 MQTT 服务器,另一个用于 Zigbee2MQTT 本身。确保根据你的需求进行调整,并匹配设备挂载,以防适配器未挂载在 /dev/ttyUSB0 上,或者在使用网络适配器的情况下。 version: '3.8' services: mqtt: image: eclipse-mosquitto:2.0 restart: unless-stopped volumes: - "./mosquitto-data:/mosquitto" ports: - "1883:1883" - "9001:9001" command: "mosquitto -c /mosquitto-no-auth.conf" zigbee2mqtt: container_name: zigbee2mqtt restart: unless-stopped image: koenkk/zigbee2mqtt volumes: - ./zigbee2mqtt-data:/app/data - /run/udev:/run/udev:ro ports: - 8080:8080 environment: - TZ=Europe/Berlin devices: - /dev/ttyUSB0:/dev/ttyUSB0 接下来,我们将在 zigbee2mqtt-data 文件夹中创建一个简单的 Zigbee2MQTT 配置文件 configuration.yaml。 # 让新设备加入我们的 Zigbee 网络 permit_join: true # Docker Compose 通过 "mqtt" 主机名使 MQTT 服务器可用 mqtt: base_topic: zigbee2mqtt server: mqtt://mqtt # Zigbee 适配器路径 serial: port: /dev/ttyUSB0 # 启用 Zigbee2MQTT 前端 frontend: port: 8080 # 让 Zigbee2MQTT 在首次启动时生成新的网络密钥 advanced: network_key: GENERATE 对于网络适配器,串行设置应如下: serial: port: tcp://192.168.1.12:6638 其中 192.168.1.112 是你的网络 Zigbee 适配器的 IP 地址,6638 是端口。 如果你的适配器支持 mDNS,则可以省略 IP 地址,并使用以下配置: serial: port: mdns://slzb-06 其中 slzb-06 是你的网络 Zigbee 适配器的 mDNS 名称。 现在,我们应该在我们的目录中有两个文件,可以启动这个堆栈: $ find ./docker-compose.yml ./zigbee2mqtt-data/configuration.yaml # 首次启动 $ docker compose up -d # 检查日志 $ docker compose logs -f 经过一段时间后,你应该看到一些日志消息,说明 Mosquitto 和 Zigbee2MQTT 已经在运行。你可以使用 http://localhost:8080(或远程服务器的主机名)打开前端。 现在,我们可以继续配对我们的第一个设备。 连接设备 查找你的设备的支持设备列表,并按照说明进行配对。 如果没有提供说明,该设备可能可以通过恢复出厂设置来进行配对。 一旦你在日志中看到类似下面的内容,你的设备就已经配对成功了,你可以开始使用前端和 MQTT 消息来控制它。 Zigbee2MQTT:info 2019-11-09T12:19:56: Successfully interviewed '0x00158d0001dc126a', device has successfully been paired 注意 重要的是在初始设置完成后,将 permit_join 设置为 false,以保持 Zigbee 网络的安全性,防止其他 Zigbee 设备的意外加入。 --- ### 140. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着物联网技术的不断发展,越来越多的设备需要能够实时监测环境数据并与云平台进行通信。本教程将介绍如何使用ESP8266微控制器、DHT传感器以及MQTT协议,创建一个简单的温湿度传感器,将数据发送到MQTT云平台上,实现实时监测和数据可视化。 所需材料 在开始之前,确保你准备好以下材料: ESP8266开发板(例如NodeMCU) DHT传感器(DHT11或DHT22) 一台电脑 USB数据线 无线网络(Wi-Fi)接入点 一个MQTT云平台账户 硬件连接 将DHT传感器连接到ESP8266开发板。在本示例中,我们将DHT传感器的数据引脚连接到GPIO 5(D1引脚)。 连接ESP8266到计算机,确保你可以通过Arduino IDE或其他编程工具进行编程。 配置Arduino IDE 在你的计算机上打开Arduino IDE,并确保已安装ESP8266开发板支持。接下来,我们将使用Arduino IDE来编写和上传代码到ESP8266开发板。 编写Arduino代码 下面是示例Arduino代码,用于读取DHT传感器的温湿度数据,并将其发布到MQTT云平台。代码的详细解释见下文。 #include <ESP8266WiFi.h> // 引入ESP8266WiFi库 #include <PubSubClient.h> // 引入MQTT客户端库 #include <DHT.h> // 引入DHT库 #define DHTPIN 5 // 定义DHT传感器连接的GPIO端口号为5(对应于D1) #define DHTTYPE DHT11 // 定义DHT传感器类型为DHT11 DHT dht(DHTPIN, DHTTYPE); // 初始化DHT传感器对象 const char* ssid = "218"; // WiFi账号 const char* password = "A1b2c3d4...5"; // WiFi密码 const char* mqtt_server = "iot.mqtt.cn"; // MQTT服务器地址 const int mqtt_port = 1883; // MQTT服务器端口号 const char* mqtt_clientID = "4QR8TZ9ThuL4G"; // MQTT客户端ID; 4QR8TZ9ThuL4G替换成自己的设备号SN const char* mqtt_user = "ceshi"; // MQTT用户名;替换成自己Modbus云平台账户名 const char* mqtt_password = "123456"; // MQTT密码;替换成自己Modbus云平台密码 const char* mqtt_pub_topic = "/dev/coo/4QR8TZ9ThuL4G"; // MQTT发布主题; 4QR8TZ9ThuL4G替换成自己的设备号SN const char* mqtt_sub_topic = "/server/coo/4QR8TZ9ThuL4G"; // MQTT订阅主题; 4QR8TZ9ThuL4G替换成自己的设备号SN WiFiClient espClient; // WiFi客户端对象 PubSubClient client(espClient); // MQTT客户端对象 // 连接WiFi的函数 void setup_wifi() { delay(10); Serial.println(); Serial.print("连接到 "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi已连接"); Serial.println("IP地址: "); Serial.println(WiFi.localIP()); } // 发布消息的函数 void publish_message() { float humidity = dht.readHumidity(); // 读取湿度 float temperature = dht.readTemperature(); // 读取温度 char msg[200]; snprintf(msg, sizeof(msg), "[ { \"sensor_device_id\":1 , \"port_id\":1 , \"sdata\":%.1f }, { \"sensor_device_id\":1 , \"port_id\":2 , \"sdata\":%.1f } ]", temperature, humidity); client.publish(mqtt_pub_topic, msg); // 发布消息到MQTT服务器 } // MQTT消息回调函数 void callback(char* topic, byte* payload, unsigned int length) { Serial.print("接收到消息 ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); } // 重新连接MQTT服务器的函数 void reconnect() { while (!client.connected()) { Serial.print("尝试连接MQTT服务器..."); if (client.connect(mqtt_clientID, mqtt_user, mqtt_password )) { Serial.println("已连接"); client.subscribe(mqtt_sub_topic); } else { Serial.print("失败,rc="); Serial.print(client.state()); Serial.println(" 5秒后再次尝试"); delay(5000); } } } // 设置串口,WiFi,MQTT服务器和端口,回调函数 void setup() { Serial.begin(115200); // 设置串口波特率为115200 setup_wifi(); // 设置WiFi client.setServer(mqtt_server, mqtt_port); // 设置MQTT服务器和端口 client.setCallback(callback); // 设置MQTT回调函数 dht.begin(); // 开始读取DHT传感器数据 } void loop() { if (!client.connected()) { // 如果未连接到MQTT服务器 reconnect(); // 重新连接 } client.loop(); // 执行MQTT客户端循环 publish_message(); // 发布消息 delay(10000); // 延迟10秒后,再次发布 } 代码解释 首先,我们引入了所需的库,包括ESP8266WiFi库、PubSubClient库(用于MQTT通信)、以及DHT库(用于与DHT传感器通信)。 我们定义了DHT传感器连接的GPIO引脚(DHTPIN)和传感器类型(DHTTYPE)。 接下来,我们配置了WiFi连接的相关信息,包括WiFi账号和密码。 针对MQTT通信,我们配置了MQTT服务器的地址、端口、客户端ID、用户名和密码,以及发布和订阅的主题。 我们创建了WiFiClient对象和PubSubClient对象,后者将用于与MQTT服务器建立连接和发送消息。 在setup_wifi函数中,我们初始化WiFi连接。 publish_message函数用于读取DHT传感器的温湿度数据,并将其封装为JSON格式的消息,然后发布到MQTT服务器。 callback函数是MQTT消息回调函数,用于处理从MQTT服务器接收到的消息。 reconnect函数用于重新连接MQTT服务器,如果连接失败,它会定时重试。 在setup函数中,我们初始化串口通信、WiFi连接、MQTT客户端,以及DHT传感器。 最后,在loop函数中,我们不断检查MQTT连接状态,执行MQTT客户端的循环操作,发布温湿度数据,并通过延迟等待一段时间来控制数据发布的频率。 总结 通过上述步骤,你可以创建一个基于ESP8266的温湿度传感器,并将其数据发送到MQTT云平台上。这个示例可以作为IoT项目的基础,你可以根据自己的需求扩展功能,例如添加更多传感器、设置数据存储、或者创建数据可视化界面。希望这个教程对你有所帮助,让你更好地理解如何使用ESP8266和MQTT构建物联网应用。 --- ### 141. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在使用MQTT协议进行通信时,建立连接是首要步骤之一。MQTT协议为了满足不同物联网应用的需求,提供了丰富的连接参数。这些参数决定了通信的可靠性、安全性和性能。本文将深入探讨MQTT连接过程中各个关键参数的作用和设置方式,帮助开发者正确配置MQTT连接以满足其项目的要求。 MQTT连接的基本概念 MQTT连接是由客户端发起到服务器端的,任何运行MQTT客户端库的设备或程序都可以成为MQTT客户端。MQTT服务器则负责接收客户端的连接请求,并负责将客户端的消息传递给其他符合条件的客户端。连接过程主要分为以下几个步骤: 连接建立(Connect): 客户端向服务器发送一个CONNECT数据包,包含了连接所需的信息。服务器接收后进行验证。 连接确认(Connack): 服务器根据验证结果,回复一个CONNACK数据包给客户端,表示连接建立成功或失败。 通信交互(Communication): 连接建立后,客户端和服务器可以相互交换消息。 连接关闭(Disconnect): 客户端或服务器可以随时关闭连接。 通常情况下,MQTT使用TCP/IP协议进行网络传输,但同时也支持WebSocket和UDP等网络传输方式。 MQTT连接参数的使用 在建立MQTT连接时,以下是一些关键参数及其作用: 连接地址(Connection Address) MQTT连接地址通常由服务器IP或域名、服务器端口和连接协议组成。 基于TCP的MQTT连接通常使用mqtt协议,端口一般为1883。 使用TLS/SSL加密的MQTT连接通常使用mqtts协议,端口一般为8883。 基于WebSocket的MQTT连接使用ws协议,端口一般为8083。 基于WebSocket的安全连接使用wss协议,端口一般为8084。 例如,mqtt://broker.example.com:1883表示基于TCP的MQTT连接地址。 客户端ID(Client ID) 每个连接到MQTT服务器的客户端都必须有唯一的客户端ID。客户端ID通常是1到23个字节的UTF-8字符串。如果多个客户端使用相同的客户端ID连接到服务器,服务器将踢掉已存在的连接。 用户名和密码(Username & Password) MQTT协议支持通过用户名和密码进行认证和授权。这些信息通常以明文方式传输,因此在安全性要求高的情况下,建议使用mqtts或wss协议。 连接超时(Connect Timeout) 连接超时指的是等待服务器响应的最大时间。如果在连接超时内未收到服务器的响应,连接将被视为失败。 保活周期(Keep Alive) 保活周期是一个以秒为单位的时间间隔,用于在无消息传输时发送心跳包以保持连接。服务器会在1.5倍保活周期内未收到客户端的任何消息时断开连接。 清除会话(Clean Session) 清除会话参数决定了在客户端断开连接后,服务器是否保留会话信息。为false时表示创建持久会话,会话保留并保存离线消息直到会话超时注销。为true时表示创建新的临时会话,在客户端断开时会话自动销毁。 遗嘱消息(Last Will) 遗嘱消息是为那些可能意外断线的设备提供的,用于在异常下线时向其他客户端发送通知。它包含主题、消息内容、QoS和Retain等信息。 协议版本(Protocol Version) MQTT协议有多个版本,包括v3.1、v3.1.1和v5.0。通常情况下,推荐使用MQTT v5.0版本,因为它支持更多高级特性。 连接属性(Connect Properties) MQTT v5.0引入了连接属性的概念,进一步增强了协 Modbus物联网云平台:议的可扩展性。 建立安全的MQTT连接 虽然MQTT协议提供了用户名、密码、Client ID等认证机制,但对于物联网安全性来说,还需要采取额外的措施。传统的TCP通信使用明文传输,存在窃听、篡改、伪造等风险。因此,建议启用SSL/TLS加密来确保通信的安全性。 不同MQTT服务器对SSL/TLS的支持方式不同,通常包括单向认证和双向认证。单向认证仅验证服务器证书,而双向认证要求服务器和客户端都提供证书进行身份认证。 在物联网应用中,安全性至关重要,因此建议开发者采用SSL/TLS加密,并根据项目需求选择合适的认证方式,以确保通信的安全性和完整性。 结论 建立MQTT连接是使用MQTT协议的第一步,正确配置连接参数对于实现可靠、安全和高性能的物联网应用至关重要。本文详细介绍了各种连接参数的作用和设置方式,以及如何确保安全的MQTT连接。开发者可以根据项目需求灵活配置这些参数,从而构建出适用于特定场景的MQTT连接。 --- ### 142. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT 发布/订阅模式的深入解析 MQTT(Message Queuing Telemetry Transport)协议作为一种轻量级、高效的消息传输协议,在物联网和远程通信领域广泛应用。其中,MQTT 的发布/订阅模式(Publish-Subscribe Pattern)作为其核心特性之一,发挥着关键作用。在本文中,我们将深入探讨 MQTT 发布/订阅模式的工作原理、关键概念以及与其他通信模式的比较。 MQTT 发布/订阅模式简介 发布订阅模式是一种消息传递模式,其核心思想是将消息的发送者(发布者)和消息的接收者(订阅者)解耦,使它们无需直接联系。发布者将消息发送到一个中介角色(代理或经纪人),而订阅者则向这个中介角色注册自己对特定消息的兴趣。中介角色负责消息的路由和分发,确保每个订阅者都能接收到其感兴趣的消息。 在 MQTT 中,这个中介角色通常被称为代理(Broker)。代理接收发布者发送的消息,并将其传递给所有订阅了相关主题的订阅者。主题(Topic)是 MQTT 中的关键概念,用于对消息进行分类和路由。发布者在发布消息时指定一个主题,而订阅者则订阅一个或多个主题以接收相关消息。 MQTT 发布/订阅模式的组成部分 MQTT 发布/订阅模式包括四个主要组成部分: 发布者(Publisher): 发布者负责将消息发布到一个或多个主题上。每个消息都会带有一个主题,发布者不需要关心订阅者是否在线或是否存在。 订阅者(Subscriber): 订阅者通过订阅一个或多个主题来接收感兴趣的消息。MQTT 允许订阅者同时订阅多个主题,这为灵活的消息过滤和路由提供了支持。 代理(Broker): 代理是消息路由的核心。它接收发布者的消息并将其转发给所有订阅了相关主题的订阅者。代理还负责处理客户端的连接、断开连接、订阅和取消订阅请求。 主题(Topic): 主题是 MQTT 消息路由的基础。它类似于消息的地址,使用斜杠(/)进行分层。主题的结构是树状的,允许更好地组织和分类消息。每个主题可以有多个发布者和订阅者,代理会将消息按照主题的结构路由到正确的订阅者。 MQTT 发布/订阅的消息路由 在 MQTT 的发布/订阅模式中,消息路由是关键环节。当发布者发布一条消息时,它将消息发送给代理,然后代理负责将消息路由到订阅了相关主题的所有订阅者。这种路由方式有两种主要方式: 根据主题(Topic): MQTT 订阅者通过订阅主题来接收消息。发布者发送的每条消息都包含一个主题,代理根据消息的主题将其路由给订阅了相同主题的订阅者。这种方式保证了消息的精确传递。 根据消息内容: MQTT 5.0 版本引入了请求响应特性,使订阅者能够向某个主题发送应答,以实现消息内容过滤。这样,订阅者可以定义消息的属性或内容,只有当消息满足订阅者定义的条件时,才会被传递给订阅者。 MQTT 与其他通信方式的比较 MQTT 的发布/订阅模式与其他通信方式,如HTTP请求响应和消息队列,有一些关键区别: 与HTTP请求响应的比较: MQTT消息最小化网络开销:MQTT的消息头部非常小,相比HTTP占用更少的网络带宽。 MQTT支持双工通信:MQTT基于发布/订阅模式,支持双工通信,而HTTP基于请求响应,需要轮询来获取数据更新。 MQTT有状态:MQTT具有会话感知能力,能够时刻知道设备是否在线,而HTTP是无状态的,无法实现从连接异常断开中恢复。 与消息队列的比较: MQTT面向海量设备:MQTT专注于物联网设备之间的消息传递,适用于海量设备接入和消息传输。 主题无需提前注册:MQTT中的主题无需提前创建或注册,由客户端自动创建,无需手动管理。 消息队列主要用于服务器之间的消息传递:消息队列通常用于服务器应用之间的消息存储和转发,数据量大但客户端数量相对较少。 在实际应用中,MQTT和消息队列通常会结合使用,以实现物联网设备与业务系统之间的高效消息传递。 结论 MQTT的发布/订阅模式是其核心特性之一,为物联网和远程通信提供了强大的消息传输能力。通过将消息的发送者与接收者解耦,MQTT使得设备之间的通信更加灵活和高效,是物联网领域的重要通信协议。 --- ### 143. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT 协议深度解析 MQTT(Message Queuing Telemetry Transport)是一种轻量级、高效的消息传输协议,特别为物联网(IoT)和远程通信应用设计。MQTT 的出现旨在解决低带宽、高延迟、不稳定网络环境下的通信需求。它的设计初衷是提供一种快速、可靠、节省带宽的方式,用于设备之间的实时通信,如传感器、嵌入式设备、智能家居、车联网等领域。本文将深度解析 MQTT 协议的关键特性和应用场景。 MQTT 协议的历史 MQTT 协议最早由 IBM 的 Andy Stanford-Clark 和 Arlen Nipper(现在是 Cirrus Link 的一部分)于 1999 年共同创建。最初,这项协议被设计用于监控遥测设备在远程管道监控系统中的数据传输。它的目标是通过极少的数据开销,在低带宽和高延迟的卫星链路上实现设备之间的实时数据通信。 Arlen Nipper 在解释 MQTT 的命名来源时提到,MQTT 原名为 "MQ TT",中间有一个空格,代表着 "MQ Telemetry Transport"。这个名字反映了该协议的本质,即通过消息传输实现遥测(Telemetry)数据的交流。 MQTT 协议的关键特性 1. 简单易实现 MQTT 协议的设计追求简洁性,协议头部仅占用 2 个字节,消息格式清晰简单。这使得它非常容易实现,即使是在资源受限的嵌入式设备上也能运行。 2. 支持多种服务质量等级(QoS) MQTT 提供了三种不同的服务质量等级: QoS 0: 最多传递一次,消息可能会丢失。 QoS 1: 至少传递一次,可保证消息到达,但可能会重复。 QoS 2: 仅传递一次,保证消息只到达一次。 这种灵活性使得 MQTT 能够适应不同应用的可靠性需求。 3. 轻量级和节省带宽 MQTT 的协议头部非常紧凑,消息传输时开销极小。这使得它适用于带宽有限的网络,尤其是对于 IoT 设备来说,可以有效降低通信成本。 4. 双向通信 MQTT 基于发布/订阅模式,支持双向通信,即设备既可以发布消息,也可以订阅消息。这使得实时双向通信成为可能,非常适用于 IoT 场景。 5. 安全性 MQTT 协议支持 TLS/SSL 加密,提供了数据传输的安全性。此外,它还提供了用户名和密码认证机制,确保只有授权的设备能够连接和通信。 6. 在线状态感知 MQTT 使用心跳保活机制,保持连接活跃。如果客户端长时间不活动,服务器可以感知到并主动断开连接。同时,遗愿(Last Will)消息机制允许客户端在意外下线时发布一条指定的消息,通知其他设备。 MQTT 协议的应用场景 MQTT 协议在众多领域中都得到广泛应用,其中包括但不限于: 1. 物联网(IoT) MQTT 是物联网通信的首选协议之一。它能够轻松应对数以百万计的 IoT 设备连接,确保设备之间的实时通信。无论是智能家居、智能城市、工业自动化还是农业领域,MQTT 都为 IoT 应用提供了可靠的消息传输方式。 2. 移动互联网 在移动应用中,MQTT 可用于推送通知、实时聊天和数据同步。它能够在移动设备和服务器之间建立可靠的通信通道,保证消息的即时传递。 3. 智能硬件 智能硬件和嵌入式设备可以使用 MQTT 实现与云端的通信。这包括智能传感器、智能车辆、智能家电等设备,通过 MQTT 实现数据传输和远程控制。 4. 车联网 MQTT 协议也在车联网应用中广泛使用。它可以用于车辆之间的实时通信,包括车辆监控、远程诊断、固件升级等功能。 5. 远程医疗 远程医疗设备可以使用 MQTT 实现与医疗服务器的连接,以传输患者数据、监测设备状态和远程诊断。 6. 电力和能源 MQTT 协议在电力监控和能源管理方面具有重要应用。它可以用于监测电力设备、实现智能电网通信和实时能源数据传输。 结语 MQTT 协议以其简单、高效、可靠的特性,以及在各种应用场景中的广泛应用而闻名。它为物联网和远程通信提供了强大的消息传输能力,使得设备之间的互联变得更加容易和可靠。随着物联网的不断发展,MQTT 仍然是一项关键的技术,将在未来继续发挥重要作用。无论是在智能家居、智慧城市还是工业自动化中,MQTT 都将继续发挥其重要作用,推动物联网的发展。 --- ═══════════════════════════════════════════ ## MQTT 新闻 ═══════════════════════════════════════════ ### 144. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着物联网(IoT)、大数据和人工智能(AI)的迅速发展,工业自动化领域也在加速推进物联网战略,推出各自的 IoT 和数字化解决方案。在这一过程中,作为主流物联网协议之一的 MQTT 协议,因其轻量、灵活和高效的特点,成为了各大自动化设备厂商关注的重点。为了加速实现工业物联网(IIoT)的互联互通,各大厂商纷纷开始在可编程逻辑控制器(PLC)中集成 MQTT 协议,以简化 PLC 数据的采集和传输,促进工业数据的高效利用。 当前的工业 PLC 数据采集 PLC,即可编程逻辑控制器,是工业自动化领域的核心设备,广泛应用于各个工业领域。从 PLC 问世至今,一直表现出强大的生命力和高速增长态势,2020 年全球 PLC 市场的销售量已经达到了百亿 RMB 级别。德国产业界将 PLC 在生产工艺自动化过程中的广泛应用定义为「工业 3.0」,其代表了各类数控机床、工业机器人等单机自动化设备在生产环节的推广及应用。而将无处不在的传感器、PLC、智能控制系统、通信设施通过 ICT 技术形成一个智能网络,使人与人、人与机器、机器与机器及服务与服务之间能够互联,则是「工业 4.0」的核心要义。人、物、数据通过物联网技术进行流程再造,由单机智能升级为万物互联的智能。 实现工业场景下的万物互联离不开对工业自动化设备的数据采集。其中 PLC 常用的工业现场总线协议就多达数十种,此外各大 PLC 厂商基本都有各自的私有总线协议。由于现场总线种类繁多各异,传统的工业 PLC 数据采集一般通过在设备侧部署边缘网关的方式进行:使用边缘网关将各类协议统一,再将 PLC 数据采集及汇聚,转发到 IoT 平台,以此实现设备间的数据互联。 主流厂商的 MQTT 集成案例 西门子(Siemens) 西门子作为工业自动化领域的领导者,已经将 MQTT 客户端功能封装成 PLC 的库文件。通过西门子 S7-1200 和 S7-1500 系列 PLC,可以实现基于 MQTT 3.1.1 协议的数据上报。这样一来,PLC 能够轻松连接到 MQTT 消息服务器,进行高效的数据传输和通信。这种集成方式极大地方便了工业现场数据的采集与传输,为智能制造提供了强有力的支持。 倍福(Beckhoff) 德国倍福公司推出了 TF6701 IoT 通讯库,通过 MQTT 协议可以将 PLC 数据直接发送到各大公有云 IoT 平台以及 MQTT 消息服务器。TF6701 通讯库还支持将 PLC 中的数据封装成 JSON 格式,进行数据上报,实现 OT(操作技术)和 IT(信息技术)领域的数据格式统一。这种数据格式的统一化,不仅提高了数据的可读性和兼容性,还为数据分析和处理提供了便利。 菲尼克斯(Phoenix Contact) 菲尼克斯推出的 PLCnext 开放式控制平台,采用 RT-Linux 操作系统,除了传统的 PLC 编程功能外,还支持 C、Java、Python、JS 等高级语言编程。这使得 PLC 可以通过 MQTT SDK 灵活接入物联网平台,实现更加灵活和多样化的数据采集和应用。PLCnext 平台的这种开放性和灵活性,为工业物联网应用提供了更多的可能性和创新空间。 MQTT 在工业 PLC 中的应用与优势 高效的数据传输MQTT 协议采用发布/订阅模式,这种模式非常适合工业环境中的数据传输。它能够在低带宽和不稳定的网络环境中高效地传输数据,确保数据的及时性和可靠性。 简化的数据采集通过将 MQTT 协议集成到 PLC 中,可以简化数据采集流程。PLC 直接通过 MQTT 协议将数据发送到消息服务器或云平台,无需复杂的中间件和协议转换,降低了系统的复杂性和维护成本。 增强的灵活性和可扩展性MQTT 协议支持灵活的主题和消息过滤机制,可以根据需要动态调整数据的传输和处理方式。这种灵活性使得系统可以根据实际需求进行扩展和调整,提高了系统的可扩展性和适应性。 跨平台的数据互操作性由于 MQTT 协议被广泛支持,PLC 通过 MQTT 协议可以与各种不同的平台和设备进行数据交互,实现跨平台的数据互操作性。这种互操作性为构建开放、互联的工业物联网系统提供了基础。 MQTT 在未来工业物联网中的作用 随着工业物联网的不断发展,MQTT 协议在未来将发挥越来越重要的作用。以下是 MQTT 在未来工业物联网中的一些重要作用: 推动智能制造的实现MQTT 协议的高效数据传输和灵活应用,将推动智能制造的实现。通过实时采集和传输生产数据,企业可以进行精细化管理和优化,提高生产效率和产品质量。 支持大规模设备互联随着工业物联网设备数量的增加,MQTT 协议的高并发和高扩展性特点,使其能够支持大规模设备的互联互通,构建庞大的工业物联网生态系统。 促进数据驱动的决策通过 MQTT 协议,工业现场的数据能够及时传输到云端进行存储和分析,企业可以基于这些数据进行实时监控和数据驱动的决策,提高运营效率和响应速度。 增强系统的安全性和可靠性MQTT 协议支持多种安全机制,如 SSL/TLS 加密和用户认证,能够有效保障数据传输的安全性和可靠性,确保工业物联网系统的稳定运行。 总之,随着工业自动化和物联网技术的不断融合发展,MQTT 协议在工业 PLC 数据采集与应用中发挥着越来越重要的作用。通过集成 MQTT 协议,工业企业可以实现高效的数据采集和传输,推动智能制造和工业物联网的快速发展,为实现更加智能化和高效化的工业生产奠定坚实基础。 --- ### 145. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 简介 MQTT 是一种轻量级的发布/订阅消息传输协议,专为连接资源受限的设备而设计。它被广泛应用于工业控制、物联网、移动应用等领域,近年来也越来越受到边缘计算和人工智能领域的关注。 起源 MQTT 诞生于 1999 年,最初由 Arcom(现为 Eurotech)的 Arlen Nipper 和 IBM 的 Andy Stanford-Clark 共同开发。当时,工业控制领域普遍采用轮询机制来采集设备数据,但这种方式存在效率低、网络负载高的问题。为了解决这些问题,Nipper 和 Clark 提出了 MQTT 协议。 MQTT 最初的名称为“Argo 轻量级有线协议”(Argo Lightweight On The Wire Protocol),后来改名为“MQ Integrator Pervasive Device Protocol”(MQIpdp)。1999 年,MQTT 协议 1.0 版本发布。 发展历程 MQTT 协议在发布后迅速得到了业界的认可,并被广泛应用于各种工业控制系统中。2003 年,IBM 和 Eurotech 联合成立了 MQTT 协议工作组,负责 MQTT 协议的标准化工作。2010 年,MQTT 协议 3.1 版本发布,成为 MQTT 协议的正式标准。 MQTT 协议 3.1 版本发布后,MQTT 协议得到了更加广泛的应用,并开始在物联网领域得到应用。2018 年,MQTT 协议 5.0 版本发布,增加了新的功能,例如共享订阅、离线消息等,更加适应物联网应用的需求。 MQTT 协议的特点 MQTT 协议具有以下特点: 轻量级:MQTT 协议的报文非常小,适合资源受限的设备。 简单易用:MQTT 协议的语法简单易懂,易于开发和使用。 可扩展性强:MQTT 协议支持发布/订阅模式,可以连接大量设备。 可靠性高:MQTT 协议支持多种消息质量等级,可以确保消息的可靠传输。 MQTT 协议的应用 MQTT 协议被广泛应用于工业控制、物联网、移动应用等领域。 工业控制:在工业控制领域,MQTT 协议被用于连接传感器、执行器等设备,实现数据的采集和控制。例如,在智能工厂中,MQTT 协议可以用于连接生产线上的各种设备,实现数据的实时采集和分析,从而提高生产效率。 物联网:在物联网领域,MQTT 协议被用于连接各种智能设备,实现数据的采集和分析。例如,在智能家居中,MQTT 协议可以用于连接智能灯、智能门锁等设备,实现远程控制和管理。 移动应用:在移动应用领域,MQTT 协议被用于实现移动应用的实时通信。例如,在聊天软件中,MQTT 协议可以用于实现用户之间的实时消息推送。 MQTT 协议在边缘计算和人工智能中的应用 近年来,MQTT 协议也越来越受到边缘计算和人工智能领域的关注。 边缘计算:在边缘计算中,MQTT 协议可以用于连接边缘设备,实现数据的本地处理和分析。例如,在工业物联网中,MQTT 协议可以用于连接边缘网关,实现数据的过滤和预处理,从而减轻云端服务器的负载。 人工智能:在人工智能中,MQTT 协议可以用于连接人工智能模型,实现模型的部署和应用。例如,在智能城市中,MQTT 协议可以用于连接人脸识别模型,实现实时的人脸识别。 总结 MQTT 协议是一种简单、轻量级、可靠的消息传输协议,在工业控制、物联网、移动应用等领域得到广泛应用。近年来,MQTT 协议也越来越受到边缘计算和人工智能领域的关注。随着这些领域的快速发展,MQTT 协议的应用前景将会更加广阔。 --- ### 146. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 HiveMQ为解决诸多性能挑战(从不可靠的公共基准测试到云部署中的噪音邻居)提出了一个解决方案,这个过程历时数月,最终诞生了自动化系统基准测试。 系统基准测试是一组围绕自动化基准测试和基准案例的工具,代表了客户的工作负载。工程师在开发和质量保证期间都会使用系统基准测试。在开发阶段,系统基准测试被用作设计辅助工具,帮助工程师快速迭代众多解决方案,并选择最佳方案。而在质量保证阶段,目的是不同的。在这个阶段,系统基准测试帮助发现生产代码中的性能回归问题,确保系统在发布给客户之前不会表现得更差。 自动化系统基准测试可以在各种云环境中执行,这要归功于Terraform。在本部分中,我们将重点放在被HiveMQ客户广泛使用的AWS平台上。 自动化系统基准测试概述 系统基准测试跨越了两个组织域——AWS(云提供商)和HiveMQ。 HiveMQ域包含系统基准测试代码库和运行Jenkins的自动化服务器。代码库包含管理、汇总和验证性能测试结果的自动化脚本(主要用Python编写)以及基准测试案例。每个基准案例包括三个组件:要评估的指标列表、Terraform配置(特别是虚拟机类型及其数量以及MQTT Broker配置)和HiveMQ Swarm场景。HiveMQ Swarm场景指定了在负载生成期间将执行的测试阶段。想了解更多关于HiveMQ Swarm的信息,请查看其产品页面。简而言之,这个负载测试工具读取脚本文件,创建并管理客户端,驱动它们通过多个阶段,如连接、订阅、发布、取消订阅和断开连接,并进行偶尔的条件检查。 AWS域包含测试部署和历史数据的持久存储。测试部署只在实验运行期间存在,一旦实验结束,测试部署将完全拆除以避免资源浪费。测试部署包括负载测试工具(HiveMQ Swarm)的部署、被测试的MQTT Broker(HiveMQ Broker)的部署以及监控基础设施(InfluxDB和Grafana)。负载测试工具和MQTT Broker都运行在多个虚拟机上,而监控则只需一台虚拟机。即使每次运行后测试部署被拆除,自动化工具会提取结果,处理并验证,然后将结果添加到AWS Athena中的测试结果历史记录中。 下图显示了组织域的概述。灰色区域表示组织域。大白框分别组连接代码库和测试部署的元素。绿色框表示永久存在的实体,而黄色框表示临时实体。 触发系统基准测试 有多种方式触发系统基准测试。在HiveMQ,我们谨慎地进行此操作。如果更改不涉及任何性能关键组件,则无需运行完整的性能测试。但是,如果有必要,可以手动触发相应的Jenkins任务,只需将Jenkins指向正确的分支,指定所需的迭代次数和场景细节(如有需要),然后点击“构建”按钮即可。 Jenkins用于自动化系统基准测试 系统基准测试运行的报告将包含所有相关指标及其一些数值。如果某个指标未通过验证,则会标记为红色。如果其性能超过预期,则会标记为绿色,否则,像下面的示例截图中的所有指标一样,都是普通的黑色。 系统基准测试报告 即使工程师不触发系统基准测试,它们仍会在主分支上每周运行两次的计划任务中运行。这种安全网可以在发布前及早发现可能的性能回归问题。 系统基准测试:收集和汇总 为了确保收集的性能结果代表系统行为,Jenkins每个基准案例都会运行多次。具体次数由工程师决定,但默认次数为三次。遵循最高的质量保证标准,每个基准案例执行前都会创建并销毁独立的测试部署。 在销毁测试部署之前,运行自动化脚本的Jenkins会将基准案例中指定的相关指标收集到简单的CSV文件中。一旦基准案例的所有执行完成,结果将汇总到所有迭代中。我们对结果应用各种汇总,从计算普通平均值到百分位数和标准差。一旦整个系统基准测试运行完成,文件将被推送到AWS Athena中进行“永久存储”。在那里,工程师可以提取汇总的性能结果并使用Athena的查询功能进行分析(请参见下面的截图)。 使用Athena的查询功能提取汇总的性能结果并进行分析 案例完成:MQTT Broker的全面基准测试 我提到过,HiveMQ的系统基准测试包含多个基准案例。每个基准案例专注于系统行为的某个特定方面,无论是特定的MQTT服务质量级别、某些虚拟机实例的大小,还是某种负载模式。有时,这些方面是结合在一起的。 这些基准案例共同构成了我所谓的全面基准测试。这个造词描述了一种在评估MQTT Broker性能方面达到全面性的能力。这是系统基准测试的一个重要特征,因为MQTT协议不仅提供了各种调优选项,如QoS级别、订阅类型和到期时间,而且在将其用例引入HiveMQ MQTT平台的各个行业中,设置和负载模式及其量级差异巨大。 让我们深入探讨涵盖HiveMQ平台在生产中面临的80%场景的核心基准案例。合成这些基准测试时涉及以下测试维度: 实例类型(多核心与常规核心数量); 实例数量(小型部署或大型部署); 消息分发模式(一个发布者到一个订阅者,多个发布者到一个订阅者,和一个发布者到多个订阅者); 订阅类型(独占或共享); 消息负载大小(小或大); 服务质量级别(QoS0,QoS1和QoS2); 负载模式(突发的发布高峰或稳定的); 主要评估特性(延迟测试或吞吐量测试)。 空闲连接案例 此案例评估单个HiveMQ节点在六分钟内建立一百万个连接的能力。虽然不会将Broker最大化,但此测试作为安全网,以防止HiveMQ Broker节点常规处理的连接数量回归问题。 发布(PUBLISH)汇聚案例 此案例评估四节点HiveMQ集群在每秒30,000个发布包总输入速率下,将30,000个发布客户端的发布包汇聚到仅十个订阅中的能力。此案例提供了对HiveMQ Broker出站消息分发子系统性能的洞察。 发布(PUBLISH)扩散案例 这是汇聚的相反操作。它也在相同的AWS部署配置上运行,使用四个节点。这次,每个由200个发布者组生成的发布包通过Broker分发到250个订阅者的队列中。此案例是深入了解HiveMQ Broker入站消息分发子系统性能的宝贵工具。 发布(PUBLISH)突发案例 一些客户(主要在联网汽车领域)面临着负载的急剧增加和减少。此基准案例尝试通过短期测试来捕捉这种情况。两万个发布者在五个短批次中将其负载推送到两万个订阅者,每分钟10,000个MQTT包。此案例使工程团队能够评估Broker如何缓解负载急剧变化的影响并从压力中恢复。 稳定的大发布(PUBLISH)供应案例 在JSON和MQTT Sparkplug的世界中,5、10和100 KiB的发布负载并不罕见。多次写入大负载到磁盘可能会因稳定存储(计算机资源中最慢的一种)的硬件限制而影响性能。为了提供高持 --- ### 147. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着智能工厂的到来,工业物联网(IIoT)正在以惊人的速度扩展。预计到2030年,IIoT市场规模将达到3.3万亿美元,意味着将有数十亿个设备相互连接。为了确保这些设备,尤其是那些资源受限且有时依赖电池供电的设备能够高效运行,找到一种高效且可扩展的物联网解决方案至关重要。 MQTT-SN(针对传感器网络的MQTT)是一种专为非TCP/IP网络上的嵌入式设备设计的轻量级发布和订阅消息协议。它优化了MQTT版本3.1.1和MQTT 5.0的规范,特别适合低功耗、受限设备。在这篇文章中,我们将探讨MQTT-SN的节能和扩展能力,以及它如何支持工业自动化和数据采集的不断增长需求。 MQTT-SN:IIoT的低功耗解决方案 减少物联网设备的电力消耗不仅可以降低能源成本,还有许多其他好处。想象一下,一个遍布大型多地点生产设施的传感器网络。每个传感器或连接设备都需要电力,如果依赖频繁更换电池,不仅麻烦,而且限制了这些部署的可扩展性和灵活性。在这种情况下,降低电力消耗尤为重要。 通过最小化单个设备的能耗,可以降低电费,减少对频繁更换电池的依赖。这不仅减少了维护需求,提高了运营的正常运行时间,还显著节省了成本。具有延长电池寿命或能够从环境中获取能量(例如通过太阳能或风能)的节能设备,可以实现更广泛的传感器分布,提供更全面的工业过程视图。这种增加的监控可扩展性,使数据驱动的决策更加有效,并有助于优化运营。 此外,减少对一次性电池的依赖,可以促进更绿色的IIoT生态系统。结合MQTT-SN这样的低功耗协议和能量收集技术,我们可以迈向IIoT的可持续未来。 为什么选择MQTT-SN? 首先,MQTT-SN为效率而生。与MQTT相比,MQTT-SN具有更紧凑的设计。消息头被最小化,主题名称可以被短主题ID替换。数据大小的减少转化为更少的带宽消耗和对资源有限设备的更低处理需求。 为了进一步降低功耗,MQTT-SN引入了睡眠机制。设备可以有效地关闭,并在重新开启时接收排队的消息。这显著降低了功耗,延长了电池供电传感器的电池寿命。 与MQTT一样,MQTT-SN利用发布/订阅模型。设备将数据发布到特定主题,感兴趣的订阅者只接收相关信息。这种有针对性的方法最小化了不必要的数据传输,优化了网络带宽的使用。多个设备可以通过MQTT-SN网关与MQTT代理通信。 通过解决功耗效率和可扩展性的关键方面,MQTT-SN为IIoT环境中的强大和可靠通信铺平了道路。随着工业领域接受自动化和数据驱动的决策,MQTT-SN成为推动创新和确保未来智能工厂无缝运行的强大工具。 为了实现更多的节能和更低的数据开销,MQTT-SN增加了一种新的QoS模式,允许盲目发送并忘记消息传递。这意味着设备可以简单地唤醒并发送消息,而不必等待响应。 与MQTT不同,MQTT-SN不依赖于TCP/IP传输。相反,它旨在与底层网络服务无关。因此,任何支持节点和网关之间双向传输服务的网络都可以支持MQTT-SN。 MQTT-SN的限制 在选择MQTT-SN作为您的通信协议时,需要意识到一些限制。最大的一个问题是安全性。虽然可以使用任何加密技术,但目前MQTT-SN协议本身并没有内置安全性。不过,这个问题将在最新的标准修订中得到解决。 在复杂性方面,学习、实施和管理MQTT-SN可能比一些更简单的协议要困难。然而,使用专为MQTT-SN设计的兼容工具和库可以简化这个过程。虽然网关使设备和代理之间的通信成为可能,但确保不同MQTT-SN实现与现有基础设施的兼容性至关重要。选择符合最新MQTT-SN规范并提供明确迁移路径的解决方案可以帮助缓解兼容性问题。 MQTT-SN在IIoT中的用例 MQTT-SN在功耗效率、可扩展性和轻量级设计方面的优势使其成为各种IIoT应用的理想选择。以下是一些典型的用例: 无线传感器网络:在工业环境中,众多传感器监测温度、压力、振动等关键参数。MQTT-SN的低数据占用和睡眠功能非常适合这些电池供电的传感器,使它们能够在节省电池寿命的同时高效地传输数据。 智能建筑管理:建筑物越来越多地与传感器集成,用于监测能源消耗、占用和环境条件。MQTT-SN促进了这些传感器与中央控制系统之间的高效通信,实现了实时数据收集和优化的建筑运营。 预测性维护:通过持续监测设备健康数据(如振动、温度),MQTT-SN允许及早发现潜在问题,使预防性维护成为可能,减少了停机时间和相关成本。 工业资产跟踪:在大型设施内跟踪关键资产(如工具、机械或库存)的位置和状态至关重要。MQTT-SN处理来自低功耗RFID标签或GNSS跟踪器的数据,使其适用于此类应用。 远程监控和控制:在石油和天然气管道或偏远地区的环境监测站等应用中,MQTT-SN使与电池供电传感器的高效通信成为可能,允许实时数据获取和远程控制能力。 总结 MQTT-SN为IIoT应用提供了一个引人注目的解决方案。它的轻量级设计、高效的通信模型和对节能的强调,使其非常适合工业环境中普遍存在的资源受限设备。随着IIoT格局的不断发展,MQTT-SN有望在促进数据的可扩展交换中发挥关键作用,最终赋能下一代工业自动化。 --- ### 148. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 对于制造组织来说,将高级分析,特别是预测分析,集成到统一命名空间(UNS)中正变得越来越关键。这种集成增强了预测数据的实用性,并将其转化为规范操作的强大工具,覆盖了组织内各个领域。 本文旨在深入探讨这种集成的重要性,探讨它如何实现高效、实时的数据共享和可操作的洞察,从而增强决策过程、运营效率和工业数据的战略利用。 集成高级分析到UNS的好处在制造业中,预测分析应用传统上作为独立的工具运作,提供基于历史和实时数据的洞察。然而,除非这些洞察被集成到组织的更广泛运营生态系统中,否则它们的真正潜力大部分仍未被开发。这就是统一命名空间(UNS)概念发挥作用的地方。 UNS充当集中的数据中心,来自不同来源的信息在此聚合、标准化、情境化、统一,并通过单一接口——MQTT代理,在整个组织中变得可访问。通过将预测分析与UNS集成,你不仅增强了预测数据的可访问性,还增强了其实用性,将其转化为战略决策过程的基石。 增强可访问性和可操作性将预测分析集成到UNS的一个主要好处是显著增强了预测数据的可访问性和可操作性。本质上,预测分析提供了对潜在故障、资产健康状况和流程效率的预见。当这些洞察被孤立时,它们的影响有限。然而,将它们集成到UNS中,使它们普遍可访问和可操作。这意味着关于潜在问题或优化的洞察可以实时在不同的组织领域被采取行动,从维护到质量控制、吞吐量优化和能源效率。 促进实时决策制定使用统一命名空间作为集成预测分析平台的一个关键优势是促进实时决策制定。在快节奏的工业领域,决策延迟可能导致重大的财务损失、降低生产力和增加运营风险。UNS提供了一个实时数据共享框架,确保预测洞察立即可供所有相关利益相关者使用。这种即时性将预测分析应用从一个被动的预测工具转变为组织决策过程的积极组成部分。 将预测分析转化为规范操作将预测分析与统一命名空间集成为预测分析向规范分析的演变铺平了道路,更广泛地,转化为规范操作。虽然预测分析侧重于根据过去和当前数据预测潜在的未来事件,但规范分析进一步推荐了从预测中受益的具体行动。这种转变对于实现预测分析生成的洞察的运营化至关重要,允许组织预测问题,并在各个运营方面主动规定和实施解决方案。 增强维护和运营效率将预测分析与UNS集成的最具体好处之一是增强了维护和运营效率。由预测分析启用的预测性维护允许在发生之前预测设备故障,减少停机时间和维护成本。当集成到UNS中时,预测性维护洞察可以与运营计划和流程无缝对齐,确保最小干扰并优化资产利用。同样,有关流程效率的洞察可以直接应用于提高吞吐量和能源使用,进一步提高运营效率。 将高级分析集成到UNS的关键步骤确定分析用例的数据源 第一步涉及对组织运营需求的彻底评估,以及识别有助于分析过程的各种数据源。这不仅包括机器和传感器数据,还包括来自ERP、CRM和其他企业系统的信息。了解将推动高级分析的数据类型对于确定如何在UNS框架内最佳地构建和标准化此数据至关重要。 在UNS中建立分析命名空间 在UNS中为您要解决的每个分析场景建立特定命名空间。例如,要为批量工厂的混合区的搅拌器电机添加预测分析解决方案,您可能会设置如下命名空间: Enterprise/BatchPlant/BlendingArea/Mixer/Motor/PredictiveAnalytics 此结构将作为与训练预测模型、执行分析和访问授权应用程序(包括分析应用程序和数据库连接器)相关的数据的访问点。您还将拥有各种数据类型的子命名空间。 将数据源集成到UNS 在设置命名空间并了解应如何组合数据之后,使用IIoT平台将来自不同系统的数据集成到统一的数据生态系统中。这涉及使用DataOps层作为桥接,将来自可能不使用MQTT协议的现代和旧系统的数据进行集成。DataOps层收集、情境化和标准化数据,然后将其发布到UNS中的适当分析命名空间。 创建统一命名空间的历史记录 存储和访问历史数据对于增加工业运营的智能至关重要。这一步涉及将历史记录器或时间序列数据库和结构化数据库(如SQL)集成到您的UNS架构中。UNS的高质量、时间归档数据成为训练机器学习和AI模型的理想数据集,实现回顾性分析。此外,旧的历史记录器通常已经包含长时间归档的数据,这些数据可用于训练AI/ML模型。 选择和实施高级分析工具 最后,选择正确的高级分析平台对于从UNS聚合的数据中提取可操作的洞察至关重要。工具的选择应与组织的特定需求一致,考虑数据复杂性、体量和所需分析能力等因素。 结论虽然将预测分析集成到统一命名空间提供了许多好处,它也提出了必须解决的挑战。这些挑战包括需要强大的数据治理以确保数据质量和一致性,将旧系统和数据源集成到UNS中,以及管理数据隐私和安全问题。此外,这种集成的成功需要组织在文化上向数据驱动的决策制定转变,并愿意根据预测和规范洞察调整运营流程。 --- ### 149. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 ERP系统,传统上是组织数据管理的支柱,旨在简化和自动化核心业务活动。然而,现代制造业的动态和互联特性需求超出了独立ERP系统所提供的。 统一命名空间(Unified Namespace,UNS)已被证明是一种架构方法,满足了数字制造业对更互联、智能和适应性数字生态系统的需求,推动了创新和竞争优势。本文探讨了如何将ERP系统集成到统一命名空间数据生态系统中。 为什么要将ERP数据集成到统一命名空间 制造公司通常将组织主数据模型存储在ERP系统中。然而,这些数据通常不能准确反映公司的整个数字基础设施,使其作为单一真相来源不可靠——原因之一。 传统上,为了将ERP数据(如产品代码、工作订单和计划)与制造执行系统(MES)集成,公司使用几种方法。一种方法是MES通过REST API调用从ERP检索数据,需要熟悉ERP的REST API文档。 另一种方法是通过SQL数据库连接,MES将使用SQL连接器,如ODBC,需要了解ERP的数据库结构。最后,可以使用自定义连接器,作为MES扩展与ERP链接。这些集成方法难以维护,特别是当系统进行修改时,因为它们需要手动更新数据集成流程。 统一命名空间(UNS)架构提供了更简化的解决方案。它使用ERP中的组织结构创建语义层次结构。然后,这个层次结构被发布到MQTT代理,允许ERP信息与其他系统的数据一起在适当的级别集成到UNS中。 在此架构中,ERP和MES系统在语义层次结构中被分配了它们的命名空间,通过统一接口促进数据交换,而无需了解对方的具体实现细节。在ERP或MES中所做的更改,如添加或删除功能,会自动更新到命名空间中。 此外,这种方法确保数据可供其他系统未来使用,增强了组织数字基础设施的效率和适应性。 将ERP系统连接到统一命名空间 当今大多数ERP系统并不天生支持MQTT通信协议。因此,将这些ERP系统与统一命名空间集成通常需要一个额外的层,即DataOps层。这层充当中介,促进将ERP特定数据结构转换为MQTT兼容格式并执行必要的数据处理。这确保数据被正确格式化并在统一命名空间内正确放置。 该过程涉及使用一个工业物联网(IIoT)平台,该平台充当信息桥接。该平台通过REST API端点或SQL数据库连接器连接到ERP系统,将数据转换并通过MQTT中继到统一命名空间。 一旦建立此基础设施,制造执行系统(MES)可以订阅ERP的命名空间,直接从ERP系统拉取所需数据。相反,ERP系统可以订阅MES的命名空间,从MES接收信息。这种双向通信简化了数据交换,允许两个系统在不需要直接了解彼此的内部数据结构的情况下保持同步。 将ERP数据发布到统一命名空间 将ERP(企业资源计划)数据发布到统一命名空间(UNS)需要一种既适应性强又组织良好的方法,旨在满足业务及其运营流程的独特要求。使用ISA-95数据模型层次结构——包括企业、站点、区域、线和单元——来构建UNS MQTT主题层次结构,ERP数据可以在各个级别集成。通常在工厂级别或大型工厂的特定区域内分配ERP命名空间,允许ERP系统传播数据,通常扩展到生产线级别。 这些ERP命名空间是存储数据的仓库,如生产订单、物料清单(BOM)和库存。在UNS中共享的ERP数据的细节在不同的生产环境中可以显著不同。在某些情况下,工作订单可能作为数据集发布到特定的ERP主题,然后被分割成单独的标签。 另一种方法是将每个工作订单视为单独的主题,位于明确定义的路径中,例如Enterprise/Site/ERP/Orders,具有BOM和物料ID的不同主题。此设置允许定期更新,必要时替换作业集。 这种灵活的方法也适用于管理工作状态。启动作业会导致其在适当的主题路径中发布,如Enterprise/Site/Area/Line/CurrentJob。这种策略强调了定制UNS框架以适应业务特定运营需求的必要性。 通过统一命名空间的示例ERP交互 为了说明ERP集成与统一命名空间(UNS)在制造环境中的动态交互,让我们考虑以下示例,概述了从创建订单到完成产品的一系列事件: 新口味推出 ERP系统记录了新口味——"Citrus Zing"的推出。这个新产品的详细信息,包括配方、批量大小和包装要求,被发布到UNS下特定的产品ID。这确保所有相关系统都了解新的生产订单。 生产计划 调度工具在UNS中拾取发布到ERP命名空间的新口味订单。它评估生产线可用性、原料库存水平和现有订单,以生成优化的生产计划。然后,该计划被发布回UNS供相关部门访问。 原料准备 仓库管理系统(WMS),在通过UNS接收更新的计划后,确定并安排将必要的原料和包装材料提前交付到指定的生产线。 生产分配 制造执行系统(MES),现在已更新为最新的计划,将"Citrus Zing"生产订单分配给特定的装瓶线,在UNS中该线命名空间下的"可用订单"下进行标记。 启动生产 装瓶线上的操作员通过MES界面激活"Citrus Zing"订单。这在UNS中触发更新,指示装瓶线上的PLC调整新口味配置文件的设置。 原料跟踪 随着生产的开始,每个使用的原料批次都在生产线上被扫描和验证。这些交易通过UNS自动记录在ERP中,提供原料使用和库存水平的实时跟踪。 生产监控 在整个装瓶过程中,PLC监控各种参数,如填充水平、盖子完整性和标签准确性。这些数据不断发布到UNS,允许实时监控和根据需要进行调整以保持质量标准。 结论 总之,将ERP系统集成到统一命名空间代表了制造公司数字化转型旅程中的重要进步。通过弥合传统ERP数据管理与现代、互联的数字生态系统之间的差距,组织可以实现前所未有的效率、灵活性和洞察力。 --- ### 150. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 目录 利用视觉检测系统和MQTT提升制造业质量控制 视觉检测系统:AI驱动的质量保证 MQTT在优化制造数据流中的作用 集成MQTT以实现动态模型部署 实际效益与应用 发布-订阅系统在制造中的优势 结论 在竞争激烈的制造业中,实现高质量输出同时最大化运营效率至关重要。将先进的视觉检测系统与AI能力(如IBM Maximo视觉检测)和高效的数据处理协议(如MQTT)集成,大大提升了质量控制流程。 本文将探讨这些技术如何简化制造环境,并实现数据和模型的动态部署直接到边缘设备。 视觉检测系统:AI驱动的质量保证 视觉检测系统通过自动化检测制造车间的零部件和产品,利用AI确保质量标准始终得到满足。以下是几个著名的系统: IBM Maximo视觉检测:利用AI工具进行实时缺陷检测,提高快速响应质量问题的能力。 Cognex VisionPro:自动化复杂的视觉检测,常用于汽车和电子领域进行装配验证和缺陷检测。 Keyence视觉系统:提供高速图像分析,对制药和消费电子等精度要求高的行业至关重要。 Sick检测解决方案:在各个制造阶段提供全面的视觉能力,确保安全和质量。 这些系统受益于边缘计算,数据在生成时处理,减少延迟并提高决策速度。 MQTT在优化制造数据流中的作用 MQTT在制造业中对于高效的数据传输至关重要。该协议支持实时数据交换,是IoT部署中的重要组成部分,能够在网络中快速高效地共享数据。 集成MQTT以实现动态模型部署 使用如HiveMQ的MQTT代理可以显著增强视觉检测系统的能力。HiveMQ管理大规模网络中的大量数据,使其成为制造商的优秀选择。它促进了AI模型和更新的部署直接到边缘设备,确保最小延迟,并使生产线能够快速适应新的操作洞察。 实际效益与应用 AI驱动的视觉检测和MQTT消息传递的集成改变了制造质量控制: 实时缺陷检测:如IBM Maximo视觉检测系统使用AI模型立即检测异常,MQTT确保这些发现触发即时纠正措施。例如,一个金属冲压工厂可能使用该系统识别和纠正冲压零件中的对齐问题,减少浪费。 动态模型部署:通过MQTT和HiveMQ,新或更新的AI模型可以迅速推送到边缘设备,提高准确性和效率。例如,一家汽车制造商可以部署更新的模型,以实时检查车架的焊点,快速适应新的车辆设计。 发布-订阅系统在制造中的优势 在这个背景下,使用发布-订阅系统(pub-sub)如MQTT至关重要。它使设备和系统能够发布和订阅与其功能相关的数据流,而无需直接的设备间通信。这种架构降低了系统的复杂性,并提高了可扩展性和可靠性。例如: 主动模型发布:视觉检测系统可以通过MQTT代理主动发布新或更新的AI模型。订阅相关主题的边缘设备立即收到这些更新,允许实时适应新的检测标准或操作增强。 高效数据分发:发布-订阅系统确保在多个订阅者(如不同制造站点或地理位置)之间高效分发数据,实现一致的更新和同步操作。 结论 IBM Maximo视觉检测和MQTT等技术通过AI和IoT提供了增强制造质量控制的强大工具。通过集成这些系统,制造商可以实现更响应和高效的质量保证流程,提高产品质量和运营效率。 本文所述的先进AI和IoT技术在制造业中的集成,为增强质量控制流程提供了一个令人信服的框架 --- ### 151. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 工业4.0革命中的边缘计算:实时数据的力量 随着工业4.0的浪潮席卷全球,企业正迅速采纳边缘计算以加强其工业能力,尤其是在数据源附近利用数据的实时监控和控制。在制造、石油和天然气等关键行业中,数据的价值在毫秒级的延迟中迅速增加,对生产力和安全的影响至关重要。 2023年物联网与边缘商用采纳调查报告的数据显示,90%的受访者已经采用或正在考虑在未来几个月内采用边缘技术。这一趋势反映了边缘计算在工业应用中提供的多个关键优势: 低延迟:边缘计算通过在数据源附近处理数据,减少了数据传输的距离,从而最小化了延迟,确保了实时或近实时的响应。在需要快速决策的工业应用中,边缘计算提供的低延迟对于维持运营和安全至关重要。 带宽优化:通过在边缘本地处理和过滤数据,只将相关信息发送到云或中央数据中心,减少了通过网络传输的数据量。这优化了带宽使用,降低了数据传输成本,并减轻了网络拥堵。 提高可靠性:边缘计算使应用程序即使在与中央云的连接中断时也能继续运行。这确保了工业环境中关键系统的不间断运行,网络中断或延迟问题可能会带来严重后果。 现代化的挑战与MQTT的解决方案 尽管边缘计算提供了显著的优势,但传统技术如OPC-UA和Modbus面临着互操作性挑战,阻碍了不同工业边缘设备和系统之间的无缝通信。为了实现真正的互操作性,行业需要采用现代标准通信协议,如MQTT(消息队列遥测传输)。 MQTT是一个轻量级的开放标准协议,非常适合工业边缘。它提供了无与伦比的灵活性和效率,使不同设备和平台之间的数据交换变得简单,开销最小。其发布-订阅架构确保了强大的实时通信,而其对轻量级客户端的支持使其成为典型的资源受限环境中工业边缘的理想选择。 改变的障碍与MQTT网关的桥梁作用 随着企业努力拥抱工业4.0并利用他们数据的巨大价值,他们遇到了一个巨大的挑战:现有的机器和设备通常深植于专有协议中,这构成了昂贵替换的重要障碍。这就需要使用MQTT网关(或工业边缘协议转换器),这是一种复杂的软件解决方案,设计用于将专有协议无缝转换为MQTT。 通过部署这项变革性技术,企业可以快速弥合旧系统与MQTT标准之间的差距,从而迅速过渡到工业4.0,无需昂贵的硬件升级。这种方法不仅保护了现有投资,还代表了解锁工业4.0全部潜力的最快途径。 现代化的工业物联网架构 现代化的工业物联网架构必须通过中央数据中心解决这些挑战,无缝地将数据从边缘发送到云,并弥合操作技术(OT)与信息技术(IT)之间的差距。这要求一个强大的平台,能够处理大量数据,同时保持实时性和可靠性。 MQTT物联网平台:工业4.0的解决方案 欢迎尝试MQTT物联网平台,它有助于公司在工业4.0倡议中解决OT数据与IT系统统一的挑战,并实现无缝的边缘到云的数据流动。新的数据中心和离线缓冲功能作为我们商业产品的一部分提供,为企业提供了一个强大的工具,以支持其数字化转型的旅程。 --- ### 152. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网(IoT)的应用范围不断扩大,涵盖了从智能手机和智能手表等消费品到可摄入诊断设备和智能农业设备等工业用途。许多科技公司都在考虑物联网,希望为其服务线增加价值并获取物联网设备生成的大量数据。 然而,要想取得成功,科技公司在推出新的物联网产品时必须采取明确的计划和基本步骤。以下是福布斯技术委员会的15名成员讨论的关键步骤: 明确你的“原因”进入物联网领域就像进入威利·旺卡的工厂一样,选择一个或两个特定的用例并专注于“为什么”,不要试图过快解决太多问题。 建立一个具体的用例确保你有一个或多个特定的用例,并清楚地了解物联网设备或平台将提供的优势。在项目一开始就明确定义成功和KPI。 确保项目的举措与业务目标保持一致将物联网计划与业务目标保持一致,确保现有物联网投资的重用,物联网中心应负责共享模式和最佳实践。 确定你的产品是否有市场为产品找到或创造市场,并定义新产品在哪些物联网领域应用,确保物联网项目取得成果。 建立物联网项目控制的新流程改变控制范式,使物联网项目成功,新技术需要新的工艺,特别是在制造领域的项目。 依靠设计思维从真正的业务问题开始,运用设计思维并与客户共同创建产品,专注于解决问题而不是局限于物联网的特殊方法。 从人员、流程、技术和平台的角度思考人员、流程、技术和平台的组合是成功的关键杠杆,采用和协作是关键。 不要专门在云端进行构建小心在云中构建整个物联网策略,研究现代现场解决方案,它们更具成本效益并提供更好的性能。 巩固您的供应链战略在当前的供应链环境下,拥有强大的硬件策略非常重要,设计硬件时要牢记稳健性。 了解需要什么数据以及如何使用这些数据专注于为物联网制定清晰简洁的战略,了解需要哪些数据以及如何使用这些数据。 确保您有能力管理数据基础设施要做好准备,以适应物联网设备生成的数据的速度、数量、价值、多样性和准确性。 实施多个安全层为企业和客户实施多个安全层,确保物联网项目的安全性,特别是考虑到黑客经常以物联网设备为目标。 注意对速度的需求物联网需要实时响应,不要购买简单开发和云的一刀切,确保在实际环境中测试产品。 投资于需要的人物联网项目的投资额要现实,从人员角度考虑项目而不是仅仅关注技术。 根据反馈继续迭代测试产品,让反馈和迭代成为开发生命周期的重要组成部分,不断迭代、成长并立即反馈反馈。 --- ### 153. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在数字化转型主导的时代,工业物联网(IIoT)代表着推动工业自动化和智能制造的重大进步。通过利用互联设备和传感器提高效率和生产力,企业正在节省时间、资源和资金。然而,随着安全漏洞的不断增加,确保鲁棒的网络安全措施变得越来越关键,以保护和维护运营卓越性。 从设备劫持到数据泄露和设备欺骗,工业操作面临着多种潜在的漏洞。随着安全漏洞继续成为头条新闻,组织必须采取积极的措施来应对这些风险。 根据IIoT World的一份新报告,网络安全被列为主要挑战之一,有35%的受访者表示担心实施新的IIoT系统。了解最佳实践和方法可以帮助开发团队确保关键工业系统的完整性、机密性和可用性。 IIoT网络安全的最佳实践 最强大的安全实践有助于保持控制并迅速应对风险。以下是一些积极消除IIoT系统风险的方法。 身份验证和授权控制 为建立IIoT战略的安全基础,优先考虑强大的身份验证和授权机制。选择实施强大身份验证的供应商,用于访问IIoT网络的设备和用户。这包括安全的凭证管理、多因素身份验证和严格的授权控制。确保只有经授权的实体可以访问关键系统,可以显著降低未经授权的入侵风险。 数据加密 在IIoT环境中,保护敏感信息至关重要。实施端到端的数据加密,包括传输过程中和静止时,以防止信息被拦截或未经授权访问。这对于保护在物联网设备、边缘设备和云服务之间传输的数据尤为重要。使用加密协议可以在潜在的网络威胁面前增加额外的防御层。 硬件安全模块(HSM) 通过引入硬件安全模块(HSM)来确保硬件组件的物理安全性。这些专用设备通过保护加密密钥和敏感数据,增加了额外的保护层。通过保护硬件本身,组织可以防止未经授权的访问和篡改,降低被攻击的风险。 定期安全审计 实施定期的系统安全审计计划,以评估现有网络安全措施的有效性。定期评估确保IIoT基础设施符合行业标准和合规要求。在高度监管的行业,如医疗保健或金融,遵循安全协议尤为关键。安全审计有助于识别漏洞,并允许及时补救,防止其被利用。 MQTT和其他安全的消息传输协议 考虑使用固有安全的消息传输协议,如MQTT,进行IIoT通信。MQTT的设计通过仅允许订阅特定主题的客户端接收消息来确保安全性。此外,使用传输层安全性(TLS)加密增强数据传输中的机密性和完整性,提供一个安全的通信渠道。 针对部署的定制安全策略 认识到安全策略可能会根据部署环境而有所不同。无论是在云端还是本地部署IIoT解决方案,组织都应根据每种情景的特定风险调整其安全策略。与本地部署相比,云部署带来了不同的挑战,因此需要一种细致入微和适应性的网络安全方法。 保持IIoT系统的安全 随着IIoT不断重塑工业格局,网络安全仍然是一个令人担忧的问题。通过实施强大的身份验证、加密、硬件安全、定期审计和定制的安全方法,组织可以强化其IIoT系统,抵御潜在的威胁。保护工业操作不仅可以保护关键系统,还可以建立信任,确保在一个日益相互连接的世界中保持客户忠诚和企业责任。 --- ### 154. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 家庭自动化和监控: 智能恒温器 用于温度控制。 自动百叶窗或窗帘 通过应用程序控制。 语音控制灯光和电器 基于物联网的安全摄像头系统 漏水检测和通知系统 智能锁 具有远程访问功能。 家庭能耗监控和优化器 自动化植物护理系统 具有浇水和阳光控制功能。 基于物联网的烟雾和一氧化碳探测器 智能镜子 带信息显示。 健康与保健: 可穿戴健身追踪器 用于监测步数、心率等。 药丸分配器 支持物联网,具有用药提醒功能。 远程健康监测系统 用于老年人或病人。 智能水瓶 可跟踪并提醒保持水分。 睡眠监测设备 提供个性化睡眠建议。 血压监测仪 支持物联网。 智能吸入器 适用于哮喘患者。 温控婴儿床 提供最佳睡眠。 姿势矫正可穿戴设备 具有实时反馈。 智能牙刷 具有刷牙分析功能。 环境监测: 空气质量监测系统 带有污染警报。 园艺土壤湿度和 pH 值监测 水质监测 适用于池塘或水族馆。 气象站 具有实时数据更新。 噪声级监测 用于跟踪噪声污染。 室内空气二氧化碳浓度监测 紫外线指数监测和防晒建议 野生动物监控 使用物联网设备进行跟踪和监控。 用水跟踪和优化系统 森林火灾探测和预防系统 车辆及交通: 车辆跟踪和防盗系统 支持物联网。 车辆燃油消耗监测器 电动汽车充电站查找器和调度器 智能停车系统 带有可用停车位通知。 实时公共交通跟踪器 自行车防盗装置 带 GPS 跟踪功能。 企业车队管理系统 车辆碰撞检测和预防系统 无人机交付系统 自动化。 摩托车手智能头盔 带有安全警报功能。 教育与学习: 交互式儿童教育玩具 基于物联网。 语言学习助手 带发音反馈。 个性化辅导系统 使用人工智能和物联网。 课堂考勤系统 具有面部识别功能。 智能电子书阅读器 具有个性化注释。 科学实验套件 具有物联网数据收集功能。 虚拟现实 (VR) 教育体验 与物联网集成。 互动艺术装置 使用物联网传感器。 盲文学习和交流设备 教育编码和机器人套件 基于物联网。 零售和购物: 智能购物车,自动结账 个性化购物推荐 基于信标。 库存管理系统 实时更新。 互动商店展示产品信息 自动售货机 支持物联网,具有库存跟踪功能。 智能衣柜助手 提供穿搭建议。 顾客跟踪和行为分析 适用于零售店。 智能冰箱 具有库存管理和食谱建议。 自动结账系统 基于RFID。 时尚零售镜子 带有虚拟试衣间。 工业和制造业: 机械预测维护系统 工业物联网 (IIoT) 传感器网络 用于工厂自动化。 危险环境远程设备监控 物联网数据优化供应链 实时库存跟踪 仓库中。 资产跟踪和管理系统 质量控制和缺陷检测 使用物联网传感器。 能源消耗优化 工业流程。 工人安全监控和警报系统 工业无人机机队 用于检查和监控。 农业及种植业: 土壤和天气数据监测作物健康 牲畜跟踪和健康监测 精准灌溉系统 基于土壤湿度。 智能蜂箱监控 为养蜂人提供。 自动化家禽养殖系统 具有物联网集成。 鱼菜共生系统 实时监控功能。 植物繁殖和生长监测 自动化。 智能害虫防治系统 基于天气。 水培农业 具有养分和 pH 值监测功能。 奶牛场自动化 用于牛奶生产监控。 娱乐和游戏: 密室逃脱谜题和挑战 支持物联网。 交互式棋盘游戏 基于物联网。 增强现实 (AR) 寻宝游戏 智能舞池 同步灯光效果。 物联网控制的室内迷你高尔夫球场 通过物联网触发的事件交互式故事讲述 激光标签竞技场 支持物联网。 可穿戴游戏配件 身临其境体验。 物联网交互功能的虚拟现实 (VR) 多人游戏 互动艺术装置 活动或画廊中。 各种各样的: 智能废物管理系统 用于优化收集。 海水淡化和净化系统 基于物联网。 应急响应和疏散系统 具有物联网警报。 实时语言翻译设备 带有物联网连接。 残疾人辅助设备 基于物联网。 垃圾分类和回收指导系统 宠物跟踪和健康监测 物联网连接。 物联网回收箱 具有奖励系统。 可持续电力的能量收集物联网设备 时间管理和生产力助手 基于物联网。 这些基于物联网的项目创意涵盖了各个领域,从家庭自动化到工业制造,再到娱乐和各种创新应用。这一百个创意项目展示了物联网技术在不同领域的应用潜力,为未来的技术发展和生活方式提供了无限可能性。 --- ### 155. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 离散制造是指生产独立、可辨认且易于计数的独立物品或单元的过程。这种制造类型涉及将组件或零件组装成成品,其中每个物品都可以与其他物品区分开。典型的离散制造行业包括汽车、电子、航空航天、机械和医疗设备。这些行业通常在生产过程中使用物料清单(BOMs)和质量控制措施。离散制造允许定制、灵活性和高效生产各种产品。 离散制造的常见过程 生产计划和调度 离散制造需要对整个生产过程进行仔细的计划和调度,以确保所需的零部件在需要时可用。调度定义了每个生产阶段需要多长时间以及每个人应该工作多少时间,以确保按时完成生产。生产计划需要优化,以最小化浪费并最大化效率。因此,供应链数据的可见性非常重要。 批量大小和交货期的优化 批量大小突显生产的数量,而交货期指整个过程所需的时间。这两个参数都影响生产效率,因此必须进行优化以获得更好的产出。实时数据的可见性和准确性非常重要。 离散制造的常见系统 计算机辅助设计(CAD) CAD软件用于设计产品,概念化想法以考虑确保最终产品完美的细节。该工具执行快速设计计算和模拟,有助于创建准确和精确的产品设计。 计算机辅助制造(CAM) 计算机辅助制造实现了管理过程的自动化,允许跟踪生产过程、资源和运输。 企业资源规划(ERP) ERP的实施提供了对库存和整个生产过程更好的控制和可见性。借助ERP,平台检查不同类型的数据和信息,并在所有点上使其可访问和可用。 产品生命周期管理(PLM) PLM确保从概念化时直到最终发运时对产品的整个生命周期进行管理。 工业物联网(IIoT)和MQTT作为连接系统的启用器 在离散制造中,IIoT在通过传感器和可编程逻辑控制器(PLC)将各种OT系统连接到上述IT系统方面发挥着重要作用。这种OT-IT连接实现了数据交换和数字化转型用例,例如,ERP系统中的订单数据需要与PLM中的生产数据相结合,以便能够进行正确的预测、计划和调度。IIoT使这些系统能够彼此通信,并通过MQTT等消息传递技术创建一个单一的窗格。 MQTT在离散制造应用中的作用 实时数据通信 MQTT在离散制造中实现了设备、系统和应用程序之间的实时通信,有助于将它们连接到企业和/或云,支持预测性维护、远程监视、数字孪生和先进的分析等高级数据用例。MQTT还促进了无显著延迟的制造设备之间的无缝机器对机器通信,这对于监视和控制离散制造非常关键,确保数据迅速而高效地交换。 可扩展性 MQTT具有很高的可扩展性,可以同时支持大量设备、系统和应用程序。在离散制造中,其中许多设备、系统和应用程序部署在生产现场,MQTT的可扩展性对于处理多样化的数据来源至关重要。提供企业级MQTT代理的HiveMQ具有额外的可扩展性功能,并已进行了2亿并发连接的基准测试。 带宽使用效率 MQTT在带宽使用效率方面设计得非常高效。在网络带宽可能有限的制造环境中,MQTT的轻量级协议确保数据可以在不给网络基础设施带来额外负担的情况下进行高效传输。 可靠性和服务质量(QoS) MQTT支持不同级别的服务质量,允许制造商选择适用于其特定用例的可靠性级别。这对于可靠的数据交换至关重要,例如远程监视关键设备。MQTT通过支持保留消息来提供额外的可靠性,其中代理会保留在特定主题上发送的最后一条消息。这个特性在离散制造中非常有用,以确保连接到网络的设备在连接时接收到最新的相关信息。HiveMQ MQTT代理提供了额外的可靠性功能,包括支持无主集群架构、可靠的通信和零停机升级。 安全性 MQTT本身提供通信的安全性,因为它基于对主题命名空间的订阅。因此,未订阅特定主题的任何客户端都不会接收到消息。除此之外,可以在MQTT上实施额外的安全功能,包括用户ID/密码、TLS加密、X.509 客户端证书授权等机制,以确保离散制造通信的安全性。 发布-订阅模型 MQTT采用发布-订阅模型,其中客户端可以将消息发布到特定主题,而其他客户端可以订阅这些主题以接收消息。这个模型非常适合离散制造场景,其中不同的组件需要实时了解相关事件或实时变化。除此之外,数据框架如Sparkplug和统一命名空间等概念提供了其他有效组织数据的方式。 边缘计算集成 MQTT通常与边缘计算一起在离散制造中使用。边缘设备、应用程序和系统使用MQTT在本地彼此通信,有选择地与服务器/云通信,从而减少将所有数据发送到中心服务器的需求。这可以提高响应时间并减少延迟。边缘网关可以将来自各种协议(如OPC UA、Modbus和Siemens S7)的数据转换成MQTT,并将数据传送到代理进行处理。 MQTT对离散制造中IIoT数据通信的改变 离散制造中的IIoT改善了效率、质量、维护和整体运营效果。通过使用可靠且高效的通信机制(如MQTT)实现数据通信,离散制造系统可以高效支持对工厂生产中各种设备、流程和应用程序的实时监视,并支持先进的数据用例。MQTT所带来的连接性使离散制造得以数字化转型,从而实现更高的效率、降低成本、更好的客户体验和更高的盈利能力。 --- ### 156. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 简介:在迅速发展的工业物联网(IIoT)领域,一份最新的2024年调查为当前IIoT系统状况提供了全面的概述。此次调查是与HiveMQ合作进行的,涉及350名来自不同行业的IIoT专业人士,揭示了塑造该领域的挑战、技术偏好和新兴趋势。 IIoT实施的关键发现:该调查突显了一些关键发现,强调了IIoT对制造业、交通运输、汽车和能源等各个领域的深远影响。 共同挑战: 公司在进入IIoT项目时面临的头号挑战包括获得利益相关者支持、解决预算问题、不确定的投资回报(ROI)以及确保网络安全。 主要协议: MQTT、HTTP以及新兴协议如MQTT Sparkplug等被认为对于成功的IIoT战略至关重要,其中60%的受访者认为MQTT是他们在IIoT系统中的首选协议。 IIoT采用: 令人印象深刻的是,74%的受访公司已经部署或正在制定IIoT战略,突显了IIoT技术的广泛采用。 与AI/ML集成: 将机器学习和人工智能应用于IIoT战略的受访者近一半,强调了IIoT与先进技术的融合。 业务影响: IIoT被认可为对生产率、整体设备效能(OEE)和成本降低产生显著积极影响,证明其战略重要性。 行业间普遍存在的实施挑战:调查对象被问及在实施新IIoT系统时面临的主要挑战,结果揭示了一些有见地的趋势。 领导愿景和管理支持: 38%的受访者认为领导愿景和管理支持是一个关键挑战,强调了IIoT项目获得高层支持的重要性。 网络安全问题: 35%的受访者提到网络安全是一个主要挑战,表明在IIoT实施中需要强大的安全措施。 预算限制和不确定的ROI: 31%的受访者表示预算限制和不确定的ROI是一个主要挑战,强调了与IIoT项目相关的财务考虑因素。 实现协同并展示ROI:报告提供了关于如何通过将IIoT战略与业务目标对齐,并通过在OT和IT团队之间进行合作来成功实现的宝贵建议。此外,它强调了通过识别和跟踪关键绩效指标(KPIs)(如OEE、停机时间减少、资产利用率、能源效率、质量改进、供应链可见性、周期时间减少和客户满意度)展示ROI的重要性。 技术创新推动IIoT成功:技术选择在IIoT成功中发挥着关键作用,其中MQTT成为首选协议。调查还强调了MQTT Sparkplug的日益流行,并确定Microsoft Azure为IIoT首选云服务提供商。 展望2024年的趋势:报告预测了2024年的一些趋势,包括生成式人工智能(GenAI)的复苏、数字孪生的持续实施以及统一命名空间在IIoT市场的重要性。可扩展性、可靠性和安全性继续是长期IIoT成功的关键原则。 结论:从调查中获得的见解为正在导航2024年IIoT复杂领域的组织提供了宝贵的路线图。随着IIoT的不断发展,战略协同、技术创新以及解决共同挑战的关注将对寻求充分利用IIoT技术潜力的组织至关重要。 --- ### 157. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在当今快速发展且日益复杂的工业网络安全领域,追求高效且安全的通信协议至关重要。MQTT,即一种简化且敏捷的消息传递协议,正在改变工业数据传输和安全的格局。MQTT 最初是为带宽受限的场景而设计的,现已迅速成为工业物联网应用工具包中的关键组件。本文将探讨MQTT在增强工业安全方面的作用,概述运营技术(OT)团队面临的挑战,并涵盖可能的攻击细节。 工业网络安全挑战: 运营技术(OT)系统面临着一系列独特且严峻的网络安全挑战,这些挑战通常比传统的IT系统更加复杂。OT系统控制和监控工业物理过程,因此成为网络威胁的目标。以下是与OT系统相关的一些特定网络安全弱点: 遗留系统和过时的技术: 许多OT系统是在网络安全成为重大问题之前设计和实施的,导致技术过时、存在漏洞,并可能无法轻松修补或更新。 有限的安全标准: 与IT领域的网络安全标准不同,OT系统通常缺乏普遍接受的标准,这使得在不同的OT环境中实施一致且有效的网络安全实践变得具有挑战性。 与IT网络融合: 在工业4.0原则的推动下,OT系统与IT网络的集成创造了新的攻击媒介,可能会将网络威胁传播到OT环境,给工业控制系统带来严重风险。 访问控制不足: 弱点的访问控制可能导致未经授权的个人或恶意行为者获得对关键OT系统的访问权限,从而引发中断、未经授权的流程更改,甚至物理损坏等问题。 这些网络安全弱点都会导致风险,尤其是在OT系统中涉及复杂供应链的情况下,供应链风险可能会给OT基础设施带来漏洞。对OT网络和流程的可见性有限,导致难以检测异常活动或安全事件,从而延迟了网络威胁的检测和响应。 MQTT如何帮助减轻网络安全攻击: MQTT针对这些网络安全挑战提供了解决方案,提供了安全高效的数据交换方式。MQTT的设计考虑了工业环境的独特需求,通过以下方式增强了工业安全性: SSL/TLS加密支持: MQTT支持SSL/TLS加密,确保数据在传输过程中不会被窃听或篡改。 服务质量(QoS)级别: MQTT提供不同的QoS级别,可确保可靠的消息传递,从而提高通信的可靠性。 遗嘱和遗嘱(LWT)功能: MQTT支持遗嘱和LWT功能,用于提高安全意识,确保在连接中断时可以采取适当的措施。 对MQTT代理的潜在安全攻击: 然而,对MQTT代理的攻击可能多种多样且复杂,包括: 窃听/拦截: 攻击者可以拦截以明文形式传输的MQTT数据,从而获取对敏感信息的未经授权的访问。 中间人攻击: 攻击者可以将自己置于代理和客户端之间以拦截或更改消息。 拒绝服务(DoS)和分布式拒绝服务(DDoS)攻击: 这些攻击可以通过淹没代理来中断合法用户的服务。 欺骗: 攻击者可以冒充合法设备或客户端向代理发送恶意消息。 不安全的身份验证: 如果代理不强制执行强大的身份验证机制,攻击者可能会获得未经授权的访问。 为了减轻这些威胁,实施强大的安全措施是至关重要的,包括强加密、安全身份验证、访问控制和定期的安全审核。 HiveMQ在网络安全方面的附加值: HiveMQ是一种流行的MQTT代理,为MQTT实现提供了增强的安全功能,特别适用于大规模和企业环境。以下是HiveMQ如何为MQTT添加安全性的方式: TLS/SSL加密: HiveMQ支持TLS(传输层安全性)和SSL(安全套接字层),以加密传输中的数据,从而保护数据免受窃听和篡改。 客户端身份验证: HiveMQ允许强大的客户端身份验证机制,包括用户名和密码身份验证以及与外部身份验证系统的集成,确保只有授权的客户端 才能连接到MQTT代理。 访问控制列表(ACL): HiveMQ可以使用ACL来定义不同客户端的精细权限,以增强安全性,确保客户端仅具有必要的访问权限。 桥接安全: HiveMQ提供安全桥接功能,以确保不同代理之间交换的数据也可以进行加密和身份验证。 安全默认设置: HiveMQ的设计考虑了安全性,降低了不安全配置的风险。 日志记录和监控: HiveMQ提供广泛的日志记录和监控功能,有助于检测和响应安全事件。 高可用性和可扩展性: HiveMQ关注高可用性和可扩展性,确保安全性不会以性能为代价,即使在大规模部署中也是如此。 额外的安全考虑因素: 除了MQTT和HiveMQ提供的安全功能外,还需要考虑其他因素来确保整体安全性: 有效负载加密: 在MQTT协议中应用有效负载加密以提供额外的安全性。 消息数据完整性: 对MQTT消息使用数字签名/MAC和校验和以确保数据完整性。 在不同层保护MQTT系统: 从基础设施级别、操作系统级别和MQTT代理级别保护MQTT系统。 防火墙: 所有与MQTT代理的连接都应至少经过一个防火墙。 总之,MQTT的集成以及与HiveMQ等平台的结合可以显著增强工业领域的网络安全性。这些平台不仅提供了安全通信的框架,还代表了一种积极主动的网络安全方法,以确保工业环境能够在面对日益增长的网络威胁时做出反应,预测和缓解潜在的网络威胁。MQTT和HiveMQ等平台正在推动工业网络安全的演变,标志着朝着更加安全、高效和有弹性的工业未来迈出了重要一步。 --- ### 158. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当我们讨论物联网(IoT)和分布式系统中的通信时,一种协议凸显出其卓越性能和独特优势,那就是MQTT(Message Queuing Telemetry Transport)。MQTT是一种轻量级的通信协议,它的设计和特性使其在各种应用场景下表现出色。在本文中,我们将深入探讨MQTT协议的优越性,以及为什么它成为了物联网和分布式系统中的首选通信协议。 什么是MQTT? 首先,让我们简要了解一下MQTT协议的背景和基本原理。MQTT是一种发布-订阅(Publish-Subscribe)模式的通信协议,最初由IBM开发。它专为低带宽、不稳定或高延迟网络环境而设计,这使得它成为连接物联网设备的理想选择。 MQTT的工作方式非常简单明了。在MQTT网络中,有两个主要的参与者:发布者(Publisher)和订阅者(Subscriber)。发布者负责将消息发布到特定的主题(Topic),而订阅者则订阅了特定的主题,以接收与该主题相关的消息。这种发布-订阅模式允许设备之间以异步的方式进行通信,而无需直接连接到彼此。这对于大规模的分布式系统和IoT应用非常有用,因为它简化了通信和数据交换的管理。 MQTT的优越性 现在让我们深入探讨MQTT协议的一些关键优势,这些优势使其在各种应用中脱颖而出。 1. 高度可靠的通信 MQTT协议在保证可靠通信方面表现出色。无论是在不稳定的网络环境下还是在低带宽情况下,它都能够可靠地传递消息。这意味着即使在网络中断或恢复的情况下,消息也不会丢失,而且它还支持消息的持久性,确保即使设备离线一段时间后再次连接时,仍然可以接收之前未接收的消息。 2. 轻量级和高效性能 MQTT协议是一种轻量级协议,它的消息头非常小,因此减少了在网络上传输的数据量。这使得它成为在带宽有限的情况下运行的理想选择。此外,MQTT的设计非常高效,可以处理大量的消息,而无需消耗大量的计算资源。这使得它非常适合高吞吐量的应用,如传感器数据收集和实时监控。 3. 异步通信 MQTT采用发布-订阅模式,允许设备之间进行异步通信。这意味着发布者和订阅者不需要在同一时间进行通信,它们可以独立地发送和接收消息。这种灵活性使得MQTT非常适合连接大量分布式设备的场景,这些设备可能具有不同的工作速度和响应时间。 4. 分布式架构支持 MQTT协议的设计允许构建分布式系统,其中多个MQTT代理可以协同工作。这使得系统具有高度的可伸缩性和弹性,可以轻松地扩展以适应不断增长的设备数量。无论是在工业自动化领域还是智能家居中,这种分布式 架构都非常有用。 5. 适用于物联网 最重要的是,MQTT协议是物联网应用的理想选择。它的轻量级特性和高可靠性使其成为连接物联网设备、传输传感器数据和监控设备的首选协议。由于物联网应用通常涉及大量设备,而这些设备可能位于不同的地理位置,MQTT的分布式架构和异步通信特性非常适合处理这些需求。 总结 在物联网和分布式系统的通信领域,MQTT协议凭借其高度可靠的通信、轻量级和高效性能、异步通信、分布式架构支持以及适用于物联网应用的特性,成为了首选的通信协议。无论是在工业控制、智能城市、农业监测还是智能家居领域,MQTT都发挥着关键作用,确保设备之间的可靠通信和数据交换。它的灵活性和可扩展性使其成为满足不断增长的通信需求的理想选择,将继续在物联网和分布式系统中发挥关键作用。因此,无论是现在还是未来,MQTT都将继续引领通信领域的发展。 --- ### 159. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 作为物联网(IoT)中的关键消息传输标准协议,MQTT以其轻量级、高效和可扩展性在连接物联网设备方面扮演着重要角色。随着技术的不断演进,特别是自 EMQ 在 2012 年发布开源 MQTT 消息服务器 EMQX 以来,MQTT 的应用和发展已经取得了长足的进步。让我们一起探索 2023 年 MQTT 技术领域的七大发展趋势。 MQTT 协议的七大技术趋势 MQTT over QUIC QUIC (Quick UDP Internet Connections) 作为一种新的传输协议,减少了新连接的建立延迟,提高了数据传输率,并解决了 TCP 的某些限制。 MQTT over QUIC 是 MQTT 5.0 规范发布以来最具创新性的进展,具备多路复用、快速连接建立和迁移等特性,有潜力成为下一代 MQTT 协议标准。 相比 MQTT over TLS/SSL,MQTT over QUIC 提供更快的速度和更低的延迟。 Serverless MQTT Serverless 架构的兴起改变了应用的设计、开发、部署和运行方式,使开发者能专注于业务逻辑而无需管理基础设施。 Serverless MQTT 提供极快的部署速度和无可比拟的灵活性,适合快速部署和弹性扩展的场景。 MQTT多租户架构 多租户架构允许来自不同用户或租户的物联网设备连接到同一个大规模的 MQTT 集群,同时保持数据和业务逻辑的隔离。 这种架构降低了管理开销,并能灵活支持大规模物联网应用。 MQTT Sparkplug 3.0 MQTT Sparkplug 3.0 是为工业设备定义的统一数据接入规范,支持 MQTT 5.0 并引入了优化的数据传输和扩展的数据模型。 此标准简化了工业设备间的连接和通信,提高了数据采集、处理和分析的效率。 MQTT 统一命名空间 统一命名空间为 MQTT 主题提供了一个集中的存储库,简化了物联网应用的开发。 该架构使 OT 和 IT 系统能够更有效地交换数据,实现物联网时代的统一。 MQTT 跨域集群 MQTT 跨域集群允许不同地区或云上的 MQTT Broker 作为一个集群一起工作,实现数据的自动同步和传输。 这为企业提供了一个跨多云的全球 MQTT 接入网络。 MQTT Streams MQTT Streams 扩展了 MQTT 的能力,允许在 Broker 内实时处理海量数据流。 这种流处理技术简化了物联网数据处理架构,提高了数据处理效率。 结语 这七大技术趋势展示了 MQTT 协议在物联网发展中的重要性和潜力。从提高连接速度到简化物联网架构,再到强化数据流处理,MQTT 正在不断演变以满足日益增长的 物联网需求。随着物联网在各个领域的深入应用,MQTT 协议无疑将在车联网、工业物联网等关键领域发挥越来越重要的作用。 --- ### 160. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 概述 数字孪生(DT)技术在复杂的工业和工程应用中具有巨大潜力,能够显著提升运营效率、安全性、以及预测准确性。然而,在实现和维护数字孪生的过程中,监管合规性是一项重要且挑战性的任务。本文旨在探讨如何利用 MQTT Sparkplug 解决工业数字孪生的监管合规性问题,并分享一些实施 MQTT 的最佳实践。 数字孪生与 MQTT Sparkplug 数字孪生的广泛应用包括提高操作效率、加强安全性、改进安全工程、减少错误、加速信息共享及优化预测。在这些用例中,数据合规性至关重要。MQTT作为一种高效的轻量级消息传递协议,能够支持DT用例,尤其在数据合规性方面显得尤为关键。Sparkplug为MQTT数据提供了上下文化,使其更适合工业物联网应用。 应对监管合规性挑战 数据准确性和完整性:确保传输的数据准确、上下文相关、完整且未被篡改是监管合规的基础。MQTT Sparkplug通过其高效的数据验证机制,帮助维护数据的准确性和完整性。 实时监控和报告:监管合规要求实时数据报告。MQTT Sparkplug的基于事件的报告机制和小型消息体确保了数据的实时性,从而使得数字孪生数据的监管合规性报告更加准确。 数据互操作性:在数字孪生环境中,来自多个应用程序、系统和设备的数据需要无缝交换。MQTT Sparkplug的统一命名空间确保了数据的无缝交换,简化了监管合规工作。 长期维护:监管合规要求不断变化,需要数字孪生应用程序持续适应这些变化。MQTT Sparkplug通过其数据模型、主题名称结构和状态管理,使数字孪生能够及时响应法规遵从性的变化。 实时记录和审计跟踪:保留所有与数字孪生相关的数据变更和交互记录对于监管合规性至关重要。MQTT Sparkplug通过集中数据湖,保持对所有实时更改的最新状态,并提供清晰的版本控制。 实施 MQTT 的关键考虑因素和最佳实践 可扩展性和性能:设计MQTT基础设施时,需考虑到大量数据处理、低延迟和实时处理的需求,以满足监管报告的要求。 冗余和可靠性:应在设计中纳入冗余和故障转移机制,以确保高可用性和可靠性,防止数据丢失和系统停机。 安全通信:实施高度安全的MQTT通信,确保数据的完整性、机密性和真实性。使用加密(SSL/TLS)和安全身份验证机制来保护数据。 与监管机构的合作:与相关监管机构或机构合作,以确保及时了解法规和标准的更新。 结论 在工业数字孪生环境中,监管合规性涉及多个领域,包括数据 准确性、实时监控、互操作性、长期维护以及审计跟踪。通过实施MQTT Sparkplug,可以有效地应对这些挑战。重点关注可扩展性、可靠性和安全性等领域,是实现监管合规的关键。与此同时,与监管机构的积极合作也是确保数字孪生长期合规的重要策略。 --- ### 161. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 数字孪生技术(DT)在工业和工程应用中具有潜在优势,包括提高运营效率、增强安全性和可靠性、改善安全工程、减少错误、加快信息共享以及更好的预测能力。在这些用例中,MQTT作为一种轻量级消息传递协议,特别在数据合规性方面发挥着关键作用。得益于MQTT所提供的优势,它已成为从现场到企业或云端传输工业数据的事实标准。 探讨如何通过MQTT改善能源使用和推动制造业的可持续发展: Sparkplug为MQTT数据提供了工业物联网环境中所需的上下文。下面我们将详细探讨这些挑战,以及MQTT Sparkplug如何应对这些挑战。 应对工业数字孪生中的合规性挑战: 数据准确性和完整性:合规性要求数据必须准确且经过验证。在数字孪生环境中,尤其是处理来自多种设备、应用、系统和传感器的数据时,维护数据的完整性可能相当复杂。不准确或不可靠的数据可能导致数字孪生数据的错误报告或解释,进而导致不合规。因此,实施有效的数据验证机制至关重要。MQTT Sparkplug能够确保传输的数据是准确、具有上下文的、完整的,并且未被篡改。 实时监控和报告:合规性报告需要基于实时数据。依赖过时数据进行合规性报告可能会导致误导性报告,甚至可能招致罚款。MQTT Sparkplug的基于异常的报告方式和消息大小控制在200KB以下,确保了数据的实时性,从而使数字孪生真实反映了物理系统的状态,这有助于提高数字孪生数据的合规性报告的准确性。 数据互操作性:数字孪生环境中的数据来自多个源。在不同应用、系统和设备之间确保互操作性对于数据的无缝交换至关重要。应用、系统和设备之间的不兼容可能会影响数据的无缝交换,从而影响合规性工作。MQTT Sparkplug提供的统一命名空间(UNS)确保所有应用、系统和设备的所有数据都能汇聚在一个地方,并从那里进行索引。UNS作为数字孪生应用的单一数据源,保证了数据的无缝交换,并简化了合规性的工作,因为它提供了一个地方,从那里可以提取所有合规性数据。 长期维护:合规性要求不断变化,对于构建数字孪生应用的工业公司来说,跟上所有必要的维护工作以保持数字孪生与法规合规是一项挑战。确保数字孪生环境在长期内保持合规是一个持续的挑战,但可以通过MQTT Sparkplug来应对。Sparkplug允许制造商定义全面的数据模型、主题名称结构和工业状态管理,使数字孪生能够及时响应数据格式和结构的变化,以适应合规性更新。这使得企业可以流线化和自动化数字孪生的长期维护,以应对合规性的变化。 实时文档和审计跟踪:保持对所有对数字孪生数据所做更改和所有与数字孪生互动的全面且最新的记录对于在合规性审计期间证明合规性至关重要。包括记录谁访问了数据、何时以及采取了什么行动。在一些受监管的行业中,这些数据和DT更改可能需要保留长达7年以进行合规性审计。MQTT Sparkplug通过其UNS架构确保所有数据都汇聚在一个位置,并从那里获得上下文,这些数据可以轻松地提供给中央数据湖。数据湖可以保持最新,记录数字孪生所有实时更改,并对审计目的进行明确的版本控制。最佳实践包括保持详细的MQTT实现文档,包括安全措施、访问控制和数据处理程序,并定期生成系统性能和合规性指标的报告,以备审计时使用。 实施数字孪生MQTT时的关键考虑因素和最佳实践: 可扩展性和性能: MQTT基础设施应设计为能够处理工业数字孪生的可扩展性要求,包括高数据量、低延迟和实时处理。 冗余和可靠性: 需要在设计中纳入冗余和故障转移机制,以确保MQTT基础设施的高可用性和可靠性,防止数据丢失和停机。 使用MQTT进行安全通信: 应实施高度安全的MQTT协议通信,确保数据的完整性、保密性和真实性。这包括对数据传输中的数据使用加密(SSL/TLS)和安全认证机制,以及部署强大的访问控制机制以限制对数字孪生数据的访问。 总结: 在实现工业数字孪生环境的合规性方面,需要解决包括数据准确性、实时监控、互操作性、长期维护、文档和审计跟踪等多个领域的挑战。通过实施MQTT Sparkplug,可以应对这些挑战。在实施时,应重点关注可扩展性、可靠性和安全性等领域,并与相关监管机构保持紧密合作,以跟进合规性要求。 --- ### 162. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 在现代技术的交汇点上,物联网(IoT)、人工智能(AI)和边缘计算正在共同塑造一个高度互联和智能化的未来。特别是在边缘计算领域,MQTT这种轻量级通信协议正在发挥着重要作用,推动分布式AI的实现和发展。 深入解析关键技术 物联网 (IoT) IoT技术正将物理世界与数字世界无缝连接。传感器、软件等技术的集成使物理设备能够交换和处理大量数据,从而实现智能决策和自动化操作。 人工智能 (AI) 和机器学习 (ML) AI和ML正在重塑我们对数据处理和分析的理解。它们使机器能够模仿人类认知功能,自动化复杂任务,提供深入洞察,并在无人干预的情况下做出决策。 边缘计算 边缘计算将数据处理从中心化的大型数据中心转移到数据产生的源头附近。这降低了延迟,提高了响应速度,使得实时数据处理成为可能。 MQTT的核心作用 MQTT作为一种轻量级的消息传递协议,解决了IoT设备在带宽有限和网络不稳定环境下的通信需求。在分布式AI中,MQTT提供了一个高效、可靠的通信框架,使设备、传感器和服务器之间的数据交换更为高效和实时。 分布式AI的应用实例 工业自动化 在制造业中,利用MQTT协议的实时数据传输和边缘计算的快速处理能力,AI系统能够及时分析生产线上的数据,预测设备故障,减少停机时间。 智慧医疗 在医疗保健领域,边缘AI的应用使得从远程监控到实时诊断变得可能。利用MQTT协议,医疗设备可以实时传输患者数据至边缘服务器,加速处理和响应。 面临的挑战与解决策略 安全性和隐私 边缘设备的分散性带来了安全挑战。解决这一问题需要开发更为强大的安全协议和加密技术,确保数据传输和处理的安全性。 互操作性 不同厂商和技术标准的多样性要求更高的互操作性。统一的通信协议和标准化的数据格式是实现这一目标的关键。 成本和复杂性 边缘计算的实施和维护可能涉及较高成本。通过优化资源分配和采用模块化设计可以在一定程度上降低成本和复杂性。 展望未来 随着技术的进步,未来的边缘AI将处理更复杂的任务,并且更加高效。MQTT将继续扮演关键角色,支持更加复杂的数据类型和通 信需求。 结论 结合MQTT和边缘计算的分布式AI不仅仅是技术的进步,它代表了一种新的工作和生活方式的转变。随着这些技术的发展,我们可以期待一个更加智能、高效和互联的世界。 --- ### 163. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 在物联网(IoT)的快速发展浪潮中,信息交换和设备互联成为核心问题。其中,一种名为MQTT(Message Queuing Telemetry Transport)的轻量级消息协议引起了广泛关注。本文将深入探讨MQTT在物联网中的作用,探究它是否真的是物联网领域的统治协议。 MQTT简介 MQTT是一种基于发布/订阅模式的轻量级消息传输协议。它最初由IBM在1999年为连接受限环境下的油管监控系统设计,现由OASIS标准化。MQTT的设计目标是提供一个带宽低、延迟小、数据包小的通信协议。 物联网中的MQTT 轻量级和高效性: MQTT在物联网设备上的资源占用极低,特别适合资源有限的嵌入式系统。 小型化的数据包减少网络带宽的占用,适用于低速网络。 稳定性和可靠性: MQTT支持多种服务质量等级,确保消息的可靠传递。 断线重连和遗嘱消息功能,确保网络不稳定时的通信连续性。 灵活的应用场景: 适用于智能家居、工业自动化、环境监测等多种场景。 支持私有部署和云平台,易于集成和扩展。 MQTT与其他物联网协议的比较 与CoAP: CoAP同样是为物联网设计的轻量级协议,基于RESTful架构。 CoAP适合使用HTTP模型的场景,而MQTT更适合持续数据流的通信。 与AMQP和XMPP: AMQP和XMPP更复杂,适用于企业级应用和更复杂的消息系统。 MQTT在物联网场景中因其简单性和低开销而更受青睐。 挑战和局限性 安全性问题:MQTT本身不包含复杂的安全机制,需结合TLS/SSL等技术保障数据安全。 标准化和互操作性:物联网设备和平台多样化,需要更统一的标准来保证不同设备间的互操作性。 结论 MQTT在物联网领域确实占据了重要地位,特别是在需要轻量级、高效、稳定通信的场景中。然而,它并非万能的。物联网的复杂性要求使用多种协议和技术的组合来满足不同的需求。MQTT作为其中一个重要组成部分,其在物联网的统治地位不是绝对的,而是与其他技术共同塑造物联网的未来。 --- ### 164. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 物联网(IoT)正迅速改变我们的世界,而核心推动力之一是背后的通信协议。本文将深入探讨五种关键的物联网协议:TCP/IP、UDP、HTTP、MQTT和CoAP,分析它们的特点、应用场景及相互间的关系。 1. TCP/IP:互联网的基石 基础:TCP/IP是一套通用的互联网协议,包括传输控制协议(TCP)和互联网协议(IP)。 特点: TCP提供可靠的数据传输,保证数据完整性和顺序。 IP处理数据包的路由,确保数据能找到正确的目的地。 物联网应用:TCP/IP适用于需要高可靠性的物联网应用,如远程监控和管理系统。 2. UDP:高效的数据传输 概述:用户数据报协议(UDP)是一个简单的传输层协议,不提供TCP的错误检查和纠正。 特点: 低延迟、低开销,适合实时数据传输。 不保证数据包的顺序和可靠性。 物联网应用:常用于实时视频流、在线游戏和VoIP等场景。 3. HTTP:Web通信的标准 简介:超文本传输协议(HTTP)是互联网上应用最广的协议。 特点: 基于请求/响应模型,适用于客户端-服务器通信。 与TCP/IP结合使用,保证数据的可靠传输。 物联网应用:适用于Web应用、云服务接入和设备管理。 4. MQTT:轻量级消息传递 定义:MQTT是一个基于发布/订阅模式的消息协议。 特点: 设计轻巧,适用于带宽受限和不稳定的网络环境。 支持异步消息传递,有效减轻网络负载。 物联网应用:广泛用于智能家居、工业自动化等需要轻量级通信的场景。 5. CoAP:物联网的Web协议 概述:受限应用协议(CoAP)是专为物联网设计的一种协议。 特点: 类似于HTTP但针对物联网环境进行了优化。 支持UDP传输,提高通信效率。 物联网应用:适合传感器网络、智能城市和环境监测等领域。 综合比较和应用场景分析 TCP/IP和UDP:适用于基础网络通信,选择取决于应用对数据传输的可靠性要求。 HTTP:优选于需要与Web服务交互的物联网应用。 MQTT和CoAP: MQTT适合需要高效、可靠消息传递的场景。 CoAP更适用于资源受限的环境,与Web技术集成度高。 结论 在物联网的复杂生态系统中,没有单一的协议能够满足所有应用的需求。因此,理解每种协议的优缺点和最佳应用场景至关重要。在实际应用中,通常需要根据具体需求灵活选择或组合这些协议,以实现最优的通信效果。 --- ### 165. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在过去的十年中,制造业取得了多项进步,有助于简化生产流程、降低成本并提高盈利能力。然而,尤其在能源使用和可持续性方面,仍存在一些问题和挑战。解决这些问题对于实现更环保、资源效率更高的制造业至关重要。基于开放标准(如MQTT)的创新解决方案可以帮助解决这些问题。在本文中,我们将深入探讨制造业领域的主要挑战以及如何通过边缘或云端的MQTT来克服这些挑战。 制造业的能源和可持续性挑战 以下是我们看到的一些阻碍制造商减少能源使用和提高可持续性的常见挑战: 使用专有设备和过时软件 制造设施通常处理具有专有通信协议和孤岛式设计的设备,导致不同系统无法相互通信。这些系统通常是基于即时需求而非长期战略设计的。它们由于需要额外资源来实现通信,妨碍了最佳能源使用,也影响了可持续性目标。 高能源和资源消耗 制造过程复杂且耗能。它们通常需要大量能源输入,导致高运营成本和碳排放的增加。此外,某些过程使用大量资源,如电力或水。在不影响生产效率的情况下优化能源和资源使用是一个重大挑战。 依赖不可再生能源 许多制造设施依赖于化石燃料等不可再生能源。由于生产压力、基础设施限制、成本、监管限制和对长期效益了解不足,向可再生能源转型并采用可持续最佳实践可能具有挑战性。制造商可能会优先考虑短期成本节约而非长期可持续性目标。 废物产生 制造过程产生大量废物,包括废料、副产品和污染物。适当的废物管理和回收策略对于减少环境影响并支持合规性至关重要。 供应链可持续性 可持续制造不仅关乎内部流程,还涉及整个供应链。确保供应商采用可持续实践可能具有挑战性,特别是在从环境标准较为宽松的地区采购原材料时。全球化供应链和竞争可能阻碍可持续性倡议的实施。 过时的设备和技术 较旧的制造设备可能缺乏节能特性,使得在不进行重大资本投资的情况下升级流程变得具有挑战性。工人可能不完全了解他们行为的环境影响或节能潜力。现代化设备、培训工人和采用工业4.0技术可能是一个渐进但必要的过程。 数据可见性不足 低效的监测和数据收集系统使得难以评估能源使用模式并识别改进领域。这也对实现可持续性最佳实践构成挑战。实施实时监控和数据分析对于做出明智决策至关重要。 解决这些问题需要结合技术创新、管理愿景、监管支持、员工参与和供应链合作的整体方法。致力于优化能源使用和促进可持续性的制造商可以探索一系列能效技术、可再生能源采用、废物减少策略和持续改进文化的组合,以克服这些挑战。最重要的是,他们需要采用智能制造以实现成功。 智能制造中的可持续之路 根据2022年麦肯锡研究,通过采用工业4.0技术(如工业物联网(IIoT)、人工智能(AI)、数字孪生、数字线程、增强现实(AR)、虚拟现实(VR))实现的智能制造优势,如停机时间减少30-50%、吞吐量增加10-30%、预测精度提高高达85%。在工业4.0技术和智能制造的最佳实践帮助下,制造行业正被转变回一个经济强国。 智能制造的一个关键方面是拥有企业数据增强策略,该策略使各种系统之间能够通过MQTT实现实时双向通信,为能源优化和可持续性铺平道路。 MQTT如何帮助改善制造业的能源使用和促进可持续性 MQTT是一种轻量级消息协议,专为工业物联网(IoT)和智能制造系统中的高效通信而设计。它是智能制造的一个组成部分。由于它在优化能源使用和促进智能制造中的可持续性方面提供的各种优势,它已成为从现场到企业或云的工业数据通信的事实标准。 以下是一些优势: 高效的通信数据包大小和消息有效负载 MQTT被创建为一个非常高效的基于事件的发布/订阅数据通信协议。消息数据包大小仅高达200KB,有助于最小化工业设备、系统、应用程序和代理之间交换的数据量,降低能源消耗。使用MQTT,设备、系统和应用程序仅接收相关信息,最小化不必要的数据传输。这也有助于优化带宽并减少运营成本。MQTT还允许通过使用高效的数据序列化格式(如JSON和协议缓冲区)来优化消息有效负载,减少网络带宽使用和能源消耗。 服务质量(QoS)等级、睡眠模式和边缘处理 MQTT提供了根据数据临界性选择合适的服务质量(QoS)级别的灵活性。这使用户能够优化他们的数据传输策略,确保效率和可靠性。更高的QoS级别确保消息传递,但可能导致增加的能源消耗。此外,鉴于MQTT的异步性质,设备可以在空闲期间实施睡眠模式以节约能源。设备可以根据MQTT触发器在有相关数据交换时唤醒。除了MQTT客户端外,本地代理允许在将数据发送到企业代理之前在边缘处理大部分数据,从而减少通过网络传输的数据量,从而节省能源。 设备配置、管理、监控和报告 可以使用MQTT数据实现远程设备配置和管理,以优化设备设置、更新固件和应用节能参数。此外,可以实施监控系统来跟踪能源使用和可持续性指标。可以根据预定义的阈值创建报告和异常警报,以识别改进领域。 可再生能源整合和系统优化 使用MQTT,可以实时监控能源消费和生产,以优化可再生能源的使用。例如,可以利用数据调整制造过程,根据绿色能源的可用性进行优化。此外,可以使用MQTT定期审查和优化基于变化需求、技术进步和节能机会的制造数据移动。 预测性维护和高级分析 借助MQTT实现的实时数据移动,可以实施预测性维护来监控设备健康。其结果是减少停机时间,提高效率,以及防止与故障机械有关的能源浪费。此外,可以使用MQTT数据实施高级数据分析和机器学习模型,提供能源使用模式的洞察,使得能够实施主动节能措施。 标准化、互操作性和持续优化 通过确保智能制造环境中的设备、系统和应用程序遵循MQTT消息标准进行数据互操作,制造商可以创建一个更灵活和可扩展的生态系统。同时,通过定期审查和修改MQTT实现,根据变化的制造要求,制造商确保他们正在优化他们的系统并为其投资未来。 结合人员、流程和技术,通过MQTT实现目标 通过创建基于MQTT的数据移动策略,建立正确的智能组织结构来利用它,以及去除障碍的流程,制造商可以创建一个更节能、更可持续的智能制造生态系统。关键是将基于MQTT的数据策略整合到考虑制造环境独特要求的全面制造战略中,并不断寻求改进机会。 智能制造通过这种方式,不仅提高了能效和可持续性,还为制造商带来了经济效益和竞争优势,是未来制造业发展的关键方向。 --- ### 166. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在物联网(IoT)不断扩展的格局中,对于高效、可扩展且可靠的通信框架的需求非常重要。MQTT,一种轻量级且健壮的消息传递协议,已成为构建物联网生态系统中设备间实时通信的首选解决方案。随着物联网部署在复杂性和规模上的增长,分片(sharding)概念登上舞台,带来了增强性能、容错能力和无与伦比的可扩展性的承诺。 在下面的2部分文章,我们将深入探讨MQTT分片集群的领域,解锁分布式系统间无缝通信的潜力。分片,即在多个节点/集群中分割数据的做法,已被证明是处理大量工作负载的改变游戏规则的做法。我们探究如何将MQTT与分片策略结合,赋予组织构建和管理其物联网应用的弹性、高性能通信网络的能力。 MQTT集群分片背后的挑战是什么? MQTT集群分片能够在可扩展性和性能方面提供显著好处,但它也带来了自己的一套挑战。 以下是一些与集群分片相关的常见挑战: 数据一致性: 在分片之间维持一致性可能是一个挑战。确保所有集群拥有一致且最新的信息至关重要,但在分布式系统中这可能相当复杂。 负载均衡: 在分片之间均匀分配负载是一个非常复杂的任务。平衡工作负载以避免某些集群过载而其他集群利用不足变得至关重要。 容错性: 在分片环境中处理故障并维持高可用性是一个挑战。如果一个分片出现故障,重要的是要有机制来重新路由流量并确保持续运行。 跨分片通信: 当连接到不同分片的设备或客户端需要通信时,可能需要进行跨分片通信。在不引入延迟的情况下有效管理这一点可能是一个复杂的任务。 弹性: 根据变化的工作负载动态调整集群大小(扩展或缩减)带来挑战。在保持系统稳定性和性能的同时增加或移除分片并不是直截了当就能处理的。 开发和维护的复杂性: 分片架构在开发、测试和维护中引入了复杂性。在分片环境中编写应用程序和管理基础设施需要更高级别的专业知识。 数据迁移: 在扩展或缩减规模,或者在节点故障的情况下,可能需要在分片之间进行数据迁移。在不引起停机或数据丢失的情况下管理这一过程是一个重大挑战。 监控和调试: 监控分片系统和调试问题可能比在非分片环境中更具挑战性。理解每个分片的状态并识别问题来源需要强大的监控工具和实践。 双向通信: 在分片的MQTT架构中保持双向通信的一致性本身可能成为一个挑战,尤其是在路由方面。 成本考虑: 分片引入了额外的基础设施和操作复杂性,这可能转化为硬件、维护和操作开销的更高成本。 解决这些挑战需要谨慎的设计、实施和持续维护工作。重要的是权衡可扩展性的好处与集群分片引入的复杂性,并选择与应用程序或系统的特定需求相符的架构。 MQTT集群分片的极限是什么? 实施MQTT部署中的分片存在一定的限制和挑战。了解这些限制以做出明智的决策并解决潜在问题至关重要。 以下是MQTT分片的一些限制: 消息排序: 分片可能会在跨分片保持消息顺序方面带来挑战。在分片环境中,来自不同分片的消息可能会以错误的顺序到达目的地,影响对消息顺序至关重要的场景。 会话持久性: 跨集群会话持久性是不可能的。如果客户端重新连接到另一个集群,它将以新会话开始。如果客户端连接时有消息在等待,您需要有一个外部服务来确保客户端即使连接到另一个集群也能正确接收消息。 跨分片通信开销: 跨分片通信可能引入额外的延迟和开销。当连接到不同分片的设备或客户端需要通信时,可能涉及跨分片通信,这可能比同一分片内的通信效率低。 跨分片的一致性: 确保分片间数据的一致性可能很复杂。在需要强一致性的场景中,管理跨分片的分布式事务和同步可能引入挑战。 开发和维护的复杂性: 分片引入了开发、测试和维护的复杂性。开发人员需要了解分片策略,并实施自定义逻辑以处理跨分片通信和潜在冲突。 受限的用例: 分片可能不适合所有用例。某些数据量低或通信模式简单的应用程序可能不会从分片中获得显著好处,增加的复杂性可能超过优势。 对现有应用程序的影响: 在现有MQTT部署中实施分片可能需要修改应用程序逻辑,并可能影响现有客户端的行为。这可能引入向后兼容性的挑战。 资源争用: 当多个分片竞争共享资源,如数据库、网络带宽或处理能力时,可能会发生资源争用。这种争用可能影响整个系统的性能和响应能力。 向下扩展的困难: 虽然为了扩展而增加分片是一个相对简单的过程,但通过移除分片来缩减规模可能更具挑战性。在缩小集群规模时,迁移数据和重新分配负载可能更加复杂。 标准化的缺乏: 分片策略通常是特定于应用的,缺乏标准化的分片机制可能使在不同MQTT部署中实施互操作解决方案更具挑战性。 运营开销增加: 管理分片环境引入了额外的运营开销。监控、故障排除和维护分片MQTT集群需要专门的知识和工具。 尽管存在这些限制,许多组织通过在MQTT部署中采用分片来实现可扩展性和性能优势。关键在于仔细评估应用程序的特定需求,考虑权衡,并实施与系统总体目标一致的分片策略。 --- ### 167. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 据Precedence Research称,全球制药制造市场预计到2030年将以近13%的复合年增长率增长到11.90亿美元。然而,根据IBISWorld的数据显示,尽管预期收入表现强劲,但由于低成本通用药品、生物仿制药的竞争加剧以及多种重磅药物专利到期,同期行业利润预计将下降。 制药制造业面临着几个额外的压力,这些压力影响了他们将安全有效的药物从研发快速推向市场的能力,从供应链中断到监管要求。单独的合规管理既耗时又成本高昂,不合规可能导致重大罚款或法律诉讼。该行业需要以成本效益高的方式解决这些挑战,同时不影响质量和效率。 引入制药4.0制药界越来越多地转向整合数字技术和自动化以解决这些问题。这种方法被称为制药4.0,这个概念借鉴于工业4.0。制药4.0涉及使用先进技术,如人工智能、机器学习、机器人技术和工业物联网(IIoT),以提高药物研发、制造和分销中的效率、质量和安全性。这一举措的目标是: 提高效率:自动化整个制造线路和地点的流程。 加强质量控制:应用实时监控和分析,快速识别并解决问题,以免它们在流程中成为普遍现象。 更快创新:使用数字技术更快响应变化,快速识别并从昂贵的错误或失败的尝试中恢复。 人们希望这种类型的数字化转型将允许高质量、成本效益高的药品更快地进入市场,这样制药公司就可以更多地专注于新药的研究。 尽管制药制造已开始适应IIoT及其潜力,但GEP称,仅有30%的前20大制药公司在其制造过程中采用了某种程度的IIoT技术。这表明,在通过正确部署IIoT解决方案来改善运营方面,制药制造业还有很大的潜在价值。 数据和制药4.0收集、理解和分析数据是采用制药4.0的关键。制药公司每天产生大量数据,从实验室实验到制造再到供应链管理。这些数据有潜力帮助制药制造商做出更明智的决策,优化流程,并推动以下领域的增长。 合规性制药业可能是监管最严格的行业之一,遵守如食品和药物管理局(FDA)、药品和保健品监管局(MHRA)、欧洲药品管理局(EMA)等监管机构的规定可能极为具有挑战性。确保合规性需要准确的数据追踪、零数据丢失、安全存储和报告,而没有数据自动化,这一切都很难实现。例如,在美国,FDA的21 CFR第11部分规定,所有药品制造数据的电子记录需要以原始未解释格式保留至少7年,用于审计。 有效的合规程序对于防止业务中断和因审核失败而损失声誉至关重要。因此,制药制造商必须保持严格的质量控制、详细的产品信息、数字化批次记录,以及运营技术(OT)和信息技术(IT)系统之间的持续数据集成。 运营效率运营效率指的是在制药制造中实现高可见性、信息透明度、强大的安全性、有效的工作管理和流程跟踪的能力。由于需要考虑众多因素,制药制造公司越来越难以实现运营效率。 一种改进方式是应用复杂算法处理流程数据,这得益于更好的计算能力和存储能力。新常态是依靠数据驱动数字创新和运营效率决策,而不是凭直觉。实际上,数据是制药制造组织最宝贵的资源。 质量控制制药制造中的质量控制旨在验证和测试生产各阶段的药品,确保每个产品都具有最高质量。质量控制还涉及识别产品中的任何缺陷,并使用纠正技术和措施解决这些问题。数据使得跟踪质量测量成为可能,确保生产条件最佳等。 制药4.0 - 旅程 如图1所示,从数据收集到制药制造中的数字成熟度旅程是一个分析、上下文和洞见被添加到从设备或系统捕获的原始数据中的过程,将其转化为信息、知识,最终为决策者提供可操作的智慧。 实现制药4.0的数据成熟模型的阶段。图1:实现制药4.0的数据成熟模型的阶段。 首先,从喂料机、湿法造粒机、平板干燥机、压缩机、冻干机等制药制造机器/流程中收集数据。然后对这些数据进行标准化、数字化和组织为大数据。接下来,添加意义(或标签),并通过AI将数据综合成知识。最后,数据被转化为通过数字成熟度获得的可操作智慧。 数据收集 - 第一前沿实现制药4.0数字成熟度的第一个也是最重要的前沿是数据收集和移动。从制药制造机器、流程和应用程序中捕获并存储的数据通过关键摄取技术。在运营技术(OT)方面,数据存储在控制器、PLC、网关和边缘设备中,在IT方面,数据存储在数据中心或企业云中。数据存储技术使从高级传感器和系统捕获的数字化数据的长期存储成为可能。这种数据 丰富的环境使得如机器学习、AI、自适应控制和数字孪生等高级倡议成为可能。 制药数据收集挑战在制药制造中进行数据收集和数据移动存在一些挑战。制药制造工厂中的机器和流程是异构的,使用各种协议进行通信。在制药制造期间生成的数据在格式、质量和完整性方面可能有很大差异。这可能使得收集、整合和分析数据变得困难。 由于工厂系统的古老、遗留性质,数据连接也是一个主要问题。因此,IT和OT系统通常没有简单的方式来通信,以实现制药4.0计划。 工业物联网(IIoT),制药4.0的一个子集,使用智能传感器和执行器以及软件来整合数据,以增强制造和工业流程。IIoT是实现OT IT融合和各种通信协议互操作性的关键推动者。它在中间创建了一个数据抽象层和一个共同的数据语言,以翻译各种通信协议,实现互操作性。 IIoT作为OT和IT系统之间的交汇点 图2:IIoT作为OT和IT系统之间的交汇点 OT IT融合之所以重要,是因为在当今互联工业景观中的成功取决于协作。IIoT正在改变制造商的工作方式,模糊了IT和运营之间的界限。例如,IT专业人员现在可能会花更多时间在工厂地板上与设备一起工作,而OT团队则必须专注于网络安全和网络最佳实践。IT-OT融合并不是要将IT专业人员变成重型机械操作员,或将工厂工程师变成数据科学家。相反,它是关于创建一个策略,弥合这一差距,让组织能够通过围绕一套统一的目标和KPIs工作,以提高运营性能。 制药数据收集解决方案 - MQTT和数据代理数据代理是实现这一数据抽象层的关键IIoT技术推动者。数据代理是一个中介实体,使OT和IT客户端系统能够相互通信。使用MQTT等底层标准,数据代理支持连接多个发布数据的客户端和多个订阅接收数据的客户端,例如企业应用程序。与代理通信的客户端可以抽象出机器/流程使用的底层协议。由于底层的发布/订阅方法,代理在低带宽环境下以不可靠的通信机制工作得很好,因为机器/流程不需要不断轮询以获取数据。 MQTT是一种标准的二进制发布-订阅消息协议,专为在非常受限条件下的设备之间快速可靠地传输数据而设计。这些约束包括不可靠的网络连接、有限的带宽、有限的电池电力和类似的受限条件。它建立在TCP/IP之上,后者是互联网上连接网络设备的首选通信协议。由于上述原因,MQTT非常适合IIoT。 MQTT消息系统的工作方式 图3:MQTT消息系统的工作方式 MQTT数据代理可以在发布客户端(通常在OT端)和订阅客户端(在IT端)之间安全地传递数据。例如,一个制造执行系统(MES)应用可能希望从SCADA系统获取数据,以便轻松地运行其分析来识别批次变异。该MES应用将运行一个订阅了代理的MQTT客户端。SCADA客户端将数据发布到代理。因此,订阅了代理的MES应用将自动获取更新,无需轮询数据。 MQTT技术旨在将数据从数千个远程设备推送到企业。Sparkplug是一个构建在MQTT之上的框架,为制造数据添加更多上下文。它是一个开源软件规范,为MQTT客户端提供了一个框架来集成数据并通过定义数据模型提供上下文。它为制药制造设备制造商和软件提供商提供了一种一致的方式来共享上下文数据,加速现有操作的数字化转型。 Sparkplug允许IIoT部署在硬件和软件源之间解耦数据。使用Sparkplug,新的数据源可以立即被其他系统组件发现,并且这些源可以成为单一真理来源。Sparkplug完全安全,不需要为新设备打开端口,并要求所有数据传输使用TLS。 MQTT使制药制造的数字化转型通过制药4.0实现打造一个基于MQTT的企业消息平台,旨在快速、高效和可靠地将数据从制造机器、流程、应用程序和供应链组件移动到企业数据位置,无论是在本地还是在云中。采用MQTT代理使客户能够优化供应链、自动化法规合规报告、提高运营效率并增强产品质量,包括启用数字批次记录。 业务关键可靠性:使用零消息丢失和冗余集群技术可靠地操作关键任务系统24/7。 端到端安全:确保应用程序和数据符合最高安全标准,具有端到端加密和可配置的安全控制。 支持增长的可扩展性:通过线性设计的可扩展性,无缝添加任意数量的站点并扩展到数百万个连接设备。 可观测性见解:使用工具和指标进行故障排除,并保持所有工厂系统按计划运行,以实现透明性和可观测性。 灵活集成:专注于核心业务,而不是使用开发资源,将OT-IT数据集成到企业应用程序和基础设施中,如Apache Kafka。 易于部署:使用足够灵活的平台,可在本地、任何云中部署. 制药制造IIoT用例参考架构以下是制药制造中供应链优化和法规报告用例的常见架构: 用例1:制药供应链优化制药供应链经理希望根据源自采购、供应商库存和运输的领先指标,在中央位置触发必要的工作流程。供应链绩效数据通过MQTT代理流向云提供商的基础设施,然后被摄取、分析或监控。 制药供应链优化 用例1:制药供应链优化 在这种情况下使用MQTT代理有两大优势。首先,它提供了一个非常可扩展的解决方案,可以负载平衡来自不同系统的控制数据,这些系统可能位于全球各地的偏远地点。其次,它提供了工具,以提供高水平的工厂IIoT数据可观测性和透明度,以克服任何数据瓶颈,无论是前往云端还是返回远程位置。 用例2:法规报告启用鉴于制药公司药品销售量不断增加,监管审查和执法行动肯定会继续。该行业将面临挑战,需要超越当前的危机管理方法,实施全面的战略性方法,将合规性融入公司的业务方式中。 通常是手工完成的批次记录,它保持所有制造步骤的详细信息,需要被数字化。MQTT可以帮助确保制造商符合FDA 21 CFR第11部分和/或欧洲医药署的审计合规性,方法是确保制造批次记录数据以及其他工厂数据通过MQTT代理流向云提供商的基础设施。在这里,原始数据存储在数据湖中,可以创建自动化报告和仪表板。 下一步:探索MQTT为制药4.0提供的解决方案正如所讨论的,转向制药4.0是一个实际的、关键的业务举措。在制药制造中,数据是最有价值的资源,是提高药物开发、制造和分销中的效率、质量和安全性的基础和衡量标准。在MQTT云平台,我们已经帮助许多制药公司开始了他们向制药4.0的转型之旅,并欢迎讨论为您的业务需求量身定制的解决方案。 --- ### 168. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 上周,全球最重要的开源软件基金会之一 Eclipse 基金会与 Eclipse Sparkplug 工作组合作,宣布了工业物联网 (IIoT) 发展的一个重要里程碑。 Eclipse Sparkplug 规范已作为国际标准正式发布,现称为 ISO/IEC 20237! Sparkplug 标准化推动 IIoT 发展 这一成就预示着工业物联网连接的新篇章,Sparkplug 规范为不同的工业系统提供了一种轻松通信和交换数据的通用方法。Eclipse Sparkplug 被认可为国际标准非常重要,因为它可以促进互操作性、增强信任和采用、推动创新、扩大市场准入、确保法规遵从性并简化 IIoT 领域的协作。  这一成就标志着在创建更加互联、高效和创新的工业格局方面向前迈出了重要一步。  什么是 MQTT Sparkplug? Sparkplug是一种开源软件规范,为 MQTT 客户端提供框架,以双向和可互操作的方式将来自 MQTT 基础设施内的应用程序、传感器、设备和网关的数据无缝集成。 MQTT Sparkplug的优势 为什么要选择MQTT Sparkplug?这个规范提供了许多优势: 数据互操作性: 通过统一的消息结构和协议规则,Sparkplug确保不同设备之间的数据能够互操作,无需在通信上投入大量精力。 说明:无论哪家供应商提供的温度传感器,它们都能够在相同的系统中无缝运行,因为它们遵循了相同的Sparkplug规范。 节省带宽和资源: 通过“按异常报告”的状态管理方式,减少了不必要的轮询,从而节省了带宽和计算资源。 说明:使用Sparkplug,系统可以立即知道设备的状态变化,而不必频繁轮询设备,从而减少了通信开销。 支持传统设备: 即使某些设备不支持Sparkplug或MQTT,它们仍然可以通过使用EON节点来与系统集成。 说明:即使某个设备使用传统的通信协议,它可以通过连接到支持Sparkplug的EON节点来参与整个系统。 自动设备发现: Sparkplug关注统一性,使系统能够自动发现网络上的设备和数据。 举例说明:当新设备添加到系统中时,它们可以自动被发现并集成,而无需手动配置。 开源规范: Sparkplug是一个开源技术,无需许可,并且可以根据需要进行定制。 举例说明:无需支付昂贵的许可费用,您可以自由地采用和修改Sparkplug规范,以满足您的特定需求。 --- ### 169. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 引言 在这个数字化和互联网快速发展的时代,串口服务器和MQTT协议在物联网(IoT)和远程通信领域发挥着越来越重要的作用。串口服务器作为连接传统串行设备和网络的桥梁,通过集成先进的MQTT协议,为数据通信带来了革新。本文将深入探讨串口服务器集成MQTT功能的重要性及其在现代通信系统中的应用。 串口服务器的重要性 串口服务器使得旧式串行设备能够接入现代网络系统。 提供了一种低成本的方式来远程访问和管理串行设备。 MQTT协议的角色 MQTT,作为一种轻量级的消息传输协议,特别适用于带宽有限的环境。 它的发布/订阅模型非常适合处理来自大量分布式设备的数据。 2. 串口服务器概述 串口服务器是一种将串行通信转换为网络通信的设备,它使得原本只能通过串行端口进行通信的设备能够通过网络进行数据传输。 定义和工作原理 串口服务器的定义:一种使串行设备接入网络的设备。 工作原理:将串行数据包转换为网络数据包,反之亦然。 串口服务器在不同行业中的应用 工业自动化:串口服务器用于连接传感器、控制器等工业设备,实现远程监控和控制。 医疗健康:在医疗设备中使用串口服务器来实现数据的实时监测和远程诊断。 零售和物流:串口服务器在物流跟踪系统中用于数据收集和设备管理。 智能建筑:用于监控和管理建筑自动化系统中的各种设备。 3. MQTT协议简介 MQTT(Message Queuing Telemetry Transport)协议是一种基于发布/订阅模式的轻量级消息传输协议,特别适用于物联网环境。 基本概念和工作原理 轻量级和高效:MQTT协议设计简洁,适用于带宽有限和不稳定的网络环境。 发布/订阅模型:允许多个客户端订阅特定主题,服务器将消息分发给订阅该主题的客户端。 MQTT的主要特点和优势 低功耗:适合电池供电的设备。 可靠的消息传递:提供不同等级的服务质量(QoS)。 灵活的通信方式:适合各种规模和复杂度的通信需求。 4. 串口服务器结合MQTT功能的重要性 将MQTT协议集成到串口服务器中,为传统串口通信带来了新的可能性,特别是在物联网应用中。 为何将MQTT集成到串口服务器中 扩展传统设备的功能:使得旧式串口设备能够接入现代的物联网系统。 提高数据传输效率:利用MQTT的高效传输,减少网络带宽的占用。 MQTT在串口通信中的优势 远程访问和控制:通过互联网远程访问串口设备。 实时数据通信:实时传输传感器数据和控制命令。 5. 串口服务器的MQTT功能详解 串口服务器的MQTT功能使其成为物联网领域的强大工具。 MQTT客户端与服务器的交互 连接管理:如何建立和维持设备与MQTT服务器之间的连接。 消息的发布和订阅:详细说明设备如何发布数据和订阅来自其他设备的数据。 通信质量和服务等级(QoS)的管理 不同QoS等级的应用场景:从QoS 0到QoS 2,不同的服务质量等级适用于不同的应用需求。 保障数据的可靠传输:如何确保在不稳定的网络环境下传输的可靠性。 主题订阅和消息发布的机制 主题的灵活性:如何定义和使用MQTT主题以适应不同的应用场景。 消息过滤和分发:服务器如何处理大量的消息并将它们正确地分发到订阅的客户端。 6. 应用实例分析 串口服务器配合MQTT协议能够在多种场景中提供高效、可靠的通信解决方案。 物联网(IoT)设备的数据集成 智能家居:串口服务器使得旧式家电通过MQTT接入智能家居系统。 工业监控:在工业环境中,实时监控传感器数据和机器状态。 远程监控和管理系统 基础设施监控:例如,远程监控电力网和水务系统。 远程设备维护:提供设备故障诊断和维护的能力。 工业自动化和智能家居系统 自动化控制:利用MQTT实现设备间的实时通信和自动化控制。 能源管理:在智能建筑中优化能源消耗。 7. 技术挑战与解决方案 在实施串口服务器和MQTT功能时,存在一些技术挑战需要克服。 网络安全性和数据加密 加密通信:实现端到端加密以保护数据安全。 访问控制:使用认证和授权机制保护设备和数据。 确保高可靠性和低延迟 网络优化:选择适合的网络协议和硬件以减少延迟。 负载均衡:确保系统在高负载下仍能稳定运行。 兼容性和可扩展性问题 协议适配:确保串口服务器与不同MQTT版本的兼容性。 系统扩展:设计可扩展的系统以适应不断增长的设备数量和数据量。 8. 未来展望 随着物联网技术的发展,串口服务器结合MQTT功能的应用将不断扩大。 MQTT和串口服务器技术的发展趋势 更高效的协议:发展更加高效和安全的通信协议。 广泛的应用领域:从工业到消费者电子,应用领域的扩大。 新兴应用领域和潜在市场 智慧城市:在城市管理中的应用。 远程医疗:用于医疗设备的远程监控和数据收集。 9. 结论 串口服务器的MQTT功能是实现高效、可靠的物联网通信的关键。通过不断的技术创新和应用拓展,这一功能将在未来的通信和自动化领域发挥更加重要的作用。 --- ### 170. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 (一)MQTT是机器对机器(M2M)/物联网(IoT)连接协议 它被设计为一个极其轻量级的发布/订阅消息传输协议。对于需要较小代码占用空间和/或网络带宽非常宝贵的远程连接非常有用,是专为受限设备和低带宽、高延迟或不可靠的网络而设计。该协议基于发布/订阅模式(Publish/Subscribe Pattern),支持多种质量等级(Quality of Service, QoS),可以实现可靠的消息传输和传输后的可靠存储。在MQTT中,发布/订阅模式的实现包括以下几个核心概念: 1. 主题(Topic): 主题是MQTT中消息的标识符,用于指定消息的内容和接收者。主题由一个或多个主题等级(Topic Level)组成。 2. 客户端(Client): MQTT中的客户端是指连接到MQTT代理服务器的设备或应用程序,它可以是发布者或订阅者。 3. 代理服务器(Broker): MQTT中的代理服务器是指负责接受、路由和转发消息的中间件。代理服务器会维护一个或多个主题,客户端可以向代理服务器发布消息或订阅主题。 4. 发布者(Publisher): MQTT的发布者是指发布消息的客户端。发布者将消息发送到代理服务器,代理服务器会根据消息的主题将其路由到订阅了相应主题的订阅者。 5. 订阅者(Subscriber): MQTT中的订阅者是指订阅主题的客户端。订阅者向代理服务器订阅特定主题,代理服务器会将订阅者的主题和相关信息保存在订阅列表中。当有新消息发布到订阅者订阅的主题时,代理服务器会将消息发送给订阅者。 在MQTT的发布/订阅模式中,发布者和订阅者之间是解耦的,他们不需要知道对方的存在和身份,只知道相应的主题即可。 图1:MQTT功能架构 (二)规则引擎是一种嵌入在其他应用程序中的程序组件 能够将业务决策从应用程序代码中分离。业务人员可以使用预定义的规则语义模块编写业务规则。规则引擎解析业务规则,接受数据输入,并根据业务规则做出业务决策。通过编写业务规则,就可以改变数据的处理逻辑,而不需要重新编写应用程序的代码。基于 MQTT 的规则引擎允许用户在物联网平台中定义和执行基于 MQTT 消息的规则。它使用 MQTT 主题(Topic)作为规则的触发器,并根据预定义的条件和逻辑,对接收到的消息进行处理和决策。 规则引擎通常由以下几个组件构成: 1. 规则定义: 如图2,用户可以定义和配置规则,包括规则的触发条件、处理逻辑和动作。规则的触发通常是基于MQTT主题的发布或订阅。 图2:规则定义组成图 2. 规则匹配: 如图 3 ,当接收到一个 MQTT 消息时,规则引擎会将其与已定义的规则进行匹配,以确定触发了哪些规则。 图3:配置流程图3.规则执行: 一旦触发了特定的规则,规则引擎将执行该规则定义的处理逻辑和动作。这可能涉及到对消息进行过滤、转换、聚合、存储或发送。4.动态更新: 基于 MQTT 的规则引擎通常支持动态更新规则,即在运行时修改和添加规则而无需停止和重新启动引擎。这种灵活性和实时性使得规则引擎能够适应动态变化的物联网环境。基于 MQTT 的规则引擎可以广泛应用于物联网平台中的数据处理、事件触发、自动化控制等场景,能够实现实时、可靠的消息传输和智能化的规则处理,提供高效的物联网应用服务。 基于MQTT的分布式规则引擎关键技术 (一)MQTT跨域集群 MQTT 跨域集群(MQTT Geo-Distribution)是一个创新架构,允许部署在不同地区或云上的 MQTT Broker 作为一个单集群一起工作。通过跨域集群,MQTT 消息可以在不同地区的 MQTT Broker 之间自动同步和传输。有两种方法可以实现 MQTT 跨域集群: 单集群,多地区:单个 MQTT 集群,每个节点在不同地区运行。 多集群,多云:分布在不同云中的多个 MQTT 集群连接在一起。 将这两种方法结合,在跨区域部署的 MQTT Broker 之间创建一个可靠的物联网数据基础设施。通过 MQTT 跨域集群,企业可以建立一个跨多云的全球 MQTT 接入网络。不管所处的物理位置在哪里,设备和应用都能从最近的节点接入实现相互通信。(二)分布式计算 分布式计算是将任务分解并分配到多个计算节点上进行并行处理的技术,可以实现高可用性。当某个节点故障或不可用时,其他节点可以接管任务,保证系统的连续性和稳定性。分布式规则引擎可以自动判断和优化规则的执行位置,因此数据流可以被分发到多个处理节点上,并行地执行规则,实现更低延迟、高吞吐量的规则处理、以及负载均衡。这样可以充分利用资源,避免单个节点负载过重,提高系统的整体性能和效率,还可以根据业务需求灵活地增加或减少计算节点,使得系统可以根据实际情况动态调整,满足业务弹性变化的需求。(三)MQTT Streams MQTT Streams 是 MQTT 协议的一项扩展能力,能够在 MQTT Broker 内实时处理海量、高频的数据流。这在发布订阅模式消息传输的基础上进一步增强了传统 MQTT Broker 的能力。通过 MQTT Streams,客户端可以像 Apache Kafka 一样将 MQTT 消息以流的形式进行生产和消费,从而实现历史消息回放。这对事件驱动的处理尤为重要,可以确保最终的数据一致性、可审计和合规性。流处理对于从物联网设备产生的大量数据中实时挖掘商业价值至关重要。以前,这一过程通过一个过时且复杂的大数据堆栈实现,需要 MQTT Broker 与 Kafka、Hadoop、Flink 或 Spark 进行集成。而通过内置的流处理,MQTT Streams 简化了物联网数据处理架构,提高了数据处理效率和响应时间,并为物联网提供了一个统一的消息传递和流处理平台。通过消息去重、消息重放和消息过期等功能,MQTT Streams 实现了高吞吐量、低时延和容错,使其成为基于 MQTT 的物联网应用中实时数据流处理的强大工具。(四)MQTT Serverless 云计算中 Serverless 模式的兴起标志着应用的设计、开发、部署和运行方式发生了突破性的范式转变。这种模式下开发者将能够专注于应用的业务逻辑,无需管理基础设施,从而提高敏捷性、可扩展性和成本效益。传统的物联网应用需要数分钟甚至数小时才能在云上或在企业私有环境中部署 MQTT 消息服务,相比之下,Serverless MQTT 只需点击几下就能快速完成 MQTT 服务的部署。除了极快的部署速度,Serverless MQTT 更大的价值在于其无可比拟的灵活性:根据用户需求对资源进行无缝扩展。Serverless MQTT 有望推动 MQTT 更广泛的应用,降低运营成本,激发不同行业的创新协作。 协同计算与联邦学习 基于MQTT的分布式规则引擎可以实现实时的消息传输和处理,结合协同计算和联邦学习,可以在分布式系统中进行实时的模型更新和预测,从而实现实时的智能决策能力;此外,还可以将多个边缘设备的计算和模型合并起来,共同完成数据处理和分析任务,共同推断并制定智能决策,从而使得分布式系统能够更好地适应不同设备上的个性化需求,并进行更准确的决策。将联邦学习与基于MQTT的分布式规则引擎结合,可以实现更高的数据隐私保护、分布式智能决策、高效的资源利用和实时决策能力,提升系统的数据协同效果和和用户体验。 技术价值 基于物联网场景的分布式规则引擎具有以下技术价值: 1. 实时性: 可以实时处理物联网中生成的大量数据,对数据进行实时的分析、决策和反应,能够为物联网应用提供更高的响应性和效率。 2. 大规模数据处理: 通过将计算任务分布到多个节点上,并行计算能力使得数据处理速度更快,帮助企业处理和分析大规模实时数据,并根据预定义的规则执行相应的决策和操作。这对于需要对实时数据进行智能分析和决策的行业,如智能城市、智能工厂、物流和供应链管理等,具有重要意义。 3. 灵活性和可扩展性: 具备灵活性和可扩展性,可以根据不同的应用场景以及系统规模和需求的增长,进行水平扩展并动态地配置和调整规则。同时,通过增加或减少节点,使系统具备良好的可扩展性,能够适应不同规模的物联网部署。 4. 自动化决策: 能够根据设定的规则和条件,自动化地进行决策和执行,可以根据物联网中的数据进行实时分析,根据设定的规则作出相应决策并执行操作,为物联网应用提供智能化的自动化决策能力。这对于需要快速响应和自动化决策的行业,如交通、电力、医疗等,具有重要意义。 --- ### 171. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网协议概述 物联网,简称IoT (Internet of Things),是通过网络将各种物体连接起来的技术。为了实现这一目的,多种协议被设计用于不同层次的通信和数据交换。物联网协议大致可以分为传输协议和通信协议。 1. 传输协议 传输协议是物联网系统中的基础,它们负责在子网内的设备之间建立通信连接。以下是一些常见的传输协议: Wi-Fi: 是最常见的无线通信技术,主要用于短距离的高速数据传输。 Zigbee: 是一个基于IEEE 802.15.4标准的低功耗、低数据速率的无线通信协议,广泛用于家庭自动化、医疗保健和工业控制等场合。 5G: 是第五代移动通信技术,提供高速、大容量和低延迟的通信服务,适合物联网中需要实时性和大数据处理的应用。 LoRa: 一种长距离、低功耗的无线通信技术,适用于农业、物流和城市管理等领域。 Bluetooth & BLE (Bluetooth Low Energy): 适用于短距离的低功耗通信,常用于穿戴设备和健康监测。 2.通讯协议 MQTT (Message Queuing Telemetry Transport) 描述:MQTT是一个基于发布/订阅模型的轻量级通讯协议。它在带宽有限或不稳定的网络环境中非常有用,因为它需要的头信息非常小。 应用:家庭自动化、车联网、工业物联网、健康监测设备、农业和气象观测。 Modbus TCP 描述:Modbus是工业领域中常用的一种通讯协议,TCP版本是其在TCP/IP网络上的实现。 应用:工业自动化、楼宇自动化系统、SCADA系统、能源管理系统。 HTTPS (Hypertext Transfer Protocol Secure) 描述:HTTPS是一个用于安全通讯的协议,它结合了HTTP和SSL/TLS协议。 应用:任何需要安全数据传输的应用,如在线购物、银行业务、社交媒体和电子邮件。 CoAP (Constrained Application Protocol) 描述:CoAP是一种专为小型、低功耗设备设计的Web传输协议。 应用:智能家居、智能城市、环境监测、健康监测。 UDP (User Datagram Protocol) 描述:UDP是一个简单的面向数据报的通讯协议,不保证数据包的顺序或可靠性。 应用:流媒体、在线游戏、VoIP。 TCP (Transmission Control Protocol) 描述:TCP是一种面向连接、可靠的数据传输协议,它确保数据的完整性和顺序。 应用:Web浏览、文件传输、电子邮件。 GB/T28181 描述:这是公共安全视频监控联网系统的国家标准。 应用:城市监控、交通管理、公共场所安全。 OPC-UA & OPC-DA 描述:OPC是工业自动化领域的数据交换标准,UA是其最新版本,支持跨平台。 应用:制造业、能源、油气、化工。 LoRa (Long Range) 描述:LoRa是一种长距离、低功耗的无线通讯技术。 应用:智慧农业、智慧城市、远程计量、动植物追踪。 特定行业协议 JT/T 808 描述:JT/T 808是针对“两客一危”车辆的通讯协议,规定了车载终端与数据中心之间的通讯格式和数据交换方式,从而实现对车辆的实时监控和管理。 应用:广泛应用于交通行业,特别是对于客运车辆、危险品运输车辆的远程监控。 HJ212 描述:HJ212是环保行业的在线自动监测数据传输标准,规定了数据格式、通讯协议和接口要求,为环境监测设备和监测中心之间的数据传输提供标准。 应用:主要用于环保行业,确保各种在线监测设备与上级监控中心的数据传输统一和准确。 SL651 描述:SL651协议是水文监测数据通信规约,为水文监测设备提供了统一的数据交换和通讯格式。 应用:广泛应用于水文监测领域,包括河流、湖泊、水库、地下水等各种水文监测场景。 GB3761 & DL645 描述:GB3761和DL645是国家标准的电表通讯协议,规定了电能计量设备的数据格式和通讯方式。 应用:广泛应用于电力行业,包括家庭、商业、工业等各种电能计量场景。 IEC104 描述:IEC104是一种电力和城市轨道交通的远动信息网络传输规约,规定了设备之间的通讯格式和数据交换方式。 应用:主要用于电力和城市轨道交通行业,确保各种设备与监控中心之间的数据传输顺畅和准确。 --- ### 172. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、MQTT协议简介 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种基于发布/订阅(publish/subscribe)模式的轻量级通讯协议。该协议构建于TCP/IP协议之上,由IBM于1999年首次发布。 MQTT的关键优势 MQTT的最大优点在于其能够以精简的代码和有限的带宽提供实时可靠的消息服务,因此在连接远程设备方面具有独特的优势。作为一种低开销、低带宽占用的即时通讯协议,MQTT在物联网、小型设备和移动应用等领域得到广泛应用。 MQTT与HTTP的对比 传统互联网应用通常广泛使用HTTP协议。然而,物联网环境下的挑战与传统互联网不同,这包括不稳定的网络连接和设备资源有限的情况。以下是MQTT相对于HTTP的优势: 网络适应性: MQTT在不稳定的网络环境中表现出色,适用于连接质量较差的情况。 资源效率: 由于物联网设备通常具有有限的计算和通信资源,MQTT的轻量级特性使其成为理想选择。 消息大小: 物联网传输的消息通常较小,相比之下,HTTP的请求-响应模式在这种情况下效率较低。 实时性: MQTT的发布/订阅模式允许设备订阅感兴趣的主题,实现实时消息推送,而HTTP通常需要设备主动轮询以获取数据,降低了实时性。 成本效益: MQTT在物联网应用中降低了数据传输成本,尤其是在大规模设备部署的情况下。 二、MQTT协议设计原则 MQTT协议的设计遵循一系列关键原则,这些原则使其成为物联网通信的理想选择: 精简而高效: MQTT坚决避免添加不必要的功能,使协议保持精简。这确保了它的性能出色,不浪费计算和带宽资源。 发布/订阅模式: MQTT采用发布/订阅(Pub/Sub)模式,这意味着设备可以轻松地发布和订阅消息,从而方便了消息在传感器之间的传递。 动态主题创建: MQTT允许用户动态创建主题,无需运维成本。这使得设备和应用可以根据需要自由定义消息主题,增加了灵活性。 最小传输量: MQTT致力于将传输数据的量降到最低,以提高传输效率。特别是对于低带宽、高延迟和不稳定的网络,这一点尤为重要。 会话控制: MQTT支持连续的会话控制,有助于维护设备的连接状态和通信的一致性。 适应性: MQTT理解到客户端的计算能力可能非常有限,因此协议的设计考虑到了这一点。 服务质量管理: MQTT提供了多种服务质量级别,允许在不同网络条件下选择适当的级别,以确保消息的可靠传递。 数据格式灵活性: MQTT协议不强求传输数据的类型和格式,保持了数据的灵活性,使其适用于各种数据类型和应用场景。 这些原则使MQTT协议在不同环境下都能够高效运作,并为物联网提供了可靠的通信基础。 MQTT协议的版本 目前,MQTT有两个主要版本:MQTT3.1.1和MQTT5。MQTT3.1.1于2014年10月发布,而MQTT5于2019年3月发布。MQTT5在MQTT3.1.1的基础上进行了升级,添加了更多功能并完善了协议规范。尽管如此,MQTT5仍然与MQTT3.1.1完全兼容,这意味着现有的应用可以无缝升级到新版本,而无需改动。 三、MQTT与消息队列MQ的区别 尽管MQTT和消息队列MQ在某些方面行为和特性相似,比如都采用发布订阅模式,但它们面向的场景存在显著差异: 消息队列MQ: 主要用于服务端应用之间的消息存储和转发,通常处理大量数据但接入量较少。 MQTT: 针对物联网和移动互联网领域设计,重点是支持大规模设备的接入、管理和消息传输。 在实际应用中,这两者经常结合使用,例如,首先由MQTT Broker接收物联网设备上传的数据,然后通过消息队列MQ将这些数据转发到具体应用进行处理。 四、MQTT协议在车联网中的应用 在车联网领域,MQTT协议发挥着重要作用,特别是在Telematics Service Provider(TSP,汽车远程服务提供商)方面。TSP作为核心角色,连接着汽车制造商、车载设备制造商和网络运营商,同时提供服务给内容提供商。 TSP在车联网中扮演着关键的角色,需要与各个环节进行多种交互,其中包括与云平台和车载终端的消息接入。 MQTT作为一种基于发布/订阅模式的物联网通信协议,在车联网场景中展现出了诸多优势: 开放的消息协议,易于实现: 在市场上,存在着大量成熟的软件库和硬件模块,它们使得车机接入变得更加容易,降低了使用成本。 灵活的发布/订阅和主题设计: MQTT允许通过众多主题进行消息通信,适用于多种车联网业务,从而满足了不同场景的需求。 灵活的Payload格式: MQTT的报文结构紧凑,可以有效地携带各类业务数据,同时减少了车机网络流量的负担。 多种服务质量级别: MQTT提供了三个可选的服务质量级别,适应了车机设备在不同网络环境下的通信需求。 在线状态感知和会话保持: MQTT协议支持车机设备的在线状态感知,同时具备会话保持能力,方便管理车机的在线状态并保留离线消息。 这些优势使得MQTT在车联网中成为了一种理想的通信协议,能够满足海量车机系统的接入需求,并确保在复杂的网络环境下实现消息的实时性和可靠性。 五、MQTT协议特性介绍 1. 客户端与服务器 MQTT协议涉及到客户端和服务器之间的通信。在这个通信过程中,有三种关键角色:发布者(Publish)、代理(Broker,服务器)和订阅者(Subscribe)。 客户端是MQTT的基本组成部分,可以执行发布和订阅操作。发布者负责向服务器发布信息,而订阅者则负责订阅信息。此外,客户端还可以执行退订操作,取消对特定主题的订阅,以及断开与服务器的连接。 服务器端是MQTT的核心,通常被称为消息代理(Broker)。它位于发布者和订阅者之间,负责传递和管理MQTT消息。服务器接受客户端的网络连接、接收发布者的应用信息、处理客户端的订阅和退订请求,并将发布者的应用程序消息转发给订阅者。 2. 主题 在MQTT中,通信是基于主题(Topic)的。主题是消息的标识,用于控制消息的传递。 例如,假设有三个MQTT客户端:汽车、手机和电脑。如果我们需要手机和电脑获取汽车的速度信息,首先要让手机和电脑订阅名为“汽车速度”的主题。然后,当汽车发布速度信息到该主题时,服务器会检查哪些客户端订阅了该主题,然后将信息传递给手机和电脑客户端。 在不同主题下,MQTT客户端可以切换其角色,可能是发布者,也可能是订阅者,具体取决于其需求和所订阅的主题。 上图中的所有客户端都是围绕“空调温度”这一主题进行通讯的。对于“空调温度”这一主题,手机和电脑客户端成为了MQTT信息的发布者,而汽车则成为了MQTT信息的订阅者(接收者)。所以,针对不同的主题,MQTT客户端可以切换自己的角色。它们可能对主题A来说是信息发布者,但是对于主题B就成了信息订阅者。 这种基于主题的通信机制使得MQTT协议在物联网中非常灵活和适用于多种场景。 3. MQTT 发布/订阅 特性 MQTT通讯的核心枢纽是MQTT服务端。有了服务端对MQTT信息的接收、储存、处理和发送,客户端在发布和订阅信息时,可以相互独立,且在空间上可以分离,时间上可以异步。 相互独立 MQTT客户端是独立的个体,无需了解彼此的存在,仍然可以实现信息交流。举例来说,汽车客户端在发布“汽车速度”信息时,不需要知道有多少其他MQTT客户端订阅了同一主题。同样,订阅了“汽车速度”主题的手机和电脑客户端也不需要了解彼此的存在。只要它们都订阅了“汽车速度”主题,MQTT服务端会在每次收到新信息时,将信息发送给所有订阅了该主题的客户端。 空间可分离 MQTT客户端可以连接到同一个MQTT通讯网络,无论它们在世界的哪个角落,只要联网,就可以实现彼此间的通讯交流。 时间可异步 MQTT客户端在发送和接收信息时无需同步。这对物联网设备尤其重要,因为它们可能会因为网络不稳定而断开连接。例如,汽车在行驶中可能会突然进入隧道,导致断开与MQTT服务端的连接。在这种情况下,如果手机客户端向汽车客户端发布了信息,而汽车不在线,MQTT服务端可以暂时保存“空调温度”主题的新信息,直到汽车再次上线时将信息推送给它。 4. 会话 MQTT通讯的会话涵盖了从客户端向服务端发起连接请求,到连接中断,直至会话过期为止的消息收发序列。 会话可能仅持续一个网络连接,但如果客户端在会话过期前重新建立了连接,会话也可以跨越多个网络连接存在。 会话状态的使用 客户端因网络波动等原因导致连接短暂中断,但在会话过期前重新连接,会话状态的保存允许客户端沿用上次连接建立的订阅关系,避免了重新订阅的需求,降低了资源消耗。 在低带宽、不稳定的网络环境下,网络中断可能会频繁发生,会话状态的保存方式防止了每次连接都需要重新订阅,减少了客户端和服务端的资源消耗。 服务端在客户端脱机期间保留未完成确认的消息以及后续到达的消息,客户端重新连接后再一并转发,确保消息不会丢失,同时降低用户对网络变化的感知度。 5. QoS(服务质量) 在物联网系统中,某些信息非常重要,需要确保它们可以准确无误地发送和接收。其他信息可能对系统的运行不那么关键,即使在传输中丢失也不会产生重大问题。 MQTT服务质量(Quality of Service,缩写 QoS)用于告知物联网系统哪些信息是重要信息,需要准确传输,哪些信息可以容忍一定的丢失。 MQTT设计了3个QoS等级: QoS 0: 消息最多发送1次,网络资源占用最少。发送端发送消息后,任务就完成了,不会检查消息是否被正确接收。 适用于信息传输不太关键的情况,但在网络不稳定时可能会导致消息丢失。 QoS 1: 消息至少发送1次,可能导致接收端多次接收同一消息。发送端在消息发送后等待接收端的确认,如果没有收到确认,会重复发送消息。 适用于对信息准确性要求较高的场景,但可能会导致消息的重复接收。 QoS 2: 消息保证只发送1次,最安全的服务级别。确保接收端只接收一次消息,但发送和接收过程更加复杂,需要两次确认。 适用于对信息传输要求非常高的情况,确保消息不会丢失且不会重复接收。 在发布和订阅消息的客户端之间,服务端会主动采用较低的QoS等级来提供服务。这意味着服务端将根据客户端的要求选择适当的QoS等级来确保信息的可靠传输。 例如,如果一个客户端使用QoS 2发布消息,而另一个客户端使用QoS 1订阅相同主题,服务端将使用较低的QoS 1来满足订阅客户端的需求。这种灵活的QoS等级适应了不同客户端的需求和网络条件。 服务质量降级 在发布和订阅消息的客户端之间,服务端会主动采用较低的服务质量级别(QoS)来实现消息传输,以适应订阅者的QoS设置。 场景1: 假设客户端A使用QoS = 2发布到主题1的消息,而客户端B在订阅主题1时选择了QoS = 1。 在这种情况下,服务端会自动采用较低的服务质量级别以提供服务。 尽管客户端A使用QoS 2发布主题1的消息,但由于客户端B订阅主题1时选择了QoS 1,因此服务端在将消息发送给客户端B时会降低消息的服务质量级别为1。 场景2: 考虑另一种情况,客户端A使用QoS 0发布主题1的消息,而客户端B在订阅主题1时选择了QoS 1。 尽管客户端B订阅主题1时使用了QoS 1,但由于客户端A使用QoS 0发布主题1的消息,因此服务端会将消息发送给客户端B时的服务质量级别降低为0。 这种服务质量降级机制确保了在不同订阅者之间灵活适应QoS设置,以确保消息传输在各种情况下的可靠性和效率。 6. 保留消息 想象一个智能家居物联网系统,其中一个MQTT客户端负责定时检测室温,并在每个整点时将当前室温发布到MQTT服务端。系统中还有另一个客户端,专门用于显示温度信息,它在启动后会立即订阅室温主题。 在正常情况下,假设室温检测客户端在上午7:00将最新的室温消息发布到服务端,那么订阅了室温主题的显示客户端会立刻获取并显示这个温度信息。 然而,在某一天的7:10,显示客户端的电源插头被意外拔掉,之后重新插上电源。客户端重新启动后,会立刻订阅室温主题。 问题出现了:室温客户端只在每个整点时发布一次温度信息,上一次发布是在7:00,下一次发布将在8:00。因此,在8:00之前的几十分钟内,显示客户端将无法获取到当前室温信息。 为了解决这个问题,我们可以让室温测量客户端在每次发布温度信息到室温主题时都使用保留消息模式。这样,无论显示客户端何时订阅室温主题,它都会立刻收到该主题中的保留消息,确保及时获取当前室温信息。 7. 心跳机制 MQTT引入了心跳机制,允许客户端定时向服务端发送一条心跳请求消息,以通知服务端客户端仍然在线。 心跳时间间隔 在客户端连接服务端时,可以设置心跳时间间隔。客户端会将这个间隔信息放入CONNECT报文的keepAlive字段中。 例如,如果设置心跳时间间隔为60秒,客户端会在60秒内不发布消息时发送心跳请求,以告知服务端它仍然在线。 客户端在心跳时间间隔内发布消息时,会直接发布消息而不发送心跳请求。 客户端掉线 如果服务端在1.5倍心跳时间间隔内没有收到客户端发布消息(PUBLISH)或心跳请求(PINGREQ),服务端会认为客户端已经掉线。 这个心跳机制让服务端随时了解客户端的连接状态。正常情况下,服务端会收到心跳请求并回复心跳响应,从而知道客户端仍然在线。如果心跳停止,服务端会检测到客户端断线。 8. 遗嘱机制 MQTT协议允许客户端在在线时设置遗嘱消息,以便在意外断线时将其发布。这样,即使客户端意外断线,服务端也能够公布客户端的遗嘱消息。 需要注意的是,客户端的遗嘱只在客户端意外断线时才会发布,如果客户端正常断开与服务端的连接,遗嘱机制不会触发,服务端也不会发布遗嘱消息。 意外断线的情况包括但不限于: 由于网络故障或波动,设备在保持连接周期内未能通讯,导致服务端关闭连接。 设备意外断电。 设备尝试进行不被允许的操作,导致服务端关闭连接,例如订阅自身权限以外的主题等。 9. 数据包结构 MQTT消息结构可分为三个部分: 固定报头 (Fixed header):存在于所有MQTT数据包中,用于表示数据包类型和数据包的分组类标识。 可变报头 (Variable header):存在于某些MQTT数据包中,其存在与否取决于数据包类型。 有效载荷 (Payload):包含实际传输的数据,也是某些MQTT数据包的一部分。 整体 MQTT 的消息格式如下图所示: 整体来看,MQTT消息的格式非常灵活,具有可扩展性,使其适用于各种不同的物联网应用场景。 希望这些说明能够帮助你更好地理解MQTT协议的关键特性和工作原理。 --- ### 173. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 IoT 设备如何基于 MQTT 协议将数据无缝写入 TDengine 时序数据库 随着物联网技术的蓬勃发展,企业和开发者们面临着一个巨大的挑战:如何有效地处理、存储和分析从 IoT 设备源源不断产生的大量数据。传统的大数据解决方案和以关系型数据库为核心的方法已经不再适用。在这种背景下,TDengine 时序数据库的出现犹如春风送暖。 TDengine:时序数据库的领军者 TDengine 是一款高性能、集群开源、云原生的时序数据库,专为物联网、工业互联网、电力、IT 运维等场景设计。它结合了内建的缓存、流式计算、数据订阅等系统功能,大幅减少了系统设计的复杂度,为企业节约了宝贵的研发和运营成本。 物联网的数据痛点 物联网设备每秒都在产生数据,这带来了以下的挑战: 数据入库缓慢:单机的写入吞吐量常常不能满足大量的写入压力。 存储成本巨大:时序数据的压缩性能很差,需要大量的硬件资源。 维护成本高昂:传统数据库需要人工分库分表,增加了维护的复杂性。 查询性能不佳:海量实时数据的聚合分析常常效率低下。 数据孤岛问题:难以实现边云协同。 TDengine 的卓越特点 针对上述的痛点,TDengine 提供了以下解决方案: 高性能:支持百万级别的并发写入和万级的并发读取。 高可用性:集群部署,无单点故障,保证生产环境的稳定运行。 低成本:优秀的数据压缩技术节省了70%的硬件资源。 一体化设计:集成了消息队列、流式计算和缓存功能。 易上手:支持 SQL 查询,减少开发难度。 边云协同:支持边云数据同步。 下面一起来看看 TDengine MQTT 数据接入功能有哪些卓越特性吧! 1.MQTT 数据接入:可以轻松从 MQTT 服务器获取数据,并高效地写入 TDengine 数据库中,实现数据的顺畅集成和分析。数据接入工具负责整个过程的自动化数据接入,最大限度地减少了手动操作的工作量。 2.支持 JSON 格式:充分利用 JSON 的灵活性,使用户能够以 JSON 格式进行数据摄取和存储。机构可以有效地构建和管理数据,从复杂数据结构中挖掘有价值的见解。 3.支持 JSON path 提取字段:TDengine 支持 JSON path 提取,在处理 JSON 数据时更加轻松。通过精确选择和捕获所需的数据元素,用户可以专注于数据集的核心内容,最大化分析效率。 4.多样 MQTT 协议支持:支持 MQTT 协议的 3.1、3.1.1 和 5.0 版本,确保无缝连接和数据消费,无论您的物联网生态系统中使用的是哪个版本。凭借全面 MQTT 协议兼容性,保持灵活性并立于未来。 5.简单配置:提供了易于使用的配置文件,您可以在其中指定 TDengine 的超级表、子表、列和标签,轻松定制数据接入流程以满足特定需求。 配置 MQTT 接入功能 另外 TDengine 的数据接入后还可以进行数据清洗和转换,用户可以根据业务需要设计相应的数据清洗和转换规则,实现完整的数据 ETL 流程。总而言之,TDengine 彻底颠覆了用户整合、存储和分析 MQTT 数据的方式,借助上述创新功能,实时数据可以实现与高性能的 TDengine 数据库的无缝结合,实时分析、预防性维护和数据驱动决策也拥有了无限可能。 TDengine 提供了一个完整的解决方案,帮助企业轻松地处理物联网设备的大数据问题。基于 MQTT 协议的数据接入功能更是为 IoT 设备提供了一个简单、高效的数据写入方法。对于任何希望利用物联网数据的企业来说,TDengine 无疑是一个不可或缺的工具。 --- ### 174. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 HTTP是最流行和广泛使用的协议。但在过去的几年里,MQTT迅速崭露头角。在物联网开发中,开发人员如何选择? 设计与消息 MQTT是以数据为中心,而HTTP是以文档为中心。HTTP是客户端-服务器计算的请求-响应协议,不总是针对移动设备进行了优化。MQTT在这方面的主要优势在于轻量级(MQTT将数据传输为字节数组)和发布/订阅模型,这使其非常适用于资源受限的设备,并有助于节省电池电量。 此外,发布/订阅模型使客户端相互独立存在,并增强了整个系统的可靠性。当一个客户端出现故障时,整个系统仍然可以正常工作。 速度与传输 根据在3G网络中的测量,MQTT的吞吐量比HTTP快93倍。 此外,与HTTP相比,MQTT协议确保高交付保证。有3种不同的服务质量级别: 至多一次:保证尽最大努力交付。 至少一次:保证至少传递一次消息。但消息也可能传递多次。 正好一次:保证每条消息只由对等方接收一次。 MQTT还为用户提供了遗嘱和保留消息的选项。第一种意味着如果客户端意外断开连接,所有订阅的客户端都会从代理收到一条消息。保留消息意味着新订阅的客户端将立即获得状态更新。 HTTP协议没有这些能力。 复杂性与消息大小 MQTT规范相当简短。对于开发人员来说,只有CONNECT、PUBLISH、SUBSCRIBE、UNSUBSCRIBE和DISCONNECT这几种类型是重要的。而HTTP规范要长得多。 MQTT具有非常短的消息头和最小的数据包消息大小,仅为2字节。HTTP协议使用文本消息格式,允许构建冗长的头部和消息。这有助于消除问题,因为它可以被人类阅读,但同时对于资源受限的设备来说是不必要的。 结论 MQTT协议易于使用。当未来解决方案的响应时间、吞吐量、较低的电池和带宽使用率位于首位时,这是至关重要的。在连接不稳定的情况下,它也非常完美。 HTTP是有价值且可扩展的。但在涉及物联网开发时,MQTT更加合适。 --- ### 175. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网(IoT)设备是一类依赖互联网进行信息传输的机器,其工作基于其特定任务。这些设备范围广泛,包括微波炉、洗衣机、灯具等各种家居设备,随着智能手机的普及,它们甚至在车辆中也变得常见。如果按照当前的趋势来看,几乎所有事物都将逐渐变成IoT设备。例如,小米米家和天猫精灵等智能家居设备的普及就展示了IoT如何像手机一样渗透到我们的生活中。然而,随着这项技术的不断发展,支持其运行的通信协议也必须不断演进。虽然在数据通过网络传输时可能会涉及多种通信协议,但在IoT领域,主要采用的协议主要有HTTP、Websockets和MQTT。而随着HTTP/2作为较新的参与者进入这个领域,重新评估其在IoT中与Websockets和MQTT相比的适用性是很有必要的。 HTTP/2 HTTP/2是HTTP协议的现代修订版本,它起源于谷歌的一个实验项目,名为SPDY,旨在提高浏览器端和服务器端的通信速度。HTTP/2的基本原理与HTTP/1.x相同,但通过改进网络和服务器端资源的利用,旨在降低终端用户感知到的延迟。换句话说,它就是HTTP/1.x的升级版本,速度更快。具体来说,新协议采用了多路复用技术来处理TCP请求,而不像HTTP/1采用了有序和阻塞的格式,这可以减少数据拥塞,提高性能。此外,HTTP/2采用了二进制格式,而不是文本格式,因此比其基于文本的前身更加紧凑。最后,HTTP/2还引入了服务器推送功能,这使得它可以向客户端推送数据,而无需等待客户端的请求,这一点之前通常需要Websockets来实现。因此,HTTP/2在IoT领域应该能够胜任,因为它的紧凑传输和低开销将减轻硬件在内存和电池消耗方面的压力。 Websockets Websockets是一种协议,用于在Web浏览器(或类似软件)与Web服务器之间进行握手,从而减少使用HTTP进行双向通信时的开销。与HTTP/1采用的请求-响应模式不同,Websockets采用双向通信,非常适用于需要实时监控和频繁更新的系统。虽然Websockets自2008年以来一直存在,但它们相对较新,因此还未完全成熟。 随着HTTP/2引入双向或全双工通信功能,Websockets的需求可能会逐渐减少,至少在IoT领域是如此。实际上,过去几年中,一直存在一个问题,即HTTP/2是否会使Websockets变得过时。答案是“不完全如此”,因为HTTP/2引入的服务器推送功能虽然可以向客户端传输数据,但不会直接推送到客户端应用程序。因此,许多设备仍然需要类似Websockets提供的握手过程。因此,将Websockets视为“过时”的说法有些过于绝对,更准确的描述应该是它们在某些情况下可能“不再必要”。 MQTT 消息队列遥测传输(MQTT)是一种轻量级协议,由IBM发明,旨在促进机器之间的通信。它采用发布和订阅模型,以确保不同平台之间的高效通信,并提供消息优先级的级别控制。尽管目前尚未标准化(正在通过结构化信息推进组织(OASIS)进行标准化),但由于其小巧的协议头和低带宽消耗,MQTT已广泛用于IoT和大规模通信。尽管尚未标准化,但MQTT已经被Facebook Messenger、Amazon Web Services和Microsoft Azure的IoT Hub等大公司采用,成为首选的IoT通信协议。MQTT的紧凑协议头和服务质量(Quality of Service,QoS)功能旨在基本层面上实现可靠的机器对机器通信,几乎不需要额外的工作来确保顺畅运行。MQTT中的QoS功能意味着每条消息都有三个级别的检查来确保消息的可靠传递。这些级别在逐级提高时会增加带宽使用,但在关键传输方面提供了最高级别的保障。 哪种协议最适合物联网? 大多数人认为最佳协议取决于您的具体需求,但也有人认为这些协议适用于不同的应用领域,难以进行直接比较。然而,所有三种协议的关键因素都是它们如何有效地利用资源,例如带宽和电池寿命,以及它们的功能多样性。因此,总的来说,对于IoT而言,MQTT 可能是最佳选择。因为HTTP/1.x和Websockets并没有专门设计用于机器对机器通信。Websockets通常不适合IoT,特别是在智能家居等场景中,因为在机器对机器通信中,第二个“机器”通常无法支持Web客户端软件。而HTTP/2虽然是新兴的协议,但在得到广泛应用之前,还不能被视为成熟的MQTT协议的可靠替代品。 --- ═══════════════════════════════════════════ ## MQTT 服务器 ═══════════════════════════════════════════ ### 176. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在当今快速发展的物联网领域,OpenMQTTGateway(简称OMG)作为一个开源项目,旨在将不同的技术和协议统一到一个固件中。该项目的目标是减少对多个物理桥接设备的需求,将各种技术整合到广泛使用的MQTT协议下。 官网:https://www.theengs.io/ 项目概述 MQTT网关的作用 MQTT,即消息队列遥测传输,是一种轻量级的物联网设备理想的通信协议。而MQTT网关或桥接器在MQTT生态系统中扮演着关键的角色: 协议翻译: 将非MQTT协议(如Zigbee或蓝牙)转换为MQTT,实现更广泛的网络通信。 数据汇聚: 将多个设备的数据合并为单一消息,优化网络使用。 安全性: 包括SSL/TLS加密等功能,保障数据传输的安全性。 设备管理: 处理固件更新和远程配置更改等任务。 在本质上,MQTT网关确保设备与MQTT代理之间的顺畅通信,增强物联网系统的效率和安全性。 OpenMQTTGateway的功能 OpenMQTTGateway集成了传统技术,如433MHz/315MHz协议和红外线(IR),使您能够升级和重新利用旧设备。此外,OMG与现代技术如低功耗蓝牙(BLE)和LoRa兼容。 主要功能包括: 兼容性广泛: 支持PIR、门窗传感器、烟雾探测器、气象站等各类设备。 适用于不同板卡: 支持ESP32、ESP8266、Arduino MEGA、UNO等多种板卡。 多协议支持: 包括433MHz、IR、BLE等协议,满足不同设备的需求。 与家居自动化平台集成: 通过MQTT,可以与OpenHAB、Home Assistant、Node-Red等平台轻松集成。 使用场景 利用OpenMQTTGateway与控制器结合使用,您可以实现各种实用的场景,例如: 监控花园: 使用Mi Flora BLE传感器监测土壤湿度,并根据需要控制灌溉阀。 温湿度控制: 利用Mi Jia/LYWSD03MMC BLE传感器,根据温度和湿度触发风扇。 远程警报: 如果冰箱或冷冻库温度过高,通过控制器通知进行警报。 出门提醒: 通过433MHz或BLE检测门窗状态,离开时进行提醒。 远程监测: 通过BLE检测水浸或烟雾,实现远程监测功能。 智能控制: 使用IR控制老式电视或空调系统,实现智能化控制。 技术细节 OpenMQTTGateway在底层提供了一些关键功能: 去重: 避免消息重复,提高系统效率。 简单轻量的API: 提供简单而轻量的API,易于使用。 与使用的库强大集成: 与使用的库(Library)进行强大集成。 信号转发/重复: 实现信号的转发和重复功能。 Wifi Web Portal Onboarding: 提供Wifi Web Portal,简化设备上线过程。 Web Portal配置: 提供Web Portal,方便进行配置。 白名单和黑名单管理: 管理设备的白名单和黑名单,增强安全性。 安全连接: 提供本地或云端的选择,确保安全连接。 空中升级: 支持通过空中更新进行固件升级。 由OpenMQTTGateway推动的产品 Theengs Bridge Theengs Bridge是一款强大的BLE到MQTT网关,支持90多种传感器。它配备有以太网端口和外部天线,确保BLE传感器具有增强的覆盖范围。同时,它还支持WiFi连接。 Theengs Plug Theengs Plug是一款BLE网关和智能插座,具有以下功能: BLE到MQTT网关,通过Theengs Decoder库支持数十种蓝牙设备。 可远程控制的智能插座。 能耗监测功能。 出席检测(测试版)。 通过购买Theengs Bridge或Theengs Plug来支持该项目。 想象力的限制。OpenMQTTGateway为物联网领域的创新提供了广泛的可能性,推动着不同技术和协议的融合。通过支持该项目,您有机会参与并塑造未来物联网的发展方向。 --- ### 177. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网(IoT)正在全球范围内快速发展,企业和开发者们面临的最大挑战之一是如何高效、安全且稳定地开发和部署物联网解决方案。在这个背景下,ThingsPanel物联网平台应运而生。 平台概述 ThingsPanel是一个开源的物联网应用平台,它结合了当前物联网领域最前沿的技术和最佳实践,为开发者提供了一套完整、高效的工具集。其核心理念是“模块化、插件化”,这意味着,开发者可以根据项目的实际需求,灵活选择和组合不同的功能模块,大大提高项目的研发效率。 电脑端使用网址​ http://dev.thingspanel.cn/ 电脑和手机端共用账号密码 (如下账号为租户账号) 用户名:admin@thingspanel.cn 密码:123456 插件系统 ThingsPanel的强大功能得益于其丰富的插件体系。这些插件分为以下几类: 设备插件:整合物模型与图表,使得设备数据可以直观、美观地展示。 协议插件:解决各类协议接入的问题,无论是MQTT、HTTP还是Modbus,都可以轻松接入。 可视化插件:扩展可视化功能,提供多样化的数据展示方式。 依赖型插件:为特定行业提供解决方案,如萤石云视频、GB28181安防摄像头等。 此外,ThingsPanel还提供了报文解析脚本和规则引擎脚本,进一步丰富了数据处理和转发的功能。 功能概要​ 多租户功能: 超级管理员管理、租户账户管理业务系统、租户用户管理设备查看数据 设备接入: 编辑创建项目、按照分组添加管理设备、查看设备推送状态、设备插件接入、网关与子设备接入、Modbus RTU/TCP协议接入、TCP协议接入、GB28181安防摄像头接入、自定- 义协议插件接入 设备监控: 设备添加后的监控图表、设备插件中的当前值、曲线、开关、写入指令组件显示 设备地图: 根据项目与分组筛选设备、设备类型筛选 可视化: 可视化编辑基本功能、开放式架构、预绑定数据图表、添加自己的图元、和系统松耦合,支持组态、大屏、3D、Three.js 产品管理: 创建产品、批量管理、二维码数据、手动激活、预注册管理 固件升级: 为产品添加固件、创建升级任务、固件升级报表 自动化: 场景联动、场景日志、定时触发、设备触发、多种触发 数据管理: 根据项目筛选数据、实时查看数据日志、数据导出 告警信息: 根据项目和分组显示告警、时间段筛选 通知功能:短信、邮件、电话、webhook多种通知方式 系统日志: IP访问路径、设备操作记录 应用管理: 设备插件管理、插件生成器、插件安装、应用市场 设备插件生成器: 快速生成、自定义物模型、自定义图表、JSON导入导出 协议接入: 开发自定义协议配置、配置后的接入参数 用户管理: Casbin方案、页面权限控制、项目权限控制、多角色定义 规则引擎: 数据转发第三方、接收设备数据并转换、接入各种协议、实时数据计算 数据网关:OpenAPI,数据库SQL-to-HTTP,对接三方系统,限制IP与数据范围,授权读取 系统设置: 更换Logo、更换系统标题、更换主题风格 物联网APP: Uniapp开发、扫码添加设备、查看监测值、切换项目和设备分组、手动控制、设置控制策略、查看操作日志、个人账号管理、手机验证码登录 依赖型插件: 依赖型插件为行业解决方案、基于设备插件和其他功能与数据、可视化调用、iframe代码引入、插件复用 产品用途与解决的问题 ThingsPanel不仅仅是一个物联网开发平台,它更是一个企业级的物联网解决方案。无论是设备上云,还是企业物联网+的需求,ThingsPanel都可以提供完整、高效的解决方案。而对于物联网项目开发周期长、复杂度高的问题,ThingsPanel通过其模块化、插件化的设计,大大简化了开发流程,提高了研发效率。 技术亮点 ThingsPanel在技术实现上同样展现出了其领先的优势。它采用了Golang作为后端语言,确保了高并发、高性能的特点,特别适合物联网这种需要处理大量设备数据的场景。前端则采用了Vue.js和ElementUI,提供了简洁、高效、响应迅速的用户界面。此外,ThingsPanel还集成了多种先进的技术,如PostgreSQL、TimescaleDB、Nginx、GMQTT、Redis等,确保了平台的稳定性、扩展性和安全性。 气象站案例: 电力配电系统案例: 结论 ThingsPanel物联网平台为物联网开发者和企业提供了一个全面、高效、灵活的解决方案。无论是设备接入、数据处理、可视化展示,还是协议转换、规则引擎、数据存储,ThingsPanel都能够提供完善的功能和出色的性能。对于物联网领域的专家和新手,ThingsPanel都是一个值得深入了解和使用的工具。 --- ### 178. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 PandaX:物联网开发的颠覆者 随着物联网的发展,企业和开发者都在寻找能够简化、加速开发过程的工具和框架。而PandaX,一款企业级的物联网平台快速开发框架,正应运而生。 1. PandaX简介 PandaX基于Go 1.20的前后端分离架构,集成了最前沿的Vue3.0、TypeScript、vite3和Element-plus技术。它不仅代码精简、高效,更拥有开箱即用的特性。对于开发者来说,PandaX不仅是一个框架,更是一个高效、稳定的物联网应用开发解决方案。 演示地址:http://101.35.247.125:7789/ 帐号:admin 密码:123456组态大屏:http://101.35.247.125:7790/规则引擎:http://101.35.247.125:7791/ 2. 主要特性 封装性强: PandaX对前后端功能进行了大部分封装,使开发更简洁,逻辑更清晰。 报表大屏设计器: 仅需简单的拖拉拽操作即可完成组态、报表和大屏的制作。 成熟的规则引擎: 通过规则链处理数据,简化了开发和配置过程。 前端技术栈: 采用VUE3.0+ TypeScript + vite3 + Element-plus,适配各种设备,减少开发量。 代码生成器: 一键生成前后端代码,可在线预览代码,大大提高开发效率。 完备的权限系统: 包括菜单按钮权限、API权限和组织权限。 多数据库支持: 同时支持MySQL、PostgreSql等多种数据库。 3.PandaX平台核心功能 🌟 内置功能: 用户管理: 作为系统的操作者,此功能负责配置系统用户。 组织管理: 它允许您配置系统的组织结构(公司、组织、小组)并以树结构展示,同时支持数据权限。 岗位管理: 这里可以配置用户的职位或角色。 菜单管理: 用于配置系统菜单,并定义操作权限和按钮标识。 角色管理: 除了为角色配置菜单和API权限外,还可以设置按组织划分的数据权限范围。 字典管理: 维护系统中经常使用的一些固定数据。 参数管理: 对系统的动态配置参数进行管理。 通知公告: 发布和维护系统的通知和公告。 日志系统: 记录并可视化系统日志。 系统接口: 根据业务代码自动生成API接口文档。 服务监控: 实时监控系统的CPU、内存、磁盘和其他关键参数。 代码生成: 提供代码生成器,能够一键生成前后端基础业务代码。 组态大屏设计器: 通过拖拽功能,您可以轻松地创建组态和大屏。 规则链设计: 这是针对物联网的规则链过滤功能。 表单设计: 设计表单的工具。 报表设计: 为数据分析创建报表。 产品管理: 用于管理设备的产品。 设备管理: 为设备提供管理功能。 🚀 未来潜在功能: 3D组态: 正在开发的功能,可以根据2d组态自动生成3D组态。 数字孪生编辑器: 一个正在开发的工具,允许在web上直接构建数字孪生模型。 4. 未来展望 PandaX团队致力于持续创 新和完善功能,未来的计划中包括3D组态的开发和数字孪生编辑器的推出,这将使物联网应用的开发更具深度和广度。 5. 系统架构 PandaX的前端工程结构明确、后端工程结构清晰。无论是API的管理、静态资源的组织、还是代码生成与业务逻辑处理,每一部分都经过精心设计,为开发者提供了一个稳定、可靠的开发环境。 6. 版权与支持 虽然PandaX完全开源,但对于二次开发或商业应用,开发团队仍然保留了一定的权利,希望保护原作者的努力成果。同时,为了维护一个良好的社区环境,PandaX团队也提供了完善的在线文档和视频教程,助力开发者快速上手。 7. 总结 PandaX不仅仅是一个物联网开发框架,更是一个集成了多种先进技术、实用功能的物联网解决方案。无论你是物联网行业的新手还是资深开发者,PandaX都能为你提供强大的支持,帮助你更快、更好地完成物联网应用的开发。 最后,如果你觉得PandaX帮助到了你,不妨给它一个Star,支持开发者继续完善这个优秀的框架。让我们一同 witness 物联网开发的未来! --- ### 179. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 FluxMQ是一款高性能,云原生的物联网接入网关,专为物联网、工业互联网、IT运维监控等场景设计并优化,具有极强的弹性伸缩能力,高并发,低延迟。能大幅度的减小物联网系统搭建过程中的复杂度,降低研发和运维成本,是一个物联网平台的基础且重要的组件。 官网:https://www.fluxmq.com/ 什么是FluxMQ? 产品介绍 FLuxMQ是一款基于java开发,支持无限设备连接的云原生分布式物联网接入平台。FluxMQ基于Netty开发,底层采用Reactor3反应堆模型,具备低延迟,高吞吐量,百万-千万设备连接;方便企业快速构建其物联网平台与应用。 核心特性 「高性能」单机支持百万TCP连接、并且支持数10万的TPS消息包上报,规则引擎支持处理海量的设备数据桥接到数据源。 「支持标准MQTT协议」完整支持MQTT3.x和MQTT5.0 协议标准;支持Qos0,1,2的MQTT消息传递;支持所有MQTT客户端和库; 「配置持久化」所有功能支持WEB配置,集群自带持久化功能,重启后配置不丢失 「规则引擎」灵活的规则模型配置,支持多种数据桥接和数据持久化; 「SQL引擎」支持实时流SQL引擎,支持对MQTT跟扩展协议进行数据流清洗 「数据安全」基于MQTT overTLS/SSL确保数据安全;LDAP,PSK和X.509证书等多种身份认证; 「灵活部署」支持物理机,容器,私有云,公有云中任何地方运行,不受位置限制,不受厂商锁定; 「低成本」性能卓越,降低硬件需求成本;支持买断和按需付费; 功能概览 功能说明集群功能支持MQTT、MQTTS、MQTT OVER WEBSOCKET集群发布订阅支持标准发布订阅服务等级QoS0,1,2ACL控制客户端发布订阅权限流量控制限制Broker接入流量管理页面-连接管理管理客户端状态,上下线管理页面-ACL访问授权管理页面-订阅查询查看设备订阅Topic管理页面-规则引擎转发消息管理页面-云客户端基于ws进行模拟测试管理页面-动态认证连接认证管理页面-日志管理标准接入日志管理页面-监控管理grafana监控方案管理页面-数据源管理多数据源管理页面-告警功能支持钉钉、微信、飞书管理页面-协议解析支持脚本解析处理payload管理页面-多协议支持Coap、Websocket、I1、V2x等协议 FluxMQ的核心特点 「高性能」:FluxMQ采用了最新的消息处理技术和数据压缩算法,提供高吞吐量、低延迟的数据传输能力,为您的物联网应用带来卓越的性能体验。 「易于使用」:FluxMQ提供了简洁明了的API接口和丰富的文档资源,无论您是物联网初学者还是经验丰富的开发者,都能轻松上手并快速实现项目部署。 「高安全性」:FluxMQ支持TLS/SSL加密通信,确保数据在传输过程中的安全性。同时,提供了多种鉴权机制和访问控制策略,保护您的物联网应用免受未经授权的访问和攻击。 「高可靠性」:FluxMQ具备强大的故障转移和负载均衡功能,确保在各种异常情况下保持稳定的运行。此外,FluxMQ还支持消息持久化,防止因意外断线等原因造成的数据丢失。 「广泛适用性」:FluxMQ适用于各种规模的物联网应用场景,从智能家居、工业自动化到智能交通、智慧城市等,都能发挥其卓越性能,满足不同行业的需求。 FluxMQ——高性能压测报告 压测配置 服务版本操作系统CPU内存数量FluxMQ1.0.0Centos 7.616C32G1Kafka集群--Centos 7.648C128G3 纯连接100W 服务运行情况CPU物理内存备注说明EMQX100W正常12%40%FluxMQ100W正常5.5%63%;JVM内存6.58G 高并发吞吐 测试单条数据payload:1024B 服务5WTPS/5W连接10WTPS/10W连接15WTPS/15W连接20WTPS/20W连接EMQX正常正常崩溃崩溃FluxMQ正常正常正常正常 10WTPS下性能对比 服务运行情况CPU物理内存备注说明EMQX10WTPS正常12%40%FluxMQ10WTPS正常10%64%;JVM内存17.6G 高并发连接下高吞吐 ❝ 测试单条数据payload:1024B;❞ 服务5WTPS/95W连接9WTPS/99W连接10WTPS/100W连接FluxMQ正常正常正常 9WTPS/99万连接下性能对比 服务运行情况CPU物理内存备注说明FluxMQ10WTPS正常12%95%;JVM内存18.3G --- ### 180. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MyQttHub:简化您的MQTT IoT项目 网址:https://myqtthub.com/en 当我们谈论物联网(IoT)的未来时,我们必须首先谈论那些连接了无数设备的技术和平台。其中,MQTT(消息队列遥测传输)成为了标准的物联网协议。而今,有一个新的云平台——MyQttHub.com,致力于简化整个MQTT的项目流程,并为用户带来丰富的功能和专业级的支持。 1. MyQttHub简介 MyQttHub.com是一个开放且可扩展的Cloud MQTT平台。其背后的团队ASPLhosting.com旨在为用户提供一个易于使用的平台,帮助他们基于MQTT.org协议创建物联网项目。除了其他功能,MyQttHub.com还提供一个完全开放和免费的计划,使您能够为家庭、工作或公司开发IoT解决方案。 2. 核心特点 开放性:MyQttHub支持MQTT和HTTPS这样的开放协议,让设备间的互联成为可能。 安全性:平台支持TLS/SSL/HTTPS,为MQTT-TLS和HTTPS通讯提供安全保障。更进一步,用户可以控制允许连接的源IP,包括MQTT管理员用户,以增强安全性。 扩展性:基于Akka和Scala技术,MyQttHub为MQTT提供高度可扩展的支持,确保即使在大规模设备部署中也能保持稳定和高效的运行。 交互性:通过Web界面,用户可以方便地管理他们的Cloud MQTT平台,包括设备、密码、已发布的消息、PUBLISH操作、订阅管理等。 REST API:通过支持REST API,平台为使用HTTPS的项目提供了完整的集成接口。此API让用户可以轻松地发布消息、整合MQTT与其他系统、使用HTTPS发送和接收MQTT消息。 过滤和储存:平台允许用户按主题和内容进行过滤,以及持久化存储重要消息。这种“stashing”或称“缓存”功能确保消息的安全存储并可以重新发送。 3. 灵活的计划选择 从免费的Open计划到高级的Premium计划,MyQttHub为各种规模的项目提供了多种选择。这些计划基于用户和设备的数量、连接数、存储空间和消息处理能力来设定,确保每位用户都能找到适合自己需求的计划。 4. 超越物联网 MyQttHub的用途不仅仅局限于IoT。其发布-订阅模型为系统间连接提供了简单且强大的手段,实现了系统间的隔离和解耦,确保数据的生产和消费可以独立进行。 5. 社区与支持 选择MyQttHub不仅仅是选择一个技术平台,还是选择一个活跃的社区和强大的支持团队。无论是设计疑问还是使用问题,MyQttHub团队都会为用户提供答案和帮助。 结论 在物联网领域,选择合适的技术和平台对于项目的成功至关重要。MyQttHub.com凭借其开放性、安全性、扩展性和多样性,已经成为一个值得信赖的选择。对于任何计划投身MQTT IoT项目的人来说,MyQttHub都会是一个不可错过的伙伴。 --- ### 181. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 HiveMQ:物联网数据的桥梁 随着物联网(IoT)的快速发展,数据交换和设备管理变得越来越关键。在这个环境下,MQTT(消息队列遥测传输)已经成为了一种首选的数据传输协议。在MQTT的世界中,HiveMQ的名字越来越受到重视。那么,HiveMQ到底是什么?它又如何帮助企业连接设备并进行高效的数据交换? HiveMQ的起源 HiveMQ于2012年在德国Landshut成立,位于慕尼黑附近。它的主旨是为企业提供一个可靠、高效、安全的平台,使设备能够与云进行双向数据交流。多年来,HiveMQ已经帮助超过130家客户,包括众多财富500强企业,完成了物联网的关键任务,如连接汽车、物流、工业4.0以及其他连接的IoT产品。 HiveMQ的产品与服务 HiveMQ提供了一系列的产品和服务,以满足不同类型的需求: HiveMQ Cloud:这是一个完全托管的MQTT平台,可以轻松地扩展,保证了IoT数据的安全性、可靠性和连续性。用户可以根据需要选择免费或付费计划,而付费计划又分为“入门”、“专业”和“企业”三个等级,以满足不同规模和复杂性的需求。 HiveMQ Swarm:这是一个新的产品,旨在进一步增强其产品组合。 HiveMQ Enterprise Extensions:这些是为大型企业设计的特定插件,如Kafka、Google Cloud Pub/Sub、MongoDB等,可以进一步提高HiveMQ的功能和适应性。 HiveMQ的安全性与稳定性 HiveMQ在设计时就充分考虑了安全性,确保IoT数据和应用能够满足最高的安全标准。它提供端到端的TLS加密、多种设备认证方法等高级安全功能。 此外,HiveMQ也为客户提供了强大的支持,包括社区支持、专门的24/7支持等,确保在整个IoT项目生命周期中都能获得所需的帮助。 HiveMQ与社区的联系 HiveMQ与MQTT社区之间有着深厚的联系。为了帮助MQTT获得更大的成功,HiveMQ成为了OASIS MQTT技术委员会和MQTT-SN技术委员会的成员。此外,它还积极赞助Eclipse Paho项目的主要提交者,并作为MQTT Sparkplug的创始成员之一加入了该行业倡议。 HiveMQ的社会责任 HiveMQ不仅仅是一个商业公司,它还对社会负有重要的责任。HiveMQ支持多个社会组织,例如“Schritt für Schritt Indienhilfe”和“Berberhilfe Landshut”,并为员工在印度的孩子提供了神父和神母的资助计划。 结论 HiveMQ是物联网领域的一个重要参与者,它为设备与云之间的数据交换提供了一个强大、可靠、安全的桥梁。无论是小型的试点项目,还是大型的生产部署,HiveMQ都能为企业提供所需的工具和支持,帮助它们实现物联网的完整潜力。 --- ### 182. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着物联网 (IoT) 技术的不断进步,连接世界各地的设备数量正呈现爆炸性增长。为了应对这种情况,我们需要一个强大、可靠且易于管理的通信平台。这正是 EMQX Cloud 所提供的。 公司介绍 EMQ 是一个致力于物联网、移动互联网、车联网和工业互联网领域的软件技术公司。自成立以来,EMQ 一直秉持创新的精神,为全球数千家企业提供了高性能、高可靠的中间件产品和解决方案。在 MQTT 通讯技术领域,EMQ 以其独特的技术视角和深厚的技术积累,建立了坚实的行业地位。 产品介绍 EMQX Cloud 是 EMQ 推出的完全托管的 IoT MQTT 服务。它旨在为广大企业和开发者提供一个稳定、可靠、易于使用的物联网通讯平台。 产品特点 高性能:EMQX Cloud 采用先进的技术架构,能够处理大量并发连接和消息传输,确保实时性和稳定性。 高扩展性:无论您是一个小型创业公司,还是一个拥有数亿设备的大型企业,EMQX Cloud 都可以轻松扩展,满足您的业务需求。 高安全性:EMQX Cloud 提供了多种安全机制,包括 SSL/TLS 加密、访问控制、身份验证等,确保您的数据始终处于安全状态。 完全托管:用户不需要担心后台的维护和升级问题,所有这些都由 EMQ 的专业团队来处理。 服务特点 用户友好的界面:EMQX Cloud 提供了一个直观、简洁的控制台,用户可以轻松地进行设备管理、监控和调试。 多区域部署:为了确保高可用性和数据的实时性,EMQX Cloud 支持多区域部署。 灵活的定价模式:根据用户的实际需求,EMQX Cloud 提供了多种定价模式,包括按量付费、预付费等。 专业的技术支持:EMQ 提供了一流的技术支持服务,无论您遇到任何问题,都可以获得及时、专业的帮助。 总之,EMQX Cloud 是物联网时代企业和开发者的首选通讯平台。无论您是 IoT 领域的初学者,还是经验丰富的专家,EMQX Cloud 都可以为您提供无与伦比的体验和价值。 --- ═══════════════════════════════════════════ ## MQTT 编程 ═══════════════════════════════════════════ ### 183. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 这段代码展示了如何使用MQTTnet库在.NET环境中发布MQTT应用消息,包括发布单个消息和发布多个消息的示例。下面是对这些示例代码加上中文注释的版本: // 授权给 .NET Foundation 根据一个或多个协议。 // .NET Foundation 在 MIT 许可下授权此文件。 // 有关详细信息,请参阅项目根目录中的 LICENSE 文件。 // ReSharper 禁用全局未使用类型 // ReSharper 禁用全局未使用成员 // ReSharper 禁用不一致命名 using MQTTnet.Client; namespace MQTTnet.Samples.Client; public static class Client_Publish_Samples { public static async Task Publish_Application_Message() { /* * 此示例推送一个包含主题和载荷的简单应用消息。 * * 总是在存在的情况下使用构建器。此项目中的构建器被设计为 * 向后兼容。通过其构造函数创建 _MqttApplicationMessage_ 也是 * 支持的,但是这个类在未来的发布中可能会经常更改,而构建器不会, * 或者至少在可能的情况下提供向后兼容性。 */ var mqttFactory = new MqttFactory(); using (var mqttClient = mqttFactory.CreateMqttClient()) { var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer("broker.hivemq.com") .Build(); await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); var applicationMessage = new MqttApplicationMessageBuilder() .WithTopic("samples/temperature/living_room") .WithPayload("19.5") .Build(); await mqttClient.PublishAsync(applicationMessage, CancellationToken.None); await mqttClient.DisconnectAsync(); Console.WriteLine("MQTT 应用消息已发布。"); } } public static async Task Publish_Multiple_Application_Messages() { /* * 此示例推送多个包含主题和载荷的简单应用消息。 * * 详情见 _Publish_Application_Message_ 示例。 */ var mqttFactory = new MqttFactory(); using (var mqttClient = mqttFactory.CreateMqttClient()) { var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer("broker.hivemq.com") .Build(); await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); var applicationMessage = new MqttApplicationMessageBuilder() .WithTopic("samples/temperature/living_room") .WithPayload("19.5") .Build(); await mqttClient.PublishAsync(applicationMessage, CancellationToken.None); applicationMessage = new MqttApplicationMessageBuilder() .WithTopic("samples/temperature/living_room") .WithPayload("20.0") .Build(); await mqttClient.PublishAsync(applicationMessage, CancellationToken.None); applicationMessage = new MqttApplicationMessageBuilder() .WithTopic("samples/temperature/living_room") .WithPayload("21.0") .Build(); await mqttClient.PublishAsync(applicationMessage, CancellationToken.None); await mqttClient.DisconnectAsync(); Console.WriteLine("MQTT 应用消息已发布。"); } } } 这些示例代码提供了使用MQTTnet库在.NET应用中与MQTT代理服务器连接并发布消息的基本方法。通过使用MqttClientOptionsBuilder来配置客户端选项,包括指定MQTT代理服务器的地址。然后,使用MqttApplicationMessageBuilder构建应用消息,并通过调用PublishAsync方法来发布这些消息。最后,示例中还展示了如何优雅地断开与MQTT代理服务器的连接。 --- ### 184. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 摘要:在构建智能家居系统时,实现不同通信协议之间的互操作性是一项关键任务。modbus2mqtt项目通过桥接Modbus和MQTT协议,为此提供了一个高效的解决方案。本文深入探讨了modbus2mqtt的实现细节,包括其依赖、功能、和实际应用。 引言:在智能家居和工业自动化领域,Modbus协议常用于传感器和执行器的通信,而MQTT作为一种轻量级的消息传递协议,适用于物联网(IoT)通信。modbus2mqtt是一个Python脚本,它实现了Modbus与MQTT之间的数据转换和传输,从而在异构的智能家居环境中提供了一个集中式消息总线解决方案。 1. 技术背景与依赖性:该项目依赖于两个关键的Python库: Eclipse Paho:用于实现MQTT客户端功能,实现与MQTT代理的通信。 modbus-tk:用于处理Modbus通信,包括读取和写入Modbus从设备的寄存器。 # # modbus2mqtt - Modbus master with MQTT publishing # # Written and (C) 2015 by Oliver Wagner <owagner@tellerulam.com> # Provided under the terms of the MIT license # # Requires: # - Eclipse Paho for Python - http://www.eclipse.org/paho/clients/python/ # - modbus-tk for Modbus communication - https://github.com/ljean/modbus-tk/ # import argparse import logging import logging.handlers import time import socket import paho.mqtt.client as mqtt import serial import io import sys import csv import signal import modbus_tk import modbus_tk.defines as cst from modbus_tk import modbus_rtu from modbus_tk import modbus_tcp version="0.5" parser = argparse.ArgumentParser(description='Bridge between ModBus and MQTT') parser.add_argument('--mqtt-host', default='localhost', help='MQTT server address. Defaults to "localhost"') parser.add_argument('--mqtt-port', default='1883', type=int, help='MQTT server port. Defaults to 1883') parser.add_argument('--mqtt-topic', default='modbus/', help='Topic prefix to be used for subscribing/publishing. Defaults to "modbus/"') parser.add_argument('--clientid', default='modbus2mqtt', help='Client ID prefix for MQTT connection') parser.add_argument('--rtu', help='pyserial URL (or port name) for RTU serial port') parser.add_argument('--rtu-baud', default='19200', type=int, help='Baud rate for serial port. Defaults to 19200') parser.add_argument('--rtu-parity', default='even', choices=['even','odd','none'], help='Parity for serial port. Defaults to even') parser.add_argument('--tcp', help='Act as a Modbus TCP master, connecting to host TCP') parser.add_argument('--tcp-port', default='502', type=int, help='Port for Modbus TCP. Defaults to 502') parser.add_argument('--registers', required=True, help='Register definition file. Required!') parser.add_argument('--log', help='set log level to the specified value. Defaults to WARNING. Use DEBUG for maximum detail') parser.add_argument('--syslog', action='store_true', help='enable logging to syslog') parser.add_argument('--force', default='0',type=int, help='publish values after "force" seconds since publish regardless of change. Defaults to 0 (change only)') args=parser.parse_args() if args.log: logging.getLogger().setLevel(args.log) if args.syslog: logging.getLogger().addHandler(logging.handlers.SysLogHandler()) else: logging.getLogger().addHandler(logging.StreamHandler(sys.stdout)) topic=args.mqtt_topic if not topic.endswith("/"): topic+="/" logging.info('Starting modbus2mqtt V%s with topic prefix \"%s\"' %(version, topic)) def signal_handler(signal, frame): print('Exiting ' + sys.argv[0]) sys.exit(0) signal.signal(signal.SIGINT, signal_handler) class Register: def __init__(self,topic,frequency,slaveid,functioncode,register,size,format): self.topic=topic self.frequency=int(frequency) self.slaveid=int(slaveid) self.functioncode=int(functioncode) self.register=int(register) self.size=int(size) self.format=format.split(":",2) self.next_due=0 self.lastval=None self.last = None def checkpoll(self): if self.next_due<time.time(): self.poll() self.next_due=time.time()+self.frequency def poll(self): try: res=master.execute(self.slaveid,self.functioncode,self.register,self.size,data_format=self.format[0]) r=res[0] if self.format[1]: r=self.format[1] % r if r!=self.lastval or (args.force and (time.time() - self.last) > int(args.force)): self.lastval=r fulltopic=topic+"status/"+self.topic logging.info("Publishing " + fulltopic) mqc.publish(fulltopic,self.lastval,qos=0,retain=True) self.last = time.time() except modbus_tk.modbus.ModbusError as exc: logging.error("Error reading "+self.topic+": Slave returned %s - %s", exc, exc.get_exception_code()) except Exception as exc: logging.error("Error reading "+self.topic+": %s", exc) registers=[] # Now lets read the register definition with open(args.registers,"r") as csvfile: dialect=csv.Sniffer().sniff(csvfile.read(8192)) csvfile.seek(0) defaultrow={"Size":1,"Format":">H","Frequency":60,"Slave":1,"FunctionCode":4} reader=csv.DictReader(csvfile,fieldnames=["Topic","Register","Size","Format","Frequency","Slave","FunctionCode"],dialect=dialect) for row in reader: # Skip header row if row["Frequency"]=="Frequency": continue # Comment? if row["Topic"][0]=="#": continue if row["Topic"]=="DEFAULT": temp=dict((k,v) for k,v in row.iteritems() if v is not None and v!="") defaultrow.update(temp) continue freq=row["Frequency"] if freq is None or freq=="": freq=defaultrow["Frequency"] slave=row["Slave"] if slave is None or slave=="": slave=defaultrow["Slave"] fc=row["FunctionCode"] if fc is None or fc=="": fc=defaultrow["FunctionCode"] fmt=row["Format"] if fmt is None or fmt=="": fmt=defaultrow["Format"] size=row["Size"] if size is None or size=="": size=defaultrow["Size"] r=Register(row["Topic"],freq,slave,fc,row["Register"],size,fmt) registers.append(r) logging.info('Read %u valid register definitions from \"%s\"' %(len(registers), args.registers)) def messagehandler(mqc,userdata,msg): try: (prefix,function,slaveid,functioncode,register) = msg.topic.split("/") if function != 'set': return if int(slaveid) not in range(0,255): logging.warning("on message - invalid slaveid " + msg.topic) return if not (int(register) >= 0 and int(register) < sys.maxint): logging.warning("on message - invalid register " + msg.topic) return if functioncode == str(cst.WRITE_SINGLE_COIL): logging.info("Writing single coil " + register) elif functioncode == str(cst.WRITE_SINGLE_REGISTER): logging.info("Writing single register " + register) else: logging.error("Error attempting to write - invalid function code " + msg.topic) return res=master.execute(int(slaveid),int(functioncode),int(register),output_value=int(msg.payload)) except Exception as e: logging.error("Error on message " + msg.topic + " :" + str(e)) def connecthandler(mqc,userdata,rc): logging.info("Connected to MQTT broker with rc=%d" % (rc)) mqc.subscribe(topic+"set/+/"+str(cst.WRITE_SINGLE_REGISTER)+"/+") mqc.subscribe(topic+"set/+/"+str(cst.WRITE_SINGLE_COIL)+"/+") mqc.publish(topic+"connected",2,qos=1,retain=True) def disconnecthandler(mqc,userdata,rc): logging.warning("Disconnected from MQTT broker with rc=%d" % (rc)) try: clientid=args.clientid + "-" + str(time.time()) mqc=mqtt.Client(client_id=clientid) mqc.on_connect=connecthandler mqc.on_message=messagehandler mqc.on_disconnect=disconnecthandler mqc.will_set(topic+"connected",0,qos=2,retain=True) mqc.disconnected =True mqc.connect(args.mqtt_host,args.mqtt_port,60) mqc.loop_start() if args.rtu: master=modbus_rtu.RtuMaster(serial.serial_for_url(args.rtu,baudrate=args.rtu_baud,parity=args.rtu_parity[0].upper())) elif args.tcp: master=modbus_tcp.TcpMaster(args.tcp,args.tcp_port) else: logging.error("You must specify a modbus access method, either --rtu or --tcp") sys.exit(1) master.set_verbose(True) master.set_timeout(5.0) while True: for r in registers: r.checkpoll() time.sleep(1) except Exception as e: logging.error("Unhandled error [" + str(e) + "]") sys.exit(1) 2. 功能概述:modbus2mqtt作为Modbus主设备运行,持续轮询连接的Modbus从设备,并将读取的数据通过MQTT发布。它支持自定义的轮询频率和寄存器地址,同时也能处理Modbus的写操作。 3. 命令行参数:脚本通过命令行参数提供了高度的定制性,包括设置MQTT服务器的地址和端口、定义MQTT主题前缀、配置Modbus RTU串口或TCP连接参数,以及指定寄存器定义文件。 4. 寄存器定义与消息发布:寄存器的定义存储在CSV文件中,包含寄存器地址、大小、格式和轮询频率等信息。脚本根据这些定义轮询Modbus寄存器,并将结果发布到相应的MQTT主题。 5. 高级特性:除了基础的读功能,modbus2mqtt还支持写入Modbus线圈和寄存器,允许通过MQTT消息对Modbus设备进行控制。此外,脚本支持强制定时发布功能,确保即使数据未变化也能定期更新状态。 6. 应用场景:modbus2mqtt适用于需要将Modbus设备集成进基于MQTT的智能家居或工业自动化系统的场景。例如,在智能家居中,可以通过MQTT控制和监视基于Modbus的温度传感器、开关等设备。 结论:modbus2mqtt弥合了Modbus和MQTT两大主流通信协议的差异,为智能家居和工业自动化系统提供了一种有效的数据集成方案。通过灵活的配置和强大的功能,它能够满足各种复杂场景的需求。 --- ### 185. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言在使用基于M2Mqtt.Net的Mqtt客户端进行网络通信时,面对网络波动或服务端不稳定情况,实现客户端的自动重连机制变得至关重要。本文详细介绍了如何在C#环境下使用M2Mqtt.Net库实现这一功能。 一、M2Mqtt.Net客户端的关键特性 在实现重连机制前,了解M2Mqtt.Net客户端的一些关键特性是必要的: 服务端地址解析: 如果服务端地址不可解析,会导致MqttClient对象无法实例化,从而引发异常。 连接状态管理: 在Connect方法无法建立连接时,会引发异常,并使IsConnected属性为false。 连接断开处理: 服务端断开将触发ConnectionClosed事件,并将IsConnected置为false。 重新连接和订阅: 重新连接后,需要重新订阅相关主题。 订阅参数要求: 在调用MqttClient.Subscribe方法时,订阅主题数组和相应的qosLevel数组长度必须一致。 二、重连流程控制 以下是自动重连机制的主要实现步骤: 1. 自动重连主体方法 _TryContinueConnect private void _TryContinueConnect() { if (IsConnected) return; Thread retryThread = new Thread(new ThreadStart(delegate { while (_MqttClient == null || !_MqttClient.IsConnected) { if (_ToClose) break; if (_MqttClient == null) { _BuildClient(); Thread.Sleep(3000); continue; } try { _TryCount++; _Connect(); } catch (Exception ce) { Debug.WriteLine("re connect exception:" + ce.Message); } if (!_MqttClient.IsConnected) { Thread.Sleep(2000); } } })); retryThread.Start(); } 2. 实例化客户端方法 _BuildClient private void _BuildClient() { try { _MqttClient = new MqttClient(_MqttServer); _MqttClient.MqttMsgPublishReceived += client_MqttMsgPublishReceived; _MqttClient.ConnectionClosed += (sender, e) => { if (!_ToClose) { _TryContinueConnect(); } }; } catch (Exception e) { Debug.WriteLine("build client error:" + e.Message); } } 3. 尝试连接方法 _Connect private void _Connect() { if (String.IsNullOrEmpty(_MqttUsername)) { var b = _MqttClient.Connect(_MqttClientId); } else { var b = _MqttClient.Connect(_MqttClientId, _MqttUsername, _MqttUserpass); } if (_MqttClient.IsConnected) { _MqttClient.Subscribe(new string[] { "topic1", "topic2" }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE }); } } 在这个完整的代码示例中,我们可以看到如何在客户端断开连接时自动重连。在_TryContinueConnect方法中,如果客户端未连接,则会启动一个新线程来尝试重新连接,直到连接成功或者明确地中断重连过程。同时,_BuildClient方法中的异常处理确保了在无法实例化MqttClient时能够正确地记录错误,并且通过绑定事件处理器来处理消息接收和连接断开的情况。最后,_Connect方法则负责处理客户端的连接逻辑,并在连接成功后重新订阅所需的主题。 三、重连逻辑详解 在_TryContinueConnect方法的循环中,不断检查客户端的连接状态,并在断开时尝试重连。每次尝试失败后,线程会暂停一段时间后再次尝试。 四、实际应用和调整 在实际应用中,这个机制显示了良好的稳定性和灵活性。延时时间可以根据网络环境和应用需求进行调整,以达到最优的重连效果。 结语通过上述步骤,我们可以在C#环境中有效实现Mqtt客户端的断线重连机制。这不仅提高了通信的稳定性,还增强了应用的健壮性,是网络通信中不可或缺的一环。 --- ### 186. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 逐步指南 引言 本指南将逐步展示如何部署和配置IoTAgent-JSON物联网代理,用于将设备连接到外部的NGSI代理(即上下文代理)。 IoTAgent-JSON物联网代理作为一个网关,使用MQTT协议与NGSI代理(或使用NGSI协议的其他组件)进行通信。通信基于一系列单向的MQTT主题(即:每个主题用于发布设备信息或订阅实体更新,但不是两者兼具)。每个主题都有相同的前缀,形式如下: /<apiKey>/<deviceId>/topicSpecificPart 其中apiKey是用于逻辑分组设备(和安全问题)的字母数字字符串,deviceId是唯一标识设备的ID。API密钥可以为IoT代理的一个实例全局配置,或为特定设备组专门配置(如后续章节所述)。 该协议的详细规范可在此处找到。 本指南将通过一个常见场景的逐步示例来展示代理的使用,从IoT代理设置到测量报告(包括单独配置设备的情况和首先配置具有新API密钥的设备组的情况)。开始指南前,请确保满足下一节中的所有要求。 在开始教程之前,我们需要一些关于即将部署服务的信息。我们将使用以下数据,模拟智能家居应用: 服务:myhome 子服务:/environment 设备ID:sensor01、sensor02 和 actuator01 先决条件 本逐步指南假设您将在一台单独的机器上安装所有软件,该机器安装了Red Hat 6.5 Linux。因此,它可能不适用于生产目的的架构,但应作为一个开发机来测试MQTT物联网代理。所有命令都应该在同一台机器上执行(甚至包括curl和mosquitto-pub命令),但将它们更改为从外部机器执行应该是一个简单的任务。 本教程选择的MQTT代理是Mosquitto,尽管可以用任何其他标准MQTT代理替代。本指南还将使用Mosquitto命令工具来测试安装和展示模拟设备与上下文代理之间的信息交换。 推荐软件及版本列表如下: Orion上下文代理(v2.5.0) Node.js(v10) Mosquitto(v1.4.7)(开箱即用设置) Curl(v7.19.7) Git(v1.7.1) 这些是编写本教程时使用的版本,但任何高于这些版本的版本也应该工作(早期版本也可能工作,但也可能不工作,因此我们鼓励您使用高于这些版本的版本)。 为了提高可读性,所有命令都将以root身份执行。要使用其他用户,请给予其适当权限并像往常一样使用sudo(从RPM包安装会为代理创建一个特殊用户,但在本教程中不会使用)。 使用默认API密钥配置单个设备 安装IoT代理 安装IoT代理有多种方式。在本教程中,我们将从仓库克隆代理的最新版本。有关不同设置,请查看主README.md文件中的安装指南。 我们将在/opt仓库中安装我们的IoT代理。要执行此操作,请转到文件夹并使用以下命令克隆仓库: cd /opt git clone https://github.com/telefonicaid/iotagent-json.git 现在仓库已被克隆,请进入新目录并使用以下命令安装依赖项: cd iotagent-json npm install 现在,通过执行以下命令在后台运行代理: nohup bin/iotagent-json &> /var/log/iotAgent& 代理现在应该在北端口(默认为4041)监听。使用netstat命令检查: netstat -ntpl | grep 4041 您应该看到如下输出: tcp 0 0 0.0.0.0:4041 0.0.0.0:* LISTEN 18388/node 检查一切是否正常工作的简单方法是从IoT代理的北端口获取版本: curl http://localhost:4041/iot/about 结果将是一个JSON文档,指示IoTAgent-JSON IoTA版本和正在使用的IoTA库版本: { "libVersion": "0.9.5", "port": 4041, "baseRoot": "/", "version": "0.1.5" } 您也可以在nohup命令创建的/var/log/iotAgent文件中检查日志。 IoT代理配置 IoTAgent的所有配置都可以通过修改单个文件config.js来完成。默认值应该满足本教程的需求。 有关这些值的详细描述,请查看iotagent-node-lib配置文档。 在遵循本教程时,您可能想要更改的一个配置值是logLevel。如果您在遵循指南时遇到任何问题,或者您只是想了解IoTA内部发生了什么,请将其值设置为DEBUG。 还要注意,deviceRegistry的配置类型设置为memory。这意味着当IoT代理重新启动时,设备注册表的所有内容都将从内存中擦除。这意味着在测试环境中使用,它将迫使您在重新启动代理后重新配置所有设备。要获得持久的注册表,请查看文档了解如何将IoTA连接到MongoDB实例。 配置设备 为了开始使用IoTA,必须配置新设备。我们将使用curl命令创建它。执行以下命令: curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{ "devices": [ { "device_id": "sensor01", "entity_name": "LivingRoomSensor", "entity_type": "multiSensor", "attributes": [ { "object_id": "t", "name": "Temperature", "type": "celsius" }, { "object_id": "l", "name": "Luminosity", "type": "lumens" } ] } ] } ' 'http://localhost:4041/iot/devices' 这个命令将创建最简单的设备类型,只声明了两个活动属性:温度和亮度。 我们还没有为我们的设备创建特定配置,因此API密钥将是IoTA的默认密钥(即:1234)。这个默认API密钥可以在配置文件中更改。 使用设备发送测量值 现在我们可以模拟一些设备的测量值。由于我们的设备具有设备ID sensor01,我们正在使用的API密钥是默认的1234,我们可以使用以下命令使用mosquitto命令行客户端发送测量值: mosquitto_pub -t /1234/sensor01/attrs -m '{"l":4,"t": "31.5"}' 这个命令应该将所有信息发布到上下文代理。对设备实体执行queryContext操作应该给出我们发布的信息: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -d '{ "entities": [ { "isPattern": "false", "id": "LivingRoomSensor", "type": "multiSensor" } ] }' 'http://localhost:1026/v1/queryContext' 结果响应应如下所示: { "contextResponses": [ { "contextElement": { "type": "multiSensor", "isPattern": "false", "id": "LivingRoomSensor", "attributes": [ { "name": "Luminosity", "type": "lumens", "value": "4" }, { "name": "Temperature", "type": "celsius", "value": "31.5" } ] }, "statusCode": { "code": "200", "reasonPhrase": "OK" } } ] } 从上下文代理检索配置参数IoTAgent-JSON物联网代理提供了一种特殊机制,用于从代表设备的实体中检索信息,以便设备配置。这种机制基于两个特殊主题,后缀分别为/configuration/commands和/configuration/values。为了测试此功能,我们首先将为代表设备的上下文代理实体添加一些配置属性。我们将使用以下NGSI请求添加sleepTime属性: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Cache-Control: no-cache" -d '{ "value" : "300" }' 'http://localhost:1026/v1/contextEntities/LivingRoomSensor/attributes/sleepTime' 当IoT代理请求配置值时,它会向上下文代理请求这些值。一旦收集到这些值,它将通过带有'/configuration/values'后缀的主题将它们发送到设备。要使用我们的模拟设备检查此操作,请执行以下行: mosquitto_sub -t /1234/sensor01/configuration/values 将此命令保留在单独的窗口中,同时执行以下步骤。现在我们可以发送类似以下的MQTT请求,向IoT代理请求属性值: mosquitto_pub -t /1234/sensor01/configuration/commands -m '{ "type": "configuration", "fields": [ "sleepTime" ] }' 如果我们现在返回到订阅窗口,我们应该能够看到sleepTime命令的值: { "sleepTime": "300", "dt": "20160209T111442Z" } 与设备请求的所有信息一起,IoT代理将在响应的dt字段中报告服务器时间。 使用配置配置多个设备 在需要配置具有类似特征的一组设备的情况下,可以为它们创建公共配置。此配置配置可用于通过为每个组建立特定的API密钥来分隔服务之间的设备消息。这可用于保护特定设备组的访问权限(在Mosquitto MQTT代理的最后一节中将展示如何实现这一点的示例)。 配置 首先,我们将使用引言部分定义的数据配置一个新的配置。为此,我们将发出以下命令: curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{ "services": [ { "resource": "/iot/json", "apikey": "AAFF9977", "type": "potSensor" } ] } ' 'http://localhost:4041/iot/services' 这将使该服务、子服务和类型下配置的设备使用提供的APIKey作为MQTT主题中的APIKey前缀。 配置设备 对于支持自动设备配置的IoT代理,配置一个配置就足以开始使用使用该配置的设备。对于那些不支持的代理,每个特定设备必须配置,以便在设备注册表中保存其deviceID。设备配置与单个设备的配置非常似: curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{ "devices": [ { "device_id": "sensor02", "entity_name": "RosesPot", "entity_type": "potSensor", "attributes": [ { "name": "humidity", "type": "degrees" }, { "name": "happiness", "type": "subjective" } ] } ] } ' 'http://localhost:4041/iot/devices' 发送测量数据 现在我们可以像单个设备配置的情况一样模拟测量。使用以下命令发送新的模拟测量: mosquitto_pub -t /AAFF9977/sensor02/attrs -m '{"humidity": 76,"happiness": "Not bad"}' 请注意,在这种情况下,API密钥不是默认的,而是我们在配置API中定义的。我们可以通过再次调用上下文代理来检查一切是否正常: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -d '{ "entities": [ { "isPattern": "false", "id": "RosesPot", "type": "potSensor" } ] }' 'http://localhost:1026/v1/queryContext' 我们将得到类似这样的响应: { "contextResponses" : [ { "contextElement" : { "type" : "potSensor", "isPattern" : "false", "id" : "RosesPot", "attributes" : [ { "name" : "happiness", "type" : "subjective", "value" : "Not bad" }, { "name" : "humidity", "type" : "degrees", "value" : "76" } ] }, "statusCode" : { "code" : "200", "reasonPhrase" : "OK" } } ] } 这表明我们发送的测量信息已正确写入上下文代理。 使用ACL保护配置访问权限 概述 使用特殊API密钥使IoT代理管理员有机会为每组设备设置不同的MQTT代理级别权限,使用不同的授权机制分隔不同组的访问。使用开箱即用的Mosquitto设置,任何设备(实际上,任何MQTT客户端)都可以冒充其他设备发送信息或读取其实体中的信息,只需知道它们的API密钥和设备ID。为了避免这个问题,我们将创建一个ACL,为我们的配置赋予特殊权限,并为该组的设备设置一组凭据(应与设备秘密共享)。为了简单起见,我们将使用一组用户和密码凭据,所有该组的设备都使用相同的凭据(也可以使用其他认证方式,如证书,请查阅Mosquitto文档了解其他选项)。IoTA访问也可能发生设备冒充问题(因为IoTA是另一个MQTT客户端,默认情况下是匿名的)。为了保护IoTA的交互,将创建另一个用户。 配置 为了创建用户,我们将使用mosquitto提供的密码工具。执行以下命令: touch /etc/mosquitto/pwfile mosquitto_passwd -b /etc/mosquitto/pwfile iota iota mosquitto_passwd -b /etc/mosquitto/pwfile potteduser pottedpass 这将创建两组凭据(登录/密码):iota/iota 和 potteduser/pottedpass。可以使用ACL文件赋予不同主题的权限。要创建一个ACL文件,只需创建一个新的`/etc/mosquitto/aclfile`文件,内容如下: topic read $SYS/# topic write /1234/+/attrs topic write /1234/+/attrs/# topic write /1234/+/configuration/commands topic read /1234/+/configuration/values user iota topic /# user potteduser topic write /AAFF9977/+/attrs topic write /AAFF9977/+/attrs/# topic write /AAFF9977/+/configuration/commands topic read /AAFF9977/+/configuration/values pattern write $SYS/broker/connection/%c/state 此文件中有三个感兴趣的部分: 1. 第一部分为默认API密钥(本例中为1234)定义了一组主题。这些主题根据设备将要执行的动作被标记为读或写。禁止除所定义动作之外的访问,以及向读主题发布或相反的操作。这确保了没有设备能冒充IoT代理,但这并不阻止一个设备冒充其他设备。此访问是匿名的。 2. iota用户是认证的,可以访问一切,因为假设是代理的所有者(只有管理员应该访问此用户)。 3. 对于potteduser账户,权限与匿名设备类似,但前缀是不同的API密钥。这确保了来自其他组的设备(假定没有作为potteduser的有效凭据)无法冒充该组的设备,或订阅该组设备发送的信息。 在我们重新开始测试之前,还需要做两个更改。首先,我们应该在IoTA配置中添加Mosquitto的IoTA凭据,以便其获得MQTT代理主题的完全访问权限。为此,请编辑`/opt/iotajson/config.js`文件,将config.mqtt部分更改为如下所示: config.mqtt = { host: "localhost", port: 1883, defaultKey: "1234", username: "iota", password: "iota", }; 最后一个操作是编辑`/etc/mosquitto/mosquitto.conf`,将aclfile和pwfile文件添加到配置中。完成的配置应该类似于以下内容: pid_file /var/run/mosquitto.pid persistence true persistence_location /var/lib/mosquitto/ log_dest file /var/log/mosquitto/mosquitto.log #acl_file /etc/mosquitto/aclfile password_file /etc/mosquitto/pwfile include_dir /etc/mosquitto/conf.d 完成所有更改后,重启mosquitto: service mosquitto restart 并重新运行IoT代理(您可以使用ps或netstat检查其PID并杀死它)。 测试 配置和设备配置 为了测试ACL文件,首先像前一章中那样配置配置和设备,但使用不同的设备,数据如下:- 名称:DaisyPot- 设备ID:sensor03重要的是,您配置的配置使用的API密钥与ACL中声明的完全相同。设备配置请求如下: curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{ "devices": [ { "device_id": "sensor03", "entity_name": "DaisyPot", "entity_type": "potSensor", "attributes": [ { "name": "humidity", "type": "degrees" }, { "name": "happiness", "type": "subjective" } ] } ] } ' 'http://localhost:4041/iot/devices' 发送测量数据 现在我们可以尝试使用与第一种情况相同的命令发送新的测量数据: mosquitto_pub -t /AAFF9977/sensor03/attrs -m '{"humidity": 76,"happiness": "Not bad"}' 如果我们使用queryContext检查更改是否已传递到上下文代理,我们会发现这些测量数据已被忽略: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -d '{ "entities": [ { "isPattern": "false", "id": "DaisyPot", "type": "potSensor" } ] }' 'http://localhost:1026/v1/queryContext' 检查IoTAgent日志,您会看到请求完全被忽略了。问题在于,客户端试图以匿名方式发布到仅允许potteduser发布新消息的受ACL保护的主题。如果我们使用我们为用户生成的凭证再次尝试: mosquitto_pub -t /AAFF9977/sensor03/attrs -m '{"humidity": 76,"happiness": "Not bad"}' -u potteduser -P pottedpass 并再次执行queryContext操作,我们将获得更新后的实体: { "contextResponses": [ { "contextElement": { "type": "potSensor", "isPattern": "false", "id": "DaisyPot", "attributes": [ { "name": "happiness", "type": "subjective", "value": " " }, { "name": "humidity", "type": "degrees", "value": " " } ] }, "statusCode": { "code": "200", "reasonPhrase": "OK" } } ] } 这表明我们发送的测量信息已经正确地传输到了上下文代理。 安装 安装JSON物联网代理有三种方式:使用Git、RPM或Docker镜像。 使用GIT 要安装TT代理,只需克隆项目并安装依赖项: git clone https://github.com/telefonicaid/iotagent-json.git npm install 要启动物联网代理,从项目的根文件夹中输入: bin/iotagent-json 使用RPM 项目包含一个脚本,用于生成可在Red Hat 6.5兼容的Linux发行版上安装的RPM。RPM依赖于Node.js 0.10版本,因此建议使用EPEL仓库。 要创建RPM,请在/rpm文件夹内执行以下脚本: create-rpm.sh -v <versionNumber> -r <releaseNumber> 一旦RPM生成,可以使用以下命令安装: yum localinstall --nogpg <nameOfTheRPM>.rpm 将作为linux服务安装,可以像往常一样使用service命令启动: service iotaJSON start 使用Docker Docker Hub上提供了一个Docker容器。它将使用config.js中定义的默认设置启动容器。 docker run -it --init fiware/iotagent-json 要使用您自己的配置,可以挂载本地配置文件: docker run -it --init -v <path-to-configuration-file>:/opt/iotajson/new_config.js fiware/iotagent-json -- new_config.js 作为替代,也可以使用环境变量传递配置,如“使用环境变量配置”小节所述。 使用 要执行JSON物联网代理,只需从根文件夹执行以下命令: bin/iotagentMqtt.js 这将在前台启动JSON物联网代理。使用标准Linux命令将其设置为在后台运行。 无参数启动时,物联网代理将预期在根文件夹中找到一个带有配置的config.js文件。可以传递一个参数,带有新配置文件的路径(相对于应用程序文件夹),以替代默认配置。 配置 概述 物联网代理的所有配置都存储在一个配置文件中(通常安装在根文件夹中)。 这个配置文件是一个JavaScript文件,包含三个配置章节: iota:此对象存储IoT代理北端口的配置,完全由IoT代理库管理。更多关于这些选项的信息可以在这里找到。 mqtt:此对象存储特定于MQTT的配置。详细描述可在下一节中找到。 http:此对象存储特定于HTTP的配置。详细描述可在下一节中找到。 还有一些全局配置选项: configRetrieval:此标志指示是否应使用来自库最新版本的双向插件处理传入IoT代理的通知,或使用JSON特定的配置检索机制(如用户手册中所述)。不允许同时使用这两种机制。 config.defaultKey:设备缺乏提供的配置时使用的默认API密钥。 config.defaultTransport:用于解析传入命令和懒惰属性的MQTT传输协议代码,以防无法为设备推断传输协议。 compressTimestamp:此标志启用时间戳压缩机制,如用户手册中所述。 MQTT配置 以下是目前可用的MQTT配置选项: protocol:用于连接MQTT代理的协议(mqtt、mqtts、tcp、tls、ws、wss)。默认为mqtt host:MQTT代理的主机。 port:MQTT代理监听的端口。 defaultKey:在没有配置的情况下为设备配置的默认API密钥。 ca:用于验证服务器证书的ca证书(可选)。默认信任Mozilla精心策划的知名CA。当使用此选项明确指定CA时,Mozilla的CA将被完全替换。 cert:PEM格式的证书链,用于验证连接到MQTT代理(可选)。仅在使用mqtts、tls或wss作为连接协议时使用。 key:PEM格式的可选私钥,用于客户端连接MQTT代理(可选)。仅在使用mqtts、tls或wss作为连接协议时使用。包含的CA列表将用于确定服务器是否获得授权。 rejectUnauthorized:是否拒绝未经提供的CA授权的任何连接。此选项仅在使用mqtts、tls或wss协议时有效(默认为true)。如果使用自签名证书,请将其设置为false,但请注意,您将暴露于中间人攻击,因此这是不推荐用于生产环境的配置。 username:标识IOTA对MQTT代理的用户名(可选)。 password:如果提供了用户名,则使用的密码(可选)。 qos:QoS级别:至多一次(0),至少一次(1),正好一次(2)。 (默认为0)。 retain:保留标志(默认为false)。 retries:MQTT连接错误重试次数(默认为5次)。 retryTime:MQTT连接重试间隔时间(默认为5秒)。 keepalive:客户端与MQTT代理之间保持连接打开的时间(默认为60秒)。如果您遇到断开连接问题,建议使用大于0的值(如本例所述)。 avoidLeadingSlash:此标志设置代理是否发布带有斜杠(旧版本中的默认)或不带斜杠的主题。请参见讨论。 clean:此标志默认为true,设置为false以接收离线时的QoS 1和2消息。 clientId:标识mqtt代理中的客户端的字符串ID。默认使用由固定前缀iotajson_和随机后缀组成的字符串,即iotajson_43bf8a3a。 TLS选项(即ca、cert、key、rejectUnauthorized)直接与Node.js的tls模块支持的选项相关。 AMQP绑定配置 config.amqp部分的配置文件包含连接到AMQP代理所需的所有信息。接受以下属性: host:AMQP代理所在的主机。 port:AMQP代理监听的端口 username:标识IOTA对AMQP代理的用户名(可选)。 password:如果提供了用户名,则使用的密码(可选)。 exchange:AMQP代理中的交换机 queue:AMQP代理中的队列 durable:持久队列标志(默认为false)。 retries:AMQP连接错误重试次数(默认为5次)。 retryTime:AMQP连接重试间隔时间(默认为5秒)。 HTTP绑定配置 config.http部分的配置文件包含启动HTTP传输协议绑定的HTTP服务器所需的所有信息。接受以下选项: port:南端口,HTTP监听器将在此监听设备的信息。 timeout:HTTP端点的HTTP超时时间(以毫秒为单位)。 key:HTTPS绑定的私钥路径 cert:HTTPS绑定的证书路径 使用环境变量配置 一些更常见的变量可以使用环境变量配置。覆盖config.iota集中的一般参数的变量在IoTA库配置手册中进行了描述。 与全局配置相关的变量在下表中描述。 环境变量配置属性IOTA_CONFIG_RETRIEVALconfigRetrievalIOTA_DEFAULT_KEYdefaultKeyIOTA_DEFAULT_TRANSPORTdefaultTransport 与特定JSON绑定相关的变量在下表中描述。 环境变量配置属性IOTA_MQTT_PROTOCOLmqtt.protocolIOTA_MQTT_HOSTmqtt.hostIOTA_MQTT_PORTmqtt.portIOTA_MQTT_CAmqtt.caIOTA_MQTT_CERTmqtt.certIOTA_MQTT_KEYmqtt.keyIOTA_MQTT_REJECT_UNAUTHORIZEDmqtt.rejectUnauthorizedIOTA_MQTT_USERNAMEmqtt.usernameIOTA_MQTT_PASSWORDmqtt.passwordIOTA_MQTT_QOSmqtt.qosIOTA_MQTT_RETAINmqtt.retainIOTA_MQTT_RETRIESmqtt.retriesIOTA_MQTT_RETRY_TIMEmqtt.retryTimeIOTA_MQTT_KEEPALIVEmqtt.keepaliveIOTA_MQTT_AVOID_LEADING_SLASHmqtt.avoidLeadingSlashIOTA_MQTT_CLEANmqtt.cleanIOTA_MQTT_CLIENT_IDmqtt.clientIdIOTA_MQTT_DISABLEDmqtt.disabledIOTA_AMQP_HOSTamqp.hostIOTA_AMQP_PORTamqp.portIOTA_AMQP_USERNAMEamqp.usernameIOTA_AMQP_PASSWORDamqp.passwordIOTA_AMQP_EXCHANGEamqp.exchangeIOTA_AMQP_QUEUEamqp.queueIOTA_AMQP_DURABLEamqp.durableIOTA_AMQP_RETRIESamqp.retriesIOTA_AMQP_RETRY_TIMEamqp.retryTimeIOTA_AMQP_DISABLEDamqp.disabledIOTA_HTTP_HOSThttp.hostIOTA_HTTP_PORThttp.portIOTA_HTTP_TIMEOUThttp.timeoutIOTA_HTTP_KEYhttp.keyIOTA_HTTP_CERThttp.cert (HTTP相关的环境变量将在即将推出的HTTP绑定中使用) IOTA_MQTT_CA、IOTA_MQTT_CERT、IOTA_MQTT_KEY环境变量应提供文件名,其内容将用于配置属性。 高性能配置 Node.js是单线程的并使用非阻塞I/O,允许它扩展到数万个并发操作。然而,Node.js有一些薄弱点和漏洞,可能会导致基于Node.js的系统在遇到快速流量增长时表现出性能不足。 此外,了解运行node.js服务器的环境很重要,因为它有限制。主机上有两种类型的限制:硬件和软件。硬件限制很容易发现。您的应用程序可能正在消耗所有内存,并需要使用磁盘继续工作。通过升级您的物理或虚拟主机来增加更多内存似乎是正确的选择。 此外,Node.js应用程序也有软件内存限制(由V8强加),因此在执行服务时我们不能忘记这些限制。在64位环境中,您的应用程序默认运行在1 GB的V8限制下。如果您的应用程序在高流量场景中运行,您将需要更高的限制。其他参数也是如此。 这意味着我们需要对node.js的执行和系统配置进行一些更改: Node.js标志 --use-idle-notification 关闭使用空闲通知以减少内存占用。 --expose-gc 使用expose-gc命令启用垃圾收集器的手动控制。在IoT代理的情况下,没有实现,因为需要在服务器代码中实现对垃圾收集器的调用,不过推荐的值是每30秒。 --max-old-space-size=xxxx 在这种情况下,我们希望增加每个V8节点进程的堆内存限制,以便使用最大容量而不是64位机器上的默认1.4Gb(32位机器上为512Mb)。建议至少使用物理或虚拟实例总内存的一半。 用户软件限制 Linux内核提供了一些关于系统相关限制和最大值的配置。在有多个用户的分布式环境中,通常需要控制每个用户可用的资源。然而,当只有一个可用用户但这个用户由于高性能应用程序需要大量资源时,默认限制不适当,需要更改以满足高性能要求。这些限制包括最大文件句柄计数、最大文件锁计数、最大进程计数等。 您可以通过执行命令查看系统的限制: bash ulimit -a 您可以在limits.conf文件中定义相应的限制。此配置文件语法的描述适用于/etc/security/limits.conf文件和/etc/security/limits.d目录中的*.conf文件。您可以在limits.con - linux手册页中获取有关limits.conf的更多信息。建议更改的值如下: core 核心文件大小的限制,以KB为单位,我们建议将硬类型和软类型都更改为无限。 * soft core unlimited * hard core unlimited data 最大数据大小,以KB为单位,我们建议将硬类型和软类型都更改为无限。 * soft data unlimited * hard data unlimited fsize 最大文件大小,以KB为单位,我们建议将硬类型和软类型都更改为无限。 * soft fsize unlimited * hard fsize unlimited memlock 最大锁定内存地址空间,以KB为单位,我们建议将硬类型和软类型都更改为无限。 * memlock unlimited * memlock unlimited nofile 最大打开文件描述符数量,我们建议将硬类型和软类型都更改为65535。 * soft nofile 65535 * hard nofile 65535 RSS 最大常驻集大小,以KB为单位(在Linux 2.4.30及更高版本中忽略),我们建议将硬类型和软类型都更改为无限。 * soft rss unlimited * hard rss unlimited stack 最大堆栈大小,以KB为单位,我们建议将硬类型和软类型都更改为无限。 * soft stack unlimited * hard stack unlimited nproc 最大进程数,我们建议将硬类型和软类型都更改为无限。 * soft nproc unlimited * hard nproc unlimited 您可以查看此文件夹中提供的limits.conf文件,了解所有提供的值。 配置内核参数 sysctl用于在运行时修改内核参数。我们计划修改相应的/etc/sysctl.conf文件。您可以在sysctl和sysctl.conf的相应手册页中获取更多信息。您可以使用命令sysctl -a搜索所有内核参数 fs.file-max 可分配的最大文件句柄数,推荐值为1000000。 fs.file-max = 1000000 fs.nr_open 可以打开的最大文件句柄数,推荐值为1000000。 fs.nr_open = 1000000 net.netfilter.nf_conntrack_max 连接跟踪表的大小。默认值是nf_conntrack_buckets值的4倍。 net.nf_conntrack_max = 1048576 有关任何其他内核参数的更多详细信息,请查看示例sysctl.conf文件。 打包 唯一允许的包类型是RPM。要执行打包脚本,系统中必须有RPM构建工具。 从项目的根文件夹创建RPM,使用以下命令: cd rpm ./create-rpm.sh -v <version-number> -r <release-number> 其中<version-number>是您希望包具有的版本(x.y.z),<release-number>是依赖于先前安装的递增数字。 --- ### 187. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTTnet 是一个高性能的MQTT类库,支持.NET Core和.NET Framework。 MQTTnet 原理 MQTTnet 是一个用于.NET的高性能MQTT类库,实现了MQTT协议的各个层级,包括连接、会话、发布/订阅、QoS(服务质量)等。其原理涉及以下关键概念 1、MqttClient: MqttClient 是MQTTnet库中表示客户端的主要类。它负责与MQTT服务器建立连接,并处理消息的发布和订阅。 2、MqttServer: MqttServer 则表示MQTT服务器,负责接受客户端的连接,管理连接状态,并转发消息到相应的订阅 3、消息处理: MQTT消息分为发布消息和订阅消息。发布消息由客户端发送到服务器,然后由服务器广播给所有订阅者。 4、QoS(服务质量): MQTT支持不同级别的服务质量,包括0、1和2。MQTTnet允许你根据需要选择适当的QoS级别。 5、异步通信: MQTTnet广泛使用异步编程模型,允许并发处理多个连接,提高性能。 MQTTnet 优点 1、高性能: MQTTnet被设计为高性能的MQTT库,适用于处理大量的消息和连接。 2、跨平台: 支持.NET Core和.NET Framework,使其可以在不同的操作系统上运行。 3、灵活性: 提供了许多配置选项,允许你根据应用程序的需求进行调整。 4、WebSocket支持: 支持通过WebSocket协议进行通信,适用于Web应用程序。 5、活跃社区: MQTTnet有一个活跃的社区,提供了文档、示例和支持。 使用方法(服务端、客户端、WEB端) 下面是一个简单的示例,演示如何在.NET Core中使用MQTTnet创建一个基本的MQTT服务端和客户端。请注意,这个示例只是为了演示基本概念,实际应用中可能需要更多的配置和错误处理。 服务端示例 using System; using MQTTnet; using MQTTnet.Server; class Program { static async System.Threading.Tasks.Task Main(string[] args) { // 创建服务端配置 var optionsBuilder = new MqttServerOptionsBuilder() .WithDefaultEndpointPort(1883) .WithConnectionValidator(c => { Console.WriteLine($"Client connected: {c.ClientId}"); // 可以在这里添加连接验证逻辑 }); // 创建MQTT服务器实例 var mqttServer = new MqttFactory().CreateMqttServer(); // 处理连接成功事件 mqttServer.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(e => { Console.WriteLine($"Client connected: {e.ClientId}"); }); // 处理连接断开事件 mqttServer.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(e => { Console.WriteLine($"Client disconnected: {e.ClientId}"); }); // 处理接收到消息事件 mqttServer.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(e => { Console.WriteLine($"Received message from client {e.ClientId}: {e.ApplicationMessage.Payload}"); }); // 启动MQTT服务器 await mqttServer.StartAsync(optionsBuilder.Build()); Console.WriteLine("MQTT Server已启动。按任意键退出。"); Console.ReadLine(); // 停止MQTT服务器 await mqttServer.StopAsync(); } } 客户端示例 using System; using System.Text; using System.Threading; using System.Threading.Tasks; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; class Program { static async Task Main(string[] args) { // 创建客户端配置 var options = new MqttClientOptionsBuilder() .WithTcpServer("localhost", 1883) .WithClientId("Client1") // 客户端ID .Build(); // 创建MQTT客户端实例 var mqttClient = new MqttFactory().CreateMqttClient(); // 处理连接成功事件 mqttClient.UseConnectedHandler(e => { Console.WriteLine("Connected to MQTT Broker"); }); // 处理连接断开事件 mqttClient.UseDisconnectedHandler(e => { Console.WriteLine("Disconnected from MQTT Broker"); }); // 处理接收到消息事件 mqttClient.UseApplicationMessageReceivedHandler(e => { Console.WriteLine($"Received message: {e.ApplicationMessage.Payload}"); }); // 连接到MQTT服务器 await mqttClient.ConnectAsync(options, CancellationToken.None); // 发布消息 var message = new MqttApplicationMessageBuilder() .WithTopic("topic/test") .WithPayload("Hello, MQTT!") .WithExactlyOnceQoS() .WithRetainFlag() .Build(); await mqttClient.PublishAsync(message, CancellationToken.None); Console.WriteLine("Message published. Press any key to exit."); Console.ReadLine(); // 断开与MQTT服务器的连接 await mqttClient.DisconnectAsync(); } } Web端示例 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://cdnjs.cloudflare.com/ajax/libs/mqtt/4.0.0/mqtt.min.js"></script> <title>MQTT Web Client</title> </head> <body> <h1>MQTT Web Client</h1> <script> // 连接到MQTT服务器 const client = mqtt.connect('mqtt://your-mqtt-broker-url'); // 当连接成功时的处理逻辑 client.on('connect', function () { console.log('Connected to MQTT Broker'); // 订阅主题 client.subscribe('topic/test', function (err) { if (!err) { console.log('Subscribed to topic/test'); } }); // 发布消息 client.publish('topic/test', 'Hello, MQTT!'); }); // 当接收到消息时的处理逻辑 client.on('message', function (topic, message) { console.log('Received message:', message.toString()); }); // 处理连接断开事件 client.on('close', function () { console.log('Connection closed'); }); // 处理错误事件 client.on('error', function (err) { console.error('Error:', err); }); </script> </body> </html> 总结 以上代码中对连接断开事件处理(UseDisconnectedHandler、Web端的close事件)和错误事件处理(Web端的error事件)。 这些事件处理可以根据实际需求进一步扩展。 --- ### 188. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网设备接入和通信示例介绍 本文介绍了如何使用阿里云物联网平台,通过设备端Link SDK来模拟物联网设备接入和实现上下行通信。以下是整个过程的概述和关键步骤总结: 前提条件 在物联网平台控制台创建产品和设备(如 device2)并获取设备证书信息(ProductKey、DeviceName 和 DeviceSecret)。 详细操作包括创建产品和创建设备。 背景信息 使用 WebSocket 方式接入设备。 在 Node.js 环境下配置和使用设备端 Link SDK。 操作步骤 安装 Node.js:在 Windows 或 Linux 系统下载并安装 Node.js。例如,在 Windows 10 上安装 node-v14.15.1-x64.msi。 验证安装:通过 node --version 命令在 CMD 窗口检查 Node.js 版本。 创建 JavaScript 文件:例如 iot_device.js,用于存放示例代码。 const iot = require('alibabacloud-iot-device-sdk'); // 设备证书信息。 const productKey = 'a1W***'; const deviceName = 'device2'; const deviceSecret = 'ff01e59d1a***'; // 新版公共实例和企业版实例,必须填写实例ID,旧版公实例无需填写。 const instanceId = ''; // 当前产品和设备所属地域的ID。 const region = 'cn-shanghai'; const brokerUrl = instanceId ? `wss://${instanceId}.mqtt.iothub.aliyuncs.com:443` : `wss://${productKey}.iot-as-mqtt.${region}.aliyuncs.com:443`; const device = iot.device({ productKey: `${productKey}`, deviceName: `${deviceName}`, deviceSecret: `${deviceSecret}`, brokerUrl, tls: true, }); // 监听connect事件:建立MQTT连接,订阅自定义Topic,通过自定义Topic向物联网平台发送消息。 device.on('connect', () => { device.subscribe(`/${productKey}/${deviceName}/user/get`); console.log('connect successfully!'); device.publish(`/${productKey}/${deviceName}/user/update`, 'hello world!'); }); // 监听message事件。 device.on('message', (topic, payload) => { console.log(topic, payload.toString()); }); // 监听error事件。 device.on('error', (error) => { console.error(error); }); // 如果您希望主动断开与物联网平台的连接,可以删除下一行注释符号,调用end函数断开与物联网平台的连接。 //device.end(); 您需参照下表,替换对应参数的值为实际场景中设备的信息。 参数示例说明productKeya1W***您添加设备后,保存的设备证书信息,请参见获取设备证书。您也可在控制台中设备device2的设备详情页面查看。deviceNamedevice2deviceSecretff01e59d1a***instanceId''实例ID。您可在物联网平台控制台的实例概览页面,查看当前实例的ID。若有ID值,必须传入该ID值。若无实例概览页面或ID值,传入空值,即iotInstanceId = ''。实例的详细说明,请参见实例概述。regioncn-shanghai您物联网平台设备所在地域的代码。地域代码表达方法,请参见地域列表。 打开CMD窗口,使用cd命令找到iot_device.js文件所在路径,在该路径下使用npm命令下载阿里云IoT的Link SDK库。下载后的库文件如下图所示。npm install alibabacloud-iot-device-sdk --save 在CMD窗口输入如下命令,运行iot_device.js代码,启动设备。node iot_device.js返回如下信息,表示设备接入成功,并成功发布消息。 查看运行日志和测试下行通信 登录物联网平台控制台。 在控制台左上方,选择物联网平台设备所在地域,然后在实例概览页面,单击目标实例。说明若无实例概览页面,会直接进入物联网平台功能页面。 在左侧导航栏,选择设备管理 > 设备。在设备列表页签,可查看设备device2的状态为在线。 单击设备device2对应操作栏的查看,在设备详情页面,单击日志服务,然后单击前往查看。在云端运行日志页签,查看日志消息。 在日志列表,找到设备到云消息,单击查看,查看设备上报到物联网平台的信息。 测试下行通信:从物联网平台向设备发送消息。 返回设备管理 > 设备页面,在设备列表页签,单击设备device2操作栏的查看。 在设备详情页面,单击Topic列表页签,找到已订阅的Topic:/a1W***/device2/user/get,单击发布消息。 输入消息内容,单击确认。 返回设备运行窗口,查看设备能接收消息,表示通信正常。您也可返回云端运行日志页签,查看详细的通信日志。 总结 此示例提供了一个实际的场景,展示了如何通过 Node.js 和阿里云物联网平台的设备端 Link SDK 实现物联网设备的接入和通信。整个过程包括从设置环境、编写和运行代码,到在物联网平台上进行设备管理和通信测试。这为开发者提供了一个指导性的例子,帮助他们快速入门物联网设备的接入和数据交互。 --- ### 189. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Async.MQTT5是一个基于Boost.Asio的C++20 MQTT客户端,专门为发布或接收与MQTT 5.0兼容的代理的消息而设计。这是一个全面实施MQTT 5.0协议标准的客户端,完全支持QoS 0、1和2级别的消息发布和接收。 Async.MQTT5 MQTT协议广泛用于现实世界的多种通信场景,主要作为IoT设备数据传输的可靠通信协议。虽然MQTT协议本身相对简单,但将其整合到应用程序中可能相当复杂,尤其是在断开/重连序列后消息重传的实现方面。 Async.MQTT5旨在为应用开发者提供一个非常简单的异步C++接口。内部客户端实现管理网络和MQTT协议细节。值得注意的是,客户端不暴露连接函数(或异步连接函数);相反,网络连接性、MQTT握手和消息重传都在客户端内部自动处理。 Async.MQTT5接口与Boost.Asio的异步模型无缝对接。客户端的异步函数与Boost.Asio支持的所有完成令牌兼容。 仓库地址:https://github.com/mireo/async-mqtt5 特点 Async.MQTT5是一个设计理念为用户只应专注于应用逻辑,而不是网络复杂性的库。该库试图通过以下一系列关键特性来提升开发体验: 完整的TCP、TLS/SSL和WebSocket支持 用户友好的简洁性:提供尽可能简单而不损功能的界面。 优先考虑效率:尽可能高效地利用网络和内存资源。 最小内存占用:确保在IoT设备典型的资源受限环境中优化性能。 自动重新连接:在断开连接的情况下自动尝试重新建立连接。 完全符合Boost.Asio规范:接口和实现策略基于Boost.Asio的基础。Boost.Asio和Boost.Beast的用户将不会在理解和整合Async.MQTT5时遇到问题。此外,Async.MQTT5与Boost.Asio生态系统中的任何其他库都能很好地整合。 自定义分配器:支持自定义分配器,允许对内存资源进行额外的灵活性和控制。Async.MQTT5将使用来自异步函数的处理器关联的分配器来创建库实现中所需的对象实例。 每项操作的取消:所有异步操作都支持Asio的每项操作取消。 完成令牌:所有异步函数都支持CompletionToken,允许使用回调、协程、futures等多种方式灵活使用。 完全实现MQTT 5.0规范 支持QoS 0、QoS 1和QoS 2 自定义认证:Async.MQTT5定义了一个接口,用于执行增强认证的自定义认证器。 高可用性:Async.MQTT5支持列出同一集群中多个客户端可以连接的代理。在与一个代理的连接失败时,客户端会切换到列表中的下一个。 离线缓冲:离线时,它会自动缓冲所有连接恢复时要发送的数据包。 使用该库 下载Boost,并将其添加到您的包含路径中。 如果使用SSL,请下载OpenSSL,链接库并将其添加到包含路径中。 另外,您可以将Async.MQTT5的包含文件夹添加到包含路径中。 您可以使用以下命令行在Linux上编译以下示例: $ clang++ -std=c++20 <source-cpp-file> -o example -I<path-to-boost> -Iinclude -pthread 使用和API 详细文档在这里。 以下示例演示了配置客户端并使用QoS 0发布“Hello World!”应用消息的简单场景。 #include <iostream> #include <boost/asio/io_context.hpp> #include <boost/asio/detached.hpp> #include <boost/asio/ip/tcp.hpp> #include <async_mqtt5.hpp> int main() { boost::asio::io_context ioc; using client_type = async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket>; client_type c(ioc, ""); c.credentials("<your-client-id>", "<client-username>", "<client-pwd>") .brokers("<your-mqtt-broker>", 1883) .run(); c.async_publish<async_mqtt5::qos_e::at_most_once>( "<topic>", "Hello world!", async_mqtt5::retain_e::no, async_mqtt5::publish_props {}, [&c](async_mqtt5::error_code ec) { std::cout << ec.message() << std::endl; c.async_disconnect(boost::asio::detached); // disconnect and close the client } ); ioc.run(); } 为什么选择它? 如果以下任何一种情况适用于您,则Async.MQTT5可能适合您: 您的应用程序使用Boost.Asio并需要集成MQTT客户端。 您需要异步访问MQTT代理。 您正在开发需要连接到MQTT代理的高级组件。 您需要一个可靠且有韧性的MQTT客户端,可以自动管理所有与网络相关的问题。 如果以下情况使用,则可能不适合您: 您仅需要同步访问MQTT代理。 您连接的MQTT代理不支持MQTT 5版本。 需求 Async.MQTT5是一个仅头文件的库。要使用Async.MQTT5,需要以下条件: C++20兼容的编译器 Boost 1.82或更高版本。除了Asio,我们还使用了Beast、Spirit等其他仅头文件的库。 OpenSSL。仅当您通过使用boost::asio::ssl::stream需要SSL连接时。 Async.MQTT5已在以下编译器上进行了测试: clang 14.0(Linux) MSVC 14.37 - Visual Studio 2022(Windows) 总结 Async.MQTT5是一个基于Boost.Asio的专业C++20 MQTT客户端,专为发布或接收与MQTT 5.0兼容代理的消息而设计。这个客户端提供了MQTT 5.0协议标准的全面实现,并全面支持QoS 0、1和2的消息发布和接收。 Async.MQTT5的目的是为应用开发者提供一个非常简单的异步C++接口,以简化MQTT协议的集成和使用。它自动处理网络连接、MQTT握手和消息重传,使用户可以专注于应用逻辑。 Async.MQTT5提供了包括TCP、TLS/SSL和WebSocket支持、最小内存占用、自动重新连接等特性,使其在IoT设备环境中表现出色。此外,它支持自定义分配器和每项操作的取消,使其在高度定制化的应用场景中也能灵活应用。 使用Async.MQTT5,您只需下载Boost和(如需SSL支持)OpenSSL,并将它们添加到包含路径中。它是一个头文件库,不需要额外的编译步骤。 Async.MQTT5适用于需要集成MQTT客户端的Boost.Asio应用程序,或那些需要稳定、自动管理网络问题的高级MQTT客户端的场景。然而,如果您只需要同步访问MQTT代理或使用的MQTT代理不支持MQTT 5版本,它可能不适合您。 最后,Async.MQTT5已经在Linux和Windows平台的最新编译器上进行了测试,保证了其广泛的兼容性和稳定性。 --- ### 190. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 架构 介绍 在本教程中,我们将学习创建物联网应用程序的数据流处理所需的内容。 在这个过程中,我们将了解物联网架构的特点,并了解如何利用MQTT代理、NiFi和InfluxDB等不同工具来构建高度可扩展的物联网应用程序的数据流处理。 物联网及其架构 首先,让我们学习一些基本概念,了解物联网应用程序的一般架构。 2.1. 什么是物联网? 物联网(IoT)广泛指的是物理对象的网络,称为“物”。例如,这些物可以包括从普通家用物品(如灯泡)到复杂的工业设备等任何物。通过这个网络,我们可以连接各种传感器和执行器以交换数据。 现在,我们可以在非常不同的环境中部署这些物 - 例如,环境可以是我们的家,也可以是一辆行驶中的货车。然而,我们不能对这些物将可以使用的电源和网络的质量进行任何假设。因此,这为物联网应用程序提出了独特的要求。 2.2. 物联网架构简介 典型的物联网架构通常分为四个不同的层次。让我们了解数据如何在这些层次之间流动: 首先,感知层主要由从环境中收集测量数据的传感器组成。然后,网络层帮助聚合原始数据并通过互联网进行传输。进一步,数据处理层会过滤原始数据并生成早期分析。最后,应用层使用强大的数据处理能力来执行更深入的数据分析和管理。 MQTT、NiFi和InfluxDB简介 现在,让我们来看看今天在物联网设置中广泛使用的一些产品。这些产品都提供了一些独特的特性,使它们适用于物联网应用程序的数据需求。 3.1. MQTT MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布-订阅网络协议。它现在是OASIS和ISO标准。IBM最初开发它用于在设备之间传输消息。MQTT适用于内存、网络带宽和电源供应有限的受限环境。 MQTT遵循客户端-服务器模型,不同组件可以充当客户端并通过TCP连接到服务器。我们将此服务器称为MQTT代理。客户端可以将消息发布到称为主题的地址。它们还可以订阅主题并接收发布到它的所有消息。 在典型的物联网设置中,传感器可以将测量数据(如温度)发布到MQTT代理,而上游数据处理系统可以订阅这些主题以接收数据: 正如我们所见,MQTT中的主题是分层的。系统可以通过使用通配符轻松订阅整个主题层次结构。 MQTT支持三个不同的服务质量(QoS)级别。它们分别是“至多传递一次”、“至少传递一次”和“确保仅传递一次”。QoS定义了客户端与服务器之间的协议级别。每个客户端可以选择适合其环境的服务级别。 客户端还可以在发布时请求代理保留消息。在某些设置中,MQTT代理可能需要从客户端那里进行用户名和密码验证以建立连接。此外,出于隐私考虑,TCP连接可能会使用SSL/TLS进行加密。 有几个MQTT代理实现和客户端库可供使用,例如HiveMQ、Mosquitto和Paho MQTT。在本教程中,我们将使用Mosquitto作为示例。Mosquitto是Eclipse基金会的一部分,我们可以轻松地将其安装在树莓派或Arduino等开发板上。 3.2. Apache NiFi Apache NiFi最初由美国国家安全局(NSA)开发,是一种自动化和数据流管理工具,基于基于流的编程模型,将应用程序定义为黑盒进程网络。 首先,让我们先了解一些基本概念。在NiFi中,系统中移动的对象称为FlowFile。FlowFile处理器实际上执行诸如路由、转换和调解FlowFiles等有用工作。FlowFile处理器通过连接与连接一起使用。 处理组是一种将组件组合在一起以组织NiFi数据流的机制。处理组可以通过输入端口接收数据并通过输出端口发送数据。远程处理组(RPG)提供了一种从远程NiFi实例发送数据或接收数据的机制。 现在,有了这些知识,让我们了解NiFi架构: NiFi是一个基于Java的程序,运行在JVM中的多个组件。Web服务器是托管命令和控制API的组件。流控制器是NiFi的核心组件,负责管理扩展何时接收资源以执行。扩展允许NiFi具有可扩展性,并支持与不同系统的集成。 NiFi通过FlowFile存储库跟踪FlowFile的状态。FlowFile的实际内容字节存储在内容存储库中。与FlowFile相关的可信事件数据存储在可信存储库中。 由于数据在源头的收集可能需要较小的占用空间和低资源消耗,NiFi有一个名为MiNiFi的子项目。MiNiFi提供了一种补充的数据收集方法,可以通过Site-to-Site(S2S)协议轻松集成到NiFi中。 此外,它通过MiNiFi命令和控制(C2)协议实现了对代理的集中管理。此外,它有助于建立数据溯源,生成完整的链式保管信息。 3.3. InfluxDB InfluxDB是由InfluxData开发的,使用Go编写的时序数据库。它专为快速和高可用性的时序数据存储和检索而设计。这在处理应用程序指标、物联网传感器数据和实时分析方面特别合适。 首先,InfluxDB中的数据是按时序组织的。时序可以包含零个或多个数据点。数据点代表具有四个组成部分的单个数据记录,包括测量、标签集、字段集和时间戳: 首先,时间戳显示与特定数据点关联的UTC日期和时间。字段集由一个或多个字段键和字段值对组成。它们捕获了点的实际数据,并附带标签。标签集也由标签键和标签值对组成,但它们是可选的。它们基本上充当点的元数据,并可用于加快查询响应。 测量充当标签集、字段集和时间戳的容器。此外,InfluxDB中的每个数据点都可以与其关联的保留策略。保留策略描述了InfluxDB将保留数据的时间以及通过复制将创建多少副本。 最后,数据库充当用户、保留策略、连续查询和时序数据的逻辑容器。我们可以将InfluxDB中的数据库理解为与传统关系数据库 loosly 相似。 此外,InfluxDB是InfluxData平台的一部分,提供了多种其他产品来高效处理时序数据。InfluxData现在将其作为InfluxDB OSS 2.0(开源平台)和InfluxDB Cloud(商业产品)提供: 除了InfluxDB之外,该平台还包括Chronograf,它为InfluxData平台提供了完整的界面。此外,它包括Telegraf,用于收集和报告度量和事件的代 理。最后,还有Kapacitor,一个实时流式数据处理引擎。 实践物联网数据管道 现在,我们已经掌握了足够的知识,可以将这些产品一起使用,为我们的物联网应用程序创建数据管道。在本教程中,我们假设我们正在从多个城市的多个观测站收集与空气质量相关的测量数据。例如,这些测量包括地面臭氧、一氧化碳、二氧化硫、二氧化氮和气溶胶等。 4.1. 基础设施设置 首先,我们假设每个城市的气象站都配备了所有感应设备。此外,这些传感器已连接到类似Raspberry Pi的开发板,用于收集模拟数据并将其数字化。该板通过无线连接发送原始测量数据: 物联网基础设施设置一个区域控制站收集来自城市中所有气象站的数据。我们可以汇总并将此数据提供给一些本地分析引擎,以获得更快的见解。来自所有区域控制中心的经过筛选的数据被发送到中央指挥中心,该中央指挥中心通常托管在云中。 4.2. 创建物联网架构 现在,我们准备为我们的简单空气质量应用程序设计物联网架构。在这里,我们将使用MQTT代理、MiNiFi Java代理、NiFi和InfluxDB: 正如我们所看到的,我们在气象站点使用了Mosquitto MQTT代理和MiNiFi Java代理。在区域控制中心,我们使用NiFi服务器来汇总和路由数据。最后,我们使用InfluxDB来存储中央指挥中心级别的测量数据。 4.3. 执行安装 在像Raspberry Pi这样的开发板上安装Mosquitto MQTT代理和MiNiFi Java代理非常容易。但是,对于本教程,我们将在本地计算机上安装它们。 Eclipse Mosquito的官方下载页面提供了多个平台的二进制文件。一旦安装完成,可以从安装目录轻松启动Mosquitto: net start mosquitto 此外,NiFi二进制文件也可以从其官方网站下载。我们必须在合适的目录中提取下载的存档。由于MiNiFi将使用站点到站点协议连接到NiFi,因此必须在/conf/nifi.properties中指定站点到站点输入套接字端口: # Site to Site properties nifi.remote.input.host= nifi.remote.input.secure=false nifi.remote.input.socket.port=1026 nifi.remote.input.http.enabled=true nifi.remote.input.http.transaction.ttl=30 sec 然后,我们可以启动NiFi: <NIFI_HOME>/bin/run-nifi.bat 同样,可以从官方网站下载Java或C++ MiNiFi代理和工具包二进制文件。同样,我们必须将存档提取到适当的目录中。 默认情况下,MiNiFi附带一组非常少的处理器。因为我们将从MQTT中获取数据,所以必须将MQTT处理器复制到/lib目录。这些处理器捆绑为NiFi Archive (NAR)文件,并位于/lib目录中: COPY <NIFI_HOME>/lib/nifi-mqtt-nar-x.x.x.nar <MINIFI_HOME>/lib/nifi-mqtt-nar-x.x.x.nar 然后,我们可以启动MiNiFi代理: <MINIFI_HOME>/bin/run-minifi.bat 最后,可以从其官方网站下载InfluxDB的开源版本。与以前一样,可以提取存档,并使用简单的命令启动InfluxDB: <INFLUXDB_HOME>/influxd.exe 对于本教程,我们应该保留所有其他配置,包括端口,以默认值。这完成了我们在本地计算机上的安装和设置。 4.4. 定义NiFi数据流 现在,我们已经准备好定义我们的数据流。NiFi提供了一个易于使用的界面,用于创建和监控数据流。这可通过URL http://localhost:8080/nifi 访问。 首先,我们将定义将在NiFi服务器上运行的主数据流: 如我们所见,我们定义了一个输入端口,该端口将从MiNiFi代理接收数据。它通过连接将数据发送到PutInfluxDB处理器,该处理器负责将数据存储在InfluxDB中。在此处理器的配置中,我们定义了InfluxDB的连接URL以及要发送数据的数据库名称。 4.5. 定义MiNiFi数据流 接下来,我们将定义在MiNiFi代理上运行的数据流。我们将使用NiFi的相同用户界面,并将数据流导出为模板,然后在MiNiFi代理中进行配置。让我们定义MiNiFi代理的数据流: 在这里,我们定义了ConsumeMQTT处理器,负责从MQTT代理获取数据。我们在属性中提供了代理URI以及主题过滤器。我们正在从层次结构"air-quality"下定义的所有主题中获取数据。 我们还定义了一个远程处理组,并将其连接到ConcumeMQTT处理器。远程处理组负责通过站点到站点协议将数据推送到NiFi。 我们可以将此数据流保存为模板,并将其下载为XML文件。让我们将此文件命名为config.xml。现在,我们可以使用转换工具包将此模板从XML转换为MiNiFi代理使用的YAML格式: <MINIFI_TOOLKIT_HOME>/bin/config.bat transform config.xml config.yml 这将生成config.yml文件,其中我们必须手动添加NiFi服务器的主机和端口: Input Ports: - id: 19442f9d-aead-3569-b94c-1ad397e8291c name: From MiNiFi comment: '' max concurrent tasks: 1 use compression: false Properties: # Deviates from spec and will later be removed when this is autonegotiated Port: 1026 Host Name: localhost 现在,我们可以将此文件放入/conf目录,替换可能已经存在的文件。之后,我们需要重新启动MiNiFi代理。 在这里,我们需要手动进行大量工作来创建数据流并在MiNiFi代理中进行配置。这在实际情况下是不切实际的,因为遥远的地点可能存在数百个代理。然而,正如我们之前所看到的,我们可以使用MiNiFi C2服务器来自动化此过程。但这超出了本教程的范围。 4.6. 测试数据管道 最后,我们准备测试我们的数据管道!由于我们无法使用真实传感器,我们将创建一个小型模拟。我们将使用一个小的Java程序生成传感器数据: class Sensor implements Callable<Boolean> { String city; String station; String pollutant; String topic; Sensor(String city, String station, String pollutant, String topic) { this.city = city; this.station = station; this.pollutant = pollutant; this.topic = topic; } @Override public Boolean call() throws Exception { MqttClient publisher = new MqttClient( "tcp://localhost:1883", UUID.randomUUID().toString()); MqttConnectOptions options = new MqttConnectOptions(); options.setAutomaticReconnect(true); options.setCleanSession(true); options.setConnectionTimeout(10); publisher.connect(options); IntStream.range(0, 10).forEach(i -> { String payload = String.format("%1$s,city=%2$s,station=%3$s value=%4$04.2f", pollutant, city, station, ThreadLocalRandom.current().nextDouble(0, 100)); MqttMessage message = new MqttMessage(payload.getBytes()); message.setQos(0); message.setRetained(true); try { publisher.publish(topic, message); Thread.sleep(1000); } catch (MqttException | InterruptedException e) { e.printStackTrace(); } }); return true; } } 在这里,我们使用Eclipse Paho Java客户端生成消息并发送到MQTT代理。我们可以添加尽可能多的传感器以创建我们的模拟: ExecutorService executorService = Executors.newCachedThreadPool(); List<Callable<Boolean>> sensors = Arrays.asList( new Simulation.Sensor("london", "central", "ozone", "air-quality/ozone"), new Simulation.Sensor("london", "central", "co", "air-quality/co"), new Simulation.Sensor("london", "central", "so2", "air-quality/so2"), new Simulation.Sensor("london", "central", "no2", "air-quality/no2"), new Simulation.Sensor("london", "central", "aerosols", "air-quality/aerosols")); List<Future<Boolean>> futures = executorService.invokeAll(sensors); 如果一切正常,我们将能够在InfluxDB数据库中查询我们的数据: 例如,我们可以查看属于“ozone”测量的所有数据点,这些数据存储在数据库“airquality”中。 结论 总之,本教程涵盖了一个基本的IoT用例。我们还了解了如何使用MQTT、NiFi和InfluxDB等工具来构建可扩展的数据管道。当然,这并不涵盖IoT应用程序的全部范围,扩展数据分析管道的可能性是无限的。 此外,本教程中选择的示例仅供演示目的。实际的IoT应用程序的基础架构和架构可以非常多样化和复杂。此外,我们可以通过将可操作的见解作为命令向后推送来完成反馈循环。 --- ### 191. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 介绍 正如我们可能已经知道的那样,Node.js是一个异步和事件驱动的JavaScript运行时和引擎,为今天存在的许多基于服务器端的、网络化的应用程序提供动力。在本文中,我们将探讨Node.js与MQTT的互动,MQTT是一种用于物联网(IoT)世界的发布/订阅(pub/sub)协议和标准。 在本文中,我们计划仅涵盖重要的公共MQTT API和函数,并探讨Node.js中的简单发布者和订阅者脚本。 什么是MQTT? 1999年,IBM的Andy Standford-Clark和Arlen Nipper设计了MQTT协议的最初版本。当时的目标是构建一个支持低带宽、轻量级且消耗最少资源的协议,因为通过卫星链路连接的设备非常昂贵。 该规范有两个版本:MQTT 3.1.1和MQTT 5.0.0。大多数商业MQTT代理现在支持MQTT 5,但许多IoT托管云服务仅支持MQTT 3.1.1,这曾经是最受欢迎和广泛支持的版本。 强烈建议新的IoT部署使用5.0.0版本(2018年批准),因为其新功能更侧重于强大的系统和云原生可伸缩性。您可以在MQTT的GitHub页面上阅读有关两个版本之间的亮点和详细差异的更多信息。 今天的用途 MQTT是一种轻量级的客户端-服务器协议,实现了发布/订阅消息传输模型,并已用于连接关键的IoT应用程序、机器对机器(M2M)通信和许多其他需要具有有限带宽但卓越性能的消息传输平滑界面的领域。这是其简单的设计、易用性和开放规范的结果。 自2014年以来,MQTT一直由OASIS技术指导委员会管理。该委员会负责维护、更新和维护该标准,包括组织用例文档和保护其知识产权。 它依赖于TCP/IP,这是一个可靠的、面向连接的低级网络堆栈,传输层独立于数据有效载荷结构,实现了一种有序和正确的双向主机对主机的通信模型。 发布/订阅模式还允许消息从一个应用程序分发到许多不同的应用程序。但在这种情况下,发布者和订户通常是独立的应用程序(解耦),只通过代理或服务器连接。例如,流行的发布/订阅消息平台RabbitMQ在内部使用了MQTT。 MQTT的用例 MQTT已经找到了许多用例,我们将在下面探讨其中一些。 启用消息广播:客户端可以发布消息或有效载荷到多个其他客户端应用程序,当然,这些应用程序需要通过代理事先通过主题订阅这些消息. 提供轻量级和最小的消息头/资源:这允许在消息传输中使用最小的带宽,因此MQTT可以有效地扩展以服务数百万个IoT设备 在其核心,它提供了可靠的消息传输或交付:大多数IoT设备都依赖于这一点,但从高层次上看,MQTT定义了保证消息传输得以处理的服务层 构建高度安全的消息传输应用程序:MQTT在这方面非常出色,因为消息有效载荷可以使用TLS和其他现代身份验证机制(如OAUTH)进行加密和安全保护 确保客户端应用程序具有持久连接:这对于网络连接可能不稳定的区域中的临时消息存储非常方便 相关的是,MQTT有助于减少在信号差的蜂窝网络上设备重新连接所需的时间 在不同行业和领域找到应用,包括汽车、石油和天然气、制造、物流、交通和智能家居设备行业 您可以在MQTT文档的用例页面上找到有关这些信息的更多详细信息。最受欢迎的开源家庭自动化项目之一,Home Assistant,基于MQTT协议。 MQTT的发布/订阅架构 MQTT协议包括代理(broker),它充当中央服务器,将发布者客户端的消息引导到订阅者客户端,以及一个或多个客户端应用程序,可以是消息或数据的订阅者或发布者。 代理可以看作是邮递员,确保消息被传递给其各自的接收者。它们应该被设计成高度可扩展和安全的,因为它们是MQTT客户端的中心关注点。 在高层次上,代理充当一个网关,将发布的消息从发布者应用程序路由到适当的订阅者。通常情况下,代理可以部署在多个集群或实例上,并置于负载均衡器后,以提高容错性。MQTT客户端将消息发布到中央代理(通常是到主题),其他客户端可以订阅代理上的相同主题以接收这些消息。 因此,一个客户端将消息发布到主题,而其他客户端订阅该主题,表示它们有兴趣接收相关消息。代理具有一种过滤机制,用于控制应该将消息发送给哪些订阅者。这意味着代理检查或筛选特定主题或主题组上的订阅者(或订阅者列表),然后将消息发送给它们。 总之,代理读取、确认和处理来自发布者客户端或应用程序的消息(包括确定主题的订阅者以及将所有适当的消息发送给它们)。 注意:MQTT依赖一种过滤消息的方式,代理将消息发送给对获取消息内容感兴趣的订阅者。消息通常包含一个主题,代理使用该主题来确定如何将特定消息路由到适当的订阅客户端。 基于主题的过滤涉及客户端(发布者和订阅者)通过主题与代理进行交互,主题是每个消息有效载荷的一部分。 到目前为止,我们已经使用了一些对一些读者可能听起来很新的技术术语。在下一节中,我们将探讨一些这些术语及其含义。 一些MQTT技术概念解释 桥接(Bridge) - 两个MQTT代理之间的连接 MQTT客户端(MQTT client) - 连接到经过安全网络连接的MQTT代理的设备或使用MQTT客户端库编写的应用程序;MQTT客户端可以是发布者或订阅者应用/客户端 消息(Message) - 简单地说,要发布的消息,可以是缓冲区(Buffer)、字符串(String)或JSON对象 主题(Topics) - 代理用于过滤并将适当的消息发送到连接的客户端的字符串标识符。主题名称通常以层次结构的方式进行构建,带有分隔符,称为主题级别 (注意,消息必须包含代理可以使用的主题,以适当地路由有效载荷到感兴趣的客户端) 示例主题名称:mytopic/homeautomation/closedoor 发布者(Publisher) - 发布者客户端将数据或消息分发到服务器/代理上的主题,供其他可能有兴趣获取这些消息的订阅者客户端使用 物联网(IoT) - 由嵌入式系统、自动化设备、无线网络和控制机制组成的连接设备的世界 解耦(Decoupling) - 在这种情况下,解耦意味着发布者/订阅者只需要知道代理的主机名/IP和端口 - 不像传统的客户端-服务器架构,其中客户端和服务器通过端点/API直接通信,通常以URI格式进行通信。 在应用级别使用MQTT 现在,让我们看看MQTT在应用级别是如何工作的。我们将使用MQTT的Node.js客户端库mqtt.js。 MQTT.js是MQTT协议的开源JavaScript库,适用于Node.js和浏览器。通常,该库可用于发布消息和订阅MQTT代理上的主题。 关于MQTT.js库的一些要点 支持ES模块和Common.js样式的文件导入 它具有基于Promise的API接口,因为MQTT本身是异步工作的 MQTT.js默认使用旧的MQTT v3.1.1,以支持旧代理,但当前的最新版本是5.0 MQTT客户端带有内置的错误处理程序,在程序员未能处理其代码中的错误时非常有用 请注意,还有可用于各种编程语言和主要操作系统(Linux、Windows和macOS)的客户端库。 连接/断开MQTT代理/服务器 客户端连接始终由代理/服务器处理,因为MQTT订阅者和发布者是独立的、解耦的应用程序。正如我们之前提到的,发布者和订阅者都是MQTT客户端,因此需要连接到同一个代理/服务器。 客户端永远不会直接连接到彼此;连接通常是在一个客户端和代理之间通过TCP/IP进行的。其他MQTT实现或变种也可以通过UDP连接(MQTT<-SN)。代理负责: 接收所有消息 通过确定哪个订阅客户端订阅每条消息来筛选适当的消息 保持客户端之间的连接/会话 对客户端进行身份验证和授权 将消息发送给正确的客户端 代理应该容易扩展并集成到不同的后端系统中。它们可以具有相当高的容错性,因为它们是发布者/订阅者通信的最关键点。 要首次连接到代理,客户端发送CONNECT消息。一旦启动,代理将返回一个CONNACK消息和一个状态代码。还需要注意的一点是,代理始终保持连接处于活动状态,除非客户端发送断开事件或其互联网连接中断。 目前有一些流行的免费托管的MQTT代理。Eclipse的Mosquitto就是其中之一,它可以运行在所有主要操作系统上。 还有其他商业云端或托管的代理,比如HIVEMQ。如果我们不打算安装和管理自己的代理,它们通常会非常方便。您可以在MQTT网站上找到用于快速测试的优秀MQTT代理。 安装我们的客户端库 要安装MQTT.js,请运行以下命令: npm install mqtt --save 请注意,MQTT.js捆绑了与代理进行交互的命令。要使MQTT协议接口可用于系统路径,我们可以全局安装它: npm install mqtt -g 安装完成后,我们的package.json文件应如下所示: // package.json { "name": "mqtt-demo", "version": "1.0.0", "description": "一个Node.js和MQTT演示", "main": "index.js", "scripts": { "start-publisher": "nodemon publisher.js", "start-consumer": "nodemon subscriber.js" }, "keywords": [ "Node.js", "MQTT", "Pub/Sub", "IoT", "message", "transport" ], "author": "Alexander Nnakwue", "license": "MIT", "dependencies": { "dotenv": "^10.0.0", "mqtt": "^4.3.2" }, "devDependencies": { "nodemon": "^2.0.15" } } 要测试程序,可以在一个终端窗口上运行发布者,然后在另一个终端窗口上运行订阅者。 创建一个MQTT发布客户端 现在,让我们创建一个发布消息的MQTT客户端。为此,我们可以导入MQTT.js库并使用connect方法。 const mqtt = require('mqtt'); require('dotenv').config(); const clientId = 'mqttjs_' + Math.random().toString(8).substr(2, 4); const client = mqtt.connect(process.env.BROKER_URL, { clientId: clientId }); 请注意,我们已经将BROKER_URL添加到我们的环境文件中。如我们所见,connect方法接受给定的URL(代理服务器URL)和可选的服务器选项对象。接受的协议可以是MQTT、ws、wss、tcp、tls等等。connect方法返回一个已连接的客户端。 为了在MQTT客户端连接中断时尝试重新连接,我们可以将reconnectPeriod选项(两次重新连接之间的时间间隔)设置为大于零。默认值为1秒,这意味着在断开连接后,它会几乎立即尝试重新打开连接。 const client = mqtt.connect(process.env.BROKER_URL, { clientId: clientId, clean: false, reconnectPeriod: 1 }); 如果将reconnectPeriod客户端选项的值设置为0,则将禁用重新连接,并在连接断开时终止。 当将resubscribe选项设置为其默认值(true)时,客户端可以在连接中断时自动重新连接和重新订阅先前订阅的主题。尤其是对于自托管的代理,我们可能需要使用用户名和密码进行身份验证。有关服务器选项对象的更多详细信息可以在MQTT GitHub上找到。 发布数据和消息 一旦连接到代理,MQTT客户端几乎可以立即发送消息。发布事件需要消息负载和主题名称,代理可以使用它来识别订阅方。此外,还有一个回调选项,用于检查错误或消息数据包是否已传输。 发送的消息类型或数据包具有以下属性: topicName dupFlag qos payload packetId或messageId retainFlag { cmd: 'publish', topic: 'test/connection', payload: '{"1":"Hello world","2":"Welcome to the test connection"}', qos: 1, retain: true, messageId: 12041, dup: false } 命令,如下所示。 当客户端向代理发送消息时,代理会根据开发人员设置的某些标准来处理消息。这应该包括QoS级别,它确定消息达到预期接收方的保证类型,并确保消息传递保证。 处理阶段通常涉及读取消息、确认消息和识别订阅主题的客户端。最后一步是将消息发送给订阅的客户端。 以下是publisher.js文件的完整代码,包括一些公共方法/API: //publisher.js const mqtt = require('mqtt') require('dotenv').config() //the client id is used by the MQTT broker to keep track of clients and and their // state const clientId = 'mqttjs_' + Math.random().toString(8).substr(2, 4) const client = mqtt.connect(process.env.BROKER_URL, {clientId: clientId, clean: false}); // console.log(process.env.BROKER_URL, 'client', clientId) const topicName = 'test/connection' client.on("connect",function(connack){ console.log("client connected", connack); // on client connection publish messages to the topic on the server/broker const payload = {1: "Hello world", 2: "Welcome to the test connection"} client.publish(topicName, JSON.stringify(payload), {qos: 1, retain: true}, (PacketCallback, err) =&gt; { if(err) { console.log(err, 'MQTT publish packet') } }) //assuming messages comes in every 3 seconds to our server and we need to publish or process these messages setInterval(() =&gt; console.log("Message published"), 3000); }) client.on("error", function(err) { console.log("Error: " + err) if(err.code == "ENOTFOUND") { console.log("Network error, make sure you have an active internet connection") } }) client.on("close", function() { console.log("Connection closed by client") }) client.on("reconnect", function() { console.log("Client trying a reconnection") }) client.on("offline", function() { console.log("Client is currently offline") }) 接下来,我们可以继续实现订阅客户端,该客户端会接收主题上的消息。 订阅消息为了接收我们感兴趣的主题的消息,客户端通过subscribe事件向代理发送订阅请求。所订阅的消息通常包含消息数据包负载,如下所示。 //stdout Packet { cmd: 'publish', retain: true, qos: 0, dup: false, length: 73, topic: 'test/connection', payload: &lt;Buffer 7b 22 31 22 3a 22 48 65 6c 6c 6f 20 77 6f 72 6c 64 22 2c 22 32 22 3a 22 57 65 6c 63 6f 6d 65 20 74 6f 20 74 68 65 20 74 65 73 74 20 63 6f 6e 6e 65 63 ... 6 more bytes&gt; } {"1":"Hello world","2":"Welcome to the test connection"}``` // [ { topic: 'test/connection', qos: 0 } ] granted 与其将主题名称作为常规的分隔字符串,我们还可以将主题存储为通配符,以便订户可以轻松订阅主题模式,而不是一次订阅一个主题。发布者和订阅者客户端需要提前了解主题模式的主题名称。 需要注意的是,订阅客户端需要提前了解他们将要接收的数据的结构,以便能够正确地处理数据。发布者以特定格式将消息发送到代理的特定主题,并接收该消息的预定订户需要知道数据的结构,以便能够在不破坏应用程序的情况下正确处理它。 订户客户端的完整代码如下所示。 // subscriber.js const mqtt = require('mqtt') const client = mqtt.connect("mqtt://test.mosquitto.org") const topicName = 'test/connection' // connect to same client and subscribe to same topic name client.on('connect', () =&gt; { // can also accept objects in the form {'topic': qos} client.subscribe(topicName, (err, granted) =&gt; { if(err) { console.log(err, 'err'); } console.log(granted, 'granted') }) }) // on receive message event, log the message to the console client.on('message', (topic, message, packet) =&gt; { console.log(packet, packet.payload.toString()); if(topic === topicName) { console.log(JSON.parse(message)); } }) client.on("packetsend", (packet) =&gt; { console.log(packet, 'packet2'); }) MQTT的其他功能 以下是MQTT的一些特点。 保留的消息 保留的消息是一个设置为true的MQTT消息,其保留标志/选项设置为true。默认情况下,当代理/服务器接收到没有订户的主题的消息时,消息会被丢弃。但是,MQTT有一种通过设置标志来保留这些消息的机制,该标志告诉发布者保留消息。请注意,代理每个主题只存储一个保留的消息。 广泛的身份验证和数据安全支持 MQTT支持各种身份验证方法和数据安全机制,包括TLS和OAuth,通常在MQTT代理上配置。因此, 这意味着实施这些服务器的客户端需要遵守所定义的机制。 默认情况下,MQTT支持重新连接机制,可以在网络连接质量低的区域建立持久连接。这对于存储消息非常重要,但与传统队列系统不同,代理不仅仅存储消息。MQTT通过确保客户端会话持久存在并且QoS级别大于0来存储消息。 服务质量(QoS) 为了处理发布/订阅系统中的典型挑战,MQTT实现了三个服务质量(QoS)级别。这三个级别包括0、1和2,它们确定消息达到预期接收方(客户端或代理)的保证类型。 为支持可靠的消息传递,该协议支持三种不同类型的服务质量消息: 0 – 至多一次 1 – 至少一次 2 – 正好一次 为存储消息,客户端必须订阅QoS大于0的主题。 数据不可知 MQTT是数据不可知的,客户端的用例确定了数据的结构方式。因此,可以发送任何类型的消息,包括图像、编码文本、加密数据等。 注意:默认的未加密MQTT端口是1883。还支持加密的TCP/IP端口8883,用于使用SSL的MQTT。 结论 MQTT提供了适用于网络带宽有限的领域的双向发布/订阅消息模型。服务独立于我们的主要应用程序,因为它们是解耦的,可以单独扩展代理或服务器。 --- ### 192. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 SMQTT 是一款高性能、开源的 MQTT 服务器,旨在提供支持单机、容器化和集群部署的 MQTT 服务,具备低延迟和高吞吐量,支持数百万 TCP 连接。本文将向您介绍 SMQTT 的主要功能、优势以及适用场景。 WIKI: https://wiki.smqtt.cc/ gitee: https://gitee.com/quickmsg 为什么选择 MQTT? MQTT 是一种轻量级的消息传递协议,采用发布/订阅模型,非常适用于物联网消息传递,如传感器、手机、嵌入式设备等。其低开销和高效性使其成为 IoT 设备之间进行可靠消息传递的理想选择。 优势 SMQTT 具有以下显著优势: 标准 MQTT 协议支持: SMQTT 实现了 MQTT 协议的标准版本,包括 3.1 和 3.1.1,确保了与各种 MQTT 客户端的兼容性。 高并发支持: SMQTT 可应对高并发场景,而且支持集群化部署,使其适用于大规模部署。 高性能和高吞吐量: SMQTT 是基于 Reactor-Netty(Spring WebFlux 的底层依赖)开发的,底层采用 Reactor3 反应堆模型,具备卓越的性能和高吞吐量。此外,它还利用 Netty 提供原生性能优势。 功能 SMQTT 具备多种功能,包括但不限于: 标准协议功能: 支持 MQTT 协议的标准功能,包括发布/订阅、QoS 等。 数据持久化: SMQTT 支持将消息数据持久化存储,以确保数据安全和可靠性。您可以选择默认内存存储或持久化存储到 Redis 或数据库。 规则引擎: 支持规则引擎,可以用于消息处理和转发。 集群化功能: SMQTT 提供集群支持,使用 Gossip 协议实现集群通信,确保高可用性。 管理监控页面: 提供管理后台,用于管理和监控 MQTT 服务器,同时支持 Grafana 监控集成,以实现性能监控。 ACL 权限管理: 支持对设备和资源的访问授权,确保数据安全性。 认证模块: 提供多种认证方式,包括 HTTP、匿名、固定密码和 SQL 认证。 拦截器: 支持自定义消息拦截器,用于处理消息。 容器化支持: 支持容器化部署,方便集成到现有容器化环境中。 总结 SMQTT 的启动和管理非常简单,支持 Spring Boot Starter,可以轻松地将其集成到 Spring Boot 项目中。此外,您可以访问管理后台以监控和管理 MQTT 服务器。 如果您正在寻找一款高性能、开源的 MQTT 服务器,SMQTT 可能是您的理想选择。它支持各种协议、高并发场景和集群化部署,具备优秀的性能和可扩展性,适用于各种 IoT 和通信需求。 启动方式 main方式启动 <!--smqtt依赖 --> <dependency> <groupId>io.github.quickmsg</groupId> <artifactId>smqtt-core</artifactId> <version>${Latest version}</version> </dependency> <!--集群依赖 --> <dependency> <artifactId>smqtt-registry-scube</artifactId> <groupId>io.github.quickmsg</groupId> <version>${Latest version}</version> </dependency> <!--管理ui依赖 --> <dependency> <artifactId>smqtt-ui</artifactId> <groupId>io.github.quickmsg</groupId> <version>${Latest version}</version> </dependency> 阻塞式启动服务: Bootstrap.builder() .rootLevel(Level.INFO) .websocketConfig( BootstrapConfig.WebsocketConfig .builder() .enable(false) .path("/mqtt") .port(8888) .build() ) .tcpConfig( BootstrapConfig .TcpConfig .builder() .port(1883) .ssl(SslContext.builder().enable(false).build()) .build()) .httpConfig( BootstrapConfig .HttpConfig .builder() .enable(false) .accessLog(true) .admin(BootstrapConfig.HttpAdmin.builder().enable(true).username("smqtt").password("smqtt").build()) .build()) .clusterConfig( BootstrapConfig. ClusterConfig .builder() .enable(false) .namespace("smqtt") .node("node-1") .port(7773) .url("127.0.0.1:7771,127.0.0.1:7772"). build()) .build() .startAwait(); 非阻塞式启动服务: Bootstrap bootstrap = Bootstrap.builder() .rootLevel(Level.INFO) .websocketConfig( BootstrapConfig.WebsocketConfig .builder() .enable(false) .path("/mqtt") .port(8888) .build() ) .tcpConfig( BootstrapConfig .TcpConfig .builder() .port(1883) .ssl(SslContext.builder().enable(false).build()) .build()) .httpConfig( BootstrapConfig .HttpConfig .builder() .enable(false) .accessLog(true) .admin(BootstrapConfig.HttpAdmin.builder().enable(true).username("smqtt").password("smqtt").build()) .build()) .clusterConfig( BootstrapConfig. ClusterConfig .builder() .enable(false) .namespace("smqtt") .node("node-1") .port(7773) .url("127.0.0.1:7771,127.0.0.1:7772"). build()) .build() .start().block(); jar方式 1.下载源码 mvn compile package -Dmaven.test.skip=true -P jar,web 在smqtt-bootstrap/target目录下生成jar 2.准备配置文件 config.yaml config.yaml java -jar smqtt-bootstrap-1.0.1-SNAPSHOT.jar <config.yaml路径> docker 方式 拉取镜像 # 拉取docker镜像地址 docker pull 1ssqq1lxr/smqtt:latest 启动镜像默认配置 # 启动服务 docker run -it -p 1883:1883 1ssqq1lxr/smqtt 启动镜像使用自定义配置(同上准备配置文件config.yaml) # 启动服务 docker run -it -v <配置文件路径目录>:/conf -p 1883:1883 -p 1999:1999 1ssqq1lxr/smqtt springboot方式 引入依赖 <dependency> <groupId>io.github.quickmsg</groupId> <artifactId>smqtt-spring-boot-starter</artifactId> <version>${Latest version >= 1.0.8}</version> </dependency> 启动类Application上添加注解 @EnableMqttServer 配置application.yml文件properties也支持,但是需要自己转换,没有提供demo文件config.yaml 启动springboot服务服务即可 如果引入的是spring-boot-starter-parent的管理包,如果启动报错,则需要添加以下依赖 <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.4.9</version> </dependency> <dependency> <groupId>io.projectreactor.netty</groupId> <artifactId>reactor-netty</artifactId> <version>1.0.10</version> </dependency> --- ### 193. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Mica-MQTT 是一款强大的 MQTT(Message Queuing Telemetry Transport)物联网组件,旨在提供出色的性能和灵活性。它适用于各种使用场景,包括物联网、消息通信、即时通讯(IM)和消息推送。本文将向您介绍 Mica-MQTT 的主要功能、优势以及使用场景。 使用场景 Mica-MQTT 可以用于多种用途,包括但不限于: 物联网(云端 MQTT Broker): 用于支持大规模物联网设备的通信和数据传输。 物联网(边缘端消息通信): 适用于连接边缘设备的消息传递,支持低延迟通信。 群组类 IM: 用于构建即时通讯应用,支持群组聊天和私聊。 消息推送: 用于实现消息推送服务,将消息快速可靠地传递给接收者。 简单易用的 MQTT 客户端: Mica-MQTT 提供了 MQTT 客户端,使开发者可以轻松与 MQTT 代理进行通信。 优势 Mica-MQTT 具有以下显著优势: 灵活而强大: Mica-MQTT 提供了丰富的功能集,同时保持了灵活性,可以根据需要进行二次开发或扩展。 支持 MQTT 协议: 支持 MQTT v3.1、v3.1.1 以及 v5.0 协议,满足不同 MQTT 版本的需求。 WebSocket 支持: 支持 MQTT 子协议的 WebSocket 连接,允许浏览器和其他应用使用 MQTT 协议进行通信。 HTTP REST API: 提供 HTTP REST API,使您可以使用 HTTP 请求进行通信。具体的 API 文档详见官方文档。 集群支持: Mica-MQTT 支持 MQTT 客户端和服务器的共享订阅,采用高效的 topic 树存储方式,能够处理百万级别的 topic,保持高性能。 遗嘱消息和保留消息: 支持 MQTT 遗嘱消息和保留消息,确保消息的可靠性和持久性。 Spring Boot 集成: 提供 Spring Boot 项目的快速接入,使集成更加简单。 监控支持: 支持与 Prometheus 和 Grafana 集成,实现监控和性能优化。 GraalVM 支持: 您可以使用 GraalVM 将 Mica-MQTT 编译成本机可执行程序,以获得更好的性能。 默认端口 Mica-MQTT 使用以下默认端口: 1883 端口:用于 MQTT TCP 通信。 8083 端口:用于 HTTP、WebSocket 以及 MQTT 子协议通信。 您可以在 演示地址 上查看 Mica-MQTT 的演示,使用账号 mica 和密码 mica 登录以了解更多。 总结 Mica-MQTT 是一款功能丰富、性能出色的 MQTT 物联网组件,适用于各种 IoT 和通信需求。如果您正在寻找可靠的 MQTT 解决方案,Mica-MQTT 可能是您的理想之选。 Spring boot 项目 客户端: 一、添加依赖 <dependency> <groupId>net.dreamlu</groupId> <artifactId>mica-mqtt-client-spring-boot-starter</artifactId> <version>${最新版本}</version> </dependency> 二、mqtt 客户端 2.1 配置项示例 mqtt: client: enabled: true # 是否开启客户端,默认:true ip: 127.0.0.1 # 连接的服务端 ip ,默认:127.0.0.1 port: 1883 # 端口:默认:1883 name: Mica-Mqtt-Client # 名称,默认:Mica-Mqtt-Client clientId: 000001 # 客户端Id(非常重要,一般为设备 sn,不可重复) user-name: mica # 认证的用户名 password: 123456 # 认证的密码 timeout: 5 # 超时时间,单位:秒,默认:5秒 reconnect: true # 是否重连,默认:true re-interval: 5000 # 重连时间,默认 5000 毫秒 version: mqtt_3_1_1 # mqtt 协议版本,可选 MQTT_3_1、mqtt_3_1_1、mqtt_5,默认:mqtt_3_1_1 read-buffer-size: 8KB # 接收数据的 buffer size,默认:8k max-bytes-in-message: 10MB # 消息解析最大 bytes 长度,默认:10M buffer-allocator: heap # 堆内存和堆外内存,默认:堆内存 keep-alive-secs: 60 # keep-alive 时间,单位:秒 clean-session: true # mqtt clean session,默认:true ssl: enabled: false # 是否开启 ssl 认证,2.1.0 开始支持双向认证 keystore-path: # 可选参数:ssl 双向认证 keystore 目录,支持 classpath:/ 路径。 keystore-pass: # 可选参数:ssl 双向认证 keystore 密码 truststore-path: # 可选参数:ssl 双向认证 truststore 目录,支持 classpath:/ 路径。 truststore-pass: # 可选参数:ssl 双向认证 truststore 密码 注意:ssl 存在三种情况 服务端开启ssl客户端ClientAuth 为 NONE(不需要客户端验证)仅仅需要开启 ssl 即可不用配置证书ClientAuth 为 OPTIONAL(与客户端协商)需开启 ssl 并且配置 truststore 证书ClientAuth 为 REQUIRE (必须的客户端验证)需开启 ssl 并且配置 truststore、 keystore证书 2.2 可实现接口(注册成 Spring Bean 即可) 接口是否必须说明IMqttClientConnectListener否客户端连接成功监听 2.3 客户端上下线监听 使用 Spring event 解耦客户端上下线监听,注意: 1.3.4 开始支持。会跟自定义的 IMqttClientConnectListener 实现冲突,取一即可。 /** * 示例:客户端连接状态监听 * * @author L.cm */ @Service public class MqttClientConnectListener { private static final Logger logger = LoggerFactory.getLogger(MqttClientConnectListener.class); @Autowired private MqttClientCreator mqttClientCreator; @EventListener public void onConnected(MqttConnectedEvent event) { logger.info("MqttConnectedEvent:{}", event); } @EventListener public void onDisconnect(MqttDisconnectEvent event) { // 离线时更新重连时的密码,适用于类似阿里云 mqtt clientId 连接带时间戳的方式 logger.info("MqttDisconnectEvent:{}", event); // 在断线时更新 clientId、username、password mqttClientCreator.clientId("newClient" + System.currentTimeMillis()) .username("newUserName") .password("newPassword"); } } 2.4 自定义 java 配置(可选) @Configuration(proxyBeanMethods = false) public class MqttClientCustomizerConfiguration { @Bean public MqttClientCustomizer mqttClientCustomizer() { return new MqttClientCustomizer() { @Override public void customize(MqttClientCreator creator) { // 此处可自定义配置 creator,会覆盖 yml 中的配置 System.out.println("----------------MqttServerCustomizer-----------------"); } }; } } 2.5 订阅示例 @Service public class MqttClientSubscribeListener { private static final Logger logger = LoggerFactory.getLogger(MqttClientSubscribeListener.class); @MqttClientSubscribe("/test/#") public void subQos0(String topic, byte[] payload) { logger.info("topic:{} payload:{}", topic, new String(payload, StandardCharsets.UTF_8)); } @MqttClientSubscribe(value = "/qos1/#", qos = MqttQoS.AT_LEAST_ONCE) public void subQos1(String topic, byte[] payload) { logger.info("topic:{} payload:{}", topic, new String(payload, StandardCharsets.UTF_8)); } @MqttClientSubscribe("/sys/${productKey}/${deviceName}/thing/sub/register") public void thingSubRegister(String topic, byte[] payload) { // 1.3.8 开始支持,@MqttClientSubscribe 注解支持 ${} 变量替换,会默认替换成 + // 注意:mica-mqtt 会先从 Spring boot 配置中替换参数 ${},如果存在配置会优先被替换。 logger.info("topic:{} payload:{}", topic, new String(payload, StandardCharsets.UTF_8)); } } 2.6 共享订阅 topic 说明 mica-mqtt 支持两种共享订阅方式: 共享订阅:订阅前缀 $queue/,多个客户端订阅了 $queue/topic,发布者发布到 topic,则只有一个客户端会接收到消息。 分组订阅:订阅前缀 $share/<group>/,组客户端订阅了 $share/group1/topic、$share/group2/topic..,发布者发布到 topic,则消息会发布到每个 group 中,但是每个 group 中只有一个客户端会接收到消息。 注意: 如果发布的 topic 以 / 开头,例如:/topic/test,需要订阅 $share/group1//topic/test,另外 mica-mqtt 默认随机消息路由,共享订阅的多个客户端会随机收到消息。 2.7 MqttClientTemplate 使用示例 import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; /** * @author wsq */ @Service public class MainService { private static final Logger logger = LoggerFactory.getLogger(MainService.class); @Autowired private MqttClientTemplate client; public boolean publish() { client.publish("/test/client", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); return true; } public boolean sub() { client.subQos0("/test/#", (context, topic, message, payload) -> { logger.info(topic + '\t' + new String(payload, StandardCharsets.UTF_8)); }); return true; } } 服务端 一、添加依赖 <dependency> <groupId>net.dreamlu</groupId> <artifactId>mica-mqtt-server-spring-boot-starter</artifactId> <version>${最新版本}</version> </dependency> 二、mqtt 服务 2.1 配置项 mqtt: server: enabled: true # 是否开启服务端,默认:true # ip: 0.0.0.0 # 服务端 ip 默认为空,0.0.0.0,建议不要设置 port: 1883 # 端口,默认:1883 name: Mica-Mqtt-Server # 名称,默认:Mica-Mqtt-Server buffer-allocator: HEAP # 堆内存和堆外内存,默认:堆内存 heartbeat-timeout: 120000 # 心跳超时,单位毫秒,默认: 1000 * 120 read-buffer-size: 8KB # 接收数据的 buffer size,默认:8k max-bytes-in-message: 10MB # 消息解析最大 bytes 长度,默认:10M auth: enable: false # 是否开启 mqtt 认证 username: mica # mqtt 认证用户名 password: mica # mqtt 认证密码 debug: true # 如果开启 prometheus 指标收集建议关闭 stat-enable: true # 开启指标收集,debug 和 prometheus 开启时需要打开,默认开启,关闭节省内存 web-port: 8083 # http、websocket 端口,默认:8083 websocket-enable: true # 是否开启 websocket,默认: true http-enable: false # 是否开启 http api,默认: false http-basic-auth: enable: false # 是否开启 http basic auth,默认: false username: mica # http basic auth 用户名 password: mica # http basic auth 密码 ssl: # mqtt tcp ssl 认证 enabled: false # 是否开启 ssl 认证,2.1.0 开始支持双向认证 keystore-path: # 必须参数:ssl keystore 目录,支持 classpath:/ 路径。 keystore-pass: # 必选参数:ssl keystore 密码 truststore-path: # 可选参数:ssl 双向认证 truststore 目录,支持 classpath:/ 路径。 truststore-pass: # 可选参数:ssl 双向认证 truststore 密码 client-auth: none # 是否需要客户端认证(双向认证),默认:NONE(不需要) 注意:ssl 存在三种情况 服务端开启ssl客户端ClientAuth 为 NONE(不需要客户端验证)仅仅需要开启 ssl 即可不用配置证书ClientAuth 为 OPTIONAL(与客户端协商)需开启 ssl 并且配置 truststore 证书ClientAuth 为 REQUIRE (必须的客户端验证)需开启 ssl 并且配置 truststore、 keystore证书 2.2 可实现接口(注册成 Spring Bean 即可) 接口是否必须说明IMqttServerUniqueIdService否用于 clientId 不唯一时,自定义实现唯一标识,后续接口使用它替代 clientIdIMqttServerAuthHandler是用于服务端认证IMqttServerSubscribeValidator否(建议实现)1.1.3 新增,用于对客户端订阅校验IMqttServerPublishPermission否(建议实现)1.2.2 新增,用于对客户端发布权限校验IMqttMessageListener否(1.3.x为否)消息监听IMqttConnectStatusListener是连接状态监听IMqttSessionManager否session 管理IMqttSessionListener否session 监听IMqttMessageStore集群是,单机否遗嘱和保留消息存储AbstractMqttMessageDispatcher集群是,单机否消息转发,(遗嘱、保留消息转发)IpStatListener否t-io ip 状态监听IMqttMessageInterceptor否消息拦截器,1.3.9 新增 2.3 IMqttMessageListener (用于监听客户端上传的消息) 使用示例 @Service public class MqttServerMessageListener implements IMqttMessageListener { private static final Logger logger = LoggerFactory.getLogger(MqttServerMessageListener.class); @Override public void onMessage(ChannelContext context, String clientId, Message message) { logger.info("clientId:{} message:{} payload:{}", clientId, message, new String(message.getPayload(), StandardCharsets.UTF_8)); } } 2.4 自定义配置(可选) @Configuration(proxyBeanMethods = false) public class MqttServerCustomizerConfiguration { @Bean public MqttServerCustomizer mqttServerCustomizer() { return new MqttServerCustomizer() { @Override public void customize(MqttServerCreator creator) { // 此处可自定义配置 creator,会覆盖 yml 中的配置 System.out.println("----------------MqttServerCustomizer-----------------"); } }; } } 2.5 MqttServerTemplate 使用示例 import net.dreamlu.iot.mqtt.spring.server.MqttServerTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.ByteBuffer; /** * @author wsq */ @Service public class ServerService { @Autowired private MqttServerTemplate server; public boolean publish(String body) { server.publishAll("/test/123", body.getBytes(StandardCharsets.UTF_8)); return true; } } 2.6 客户端上下线监听 使用 Spring event 解耦客户端上下线监听,注意: 1.3.4 开始支持。会跟自定义的 IMqttConnectStatusListener 实现冲突,取一即可。 @Service public class MqttConnectStatusListener { private static final Logger logger = LoggerFactory.getLogger(MqttConnectStatusListener.class); @EventListener public void online(MqttClientOnlineEvent event) { logger.info("MqttClientOnlineEvent:{}", event); } @EventListener public void offline(MqttClientOfflineEvent event) { logger.info("MqttClientOfflineEvent:{}", event); } } 2.7 基于 mq 消息广播集群处理 详见: mica-mqtt-broker 2.8 Prometheus + Grafana 监控对接 <!-- 开启 prometheus 指标收集 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> 支持得指标说明mqtt_connections_accepted共接受过连接数mqtt_connections_closed关闭过的连接数mqtt_connections_size当前连接数mqtt_messages_handled_packets已处理消息数mqtt_messages_handled_bytes已处理消息字节数mqtt_messages_received_packets已接收消息数mqtt_messages_received_bytes已处理消息字节数mqtt_messages_send_packets已发送消息数mqtt_messages_send_bytes已发送消息字节数 非 Spring boot 项目 客户端 topic 通配符含义 /:用来表示层次,比如 a/b,a/b/c。 #:表示匹配 >=0 个层次,比如 a/# 就匹配 a/,a/b,a/b/c。单独的一个 # 表示匹配所有。不允许 a# 和 a/#/c。 +:表示匹配一个层次,例如 a/+ 匹配 a/b,a/c,不匹配 a/b/c。单独的一个 + 是允许的,a+ 不允许,也可以和多层通配符一起使用,+/tennis/# 、sport/+/player1 都有有效的。 使用说明 MQTT 遗嘱消息场景 当客户端断开连接时,发送给相关的订阅者的遗嘱消息。在设备 A 进行连接时候,遗嘱消息设定为 offline,手机App B 订阅这个遗嘱主题。 当 A 异常断开时,手机App B 会收到这个 offline 的遗嘱消息,从而知道设备 A 离线了。 MQTT 保留消息场景 例如,某设备定期发布自身 GPS 坐标,但对于订阅者而言,从它发起订阅到第一次收到数据可能需要几秒钟,也可能需要十几分钟甚至更多,这样并不友好。因此 MQTT 引入了保留消息。 而每当有订阅者建立订阅时,服务端就会查找是否存在匹配该订阅的保留消息,如果保留消息存在,就会立即转发给订阅者。 借助保留消息,新的订阅者能够立即获取最近的状态。 共享订阅 mica-mqtt 支持两种共享订阅方式: 共享订阅:订阅前缀 $queue/,多个客户端订阅了 $queue/topic,发布者发布到 topic,则只有一个客户端会接收到消息。 分组订阅:订阅前缀 $share/<group>/,组客户端订阅了 $share/group1/topic、$share/group2/topic..,发布者发布到 topic,则消息会发布到每个 group 中,但是每个 group 中只有一个客户端会接收到消息。 注意: 如果发布的 topic 以 / 开头,例如:/topic/test,需要订阅 $share/group1//topic/test,另外 mica-mqtt 默认随机消息路由,共享订阅的多个客户端会随机收到消息。 客户端使用 // 初始化 mqtt 客户端 MqttClient client = MqttClient.create() .ip("127.0.0.1") // mqtt 服务端 ip 地址 .port(1883) // 默认:1883 .username("admin") // 账号 .password("123456") // 密码 .version(MqttVersion.MQTT_5) // 默认:3_1_1 .clientId("xxxxxx") // 非常重要务必手动设置,一般设备 sn 号,默认:MICA-MQTT- 前缀和 36进制的纳秒数 .bufferAllocator(ByteBufferAllocator.DIRECT) // 堆内存和堆外内存,默认:堆内存 .readBufferSize(512) // 消息一起解析的长度,默认:为 8092 (mqtt 消息最大长度) .maxBytesInMessage(1024 * 10) // 最大包体长度,如果包体过大需要设置此参数,默认为: 10M (10*1024*1024) .keepAliveSecs(120) // 默认:60s .timeout(10) // 超时时间,t-io 配置,可为 null,为 null 时,t-io 默认为 5 .reconnect(true) // 是否重连,默认:true .reInterval(5000) // 重连重试时间,reconnect 为 true 时有效,t-io 默认为:5000 .willMessage(builder -> { builder.topic("/test/offline").messageText("down"); // 遗嘱消息 }) .connectListener(new IMqttClientConnectListener() { @Override public void onConnected(ChannelContext context, boolean isReconnect) { logger.info("链接服务器成功..."); } @Override public void onDisconnect(ChannelContext channelContext, Throwable throwable, String remark, boolean isRemove) { logger.info("与链接服务器断开连接..."); } }) .properties() // mqtt5 properties .connectSync(); // 同步连接,也可以使用 connect(),可以避免 broker 没启动照成启动卡住。 // 消息订阅,同类方法 subxxx client.subQos0("/test/#", (context, topic, message, payload) -> { logger.info(topic + '\t' + new String(payload, StandardCharsets.UTF_8)); }); // 取消订阅 client.unSubscribe("/test/#"); // 发送消息 client.publish("/test/client", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 断开连接 client.disconnect(); // 重连 client.reconnect(); // 停止 client.stop(); 服务端 // 注意:为了能接受更多链接(降低内存),请添加 jvm 参数 -Xss129k MqttServer mqttServer = MqttServer.create() // 服务端 ip 默认为空,0.0.0.0,建议不要设置 .ip("0.0.0.0") // 默认:1883 .port(1883) // 默认为: 8092(mqtt 默认最大消息大小),为了降低内存可以减小小此参数,如果消息过大 t-io 会尝试解析多次(建议根据实际业务情况而定) .readBufferSize(512) // 最大包体长度,如果包体过大需要设置此参数,默认为: 8092 .maxBytesInMessage(1024 * 100) // 自定义认证 .authHandler((clientId, userName, password) -> true) // 消息监听 .messageListener((context, clientId, message) -> { logger.info("clientId:{} message:{} payload:{}", clientId, message, new String(message.getPayload(), StandardCharsets.UTF_8)); }) // 堆内存和堆外内存选择,默认:堆内存 .bufferAllocator(ByteBufferAllocator.HEAP) // 心跳超时时间,默认:120s .heartbeatTimeout(120_1000L) // ssl 配置 .useSsl("", "", "") // 自定义客户端上下线监听 .connectStatusListener(new IMqttConnectStatusListener() { @Override public void online(String clientId) { } @Override public void offline(String clientId) { } }) // 自定义消息转发,可用 mq 广播实现集群化处理 .messageDispatcher(new IMqttMessageDispatcher() { @Override public void config(MqttServer mqttServer) { } @Override public boolean send(Message message) { return false; } @Override public boolean send(String clientId, Message message) { return false; } }) .debug() // 开启 debug 信息日志 .start(); // 发送给某个客户端 mqttServer.publish("clientId","/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 发送给所有在线监听这个 topic 的客户端 mqttServer.publishAll("/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 停止服务 mqttServer.stop(); --- ### 194. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 WeConnect-MQTT是一个用于将大众汽车WeConnect服务数据发布到MQTT协议的客户端。MQTT(Message Queuing Telemetry Transport)是一种标准协议,用于集成来自WeConnect启用的汽车的数据。该客户端允许您将数据集成到您选择的MQTT代理中,例如家庭自动化解决方案(如ioBroker、FHEM或Home Assistant)。 2. 硬件和软件要求 在您的系统上安装Python 3是必需的,最低要求的Python版本为3.8。如果您的车型使用新的WeConnect API,您可能需要同意新的WeConnect接口的条款和条件。最简单的方式是在智能手机上安装大众汽车应用程序并在那里登录。 3. 安装 要使用WeConnect-MQTT,最简单的方式是从PyPI获取它。只需运行以下命令进行安装: pip3 install weconnect-mqtt 4. 升级 如果您希望升级WeConnect-MQTT,最简单的方式是运行以下命令: pip3 install weconnect-mqtt --upgrade 5. Docker支持 还提供了一个Docker镜像,以轻松托管WeConnect-MQTT,您可以在Dockerhub上找到它。 6. 使用说明 您可以通过命令行启动WeConnect-MQTT客户端: weconnect-mqtt 您可以使用"--help"命令来获取所有使用说明: weconnect-mqtt --help 以下是一个连接到MQTT代理地址为192.168.0.1,使用用户名test和密码test123的示例: weconnect-mqtt --username test@test.de --password test123 --mqttbroker 192.168.0.1 --mqtt-username test --mqtt-password test123 --prefix weconnect 在此示例中,客户端使用用户名test@test.de和密码test123连接到WeConnect。 7. S-PIN 对于某些命令(例如,某些车型支持的锁定/解锁功能),除了登录,您还需要提供S-PIN(安全个人识别码),您可以使用"--spin"选项来提供: weconnect-mqtt --username test@test.de --password test123 --spin 1234 --mqttbroker 192.168.0.1 --mqtt-username test --mqtt-password test123 --prefix weconnect 8. 凭据 如果您不想每次都提供用户名和密码,您可以在适当的位置(通常是主文件夹)创建一个".netrc"文件: # 对于WeConnect machine volkswagen.de login test@test.de password testpassword123 # 对于MQTT代理 machine 192.168.0.1 login test password testpassword123 您还可以使用"--netrc"选项来指定".netrc"文件的位置。 9. 充电站数据 您还可以通过添加位置和半径信息来获取充电站的数据,例如"--chargingLocation 52.437132 10.796628 --chargingLocationRadius=500"。充电站的数据主要是静态的,但您可以查看当前的可用性。 10. 主题 如果您的MQTT代理不允许您观察所有可用主题,您可以传递参数"--list-topics"以在命令行上显示所有主题。带有"(writeable)"标记的主题可以进行操作。还有两个主题,用于以逗号分隔的列表形式接收所有可用主题:"weconnect/0/mqtt/topics"和"weconnect/0/mqtt/writeableTopics"。 11. 禁用功能 您可以使用"--no-capabilities"选项来禁用车辆功能数据。如果只需要数据的子集,您可以使用"--selective"选项。例如,"--selective climatisation"。 12. 图像 您可以使用"--pictures"选项来启用汽车的ASCII Art图片。 13. PNG车辆图片 如果您的MQTT客户端可以处理通过MQTT接收的PNG图片,您可以使用"--picture-format png"选项。 14. 时间设置 默认情况下,车辆传来的时间是UTC isoformat。您可以通过添加"--convert-times"选项将时间转换为本地时区。要将时间设置为特定的时区,可以使用"--convert-times Europe/Berlin"。您还可以通过"--timeformat"将时间格式化为本地时间格式,例如"--timeformat '%a %d %b %Y %T'"。如果要使用不同于系统默认语言的日期格式,可以使用"--locale"选项。 15. 原始JSON数据 如果您想继续处理完整的数据,您还可以使用"--with-raw-json-topic"选项启用原始JSON数据主题。该主题在JSON字符串发生更改时发布。 16. 已测试车型 大众ID.3(2021年车型) 大众Passat GTE(2021年车型) 17. 相关项目 WeConnect-cli:用于与大众汽车WeConnect服务进行交互的命令行界面 WeConnect-python:连接到大众汽车WeConnect服务的Python API VWsFriend:VWsFriend是一款可视化记录汽车统计数据并允许通过HomeKit进行控制的软件。 通过WeConnect-MQTT,您可以轻松将大众汽车WeConnect服务的数据发布到MQTT,并将其集成到您的自动化解决方案中。这个客户端提供了丰富的功能和选项,使其非常灵活,适用于多种应用场景。 --- ### 195. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,广泛应用于物联网和实时通信领域。asyncio-mqtt是一个为Python开发者设计的基于异步IO的MQTT客户端库,通过利用Python的asyncio库提供高效、可靠的异步MQTT通信。 2. 安装 要安装asyncio-mqtt库,可以使用以下命令: pip install asyncio-mqtt 3. 使用方法 使用asyncio-mqtt库可以轻松地实现异步MQTT通信。 3.1 连接到MQTT代理 首先,需要创建一个MQTT客户端并连接到MQTT代理服务器: import asyncio_mqtt as mqtt async def connect_mqtt(): client = mqtt.Client() await client.connect('mqtt.example.com') return client client = asyncio.run(connect_mqtt()) 在上述示例中,'mqtt.example.com' 是MQTT代理服务器的地址。 3.2 发布消息 要发布消息到MQTT代理服务器,可以使用publish方法: await client.publish('topic', 'message') 在上述示例中,'topic' 是要发布到的主题,'message' 是要发送的消息。 3.3 订阅消息 要订阅MQTT代理服务器的消息,可以使用subscribe方法: async def on_message(topic, message): print(f'Received message in topic "{topic}": {message}') await client.subscribe('topic', on_message) 在上述示例中,'topic' 是要订阅的主题,'on_message' 是在接收到消息时调用的回调函数。 3.4 断开连接 当不再需要与MQTT代理服务器通信时,可以断开连接: await client.disconnect() 4. 优点 使用asyncio-mqtt库具有以下优点: 异步IO支持:asyncio-mqtt利用Python的asyncio库实现了异步IO,提高了MQTT通信的效率和可靠性。 易于使用:asyncio-mqtt提供了简洁的API接口,使得MQTT通信容易上手并可以轻松集成到现有项目中。 5. 应用场景 asyncio-mqtt适用于各种需要异步MQTT通信的场景,特别在以下情况下它尤为有用: 物联网应用:asyncio-mqtt能够轻松与物联网设备进行异步通信,实现实时数据传输和控制。 实时监控系统:使用asyncio-mqtt,您可以建立快速响应的实时监控系统,监控设备状态并接收实时数据。 消息订阅与发布:通过asyncio-mqtt,可以轻松实现消息订阅和发布机制,支持实时信息推送和订阅者的消息更新。 综上所述,asyncio-mqtt是一个高效、易于使用的异步MQTT客户端库。它基于Python的asyncio库,提供异步MQTT通信功能,使得在物联网和实时通信领域更加便捷。通过asyncio-mqtt,您可以轻松构建异步MQTT应用,满足各种实时通信需求。 --- ### 196. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在当前的数字化时代,实时数据交流和物联网(IoT)技术正快速增长,开发者们正在寻找更高效和更稳定的方法来处理数据流。在这方面,MQTT 和 Django 都已经成为了各自领域的领导者。在本文中,我们将介绍如何将这两个强大的工具集成在一起,以打造一个稳定、快速的实时通讯系统。 Django 简介及其特点 Django 是一个开放源代码的 Web 开发框架,由 Python 语言编写。它鼓励“不要重复自己”的设计哲学和“框架即插件”的结构,使得开发者能够快速、高效地构建高品质的 Web 应用程序。以下是 Django 的主要特点: DRY原则 (Don't Repeat Yourself):Django 遵循 DRY 原则,意味着系统应尽量避免重复的功能和信息。 安全性:Django 自带了防范多种网络攻击的功能,如 CSRF、XSS、SQL注入等。 可扩展性:它的“框架即插件”结构使得开发者可以轻松地添加功能和组件。 MVC 架构:Django 遵循模型-视图-控制器 (MVC) 设计模式,帮助开发者组织代码和逻辑。 MQTT 简介及其特点 MQTT (Message Queuing Telemetry Transport) 是一种基于发布/订阅模式的轻量级消息传递协议,特别适用于低带宽、不稳定的网络环境。以下是 MQTT 的主要特点: 轻量级:MQTT 是为低带宽和低功耗的设备设计的,它的协议头非常小。 质量服务等级:MQTT 提供三种消息交付级别:At most once、At least once、Exactly once,使得开发者可以根据需要选择合适的级别。 持久性会话:MQTT 支持持久会话,即客户端可以选择保持其会话信息,从而避免频繁的重新连接。 Last Will 和 Testament (LWT) 消息:这是一个预定义的消息,只有在发布者失去连接时,才会被发布。 有了上述背景知识,我们现在可以探讨如何在 Django 项目中整合 MQTT,实现实时通信。 初始化项目 首先,我们将使用 Python 3.8 作为开发环境,你可以通过以下命令确认你的 Python 版本: $ python3 --version Python 3.8.2 接着,使用 Pip 安装所需的包: pip3 install django paho-mqtt 然后,创建一个新的 Django 项目: django-admin startproject mqtt_test 项目结构如下: ├── manage.py └── mqtt_test ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py ├── views.py └── wsgi.py MQTT 的整合 我们将使用由 EMQ 提供的公共 MQTT 服务器,服务器信息如下: Broker: broker.emqx.io TCP Port: 1883 Websocket Port: 8083 首先,导入必要的库: import paho.mqtt.client as mqtt 设置连接的回调函数。成功连接后,我们将订阅到 django/mqtt 主题: def on_connect(mqtt_client, userdata, flags, rc): if rc == 0: print('Connected successfully') mqtt_client.subscribe('django/mqtt') else: print('Connection failed. Code:', rc) 设置接收消息的回调函数: def on_message(mqtt_client, userdata, msg): print(f'Received message on topic: {msg.topic} with payload: {msg.payload}') 在 settings.py 中配置 MQTT: MQTT_SERVER = 'broker.emqx.io' MQTT_PORT = 1883 MQTT_KEEPALIVE = 60 MQTT_USER = '' MQTT_PASSWORD = '' 初始化 MQTT 客户端并连接: client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.username_pw_set(settings.MQTT_USER, settings.MQTT_PASSWORD) client.connect( host=settings.MQTT_SERVER, port=settings.MQTT_PORT, keepalive=settings.MQTT_KEEPALIVE ) 为了演示,我们创建一个发布消息的接口: import json from django.http import JsonResponse from mqtt_test.mqtt import client as mqtt_client def publish_message(request): request_data = json.loads(request.body) rc, mid = mqtt_client.publish(request_data['topic'], request_data['msg']) return JsonResponse({'code': rc}) 在 urls.py 中,将接口与 URL 进行绑定: from django.urls import path from . import views urlpatterns = [ path('publish', views.publish_message, name='publish'), ] 最后,在 __init__.py 中启动 MQTT 客户端: from . import mqtt mqtt.client.loop_start() 运行项目 执行以下命令,启动 Django 项目: python3 manage.py runserver 项目启动后,MQTT 客户端将连接服务器,并订阅 django/mqtt 主题。 至此,我们已成功在 Django 项目中整合了 MQTT。这为你提供了一个强大的实时消息功能,无论是 IoT 项目还是其他实时更新的应用,这种结合都会带来巨大的便利。 --- ### 197. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着物联网 (IoT) 和微服务架构的日益普及,MQTT 已经成为一个关键的消息传递协议。在本文中,我们将讨论如何在 Spring Boot 应用程序中集成 MQTT,从而为你的应用带来更好的扩展性和响应性。 1. 什么是 MQTT? MQTT(Message Queuing Telemetry Transport)是一个轻量级的发布/订阅协议,专为低带宽、高延迟或不可靠的网络设计。它广泛应用于 IoT 场景中,连接传感器、设备和应用。 2. 为什么选择 MQTT? 轻量级:MQTT 的报文头部很小,非常适合于受到带宽限制的网络。 消息等级:它支持不同级别的消息传递保证。 持久会话:支持持久会话,即客户端和服务器之间的会话状态可以被保留。 最后遗言:如果一个客户端断开连接,它可以预先设定一个“最后遗言”消息。 3. Spring Boot 中的 MQTT 要在 Spring Boot 中使用 MQTT,我们首先需要添加相关的依赖。我们将使用 Eclipse Paho Java 客户端作为 MQTT 的客户端库。 <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-mqtt</artifactId> <version>5.5.9</version> </dependency> <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.5</version> </dependency> 4. 配置 MQTT 包含接收消息的配置和发送消息的配置 package com.demo.config; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.integration.annotation.ServiceActivator; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.core.MessageProducer; import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory; import org.springframework.integration.mqtt.core.MqttPahoClientFactory; import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter; import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler; import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import java.util.UUID; /** * mqtt连接配置 */ @Configuration public class MqttConfig { /** * 创建连接 * * @return */ @Bean public MqttPahoClientFactory mqttClientFactory() { DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory(); MqttConnectOptions options = new MqttConnectOptions(); // mqtt用户名&密码 String userName = ""; String pwd = ""; // mqtt服务地址,可以是多个 options.setServerURIs(new String[]{"tcp://server:1883"}); options.setUserName(userName); options.setPassword(pwd.toCharArray()); factory.setConnectionOptions(options); return factory; } /** * 2、接收消息的通道 */ @Bean public MessageChannel mqttInputChannel() { return new DirectChannel(); } /** * 接收消息 * * @return */ @Bean public MessageProducer inbound() { // 订阅主题,保证唯一性 String inClientId = UUID.randomUUID().toString().replaceAll("-", ""); // 最后的#相当于通配符的概念 String[] topic = {"topic_prefix/topic/#"}; MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter( inClientId, mqttClientFactory(), topic); adapter.setCompletionTimeout(5000); DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter(); // 按字节接收消息 // defaultPahoMessageConverter.setPayloadAsBytes(true); adapter.setConverter(defaultPahoMessageConverter); // 设置QoS adapter.setQos(1); adapter.setOutputChannel(mqttInputChannel()); return adapter; } /** * 3、消息处理 * ServiceActivator注解表明:当前方法用于处理MQTT消息,inputChannel参数指定了用于消费消息的channel */ @Bean @ServiceActivator(inputChannel = "mqttInputChannel") public MessageHandler handler() { return message -> { String payload = message.getPayload().toString(); // byte[] bytes = (byte[]) message.getPayload(); // 收到的消息是字节格式 String topic = message.getHeaders().get("mqtt_receivedTopic").toString(); // 可以根据topic进行处理不同的业务类型 System.out.println("主题[" + topic + "],负载:" + payload); }; } /** * 发送消息的通道 * * @return */ @Bean public MessageChannel mqttOutboundChannel() { return new DirectChannel(); } /** * 发送消息 */ @Bean @ServiceActivator(inputChannel = "mqttOutboundChannel") public MessageHandler outbound() { // 连接clientId保证唯一 String outClientId = UUID.randomUUID().toString().replaceAll("-", ""); // 发送消息和消费消息Channel可以使用相同MqttPahoClientFactory MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(outClientId, mqttClientFactory()); // 如果设置成true,即异步,发送消息时将不会阻塞。 // messageHandler.setAsync(true); // 设置默认的topic // messageHandler.setDefaultTopic("defaultTopic"); // 设置默认QoS messageHandler.setDefaultQos(1); // Paho消息转换器 DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter(); // 发送默认按字节类型发送消息 // defaultPahoMessageConverter.setPayloadAsBytes(true); messageHandler.setConverter(defaultPahoMessageConverter); return messageHandler; } } 5. 消息发送 1. 定义消息发送的接口 package com.demo.config; import org.springframework.integration.annotation.MessagingGateway; import org.springframework.integration.mqtt.support.MqttHeaders; import org.springframework.messaging.handler.annotation.Header; /** * 定义消息发送的接口 */ @MessagingGateway(defaultRequestChannel = "mqttOutboundChannel") public interface MqttGateWay { /** * 发送消息 * * @param payload 发送的消息 */ void sendToMqtt(String payload); /** * 指定topic消息发送 * * @param topic 指定topic * @param payload 消息 */ void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload); void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload); void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, byte[] payload); } 2. 定义消息发送的controller package com.demo.business; import com.sonli.config.MqttGateWay; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 对外暴露发送消息的controller */ @RestController @RequestMapping("/mqtt") public class MqttController { @Autowired private MqttGateWay mqttGateWay; @PostMapping("/sendMessage") public String sendMessage(String topic, String message) { // 发送消息到指定topic mqttGateWay.sendToMqtt(topic, 1, message); return "send topic: " + topic + ", message : " + message; } } 测试 发送消息 消息的监听,收到的消息 总结 Spring Boot 与 MQTT 的集成为开发者提供了一个简单但功能强大的方式,用于创建 IoT 和消息驱动的应用程序。这种集成不仅确保了消息传递的可靠性和效率,还使得应用程序更具扩展性和响应性。 希望这篇文章能为你提供在 Spring Boot 中集成 MQTT 的指导。如果你有任何问题或需要进一步的指导,请随时留言或联系我们。 --- ### 198. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. Rust编程语言的简介Rust是Mozilla研发的编译型通用编程语言,它的核心原则是安全性、并发性和实用性。结合函数式、并发式、过程式以及面向对象的编程风格,Rust提供了出色的性能和高效的内存利用。不同于其他具有垃圾收集机制的语言,Rust没有运行时,这使其在高性能要求的服务和嵌入式设备上运行得更加高效。其强大的类型系统和所有权模型进一步确保了内存和线程的安全性,从而在编译时消除了众多错误。 2. MQTT的物联网传输协议MQTT是一个轻量级的物联网通信协议,基于发布/订阅模式,它针对网络带宽低和代码资源有限的环境进行了优化。被广泛应用于物联网、移动应用、智能硬件、车联网和能源行业。 3. Rust中的paho-mqtt客户端库为了使Rust与MQTT进行高效通信,我们选择使用paho-mqtt,一个在Rust社区中广受欢迎的MQTT客户端库。它支持最新的MQTT版本,并提供多种传输协议选项。 项目初始化 本项目使用 Rust 1.44.0 进行开发测试,并使用 Cargo 1.44.0 包管理工具进行项目管理,读者可用如下命令查看当前的 Rust 版本。 ~ rustc --version rustc 1.44.0 (49cae5576 2020-06-01) 选择 MQTT 客户端库 paho-mqtt 是目前 Rust 中,功能完善且使用较多的 MQTT 客户端,最新的 0.7.1 版本支持 MQTT v5、3.1.1、3.1,支持通过标准 TCP、SSL / TLS、WebSockets 传输数据,QoS 支持 0、1、2 等。 初始化项目 执行以下命令创建名为 mqtt-example 的 Rust 新项目。 ~ cargo new mqtt-example Created binary (application) `mqtt-example` package 编辑项目中的 Cargo.toml 文件,在 dependencies 中添加 paho-mqtt 库的地址,以及指定订阅、发布代码文件对应的二进制文件。 [dependencies] paho-mqtt = { git = "https://github.com/eclipse/paho.mqtt.rust.git", branch = "master" } [[bin]] name = "sub" path = "src/sub/main.rs" [[bin]] name = "pub" path = "src/pub/main.rs" Rust MQTT 的使用 创建客户端连接 本文将使用 EMQX 提供的 免费公共 MQTT 服务器 作为测试连接的 MQTT 服务器,该服务基于 EMQX 的 MQTT 物联网云平台 创建。服务器接入信息如下: Broker: broker.emqx.io TCP Port: 1883 Websocket Port: 8083 配置 MQTT Broker 连接参数 配置 MQTT Broker 连接地址(包括端口)、topic (这里我们配置了两个 topic ),以及客户端 id。 const DFLT_BROKER:&str = "tcp://broker.emqx.io:1883"; const DFLT_CLIENT:&str = "rust_publish"; const DFLT_TOPICS:&[&str] = &["rust/mqtt", "rust/test"]; 编写 MQTT 连接代码 编写 MQTT 连接代码,为了提升使用体验,可在执行二进制文件时通过命令行参数的形式传入连接地址。通常我们需要先创建一个客户端,然后将该客户端连接到 broker.emqx.io。 let host = env::args().nth(1).unwrap_or_else(|| DFLT_BROKER.to_string() ); // Define the set of options for the create. // Use an ID for a persistent session. let create_opts = mqtt::CreateOptionsBuilder::new() .server_uri(host) .client_id(DFLT_CLIENT.to_string()) .finalize(); // Create a client. let cli = mqtt::Client::new(create_opts).unwrap_or_else(|err| { println!("Error creating the client: {:?}", err); process::exit(1); }); // Define the set of options for the connection. let conn_opts = mqtt::ConnectOptionsBuilder::new() .keep_alive_interval(Duration::from_secs(20)) .clean_session(true) .finalize(); // Connect and wait for it to complete or fail. if let Err(e) = cli.connect(conn_opts) { println!("Unable to connect:\n\t{:?}", e); process::exit(1); } 发布消息 这里我们总共发布五条消息,根据循环的奇偶性,分别向 rust/mqtt、 rust/test 这两个主题发布。 for num in 0..5 { let content = "Hello world! ".to_string() + &num.to_string(); let mut msg = mqtt::Message::new(DFLT_TOPICS[0], content.clone(), QOS); if num % 2 == 0 { println!("Publishing messages on the {:?} topic", DFLT_TOPICS[1]); msg = mqtt::Message::new(DFLT_TOPICS[1], content.clone(), QOS); } else { println!("Publishing messages on the {:?} topic", DFLT_TOPICS[0]); } let tok = cli.publish(msg); if let Err(e) = tok { println!("Error sending message: {:?}", e); break; } } 订阅消息 在客户端连接之前,需要先初始化消费者。这里我们会循环处理消费者中的消息队列,并打印出订阅的 topic 名称及接收到的消息内容。 fn subscribe_topics(cli: &mqtt::Client) { if let Err(e) = cli.subscribe_many(DFLT_TOPICS, DFLT_QOS) { println!("Error subscribes topics: {:?}", e); process::exit(1); } } fn main() { ... // Initialize the consumer before connecting. let rx = cli.start_consuming(); ... // Subscribe topics. subscribe_topics(&cli); println!("Processing requests..."); for msg in rx.iter() { if let Some(msg) = msg { println!("{}", msg); } else if !cli.is_connected() { if try_reconnect(&cli) { println!("Resubscribe topics..."); subscribe_topics(&cli); } else { break; } } } ... } 完整代码 消息发布代码 use std::{ env, process, time::Duration }; extern crate paho_mqtt as mqtt; const DFLT_BROKER:&str = "tcp://broker.emqx.io:1883"; const DFLT_CLIENT:&str = "rust_publish"; const DFLT_TOPICS:&[&str] = &["rust/mqtt", "rust/test"]; // Define the qos. const QOS:i32 = 1; fn main() { let host = env::args().nth(1).unwrap_or_else(|| DFLT_BROKER.to_string() ); // Define the set of options for the create. // Use an ID for a persistent session. let create_opts = mqtt::CreateOptionsBuilder::new() .server_uri(host) .client_id(DFLT_CLIENT.to_string()) .finalize(); // Create a client. let cli = mqtt::Client::new(create_opts).unwrap_or_else(|err| { println!("Error creating the client: {:?}", err); process::exit(1); }); // Define the set of options for the connection. let conn_opts = mqtt::ConnectOptionsBuilder::new() .keep_alive_interval(Duration::from_secs(20)) .clean_session(true) .finalize(); // Connect and wait for it to complete or fail. if let Err(e) = cli.connect(conn_opts) { println!("Unable to connect:\n\t{:?}", e); process::exit(1); } // Create a message and publish it. // Publish message to 'test' and 'hello' topics. for num in 0..5 { let content = "Hello world! ".to_string() + &num.to_string(); let mut msg = mqtt::Message::new(DFLT_TOPICS[0], content.clone(), QOS); if num % 2 == 0 { println!("Publishing messages on the {:?} topic", DFLT_TOPICS[1]); msg = mqtt::Message::new(DFLT_TOPICS[1], content.clone(), QOS); } else { println!("Publishing messages on the {:?} topic", DFLT_TOPICS[0]); } let tok = cli.publish(msg); if let Err(e) = tok { println!("Error sending message: {:?}", e); break; } } // Disconnect from the broker. let tok = cli.disconnect(None); println!("Disconnect from the broker"); tok.unwrap(); } 消息订阅代码 为了提升使用体验,消息订阅做了断开重连的处理,并在重新建立连接后对主题进行重新订阅。 use std::{ env, process, thread, time::Duration }; extern crate paho_mqtt as mqtt; const DFLT_BROKER:&str = "tcp://broker.emqx.io:1883"; const DFLT_CLIENT:&str = "rust_subscribe"; const DFLT_TOPICS:&[&str] = &["rust/mqtt", "rust/test"]; // The qos list that match topics above. const DFLT_QOS:&[i32] = &[0, 1]; // Reconnect to the broker when connection is lost. fn try_reconnect(cli: &mqtt::Client) -> bool { println!("Connection lost. Waiting to retry connection"); for _ in 0..12 { thread::sleep(Duration::from_millis(5000)); if cli.reconnect().is_ok() { println!("Successfully reconnected"); return true; } } println!("Unable to reconnect after several attempts."); false } // Subscribes to multiple topics. fn subscribe_topics(cli: &mqtt::Client) { if let Err(e) = cli.subscribe_many(DFLT_TOPICS, DFLT_QOS) { println!("Error subscribes topics: {:?}", e); process::exit(1); } } fn main() { let host = env::args().nth(1).unwrap_or_else(|| DFLT_BROKER.to_string() ); // Define the set of options for the create. // Use an ID for a persistent session. let create_opts = mqtt::CreateOptionsBuilder::new() .server_uri(host) .client_id(DFLT_CLIENT.to_string()) .finalize(); // Create a client. let mut cli = mqtt::Client::new(create_opts).unwrap_or_else(|err| { println!("Error creating the client: {:?}", err); process::exit(1); }); // Initialize the consumer before connecting. let rx = cli.start_consuming(); // Define the set of options for the connection. let lwt = mqtt::MessageBuilder::new() .topic("test") .payload("Consumer lost connection") .finalize(); let conn_opts = mqtt::ConnectOptionsBuilder::new() .keep_alive_interval(Duration::from_secs(20)) .clean_session(false) .will_message(lwt) .finalize(); // Connect and wait for it to complete or fail. if let Err(e) = cli.connect(conn_opts) { println!("Unable to connect:\n\t{:?}", e); process::exit(1); } // Subscribe topics. subscribe_topics(&cli); println!("Processing requests..."); for msg in rx.iter() { if let Some(msg) = msg { println!("{}", msg); } else if !cli.is_connected() { if try_reconnect(&cli) { println!("Resubscribe topics..."); subscribe_topics(&cli); } else { break; } } } // If still connected, then disconnect now. if cli.is_connected() { println!("Disconnecting"); cli.unsubscribe_many(DFLT_TOPICS).unwrap(); cli.disconnect(None).unwrap(); } println!("Exiting"); } 运行与测试 编译二进制文件 执行以下命令,会在 mqtt-example/target/debug 目录下生成消息订阅、发布对应的 sub、pub 二进制文件。 cargo build 消息订阅 执行 sub 二进制文件,等待消费发布。 消息发布 执行 pub 二进制文件,可以看到分别往 rust/test 、rust/mqtt 这两个主题发布了消息。 同时在消息订阅中可看到发布的消息 至此,我们完成了使用 paho-mqtt 客户端连接到 公共 MQTT 服务器,并实现了测试客户端与 MQTT 服务器的连接、消息发布和订阅。 8. 结论结合Rust的高性能特性和MQTT的轻量级通信,物联网应用可以实现更快、更可靠的消息传输和处理。这不仅提高了物联网设备的性能,还为开发者带来了更为便捷的开发体验。 总之,Rust与MQTT结合为物联网通信带来了一场革命。利用这些技术,开发者可以设计出响应迅速、安全并且低成本的物联网应用。 --- ### 199. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 PHP是一种广泛使用的开放源代码脚本语言,专门针对Web开发而设计,并可嵌入到HTML中直接执行。起初,PHP是代表“Personal Home Page”的缩写,但现在它是“PHP: Hypertext Preprocessor”的递归缩写。PHP支持各种数据库、协议和具有丰富的内置函数库。运行于大多数服务器、操作系统平台,并且与其他流行的数据库完美集成。随着时间的推移,许多框架如Laravel、Symfony和CodeIgniter为PHP开发提供了极大的便利,使其在现代Web开发中继续保持其核心地位。 MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息传输协议,专为低带宽和不稳定的网络环境设计。起初为监控远程传感器和设备而开发,现在已广泛应用于物联网(IoT)领域。它允许设备在最小的代码和电源消耗下进行有效通信,使其成为联网设备的理想选择。随着物联网的发展,MQTT已被多家大型技术公司所采纳,并且逐渐成为物联网通信的事实标准。其核心概念包括Broker(消息中心)和客户端,通过Topic(主题)实现消息的分发和接收。 本篇文章深入探讨了如何在PHP项目中通过php-mqtt/client库,有效地建立MQTT客户端与MQTT服务器的连接,并实现订阅、取消订阅以及消息的收发功能。 选择MQTT客户端库 当谈及PHP中的MQTT客户端库,php-mqtt/client无疑是composer平台上最受欢迎的选择,其下载量领先于其他库。对于感兴趣的开发者,Packagist的Search MQTT功能提供了更多的客户端库选择。 为了更深入地了解如何使用php-mqtt/client,您可以参考Packagist上的php-mqtt/client官方文档。 PHP中的MQTT通信 值得注意的是,MQTT通信并不属于传统的HTTP体系。由于PHP的某些特性限制,采用专为网络通信设计的PHP拓展,如Swoole或Workerman,会为开发者带来更为流畅的体验。在这里,我们不再深入这些拓展的具体使用方法,但以下是一些与MQTT相关的客户端库: workerman/mqtt: 一个基于workerman的PHP异步MQTT客户端。 simps/mqtt: 专为PHP设计的MQTT协议解析和协程客户端。 项目准备 确认 PHP 版本 本项目使用 7.4.21 进行开发测试,读者可用如下命令确认 PHP 的版本。 php --version PHP 7.4.21 (cli) (built: Jul 12 2021 11:52:30) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.21, Copyright (c), by Zend Technologies 使用 Composer 安装 php-mqtt/client 客户端 Composer 是 PHP 的一个依赖管理工具,它能管理你的 PHP 项目所需要的所有依赖关系。 composer require php-mqtt/client 准备 MQTT Broker 在继续之前,您需要一个 MQTT Broker 进行通信和测试。你可以通过一下方式获取 MQTT Broker: 私有部署EMQX 是应用于物联网、工业物联网和车联网的最具可扩展性的开源 MQTT Broker。您可以通过以下 Docker 命令来安装 EMQX: docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx 本文将使用 EMQX 提供的 免费公共 MQTT 服务器,该服务基于 EMQX 的 MQTT 物联网云平台 创建。服务器接入信息如下: Broker: broker-cn.emqx.io TCP Port: 1883 SSL/TLS Port: 8883 PHP MQTT 使用指南 导入 composer autoload 文件和 php-mqtt/client require('vendor/autoload.php'); use \PhpMqtt\Client\MqttClient; 设置 MQTT Broker 连接参数 设置 MQTT Broker 连接地址,端口,客户端 ID,用户名以及 topic,这里我们调用 PHP rand 函数随机生成 MQTT 客户端 ID,避免与其他客户端 ID 重复。 $server = 'broker-cn.emqx.io'; $port = 1883; $clientId = rand(5, 15); $username = 'emqx_user'; $password = null; $clean_session = false; 使用上述的参数进行连接,通过 ConnectionSettings 设置连接参数: $connectionSettings = new ConnectionSettings(); $connectionSettings ->setUsername($username) ->setPassword(null) ->setKeepAliveInterval(60) // Last Will 设置 ->setLastWillTopic('emqx/test/last-will') ->setLastWillMessage('client disconnect') ->setLastWillQualityOfService(1); 订阅消息 编写代码订阅 emqx/test 主题,并为该订阅配置回调函数以处理接收到的消息,此处我们将订阅得到的主题和消息打印出来: // 订阅 $mqtt->subscribe('emqx/test', function ($topic, $message) { printf("Received message on topic [%s]: %s\n", $topic, $message); }, 0); 发布消息 构造一个 payload,调用 publish 函数向 emqx/test 主题发布消息,发布完成之后客户端需要进入轮询状态,处理传入的消息和重发队列: for ($i = 0; $i< 10; $i++) { $payload = array( 'protocol' => 'tcp', 'date' => date('Y-m-d H:i:s'), 'url' => 'https://github.com/emqx/MQTT-Client-Examples' ); $mqtt->publish( // topic 'emqx/test', // payload json_encode($payload), // qos 0, // retain true ); printf("msg $i send\n"); sleep(1); } // 客户端轮询以处理传入消息和重发队列 $mqtt->loop(true); // 断开 MQTT 连接 // $client->disconnect(); 完整代码 服务器连接、消息发布与接收代码。 <?php require('vendor/autoload.php'); use \PhpMqtt\Client\MqttClient; use \PhpMqtt\Client\ConnectionSettings; $server = 'broker.emqx.io'; $port = 1883; $clientId = rand(5, 15); $username = 'emqx_user'; $password = null; $clean_session = false; $connectionSettings = new ConnectionSettings(); $connectionSettings ->setUsername($username) ->setPassword(null) ->setKeepAliveInterval(60) // Last Will 设置 ->setLastWillTopic('emqx/test/last-will') ->setLastWillMessage('client disconnect') ->setLastWillQualityOfService(1); $mqtt = new MqttClient($server, $port, $clientId); $mqtt->connect($connectionSettings, $clean_session); printf("client connected\n"); $mqtt->subscribe('emqx/test', function ($topic, $message) { printf("Received message on topic [%s]: %s\n", $topic, $message); }, 0); for ($i = 0; $i< 10; $i++) { $payload = array( 'protocol' => 'tcp', 'date' => date('Y-m-d H:i:s'), 'url' => 'https://github.com/emqx/MQTT-Client-Examples' ); $mqtt->publish( // topic 'emqx/test', // payload json_encode($payload), // qos 0, // retain true ); printf("msg $i send\n"); sleep(1); } $mqtt->loop(true); // 断开 MQTT 连接 // $client->disconnect(); 测试 运行 MQTT 消息发布代码,我们将看到客户端已经成功连接,且消息已经逐条发布并接收成功: php pubsub_tcp.php 5. 总结 整合MQTT到PHP项目可能初看有些复杂,但随着上述指南的帮助,流程将变得明确和简单。选择适当的客户端库、理解PHP与MQTT的通信特性,再结合实战经验,即可轻松实现MQTT在PHP中的应用。 --- ### 200. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网(IoT)正在改变全球的工作和生活方式。为了实现这种互联和通信,我们需要强大、灵活且可靠的工具。本文将探索如何结合Python的强大功能和MQTT的高效通信,为物联网项目提供无缝解决方案。 为何选择Python与MQTT? Python,这一简洁、高效的编程语言,由于其出色的库支持和跨平台特性,已经成为了数据科学、网络开发和自动化的首选。它简单的语法和代码可读性使得开发过程更为迅速和直观。 另一方面,MQTT是一种轻量级的发布/订阅模式的通信协议,特别适用于低带宽、高延迟或不稳定的网络环境。正因为其高效和低耗,MQTT已成为物联网通信的标准。 步骤详解:构建基于Python的MQTT物联网应用 1. 环境准备 确保已安装Python 3.6或更高版本。你可以使用以下命令确认: python3 --version 2. 安装MQTT库 我们将使用paho-mqtt,这是一个流行的Python MQTT客户端库。 pip3 install -i https://pypi.doubanio.com/simple paho-mqtt 3. 连接到MQTT服务器 在此,我们选择使用EMQX提供的免费MQTT公共服务器,但同样可以选择其他任何MQTT broker。 Broker: broker.emqx.io TCP Port: 1883 Websocket Port: 8083 导入 Paho MQTT客户端 from paho.mqtt import client as mqtt_client 设置 MQTT Broker 连接参数 设置 MQTT Broker 连接地址,端口以及 topic,同时我们调用 Python random.randint 函数随机生成 MQTT 客户端 id。 broker = 'broker.emqx.io' port = 1883 topic = "/python/mqtt" client_id = f'python-mqtt-{random.randint(0, 1000)}' 编写 MQTT 连接函数 编写连接回调函数 on_connect,该函数将在客户端连接后被调用,在该函数中可以依据 rc 来判断客户端是否连接成功。通常同时我们将创建一个 MQTT 客户端,该客户端将连接到 broker.emqx.io。 def connect_mqtt(): def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) # Set Connecting Client ID client = mqtt_client.Client(client_id) client.on_connect = on_connect client.connect(broker, port) return client 发布消息 首先定义一个 while 循环语句,在循环中我们将设置每秒调用 MQTT 客户端 publish 函数向 /python/mqtt 主题发送消息。 def publish(client): msg_count = 0 while True: time.sleep(1) msg = f"messages: {msg_count}" result = client.publish(topic, msg) # result: [0, 1] status = result[0] if status == 0: print(f"Send `{msg}` to topic `{topic}`") else: print(f"Failed to send message to topic {topic}") msg_count += 1 订阅消息 编写消息回调函数 on_message,该函数将在客户端从 MQTT Broker 收到消息后被调用,在该函数中我们将打印出订阅的 topic 名称以及接收到的消息内容。 def subscribe(client: mqtt_client): def on_message(client, userdata, msg): print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic") client.subscribe(topic) client.on_message = on_message 完整代码 消息发布代码 # python 3.6 import random import time from paho.mqtt import client as mqtt_client broker = 'broker.emqx.io' port = 1883 topic = "/python/mqtt" # generate client ID with pub prefix randomly client_id = f'python-mqtt-{random.randint(0, 1000)}' def connect_mqtt(): def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) client = mqtt_client.Client(client_id) client.on_connect = on_connect client.connect(broker, port) return client def publish(client): msg_count = 0 while True: time.sleep(1) msg = f"messages: {msg_count}" result = client.publish(topic, msg) # result: [0, 1] status = result[0] if status == 0: print(f"Send `{msg}` to topic `{topic}`") else: print(f"Failed to send message to topic {topic}") msg_count += 1 def run(): client = connect_mqtt() client.loop_start() publish(client) if __name__ == '__main__': run() 消息订阅代码 # python3.6 import random from paho.mqtt import client as mqtt_client broker = 'broker.emqx.io' port = 1883 topic = "/python/mqtt" # generate client ID with pub prefix randomly client_id = f'python-mqtt-{random.randint(0, 100)}' def connect_mqtt() -> mqtt_client: def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) client = mqtt_client.Client(client_id) client.on_connect = on_connect client.connect(broker, port) return client def subscribe(client: mqtt_client): def on_message(client, userdata, msg): print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic") client.subscribe(topic) client.on_message = on_message def run(): client = connect_mqtt() subscribe(client) client.loop_forever() if __name__ == '__main__': run() 测试 消息发布 运行 MQTT 消息发布代码,我们将看到客户端连接成功,并且成功将消息发布。 python3 pub.py 消息订阅 运行 MQTT 消息订阅代码,我们将看到客户端连接成功,并且成功接收到发布的消息。 python3 sub.py 扩展你的IoT应用 数据安全:使用SSL/TLS保证数据的安全传输。 数据存储:结合数据库技术,例如SQLite、MySQL或MongoDB,持久化存储设备数据。 实时分析:利用Python的强大数据分析库,如pandas、NumPy和matplotlib,对接收到的数据进行实时处理和可视化。 设备管理:考虑添加一个设备管理系统,以便跟踪、更新和维护所有连接的设备。 总结 物联网的未来取决于我们如何有效地处理海量的设备数据。Python和MQTT为我们提供了一个高效、简洁且可靠的方式来捕获、分析和共享这些数据。无论是智能家居、工业自动化还是智慧城市,结合Python和MQTT的IoT解决方案都将开创新的可能性和机会。 --- ### 201. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Node.js 与 MQTT:构建下一代物联网应用 在今天的数字化时代,物联网应用正迅速成为前沿技术。而在这方面,Node.js 和 MQTT 的组合无疑为开发者提供了一种高效、灵活的方式来构建应用。在这篇文章中,我们将详细探讨如何在 Node.js 中利用 MQTT 来开发物联网应用。 1. 理解 Node.js 和 MQTT Node.js 不仅仅是一种服务端的 JavaScript 运行环境,它更是开发高性能、实时应用的绝佳选择。MQTT 则为我们提供了一个轻量、高效的消息通讯协议,特别适用于网络带宽有限或不稳定的环境中。 2. MQTT.js:构建 Node.js 中的 MQTT 应用 MQTT.js 是 Node.js 中最流行的 MQTT 客户端库,它为开发者提供了一个简单易用的 API 来开发 MQTT 客户端应用。 3. 快速入门:Node.js MQTT 客户端 首先,确保你的系统已经安装了 Node.js v14.14.0 或更高版本,接下来,我们将通过几个简单的步骤来搭建你的第一个 Node.js MQTT 客户端。 本项目使用 Node.js v14.14.0 进行开发和测试,读者可用如下命令确认 Node.js 的版本 node --version v14.14.0 使用 npm 安装 MQTT.js 客户端库 # 新建项目 npm init -y # 安装依赖 npm install mqtt --save 完成后我们在当前目录下新建一个 index.js 文件作为项目的入口文件,在该文件中来实现 MQTT 连接测试的完整逻辑。 Node.js MQTT 使用 连接 MQTT 服务器 本文将使用 EMQX 提供的 免费公共 MQTT 服务器,该服务基于 EMQX 的 MQTT 物联网云平台 创建。服务器接入信息如下: Broker: broker.emqx.io(国内可以使用 broker-cn.emqx.io) TCP Port: 1883 SSL/TLS Port: 8883 引入 MQTT.js 客户端库 注意:在 Node.js 环境中,导入依赖模块请使用 commonjs 规范 const mqtt = require('mqtt') 设置 MQTT Broker 的连接参数 设置 MQTT Broker 连接地址,端口以及 topic,这里我们使用 JavaScript 中的生成随机数的函数来生成客户端 ID。 const host = 'broker.emqx.io' const port = '1883' const clientId = `mqtt_${Math.random().toString(16).slice(3)}` 编写 MQTT 连接函数 我们使用刚才设置的连接参数来进行连接,连接的 URL 通过上面定义的 host、port 端口来进行拼接。然后调用 mqtt 模块内置的 connect 函数,连接成功后返回一个 Client 实例。 const connectUrl = `mqtt://${host}:${port}` const client = mqtt.connect(connectUrl, { clientId, clean: true, connectTimeout: 4000, username: 'emqx', password: 'public', reconnectPeriod: 1000, }) 订阅主题 使用返回的 Client 实例的 on 方法来监听连接成功状态,并在连接成功后的回调函数中订阅 topic。此时我们连接成功后调用 Client 实例的 subscribe 方法订阅 /nodejs/mqtt 主题。 const topic = '/nodejs/mqtt' client.on('connect', () => { console.log('Connected') client.subscribe([topic], () => { console.log(`Subscribe to topic '${topic}'`) }) }) 订阅主题成功后,我们再使用 on 方法来监听接收消息的方法,当接受到消息时,我们可以在该方法的回调函数中获取到 topic 和 message 消息。 注意:回调函数中的 message 是 Buffer 类型,需要使用 toString 方法将其转化为字符串 client.on('message', (topic, payload) => { console.log('Received Message:', topic, payload.toString()) }) 消息发布 完成上述的订阅主题和消息监听后,我们再来编写一个发布消息的方法。 注意:消息发布需要在 MQTT 连接成功以后,因此这里我们写到 Connect 成功的回调函数里 client.on('connect', () => { client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false }, (error) => { if (error) { console.error(error) } }) }) 完整代码 服务器连接、主题订阅、消息发布与接收的代码。 const mqtt = require('mqtt') const host = 'broker.emqx.io' const port = '1883' const clientId = `mqtt_${Math.random().toString(16).slice(3)}` const connectUrl = `mqtt://${host}:${port}` const client = mqtt.connect(connectUrl, { clientId, clean: true, connectTimeout: 4000, username: 'emqx', password: 'public', reconnectPeriod: 1000, }) const topic = '/nodejs/mqtt' client.on('connect', () => { console.log('Connected') client.subscribe([topic], () => { console.log(`Subscribe to topic '${topic}'`) }) client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false }, (error) => { if (error) { console.error(error) } }) }) client.on('message', (topic, payload) => { console.log('Received Message:', topic, payload.toString()) }) 项目完整代码请见:https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-Node.js 测试 我们在 package.json 文件中的脚本字段中添加一行启动脚本。 "scripts": { "start": "node index.js" } 然后就可以简单使用 npm start 来运行项目。 npm start 运行后我们可以看到控制的输出信息如下: 4. 安全性考虑 当涉及到物联网应用时,安全性是首要考虑的问题。确保使用 TLS/SSL 加密来保障你的数据安全。 5. 扩展阅读:更多 Node.js 与 MQTT 的强大特性 除了基本功能外,Node.js 和 MQTT 还有许多强大的特性等待你去发掘,如 QoS、消息保留、遗嘱消息等。 6. 结语 随着物联网应用的持续发展,Node.js 结合 MQTT 为开发者提供了一个强大、灵活且高效的工具来满足日益增长的需求。而你,作为一名开发者,现在已经掌握了使用这两个工具构建下一代物联网应用的知识。不要等待,开始你的 MQTT 之旅吧! 本文旨在为读者提供实际的价值,帮助开发者快速、高效地开发物联网应用。感谢你的阅读,期待你的反馈和建议。 --- ### 202. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Golang与MQTT:轻松构建物联网应用 在今天的数字时代,物联网和实时消息传递变得越来越重要。Golang,由Google推出的革命性编程语言,与MQTT,一个高效的物联网消息传输协议,共同为开发者带来了无数的机会。这篇文章将带你走进Golang和MQTT的世界,详细介绍如何实现二者的融合与应用。 1. 为什么选择Golang? Golang以其简洁、强大和高效的特性而脱颖而出,特别适合处理并发任务,是物联网项目的理想选择。 2. MQTT: 物联网的动力 MQTT的发布/订阅模式使其成为物联网领域的翘楚。它能够为联网设备提供实时、可靠的消息服务,广泛应用于各个行业。 3. 开启Golang与MQTT的旅程 我们将使用paho.mqtt.golang库,这是一个为Golang设计的高效MQTT客户端。 3.1 项目准备 确保你的系统安装了go1.13.12或更高版本。安装paho.mqtt.golang: go get github.com/eclipse/paho.mqtt.golang 3.2 连接到MQTT broker 我们选择EMQX提供的公共MQTT服务器,地址为broker.emqx.io。 package main import ( "fmt" mqtt "github.com/eclipse/paho.mqtt.golang" "time" ) var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { fmt.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic()) } var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) { fmt.Println("Connected") } var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) { fmt.Printf("Connect lost: %v", err) } func main() { var broker = "broker.emqx.io" var port = 1883 opts := mqtt.NewClientOptions() opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port)) opts.SetClientID("go_mqtt_client") opts.SetUsername("emqx") opts.SetPassword("public") opts.SetDefaultPublishHandler(messagePubHandler) opts.OnConnect = connectHandler opts.OnConnectionLost = connectLostHandler client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { panic(token.Error()) } } ClientOptions:用于设置 broker,端口,客户端 id ,用户名密码等选项 messagePubHandler:全局 MQTT pub 消息处理 connectHandler:连接的回调 connectLostHandler:连接丢失的回调 如果想使用 TLS 连接,可以如下设置: func NewTlsConfig() *tls.Config { certpool := x509.NewCertPool() ca, err := ioutil.ReadFile("ca.pem") if err != nil { log.Fatalln(err.Error()) } certpool.AppendCertsFromPEM(ca) // Import client certificate/key pair clientKeyPair, err := tls.LoadX509KeyPair("client-crt.pem", "client-key.pem") if err != nil { panic(err) } return &tls.Config{ RootCAs: certpool, ClientAuth: tls.NoClientCert, ClientCAs: nil, InsecureSkipVerify: true, Certificates: []tls.Certificate{clientKeyPair}, } } 如果不设置客户端证书,可以如下设置: func NewTlsConfig() *tls.Config { certpool := x509.NewCertPool() ca, err := ioutil.ReadFile("ca.pem") if err != nil { log.Fatalln(err.Error()) } certpool.AppendCertsFromPEM(ca) return &tls.Config{ RootCAs: certpool, } } 然后设置 TLS var broker = "broker.emqx.io" var port = 8883 opts := mqtt.NewClientOptions() opts.AddBroker(fmt.Sprintf("ssl://%s:%d", broker, port)) tlsConfig := NewTlsConfig() opts.SetTLSConfig(tlsConfig) // other options 3.3 MQTT消息发布与订阅 Golang与MQTT的结合使得消息发布和订阅变得轻而易举。 订阅 func sub(client mqtt.Client) { topic := "topic/test" token := client.Subscribe(topic, 1, nil) token.Wait() fmt.Printf("Subscribed to topic %s", topic) } 发布 func publish(client mqtt.Client) { num := 10 for i := 0; i < num; i++ { text := fmt.Sprintf("Message %d", i) token := client.Publish("topic/test", 0, false, text) token.Wait() time.Sleep(time.Second) } } 4. 深入理解:连接回调与安全性 当与broker的连接建立或断开时,执行相应的回调函数可以增加程序的健壮性。同时,为了数据安全,建议使用TLS连接。 5. 实战测试 通过以下代码,我们可以一目了然地了解如何在Golang中实现MQTT客户端的完整流程。 package main import ( "fmt" mqtt "github.com/eclipse/paho.mqtt.golang" "log" "time" ) var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { fmt.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic()) } var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) { fmt.Println("Connected") } var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) { fmt.Printf("Connect lost: %v", err) } func main() { var broker = "broker.emqx.io" var port = 1883 opts := mqtt.NewClientOptions() opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port)) opts.SetClientID("go_mqtt_client") opts.SetUsername("emqx") opts.SetPassword("public") opts.SetDefaultPublishHandler(messagePubHandler) opts.OnConnect = connectHandler opts.OnConnectionLost = connectLostHandler client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { panic(token.Error()) } sub(client) publish(client) client.Disconnect(250) } func publish(client mqtt.Client) { num := 10 for i := 0; i < num; i++ { text := fmt.Sprintf("Message %d", i) token := client.Publish("topic/test", 0, false, text) token.Wait() time.Sleep(time.Second) } } func sub(client mqtt.Client) { topic := "topic/test" token := client.Subscribe(topic, 1, nil) token.Wait() fmt.Printf("Subscribed to topic: %s", topic) } 运行代码,可以看到 MQTT 连接、订阅成功,并能成功收到订阅 topic 的消息 6. 结语 结合Golang的强大性能和MQTT的轻量级特点,为物联网应用开发提供了一个强大的解决方案。通过这篇文章,您应该已经掌握了如何使用Golang构建MQTT应用的基本知识,期待您在实际应用中创造更多的可能性。 本文旨在为读者提供真实、有价值的内容,如有任何建议或反馈,请随时与我们联系。 --- ### 203. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Java中的MQTT:深入实践与探索指南 随着物联网的快速发展,需要一个轻量级、高效和可靠的消息传递机制,而MQTT(Message Queuing Telemetry Transport)正好满足了这些需求。这篇文章将为您解开在Java中使用MQTT的奥秘,确保您能够快速入门并深入实践。 1. MQTT简介 MQTT是一种发布/订阅模式的消息传输协议,尤其适合低功耗设备和不稳定网络环境。它可以轻松处理设备间的消息通信,使物联网应用更为简洁。 2. 选择Java作为MQTT客户端的优势 Java是一个跨平台、稳定和安全的编程语言。其丰富的库和社区资源使得开发MQTT应用变得相对简单。 3. 开始之前 确保您的系统上已经安装了JDK 1.8或更高版本,并且配置了合适的Java环境。 4. 选择合适的库:Eclipse Paho Eclipse Paho Java Client是一个非常受欢迎的库,支持MQTT协议。为了在你的Maven项目中使用它,请添加以下依赖: <dependencies> <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.5</version> </dependency> </dependencies> 5. 构建MQTT客户端 连接到MQTT broker 首先,我们需要连接到一个MQTT broker。为了简化,这里使用一个公开的broker:broker.emqx.io。 String broker = "tcp://broker.emqx.io:1883"; // TLS/SSL // String broker = "ssl://broker.emqx.io:8883"; String username = "emqx"; String password = "public"; String clientid = "publish_client"; 然后创建 MQTT 客户端并连接。 MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); client.connect(options); 说明 MqttClient: 同步调用客户端,使用阻塞方法通信。 MqttClientPersistence: 代表一个持久的数据存储,用于在传输过程中存储出站和入站的信息,使其能够传递到指定的 QoS。 MqttConnectOptions: 连接选项,用于指定连接的参数,下面列举一些常见的方法。 setUserName: 设置用户名 setPassword: 设置密码 setCleanSession: 设置是否清除会话 setKeepAliveInterval: 设置心跳间隔 setConnectionTimeout: 设置连接超时时间 setAutomaticReconnect: 设置是否自动重连 6. 强化安全性:SSL/TLS连接 保证数据安全是非常关键的,建议使用SSL/TLS来连接到MQTT broker。要实现这一点,你需要确保broker支持SSL,并在客户端配置适当的证书和加密设置。 TLS/SSL 连接 如果要使用自签名证书进行 TLS/SSL 连接,需添加 bcpkix-jdk15on 到 pom.xml 文件。 <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.70</version> </dependency> 然后使用如下代码创建 SSLUtils.java 文件。 package io.emqx.mqtt; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileReader; import java.security.KeyPair; import java.security.KeyStore; import java.security.Security; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; public class SSLUtils { public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile, final String password) throws Exception { Security.addProvider(new BouncyCastleProvider()); // load CA certificate X509Certificate caCert = null; FileInputStream fis = new FileInputStream(caCrtFile); BufferedInputStream bis = new BufferedInputStream(fis); CertificateFactory cf = CertificateFactory.getInstance("X.509"); while (bis.available() > 0) { caCert = (X509Certificate) cf.generateCertificate(bis); } // load client certificate bis = new BufferedInputStream(new FileInputStream(crtFile)); X509Certificate cert = null; while (bis.available() > 0) { cert = (X509Certificate) cf.generateCertificate(bis); } // load client private key PEMParser pemParser = new PEMParser(new FileReader(keyFile)); Object object = pemParser.readObject(); JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); KeyPair key = converter.getKeyPair((PEMKeyPair) object); pemParser.close(); // CA certificate is used to authenticate server KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType()); caKs.load(null, null); caKs.setCertificateEntry("ca-certificate", caCert); TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); tmf.init(caKs); // client key and certificates are sent to server so it can authenticate KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(null, null); ks.setCertificateEntry("certificate", cert); ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert}); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory .getDefaultAlgorithm()); kmf.init(ks, password.toCharArray()); // finally, create SSL socket factory SSLContext context = SSLContext.getInstance("TLSv1.2"); context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); return context.getSocketFactory(); } } 参照如下设置 options。 // 设置 SSL/TLS 连接地址 String broker = "ssl://broker.emqx.io:8883"; // 设置 socket factory String caFilePath = "/cacert.pem"; String clientCrtFilePath = "/client.pem"; String clientKeyFilePath = "/client.key"; SSLSocketFactory socketFactory = getSocketFactory(caFilePath, clientCrtFilePath, clientKeyFilePath, ""); options.setSocketFactory(socketFactory); 发布 MQTT 消息 创建一个发布客户端类 PublishSample,该类将发布一条 Hello MQTT 消息至主题 mqtt/test。 package io.emqx.mqtt; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; public class PublishSample { public static void main(String[] args) { String broker = "tcp://broker.emqx.io:1883"; String topic = "mqtt/test"; String username = "emqx"; String password = "public"; String clientid = "publish_client"; String content = "Hello MQTT"; int qos = 0; try { MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); // 连接参数 MqttConnectOptions options = new MqttConnectOptions(); // 设置用户名和密码 options.setUserName(username); options.setPassword(password.toCharArray()); options.setConnectionTimeout(60); options.setKeepAliveInterval(60); // 连接 client.connect(options); // 创建消息并设置 QoS MqttMessage message = new MqttMessage(content.getBytes()); message.setQos(qos); // 发布消息 client.publish(topic, message); System.out.println("Message published"); System.out.println("topic: " + topic); System.out.println("message content: " + content); // 关闭连接 client.disconnect(); // 关闭客户端 client.close(); } catch (MqttException e) { throw new RuntimeException(e); } } } 订阅 MQTT 主题 创建一个订阅客户端类 SubscribeSample,该类将订阅主题 mqtt/test。 package io.emqx.mqtt; import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; public class SubscribeSample { public static void main(String[] args) { String broker = "tcp://broker.emqx.io:1883"; String topic = "mqtt/test"; String username = "emqx"; String password = "public"; String clientid = "subscribe_client"; int qos = 0; try { MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); // 连接参数 MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); options.setConnectionTimeout(60); options.setKeepAliveInterval(60); // 设置回调 client.setCallback(new MqttCallback() { public void connectionLost(Throwable cause) { System.out.println("connectionLost: " + cause.getMessage()); } public void messageArrived(String topic, MqttMessage message) { System.out.println("topic: " + topic); System.out.println("Qos: " + message.getQos()); System.out.println("message content: " + new String(message.getPayload())); } public void deliveryComplete(IMqttDeliveryToken token) { System.out.println("deliveryComplete---------" + token.isComplete()); } }); client.connect(options); client.subscribe(topic, qos); } catch (Exception e) { e.printStackTrace(); } } } MqttCallback 说明: connectionLost(Throwable cause): 连接丢失时被调用 messageArrived(String topic, MqttMessage message): 接收到消息时被调用 deliveryComplete(IMqttDeliveryToken token): 消息发送完成时被调用 测试 接下来运行 SubscribeSample,订阅 mqtt/test 主题。 然后运行 PublishSample,发布消息到 mqtt/test 主题。 我们将会看到发布端成功发布消息,同时订阅端接收到消息。 8. 总结 MQTT在Java中的实现变得更为简单,感谢丰富的库和工具。通过本指南,您应该能够构建一个基本的MQTT客户端,并对其进行扩展以满足更复杂的需求。 希望这篇文章为您提供了宝贵的知识和实践指南! --- ### 204. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT简介 MQTT(Message Queuing Telemetry Transport)是一种轻量级的通信协议,设计用于在低带宽和不稳定的网络环境中传输消息。它最初由IBM开发,用于连接远程设备和传感器到网络,并支持发布/订阅模型的消息通信。MQTT被广泛用于物联网(IoT)领域,其中大量的设备需要进行实时通信和数据交换。它采用了一种发布/订阅(publish/subscribe)模型,其中消息的发送者(发布者)将消息发布到特定的主题(topic),而订阅者可以选择性地订阅感兴趣的主题,以接收相应的消息。 MQTT特点 以下是MQTT的一些关键特点:轻量级:MQTT的设计非常轻量,协议头部非常小,传输的数据量很小,适用于带宽有限的网络环境,如低速、高延迟或不稳定的网络。简单:MQTT的协议规范相对简单,易于实现和部署。它定义了少量的消息类型和协议操作,使得开发人员可以快速上手。异步通信:MQTT使用异步通信模式,发布者发送消息后,不需要等待接收者的响应,可以继续执行其他操作。这种异步通信模式适合在资源有限的设备和网络中工作。可靠性:MQTT支持三种不同的消息传递质量(QoS)级别:QoS 0(至多一次),QoS 1(至少一次)和QoS 2(只有一次)。这使得可以根据应用程序的要求选择适当的消息交付保证级别。网络状况适应性:MQTT可以适应不稳定的网络状况,如网络中断、重连等。它具有断开连接后自动重连的机制,可以确保消息的可靠传输。 订阅和发布模型 Publisher(发布者):发布者是消息的发送者,它将消息发布到特定的主题(topic)上。可以有一个或多个发布者。Subscriber(订阅者):订阅者是对消息感兴趣的实体,它选择性地订阅一个或多个主题。一旦订阅了主题,它就会接收到相应的消息。MQTT Broker(MQTT代理):MQTT代理是中间件,负责接收发布者发送的消息,并将其路由到对应的订阅者。它维护着主题和订阅关系的注册表,并确保消息的可靠传递。 工作流程如下: 发布者将消息发布到特定的主题上。MQTT代理接收到消息后,根据订阅者的注册信息,将消息路由到对应的订阅者。订阅者接收到发布者发布的消息,并进行相应的处理。通过发布/订阅模型,MQTT允许实现解耦和灵活性,发布者和订阅者之间不需要直接的点对点连接,而是通过MQTT代理进行中转和路由。这种模型非常适合在物联网中进行大规模设备间的通信和数据交换。 MQTT QoS MQTT(Message Queuing Telemetry Transport)协议支持三种不同的QoS(Quality of Service)级别,用于控制消息的可靠性和传输保证。以下是MQTT的三个QoS级别: QoS 0(至多一次): 在QoS 0级别下,消息以“至多一次”传输,没有确认机制。消息被发布后,发布者不会接收到关于消息是否成功传输或交付的确认。MQTT代理会尽最大努力将消息传输给订阅者,但可能会出现消息丢失或重复的情况。此级别适用于对消息传输的可靠性要求不高的场景,如传感器数据的临时更新等。 QoS 1(至少一次): 在QoS 1级别下,消息以“至少一次”传输,确保至少传输一次。发布者发送消息后,会等待MQTT代理发送确认消息(PUBACK)来确认消息的接收。如果发布者没有收到确认消息,它会再次发送相同的消息,直到收到确认为止。MQTT代理会确保消息至少传输一次给订阅者,但可能会出现重复传输的情况。此级别适用于对消息传输的可靠性要求较高的场景,如控制指令的传递。 QoS 2(只有一次): 在QoS 2级别下,消息以“只有一次”传输,确保仅传输一次。发布者发送消息后,会等待MQTT代理发送两个确认消息(PUBREC和PUBCOMP)来确认消息的接收和完成。MQTT代理会确保消息仅传输一次给订阅者,没有重复传输的情况。此级别提供了最高的消息传输可靠性,但也伴随着更高的网络开销。此级别适用于对消息传输的可靠性要求非常高的场景,如金融交易或严格的数据同步。选择合适的QoS级别取决于应用程序对消息传输可靠性和网络开销的要求。更高的QoS级别提供了更可靠的传输,但同时也增加了网络开销。因此,需要根据具体场景的需求来选择适当的级别。 OpenWrt中使用mosquitto 插件安装 默认是没有包含mosquitto客户端和broker的,我们可以手动安装相关插件,为了测试我们需要安装broker和client 首先更新openwrt软件源 opkg update 然后调用以下命令分别安装mosquitto broker和client,这里我们选用nossl版本,也就是不需要ssl加密,方便测试 opkg install mosquitto-nossl opkg install mosquitto-client-nossl mosquitto服务 安装完成后就可以使用broker和client了,首先我们需要启动mosquitto broker服务, mosquitto broker服务配置文件在/etc/mosquitto/目录中,我们可以修改服务器相关信息,比如监听端口号、接口、ip地址等。 root@OpenWrt:~# ls /etc/mosquitto/mosquitto.conf /etc/mosquitto/mosquitto.conf root@OpenWrt:~# mosquitto客户端 mosquitto客户端包含sub和pub两部分,分别用于订阅和发布 订阅主题: mosquitto_sub -h <MQTT Broker IP> -p <MQTT Broker Port> -t <Topic> 其中,是MQTT Broker的IP地址,是MQTT Broker的端口号,是要订阅的主题名称。示例: mosquitto_sub -h 192.168.1.1 -p 1883 -t test/topic 发布主题: mosquitto_pub -h <MQTT Broker IP> -p <MQTT Broker Port> -t <Topic> -m <Message> 其中,是MQTT Broker的IP地址,是MQTT Broker的端口号,是要发布的主题名称,是要发布的消息内容。示例: mosquitto_pub -h 192.168.1.1 -p 1883 -t test/topic -m "Hello, MQTT!" 运行结果: 由于订阅和发布客户端都在本地,ip使用localhost地址127.0.0.1 root@OpenWrt:~# mosquitto_sub -h 127.0.0.1 -p 1883 -t test/topic & root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t test/topic -m "hello MQTT." root@OpenWrt:~# hello MQTT. 在订阅主题时,我们还可以使用通配符,最常用就是通配符"#",通过"#"可以匹配多级topic 比如订阅了主题"test/#",则可以收到"test/"开头的所有topic,比如"test/topic1"、"test/hello"等 以下实例中分别订阅了"test/#"和"test/topic1",当发布"test/topic1"消息时,二者都可以收到,而发布"test/topic2"时只有一个可以收到。 除了通配符"#"之外,还有"$"、"+"等通配符,不在这里详解。使用云端公共broker测试 emqx提供了公共免费的broker供开发者测试,注意不要在生产环境使用,仅供测试 我们可以准备两台不同的设备,都连接broker.emqx.io,这两台设备可以在不同区域,通过公网broker可以轻松实现两台设备通信。●客户端1 客户端1订阅openwrt/topic消息 mosquitto_sub -h broker.emqx.io -p 1883 -i client_001 -t openwrt/topic ●客户端2 发送一条消息到主题openwrt/topic,这样客户端1就可以收到该消息 mosquitto_pub -h broker.emqx.io -p 1883 -t openwrt/topic -i client_002 -m "hello client1, i am froms client2" OpenWrt中基于libmosquitto开发 前面给大家演示了mosquitto客户端的使用,但命令行客户端仅供测试使用,我们在开发过程中需要自定义消息并且能够实时解析消息,而通过命令行就没那么方便消息的处理了,需要调用mosquitto底层api接口实现想要的功能。 libmosquitto库 在openwrt系统中默认集成了mosquitto库,可以直接依赖调用。 对应依赖的库为: libmosquitto-nossl 不支持ssl加密 libmosquitto 支持ssl加密。 api接口详解 mosquitto_lib_init:初始化libmosquitto库。在使用其他libmosquitto函数之前,应该首先调用此函数。mosquitto_lib_version:获取libmosquitto库的版本号信息。mosquitto_new:创建一个新的mosquitto对象(MQTT客户端)。mosquitto_connect:与MQTT代理服务器建立连接。mosquitto_disconnect:断开与MQTT代理服务器的连接。mosquitto_publish:向指定主题发布消息。mosquitto_subscribe:订阅一个或多个主题。mosquitto_unsubscribe:取消订阅一个或多个主题。mosquitto_loop_start:启动一个线程来处理MQTT消息循环。mosquitto_loop_forever:开始一个阻塞的循环,处理MQTT消息。mosquitto_loop:在非阻塞模式下处理MQTT消息。mosquitto_message_callback_set:设置用于接收订阅消息的回调函数。mosquitto_username_pw_set:设置连接时使用的用户名和密码。mosquitto_tls_set:为MQTT连接启用SSL/TLS加密。mosquitto_tls_opts_set:设置SSL/TLS选项,如CA证书、客户端证书和私钥等。mosquitto_tls_insecure_set:设置是否允许SSL/TLS连接中的不安全选项。mosquitto_will_set:设置遗嘱消息,即在客户端异常断开时发布的消息。 基于libmosquitto实现一个消息订阅程序 源码 #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <mosquitto.h> #include <sys/time.h> #include <sys/sysinfo.h> struct mosquitto *g_test_mosq = NULL; void mqtt_connect_callback(struct mosquitto *mosq, void *userdata, int result) { printf("connect to mqtt server ok\n"); if (MOSQ_ERR_SUCCESS != mosquitto_subscribe(mosq, NULL, "openwrt/#", 0)) { printf("sub topic openwrt/# failed...\n"); } else{ printf("sub topic openwrt/# failed...\n"); } } void mqtt_disconnect_callback(struct mosquitto *mosq, void *userdata, int result) { if (result) printf("disconnect %s\n", mosquitto_connack_string(result)); else printf("disconnect from mqtt server.\n"); } void mqtt_sub_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos) { printf("sub callback\n"); } void mqtt_msg_callback(struct mosquitto *mosq, void *userdata, struct mosquitto_message *message) { printf("callback recv mqtt msg, topic = %s, payload = %s\n", message->topic, message->payload); } struct mosquitto *connect_to_mqtt_server(char *server_ip) { struct mosquitto *mosq = NULL; int rc; char mqtt_user[128] = {0}; char mqtt_pwd[128] = {0}; char client_id[128] = {0}; struct timeval tv; gettimeofday(&tv, NULL); mosquitto_lib_init(); snprintf(client_id, sizeof(client_id), "test_%d", tv.tv_sec); printf("connect to mqtt server..client_id=%s\n", client_id); mosq = mosquitto_new(client_id, true, NULL); if (!mosq) { return NULL; } #if 0 rc = mosquitto_username_pw_set(mosq, "test", "test"); if (rc) { mosquitto_destroy(mosq); return NULL; } #endif mosquitto_connect_callback_set(mosq, mqtt_connect_callback); mosquitto_message_callback_set(mosq, mqtt_msg_callback); mosquitto_subscribe_callback_set(mosq, mqtt_sub_callback); mosquitto_disconnect_callback_set(mosq, mqtt_disconnect_callback); rc = mosquitto_connect(mosq, server_ip, 1883, 30); if (rc) { printf("Unable to connect mqtt server rc=%d\n", rc); mosquitto_destroy(mosq); return NULL; } return mosq; } int mqtt_bcast_msg(char *api, char *data, int len) { char topic[128] = {0}; int mid; if (!api || !data || len == 0) return -1; if (!g_test_mosq) return -1; sprintf(topic, "openwrt/%s", api); return mosquitto_publish(g_test_mosq, &mid, topic, len, data, 0, 0); } int main(int argc, char *argv[]){ char *host = NULL; if (argc < 2){ host = "127.0.0.1"; printf("use default ip: 127.0.0.1\n"); } else{ host = argv[1]; printf("use ip: %s\n", host); } g_test_mosq = connect_to_mqtt_server(host); if (!g_test_mosq){ printf("connect to server %s failed\n", host); exit(0); } mosquitto_loop_forever(g_test_mosq, -1, 1); mosquitto_destroy(g_test_mosq); mosquitto_lib_cleanup(); return 0; } 实例源码编译 将源码包拷贝到openwrt源码package目录 开启mqtt_test宏并生成默认依赖配置 echo "CONFIG_PACKAGE_mqtt_test=y" >>.config make defconfig 编译 make package/mqtt_test/compile V=s 插件安装: mqtt_test依赖了libmosquitto库,而libmosquitto依赖了libcares,所以需要安装三个插件●libcares●libmosquitto-nossl●mqtt_test将插件通过winscp或其他工具上传到openwrt系统中,执行以下命令安装(以X86为例) opkg install libcares_1.18.1-1_x86_64.ipk opkg install libmosquitto-nossl_2.0.15-1_x86_64.ipk opkg install mqtt_test_1.0-1_x86_64.ipk 运行:mqtt_test默认连接本地broker,也可以指定ip运行如果出现错误,表示服务器没有启动或者参数异常,请先确认mosquitto服务已经启动。 use default ip: 127.0.0.1 connect to mqtt server..client_id=test_1686993389 Unable to connect mqtt server rc=14 connect to server 127.0.0.1 failed 运行成功 root@OpenWrt:~# mqtt_test use default ip: 127.0.0.1 connect to mqtt server..client_id=test_1686993598 connect to mqtt server ok sub callback 现在就启动了一个mqtt客户端,订阅了openwrt/# 通过mosquitto_pub工具可以发送指令到该客户端,客户端当前处理方式是输出收到的消息,当然实际开发是解析指令并执行对应的命令,比如接收到reboot命令后执行重启。 pub命令如下: root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t openwrt/send_msg -m "hello openwrt" root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t openwrt/send_msg -m "你好" root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t openwrt/send_msg -m "你好" root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t openwrt/send_msg -m "reboot" root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t openwrt/send_msg -m "reboot" 客户端输出如下: callback recv mqtt msg, topic = openwrt/send_msg, payload = hello openwrt callback recv mqtt msg, topic = openwrt/send_msg, payload = 你好 callback recv mqtt msg, topic = openwrt/send_msg, payload = 你好 callback recv mqtt msg, topic = openwrt/send_msg, payload = reboot callback recv mqtt msg, topic = openwrt/send_msg, payload = reboot 如果客户端连接云端的broker,就可以实现远程操作设备,比如远程重启设备、配置下发等。 总结 在物联网开发中我们会经常用的MQTT协议,常见的就是边缘设备和云端通信,上报实时状态、远程管理等,当然也可以局域网间通信,实现节点间通信,比如可以通过MQTT协议实现mesh数据同步、AC集中管理等,有了MQTT协议我们不需要自己通过底层socket实现私有协议,可以只关注业务处理,可大大提高程序稳定性。 --- ### 205. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 https://github.com/mgdm/Mosquitto-PHP Mosquitto-PHP是一个用于与MQTT(Message Queuing Telemetry Transport)协议交互的PHP扩展,它允许PHP应用程序通过MQTT与消息代理进行通信。以下是有关Mosquitto-PHP的一些关键信息: 1. Mosquitto-PHP扩展介绍: Mosquitto-PHP是一个PHP扩展,它提供了与Eclipse Mosquitto MQTT客户端库的集成,使PHP开发者能够轻松地编写MQTT客户端应用程序。 2. PHP 7支持: Mosquitto-PHP扩展已更新以支持PHP 7版本,这意味着它可以在PHP 7及更高版本上运行。这扩展的PHP 7支持得益于Sara Golemon的工作。 3. 扩展要求: PHP版本要求:Mosquitto-PHP扩展要求PHP 5.3及更高版本。 libmosquitto版本要求:它需要使用libmosquitto库的1.2.x版本或更高版本。 支持的操作系统:通常在Linux和Mac OS X上工作,但未明确支持Windows。不过,欢迎开发人员提交Windows支持的贡献。 4. 安装Mosquitto-PHP: 您可以使用PECL来安装Mosquitto-PHP扩展。例如,使用以下命令来安装: pecl install Mosquitto-alpha 或者,您也可以使用传统的扩展构建过程来手动构建和安装它: phpize ./configure --with-mosquitto=/path/to/libmosquitto make make install 最后,将extension=mosquitto.so添加到您的php.ini文件中以启用扩展。 5. 使用Mosquitto-PHP: Mosquitto-PHP允许您以异步方式与MQTT代理进行交互。您需要使用回调函数来处理连接、发布、订阅和消息接收等事件。 例如,以下是如何正确发布QoS为2的消息的示例: use Mosquitto\Client; $mid = 0; $c = new Mosquitto\Client("PHP"); $c->onConnect(function() use ($c, &$mid) { $mid = $c->publish("mgdm/test", "Hello", 2); }); $c->onPublish(function($publishedId) use ($c, $mid) { if ($publishedId == $mid) { $c->disconnect(); } }); $c->connect("localhost"); $c->loopForever(); 您可以根据具体的MQTT应用程序要求,使用Mosquitto-PHP来创建定制的MQTT客户端。 总之,Mosquitto-PHP扩展使PHP开发者能够轻松地与MQTT代理进行通信,这对于构建物联网(IoT)应用程序和其他需要实时消息传递的应用程序非常有用。您可以使用它来连接、发布、订阅和处理MQTT消息。 event.php <?php $c = new Mosquitto\Client(); $c->onConnect(function($code, $message) { echo "I'm connected\n"; }); $c->connect('localhost', 1883, 60); $c->subscribe('#', 1); $c->onMessage(function($m) { var_dump($m); }); $socket = $c->getSocket(); $base = new EventBase(); $ev = new Event($base, $socket, Event::READ | Event::PERSIST, 'cb', $base); function cb($fd, $what, $arg) { global $c; echo "Triggered\n"; var_dump(func_get_args()); $c->loop(); } $ev->add(); $base->dispatch(); 这段 PHP 代码演示了如何使用 Mosquitto-PHP 扩展与 MQTT 服务器进行通信,并使用 libevent 库创建一个事件驱动的应用程序。以下是对代码的详细解释: 创建 Mosquitto 客户端对象: $c = new Mosquitto\Client(); 在这里,您创建了一个 Mosquitto 客户端对象 $c。 设置连接回调函数: $c->onConnect(function($code, $message) { echo "I'm connected\n"; }); 这个回调函数会在成功连接到 MQTT 服务器时执行,它简单地打印出 "I'm connected"。 连接到 MQTT 服务器: $c->connect('localhost', 1883, 60); 这行代码连接到 MQTT 服务器,指定了服务器的主机名为 'localhost',端口号为 1883,超时时间为 60 秒。 订阅 MQTT 主题: $c->subscribe('#', 1); 这里使用 subscribe 方法订阅了 MQTT 主题 '#',表示订阅所有主题。第二个参数 1 表示使用 QoS 1 等级。 设置接收消息的回调函数: $c->onMessage(function($m) { var_dump($m); }); 这个回调函数将在接收到 MQTT 消息时执行,它简单地使用 var_dump 打印消息内容。 获取 Mosquitto 客户端的套接字: $socket = $c->getSocket(); 这里通过 $c->getSocket() 获取 Mosquitto 客户端的套接字,以便后续在 libevent 中使用。 创建 libevent 基础对象和事件对象: $base = new EventBase(); $ev = new Event($base, $socket, Event::READ | Event::PERSIST, 'cb', $base); 这里创建了 libevent 基础对象 $base 和事件对象 $ev。事件对象监听 Mosquitto 客户端套接字的可读事件,并在事件触发时调用 'cb' 函数。 定义事件触发后的回调函数: function cb($fd, $what, $arg) { global $c; echo "Triggered\n"; var_dump(func_get_args()); $c->loop(); } 这是事件触发后执行的回调函数 'cb'。它会在事件触发时打印 "Triggered" 和一些调试信息,然后调用 Mosquitto 客户端的 loop 方法来处理 MQTT 消息。 将事件对象添加到 libevent 循环: $ev->add(); 这行代码将事件对象 $ev 添加到 libevent 的事件循环中,以便监听 Mosquitto 客户端套接字的可读事件。 启动 libevent 事件循环: $base->dispatch(); 最后,这行代码启动 libevent 的事件循环,使其开始监听事件并执行回调函数。这将允许 Mosquitto 客户端接收和处理 MQTT 消息。 总之,这段代码创建了一个 Mosquitto 客户端,连接到 MQTT 服务器,订阅所有主题,并使用 libevent 库实现了一个事件驱动的应用程序,该应用程序能够异步接收和处理 MQTT 消息。当 Mosquitto 客户端接收到消息时,会触发 libevent 事件,然后执行回调函数来处理消息。 pub.php <?php $client = new Mosquitto\Client(); $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->connect("localhost", 1883, 5); $client->subscribe('/#', 1); while (true) { $client->loop(); $mid = $client->publish('/hello', "Hello from PHP at " . date('Y-m-d H:i:s'), 1, 0); echo "Sent message ID: {$mid}\n"; $client->loop(); sleep(2); } $client->disconnect(); unset($client); function connect($r) { echo "I got code {$r}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function message($message) { printf("Got a message ID %d on topic %s with payload:\n%s\n\n", $message->mid, $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } 这段 PHP 代码演示了如何使用 Mosquitto-PHP 扩展与 MQTT 服务器进行通信以及订阅和发布 MQTT 消息。以下是代码的详细解释: 创建 Mosquitto 客户端对象: $client = new Mosquitto\Client(); 在这里,您创建了一个 Mosquitto 客户端对象 $client。 设置连接、订阅、消息和断开连接的回调函数: $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); 这些回调函数分别用于处理连接成功时的事件('connect')、断开连接时的事件('disconnect')、订阅主题时的事件('subscribe')、接收到消息时的事件('message')。 连接到 MQTT 服务器: $client->connect("localhost", 1883, 5); 这行代码连接到 MQTT 服务器,指定了服务器的主机名为 'localhost',端口号为 1883,超时时间为 5 秒。 订阅 MQTT 主题: $client->subscribe('/#', 1); 这里使用 subscribe 方法订阅了 MQTT 主题 '/#',表示订阅所有以 '/' 开头的主题。第二个参数 1 表示使用 QoS 1 等级。 进入循环并发送消息: while (true) { $client->loop(); $mid = $client->publish('/hello', "Hello from PHP at " . date('Y-m-d H:i:s'), 1, 0); echo "Sent message ID: {$mid}\n"; $client->loop(); sleep(2); } 这个 while 循环会持续运行,其中包含了 Mosquitto 客户端的 loop 方法,以便处理 MQTT 消息和事件。在循环中,它会使用 publish 方法发布一条带有时间戳的消息到主题 '/hello'。然后等待 2 秒继续下一轮循环。 断开连接和清理: $client->disconnect(); unset($client); 最后,代码在循环结束后手动断开了与 MQTT 服务器的连接,并释放了 Mosquitto 客户端对象。 回调函数的定义: function connect($r) { echo "I got code {$r}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function message($message) { printf("Got a message ID %d on topic %s with payload:\n%s\n\n", $message->mid, $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } 这些回调函数分别用于处理连接成功、订阅成功、接收到消息和断开连接的事件。在这些函数中,您可以自定义处理逻辑以响应不同事件。 总之,这段代码创建了一个 Mosquitto 客户端,连接到 MQTT 服务器,订阅主题,并周期性地发布消息。它还设置了回调函数来处理不同的事件,使您能够根据需要自定义处理逻辑。最后,代码手动断开了连接并清理资源。 subclass.php <?php class MyClient extends Mosquitto\Client { protected $pendingSubs = []; protected $grantedSubs = []; protected $subscribeCallback = null; public function __construct($id = null, $cleanSession = false) { parent::__construct($id, $cleanSession); parent::onSubscribe(array($this, 'subscribeHandler')); } public function subscribeHandler($mid, $qosCount, $grantedQos) { if (!isset($this->pendingSubs[$mid])) { return; } $topic = $this->pendingSubs[$mid]; $this->grantedSubs[$topic] = $grantedQos; echo "Subscribed to topic {$topic} with message ID {$mid}\n"; if (is_callable($this->subscribeCallback)) { $this->subscribeCallback($mid, $qosCount, $grantedQos); } } public function subscribe($topic, $qos) { $mid = parent::subscribe($topic, $qos); $this->pendingSubs[$mid] = $topic; } public function onSubscribe(callable $callable) { $this->subscribeCallback = $callable; } public function getSubscriptions() { return $this->grantedSubs; } } $c = new MyClient('subscriptionTest'); $c->onSubscribe(function() { echo "Hello, I got subscribed\n"; }); $c->connect('localhost', 1883, 50); $c->subscribe('#', 1); for ($i = 0; $i < 5; $i++) { $c->loop(10); } var_dump($c->getSubscriptions()); 这段 PHP 代码演示了如何创建一个自定义的 Mosquitto 客户端类 MyClient,该类继承了 Mosquitto 客户端,并添加了一些自定义功能。以下是代码的详细解释: 创建自定义 Mosquitto 客户端类 MyClient: class MyClient extends Mosquitto\Client { // ... } 在这里,您创建了一个名为 MyClient 的类,它继承自 Mosquitto 客户端。 构造函数 __construct: public function __construct($id = null, $cleanSession = false) { parent::__construct($id, $cleanSession); parent::onSubscribe(array($this, 'subscribeHandler')); } 在构造函数中,您首先调用了父类(Mosquitto 客户端)的构造函数,并注册了 subscribeHandler 方法作为订阅事件的回调函数。 订阅处理函数 subscribeHandler: public function subscribeHandler($mid, $qosCount, $grantedQos) { // ... } 这个方法会在成功订阅主题时被调用。它会处理订阅事件的回调,并将订阅的主题和相应的 QoS 存储到 grantedSubs 数组中。然后,它会触发 subscribeCallback 回调函数(如果已设置)。 订阅主题方法 subscribe: public function subscribe($topic, $qos) { $mid = parent::subscribe($topic, $qos); $this->pendingSubs[$mid] = $topic; } 这个方法用于订阅主题,并将主题和消息 ID 存储到 pendingSubs 数组中。 设置订阅回调方法 onSubscribe: public function onSubscribe(callable $callable) { $this->subscribeCallback = $callable; } 这个方法允许您设置订阅事件的回调函数,以便在订阅时执行自定义逻辑。 获取订阅信息方法 getSubscriptions: public function getSubscriptions() { return $this->grantedSubs; } 这个方法用于获取已订阅的主题及其对应的 QoS。 创建 MyClient 对象,设置回调和执行订阅: $c = new MyClient('subscriptionTest'); $c->onSubscribe(function() { echo "Hello, I got subscribed\n"; }); $c->connect('localhost', 1883, 50); $c->subscribe('#', 1); 在这里,您创建了一个 MyClient 对象,并设置了订阅回调函数。然后,连接到 MQTT 服务器,订阅了以 '#' 开头的所有主题。 使用 loop 方法运行客户端循环: for ($i = 0; $i < 5; $i++) { $c->loop(10); } 这个循环允许客户端运行,并处理 MQTT 消息和事件。loop(10) 意味着每次循环会等待 10 毫秒来处理事件。 获取订阅信息并输出: var_dump($c->getSubscriptions()); 最后,您使用 getSubscriptions 方法获取已订阅的主题信息,并将其输出。 总之,这段代码演示了如何创建自定义的 Mosquitto 客户端类,以处理 MQTT 订阅事件,并提供了一些自定义功能,例如获取已订阅的主题信息和设置订阅回调函数。这使您能够更灵活地与 MQTT 服务器进行通信和处理订阅。 test.php <?php $client = new Mosquitto\Client(); $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->connect("localhost", 1883, 5); $client->onLog('logger'); $client->subscribe('#', 1); for ($i = 0; $i < 10; $i++) { $client->loop(); } $client->unsubscribe('#'); for ($i = 0; $i < 10; $i++) { $client->loop(); } function connect($r, $message) { echo "I got code {$r} and message {$message}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function unsubscribe() { echo "Unsubscribed from a topic\n"; } function message($message) { printf("Got a message on topic %s with payload:\n%s\n", $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } function logger() { var_dump(func_get_args()); } 这段 PHP 代码演示了如何使用 Mosquitto 客户端库与 MQTT 代理(通常在 localhost 上运行)进行通信,并定义了一些回调函数来处理不同的 MQTT 事件。以下是这段代码的详细解释: 1. 创建 Mosquitto 客户端对象: $client = new Mosquitto\Client(); 这行代码创建了一个 Mosquitto 客户端对象,用于连接到 MQTT 代理并执行 MQTT 操作。 2. 设置回调函数: $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->onLog('logger'); 这些行设置了不同事件的回调函数。当客户端连接成功时,onConnect 回调函数将被调用,当客户端断开连接时,onDisconnect 回调函数将被调用,以此类推。这些回调函数会在后面的代码中定义。 3. 连接到 MQTT 代理: $client->connect("localhost", 1883, 5); 这行代码连接到本地 MQTT 代理,通常运行在 localhost 主机的 1883 端口上。连接的超时时间设置为 5 秒。 4. 订阅 MQTT 主题: $client->subscribe('#', 1); 这行代码订阅了名为 # 的 MQTT 主题,这个特殊的主题表示订阅所有主题。订阅的 QoS(服务质量)级别设置为 1。 5. 运行 MQTT 客户端循环: for ($i = 0; $i < 10; $i++) { $client->loop(); } 这个循环运行 MQTT 客户端,允许它接收和处理来自 MQTT 代理的消息以及触发不同事件的回调函数。 6. 取消订阅 MQTT 主题: $client->unsubscribe('#'); 这行代码取消订阅之前订阅的 # 主题,即停止接收与该主题相关的消息。 7. 再次运行 MQTT 客户端循环: for ($i = 0; $i < 10; $i++) { $client->loop(); } 这段代码再次运行 MQTT 客户端循环,确保处理所有取消订阅后的事件。 8. 定义各种事件回调函数: 下面是定义的不同事件的回调函数: connect($r, $message):当客户端成功连接到 MQTT 代理时,此回调被调用,显示连接结果代码 $r 和消息 $message。 subscribe():当客户端成功订阅主题时,此回调被调用,显示 "Subscribed to a topic"。 unsubscribe():当客户端成功取消订阅主题时,此回调被调用,显示 "Unsubscribed from a topic"。 message($message):当客户端接收到新消息时,此回调被调用,显示消息的主题和有效载荷。 disconnect():当客户端与 MQTT 代理断开连接时,此回调被调用,显示 "Disconnected cleanly"。 logger():此回调用于记录日志信息,它将输出回调函数的所有参数。 总之,这段代码创建了一个 MQTT 客户端并设置了回调函数,然后连接到 MQTT 代理,订阅主题,运行客户端循环以接收消息和处理事件,并在不同的事件发生时触发相应的回调函数,从而实现了 MQTT 通信。这对于与 MQTT 代理进行互动和处理消息非常有用。 testOnpublish.php <?php class MQ { public static $publish = array(); public static $receive = array(); public static function addPublish($mid, $msg) { $msg->id = $mid; self::$publish[$mid] = $msg; } public static function confirm($mid) { if(array_key_exists($mid, self::$publish)) { self::$publish[$mid]->state = true; } } public static function addReceive($msg) { $msg = Message::factory($msg, true); self::$receive[$msg->id] = $msg; } } class Message { public $id; public $state = false; public $msg; public static function factory(Mosquitto\Message $msg, $state = false) { $message = new Message(); $message->state = $state; $message->msg = $msg; $message->id = $msg->mid; return $message; } } $client = new Mosquitto\Client('client.terminal.onpublish', false); $client->onMessage(function($msg) { print_r(array('receive', $msg)); MQ::addReceive($msg); }); $client->onPublish(function($mid) { MQ::confirm($mid); print_r(array('comfirm publish', MQ::$publish[$mid])); }); $client->onConnect(function($rc, $msg) { print_r(array('rc' => $rc, 'message' => $msg)); }); $client->connect('localhost', 1883, 60); sleep(1); $client->subscribe('/test/publish', 1); $msg = Message::factory(new Mosquitto\Message()); $msg->msg->topic = '/test/publish'; $msg->msg->payload = 'hello from on publish'; $msg->msg->qos = 1; $mid = $client->publish($msg->msg->topic, $msg->msg->payload, $msg->msg->qos); print_r(array('publish', $msg)); MQ::addPublish($mid, $msg); sleep(1); $client->loopForever(); 这段PHP代码演示了如何使用Mosquitto客户端库创建一个MQTT客户端,该客户端具有自定义的消息确认和处理机制。以下是代码的详细解释: 1. 创建MQ类: class MQ { public static $publish = array(); public static $receive = array(); public static function addPublish($mid, $msg) { $msg->id = $mid; self::$publish[$mid] = $msg; } public static function confirm($mid) { if(array_key_exists($mid, self::$publish)) { self::$publish[$mid]->state = true; } } public static function addReceive($msg) { $msg = Message::factory($msg, true); self::$receive[$msg->id] = $msg; } } 这个类用于管理发布和接收的消息。它包括以下方法: addPublish($mid, $msg):将发布的消息添加到 $publish 数组中,以便稍后进行确认。 confirm($mid):确认已发布的消息,将其状态标记为已确认。 addReceive($msg):将接收的消息添加到 $receive 数组中。 2. 创建消息类Message: class Message { public $id; public $state = false; public $msg; public static function factory(Mosquitto\Message $msg, $state = false) { $message = new Message(); $message->state = $state; $message->msg = $msg; $message->id = $msg->mid; return $message; } } 这个类表示MQTT消息。它包括以下属性: $id:消息ID。 $state:消息状态,用于确认是否已接收。 $msg:实际的Mosquitto消息对象。 还包括一个工厂方法factory,用于从Mosquitto消息创建Message对象。 3. 创建Mosquitto客户端对象: $client = new Mosquitto\Client('client.terminal.onpublish', false); 这行代码创建了一个Mosquitto客户端对象,并为其指定了客户端ID和cleanSession标志。 4. 设置回调函数: $client->onMessage(function($msg) { print_r(array('receive', $msg)); MQ::addReceive($msg); }); $client->onPublish(function($mid) { MQ::confirm($mid); print_r(array('comfirm publish', MQ::$publish[$mid])); }); $client->onConnect(function($rc, $msg) { print_r(array('rc' => $rc, 'message' => $msg)); }); 这些回调函数用于处理不同的MQTT事件: onMessage:处理接收到的消息,将消息添加到MQ::$receive数组中。 onPublish:处理已发布的消息的确认,将消息标记为已确认。 onConnect:处理连接事件,打印连接结果。 5. 连接到MQTT代理: $client->connect('localhost', 1883, 60); 这行代码连接到本地MQTT代理,通常运行在localhost上的1883端口上。连接的超时时间设置为60秒。 6. 发布消息和处理: sleep(1); $client->subscribe('/test/publish', 1); $msg = Message::factory(new Mosquitto\Message()); $msg->msg->topic = '/test/publish'; $msg->msg->payload = 'hello from on publish'; $msg->msg->qos = 1; $mid = $client->publish($msg->msg->topic, $msg->msg->payload, $msg->msg->qos); print_r(array('publish', $msg)); MQ::addPublish($mid, $msg); sleep(1); $client->loopForever(); 这段代码的主要功能是: 订阅主题/test/publish。 创建一个要发布的消息对象$msg。 发布消息,并将消息添加到MQ::$publish数组中以进行后续确认。 使用loopForever方法持续运行MQTT客户端以处理消息和事件。 总之,这段代码创建了一个具有自定义消息确认和处理机制的MQTT客户端,它可以发布和接收消息,并在处理时跟踪消息的状态。这对于实现更高级的MQTT消息管理非常有用。 testwill.php <?php $client = new Mosquitto\Client(); $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->setWill('/hello', "Client died :-(", 1, 0); $client->connect("localhost", 1883, 5); $client->subscribe('/#', 1); $client->loopForever(); function connect($r) { echo "I got code {$r}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function message($message) { printf("Got a message on topic %s with payload:\n%s\n", $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } 这段PHP代码演示了如何创建一个Mosquitto MQTT客户端,该客户端具有以下功能: 1. 创建Mosquitto客户端对象: $client = new Mosquitto\Client(); 这行代码创建了一个Mosquitto客户端对象。 2. 设置连接和事件回调: $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); 这些行代码设置了不同MQTT事件的回调函数,当客户端连接、断开连接、订阅主题或接收消息时,将调用相应的回调函数。 3. 设置遗嘱消息(Will Message): $client->setWill('/hello', "Client died :-(", 1, 0); 这行代码设置了遗嘱消息,当客户端意外断开连接时,将自动发布遗嘱消息到主题/hello,消息内容是"Client died :-(",QoS级别为1,保留标志为0。 4. 连接到MQTT代理: $client->connect("localhost", 1883, 5); 这行代码连接到MQTT代理,该代理通常运行在本地主机(localhost)的1883端口上。连接超时设置为5秒。 5. 订阅主题: $client->subscribe('/#', 1); 这行代码订阅了以/#开头的所有主题,并将QoS级别设置为1。 6. 使用loopForever方法持续运行客户端: $client->loopForever(); 这行代码使客户端进入无限循环,以便处理MQTT消息和事件。客户端将保持连接状态,并在收到消息时调用相应的消息回调函数。 7. 定义连接、订阅、消息和断开连接的回调函数: 这些回调函数用于处理不同的MQTT事件: connect($r):处理连接事件,其中$r参数包含连接的返回码。 subscribe():处理订阅事件,表示成功订阅主题。 message($message):处理接收到的消息,打印主题和消息内容。 disconnect():处理断开连接事件,表示客户端已经断开连接。 总之,这段代码创建了一个Mosquitto MQTT客户端,连接到MQTT代理,订阅了一组主题,并设置了各种事件的回调函数。它还配置了遗嘱消息,以便在客户端意外断开连接时发送通知。最后,客户端使用loopForever方法持续运行,以便处理MQTT消息和事件。 --- ### 206. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT简介 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,广泛用于物联网设备之间的通信。MQTT协议采用了客户端/服务器架构,支持发布/订阅模式和点对点模式,以其高效、可靠、灵活等特点而著称。 MQTT协议的核心概念包括发布者(publisher)、代理服务器(broker)和订阅者(subscriber)。发布者将消息发布到代理服务器上,而订阅者则从代理服务器中订阅感兴趣的消息。代理服务器负责将消息传递给订阅者。 在MQTT中,主题(topic)是一个重要的概念,用于定义消息的类型和内容。发布者可以将消息发布到一个或多个主题上,而订阅者则可以订阅一个或多个主题的消息。 MQTT协议的轻量级和可靠性使其非常适合在不稳定的网络环境中传输大量消息。它被广泛应用于智能家居、车联网、工业物联网等领域,因为它具有快速响应和低带宽消耗的优势。 MQTTnet简介 MQTTnet是一个跨平台、高性能、开源的MQTT客户端库和服务端实现,是.NET平台上最受欢迎的MQTT实现之一。它可以方便地在.NET平台上集成MQTT功能,实现MQTT协议的消息传输和其他功能。 MQTTnet的源码托管在GitHub上,地址为:https://github.com/dotnet/MQTTnet 在.NET 7中使用MQTTnet 接下来,我们将介绍如何在.NET 7中使用MQTTnet来创建一个简单的MQTT发布和订阅示例。这个示例将包括一个MQTT服务端和一个MQTT客户端。 项目准备 首先,我们需要创建两个.NET 7控制台项目,一个用作服务端,另一个用作客户端。这两个项目将实现MQTT消息发布和订阅功能。 然后,我们需要安装MQTTnet包。在本示例中,我们选择安装3.12版本的MQTTnet,但请注意,MQTTnet的不同版本之间可能存在差异,选择适合您项目需求的版本。 您可以使用NuGet包管理器或命令行来安装MQTTnet,命令如下: dotnet add package MQTTnet --3.12 服务端代码编写 接下来,我们将编写服务端的代码。以下是一个简化版本的服务端代码示例: using System; using System.Text; using System.Threading.Tasks; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; using MQTTnet.Extensions.ManagedClient; public static async Task RunMqttServer() { // 创建一个MQTT客户端工厂 var factory = new MqttFactory(); var client = factory.CreateMqttClient(); // 配置MQTT客户端选项 var options = new MqttClientOptionsBuilder() .WithTcpServer("localhost", 1883) // 指定MQTT代理服务器的地址和端口 .Build(); // 连接到MQTT代理服务器 await client.ConnectAsync(options); while (true) { Console.WriteLine("请输入要发布的消息: "); var message = Console.ReadLine(); // 创建MQTT消息 var mqttMessage = new MqttApplicationMessageBuilder() .WithTopic("testTopic") // 指定消息的主题 .WithPayload(Encoding.UTF8.GetBytes(message)) // 设置消息内容 .WithExactlyOnceQoS() // 设置消息的质量等级 .Build(); // 发布MQTT消息到代理服务器 await client.PublishAsync(mqttMessage); } } static async Task Main(string[] args) { // 运行MQTT服务端 await RunMqttServer(); } 在这个示例中,我们创建了一个MQTT客户端,连接到本地的MQTT代理服务器(broker)并发布消息到名为"testTopic"的主题。服务端将不断等待用户输入,并将用户输入的消息发布到MQTT代理服务器。 客户端代码编写 接下来,我们编写客户端的代码,以下是客户端代码示例: using System; using System.Text; using System.Threading.Tasks; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; public static async Task RunMqttClient() { // 创建 MQTT 客户端工厂 var factory = new MqttFactory(); var client = factory.CreateMqttClient(); // 配置 MQTT 客户端选项 var options = new MqttClientOptionsBuilder() .WithTcpServer("localhost", 1883) // 指定 MQTT 服务器地址和端口 .Build(); // 设置消息接收处理程序 client.UseApplicationMessageReceivedHandler(e => { // 当接收到 MQTT 消息时,将消息内容打印到控制台 Console.WriteLine($"接收到的消息: {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}"); }); // 连接到 MQTT 服务器 await client.ConnectAsync(options); // 订阅指定主题的消息 await client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("testTopic").Build()); } static async Task Main(string[] args) { // 运行 MQTT 客户端 await RunMqttClient(); } 在这个示例中,我们创建了一个MQTT客户端,连接到本地的 MQTT代理服务器,并订阅了名为"testTopic"的主题。一旦客户端接收到新的消息,它将在控制台上打印消息内容。 运行和测试 现在,我们已经完成了服务端和客户端的代码编写。您可以使用以下步骤来运行和测试这个示例: 在本地安装MQTT代理服务器,确保端口号和配置与代码中匹配。 分别运行服务端和客户端项目,它们将连接到MQTT代理服务器。 在服务端的控制台中输入要发布的消息,然后按回车键。 在客户端的控制台中,您将看到接收到的消息。 这个示例是一个简单的MQTT发布和订阅功能演示,实际项目中可以根据需求进行扩展,例如处理异常、加强安全性等。 总结 MQTT是一种重要的物联网通信协议,它提供了可靠、高效的消息传输机制,适用于各种物联网应用。MQTTnet是.NET平台上的一种强大工具,帮助您轻松集成MQTT功能到.NET应用程序中,无论是服务端还是客户端。 通过以上示例,您可以快速开始使用MQTTnet在.NET 7中创建自己的MQTT应用程序,并实现消息的发布和订阅功能。希望这个教程对您有所帮助,使您更好地理解和应用MQTT协议和MQTTnet库。 --- ### 207. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 如何在 Python 中使用 MQTT Python是一种广泛使用的解释型、高级编程、通用型编程语言。Python的设计哲学强调代码的可读性和简洁的语法,使得开发者能够用更少的代码表达想法,不管是小型还是大型程序。本文将介绍如何在Python项目中使用paho-mqtt客户端库来实现与MQTT服务器的连接、订阅、取消订阅、消息发布和接收等功能。 项目初始化 首先,确保您的Python版本为3.6或更高版本。 python3 --version 选择MQTT客户端库 在Python中,paho-mqtt是一种常用的MQTT客户端库,它提供了对MQTT v3.1和v3.1.1的支持。您可以使用Pip来安装paho-mqtt。 pip3 install -i https://pypi.doubanio.com/simple paho-mqtt Python MQTT 使用 连接MQTT服务器 本文将使用EMQX提供的免费公共MQTT服务器,服务器接入信息如下: Broker: iot.mqtt.cn TCP Port: 1883 Websocket Port: 8083 首先,导入paho-mqtt客户端库: from paho.mqtt import client as mqtt_client 然后,设置MQTT Broker连接参数: broker = 'iot.mqtt.cn' port = 1883 topic = "/python/mqtt" client_id = f'python-mqtt-{random.randint(0, 1000)}' 接下来,编写连接MQTT Broker的函数: def connect_mqtt(): def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print(f"Failed to connect, return code {rc}\n") client = mqtt_client.Client(client_id) client.on_connect = on_connect client.connect(broker, port) return client 发布消息 您可以使用以下代码发布消息到指定主题: def publish(client): msg_count = 0 while True: time.sleep(1) msg = f"messages: {msg_count}" result = client.publish(topic, msg) status = result[0] if status == 0: print(f"Send `{msg}` to topic `{topic}`") else: print(f"Failed to send message to topic {topic}") msg_count += 1 订阅消息 编写消息回调函数on_message,在客户端从MQTT Broker收到消息后将被调用: def subscribe(client: mqtt_client): def on_message(client, userdata, msg): print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic") client.subscribe(topic) client.on_message = on_message 完整代码 发布消息的代码: # python 3.6 import random import time from paho.mqtt import client as mqtt_client # ...(前面的代码) def run(): client = connect_mqtt() client.loop_start() publish(client) if __name__ == '__main__': run() 订阅消息的代码: # python3.6 import random from paho.mqtt import client as mqtt_client # ...(前面的代码) def run(): client = connect_mqtt() subscribe(client) client.loop_forever() if __name__ == '__main__': run() 测试 发布消息:运行发布消息的代码,您将看到客户端成功连接并成功发布消息。 python3 pub.py 订阅消息:运行订阅消息的代码,您将看到客户端成功连接并成功接收到发布的消息。 python3 sub.py 总结 通过paho-mqtt客户端库,我们可以轻松地在Python项目中实现与MQTT服务器的连接、消息发布和订阅功能。Python在物联网领域的应用越来越广泛,其简洁的语法和高可读性使其成为设备侧业务逻辑实现的理想选择。希望本文能帮助您更好地理解如何在Python中使用MQTT。 --- ### 208. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT(Message Queuing Telemetry Transport)是一种轻量级物联网消息传输协议,它基于发布/订阅模式,适用于硬件受限、网络带宽有限、延迟较高的环境。在本文中,我们将详细介绍如何在Java项目中使用MQTT,实现连接到MQTT服务器、订阅主题和发布消息的功能。 步骤1:引入客户端库 首先,我们需要添加Eclipse Paho Java Client库的依赖项到项目的pom.xml文件中: <dependencies> <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.5</version> </dependency> </dependencies> 步骤2:创建MQTT连接 我们将使用免费公共MQTT服务器提供的MQTT服务器,以下是服务器接入信息: Broker: iot.mqtt.cn TCP Port: 1883 SSL/TLS Port: 8883 普通TCP连接 设置MQTT Broker的基本连接参数,用户名和密码为非必选参数: String broker = "tcp://iot.mqtt.cn:1883"; String username = "emqx"; String password = "public"; String clientid = "publish_client"; MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); client.connect(options); TLS/SSL连接 如果需要使用自签名证书进行TLS/SSL连接,需要添加bcpkix-jdk15on依赖项到pom.xml文件,并创建一个SSLUtils工具类。 <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.70</version> </dependency> 然后,根据TLS/SSL连接设置选项: // 设置 SSL/TLS 连接地址 String broker = "ssl://broker.emqx.io:8883"; // 设置 socket factory String caFilePath = "/cacert.pem"; String clientCrtFilePath = "/client.pem"; String clientKeyFilePath = "/client.key"; SSLSocketFactory socketFactory = SSLUtils.getSocketFactory(caFilePath, clientCrtFilePath, clientKeyFilePath, ""); options.setSocketFactory(socketFactory); 步骤3:发布MQTT消息 创建一个发布客户端类PublishSample,该类将发布一条"Hello MQTT"消息到主题mqtt/test: public class PublishSample { public static void main(String[] args) { String broker = "tcp://broker.emqx.io:1883"; String topic = "mqtt/test"; String username = "emqx"; String password = "public"; String clientid = "publish_client"; String content = "Hello MQTT"; int qos = 0; try { MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); options.setConnectionTimeout(60); options.setKeepAliveInterval(60); client.connect(options); MqttMessage message = new MqttMessage(content.getBytes()); message.setQos(qos); client.publish(topic, message); System.out.println("Message published"); System.out.println("topic: " + topic); System.out.println("message content: " + content); client.disconnect(); client.close(); } catch (MqttException e) { throw new RuntimeException(e); } } } 步骤4:订阅MQTT主题 创建一个订阅客户端类SubscribeSample,该类将订阅主题mqtt/test: public class SubscribeSample { public static void main(String[] args) { String broker = "tcp://broker.emqx.io:1883"; String topic = "mqtt/test"; String username = "emqx"; String password = "public"; String clientid = "subscribe_client"; int qos = 0; try { MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); options.setConnectionTimeout(60); options.setKeepAliveInterval(60); client.setCallback(new MqttCallback() { public void connectionLost(Throwable cause) { System.out.println("Connection lost: " + cause.getMessage()); } public void messageArrived(String topic, MqttMessage message) { System.out.println("Received message from topic: " + topic); System.out.println("QoS: " + message.getQos()); System.out.println("Message content: " + new String(message.getPayload())); } public void deliveryComplete(IMqttDeliveryToken token) { System.out.println("Delivery complete: " + token.isComplete()); } }); client.connect(options); client.subscribe(topic, qos); } catch (Exception e) { e.printStackTrace(); } } } 步骤5:测试 现在,您可以运行SubscribeSample订阅mqtt/test主题。然后运行PublishSample发布消息到mqtt/test主题。您将看到发布端成功发布消息,同时订阅端接收到消息。 总结 通过这篇文章,我们详细学习了如何在Java中使用Paho Java Client来连接到公共MQTT服务器,并实现了测试客户端与MQTT服务器的连接、消息发布和订阅。希望这篇文章对您在Java中使用MQTT有所帮助。 --- ═══════════════════════════════════════════ ## MQTT 规范 ═══════════════════════════════════════════ ### 209. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着智能工厂的到来,工业物联网(IIoT)正在以惊人的速度扩展。预计到2030年,IIoT市场规模将达到3.3万亿美元,意味着将有数十亿个设备相互连接。为了确保这些设备,尤其是那些资源受限且有时依赖电池供电的设备能够高效运行,找到一种高效且可扩展的物联网解决方案至关重要。 MQTT-SN(针对传感器网络的MQTT)是一种专为非TCP/IP网络上的嵌入式设备设计的轻量级发布和订阅消息协议。它优化了MQTT版本3.1.1和MQTT 5.0的规范,特别适合低功耗、受限设备。在这篇文章中,我们将探讨MQTT-SN的节能和扩展能力,以及它如何支持工业自动化和数据采集的不断增长需求。 MQTT-SN:IIoT的低功耗解决方案 减少物联网设备的电力消耗不仅可以降低能源成本,还有许多其他好处。想象一下,一个遍布大型多地点生产设施的传感器网络。每个传感器或连接设备都需要电力,如果依赖频繁更换电池,不仅麻烦,而且限制了这些部署的可扩展性和灵活性。在这种情况下,降低电力消耗尤为重要。 通过最小化单个设备的能耗,可以降低电费,减少对频繁更换电池的依赖。这不仅减少了维护需求,提高了运营的正常运行时间,还显著节省了成本。具有延长电池寿命或能够从环境中获取能量(例如通过太阳能或风能)的节能设备,可以实现更广泛的传感器分布,提供更全面的工业过程视图。这种增加的监控可扩展性,使数据驱动的决策更加有效,并有助于优化运营。 此外,减少对一次性电池的依赖,可以促进更绿色的IIoT生态系统。结合MQTT-SN这样的低功耗协议和能量收集技术,我们可以迈向IIoT的可持续未来。 为什么选择MQTT-SN? 首先,MQTT-SN为效率而生。与MQTT相比,MQTT-SN具有更紧凑的设计。消息头被最小化,主题名称可以被短主题ID替换。数据大小的减少转化为更少的带宽消耗和对资源有限设备的更低处理需求。 为了进一步降低功耗,MQTT-SN引入了睡眠机制。设备可以有效地关闭,并在重新开启时接收排队的消息。这显著降低了功耗,延长了电池供电传感器的电池寿命。 与MQTT一样,MQTT-SN利用发布/订阅模型。设备将数据发布到特定主题,感兴趣的订阅者只接收相关信息。这种有针对性的方法最小化了不必要的数据传输,优化了网络带宽的使用。多个设备可以通过MQTT-SN网关与MQTT代理通信。 通过解决功耗效率和可扩展性的关键方面,MQTT-SN为IIoT环境中的强大和可靠通信铺平了道路。随着工业领域接受自动化和数据驱动的决策,MQTT-SN成为推动创新和确保未来智能工厂无缝运行的强大工具。 为了实现更多的节能和更低的数据开销,MQTT-SN增加了一种新的QoS模式,允许盲目发送并忘记消息传递。这意味着设备可以简单地唤醒并发送消息,而不必等待响应。 与MQTT不同,MQTT-SN不依赖于TCP/IP传输。相反,它旨在与底层网络服务无关。因此,任何支持节点和网关之间双向传输服务的网络都可以支持MQTT-SN。 MQTT-SN的限制 在选择MQTT-SN作为您的通信协议时,需要意识到一些限制。最大的一个问题是安全性。虽然可以使用任何加密技术,但目前MQTT-SN协议本身并没有内置安全性。不过,这个问题将在最新的标准修订中得到解决。 在复杂性方面,学习、实施和管理MQTT-SN可能比一些更简单的协议要困难。然而,使用专为MQTT-SN设计的兼容工具和库可以简化这个过程。虽然网关使设备和代理之间的通信成为可能,但确保不同MQTT-SN实现与现有基础设施的兼容性至关重要。选择符合最新MQTT-SN规范并提供明确迁移路径的解决方案可以帮助缓解兼容性问题。 MQTT-SN在IIoT中的用例 MQTT-SN在功耗效率、可扩展性和轻量级设计方面的优势使其成为各种IIoT应用的理想选择。以下是一些典型的用例: 无线传感器网络:在工业环境中,众多传感器监测温度、压力、振动等关键参数。MQTT-SN的低数据占用和睡眠功能非常适合这些电池供电的传感器,使它们能够在节省电池寿命的同时高效地传输数据。 智能建筑管理:建筑物越来越多地与传感器集成,用于监测能源消耗、占用和环境条件。MQTT-SN促进了这些传感器与中央控制系统之间的高效通信,实现了实时数据收集和优化的建筑运营。 预测性维护:通过持续监测设备健康数据(如振动、温度),MQTT-SN允许及早发现潜在问题,使预防性维护成为可能,减少了停机时间和相关成本。 工业资产跟踪:在大型设施内跟踪关键资产(如工具、机械或库存)的位置和状态至关重要。MQTT-SN处理来自低功耗RFID标签或GNSS跟踪器的数据,使其适用于此类应用。 远程监控和控制:在石油和天然气管道或偏远地区的环境监测站等应用中,MQTT-SN使与电池供电传感器的高效通信成为可能,允许实时数据获取和远程控制能力。 总结 MQTT-SN为IIoT应用提供了一个引人注目的解决方案。它的轻量级设计、高效的通信模型和对节能的强调,使其非常适合工业环境中普遍存在的资源受限设备。随着IIoT格局的不断发展,MQTT-SN有望在促进数据的可扩展交换中发挥关键作用,最终赋能下一代工业自动化。 --- ### 210. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Abstract MQ Telemetry Transport (MQTT) is a lightweight broker-based publish/subscribe messaging protocol designed to be open, simple, lightweight and easy to implement. These characteristics make it ideal for use in constrained environments, for example, but not limited to: Where the network is expensive, has low bandwidth or is unreliable When run on an embedded device with limited processor or memory resources Features of the protocol include: The publish/subscribe message pattern to provide one-to-many message distribution and decoupling of applications A messaging transport that is agnostic to the content of the payload The use of TCP/IP to provide basic network connectivity Three qualities of service for message delivery: "At most once", where messages are delivered according to the best efforts of the underlying TCP/IP network. Message loss or duplication can occur. This level could be used, for example, with ambient sensor data where it does not matter if an individual reading is lost as the next one will be published soon after. "At least once", where messages are assured to arrive but duplicates may occur. "Exactly once", where message are assured to arrive exactly once. This level could be used, for example, with billing systems where duplicate or lost messages could lead to incorrect charges being applied. A small transport overhead (the fixed-length header is just 2 bytes), and protocol exchanges minimised to reduce network traffic A mechanism to notify interested parties to an abnormal disconnection of a client using the Last Will and Testament feature Copyright Notice © 1999-2010 Eurotech, International Business Machines Corporation (IBM). All rights reserved. Permission to copy and display the MQ Telemetry Transport specification (the "Specification"), in any medium without fee or royalty is hereby granted by Eurotech and International Business Machines Corporation (IBM) (collectively, the "Authors"), provided that you include the following on ALL copies of the Specification, or portions thereof, that you make: A link or URL to the Specification at one of the Authors' websites. The copyright notice as shown in the Specification. The Authors each agree to grant you a royalty-free license, under reasonable, non-discriminatory terms and conditions to their respective patents that they deem necessary to implement the Specification. THE SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY USE OR DISTRIBUTION OF THE SPECIFICATION. The name and trademarks of the Authors may NOT be used in any manner, including advertising or publicity pertaining to the Specification or its contents without specific, written prior permission. Title to copyright in the Specification will at all times remain with the Authors. No other rights are granted by implication, estoppel or otherwise. 1. Introduction This specification is split into three main sections: the message format that is common to all packet types, the specific details of each packet type, how the packets flow between client and server. Information on how topic wildcards are used is provided in the appendix. 1.1. Changes The following are the changes between MQTT V3 and MQTT V3.1: User name and password can now be sent with a CONNECT packet New return codes on CONNACK packets, for security problems Clarification that clients are not informed of un-authorized PUBLISH or SUBSCRIBE commands, and that the normal MQTT flow should complete even though the command has not been performed. Strings in MQTT now support full UTF-8, instead of just the US-ASCII subset. The protocol version number passed with CONNECT packets, is unchanged for this revision, and remains as the "3". Existing MQTT V3 server implementations should be able to accept connections from clients that support this revision, as long as they correctly respect the "Remaining Length" field, and therefore ignore the extra security information. 2. Message format The message header for each MQTT command message contains a fixed header. Some messages also require a variable header and a payload. The format for each part of the message header is described in the following sections: 2.1. Fixed header The message header for each MQTT command message contains a fixed header. The table below shows the fixed header format. bit76543210byte 1Message TypeDUP flagQoS levelRETAINbyte 2Remaining Length Byte 1 Contains the Message Type and Flags (DUP, QoS level, and RETAIN) fields.Byte 2 (At least one byte) contains the Remaining Length field. The fields are described in the following sections. All data values are in big-endian order: higher order bytes precede lower order bytes. A 16-bit word is presented on the wire as Most Significant Byte (MSB), followed by Least Significant Byte (LSB). Message Type Position: byte 1, bits 7-4. Represented as a 4-bit unsigned value. The enumerations for this version of the protocol are shown in the table below. MnemonicEnumerationDescriptionReserved0ReservedCONNECT1Client request to connect to ServerCONNACK2Connect AcknowledgmentPUBLISH3Publish messagePUBACK4Publish AcknowledgmentPUBREC5Publish Received (assured delivery part 1)PUBREL6Publish Release (assured delivery part 2)PUBCOMP7Publish Complete (assured delivery part 3)SUBSCRIBE8Client Subscribe requestSUBACK9Subscribe AcknowledgmentUNSUBSCRIBE10Client Unsubscribe requestUNSUBACK11Unsubscribe AcknowledgmentPINGREQ12PING RequestPINGRESP13PING ResponseDISCONNECT14Client is DisconnectingReserved15Reserved Flags The remaining bits of byte 1 contain the fields DUP, QoS, and RETAIN. The bit positions are encoded to represent the flags as shown in the table below. Bit positionNameDescription3DUPDuplicate delivery2-1QoSQuality of Service0RETAINRETAIN flag DUP Position: byte 1, bit 3. This flag is set when the client or server attempts to re-deliver a PUBLISH, PUBREL, SUBSCRIBE or UNSUBSCRIBE message. This applies to messages where the value of QoS is greater than zero (0), and an acknowledgment is required. When the DUP bit is set, the variable header includes a Message ID. The recipient should treat this flag as a hint as to whether the message may have been previously received. It should not be relied on to detect duplicates.QoS Position: byte 1, bits 2-1. This flag indicates the level of assurance for delivery of a PUBLISH message. The QoS levels are shown in the table below. QoS valuebit 2bit 1Description000At most onceFire and Forget<=1101At least onceAcknowledged delivery>=1210Exactly onceAssured delivery=1311Reserved RETAIN Position: byte 1, bit 0. This flag is only used on PUBLISH messages. When a client sends a PUBLISH to a server, if the Retain flag is set (1), the server should hold on to the message after it has been delivered to the current subscribers. When a new subscription is established on a topic, the last retained message on that topic should be sent to the subscriber with the Retain flag set. If there is no retained message, nothing is sent This is useful where publishers send messages on a "report by exception" basis, where it might be some time between messages. This allows new subscribers to instantly receive data with the retained, or Last Known Good, value. When a server sends a PUBLISH to a client as a result of a subscription that already existed when the original PUBLISH arrived, the Retain flag should not be set, regardless of the Retain flag of the original PUBLISH. This allows a client to distinguish messages that are being received because they were retained and those that are being received "live". Retained messages should be kept over restarts of the server. A server may delete a retained message if it receives a message with a zero-length payload and the Retain flag set on the same topic. Remaining Length Position: byte 2. Represents the number of bytes remaining within the current message, including data in the variable header and the payload. The variable length encoding scheme uses a single byte for messages up to 127 bytes long. Longer messages are handled as follows. Seven bits of each byte encode the Remaining Length data, and the eighth bit indicates any following bytes in the representation. Each byte encodes 128 values and a "continuation bit". For example, the number 64 decimal is encoded as a single byte, decimal value 64, hex 0x40. The number 321 decimal (= 65 + 2*128) is encoded as two bytes, least significant first. The first byte 65+128 = 193. Note that the top bit is set to indicate at least one following byte. The second byte is 2. The protocol limits the number of bytes in the representation to a maximum of four. This allows applications to send messages of up to 268 435 455 (256 MB). The representation of this number on the wire is: 0xFF, 0xFF, 0xFF, 0x7F. The table below shows the Remaining Length values represented by increasing numbers of bytes. DigitsFromTo10 (0x00)127 (0x7F)2128 (0x80, 0x01)16 383 (0xFF, 0x7F)316 384 (0x80, 0x80, 0x01)2 097 151 (0xFF, 0xFF, 0x7F)42 097 152 (0x80, 0x80, 0x80, 0x01)268 435 455 (0xFF, 0xFF, 0xFF, 0x7F) The algorithm for encoding a decimal number (X) into the variable length encoding scheme is as follows:do digit = X MOD 128 X = X DIV 128 // if there are more digits to encode, set the top bit of this digit if ( X > 0 ) digit = digit OR 0x80 endif 'output' digit while ( X> 0 ) where MOD is the modulo operator (% in C), DIV is integer division (/ in C), and OR is bit-wise or (| in C). The algorithm for decoding the Remaining Length field is as follows:multiplier = 1 value = 0 do digit = 'next digit from stream' value += (digit AND 127) * multiplier multiplier *= 128 while ((digit AND 128) != 0) where AND is the bit-wise and operator (& in C). When this algorithm terminates, value contains the Remaining Length in bytes. Remaining Length encoding is not part of the variable header. The number of bytes used to encode the Remaining Length does not contribute to the value of the Remaining Length. The variable length "extension bytes" are part of the fixed header, not the variable header. 2.2. Variable header Some types of MQTT command messages also contain a variable header component. It resides between the fixed header and the payload. The variable length Remaining Length field is not part of the variable header. The bytes of the Remaining Length field do not contribute to the byte count of the Remaining Length value. This value only takes account of the variable header and the payload. See Fixed header for more information. The format of the variable header fields are described in the following sections, in the order in which they must appear in the header: Protocol name The protocol name is present in the variable header of a MQTT CONNECT message. This field is a UTF-encoded string that represents the protocol name MQIsdp, capitalized as shown. Protocol version The protocol version is present in the variable header of a CONNECT message. The field is an 8-bit unsigned value that represents the revision level of the protocol used by the client. The value of the Protocol version field for the current version of the protocol, 3 (0x03), is shown in the table below. bit76543210Protocol Version00000011 Connect flags The Clean session, Will, Will QoS, and Retain flags are present in the variable header of a CONNECT message. Clean session flag Position: bit 1 of the Connect flags byte. If not set (0), then the server must store the subscriptions of the client after it disconnects. This includes continuing to store QoS 1 and QoS 2 messages for the subscribed topics so that they can be delivered when the client reconnects. The server must also maintain the state of in-flight messages being delivered at the point the connection is lost. This information must be kept until the client reconnects. If set (1), then the server must discard any previously maintained information about the client and treat the connection as "clean". The server must also discard any state when the client disconnects. Typically, a client will operate in one mode or the other and not change. The choice will depend on the application. A clean session client will not receive stale information and it must resubscribe each time it connects. A non-clean session client will not miss any QoS 1 or QoS 2 messages that were published whilst it was disconnected. QoS 0 messages are never stored, since they are delivered on a best efforts basis. This flag was formerly known as "Clean start". It has been renamed to clarify the fact it applies to the whole session and not just to the initial connect. A server may provide an administrative mechanism for clearing stored information about a client which can be used when it is known that a client will never reconnect. bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReservedxxxxxxx Bit 0 of this byte is not used in the current version of the protocol. It is reserved for future use. Will flag Position: bit 2 of the Connect flags byte. The Will message defines that a message is published on behalf of the client by the server when either an I/O error is encountered by the server during communication with the client, or the client fails to communicate within the Keep Alive timer schedule. Sending a Will message is not triggered by the server receiving a DISCONNECT message from the client. If the Will flag is set, the Will QoS and Will Retain fields must be present in the Connect flags byte, and the Will Topic and Will Message fields must be present in the payload. The format of the Will flag is shown in the table below. bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReservedxxxxxxx Bit 0 of this byte is not used in the current version of the protocol. It is reserved for future use. Will QoS Position: bits 4 and 3 of the Connect flags byte. A connecting client specifies the QoS level in the Will QoS field for a Will message that is sent in the event that the client is disconnected involuntarily. The Will message is defined in the payload of a CONNECT message. If the Will flag is set, the Will QoS field is mandatory, otherwise its value is disregarded. The value of Will QoS is 0 (0x00), 1 (0x01), or 2 (0x02). The Will QoS flag is shown in the table below. bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReservedxxx1xx Bit 0 of this byte is not used in the current version of the protocol. It is reserved for future use. Will Retain flag Position: bit 5 of the Connect flags byte. The Will Retain flag indicates whether the server should retain the Will message which is published by the server on behalf of the client in the event that the client is disconnected unexpectedly. The Will Retain flag is mandatory if the Will flag is set, otherwise, it is disregarded. The format of the Will Retain flag is shown in the table below. bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReservedxxxx1xx Bit 0 of this byte is not used in the current version of the protocol. It is reserved for future use. User name and password flags Position: bits 6 and 7 of the Connect flags byte. A connecting client can specify a user name and a password, and setting the flag bits signifies that a User Name, and optionally a password, are included in the payload of a CONNECT message. If the User Name flag is set, the User Name field is mandatory, otherwise its value is disregarded. If the Password flag is set, the Password field is mandatory, otherwise its value is disregarded. It is not valid to supply a password without supplying a user name. bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean SessionReservedxxxxxx Bit 0 of this byte is not used in the current version of the protocol. It is reserved for future use. Keep Alive timer The Keep Alive timer is present in the variable header of a MQTT CONNECT message. The Keep Alive timer, measured in seconds, defines the maximum time interval between messages received from a client. It enables the server to detect that the network connection to a client has dropped, without having to wait for the long TCP/IP timeout. The client has a responsibility to send a message within each Keep Alive time period. In the absence of a data-related message during the time period, the client sends a PINGREQ message, which the server acknowledges with a PINGRESP message. If the server does not receive a message from the client within one and a half times the Keep Alive time period (the client is allowed "grace" of half a time period), it disconnects the client as if the client had sent a DISCONNECT message. This action does not impact any of the client's subscriptions. See DISCONNECT for more details. If a client does not receive a PINGRESP message within a Keep Alive time period after sending a PINGREQ, it should close the TCP/IP socket connection. The Keep Alive timer is a 16-bit value that represents the number of seconds for the time period. The actual value is application-specific, but a typical value is a few minutes. The maximum value is approximately 18 hours. A value of zero (0) means the client is not disconnected. The format of the Keep Alive timer is shown in the table below. The ordering of the 2 bytes of the Keep Alive Timer is MSB, then LSB (big-endian). bit76543210Keep Alive MSBKeep Alive LSB Connect return code The connect return code is sent in the variable header of a CONNACK message. This field defines a one byte unsigned return code. The meanings of the values, shown in the tables below, are specific to the message type. A return code of zero (0) usually indicates success. EnumerationHEXMeaning00x00Connection Accepted10x01Connection Refused: unacceptable protocol version20x02Connection Refused: identifier rejected30x03Connection Refused: server unavailable40x04Connection Refused: bad user name or password50x05Connection Refused: not authorized6-255Reserved for future use bit76543210Return Code Topic name The topic name is present in the variable header of an MQTT PUBLISH message. The topic name is the key that identifies the information channel to which payload data is published. Subscribers use the key to identify the information channels on which they want to receive published information. The topic name is a UTF-encoded string. See the section on MQTT and UTF-8 for more information. Topic name has an upper length limit of 32,767 characters. 2.3. Payload The following types of MQTT command message have a payload:CONNECTThe payload contains one or more UTF-8 encoded strings. They specify a unqiue identifier for the client, a Will topic and message and the User Name and Password to use. All but the first are optional and their presence is determined based on flags in the variable header.SUBSCRIBEThe payload contains a list of topic names to which the client can subscribe, and the QoS level. These strings are UTF-encoded.SUBACKThe payload contains a list of granted QoS levels. These are the QoS levels at which the administrators for the server have permitted the client to subscribe to a particular Topic Name. Granted QoS levels are listed in the same order as the topic names in the corresponding SUBSCRIBE message. The payload part of a PUBLISH message contains application-specific data only. No assumptions are made about the nature or content of the data, and this part of the message is treated as a BLOB. If you want an application to apply compression to the payload data, you need to define in the application the appropriate payload flag fields to handle the compression details. You cannot define application-specific flags in the fixed or variable headers. 2.4. Message identifiers The message identifier is present in the variable header of the following MQTT messages: PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK. The Message Identifier (Message ID) field is only present in messages where the QoS bits in the fixed header indicate QoS levels 1 or 2. See section on Quality of Service levels and flows for more information. The Message ID is a 16-bit unsigned integer that must be unique amongst the set of "in flight" messages in a particular direction of communication. It typically increases by exactly one from one message to the next, but is not required to do so. A client will maintain its own list of Message IDs separate to the Message IDs used by the server it is connected to. It is possible for a client to send a PUBLISH with Message ID 1 at the same time as receiving a PUBLISH with Message ID 1. The ordering of the two bytes of the Message Identifier is MSB, then LSB (big-endian). Do not use Message ID 0. It is reserved as an invalid Message ID. bit76543210Message Identifier MSBMessage Identifier LSB 2.5. MQTT and UTF-8 UTF-8 is an efficient encoding of Unicode character-strings that optimizes the encoding of ASCII characters in support of text-based communications. In MQTT, strings are prefixed with two bytes to denote the length, as shown in the table below. bit76543210byte 1String Length MSBbyte 2String Length LSBbytes 3 ...Encoded Character Data String Length is the number of bytes of encoded string characters, not the number of characters. For example, the string OTWP is encoded in UTF-8 as shown in the table below. bit76543210byte 1Message Length MSB (0x00)00000000byte 2Message Length LSB (0x04)00000100byte 3'O' (0x4F)01001111byte 4'T' (0x54)01010100byte 5'W' (0x57)01010111byte 6'P' (0x50)01010000 The Java writeUTF() and readUTF() data stream methods use this format. 2.6. Unused bits Any bits marked as unused should be set to zero (0). 3. Command messages CONNECT CONNACK PUBLISH PUBACK PUBREC PUBREL PUBCOMP SUBSCRIBE SUBACK UNSUBSCRIBE UNSUBACK PINGREQ PINGRESP DISCONNECT 3.1. CONNECT - Client requests a connection to a server When a TCP/IP socket connection is established from a client to a server, a protocol level session must be created using a CONNECT flow. Fixed header The fixed header format is shown in the table below. bit76543210byte 1Message Type (1)DUP flagQoS levelRETAIN0001xxxxbyte 2Remaining Length The DUP, QoS, and RETAIN flags are not used in the CONNECT message. Remaining Length is the length of the variable header (12 bytes) and the length of the Payload. This can be a multibyte field. Variable header An example of the format of the variable header is shown in the table below. Description76543210Protocol Namebyte 1Length MSB (0)00000000byte 2Length LSB (6)00000110byte 3'M'01001101byte 4'Q'01010001byte 5'I'01001001byte 6's'01110011byte 7'd'01100100byte 8'p'01110000Protocol Version Numberbyte 9Version (3)00000011Connect Flagsbyte 10User name flag (1)Password flag (1)Will RETAIN (0)Will QoS (01)Will flag (1)Clean Session (1)1100111xKeep Alive timerbyte 11Keep Alive MSB (0)00000000byte 12Keep Alive LSB (10)00001010 User name flagSet (1).Password flagSet (1).Clean Session flagSet (1).Keep Alive timerSet to 10 seconds (0x000A).Will message Will flag is set (1) Will QoS field is 1 Will RETAIN flag is clear (0) Payload The payload of the CONNECT message contains one or more UTF-8 encoded strings, based on the flags in the variable header. The strings, if present, must appear in the following order:Client Identifier The first UTF-encoded string. The Client Identifier (Client ID) is between 1 and 23 characters long, and uniquely identifies the client to the server. It must be unique across all clients connecting to a single server, and is the key in handling Message IDs messages with QoS levels 1 and 2. If the Client ID contains more than 23 characters, the server responds to the CONNECT message with a CONNACK return code 2: Identifier Rejected.Will Topic If the Will Flag is set, this is the next UTF-8 encoded string. The Will Message is published to the Will Topic. The QoS level is defined by the Will QoS field, and the RETAIN status is defined by the Will RETAIN flag in the variable header.Will Message If the Will Flag is set, this is the next UTF-8 encoded string. The Will Message defines the content of the message that is published to the Will Topic if the client is unexpectedly disconnected. This may be a zero-length message. Although the Will Message is UTF-8 encoded in the CONNECT message, when it is published to the Will Topic only the bytes of the message are sent, not the first two length bytes. The message must therefore only consist of 7-bit ASCII characters.User Name If the User Name flag is set, this is the next UTF-encoded string. The user name identifies the name of the user who is connecting, which can be used for authentication. It is recommended that user names are kept to 12 characters or fewer, but it is not required. Note that, for compatibility with the original MQTT V3 specification, the Remaining Length field from the fixed header takes precedence over the User Name flag. Server implementations must allow for the possibility that the User Name flag is set, but the User Name string is missing. This is valid, and connections should be allowed to continue.Password If the Password flag is set, this is the next UTF-encoded string. The password corresponding to the user who is connecting, which can be used for authentication. It is recommended that passwords are kept to 12 characters or fewer, but it is not required. Note that, for compatibility with the original MQTT V3 specification, the Remaining Length field from the fixed header takes precedence over the Password flag. Server implementations must allow for the possibility that the Password flag is set, but the Password string is missing. This is valid, and connections should be allowed to continue. Response The server sends a CONNACK message in response to a CONNECT message from a client. If the server does not receive a CONNECT message within a reasonable amount of time after the TCP/IP connection is established, the server should close the connection. If the client does not receive a CONNACK message from the server within a reasonable amount of time, the client should close the TCP/IP socket connection, and restart the session by opening a new socket to the server and issuing a CONNECT message. In both of these scenarios, a "reasonable" amount of time depends on the type of application and the communications infrastructure. If a client with the same Client ID is already connected to the server, the "older" client must be disconnected by the server before completing the CONNECT flow of the new client. If the client sends an invalid CONNECT message, the server should close the connection. This includes CONNECT messages that provide invalid Protocol Name or Protocol Version Numbers. If the server can parse enough of the CONNECT message to determine that an invalid protocol has been requested, it may try to send a CONNACK containing the "Connection Refused: unacceptable protocol version" code before dropping the connection. 3.2. CONNACK - Acknowledge connection request The CONNACK message is the message sent by the server in response to a CONNECT request from a client. Fixed header The fixed header format is shown in the table below. bit76543210byte 1Message type (2)DUP flagQoS flagsRETAIN0010xxxxbyte 2Remaining Length (2)00000010 The DUP, QoS and RETAIN flags are not used in the CONNACK message. Variable header The variable header format is shown in the table below. Description76543210Topic Name Compression Responsebyte 1Reserved values. Not used.xxxxxxxxConnect Return Codebyte 2Return Code The values for the one byte unsigned Connect return code field are shown in the table below. EnumerationHEXMeaning00x00Connection Accepted10x01Connection Refused: unacceptable protocol version20x02Connection Refused: identifier rejected30x03Connection Refused: server unavailable40x04Connection Refused: bad user name or password50x05Connection Refused: not authorized6-255Reserved for future use Return code 2 (identifier rejected) is sent if the unique client identifier is not between 1 and 23 characters in length. Payload There is no payload. 3.3. PUBLISH - Publish message A PUBLISH message is sent by a client to a server for distribution to interested subscribers. Each PUBLISH message is associated with a topic name (also known as the Subject or Channel). This is a hierarchical name space that defines a taxonomy of information sources for which subscribers can register an interest. A message that is published to a specific topic name is delivered to connected subscribers for that topic. If a client subscribes to one or more topics, any message published to those topics are sent by the server to the client as a PUBLISH message. Fixed header The table below shows the fixed header format. bit76543210byte 1Message type (3)DUP flagQoS levelRETAIN00110010byte 2Remaining Length QoS levelSet to 1. See QoS for more details.DUP flagSet to zero (0). This means that the message is being sent for the first time. See DUP for more details.RETAIN flag Set to zero. This means do not retain. See Retain for more details.Remaining Length fieldThe length of the variable header plus the length of the payload. It can be a multibyte field. Variable header The variable header contains the following fields:Topic nameA UTF-encoded string. This must not contain Topic wildcard characters. When received by a client that subscribed using wildcard characters, this string will be the absolute topic specified by the originating publisher and not the subscription string used by the client.Message IDPresent for messages with QoS level 1 and QoS level 2. See Message identifiers for more details. The table below shows an example variable header for a PUBLISH message. FieldValueTopic Name:"a/b"QoS level1Message ID:10 The format of the variable header in this case is shown in the table below. Description76543210Topic Namebyte 1Length MSB (0)00000000byte 2Length LSB (3)00000011byte 3'a' (0x61)01100001byte 4'/' (0x2F)00101111byte 5'b' (0x62)01100010Message Identifierbyte 6Message ID MSB (0)00000000byte 7Message ID LSB (10)00001010 Payload Contains the data for publishing. The content and format of the data is application specific. The Remaining Length field in the fixed header includes both the variable header length and the payload length. As such, it is valid for a PUBLISH to contain a 0-length payload. Response The response to a PUBLISH message depends on the QoS level. The table below shows the expected responses. QoS LevelExpected responseQoS 0NoneQoS 1PUBACKQoS 2PUBREC Actions PUBLISH messages can be sent either from a publisher to the server, or from the server to a subscriber. The action of the recipient when it receives a message depends on the QoS level of the message:QoS 0Make the message available to any interested parties.QoS 1Log the message to persistent storage, make it available to any interested parties, and return a PUBACK message to the sender.QoS 2Log the message to persistent storage, do not make it available to interested parties yet, and return a PUBREC message to the sender. If the server receives the message, interested parties means subscribers to the topic of the PUBLISH message. If a subscriber receives the message, interested parties means the application on the client which has subscribed to one or more topics, and is waiting for a message from the server. See Quality of Service levels and flows for more details. Note that if a server implementation does not authorize a PUBLISH to be made by a client, it has no way of informing that client. It must therefore make a positive acknowledgement, according to the normal QoS rules, and the client will not be informed that it was not authorized to publish the message. 3.4. PUBACK - Publish acknowledgment A PUBACK message is the response to a PUBLISH message with QoS level 1. A PUBACK message is sent by a server in response to a PUBLISH message from a publishing client, and by a subscriber in response to a PUBLISH message from the server. Fixed header The table below shows the format of the fixed header. bit76543210byte 1Message Type (4)DUP flagQoS levelRETAIN0100xxxxbyte 2Remaining Length (2)00000010 QoS levelNot used.DUP flagNot used.RETAIN flagNot used.Remaining Length fieldThis is the length of the variable header (2 bytes). It can be a multibyte field. Variable header Contains the Message Identifier (Message ID) for the PUBLISH message that is being acknowledged. The table below shows the format of the variable header. bit76543210byte 1Message ID MSBbyte 2Message ID LSB Payload There is no payload. Actions When the client receives the PUBACK message, it discards the original message, because it is also received (and logged) by the server. 3.5. PUBREC - Assured publish received (part 1) A PUBREC message is the response to a PUBLISH message with QoS level 2. It is the second message of the QoS level 2 protocol flow. A PUBREC message is sent by the server in response to a PUBLISH message from a publishing client, or by a subscriber in response to a PUBLISH message from the server. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (5)DUP flagQoS levelRETAIN0101xxxxbyte 2Remaining Length (2)00000010 QoS levelNot used.DUP flagNot used.RETAIN flagNot used.Remaining Length fieldThe length of the variable header (2 bytes). It can be a multibyte field. Variable header The variable header contains the Message ID for the acknowledged PUBLISH. The table below shows the format of the variable header. bit76543210byte 1Message ID MSBbyte 2Message ID LSB Payload There is no payload. Actions When it receives a PUBREC message, the recipient sends a PUBREL message to the sender with the same Message ID as the PUBREC message. 3.6. PUBREL - Assured Publish Release (part 2) A PUBREL message is the response either from a publisher to a PUBREC message from the server, or from the server to a PUBREC message from a subscriber. It is the third message in the QoS 2 protocol flow. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (6)DUP flagQoS levelRETAIN0110001xbyte 2Remaining Length (2)00000010 QoS level PUBREL messages use QoS level 1 as an acknowledgement is expected in the form of a PUBCOMP. Retries are handled in the same way as PUBLISH messages.DUP flag Set to zero (0). This means that the message is being sent for the first time. See DUP for more details.RETAIN flagNot used.Remaining Length fieldThe length of the variable header (2 bytes). It can be a multibyte field. Variable header The variable header contains the same Message ID as the PUBREC message that is being acknowledged. The table below shows the format of the variable header. bit76543210byte 1Message ID MSBbyte 2Message ID LSB Payload There is no payload. Actions When the server receives a PUBREL message from a publisher, the server makes the original message available to interested subscribers, and sends a PUBCOMP message with the same Message ID to the publisher. When a subscriber receives a PUBREL message from the server, the subscriber makes the message available to the subscribing application and sends a PUBCOMP message to the server. 3.7. PUBCOMP - Assured publish complete (part 3) This message is either the response from the server to a PUBREL message from a publisher, or the response from a subscriber to a PUBREL message from the server. It is the fourth and last message in the QoS 2 protocol flow. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (7)DUP flagQoS levelRETAIN0111xxxxbyte 2Remaining Length (2)00000010 QoS levelNot used.DUP flagNot used.RETAIN flagNot used.Remaining Length fieldThe length of the variable header (2 bytes). It can be a multibyte field. Variable header The variable header contains the same Message ID as the acknowledged PUBREL message. bit76543210byte 1Message ID MSBbyte 2Message ID LSB Payload There is no payload. Actions When the client receives a PUBCOMP message, it discards the original message because it has been delivered, exactly once, to the server. 3.8. SUBSCRIBE - Subscribe to named topics The SUBSCRIBE message allows a client to register an interest in one or more topic names with the server. Messages published to these topics are delivered from the server to the client as PUBLISH messages. The SUBSCRIBE message also specifies the QoS level at which the subscriber wants to receive published messages. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (8)DUP flagQoS levelRETAIN1000001xbyte 2Remaining Length QoS levelSUBSCRIBE messages use QoS level 1 to acknowledge multiple subscription requests. The corresponding SUBACK message is identified by matching the Message ID. Retries are handled in the same way as PUBLISH messages.DUP flag Set to zero (0). This means that the message is being sent for the first time. See DUP for more details.RETAIN flagNot used.Remaining Length fieldThe length of the payload. It can be a multibyte field. Variable header The variable header contains a Message ID because a SUBSCRIBE message has a QoS level of 1. See Message identifiers for more details. The table below shows an example format for the variable header with a Message ID of 10. Description76543210Message Identifierbyte 1Message ID MSB (0)00000000byte 2Message ID LSB (10)00001010 Payload The payload of a SUBSCRIBE message contains a list of topic names to which the client wants to subscribe, and the QoS level at which the client wants to receive the messages. The strings are UTF-encoded, and the QoS level occupies 2 bits of a single byte. The topic strings may contain special Topic wildcard characters to represent a set of topics. These topic/QoS pairs are packed contiguously as shown in the example payload in the table below. Topic name"a/b"Requested QoS1Topic name"c/d"Requested QoS2 Topic names in a SUBSCRIBE message are not compressed. The format of the example payload is shown in the table below. Description76543210Topic namebyte 1Length MSB (0)00000000byte 2Length LSB (3)00000011byte 3'a' (0x61)01100001byte 4'/' (0x2F)00101111byte 5'b' (0x62)01100010Requested QoSbyte 6Requested QoS (1)xxxxxx01Topic Namebyte 7Length MSB (0)00000000byte 8Length LSB (3)00000011byte 9'c' (0x63)01100011byte 10'/' (0x2F)00101111byte 11'd' (0x64)01100100Requested QoSbyte 12Requested QoS (2)xxxxxx10 Assuming that the requested QoS level is granted, the client receives PUBLISH messages at less than or equal to this level, depending on the QoS level of the original message from the publisher. For example, if a client has a QoS level 1 subscription to a particular topic, then a QoS level 0 PUBLISH message to that topic is delivered to the client at QoS level 0. A QoS level 2 PUBLISH message to the same topic is downgraded to QoS level 1 for delivery to the client. A corollary to this is that subscribing to a topic at QoS level 2 is equivalent to saying "I would like to receive messages on this topic at the QoS at which they are published". This means a publisher is responsible for determining the maximum QoS a message can be delivered at, but a subscriber is able to downgrade the QoS to one more suitable for its usage. The QoS of a message is never upgraded. The Requested QoS field is encoded in the byte following each UTF-encoded topic name as shown in the table below. bit76543210ReservedReservedReservedReservedReservedReservedQoS levelxxxxxx The upper 6 bits of this byte are not used in the current version of the protocol. They are reserved for future use. A request with both QoS level bits set should be considered an invalid packet and the connection closed. Response When it receives a SUBSCRIBE message from a client, the server responds with a SUBACK message. A server may start sending PUBLISH messages due to the subscription before the client receives the SUBACK message. Note that if a server implementation does not authorize a SUBSCRIBE request to be made by a client, it has no way of informing that client. It must therefore make a positive acknowledgement with a SUBACK, and the client will not be informed that it was not authorized to subscribe. A server may chose to grant a lower level of QoS than the client requested. This could happen if the server is not able to provide the higher levels of QoS. For example, if the server does not provider a reliable persistence mechanism it may chose to only grant subscriptions at QoS 0. 3.9. SUBACK - Subscription acknowledgement A SUBACK message is sent by the server to the client to confirm receipt of a SUBSCRIBE message. A SUBACK message contains a list of granted QoS levels. The order of granted QoS levels in the SUBACK message matches the order of the topic names in the corresponding SUBSCRIBE message. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (9)DUP flagQoS levelRETAIN1001xxxxbyte 2Remaining Length QoS levelNot used.DUP flagNot used.RETAIN flagNot used.Remaining Length fieldThe length of the payload. It can be a multibyte field. Variable header The variable header contains the Message ID for the SUBSCRIBE message that is being acknowledged. The table below shows the format of the variable header. 76543210byte 1Message ID MSBbyte 2Message ID LSB Payload The payload contains a vector of granted QoS levels. Each level corresponds to a topic name in the corresponding SUBSCRIBE message. The order of QoS levels in the SUBACK message matches the order of topic name and Requested QoS pairs in the SUBSCRIBE message. The Message ID in the variable header enables you to match SUBACK messages with the corresponding SUBSCRIBE messages. The table below shows the Granted QoS field encoded in a byte. bit76543210ReservedReservedReservedReservedReservedReservedQoS levelxxxxxx The upper 6 bits of this byte are not used in the current version of the protocol. They are reserved for future use. The table below shows an example payload. Granted QoS0Granted QoS2 The table below shows the format of this payload. Description76543210byte 1Granted QoS (0)xxxxxx00byte 1Granted QoS (2)xxxxxx10 3.10. UNSUBSCRIBE - Unsubscribe from named topics An UNSUBSCRIBE message is sent by the client to the server to unsubscribe from named topics. Fixed header The table below shows an example fixed header format. bit76543210byte 1Message Type (10)DUP flagQoS levelRETAIN1010001xbyte 2Remaining Length QoS levelUNSUBSCRIBE messages use QoS level 1 to acknowledge multiple unsubscribe requests. The corresponding UNSUBACK message is identified by the Message ID. Retries are handled in the same way as PUBLISH messages.DUP flag Set to zero (0). This means that the message is being sent for the first time. See DUP for more details.RETAIN flagNot used.Remaining LengthThis is the length of the Payload. It can be a multibyte field. Variable header The variable header contains a Message ID because an UNSUBSCRIBE message has a QoS level of 1. See Message identifiers for more details. The table below shows an example format for the variable header with a Message ID of 10. Description76543210Message Identifierbyte 1Message ID MSB (0)00000000byte 2Message ID LSB (10)00001010 Payload The client unsubscribes from the list of topics named in the payload. The strings are UTF-encoded and are packed contiguously. Topic names in a UNSUBSCRIBE message are not compressed. The table below shows an example payload. Topic Name"a/b"Topic Name"c/d" The table below shows the format of this payload. Description76543210Topic Namebyte 1Length MSB (0)00000000byte 2Length LSB (3)00000011byte 3'a' (0x61)01100001byte 4'/' (0x2F)00101111byte 5'b' (0x62)01100010Topic Namebyte 6Length MSB (0)00000000byte 7Length LSB (3)00000011byte 8'c' (0x63)01100011byte 9'/' (0x2F)00101111byte 10'd' (0x64)01100100 Response The server sends an UNSUBACK to a client in response to an UNSUBSCRIBE message. 3.11. UNSUBACK - Unsubscribe acknowledgment The UNSUBACK message is sent by the server to the client to confirm receipt of an UNSUBSCRIBE message. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (11)DUP flagQoS levelRETAIN1011xxxxbyte 2Remaining length (2)00000010 QoS levelNot used.DUP flagNot used.RETAIN flagNot used.Remaining LengthThe length of the Variable Header (2 bytes). Variable header The variable header contains the Message ID for the UNSUBSCRIBE message that is being acknowledged. The table below shows the format of the variable header. bit76543210byte 1Message ID MSBbyte 2Message ID LSB Payload There is no payload. 3.12. PINGREQ - PING request The PINGREQ message is an "are you alive?" message that is sent from a connected client to the server. See Keep Alive timer for more details. Fixed header The table below shows the fixed header format. bit76543210byte 1Message Type (12)DUP flagQoS levelRETAIN1100xxxxbyte 2Remaining Length (0)00000000 The DUP, QoS, and RETAIN flags are not used. Variable header There is no variable header. Payload There is no payload. Response The response to a PINGREQ message is a PINGRESP message. 3.13. PINGRESP - PING response A PINGRESP message is the response sent by a server to a PINGREQ message and means "yes I am alive". See Keep Alive timer for more details. Fixed header The table below shows the fixed header format: bit76543210byte 1Message Type (13)DUP flagQoS levelRETAIN1101xxxxbyte 2Remaining Length (0)00000000 The DUP, QoS, and RETAIN flags are not used. Payload There is no payload. Variable header There is no variable header. 3.14. DISCONNECT - Disconnect notification The DISCONNECT message is sent from the client to the server to indicate that it is about to close its TCP/IP connection. This allows for a clean disconnection, rather than just dropping the line. If the client had connected with the clean session flag set, then all previously maintained information about the client will be discarded. A server should not rely on the client to close the TCP/IP connection after receiving a DISCONNECT. Fixed header The fixed header format is shown in the table below. bit76543210byte 1Message Type (14)DUP flagQoS levelRETAIN1110xxxxbyte 2Remaining Length (0)00000000 The DUP, QoS, and RETAIN flags are not used in the DISCONNECT message. Payload There is no payload. Variable header There is no variable header. 4. Flows 4.1. Quality of Service levels and flows MQTT delivers messages according to the levels defined in a Quality of Service (QoS). The levels are described below:QoS level 0: At most once deliveryThe message is delivered according to the best efforts of the underlying TCP/IP network. A response is not expected and no retry semantics are defined in the protocol. The message arrives at the server either once or not at all. The table below shows the QoS level 0 protocol flow. ClientMessage and directionServerQoS = 0PUBLISH---------->Action: Publish message to subscribers QoS level 1: At least once deliveryThe receipt of a message by the server is acknowledged by a PUBACK message. If there is an identified failure of either the communications link or the sending device, or the acknowledgement message is not received after a specified period of time, the sender resends the message with the DUP bit set in the message header. The message arrives at the server at least once. Both SUBSCRIBE and UNSUBSCRIBE messages use QoS level 1. A message with QoS level 1 has a Message ID in the message header. The table below shows the QoS level 1 protocol flow. ClientMessage and directionServerQoS = 1DUP = 0Message ID = xAction: Store messagePUBLISH---------->Actions:Store messagePublish message to subscribersDelete messageAction: Discard messagePUBACK<---------- If the client does not receive a PUBACK message (either within a time period defined in the application, or if a failure is detected and the communications session is restarted), the client may resend the PUBLISH message with the DUP flag set. When it receives a duplicate message from the client, the server republishes the message to the subscribers, and sends another PUBACK message.QoS level 2: Exactly once deliveryAdditional protocol flows above QoS level 1 ensure that duplicate messages are not delivered to the receiving application. This is the highest level of delivery, for use when duplicate messages are not acceptable. There is an increase in network traffic, but it is usually acceptable because of the importance of the message content. A message with QoS level 2 has a Message ID in the message header. The table below shows the QoS level 2 protocol flow. There are two semantics available for how a PUBLISH flow should be handled by the recipient. They affect the point within the flow that the message is made available to the subscribers. The choice of semantic is implementation specific and does not affect the guarantees of a QoS level 2 flow. ClientMessage and directionServerQoS = 2DUP = 0Message ID = xAction: Store messagePUBLISH---------->Action: Store messageorActions:Store message IDPublish message to subscribersPUBREC<----------Message ID = xMessage ID = xPUBREL---------->Actions:Publish message to subscribersDelete messageorAction: Delete message IDAction: Discard messagePUBCOMP<----------Message ID = x If a failure is detected, or after a defined time period, the protocol flow is retried from the last unacknowledged protocol message; either the PUBLISH or PUBREL. See Message delivery retry for more details. The additional protocol flows ensure that the message is delivered to subscribers once only. Assumptions for QoS levels 1 and 2 In any network, it is possible for devices or communication links to fail. If this happens, one end of the link might not know what is happening at the other end; these are known as in doubt windows. In these scenarios assumptions have to be made about the reliability of the devices and networks involved in message delivery. MQTT assumes that the client and server are generally reliable, and that the communications channel is more likely to be unreliable. If the client device fails, it is typically a catastrophic failure, rather than a transient one. The possibility of recovering data from the device is low. Some devices have non-volatile storage, for example flash ROM. The provision of more persistent storage on the client device protects the most critical data from some modes of failure. Beyond the basic failure of the communications link, the failure mode matrix becomes complex, resulting in more scenarios than the specification for MQTT can handle. 4.2. Message delivery retry Although TCP normally guarantees delivery of packets, there are certain scenarios where an MQTT message may not be received. In the case of MQTT messages that expect a response (QoS >0 PUBLISH, PUBREL, SUBSCRIBE, UNSUBSCRIBE), if the response is not received within a certain time period, the sender may retry delivery. The sender should set the DUP flag on the message. The retry timeout should be a configurable option. However care must be taken to ensure message delivery does not timeout while it is still being sent. For example, sending a large message over a slow network will naturally take longer than a small message over a fast network. Repeatedly retrying a timed-out message could often make matters worse so a strategy of increasing the timeout value across multiple retries should be used. When a client reconnects, if it is not marked clean session, both the client and server should redeliver any previous in-flight messages. Other than this "on reconnect" retry behaviour, clients are not required to retry message delivery. Brokers, however, should retry any unacknowledged message. 4.3. Message ordering Message ordering can be affected by a number of factors, including how many in-flight PUBLISH flows a client allows and whether the client is single- or multi-threaded. For purposes of discussion, clients are assumed to be single-threaded at the point packets are written to and read from the network. For an implementation to provide any guarantees regarding the ordering of messages it must ensure each stage of the message delivery flows are completed in the order they were started. For example, in a series of QoS level 2 flows, the PUBREL flows must be sent in the same order as the original PUBLISH flows: ClientMessage and directionServer PUBLISH 1---------->PUBLISH 2---------->PUBLISH 3---------->  PUBREC 1<----------PUBREC 2<----------  PUBREL 1---------->  PUBREC 3<----------  PUBREL 2---------->  PUBCOMP 1<----------  PUBREL 3---------->  PUBCOMP 2<----------PUBCOMP 3<----------  The number of in-flight messages permitted also has an effect on the type of guarantees that can be made: With an in-flight window of 1, each delivery flow is completed before the next one starts. This guarantees messages are delivered in the order they were submitted. With an in-flight window greater than 1, message ordering can only be guaranteed within the QoS level. Appendix A - Topic wildcards A subscription may contain special characters, which allow you to subscribe to multiple topics at once. The topic level separator is used to introduce structure into the topic, and can therefore be specified within the topic for that purpose. The multi-level wildcard and single-level wildcard can be used for subscriptions, but they cannot be used within a topic by the publisher of a message.Topic level separatorThe forward slash (/) is used to separate each level within a topic tree and provide a hierarchical structure to the topic space. The use of the topic level separator is significant when the two wildcard characters are encountered in topics specified by subscribers.Multi-level wildcard The number sign (#) is a wildcard character that matches any number of levels within a topic. For example, if you subscribe to finance/stock/ibm/#, you receive messages on these topics: finance/stock/ibm finance/stock/ibm/closingprice finance/stock/ibm/currentprice The multi-level wildcard can represent zero or more levels. Therefore, finance/# can also match the singular finance, where # represents zero levels. The topic level separator is meaningless in this context, because there are no levels to separate. The multi-level wildcard can be specified only on its own or next to the topic level separator character. Therefore, # and finance/# are both valid, but finance# is not valid. The multi-level wildcard must be the last character used within the topic tree. For example, finance/# is valid but finance/#/closingprice is not valid.Single-level wildcard The plus sign (+) is a wildcard character that matches only one topic level. For example, finance/stock/+ matches finance/stock/ibm and finance/stock/xyz, but not finance/stock/ibm/closingprice. Also, because the single-level wildcard matches only a single level, finance/+ does not match finance. The single-level wildcard can be used at any level in the topic tree, and in conjunction with the multilevel wildcard. It must be used next to the topic level separator, except when it is specified on its own. Therefore, + and finance/+ are both valid, but finance+ is not valid. The single-level wildcard can be used at the end of the topic tree or within the topic tree. For example, finance/+ and finance/+/ibm are both valid. Topic semantics and usage When you build an application, the design of the topic tree should take into account the following principles of topic name syntax and semantics: A topic must be at least one character long. Topic names are case sensitive. For example, ACCOUNTS and Accounts are two different topics. Topic names can include the space character. For example, Accounts payable is a valid topic. A leading "/" creates a distinct topic. For example, /finance is different from finance. /finance matches "+/+" and "/+", but not "+". Do not include the null character (Unicode \x0000) in any topic. The following principles apply to the construction and content of a topic tree: The length is limited to 64k but within that there are no limits to the number of levels in a topic tree. There can be any number of root nodes; that is, there can be any number of topic trees. --- ### 211. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 2024032209182023下载 --- ### 212. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 2024032209060883下载 --- ### 213. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 近期对无线传感网络(WSNs)的兴趣不断增长,无论是从商业还是技术的角度来看,都因其简易性、低成本和易于部署而受到关注。这些网络可以用于不同的目的,从测量和检测到自动化和过程控制。一个典型的WSN由大量电池操作的传感器和执行器(SAs)组成,这些设备通常配备有有限的存储和处理能力。重要的是这些设备能够通过无线方式通信,因为SA节点的数量通常非常大,且部署有线基础设施的成本极其昂贵。这样的网络本质上非常动态:无线链接可能随时临时断开,节点可能会经常失败并被频繁替换。在这种情况下,使用地址来与个别节点通信的传统方法可能变成一场噩梦。居住在固定网络上并需要与无线SA设备交互的应用程序需要管理和维护与大量节点通信的手段。在大多数情况下,它们不需要知道提供信息的设备的地址或身份,而是更感兴趣于数据的内容。例如,资产跟踪应用程序更感兴趣于某个特定资产的当前位置,而不是提供该信息的GPS接收器的网络地址。此外,几个应用程序可能对相同的传感器数据感兴趣,但出于不同的目的。在这种情况下,SA节点需要同时与多个应用程序并行管理和维护通信手段。这可能超出了简单和低成本SA设备的有限能力。另一个问题是涉及的网络之间的寻址方案差异。例如,一个驻留在基于TCP/IP的网络上的应用程序如何寻址一个运行在基于ZigBee R1的无线网络上的SA设备? 通过使用以数据为中心的通信方法可以克服上述问题,在这种方法中,信息的传递不是基于它们的网络地址,而是作为其内容和兴趣的函数。一个众所周知的以数据为中心的通信示例是“发布/订阅”(pub/sub)消息系统,该系统已在企业网络中被广泛使用,主要是因为其可扩展性和支持动态网络拓扑。将企业pub/sub系统扩展到WSNs还可以实现WSNs到企业网络的无缝集成,从而使SAs收集的现场数据可用于所有应用程序,就像任何其他企业信息一样,并使SAs能够受到任何企业应用程序的控制。 ZigBee是ZigBee联盟在美国、其他国家或两者中的商标。其他公司、产品或服务名称可能是其他人的商标或服务标记。 MQTT-SN规范简介 本文档的目的是规定MQTT-SN,一种适用于无线传感网络的发布/订阅协议。MQTT-SN可以被视为适应无线通信环境特点的MQTT版本。无线电链路通常比有线链路具有更高的故障率,因为它们容易受到衰减和干扰的影响。它们的传输速率也较低。例如,基于IEEE 802.15.4标准的WSN在2.4 GHz带提供的最大带宽为250 kbit/s。此外,为了抵抗传输错误,它们的数据包长度非常短。在IEEE 802.15.4的情况下,物理层的包长限制为128字节。这128字节中的一半可能会被MAC层、网络、安全等支持功能所需的开销信息占据。MQTT-SN还针对在低成本电池操作设备上的实现进行了优化,这些设备具有有限的处理和存储资源。 MQTT-SN最初是为在ZigBee R1 APS层之上运行而开发的。ZigBee R1是一个开放的工业联盟,旨在为WSN定义一个开放和全球的通信标准。为了实现全球化,ZigBee R1选择了IEEE 802.15.4标准作为PHY和MAC层的协议,并在此标准的基础上增加了所需的网络、安全和应用层,从而提供不同厂商产品之间的互操作性。 MQTT-SN的设计使其不依赖于底层网络服务。任何提供节点与特定节点(即网关)之间双向数据传输服务的网络都应能够支持MQTT-SN。例如,一个简单的数据报服务,允许源端点向特定的目的端点发送数据消息应该就足够了。如果使用网关发现程序,则只需要广播数据传输服务。为了减少发现程序产生的广播流量,最好是MQTT-SN能够向底层层指示所需的广播半径。 3.MQTT-SN 与 MQTT MQTT-SN旨在尽可能接近MQTT,但针对无线通信环境的特殊性进行了适应,如低带宽、高链路故障、短消息长度等。它也针对低成本、电池操作的设备上的实现进行了优化,这些设备具有有限的处理和存储资源。 与MQTT相比,MQTT-SN有以下不同之处: CONNECT消息被分解为三个消息。两个额外的消息是可选的,用于将遗嘱主题和遗嘱消息传输给服务器。 为了应对无线网络中的短消息长度和有限的传输带宽,PUBLISH消息中的主题名称被一个短的、两字节长的“主题ID”替代。定义了一个注册程序,允许客户端向服务器/网关注册它们的主题名称,并获得相应的主题ID。它也用于相反方向,以通知客户端即将在后续的PUBLISH消息中包括的主题名称和相应的主题ID。 引入了“预定义”的主题ID和“短”的主题名称,它们不需要注册。预定义的主题ID也是替代主题名称的两字节长的值,它们之间的映射事先已经为客户端的应用程序和网关/服务器所知。因此,双方可以开始使用预定义的主题ID;与上述的“普通”主题ID不同。短主题名称是长度固定为两个字节的主题名称。它们足够短,可以在PUBLISH消息中与数据一起携带。就像预定义的主题ID一样,短主题名称也不需要注册。 发现程序帮助没有预配置服务器/网关地址的客户端发现运行中的服务器/网关的实际网络地址。同一无线网络内可能同时存在多个网关,它们可以以负载共享或备用模式合作。 “清理会话”的语义扩展到了遗嘱特性,即不仅客户端的订阅是持久的,遗嘱主题和遗嘱消息也是如此。客户端还可以在会话期间修改其遗嘱主题和遗嘱消息。 为支持休眠客户端定义了新的离线保持活动程序。有了这个程序,电池操作的设备可以在睡眠状态下进入,期间所有发给它们的消息都在服务器/网关处缓冲,之后当它们唤醒时再交付给它们。 4. MQTT-SN架构 图1: MQTT-SN架构 MQTT-SN的架构如图1所示。有三种类型的MQTT-SN组件,MQTT-SN客户端、MQTT-SN网关(GW)和MQTT-SN转发器。MQTT-SN客户端通过MQTT-SN网关使用MQTT-SN协议连接到MQTT服务器。MQTT-SN网关可能与MQTT服务器集成,也可能不集成。如果是独立的网关,那么MQTT服务器和MQTT-SN网关之间使用MQTT协议。其主要功能是MQTT与MQTT-SN之间的转换。 如果网关没有直接连接到它们的网络,MQTT-SN客户端也可以通过转发器访问网关。转发器简单地封装它在无线侧接收到的MQTT-SN帧,并不加改变地转发给网关;反方向也是如此,它从网关接收到的帧解封装后,也不加改变地发送给客户端。 根据网关如何执行MQTT与MQTT-SN之间的协议转换,我们可以区分两种类型的网关,即透明网关和聚合网关,见图2。以下部分将对这两种网关进行解释。 4.1 透明网关 对于每个连接的MQTT-SN客户端,透明网关将建立并维护一个到MQTT服务器的MQTT连接。这个MQTT连接专门用于客户端和服务器之间端到端且几乎透明的消息交换。网关和服务器之间的MQTT连接数量将与连接到网关的MQTT-SN客户端数量一样多。透明网关将执行两种协议之间的“语法”转换。由于所有消息交换都是客户端与MQTT服务器之间的端到端,服务器实现的所有功能和特性都可以提供给客户端。 尽管与聚合网关相比,透明网关的实现更简单,但它需要MQTT服务器为每个活动客户端支持一个单独的连接。某些MQTT服务器实现可能会限制它们所支持的并发连接的数量。 图2:透明和聚合网关 4.2 聚合网关 与为每个连接的客户端拥有一个MQTT连接不同,聚合网关只与服务器有一个MQTT连接。MQTT-SN客户端和聚合网关之间的所有消息交换都在网关处终止。然后,网关决定哪些信息将进一步传递给服务器。虽然其实现比透明网关的实现更复杂,但在具有非常大量SAs的WSN案例中,聚合网关可能会很有帮助,因为它减少了服务器必须同时支持的MQTT连接数量。 5.消息格式 5.1 通用消息格式 消息头 (2或4字节)消息变量部分 (n字节)表1:通用消息格式 MQTT-SN消息的通用格式如表1所示。MQTT-SN消息由两部分组成:一个2或4字节长的头部和一个可选的变量部分。虽然头部总是存在且包含相同的字段,但变量部分的存在和内容取决于所考虑消息的类型。 5.2 消息头 消息头的格式如表2所示。 表2:消息头 5.2.1 长度 长度字段要么是1字节长,要么是3字节长,指定消息中包含的字节总数(包括长度字段本身)。 如果长度字段的第一个字节编码为“0x01”,则长度字段为3字节长;在这种情况下,接下来的两个字节指定消息的总字节数(最高有效字节在前)。否则,长度字段只有1字节长,并自身指定消息中包含的字节总数。 3字节格式允许编码长度高达65535字节的消息。长度小于256字节的消息可以使用较短的1字节格式。 注意,因为MQTT-SN不支持消息分段和重组,所以在网络中可以使用的最大消息长度由该网络支持的最大数据包大小决定,而不是由MQTT-SN可以编码的最大长度决定。 5.2.2 消息类型 消息类型字段长度为1字节,指定消息类型。它应该设置为表3中显示的值之一。 消息类型字段值消息类型消息类型字段值消息类型0x00ADVERTISE0x01SEARCHGW0x02GWINFO0x03保留0x04CONNECT0x05CONNACK0x06WILLTOPICREQ0x07WILLTOPIC0x08WILLMSGREQ0x09WILLMSG0x0AREGISTER0x0BREGACK0x0CPUBLISH0x0DPUBACK0x0EPUBCOMP0x0FPUBREC0x10PUBREL0x11保留0x12SUBSCRIBE0x13SUBACK0x14UNSUBSCRIBE0x15UNSUBACK0x16PINGREQ0x17PINGRESP0x18DISCONNECT0x19保留0x1AWILLTOPICUPD0x1BWILLTOPICRESP0x1CWILLMSGUPD0x1DWILLMSGRESP0x1E-0xFD保留0xFE封装消息0xFF保留表3:消息类型字段的值 5.3 消息变量部分 消息变量部分的内容取决于消息的类型。以下字段为消息变量部分定义。 5.3.1 客户端ID 与MQTT一样,客户端ID字段长度可变,包含一个1-23个字符的字符串,用于将客户端唯一地标识给服务器。 5.3.2 数据 数据字段对应于MQTT PUBLISH消息的负载。它长度可变,包含正在发布的应用数据。 5.3.3 持续时间 持续时间字段长度为2字节,指定时间周期的持续时间,以秒为单位。可以编码的最大值约为18小时。 5.3.4 标志 DUP(bit 7)QoS(6,5)保留(4)遗嘱(3)清除会话(2)主题ID类型(1,0)表4:标志字段 标志字段长度为1字节,包含以下标志(见表4): 复制(DUP):与MQTT含义相同,即如果消息是第一次发送则设置为“0”;如果是重传,则设置为“1”(仅在PUBLISH消息中相关); QoS:与MQTT的QoS级别0、1和2的含义相同;对于QoS级别0设置为“0b00”,QoS级别1设置为“0b01”,QoS级别2设置为“0b10”,新的QoS级别-1设置为“0b11”(仅在客户端发送的PUBLISH消息中相关); 保留(Retain):与MQTT含义相同(仅在PUBLISH消息中相关); 遗嘱(Will):如果设置,表示客户端请求遗嘱主题和遗嘱消息提示(仅在CONNECT消息中相关); 清除会话(CleanSession):与MQTT含义相同,但扩展了遗嘱主题和遗嘱消息(仅在CONNECT消息中相关); 主题ID类型(TopicIdType):指示此消息中包含的主题ID或主题名称字段是普通主题ID(设置为“0b00”)、预定义主题ID(设置为“0b01”)还是短主题名称(设置为“0b10”)。值“0b11”被保留。参见第3节和6.7节,了解各种类型的主题ID的定义。 5.3.5 网关地址 网关地址(GwAdd)字段长度可变,包含一个网关的地址。它依赖于MQTT-SN操作的网络,并在此字段的第一个字节中指示。例如,在ZigBee网络中,网络地址长度为2字节。 5.3.6 网关ID 网关ID(GwId)字段长度为1字节,唯一地标识一个网关。 版权所有 © 国际商业机器公司1999, 2013。保留所有权利。 5.3.7 消息ID 消息ID字段长度为2字节,对应于MQTT中的“消息ID”参数。它允许发送者将消息与其相应的确认消息匹配。 5.3.8 协议ID 协议ID长度为1字节。它仅在CONNECT消息中出现,对应于MQTT的“协议名称”和“协议版本”。它编码为0x01。所有其他值都是保留的。 5.3.9 半径 半径字段长度为1字节,指示广播半径的值。值0x00表示“向网络中的所有节点广播”。 5.3.10 返回码 1字节长的返回码字段的值及其含义如表5所示。 返回码值含义0x00接受0x01拒绝:拥挤0x02拒绝:无效的主题ID0x03拒绝:不支持0x04 - 0xFF保留 表5:返回码值 5.3.11 主题ID 主题ID字段长度为2字节,包含主题ID的值。值“0x0000”和“0xFFFF”是保留的,因此不应使用。 5.3.12 主题名称 主题名称字段长度可变,包含指定主题名称的UTF8编码字符串。 5.3.13 遗嘱消息 遗嘱消息字段长度可变,包含遗嘱消息。 5.3.14 遗嘱主题 遗嘱主题字段长度可变,包含遗嘱主题名称。 5.4 个别消息的格式 本节规定了个别MQTT-SN消息的格式。所有消息都用1字节长度字段描述。在3字节长度字段的情况下,消息格式可以直接推导,因此没有提及。 版权所有 © 国际商业机器公司1999, 2013。保留所有权利。 5.4.1 ADVERTISE 长度 消息类型 网关ID 持续时间(字节 0) (1) (2) (3,4)表6:ADVERTISE消息ADVERTISE消息由网关定期广播,以宣告其存在。下一次广播时间的时间间隔在此消息的持续时间字段中指示。其格式如表6所示: 长度和消息类型:见5.2节。 网关ID:发送此消息的网关的ID。 持续时间:直到此网关广播下一个ADVERTISE的时间间隔。 5.4.2 SEARCHGW 长度 消息类型 半径(字节 0) (1) (2)表7:SEARCHGW消息当客户端寻找网关时,会广播SEARCHGW消息。SEARCHGW的广播半径是有限的,取决于客户端部署的密度,例如,在非常密集的网络中,每个MQTT-SN客户端都可以通过1跳传输相互到达的情况下,只进行1跳广播。SEARCHGW消息的格式如表7所示: 长度和消息类型:见5.2节。 半径:此消息的广播半径。当MQTT-SN将此消息传输给底层网络层时,也会指示广播半径。 5.4.3 GWINFO 长度 消息类型 网关ID 网关地址*(字节 0) (1) (2) (3:n)(*) 如果消息由客户端发送,则包含表8:GWINFO消息GWINFO消息作为对SEARCHGW消息的响应通过底层层的广播服务发送,广播半径如SEARCHGW消息中所示。如果由网关发送,它只包含发送网关的ID;否则,如果由客户端发送,它还包括网关的地址,见表8: 长度和消息类型:见5.2节。 网关ID:网关的ID。 5.4.1 广告 长度 消息类型 网关ID 持续时间(字节0) (1) (2) (3,4)表6:广告消息广告消息由网关定期广播以宣告其存在。下一次广播时间间隔在此消息的持续时间字段中指示。其格式如表6所示: 长度和消息类型:参见5.2节。 网关ID:发送此消息的网关的ID。 持续时间:直到此网关下一次广播广告的时间间隔。 5.4.2 搜索网关 长度 消息类型 广播半径(字节0) (1) (2)表7:搜索网关消息当客户端寻找网关时,会广播搜索网关消息。搜索网关的广播半径是有限制的,取决于客户端部署的密度,例如,在一个非常密集的网络中,每个MQTT-SN客户端在1跳传输内相互可达,只需要1跳广播。搜索网关消息的格式如表7所示: 长度和消息类型:参见5.2节。 广播半径:此消息的广播半径。当MQTT-SN传输此消息时,广播半径也会指示给底层网络层。 5.4.3 网关信息 长度 消息类型 网关ID 网关地址*(字节0) (1) (2) (3:n)(*) 如果消息由客户端发送,则仅包含表8:网关信息消息网关信息消息是响应搜索网关消息而通过底层层的广播服务发送的。如果由网关发送,它只包含发送网关的ID;否则,如果由客户端发送,它还包括网关的地址,见表8: 长度和消息类型:参见5.2节。 网关ID:网关的ID。 网关地址:指示的网关的地址;可选,只在客户端发送此消息时包括。与搜索网关消息一样,此消息的广播半径在MQTT-SN传输此消息时也会指示给底层网络层。 5.4.4 连接 长度 消息类型 标志 协议ID 持续时间 客户端ID(字节0) (1) (2) (3) (4,5) (6:n)表9:连接消息客户端发送连接消息以建立连接。其格式如表9所示: 长度和消息类型:参见5.2节。 标志: DUP, QoS, Retain, TopicIdType:未使用。 Will:如果设置,表示客户端请求遗嘱主题和遗嘱消息提示; CleanSession:与MQTT含义相同,但扩展到了遗嘱主题和遗嘱消息(参见6.3节)。 协议ID:对应于MQTT连接消息的“协议名称”和“协议版本”。 持续时间:与MQTT相同,包含保持活动定时器的值。 客户端ID:与MQTT相同,包含客户端ID,是一个1-23个字符长的字符串,唯一标识服务器中的客户端。 5.4.5 连接确认 长度 消息类型 返回码(字节0) (1) (2)表10:连接确认消息服务器响应客户端的连接请求发送连接确认消息。其格式如表10所示: 长度和消息类型:参见5.2节。 返回码:根据表5编码。 5.4.6 遗嘱主题请求 长度 消息类型(字节0) (1)表11:遗嘱主题请求和遗嘱消息请求 5.4.7 遗嘱主题 长度 消息类型 标志 遗嘱主题(字节0) (1) (2) (3:n)表12:遗嘱主题消息客户端发送遗嘱主题消息作为对遗嘱主题请求消息的响应,以将其遗嘱主题名称传输给网关。其格式如表12所示: 长度和消息类型:参见5.2节。 标志: DUP:未使用。 QoS:与MQTT相同,包含遗嘱QoS Retain:与MQTT相同,包含遗嘱保留标志 Will:未使用 CleanSession:未使用 TopicIdType:未使用。 遗嘱主题:包含遗嘱主题名称。空的遗嘱主题消息是没有标志和遗嘱主题字段的遗嘱主题消息(即它正好2字节长)。客户端使用它来删除服务器中存储的遗嘱主题和遗嘱消息,参见6.4节。 5.4.8 遗嘱消息请求 网关发送遗嘱消息请求消息,请求客户端发送遗嘱消息。其格式如表11所示:它只有头部,没有变量部分。 5.4.9 遗嘱消息 长度 消息类型 遗嘱消息(字节0) (1) (2:n)表13:遗嘱消息客户端作为对遗嘱消息请求的响应发送遗嘱消息,以将其遗嘱消息传输给网关。其格式如表13所示: 长度和消息类型:参见5.2节。 遗嘱消息:包含遗嘱消息。 5.4.10 注册 长度 消息类型 主题ID 消息ID 主题名称(字节0) (1) (2,3) (4,5) (6:n)表14:注册消息客户端发送注册消息给网关,请求为包含的主题名称分配一个主题ID值。网关也发送注册消息给客户端,通知其已分配给包含的主题名称的主题ID值。其格式如表14所示: 长度和消息类型:参见5.2节。 主题ID:如果由客户端发送,则编码为0x0000,此时不相关;如果由网关发送,则包含分配给TopicName字段中包含的主题名称的主题ID值; 消息ID:应该编码,以便用于识别相应的REGACK消息。 主题名称:包含主题名称。 5.4.11 注册确认 长度 消息类型 主题ID 消息ID 返回码(字节0) (1) (2,3) (4,5) (6)表15:注册确认消息客户端或网关发送注册确认消息,作为对接收和处理注册消息的确认。其格式如表15所示: 长度和消息类型:参见5.2节。 主题ID:在PUBLISH消息中将作为主题ID使用的值; 消息ID:与相应注册消息中包含的值相同。 返回码:“已接受”,或拒绝原因。 5.4.12 发布 长度 消息类型 标志 主题ID 消息ID 数据(字节0) (1) (2) (3-4) (5-6) (7:n)表16:发布消息此消息由客户端和网关用于发布某个主题的数据。其格式如表16所示: 长度和消息类型:参见5.2节。 标志: DUP:与MQTT相同,指示消息是首次发送还是重传。 QoS:与MQTT相同,包含此发布消息的QoS级别。 Retain:与MQTT相同,包含保留标志。 Will:未使用 CleanSession:未使用 TopicIdType:指示TopicId字段中包含的主题ID的类型。 TopicId:包含发布数据所针对的主题ID值或短主题名称。 MsgId:与MQTT的“消息ID”含义相同;仅在QoS级别1和2的情况下相关,否则编码为0x0000。 数据:发布的数据。 5.4.13 PUBACK 长度 消息类型 主题ID 消息ID 返回码(字节0) (1) (2,3) (4,5) (6)表17:PUBACK消息网关或客户端发送PUBACK消息作为对接收和处理QoS级别1或2的发布消息的确认。在出现错误的情况下,也可以作为对发布消息的响应发送;然后在返回码字段中指示错误原因。其格式如表17所示: 长度和消息类型:参见5.2节。 主题ID:与相应发布消息中包含的值相同。 消息ID:与相应发布消息中包含的值相同。 返回码:“已接受”,或拒绝原因。 5.4.14 PUBREC, PUBREL, 和 PUBCOMP 长度 消息类型 消息ID(字节0) (1) (2-3)表18:PUBREC, PUBREL, 和 PUBCOMP消息与MQTT相同,PUBREC、PUBREL和PUBCOMP消息与QoS级别2的发布消息一起使用。它们的格式如表18所示: 长度和消息类型:参见5.2节。 消息ID:与相应发布消息中包含的值相同。 5.4.15 订阅 订阅消息由客户端使用,用于订阅某个特定的主题名称。其格式如表19所示: 长度和消息类型:参见5.2节。 标志: DUP:与MQTT相同,指示消息是首次发送还是重传。 QoS:与MQTT相同,包含此主题请求的QoS等级。 Retain:未使用 Will:未使用 CleanSession:未使用 TopicIdType:指示消息末尾包含的信息类型,即“0b00”主题名称,“0b01”预定义主题ID,“0b10”短主题名称,以及“0b11”保留。 消息ID:应编码,以便用于识别相应的SUBACK消息。 主题名称或主题ID:根据TopicIdType字段指示,包含主题名称、主题ID或短主题名称。 5.4.16 订阅确认 长度 消息类型 标志 主题ID 消息ID 返回码(字节0) (1) (2) (3,4) (5,6) (7)表20:订阅确认消息订阅确认消息由网关发送给客户端,作为对接收和处理订阅消息的确认。其格式如表20所示: 长度和消息类型:参见5.2节。 标志: DUP:未使用。 QoS:与MQTT相同,包含授予的QoS等级。 Retain:未使用。 Will:未使用 CleanSession:未使用 TopicIdType:未使用 5.4.16 订阅确认 长度 消息类型 标志 主题ID 消息ID 返回码(字节0) (1) (2) (3,4) (5,6) (7)表20:订阅确认消息网关发送订阅确认消息给客户端,作为对接收和处理订阅消息的确认。其格式如表20所示: 长度和消息类型:参见5.2节。 标志: DUP:未使用。 QoS:与MQTT相同,包含授予的QoS级别。 Retain:未使用。 Will:未使用。 CleanSession:未使用。 TopicIdType:未使用。 主题ID:在“已接受”的情况下,网关在向客户端发送PUBLISH消息时将使用该值作为主题ID(在订阅短主题名称或包含通配符字符的主题名称的情况下不相关)。 消息ID:与相应的订阅消息中包含的值相同。 返回码:“已接受”,或拒绝原因。 5.4.17 取消订阅 客户端发送取消订阅消息给网关,以取消订阅命名主题。其格式如表19所示: 长度和消息类型:参见5.2节。 标志: DUP:未使用。 QoS:未使用。 Retain:未使用。 Will:未使用。 CleanSession:未使用。 TopicIdType:指示消息末尾包含的信息类型,即“0b00”主题名称,“0b01”预定义主题ID,“0b10”短主题名称,和“0b11”保留。 消息ID:应编码以便用来识别相应的订阅确认消息。 主题名称或主题ID:包含主题名称、预定义主题ID或短主题名称,如TopicIdType字段所示。 5.4.18 取消订阅确认 长度 消息类型 消息ID(字节0) (1) (2-3)表21:取消订阅确认消息网关发送取消订阅确认消息以确认接收和处理取消订阅消息。其格式如表21所示: 长度和消息类型:参见5.2节。 消息ID:与相应取消订阅消息中包含的值相同。 5.4.19 PING请求 长度 消息类型 客户端ID(可选)(字节0) (1) (2:n)表22:PING请求消息与MQTT一样,PING请求消息是从连接的客户端发送或接收的“你还活着吗”的消息。其格式如表22所示: 长度和消息类型:参见5.2节。 客户端ID:包含客户端ID;此字段为可选,由“休眠”客户端在进入“唤醒”状态并等待服务器/网关发送的消息时包含,更多详情参见6.14节。 5.4.20 PING响应 长度 消息类型(字节0) (1)表23:PING响应消息与MQTT一样,PING响应消息是对PING请求消息的回应,意味着“是的,我还活着”。保持活动消息可由连接的客户端或网关发送,流向任一方向。其格式如表23所示:它只有头部,没有变量部分。此外,网关发送PING响应消息通知休眠客户端,表示没有更多为该客户端缓冲的消息,更多详情参见6.14节。 5.4.21 断开连接 长度 消息类型 持续时间(可选)(字节0) (1) (2-3)表24:断开连接消息断开连接消息的格式如表24所示: 长度和消息类型:参见5.2节。 持续时间:包含休眠定时器的值;此字段为可选,由希望进入“休眠”状态的“休眠”客户端包含,更多详情参见6.14节。与MQTT一样,客户端发送断开连接消息表示希望关闭连接。网关将通过向客户端返回一个断开连接消息来确认收到该消息。服务器或网关也可能向客户端发送断开连接消息,例如,如果网关由于错误不能将收到的消息映射到客户端。接收到此类断开连接消息的客户端应尝试通过向网关或服务器发送连接消息再次建立连接。在所有这些情况下,断开连接消息不包含持续时间字段。客户端发送带有持续时间字段的断开连接消息时,希望进入“休眠”状态。网关也通过发送断开连接消息(不带持续时间字段)来确认收到此消息。 5.4.22 遗嘱主题更新 长度 消息类型 标志 遗嘱主题(字节0) (1) (2) (3:n)表25:遗嘱主题更新消息 遗嘱主题更新消息由客户端发送给网关/服务器,以更新其在网关/服务器中存储的遗嘱主题名称。其格式如表25所示: 长度和消息类型:参见5.2节。 标志: DUP:未使用。 QoS:与MQTT相同,包含遗嘱QoS。 Retain:与MQTT相同,包含遗嘱保留标志。 Will:未使用。 CleanSession:未使用。 TopicIdType:未使用。 遗嘱主题:包含遗嘱主题名称。空的遗嘱主题更新消息是没有标志和遗嘱主题字段的遗嘱主题更新消息(即它正好2字节长)。客户端使用它来删除其在网关/服务器中存储的遗嘱主题和遗嘱消息。 5.4.23 遗嘱消息更新 长度 消息类型 遗嘱消息(字节0) (1) (2:n)表26:遗嘱消息更新消息遗嘱消息更新消息由客户端发送给网关/服务器,以更新其在网关/服务器中存储的遗嘱消息。其格式如表26所示: 长度和消息类型:参见5.2节。 遗嘱消息:包含遗嘱消息。 5.4.24 遗嘱主题响应 长度 消息类型 返回码(字节0) (1) (2)表27:遗嘱主题响应和遗嘱消息响应消息遗嘱主题响应消息由网关发送,以确认收到并处理了遗嘱主题更新消息。其格式如表27所示: 长度和消息类型:参见5.2节。 返回码:“已接受”,或拒绝原因。 5.4.25 遗嘱消息响应 遗嘱消息响应消息由网关发送,以确认接收并处理了遗嘱消息更新消息。其格式如表27所示: 长度和消息类型:参见5.2节。 返回码:“已接受”,或拒绝原因。 5.5 转发器封装 如第4节所述,如果网关没有直接连接到他们的无线传感网络,MQTT-SN客户端也可以通过转发器访问网关。转发器简单地封装它在无线侧收到的MQTT-SN帧,并不改变地转发给网关;反方向也是如此,它解封装从网关收到的帧,并同样不改变地发送给客户端。长度 消息类型 控制 无线节点ID MQTT-SN消息(字节0) (1) (2) (3:n) (n+1,m)表28:封装的MQTT-SN帧的格式封装的MQTT-SN帧的格式如表28所示: 长度:1字节长,指定到“无线节点ID”字段结束的字节数(包括长度字节本身)。 消息类型:编码为“0xFE”,见表3。 控制:控制字节包含网关和转发器之间交换的控制信息。其格式如表29所示: 广播半径:广播半径(只在网关到转发器的方向上相关)。 所有剩余位都保留。 无线节点ID:标识发送或应接收封装的MQTT-SN消息的无线节点。此ID与无线节点的地址之间的映射由转发器实现(如果需要)。 MQTT-SN消息:根据表1编码的MQTT-SN消息。保留 广播半径(位7:2) (位1,0)表29:控制字节的格式 6 功能描述 MQTT-SN的一个重要设计点是尽可能接近MQTT。因此,所有协议语义应尽可能保持与MQTT定义的相同。接下来我们将关注那些对MQTT来说是新的或有所偏离的点。 6.1 网关广告和发现 此程序是新的,MQTT中不存在。 网关可以通过定期向网络中当前的所有设备广播ADVERTISE(广告)消息来宣告其存在。网关只有在连接到服务器(或自身就是服务器)时才应广告其存在。 同一网络中可以同时有多个活跃的网关。在这种情况下,它们将拥有不同的ID。客户端可以自行决定连接哪个网关。然而,在任何时间点,客户端只允许连接到一个网关。 客户端应维护一个活跃网关及其网络地址的列表。这个列表是通过接收到的ADVERTISE和GWINFO(网关信息)消息填充的。 网关发送下一个ADVERTISE消息的时间持续期TADV在ADVERTISE消息的持续时间字段中指示。客户端可以使用这些信息来监控网关的可用性。例如,如果它连续NADV次没有收到来自某个网关的ADVERTISE消息,它可能会假设网关已经下线,并将其从活跃网关列表中移除。同样,如果备用模式的网关连续几次错过某个网关的广告,则会变为活跃状态(即开始发送ADVERTISE消息)。 由于ADVERTISE消息被广播到整个无线网络,网关发送两个ADVERTISE消息之间的时间间隔TADV应足够大(例如,大于15分钟),以避免网络中的带宽拥堵。 TADV的大值将导致寻找网关的新客户端等待时间过长。为了缩短这个等待时间,客户端可以广播SEARCHGW(搜索网关)消息。为了防止当多个客户端几乎同时开始搜索网关时发生广播风暴,发送SEARCHGW消息会被延迟一个在0到TSEARCHGW之间的随机时间。如果在这段延迟时间内,客户端接收到另一个客户端发送的与其想要发送的相同的SEARCHGW消息,它将取消发送SEARCHGW消息的传输,并表现得就像SEARCHGW消息是由它自己发送的一样。 SEARCHGW消息的广播半径Rb是有限的,例如,在MQTT-SN客户端密集部署的情况下,限制为单跳。 收到SEARCHGW消息后,网关用包含其ID的GWINFO消息作为回应。同样,如果客户端在其活跃网关列表中至少有一个活跃网关,则也用GWINFO消息作答。如果客户端在其列表中有多个网关,它将从列表中选择一个网关,并将该信息包含在GWINFO消息中。 与SEARCHGW消息一样,GWINFO消息也以相同的半径Rb广播,这在SEARCHGW消息中指示。当这两条消息传递给底层层进行传输时,也会给出半径Rb。 为了给网关优先权,客户端将延迟发送GWINFO消息一个随机时间TGWINFO。如果在这段延迟时间内,客户端接收到GWINFO消息,它将取消发送其GWINFO消息。 如果没有响应,SEARCHGW消息可以被重新传输。在这种情况下,两个连续SEARCHGW消息之间的时间间隔应该指数级增加。 6.2 客户端的连接设置 与MQTT一样,MQTT-SN客户端需要先与网关建立连接,然后才能与网关交换信息。与网关建立连接的程序如图3所示,假设客户端请求网关提示传输遗嘱主题和遗嘱消息。通过设置CONNECT消息的Will标志来表示此请求。客户端在接收到相应的请求消息WILLTOPICREQ和WILLMSGREQ后, 如果网关无法接受连接请求(例如,因为拥堵或不支持CONNECT消息中指示的某个功能),网关会返回一个带有拒绝原因的CONNACK消息。 6.3 清除会话 在MQTT中,当客户端断开连接时,其订阅不会被删除。它们是持久的,对于新连接仍然有效,直到客户端显式取消订阅,或客户端建立新的连接时设置了“清除会话”标志。 在MQTT-SN中,“清除会话”的含义扩展到了遗嘱功能,即不仅订阅是持久的,遗嘱主题和遗嘱消息也是持久的。CONNECT中的“CleanSession”和“Will”两个标志具有以下含义: CleanSession=true, Will=true:网关将删除与客户端相关的所有订阅和遗嘱数据,并开始提示新的遗嘱主题和遗嘱消息。 CleanSession=true, Will=false:网关将删除与客户端相关的所有订阅和遗嘱数据,并返回CONNACK(不提示遗嘱主题和遗嘱消息)。 CleanSession=false, Will=true:网关保留所有存储的客户端数据,但提示新的遗嘱主题和遗嘱消息。新收到的遗嘱数据将覆盖存储的遗嘱数据。 CleanSession=false, Will=false:网关保留所有存储的客户端数据,并返回CONNACK(不提示遗嘱主题和遗嘱消息)。 注意,如果客户端想在建立连接时只删除其遗嘱数据,它可以发送一个“CleanSession=false”和“Will=true”的CONNECT消息,并在被提示时向网关发送一个空的WILLTOPIC消息。它也可以发送一个“CleanSession=false”和“Will=false”的CONNECT消息,并使用6.4节的程序来删除或修改遗嘱数据。 6.4 更新遗嘱数据的程序 在连接期间的任何时候,客户端都可以通过发送WILLTOPICUPD或WILLMSGUPD消息来更新存储在网关中的遗嘱数据。这两条消息中包含的信息将覆盖网关中存储的相应信息。网关将确认这两条消息。这两条消息可以相互独立使用。 注意,一个空的WILLTOPICUPD消息将删除网关存储的遗嘱主题和遗嘱消息。 6.5 主题名称注册程序 由于无线传感网络的带宽有限和消息负载较小,数据不会像MQTT中那样与其主题名称一起发布。引入了一种注册程序,允许客户端和网关在可以开始使用短主题ID发送PUBLISH消息之前,通知对方短主题ID及其对应的主题名称。 为了注册一个主题名称,客户端向网关发送一个REGISTER消息。如果注册被接受,网关将为接收到的主题名称分配一个主题ID,并通过REGACK消息返回给客户端。如果注册未被接受,也会返回REGACK消息给客户端,并在ReturnCode字段中编码失败原因。 在收到ReturnCode为“已接受”的REGACK消息后,客户端应使用分配的主题ID发布对应主题名称的数据。如果REGACK包含拒绝代码,客户端可以稍后再次尝试注册。如果返回码为“拒绝:拥堵”,客户端应等待一段时间TWAIT后再重新开始注册程序。 任何时候,客户端可能只有一个未完成的REGISTER消息,即它必须等待REGACK消息才能注册另一个主题名称。 网关向客户端发送REGISTER消息,如果它想通知客户端将来发送PUBLISH消息时将使用的主题名称和分配的主题ID。例如,当客户端重新连接而没有设置“CleanSession”标志,或客户端已订阅包含通配符字符如#或+的主题名称时,就会发生这种情况。 6.6 客户端的发布程序 在成功地向网关注册了主题名称后,客户端可以开始通过向网关发送PUBLISH消息发布与注册主题名称相关的数据。PUBLISH消息包含分配的主题ID。 支持所有三个QoS级别及其相应的消息流,如MQTT定义。唯一的区别是PUBLISH消息中使用主题ID代替主题名称。 无论请求的QoS级别如何,客户端可能收到对其PUBLISH的响应是一个PUBACK消息,其中包含: ReturnCode=“拒绝:无效的主题ID”:在这种情况下,客户端需要再次注册主题名称,然后才能发布与该主题名称相关的数据;或 ReturnCode=“拒绝:拥堵”:在这种情况下,客户端应至少在TWAIT时间内停止向网关发布。 任何时候,客户端可能只有一个QoS级别1或2的PUBLISH消息未完成,即它必须等待这次PUBLISH消息交换结束后,才能开始新的级别1或2交易。 6.7 预定义的主题ID和短主题名称 如6.5节所述,主题ID是基于字符串的主题名称的两字节长的替代品。客户端需要使用REGISTER程序通知网关它想要使用的主题名称,并从网关获取相应的主题ID。然后,它将在发送给网关的PUBLISH消息中使用这个主题ID。反方向,PUBLISH消息也包含2字节的主题ID(而不是基于字符串的主题名称)。客户端通过先前的SUBSCRIBE程序或网关启动的REGISTER程序,被告知主题ID和主题名称之间的关系。 6.5 主题名称注册程序 由于无线传感网络中的带宽有限和消息负载较小,数据不会像在MQTT中那样连同其主题名称一起发布。引入了注册程序,允许客户端和网关在开始使用短主题ID发送PUBLISH消息之前,通知对方短主题ID及其对应的主题名称。客户端向网关发送REGISTER消息以注册一个主题名称。如果注册被接受,网关将为接收到的主题名称分配一个主题ID,并通过REGACK消息返回给客户端。如果注册未被接受,也会通过REGACK消息返回给客户端,并在ReturnCode字段中编码失败原因。在收到ReturnCode=“已接受”的REGACK消息后,客户端应使用分配的主题ID来发布对应主题名称的数据。如果REGACK包含拒绝代码,客户端可以稍后再次尝试注册。如果返回码为“拒绝:拥塞”,客户端应在重新开始注册程序之前等待一段时间TWAIT。客户端在任何时间点只能有一个REGISTER消息未决,即它必须等待REGACK消息之后才能注册另一个主题名称。网关向客户端发送REGISTER消息,如果它想通知客户端将在稍后发送PUBLISH消息时使用的主题名称和分配的主题ID。例如,当客户端重新连接而没有设置“CleanSession”标志,或客户端已订阅包含通配符字符如#或+的主题名称时,就会发生这种情况。 6.6 客户端发布程序 在成功注册主题名称后,客户端可以开始通过向网关发送PUBLISH消息来发布与注册主题名称相关的数据。PUBLISH消息包含分配的主题ID。支持所有三个QoS级别及其相应的消息流程,如MQTT中定义的那样。唯一的区别是在PUBLISH消息中使用主题ID代替主题名称。无论请求的QoS级别如何,客户端可能会收到PUBLISH的响应PUBACK消息,其中包含以下内容之一:·ReturnCode=“拒绝:无效的主题ID”:在这种情况下,客户端需要再次注册主题名称,然后才能发布与该主题名称相关的数据;或·ReturnCode=“拒绝:拥塞”:在这种情况下,客户端应停止向网关发布至少TWAIT时间。在任何时间点,客户端可能只有一个QoS级别1或2的PUBLISH消息未决,即它必须等待这个PUBLISH消息交换结束之后,才能开始新的级别1或2事务。 6.7 预定义主题ID和短主题名称 如6.5节所述,主题ID是基于字符串的主题名称的两字节长的替代品。客户端需要使用REGISTER程序通知网关它想使用的主题名称,并从网关获取相应的主题ID。然后,它将在发送给网关的PUBLISH消息中使用此主题ID。相反方向上,PUBLISH消息也包含2字节的主题ID(而不是基于字符串的主题名称)。客户端通过之前的SUBSCRIBE程序或网关启动的REGISTER程序,了解主题ID和主题名称之间的关系。"预定义"主题ID是客户端应用程序和网关预先知道其映射到主题名称的主题ID。这在消息的Flags字段中指示。使用预定义主题ID时,双方可以立即开始发送PUBLISH消息;不需要像"普通"主题ID那样的REGISTER程序。如果收到一个带有预定义主题ID的PUBLISH消息,其映射到主题名称未知,则接收方应返回一个PUBACK,ReturnCode=“拒绝:无 6.10 网关的发布程序 类似于第6.6节中描述的客户端的发布程序,网关发送带有在SUBACK消息中返回给客户端的主题ID值的PUBLISH消息。 在发送PUBLISH消息之前,网关可能会发送一个REGISTER消息以通知客户端有关主题名称及其分配的主题ID值。例如,当客户端重新连接时没有选择清理会话,或者订阅了带有通配符字符的主题名称时,就会发生这种情况。在收到REGISTER消息后,客户端回复一个REGACK消息。网关将等待REGACK消息,然后再将PUBLISH消息发送给客户端。 客户端可以通过带有拒绝原因的REGACK消息拒绝REGISTER消息;这相当于取消订阅REGISTER消息中指示的主题名称。注意,只有通过第6.9节中描述的取消订阅程序才能取消订阅带有通配符字符的主题名称,而不能通过拒绝REGISTER消息来完成,因为REGISTER消息从不包含带有通配符字符的主题名称。 如果客户端收到一个带有未知主题ID值的PUBLISH消息,它应该回复一个ReturnCode=“拒绝:无效的主题ID”的PUBACK消息。这将触发网关删除或更正错误的主题ID分配。 注意,如果主题名称或数据太长而不能适应REGISTER或PUBLISH消息,网关会默默地中止发布程序,即不会向受影响的订阅者发送警告。 6.11 保持活动和PING程序 与MQTT一样,保持活动计时器的值在CONNECT消息中指示。客户端应在每个保持活动时间周期内发送一个PINGREQ消息,网关用PINGRESP消息进行回应。 同样,当客户端收到其连接的网关发送的PINGREQ消息时,应用PINGRESP消息回复。否则,接收到的PINGREQ消息将被忽略。 客户端应使用此程序来监督其所连接的网关的活动状态。如果客户端在多次重传PINGREQ消息后仍未从网关收到PINGRESP,它应首先尝试连接到另一个网关,然后再尝试重新连接到这个网关(参见第6.13节)。注意,由于客户端的保持活动计时器彼此不同步,在网关故障的情况下,所有受影响的客户端几乎同时向新网关发送CONNECT消息的风险实际上是不存在的。 6.12 客户端的断开连接程序 客户端发送DISCONNECT消息给网关,表明它即将关闭连接。此后,客户端需要与网关建立新连接才能再次与网关交换信息。与MQTT相似,发送DISCONNECT消息不会影响现有订阅和遗嘱数据,如果设置了CleanSession标志。它们将持续存在,直到它们被客户端显式取消订阅、删除或修改,或者客户端与设置了CleanSession标志的新连接建立。网关通过向客户端返回一个DISCONNECT消息来确认收到DISCONNECT消息。 客户端也可能接收到网关发送的未经请求的DISCONNECT。例如,当网关由于错误无法识别收到消息所属的客户端时,就可能发生这种情况。在收到此类DISCONNECT消息后,客户端应尝试通过向网关发送CONNECT消息再次建立连接。 6.13 客户端的重传程序 所有“单播”到网关的消息(即使用网关的单播地址发送而不是广播)以及期待网关回复的消息,都由重试计时器Tretry和重试计数器Nretry监控。客户端在发送消息时启动重试计时器Tretry,并在收到期待的网关回复时停止。如果Tretry超时且未收到期待的网关回复,客户端将重新传输消息。经过Nretry次重传后,客户端将中止程序并假设其MQTT-SN连接到网关已断开。然后,它应尝试连接到另一个网关,仅在重新连接到前一个网关失败时尝试。 6.14 支持休眠客户端 休眠客户端是居住在(电池操作的)设备上的客户端,这些设备希望尽可能节省能量。这些设备需要在不活跃时进入睡眠模式,并在有数据发送或接收时唤醒。服务器/网关需要了解这些客户端的睡眠状态,并将发送给它们的消息缓存起来,以便它们唤醒时后续交付。 图4:客户端状态转换图 如图4所示,从服务器/网关的角度看,客户端可能处于以下状态之一:活跃、睡眠、唤醒、断开连接或丢失。当服务器/网关收到来自该客户端的CONNECT消息时,客户端处于活跃状态,如第6.2节所述。服务器/网关使用“保持活动”计时器监控此状态,如第6.11节所述。如果服务器/网关在超过CONNECT消息中指示的保持活动持续时间的时间内未收到客户端的任何消息,网关将认为该客户端已丢失,并且例如为该客户端激活遗嘱功能。 当服务器/网关接收到一个不包含持续时间字段的DISCONNECT消息时,客户端进入断开连接状态。服务器/网关不对此状态进行时间监控。 如果客户端想要休眠,它发送一个包含睡眠持续时间的DISCONNECT消息。服务器/网关用一个DISCONNECT消息回复该消息,并将客户端视为处于睡眠状态,参见图5。睡眠状态由服务器/网关使用指示的睡眠持续时间监控。如果服务器/网关在超过睡眠持续时间的时间内未收到客户端的任何消息,服务器/网关将认为该客户端已丢失,并且-如同保持活动程序一样-例如激活遗嘱功能。 睡眠程序 在睡眠状态期间,所有需要发送给客户端的消息都在服务器/网关处缓存。 图5:睡眠程序 当服务器/网关收到客户端的PINGREQ消息时,睡眠计时器停止。像CONNECT消息一样,这个PINGREQ消息包含客户端ID。然后识别的客户端处于唤醒状态。如果服务器/网关有为客户端缓存的消息,它将把这些消息发送给客户端。服务器/网关通过PINGRESP消息结束向客户端传输消息,即服务器/网关在发送PINGRESP消息后会认为客户端处于睡眠状态并重新启动睡眠计时器。 如果服务器/网关没有为客户端缓存任何消息,它会立即回复PINGRESP消息,将客户端返回到睡眠状态,并为该客户端重新启动睡眠计时器。 在向服务器/网关发送PINGREQ后,客户端使用第6.13节的“重传程序”来监督由服务器/网关发送的消息的到达,即它在接收到非PINGRESP的消息时重新启动计时器Tretry,并在接收到PINGRESP时停止它。当计时器Tretry超时时,PINGREQ消息被重传并重新启动计时器Tretry。为了避免因过度重传PINGREQ消息(例如,如果它失去了网关)而导致电池耗尽,客户端应限制PINGREQ消息的重传(例如,通过重试计数器),并在达到限制且仍未收到PINGRESP消息时回到睡眠状态。 从睡眠或唤醒状态,客户端可以通过发送CONNECT消息返回到活跃状态,或通过发送普通DISCONNECT消息(即没有持续时间字段的)返回到断开连接状态。客户端还可以通过发送带有新的睡眠持续时间值的DISCONNECT消息来修改其睡眠持续时间。 请注意,休眠客户端只应在它只是想检查服务器/网关是否有任何消息为其缓存时进入唤醒状态,并尽快返回到睡眠状态,而不向服务器/网关发送任何消息。否则,它应通过向服务器/网关发送CONNECT消息返回到活跃状态。 7 实施注意事项 7.1 支持QoS级别-1 因为QoS级别-1的PUBLISH消息可以随时由客户端发送(即使没有建立连接),透明网关需要为这些消息与服务器维持一个专用的MQTT连接。一个聚合或混合网关可以使用任何聚合MQTT连接将这些消息转发给服务器。 7.2 定时器和计数器的“最佳实践”值 表30显示了本规范中定义的定时器和计数器的“最佳实践”值。 定时器/计数器推荐值TADV大于15分钟NADV2-3TSEARCHGW5秒TGWINFO5秒TWAIT大于5分钟Tretry10-15秒Nretry3-5表30:定时器和计数器的“最佳实践”值 服务器/网关的睡眠和保持活动定时器的“容忍度”取决于客户端指示的持续时间。例如,对于大于1分钟的持续时间,定时器值应比指示值高10%,如果少于此值,则高50%。 7.3 主题ID与主题名称的映射 强烈建议在网关中,主题ID与主题名称之间的映射表按客户端实现(而不是在所有客户端之间共享一个单一的池),以降低一个客户端的错误主题ID与另一个客户端的有效主题匹配,并因此导致向错误主题的发布,这可能会产生灾难性的后果。 7.4 与ZigBee相关的问题 在ZigBee网络中,网关不需要由协调器节点托管。但它应该位于一个始终在线的路由器节点上,以便随时接收客户端消息。 由于ZigBee网络/APS层的有效载荷长度短,MQTT-SN消息的最大长度限制为60字节。 --- ### 214. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT 的一个突出特点,使其在许多行业中获得广泛接受,是它允许使用任何格式来创建分层主题路径。例如,在一个乳品制造企业中,可以使用 DairyPlant01/Refrigerator03/DischargePressure 作为自定义的主题命名空间。 尽管这种灵活性允许您根据需要定义 MQTT 主题结构,但在扩展或集成不同系统时,由于缺乏标准化方法,它也带来了挑战。更在工业物联网(IIoT)或 SCADA 网络中,通常存在嵌套设备、资产和系统的复杂工业设置。 IIoT 中不同 MQTT 主题格式的挑战 以下是由于缺乏系统化和一致的 MQTT 主题命名格式而引入的一些挑战: IT-OT 互操作性挑战 使用不同 MQTT 主题结构的不同设备和应用程序很难集成到统一系统中。这导致来自不同供应商或工业操作的不同业务部门的数据交流和通信困难。 可扩展性问题 随着设备或主题数量的增长,配置、管理和监控大量非标准化 MQTT 主题结构的网络变得越来越复杂。这通常导致扩展能力降低,并增加了集成成本。 数据不一致性 如果设备或发布者使用不同的主题结构或命名约定,可能会对数据的来源或类型产生歧义,导致潜在的数据不一致性。在 IIoT 或 SCADA 系统中,数据的误解读或错误路由可能导致操作问题甚至安全问题。 IIoT 中标准化 MQTT 主题命名空间的好处 为了减轻上述许多挑战,MQTT Sparkplug 规范定义了用于 IIoT 网络的标准 MQTT 主题格式。通过提供标准化的主题命名空间定义,MQTT Sparkplug 帮助创建了一个更一致、有组织且互操作性更强的 MQTT 基础 IIoT 和操作数据系统环境。这使得部署、管理和扩展这些系统变得更加容易,同时确保数据易于访问和理解。 使用 Sparkplug 的标准主题命名空间定义,遵循 Sparkplug 规范的设备和系统可以无需任何额外配置或转换即可相互通信。此外,Sparkplug 的主题命名空间提供了数据的一致性和逻辑性组织,确保相似的数据点被分组在一起,数据易于定位。 随着越来越多的设备和系统采用 Sparkplug 规范,集成变得更简单。系统可以使用一套标准规则和逻辑进行集成,而不是为每个独特的主题结构定制集成。 通过标准化主题结构,更容易实施精细化的安全和访问控制措施。例如,可以根据主题命名空间的特定部分授予权限,确保设备和用户只能访问他们被授权查看的数据。 MQTT Sparkplug 主题命名空间的组成部分 为了提供一种结构化的方式,确保信息在 IIoT 环境中易于路由、理解和操作,Sparkplug 将 MQTT 主题命名空间细分为特定组成部分。因此,Sparkplug 主题命名空间的结构化特性如下所示: spBv1.0/[Group ID]/[Message Type]/[EON Node ID]/[Device ID] 以下是 MQTT Sparkplug 主题命名空间组成部分的详细说明: 命名空间 这始终以“spBv1.0”开头,表明该主题使用 Sparkplug B 版本 1.0 规范。这作为所使用协议版本的标识符,以及相关有效载荷数据的编码。 组号 这标识了网络边缘(EoN)节点和设备的逻辑分组。例如,您可能使用组 ID 来表示特定的工厂或工厂位置。它确保在不同组之间的数据隔离,有助于高效的数据管理和安全性。 消息类型 主题命名空间的消息类型组件指示如何处理 MQTT 有效载荷。以下消息类型组件为 Sparkplug 主题命名空间定义: NBIRTH:边缘节点出生证书。这是来自 EoN 的启动消息,用以宣告其存在并分享其配置。 NDEATH:边缘节点断开连接或故障的通知。 DBIRTH:设备出生证书。类似于 NBIRTH,但针对设备,宣告它们的存在和配置。 DDEATH:设备断开连接或故障的通知。 NDATA:来自边缘节点的数据消息。这些通常包括度量数据。 DDATA:来自设备的数据消息。类似于 NDATA,但专门针对设备相关度量。 NCMD:对边缘节点的命令。 DCMD:对设备的命令。 STATE:代表主机应用程序的状态。边缘节点订阅它以获取主机的在线状态。 网络边缘(EON)节点 ID 这唯一地标识了同一组中 EoN 中的特定边缘节点。EON 节点负责代表其控制或连接的设备报告数据。EON 节点 ID 有助于将命令定向到正确的节点,并将来自各种节点的数据进行分离。 设备 ID(可选) 如果消息与边缘节点控制的特定设备有关,设备 ID 将唯一地标识该设备。 下表显示了 MQTT Sparklug 主题命名空间每个组成部分的示例描述和示例。 NameDescriptionExamplenamespaceRoot element to set the sparkplug versionspBv1.0group_idLogical grouping of MQTT edge nodesFactoryAmessage_typeSpecific message typeNBIRTHedge_node_idID of a specific edge nodeProductionLine03device_idID of a specific device tied to an edge nodeSeatAssembly_PLC spBv1.0/FactoryA/DDATA]/ProductionLine03/SeatAssembly 需要注意的是,由组 ID 和边缘节点 ID 组合而成的边缘节点描述符在 MQTT Sparkplug 网络中的所有边缘节点之间必须是不同的。这意味着 Sparkplug 设置中的两个边缘节点不能共享相同的组 ID 和边缘节点 ID。 Sparkplug 边缘节点布局 在实际场景中实施 Sparkplug 主题命名空间 让我们看看 MQTT Sparkplug 主题命名空间定义在实际场景中的好处示例。 例如,在智能制造设施中,每条生产线可能包括许多机器,每台机器都生成温度、运行时间和错误率等度量数据。使用 Sparkplug 的主题命名空间,这些机器的消息可以被轻松地路由和分类。一个诸如 spBv1.0/FactoryA/DDATA/Line3/Machine7 的主题立即提供了关于消息来源和性质的上下文,确保监控工具、控制系统和操作员可以快速处理并对数据采取行动。 此外,Sparkplug 的主题命名空间不仅仅是高效的路由;它在系统诊断和故障排除中发挥着关键作用。例如,在能源领域,拥有多个面板的太阳能发电厂可以从 Sparkplug 的结构化消息传递中获益匪浅。如果面板发生故障,主题为spBv1.0/SolarFarmB/NDEATH/PanelArray5/Panel23的消息将立即通知操作员,不仅会出现问题,还会通知其在基础设施中的确切位置。Sparkplug 的主题命名空间使通信的粒度和清晰度成为可能,这在现实场景中非常宝贵,在现实场景中,快速响应时间可以带来显着的节省和更安全的操作。 结论 总结来说,MQTT Sparkplug 是一个旨在确保使用 MQTT 协议通信的设备、应用程序和服务之间的互操作性的规范,特别是在工业自动化领域。Sparkplug 中定义的主题命名空间在提供标准化的主题结构方面起着关键作用,这确保了跨各种设备和系统的一致数据表现、简化的设备命令和控制,以及改进的状态管理。 通过遵守 Sparkplug 主题命名空间,供应商和系统集成商可以无缝集成设备和软件解决方案,从而减少集成工作并确保 MQTT 基础 IIoT 部署中更可预测和可靠的通信。 --- ### 215. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Sparkplug 使用发布/订阅(Pub/Sub)架构模式,为可扩展且高效的通信提供了解决方案,这与过去40多年来工业自动化、离散制造业及石油和天然气行业中使用的传统轮询/响应协议截然不同。这意味着过去几十年的通信协议需要数据生产者(通常是 PLC)和数据消费者之间非常紧密的耦合。这种耦合使得改变工作流程和流程变得困难,使得建立新的系统和设施变得困难,并且使得在整个系统中使用和分析数据变得困难甚至不可能。 图1:轮询/响应方式 图 1 显示了从 PLC、网关和应用程序获取数据的传统轮询/响应方式。轮询系统向生成数据的设备请求数据,或者是特定数据的单一来源。为了尽快获取数据,轮询系统会以非常高的频率请求数据,否则新数据将无法及时提供给需要该数据的系统。这种方法效率非常低,因为它非常浪费带宽和处理能力。 在本次演示中,比较了 MQTT、OPC-UA 和 Modbus,并表明即使对于基本场景,使用 MQTT Sparkplug 与 OPC-UA 相比,效率也有数个数量级的提升。可以在此处找到演示文稿。如果您想通过加密通信来增加安全性(如果您通过互联网连接设备,则必须这样做),那么与 Sparkplug 相比,旧协议产生的开销甚至更大。 图 2 描述了系统需要对每个新的数据生产者进行轮询。这意味着在最坏的情况下,每个标签都需要单独轮询。 图2:众多制造者的轮询/响应 这种轮询方法在行业中广泛使用,特别是在Modbus和OPC-UA等协议中。数据产生的指数级增长以及工厂本地和全球范围内的超连接性显示了轮询/响应方法的局限性。如今,公司需要即时获取全球数百家工厂和数千台机器生成的数据,并希望所有利益相关者都能轻松访问重要数据,无论他们身在何处。行业现在终于迈向了一个必须打破数据孤岛的世界。 从技术角度来看,与现代发布/订阅方法相比,轮询/响应有一些严重的缺点: 无状态意识,大多数 IIoT 协议都无法感知状态,这意味着需要始终轮询状态,有时每个设备每秒轮询多次,以确保不会丢失重要数据或状态更改。 大量不必要的数据流量,即使没有发生状态更改或数据更改,数据生产者也会每秒被轮询多次。 仅定期检查新数据,没有基于即时推送的机制来获取发生的数据和事件。 轮询设备上的计算密集型,大量不必要的计算周期被浪费,因为即使数据没有改变,数据也会一直被请求。 轮询组件和轮询组件之间的紧密耦合。如果需要更改/更换数据生产者,则需要重新配置多个系统,可能会导致停机。 无法扩展到大量数据生产者。 显然有更好的方法。这就是为什么 MQTT Sparkplug 从一张白纸开始,并提出了这样的问题:“如果我们可以使用最轻量级的通信协议(MQTT),并结合过去 40 多年的经验教训,弥合 OT/IT 差距,实现即插即用的互操作性,那会怎样?” 为了克服传统协议的缺点,Sparkplug 使用基于现代发布-订阅的架构,如图 3 所示。 图3:发布/订阅架构 这种基于 MQTT 的架构具有以下优点: 异常报告:仅当发生变化时才发布数据和状态。 最小化计算密集度:设备和应用程序自行决定何时发送数据,并且不会不必要地浪费计算周期。 通过单个代理(集群)可扩展到数十万甚至数百万台设备,每天处理数十亿个标签数据和状态变化。 基于推送的通信。 完全解耦。要更改、添加或删除数据消费者或生产者,无需更改其他组件。 MQTT Sparkplug 在大多数行业中越来越受欢迎,可以用其相对于传统协议的明显优势来解释,甚至能够将这些传统协议集成到 Sparkplug 架构中。 --- ### 216. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 典型的工业物联网(IIoT)架构通过轮询/响应方式来连接各个组件。应用程序会直接从PLC、网关或服务器中通过诸如Modbus、西门子S7协议或OPC-UA等协议轮询数据。这种方法在只有少数几个系统需要集成时效果不错,但随着组件数量的增加,会导致一个难以维护的复杂架构。 图片1:未采用Sparkplug的工业IIoT架构 在这种架构中,系统通过点对点方式连接,从而使系统和数据紧密耦合在一起。现代的架构需要在IIoT系统中实现灵活性和清晰的职责分离。许多公司期望在IT环境中找到适应性、灵活性和易于实施的特性,同时也需要满足OT环境对可靠性、安全性和可预测性的需求。这种变革需要一种全新的架构。 图片2:IIoT的新架构 这种新的IIoT架构(如图片2所示)相较于传统IIoT架构有所优势: 数据生产者和消费者之间的解耦。 异常报告(RBE),节省了数据生产者和消费者的带宽、内存和计算能力。 一对多通信。数据只需发送一次,多个接收方就可以接收数据。 灵活性:设备和应用程序可以随时添加或移除,而不会影响整个系统。 通过集中的权限和策略处理实现数据治理。 通过从云到边缘的数据分发实现车间到云端的连接。 过去,许多公司已经采用MQTT来为其工厂创建解耦架构。这并不令人意外,因为MQTT最初是为SCADA系统设计的。但在IIoT用例中,仍然缺少一些部分,例如MQTT主题结构定义、MQTT状态管理和有效载荷数据定义。Sparkplug为MQTT增加了这些功能,通常情况下Sparkplug架构类似于图片3所示。 图片3:Sparkplug架构 原则与机制 Sparkplug架构之所以比传统方案更加优雅,是因为它基于以下原则和机制: 发布/订阅:使用MQTT作为底层应用的发布/订阅架构,从而解耦了数据的生产者和消费者。MQTT基于推送通信机制,这意味着数据会立即传递给所有感兴趣的各方。 异常报告:只有在数据和设备状态发生变化时才更新,从而在所有组件上大幅节省带宽和计算能力,因为只有新的和更新的数据才会被发送。 持续会话感知:Sparkplug和MQTT具备持续会话感知的特性。如果设备的在线/离线状态发生变化,它会通知所有关心这一状态的客户端。这个机制还确保了数据在传输过程中的连续性,比如当设备从离线状态恢复到在线状态时,数据传输会继续进行。使用Sparkplug,您可以实时准确地监控部署中所有设备、网关和应用程序的状态。 死亡和出生证明:Sparkplug引入了用于管理和发现设备状态的死亡和出生证明机制 。出生证明包含了有关设备及其将要发送的数据的信息,而死亡证明则利用MQTT的遗嘱和遗言机制来向所有关心的应用程序推送设备离线信息。 持久连接:所有设备、网关和应用程序默认保持在线,并通过持久的TCP连接进行通信。 自动发现:应用程序和设备能够自动发现Sparkplug部署中所有参与者将要发送的数据(及其对应的主题),以及当前连接的在线/离线设备。 标准化有效载荷定义:Sparkplug消息中所有消息的数据格式都进行了标准化,使得所有通信参与者都可以解码和编码数据。 标准化主题命名空间:所有Sparkplug参与者使用相同的主题命名空间。这个主题命名空间允许对特定数据进行精确的订阅,并支持动态地添加或移除参与者。 组件 Sparkplug充分认识到在任何复杂的IIoT场景中,都会涉及不同类型的设备/传感器、网关、应用程序以及其他软件(和硬件)。因此,Sparkplug为架构中的不同类型参与者定义了各自的行为和语义。 传统的Sparkplug架构包括以下组件: SCADA / IIoT主机 网络边缘(EoN)节点 设备/传感器 MQTT应用节点 MQTT代理 我们现在将对这些组件进行详细的解读。 SCADA / IIoT主机 SCADA / IIoT主机,有时也被称为主应用程序,是负责监控和控制MQTT EoN节点及其所连接的设备和传感器的监督性应用程序。IIoT系统的持续会话状态感知是至关重要的,这意味着所有参与者(包括机器、设备、PLC、传感器、网关和应用程序)的当前状态随时都需要在中心位置进行监控。管理状态并根据状态变化采取行动的中心应用程序就是SCADA / IIOT主机应用程序。它是系统操作员用于管理和监督整个系统健康状况的关键应用程序。 与大多数传统的SCADA系统架构不同,SCADA / IIoT主机并不负责直接建立和维护与设备的连接。在Sparkplug架构中,设备、EoN节点和SCADA / IIoT主机都连接到中心MQTT代理,并通过发布和订阅数据进行通信。这样的设计允许仅在数据发生变化时进行更新,从而实现了异常报告(RBE)功能。 网络边缘(EoN)节点 网络边缘(EoN)节点在任何Sparkplug系统中都扮演着关键角色。EoN节点通常提供物理或逻辑上的网关功能,使那些不直接实现Sparkplug的传感器或设备能够参与到MQTT主题命名空间中。EoN节点负责管理自身以及通过诸如OPC-UA、Modbus、专有PLC供应商协议、HTTP、MQTT或本地离散I/O等协议连接到该EoN节点的传感器和设备的状态和会话。EoN节点负责管理这些连接设备和传感器的生命周期和状态,以及接收和发送设备数据到Sparkplug基础设施中。EoN节点是任何Sparkplug基础设施中的关键组成部分,它们通常被用于将传统的基础设施与Sparkplug桥接。 设备/传感器 设备和传感器构成了工业自动化的核心。一个设备通常是一个实体或逻辑上的单元,它通过一个或多个工业通信协议来发送和/或接收数据。这些工业协议一般基于轮询/响应机制。在Sparkplug的上下文中,设备通过EoN节点连接到Sparkplug基础设施中。EoN节点将MQTT Sparkplug的发布/订阅机制桥接到这些轮询/响应协议上。 支持MQTT的传感器和设备 尽管大部分设备和传感器采用像Modbus、OPC-UA、Beckhoff ADS等标准化和专有协议,但许多厂商为其设备和传感器提供了原生的MQTT支持。如果一个MQTT支持的设备已经配备了Sparkplug功能,通过提供适当的数据格式和主题结构,那么该设备可以直接与Sparkplug基础设施交互。在这种情况下,该设备将作为EoN节点被Sparkplug基础设施识别。如果MQTT设备仅支持标准的MQTT而没有Sparkplug意识,那么它仍然需要通过EoN节点来连接。 MQTT应用节点 MQTT应用节点是参与Sparkplug通信的节点,可以产生和消费消息,但它们不是SCADA / IIoT主机。这些通常被称为辅助应用程序。它们通常是提供专门功能的软件系统,例如MES(制造执行系统)、历史数据分析等。许多部署也会使用定制软件来满足特定用例的需求,这些软件需要消费由其他Sparkplug参与者产生的数据。 MQTT代理 MQTT代理是中心数据分发组件。所有启用Sparkplug的设备、EoN节点、SCADA / IIoT主机和MQTT应用都通过MQTT连接到代理。代理负责处理认证、授权、参与者状态管理以及在Sparkplug启用系统间的数据分发。MQTT代理需要100%兼容MQTT 3.1.1标准,因为需要支持保留消息、遗嘱和遗言以及QoS等功能。 --- ### 217. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 工业物联网(IIoT)和工业4.0是制造业中的关键趋势。车间操作员寻求提高运营效率、实现小批量生产,并获得实时制造洞察。然而,传统的软件和硬件栈通常是封闭和专有的,互操作性并不是供应商的主要关注点。像OPC-UA这样的协议虽然承诺为设备、机器和软件应用之间提供通用的行业语言,从而打破孤立,但现实却是,对于大多数开发人员和软件架构师来说,OPC-UA并不像人们所希望的那样是解决所有问题的万能药。它非常复杂和笨重,尤其是在大多数制造项目中常见的棕地环境下,集成OPC-UA并不容易。因此,人们开始寻找更好的方法。 与此同时,通过MQTT协议,设备到云的通信在最小化延迟和最大化吞吐量方面变得非常简单。许多开发人员期望有类似于MQTT的简单解决方案,但又能满足制造业的特定需求,如有效载荷定义和跨机器及供应商的统一消息行为。 这一愿望得以实现,当基于MQTT的Sparkplug协议由MQTT的创始人之一Arlen Nipper首次发布时。Sparkplug规范迅速在整个行业中流行起来,像雪佛龙(Chevron)这样的大公司采用它以提高运营效率,并创造下一代制造解决方案。 那么,Sparkplug究竟是什么呢? Sparkplug是一个开源软件规范,它为MQTT客户端提供了一个框架,使其应用、传感器、设备和网关能够在MQTT基础设施中无缝、双向、互操作地集成数据。为了为IIoT提供通用语言,Sparkplug规范定义了三个目标:定义MQTT主题命名空间、MQTT状态管理和MQTT有效载荷。值得注意的是,Sparkplug实际上被设计为完全运行在MQTT上,因为MQTT的发布/订阅模式允许系统的所有组件进行双向和解耦的集成。当1999年MQTT被发明时,它最初是为SCADA系统设计的,但没有具体规定主题和有效载荷的结构以及设备的行为方式。这使得MQTT可以在不同的行业中使用,如智能汽车、物流和智能制造。现在,Sparkplug填补了这个空白,并为IIoT场景中的数据格式、主题结构、状态管理和拓扑结构提供了一个厂商中立的规范。 那么,Sparkplug与纯粹的MQTT有何不同? Sparkplug是专为基于MQTT的工业物联网应用设计的。许多供应商的PLC(例如西门子S7)以及大多数制造执行系统(MES)和SCADA系统(如感应自动化®的Ignition SCADA)支持MQTT。当然,大多数专业网关解决方案也支持MQTT。 总结 加入Sparkplug的原因在于,对于非Sparkplug的MQTT通信,需要确保所有感兴趣的参与者知道在哪里订阅数据,并且能够解释数据。这通常涉及到数据转换,需要约定,从而在所有应用之间创建紧密耦合。而使用Sparkplug,所有参与者都会就一种共同的数据格式达成一致,明确如何接收特定数据,如何发布他们的数据,以及如何解释数据。更好的是,Sparkplug还允许集成来自非MQTT设备的数据以及其他协议(如OPC-UA或Modbus)的数据。我们还可以从中获得所有这些设备和应用的自动发现功能。 --- ### 218. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT协议5.0中文版 最新版本: v0.0.1 2018-05-18 概述 MQTT是一个客户端-服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。 MQTT协议5.0版本在3.1.1版本的基础上增加了会话/消息延时功能、原因码、主题别名、in-flight流控、属性、共享订阅等功能,增加了用于增强认证的AUTH报文。 MQTT协议5.0中文版 OASIS标准 2017年10月26日 规范链接 (Specification URIs) 当前版本(This version): http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd02/mqtt-v5.0-csprd02.docx (Authoritative) http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd02/mqtt-v5.0-csprd02.html http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd02/mqtt-v5.0-csprd02.pdf 以前的版本(Previous version): http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd01/mqtt-v5.0-csprd01.docx (Authoritative) http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd01/mqtt-v5.0-csprd01.html http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd01/mqtt-v5.0-csprd01.pdf 最新版本(Latest version): http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.docx (Authoritative) http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.pdf 技术委员会(Technical Committee): 结构化信息标准促进组织MQTT技术委员会 主席(Chairs): Brian Raymor (brian.raymor@microsoft.com), Microsoft Richard Coppen (coppen@uk.ibm.com), IBM 编辑(Editors): Andrew Banks (Andrew_Banks@uk.ibm.com), IBM Ed Briggs (edbriggs@microsoft.com), Microsoft Ken Borgendale (kwb@us.ibm.com), IBM Rahul Gupta (rahul.gupta@us.ibm.com), IBM 相关文档(Related work): 本规范代替: MQTT协议3.1.1版本。编辑是Andrew Banks和Rahul Gupta,发布于2014年10月29日,OASIS标准: < http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html>. 本规范与此有关: MQTT和NIST网络安全框架1.0版。 编辑是杰夫·布朗和路易·菲利普·拉穆勒。最新版本: http://docs.oasis-open.org/mqtt/mqtt-nist-cybersecurity/v1.0/mqtt-nist-cybersecurity-v1.0.html. 摘要 (Abstract) MQTT是一个客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,因此易于实现。这些特点使得它对很多场景来说都是很好的选择,包括受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT),这些场景要求很小的代码封装或者网络带宽非常昂贵。 本协议运行在TCP/IP,或其它提供了有序、可靠、双向连接的网络连接上。它有以下特点: 使用发布/订阅消息模式,提供了一对多的消息分发和应用之间的解耦。 消息传输不需要知道负载内容。 提供三种等级的服务质量: “最多一次”,尽操作环境所能提供的最大努力分发消息。消息可能会丢失。例如,这个等级可用于环境传感器数据,单次的数据丢失没关系,因为不久之后会再次发送。 “至少一次”,保证消息可以到达,但是可能会重复。 “仅一次”,保证消息只到达一次。例如,这个等级可用在一个计费系统中,这里如果消息重复或丢失会导致不正确的收费。 很小的传输消耗和协议数据交换,最大限度减少网络流量。 异常连接断开发生时,能通知到相关各方。 状态 (Status) 本文档最后由OASIS成员在上面标示的日期最终修订或批准。批准的级别也在上面列出了。如果要查看本文档最新的修订版请检查上面的 最新版本 位置。技术委员会产生的其它修订版和其它技术文档都列在这里:https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=mqtt#technical 。 技术委员会成员对本规范的评论应该发送到技术委员会的邮件列表。其他人应该发送评论到技术委员会的公共评论列表,方法是点击技术委员会网站的 发送评论 按钮,网页地址是 https://www.oasis-open.org/committees/mqtt/ 。 本规范草案的发布基于 OASIS知识产权政策 的 Non-Assertion 模式。关于实现本规范必不可少的任何专利是否已公开,以及其它的专利许可条款相关的信息,请参考技术委员会网站的知识产权部分(https://www.oasis-open.org/committees/mqtt/ipr.php)。 引用格式(Citation format): 引用此规范时应该使用下面的引文格式: [mqtt-v5.0] MQTT Version 5.0. Edited by Andrew Banks, Ed Briggs, Ken Borgendale, and Rahul Gupta. 26 October 2017. OASIS Committee Specification Draft 02 / Public Review Draft 02. http://docs.oasis-open.org/mqtt/mqtt/v5.0/csprd02/mqtt-v5.0-csprd02.html. Latest version: http://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html. 文档链接 MQTT协议草案5.0中文翻译项目 修订记录 版 本日 期发布说明0.0.12018-05-18发布全部文本,完成初步审校,公开发布第一版 第一章 概述 Introduction 1.0 知识产权政策 Intellectual property rights policy 此公开评审草案的发布基于 OASIS IPR Policy 的 Non-Assertion 模式。 关于实现本规范必不可少的任何专利是否已公开,以及其他的专利许可条款相关的信息,请参考技术委员会网站的知识产权部分(https://www.oasis-open.org/committees/mqtt/ipr.php). 1.1 MQTT协议的组织结构 Organization of MQTT 本规范分为七个章节: [第一章 – 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] 1.2 术语 Terminology 本规范中用到的关键字 必须 MUST,不能 MUST NOT,要求 REQUIRED,将会 SHALL,不会 SHALL NOT,应该 SHOULD,不应该 SHOULD NOT,推荐 RECOMMENDED,可以 MAY,可选 OPTIONAL 都是按照 IETF RFC 2119 [RFC2119] 中的描述解释。 网络连接 Network Connection MQTT使用的底层传输协议基础设施。 客户端使用它连接服务端。 它提供有序的、可靠的、双向字节流传输。 例子见4.2节。 应用消息 Application Message MQTT协议通过网络传输应用数据。应用消息通过MQTT传输时,它们有关联的服务质量(QoS)和主题(Topic)。 客户端 Client使用MQTT的程序或设备。客户端总是通过网络连接到服务端。它可以 打开连接到服务端的网络连接 发布应用消息给其它相关的客户端 订阅以请求接受相关的应用消息 取消订阅以移除接受应用消息的请求 关闭连接到服务端的网络连接 服务端 Server一个程序或设备,作为发送消息的客户端和请求订阅的客户端之间的中介。服务端 接受来自客户端的网络连接 接受客户端发布的应用消息 处理客户端的订阅和取消订阅请求 转发应用消息给符合条件的已订阅客户端 关闭来自客户端的网络连接 会话 Subscription客户端和服务端之间的状态交互。一些会话持续时长与网络连接一样,另一些可以在客户端和服务端的多个连续网络连接间扩展。 订阅 Subscription订阅包含一个主题过滤器(Topic Filter)和一个最大的服务质量(QoS)等级。订阅与单个会话(Session)关联。会话可以包含多于一个的订阅。会话的每个订阅都有一个不同的主题过滤器。 共享订阅 Shared Subscription一个共享订阅包含一个主题过滤器(Topic Filter)和一个最大的服务质量(QoS)等级。一个共享订阅可以与多个订阅会话相关联,便于支持大范围消息交换模式。一条主题匹配的应用消息只发送给关联到此共享订阅的多个会话中的一个会话。一个会话可以包括多个共享订阅,可以同时包含共享订阅与非共享订阅。 通配符订阅 Wildcard Subscription通配符订阅是指主题过滤器(Topic Filter)包含一个或多个通配符的订阅。通配符订阅使得一次订阅匹配多个主题名(Topic Name)。4.7节 描述了主题过滤器中的通配符。 主题名 Topic Name附加在应用消息上的一个标签,服务端已知且与订阅匹配。服务端发送应用消息的一个副本给每一个匹配的客户端订阅。 主题过滤器 Topic Filter订阅中包含的一个表达式,用于表示相关的一个或多个主题。主题过滤器可以使用通配符。 MQTT控制报文 MQTT Control Packet通过网络连接发送的信息数据包。MQTT 规范定义了十四种不同类型的MQTT控制报文,其中一个(PUBLISH 报文)用于传输应用消息。 无效报文 Malformed Packet根据规范不能被正确解析的控制报文。4.13节 描述了如何进行相应的错误处理。 协议错误 Protocol Error在报文解析之后发现包含协议不允许或与客户端或服务端当前状态不一致的数据的错误。4.13节 描述了如何进行相应的错误处理。 遗嘱消息 Will Message在网络连接非正常关闭的情况下,由服务端发布的应用消息。3.1.2.5节 描述了遗嘱消息。 1.3 规范引用 Normative references [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997,http://www.rfc-editor.org/info/rfc2119 [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003,http://www.rfc-editor.org/info/rfc3629http://www.rfc-editor.org/info/rfc6455 [Unicode] The Unicode Consortium. The Unicode Standard,http://www.rfc-editor.org/info/rfc2119 1.4 非规范引用 Non-normative references [RFC0793] Postel, J., "Transmission Control Protocol", STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981,http://www.rfc-editor.org/info/rfc793 [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008,http://www.rfc-editor.org/info/rfc2119 [AES] Advanced Encryption Standard (AES) (FIPS PUB 197).https://csrc.nist.gov/csrc/media/publications/fips/197/final/documents/fips-197.pdf [CHACHA20] ChaCha20 and Poly1305 for IETF Protocolshttps://tools.ietf.org/html/rfc7539 [FIPS1402] Security Requirements for Cryptographic Modules (FIPS PUB 140-2)https://csrc.nist.gov/csrc/media/publications/fips/140/2/final/documents/fips1402.pdf [IEEE 802.1AR] IEEE Standard for Local and metropolitan area networks - Secure Device Identityhttp://standards.ieee.org/findstds/standard/802.1AR-2009.html [ISO29192] ISO/IEC 29192-1:2012 Information technology -- Security techniques -- Lightweight cryptography -- Part 1: Generalhttps://www.iso.org/standard/56425.html [MQTT NIST] MQTT supplemental publication, MQTT and the NIST Framework for Improving Critical Infrastructure Cybersecurityhttp://docs.oasis-open.org/mqtt/mqtt-nist-cybersecurity/v1.0/mqtt-nist-cybersecurity-v1.0.html [MQTTV311] MQTT V3.1.1 Protocol Specificationhttp://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html [ISO20922] MQTT V3.1.1 ISO Standard (ISO/IEC 20922:2016)https://www.iso.org/standard/69466.html [NISTCSF] Improving Critical Infrastructure Cybersecurity Executive Order 13636https://www.nist.gov/sites/default/files/documents/itl/preliminary-cybersecurity-framework.pdf [NIST7628] NISTIR 7628 Guidelines for Smart Grid Cyber Security Cataloguehttps://www.nist.gov/sites/default/files/documents/smartgrid/nistir-7628_total.pdf [NSAB] NSA Suite B Cryptographyhttp://www.nsa.gov/ia/programs/suiteb_cryptography/ [PCIDSS] PCI-DSS Payment Card Industry Data Security Standardhttps://www.pcisecuritystandards.org/pci_security/ [RFC1928] Leech, M., Ganis, M., Lee, Y., Kuris, R., Koblas, D., and L. Jones, "SOCKS Protocol Version 5", RFC 1928, DOI 10.17487/RFC1928, March 1996,http://www.rfc-editor.org/info/rfc1928http://www.rfc-editor.org/info/rfc4511 [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,http://www.rfc-editor.org/info/rfc5280 [RFC6066] Eastlake 3rd, D., "Transport Layer Security (TLS) Extensions: Extension Definitions", RFC 6066, DOI 10.17487/RFC6066, January 2011,http://www.rfc-editor.org/info/rfc6066 [RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, October 2012,http://www.rfc-editor.org/info/rfc6749 [RFC6960] Santesson, S., Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. Adams, "X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP", RFC 6960, DOI 10.17487/RFC6960, June 2013,http://www.rfc-editor.org/info/rfc6960 [SARBANES] Sarbanes-Oxley Act of 2002.http://www.gpo.gov/fdsys/pkg/PLAW-107publ204/html/PLAW-107publ204.htm [USEUPRIVSH] U.S.-EU Privacy Shield Frameworkhttps://www.privacyshield.gov [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005,http://www.rfc-editor.org/info/rfc3986 [RFC1035] Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, DOI 10.17487/RFC1035, November 1987,http://www.rfc-editor.org/info/rfc1035 [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for specifying the location of services (DNS SRV)", RFC 2782, DOI 10.17487/RFC2782, February 2000,http://www.rfc-editor.org/info/rfc2782 1.5 数据表示 Data representations 1.5.1 二进制位 Bits 字节中的位从0到7。第7位是最高有效位,第0位是最低有效位。 1.5.2 双字节整数 Two Byte Integer 双字节整数是 16 位,使用大端序(big-endian,高位字节在低位字节前面)。这意味着一个 16 位的字在网络上表示为最高有效字节(MSB),后面跟着最低有效字节(LSB)。 1.5.3 四字节整数 Four Byte Integer 四字节整数是32位,使用大端序(big-endian,高位字节在低位字节前面)。这意味着一个32位的字在网络上表示为第一个最高有效字节(MSB)后面跟着第一个最低有效字节(LSB),再后面为第二个最高有效字节(MSB)后面跟着第二个最低有效字节(LSB)。 1.5.4 UTF-8编码字符串 UTF-8 encoded strings 后面会描述的控制报文中的文本字段编码为UTF-8格式的字符串。UTF-8 [RFC3629] 是一个高效的Unicode字符编码格式,为了支持基于文本的通信,它对ASCII字符的编码做了优化。 每一个字符串都有一个两字节的长度字段作为前缀,它给出这个字符串UTF-8编码的字节数,它们在图例 1.1 UTF-8编码字符串的结构 中描述。因此可以传送的UTF-8编码的字符串大小有一个限制,不能超过 65535字节。 除非另有说明,所有的UTF-8编码字符串的长度都在0到65535字节这个范围内。 图 1-1 - UTF-8编码字符串的结构 Structure of UTF-8 encoded strings 二进制位76543210byte 1字符串长度的最高有效字节(MSB)byte 2字符串长度的最低有效字节(LSB)byte 3 ...如果长度大于0,这里是UTF-8编码的字符数据。 UTF-8编码字符串中的字符数据必须是按照Unicode规范 [Unicode] 定义的和在RFC3629 [RFC3629] 中重申的有效的UTF-8格式。特别需要指出的是,这些数据不能包含字符码在U+D800和U+DFFF之间的数据。如果服务端或客户端收到了一个包含无效UTF-8字符的控制报文,它必须关闭网络连接 [MQTT-1.5.3-1]。 UTF-8编码的字符串不能包含空字符U+0000。如果客户端或服务端收到了一个包含U+0000的控制报文,它必须关闭网络连接 [MQTT-1.5.3-2]。 数据中不应该包含下面这些Unicode代码点的编码。如果一个接收者(服务端或客户端)收到了包含下列任意字符的控制报文,它可以关闭网络连接: U+0001和U+001F之间的控制字符 U+007F和U+009F之间的控制字符 Unicode规范定义的非字符代码点(例如U+0FFFF) Unicode规范定义的保留字符(例如U+0FFFF) UTF-8编码序列0XEF 0xBB 0xBF总是被解释为U+FEFF(零宽度非换行空白字符),无论它出现在字符串的什么位置,报文接收者都不能跳过或者剥离它 [MQTT-1.5.3-3]。 非规范示例 Non normative example 例如,字符串 A𪛔 是一个拉丁字母A后面跟着一个代码点U+2A6D4(它表示一个中日韩统一表意文字扩展B中的字符),这个字符串编码如下: 图 1-2 - UTF-8编码字符串非规范示例 UTF-8 encoded string non normative example 比特位76543210byte 1字符串长度MSB (0x00)00000000byte 2字符串长度LSB (0x05)00000101byte 3‘A’ (0x41)01000001byte 4(0xF0)11110000byte 5(0xAA)10101010byte 6(0x9B)10011011byte 7(0x94)10010100 1.5.5 变长字节整数 Variable Byte Integer 剩余长度字段使用一个变长字节编码方案,对小于 128 的值它使用单字节编码。更大的值按下面的方式处理。低 7 位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个字节可以编码 128 个数值和一个延续位(continuation bit)。剩余长度字段最大 4 个字节[MQTT-1.5.5-1],如表 1-1 所示。 表 1-1 - 变长字节整数大小 Size of Variable Byte Integer 字节数最小值最大值10 (0x00)127 (0x7F)2128 (0x80, 0x01)16,383 (0xFF, 0x7F)316,384 (0x80, 0x80, 0x01)2,097,151 (0xFF, 0xFF, 0x7F)42,097,152 (0x80, 0x80, 0x80, 0x01)268,435,455 (0xFF, 0xFF, 0xFF, 0x7F) 非规范示例 Non normative example 非负整数 X 使用变长编码方案的算法如下: do  encodedByte = X MOD 128  X = X DIV 128  // if there are more data to encode, set the top bit of this byte  if (X > 0)    encodedByte = encodedByte OR 128  endif  'output' encodedBytewhile (X > 0)MOD是模运算,DIV是整数除法,OR是位操作或(C语言中分别是%,/,|)。 非规范示例 Non normative example 剩余长度字段的解码算法如下: multiplier = 1value = 0do  encodedByte = 'next byte from stream'  value += (encodedByte AND 127) multiplier  if (multiplier > 128128128)    throw Error(Malformed Variable Byte Integer)  multiplier = 128while ((encodedByte AND 128) != 0)AND 是位操作与(C 语言中的&) 这个算法终止时,value 包含的就是剩余长度的值。 1.5.6 二进制数据 Binary Data 二进制数据由一个双字节整数指示其数据长度,因此,二进制数据的长度被限制为0到65,535字节。 1.5.7 UTF-8字符串对 UTF-8 String Pair UTF-8字符串对由两个UTF-8编码的字符串组成,用来表示名字-值对,第一个字符串表示名字,第二个字符串表示值。 所有的字符串必须遵循UTF-8字符串编码规范 [MQTT-1.5.7-1]。如果接受者(客户端或者服务端)接受到一个字符串对,然而其编码并不遵循规范,则此报文为无效报文。4.13节描述了错误处理的信息。 1.6 安全 Security MQTT客户端和服务端实现应该提供认证、授权和安全通信功能,如第5章所描述。强烈建议任何关注于个人身份信息或敏感信息的应用使用这些安全设施。 1.7 编辑约定 Editing conventions 本规范用黄色高亮的文本标识一致性声明,每个一致性声明都分配了一个这种格式的引用:[MQTT-x.x.x-y]。 1.8 变更历史 Editing conventions 1.8.1 MQTT v3.1.1 MQTT v3.1.1 是首个OASIS标准版本MQTT [MQTTV311]。MQTT v3.1.1也是ISO/IEC 20922:2016 [ISO20922] 标准。 1.8.2 MQTT v5.0 MQTT v5.0 在保持MQTT核心不变的基础上添加了大量的新功能。这些功能的主要目标如下: 进一步支持大规模可扩展系统 改进的错误报告 规范化包括容量探索和请求响应在内的通用模式 包括用户属性在内的可扩展机制 改进性能并支持小型客户端 项目主页 MQTT v5.0协议草案中文版 第二章 MQTT控制报文格式 MQTT Control Packet format 2.1 MQTT控制报文结构 Structure of an MQTT Control Packet MQTT协议通过交换预定义的MQTT控制报文来通信。这一节描述这些报文的格式。 MQTT控制报文由三部分组成,按照下图描述的顺序: 图 2-1 - MQTT控制报文的结构 Structure of an MQTT Control Packet Fixed Header固定报头,所有控制报文都包含Variable Header 可变报头,部分控制报文包含Payload 有效载荷,部分控制报文包含 2.1.1 固定报头 Fixed header 如下图所示,每个MQTT控制报文都包含一个固定报头。 图 2-2 - 固定报头的格式 Fixed Header format 比特位76543210byte 1MQTT控制报文的类型用于指定控制报文类型的标志位byte 2...剩余长度 2.1.2 MQTT控制报文的类型 MQTT Control Packet type 位置: 第1个字节,二进制位7-4。 表示为4位无符号值,这些值的定义见下表。 表 2-1 - MQTT控制报文的类型 MQTT Control Packet types 名字值报文流动方向描述Reserved0禁止保留CONNECT1客户端到服务端客户端请求连接服务端CONNACK2服务端到客户端连接报文确认PUBLISH3两个方向都允许发布消息PUBACK4两个方向都允许QoS 1消息发布收到确认PUBREC5两个方向都允许发布收到(保证交付第一步)PUBREL6两个方向都允许发布释放(保证交付第二步)PUBCOMP7两个方向都允许QoS 2消息发布完成(保证交互第三步)SUBSCRIBE8客户端到服务端客户端订阅请求SUBACK9服务端到客户端订阅请求报文确认UNSUBSCRIBE10客户端到服务端客户端取消订阅请求UNSUBACK11服务端到客户端取消订阅报文确认PINGREQ12客户端到服务端心跳请求PINGRESP13服务端到客户端心跳响应DISCONNECT14两个方向都允许断开连接通知AUTH15两个方向都允许认证信息交换 2.1.3 标志 Flags 固定报头第1个字节的剩余的4位 [3-0]包含每个 MQTT 控制报文类型特定的标志如下表所示。表格中任何标记为“保留”的标志位,都是保留给以后使用的,必须设置为表格中列出的值 [MQTT-2.1.3-1]。如果收到非法的标志,此报文被当做无效报文。有关错误处理的详细信息见 4.8节 [MQTT-2.2.2-2]。 表 2-2 - 标志位 Flag Bits 控制报文固定报头标志Bit 3Bit 2Bit 1Bit 0CONNECTReserved0000CONNACKReserved0000PUBLISHUsed in MQTT v5.0DUPQoSRETAINPUBACKReserved0000PUBRECReserved0000PUBRELReserved0010PUBCOMPReserved0000SUBSCRIBEReserved0010SUBACKReserved0000UNSUBSCRIBEReserved0010UNSUBACKReserved0000PINGREQReserved0000PINGRESPReserved0000DISCONNECTReserved0000AUTHReserved0000 DUP1 =控制报文的重复分发标志 QoS2 = PUBLISH报文的服务质量等级 RETAIN3 = PUBLISH报文的保留标志 PUBLISH控制报文中的DUP, QoS和RETAIN标志的描述见 3.3.1节。 2.1.4 剩余长度 Remaining Length 位置: 从第2个字节开始。 剩余长度(Remaining Length)是一个变长字节整数,用来表示当前控制报文剩余部分的字节数,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。MQTT控制报文总长度等于固定报头的长度加上剩余长度。 2.2 可变报头 Variable header 某些 MQTT 控制报文包含一个可变报头部分。它在固定报头和有效载荷之间。可变报头的内容根据报文类型的不同而不同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。 2.2.1 报文标识符 Packet Identifier 部分类型MQTT控制报文的可变报头部分包含了2个字节的报文标识符字段。这些MQTT控制报文类型为:PUBLISH报文(当QoS>0时),PUBACK,PUBREC,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBSCRIBE,UNSUBACK。 需要报文标识符的MQTT控制报文如下表所示。 表 2-3 - 包含报文标识符的MQTT控制报文 MQTT Control Packets that contain a Packet Identifier 名字值CONNECT不需要CONNACK不需要PUBLISH需要(如果QoS>0)PUBACK需要PUBREC需要PUBREL需要PUBCOMP需要SUBSCRIBE需要SUBACK需要UNSUBSCRIBE需要UNSUBACK需要PINGREQ不需要PINGRESP不需要DISCONNECT不需要AUTH不需要 QoS设置为0的 PUBLISH 报文不能包含报文标识符[MQTT-2.2.1-2]。 客户端每次发送一个新的SUBSCRIBE,UNSUBSCRIBE或者PUBLISH(当QoS>0时)MQTT控制报文时都必须分配一个当前未使用的非零报文标识符 [MQTT-2.2.1-3]。 服务端每次发送一个新的PUBLISH(当QoS>0)MQTT控制报文时都必须分配一个当前未使用的非零报文标识符 [MQTT-2.2.1-4]。 当客户端处理完这个报文对应的确认后,这个报文标识符就释放可重用。QoS 1的PUBLISH对应的是PUBACK,QoS 2的PUBLISH对应的是包含原因码128以上的PUBCOMP或PUBREC,与SUBSCRIBE或UNSUBSCRIBE对应的分别是SUBACK或UNSUBACK。 PUBLISH,SUBSCRIBE和UNSUBSCRIBE的报文标识符,在一次会话中对于客户端和服务端来说分属于不同的组。某个报文标识符在某一时刻不能被多个命令所使用。 PUBACK,PUBREC和PUBREL报文必须包含与最初发送的PUBLISH报文相同的报文标识符 [MQTT-2.2.1-5]。类似地,SUBACK和UNSUBACK必须包含在对应的SUBSCRIBE和UNSUBSCRIBE报文中使用的报文标识符 [MQTT-2.2.1-6]。 客户端和服务端彼此独立地分配报文标识符。因此,客户端服务端组合使用相同的报文标识符可以实现并发的消息交换。 非规范评注 客户端发送标识符为0x1234的PUBLISH报文,它有可能会在收到那个报文的PUBACK之前,先收到服务端发送的另一个不同的但是报文标识符也为0x1234的PUBLISH报文。 客户端服务端PUBLISH Packet Identifier = 0x1234---><---PUBLISH Packet Identifier = 0x1234PUBACK Packet Identifier = 0x1234---><---PUBACK Packet Identifier = 0x1234 2.2.2 属性 Properties CONNECT,CONNACK,PUBLISH,PUBACK,PUBREC,PUBREL,PUBCOMP,SUBSCRIBE,SUBACK,UNSUBACK,DISCONNECT和AUTH报文可变报头的最后一部分是一组属性。CONNECT报文的遗嘱(Will)属性字段中也包含了一组可选的属性。 属性字段由属性长度和所有属性组成。 2.2.2.1 属性长度 Property Length 属性长度被编码为变长字节整数。属性长度不包含用于编码属性长度自身的字节数,但包含所有属性的长度。如果没有任何属性,必须由属性长度为零的字段来指示 [MQTT-2.2.2-1]。 2.2.2.2 属性 Property 一个属性包含一段数据和一个定义了属性用途和数据类型的标识符。标识符被编码为变长字节整数。任何控制报文,如果包含了:对于该报文类型无效的标识符,或者错误类型的数据,都是无效报文。收到无效报文时,服务端或客户端使用包含原因码0x81(无效报文)CONNACK或DISCONNECT报文进行错误处理,如4.13节所述。标识符排序不分先后。 表 2-4 - 属性 Properties 标识符属性名数据类型报文/遗嘱属性DecHex10x01载荷格式说明字节PUBLISH, Will Properties20x02消息过期时间四字节整数PUBLISH, Will Properties30x03内容类型UTF-8编码字符串PUBLISH, Will Properties80x08响应主题UTF-8编码字符串PUBLISH, Will Properties90x09相关数据二进制数据PUBLISH, Will Properties110x0B定义标识符变长字节整数PUBLISH, SUBSCRIBE170x11会话过期间隔四字节整数CONNECT, CONNACK, DISCONNECT180x12分配客户标识符UTF-8编码字符串CONNACK190x13服务端保活时间双字节整数CONNACK210x15认证方法UTF-8编码字符串CONNECT, CONNACK, AUTH220x16认证数据二进制数据CONNECT, CONNACK, AUTH230x17请求问题信息字节CONNECT240x18遗嘱延时间隔四字节整数Will Properties250x19请求响应信息字节CONNECT260x1A请求信息UTF-8编码字符串CONNACK280x1C服务端参考UTF-8编码字符串CONNACK, DISCONNECT310x1F原因字符串UTF-8编码字符串CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT, AUTH330x21接收最大数量双字节整数CONNECT, CONNACK340x22主题别名最大长度双字节整数CONNECT, CONNACK350x23主题别名双字节整数PUBLISH360x24最大QoS字节CONNACK370x25保留属性可用性字节CONNACK380x26用户属性UTF-8字符串对CONNECT, CONNACK, PUBLISH, Will Properties, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, DISCONNECT, AUTH390x27最大报文长度四字节整数CONNECT, CONNACK400x28通配符订阅可用性字节CONNACK410x29订阅标识符可用性字节CONNACK420x2A共享订阅可用性字节CONNACK 非规范评注 尽管属性标识符用变长字节整数来表示,但在此版本协议中,所有的标识符均由一个字节来表示。 2.3 有效载荷 Payload 某些MQTT控制报文在报文的最后部分包含一个有效载荷,这将在第三章论述。对于PUBLISH来说有效载荷就是应用消息。 表 2-5 包含有效载荷的MQTT控制报文 MQTT Control Packets that contain a Payload MQTT控制报文有效载荷CONNECT需要CONNACK不需要PUBLISH可选PUBACK不需要PUBREC不需要PUBREL不需要PUBCOMP不需要SUBSCRIBE需要SUBACK需要UNSUBSCRIBE需要UNSUBACK需要PINGREQ不需要PINGRESP不需要DISCONNECT不需要AUTH不需要 2.4 原因码 Reason Code 原因码是一个单字节无符号数,用来指示一次操作的结果。小于0x80的原因码指示某次操作成功完成,通常用0来表示。大于等于0x80的原因码用来指示操作失败。 CONNACK,PUBACK,PUBREC,PUBREL,PUBCOMP,DISCONNECT和AUTH控制报文的可变报头有一个单字节的原因码。SUBACK和UNSUBACK报文的载荷字段包含一个或多个原因码。 原因码如下表所示。 表 2-6 - 原因码 Reason Code 原因码名称报文DecHex00x00成功CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH00x00正常断开DISCONNECT00x00授权的QoS 0SUBACK10x01授权的QoS 1SUBACK20x02授权的QoS 2SUBACK40x04包含遗嘱的断开DISCONNECT160x10无匹配订阅PUBACK, PUBREC170x11订阅不存在UNSUBACK240x18继续认证AUTH250x19重新认证AUTH1280x80未指明的错误CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT1290x81无效报文CONNACK, DISCONNECT1300x82协议错误CONNACK, DISCONNECT1310x83实现错误CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT1320x84协议版本不支持CONNACK1330x85客户标识符无效CONNACK1340x86用户名密码错误CONNACK1350x87未授权CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT1360x88服务端不可用CONNACK1370x89服务端正忙CONNACK, DISCONNECT1380x8A禁止CONNACK1390x8B服务端关闭中DISCONNECT1400x8C无效的认证方法CONNACK, DISCONNECT1410x8D保活超时DISCONNECT1420x8E会话被接管DISCONNECT1430x8F主题过滤器无效SUBACK, UNSUBACK, DISCONNECT1440x90主题名无效CONNACK, PUBACK, PUBREC, DISCONNECT1450x91报文标识符已被占用PUBACK, PUBREC, SUBACK, UNSUBACK1460x92报文标识符无效PUBREL, PUBCOMP1470x93接收超出最大数量DISCONNECT1480x94主题别名无效DISCONNECT1490x95报文过长CONNACK, DISCONNECT1500x96消息太过频繁DISCONNECT1510x97超出配额CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT1520x98管理行为DISCONNECT1530x99载荷格式无效CONNACK, PUBACK, PUBREC, DISCONNECT1540x9A不支持保留CONNACK, DISCONNECT1550x9B不支持的QoS等级CONNACK, DISCONNECT1560x9C(临时)使用其他服务端CONNACK, DISCONNECT1570x9D服务端已(永久)移动CONNACK, DISCONNECT1580x9E不支持共享订阅SUBACK, DISCONNECT1590x9F超出连接速率限制CONNACK, DISCONNECT1600xA0最大连接时间DISCONNECT1610xA1不支持订阅标识符SUBACK, DISCONNECT1620xA2不支持通配符订阅SUBACK, DISCONNECT 非规范评注 对于原因码0x91(报文标识符已被占用)的处理可以为尝试修复会话、以新会话标志为1重置会话或者判定客户端或服务端实现有缺陷。 项目主页 MQTT v5.0协议草案中文版 第三章 MQTT控制报文 MQTT Control Packets 3.1 CONNECT – 连接请求 客户端到服务端的网络连接建立后,客户端发送给服务端的第一个报文必须是CONNECT报文 [MQTT-3.1.0-1]。 在一个网络连接上,客户端只能发送一次CONNECT报文。服务端必须将客户端发送的第二个CONNECT报文当作协议违规处理并断开客户端的连接 [MQTT-3.1.0-2]。有关错误处理的信息请查看4.13节。 有效载荷包含一个或多个编码的字段。包括客户端的唯一标识符,Will主题,Will消息,用户名和密码。除了客户端标识之外,其它的字段都是可选的,基于标志位来决定可变报头中是否需要包含这些字段。 3.1.1 CONNECT 固定报头 CONNECT Fixed header 图 3-1 – CONNECT报文的固定报头 CONNECT packet Fixed Header Bit76543210byte 1MQTT报文类型 (1)Reserved 保留位00010000byte 2...剩余长度 剩余长度字段剩余长度等于可变报头的长度加上有效载荷的长度。编码方式为变长字节整数。 3.1.2 CONNECT 可变报头 CONNECT Variable header CONNECT 报文的可变报头按下列次序包含四个字段:协议名(Protocol Name),协议级别(Protocol Level),连接标志(Connect Flags),保持连接(Keep Alive)和属性(Properties)。2.2.2节 描述了属性(Properties)编码规则。 3.1.2.1 协议名 Protocol Name 图 3-2 - 协议名字节 Protocol Name bytes 说明76543210协议名byte 1长度MSB (0)00000000byte 2长度LSB (4)00000100byte 3‘M’01001101byte 4‘Q’01010001byte 5‘T’01010100byte 6‘T’01010100 协议名是表示协议名MQTT的UTF-8编码的字符串。MQTT规范的后续版本不会改变这个字符串的偏移和长度。 支持多种协议的服务端使用协议名字段判断数据是否为MQTT报文。协议名必须是UTF-8字符串“MQTT”。如果服务端不愿意接受CONNECT但希望表明其MQTT服务端身份,可以发送包含原因码为0x84(不支持的协议版本)的CONNACK报文,然后必须关闭网络连接 [MQTT-3.1.2-1]。 非规范评注 数据包检测工具,例如防火墙,可以使用协议名来识别MQTT流量。 3.1.2.2 协议版本 Protocol Version 图 3-3 - 协议级别字节 Protocol Version byte 说明76543210协议级别byte 7版本(5)00000101 客户端使用一个字节无符号数表示协议修订级别。MQTT v5.0的协议版本字段为5(0x05)。 支持多版本MQTT协议的服务端使用协议版本字段判定客户端正使用的MQTT协议版本。如果协议版本不是5且服务端不愿意接受此CONNECT报文,可以发送包含原因码0x84(不支持的协议版本)的CONNACK报文,然后必须关闭网络连接 [MQTT-3.1.2-2]。 3.1.2.3 连接标志 Connect Flags 连接标志字节包含一些用于指定MQTT连接行为的参数。它还指出有效载荷中的字段是否存在。 图 3-4 - 连接标志位 Connect Flag bits Bit76543210User Name FlagPassword FlagWill RetainWill QoSWill FlagClean StartReservedbyte 8XXXXXXX0 服务端必须验证CONNECT控制报文的保留标志位(第0位)是否为0 [MQTT-3.1.2-3],如果不为0则此报文为无效报文。4.13节给出了错误处理信息。 3.1.2.4 新开始 Clean Start 位置: 连接标志字节的第1位 这个二进制位表明此次连接是一个新的会话还是一个已存在的会话的延续。4.1节定义了会话状态。 如果收到新开始(Clean Start)为1的CONNECT报文,客户端和服务端必须丢弃任何已存在的会话,并开始一个新的会话 [MQTT-3.1.2-4]。相应的,CONNACK报文中的会话存在标志设置为0。 如果收到新开始(Clean Start)为0的CONNECT报文,并且存在一个关联此客户标识符的会话,服务端必须基于此会话的状态恢复与客户端的通信 [MQTT-3.1.2-5]。如果收到新开始(Clean Start)为0的CONNECT报文,并且不存在任何关联此客户标识符的会话,服务端必须创建一个新的会话 [MQTT-3.1.2-6]。 3.1.2.5 遗嘱标志 Will Flag 位置: 连接标志字节的第2位 如果遗嘱标志(Will Flag)被设置为1,表示遗嘱消息必须已存储在服务端与此客户标识符相关的会话中 [MQTT-3.1.2-7]。遗嘱消息(Will Message)包含遗嘱属性,遗嘱主题和遗嘱载荷字段。遗嘱必须在网络连接被关闭、遗嘱延时间隔到期或者会话结束之后被发布,除非服务端收到包含原因码为0x00(正常关闭)的DISCONNECT报文之后删除了遗嘱消息(Will Message),或者一个关于此客户标识符的新的网络连接在遗嘱迟发时间(Will Delay Interval)超时之前被创建 [MQTT-3.1.2-8]。 遗嘱消息发布的条件,包括但不限于: 服务端检测到了一个I/O错误或者网络故障 客户端在保持连接(Keep Alive)的时间内未能通讯 客户端在没有发送包含原因码0x00(正常关闭)的情况下关闭了网络连接 服务端在没有收到包含原因码0x00(正常关闭)的情况下关闭了网络连接 如果遗嘱标志(Will Flag)被设置为1,遗嘱属性(Will Property)、遗嘱主题(Will Topic)和遗嘱载荷(Will Payload)字段必须存在于报文有效载荷中 [MQTT-3.1.2-9]。一旦遗嘱消息(Will Message)被发布或者服务端收到包含原因码为0x00(正常关闭)的DISCONNECT报文,遗嘱消息(Will Message)必须从服务端的会话中删除 [MQTT-3.1.2-10]。 服务端应该在网络连接断开并且遗嘱迟发时间(Will Delay Interval)到期,或者会话结束之后立即发布遗嘱消息。服务端关闭或出错的情况下,可以在服务重新启动之后发布遗嘱消息(Will Message)。这种情况下从服务端出错到遗嘱发布之间存在一定的延迟。 关于遗嘱延时间隔(Will Delay Interval)的详细信息,请参考3.1.3.2节。 非规范评注 通过设置晚于会话过期间隔(Session Expiry Interval)的遗嘱迟发时间(Will Delay Interval)并发送包含原因码0x04(包含遗嘱的断开连接),客户端得以发出会话过期(Session Expiry)通告。 3.1.2.6 遗嘱 QoS Will QoS 位置: 连接标志字节的第3、4位 这两个比特指定了发布遗嘱消息(Will Message)时的服务质量(QoS)。 如果遗嘱标志(Will Flag)设置为0,遗嘱服务质量(Will QoS)必须也设置为0(0x00) [MQTT-3.1.2-11]。 如果遗嘱标志设置为1,遗嘱服务质量可以被设置为0(0x00),1(0x01)或2(0x02) [MQTT-3.1.2-12]。设置为3(0x03)的报文是无效报文。4.13节描述了错误处理信息。 3.1.2.7 遗嘱保留 Will Retain 位置: 连接标志字节的第5位 此位指定遗嘱消息(Will Message)在发布时是否会被保留。 如果遗嘱标志被设置为0,遗嘱保留(Will Retain)标志也必须设置为0 [MQTT-3.1.2-13]。如果遗嘱标志被设置为1时,如果遗嘱保留被设置为0,则服务端必须将遗嘱消息当做非保留消息发布 [MQTT-3.1.2-14]。如果遗嘱保留被设置为1,则服务端必须将遗嘱消息当做保留消息发布 [MQTT-3.1.2-15]。 3.1.2.8 用户名标志 User Name Flag 位置: 连接标志字节的第7位 如果用户名标志(User Name Flag)被设置为0,有效载荷中不能包含用户名字段 [MQTT-3.1.2-16]。如果用户名标志被设置为0,有效载荷中必须包含用户名字段 [MQTT-3.1.2-17]。 3.1.2.9 密码标志 Password Flag 位置: 连接标志字节的第6位 如果密码标志(Password Flag)被设置为0,有效载荷中不能包含密码字段 [MQTT-3.1.2-18]。如果密码标志被设置为1,有效载荷中必须包含密码字段 [MQTT-3.1.2-19]。 非规范评注 相比MQTT v3.1.1,此版本协议允许在没有用户名的情况下发送密码。这表明密码除了作为口令之外还可以有其他用途。 3.1.2.10 保持连接 Keep Alive 图 3-5 - 保持连接字节 Keep Alive bytes Bit76543210byte 9保持连接Keep Alive MSBbyte 10保持连接Keep Alive LSB 保持连接(Keep Alive)使用双字节整数来表示以秒为单位的时间间隔。它是指在客户端传输完成一个MQTT控制报文的时刻到发送下一个报文的时刻,两者之间允许空闲的最大时间间隔。客户端负责保证控制报文发送的时间间隔不超过保持连接的值。如果没有任何其它的MQTT控制报文可以发送,客户端必须发送一个PINGREQ 报文 [MQTT-3.1.2-20]。 如果服务端返回的CONNACK报文中包含服务端保持连接(Server Keep Alive),客户端必须使用此值代替其发送的保持连接(Keep Alive) [MQTT-3.1.2-21]。 不管保持连接的值是多少,客户端任何时候都可以发送PINGREQ报文,并且使用PINGRESP报文判断网络和服务端的活动状态。 如果保持连接的值非零,并且服务端在1.5倍的保持连接时间内没有收到客户端的控制报文,它必须断开客户端的网络连接,并判定网络连接已断开 [MQTT-3.1.2-22]。 客户端发送了PINGREQ报文之后,如果在合理的时间内仍没有收到PINGRESP报文,它应该关闭到服务端的网络连接。 保持连接(Keep Alive)值为零的结果是关闭保持连接(Keep Alive)机制。如果保持连接(Keep Alive)值为零,客户端不必按照任何特定的时间发送MQTT控制报文。 非规范评注 服务端可能因为其他原因断开客户端连接,比如服务端将要关闭服务。设置保持连接(Keep Alive)不保证客户端将一直保持连接状态。 非规范评注 保持连接的实际值是由应用指定的,一般是几分钟。允许的最大值是18小时12分15秒。 3.1.2.11 CONNECT 属性 CONNECT Properties 3.1.2.11.1 属性长度 Property Length CONNECT报文可变报头中的属性(Properties)长度被编码为变长字节整数。 3.1.2.11.2 会话过期间隔 Session Expiry Interval 17 (0x11),会话过期间隔(Session Expiry Interval)标识符。跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话过期间隔(Session Expiry Interval)将造成协议错误(Protocol Error)。 如果会话过期间隔(Session Expiry Interval)值未指定,则使用0。如果设置为0或者未指定,会话将在网络连接(Network Connection)关闭时结束。 如果会话过期间隔(Session Expiry Interval)为0xFFFFFFFF (UINT_MAX),则会话永不过期。 如果网络连接关闭时会话过期间隔(Session Expiry Interval)大于0,则客户端与服务端必须存储会话状态 [MQTT-3.1.2-23]。 非规范评注 客户端或服务端可能会因为中断运行导致会话时钟某些时间未运行。这将导致会话的删除被延迟。 更多关于会话的信息参考4.1节。关于会话存储的状态的详细和限制参考4.1.1节。 当会话过期时,客户端和服务端无需以原子操作的方式删除会话状态。 非规范评注 把新开始(Clean Start)设置为1且会话过期间隔(Session Expiry Interval)设置为0,等同于在MQTT v3.1.1中把清理会话(CleanSession)设置为1。把新开始(Clean Start)设置为0且不设置会话过期间隔(Session Expiry Interval),等同于在MQTT v3.1.1中把清理会话标志设置为0。 非规范评注 当希望只处理连接上服务端之后才发布的消息,客户端应该把新开始(Clean Start)设置为1且会话过期间隔(Session Expiry Interval)设置为0,这样客户端就不会收到它连接之前被服务端所发布的消息,并且需要每次连接上服务端时重新订阅其感兴趣的主题。 非规范评注 某些客户端使用的网络可能只能提供断断续续的连接,这种客户端可以使用较短的会话过期间隔(Session Expiry Interval)以便在网络再次可用后重新连接到服务端时获得持续的消息交付。如果客户端不再重新连接,且允许会话过期,应用消息将会丢失。 非规范评注 某个客户端设置较长的会话过期间隔(Session Expiry Interval)或设置会话不过期,即要求服务端为其保持会话到其下一次连接上服务端之后。只有打算在一段时间之后将会重连服务端时,客户端才应该设置较长的会话过期间隔(Session Expiry Interval)。当客户端认定其将来不会使用本次会话时,应该在断开时把会话过期间隔(Session Expiry Interval)设置为0。 非规范评注 客户端应当使用CONNACK报文中的会话存在(Session Present)来判定服务端是否存储了其会话。 非规范评注 客户端应当以服务端返回的会话存在(Session Present)标志来判定会话是否已过期,而不是客户端自己实现的会话过期状态。如果客户端自己实现会话过期状态,则需要将会话应当被删除的时间作为会话状态的一部分而存储。 3.1.2.11.3 接收最大值 Receive Maximum 33 (0x21),接收最大值(Receive Maximum)标识符。跟随其后的是由双字节整数表示的最大接收值。包含多个接收最大值或接收最大值为0将造成协议错误(Protocol Error)。 客户端使用此值限制客户端愿意同时处理的QoS为1和QoS为2的发布消息最大数量。没有机制可以限制服务端试图发送的QoS为0的发布消息。 接收最大值只将被应用在当前网络连接。如果没有设置最大接收值,将使用默认值65535。 关于接收最大值的详细使用,参考4.9节流控。 3.1.2.11.4 最大报文长度 Maximum Packet Size 39 (0x27),最大报文长度(Maximum Packet Size)标识符。跟随其后的是由四字节整数表示的客户端愿意接收的最大报文长度(Maximum Packet Size),如果没有设置最大报文长度(Maximum Packet Size),则按照协议由固定报头中的剩余长度可编码最大值和协议报头对数据包的大小做限制。 包含多个最大报文长度(Maximum Packet Size)或者最大报文长度(Maximum Packet Size)值为0将造成协议错误。 非规范评注 客户端如果选择了限制最大报文长度,应该为最大报文长度设置一个合理的值。 如2.1.4节所述,最大报文长度是MQTT控制报文的总长度。客户端使用最大报文长度通知服务端其所能处理的单个报文长度限制。 服务端不能发送超过最大报文长度(Maximum Packet Size)的报文给客户端 [MQTT-3.1.2-24]。收到长度超过限制的报文将导致协议错误,客户端发送包含原因码0x95(报文过大)的DISCONNECT报文给服务端,详见4.13节。 当报文过大而不能发送时,服务端必须丢弃这些报文,然后当做应用消息发送已完成处理 [MQTT-3.1.2-25]。 共享订阅的情况下,如果一条消息对于部分客户端来说太长而不能发送,服务端可以选择丢弃此消息或者把消息发送给剩余能够接收此消息的客户端。 非规范评注 服务端可以把那些没有发送就被丢弃的报文放在死信队列上,或者执行其他诊断操作。具体的操作超出了本规范的范围。 3.1.2.11.5 主题别名最大值 Topic Alias Maximum 34 (0x22),主题别名最大值(Topic Alias Maximum)标识符。跟随其后的是用双字节整数表示的主题别名最大值(Topic Alias Maximum)。包含多个主题别名最大值(Topic Alias Maximum)将造成协议错误(Protocol Error)。没有设置主题别名最大值属性的情况下,主题别名最大值默认为零。 此值指示了客户端能够接收的来自服务端的主题别名(Topic Alias)最大数量。客户端使用此值来限制本次连接可以拥有的主题别名的数量。服务端在一个PUBLISH报文中发送的主题别名不能超过客户端设置的主题别名最大值(Topic Alias Maximum) [MQTT-3.1.2-26]。值为零表示本次连接客户端不接受任何主题别名(Topic Alias)。如果主题别名最大值(Topic Alias)没有设置,或者设置为零,则服务端不能向此客户端发送任何主题别名(Topic Alias) [MQTT-3.1.2-27]。 3.1.2.11.6 请求响应信息 Request Response Information 25 (0x19),请求响应信息(Request Response Information)标识符。跟随其后的是用一个字节表示的0或1。包含多个请求响应信息(Request Response Information),或者请求响应信息(Request Response Information)的值既不为0也不为1会造成协议错误(Protocol Error)。如果没有请求响应信息(Request Response Information),则请求响应默认值为0。 客户端使用此值向服务端请求CONNACK报文中的响应信息(Response Information)。值为0,表示服务端不能返回响应信息 [MQTT-3.1.2-28]。值为1,表示服务端可以在CONNACK报文中返回响应信息。 非规范评注 即使客户端请求响应信息(Response Information),服务端也可以选择不发送响应信息(Response Information)。 更多关于请求/响应信息的内容,请参考4.10节。 3.1.2.11.7 请求问题信息 Request Problem Information 23 (0x17),请求问题信息(Request Problem Information)标识符。跟随其后的是用一个字节表示的0或1。包含多个请求问题信息(Request Problem Information),或者请求问题信息(Request Problem Information)的值既不为0也不为1会造成协议错误(Protocol Error)。如果没有请求问题信息(Request Problem Information),则请求问题默认值为1。 客户端使用此值指示遇到错误时是否发送原因字符串(Reason String)或用户属性(User Properties)。 如果请求问题信息的值为0,服务端可以选择在CONNACK或DISCONNECT报文中返回原因字符串(Reason String)或用户属性(User Properties),但不能在除PUBLISH,CONNACK或DISCONNECT之外的报文中发送原因字符串(Reason String)或用户属性(User Properties) [MQTT-3.1.2-29]。如果此值为0,并且在除PUBLISH,CONNACK或DISCONNECT之外的报文中收到了原因字符串(Reason String)或用户属性(User Properties),客户端将发送一个包含原因码0x82(协议错误)的DISCONNECT报文给服务端,如4.13节所述。 如果此值为1,服务端可以在任何被允许的报文中返回原因字符串(Reason String)或用户属性(User Properties)。 3.1.2.11.8 用户属性 User Property 38 (0x26),用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。 用户属性(User Property)可以出现多次,表示多个名字/值对。相同的名字可以出现多次。 非规范评注 CONNECT报文中的用户属性可以被用来发送客户端到服务端的连接相关的属性。这些属性的意义本规范不做定义。 3.1.2.11.9 认证方法 Authentication Method 21 (0x15),认证方法(Authentication Method)标识符。跟随其后的是一个UTF-8编码的字符串,包含了扩展认证的认证方法(Authentication Method)名称。包含多个认证方法将造成协议错误(协议错误)。 如果没有认证方法,则不进行扩展验证。参考4.12节。 如果客户端在CONNECT报文中设置了认证方法,则客户端在收到CONNACK报文之前不能发送除AUTH或DISCONNECT之外的报文 [MQTT-3.1.2-30]。 3.1.2.11.10 认证数据 Authentication Data 22 (0x16),认证数据(Authentication Data)标识符。跟随其后的是二进制的认证数据。没有认证方法却包含了认证数据(Authentication Data),或者包含多个认证数据(Authentication Data)将造成协议错误(Protocol Error)。 认证数据的内容由认证方法定义,关于扩展认证的更多信息,请参考4.12节。 3.1.2.12 可变报头非规范示例 Variable Header non-normative example 图 3-6 - 可变报头示例 说明76543210协议名 Protocol Namebyte 1长度 Length MSB (0)00000000byte 2长度 Length LSB (4)00000100byte 3‘M’01001101byte 4‘Q’01010001byte 5‘T’01010100byte 6‘T’01010100协议版本 Protocol Version说明76543210byte 7版本 Version (5)00000101连接标志 Connect Flagsbyte 8用户名标志 User Name Flag (1)密码标志 Password Flag (1)遗嘱保留标志 Will Retain (0)遗嘱服务质量 Will QoS (01)遗嘱标志 Will Flag (1)新开始 Clean Start(1)保留 Reserved (0)11001110保持连接 Keep Alivebyte 9保持连接 Keep Alive MSB (0)00000000byte 10保持连接 Keep Alive LSB (10)00001010属性 Propertiesbyte 11长度 Length (5)00000101byte 12会话过期间隔标识符 (17)00010001byte 13会话过期间隔Session Expiry Interval (10)00000000byte 1400000000byte 1500000000byte 1600001010 3.1.3 CONNECT 载荷 CONNECT Payload CONNECT报文的载荷中包含由可变报头(Variable Header)中的标志确定的一个或多个以长度为前缀的字段。这些字段若存在,必须按照客户标识符(Client Identifier)、遗嘱属性(Will Properties)、遗嘱主题(Will Topic)、遗嘱载荷(Will Payload)、用户名(User Name)、密码(Password)的顺序出现 [MQTT-3.1.3-1]。 3.1.3.1 客户标识符 Client Identifier 服务端使用客户标识符(ClientID)识别客户端。连接服务端的每个客户端都有唯一的客户标识符(ClientID)。客户端和服务端都必须使用客户标识符(ClientID)识别两者之间的 MQTT 会话相关的状态 [MQTT-3.1.3-2]。更多关于会话状态的信息请参考4.1节。 客户标识符必须存在,且作为CONNECT报文载荷的第一个字段出现 [MQTT-3.1.3-3]。 客户标识符必须被编码为1.5.4节 中所定义的UTF-8字符串 [MQTT-3.1.3-4]。 服务端必须允许1到23个字节长的UTF-8编码的客户标识符,客户标识符只能包含这些字符: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"(大写字母、小写字母和数字) [MQTT-3.1.3-5]。 服务端可以允许编码后超过23个字节的客户标识符 (ClientID)。服务端可以允许包含不是上面列表字符的客户标识符 (ClientID)。 服务端可以允许客户端提供一个零字节的客户标识符 (ClientID) ,如果这样做了,服务端必须将这看作特殊情况并分配唯一的客户标识符给那个客户端 [MQTT-3.1.3-6]。然后它必须假设客户端提供了那个唯一的客户标识符,正常处理这个CONNECT报文 [MQTT-3.1.3-7]。 如果服务端拒绝了某个客户标识符(ClientID),它可以发送包含原因码0x85(客户标识符无效)的CONNACK报文作为对客户端的CONNECT报文的回应,如4.13节所述。之后必须关闭网络连接 [MQTT-3.1.3-8]。 非规范评注 客户端在实现时可以提供一个便于生成随机客户标识符的算法。使用此算法时,客户端需要注意避免创建长期孤儿会话。 3.1.3.2 遗嘱属性 Will Properties 如果遗嘱标志(Will Flag)被设置为1,有效载荷的下一个字段是遗嘱属性(Will Properties)。遗嘱属性字段定义了遗嘱消息(Will Message)将何时被发布,以及被发布时的应用消息(Application Message)属性。遗嘱属性包括属性长度和属性。 3.1.3.2.1 属性长度 Property Length 遗嘱属性(Will Properties)中的属性长度被编码为可变长字节整数。 3.1.3.2.2 遗嘱延时间隔 Property Length 24 (0x18),遗嘱延时间隔(Will Delay Interval)标识符。跟随其后的是由四字节整数表示的以秒为单位的遗嘱延时间隔(Will Delay Interval)。包含多个遗嘱延时间隔将造成协议错误(Protocol Error)。如果没有设置遗嘱延时间隔,遗嘱延时间隔默认值将为0,即不用延时发布遗嘱消息(Will Message)。 服务端将在遗嘱延时间隔(Will Delay Interval)到期或者会话(Session)结束时发布客户端的遗嘱消息(Will Message),取决于两者谁先发生。如果某个会话在遗嘱延时间隔到期之前创建了新的网络连接,则服务端不能发送遗嘱消息 [MQTT-3.1.3-9]。 非规范评注 遗嘱时间间隔的一个用途是避免在频繁的网络连接临时断开时发布遗嘱消息,因为客户端往往会很快重新连上网络并继续之前的会话。 非规范评注 如果某个连接到服务端的网络连接使用已存在的客户标识符,此已存在的网络连接的遗嘱消息将会被发布,除非新的网络连接设置了新开始(Clean Start)为0并且遗嘱延时大于0。如果遗嘱延时为0,遗嘱消息将在网络连接断开时发布。如果新开始为1,遗嘱消息也将被发布,因为此会话已结束。 3.1.3.2.3 载荷格式指示 Payload Format Indicator 1 (0x01),载荷格式指示(Payload Format Indicator)标识符。跟随载荷格式指示(Payload Format Indicator )之后的可能是: 0 (0x00),表示遗嘱消息(Will Message)是未指定的字节,等同于不发送载荷格式指示。 1 (0x01),表示遗嘱消息(Will Message)是UTF-8编码的字符数据。载荷中的UTF-8数据必须按照Unicode规范[Unicode]和RFC 3629 [RFC3629]中的申明进行编码。 包含多个载荷格式指示(Payload Format Indicator)将造成协议错误(Protocol Error)。服务端可以按照格式指示对遗嘱消息(Will Message)进行验证,如果验证失败发送一条包含原因码0x99(载荷格式无效)的CONNACK报文。如4.13节所述。 3.1.3.2.4 消息过期间隔 Message Expiry Interval 2 (0x02),消息过期间隔(Message Expiry Interval)标识符。跟随其后的是表示消息过期间隔(Message Expiry Interval)的四字节整数。包含多个消息过期间隔将导致协议错误(Protocol Error)。 如果设定了消息过期间隔(Message Expiry Interval),四字节整数描述了遗嘱消息的生命周期(秒),并在服务端发布遗嘱消息时被当做发布过期间隔(Publication Expiry Interval)。 如果没有设定消息过期间隔,服务端发布遗嘱消息时将不发送消息过期间隔(Message Expiry Interval)。 3.1.3.2.5 内容类型 Content Type 3 (0x03),内容类型(Content Type)标识符。跟随其后的是一个以UTF-8格式编码的字符串,用来描述遗嘱消息(Will Message)的内容。包含多个内容类型(Content Type)将造成协议错误(Protocol Error)。内容类型的值由发送应用程序和接收应用程序确定。 3.1.3.2.6 响应主题 Response Topic 8 (0x08),响应主题(Response Topic)标识符。跟随其后的是一个以UTF-8格式编码的字符串,用来表示响应消息的主题名(Topic Name)。包含多个响应主题(Response Topic)将造成协议错误。响应主题的存在将遗嘱消息(Will Message)标识为一个请求报文。 更多关于请求/响应的内容,参考4.10节。 3.1.3.2.7 对比数据 Correlation Data 9 (0x09),对比数据(Correlation Data)标识符。跟随其后的是二进制数据。对比数据被请求消息发送端在收到响应消息时用来标识相应的请求。包含多个对比数据将造成协议错误(Protocol Error)。如果没有设置对比数据,则请求方(Requester)不需要任何对比数据。 对比数据只对请求消息(Request Message)的发送端和响应消息(Response Message)的接收端有意义。 更多关于请求/响应的内容,参考4.10节。 3.1.3.2.8 用户属性 User Property 38 (0x26),用户属性(User Property)标识符。 跟随其后的是一个UTF-8字符串对。用户属性(User Property)可以出现多次,表示多个名字/值对。相同的名字可以出现多次。 服务端在发布遗嘱消息(Will Message)时必须维护用户属性(User Properties)的顺序 [MQTT-3.1.3-10]。 非规范评注 此属性旨在提供一种传递应用层名称-值标签的方法,其含义和解释仅由负责发送和接收它们的应用程序所有。 3.1.3.3 遗嘱主题 Will Topic 如果遗嘱标志(Will Flag)被设置为1,遗嘱主题(Will Topic)为载荷中下一个字段。遗嘱主题(Will Topic)必须为UTF-8编码的字符串,如1.5.4节 所定义 [MQTT-3.1.3-11]。 3.1.3.4 遗嘱载荷 Will Payload 如果遗嘱标志(Will Flag)被设置为1,遗嘱载荷(Will Payload)为载荷中下一个字段。遗嘱载荷定义了将要发布到遗嘱主题(Will Topic)的应用消息载荷,如3.1.2.5节所定义。此字段为二进制数据。 3.1.3.5 用户名 User Name 如果用户名标志(User Name Flag)被设置为1,用户名(User Name)为载荷中下一个字段。用户名必须是1.5.4节定义的UTF-8 编码字符串 [MQTT-3.1.3-12]。服务端可以将它用于身份验证和授权。 3.1.3.6 密码 Password 如果密码标志(Password Flag)被设置为1,密码(Password)为载荷中下一个字段。密码字段是二进制数据,尽管被称为密码,但可以被用来承载任何认证信息。 3.1.4 CONNECT 行为 CONNECT Actions 注意:服务器可以在同一个TCP端口或其他网络端点上支持多种协议(包括本协议的早期版本)。如果服务器确定协议是MQTT v5.0,那么它按照下面的方法验证连接请求。 网络连接建立后,如果服务端在合理的时间内没有收到 CONNECT 报文,服务端应该关闭这个连接。 服务端必须按照3.1节的要求验证CONNECT报文,如果报文不符合规范,服务端关闭网络连接 [MQTT-3.1.4-1]。服务端可以在关闭网络连接之前发送包含3.1.2.4节所述的0x80及以上原因码的CONNACK报文。 服务端可以检查CONNECT报文的内容是不是满足任何进一步的限制,应该执行身份验证和授权检查。如果任何一项检查没通过,服务端必须关闭网络连接 [MQTT-3.1.4-2]。在关闭网络连接之前,服务端可以发送一个合适的包含如3.2节和4.13节所述的0x80及以上原因码的CONNACK报文。 如果验证成功,服务端会执行下列步骤。 如果客户标识符(ClientID)所代表的客户端已经连接到此服务端,那么向原有的客户端发送一个包含原因码为0x8E(会话被接管)的DISCONNECT报文,并且必须关闭原有的网络连接 [MQTT-3.1.4-3]。如果原有客户端存在遗嘱消息(Will Message),遗嘱消息按照 3.1.2.5节所描述的方式发布。 非规范评注 如果原有网络连接包含遗嘱消息,且遗嘱延时间隔为0,则遗嘱消息会在此网络连接被关闭时发送。如果原有网络连接会话过期间隔为0,或者新网络连接新开始标志设置为1且原有网络连接包含遗嘱消息,则遗嘱消息会被发送,因为原有会话已结束。 服务端必须按照3.1.2.4节所描述的方式对新开始标志进行处理 [MQTT-3.1.4-4]。 服务端必须使用包含原因码为0x00(成功)的CONNACK报文对客户端的CONNECT报文进行确认 [MQTT-3.1.4-5]。 非规范评注 如果服务端被用来处理商业关键数据,推荐对网络连接进行认证和授权。如果认证和授权成功,服务端可通过发送包含原因码为0x00(成功)的CONNACK报文进行响应,否则建议服务端根本不要发送CONNACK报文,因为这是一种潜在的对MQTT服务端的攻击,可以被用来进行拒绝服务攻击或密码猜测攻击。 开始消息分发和保持连接状态监视。 允许客户端在发送CONNECT报文之后立即发送其它的MQTT控制报文;客户端不需要等待服务端的CONNACK报文。如果服务端拒绝了CONNECT报文,它不能处理客户端在CONNECT报文之后发送的任何除AUTH以外的报文 [MQTT-3.1.4-6]。 非规范评注 客户端通常会等待CONNACK报文。然而,如果在收到CONNACK报文之前就自由的发送其它MQTT控制报文将会简化客户端的实现,因为它不必监督连接的状态。如果连接被拒绝了,客户端在接收CONNACK报文之前发送的任何数据将不会被服务端所处理。 非规范评注 选择在收到CONNACK报文之前就发送MQTT控制报文的客户端将不知道服务端所存在的约束以及会话是否被使用。 非规范评注 服务端在对某个客户端完成认证之前,可以选择限制读取该客户端的网络数据或者关闭该客户端的网络连接。这是一种避免拒绝服务攻击的方法。 项目主页 MQTT v5.0协议草案中文版 3.2 CONNACK – 确认连接请求 Connect acknowledgement CONNACK报文由服务端所发送,作为对来自客户端的CONNECT报文的响应。服务端在发送任何除AUTH以外的报文之前必须先发送包含原因码为0x00(成功)的CONNACK报文 [MQTT-3.2.0-1]。服务端在一次网络连接中不能发送多个CONNACK报文 [MQTT-3.2.0-2]。 如果客户端在合理的时间内没有收到服务端的CONNACK报文,客户端应该关闭网络连接。合理 的时间取决于应用的类型和通信基础设施。 3.2.1 CONNACK 固定报头 CONNACK Fixed Header 固定报头的格式见图 3-7的描述。 图 3-7 – CONNACK 报文固定报头 CONNACK packet Fixed Header Bit76543210byte 1MQTT报文类型 (2)Reserved 保留位00100000byte 2...剩余长度 (2)00000010 剩余长度字段用变长字节整数来编码,表示可变报头的长度。 3.2.2 CONNACK 可变报头 CONNACK Variable Header CONNACK报文的可变报头按顺序包含以下字段:连接确认标志(Connect Acknowledge Flags),连接原因码(Reason Code),属性(Properties)。属性的编码规则如2.2.2节所描述。 3.2.2.1 连接确认标志 Connect Acknowledge Flags 第1个字节是连接确认标志,位7-1是保留位且必须设置为0 [MQTT-3.2.2-1]。 第0(SP)位是会话存在标志(Session Present Flag)。 3.2.2.1.1 会话存在 Session Present 位置: 连接确认标志(Connect Acknowledge Flags)的第0位。 会话存在(Session Present)标志通知客户端,服务端是否正在使用此客户标识符之前连接的会话状态(Session State)。会话存在标志使服务端和客户端在是否有已存储的会话状态上保持一致。 如果服务端接受一个新开始(Clean Start)为1的连接,服务端在CONNACK报文中除了把原因码设置为0x00(成功)之外,还必须把会话存在标志设置为0 [MQTT-3.2.2-2]。 如果服务端接受一个新开始(Clean Start)为0的连接,并且服务端已经保存了此客户标识符(ClientID)的会话状态(Session State),服务端在CONNACK报文中必须把会话存在标志设置为1。否则,服务端必须把会话存在标志设置为0。无论如何,服务端在CONNACK报文中必须把原因码设置为0x00(成功) [MQTT-3.2.2-3]。 如果客户端从服务端接收到的会话存在标志值与预期的不同,客户端做如下处理: 如果客户端没有保存的会话状态,但收到会话存在标志为1,客户端必须关闭网络连接 [MQTT-3.2.2-4]。 如果希望重新开始一个新的会话,客户端可以使用新开始(Clean Start)为1并重新连接服务端。 如果客户端保存了会话状态,但收到的会话存在标志为0,客户端若要继续此网络连接,它必须丢弃其保存的会话状态 [MQTT-3.2.2-5]。 如果服务端发送的CONNACK报文中原因码非0,它必须把会话存在标志设置为0 [MQTT-3.2.2-6]。 3.2.2.2 连接原因码 Connect Reason Code 可变报头中第2个字节是连接原因码(Reason Code)。 连接原因码(Reason Code)的值如下所示。如果服务端收到一个格式正确的CONNECT报文,但服务端无法完成连接的创建,服务端可以发送一个包含适当的连接原因码的CONNACK报文。如果服务端发送了一个包含原因码大于等于128的CONNACK报文,它随后必须关闭网络连接 [MQTT-3.2.2-7]。 表 3-1 - 连接原因码 Connect Reason Code values 值16进制原因码名称说明00x00成功连接被接受。1280x80未指明的错误服务端不愿透露的错误,或者没有适用的原因码。1290x81无效报文CONNECT报文内容不能被正确的解析。1300x82协议错误CONNECT报文内容不符合本规范。1310x83实现特定错误CONNECT有效,但不被服务端所接受。1320x84协议版本不支持服务端不支持客户端所请求的MQTT协议版本。1330x85客户标识符无效客户标识符有效,但未被服务端所接受。1340x86用户名密码错误客户端指定的用户名密码未被服务端所接受。1350x87未授权客户端未被授权连接。1360x88服务端不可用MQTT服务端不可用。1370x89服务端正忙服务端正忙,请重试。1380x8A禁止客户端被禁止,请联系服务端管理员。1400x8C无效的认证方法认证方法未被支持,或者不匹配当前使用的认证方法。1440x90主题名无效遗嘱主题格式正确,但未被服务端所接受。1490x95报文过长CONNECT报文超过最大允许长度。1510x97超出配额已超出实现限制或管理限制。1530x99载荷格式无效遗嘱载荷数据与载荷格式指示符不匹配。1540x9A不支持保留遗嘱保留标志被设置为1,但服务端不支持保留消息。1550x9B不支持的QoS等级服务端不支持遗嘱中设置的QoS等级。1560x9C(临时)使用其他服务端客户端应该临时使用其他服务端。1570x9D服务端已(永久)移动客户端应该永久使用其他服务端1590x9F超出连接速率限制超出了所能接受的连接速率限制。 服务端发送的CONNACK报文必须设置一种原因码 [MQTT-3.2.2-8]。 非规范评注 原因码0x80(未指明的错误)可以被用作:服务器知道失败的原因但是并不希望透露给客户端,或者没有其他适用的原因码。 出于安全考虑,发现CONNECT出错时服务端可以选择不发送CONNACK报文而关闭网络连接。例如,在公网中向未被授权的网络连接告知自身MQTT服务端身份并不明智。 3.2.2.3 CONNACK属性 CONNACK Properties 3.2.2.3.1 属性长度 Property Length CONNACK报文可变报头中的属性长度,编码为变长字节整数。 3.2.2.3.2 会话过期间隔 Session Expiry Interval 17 (0x11),会话过期间隔(Session Expiry Interval)标识符。跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话过期间隔(Session Expiry Interval)将造成协议错误(Protocol Error)。 如果会话过期间隔(Session Expiry Interval)值未指定,则使用CONNECT报文中指定的会话过期时间间隔。服务端使用此属性通知客户端它使用的会话过期时间间隔与客户端在CONNECT中发送的值不同。更详细的关于会话过期时间的描述,请参考3.1.2.11.2节。 3.2.2.3.3 接收最大值 Receive Maximum 33 (0x21),接收最大值(Receive Maximum)描述符。跟随其后的是由双字节整数表示的最大接收值。包含多个接收最大值或接收最大值为0将造成协议错误(Protocol Error)。 服务端使用此值限制服务端愿意为该客户端同时处理的QoS为1和QoS为2的发布消息最大数量。没有机制可以限制客户端试图发送的QoS为0的发布消息。 如果没有设置最大接收值,将使用默认值65535。 关于接收最大值的详细使用,参考4.9节流控部分。 3.2.2.3.4 最大服务质量 Maximum QoS 36 (0x24),最大服务质量(Maximum QoS)标识符。跟随其后的是用一个字节表示的0或1。包含多个最大服务质量(Maximum QoS)或最大服务质量既不为0也不为1将造成协议错误。如果没有设置最大服务质量,客户端可使用最大QoS为2。 如果服务端不支持Qos为1或2的PUBLISH报文,服务端必须在CONNACK报文中发送最大服务质量以指定其支持的最大QoS值 [MQTT-3.2.2-9]。即使不支持QoS为1或2的PUBLISH报文,服务端也必须接受请求QoS为0、1或2的SUBSCRIBE报文 [MQTT-3.2.2-10]。 如果从服务端接收到了最大QoS等级,则客户端不能发送超过最大QoS等级所指定的QoS等级的PUBLISH报文 [MQTT-3.2.2-11]。服务端接收到超过其指定的最大服务质量的PUBLISH报文将造成协议错误(Protocol Error)。这种情况下应使用包含原因码为0x9B(不支持的QoS等级)的DISCONNECT报文进行处理,如4.13节所述。 如果服务端收到包含遗嘱的QoS超过服务端处理能力的CONNECT报文,服务端必须拒绝此连接。服务端应该使用包含原因码为0x9B(不支持的QoS等级)的CONNACK报文进行错误处理,随后必须关闭网络连接。4.13节所述 [MQTT-3.2.2-12]。 非规范评注 客户端不必支持QoS为1和2的PUBLISH报文。客户端只需将其发送的任何SUBSCRIBE报文中的QoS字段限制在其支持的最大服务质量以内即可。 3.2.2.3.5 保留可用 Retain Available 37 (0x25),保留可用(Retain Available)标识符。跟随其后的是一个单字节字段,用来声明服务端是否支持保留消息。值为0表示不支持保留消息,为1表示支持保留消息。如果没有设置保留可用字段,表示支持保留消息。包含多个保留可用字段或保留可用字段值不为0也不为1将造成协议错误(Protocol Error)。 如果服务端收到一个包含保留标志位1的遗嘱消息的CONNECT报文且服务端不支持保留消息,服务端必须拒绝此连接请求,且应该发送包含原因码为0x9A(不支持保留)的CONNACK报文,随后必须关闭网络连接 [MQTT-3.2.2-13]。 从服务端接收到的保留可用标志为0时,客户端不能发送保留标志设置为1的PUBLISH报文 [MQTT-3.2.2-14]。如果服务端收到这种PUBLISH报文,将造成协议错误(Protocol Error),此时服务端应该发送包含原因码为0x9A(不支持保留)的DISCONNECT报文,如4.13节所述。 3.2.2.3.6 最大报文长度 Maximum Packet Size 39 (0x27),最大报文长度(Maximum Packet Size)标识符。跟随其后的是由四字节整数表示的服务端愿意接收的最大报文长度(Maximum Packet Size)。如果没有设置最大报文长度,则按照协议由固定报头中的剩余长度可编码最大值和协议报头对数据包的大小做限制。 包含多个最大报文长度(Maximum Packet Size),或最大报文长度为0将造成协议错误(Protocol Error)。 如2.1.4节所述,最大报文长度是MQTT控制报文的总长度。服务端使用最大报文长度通知客户端其所能处理的单个报文长度限制。 客户端不能发送超过最大报文长度(Maximum Packet Size)的报文给服务端 [MQTT-3.2.2-15]。收到长度超过限制的报文将导致协议错误,此时服务端应该发送包含原因码0x95(报文过长)的DISCONNECT报文给客户端,详见4.13节。 3.2.2.3.7 分配客户标识符 Assigned Client Identifier 18 (0x12),分配客户标识符(Assigned Client Identifier)标识符。跟随其后的是UTF-8编码的分配客户标识符(Assigned Client Identifier)字符串。包含多个分配客户标识符将造成协议错误(Protocol Error)。 服务端分配客户标识符的原因是CONNECT报文中的客户标识符长度为0。 如果客户端使用长度为0的客户标识符(ClientID),服务端必须回复包含分配客户标识符(Assigned Client Identifier)的CONNACK报文。分配客户标识符必须是没有被服务端的其他会话所使用的新客户标识符 [MQTT-3.2.2-16]。 3.2.2.3.8 主题别名最大值 Topic Alias Maximum 34 (0x22),主题别名最大值(Topic Alias Maximum)标识符。跟随其后的是用双字节整数表示的主题别名最大值(Topic Alias Maximum)。包含多个主题别名最大值(Topic Alias Maximum)将造成协议错误(Protocol Error)。没有设置主题别名最大值属性的情况下,主题别名最大值默认为零。 此值指示了服务端能够接收的来自客户端的主题别名(Topic Alias)最大值。服务端使用此值来限制本次连接可以拥有的主题别名的值。客户端在一个PUBLISH报文中发送的主题别名值不能超过服务端设置的主题别名最大值(Topic Alias Maximum) [MQTT-3.2.2-17]。值为0表示本次连接服务端不接受任何主题别名(Topic Alias)。如果主题别名最大值(Topic Alias)没有设置,或者设置为0,则客户端不能向此服务端发送任何主题别名(Topic Alias) [MQTT-3.2.2-18]。 3.2.2.3.9 原因字符串 Reason String 31 (0x1F),原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。如果加上原因字符串之后的CONNACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串 [MQTT-3.2.2-19]。包含多个原因字符串将造成协议错误(Protocol Error)。 非规范评注 客户端对原因字符串的恰当使用包括:抛出异常时使用此字符串,或者将此字符串写入日志。 3.2.2.3.10 用户属性 User Property 38 (0x26),用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的CONNACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性 [MQTT-3.2.2-20]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 用户属性的内容和意义本规范不做定义。CONNACK报文的接收端可以选择忽略此属性。 3.2.2.3.11 通配符订阅可用 Wildcard Subscription Available 40 (0x28),通配符订阅可用(Wildcard Subscription Available)标识符。跟随其后的是一个单字节字段,用来声明服务器是否支持通配符订阅(Wildcard Subscriptions)。值为0表示不支持通配符订阅,值为1表示支持通配符订阅。如果没有设置此值,则表示支持通配符订阅。包含多个通配符订阅可用属性,或通配符订阅可用属性值不为0也不为1将造成协议错误(Protocol Error)。 如果服务端在不支持通配符订阅(Wildcard Subscription)的情况下收到了包含通配符订阅的SUBSCRIBE报文,将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为0xA2(通配符订阅不支持)的DISCONNECT报文,如4.13节所述。 服务端在支持通配符订阅的情况下仍然可以拒绝特定的包含通配符订阅的订阅请求。这种情况下,服务端可以发送一个包含原因码为0xA2(通配符订阅不支持)的SUBACK报文。 3.2.2.3.12 订阅标识符可用 Subscription Identifier Available 41 (0x29),订阅标识符可用(Subscription Identifier Available)标识符。跟随其后的是一个单字节字段,用来声明服务端是否支持订阅标识符(Subscription Identifiers)。值为0表示不支持订阅标识符,值为1表示支持订阅标识符。如果没有设置此值,则表示支持订阅标识符。包含多个订阅标识符可用属性,或订阅标识符可用属性值不为0也不为1将造成协议错误(Protocol Error)。 如果服务端在不支持订阅标识符(Subscription Identifier)的情况下收到了包含订阅标识符的SUBSCRIBE报文,将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为0xA1(订阅标识符不支持)的DISCONNECT报文,如4.13节所述。 3.2.2.3.13 共享订阅可用 Shared Subscription Available 42 (0x2A),共享订阅可用(Shared Subscription Available)标识符。跟随其后的是一个单字节字段,用来声明服务端是否支持共享订阅(Shared Subscription)。值为0表示不支持共享订阅,值为1表示支持共享订阅。如果没有设置此值,则表示支持共享订阅。包含多个共享订阅可用(Shared Subscription Available),或共享订阅可用属性值不为0也不为1将造成协议错误(Protocol Error)。 如果服务端在不支持共享订阅(Shared Subscription)的情况下收到了包含共享订阅的SUBSCRIBE报文,将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为0x9E(共享订阅不支持)的DISCONNECT报文,如4.13节所述。 3.2.2.3.14 服务端保持连接 Server Keep Alive 19 (0x13),服务端保持连接(Server Keep Alive)标识符。跟随其后的是由服务端分配的双字节整数表示的保持连接(Keep Alive)时间。如果服务端发送了服务端保持连接(Server Keep Alive)属性,客户端必须使用此值代替其在CONNECT报文中发送的保持连接时间值 [MQTT-3.2.2-21]。如果服务端没有发送服务端保持连接属性,服务端必须使用客户端在CONNECT报文中设置的保持连接时间值 [MQTT-3.2.2-22]。包含多个服务端保持连接属性将造成协议错误(Protocol Error)。 非规范评注 服务端保持连接属性的主要作用是通知客户端它将会比客户端指定的保持连接更快的断开非活动的客户端。 3.2.2.3.15 响应信息 Response Information 26 (0x1A),响应信息(Response Information)标识符。跟随其后的是一个以UTF-8编码的字符串,作为创建响应主题(Response Topic)的基本信息。关于客户端如何根据响应信息(Response Information)创建响应主题不在本规范的定义范围内。包含多个响应信息将造成协议错误(Protocol Error)。 如果客户端发送的请求响应信息(Request Response Information)值为1,则服务端在CONNACK报文中发送响应信息(Response Information)为可选项。 非规范评注 响应信息通常被用来传递主题订阅树的一个全局唯一分支,此分支至少在该客户端的会话生命周期内为该客户端所保留。请求客户端和响应客户端的授权需要使用它,所以它通常不能仅仅是一个随机字符串。一般把此分支作为特定客户端的订阅树根节点。通常此信息需要正确配置,以使得服务器能返回信息。使用此机制时,具体的信息一般由服务端来进行统一配置,而非由各个客户端自己配置。 更多关于请求/响应的信息,请参考4.10节。 3.2.2.3.16 服务端参考 Server Reference 28 (0x1C),服务端参考(Server Reference)标识符。跟随其后的是一个以UTF-8编码的字符串,可以被客户端用来标识其他可用的服务端。包含多个服务端参考(Server Reference)将造成协议错误(Protocol Error)。 服务端在包含了原因码为0x9C((临时)使用其他服务端)或0x9D(服务端已(永久)移动)的CONNACK报文或DISCONNECT报文中设置服务端参考,如4.13节所述。 关于如何使用服务端参考,请参考4.11节服务端重定向信息。 3.2.2.3.17 认证方法 Authentication Method 21 (0x15),认证方法(Authentication Method)标识符。跟随其后的是一个以UTF-8编码的字符串,包含了认证方法(Authentication Method)名。包含多个认证方法将造成协议错误(Protocol Error)。更多关于扩展认证的信息,请参考4.12节。 3.2.2.3.18 认证数据 Authentication Data 22 (0x16),认证数据(Authentication Data)标识符。跟随其后的是包含认证数据(Authentication Data)的二进制数据。此数据的内容由认证方法和已交换的认证数据状态定义。包含多个认证数据将造成协议错误(Protocol Error)。更多关于扩展认证的信息,请参考4.12节。 3.2.3 CONNACK 载荷 CONNACK Payload CONNACK报文不包含有效载荷。 项目主页 MQTT v5.0协议草案中文版 3.3 PUBLISH – 发布消息 Publish message PUBLISH报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。 3.3.1 PUBLISH 固定报头 PUBLISH Fixed Header 图 3-8 – PUBLISH报文固定报头 PUBLISH packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (3)DUPQoS等级RETAIN0011XXXXbyte 2...剩余长度 3.3.1.1 重发标志 DUP 位置: 第1个字节,第3位 如果DUP标志被设置为0,表示这是客户端或服务端第一次请求发送这个PUBLISH报文。如果DUP标志被设置为1,表示这可能是一个早前报文请求的重发。 客户端或服务端请求重发一个PUBLISH报文时,必须将DUP标志设置为1 [MQTT-3.3.1-1]。对于QoS为0的消息,DUP标志必须设置为0 [MQTT-3.3.1-2]。 服务端发送PUBLISH报文给订阅者时,收到(入站)的PUBLISH报文的DUP标志的值不会被传播。发送(出站)的PUBLISH报文与收到(入站)的PUBLISH报文中的DUP标志是独立设置的,它的值必须单独的根据发送(出站)的PUBLISH报文是否是一个重发来确定 [MQTT-3.3.1-3]。 非规范评注 接收者收到一个DUP标志位1的MQTT控制报文时,不能假设它看到了一个这个报文之前的一个副本。 非规范评注 需要特别指出的是,DUP标志关注的是MQTT控制报文本身,与它包含的应用消息无关。当使用QoS 1时,客户端可能会收到一个DUP标志为0的PUBLISH 报文,这个报文包含一个它之前收到过的应用消息的副本,但是用的是不同的报文标识符。 2.2.1节提供了有关报文标识符的更多信息。 3.3.1.2 服务质量等级 QoS 位置: 第1个字节,第2-1位。 这个字段表示应用消息分发的服务质量等级保证。服务质量等级在下表中列出。 表格 3-2 - 服务质量定义 QoS definitions QoS值Bit 2Bit 1说明000最多分发一次101至少分发一次210只分发一次-11保留位 如果服务端在对客户端响应的CONNACK报文中包含了最大服务质量(Maximum QoS)且服务端收到的PUBLISH报文的QoS大于此最大服务质量,服务端发送包含原因码为0x9B(不支持的QoS等级)的DISCONNECT报文,如4.13节所述。 PUBLISH报文的2个QoS比特位不能同时设置为1 [MQTT-3.3.1-4]。如果服务端或客户端收到QoS 2个比特位都为1的无效PUBLISH报文,使用包含原因码为0x81(无效报文)的DISCONNECT报文关闭网络连接,如4.13节所述。 3.3.1.3 保留标志 RETAIN 位置: 第1个字节,第0位。 如果客户端发给服务端的PUBLISH报文的保留(Retain)标志被设置为1,服务端必须存储此应用消息,并用其替换此话题下任何已存在的消息 [MQTT-3.3.1-5],以便它可以被分发给未来的匹配此主题名(Topic Name)的订阅者。如果载荷为空,消息可以正常被服务端所处理,但是此话题下的任何保留消息必须被丢弃,并且此话题未来的订阅者将不会收到保留消息 [MQTT-3.3.1-6]。载荷为空的保留消息将不能被存储在服务端 [MQTT-3.3.1-7]。 如果客户端发给服务端的PUBLISH报文的保留标志位为0,服务器不能把此消息存储为保留消息,也不能丢弃或替换任何已存在的保留消息 [MQTT-3.3.1-8]。 如果服务端发送给客户端的CONNACK报文中包含保留可用属性,且属性值为0,但收到的PUBLISH报文中保留标志位为1,服务端使用包含原因码为0x9A(保留不支持)的DISCONNECT报文断开网络连接,如4.13节所述。 当一个新的非共享订阅(Non-shared Subscription)被创建时,每个匹配的话题下的最新保留消息如果存在,将根据保留消息订阅选项(Retain Handling Subscription Option)发送给客户端。这些消息在发送时保留标志被设置为1。保留消息的发送由保留消息处理订阅选项控制,收到订阅时: 如果保留消息处理属性被设置为0,服务端必须发送主题与客户端订阅的主题过滤器(Topic Filter)相匹配的所有保留消息 [MQTT-3.3.1-9]。 如果保留消息处理属性被设置为1,如果尚不存在匹配的订阅,服务端必须发送主题与客户端订阅的主题过滤器相匹配的所有保留消息。如果已存在相匹配的订阅,服务器不能发送这些保留消息 [MQTT-3.3.1-10]。 如果保留消息处理属性被设置为2,服务器不能发送这些保留消息 [MQTT-3.3.1-11]。 订阅选项(Subscription Options)的定义,参考3.8.3.1节。 如果服务端收到保留标志设置为1且QoS设置为0的PUBLISH报文,服务端应该把此QoS为0的消息存储为其主题下最新的保留消息,但服务端可以选择在任何时间丢弃此消息。如果发生丢弃,该主题下将不存在任何保留消息。 如果某个主题当前的保留消息过期,该主题下将不存在任何保留消息。 服务端转发应用消息时,保留标志位的设置由发布保留(Retain As Published)订阅选项决定。订阅选项的定义,请参考3.8.3.1节。 如果发布保留(Retain As Published)订阅选项被设置为0,服务端在转发应用消息时必须将保留标志设置为0,而不管收到的PUBLISH报文中保留标志位如何设置的 [MQTT-3.3.1-12]。 如果发布保留(Retain As Published)订阅选项被设置为1,服务端在转发应用消息时必须将保留标志设置为与收到的PUBLISH消息中的保留标志位相同 [MQTT-3.3.1-13]。 非规范评注 对于发布者不定期发送状态消息这个场景,保留消息很有用。新的非共享订阅者将会收到最近的状态。 3.3.1.4 剩余长度 Remaining Length 等于可变报头的长度加上有效载荷的长度,被编码为变长字节整数。 3.3.2 PUBLISH可变报头 PUBLISH Variable Header PUBLISH报文可变报头按顺序包含:主题名(Topic Name),报文标识符(Packet Identifier),属性(Properties)。属性的编码规则如2.2.2节所述。 3.3.2.1 主题名 Topic Name 主题名(Topic Name)用于识别有效载荷数据应该被发布到哪一个信息通道。 主题名必须是PUBLISH报文可变报头的第一个字段。它必须是 1.5.4节定义的UTF-8编码的字符串 [MQTT-3.3.2-1]。 PUBLISH报文中的主题名不能包含通配符 [MQTT-3.3.2-2]。 服务端发送给订阅客户端的PUBLISH报文中的主题名必须匹配该订阅的主题过滤器(Topic Filter), 如4.7节所定义的匹配过程 [MQTT-3.3.2-3]。然而,由于服务端允许将主题名映射为其他名字,主题名可能与原始PUBLISH报文中的主题名不同。 发送端可以使用主题别名(Topic Alias)以便减少PUBLISH报文的长度。主题别名如3.3.2.3.4节所述。主题名长度为0且没有主题别名,将造成协议错误(Protocol Error)。 3.3.2.2 报文标识符 Packet Identifier 只有当QoS等级是1或2时,报文标识符(Packet Identifier)字段才能出现在PUBLISH报文中。2.2.1节提供了有关报文标识符的更多信息。 3.3.2.3 PUBLISH 属性 PUBLISH Properties 3.3.2.3.1 属性长度 Property Length PUBLISH报文可变报头中的属性长度被编码为变长字节整数。 3.3.2.3.2 载荷格式指示 Payload Format Indicator 1 (0x01),载荷格式指示(Payload Format Indicator)标识符。跟随其后的是单字节的载荷格式指示值,可以是: 0 (0x00),说明载荷是未指定格式的字节,相当于没有发送载荷格式指示。 1 (0x01),说明载荷是UTF-8编码的字符数据。载荷中的UTF-8数据必须是按照Unicode [Unicode]的规范和RFC 3629 [RFC3629]的重申进行编码。 服务端必须把接收到的应用消息中的载荷格式指示原封不动的发给所有的订阅者 [MQTT-3.3.2-4]。接收者可以验证载荷数据与所指示的格式一致,如果不一致,发送包含原因码为0x99(载荷格式无效)的PUBACK,PUBREC或DISCONNECT报文,如4.13节所述。 3.3.2.3.3 消息过期间隔 Message Expiry Interval 2 (0x02),消息过期间隔(Message Expiry Interval)标识符。跟随其后的是四字节整数表示的消息过期间隔(Message Expiry Interval)。 如果消息过期间隔存在,四字节整数表示以秒为单位的应用消息(Application Message)生命周期。如果消息过期间隔(Message Expiry Interval)已过期,服务端还没开始向匹配的订阅者交付该消息,则服务端必须删除该订阅者的消息副本 [MQTT-3.3.2-5]。 如果消息过期间隔不存在,应用消息不会过期。 服务端发送给客户端的PUBLISH报文中必须包含消息过期间隔,值为接收时间减去消息在服务端的等待时间 [MQTT-3.3.2-6]。关于状态存储的细节和限制,参考4.1节。 3.3.2.3.4 主题别名 Topic Alias 35 (0x23),主题别名(Topic Alias)标识符。跟随其后的是表示主题别名(Topic Alias)值的双字节整数。包含多个主题别名值将造成协议错误(Protocol Error)。 主题别名是一个整数,用来代替主题名对主题进行识别。主题别名可以减小PUBLISH报文的长度,这对某个网络连接中发送的很长且反复使用的主题名来说很有用。 发送端决定是否使用主题别名及别名值如何选取。发送端通过在PUBLISH报文中包含的非0长度主题名和主题别名来设置主题别名映射。接收端正常处理该PUBLISH报文,但同样将指定的主题别名映射到主题名。 如果接收端已经设置了某个主题别名映射,发送端可以发送包含主题别名和长度为0的主题名的PUBLISH报文。接收端把此PUBLISH报文的主题名当做其包含的主题别名所映射的主题名。 发送端可以通过在同一个网络连接中发送另一个包含同样主题别名和不同非0长度主题名的PUBLISH报文来修改主题别名映射关系。 主题别名映射仅作用于某个网络连接及其生命周期内。接收端不能将任何主题别名映射从一个网络连接转发到另一个网络连接 [MQTT-3.3.2-7]。 主题别名不允许为0。发送端不能发送包含主题别名值为0的PUBLISH报文 [MQTT-3.3.2-8]。 客户端不能发送主题别名值大于服务端的CONNACK报文中指定的主题别名最大值(Topic Alias Maximum)的PUBLISH报文 [MQTT-3.3.2-9]。客户端必须接受所有值大于0且小于等于其发送的CONNECT报文中的主题别名最大值的主题别名 [MQTT-3.3.2-10]。 服务端不能发送包含主题别名值大于客户端在CONNECT报文中指定的主题别名最大值(Topic Alias Maximum)的PUBLISH报文 [MQTT-3.3.2-11]。服务端必须接受所有值大于0且小于等于其发送的CONNACK报文中的主题别名最大值的主题别名 [MQTT-3.3.2-12]。 客户端和服务端使用的主题别名映射相互独立。因此一般来说,客户端发送给服务端的主题别名值为1的PUBLISH报文和服务端发送给客户端的主题别名值为1的PUBLISH报文,将被映射到不同的主题。 3.3.2.3.5 响应主题 Response Topic 8 (0x08),响应主题(Response Topic)标识符。跟随其后的是一个UTF-8编码的字符串,用作响应消息的主题名。响应主题必须是按照1.5.4节所定义的UTF-8编码的字符串 [MQTT-3.3.2-13]。响应主题不能包含通配符 [MQTT-3.3.2-14]。包含多个响应主题将造成协议错误(Protocol Error)。响应主题的存在将消息标识为请求报文。 更多关于请求/响应的信息,参考4.10节 。 服务端在收到应用消息时必须将响应主题原封不动的发送给所有的订阅者 [MQTT-3.3.2-15]。 非规范评注 包含响应主题的应用消息接收端使用响应主题作为主题名,发送作为响应消息的PUBLISH报文。如果请求消息中包含对比数据,接收端应当在发送作为对此请求消息进行响应的PUBLISH报文中包含此对比数据。 3.3.2.3.6 对比数据 Correlation Data 9 (0x09),对比数据(Correlation Data)标识符。跟随其后的是二进制数据。对比数据被请求消息发送端在收到响应消息时用来标识相应的请求。包含多个对比数据将造成协议错误(Protocol Error)。如果没有设置对比数据,则请求方(Requester)不需要任何对比数据。 服务端在收到应用消息时必须原封不动的把对比数据发送给所有的订阅者 [MQTT-3.3.2-16]。对比数据只对请求消息(Request Message)的发送端和响应消息(Response Message)的接收端有意义。 非规范评注 接收端收到包含响应主题和对比数据的应用消息时,发送以响应主题为主题名的PUBLISH报文作为响应消息。客户端在响应消息中应将对比数据作为PUBLISH报文的一部分原封不动的发送出去。 非规范评注 如果对客户端响应消息中的对比数据所做的任何更改会造成应用程序错误,则应当对对比数据进行加密/哈希,以便接收端能检测到对比数据是否被更改。 更多关于请求/响应的信息,请参考4.10节。 3.3.2.3.7 用户属性 Property Length 38 (0x26),用户属性(User Property)。跟随其后的是UTF-8字符串对。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 服务端在转发应用消息到客户端时必须原封不动的把所有的用户属性放在PUBLISH报文中 [MQTT-3.3.2-17]。服务端在转发应用消息时必须保持所有用户属性的先后顺序 [MQTT-3.3.2-18]。 非规范评注 此属性旨在提供一种传递应用层名称-值标签的方法,其含义和解释仅由负责发送和接收它们的应用程序所有。 3.3.2.3.8 订阅标识符 Subscription Identifier 11 (0x0B),订阅标识符(Subscription Identifier)标识符。跟随其后的是一个变长字节整数表示的订阅标识符。 订阅标识符取值范围从1到268,435,455。订阅标识符的值为0将造成协议错误。如果某条发布消息匹配了多个订阅,则将包含多个订阅标识符。这种情况下他们的顺序并不重要。 3.3.2.3.9 内容类型 Content Type 3 (0x03), 内容类型(Content Type)标识符。跟随其后的是一个以UTF-8格式编码的字符串,用来描述应用消息的内容。内容类型必须是UTF-8编码的字符串,如1.5.4节所定义 [MQTT-3.3.2-19]。 包含多个内容类型将造成协议错误(Protocol Error)。内容类型的值由发送应用程序和接收应用程序确定。 服务端必须把收到的应用消息中的内容类型原封不动的发送给所有的订阅者 [MQTT-3.3.2-20]。 非规范评注 UTF-8编码字符串可以使用一个MIME内容类型字符串来描述应用消息的内容。由于发送程序和接收程序负责内容类型字符串的定义和解释,因此MQTT服务端只确保内容类型是有效的UTF-8编码的字符串,不会做其他方面的验证。 非规范评注 图3-9是一个PUBLISH示例报文,其中主题名为a/b,报文标识符为10,没有属性。 图 3-9 - PUBLISH报文可变报头非规范示例 PUBLISH packet Variable Header non-normative example 说明76543210主题名byte 1长度MSB (0)00000000byte 2长度LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010报文标识符byte 6报文标识符MSB (0)00000000byte 7报文标识符LSB (10)00001010属性长度byte 8无属性00000000 3.3.3 PUBLISH 载荷 PUBLISH Payload 载荷包含将被发布的应用消息。载荷的内容和格式由应用程序指定。有效载荷的长度这样计算:用固定报头中的剩余长度字段的值减去可变报头的长度。包含零长度有效载荷的PUBLISH报文是合法的。 3.3.4 PUBLISH 行为 PUBLISH Actions PUBLISH报文的接收端必须按照PUBLISH报文中的QoS等级发送响应报文 [MQTT-3.3.4-1]。 表 3-3 - PUBLISH报文的预期响应 Expected PUBLISH packet response 服务质量等级预期响应QoS 0无响应QoS 1PUBACK报文QoS 2PUBREC报文 客户端使用PUBLISH报文发送应用消息给服务端,目的是分发到其他订阅匹配的客户端。 服务端使用PUBLISH报文发送应用消息给每一个订阅匹配的客户端。PUBLISH报文包含SUBSCRIBE报文中承载的订阅标识符--如果存在的话。 客户端使用带通配符的主题过滤器请求订阅时,客户端的订阅可能会重叠,因此发布的消息可能会匹配多个主题过滤器。这种情况下,服务端必须按照所有匹配的订阅中最大的QoS等级把消息发送给客户端 [MQTT-3.3.4-2]。此外,服务端可以为每一个匹配的订阅按照订阅时的QoS等级,把消息副本分发给客户端。 如果客户端收到一个未经请求的应用消息(没有匹配任何订阅),且QoS大于客户端指定的最大服务质量(Maximum QoS),客户端使用包含原因码为0x9B(不支持的QoS等级)的DISCONNECT报文断开连接,如4.13节所述。 如果客户端在这些重叠的订阅中指定了订阅标识符,服务端在发布这些订阅相匹配的消息时必须包含这些订阅标识符 [MQTT-3.3.4-3]。如果服务端对这些重叠的订阅只发送一条相匹配的消息,服务端必须在PUBLISH报文中包含所有的相匹配的订阅标识符(如果存在),但没有顺序要求 [MQTT-3.3.4-4]。如果服务端对这些重叠的订阅必须分别发送相匹配的消息,则每个PUBLISH报文中含与订阅相匹配的订阅标识符(如果存在) [MQTT-3.3.4-5]。 可能存在客户端对同一个发布消息做了多次订阅,并且这些订阅中有多个订阅使用了相同的订阅标识符,这种情况下PUBLISH报文将携带多个相同的订阅标识符。 PUBLISH报文中若包含服务端收到的SUBSCRIBE报文以外的订阅标识符,将造成协议错误(Protocol Error)。从客户端发送给服务端的PUBLISH报文不能包含订阅标识符 [MQTT-3.3.4-6]。 对于共享订阅,发送给某个客户端的PUBLISH报文中将只包含该客户端的SUBSCRIBE报文中发送的订阅标识符。 收到PUBLISH报文时,接收端的行为取决于报文的QoS等级,如4.3节所述。 如果PUBLISH报文包含主题别名,接收端按照以下方式进行处理: 1) 主题别名为0或大于最大主题别名(Maximum Topic Alias),将造成协议错误(Protocol Error),接收端使用包含原因码为0x94(主题别名无效)的DISCONNECT报文断开网络连接,如4.13节所述。 2) 如果接收端已创建此主题别名的映射, a) 如果报文包含的主题名长度为0,接收端使用主题别名对应的主题名处理此报文 b) 如果报文包含的主题名长度不为0,接收端使用此主题名处理此报文,并更新此主题别名映射到此主题名 3) 如果接收端还没有创建此主题别名的映射, a) 如果报文包含的主题名长度为0,将造成协议错误,接收端使用包含原因码为0x82(协议错误)的DISCONNECT报文断开网络连接,如4.13节所述。 b) 如果报文包含的主题名长度不为0,接收端使用此主题名处理此报文,并为此报文中的主题别名和主题名创建映射关系 非规范评注 如果服务端向客户端分发应用消息时使用了不同的协议级别(比如MQTT v3.1.1)-- 不支持属性或本规范提供的其他功能,应用消息中的某些信息将丢失,依赖于这些信息的应用程序可能无法正常工作。 客户端在收到服务端的PUBACK,PUBCOMP或包含原因码大于等于128的PUBREC报文之前,不能发送数量超过服务端的接收最大值(Receive Maximum)的QoS为1和2的PUBLISH报文 [MQTT-3.3.4-7]。服务端在发送PUBACK或PUBCOMP响应之前,如果收到数量超过客户端的接收最大值的QoS为1和2的PUBLISH报文,服务端使用包含原因码为0x93(超出接收最大值)的DISCONNECT报文断开网络连接,如4.13节所述。更多关于流量控制的信息,参考4.9节。 客户端不能延迟发送任何报文,除了PUBLISH报文--如果已发送且没有收到确认的PUBLISH报文数量已达到服务端的接收最大值(Receive Maximum) [MQTT-3.3.4-8]。接收最大值只应用于当前网络连接。 非规范评注 客户端可以选择发送少于服务端接收最大值的未经确认的PUBLISH报文,尽管它可以发送更多数量的报文。 非规范评注 客户端可以选择暂停发送QoS为0的报文,当其暂停发送了QoS为1和2的PUBLISH报文。 非规范评注 如果客户端在收到CONNACK之前发送QoS为1或QoS为2的PUBLISH报文,客户端有可能被服务器断开连接,因为它发送了超过服务端接收最大值数量的发布报文。 服务端在接收到客户端的PUBACK,PUBCOMP或包含原因码大于等于128的PUBREC报文之前,不能发送数量超过客户端的接收最大值(Receive Maximum)的QoS为1和2的PUBLISH报文 [MQTT-3.3.4-9]。客户端在发送PUBACK或PUBCOMP响应之前,如果收到数量超过服务端的接收最大值的QoS为1和2的PUBLISH报文,客户端使用包含原因码为0x93(超出接收最大值)的DISCONNECT报文断开网络连接,如4.13节所述。更多关于流量控制的信息,参考4.9节 。 服务端不能延迟发送任何报文,除了PUBLISH报文--如果已发送且没有收到确认的PUBLISH报文数量已到达客户端的接收最大值(Receive Maximum) [MQTT-3.3.4-10]。 非规范评注 服务端可以选择发送少于客户端接收最大值的未经确认的PUBLISH报文,尽管它可以发送更多数量的报文。 非规范评注 服务端可以选择暂停发送QoS为0的报文,当其暂停发送了QoS为1和2的PUBLISH报文。 项目主页 MQTT v5.0协议草案中文版3.4 PUBACK –发布确认 Publish acknowledgement PUBACK报文是对QoS 1等级的PUBLISH报文的响应。 3.4.1 PUBACK 固定报头 PUBACK Fixed Header 图 3-10 - PUBACK报文固定报头 PUBACK packet Fixed Header Bit76543210byte 1MQTT报文类型 (4)保留位01000000byte 2...剩余长度01000000 剩余长度字段表示可变报头的长度,用变长字节整数编码。 3.4.2 PUBACK 可变报头 PUBACK Variable Header PUBACK可变报头按顺序包含以下字段:所确认的PUBLISH报文标识符,PUBACK原因码,属性长度,属性(Properties)。属性编码规则如2.22节所述。 图 3-11 – PUBACK报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBACK原因码byte 4属性长度 LSB 3.4.2.1 PUBACK 原因码 PUBACK Reason Code PUBACK可变报头第3字节是原因码( Reason Code)。剩余长度为2,则表示使用原因码0x00(成功)。 表 3-4 – PUBACK原因码 PUBACK Reason Codes 值16进制原因码名称说明00x00成功消息被接收。QoS为1的消息已发布。160x10无匹配的订阅者消息被接收,但没有订阅者。只有服务端会发送此原因码。如果服务端得知没有匹配的订阅者,服务端可以使用此原因码代替0x00(成功)。1280x80未指明的错误接收端不接受此消息,且不愿意透露错误原因或没有适用的原因码。1310x83实现特定错误PUBLISH报文有效,但不被接收端所接受。1350x87未授权PUBLISH报文未授权。1440x90主题名无效主题名格式正确,但未被客户端或服务端所接受。1450x91报文标识符被占用报文标识符已被占用。可能表明客户端和服务端之间的会话状态不匹配。1510x97超出配额已超出实现限制或管理限制。1530x99载荷格式无效载荷格式与载荷格式指示符不匹配。 服务端或客户端发送PUBACK报文时必须设置其中一种PUBACK原因码 [MQTT-3.4.2-1]。当原因码为0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBACK剩余长度为2。 3.4.2.2 PUBACK 属性 PUBACK Properties 3.4.2.2.1 属性长度 Property Length PUBACK可变报头中属性长度被编码为变长字节整数。如果剩余长度小于4字节,则没有属性长度。 3.4.2.2.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不能被接收端所解析。 发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的PUBACK报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此原因字符串 [MQTT-3.4.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.4.2.2.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于提供包括诊断信息在内的附加信息。如果加上用户属性之后的PUBACK报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此属性 [MQTT-3.4.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.4.3 PUBACK 载荷 PUBACK Payload PUBACK报文没有有效载荷。 3.4.4 动作 描述见4.3.2节。 项目主页 MQTT v5.0协议草案中文版 3.5 PUBREC – 发布已接收(QoS 2,第一步) PUBREC报文是对QoS等级2的PUBLISH报文的响应。它是QoS 2等级协议交换的第二个报文。 3.5.1 PUBREC 固定报头 PUBREC Fixed Header 图 3-12 – PUBREC报文固定报头 PUBREC packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (5)保留位01010000byte 2剩余长度 (2) 剩余长度字段表示可变报头的长度,用变长字节整数编码。 3.5.2 PUBREC 可变报头 PUBREC Variable Header PUBREC可变报头按顺序包含以下字段:所确认的PUBLISH报文标识符(Packet Identifier),PUBREC原因码(Reason Code),属性(Properties)。属性的编码规则,如2.2.2节所述。 图 3-13 – PUBREC报文可变报头 PUBREC packet Variable Header Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBREC原因码byte 4属性长度 3.5.2.1 PUBREC 原因码 PUBREC Reason Code PUBREC可变报头第3字节是原因码(Reason Code)。如果剩余长度为2,则表示使用原因码0x00(成功)。 表 3-5 – PUBACK原因码 PUBREC Reason Codes 值16进制原因码名称说明00x00成功消息被接收。QoS为2的消息已发布。160x10无匹配的订阅者消息被接收,但没有订阅者。只有服务端会发送此原因码。如果服务端得知没有匹配的订阅者,服务端可以使用此原因码代替0x00(成功)。1280x80未指明的错误接收端不接受此消息,且不愿意透露错误原因或没有适用的原因码。1310x83实现特定错误PUBLISH报文有效,但不被接收端所接受。1350x87未授权PUBLISH报文未授权。1440x90主题名无效主题名格式正确,但未被客户端或服务端所接受。1450x91报文标识符被占用报文标识符正被占用。可能表明客户端和服务端之间的会话状态不匹配。1510x97超出配额已超出实现限制或管理限制。1530x99载荷格式无效载荷格式与载荷格式指示符不匹配。 服务端或客户端发送PUBREC报文时必须设置其中一种原因码 [MQTT-3.5.2-1]。当原因码为0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBREC剩余长度为2。 3.5.2.2 PUBREC 属性 PUBREC Properties 3.5.2.2.1 属性长度 Property Length PUBREC可变报头的属性长度被编码为变长字节整数。如果剩余长度小于4,则表示没有属性长度字段。 3.5.2.2.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的PUBREC报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此属性 [MQTT-3.5.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.5.2.2.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是UTF-8字符串对。此属性可用于提供包括诊断信息在内的附加信息。如果加上用户属性之后的PUBREC报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此属性 [MQTT-3.5.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.5.3 有效载荷 PUBREC Payload PUBREC报文没有有效载荷。 3.5.4 动作 PUBREC Actions 描述见 4.3.3节。 项目主页 MQTT v5.0协议草案中文版 3.6 PUBREL – 发布释放(QoS 2,第二步) PUBREL报文是对PUBREC报文的响应。它是QoS 2等级协议交换的第三个报文。 3.6.1 PUBREL 固定报头 PUBREL Fixed Header 图 3-14 – PUBREL报文固定报头 PUBREL packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (6)保留位01100010byte 2剩余长度 PUBREL固定报头的第3,2,1,0位是保留位,必须被设置为0,0,1,0。服务端必须将其它的任何值都当做是不合法的并关闭网络连接 [MQTT-3.6.1-1]。 剩余长度字段表示可变报头的长度,被编码为变长字节整数。 3.6.2 PUBREL 可变报头 PUBREL Variable Header PUBREL报文的可变报头按顺序包含以下字段:所确认的PUBREC报文标识符,PUBREL原因码,属性(Properties)。属性的编码规则如2.2.2节所述。 图 3-15 – PUBREL报文可变报头 PUBREL packet Variable Header Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBREL原因码byte 4属性长度 3.6.2.1 PUBREL 原因码 PUBREL Reason Code 可变报头第3字节是PUBREL原因码。如果剩余长度为2,则表示使用原因码0x00 (成功)。 表 3-6 – PUBREL原因码 PUBREL Reason Codes 值16进制原因码名称说明00x00成功消息已释放。1460x92报文标识符未发现未知的报文标识符。会话恢复阶段这并非错误,但其他时间这表明服务端和客户端的会话状态不匹配。 客户端或服务端发送PUBREL报文时必须设置其中一种PUBREL原因码 [MQTT-3.6.2-1]。当原因码为0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBREL剩余长度为2。 3.6.2.2 PUBREL 属性 PUBREL Properties 3.6.2.2.1 属性长度 Property Length PUBREL报文可变报头中的属性长度被编码为变长字节整数。如果剩余长度小于4,则表示没有属性长度字段。 3.6.2.2.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的PUBREL报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此原因字符串 [MQTT-3.6.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.6.2.2.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于提供包括诊断信息或关于PUBREL的信息。如果加上用户属性之后的PUBREL报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此属性 [MQTT-3.6.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.6.3 PUBREL 有效载荷 PUBREL Payload PUBREL报文没有有效载荷。 3.6.4 PUBREL 行为 PUBREL Actions 描述见4.3.3节。 项目主页 MQTT v5.0协议草案中文版 3.7 PUBCOMP – 发布完成(QoS 2,第三步) PUBCOMP报文是对PUBREL报文的响应。它是QoS 2等级协议交换的第四个也是最后一个报文。 3.7.1 PUBCOMP 固定报头 PUBCOMP Fixed Header 图 3-16 – PUBCOMP报文固定报头 PUBCOMP packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (7)保留位01110000byte 2剩余长度 (2) 剩余长度字段表示可变报头的长度,编码为变长字节整数。 3.7.2 PUBCOMP 可变报头 PUBCOMP Variable Header PUBCOMP报文可变报头按顺序包含以下字段:所确认的PUBREL报文标识符,PUBCOMP原因码,属性。属性(Properties)编码规则如2.2.2节所述。 图 3-17 – PUBCOMP报文可变报头 PUBCOMP packet Variable Header Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBCOMP原因码byte 4属性长度 3.7.2.1 PUBCOMP 原因码 PUBCOMP Reason Codes 可变报头第3字节是PUBCOMP原因码。如果剩余长度为2,则表示使用原因码0x00(成功)。 表 3-7 – PUBCOMP 原因码 PUBCOMP Reason Codes 值16进制原因码名称说明00x00成功报文标识符已释放。QoS 2消息已完成发布。1460x92报文标识符未发现未知的报文标识符。会话恢复阶段这并非错误,但其他时间这表明服务端和客户端的会话状态不匹配。 服务端或客户端发送PUBCOMP报文时必须设置一种PUBCOMP原因码 [MQTT-3.7.2-1]。当原因码为0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBCOMP剩余长度为2。 3.7.2.2 PUBCOMP 属性 PUBCOMP Properties 3.7.2.2.1 属性长度 Property Length PUBCOMP报文可变报头中的属性长度被编码为变长字节整数。如果剩余长度小于4,则表示没有属性长度字段。 3.7.2.2.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的PUBCOMP报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此原因字符串 [MQTT-3.7.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.7.2.2.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是UTF-8字符串对。此属性可用于提供诊断信息或关于其他信息。如果加上用户属性之后的PUBCOMP报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此属性 [MQTT-3.7.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.7.3 PUBCOMP 载荷 PUBCOMP Payload PUBCOMP报文没有有效载荷。 3.7.4 PUBCOMP 行为 PUBCOMP Actions 描述见4.3.3节。 项目主页 MQTT v5.0协议草案中文版 3.8 SUBSCRIBE - 订阅请求 客户端向服务端发送SUBSCRIBE报文用于创建一个或多个订阅。每个订阅(Subscription)注册客户端所感兴趣的一个或多个主题。服务端向客户端发送PUBLISH报文以转发被发布到符合这些订阅主题的应用消息。SUBSCRIBE报文同样(为每个订阅)指定了服务端可以向其发送的应用消息最大QoS等级。 3.8.1 固定报头 SUBSCRIBE Fixed Header 图 3-20 – SUBSCRIBE报文固定报头 SUBSCRIBE packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (8)保留位10000010byte 2剩余长度 SUBSCRIBE报文固定报头第3,2,1,0比特位是保留位,必须被设置为0,0,1,0。服务端必须将其他的任何值都当做是不合法的并关闭网络连接 [MQTT-3.8.1-1]。 剩余长度字段表示可变报头的长度加上有效载荷的长度,被编码为变长字节整数。 3.8.2 可变报头 SUBSCRIBE Variable Header SUBSCRIBE报文可变报头按顺序包含以下字段:报文标识符(Packet Identifier),属性(Properties)。2.2.1节提供了更多关于报文标识符的信息。属性的编码规则如2.2.2节所述。 非规范示例 图3-19展示了一个包含报文标识符为10,且没有属性的SUBSCRIBE可变报头。 图 3-19 – SUBSCRIBE 可变报头示例 SUBSCRIBE Variable Header example 说明76543210报文标识符byte 1报文标识符MSB (0)00000000byte 2报文标识符LSB (10)00001010byte 3属性长度 (0)00000000 3.8.2.1 SUBSCRIBE 属性 SUBSCRIBE Properties 3.8.2.1.1 属性长度 Property Length SUBSCRIBE报文可变报头中的属性长度被编码为变长字节整数。 3.8.2.1.2 订阅标识符 Subscription Identifier 11 (0x0B) ,订阅标识符(Subscription Identifier)标识符。跟随其后的是一个变长字节整数表示订阅标识符。订阅标识符取值范围从1到268,435,455。订阅标识符的值为0或包含多个订阅标识符将造成协议错误(Protocol Error)。 订阅标识符与SUBSCRIBE报文所创建或修改的订阅(Subscription)相关联。如果包含订阅标识符,它将与订阅一起被存储。如果未指定此属性,则订阅被存储时将不包含订阅标识符。 更多关于订阅标识符的处理信息,参考3.8.3.1节。 3.8.2.1.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。 用户属性允许出现多次,以表示多个名字/值对。同样的名字允许出现多次。 非规范评注 SUBSCRIBE报文的用户属性可以被客户端用来向服务端发送订阅相关的属性。本规范不定义这些属性的意义。 3.8.3 SUBSCRIBE 载荷 SUBSCRIBE Payload SUBSCRIBE报文的载荷包含一列主题过滤器,指明客户端希望订阅的主题。主题过滤器必须为UTF-8 编码的字符串 [MQTT-3.8.3-1]。每个主题过滤器之后跟着一个订阅选项(Subscription Options)字节。 载荷必须包含至少一个主题过滤器/订阅选项对 [MQTT-3.8.3-2]。不包含载荷的SUBSCRIBE报文将造成协议错误(Protocol Error)。错误处理信息,参考4.13节。 3.8.3.1 订阅选项 Subscription Options 订阅选项的第0和1比特代表最大服务质量字段。此字段给出服务端可以向此客户端发送的应用消息的最大QoS等级。最大服务质量字段为3将造成协议错误(Protocol Error)。 订阅选项的第2比特表示非本地(No Local)选项。值为1,表示应用消息不能被转发给发布此消息的客户标识符 [MQTT-3.8.3-3]。共享订阅时把非本地选项设为1将造成协议错误(Protocol Error) [MQTT-3.8.3-4]。 订阅选项的第3比特表示发布保留(Retain As Published)选项。值为1,表示向此订阅转发应用消息时保持消息被发布时设置的保留(RETAIN)标志。值为0,表示向此订阅转发应用消息时把保留标志设置为0。当订阅建立之后,发送保留消息时保留标志设置为1。 订阅选项的第4和5比特表示保留操作(Retain Handling)选项。此选项指示当订阅建立时,是否发送保留消息。此选项不影响之后的任何保留消息的发送。如果没有匹配主题过滤器的保留消息,则此选项所有值的行为都一样。值可以设置为:0 = 订阅建立时发送保留消息1 = 订阅建立时,若该订阅当前不存在则发送保留消息2 = 订阅建立时不要发送保留消息保留操作的值设置为3将造成协议错误(Protocol Error)。 订阅选项的第6和7比特为将来所保留。服务端必须把此保留位非0的SUBSCRIBE报文当做无效报文 [MQTT-3.8.3-5]。 非规范评注 非本地(No Local)和发布保留(Retain As Published)订阅选项在客户端把消息发送给其他服务端的情况下,可以被用来实现桥接。 非规范评注 已存在订阅的情况下不发送保留消息是很有用的,比如重连完成时客户端不确定订阅是否在之前的会话连接中被创建。 非规范评注 不发送保存的保留消息给新创建的订阅是很有用的,比如客户端希望接收变更通知且不需要知道最初的状态。 非规范评注 对于某个指示其不支持保留消息的服务端,发布保留和保留处理选项的所有有效值都将得到同样的结果:订阅时不发送任何保留消息,且所有消息的保留标志都会被设置为0。 图 3-20 – SUBSCRIBE报文载荷格式 SUBSCRIBE packet Payload format 说明76543210主题过滤器byte 1长度 MSBbyte 2长度 LSBbyte 3..N主题过滤器(Topic Filter)订阅选项保留位保留处理RAPNLQoSbyte N+100XXXXXX RAP指发布保留(Retain as Published)。NL指非本地(No Local)。 图 3-21 – 载荷字节格式非规范示例 Payload byte format non-normative example 说明76543210主题过滤器byte 1长度MSB (0)00000000byte 2长度LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010订阅选项byte 6订阅选项 (1)00000001主题过滤器byte 7长度MSB (0)00000000byte 8长度LSB (3)00000011byte 9‘c’ (0x63)01100011byte 10‘/’ (0x2F)00101111byte 11‘d’ (0x64)01100100订阅选项byte 12订阅选项 (2)00000010 3.8.4 SUBSCRIBE 行为 SUBSCRIBE Actions 当服务端收到来自客户端的SUBSCRIBE报文时,必须使用SUBACK报文作为相应 [MQTT-3.8.4-1]。SUBACK报文必须和待确认的SUBSCRIBE报文有相同的报文标识符 [MQTT-3.8.4-2]。 允许服务端在发送SUBACK报文之前就开始发送与订阅相匹配的PUBLISH报文。 如果服务端收到的SUBSCRIBE报文中的一个主题过滤器与当前会话的一个非共享订阅(Non-shared Subscription)相同,那么必须使用新的订阅替换现存的订阅 [MQTT-3.8.4-3]。新订阅的主题过滤器与之前的订阅相同,但其订阅选项可能不同。如果保留处理选项为0,任何匹配该主题过滤器的保留消息必须被重发,但替换订阅不能造成应用消息的丢失 [MQTT-3.8.4-4]。 如果服务端收到的非共享主题过滤器(Non-shared Topic Filter)不同于当前会话的任何主题过滤器,一个新的非共享订阅将被创建。如果保留处理选项不为2,所有相匹配的保留消息将发送给客户端。 如果服务端收到的主题过滤器与服务端已存在的某个共享订阅(Shared Subscription)主题过滤器相同,则将此会话添加到该共享订阅中。不发送任何保留消息。 如果服务端收到的共享订阅主题过滤器(Shared Subscription Topic Filter)与任何已存在的共享订阅主题过滤器都不同,一个新的共享订阅将被创建。将此会话作为订阅者添加到该共享订阅。不发送任何保留消息。 更多关于共享订阅的细节,参考4.8节。 如果服务端收到的SUBSCRIBE报文包含多个主题过滤器,服务端必须当做收到一系列多个SUBSCRIBE报文来处理--除了将它们的响应组合为单个SUBACK响应 [MQTT-3.8.4-5]。 服务端发送给客户端的SUBACK报文必须为每一个主题过滤器/订阅选项对包含一个原因码 [MQTT-3.8.4-6]。 此原因码必须说明为该订阅授予的最大QoS等级,或指示订阅失败 [MQTT-3.8.4-7]。服务端可能授予了低于订阅者所请求的最大QoS等级。响应该订阅的应用消息QoS等级必须为该消息发布时的QoS等级和服务端授予的最大QoS等级二者最小值 [MQTT-3.8.4-8]。在原始消息发布的QoS等级为1,且授予的最大QoS等级为0的情况下,服务端允许发送重复的消息副本给订阅者(?)。 非规范评注 如果订阅客户端的某个主题过滤器已被授予的最大QoS等级为1,那么匹配此过滤器的QoS等级为0的应用消息按照QoS等级为0分发给此客户端。这意味着客户端最多只能收到该消息的一个副本。另一方面,发布到相同主题的QoS等级为2的消息,其QoS等级被服务端降级为1以便分发给该客户端。因此该客户端可能收到此消息的多个副本。 非规范评注 如果订阅客户端被授予的最大QoS等级为0,那么按照QoS等级为2发布的应用消息在繁忙时可能会丢失,但服务端不应该发送重复的消息副本。发布到相同主题的QoS等级为1的消息,分发给该客户端时可能会丢失或重复。 非规范评注 使用QoS等级2订阅某个主题过滤器,等于是说:我想要按照消息被发布时的QoS等级接收匹配此过滤器的消息 。这意味着发布者负责决定消息可以被发布的最大QoS等级,但订阅端可以要求服务端降低该消息的QoS到更适合它的等级。 订阅标识符是服务端的会话状态的一部分,并将在收到PUBLISH报文时返回给客户端。当服务端收到客户端的UNSUBSCRIBE报文时,服务端将此会话标识符从服务端的会话状态中移除:当服务端收到客户端的UNSUBSCRIBE报文,当服务端收到客户端对同样主题过滤器的SUBSCRIBE报文但订阅标识符不同或没有订阅标识符,或者当服务端在CONNACK报文中将会话存在标志设置为0。 订阅标识符不构成客户端的会话状态的一部分。在一个有用的实现中,客户端将订阅标识符与其他客户端状态相关联,此客户端状态将被移除:当客户端取消订阅,当客户端以不同的订阅标识符或没有订阅标识符订阅同样的主题过滤器,或者当客户端收到的CONNACK报文中会话存在标志被设置为0。 服务端在重传的PUBLISH报文中无需使用同一组订阅标识符。客户端可以通过发送包含与当前会话已存在的主题过滤器的SUBSCRIBE报文进行重新订阅。如果客户端在PUBLISH报文初传之后重新订阅并使用了不同的订阅标识符,允许服务端在任何重传中使用初传所包含的订阅标识符,或者在重传中使用此新的订阅标识符。不允许服务端在发送了包含新的订阅标识符的PUBLISH报文之后再次使用旧的订阅标识符。 非规范评注 使用场景,用以阐述订阅标识符: 客户端实现指示某条发布消息匹配多个订阅的编程接口,客户端实现每次订阅时生成新的订阅标识符。如果返回的发布消息包含多个订阅标识符,则该发布消息匹配多个订阅。 客户端实现允许订阅者将消息定向到其相关联的订阅的回调,客户端实现生成映射到唯一回调的订阅标识符。收到某条发布消息时,使用订阅标识符决定触发哪一个回调。 客户端实现在发布消息时返回程序用于订阅的主题字符串,为此客户端生成一个唯一标识了该主题过滤器的标识符。收到某条发布消息时,客户端实现使用此标识符查找原始主题过滤器,并将主题过滤器返回给其应用程序。 网关(Gateway)将从服务端收到的发布消息转发给向该网关做了订阅的客户端,网关实现维护其收到的每个唯一的订阅过滤器到其收到的一组客户标识符--订阅标识符对的映射,网关对它转发给服务端的每个主题过滤器生成一个唯一的标识符。收到某条发布消息时,网关使用从服务端收到的订阅标识符查找对应的客户标识符--订阅标识符对,并把它们加入发送给客户端的PUBLISH报文中。如果上游服务端因为消息匹配了多个订阅而发送了多个PUBLISH报文,则此行为将反映到客户端。 项目主页 MQTT v5.0协议草案中文版 3.9 SUBACK – 订阅确认 服务端发送SUBACK报文给客户端,用于确认它已收到并且正在处理SUBSCRIBE报文。 SUBACK报文包含一个原因码列表,用于指定授予的最大QoS等级或SUBSCRIBE报文所请求的每个订阅发生的错误。 3.9.1 SUBACK 固定报头 SUBACK Fixed Header 图 3-24 – SUBACK报文固定报头 SUBACK Packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (9)保留位10010000byte 2剩余长度 剩余长度字段可变报头长度加上有效载荷长度,编码为变长字节整数。 3.9.2 SUBACK 可变报头 SUBACK Variable Header SUBACK报文可变报头按顺序包含以下字段:所确认的SUBSCRIBE报文标识符,属性(Properties)。 图例 3.25 – SUBACK报文可变报头 3.9.2.1 SUBACK 属性 SUBACK Properties 3.9.2.1.1 属性长度 Property Length SUBACK可变报头中的属性长度被编码为变长字节整数。 3.9.2.1.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。如果加上原因字符串之后的SUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串 [MQTT-3.9.2-1]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.9.2.1.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的SUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性 [MQTT-3.9.2-2]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 图 3-23 - SUBACK报文可变报头 SUBACK packet Variable Header Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSB 3.9.3 SUBACK 载荷 SUBACK Payload 有效载荷包含一个原因码列表。每个原因码对应SUBSCRIBE报文中的一个被确认的主题过滤器。SUBACK报文中的原因码顺序必须与SUBSCRIBE报文中的主题过滤器顺序相匹配 [MQTT-3.9.3-1]。 表 3-8 - 订阅原因码 Subscribe Reason Codes 值16进制原因码名称说明00x00授予QoS等级0订阅被接受且最大QoS等级为0。可能低于所请求的QoS等级。10x01授予QoS等级1订阅被接受且最大QoS等级为1。可能低于所请求的QoS等级。20x02授予QoS等级2订阅被接受且最大QoS等级为2。可能低于所请求的QoS等级。1280x80未指明错误订阅未被接受,且服务端不愿意透露原因或没有适用的原因码。1310x83实现特定错误SUBSCRIBE有效但不被服务端所接受。1350x87未授权客户端未被授权做此订阅。1430x8F主题过滤器无效主题过滤器格式正确,但不被允许。1450x91报文标识符已被占用指定的报文标识符正在被使用中。1510x97超出配额已超出实现限制或管理限制。1580x9E共享订阅不支持服务端不支持此客户端进行共享订阅。1610xA1订阅标识符不支持服务端不支持订阅标识符;订阅标识符不被接受。1620xA2通配符订阅不支持服务端不支持通配符订阅;订阅未被接受。 服务端发送SUBACK报文时必须对收到的每一个主题过滤器设置一种原因码 [MQTT-3.9.3-2]。 非规范评注 对于SUBSCRIBE报文中的每个主题过滤器,总有一个对应的原因码。如果原因码不是针对某个特定的主题过滤器(比如0x91(报文标识符已占用)),则对每个主题过滤器都使用此原因码。 项目主页 MQTT v5.0协议草案中文版 3.10 UNSUBSCRIBE –取消订阅请求 客户端发送UNSUBSCRIBE报文给服务端,用于取消订阅主题。 3.10.1 UNSUBSCRIBE 固定报头 UNSUBSCRIBE Fixed Header 图 3-28 – UNSUBSCRIBE报文固定报头 Bit76543210byte 1MQTT控制报文类型 (10)保留位10100010byte 2剩余长度 UNSUBSCRIBE固定报头的第3,2,1,0位是保留位且必须分别设置为0,0,1,0。服务端必须认为任何其它的值都是不合法的并关闭网络连接 [MQTT-3.10.1-1]。 剩余长度字段等于可变报头长度(2字节)加上有效载荷长度,编码为变长字节整数。 3.10.2 UNSUBSCRIBE 可变报头 UNSUBSCRIBE Variable Header UNSUBSCRIBE报文可变报头按顺序包含以下字段:报文标识符和属性(Properties)。2.2.1节提供了有关报文标识符的更多信息。属性的编码规则,如2.2.2节所述。 3.10.2.1 UNSUBSCRIBE 属性 UNSUBSCRIBE Properties 3.10.2.1.1 属性长度 Property Length SUBSCRIBE可变报头中属性的长度被编码为变长字节整数。 3.10.2.1.2 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是一个UTF-8字符串对。 用户属性允许出现多次,以表示多个名字/值对。相同的名字可以出现多次。 非规范评注 UNSUBSCRIBE报文中的用户属性可以被客户端用来向服务端发送订阅相关的属性。本规范不定义这些属性的意义。 3.10.3 3.10.3 UNSUBSCRIBE 载荷 UNSUBSCRIBE Payload UNSUBSCRIBE报文有效载荷包含一列客户端希望取消订阅的主题过滤器。UNSUBSCRIBE报文中的主题过滤器必须为1.5.4节所述的UTF-8编码字符串 [MQTT-3.10.3-1] ,且连续填充。 UNSUBSCRIBE报文有效载荷必须包含至少一个主题过滤器 [MQTT-3.10.3-2]。不包含有效载荷的UNSUBSCRIBE报文将造成协议错误(Protocol Error)。错误处理信息,参考4.13节。 非规范示例 图 3-30 展示了UNSUBSCRIBE报文的载荷示例,包括两个主题过滤器 “a/b”和“c/d”。 图 3-30 - 载荷字节格式非规范示例 Payload byte format non-normative example 说明76543210主题过滤器byte 1长度MSB (0)00000000byte 2长度LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010主题过滤器byte 6长度MSB (0)00000000byte 7长度LSB (3)00000011byte 8‘c’ (0x63)01100011byte 9‘/’ (0x2F)00101111byte 10‘d’ (0x64)01100100 3.10.4 UNSUBSCRIBE 行为 UNSUBSCRIBE Actions 服务端必须对客户端的UNSUBSCRIBE报文中提供的主题过滤器(不管是否包含通配符)逐个字符与当前持有的主题过滤器集进行比较。如果任何过滤器完全匹配,则必须删除其拥有的订阅 [MQTT-3.10.4-1],否则不会进行额外的处理。 当服务端收到UNSUBSCRIBE报文: 它必须停止添加为了交付给客户端的与主题过滤器相匹配的任何新消息 [MQTT-3.10.4-2]。 它必须完成任何已经开始发送给客户端的、与主题过滤器相匹配的、QoS等级为1或2的消息 [MQTT-3.10.4-3]。 它可以继续交付任何为交付给客户端而缓存的消息。 服务端必须发送UNSUBACK报文以响应客户端的UNSUBSCRIBE请求 [MQTT-3.10.4-4]。UNSUBACK报文必须包含和UNSUBSCRIBE报文相同的报文标识符。即使没有删除任何主题订阅,服务端也必须发送一个UNSUBACK响应 [MQTT-3.10.4-5]。 如果服务端收到的UNSUBSCRIBE报文包含多个主题过滤器,服务端必须当做收到一系列多个UNSUBSCRIBE报文来处理--除了将它们的响应组合为单个SUBACK响应 [MQTT-3.10.4-6]。 如果某个主题过滤器代表一个共享订阅,此会话将被从该共享订阅中删除。如果此会话是该共享订阅所关联的唯一会话,该共享订阅被删除。共享订阅的处理,参考4.8.2节。 项目主页 MQTT v5.0协议草案中文版 3.11 UNSUBACK – 取消订阅确认 服务端发送UNSUBACK报文给客户端用于确认收到UNSUBSCRIBE报文。 3.11.1 UNSUBACK 固定报头 UNSUBACK Fixed Header 图 3-31 – UNSUBACK 报文固定报头 UNSUBACK packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (11)保留位10110000byte 2剩余长度 剩余长度字段表示可变报头的长度,对UNSUBACK报文这个值等于2。 3.11.2 UNSUBACK 可变报头 UNSUBACK Variable Header UNSUBACK报文可变报头按顺序包含以下字段:所确认的UNSUBSCRIBE报文标识符和属性( Properties)。属性的编码规则如2.2.2节所述。 图 3-32 – UNSUBACK 报文可变报头 UNSUBACK packet Variable Header Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSB 3.11.2.1 UNSUBACK 属性 UNSUBACK Properties 3.11.2.1.1 属性长度 Property Length UNSUBACK报文可变报头中的属性的长度被编码为变长字节整数。 3.11.2.1.2 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断而设计的可读字符串,不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。如果加上原因字符串之后的UNSUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串 [MQTT-3.11.2-1]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.11.2.1.3 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的UNSUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性 [MQTT-3.11.2-2]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.11.3 UNSUBACK 载荷 UNSUBACK Payload 有效载荷包含一个原因码列表。每个原因码对应UNSUBSCRIBE报文中的一个被确认的主题过滤器。UNSUBACK报文中的原因码顺序必须与UNSUBSCRIBE报文中的主题过滤器顺序相匹配 [MQTT-3.11.3-1]。 单字节无符号取消订阅原因码的值如下所示。服务端发送UNSUBACK报文时对于每个收到的主题过滤器,必须使用一个取消订阅原因码 [MQTT-3.11.3-2]。 表 3-9 – UNSUBACK 报文可变报头 UNSUBACK packet Variable Header 值16进制原因码名称说明00x00成功订阅已被删除。170x11订阅未发现没有该客户端匹配的主题过滤器被使用。1280x80未指定错误取消订阅不能被完成且服务端不愿意透露原因或没有其他适用的原因码。1310x83实现指定错误UNSUBSCRIBE报文有效,但服务端不接受。1350x87未授权客户端未被授权进行取消订阅。1430x8F主题过滤器无效主题过滤器格式正确,但不被允许。1450x91报文标识符已占用指定的报文标识符正在被使用中。 非规范评注 对于UNSUBSCRIBE报文中的每个主题过滤器,总有一个对应的原因码。如果原因码不是针对某个特定的主题过滤器(比如0x91(报文标识符已占用)),则对每个主题过滤器都使用此原因码。 项目主页 MQTT v5.0协议草案中文版 3.12 PINGREQ – PING 请求 客户端发送PINGREQ报文给服务端,可被用于: 在没有任何其他MQTT控制报文从客户端发给服务端时,告知服务端客户端还活着。 请求服务端发送响应以确认服务端还活着。 使用网络已确认网络连接没有断开。 此报文被用在保持连接(Keep Alive)的处理中。详细信息,参考3.1.2.10节。 3.12.1 PINGREQ 固定报头 PINGREQ Fixed Header 图 3-33 – PINGREQ 报文固定报头 PINGREQ packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (12)保留位11000000byte 2剩余长度 (0)00000000 3.12.2 PINGREQ 可变报头 PINGREQ Variable Header PINGREQ报文没有可变报头。 3.12.3 PINGREQ 有效载荷 PINGREQ Payload PINGREQ报文没有有效载荷。 3.12.4 PINGREQ 行为 PINGREQ Actions 服务端必须发送PINGRESP报文响应客户端的PINGREQ报文 [MQTT-3.12.4-1]。 项目主页 MQTT v5.0协议草案中文版 3.13 PINGRESP – 心跳响应 服务端发送PINGRESP报文响应客户端的PINGREQ报文。表示服务端还活着。 保持连接(Keep Alive)处理中用到这个报文,详情请查看 3.1.2.10节。 3.13.1 固定报头 PINGRESP Fixed Header 图例 3-34 – PINGRESP 报文固定报头 PINGRESP packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (13)保留位11010000byte 2剩余长度00000000 3.13.2 PINGRESP 可变报头 PINGRESP Variable Header PINGRESP报文没有可变报头。 3.13.3 PINGRESP 载荷 PINGRESP Payload PINGRESP报文没有有效载荷。 3.13.4 PINGRESP 行为 PINGRESP Actions 客户端收到此报文时不做任何处理。 项目主页 MQTT v5.0协议草案中文版 3.14 DISCONNECT – 断开通知 DISCONNECT报文是客户端发给服务端的最后一个MQTT控制报文。表示客户端为什么断开网络连接的原因。客户端和服务端在关闭网络连接之前可以发送一个DISCONNECT报文。如果在客户端没有首先发送包含原因码为0x00(正常断开)DISCONNECT报文并且连接包含遗嘱消息的情况下,遗嘱消息会被发布。更多细节,参考3.1.2.5节。 服务端不能发送DISCONNECT报文,直到它发送了包含原因码小于0x80的CONNACK报文之后 [MQTT-3.14.0-1]。 3.14.1 DISCONNECT 固定报头 DISCONNECT Fixed Header 图例 3-35 – DISCONNECT 报文固定报头 DISCONNECT packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (14)保留位11100000byte 2剩余长度 服务端或客户端必须验证所有的保留位都被设置为0,如果他们不为0,发送包含原因码为0x81(无效报文)的DISCONNECT报文,如4.13节所述 [MQTT-3.14.1-1]。 剩余长度字段等于可变报头的长度,编码为变长字节整数。 3.14.2 DISCONNECT 可变报头 DISCONNECT Variable Header DISCONNECT报文的可变报头按顺序包含以下字段:断开原因码,属性(Properties)。属性的编码规则如2.2.2节所述。 3.14.2.1 DISCONNECT 断开原因码 Disconnect Reason Code 可变报头的第1个字节是断开原因码。如果剩余长度小于1,则表示使用原因码0x00(正常断开)。 单字节无符号断开原因码字段如下所示。 表 3-10 – 断开原因值 Disconnect Reason Code 值16进制原因码名称发送端说明00x00正常断开客户端或服务端正常关闭连接。不发送遗嘱。40x04包含遗嘱消息的断开客户端客户端希望断开但也需要服务端发布它的遗嘱消息。1280x80未指定错误客户端或服务端连接被关闭,但发送端不愿意透露原因,或者没有其他适用的原因码。1290x81无效的报文客户端或服务端收到的报文不符合本规范。1300x82协议错误客户端或服务端收到意外的或无序的报文。1310x83实现指定错误客户端或服务端收到的报文有效,但根据实现无法进行处理。1350x87未授权服务端请求没有被授权1370x89服务端正忙服务端服务端正忙且不能继续处理此客户端的请求。1390x8B服务正关闭服务端服务正在关闭。1410x8D保持连接超时服务端连接因为在超过1.5倍的保持连接时间内没有收到任何报文而关闭。1420x8E会话被接管服务端另一个使用了相同的客户标识符的连接已建立,导致此连接关闭。1430x8F主题过滤器无效服务端主题过滤器格式正确,但不被服务端所接受。1440x90主题名无效客户端或服务端主题名格式正确,但不被客户端或服务端所接受。1470x93超出接收最大值客户端或服务端客户端或服务端收到了数量超过接收最大值的未发送PUBACK或PUBCOMP的发布消息。1480x94主题别名无效客户端或服务端客户端或服务端收到的PUBLISH报文包含的主题别名大于其在CONNECT或CONNACK中发送的主题别名最大值。1490x95报文过大客户端或服务端报文长度大于此客户端或服务端的最大报文长度。1500x96消息速率过高客户端或服务端收到的数据速率太高。1510x97超出配额客户端或服务端已超出实现限制或管理限制。1520x98管理操作客户端或服务端连接因为管理操作被关闭。1530x99载荷格式无效客户端或服务端载荷格式与指定的载荷格式指示符不匹配。1540x9A不支持保留服务端服务端不支持保留消息。1550x9B不支持的QoS等级服务端客户端指定的QoS等级大于CONNACK报文中指定的最大QoS等级。1560x9C(临时)使用其他服务端服务端客户端应该临时使用其他服务端。1570x9D服务端已(永久)移动服务端服务端已移动且客户端应该永久使用其他服务端。1580x9E不支持共享订阅服务端服务端不支持共享订阅。1590x9F超出连接速率限制服务端此连接因为连接速率过高而被关闭。1600xA0最大连接时间服务端超出为此连接授予的最大连接时间。1610xA1不支持订阅标识符服务端服务端不支持订阅标识符;订阅未被接受。1620xA2不支持通配符订阅服务端服务端不支持通配符订阅;订阅未被接受。 客户端或服务端发送DISCONNECT报文时必须使用一种DISCONNECT原因码 [MQTT-3.14.2-1]。如果原因码为0x00(正常断开)且没有属性,原因码和属性长度可以被省略。这种情况下DISCONNECT报文剩余长度为0。 非规范评注 DISCONNECT报文用于指示断开的原因,例如没有确认报文(比如QoS等级0的发布消息)或当客户端或服务端不能继续处理连接。 非规范评注 客户端可以使用这些信息来决定是否重新连接,以及在重新尝试之前应该等待多长时间。 3.14.2.2 DISCONNECT 属性 DISCONNECT Properties 3.14.2.2.1 属性长度 Property Length DISCONNECT报文可变报头中的属性(Properties)的长度被编码为变长字节整数。如果剩余长度小于2,属性长度使用0。 3.14.2.2.2 会话过期间隔 Session Expiry Interval 17 (0x11) ,会话过期间隔(Session Expiry Interval)标识符。跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话过期间隔将造成协议错误(Protocol Error)。 如果没有设置会话过期间隔,则使用CONNECT报文中的会话过期间隔。 会话过期间隔不能由服务端的DISCONNECT报文发送 [MQTT-3.14.2-2]。 如果CONNECT报文中的会话过期间隔为0,则客户端在DISCONNECT报文中设置非0会话过期间隔将造成协议错误(Protocol Error)。如果服务端收到这种非0会话过期间隔,则不会将其视为有效的DISCONNECT报文。服务端使用包含原因码为0x82(协议错误)的DISCONNECT报文,如4.13节所述。 3.14.2.2.3 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码字符串表示断开原因。此原因字符串是为诊断而设计的可读字符串,不应该被接收端所解析。 如果此属性使得DISCONNECT报文的长度超出了接收端指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.14.2-3]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.14.2.2.4 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的DISCONNECT报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.14.2-4]。用户属性允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.14.2.2.5 服务端参考 Server Reference 28 (0x1C) ,服务端参考(Server Reference)标识符。跟随其后的是一个UTF-8编码字符串,客户端可以使用它来识别其他要使用的服务端。包含多个服务端参考将造成协议错误(Protocol Error)。 服务端发送包含一个服务端参考和原因码0x9C((临时)使用其他服务端)或0x9D(服务端已(永久)移动)的DISCONNECT报文,如4.13节所述。 关于如何使用服务端参考,参考4.11节服务端重定向。 图 3-24 - DISCONNECT 报文可变报头非规范示例 DISCONNECT packet Variable Header non-normative example 说明76543210断开原因码byte 100000000属性byte 2长度 (5)00000111byte 3会话过期间隔标识符 (17)00010001byte 4会话过期间隔标识符 (17)00000000byte 500000000byte 600000000byte 700000000 3.14.3 DISCONNECT 有效载荷 DISCONNECT Payload DISCONNECT报文没有有效载荷。 3.14.4 DISCONNECT 行为 DISCONNECT Actions 发送端发送完DISCONNECT报文之后: 不能再在此网络连接上发送任何MQTT控制报文 [MQTT-3.14.4-1]。 必须关闭网络连接 [MQTT-3.14.4-2]。 接收到包含原因码为0x00(成功)的DISCONNECT时,服务端: 必须丢弃任何与当前连接相关的遗嘱消息,而不发布它 [MQTT-3.14.4-3],如3.1.2.5节所述。 接收到DISCONNECT报文时,接收端: 应该关闭网络连接 项目主页 MQTT v5.0协议草案中文版 3.15 AUTH – 认证交换 AUTH报文被从客户端发送给服务端,或从服务端发送给客户端,作为扩展认证交换的一部分,比如质询/响应认证。如果CONNECT报文不包含相同的认证方法,则客户端或服务端发送AUTH报文将造成协议错误(Protocol Error)。 3.15.1 AUTH 固定报头 AUTH Fixed Header 图例 3-35 – AUTH 报文固定报头 AUTH packet Fixed Header Bit76543210byte 1MQTT控制报文类型 (15)保留位11110000byte 2剩余长度 AUTH报文固定报头第3,2,1,0位是保留位,必须全设置为0。客户端或服务端必须把其他值当做无效值并关闭网络连接 [MQTT-3.15.1-1]。 剩余长度字段等于可变报头的长度,编码为变长字节整数。 3.15.2 AUTH 可变报头 AUTH Variable Header AUTH报文可变报头按顺序包含以下字段:认证原因码(Authentication Reason Code),属性(Properties)。属性的编码规则,如2.2.2节所述。 3.15.2.1 认证原因码 Authenticate Reason Code 可变报头第0字节是认证原因码(Authenticate Reason Code)。单字节无符号认证原因码字段的值如下所示。AUTH报文的发送端必须使用一种认证原因码 [MQTT-3.15.2-1]。 表 3-11 – 认证原因码 Authenticate Reason Codes 值16进制原因码名称发送端说明00x00成功服务端认证成功。240x18继续认证客户端或服务端继续下一步认证。250x19重新认证客户端开始重新认证。 如果原因码为0x00(成功)并且没有属性字段,则可以省略原因码和属性长度。这种情况下,AUTH报文剩余长度为0。 3.15.2.2 AUTH 属性 AUTH Properties 3.15.2.2.1 属性长度 Property Length AUTH报文可变报头中的属性的长度被编码为变长字节整数。 3.15.2.2.2 认证方法 Authentication Method *21 (0x15) ,认证方法(Authentication Method)标识符。跟随其后的是一个UTF-8编码字符串,包含认证方法名称。省略认证方法或者包含多个认证方法都将造成协议错误(Protocol Error)。更多关于扩展认证的信息,参考4.12节。 3.15.2.2.3 认证数据 Authentication Data 22 (0x16) ,认证数据(Authentication Data)标识符。跟随其后的是二进制数据,包含认证数据。包含多个认证数据将造成协议错误(Protocol Error)。此数据的内容由认证方法定义。更多关于扩展认证的信息,参考4.12节。 3.15.2.2.4 原因字符串 Reason String 31 (0x1F) ,原因字符串(Reason String)标识符。跟随其后的是UTF-8编码字符串,表示断开原因。此原因字符串是为诊断而设计的可读字符串,不应该被接收端所解析。 如果加上原因字符串之后的AUTH报文长度超出了接收端所指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.15.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.15.2.2.5 用户属性 User Property 38 (0x26) ,用户属性(User Property)标识符。跟随其后的是UTF-8字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户属性之后的AUTH报文长度超出了接收端指定的最大报文长度,则服务端不能发送此属性 [MQTT-3.15.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.15.3 AUTH 载荷 AUTH Payload AUTH报文没有有效载荷。 更多关于扩展认证的信息,参考4.12节。 项目主页 MQTT v5.0协议草案中文版 第四章 操作行为 Operational behavior 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] 4.1 会话状态 Session State 为实现QoS等级1和QoS等级2协议流,客户端和服务端需要将状态与客户标识符相关联,这被称为会话状态。服务端还将订阅信息存储为会话状态的一部分。 会话可以跨越一系列的网络连接。它持续到最新的网络连接(Network Connections)加上会话过期间隔(Session Expiry Interval)。 客户端的会话状态包括: 已发送给服务端,但是还没有完成确认的QoS等级1和QoS等级2的消息。 从服务端收到的,但是还没有完成确认的QoS等级2消息。 服务端的会话状态包括: 会话是否存在,即使会话状态其余部分为空。 客户端订阅信息,包括任何订阅标识符。 已发送给客户端,但是还没有完成确认的QoS等级1和QoS等级2的消息。 等待传输给客户端的QoS等级0(可选),QoS等级1和QoS等级2的消息。 从客户端收到的,但是还没有完成确认的QoS等级2消息。遗嘱小子和遗嘱延时间隔。 如果会话当前未连接,会话结束时间和会话状态将被丢弃。 保留消息不是会话状态的一部分,会话结束时不被删除。 4.1.1 存储会话状态 Storing Session State 当网络连接打开时,客户端和服务端不能丢弃会话状态 [MQTT-4.1.0-1]。当网络连接被关闭并且会话过期间隔已过时,服务端必须丢弃会话状态 [MQTT-4.1.0-2]。 非规范评注 客户端和服务端实现的存储容量必然是有限的,还可能要受管理策略的限制。已存储的会话状态可能因为管理操作(比如某个预定义条件的自动响应)而被丢弃。它造成的后果就是会话终止。这些操作可能是因为资源受限或其他操作原因引发的。硬件或软件故障可能导致客户端或服务端存储的会话状态丢失或损坏。需要谨慎的评估客户端和服务端的存储能力,以确保存储空间充足。 4.1.2 会话状态非规范示例 Session State non-normative examples 例如,想要收集电表读数的用户可能会决定使用QoS等级1的消息,因为他们不能接受数据在网络传输途中丢失,但是,他们可能认为客户端和服务端的数据可以存储在内存(易失性存储器)中,因为(他们觉得)电力供应是非常可靠的,不会有太大的数据丢失风险。 与之相反,停车计费支付应用的提供商可能决定任何情况下都不能让数据支付消息丢失,因此他们要求在通过网络传输之前将所有的数据写入到非易失性存储器中(如硬盘)。 4.2 网络连接 Network Connections MQTT协议要求基础传输层能够提供有序的、可靠的、双向传输(从客户端到服务端和从服务端到客户端)字节流。此规范不要求任何指定的传输协议。客户端或服务端可以支持这里列出的任何传输协议,或者满足本节要求的任何其他传输协议。 客户端或服务端必须支持使用一个或多个提供有序的、可靠的、双向传输(从客户端到服务端和从服务端到客户端)字节流传输的底层传输协议 [MQTT-4.2-1]。 非规范评注 MQTT 3.1使用的传输层协议是 [RFC793] 定义的TCP/IP协议。下面的协议也支持: TLS协议 [RFC5246] WebSocket协议 [RFC6455] 非规范评注 TCP端口8883和1883已在IANA注册,分别用于MQTT的TLS和非TLS通信。 非规范评注 无连接的网络传输,如用户数据包协议 (UDP) 本身不适合,因为它们可能丢失或重新排列数据。 4.3 服务质量等级和协议流程 Quality of Service levels and protocol flows MQTT按照后面章节定义的服务质量(QoS)等级分发应用消息。分发协议是对称的,在下面的描述中,客户端和服务端既可以是发送端也可以是接收端。分发协议关注的是从单个发送者到单个接收者的应用消息。服务端分发应用消息给多个客户端时,每个客户端独立处理。分发给客户端的出站应用消息和入站应用消息的QoS等级可能是不同的。 4.3.1 QoS 0:最多分发一次 QoS 0: At most once delivery 消息的分发依赖于底层网络的能力。接收端不会发送响应,发送端也不会重试。消息可能送达一次也可能根本没送达。 对于QoS等级0的分发协议,发送端 必须发送QoS等于0,DUP等于0的PUBLISH报文 [MQTT-4.3.1-1]。 对于QoS等级0的分发协议,接收端 接受PUBLISH报文时同时接受消息的所有权。 图 4-1 - QoS等级0协议流程图,非规范示例 QoS 0 protocol flow diagram, non-normative example 发送端动作控制报文接收端动作PUBLISH报文QoS 0, DUP=0---------->分发应用消息给适当的后续接收者(们) 4.3.2 QoS 1: 至少分发一次 QoS 1: At least once delivery 服务质量等级1确保消息至少送达一次。QoS等级1的PUBLISH报文的可变报头中包含一个报文标识符,需要PUBACK 报文确认。2.2.1节提供了有关报文标识符的更多信息。 对于QoS等级1的分发协议,发送端 每次发送新的应用消息都必须分配一个未使用的报文标识符 [MQTT-4.3.2-1]。 发送的PUBLISH报文必须包含报文标识符且QoS等于1,DUP等于0 [MQTT-4.3.2-2]。 必须将这个PUBLISH报文看作是未确认的 ,直到从接收端那收到对应的PUBACK报文。 4.4节有一个关于未确认消息的讨论 [MQTT-4.3.2-3]。 一旦发送端收到PUBACK报文,这个报文标识符就可以重用。 注意:允许发送端在等待确认时使用不同的报文标识符发送后续的PUBLISH报文。 对于QoS等级1的分发协议,接收端 响应的PUBACK报文必须包含一个报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文 [MQTT-4.3.2-4]。 发送了PUBACK报文之后,接收端必须将任何包含相同报文标识符的入站PUBLISH报文当做一个新的消息,并忽略它的DUP标志的值 [MQTT-4.3.2-5]。 图 4-2 - QoS 1协议流程图,非规范示例 QoS 1 protocol flow diagram, non-normative example 发送端动作控制报文接收端动作存储消息发送PUBLISH报文QoS=1,DUP=0,带报文标识符---------->开始应用消息的后续分发1<----------发送PUBACK报文,带报文标识符丢弃消息 1不要求接收端在发送 PUBACK 之前完整分发应用消息。原来的发送端收到 PUBACK 报文之后,应用消息的所有权就会转移给这个接收端。 4.3.3 QoS 2:仅分发一次 QoS 2: Exactly once delivery 这是最高等级的服务质量,消息丢失和重复都是不可接受的。使用这个服务质量等级会有额外的开销。 QoS等2消息可变报头中有报文标识符。2.2.1节 提供了有关报文标识符的更多信息。QoS等级2的PUBLISH报文的接收端使用一个两部确认过程来确认收到。 对于QoS等级2的分发协议,发送端 必须给要发送的新应用消息分配一个未使用的报文标识符 [MQTT-4.3.3-1]。 发送端PUBLISH报文必须包含报文标识符且报文的QoS等于2,DUP等于0 [MQTT-4.3.3-2]。 必须将这个PUBLISH报文看作是未确认的,直到从接收端那收到对应的PUBREC报文 [MQTT-4.3.3-3]。4.4节有一个关于未确认消息的讨论。 收到发送端发送的包含原因码小于0x80的PUBREC报文后必须发送一个PUBREL报文。PUBREL报文必须包含与原始PUBLISH报文相同的报文标识符 [MQTT-4.3.3-4]。 必须将这个PUBREL报文看作是未确认的 ,直到从接收端那收到对应的PUBCOMP报文 [MQTT-4.3.3-5]。 一旦发送了对应的PUBREL报文就不能重发这个PUBLISH报文 [MQTT-4.3.3-6]。 如果PUBLISH报文已发送,不能应用消息过期属性 [MQTT-4.3.3-7]。 一旦发送端收到包含原因码大于0x80的PUBCOMP报文,这个报文标识符就可以重用。 注意:允许发送端在等待确认时使用不同的报文标识符发送后续的PUBLISH报文,受制于4.9节描述的流量控制。 对于QoS等级2的分发协议,接收端 响应的PUBREC报文必须包含报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文 [MQTT-4.3.3-8]。 如果接收端发送了包含原因码大于等于0x80的PUBREC报文,它必须将后续包含相同报文标识符的PUBLISH报文当做是新的应用消息 [MQTT-4.3.3-9]。 在收到对应的PUBREL报文之前,接收端必须发送PUBREC报文确认任何后续的具有相同报文标识符的PUBLISH报文。在这种情况下,它不能重复分发消息给任何后续的接收者 [MQTT-4.3.3-10]。 必须发送包含与PUBREL相同报文标识符的PUBCOMP报文作为对PUBREL报文的响应 [MQTT-4.3.3-11]。 发送PUBCOMP报文之后,接收端必须将后续包含相同报文标识符的PUBLISH报文当做是新的应用消息 [MQTT-4.3.3-12]。 必须继续QoS等级2确认序列,即使它已经应用了消息过期属性 [MQTT-4.3.3-13]。 4.4 消息分发重试 Message delivery retry 客户端以新开始(Clean Start)标志为0且会话存在的情况下重连时,客户端和服务端都必须使用原始报文标识符重新发送任何未被确认的PUBLISH报文(当QoS > 0)和PUBREL报文。这是唯一要求客户端或服务端重发消息的情况。客户端和服务端不能在其他任何时间重发消息 [MQTT-4.4.0-1]。 如果收到包含原因码大于等于0x80的PUBACK或PUBREC,则对应的PUBLISH报文被看作已确认,且不能被重传 [MQTT-4.4.0-2]。 图 4-3 - QoS 2协议流程图,非规范示例 QoS 2 protocol flow diagram, non-normative example 发送端动作控制报文接收端动作存储消息发送PUBLISH报文QoS=2,DUP=0,带报文标识符---------->存储报文标识符,然后启动应用消息的向前分发1发送PUBREC报文,带报文标识符和原因码<----------丢弃消息,存储PUBREC中的报文标识符发送PUBREL报文,带报文标识符---------->丢弃报文标识符发送PUBCOMP报文,带报文标识符<----------丢弃已保存的状态 1 不要求接收端在发送PUBREC和PUBCOMP之前完整分发应用消息。原始发送端收到PUBREC报文之后,应用消息的所有权就会转移给这个接收端。然而,接收端需要在接受所有权之前执行对所有可能导致转发失败(例如超出配额、权限等)的条件的检查。接收端在PUBREC中使用适当的原因码指示所有权接受成功或失败。 4.5 消息收到 Message receipt 当服务端接受入站应用消息的所有权时,它必须将消息添加到订阅匹配的客户端的会话状态中 [MQTT-4.5.0-1]。匹配规则定义见 4.7节 。 正常情况下,客户端收到的消息是对他们创建的订阅的响应。客户端也可能收到不是与它的订阅精确匹配的消息。如果服务端自动给客户端分配了一个订阅,可能发生这种情况。 UNSUBSCRIBE 操作正在被处理时也可能收到消息。客户端必须按照可用的服务质量(QoS)规则确认它收到的任何PUBLISH报文,不管它是否选择处理其包含的应用消息 [MQTT-4.5.0-2]。 4.6 消息排序 Message ordering 实现4.3节定义的协议流程时,客户端必须遵循下列规则 重发任何之前的PUBLISH报文时,必须按原始PUBLISH报文的发送顺序重发(适用于QoS等级1和QoS等级2消息)[MQTT-4.6.0-1]。 必须按照对应的PUBLISH报文的顺序发送PUBACK报文(QoS等级1消息)[MQTT-4.6.0-2]。 必须按照对应的PUBLISH报文的顺序发送PUBREC报文(QoS等级2消息)[MQTT-4.6.0-3]。 必须按照对应的PUBREC报文的顺序发送PUBREL报文(QoS等级2消息)[MQTT-4.6.0-4]。 一个有序主题(Ordered Topic)是一个主题,在这个主题中,客户端可以确定从同一个客户端接收的相同QoS等级的消息的顺序与他们发布的顺序一致。当服务端处理发布到有序主题的消息时,它必须按照消息从任何给定客户端接收的顺序发送PUBLISH报文给消费端(对于同一主题和QoS等级) [MQTT-4.6.0-5]。这是上面列出的规则的补充。 服务端处理发送给有序主题的消息时,必须按照上面的规则将消息分发给每个订阅者。此外,它必须按照从客户端收到的顺序发送PUBLISH报文给消费者(对相同的主题和QoS)[MQTT-4.6.0-6]。 默认情况下,服务端转发非共享订阅的消息时,必须将每个主题都视为有序主题 [MQTT-4.6.0-6]。服务端可以提供管理或其他机制来允许一个或多个主题不被当作有序主题。 非规范评注 上面列出的规则确保,使用QoS等级1发布和订阅的消息流,订阅者按照消息发布时的顺序收到每条消息的最终副本,但是消息可能会重复,这可能导致在它的后继消息之后收到某个已经收到消息的重发版本。例如,发布者按顺序1,2,3,4发送消息,订阅者收到的顺序可能是1,2,3,2,3,4。 如果客户端和服务端能保证任何时刻最多有一条消息在 传输中(in-flight)(在某条消息被确认前不发送后面的那条消息),那么,不会有QoS等级1的消息会在它的任何后续消息之后收到。例如,订阅者收到的顺序可能是 1,2,3,3,4,而不是 1,2,3,2,3,4。关于如何使用Receive Maximum的详细信息,参考4.9节流控。 4.7 主题名和主题过滤器 Topic Names and Topic Filters 4.7.1 主题通配符 Topic wildcards 主题层级(topic level)分隔符用于将结构化引入主题名。如果存在分隔符,它将主题名分割为多个主题层级 topic level 。 订阅的主题过滤器可以包含特殊的通配符,允许客户端一次订阅多个主题。 主题过滤器中可以使用通配符,但是主题名不能使用通配符 [MQTT-4.7.0-1]。 4.7.1.1 主题层级分隔符 Topic level separator 斜杠(“/” U+002F)用于分割主题的每个层级,为主题名提供一个分层结构。当客户端订阅指定的主题过滤器包含两种通配符时,主题层级分隔符就很有用了。主题层级分隔符可以出现在主题过滤器或主题名字的任何位置。相邻的主题层次分隔符表示一个零长度的主题层级。 4.7.1.2 多层通配符 Multi-level wildcard 数字符号(“#” U+0023)是用于匹配主题中任意层级的通配符。多层通配符表示它的父级和任意数量的子层级。多层通配符必须单独指定,或者跟在主题层级分隔符后面。不管哪种情况,它都必须是主题过滤器的最后一个字符 [MQTT-4.7.1-1]。 非规范评注 例如,如果客户端订阅主题 “sport/tennis/player1/#”,它会收到使用下列主题名发布的消息: “sport/tennis/player1” “sport/tennis/player1/ranking” “sport/tennis/player1/score/wimbledon” 非规范评注 “sport/#”也匹配单独的 “sport” 主题名,因为#包括它的父级。 “#”是有效的,会收到所有的应用消息。 “sport/tennis/#”也是有效的。 “sport/tennis#”是无效的。 “sport/tennis/#/ranking”是无效的。 4.7.1.3 单层通配符 Single-level wildcard 加号(“+” U+002B) 是只能用于单个主题层级匹配的通配符。 在主题过滤器的任意层级都可以使用单层通配符,包括第一个和最后一个层级。在使用它时,它必须占据过滤器的整个层级 [MQTT-4.7.1-2]。可以在主题过滤器中的多个层级中使用它,也可以和多层通配符一起使用。 非规范评注 例如,“sport/tennis/+”匹配“sport/tennis/player1”和“sport/tennis/player2”,但是不匹配“sport/tennis/player1/ranking”。同时,由于单层通配符只能匹配一个层级,“sport/+”不匹配“sport”但是却匹配 “sport/”。 “+” 是有效的。 “+/tennis/#” 是有效的。 “sport+” 是无效的。 “sport/+/player1” 也是有效的。 “/finance” 匹配 “+/+” 和 “/+” ,但是不匹配 “+”。 4.7.2 以\$开头的主题 Topics beginning with \$ 服务端不能将$字符开头的主题名匹配通配符(#或+)开头的主题过滤器 [MQTT-4.7.2-1]。服务端应该阻止客户端使用这种主题名与其它客户端交换消息。服务端实现可以将$开头的主题名用作其他目的。 非规范评注 $SYS/被广泛用作包含服务器特定信息或控制接口的主题的前缀。 应用不能使用$字符开头的主题。 非规范评注 订阅“#”的客户端不会收到任何发布到以“$”开头主题的消息。 订阅“+/monitor/Clients”的客户端不会收到任何发布到“$SYS/monitor/Clients”的消息。 订阅“$SYS/#”的客户端会收到发布到以“$SYS/”开头主题的消息。 订阅“$SYS/monitor/+” 的客户端会收到发布到“$SYS/monitor/Clients”主题的消息。 如果客户端想同时接受以“$SYS/”开头主题的消息和不以$开头主题的消息,它需要同时订阅“#”和“$SYS/#”。 4.7.3 主题语义和用法 Topic semantic and usage 下列规则应用于主题名和主题过滤器: 所有的主题名和主题过滤器必须至少包含一个字符 [MQTT-4.7.3-1]。 主题名和主题过滤器是大小写敏感的。 主题名和主题过滤器可以包含空格字符。 主题名或主题过滤器以前置或后置斜杠“/”区分。 只包含斜杠“/”的主题名或主题过滤器是合法的。 主题名和主题过滤器不能包含空字符(Unicode U+0000) [Unicode] [MQTT-4.7.3-2]。 主题名和主题过滤器是UTF-8编码字符串,它们不能超过65535字节 [MQTT-4.7.3-3]。见1.5.4节。 除了不能超过UTF-8编码字符串的长度限制之外,主题名或主题过滤器的层级数量没有其它限制。 匹配订阅时,服务端不能对主题名或主题过滤器执行任何规范化(normalization)处理,不能修改或替换任何未识别的字符 [MQTT-4.7.3-4]。主题过滤器中的每个非通配符层级需要逐字符匹配主题名中对应的层级才算匹配成功。 非规范评注 使用UTF-8编码规则意味着,主题过滤器和主题名的比较可以通过比较编码后的UTF-8字节或解码后的Unicode字符。 非规范评注 “ACCOUNTS”和“Accounts”是不同的主题名。 “Accounts payable”是合法的主题名 “/finance”和“finance”是不同的。 如果订阅的主题过滤器与消息的主题名匹配,应用消息会被发送给每一个匹配的客户端订阅。主题资源可以是管理员在服务端预先定义好的,也可以是服务端收到第一个订阅或使用那个主题名的应用消息时动态添加的。服务端也可以使用一个安全组件有选择地授权客户端使用某个主题资源。 4.8 订阅 Subscriptions MQTT提供两种订阅方式,共享和非共享。 非规范评注 在早期的MQTT版本中,所有的订阅都是非共享的。 4.8.1 非共享订阅 Non-shared Subscriptions 非共享订阅只与创建它的会话相关联。每个订阅(Subscription)包含一个指示用于在此会话上分发消息的主题过滤器和订阅选项。服务端负责收集与过滤器相匹配的消息,并在此会话的连接上发送这些消息。 一个会话不能有多个包含相同主题过滤器的非共享订阅,因此主题过滤器可以用作标识此会话的订阅的关键词。 如果有多个客户端,每个客户端都拥有对某个相同主题的非共享订阅,则每个客户端都将获得在该主题上发布的应用消息的副本。这意味着非共享订阅不能被用于多个消费客户端的应用消息负载均衡,因为在这种情况下,每条消息都将被传递给每一个订阅的客户端。 4.8.2 共享订阅 Shared Subscriptions 共享订阅可以与多个订阅会话相关联。与非共享订阅一样,它包含一个主题过滤器和订阅选项。但是,与此主题过滤器相匹配的发布消息仅被发布到其中一个订阅会话。共享订阅在多个消费客户端并行共享处理发布消息时是很有用的。 使用特殊样式的主题过滤器来表示共享订阅。过滤器格式如下: $share/{ShareName}/{filter} $share是字符串字面量,用来把主题过滤器标记为共享订阅主题过滤器。 {ShareName}是字符串,不包含“/”,“+”或“#”。 {filter}该字符串的剩余部分与非共享订阅中的主题过滤器具有相同的语法和语义。参考4.7节。 共享订阅主题过滤器必须以$share/开始,且必须包含至少一个字符长度的共享名(ShareName) [MQTT-4.8.2-1]。共享名不能包含字符“/”,“+”或“#”,但必须跟在“/”字符后面。此“/”字符后面必须跟随一个主题过滤器 [MQTT-4.8.2-2],如4.7节所述。 非规范评注 共享订阅在MQTT服务端的范围内定义,而不是在会话中定义。共享订阅的主题过滤器包含共享名,因此服务端可以有多个包含相同{过滤器}组件的共享订阅。通常,应用程序使用共享名表示共享同一个订阅的一组订阅会话。 示例: 共享订阅“$share/consumer1/sport/tennis/+”和“$share/consumer2/sport/tennis/+”是不同的共享订阅,因此可以被关联到不同的会话组。它们都与非共享订阅主题“sport/tennis/+”相匹配。如果一条消息被发布到匹配主题“sport/tennis/+”,则消息的副本仅发送给所有订阅“$share/consumer1/sport/tennis/+”的会话中的一个会话,也仅发送给所有订阅“$share/consumer2/sport/tennis/+”的会话中的一个会话。更多的副本将发送给所有对“sport/tennis/+”进行非共享订阅的客户端。 共享订阅“$share/consumer1//finance”匹配非共享订阅主题“/finance”。注意,“$share/consumer1//finance”和“$share/consumer1/sport/tennis/+”是不同的共享订阅,尽管它们有相同的共享名。它们可能在某种程度上是相关的,但拥有相同的共享名并不意味着它们之间有某种关系。 通过SUBSCRIBE请求中的共享订阅主题过滤器创建共享订阅。只有一个会话订阅了某个共享订阅时,共享订阅行为如同非共享订阅,除了: 匹配发布消息时,不考虑"$share"和{ShareName}部分。 第一次订阅时,保留消息不发送给此会话。其他匹配的发布消息将发送给此会话。 一旦某个共享订阅存在,其他会话就有可能订阅了相同的共享订阅主题过滤器。新的会话作为额外的订阅者关联到此共享订阅。保留消息不发送给此新的订阅者。后续每条与此共享订阅相匹配的应用消息被发送到该共享订阅关联的其中一个会话。 会话可以通过发送包含某共享订阅主题过滤器的UNSUBSCRIBE报文来显式的将其从共享订阅中分离。会话终止时,也将从共享订阅中分离。 共享订阅持续到至少有一个与其相关的会话(即,会话已经对此共享订阅主题过滤器发布了成功的SUBSCRIBE请求,且尚未完成相应的UNSUBSCRIBE)。当初始创建此共享订阅的会话取消订阅时,除非没有其他的相关会话,否则共享订阅仍然存在。共享订阅在没有被任何会话订阅时结束,且任何相关的未分发的消息都被删除。 共享订阅注释 如果有不止一个会话订阅了某个共享订阅,服务端在消息的基础上自由的选择使用哪个会话,以及使用什么标准来进行该选择。 允许不同的订阅客户端在其SUBSCRIBE报文中请求不同的QoS等级。服务端决定授予每个客户端的最大QoS等级,并且允许向不同的订阅者授予不同的最大QoS等级。向客户端发送应用消息时,服务端必须考虑授予客户端的QoS等级 [MQTT-4.8.2-3],与向订阅者发送消息相同。 如果服务端正在向其选中的订阅客户端发送QoS等级2的消息,并且在分发完成之前网络中断,服务端必须在客户端重新连接时完成向该客户端的消息分发 [MQTT-4.8.2-4],如4.3.3节 所述。如果客户端的会话在客户端重连之前终止,服务端不能把此消息发送给其他订阅的客户端 [MQTT-4.8.2-5]。 如果服务端正在向其选中的订阅客户端发送QoS等级1的消息,并且服务端在收到此客户端的确认报文之前网络中断,服务端可以等客户端重新连接之后将消息重传给客户端。如果客户端的会话在客户端重连之前终止,服务端应该把此应用消息发送给与此共享订阅相关的另一个客户端。服务端可以在第一个客户端断开连接时就尝试将消息发送给另一个客户端。 如果客户端对来自服务端的PUBLISH报文使用包含原因码大于等于0x80的PUBACK或PUBREC报文进行响应,服务端必须丢弃应用消息而不尝试将其发送给任何其他订阅者 [MQTT-4.8.2-6]。 允许客户端向已订阅的共享订阅第二次发送SUBSCRIBE请求。比如,它可以通过这样改变其订阅请求的QoS等级,或者因为它不确定以前的连接关闭之前订阅是否已完成。这不会增加共享订阅关联的会话个数,因此会话将在其第一次发送UNSUBSCRIBE之后脱离此共享订阅。 每个共享订阅都是独立于其他共享订阅的。有可能两个共享订阅包含了重叠的过滤器。在这种情况下,与两个共享订阅都相匹配的消息都将被它们单独处理。如果某个客户端既有共享订阅也有非共享订阅,且某个消息与它们都相匹配,客户端将由于存在非共享订阅而接收此消息的副本,此消息的第二个副本将分发给此共享订阅的某个订阅者,因此可能导致两份副本都被发送给此客户端。 4.9 流控 Flow Control 客户端和服务端使用接收最大值来控制接收未被确认的PUBLISH报文数量,如3.1.2.11.4节和3.2.2.3.2节所述。接收最大值创建了一个发送配额,用于限制可以在没收到PUBACK(QoS等级1)或PUBCOMP(QoS等级2)的情况下发送的QoS等级大于0的PUBLISH报文数量。PUBACK和PUBCOMP按照下述方式补充配额。 客户端或服务端必须将其初始发送配额设置为不超过接收最大值的非0值 [MQTT-4.9.0-1]。 每当客户端或服务端发送了一个QoS等级大于0的PUBLISH报文,它就会减少发送配额。如果发送配额减为0,客户端或服务端不能再发送任何QoS等级大于0的PUBLISH报文 [MQTT-4.9.0-2]。它可以继续发送QoS为0的PUBLISH报文,也可以选择暂停发送这些报文。即使配额为0,客户端和服务端也必须继续处理和响应其他MQTT控制报文 [MQTT-4.9.0-3]。 发送配额增加1: 每当收到一个PUBACK报文或PUBCOMP报文,不管PUBACK或PUBCOMP报文是否包含错误码。 每次收到一个包含返回码大于等于0x80的PUBREC报文。 如果发送配额已到达初始发送配额,则不继续增加。在初始发送配额之上尝试增加配额可能是由建立新的网络连接后重新发送PUBREL数据包引起的。 关于客户端和服务端在超出最大接收值的允许的情况下发送PUBLISH报文的描述,参考3.3.4节。 发送配额和接收最大值的保留不跨越网络连接,每次建立新的网络连接时按照上面的描述进行初始化。它们不是会话状态的一部分。 4.10 请求/响应 Request / Response 有些应用程序或标准可能希望通过MQTT协议运行请求/响应交互。此版本MQTT协议包含三个可用于此目的的属性: 响应主题,在3.3.2.3.5节中描述 对比数据,在3.3.2.3.6节中描述 请求响应信息,在3.1.2.11.7节中描述 响应信息,在3.2.2.3.14节中描述 以下非规范部分描述了如何使用这些属性。 客户端通过发布一个包含响应主题的应用消息来发送请求消息,如3.3.2.3.5节所述。请求消息可以包含对比数据属性,如3.3.2.3.6节所述。 4.10.1 基本请求响应(非规范) Basic Request Response (non-normative) 请求/响应交互过程如下: MQTT客户端(请求方)向主题发布请求消息。请求消息是具有响应主题的应用消息。 另一个MQTT客户端(响应方)订阅了与请求消息发布时使用的主题名相匹配的主题过滤器。结果,它收到请求消息。可能有多个响应方订阅了此主题名,也可能没有响应方。 响应方根据请求消息采取适当的操作,然后往请求消息中携带的响应主题属性中的主题名发布响应消息。 典型用法,请求放订阅了响应主题,从而接收到响应信息。但是,其他某些客户端可能会订阅响应主题,因此它们也将接收和处理响应消息。与请求消息一样,可能有多个客户端订阅了响应消息的发送主题,也可能没有。 如果请求消息包含对比数据属性,则响应方将此属性拷贝到响应消息中,由响应消息的接收端用来将响应消息与原始请求相关联。响应消息不包含响应主题属性。 MQTT服务端转发请求消息中的响应主题和对比数据属性,和响应消息中的对比数据属性。服务端像处理其他应用程序消息一样处理请求消息和响应消息。 请求放通常在发布请求消息之前订阅响应主题。如果响应消息发送时没有任何订阅者订阅了响应主题,则响应消息将不会传递给任何客户端。 请求消息和响应消息可以具有任何QoS等级,并且响应方可以使用具有非0会话过期间隔的会话。通常使用QoS等级0发送请求消息,并且只有在应答者正连接时才发送请求消息。但这不是必须的。 响应者可以使用共享订阅来允许响应客户端池。注意,使用共享订阅时,不保证消息在客户端之间的分发顺序。 请求方有责任确保它具有发布消息到请求消息的主题、并订阅响应主题属性中主题名的必要权限。响应方有责任确保它具有订阅请求主题和发布到响应主题的权限。虽然主题授权不属于本规范,但建议服务端实施此类授权。 4.10.2 确定响应主题值(非规范) Determining a Response Topic value (non-normative) 请求方可以通过包括本地配置在内的任何方式来确定作为他们的响应主题的主题名。为避免不同请求方之间的冲突,由请求方客户端使用的响应主题最好对于该客户端是唯一的。由于请求方和响应方通常都需要对这些主题进行授权,因此使用随机主题名称将会对授权造成挑战。 为了解决此问题,本规范在CONNACK报文中定义了一个名为响应信息的属性。服务端可以使用此属性指导客户端如何选择使用的响应主题。此机制对于服务端和客户端都是可选的。连接时,客户端通过设置CONNECT报文中的请求响应信息属性来请求服务端发送响应信息。这会导致服务端在CONNACK报文中插入响应信息属性(UTF-8编码的字符串)。 本规范不定义响应信息的内容,但它可以被用来传递主题树的全局唯一部分,该部分至少在其会话的整个生命周期内保留给该客户端。使用这种机制,可以在服务端而不是每个客户端中完成该属性的配置。 有关响应信息的定义,参考3.1.2.11.7节。 4.11 服务端重定向 Server redirection 服务端可以通过发送包含原因码为0x9C((临时)使用其他服务端)或0x9D(服务端已(永久)移动)的CONNACK或DISCONNECT报文请求客户端使用另一台服务端,如4.13节 所述。服务端发送这些原因码时可以包含一个服务端参考属性,用以说明客户端应该使用的服务端位置。 原因码0x9C ((临时)使用其他服务端) 指定客户端应该临时切换到另一台服务端。另一台服务端可能是客户端已知的,也可能是由服务端参考所指定的。 原因码0x9D (服务端已(永久)移动)指定客户端应该永久切换到另一台服务端。另一台服务端可能是客户端已知的,也可能是由服务端参考所指定的。 服务端参考是一个UTF-8编码字符串,其值是一个由空格分隔开的参考列表。本规范不指定服务端参考的格式。 非规范评注 推荐每个参考包含名称及可选的端口号。如果名称包含冒号,则名称字符串可以由方括号括起来(“[“和“]”)。由方括号括起来的名称不能包含右方括号(“]”)字符,用于表示使用冒号分隔符的IPv6地址。这是一个简化版的URI授权,如[RFC3986]所述。 非规范评注 服务端参考中的名字通常代表主机名、DNS名[RFC1035]、SRV名RFC2782或IP地址。跟随冒号分隔符的通常是十进制端口号。如果端口信息来自于DNS(比如包含SRV)或者使用默认端口,则主机名后无需跟随端口号。 非规范评注 如果给出了多个服务端参考,则期望客户端选择其中一个。 非规范评注 服务端参考示例如下:myserver.xyz.orgmyserver.xyz.org:888310.10.151.22:8883 [fe80::9610:3eff:fe1c]:1883 允许服务端不发送服务端参考,允许客户端忽略服务端参考。此特性可用于负载均衡、服务端重定位和服务端预置服务端。 4.12 增强认证 Enhanced authentication MQTT CONNECT报文使用用户名和密码字段支持基本的网络连接认证。这些字段虽然称为简单密码认证,但可以被用来承载其他形式的认证,例如把密码作为令牌(Token)传递。 增强认证包含质询/响应风格的认证,从而扩展了基本认证。它可能涉及在CONNECT报文之后、CONNACK报文之前的客户端和服务端之间AUTH报文交换。 服务端通过在CONNECT报文中添加认证方法字段来启动增强认证。此字段指定使用的认证方法。如果服务端不支持客户端提供的认证方法,它可以发送一个包含原因码0x8C(无效的认证方法)或0x87(未授权)的CONNACK报文,如4.13节所述,并且必须关闭网络连接 [MQTT-4.12.0-1]。 认证方法是客户端和服务端关于认证数据中的数据和CONNECT报文中其他字段的含义,以及客户端和服务端完成认证需要交换和处理的协议。 非规范评注 认证方法通常为SASL(Simple Authentication and Security Layer)机制,使用一个注册过的名称便于信息交换。然而,认证方法不限于使用已注册的SASL机制。 如果客户端选择的认证方法指定客户端先发送数据,客户端应该在CONNECT报文中包含认证数据属性。此属性可被用来提供认证方法指定的数据,认证数据的内容由认证方法定义。 如果服务端需要额外的信息来完成认证,它可以向客户端发送AUTH报文,此报文必须包含原因码0x18(继续认证) [MQTT-4.12.0-2]。如果认证方法需要服务端向客户端发送认证相关的数据,这些数据在认证数据(Authentication Data)中发送。 客户端通过发送另一个AUTH报文响应来自服务端的AUTH报文,此报文必须包含原因码0x18(继续认证) [MQTT-4.12.0-3]。如果认证方法要求客户端向服务端发送认证相关的数据,这些数据在认证数据(Authentication Data)中发送。 客户端和服务端按需交换AUTH报文,直到服务端通过发送包含原因码为0的CONNACK报文接受认证为止。如果接受认证需要向客户端发送数据,这些数据在认证数据中发送。 客户端可以在处理过程中随时关闭连接。它可以在关闭之前发送DISCONNECT报文。服务端可以在处理过程中随时拒绝认证。它可以发送包含原因码大于等于0x80的CONNACK报文 ,如4.13节所述,并且必须关闭网络连接 [MQTT-4.12.0-4]。 如果初始CONNECT报文包含认证方法属性,则所有的AUTH报文和成功的CONNACK报文必须包含与CONNECT报文中相同的认证方法属性。 [MQTT-4.12.0-5]。 增强认证的实现对于客户端和服务端来说都是可选的。如果客户端在CONNECT报文中没有包含认证方法,则服务端不能发送AUTH报文,且不能在CONNACK报文中发送认证方法 [MQTT-4.12.0-6]。如果客户端在CONNECT报文中没有包含认证方法,则客户端不能向服务端发送AUTH报文 [MQTT-4.12.0-7]。 如果客户端在CONNECT报文中没有包含认证方法,服务端应该使用CONNECT报文中的信息、TLS会话和网络连接进行认证。 SCRAM认证非规范示例 客户端到服务端:CONNECT认证方法="SCRAM-SHA-1",认证数据=client-first-data 服务端到客户端:AUTH原因码=0x18,认证方法="SCRAM-SHA-1",认证数据=server-first-data 客户端到服务端:AUTH原因码=0x18,认证方法="SCRAM-SHA-1",认证数据=client-final-data 服务端到客户端:CONNACK原因码=0,认证方法="SCRAM-SHA-1",认证数据=server-final-data Kerberos认证非规范示例 客户端到服务端:CONNECT认证方法="GS2-KRB5" 服务端到客户端:AUTH原因码=0x18,认证方法="GS2-KRB5" 客户端到服务端:AUTH原因码=0x18,认证方法="GS2-KRB5",认证数据=initial context token 服务端到客户端:AUTH原因码=0x18,认证方法="GS2-KRB5",认证数据=reply context token 客户端到服务端:AUTH原因码=0x18,认证方法="GS2-KRB5" 服务端到客户端:CONNACK原因码=0,认证方法="GS2-KRB5",认证数据=outcome of authentication 4.12.1 重新认证 Re-authentication 如果客户端在CONNECT报文中提供了认证方法,它可以在收到CONNACK报文之后的任何时间通过发送包含原因码0x19(重新认证)的AUTH报文发起重新认证。客户端必须将认证方法设置为与最初验证网络连接时的认证方法一致 [MQTT-4.12.1-1]。如果认证方法需要客户端先发送数据,则此AUTH报文包含第一片认证数据。 服务端通过向客户端发送AUTH报文来响应此重新认证请求,包含原因码为0x00(成功)的AUTH报文指示重新认证完成,包含原因码为0x18(继续认证)的AUTH报文指示需要更多的认证数据。客户端可以通过发送包含原因码0x18(继续认证)的AUTH报文来响应附加的认证数据。此流程与原始身份验证一样,直到重新认证完成或重新认证失败。 如果重新认证失败,客户端或服务端应该发送包含适当原因码的DISCONNECT报文,如4.13节所述。并且必须关闭网络连接 [MQTT-4.12.1-2]。 在重新认证的过程中,客户端和服务端的其他报文流可以继续使用之前的认证。 非规范评注 服务端可以通过拒绝重新认证来限制客户端在重新认证中尝试的更改范围。例如,如果服务端不允许更改用户名,它可以使任何尝试更改用户名的重新认证都失败。 4.13 错误处理 Handling errors 4.13.1 无效报文和协议错误 Malformed Packet and Protocol Errors 无效报文(Malformed Packet)和协议错误(Protocol Error)的定义见1.2节术语。这些错误案例的部分术语贯穿本规范。客户端或服务端对其收到的MQTT控制报文的检查严格程度依赖: 客户端或服务端实现的大小。 实现支持的性能。 接收端对发送端发送的MQTT控制报文的信任程度。 接收端对用于分发MQTT控制报文的网络的信任程度。 继续处理错误报文的的后果。 如果发送端遵守此规范,它将不会发送无效报文或导致协议错误。然而,如果客户端在收到CONNACK报文之前发送MQTT控制报文,它可能会因为错误的估计了服务端的性能而导致协议错误。参考3.1.4节CONNECT 行为。 无效报文和协议错误使用的原因码包括: 0x81 无效报文 0x82 协议错误 0x93 超过接收最大值 0x95 报文过大 0x9A 不支持保留 0x9B 不支持的QoS等级 0x9E 不支持共享订阅 0xA1 不支持订阅标识符 0xA2 不支持通配符订阅 当客户端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时,它应该关闭网络连接。在AUTH报文出错的情况下它可以在关闭网络连接之前发送包含原因码的DISCONNECT报文。在其他报文出错的情况下它应该在关闭网络连接之前发送包含原因码的DISCONNECT报文。使用原因码0x81(错误报文)或0x82(协议错误),除非包含3.14.2.1断开原因码 中定义的更具体的原因码。 当服务端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时,它必须关闭网络连接 [MQTT-4.13.1-1]。在CONNECT报文出错的情况下它可以在关闭网络连接之前发送包含原因码的CONNACK报文。在其他报文出错的情况下它应该在关闭网络连接之前发送包含原因码的DISCONNECT报文。使用原因码0x81(无效报文)或0x82(协议错误),除非包含3.2.2.2节 - 连接原因码 或3.14.2.1节 – 断开原因码 中定义的更具体的原因码。对其他会话没有影响。 如果服务端或客户端省略了检查MQTT控制报文的某些特性,它可能无法检测到某个错误,因此可能会导致数据被损坏。 4.13.2 其他错误 Other errors 发送端无法预料到无效报文和协议错误以外的错误,因为它可能有某些没有告知发送端的约束。客户端或服务端可能在接收时遇到短暂的错误,比如内存不足,导致无法成功的处理某个MQTT控制报文。 包含原因码大于等于0x80的确认报文PUBACK,PUBREC,PUBREL,PUBCOMP,SUBACK,UNSUBACK表明收到了某个报文标识符的报文出错。这不会影响其他会话或此会话上的其他报文。 CONNACK报文和DISCONNECT报文允许使用大于等于0x80的原因码以指示网络连接将被关闭。如果某个大于等于0x80的原因码被指定,无论是否发送CONNACK报文或DISCONNECT报文,必须关闭网络连接 [MQTT-4.13.2-1]。发送这些原因码不会影响任何其他会话。 如果控制报文包含多个错误,接收端可以按照任意顺序对报文进行验证,并对发现的任何错误采取适当的行为。 项目主页 MQTT v5.0协议草案中文版 第五章 安全(非规范) 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] 5.1 概述 Introduction 强烈建议提供TLS [RFC5246]的服务端实现使用TCP端口8883(IANA服务名:secure-mqtt)。 安全是一个快速变化的领域,所以在设计安全解决方案时总是使用最新的建议。 解决方案需要考虑的风险包括: 设备可能会被盗用 客户端和服务端的静态数据可能是可访问的(可能会被修改) 协议行为可能有副作用(如计时器攻击) 拒绝服务攻击 通信可能会被拦截、修改、重定向或者泄露 虚假MQTT控制报文注入 MQTT方案通常部署在不安全的通信环境中。在这种情况下,协议实现通常需要提供这些机制: 用户和设备身份认证 服务端资源访问授权 MQTT控制报文和内嵌应用数据的完整性校验 MQTT控制报文和内嵌应用数据的隐私控制 作为传输层协议,MQTT仅关注消息传输,提供合适的安全功能是实现者的责任。使用TLS [RFC5246]是比较普遍的选择。 除了技术上的安全问题外,还有地区因素(例如美国欧盟隐私盾框架[USEUPRIVSH]),行业标准(例如第三方支付行业数据安全标准 [PCIDSS]),监管方面的考虑(例如萨斯班-奥克斯利法案[SARBANES])。 5.2 MQTT解决方案:安全和认证 MQTT solutions: security and certification 协议实现可能需要提供符合特定行业安全标准,如NIST网络安全框架 [NISTCSF],第三方支付行业数据安全标准 [PCIDSS],美国联邦信息处理标准 [FIPS1402] 和NSA加密组合B [NSAB]。 在MQTT的补充出版物(MQTT and the NIST Framework for Improving Critical Infrastructure Cybersecurity [MQTTNIST])中可以找到在NIST网络安全框架 [NISTCSF] 中使用MQTT的指导。使用行业证明、独立审计和认证技术有助于满足合规要求。 5.3 轻量级的加密与受限设备 Lightweight crytography and constrained devices 广泛采用的加密算法是高级加密标准 [AES]。对AES提供了硬件支持的处理器有很多,但通常不包含嵌入式处理器。加密算法ChaCha20 [CHACHA20] 软件加解密速度快很多,但不像AES那样广泛可用。 推荐使用为资源受限的低端设备特别优化过的轻量级加密国际标准ISO 29192 [ISO29192]。 5.4 实现注意事项 Implementation notes 实现或使用MQTT时需要考虑许多安全问题。以下章节不应被视为核对清单。 协议实现时可以实现下面的一部分或全部: 5.4.1 客户端身份验证 Authentication of Clients by the Server CONNECT报文包含用户名和密码字段。实现可以决定如何使用这些字段的内容。实现者可以提供自己的身份验证机制,或者使用外部的认证系统如LDAP [RFC4511] 或Auth [RFC6749],还可以利用操作系统的认证机制。 MQTT v5.0提供了一种增强认证机制,如4.12节所述。使用此机制需要客户端和服务端双方的支持。 实现可以明文传递认证数据,混淆数据元素,或者不要求任何认证数据,但应该意识到这会增加中间人攻击和重放攻击的风险。5.4.5节介绍了确保数据私密的方法。 在客户端和服务端之间使用虚拟专用网(VPN)可以确保数据只被授权的客户端收到。 使用TLS [RFC5246]时,服务端可以使用客户端发送的TLS证书验证客户端的身份。 实现可以允许客户端通过应用消息给服务端发送用于身份验证的凭证。 5.4.2 客户端授权 Authorization of Clients by the Server 如果客户端已经成功通过身份认证,服务端实现需要在接受连接之前执行授权检查。 授权可以基于客户端提供的信息如用户名,客户端主机名/IP地址,或认证机制的结果。 具体来说,实现应该检查客户端是否被授权使用此客户标识符,因为客户标识符提供了对MQTT会话状态的访问(如4.1节所述)。此授权检查是为了防止某个客户端偶然或恶意的使用了已被其他客户端所使用的客户标识符。 实现应该提供发生在CONNECT之后的访问控制以限制客户端发布消息到特定主体或使用特定主体过滤器进行订阅的能力。实现需要考虑对具有广泛作用域的主题过滤器的访问限制,如"#"主题过滤器。 5.4.3 服务端身份验证 Authentication of the Server by the Client MQTT协议不是双向信任的。基本认证没有提供客户端验证服务端身份的机制。某些形式的扩展认证允许双向认证。 但是使用TLS [RFC5246]时,客户端可以使用服务端发送的TLS证书验证服务端的身份。从单IP多域名提供MQTT服务的实现应该考虑 [RFC6066]第3节定义的TLS的SNI扩展。SNI允许客户端告诉服务端它要连接的服务端主机名。 实现可以允许服务端通过应用消息给客户端发送凭证用于身份验证。MQTT v5.0提供了一种增强的认证机制,如4.12节所述,它可以被客户端用于验证服务端。使用此机制需要客户端和服务端双方的支持。 在客户端和服务端之间使用虚拟专用网(VPN)可以确保客户端正连接的是预期的服务端。 5.4.4 应用消息和MQTT控制报文的完整性 Integrity of Application Messages and MQTT Control Packets 应用可以在应用消息中单独包含哈希值。这样做可以为PUBLISH报文的网络传输和静态数据提供内容的完整性检查。 TLS [RFC5246]提供了对网络传输的数据做完整性校验的哈希算法。 在客户端和服务端之间使用虚拟专用网(VPN)连接可以在VPN覆盖的网络段提供数据完整性检查。 5.4.5 应用消息和MQTT控制报文的保密性 Privacy of Application Messages and Control Packets TLS [RFC5246]可以对网络传输的数据加密。如果有效的 TLS 密码组合包含的加密算法为 NULL,那么它不会加密数据。要确保客户端和服务端的保密,应避免使用这些密码组合。 应用可以单独加密应用消息的内容。这可以提供应用消息传输途中和静态数据的私密性。但不能给应用消息的其它属性如主题名加密。 客户端和服务端实现可以加密存储静态数据,例如可以将应用消息作为会话的一部分存储。 在客户端和服务端之间使用虚拟专用网(VPN)连接可以在VPN覆盖的网络段保证数据的私密性。 .5.4.6 消息传输的不可否认性 Non-repudiation of message transmission 应用设计者可能需要考虑适当的策略,以实现端到端的不可否认性(non-repudiation)。 5.4.7 检测客户端和服务端的盗用 Detecting compromise of Clients and Servers 使用TLS [RFC5246]的客户端和服务端实现应该能够确保,初始化TLS连接时提供的 SSL 证书是与主机名(客户端要连接的或服务端将被连接的)关联的。 使用TLS [RFC5246]的客户端和服务端实现,可以选择提供检查证书吊销列表(CRLs [RFC5280])和在线整数状态协议(OSCP)[RFC6960]的功能,拒绝使用被吊销的整数。 物理部署可以将防篡改硬件与应用消息的特殊数据传输结合。例如,一个仪表可能会内置一个GPS以确保没有在未授权的地区使用。IEEE安全设备认证[IEEE8021AR]就是用于实现这个机制的一个标准,它使用加密绑定标识符验证设备身份。 5.4.8 检测异常行为 Detecting abnormal behaviors 服务端实现可以监视客户端的行为,检测潜在的安全风险。例如: 重复的连接请求 重复的身份验证请求 连接的异常终止 主题扫描(请求发送或订阅大量主题) 发送无法送达的消息(没有订阅者的主题) 客户端连接但是不发送数据 发现违反安全规则的行为,服务端实现可以断开客户端连接。 服务端实现检测不受欢迎的行为,可以基于IP地址或客户端标识符实现一个动态黑名单列表。 服务部署可以使用网络层次控制(如果可用)实现基于IP地址或其它信息的速率限制或黑名单。 5.4.9 其它的安全注意事项 Other security considerations 如果客户端或服务端的SSL证书丢失,或者我们考虑证书被盗用或者被吊销(利用 CRLs [RFC5280]和OSCP [RFC6960]的情况。 客户端或服务端验证凭证时,如果发现用户名和密码丢失或被盗用,应该吊销或者重新发放。 在使用长连接时: 客户端和服务端使用TLS [RFC5246]时应该允许重新协商会话以确认新的加密参数(替换会话密钥,更换密码组合,更换认证凭证)。 服务端可以关闭客户端的网络连接,并要求他们使用新的凭证重新验证身份。 服务端可以要求客户端使用4.12.1节 中描述的机制周期性的进行重新认证。 资源受限设备或使用受限网络的客户端可以使用TLS RFC5246会话恢复,以降低TLS RFC5246会话重连的成本。 连接到服务端的客户端与其它连接到服务端的客户端之间有一个信任传递关系,它们都有权在同一个主题上发布消息。 5.4.10 使用SOCKS代理 Use of SOCKS 客户端实现应该意识到某些环境要求使用SOCKSv5 [RFC1928]代理创建出站的网络连接。某些MQTT实现可以利用安全隧道(如SSH)通过SOCKS代理。一个实现决定支持SOCKS时,它们应该同时支持匿名的和用户名密码验证的SOCKS代理。对于后一种情况,实现应该意识到SOCKS可能使用明文认证,因此应该避免使用相同的凭证连接 MQTT 服务器。 5.4.11 安全配置文件 Security profiles 实现者和方案设计者可能希望将安全当作配置文件集合应用到MQTT协议中。下面描述的是一个分层的安全等级结构。 5.4.11.1 开放通信配置 Clear communication profile 使用开放通信配置时,MQTT协议运行在一个没有内置额外安全通信机制的开放网络上。 5.4.11.2 安全网络通信配置 Secured network communication profile 使用安全网络通信配置时,MQTT协议运行在有安全控制的物理或虚拟网络上,如VPN或物理安全网络。 5.4.11.3 安全传输配置 Secured transport profile 使用安全传输配置时,MQTT协议运行在使用TLS [RFC5246] 的物理或虚拟网络上,它提供了身份认证,完整性和保密性。 使用内置的用户名和密码字段,TLS [RFC5246] 客户端身份认证可被用于(或者代替)MQTT客户端认证。 5.4.11.4 工业标准的安全配置 Industry specific security profiles 可以预料的是,MQTT协议被设计为支持很多工业标准的应用配置,每一种定义一个威胁模型和用于定位威胁的特殊安全机制。特殊的安全机制推荐从下面的方案中选择: [NISTCSF] NIST网络安全框架[NIST7628] NISTIR 7628智能电网网络安全指南[FIPS1402] (FIPS PUB 140-2) 加密模块的安全要求[PCIDSS] PCI-DSS第三方支付行业数据安全标准[NSAB] NSA加密组合B 项目主页 MQTT v5.0协议草案中文版 第六章 使用WebSocket作为网络层 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] 如果MQTT在WebSocket [RFC6455] 连接上传输,必须满足下面的条件: MQTT控制报文必须使用WebSocket二进制数据帧发送。如果收到任何其它类型的数据帧,接收者必须关闭网络连接 [MQTT-6.0.0-1]。 单个WebSocket数据帧可以包含多个或者部分MQTT报文。接收者不能假设MQTT控制报文按WebSocket帧边界对齐 [MQTT-6.0.0-2]。 客户端必须将字符串"mqtt"包含在它提供的WebSocket子协议列表里 [MQTT-6.0.0-3]。 服务端选择和返回的WebSocket子协议名必须是 mqtt [MQTT-6.0.0-4]。 用于连接客户端和服务器的WebSocket URI对MQTT协议没有任何影响。 6.1 IANA注意事项 IANA Considerations 本规范请求IANA在WebSocket子协议名条目下注册WebSocket MQTT子协议,使用下列数据: 图例 6-1 - IANA WebSocket标识符 IANA WebSocket Identifier 子协议标识符mqtt子协议通用名mqtt子协议定义http://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html 项目主页 MQTT v5.0协议草案中文版 第七章 一致性 Conformance 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] MQTT规范定义了MQTT客户端实现和MQTT服务端实现的一致性要求。MQTT实现可以同时作为MQTT客户端和MQTT服务端。 7.1 一致性条款 Conformance clauses 7.1.1 MQTT服务端一致性条款 MQTT Server conformance clause 服务端的定义,参考术语章节的[服务端(Server)]部分。 MQTT服务端只有满足下面所有的要求才算是符合本规范: 服务端发送的所有MQTT控制报文的格式符合[第二章]和[第三章]描述的格式。 遵守4.7节描述的主题匹配规则和4.8节匹配的订阅规则。 满足下列章节中所有必须级别的要求,明确仅适用于对客户端的除外: [第一章 – 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第六章 – 使用WebSocket作为网络层] 为了能够与任何其他一致的(MQTT)实现进行互操作,无需使用在规范之外定义的任何扩展。 7.1.2 MQTT客户端一致性条款 MQTT Client conformance clause 客户端的定义,参考术语章节的[客户端(Client)]部分。 MQTT客户端只有满足下面所有的要求才算是符合本规范: 客户端发送端所有MQTT控制报文的格式符合[第二章]和[第三章]描述的格式。 满足下列章节中所有必须级别的要求,明确仅适用于对服务端的除外: [第一章 – 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第六章 – 使用WebSocket作为网络层] 为了能够与任何其他一致的(MQTT)实现进行互操作,无需使用在规范之外定义的任何扩展。 项目主页 MQTT v5.0协议草案中文版 附录B 强制性规范声明(非规范) 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] 此附录是非规范性的,只作为本文档正文中可以找到的大量一致性声明的摘要提供。参考 第七章 一致性要求限制列表。 规范声明序号规范声明[MQTT-1.5.4-1]UTF-8编码字符串中的数据必须是按照 [Unicode] 规范定义的,在RFC 3629 [RFC3629] 中重申的有效的UTF-8格式。特别需要指出的是,这些数据不能包含字符码在U+D800和U+DFFF之间的数据。[MQTT-1.5.4-2]UTF-8编码的字符串不能包含空字符U+0000。[MQTT-1.5.4-3]UTF-8编码序列0xEF 0xBB 0xBF总是被解释为U+FEFF ("零宽度非换行空白字符") ,无论它出现在字符串的什么位置,报文接收者都不能跳过或者剥离它。[MQTT-1.5.5-1]编码值必须使用表示该值所需的最少字节数。[MQTT-1.5.7-1]所有的字符串都必须符合UTF-8编码字符串的要求。[MQTT-2.1.3-1]如果标记位被标记为“保留”,则保留它以供将来使用,并且必须设置为所列出的值。[MQTT-2.2.1-2]QoS等级为0的PUBLISH报文不能包含报文标识符。[MQTT-2.2.1-3]客户端每次发送新的SUBSCRIBE,UNSUBSCRIBE或PUBLISH(当QoS等级>0)MQTT控制报文时,它必须为其分配一个当前未被使用的非0报文标识符。[MQTT-2.2.1-4]服务端每次发送新的PUBLISH(当QoS等级>0)MQTT控制报文时,它必须为其分配一个当前未被使用的非0报文标识符。[MQTT-2.2.1-5]PUBACK,PUBREC,PUBREL或PUBCOMP报文必须包含PUBLISH报文中发送的原始报文标识符。[MQTT-2.2.1-6]SUBACK和UNSUBACK报文必须包含相应的SUBSCRIBE和UNSUBSCRIBE报文中使用的报文标识符。[MQTT-2.2.2-1]如果没有属性,属性长度必须为0。[MQTT-3.1.0-1]当协议错误并关闭网络连接时,服务端必须处理客户端发送的第二个CONNECT报文。[MQTT-3.1.2-1]协议名必须是UTF-8字符串"MQTT"。如果服务端不想接受CONNECT,并希望透露它是MQTT服务端,它可以发送一个包含原因码为0x84(不支持的协议版本)的CONNACK报文,然后必须关闭网络连接。[MQTT-3.1.2-2]如果协议版本不为5,且服务端不想接受CONNECT报文,则服务端可以发送一个包含原因码为0x84(不支持的协议版本)的CONNACK报文,然后必须关闭网络连接。[MQTT-3.1.2-3]服务端必须验证CONNECT报文的保留标志位(第0位)是否为 0。[MQTT-3.1.2-4]如果CONNECT报文的新开始标志被设置为1,则客户端和服务端必须丢弃任何已存在的会话并开始一个新的会话。[MQTT-3.1.2-5]如果CONNECT报文的新开始标志被设置为0,并且存在与该客户标识符相关联的会话,服务端必须基于此会话恢复与客户端的通信。[MQTT-3.1.2-6]如果CONNECT报文的新开始标志被设置为0,并且不存在与该客户标识符相关联的会话,则服务端必须创建一个新的会话。[MQTT-3.1.2.7]遗嘱标志被设置为1,表示遗嘱消息必须被存储在服务端并与会话相关联。[MQTT-3.1.2-8]在网络连接被关闭且遗嘱延时间隔已过或会话结束时遗嘱消息必须被发布,除非遗嘱消息被服务端在收到包含原因码为0x00(正常关闭)的DISCONNECT报文后删除或关于此客户标识符的一个新的网络连接在遗嘱消息间隔过期之前被打开。[MQTT-3.1.2-9]如果遗嘱标志被设置为0,连接标志中的遗嘱QoS等级和遗嘱保留字段将会被服务端使用,遗嘱属性、遗嘱主题和遗嘱消息字段必须存在于载荷中。[MQTT-3.1.2-10]一旦遗嘱消息被发布或者服务端收到包含原因码为0x00(正常关闭)的DISCONNECT报文,遗嘱消息必须从服务端的会话中删除。[MQTT-3.1.2-11]如果遗嘱标志设置为0,遗嘱QoS等级必须也设置为0 (0x00)。[MQTT-3.1.2-12]如果遗嘱标志设置为1,遗嘱QoS等级可以被设置为0(0x00),1(0x01)或2(0x02)。[MQTT-3.1.2-13]如果遗嘱标志被设置为0,遗嘱保留标志也必须设置为0。[MQTT-3.1.2-14]如果遗嘱标志被设置为1时,如果遗嘱保留被设置为0,则服务端必须将遗嘱消息当做非保留消息发布。[MQTT-3.1.2-15]如果遗嘱保留被设置为1,则服务端必须将遗嘱消息当做保留消息发布。[MQTT-3.1.2-16]如果用户名标志被设置为0,有效载荷中不能包含用户名字段。[MQTT-3.1.2-17]如果用户名标志被设置为0,有效载荷中必须包含用户名字段。[MQTT-3.1.2-18]如果密码标志被设置为0,有效载荷中不能包含密码字段。[MQTT-3.1.2-19]如果密码标志被设置为1,有效载荷中必须包含密码字段。[MQTT-3.1.2-20]如果保持连接值不为0,且没有任何其它的MQTT控制报文可以发送,客户端必须发送一个PINGREQ 报文。[MQTT-3.1.2-21]如果服务端返回的CONNACK报文中包含服务端保持连接,客户端必须使用此值代替其发送的保持连接。[MQTT-3.1.2-22]如果保持连接的值非零,并且服务端在1.5倍的保持连接时间内没有收到客户端的MQTT控制报文,它必须断开客户端的网络连接,并判定网络连接已断开。[MQTT-3.1.2-23]如果网络连接关闭时会话过期间隔大于0,则客户端与服务端必须存储会话状态。[MQTT-3.1.2-24]服务端不能发送超过最大报文长度的报文给客户端。[MQTT-3.1.2-25]当报文过大而不能发送时,服务端必须丢弃这些报文,然后当做应用消息发送已完成处理。[MQTT-3.1.2-26]服务端在一个PUBLISH报文中发送的主题别名不能超过客户端设置的主题别名最大值。[MQTT-3.1.2-27]如果主题别名最大值没有设置,或者设置为零,则服务端不能向此客户端发送任何主题别名。[MQTT-3.1.2-28]请求响应信息值为0,表示服务端不能返回响应信息。[MQTT-3.1.2-29]如果请求问题信息的值为0,服务端可以选择在CONNACK或DISCONNECT报文中返回原因字符串或用户属性,但不能在除PUBLISH,CONNACK或DISCONNECT之外的报文中发送原因字符串或用户属性。[MQTT-3.1.2-30]如果客户端在CONNECT报文中设置了认证方法,则客户端在收到CONNACK报文之前不能发送除AUTH或DISCONNECT之外的报文。[MQTT-3.1.3-1]CONNECT报文的载荷中包含由可变报头中的标志确定的一个或多个以长度为前缀的字段。这些字段若存在,必须按照客户标识符、遗嘱属性、遗嘱主题、遗嘱载荷、用户名、密码的顺序出现。[MQTT-3.1.3-2]客户端和服务端都必须使用客户标识符识别两者之间的MQTT会话相关的状态。[MQTT-3.1.3-3]客户标识符必须存在,且作为CONNECT报文载荷的第一个字段出现。[MQTT-3.1.3-4]客户标识符必须被编码为UTF-8字符串。[MQTT-3.1.3-5]服务端必须允许1到23个字节长的UTF-8编码的客户标识符,客户标识符只能包含这些字符:"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[MQTT-3.1.3-6]服务端可以允许客户端提供一个零字节的客户标识符,如果这样做了,服务端必须将这看作特殊情况并分配唯一的客户标识符给那个客户端。[MQTT-3.1.3-7]服务端必须假设客户端提供了那个唯一的客户标识符,且必须在CONNACK报文中返回分配的客户标识符。[MQTT-3.1.3-8]如果服务端拒绝了某个客户标识符,它可以发送包含原因码0x85(客户标识符无效)的CONNACK报文作为对客户端的CONNECT报文的回应 ,如4.13节所述。之后必须关闭网络连接。[MQTT-3.1.3-9]如果某个会话在遗嘱延时间隔到期之前创建了新的网络连接,则服务端不能发送遗嘱消息。[MQTT-3.1.3-10]服务端在发布遗嘱消息时必须维护用户属性的顺序。[MQTT-3.1.3-11]遗嘱主题必须为UTF-8编码的字符串。[MQTT-3.1.3-12]如果用户名标志被设置为1,用户名为载荷中下一个字段。用户名必须是UTF-8编码字符串。[MQTT-3.1.4-1]服务端必须按照3.1节的要求验证CONNECT报文,如果报文不符合规范,服务端关闭网络连接。[MQTT-3.1.4-2]服务端可以检查CONNECT报文的内容是不是满足任何进一步的限制,应该执行身份验证和授权检查。如果任何一项检查没通过,服务端必须关闭网络连接。[MQTT-3.1.4-3]如果客户标识符所代表的客户端已经连接到此服务端,那么向原有的客户端发送一个包含原因码为0x8E(会话被接管)的DISCONNECT报文,并且必须关闭原有的网络连接。[MQTT-3.1.4-4]服务端必须对新开始标志进行处理。[MQTT-3.1.4-5]服务端必须使用包含原因码为0x00(成功)的CONNACK报文对客户端的CONNECT报文进行确认。[MQTT-3.1.4-6]如果服务端拒绝了CONNECT报文,它不能处理客户端在CONNECT报文之后发送的任何除AUTH以外的报文。[MQTT-3.2.0-1]服务端在发送任何除AUTH以外的报文之前必须先发送包含原因码为0x00(成功)的CONNACK报文。[MQTT-3.2.0-2]服务端在一次网络连接中不能发送多个CONNACK报文。[MQTT-3.2.2-1]第1个字节是连接确认标志,位7-1是保留位且必须设置为0。[MQTT-3.2.2-2]如果服务端接受一个新开始为1的连接,服务端在CONNACK报文中除了把原因码设置为0x00(成功)之外,还必须把会话存在标志设置为0。[MQTT-3.2.2-3]如果服务端接受一个新开始为0的连接,并且服务端已经保存了此客户标识符的会话状态,服务端在CONNACK报文中必须把会话存在标志设置为1。否则,服务端必须把会话存在标志设置为0。无论如何,服务端在CONNACK报文中必须把原因码设置为0x00(成功)。[MQTT-3.2.2-4]如果客户端没有保存的会话状态,但收到会话存在标志为1,客户端必须关闭网络连接。[MQTT-3.2.2-5]如果客户端保存了会话状态,但收到的会话存在标志为0,客户端若要继续此网络连接,它必须丢弃其保存的会话状态。[MQTT-3.2.2-6]如果服务端发送的CONNACK报文中原因码非0,它必须把会话存在标志设置为0。[MQTT-3.2.2-7]如果服务端发送了一个包含原因码大于等于128的CONNACK报文,它随后必须关闭网络连接。[MQTT-3.2.2-8]服务端发送的CONNACK报文必须设置一种原因码。[MQTT-3.2.2-9]如果服务端不支持Qos为1或2的PUBLISH报文,服务端必须在CONNACK报文中发送最大服务质量以指定其支持的最大QoS值。[MQTT-3.2.2-10]即使不支持QoS为1或2的PUBLISH报文,服务端也必须接受请求QoS为0、1或2的SUBSCRIBE报文。[MQTT-3.2.2-11]如果从服务端接收到了最大QoS等级,则客户端不能发送超过最大QoS等级所指定的QoS等级的PUBLISH报文。[MQTT-3.2.2-12]如果服务端收到包含遗嘱的QoS超过服务端处理能力的CONNECT报文,服务端必须拒绝此连接。服务端应该使用包含原因码为0x9B(不支持的QoS等级)的CONNACK报文进行错误处理,随后必须关闭网络连接。[MQTT-3.2.2-13]如果服务端收到一个包含保留标志位1的遗嘱消息的CONNECT报文且服务端不支持保留消息,服务端必须拒绝此连接请求,且应该发送包含原因码为0x9A(不支持保留)的CONNACK报文,随后必须关闭网络连接。[MQTT-3.2.2-14]从服务端接收到的保留可用标志为0时,客户端不能发送保留标志设置为1的PUBLISH报文。[MQTT-3.2.2-15]客户端不应该发送超过最大报文长度的报文给服务端。[MQTT-3.2.2-16]如果客户端使用长度为0的客户标识符,服务端必须回复包含分配客户标识符的CONNACK报文。分配客户标识符必须是没有被服务端的其他会话所使用的新客户标识符。[MQTT-3.2.2-17]客户端在一个PUBLISH报文中发送的主题别名值不能超过服务端设置的主题别名最大值。[MQTT-3.2.2-18]如果主题别名最大值没有设置,或者设置为0,则客户端不能向此服务端发送任何主题别名。[MQTT-3.2.2-19]如果加上原因字符串之后的CONNACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串。[MQTT-3.2.2-20]如果加上用户属性之后的CONNACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性。[MQTT-3.2.2-21]如果服务端发送了服务端保持连接属性,客户端必须使用此值代替其在CONNECT报文中发送的保持连接时间值。[MQTT-3.2.2-22]如果服务端没有发送服务端保持连接属性,服务端必须使用客户端在CONNECT报文中设置的保持连接时间值。[MQTT-3.3.1-1]客户端或服务端请求重发一个PUBLISH报文时,必须将DUP标志设置为1。[MQTT-3.3.1-2]对于QoS为0的消息,DUP标志必须设置为0。[MQTT-3.3.1-3]发送(出站)的PUBLISH报文与收到(入站)的PUBLISH报文中的DUP标志是独立设置的,它的值必须单独的根据发送(出站)的PUBLISH报文是否是一个重发来确定。[MQTT-3.3.1-4]PUBLISH报文的2个QoS比特位不能同时设置为1。[MQTT-3.3.1-5]如果客户端发给服务端的PUBLISH报文的保留标志被设置为1,服务端必须存储此应用消息,并用其替换此话题下任何已存在的消息。[MQTT-3.3.1-6]如果载荷为空,消息可以正常被服务端所处理,但是此话题下的任何保留消息必须被丢弃,并且此话题未来的订阅者将不会收到保留消息。[MQTT-3.3.1-7]载荷为空的保留消息将不能被存储在服务端。[MQTT-3.3.1-8]如果客户端发给服务端的PUBLISH报文的保留标志位为0,服务器不能把此消息存储为保留消息,也不能丢弃或替换任何已存在的保留消息。[MQTT-3.3.1-9]如果保留消息处理属性被设置为0,服务端必须发送主题与客户端订阅的主题过滤器相匹配的所有保留消息。[MQTT-3.3.1-10]如果保留消息处理属性被设置为1,如果尚不存在匹配的订阅,服务端必须发送主题与客户端订阅的主题过滤器相匹配的所有保留消息。如果已存在相匹配的订阅,服务器不能发送这些保留消息。[MQTT-3.3.1-11]如果保留消息处理属性被设置为2,服务器不能发送这些保留消息。[MQTT-3.3.1-12]如果发布保留订阅选项被设置为0,服务端在转发应用消息时必须将保留标志设置为0,而不管收到的PUBLISH报文中保留标志位如何设置的。[MQTT-3.3.1-13]如果发布保留订阅选项被设置为1,服务端在转发应用消息时必须将保留标志设置为与收到的PUBLISH消息中的保留标志位相同。[MQTT-3.3.2-1]主题名必须是PUBLISH报文可变报头的第一个字段。它必须是UTF-8编码的字符串。[MQTT-3.3.2-2]PUBLISH报文中的主题名不能包含通配符。[MQTT-3.3.2-3]服务端发送给订阅客户端的PUBLISH报文中的主题名必须匹配该订阅的主题过滤器。[MQTT-3.3.2-4]服务端必须把接收到的应用消息中的载荷格式指示原封不动的发给所有的订阅者。[MQTT-3.3.2-5]如果消息过期间隔已过期,服务端还没开始向匹配的订阅者交付该消息,则服务端必须删除该订阅者的消息副本。[MQTT-3.3.2-6]服务端发送给客户端的PUBLISH报文中必须包含消息过期间隔,值为接收时间减去消息在服务端的等待时间。[MQTT-3.3.2-7]接收端不能将任何主题别名映射从一个网络连接转发到另一个网络连接。[MQTT-3.3.2-8]发送端不能发送包含主题别名值为0的PUBLISH报文。[MQTT-3.3.2-9]客户端不能发送主题别名值大于服务端的CONNACK报文中指定的主题别名最大值的PUBLISH报文。[MQTT-3.3.2-10]客户端必须接受所有值大于0且小于等于其发送的CONNECT报文中的主题别名最大值的主题别名。[MQTT-3.3.2-11]服务端不能发送包含主题别名值大于客户端在CONNECT报文中指定的主题别名最大值的PUBLISH报文。[MQTT-3.3.2-12]服务端必须接受所有值大于0且小于等于其发送的CONNACK报文中的主题别名最大值的主题别名。[MQTT-3.3.2-13]响应主题必须是UTF-8编码的字符串。[MQTT-3.3.2-14]响应主题不能包含通配符。[MQTT-3.3.2-15]服务端在收到应用消息时必须将响应主题原封不动的发送给所有的订阅者。[MQTT-3.3.2-16]服务端在收到应用消息时必须原封不动的把对比数据发送给所有的订阅者。[MQTT-3.3.2-17]服务端在转发应用消息到客户端时必须原封不动的把所有的用户属性放在PUBLISH报文中。[MQTT-3.3.2-18]服务端在转发应用消息时必须保持所有用户属性的先后顺序。[MQTT-3.3.2-19]内容类型必须是UTF-8编码的字符串。[MQTT-3.3.2-20]服务端必须把收到的应用消息中的内容类型原封不动的发送给所有的订阅者。[MQTT-3.3.4-1]PUBLISH报文的接收端必须按照PUBLISH报文中的QoS等级发送响应报文。[MQTT-3.3.4-2]这种情况下,服务端必须按照所有匹配的订阅中最大的QoS等级把消息发送给客户端。[MQTT-3.3.4-3]如果客户端在这些重叠的订阅中指定了订阅标识符,服务端在发布这些订阅相匹配的消息时必须包含这些订阅标识符。[MQTT-3.3.4-4]如果服务端对这些重叠的订阅只发送一条相匹配的消息,服务端必须在PUBLISH报文中包含所有的相匹配的订阅标识符(如果存在),但没有顺序要求。[MQTT-3.3.4-5]如果服务端对这些重叠的订阅必须分别发送相匹配的消息,则每个PUBLISH报文中包含与订阅相匹配的订阅标识符(如果存在)。[MQTT-3.3.4-6]从客户端发送给服务端的PUBLISH报文不能包含订阅标识符。[MQTT-3.3.4-7]客户端在收到服务端的PUBACK,PUBCOMP或包含原因码大于等于128的PUBREC报文之前,不能发送数量超过服务端的接收最大值的QoS为1和2的PUBLISH报文。[MQTT-3.3.4-8]客户端不能延迟发送任何报文,除了PUBLISH报文--如果已发送且没有收到确认的PUBLISH报文数量已达到服务端的接收最大值。[MQTT-3.3.4-9]服务端在接收到客户端的PUBACK,PUBCOMP或包含原因码大于等于128的PUBREC报文之前,不能发送数量超过客户端的接收最大值的QoS为1和2的PUBLISH报文。[MQTT-3.3.4-10]服务端不能延迟发送任何报文,除了PUBLISH报文--如果已发送且没有收到确认的PUBLISH报文数量已到达客户端的接收最大值。[MQTT-3.4.2-1]服务端或客户端发送PUBACK报文时必须设置其中一种PUBACK原因码。[MQTT-3.4.2-2]如果加上原因字符串之后的PUBACK报文长度超出了接收端指定的最大报文长度,则发送端不能发送此原因字符串。[MQTT-3.4.2-3]如果加上用户属性之后的PUBACK报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.5.2-1]服务端或客户端发送PUBREC报文时必须设置其中一种原因码。[MQTT-3.5.2-2]发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的PUBREC报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.5.2-3]如果加上用户属性之后的PUBREC报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.6.1-1]PUBREL固定报头的第3,2,1,0位是保留位,必须被设置为0,0,1,0。服务端必须将其它的任何值都当做是不合法的并关闭网络连接。[MQTT-3.6.2-1]客户端或服务端发送PUBREL报文时必须设置其中一种PUBREL原因码。[MQTT-3.6.2-2]如果加上原因字符串之后的PUBREL报文长度超出了接收端指定的最大报文长度,则发送端不能发送此原因字符串。[MQTT-3.6.2-3]如果加上用户属性之后的PUBREL报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.7.2-1]服务端或客户端发送PUBCOMP报文时必须设置一种PUBCOMP原因码。[MQTT-3.7.2-2]如果加上原因字符串之后的PUBCOMP报文长度超出了接收端指定的最大报文长度,则发送端不能发送此原因字符串。[MQTT-3.7.2-3]如果加上用户属性之后的PUBCOMP报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.8.1-1]SUBSCRIBE报文固定报头第3,2,1,0比特位是保留位,必须被设置为0,0,1,0。服务端必须将其他的任何值都当做是不合法的并关闭网络连接。[MQTT-3.8.3-1]主题过滤器必须为UTF-8 编码的字符串。[MQTT-3.8.3-2]载荷必须包含至少一个主题过滤器/订阅选项对。[MQTT-3.8.3-3]订阅选项的第2比特表示非本地选项。值为1,表示应用消息不能被转发给发布此消息的客户标识符。[MQTT-3.8.3-4]共享订阅时把非本地选项设为1将造成协议错误。[MQTT-3.8.3-5]订阅选项的第6和7比特为将来所保留。服务端必须把此保留位非0的SUBSCRIBE报文当做无效报文。[MQTT-3.8.4-1]当服务端收到来自客户端的SUBSCRIBE报文时,必须使用SUBACK报文作为相应。[MQTT-3.8.4-2]SUBACK报文必须和待确认的SUBSCRIBE报文有相同的报文标识符。[MQTT-3.8.4-3]如果服务端收到的SUBSCRIBE报文中的一个主题过滤器与当前会话的一个非共享订阅相同,那么必须使用新的订阅替换现存的订阅。[MQTT-3.8.4-4]如果保留处理选项为0,任何匹配该主题过滤器的保留消息必须被重发,但替换订阅不能造成应用消息的丢失。[MQTT-3.8.4-5]如果服务端收到的SUBSCRIBE报文包含多个主题过滤器,服务端必须当做收到一系列多个SUBSCRIBE报文来处理--除了将它们的响应组合为单个SUBACK响应。[MQTT-3.8.4-6]服务端发送给客户端的SUBACK报文必须为每一个主题过滤器/订阅选项对包含一个原因码。[MQTT-3.8.4-7]此原因码必须说明为该订阅授予的最大QoS等级,或指示订阅失败。[MQTT-3.8.4-8]响应该订阅的应用消息QoS等级必须为该消息发布时的QoS等级和服务端授予的最大QoS等级二者最小值。[MQTT-3.9.2-1]如果加上原因字符串之后的SUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串。[MQTT-3.9.2-2]如果加上用户属性之后的SUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性。[MQTT-3.9.3-1]SUBACK报文中的原因码顺序必须与SUBSCRIBE报文中的主题过滤器顺序相匹配。[MQTT-3.9.3-2]服务端发送SUBACK报文时必须对收到的每一个主题过滤器设置一种原因码。[MQTT-3.10.1-1]UNSUBSCRIBE固定报头的第3,2,1,0位是保留位且必须分别设置为0,0,1,0。服务端必须认为任何其它的值都是不合法的并关闭网络连接。[MQTT-3.10.3-1]UNSUBSCRIBE报文中的主题过滤器必须为UTF-8编码的字符串。[MQTT-3.10.3-2]UNSUBSCRIBE报文有效载荷必须包含至少一个主题过滤器。[MQTT-3.10.4-1]服务端必须对客户端的UNSUBSCRIBE报文中提供的主题过滤器(不管是否包含通配符)逐个字符与当前持有的主题过滤器集进行比较。如果任何过滤器完全匹配,则必须删除其拥有的订阅。[MQTT-3.10.4-2]当服务端收到UNSUBSCRIBE报文,它必须停止添加为了交付给客户端的与主题过滤器相匹配的任何新消息。[MQTT-3.10.4-3]当服务端收到UNSUBSCRIBE报文,它必须完成任何已经开始发送给客户端的、与主题过滤器相匹配的、QoS等级为1或2的消息。[MQTT-3.10.4-4]服务端必须发送UNSUBACK报文以响应客户端的UNSUBSCRIBE请求。[MQTT-3.10.4-5]UNSUBACK报文必须包含和UNSUBSCRIBE报文相同的报文标识符。即使没有删除任何主题订阅,服务端也必须发送一个UNSUBACK响应。[MQTT-3.10.4-6]如果服务端收到的UNSUBSCRIBE报文包含多个主题过滤器,服务端必须当做收到一系列多个UNSUBSCRIBE报文来处理--除了将它们的响应组合为单个SUBACK响应。[MQTT-3.11.2-1]如果加上原因字符串之后的UNSUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此原因字符串。[MQTT-3.11.2-2]如果加上用户属性之后的UNSUBACK报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性。[MQTT-3.11.3-1]UNSUBACK报文中的原因码顺序必须与UNSUBSCRIBE报文中的主题过滤器顺序相匹配。[MQTT-3.11.3-2]服务端发送UNSUBACK报文时对于每个收到的主题过滤器,必须使用一个取消订阅原因码。[MQTT-3.12.4-1]服务端必须发送PINGRESP报文响应客户端的PINGREQ报文。[MQTT-3.14.0-1]服务端不能发送DISCONNECT报文,直到它发送了包含原因码小于0x80的CONNACK报文之后。[MQTT-3.14.1-1]服务端或客户端必须验证所有的保留位都被设置为0,如果他们不为0,发送包含原因码为0x81(无效报文)的DISCONNECT报文。[MQTT-3.14.2-1]客户端或服务端发送DISCONNECT报文时必须使用一种DISCONNECT原因码。[MQTT-3.14.2-2]会话过期间隔不能由服务端的DISCONNECT报文发送。[MQTT-3.14.2-3]如果此属性使得DISCONNECT报文的长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.14.2-4]如果加上用户属性之后的DISCONNECT报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.14.4-1]发送端发送完DISCONNECT报文之后不能再在此网络连接上发送任何MQTT控制报文。[MQTT-3.14.4-2]发送端发送完DISCONNECT报文之后必须关闭网络连接。[MQTT-3.14.4-3]接收到包含原因码为0x00(成功)的DISCONNECT时,服务端必须丢弃任何与当前连接相关的遗嘱消息,而不发布它。[MQTT-3.15.1-1]AUTH报文固定报头第3,2,1,0位是保留位,必须全设置为0。客户端或服务端必须把其他值当做无效值并关闭网络连接。[MQTT-3.15.2-1]AUTH报文的发送端必须使用一种认证原因码。[MQTT-3.15.2-2]如果加上原因字符串之后的AUTH报文长度超出了接收端所指定的最大报文长度,则发送端不能发送此属性。[MQTT-3.15.2-3]如果加上用户属性之后的AUTH报文长度超出了接收端指定的最大报文长度,则服务端不能发送此属性。[MQTT-4.1.0-1]当网络连接打开时,客户端和服务端不能丢弃会话状态。[MQTT-4.2.0-1]客户端或服务端必须支持使用一个或多个提供有序的、可靠的、双向传输(从客户端到服务端和从服务端到客户端)字节流传输的底层传输协议。[MQTT-4.1.0-2]当网络连接被关闭并且会话过期间隔已过时,服务端必须丢弃会话状态。[MQTT-4.3.1-1]对于QoS等级0的分发协议,发送端必须发送QoS等于0,DUP等于0的PUBLISH报文。[MQTT-4.3.2-1]对于QoS等级1的分发协议,发送端每次发送新的应用消息都必须分配一个未使用的用户标识符。[MQTT-4.3.2-2]对于QoS等级1的分发协议,发送端发送的PUBLISH报文必须包含报文标识符且QoS等于1,DUP等于0。[MQTT-4.3.2-3]对于QoS等级1的分发协议,发送端必须将这个PUBLISH报文看作是未确认的 ,直到从接收端那收到对应的PUBACK报文。[MQTT-4.3.2-4]对于QoS等级1的分发协议,接收端响应的PUBACK报文必须包含一个报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文。[MQTT-4.3.2-5]对于QoS等级1的分发协议,接收端发送了PUBACK报文之后,接收端必须将任何包含相同报文标识符的入站PUBLISH报文当做一个新的消息,并忽略它的DUP标志的值。[MQTT-4.3.3-1]对于QoS等级2的分发协议,发送端必须给要发送的新应用消息分配一个未使用的报文标识符。[MQTT-4.3.3-2]对于QoS等级2的分发协议,发送端PUBLISH报文必须包含报文标识符且报文的QoS等于2,DUP等于0。[MQTT-4.3.3-3]对于QoS等级2的分发协议,发送端必须将这个PUBLISH报文看作是未确认的 ,直到从接收端那收到对应的PUBREC报文。[MQTT-4.3.3-4]对于QoS等级2的分发协议,收到发送端发送的包含原因码小于0x80的PUBREC报文后必须发送一个PUBREL报文。PUBREL报文必须包含与原始PUBLISH报文相同的报文标识符。[MQTT-4.3.3-5]对于QoS等级2的分发协议,发送端必须将这个PUBREL报文看作是未确认的 ,直到从接收端那收到对应的PUBCOMP报文。[MQTT-4.3.3-6]对于QoS等级2的分发协议,发送端一旦发送了对应的PUBREL报文就不能重发这个PUBLISH报文。[MQTT-4.3.3-7]对于QoS等级2的分发协议,如果PUBLISH报文已发送,不能应用消息过期属性。[MQTT-4.3.3-8]对于QoS等级2的分发协议,接收端响应的PUBREC报文必须包含报文标识符,这个标识符来自接收到的、已经接受所有权的PUBLISH报文。[MQTT-4.3.3-9]对于QoS等级2的分发协议,如果接收端发送了包含原因码大于等于0x80的PUBREC报文,它必须将后续包含相同报文标识符的PUBLISH报文当做是新的应用消息。[MQTT-4.3.3-10]对于QoS等级2的分发协议,接收端在收到对应的PUBREL报文之前,接收端必须发送PUBREC报文确认任何后续的具有相同报文标识符的PUBLISH报文。在这种情况下,它不能重复分发消息给任何后续的接收者。[MQTT-4.3.3-11]对于QoS等级2的分发协议,接收端必须发送包含与PUBREL相同报文标识符的PUBCOMP报文作为对PUBREL报文的响应。[MQTT-4.3.3-12]对于QoS等级2的分发协议,接收端发送PUBCOMP报文之后,必须将后续包含相同报文标识符的PUBLISH报文当做是新的应用消息。[MQTT-4.3.3-13]对于QoS等级2的分发协议,接收端必须继续QoS等级2确认序列,即使它已经应用了消息过期属性。[MQTT-4.4.0-1]客户端以新开始标志为0且会话存在的情况下重连时,客户端和服务端都必须使用原始报文标识符重新发送任何未被确认的PUBLISH报文(当QoS > 0)和PUBREL报文。这是唯一要求客户端或服务端重发消息的情况。客户端和服务端不能在其他任何时间重发消息。[MQTT-4.4.0-2]如果收到包含原因码大于等于0x80的PUBACK或PUBREC,则对应的PUBLISH报文被看作已确认,且不能被重传。[MQTT-4.5.0-1]当服务端接受入站应用消息的所有权时,它必须将消息添加到订阅匹配的客户端的会话状态中。[MQTT-4.5.0-2]客户端必须按照可用的服务质量(QoS)规则确认它收到的任何PUBLISH报文,不管它是否选择处理其包含的应用消息。[MQTT-4.6.0-1]重发任何之前的PUBLISH报文时,客户端必须按原始PUBLISH报文的发送顺序重发(适用于QoS等级1和QoS等级2 消息)。[MQTT-4.6.0-2]客户端必须按照对应的PUBLISH报文的顺序发送PUBACK报文(QoS等级1消息)。[MQTT-4.6.0-3]客户端必须按照对应的PUBLISH报文的顺序发送PUBREC报文(QoS等级2消息)。[MQTT-4.6.0-4]客户端必须按照对应的PUBREC报文的顺序发送PUBREL报文(QoS等级2消息)。[MQTT-4.6.0-5]当服务端处理发布到有序主题的消息时,它必须按照消息从任何给定客户端接收的顺序发送PUBLISH报文给消费端(对于同一主题和QoS等级)。[MQTT-4.6.0-6]默认情况下,服务端转发非共享订阅的消息时,必须将每个主题都视为有序主题。[MQTT-4.7.0-1]主题过滤器中可以使用通配符,但是主题名不能使用通配符。[MQTT-4.7.1-1]多层通配符必须单独指定,或者跟在主题层级分隔符后面。不管哪种情况,它都必须是主题过滤器的最后一个字符。[MQTT-4.7.1-2]在主题过滤器的任意层级都可以使用单层通配符,包括第一个和最后一个层级。在使用它时,它必须占据过滤器的整个层级。[MQTT-4.7.2-1]服务端不能将$字符开头的主题名匹配通配符(#或+)开头的主题过滤器。[MQTT-4.7.3-1]所有的主题名和主题过滤器必须至少包含一个字符。[MQTT-4.7.3-2]主题名和主题过滤器不能包含空字符 (Unicode U+0000) [Unicode]。[MQTT-4.7.3-3]主题名和主题过滤器是UTF-8编码字符串,它们不能超过65,535字节。[MQTT-4.7.3-4]匹配订阅时,服务端不能对主题名或主题过滤器执行任何规范化处理,不能修改或替换任何未识别的字符。[MQTT-4.8.2-1]除非另有说明,如果服务端或客户端遇到了协议违规的行为,它必须关闭传输这个协议违规控制报文的网络连接。[MQTT-4.8.2-2]如果客户端或服务端处理入站控制报文时遇到了瞬时错误,它必须关闭传输那个控制报文的网络连接。[MQTT-4.8.2-3]向客户端发送应用消息时,服务端必须考虑授予客户端的QoS等级。[MQTT-4.8.2-4]服务端必须在客户端重新连接时完成向该客户端的消息分发。[MQTT-4.8.2-5]如果客户端的会话在客户端重连之前终止,服务端不能把此消息发送给其他订阅的客户端。[MQTT-4.8.2-6]如果客户端对来自服务端的PUBLISH报文使用包含原因码大于等于0x80的PUBACK或PUBREC报文进行响应,服务端必须丢弃应用消息而不尝试将其发送给任何其他订阅者。[MQTT-4.9.0-1]客户端或服务端必须将其初始发送配额设置为不超过接收最大值的非0值。[MQTT-4.9.0-2]每当客户端或服务端发送了一个QoS等级大于0的PUBLISH报文,它就会减少发送配额。如果发送配额减为0,客户端或服务端不能再发送任何QoS等级大于0的PUBLISH报文。[MQTT-4.9.0-3]它可以继续发送QoS为0的PUBLISH报文,也可以选择暂停发送这些报文。即使配额为0,客户端和服务端也必须继续处理和响应其他MQTT控制报文。[MQTT-4.12.0-1]如果服务端不支持客户端提供的认证方法,它可以发送一个包含原因码0x8C(无效的认证方法)或0x87(未授权)的CONNACK报文,并且必须关闭网络连接。[MQTT-4.12.0-2]如果服务端需要额外的信息来完成认证,它可以向客户端发送AUTH报文,此报文必须包含原因码0x18(继续认证)。[MQTT-4.12.0-3]客户端通过发送另一个AUTH报文响应来自服务端的AUTH报文,此报文必须包含原因码0x18(继续认证)。[MQTT-4.12.0-4]服务端可以在处理过程中随时拒绝认证。它可以发送包含原因码大于等于0x80的CONNACK报文,如4.13节所述,并且必须关闭网络连接。[MQTT-4.12.0-5]如果初始CONNECT报文包含认证方法属性,则所有的AUTH报文和成功的CONNACK报文必须包含与CONNECT报文中相同的认证方法属性。[MQTT-4.12.0-6]如果客户端在CONNECT报文中没有包含认证方法,则服务端不能发送AUTH报文,且不能在CONNACK报文中发送认证方法。[MQTT-4.12.0-7]如果客户端在CONNECT报文中没有包含认证方法,则客户端不能向服务端发送AUTH报文。[MQTT-4.12.1-1]如果客户端在CONNECT报文中提供了认证方法,它可以在收到CONNACK报文之后的任何时间通过发送包含原因码0x19(重新认证)的AUTH报文发起重新认证。客户端必须将认证方法设置为与最初验证网络连接时的认证方法一致。[MQTT-4.12.1-2]如果重新认证失败,客户端或服务端应该发送包含适当原因码的DISCONNECT报文,如 section 4.13节 所述。并且必须关闭网络连接。[MQTT-4.13.1-1]当服务端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时,它必须关闭网络连接。[MQTT-4.13.2-1]CONNACK报文和DISCONNECT报文允许使用大于等于0x80的原因码以指示网络连接将被关闭。如果某个大于等于0x80的原因码被指定,无论是否发送CONNACK报文或DISCONNECT报文,必须关闭网络连接。[MQTT-6.0.0-1]MQTT控制报文必须使用WebSocket二进制数据帧发送。如果收到任何其它类型的数据帧,接收者必须关闭网络连接。[MQTT-6.0.0-2]单个WebSocket数据帧可以包含多个或者部分MQTT报文。接收者不能假设MQTT控制报文按WebSocket帧边界对齐。[MQTT-6.0.0-3]客户端必须将字符串"mqtt"包含在它提供的WebSocket子协议列表里。[MQTT-6.0.0-4]服务端选择和返回的WebSocket子协议名必须是mqtt。 项目主页 MQTT v5.0协议草案中文版 附录C MQTT v5.0新特性总结(非规范) 目录 [第一章 - 介绍] [第二章 – MQTT控制报文格式] [第三章 – MQTT控制报文] [第四章 – 操作行为] [第五章 – 安全(非规范)] [第六章 – 使用WebSocket作为网络层] [第七章 – 一致性] [附录B - 强制性规范声明(非规范)] [附录C - MQTT v5.0新特性总结(非规范)] MQTT v5.0添加了以下特性 会话过期把清理会话标志拆分成新开始标志(指示会话应该在不使用现有会话的情况下开始)和会话过期间隔标志(指示连接断开之后会话保留的时间)。会话过期间隔时间可以在断开时修改。把新开始标志设置为1且会话过期间隔标志设置为0,等同于在MQTT v3.1.1中把清理会话(CleanSession)设置为1。 消息过期允许消息在发布时设置一个过期间隔。 所有确认报文原因码更改所有响应报文以包含原因码,包括CONNACK,PUBACK,PUBREC,PUBREL,PUBCOMP,SUBACK,UNSUBACK,DISCONNECT和AUTH,以使得调用方确定请求的函数是否成功。 所有确认报文原因字符串更改大部分报文以包含原因码同时也允许一个可选的原因字符串。这是为问题定位而设计的,并且不应由接收端所解析。 服务端断开允许服务端发送DISCONNECT报文,以指示连接被关闭的原因。 载荷格式和内容类型允许在消息发布时指定载荷格式(二进制、文本)和MIME样式内容类型。这些信息被转发到消息的接收端。 请求/响应规定MQTT请求/响应模式,提供响应主题和对比数据属性,以使得响应消息被路由回请求的发布者。此外,为客户端添加从服务端获取获取关于构造响应主题的配置信息的能力。 共享订阅添加对共享订阅的支持,以允许多个订阅消费者进行负载均衡。 订阅标识符允许在SUBSCRIBE报文中指定一个数字订阅标识符,并在消息分发时返回此标识符。这使得客户端收到分发的消息时确定此消息是由哪个或哪些订阅导致的。 主题别名通过将主题名缩写为小整数来减小MQTT报文的开销大小。客户端和服务端分别指定它们允许的主题别名的数量。 流量控制允许客户端和服务端分别指定未完成的可靠消息(QoS>0)的数量。发送端可以暂停发送此类消息以保持消息数量低于配额。这被用于限制可靠消息的速率和某一时刻的传输中(in-flight)消息数量。 用户属性为大多数报文添加用户属性。PUBLISH报文的用户属性由客户端应用程序定义。PUBLISH报文和遗嘱报文的用户属性由服务端转发给应用消息的接收端。CONNECT,SUBSCRIBE和UNSUBSCRIBE报文的用户属性由服务端实现定义。CONNACK,PUBACK,PUBREC,PUBREL,PUBCOMP,SUBACK,UNSUBACK和AUTH报文的用户属性由发送端定义,且对发送端具有唯一性。MQTT规范不定义用户属性的意义。 最大报文长度允许客户端和服务端各自指定它们支持的最大报文长度。会话参与方发送更大的报文将造成错误。 可选的服务端功能可用性提供定义一组服务端不允许的功能,并告知客户端的机制。可以使用这种方式指定的功能包括:最大QoS等级,保留可用,通配符订阅可用,订阅标识符可用和共享订阅可用。客户端使用服务端通知了(不可用)的功能将造成错误。在早期版本的MQTT协议中,服务端没有实现的功能通过未授权告知客户端。当客户端使用其中一种(不可用的)功能时,此功能允许服务端告知客户端,并添加特定的原因码。 增强的认证提供一种机制来启用包括互相认证在内的质询/响应风格的认证。这允许在客户端和服务端都支持的情况下使用SASL风格的认证,包括客户端在连接中重新认证的功能。 订阅选项提供主要用于定义允许消息桥接应用的订阅选项。包括不要把消息发送给消息源客户端(非本地)的选项和订阅时处理保留消息的选项。 遗嘱延迟提供指定遗嘱消息在连接中断后延时发送的能力。设计此特性是为了在会话的连接重建的情况下不发送遗嘱消息。此特性允许连接短暂中断而不通知其他客户端。 服务端保持连接允许服务端指定其希望客户端使用的保持连接值。此特性允许服务端设置最大允许的保持连接值并被客户端使用。 分配客户标识符服务端分配了客户标识符的情况下,向客户端返回此客户标识符。服务端分配客户标识符只能用于新开始标志为1的连接。 服务端参考允许服务端使用CONNACK或DISCONNECT报文指定备用服务端。此特性被用于(服务端)重定向或做准备。 --- ### 219. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Sparkplug 是一个规范,由 Eclipse Sparkplug 提供,旨在定义如何在 MQTT 基础设施内进行双向通信。它主要针对边缘网络网关(Sparkplug 边缘节点)或原生支持 MQTT 的终端设备以及 Sparkplug 主机应用程序。Sparkplug 规范的目的是为 SCADA/IIoT 解决方案领域确定和文档化一个经过深思熟虑且经过优化的主题命名空间。此外,Sparkplug 以一种方式定义了一个主题命名空间,使其提供语义,允许系统中的 MQTT 客户端自动发现并进行双向通信。 Sparkplug 还定义了 MQTT 的状态管理,以充分利用 MQTT 的原生连续会话感知能力,特别是针对实时 SCADA/IIoT 解决方案。此外,Sparkplug 规范旨在定义有效载荷编码机制,这些机制保持了 MQTT 的原始、轻量级、带宽高效、低延迟特性,同时添加了针对 SCADA/IIoT 解决方案空间的现代编码方案。 总的来说,Sparkplug 规范为 MQTT 提供了一个明确的框架,使其更适合实时 SCADA 和 IIoT 应用。 2023100113392958下载 --- ### 220. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT是OASIS的标准。该规范由OASIS MQTT技术委员会管理。 MQTT 5 规范 MQTT 5 规范 是OASIS标准。该规范可作为> single-page HTML or> PDF. MQTT 3.1.1 规范 是较早的ISO和OASIS标准。该规范可作为> single-page HTML or> PDF. MQTT 3.1 规范 供历史参考,MQTT v3.1规范可在> here. MQTT-SN v1.2 原名MQTT-S,可在> here MQTT用于传感器网络,针对非TCP/IP网络上的嵌入式设备,例如Zigbee。MQTT-SN是一种用于无线传感器网络(WSN)的发布/订阅消息传输协议,旨在将MQTT协议扩展到TCP/IP基础设施无法覆盖的传感器和执行器解决方案领域。 详细了解请参阅IBM苏黎世研究中心网站。Read more about it at the IBM Zurich Research website. --- ### 221. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1  概述 1.0 知识产权政策 此公开评审草案的发布基于OASIS IPR Policy 的Non-Assertion 模式。 关于实现本规范必不可少的任何专利是否已公开, 以及其他的专利许可条款相关的信息,请参考技术委员 会网站的知识产权部分(https://www.oasis-open.org/committees/mqtt/ipr.php)。 1.1 MQTT 协议的组织结构 本规范分为七个章节: .    第一章 - 介绍 .    第二章 - MQTT 控制报文格式 .    第三章 - MQTT 控制报文 .    第四章 - 操作行为 .    第五章 - 安全 .    第六章 - 使用 Websocket 作为网络传输层 .    第七章 - 一致性目标 1.2 术语 本规范中用到的关键字 必须 MUST ,不能 MUST NOT ,要求 REQUIRED ,将会 SHALL ,不会 SHALL NOT ,应该 SHOULD ,不应该 SHOULD NOT ,推荐 RECOMMENDED ,可以 MAY ,可选 OPTIONAL 都 是按照 IETF RFC 2119[RFC2119]中的描述解释。 网络连接(Network Connection): MQTT 使用的底层传输协议基础设施。 .     客户端使用它连接服务端。 .      它提供有序的、可靠的、双向字节流传输。 例子见4.2节。 应用消息(Application Message): MQTT 协议通过网络传输应用数据。应用消息通过 MQTT 传输时,它们有关联的服务质量(QoS)和主题 (Topic)。 客户端(Client): 使用 MQTT 的程序或设备。客户端总是通过网络连接到服务端。它可以: .     打开连接到服务端的网络连接 .     发布应用消息给其他相关的客户端 .     订阅以请求接受相关的应用消息 .     取消订阅以移除接受相应消息的请求 .     关闭连接到服务端的网络连接 服务端(Server): 一个程序或设备,作为发送消息的客户端和请求订阅的客户端之间的中介。服务端: .     接受来自客户端的网络连接 .     接受客户端发布的应用消息 .     处理客户端的订阅和取消订阅请求 .     转发应用消息给符合条件的客户端订阅 .     关闭来自客户端的网络连接 会话(Session): 客户端和服务端之间的状态交互。 一些会话持续时长与网络连接一样, 另一些可以在客户端和服务端的多 个连续网络连接间扩展。 订阅(Subscription): 订阅包含一个主题过滤器(Topic  Filter)和一个最大的服务质量(QoS)等级。订阅与单个会话(Session) 关联。会话可以包含多于一个的订阅。会话的每个订阅都有一个不同的主题过滤器。 共享订阅(Shared Subscription): 一个共享订阅包含一个主题过滤器(Topic Filter)和一个最大的服务质量(QoS)等级。 一个共享订阅可 以与多个订阅会话相关联, 便于支持大范围消息交换模式。 一条主题匹配的应用消息只发送给关联到此共 享订阅的多个会话中的一个会话。一个会话可以包括多个共享订阅,可以同时包含共享订阅与非共享订阅。 通配符订阅(Wildcard Subscription): 通配符订阅是指主题过滤器(Topic Filter)包含一个或多个通配符的订阅。通配符订阅使得一次订阅匹配 多个主题名(Topic Name)。4.7节描述了主题过滤器中的通配符。 主题名(Topic Name): 附加在应用消息上的一个标签,服务端已知且与订阅匹配。服务端发送应用消息的一个副本给每一个匹配 的客户端订阅。 主题过滤器(Topic Filter): 订阅中包含的一个表达式, 用于表示相关的一个或多个主题。主题过滤器可以使用通配符。 MQTT 控制报文(MQTT Control Packet): 通过网络连接发送的信息数据包。 MQTT 规范定义了十四种不同类型的 MQTT 控制报文, 其中一个 (PUBLISH 报文)用于传输应用消息。 无效报文(Malformed Packet): 根据规范不能被正确解析的控制报文。4.13节描述了如何进行相应的错误处理。 协议错误(Protocol Error): 在报文解析之后发现包含协议不允许或与客户端或服务端当前状态不一致的数据的错误。 4.13节描述了如 何进行相应的错误处理。 遗嘱消息(Will Message): 在网络连接非正常关闭的情况下,由服务端发布的应用消息。 3.1.2.5节描述了遗嘱消息。 1.3 规范引用 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, http://www.rfc-editor.org/info/rfc2119 [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003, http://www.rfc-editor.org/info/rfc3629 [RFC6455] Fette, I. and A. Melnikov, "The WebSocket Protocol", RFC 6455, DOI 10.17487/RFC6455, December 2011, http://www.rfc-editor.org/info/rfc6455 [Unicode] The Unicode Consortium. The Unicode Standard, http://www.unicode.org/versions/latest/ 1.4 非规范引用 [RFC0793] Postel, J., "Transmission Control Protocol", STD 7, RFC 793, DOI 10.17487/RFC0793, September 1981, http://www.rfc-editor.org/info/rfc793 [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008, http://www.rfc-editor.org/info/rfc5246 [AES] Advanced Encryption Standard (AES) (FIPS PUB 197). https://csrc.nist.gov/csrc/media/publications/fips/197/final/documents/fips-197.pdf [CHACHA20] ChaCha20 and Poly1305 for IETF Protocols https://tools.ietf.org/html/rfc7539 [FIPS1402] Security Requirements for Cryptographic Modules (FIPS PUB 140-2) https://csrc.nist.gov/csrc/media/publications/fips/140/2/final/documents/fips1402.pdf [IEEE 802.1AR] IEEE Standard for Local and metropolitan area networks - Secure Device Identity http://standards.ieee.org/findstds/standard/802.1AR-2009.html [ISO29192] ISO/IEC 29192- 1:2012 Information technology -- Security techniques -- Lightweight cryptography -- Part 1: General https://www.iso.org/standard/56425.html [MQTT NIST] MQTT supplemental publication, MQTT and the NIST Framework for Improving Critical Infrastructure Cybersecurity http://docs.oasis-open.org/mqtt/mqtt-nist-cybersecurity/v1.0/mqtt-nist-cybersecurity-v1.0.html [MQTTV311] MQTT V3.1.1 Protocol Specification http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html [ISO20922] MQTT V3.1.1 ISO Standard (ISO/IEC 20922:2016) https://www.iso.org/standard/69466.html [NISTCSF] Improving Critical Infrastructure Cybersecurity Executive Order 13636 https://www.nist.gov/sites/default/files/documents/itl/preliminary-cybersecurity-framework.pdf [NIST7628] NISTIR 7628 Guidelines for Smart Grid Cyber Security Catalogue https://www.nist.gov/sites/default/files/documents/smartgrid/nistir-7628_total.pdf [NSAB] NSA Suite B Cryptography http://www.nsa.gov/ia/programs/suiteb_cryptography/ [PCIDSS] PCI-DSS Payment Card Industry Data Security Standard https://www.pcisecuritystandards.org/pci_security/ [RFC1928] Leech, M., Ganis, M., Lee, Y., Kuris, R., Koblas, D., and L. Jones, "SOCKS Protocol Version 5", RFC 1928, DOI 10.17487/RFC1928, March 1996, http://www.rfc-editor.org/info/rfc1928 [RFC4511] Sermersheim, J., Ed., "Lightweight Directory Access Protocol (LDAP): The Protocol", RFC 4511, DOI 10.17487/RFC4511, June 2006, http://www.rfc-editor.org/info/rfc4511 [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008, http://www.rfc-editor.org/info/rfc5280 [RFC6066] Eastlake 3rd, D., "Transport Layer Security (TLS) Extensions: Extension Definitions", RFC 6066, DOI 10.17487/RFC6066, January 2011, http://www.rfc-editor.org/info/rfc6066 [RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, October 2012, http://www.rfc-editor.org/info/rfc6749 [RFC6960] Santesson, S., Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. Adams, "X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP", RFC 6960, DOI 10.17487/RFC6960, June 2013, http://www.rfc-editor.org/info/rfc6960 [SARBANES] Sarbanes-Oxley Act of 2002. http://www.gpo.gov/fdsys/pkg/PLAW-107publ204/html/PLAW-107publ204.htm [USEUPRIVSH] U.S.-EU Privacy Shield Framework https://www.privacyshield.gov [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005, http://www.rfc-editor.org/info/rfc3986 [RFC1035] Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, DOI 10.17487/RFC1035, November 1987, http://www.rfc-editor.org/info/rfc1035 [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for specifying the location of services (DNS SRV)", RFC 2782, DOI 10.17487/RFC2782, February 2000, http://www.rfc-editor.org/info/rfc2782 1.5 数据表示 1.5.1 二进制位 字节中的位从 0 到 7。第 7 位是最高有效位,第 0 位是最低有效位。 1.5.2 双字节整数 双字节整数是 16 位,使用大端序(big-endian,高位字节在低位字节前面) 。这意味着一个 16 位的字在 网络上表示为最高有效字节(MSB) ,后面跟着最低有效字节(LSB)。 1.5.3 四字节整数 四字节整数是 32 位,使用大端序(big-endian,高位字节在低位字节前面) 。这意味着一个 32 位的字在 网络上表示为第一个最高有效字节(MSB)后面跟着第一个最低有效字节(LSB),再后面为第二个最高 有效字节(MSB)后面跟着第二个最低有效字节(LSB)。 1.5.4 UTF-8 编码字符串 后续描述的 MQTT 控制报文中的文本字段编码为 UTF-8 格式的字符串。UTF-8[RFC3629]是一个高效的 Unicode 字符编码格式, 为了支持基于文本的通信,它对 ASCII 字符的编码做了优化。 每一个字符串都有一个两字节的长度字段作为前缀,它给出这个字符串 UTF-8 编码的字节数,它们在图 1.1 UTF-8 编码字符串的结构中描述。因此可以传送的 UTF-8 编码的字符串大小有一个限制,不能超过 65535 字节。 除非另有说明, 所有的 UTF-8 编码字符串的长度都在 0 到 65535 字节这个范围内。 图 1- 1 - UTF-8 编码字符串的结构 二进制位76543210 byte 1字符串长度的最高有效字节(MSB)byte 2字符串长度的最低有效字节(LSB)byte 3 … .如果长度大于 0,这里是 UTF-8 编码的字符数据 UTF-8 编码字符串中的字符数据必须是按照 Unicode 规范[Unicode]定义的和在 RFC3629[RFC3629]中重 申的有效的 UTF-8 格式。特别需要指出的是,这些数据不能包含字符码在 U+D800 和 U+DFFF 之间的数  据。如果服务端或客户端收到了一个包含无效 UTF-8 字符的 MQTT 控制报文, 它必须关闭网络连接 [MQTT- 1.5.4- 1]。 UTF-8 编码的字符串不能包含空字符 U+0000 [MQTT- 1.5.4-2]。如果客户端或服务端收到了一个包含 U+0000 的控制报文, 它必须关闭网络连接。 数据中不应该包含下面这些 Unicode 代码点的编码。如果一个接收者(服务端或客户端)收到了包含下列 任意字符的 MQTT 控制报文,它可以把此报文当做无效报文。 .     U+0001 和 U+001F 之间的控制字符 .     U+007F 和 U+009F 之间的控制字符 .    [Unicode]规范定义的非字符代码点(例如 U+0FFFF) UTF-8 编码序列 0XEF 0xBB 0xBF 总是被解释为 U+FEFF(零宽度非换行空白字符),无论它出现在字符 串的什么位置, 报文接收者都不能跳过或者剥离它 [MQTT- 1.5.4-3]。 非规范示例 例如,字符串 A    是一个大写拉丁字母 A 后面跟着一个代码点 U+2A6D4(它表示一个中日韩统一 表意文字扩展 B 中的字符),这个字符串编码如下: 图 1-2 UTF-8 编码字符串非规范示例 Bit76543210byte 1字符串长度 MSB (0x00) 00000000byte 2字符串长度 LSB (0x05) 00000101byte 3‘A’ (0x41) 01000001byte 4(0xF0) 11110000byte 5(0xAA) 10101010 byte 6(0x9B) 10011011byte 7(0x94) 10010100 1.5.5 变长字节整数 剩余长度字段使用一个变长字节编码方案, 对小于 128 的值它使用单字节编码。更大的值按下面的方式处 理。低 7 位有效位用于编码数据,最高有效位用于指示是否有更多的字节。因此每个字节可以编码 128 个 数值和一个延续位(continuation bit)。剩余长度字段最大 4 个字节 [MQTT- 1.5.5- 1] ,如表 1-1 所示。 表 1- 1 - 变长字节整数大小 字节数最小值最大值10 (0x00)127 (0x7F)2128 (0x80, 0x01)16,383 (0xFF, 0x7F)316,384 (0x80, 0x80, 0x01)2,097,151 (0xFF, 0xFF, 0x7F)42,097,152 (0x80, 0x80, 0x80, 0x01)268,435,455 (0xFF, 0xFF, 0xFF, 0x7F) 非规范评注 非负整数 X 使用变长编码方案的算法如下: do encodedByte = X MOD 128 X = X DIV 128 // if there are more data to encode, set the top bit of this byte if (X > 0) encodedByte = encodedByte OR 128 endif 'output' encodedByte while (X > 0) MOD 是模运算,DIV 是整数除法, OR 是位操作或(C 语言中分别是% ,/ ,|)。 非规范评注 剩余长度字段的解码算法如下: multiplier = 1 value = 0 do encodedByte = 'next byte from stream' value += (encodedByte AND 127) * multiplier if (multiplier > 128*128*128) throw Error(Malformed Variable Byte Integer) multiplier *= 128 while ((encodedByte AND 128) != 0) AND 是位操作与(C 语言中的&) 这个算法终止时,value 包含的就是剩余长度的值。 1.5.6 二进制数据 二进制数据由一个双字节整数指示其数据长度,因此, 二进制数据的长度被限制为 0 到 65,535 字节。 1.5.7 UTF-8 字符串对 UTF-8 字符串对由两个 UTF-8 编码的字符串组成,用来表示名字-值对,第一个字符串表示名字, 第二个字 符串表示值。 所有的字符串必须遵循 UTF-8 字符串编码规范 [MQTT- 1.5.7- 1]。如果接受者(客户端或者服务端)接受到 一个字符串对, 然而其编码并不遵循规范, 则此报文为无效报文。4.13 节描述了错误处理的信息。 1.6 安全 MQTT 客户端和服务端实现应该提供认证、授权和安全通信功能,如第 5 章所描述。强烈建议任何关注于 个人身份信息或敏感信息的应用使用这些安全设施。 1.7 编辑约定 本规范用黄色高亮的文本标识一致性声明,每个一致性声明都分配了一个这种格式的引用: [MQTT-x.x.x-y]。 1.8 变更历史 1.8.1 MQTT v3.1.1 MQTT v3.1.1 MQTT v3.1.1 是首个 OASIS 标准版本 MQTT[MQTTV311]。 也是 ISO/IEC 20922:2016 [ISO20922]标准。 1.8.2 MQTT v5.0 MQTT v5.0 在保持 MQTT 核心不变的基础上添加了大量的新功能。这些功能的主要目标如下: .     进一步支持大规模可扩展系统 .     改进的错误报告 Improved error reporting .     规范化包括容量探索和请求响应在内的通用模式 .     包括用户属性在内的可扩展机制 .     改进性能并支持小型客户端 附录C对 MQTT v5.0 的改进做出了总结。 2  MQTT 控制报文格式 2.1 MQTT 控制报文结构 MQTT 协议通过交换预定义的 MQTT 控制报文来通信。这一节描述这些报文的格式。 MQTT 控制报文由三部分组成,按照下图描述的顺序。 图 2- 1 - MQTT 控制报文的结构 Fixed Header 固定报头, 所有控制报文都包含Variable Header 可变报头,部分控制报文包含Payload 有效载荷,部分控制报文包含 2.1.1 固定报头 如下图所示,每个 MQTT 控制报文都包含一个固定报头。 图 2-2 - 固定报头的格式 Bit76543210byte 1MQTT 控制报文的类型用于指定控制报文类型的标志位byte 2 …剩余长度 2.1.2 MQTT 控制报文的类型 位置: 第 1 个字节, 二进制位 7-4。 表示为 4 位无符号值,这些值的定义见下表。 表 2- 1 - MQTT 控制报文的类型 名字值报文流动方向描述Reserved0禁止保留CONNECT1客户端到服务端客户端请求连接服务端CONNACK2服务端到客户端连接报文确认PUBLISH3两个方向都允许发布消息PUBACK4两个方向都允许QoS 1 消息发布收到确认 PUBREC5两个方向都允许发布收到(保证交付第一步)PUBREL6两个方向都允许发布释放(保证交付第二步)PUBCOMP7两个方向都允许QoS 2 消息发布完成(保证交付第三步)SUBSCRIBE8客户端到服务端客户端订阅请求SUBACK9服务端到客户端订阅请求报文确认UNSUBSCRIBE10客户端到服务端客户端取消订阅请求UNSUBACK11服务端到客户端取消订阅报文确认PINGREQ12客户端到服务端心跳请求PINGRESP13服务端到客户端心跳响应DISCONNECT14两个方向都允许断开连接通知AUTH15两个方向都允许认证信息交换 2.1.3 标志 固定报头第 1 个字节的剩余的 4 位 [3-0]包含每个 MQTT 控制报文类型特定的标志如下表所示。 表格中任   何标记为“保留” 的标志位, 都是保留给以后使用的,必须设置为表格中列出的值 [MQTT-2.1.3- 1]。如果收到 非法的标志, 此报文被当做无效报文。有关错误处理的详细信息见4.13节。 表格 2-2 - 标志位 MQTT 控制报文固定报头标志Bit 3Bit 2Bit 1Bit 0CONNECTReserved0000CONNACKReserved0000PUBLISHUsed in MQTT v5.0DUPQoSRETAINPUBACKReserved0000PUBRECReserved0000PUBRELReserved0010PUBCOMPReserved0000SUBSCRIBEReserved0010SUBACKReserved0000UNSUBSCRIBEReserved0010UNSUBACKReserved0000PINGREQReserved0000PINGRESPReserved0000 DISCONNECTReserved0000AUTHReserved0000 DUP = PUBLISH 报文的重复分发标志 QoS = PUBLISH 报文的服务质量等级 RETAIN = PUBLISH 报文的保留标志 PUBLISH 报文中的 DUP 、QoS 和 RETAIN 标志的描述见3.3.1节。 2.1.4 剩余长度 位置: 从第 2 个字节开始。 剩余长度(Remaining Length)是一个变长字节整数,用来表示当前控制报文剩余部分的字节数,包括可 变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。 MQTT 控制报文总长度等于 固定报头的长度加上剩余长度。 2.2 可变报头 某些 MQTT 控制报文包含一个可变报头部分。它在固定报头和有效载荷之间。可变报头的内容根据报文类 型的不同而不同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。 2.2.1 报文标识符 部分类型 MQTT 控制报文的可变报头部分包含了 2 个字节的报文标识符字段。这些 MQTT 控制报文类型为: PUBLISH 报文(当 QoS>0 时), PUBACK ,PUBREC ,PUBREC ,PUBREL ,PUBCOMP, SUBSCRIBE ,SUBACK ,UNSUBSCRIBE ,UNSUBACK。 需要报文标识符的 MQTT 控制报文如下表所示。 表 2-3 - 包含报文标识符的 MQTT 控制报文 MQTT 控制报文报文标识符字段CONNECT不需要CONNACK不需要PUBLISH需要(如果 QoS > 0)PUBACK需要PUBREC需要PUBREL需要PUBCOMP需要 SUBSCRIBE需要SUBACK需要UNSUBSCRIBE需要UNSUBACK需要PINGREQ不需要PINGRESP不需要DISCONNECT不需要AUTH不需要 QoS 设置为 0 的 PUBLISH 报文不能包含报文标识符[MQTT-2.2.1-2]。 客户端每次发送一个新的 SUBSCRIBE ,UNSUBSCRIBE 或者 PUBLISH(当 QoS>0 时) MQTT 控制报文 时都必须分配一个当前未使用的非零报文标识符 [MQTT-2.2.1-3]。 服务端每次发送一个新的 PUBLISH(当 QoS>0)MQTT 控制报文时都必须分配一个当前未使用的非零报 文标识符 [MQTT-2.2.1-4]。 当客户端处理完这个报文对应的确认后,这个报文标识符就释放可重用。QoS 1 的 PUBLISH 对应的是 PUBACK ,QoS 2 的 PUBLISH 对应的是包含原因码 128 以上的 PUBCOMP 或 PUBREC,与 SUBSCRIBE 或 UNSUBSCRIBE 对应的分别是 SUBACK 或 UNSUBACK。 PUBLISH ,SUBSCRIBE 和 UNSUBSCRIBE 的报文标识符,在一次会话中对于客户端和服务端来说分属 于不同的组。 某个报文标识符在某一时刻不能被多个命令所使用。 PUBACK ,PUBREC 和 PUBREL 报文必须包含与最初发送的 PUBLISH 报文相同的报文标识符 [MQTT- 2.2.1-5] 。类似地, SUBACK 和 UNSUBACK 必须包含在对应的 SUBSCRIBE 和 UNSUBSCRIBE 报文中使 用的报文标识符 [MQTT-2.2.1-6]。 客户端和服务端彼此独立地分配报文标识符。因此,客户端服务端组合使用相同的报文标识符可以实现并 发的消息交换。 非规范评注 客户端发送标识符为 0x1234 的 PUBLISH 报文,它有可能会在收到那个报文的 PUBACK 之前,先 收到服务端发送的另一个不同的但是报文标识符也为 0x1234 的 PUBLISH 报文。 2.2.2 属性 CONNECT ,CONNACK ,PUBLISH ,PUBACK ,PUBREC ,PUBREL ,PUBCOMP ,SUBSCRIBE, SUBACK ,UNSUBACK ,DISCONNECT 和 AUTH 报文可变报头的最后一部分是一组属性。CONNECT 报文的遗嘱(Will)属性字段中也包含了一组可选的属性。 属性字段由属性长度和所有属性组成。 2.2.2.1 属性长度 属性长度被编码为变长字节整数。属性长度不包含用于编码属性长度自身的字节数,但包含所有属性的长 度。 如果没有任何属性,必须由属性长度为零的字段来指示 [MQTT-2.2.2- 1]。 2.2.2.2 属性 一个属性包含一段数据和一个定义了属性用途和数据类型的标识符。 标识符被编码为变长字节整数。任何  控制报文,如果包含了:对于该报文类型无效的标识符,或者错误类型的数据,都是无效报文。收到无效  报文时, 服务端或客户端使用包含原因码 0x81(无效报文) CONNACK 或 DISCONNECT 报文进行错误处 理,如4.13节所述。 标识符排序不分先后。 表 2-4 - 属性 标识符属性名 (用途)数据类型报文/遗嘱属性DecHex10x01载荷格式说明字节PUBLISH, Will Properties20x02消息过期时间四字节整数PUBLISH, Will Properties30x03内容类型UTF-8 编码字符串PUBLISH, Will Properties80x08响应主题UTF-8 编码字符串PUBLISH, Will Properties90x09相关数据二进制数据PUBLISH, Will Properties110x0B定义标识符变长字节整数PUBLISH, SUBSCRIBE170x11会话过期间隔四字节整数CONNECT, CONNACK, DISCONNECT180x12分配客户标识符UTF-8 编码字符串CONNACK190x13服务端保活时间双字节整数CONNACK210x15认证方法UTF-8 编码字符串CONNECT, CONNACK, AUTH220x16认证数据二进制数据CONNECT, CONNACK, AUTH230x17请求问题信息字节CONNECT240x18遗嘱延时间隔四字节整数Will Properties250x19请求响应信息字节CONNECT 260x1A请求信息UTF-8 编码字符串CONNACK280x1C服务端参考UTF-8 编码字符串CONNACK, DISCONNECT310x1F原因字符串UTF-8 编码字符串CONNACK, PUBACK, PUBREC,PUBREL, PUBCOMP, SUBACK,UNSUBACK, DISCONNECT, AUTH330x21接收最大数量双字节整数CONNECT, CONNACK340x22主题别名最大长度双字节整数CONNECT, CONNACK350x23主题别名双字节整数PUBLISH360x24最大 QoS字节CONNACK370x25保留属性可用性字节CONNACK380x26用户属性UTF-8 字符串对CONNECT, CONNACK, PUBLISH, WillProperties, PUBACK, PUBREC,PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE,UNSUBACK, DISCONNECT, AUTH390x27最大报文长度四字节整数CONNECT, CONNACK400x28通配符订阅可用性字节CONNACK410x29订阅标识符可用性字节CONNACK420x2A共享订阅可用性字节CONNACK 非规范评注 尽管属性标识符用变长字节整数来表示,但在此版本协议中,所有的标识符均由一个字节来表示。 2.3 有效载荷 某些 MQTT 控制报文在报文的最后部分包含一个有效载荷,这将在第三章论述。对于 PUBLISH 来说有效 载荷就是应用消息。 表 2-5 - 包含有效载荷的 MQTT 控制报文 MQTT 控制报文有效载荷CONNECT需要CONNACK不需要PUBLISH可选PUBACK不需要PUBREC不需要 PUBREL不需要PUBCOMP不需要SUBSCRIBE需要SUBACK需要UNSUBSCRIBE需要UNSUBACK需要PINGREQ不需要PINGRESP不需要DISCONNECT不需要AUTH不需要 2.4 原因码 原因码是一个单字节无符号数,用来指示一次操作的结果。小于 0x80 的原因码指示某次操作成功完成, 通 常用 0 来表示。大于等于 0x80 的原因码用来指示操作失败。 CONNACK ,PUBACK ,PUBREC ,PUBREL ,PUBCOMP ,DISCONNECT 和 AUTH 控制报文的可变报 头有一个单字节的原因码。 SUBACK 和 UNSUBACK 报文的载荷字段包含一个或多个原因码。 原因码如下表所示。 表 2-6 - 原因码 原因码名称报文DecimalHex00x00成功CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH00x00正常断开DISCONNECT00x00授权的 QoS 0SUBACK10x01授权的 QoS 1SUBACK20x02授权的 QoS 2SUBACK40x04包含遗嘱的断开DISCONNECT160x10无匹配订阅PUBACK, PUBREC170x11订阅不存在UNSUBACK240x18继续认证AUTH 250x19重新认证AUTH1280x80未指明的错误CONNACK, PUBACK, PUBREC, SUBACK,UNSUBACK, DISCONNECT1290x81无效报文CONNACK, DISCONNECT1300x82协议错误CONNACK, DISCONNECT1310x83实现错误CONNACK, PUBACK, PUBREC, SUBACK,UNSUBACK, DISCONNECT1320x84协议版本不支持CONNACK1330x85客户标识符无效CONNACK1340x86用户名密码错误CONNACK1350x87未授权CONNACK, PUBACK, PUBREC, SUBACK,UNSUBACK, DISCONNECT1360x88服务端不可用CONNACK1370x89服务端正忙CONNACK, DISCONNECT1380x8A禁止CONNACK1390x8B服务端关闭中DISCONNECT1400x8C无效的认证方法CONNACK, DISCONNECT1410x8D保活超时DISCONNECT1420x8E会话被接管DISCONNECT1430x8F主题过滤器无效SUBACK, UNSUBACK, DISCONNECT1440x90主题名无效CONNACK, PUBACK, PUBREC, DISCONNECT1450x91报文标识符已被占用PUBACK, PUBREC, SUBACK, UNSUBACK1460x92报文标识符无效PUBREL, PUBCOMP1470x93接收超出最大数量DISCONNECT1480x94主题别名无效DISCONNECT1490x95报文过长CONNACK, DISCONNECT1500x96消息太过频繁DISCONNECT1510x97超出配额CONNACK, PUBACK, PUBREC, SUBACK,DISCONNECT1520x98管理行为DISCONNECT1530x99载荷格式无效CONNACK, PUBACK, PUBREC, DISCONNECT1540x9A不支持保留CONNACK, DISCONNECT 1550x9B不支持的 QoS 等级CONNACK, DISCONNECT1560x9C(临时) 使用其他服务端CONNACK, DISCONNECT1570x9D服务端已 (永久)移动CONNACK, DISCONNECT1580x9E不支持共享订阅SUBACK, DISCONNECT1590x9F超出连接速率限制CONNACK, DISCONNECT1600xA0最大连接时间DISCONNECT1610xA1不支持订阅标识符SUBACK, DISCONNECT1620xA2不支持通配符订阅SUBACK, DISCONNECT 非规范评注 对于原因码 0x91 (报文标识符已被占用) 的处理可以为尝试修复会话、以新会话标志为 1 重置会 话或者判定客户端或服务端实现有缺陷。 3  MQTT 控制报文 3.1 CONNECT – 连接请求 客户端到服务端的网络连接建立后, 客户端发给服务端的第一个报文必须是 CONNECT 报文 [MQTT-3.1.0- 1]。 在一个网络连接上,客户端只能发送一次 CONNECT 报文。服务端必须将客户端发送的第二个 CONNECT 报文当作协议违规处理并断开客户端的连接[MQTT-3.1.0-2]. 有关错误处理的信息请查看4.13节。 有效载荷包含一个或多个编码的字段。包括客户端的唯一标识符,Will 主题, Will 消息,用户名和密码。除 了客户端标识之外,其它的字段都是可选的,基于标志位来决定可变报头中是否需要包含这些字段。 3.1.1 CONNECT 固定报头 图 3- 1 - CONNECT 报文固定报头 Bit76543210byte 1MQTT 报文类型 (1)保留位 00010000byte 2 …剩余长度值 剩余长度字段 剩余长度等于可变报头的长度加上有效载荷的长度。编码方式为变长字节整数。 3.1.2 CONNECT 可变报头 CONNECT 报文的可变报头按下列次序包含四个字段: 协议名(Protocol Name) ,协议级别(Protocol  Level),连接标志(Connect Flags) ,保持连接(Keep Alive)和属性(Properties)。2.2.2节描述了 属性(Properties)编码规则。 3.1.2.1 协议名 图 3-2 - 协议名字节  说明76543210协议名byte 1长度 MSB (0)00000000 byte 2长度 LSB (4)00000100byte 3‘M’01001101byte 4‘Q’01010001byte 5‘T’01010100byte 6‘T’01010100 协议名是表示协议名 MQTT 的 UTF-8 编码的字符串。 MQTT 规范的后续版本不会改变这个字符串的偏移和 长度。 支持多种协议的服务端使用协议名字段判断数据是否为 MQTT 报文。协议名必须是 UTF-8 字符串“MQTT”。 如果服务端不愿意接受 CONNECT 但希望表明其 MQTT 服务端身份, 可以发送包含原因码为 0x84 (不支 持的协议版本) 的 CONNACK 报文, 然后必须关闭网络连接 [MQTT-3.1.2- 1]。 非规范评注 数据包检测工具,例如防火墙,可以使用协议名来识别 MQTT 流量。 3.1.2.2 协议版本 图 3-3 - 协议版本字节  说明76543210协议级别byte 7版本(5)00000101 客户端使用一个字节无符号数表示协议修订级别。 MQTT v5.0 的协议版本字段为 5(0x05)。 支持多版本 MQTT 协议的服务端使用协议版本字段判定客户端正使用的 MQTT 协议版本。如果协议版本 不是 5 且服务端不愿意接受此 CONNECT 报文,可以发送包含原因码 0x84(不支持的协议版本)的 CONNACK 报文,然后必须关闭网络连接 [MQTT-3.1.2-2]。 3.1.2.3 连接标志 连接标志字节包含一些用于指定 MQTT 连接行为的参数。它还指出有效载荷中的字段是否存在。 图 3-4 - 连接标志位 Bit76543210 User Name FlagPassword FlagWill RetainWill QoSWill FlagCleanStartReservedbyte 8XXXXXXX0 服务端必须验证 CONNECT 报文的保留标志位(第 0 位)是否为 0 [MQTT-3.1.2-3],如果不为 0 则此报文 为无效报文。4.13节给出了错误处理信息。 3.1.2.4 新开始 位置: 连接标志字节的第 1 位 这个二进制位表明此次连接是一个新的会话还是一个已存在的会话的延续。4.1节定义了会话状态。 如果收到新开始(Clean Start)为 1 的 CONNECT 报文,客户端和服务端必须丢弃任何已存在的会话, 并 开始一个新的会话 [MQTT-3.1.2-4]。相应的, CONNACK 报文中的会话存在标志设置为 0。 6]。 3.1.2.5 遗嘱标志 位置: 连接标志字节的第 2 位 如果遗嘱标志(Will Flag)被设置为 1,表示遗嘱消息必须已存储在服务端与此客户标识符相关的会话中 [MQTT-3.1.2-7]。遗嘱消息(Will Message)包含遗嘱属性,遗嘱主题和遗嘱载荷字段。 遗嘱必须在网络连 接被关闭、遗嘱延时间隔到期或者会话结束之后被发布,除非服务端收到包含原因码为 0x00 (正常关闭)  的 DISCONNECT 报文之后删除了遗嘱消息(Will Message) ,或者一个关于此客户标识符的新的网络连  接在遗嘱迟发时间(Will Delay Interval)超时之前被创建 [MQTT-3.1.2-8]。 遗嘱发布的条件,包括但不限于: .     服务端检测到了一个 I/O 错误或者网络故障 .     客户端在保持连接(Keep Alive)的时间内未能通讯 .     客户端在没有发送包含原因码 0x00(正常关闭)的情况下关闭了网络连接 .     服务端在没有收到包含原因码 0x00(正常关闭)的情况下关闭了网络连接 如果遗嘱标志(Will Flag)被设置为 1 ,遗嘱属性(Will Property)、遗嘱主题(Will Topic)和遗嘱载荷   (Will Payload)字段必须存在于报文有效载荷中 [MQTT-3.1.2-9] 。一旦遗嘱消息(Will Message)被发布 或者服务端收到包含原因码为 0x00(正常关闭)的 DISCONNECT 报文,遗嘱消息(Will Message)必须 从服务端的会话中删除 [MQTT-3.1.2- 10]。 服务端应该在网络连接断开并且遗嘱迟发时间(Will Delay Interval)到期, 或者会话结束之后立即发布遗 嘱消息。服务端关闭或出错的情况下,可以在服务重新启动之后发布遗嘱消息(Will Message)。这种情 况下从服务端出错到遗嘱发布之间存在一定的延迟。 关于遗嘱延时间隔(Will Delay Interval)的详细信息, 请参考3.1.3.2节。 非规范评注 通过设置晚于会话过期间隔(Session Expiry Interval)的遗嘱迟发时间(Will Delay Interval)并发 送包含原因码 0x04(包含遗嘱的断开连接),客户端得以发出会话过期(Session Expiry)通告。 3.1.2.6 遗嘱 QoS 位置: 连接标志字节的第 3 、4 位 这两个比特指定了发布遗嘱消息(Will Message)时的服务质量(QoS)。 如果遗嘱标志(Will Flag)设置为 0,遗嘱服务质量(Will QoS)必须也设置为 0(0x00) [MQTT-3.1.2- 11]。 如果遗嘱标志设置为 1,遗嘱服务质量可以被设置为 0(0x00), 1(0x01)或 2(0x02) [MQTT-3.1.2- 12] 。设置为 3(0x03)的报文是无效报文。4.13节描述了错误处理信息。 3.1.2.7 遗嘱保留 位置: 连接标志字节的第 5 位 此位指定遗嘱消息(Will Message)在发布时是否会被保留。 如果遗嘱标志被设置为 0,遗嘱保留(Will Retain)标志也必须设置为 0 [MQTT-3.1.2- 13] 。如果遗嘱标志    被设置为 1 时,如果遗嘱保留被设置为 0,则服务端必须将遗嘱消息当做非保留消息发布 [MQTT-3.1.2- 14]。 如果遗嘱保留被设置为 1 ,则服务端必须将遗嘱消息当做保留消息发布 [MQTT-3.1.2- 15]。 3.1.2.8 用户名标志 位置: 连接标志字节的第 7 位 如果用户名标志(User Name Flag)被设置为 0,有效载荷中不能包含用户名字段 [MQTT-3.1.2- 16] 。如果 用户名标志被设置为 0,有效载荷中必须包含用户名字段 [MQTT-3.1.2- 17]。 3.1.2.9 密码标志 位置: 连接标志字节的第 6 位 如果密码标志(Password Flag)被设置为 0,有效载荷中不能包含密码字段 [MQTT-3.1.2- 18] 。如果密码 标志被设置为 1,有效载荷中必须包含密码字段 [MQTT-3.1.2- 19]。 非规范评注 相比 MQTT v3.1.1,此版本协议允许在没有用户名的情况下发送密码。这表明密码除了作为口令之 外还可以有其他用途。 3.1.2.10 保持连接 图 3-5 - 保持连接字节 Bit76543210byte 9保持连接 Keep Alive MSBbyte 10保持连接 Keep Alive LSB 保持连接(Keep Alive)使用双字节整数来表示以秒为单位的时间间隔。它是指在客户端传输完成一个 MQTT 控制报文的时刻到发送下一个报文的时刻, 两者之间允许空闲的最大时间间隔。客户端负责保证控 制报文发送的时间间隔不超过保持连接的值。如果没有任何其它的 MQTT 控制报文可以发送,客户端必须 发送一个 PINGREQ 报文 [MQTT-3.1.2-20]。 如果服务端返回的 CONNACK 报文中包含服务端保持连接(Server Keep Alive) ,客户端必须使用此值代 替其发送的保持连接(Keep Alive) [MQTT-3.1.2-21]。 不管保持连接的值是多少, 客户端任何时候都可以发送 PINGREQ 报文,并且使用 PINGRESP 报文判断网 络和服务端的活动状态。 如果保持连接的值非零,并且服务端在 1.5 倍的保持连接时间内没有收到客户端的控制报文,它必须断开 客户端的网络连接,并判定网络连接已断开 [MQTT-3.1.2-22]。 客户端发送了 PINGREQ 报文之后, 如果在合理的时间内仍没有收到 PINGRESP 报文,它应该关闭到服务 端的网络连接。 保持连接(Keep Alive)值为零的结果是关闭保持连接(Keep Alive)机制。如果保持连接(Keep Alive) 值为零, 客户端不必按照任何特定的时间发送 MQTT 控制报文。 非规范评注 服务端可能因为其他原因断开客户端连接,比如服务端将要关闭服务。设置保持连接(Keep Alive) 不保证客户端将一直保持连接状态。 非规范评注 保持连接的实际值是由应用指定的, 一般是几分钟。允许的最大值是 18 小时 12 分 15 秒。 3.1.2.11 CONNECT 属性 3.1.2.11.1 属性长度 CONNECT 报文可变报头中的属性(Properties)长度被编码为变长字节整数。 3.1.2.11.2 会话过期间隔 17 (0x11) ,会话过期间隔(Session Expiry Interval)标识符。 跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话 过期间隔(Session Expiry Interval)将造成协议错误(Protocol Error)。 如果会话过期间隔(Session Expiry Interval)值未指定,则使用 0。如果设置为 0 或者未指定,会话将在 网络连接(Network Connection)关闭时结束。 如果会话过期间隔(Session Expiry Interval)为 0xFFFFFFFF (UINT_MAX),则会话永不过期。 如果网络连接关闭时会话过期间隔(Session Expiry Interval)大于 0,则客户端与服务端必须存储会话状 态 [MQTT-3.1.2-23]。 非规范评注 客户端或服务端可能会因为中断运行导致会话时钟某些时间未运行。这将导致会话的删除被延迟。 更多关于会话的信息参考4.1节。关于会话存储的状态的详细和限制参考4.1.1节。 当会话过期时, 客户端和服务端无需以原子操作的方式删除会话状态。 非规范评注 把新开始(Clean Start)设置为 1 且会话过期间隔(Session Expiry Interval)设置为 0,等同于在   MQTT v3.1.1 中把清理会话(CleanSession)设置为 1。把新开始(Clean Start)设置为 0 且不设   置会话过期间隔(Session  Expiry  Interval), 等同于在 MQTT v3.1.1 中把清理会话标志设置为 0。 非规范评注 当希望只处理连接上服务端之后才发布的消息,客户端应该把新开始(Clean Start)设置为 1 且会 话过期间隔(Session Expiry Interval)设置为 0,这样客户端就不会收到它连接之前被服务端所发 布的消息,并且需要每次连接上服务端时重新订阅其感兴趣的主题。 非规范评注 某些客户端使用的网络可能只能提供断断续续的连接, 这种客户端可以使用较短的会话过期间隔 (Session Expiry Interval)以便在网络再次可用后重新连接到服务端时获得持续的消息交付。如果 客户端不再重新连接, 且允许会话过期,应用消息将会丢失。 非规范评注 某个客户端设置较长的会话过期间隔(Session Expiry Interval)或设置会话不过期,即要求服务端 为其保持会话到其下一次连接上服务端之后。只有打算在一段时间之后将会重连服务端时, 客户端 才应该设置较长的会话过期间隔(Session Expiry Interval)。当客户端认定其将来不会使用本次会 话时,应该在断开时把会话过期间隔(Session Expiry Interval)设置为 0。 非规范评注 客户端应当使用 CONNACK 报文中的会话存在(Session Present)来判定服务端是否存储了其会 话。 非规范评注 客户端应当以服务端返回的会话存在(Session Present)标志来判定会话是否已过期,而不是客  户端自己实现的会话过期状态。如果客户端自己实现会话过期状态,则需要将会话应当被删除的时 间作为会话状态的一部分而存储。 3.1.2.11.3 接收最大值 33 (0x21) ,接收最大值(Receive Maximum)标识符。 跟随其后的是由双字节整数表示的最大接收值。包含多个接收最大值或接收最大值为 0 将造成协议错误 (Protocol Error)。 客户端使用此值限制客户端愿意同时处理的 QoS 等级 1 和 QoS 等级 2 的发布消息最大数量。没有机制可 以限制服务端试图发送的 QoS 为 0 的发布消息。 接收最大值只将被应用在当前网络连接。如果没有设置最大接收值,将使用默认值 65535。 关于接收最大值的详细使用,参考4.9节流控。 3.1.2.11.4 最大报文长度 39 (0x27),最大报文长度(Maximum Packet Size)标识符。 跟随其后的是由四字节整数表示的客户端愿意接收的最大报文长度(Maximum Packet Size) ,如果没有 设置最大报文长度(Maximum Packet Size) ,则按照协议由固定报头中的剩余长度可编码最大值和协议 报头对数据包的大小做限制。 包含多个最大报文长度(Maximum Packet Size)或者最大报文长度(Maximum Packet Size)值为 0 将 造成协议错误。 非规范评注 客户端如果选择了限制最大报文长度,应该为最大报文长度设置一个合理的值。 如2.1.4节所述, 最大报文长度是 MQTT 控制报文的总长度。客户端使用最大报文长度通知服务端其所能 处理的单个报文长度限制。 服务端不能发送超过最大报文长度(Maximum Packet Size)的报文给客户端 [MQTT-3.1.2-24]。收到长度 超过限制的报文将导致协议错误,客户端发送包含原因码 0x95(报文过大)的 DISCONNECT 报文给服务 端,详见4.13节。 当报文过大而不能发送时, 服务端必须丢弃这些报文,然后当做应用消息发送已完成处理 [MQTT-3.1.2-25]。 共享订阅的情况下,如果一条消息对于部分客户端来说太长而不能发送,服务端可以选择丢弃此消息或者 把消息发送给剩余能够接收此消息的客户端。 非规范评注 服务端可以把那些没有发送就被丢弃的报文放在死信队列上, 或者执行其他诊断操作。具体的操 作超出了本规范的范围。 3.1.2.11.5 主题别名最大值 34 (0x22) ,主题别名最大值(Topic Alias Maximum)标识符。 跟随其后的是用双字节整数表示的主题别名最大值(Topic Alias Maximum)。包含多个主题别名最大值 (Topic Alias Maximum)将造成协议错误(Protocol Error)。没有设置主题别名最大值属性的情况下, 主 题别名最大值默认为零。 此值指示了客户端能够接收的来自服务端的主题别名(Topic Alias)最大数量。客户端使用此值来限制本 次连接可以拥有的主题别名的数量。 服务端在一个 PUBLISH 报文中发送的主题别名不能超过客户端设置的 主题别名最大值(Topic Alias Maximum) [MQTT-3.1.2-26]。值为零表示本次连接客户端不接受任何主题  别名(Topic Alias)。 如果主题别名最大值(Topic Alias)没有设置,或者设置为零,则服务端不能向此客 户端发送任何主题别名(Topic Alias) [MQTT-3.1.2-27]。 3.1.2.11.6 请求响应信息 25 (0x19) ,请求响应信息(Request Response Information)标识符。 跟随其后的是用一个字节表示的 0 或 1。包含多个请求响应信息(Request Response Information) ,或者 请求响应信息(Request Response Information)的值既不为 0 也不为 1 会造成协议错误(Protocol Error)。如果没有请求响应信息(Request Response Information),则请求响应默认值为 0。 客户端使用此值向服务端请求 CONNACK 报文中的响应信息(Response Information)。 值为 0,表示服 务端不能返回响应信息 [MQTT-3.1.2-28]。值为 1,表示服务端可以在 CONNACK 报文中返回响应信息。 非规范评注 即使客户端请求响应信息(Response Information), 服务端也可以选择不发送响应信息 (Response Information)。 更多关于请求/响应信息的内容,请参考4.10节。 3.1.2.11.7 请求问题信息 23 (0x17) ,请求问题信息(Request Problem Information)标识符。 跟随其后的是用一个字节表示的 0 或 1。包含多个请求问题信息(Request Problem Information),或者 请求问题信息(Request Problem  Information)的值既不为 0 也不为 1 会造成协议错误(Protocol Error)。 如果没有请求问题信息(Request Problem Information) ,则请求问题默认值为 1。 客户端使用此值指示遇到错误时是否发送原因字符串(Reason String)或用户属性(User Properties)。 如果请求问题信息的值为 0,服务端可以选择在 CONNACK 或 DISCONNECT 报文中返回原因字符串 (Reason String)或用户属性(User Properties),但不能在除 PUBLISH ,CONNACK 或 DISCONNECT 之外的报文中发送原因字符串(Reason String)或用户属性(User Properties) [MQTT-    3.1.2-29]。如果此值为 0 ,并且在除 PUBLISH ,CONNACK 或 DISCONNECT 之外的报文中收到了原因字 符串(Reason String)或用户属性(User Properties),客户端将发送一个包含原因码 0x82(协议错误) 的 DISCONNECT 报文给服务端,如4.13节所述。 如果此值为 1,服务端可以在任何被允许的报文中返回原因字符串(Reason String)或用户属性(User Properties)。 3.1.2.11.8 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。 用户属性(User Property)可以出现多次, 表示多个名字/值对。相同的名字可以出现多次。 非规范评注 CONNECT 报文中的用户属性可以被用来发送客户端到服务端的连接相关的属性。这些属性的意义 本规范不做定义。 3.1.2.11.9 认证方法 21 (0x15) ,认证方法(Authentication Method)标识符。 跟随其后的是一个 UTF-8 编码的字符串, 包含了扩展认证的认证方法(Authentication Method)名称。包 含多个认证方法将造成协议错误(协议错误)。 如果没有认证方法,则不进行扩展验证。参考4.12节。 如果客户端在 CONNECT 报文中设置了认证方法,则客户端在收到 CONNACK 报文之前不能发送除 AUTH 或 DISCONNECT 之外的报文 [MQTT-3.1.2-30]。 3.1.2.11.10 认证数据 22 (0x16) ,认证数据(Authentication Data)标识符。 跟随其后的是二进制的认证数据。没有认证方法却包含了认证数据(Authentication Data), 或者包含多个 认证数据(Authentication Data)将造成协议错误(Protocol Error)。 认证数据的内容由认证方法定义,关于扩展认证的更多信息,请参考4.12节。 3.1.2.12 可变报头非规范示例 图 3-6 - 可变报头示例  说明76543210协议名 Protocol Namebyte 1长度 Length MSB (0)00000000byte 2长度 Length LSB (4)00000100byte 3‘M’01001101byte 4‘Q’01010001byte 5‘T’01010100byte 6‘T’01010100协议版本 Protocol Version 说明76543210byte 7版本 Version (5)00000101连接标志 Connect Flags     byte 8用户名标志 User Name Flag (1)密码标志 Password Flag (1)遗嘱保留标志 Will Retain (0)遗嘱服务质量 Will QoS (01)遗嘱标志 Will Flag (1)新开始 Clean Start(1)保留Reserved (0)     1     1     0     0     1     1     1     0保持连接 Keep Alivebyte 9保持连接 Keep Alive MSB (0)00000000byte 10保持连接 Keep Alive LSB (10)00001010属性 Propertiesbyte 11长度 Length (5)00000101byte 12会话过期间隔标识符 (17)00010001byte 13会话过期间隔Session Expiry Interval (10)00000000byte 1400000000byte 1500000000 byte 16 00001010 3.1.3 CONNECT 载荷 CONNECT 报文的载荷中包含由可变报头(Variable Header)中的标志确定的一个或多个以长度为前缀的 字段。这些字段若存在,必须按照客户标识符(Client Identifier)、遗嘱属性(Will Properties) 、遗嘱主 题(Will Topic) 、遗嘱载荷(Will Payload)、用户名(User Name) 、密码(Password)的顺序出现 [MQTT-3.1.3- 1]。 3.1.3.1 客户标识符 服务端使用客户标识符(ClientID )识别客户端。连接服务端的每个客户端都有唯一的客户标识符 (ClientID)。 客户端和服务端都必须使用客户标识符(ClientID)识别两者之间的 MQTT 会话相关的状态 [MQTT-3.1.3-2]。更多关于会话状态的信息请参考4.1节。 客户标识符必须存在,且作为 CONNECT 报文载荷的第一个字段出现 [MQTT-3.1.3-3]。 客户标识符必须被编码为1.5.4节中所定义的 UTF-8 字符串 [MQTT-3.1.3-4]。 服务端必须允许 1 到 23 个字节长的 UTF-8 编码的客户标识符,客户标识符只能包含这些字符: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"  (大写字母、小写字母 和数字)  [MQTT-3.1.3-5]。 服务端可以允许编码后超过 23 个字节的客户标识符 (ClientID)。服务端可以允许包含不是上面列表字符的 客户标识符 (ClientID)。 服务端可以允许客户端提供一个零字节的客户标识符 (ClientID) ,如果这样做了, 服务端必须将这看作特殊 情况并分配唯一的客户标识符给那个客户端 [MQTT-3.1.3-6]。然后它必须假设客户端提供了那个唯一的客  户标识符,正常处理这个 CONNECT 报文 [MQTT-3.1.3-7]。 如果服务端拒绝了某个客户标识符(ClientID), 它可以发送包含原因码 0x85(客户标识符无效)的 CONNACK 报文作为对客户端的 CONNECT 报文的回应,如4.13节所述。之后必须关闭网络连接 [MQTT-3.1.3-8]。 非规范评注 客户端在实现时可以提供一个便于生成随机客户标识符的算法。使用此算法时,客户端需要注意避 免创建长期孤儿会话。 3.1.3.2 遗嘱属性 如果遗嘱标志(Will Flag)被设置为 1,有效载荷的下一个字段是遗嘱属性(Will Properties) 。遗嘱属性 字段定义了遗嘱消息(Will Message)将何时被发布, 以及被发布时的应用消息(Application Message) 属性。遗嘱属性包括属性长度和属性。 3.1.3.2.1 属性长度 遗嘱属性(Will Properties)中的属性长度被编码为可变长字节整数。 3.1.3.2.2 遗嘱延时间隔 24 (0x18) ,遗嘱延时间隔(Will Delay Interval)标识符。 跟随其后的是由四字节整数表示的以秒为单位的遗嘱延时间隔(Will Delay Interval)。包含多个遗嘱延时 间隔将造成协议错误(Protocol Error)。如果没有设置遗嘱延时间隔,遗嘱延时间隔默认值将为 0,即不 用延时发布遗嘱消息(Will Message)。 服务端将在遗嘱延时间隔(Will Delay Interval)到期或者会话(Session)结束时发布客户端的遗嘱消息  (Will Message) ,取决于两者谁先发生。 如果某个会话在遗嘱延时间隔到期之前创建了新的网络连接,  则服务端不能发送遗嘱消息 [MQTT-3.1.3-9]。 非规范评注 遗嘱时间间隔的一个用途是避免在频繁的网络连接临时断开时发布遗嘱消息, 因为客户端往往会很 快重新连上网络并继续之前的会话。 非规范评注 如果某个连接到服务端的网络连接使用已存在的客户标识符, 此已存在的网络连接的遗嘱消息将会 被发布, 除非新的网络连接设置了新开始(Clean Start)为 0 并且遗嘱延时大于 0。如果遗嘱延时 为 0,遗嘱消息将在网络连接断开时发布。如果新开始为 1,遗嘱消息也将被发布,因为此会话已 结束。 3.1.3.2.3 载荷格式指示 1 (0x01) ,载荷格式指示(Payload Format Indicator)标识符。 跟随载荷格式指示(Payload Format Indicator )之后的可能是: .     0 (0x00),表示遗嘱消息(Will Message)是未指定的字节,等同于不发送载荷格式指示。 .     1 (0x01),表示遗嘱消息(Will Message)是 UTF-8 编码的字符数据。载荷中的 UTF-8 数据必须 按照 Unicode规范[Unicode] 和 RFC 3629[RFC3629]中的申明进行编码。 包含多个载荷格式指示(Payload Format Indicator)将造成协议错误(Protocol Error)。服务端可以按照   格式指示对遗嘱消息(Will Message)进行验证,如果验证失败发送一条包含原因码 0x99(载荷格式无效) 的 CONNACK 报文。如4.13节所述。 3.1.3.2.4 消息过期间隔 2 (0x02) ,消息过期间隔(Message Expiry Interval)标识符。 跟随其后的是表示消息过期间隔(Message Expiry Interval)的四字节整数。包含多个消息过期间隔将导致 协议错误(Protocol Error)。 如果设定了消息过期间隔(Message Expiry Interval) ,四字节整数描述了遗嘱消息的生命周期(秒), 并 在服务端发布遗嘱消息时被当做发布过期间隔(Publication Expiry Interval)。 如果没有设定消息过期间隔,服务端发布遗嘱消息时将不发送消息过期间隔(Message Expiry Interval)。 3.1.3.2.5 内容类型 3 (0x03),内容类型(Content Type)标识符。 跟随其后的是一个以 UTF-8 格式编码的字符串,用来描述遗嘱消息(Will Message)的内容。包含多个内 容类型(Content Type)将造成协议错误(Protocol Error)。内容类型的值由发送应用程序和接收应用程 序确定。 3.1.3.2.6 响应主题 8 (0x08),响应主题(Response Topic)标识符。 跟随其后的是一个以 UTF-8 格式编码的字符串,用来表示响应消息的主题名(Topic Name)。包含多个响 应主题(Response Topic)将造成协议错误。响应主题的存在将遗嘱消息(Will Message)标识为一个请  求报文。 更多关于请求/响应的内容, 参考4.10 节。 3.1.3.2.7 对比数据 9 (0x09) ,对比数据(Correlation Data)标识符。 跟随其后的是二进制数据。对比数据被请求消息发送端在收到响应消息时用来标识相应的请求。包含多个  对比数据将造成协议错误(Protocol Error)。如果没有设置对比数据, 则请求方(Requester)不需要任何 对比数据。 对比数据只对请求消息(Request Message)的发送端和响应消息(Response Message)的接收端有意 义。 更多关于请求/响应的内容, 参考4.10节。 3.1.3.2.8 用户属性 38 (0x26),用户属性(User Property)标识符。 跟随其后的是一个 UTF-8 字符串对。用户属性(User Property)可以出现多次,表示多个名字/值对。相同 的名字可以出现多次。 服务端在发布遗嘱消息(Will Message)时必须维护用户属性(User Properties)的顺序 [MQTT-3.1.3- 10]。 非规范评注 此属性旨在提供一种传递应用层名称-值标签的方法, 其含义和解释仅由负责发送和接收它们的应 用程序所有。 3.1.3.3 遗嘱主题 如果遗嘱标志(Will Flag)被设置为 1,遗嘱主题(Will Topic)为载荷中下一个字段。 Topic)必须为 UTF-8 编码的字符串,如1.5.4节所定义 [MQTT-3.1.3- 11]。 遗嘱主题(Will 3.1.3.4 遗嘱载荷 如果遗嘱标志(Will Flag)被设置为 1,遗嘱载荷(Will Payload)为载荷中下一个字段。遗嘱载荷定义了 将要发布到遗嘱主题(Will Topic)的应用消息载荷,如3.1.2.5节所定义。此字段为二进制数据。 3.1.3.5 用户名 如果用户名标志(User Name Flag)被设置为 1,用户名(User Name)为载荷中下一个字段。用户名必 须是1.5.4节定义的 UTF-8 编码字符串 [MQTT-3.1.3- 12]。服务端可以将它用于身份验证和授权。 3.1.3.6 密码 如果密码标志(Password Flag)被设置为 1,密码(Password)为载荷中下一个字段。密码字段是二进 制数据, 尽管被称为密码, 但可以被用来承载任何认证信息。 3.1.4 CONNECT 行为 注意:服务端可以在同一个 TCP 端口或其他网络端点上支持多种协议(包括 MQTT 协议的早期版本)。 如果服务端确定协议是 MQTT v5.0,那么它按照下面的方法验证连接请求。 1.    网络连接建立后,如果服务端在合理的时间内没有收到 CONNECT 报文, 服务端应该关闭这个连 接。 2.   服务端必须按照3.1节的要求验证 CONNECT 报文, 如果报文不符合规范, 服务端关闭网络连接  [MQTT-3.1.4- 1] 。服务端可以在关闭网络连接之前发送包含3.1.2.4节所述的 0x80 及以上原因码的 CONNACK 报文。 3.   服务端可以检查 CONNECT  报文的内容是不是满足任何进一步的限制, 应该执行身份验证和授权  检查。如果任何一项检查没通过,服务端必须关闭网络连接 [MQTT-3.1.4-2]。在关闭网络连接之前, 服务端可以发送一个合适的包含如3.2节和4.13节所述的 0x80 及以上原因码的 CONNACK 报文。 如果验证成功, 服务端会执行下列步骤。 1.   如果客户标识符(ClientID)所代表的客户端已经连接到此服务端,那么向原有的客户端发送一个 包含原因码为 0x8E(会话被接管)的 DISCONNECT 报文,并且必须关闭原有的网络连接 [MQTT-3.1.4-3]。如果原有客户端存在遗嘱消息(Will Message),遗嘱消息按照3.1.2.5节所描 述的方式发布。 非规范评注 如果原有网络连接包含遗嘱消息, 且遗嘱延时间隔为 0,则遗嘱消息会在此网络连接被关闭时发送。 如果原有网络连接会话过期间隔为 0,或者新网络连接新开始标志设置为 1 且原有网络连接包含遗   嘱消息, 则遗嘱消息会被发送,因为原有会话已结束。 2.   服务端必须按照3.1.2.4节所描述的方式对新开始标志进行处理[MQTT-3.1.4-4]。 3.   服务端必须使用包含原因码为 0x00(成功)的 CONNACK 报文对客户端的 CONNECT 报文进行 确认 [MQTT-3.1.4-5]。 非规范评注 如果服务端被用来处理商业关键数据,推荐对网络连接进行认证和授权。如果认证和授权成功,服 务端可通过发送包含原因码为 0x00(成功)的 CONNACK 报文进行响应,否则建议服务端根本不 要发送 CONNACK 报文, 因为这是一种潜在的对 MQTT 服务端的攻击,可以被用来进行拒绝服务 攻击或密码猜测攻击。 4.   开始消息分发和保持连接状态监视。 允许客户端在发送 CONNECT 报文之后立即发送其它的 MQTT 控制报文; 客户端不需要等待服务端的 CONNACK 报文。 如果服务端拒绝了 CONNECT 报文,它不能处理客户端在 CONNECT 报文之后发送的 任何除 AUTH 以外的报文 [MQTT-3.1.4-6]。 非规范评注 客户端通常会等待 CONNACK 报文。然而, 如果在收到 CONNACK 报文之前就自由的发送其它 MQTT 控制报文将会简化客户端的实现,因为它不必监督连接的状态。如果连接被拒绝了, 客户端 在接收 CONNACK 报文之前发送的任何数据将不会被服务端所处理。 非规范评注 选择在收到 CONNACK 报文之前就发送 MQTT 控制报文的客户端将不知道服务端所存在的约束以及 会话是否被使用。 非规范评注 服务端在对某个客户端完成认证之前,可以选择限制读取该客户端的网络数据或者关闭该客户端的 网络连接。这是一种避免拒绝服务攻击的方法。 3.2 CONNACK – 确认连接请求 CONNACK 报文由服务端所发送,作为对来自客户端的 CONNECT 报文的响应。 服务端在发送任何除 AUTH 以外的报文之前必须先发送包含原因码为 0x00 (成功) 的 CONNACK 报文 [MQTT-3.2.0- 1] 。服务 端在一次网络连接中不能发送多个 CONNACK 报文 [MQTT-3.2.0-2]。 如果客户端在合理的时间内没有收到服务端的 CONNACK 报文, 客户端应该关闭网络连接。合理的时间取 决于应用的类型和通信基础设施。 3.2.1 CONNACK 固定报头 固定报头的格式见图 3-7 的描述。 图 3-7 – CONNACK 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (2)Reserved 保留位 00100000byte 2剩余长度 剩余长度字段 用变长字节整数来编码,表示可变报头的长度。 3.2.2 CONNACK 可变报头 CONNACK 报文的可变报头按顺序包含以下字段: 连接确认标志(Connect Acknowledge Flags) ,连接 原因码(Reason Code) ,属性(Properties) 。属性的编码规则如2.2.2节所描述。 3.2.2.1 连接确认标志 第 1 个字节是连接确认标志,位 7- 1 是保留位且必须设置为 0 [MQTT-3.2.2- 1] 。 第 0(SP)位是会话存在标志(Session Present Flag)。 3.2.2.1.1 会话存在 位置: 连接确认标志(Connect Acknowledge Flags)的第 0 位。 会话存在(Session Present)标志通知客户端, 服务端是否正在使用此客户标识符之前连接的会话状态 (Session State)。会话存在标志使服务端和客户端在是否有已存储的会话状态上保持一致。 如果服务端接受一个新开始(Clean Start)为 1 的连接,服务端在 CONNACK 报文中除了把原因码设置为 0x00(成功)之外,还必须把会话存在标志设置为 0 [MQTT-3.2.2-2]。 如果服务端接受一个新开始(Clean Start)为 0 的连接,并且服务端已经保存了此客户标识符(ClientID) 的会话状态(Session State),服务端在 CONNACK 报文中必须把会话存在标志设置为 1。否则,服务端 必须把会话存在标志设置为 0。无论如何, 服务端在 CONNACK 报文中必须把原因码设置为 0x00 (成功) [MQTT-3.2.2-3]。 如果客户端从服务端接收到的会话存在标志值与预期的不同,客户端做如下处理: .     如果客户端没有保存的会话状态,但收到会话存在标志为 1,客户端必须关闭网络连接 [MQTT-     3.2.2-4] 。 如果希望重新开始一个新的会话,客户端可以使用新开始(Clean Start)为 1 并重新连 接服务端。 .     如果客户端保存了会话状态,但收到的会话存在标志为 0,客户端若要继续此网络连接,它必须丢 弃其保存的会话状态 [MQTT-3.2.2-5]。 如果服务端发送的 CONNACK 报文中原因码非 0,它必须把会话存在标志设置为 0 [MQTT-3.2.2-6]。 3.2.2.2 连接原因码 可变报头中第 2 个字节是连接原因码(Reason Code)。 连接原因码(Reason Code)的值如下所示。如果服务端收到一个格式正确的 CONNECT 报文, 但服务端 无法完成连接的创建, 服务端可以发送一个包含适当的连接原因码的 CONNACK 报文。 如果服务端发送了 一个包含原因码大于等于 128 的 CONNACK 报文, 它随后必须关闭网络连接 [MQTT-3.2.2-7]。 表 3- 1 - 连接原因码 值16 进制原因码名称说明00x00成功连接被接受。1280x80未指明的错误服务端不愿透露的错误,或者没有适用的原因码。1290x81无效报文CONNECT 报文内容不能被正确的解析。1300x82协议错误CONNECT 报文内容不符合本规范。1310x83实现特定错误CONNECT 有效, 但不被服务端所接受。1320x84协议版本不支持服务端不支持客户端所请求的 MQTT 协议版本。1330x85客户标识符无效客户标识符有效,但未被服务端所接受。1340x86用户名密码错误客户端指定的用户名密码未被服务端所接受。1350x87未授权客户端未被授权连接。1360x88服务端不可用MQTT 服务端不可用。1370x89服务端正忙服务端正忙,请重试。1380x8A禁止客户端被禁止, 请联系服务端管理员。1400x8C无效的认证方法认证方法未被支持,或者不匹配当前使用的认证方法。1440x90主题名无效遗嘱主题格式正确,但未被服务端所接受。1490x95报文过长CONNECT 报文超过最大允许长度。1510x97超出配额已超出实现限制或管理限制。 1530x99载荷格式无效遗嘱载荷数据与载荷格式指示符不匹配。1540x9A不支持保留遗嘱保留标志被设置为 1,但服务端不支持保留消息。1550x9B不支持的 QoS 等级服务端不支持遗嘱中设置的 QoS 等级。1560x9C(临时) 使用其他服务端客户端应该临时使用其他服务端。1570x9D服务端已 (永久)移动客户端应该永久使用其他服务端1590x9F超出连接速率限制超出了所能接受的连接速率限制。 服务端发送的 CONNACK 报文必须设置一种原因码 [MQTT-3.2.2-8]。 非规范评注 原因码 0x80(未指明的错误)可以被用作:服务器知道失败的原因但是并不希望透露给客户端, 或者没有其他适用的原因码。 出于安全考虑, 发现 CONNECT 出错时服务端可以选择不发送 CONNACK 报文而关闭网络连接。 例如,在公网中向未被授权的网络连接告知自身 MQTT 服务端身份并不明智。 3.2.2.3 CONNACK 属性 3.2.2.3.1 属性长度 CONNACK 报文可变报头中的属性长度,编码为变长字节整数。 3.2.2.3.2 会话过期间隔 17 (0x11) ,会话过期间隔(Session Expiry Interval)标识符。 跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。包含多个会话 过期间隔(Session Expiry Interval)将造成协议错误(Protocol Error)。 如果会话过期间隔(Session Expiry Interval)值未指定,则使用 CONNECT 报文中指定的会话过期时间间 隔。服务端使用此属性通知客户端它使用的会话过期时间间隔与客户端在 CONNECT 中发送的值不同。更 详细的关于会话过期时间的描述,请参考3.1.2.11.2节 。 3.2.2.3.3 接收最大值 33 (0x21) ,接收最大值(Receive Maximum)描述符。 跟随其后的是由双字节整数表示的最大接收值。包含多个接收最大值或接收最大值为 0 将造成协议错误 (Protocol Error)。 服务端使用此值限制服务端愿意为该客户端同时处理的 QoS 为 1 和 QoS 为 2 的发布消息最大数量。没有 机制可以限制客户端试图发送的 QoS 为 0 的发布消息。 如果没有设置最大接收值, 将使用默认值 65535。 关于接收最大值的详细使用,参考4.9节流控部分。 3.2.2.3.4 最大服务质量 36 (0x24) ,最大服务质量(Maximum QoS)标识符。 跟随其后的是用一个字节表示的 0 或 1。包含多个最大服务质量(Maximum QoS)或最大服务质量既不为 0 也不为 1 将造成协议错误。如果没有设置最大服务质量,客户端可使用最大 QoS 为 2。 如果服务端不支持 Qos 为 1 或 2 的 PUBLISH 报文, 服务端必须在 CONNACK 报文中发送最大服务质量以 指定其支持的最大 QoS 值 [MQTT-3.2.2-9] 。即使不支持 QoS 为 1 或 2 的 PUBLISH 报文, 服务端也必须  接受请求 QoS 为 0 、1 或 2 的 SUBSCRIBE 报文 [MQTT-3.2.2- 10]。 如果从服务端接收到了最大 QoS 等级,则客户端不能发送超过最大 QoS 等级所指定的 QoS 等级的 PUBLISH 报文 [MQTT-3.2.2- 11]。服务端接收到超过其指定的最大服务质量的 PUBLISH 报文将造成协议 错误(Protocol Error)。 这种情况下应使用包含原因码为 0x9B(不支持的 QoS 等级)的 DISCONNECT 报文进行处理, 如4.13节所述。 如果服务端收到包含遗嘱的 QoS 超过服务端处理能力的 CONNECT 报文,服务端必须拒绝此连接。服务  端应该使用包含原因码为 0x9B(不支持的 QoS 等级)的 CONNACK 报文进行错误处理, 随后必须关闭网 络连接。 4.13节所述 [MQTT-3.2.2- 12]。 非规范评注 客户端不必支持 QoS 为 1 和 2 的 PUBLISH 报文。客户端只需将其发送的任何 SUBSCRIBE 报文 中的 QoS 字段限制在其支持的最大服务质量以内即可。 3.2.2.3.5 保留可用 37 (0x25) ,保留可用(Retain Available)标识符。 跟随其后的是一个单字节字段,用来声明服务端是否支持保留消息。值为 0 表示不支持保留消息, 为 1 表 示支持保留消息。如果没有设置保留可用字段,表示支持保留消息。包含多个保留可用字段或保留可用字 段值不为 0 也不为 1 将造成协议错误(Protocol Error)。 如果服务端收到一个包含保留标志位 1 的遗嘱消息的 CONNECT 报文且服务端不支持保留消息, 服务端必 须拒绝此连接请求, 且应该发送包含原因码为 0x9A(不支持保留)的 CONNACK 报文,随后必须关闭网 络连接 [MQTT-3.2.2- 13]。 从服务端接收到的保留可用标志为 0 时, 客户端不能发送保留标志设置为 1 的 PUBLISH 报文 [MQTT- 3.2.2- 14] 。如果服务端收到这种 PUBLISH 报文,将造成协议错误(Protocol Error),此时服务端应该发 送包含原因码为 0x9A (不支持保留)的 DISCONNECT 报文,如4.13节所述。 3.2.2.3.6 最大报文长度 39 (0x27) ,最大报文长度(Maximum Packet Size)标识符。 跟随其后的是由四字节整数表示的服务端愿意接收的最大报文长度(Maximum Packet Size)。如果没有 设置最大报文长度,则按照协议由固定报头中的剩余长度可编码最大值和协议报头对数据包的大小做限制。 包含多个最大报文长度(Maximum Packet Size) ,或最大报文长度为 0 将造成协议错误(Protocol Error)。 如2.1.4节所述, 最大报文长度是 MQTT 控制报文的总长度。服务端使用最大报文长度通知客户端其所能 处理的单个报文长度限制。 客户端不能发送超过最大报文长度(Maximum Packet Size)的报文给服务端 [MQTT-3.2.2- 15]。收到长度 超过限制的报文将导致协议错误,此时服务端应该发送包含原因码 0x95 (报文过长)的 DISCONNECT 报 文给客户端,详见4.13节。 3.2.2.3.7 分配客户标识符 18 (0x12) ,分配客户标识符(Assigned Client Identifier)标识符。 跟随其后的是 UTF-8 编码的分配客户标识符(Assigned Client Identifier)字符串。包含多个分配客户标识 符将造成协议错误(Protocol Error)。 服务端分配客户标识符的原因是 CONNECT 报文中的客户标识符长度为 0。 如果客户端使用长度为 0 的客户标识符(ClientID), 服务端必须回复包含分配客户标识符(Assigned Client Identifier)的 CONNACK 报文。分配客户标识符必须是没有被服务端的其他会话所使用的新客户标 识符 [MQTT-3.2.2- 16]。 3.2.2.3.8 主题别名最大值 34 (0x22) ,主题别名最大值(Topic Alias Maximum)标识符。 跟随其后的是用双字节整数表示的主题别名最大值(Topic Alias Maximum)。包含多个主题别名最大值 (Topic Alias Maximum)将造成协议错误(Protocol Error)。没有设置主题别名最大值属性的情况下, 主 题别名最大值默认为零。 此值指示了服务端能够接收的来自客户端的主题别名(Topic Alias)最大值。服务端使用此值来限制本次 连接可以拥有的主题别名的值。客户端在一个 PUBLISH 报文中发送的主题别名值不能超过服务端设置的主 题别名最大值(Topic Alias Maximum) [MQTT-3.2.2- 17]。值为 0 表示本次连接服务端不接受任何主题别  名(Topic Alias)。 如果主题别名最大值(Topic Alias)没有设置,或者设置为 0,则客户端不能向此服务 端发送任何主题别名(Topic Alias) [MQTT-3.2.2- 18]。 3.2.2.3.9 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。 如果加上原因字符串之后的 CONNACK 报文长度超出了客户端指 定的最大报文长度,则服务端不能发送此原因字符串 [MQTT-3.2.2- 19] 。包含多个原因字符串将造成协议错 误(Protocol Error)。 非规范评注 客户端对原因字符串的恰当使用包括:抛出异常时使用此字符串,或者将此字符串写入日志。 3.2.2.3.10 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户 属性之后的 CONNACK 报文长度超出了客户端指定的最大报文长度, 则服务端不能发送此属性 [MQTT- 3.2.2-20]。用户属性(User Property)允许出现多次,以表示多个名字/值对, 且相同的名字可以多次出现。 用户属性的内容和意义本规范不做定义。 CONNACK 报文的接收端可以选择忽略此属性。 3.2.2.3.11 通配符订阅可用 40 (0x28) ,通配符订阅可用(Wildcard Subscription Available)标识符。 跟随其后的是一个单字节字段,用来声明服务器是否支持通配符订阅(Wildcard Subscriptions)。值为 0 表示不支持通配符订阅,值为 1 表示支持通配符订阅。如果没有设置此值,则表示支持通配符订阅。包含 多个通配符订阅可用属性, 或通配符订阅可用属性值不为 0 也不为 1 将造成协议错误(Protocol Error)。 如果服务端在不支持通配符订阅(Wildcard Subscription)的情况下收到了包含通配符订阅的 SUBSCRIBE 报文,将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为 0xA2  (通配符订阅不支持) 的 DISCONNECT 报文, 如4.13节所述。 服务端在支持通配符订阅的情况下仍然可以拒绝特定的包含通配符订阅的订阅请求。这种情况下, 服务端 可以发送一个包含原因码为 0xA2(通配符订阅不支持) 的 SUBACK 报文。 3.2.2.3.12 订阅标识符可用 41 (0x29) ,订阅标识符可用(Subscription Identifier Available)标识符。 跟随其后的是一个单字节字段,用来声明服务端是否支持订阅标识符(Subscription Identifiers)。值为 0 表示不支持订阅标识符,值为 1 表示支持订阅标识符。如果没有设置此值,则表示支持订阅标识符。包含 多个订阅标识符可用属性, 或订阅标识符可用属性值不为 0 也不为 1 将造成协议错误(Protocol Error)。 如果服务端在不支持订阅标识符(Subscription Identifier)的情况下收到了包含订阅标识符的 SUBSCRIBE 报文,将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为 0xA1  (订阅标识符不支持) 的 DISCONNECT 报文, 如4.13节所述。 3.2.2.3.13 共享订阅可用 42 (0x2A) ,共享订阅可用(Shared Subscription Available)标识符。 跟随其后的是一个单字节字段,用来声明服务端是否支持共享订阅(Shared Subscription)。值为 0 表示 不支持共享订阅,值为 1 表示支持共享订阅。如果没有设置此值,则表示支持共享订阅。包含多个共享订 阅可用(Shared Subscription Available) ,或共享订阅可用属性值不为 0 也不为 1 将造成协议错误 (Protocol Error)。 如果服务端在不支持共享订阅(Shared Subscription)的情况下收到了包含共享订阅的 SUBSCRIBE 报文, 将造成协议错误(Protocol Error)。此时服务端将发送包含原因码为 0x9E(共享订阅不支持)的 DISCONNECT 报文, 如4.13节所述。 3.2.2.3.14 服务端保持连接 19 (0x13) ,服务端保持连接(Server Keep Alive)标识符。 跟随其后的是由服务端分配的双字节整数表示的保持连接(Keep Alive)时间。 如果服务端发送了服务端保 持连接(Server Keep Alive)属性, 客户端必须使用此值代替其在 CONNECT 报文中发送的保持连接时间 值 [MQTT-3.2.2-21] 。如果服务端没有发送服务端保持连接属性,服务端必须使用客户端在 CONNECT 报 文中设置的保持连接时间值 [MQTT-3.2.2-22]。包含多个服务端保持连接属性将造成协议错误(Protocol Error)。 非规范评注 服务端保持连接属性的主要作用是通知客户端它将会比客户端指定的保持连接更快的断开非活动的 客户端。 3.2.2.3.15 响应信息 26 (0x1A) ,响应信息(Response Information)标识符。 跟随其后的是一个以 UTF-8 编码的字符串, 作为创建响应主题(Response Topic)的基本信息。关于客户 端如何根据响应信息(Response Information)创建响应主题不在本规范的定义范围内。包含多个响应信息 将造成协议错误(Protocol Error)。 如果客户端发送的请求响应信息(Request Response Information)值为 1,则服务端在 CONNACK 报文 中发送响应信息(Response Information)为可选项。 非规范评注 响应信息通常被用来传递主题订阅树的一个全局唯一分支,此分支至少在该客户端的会话生命周期 内为该客户端所保留。请求客户端和响应客户端的授权需要使用它,所以它通常不能仅仅是一个随 机字符串。一般把此分支作为特定客户端的订阅树根节点。 通常此信息需要正确配置,以使得服务 器能返回信息。使用此机制时,具体的信息一般由服务端来进行统一配置,而非由各个客户端自己 配置。 更多关于请求/响应的信息, 请参考4.10节 。 3.2.2.3.16 服务端参考 28 (0x1C) ,服务端参考(Server Reference)标识符。 跟随其后的是一个以 UTF-8 编码的字符串,可以被客户端用来标识其他可用的服务端。包含多个服务端参 考(Server Reference)将造成协议错误(Protocol Error)。 服务端在包含了原因码为 0x9C( (临时) 使用其他服务端)或 0x9D(服务端已(永久) 移动) 的 CONNACK 报文或 DISCONNECT 报文中设置服务端参考,如4.13节所述。 关于如何使用服务端参考, 请参考4.11节服务端重定向信息。 3.2.2.3.17 认证方法 21 (0x15) ,认证方法(Authentication Method)标识符。 跟随其后的是一个以 UTF-8 编码的字符串, 包含了认证方法(Authentication Method)名。包含多个认证 方法将造成协议错误(Protocol Error)。更多关于扩展认证的信息, 请参考4.12节 。 3.2.2.3.18 认证数据 22 (0x16) ,认证数据(Authentication Data)标识符。 跟随其后的是包含认证数据(Authentication Data)的二进制数据。此数据的内容由认证方法和已交换的认 证数据状态定义。包含多个认证数据将造成协议错误(Protocol Error)。更多关于扩展认证的信息,请参  考4.12节 。 3.2.3 CONNACK 载荷 CONNACK 报文没有有效载荷。 3.3 PUBLISH – 发布消息 PUBLISH 报文是指从客户端向服务端或者服务端向客户端传输一个应用消息。 3.3.1 PUBLISH 固定报头 图 3-8 – PUBLISH 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (3)DUPQoS 等级RETAIN 0011XXXXbyte 2 …剩余长度 3.3.1.1 重发标志 位置: 第 1 个字节,第 3 位。 如果 DUP 标志被设置为 0,表示这是客户端或服务端第一次请求发送这个 PUBLISH 报文。如果 DUP 标志 被设置为 1,表示这可能是一个早前报文请求的重发。 客户端或服务端请求重发一个 PUBLISH 报文时,必须将 DUP 标志设置为 1 [MQTT-3.3.1- 1] 。对于 QoS 为 0 的消息, DUP 标志必须设置为 0 [MQTT-3.3.1-2]。 服务端发送 PUBLISH 报文给订阅者时,收到(入站) 的 PUBLISH 报文的 DUP 标志的值不会被传播。 发 送(出站)的 PUBLISH 报文与收到(入站)的 PUBLISH 报文中的 DUP 标志是独立设置的,它的值必须 单独的根据发送(出站)的 PUBLISH 报文是否是一个重发来确定 [MQTT-3.3.1-3]。 非规范评注 接收者收到一个 DUP 标志位 1 的 MQTT 控制报文时,不能假设它看到了一个这个报文之前的一个 副本。 非规范评注 需要特别指出的是, DUP 标志关注的是 MQTT 控制报文本身,与它包含的应用消息无关。当使用 QoS 1 时, 客户端可能会收到一个 DUP 标志为 0 的 PUBLISH 报文,这个报文包含一个它之前收  到过的应用消息的副本,但是用的是不同的报文标识符。2.2.1节提供了有关报文标识符的更多信 息。 3.3.1.2 服务质量等级 位置: 第 1 个字节,第 2- 1 位。 这个字段表示应用消息分发的服务质量(QoS)等级保证。服务质量等级在下表中列出。 表 3-2 - QoS 定义 QoS 值Bit 2Bit 1说明000最多分发一次101至少分发一次210仅分发一次-11保留 – 不能使用 如果服务端在对客户端响应的 CONNACK 报文中包含了最大服务质量(Maximum QoS)且服务端收到的 PUBLISH 报文的 QoS 大于此最大服务质量,服务端发送包含原因码为 0x9B (不支持的 QoS 等级)的 DISCONNECT 报文, 如4.13节所述。 PUBLISH 报文的 2 个 QoS 比特位不能同时设置为 1 [MQTT-3.3.1-4]。如果服务端或客户端收到 QoS 2 个 比特位都为 1 的无效 PUBLISH 报文, 使用包含原因码为 0x81(无效报文) 的 DISCONNECT 报文关闭网 络连接, 如4.13节所述。 3.3.1.3 保留标志 位置: 第 1 个字节,第 0 位。 如果客户端发给服务端的 PUBLISH 报文的保留(Retain)标志被设置为 1,服务端必须存储此应用消息,  并用其替换此话题下任何已存在的消息 [MQTT-3.3.1-5],以便它可以被分发给未来的匹配此主题名(Topic Name)的订阅者。 如果载荷为空, 消息可以正常被服务端所处理,但是此话题下的任何保留消息必须被丢 弃,并且此话题未来的订阅者将不会收到保留消息 [MQTT-3.3.1-6] 。载荷为空的保留消息将不能被存储在  服务端 [MQTT-3.3.1-7]。 如果客户端发给服务端的 PUBLISH 报文的保留标志位为 0,服务器不能把此消息存储为保留消息,也不能 丢弃或替换任何已存在的保留消息 [MQTT-3.3.1-8]。 如果服务端发送给客户端的 CONNACK 报文中包含保留可用属性,且属性值为 0,但收到的 PUBLISH 报 文中保留标志位为 1,服务端使用包含原因码为 0x9A  (保留不支持) 的 DISCONNECT 报文断开网络连接, 如4.13节所述。 当一个新的非共享订阅(Non-shared Subscription)被创建时, 每个匹配的话题下的最新保留消息如果存 在,将根据保留消息订阅选项(Retain Handling Subscription Option)发送给客户端。这些消息在发送时 保留标志被设置为 1。保留消息的发送由保留消息处理订阅选项控制, 收到订阅时: .     如果保留消息处理属性被设置为 0,服务端必须发送主题与客户端订阅的主题过滤器(Topic  Filter) 相匹配的所有保留消息 [MQTT-3.3.1-9]。 .     如果保留消息处理属性被设置为 1,如果尚不存在匹配的订阅, 服务端必须发送主题与客户端订阅 的主题过滤器相匹配的所有保留消息。如果已存在相匹配的订阅,服务器不能发送这些保留消息  [MQTT-3.3.1- 10]。 .     如果保留消息处理属性被设置为 2,服务器不能发送这些保留消息 [MQTT-3.3.1- 11]。 订阅选项(Subscription Options)的定义,参考3.8.3.1节 。 如果服务端收到保留标志设置为 1 且 QoS 设置为 0 的 PUBLISH 报文,服务端应该把此 QoS 为 0 的消息存 储为其主题下最新的保留消息,但服务端可以选择在任何时间丢弃此消息。如果发生丢弃, 该主题下将不  存在任何保留消息。 如果某个主题当前的保留消息过期, 该主题下将不存在任何保留消息。 服务端转发应用消息时,保留标志位的设置由发布保留(Retain As Published)订阅选项决定。订阅选项 的定义, 请参考3.8.3.1节 。 . . 如果发布保留(Retain As Published)订阅选项被设置为 0,服务端在转发应用消息时必须将保留标志 设置为 0,而不管收到的 PUBLISH 报文中保留标志位如何设置的 [MQTT-3.3.1- 12]。 如果发布保留(Retain As Published)订阅选项被设置为 1,服务端在转发应用消息时必须将保留标志 设置为与收到的 PUBLISH 消息中的保留标志位相同 [MQTT-3.3.1- 13]。 非规范评注 对于发布者不定期发送状态消息这个场景, 保留消息很有用。新的非共享订阅者将会收到最近的状态。 3.3.1.4 剩余长度 等于可变报头的长度加上有效载荷的长度, 被编码为变长字节整数。 3.3.2 PUBLISH 可变报头 PUBLISH 报文可变报头按顺序包含:主题名(Topic Name),报文标识符(Packet Identifier), 属性 (Properties)。属性的编码规则如2.2.2节所述。 3.3.2.1 主题名 主题名(Topic Name)用于识别有效载荷数据应该被发布到哪一个信息通道。 主题名必须是 PUBLISH 报文可变报头的第一个字段。它必须是1.5.4节定义的 UTF-8 编码的字符串 [MQTT-3.3.2- 1]。 PUBLISH 报文中的主题名不能包含通配符 [MQTT-3.3.2-2]。 服务端发送给订阅客户端的 PUBLISH 报文中的主题名必须匹配该订阅的主题过滤器(Topic Filter),  如 4.7节所定义的匹配过程 [MQTT-3.3.2-3]。然而, 由于服务端允许将主题名映射为其他名字,主题名可能 与原始 PUBLISH 报文中的主题名不同。 发送端可以使用主题别名(Topic Alias)以便减少 PUBLISH 报文的长度。主题别名如3.3.2.3.4节所述。 主题名长度为 0 且没有主题别名,将造成协议错误(Protocol Error)。 3.3.2.2 报文标识符 只有当 QoS 等级是 1 或 2 时,报文标识符(Packet Identifier)字段才能出现在 PUBLISH 报文中。2.2.1 节提供了有关报文标识符的更多信息。 3.3.2.3 PUBLISH 属性 3.3.2.3.1 属性长度 PUBLISH 报文可变报头中的属性长度被编码为变长字节整数。 3.3.2.3.2 载荷格式指示 1 (0x01) ,载荷格式指示(Payload Format Indicator)标识符。 跟随其后的是单字节的载荷格式指示值,可以是: .     0 (0x00),说明载荷是未指定格式的字节, 相当于没有发送载荷格式指示。 .     1 (0x01),说明载荷是 UTF-8 编码的字符数据。载荷中的 UTF-8 数据必须是按照 Unicode [Unicode] 的规范和 RFC 3629[RFC3629]的重申进行编码。 服务端必须把接收到的应用消息中的载荷格式指示原封不动的发给所有的订阅者 [MQTT-3.3.2-4]。接收者 可以验证载荷数据与所指示的格式一致,如果不一致, 发送包含原因码为 0x99(载荷格式无效) 的 PUBACK ,PUBREC 或 DISCONNECT 报文,如4.13节所述。 3.3.2.3.3 消息过期间隔 2 (0x02) ,消息过期间隔(Message Expiry Interval)标识符。 跟随其后的是四字节整数表示的消息过期间隔(Message Expiry Interval)。 如果消息过期间隔存在,四字节整数表示以秒为单位的应用消息(Application Message)生命周期。如果  消息过期间隔(Message Expiry Interval)已过期,服务端还没开始向匹配的订阅者交付该消息, 则服务端 必须删除该订阅者的消息副本 [MQTT-3.3.2-5]。 如果消息过期间隔不存在, 应用消息不会过期。 服务端发送给客户端的 PUBLISH 报文中必须包含消息过期间隔,值为接收时间减去消息在服务端的等待时 间 [MQTT-3.3.2-6]。关于状态存储的细节和限制, 参考4.1节。 3.3.2.3.4 主题别名 35 (0x23) ,主题别名(Topic Alias)标识符。 跟随其后的是表示主题别名(Topic Alias)值的双字节整数。包含多个主题别名值将造成协议错误 (Protocol Error)。 主题别名是一个整数, 用来代替主题名对主题进行识别。主题别名可以减小 PUBLISH 报文的长度, 这对某 个网络连接中发送的很长且反复使用的主题名来说很有用。 发送端决定是否使用主题别名及别名值如何选取。发送端通过在 PUBLISH 报文中包含的非 0 长度主题名和  主题别名来设置主题别名映射。接收端正常处理该 PUBLISH 报文,但同样将指定的主题别名映射到主题名。 如果接收端已经设置了某个主题别名映射, 发送端可以发送包含主题别名和长度为 0 的主题名的 PUBLISH 报文。接收端把此 PUBLISH 报文的主题名当做其包含的主题别名所映射的主题名。 发送端可以通过在同一个网络连接中发送另一个包含同样主题别名和不同非 0 长度主题名的 PUBLISH 报文 来修改主题别名映射关系。 主题别名映射仅作用于某个网络连接及其生命周期内。 接收端不能将任何主题别名映射从一个网络连接转 发到另一个网络连接 [MQTT-3.3.2-7]。 主题别名不允许为 0 。发送端不能发送包含主题别名值为 0 的 PUBLISH 报文 [MQTT-3.3.2-8]。 客户端不能发送主题别名值大于服务端的 CONNACK 报文中指定的主题别名最大值(Topic Alias    Maximum)的 PUBLISH 报文 [MQTT-3.3.2-9] 。客户端必须接受所有值大于 0 且小于等于其发送的 CONNECT 报文中的主题别名最大值的主题别名 [MQTT-3.3.2- 10]。 服务端不能发送包含主题别名值大于客户端在 CONNECT 报文中指定的主题别名最大值(Topic Alias Maximum)的 PUBLISH 报文 [MQTT-3.3.2- 11] 。服务端必须接受所有值大于 0 且小于等于其发送的  CONNACK 报文中的主题别名最大值的主题别名 [MQTT-3.3.2- 12]。 客户端和服务端使用的主题别名映射相互独立。因此一般来说, 客户端发送给服务端的主题别名值为 1 的 PUBLISH 报文和服务端发送给客户端的主题别名值为 1 的 PUBLISH 报文,将被映射到不同的主题。 3.3.2.3.5 响应主题 8 (0x08) ,响应主题(Response Topic)标识符。 跟随其后的是一个 UTF-8 编码的字符串, 用作响应消息的主题名。 响应主题必须是按照1.5.4 节 所定义的 UTF-8 编码的字符串 [MQTT-3.3.2- 13] 。响应主题不能包含通配符 [MQTT-3.3.2- 14]。包含多个响应主题将 造成协议错误(Protocol Error)。响应主题的存在将消息标识为请求报文。 更多关于请求/响应的信息, 参考4.10节 。 服务端在收到应用消息时必须将响应主题原封不动的发送给所有的订阅者 [MQTT-3.3.2- 15]。 非规范评注 包含响应主题的应用消息接收端使用响应主题作为主题名,发送作为响应消息的 PUBLISH 报文。 如果请求消息中包含对比数据,接收端应当在发送作为对此请求消息进行响应的 PUBLISH 报文中 包含此对比数据。 3.3.2.3.6 对比数据 9 (0x09) ,对比数据(Correlation Data)标识符。 跟随其后的是二进制数据。对比数据被请求消息发送端在收到响应消息时用来标识相应的请求。包含多个  对比数据将造成协议错误(Protocol Error)。如果没有设置对比数据, 则请求方(Requester)不需要任何 对比数据。 服务端在收到应用消息时必须原封不动的把对比数据发送给所有的订阅者 [MQTT-3.3.2- 16]。对比数据只对 请求消息(Request Message)的发送端和响应消息(Response Message)的接收端有意义。 非规范评注 接收端收到包含响应主题和对比数据的应用消息时,发送以响应主题为主题名的 PUBLISH 报文作   为响应消息。客户端在响应消息中应将对比数据作为 PUBLISH 报文的一部分原封不动的发送出去。 非规范评注 如果对客户端响应消息中的对比数据所做的任何更改会造成应用程序错误,则应当对对比数据进行 加密/哈希,以便接收端能检测到对比数据是否被更改。 更多关于请求/响应的信息, 请参考4.10节。 3.3.2.3.7 用户属性 38 (0x26) ,用户属性(User Property)。 跟随其后的是 UTF-8 字符串对。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同 的名字可以多次出现。 服务端在转发应用消息到客户端时必须原封不动的把所有的用户属性放在 PUBLISH 报文中 [MQTT-3.3.2- 17] 。服务端在转发应用消息时必须保持所有用户属性的先后顺序 [MQTT-3.3.2- 18]。 非规范评注 此属性旨在提供一种传递应用层名称-值标签的方法, 其含义和解释仅由负责发送和接收它们的应 用程序所有。 3.3.2.3.8 订阅标识符 11 (0x0B),订阅标识符(Subscription Identifier)标识符。 跟随其后的是一个变长字节整数表示的订阅标识符。 订阅标识符取值范围从 1 到 268,435,455。订阅标识符的值为 0 将造成协议错误。如果某条发布消息匹配 了多个订阅,则将包含多个订阅标识符。这种情况下他们的顺序并不重要。 3.3.2.3.9 内容类型 3 (0x03) , 内容类型(Content Type)标识符。 跟随其后的是一个以 UTF-8 格式编码的字符串,用来描述应用消息的内容。 内容类型必须是 UTF-8 编码的 字符串, 如1.5.4节所定义 [MQTT-3.3.2- 19]。 包含多个内容类型将造成协议错误(Protocol  Error)。 内容类型的值由发送应用程序和接收应用程序确定。 服务端必须把收到的应用消息中的内容类型原封不动的发送给所有的订阅者 [MQTT-3.3.2-20]。 非规范评注 UTF-8 编码字符串可以使用一个 MIME 内容类型字符串来描述应用消息的内容。由于发送程序和接 收程序负责内容类型字符串的定义和解释, 因此 MQTT 服务端只确保内容类型是有效的 UTF-8 编  码的字符串,不会做其他方面的验证。 非规范评注 图 3-9 是一个 PUBLISH 示例报文, 其中主题名为 a/b,报文标识符为 10,没有属性。 图 3-9 - PUBLISH 报文可变报头非规范示例  说明76543210主题名byte 1长度 MSB (0)00000000byte 2长度 LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010报文标识符byte 6报文标识符 MSB (0)00000000byte 7报文标识符 LSB (10)00001010属性长度byte 8无属性00000000 3.3.3 PUBLISH 载荷 载荷包含将被发布的应用消息。载荷的内容和格式由应用程序指定。有效载荷的长度这样计算:用固定报 头中的剩余长度字段的值减去可变报头的长度。包含零长度有效载荷的 PUBLISH 报文是合法的。 3.3.4 PUBLISH 行为 PUBLISH 报文的接收端必须按照 PUBLISH 报文中的 QoS 等级发送响应报文 [MQTT-3.3.4- 1]。 表 3-3 - PUBLISH 报文的预期响应 服务质量等级预期响应QoS 0无响应QoS 1PUBACK 报文QoS 2PUBREC 报文 客户端使用 PUBLISH 报文发送应用消息给服务端,目的是分发到其他订阅匹配的客户端。 服务端使用 PUBLISH 报文发送应用消息给每一个订阅匹配的客户端。 PUBLISH 报文包含 SUBSCRIBE 报 文中承载的订阅标识符--如果存在的话。 客户端使用带通配符的主题过滤器请求订阅时,客户端的订阅可能会重叠,因此发布的消息可能会匹配多 个主题过滤器。 这种情况下,服务端必须按照所有匹配的订阅中最大的 QoS 等级把消息发送给客户端 [MQTT-3.3.4-2]。此外,服务端可以为每一个匹配的订阅按照订阅时的 QoS 等级,把消息副本分发给客户 端。 如果客户端收到一个未经请求的应用消息(没有匹配任何订阅) ,且 QoS 大于客户端指定的最大服务质量 (Maximum QoS),客户端使用包含原因码为 0x9B(不支持的 QoS 等级)的 DISCONNECT 报文断开连 接,如4.13节所述。 如果客户端在这些重叠的订阅中指定了订阅标识符,服务端在发布这些订阅相匹配的消息时必须包含这些 订阅标识符 [MQTT-3.3.4-3] 。如果服务端对这些重叠的订阅只发送一条相匹配的消息,服务端必须在 PUBLISH 报文中包含所有的相匹配的订阅标识符(如果存在) ,但没有顺序要求 [MQTT-3.3.4-4] 。如果服 务端对这些重叠的订阅必须分别发送相匹配的消息,则每个 PUBLISH 报文中含与订阅相匹配的订阅标识符  (如果存在)  [MQTT-3.3.4-5]。 可能存在客户端对同一个发布消息做了多次订阅, 并且这些订阅中有多个订阅使用了相同的订阅标识符, 这种情况下 PUBLISH 报文将携带多个相同的订阅标识符。 PUBLISH 报文中若包含服务端收到的 SUBSCRIBE 报文以外的订阅标识符, 将造成协议错误(Protocol Error)。 从客户端发送给服务端的 PUBLISH 报文不能包含订阅标识符 [MQTT-3.3.4-6]。 对于共享订阅, 发送给某个客户端的 PUBLISH 报文中将只包含该客户端的 SUBSCRIBE 报文中发送的订 阅标识符。 收到 PUBLISH 报文时,接收端的行为取决于报文的 QoS 等级, 如4.3节所述。 如果 PUBLISH 报文包含主题别名, 接收端按照以下方式进行处理: 1)   主题别名为 0 或大于最大主题别名(Maximum Topic Alias), 将造成协议错误(Protocol Error), 接   收端使用包含原因码为 0x94(主题别名无效) 的 DISCONNECT 报文断开网络连接, 如4.13节所述。 2)   如果接收端已创建此主题别名的映射, a)   如果报文包含的主题名长度为 0,接收端使用主题别名对应的主题名处理此报文 b)   如果报文包含的主题名长度不为 0,接收端使用此主题名处理此报文, 并更新此主题别名映射到此 主题名 3)   如果接收端还没有创建此主题别名的映射, a)   如果报文包含的主题名长度为 0,将造成协议错误,接收端使用包含原因码为 0x82(协议错误) 的 DISCONNECT 报文断开网络连接,如4.13节所述。 b)   如果报文包含的主题名长度不为 0,接收端使用此主题名处理此报文, 并为此报文中的主题别名和 主题名创建映射关系 非规范评注 如果服务端向客户端分发应用消息时使用了不同的协议级别(比如 MQTT v3.1.1)-- 不支持属性或 本规范提供的其他功能,应用消息中的某些信息将丢失,依赖于这些信息的应用程序可能无法正常 工作。 客户端在收到服务端的 PUBACK ,PUBCOMP 或包含原因码大于等于 128 的 PUBREC 报文之前,不能发 送数量超过服务端的接收最大值(Receive Maximum)的 QoS 为 1 和 2 的 PUBLISH 报文 [MQTT-3.3.4-7]。 服务端在发送 PUBACK 或 PUBCOMP 响应之前, 如果收到数量超过客户端的接收最大值的 QoS 为 1 和 2     的 PUBLISH 报文, 服务端使用包含原因码为 0x93(超出接收最大值)的 DISCONNECT 报文断开网络连 接,如4.13节所述。更多关于流量控制的信息, 参考4.9节。 客户端不能延迟发送任何报文,除了 PUBLISH 报文--如果已发送且没有收到确认的 PUBLISH 报文数量已 达到服务端的接收最大值(Receive Maximum) [MQTT-3.3.4-8]。接收最大值只应用于当前网络连接。 非规范评注 客户端可以选择发送少于服务端接收最大值的未经确认的 PUBLISH 报文, 尽管它可以发送更多数 量的报文。 非规范评注 客户端可以选择暂停发送 QoS 为 0 的报文,当其暂停发送了 QoS 为 1 和 2 的 PUBLISH 报文。 非规范评注 如果客户端在收到 CONNACK 之前发送 QoS 为 1 或 QoS 为 2 的 PUBLISH 报文, 客户端有可能 被服务器断开连接,因为它发送了超过服务端接收最大值数量的发布报文。 服务端在接收到客户端的 PUBACK ,PUBCOMP 或包含原因码大于等于 128 的 PUBREC 报文之前,不能 发送数量超过客户端的接收最大值(Receive Maximum)的 QoS 为 1 和 2 的 PUBLISH 报文 [MQTT-3.3.4- 9]。客户端在发送 PUBACK 或 PUBCOMP 响应之前,如果收到数量超过服务端的接收最大值的 QoS 为 1   和 2 的 PUBLISH 报文,客户端使用包含原因码为 0x93(超出接收最大值) 的 DISCONNECT 报文断开网  络连接, 如4.13节所述。更多关于流量控制的信息, 参考4.9节 。 服务端不能延迟发送任何报文,除了 PUBLISH 报文--如果已发送且没有收到确认的 PUBLISH 报文数量已 到达客户端的接收最大值(Receive Maximum) [MQTT-3.3.4- 10]。 非规范评注 服务端可以选择发送少于客户端接收最大值的未经确认的 PUBLISH 报文, 尽管它可以发送更多数 量的报文。 非规范评注 服务端可以选择暂停发送 QoS 为 0 的报文,当其暂停发送了 QoS 为 1 和 2 的 PUBLISH 报文。 3.4 PUBACK – 发布确认 PUBACK 报文是对 QoS 1 等级的 PUBLISH 报文的响应。 3.4.1 PUBACK 固定报头 图 3- 10 - PUBACK 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (4)保留位 01000000byte 2剩余长度 剩余长度字段 表示可变报头的长度, 用变长字节整数编码。 3.4.2 PUBACK 可变报头 PUBACK 可变报头按顺序包含以下字段: 所确认的 PUBLISH 报文标识符, PUBACK 原因码,属性长度, 属性(Properties) 。属性编码规则如2.22节所述。 图 3- 11 – PUBACK 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBACK 原因码byte 4属性长度 3.4.2.1 PUBACK 原因码 PUBACK 可变报头第 3 字节是原因码(Reason Code)。剩余长度为 2,则表示使用原因码 0x00(成 功)。 表 3-4 - PUBACK 原因码 值16 进制原因码名称说明00x00成功消息被接收。 QoS 为 1 的消息已发布。160x10无匹配的订阅者消息被接收,但没有订阅者。只有服务端会发送此原 因码。如果服务端得知没有匹配的订阅者, 服务端可 以使用此原因码代替 0x00 (成功) 。1280x80未指明的错误接收端不接受此消息, 且不愿意透露错误原因或没有 适用的原因码。1310x83实现特定错误PUBLISH 报文有效,但不被接收端所接受。1350x87未授权PUBLISH 报文未授权。1440x90主题名无效主题名格式正确,但未被客户端或服务端所接受。 1450x91报文标识符被占用报文标识符正被占用。 可能表明客户端和服务端之间 的会话状态不匹配。1510x97超出配额已超出实现限制或管理限制。1530x99载荷格式无效载荷格式与载荷格式指示符不匹配。 服务端或客户端发送 PUBACK 报文时必须设置其中一种 PUBACK 原因码 [MQTT-3.4.2- 1]。当原因码为  0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBACK 剩 余长度为 2。 3.4.2.2 PUBACK 属性 3.4.2.2.1 属性长度 PUBACK 可变报头中属性长度被编码为变长字节整数。如果剩余长度小于 4 字节,则没有属性长度。 3.4.2.2.2 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不能被接收端所解析。 发送端使用此值向接收端提供附加信息。 如果加上原因字符串之后的 PUBACK 报文长度超出了接收端指定 的最大报文长度(Maximum Packet Size),则发送端不能发送此原因字符串 [MQTT-3.4.2-2]。包含多个 原因字符串将造成协议错误(Protocol Error)。 3.4.2.2.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于提供包括诊断信息在内的附加信息。如果加上用户属性之后 的 PUBACK 报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此 属性 [MQTT-3.4.2-3] 。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可 以多次出现。 3.4.3 PUBACK 载荷 PUBACK 报文没有有效载荷。 3.4.4 PUBACK 行为 描述见4.3.2节。 3.5 PUBREC – 发布已接收(QoS 2,第一步) PUBREC 报文是对 QoS 等级 2 的 PUBLISH 报文的响应。它是 QoS 2 等级协议交换的第二个报文。 3.5.1 PUBREC 固定报头 图 3- 12 - PUBREC 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (5)保留 01010000byte 2剩余长度 剩余长度字段 表示可变报头的长度, 用变长字节整数编码。 3.5.2 PUBREC 可变报头 PUBREC 可变报头按顺序包含以下字段: 所确认的 PUBLISH 报文标识符(Packet Identifier), PUBREC 原因码(Reason Code) ,属性(Properties) 。属性的编码规则,如2.2.2 节 所述。 图 3- 13 - PUBREC 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBREC 原因码byte 4属性长度 3.5.2.1 PUBREC 原因码 PUBREC 可变报头第 3 字节是原因码(Reason Code)。如果剩余长度为 2,则表示使用原因码 0x00(成 功)。 表 3-5 – PUBREC 原因码 值16 进制原因码名称说明00x00成功消息被接收。 QoS 为 2 的消息已发布。160x10无匹配的订阅者消息被接收,但没有订阅者。只有服务端会发送此原因码。 如果服务端得知没有匹配的订阅者, 服务端可以使用此原因    码代替 0x00(成功)。1280x80未指明的错误接收端不接受此消息, 且不愿意透露错误原因或没有适用的 原因码。1310x83实现特定错误PUBLISH 报文有效, 但不被接收端所接受。1350x87未授权PUBLISH 报文未授权。1440x90主题名无效主题名格式正确,但未被客户端或服务端所接受。1450x91报文标识符被占用报文标识符正被占用。可能表明客户端和服务端之间的会话 状态不匹配。1510x97超出配额已超出实现限制或管理限制。1530x99载荷格式无效载荷格式与载荷格式指示符不匹配。 服务端或客户端发送 PUBREC 报文时必须设置其中一种原因码 [MQTT-3.5.2- 1]。当原因码为 0x00(成功) 且没有属性(Properties)时,原因码和属性长度可以被省略。 在这种情况下,PUBREC 剩余长度为 2。 3.5.2.2 PUBREC 属性 3.5.2.2.1 属性长度 PUBREC 可变报头的属性长度被编码为变长字节整数。如果剩余长度小于 4,则表示没有属性长度字段。 3.5.2.2.2 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的 PUBREC 报文长度超出了接收端指定 的最大报文长度(Maximum Packet Size), 则发送端不能发送此属性 [MQTT-3.5.2-2]。包含多个原因字  符串将造成协议错误(Protocol Error)。 3.5.2.2.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于提供包括诊断信息在内的附加信息。如果加上用户属性之后 的 PUBREC 报文长度超出了接收端指定的最大报文长度(Maximum Packet Size),则发送端不能发送此 属性 [MQTT-3.5.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可 以多次出现。 3.5.3 PUBREC 载荷 PUBREC 报文没有有效载荷。 3.5.4 PUBREC 行为 描述见4.3.3节。 3.6 PUBREL – 发布释放(QoS 2,第二步) PUBREL 报文是对 PUBREC 报文的响应。它是 QoS 2 等级协议交换的第三个报文。 3.6.1 PUBREL 固定报头 图 3- 14 – PUBREL 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (6)保留位 01100010byte 2剩余长度 PUBREL 固定报头的第 3 ,2 ,1 ,0 位是保留位, 必须被设置为 0 ,0 ,1 ,0。服务端必须将其它的任何值 都当做是不合法的并关闭网络连接 [MQTT-3.6.1- 1]。 剩余长度字段 表示可变报头的长度,被编码为变长字节整数。 3.6.2 PUBREL 可变报头 PUBREL 报文的可变报头按顺序包含以下字段:所确认的 PUBREC 报文标识符, PUBREL 原因码, 属性 (Properties)。属性的编码规则如2.2.2节所述。 图 3- 15 – PUBREL 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBREL 原因码byte 4属性长度 3.6.2.1 PUBREL 原因码 可变报头第 3 字节是 PUBREL 原因码。如果剩余长度为 2,则表示使用原因码 0x00 (成功) 。 表 3-6 - PUBREL 原因码 值16 进制原因码名称说明00x00成功消息已释放。1460x92报文标识符未发现未知的报文标识符。会话恢复阶段这并非错误,但其他时间这表明 服务端和客户端的会话状态不匹配。 客户端或服务端发送 PUBREL 报文时必须设置其中一种 PUBREL 原因码 [MQTT-3.6.2- 1]。当原因码为  0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBREL 剩 余长度为 2。 3.6.2.2 PUBREL 属性 3.6.2.2.1 属性长度 PUBREL 报文可变报头中的属性长度被编码为变长字节整数。如果剩余长度小于 4,则表示没有属性长度 字段。 3.6.2.2.2 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。 如果加上原因字符串之后的 PUBREL 报文长度超出了接收端指定 的最大报文长度(Maximum Packet Size), 则发送端不能发送此原因字符串 [MQTT-3.6.2-2]。包含多个 原因字符串将造成协议错误(Protocol Error)。 3.6.2.2.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于提供包括诊断信息或关于 PUBREL 的信息。 如果加上用户属 性之后的 PUBREL 报文长度超出了接收端指定的最大报文长度(Maximum Packet Size), 则发送端不能 发送此属性 [MQTT-3.6.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对, 且相同的 名字可以多次出现。 3.6.3 PUBREL 载荷 PUBREL 报文没有有效载荷。 3.6.4 PUBREL 行为 描述见4.3.3节 。 3.7 PUBCOMP – 发布完成(QoS 2,第三步) PUBCOMP 报文是对 PUBREL 报文的响应。它是 QoS 2 等级协议交换的第四个也是最后一个报文。 3.7.1 PUBCOMP 固定报头 图 3- 16 – PUBCOMP 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (7)保留位 01110000byte 2剩余长度 剩余长度字段 表示可变报头的长度, 编码为变长字节整数。 3.7.2 PUBCOMP 可变报头 PUBCOMP 报文可变报头按顺序包含以下字段: 所确认的 PUBREL 报文标识符, PUBCOMP 原因码,属 性。属性(Properties)编码规则如2.2.2节所述。 图 3- 17 - PUBCOMP 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSBbyte 3PUBCOMP 原因码byte 4属性长度 3.7.2.1 PUBCOMP 原因码 可变报头第 3 字节是 PUBCOMP 原因码。如果剩余长度为 2,则表示使用原因码 0x00(成功)。 表 3-7 – PUBCOMP 原因码 值16 进制原因码名称说明 00x00成功报文标识符已释放。 QoS 2 消息已完成发布。1460x92报文标识符未发现未知的报文标识符。会话恢复阶段这并非错误,但其他时间这表 明服务端和客户端的会话状态不匹配。 服务端或客户端发送 PUBCOMP 报文时必须设置一种 PUBCOMP 原因码 [MQTT-3.7.2- 1]。当原因码为  0x00(成功)且没有属性(Properties)时,原因码和属性长度可以被省略。在这种情况下,PUBCOMP 剩余长度为 2。 3.7.2.2 PUBCOMP 属性 3.7.2.2.1 属性长度 PUBCOMP 报文可变报头中的属性长度被编码为变长字节整数。如果剩余长度小于 4,则表示没有属性长 度字段。 3.7.2.2.2 原因字符串 31 (0x1F),原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被接收端所解析。 发送端使用此值向接收端提供附加信息。 如果加上原因字符串之后的 PUBCOMP 报文长度超出了接收端指 定的最大报文长度(Maximum Packet Size) ,则发送端不能发送此原因字符串 [MQTT-3.7.2-2]。包含多 个原因字符串将造成协议错误(Protocol Error)。 3.7.2.2.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于提供诊断信息或关于其他信息。如果加上用户属性之后的 PUBCOMP 报文长度超出了接收端指定的最大报文长度(Maximum Packet Size) ,则发送端不能发送此 属性 [MQTT-3.7.2-3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可 以多次出现。 3.7.3 PUBCOMP 载荷 PUBCOMP 报文没有有效载荷。 3.7.4 PUBCOMP 行为 描述见4.3.3节。 3.8 SUBSCRIBE - 订阅请求 客户端向服务端发送 SUBSCRIBE 报文用于创建一个或多个订阅。每个订阅(Subscription)注册客户端所 感兴趣的一个或多个主题。服务端向客户端发送 PUBLISH 报文以转发被发布到符合这些订阅主题的应用消 息。 SUBSCRIBE 报文同样(为每个订阅) 指定了服务端可以向其发送的应用消息最大 QoS 等级。 3.8.1 SUBSCRIBE 固定报头 图 3- 18 - SUBSCRIBE 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (8)保留位 10000010byte 2剩余长度 SUBSCRIBE 报文固定报头第 3 ,2 ,1 ,0 比特位是保留位, 必须被设置为 0 ,0 ,1 ,0 。服务端必须将其 他的任何值都当做是不合法的并关闭网络连接 [MQTT-3.8.1- 1]。 剩余长度字段 表示可变报头的长度加上有效载荷的长度, 被编码为变长字节整数。 3.8.2 SUBSCRIBE 可变报头 SUBSCRIBE 报文可变报头按顺序包含以下字段: 报文标识符(Packet Identifier),属性(Properties)。 2.2.1节提供了更多关于报文标识符的信息。属性的编码规则如2.2.2节所述。 非规范示例 图 3- 19 展示了一个包含报文标识符为 10,且没有属性的 SUBSCRIBE 可变报头。 图 3- 19 – SUBSCRIBE 可变报头示例  说明76543210报文标识符byte 1报文标识符 MSB (0)00000000byte 2报文标识符 LSB (10)00001010byte 3属性长度 (0)00000000 3.8.2.1 SUBSCRIBE 属性 3.8.2.1.1 属性长度 SUBSCRIBE 报文可变报头中的属性长度被编码为变长字节整数。 3.8.2.1.2 订阅标识符 11 (0x0B) ,订阅标识符(Subscription Identifier)标识符。 跟随其后的是一个变长字节整数表示订阅标识符。订阅标识符取值范围从 1 到 268,435,455。订阅标识符 的值为 0 或包含多个订阅标识符将造成协议错误(Protocol Error)。 订阅标识符与 SUBSCRIBE 报文所创建或修改的订阅(Subscription)相关联。如果包含订阅标识符,它将 与订阅一起被存储。如果未指定此属性,则订阅被存储时将不包含订阅标识符。 更多关于订阅标识符的处理信息,参考3.8.3.1节 。 3.8.2.1.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。 用户属性允许出现多次,以表示多个名字/值对。同样的名字允许出现多次。 非规范评注 SUBSCRIBE 报文的用户属性可以被客户端用来向服务端发送订阅相关的属性。本规范不定义这些 属性的意义。 3.8.3 SUBSCRIBE 载荷 SUBSCRIBE 报文的载荷包含一列主题过滤器,指明客户端希望订阅的主题。 主题过滤器必须为 UTF-8 编 码的字符串 [MQTT-3.8.3- 1]。每个主题过滤器之后跟着一个订阅选项(Subscription Options)字节。 载荷必须包含至少一个主题过滤器/订阅选项对 [MQTT-3.8.3-2] 。不包含载荷的 SUBSCRIBE 报文将造成协 议错误(Protocol Error)。错误处理信息, 参考4.13节。 3.8.3.1 订阅选项 订阅选项的第 0 和 1 比特代表最大服务质量字段。此字段给出服务端可以向此客户端发送的应用消息的最 大 QoS 等级。最大服务质量字段为 3 将造成协议错误(Protocol Error)。 订阅选项的第 2 比特表示非本地(No Local)选项。值为 1,表示应用消息不能被转发给发布此消息的客户 标识符 [MQTT-3.8.3-3] 。共享订阅时把非本地选项设为 1 将造成协议错误(Protocol Error) [MQTT-3.8.3- 4]。 订阅选项的第 3 比特表示发布保留(Retain As Published)选项。值为 1 ,表示向此订阅转发应用消息时  保持消息被发布时设置的保留(RETAIN)标志。值为 0,表示向此订阅转发应用消息时把保留标志设置为 0。当订阅建立之后, 发送保留消息时保留标志设置为 1。 订阅选项的第 4 和 5 比特表示保留操作(Retain Handling)选项。此选项指示当订阅建立时,是否发送保 留消息。此选项不影响之后的任何保留消息的发送。如果没有匹配主题过滤器的保留消息, 则此选项所有 值的行为都一样。值可以设置为: 0 = 订阅建立时发送保留消息 1 = 订阅建立时, 若该订阅当前不存在则发送保留消息 2 = 订阅建立时不要发送保留消息 保留操作的值设置为 3 将造成协议错误(Protocol Error)。 订阅选项的第 6 和 7 比特为将来所保留。 服务端必须把此保留位非 0 的 SUBSCRIBE 报文当做无效报文 [MQTT-3.8.3-5]。 非规范评注 非本地(No Local)和发布保留(Retain As Published)订阅选项在客户端把消息发送给其他服务 端的情况下,可以被用来实现桥接。 非规范评注 已存在订阅的情况下不发送保留消息是很有用的, 比如重连完成时客户端不确定订阅是否在之前的 会话连接中被创建。 非规范评注 不发送保存的保留消息给新创建的订阅是很有用的,比如客户端希望接收变更通知且不需要知道最 初的状态。 非规范评注 对于某个指示其不支持保留消息的服务端, 发布保留和保留处理选项的所有有效值都将得到同样的 结果:订阅时不发送任何保留消息, 且所有消息的保留标志都会被设置为 0。 图 3-20 – SUBSCRIBE 报文载荷格式 说明76543210主题过滤器byte 1长度 MSBbyte 2长度 LSB bytes 3..N主题过滤器订阅选项 保留位保留处理RAPNLQoSbyte N+100XXXXXX RAP 指发布保留(Retain as Published)。 NL 指非本地(No Local)。 非规范示例 图 3-21 展示了 SUBSCRIBE 载荷示例,包含 2 个主题过滤器: 第一个为“a/b” ,QoS 为 1;第二个 为“c/d” QoS 为 2。 图 3-21 - 载荷字节格式非规范示例  说明76543210主题过滤器byte 1长度 MSB (0)00000000byte 2长度 LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010订阅选项byte 6订阅选项 (1)00000001主题过滤器byte 7长度 MSB (0)00000000byte 8长度 LSB (3)00000011byte 9‘c’ (0x63)01100011byte 10‘/’ (0x2F)00101111byte 11‘d’ (0x64)01100100订阅选项byte 12订阅选项 (2)00000010 3.8.4 SUBSCRIBE 行为 当服务端收到来自客户端的 SUBSCRIBE 报文时, 必须使用 SUBACK 报文作为相应 [MQTT-3.8.4- 1]。 SUBACK 报文必须和待确认的 SUBSCRIBE 报文有相同的报文标识符 [MQTT-3.8.4-2]。 允许服务端在发送 SUBACK 报文之前就开始发送与订阅相匹配的 PUBLISH 报文。 如果服务端收到的 SUBSCRIBE 报文中的一个主题过滤器与当前会话的一个非共享订阅(Non-shared Subscription)相同,那么必须使用新的订阅替换现存的订阅 [MQTT-3.8.4-3]。新订阅的主题过滤器与之前 的订阅相同,但其订阅选项可能不同。如果保留处理选项为 0,任何匹配该主题过滤器的保留消息必须被  重发,但替换订阅不能造成应用消息的丢失 [MQTT-3.8.4-4]。 如果服务端收到的非共享主题过滤器(Non-shared Topic Filter)不同于当前会话的任何主题过滤器,一个 新的非共享订阅将被创建。如果保留处理选项不为 2,所有相匹配的保留消息将发送给客户端。 如果服务端收到的主题过滤器与服务端已存在的某个共享订阅(Shared Subscription)主题过滤器相同, 则将此会话添加到该共享订阅中。不发送任何保留消息。 如果服务端收到的共享订阅主题过滤器(Shared Subscription Topic Filter)与任何已存在的共享订阅主题 过滤器都不同, 一个新的共享订阅将被创建。将此会话作为订阅者添加到该共享订阅。不发送任何保留消 息。 更多关于共享订阅的细节, 参考4.8节。 如果服务端收到的 SUBSCRIBE 报文包含多个主题过滤器, 服务端必须当做收到一系列多个 SUBSCRIBE 报文来处理--除了将它们的响应组合为单个 SUBACK 响应 [MQTT-3.8.4-5]。 服务端发送给客户端的 SUBACK 报文必须为每一个主题过滤器/订阅选项对包含一个原因码 [MQTT-3.8.4-   6] 。 此原因码必须说明为该订阅授予的最大 QoS 等级,或指示订阅失败 [MQTT-3.8.4-7] 。服务端可能授予 了低于订阅者所请求的最大 QoS 等级。响应该订阅的应用消息 QoS 等级必须为该消息发布时的 QoS 等级 和服务端授予的最大 QoS 等级二者最小值 [MQTT-3.8.4-8] 。在原始消息发布的 QoS 等级为 1,且授予的 最大 QoS 等级为 0 的情况下,服务端允许发送重复的消息副本给订阅者(? )。 非规范评注 如果订阅客户端的某个主题过滤器已被授予的最大 QoS 等级为 1 ,那么匹配此过滤器的 QoS 等级 为 0 的应用消息按照 QoS 等级为 0 分发给此客户端。这意味着客户端最多只能收到该消息的一个  副本。另一方面,发布到相同主题的 QoS 等级为 2 的消息,其 QoS 等级被服务端降级为 1 以便分 发给该客户端。因此该客户端可能收到此消息的多个副本。 非规范评注 如果订阅客户端被授予的最大 QoS 等级为 0,那么按照 QoS 等级为 2 发布的应用消息在繁忙时可 能会丢失,但服务端不应该发送重复的消息副本。发布到相同主题的 QoS 等级为 1 的消息,分发 给该客户端时可能会丢失或重复。 非规范评注 使用 QoS 等级 2 订阅某个主题过滤器,等于是说:我想要按照消息被发布时的QoS 等级接收匹配 此过滤器的消息。这意味着发布者负责决定消息可以被发布的最大 QoS 等级,但订阅端可以要求  服务端降低该消息的 QoS 到更适合它的等级。 订阅标识符是服务端的会话状态的一部分, 并将在收到 PUBLISH 报文时返回给客户端。当服务端收到客户 端的 UNSUBSCRIBE 报文时,服务端将此会话标识符从服务端的会话状态中移除:当服务端收到客户端的 UNSUBSCRIBE 报文, 当服务端收到客户端对同样主题过滤器的 SUBSCRIBE 报文但订阅标识符不同或没 有订阅标识符, 或者当服务端在 CONNACK 报文中将会话存在标志设置为 0。 订阅标识符不构成客户端的会话状态的一部分。在一个有用的实现中, 客户端将订阅标识符与其他客户端 状态相关联,此客户端状态将被移除:当客户端取消订阅,当客户端以不同的订阅标识符或没有订阅标识 符订阅同样的主题过滤器, 或者当客户端收到的 CONNACK 报文中会话存在标志被设置为 0。 服务端在重传的 PUBLISH 报文中无需使用同一组订阅标识符。客户端可以通过发送包含与当前会话已存在 的主题过滤器的 SUBSCRIBE 报文进行重新订阅。如果客户端在 PUBLISH 报文初传之后重新订阅并使用  了不同的订阅标识符, 允许服务端在任何重传中使用初传所包含的订阅标识符,或者在重传中使用此新的  订阅标识符。不允许服务端在发送了包含新的订阅标识符的 PUBLISH 报文之后再次使用旧的订阅标识符。 非规范评注 使用场景,用以阐述订阅标识符: .     客户端实现指示某条发布消息匹配多个订阅的编程接口,客户端实现每次订阅时生成新的订阅 标识符。如果返回的发布消息包含多个订阅标识符,则该发布消息匹配多个订阅。 .     客户端实现允许订阅者将消息定向到其相关联的订阅的回调,客户端实现生成映射到唯一回调 的订阅标识符。 收到某条发布消息时,使用订阅标识符决定触发哪一个回调。 .     客户端实现在发布消息时返回程序用于订阅的主题字符串,为此客户端生成一个唯一标识了该 主题过滤器的标识符。收到某条发布消息时,客户端实现使用此标识符查找原始主题过滤器, 并将主题过滤器返回给其应用程序。 .     网关(Gateway)将从服务端收到的发布消息转发给向该网关做了订阅的客户端,网关实现维 护其收到的每个唯一的订阅过滤器到其收到的一组客户标识符--订阅标识符对的映射,网关对 它转发给服务端的每个主题过滤器生成一个唯一的标识符。收到某条发布消息时, 网关使用从 服务端收到的订阅标识符查找对应的客户标识符--订阅标识符对,并把它们加入发送给客户端 的 PUBLISH 报文中。如果上游服务端因为消息匹配了多个订阅而发送了多个 PUBLISH  报文, 则此行为将反映到客户端。 3.9 SUBACK – 订阅确认 服务端发送 SUBACK 报文给客户端,用于确认它已收到并且正在处理 SUBSCRIBE 报文。 SUBACK 报文包含一个原因码列表,用于指定授予的最大 QoS 等级或 SUBSCRIBE 报文所请求的每个订 阅发生的错误。 3.9.1 SUBACK 固定报头 图 3-22 - SUBACK 报文固定报头 Bit76543210 byte 1MQTT 控制报文类型 (9)保留位 10010000byte 2剩余长度 剩余长度字段 可变报头长度加上有效载荷长度,编码为变长字节整数。 3.9.2 SUBACK 可变报头 SUBACK 报文可变报头按顺序包含以下字段:所确认的 SUBSCRIBE 报文标识符,属性(Properties)。 3.9.2.1 SUBACK 属性 3.9.2.1.1 属性长度 SUBACK 可变报头中的属性长度被编码为变长字节整数。 3.9.2.1.2 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。 如果加上原因字符串之后的 SUBACK 报文长度超出了客户端指定 的最大报文长度,则服务端不能发送此原因字符串 [MQTT-3.9.2- 1]。包含多个原因字符串将造成协议错误 (Protocol Error)。 3.9.2.1.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户 属性之后的 SUBACK 报文长度超出了客户端指定的最大报文长度,则服务端不能发送此属性 [MQTT- 3.9.2-2]。用户属性(User  Property)允许出现多次, 以表示多个名字/值对,且相同的名字可以多次出现。 图 3-23 - SUBACK 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSB 3.9.3 SUBACK 载荷 有效载荷包含一个原因码列表。每个原因码对应 SUBSCRIBE 报文中的一个被确认的主题过滤器。 SUBACK 报文中的原因码顺序必须与 SUBSCRIBE 报文中的主题过滤器顺序相匹配 [MQTT-3.9.3- 1]。 表 3-8 - 订阅原因码 值16 进制原因码名称说明00x00授予 QoS 等级 0订阅被接受且最大 QoS 等级为 0。可能低于所请求的 QoS 等级。10x01授予 QoS 等级 1订阅被接受且最大 QoS 等级为 1。可能低于所请求的 QoS 等级。20x02授予 QoS 等级 2订阅被接受且任何 QoS 等级都将被发送给此订阅。1280x80未指明错误订阅未被接受, 且服务端不愿意透露原因或没有适用的原因码。1310x83实现特定错误SUBSCRIBE 有效但不被服务端所接受。1350x87未授权客户端未被授权做此订阅。1430x8F主题过滤器无效主题过滤器格式正确, 但不被允许。1450x91报文标识符已占用指定的报文标识符正在被使用中。1510x97超出配额已超出实现限制或管理限制。1580x9E共享订阅不支持服务端不支持此客户端进行共享订阅。1610xA1订阅标识符不支持服务端不支持订阅标识符; 订阅标识符不被接受。1620xA2通配符订阅不支持服务端不支持通配符订阅; 订阅未被接受。 服务端发送 SUBACK 报文时必须对收到的每一个主题过滤器设置一种原因码 [MQTT-3.9.3-2]。 非规范评注 对于 SUBSCRIBE 报文中的每个主题过滤器,总有一个对应的原因码。如果原因码不是针对某个 特定的主题过滤器(比如 0x91(报文标识符已占用)), 则对每个主题过滤器都使用此原因码。 3.10 UNSUBSCRIBE – 取消订阅请求 客户端发送 UNSUBSCRIBE 报文给服务端, 用于取消订阅主题。 3.10.1 UNSUBSCRIBE 固定报头 图 3-28 – UNSUBSCRIBE 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (10)保留位  10100010byte 2剩余长度 UNSUBSCRIBE 固定报头的第 3 ,2 ,1 ,0 位是保留位且必须分别设置为 0 ,0 ,1 ,0。服务端必须认为任 何其它的值都是不合法的并关闭网络连接 [MQTT-3.10.1- 1]。 剩余长度字段 等于可变报头长度(2 字节)加上有效载荷长度, 编码为变长字节整数。 3.10.2 UNSUBSCRIBE 可变报头 UNSUBSCRIBE 报文可变报头按顺序包含以下字段: 报文标识符和属性(Properties)。2.2.1节提供了有 关报文标识符的更多信息。属性的编码规则,如2.2.2节所述。 3.10.2.1 UNSUBSCRIBE 属性 3.10.2.1.1 属性长度 SUBSCRIBE 可变报头中属性的长度被编码为变长字节整数。 3.10.2.1.2 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是一个 UTF-8 字符串对。 用户属性允许出现多次,以表示多个名字/值对。相同的名字可以出现多次。 非规范评注 UNSUBSCRIBE 报文中的用户属性可以被客户端用来向服务端发送订阅相关的属性。本规范不定 义这些属性的意义。 3.10.3 UNSUBSCRIBE 载荷 UNSUBSCRIBE 报文有效载荷包含一列客户端希望取消订阅的主题过滤器。 UNSUBSCRIBE 报文中的主 题过滤器必须为1.5.4节所述的 UTF-8 编码字符串 [MQTT-3.10.3- 1] ,且连续填充。 UNSUBSCRIBE 报文有效载荷必须包含至少一个主题过滤器 [MQTT-3.10.3-2]。不包含有效载荷的 UNSUBSCRIBE 报文将造成协议错误(Protocol Error)。错误处理信息,参考4.13节。 非规范示例 图 3-30 展示了 UNSUBSCRIBE 报文的载荷示例,包括两个主题过滤器 “a/b”和“c/d”。 图 3-30 - 载荷字节格式非规范示例  说明76543210主题过滤器byte 1长度 MSB (0)00000000byte 2长度 LSB (3)00000011byte 3‘a’ (0x61)01100001byte 4‘/’ (0x2F)00101111byte 5‘b’ (0x62)01100010主题过滤器byte 6长度 MSB (0)00000000byte 7长度 LSB (3)00000011byte 8‘c’ (0x63)01100011byte 9‘/’ (0x2F)00101111byte 10‘d’ (0x64)01100100 3.10.4 UNSUBSCRIBE 行为 服务端必须对客户端的 UNSUBSCRIBE 报文中提供的主题过滤器(不管是否包含通配符) 逐个字符与当前 持有的主题过滤器集进行比较。如果任何过滤器完全匹配,则必须删除其拥有的订阅 [MQTT-3.10.4- 1],否 则不会进行额外的处理。 当服务端收到 UNSUBSCRIBE 报文: .     它必须停止添加为了交付给客户端的与主题过滤器相匹配的任何新消息 [MQTT-3.10.4-2]。 .     它必须完成任何已经开始发送给客户端的、与主题过滤器相匹配的、 QoS 等级为 1 或 2 的消息 [MQTT-3.10.4-3]。 .     它可以继续交付任何为交付给客户端而缓存的消息。 服务端必须发送 UNSUBACK 报文以响应客户端的 UNSUBSCRIBE 请求 [MQTT-3.10.4-4] 。UNSUBACK    报文必须包含和 UNSUBSCRIBE 报文相同的报文标识符。即使没有删除任何主题订阅,服务端也必须发送 一个 UNSUBACK 响应 [MQTT-3.10.4-5]。 如果某个主题过滤器代表一个共享订阅,此会话将被从该共享订阅中删除。如果此会话是该共享订阅所关 联的唯一会话, 该共享订阅被删除。共享订阅的处理, 参考4.8.2节。 3.11 UNSUBACK – 取消订阅确认 服务端发送 UNSUBACK 报文给客户端用于确认收到 UNSUBSCRIBE 报文。 3.11.1 UNSUBACK 固定报头 图 3-31 – UNSUBACK 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (11)保留位 10110000byte 2剩余长度 剩余长度字段 等于可变报头的长度加上有效载荷的长度, 编码为变长字节整数。 3.11.2 UNSUBACK 可变报头 UNSUBACK 报文可变报头按顺序包含以下字段: 所确认的 UNSUBSCRIBE 报文标识符和属性 (Properties)。 属性的编码规则如2.2.2节所述。 图 3-32 – UNSUBACK 报文可变报头 Bit76543210byte 1报文标识符 MSBbyte 2报文标识符 LSB 3.11.2.1 UNSUBACK 属性 3.11.2.1.1 属性长度 UNSUBACK 报文可变报头中的属性的长度被编码为变长字节整数。 3.11.2.1.2 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码的字符串,表示此次响应相关的原因。此原因字符串(Reason String)是为诊断 而设计的可读字符串, 不应该被客户端所解析。 服务端使用此值向客户端提供附加信息。 如果加上原因字符串之后的 UNSUBACK 报文长度超出了客户端  指定的最大报文长度, 则服务端不能发送此原因字符串 [MQTT-3.11.2- 1]。包含多个原因字符串将造成协议 错误(Protocol Error)。 3.11.2.1.3 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户 属性之后的 UNSUBACK 报文长度超出了客户端指定的最大报文长度, 则服务端不能发送此属性 [MQTT- 3.11.2-2]。用户属性(User Property)允许出现多次,以表示多个名字/值对, 且相同的名字可以多次出现。 3.11.3 UNSUBACK 载荷 有效载荷包含一个原因码列表。每个原因码对应 UNSUBSCRIBE 报文中的一个被确认的主题过滤器。 UNSUBACK 报文中的原因码顺序必须与 UNSUBSCRIBE 报文中的主题过滤器顺序相匹配 [MQTT-3.11.3- 1]。 单字节无符号取消订阅原因码的值如下所示。 服务端发送 UNSUBACK  报文时对于每个收到的主题过滤器,  必须使用一个取消订阅原因码 [MQTT-3.11.3-2]。 表 3-9 - 取消订阅原因码 值16 进制原因码名称说明00x00成功订阅已被删除。170x11订阅未发现没有该客户端匹配的主题过滤器被使用。1280x80未指定错误取消订阅不能被完成且服务端不愿意透露原因或没有其他适 用的原因码。1310x83实现指定错误UNSUBSCRIBE 报文有效,但服务端不接受。1350x87未授权客户端未被授权进行取消订阅。1430x8F主题过滤器无效主题过滤器格式正确, 但不被允许。1450x91报文标识符已占用指定的报文标识符正在被使用中。 非规范评注 对于 UNSUBSCRIBE 报文中的每个主题过滤器, 总有一个对应的原因码。如果原因码不是针对某   个特定的主题过滤器(比如 0x91(报文标识符已占用)) ,则对每个主题过滤器都使用此原因码。 3.12 PINGREQ – PING 请求 客户端发送 PINGREQ 报文给服务端,可被用于: .     在没有任何其他 MQTT 控制报文从客户端发给服务端时,告知服务端客户端还活着。 .     请求服务端发送响应以确认服务端还活着。 .     使用网络已确认网络连接没有断开。 此报文被用在保持连接(Keep Alive)的处理中。详细信息,参考3.1.2.10节。 3.12.1 PINGREQ 固定报头 图 3-33 – PINGREQ 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (12)保留位 11000000byte 2剩余长度 (0) 00000000 3.12.2 PINGREQ 可变报头 PINGREQ 报文没有可变报头。 3.12.3 PINGREQ 载荷 PINGREQ 报文没有有效载荷 3.12.4 PINGREQ 行为 服务端必须发送 PINGRESP 报文响应客户端的 PINGREQ 报文 [MQTT-3.12.4- 1]。 3.13 PINGRESP – PING 响应 服务端发送 PINGRESP 报文响应客户端的 PINGREQ 报文。表示服务端还活着。 此报文被用在保持连接(Keep Alive)的处理中。详细信息,参考3.1.2.10节。 3.13.1 PINGRESP 固定报头 图 3-34 – PINGRESP 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (13)保留位 11010000byte 2剩余长度 (0) 00000000 3.13.2 PINGRESP 可变报头 PINGRESP 报文没有可变报头。 3.13.3 PINGRESP 载荷 PINGRESP 报文没有有效载荷。 3.13.4 PINGRESP 行为 客户端收到此报文时不做任何处理。 3.14 DISCONNECT – 断开通知 DISCONNECT 报文是客户端发给服务端的最后一个 MQTT 控制报文。表示客户端为什么断开网络连接的 原因。客户端和服务端在关闭网络连接之前可以发送一个 DISCONNECT 报文。如果在客户端没有首先发 送包含原因码为 0x00(正常断开) DISCONNECT 报文并且连接包含遗嘱消息的情况下, 遗嘱消息会被发 布。更多细节, 参考3.1.2.5节。 服务端不能发送 DISCONNECT 报文,直到它发送了包含原因码小于 0x80 的 CONNACK 报文之后 [MQTT-3.14.0- 1]。 3.14.1 DISCONNECT 固定报头 图 3-35 – DISCONNECT 报文固定报头 Bit76543210byte 1MQTT 控制报文类型 (14)保留字段 11100000byte 2剩余长度 服务端或客户端必须验证所有的保留位都被设置为 0,如果他们不为 0,发送包含原因码为 0x81(无效报 文)的 DISCONNECT 报文,如4.13节所述 [MQTT-3.14.1- 1]。 剩余长度字段 等于可变报头的长度, 编码为变长字节整数。 3.14.2 DISCONNECT 可变报头 DISCONNECT 报文的可变报头按顺序包含以下字段: 断开原因码,属性(Properties)。属性的编码规则 如2.2.2节所述。 3.14.2.1 断开原因码 可变报头的第 1 个字节是断开原因码。如果剩余长度小于 1,则表示使用原因码 0x00(正常断开)。 单字节无符号断开原因码字段如下所示。 表 3- 10 – 断开原因值 值16 进制原因码名称发送端说明00x00正常断开客户端或 服务端正常关闭连接。不发送遗嘱。40x04包含遗嘱消息的断开客户端客户端希望断开但也需要服务端发布它的遗嘱消 息。1280x80未指定错误客户端或 服务端连接被关闭,但发送端不愿意透露原因,或者没 有其他适用的原因码。1290x81无效的报文客户端或 服务端收到的报文不符合本规范。1300x82协议错误客户端或 服务端收到意外的或无序的报文。1310x83实现指定错误客户端或 服务端收到的报文有效,但根据实现无法进行处理。1350x87未授权服务端请求没有被授权1370x89服务端正忙服务端服务端正忙且不能继续处理此客户端的请求。1390x8B服务正关闭服务端服务正在关闭。1410x8D保持连接超时服务端连接因为在超过 1.5 倍的保持连接时间内没有收 到任何报文而关闭。1420x8E会话被接管服务端另一个使用了相同的客户标识符的连接已建立, 导致此连接关闭。1430x8F主题过滤器无效服务端主题过滤器格式正确, 但不被服务端所接受。1440x90主题名无效客户端或 服务端主题名格式正确,但不被客户端或服务端所接 受。1470x93超出接收最大值客户端或 服务端客户端或服务端收到了数量超过接收最大值的未 发送 PUBACK 或 PUBCOMP 的发布消息。1480x94主题别名无效客户端或 服务端客户端或服务端收到的 PUBLISH 报文包含的主 题别名大于其在 CONNECT 或 CONNACK 中发 送的主题别名最大值。1490x95报文过大客户端或 服务端报文长度大于此客户端或服务端的最大报文长 度。 1500x96消息速率过高客户端或 服务端收到的数据速率太高。1510x97超出配额客户端或 服务端已超出实现限制或管理限制。1520x98管理操作客户端或 服务端连接因为管理操作被关闭。1530x99载荷格式无效客户端或 服务端载荷格式与指定的载荷格式指示符不匹配。1540x9A不支持保留服务端服务端不支持保留消息。1550x9B不支持的 QoS 等级服务端客户端指定的 QoS 等级大于 CONNACK 报文中 指定的最大 QoS 等级。1560x9C(临时) 使用其他服务端服务端客户端应该临时使用其他服务端。1570x9D服务端已 (永久)移动服务端服务端已移动且客户端应该永久使用其他服务 端。1580x9E不支持共享订阅服务端服务端不支持共享订阅。1590x9F超出连接速率限制服务端此连接因为连接速率过高而被关闭。1600xA0最大连接时间服务端超出为此连接授予的最大连接时间。1610xA1不支持订阅标识符服务端服务端不支持订阅标识符; 订阅未被接受。1620xA2不支持通配符订阅服务端服务端不支持通配符订阅; 订阅未被接受。 客户端或服务端发送 DISCONNECT 报文时必须使用一种 DISCONNECT 原因码 [MQTT-3.14.2- 1]。如果  原因码为 0x00(正常断开)且没有属性, 原因码和属性长度可以被省略。这种情况下 DISCONNECT 报文 剩余长度为 0。 非规范评注 DISCONNECT 报文用于指示断开的原因, 例如没有确认报文(比如 QoS 等级 0 的发布消息)或 当客户端或服务端不能继续处理连接。 非规范评注 客户端可以使用这些信息来决定是否重新连接,以及在重新尝试之前应该等待多长时间。 3.14.2.2 DISCONNECT 属性 3.14.2.2.1 属性长度 DISCONNECT 报文可变报头中的属性(Properties)的长度被编码为变长字节整数。如果剩余长度小于 2, 属性长度使用 0。 3.14.2.2.2 会话过期间隔 17 (0x11) ,会话过期间隔(Session Expiry Interval)标识符。 跟随其后的是用四字节整数表示的以秒为单位的会话过期间隔(Session Expiry Interval)。 包含多个会话 过期间隔将造成协议错误(Protocol Error)。 如果没有设置会话过期间隔,则使用 CONNECT 报文中的会话过期间隔。 会话过期间隔不能由服务端的 DISCONNECT 报文发送 [MQTT-3.14.2-2]。 如果 CONNECT 报文中的会话过期间隔为 0,则客户端在 DISCONNECT 报文中设置非 0 会话过期间隔将 造成协议错误(Protocol Error)。如果服务端收到这种非 0 会话过期间隔, 则不会将其视为有效的 DISCONNECT 报文。服务端使用包含原因码为 0x82  (协议错误)的 DISCONNECT 报文,如4.13节所 述。 3.14.2.2.3 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码字符串表示断开原因。此原因字符串是为诊断而设计的可读字符串, 不应该被接 收端所解析。 如果此属性使得 DISCONNECT 报文的长度超出了接收端指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.14.2-3] 。包含多个原因字符串将造成协议错误(Protocol Error)。 3.14.2.2.4 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户 属性之后的 DISCONNECT 报文长度超出了接收端指定的最大报文长度,则发送端不能发送此属性 [MQTT-3.14.2-4] 。用户属性允许出现多次,以表示多个名字/值对, 且相同的名字可以多次出现。 3.14.2.2.5 服务端参考 28 (0x1C) ,服务端参考(Server Reference)标识符。 跟随其后的是一个 UTF-8 编码字符串,客户端可以使用它来识别其他要使用的服务端。包含多个服务端参 考将造成协议错误(Protocol Error)。 服务端发送包含一个服务端参考和原因码 0x9C( (临时) 使用其他服务端) 或 0x9D(服务端已(永久) 移动)的 DISCONNECT 报文,如4.13节所述。 关于如何使用服务端参考,参考4.11节服务端重定向。 图 3-24 - DISCONNECT 报文可变报头非规范示例  说明76543210断开原因码byte 1 00000000属性byte 2长度 (5)00000101byte 3会话过期间隔标识符 (17)00010001byte 4会话过期间隔 (0)00000000byte 500000000byte 600000000byte 700000000 3.14.3 DISCONNECT 载荷 DISCONNECT 报文没有有效载荷。 3.14.4 DISCONNECT 行为 发送端发送完 DISCONNECT 报文之后: .     不能再在此网络连接上发送任何 MQTT 控制报文 [MQTT-3.14.4- 1]。 .     必须关闭网络连接 [MQTT-3.14.4-2]。 接收到包含原因码为 0x00 (成功) 的 DISCONNECT 时,服务端: .     必须丢弃任何与当前连接相关的遗嘱消息, 而不发布它 [MQTT-3.14.4-3],如3.1.2.5节所述。 接收到 DISCONNECT 报文时,接收端: .     应该关闭网络连接 3.15 AUTH – 认证交换 AUTH 报文被从客户端发送给服务端,或从服务端发送给客户端,作为扩展认证交换的一部分, 比如质询/  响应认证。如果 CONNECT 报文不包含相同的认证方法,则客户端或服务端发送 AUTH 报文将造成协议错 误(Protocol Error)。 3.15.1 AUTH 固定报头 图 3-35 – AUTH 报文固定报头 Bit76543210 byte 1MQTT 控制报文类型 (15)保留位 11110000byte 2剩余长度 AUTH 报文固定报头第 3 ,2 ,1 ,0 位是保留位, 必须全设置为 0。客户端或服务端必须把其他值当做无效 值并关闭网络连接 [MQTT-3.15.1- 1]。 剩余长度字段 等于可变报头的长度, 编码为变长字节整数。 3.15.2 AUTH 可变报头 AUTH 报文可变报头按顺序包含以下字段: 认证原因码(Authentication Reason Code) ,属性 (Properties)。 属性的编码规则, 如2.2.2节所述。 3.15.2.1 认证原因码 可变报头第 0 字节是认证原因码(Authenticate Reason Code)。单字节无符号认证原因码字段的值如下 所示。 AUTH 报文的发送端必须使用一种认证原因码 [MQTT-3.15.2- 1]。 表 3- 11 - 认证原因码 值16 进制原因码名称发送端说明00x00成功服务端认证成功。240x18继续认证服务端或 客户端继续下一步认证。250x19重新认证客户端开始重新认证。 如果原因码为 0x00(成功)并且没有属性字段, 则可以省略原因码和属性长度。这种情况下, AUTH 报文 剩余长度为 0。 3.15.2.2 AUTH 属性 3.15.2.2.1 属性长度 AUTH 报文可变报头中的属性的长度被编码为变长字节整数。 3.15.2.2.2 认证方法 21 (0x15) ,认证方法(Authentication Method)标识符。 跟随其后的是一个 UTF-8 编码字符串,包含认证方法名称。省略认证方法或者包含多个认证方法都将造成 协议错误(Protocol Error)。 更多关于扩展认证的信息,参考4.12节。 3.15.2.2.3 认证数据 22 (0x16) ,认证数据(Authentication Data)标识符。 跟随其后的是二进制数据, 包含认证数据。包含多个认证数据将造成协议错误(Protocol Error)。此数据 的内容由认证方法定义。更多关于扩展认证的信息,参考4.12节。 3.15.2.2.4 原因字符串 31 (0x1F) ,原因字符串(Reason String)标识符。 跟随其后的是 UTF-8 编码字符串, 表示断开原因。此原因字符串是为诊断而设计的可读字符串, 不应该被 接收端所解析。 如果加上原因字符串之后的 AUTH 报文长度超出了接收端所指定的最大报文长度, 则发送端不能发送此属 性 [MQTT-3.15.2-2]。包含多个原因字符串将造成协议错误(Protocol Error)。 3.15.2.2.5 用户属性 38 (0x26) ,用户属性(User Property)标识符。 跟随其后的是 UTF-8 字符串对。此属性可用于向客户端提供包括诊断信息在内的附加信息。如果加上用户 属性之后的 AUTH 报文长度超出了接收端指定的最大报文长度, 则服务端不能发送此属性 [MQTT-3.15.2-  3]。用户属性(User Property)允许出现多次,以表示多个名字/值对,且相同的名字可以多次出现。 3.15.3 AUTH 载荷 AUTH 报文没有有效载荷。 3.15.4 AUTH 行为 更多关于扩展认证的信息, 参考4.12节。 4  操作行为 4.1 会话状态 为实现 QoS 等级 1 和 QoS 等级 2 协议流,客户端和服务端需要将状态与客户标识符相关联,这被称为会 话状态。服务端还将订阅信息存储为会话状态的一部分。 会话可以跨越一系列的网络连接。它持续到最新的网络连接(Network Connections)加上会话过期间隔 (Session Expiry Interval)。 客户端的会话状态包括: .     已发送给服务端,但是还没有完成确认的 QoS 等级 1 和 QoS 等级 2 的消息。 .     从服务端收到的,但是还没有完成确认的 QoS 等级 2 消息。 服务端的会话状态包括: .     会话是否存在, 即使会话状态其余部分为空。 .     客户端订阅信息,包括任何订阅标识符。 .     已发送给客户端,但是还没有完成确认的 QoS 等级 1 和 QoS 等级 2 的消息。 .     等待传输给客户端的 QoS 等级 0(可选) ,QoS 等级 1 和 QoS 等级 2 的消息。 .     从客户端收到的,但是还没有完成确认的 QoS 等级 2 消息。遗嘱小子和遗嘱延时间隔。 .     如果会话当前未连接, 会话结束时间和会话状态将被丢弃。 保留消息不是会话状态的一部分,会话结束时不被删除。 4.1.1 存储会话状态 当网络连接打开时,客户端和服务端不能丢弃会话状态 [MQTT-4.1.0- 1] 。当网络连接被关闭并且会话过期 间隔已过时,服务端必须丢弃会话状态 [MQTT-4.1.0-2]。 非规范评注 客户端和服务端实现的存储容量必然是有限的,还可能要受管理策略的限制。已存储的会话状态可 能因为管理操作(比如某个预定义条件的自动响应)而被丢弃。它造成的后果就是会话终止。这些 操作可能是因为资源受限或其他操作原因引发的。硬件或软件故障可能导致客户端或服务端存储的 会话状态丢失或损坏。 需要谨慎的评估客户端和服务端的存储能力,以确保存储空间充足。 4.1.2 会话状态非规范示例 例如,想要收集电表读数的用户可能会决定使用 QoS 等级 1 的消息,因为他们不能接受数据在网络传输途 中丢失, 但是, 他们可能认为客户端和服务端的数据可以存储在内存(易失性存储器)中, 因为(他们觉  得)电力供应是非常可靠的,不会有太大的数据丢失风险。 与之相反,停车计费支付应用的提供商可能决定任何情况下都不能让数据支付消息丢失,因此他们要求在 通过网络传输之前将所有的数据写入到非易失性存储器中(如硬盘)。 4.2 网络连接 MQTT 协议要求基础传输层能够提供有序的、可靠的、双向传输(从客户端到服务端和从服务端到客户端) 字节流。此规范不要求任何指定的传输协议。客户端或服务端可以支持这里列出的任何传输协议, 或者满 足本节要求的任何其他传输协议。 客户端或服务端必须支持使用一个或多个提供有序的、可靠的、双向传输(从客户端到服务端和从服务端 到客户端)字节流传输的底层传输协议 [MQTT-4.2- 1]。 非规范评注 MQTT v5.0 使用的传输层协议是[RFC0793]定义的 TCP/IP 协议。下面的协议也支持: .     TLS[RFC5246] .     WebSocket[RFC6455] 非规范评注 TCP 端口 8883 和 1883 已在 IANA 注册,分别用于 MQTT 的 TLS 和非 TLS 通信。 非规范评注 无连接的网络传输,如用户数据包协议 (UDP) 本身不适合,因为它们可能丢失或重新排列数据。 4.3 服务质量等级和协议流程 MQTT 按照后面章节定义的服务质量(QoS)等级分发应用消息。分发协议是对称的,在下面的描述中, 客户端和服务端既可以是发送端也可以是接收端。分发协议关注的是从单个发送者到单个接收者的应用消 息。服务端分发应用消息给多个客户端时, 每个客户端独立处理。分发给客户端的出站应用消息和入站应 用消息的 QoS 等级可能是不同的。 4.3.1 QoS 0:最多分发一次 消息的分发依赖于底层网络的能力。接收端不会发送响应,发送端也不会重试。消息可能送达一次也可能 根本没送达。 对于 QoS 等级 0 的分发协议,发送端 .     必须发送 QoS 等于 0 ,DUP 等于 0 的 PUBLISH 报文 [MQTT-4.3.1- 1]。 对于 QoS 等级 0 的分发协议,接收端 .     接受 PUBLISH 报文时同时接受消息的所有权。 图 4- 1 – QoS 等级 0 协议流程图,非规范示例 发送端动作控制报文接收端动作PUBLISH 报文 QoS 0, DUP=0   ---------->   分发应用消息给适当的后续接收 者(们) 4.3.2 QoS 1:至少分发一次 服务质量等级 1 确保消息至少送达一次。 QoS 等级 1 的 PUBLISH 报文的可变报头中包含一个报文标识符, 需要 PUBACK 报文确认。 2.2.1节提供了有关报文标识符的更多信息。 对于 QoS 等级 1 的分发协议,发送端 .     每次发送新的应用消息都必须分配一个未使用的报文标识符 [MQTT-4.3.2- 1]。 .     发送的 PUBLISH 报文必须包含报文标识符且 QoS 等于 1 ,DUP 等于 0 [MQTT-4.3.2-2]。 .     必须将这个 PUBLISH 报文看作是未确认的,直到从接收端那收到对应的 PUBACK 报文。4.4节 有一个关于未确认消息的讨论 [MQTT-4.3.2-3]。 一旦发送端收到 PUBACK 报文,这个报文标识符就可以重用。 注意:允许发送端在等待确认时使用不同的报文标识符发送后续的 PUBLISH 报文。 对于 QoS 等级 1 的分发协议,接收端 .     响应的 PUBACK 报文必须包含一个报文标识符, 这个标识符来自接收到的、已经接受所有权的 PUBLISH 报文 [MQTT-4.3.2-4]。 .     发送了 PUBACK 报文之后,接收端必须将任何包含相同报文标识符的入站 PUBLISH 报文当做一 个新的消息,并忽略它的 DUP 标志的值 [MQTT-4.3.2-5]。 图 4-2 – QoS 等级 1 协议流程图,非规范示例 发送端动作控制报文接收端动作存储消息  发送 PUBLISH 报文 QoS=1, DUP=0,带报文标识符---------->   开始应用消息的后续分发 1 <----------发送 PUBACK 报文,带报文标 识符丢弃消息   1 不要求接收端在发送 PUBACK 之前完整分发应用消息。原来的发送端收到 PUBACK 报文之后, 应用消息的所有权就会转移给这个接收端。 4.3.3 QoS 2:仅分发一次 这是最高等级的服务质量, 消息丢失和重复都是不可接受的。使用这个服务质量等级会有额外的开销。 QoS 等 2 消息可变报头中有报文标识符。2.2.1节提供了有关报文标识符的更多信息。 QoS 等级 2 的 PUBLISH 报文的接收端使用一个两部确认过程来确认收到。 对于 QoS 等级 2 的分发协议,发送端 .     必须给要发送的新应用消息分配一个未使用的报文标识符 [MQTT-4.3.3- 1]。 .     发送端 PUBLISH 报文必须包含报文标识符且报文的 QoS 等于 2 ,DUP 等于 0 [MQTT-4.3.3-2]。 .     必须将这个 PUBLISH 报文看作是未确认的,直到从接收端那收到对应的 PUBREC 报文 [MQTT- 4.3.3-3]。4.4节有一个关于未确认消息的讨论。 .     收到发送端发送的包含原因码小于 0x80 的 PUBREC 报文后必须发送一个 PUBREL 报文。 PUBREL 报文必须包含与原始 PUBLISH 报文相同的报文标识符 [MQTT-4.3.3-4]。 .     必须将这个 PUBREL 报文看作是未确认的,直到从接收端那收到对应的 PUBCOMP 报文 [MQTT- 4.3.3-5]。 .     一旦发送了对应的 PUBREL 报文就不能重发这个 PUBLISH 报文 [MQTT-4.3.3-6]。 .     如果 PUBLISH 报文已发送,不能应用消息过期属性 [MQTT-4.3.3-7]。 一旦发送端收到包含原因码大于 0x80 的 PUBCOMP 报文,这个报文标识符就可以重用。 注意:允许发送端在等待确认时使用不同的报文标识符发送后续的 PUBLISH 报文,受制于4.9节描述的 流量控制。 对于 QoS 等级 2 的分发协议,接收端 . . . 响应的 PUBREC 报文必须包含报文标识符,这个标识符来自接收到的、已经接受所有权的 PUBLISH 报文 如果接收端发送了包含原因码大于等于 0x80 的 PUBREC 报文, 它必须将后续包含相同报文标识 符的 PUBLISH 报文当做是新的应用消息 [MQTT-4.3.3-9]。 10]。 .     必须发送包含与 PUBREL 相同报文标识符的 PUBCOMP 报文作为对 PUBREL 报文的响应 [MQTT-4.3.3- 11]。 .     发送 PUBCOMP 报文之后,接收端必须将后续包含相同报文标识符的 PUBLISH 报文当做是新的 应用消息 [MQTT-4.3.3- 12]。 .     必须继续 QoS 等级 2 确认序列,即使它已经应用了消息过期属性 [MQTT-4.3.3- 13]。 4.4 消息分发重试 如果收到包含原因码大于等于 0x80 的 PUBACK 或 PUBREC,则对应的 PUBLISH 报文被看作已确认,且 不能被重传 [MQTT-4.4.0-2]。 图 4-3 – QoS 等级 2 协议流程图,非规范示例 发送端动作控制报文接收端行为存储消息  发送 PUBLISH 报文 QoS=2, DUP=0,带报文标识符   ---------->   存储报文标识符,然后启动应用 消息的向前分发 1  发送 PUBREC 报文, 带报文标 识符和原因码 <---------- 丢弃消息,存储 PUBREC 中的 报文标识符  发送 PUBREL 报文, 带报文标 识符   ---------->   丢弃报文标识符  发送 PUBCOMP 报文, 带报文 标识符 <---------- 丢弃已保存的状态   1 不要求接收端在发送 PUBREC 和 PUBCOMP 之前完整分发应用消息。原始发送端收到 PUBREC 报文之后,应用消息的所有权就会转移给这个接收端。然而,接收端需要在接受所有权之前执行对 所有可能导致转发失败(例如超出配额、权限等) 的条件的检查。接收端在 PUBREC 中使用适当  的原因码指示所有权接受成功或失败。 4.5 消息收到 当服务端接受入站应用消息的所有权时, 它必须将消息添加到订阅匹配的客户端的会话状态中 [MQTT- 4.5.0- 1]。匹配规则定义见4.7节 。 正常情况下,客户端收到的消息是对他们创建的订阅的响应。客户端也可能收到不是与它的订阅精确匹配  的消息。如果服务端自动给客户端分配了一个订阅,可能发生这种情况。 UNSUBSCRIBE 操作正在被处理 时也可能收到消息。 客户端必须按照可用的服务质量(QoS)规则确认它收到的任何 PUBLISH 报文, 不管 它是否选择处理其包含的应用消息 [MQTT-4.5.0-2]。 4.6 消息排序 实现 4.3 节定义的协议流程时,客户端必须遵循下列规则 .     重发任何之前的 PUBLISH 报文时, 必须按原始 PUBLISH 报文的发送顺序重发(适用于 QoS 等级 1 和 QoS 等级 2 消息)  [MQTT-4.6.0- 1]。 .     必须按照对应的 PUBLISH 报文的顺序发送 PUBACK 报文(QoS 等级 1 消息)  [MQTT-4.6.0-2]。 .     必须按照对应的 PUBLISH 报文的顺序发送 PUBREC 报文(QoS 等级 2 消息)  [MQTT-4.6.0-3]。 .     必须按照对应的 PUBREC 报文的顺序发送 PUBREL 报文(QoS 等级 2 消息)  [MQTT-4.6.0-4]。 一个有序主题(Ordered Topic)是一个主题,在这个主题中,客户端可以确定从同一个客户端接收的相同   QoS 等级的消息的顺序与他们发布的顺序一致。 当服务端处理发布到有序主题的消息时,它必须按照消息    从任何给定客户端接收的顺序发送 PUBLISH 报文给消费端(对于同一主题和 QoS 等级)  [MQTT-4.6.0-5]。 这是上面列出的规则的补充。 默认情况下,服务端转发非共享订阅的消息时, 必须将每个主题都视为有序主题 [MQTT-4.6.0-6]。服务端 可以提供管理或其他机制来允许一个或多个主题不被当作有序主题。 非规范评注 上面列出的规则确保,使用 QoS 等级 1 发布和订阅的消息流,订阅者按照消息发布时的顺序收到 每条消息的最终副本,但是消息可能会重复,这可能导致在它的后继消息之后收到某个已经收到消   息的重发版本。例如, 发布者按顺序 1 ,2 ,3 ,4 发送消息,订阅者收到的顺序可能是 1 ,2 ,3 ,2, 3 ,4。 如果客户端和服务端能保证任何时刻最多有一条消息在 传输中(in-flight) (在某条消息被确认前 不发送后面的那条消息), 那么,不会有 QoS 等级 1 的消息会在它的任何后续消息之后收到。例 如,订阅者收到的顺序可能是 1 ,2 ,3 ,3 ,4,而不是 1 ,2 ,3 ,2 ,3 ,4。关于如何使用 Receive Maximum 的详细信息,参考4.9节流控。 4.7 主题名和主题过滤器 4.7.1 主题通配符 主题层级(topic level)分隔符用于将结构化引入主题名。如果存在分隔符, 它将主题名分割为多个主题层 级topic level 。 订阅的主题过滤器可以包含特殊的通配符, 允许客户端一次订阅多个主题。 主题过滤器中可以使用通配符,但是主题名不能使用通配符 [MQTT-4.7.0- 1]。 4.7.1.1 主题层级分隔符 斜杠(’/’ U+002F)用于分割主题的每个层级,为主题名提供一个分层结构。当客户端订阅指定的主题过滤 器包含两种通配符时, 主题层级分隔符就很有用了。主题层级分隔符可以出现在主题过滤器或主题名字的  任何位置。相邻的主题层次分隔符表示一个零长度的主题层级。 4.7.1.2 多层通配符 数字符号(‘#’ U+0023)是用于匹配主题中任意层级的通配符。多层通配符表示它的父级和任意数量的子 层级。 多层通配符必须单独指定,或者跟在主题层级分隔符后面。不管哪种情况, 它都必须是主题过滤器 的最后一个字符 [MQTT-4.7.1- 1]。 非规范评注 例如,如果客户端订阅主题 “sport/tennis/player1/#” ,它会收到使用下列主题名发布的消息: .     “sport/tennis/player1” .     “sport/tennis/player1/ranking .     “sport/tennis/player1/score/wimbledon” 非规范评注 .     “sport/#”也匹配单独的“sport”主题名,因为#包括它的父级。 .     “#”是有效的,会收到所有的应用消息。 .     “sport/tennis/#”也是有效的。 .     “sport/tennis#”是无效的。 .     “sport/tennis/#/ranking”是无效的。 4.7.1.3 单层通配符 加号( ‘+’ U+002B)是只能用于单个主题层级匹配的通配符。 在主题过滤器的任意层级都可以使用单层通配符, 包括第一个和最后一个层级。在使用它时,它必须占据 过滤器的整个层级 [MQTT-4.7.1-2]。可以在主题过滤器中的多个层级中使用它,也可以和多层通配符一起 使用。 非规范评注 例如, “sport/tennis/+”匹配“sport/tennis/player1”和“sport/tennis/player2”,但是不匹配 “sport/tennis/player1/ranking”。同时, 由于单层通配符只能匹配一个层级, “sport/+”不匹配“sport” 但是却匹配“sport/”。 .      “+”是有效的。 .     “+/tennis/#”是有效的。 .     “sport+”是无效的。 .     “sport/+/player1”是有效的。 .     “/finance”匹配“+/+”和“/+”,但是不匹配“+”。 4.7.2  以$开头的主题 服务端不能将$字符开头的主题名匹配通配符(#或+ )开头的主题过滤器 [MQTT-4.7.2- 1]。服务端应该阻 止客户端使用这种主题名与其他客户端交换消息。服务端实现可以将$开头的主题名用作其他目的。 非规范评注 .     $SYS/被广泛用作包含服务端特定信息或控制接口的主题的前缀。 .     应用不能使用$字符开头的主题。 非规范评注 .     订阅“#”的客户端不会收到任何发布到以$开头主题的消息。 .     订阅“+/monitor/Clients”的客户端不会收到任何发布到“$SYS/monitor/Clients”的消息。 .     订阅“$SYS/#”的客户端会收到发布到以“$SYS/”开头主题的消息。 .     订阅“$SYS/monitor/+”的客户端会收到发布到“$SYS/monitor/Clients”主题的消息。 .     如果客户端想同时接受以“$SYS/”开头主题的消息和不以$开头主题的消息, 它需要同时订阅“#” 和“$SYS/#”。 4.7.3 主题语义和用法 下列规则应用于主题名和主题过滤器: . . . . . . . 所有的主题名和主题过滤器必须至少包含一个字符 [MQTT-4.7.3- 1]。 主题名和主题过滤器是大小写敏感的。 主题名和主题过滤器可以包含空格字符。 主题名或主题过滤器以前置或后置斜杠‘/’区分。 只包含斜杠‘/’的主题名或主题过滤器是合法的。 主题名和主题过滤器不能包含空字符(Unicode U+0000)[Unicode][MQTT-4.7.3-2]。 主题名和主题过滤器是 UTF-8 编码字符串,它们不能超过 65,535 字节 [MQTT-4.7.3-3]。见1.5.4节 。 除了不能超过 UTF-8 编码字符串的长度限制之外,主题名或主题过滤器的层级数量没有其它限制。 匹配订阅时,服务端不能对主题名或主题过滤器执行任何规范化(normalization)处理, 不能修改或替换 任何未识别的字符 [MQTT-4.7.3-4]。主题过滤器中的每个非通配符层级需要逐字符匹配主题名中对应的层 级才算匹配成功。 非规范评注 使用 UTF-8 编码规则意味着,主题过滤器和主题名的比较可以通过比较编码后的 UTF-8 字节或解 码后的 Unicode 字符。 非规范评注 .     “ACCOUNTS”和“Accounts”是不同的主题名。 .     “Accounts payable”是合法的主题名。 .     “/finance”和“finance”是不同的主题名。 如果订阅的主题过滤器与消息的主题名匹配,应用消息会被发送给每一个匹配的客户端订阅。主题资源可 以是管理员在服务端预先定义好的, 也可以是服务端收到第一个订阅或使用那个主题名的应用消息时动态 添加的。服务端也可以使用一个安全组件有选择地授权客户端使用某个主题资源。 4.8 订阅 MQTT 提供两种订阅方式,共享和非共享。 非规范评注 在早期的 MQTT 版本中, 所有的订阅都是非共享的。 4.8.1 非共享订阅 非共享订阅只与创建它的会话相关联。每个订阅(Subscription)包含一个指示用于在此会话上分发消息的 主题过滤器和订阅选项。服务端负责收集与过滤器相匹配的消息,并在此会话的连接上发送这些消息。 一个会话不能有多个包含相同主题过滤器的非共享订阅,因此主题过滤器可以用作标识此会话的订阅的关 键词。 如果有多个客户端,每个客户端都拥有对某个相同主题的非共享订阅, 则每个客户端都将获得在该主题上 发布的应用消息的副本。这意味着非共享订阅不能被用于多个消费客户端的应用消息负载均衡,因为在这 种情况下,每条消息都将被传递给每一个订阅的客户端。 4.8.2 共享订阅 共享订阅可以与多个订阅会话相关联。与非共享订阅一样,它包含一个主题过滤器和订阅选项。但是,与 此主题过滤器相匹配的发布消息仅被发布到其中一个订阅会话。共享订阅在多个消费客户端并行共享处理 发布消息时是很有用的。 使用特殊样式的主题过滤器来表示共享订阅。过滤器格式如下: $share/{ShareName}/{filter} .      $share 是字符串字面量, 用来把主题过滤器标记为共享订阅主题过滤器。 .      {ShareName}是字符串, 不包含"/" ,"+"或"#"。 .      {filter}该字符串的剩余部分与非共享订阅中的主题过滤器具有相同的语法和语义。参考4.7节。 共享订阅主题过滤器必须以$share/开始,且必须包含至少一个字符长度的共享名(ShareName) [MQTT- 4.8.2- 1] 。共享名不能包含字符"/" ,"+"或"#",但必须跟在"/"字符后面。此"/"字符后面必须跟随一个主题过  滤器 [MQTT-4.8.2-2] ,如4.7节所述。 非规范评注 共享订阅在 MQTT 服务端的范围内定义, 而不是在会话中定义。共享订阅的主题过滤器包含共享 名,因此服务端可以有多个包含相同{过滤器}组件的共享订阅。通常, 应用程序使用共享名表示共 享同一个订阅的一组订阅会话。 示例: .     共享订阅"$share/consumer1/sport/tennis/+"和"$share/consumer2/sport/tennis/+"是不同的共 享订阅, 因此可以被关联到不同的会话组。它们都与非共享订阅主题"sport/tennis/+"相匹配。 如果一条消息被发布到匹配主题"sport/tennis/+" ,则消息的副本仅发送给所有订阅 "$share/consumer1/sport/tennis/+"的会话中的一个会话,也仅发送给所有订阅 "$share/consumer2/sport/tennis/+"的会话中的一个会话。更多的副本将发送给所有对 "sport/tennis/+"进行非共享订阅的客户端。 .     共享订阅"$share/consumer1//finance"匹配非共享订阅主题"/finance"。 注意, "$share/consumer1//finance"和"$share/consumer1/sport/tennis/+"是不同的共享订阅, 尽管它们有相同的共享名。它们可能在某种程度上是相关的,但拥有相同的共享名并不意味着 它们之间有某种关系。 通过 SUBSCRIBE 请求中的共享订阅主题过滤器创建共享订阅。只有一个会话订阅了某个共享订阅时,共 享订阅行为如同非共享订阅,除了: .      匹配发布消息时,不考虑"$share"和{共享名}部分。 .     第一次订阅时, 保留消息不发送给此会话。其他匹配的发布消息将发送给此会话。 一旦某个共享订阅存在,其他会话就有可能订阅了相同的共享订阅主题过滤器。新的会话作为额外的订阅 者关联到此共享订阅。保留消息不发送给此新的订阅者。后续每条与此共享订阅相匹配的应用消息被发送 到该共享订阅关联的其中一个会话。 会话可以通过发送包含某共享订阅主题过滤器的 UNSUBSCRIBE 报文来显式的将其从共享订阅中分离。会 话终止时,也将从共享订阅中分离。 共享订阅持续到至少有一个与其相关的会话(即, 会话已经对此共享订阅主题过滤器发布了成功的 SUBSCRIBE 请求,且尚未完成相应的 UNSUBSCRIBE)。当初始创建此共享订阅的会话取消订阅时, 除 非没有其他的相关会话,否则共享订阅仍然存在。共享订阅在没有被任何会话订阅时结束, 且任何相关的  未分发的消息都被删除。 共享订阅注释 .     如果有不止一个会话订阅了某个共享订阅, 服务端在消息的基础上自由的选择使用哪个会话,以及使用 什么标准来进行该选择。 .     允许不同的订阅客户端在其 SUBSCRIBE 报文中请求不同的 QoS 等级。服务端决定授予每个客户端的 最大 QoS 等级,并且允许向不同的订阅者授予不同的最大 QoS 等级。向客户端发送应用消息时,服务 端必须考虑授予客户端的 QoS 等级 [MQTT-4.8.2-3],与向订阅者发送消息相同。 .     如果服务端正在向其选中的订阅客户端发送 QoS 等级 2 的消息, 并且在分发完成之前网络中断, 服务 端必须在客户端重新连接时完成向该客户端的消息分发 [MQTT-4.8.2-4],如4.3.3节所述。如果客户 端的会话在客户端重连之前终止,服务端不能把此消息发送给其他订阅的客户端 [MQTT-4.8.2-5]。 .     如果服务端正在向其选中的订阅客户端发送 QoS 等级 1 的消息,并且服务端在收到此客户端的确认报 文之前网络中断,服务端可以等客户端重新连接之后将消息重传给客户端。如果客户端的会话在客户  端重连之前终止,服务端应该把此应用消息发送给与此共享订阅相关的另一个客户端。服务端可以在  第一个客户端断开连接时就尝试将消息发送给另一个客户端。 .     如果客户端对来自服务端的 PUBLISH 报文使用包含原因码大于等于 0x80 的 PUBACK 或 PUBREC 报 文进行响应,服务端必须丢弃应用消息而不尝试将其发送给任何其他订阅者 [MQTT-4.8.2-6]。 .     允许客户端向已订阅的共享订阅第二次发送 SUBSCRIBE 请求。比如,它可以通过这样改变其订阅请 求的 QoS 等级,或者因为它不确定以前的连接关闭之前订阅是否已完成。这不会增加共享订阅关联的 会话个数,因此会话将在其第一次发送 UNSUBSCRIBE 之后脱离此共享订阅。 .     每个共享订阅都是独立于其他共享订阅的。有可能两个共享订阅包含了重叠的过滤器。在这种情况下, 与两个共享订阅都相匹配的消息都将被它们单独处理。如果某个客户端既有共享订阅也有非共享订阅, 且某个消息与它们都相匹配,客户端将由于存在非共享订阅而接收此消息的副本, 此消息的第二个副本 将分发给此共享订阅的某个订阅者, 因此可能导致两份副本都被发送给此客户端。 4.9 流控 客户端和服务端使用接收最大值来控制接收未被确认的 PUBLISH 报文数量,如3.1.2.11.4节和3.2.2.3.2 节所述。接收最大值创建了一个发送配额, 用于限制可以在没收到 PUBACK(QoS 等级 1)或   PUBCOMP(QoS 等级 2)的情况下发送的 QoS 等级大于 0 的 PUBLISH 报文数量。 PUBACK 和 PUBCOMP 按照下述方式补充配额。 客户端或服务端必须将其初始发送配额设置为不超过接收最大值的非 0 值 [MQTT-4.9.0- 1]。 每当客户端或服务端发送了一个 QoS 等级大于 0 的 PUBLISH 报文, 它就会减少发送配额。如果发送配额 减为 0,客户端或服务端不能再发送任何 QoS 等级大于 0 的 PUBLISH 报文 [MQTT-4.9.0-2]。它可以继续 发送 QoS 为 0 的 PUBLISH 报文,也可以选择暂停发送这些报文。即使配额为 0,客户端和服务端也必须 继续处理和响应其他 MQTT 控制报文 [MQTT-4.9.0-3]。 发送配额增加 1: .     每当收到一个 PUBACK 报文或 PUBCOMP 报文, 不管 PUBACK 或 PUBCOMP 报文是否包含错 误码。 .     每次收到一个包含返回码大于等于 0x80 的 PUBREC 报文。 如果发送配额已到达初始发送配额, 则不继续增加。在初始发送配额之上尝试增加配额可能是由建立新的 网络连接后重新发送 PUBREL 数据包引起的。 关于客户端和服务端在超出最大接收值的允许的情况下发送 PUBLISH 报文的描述,参考3.3.4节。 发送配额和接收最大值的保留不跨越网络连接,每次建立新的网络连接时按照上面的描述进行初始化。它 们不是会话状态的一部分。 4.10 请求/响应 有些应用程序或标准可能希望通过 MQTT 协议运行请求/响应交互。此版本 MQTT 协议包含三个可用于此 目的的属性: . . . . 响应主题,在3.3.2.3.5节中描述 对比数据,在3.3.2.3.6节中描述 请求响应信息, 在3.1.2.11.7节中描述 响应信息,在3.2.2.3.14节中描述 以下非规范部分描述了如何使用这些属性。 客户端通过发布一个包含响应主题的应用消息来发送请求消息, 如3.3.2.3.5节所述。请求消息可以包含对 比数据属性,如3.3.2.3.6节所述。 4.10.1 基本请求响应(非规范) 请求/响应交互过程如下: 1.   MQTT 客户端(请求方) 向主题发布请求消息。请求消息是具有响应主题的应用消息。 2.    另一个 MQTT 客户端(响应方)订阅了与请求消息发布时使用的主题名相匹配的主题过滤器。结 果,它收到请求消息。可能有多个响应方订阅了此主题名,也可能没有响应方。 3.   响应方根据请求消息采取适当的操作,然后往请求消息中携带的响应主题属性中的主题名发布响 应消息。 4.   典型用法,请求放订阅了响应主题, 从而接收到响应信息。但是,其他某些客户端可能会订阅响 应主题, 因此它们也将接收和处理响应消息。与请求消息一样, 可能有多个客户端订阅了响应消 息的发送主题,也可能没有。 如果请求消息包含对比数据属性,则响应方将此属性拷贝到响应消息中,由响应消息的接收端用来将响应 消息与原始请求相关联。响应消息不包含响应主题属性。 MQTT 服务端转发请求消息中的响应主题和对比数据属性,和响应消息中的对比数据属性。服务端像处理 其他应用程序消息一样处理请求消息和响应消息。 请求放通常在发布请求消息之前订阅响应主题。如果响应消息发送时没有任何订阅者订阅了响应主题,则 响应消息将不会传递给任何客户端。 请求消息和响应消息可以具有任何 QoS 等级,并且响应方可以使用具有非 0 会话过期间隔的会话。通常使 用 QoS 等级 0 发送请求消息,并且只有在应答者正连接时才发送请求消息。但这不是必须的。 响应者可以使用共享订阅来允许响应客户端池。注意, 使用共享订阅时,不保证消息在客户端之间的分发 顺序。 请求方有责任确保它具有发布消息到请求消息的主题、并订阅响应主题属性中主题名的必要权限。响应方 有责任确保它具有订阅请求主题和发布到响应主题的权限。虽然主题授权不属于本规范, 但建议服务端实 施此类授权。 4.10.2 确定响应主题值(非规范) 请求方可以通过包括本地配置在内的任何方式来确定作为他们的响应主题的主题名。为避免不同请求方之 间的冲突,由请求方客户端使用的响应主题最好对于该客户端是唯一的。由于请求方和响应方通常都需要 对这些主题进行授权, 因此使用随机主题名称将会对授权造成挑战。 为了解决此问题,本规范在 CONNACK 报文中定义了一个名为响应信息的属性。服务端可以使用此属性指 导客户端如何选择使用的响应主题。此机制对于服务端和客户端都是可选的。连接时,客户端通过设置 CONNECT 报文中的请求响应信息属性来请求服务端发送响应信息。这会导致服务端在 CONNACK 报文中 插入响应信息属性(UTF-8 编码的字符串) 。 本规范不定义响应信息的内容,但它可以被用来传递主题树的全局唯一部分, 该部分至少在其会话的整个 生命周期内保留给该客户端。使用这种机制,可以在服务端而不是每个客户端中完成该属性的配置。 有关响应信息的定义, 参考3.1.2.11.7节 。 4.11 服务端重定向 服务端可以通过发送包含原因码为 0x9C ((临时)使用其他服务端) 或 0x9D(服务端已(永久)移动) 的 CONNACK 或 DISCONNECT 报文请求客户端使用另一台服务端, 如4.13节所述。服务端发送这些原 因码时可以包含一个服务端参考属性,用以说明客户端应该使用的服务端位置。 原因码 0x9C ((临时) 使用其他服务端) 指定客户端应该临时切换到另一台服务端。另一台服务端可能 是客户端已知的,也可能是由服务端参考所指定的。 原因码 0x9D  (服务端已(永久)移动)指定客户端应该永久切换到另一台服务端。另一台服务端可能是 客户端已知的, 也可能是由服务端参考所指定的。 服务端参考是一个 UTF-8 编码字符串,其值是一个由空格分隔开的参考列表。本规范不指定服务端参考的 格式。 非规范评注 推荐每个参考包含名称及可选的端口号。如果名称包含冒号,则名称字符串可以由方括号括起来   (ℼ[“和“]”)。由方括号括起来的名称不能包含右方括号(“]”)字符,用于表示使用冒号分隔符的 IPv6 地址。这是一个简化版的 URI 授权,如[RFC3986]所述。 非规范评注 服务端参考中的名字通常代表主机名、DNS 名[RFC1035] 、SRV 名[RFC2782]或 IP 地址。跟随 冒号分隔符的通常是十进制端口号。如果端口信息来自于 DNS(比如包含 SRV)或者使用默认端 口,则主机名后无需跟随端口号。 非规范评注 如果给出了多个服务端参考,则期望客户端选择其中一个。 非规范评注 服务端参考示例如下: myserver.xyz.org myserver.xyz.org:8883 10.10.151.22:8883 [fe80::9610:3eff:fe1c]:1883 允许服务端不发送服务端参考,允许客户端忽略服务端参考。此特性可用于负载均衡、服务端重定位和服 务端预置服务端。 4.12 增强认证 MQTT CONNECT 报文使用用户名和密码字段支持基本的网络连接认证。这些字段虽然称为简单密码认证, 但可以被用来承载其他形式的认证, 例如把密码作为令牌(Token)传递。 增强认证包含质询/响应风格的认证, 从而扩展了基本认证。它可能涉及在 CONNECT 报文之后、 CONNACK 报文之前的客户端和服务端之间 AUTH 报文交换。 服务端通过在 CONNECT 报文中添加认证方法字段来启动增强认证。此字段指定使用的认证方法。如果服 务端不支持客户端提供的认证方法, 它可以发送一个包含原因码 0x8C(无效的认证方法) 或 0x87 (未授 权)的 CONNACK 报文,如4.13节所述, 并且必须关闭网络连接 [MQTT-4.12.0- 1]。 认证方法是客户端和服务端关于认证数据中的数据和 CONNECT 报文中其他字段的含义, 以及客户端和服 务端完成认证需要交换和处理的协议。 非规范评注 认证方法通常为 SASL(Simple Authentication and Security Layer)机制,使用一个注册过的名称 便于信息交换。然而, 认证方法不限于使用已注册的 SASL 机制。 如果客户端选择的认证方法指定客户端先发送数据,客户端应该在 CONNECT 报文中包含认证数据属性。 此属性可被用来提供认证方法指定的数据, 认证数据的内容由认证方法定义。 如果服务端需要额外的信息来完成认证,它可以向客户端发送 AUTH 报文,此报文必须包含原因码 0x18 (继续认证) [MQTT-4.12.0-2]。如果认证方法需要服务端向客户端发送认证相关的数据, 这些数据在认证 数据(Authentication Data)中发送。 客户端通过发送另一个 AUTH 报文响应来自服务端的 AUTH 报文,此报文必须包含原因码 0x18(继续认 证)  [MQTT-4.12.0-3]。如果认证方法要求客户端向服务端发送认证相关的数据, 这些数据在认证数据 (Authentication Data)中发送。 客户端和服务端按需交换 AUTH 报文,直到服务端通过发送包含原因码为 0 的 CONNACK 报文接受认证为 止。如果接受认证需要向客户端发送数据, 这些数据在认证数据中发送。 客户端可以在处理过程中随时关闭连接。它可以在关闭之前发送 DISCONNECT 报文。 服务端可以在处理 过程中随时拒绝认证。它可以发送包含原因码大于等于 0x80 的 CONNACK 报文 ,如4.13节所述, 并且 必须关闭网络连接 [MQTT-4.12.0-4]。 如果初始 CONNECT 报文包含认证方法属性,则所有的 AUTH 报文和成功的 CONNACK 报文必须包含与 CONNECT 报文中相同的认证方法属性。  [MQTT-4.12.0-5]。 增强认证的实现对于客户端和服务端来说都是可选的。 如果客户端在 CONNECT 报文中没有包含认证方法,  则服务端不能发送 AUTH 报文,且不能在 CONNACK 报文中发送认证方法 [MQTT-4.12.0-6] 。如果客户端 在 CONNECT 报文中没有包含认证方法, 则客户端不能向服务端发送 AUTH 报文 [MQTT-4.12.0-7]。 如果客户端在 CONNECT 报文中没有包含认证方法, 服务端应该使用 CONNECT 报文中的信息、TLS 会 话和网络连接进行认证。 SCRAM 认证非规范示例 .     客户端到服务端:CONNECT 认证方法="SCRAM-SHA- 1",认证数据=client-first-data .     服务端到客户端:AUTH 原因码=0x18,认证方法="SCRAM-SHA- 1",认证数据=server-first- data .     客户端到服务端:AUTH 原因码=0x18,认证方法="SCRAM-SHA- 1",认证数据=client-final- data .     服务端到客户端:CONNACK 原因码=0 ,认证方法="SCRAM-SHA- 1",认证数据=server-final- data Kerberos 认证非规范示例 .     客户端到服务端:CONNECT 认证方法="GS2-KRB5" .     服务端到客户端:AUTH 原因码=0x18,认证方法="GS2-KRB5" .     客户端到服务端:AUTH 原因码=0x18,认证方法="GS2-KRB5",认证数据=initial context token .     服务端到客户端:AUTH 原因码=0x18,认证方法="GS2-KRB5",认证数据=reply context token .     客户端到服务端:AUTH 原因码=0x18,认证方法="GS2-KRB5" .     服务端到客户端:CONNACK 原因码=0,认证方法="GS2-KRB5",认证数据=outcome of authentication 4.12.1 重新认证 如果客户端在 CONNECT 报文中提供了认证方法,它可以在收到 CONNACK 报文之后的任何时间通过发  送包含原因码 0x19(重新认证)的 AUTH 报文发起重新认证。客户端必须将认证方法设置为与最初验证网 络连接时的认证方法一致 [MQTT-4.12.1- 1]。如果认证方法需要客户端先发送数据,则此 AUTH 报文包含 第一片认证数据。 服务端通过向客户端发送 AUTH 报文来响应此重新认证请求,包含原因码为 0x00 (成功) 的 AUTH 报文 指示重新认证完成,包含原因码为 0x18(继续认证)的 AUTH 报文指示需要更多的认证数据。客户端可以   通过发送包含原因码 0x18  (继续认证)的 AUTH 报文来响应附加的认证数据。此流程与原始身份验证一样, 直到重新认证完成或重新认证失败。 如果重新认证失败,客户端或服务端应该发送包含适当原因码的 DISCONNECT 报文,如4.13 节 所述。并 且必须关闭网络连接 [MQTT-4.12.1-2]。 在重新认证的过程中, 客户端和服务端的其他报文流可以继续使用之前的认证。 非规范评注 服务端可以通过拒绝重新认证来限制客户端在重新认证中尝试的更改范围。例如, 如果服务端不允 许更改用户名, 它可以使任何尝试更改用户名的重新认证都失败。 4.13 错误处理 4.13.1 无效报文和协议错误 无效报文(Malformed Packet)和协议错误(Protocol Error)的定义见1.2节术语。 这些错误案例的部分 术语贯穿本规范。客户端或服务端对其收到的 MQTT 控制报文的检查严格程度依赖: .     客户端或服务端实现的大小。 .     实现支持的性能。 .     接收端对发送端发送的 MQTT 控制报文的信任程度。 .     接收端对用于分发 MQTT 控制报文的网络的信任程度。 .     继续处理错误报文的的后果。 如果发送端遵守此规范,它将不会发送无效报文或导致协议错误。然而,如果客户端在收到 CONNACK 报 文之前发送 MQTT 控制报文,它可能会因为错误的估计了服务端的性能而导致协议错误。参考3.1.4节 CONNECT 行为。 无效报文和协议错误使用的原因码包括: .     0x81            无效报文 .     0x82            协议错误 .     0x93            超过接收最大值 .     0x95            报文过大 .     0x9A            不支持保留 .     0x9B            不支持的 QoS 等级 .     0x9E            不支持共享订阅 .     0xA1           不支持订阅标识符 .     0xA2           不支持通配符订阅 当客户端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时, 它应该关闭网络连接。在 AUTH 报文出错的情况下它可以在关闭网络连接之前发送包含原因码的 DISCONNECT 报文。在其他报文  出错的情况下它应该在关闭网络连接之前发送包含原因码的 DISCONNECT 报文。使用原因码 0x81 (错误 报文)或 0x82(协议错误),除非包含3.14.2.1断开原因码中定义的更具体的原因码。 当服务端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时, 它必须关闭网络连接 [MQTT- 4.13.1- 1]。在 CONNECT 报文出错的情况下它可以在关闭网络连接之前发送包含原因码的 CONNACK 报 文。 在其他报文出错的情况下它应该在关闭网络连接之前发送包含原因码的 DISCONNECT 报文。使用原 因码 0x81 (无效报文)或 0x82(协议错误) ,除非包含3.2.2.2 节 - 连接原因码或3.14.2.1 节 – 断开原因 码中定义的更具体的原因码。对其他会话没有影响。 如果服务端或客户端省略了检查 MQTT 控制报文的某些特性, 它可能无法检测到某个错误,因此可能会导 致数据被损坏。 4.13.2 其他错误 发送端无法预料到无效报文和协议错误以外的错误,因为它可能有某些没有告知发送端的约束。客户端或 服务端可能在接收时遇到短暂的错误,比如内存不足, 导致无法成功的处理某个 MQTT 控制报文。 包含原因码大于等于 0x80 的确认报文 PUBACK ,PUBREC ,PUBREL ,PUBCOMP ,SUBACK , UNSUBACK 表明收到了某个报文标识符的报文出错。 这不会影响其他会话或此会话上的其他报文。 CONNACK 报文和 DISCONNECT 报文允许使用大于等于 0x80 的原因码以指示网络连接将被关闭。如果 某个大于等于 0x80 的原因码被指定,无论是否发送 CONNACK 报文或 DISCONNECT 报文, 必须关闭网 络连接 [MQTT-4.13.2- 1]。发送这些原因码不会影响任何其他会话。 如果控制报文包含多个错误,接收端可以按照任意顺序对报文进行验证,并对发现的任何错误采取适当的 行为。 5  安全(非规范) 5.1 概述 强烈建议提供 TLS[RFC5246]的服务端实现使用 TCP 端口 8883(IANA 服务名:secure-mqtt)。 安全是一个快速变化的领域,所以在设计安全解决方案时总是使用最新的建议。 解决方案需要考虑的风险包括: .     设备可能会被盗用 .     客户端和服务端的静态数据可能是可访问的(可能会被修改) .     协议行为可能有副作用(如计时器攻击) .     拒绝服务(DoS)攻击 .     通信可能会被拦截、修改、重定向或泄露 .     虚假 MQTT 控制报文注入 MQTT 方案通常部署在不安全的通信环境中。在这种情况下,协议实现通常需要提供这些机制: .     用户和设备身份认证 .     服务端资源访问授权 .     MQTT 控制报文和内嵌应用数据的完整性校验 .     MQTT 控制报文和内嵌应用数据的隐私控制 作为传输层协议,MQTT 仅关注消息传输, 提供合适的安全功能是实现者的责任。使用 TLS[RFC5246]是 比较普遍的选择。 除了技术上的安全问题外, 还有地区因素(例如美国欧盟隐私盾框架[USEUPRIVSH]) ,行业标准(例如   第三方支付行业数据安全标准 [PCIDSS]) ,监管方面的考虑(例如萨斯班-奥克斯利法案[SARBANES])。 5.2 MQTT 解决方案: 安全和认证 协议实现可能需要提供符合特定行业安全标准,如 NIST 网络安全框架[NISTCSF] ,第三方支付行业数据 安全标准[PCIDSS] ,美国联邦信息处理标准[FIPS1402]和 NSA 加密组合 B[NSAB]。 在 MQTT 的补充出版物(MQTT and the NIST Framework for Improving Critical Infrastructure Cybersecurity[MQTTNIST])中可以找到在 NIST 网络安全框架[NISTCSF]中使用 MQTT 的指导。使用行 业证明、独立审计和认证技术有助于满足合规要求。 5.3 轻量级的加密与受限设备 广泛采用的加密算法是高级加密标准[AES]。对 AES 提供了硬件支持的处理器有很多,但通常不包含嵌入 式处理器。加密算法 ChaCha20 [CHACHA20] 软件加解密速度快很多,但不像 AES 那样广泛可用。 推荐使用为资源受限的低端设备特别优化过的轻量级加密国际标准 ISO 29192[ISO29192] 。 5.4 实现注意事项 实现或使用 MQTT 时需要考虑许多安全问题。以下章节不应被视为核对清单。 协议实现时可以实现下面的一部分或全部: 5.4.1 客户端身份认证 CONNECT 报文包含用户名和密码字段。实现可以决定如何使用这些字段的内容。实现者可以提供自己的 身份验证机制, 或者使用外部的认证系统如 LDAP[RFC4511]或 Auth[RFC6749],还可以利用操作系统 的认证机制。 MQTT v5.0 提供了一种增强认证机制,如4.12节所述。使用此机制需要客户端和服务端双方的支持。 实现可以明文传递认证数据,混淆数据元素,或者不要求任何认证数据,但应该意识到这会增加中间人攻 击和重放攻击的风险。 5.4.5节介绍了确保数据私密的方法。 在客户端和服务端之间使用虚拟专用网(VPN)可以确保数据只被授权的客户端收到。 使用 TLS[RFC5246]时, 服务端可以使用客户端发送的 TLS 证书验证客户端的身份。 实现可以允许客户端通过应用消息给服务端发送用于身份验证的凭证。 5.4.2 客户端授权 如果客户端已经成功通过身份认证, 服务端实现需要在接受连接之前执行授权检查。 授权可以基于客户端提供的信息如用户名, 客户端主机名/IP 地址,或认证机制的结果。 具体来说,实现应该检查客户端是否被授权使用此客户标识符, 因为客户标识符提供了对 MQTT 会话状态 的访问(如4.1节所述) 。此授权检查是为了防止某个客户端偶然或恶意的使用了已被其他客户端所使用 的客户标识符。 实现应该提供发生在 CONNECT 之后的访问控制以限制客户端发布消息到特定主体或使用特定主体过滤器 进行订阅的能力。实现需要考虑对具有广泛作用域的主题过滤器的访问限制, 如"#"主题过滤器。 5.4.3 服务端身份认证 MQTT 协议不是双向信任的。基本认证没有提供客户端验证服务端身份的机制。某些形式的扩展认证允许 双向认证。 但是使用 TLS[RFC5246]时,客户端可以使用服务端发送的 TLS 证书验证服务端的身份。从单 IP 多域名 提供 MQTT 服务的实现应该考虑[RFC6066]第 3 节定义的 TLS 的 SNI 扩展。SNI 允许客户端告诉服务端 它要连接的服务端主机名。 实现可以允许服务端通过应用消息给客户端发送凭证用于身份验证。 MQTT v5.0 提供了一种增强的认证机 制,如4.12节所述,它可以被客户端用于验证服务端。使用此机制需要客户端和服务端双方的支持。 在客户端和服务端之间使用虚拟专用网(VPN)可以确保客户端正连接的是预期的服务端。 5.4.4 应用消息和 MQTT 控制报文的完整性 应用可以在应用消息中单独包含哈希值。这样做可以为 PUBLISH 报文的网络传输和静态数据提供内容的完 整性检查。 TLS[RFC5246]提供了对网络传输的数据做完整性校验的哈希算法。 在客户端和服务端之间使用虚拟专用网(VPN)连接可以在 VPN 覆盖的网络段提供数据完整性检查。 5.4.5 应用消息和 MQTT 控制报文的保密性 TLS[RFC5246]可以对网络传输的数据加密。如果有效的 TLS 密码组合包含的加密算法为 NULL,那么它 不会加密数据。要确保客户端和服务端的保密,应避免使用这些密码组合。 应用可以单独加密应用消息的内容。这可以提供应用消息传输途中和静态数据的私密性。但不能给应用消 息的其它属性如主题名加密。 客户端和服务端实现可以加密存储静态数据,例如可以将应用消息作为会话的一部分存储。 在客户端和服务端之间使用虚拟专用网(VPN)连接可以在 VPN 覆盖的网络段保证数据的私密性。 5.4.6  消息传输的不可否认性 应用设计者可能需要考虑适当的策略,以实现端到端的不可否认性(non-repudiation)。 5.4.7 客户端和服务端盗用检测 使用 TLS[RFC5246]的客户端和服务端实现应该能够确保,初始化 TLS 连接时提供的 SSL 证书是与主机 名(客户端要连接的或服务端将被连接的) 关联的。 使用 TLS[RFC5246]的客户端和服务端实现,可以选择提供检查证书吊销列表(CRLs [RFC5280])和在 线整数状态协议(OSCP)[RFC6960]的功能, 拒绝使用被吊销的整数。 物理部署可以将防篡改硬件与应用消息的特殊数据传输结合。例如, 一个仪表可能会内置一个 GPS 以确保 没有在未授权的地区使用。 IEEE 安全设备认证[IEEE8021AR]就是用于实现这个机制的一个标准, 它使用 加密绑定标识符验证设备身份。 5.4.8 异常行为检测 服务端实现可以监视客户端的行为, 检测潜在的安全风险。 例如: .     重复的连接请求 .     重复的身份验证请求 .     连接的异常终止 .     主题扫描(请求发送或订阅大量主题) .     发送无法送达的消息(没有订阅者的主题) .     客户端连接但是不发送数据 发现违反安全规则的行为, 服务端实现可以关闭客户端的网络连接。 服务端实现检测不受欢迎的行为,可以基于 IP 地址或客户标识符实现一个动态黑名单列表。 服务部署可以使用网络层次控制(如果可用)实现基于 IP 地址或其它信息的速率限制或黑名单。 5.4.9 其它安全注意事项 如果客户端或服务端的 TLS 证书丢失,或者我们考虑证书被盗用或者被吊销(利用 CRLs[RFC5280]和 OSCP[RFC6960])的情况。 客户端或服务端验证凭证时,如果发现用户名和密码丢失或被盗用,应该吊销或者重新发放。 在使用长连接时: .     客户端和服务端使用 TLS[RFC5246]时应该允许重新协商会话以确认新的加密参数(替换会话密钥, 更换密码组合, 更换认证凭证)。 .     服务端可以关闭客户端的网络连接, 并要求他们使用新的凭证重新验证身份。 .     服务端可以要求客户端使用4.12.1节中描述的机制周期性的进行重新认证。 资源受限设备或使用受限网络的客户端可以使用 TLS[RFC5246]会话恢复,以降低 TLS[RFC5246]会话 重连的成本。 连接到服务端的客户端与其它连接到服务端的客户端之间有一个信任传递关系,它们都有权在同一个主题 上发布消息。 5.4.10 使用 SOCK 代理 客户端实现应该意识到某些环境要求使用 SOCKSv5[RFC1928]代理创建出站的网络连接。某些 MQTT 实 现可以利用安全隧道(如 SSH)通过 SOCKS 代理。一个实现决定支持 SOCKS 时,它们应该同时支持匿 名的和用户名密码验证的 SOCKS 代理。对于后一种情况,实现应该意识到 SOCKS 可能使用明文认证, 因此应该避免使用相同的凭证连接 MQTT 服务器。 5.4.11 安全配置文件 实现者和方案设计者可能希望将安全当作配置文件集合应用到 MQTT 协议中。下面描述的是一个分层的安 全等级结构。 5.4.11.1 开放通信配置 使用开放通信配置时, MQTT 协议运行在一个没有内置额外安全通信机制的开放网络上。 5.4.11.2 安全网络通信配置 使用安全网络通信配置时, MQTT 协议运行在有安全控制的物理或虚拟网络上,如 VPN 或物理安全网络。 5.4.11.3 安全传输配置 使用安全传输配置时, MQTT 协议运行在使用 TLS[RFC5246]的物理或虚拟网络上,它提供了身份认证, 完整性和保密性。 使用内置的用户名称和密码字段, TLS[RFC5246]客户端身份认证可被用于(或者替代) MQTT 客户端认 证。 5.4.11.4 工业标准的安全配置 可以预料的是, MQTT 协议被设计为支持很多工业标准的应用配置,每一种定义一个威胁模型和用于定位 威胁的特殊安全机制。特殊的安全机制推荐从下面的方案中选择: [NISTCSF] NIST 网络安全框架 [NIST7628] NISTIR 7628 智能电网网络安全指南 [FIPS1402](FIPS PUB 140-2)加密模块的安全要求 [PCIDSS] PCI-DSS 第三方支付行业数据安全标准 [NSAB] NSA 加密组合 B 6  使用 WebSocket 作为网络层 如果 MQTT 在 WebSocket[RFC6455]连接上传输, 要满足下面的条件: .     MQTT 控制报文必须使用 WebSocket 二进制数据帧发送。如果收到任何其它类型的数据帧,接收者必 须关闭网络连接 [MQTT-6.0.0- 1]。 .     单个 WebSocket 数据帧可以包含多个或者部分 MQTT 报文。接收者不能假设 MQTT 控制报文按 WebSocket 帧边界对齐 [MQTT-6.0.0-2]。 .     客户端必须将字符串"mqtt"包含在它提供的 WebSocket 子协议列表里 [MQTT-6.0.0-3]。 .     服务端选择和返回的 WebSocket 子协议名必须是"mqtt" [MQTT-6.0.0-4]。 .     用于连接客户端和服务器的 WebSocket URI 对 MQTT 协议没有任何影响。 6.1  IANA 注意事项 本规范请求 IANA 修改“WebSocket 子协议名”条目下 MQTT 子协议注册信息为下列数据: 图 6- 1 - IANA WebSocket 标识符 子协议标识符mqtt子协议通用名mqtt子协议定义http://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html 7  一致性 MQTT 规范定义了 MQTT 客户端实现和 MQTT 服务端实现的一致性要求。 MQTT 实现可以同时作为 MQTT 客户端和 MQTT 服务端。 7.1 一致性条款 7.1.1 MQTT 服务端一致性条款 服务端的定义, 参考术语章节的服务端(Server)部分。 MQTT 服务端只有满足下面所有的要求才算是符合本规范: 1. 2. 3. 4. 服务端发送的所有 MQTT控制报文的格式符合第二章和第三章描述的格式。 遵守4.7节描述的主题匹配规则和4.8节匹配的订阅规则。 满足下列章节中所有必须级别的要求,明确仅适用于对客户端的除外: .    第一章 - 介绍 .    第二章 - MQTT 控制报文格式 .    第三章 - MQTT 控制报文 .    第四章 - 操作行为 .    第六章 - 使用 WebSocket 作为网络层 为了能够与任何其他一致的(MQTT)实现进行互操作,无需使用在规范之外定义的任何扩展。 7.1.2 MQTT 客户端一致性条款 客户端的定义, 参考术语章节的客户端(Client)部分。 MQTT 客户端只有满足下面所有的要求才算是符合本规范: 1.   客户端发送端所有 MQTT控制报文的格式符合第二章和第三章描述的格式。 2.   满足下列章节中所有必须级别的要求,明确仅适用于对服务端的除外: .    第一章 - 介绍 .    第二章 - MQTT 控制报文格式 .    第三章 - MQTT 控制报文 .    第四章 - 操作行为 .    第六章 - 使用 WebSocket 作为网络层 3.   为了能够与任何其他一致的(MQTT)实现进行互操作,无需使用在规范之外定义的任何扩展。 Appendix A. 致谢 技术委员会特别感谢 Andy Stanford-Clark 博士和 Arlen Nipper 博士作为 MQTT 协议的原始发明者以及他 们对标准化过程的持续支持。 以下成员在本规范制定期间为 OASIS 技术委员会成员,他们的贡献值得感谢: 参与者: .     Senthil Nathan Balasubramaniam (Infiswift) .     Dr. Andrew Banks, editor (IBM) .     Ken Borgendale, editor (IBM) .     Ed Briggs, editor (Microsoft) .     Raphael Cohn (Individual) .     Richard Coppen, chairman (IBM) .     William Cox (Individual) .      Ian Craggs , secretary (IBM) .     Konstantin Dotchkoff (Microsoft) .     Derek Fu (IBM) .     Rahul Gupta, editor (IBM) .     Stefan Hagen (Individual) .     David Horton (Solace Systems) .     Alex Kritikos (Software AG, Inc.) .     Jonathan Levell (IBM) .     Shawn McAllister (Solace Systems) .     William McLane (TIBCO Software Inc.) .     Peter Niblett (IBM) .     Dominik Obermaier (dc-square GmbH) .     Nicholas O'Leary (IBM) .     Brian Raymor, chairman (Microsoft) .     Andrew Schofield (IBM) .     Tobias Sommer (Cumulocity) .     Joe Speed (IBM) .     Dr Andy Stanford-Clark (IBM) .     Allan Stockdill-Mander (IBM) .     Stehan Vaillant (Cumulocity) 有关对早期版本 MQTT 协议做出贡献的人员列表,参考 MQTT v3.1.1 规范中的附录 A[MQTTV311]。 Appendix B. 强制性规范声明(非规范) 此附录是非规范性的, 只作为本文档正文中可以找到的大量一致性声明的摘要提供。参考第七章一致性要 求限制列表。 规范声明序号规范声明[MQTT- 1.5.4- 1]UTF-8 编码字符串中的数据必须是按照 [Unicode] 规范定义的, 在 RFC 3629 [RFC3629]    中重申的有效的 UTF-8 格式。特别需要指出的是,这些数据不能包含字符码在 U+D800 和 U+DFFF 之间的数据。[MQTT- 1.5.4-2]UTF-8 编码的字符串不能包含空字符 U+0000。[MQTT- 1.5.4-3]UTF-8 编码序列 0xEF 0xBB 0xBF 总是被解释为 U+FEFF ("零宽度非换行空白字符") ,无 论它出现在字符串的什么位置,报文接收者都不能跳过或者剥离它。[MQTT- 1.5.5- 1]编码值必须使用表示该值所需的最少字节数。[MQTT- 1.5.7- 1]所有的字符串都必须符合 UTF-8 编码字符串的要求。[MQTT-2.1.3- 1]如果标记位被标记为“保留” ,则保留它以供将来使用, 并且必须设置为所列出的值。[MQTT-2.2.1-2]QoS 等级为 0 的 PUBLISH 报文不能包含报文标识符。[MQTT-2.2.1-3]客户端每次发送新的 SUBSCRIBE ,UNSUBSCRIBE 或 PUBLISH(当 QoS 等级>0) MQTT 控制报文时, 它必须为其分配一个当前未被使用的非 0 报文标识符。[MQTT-2.2.1-4]服务端每次发送新的 PUBLISH(当 QoS 等级>0)MQTT 控制报文时, 它必须为其分配一 个当前未被使用的非 0 报文标识符。[MQTT-2.2.1-5]PUBACK ,PUBREC ,PUBREL 或 PUBCOMP 报文必须包含 PUBLISH 报文中发送的原 始报文标识符。[MQTT-2.2.1-6]SUBACK 和 UNSUBACK 报文必须包含相应的 SUBSCRIBE 和 UNSUBSCRIBE 报文中使 用的报文标识符。[MQTT-2.2.2- 1]如果没有属性, 属性长度必须为 0。[MQTT-3.1.0- 1]客户端到服务端的网络连接建立后, 客户端发送给服务端的第一个报文必须是 CONNECT 报文。[MQTT-3.1.0-2]当协议错误并关闭网络连接时,服务端必须处理客户端发送的第二个 CONNECT 报文。[MQTT-3.1.2- 1]协议名必须是 UTF-8 字符串"MQTT"。如果服务端不想接受 CONNECT,并希望透露它是 MQTT 服务端,它可以发送一个包含原因码为 0x84(不支持的协议版本)的 CONNACK  报文,然后必须关闭网络连接。 [MQTT-3.1.2-2]如果协议版本不为 5,且服务端不想接受 CONNECT 报文,则服务端可以发送一个包含原 因码为 0x84(不支持的协议版本) 的 CONNACK 报文,然后必须关闭网络连接。[MQTT-3.1.2-3]服务端必须验证 CONNECT 报文的保留标志位(第 0 位)是否为 0。[MQTT-3.1.2-4]如果 CONNECT 报文的新开始标志被设置为 1,则客户端和服务端必须丢弃任何已存在的 会话并开始一个新的会话。[MQTT-3.1.2-5]如果 CONNECT 报文的新开始标志被设置为 0,并且存在与该客户标识符相关联的会话, 服务端必须基于此会话恢复与客户端的通信。[MQTT-3.1.2-6]如果 CONNECT 报文的新开始标志被设置为 0,并且不存在与该客户标识符相关联的会 话,则服务端必须创建一个新的会话。[MQTT-3.1.2-7]遗嘱标志被设置为 1,表示遗嘱消息必须被存储在服务端并与会话相关联。[MQTT-3.1.2-8]在网络连接被关闭且遗嘱延时间隔已过或会话结束时遗嘱消息必须被发布,除非遗嘱消息  被服务端在收到包含原因码为 0x00(正常关闭)的 DISCONNECT 报文后删除或关于此客 户标识符的一个新的网络连接在遗嘱消息间隔过期之前被打开。[MQTT-3.1.2-9]如果遗嘱标志被设置为 0,连接标志中的遗嘱 QoS 等级和遗嘱保留字段将会被服务端使 用,遗嘱属性、遗嘱主题和遗嘱消息字段必须存在于载荷中。[MQTT-3.1.2- 10]一旦遗嘱消息被发布或者服务端收到包含原因码为 0x00(正常关闭) 的 DISCONNECT 报 文,遗嘱消息必须从服务端的会话中删除。[MQTT-3.1.2- 11]如果遗嘱标志设置为 0,遗嘱 QoS 等级必须也设置为 0 (0x00)。[MQTT-3.1.2- 12]如果遗嘱标志设置为 1,遗嘱 QoS 等级可以被设置为 0(0x00), 1(0x01)或 2 (0x02)。[MQTT-3.1.2- 13]如果遗嘱标志被设置为 0,遗嘱保留标志也必须设置为 0。[MQTT-3.1.2- 14]如果遗嘱标志被设置为 1 时,如果遗嘱保留被设置为 0,则服务端必须将遗嘱消息当做非 保留消息发布。[MQTT-3.1.2- 15]如果遗嘱保留被设置为 1,则服务端必须将遗嘱消息当做保留消息发布。[MQTT-3.1.2- 16]如果用户名标志被设置为 0,有效载荷中不能包含用户名字段。[MQTT-3.1.2- 17]如果用户名标志被设置为 0,有效载荷中必须包含用户名字段。[MQTT-3.1.2- 18]如果密码标志被设置为 0,有效载荷中不能包含密码字段。[MQTT-3.1.2- 19]如果密码标志被设置为 1,有效载荷中必须包含密码字段。[MQTT-3.1.2-20]如果保持连接值不为 0,且没有任何其它的 MQTT 控制报文可以发送,客户端必须发送一 个 PINGREQ 报文。 [MQTT-3.1.2-21]如果服务端返回的 CONNACK 报文中包含服务端保持连接,客户端必须使用此值代替其发 送的保持连接。[MQTT-3.1.2-22]如果保持连接的值非零,并且服务端在 1.5 倍的保持连接时间内没有收到客户端的 MQTT 控制报文,它必须断开客户端的网络连接, 并判定网络连接已断开。[MQTT-3.1.2-23]如果网络连接关闭时会话过期间隔大于 0,则客户端与服务端必须存储会话状态。[MQTT-3.1.2-24]服务端不能发送超过最大报文长度的报文给客户端。[MQTT-3.1.2-25]当报文过大而不能发送时, 服务端必须丢弃这些报文,然后当做应用消息发送已完成处 理。[MQTT-3.1.2-26]服务端在一个 PUBLISH 报文中发送的主题别名不能超过客户端设置的主题别名最大值。[MQTT-3.1.2-27]如果主题别名最大值没有设置,或者设置为零,则服务端不能向此客户端发送任何主题别 名。[MQTT-3.1.2-28]请求响应信息值为 0,表示服务端不能返回响应信息。[MQTT-3.1.2-29]如果请求问题信息的值为 0,服务端可以选择在 CONNACK 或 DISCONNECT 报文中返回 原因字符串或用户属性,但不能在除 PUBLISH ,CONNACK 或 DISCONNECT 之外的报  文中发送原因字符串或用户属性。[MQTT-3.1.2-30]如果客户端在 CONNECT 报文中设置了认证方法,则客户端在收到 CONNACK 报文之前 不能发送除 AUTH 或 DISCONNECT 之外的报文。[MQTT-3.1.3- 1]CONNECT 报文的载荷中包含由可变报头中的标志确定的一个或多个以长度为前缀的字  段。这些字段若存在, 必须按照客户标识符、遗嘱属性、遗嘱主题、遗嘱载荷、用户名、 密码的顺序出现。[MQTT-3.1.3-2]客户端和服务端都必须使用客户标识符识别两者之间的 MQTT 会话相关的状态。[MQTT-3.1.3-3]客户标识符必须存在,且作为 CONNECT 报文载荷的第一个字段出现。[MQTT-3.1.3-4]客户标识符必须被编码为 UTF-8 字符串。[MQTT-3.1.3-5]服务端必须允许 1 到 23 个字节长的 UTF-8 编码的客户标识符,客户标识符只能包含这些 字符:"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[MQTT-3.1.3-6]服务端可以允许客户端提供一个零字节的客户标识符, 如果这样做了, 服务端必须将这看 作特殊情况并分配唯一的客户标识符给那个客户端。[MQTT-3.1.3-7]服务端必须假设客户端提供了那个唯一的客户标识符, 且必须在 CONNACK 报文中返回分 配的客户标识符。 [MQTT-3.1.3-8]如果服务端拒绝了某个客户标识符, 它可以发送包含原因码 0x85 (客户标识符无效)的CONNACK 报文作为对客户端的 CONNECT 报文的回应 ,如 4.13 节所述。之后必须关闭 网络连接。[MQTT-3.1.3-9]如果某个会话在遗嘱延时间隔到期之前创建了新的网络连接,则服务端不能发送遗嘱消 息。[MQTT-3.1.3- 10]服务端在发布遗嘱消息时必须维护用户属性的顺序。[MQTT-3.1.3- 11]遗嘱主题必须为 UTF-8 编码的字符串。[MQTT-3.1.3- 12]如果用户名标志被设置为 1,用户名为载荷中下一个字段。用户名必须是 UTF-8 编码字符 串。[MQTT-3.1.4- 1]服务端必须按照 3.1 节的要求验证 CONNECT 报文, 如果报文不符合规范, 服务端关闭网 络连接。[MQTT-3.1.4-2]服务端可以检查 CONNECT 报文的内容是不是满足任何进一步的限制,应该执行身份验证 和授权检查。如果任何一项检查没通过,服务端必须关闭网络连接。[MQTT-3.1.4-3]如果客户标识符所代表的客户端已经连接到此服务端, 那么向原有的客户端发送一个包含 原因码为 0x8E(会话被接管)的 DISCONNECT 报文,并且必须关闭原有的网络连接。[MQTT-3.1.4-4]服务端必须对新开始标志进行处理。[MQTT-3.1.4-5]服务端必须使用包含原因码为 0x00(成功)的 CONNACK 报文对客户端的 CONNECT 报 文进行确认。[MQTT-3.1.4-6]如果服务端拒绝了 CONNECT 报文,它不能处理客户端在 CONNECT 报文之后发送的任 何除 AUTH 以外的报文。[MQTT-3.2.0- 1]服务端在发送任何除 AUTH 以外的报文之前必须先发送包含原因码为 0x00(成功)的 CONNACK 报文。[MQTT-3.2.0-2]服务端在一次网络连接中不能发送多个 CONNACK 报文。[MQTT-3.2.2- 1]第 1 个字节是连接确认标志,位 7- 1 是保留位且必须设置为 0。[MQTT-3.2.2-2]如果服务端接受一个新开始为 1 的连接, 服务端在 CONNACK 报文中除了把原因码设置为 0x00(成功)之外,还必须把会话存在标志设置为 0。[MQTT-3.2.2-3]如果服务端接受一个新开始为 0 的连接, 并且服务端已经保存了此客户标识符的会话状态,服务端在 CONNACK 报文中必须把会话存在标志设置为 1。否则,服务端必须把会话 存在标志设置为 0。无论如何,服务端在 CONNACK 报文中必须把原因码设置为 0x00(成功) 。[MQTT-3.2.2-4]如果客户端没有保存的会话状态,但收到会话存在标志为 1,客户端必须关闭网络连接。[MQTT-3.2.2-5]如果客户端保存了会话状态,但收到的会话存在标志为 0,客户端若要继续此网络连接, 它必须丢弃其保存的会话状态。 [MQTT-3.2.2-6]如果服务端发送的 CONNACK 报文中原因码非 0,它必须把会话存在标志设置为 0。[MQTT-3.2.2-7]如果服务端发送了一个包含原因码大于等于 128 的 CONNACK 报文,它随后必须关闭网 络连接。[MQTT-3.2.2-8]服务端发送的 CONNACK 报文必须设置一种原因码。[MQTT-3.2.2-9]如果服务端不支持 Qos 为 1 或 2 的 PUBLISH 报文, 服务端必须在 CONNACK 报文中发送 最大服务质量以指定其支持的最大 QoS 值。[MQTT-3.2.2- 10]即使不支持 QoS 为 1 或 2 的 PUBLISH 报文, 服务端也必须接受请求 QoS 为 0 、1 或 2 的 SUBSCRIBE 报文。[MQTT-3.2.2- 11]如果从服务端接收到了最大 QoS 等级, 则客户端不能发送超过最大 QoS 等级所指定的 QoS 等级的 PUBLISH 报文。[MQTT-3.2.2- 12]如果服务端收到包含遗嘱的 QoS 超过服务端处理能力的 CONNECT 报文,服务端必须拒  绝此连接。服务端应该使用包含原因码为 0x9B(不支持的 QoS 等级)的 CONNACK 报文 进行错误处理, 随后必须关闭网络连接。[MQTT-3.2.2- 13]如果服务端收到一个包含保留标志位 1 的遗嘱消息的 CONNECT 报文且服务端不支持保留消息,服务端必须拒绝此连接请求, 且应该发送包含原因码为 0x9A(不支持保留)的 CONNACK 报文,随后必须关闭网络连接。[MQTT-3.2.2- 14]从服务端接收到的保留可用标志为 0 时, 客户端不能发送保留标志设置为 1 的 PUBLISH 报文。[MQTT-3.2.2- 15]客户端不应该发送超过最大报文长度的报文给服务端。[MQTT-3.2.2- 16]如果客户端使用长度为 0 的客户标识符,服务端必须回复包含分配客户标识符的CONNACK 报文。分配客户标识符必须是没有被服务端的其他会话所使用的新客户标识 符。[MQTT-3.2.2- 17]客户端在一个 PUBLISH 报文中发送的主题别名值不能超过服务端设置的主题别名最大 值。[MQTT-3.2.2- 18]如果主题别名最大值没有设置,或者设置为 0,则客户端不能向此服务端发送任何主题别 名。[MQTT-3.2.2- 19]如果加上原因字符串之后的 CONNACK 报文长度超出了客户端指定的最大报文长度,则服 务端不能发送此原因字符串。[MQTT-3.2.2-20]如果加上用户属性之后的 CONNACK 报文长度超出了客户端指定的最大报文长度,则服务 端不能发送此属性。[MQTT-3.2.2-21]如果服务端发送了服务端保持连接属性,客户端必须使用此值代替其在 CONNECT 报文中 发送的保持连接时间值。[MQTT-3.2.2-22]如果服务端没有发送服务端保持连接属性, 服务端必须使用客户端在 CONNECT 报文中设 置的保持连接时间值。 [MQTT-3.3.1- 1]客户端或服务端请求重发一个 PUBLISH 报文时,必须将 DUP 标志设置为 1。[MQTT-3.3.1-2]对于 QoS 为 0 的消息, DUP 标志必须设置为 0。[MQTT-3.3.1-3]发送(出站)的 PUBLISH 报文与收到(入站)的 PUBLISH 报文中的 DUP 标志是独立设 置的,它的值必须单独的根据发送(出站) 的 PUBLISH 报文是否是一个重发来确定。[MQTT-3.3.1-4]PUBLISH 报文的 2 个 QoS 比特位不能同时设置为 1。[MQTT-3.3.1-5]如果客户端发给服务端的 PUBLISH 报文的保留标志被设置为 1,服务端必须存储此应用消 息,并用其替换此话题下任何已存在的消息。[MQTT-3.3.1-6]如果载荷为空, 消息可以正常被服务端所处理,但是此话题下的任何保留消息必须被丢 弃,并且此话题未来的订阅者将不会收到保留消息。[MQTT-3.3.1-7]载荷为空的保留消息将不能被存储在服务端。[MQTT-3.3.1-8]如果客户端发给服务端的 PUBLISH 报文的保留标志位为 0,服务器不能把此消息存储为保 留消息, 也不能丢弃或替换任何已存在的保留消息。[MQTT-3.3.1-9]如果保留消息处理属性被设置为 0,服务端必须发送主题与客户端订阅的主题过滤器相匹 配的所有保留消息。[MQTT-3.3.1- 10]如果保留消息处理属性被设置为 1,如果尚不存在匹配的订阅, 服务端必须发送主题与客 户端订阅的主题过滤器相匹配的所有保留消息。如果已存在相匹配的订阅,服务器不能发 送这些保留消息。[MQTT-3.3.1- 11]如果保留消息处理属性被设置为 2,服务器不能发送这些保留消息。[MQTT-3.3.1- 12]如果发布保留订阅选项被设置为 0,服务端在转发应用消息时必须将保留标志设置为 0, 而不管收到的 PUBLISH 报文中保留标志位如何设置的。[MQTT-3.3.1- 13]如果发布保留订阅选项被设置为 1,服务端在转发应用消息时必须将保留标志设置为与收 到的 PUBLISH 消息中的保留标志位相同。[MQTT-3.3.2- 1]主题名必须是 PUBLISH 报文可变报头的第一个字段。它必须是 UTF-8 编码的字符串。[MQTT-3.3.2-2]PUBLISH 报文中的主题名不能包含通配符。[MQTT-3.3.2-3]服务端发送给订阅客户端的 PUBLISH 报文中的主题名必须匹配该订阅的主题过滤器。[MQTT-3.3.2-4]服务端必须把接收到的应用消息中的载荷格式指示原封不动的发给所有的订阅者。[MQTT-3.3.2-5]如果消息过期间隔已过期, 服务端还没开始向匹配的订阅者交付该消息,则服务端必须删 除该订阅者的消息副本。[MQTT-3.3.2-6]服务端发送给客户端的 PUBLISH 报文中必须包含消息过期间隔,值为接收时间减去消息 在服务端的等待时间。 [MQTT-3.3.2-7]接收端不能将任何主题别名映射从一个网络连接转发到另一个网络连接。[MQTT-3.3.2-8]发送端不能发送包含主题别名值为 0 的 PUBLISH 报文。[MQTT-3.3.2-9]客户端不能发送主题别名值大于服务端的 CONNACK 报文中指定的主题别名最大值的 PUBLISH 报文。[MQTT-3.3.2- 10]客户端必须接受所有值大于 0 且小于等于其发送的 CONNECT 报文中的主题别名最大值的 主题别名。[MQTT-3.3.2- 11]服务端不能发送包含主题别名值大于客户端在 CONNECT 报文中指定的主题别名最大值的 PUBLISH 报文。[MQTT-3.3.2- 12]服务端必须接受所有值大于 0 且小于等于其发送的 CONNACK 报文中的主题别名最大值的 主题别名。[MQTT-3.3.2- 13]响应主题必须是 UTF-8 编码的字符串。[MQTT-3.3.2- 14]响应主题不能包含通配符。[MQTT-3.3.2- 15]服务端在收到应用消息时必须将响应主题原封不动的发送给所有的订阅者。[MQTT-3.3.2- 16]服务端在收到应用消息时必须原封不动的把对比数据发送给所有的订阅者。[MQTT-3.3.2- 17]服务端在转发应用消息到客户端时必须原封不动的把所有的用户属性放在 PUBLISH 报文 中。[MQTT-3.3.2- 18]服务端在转发应用消息时必须保持所有用户属性的先后顺序。[MQTT-3.3.2- 19]内容类型必须是 UTF-8 编码的字符串。[MQTT-3.3.2-20]服务端必须把收到的应用消息中的内容类型原封不动的发送给所有的订阅者。[MQTT-3.3.4- 1]PUBLISH 报文的接收端必须按照 PUBLISH 报文中的 QoS 等级发送响应报文。[MQTT-3.3.4-2]这种情况下,服务端必须按照所有匹配的订阅中最大的 QoS 等级把消息发送给客户端。[MQTT-3.3.4-3]如果客户端在这些重叠的订阅中指定了订阅标识符,服务端在发布这些订阅相匹配的消息 时必须包含这些订阅标识符。[MQTT-3.3.4-4]如果服务端对这些重叠的订阅只发送一条相匹配的消息,服务端必须在 PUBLISH 报文中 包含所有的相匹配的订阅标识符(如果存在),但没有顺序要求。[MQTT-3.3.4-5]如果服务端对这些重叠的订阅必须分别发送相匹配的消息,则每个 PUBLISH 报文中包含 与订阅相匹配的订阅标识符(如果存在)。[MQTT-3.3.4-6]从客户端发送给服务端的 PUBLISH 报文不能包含订阅标识符。 [MQTT-3.3.4-7]客户端在收到服务端的 PUBACK ,PUBCOMP 或包含原因码大于等于 128 的 PUBREC 报 文之前, 不能发送数量超过服务端的接收最大值的 QoS 为 1 和 2 的 PUBLISH 报文。[MQTT-3.3.4-8]客户端不能延迟发送任何报文,除了 PUBLISH 报文--如果已发送且没有收到确认的 PUBLISH 报文数量已达到服务端的接收最大值。[MQTT-3.3.4-9]服务端在接收到客户端的 PUBACK ,PUBCOMP 或包含原因码大于等于 128 的 PUBREC 报文之前,不能发送数量超过客户端的接收最大值的 QoS 为 1 和 2 的 PUBLISH 报文。[MQTT-3.3.4- 10]服务端不能延迟发送任何报文,除了 PUBLISH 报文--如果已发送且没有收到确认的 PUBLISH 报文数量已到达客户端的接收最大值。[MQTT-3.4.2- 1]服务端或客户端发送 PUBACK 报文时必须设置其中一种 PUBACK 原因码。[MQTT-3.4.2-2]如果加上原因字符串之后的 PUBACK 报文长度超出了接收端指定的最大报文长度,则发送 端不能发送此原因字符串。[MQTT-3.4.2-3]如果加上用户属性之后的 PUBACK 报文长度超出了接收端指定的最大报文长度, 则发送端 不能发送此属性。[MQTT-3.5.2- 1]服务端或客户端发送 PUBREC 报文时必须设置其中一种原因码。[MQTT-3.5.2-2]发送端使用此值向接收端提供附加信息。如果加上原因字符串之后的 PUBREC 报文长度 超出了接收端指定的最大报文长度, 则发送端不能发送此属性。[MQTT-3.5.2-3]如果加上用户属性之后的 PUBREC 报文长度超出了接收端指定的最大报文长度, 则发送 端不能发送此属性。[MQTT-3.6.1- 1]PUBREL 固定报头的第 3 ,2 ,1 ,0 位是保留位, 必须被设置为 0 ,0 ,1 ,0。服务端必须 将其它的任何值都当做是不合法的并关闭网络连接。[MQTT-3.6.2- 1]客户端或服务端发送 PUBREL 报文时必须设置其中一种 PUBREL 原因码。[MQTT-3.6.2-2]如果加上原因字符串之后的 PUBREL 报文长度超出了接收端指定的最大报文长度, 则发送 端不能发送此原因字符串。[MQTT-3.6.2-3]如果加上用户属性之后的 PUBREL 报文长度超出了接收端指定的最大报文长度, 则发送端 不能发送此属性。[MQTT-3.7.2- 1]服务端或客户端发送 PUBCOMP 报文时必须设置一种 PUBCOMP 原因码。[MQTT-3.7.2-2]如果加上原因字符串之后的 PUBCOMP 报文长度超出了接收端指定的最大报文长度,则发 送端不能发送此原因字符串。[MQTT-3.7.2-3]如果加上用户属性之后的 PUBCOMP 报文长度超出了接收端指定的最大报文长度,则发送 端不能发送此属性。[MQTT-3.8.1- 1]SUBSCRIBE 报文固定报头第 3 ,2 ,1 ,0 比特位是保留位, 必须被设置为 0 ,0 ,1 ,0。 服务端必须将其他的任何值都当做是不合法的并关闭网络连接。[MQTT-3.8.3- 1]主题过滤器必须为 UTF-8 编码的字符串。 [MQTT-3.8.3-2]载荷必须包含至少一个主题过滤器/订阅选项对。[MQTT-3.8.3-3]订阅选项的第 2 比特表示非本地选项。值为 1,表示应用消息不能被转发给发布此消息的 客户标识符。[MQTT-3.8.3-4]共享订阅时把非本地选项设为 1 将造成协议错误。[MQTT-3.8.3-5]订阅选项的第 6 和 7 比特为将来所保留。服务端必须把此保留位非 0 的 SUBSCRIBE 报文 当做无效报文。[MQTT-3.8.4- 1]当服务端收到来自客户端的 SUBSCRIBE 报文时, 必须使用 SUBACK 报文作为相应。[MQTT-3.8.4-2]SUBACK 报文必须和待确认的 SUBSCRIBE 报文有相同的报文标识符。[MQTT-3.8.4-3]如果服务端收到的 SUBSCRIBE 报文中的一个主题过滤器与当前会话的一个非共享订阅相 同,那么必须使用新的订阅替换现存的订阅。[MQTT-3.8.4-4]如果保留处理选项为 0,任何匹配该主题过滤器的保留消息必须被重发, 但替换订阅不能 造成应用消息的丢失。[MQTT-3.8.4-5]如果服务端收到的 SUBSCRIBE 报文包含多个主题过滤器,服务端必须当做收到一系列多 个 SUBSCRIBE 报文来处理--除了将它们的响应组合为单个 SUBACK 响应。[MQTT-3.8.4-6]服务端发送给客户端的 SUBACK 报文必须为每一个主题过滤器/订阅选项对包含一个原因 码。[MQTT-3.8.4-7]此原因码必须说明为该订阅授予的最大 QoS 等级,或指示订阅失败。[MQTT-3.8.4-8]响应该订阅的应用消息 QoS 等级必须为该消息发布时的 QoS 等级和服务端授予的最大 QoS 等级二者最小值。[MQTT-3.9.2- 1]如果加上原因字符串之后的 SUBACK 报文长度超出了客户端指定的最大报文长度,则服务 端不能发送此原因字符串。[MQTT-3.9.2-2]如果加上用户属性之后的 SUBACK 报文长度超出了客户端指定的最大报文长度, 则服务端 不能发送此属性。[MQTT-3.9.3- 1]SUBACK 报文中的原因码顺序必须与 SUBSCRIBE 报文中的主题过滤器顺序相匹配。[MQTT-3.9.3-2]服务端发送 SUBACK 报文时必须对收到的每一个主题过滤器设置一种原因码。[MQTT-3.10.1- 1]UNSUBSCRIBE 固定报头的第 3 ,2 ,1 ,0 位是保留位且必须分别设置为 0 ,0 ,1 ,0。 服务端必须认为任何其它的值都是不合法的并关闭网络连接。[MQTT-3.10.3- 1]UNSUBSCRIBE 报文中的主题过滤器必须为 UTF-8 编码的字符串。[MQTT-3.10.3-2]UNSUBSCRIBE 报文有效载荷必须包含至少一个主题过滤器。 [MQTT-3.10.4- 1]服务端必须对客户端的 UNSUBSCRIBE 报文中提供的主题过滤器(不管是否包含通配符)逐个字符与当前持有的主题过滤器集进行比较。如果任何过滤器完全匹配,则必须删 除其拥有的订阅。[MQTT-3.10.4-2]当服务端收到 UNSUBSCRIBE 报文,它必须停止添加为了交付给客户端的与主题过滤器 相匹配的任何新消息。[MQTT-3.10.4-3]当服务端收到 UNSUBSCRIBE 报文,它必须完成任何已经开始发送给客户端的、与主题 过滤器相匹配的、QoS 等级为 1 或 2 的消息。[MQTT-3.10.4-4]服务端必须发送 UNSUBACK 报文以响应客户端的 UNSUBSCRIBE 请求。[MQTT-3.10.4-5]UNSUBACK 报文必须包含和 UNSUBSCRIBE 报文相同的报文标识符。即使没有删除任何 主题订阅,服务端也必须发送一个 UNSUBACK 响应。[MQTT-3.10.4-6]如果服务端收到的 UNSUBSCRIBE 报文包含多个主题过滤器, 服务端必须当做收到一系 列多个 UNSUBSCRIBE 报文来处理--除了将它们的响应组合为单个 SUBACK 响应。[MQTT-3.11.2- 1]如果加上原因字符串之后的 UNSUBACK 报文长度超出了客户端指定的最大报文长度,则 服务端不能发送此原因字符串。[MQTT-3.11.2-2]如果加上用户属性之后的 UNSUBACK 报文长度超出了客户端指定的最大报文长度,则服 务端不能发送此属性。[MQTT-3.11.3- 1]UNSUBACK 报文中的原因码顺序必须与 UNSUBSCRIBE 报文中的主题过滤器顺序相匹 配。[MQTT-3.11.3-2]服务端发送 UNSUBACK 报文时对于每个收到的主题过滤器, 必须使用一个取消订阅原因 码。[MQTT-3.12.4- 1]服务端必须发送 PINGRESP 报文响应客户端的 PINGREQ 报文。[MQTT-3.14.0- 1]服务端不能发送 DISCONNECT 报文,直到它发送了包含原因码小于 0x80 的 CONNACK 报文之后。[MQTT-3.14.1- 1]服务端或客户端必须验证所有的保留位都被设置为 0,如果他们不为 0,发送包含原因码 为 0x81(无效报文)的 DISCONNECT 报文。[MQTT-3.14.2- 1]客户端或服务端发送 DISCONNECT 报文时必须使用一种 DISCONNECT 原因码。[MQTT-3.14.2-2]会话过期间隔不能由服务端的 DISCONNECT 报文发送。[MQTT-3.14.2-3]如果此属性使得 DISCONNECT 报文的长度超出了接收端指定的最大报文长度,则发送端 不能发送此属性。[MQTT-3.14.2-4]如果加上用户属性之后的 DISCONNECT 报文长度超出了接收端指定的最大报文长度,则 发送端不能发送此属性。[MQTT-3.14.4- 1]发送端发送完 DISCONNECT 报文之后不能再在此网络连接上发送任何 MQTT 控制报文。 [MQTT-3.14.4-2]发送端发送完 DISCONNECT 报文之后必须关闭网络连接。[MQTT-3.14.4-3]接收到包含原因码为 0x00 (成功) 的 DISCONNECT 时,服务端必须丢弃任何与当前连接 相关的遗嘱消息,而不发布它。[MQTT-3.15.1- 1]AUTH 报文固定报头第 3 ,2 ,1 ,0 位是保留位, 必须全设置为 0。客户端或服务端必须把 其他值当做无效值并关闭网络连接。[MQTT-3.15.2- 1]AUTH 报文的发送端必须使用一种认证原因码。[MQTT-3.15.2-2]如果加上原因字符串之后的 AUTH 报文长度超出了接收端所指定的最大报文长度, 则发送 端不能发送此属性。[MQTT-3.15.2-3]如果加上用户属性之后的 AUTH 报文长度超出了接收端指定的最大报文长度, 则服务端不 能发送此属性。[MQTT-4.1.0- 1]当网络连接打开时,客户端和服务端不能丢弃会话状态。[MQTT-4.2.0- 1]客户端或服务端必须支持使用一个或多个提供有序的、可靠的、双向传输(从客户端到服 务端和从服务端到客户端) 字节流传输的底层传输协议。[MQTT-4.1.0-2]当网络连接被关闭并且会话过期间隔已过时,服务端必须丢弃会话状态。[MQTT-4.3.1- 1]对于 QoS 等级 0 的分发协议,发送端必须发送 QoS 等于 0 ,DUP 等于 0 的 PUBLISH 报 文。[MQTT-4.3.2- 1]对于 QoS 等级 1 的分发协议,发送端每次发送新的应用消息都必须分配一个未使用的用户 标识符。[MQTT-4.3.2-2]对于 QoS 等级 1 的分发协议,发送端发送的 PUBLISH 报文必须包含报文标识符且 QoS 等于 1 ,DUP 等于 0。[MQTT-4.3.2-3]对于 QoS 等级 1 的分发协议,发送端必须将这个 PUBLISH 报文看作是未确认的,直到从 接收端那收到对应的 PUBACK 报文。[MQTT-4.3.2-4]对于 QoS 等级 1 的分发协议,接收端响应的 PUBACK 报文必须包含一个报文标识符,这 个标识符来自接收到的、已经接受所有权的 PUBLISH 报文。[MQTT-4.3.2-5]对于 QoS 等级 1 的分发协议,接收端发送了 PUBACK 报文之后,接收端必须将任何包含 相同报文标识符的入站 PUBLISH 报文当做一个新的消息,并忽略它的 DUP 标志的值。[MQTT-4.3.3- 1]对于 QoS 等级 2 的分发协议,发送端必须给要发送的新应用消息分配一个未使用的报文标 识符。[MQTT-4.3.3-2]对于 QoS 等级 2 的分发协议,发送端 PUBLISH 报文必须包含报文标识符且报文的 QoS 等于 2 ,DUP 等于 0。[MQTT-4.3.3-3]对于 QoS 等级 2 的分发协议,发送端必须将这个 PUBLISH 报文看作是未确认的,直到从 接收端那收到对应的 PUBREC 报文。 [MQTT-4.3.3-4]对于 QoS 等级 2 的分发协议,收到发送端发送的包含原因码小于 0x80 的 PUBREC 报文  后必须发送一个 PUBREL 报文。 PUBREL 报文必须包含与原始 PUBLISH 报文相同的报文 标识符。[MQTT-4.3.3-5]对于 QoS 等级 2 的分发协议,发送端必须将这个 PUBREL 报文看作是未确认的,直到从 接收端那收到对应的 PUBCOMP 报文。[MQTT-4.3.3-6]对于 QoS 等级 2 的分发协议,发送端一旦发送了对应的 PUBREL 报文就不能重发这个 PUBLISH 报文。[MQTT-4.3.3-7]对于 QoS 等级 2 的分发协议,如果 PUBLISH 报文已发送, 不能应用消息过期属性。[MQTT-4.3.3-8]对于 QoS 等级 2 的分发协议,接收端响应的 PUBREC 报文必须包含报文标识符,这个标 识符来自接收到的、已经接受所有权的 PUBLISH 报文。[MQTT-4.3.3-9]对于 QoS 等级 2 的分发协议,如果接收端发送了包含原因码大于等于 0x80 的 PUBREC 报文,它必须将后续包含相同报文标识符的 PUBLISH 报文当做是新的应用消息。[MQTT-4.3.3- 10]对于 QoS 等级 2 的分发协议,接收端在收到对应的 PUBREL 报文之前,接收端必须发送 PUBREC 报文确认任何后续的具有相同报文标识符的 PUBLISH 报文。在这种情况下,它 不能重复分发消息给任何后续的接收者。[MQTT-4.3.3- 11]对于 QoS 等级 2 的分发协议,接收端必须发送包含与 PUBREL 相同报文标识符的 PUBCOMP 报文作为对 PUBREL 报文的响应。[MQTT-4.3.3- 12]对于 QoS 等级 2 的分发协议,接收端发送 PUBCOMP 报文之后,必须将后续包含相同报 文标识符的 PUBLISH 报文当做是新的应用消息。[MQTT-4.3.3- 13]对于 QoS 等级 2 的分发协议,接收端必须继续 QoS 等级 2 确认序列,即使它已经应用了 消息过期属性。[MQTT-4.4.0- 1]客户端以新开始标志为 0 且会话存在的情况下重连时, 客户端和服务端都必须使用原始报 文标识符重新发送任何未被确认的 PUBLISH 报文(当 QoS > 0)和 PUBREL 报文。这是 唯一要求客户端或服务端重发消息的情况。客户端和服务端不能在其他任何时间重发消息。[MQTT-4.4.0-2]如果收到包含原因码大于等于 0x80 的 PUBACK 或 PUBREC,则对应的 PUBLISH 报文被 看作已确认,且不能被重传。[MQTT-4.5.0- 1]当服务端接受入站应用消息的所有权时,它必须将消息添加到订阅匹配的客户端的会话状 态中。[MQTT-4.5.0-2]客户端必须按照可用的服务质量(QoS)规则确认它收到的任何 PUBLISH 报文, 不管它 是否选择处理其包含的应用消息。[MQTT-4.6.0- 1]重发任何之前的 PUBLISH 报文时, 客户端必须按原始 PUBLISH 报文的发送顺序重发(适 用于 QoS 等级 1 和 QoS 等级 2 消息)。[MQTT-4.6.0-2]客户端必须按照对应的 PUBLISH 报文的顺序发送 PUBACK 报文(QoS 等级 1 消息)。[MQTT-4.6.0-3]客户端必须按照对应的 PUBLISH 报文的顺序发送 PUBREC 报文(QoS 等级 2 消息)。 [MQTT-4.6.0-4]客户端必须按照对应的 PUBREC 报文的顺序发送 PUBREL 报文(QoS 等级 2 消息)。[MQTT-4.6.0-5]当服务端处理发布到有序主题的消息时,它必须按照消息从任何给定客户端接收的顺序发 送 PUBLISH 报文给消费端(对于同一主题和 QoS 等级)。[MQTT-4.6.0-6]默认情况下,服务端转发非共享订阅的消息时, 必须将每个主题都视为有序主题。[MQTT-4.7.0- 1]主题过滤器中可以使用通配符,但是主题名不能使用通配符。[MQTT-4.7.1- 1]多层通配符必须单独指定,或者跟在主题层级分隔符后面。不管哪种情况,它都必须是主 题过滤器的最后一个字符。[MQTT-4.7.1-2]在主题过滤器的任意层级都可以使用单层通配符, 包括第一个和最后一个层级。在使用它 时,它必须占据过滤器的整个层级。[MQTT-4.7.2- 1]服务端不能将$字符开头的主题名匹配通配符(#或+ )开头的主题过滤器。[MQTT-4.7.3- 1]所有的主题名和主题过滤器必须至少包含一个字符。[MQTT-4.7.3-2]主题名和主题过滤器不能包含空字符(Unicode U+0000)。[MQTT-4.7.3-3]主题名和主题过滤器是 UTF-8 编码字符串,它们不能超过 65,535 字节。[MQTT-4.7.3-4]匹配订阅时,服务端不能对主题名或主题过滤器执行任何规范化处理, 不能修改或替换任 何未识别的字符。[MQTT-4.8.2- 1]共享订阅主题过滤器必须以"$share/"开始, 且必须包含至少一个字符长度的共享名。[MQTT-4.8.2-2]共享名不能包含字符"/" ,"+"或"#",但必须跟在"/"字符后面。此"/"字符后面必须跟随一个主 题过滤器。[MQTT-4.8.2-3]向客户端发送应用消息时, 服务端必须考虑授予客户端的 QoS 等级。[MQTT-4.8.2-4]服务端必须在客户端重新连接时完成向该客户端的消息分发。[MQTT-4.8.2-5]如果客户端的会话在客户端重连之前终止, 服务端不能把此消息发送给其他订阅的客户 端。[MQTT-4.8.2-6]如果客户端对来自服务端的 PUBLISH 报文使用包含原因码大于等于 0x80 的 PUBACK 或 PUBREC 报文进行响应, 服务端必须丢弃应用消息而不尝试将其发送给任何其他订阅者。[MQTT-4.9.0- 1]客户端或服务端必须将其初始发送配额设置为不超过接收最大值的非 0 值。[MQTT-4.9.0-2]每当客户端或服务端发送了一个 QoS 等级大于 0 的 PUBLISH 报文, 它就会减少发送配  额。如果发送配额减为 0,客户端或服务端不能再发送任何 QoS 等级大于 0 的 PUBLISH 报文。 [MQTT-4.9.0-3]它可以继续发送 QoS 为 0 的 PUBLISH 报文, 也可以选择暂停发送这些报文。即使配额为 0,客户端和服务端也必须继续处理和响应其他 MQTT 控制报文。[MQTT-4.12.0- 1]如果服务端不支持客户端提供的认证方法, 它可以发送一个包含原因码 0x8C(无效的认证 方法)或 0x87(未授权)的 CONNACK 报文, 并且必须关闭网络连接。[MQTT-4.12.0-2]如果服务端需要额外的信息来完成认证,它可以向客户端发送 AUTH 报文,此报文必须包 含原因码 0x18(继续认证)。[MQTT-4.12.0-3]客户端通过发送另一个 AUTH 报文响应来自服务端的 AUTH 报文,此报文必须包含原因码 0x18(继续认证)。[MQTT-4.12.0-4]服务端可以在处理过程中随时拒绝认证。它可以发送包含原因码大于等于 0x80 的 CONNACK 报文,如 4.13 节所述, 并且必须关闭网络连接。[MQTT-4.12.0-5]如果初始 CONNECT 报文包含认证方法属性,则所有的 AUTH 报文和成功的 CONNACK 报文必须包含与 CONNECT 报文中相同的认证方法属性。[MQTT-4.12.0-6]如果客户端在 CONNECT 报文中没有包含认证方法, 则服务端不能发送 AUTH 报文,且 不能在 CONNACK 报文中发送认证方法。[MQTT-4.12.0-7]如果客户端在 CONNECT 报文中没有包含认证方法, 则客户端不能向服务端发送 AUTH 报文。[MQTT-4.12.1- 1]如果客户端在 CONNECT 报文中提供了认证方法,它可以在收到 CONNACK 报文之后的 任何时间通过发送包含原因码 0x19(重新认证)的 AUTH 报文发起重新认证。客户端必 须将认证方法设置为与最初验证网络连接时的认证方法一致。[MQTT-4.12.1-2]如果重新认证失败,客户端或服务端应该发送包含适当原因码的 DISCONNECT 报文,如 section 4.13 节 所述。并且必须关闭网络连接。[MQTT-4.13.1- 1]当服务端检测到无效报文或协议错误,并且本规范中给出了相应的原因码时, 它必须关闭 网络连接。[MQTT-4.13.2- 1]CONNACK 报文和 DISCONNECT 报文允许使用大于等于 0x80 的原因码以指示网络连接 将被关闭。如果某个大于等于 0x80 的原因码被指定, 无论是否发送 CONNACK 报文或  DISCONNECT 报文, 必须关闭网络连接。[MQTT-6.0.0- 1]MQTT 控制报文必须使用 WebSocket 二进制数据帧发送。如果收到任何其它类型的数据 帧,接收者必须关闭网络连接。[MQTT-6.0.0-2]单个 WebSocket 数据帧可以包含多个或者部分 MQTT 报文。接收者不能假设 MQTT 控制 报文按 WebSocket 帧边界对齐。[MQTT-6.0.0-3]客户端必须将字符串"mqtt"包含在它提供的 WebSocket 子协议列表里。[MQTT-6.0.0-4]服务端选择和返回的 WebSocket 子协议名必须是"mqtt"。 Appendix C. MQTT v5.0 新特性总结(非规范) MQTT v5.0添加了以下特性 .    会话过期 把清理会话标志拆分成新开始标志(指示会话应该在不使用现有会话的情况下开始)和会话过期间隔标 志(指示连接断开之后会话保留的时间)。会话过期间隔时间可以在断开时修改。 把新开始标志设置为 1且会话过期间隔标志设置为0,等同于在MQTT v3.1.1中把清理会话(CleanSession)设置为1。 .    消息过期 允许消息在发布时设置一个过期间隔。 .    所有确认报文原因码 更改所有响应报文以包含原因码,包括CONNACK ,PUBACK ,PUBREC ,PUBREL ,PUBCOMP, SUBACK ,UNSUBACK ,DISCONNECT和AUTH,以使得调用方确定请求的函数是否成功。 .    所有确认报文原因字符串 更改大部分报文以包含原因码同时也允许一个可选的原因字符串。这是为问题定位而设计的,并且不应 由接收端所解析。 .    服务端断开 允许服务端发送DISCONNECT报文,以指示连接被关闭的原因。 .    载荷格式和内容类型 允许在消息发布时指定载荷格式(二进制、文本) 和MIME样式内容类型。这些信息被转发到消息的接 收端。 .    请求/响应 规定MQTT请求/响应模式, 提供响应主题和对比数据属性,以使得响应消息被路由回请求的发布者。 此外,为客户端添加从服务端获取获取关于构造响应主题的配置信息的能力。 .    共享订阅 添加对共享订阅的支持,以允许多个订阅消费者进行负载均衡。 .    订阅标识符 允许在SUBSCRIBE报文中指定一个数字订阅标识符, 并在消息分发时返回此标识符。这使得客户端收 到分发的消息时确定此消息是由哪个或哪些订阅导致的。 .    主题别名 通过将主题名缩写为小整数来减小MQTT报文的开销大小。客户端和服务端分别指定它们允许的主题别 名的数量。 .    流量控制 允许客户端和服务端分别指定未完成的可靠消息(QoS>0)的数量。发送端可以暂停发送此类消息以 保持消息数量低于配额。这被用于限制可靠消息的速率和某一时刻的传输中(in-flight)消息数量。 .    用户属性 为大多数报文添加用户属性。PUBLISH报文的用户属性由客户端应用程序定义。PUBLISH报文和遗嘱 报文的用户属性由服务端转发给应用消息的接收端。CONNECT ,SUBSCRIBE和UNSUBSCRIBE报文 的用户属性由服务端实现定义。 CONNACK ,PUBACK ,PUBREC ,PUBREL ,PUBCOMP, SUBACK ,UNSUBACK和AUTH报文的用户属性由发送端定义,且对发送端具有唯一性。 MQTT规范 不定义用户属性的意义。 .    最大报文长度 允许客户端和服务端各自指定它们支持的最大报文长度。会话参与方发送更大的报文将造成错误。 .    可选的服务端功能可用性 提供定义一组服务端不允许的功能, 并告知客户端的机制。可以使用这种方式指定的功能包括:最大 QoS等级,保留可用, 通配符订阅可用,订阅标识符可用和共享订阅可用。客户端使用服务端通知了 (不可用)的功能将造成错误。 在早期版本的MQTT协议中,服务端没有实现的功能通过未授权告知客户端。 当客户端使用其中一种 (不可用的)功能时, 此功能允许服务端告知客户端, 并添加特定的原因码。 .    增强的认证 提供一种机制来启用包括互相认证在内的质询/响应风格的认证。这允许在客户端和服务端都支持的情 况下使用SASL风格的认证,包括客户端在连接中重新认证的功能。 .    订阅选项 提供主要用于定义允许消息桥接应用的订阅选项。包括不要把消息发送给消息源客户端(非本地) 的选 项和订阅时处理保留消息的选项。 .    遗嘱延迟 提供指定遗嘱消息在连接中断后延时发送的能力。设计此特性是为了在会话的连接重建的情况下不发送 遗嘱消息。此特性允许连接短暂中断而不通知其他客户端。 .    服务端保持连接 允许服务端指定其希望客户端使用的保持连接值。此特性允许服务端设置最大允许的保持连接值并被客 户端使用。 .    分配客户标识符 服务端分配了客户标识符的情况下, 向客户端返回此客户标识符。服务端分配客户标识符只能用于新开 始标志为1的连接。 .    服务端参考 允许服务端使用 CONNACK 或 DISCONNECT 报文指定备用服务端。此特性被用于(服务端) 重定向 或做准备。 --- ═══════════════════════════════════════════ ## MQTT 软件 ═══════════════════════════════════════════ ### 222. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、MQTT.fx简介MQTT.fx是一款功能强大、用户友好的MQTT客户端工具,专为设计、调试和测试基于MQTT的物联网(IoT)应用而构建。它提供了一个直观的界面,让连接、监控和管理MQTT主题变得轻而易举。无论是物联网爱好者还是专业开发者,MQTT.fx都是探索和实验MQTT协议的理想选择。 二、核心特性 直观的用户界面:MQTT.fx拥有一个清晰、直观的用户界面,即使是初学者也能快速上手。 实时数据监控:用户可以实时监控MQTT消息,包括订阅和发布的数据流,实现对信息流的即时掌控。 高级消息发布:支持定制化的消息发布,包括设置QoS等级、保留标志和有效载荷,为测试和开发提供了极大的灵活性。 丰富的调试功能:提供详细的日志记录,帮助用户追踪和解决在MQTT通信中遇到的问题。 脚本支持:支持使用脚本进行高级消息处理和流程自动化,为开发者提供了强大的自定义能力。 三、应用场景 物联网设备测试:开发者可以使用MQTT.fx测试物联网设备的MQTT通信,确保设备能够正确处理MQTT消息。 数据流分析:通过监控数据流,用户可以分析和优化消息传输过程,提高整体通信效率。 教育和研究:MQTT.fx也是一个教学和研究MQTT协议的绝佳工具,特别适合在学术和研究环境中使用。 四、如何入门使用MQTT.fx开始您的MQTT之旅非常简单。只需下载并安装MQTT.fx软件,配置您的MQTT服务器详情,即可开始创建连接、订阅主题和发布消息。 主界面 设置界面 用户名和密码 安全证书设置 网络代理设置 遗嘱设置 五、结语MQTT.fx不仅仅是一个工具,它是通信效率和便捷性的代名词,是连接现代物联网世界的桥梁。无论您是物联网领域的新手还是资深专家,MQTT.fx都将为您的项目增添不可或缺的价值。立刻体验MQTT.fx,开启您在物联网世界中的创新之旅吧! --- ### 223. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTTX Web,一款基于浏览器的MQTT 5.0客户端工具,以其开源性、易用性和高效性,在物联网(IoT)开发领域中占有一席之地。随着IoT领域的迅速发展,开发者们越来越需要这样一种工具,它能够在无需下载和安装的情况下快速连接和测试MQTT服务。MQTTX Web正是为了满足这种需求而设计,它提供了一种直观的方式来进行MQTT消息的发送和接收,从而加快了开发和调试过程。 MQTT X Web 简介 MQTT X Web 针对初次接触 MQTT 协议的用户而设计,提供了一种更加直观和便捷的方式来快速理解和上手 MQTT 协议。用户无需进行复杂的下载和安装步骤,只需在浏览器中打开相应页面,就可以迅速连接到 MQTT 服务和应用,进而探索和理解 MQTT 协议。 作为一个在线 MQTT 5.0 客户端工具,MQTT X Web 在浏览器中作为 MQTT 5.0 WebSocket 客户端运行,并具备以下主要功能: 支持通过标准或加密的 WebSocket 端口连接到 MQTT 服务。 管理连接的创建、编辑、删除及缓存,以便下次方便使用。 不同连接的订阅列表管理。 发布消息、接收消息,以及接收新消息时的提示功能,同时支持根据消息类型过滤消息列表。 相关资源链接: MQTT X Web 官网:https://mqttx.app/zh/web 在线使用地址:http://www.emqx.io/online-mqtt-client GitHub 仓库:https://github.com/emqx/MQTTX/tree/main/web MQTT over WebSocket 随着 Web 前端技术的迅猛发展,浏览器功能日益增强,越来越多的应用得以在浏览器端实现。其中,WebSocket 作为 Web 应用的实时通信方式,已被广泛应用。MQTT X Web 利用 WebSocket 技术连接 MQTT 服务,不仅使用方便,而且能够提供 MQTT over WebSocket 的连接测试功能。当需要在 Web 应用场景中使用 MQTT 时,用户可以通过 MQTT X Web 调试 MQTT 服务和应用,从而加速应用的开发并提高稳定性。 基于现代浏览器技术 MQTT X Web 基于现代浏览器技术开发,将应用部署到网页上,使用户无需下载和安装任何软件即可使用。此外,它还支持将新建的连接和消息信息等持久化存储到浏览器内,方便用户下次访问。 开源代码 MQTT X Web 的代码与 MQTT X 桌面应用及 CLI 保持一致,基于 Apache License 2.0 协议开源。高级用户可以直接从代码仓库中获取 MQTT X Web 的代码,根据自己的需要进行修改和部署。 开发和调试 MQTT 服务与应用 MQTT X Web 的图形化界面设计,采用类似聊天界面的形式,帮助用户快速测试 MQTT 服务,其使用方式与 MQTT X 桌面应用基本一致。用户只需在浏览器中输入 http://www.emqx.io/online-mqtt-client/ 就可以访问到 MQTT X Web。 有关如何使用 MQTT X Web 的更多详细介绍,请参考其使用文档:https://mqttx.app/zh/docs/get-started。 结语 MQTT X Web 的发布为物联网开发者提供了一种全新的 MQTT 连接测试方式。它对命令行调用、桌面客户端下载和在线浏览器交互的全面支持,使得 MQTT X 1.8.0 能够帮助不同场景下的用户开发和调试 MQTT 服务或应用,提高了用户的业务能力和稳定性。简单易用的 MQTT X 测试工具结合高效可靠的 EMQX 物联网消息服务器,将帮助物联网开发者构建更具竞争力的物联网平台和应用。 --- ### 224. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT CLI是一个完全兼容MQTT 5.0和MQTT 3.1.1的命令行界面,用于MQTT客户端,基于HiveMQ MQTT客户端API。 HiveMQ CLI是由HiveMQ支持的开源项目。 可以在GitHub上查看。 功能特点: 支持所有MQTT 3.1.1和MQTT 5.0特性 所有MQTT命令的交互式、直接和详细模式 具有语法高亮、命令历史记录的Shell行为 能够同时连接不同Broker的多个MQTT客户端 快速Broker测试 从HiveMQ API端点导出信息 提供多种发行版 新闻动态 前提条件运行MQTT CLI至少需要Java 8。 该CLI用Java 11实现,是运行此项目的首选版本。 Docker您可以在支持Docker的任何操作系统上运行MQTT-CLI。要执行一个简单的命令,请使用以下语法: docker run hivemq/mqtt-cli <您的命令> 要启动CLI的Shell-Mode,您需要在docker命令中添加-it标志: docker run -it hivemq/mqtt-cli shell Homebrew对于Mac OS X和Linux系统,请使用Homebrew通过MQTT CLI Tap安装MQTT CLI。 brew install hivemq/mqtt-cli/mqtt-cli 注意:如果您遇到类似Java 1.8+是安装此配方所需的错误,请安装高于1.8的java版本。您可以使用brew install --cask zulu来安装最新版本的Azul Zulu OpenJDK。 注意:由于延迟问题可能会减慢Mac OS X下CLI的速度,请验证您在/etc/hosts下指定了127.0.0.1 localhost 您的电脑名称。您可以使用sudo sh -c "echo 127.0.0.1 localhost $(hostname) >> /etc/hosts"将此配置附加到您的主机文件中。 Windows Zip下载Windows Zip文件并在您选择的位置解压缩。要执行MQTT CLI,只需用⊞ Win + R打开Windows命令提示符并执行cmd。导航到解压缩的MQTT CLI文件夹并执行mqtt -cli.exe。 要快速启动shell,只需双击mqtt-cli-shell.cmd文件。 Debian包如果您使用的是使用debian包的*nix操作系统,您可以通过wget或curl从发布页面下载MQTT CLI debian包,并使用sudo dpkg -i或sudo apt install安装该包: wget https://github.com/hivemq/mqtt-cli/releases/download/v4.22.0/mqtt-cli-4.22.0.deb sudo apt install ./mqtt-cli-4.22.0.deb RPM包对于Red Hat、Fedora、Mandriva、OpenSuse、CentOS等发行版,您可以在发布页面使用提供的rpm包。首选通过yum包管理器安装该包。要安装包,只需执行: sudo yum install -y https://github.com/hivemq/mqtt-cli/releases/download/v4.22.0/mqtt-cli-4.22.0.rpm 从源代码构建mqtt-cli使用Gradle进行构建。为了能够执行集成测试,需要一个运行中的Docker环境为了能够构建和测试本地镜像,需要安装GraalVM。您可以通过运行./gradlew installNativeImageTooling来设置。要进行干净的构建,请执行以下命令:./gradlew clean build 这将运行单元测试,并将新的mqtt-cli-.jar编译到build/libs中。然后,您可以通过替换现有MQTT CLI安装的mqtt-cli-.jar来更新它。 build.gradle.kts文件包含了进一步的指令,用于构建特定平台的发行包。简单来说: 对于MacOS/Linux brew: ./gradlew buildBrewFormula 对于Debian包: ./gradlew buildDebianPackage 对于RPM包: ./gradlew buildRpmPackage 对于Windows安装程序: ./gradlew buildWindowsZip 构建本地docker镜像: ./gradlew jibDockerBuild MQTT 发布命令说明 MQTT发布(publish)指令允许用户向一个或多个主题发送消息。 基本命令: mqtt publish别名: mqtt pub 简单示例 命令解释mqtt pub -t test -m "Hello"使用默认设置发布消息“Hello”至主题‘test’。mqtt pub -t test1 -t test2 -m "Hello Tests"发布消息“Hello Tests”至主题‘test1’和‘test2’。mqtt pub -t test -m "Hello" -h localhost -p 1884将消息“Hello”发布至主题‘test’,目标为localhost:1884的代理服务器。mqtt pub -t test -m:file payload.txt使用默认设置发布文件payload.txt中的消息至主题‘test’。 选项 发布选项: 选项完整版本解释默认值-t--topic要发布消息的MQTT主题。-m--message将在主题上发布的消息。-m:file--message-file包含要发布消息的文件。-m:empty--message-empty设置消息为空载荷。-r--[no-]retain消息是否保留。false-q--qos定义服务质量等级。如果只指定了一个QoS,则将用于所有主题。你可以为每个主题定义特定的QoS级别。0-e--messageExpiryInterval发布消息的生命周期(秒)。-ct--contentType发布消息内容的描述。-cd--correlationData发布消息的相关数据。-pf--payloadFormatIndicator发布消息的载荷格式指示符。-rt--responseTopic发布消息的响应消息主题名称。-up--userProperty发布消息的用户属性。 连接选项: 选项完整版本解释默认值-h--hostMQTT主机。localhost-p--portMQTT端口。1883-V--mqttVersion可以设置为3或5的MQTT版本。5-i--identifier可以定义唯一的客户端标识符。随机生成的UTF-8字符串。-ip--identifierPrefix如果没有给定标识符,则为随机生成的客户端标识符的前缀。mqttClient-c--[no-]cleanStart客户端是否开始一个干净的会话。truek--keepAlive客户端的保活时间(秒)。60-se--sessionExpiryInterval会话过期值(秒)。0(即时过期) --- ### 225. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 产品背景 随着物联网的快速发展,中小企业越来越需要集中管理数据。不论是物联网公有云方案还是传统的智能网关,都存在明显的缺陷。为此,Fox-Edge致力于提供一种新颖的边缘计算方案及配套产品。 方案亮点 1、传统应用系统解决方案 在传统的自动化行业中,各家设备生产企业由于业务场景的千差万别,以及生产成本因素的考量,它们生产的的智能设备在提供 通信接口的时候,普遍采用自定义的为私有接口,或者是在modbus、IEC104、DLT645等各种流行通信协议之上二次开发自己的私 有应用接口。 为了能够对这些私有接口的智能化设备进行管理,生产企业们普遍会另外提供一套厂家配套的现场监控系统,对自家的智能 设备进行监控管理。 但是用户的物联网,通常并不是单一的设备系统,而是多种设备系统的构成的综合网络。这就在用户的设备现场,形成一个个各家 设备生产厂商自成体系的独立式封闭系统。 各家厂家的监控系统,不但左右之间不能互联互通,而且在跟上面的业务系统也很难互联互通。它们跟用户期望的各应用场景打通, 集中化的业务数据分析,相距甚远。不能形成数据集中后所产生的商业价值。 2、物联网云平台解决方案 针对传统应用系统解决方案的缺陷,互联网新势力提出了通过MQTT、CoAP、NB等公共的通信接口,由设备一站式直通云端的数据中心的方案。 直接绕过现场组网、各家设备厂商的设备不能互联互通、难以数据上行到中心的业务系统的难题。 但是这种方案在解决了一批旧的问题的时候,也同时制造了一批新的问题。 1、 新增了MQTT、CoAP、NB等公共的通信模块后,每个设备的单位生产成本大幅度提升2、 设备与云端之间的电信网络,并不总是稳定的和可靠的,现场设备会经常面临脱管的危险,给用户带来损失3、 用户的设备数据上到云平台的时候,数据的所有权和访问权却不归属用户4、 物联网云平台只提供低代码平台对用户数据进行简单加工,但是用户对数据的业务场景却千变万化,异常复杂 上面的这些新的问题,对企业用户来说,可以说都是无法接受的红线。 它们只能用在面向消费者用户的场景,而不能用在面向企业的生产场景。 3、Fox-Edge的解决方案 结合上述两种方案的优点,并针对它们的缺点,Fox-Edge的方案是在物联网现场提供一个就近的边缘计算设备,对各种现场设备进行集中管 理,然后将数据推送给企业的数据中心,或者云端数据平台。 1、Fox-Edge边缘计算节点,部署在现场,下接现场网络,能够对就近管理,不受到上行电信网络断网的影响,高度可靠。2、Fox-Edge边缘计算节点,能够下行管理各种设备厂商生产的设备,也能上行统一对接企业的数据中心或者云端的云平台。3、不需要设备厂商为同一款设备,根据各种网络接口,生产一系列的子型号设备,降低研、生产、管理成本。4、灵狐技术在提供现场侧的Fox-Edge边缘计算产品的同时,也提供数据中心侧的Fox-Cloud产品供用户部署,数据所有权和控制权归属用户。5、Fox-Edge是通用性的免费产品,有众多的解码器、通道服务供用户选择,并且具有帮助用户快速进行二次开发的能力。 4、跟传统智能网关的对比 1、传统智能网关只能对接ModBus、IEC104、DLT645等少数几个固化的通信协议,而Fox-Edge能够通过解码器对接各种设备的各种私有接口2、传统智能网关只能进行数据透传,而Fox-Edge能够部署各种控制服务,完成对现场网络的各种管理和控制能力3、传统智能网关的定位只是简单的电子设备,容量和性能非常有限,但Fox-Edge部署的x86工控机拥有比肩计算机的性能4、传统智能网关属于小众设备,价格相对高昂,而Fox-Edge部署的x86工控机属于大量生产的通用性硬件,价格不过前者的几分之一 硬件需求 x86系列或者ARM系列的小型工控机 或者是 软路由 或者是 小型工业网关 这类小型物理设备 最低配置:4G物理内存(推荐8G内存),64G存储空间。 产品特色 fox-edge 边缘计算 采用积木式的全开放式的架构,方便用户自选各种组件和从仓库中选择解码器。目前正在增强解码器仓库功能,方便各用户互相分享自己开发的解码器。 积木式架构,用户可以根据自己的需要,可以从中央仓库中自行挑选组件和服务,搭建成适合自己项目的边缘计算系统 开放的架构,如果仓库中找不到适合自己项目的组件和服务,用户也可以自行开发或者委托第三方开发者开发组件和服务 共享的资源,中央仓库可以为用户们互相分享自己开发的解码器组件和各类应用服务 通用的平台,硬件环境运行在通用的x86工控机环境,不用担心专用设备对企业的绑定 方便的ODM,让企业可以将Fox-Edge部署在通用工控机上后,以企业自己的产品形式对外销售 免费的产品,用户可以从官网免费下载产品,用于非商业用途。 软件架构 Fox-Edge支持自定义通道服务部件和通信协议解码器插件,从而实现与现场网络设备的对接。此外,还支持自定义控制器、触发器部件和上行接口,以满足不同的业务需求。 在线演示 感兴趣的用户可以访问Fox-Edge的在线演示,或者从代码仓库中下载产品以进行非商业用途的使用。 演示地址:http://fox-edge-demo.fox-tech.cn 账号:admin 密码:12345678 代码仓库:https://gitee.com/fierce_wolf/fox-edge-server --- ### 226. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 FluxMQ是一款高性能,云原生的物联网接入网关,专为物联网、工业互联网、IT运维监控等场景设计并优化,具有极强的弹性伸缩能力,高并发,低延迟。能大幅度的减小物联网系统搭建过程中的复杂度,降低研发和运维成本,是一个物联网平台的基础且重要的组件。 官网:https://www.fluxmq.com/ 什么是FluxMQ? 产品介绍 FLuxMQ是一款基于java开发,支持无限设备连接的云原生分布式物联网接入平台。FluxMQ基于Netty开发,底层采用Reactor3反应堆模型,具备低延迟,高吞吐量,百万-千万设备连接;方便企业快速构建其物联网平台与应用。 核心特性 「高性能」单机支持百万TCP连接、并且支持数10万的TPS消息包上报,规则引擎支持处理海量的设备数据桥接到数据源。 「支持标准MQTT协议」完整支持MQTT3.x和MQTT5.0 协议标准;支持Qos0,1,2的MQTT消息传递;支持所有MQTT客户端和库; 「配置持久化」所有功能支持WEB配置,集群自带持久化功能,重启后配置不丢失 「规则引擎」灵活的规则模型配置,支持多种数据桥接和数据持久化; 「SQL引擎」支持实时流SQL引擎,支持对MQTT跟扩展协议进行数据流清洗 「数据安全」基于MQTT overTLS/SSL确保数据安全;LDAP,PSK和X.509证书等多种身份认证; 「灵活部署」支持物理机,容器,私有云,公有云中任何地方运行,不受位置限制,不受厂商锁定; 「低成本」性能卓越,降低硬件需求成本;支持买断和按需付费; 功能概览 功能说明集群功能支持MQTT、MQTTS、MQTT OVER WEBSOCKET集群发布订阅支持标准发布订阅服务等级QoS0,1,2ACL控制客户端发布订阅权限流量控制限制Broker接入流量管理页面-连接管理管理客户端状态,上下线管理页面-ACL访问授权管理页面-订阅查询查看设备订阅Topic管理页面-规则引擎转发消息管理页面-云客户端基于ws进行模拟测试管理页面-动态认证连接认证管理页面-日志管理标准接入日志管理页面-监控管理grafana监控方案管理页面-数据源管理多数据源管理页面-告警功能支持钉钉、微信、飞书管理页面-协议解析支持脚本解析处理payload管理页面-多协议支持Coap、Websocket、I1、V2x等协议 FluxMQ的核心特点 「高性能」:FluxMQ采用了最新的消息处理技术和数据压缩算法,提供高吞吐量、低延迟的数据传输能力,为您的物联网应用带来卓越的性能体验。 「易于使用」:FluxMQ提供了简洁明了的API接口和丰富的文档资源,无论您是物联网初学者还是经验丰富的开发者,都能轻松上手并快速实现项目部署。 「高安全性」:FluxMQ支持TLS/SSL加密通信,确保数据在传输过程中的安全性。同时,提供了多种鉴权机制和访问控制策略,保护您的物联网应用免受未经授权的访问和攻击。 「高可靠性」:FluxMQ具备强大的故障转移和负载均衡功能,确保在各种异常情况下保持稳定的运行。此外,FluxMQ还支持消息持久化,防止因意外断线等原因造成的数据丢失。 「广泛适用性」:FluxMQ适用于各种规模的物联网应用场景,从智能家居、工业自动化到智能交通、智慧城市等,都能发挥其卓越性能,满足不同行业的需求。 FluxMQ——高性能压测报告 压测配置 服务版本操作系统CPU内存数量FluxMQ1.0.0Centos 7.616C32G1Kafka集群--Centos 7.648C128G3 纯连接100W 服务运行情况CPU物理内存备注说明EMQX100W正常12%40%FluxMQ100W正常5.5%63%;JVM内存6.58G 高并发吞吐 测试单条数据payload:1024B 服务5WTPS/5W连接10WTPS/10W连接15WTPS/15W连接20WTPS/20W连接EMQX正常正常崩溃崩溃FluxMQ正常正常正常正常 10WTPS下性能对比 服务运行情况CPU物理内存备注说明EMQX10WTPS正常12%40%FluxMQ10WTPS正常10%64%;JVM内存17.6G 高并发连接下高吞吐 ❝ 测试单条数据payload:1024B;❞ 服务5WTPS/95W连接9WTPS/99W连接10WTPS/100W连接FluxMQ正常正常正常 9WTPS/99万连接下性能对比 服务运行情况CPU物理内存备注说明FluxMQ10WTPS正常12%95%;JVM内存18.3G --- ### 227. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 中文站:MQTT Assistant - MQTT可视化管理与监控工具 (redisant.cn) 英文站:MQTT Assistant - MQTT visual management and monitoring tool (redisant.com) 在IoT和边缘计算的时代,MQTT已成为消息传输的首选协议之一。而MQTT Assistant的出现,无疑是此领域的一大进步。它不仅提供了一系列强大的功能,还在性能和用户体验方面进行了优化。 1. GPU加速渲染:MQTT Assistant的首要特点是其对GPU的利用。当进行渲染界面时,它会充分发挥GPU的优势,为用户提供一个流畅而高效的体验。更值得一提的是,其在渲染过程中的功率消耗比许多传统应用更低,确保了高性能的同时还节能环保。 2. 主题的结构化与实时预览:通过MQTT Assistant,用户可以轻松地看到以树状结构组织的主题,使得主题间的关系一目了然。此外,它还提供了实时预览功能,使得消息到达时,用户能够立即得知。 3. 图表的绘制与数据可视化:对于每一个主题,MQTT Assistant都能保留其历史消息,随后根据消息的内容自动绘制出各种图表,如折线图、二次拟合图和阶梯图,使得数据的变化趋势清晰可见。 4. 数据的智能识别与格式化:无论是Text、JSON、XML、HEX还是MessagePack,MQTT Assistant都能够智能地识别并格式化,为用户呈现出整齐且清晰的数据格式。 5. 数据模板与压力测试:为了满足开发和测试的需求,MQTT Assistant提供了数据模板功能,帮助用户快速生成大量的模拟数据。与此同时,它还配备了压力测试工具,允许用户一次性发送数千条消息,以评估系统处理大量数据的能力。 6. 高效的资源管理与协议支持:MQTT Assistant的性能优化不仅体现在GPU渲染上,其整体的资源管理也做得相当出色,相比于使用Electron等Web技术开发的应用程序,它的资源消耗要少得多。此外,它还支持最新的MQTT v5.0和MQTT v3.1.1协议,并且可以通过WebSocket连接到MQTT服务器。 7. 安全性与本地化测试:考虑到数据的安全性,MQTT Assistant支持SSL/TLS加密,确保数据传输的安全。而为了方便用户进行本地测试,它还内置了一个MQTT服务器,支持MQTT v5.0协议,并能在毫秒级内完成启动和关闭。 总的来说,MQTT Assistant是一个全面而高效的MQTT工具,无论是对于开发人员还是日常使用者,它都能提供卓越的服务。 --- ═══════════════════════════════════════════ ## MQTT 进阶 ═══════════════════════════════════════════ ### 228. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着物联网(IoT)技术的飞速发展,消息队列遥测传输(MQTT)协议作为一种轻量级的消息传递协议,在物联网设备间的消息传输中扮演着重要的角色。尤其是MQTT 5.0的发布,为开发者带来了一系列创新特性,极大地拓宽了MQTT协议的应用场景。其中,用户属性(User Properties)的引入为自定义消息元数据提供了无限可能,本文将探索用户属性的概念、必要性及其在实际应用中的运用,以通俗易懂的方式向开发者展示这一新特性的魅力。 用户属性的定义与必要性 用户属性是MQTT 5.0引入的一种新特性,允许在MQTT消息中添加自定义的键值对信息,从而传递额外的自定义元数据。每个键值对都由UTF-8编码的字符串组成,为消息传递提供了更丰富的上下文信息。这一功能与HTTP协议中的Header概念相似,但设计得更为灵活,可以无限扩展。 在MQTT 5.0之前,MQTT的扩展性较差,用户难以在标准协议基础上传递特定的元数据信息。用户属性的引入有效解决了这一问题,不仅支持在客户端与MQTT服务器间传递任意信息,还可在客户端间实现元数据的交换,极大增强了MQTT的可用性和灵活性。 应用场景举例 场景一:文件传输 在传统的MQTT通信中,文件通常被转换为二进制数据并嵌入到消息的Payload中进行传输。MQTT 5.0允许通过用户属性传输文件的元数据,如文件名、类型等,而文件内容仍通过Payload传输。这样,接收方可以在收到消息前就获得文件的相关信息,从而更有效地处理文件数据。 例如,发送方可以设置以下用户属性来传输一个文本文件: { "filename": "example.txt", "filetype": "text/plain" } 场景二:资源解析 在一个全球分布的物联网系统中,不同地区的设备可能使用不同格式的消息进行通信(如JSON、XML)。通过用户属性,发送方可以指明消息格式和地区信息,使得MQTT服务器或接收方能够根据这些元数据选择正确的解析器解析消息。 例如,一个位于欧洲的设备发送的消息可能包含以下用户属性: { "region": "Europe", "format": "JSON" } 场景三:消息路由 用户属性还可以用于实现更高级的消息路由机制。在复杂的物联网应用中,根据消息的类型、优先级或目的地对消息进行路由是非常常见的需求。通过在消息中添加相应的用户属性,MQTT服务器可以根据这些属性将消息路由到正确的处理队列或服务。 例如,一个紧急报警消息可以包含如下用户属性: { "priority": "high", "alertType": "gasLeak" } 在客户端中使用用户属性 使用JavaScript和MQTT.js库为例,下面演示如何在连接客户端时和发布消息时设置用户属性。 连接客户端时的用户属性 连接到MQTT服务器时,可以在connect方法的options中添加用户属性,这些属性将随着连接请求一起发送给MQTT服务器。 // connect options const OPTIONS = { clientId: 'mqtt_test', clean: true, connectTimeout: 4000, username: 'emqx', password: 'public', reconnectPeriod: 1000, protocolVersion: 5, properties: { userProperties: { region: 'A', type: 'JSON', }, }, } const client = mqtt.connect('mqtt://broker.emqx.io', OPTIONS) 发布消息时的用户属性 当发布MQTT消息时,也可以添加用户属性,这些属性将随消息一同传递给订阅了相应主题的客户端。 client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false, properties: { userProperties: { region: 'A', type: 'JSON', }, }, }, (error) => { if (error) { console.error(error) } }) client.on('message', (topic, payload, packet) => { console.log('packet:', packet) console.log('Received Message:', topic, payload.toString()) }) 结论 MQTT 5.0的用户属性特性为MQTT协议带来了前所未有的灵活性和扩展性,使得开发者能够更便捷地在MQTT消息中携带丰富的上下文信息。无论是进行文件传输、资源解析还是实现复杂的消息路由,用户属性都提供了一个简洁而强大的解决方案。随着越来越多的应用开始利用这一新特性,我们有理由相信MQTT协议在物联网领域的应用将变得更加广泛和深入。 --- ### 229. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在现代物联网(IoT)生态系统中,MQTT(Message Queuing Telemetry Transport)协议由于其轻量级和高效性,已成为连接数十亿智能设备的首选协议。尽管MQTT的发布订阅模型为异步消息传递提供了极大的灵活性,但在一些场景下,如设备配置更新或遥控命令执行等,通信双方可能需要一个更确定性的“请求/响应”机制来确保操作的成功执行。幸运的是,MQTT 5.0 引入了若干新特性,为实现这种机制提供了强大支持。本文将深入探讨如何借助这些新特性,在MQTT的异步框架下实现有效的“请求/响应”模式。 MQTT 5.0 前的挑战 在MQTT 5.0之前,实现“请求/响应”通常依赖于客户端和服务端之间的预先约定:请求方向一个特定主题发布请求消息,而响应方监听该主题,并向另一个预定的响应主题发布其响应。这种方法的主要限制是响应主题的固定性,当多个请求方涉及时,每个方都会接收到对同一请求的响应,导致消息处理上的混乱。 利用 MQTT 5.0 实现高效的“请求/响应”机制 响应主题(Response Topic) MQTT 5.0 允许请求方在发送请求消息时指定一个期望收到响应的主题,从而实现动态响应路由。这意味着响应方可以直接将响应消息发送到请求中指定的主题,极大提升了系统的灵活性和响应的准确性。 关联数据(Correlation Data) 关联数据特性使请求方能够在请求消息中包含一个唯一的标识符,响应方需要在其响应消息中包含相同的标识符。这使请求方能够将响应正确地匹配到相应的请求,特别是在处理多个并发请求时,这一机制显得尤为重要。 响应信息(Response Information) 通过使用响应信息属性,服务端可以提供额外的响应主题信息,帮助客户端构建合规的响应主题,确保通信的安全性和有效性。 智能家居场景示例 考虑一个智能家居场景,用户通过智能手机控制家中的多个智能设备,如灯光、空调等。在这个场景中,用户的请求(如“关闭客厅的灯”)需要得到设备的响应(如“已关闭”),以确认操作已成功执行。 请求消息:用户的智能手机发布一个请求消息到 MQTT 服务器,请求关闭客厅的灯。在这个请求消息中,用户指定了一个响应主题,如 smartHome/user123/lights/livingRoom/response,并且包含了一个关联数据,比如一个随机生成的ID abcd1234。 设备响应:智能灯光设备订阅了相应的请求主题,并收到了关闭灯光的请求。执行关闭操作后,设备发布一个响应消息到 smartHome/user123/lights/livingRoom/response,消息中包含了相同的关联数据 abcd1234。 用户确认:用户的智能手机订阅了响应主题 smartHome/user123/lights/livingRoom/response,并收到了设备的响应消息。通过匹配关联数据 abcd1234,用户的智能手机确认这是对关闭灯光请求的响应,并向用户显示一个确认信息。 这个过程中,响应主题的使用使得每个请求都有一个明确的响应路径,而关联数据则确保了响应可以被正确地关联到其请求。此外,通过利用 MQTT 5.0 的属性,智能设备的响应可以更加灵活地处理,并且可以保证仅由正确的请求方接收。 结论 通过MQTT 5.0的新特性,特别是响应主题、关联数据和响应信息,我们不仅能够在异步的消息传递框架下实现高效的“请求/响应”机制,还能提供更加动态和安全的通信模式。这些机制为物联网应用,如智能家居控制系统,提供了极大的灵活性和可靠性,确保了用户命令的准确执行和状态反馈,极大地增强了用户体验。随着越来越多的设备和应用采用MQTT 5.0,我们期待看到更多创新和改进,在保持通信高效的同时,提高物联网系统的整体安全性和可靠性。 --- ### 230. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在物联网的世界里,安全性是一个永远绕不开的话题。随着物联网设备的普及和应用的复杂化,传统的身份认证方法已经无法满足日益增长的安全需求。MQTT 作为物联网领域广泛使用的轻量级消息协议,其安全机制的升级显得尤为重要。在此背景下,MQTT 5.0 引入的增强认证机制为物联网安全通信提供了新的解决方案。 增强认证机制简介 增强认证是 MQTT 5.0 的一个重要特性,它通过引入更加安全的身份验证方法来提升通信安全性。不同于传统的用户名和密码验证,增强认证允许使用诸如SCRAM(Salted Challenge Response Authentication Mechanism)等多轮次的认证流程,大幅增强了认证过程的安全性。此外,增强认证还支持双向身份验证,即客户端和服务器可以互相验证对方的身份,进一步提高安全水平。 增强认证解决的问题 传统的密码认证虽然简单,但存在明显的安全弱点,最大的问题是密码在网络中的明文传输可能被窃听。即便使用加密通信,低版本的 SSL/TLS 仍可能因安全漏洞被攻击者利用,导致密码泄露。此外,密码认证无法实现服务端的身份验证,使得中间人攻击成为可能。 增强认证通过引入质询-响应机制,避免了密码的直接传输,即使通信被窃听,攻击者也无法直接获得密码信息。同时,通过客户端和服务端的互相验证,有效防止了中间人攻击。 常见的增强认证机制 DIGEST-MD5 DIGEST-MD5 是一种基于MD5散列算法的身份验证机制。它通过一次性的随机数(质询)和必要参数,要求客户端和服务器分别生成响应进行比较,以此验证身份。这种机制虽然比明文密码传输安全,但由于MD5算法本身的安全性已不再被认为是安全的,因此在安全性要求高的场景中,建议使用更安全的算法。 SCRAM SCRAM 是一种更为安全的身份验证机制,它通过使用盐值(Salt)和迭代次数(Iterations),结合SHA-256或SHA-512等安全哈希算法,大大增强了密码的安全性。SCRAM 不仅防止了密码的明文传输,还通过服务端对客户端的证明过程,实现了双向身份验证。 Kerberos Kerberos 是一种基于票据的认证机制,它通过引入可信的第三方(Kerberos服务器)进行身份验证。Kerberos 的优点在于能够实现单点登录(SSO),提高了使用便捷性的同时,也保证了较高的安全性。然而,Kerberos 的实现相对复杂,且对网络环境的要求较高。 下面是增强认证在 MQTT 5.0 中的运作方式的概览: 认证流程的开始 客户端发送 CONNECT 报文:在连接到服务器时,客户端发送一个 CONNECT 报文,该报文中包含了认证方法(Authentication Method)和可能的认证数据(Authentication Data)。这里的认证方法可以是“SCRAM-SHA-256”或其他支持的方法。 服务端回应 CONNACK 报文:服务端收到 CONNECT 报文后,根据提供的认证方法决定是否需要更多的认证数据。如果需要更多数据,服务端会响应一个 CONNACK 报文,其中包含一个指示继续认证过程的代码(如 0x18,表示继续认证),或者如果一步就能验证完成,则直接返回认证成功或失败的响应。 多轮认证过程 使用 AUTH 报文进行多轮认证:如果认证过程需要多轮交换数据(如 SCRAM),则会使用 AUTH 报文来进行。这一步中,服务端和客户端会根据具体的认证方法多次交换 AUTH 报文。 服务端发送 AUTH 报文:服务端发送 AUTH 报文,包含质询信息(如 SCRAM 中的盐值、迭代次数等)。 客户端回应 AUTH 报文:客户端根据收到的质询计算相应的响应,并通过 AUTH 报文发送回服务端。 这一过程可能会重复进行多轮,直到认证过程完成。 认证的完成 认证成功或失败:一旦认证过程完成,服务端会发送一个 CONNACK 报文,指示认证成功(通过 Reason Code 0x00 表示连接被接受)或失败(通过其他 Reason Code 指示失败原因)。如果认证失败,客户端应该断开连接。 SCRAM 需要传递四次消息才能完成认证。 client-first-message server-first-message client-final-message server-final-message 结语 MQTT 5.0 引入的增强认证为物联网通信安全提供了强有力的保障。通过选择适合的增强认证机制,开发者可以根据自己的安全需求和场景,灵活部署高安全性的物联网应用。随着物联网技术的不断进步,增强认证无疑将成为保护物联网通信安全的重要工具之一。 --- ### 231. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在实时通讯协议 MQTT 的最新版本 5.0 中,引入了一个称为“消息过期间隔”(Message Expiry Interval)的新特性。这一功能允许消息发布者为每条消息设置一个有效期限。如果消息在服务器上停留的时间超过了这个期限,它就不会被分发给任何订阅者。这意味着,当消息的内容不再相关或有用时,它会被自动清理,从而优化了网络资源的使用和提高了通信的效率。 什么是消息过期间隔? 消息过期间隔定义了一个消息从被发布起,到它变得不再可分发为止的时间长度。在 MQTT 协议中,这是通过在消息中设置一个特定的“过期间隔”值来实现的。默认情况下,消息不设置过期间隔,即视为永不过期。但在某些场景下,设定一个合理的过期时间可以显著提高数据传输的效率和实时性。 应用场景 时间敏感的信息 例如,一个促销活动仅在接下来的两小时内有效。如果消费者在活动结束后才收到这个消息,那么这个消息就失去了它的价值。 状态更新 考虑到实时交通信息的更新,如道路拥堵情况。随着时间的推移和交通流量的变化,过时的拥堵信息就不再有参考价值。 自动管理保留消息 在 MQTT 中,保留消息功能允许新的订阅者接收到他们订阅主题的最后一条消息。通过设置消息的过期间隔,可以避免过时的保留消息长时间占用服务器资源。 实例演示 假设有一个联网汽车应用场景,其中包括发送实时交通状况和路口信号灯配时建议。通过设置消息的过期间隔,可以确保车辆只接收到当前位置附近的、时效性强的信息。 设置消息过期间隔的操作步骤 要演示消息过期间隔的代码示例,我们可以使用 Python 和 paho-mqtt 库,这是一个常用于 MQTT 客户端开发的库。下面的示例将分为两部分:发布者(Publisher)和订阅者(Subscriber)。 安装 paho-mqtt 首先,确保你已经安装了 paho-mqtt。如果没有安装,可以通过 pip 安装: pip install paho-mqtt 发布者(Publisher) 发布者将发送两条消息,一条设置了5秒的过期间隔,另一条设置了60秒。 import time import paho.mqtt.client as mqtt # MQTT 服务器地址 MQTT_HOST = "test.mosquitto.org" MQTT_PORT = 1883 MQTT_TOPIC = "mqttx/demo/message_expiry" def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") client = mqtt.Client() client.on_connect = on_connect client.connect(MQTT_HOST, MQTT_PORT, 60) # 发送第一条消息,设置5秒过期间隔 client.publish(MQTT_TOPIC, payload="This message will expire in 5 seconds.", qos=1, properties={'message_expiry_interval': 5}) print("Published message with 5 seconds expiry.") # 发送第二条消息,设置60秒过期间隔 client.publish(MQTT_TOPIC, payload="This message will expire in 60 seconds.", qos=1, properties={'message_expiry_interval': 60}) print("Published message with 60 seconds expiry.") # 断开连接 client.disconnect() 订阅者(Subscriber) 订阅者订阅同一个主题,并处理接收到的消息。 import paho.mqtt.client as mqtt # MQTT 服务器地址 MQTT_HOST = "test.mosquitto.org" MQTT_PORT = 1883 MQTT_TOPIC = "mqttx/demo/message_expiry" def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") client.subscribe(MQTT_TOPIC) def on_message(client, userdata, msg): print(f"Received message: {msg.payload.decode()} on topic {msg.topic}") client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect(MQTT_HOST, MQTT_PORT, 60) client.loop_forever() 运行示例 运行订阅者代码:首先启动订阅者客户端,让它在后台运行并监听指定主题的消息。 运行发布者代码:然后运行发布者代码,发送两条带有不同过期间隔的消息。 你将看到订阅者只接收到在其过期间隔内的消息。如果你在发布后立刻运行订阅者,两条消息都可能被接收。但如果在5秒后再启动订阅者,只有设置了60秒过期间隔的消息会被接收,因为另一条消息已经过期。 这个演示说明了如何在MQTT 5.0中使用消息过期间隔功能,以及它如何影响消息的传递和接收。 通过这个例子,我们可以清楚地看到消息过期间隔如何在实际应用中起作用,以确保信息的实时性和相关性。 总结 消息过期间隔是 MQTT 5.0 提供的一个非常实用的特性,它帮助开发者和企业确保消息的时效性,同时减轻服务器的负担,并优化资源使用。无论是在实时交通信息、促销活动通知,还是在智能家居和工业物联网应用中,适当使用消息过期间隔都能带来显著的效益。 在设计和实现基于 MQTT 协议的通信系统时,合理利用消息过期间隔不仅可以提高信息传输的效率,还能增强用户体验,确保用户及时获取最重要和最相关的信息。同时,它还减少了网络带宽的浪费,优化了服务器存储资源的使用,使得系统更加高效和可靠。 --- ### 232. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在MQTT 5.0中,Reason Code的引入为客户端和服务端提供了更详细的反馈机制。这些代码不仅帮助诊断连接问题,还让开发者能够更精确地处理各种异常情况。与MQTT 3.1.1相比,MQTT 5.0扩展了Reason Code的范围和应用,使得错误处理更加灵活和详细。 MQTT 3.1.1与MQTT 5.0中的Reason Code对比 在MQTT 3.1.1版本中,Reason Code的使用相对有限,仅在CONNACK和SUBACK报文中提供了一些基本的错误代码。这些代码的范围和细节都较为有限,使得开发者在诊断和处理问题时可能会遇到一些挑战。 而MQTT 5.0则大幅扩展了Reason Code的数量和应用场景,引入了43个不同的代码,覆盖了连接、发布、订阅、取消订阅等多种操作的成功与失败情况。这些代码被分为两大类:小于0x80的表示操作成功,等于或大于0x80的表示操作失败。 MQTT 5.0 Reason Code速查表 为了便于理解和应用,以下是一些常见MQTT 5.0 Reason Codes的速查表,包括它们的含义和使用场景: Reason CodeNamePacketsDetails0x00SuccessCONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH这个 Reason Code 可以用在所有存在 Reason Code 的报文中,例如 CONNACK、DISCONNECT 报文等等。它通常用于表示成功,比如连接成功、取消订阅成功、消息接收成功和认证成功等等。0x00Normal disconnectionDISCONNECT在 DISCONNECT 报文中,0 则表示连接正常断开,这种情况下遗嘱消息不会被发布。0x00Granted QoS 0SUBACK0,1,2 在 SUBACK 这个订阅确认报文中,用来指示订阅结果,它们都表示订阅成功,同时向订阅端指示最终被授予的最大 QoS 等级,0,1,2 正好对应了三个 QoS 等级。 这是因为服务端最终授予的最大 QoS 等级,可能小于订阅时请求的最大 QoS 等级。比如订阅时请求的最大 QoS 等级是 2,但服务端最高仅支持 QoS 1 等等。0x01Granted QoS 1SUBACK-0x02Granted QoS 2SUBACK-0x04Disconnect with Will MessageDISCONNECT仅用于 DISCONNECT 报文,适用于客户端希望正常断开连接但服务端仍然需要发布遗嘱消息的情况,比如客户端希望会话过期时可以对外发出通知。0x10No matching subscribersPUBACK, PUBREC这个 Reason Code 用于向发送方指示,消息已经收到,但是当前没有匹配的订阅者,所以只有服务端可以使用这个 Reason Code。我们可以通过收到 Reason Code 为 0x10 的响应报文得知当前没有人会收到自己的消息,但是不能通过没有收到 Reason Code 为 0x10 的响应报文来假定所有人都会收到自己的消息,除非最多只会存在一个订阅者。但需要注意,没有匹配的订阅者时使用 0x10 替代 0x00,并不是一个必须实现的行为,这取决于服务端的具体实现。0x11No subscription existedUNSUBACK仅用于 UNSUBACK 报文,表示取消订阅时没有发现匹配的订阅。0x18Continue authenticationAUTH仅用于 AUTH 报文,表示继续认证,通过这个 Reason Code,客户端和服务端之间可以进行任意次数的 AUTH 报文交换,以满足不同的认证方法的需要。0x19Re-authenticateAUTH仅用于 AUTH 报文,在增强认证成功后客户端可以随时通过发送 Reason Code 为 0x19 的 AUTH 报文发起重新认证。重新认证期间,其他报文收发会正常继续,如果重新认证失败,连接就会被关闭。0x80Unspecified errorCONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT表示未指明的错误。当一方不希望向另一方透露错误的具体原因,或者协议规范中没有能够匹配当前情况的 Reason Code 时,那么它可以在报文中使用这个 Reason Code。0x81Malformed PacketCONNACK, DISCONNECT当收到了无法根据协议规范正确解析的控制报文时,接收方需要发送 Reason Code 为 0x81 的 DISCONNECT 报文来断开连接。如果是 CONNECT 报文存在问题,那么服务端应该使用 CONNACK 报文。当控制报文中出现固定报头中的保留位没有按照协议要求置 0、QoS 被指定为 3、UTF-8 字符串中包含了一个空字符等等这些情况时,都将被认为是一个畸形的报文。0x82Protocol ErrorCONNACK, DISCONNECT在控制报文被按照协议规范解析后检测到的错误,比如包含协议不允许的数据,行为与协议要求不符等等,都会被认为是协议错误。接收方需要发送 Reason Code 为 0x81 的 DISCONNECT 报文来断开连接。如果是 CONNECT 报文存在问题,那么服务端应该使用 CONNACK 报文。常见的协议错误包括,客户端在一个连接内发送了两个 CONNECT 报文、一个报文中包含了多个相同的属性,以及某个属性被设置成了一个协议不允许的值等等。但是当我们有其他更具体的 Reason Code 时,就不会使用 0x81 (Malformed Packet) 或者 0x82 (Protocol Error) 了。例如,服务端已经声明自己不支持保留消息,但客户端仍然向服务端发送保留消息,这本质上也属于协议错误,但我们会选择使用 0x9A (Retain not supported) 这个能够更清楚指明错误原因的 Reason Code。0x83Implementation specific errorCONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT报文有效,但是不被当前接收方的实现所接受。0x84Unsupported Protocol VersionCONNACK仅用于 CONNACK 报文。对于支持了 MQTT 5.0 的服务端来说,如果不支持客户端当前使用的 MQTT 协议版本,或者客户端指定了一个错误的协议版本或协议名。例如,客户端将协议版本设置为 6,那么服务端可以发送 Reason Code 为 0x84 的 CONNACK 报文,表示不支持该协议版本并且表明自己 MQTT 服务端的身份,然后关闭网络连接。当然服务端也可以选择直接关闭网络连接,因为使用 MQTT 3.1 或 3.1.1 的 MQTT 客户端可能并不能理解 0x84 这个 Reason Code 的含义。这两个版本都是在 CONNACK 报文使用 0x01 来表示不支持客户端指定的协议版本。0x85Client Identifier not validCONNACK仅用于 CONNACK 报文,表示 Client ID 是有效的字符串,但是服务端不允许。可能的情形有 Clean Start 为 0 但 Client ID 为空、或者 Client ID 超出了服务端允许的最大长度等等。0x86Bad User Name or PasswordCONNACK仅用于 CONNACK 报文,表示客户端使用了错误的用户名或密码,这也意味着客户端将被拒绝连接。0x87Not authorizedCONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT当客户端使用 Token 认证或者增强认证时,使用 0x87 来表示客户端没有被授权连接会比 0x86 更加合适。当客户端进行发布、订阅等操作时,如果没有通过服务端的授权检查,那么服务端也可以在 PUBACK 等应答报文中指定 0x87 这个 Reason Code 来指示授权结果。0x88Server unavailableCONNACK仅用于 CONNACK 报文,向客户端指示当前服务端不可用。比如当前服务端认证服务异常无法接入新客户端等等。0x89Server busyCONNACK, DISCONNECT向客户端指示服务端正忙,请稍后再试。0x8ABannedCONNACK仅用于 CONNACK 报文,表示客户端被禁止登录。例如服务端检测到客户端的异常连接行为,所以将这个客户端的 Client ID 或者 IP 地址加入到了黑名单列表中,又或者是后台管理人员手动封禁了这个客户端,当然以上这些通常需要视服务端的具体实现而定。0x8BServer shutting downDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。如果服务端正在或即将关闭,它可以通过主动发送 Reason Code 为 0x8B 的 DISCONNECT 报文的方式告知客户端连接因为服务端正在关闭而被终止。这可以帮助客户端避免在连接关闭后继续向此服务端发起连接请求。0x8CBad authentication methodCONNACK, DISCONNECT当服务端不支持客户端指定的增强认证方法,或者客户端在重新认证时使用了和之前认证不同的认证方法时,那么服务端就会发送 Reason Code 为 0x8C 的 CONNACK 或者 DISCONNECT 报文。0x8DKeep Alive timeoutDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。如果客户端没能在 1.5 倍的 Keep Alive 时间内保持通信,服务端将会发送 Reason Code 为 0x8D 的 DISCONNECT 报文然后关闭网络连接。0x8ESession taken overDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。当客户端连接到服务端时,如果服务端中已经存在使用相同 Client ID 的客户端连接,那么服务端就会向原有的客户端发送 Reason Code 为 0x8E 的 DISCONNECT 报文,表示会话被新的客户端连接接管,然后关闭原有的网络连接。不管新的客户端连接中的 Clean Start 是 0 还是 1,服务端都会使用这个 Reason Code 向原有客户端指示会话被接管。0x8FTopic Filter invalidSUBACK, UNSUBACK, DISCONNECT主题过滤器的格式正确,但是不被服务端接受。比如主题过滤器的层级超过了服务端允许的最大数量限制,或者主题过滤器中包含了空格等不被当前服务端接受的字符。0x90Topic Name invalidCONNACK, PUBACK, PUBREC, DISCONNECT主题名的格式正确,但是不被客户端或服务端接受。0x91Packet Identifier in usePUBACK, PUBREC, SUBACK, UNSUBACK表示收到报文中的 Packet ID 正在被使用,例如发送方发送了一个 Packet ID 为 100 的 QoS 1 消息,但是接收方认为当前有一个使用相同 Packet ID 的 QoS 2 消息还没有按成它的报文流程。这通常意味着当前客户端和服务端之前的会话状态不匹配,可能需要通过设置 Clean Start 为 1 重新连接来重置会话状态。0x92Packet Identifier not foundPUBREL, PUBCOMP表示未找到对应的 Packet ID,这只会在 QoS 2 的报文交互流程中发生。比如当接收方回复 PUBREC 报文时,发送方未找到使用相同 Packet ID 的等待确认的 PUBLISH 报文,或者当发送方发送 PUBREL 报文时,接收方未找到使用相同 Packet ID 的 PUBREC 报文。这通常意味着当前客户端和服务端之间的会话状态不匹配,可能需要通过设置 Clean Start 为 1 重新连接来重置会话状态。0x93Receive Maximum exceededDISCONNECT仅用于 DISCONNECT 报文,表示超出了接收最大值。MQTT 5.0 增加了流控机制,客户端和服务端在连接时通过 Receive Maximum 属性约定它们愿意并发处理的可靠消息数(QoS > 0)。所以一旦发送方发送的没有完成确认的消息超过了这一数量限制,接收方就会发送 Reason Code 为 0x93 的 DISCONNECT 报文然后关闭网络连接。0x94Topic Alias invalidDISCONNECT仅用于 DISCONNECT 报文,表示主题别名不合法。如果 PUBLISH 报文中的主题别名值为 0 或者大于连接时约定的最大主题别名,接收方会将此视为协议错误,它将发送 Reason Code 为 0x94 的 DISCONNECT 报文然后关闭网络连接。0x95Packet too largeCONNACK, DISCONNECT用于表示报文超过了最大允许长度。客户端和服务端各自允许的最大报文长度,可以在 CONNECT 和 CONNACK 报文中通过 Maximum Packet Size 属性约定。当一方发送了过大的报文,那么另一方将发送 Reason Code 为 0x95 的 DISCONNECT 报文,然后关闭网络连接。由于客户端可以在连接时设置遗嘱消息,因此 CONNECT 报文也有可能超过服务端能够处理的最大报文长度限制,此时服务端需要在 CONNACK 报文中使用这个 Reason Code。0x96Message rate too highDISCONNECT仅用于 DISCONNECT 报文,表示超过了允许的最大消息发布速率。需要注意它与 Quota exceeded 的区别,Message rate 限制消息的发布速率,比如每秒最高可发布多少消息,Quota 限制的是资源的配额,比如客户端每天可以发布的消息数量,但客户端可能在一小时内耗尽它的配额。0x97Quota exceededCONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT用于表示超出了配额限制。服务端可能会对发布端的发送配额进行限制,比如每天最多为其转发 1000 条消息。当发布端的配额耗尽,服务端就会在 PUBACK 等确认报文中使用这个 Reason Code 提醒对方。另一方面,服务端还可能限制客户端的连接数量和订阅数量,当超出这一限制时,服务端就会通过 CONNACK 或者 SUBACK 报文向客户端指示当前超出了配额。一些严格的客户端和服务端,在发现对端超出配额时,可能会选择发送 DISCONNECT 报文然后关闭连接。0x98Administrative actionDISCONNECT仅用于 DISCONNECT 报文,向客户端指示连接因为管理操作而被关闭,例如运维人员在后台踢除了这个客户端连接等等。0x99Payload format invalidCONNACK, PUBACK, PUBREC, DISCONNECT当消息中包含 Payload Format Indicator 属性时,接收方可以检查消息中 Payload 的格式与该属性是否匹配。如果不匹配,接收方需要发送 Reason Code 为 0x99 的确认报文。一些严格的客户端或者服务器,可能会直接发送 DISCONNECT 报文然后关闭网络连接。如果是 CONNECT 报文中的遗嘱消息存在问题,服务端将发送 Reason Code 为 0x99 的 CONNACK 报文然后关闭网络连接。0x9ARetain not supportedCONNACK, DISCONNECT当服务端不支持保留消息,但是客户端发送了保留消息时,服务端就会向它发送 Reason Code 为 0x9A 的 DISCONNECT 报文然后关闭网络连接。由于客户端还可以在连接时将遗嘱消息设置为保留消息,所以服务端也可能在 CONNACK 报文中使用这个 Reason Code。0x9BQoS not supportedCONNACK, DISCONNECT用于表示不支持当前的 QoS 等级。如果客户端在消息(包括遗嘱消息)中指定的 QoS 大于服务端支持的最大 QoS,服务端将会发送 Reason Code 为 0x9B 的 DISCONNECT 或者 CONNACK 报文然后关闭网络连接。在大部份情况下,这个 Reason Code 都是由服务端使用。但是在客户端收到不是来自订阅的消息,并且消息的 QoS 大于它支持的最大 QoS 时,它也会发送 Reason Code 为 0x9B 的 DISCONNECT 报文然后关闭网络连接。这种情况通常意味着服务端的实现可能存在问题。0x9CUse another serverCONNACK, DISCONNECT服务端在 CONNACK 或者 DISCONNECT 报文中通过这个 Reason Code 告知客户端应该临时切换到另一个服务端。如果另一个服务端不是客户端已知的,那么这个 Reason Code 还需要配合 Server Reference 属性一起使用,以告知客户端新的服务端的地址。0x9DServer movedCONNACK, DISCONNECT服务端在 CONNACK 或者 DISCONNECT 报文中通过这个 Reason Code 告知客户端应该永久切换到另一个服务端。如果另一个服务端不是客户端已知的,那么这个 Reason Code 还需要配合 Server Reference 属性一起使用,以告知客户端新的服务端的地址。0x9EShared Subscriptions not supportedSUBACK, DISCONNECT当服务端不支持共享订阅,但是客户端尝试建立共享订阅时,服务端可以发送 Reason Code 为 0x9E 的 SUBACK 报文拒绝这次订阅请求,也可以直接发送 Reason Code 为 0x9E 的 DISCONNECT 报文然后关闭网络连接。0x9FConnection rate exceededCONNACK, DISCONNECT用于表示客户端已超过连接速率限制。服务端可以对客户端的连接速率做出限制,客户端连接过快时,服务端可以发送 Reason Code 为 0x9F 的 CONNACK 报文来拒绝新的连接。当然这并不是绝对的情况,考虑到不是所有的客户端都会等待一段时间再重新发起连接,一些服务端实现可能会选择暂时挂起连接而不是返回 CONNACK。0xA0Maximum connect timeDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。出于安全性的考虑,服务端可以限制单次授权中客户端的最大连接时间,比如在使用 JWT 认证时,客户端连接不应在 JWT 过期后继续保持。这种情况下,服务端可以发送 Reason Code 为 0xA0 的 DISCONNECT 报文,向客户端指示连接因为超过授权的最大连接时间而被关闭。客户端可以在收到包含这个 Reason Code 的 DISCONNECT 报文后,重新获取认证凭据然后再次请求连接。0xA1Subscription Identifiers not supportedSUBACK, DISCONNECT当服务端不支持订阅标识符,但是客户端的订阅请求中包含了订阅标识符时,服务端可以发送 Reason Code 为 0xA1 的 SUBACK 报文拒绝这次订阅请求,也可以直接发送 Reason Code 为 0xA1 的 DISCONNECT 报文然后关闭网络连接。0xA2Wildcard Subscriptions not supportedSUBACK, DISCONNECT当服务端不支持通配符订阅,但是客户端的订阅请求中包含了主题通配符时,服务端可以发送 Reason Code 为 0xA2 的 SUBACK 报文拒绝这次订阅请求,也可以直接发送 Reason Code 为 0xA2 的 DISCONNECT 报文然后关闭网络连接。 使用Reason Code的注意事项 精确处理错误:利用MQTT 5.0的Reason Code,开发者可以更精确地诊断和处理连接或操作失败的原因。 优化用户体验:通过根据不同的错误代码提供更具体的错误信息或采取相应的恢复措施,可以优化最终用户的体验。 日志记录:在开发和调试过程中,记录包含Reason Code的操作可以帮助快速定位问题。 MQTT 5.0的Reason Code为MQTT协议的使用提供了更强大的错误处理能力,使得开发者能够构建更健壮、更可靠的MQTT应用。 --- ### 233. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT遗嘱消息(Last Will and Testament,简称LWT)是MQTT协议中的一个特性,允许客户端在建立连接时向服务器注册一个遗嘱消息。这个消息将在客户端异常断开连接时由服务器自动发布,通知其他客户端该客户端已离线。这个功能对于监控设备状态、实现设备断线通知等场景非常有用。 MQTT遗嘱消息的工作原理 客户端连接时指定遗嘱消息: 客户端在与MQTT服务器(Broker)建立连接时,可以指定一个遗嘱消息。这包括遗嘱消息的主题(Will Topic)、消息内容(Will Message)、消息质量(QoS)和是否保留(Retain)等信息。 服务器存储遗嘱消息: MQTT服务器接收到遗嘱消息后,会将其存储,但不立即发布。只有在满足特定条件时,服务器才会发布这个遗嘱消息。 客户端异常断开连接: 如果客户端因网络故障、设备故障或其他原因异常断开连接(不包括正常发送DISCONNECT报文的情况),MQTT服务器将判断客户端“死亡”,并自动发布之前存储的遗嘱消息。 其他客户端接收遗嘱消息: 其他订阅了遗嘱消息主题的客户端将接收到这个遗嘱消息,从而得知特定客户端已经断开连接。 使用遗嘱消息的场景 设备状态监控: 在物联网应用中,可以利用遗嘱消息监控设备的在线状态。如果设备异常断开,遗嘱消息可以通知监控系统或其他设备,采取相应措施。 用户在线状态通知: 在即时通讯应用中,遗嘱消息可以用来通知其他用户某个用户已经离线。 示例代码 以下是使用paho-mqtt客户端库(Python)设置遗嘱消息的示例: 首先,确保安装了paho-mqtt: pip install paho-mqtt 然后,创建一个MQTT客户端,设置遗嘱消息,并连接到MQTT服务器: import paho.mqtt.client as mqtt # MQTT服务器地址 broker_address = "broker.hivemq.com" # 遗嘱消息的主题和内容 will_topic = "device/status" will_message = "Device offline" # 创建MQTT客户端实例 client = mqtt.Client("ClientID") # 设置遗嘱消息 client.will_set(will_topic, payload=will_message, qos=1, retain=True) # 连接到MQTT代理 client.connect(broker_address, 1883, 60) # 进入阻塞状态,处理消息接收和发送等操作 client.loop_forever() 在这个示例中,如果客户端异常断开连接,MQTT服务器将自动发布遗嘱消息到device/status主题,消息内容为Device offline。其他订阅了这个主题的客户端将接收到这个消息,知道该设备已离线。 小结 MQTT遗嘱消息是一个强大的功能,它为客户端提供了一种机制,在无法正常断开连接时通知其他客户端或系统。这在需要高可靠性的物联网应用中尤其有用,可以帮助系统及时响应设备故障或网络问题。 --- ### 234. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT(Message Queuing Telemetry Transport)是一个轻量级的消息协议,广泛用于物联网(IoT)中设备间的通信。它支持多种消息传递模式,包括发布/订阅模式,使得数据交换变得简单高效。在MQTT协议中,保留消息(Retained Messages)是一个特殊的功能,它允许消息被保留在MQTT代理(Broker)上,直到有新的客户端订阅匹配的主题(Topic)时才被发送。 什么是MQTT保留消息? 当一个MQTT客户端向代理发布一个消息时,它可以选择将这个消息标记为“保留”。这意味着即使在消息发布之后,这个消息也会在MQTT代理上保留。当有新的客户端订阅了这个消息的主题时,这个保留的消息会立即被发送给这个新的订阅者,即使这个消息是在很久以前发布的。这样做的好处是,新的订阅者可以立即获得最新的状态更新,而不需要等待下一个状态变化的消息。 如何使用MQTT保留消息? 发布保留消息: 当客户端发布一个消息到MQTT代理时,它可以设置MQTT消息的retain标志为true。这可以通过客户端库的API完成,具体方法取决于所使用的库。例如,在Mosquitto的C库中,可以使用mosquitto_publish函数,并将retain参数设置为true。 订阅并接收保留消息: 当客户端订阅一个主题时,如果该主题有保留消息,MQTT代理会立即发送这个保留消息给客户端。客户端不需要进行任何特殊操作来接收保留消息,这是MQTT协议的标准行为。 使用保留消息的注意事项: 及时更新保留消息: 如果主题的状态发生变化,应该发布一个新的保留消息来更新状态。否则,新订阅者可能会收到过时的信息。 清除保留消息: 如果不再需要保留消息,可以通过发布一个空的消息体(payload为空)并将retain标志设置为true到相同的主题来清除保留消息。 谨慎使用: 保留消息非常有用,但如果不当使用,可能会导致意外的行为。例如,如果客户端不期望接收旧的状态信息,但主题中存在保留消息,它们将会收到这些信息。 发布保留消息 假设我们使用paho-mqtt客户端库(Python)来发布一个保留消息。首先,确保安装了paho-mqtt: pip install paho-mqtt 然后,发布一个保留消息的代码示例如下: import paho.mqtt.client as mqtt # MQTT服务器地址 broker_address = "broker.hivemq.com" # 主题 topic = "home/livingroom/temperature" # 创建MQTT客户端实例 client = mqtt.Client("Publisher") # 连接到MQTT代理 client.connect(broker_address) # 发布保留消息 # 参数:主题、消息内容、QoS、retain标志 client.publish(topic, payload="23", qos=1, retain=True) print(f"Published retained message to {topic}") # 断开连接 client.disconnect() 订阅并接收保留消息 下面是一个订阅者的示例,它订阅上面发布者使用的相同主题,并接收保留消息: import paho.mqtt.client as mqtt # MQTT服务器地址 broker_address = "broker.hivemq.com" # 主题 topic = "home/livingroom/temperature" # 当连接到MQTT代理时的回调函数 def on_connect(client, userdata, flags, rc): print("Connected with result code "+str(rc)) client.subscribe(topic) # 当接收到消息时的回调函数 def on_message(client, userdata, msg): print(f"Received message: {msg.payload.decode()} on topic {msg.topic} with QoS {msg.qos}") # 创建MQTT客户端实例 client = mqtt.Client("Subscriber") # 指定回调函数 client.on_connect = on_connect client.on_message = on_message # 连接到MQTT代理 client.connect(broker_address) # 阻塞循环,以处理接收消息和重新连接等操作 client.loop_forever() 注意事项 更新保留消息:如果主题的状态更新,应该发布一个新的保留消息以反映最新状态。 清除保留消息:通过向相同的主题发布一个空消息(payload为空字符串)并设置retain=True,可以清除保留消息。 谨慎使用:虽然保留消息功能非常有用,但在不需要旧状态信息的场景中应谨慎使用,以避免混淆和不必要的数据传输。 通过上述示例,你应该对如何在MQTT中使用保留消息有了清晰的理解。这个功能在确保新订阅者能够立即获得最新状态信息方面非常有用。 --- ═══════════════════════════════════════════ ## MQTT-SN v1.2规范 ═══════════════════════════════════════════ ### 235. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着智能工厂的到来,工业物联网(IIoT)正在以惊人的速度扩展。预计到2030年,IIoT市场规模将达到3.3万亿美元,意味着将有数十亿个设备相互连接。为了确保这些设备,尤其是那些资源受限且有时依赖电池供电的设备能够高效运行,找到一种高效且可扩展的物联网解决方案至关重要。 MQTT-SN(针对传感器网络的MQTT)是一种专为非TCP/IP网络上的嵌入式设备设计的轻量级发布和订阅消息协议。它优化了MQTT版本3.1.1和MQTT 5.0的规范,特别适合低功耗、受限设备。在这篇文章中,我们将探讨MQTT-SN的节能和扩展能力,以及它如何支持工业自动化和数据采集的不断增长需求。 MQTT-SN:IIoT的低功耗解决方案 减少物联网设备的电力消耗不仅可以降低能源成本,还有许多其他好处。想象一下,一个遍布大型多地点生产设施的传感器网络。每个传感器或连接设备都需要电力,如果依赖频繁更换电池,不仅麻烦,而且限制了这些部署的可扩展性和灵活性。在这种情况下,降低电力消耗尤为重要。 通过最小化单个设备的能耗,可以降低电费,减少对频繁更换电池的依赖。这不仅减少了维护需求,提高了运营的正常运行时间,还显著节省了成本。具有延长电池寿命或能够从环境中获取能量(例如通过太阳能或风能)的节能设备,可以实现更广泛的传感器分布,提供更全面的工业过程视图。这种增加的监控可扩展性,使数据驱动的决策更加有效,并有助于优化运营。 此外,减少对一次性电池的依赖,可以促进更绿色的IIoT生态系统。结合MQTT-SN这样的低功耗协议和能量收集技术,我们可以迈向IIoT的可持续未来。 为什么选择MQTT-SN? 首先,MQTT-SN为效率而生。与MQTT相比,MQTT-SN具有更紧凑的设计。消息头被最小化,主题名称可以被短主题ID替换。数据大小的减少转化为更少的带宽消耗和对资源有限设备的更低处理需求。 为了进一步降低功耗,MQTT-SN引入了睡眠机制。设备可以有效地关闭,并在重新开启时接收排队的消息。这显著降低了功耗,延长了电池供电传感器的电池寿命。 与MQTT一样,MQTT-SN利用发布/订阅模型。设备将数据发布到特定主题,感兴趣的订阅者只接收相关信息。这种有针对性的方法最小化了不必要的数据传输,优化了网络带宽的使用。多个设备可以通过MQTT-SN网关与MQTT代理通信。 通过解决功耗效率和可扩展性的关键方面,MQTT-SN为IIoT环境中的强大和可靠通信铺平了道路。随着工业领域接受自动化和数据驱动的决策,MQTT-SN成为推动创新和确保未来智能工厂无缝运行的强大工具。 为了实现更多的节能和更低的数据开销,MQTT-SN增加了一种新的QoS模式,允许盲目发送并忘记消息传递。这意味着设备可以简单地唤醒并发送消息,而不必等待响应。 与MQTT不同,MQTT-SN不依赖于TCP/IP传输。相反,它旨在与底层网络服务无关。因此,任何支持节点和网关之间双向传输服务的网络都可以支持MQTT-SN。 MQTT-SN的限制 在选择MQTT-SN作为您的通信协议时,需要意识到一些限制。最大的一个问题是安全性。虽然可以使用任何加密技术,但目前MQTT-SN协议本身并没有内置安全性。不过,这个问题将在最新的标准修订中得到解决。 在复杂性方面,学习、实施和管理MQTT-SN可能比一些更简单的协议要困难。然而,使用专为MQTT-SN设计的兼容工具和库可以简化这个过程。虽然网关使设备和代理之间的通信成为可能,但确保不同MQTT-SN实现与现有基础设施的兼容性至关重要。选择符合最新MQTT-SN规范并提供明确迁移路径的解决方案可以帮助缓解兼容性问题。 MQTT-SN在IIoT中的用例 MQTT-SN在功耗效率、可扩展性和轻量级设计方面的优势使其成为各种IIoT应用的理想选择。以下是一些典型的用例: 无线传感器网络:在工业环境中,众多传感器监测温度、压力、振动等关键参数。MQTT-SN的低数据占用和睡眠功能非常适合这些电池供电的传感器,使它们能够在节省电池寿命的同时高效地传输数据。 智能建筑管理:建筑物越来越多地与传感器集成,用于监测能源消耗、占用和环境条件。MQTT-SN促进了这些传感器与中央控制系统之间的高效通信,实现了实时数据收集和优化的建筑运营。 预测性维护:通过持续监测设备健康数据(如振动、温度),MQTT-SN允许及早发现潜在问题,使预防性维护成为可能,减少了停机时间和相关成本。 工业资产跟踪:在大型设施内跟踪关键资产(如工具、机械或库存)的位置和状态至关重要。MQTT-SN处理来自低功耗RFID标签或GNSS跟踪器的数据,使其适用于此类应用。 远程监控和控制:在石油和天然气管道或偏远地区的环境监测站等应用中,MQTT-SN使与电池供电传感器的高效通信成为可能,允许实时数据获取和远程控制能力。 总结 MQTT-SN为IIoT应用提供了一个引人注目的解决方案。它的轻量级设计、高效的通信模型和对节能的强调,使其非常适合工业环境中普遍存在的资源受限设备。随着IIoT格局的不断发展,MQTT-SN有望在促进数据的可扩展交换中发挥关键作用,最终赋能下一代工业自动化。 --- ### 236. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 2024032209060883下载 --- ### 237. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 近期对无线传感网络(WSNs)的兴趣不断增长,无论是从商业还是技术的角度来看,都因其简易性、低成本和易于部署而受到关注。这些网络可以用于不同的目的,从测量和检测到自动化和过程控制。一个典型的WSN由大量电池操作的传感器和执行器(SAs)组成,这些设备通常配备有有限的存储和处理能力。重要的是这些设备能够通过无线方式通信,因为SA节点的数量通常非常大,且部署有线基础设施的成本极其昂贵。这样的网络本质上非常动态:无线链接可能随时临时断开,节点可能会经常失败并被频繁替换。在这种情况下,使用地址来与个别节点通信的传统方法可能变成一场噩梦。居住在固定网络上并需要与无线SA设备交互的应用程序需要管理和维护与大量节点通信的手段。在大多数情况下,它们不需要知道提供信息的设备的地址或身份,而是更感兴趣于数据的内容。例如,资产跟踪应用程序更感兴趣于某个特定资产的当前位置,而不是提供该信息的GPS接收器的网络地址。此外,几个应用程序可能对相同的传感器数据感兴趣,但出于不同的目的。在这种情况下,SA节点需要同时与多个应用程序并行管理和维护通信手段。这可能超出了简单和低成本SA设备的有限能力。另一个问题是涉及的网络之间的寻址方案差异。例如,一个驻留在基于TCP/IP的网络上的应用程序如何寻址一个运行在基于ZigBee R1的无线网络上的SA设备? 通过使用以数据为中心的通信方法可以克服上述问题,在这种方法中,信息的传递不是基于它们的网络地址,而是作为其内容和兴趣的函数。一个众所周知的以数据为中心的通信示例是“发布/订阅”(pub/sub)消息系统,该系统已在企业网络中被广泛使用,主要是因为其可扩展性和支持动态网络拓扑。将企业pub/sub系统扩展到WSNs还可以实现WSNs到企业网络的无缝集成,从而使SAs收集的现场数据可用于所有应用程序,就像任何其他企业信息一样,并使SAs能够受到任何企业应用程序的控制。 ZigBee是ZigBee联盟在美国、其他国家或两者中的商标。其他公司、产品或服务名称可能是其他人的商标或服务标记。 MQTT-SN规范简介 本文档的目的是规定MQTT-SN,一种适用于无线传感网络的发布/订阅协议。MQTT-SN可以被视为适应无线通信环境特点的MQTT版本。无线电链路通常比有线链路具有更高的故障率,因为它们容易受到衰减和干扰的影响。它们的传输速率也较低。例如,基于IEEE 802.15.4标准的WSN在2.4 GHz带提供的最大带宽为250 kbit/s。此外,为了抵抗传输错误,它们的数据包长度非常短。在IEEE 802.15.4的情况下,物理层的包长限制为128字节。这128字节中的一半可能会被MAC层、网络、安全等支持功能所需的开销信息占据。MQTT-SN还针对在低成本电池操作设备上的实现进行了优化,这些设备具有有限的处理和存储资源。 MQTT-SN最初是为在ZigBee R1 APS层之上运行而开发的。ZigBee R1是一个开放的工业联盟,旨在为WSN定义一个开放和全球的通信标准。为了实现全球化,ZigBee R1选择了IEEE 802.15.4标准作为PHY和MAC层的协议,并在此标准的基础上增加了所需的网络、安全和应用层,从而提供不同厂商产品之间的互操作性。 MQTT-SN的设计使其不依赖于底层网络服务。任何提供节点与特定节点(即网关)之间双向数据传输服务的网络都应能够支持MQTT-SN。例如,一个简单的数据报服务,允许源端点向特定的目的端点发送数据消息应该就足够了。如果使用网关发现程序,则只需要广播数据传输服务。为了减少发现程序产生的广播流量,最好是MQTT-SN能够向底层层指示所需的广播半径。 3.MQTT-SN 与 MQTT MQTT-SN旨在尽可能接近MQTT,但针对无线通信环境的特殊性进行了适应,如低带宽、高链路故障、短消息长度等。它也针对低成本、电池操作的设备上的实现进行了优化,这些设备具有有限的处理和存储资源。 与MQTT相比,MQTT-SN有以下不同之处: CONNECT消息被分解为三个消息。两个额外的消息是可选的,用于将遗嘱主题和遗嘱消息传输给服务器。 为了应对无线网络中的短消息长度和有限的传输带宽,PUBLISH消息中的主题名称被一个短的、两字节长的“主题ID”替代。定义了一个注册程序,允许客户端向服务器/网关注册它们的主题名称,并获得相应的主题ID。它也用于相反方向,以通知客户端即将在后续的PUBLISH消息中包括的主题名称和相应的主题ID。 引入了“预定义”的主题ID和“短”的主题名称,它们不需要注册。预定义的主题ID也是替代主题名称的两字节长的值,它们之间的映射事先已经为客户端的应用程序和网关/服务器所知。因此,双方可以开始使用预定义的主题ID;与上述的“普通”主题ID不同。短主题名称是长度固定为两个字节的主题名称。它们足够短,可以在PUBLISH消息中与数据一起携带。就像预定义的主题ID一样,短主题名称也不需要注册。 发现程序帮助没有预配置服务器/网关地址的客户端发现运行中的服务器/网关的实际网络地址。同一无线网络内可能同时存在多个网关,它们可以以负载共享或备用模式合作。 “清理会话”的语义扩展到了遗嘱特性,即不仅客户端的订阅是持久的,遗嘱主题和遗嘱消息也是如此。客户端还可以在会话期间修改其遗嘱主题和遗嘱消息。 为支持休眠客户端定义了新的离线保持活动程序。有了这个程序,电池操作的设备可以在睡眠状态下进入,期间所有发给它们的消息都在服务器/网关处缓冲,之后当它们唤醒时再交付给它们。 4. MQTT-SN架构 图1: MQTT-SN架构 MQTT-SN的架构如图1所示。有三种类型的MQTT-SN组件,MQTT-SN客户端、MQTT-SN网关(GW)和MQTT-SN转发器。MQTT-SN客户端通过MQTT-SN网关使用MQTT-SN协议连接到MQTT服务器。MQTT-SN网关可能与MQTT服务器集成,也可能不集成。如果是独立的网关,那么MQTT服务器和MQTT-SN网关之间使用MQTT协议。其主要功能是MQTT与MQTT-SN之间的转换。 如果网关没有直接连接到它们的网络,MQTT-SN客户端也可以通过转发器访问网关。转发器简单地封装它在无线侧接收到的MQTT-SN帧,并不加改变地转发给网关;反方向也是如此,它从网关接收到的帧解封装后,也不加改变地发送给客户端。 根据网关如何执行MQTT与MQTT-SN之间的协议转换,我们可以区分两种类型的网关,即透明网关和聚合网关,见图2。以下部分将对这两种网关进行解释。 4.1 透明网关 对于每个连接的MQTT-SN客户端,透明网关将建立并维护一个到MQTT服务器的MQTT连接。这个MQTT连接专门用于客户端和服务器之间端到端且几乎透明的消息交换。网关和服务器之间的MQTT连接数量将与连接到网关的MQTT-SN客户端数量一样多。透明网关将执行两种协议之间的“语法”转换。由于所有消息交换都是客户端与MQTT服务器之间的端到端,服务器实现的所有功能和特性都可以提供给客户端。 尽管与聚合网关相比,透明网关的实现更简单,但它需要MQTT服务器为每个活动客户端支持一个单独的连接。某些MQTT服务器实现可能会限制它们所支持的并发连接的数量。 图2:透明和聚合网关 4.2 聚合网关 与为每个连接的客户端拥有一个MQTT连接不同,聚合网关只与服务器有一个MQTT连接。MQTT-SN客户端和聚合网关之间的所有消息交换都在网关处终止。然后,网关决定哪些信息将进一步传递给服务器。虽然其实现比透明网关的实现更复杂,但在具有非常大量SAs的WSN案例中,聚合网关可能会很有帮助,因为它减少了服务器必须同时支持的MQTT连接数量。 5.消息格式 5.1 通用消息格式 消息头 (2或4字节)消息变量部分 (n字节)表1:通用消息格式 MQTT-SN消息的通用格式如表1所示。MQTT-SN消息由两部分组成:一个2或4字节长的头部和一个可选的变量部分。虽然头部总是存在且包含相同的字段,但变量部分的存在和内容取决于所考虑消息的类型。 5.2 消息头 消息头的格式如表2所示。 表2:消息头 5.2.1 长度 长度字段要么是1字节长,要么是3字节长,指定消息中包含的字节总数(包括长度字段本身)。 如果长度字段的第一个字节编码为“0x01”,则长度字段为3字节长;在这种情况下,接下来的两个字节指定消息的总字节数(最高有效字节在前)。否则,长度字段只有1字节长,并自身指定消息中包含的字节总数。 3字节格式允许编码长度高达65535字节的消息。长度小于256字节的消息可以使用较短的1字节格式。 注意,因为MQTT-SN不支持消息分段和重组,所以在网络中可以使用的最大消息长度由该网络支持的最大数据包大小决定,而不是由MQTT-SN可以编码的最大长度决定。 5.2.2 消息类型 消息类型字段长度为1字节,指定消息类型。它应该设置为表3中显示的值之一。 消息类型字段值消息类型消息类型字段值消息类型0x00ADVERTISE0x01SEARCHGW0x02GWINFO0x03保留0x04CONNECT0x05CONNACK0x06WILLTOPICREQ0x07WILLTOPIC0x08WILLMSGREQ0x09WILLMSG0x0AREGISTER0x0BREGACK0x0CPUBLISH0x0DPUBACK0x0EPUBCOMP0x0FPUBREC0x10PUBREL0x11保留0x12SUBSCRIBE0x13SUBACK0x14UNSUBSCRIBE0x15UNSUBACK0x16PINGREQ0x17PINGRESP0x18DISCONNECT0x19保留0x1AWILLTOPICUPD0x1BWILLTOPICRESP0x1CWILLMSGUPD0x1DWILLMSGRESP0x1E-0xFD保留0xFE封装消息0xFF保留表3:消息类型字段的值 5.3 消息变量部分 消息变量部分的内容取决于消息的类型。以下字段为消息变量部分定义。 5.3.1 客户端ID 与MQTT一样,客户端ID字段长度可变,包含一个1-23个字符的字符串,用于将客户端唯一地标识给服务器。 5.3.2 数据 数据字段对应于MQTT PUBLISH消息的负载。它长度可变,包含正在发布的应用数据。 5.3.3 持续时间 持续时间字段长度为2字节,指定时间周期的持续时间,以秒为单位。可以编码的最大值约为18小时。 5.3.4 标志 DUP(bit 7)QoS(6,5)保留(4)遗嘱(3)清除会话(2)主题ID类型(1,0)表4:标志字段 标志字段长度为1字节,包含以下标志(见表4): 复制(DUP):与MQTT含义相同,即如果消息是第一次发送则设置为“0”;如果是重传,则设置为“1”(仅在PUBLISH消息中相关); QoS:与MQTT的QoS级别0、1和2的含义相同;对于QoS级别0设置为“0b00”,QoS级别1设置为“0b01”,QoS级别2设置为“0b10”,新的QoS级别-1设置为“0b11”(仅在客户端发送的PUBLISH消息中相关); 保留(Retain):与MQTT含义相同(仅在PUBLISH消息中相关); 遗嘱(Will):如果设置,表示客户端请求遗嘱主题和遗嘱消息提示(仅在CONNECT消息中相关); 清除会话(CleanSession):与MQTT含义相同,但扩展了遗嘱主题和遗嘱消息(仅在CONNECT消息中相关); 主题ID类型(TopicIdType):指示此消息中包含的主题ID或主题名称字段是普通主题ID(设置为“0b00”)、预定义主题ID(设置为“0b01”)还是短主题名称(设置为“0b10”)。值“0b11”被保留。参见第3节和6.7节,了解各种类型的主题ID的定义。 5.3.5 网关地址 网关地址(GwAdd)字段长度可变,包含一个网关的地址。它依赖于MQTT-SN操作的网络,并在此字段的第一个字节中指示。例如,在ZigBee网络中,网络地址长度为2字节。 5.3.6 网关ID 网关ID(GwId)字段长度为1字节,唯一地标识一个网关。 版权所有 © 国际商业机器公司1999, 2013。保留所有权利。 5.3.7 消息ID 消息ID字段长度为2字节,对应于MQTT中的“消息ID”参数。它允许发送者将消息与其相应的确认消息匹配。 5.3.8 协议ID 协议ID长度为1字节。它仅在CONNECT消息中出现,对应于MQTT的“协议名称”和“协议版本”。它编码为0x01。所有其他值都是保留的。 5.3.9 半径 半径字段长度为1字节,指示广播半径的值。值0x00表示“向网络中的所有节点广播”。 5.3.10 返回码 1字节长的返回码字段的值及其含义如表5所示。 返回码值含义0x00接受0x01拒绝:拥挤0x02拒绝:无效的主题ID0x03拒绝:不支持0x04 - 0xFF保留 表5:返回码值 5.3.11 主题ID 主题ID字段长度为2字节,包含主题ID的值。值“0x0000”和“0xFFFF”是保留的,因此不应使用。 5.3.12 主题名称 主题名称字段长度可变,包含指定主题名称的UTF8编码字符串。 5.3.13 遗嘱消息 遗嘱消息字段长度可变,包含遗嘱消息。 5.3.14 遗嘱主题 遗嘱主题字段长度可变,包含遗嘱主题名称。 5.4 个别消息的格式 本节规定了个别MQTT-SN消息的格式。所有消息都用1字节长度字段描述。在3字节长度字段的情况下,消息格式可以直接推导,因此没有提及。 版权所有 © 国际商业机器公司1999, 2013。保留所有权利。 5.4.1 ADVERTISE 长度 消息类型 网关ID 持续时间(字节 0) (1) (2) (3,4)表6:ADVERTISE消息ADVERTISE消息由网关定期广播,以宣告其存在。下一次广播时间的时间间隔在此消息的持续时间字段中指示。其格式如表6所示: 长度和消息类型:见5.2节。 网关ID:发送此消息的网关的ID。 持续时间:直到此网关广播下一个ADVERTISE的时间间隔。 5.4.2 SEARCHGW 长度 消息类型 半径(字节 0) (1) (2)表7:SEARCHGW消息当客户端寻找网关时,会广播SEARCHGW消息。SEARCHGW的广播半径是有限的,取决于客户端部署的密度,例如,在非常密集的网络中,每个MQTT-SN客户端都可以通过1跳传输相互到达的情况下,只进行1跳广播。SEARCHGW消息的格式如表7所示: 长度和消息类型:见5.2节。 半径:此消息的广播半径。当MQTT-SN将此消息传输给底层网络层时,也会指示广播半径。 5.4.3 GWINFO 长度 消息类型 网关ID 网关地址*(字节 0) (1) (2) (3:n)(*) 如果消息由客户端发送,则包含表8:GWINFO消息GWINFO消息作为对SEARCHGW消息的响应通过底层层的广播服务发送,广播半径如SEARCHGW消息中所示。如果由网关发送,它只包含发送网关的ID;否则,如果由客户端发送,它还包括网关的地址,见表8: 长度和消息类型:见5.2节。 网关ID:网关的ID。 5.4.1 广告 长度 消息类型 网关ID 持续时间(字节0) (1) (2) (3,4)表6:广告消息广告消息由网关定期广播以宣告其存在。下一次广播时间间隔在此消息的持续时间字段中指示。其格式如表6所示: 长度和消息类型:参见5.2节。 网关ID:发送此消息的网关的ID。 持续时间:直到此网关下一次广播广告的时间间隔。 5.4.2 搜索网关 长度 消息类型 广播半径(字节0) (1) (2)表7:搜索网关消息当客户端寻找网关时,会广播搜索网关消息。搜索网关的广播半径是有限制的,取决于客户端部署的密度,例如,在一个非常密集的网络中,每个MQTT-SN客户端在1跳传输内相互可达,只需要1跳广播。搜索网关消息的格式如表7所示: 长度和消息类型:参见5.2节。 广播半径:此消息的广播半径。当MQTT-SN传输此消息时,广播半径也会指示给底层网络层。 5.4.3 网关信息 长度 消息类型 网关ID 网关地址*(字节0) (1) (2) (3:n)(*) 如果消息由客户端发送,则仅包含表8:网关信息消息网关信息消息是响应搜索网关消息而通过底层层的广播服务发送的。如果由网关发送,它只包含发送网关的ID;否则,如果由客户端发送,它还包括网关的地址,见表8: 长度和消息类型:参见5.2节。 网关ID:网关的ID。 网关地址:指示的网关的地址;可选,只在客户端发送此消息时包括。与搜索网关消息一样,此消息的广播半径在MQTT-SN传输此消息时也会指示给底层网络层。 5.4.4 连接 长度 消息类型 标志 协议ID 持续时间 客户端ID(字节0) (1) (2) (3) (4,5) (6:n)表9:连接消息客户端发送连接消息以建立连接。其格式如表9所示: 长度和消息类型:参见5.2节。 标志: DUP, QoS, Retain, TopicIdType:未使用。 Will:如果设置,表示客户端请求遗嘱主题和遗嘱消息提示; CleanSession:与MQTT含义相同,但扩展到了遗嘱主题和遗嘱消息(参见6.3节)。 协议ID:对应于MQTT连接消息的“协议名称”和“协议版本”。 持续时间:与MQTT相同,包含保持活动定时器的值。 客户端ID:与MQTT相同,包含客户端ID,是一个1-23个字符长的字符串,唯一标识服务器中的客户端。 5.4.5 连接确认 长度 消息类型 返回码(字节0) (1) (2)表10:连接确认消息服务器响应客户端的连接请求发送连接确认消息。其格式如表10所示: 长度和消息类型:参见5.2节。 返回码:根据表5编码。 5.4.6 遗嘱主题请求 长度 消息类型(字节0) (1)表11:遗嘱主题请求和遗嘱消息请求 5.4.7 遗嘱主题 长度 消息类型 标志 遗嘱主题(字节0) (1) (2) (3:n)表12:遗嘱主题消息客户端发送遗嘱主题消息作为对遗嘱主题请求消息的响应,以将其遗嘱主题名称传输给网关。其格式如表12所示: 长度和消息类型:参见5.2节。 标志: DUP:未使用。 QoS:与MQTT相同,包含遗嘱QoS Retain:与MQTT相同,包含遗嘱保留标志 Will:未使用 CleanSession:未使用 TopicIdType:未使用。 遗嘱主题:包含遗嘱主题名称。空的遗嘱主题消息是没有标志和遗嘱主题字段的遗嘱主题消息(即它正好2字节长)。客户端使用它来删除服务器中存储的遗嘱主题和遗嘱消息,参见6.4节。 5.4.8 遗嘱消息请求 网关发送遗嘱消息请求消息,请求客户端发送遗嘱消息。其格式如表11所示:它只有头部,没有变量部分。 5.4.9 遗嘱消息 长度 消息类型 遗嘱消息(字节0) (1) (2:n)表13:遗嘱消息客户端作为对遗嘱消息请求的响应发送遗嘱消息,以将其遗嘱消息传输给网关。其格式如表13所示: 长度和消息类型:参见5.2节。 遗嘱消息:包含遗嘱消息。 5.4.10 注册 长度 消息类型 主题ID 消息ID 主题名称(字节0) (1) (2,3) (4,5) (6:n)表14:注册消息客户端发送注册消息给网关,请求为包含的主题名称分配一个主题ID值。网关也发送注册消息给客户端,通知其已分配给包含的主题名称的主题ID值。其格式如表14所示: 长度和消息类型:参见5.2节。 主题ID:如果由客户端发送,则编码为0x0000,此时不相关;如果由网关发送,则包含分配给TopicName字段中包含的主题名称的主题ID值; 消息ID:应该编码,以便用于识别相应的REGACK消息。 主题名称:包含主题名称。 5.4.11 注册确认 长度 消息类型 主题ID 消息ID 返回码(字节0) (1) (2,3) (4,5) (6)表15:注册确认消息客户端或网关发送注册确认消息,作为对接收和处理注册消息的确认。其格式如表15所示: 长度和消息类型:参见5.2节。 主题ID:在PUBLISH消息中将作为主题ID使用的值; 消息ID:与相应注册消息中包含的值相同。 返回码:“已接受”,或拒绝原因。 5.4.12 发布 长度 消息类型 标志 主题ID 消息ID 数据(字节0) (1) (2) (3-4) (5-6) (7:n)表16:发布消息此消息由客户端和网关用于发布某个主题的数据。其格式如表16所示: 长度和消息类型:参见5.2节。 标志: DUP:与MQTT相同,指示消息是首次发送还是重传。 QoS:与MQTT相同,包含此发布消息的QoS级别。 Retain:与MQTT相同,包含保留标志。 Will:未使用 CleanSession:未使用 TopicIdType:指示TopicId字段中包含的主题ID的类型。 TopicId:包含发布数据所针对的主题ID值或短主题名称。 MsgId:与MQTT的“消息ID”含义相同;仅在QoS级别1和2的情况下相关,否则编码为0x0000。 数据:发布的数据。 5.4.13 PUBACK 长度 消息类型 主题ID 消息ID 返回码(字节0) (1) (2,3) (4,5) (6)表17:PUBACK消息网关或客户端发送PUBACK消息作为对接收和处理QoS级别1或2的发布消息的确认。在出现错误的情况下,也可以作为对发布消息的响应发送;然后在返回码字段中指示错误原因。其格式如表17所示: 长度和消息类型:参见5.2节。 主题ID:与相应发布消息中包含的值相同。 消息ID:与相应发布消息中包含的值相同。 返回码:“已接受”,或拒绝原因。 5.4.14 PUBREC, PUBREL, 和 PUBCOMP 长度 消息类型 消息ID(字节0) (1) (2-3)表18:PUBREC, PUBREL, 和 PUBCOMP消息与MQTT相同,PUBREC、PUBREL和PUBCOMP消息与QoS级别2的发布消息一起使用。它们的格式如表18所示: 长度和消息类型:参见5.2节。 消息ID:与相应发布消息中包含的值相同。 5.4.15 订阅 订阅消息由客户端使用,用于订阅某个特定的主题名称。其格式如表19所示: 长度和消息类型:参见5.2节。 标志: DUP:与MQTT相同,指示消息是首次发送还是重传。 QoS:与MQTT相同,包含此主题请求的QoS等级。 Retain:未使用 Will:未使用 CleanSession:未使用 TopicIdType:指示消息末尾包含的信息类型,即“0b00”主题名称,“0b01”预定义主题ID,“0b10”短主题名称,以及“0b11”保留。 消息ID:应编码,以便用于识别相应的SUBACK消息。 主题名称或主题ID:根据TopicIdType字段指示,包含主题名称、主题ID或短主题名称。 5.4.16 订阅确认 长度 消息类型 标志 主题ID 消息ID 返回码(字节0) (1) (2) (3,4) (5,6) (7)表20:订阅确认消息订阅确认消息由网关发送给客户端,作为对接收和处理订阅消息的确认。其格式如表20所示: 长度和消息类型:参见5.2节。 标志: DUP:未使用。 QoS:与MQTT相同,包含授予的QoS等级。 Retain:未使用。 Will:未使用 CleanSession:未使用 TopicIdType:未使用 5.4.16 订阅确认 长度 消息类型 标志 主题ID 消息ID 返回码(字节0) (1) (2) (3,4) (5,6) (7)表20:订阅确认消息网关发送订阅确认消息给客户端,作为对接收和处理订阅消息的确认。其格式如表20所示: 长度和消息类型:参见5.2节。 标志: DUP:未使用。 QoS:与MQTT相同,包含授予的QoS级别。 Retain:未使用。 Will:未使用。 CleanSession:未使用。 TopicIdType:未使用。 主题ID:在“已接受”的情况下,网关在向客户端发送PUBLISH消息时将使用该值作为主题ID(在订阅短主题名称或包含通配符字符的主题名称的情况下不相关)。 消息ID:与相应的订阅消息中包含的值相同。 返回码:“已接受”,或拒绝原因。 5.4.17 取消订阅 客户端发送取消订阅消息给网关,以取消订阅命名主题。其格式如表19所示: 长度和消息类型:参见5.2节。 标志: DUP:未使用。 QoS:未使用。 Retain:未使用。 Will:未使用。 CleanSession:未使用。 TopicIdType:指示消息末尾包含的信息类型,即“0b00”主题名称,“0b01”预定义主题ID,“0b10”短主题名称,和“0b11”保留。 消息ID:应编码以便用来识别相应的订阅确认消息。 主题名称或主题ID:包含主题名称、预定义主题ID或短主题名称,如TopicIdType字段所示。 5.4.18 取消订阅确认 长度 消息类型 消息ID(字节0) (1) (2-3)表21:取消订阅确认消息网关发送取消订阅确认消息以确认接收和处理取消订阅消息。其格式如表21所示: 长度和消息类型:参见5.2节。 消息ID:与相应取消订阅消息中包含的值相同。 5.4.19 PING请求 长度 消息类型 客户端ID(可选)(字节0) (1) (2:n)表22:PING请求消息与MQTT一样,PING请求消息是从连接的客户端发送或接收的“你还活着吗”的消息。其格式如表22所示: 长度和消息类型:参见5.2节。 客户端ID:包含客户端ID;此字段为可选,由“休眠”客户端在进入“唤醒”状态并等待服务器/网关发送的消息时包含,更多详情参见6.14节。 5.4.20 PING响应 长度 消息类型(字节0) (1)表23:PING响应消息与MQTT一样,PING响应消息是对PING请求消息的回应,意味着“是的,我还活着”。保持活动消息可由连接的客户端或网关发送,流向任一方向。其格式如表23所示:它只有头部,没有变量部分。此外,网关发送PING响应消息通知休眠客户端,表示没有更多为该客户端缓冲的消息,更多详情参见6.14节。 5.4.21 断开连接 长度 消息类型 持续时间(可选)(字节0) (1) (2-3)表24:断开连接消息断开连接消息的格式如表24所示: 长度和消息类型:参见5.2节。 持续时间:包含休眠定时器的值;此字段为可选,由希望进入“休眠”状态的“休眠”客户端包含,更多详情参见6.14节。与MQTT一样,客户端发送断开连接消息表示希望关闭连接。网关将通过向客户端返回一个断开连接消息来确认收到该消息。服务器或网关也可能向客户端发送断开连接消息,例如,如果网关由于错误不能将收到的消息映射到客户端。接收到此类断开连接消息的客户端应尝试通过向网关或服务器发送连接消息再次建立连接。在所有这些情况下,断开连接消息不包含持续时间字段。客户端发送带有持续时间字段的断开连接消息时,希望进入“休眠”状态。网关也通过发送断开连接消息(不带持续时间字段)来确认收到此消息。 5.4.22 遗嘱主题更新 长度 消息类型 标志 遗嘱主题(字节0) (1) (2) (3:n)表25:遗嘱主题更新消息 遗嘱主题更新消息由客户端发送给网关/服务器,以更新其在网关/服务器中存储的遗嘱主题名称。其格式如表25所示: 长度和消息类型:参见5.2节。 标志: DUP:未使用。 QoS:与MQTT相同,包含遗嘱QoS。 Retain:与MQTT相同,包含遗嘱保留标志。 Will:未使用。 CleanSession:未使用。 TopicIdType:未使用。 遗嘱主题:包含遗嘱主题名称。空的遗嘱主题更新消息是没有标志和遗嘱主题字段的遗嘱主题更新消息(即它正好2字节长)。客户端使用它来删除其在网关/服务器中存储的遗嘱主题和遗嘱消息。 5.4.23 遗嘱消息更新 长度 消息类型 遗嘱消息(字节0) (1) (2:n)表26:遗嘱消息更新消息遗嘱消息更新消息由客户端发送给网关/服务器,以更新其在网关/服务器中存储的遗嘱消息。其格式如表26所示: 长度和消息类型:参见5.2节。 遗嘱消息:包含遗嘱消息。 5.4.24 遗嘱主题响应 长度 消息类型 返回码(字节0) (1) (2)表27:遗嘱主题响应和遗嘱消息响应消息遗嘱主题响应消息由网关发送,以确认收到并处理了遗嘱主题更新消息。其格式如表27所示: 长度和消息类型:参见5.2节。 返回码:“已接受”,或拒绝原因。 5.4.25 遗嘱消息响应 遗嘱消息响应消息由网关发送,以确认接收并处理了遗嘱消息更新消息。其格式如表27所示: 长度和消息类型:参见5.2节。 返回码:“已接受”,或拒绝原因。 5.5 转发器封装 如第4节所述,如果网关没有直接连接到他们的无线传感网络,MQTT-SN客户端也可以通过转发器访问网关。转发器简单地封装它在无线侧收到的MQTT-SN帧,并不改变地转发给网关;反方向也是如此,它解封装从网关收到的帧,并同样不改变地发送给客户端。长度 消息类型 控制 无线节点ID MQTT-SN消息(字节0) (1) (2) (3:n) (n+1,m)表28:封装的MQTT-SN帧的格式封装的MQTT-SN帧的格式如表28所示: 长度:1字节长,指定到“无线节点ID”字段结束的字节数(包括长度字节本身)。 消息类型:编码为“0xFE”,见表3。 控制:控制字节包含网关和转发器之间交换的控制信息。其格式如表29所示: 广播半径:广播半径(只在网关到转发器的方向上相关)。 所有剩余位都保留。 无线节点ID:标识发送或应接收封装的MQTT-SN消息的无线节点。此ID与无线节点的地址之间的映射由转发器实现(如果需要)。 MQTT-SN消息:根据表1编码的MQTT-SN消息。保留 广播半径(位7:2) (位1,0)表29:控制字节的格式 6 功能描述 MQTT-SN的一个重要设计点是尽可能接近MQTT。因此,所有协议语义应尽可能保持与MQTT定义的相同。接下来我们将关注那些对MQTT来说是新的或有所偏离的点。 6.1 网关广告和发现 此程序是新的,MQTT中不存在。 网关可以通过定期向网络中当前的所有设备广播ADVERTISE(广告)消息来宣告其存在。网关只有在连接到服务器(或自身就是服务器)时才应广告其存在。 同一网络中可以同时有多个活跃的网关。在这种情况下,它们将拥有不同的ID。客户端可以自行决定连接哪个网关。然而,在任何时间点,客户端只允许连接到一个网关。 客户端应维护一个活跃网关及其网络地址的列表。这个列表是通过接收到的ADVERTISE和GWINFO(网关信息)消息填充的。 网关发送下一个ADVERTISE消息的时间持续期TADV在ADVERTISE消息的持续时间字段中指示。客户端可以使用这些信息来监控网关的可用性。例如,如果它连续NADV次没有收到来自某个网关的ADVERTISE消息,它可能会假设网关已经下线,并将其从活跃网关列表中移除。同样,如果备用模式的网关连续几次错过某个网关的广告,则会变为活跃状态(即开始发送ADVERTISE消息)。 由于ADVERTISE消息被广播到整个无线网络,网关发送两个ADVERTISE消息之间的时间间隔TADV应足够大(例如,大于15分钟),以避免网络中的带宽拥堵。 TADV的大值将导致寻找网关的新客户端等待时间过长。为了缩短这个等待时间,客户端可以广播SEARCHGW(搜索网关)消息。为了防止当多个客户端几乎同时开始搜索网关时发生广播风暴,发送SEARCHGW消息会被延迟一个在0到TSEARCHGW之间的随机时间。如果在这段延迟时间内,客户端接收到另一个客户端发送的与其想要发送的相同的SEARCHGW消息,它将取消发送SEARCHGW消息的传输,并表现得就像SEARCHGW消息是由它自己发送的一样。 SEARCHGW消息的广播半径Rb是有限的,例如,在MQTT-SN客户端密集部署的情况下,限制为单跳。 收到SEARCHGW消息后,网关用包含其ID的GWINFO消息作为回应。同样,如果客户端在其活跃网关列表中至少有一个活跃网关,则也用GWINFO消息作答。如果客户端在其列表中有多个网关,它将从列表中选择一个网关,并将该信息包含在GWINFO消息中。 与SEARCHGW消息一样,GWINFO消息也以相同的半径Rb广播,这在SEARCHGW消息中指示。当这两条消息传递给底层层进行传输时,也会给出半径Rb。 为了给网关优先权,客户端将延迟发送GWINFO消息一个随机时间TGWINFO。如果在这段延迟时间内,客户端接收到GWINFO消息,它将取消发送其GWINFO消息。 如果没有响应,SEARCHGW消息可以被重新传输。在这种情况下,两个连续SEARCHGW消息之间的时间间隔应该指数级增加。 6.2 客户端的连接设置 与MQTT一样,MQTT-SN客户端需要先与网关建立连接,然后才能与网关交换信息。与网关建立连接的程序如图3所示,假设客户端请求网关提示传输遗嘱主题和遗嘱消息。通过设置CONNECT消息的Will标志来表示此请求。客户端在接收到相应的请求消息WILLTOPICREQ和WILLMSGREQ后, 如果网关无法接受连接请求(例如,因为拥堵或不支持CONNECT消息中指示的某个功能),网关会返回一个带有拒绝原因的CONNACK消息。 6.3 清除会话 在MQTT中,当客户端断开连接时,其订阅不会被删除。它们是持久的,对于新连接仍然有效,直到客户端显式取消订阅,或客户端建立新的连接时设置了“清除会话”标志。 在MQTT-SN中,“清除会话”的含义扩展到了遗嘱功能,即不仅订阅是持久的,遗嘱主题和遗嘱消息也是持久的。CONNECT中的“CleanSession”和“Will”两个标志具有以下含义: CleanSession=true, Will=true:网关将删除与客户端相关的所有订阅和遗嘱数据,并开始提示新的遗嘱主题和遗嘱消息。 CleanSession=true, Will=false:网关将删除与客户端相关的所有订阅和遗嘱数据,并返回CONNACK(不提示遗嘱主题和遗嘱消息)。 CleanSession=false, Will=true:网关保留所有存储的客户端数据,但提示新的遗嘱主题和遗嘱消息。新收到的遗嘱数据将覆盖存储的遗嘱数据。 CleanSession=false, Will=false:网关保留所有存储的客户端数据,并返回CONNACK(不提示遗嘱主题和遗嘱消息)。 注意,如果客户端想在建立连接时只删除其遗嘱数据,它可以发送一个“CleanSession=false”和“Will=true”的CONNECT消息,并在被提示时向网关发送一个空的WILLTOPIC消息。它也可以发送一个“CleanSession=false”和“Will=false”的CONNECT消息,并使用6.4节的程序来删除或修改遗嘱数据。 6.4 更新遗嘱数据的程序 在连接期间的任何时候,客户端都可以通过发送WILLTOPICUPD或WILLMSGUPD消息来更新存储在网关中的遗嘱数据。这两条消息中包含的信息将覆盖网关中存储的相应信息。网关将确认这两条消息。这两条消息可以相互独立使用。 注意,一个空的WILLTOPICUPD消息将删除网关存储的遗嘱主题和遗嘱消息。 6.5 主题名称注册程序 由于无线传感网络的带宽有限和消息负载较小,数据不会像MQTT中那样与其主题名称一起发布。引入了一种注册程序,允许客户端和网关在可以开始使用短主题ID发送PUBLISH消息之前,通知对方短主题ID及其对应的主题名称。 为了注册一个主题名称,客户端向网关发送一个REGISTER消息。如果注册被接受,网关将为接收到的主题名称分配一个主题ID,并通过REGACK消息返回给客户端。如果注册未被接受,也会返回REGACK消息给客户端,并在ReturnCode字段中编码失败原因。 在收到ReturnCode为“已接受”的REGACK消息后,客户端应使用分配的主题ID发布对应主题名称的数据。如果REGACK包含拒绝代码,客户端可以稍后再次尝试注册。如果返回码为“拒绝:拥堵”,客户端应等待一段时间TWAIT后再重新开始注册程序。 任何时候,客户端可能只有一个未完成的REGISTER消息,即它必须等待REGACK消息才能注册另一个主题名称。 网关向客户端发送REGISTER消息,如果它想通知客户端将来发送PUBLISH消息时将使用的主题名称和分配的主题ID。例如,当客户端重新连接而没有设置“CleanSession”标志,或客户端已订阅包含通配符字符如#或+的主题名称时,就会发生这种情况。 6.6 客户端的发布程序 在成功地向网关注册了主题名称后,客户端可以开始通过向网关发送PUBLISH消息发布与注册主题名称相关的数据。PUBLISH消息包含分配的主题ID。 支持所有三个QoS级别及其相应的消息流,如MQTT定义。唯一的区别是PUBLISH消息中使用主题ID代替主题名称。 无论请求的QoS级别如何,客户端可能收到对其PUBLISH的响应是一个PUBACK消息,其中包含: ReturnCode=“拒绝:无效的主题ID”:在这种情况下,客户端需要再次注册主题名称,然后才能发布与该主题名称相关的数据;或 ReturnCode=“拒绝:拥堵”:在这种情况下,客户端应至少在TWAIT时间内停止向网关发布。 任何时候,客户端可能只有一个QoS级别1或2的PUBLISH消息未完成,即它必须等待这次PUBLISH消息交换结束后,才能开始新的级别1或2交易。 6.7 预定义的主题ID和短主题名称 如6.5节所述,主题ID是基于字符串的主题名称的两字节长的替代品。客户端需要使用REGISTER程序通知网关它想要使用的主题名称,并从网关获取相应的主题ID。然后,它将在发送给网关的PUBLISH消息中使用这个主题ID。反方向,PUBLISH消息也包含2字节的主题ID(而不是基于字符串的主题名称)。客户端通过先前的SUBSCRIBE程序或网关启动的REGISTER程序,被告知主题ID和主题名称之间的关系。 6.5 主题名称注册程序 由于无线传感网络中的带宽有限和消息负载较小,数据不会像在MQTT中那样连同其主题名称一起发布。引入了注册程序,允许客户端和网关在开始使用短主题ID发送PUBLISH消息之前,通知对方短主题ID及其对应的主题名称。客户端向网关发送REGISTER消息以注册一个主题名称。如果注册被接受,网关将为接收到的主题名称分配一个主题ID,并通过REGACK消息返回给客户端。如果注册未被接受,也会通过REGACK消息返回给客户端,并在ReturnCode字段中编码失败原因。在收到ReturnCode=“已接受”的REGACK消息后,客户端应使用分配的主题ID来发布对应主题名称的数据。如果REGACK包含拒绝代码,客户端可以稍后再次尝试注册。如果返回码为“拒绝:拥塞”,客户端应在重新开始注册程序之前等待一段时间TWAIT。客户端在任何时间点只能有一个REGISTER消息未决,即它必须等待REGACK消息之后才能注册另一个主题名称。网关向客户端发送REGISTER消息,如果它想通知客户端将在稍后发送PUBLISH消息时使用的主题名称和分配的主题ID。例如,当客户端重新连接而没有设置“CleanSession”标志,或客户端已订阅包含通配符字符如#或+的主题名称时,就会发生这种情况。 6.6 客户端发布程序 在成功注册主题名称后,客户端可以开始通过向网关发送PUBLISH消息来发布与注册主题名称相关的数据。PUBLISH消息包含分配的主题ID。支持所有三个QoS级别及其相应的消息流程,如MQTT中定义的那样。唯一的区别是在PUBLISH消息中使用主题ID代替主题名称。无论请求的QoS级别如何,客户端可能会收到PUBLISH的响应PUBACK消息,其中包含以下内容之一:·ReturnCode=“拒绝:无效的主题ID”:在这种情况下,客户端需要再次注册主题名称,然后才能发布与该主题名称相关的数据;或·ReturnCode=“拒绝:拥塞”:在这种情况下,客户端应停止向网关发布至少TWAIT时间。在任何时间点,客户端可能只有一个QoS级别1或2的PUBLISH消息未决,即它必须等待这个PUBLISH消息交换结束之后,才能开始新的级别1或2事务。 6.7 预定义主题ID和短主题名称 如6.5节所述,主题ID是基于字符串的主题名称的两字节长的替代品。客户端需要使用REGISTER程序通知网关它想使用的主题名称,并从网关获取相应的主题ID。然后,它将在发送给网关的PUBLISH消息中使用此主题ID。相反方向上,PUBLISH消息也包含2字节的主题ID(而不是基于字符串的主题名称)。客户端通过之前的SUBSCRIBE程序或网关启动的REGISTER程序,了解主题ID和主题名称之间的关系。"预定义"主题ID是客户端应用程序和网关预先知道其映射到主题名称的主题ID。这在消息的Flags字段中指示。使用预定义主题ID时,双方可以立即开始发送PUBLISH消息;不需要像"普通"主题ID那样的REGISTER程序。如果收到一个带有预定义主题ID的PUBLISH消息,其映射到主题名称未知,则接收方应返回一个PUBACK,ReturnCode=“拒绝:无 6.10 网关的发布程序 类似于第6.6节中描述的客户端的发布程序,网关发送带有在SUBACK消息中返回给客户端的主题ID值的PUBLISH消息。 在发送PUBLISH消息之前,网关可能会发送一个REGISTER消息以通知客户端有关主题名称及其分配的主题ID值。例如,当客户端重新连接时没有选择清理会话,或者订阅了带有通配符字符的主题名称时,就会发生这种情况。在收到REGISTER消息后,客户端回复一个REGACK消息。网关将等待REGACK消息,然后再将PUBLISH消息发送给客户端。 客户端可以通过带有拒绝原因的REGACK消息拒绝REGISTER消息;这相当于取消订阅REGISTER消息中指示的主题名称。注意,只有通过第6.9节中描述的取消订阅程序才能取消订阅带有通配符字符的主题名称,而不能通过拒绝REGISTER消息来完成,因为REGISTER消息从不包含带有通配符字符的主题名称。 如果客户端收到一个带有未知主题ID值的PUBLISH消息,它应该回复一个ReturnCode=“拒绝:无效的主题ID”的PUBACK消息。这将触发网关删除或更正错误的主题ID分配。 注意,如果主题名称或数据太长而不能适应REGISTER或PUBLISH消息,网关会默默地中止发布程序,即不会向受影响的订阅者发送警告。 6.11 保持活动和PING程序 与MQTT一样,保持活动计时器的值在CONNECT消息中指示。客户端应在每个保持活动时间周期内发送一个PINGREQ消息,网关用PINGRESP消息进行回应。 同样,当客户端收到其连接的网关发送的PINGREQ消息时,应用PINGRESP消息回复。否则,接收到的PINGREQ消息将被忽略。 客户端应使用此程序来监督其所连接的网关的活动状态。如果客户端在多次重传PINGREQ消息后仍未从网关收到PINGRESP,它应首先尝试连接到另一个网关,然后再尝试重新连接到这个网关(参见第6.13节)。注意,由于客户端的保持活动计时器彼此不同步,在网关故障的情况下,所有受影响的客户端几乎同时向新网关发送CONNECT消息的风险实际上是不存在的。 6.12 客户端的断开连接程序 客户端发送DISCONNECT消息给网关,表明它即将关闭连接。此后,客户端需要与网关建立新连接才能再次与网关交换信息。与MQTT相似,发送DISCONNECT消息不会影响现有订阅和遗嘱数据,如果设置了CleanSession标志。它们将持续存在,直到它们被客户端显式取消订阅、删除或修改,或者客户端与设置了CleanSession标志的新连接建立。网关通过向客户端返回一个DISCONNECT消息来确认收到DISCONNECT消息。 客户端也可能接收到网关发送的未经请求的DISCONNECT。例如,当网关由于错误无法识别收到消息所属的客户端时,就可能发生这种情况。在收到此类DISCONNECT消息后,客户端应尝试通过向网关发送CONNECT消息再次建立连接。 6.13 客户端的重传程序 所有“单播”到网关的消息(即使用网关的单播地址发送而不是广播)以及期待网关回复的消息,都由重试计时器Tretry和重试计数器Nretry监控。客户端在发送消息时启动重试计时器Tretry,并在收到期待的网关回复时停止。如果Tretry超时且未收到期待的网关回复,客户端将重新传输消息。经过Nretry次重传后,客户端将中止程序并假设其MQTT-SN连接到网关已断开。然后,它应尝试连接到另一个网关,仅在重新连接到前一个网关失败时尝试。 6.14 支持休眠客户端 休眠客户端是居住在(电池操作的)设备上的客户端,这些设备希望尽可能节省能量。这些设备需要在不活跃时进入睡眠模式,并在有数据发送或接收时唤醒。服务器/网关需要了解这些客户端的睡眠状态,并将发送给它们的消息缓存起来,以便它们唤醒时后续交付。 图4:客户端状态转换图 如图4所示,从服务器/网关的角度看,客户端可能处于以下状态之一:活跃、睡眠、唤醒、断开连接或丢失。当服务器/网关收到来自该客户端的CONNECT消息时,客户端处于活跃状态,如第6.2节所述。服务器/网关使用“保持活动”计时器监控此状态,如第6.11节所述。如果服务器/网关在超过CONNECT消息中指示的保持活动持续时间的时间内未收到客户端的任何消息,网关将认为该客户端已丢失,并且例如为该客户端激活遗嘱功能。 当服务器/网关接收到一个不包含持续时间字段的DISCONNECT消息时,客户端进入断开连接状态。服务器/网关不对此状态进行时间监控。 如果客户端想要休眠,它发送一个包含睡眠持续时间的DISCONNECT消息。服务器/网关用一个DISCONNECT消息回复该消息,并将客户端视为处于睡眠状态,参见图5。睡眠状态由服务器/网关使用指示的睡眠持续时间监控。如果服务器/网关在超过睡眠持续时间的时间内未收到客户端的任何消息,服务器/网关将认为该客户端已丢失,并且-如同保持活动程序一样-例如激活遗嘱功能。 睡眠程序 在睡眠状态期间,所有需要发送给客户端的消息都在服务器/网关处缓存。 图5:睡眠程序 当服务器/网关收到客户端的PINGREQ消息时,睡眠计时器停止。像CONNECT消息一样,这个PINGREQ消息包含客户端ID。然后识别的客户端处于唤醒状态。如果服务器/网关有为客户端缓存的消息,它将把这些消息发送给客户端。服务器/网关通过PINGRESP消息结束向客户端传输消息,即服务器/网关在发送PINGRESP消息后会认为客户端处于睡眠状态并重新启动睡眠计时器。 如果服务器/网关没有为客户端缓存任何消息,它会立即回复PINGRESP消息,将客户端返回到睡眠状态,并为该客户端重新启动睡眠计时器。 在向服务器/网关发送PINGREQ后,客户端使用第6.13节的“重传程序”来监督由服务器/网关发送的消息的到达,即它在接收到非PINGRESP的消息时重新启动计时器Tretry,并在接收到PINGRESP时停止它。当计时器Tretry超时时,PINGREQ消息被重传并重新启动计时器Tretry。为了避免因过度重传PINGREQ消息(例如,如果它失去了网关)而导致电池耗尽,客户端应限制PINGREQ消息的重传(例如,通过重试计数器),并在达到限制且仍未收到PINGRESP消息时回到睡眠状态。 从睡眠或唤醒状态,客户端可以通过发送CONNECT消息返回到活跃状态,或通过发送普通DISCONNECT消息(即没有持续时间字段的)返回到断开连接状态。客户端还可以通过发送带有新的睡眠持续时间值的DISCONNECT消息来修改其睡眠持续时间。 请注意,休眠客户端只应在它只是想检查服务器/网关是否有任何消息为其缓存时进入唤醒状态,并尽快返回到睡眠状态,而不向服务器/网关发送任何消息。否则,它应通过向服务器/网关发送CONNECT消息返回到活跃状态。 7 实施注意事项 7.1 支持QoS级别-1 因为QoS级别-1的PUBLISH消息可以随时由客户端发送(即使没有建立连接),透明网关需要为这些消息与服务器维持一个专用的MQTT连接。一个聚合或混合网关可以使用任何聚合MQTT连接将这些消息转发给服务器。 7.2 定时器和计数器的“最佳实践”值 表30显示了本规范中定义的定时器和计数器的“最佳实践”值。 定时器/计数器推荐值TADV大于15分钟NADV2-3TSEARCHGW5秒TGWINFO5秒TWAIT大于5分钟Tretry10-15秒Nretry3-5表30:定时器和计数器的“最佳实践”值 服务器/网关的睡眠和保持活动定时器的“容忍度”取决于客户端指示的持续时间。例如,对于大于1分钟的持续时间,定时器值应比指示值高10%,如果少于此值,则高50%。 7.3 主题ID与主题名称的映射 强烈建议在网关中,主题ID与主题名称之间的映射表按客户端实现(而不是在所有客户端之间共享一个单一的池),以降低一个客户端的错误主题ID与另一个客户端的有效主题匹配,并因此导致向错误主题的发布,这可能会产生灾难性的后果。 7.4 与ZigBee相关的问题 在ZigBee网络中,网关不需要由协调器节点托管。但它应该位于一个始终在线的路由器节点上,以便随时接收客户端消息。 由于ZigBee网络/APS层的有效载荷长度短,MQTT-SN消息的最大长度限制为60字节。 --- ═══════════════════════════════════════════ ## MQTT要点 ═══════════════════════════════════════════ ### 238. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 目录 为数字化转型建立统一命名空间:CXO常见问题 FAQ #1 – 如果我将UNS纳入我的数字化转型项目,它如何提高投资回报率? FAQ #2 – 设计UNS语义信息层次结构的最佳方式是什么? FAQ #3 – 在实施UNS时,我还能使用ISA-95功能建模标准吗? FAQ #4 – 如何在工业物联网环境中保持UNS架构的安全性? FAQ #5 – UNS如何进行扩展和维护? FAQ #6 – 创建UNS概念验证(PoC)的成本是多少? 利用UNS推动数字化转型的成功 为数字化转型建立统一命名空间:CXO常见问题 统一命名空间(UNS)是一种突破性的架构方法,适用于制造业的数字化转型。它通过采用边缘驱动架构和利用MQTT等标准数据协议的开放架构,帮助组织管理复杂性并增强数据互操作性。UNS架构将各个功能域的上下文数据外部化为实时语义层次结构,建立一个中枢辐射模型,作为企业当前状态和事件的单一信息源。 作为负责数字化转型项目的CXO,UNS可以提升您连接生态系统的投资回报率,并简化数据集成。以下是我们在HiveMQ从CXO那里听到的关于UNS对其数字化转型之旅影响的常见问题(FAQ)。 FAQ #1 – 如果我将UNS纳入我的数字化转型项目,它如何提高投资回报率? 统一命名空间(UNS)架构通过提供一个实时的、语义化组织的分层数据结构,作为工业物联网(IIoT)环境中数据访问和集成的中央枢纽,可以显著提高您的数字化转型项目的投资回报率(ROI)。 通过采用UNS架构,组织可以有效地管理复杂性并增强其IIoT系统中的数据互操作性,从而提高效率、生产力和投资回报率。 以下是UNS架构的一些关键优势,这些优势有助于提高投资回报率: 改进的数据访问和集成:UNS架构确保在特定区域内和整个组织中跨不同平台和应用程序的无缝数据访问和集成。这使公司能够有效利用数据来增强运营智能,从而改进决策和运营效率。 实时语义层次结构:UNS架构建立了一个实时语义数据层次结构,作为企业当前状态和事件的单一信息源。这使每个网络参与者都能立即访问整个组织的信息,减少通信延迟并提高整体生产力。 数据建模和功能建模:UNS架构利用数据和功能建模来定义数据的上下文和含义,实现语义互操作性。这确保了不同的应用程序和子系统能够理解他们交换的数据,从而促进数据驱动的决策和运营效率。 边缘驱动架构:UNS架构基于边缘驱动架构,允许在网络边缘进行数据处理和分析,从而减少延迟并提高整体系统性能。这导致更快的决策和更高的生产力,从而提高投资回报率。 标准数据基础设施:UNS架构利用MQTT等标准数据基础设施,确保不同系统和应用程序之间的兼容性和互操作性。这减少了集成成本,并简化了数据管理过程,从而提高投资回报率。 FAQ #2 – 设计UNS语义信息层次结构的最佳方式是什么? 设计UNS语义信息层次结构涉及建立一个明确的语义层次结构,包含分层的结构化数据。以下是一个示例: markdown复制代码manufacturing/ - plantA/ - sensors/ - humidity/ - sensor001 - sensor002 - ... - inventory/ - raw_materials/ - current_stock - reorder_levels - finished_goods/ - current_stock - shipping_schedule - quality_control/ - inspection/ - results - trends - testing/ - test001/ - results - next_schedule - ... - plantB/ - ... 该结构作为中央枢纽,一个单一的信息源,反映企业的当前状态和事件。它使每个网络参与者能够立即访问数据,打破ISA-95的限制,使其在整个车间都可以使用。此外,UNS为找到组织中不同角色相关的分析数据提供了明确的路径——从数字化转型专家到运营技术(OT)工程师。 阅读我们的博客文章《设计您的UNS语义信息层次结构》了解更多信息。 FAQ #3 – 在实施UNS时,我还能使用ISA-95功能建模标准吗? 在UNS架构中,OT和IT的不同应用程序和子系统必须理解他们交换的数据。这种理解是通过数据模型实现的,数据模型定义了数据的上下文和含义,实现语义互操作性。在UNS中进行任何数据集成过程时,数据建模是至关重要的。而在开发数据模型以实现操作和业务领域之间的信息流时,有两种主要策略:从头开始构建或使用ISA-95功能建模标准作为指南或灵感来源。 UNS的主要目标是概述数据的结构、关系和属性。 阅读我们的博客文章《统一命名空间的数据和功能建模》了解有效集成到UNS的数据模型设计过程,以及为什么DataOps对UNS架构至关重要。 FAQ #4 – 如何在工业物联网环境中保持UNS架构的安全性? 从一开始就设计UNS时实施严格的安全协议,以保护数据完整性和隐私。这可以通过实施数据加密、访问控制、身份验证、授权、使用防火墙、负载均衡器和隔离区等安全策略和最佳实践来实现。 如果您使用MQTT,您可以通过为每个客户端设置授权来保护UNS中的MQTT通信,以防止对所有主题的无限制访问。 阅读我们的博客文章《为工业物联网保护统一命名空间架构》了解如何通过可行的策略和最佳实践来应对UNS在工业物联网环境中的关键安全挑战。 FAQ #5 – UNS如何进行扩展和维护? UNS设计为可扩展的。随着组织的发展或新技术的采用,架构可以扩展而不失效率。定期审计和更新是必要的,以确保系统保持强大并对新挑战做出响应。 观看我们的网络研讨会《为工业物联网架构统一命名空间》了解UNS如何帮助工业公司创建敏捷和可扩展的框架,弥合OT与IT之间的差距,并为复杂用例如人工智能/机器学习和数字化转型所必需的高级分析做好准备。 FAQ #6 – 创建UNS概念验证(PoC)的成本是多少? 您可以使用基于开放标准的自管理或自服务MQTT平台免费或以最低成本创建PoC,该平台提供数据策略、安全性和可观察性。 试用HiveMQ Cloud,一个完全托管的云MQTT平台,免费。许多HiveMQ客户使用它来开发、测试、部署和扩展生产物联网用例,而无需大量投资和维护自己的基础设施的复杂性。 利用UNS推动数字化转型的成功 在当今快速发展的工业环境中,能够跨各种系统和平台无缝集成和分析数据至关重要。通过UNS,您的组织可以有效地管理复杂性,增强IIoT系统中的数据互操作性,并加速数字化转型。 。 --- ### 239. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 目录 探索Postman与HiveMQ的MQTT集成 Postman对MQTT的支持 使用Postman进行MQTT通信 利用Postman通过API管理HiveMQ云代理 执行API调用 结论 Postman是一个REST/HTTP API开发和测试平台,提供多种功能。它允许开发人员轻松创建、使用和共享API请求和集合,自动化测试、模拟API和监控性能。Postman还提供协作和文档工具,使团队能够更高效地协同工作并有效地沟通API行为。 通过新增MQTT支持,Postman不仅限于处理Rest/HTTP API,还可以支持MQTT通信,定义MQTT集合并开发基于MQTT的文档。在HiveMQ,我们视自己为MQTT协议的守护者,我们很高兴看到Postman现已全面实现对MQTT的支持。 MQTT(消息队列遥测传输)是一种轻量级通信协议,专为物联网(IoT)设计。它使设备能够高效地交换数据,通过订阅特定“主题”并向这些主题发布消息。MQTT非常适合于工业自动化和监控、传感器站和车辆遥测等IoT应用。它在低带宽、实时和低功耗场景中表现出色。 HiveMQ是值得信赖并在业界广泛验证的企业级MQTT平台,能够在MQTT客户端之间实现可靠且可扩展的通信。它在实际环境中表现非常可靠,具有灵活性、安全性和可扩展性,提供实际解决方案。 以API开发和测试的多功能性著称的Postman,现在也可以有效地用于MQTT通信和通过HiveMQ代理API管理HiveMQ代理。利用Postman功能的双重适用性,开发人员可以简化MQTT系统的测试、调试和管理,这些系统连接到HiveMQ。 让我们探索如何使用Postman进行HiveMQ的MQTT通信和API管理,并了解为什么HiveMQ和Postman是最佳搭档! Postman对MQTT的支持 Postman对MQTT的支持为从事IoT项目的开发人员提供了广泛的可能性。以下是Postman可用于MQTT的概述。 Postman提供了一个用户友好的界面,用于配置MQTT连接。开发人员可以直接在Postman应用程序中指定代理URL、客户端ID、凭证(如果需要)和其他参数。 使用Postman,开发人员可以轻松地向MQTT主题发布消息。Postman的直观界面允许用户指定有效载荷、主题、服务质量(QoS)级别和其他消息属性,简化了向设备或应用程序发送测试消息的过程。 Postman允许开发人员轻松订阅MQTT主题,并实时查看接收到的消息。这简化了监控消息流量的过程,确保订阅正确配置。 在Postman的MQTT支持中,引入了一个突出的功能,即能够以更易读的方式查看遥测数据。接收数据后,可以在订阅的主题上看到可视化效果。除了订阅主题外,不需要额外配置。 Postman强大的测试功能可以用于基于MQTT的系统。开发人员可以创建测试脚本来自动化消息发布、订阅管理和验证,进行IoT应用的全面测试。 Postman可免费下载,支持所有主流平台,下载地址:https://www.postman.com/downloads 使用Postman进行MQTT通信 在这个示例中,我们将使用免费的HiveMQ社区版。当然,你可以替换为任何你选择的MQTT代理,无论是本地托管还是云托管。 首先启动Postman,在工作区中点击“新建”,选择MQTT请求类型。在连接栏中输入mqtt://broker.hivemq.com,选择MQTT版本5(默认)并点击蓝色的连接按钮。 连接后,可以发送消息字段中引用的有效载荷(MQTT中的任何内容)到主题字段中引用的主题。点击蓝色的发送按钮实际发送它。响应窗口中显示一个向上的箭头。 在“主题”标签中,你可以订阅任何你想跟踪的主题。一旦收到一个主题,这些内容将在响应窗口中显示,并带有一个向下的箭头。 现在,如果你发布消息到刚刚订阅的主题,该消息将被发布并随后被接收,如下图所示。 这就是发布和订阅MQTT代理和主题的简单方法。请随意使用高级功能,例如服务质量、保留、持久/清除会话和遗嘱消息(LWT)功能。这些标准MQTT功能展示了MQTT协议的额外强大功能,所有这些都可以在Postman环境中轻松演示。 利用Postman通过API管理HiveMQ云代理 Postman以其设置和测试API的能力而闻名,因此我们可以用它远程管理HiveMQ云代理。 我们将通过在cloud.hivemq.com上设置一个HiveMQ Cloud Starter集群,并在Postman中通过提供的API进行管理来进行演示。 首先,在cloud.hivemq.com上免费设置一个私人“starter”集群,无需信用卡。 部署后,打开https://console.hivemq.cloud并选择API访问标签,创建一个新的令牌。 使用合适的名称、合理的过期时间和“完全访问”来创建令牌。将令牌连同基本API和REST URL复制粘贴到文本编辑器中并安全存储。 现在下载OpenAPI规范。点击Postman应用程序中间顶部的按钮,将API导入为Postman定义,并优选地创建一个集合。集合允许你修改和添加参数并将其保存到适用的环境或集合中。 定义需要你创建一些包含orgId、clusterId和baseUrl的变量。这些变量可以在REST基本URL中找到,如下图所示。 最简单的方法是创建一个新环境,包含这些变量,并在右上角选择该环境作为默认环境。 在集合的顶层,可以为集合中的所有API调用设置承载令牌。请将从HiveMQ网页界面复制的令牌粘贴到令牌字段中(不要带尾随换行符)。 点击右上角的保存图标,并将每个集合中API的授权选项设置为“从父项继承授权”。 现在,选择一个API调用,将参数设置为固定值或环境中的变量字段,使用双括号。示例如下图所示。 现在所有参数和承载授权都已设置,可以发送API调用并正确执行。 执行API调用 一旦所有参数、API端点和安全性到位,我们就可以针对运行中的集群执行API调用。例如,我们使用“不需要进一步参数化的列出所有MQTT客户端”;只需选择它,将环境变量添加到变量部分的值字段中间,点击发送按钮。作为回复,你会得到连接到代理的MQTT客户端名称列表。 另一个示例,我们使用“列出所有角色”也不需要进一步参数化;只需选择它,将环境变量添加到变量部分的值字段中间,点击发送按钮。作为回复,你会得到代理上定义的所有角色列表。 此时,你已经准备好尝试API集合中可用的所有其他调用。不要忘记保存它们,以免每次都要添加参数值。 结论 随着MQTT云代理的使用越来越普遍,通过部署管道来管理它们的需求也会增加。HiveMQ云代理通过提供的安全API具有出色的可配置性。可以轻松地在Postman中使用提供的HiveMQ API定义构建和测试这些程序接口。 Postman是简化MQTT开发和测试的有价值工具。它还提供了一个强大且定义明确的REST API工具,以编程方式管理HiveMQ代理。 通过提供用户友好的界面、强大的测试功能和协作和文档支持,Postman使开发人员能够更高效地构建和调试基于HiveMQ的系统。无论你是在进行小型IoT项目还是开发大型M2M解决方案,Postman对MQTT和REST-API的支持将简化你的开发工作流程并加快上市时间。 --- ### 240. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 什么是 MQTT 发布消息? 在 MQTT 中,客户端连接到代理后可以立即发布消息。消息根据主题进行过滤,每条消息必须包含一个主题,代理可以使用该主题将消息转发给感兴趣的客户端。每条消息的有效负载包括以字节格式传输的数据,发送客户端可以选择发送任何类型的数据,包括文本、数字、图像、二进制数据,甚至成熟的 XML 或 JSON。 MQTT 负载格式示例 MQTT 与数据无关,这意味着可以根据客户端的特定用例构建有效负载。有效负载是消息的主要内容,是客户端订阅、接收和处理的内容。 MQTT 中的 PUBLISH 消息具有确定其行为的多个属性,包括数据包标识符、主题名称、服务质量、保留标志、有效负载和 DUP 标志。让我们分别看一下。 什么是 MQTT PacketId 或数据包标识符? 数据包标识符(PacketId)是 MQTT 中的一个基本属性。它用于识别特定消息并确保消息按发送顺序传递,特别是在使用大于零的 QoS 级别时。数据包 ID 由客户端分配,并包含在 PUBLISH、PUBREL、PUBREC 和 PUBCOMP 消息中。当代理收到 PUBLISH 消息时,它会为该消息分配一个数据包 ID,并向客户端发送包含 PUBLISH 消息的数据包 ID 的 PUBACK 消息。客户端使用 PUBACK 消息来确认代理已收到消息。 在 MQTT 协议中,与消息发布和确认相关的消息分为几个阶段: 1.发布 (PUBLISH):这是该过程的第一阶段,涉及 MQTT 客户端向代理发布消息。该消息包含主题和负载。 2.发布接收(PUBREC):broker收到PUBLISH消息后,发送PUBREC消息以确认已收到该消息。这是该过程的第二阶段。 3.发布发布(PUBREL):客户端收到 PUBREC 消息后,会发送 PUBREL 消息以释放代理将消息保留在内存中的责任。这是第三阶段。 4.发布完成(PUBCOMP):代理最终发送 PUBCOMP 消息以确认已成功接收并处理该消息。这是该过程的第四个也是最后一个阶段。 这四个消息是 MQTT 协议的服务质量 (QoS) 机制的一部分,可确保可靠的消息传递。QoS 级别决定客户端和代理之间交换的消息数量。 值得注意的是,当消息在客户端和代理之间流动时,数据包标识符唯一地标识消息。数据包标识符仅与大于零的 QoS 级别相关。这不仅适用于 PUBLISH,也适用于 SUBSCRIBE、UNSUBSCRIBE 和 CONNECT 消息。 客户端库和/或代理负责设置此内部 MQTT 标识符。当使用大于零的 QoS 级别时,客户端必须等待来自代理的 PUBACK 或 PUBREC 消息,然后才能发送下一条消息。客户端还应该跟踪它已发送和接收的数据包 ID,以确保消息不会丢失或重复。总体而言,数据包 ID 对于 MQTT 的可靠性机制至关重要,有助于确保消息正确高效地传递。 MQTT 主题名称是什么? MQTT 使用主题名称作为基本概念。它使用正斜杠作为分隔符分层构造该名称,并创建一个简单的字符串。它类似于 URL 路径,但没有协议和域组件。MQTT 主题用于标记消息并为客户端提供订阅特定消息的方式。 例如,测量温度的设备可能会将其读数发布到主题"sensors/temperature/livingroom"。对这些读物感兴趣的客户可以订阅该主题并在发布时接收更新。 MQTT 提供两种类型的通配符用于主题订阅: “+”(加号)用于匹配层次结构中的单个级别。例如,订阅将"sensors/+/livingroom"匹配“传感器/温度/客厅”和“传感器/湿度/客厅”,但不匹配“传感器/温度/厨房”。 “#”(井号)用于匹配层次结构中的多个级别。例如,订阅“sensors/#”将匹配“sensors/温度/livingroom”、“sensors/humidity/kitchen”和“sensors/power/meter1”。 订阅大量主题会对代理性能产生重大影响。这是因为发布到客户端订阅的主题的每条消息都必须传递到该客户端。如果许多客户订阅许多主题,这很快就会成为经纪人的沉重负担。 使用通配符通过单个订阅来订阅多个主题也会影响性能。当客户端使用通配符订阅主题时,代理必须评估发布到匹配主题的每条消息,并确定是否将其转发给客户端。如果匹配主题的数量很大,这可能会导致代理的资源紧张。 为了避免性能问题,有效使用主题订阅非常重要。一种方法是尽可能使用更具体的主题过滤器,而不是依赖通配符。另一种方法是使用共享订阅,它允许多个客户端共享对某个主题的单个订阅。这可以帮助减少代理必须处理的订阅和消息的数量。最后,监控代理的性能并根据需要调整其配置对于确保最佳性能非常重要。 MQTT 中的服务质量 (QoS) 是什么? 我们在介绍 MQTT 协议一文中谈到了 MQTT 消息的服务质量级别 (QoS) 。回顾一下,QoS 由 0 到 2 范围内的数字表示。每个级别都为消息传递提供不同级别的可靠性和保证。 QoS 0(最多一次):此级别不保证消息将被传递。消息发送一次,如果丢失或收件人未收到,则不会重发。 QoS 1(至少一次):此级别确保消息至少传递一次,但在网络问题或故障的情况下可能会传递多次。 QoS 2(恰好一次):此级别为消息传递提供最高级别的保证。保证消息恰好传递一次,但此级别需要发送者和接收者之间进行更多通信,这可能会增加延迟和网络流量。 选择适当的 QoS 级别取决于具体的用例。例如,QoS 0 可能适用于非关键数据,而 QoS 2 可能适用于需要高可靠性级别的关键数据。 请务必注意,QoS 级别会影响代理和网络的性能,因此建议针对特定用例使用适当的级别。有关更多信息,请阅读我们的文章MQTT 服务质量 (QoS) 0,1, & 2或其他资源,例如MQTT 5 Essentials。 什么是 MQTT 保留标志? 保留标志是一项重要功能,它确定代理是否将消息保存为指定主题的最后一个已知正确值。当retained标志设置为true时,无论是否有任何订阅的客户端,代理都会保存与指定主题匹配的最新消息。 当新客户端订阅带有保留消息的主题时,代理会将最后保留的消息(关于该主题)发送给客户端。这允许客户接收最新的相关信息,即使他们以前没有订阅过该主题。 需要注意的是,与许多其他元素一样,保留消息的使用也会影响代理的性能,尤其是在存在许多保留消息的情况下。此外,如果保留的消息频繁更新,可能会导致网络流量增加,并可能影响网络性能。 什么是 MQTT 有效负载? 有效负载是消息的实际内容,可以包含任何类型的数据。MQTT 与数据无关,这意味着它可以处理不同的数据类型,包括图像、任何编码的文本、加密数据和二进制数据。但是,请务必注意,有效负载大小可能会影响客户端和代理上的网络性能和内存使用情况。因此,建议保持有效负载尽可能小,尤其是在高频率发布消息时。 什么是 MQTT DUP 标志? MQTT DUP 标志表示消息是重复的,并且由于预期接收者(客户端或代理)未确认原始消息而已重新发送。它仅与 QoS 大于 0 的消息相关。当客户端或代理收到设置了 DUP 标志的消息时,如果它已经收到具有相同消息 ID 的消息,则应忽略该消息。如果客户端或代理之前未收到消息,则应正常处理该消息。 MQTT 协议(MQTT 客户端库或代理)自动处理重新发送和重复机制,但需要注意的是,这可能会影响网络性能并增加网络流量。 MQTT 代理如何处理来自客户端的消息? 当客户端向 MQTT 代理发布消息时,代理会执行多项任务以确保根据客户端指定的 QoS 级别传递消息。发生的情况如下: 消息接收:broker读取客户端发送的消息并验证其语法和格式。 确认:代理向客户端发送确认消息以确认收到消息。确认级别取决于客户端请求的 QoS 级别。 处理:代理确定哪些客户端订阅了消息的主题,并向每个客户端发送消息的副本。代理还可以将消息保留为该主题的最后一个已知的正确值,具体取决于 Retained 标志的值。 反馈:发布客户端收到来自代理的确认消息,表明消息已成功发布。但是,客户端不会收到有关有多少订阅者收到该消息或是否有人对此感兴趣的反馈。 MQTT 发布的工作原理 最初发布消息的客户端只关心将 PUBLISH 消息传递给代理。一旦代理收到 PUBLISH 消息,代理就有责任将该消息传递给所有订阅者。发布客户端不会获得任何关于是否有人对已发布消息感兴趣或有多少客户端从代理收到消息的反馈。 如何订阅MQTT主题? 如果没有人收到消息,那么发布消息就没有意义。这就是订阅发挥作用的地方。一旦客户端向 MQTT 代理发布消息,该消息就必须传递给感兴趣的客户端。想要接收有关感兴趣主题的消息的客户端向代理发送一条SUBSCRIBE消息。SUBSCRIBE 消息很简单,包含唯一的数据包标识符和订阅列表。 MQTT 订阅数据包示例 数据包标识符:数据包标识符是唯一的,用于标识客户端和代理之间传输的消息。客户端库或代理负责设置此内部 MQTT 标识符。 订阅列表:一条 SUBSCRIBE 消息可以包含一个客户端的多个订阅。每个订阅都包含一个主题和一个 QoS 级别。SUBSCRIBE 消息中的主题可以包含通配符,从而可以订阅主题模式而不是特定主题。如果一个客户端存在重叠订阅,则代理会传递该主题具有最高 QoS 级别的消息。 总体而言,MQTT 允许客户端订阅特定主题、接收发布到这些主题的消息,并根据其特定用例处理有效负载。SUBSCRIBE 消息中的数据包标识符和 QoS 级别可确保消息以适当的质量级别可靠地传送。 一旦客户端向 MQTT 代理发送包含所需主题列表和 QoS 级别的 SUBSCRIBE 消息,代理就会使用 SUBACK 消息进行响应,该消息确认订阅并指示代理将提供的最大 QoS 级别。让我们更深入地了解 SUBACK。 什么是 MQTT Subback? 一旦客户端向代理发送包含主题和相应 QoS 级别的 SUBSCRIBE 消息,代理就会通过向客户端发送SUBACK消息来确认订阅请求。SUBACK 消息确认 SUBSCRIBE 消息的接收,并指示代理是否已接受或拒绝每个订阅。 MQTT SUBACK 数据包示例 数据包标识符:SUBACK 消息包含与客户端在 SUBSCRIBE 消息中包含的相同的数据包标识符,这使得客户端能够将确认与原始请求进行匹配。 返回代码:SUBACK 消息还包括针对 SUBSCRIBE 消息中指定的每个主题/QoS 对的一个返回代码。返回代码是二进制值,指示代理是否已批准或拒绝每个主题的订阅请求。 QoS级别的返回码如下: QoS 0:这意味着订阅请求已在 QoS 0 下获得批准。代理会在消息可用时立即将消息传递给客户端,并且没有质量保证。 QoS 1:这意味着订阅请求已在 QoS 1 上获得批准。代理至少传递消息一次,这意味着代理向客户端至少发送一次消息。客户端收到消息后向代理发送回 PUBACK 消息,作为确认。 QoS 2:这意味着订阅请求已在 QoS 2 上获得批准。代理只传送消息一次,这意味着代理保证消息向客户端传送一次且仅传送一次。客户端收到消息后将 PUBREC 消息发送回代理,作为确认。Broker收到PUBREC消息后向Client发送PUBREL消息,Client收到PUBREL消息后向Broker发送PUBCOMP消息。 如果代理拒绝 SUBSCRIBE 消息中的任何订阅,则 SUBACK 消息将包含该特定主题的失败返回代码。失败的原因可能是客户端没有足够的权限订阅主题、主题格式错误或其他原因。 失败返回码用0x80表示,表示经纪商不接受订阅。如果客户端没有足够的权限来订阅该主题、主题格式错误或者订阅请求存在其他问题,则可能会发生这种情况。当客户端收到失败返回代码时,它应该使用不同的主题或 QoS 级别重试订阅,或者采取适当的操作来解决订阅请求的问题。 返回码返回码响应0成功 - 最大 QoS 01成功 - 最大 QoS 12成功 - 最大 QoS 2128失败 MQTT SUBSCRIBE、SUBACK 和 PUBLISH 的工作原理 SUBACK 消息是从代理到客户端的确认消息,用于确认已授予或拒绝的订阅。数据包标识符使客户端能够将确认与原始请求相匹配,而返回代码则指示代理授予订阅的 QoS 级别。 当客户端订阅了感兴趣的主题并收到发布到这些主题的消息后,它最终可能需要取消订阅。现在让我们探讨一下 SUBSCRIBE 消息的对应部分、UNSUBSCRIBE 消息以及确认取消订阅的相应 UNSUBACK 消息。 如何使用MQTT中的取消订阅来撤销订阅? 在 MQTT 中,客户端可以通过向代理发送UNSUBSCRIBE消息来取消订阅他们已订阅的主题。与 SUBSCRIBE 类似,此消息包含用于唯一标识它的数据包标识符以及要取消订阅的主题列表。 MQTT 取消订阅数据包示例 数据包标识符:与 SUBSCRIBE 消息类似,UNSUBSCRIBE 消息中的数据包标识符用作客户端和代理之间消息流的内部 MQTT 标识符。它确保客户端和代理可以跟踪消息及其相应的确认消息。 主题列表:UNSUBSCRIBE消息中的主题列表可以包含一个或多个客户端想要取消订阅的主题。无需指定 QoS 级别,因为无论最初订阅的主题是什么,代理都会取消订阅该主题。 什么是 MQTT Unsubback? 收到 UNSUBSCRIBE 消息后,代理会发送UNSUBACK确认消息以确认删除客户端的订阅。该消息包括 UNSUBSCRIBE 消息的数据包标识符,并用作代理已成功从客户端的订阅列表中删除主题的确认。 MQTT UNSUBACK 数据包示例 数据包标识符:UNSUBACK消息中的数据包标识符与相应的UNSUBSCRIBE消息中的数据包标识符相同。这确保客户端可以识别确认消息并将其与原始取消订阅消息相关联。 返回代码:UNSUBACK 消息包含已取消订阅的每个主题/QoS 对的返回代码列表。返回代码 0 表示删除成功,而返回代码 17 表示由于主题无效或格式错误而导致删除不成功。还可以为不同的错误场景指定其他返回码。 MQTT UNSUBACK 的工作原理 在收到来自代理的 UNSUBACK 消息后,客户端可以认为 UNSUBSCRIBE 消息中的订阅已被删除。 这些详细信息可让您全面了解客户端如何取消订阅主题以及代理如何分别通过 UNSUBSCRIBE 和 UNSUBACK 消息确认删除这些订阅。 结论 MQTT 提供了一种灵活且与数据无关的方法来在客户端和代理之间发布消息。通过使用主题来过滤消息,客户可以快速轻松地订阅他们感兴趣的内容。每条消息的有效负载都可以定制,以满足每个客户端的特定需求,并且 MQTT 对各种数据类型的支持使其成为适用于许多用例的多功能解决方案。此外,了解 PUBLISH 消息的属性(例如 QoS 级别和保留标志)可以帮助客户端和代理确保消息高效可靠地传递。 --- ### 241. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 MQTT协议的概述 MQTT(Message Queuing Telemetry Transport)是一个轻量级的消息协议,广泛用于物联网(IoT)中,特别适用于带宽有限、延迟高、不可靠的网络环境。它基于发布/订阅模型,使得多个设备能够通过共享主题交换消息。 保留消息的定义 在MQTT中,保留消息是一种独特的消息类型。当一个消息被标记为保留时,MQTT代理(Broker)会将这个消息存储下来,并确保它被发送给未来订阅相应主题的客户端。这种机制保证了新的订阅者可以接收到他们订阅主题的最新状态,即便该状态是在他们订阅之前发布的。 2. 保留消息的工作原理 如何发布保留消息 为了发布一个保留消息,客户端在发送MQTT Publish命令时,需要将“Retain”标志设置为真(true)。这个动作指示MQTT代理保留这个消息,并把它分发给未来订阅对应主题的所有客户端。 MQTT代理如何处理保留消息 一旦MQTT代理接收到一个保留消息,它会存储这个消息,并用它来响应后续对该主题的新订阅请求。这意味着即使发布者离线,订阅者也能获取最近的状态更新。 保留消息与普通消息的区别 普通MQTT消息只被发送给当前订阅该主题的客户端,并且一旦送达,就不再保留。相比之下,保留消息会被MQTT代理存储,直到一个新的消息被发布到同一个主题并且被标记为保留。这使得保留消息成为一种持久的状态更新工具。 3. 保留消息的使用场景 为什么需要保留消息 保留消息的主要作用是确保新的订阅者可以立即获取到最新的消息。在物联网应用中,设备可能不定期上线并发布状态更新,保留消息确保新设备或服务在订阅后能立即获取到最近的状态,而不是等待下一个更新。 典型应用案例 智能家居系统:在智能家居系统中,例如温度或照明控制器的最后状态可以作为保留消息发布,以便新设备或应用程序在连接时能立即知晓当前状态。 遥测数据:在遥测场景中,如环境监测系统,保留消息可用于立即向新的监控节点提供最新的传感器读数。 配置更新:在分布式系统中,配置信息可以通过保留消息发布,确保所有新接入的系统组件都获得当前的配置。 4. 保留消息的优点和限制 保留消息的优势 即时信息获取:新订阅者可以立刻获取到关键信息,而不需要等待下一次更新。 网络效率:减少了频繁的状态查询或轮询,从而降低网络流量和负载。 持久性:状态信息持久化,即使在发布者离线时也能提供给新订阅者。 使用保留消息时需要考虑的问题 数据时效性:保留的消息可能不是实时的,依赖于最后一次发布的时间。 安全性和隐私:保留消息可能涉及敏感信息,需要考虑加密和访问控制。 资源使用:保留大量消息可能占用额外的存储和内存资源。 5. 实现细节 如何在不同的MQTT客户端实现保留消息 保留消息的实现在不同的MQTT客户端库中可能略有不同。通常,发布保留消息只需在发布时设置相应的标志。例如,在使用MQTT的流行库如 Paho MQTT 时,可以通过设置retain=True来实现。 实际示例和代码演示 以Paho MQTT客户端为例,发布保留消息的代码示例可能如下: import paho.mqtt.client as mqtt client = mqtt.Client() client.connect("mqtt.example.com", 1883, 60) client.publish("home/livingroom/temperature", "23°C", qos=1, retain=True) client.disconnect() 在这个示例中,客户端连接到MQTT代理,发布一个温度值到指定主题,并设置消息为保留。 6. 最佳实践和注意事项 如何有效利用保留消息 目标明确:仅对需要立即可用给新订阅者的关键信息使用保留消息。 更新及时:定期更新保留消息以确保其反映最新状态。 资源管理:考虑保留消息数量和大小,避免过度占用代理资源。 常见的错误和如何避免 忽略清理:在主题不再需要时,应发布空消息以清除保留状态。 过度依赖:不应将保留消息作为唯一的状态同步手段,应结合其他机制。 安全风险:确保对保留消息实施适当的安全措施,防止未授权访问。 7. 结论 保留消息在MQTT协议中的重要性 保留消息是MQTT协议中的一个重要特性,它提供了一种有效的机制来确保新订阅者能够迅速接收到关键信息。这在物联网和其他实时数据处理应用中尤为重要。 未来的发展方向和潜在改进 随着物联网的不断发展,对MQTT和其保留消息特性的需求将继续增长。期待未来会有更多关于保留消息管理、性能优化以及安全性增强的改进。 8. 高级应用与扩展 集成与自动化系统 保留消息可以与智能自动化系统紧密集成,如在建筑管理系统中自动调节环境参数。通过使用保留消息,系统能够即时获取到最新的设备状态,从而做出智能决策。 与其他协议和服务的融合 MQTT的保留消息可以与其他通信协议和云服务结合,如结合HTTP接口或集成至AWS IoT、Azure IoT等服务。这种融合扩展了MQTT的应用范围,提升了系统的互操作性和灵活性。 9. 性能考虑和优化 处理大量保留消息 在处理大量保留消息时,需要考虑MQTT代理的性能和存储能力。优化策略可能包括使用更高效的存储机制、负载均衡等。 保留消息与实时性 虽然保留消息为新订阅者提供了便利,但在需要高度实时性的应用中,应谨慎使用。可能需要结合其他实时通讯机制来补充保留消息的潜在延迟。 10. 安全性和合规性 数据加密和访问控制 对于传输敏感或关键数据的保留消息,应采取加密措施。同时,确保适当的访问控制,防止未授权访问保畈消息。 遵守数据保护法规 在使用保留消息时,特别是涉及个人数据时,必须遵守相应的数据保护和隐私法规,如欧盟的GDPR。 11. 未来展望 技术发展趋势 随着物联网技术的进步和普及,MQTT及其保留消息特性可能会更加智能化,例如通过AI来优化消息处理和分发。 潜在的新应用领域 保留消息的概念可能被扩展到新的应用领域,如智能交通系统、远程医疗等,为这些领域提供更高效和灵活的数据交换机制。 结束语 在这篇文章中,我们全面探讨了MQTT中的保留消息特性,包括它的工作原理、应用场景、实现细节、最佳实践以及面临的挑战。通过对这一特性的深入理解,我们可以更好地利用MQTT来设计和实现高效、可靠的物联网应用。随着技术的发展,MQTT和保留消息的应用范围和能力也将不断扩展和增强。 --- ### 242. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 在当今迅速发展的物联网(IoT)领域,确保数据通讯的可靠性和持续性是极其重要的。其中,MQ Telemetry Transport(MQTT)协议作为一种轻量级的消息传递协议,在物联网通信中扮演着关键角色。MQTT以其高效、低带宽占用和易于实现的特点,在远程监控、智能设备及其他许多实时通信应用中得到了广泛应用。在这个背景下,理解MQTT协议的一个关键特性——遗嘱(Will)和最后遗嘱(Last Will and Testament,简称LWT)机制,对于构建可靠和健壮的物联网系统至关重要。本文旨在深入探讨MQTT中的遗嘱机制,解析其工作原理及在现代物联网解决方案中的应用。 第一部分:MQTT协议基础 MQTT协议概述 MQTT,全称为消息队列遥测传输协议,是一种基于发布/订阅模式的轻量级通信协议。它允许设备在网络带宽有限、延迟较高、不稳定或资源受限的环境中进行有效通信。MQTT的设计简洁、易于实现,使其成为物联网通信的理想选择。 MQTT的工作原理 MQTT协议基于客户端-服务器模型。其中,客户端发布消息到某个主题,而服务器(也称为消息代理)负责接收这些消息并转发给订阅了对应主题的其他客户端。这种模式使得数据发送者和接收者之间解耦,提高了通信的灵活性和扩展性。 MQTT的关键特性和优势 轻量级协议:设计简单,适用于带宽和资源受限的环境。 低功耗:适合于电池供电的设备,延长设备的使用寿命。 高可靠性:提供多种服务质量等级,确保消息的可靠传输。 安全性:支持SSL/TLS加密,保障数据传输安全。 第二部分:MQTT遗嘱和最后遗嘱的定义 遗嘱消息(Will Message)的定义 遗嘱消息是MQTT协议中的一项特性,允许客户端在建立连接时指定一个消息,该消息将在客户端意外断开连接时由代理服务器发布。这种机制确保在发生网络故障或客户端崩溃时,系统中的其他部分能够得到通知。 最后遗嘱(Last Will and Testament, LWT)的定义 最后遗嘱是遗嘱消息的正式称呼,它是在MQTT连接建立阶段由客户端设置的。客户端定义了遗嘱消息的内容、目的主题以及服务质量等级。如果客户端没有按照预期的方式断开连接(例如发送DISCONNECT消息),代理服务器将发布这个遗嘱消息。 遗嘱和最后遗嘱在MQTT中的作用和重要性 故障检测:允许系统监测和响应客户端断开,特别是在故障情况下。 状态通知:确保在客户端意外断开时,系统中的其他客户端能够得到及时的状态更新。 增强健壮性:在物联网环境中,设备可能因多种原因断开连接,遗嘱机制增加了系统的健壮性,确保其他组件能够适当响应。 应急处理:在关键应用中,遗嘱消息可以触发应急流程或警报,从而快速响应可能的设备故障或网络问题。 通过这两部分内容的阐述,读者可以对MQTT协议及其关键特性有一个基本的理解,同时明白遗嘱和最后遗嘱在MQTT中的重要性和应用。这为进一步深入到遗嘱机制的具体工作原理和实际应用场景打下了良好的基础。 第三部分:MQTT遗嘱的工作机制 遗嘱消息的设置和触发条件 设置遗嘱消息:在建立MQTT连接时,客户端可以指定遗嘱消息的内容、目标主题和服务质量(QoS)等级。这个消息被代理服务器存储,直到触发条件满足。 触发条件:遗嘱消息将在客户端未能发送正常的断开连接(DISCONNECT)指令时被代理服务器发布。这可能是因为网络故障、客户端崩溃或其他意外中断。 最后遗嘱的工作流程 连接阶段:客户端在建立连接请求(CONNECT)消息中指定遗嘱消息。 存储遗嘱:MQTT代理服务器在确认连接后,存储遗嘱消息。 非正常断开:如果客户端连接异常中断,代理服务器将发布遗嘱消息到指定的主题。 正常断开:如果客户端通过DISCONNECT消息正常断开连接,遗嘱消息将被代理服务器丢弃,不会发布。 遗嘱消息与常规MQTT消息的区别 生命周期:遗嘱消息只有在异常断开时才会被发布,而常规消息是在正常的通信过程中交换。 用途:遗嘱消息主要用于异常监测和通知,而常规消息用于正常的数据交换和通信。 设置时间点:遗嘱消息在连接建立时设置,而常规消息可以在任何时间点发送。 第四部分:实际应用场景 遗嘱和最后遗嘱在物联网应用中的实例 智能家居:设备异常断开可以触发自动化脚本,如关闭设备或发送警告消息。 工业监控:传感器或控制器断开连接时,遗嘱消息可以通知中央监控系统进行故障诊断或启动备用系统。 车辆跟踪:在GPS跟踪设备失去连接时,遗嘱消息可用于触发位置丢失的警告。 处理设备断开连接的策略 预防性维护:利用遗嘱消息监控设备状态,进行预防性维护和故障预测。 快速响应:在关键应用中,遗嘱消息可以被用来触发快速响应机制,以减轻故障的影响。 提高系统的健壮性和可靠性 容错机制:遗嘱消息提供了一种自然的容错机制,有助于提高整个系统的健壮性和可靠性。 异常检测与响应:通过遗嘱消息的实时异常检测,系统能够及时响应并采取适当措施。 第五部分:技术实现和挑战 如何在MQTT客户端设置遗嘱消息 初始化设置:在建立MQTT连接时,通过连接请求(CONNECT)消息设置遗嘱消息的参数,包括遗嘱主题、消息内容、QoS等级和保留标志。 编程考虑:讨论不同编程环境(如Java, Python, C++)中如何使用常用的MQTT库来设置遗嘱消息。 最佳实践:提供有效设置遗嘱消息的策略和技巧,以保证其在必要时能被正确发布。 处理遗嘱消息的服务器端逻辑 遗嘱消息的存储与管理:解析MQTT代理服务器如何处理和存储遗嘱消息。 发布遗嘱消息:讨论在检测到客户端异常断开连接时,代理服务器如何发布遗嘱消息。 安全与权限:探讨在处理遗嘱消息时应考虑的安全性和权限问题,确保仅在适当的情况下发布遗嘱消息。 应对遗嘱机制的技术挑战和限制 遗嘱消息的可靠性:讨论如何确保遗嘱消息在网络不稳定或代理服务器负载高时能被可靠发布。 性能影响:分析遗嘱消息机制对MQTT代理服务器性能的影响,以及如何优化。 设计挑战:探讨在设计使用遗嘱消息的系统时可能遇到的挑战,如避免错误触发遗嘱消息。 第六部分:结论 遗嘱机制对于保障MQTT协议可靠性的重要性 关键角色:强调遗嘱消息在确保MQTT通信可靠性和系统健壮性方面的关键作用。 系统稳定性的提升:讨论遗嘱机制如何帮助维持系统的稳定性,特别是在面对网络不稳定和设备故障的情况下。 未来展望和潜在的改进方向 技术发展:展望未来技术的发展可能如何影响遗嘱消息的实现和应用。 改进机制:讨论可能的改进方向,如增强遗嘱消息的灵活性和配置选项。 --- ### 243. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 在当今日益增长的物联网(IoT)应用中,消息队列遥测传输(MQTT)协议因其高效性和可靠性而成为了数据通信的首选。MQTT是一种基于发布/订阅模式的轻量级消息协议,被广泛应用于从智能家居到工业自动化的各种场景。在这些应用中,确保消息准确无误地从发布者传达到订阅者变得至关重要。这里,MQTT协议中的一个核心概念——服务质量(Quality of Service,简称QoS)——发挥着关键作用。QoS等级决定了消息传递的保证级别,是设计任何基于MQTT的系统时的一个关键考量点。 MQTT服务质量(QoS)基础 服务质量(QoS)是衡量消息传递可靠性的标准。在MQTT协议中,QoS用于定义消息传递的保证级别。根据QoS等级的不同,MQTT协议可以确保消息按照不同的标准进行传输,从而适应不同的网络环境和应用需求。 QoS在MQTT中尤为重要,因为它直接影响到消息的传输可靠性和系统的整体性能。一个合适的QoS等级可以在保证消息可靠传递的同时,优化网络带宽的使用和系统资源的分配。MQTT定义了三个QoS等级:0、1和2,每个等级都有其特定的用途和应用场景。 在接下来的章节中,我们将逐一深入探讨这三个QoS等级的工作原理、优势、局限性以及它们在实际应用中的最佳使用场景。 QoS等级0:最多一次传输 QoS等级0,被称为“最多一次”传输,是MQTT协议中最基本的服务质量等级。在这个级别上,消息从发布者发送到订阅者时,不进行额外的确认和重传机制。这意味着消息可能会丢失,但在网络条件良好的情况下可以快速传输。 工作机制 当使用QoS 0时,消息被发送一次,不论它是否到达订阅者。 没有消息到达确认或重传机制,因此减少了通信开销。 优点与局限性 优点:QoS 0的主要优点是低延迟和低开销,使其成为网络带宽受限或对实时性要求高的应用的理想选择。 局限性:最大的局限是消息可靠性无法得到保证。在网络不稳定的环境中,消息可能会丢失。 应用场景 QoS 0适合于那些对数据传输速度要求高而对数据丢失容忍度较高的场景,如实时环境监测或快速数据采集。 QoS等级1:至少一次传输 QoS等级1,被称为“至少一次”传输,确保消息至少被送达一次。这种级别提供了比QoS 0更高的消息可靠性,适用于需要确保消息送达但可以容忍消息重复的场景。 工作机制 在QoS 1中,消息至少发送一次,直到接收方发送回一个确认响应。 如果发布者没有收到确认,它可能会再次发送消息,这可能导致消息重复。 优点与局限性 优点:QoS 1提供了比QoS 0更高的消息送达保证,适用于需要可靠消息传输的应用。 局限性:可能出现消息重复的情况,增加了消息处理的复杂性。 应用场景 QoS 1适合于那些需要确保消息送达但可以接受偶尔重复的场景,如智能家居控制或设备状态更新。 QoS等级2:恰好一次传输 QoS等级2是MQTT协议中最高级别的服务质量,被称为“恰好一次”传输。这个级别保证了消息在不丢失和不重复的前提下被准确送达,适用于对消息准确性要求极高的场景。 工作机制 QoS 2通过一个复杂的四步握手过程来确保消息的唯一性和可靠性。这包括发布者和订阅者之间的多次信息交换,确保每条消息只被接收一次。 这个过程避免了消息的丢失和重复,但相应地增加了通信的开销。 优点与局限性 优点:QoS 2提供了最高级别的消息可靠性,适合于对数据准确性有严格要求的应用。 局限性:较高的通信开销和处理延迟使得它不适用于需要快速响应或网络带宽有限的场景。 应用场景 QoS 2适合于需要严格消息准确性和可靠性的场景,如财务交易、关键任务控制系统等。 QoS等级选择的最佳实践 选择合适的QoS等级对于MQTT应用的成功至关重要。以下是一些最佳实践建议,帮助决定在特定场景下应使用哪个QoS等级。 评估应用需求 考虑应用的特性:是否需要高速数据传输、消息的可靠性有多重要,以及对消息重复的容忍度。 分析网络环境:带宽限制、连接的稳定性等。 权衡优势与限制 在选择QoS等级时,需要在消息可靠性、系统性能和资源消耗之间找到平衡点。 例如,对于不需要严格消息可靠性的实时监控应用,QoS 0或1可能更合适;而对于需要确保数据完整性的关键应用,则应考虑使用QoS 2。 持续优化 持续监测和评估MQTT系统的性能,根据实际运行情况调整QoS设置。 保持对MQTT技术和网络环境变化的关注,以适应可能的新需求和挑战。 结论 在深入探讨了MQTT协议中的服务质量等级——QoS 0, 1, 和 2之后,我们可以看到每个等级都有其独特的特点和适用场景。选择合适的QoS等级对于确保MQTT应用的有效性和可靠性至关重要。 QoS 0,作为最基本的服务等级,提供了最快的传输速度,但不保证消息的可靠送达。它适用于对实时性要求高且可以容忍消息丢失的应用。 QoS 1保证了消息至少被送达一次,提供了一个平衡点,适用于需要确保消息送达但可以容忍偶尔重复的情况。 QoS 2提供了最高级别的消息传递保证,确保每条消息恰好被送达一次,适用于对消息准确性要求极高的应用。 在选择QoS等级时,重要的是要根据具体的应用需求、网络条件和系统资源进行综合考量。正确的QoS等级选择可以显著提升系统的整体性能和用户体验。随着物联网技术的持续发展,对MQTT及其服务质量等级的深入理解将继续成为设计高效、可靠通信系统的关键。 --- ### 244. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 在当今迅速发展的物联网(IoT)领域,数据通信的可靠性和效率变得至关重要。消息队列遥测传输(MQTT)作为一种轻量级的发布/订阅消息协议,广泛应用于IoT环境,尤其在需要低带宽、高延迟或不可靠网络的场景中表现卓越。在MQTT的众多特性中,会话管理机制扮演着关键角色。特别地,MQTT定义了两种类型的会话:持久会话(Persistent Session)和清理会话(Clean Session)。这两种会话方式在保证消息传递的可靠性和效率方面发挥着不同但同等重要的作用。 MQTT会话概述 MQTT会话是指客户端与服务器之间建立的网络连接和相关的会话状态。会话状态包括订阅信息、未确认的消息、以及其他必要的数据,这些信息对于实现消息的可靠传输至关重要。在MQTT协议中,会话的概念至关重要,因为它保证了即使在网络连接不稳定的情况下,消息也能被正确地传递和接收。 客户端在连接到MQTT代理(Broker)时,可以选择启用持久会话或清理会话。这个选择将直接影响MQTT代理如何处理客户端的连接断开和重连。持久会话允许客户端在断开连接后重新连接时恢复其会话状态,而清理会话则在每次连接断开时清除所有相关状态。这两种方法各有利弊,适用于不同的应用场景。 在接下来的章节中,我们将详细探讨持久会话和清理会话的工作原理、应用场景以及它们之间的关键差异。通过深入了解这两种会话类型,开发者和系统架构师可以更好地利用MQTT协议,为各种IoT应用提供可靠、高效的数据通信解决方案。 持久会话的工作原理 在MQTT协议中,持久会话是一种关键特性,它使得客户端能够在断线后重新连接时保持其订阅状态。当一个客户端以持久会话的方式连接到MQTT代理时,代理会存储所有关于这个会话的信息,包括客户端的订阅和未交付的消息。 会话持久化 持久会话的核心在于会话持久化机制。当客户端断开连接时,其会话信息不会被清除。这意味着MQTT代理保留了客户端的所有订阅信息以及那些按照服务质量(QoS)1或2发送但未确认接收的消息。 服务质量(QoS)的作用 在持久会话中,服务质量级别尤为重要。对于QoS 1的消息,MQTT代理会确保至少交付一次;对于QoS 2的消息,则确保仅交付一次。这种机制确保即使在网络不稳定的情况下,所有重要消息也都能可靠传输。 清理会话的工作原理 与持久会话不同,清理会话提供了一种无状态的连接方式。当客户端使用清理会话连接到MQTT代理时,一旦连接断开,所有相关的会话信息和订阅都会被清除。 会话无状态化 清理会话的主要特点是其无状态性。在客户端断开连接后,MQTT代理不保留任何有关该客户端的信息。这种方式适用于那些不需要保留消息或订阅状态的场景,如临时连接和短暂数据传输。 适用场景 清理会话适用于对实时数据传输需求较高的应用场景,如传感器数据的即时监测。在这些场景中,一旦连接断开,历史数据的价值可能迅速降低,因此不需要保留这些信息。 清理会话的局限性 虽然清理会话在某些应用场景中非常有用,但它也有其局限性。由于不保留任何会话信息,如果网络连接不稳定,客户端可能会丢失在断开期间发送的消息。这在需要持续监控或数据记录的应用中可能不是最佳选择。 持久会话与清理会话的对比 理解持久会话和清理会话之间的差异对于有效地使用MQTT协议至关重要。这两种会话类型各有优势和局限性,选择哪一种取决于特定应用的需求。 应用场景差异 持久会话最适用于那些需要稳定连接和数据完整性的长期运行应用,如远程监控系统。在这些应用中,即使在连接断开的情况下,也需要保证数据不丢失。 清理会话则适用于那些对实时数据处理要求高,但对历史数据不敏感的场景,如实时环境监测或临时数据传输。 性能考量 持久会话需要更多的服务器资源来维护会话状态,这可能在有大量客户端的系统中成为一个考虑因素。 清理会话由于其无状态特性,通常对服务器资源的消耗较小,适合于大规模部署,尤其是当客户端数量众多且连接频繁更换时。 可靠性与效率 持久会话提供了更高的消息可靠性,但可能会牺牲一定的网络效率,特别是在网络条件较差的环境中。 清理会话在保证较高的网络效率同时,可能无法保证在所有情况下消息的完整性和可靠性。 实际应用案例 为了更好地理解持久会话和清理会话在实际应用中的表现,以下是两个具体的应用案例: 持久会话应用案例:远程监控系统 在一个远程监控系统中,如工厂的设备监控,持久会话的使用至关重要。设备状态的实时监控需要持续、稳定的数据传输。使用持久会话,即使在网络断开或设备重启的情况下,一旦重新连接,设备可以立即恢复其之前的订阅状态,确保没有任何监控数据丢失。这对于维护系统的完整性和可靠性是必不可少的。 清理会话应用案例:智能家居系统 在一个智能家居系统中,例如控制灯光或温度的短期连接,清理会话更为适用。当用户通过智能手机控制家中的设备时,通常是一次性的操作,不需要保留长期的会话状态。清理会话在这种情况下可以提供更快的响应时间和更高的网络效率,因为一旦操作完成,不需要保留任何状态信息。 面临的挑战与最佳实践 在实施持久会话和清理会话时,开发者可能会遇到一些挑战,以下是一些最佳实践,可以帮助克服这些挑战: 持久会话的挑战 资源管理:由于持久会话需要在服务器上存储更多的信息,有效的资源管理变得至关重要。确保MQTT代理足够健壮,可以处理大量的持久会话。 数据同步:在客户端重新连接时,确保正确同步所有未确认的消息和订阅状态。 清理会话的挑战 消息可靠性:由于清理会话不保留任何状态,开发者需要确保在必要时采用其他机制来保证消息的可靠传输。 连接管理:在频繁的连接和断开中,合理管理网络资源和连接请求,以防止服务器过载。 最佳实践 场景分析:在选择持久会话或清理会话之前,彻底分析应用场景的需求。 负载测试:对MQTT代理进行负载测试,确保在高负荷情况下仍能稳定运行。 安全措施:无论使用哪种会话类型,都要实施适当的安全措施,包括加密通信和身份验证。 结论 在探索了MQTT的持久会话和清理会话的工作原理、应用场景和面临的挑战之后,我们可以看到,这两种会话类型为物联网通信提供了灵活而有效的解决方案。每种会话类型都有其独特的优势,适用于不同的应用需求。 持久会话通过保持客户端状态和消息,为那些需要高度可靠性和数据完整性的应用提供了坚实的基础。它适合于那些长期运行、需要持续监控或数据记录的场景,如工业自动化和远程监控系统。然而,这种可靠性是以牺牲一定的网络资源为代价的。 相比之下,清理会话以其轻量级和高效性在需要快速、短暂交互的应用中占据优势。它特别适合于那些对实时数据传输需求高,但对历史数据不敏感的场景,如智能家居控制系统。但这种效率是以牺牲长期状态和消息持久性为代价的。 选择持久会话还是清理会话取决于特定应用的需求。重要的是要根据应用的特定需求和环境来决定使用哪种类型。同时,无论选择哪种会话类型,都需要考虑到资源管理、数据同步和安全性等因素,以确保系统的高效和安全运行。 总体而言,MQTT的这两种会话类型提供了在不同物联网应用场景中灵活调整的能力,使得设计者和开发者能够根据具体需求制定最适合的通信策略。随着物联网技术的不断发展和普及,对这些通信机制的深入理解将成为设计高效、可靠系统的关键。 --- ═══════════════════════════════════════════ ## Node-RED ═══════════════════════════════════════════ ### 245. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 该节点是作为 ST-One 项目的一部分创建的。 安装 您可以直接从 Node-RED 界面中的 “管理面板” 菜单安装此节点。 或者,在 Node-RED 用户目录中运行以下命令 - 通常在 Linux 上是 ~/.node-red 或在 Windows 上是 %HOMEPATH%\.nodered npm install node-red-contrib-s7 需要 NodeJS 版本 10 或更高版本以及 Node-RED 版本 1.0 或更高版本。 用法 每个与 PLC 的连接都由 S7 端点配置节点表示。您可以配置 PLC 的地址、可用变量及其地址以及读取变量的循环时间。 S7 In 节点使变量的值在流中以三种不同的模式可用: 单个变量:可以从配置的变量中选择单个变量,并且每个周期发送一条消息,或者如果检查了 diff 则仅当它发生变化时发送消息。msg.payload 包含变量的值,msg.topic 具有变量的名称。 所有变量,每条消息一个:与单变量模式类似,但适用于配置的所有变量。如果选中 diff,则每次任何变量更改时都会发送一条消息。如果未选中 diff,则在每个周期中为每个变量发送一条消息。必须注意此模式下每秒的消息数。 所有变量:在此模式下,msg.payload 包含一个包含所有配置变量及其值的对象。如果选中 diff,则当至少一个变量更改其值时,将发送一条消息。 变量寻址 S7 Endpoint 上配置的变量及其地址遵循的方案与 Step 7 或 TIA Portal 上使用的方案略有不同。以下是一些可以指导您处理变量的示例: 地址相当于 Step7JS 数据类型描述DB5,X0.1DB5.DBX0.1布尔值DB 5 字节 0 的位 1DB23,B1 或 DB23,BYTE1DB23.DBB1数字DB 23 的字节 1 (0-255)DB100,C2 或 DB100,CHAR2DB100.DBB2字符串DB 100 的字节 2 作为字符DB42,I3 或 DB42,INT3DB42.DBW3数字DB 42 的字节 3 处有符号 16 位数字DB57,WORD4DB57.DBW4数字DB 57 字节 4 处的无符号 16 位数字DB13,DI5 或 DB13,DINT5DB13.DBD5数字DB 13 的字节 5 处有符号 32 位数字DB19,DW6 或 DB19,DWORD6DB19.DBD6数字DB 19 的字节 6 处的无符号 32 位数字DB21,R7 或 DB21,REAL7DB21.DBD7数字DB 21 的字节 7 处的浮点 32 位数字DB2,S7.10*-字符串从 DB 2 的字节 7 开始的长度为 10 的字符串I1.0 或 E1.0I1.0 或 E1.0布尔值输入区域字节 1 的位 0Q2.1 或 A2.1Q2.1 或 A2.1布尔值输出区域字节 2 的位 1M3.2M3.2布尔值内存区域字节 3 的位 2IB4 或 EB4IB4 或 EB4数字输入区域的字节 4 (0 -255)QB5 或 AB5QB5 或 AB5数字输出区域的字节 5 (0 -255)MB6MB6数字内存区域的字节 6 (0 -255)IC7 或 EC7IB7 或 EB7字符串输入区域的字节 7 作为字符QC8 或 AC8QB8 或 AB8字符串输出区域的字节 8 作为字符MC9MB9字符串内存区域的字节 9 作为字符II10 或 EI10IW10 或 EW10数字输入区域字节 10 处的有符号 16 位数字QI12 或 AI12QW12 或 AW12数字输出区域字节 12 处的有符号 16 位数字MI14MW14数字内存区域字节 14 处的有符号 16 位数字IW16 或 EW16IW16 或 EW16数字输入区域字节 16 处的无符号 16 位数字QW18 或 AW18QW18 或 AW18数字输出区域字节 18 处的无符号 16 位数字MW20MW20数字内存区域字节 20 处的无符号 16 位数字IDI22 或 EDI22ID22 或 ED22数字输入区域字节 22 处的有符号 32 位数字QDI24 或 ADI24QD24 或 AD24数字输出区域字节 24 处的有符号 32 位数字MDI26MD26数字内存区域字节 26 处的有符号 32 位数字ID28 或 ED28ID28 或 ED28数字输入区域字节 28 处的无符号 32 位数字QD30 或 AD30QD30 或 AD30数字输出区域字节 30 处的无符号 32 位数字MD32MD32数字内存区域字节 32 处的无符号 32 位数字IR34 或 ER34IR34 或 ER34数字输入区域字节 34 处的浮点 32 位数字QR36 或 AR36QR36 或 AR36数字输出区域字节 36 处的浮点 32 位数字MR38MR38数字内存区域字节 38 处的浮点 32 位数字DB1,DT0-日期**DATE_AND_TIME 格式的时间戳DB1,DTZ10-日期**DATE_AND_TIME 格式的时间戳(UTC)DB2,DTL2-日期**DTL 格式的时间戳DB2,DTLZ12-日期**DTL 格式的时间戳(UTC 格式)DB57,RWORD4DB57.DBW4数字DB 57 字节 4 处的无符号 16 位数字,解释为 Little-EndianDB13,RDI5 或 DB13,RDINT5DB13.DBD5数字DB 13 的字节 5 处的有符号 32 位数字,解释为 Little-EndianMRW20MW20数字内存区域字节 20 处的无符号 16 位数字,解释为 Little-Endian 备注: 布尔值 表示是非类型的值,例如开或关。 数字 表示可以是整数或浮点数的值。 字符串 表示文本类型的值。 日期 表示时间戳类型的值。 *) 请注意,PLC 上的字符串在开头使用 2 个额外字节来表示字符串的大小/长度**) 请注意,javascriptDate始终以UTC 表示。请使用其他节点(例如node-red-contrib-moment)来正确处理类型转换 关于 S7-1200/1500 的注意事项 这些较新的 PLC 提供 S7 协议的 “扩展” 版本,而我们只有 “基本” 版本。 因此,需要对 PLC 进行一些额外的配置步骤: 对于我们想要访问的数据库,必须禁用 “优化块访问”。 在 CPU 属性的 “保护” 部分中,启用 “允许使用 PUT/GET 访问” 复选框。 标志注意事项! 最新的标志!8.FS4(可能还有 0BA8)逻辑模块无需再将模式设置为 TSAP,而是使用默认的机架/插槽值 0/2 即可正常工作。 下表显示无需在控制器程序中进行额外设置即可访问的存储区域: 标志块标志 VM 范围示例 Node-RED 地址描述I1024 - 1031DB1,BYTE1024 或 DB1,X1024.5 或 DB1,WORD1024读取输入端子 1...8 或 6 或 1...16AI1032 - 1063DB1,WORD1032读取模拟输入端子 1。始终为字大小。Q1064 - 1071DB1,BYTE1064 或 DB1,X1064.5 或 DB1,WORD1064读取输出端子 1...8 或 6 或 1...16AQ1072 - 1103DB1,WORD1072读取模拟输出端子 1。始终为字大小。M1104 - 1117DB1,BYTE1104 或 DB1,X1104.5 或 DB1,WORD1104读取位标志 M1...M8 或 M6 或 M1...16AM1118 - 1245DB1,WORD1118读取模拟标志 1。始终为字大小。NI1246 - 1061DB1,BYTE1246 或 DB1,X1246.5 或 DB1,WORD1246读取网络输入 1...8 或 6 或 1...16NAI1262 - 1389DB1,WORD1262读取模拟网络输入 1。始终为字大小。NQ1390 - 1405DB1,BYTE1390 或 DB1,X1390.5 或 DB1,WORD1390读取网络输出 1...8 或 6 或 1...16NAQ1406 - 1469DB1,WORD1406读取网络输出 1。始终为字大小。 这个表格描述了在 Siemens Logo! 控制器中可访问的不同存储区域,并提供了如何在 Node-RED 中使用这些区域的实际示例。每个区域都有特定的范围和功能,例如读取输入端子、模拟输入或输出端子等。 另一方面,Logo 内存区域 VM 0-849 从控制器外部是可变的,但需要将它们映射到 Logo 程序中。如果没有映射,写入这些地址的数据将不会影响程序的执行。上述范围内使用的VM地址可以使用“网络”功能块在Logo程序中读取/写入(在功能块设置中使用“本地变量存储器(VM)”选项将VM映射到功能堵塞)。 一些寻址示例: 标志虚拟机示例 Node-RED 地址描述0DB1,BYTE0读/写访问1DB1,X1.3读/写访问 注意:使用布尔值2..3DB1,WORD2读/写访问4..7DB1,DWORD4读/写访问 这个表格描述了在 Siemens Logo! 控制器中可变的虚拟机存储区域,以及如何在 Node-RED 中访问这些区域。每个区域都提供了读写访问权限,不同的地址范围表示不同的数据类型和大小。例如,BYTE、WORD、DWORD 分别表示不同大小的数据单位。 --- ### 246. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网 (IoT) 在当今世界无所不在,已经渗透到多个主导领域,从智慧健康医疗服务到智慧城市、零售行业、农业以及许多其他领域。这个技术的普及为我们的生活带来了前所未有的便利和效率。在这篇文章中,我们将探讨物联网在不同领域中的主导地位以及一些用于处理 IoT 和边缘场景的编程平台软件。 智慧健康医疗服务 物联网在医疗领域的应用是关键的,它为智能救护车、医院管理和智能药控等提供了支持。通过连接医疗设备和患者,医疗专业人员可以实时监测患者的健康状况,迅速采取行动。这可以帮助挽救生命,提高医疗服务的质量。 智慧城市 在智慧城市领域,物联网的应用范围广泛,包括智能交通控制、智能收费站、污染监测、水质管理、自动驾驶汽车、无人机、执法、节能等。这些技术的结合使城市更加智能、可持续,提高了居民的生活质量。 个人应用 在个人生活中,物联网也有着显著的影响,例如智能健康设备、防盗系统以及家电控制。人们可以通过智能手机或其他设备监控他们的健康状况,保护他们的家庭,实现远程控制家电等功能。 零售行业 在零售行业,物联网的应用包括自动结账、物流监控和管理等。这些技术可以加速购物体验,提高库存管理效率,降低运营成本。 农业 农业领域也受益于物联网的应用,包括作物分析、动态配水、智能灌溉、农场监控、智能农业无人机和农业机器人。这些技术有助于提高农作物产量,减少资源浪费。 编程平台软件 为了处理 IoT、IoE、雾或边缘场景,存在许多编程平台软件。以下是一些常见的平台: Node-RED:Node-RED是一个基于流程的编程环境,适用于模拟 IoT 场景。它易于使用,支持多种硬件和协议,是物联网开发的理想工具。 Contiki:Contiki是一个适用于微控制器的开源操作系统,支持 IPv6、IPv4、原线程等,适用于低资源设备和游戏机。 FlowHub:FlowHub是一个基于流程的物联网编程平台,提供直观的可视化编程工具。 NoFloJS:NoFloJS是基于 JavaScript 的流程编程框架,用于物联网应用程序的开发。 Netron:Netron是一个动态可视化工具,用于可视化 IoT 场景的数据流程。 PyFlow:PyFlow是一个可视化脚本工具,可用于创建 IoT 场景中的逻辑和数据流程。 Node-RED 当谈到物联网(IoT)和边缘计算(Edge Computing)场景时,Node-RED是一个备受欢迎的工具,它为开发人员提供了一种直观且灵活的方式来构建、部署和管理物联网应用程序。下文将介绍Node-RED在这两个领域中的应用,以及它是如何帮助解决复杂的问题的。 Node-RED简介 Node-RED是一个开源的流程编排工具,最初由IBM开发,现在由开放社区维护。它的核心概念是使用可视化方式连接各种输入、处理和输出节点,以创建数据流程。这些节点以可重用的方式构建,开发人员可以自定义节点或从社区贡献的节点库中选择节点,以实现各种功能。Node-RED具有丰富的插件生态系统,支持多种硬件和协议,这使得它成为物联网和边缘计算场景的理想选择。 物联网场景中的Node-RED 1. 数据采集和传输 在物联网应用中,Node-RED可以用于收集传感器数据、设备状态和其他信息。通过使用节点,开发人员可以轻松地连接到各种传感器和设备,无论是通过MQTT、HTTP、WebSocket还是其他协议。这使得数据采集变得容易,并且可以自动化处理。 2. 数据处理和分析 一旦数据被采集,Node-RED可以用于处理和分析它。开发人员可以编排一系列节点,执行数据清洗、转换和计算操作。此外,Node-RED还支持可视化工具,如图表和仪表板,可用于实时监控和可视化数据。 3. 响应和控制 物联网应用程序通常需要对设备进行远程控制和响应。Node-RED可以用于创建决策逻辑,根据接收到的数据触发操作,例如发送命令到设备,或者触发警报和通知。这种反应性的能力对于监控和管理物联网设备至关重要。 边缘计算场景中的Node-RED 1. 本地数据处理 边缘计算是一种将计算能力移到数据源附近的策略。Node-RED可以轻松部署到边缘设备上,以进行本地数据处理。这样可以减少数据传输延迟,提高应用程序的响应速度,并减少云端计算的负载。 2. 远程监控和管理 在边缘设备上运行的Node-RED实例可以与远程服务器通信,以实现监控和管理。这使得远程团队可以实时监控设备状态、远程更新应用程序,以及远程执行故障排除和维护操作。 3. 边缘智能 Node-RED的可扩展性和灵活性使其成为在边缘设备上实现边缘智能的理想工具。开发人员可以构建复杂的决策逻辑和自动化任务,而无需互联网连接。这对于需要高度可用性和低延迟的应用程序非常重要,如工业自动化和自动驾驶车辆。 总结 Node-RED是一个功能强大且易于使用的工具,适用于物联网和边缘计算场景。它的可视化编排和丰富的节点库使开发人员能够快速构建、测试和部署应用程序。不仅如此,Node-RED还有一个强大的社区支持,提供了大量的资源和插件,帮助开发人员解决各种复杂的问题。 对于那些希望在物联网和边缘计算领域创造创新解决方案的开发人员来说,Node-RED是一个不可或缺的工具。无论是用于数据采集、处理、分析,还是用于远程监控和本地计算,Node-RED都能够大大简化开发过程,加速应用程序的上线,提高系统的可维护性和可扩展性。在不断发展的IoT和边缘计算领域,Node-RED为开发人员提供了一个强大的工具,助力他们创造出更加智能、高效和响应速度更快的应用程序。 --- ### 247. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 创建你的第一个节点 当一个流程部署后,节点会被创建。当流程运行时,节点会进行消息的发送和接收;当下一个流程被部署时,原先的节点则被删除。 每个节点由三部分组成: 一个JavaScript文件:定义了节点的功能。 一个html文件:定义了节点的属性、编辑界面和帮助文本。 一个package.json文件:用于将以上内容打包为npm模块。 创建一个简单的节点 下面的示例会教你如何创建一个能够将消息内容转为小写的节点。 首先,确保你的电脑上安装了Node.js的长期支持版本。本文写作时使用的版本是10.x。 在你想要写代码的文件夹中,创建以下三个文件: package.json lower-case.js lower-case.html package.json 这是用于描述Node.js模块内容的标准文件。 你可以运行npm init来生成这个文件,系统会询问你一些问题来帮你创建文件的初始内容。当系统提示你输入名字时,可以命名为node-red-contrib-example-lower-case。 生成后,你需要增加一个node-red的部分: { "name" : "node-red-contrib-example-lower-case", ... "node-red" : { "nodes": { "lower-case": "lower-case.js" } } } 这样就可以告诉Node-RED哪些文件是节点文件。 关于如何打包节点,包括发布节点前的命名和其他要求,你可以参考相关打包指南。 注意:这只是一个示例,请不要将次节点发布到npm上! lower-case.js module.exports = function(RED) { function LowerCaseNode(config) { RED.nodes.createNode(this,config); var node = this; node.on('input', function(msg) { msg.payload = msg.payload.toLowerCase(); node.send(msg); }); } RED.nodes.registerType("lower-case",LowerCaseNode); } 每个节点都被封装在一个Node.js模块中。这个模块会导出一个函数,这个函数在Node-RED启动并加载节点时会被调用,这个函数有一个RED参数,它使模块能够访问Node-RED的运行时API。 节点的定义是通过一个函数完成的,这个函数在每次创建节点的实例时都会被调用。这个函数会接收一个对象,这个对象包含了在流编辑器中为节点设置的特性。LowerCaseNode 这个函数首先调用了RED.nodes.createNode来初始化节点的基本功能。接着,特定于节点的代码就开始运行。 在这里,节点注册了一个监听input事件的监听器,这个监听器会在节点收到消息时被调用。监听器会将消息内容转为小写,然后调用send函数将消息发送到流中。 最后,节点使用名为“lower-case”的名称注册到了运行时。 如果节点依赖其他外部模块,那些模块必须在package.json文件的dependencies部分列出。 更多关于节点的运行时部分的信息,请查阅相关文档。 lower-case.html <script type="text/javascript"> RED.nodes.registerType('lower-case',{ category: 'function', color: '#a6bbcf', defaults: { name: {value:""} }, inputs: 1, outputs: 1, icon: "file.svg", label: function() { return this.name||"lower-case"; } }); </script> <script type="text/html" data-template-name="lower-case"> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> 名称</label> <input type="text" id="node-input-name" placeholder="名称"> </div> </script> <script type="text/html" data-help-name="lower-case"> <p>这是一个简单的节点,可以将消息内容转为小写。</p> </script> 节点的HTML文件主要包含三部分: 注册到编辑器的主要节点定义。 节点的编辑模板。 节点的帮助文本。 在这个示例中,节点有一个可以编辑的属性,叫做name。尽管这并不是必须的,但在同一个流程中使用多个相似的节点时,给每个节点命名可以帮助你区分它们。 关于节点编辑部分的更多信息,你可以查阅相关文档。 如何在Node-RED中测试你的节点 按照上面的步骤创建了基础节点模块后,你就可以在Node-RED运行时中安装并测试它了。 为了在本地测试这个节点模块,你可以使用npm install <文件夹路径>。这样你就可以在本地目录中开发节点,同时将它链接到你的Node-RED安装中。 在Node-RED的用户目录中(通常是~/.node-red)执行: npm install <你的节点模块的路径> 例如,如果你在Mac OS或Linux上的节点路径是~/dev/node-red-contrib-example-lower-case,你应该这样操作: cd ~/.node-red npm install ~/dev/node-red-contrib-example-lower-case 对于Windows用户: cd C:\Users\你的用户名\.node_red npm install C:\Users\你的用户名\Documents\GitHub\node-red-contrib-example-lower-case 这会在~/.node-red/node_modules中为你的节点模块创建一个链接,这样在启动Node-RED时,它就会加载这个节点。你只需重启Node-RED,就可以查看节点的变化了。同样,在Windows上使用npm 5.x或更高版本:~/.node-red/node_modules 单元测试 为了支持单元测试,你可以使用一个叫做 node-red-node-test-helper 的 npm 模块。这个测试助手基于 Node-RED 运行时,并使节点的测试变得更为简单。 借助这个框架,你可以设计测试流,并验证节点的属性和输出是否符合预期。例如,若想给 lower-case 节点添加单元测试,你可以在节点模块包里新建一个名为 test_spec.js 的文件。 test/lower-case_spec.js var helper = require("node-red-node-test-helper"); var lowerNode = require("../lower-case.js"); describe('lower-case Node', function () { afterEach(function () { helper.unload(); }); it('should be loaded', function (done) { var flow = [{ id: "n1", type: "lower-case", name: "test name" }]; helper.load(lowerNode, flow, function () { var n1 = helper.getNode("n1"); n1.should.have.property('name', 'test name'); done(); }); }); it('should make payload lower case', function (done) { var flow = [{ id: "n1", type: "lower-case", name: "test name",wires:[["n2"]] }, { id: "n2", type: "helper" }]; helper.load(lowerNode, flow, function () { var n2 = helper.getNode("n2"); var n1 = helper.getNode("n1"); n2.on("input", function (msg) { msg.should.have.property('payload', 'uppercase'); done(); }); n1.receive({ payload: "UpperCase" }); }); }); }); 这些测试旨在验证节点是否被正确加载,并且能否正确地将有效载荷转为小写。 两个测试都通过 helper.load 方法将节点加载进运行时。第一个测试核实运行时的节点是否具有预期的名字属性。第二个测试利用助手节点来验证节点输出的确为小写。 助手模块中还包含了许多来自 Node-RED 核心节点的测试样例。要了解更多关于助手模块的信息,你可以查阅相关的 README。 --- ### 248. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 请求方法路径描述GET/auth/login获取活动的身份验证方案POST/auth/token用证书交换访问令牌POST/auth/revoke撤销访问令牌GET/settings获取运行时设置GET/diagnostics获取运行时诊断GET/flows获取活动的流程配置GET/flows/state获取活动流的运行状态POST/flows设置活动的流程配置POST/flows/state设置活动流的运行状态POST/flow将流添加到活动配置GET/flow/:id获取单个流程配置PUT/flow/:id更新单个流程配置DELETE/flow/:id删除单个流程配置GET/nodes获取已安装的节点列表POST/nodes安装新的节点模块GET/nodes/:module获取节点模块的信息PUT/nodes/:module启用/禁用节点模块DELETE/nodes/:module删除节点模块GET/nodes/:module/:set获取节点模块集信息PUT/nodes/:module/:set启用/禁用节点集 --- ### 249. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 错误处理 所有API方法使用标准的HTTP响应代码表示成功或失败。 状态码原因200成功 - 结果在响应内容中204成功 - 但无其他内容400错误请求 - 参见以下响应格式401未授权 - 请查看“身份验证”404未找到 - 没有找到资源409版本不匹配 - 请查看 POST /flows500服务器错误 - 服务器上出现了问题 错误响应 对于响应代码400,响应内容将是一个包含以下字段的JSON对象: 我为您提供了这个JSON对象的表格形式: 字段描述code错误代码message错误描述 您可以将这个格式复制到任何支持Markdown的编辑器中查看效果。 示例: { "code": "module_already_loaded", "message": "模块已加载" } 错误代码列表 代码描述unexpected_error发生意外错误invalid_request请求中包含无效参数settings_unavailable存储系统不支持更改设置module_already_loaded请求的模块已加载type_in_use请求试图删除/禁用当前正在使用的节点类型invalid_api_version请求在头部指定了无效的API版本Node-RED-API-Version --- ### 250. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 传统上,流配置被表示为节点对象的平面数组。 从Node-RED 0.13版本开始,新增了一个API,允许单独维护流程(也称为选项卡)。这些API使用了更丰富的流程配置格式。我们计划在未来更新主流配置以使用这种更丰富的格式,但现在两种格式需要同时存在。 流配置变化 传统上,流配置表示为节点对象的平面数组。从Node-RED 0.13开始,增加了一个api,允许单独维护流(又称为标签)。这些API使用更丰富的流配置格式。我们计划在未来更新主流配置以使用这种丰富格式,但目前这两种格式必须共存。 节点 节点代表流中单个节点的配置。 { "id": "123", "type": "inject", "x": 0, "y": 0, "z": "456", "wires": ["example_wire"] } 字段描述id节点的唯一IDtype节点的类型x,y在绘制流时节点的x/y坐标z节点所属的流或子流wires节点输出连接的线路*由特定类型定义的其他字段 如果节点是配置节点,则它不得具有x, y或wires属性。 子流 子流节点代表子流的配置。 { "id": "6115be82.9eea4", "type": "subflow", "name": "Subflow 1", "info": "", "in": [{"x": 60,"y": 40,"wires": [{"id": "1830cc4e.e7cf34"}]}], "out": [{"x": 320,"y": 40,"wires": [{"id": "1830cc4e.e7cf34","port": 0}]}], "configs": [], "nodes": [] } 完整流配置 完整流配置代表运行时中活动的所有流。它表示为节点对象的平面数组。这是由API使用的主流格式,并由编辑器导入/导出。 [ {"id": "1234", "type": "inject"}, {"id": "5678", "type": "debug"} ] 从0.15.0开始,如果头部设置为Node-RED-API-Version: v2,API支持新格式。 { "rev": "abc-123", "flows": [ {"id": "1234", "type": "inject"}, {"id": "5678", "type": "debug"} ] } 单个流配置 单流配置代表编辑器中作为标签显示的内容。 { "id": "1234", "label": "Sheet1", "nodes": [], "configs": [], "subflows": [] } 字段描述id流的唯一IDlabel流的标签nodes流中的节点数组configs流中的配置数组subflows表示流配置时使用的子流数组 节点模块 节点模块代表由npm包提供的节点集合。 { "name": "node-module-name", "version": "0.0.6", "nodes": [] } 字段说明name模块的名称 - 根据其package.json文件定义version模块的版本 - 根据其package.json文件定义nodes由此模块提供的节点集对象数组 节点集 节点集代表节点模块中单个文件提供的类型集合。 { "id": "node-module-name/node-set-name", "name": "node-set-name", "types": [], "enabled": true, "module": "node-module-name", "version": "0.0.6" } 字段描述id此集的ID - 格式为模块/名称name集的名称 - 定义在模块的package.json中types此集提供的节点类型的字符串数组enabled此集是否当前已启用module提供该集的模块名称。如果其值为node-red,表示节点是从复制的文件中加载的,而不是npm模块。 --- ### 251. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 认证 Node-RED的管理API是通过您的settings.js文件中的adminAuth属性进行安全验证的。安全性部分描述了该属性应如何配置。 如果该属性未设置,任何有网络访问权限的人都可以访问Node-RED的管理API。 步骤 0 - 检查认证方案对/auth/login进行HTTP GET请求将返回当前的认证方案。 curl 示例: curl http://localhost:1880/auth/login 在API的当前版本中,有两种可能的结果: 无活跃认证 {} 所有API请求都可以在不提供任何进一步认证信息的情况下进行。 基于凭证的认证 { "type": "credentials", "prompts": [ { "id": "username", "type": "text", "label": "用户名" }, { "id": "password", "type": "password", "label": "密码" } ] } API由访问令牌保护。 步骤 1 - 获取访问令牌对/auth/token进行HTTP POST请求,用于将用户凭证换取访问令牌。 必须提供以下参数: client_id - 标识客户端。目前,必须是node-red-admin或node-red-editor。 grant_type - 必须是password。 scope - 请求的权限的空格分隔列表。目前,必须是*或read。 username - 用于认证的用户名。 password - 用于认证的密码。 curl 示例: curl http://localhost:1880/auth/token --data 'client_id=node-red-admin&grant_type=password&scope=*&username=admin&password=password' 如果成功,响应将包含访问令牌: { "access_token": "A_SECRET_TOKEN", "expires_in": 604800, "token_type": "Bearer" } 步骤 2 - 使用访问令牌所有后续的API调用都应在头部提供此令牌Authorization。 curl 示例: curl -H "Authorization: Bearer A_SECRET_TOKEN" http://localhost:1880/settings 撤销令牌当不再需要令牌时,为了撤销它,应该在一个HTTP POST中发送到/auth/revoke。 curl 示例: curl --data 'token=A_SECRET_TOKEN' -H "Authorization: Bearer A_SECRET_TOKEN" http://localhost:1880/auth/revoke --- ### 252. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 前提条件要在本地安装 Node-RED,您需要一个支持的 Node.js 版本。 使用 npm 安装要安装 Node-RED,您可以使用随 node.js 附带的命令:npm sudo npm install -g --unsafe-perm node-red 如果您使用的是 Windows,请不要在命令前加上 sudo。 该命令将与其依赖关系一起将 Node-RED 安装为全局模块。 您可以通过命令输出的末尾查看是否成功,例如: + node-red@1.1.0 added 332 packages from 341 contributors in 18.494s found 0 vulnerabilities 使用 Docker 安装以最简单的形式在 Docker 中运行,只需执行: docker run -it -p 1880:1880 --name mynodered nodered/node-red 更多详细信息,请查看我们的 Docker 指南。 使用 Snap 安装如果您的操作系统支持 Snap,您可以使用以下命令安装 Node-RED: sudo snap install node-red 作为 Snap 包安装时,它将在一个安全容器中运行,该容器不能访问您可能需要使用的一些额外功能,例如: 主系统存储的访问权限。只能读/写本地主目录。 gcc - 如果需要编译您想要安装的节点的任何二进制组件 git - 如果您想使用项目功能 直接访问 gpio 硬件 您的流程希望使用 Exec 节点运行的任何外部命令。 如果您需要访问系统硬件或添加需要编译的节点,我们建议使用 Node-RED 的完整安装,而不使用 snap。 运行一旦作为全局模块安装,您可以使用以下命令在终端中启动 Node-RED。您可以使用 Ctrl-C 或关闭终端窗口来停止 Node-RED。 $ node-red Welcome to Node-RED =================== 30 Jun 23:43:39 - [info] Node-RED version: v1.3.5 30 Jun 23:43:39 - [info] Node.js version: v14.7.2 30 Jun 23:43:39 - [info] Darwin 19.6.0 x64 LE 30 Jun 23:43:39 - [info] Loading palette nodes 30 Jun 23:43:44 - [warn] rpi-gpio : Raspberry Pi specific node set inactive 30 Jun 23:43:44 - [info] Settings file : /Users/nol/.node-red/settings.js 30 Jun 23:43:44 - [info] HTTP Static : /Users/nol/node-red/web 30 Jun 23:43:44 - [info] Context store : 'default' [module=localfilesystem] 30 Jun 23:43:44 - [info] User directory : /Users/nol/.node-red 30 Jun 23:43:44 - [warn] Projects disabled : set editorTheme.projects.enabled=true to enable 30 Jun 23:43:44 - [info] Creating new flows file : flows_noltop.json 30 Jun 23:43:44 - [info] Starting flows 30 Jun 23:43:44 - [info] Started flows 30 Jun 23:43:44 - [info] Server now running at http://127.0.0.1:1880/red/ 然后,您可以通过指向 http://localhost:1880 在浏览器中访问 Node-RED 编辑器。 日志输出为您提供了各种信息,如 Node-RED 和 Node.js 的版本,加载调色板节点时遇到的任何错误,您的设置文件和用户目录的位置,以及正在使用的流文件的名称。 Node-RED 默认使用 flows_<主机名>.json 作为流文件。您可以通过提供流文件名作为命令参数来更改此设置。 flows_<hostname>.jsonnode-red 命令行使用Node-RED 可以使用以下命令启动,此命令可以接受多种参数: node-red [-v] [-?] [--settings settings.js] [--userDir DIR] [--port PORT] [--title TITLE] [--safe] [flows.json|projectName] [-D X=Y|@file] 此处的选项有: -p, --port PORT:设置运行时监听的 TCP 端口。默认为:1880。 --safe:启动 Node-RED,但不启动流程。这允许您在编辑器中打开流程并进行更改,而不运行流程。部署更改后,将启动流程。 -s, --settings FILE:设置要使用的设置文件。默认位置在 userDir 的 settings.js 中。 --title TITLE:设置进程窗口标题。 -u, --userDir DIR:设置要使用的用户目录。默认为:~/.node-red。 -v:启用详细输出。 -D X=Y|@file:覆盖单个设置。 -?,--help:显示命令行使用帮助并退出。 flows.json|projectName:如果未启用项目功能,这将设置您要使用的流文件。如果启用了项目功能,这将确定应启动哪个项目。 Node-RED 用作默认流文件。如果计算机 您正在运行可能会更改其主机名,那么您应该确保提供 静态文件名;作为命令行参数或使用选项 在您的设置文件中。flows_<hostname>.jsonflowsFile 覆盖个别设置从 Node-RED 1.1.0 开始 您可以使用 -D 或 --define 选项在命令行上覆盖个别设置。 例如,要更改日志级别,您可以使用:-D logging.console.level=trace 您还可以将自定义设置提供为文件:-D @./custom-settings.txt文件应包含要覆盖的设置列表: logging.console.level=trace logging.console.audit=true 向底层的 Node.js 进程传递参数有时需要向底层的 Node.js 进程传递参数。例如,在运行于像 Raspberry Pi 或 BeagleBone Black 这样内存受限的设备时。 为此,您必须使用启动脚本 node-red-pi 而不是 node-red。注意:Windows上没有这个脚本。 另外,如果您使用 nodered.js 命令运行 Node-RED,您必须在指定 nodered.js 和要传递给 Node-RED 的参数之前,为 node 进程提供参数。 以下两个命令显示了这两种方法: node-red-pi --max-old-space-size=128 --userDir /home/user/node-red-data/ node --max-old-space-size=128 red.js --userDir /home/user/node-red-data/ 升级 Node-RED如果您使用 Pi 脚本安装了 Node-RED,您可以重新运行它进行升级。脚本可以在此处找到。如果您已经将 Node-RED 安装为全局 npm 包,您可以使用以下命令升级到最新版本:sudo npm install -g --unsafe-perm node-red如果您使用的是 Windows,不要在命令前加上 sudo。 --- ### 253. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 仅建议希望使用开发版本代码的用户或希望为项目做出贡献的开发者从源代码构建和运行。 前提条件 要从源代码运行 Node-RED,您需要: 一个受支持的 Node.js 版本。 git 客户端 全局安装的 npm 模块:grunt-cli sudo npm install -g grunt-cli 克隆代码并安装依赖 您可以直接从 GitHub 克隆源代码仓库: git clone https://github.com/node-red/node-red.git 这将在当前目录中创建一个包含项目完整源代码的目录。以下指令假定您位于该目录中。 接着,您应选择您要构建的分支。 master:默认分支。这是维护分支,包含当前稳定发布的代码,以及为下一个维护版本预先应用的所有错误修复。 dev:开发分支。所有新的开发都在这里进行。 如果您想使用 dev 分支,应运行以下命令: git checkout dev 在选择了分支后,您应使用以下命令安装所有依赖: npm install 构建 Node-RED 在启动 Node-RED 之前,您必须先构建它。这可以使用以下命令完成: grunt build 运行 Node-RED 然后,您可以使用以下命令运行 Node-RED: npm start 如果您想传递任何命令行参数,您必须使用以下语法: npm start -- <args> 其中 -- 参数告诉 npm 将其后的任何参数传递给它运行的命令。 自动重启 如果您正在编辑源代码,您必须重新启动 Node-RED 以加载更改。为此,提供了一个特殊的 grunt 任务来自动执行: grunt dev 该命令将构建并运行 Node-RED,然后监视文件系统以查看源代码的任何更改。如果检测到对编辑器代码的更改,它将重新构建编辑器组件,然后您可以重新加载编辑器以查看更改。如果检测到对运行时或节点的更改,它将重新启动 Node-RED 以加载这些更改。 除了指定不同的流文件之外,此模式不允许您传递参数给 Node-RED 命令: grunt dev --flowFile=my-flow-file.json --- ### 254. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 本指南假设你对Docker和Docker命令行有基本的了解。它描述了Node-RED在Docker下运行的多种方式,并支持多种架构(amd64, arm32v6, arm32v7, arm64v8 和 s390x)。 注意: 从Node-RED 1.0开始,Docker Hub上的仓库名称已被更改为 nodered/node-red。 快速开始 要在Docker中运行Node-RED,请执行以下命令: docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red 这个命令的解释: docker run:运行容器。 -it:连接终端会话,以便我们能够查看输出。 -p 1880:1880:将本地端口1880连接到容器内部暴露的1880端口。 -v node_red_data:/data:将名为node_red_data的Docker卷挂载到容器的/data目录,以持久化流程的更改。 --name mynodered:为这个容器指定一个友好的名称。 nodered/node-red:基于当前的Node-RED v1.2.0镜像。 运行此命令后,你会看到一个终端窗口显示Node-RED的运行实例。 你可以通过浏览器访问 http://{host-ip}:1880 来打开Node-RED的界面。 命名容器为“mynodered”可以更方便地管理它。此命令只能运行一个实例,但我们可以一步步来。 如果你觉得没问题,你可以使用 Ctrl-pCtrl-q 组合键来分离终端,而容器将在后台继续运行。 要重新连接到终端,请运行: docker attach mynodered 如果需要重新启动容器(例如,重启后): docker start mynodered 需要停止时执行: docker stop mynodered 镜像版本 Node-RED的镜像基于官方的Node.js Alpine Linux镜像,以保持尽可能小的体积。但这意味着一些用于原生模块编译的标准依赖项被移除了。若你需要添加原生依赖,可以查看Node-RED Docker项目的README.md中有关docker-custom的部分。 具体的镜像、标签和Manifest信息,请查阅GitHub项目的README。 例如,如果你在Raspberry PI 3B(架构为arm32v7)上运行,只需执行以下命令来拉取并运行容器: docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red:latest Docker会根据运行的主机环境自动选择匹配的镜像标签。 但要注意,Docker的某些架构检测存在缺陷,例如Raspberry Pi Zero或1的arm32v6。对于这些设备,你需要明确指定镜像标签: docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red:1.2.0-10-arm32v6 管理用户数据 运行Node-RED后,我们需要确保添加的节点或流程数据不会在容器被销毁时丢失。这可以通过将容器内的数据目录挂载到容器外部的卷来实现。 要将Node-RED的用户目录保存到容器外部的主机目录,例如/home/pi/.node-red,可以使用: docker run -it -p 1880:1880 -v /home/pi/.node-red:/data --name mynodered nodered/node-red 请注意,从0.20升级到1.0版本的用户需要确保已有的/data目录拥有正确的权限,这通常是1000:1000。可以使用以下命令来调整: sudo chown -R 1000:1000 /path/to/your/node-red/data 更多关于权限的详细信息,请参考官方文档。 使用命名数据卷 Docker还支持使用命名数据卷在容器外部存储持久化或共享数据。若要创建一个新的命名数据卷来保存用户数据,并使用此卷运行新的容器,可以这样操作: # 创建一个新的命名数据卷 $ docker volume create --name node_red_data # 显示当前所有的数据卷 $ docker volume ls # 输出 DRIVER VOLUME NAME local node_red_data # 使用该数据卷运行新的容器 $ docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red 若要备份从挂载的数据卷中的数据,您可以在容器运行时这样操作: # 从运行的容器中备份数据到指定的目录 $ docker cp mynodered:/data /your/backup/directory 使用Node-RED创建并部署了一些示例流程后,您可以销毁容器并启动一个新的实例,而不会丢失用户数据: $ docker stop mynodered $ docker rm mynodered $ docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red 更新 由于 /data 现在是在容器外部保存的,所以更新基础容器镜像变得非常简单: $ docker pull nodered/node-red $ docker stop mynodered $ docker rm mynodered $ docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red Docker Stack / Docker Compose 以下是一个Docker Compose文件示例,您可以使用docker stack或docker-compose来运行它。更多关于Docker stack和Docker compose的信息,请参考官方Docker文档。 # Node-RED Stack 或 Compose # 使用docker stack部署 # docker stack deploy node-red --compose-file docker-compose-node-red.yml # 使用docker-compose启动 # docker-compose -f docker-compose-node-red.yml -p myNoderedProject up version: "3.7" services: node-red: image: nodered/node-red:latest environment: - TZ=Europe/Amsterdam ports: - "1880:1880" networks: - node-red-net volumes: - node-red-data:/data volumes: node-red-data: networks: node-red-net: 以上的compose文件: 创建了一个node-red服务 使用最新的node-red镜像 设置时区为Europe/Amsterdam 将容器的1880端口映射到主机的1880端口 创建了一个node-red-net网络,并将容器连接到这个网络 将容器内部的目录持久化到Docker卷node-red-data 有时,您可能希望使用Dockerfile将本地资源复制到Node-RED Docker镜像中(例如,如果您希望整个项目保存在git仓库中)。为此,您需要使本地目录如下所示: Dockerfile README.md package.json # 在你自己的package.json中添加流程所需的任何额外节点。 flows.json # Node-RED保存您的流程的正常位置 flows_cred.json # 您的流程可能需要的凭证 settings.js # 您的设置文件 注意:如果您希望将/data卷外部挂载,此方法不适用。如果您需要使用外部卷进行持久化存储,请将您的设置和流程文件复制到该卷。 以下的Dockerfile基于基本的Node-RED Docker镜像,但还将您自己的文件放到该镜像中: FROM nodered/node-red # 将package.json复制到工作目录,以便npm为Node-RED构建所有已添加的节点模块 COPY package.json . RUN npm install --unsafe-perm --no-update-notifier --no-fund --only=production # 将您的Node-RED项目文件复制到适当的位置 # 注意:只有在您后面不将/data作为外部卷挂载时,这样做才有效。 # 如果需要使用外部卷进行持久化,则将设置和流文件复制到该卷。 COPY settings.js /data/settings.js COPY flows_cred.json /data/flows_cred.json COPY flows.json /data/flows.json # 您应该通过您的package.json文件添加额外的节点,但您也可以在此处添加它们: # WORKDIR /usr/src/node-red # RUN npm install node-red-node-smooth 注意:package.json文件必须在脚本部分中包含一个启动选项。例如,默认容器如下: "scripts": { "start": "node $NODE_OPTIONS node_modules/node-red/red.js $FLOWS", ... } Dockerfile顺序和构建速度 虽然不是必需的,但最好早点执行COPY package... npm install...步骤,因为尽管在Node-RED中工作时flows.json经常发生变化,但package.json只有在项目模块变化时才会发生变化。由于更改package.json时需要执行的步骤有时可能会消耗很长时间,因此最好在Dockerfile中尽早执行那些时间消耗较大的、通常不会改变的步骤,这样那些构建镜像可以被重用,从而使后续的整体构建更快。 凭证、密钥和环境变量 当然 ,您永远不应该在任何地方硬编码凭证。例如,如果您需要在Node-RED项目中使用密钥,则上述Dockerfile允许您在settings.js中这样做: module.exports = { credentialSecret: process.env.NODE_RED_CREDENTIAL_SECRET }; 然后,当您在Docker中运行它时,您可以添加一个环境变量到运行命令中: docker run -e "NODE_RED_CREDENTIAL_SECRET=您的密钥内容" 构建和运行 正常地构建这个Dockerfile: docker build -t 您的镜像名:您的标签 . 为了进行本地开发,并确保任何更改都可以立即被应用,只需从您正在工作的本地目录中进入项目目录,然后执行: docker run --rm -e "NODE_RED_CREDENTIAL_SECRET=您的密钥内容" -p 1880:1880 -v `pwd`:/data --name 您的容器名 您的镜像名 启动 可以将环境变量传递到容器中,以配置Node-RED的运行时。 使用环境参数(FLOWS)设置流配置文件,默认为‘flows.json’。您可以使用以下命令行标志在运行时更改它: docker run -it -p 1880:1880 -v node_red_data:/data -e FLOWS=my_flows.json nodered/node-red 注意:如果您设置了FLOWS="",那么可以通过settings.js文件中的flowFile属性来设置流文件。 还有其他一些有用的环境变量,例如: -e NODE_RED_ENABLE_SAFE_MODE=false # 设为true则在安全模式(不运行)下启动Node-RED -e NODE_RED_ENABLE_PROJECTS=false # 设为true则启动支持项目功能的Node-RED 您可以使用环境参数(NODE_OPTIONS)将Node.js运行时参数传递到容器。例如,要固定Node.js垃圾回收器使用的堆大小,您可以使用以下命令: docker run -it -p 1880:1880 -v node_red_data:/data -e NODE_OPTIONS="--max_old_space_size=128" nodered/node-red 无头运行 要在后台(即无头)运行,只需在大多数先前的命令中将-it替换为-d,例如: docker run -d -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red 容器Shell 一旦以无头方式运行,您可以使用以下命令重新进入容器: $ docker exec -it mynodered /bin/bash bash-4.4$ 这将在容器内部给出一个命令行,您可以运行您想要的npm安装命令,例如: bash-4.4$ npm install node-red-dashboard bash-4.4$ exit $ docker stop mynodered $ docker start mynodered 刷新浏览器页面应该会在调色板中显示新添加的节点。 多个实例 运行: docker run -d -p 1880 nodered/node-red 将在本地创建一个运行实例。注意:我们没有指定一个名称。 此容器将有一个ID号并在一个随机端口上运行…要找出哪个端口,请运行docker ps。 $ docker ps 您现在可以指向在返回的tcp端口上的主机机器,所以在上面的示例中浏览http://{主机ip}:32768。 连接容器 您可以使用Docker用户定义的桥接器在docker运行时“内部”连接容器。 使用桥接器之前,需要创建它。以下命令将创建一个名为iot的新桥: docker network create iot 然后,需要使用--network命令行选项将所有需要通信的容器添加到同一个桥上: docker run -itd --network iot --name mybroker eclipse-mosquitto mosquitto -c /mosquitto-no-auth.conf 然后运行nodered docker,也添加到同一个桥上: docker run -itd -p 1880:1880 --network iot --name mynodered nodered/node-red 在同一个用户定义的桥上的容器可以利用桥提供的内置名称解析,并使用--name选项指定的容器名称作为目标主机名。 在上面的示例中,可以使用主机名mybroker从Node-RED应用程序访问代理。 然后,一个简单的流,如下所示,显示了连接到代理的mqtt节点: [{"id":"c51cbf73.d90738","type":"mqtt in","z":"3fa278ec.8cbaf","name":"","topic":"test","broker":"5673f1d5.dd5f1","x":290,"y":240,"wires":[["7781c73.639b8b8"]]},{"id":"7008d6ef.b6ee38","type":"mqtt out","z":"3fa278ec.8cbaf","name":"","topic":"test","qos":"","retain":"","broker":"5673f1d5.dd5f1","x":517,"y":131,"wires":[]},{"id":"ef5b970c.7c864","type":"inject","z":"3fa278ec.8cbaf","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"","payloadType":"date","x":290,"y":153,"wires":[["7008d6ef.b6ee38"]]},{"id":"7781c73.639b8b8","type":"debug","z":"3fa278ec.8cbaf","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":505,"y":257,"wires":[]},{"id":"5673f1d5.dd5f1","type":"mqtt-broker","z":"","name":"","broker":"mybroker","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"15","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","closeTopic":"","closeRetain":"false","closePayload":"","willTopic":"","willQos":"0","willRetain":"false","willPayload":""}] 这样,内部代理就不会暴露在docker主机之外了 - 当然,如果您希望您的计算机之外的其他系统能够使用代理,您可以在代理运行命令中添加-p 1883:1883。 树莓派 - 原生GPIO支持 | v1.0 - BREAKING: 树莓派的原生GPIO支持已被弃用 | | — | 替代原生GPIO的是node-red-node-pi-gpiod。 原生GPIO支持的缺点是: 您的Docker容器需要部署在您希望控制gpio的同一个Docker节点/主机上。 访问您的Docker节点/主机的/dev/mem。 privileged=true对于docker stack命令不受支持。 node-red-node-pi-gpiod修复了所有这些缺点。它可以从单个Node-RED容器与多个树莓派的gpio进行交互,并且多个容器可以在同一个Pi上访问不同的gpio。 快速迁移到node-red-node-pi-gpiod 通过Node-RED调色板安装node-red-node-pi-gpiod。 在主机Pi上安装并运行。有关详细的安装说明,请参阅README。 使用pi gpiod节点替换所有原生gpio节点。 将节点配置为连接到pi gpiod。通常,主机机器将有一个IP 172.17.0.1端口8888,但并不总是这样。您可以使用以下命令来检查: docker exec -it mynodered ip route show default | awk '/default/ {print $3}' 注意:有一个名为gpiod的贡献项目,如果需要,可以在其自己的容器中运行gpiod,而不是在主机上。 串行端口 - Dialout - 添加组如果您需要访问主机的串行端口,可能需要将容器添加到对应的组中。这可以通过在启动命令中添加相应的参数来实现。例如,dialout --group-add dialout: docker run -it -p 1880:1880 -v node_red_data:/data --group-add dialout --name mynodered nodered/node-red 常见问题和建议以下是用户报告的常见问题及可能的解决方案列表: 用户权限错误查看wiki以获取关于权限的详细信息。 如果您在打开文件或访问主机设备时看到“权限被拒绝”的错误,请尝试以root用户身份运行容器。 docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered -u node-red:dialout nodered/node-red 参考资料: https://github.com/node-red/node-red-docker/issues/15 https://github.com/node-red/node-red-docker/issues/8 访问主机设备如果您希望从容器内部访问主机的某个设备,例如串行端口,请使用以下命令行标志来传递访问权限。 docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered --device=/dev/ttyACM0 nodered/node-red 参考资料:https://github.com/node-red/node-red/issues/15 设置时区如果您想要修改默认时区,请使用TZ环境变量并提供相应的时区。 docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered -e TZ=America/New_York nodered/node-red 或者在docker-compose文件中: node-red: environment: - TZ=America/New_York --- ### 255. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 前提条件:如果您使用的是Raspberry Pi OS,Bullseye是当前支持的版本。 安装与更新Node-RED:我们为您提供了一个脚本,可以帮助您在树莓派上安装Node.js、npm和Node-RED。当有新版本发布时,您也可以使用此脚本来更新Node-RED。 想要下载并执行这个脚本,您可以运行以下命令。如果您想事先查看脚本的具体内容,您可以在Github上进行查阅。 bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered) 您还可以给脚本添加一些参数,只需在上面的命令后面加上 --help 就可以查看所有可用参数了。 此脚本适用于所有基于Debian的操作系统,包括Ubuntu和Diet-Pi。在执行脚本之前,为确保npm可以正常工作,您可能需要先执行 sudo apt install build-essential git curl。 执行该脚本后,系统会: 移除当前的Node-RED版本(如果已安装的话)。 检查系统中是否已安装Node.js,如果已安装并且版本低于v14,脚本会提示您决定是否升级。如果系统中未检测到Node.js,脚本会自动安装Node.js 16 LTS版本。 安装最新版本的Node-RED。 可以选择性地为您安装一些特定于树莓派的有用节点。 设置Node-RED作为服务运行,并提供了一套简单的命令,以便您能够管理这个服务。 需要注意的是,Node-RED已经被包括在树莓派操作系统的软件库中,因此您也可以直接通过 apt-get install nodered 进行安装,但这种方法不包括npm。尽管直接使用软件库中的包安装很简单,但我们仍建议您使用上面的脚本来安装,以确保功能的完整性和稳定性。 本地运行:跟在其他系统上运行Node-RED一样,您可以在树莓派的终端中直接使用 node-red 命令。想要停止程序,只需按下 Ctrl-C 或关闭终端即可。 考虑到树莓派的内存限制,建议您使用下面的命令来启动Node-RED,这可以帮助系统更有效地管理内存。 node-red-pi --max-old-space-size=256 作为服务运行:通过上面的脚本安装Node-RED后,它会默认设置为一个服务,在后台运行。您还可以设置它开机自启。 为了方便管理,以下命令可以帮助您控制Node-RED服务: node-red-start:启动服务并显示日志。 node-red-stop:停止服务。 node-red-restart:重新启动服务。 node-red-log:查看服务日志。 在树莓派的桌面环境中,您还可以通过 菜单 -> 编程 -> Node-RED 来启动它。 开机自启:想要设置Node-RED在树莓派启动时自动运行,您可以使用以下命令: sudo systemctl enable nodered.service 如果不想让它开机自启,只需执行: sudo systemctl disable nodered.service 访问编辑器:当Node-RED运行起来后,您可以通过浏览器来访问其编辑器界面。在树莓派本机上,地址为:http://localhost:1880。 当然,我们更推荐您在PC或其他设备上,使用Chrome或Firefox浏览器来访问树莓派上运行的Node-RED。此时,访问地址为:http://<您的树莓派IP地址>:1880。不确定IP地址的话,可以在树莓派终端中运行 hostname -I 来查看。 --- ═══════════════════════════════════════════ ## Node-RED 创建节点 ═══════════════════════════════════════════ ### 256. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 创建你的第一个节点 当一个流程部署后,节点会被创建。当流程运行时,节点会进行消息的发送和接收;当下一个流程被部署时,原先的节点则被删除。 每个节点由三部分组成: 一个JavaScript文件:定义了节点的功能。 一个html文件:定义了节点的属性、编辑界面和帮助文本。 一个package.json文件:用于将以上内容打包为npm模块。 创建一个简单的节点 下面的示例会教你如何创建一个能够将消息内容转为小写的节点。 首先,确保你的电脑上安装了Node.js的长期支持版本。本文写作时使用的版本是10.x。 在你想要写代码的文件夹中,创建以下三个文件: package.json lower-case.js lower-case.html package.json 这是用于描述Node.js模块内容的标准文件。 你可以运行npm init来生成这个文件,系统会询问你一些问题来帮你创建文件的初始内容。当系统提示你输入名字时,可以命名为node-red-contrib-example-lower-case。 生成后,你需要增加一个node-red的部分: { "name" : "node-red-contrib-example-lower-case", ... "node-red" : { "nodes": { "lower-case": "lower-case.js" } } } 这样就可以告诉Node-RED哪些文件是节点文件。 关于如何打包节点,包括发布节点前的命名和其他要求,你可以参考相关打包指南。 注意:这只是一个示例,请不要将次节点发布到npm上! lower-case.js module.exports = function(RED) { function LowerCaseNode(config) { RED.nodes.createNode(this,config); var node = this; node.on('input', function(msg) { msg.payload = msg.payload.toLowerCase(); node.send(msg); }); } RED.nodes.registerType("lower-case",LowerCaseNode); } 每个节点都被封装在一个Node.js模块中。这个模块会导出一个函数,这个函数在Node-RED启动并加载节点时会被调用,这个函数有一个RED参数,它使模块能够访问Node-RED的运行时API。 节点的定义是通过一个函数完成的,这个函数在每次创建节点的实例时都会被调用。这个函数会接收一个对象,这个对象包含了在流编辑器中为节点设置的特性。LowerCaseNode 这个函数首先调用了RED.nodes.createNode来初始化节点的基本功能。接着,特定于节点的代码就开始运行。 在这里,节点注册了一个监听input事件的监听器,这个监听器会在节点收到消息时被调用。监听器会将消息内容转为小写,然后调用send函数将消息发送到流中。 最后,节点使用名为“lower-case”的名称注册到了运行时。 如果节点依赖其他外部模块,那些模块必须在package.json文件的dependencies部分列出。 更多关于节点的运行时部分的信息,请查阅相关文档。 lower-case.html <script type="text/javascript"> RED.nodes.registerType('lower-case',{ category: 'function', color: '#a6bbcf', defaults: { name: {value:""} }, inputs: 1, outputs: 1, icon: "file.svg", label: function() { return this.name||"lower-case"; } }); </script> <script type="text/html" data-template-name="lower-case"> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> 名称</label> <input type="text" id="node-input-name" placeholder="名称"> </div> </script> <script type="text/html" data-help-name="lower-case"> <p>这是一个简单的节点,可以将消息内容转为小写。</p> </script> 节点的HTML文件主要包含三部分: 注册到编辑器的主要节点定义。 节点的编辑模板。 节点的帮助文本。 在这个示例中,节点有一个可以编辑的属性,叫做name。尽管这并不是必须的,但在同一个流程中使用多个相似的节点时,给每个节点命名可以帮助你区分它们。 关于节点编辑部分的更多信息,你可以查阅相关文档。 如何在Node-RED中测试你的节点 按照上面的步骤创建了基础节点模块后,你就可以在Node-RED运行时中安装并测试它了。 为了在本地测试这个节点模块,你可以使用npm install <文件夹路径>。这样你就可以在本地目录中开发节点,同时将它链接到你的Node-RED安装中。 在Node-RED的用户目录中(通常是~/.node-red)执行: npm install <你的节点模块的路径> 例如,如果你在Mac OS或Linux上的节点路径是~/dev/node-red-contrib-example-lower-case,你应该这样操作: cd ~/.node-red npm install ~/dev/node-red-contrib-example-lower-case 对于Windows用户: cd C:\Users\你的用户名\.node_red npm install C:\Users\你的用户名\Documents\GitHub\node-red-contrib-example-lower-case 这会在~/.node-red/node_modules中为你的节点模块创建一个链接,这样在启动Node-RED时,它就会加载这个节点。你只需重启Node-RED,就可以查看节点的变化了。同样,在Windows上使用npm 5.x或更高版本:~/.node-red/node_modules 单元测试 为了支持单元测试,你可以使用一个叫做 node-red-node-test-helper 的 npm 模块。这个测试助手基于 Node-RED 运行时,并使节点的测试变得更为简单。 借助这个框架,你可以设计测试流,并验证节点的属性和输出是否符合预期。例如,若想给 lower-case 节点添加单元测试,你可以在节点模块包里新建一个名为 test_spec.js 的文件。 test/lower-case_spec.js var helper = require("node-red-node-test-helper"); var lowerNode = require("../lower-case.js"); describe('lower-case Node', function () { afterEach(function () { helper.unload(); }); it('should be loaded', function (done) { var flow = [{ id: "n1", type: "lower-case", name: "test name" }]; helper.load(lowerNode, flow, function () { var n1 = helper.getNode("n1"); n1.should.have.property('name', 'test name'); done(); }); }); it('should make payload lower case', function (done) { var flow = [{ id: "n1", type: "lower-case", name: "test name",wires:[["n2"]] }, { id: "n2", type: "helper" }]; helper.load(lowerNode, flow, function () { var n2 = helper.getNode("n2"); var n1 = helper.getNode("n1"); n2.on("input", function (msg) { msg.should.have.property('payload', 'uppercase'); done(); }); n1.receive({ payload: "UpperCase" }); }); }); }); 这些测试旨在验证节点是否被正确加载,并且能否正确地将有效载荷转为小写。 两个测试都通过 helper.load 方法将节点加载进运行时。第一个测试核实运行时的节点是否具有预期的名字属性。第二个测试利用助手节点来验证节点输出的确为小写。 助手模块中还包含了许多来自 Node-RED 核心节点的测试样例。要了解更多关于助手模块的信息,你可以查阅相关的 README。 --- ═══════════════════════════════════════════ ## Node-RED 安装部署 ═══════════════════════════════════════════ ### 257. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 前提条件要在本地安装 Node-RED,您需要一个支持的 Node.js 版本。 使用 npm 安装要安装 Node-RED,您可以使用随 node.js 附带的命令:npm sudo npm install -g --unsafe-perm node-red 如果您使用的是 Windows,请不要在命令前加上 sudo。 该命令将与其依赖关系一起将 Node-RED 安装为全局模块。 您可以通过命令输出的末尾查看是否成功,例如: + node-red@1.1.0 added 332 packages from 341 contributors in 18.494s found 0 vulnerabilities 使用 Docker 安装以最简单的形式在 Docker 中运行,只需执行: docker run -it -p 1880:1880 --name mynodered nodered/node-red 更多详细信息,请查看我们的 Docker 指南。 使用 Snap 安装如果您的操作系统支持 Snap,您可以使用以下命令安装 Node-RED: sudo snap install node-red 作为 Snap 包安装时,它将在一个安全容器中运行,该容器不能访问您可能需要使用的一些额外功能,例如: 主系统存储的访问权限。只能读/写本地主目录。 gcc - 如果需要编译您想要安装的节点的任何二进制组件 git - 如果您想使用项目功能 直接访问 gpio 硬件 您的流程希望使用 Exec 节点运行的任何外部命令。 如果您需要访问系统硬件或添加需要编译的节点,我们建议使用 Node-RED 的完整安装,而不使用 snap。 运行一旦作为全局模块安装,您可以使用以下命令在终端中启动 Node-RED。您可以使用 Ctrl-C 或关闭终端窗口来停止 Node-RED。 $ node-red Welcome to Node-RED =================== 30 Jun 23:43:39 - [info] Node-RED version: v1.3.5 30 Jun 23:43:39 - [info] Node.js version: v14.7.2 30 Jun 23:43:39 - [info] Darwin 19.6.0 x64 LE 30 Jun 23:43:39 - [info] Loading palette nodes 30 Jun 23:43:44 - [warn] rpi-gpio : Raspberry Pi specific node set inactive 30 Jun 23:43:44 - [info] Settings file : /Users/nol/.node-red/settings.js 30 Jun 23:43:44 - [info] HTTP Static : /Users/nol/node-red/web 30 Jun 23:43:44 - [info] Context store : 'default' [module=localfilesystem] 30 Jun 23:43:44 - [info] User directory : /Users/nol/.node-red 30 Jun 23:43:44 - [warn] Projects disabled : set editorTheme.projects.enabled=true to enable 30 Jun 23:43:44 - [info] Creating new flows file : flows_noltop.json 30 Jun 23:43:44 - [info] Starting flows 30 Jun 23:43:44 - [info] Started flows 30 Jun 23:43:44 - [info] Server now running at http://127.0.0.1:1880/red/ 然后,您可以通过指向 http://localhost:1880 在浏览器中访问 Node-RED 编辑器。 日志输出为您提供了各种信息,如 Node-RED 和 Node.js 的版本,加载调色板节点时遇到的任何错误,您的设置文件和用户目录的位置,以及正在使用的流文件的名称。 Node-RED 默认使用 flows_<主机名>.json 作为流文件。您可以通过提供流文件名作为命令参数来更改此设置。 flows_<hostname>.jsonnode-red 命令行使用Node-RED 可以使用以下命令启动,此命令可以接受多种参数: node-red [-v] [-?] [--settings settings.js] [--userDir DIR] [--port PORT] [--title TITLE] [--safe] [flows.json|projectName] [-D X=Y|@file] 此处的选项有: -p, --port PORT:设置运行时监听的 TCP 端口。默认为:1880。 --safe:启动 Node-RED,但不启动流程。这允许您在编辑器中打开流程并进行更改,而不运行流程。部署更改后,将启动流程。 -s, --settings FILE:设置要使用的设置文件。默认位置在 userDir 的 settings.js 中。 --title TITLE:设置进程窗口标题。 -u, --userDir DIR:设置要使用的用户目录。默认为:~/.node-red。 -v:启用详细输出。 -D X=Y|@file:覆盖单个设置。 -?,--help:显示命令行使用帮助并退出。 flows.json|projectName:如果未启用项目功能,这将设置您要使用的流文件。如果启用了项目功能,这将确定应启动哪个项目。 Node-RED 用作默认流文件。如果计算机 您正在运行可能会更改其主机名,那么您应该确保提供 静态文件名;作为命令行参数或使用选项 在您的设置文件中。flows_<hostname>.jsonflowsFile 覆盖个别设置从 Node-RED 1.1.0 开始 您可以使用 -D 或 --define 选项在命令行上覆盖个别设置。 例如,要更改日志级别,您可以使用:-D logging.console.level=trace 您还可以将自定义设置提供为文件:-D @./custom-settings.txt文件应包含要覆盖的设置列表: logging.console.level=trace logging.console.audit=true 向底层的 Node.js 进程传递参数有时需要向底层的 Node.js 进程传递参数。例如,在运行于像 Raspberry Pi 或 BeagleBone Black 这样内存受限的设备时。 为此,您必须使用启动脚本 node-red-pi 而不是 node-red。注意:Windows上没有这个脚本。 另外,如果您使用 nodered.js 命令运行 Node-RED,您必须在指定 nodered.js 和要传递给 Node-RED 的参数之前,为 node 进程提供参数。 以下两个命令显示了这两种方法: node-red-pi --max-old-space-size=128 --userDir /home/user/node-red-data/ node --max-old-space-size=128 red.js --userDir /home/user/node-red-data/ 升级 Node-RED如果您使用 Pi 脚本安装了 Node-RED,您可以重新运行它进行升级。脚本可以在此处找到。如果您已经将 Node-RED 安装为全局 npm 包,您可以使用以下命令升级到最新版本:sudo npm install -g --unsafe-perm node-red如果您使用的是 Windows,不要在命令前加上 sudo。 --- ### 258. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 仅建议希望使用开发版本代码的用户或希望为项目做出贡献的开发者从源代码构建和运行。 前提条件 要从源代码运行 Node-RED,您需要: 一个受支持的 Node.js 版本。 git 客户端 全局安装的 npm 模块:grunt-cli sudo npm install -g grunt-cli 克隆代码并安装依赖 您可以直接从 GitHub 克隆源代码仓库: git clone https://github.com/node-red/node-red.git 这将在当前目录中创建一个包含项目完整源代码的目录。以下指令假定您位于该目录中。 接着,您应选择您要构建的分支。 master:默认分支。这是维护分支,包含当前稳定发布的代码,以及为下一个维护版本预先应用的所有错误修复。 dev:开发分支。所有新的开发都在这里进行。 如果您想使用 dev 分支,应运行以下命令: git checkout dev 在选择了分支后,您应使用以下命令安装所有依赖: npm install 构建 Node-RED 在启动 Node-RED 之前,您必须先构建它。这可以使用以下命令完成: grunt build 运行 Node-RED 然后,您可以使用以下命令运行 Node-RED: npm start 如果您想传递任何命令行参数,您必须使用以下语法: npm start -- <args> 其中 -- 参数告诉 npm 将其后的任何参数传递给它运行的命令。 自动重启 如果您正在编辑源代码,您必须重新启动 Node-RED 以加载更改。为此,提供了一个特殊的 grunt 任务来自动执行: grunt dev 该命令将构建并运行 Node-RED,然后监视文件系统以查看源代码的任何更改。如果检测到对编辑器代码的更改,它将重新构建编辑器组件,然后您可以重新加载编辑器以查看更改。如果检测到对运行时或节点的更改,它将重新启动 Node-RED 以加载这些更改。 除了指定不同的流文件之外,此模式不允许您传递参数给 Node-RED 命令: grunt dev --flowFile=my-flow-file.json --- ### 259. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 本指南假设你对Docker和Docker命令行有基本的了解。它描述了Node-RED在Docker下运行的多种方式,并支持多种架构(amd64, arm32v6, arm32v7, arm64v8 和 s390x)。 注意: 从Node-RED 1.0开始,Docker Hub上的仓库名称已被更改为 nodered/node-red。 快速开始 要在Docker中运行Node-RED,请执行以下命令: docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red 这个命令的解释: docker run:运行容器。 -it:连接终端会话,以便我们能够查看输出。 -p 1880:1880:将本地端口1880连接到容器内部暴露的1880端口。 -v node_red_data:/data:将名为node_red_data的Docker卷挂载到容器的/data目录,以持久化流程的更改。 --name mynodered:为这个容器指定一个友好的名称。 nodered/node-red:基于当前的Node-RED v1.2.0镜像。 运行此命令后,你会看到一个终端窗口显示Node-RED的运行实例。 你可以通过浏览器访问 http://{host-ip}:1880 来打开Node-RED的界面。 命名容器为“mynodered”可以更方便地管理它。此命令只能运行一个实例,但我们可以一步步来。 如果你觉得没问题,你可以使用 Ctrl-pCtrl-q 组合键来分离终端,而容器将在后台继续运行。 要重新连接到终端,请运行: docker attach mynodered 如果需要重新启动容器(例如,重启后): docker start mynodered 需要停止时执行: docker stop mynodered 镜像版本 Node-RED的镜像基于官方的Node.js Alpine Linux镜像,以保持尽可能小的体积。但这意味着一些用于原生模块编译的标准依赖项被移除了。若你需要添加原生依赖,可以查看Node-RED Docker项目的README.md中有关docker-custom的部分。 具体的镜像、标签和Manifest信息,请查阅GitHub项目的README。 例如,如果你在Raspberry PI 3B(架构为arm32v7)上运行,只需执行以下命令来拉取并运行容器: docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red:latest Docker会根据运行的主机环境自动选择匹配的镜像标签。 但要注意,Docker的某些架构检测存在缺陷,例如Raspberry Pi Zero或1的arm32v6。对于这些设备,你需要明确指定镜像标签: docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red:1.2.0-10-arm32v6 管理用户数据 运行Node-RED后,我们需要确保添加的节点或流程数据不会在容器被销毁时丢失。这可以通过将容器内的数据目录挂载到容器外部的卷来实现。 要将Node-RED的用户目录保存到容器外部的主机目录,例如/home/pi/.node-red,可以使用: docker run -it -p 1880:1880 -v /home/pi/.node-red:/data --name mynodered nodered/node-red 请注意,从0.20升级到1.0版本的用户需要确保已有的/data目录拥有正确的权限,这通常是1000:1000。可以使用以下命令来调整: sudo chown -R 1000:1000 /path/to/your/node-red/data 更多关于权限的详细信息,请参考官方文档。 使用命名数据卷 Docker还支持使用命名数据卷在容器外部存储持久化或共享数据。若要创建一个新的命名数据卷来保存用户数据,并使用此卷运行新的容器,可以这样操作: # 创建一个新的命名数据卷 $ docker volume create --name node_red_data # 显示当前所有的数据卷 $ docker volume ls # 输出 DRIVER VOLUME NAME local node_red_data # 使用该数据卷运行新的容器 $ docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red 若要备份从挂载的数据卷中的数据,您可以在容器运行时这样操作: # 从运行的容器中备份数据到指定的目录 $ docker cp mynodered:/data /your/backup/directory 使用Node-RED创建并部署了一些示例流程后,您可以销毁容器并启动一个新的实例,而不会丢失用户数据: $ docker stop mynodered $ docker rm mynodered $ docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red 更新 由于 /data 现在是在容器外部保存的,所以更新基础容器镜像变得非常简单: $ docker pull nodered/node-red $ docker stop mynodered $ docker rm mynodered $ docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red Docker Stack / Docker Compose 以下是一个Docker Compose文件示例,您可以使用docker stack或docker-compose来运行它。更多关于Docker stack和Docker compose的信息,请参考官方Docker文档。 # Node-RED Stack 或 Compose # 使用docker stack部署 # docker stack deploy node-red --compose-file docker-compose-node-red.yml # 使用docker-compose启动 # docker-compose -f docker-compose-node-red.yml -p myNoderedProject up version: "3.7" services: node-red: image: nodered/node-red:latest environment: - TZ=Europe/Amsterdam ports: - "1880:1880" networks: - node-red-net volumes: - node-red-data:/data volumes: node-red-data: networks: node-red-net: 以上的compose文件: 创建了一个node-red服务 使用最新的node-red镜像 设置时区为Europe/Amsterdam 将容器的1880端口映射到主机的1880端口 创建了一个node-red-net网络,并将容器连接到这个网络 将容器内部的目录持久化到Docker卷node-red-data 有时,您可能希望使用Dockerfile将本地资源复制到Node-RED Docker镜像中(例如,如果您希望整个项目保存在git仓库中)。为此,您需要使本地目录如下所示: Dockerfile README.md package.json # 在你自己的package.json中添加流程所需的任何额外节点。 flows.json # Node-RED保存您的流程的正常位置 flows_cred.json # 您的流程可能需要的凭证 settings.js # 您的设置文件 注意:如果您希望将/data卷外部挂载,此方法不适用。如果您需要使用外部卷进行持久化存储,请将您的设置和流程文件复制到该卷。 以下的Dockerfile基于基本的Node-RED Docker镜像,但还将您自己的文件放到该镜像中: FROM nodered/node-red # 将package.json复制到工作目录,以便npm为Node-RED构建所有已添加的节点模块 COPY package.json . RUN npm install --unsafe-perm --no-update-notifier --no-fund --only=production # 将您的Node-RED项目文件复制到适当的位置 # 注意:只有在您后面不将/data作为外部卷挂载时,这样做才有效。 # 如果需要使用外部卷进行持久化,则将设置和流文件复制到该卷。 COPY settings.js /data/settings.js COPY flows_cred.json /data/flows_cred.json COPY flows.json /data/flows.json # 您应该通过您的package.json文件添加额外的节点,但您也可以在此处添加它们: # WORKDIR /usr/src/node-red # RUN npm install node-red-node-smooth 注意:package.json文件必须在脚本部分中包含一个启动选项。例如,默认容器如下: "scripts": { "start": "node $NODE_OPTIONS node_modules/node-red/red.js $FLOWS", ... } Dockerfile顺序和构建速度 虽然不是必需的,但最好早点执行COPY package... npm install...步骤,因为尽管在Node-RED中工作时flows.json经常发生变化,但package.json只有在项目模块变化时才会发生变化。由于更改package.json时需要执行的步骤有时可能会消耗很长时间,因此最好在Dockerfile中尽早执行那些时间消耗较大的、通常不会改变的步骤,这样那些构建镜像可以被重用,从而使后续的整体构建更快。 凭证、密钥和环境变量 当然 ,您永远不应该在任何地方硬编码凭证。例如,如果您需要在Node-RED项目中使用密钥,则上述Dockerfile允许您在settings.js中这样做: module.exports = { credentialSecret: process.env.NODE_RED_CREDENTIAL_SECRET }; 然后,当您在Docker中运行它时,您可以添加一个环境变量到运行命令中: docker run -e "NODE_RED_CREDENTIAL_SECRET=您的密钥内容" 构建和运行 正常地构建这个Dockerfile: docker build -t 您的镜像名:您的标签 . 为了进行本地开发,并确保任何更改都可以立即被应用,只需从您正在工作的本地目录中进入项目目录,然后执行: docker run --rm -e "NODE_RED_CREDENTIAL_SECRET=您的密钥内容" -p 1880:1880 -v `pwd`:/data --name 您的容器名 您的镜像名 启动 可以将环境变量传递到容器中,以配置Node-RED的运行时。 使用环境参数(FLOWS)设置流配置文件,默认为‘flows.json’。您可以使用以下命令行标志在运行时更改它: docker run -it -p 1880:1880 -v node_red_data:/data -e FLOWS=my_flows.json nodered/node-red 注意:如果您设置了FLOWS="",那么可以通过settings.js文件中的flowFile属性来设置流文件。 还有其他一些有用的环境变量,例如: -e NODE_RED_ENABLE_SAFE_MODE=false # 设为true则在安全模式(不运行)下启动Node-RED -e NODE_RED_ENABLE_PROJECTS=false # 设为true则启动支持项目功能的Node-RED 您可以使用环境参数(NODE_OPTIONS)将Node.js运行时参数传递到容器。例如,要固定Node.js垃圾回收器使用的堆大小,您可以使用以下命令: docker run -it -p 1880:1880 -v node_red_data:/data -e NODE_OPTIONS="--max_old_space_size=128" nodered/node-red 无头运行 要在后台(即无头)运行,只需在大多数先前的命令中将-it替换为-d,例如: docker run -d -p 1880:1880 -v node_red_data:/data --name mynodered nodered/node-red 容器Shell 一旦以无头方式运行,您可以使用以下命令重新进入容器: $ docker exec -it mynodered /bin/bash bash-4.4$ 这将在容器内部给出一个命令行,您可以运行您想要的npm安装命令,例如: bash-4.4$ npm install node-red-dashboard bash-4.4$ exit $ docker stop mynodered $ docker start mynodered 刷新浏览器页面应该会在调色板中显示新添加的节点。 多个实例 运行: docker run -d -p 1880 nodered/node-red 将在本地创建一个运行实例。注意:我们没有指定一个名称。 此容器将有一个ID号并在一个随机端口上运行…要找出哪个端口,请运行docker ps。 $ docker ps 您现在可以指向在返回的tcp端口上的主机机器,所以在上面的示例中浏览http://{主机ip}:32768。 连接容器 您可以使用Docker用户定义的桥接器在docker运行时“内部”连接容器。 使用桥接器之前,需要创建它。以下命令将创建一个名为iot的新桥: docker network create iot 然后,需要使用--network命令行选项将所有需要通信的容器添加到同一个桥上: docker run -itd --network iot --name mybroker eclipse-mosquitto mosquitto -c /mosquitto-no-auth.conf 然后运行nodered docker,也添加到同一个桥上: docker run -itd -p 1880:1880 --network iot --name mynodered nodered/node-red 在同一个用户定义的桥上的容器可以利用桥提供的内置名称解析,并使用--name选项指定的容器名称作为目标主机名。 在上面的示例中,可以使用主机名mybroker从Node-RED应用程序访问代理。 然后,一个简单的流,如下所示,显示了连接到代理的mqtt节点: [{"id":"c51cbf73.d90738","type":"mqtt in","z":"3fa278ec.8cbaf","name":"","topic":"test","broker":"5673f1d5.dd5f1","x":290,"y":240,"wires":[["7781c73.639b8b8"]]},{"id":"7008d6ef.b6ee38","type":"mqtt out","z":"3fa278ec.8cbaf","name":"","topic":"test","qos":"","retain":"","broker":"5673f1d5.dd5f1","x":517,"y":131,"wires":[]},{"id":"ef5b970c.7c864","type":"inject","z":"3fa278ec.8cbaf","name":"","repeat":"","crontab":"","once":false,"topic":"","payload":"","payloadType":"date","x":290,"y":153,"wires":[["7008d6ef.b6ee38"]]},{"id":"7781c73.639b8b8","type":"debug","z":"3fa278ec.8cbaf","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":505,"y":257,"wires":[]},{"id":"5673f1d5.dd5f1","type":"mqtt-broker","z":"","name":"","broker":"mybroker","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"15","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","closeTopic":"","closeRetain":"false","closePayload":"","willTopic":"","willQos":"0","willRetain":"false","willPayload":""}] 这样,内部代理就不会暴露在docker主机之外了 - 当然,如果您希望您的计算机之外的其他系统能够使用代理,您可以在代理运行命令中添加-p 1883:1883。 树莓派 - 原生GPIO支持 | v1.0 - BREAKING: 树莓派的原生GPIO支持已被弃用 | | — | 替代原生GPIO的是node-red-node-pi-gpiod。 原生GPIO支持的缺点是: 您的Docker容器需要部署在您希望控制gpio的同一个Docker节点/主机上。 访问您的Docker节点/主机的/dev/mem。 privileged=true对于docker stack命令不受支持。 node-red-node-pi-gpiod修复了所有这些缺点。它可以从单个Node-RED容器与多个树莓派的gpio进行交互,并且多个容器可以在同一个Pi上访问不同的gpio。 快速迁移到node-red-node-pi-gpiod 通过Node-RED调色板安装node-red-node-pi-gpiod。 在主机Pi上安装并运行。有关详细的安装说明,请参阅README。 使用pi gpiod节点替换所有原生gpio节点。 将节点配置为连接到pi gpiod。通常,主机机器将有一个IP 172.17.0.1端口8888,但并不总是这样。您可以使用以下命令来检查: docker exec -it mynodered ip route show default | awk '/default/ {print $3}' 注意:有一个名为gpiod的贡献项目,如果需要,可以在其自己的容器中运行gpiod,而不是在主机上。 串行端口 - Dialout - 添加组如果您需要访问主机的串行端口,可能需要将容器添加到对应的组中。这可以通过在启动命令中添加相应的参数来实现。例如,dialout --group-add dialout: docker run -it -p 1880:1880 -v node_red_data:/data --group-add dialout --name mynodered nodered/node-red 常见问题和建议以下是用户报告的常见问题及可能的解决方案列表: 用户权限错误查看wiki以获取关于权限的详细信息。 如果您在打开文件或访问主机设备时看到“权限被拒绝”的错误,请尝试以root用户身份运行容器。 docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered -u node-red:dialout nodered/node-red 参考资料: https://github.com/node-red/node-red-docker/issues/15 https://github.com/node-red/node-red-docker/issues/8 访问主机设备如果您希望从容器内部访问主机的某个设备,例如串行端口,请使用以下命令行标志来传递访问权限。 docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered --device=/dev/ttyACM0 nodered/node-red 参考资料:https://github.com/node-red/node-red/issues/15 设置时区如果您想要修改默认时区,请使用TZ环境变量并提供相应的时区。 docker run -it -p 1880:1880 -v node_red_data:/data --name mynodered -e TZ=America/New_York nodered/node-red 或者在docker-compose文件中: node-red: environment: - TZ=America/New_York --- ### 260. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 前提条件:如果您使用的是Raspberry Pi OS,Bullseye是当前支持的版本。 安装与更新Node-RED:我们为您提供了一个脚本,可以帮助您在树莓派上安装Node.js、npm和Node-RED。当有新版本发布时,您也可以使用此脚本来更新Node-RED。 想要下载并执行这个脚本,您可以运行以下命令。如果您想事先查看脚本的具体内容,您可以在Github上进行查阅。 bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered) 您还可以给脚本添加一些参数,只需在上面的命令后面加上 --help 就可以查看所有可用参数了。 此脚本适用于所有基于Debian的操作系统,包括Ubuntu和Diet-Pi。在执行脚本之前,为确保npm可以正常工作,您可能需要先执行 sudo apt install build-essential git curl。 执行该脚本后,系统会: 移除当前的Node-RED版本(如果已安装的话)。 检查系统中是否已安装Node.js,如果已安装并且版本低于v14,脚本会提示您决定是否升级。如果系统中未检测到Node.js,脚本会自动安装Node.js 16 LTS版本。 安装最新版本的Node-RED。 可以选择性地为您安装一些特定于树莓派的有用节点。 设置Node-RED作为服务运行,并提供了一套简单的命令,以便您能够管理这个服务。 需要注意的是,Node-RED已经被包括在树莓派操作系统的软件库中,因此您也可以直接通过 apt-get install nodered 进行安装,但这种方法不包括npm。尽管直接使用软件库中的包安装很简单,但我们仍建议您使用上面的脚本来安装,以确保功能的完整性和稳定性。 本地运行:跟在其他系统上运行Node-RED一样,您可以在树莓派的终端中直接使用 node-red 命令。想要停止程序,只需按下 Ctrl-C 或关闭终端即可。 考虑到树莓派的内存限制,建议您使用下面的命令来启动Node-RED,这可以帮助系统更有效地管理内存。 node-red-pi --max-old-space-size=256 作为服务运行:通过上面的脚本安装Node-RED后,它会默认设置为一个服务,在后台运行。您还可以设置它开机自启。 为了方便管理,以下命令可以帮助您控制Node-RED服务: node-red-start:启动服务并显示日志。 node-red-stop:停止服务。 node-red-restart:重新启动服务。 node-red-log:查看服务日志。 在树莓派的桌面环境中,您还可以通过 菜单 -> 编程 -> Node-RED 来启动它。 开机自启:想要设置Node-RED在树莓派启动时自动运行,您可以使用以下命令: sudo systemctl enable nodered.service 如果不想让它开机自启,只需执行: sudo systemctl disable nodered.service 访问编辑器:当Node-RED运行起来后,您可以通过浏览器来访问其编辑器界面。在树莓派本机上,地址为:http://localhost:1880。 当然,我们更推荐您在PC或其他设备上,使用Chrome或Firefox浏览器来访问树莓派上运行的Node-RED。此时,访问地址为:http://<您的树莓派IP地址>:1880。不确定IP地址的话,可以在树莓派终端中运行 hostname -I 来查看。 --- ═══════════════════════════════════════════ ## Node-RED 接口参考 ═══════════════════════════════════════════ ### 261. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 请求方法路径描述GET/auth/login获取活动的身份验证方案POST/auth/token用证书交换访问令牌POST/auth/revoke撤销访问令牌GET/settings获取运行时设置GET/diagnostics获取运行时诊断GET/flows获取活动的流程配置GET/flows/state获取活动流的运行状态POST/flows设置活动的流程配置POST/flows/state设置活动流的运行状态POST/flow将流添加到活动配置GET/flow/:id获取单个流程配置PUT/flow/:id更新单个流程配置DELETE/flow/:id删除单个流程配置GET/nodes获取已安装的节点列表POST/nodes安装新的节点模块GET/nodes/:module获取节点模块的信息PUT/nodes/:module启用/禁用节点模块DELETE/nodes/:module删除节点模块GET/nodes/:module/:set获取节点模块集信息PUT/nodes/:module/:set启用/禁用节点集 --- ### 262. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 错误处理 所有API方法使用标准的HTTP响应代码表示成功或失败。 状态码原因200成功 - 结果在响应内容中204成功 - 但无其他内容400错误请求 - 参见以下响应格式401未授权 - 请查看“身份验证”404未找到 - 没有找到资源409版本不匹配 - 请查看 POST /flows500服务器错误 - 服务器上出现了问题 错误响应 对于响应代码400,响应内容将是一个包含以下字段的JSON对象: 我为您提供了这个JSON对象的表格形式: 字段描述code错误代码message错误描述 您可以将这个格式复制到任何支持Markdown的编辑器中查看效果。 示例: { "code": "module_already_loaded", "message": "模块已加载" } 错误代码列表 代码描述unexpected_error发生意外错误invalid_request请求中包含无效参数settings_unavailable存储系统不支持更改设置module_already_loaded请求的模块已加载type_in_use请求试图删除/禁用当前正在使用的节点类型invalid_api_version请求在头部指定了无效的API版本Node-RED-API-Version --- ### 263. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 传统上,流配置被表示为节点对象的平面数组。 从Node-RED 0.13版本开始,新增了一个API,允许单独维护流程(也称为选项卡)。这些API使用了更丰富的流程配置格式。我们计划在未来更新主流配置以使用这种更丰富的格式,但现在两种格式需要同时存在。 流配置变化 传统上,流配置表示为节点对象的平面数组。从Node-RED 0.13开始,增加了一个api,允许单独维护流(又称为标签)。这些API使用更丰富的流配置格式。我们计划在未来更新主流配置以使用这种丰富格式,但目前这两种格式必须共存。 节点 节点代表流中单个节点的配置。 { "id": "123", "type": "inject", "x": 0, "y": 0, "z": "456", "wires": ["example_wire"] } 字段描述id节点的唯一IDtype节点的类型x,y在绘制流时节点的x/y坐标z节点所属的流或子流wires节点输出连接的线路*由特定类型定义的其他字段 如果节点是配置节点,则它不得具有x, y或wires属性。 子流 子流节点代表子流的配置。 { "id": "6115be82.9eea4", "type": "subflow", "name": "Subflow 1", "info": "", "in": [{"x": 60,"y": 40,"wires": [{"id": "1830cc4e.e7cf34"}]}], "out": [{"x": 320,"y": 40,"wires": [{"id": "1830cc4e.e7cf34","port": 0}]}], "configs": [], "nodes": [] } 完整流配置 完整流配置代表运行时中活动的所有流。它表示为节点对象的平面数组。这是由API使用的主流格式,并由编辑器导入/导出。 [ {"id": "1234", "type": "inject"}, {"id": "5678", "type": "debug"} ] 从0.15.0开始,如果头部设置为Node-RED-API-Version: v2,API支持新格式。 { "rev": "abc-123", "flows": [ {"id": "1234", "type": "inject"}, {"id": "5678", "type": "debug"} ] } 单个流配置 单流配置代表编辑器中作为标签显示的内容。 { "id": "1234", "label": "Sheet1", "nodes": [], "configs": [], "subflows": [] } 字段描述id流的唯一IDlabel流的标签nodes流中的节点数组configs流中的配置数组subflows表示流配置时使用的子流数组 节点模块 节点模块代表由npm包提供的节点集合。 { "name": "node-module-name", "version": "0.0.6", "nodes": [] } 字段说明name模块的名称 - 根据其package.json文件定义version模块的版本 - 根据其package.json文件定义nodes由此模块提供的节点集对象数组 节点集 节点集代表节点模块中单个文件提供的类型集合。 { "id": "node-module-name/node-set-name", "name": "node-set-name", "types": [], "enabled": true, "module": "node-module-name", "version": "0.0.6" } 字段描述id此集的ID - 格式为模块/名称name集的名称 - 定义在模块的package.json中types此集提供的节点类型的字符串数组enabled此集是否当前已启用module提供该集的模块名称。如果其值为node-red,表示节点是从复制的文件中加载的,而不是npm模块。 --- ### 264. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 认证 Node-RED的管理API是通过您的settings.js文件中的adminAuth属性进行安全验证的。安全性部分描述了该属性应如何配置。 如果该属性未设置,任何有网络访问权限的人都可以访问Node-RED的管理API。 步骤 0 - 检查认证方案对/auth/login进行HTTP GET请求将返回当前的认证方案。 curl 示例: curl http://localhost:1880/auth/login 在API的当前版本中,有两种可能的结果: 无活跃认证 {} 所有API请求都可以在不提供任何进一步认证信息的情况下进行。 基于凭证的认证 { "type": "credentials", "prompts": [ { "id": "username", "type": "text", "label": "用户名" }, { "id": "password", "type": "password", "label": "密码" } ] } API由访问令牌保护。 步骤 1 - 获取访问令牌对/auth/token进行HTTP POST请求,用于将用户凭证换取访问令牌。 必须提供以下参数: client_id - 标识客户端。目前,必须是node-red-admin或node-red-editor。 grant_type - 必须是password。 scope - 请求的权限的空格分隔列表。目前,必须是*或read。 username - 用于认证的用户名。 password - 用于认证的密码。 curl 示例: curl http://localhost:1880/auth/token --data 'client_id=node-red-admin&grant_type=password&scope=*&username=admin&password=password' 如果成功,响应将包含访问令牌: { "access_token": "A_SECRET_TOKEN", "expires_in": 604800, "token_type": "Bearer" } 步骤 2 - 使用访问令牌所有后续的API调用都应在头部提供此令牌Authorization。 curl 示例: curl -H "Authorization: Bearer A_SECRET_TOKEN" http://localhost:1880/settings 撤销令牌当不再需要令牌时,为了撤销它,应该在一个HTTP POST中发送到/auth/revoke。 curl 示例: curl --data 'token=A_SECRET_TOKEN' -H "Authorization: Bearer A_SECRET_TOKEN" http://localhost:1880/auth/revoke --- ═══════════════════════════════════════════ ## Node-RED 用户指南 ═══════════════════════════════════════════ ### 265. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网 (IoT) 在当今世界无所不在,已经渗透到多个主导领域,从智慧健康医疗服务到智慧城市、零售行业、农业以及许多其他领域。这个技术的普及为我们的生活带来了前所未有的便利和效率。在这篇文章中,我们将探讨物联网在不同领域中的主导地位以及一些用于处理 IoT 和边缘场景的编程平台软件。 智慧健康医疗服务 物联网在医疗领域的应用是关键的,它为智能救护车、医院管理和智能药控等提供了支持。通过连接医疗设备和患者,医疗专业人员可以实时监测患者的健康状况,迅速采取行动。这可以帮助挽救生命,提高医疗服务的质量。 智慧城市 在智慧城市领域,物联网的应用范围广泛,包括智能交通控制、智能收费站、污染监测、水质管理、自动驾驶汽车、无人机、执法、节能等。这些技术的结合使城市更加智能、可持续,提高了居民的生活质量。 个人应用 在个人生活中,物联网也有着显著的影响,例如智能健康设备、防盗系统以及家电控制。人们可以通过智能手机或其他设备监控他们的健康状况,保护他们的家庭,实现远程控制家电等功能。 零售行业 在零售行业,物联网的应用包括自动结账、物流监控和管理等。这些技术可以加速购物体验,提高库存管理效率,降低运营成本。 农业 农业领域也受益于物联网的应用,包括作物分析、动态配水、智能灌溉、农场监控、智能农业无人机和农业机器人。这些技术有助于提高农作物产量,减少资源浪费。 编程平台软件 为了处理 IoT、IoE、雾或边缘场景,存在许多编程平台软件。以下是一些常见的平台: Node-RED:Node-RED是一个基于流程的编程环境,适用于模拟 IoT 场景。它易于使用,支持多种硬件和协议,是物联网开发的理想工具。 Contiki:Contiki是一个适用于微控制器的开源操作系统,支持 IPv6、IPv4、原线程等,适用于低资源设备和游戏机。 FlowHub:FlowHub是一个基于流程的物联网编程平台,提供直观的可视化编程工具。 NoFloJS:NoFloJS是基于 JavaScript 的流程编程框架,用于物联网应用程序的开发。 Netron:Netron是一个动态可视化工具,用于可视化 IoT 场景的数据流程。 PyFlow:PyFlow是一个可视化脚本工具,可用于创建 IoT 场景中的逻辑和数据流程。 Node-RED 当谈到物联网(IoT)和边缘计算(Edge Computing)场景时,Node-RED是一个备受欢迎的工具,它为开发人员提供了一种直观且灵活的方式来构建、部署和管理物联网应用程序。下文将介绍Node-RED在这两个领域中的应用,以及它是如何帮助解决复杂的问题的。 Node-RED简介 Node-RED是一个开源的流程编排工具,最初由IBM开发,现在由开放社区维护。它的核心概念是使用可视化方式连接各种输入、处理和输出节点,以创建数据流程。这些节点以可重用的方式构建,开发人员可以自定义节点或从社区贡献的节点库中选择节点,以实现各种功能。Node-RED具有丰富的插件生态系统,支持多种硬件和协议,这使得它成为物联网和边缘计算场景的理想选择。 物联网场景中的Node-RED 1. 数据采集和传输 在物联网应用中,Node-RED可以用于收集传感器数据、设备状态和其他信息。通过使用节点,开发人员可以轻松地连接到各种传感器和设备,无论是通过MQTT、HTTP、WebSocket还是其他协议。这使得数据采集变得容易,并且可以自动化处理。 2. 数据处理和分析 一旦数据被采集,Node-RED可以用于处理和分析它。开发人员可以编排一系列节点,执行数据清洗、转换和计算操作。此外,Node-RED还支持可视化工具,如图表和仪表板,可用于实时监控和可视化数据。 3. 响应和控制 物联网应用程序通常需要对设备进行远程控制和响应。Node-RED可以用于创建决策逻辑,根据接收到的数据触发操作,例如发送命令到设备,或者触发警报和通知。这种反应性的能力对于监控和管理物联网设备至关重要。 边缘计算场景中的Node-RED 1. 本地数据处理 边缘计算是一种将计算能力移到数据源附近的策略。Node-RED可以轻松部署到边缘设备上,以进行本地数据处理。这样可以减少数据传输延迟,提高应用程序的响应速度,并减少云端计算的负载。 2. 远程监控和管理 在边缘设备上运行的Node-RED实例可以与远程服务器通信,以实现监控和管理。这使得远程团队可以实时监控设备状态、远程更新应用程序,以及远程执行故障排除和维护操作。 3. 边缘智能 Node-RED的可扩展性和灵活性使其成为在边缘设备上实现边缘智能的理想工具。开发人员可以构建复杂的决策逻辑和自动化任务,而无需互联网连接。这对于需要高度可用性和低延迟的应用程序非常重要,如工业自动化和自动驾驶车辆。 总结 Node-RED是一个功能强大且易于使用的工具,适用于物联网和边缘计算场景。它的可视化编排和丰富的节点库使开发人员能够快速构建、测试和部署应用程序。不仅如此,Node-RED还有一个强大的社区支持,提供了大量的资源和插件,帮助开发人员解决各种复杂的问题。 对于那些希望在物联网和边缘计算领域创造创新解决方案的开发人员来说,Node-RED是一个不可或缺的工具。无论是用于数据采集、处理、分析,还是用于远程监控和本地计算,Node-RED都能够大大简化开发过程,加速应用程序的上线,提高系统的可维护性和可扩展性。在不断发展的IoT和边缘计算领域,Node-RED为开发人员提供了一个强大的工具,助力他们创造出更加智能、高效和响应速度更快的应用程序。 --- ═══════════════════════════════════════════ ## Node-RED 示例教程 ═══════════════════════════════════════════ ### 266. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 该节点是作为 ST-One 项目的一部分创建的。 安装 您可以直接从 Node-RED 界面中的 “管理面板” 菜单安装此节点。 或者,在 Node-RED 用户目录中运行以下命令 - 通常在 Linux 上是 ~/.node-red 或在 Windows 上是 %HOMEPATH%\.nodered npm install node-red-contrib-s7 需要 NodeJS 版本 10 或更高版本以及 Node-RED 版本 1.0 或更高版本。 用法 每个与 PLC 的连接都由 S7 端点配置节点表示。您可以配置 PLC 的地址、可用变量及其地址以及读取变量的循环时间。 S7 In 节点使变量的值在流中以三种不同的模式可用: 单个变量:可以从配置的变量中选择单个变量,并且每个周期发送一条消息,或者如果检查了 diff 则仅当它发生变化时发送消息。msg.payload 包含变量的值,msg.topic 具有变量的名称。 所有变量,每条消息一个:与单变量模式类似,但适用于配置的所有变量。如果选中 diff,则每次任何变量更改时都会发送一条消息。如果未选中 diff,则在每个周期中为每个变量发送一条消息。必须注意此模式下每秒的消息数。 所有变量:在此模式下,msg.payload 包含一个包含所有配置变量及其值的对象。如果选中 diff,则当至少一个变量更改其值时,将发送一条消息。 变量寻址 S7 Endpoint 上配置的变量及其地址遵循的方案与 Step 7 或 TIA Portal 上使用的方案略有不同。以下是一些可以指导您处理变量的示例: 地址相当于 Step7JS 数据类型描述DB5,X0.1DB5.DBX0.1布尔值DB 5 字节 0 的位 1DB23,B1 或 DB23,BYTE1DB23.DBB1数字DB 23 的字节 1 (0-255)DB100,C2 或 DB100,CHAR2DB100.DBB2字符串DB 100 的字节 2 作为字符DB42,I3 或 DB42,INT3DB42.DBW3数字DB 42 的字节 3 处有符号 16 位数字DB57,WORD4DB57.DBW4数字DB 57 字节 4 处的无符号 16 位数字DB13,DI5 或 DB13,DINT5DB13.DBD5数字DB 13 的字节 5 处有符号 32 位数字DB19,DW6 或 DB19,DWORD6DB19.DBD6数字DB 19 的字节 6 处的无符号 32 位数字DB21,R7 或 DB21,REAL7DB21.DBD7数字DB 21 的字节 7 处的浮点 32 位数字DB2,S7.10*-字符串从 DB 2 的字节 7 开始的长度为 10 的字符串I1.0 或 E1.0I1.0 或 E1.0布尔值输入区域字节 1 的位 0Q2.1 或 A2.1Q2.1 或 A2.1布尔值输出区域字节 2 的位 1M3.2M3.2布尔值内存区域字节 3 的位 2IB4 或 EB4IB4 或 EB4数字输入区域的字节 4 (0 -255)QB5 或 AB5QB5 或 AB5数字输出区域的字节 5 (0 -255)MB6MB6数字内存区域的字节 6 (0 -255)IC7 或 EC7IB7 或 EB7字符串输入区域的字节 7 作为字符QC8 或 AC8QB8 或 AB8字符串输出区域的字节 8 作为字符MC9MB9字符串内存区域的字节 9 作为字符II10 或 EI10IW10 或 EW10数字输入区域字节 10 处的有符号 16 位数字QI12 或 AI12QW12 或 AW12数字输出区域字节 12 处的有符号 16 位数字MI14MW14数字内存区域字节 14 处的有符号 16 位数字IW16 或 EW16IW16 或 EW16数字输入区域字节 16 处的无符号 16 位数字QW18 或 AW18QW18 或 AW18数字输出区域字节 18 处的无符号 16 位数字MW20MW20数字内存区域字节 20 处的无符号 16 位数字IDI22 或 EDI22ID22 或 ED22数字输入区域字节 22 处的有符号 32 位数字QDI24 或 ADI24QD24 或 AD24数字输出区域字节 24 处的有符号 32 位数字MDI26MD26数字内存区域字节 26 处的有符号 32 位数字ID28 或 ED28ID28 或 ED28数字输入区域字节 28 处的无符号 32 位数字QD30 或 AD30QD30 或 AD30数字输出区域字节 30 处的无符号 32 位数字MD32MD32数字内存区域字节 32 处的无符号 32 位数字IR34 或 ER34IR34 或 ER34数字输入区域字节 34 处的浮点 32 位数字QR36 或 AR36QR36 或 AR36数字输出区域字节 36 处的浮点 32 位数字MR38MR38数字内存区域字节 38 处的浮点 32 位数字DB1,DT0-日期**DATE_AND_TIME 格式的时间戳DB1,DTZ10-日期**DATE_AND_TIME 格式的时间戳(UTC)DB2,DTL2-日期**DTL 格式的时间戳DB2,DTLZ12-日期**DTL 格式的时间戳(UTC 格式)DB57,RWORD4DB57.DBW4数字DB 57 字节 4 处的无符号 16 位数字,解释为 Little-EndianDB13,RDI5 或 DB13,RDINT5DB13.DBD5数字DB 13 的字节 5 处的有符号 32 位数字,解释为 Little-EndianMRW20MW20数字内存区域字节 20 处的无符号 16 位数字,解释为 Little-Endian 备注: 布尔值 表示是非类型的值,例如开或关。 数字 表示可以是整数或浮点数的值。 字符串 表示文本类型的值。 日期 表示时间戳类型的值。 *) 请注意,PLC 上的字符串在开头使用 2 个额外字节来表示字符串的大小/长度**) 请注意,javascriptDate始终以UTC 表示。请使用其他节点(例如node-red-contrib-moment)来正确处理类型转换 关于 S7-1200/1500 的注意事项 这些较新的 PLC 提供 S7 协议的 “扩展” 版本,而我们只有 “基本” 版本。 因此,需要对 PLC 进行一些额外的配置步骤: 对于我们想要访问的数据库,必须禁用 “优化块访问”。 在 CPU 属性的 “保护” 部分中,启用 “允许使用 PUT/GET 访问” 复选框。 标志注意事项! 最新的标志!8.FS4(可能还有 0BA8)逻辑模块无需再将模式设置为 TSAP,而是使用默认的机架/插槽值 0/2 即可正常工作。 下表显示无需在控制器程序中进行额外设置即可访问的存储区域: 标志块标志 VM 范围示例 Node-RED 地址描述I1024 - 1031DB1,BYTE1024 或 DB1,X1024.5 或 DB1,WORD1024读取输入端子 1...8 或 6 或 1...16AI1032 - 1063DB1,WORD1032读取模拟输入端子 1。始终为字大小。Q1064 - 1071DB1,BYTE1064 或 DB1,X1064.5 或 DB1,WORD1064读取输出端子 1...8 或 6 或 1...16AQ1072 - 1103DB1,WORD1072读取模拟输出端子 1。始终为字大小。M1104 - 1117DB1,BYTE1104 或 DB1,X1104.5 或 DB1,WORD1104读取位标志 M1...M8 或 M6 或 M1...16AM1118 - 1245DB1,WORD1118读取模拟标志 1。始终为字大小。NI1246 - 1061DB1,BYTE1246 或 DB1,X1246.5 或 DB1,WORD1246读取网络输入 1...8 或 6 或 1...16NAI1262 - 1389DB1,WORD1262读取模拟网络输入 1。始终为字大小。NQ1390 - 1405DB1,BYTE1390 或 DB1,X1390.5 或 DB1,WORD1390读取网络输出 1...8 或 6 或 1...16NAQ1406 - 1469DB1,WORD1406读取网络输出 1。始终为字大小。 这个表格描述了在 Siemens Logo! 控制器中可访问的不同存储区域,并提供了如何在 Node-RED 中使用这些区域的实际示例。每个区域都有特定的范围和功能,例如读取输入端子、模拟输入或输出端子等。 另一方面,Logo 内存区域 VM 0-849 从控制器外部是可变的,但需要将它们映射到 Logo 程序中。如果没有映射,写入这些地址的数据将不会影响程序的执行。上述范围内使用的VM地址可以使用“网络”功能块在Logo程序中读取/写入(在功能块设置中使用“本地变量存储器(VM)”选项将VM映射到功能堵塞)。 一些寻址示例: 标志虚拟机示例 Node-RED 地址描述0DB1,BYTE0读/写访问1DB1,X1.3读/写访问 注意:使用布尔值2..3DB1,WORD2读/写访问4..7DB1,DWORD4读/写访问 这个表格描述了在 Siemens Logo! 控制器中可变的虚拟机存储区域,以及如何在 Node-RED 中访问这些区域。每个区域都提供了读写访问权限,不同的地址范围表示不同的数据类型和大小。例如,BYTE、WORD、DWORD 分别表示不同大小的数据单位。 --- ═══════════════════════════════════════════ ## Sparkplug ═══════════════════════════════════════════ ### 267. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 上周,全球最重要的开源软件基金会之一 Eclipse 基金会与 Eclipse Sparkplug 工作组合作,宣布了工业物联网 (IIoT) 发展的一个重要里程碑。 Eclipse Sparkplug 规范已作为国际标准正式发布,现称为 ISO/IEC 20237! Sparkplug 标准化推动 IIoT 发展 这一成就预示着工业物联网连接的新篇章,Sparkplug 规范为不同的工业系统提供了一种轻松通信和交换数据的通用方法。Eclipse Sparkplug 被认可为国际标准非常重要,因为它可以促进互操作性、增强信任和采用、推动创新、扩大市场准入、确保法规遵从性并简化 IIoT 领域的协作。  这一成就标志着在创建更加互联、高效和创新的工业格局方面向前迈出了重要一步。  什么是 MQTT Sparkplug? Sparkplug是一种开源软件规范,为 MQTT 客户端提供框架,以双向和可互操作的方式将来自 MQTT 基础设施内的应用程序、传感器、设备和网关的数据无缝集成。 MQTT Sparkplug的优势 为什么要选择MQTT Sparkplug?这个规范提供了许多优势: 数据互操作性: 通过统一的消息结构和协议规则,Sparkplug确保不同设备之间的数据能够互操作,无需在通信上投入大量精力。 说明:无论哪家供应商提供的温度传感器,它们都能够在相同的系统中无缝运行,因为它们遵循了相同的Sparkplug规范。 节省带宽和资源: 通过“按异常报告”的状态管理方式,减少了不必要的轮询,从而节省了带宽和计算资源。 说明:使用Sparkplug,系统可以立即知道设备的状态变化,而不必频繁轮询设备,从而减少了通信开销。 支持传统设备: 即使某些设备不支持Sparkplug或MQTT,它们仍然可以通过使用EON节点来与系统集成。 说明:即使某个设备使用传统的通信协议,它可以通过连接到支持Sparkplug的EON节点来参与整个系统。 自动设备发现: Sparkplug关注统一性,使系统能够自动发现网络上的设备和数据。 举例说明:当新设备添加到系统中时,它们可以自动被发现并集成,而无需手动配置。 开源规范: Sparkplug是一个开源技术,无需许可,并且可以根据需要进行定制。 举例说明:无需支付昂贵的许可费用,您可以自由地采用和修改Sparkplug规范,以满足您的特定需求。 --- ### 268. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 工业物联网中MQTT有效负载的挑战 在工业物联网(IIoT)中,从简单的温度传感器到复杂的工业机器,各种设备之间的通信常常存在格式不一致和非标准化的问题。而MQTT并没有规定特定的负载结构,这意味着负载可以是任何格式,从纯文本、二进制数据到JSON或XML等,这种多样性虽然允许使用多种数据类型,但对于需要一致和标准化的MQTT有效负载格式的IIoT实现来说可能并不理想。 以下是不一致和非标准化有效负载格式所带来的挑战: 兼容性问题: 如果有效负载没有标准化,不同设备或应用可能发送无法被其他设备或应用正确解读的数据格式,导致集成困难,特别是在涉及多个制造商的大规模IIoT部署中。 增加复杂性: 未标准化的有效负载要求开发者为每种不同的负载格式创建自定义解析器,这不仅使代码库复杂化,还增加了错误的可能性。 效率降低: 解析非标准化或不一致的有效负载通常需要更多的计算资源。在IIoT设备通常受限于处理能力和内存的情况下,这尤其成问题。 维护挑战: 不一致的有效负载结构使系统维护和更新变得更加困难。如果设备改变其有效负载格式,所有订阅实体都必须更新以理解这种新格式。 歧义和数据损坏: 没有标准化结构,数据解读错误或损坏的可能性增加,尤其在像医疗保健或工业自动化等关键应用中,后果可能非常严重。 Sparkplug如何实现标准化和结构化的MQTT有效负载 MQTT Sparkplug规范旨在标准化MQTT消息,确保一致的数据结构,以开发基于MQTT的互操作IIoT解决方案。它通过提供有效负载编码机制实现这一点,这不仅保留了MQTT的基本特性 - 轻量级、带宽高效和低延迟 - 同时还整合了适合IIoT环境的现代编码方案。 Sparkplug B(spBv1.0)有效负载格式是一种数据编码方案,使用Google Protocol Buffers或Google Protobufs。Google Protobufs是一种语言中立的结构化数据序列化机制,使Sparkplug B能够有效且可扩展地编码结构化MQTT数据。 Sparkplug B通过以下方式支持丰富的数据模型: 使用模板的复杂数据类型 数据集 增强的指标 指标别名支持 历史数据集成 文件数据管理 MQTT Sparkplug有效负载的关键组件 主要地,Sparkplug有效负载包含一些基本信息,如时间戳和序列号,以及包含键/值对数据的一系列指标。以下是这些及更多组件的详细说明。 时间戳: Sparkplug要求每个指标都包含时间戳,确保每个数据点都与其记录时间相关联。 指标: Sparkplug有效负载的指标组件由一系列指标组成。在Sparkplug有效负载上下文中,指标指的是设备间通信的具体数据点或值,例如温度读数、压力值或开关状态。为了描述其包含的信息,一个Sparkplug指标表示一个键、值、时间戳、数据类型以及可能与之相关联的任何元数据。 序列号: 每个Sparkplug消息包含一个序列号,每个新消息都会增加。如果接收者检测到序列号中有缺口,它知道有消息丢失了。这一特性对于数据的一致性至关重要,使设备或系统能够请求丢失的数据或采取纠正措施。 Sparkplug有效负载指标组件解析 name(名称): 指标的标识符。 alias(别名): 指标的数值别名,用于减少重复消息中的有效负载大小。 timestamp(时间戳): 表示指标采集或创建的时间。 datatype(数据类型): 指标持有的数据类型(例如,Boolean布尔型、Int32整型、String字符串等)。 value(值): 实际的数据。 is_historical(是否为历史值): 一个布尔标志,表示此指标是否代表一个历史值。 is_transient(是否为瞬时值): 一个布尔标志,表示此指标是否不应被记录为历史数据。 is_null(是否为空值): 一个布尔标志,表示此指标是否有一个空值。 metadata(元数据): 与指标相关联的元数据对象。 properties(属性): 与指标相关联的属性集对象。 Sparkplug B有效负载的示例 下面是一个简单的Sparkplug B有效负载的例子。 { "timestamp": 1486144502122, "metrics": [{ "name": "My Metric", "alias": 1, "timestamp": 1479123452194, "dataType": "String", "value": "Test" }], "seq": 2 } NBIRTH有效负载表示 NBIRTH消息负责通知主机应用程序边缘节点的所有信息,包括将来它将发布数据的每个指标。 以下是一个简单的NBIRTH消息的表示,在主题上: spBv1.0/DairyPlant/NBIRTH/Refrigeration Sparkplug B有效负载在NBIRTH消息中的发布可能如下所示: { "timestamp": 1486144502122, "metrics": [{ "name": "bdSeq", "timestamp": 1486144502122, "dataType": "Int64", "value": 0 }, { "name": "Node Control/Scan Rate", "timestamp": 1486144502122, "dataType": "Int64", "value": 3000 }, { "name": "Properties/Hardware Make", "timestamp": 1486144502122, "dataType": "String", "value": "Opto22 Groov EPIC" }, { "name": "Inputs/Temperature", "timestamp": 1486144502122, "dataType": "Float", "value": 25.6 }, { "name": "Inputs/Humidity", "timestamp": 1486144502122, "dataType": "Float", "value": 67.8 }, { "name": "Outputs/Pump", "timestamp": 1486144502122, "dataType": "Boolean", "value": true }], "seq": 0 } NDATA有效负载表示 NDATA消息用于更新边缘节点在NBIRTH消息中最初发布的任何指标的值。当边缘节点的输入发生变化时,将生成NDATA消息并发布到MQTT服务器。如果边缘节点上的多个指标发生变化,它们都可以包含在单个NDATA消息中。 以下是一个简单的NDATA消息的表示,在主题上: spBv1.0/DairyPlant/NDATA/Refrigeration Sparkplug B有效负载在NDATA消息中的发布可能如下所示: { "timestamp": 1486144502122, "metrics": [{ "name": "Inputs/Temperature", "timestamp": 1486144502122, "dataType": "Float", "value": 29.2 }, { "name": "Inputs/Humidity", "timestamp": 1486144502122, "dataType": "Float", "value": 55.9 }], "seq": 0 } 请注意,如果泵状态的值没有改变,则可以从指标中排除泵状态的值。 结论 总而言之,尽管MQTT在其有效负载结构上提供了灵活性,但这种灵活性可能导致集成挑战和复杂性增加,特别是在使用来自不同厂商的设备和应用程序时。MQTT Sparkplug规范通过提供一致和标准化的有效负载结构来解决这一挑战,专为IIoT量身定制。通过其使用Google Protocol Buffers的Sparkplug B数据编码机制,它确保设备能够高效地交换信息,同时保留MQTT的关键属性。这种统一性不仅简化了开发和集成工作,还增强了IIoT部署中数据通信的可靠性和完整性。 --- ### 269. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT Sparkplug在IIoT架构中的关键组件运作 要有效地设计和开发基于MQTT Sparkplug的IIoT架构,理解其组件的运作方式至关重要。具体来说,这包括它们如何连接、发布、接收数据以及如何从网络断开。 本文将探讨三个关键组件在IIoT网络中的会话生命周期:Sparkplug主机应用程序、网络边缘节点和设备,以解释连接机制、数据传输方法和会话建立的复杂性。 MQTT Sparkplug主机应用程序会话生命周期 当Sparkplug主机应用程序启动或重新建立连接时,它会立即尝试与MQTT服务器(已预先配置)建立会话。 一旦与MQTT服务器成功连接,主机应用程序会采取两项主要行动: 它订阅指定的Sparkplug主题命名空间,特别是spBv1.0/#。 它还确保通过名为STATE/host_app_id的主题订阅其自身的状态。 在完成这些订阅后,Sparkplug主机应用程序负责通过发布新的STATE消息通知其他人自己的状态。 此时,主机应用程序准备好接收网络中任何边缘节点发送的MQTT消息。每当边缘节点发送其Sparkplug NBIRTH和DBIRTH通知时,主机应用程序会更新其指标,显示它目前在线并正在处理数据。 MQTT Sparkplug边缘节点会话生命周期 像Sparkplug网络中的任何设备一样,边缘节点通过发送连接请求来初始化其与MQTT代理的连接。此请求通常包含节点的凭据和其他必要细节。 当Sparkplug边缘节点发送其MQTT CONNECT数据包时,它会包含以下主题格式下的“遗嘱消息”: spBv1.0/group_id/NDEATH/edge_node_id 在这里,group_id是Sparkplug组ID,edge_node_id是该边缘节点的Sparkplug边缘节点ID。 在Sparkplug环境中,边缘节点可以设置为识别主机应用程序。如果这样配置,边缘节点只会在主机应用程序在线并主动监听Sparkplug消息时发送其NBIRTH和DBIRTH消息。 成功连接到MQTT服务器后,边缘节点将订阅NCMD和STATE主题。NCMD订阅允许边缘节点处理重生请求。同时,订阅STATE有助于边缘节点了解主机应用程序的当前状态。 随后,边缘节点将使用以下格式广播NBIRTH消息: spBv1.0/group_id/NBIRTH/edge_node_id 此时,主机应用程序可以建立边缘节点的指标结构,显示其在线状态。 MQTT Sparkplug设备会话生命周期 在边缘节点准备向MQTT服务器报告其所有Sparkplug定义的指标数据时,边缘节点(逻辑或物理)负责发布设备诞生消息,DBIRTH。 然而,在发送DBIRTH消息之前,如果设备支持写入输出,则与Sparkplug设备相关联的MQTT客户端必须订阅接收DCMD消息,使用以下主题格式: spBv1.0/group_id/DCMD/edge_node_id/device_id 在这里,group_id是Sparkplug组ID,edge_node_id是Sparkplug边缘节点ID,device_id是设备的Sparkplug设备ID。 从那时起,所有后续指标都会按照例外报告(RBE)的方式使用DDATA消息格式发布给主机应用程序。 结论 总之,本文解释了MQTT Sparkplug的运作行为,阐明了有效的IIoT通信所需的复杂机制。 --- ### 270. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 数据获取与聚合:MQTT与Sparkplug的运用 MQTT是一种标准的二进制发布-订阅消息传递协议,旨在实现设备和系统间快速且可靠的OEE数据传输,尤其适用于网络不稳定、带宽有限、电池动力有限等受限条件下。它基于TCP/IP协议构建,是互联网上网络设备互联的首选通信协议。因此,MQTT非常适合用于工业物联网(IIoT),支持事件驱动架构。 Sparkplug是建立在MQTT之上的框架,为制造数据添加更多上下文。它是一个开源软件规范,为MQTT客户端提供了一个框架,以集成OEE数据并通过定义数据模型提供上下文。它为制造设备制造商和软件提供商共享上下文OEE数据提供了一致的方法,加速了现有运营的数字化转型。 MQTT Sparkplug帮助提高工业过程中OEE的5种方式 实现实时OEE数据流动: MQTT的发布订阅特性和低数据开销使其能够实时访问事件驱动数据,即使在包括连接问题或低带宽等受限环境中也是如此。Sparkplug的出生和死亡通知定义了适当的状态监控机制,可以通知用户工厂地板上淘汰的旧系统和新增的新系统,以确保OEE跟踪是最新的。 高度安全的OEE数据流动: MQTT通信需要客户端与代理进行身份验证,这使得通信高度安全。HiveMQ提供额外的安全特性,包括用户名和密码、OAuth 2.0(JWT)、X.509客户端证书、动态权限、基于角色的权限等授权/认证功能。 随着业务增长而扩展OEE数据: MQTT的发布/订阅模型允许任意数量的客户端连接到代理,易于根据连接数量扩展。这在工厂中很常见,因为需要跟踪的OEE数据点随着新机器和系统的增加而增加。 高可靠性的OEE数据: MQTT确保OEE数据的高可靠性。其中一个关键特性是服务质量(QoS),它使制造商能够选择与网络可靠性和应用逻辑相匹配的服务水平。 支持不同数据类型和数据速率: MQTT最大的优势之一是能够具有统一的命名空间(UNS),作为来自不同系统(如工厂机器、质量系统、MES、ERP等)的所有OEE数据的单一真实来源,然后提供给可以使用和行动的应用程序。 结论 OEE是衡量生产效率的有力方式。拥有全面的数据管理策略有助于改善OEE数据收集,而MQTT Sparkplug可以在许多方面帮助提高工业过程中的OEE。 --- ### 271. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在制造公司的数字转型战略中,成功取决于其能否连接各种工业数据源,并通过互联网移动它们,以实现OT中心数据与企业/IT应用程序的集成。 在这方面,有两种领先的通信协议提供了标准化的消息交换,为这两个传统上相互隔离的领域之间提供了必要的互操作性连接。这两种协议分别是MQTT Sparkplug和OPC UA。 在本文中,我将描述MQTT Sparkplug和OPC UA之间的主要差异。但在深入探讨这些协议的定义特性之前,让我们简要定义一下每种通信技术。 什么是MQTT Sparkplug? MQTT Sparkplug是一个开源的软件规范,为MQTT客户端提供了一个框架,以双向和互操作的方式无缝集成来自工业数据源的数据到MQTT基础架构中。它通过定义一致的MQTT主题命名空间、有效负载表示和会话状态管理来实现这一目标。 什么是OPC UA? OPC UA是一种跨平台的开源数据交换标准,用于机器对机器的工业通信。它通过使用面向服务的架构和定义独立于制造商或系统供应商的通用设备和信息模型来实现互操作性。 以下是MQTT Sparkplug和OPC UA之间的主要差异: 可扩展性 MQTT Sparkplug的中心代理式发布-订阅通信模型使您能够构建高度可扩展的工业物联网解决方案,因为即使数千个组件订阅以消耗事件,也不会影响事件的生成方式。根据MQTT代理的不同,基于MQTT Sparkplug的工业物联网系统可以扩展到数千万个连接的设备和系统。 另一方面,由于OPC UA采用的是请求-响应通信模型,它仅在服务器具备响应所有客户端需求的能力的小型内部网络中运行良好。因此,要显着扩展基于OPC UA的工业物联网解决方案以包括其他业务功能是严重受限的。 数据带宽效率 MQTT Sparkplug的“按异常报告”规则确保数据生成者仅在检测到监视数据点的值发生更改时才发布数据,这意味着MQTT Sparkplug客户端仅传输已更改的数据和一个小型的保持活动包,以通知MQTT代理客户端仍在运行。这节省了带宽、内存、CPU时间、能源,当与小型有效负载大小结合使用时,实现了高效的协议。 OPC UA的请求-响应模型要求客户端在流程数据没有发生更改时持续轮询服务器。这会消耗大量的带宽、内存、CPU时间、能源,并且需要保持有状态的连接,导致协议效率低下。 数据完整性 MQTT Sparkplug的数据建模能力使其能够在车间实现有关上下文模型、资产和标签数据的单一数据源,可以通过单一的非更改消息媒介,即MQTT代理,被数百甚至数千个OT和IT应用程序使用。这使您能够定义和组织围绕数据模型的业务流程。 OPC UA也有一个OT中心建模引擎,具有多个不同的数据模型定义。首先,各种数据模型的多样性会在标准内部产生碎片化,而且,因为数据的消耗取决于有限数量的客户端应用程序的直接连接,这样就不能保证数据的完整性将在管道上得以维持,因此无法组织业务流程。 集成的便捷性 MQTT Sparkplug的发布-订阅体系结构模型通过统一命名空间连接设备和应用程序,因此它们永远不必直接联系对方,这导致了集成(新)组件更容易。 OPC UA的请求-响应体系结构模型要求设备直接连接到应用程序,这意味着应用程序依赖于它们控制的特定设备,导致了紧密耦合的工业物联网系统,难以集成新组件。 自动发现 MQTT Sparkplug组件可以自动发现所有连接的网络参与者将发送的数据。 OPC UA客户端需要预先配置信息,如节点地址或OPC UA设备类型。 会话状态感知 MQTT Sparkplug通过“出生消息”和“死亡消息”与MQTT连接的“保持活动”计时器的内置会话状态管理功能,能够提供所有系统组件的实时可见性。 与此同时,OPC UA依赖于昂贵且有时不可行的持续轮询,以维护工业物联网组件之间连接状态的概念。 响应性 由于MQTT Sparkplug使用基于事件的架构和按异常报告,它允许在出现异常或事件(如警报)时快速进行调整,从而实现高度响应的工业物联网系统。而在OP C UA中,您必须调整轮询频率以接近实时事件报告。 通信方向性 MQTT Sparkplug允许由工业物联网系统中的任何组件发起的双向通信,而在OPC UA中,服务器仅对客户端发出的请求作出响应。 安全和隐私 MQTT Sparkplug没有定义安全协议,它允许您在TCP/IP层面处理安全性。这意味着您的IT部门可以选择安全模型,如TLS/SSL、证书等,而MQTT将在其之上运行。因为MQTT Sparkplug客户端使用出站通信端口与服务器进行通信,所以无需打开可能增加IT基础设施攻击面的入站通信端口。 另一方面,OPC UA定义了安全协议。但由于与OPC UA服务器的通信是由云等外部平台发起的,这意味着您的IT基础设施需要为入站流量打开端口,从而使其暴露给具有恶意意图的操作者。但它们都具有应用层安全机制,如用户名和密码以及安全令牌。 云连接 MQTT Sparkplug使得将云应用程序与车间系统集成变得轻而易举,只需将云应用程序插入托管在云中的MQTT代理即可。此外,在只需要偶尔与云连接的关键应用程序中,MQTT代理可以在本地托管,以实现低延迟数据交换,同时通过桥接与云基MQTT代理及时连接。 另一方面,要将OPC UA系统与基于云的应用程序集成,需要多个组件在边缘和云中执行发现和数据聚合。虽然OPC UA最近引入了针对云连接的PubSub规范,使用诸如MQTT等协议,但由于其不成熟,其实施较少,并且尚未定义如何将OPC UA的丰富信息模型映射到MQTT。 规范的复杂性 MQTT Sparkplug规范包含68页的简明信息,使其易于在设备和应用程序上实施。 OPC UA规范由多个部分(超过14个)组成,每个部分都有数百页(总共超过1200页),使其成为一种难以在设备和应用程序上实施的复杂标准。 总结:OPC UA与MQTT Sparkplug 特征MQTT SparkplugOPC UA可扩展性高度可扩展不可扩展数据完整性良好差效率高效不高效集成的便捷性易难自动发现可能不可能安全性高度安全有漏洞的安全性云连接易难规范的复杂性简单复杂会话状态感知实时通过轮询通信方向性双向单向轻量级是不是轻量级也不高性能按异常报告是否,不可能响应性高度响应性不响应 结论 总之,虽然本文涵盖了多个特性,以突出MQTT Sparkplug和OPC UA之间的主要差异,但每个特性对于制造企业的重要性因用例而异。因此,要确定它们的重要性,将这些特性分组到主要的制造业务KPI(成本、风险和收入)中会有意义。 可扩展性、数据带宽效率、集成的便捷性和规范的复杂性导致了降低成本。数据完整性、安全性和隐私导致降低业务风险。最后,响应性、自动发现、会话状态感知、云连接和通信方向性导致通过增加运营效率来避免收入损失。 --- ### 272. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在工业物联网(IIoT)的快速演进中,跨设备和应用程序之间的无缝数据通信变得至关重要。为了应对这一需求,开源规范Sparkplug诞生了,它为MQTT客户端提供了一个框架,使它们能够轻松地将数据集成到MQTT基础架构中。本文将介绍Sparkplug规范,探讨其重要性,以及它如何加速实现工业物联网的回报率(ROI)。 Sparkplug规范简介 Sparkplug是一个开源规范,托管在Eclipse Foundation上,旨在为MQTT客户端提供一个框架,以无缝集成应用程序、传感器、设备和网关的数据到MQTT基础架构中。Sparkplug规范的发展是在GitHub上以开放的方式进行的,并受Eclipse Foundation Specification Process(EFSP)的监管。任何人都可以在任何媒介上复制和分发规范文档,无需支付费用或版税。 Sparkplug规范的目标 Sparkplug规范的目标是定义一个MQTT主题命名空间、有效负载和会话状态管理,可以通用地应用于工业物联网市场,同时也满足实时SCADA/控制HMI解决方案的需求。通过满足这些系统的运行需求,基于MQTT的基础架构可以为业务线和MES解决方案提供更有价值的实时信息。 修订历史 1.0(2016年5月26日):初始发布,由Cirrus Link Solutions完成。 2.1(2016年12月10日):增加了有效负载B。 2.2(2019年10月11日):迁移到Eclipse Foundation品牌。 3.0(2022年10月21日):迁移到AsciiDoc,完全重新组织,添加明确的规范和非规范性声明。 注:版本3.0是本文的主要焦点。 规范委员会 规范委员会负责为Sparkplug工作组管辖下的所有规范项目执行Eclipse Foundation Specification Process(EFSP)。该委员会确保EFSP得以遵守,并对Sparkplug规范项目提交的创建审查、进展审查和发布审查进行投票批准。 资源 Sparkplug兼容软件 Sparkplug兼容硬件 Sparkplug TCK流程(技术兼容性套件) 委员会成员 Sparkplug规范对工业物联网的重要性 Sparkplug规范在工业物联网中发挥着至关重要的作用。以下是一些关键方面,解释了它为何对实现ROI至关重要: 1. 互操作性:Sparkplug规范提供了统一的消息结构和协议规则,使不同设备之间的数据能够无缝地互操作。这消除了在通信上的混乱和矛盾。 2. 状态管理:Sparkplug引入了状态管理,通过“出生消息”和“遗嘱消息”的方式,实时通知系统中的设备是否在线或离线。这降低了通信开销,提高了实时性。 3. 支持传统设备:即使某些设备不支持Sparkplug或MQTT,它们仍然可以通过连接到支持Sparkplug的EON节点来与系统集成。这种灵活性确保了现有设备的无缝融入。 4. 自动设备发现:Sparkplug规范使系统能够自动发现网络上的设备和数据,无需手动配置。这节省了时间和资源。 5. 开源规范:Sparkplug是一个开源技术,无需许可,并且可以根据需要进行定制。这使其成为广泛采用和灵活配置的理想选择。 结论 Sparkplug规范是工业物联网中的关键技术,为实现工业自动化系统的互操作性、可靠性和高效性提供了坚实的基础。通过为工业设备之间的数据通信建立标准,Sparkplug帮助企业避免供应商依赖性,降低了系统复杂性,从而实现更容易扩展。通过采用基于Sparkplug规范的数据传输架构,企业能够更快地实现工业物联网的回报率,为其工业自动化系统带来更大的成功。 --- ### 273. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当在工业控制系统中使用相同的语言,但存在不同的词汇来指代相同的物体时,可能会导致严重的混淆,特别是在需要迅速采取行动来纠正问题的关键时刻。这个问题类似于一群人在尝试一起解决一个谜题,但每个人都使用不同的拼图来组成完整的图像,因此难以协同合作。 幸运的是,有一种解决这个问题的方法,即采用统一的标准和词汇,以确保所有人都在同一个频道上。在工业控制系统中,这一标准就是MQTT Sparkplug。 什么是MQTT Sparkplug? MQTT Sparkplug是一种开源软件规范,旨在指导MQTT客户端如何在工业环境中使用MQTT协议。它的目标是消除在工业自动化中出现的通信混乱,提高互操作性,加速新设备的集成,以及降低因通信问题而导致的停机和风险。 Sparkplug通过定义特定的消息结构和协议规则,为工业4.0和工业物联网(IIoT)创建了即插即用的解决方案。 举例:想象一下,你正在管理一个工厂的自动化系统,其中有多个设备负责监测温度。但是,不同的工程师和供应商使用了不同的命名约定来表示温度数据。有的人称之为“温度1”,有的人称之为“热量-A”,还有的人称之为“温度_reading_5”。在没有统一标准的情况下,混乱不断上升,工程师们必须不断查看文档以了解各种温度传感器的命名约定。这不仅浪费时间,还可能导致错误和混淆。 MQTT Sparkplug的三个关键目标 MQTT Sparkplug旨在实现以下三个关键目标: 定义MQTT主题命名空间: 它提供了一种结构化方法来命名MQTT主题,以便在整个系统中统一表示不同设备和传感器的数据。这消除了在不同设备之间的不同命名约定所导致的混淆。 举例说明:使用Sparkplug,所有温度传感器可以使用相同的命名约定,例如“温度1”,“温度2”和“温度3”,使工程师能够轻松地订阅和理解这些数据。 定义MQTT状态管理: Sparkplug规范引入了状态管理,通过广播“出生消息”和“遗嘱消息”的方式,及时通知系统中的设备是否在线或离线。这消除了传统的轮询方式,减少了通信的带宽和计算资源的浪费。 举例说明:假设一个温度传感器由于故障而突然断线。使用Sparkplug,它将立即广播“离线”状态,而无需等待系统进行轮询检查。这大大提高了系统对设备状态的实时感知。 定义MQTT有效负载: 规范规定了如何结构化消息有效负载,使其易于理解和处理。每个消息有效负载包含了名称、别名、时间戳、数据类型和值,这使数据的解释和处理变得更加一致和方便。 举例说明:有效负载结构的统一性确保数据以一致的方式表示。例如,温度传感器的数据将包括名称("温度")、别名("温度传感器1")、时间戳、数据类型和实际温度值。这使数据处理变得更加简单,无需不断适应不同的数据格式。 MQTT Sparkplug的工作原理 在MQTT Sparkplug架构中,MQTT代理充当关键的中央枢纽。它负责接收发布的消息并将其路由到正确的订阅者。这种基于发布/订阅的消息传递方式使系统的组件能够以松散耦合的方式通信。 举例说明1:想象一下,多个温度传感器不断向MQTT代理发布温度数据。SCADA系统和其他应用程序可以订阅这些数据,而无需直接连接到传感器,从而实现了松散耦合的通信。 各种设备,特别是那些位于工厂设备的“边缘”或EON(Edge of Network)的设备,持续向MQTT代理发布数据。即使某些设备不支持原生的Sparkplug,它们仍然可以通过将数据发送到支持Sparkplug的EON节点来参与网络。 举例说明2:某台设备在工厂的边缘不支持Sparkplug,但它可以通过一个支持Sparkplug的EON网关将其数据发送到系统。这种灵活性确保了所有设备都可以参与通信。 SCADA/IIoT主机则是监视和控制这些EON节点及其下属设备和传感器的应用程序。它们连接到MQTT代理,可以实时监控设备状态、数据和执行控制操作。 说明:SCADA系统监视温度传感器的数据,并在需要时触发控制操作,例如调整温度设定或触发报警。 另外,还有MQTT应用节点,用于执行各种任务,例如数据历史记录、制造执行系统(MES)和数据分析。这些应用程序使用通过MQTT传输的数据,也可以生成消息以觋发操作。 说明:一个数据分析应用程序可以接收温度数据,将其与其他数据集进行比较,然后生成预测性维护建议,例如何时对设备进行维护,以确保其正常运行。 MQTT Sparkplug的优势 为什么要选择MQTT Sparkplug?这个规范提供了许多优势: 数据互操作性: 通过统一的消息结构和协议规则,Sparkplug确保不同设备之间的数据能够互操作,无需在通信上投入大量精力。 说明:无论哪家供应商提供的温度传感器,它们都能够在相同的系统中无缝运行,因为它们遵循了相同的Sparkplug规范。 节省带宽和资源: 通过“按异常报告”的状态管理方式,减少了不必要的轮询,从而节省了带宽和计算资源。 说明:使用Sparkplug,系统可以立即知道设备的状态变化,而不必频繁轮询设备,从而减少了通信开销。 支持传统设备: 即使某些设备不支持Sparkplug或MQTT,它们仍然可以通过使用EON节点来与系统集成。 说明:即使某个设备使用传统的通信协议,它可以通过连接到支持Sparkplug的EON节点来参与整个系统。 自动设备发现: Sparkplug关注统一性,使系统能够自动发现网络上的设备和数据。 举例说明:当新设备添加到系统中时,它们可以自动被发现并集成,而无需手动配置。 开源规范: Sparkplug是一个开源技术,无需许可,并且可以根据需要进行定制。 举例说明:无需支付昂贵的许可费用,您可以自由地采用和修改Sparkplug规范,以满足您的特定需求。 结论 MQTT Sparkplug是工业控制系统中的一项关键技术,它大大简化了设备之间的通信和集成,提高了系统的互操作性和可靠性。它为工业4.0和工业物联网(IIoT)的实施提供了强大的支持,使工业自动化系统更加安全、高效和可用。如果您正在考虑采用最新的工业技术,MQTT Sparkplug是您的有力助手,为您铺平通往成功的道路。在这个过程中,可以考虑与值得信赖的合作伙伴如Outlier Automation合作,以实现自动化目标。无论您需要帮助开始使用MQTT Sparkplug,计划升级PLC,还是进行概念验证,Outlier Automation都可以提供专业支持,助您顺利实现工业自动化的目标。 --- ### 274. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 新的v3.0.0 Sparkplug®规范对之前版本进行了整理和正式化。根据Eclipse Sparkplug工作组的说法,其目标是澄清v2.2版本中存在的模糊不清的地方,并明确规范性的陈述,同时保持v2.2规范的总体意图。 例如,新规范的第2章“原则”取代了2.2规范中的“背景”章节。现在,它详细描述了Sparkplug的关键原则,第5章“操作行为”非常详细地描述了Sparkplug环境的操作方面。该组织还包括了MQTT v5.0的特定设置,特别是关于不同会话设置的设置,例如MQTT 3.1.1中的“清除会话”与v5.0中的“清除开始”。 Sparkplug基础设施对MQTT服务器(在规范文件中,将“MQTT代理”称为“MQTT服务器”)有特定的要求。任何完全符合MQTT v3.1.1的服务器/代理都将符合Sparkplug基础设施的要求。 然而,并不是MQTT规范的所有功能都是必需的。 基本要求功能包括: 用于数据的QoS 0(最多一次) 用于状态管理的QoS 1(至少一次) 保留消息支持 状态管理的“遗嘱消息”(LWT) 支持通配符 规范区分了“符合Sparkplug MQTT服务器”和“了解Sparkplug MQTT服务器”。让我们快速看看两者之间的区别。 符合Sparkplug MQTT服务器 符合Sparkplug MQTT服务器必须支持以下功能: 在QoS 0上发布和订阅 在QoS 1上发布和订阅 遗嘱消息的所有方面,包括使用保留标志和QoS 1 保留标志的所有方面 了解Sparkplug MQTT服务器 而了解Sparkplug MQTT服务器包括了符合Sparkplug MQTT服务器的所有方面,并且必须具备以下额外的能力: 在MQTT服务器传递NBIRTH消息时,存储NBIRTH消息 将NBIRTH消息提供在以下形式的主题上: $sparkplug/certificates/{namespace}/{group_id}/NBIRTH/{edge_node_id}假设group_id=GROUP1和edge_node_id=EON1,则必须在主题上提供NBIRTH消息:$sparkplug/certificates/spBv1.0/GROUP1/NBIRTH/EON1 将NBIRTH消息提供在以下形式的主题上: $sparkplug/certificates/{namespace}/{group_id}/NBIRTH/{edge_node_id}并将MQTT保留标志设置为true 将DBIRTH消息提供在以下形式的主题上: $sparkplug/certificates/namespace/group_id/DBIRTH/edge_node_id/device_id假设group_id=GROUP1,edge_node_id=EON1和device_id=DEVICE1,则必须在主题上提供DBIRTH消息:$sparkplug/certificates/spBv1.0/GROUP1/DBIRTH/EON1/DEVICE1 将DBIRTH消息提供在以下形式的主题上: $sparkplug/certificates/{namespace}/{group_id}/DBIRTH/{edge_node_id}/{device_id}并将MQTT保留标志设置为true 此外,了解Sparkplug MQTT服务器还可以替换NDEATH消息的时间戳。如果这样做,它必须将时间戳设置为UTC时间,以尝试将NDEATH传递给订阅客户端的时间。 因此,了解Sparkplug MQTT服务器扩展了Sparkplug的状态管理方法。简而言之,出生和死亡证书现在被存储为保留消息,并提供了新引入的主题结构$sparkplug/certificates/#。 更新NDEATH消息的时间戳的这一可选功能是这个版本的亮点。这些时间戳由于“遗嘱功能”而存储在代理中。遗嘱消息包含在MQTT连接尝试中,并且将包含无条件客户端断开连接的时间戳,实际上是未知的。这个(可选的)时间戳更新LWT消息发布解决了这个问题。 通过Sparkplug®兼容性计划让终端用户知道您已经准备好了 Sparkplug兼容性计划允许软件和硬件供应商证明其产品与Eclipse Sparkplug和基于MQTT的物联网基础设施兼容,并为之获得认证。 获得认证的供应商使集成商和终端用户能够轻松地采购与Sparkplug规范兼容的设备和软件产品。该计划确保其解决方案能够与工业物联网中最常见的设备和网络无缝集成。 要获得认证,供应商的产品必须通过多个开源测试,以确认其符合Sparkplug技术兼容性工具包(TCK)的标准。如果产品通过了兼容性测试,Sparkplug工作组将将其添加到其官方的兼容产品列表中(可以在其网站上找到)。一旦获得许可,供应商可以使用Sparkplug兼容的标志向外界宣传其兼容性。 https://sparkplug.eclipse.org/compatibility/get-listed/ 以下是您需要了解有关TCK的信息… Sparkplug技术兼容性工具包(TCK) 适当的Sparkplug实施需要完全兼容以下组件: 网络边缘节点/设备, 主要应用程序,当然还有 MQTT代理。 Sparkplug技术兼容性工具包(TCK)提供了指南,验证所有待认证的组件是否符合Sparkplug规范。 TCK是一个Web应用程序,包括一个带有HiveMQ扩展和Web界面的HiveMQ代理。Web界面提供了对兼容性测试的访问。 TCK可以在Eclipse Sparkplug存储库中找到。 要使用JDK 11构建Sparkplug TCK HiveMQ扩展(JDK 17不起作用),请从GitHub中的“sparkplug/tck”进行检出并运行./gradlew。您可以在项目文件夹的build/hivemq-extension中找到扩展工件。 您必须向HiveMQ代理添加WebSocket监听器,并将扩展包含在HiveMQ的扩展文件夹中。启动或重新启动HiveMQ后,扩展即可使用。 如果您想要在自己的IDE中直接运行或调试HiveMQ扩展,请使用./gradlew runHivemqWithExtension。在此Gradle目标中,HiveMQ Community Edition将自动下载并根据Gradle构建文件中的任务完全配置为TCK扩展。 如上所述,基于Nuxt.js(Vue.js)的Web控制台控制TCK。确保您的计算机上有最新版本的yarn和node.js。Mac用户应该查找brew install yarn和brew install node。如果出现错误消息:“env:node:No such file or directory”,这意味着未安装node。在这种情况下,您可以使用yarn install和yarn dev(有关更多详细信息,请参阅webconsole readme)来安装和启动Web控制台。 TCK Web控制台可以通过浏览器中的http://localhost:3000访问: 您可以为主机应用程序、边缘节点和MQTT代理选择Sparkplug符合性配置文件。 主机应用程序配置文件包含用于测试以下内容的测试: 会话建立 会话终止 发送命令 边缘会话终止 消息排序和 多个MQTT服务器(代理)。 边缘节点测试包括 会话建立 会话终止 发送数据、发送复杂数据 接收命令 主机和多个MQTT服务器(代理)。 使用代理配置可以测试MQTT代理是否符合Sparkplug规范并具有了解Sparkplug的功能。 结论 尽管没有太多新规定,但新规范已经整理了许多主题,并更严格和全面地阐述了它们。然而,真正的收获主要在于证书产品或甚至检查产品的Sparkplug兼容性的可能性。这不仅对制造商有增值,也对终端用户有增值。 --- ### 275. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 随着工业物联网(IIoT)的部署日益增多和成熟,它们为全球的工业和制造组织带来了服务创新、生产力增加、运营流程优化,最重要的是成本降低。一些公司正在扩展其用例,而其他公司刚刚起步。根据Grandview Research的估计,全球IIoT市场规模为2630亿美元,到2028年将增长到1.11万亿美元(图1)。 图1:Grandview Research估计的IIoT市场规模 实现投资回报率(ROI)并从IIoT中获得价值取决于一个关键因素:数据。操作数据支持用例,如机器状态监测、提高OEE和实施预防性维护。数据的连通性和可用性通常是IIoT部署的主要挑战。因此,我们已经看到了两种旨在解决数据传输挑战并帮助制造业变得数据驱动的开放标准消息传递协议的增加采用 - MQTT和Sparkplug。 MQTT是一种轻量级的发布/订阅消息传递协议,非常适合连接远程设备(例如,IIoT)。MQTT具有小的代码占用空间。这种设计允许数据在具有资源限制或有限网络带宽的复杂通信环境中传输。MQTT已经成为IIoT通信中设备消息传递的事实标准,数百万设备利用其功能。 更近期,Sparkplug已经成为一项新的开放规范,当与MQTT一起部署时,它在成本节省、上市时间缩短、降低复杂性和提高生产力方面产生了数量级的业务益处。本文将重点讨论这些业务益处,强调采用MQTT/Sparkplug架构所产生的积极结果和投资回报率。虽然对这些部署的技术方面有一些一般性了解会有所帮助,但我们在本文中的目标是分享采用Sparkplug将如何积极影响您的业务,并帮助您更有效地竞争并降低成本。 什么是Sparkplug? Sparkplug是一种针对智能制造和工业物联网中提高MQTT互操作性的开源软件规范。该规范提供了操作技术(OT)数据的上下文,以便与信息技术(IT)以双向和互操作的方式进行无缝集成。更简单地说,Sparkplug可以使边缘到云或企业数据中心的数据标准化,以便用于创建本地统一命名空间,用于机器学习或其他IIoT应用程序。 MQTT有效地使得IIoT框架中的任何设备或系统能够连接到任何类型或型号的设备。然而,MQTT消息传递不提供有关其共享的信息的上下文。Sparkplug的添加为工业数据提供了必要的上下文,以便根据数据的需求采取特定类型的操作。借助MQTT和Sparkplug,任何应用程序或设备都可以订阅数据。新的数据源可以立即被其他系统组件发现,这些数据源可以成为整个系统可以采取操作的唯一真相来源。 Sparkplug架构可能如图2所示,具有在一侧产生数据的启用了Sparkplug的OT系统,中间是完全符合Sparkplug规范的MQTT代理以传输数据,另一侧是启用了Sparkplug的IT系统以消耗数据。数据可以双向流动,Sparkplug增加了有价值的上下文,包括MQTT主题结构定义、MQTT状态管理和负载数据定义。 图2:IIoT的新架构 因此,Sparkplug为工业组织提供了一些关键能力。首先,它标准化和定义了OT数据,以便所有订阅者都知道如何使用它,无需特殊编程或编码。这使得我们上面提到的“单一真相”成为整个组织的IIoT架构中的混淆消除,允许所有云和企业系统利用数据。 其次,Sparkplug使组织能够将设备连接到基础设施而不是应用程序。通过这样做,该规范为其他系统摄取数据为其目的铺平了道路。第三,Sparkplug为真正的、关键任务的IIoT应用程序奠定了基础,具有极高的可靠性和低延迟操作。没有这些特点,真正的IIoT是无法存在的。最后,Sparkplug实现了一个真正的、互操作的“即插即用”IIoT环境。不仅可以轻松分发消息,还可以为这些消息定义共同的含义,它们代表哪些设备以及应该如何处理它们。 让我们看看采用Sparkplug如何能积极影响您的业务。 通过开放标准避免供应商“锁定” 在一个自1978年以来一直采用相同控制和命令系统策略的市场中,OT-IT协作的出现应该为工业组织带来灵活 性的欢迎变化。几十年来,系统和应用程序的硬编码意味着公司不得不依赖于单一供应商。这些供应商可以有效地“锁定”他们的客户,因为移动的风险、成本和集成问题对大多数工业公司来说过于繁重。 通过由厂商中立的非营利组织(在Sparkplug的情况下是Eclipse基金会)管理的开放规范,工业组织现在可以轻松、具有成本效益地从硬编码的专用系统迁移到开放标准的世界。公司可以轻松升级标准化系统或更换其他解决方案。 将开放规范(如Sparkplug)和开源软件应用于工业制造领域将为从使用专有接口并在固定功能硬件上运行工作负载转向在商用现成硬件上运行的可互操作的工作负载的戏剧性变化奠定基础。这种转变将导致广泛可扩展的解决方案,生成支持工业部门更高级附加值解决方案的标准化数据。 通过应用这些新兴模型,制造商将能够实现以下目标: 由于Sparkplug的互操作性,可以访问更多的供应商来获取解决方案。 最小化工作和风险的情况下,从一代技术升级到下一代。 合并现有系统并降低总拥有成本(TCO)。 简化和降低运营支出。 更快速地部署创新。 这种规模的转变将需要不仅仅是Sparkplug规范本身。还需要全球生态系统的供应商和公司共同合作,以持续推动工业部门的发展。这个过程在Sparkplug创立时已经得以实施,因为它是由Eclipse基金会管理的开源项目,是世界上最大的专注于IIoT和边缘技术的开源软件基金会。Eclipse基金会在提供供应商中立的管理方面拥有几十年的经验,同时吸引了行业领袖和创新型初创公司提供对Sparkplug和其他技术的发展提供意见和指导。 弥合OT和IT之间的鸿沟 在其核心,IIoT是关于利用IT的低成本、创新和灵活性,同时保留OT系统的高可靠性。这个概念并不新鲜,但许多以前的努力来弥合鸿沟令人困惑,并且存在着对工业网络产生负面影响的技术障碍。没有Sparkplug提供的数据上下文,IIoT架构往往无法满足成功使OT和IT系统协同工作所需的关键的“最后几英尺”。 Sparkplug彻底改变了游戏规则。通过上下文定义工业用途和意图,使IT系统能够轻松“摄取”和“理解”OT数据,这是以前不可能的,需要工业组织进行复杂、漫长且有缺陷的编码工作。这意味着额外的成本,前提是组织可以找到开展该项目的开发人员人才。 一旦Sparkplug降低了连接IT和OT系统的障碍,它们可以相互通信,然后IT系统可以根据OT数据进行高级分析和建模。创建反馈环路并根据OT数据采取行动的能力,从而提供了导致更具成本效益的架构的IT的所有优点。一些这些新的能力包括: 实时数据分析:启用Sparkplug的架构使得能够对工业环境中每个系统和设备生成的数据进行细粒度的实时分析。 数字孪生:智能传感器数据可以用于运行模拟,然后再部署实际设备之前。 应用AI和机器学习:Sparkplug使得实现AI的潜力,以提供关于运营效率的实时见解,成为相对简单的任务。 远程监控和预测分析:由MQTT和Sparkplug从OT到IT传递的数据可以用于进行高级分析,提供关于机器操作的见解,甚至可以实现预测性维护。 健康与安全:Sparkplug使得能够为安全和健康的工作环境做出贡献。 高级无线技术:通过Sparkplug,现在可以使用多种用于推进供应链应用的移动技术,如5G、LoRA、Wi-Fi7。 灵活的架构:基于MQTT和Sparkplug构建的IIoT网络为组织提供了惊人的灵活性,可以灵活管理供应商和资源。 减少系统复杂性并轻松扩展 Sparkplug启用系统的另一个关键好处是减少整个系统部署的复杂性,既可以在每个站点轻松复制所需的软件,也可以减少为服务相同区域所需的站点数量。许多数据传输解决方案都启用了自定义代码来操纵数据,而无 法扩展。Sparkplug为工厂提供了一个开放的数据传输结构,其中多个产品和系统都支持Sparkplug,并可以定义和配置模板。组织可以使用自动发现和模板快速添加新设备或站点。 一家大型石油和天然气公司的自动化专家分享了如何利用Sparkplug为一个业务单位降低了复杂性,从而每年节省了130万美元的软件编程成本。该业务单位每年建设50个新设施。通过为每个设施简化系统架构开发,他们实现了财务节省,并加快了上市时间。 这位会计专家认为,这种节省的财务成本是保守估算的,主要是因为Sparkplug使“写一次,随处使用”的模型成为可能,从而加速了构建系统架构的时间价值。他的Sparkplug启用系统将开发人员将新对象(如油罐、泵等)整合到系统中的时间从30分钟减少到5分钟,使用MQTT Sparkplug,或是6倍的集成时间。没有MQTT Sparkplug,该公司需要支付系统集成商多次构建相同的对象,多达三次(POC、PLC和HMI级别),实际上每次都要重新发明轮子。 通过利用Sparkplug的功能,他的团队还可以在无需派遣人员到远程站点的情况下,立即呼叫所有泵或所有油罐,并在需要时确定它们的状态。这些相同的系统还可以通过使用预测分析来主动警告团队是否存在问题,以识别事件是否即将发生。 除了减少编程时间外,Sparkplug系统还可以减少整个系统中的1:1关系的数量,降低了同时维护数十个站点的工作量。总的来说,这位自动化和IIoT专家通过Sparkplug系统将超过50个站点的总成本每年节省了260万美元以上。 实现关键任务的系统 Sparkplug对于实现具有低延迟架构的关键任务OT系统至关重要。Sparkplug的互操作的“即插即用”能力以及作为真相的单一来源的能力使得复杂的边缘计算架构成为现实。边缘计算将数据和计算智能放置在与其交互的物理对象附近,从而减少了系统的延迟,使反应更加迅速,性能更好。在工厂车间中,Sparkplug启用的架构可以比传统的OT系统更快地处理数千兆字节的数据,并且成本更低。从运营到预测性维护等,这种架构使企业能够比将信息批量传输并将其发送到其他地方进行处理的情况下采取更快的行动。 结论 Sparkplug的使用正在跨足众多行业。主要的汽车、制造、工业、石油和天然气以及供应链/物流公司正在利用其能力。云超大规模供应商正在积极利用这一规范来构建针对行业市场的新托管服务。这意味着如果您的竞争对手尚未使用Sparkplug,他们可能正在积极评估将其集成到其环境中。IIoT World最近进行的一项调查问及正在构建IIoT系统的公司认为哪些数据传输工具对于实现他们的IIoT战略至关重要。55%的回答是MQTT,令人印象深刻的25%回答是MQTT Sparkplug,巩固了这一相对新技术作为公司数字转型和IIoT项目的关键组成部分。 图3:许多部署IIoT的公司认为MQTT和Sparkplug至关重要 随着一个强大且开放的生态系统支持这项技术的发展,并且市场对其部署的广泛支持,Sparkplug应该成为您未来IIoT部署计划的重要组成部分。鉴于其益处,Sparkplug可以并将为您的组织带来竞争优势。 --- ### 276. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Sparkplug 规范中涉及 MQTT Broker 的 5 个关键概念 在现代工业领域,物联网技术的广泛应用已经成为了提高生产效率、降低成本以及增强设备之间通信能力的关键。而为了实现这些目标,Sparkplug 规范应运而生。它不仅是一种开放源代码的软件规范,还是MQTT(Message Queuing Telemetry Transport)协议的强大增强工具,旨在改进工业物联网(IIoT)通信。在本文中,我们将深入探讨Sparkplug规范中的MQTT Broker的5个关键概念。 1. MQTT 主题命名空间: Sparkplug 规范引入了MQTT主题命名空间的概念,这是为了实现工业物联网的最优化。它的核心思想是为不同设备和系统提供一个统一的命名规则,使它们能够更轻松地共享数据。这种命名约定的一致性简化了设备之间的数据交换,无论这些设备来自不同的制造商或具有不同的功能,都能实现高度互操作性。 2. MQTT 状态管理: Sparkplug 规范中的MQTT状态管理旨在最大程度地利用连续会话感知。这意味着即使在网络连接断开的情况下,设备也能够与MQTT Broker保持连接,降低了宕机和数据丢失的风险。对于工业应用来说,这个特性非常关键,因为它确保了设备之间的持续通信,即使在不稳定的网络条件下也是如此。 3. MQTT 有效负载: Sparkplug 规范中MQTT有效负载的定义确保了数据的一致性和可靠性。通过标准化有效负载,不同设备和系统之间能够共享和解释数据,从而简化了集成过程,提高了互操作性。这种标准化还有助于确保数据被正确地传递和解释,从而减少了潜在的错误。 4. 开放标准与自由工具: Sparkplug 是一个开放的标准,可供任何人使用。越来越多的设备制造商开始支持Sparkplug,这意味着它可以内置于OT层的设备上。这降低了采用门槛,鼓励创新,减少了对特定供应商的依赖。工程师和开发者可以自由选择与其工作流程和需求最匹配的工具,而不必受限于特定的封闭标准。 5. 无需全新基础设施: 具备MQTT和Sparkplug B的SCADA平台使IIoT项目更加经济高效。最重要的是,这些工具不需要对整个基础设施进行大规模更改。它们能够在现有OT和IT系统之间实现恒定的数据流,从而节省了时间和金钱。这种无缝集成的能力使企业能够更快地采用IIoT技术,而无需担心繁琐的基础设施升级。 总结而言,Sparkplug 规范通过优化MQTT协议的使用,提高了工业物联网的效率和安全性,降低了IIoT项目的复杂性和成本。这五个关键概念使Sparkplug成为实现工业物联网互操作性的有力支持者,为设备和系统之间的数据交流铺平了道路。在现代工业中,Sparkplug规范正在为更高效、更具竞争力的生产奠定坚实的基础。 扩展阅读: OT(Operational Technology):这通常指的是用于监控和控制实际物理过程的技术和系统,例如在工厂、制造业和工业环境中使用的设备和自动化系统。OT 包括传感器、PLC(可编程逻辑控制器)、SCADA(Supervisory Control and Data Acquisition)系统等,用于管理和控制物理过程。 IT(Information Technology):这是通常与计算机系统、网络和数据处理相关的技术领域。IT 用于处理和管理数字数据、信息和通信。在工业物联网环境中,IT 技术通常与云计算、数据分析、网络通信等相关,用于处理从OT系统中收集到的数据以及与其他系统进行集成和通信。 在工业物联网(IIoT)项目中,将OT和IT整合在一起是非常关键的,以实现实时数据收集、分析和决策,从而提高生产效率和监控工业过程。 --- ### 277. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 当我们比较工业通信中常用的技术,如OPC-UA、HTTP、Modbus、MQTT和Sparkplug,通信效率是一个关键的考量因素。在这篇文章中,我们将从几个通信标准的角度来进行比较,这些标准会影响传输带宽的利用。 连接开销:连接开销是建立通信连接所需的开销,包括握手、协议开销等。在这方面的比较如下: OPC-UA:OPC-UA连接的建立较为复杂,需要多个步骤,包括握手、安全协商和会话创建,因此连接开销较高。 Modbus:Modbus的连接开销很低,因为它不需要复杂的握手或会话管理,通常只涉及网络连接和设备寻址。 HTTP:HTTP的连接开销较高,每个HTTP请求-响应周期通常需要建立新的连接,涉及握手、头部交换和会话管理等额外开销。 MQTT:MQTT设计简单高效,连接开销较低,使用二进制协议和小型头部,减少了连接和维护的数据量。 Sparkplug:Sparkplug与MQTT相比,引入的额外开销较小,因为它主要定义了有效载荷格式和数据表示,而没有改变连接行为。 连接持久性:连接持久性涉及连接建立后需要保持连接的开销,以及连接的稳定性。在这方面的比较如下: OPC-UA:OPC-UA支持客户端-服务器模型,可以选择持久或非持久连接。 Modbus:Modbus通常不使用持久连接,每个请求都会建立一个连接。 HTTP:HTTP是无状态协议,每个HTTP请求-响应周期都是独立的,默认情况下不保持连接活动。 MQTT:MQTT使用持久连接模型,可以长期保持连接,提供保活和自动重连功能。 Sparkplug:Sparkplug基于MQTT,继承了MQTT的连接特性,支持持久连接。 数据变化:数据变化机制涉及是否支持“变化时传送”,即只在数据变化时传输数据,以减少不必要的数据传输。在这方面的比较如下: OPC-UA:OPC-UA通过订阅模型支持“变化时传送”机制,只在订阅的数据变化时发送更新。 Modbus:Modbus不支持内置的数据变化传送机制,主要提供直接访问数据点的功能。 HTTP:HTTP本身不支持“变化时传送”,但可以在应用层使用长轮询或服务器发送事件(SSE)等技术来实现。 MQTT:MQTT并没有内置“变化时传送”机制,但可以与其他协议或应用逻辑配合使用,以实现该功能。 Sparkplug:Sparkplug原生支持“变化时传送”机制,定义了标准有效载荷格式,只在数据值变化时发送更新。 数据压缩:数据压缩涉及在传输中减小数据大小,以提高传输效率。在这方面的比较如下: OPC-UA:OPC-UA使用的数据传输格式通常不支持数据压缩,而且压缩率较低。 Modbus:Modbus不支持数据压缩,侧重于简单高效的数据传输。 HTTP:HTTP支持内容编码等特性,可以在应用层进行数据压缩。 MQTT:MQTT不包含内置的数据压缩,但可以与其他压缩技术或库结合使用。 Sparkplug:Sparkplug采用Google Protobuf作为数据格式,具有一定的压缩能力。 综上所述,不同的技术在连接开销、连接持久性、数据变化和数据压缩方面有不同的特点。对于工业场景,Sparkplug协议在多个方面都表现出色,特别适合高效的数据传输和变化时传送。 --- ═══════════════════════════════════════════ ## Sparkplug® v3.0.0规范 ═══════════════════════════════════════════ ### 278. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT 的一个突出特点,使其在许多行业中获得广泛接受,是它允许使用任何格式来创建分层主题路径。例如,在一个乳品制造企业中,可以使用 DairyPlant01/Refrigerator03/DischargePressure 作为自定义的主题命名空间。 尽管这种灵活性允许您根据需要定义 MQTT 主题结构,但在扩展或集成不同系统时,由于缺乏标准化方法,它也带来了挑战。更在工业物联网(IIoT)或 SCADA 网络中,通常存在嵌套设备、资产和系统的复杂工业设置。 IIoT 中不同 MQTT 主题格式的挑战 以下是由于缺乏系统化和一致的 MQTT 主题命名格式而引入的一些挑战: IT-OT 互操作性挑战 使用不同 MQTT 主题结构的不同设备和应用程序很难集成到统一系统中。这导致来自不同供应商或工业操作的不同业务部门的数据交流和通信困难。 可扩展性问题 随着设备或主题数量的增长,配置、管理和监控大量非标准化 MQTT 主题结构的网络变得越来越复杂。这通常导致扩展能力降低,并增加了集成成本。 数据不一致性 如果设备或发布者使用不同的主题结构或命名约定,可能会对数据的来源或类型产生歧义,导致潜在的数据不一致性。在 IIoT 或 SCADA 系统中,数据的误解读或错误路由可能导致操作问题甚至安全问题。 IIoT 中标准化 MQTT 主题命名空间的好处 为了减轻上述许多挑战,MQTT Sparkplug 规范定义了用于 IIoT 网络的标准 MQTT 主题格式。通过提供标准化的主题命名空间定义,MQTT Sparkplug 帮助创建了一个更一致、有组织且互操作性更强的 MQTT 基础 IIoT 和操作数据系统环境。这使得部署、管理和扩展这些系统变得更加容易,同时确保数据易于访问和理解。 使用 Sparkplug 的标准主题命名空间定义,遵循 Sparkplug 规范的设备和系统可以无需任何额外配置或转换即可相互通信。此外,Sparkplug 的主题命名空间提供了数据的一致性和逻辑性组织,确保相似的数据点被分组在一起,数据易于定位。 随着越来越多的设备和系统采用 Sparkplug 规范,集成变得更简单。系统可以使用一套标准规则和逻辑进行集成,而不是为每个独特的主题结构定制集成。 通过标准化主题结构,更容易实施精细化的安全和访问控制措施。例如,可以根据主题命名空间的特定部分授予权限,确保设备和用户只能访问他们被授权查看的数据。 MQTT Sparkplug 主题命名空间的组成部分 为了提供一种结构化的方式,确保信息在 IIoT 环境中易于路由、理解和操作,Sparkplug 将 MQTT 主题命名空间细分为特定组成部分。因此,Sparkplug 主题命名空间的结构化特性如下所示: spBv1.0/[Group ID]/[Message Type]/[EON Node ID]/[Device ID] 以下是 MQTT Sparkplug 主题命名空间组成部分的详细说明: 命名空间 这始终以“spBv1.0”开头,表明该主题使用 Sparkplug B 版本 1.0 规范。这作为所使用协议版本的标识符,以及相关有效载荷数据的编码。 组号 这标识了网络边缘(EoN)节点和设备的逻辑分组。例如,您可能使用组 ID 来表示特定的工厂或工厂位置。它确保在不同组之间的数据隔离,有助于高效的数据管理和安全性。 消息类型 主题命名空间的消息类型组件指示如何处理 MQTT 有效载荷。以下消息类型组件为 Sparkplug 主题命名空间定义: NBIRTH:边缘节点出生证书。这是来自 EoN 的启动消息,用以宣告其存在并分享其配置。 NDEATH:边缘节点断开连接或故障的通知。 DBIRTH:设备出生证书。类似于 NBIRTH,但针对设备,宣告它们的存在和配置。 DDEATH:设备断开连接或故障的通知。 NDATA:来自边缘节点的数据消息。这些通常包括度量数据。 DDATA:来自设备的数据消息。类似于 NDATA,但专门针对设备相关度量。 NCMD:对边缘节点的命令。 DCMD:对设备的命令。 STATE:代表主机应用程序的状态。边缘节点订阅它以获取主机的在线状态。 网络边缘(EON)节点 ID 这唯一地标识了同一组中 EoN 中的特定边缘节点。EON 节点负责代表其控制或连接的设备报告数据。EON 节点 ID 有助于将命令定向到正确的节点,并将来自各种节点的数据进行分离。 设备 ID(可选) 如果消息与边缘节点控制的特定设备有关,设备 ID 将唯一地标识该设备。 下表显示了 MQTT Sparklug 主题命名空间每个组成部分的示例描述和示例。 NameDescriptionExamplenamespaceRoot element to set the sparkplug versionspBv1.0group_idLogical grouping of MQTT edge nodesFactoryAmessage_typeSpecific message typeNBIRTHedge_node_idID of a specific edge nodeProductionLine03device_idID of a specific device tied to an edge nodeSeatAssembly_PLC spBv1.0/FactoryA/DDATA]/ProductionLine03/SeatAssembly 需要注意的是,由组 ID 和边缘节点 ID 组合而成的边缘节点描述符在 MQTT Sparkplug 网络中的所有边缘节点之间必须是不同的。这意味着 Sparkplug 设置中的两个边缘节点不能共享相同的组 ID 和边缘节点 ID。 Sparkplug 边缘节点布局 在实际场景中实施 Sparkplug 主题命名空间 让我们看看 MQTT Sparkplug 主题命名空间定义在实际场景中的好处示例。 例如,在智能制造设施中,每条生产线可能包括许多机器,每台机器都生成温度、运行时间和错误率等度量数据。使用 Sparkplug 的主题命名空间,这些机器的消息可以被轻松地路由和分类。一个诸如 spBv1.0/FactoryA/DDATA/Line3/Machine7 的主题立即提供了关于消息来源和性质的上下文,确保监控工具、控制系统和操作员可以快速处理并对数据采取行动。 此外,Sparkplug 的主题命名空间不仅仅是高效的路由;它在系统诊断和故障排除中发挥着关键作用。例如,在能源领域,拥有多个面板的太阳能发电厂可以从 Sparkplug 的结构化消息传递中获益匪浅。如果面板发生故障,主题为spBv1.0/SolarFarmB/NDEATH/PanelArray5/Panel23的消息将立即通知操作员,不仅会出现问题,还会通知其在基础设施中的确切位置。Sparkplug 的主题命名空间使通信的粒度和清晰度成为可能,这在现实场景中非常宝贵,在现实场景中,快速响应时间可以带来显着的节省和更安全的操作。 结论 总结来说,MQTT Sparkplug 是一个旨在确保使用 MQTT 协议通信的设备、应用程序和服务之间的互操作性的规范,特别是在工业自动化领域。Sparkplug 中定义的主题命名空间在提供标准化的主题结构方面起着关键作用,这确保了跨各种设备和系统的一致数据表现、简化的设备命令和控制,以及改进的状态管理。 通过遵守 Sparkplug 主题命名空间,供应商和系统集成商可以无缝集成设备和软件解决方案,从而减少集成工作并确保 MQTT 基础 IIoT 部署中更可预测和可靠的通信。 --- ### 279. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Sparkplug 使用发布/订阅(Pub/Sub)架构模式,为可扩展且高效的通信提供了解决方案,这与过去40多年来工业自动化、离散制造业及石油和天然气行业中使用的传统轮询/响应协议截然不同。这意味着过去几十年的通信协议需要数据生产者(通常是 PLC)和数据消费者之间非常紧密的耦合。这种耦合使得改变工作流程和流程变得困难,使得建立新的系统和设施变得困难,并且使得在整个系统中使用和分析数据变得困难甚至不可能。 图1:轮询/响应方式 图 1 显示了从 PLC、网关和应用程序获取数据的传统轮询/响应方式。轮询系统向生成数据的设备请求数据,或者是特定数据的单一来源。为了尽快获取数据,轮询系统会以非常高的频率请求数据,否则新数据将无法及时提供给需要该数据的系统。这种方法效率非常低,因为它非常浪费带宽和处理能力。 在本次演示中,比较了 MQTT、OPC-UA 和 Modbus,并表明即使对于基本场景,使用 MQTT Sparkplug 与 OPC-UA 相比,效率也有数个数量级的提升。可以在此处找到演示文稿。如果您想通过加密通信来增加安全性(如果您通过互联网连接设备,则必须这样做),那么与 Sparkplug 相比,旧协议产生的开销甚至更大。 图 2 描述了系统需要对每个新的数据生产者进行轮询。这意味着在最坏的情况下,每个标签都需要单独轮询。 图2:众多制造者的轮询/响应 这种轮询方法在行业中广泛使用,特别是在Modbus和OPC-UA等协议中。数据产生的指数级增长以及工厂本地和全球范围内的超连接性显示了轮询/响应方法的局限性。如今,公司需要即时获取全球数百家工厂和数千台机器生成的数据,并希望所有利益相关者都能轻松访问重要数据,无论他们身在何处。行业现在终于迈向了一个必须打破数据孤岛的世界。 从技术角度来看,与现代发布/订阅方法相比,轮询/响应有一些严重的缺点: 无状态意识,大多数 IIoT 协议都无法感知状态,这意味着需要始终轮询状态,有时每个设备每秒轮询多次,以确保不会丢失重要数据或状态更改。 大量不必要的数据流量,即使没有发生状态更改或数据更改,数据生产者也会每秒被轮询多次。 仅定期检查新数据,没有基于即时推送的机制来获取发生的数据和事件。 轮询设备上的计算密集型,大量不必要的计算周期被浪费,因为即使数据没有改变,数据也会一直被请求。 轮询组件和轮询组件之间的紧密耦合。如果需要更改/更换数据生产者,则需要重新配置多个系统,可能会导致停机。 无法扩展到大量数据生产者。 显然有更好的方法。这就是为什么 MQTT Sparkplug 从一张白纸开始,并提出了这样的问题:“如果我们可以使用最轻量级的通信协议(MQTT),并结合过去 40 多年的经验教训,弥合 OT/IT 差距,实现即插即用的互操作性,那会怎样?” 为了克服传统协议的缺点,Sparkplug 使用基于现代发布-订阅的架构,如图 3 所示。 图3:发布/订阅架构 这种基于 MQTT 的架构具有以下优点: 异常报告:仅当发生变化时才发布数据和状态。 最小化计算密集度:设备和应用程序自行决定何时发送数据,并且不会不必要地浪费计算周期。 通过单个代理(集群)可扩展到数十万甚至数百万台设备,每天处理数十亿个标签数据和状态变化。 基于推送的通信。 完全解耦。要更改、添加或删除数据消费者或生产者,无需更改其他组件。 MQTT Sparkplug 在大多数行业中越来越受欢迎,可以用其相对于传统协议的明显优势来解释,甚至能够将这些传统协议集成到 Sparkplug 架构中。 --- ### 280. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 典型的工业物联网(IIoT)架构通过轮询/响应方式来连接各个组件。应用程序会直接从PLC、网关或服务器中通过诸如Modbus、西门子S7协议或OPC-UA等协议轮询数据。这种方法在只有少数几个系统需要集成时效果不错,但随着组件数量的增加,会导致一个难以维护的复杂架构。 图片1:未采用Sparkplug的工业IIoT架构 在这种架构中,系统通过点对点方式连接,从而使系统和数据紧密耦合在一起。现代的架构需要在IIoT系统中实现灵活性和清晰的职责分离。许多公司期望在IT环境中找到适应性、灵活性和易于实施的特性,同时也需要满足OT环境对可靠性、安全性和可预测性的需求。这种变革需要一种全新的架构。 图片2:IIoT的新架构 这种新的IIoT架构(如图片2所示)相较于传统IIoT架构有所优势: 数据生产者和消费者之间的解耦。 异常报告(RBE),节省了数据生产者和消费者的带宽、内存和计算能力。 一对多通信。数据只需发送一次,多个接收方就可以接收数据。 灵活性:设备和应用程序可以随时添加或移除,而不会影响整个系统。 通过集中的权限和策略处理实现数据治理。 通过从云到边缘的数据分发实现车间到云端的连接。 过去,许多公司已经采用MQTT来为其工厂创建解耦架构。这并不令人意外,因为MQTT最初是为SCADA系统设计的。但在IIoT用例中,仍然缺少一些部分,例如MQTT主题结构定义、MQTT状态管理和有效载荷数据定义。Sparkplug为MQTT增加了这些功能,通常情况下Sparkplug架构类似于图片3所示。 图片3:Sparkplug架构 原则与机制 Sparkplug架构之所以比传统方案更加优雅,是因为它基于以下原则和机制: 发布/订阅:使用MQTT作为底层应用的发布/订阅架构,从而解耦了数据的生产者和消费者。MQTT基于推送通信机制,这意味着数据会立即传递给所有感兴趣的各方。 异常报告:只有在数据和设备状态发生变化时才更新,从而在所有组件上大幅节省带宽和计算能力,因为只有新的和更新的数据才会被发送。 持续会话感知:Sparkplug和MQTT具备持续会话感知的特性。如果设备的在线/离线状态发生变化,它会通知所有关心这一状态的客户端。这个机制还确保了数据在传输过程中的连续性,比如当设备从离线状态恢复到在线状态时,数据传输会继续进行。使用Sparkplug,您可以实时准确地监控部署中所有设备、网关和应用程序的状态。 死亡和出生证明:Sparkplug引入了用于管理和发现设备状态的死亡和出生证明机制 。出生证明包含了有关设备及其将要发送的数据的信息,而死亡证明则利用MQTT的遗嘱和遗言机制来向所有关心的应用程序推送设备离线信息。 持久连接:所有设备、网关和应用程序默认保持在线,并通过持久的TCP连接进行通信。 自动发现:应用程序和设备能够自动发现Sparkplug部署中所有参与者将要发送的数据(及其对应的主题),以及当前连接的在线/离线设备。 标准化有效载荷定义:Sparkplug消息中所有消息的数据格式都进行了标准化,使得所有通信参与者都可以解码和编码数据。 标准化主题命名空间:所有Sparkplug参与者使用相同的主题命名空间。这个主题命名空间允许对特定数据进行精确的订阅,并支持动态地添加或移除参与者。 组件 Sparkplug充分认识到在任何复杂的IIoT场景中,都会涉及不同类型的设备/传感器、网关、应用程序以及其他软件(和硬件)。因此,Sparkplug为架构中的不同类型参与者定义了各自的行为和语义。 传统的Sparkplug架构包括以下组件: SCADA / IIoT主机 网络边缘(EoN)节点 设备/传感器 MQTT应用节点 MQTT代理 我们现在将对这些组件进行详细的解读。 SCADA / IIoT主机 SCADA / IIoT主机,有时也被称为主应用程序,是负责监控和控制MQTT EoN节点及其所连接的设备和传感器的监督性应用程序。IIoT系统的持续会话状态感知是至关重要的,这意味着所有参与者(包括机器、设备、PLC、传感器、网关和应用程序)的当前状态随时都需要在中心位置进行监控。管理状态并根据状态变化采取行动的中心应用程序就是SCADA / IIOT主机应用程序。它是系统操作员用于管理和监督整个系统健康状况的关键应用程序。 与大多数传统的SCADA系统架构不同,SCADA / IIoT主机并不负责直接建立和维护与设备的连接。在Sparkplug架构中,设备、EoN节点和SCADA / IIoT主机都连接到中心MQTT代理,并通过发布和订阅数据进行通信。这样的设计允许仅在数据发生变化时进行更新,从而实现了异常报告(RBE)功能。 网络边缘(EoN)节点 网络边缘(EoN)节点在任何Sparkplug系统中都扮演着关键角色。EoN节点通常提供物理或逻辑上的网关功能,使那些不直接实现Sparkplug的传感器或设备能够参与到MQTT主题命名空间中。EoN节点负责管理自身以及通过诸如OPC-UA、Modbus、专有PLC供应商协议、HTTP、MQTT或本地离散I/O等协议连接到该EoN节点的传感器和设备的状态和会话。EoN节点负责管理这些连接设备和传感器的生命周期和状态,以及接收和发送设备数据到Sparkplug基础设施中。EoN节点是任何Sparkplug基础设施中的关键组成部分,它们通常被用于将传统的基础设施与Sparkplug桥接。 设备/传感器 设备和传感器构成了工业自动化的核心。一个设备通常是一个实体或逻辑上的单元,它通过一个或多个工业通信协议来发送和/或接收数据。这些工业协议一般基于轮询/响应机制。在Sparkplug的上下文中,设备通过EoN节点连接到Sparkplug基础设施中。EoN节点将MQTT Sparkplug的发布/订阅机制桥接到这些轮询/响应协议上。 支持MQTT的传感器和设备 尽管大部分设备和传感器采用像Modbus、OPC-UA、Beckhoff ADS等标准化和专有协议,但许多厂商为其设备和传感器提供了原生的MQTT支持。如果一个MQTT支持的设备已经配备了Sparkplug功能,通过提供适当的数据格式和主题结构,那么该设备可以直接与Sparkplug基础设施交互。在这种情况下,该设备将作为EoN节点被Sparkplug基础设施识别。如果MQTT设备仅支持标准的MQTT而没有Sparkplug意识,那么它仍然需要通过EoN节点来连接。 MQTT应用节点 MQTT应用节点是参与Sparkplug通信的节点,可以产生和消费消息,但它们不是SCADA / IIoT主机。这些通常被称为辅助应用程序。它们通常是提供专门功能的软件系统,例如MES(制造执行系统)、历史数据分析等。许多部署也会使用定制软件来满足特定用例的需求,这些软件需要消费由其他Sparkplug参与者产生的数据。 MQTT代理 MQTT代理是中心数据分发组件。所有启用Sparkplug的设备、EoN节点、SCADA / IIoT主机和MQTT应用都通过MQTT连接到代理。代理负责处理认证、授权、参与者状态管理以及在Sparkplug启用系统间的数据分发。MQTT代理需要100%兼容MQTT 3.1.1标准,因为需要支持保留消息、遗嘱和遗言以及QoS等功能。 --- ### 281. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 工业物联网(IIoT)和工业4.0是制造业中的关键趋势。车间操作员寻求提高运营效率、实现小批量生产,并获得实时制造洞察。然而,传统的软件和硬件栈通常是封闭和专有的,互操作性并不是供应商的主要关注点。像OPC-UA这样的协议虽然承诺为设备、机器和软件应用之间提供通用的行业语言,从而打破孤立,但现实却是,对于大多数开发人员和软件架构师来说,OPC-UA并不像人们所希望的那样是解决所有问题的万能药。它非常复杂和笨重,尤其是在大多数制造项目中常见的棕地环境下,集成OPC-UA并不容易。因此,人们开始寻找更好的方法。 与此同时,通过MQTT协议,设备到云的通信在最小化延迟和最大化吞吐量方面变得非常简单。许多开发人员期望有类似于MQTT的简单解决方案,但又能满足制造业的特定需求,如有效载荷定义和跨机器及供应商的统一消息行为。 这一愿望得以实现,当基于MQTT的Sparkplug协议由MQTT的创始人之一Arlen Nipper首次发布时。Sparkplug规范迅速在整个行业中流行起来,像雪佛龙(Chevron)这样的大公司采用它以提高运营效率,并创造下一代制造解决方案。 那么,Sparkplug究竟是什么呢? Sparkplug是一个开源软件规范,它为MQTT客户端提供了一个框架,使其应用、传感器、设备和网关能够在MQTT基础设施中无缝、双向、互操作地集成数据。为了为IIoT提供通用语言,Sparkplug规范定义了三个目标:定义MQTT主题命名空间、MQTT状态管理和MQTT有效载荷。值得注意的是,Sparkplug实际上被设计为完全运行在MQTT上,因为MQTT的发布/订阅模式允许系统的所有组件进行双向和解耦的集成。当1999年MQTT被发明时,它最初是为SCADA系统设计的,但没有具体规定主题和有效载荷的结构以及设备的行为方式。这使得MQTT可以在不同的行业中使用,如智能汽车、物流和智能制造。现在,Sparkplug填补了这个空白,并为IIoT场景中的数据格式、主题结构、状态管理和拓扑结构提供了一个厂商中立的规范。 那么,Sparkplug与纯粹的MQTT有何不同? Sparkplug是专为基于MQTT的工业物联网应用设计的。许多供应商的PLC(例如西门子S7)以及大多数制造执行系统(MES)和SCADA系统(如感应自动化®的Ignition SCADA)支持MQTT。当然,大多数专业网关解决方案也支持MQTT。 总结 加入Sparkplug的原因在于,对于非Sparkplug的MQTT通信,需要确保所有感兴趣的参与者知道在哪里订阅数据,并且能够解释数据。这通常涉及到数据转换,需要约定,从而在所有应用之间创建紧密耦合。而使用Sparkplug,所有参与者都会就一种共同的数据格式达成一致,明确如何接收特定数据,如何发布他们的数据,以及如何解释数据。更好的是,Sparkplug还允许集成来自非MQTT设备的数据以及其他协议(如OPC-UA或Modbus)的数据。我们还可以从中获得所有这些设备和应用的自动发现功能。 --- ### 282. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Sparkplug 是一个规范,由 Eclipse Sparkplug 提供,旨在定义如何在 MQTT 基础设施内进行双向通信。它主要针对边缘网络网关(Sparkplug 边缘节点)或原生支持 MQTT 的终端设备以及 Sparkplug 主机应用程序。Sparkplug 规范的目的是为 SCADA/IIoT 解决方案领域确定和文档化一个经过深思熟虑且经过优化的主题命名空间。此外,Sparkplug 以一种方式定义了一个主题命名空间,使其提供语义,允许系统中的 MQTT 客户端自动发现并进行双向通信。 Sparkplug 还定义了 MQTT 的状态管理,以充分利用 MQTT 的原生连续会话感知能力,特别是针对实时 SCADA/IIoT 解决方案。此外,Sparkplug 规范旨在定义有效载荷编码机制,这些机制保持了 MQTT 的原始、轻量级、带宽高效、低延迟特性,同时添加了针对 SCADA/IIoT 解决方案空间的现代编码方案。 总的来说,Sparkplug 规范为 MQTT 提供了一个明确的框架,使其更适合实时 SCADA 和 IIoT 应用。 2023100113392958下载 --- ═══════════════════════════════════════════ ## Zigbee2MQTT ═══════════════════════════════════════════ ### 283. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在智能科技的风潮中,通过Zigbee MQTT技术,你可以将小米蓝牙插座和支持Zigbee的设备变得更加智能化。以下是一步步的指南,教你如何完成这个令人兴奋的DIY智能家居项目。 硬件准备: 首先,确保你拥有以下硬件设备: 小米蓝牙插座(型号:Xiao Mi Zigbee ZNCZ02LM)或其他支持Zigbee的插座或设备。 Zigbee设备(型号:CC2531设备)。 可以参考以下链接获取更多信息: Zigbee2MQTT项目主页:https://github.com/Koenkk/zigbee2mqtt Zigbee2MQTT官方文档:https://www.zigbee2mqtt.io/ CC2531设备识别并安装pyCCSniffer: 插入CC2531设备,并在终端中输入以下命令查看设备是否被识别:lsusb 使用pyCCSniffer工具进行数据嗅探,确保CC2531设备被正确识别。你可以在https://github.com/andrewdodd/pyCCSniffer.git获取该工具。 查看usb设备, 插入CC2531设备后 lsusb 显示CC2531设备 Bus 001 Device 003: ID 0451:16ae Texas Instruments, Inc. cd /opt git clone https://github.com/andrewdodd/pyCCSniffer.git cd pyCCSniffer python pyCCSniffer.py apt install python-pip pip install future pip install pyusb 安装失败,升级pip就成功了: Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-4hIAE4/pyusb/ pip install libusb pip install --upgrade pip pip install pyusb 成功显示 python pyCCSniffer.py CC2531 USB Dongle <Channel: 11> ------------------------------- Commands: c: Print current RF Channel h,?: Print this message [11,26]: Change RF channel s: Start/stop the packet capture d: Toggle frame dissector a*: Set an annotation (write "a" to remove it) p: Print all capture packets q: Quit python pyCCSniffer.py -L /root/zigbee.log -D INFO 输入s 没有这个目录 ls -l /dev/ttyACM0 ls -l /dev/bus/usb/001/003 拔掉之后就没有了 ls -l /dev/bus/usb/001/005 lsusb 换了一个CC2531设备后 Bus 001 Device 004: ID 0451:16a8 Texas Instruments, Inc. 就有这个目录了 ls -l /dev/ttyACM0 ls -l /dev/bus/usb/001/004 安装Zigbee2MQTT: 首先安装Node.js和相关依赖:sudo curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -,然后sudo apt-get install -y nodejs git make g++ gcc 克隆Zigbee2MQTT项目到/opt目录:sudo git clone https://github.com/Koenkk/zigbee2mqtt.git /opt/zigbee2mqtt 进入项目目录:cd /opt/zigbee2mqtt,然后安装依赖:npm ci 配置Zigbee2MQTT:编辑配置文件vim /opt/zigbee2mqtt/data/configuration.yaml,在advanced下添加network_key: GENERATE 安装依赖并启动:npm install,然后npm start 安装Zigbee2MQTT sudo curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash - sudo apt-get install -y nodejs git make g++ gcc node --version npm --version sudo git clone https://github.com/Koenkk/zigbee2mqtt.git /opt/zigbee2mqtt cd /opt/zigbee2mqtt npm ci vim /opt/zigbee2mqtt/data/configuration.yaml advanced: network_key: GENERATE npm install 启动 npm start > zigbee2mqtt@1.21.1 start /opt/zigbee2mqtt > node index.js Zigbee2MQTT requires node version ^10 || ^12 || ^14 || ^15 || ^16, you are running v8.10.0! Zigbee2MQTT:info 2022-09-30 14:38:47: Logging to console and directory: '/opt/zigbee2mqtt/data/log/2021-09-30.14-38-45' filename: log.txt Zigbee2MQTT:info 2022-09-30 14:38:47: Starting Zigbee2MQTT version 1.21.1 (commit #4a51e0c0) Zigbee2MQTT:info 2022-09-30 14:38:47: Starting zigbee-herdsman (0.13.138) Zigbee2MQTT:info 2022-09-30 14:38:51: zigbee-herdsman started (resumed) Zigbee2MQTT:info 2022-09-30 14:38:51: Coordinator firmware version: '{"meta":{"maintrel":3,"majorrel":2,"minorrel":6,"product":0,"revision":20190608,"transportrev":2},"type":"zStack12"}' Zigbee2MQTT:info 2022-09-30 14:38:51: Currently 0 devices are joined: Zigbee2MQTT:warn 2022-09-30 14:38:51: `permit_join` set to `true` in configuration.yaml. Zigbee2MQTT:warn 2022-09-30 14:38:51: Allowing new devices to join. Zigbee2MQTT:warn 2022-09-30 14:38:51: Set `permit_join` to `false` once you joined all devices. Zigbee2MQTT:info 2022-09-30 14:38:51: Zigbee: allowing new devices to join. Zigbee2MQTT:info 2022-09-30 14:38:51: Connecting to MQTT server at mqtt://localhost Zigbee2MQTT:info 2022-09-30 14:38:52: Connected to MQTT server Zigbee2MQTT:info 2022-09-30 14:38:52: MQTT publish: topic 'zigbee2mqtt/bridge/state', payload 'online' 成功连接小米插座: 使用MQTT工具连接服务,例如:mqtt://localhost。你可以使用MQTTX等工具监听相应的topic。 将小米插座按下按钮5秒左右,观察终端日志,确保设备成功加入。 Xiao Mi zigbee ZNCZ02LM 设备按下按钮5秒左右, 灯闪烁,日志打印: Device '0x00158d00012ccbc2' joined 成功加入 Zigbee2MQTT:info 2022-09-30 14:39:29: Device '0x00158d00012ccbc2' joined Zigbee2MQTT:info 2022-09-30 14:39:29: MQTT publish: topic 'zigbee2mqtt/bridge/event', payload '{"data":{"friendly_name":"0x00158d00012ccbc2","ieee_address":"0x00158d00012ccbc2"},"type":"device_joined"}' Zigbee2MQTT:info 2022-09-30 14:39:29: Starting interview of '0x00158d00012ccbc2' Zigbee2MQTT:info 2022-09-30 14:39:29: MQTT publish: topic 'zigbee2mqtt/bridge/event', payload '{"data":{"friendly_name":"0x00158d00012ccbc2","ieee_address":"0x00158d00012ccbc2","status":"started"},"type":"device_interview"}' Zigbee2MQTT:info 2022-09-30 14:39:29: MQTT publish: topic 'zigbee2mqtt/bridge/event', payload '{"data":{"friendly_name":"0x00158d00012ccbc2","ieee_address":"0x00158d00012ccbc2"},"type":"device_announce"}' Zigbee2MQTT:info 2022-09-30 14:39:30: MQTT publish: topic 'zigbee2mqtt/0x00158d00012ccbc2', payload '{"consumption":0,"energy":0,"linkquality":81,"power":0,"state":"ON","temperature":38}' Zigbee2MQTT:info 2022-09-30 14:39:31: MQTT publish: topic 'zigbee2mqtt/0x00158d00012ccbc2', payload '{"consumption":0,"energy":0,"linkquality":84,"power":0,"state":"ON","temperature":38}' Zigbee2MQTT:info 2022-09-30 14:39:32: Successfully interviewed '0x00158d00012ccbc2', device has successfully been paired Zigbee2MQTT:info 2022-09-30 14:39:32: Device '0x00158d00012ccbc2' is supported, identified as: Xiaomi Mi power plug ZigBee (ZNCZ02LM) Zigbee2MQTT:info 2022-09-30 14:39:32: MQTT publish: topic 'zigbee2mqtt/bridge/event', payload '{"data":{"definition":{"description":"Mi power plug ZigBee","exposes":[{"features":[{"access":7,"description":"On/off state of the switch","name":"state","property":"state","type":"binary","value_off":"OFF","value_on":"ON","value_toggle":"TOGGLE"}],"type":"switch"},{"access":5,"description":"Instantaneous measured power","name":"power","property":"power","type":"numeric","unit":"W"},{"access":1,"description":"Sum of consumed energy","name":"energy","property":"energy","type":"numeric","unit":"kWh"},{"access":1,"description":"Measured temperature value","name":"temperature","property":"temperature","type":"numeric","unit":"°C"},{"access":7,"description":"Enable/disable the power outage memory, this recovers the on/off mode after power failure","name":"power_outage_memory","property":"power_outage_memory","type":"binary","value_off":false,"value_on":true},{"access":1,"description":"Link quality (signal strength)","name":"linkquality","property":"linkquality","type":"numeric","unit":"lqi","value_max":255,"value_min":0}],"model":"ZNCZ02LM","supports_ota":true,"vendor":"Xiaomi"},"friendly_name":"0x00158d00012ccbc2","ieee_address":"0x00158d00012ccbc2","status":"successful","supported":true},"type":"device_interview"}' 通过MQTT工具发送指令,例如zigbee2mqtt/0x00158d00012ccbc2/set,控制插座的开关状态,观察小米插座上的指示灯。 zigbee2mqtt/0x00158d00012ccbc2/set { "state": "OFF" } { "state": "ON" } Zigbee2MQTT:info 2022-09-30 14:47:14: MQTT publish: topic 'zigbee2mqtt/0x00158d00012ccbc2', payload '{"consumption":0,"energy":0,"linkquality":81,"power":0,"state":"ON","temperature":38}' Zigbee2MQTT:info 2022-09-30 14:47:24: MQTT publish: topic 'zigbee2mqtt/0x00158d00012ccbc2', payload '{"consumption":0,"energy":0,"linkquality":86,"power":0,"state":"OFF","temperature":38}' 通过这个简单的DIY项目,你可以轻松地将小米插座变成一个智能设备,实现远程控制和自动化操作。希望这个指南对你的智能家居探索有所帮助! --- ### 284. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Zigbee2MQTT 是一个流行的项目,使 Zigbee 设备能够与 MQTT 代理进行通信,进而允许各种智能家居平台(如 Home Assistant)与 Zigbee 设备进行交互。下面是在 Home Assistant 中使用 Zigbee2MQTT 的完整指南: 1. 安装 Mosquitto MQTT broker 首先,如果您还没有 MQTT broker,需要安装一个。在 Home Assistant 中,转到 设置 → 插件 → 插件商店,然后安装 Mosquitto broker 插件。 2. 添加 Zigbee2MQTT 仓库 回到插件商店,点击 ⋮ → 仓库。 输入以下地址:https://github.com/zigbee2mqtt/hassio-zigbee2mqtt,然后点击 添加 → 关闭。 在 Home Assistant 实例中,您将看到预填充了特定仓库 URL 的插件仓库对话框。 3. 选择并安装 Zigbee2MQTT 插件 Zigbee2MQTT:这是稳定版本,追踪 Zigbee2MQTT 的已发布版本,推荐大多数用户使用。 Zigbee2MQTT Edge:这是开发版本,有一些未正式发布的特性和修复。 选择所需的版本,点击 安装 并等待完成。 4. 配置 Zigbee2MQTT 转到 配置。 如果不使用 Mosquitto broker 插件,请填写您的 MQTT 详细信息。使用 Mosquitto broker 插件时,请留空。 mqtt: server: mqtt://localhost:1883 user: my_user password: "my_password" 填写串行详情,如您的 USB 协调器的端口。 serial: port: /dev/ttyUSB0 点击 保存。 通过转到 信息 并点击 开始 来启动插件。 等待 Zigbee2MQTT 启动,然后按 打开 WEB UI 以验证是否正确启动。 5. 从独立安装中恢复数据(如有需要) 确保两个环境都运行相同版本。 备份您的独立环境。 使用 HA 插件配置 UI 来配置串行端口。 恢复数据。 确保配置文件的串行端口部分与 UI 的配置匹配。 启动插件。 6. 注意事项与故障排除 如果遇到 502: Bad Gateway 错误,请稍等片刻后刷新页面。 如果插件启动时间过长,检查 日志 选项卡以查看出了什么问题。 如果您在插件中发现任何问题,请首先检查问题跟踪器中是否有类似的问题。 7. 更多资源 要了解更多详细信息和进阶功能,请参考 Zigbee2MQTT 官方文档。 总之,Zigbee2MQTT 为 Home Assistant 用户提供了与 Zigbee 设备通信的强大工具。通过遵循上述步骤,您可以轻松地将 Zigbee 设备集成到您的智能家居环境中。 --- ### 285. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 可以使用官方的Zigbee2MQTT Docker镜像在Docker容器中运行Zigbee2MQTT。 此镜像支持以下架构:386、amd64、arm/v6、arm/v7、arm64。由于Zigbee2MQTT镜像已列出清单,因此Docker会自动检测架构并拉取正确的镜像。 首先,根据此处的说明确定适配器的位置。 重要提示:使用Raspberry Pi吗?确保查看Raspberry Pi用户的注意事项。 创建初始配置导航到存储Zigbee2MQTT数据的目录,并执行以下命令: wget https://raw.githubusercontent.com/Koenkk/zigbee2mqtt/master/data/configuration.yaml -P data 现在,根据此处的说明配置MQTT服务器和适配器位置。 运行容器执行以下命令,更新--device参数以匹配适配器的位置。 $ docker run \ --name zigbee2mqtt \ --restart=unless-stopped \ --device=/dev/serial/by-id/usb-Texas_Instruments_TI_CC2531_USB_CDC___0X00124B0018ED3DDF-if00:/dev/ttyACM0 \ -p 8080:8080 \ -v $(pwd)/data:/app/data \ -v /run/udev:/run/udev:ro \ -e TZ=Europe/Amsterdam \ koenkk/zigbee2mqtt 参数解释: --name zigbee2mqtt:容器名称 --restart=unless-stopped:在启动时自动启动并在崩溃后重启 --device=/dev/serial/by-id/...:适配器位置(例如CC2531)。 -v $(pwd)/data:/app/data:Zigbee2MQTT存储配置的目录 -v /run/udev:/run/udev:ro:仅用于自动检测端口和某些适配器,如ConBee -e TZ=Europe/Amsterdam:配置时区 -p 8080:8080:从Docker容器内部到主机的端口转发(用于前端) 提示:如果在同一主机上运行MQTT服务器(localhost),则可以使用docker0桥的IP建立连接:server: mqtt://172.17.0.1。 无根容器为了提高部署的安全性,您可能希望以非root用户身份运行Zigbee2MQTT。 确定可以访问适配器的组(例如在Ubuntu中,可能会分配给dialout)。更新ttyACM0以匹配您的适配器位置。 如果您想使用当前用户运行Zigbee2MQTT,请找到uid(用户ID)和gid(组ID)。 启动docker容器后,更新设备、用户(uid:gid)和group-add。 更新要更新到最新的Docker镜像: docker pull koenkk/zigbee2mqtt:latest docker rm -f zigbee2mqtt 然后按照上面的说明再次运行容器。 标签以下标签可用: 最新发布版本:latest 基于dev分支的最新开发版本:latest-dev 特定发布版本,例如:1.7.0 Docker ComposeDocker Compose文件的示例: version: '3.8' services: zigbee2mqtt: container_name: zigbee2mqtt image: koenkk/zigbee2mqtt ... Raspberry Pi用户的注意事项如果您正在运行Raspbian Buster(而不是Bullseye!)(通过执行grep "PRETTY_NAME" /etc/os-release找出),则需要安装libseccomp2。 对于Raspberry Pi 1和零用户:Docker中有一个错误会选择错误的图像架构。在执行docker run之前,使用docker pull koenkk/zigbee2mqtt --platform linux/arm/v6拉取正确的镜像。 Docker Stack设备映射此内容仅与 Docker Stack 有关。 在 swarm 模式下部署堆栈时,Docker stack 不支持使用 --devices 选项进行设备映射。为此,我们有两种解决方案。这两种方法的起点都是将设备绑定为卷。 自动设备映射 cgroup v1 和 v2启用 Docker Stacks 上的设备的最简单解决方案是 allfro 设备映射管理器 docker 映像。这个容器有一个小程序,可以读取其自身主机上的所有卷挂载,识别设备,然后修改主机上的权限,允许容器使用它们。与其他解决方案不同,这适用于两个版本的 cgroups。 这个容器必须直接部署到 docker,而不是通过堆栈。可以通过创建一个特权服务的堆栈来绕过这个问题,该服务作为代理启动实际的设备映射容器。 version: "3.8" services: dmm: image: docker entrypoint: docker restart: unless-stopped privileged: true command: | run -i --rm --privileged --cgroupns=host --pid=host --userns=host -v /sys:/host/sys -v /var/run/docker.sock:/var/run/docker.sock -v /dev:/dev ghcr.io/allfro/allfro/device-mapping-manager:latest volumes: - /var/run/docker.sock:/var/run/docker.sock deploy: mode: global 手动 cgroup v1可以通过手动设置正确的权限来进行规避。此解决方案基于在 "service create" 上添加设备支持的解决方案,所有的荣誉都归给他。 此解决方案只适用于 cgroup v1,许多新的发行版上都没有启用此功能。 识别串行适配器 使用以下命令识别串行适配器: sudo lsusb -v UDEV 规则 为串行适配器创建一个新的 udev 规则,idVendor 和 idProduct 必须与 lsusb 命令的值相等。下面的规则创建了 /dev/zigbee-serial 设备: echo "SUBSYSTEM==\"tty\", ATTRS{idVendor}==\"0451\", ATTRS{idProduct}==\"16a8\", SYMLINK+=\"zigbee-serial\", RUN+=\"/usr/local/bin/docker-setup-zigbee-serial.sh\"" | sudo tee /etc/udev/rules.d/99-zigbee-serial.rules 使用以下命令重新加载新创建的规则: sudo udevadm control --reload-rules 创建 docker-setup-zigbee-serial.sh: sudo nano /usr/local/bin/docker-setup-zigbee-serial.sh 复制以下内容: #!/bin/bash USBDEV=`readlink -f /dev/zigbee-serial` read minor major < <(stat -c '%T %t' $USBDEV) if [[ -z $minor || -z $major ]]; then echo 'Device not found' exit fi dminor=$((0x${minor})) dmajor=$((0x${major})) CID=`docker ps -a --no-trunc | grep koenkk/zigbee2mqtt | head -1 | awk '{print $1}'` if [[ -z $CID ]]; then echo 'CID not found' exit fi echo 'Setting permissions' echo "c $dmajor:$dminor rwm" > /sys/fs/cgroup/devices/docker/$CID/devices.allow 设置权限: sudo chmod 744 /usr/local/bin/docker-setup-zigbee-serial.sh 创建 docker-event-listener.sh: sudo nano /usr/local/bin/docker-event-listener.sh 复制以下内容: #!/bin/bash docker events --filter 'event=start'| \ while read line; do /usr/local/bin/docker-setup-zigbee-serial.sh done 设置权限: sudo chmod 744 /usr/local/bin/docker-event-listener.sh 创建 docker-event-listener.service: sudo nano /etc/systemd/system/docker-event-listener.service 复制以下内容: [Unit] Description=Docker Event Listener for Zigbee serial adapter After=network.target StartLimitIntervalSec=0 [Service] Type=simple Restart=always RestartSec=1 User=root ExecStart=/bin/bash /usr/local/bin/docker-event-listener.sh [Install] WantedBy=multi-user.target 设置权限: sudo chmod 744 /etc/systemd/system/docker-event-listener.service 重新加载守护程序: sudo systemctl daemon-reload 启动 Docker 事件监听器: sudo systemctl start docker-event-listener.service 查看 Docker 事件监听器状态: sudo systemctl status docker-event-listener.service 启用 Docker 事件监听器: sudo systemctl enable docker-event-listener.service 验证并部署 Zigbee2MQTT 堆栈: 现在重新连接串行适配器。使用以下命令验证: ls -al /dev/zigbee-serial 以下是 docker-stack-zigbee2mqtt.yml 的示例: version: "3.7" services: zigbee2mqtt: image: koenkk/zigbee2mqtt:latest-dev environment: - TZ=Europe/Amsterdam volumes: - /mnt/docker-cluster/zigbee2mqtt/data:/app/data - /dev/zigbee-serial:/dev/zigbee-serial networks: - proxy_traefik-net deploy: placement: constraints: [node.hostname == rpi-3] replicas: 1 networks: proxy_traefik-net: external: true 在上述示例中,proxy_traefik-net 是连接到 mqtt 代理的网络。约束确保 Docker 只部署到这个 (rpi-3) 节点,串行适配器连接到这个节点。卷绑定 /mnt/docker-cluster/zigbee2mqtt/data 是 zigbee2mqtt 的持久目录, /dev/zigbee-serial 是 zigbee2mqtt 的串行适配器。 部署堆栈: docker stack deploy -c docker-stack-zigbee2mqtt.yml zigbee2mqtt 遵循以上步骤应该允许你在 swarm 模式下通过 docker stack 部署 zigbee2mqtt,同时解决了 zigbee 串行适配器权限问题。 故障排查即使按照上述方法操作,也可能会出现容器无法正确启动,并在服务的日志中显示 "Operation not permitted" 的消息: 错误:尝试打开串行端口时发生错误 'Error: Error: Operation not permitted, cannot open /dev/zigbee-serial'这是因为使用了 cgroupv2 而不是 cgroupv1,而 docker/containerd 并不完全支持 cgroupv2。要从 cgroupv2 切换到 cgroupv1,你需要在 grub cmdline 中添加 systemd.unified_cgroup_hierarchy=false。例如,在 Raspberry Pi 4 上使用 Raspian Bullseye,你可以在 /boot/cmdline.txt 文件的行末添加它: […] rootfstype=ext4 fsck.repair=yes rootwait cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1 systemd.unified_cgroup_hierarchy=false Docker 在 Synology DSM 7.0 上的应用注意:这可能不适用于所有 Zigbee 控制器,但已在 CC2531 上进行了测试。 从 Disk Station Manager 版本 7 开始,Synology 移除了对像 Zigbee 控制器这样的 USB 设备的内置支持。但你可以通过执行以下命令作为 root 用户来将 USB 支持安装到 Linux 内核。 modprobe usbserial modprobe ftdi_sio modprobe cdc-acm 执行上述命令后,可能需要拔出 Zigbee 控制器并重新插入 USB 端口。 你可能还需要基于你的 USB Zigbee 控制器设置的其他驱动程序,例如,默认情况下不包括 CH341 模块。你可以从 jadahl.com 的页面下载预编译的模块 - 根据 NAS CPU 架构选择模块目录(DS218+ -> INTEL Celeron J3355 -> Apollo Lake)。 cd /lib/modules wget http://www.jadahl.com/iperf-arp-scan/DSM_7.0/apollolake/ch341.ko insmod /lib/modules/ch341.ko 你还可以创建一个启动任务来执行上述命令: 创建一个包含三个 modprobe 命令的可执行脚本文件。 使用 DSM 的控制面板 -> 任务调度器 -> 创建 -> 触发任务 -> 用户定义脚本,并设置:用户:root,事件:启动,并在任务设置下执行可执行文件的 bash 命令。 --- ### 286. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 本指南将教你如何在 Linux 上运行 Zigbee2MQTT。 虽然我们以在 Raspberry Pi 4 上使用 Raspbian Stretch Lite 为例,但这个指南基本上适用于所有的 Linux 设备。 有些用户可能会在不同的系统版本上操作,比如在 Openhabian.piopenhabian 上,所以具体步骤可能会略有不同。 开始前,请确保你的系统中已经配置了 MQTT broker。Mosquitto 是一个很好的选择,当然,其他的 broker 也可以。 确定适配器位置及检查权限首先,你要确认适配器的具体位置。把适配器接到 Raspberry Pi 上,大部分时间它的位置都是 /dev/ttyACM0。可以用下面的命令检查: pi@raspberry:~ $ ls -l /dev/ttyACM0 crw-rw---- 1 root dialout 166, 0 May 16 19:15 /dev/ttyACM0 # <-- adapter (CC2531 in this case) on /dev/ttyACM0 如果你使用的是 Ethernet 连接的适配器,请按照适配器的说明书操作。 不过,建议使用 "by ID" 路径来找设备(详见“适配器设置”部分)。这种方法更加稳定,尤其是当 Raspberry Pi 连接了多个串行设备时。例如,设备位置可能是 /dev/serial/by-id/usb-Texas_Instruments_TI_CC2531_USB_CDC___0X00124B0018ED3DDF-if00。 pi@raspberry:/ $ ls -l /dev/serial/by-id total 0 lrwxrwxrwx. 1 root root 13 Oct 19 19:26 usb-Texas_Instruments_TI_CC2531_USB_CDC___0X00124B0018ED3DDF-if00 -> ../../ttyACM0 安装步骤 安装 Node.js 和所需依赖 sudo curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt-get install -y nodejs git make g++ gcc 确认正确安装了 nodejs 和 npm node --version npm --version 创建 zigbee2mqtt 的目录,并赋予权限 sudo mkdir /opt/zigbee2mqtt sudo chown -R ${USER}: /opt/zigbee2mqtt 克隆 Zigbee2MQTT 仓库 git clone --depth 1 https://github.com/Koenkk/zigbee2mqtt.git /opt/zigbee2mqtt 安装必要的依赖 cd /opt/zigbee2mqtt npm ci 构建应用程序 npm run build 在 Ubuntu 上的提示你可以用 Snap 在 Ubuntu 上安装 Node.js。 sudo snap install node --classic node --version 配置在启动 Zigbee2MQTT 前,要复制并调整 configuration.yaml 文件的设置。 复制并编辑配置文件: cp /opt/zigbee2mqtt/data/configuration.example.yaml /opt/zigbee2mqtt/data/configuration.yaml nano /opt/zigbee2mqtt/data/configuration.yaml 默认的配置已经很完善,你只需要修改 MQTT 服务器的 url/认证以及串口设置。 启动 Zigbee2MQTT一切准备好后,就可以启动 Zigbee2MQTT 了。 cd /opt/zigbee2mqtt npm start 如果成功,你会看到以下输出: Zigbee2MQTT:info 开始 Zigbee2MQTT 版本 1.X.X Zigbee2MQTT:info 启动 zigbee-herdsman (可选) 使用 systemctl 使 Zigbee2MQTT 作为守护进程运行若希望 Zigbee2MQTT 在后台作为守护进程运行,并在开机时自动启动,我们可以通过 systemctl 来实现。 为 Zigbee2MQTT 创建一个 systemctl 配置文件 sudo nano /etc/systemd/system/zigbee2mqtt.service 将以下内容添加到文件中: [Unit] Description=zigbee2mqtt After=network.target [Service] Environment=NODE_ENV=production ExecStart=/usr/bin/npm start WorkingDirectory=/opt/zigbee2mqtt StandardOutput=inherit # 若不希望 Zigbee2MQTT 的消息填充 syslog,可以使用 StandardOutput=null,更多选项参考 systemd.exec(5) StandardError=inherit Restart=always RestartSec=10s User=pi [Install] WantedBy=multi-user.target 如果你使用的是 Raspberry Pi 1 或 Zero 并且按照这个指南操作,将 ExecStart=/usr/bin/npm start 替换为 ExecStart=/usr/local/bin/npm start。 如果你使用的是 Raspberry Pi 或一个从 SD 卡启动的系统,你可能希望减少写入到磁盘的日志文件数量。通过 Systemd 服务会导致所有内容都记录两次:一次通过 systemd 单元,另一次是 Zigbee2MQTT 默认记录到文件下。你可能只想保留其中之一: 仅保留下面的日志 --> 在 systemd 单元中使用 StandardOutput=null 仅保留日志 --> 在 Zigbee2MQTT 配置中设置 advanced.log_output = ['console'] 如果想在另一个目录放置所有 Zigbee2MQTT 数据,加入 Environment=ZIGBEE2MQTT_DATA=/路径/到/数据 在 [Service] 下。 保存文件并退出。 验证配置是否工作: # 启动 Zigbee2MQTT sudo systemctl start zigbee2mqtt # 显示状态 systemctl status zigbee2mqtt.service 输出应如下: [输出内容] 既然一切都正常,我们希望 systemctl 在开机时自动启动 Zigbee2MQTT,执行以下命令即可: sudo systemctl enable zigbee2mqtt.service 完成!😃 以下是一些建议你可能会用到的小技巧: 停止 Zigbee2MQTT sudo systemctl stop zigbee2mqtt 启动 Zigbee2MQTT sudo systemctl start zigbee2mqtt 查看 Zigbee2MQTT 的日志 sudo journalctl -u zigbee2mqtt.service -f (以后) 更新 Zigbee2MQTT 到最新版本要更新 Zigbee2MQTT 到最新版本,执行以下命令: # 停止 Zigbee2MQTT 并转到目录 sudo systemctl stop zigbee2mqtt cd /opt/zigbee2mqtt # 备份配置 cp -R data data-backup # 更新 git pull npm ci npm run build # 恢复配置 cp -R data-backup/* data rm -rf data-backup # 启动 Zigbee2MQTT sudo systemctl start zigbee2mqtt --- ═══════════════════════════════════════════ ## 交通物流 ═══════════════════════════════════════════ ### 287. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智能交通系统方案:利用串口服务器实现高效城市交通管理 随着城市化进程的加速,交通拥堵、事故频发和通行效率低下等问题日益凸显,智能交通系统的建设成为解决这些问题的关键。通过运用串口服务器,我们可以构建一个高效、可靠且易于管理的智能交通网络,实现对城市交通的实时监控、数据分析和优化调度。 一、系统架构 智能交通系统的核心是串口服务器,它将传统的串口设备连接到以太网,实现设备的远程控制和数据采集。串口服务器作为桥梁,将信号灯、道闸、摄像头、称重仪表、LED显示屏、RFID读卡器、车辆感应线圈和票据打印机等设备接入局域网,实现集中管理和多用户访问。 二、关键技术 以太网连接:通过以太网技术,支持RS232和RS485两种串口信号,以及TCP Client、TCP Server、UDP Client、UDP Server、HTTPD Client等多种工作模式,确保与各种交通设备的兼容性。实现串口设备与控制中心的高速连接,确保数据传输的稳定性和实时性。 Modbus网关功能:轻松实现Modbus RTU和ModbusTCP协议互转,方便与现有的交通监控系统进行集成。串口服务器支持多用户同时访问,使得不同的客户端可以根据自己的需求获取交通数据。 自动轮询与数据采集:毫秒级的数据采集能力,确保交通数据的实时性和准确性。通过中央服务器,实现对所有串口设备的集中管理和配置,简化了维护工作,提高了管理效率。 虚拟串口技术:通过USR-VCOM软件,实现串口设备的虚拟化,简化软件开发和调试过程。实现对串口设备的远程管理和配置,无需更换现有串口软件。 三、应用场景 交通信号控制:通过串口服务器连接信号灯,控制中心可以根据实时交通流量调整信号灯的时序,优化交通流。 无人值守称重:将串口服务器与道闸和称重仪表相连,实现车辆的自动称重和道闸的远程控制。 交通数据采集:连接摄像头和车辆感应线圈,实时采集交通流量、速度等数据,为交通规划提供决策支持。 事故应急响应:通过实时监控,快速发现交通事故,及时调度救援资源,减少事故影响。 四、方案优势 高效性:通过实时数据分析,提高交通管理的响应速度和处理能力。 可靠性:串口服务器的稳定性保证了交通数据的准确传输和设备的可靠控制。 灵活性:支持多种串口设备的接入,便于根据实际需求扩展系统功能。 易维护性:集中管理和虚拟串口技术简化了设备的维护和升级工作。 五、结论 利用串口服务器实现的智能交通系统,不仅能够提高城市交通管理的效率和响应速度,还能够为交通规划和应急响应提供强有力的技术支持。随着技术的不断发展,未来的智能交通系统将更加智能化、网络化,为城市居民提供更加便捷、安全的出行环境。 --- ### 288. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 冷链物流是指冷冻、冷藏类物品从生产、储藏、运输到销售的各个环节始终处于规定的低温环境下,以保证货物质量和安全的一项系统工程 冷链物流中的主要运输对象:▲鲜活品:蔬菜、水果;肉、禽、蛋;水产品、花卉产品。加工食品:速冻食品、离、肉、水产等包装熟食、冰淇淋和奶制品;快餐原料,▲医药品:各类针剂、药剂。 冷链运输是确保温度敏感产品(如食品、药品和某些化学品)在整个供应链过程中保持在适宜和安全的温度范围内的物流管理过程。一个有效的冷链运输方案通常包括以下关键组成部分: 规划与管理需求分析:明确冷链运输的需求,包括运输的物品类型、温度要求、运输距离、法规要求等。供应链设计:设计高效、可靠的供应链流程,确保从生产到最终用户的每一步都满足温度控制的要求。风险管理:识别潜在的风险点并制定应对策略,如设备故障、运输延误等。 温控设备与包装冷藏/冷冻设备:使用适当的冷藏或冷冻运输工具,如冷藏车、冷藏集装箱等。温度监控技术:部署温度记录器、GPS追踪和实时温度监控系统来确保货物在整个运输过程中保持在适宜的温度范围内。绝缘和冷冻包装:使用高性能的绝缘材料和冷源(如干冰、凝胶包)来保持产品的温度。 运输与物流优化的物流路线:选择最短、最可靠的物流路线,减少运输时间和风险。专业的冷链物流服务商:合作有经验的冷链物流公司,确保运输过程中的专业管理和操作。 温度控制与监控全程温度监控:实时监控货物温度,确保整个运输过程中温度的稳定。数据记录与分析:记录温度数据,进行分析以改进未来的运输过程。 合规性与质量保证法规遵守:确保所有运输过程遵循相关法规和行业标准。培训与认证:为参与冷链运输的所有人员提供必要的培训,确保他们了解和能够遵循正确的操作程序。 应急计划应对措施:制定应急计划,以应对可能的设备故障、极端天气、运输延迟等情况。 客户沟通与服务透明度:向客户提供运输过程中的实时信息,包括温度数据和货物位置。客户服务:设立客户服务热线,解答客户的疑问并提供必要的支持。整合上述元素,开发出一个适应性强、高效可靠的冷链运输方案,可以显著降低产品损耗率,保证产品品质,满足客户和法规的要求。 --- ### 289. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 实时监测和数据采集: 物联网传感器可以安装在隧道内部,监测交通流量、车辆速度、车辆密度以及能见度等参数。这些数据通过网络传输到中央控制中心,并实时显示在监控屏幕上,使交通管理人员能够随时了解隧道内的交通状况。 进一步地,传感器可以监测隧道结构的健康状况,包括裂缝、位移和变形等情况,从而及时发现潜在的结构安全隐患。 事故预警系统: 基于物联网技术的事故预警系统可以利用传感器监测的数据,识别交通事故的迹象,例如车辆突然减速或停止、车辆偏离车道等。系统可以自动发出警报,并向交通管理人员和驾驶员发送警示信息。 一些高级系统甚至可以通过机器学习算法分析历史数据和实时数据,预测潜在的事故风险,并提出相应的预防措施。 紧急救援和应急响应: 物联网技术可以与GPS定位系统结合,实现对事故车辆和受困人员的精确定位。一旦发生事故,紧急呼救系统可以自动触发,并将事故位置和相关信息发送给救援中心。 救援人员可以通过智能手机或车载终端接收到事故现场的详细信息,包括实时交通状况、最佳救援路线以及事故类型等,从而提高救援效率。 交通管理和优化: 利用物联网技术收集的数据,交通管理人员可以进行实时交通流量分析和预测,制定最佳的交通管理策略,减少交通拥堵和事故发生的可能性。 智能交通信号灯系统可以根据实时交通情况进行调整,优化交通信号控制,提高路口通过能力和安全性。 通过以上这些方式,物联网技术为隧道交通事故的预防、监测和救援提供了全方位的支持,有效地提高了隧道交通的安全性和效率。 --- ### 290. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信   MQTT在运输和物流中的车队管理革命 为什么MQTT是车队管理的理想选择?运输和物流公司如何使用MQTT进行车队管理如何开始使用MQTT进行车队管理 在运输和物流行业中,高效的车队管理对于确保车辆平稳运行和优化配送过程至关重要。其中,MQTT这一轻量级且高效的消息传递协议正在改变车队管理的面貌。MQTT的设计初衷就是促进实时数据通信,使其成为应对行业独特挑战的理想工具。接下来,我们将深入探讨MQTT如何改变车队管理的游戏规则。 为什么MQTT适合车队管理? 实时洞察:车队管理依赖于实时数据。MQTT允许关键信息的交换,使公司能够实时监控其车辆和驾驶员。这种实时可见性对于数据驱动的决策制定和运营效率至关重要。通过MQTT,公司可以实时掌握车辆位置、速度、油量等关键信息,从而及时调整运营策略,优化配送路线,提高运输效率。 高效数据传输:MQTT的轻量级设计确保了数据可以高效传输。无论是追踪车辆位置、监控驾驶员行为,还是管理配送路线,MQTT都能以最小的开销处理数据交换,确保通信的快速和顺畅。这有助于减少数据传输过程中的延迟和错误,提高整个车队的运营效率。 可扩展性:车队管理的需求随着业务规模的变化而变化。MQTT提供了出色的可扩展性,能够适应不断变化的业务需求。无论是增加新的车辆,还是调整现有的配送网络,MQTT都能轻松应对,确保车队管理的灵活性和效率。 可靠性:确保车队的连续运营至关重要。MQTT的服务质量(QoS)级别保证了即使在恶劣条件下也能可靠地传递消息。这使得MQTT成为车队管理的理想选择,因为它能够在各种环境下确保数据的完整性和准确性。 那么,运输和物流公司是如何利用MQTT进行车队管理的呢? 首先,这些公司利用MQTT构建实时监控系统,实时追踪车辆位置和状态。通过MQTT协议,车辆可以定期发送位置、速度、油量等关键数据到中央服务器。这样,公司可以实时掌握车队运行情况,及时发现并解决潜在问题,从而提高运输效率和服务质量。 其次,MQTT还用于监控驾驶员行为。通过安装在车辆上的传感器,可以收集驾驶员的驾驶习惯、行驶速度、制动频率等数据,并通过MQTT协议传输到后端系统进行分析。这有助于公司评估驾驶员的表现,发现不良驾驶习惯,及时采取纠正措施,从而提高行车安全性。 此外,MQTT还可以用于智能路线规划和调度。通过分析实时交通数据和车队状态,系统可以自动生成最优路线,并通过MQTT协议将指令发送给相关车辆。这有助于减少拥堵和延误,提高配送效率,降低运营成本。 对于希望开始使用MQTT进行车队管理的公司,以下是一些建议: 首先,了解MQTT的基本原理和应用场景是至关重要的。公司需要研究MQTT协议的特点和优势,了解它在车队管理中的应用场景和潜在价值。这将有助于公司更好地利用MQTT技术提升车队管理效率。 其次,选择合适的MQTT代理和工具是关键。公司需要根据自身需求选择稳定、可靠且易于集成的MQTT代理和工具。这将有助于确保数据的安全传输和高效处理,提高整个系统的稳定性和可靠性。 最后,建立有效的数据分析和决策支持系统是必要的。通过收集和分析MQTT传输的数据,公司可以深入了解车队的运营情况,制定更加科学合理的决策。同时,公司还可以利用这些数据优化配送路线、提高运输效率、降低运营成本等。 总之,MQTT在运输和物流行业的车队管理中具有广阔的应用前景。通过充分利用MQTT的优势,公司可以实现对车队的实时、高效和智能化管理,为业务发展提供有力支持。随着物联网技术的不断发展,相信MQTT将在未来继续为车队管理带来更多创新和可能性。 --- ### 291. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在交通和物流行业,高效的车队管理对于确保车辆的顺畅运营和优化配送过程至关重要。一项正在转变车队管理的关键技术是MQTT。这种轻量级且高效的消息传输协议旨在促进实时数据通信,使其成为解决该行业独特挑战的完美工具。让我们深入了解MQTT如何改变车队管理游戏规则。 为什么MQTT适合车队管理? 实时洞察:车队管理依赖实时数据。MQTT允许交换关键信息,使公司能够实时监控他们的车辆和驾驶员。这种可见性对于数据驱动的决策制定和运营效率至关重要。 高效的数据传输:MQTT的轻量级设计确保数据可以高效传输。无论是追踪车辆、监控驾驶员行为还是管理路线,MQTT都能以最小的开销处理数据交换,确保快速且无缝的通信。 可伸缩性:车队管理需求随着需求变化。MQTT提供可适应业务变化需求的可伸缩性。它可以轻松地随着车队的增长而扩展,确保灵活性和效率。 可靠性:确保车队的持续运营至关重要。MQTT的服务质量(QoS)级别保证了即使在挑战性条件下也能可靠地传递消息,使其成为任务关键型应用的理想选择。 交通和物流公司如何使用MQTT进行车队管理 以下是MQTT在车队管理中的一些主要用途: 实时可见性:MQTT允许对车辆进行实时追踪,提供最新的位置和状态更新。这项能力有助于监控和改进交付时间表,优化路线,并提高整体车队效率。 优化路线:MQTT使企业能够收集和分析有助于路线优化的数据。通过监控交通状况、道路关闭和其他相关因素,车队经理可以即时调整路线,减少行驶时间和燃油成本。 监控车辆健康:车队维护是确保车辆可靠性的关键方面。MQTT协助远程监控车辆健康状况,提供实时诊断和维护需求警报。这种主动方式减少了停机时间,并延长了车队资产的使用寿命。 分析驾驶员行为:通过MQTT收集的IoT数据使公司能够详细了解驾驶员行为。公司可以追踪诸如速度、刹车和怠速等方面,帮助提高安全性,减少燃油消耗,并对驾驶员培训做出明智的决定。 例如,HiveMQ的客户FELA Management,已经为巴士、铁路和物流创建了创新的基于GPS的信息和追踪系统超过50年。他们最近采用了MQTT进行车队管理,以实现几乎实时的信息交换,使他们能够更准确地了解车辆运动。连接到HiveMQ代理的设备数量根据运输公司的车队规模而大幅波动,FELA发现HiveMQ MQTT平台有足够的性能来处理多个应用的需求。 另一个例子是宝马移动服务,宝马集团内的一个业务团队,为车队运营商提供共享汽车产品。该服务为车队运营商提供远程管理车队的能力,发出对单个车辆的远程命令(例如上锁/解锁)并从每辆车收集数据。使用MQTT帮助宝马将开锁时间从最高30秒减少到不到一秒。 如何开始使用MQTT进行车队管理 HiveMQ处于利用MQTT革新交通和物流行业车队管理的前沿。其实时能力、高效的数据传输、可伸缩性和可靠性使其成为希望优化车队运营的公司的理想选择。通过利用MQTT,企业可以实现成本削减、安全性提升和效率提高,最终创建一个更加精简和响应迅速的车队管理系统。 --- ═══════════════════════════════════════════ ## 学习 ═══════════════════════════════════════════ ### 292. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT 简介 MQTT 是一种为连接物联网设备而设计的发布/订阅协议。与 HTTP 的请求/响应模式不同,MQTT 以事件驱动的方式运作,允许将消息推送给客户端。这种架构方法通过解耦数据生产者和数据消费者,消除了它们之间的依赖关系,从而实现了高度可扩展的解决方案。建立 MQTT 连接以发布和订阅消息的两个关键组件是 MQTT 客户端和 MQTT 代理,如下图所示。 MQTT 的优势 MQTT 提供了几个关键优势: 轻量级和高效:MQTT 最小化了客户端所需的资源和网络带宽。 双向通信:MQTT 促进了设备和服务器之间的通信,支持发布和订阅。它还允许向设备组广播消息。 可扩展性:MQTT 可以扩展以支持物联网或工业物联网生态系统中的数百万设备或“事物”。 服务质量(QoS)级别:MQTT 指定了不同的 QoS 级别以确保可靠的消息传递。 持久会话:MQTT 支持设备和服务器之间的持久会话,减少了在不可靠网络上的重新连接时间。 安全特性:MQTT 支持 TLS 加密以确保消息的保密性,并支持认证协议以验证客户端。 MQTT 应用和案例 MQTT 在各个行业和领域都有应用。它已被 BMW、Liberty Global、Fortum、Hytera、Awair 和 Matternet 等公司采用。这些公司在汽车、电信、能源、公共安全和连接产品领域成功利用了 MQTT。 MQTT 基础:掌握这一物联网协议的要点 MQTT 的核心是 MQTT 代理和 MQTT 客户端。MQTT 代理是发送者和接收者之间的中介,将消息分发给适当的接收者。MQTT 客户端将消息发布到代理,其他客户端订阅特定主题以接收消息。每个 MQTT 消息都包含一个主题,客户端订阅他们感兴趣的主题。MQTT 代理维护一个订阅者列表,并使用它将消息传递给相关客户端。 MQTT 代理还可以为离线客户端缓冲消息,即使在不可靠的网络条件下也确保可靠的消息传递。为了实现这一点,MQTT 支持三种不同的服务质量(QoS)级别:0(最多一次)、1(至少一次)和 2(恰好一次)。 MQTT 规范有两个版本:MQTT 3.1.1 和 MQTT 5。虽然大多数商业 MQTT 代理现在支持 MQTT 5,但一些物联网管理的云服务仍然主要支持 MQTT 3.1.1。我们强烈建议在新的物联网部署中使用 MQTT 5,因为它增强了专注于健壮性和云原生可扩展性的功能。 MQTT 客户端 有许多开源客户端可用于多种编程语言。HiveMQ 通过 HiveMQ MQTT 客户端库提供自己的 MQTT 客户端,旨在简化 MQTT 客户端的部署和实施,并为用户提供一流的功能、性能、安全性和可靠性。支持的一些编程语言包括 C#、C++、Java、Websockets、Python 等。Eclipse Paho 也提供了适用于 C/C++ 和 Python 等语言的 MQTT 客户端库。 MQTT 代理 MQTT 代理有多种实现方式,以满足不同的需求,如开源、商业和托管云服务。HiveMQ 提供商业版:HiveMQ 自托管和 HiveMQ 云,一个托管的云 MQTT 服务,以及 HiveMQ 社区版,一个开源版本。有关 MQTT 代理的详细列表,请访问 mqtt.cn。 MQTT 使用案例示例: https://iot.mqtt.cn JAVA通过MQTT接入示例 说明: 本文中使用的代码为样例代码,仅用于体验平台通信功能,如需进行商用,可以参考资源获取获取对应语言的IoT Device SDK进行集成。 前提条件 已在管理控制台获取设备接入地址。获取地址的操作步骤,请参考平台对接信息。 已在管理控制台创建产品和设备。创建产品和设备的具体操作细节,请参考创建产品、注册单个设备或批量注册设备。 准备工作 安装IntelliJ IDEA 访问IntelliJ IDEA官网,选择合适系统的版本下载。(本文以windows 64-bit系统IntelliJ IDEA 2019.2.3 Ultimate为例)。 下载完成后,运行安装文件,根据界面提示安装。 导入代码样例 下载JAVA样例。 链接:https://pan.baidu.com/s/1JtQsONuIX8y7r0VpIepA5w?pwd=zne7 提取码:zne7 打开IDEA开发者工具,单击“ Import Project”。 选择步骤1中下载的样例,然后根据界面提示,单击“next”。 完成代码导入。 建立连接 设备或网关在接入物联网平台时首先需要和平台建立连接,从而将设备或网关与平台进行关联。开发者通过传入设备信息,将设备或网关连接到物联网平台。 MQTT基本信息 Topic权限说明Broker Addressiot.mqtt.cnMQTT地址Broker Port1883MQTT端口号Client ID4QR8TZ9ThuL4G设备号SN(请替换为自己的) MQTT账号密码 Topic权限说明User Nameceshi用户账户Password123456用户密码 在建立连接之前,先修改以下参数: // MQTT 服务器地址 private static final String MQTT_BROKER = "tcp://iot.mqtt.cn:1883"; MQTT地址/端口号 // MQTT 客户端 ID private static final String MQTT_CLIENT_ID = "4QR8TZ9ThuL4G"; //设备号SN码 // MQTT 用户名 private static final String MQTT_USERNAME = "ceshi"; // MQTT 密码 private static final String MQTT_PASSWORD = "Abc123456"; // 订阅的主题 private static final String MQTT_TOPIC_SUBSCRIBE = "/server/coo/4QR8TZ9ThuL4G"; // 发布的主题 private static final String MQTT_TOPIC_PUBLISH = "/dev/coo/4QR8TZ9ThuL4G"; MQTT_BROKER为物联网平台的设备对接地址,可参考平台对接信息获取(获取的是域名信息,可通过在cmd命令框中执行“ping 域名”,获取IP地址)。 MQTT_CLIENT_ID为设备号SN,在成功添加设备后获取。 修改完1中的参数后就可使用MqttClient建立连接了。 连接成功后,设备显示在线。 备注:从设备地址是sensor_device_id ,寄存器是port_id,数据数值是Sdata ,具体稍后有具体说明。 使用MQTT通讯协议,下面的属性名称,Modbus功能码,数据格式,数据顺序不会影响最终数据,随便选择就可以! MQTT 主题一览 MQTT物联网平台 作为物联网 PaaS 云平台,对设备 MQTT 接入提供了内置的访问协议规范,让设备和云平台的消息通信更加有章可循,大大简化了物联网项目的开发难度,缩短了产品的开发周期。 不同于普通的 MQTT 使用方式,我们提供了标准的内置主题,这足以实现绝大多数的物联网应用场景。 Topic权限说明/dev/coo/4QR8TZ9ThuL4G发布上行通信:设备通过该Topic向物联网平台发送消息。/server/coo/4QR8TZ9ThuL4G订阅下行通信:设备通过订阅该Topic,获取从物联网平台下发的消息。 4QR8TZ9ThuL4G为示例设备号SN,请替换为自己的! 上行通信 Topic:/dev/coo/4QR8TZ9ThuL4G 设备号SN(请替换为自己的) // 连接到 MQTT 服务器 mqttClient.connect(options); // 订阅主题 mqttClient.subscribe(MQTT_TOPIC_SUBSCRIBE); // 创建消息 MqttMessage message = new MqttMessage(); message.setPayload("[{"sensor_device_id": 1, "port_id": 1, "sdata": 66}]".getBytes()); // 发布消息 mqttClient.publish(MQTT_TOPIC_PUBLISH, message); 备注:从设备地址是sensor_device_id ,寄存器是port_id,数据数值是Sdata 下行通信 Topic:/server/coo/4QR8TZ9ThuL4G 设备号SN(请替换为自己的) System.out.println("设备ID: " + sensor_device_id + ", 端口ID: " + port_id + ", 数据: " + sdata); 备注:从设备地址是sensor_device_id ,寄存器是port_id,数据数值是Sdata 完整代码: import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import org.json.JSONArray; import org.json.JSONObject; public class MqttDemo { // MQTT 服务器地址 private static final String MQTT_BROKER = "tcp://iot.mqtt.cn:1883"; // MQTT 客户端 ID private static final String MQTT_CLIENT_ID = "4QR8TZ9ThuL4G"; // MQTT 用户名 private static final String MQTT_USERNAME = "ceshi"; // MQTT 密码 private static final String MQTT_PASSWORD = "Abc123456"; // 订阅的主题 private static final String MQTT_TOPIC_SUBSCRIBE = "/server/coo/4QR8TZ9ThuL4G"; // 发布的主题 private static final String MQTT_TOPIC_PUBLISH = "/dev/coo/4QR8TZ9ThuL4G"; // 心跳间隔,单位为秒 private static final int MQTT_KEEP_ALIVE_INTERVAL = 60; public static void main(String[] args) throws MqttException { // 创建 MQTT 客户端 MqttClient mqttClient = new MqttClient(MQTT_BROKER, MQTT_CLIENT_ID, new MemoryPersistence()); // 设置 MQTT 连接选项 MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(MQTT_USERNAME); options.setPassword(MQTT_PASSWORD.toCharArray()); options.setCleanSession(true); options.setKeepAliveInterval(MQTT_KEEP_ALIVE_INTERVAL); // 设置回调 mqttClient.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable cause) { System.out.println("连接断开"); } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { System.out.println("收到消息。主题: " + topic); System.out.println("消息: " + new String(message.getPayload())); // 将消息转换为字符串 String msg = new String(message.getPayload()); // 使用 JSON 工具解析字符串 JSONArray jsonArray = new JSONArray(msg); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); int sensor_device_id = jsonObject.getInt("sensor_device_id"); int port_id = jsonObject.getInt("port_id"); int sdata = jsonObject.getInt("sdata"); // 在这里你可以处理接收到的数据 System.out.println("设备ID: " + sensor_device_id + ", 端口ID: " + port_id + ", 数据: " + sdata); } } @Override public void deliveryComplete(IMqttDeliveryToken token) { System.out.println("消息发布完成"); } }); // 连接到 MQTT 服务器 mqttClient.connect(options); // 订阅主题 mqttClient.subscribe(MQTT_TOPIC_SUBSCRIBE); // 创建消息 MqttMessage message = new MqttMessage(); message.setPayload("[{"sensor_device_id": 1, "port_id": 1, "sdata": 66}]".getBytes()); // 发布消息 mqttClient.publish(MQTT_TOPIC_PUBLISH, message); } } --- ### 293. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着物联网(IoT)技术的飞速发展,消息队列遥测传输(MQTT)协议作为一种轻量级的消息传递协议,在物联网设备间的消息传输中扮演着重要的角色。尤其是MQTT 5.0的发布,为开发者带来了一系列创新特性,极大地拓宽了MQTT协议的应用场景。其中,用户属性(User Properties)的引入为自定义消息元数据提供了无限可能,本文将探索用户属性的概念、必要性及其在实际应用中的运用,以通俗易懂的方式向开发者展示这一新特性的魅力。 用户属性的定义与必要性 用户属性是MQTT 5.0引入的一种新特性,允许在MQTT消息中添加自定义的键值对信息,从而传递额外的自定义元数据。每个键值对都由UTF-8编码的字符串组成,为消息传递提供了更丰富的上下文信息。这一功能与HTTP协议中的Header概念相似,但设计得更为灵活,可以无限扩展。 在MQTT 5.0之前,MQTT的扩展性较差,用户难以在标准协议基础上传递特定的元数据信息。用户属性的引入有效解决了这一问题,不仅支持在客户端与MQTT服务器间传递任意信息,还可在客户端间实现元数据的交换,极大增强了MQTT的可用性和灵活性。 应用场景举例 场景一:文件传输 在传统的MQTT通信中,文件通常被转换为二进制数据并嵌入到消息的Payload中进行传输。MQTT 5.0允许通过用户属性传输文件的元数据,如文件名、类型等,而文件内容仍通过Payload传输。这样,接收方可以在收到消息前就获得文件的相关信息,从而更有效地处理文件数据。 例如,发送方可以设置以下用户属性来传输一个文本文件: { "filename": "example.txt", "filetype": "text/plain" } 场景二:资源解析 在一个全球分布的物联网系统中,不同地区的设备可能使用不同格式的消息进行通信(如JSON、XML)。通过用户属性,发送方可以指明消息格式和地区信息,使得MQTT服务器或接收方能够根据这些元数据选择正确的解析器解析消息。 例如,一个位于欧洲的设备发送的消息可能包含以下用户属性: { "region": "Europe", "format": "JSON" } 场景三:消息路由 用户属性还可以用于实现更高级的消息路由机制。在复杂的物联网应用中,根据消息的类型、优先级或目的地对消息进行路由是非常常见的需求。通过在消息中添加相应的用户属性,MQTT服务器可以根据这些属性将消息路由到正确的处理队列或服务。 例如,一个紧急报警消息可以包含如下用户属性: { "priority": "high", "alertType": "gasLeak" } 在客户端中使用用户属性 使用JavaScript和MQTT.js库为例,下面演示如何在连接客户端时和发布消息时设置用户属性。 连接客户端时的用户属性 连接到MQTT服务器时,可以在connect方法的options中添加用户属性,这些属性将随着连接请求一起发送给MQTT服务器。 // connect options const OPTIONS = { clientId: 'mqtt_test', clean: true, connectTimeout: 4000, username: 'emqx', password: 'public', reconnectPeriod: 1000, protocolVersion: 5, properties: { userProperties: { region: 'A', type: 'JSON', }, }, } const client = mqtt.connect('mqtt://broker.emqx.io', OPTIONS) 发布消息时的用户属性 当发布MQTT消息时,也可以添加用户属性,这些属性将随消息一同传递给订阅了相应主题的客户端。 client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false, properties: { userProperties: { region: 'A', type: 'JSON', }, }, }, (error) => { if (error) { console.error(error) } }) client.on('message', (topic, payload, packet) => { console.log('packet:', packet) console.log('Received Message:', topic, payload.toString()) }) 结论 MQTT 5.0的用户属性特性为MQTT协议带来了前所未有的灵活性和扩展性,使得开发者能够更便捷地在MQTT消息中携带丰富的上下文信息。无论是进行文件传输、资源解析还是实现复杂的消息路由,用户属性都提供了一个简洁而强大的解决方案。随着越来越多的应用开始利用这一新特性,我们有理由相信MQTT协议在物联网领域的应用将变得更加广泛和深入。 --- ### 294. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在现代物联网(IoT)生态系统中,MQTT(Message Queuing Telemetry Transport)协议由于其轻量级和高效性,已成为连接数十亿智能设备的首选协议。尽管MQTT的发布订阅模型为异步消息传递提供了极大的灵活性,但在一些场景下,如设备配置更新或遥控命令执行等,通信双方可能需要一个更确定性的“请求/响应”机制来确保操作的成功执行。幸运的是,MQTT 5.0 引入了若干新特性,为实现这种机制提供了强大支持。本文将深入探讨如何借助这些新特性,在MQTT的异步框架下实现有效的“请求/响应”模式。 MQTT 5.0 前的挑战 在MQTT 5.0之前,实现“请求/响应”通常依赖于客户端和服务端之间的预先约定:请求方向一个特定主题发布请求消息,而响应方监听该主题,并向另一个预定的响应主题发布其响应。这种方法的主要限制是响应主题的固定性,当多个请求方涉及时,每个方都会接收到对同一请求的响应,导致消息处理上的混乱。 利用 MQTT 5.0 实现高效的“请求/响应”机制 响应主题(Response Topic) MQTT 5.0 允许请求方在发送请求消息时指定一个期望收到响应的主题,从而实现动态响应路由。这意味着响应方可以直接将响应消息发送到请求中指定的主题,极大提升了系统的灵活性和响应的准确性。 关联数据(Correlation Data) 关联数据特性使请求方能够在请求消息中包含一个唯一的标识符,响应方需要在其响应消息中包含相同的标识符。这使请求方能够将响应正确地匹配到相应的请求,特别是在处理多个并发请求时,这一机制显得尤为重要。 响应信息(Response Information) 通过使用响应信息属性,服务端可以提供额外的响应主题信息,帮助客户端构建合规的响应主题,确保通信的安全性和有效性。 智能家居场景示例 考虑一个智能家居场景,用户通过智能手机控制家中的多个智能设备,如灯光、空调等。在这个场景中,用户的请求(如“关闭客厅的灯”)需要得到设备的响应(如“已关闭”),以确认操作已成功执行。 请求消息:用户的智能手机发布一个请求消息到 MQTT 服务器,请求关闭客厅的灯。在这个请求消息中,用户指定了一个响应主题,如 smartHome/user123/lights/livingRoom/response,并且包含了一个关联数据,比如一个随机生成的ID abcd1234。 设备响应:智能灯光设备订阅了相应的请求主题,并收到了关闭灯光的请求。执行关闭操作后,设备发布一个响应消息到 smartHome/user123/lights/livingRoom/response,消息中包含了相同的关联数据 abcd1234。 用户确认:用户的智能手机订阅了响应主题 smartHome/user123/lights/livingRoom/response,并收到了设备的响应消息。通过匹配关联数据 abcd1234,用户的智能手机确认这是对关闭灯光请求的响应,并向用户显示一个确认信息。 这个过程中,响应主题的使用使得每个请求都有一个明确的响应路径,而关联数据则确保了响应可以被正确地关联到其请求。此外,通过利用 MQTT 5.0 的属性,智能设备的响应可以更加灵活地处理,并且可以保证仅由正确的请求方接收。 结论 通过MQTT 5.0的新特性,特别是响应主题、关联数据和响应信息,我们不仅能够在异步的消息传递框架下实现高效的“请求/响应”机制,还能提供更加动态和安全的通信模式。这些机制为物联网应用,如智能家居控制系统,提供了极大的灵活性和可靠性,确保了用户命令的准确执行和状态反馈,极大地增强了用户体验。随着越来越多的设备和应用采用MQTT 5.0,我们期待看到更多创新和改进,在保持通信高效的同时,提高物联网系统的整体安全性和可靠性。 --- ### 295. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在物联网的世界里,安全性是一个永远绕不开的话题。随着物联网设备的普及和应用的复杂化,传统的身份认证方法已经无法满足日益增长的安全需求。MQTT 作为物联网领域广泛使用的轻量级消息协议,其安全机制的升级显得尤为重要。在此背景下,MQTT 5.0 引入的增强认证机制为物联网安全通信提供了新的解决方案。 增强认证机制简介 增强认证是 MQTT 5.0 的一个重要特性,它通过引入更加安全的身份验证方法来提升通信安全性。不同于传统的用户名和密码验证,增强认证允许使用诸如SCRAM(Salted Challenge Response Authentication Mechanism)等多轮次的认证流程,大幅增强了认证过程的安全性。此外,增强认证还支持双向身份验证,即客户端和服务器可以互相验证对方的身份,进一步提高安全水平。 增强认证解决的问题 传统的密码认证虽然简单,但存在明显的安全弱点,最大的问题是密码在网络中的明文传输可能被窃听。即便使用加密通信,低版本的 SSL/TLS 仍可能因安全漏洞被攻击者利用,导致密码泄露。此外,密码认证无法实现服务端的身份验证,使得中间人攻击成为可能。 增强认证通过引入质询-响应机制,避免了密码的直接传输,即使通信被窃听,攻击者也无法直接获得密码信息。同时,通过客户端和服务端的互相验证,有效防止了中间人攻击。 常见的增强认证机制 DIGEST-MD5 DIGEST-MD5 是一种基于MD5散列算法的身份验证机制。它通过一次性的随机数(质询)和必要参数,要求客户端和服务器分别生成响应进行比较,以此验证身份。这种机制虽然比明文密码传输安全,但由于MD5算法本身的安全性已不再被认为是安全的,因此在安全性要求高的场景中,建议使用更安全的算法。 SCRAM SCRAM 是一种更为安全的身份验证机制,它通过使用盐值(Salt)和迭代次数(Iterations),结合SHA-256或SHA-512等安全哈希算法,大大增强了密码的安全性。SCRAM 不仅防止了密码的明文传输,还通过服务端对客户端的证明过程,实现了双向身份验证。 Kerberos Kerberos 是一种基于票据的认证机制,它通过引入可信的第三方(Kerberos服务器)进行身份验证。Kerberos 的优点在于能够实现单点登录(SSO),提高了使用便捷性的同时,也保证了较高的安全性。然而,Kerberos 的实现相对复杂,且对网络环境的要求较高。 下面是增强认证在 MQTT 5.0 中的运作方式的概览: 认证流程的开始 客户端发送 CONNECT 报文:在连接到服务器时,客户端发送一个 CONNECT 报文,该报文中包含了认证方法(Authentication Method)和可能的认证数据(Authentication Data)。这里的认证方法可以是“SCRAM-SHA-256”或其他支持的方法。 服务端回应 CONNACK 报文:服务端收到 CONNECT 报文后,根据提供的认证方法决定是否需要更多的认证数据。如果需要更多数据,服务端会响应一个 CONNACK 报文,其中包含一个指示继续认证过程的代码(如 0x18,表示继续认证),或者如果一步就能验证完成,则直接返回认证成功或失败的响应。 多轮认证过程 使用 AUTH 报文进行多轮认证:如果认证过程需要多轮交换数据(如 SCRAM),则会使用 AUTH 报文来进行。这一步中,服务端和客户端会根据具体的认证方法多次交换 AUTH 报文。 服务端发送 AUTH 报文:服务端发送 AUTH 报文,包含质询信息(如 SCRAM 中的盐值、迭代次数等)。 客户端回应 AUTH 报文:客户端根据收到的质询计算相应的响应,并通过 AUTH 报文发送回服务端。 这一过程可能会重复进行多轮,直到认证过程完成。 认证的完成 认证成功或失败:一旦认证过程完成,服务端会发送一个 CONNACK 报文,指示认证成功(通过 Reason Code 0x00 表示连接被接受)或失败(通过其他 Reason Code 指示失败原因)。如果认证失败,客户端应该断开连接。 SCRAM 需要传递四次消息才能完成认证。 client-first-message server-first-message client-final-message server-final-message 结语 MQTT 5.0 引入的增强认证为物联网通信安全提供了强有力的保障。通过选择适合的增强认证机制,开发者可以根据自己的安全需求和场景,灵活部署高安全性的物联网应用。随着物联网技术的不断进步,增强认证无疑将成为保护物联网通信安全的重要工具之一。 --- ### 296. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 这段代码展示了如何使用MQTTnet库在.NET环境中发布MQTT应用消息,包括发布单个消息和发布多个消息的示例。下面是对这些示例代码加上中文注释的版本: // 授权给 .NET Foundation 根据一个或多个协议。 // .NET Foundation 在 MIT 许可下授权此文件。 // 有关详细信息,请参阅项目根目录中的 LICENSE 文件。 // ReSharper 禁用全局未使用类型 // ReSharper 禁用全局未使用成员 // ReSharper 禁用不一致命名 using MQTTnet.Client; namespace MQTTnet.Samples.Client; public static class Client_Publish_Samples { public static async Task Publish_Application_Message() { /* * 此示例推送一个包含主题和载荷的简单应用消息。 * * 总是在存在的情况下使用构建器。此项目中的构建器被设计为 * 向后兼容。通过其构造函数创建 _MqttApplicationMessage_ 也是 * 支持的,但是这个类在未来的发布中可能会经常更改,而构建器不会, * 或者至少在可能的情况下提供向后兼容性。 */ var mqttFactory = new MqttFactory(); using (var mqttClient = mqttFactory.CreateMqttClient()) { var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer("broker.hivemq.com") .Build(); await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); var applicationMessage = new MqttApplicationMessageBuilder() .WithTopic("samples/temperature/living_room") .WithPayload("19.5") .Build(); await mqttClient.PublishAsync(applicationMessage, CancellationToken.None); await mqttClient.DisconnectAsync(); Console.WriteLine("MQTT 应用消息已发布。"); } } public static async Task Publish_Multiple_Application_Messages() { /* * 此示例推送多个包含主题和载荷的简单应用消息。 * * 详情见 _Publish_Application_Message_ 示例。 */ var mqttFactory = new MqttFactory(); using (var mqttClient = mqttFactory.CreateMqttClient()) { var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer("broker.hivemq.com") .Build(); await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); var applicationMessage = new MqttApplicationMessageBuilder() .WithTopic("samples/temperature/living_room") .WithPayload("19.5") .Build(); await mqttClient.PublishAsync(applicationMessage, CancellationToken.None); applicationMessage = new MqttApplicationMessageBuilder() .WithTopic("samples/temperature/living_room") .WithPayload("20.0") .Build(); await mqttClient.PublishAsync(applicationMessage, CancellationToken.None); applicationMessage = new MqttApplicationMessageBuilder() .WithTopic("samples/temperature/living_room") .WithPayload("21.0") .Build(); await mqttClient.PublishAsync(applicationMessage, CancellationToken.None); await mqttClient.DisconnectAsync(); Console.WriteLine("MQTT 应用消息已发布。"); } } } 这些示例代码提供了使用MQTTnet库在.NET应用中与MQTT代理服务器连接并发布消息的基本方法。通过使用MqttClientOptionsBuilder来配置客户端选项,包括指定MQTT代理服务器的地址。然后,使用MqttApplicationMessageBuilder构建应用消息,并通过调用PublishAsync方法来发布这些消息。最后,示例中还展示了如何优雅地断开与MQTT代理服务器的连接。 --- ### 297. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在实时通讯协议 MQTT 的最新版本 5.0 中,引入了一个称为“消息过期间隔”(Message Expiry Interval)的新特性。这一功能允许消息发布者为每条消息设置一个有效期限。如果消息在服务器上停留的时间超过了这个期限,它就不会被分发给任何订阅者。这意味着,当消息的内容不再相关或有用时,它会被自动清理,从而优化了网络资源的使用和提高了通信的效率。 什么是消息过期间隔? 消息过期间隔定义了一个消息从被发布起,到它变得不再可分发为止的时间长度。在 MQTT 协议中,这是通过在消息中设置一个特定的“过期间隔”值来实现的。默认情况下,消息不设置过期间隔,即视为永不过期。但在某些场景下,设定一个合理的过期时间可以显著提高数据传输的效率和实时性。 应用场景 时间敏感的信息 例如,一个促销活动仅在接下来的两小时内有效。如果消费者在活动结束后才收到这个消息,那么这个消息就失去了它的价值。 状态更新 考虑到实时交通信息的更新,如道路拥堵情况。随着时间的推移和交通流量的变化,过时的拥堵信息就不再有参考价值。 自动管理保留消息 在 MQTT 中,保留消息功能允许新的订阅者接收到他们订阅主题的最后一条消息。通过设置消息的过期间隔,可以避免过时的保留消息长时间占用服务器资源。 实例演示 假设有一个联网汽车应用场景,其中包括发送实时交通状况和路口信号灯配时建议。通过设置消息的过期间隔,可以确保车辆只接收到当前位置附近的、时效性强的信息。 设置消息过期间隔的操作步骤 要演示消息过期间隔的代码示例,我们可以使用 Python 和 paho-mqtt 库,这是一个常用于 MQTT 客户端开发的库。下面的示例将分为两部分:发布者(Publisher)和订阅者(Subscriber)。 安装 paho-mqtt 首先,确保你已经安装了 paho-mqtt。如果没有安装,可以通过 pip 安装: pip install paho-mqtt 发布者(Publisher) 发布者将发送两条消息,一条设置了5秒的过期间隔,另一条设置了60秒。 import time import paho.mqtt.client as mqtt # MQTT 服务器地址 MQTT_HOST = "test.mosquitto.org" MQTT_PORT = 1883 MQTT_TOPIC = "mqttx/demo/message_expiry" def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") client = mqtt.Client() client.on_connect = on_connect client.connect(MQTT_HOST, MQTT_PORT, 60) # 发送第一条消息,设置5秒过期间隔 client.publish(MQTT_TOPIC, payload="This message will expire in 5 seconds.", qos=1, properties={'message_expiry_interval': 5}) print("Published message with 5 seconds expiry.") # 发送第二条消息,设置60秒过期间隔 client.publish(MQTT_TOPIC, payload="This message will expire in 60 seconds.", qos=1, properties={'message_expiry_interval': 60}) print("Published message with 60 seconds expiry.") # 断开连接 client.disconnect() 订阅者(Subscriber) 订阅者订阅同一个主题,并处理接收到的消息。 import paho.mqtt.client as mqtt # MQTT 服务器地址 MQTT_HOST = "test.mosquitto.org" MQTT_PORT = 1883 MQTT_TOPIC = "mqttx/demo/message_expiry" def on_connect(client, userdata, flags, rc): print(f"Connected with result code {rc}") client.subscribe(MQTT_TOPIC) def on_message(client, userdata, msg): print(f"Received message: {msg.payload.decode()} on topic {msg.topic}") client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.connect(MQTT_HOST, MQTT_PORT, 60) client.loop_forever() 运行示例 运行订阅者代码:首先启动订阅者客户端,让它在后台运行并监听指定主题的消息。 运行发布者代码:然后运行发布者代码,发送两条带有不同过期间隔的消息。 你将看到订阅者只接收到在其过期间隔内的消息。如果你在发布后立刻运行订阅者,两条消息都可能被接收。但如果在5秒后再启动订阅者,只有设置了60秒过期间隔的消息会被接收,因为另一条消息已经过期。 这个演示说明了如何在MQTT 5.0中使用消息过期间隔功能,以及它如何影响消息的传递和接收。 通过这个例子,我们可以清楚地看到消息过期间隔如何在实际应用中起作用,以确保信息的实时性和相关性。 总结 消息过期间隔是 MQTT 5.0 提供的一个非常实用的特性,它帮助开发者和企业确保消息的时效性,同时减轻服务器的负担,并优化资源使用。无论是在实时交通信息、促销活动通知,还是在智能家居和工业物联网应用中,适当使用消息过期间隔都能带来显著的效益。 在设计和实现基于 MQTT 协议的通信系统时,合理利用消息过期间隔不仅可以提高信息传输的效率,还能增强用户体验,确保用户及时获取最重要和最相关的信息。同时,它还减少了网络带宽的浪费,优化了服务器存储资源的使用,使得系统更加高效和可靠。 --- ### 298. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在MQTT 5.0中,Reason Code的引入为客户端和服务端提供了更详细的反馈机制。这些代码不仅帮助诊断连接问题,还让开发者能够更精确地处理各种异常情况。与MQTT 3.1.1相比,MQTT 5.0扩展了Reason Code的范围和应用,使得错误处理更加灵活和详细。 MQTT 3.1.1与MQTT 5.0中的Reason Code对比 在MQTT 3.1.1版本中,Reason Code的使用相对有限,仅在CONNACK和SUBACK报文中提供了一些基本的错误代码。这些代码的范围和细节都较为有限,使得开发者在诊断和处理问题时可能会遇到一些挑战。 而MQTT 5.0则大幅扩展了Reason Code的数量和应用场景,引入了43个不同的代码,覆盖了连接、发布、订阅、取消订阅等多种操作的成功与失败情况。这些代码被分为两大类:小于0x80的表示操作成功,等于或大于0x80的表示操作失败。 MQTT 5.0 Reason Code速查表 为了便于理解和应用,以下是一些常见MQTT 5.0 Reason Codes的速查表,包括它们的含义和使用场景: Reason CodeNamePacketsDetails0x00SuccessCONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH这个 Reason Code 可以用在所有存在 Reason Code 的报文中,例如 CONNACK、DISCONNECT 报文等等。它通常用于表示成功,比如连接成功、取消订阅成功、消息接收成功和认证成功等等。0x00Normal disconnectionDISCONNECT在 DISCONNECT 报文中,0 则表示连接正常断开,这种情况下遗嘱消息不会被发布。0x00Granted QoS 0SUBACK0,1,2 在 SUBACK 这个订阅确认报文中,用来指示订阅结果,它们都表示订阅成功,同时向订阅端指示最终被授予的最大 QoS 等级,0,1,2 正好对应了三个 QoS 等级。 这是因为服务端最终授予的最大 QoS 等级,可能小于订阅时请求的最大 QoS 等级。比如订阅时请求的最大 QoS 等级是 2,但服务端最高仅支持 QoS 1 等等。0x01Granted QoS 1SUBACK-0x02Granted QoS 2SUBACK-0x04Disconnect with Will MessageDISCONNECT仅用于 DISCONNECT 报文,适用于客户端希望正常断开连接但服务端仍然需要发布遗嘱消息的情况,比如客户端希望会话过期时可以对外发出通知。0x10No matching subscribersPUBACK, PUBREC这个 Reason Code 用于向发送方指示,消息已经收到,但是当前没有匹配的订阅者,所以只有服务端可以使用这个 Reason Code。我们可以通过收到 Reason Code 为 0x10 的响应报文得知当前没有人会收到自己的消息,但是不能通过没有收到 Reason Code 为 0x10 的响应报文来假定所有人都会收到自己的消息,除非最多只会存在一个订阅者。但需要注意,没有匹配的订阅者时使用 0x10 替代 0x00,并不是一个必须实现的行为,这取决于服务端的具体实现。0x11No subscription existedUNSUBACK仅用于 UNSUBACK 报文,表示取消订阅时没有发现匹配的订阅。0x18Continue authenticationAUTH仅用于 AUTH 报文,表示继续认证,通过这个 Reason Code,客户端和服务端之间可以进行任意次数的 AUTH 报文交换,以满足不同的认证方法的需要。0x19Re-authenticateAUTH仅用于 AUTH 报文,在增强认证成功后客户端可以随时通过发送 Reason Code 为 0x19 的 AUTH 报文发起重新认证。重新认证期间,其他报文收发会正常继续,如果重新认证失败,连接就会被关闭。0x80Unspecified errorCONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT表示未指明的错误。当一方不希望向另一方透露错误的具体原因,或者协议规范中没有能够匹配当前情况的 Reason Code 时,那么它可以在报文中使用这个 Reason Code。0x81Malformed PacketCONNACK, DISCONNECT当收到了无法根据协议规范正确解析的控制报文时,接收方需要发送 Reason Code 为 0x81 的 DISCONNECT 报文来断开连接。如果是 CONNECT 报文存在问题,那么服务端应该使用 CONNACK 报文。当控制报文中出现固定报头中的保留位没有按照协议要求置 0、QoS 被指定为 3、UTF-8 字符串中包含了一个空字符等等这些情况时,都将被认为是一个畸形的报文。0x82Protocol ErrorCONNACK, DISCONNECT在控制报文被按照协议规范解析后检测到的错误,比如包含协议不允许的数据,行为与协议要求不符等等,都会被认为是协议错误。接收方需要发送 Reason Code 为 0x81 的 DISCONNECT 报文来断开连接。如果是 CONNECT 报文存在问题,那么服务端应该使用 CONNACK 报文。常见的协议错误包括,客户端在一个连接内发送了两个 CONNECT 报文、一个报文中包含了多个相同的属性,以及某个属性被设置成了一个协议不允许的值等等。但是当我们有其他更具体的 Reason Code 时,就不会使用 0x81 (Malformed Packet) 或者 0x82 (Protocol Error) 了。例如,服务端已经声明自己不支持保留消息,但客户端仍然向服务端发送保留消息,这本质上也属于协议错误,但我们会选择使用 0x9A (Retain not supported) 这个能够更清楚指明错误原因的 Reason Code。0x83Implementation specific errorCONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT报文有效,但是不被当前接收方的实现所接受。0x84Unsupported Protocol VersionCONNACK仅用于 CONNACK 报文。对于支持了 MQTT 5.0 的服务端来说,如果不支持客户端当前使用的 MQTT 协议版本,或者客户端指定了一个错误的协议版本或协议名。例如,客户端将协议版本设置为 6,那么服务端可以发送 Reason Code 为 0x84 的 CONNACK 报文,表示不支持该协议版本并且表明自己 MQTT 服务端的身份,然后关闭网络连接。当然服务端也可以选择直接关闭网络连接,因为使用 MQTT 3.1 或 3.1.1 的 MQTT 客户端可能并不能理解 0x84 这个 Reason Code 的含义。这两个版本都是在 CONNACK 报文使用 0x01 来表示不支持客户端指定的协议版本。0x85Client Identifier not validCONNACK仅用于 CONNACK 报文,表示 Client ID 是有效的字符串,但是服务端不允许。可能的情形有 Clean Start 为 0 但 Client ID 为空、或者 Client ID 超出了服务端允许的最大长度等等。0x86Bad User Name or PasswordCONNACK仅用于 CONNACK 报文,表示客户端使用了错误的用户名或密码,这也意味着客户端将被拒绝连接。0x87Not authorizedCONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT当客户端使用 Token 认证或者增强认证时,使用 0x87 来表示客户端没有被授权连接会比 0x86 更加合适。当客户端进行发布、订阅等操作时,如果没有通过服务端的授权检查,那么服务端也可以在 PUBACK 等应答报文中指定 0x87 这个 Reason Code 来指示授权结果。0x88Server unavailableCONNACK仅用于 CONNACK 报文,向客户端指示当前服务端不可用。比如当前服务端认证服务异常无法接入新客户端等等。0x89Server busyCONNACK, DISCONNECT向客户端指示服务端正忙,请稍后再试。0x8ABannedCONNACK仅用于 CONNACK 报文,表示客户端被禁止登录。例如服务端检测到客户端的异常连接行为,所以将这个客户端的 Client ID 或者 IP 地址加入到了黑名单列表中,又或者是后台管理人员手动封禁了这个客户端,当然以上这些通常需要视服务端的具体实现而定。0x8BServer shutting downDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。如果服务端正在或即将关闭,它可以通过主动发送 Reason Code 为 0x8B 的 DISCONNECT 报文的方式告知客户端连接因为服务端正在关闭而被终止。这可以帮助客户端避免在连接关闭后继续向此服务端发起连接请求。0x8CBad authentication methodCONNACK, DISCONNECT当服务端不支持客户端指定的增强认证方法,或者客户端在重新认证时使用了和之前认证不同的认证方法时,那么服务端就会发送 Reason Code 为 0x8C 的 CONNACK 或者 DISCONNECT 报文。0x8DKeep Alive timeoutDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。如果客户端没能在 1.5 倍的 Keep Alive 时间内保持通信,服务端将会发送 Reason Code 为 0x8D 的 DISCONNECT 报文然后关闭网络连接。0x8ESession taken overDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。当客户端连接到服务端时,如果服务端中已经存在使用相同 Client ID 的客户端连接,那么服务端就会向原有的客户端发送 Reason Code 为 0x8E 的 DISCONNECT 报文,表示会话被新的客户端连接接管,然后关闭原有的网络连接。不管新的客户端连接中的 Clean Start 是 0 还是 1,服务端都会使用这个 Reason Code 向原有客户端指示会话被接管。0x8FTopic Filter invalidSUBACK, UNSUBACK, DISCONNECT主题过滤器的格式正确,但是不被服务端接受。比如主题过滤器的层级超过了服务端允许的最大数量限制,或者主题过滤器中包含了空格等不被当前服务端接受的字符。0x90Topic Name invalidCONNACK, PUBACK, PUBREC, DISCONNECT主题名的格式正确,但是不被客户端或服务端接受。0x91Packet Identifier in usePUBACK, PUBREC, SUBACK, UNSUBACK表示收到报文中的 Packet ID 正在被使用,例如发送方发送了一个 Packet ID 为 100 的 QoS 1 消息,但是接收方认为当前有一个使用相同 Packet ID 的 QoS 2 消息还没有按成它的报文流程。这通常意味着当前客户端和服务端之前的会话状态不匹配,可能需要通过设置 Clean Start 为 1 重新连接来重置会话状态。0x92Packet Identifier not foundPUBREL, PUBCOMP表示未找到对应的 Packet ID,这只会在 QoS 2 的报文交互流程中发生。比如当接收方回复 PUBREC 报文时,发送方未找到使用相同 Packet ID 的等待确认的 PUBLISH 报文,或者当发送方发送 PUBREL 报文时,接收方未找到使用相同 Packet ID 的 PUBREC 报文。这通常意味着当前客户端和服务端之间的会话状态不匹配,可能需要通过设置 Clean Start 为 1 重新连接来重置会话状态。0x93Receive Maximum exceededDISCONNECT仅用于 DISCONNECT 报文,表示超出了接收最大值。MQTT 5.0 增加了流控机制,客户端和服务端在连接时通过 Receive Maximum 属性约定它们愿意并发处理的可靠消息数(QoS > 0)。所以一旦发送方发送的没有完成确认的消息超过了这一数量限制,接收方就会发送 Reason Code 为 0x93 的 DISCONNECT 报文然后关闭网络连接。0x94Topic Alias invalidDISCONNECT仅用于 DISCONNECT 报文,表示主题别名不合法。如果 PUBLISH 报文中的主题别名值为 0 或者大于连接时约定的最大主题别名,接收方会将此视为协议错误,它将发送 Reason Code 为 0x94 的 DISCONNECT 报文然后关闭网络连接。0x95Packet too largeCONNACK, DISCONNECT用于表示报文超过了最大允许长度。客户端和服务端各自允许的最大报文长度,可以在 CONNECT 和 CONNACK 报文中通过 Maximum Packet Size 属性约定。当一方发送了过大的报文,那么另一方将发送 Reason Code 为 0x95 的 DISCONNECT 报文,然后关闭网络连接。由于客户端可以在连接时设置遗嘱消息,因此 CONNECT 报文也有可能超过服务端能够处理的最大报文长度限制,此时服务端需要在 CONNACK 报文中使用这个 Reason Code。0x96Message rate too highDISCONNECT仅用于 DISCONNECT 报文,表示超过了允许的最大消息发布速率。需要注意它与 Quota exceeded 的区别,Message rate 限制消息的发布速率,比如每秒最高可发布多少消息,Quota 限制的是资源的配额,比如客户端每天可以发布的消息数量,但客户端可能在一小时内耗尽它的配额。0x97Quota exceededCONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT用于表示超出了配额限制。服务端可能会对发布端的发送配额进行限制,比如每天最多为其转发 1000 条消息。当发布端的配额耗尽,服务端就会在 PUBACK 等确认报文中使用这个 Reason Code 提醒对方。另一方面,服务端还可能限制客户端的连接数量和订阅数量,当超出这一限制时,服务端就会通过 CONNACK 或者 SUBACK 报文向客户端指示当前超出了配额。一些严格的客户端和服务端,在发现对端超出配额时,可能会选择发送 DISCONNECT 报文然后关闭连接。0x98Administrative actionDISCONNECT仅用于 DISCONNECT 报文,向客户端指示连接因为管理操作而被关闭,例如运维人员在后台踢除了这个客户端连接等等。0x99Payload format invalidCONNACK, PUBACK, PUBREC, DISCONNECT当消息中包含 Payload Format Indicator 属性时,接收方可以检查消息中 Payload 的格式与该属性是否匹配。如果不匹配,接收方需要发送 Reason Code 为 0x99 的确认报文。一些严格的客户端或者服务器,可能会直接发送 DISCONNECT 报文然后关闭网络连接。如果是 CONNECT 报文中的遗嘱消息存在问题,服务端将发送 Reason Code 为 0x99 的 CONNACK 报文然后关闭网络连接。0x9ARetain not supportedCONNACK, DISCONNECT当服务端不支持保留消息,但是客户端发送了保留消息时,服务端就会向它发送 Reason Code 为 0x9A 的 DISCONNECT 报文然后关闭网络连接。由于客户端还可以在连接时将遗嘱消息设置为保留消息,所以服务端也可能在 CONNACK 报文中使用这个 Reason Code。0x9BQoS not supportedCONNACK, DISCONNECT用于表示不支持当前的 QoS 等级。如果客户端在消息(包括遗嘱消息)中指定的 QoS 大于服务端支持的最大 QoS,服务端将会发送 Reason Code 为 0x9B 的 DISCONNECT 或者 CONNACK 报文然后关闭网络连接。在大部份情况下,这个 Reason Code 都是由服务端使用。但是在客户端收到不是来自订阅的消息,并且消息的 QoS 大于它支持的最大 QoS 时,它也会发送 Reason Code 为 0x9B 的 DISCONNECT 报文然后关闭网络连接。这种情况通常意味着服务端的实现可能存在问题。0x9CUse another serverCONNACK, DISCONNECT服务端在 CONNACK 或者 DISCONNECT 报文中通过这个 Reason Code 告知客户端应该临时切换到另一个服务端。如果另一个服务端不是客户端已知的,那么这个 Reason Code 还需要配合 Server Reference 属性一起使用,以告知客户端新的服务端的地址。0x9DServer movedCONNACK, DISCONNECT服务端在 CONNACK 或者 DISCONNECT 报文中通过这个 Reason Code 告知客户端应该永久切换到另一个服务端。如果另一个服务端不是客户端已知的,那么这个 Reason Code 还需要配合 Server Reference 属性一起使用,以告知客户端新的服务端的地址。0x9EShared Subscriptions not supportedSUBACK, DISCONNECT当服务端不支持共享订阅,但是客户端尝试建立共享订阅时,服务端可以发送 Reason Code 为 0x9E 的 SUBACK 报文拒绝这次订阅请求,也可以直接发送 Reason Code 为 0x9E 的 DISCONNECT 报文然后关闭网络连接。0x9FConnection rate exceededCONNACK, DISCONNECT用于表示客户端已超过连接速率限制。服务端可以对客户端的连接速率做出限制,客户端连接过快时,服务端可以发送 Reason Code 为 0x9F 的 CONNACK 报文来拒绝新的连接。当然这并不是绝对的情况,考虑到不是所有的客户端都会等待一段时间再重新发起连接,一些服务端实现可能会选择暂时挂起连接而不是返回 CONNACK。0xA0Maximum connect timeDISCONNECT仅用于 DISCONNECT 报文,并且只有服务端可以使用。出于安全性的考虑,服务端可以限制单次授权中客户端的最大连接时间,比如在使用 JWT 认证时,客户端连接不应在 JWT 过期后继续保持。这种情况下,服务端可以发送 Reason Code 为 0xA0 的 DISCONNECT 报文,向客户端指示连接因为超过授权的最大连接时间而被关闭。客户端可以在收到包含这个 Reason Code 的 DISCONNECT 报文后,重新获取认证凭据然后再次请求连接。0xA1Subscription Identifiers not supportedSUBACK, DISCONNECT当服务端不支持订阅标识符,但是客户端的订阅请求中包含了订阅标识符时,服务端可以发送 Reason Code 为 0xA1 的 SUBACK 报文拒绝这次订阅请求,也可以直接发送 Reason Code 为 0xA1 的 DISCONNECT 报文然后关闭网络连接。0xA2Wildcard Subscriptions not supportedSUBACK, DISCONNECT当服务端不支持通配符订阅,但是客户端的订阅请求中包含了主题通配符时,服务端可以发送 Reason Code 为 0xA2 的 SUBACK 报文拒绝这次订阅请求,也可以直接发送 Reason Code 为 0xA2 的 DISCONNECT 报文然后关闭网络连接。 使用Reason Code的注意事项 精确处理错误:利用MQTT 5.0的Reason Code,开发者可以更精确地诊断和处理连接或操作失败的原因。 优化用户体验:通过根据不同的错误代码提供更具体的错误信息或采取相应的恢复措施,可以优化最终用户的体验。 日志记录:在开发和调试过程中,记录包含Reason Code的操作可以帮助快速定位问题。 MQTT 5.0的Reason Code为MQTT协议的使用提供了更强大的错误处理能力,使得开发者能够构建更健壮、更可靠的MQTT应用。 --- ### 299. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT遗嘱消息(Last Will and Testament,简称LWT)是MQTT协议中的一个特性,允许客户端在建立连接时向服务器注册一个遗嘱消息。这个消息将在客户端异常断开连接时由服务器自动发布,通知其他客户端该客户端已离线。这个功能对于监控设备状态、实现设备断线通知等场景非常有用。 MQTT遗嘱消息的工作原理 客户端连接时指定遗嘱消息: 客户端在与MQTT服务器(Broker)建立连接时,可以指定一个遗嘱消息。这包括遗嘱消息的主题(Will Topic)、消息内容(Will Message)、消息质量(QoS)和是否保留(Retain)等信息。 服务器存储遗嘱消息: MQTT服务器接收到遗嘱消息后,会将其存储,但不立即发布。只有在满足特定条件时,服务器才会发布这个遗嘱消息。 客户端异常断开连接: 如果客户端因网络故障、设备故障或其他原因异常断开连接(不包括正常发送DISCONNECT报文的情况),MQTT服务器将判断客户端“死亡”,并自动发布之前存储的遗嘱消息。 其他客户端接收遗嘱消息: 其他订阅了遗嘱消息主题的客户端将接收到这个遗嘱消息,从而得知特定客户端已经断开连接。 使用遗嘱消息的场景 设备状态监控: 在物联网应用中,可以利用遗嘱消息监控设备的在线状态。如果设备异常断开,遗嘱消息可以通知监控系统或其他设备,采取相应措施。 用户在线状态通知: 在即时通讯应用中,遗嘱消息可以用来通知其他用户某个用户已经离线。 示例代码 以下是使用paho-mqtt客户端库(Python)设置遗嘱消息的示例: 首先,确保安装了paho-mqtt: pip install paho-mqtt 然后,创建一个MQTT客户端,设置遗嘱消息,并连接到MQTT服务器: import paho.mqtt.client as mqtt # MQTT服务器地址 broker_address = "broker.hivemq.com" # 遗嘱消息的主题和内容 will_topic = "device/status" will_message = "Device offline" # 创建MQTT客户端实例 client = mqtt.Client("ClientID") # 设置遗嘱消息 client.will_set(will_topic, payload=will_message, qos=1, retain=True) # 连接到MQTT代理 client.connect(broker_address, 1883, 60) # 进入阻塞状态,处理消息接收和发送等操作 client.loop_forever() 在这个示例中,如果客户端异常断开连接,MQTT服务器将自动发布遗嘱消息到device/status主题,消息内容为Device offline。其他订阅了这个主题的客户端将接收到这个消息,知道该设备已离线。 小结 MQTT遗嘱消息是一个强大的功能,它为客户端提供了一种机制,在无法正常断开连接时通知其他客户端或系统。这在需要高可靠性的物联网应用中尤其有用,可以帮助系统及时响应设备故障或网络问题。 --- ### 300. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT(Message Queuing Telemetry Transport)是一个轻量级的消息协议,广泛用于物联网(IoT)中设备间的通信。它支持多种消息传递模式,包括发布/订阅模式,使得数据交换变得简单高效。在MQTT协议中,保留消息(Retained Messages)是一个特殊的功能,它允许消息被保留在MQTT代理(Broker)上,直到有新的客户端订阅匹配的主题(Topic)时才被发送。 什么是MQTT保留消息? 当一个MQTT客户端向代理发布一个消息时,它可以选择将这个消息标记为“保留”。这意味着即使在消息发布之后,这个消息也会在MQTT代理上保留。当有新的客户端订阅了这个消息的主题时,这个保留的消息会立即被发送给这个新的订阅者,即使这个消息是在很久以前发布的。这样做的好处是,新的订阅者可以立即获得最新的状态更新,而不需要等待下一个状态变化的消息。 如何使用MQTT保留消息? 发布保留消息: 当客户端发布一个消息到MQTT代理时,它可以设置MQTT消息的retain标志为true。这可以通过客户端库的API完成,具体方法取决于所使用的库。例如,在Mosquitto的C库中,可以使用mosquitto_publish函数,并将retain参数设置为true。 订阅并接收保留消息: 当客户端订阅一个主题时,如果该主题有保留消息,MQTT代理会立即发送这个保留消息给客户端。客户端不需要进行任何特殊操作来接收保留消息,这是MQTT协议的标准行为。 使用保留消息的注意事项: 及时更新保留消息: 如果主题的状态发生变化,应该发布一个新的保留消息来更新状态。否则,新订阅者可能会收到过时的信息。 清除保留消息: 如果不再需要保留消息,可以通过发布一个空的消息体(payload为空)并将retain标志设置为true到相同的主题来清除保留消息。 谨慎使用: 保留消息非常有用,但如果不当使用,可能会导致意外的行为。例如,如果客户端不期望接收旧的状态信息,但主题中存在保留消息,它们将会收到这些信息。 发布保留消息 假设我们使用paho-mqtt客户端库(Python)来发布一个保留消息。首先,确保安装了paho-mqtt: pip install paho-mqtt 然后,发布一个保留消息的代码示例如下: import paho.mqtt.client as mqtt # MQTT服务器地址 broker_address = "broker.hivemq.com" # 主题 topic = "home/livingroom/temperature" # 创建MQTT客户端实例 client = mqtt.Client("Publisher") # 连接到MQTT代理 client.connect(broker_address) # 发布保留消息 # 参数:主题、消息内容、QoS、retain标志 client.publish(topic, payload="23", qos=1, retain=True) print(f"Published retained message to {topic}") # 断开连接 client.disconnect() 订阅并接收保留消息 下面是一个订阅者的示例,它订阅上面发布者使用的相同主题,并接收保留消息: import paho.mqtt.client as mqtt # MQTT服务器地址 broker_address = "broker.hivemq.com" # 主题 topic = "home/livingroom/temperature" # 当连接到MQTT代理时的回调函数 def on_connect(client, userdata, flags, rc): print("Connected with result code "+str(rc)) client.subscribe(topic) # 当接收到消息时的回调函数 def on_message(client, userdata, msg): print(f"Received message: {msg.payload.decode()} on topic {msg.topic} with QoS {msg.qos}") # 创建MQTT客户端实例 client = mqtt.Client("Subscriber") # 指定回调函数 client.on_connect = on_connect client.on_message = on_message # 连接到MQTT代理 client.connect(broker_address) # 阻塞循环,以处理接收消息和重新连接等操作 client.loop_forever() 注意事项 更新保留消息:如果主题的状态更新,应该发布一个新的保留消息以反映最新状态。 清除保留消息:通过向相同的主题发布一个空消息(payload为空字符串)并设置retain=True,可以清除保留消息。 谨慎使用:虽然保留消息功能非常有用,但在不需要旧状态信息的场景中应谨慎使用,以避免混淆和不必要的数据传输。 通过上述示例,你应该对如何在MQTT中使用保留消息有了清晰的理解。这个功能在确保新订阅者能够立即获得最新状态信息方面非常有用。 --- ### 301. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 摘要:在构建智能家居系统时,实现不同通信协议之间的互操作性是一项关键任务。modbus2mqtt项目通过桥接Modbus和MQTT协议,为此提供了一个高效的解决方案。本文深入探讨了modbus2mqtt的实现细节,包括其依赖、功能、和实际应用。 引言:在智能家居和工业自动化领域,Modbus协议常用于传感器和执行器的通信,而MQTT作为一种轻量级的消息传递协议,适用于物联网(IoT)通信。modbus2mqtt是一个Python脚本,它实现了Modbus与MQTT之间的数据转换和传输,从而在异构的智能家居环境中提供了一个集中式消息总线解决方案。 1. 技术背景与依赖性:该项目依赖于两个关键的Python库: Eclipse Paho:用于实现MQTT客户端功能,实现与MQTT代理的通信。 modbus-tk:用于处理Modbus通信,包括读取和写入Modbus从设备的寄存器。 # # modbus2mqtt - Modbus master with MQTT publishing # # Written and (C) 2015 by Oliver Wagner <owagner@tellerulam.com> # Provided under the terms of the MIT license # # Requires: # - Eclipse Paho for Python - http://www.eclipse.org/paho/clients/python/ # - modbus-tk for Modbus communication - https://github.com/ljean/modbus-tk/ # import argparse import logging import logging.handlers import time import socket import paho.mqtt.client as mqtt import serial import io import sys import csv import signal import modbus_tk import modbus_tk.defines as cst from modbus_tk import modbus_rtu from modbus_tk import modbus_tcp version="0.5" parser = argparse.ArgumentParser(description='Bridge between ModBus and MQTT') parser.add_argument('--mqtt-host', default='localhost', help='MQTT server address. Defaults to "localhost"') parser.add_argument('--mqtt-port', default='1883', type=int, help='MQTT server port. Defaults to 1883') parser.add_argument('--mqtt-topic', default='modbus/', help='Topic prefix to be used for subscribing/publishing. Defaults to "modbus/"') parser.add_argument('--clientid', default='modbus2mqtt', help='Client ID prefix for MQTT connection') parser.add_argument('--rtu', help='pyserial URL (or port name) for RTU serial port') parser.add_argument('--rtu-baud', default='19200', type=int, help='Baud rate for serial port. Defaults to 19200') parser.add_argument('--rtu-parity', default='even', choices=['even','odd','none'], help='Parity for serial port. Defaults to even') parser.add_argument('--tcp', help='Act as a Modbus TCP master, connecting to host TCP') parser.add_argument('--tcp-port', default='502', type=int, help='Port for Modbus TCP. Defaults to 502') parser.add_argument('--registers', required=True, help='Register definition file. Required!') parser.add_argument('--log', help='set log level to the specified value. Defaults to WARNING. Use DEBUG for maximum detail') parser.add_argument('--syslog', action='store_true', help='enable logging to syslog') parser.add_argument('--force', default='0',type=int, help='publish values after "force" seconds since publish regardless of change. Defaults to 0 (change only)') args=parser.parse_args() if args.log: logging.getLogger().setLevel(args.log) if args.syslog: logging.getLogger().addHandler(logging.handlers.SysLogHandler()) else: logging.getLogger().addHandler(logging.StreamHandler(sys.stdout)) topic=args.mqtt_topic if not topic.endswith("/"): topic+="/" logging.info('Starting modbus2mqtt V%s with topic prefix \"%s\"' %(version, topic)) def signal_handler(signal, frame): print('Exiting ' + sys.argv[0]) sys.exit(0) signal.signal(signal.SIGINT, signal_handler) class Register: def __init__(self,topic,frequency,slaveid,functioncode,register,size,format): self.topic=topic self.frequency=int(frequency) self.slaveid=int(slaveid) self.functioncode=int(functioncode) self.register=int(register) self.size=int(size) self.format=format.split(":",2) self.next_due=0 self.lastval=None self.last = None def checkpoll(self): if self.next_due<time.time(): self.poll() self.next_due=time.time()+self.frequency def poll(self): try: res=master.execute(self.slaveid,self.functioncode,self.register,self.size,data_format=self.format[0]) r=res[0] if self.format[1]: r=self.format[1] % r if r!=self.lastval or (args.force and (time.time() - self.last) > int(args.force)): self.lastval=r fulltopic=topic+"status/"+self.topic logging.info("Publishing " + fulltopic) mqc.publish(fulltopic,self.lastval,qos=0,retain=True) self.last = time.time() except modbus_tk.modbus.ModbusError as exc: logging.error("Error reading "+self.topic+": Slave returned %s - %s", exc, exc.get_exception_code()) except Exception as exc: logging.error("Error reading "+self.topic+": %s", exc) registers=[] # Now lets read the register definition with open(args.registers,"r") as csvfile: dialect=csv.Sniffer().sniff(csvfile.read(8192)) csvfile.seek(0) defaultrow={"Size":1,"Format":">H","Frequency":60,"Slave":1,"FunctionCode":4} reader=csv.DictReader(csvfile,fieldnames=["Topic","Register","Size","Format","Frequency","Slave","FunctionCode"],dialect=dialect) for row in reader: # Skip header row if row["Frequency"]=="Frequency": continue # Comment? if row["Topic"][0]=="#": continue if row["Topic"]=="DEFAULT": temp=dict((k,v) for k,v in row.iteritems() if v is not None and v!="") defaultrow.update(temp) continue freq=row["Frequency"] if freq is None or freq=="": freq=defaultrow["Frequency"] slave=row["Slave"] if slave is None or slave=="": slave=defaultrow["Slave"] fc=row["FunctionCode"] if fc is None or fc=="": fc=defaultrow["FunctionCode"] fmt=row["Format"] if fmt is None or fmt=="": fmt=defaultrow["Format"] size=row["Size"] if size is None or size=="": size=defaultrow["Size"] r=Register(row["Topic"],freq,slave,fc,row["Register"],size,fmt) registers.append(r) logging.info('Read %u valid register definitions from \"%s\"' %(len(registers), args.registers)) def messagehandler(mqc,userdata,msg): try: (prefix,function,slaveid,functioncode,register) = msg.topic.split("/") if function != 'set': return if int(slaveid) not in range(0,255): logging.warning("on message - invalid slaveid " + msg.topic) return if not (int(register) >= 0 and int(register) < sys.maxint): logging.warning("on message - invalid register " + msg.topic) return if functioncode == str(cst.WRITE_SINGLE_COIL): logging.info("Writing single coil " + register) elif functioncode == str(cst.WRITE_SINGLE_REGISTER): logging.info("Writing single register " + register) else: logging.error("Error attempting to write - invalid function code " + msg.topic) return res=master.execute(int(slaveid),int(functioncode),int(register),output_value=int(msg.payload)) except Exception as e: logging.error("Error on message " + msg.topic + " :" + str(e)) def connecthandler(mqc,userdata,rc): logging.info("Connected to MQTT broker with rc=%d" % (rc)) mqc.subscribe(topic+"set/+/"+str(cst.WRITE_SINGLE_REGISTER)+"/+") mqc.subscribe(topic+"set/+/"+str(cst.WRITE_SINGLE_COIL)+"/+") mqc.publish(topic+"connected",2,qos=1,retain=True) def disconnecthandler(mqc,userdata,rc): logging.warning("Disconnected from MQTT broker with rc=%d" % (rc)) try: clientid=args.clientid + "-" + str(time.time()) mqc=mqtt.Client(client_id=clientid) mqc.on_connect=connecthandler mqc.on_message=messagehandler mqc.on_disconnect=disconnecthandler mqc.will_set(topic+"connected",0,qos=2,retain=True) mqc.disconnected =True mqc.connect(args.mqtt_host,args.mqtt_port,60) mqc.loop_start() if args.rtu: master=modbus_rtu.RtuMaster(serial.serial_for_url(args.rtu,baudrate=args.rtu_baud,parity=args.rtu_parity[0].upper())) elif args.tcp: master=modbus_tcp.TcpMaster(args.tcp,args.tcp_port) else: logging.error("You must specify a modbus access method, either --rtu or --tcp") sys.exit(1) master.set_verbose(True) master.set_timeout(5.0) while True: for r in registers: r.checkpoll() time.sleep(1) except Exception as e: logging.error("Unhandled error [" + str(e) + "]") sys.exit(1) 2. 功能概述:modbus2mqtt作为Modbus主设备运行,持续轮询连接的Modbus从设备,并将读取的数据通过MQTT发布。它支持自定义的轮询频率和寄存器地址,同时也能处理Modbus的写操作。 3. 命令行参数:脚本通过命令行参数提供了高度的定制性,包括设置MQTT服务器的地址和端口、定义MQTT主题前缀、配置Modbus RTU串口或TCP连接参数,以及指定寄存器定义文件。 4. 寄存器定义与消息发布:寄存器的定义存储在CSV文件中,包含寄存器地址、大小、格式和轮询频率等信息。脚本根据这些定义轮询Modbus寄存器,并将结果发布到相应的MQTT主题。 5. 高级特性:除了基础的读功能,modbus2mqtt还支持写入Modbus线圈和寄存器,允许通过MQTT消息对Modbus设备进行控制。此外,脚本支持强制定时发布功能,确保即使数据未变化也能定期更新状态。 6. 应用场景:modbus2mqtt适用于需要将Modbus设备集成进基于MQTT的智能家居或工业自动化系统的场景。例如,在智能家居中,可以通过MQTT控制和监视基于Modbus的温度传感器、开关等设备。 结论:modbus2mqtt弥合了Modbus和MQTT两大主流通信协议的差异,为智能家居和工业自动化系统提供了一种有效的数据集成方案。通过灵活的配置和强大的功能,它能够满足各种复杂场景的需求。 --- ### 302. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言在使用基于M2Mqtt.Net的Mqtt客户端进行网络通信时,面对网络波动或服务端不稳定情况,实现客户端的自动重连机制变得至关重要。本文详细介绍了如何在C#环境下使用M2Mqtt.Net库实现这一功能。 一、M2Mqtt.Net客户端的关键特性 在实现重连机制前,了解M2Mqtt.Net客户端的一些关键特性是必要的: 服务端地址解析: 如果服务端地址不可解析,会导致MqttClient对象无法实例化,从而引发异常。 连接状态管理: 在Connect方法无法建立连接时,会引发异常,并使IsConnected属性为false。 连接断开处理: 服务端断开将触发ConnectionClosed事件,并将IsConnected置为false。 重新连接和订阅: 重新连接后,需要重新订阅相关主题。 订阅参数要求: 在调用MqttClient.Subscribe方法时,订阅主题数组和相应的qosLevel数组长度必须一致。 二、重连流程控制 以下是自动重连机制的主要实现步骤: 1. 自动重连主体方法 _TryContinueConnect private void _TryContinueConnect() { if (IsConnected) return; Thread retryThread = new Thread(new ThreadStart(delegate { while (_MqttClient == null || !_MqttClient.IsConnected) { if (_ToClose) break; if (_MqttClient == null) { _BuildClient(); Thread.Sleep(3000); continue; } try { _TryCount++; _Connect(); } catch (Exception ce) { Debug.WriteLine("re connect exception:" + ce.Message); } if (!_MqttClient.IsConnected) { Thread.Sleep(2000); } } })); retryThread.Start(); } 2. 实例化客户端方法 _BuildClient private void _BuildClient() { try { _MqttClient = new MqttClient(_MqttServer); _MqttClient.MqttMsgPublishReceived += client_MqttMsgPublishReceived; _MqttClient.ConnectionClosed += (sender, e) => { if (!_ToClose) { _TryContinueConnect(); } }; } catch (Exception e) { Debug.WriteLine("build client error:" + e.Message); } } 3. 尝试连接方法 _Connect private void _Connect() { if (String.IsNullOrEmpty(_MqttUsername)) { var b = _MqttClient.Connect(_MqttClientId); } else { var b = _MqttClient.Connect(_MqttClientId, _MqttUsername, _MqttUserpass); } if (_MqttClient.IsConnected) { _MqttClient.Subscribe(new string[] { "topic1", "topic2" }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE }); } } 在这个完整的代码示例中,我们可以看到如何在客户端断开连接时自动重连。在_TryContinueConnect方法中,如果客户端未连接,则会启动一个新线程来尝试重新连接,直到连接成功或者明确地中断重连过程。同时,_BuildClient方法中的异常处理确保了在无法实例化MqttClient时能够正确地记录错误,并且通过绑定事件处理器来处理消息接收和连接断开的情况。最后,_Connect方法则负责处理客户端的连接逻辑,并在连接成功后重新订阅所需的主题。 三、重连逻辑详解 在_TryContinueConnect方法的循环中,不断检查客户端的连接状态,并在断开时尝试重连。每次尝试失败后,线程会暂停一段时间后再次尝试。 四、实际应用和调整 在实际应用中,这个机制显示了良好的稳定性和灵活性。延时时间可以根据网络环境和应用需求进行调整,以达到最优的重连效果。 结语通过上述步骤,我们可以在C#环境中有效实现Mqtt客户端的断线重连机制。这不仅提高了通信的稳定性,还增强了应用的健壮性,是网络通信中不可或缺的一环。 --- ### 303. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 逐步指南 引言 本指南将逐步展示如何部署和配置IoTAgent-JSON物联网代理,用于将设备连接到外部的NGSI代理(即上下文代理)。 IoTAgent-JSON物联网代理作为一个网关,使用MQTT协议与NGSI代理(或使用NGSI协议的其他组件)进行通信。通信基于一系列单向的MQTT主题(即:每个主题用于发布设备信息或订阅实体更新,但不是两者兼具)。每个主题都有相同的前缀,形式如下: /<apiKey>/<deviceId>/topicSpecificPart 其中apiKey是用于逻辑分组设备(和安全问题)的字母数字字符串,deviceId是唯一标识设备的ID。API密钥可以为IoT代理的一个实例全局配置,或为特定设备组专门配置(如后续章节所述)。 该协议的详细规范可在此处找到。 本指南将通过一个常见场景的逐步示例来展示代理的使用,从IoT代理设置到测量报告(包括单独配置设备的情况和首先配置具有新API密钥的设备组的情况)。开始指南前,请确保满足下一节中的所有要求。 在开始教程之前,我们需要一些关于即将部署服务的信息。我们将使用以下数据,模拟智能家居应用: 服务:myhome 子服务:/environment 设备ID:sensor01、sensor02 和 actuator01 先决条件 本逐步指南假设您将在一台单独的机器上安装所有软件,该机器安装了Red Hat 6.5 Linux。因此,它可能不适用于生产目的的架构,但应作为一个开发机来测试MQTT物联网代理。所有命令都应该在同一台机器上执行(甚至包括curl和mosquitto-pub命令),但将它们更改为从外部机器执行应该是一个简单的任务。 本教程选择的MQTT代理是Mosquitto,尽管可以用任何其他标准MQTT代理替代。本指南还将使用Mosquitto命令工具来测试安装和展示模拟设备与上下文代理之间的信息交换。 推荐软件及版本列表如下: Orion上下文代理(v2.5.0) Node.js(v10) Mosquitto(v1.4.7)(开箱即用设置) Curl(v7.19.7) Git(v1.7.1) 这些是编写本教程时使用的版本,但任何高于这些版本的版本也应该工作(早期版本也可能工作,但也可能不工作,因此我们鼓励您使用高于这些版本的版本)。 为了提高可读性,所有命令都将以root身份执行。要使用其他用户,请给予其适当权限并像往常一样使用sudo(从RPM包安装会为代理创建一个特殊用户,但在本教程中不会使用)。 使用默认API密钥配置单个设备 安装IoT代理 安装IoT代理有多种方式。在本教程中,我们将从仓库克隆代理的最新版本。有关不同设置,请查看主README.md文件中的安装指南。 我们将在/opt仓库中安装我们的IoT代理。要执行此操作,请转到文件夹并使用以下命令克隆仓库: cd /opt git clone https://github.com/telefonicaid/iotagent-json.git 现在仓库已被克隆,请进入新目录并使用以下命令安装依赖项: cd iotagent-json npm install 现在,通过执行以下命令在后台运行代理: nohup bin/iotagent-json &> /var/log/iotAgent& 代理现在应该在北端口(默认为4041)监听。使用netstat命令检查: netstat -ntpl | grep 4041 您应该看到如下输出: tcp 0 0 0.0.0.0:4041 0.0.0.0:* LISTEN 18388/node 检查一切是否正常工作的简单方法是从IoT代理的北端口获取版本: curl http://localhost:4041/iot/about 结果将是一个JSON文档,指示IoTAgent-JSON IoTA版本和正在使用的IoTA库版本: { "libVersion": "0.9.5", "port": 4041, "baseRoot": "/", "version": "0.1.5" } 您也可以在nohup命令创建的/var/log/iotAgent文件中检查日志。 IoT代理配置 IoTAgent的所有配置都可以通过修改单个文件config.js来完成。默认值应该满足本教程的需求。 有关这些值的详细描述,请查看iotagent-node-lib配置文档。 在遵循本教程时,您可能想要更改的一个配置值是logLevel。如果您在遵循指南时遇到任何问题,或者您只是想了解IoTA内部发生了什么,请将其值设置为DEBUG。 还要注意,deviceRegistry的配置类型设置为memory。这意味着当IoT代理重新启动时,设备注册表的所有内容都将从内存中擦除。这意味着在测试环境中使用,它将迫使您在重新启动代理后重新配置所有设备。要获得持久的注册表,请查看文档了解如何将IoTA连接到MongoDB实例。 配置设备 为了开始使用IoTA,必须配置新设备。我们将使用curl命令创建它。执行以下命令: curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{ "devices": [ { "device_id": "sensor01", "entity_name": "LivingRoomSensor", "entity_type": "multiSensor", "attributes": [ { "object_id": "t", "name": "Temperature", "type": "celsius" }, { "object_id": "l", "name": "Luminosity", "type": "lumens" } ] } ] } ' 'http://localhost:4041/iot/devices' 这个命令将创建最简单的设备类型,只声明了两个活动属性:温度和亮度。 我们还没有为我们的设备创建特定配置,因此API密钥将是IoTA的默认密钥(即:1234)。这个默认API密钥可以在配置文件中更改。 使用设备发送测量值 现在我们可以模拟一些设备的测量值。由于我们的设备具有设备ID sensor01,我们正在使用的API密钥是默认的1234,我们可以使用以下命令使用mosquitto命令行客户端发送测量值: mosquitto_pub -t /1234/sensor01/attrs -m '{"l":4,"t": "31.5"}' 这个命令应该将所有信息发布到上下文代理。对设备实体执行queryContext操作应该给出我们发布的信息: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -d '{ "entities": [ { "isPattern": "false", "id": "LivingRoomSensor", "type": "multiSensor" } ] }' 'http://localhost:1026/v1/queryContext' 结果响应应如下所示: { "contextResponses": [ { "contextElement": { "type": "multiSensor", "isPattern": "false", "id": "LivingRoomSensor", "attributes": [ { "name": "Luminosity", "type": "lumens", "value": "4" }, { "name": "Temperature", "type": "celsius", "value": "31.5" } ] }, "statusCode": { "code": "200", "reasonPhrase": "OK" } } ] } 从上下文代理检索配置参数IoTAgent-JSON物联网代理提供了一种特殊机制,用于从代表设备的实体中检索信息,以便设备配置。这种机制基于两个特殊主题,后缀分别为/configuration/commands和/configuration/values。为了测试此功能,我们首先将为代表设备的上下文代理实体添加一些配置属性。我们将使用以下NGSI请求添加sleepTime属性: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Cache-Control: no-cache" -d '{ "value" : "300" }' 'http://localhost:1026/v1/contextEntities/LivingRoomSensor/attributes/sleepTime' 当IoT代理请求配置值时,它会向上下文代理请求这些值。一旦收集到这些值,它将通过带有'/configuration/values'后缀的主题将它们发送到设备。要使用我们的模拟设备检查此操作,请执行以下行: mosquitto_sub -t /1234/sensor01/configuration/values 将此命令保留在单独的窗口中,同时执行以下步骤。现在我们可以发送类似以下的MQTT请求,向IoT代理请求属性值: mosquitto_pub -t /1234/sensor01/configuration/commands -m '{ "type": "configuration", "fields": [ "sleepTime" ] }' 如果我们现在返回到订阅窗口,我们应该能够看到sleepTime命令的值: { "sleepTime": "300", "dt": "20160209T111442Z" } 与设备请求的所有信息一起,IoT代理将在响应的dt字段中报告服务器时间。 使用配置配置多个设备 在需要配置具有类似特征的一组设备的情况下,可以为它们创建公共配置。此配置配置可用于通过为每个组建立特定的API密钥来分隔服务之间的设备消息。这可用于保护特定设备组的访问权限(在Mosquitto MQTT代理的最后一节中将展示如何实现这一点的示例)。 配置 首先,我们将使用引言部分定义的数据配置一个新的配置。为此,我们将发出以下命令: curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{ "services": [ { "resource": "/iot/json", "apikey": "AAFF9977", "type": "potSensor" } ] } ' 'http://localhost:4041/iot/services' 这将使该服务、子服务和类型下配置的设备使用提供的APIKey作为MQTT主题中的APIKey前缀。 配置设备 对于支持自动设备配置的IoT代理,配置一个配置就足以开始使用使用该配置的设备。对于那些不支持的代理,每个特定设备必须配置,以便在设备注册表中保存其deviceID。设备配置与单个设备的配置非常似: curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{ "devices": [ { "device_id": "sensor02", "entity_name": "RosesPot", "entity_type": "potSensor", "attributes": [ { "name": "humidity", "type": "degrees" }, { "name": "happiness", "type": "subjective" } ] } ] } ' 'http://localhost:4041/iot/devices' 发送测量数据 现在我们可以像单个设备配置的情况一样模拟测量。使用以下命令发送新的模拟测量: mosquitto_pub -t /AAFF9977/sensor02/attrs -m '{"humidity": 76,"happiness": "Not bad"}' 请注意,在这种情况下,API密钥不是默认的,而是我们在配置API中定义的。我们可以通过再次调用上下文代理来检查一切是否正常: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -d '{ "entities": [ { "isPattern": "false", "id": "RosesPot", "type": "potSensor" } ] }' 'http://localhost:1026/v1/queryContext' 我们将得到类似这样的响应: { "contextResponses" : [ { "contextElement" : { "type" : "potSensor", "isPattern" : "false", "id" : "RosesPot", "attributes" : [ { "name" : "happiness", "type" : "subjective", "value" : "Not bad" }, { "name" : "humidity", "type" : "degrees", "value" : "76" } ] }, "statusCode" : { "code" : "200", "reasonPhrase" : "OK" } } ] } 这表明我们发送的测量信息已正确写入上下文代理。 使用ACL保护配置访问权限 概述 使用特殊API密钥使IoT代理管理员有机会为每组设备设置不同的MQTT代理级别权限,使用不同的授权机制分隔不同组的访问。使用开箱即用的Mosquitto设置,任何设备(实际上,任何MQTT客户端)都可以冒充其他设备发送信息或读取其实体中的信息,只需知道它们的API密钥和设备ID。为了避免这个问题,我们将创建一个ACL,为我们的配置赋予特殊权限,并为该组的设备设置一组凭据(应与设备秘密共享)。为了简单起见,我们将使用一组用户和密码凭据,所有该组的设备都使用相同的凭据(也可以使用其他认证方式,如证书,请查阅Mosquitto文档了解其他选项)。IoTA访问也可能发生设备冒充问题(因为IoTA是另一个MQTT客户端,默认情况下是匿名的)。为了保护IoTA的交互,将创建另一个用户。 配置 为了创建用户,我们将使用mosquitto提供的密码工具。执行以下命令: touch /etc/mosquitto/pwfile mosquitto_passwd -b /etc/mosquitto/pwfile iota iota mosquitto_passwd -b /etc/mosquitto/pwfile potteduser pottedpass 这将创建两组凭据(登录/密码):iota/iota 和 potteduser/pottedpass。可以使用ACL文件赋予不同主题的权限。要创建一个ACL文件,只需创建一个新的`/etc/mosquitto/aclfile`文件,内容如下: topic read $SYS/# topic write /1234/+/attrs topic write /1234/+/attrs/# topic write /1234/+/configuration/commands topic read /1234/+/configuration/values user iota topic /# user potteduser topic write /AAFF9977/+/attrs topic write /AAFF9977/+/attrs/# topic write /AAFF9977/+/configuration/commands topic read /AAFF9977/+/configuration/values pattern write $SYS/broker/connection/%c/state 此文件中有三个感兴趣的部分: 1. 第一部分为默认API密钥(本例中为1234)定义了一组主题。这些主题根据设备将要执行的动作被标记为读或写。禁止除所定义动作之外的访问,以及向读主题发布或相反的操作。这确保了没有设备能冒充IoT代理,但这并不阻止一个设备冒充其他设备。此访问是匿名的。 2. iota用户是认证的,可以访问一切,因为假设是代理的所有者(只有管理员应该访问此用户)。 3. 对于potteduser账户,权限与匿名设备类似,但前缀是不同的API密钥。这确保了来自其他组的设备(假定没有作为potteduser的有效凭据)无法冒充该组的设备,或订阅该组设备发送的信息。 在我们重新开始测试之前,还需要做两个更改。首先,我们应该在IoTA配置中添加Mosquitto的IoTA凭据,以便其获得MQTT代理主题的完全访问权限。为此,请编辑`/opt/iotajson/config.js`文件,将config.mqtt部分更改为如下所示: config.mqtt = { host: "localhost", port: 1883, defaultKey: "1234", username: "iota", password: "iota", }; 最后一个操作是编辑`/etc/mosquitto/mosquitto.conf`,将aclfile和pwfile文件添加到配置中。完成的配置应该类似于以下内容: pid_file /var/run/mosquitto.pid persistence true persistence_location /var/lib/mosquitto/ log_dest file /var/log/mosquitto/mosquitto.log #acl_file /etc/mosquitto/aclfile password_file /etc/mosquitto/pwfile include_dir /etc/mosquitto/conf.d 完成所有更改后,重启mosquitto: service mosquitto restart 并重新运行IoT代理(您可以使用ps或netstat检查其PID并杀死它)。 测试 配置和设备配置 为了测试ACL文件,首先像前一章中那样配置配置和设备,但使用不同的设备,数据如下:- 名称:DaisyPot- 设备ID:sensor03重要的是,您配置的配置使用的API密钥与ACL中声明的完全相同。设备配置请求如下: curl -X POST -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -H "Content-Type: application/json" -H "Cache-Control: no-cache" -d '{ "devices": [ { "device_id": "sensor03", "entity_name": "DaisyPot", "entity_type": "potSensor", "attributes": [ { "name": "humidity", "type": "degrees" }, { "name": "happiness", "type": "subjective" } ] } ] } ' 'http://localhost:4041/iot/devices' 发送测量数据 现在我们可以尝试使用与第一种情况相同的命令发送新的测量数据: mosquitto_pub -t /AAFF9977/sensor03/attrs -m '{"humidity": 76,"happiness": "Not bad"}' 如果我们使用queryContext检查更改是否已传递到上下文代理,我们会发现这些测量数据已被忽略: curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Fiware-Service: myHome" -H "Fiware-ServicePath: /environment" -d '{ "entities": [ { "isPattern": "false", "id": "DaisyPot", "type": "potSensor" } ] }' 'http://localhost:1026/v1/queryContext' 检查IoTAgent日志,您会看到请求完全被忽略了。问题在于,客户端试图以匿名方式发布到仅允许potteduser发布新消息的受ACL保护的主题。如果我们使用我们为用户生成的凭证再次尝试: mosquitto_pub -t /AAFF9977/sensor03/attrs -m '{"humidity": 76,"happiness": "Not bad"}' -u potteduser -P pottedpass 并再次执行queryContext操作,我们将获得更新后的实体: { "contextResponses": [ { "contextElement": { "type": "potSensor", "isPattern": "false", "id": "DaisyPot", "attributes": [ { "name": "happiness", "type": "subjective", "value": " " }, { "name": "humidity", "type": "degrees", "value": " " } ] }, "statusCode": { "code": "200", "reasonPhrase": "OK" } } ] } 这表明我们发送的测量信息已经正确地传输到了上下文代理。 安装 安装JSON物联网代理有三种方式:使用Git、RPM或Docker镜像。 使用GIT 要安装TT代理,只需克隆项目并安装依赖项: git clone https://github.com/telefonicaid/iotagent-json.git npm install 要启动物联网代理,从项目的根文件夹中输入: bin/iotagent-json 使用RPM 项目包含一个脚本,用于生成可在Red Hat 6.5兼容的Linux发行版上安装的RPM。RPM依赖于Node.js 0.10版本,因此建议使用EPEL仓库。 要创建RPM,请在/rpm文件夹内执行以下脚本: create-rpm.sh -v <versionNumber> -r <releaseNumber> 一旦RPM生成,可以使用以下命令安装: yum localinstall --nogpg <nameOfTheRPM>.rpm 将作为linux服务安装,可以像往常一样使用service命令启动: service iotaJSON start 使用Docker Docker Hub上提供了一个Docker容器。它将使用config.js中定义的默认设置启动容器。 docker run -it --init fiware/iotagent-json 要使用您自己的配置,可以挂载本地配置文件: docker run -it --init -v <path-to-configuration-file>:/opt/iotajson/new_config.js fiware/iotagent-json -- new_config.js 作为替代,也可以使用环境变量传递配置,如“使用环境变量配置”小节所述。 使用 要执行JSON物联网代理,只需从根文件夹执行以下命令: bin/iotagentMqtt.js 这将在前台启动JSON物联网代理。使用标准Linux命令将其设置为在后台运行。 无参数启动时,物联网代理将预期在根文件夹中找到一个带有配置的config.js文件。可以传递一个参数,带有新配置文件的路径(相对于应用程序文件夹),以替代默认配置。 配置 概述 物联网代理的所有配置都存储在一个配置文件中(通常安装在根文件夹中)。 这个配置文件是一个JavaScript文件,包含三个配置章节: iota:此对象存储IoT代理北端口的配置,完全由IoT代理库管理。更多关于这些选项的信息可以在这里找到。 mqtt:此对象存储特定于MQTT的配置。详细描述可在下一节中找到。 http:此对象存储特定于HTTP的配置。详细描述可在下一节中找到。 还有一些全局配置选项: configRetrieval:此标志指示是否应使用来自库最新版本的双向插件处理传入IoT代理的通知,或使用JSON特定的配置检索机制(如用户手册中所述)。不允许同时使用这两种机制。 config.defaultKey:设备缺乏提供的配置时使用的默认API密钥。 config.defaultTransport:用于解析传入命令和懒惰属性的MQTT传输协议代码,以防无法为设备推断传输协议。 compressTimestamp:此标志启用时间戳压缩机制,如用户手册中所述。 MQTT配置 以下是目前可用的MQTT配置选项: protocol:用于连接MQTT代理的协议(mqtt、mqtts、tcp、tls、ws、wss)。默认为mqtt host:MQTT代理的主机。 port:MQTT代理监听的端口。 defaultKey:在没有配置的情况下为设备配置的默认API密钥。 ca:用于验证服务器证书的ca证书(可选)。默认信任Mozilla精心策划的知名CA。当使用此选项明确指定CA时,Mozilla的CA将被完全替换。 cert:PEM格式的证书链,用于验证连接到MQTT代理(可选)。仅在使用mqtts、tls或wss作为连接协议时使用。 key:PEM格式的可选私钥,用于客户端连接MQTT代理(可选)。仅在使用mqtts、tls或wss作为连接协议时使用。包含的CA列表将用于确定服务器是否获得授权。 rejectUnauthorized:是否拒绝未经提供的CA授权的任何连接。此选项仅在使用mqtts、tls或wss协议时有效(默认为true)。如果使用自签名证书,请将其设置为false,但请注意,您将暴露于中间人攻击,因此这是不推荐用于生产环境的配置。 username:标识IOTA对MQTT代理的用户名(可选)。 password:如果提供了用户名,则使用的密码(可选)。 qos:QoS级别:至多一次(0),至少一次(1),正好一次(2)。 (默认为0)。 retain:保留标志(默认为false)。 retries:MQTT连接错误重试次数(默认为5次)。 retryTime:MQTT连接重试间隔时间(默认为5秒)。 keepalive:客户端与MQTT代理之间保持连接打开的时间(默认为60秒)。如果您遇到断开连接问题,建议使用大于0的值(如本例所述)。 avoidLeadingSlash:此标志设置代理是否发布带有斜杠(旧版本中的默认)或不带斜杠的主题。请参见讨论。 clean:此标志默认为true,设置为false以接收离线时的QoS 1和2消息。 clientId:标识mqtt代理中的客户端的字符串ID。默认使用由固定前缀iotajson_和随机后缀组成的字符串,即iotajson_43bf8a3a。 TLS选项(即ca、cert、key、rejectUnauthorized)直接与Node.js的tls模块支持的选项相关。 AMQP绑定配置 config.amqp部分的配置文件包含连接到AMQP代理所需的所有信息。接受以下属性: host:AMQP代理所在的主机。 port:AMQP代理监听的端口 username:标识IOTA对AMQP代理的用户名(可选)。 password:如果提供了用户名,则使用的密码(可选)。 exchange:AMQP代理中的交换机 queue:AMQP代理中的队列 durable:持久队列标志(默认为false)。 retries:AMQP连接错误重试次数(默认为5次)。 retryTime:AMQP连接重试间隔时间(默认为5秒)。 HTTP绑定配置 config.http部分的配置文件包含启动HTTP传输协议绑定的HTTP服务器所需的所有信息。接受以下选项: port:南端口,HTTP监听器将在此监听设备的信息。 timeout:HTTP端点的HTTP超时时间(以毫秒为单位)。 key:HTTPS绑定的私钥路径 cert:HTTPS绑定的证书路径 使用环境变量配置 一些更常见的变量可以使用环境变量配置。覆盖config.iota集中的一般参数的变量在IoTA库配置手册中进行了描述。 与全局配置相关的变量在下表中描述。 环境变量配置属性IOTA_CONFIG_RETRIEVALconfigRetrievalIOTA_DEFAULT_KEYdefaultKeyIOTA_DEFAULT_TRANSPORTdefaultTransport 与特定JSON绑定相关的变量在下表中描述。 环境变量配置属性IOTA_MQTT_PROTOCOLmqtt.protocolIOTA_MQTT_HOSTmqtt.hostIOTA_MQTT_PORTmqtt.portIOTA_MQTT_CAmqtt.caIOTA_MQTT_CERTmqtt.certIOTA_MQTT_KEYmqtt.keyIOTA_MQTT_REJECT_UNAUTHORIZEDmqtt.rejectUnauthorizedIOTA_MQTT_USERNAMEmqtt.usernameIOTA_MQTT_PASSWORDmqtt.passwordIOTA_MQTT_QOSmqtt.qosIOTA_MQTT_RETAINmqtt.retainIOTA_MQTT_RETRIESmqtt.retriesIOTA_MQTT_RETRY_TIMEmqtt.retryTimeIOTA_MQTT_KEEPALIVEmqtt.keepaliveIOTA_MQTT_AVOID_LEADING_SLASHmqtt.avoidLeadingSlashIOTA_MQTT_CLEANmqtt.cleanIOTA_MQTT_CLIENT_IDmqtt.clientIdIOTA_MQTT_DISABLEDmqtt.disabledIOTA_AMQP_HOSTamqp.hostIOTA_AMQP_PORTamqp.portIOTA_AMQP_USERNAMEamqp.usernameIOTA_AMQP_PASSWORDamqp.passwordIOTA_AMQP_EXCHANGEamqp.exchangeIOTA_AMQP_QUEUEamqp.queueIOTA_AMQP_DURABLEamqp.durableIOTA_AMQP_RETRIESamqp.retriesIOTA_AMQP_RETRY_TIMEamqp.retryTimeIOTA_AMQP_DISABLEDamqp.disabledIOTA_HTTP_HOSThttp.hostIOTA_HTTP_PORThttp.portIOTA_HTTP_TIMEOUThttp.timeoutIOTA_HTTP_KEYhttp.keyIOTA_HTTP_CERThttp.cert (HTTP相关的环境变量将在即将推出的HTTP绑定中使用) IOTA_MQTT_CA、IOTA_MQTT_CERT、IOTA_MQTT_KEY环境变量应提供文件名,其内容将用于配置属性。 高性能配置 Node.js是单线程的并使用非阻塞I/O,允许它扩展到数万个并发操作。然而,Node.js有一些薄弱点和漏洞,可能会导致基于Node.js的系统在遇到快速流量增长时表现出性能不足。 此外,了解运行node.js服务器的环境很重要,因为它有限制。主机上有两种类型的限制:硬件和软件。硬件限制很容易发现。您的应用程序可能正在消耗所有内存,并需要使用磁盘继续工作。通过升级您的物理或虚拟主机来增加更多内存似乎是正确的选择。 此外,Node.js应用程序也有软件内存限制(由V8强加),因此在执行服务时我们不能忘记这些限制。在64位环境中,您的应用程序默认运行在1 GB的V8限制下。如果您的应用程序在高流量场景中运行,您将需要更高的限制。其他参数也是如此。 这意味着我们需要对node.js的执行和系统配置进行一些更改: Node.js标志 --use-idle-notification 关闭使用空闲通知以减少内存占用。 --expose-gc 使用expose-gc命令启用垃圾收集器的手动控制。在IoT代理的情况下,没有实现,因为需要在服务器代码中实现对垃圾收集器的调用,不过推荐的值是每30秒。 --max-old-space-size=xxxx 在这种情况下,我们希望增加每个V8节点进程的堆内存限制,以便使用最大容量而不是64位机器上的默认1.4Gb(32位机器上为512Mb)。建议至少使用物理或虚拟实例总内存的一半。 用户软件限制 Linux内核提供了一些关于系统相关限制和最大值的配置。在有多个用户的分布式环境中,通常需要控制每个用户可用的资源。然而,当只有一个可用用户但这个用户由于高性能应用程序需要大量资源时,默认限制不适当,需要更改以满足高性能要求。这些限制包括最大文件句柄计数、最大文件锁计数、最大进程计数等。 您可以通过执行命令查看系统的限制: bash ulimit -a 您可以在limits.conf文件中定义相应的限制。此配置文件语法的描述适用于/etc/security/limits.conf文件和/etc/security/limits.d目录中的*.conf文件。您可以在limits.con - linux手册页中获取有关limits.conf的更多信息。建议更改的值如下: core 核心文件大小的限制,以KB为单位,我们建议将硬类型和软类型都更改为无限。 * soft core unlimited * hard core unlimited data 最大数据大小,以KB为单位,我们建议将硬类型和软类型都更改为无限。 * soft data unlimited * hard data unlimited fsize 最大文件大小,以KB为单位,我们建议将硬类型和软类型都更改为无限。 * soft fsize unlimited * hard fsize unlimited memlock 最大锁定内存地址空间,以KB为单位,我们建议将硬类型和软类型都更改为无限。 * memlock unlimited * memlock unlimited nofile 最大打开文件描述符数量,我们建议将硬类型和软类型都更改为65535。 * soft nofile 65535 * hard nofile 65535 RSS 最大常驻集大小,以KB为单位(在Linux 2.4.30及更高版本中忽略),我们建议将硬类型和软类型都更改为无限。 * soft rss unlimited * hard rss unlimited stack 最大堆栈大小,以KB为单位,我们建议将硬类型和软类型都更改为无限。 * soft stack unlimited * hard stack unlimited nproc 最大进程数,我们建议将硬类型和软类型都更改为无限。 * soft nproc unlimited * hard nproc unlimited 您可以查看此文件夹中提供的limits.conf文件,了解所有提供的值。 配置内核参数 sysctl用于在运行时修改内核参数。我们计划修改相应的/etc/sysctl.conf文件。您可以在sysctl和sysctl.conf的相应手册页中获取更多信息。您可以使用命令sysctl -a搜索所有内核参数 fs.file-max 可分配的最大文件句柄数,推荐值为1000000。 fs.file-max = 1000000 fs.nr_open 可以打开的最大文件句柄数,推荐值为1000000。 fs.nr_open = 1000000 net.netfilter.nf_conntrack_max 连接跟踪表的大小。默认值是nf_conntrack_buckets值的4倍。 net.nf_conntrack_max = 1048576 有关任何其他内核参数的更多详细信息,请查看示例sysctl.conf文件。 打包 唯一允许的包类型是RPM。要执行打包脚本,系统中必须有RPM构建工具。 从项目的根文件夹创建RPM,使用以下命令: cd rpm ./create-rpm.sh -v <version-number> -r <release-number> 其中<version-number>是您希望包具有的版本(x.y.z),<release-number>是依赖于先前安装的递增数字。 --- ### 304. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTTnet 是一个高性能的MQTT类库,支持.NET Core和.NET Framework。 MQTTnet 原理 MQTTnet 是一个用于.NET的高性能MQTT类库,实现了MQTT协议的各个层级,包括连接、会话、发布/订阅、QoS(服务质量)等。其原理涉及以下关键概念 1、MqttClient: MqttClient 是MQTTnet库中表示客户端的主要类。它负责与MQTT服务器建立连接,并处理消息的发布和订阅。 2、MqttServer: MqttServer 则表示MQTT服务器,负责接受客户端的连接,管理连接状态,并转发消息到相应的订阅 3、消息处理: MQTT消息分为发布消息和订阅消息。发布消息由客户端发送到服务器,然后由服务器广播给所有订阅者。 4、QoS(服务质量): MQTT支持不同级别的服务质量,包括0、1和2。MQTTnet允许你根据需要选择适当的QoS级别。 5、异步通信: MQTTnet广泛使用异步编程模型,允许并发处理多个连接,提高性能。 MQTTnet 优点 1、高性能: MQTTnet被设计为高性能的MQTT库,适用于处理大量的消息和连接。 2、跨平台: 支持.NET Core和.NET Framework,使其可以在不同的操作系统上运行。 3、灵活性: 提供了许多配置选项,允许你根据应用程序的需求进行调整。 4、WebSocket支持: 支持通过WebSocket协议进行通信,适用于Web应用程序。 5、活跃社区: MQTTnet有一个活跃的社区,提供了文档、示例和支持。 使用方法(服务端、客户端、WEB端) 下面是一个简单的示例,演示如何在.NET Core中使用MQTTnet创建一个基本的MQTT服务端和客户端。请注意,这个示例只是为了演示基本概念,实际应用中可能需要更多的配置和错误处理。 服务端示例 using System; using MQTTnet; using MQTTnet.Server; class Program { static async System.Threading.Tasks.Task Main(string[] args) { // 创建服务端配置 var optionsBuilder = new MqttServerOptionsBuilder() .WithDefaultEndpointPort(1883) .WithConnectionValidator(c => { Console.WriteLine($"Client connected: {c.ClientId}"); // 可以在这里添加连接验证逻辑 }); // 创建MQTT服务器实例 var mqttServer = new MqttFactory().CreateMqttServer(); // 处理连接成功事件 mqttServer.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(e => { Console.WriteLine($"Client connected: {e.ClientId}"); }); // 处理连接断开事件 mqttServer.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(e => { Console.WriteLine($"Client disconnected: {e.ClientId}"); }); // 处理接收到消息事件 mqttServer.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(e => { Console.WriteLine($"Received message from client {e.ClientId}: {e.ApplicationMessage.Payload}"); }); // 启动MQTT服务器 await mqttServer.StartAsync(optionsBuilder.Build()); Console.WriteLine("MQTT Server已启动。按任意键退出。"); Console.ReadLine(); // 停止MQTT服务器 await mqttServer.StopAsync(); } } 客户端示例 using System; using System.Text; using System.Threading; using System.Threading.Tasks; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; class Program { static async Task Main(string[] args) { // 创建客户端配置 var options = new MqttClientOptionsBuilder() .WithTcpServer("localhost", 1883) .WithClientId("Client1") // 客户端ID .Build(); // 创建MQTT客户端实例 var mqttClient = new MqttFactory().CreateMqttClient(); // 处理连接成功事件 mqttClient.UseConnectedHandler(e => { Console.WriteLine("Connected to MQTT Broker"); }); // 处理连接断开事件 mqttClient.UseDisconnectedHandler(e => { Console.WriteLine("Disconnected from MQTT Broker"); }); // 处理接收到消息事件 mqttClient.UseApplicationMessageReceivedHandler(e => { Console.WriteLine($"Received message: {e.ApplicationMessage.Payload}"); }); // 连接到MQTT服务器 await mqttClient.ConnectAsync(options, CancellationToken.None); // 发布消息 var message = new MqttApplicationMessageBuilder() .WithTopic("topic/test") .WithPayload("Hello, MQTT!") .WithExactlyOnceQoS() .WithRetainFlag() .Build(); await mqttClient.PublishAsync(message, CancellationToken.None); Console.WriteLine("Message published. Press any key to exit."); Console.ReadLine(); // 断开与MQTT服务器的连接 await mqttClient.DisconnectAsync(); } } Web端示例 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://cdnjs.cloudflare.com/ajax/libs/mqtt/4.0.0/mqtt.min.js"></script> <title>MQTT Web Client</title> </head> <body> <h1>MQTT Web Client</h1> <script> // 连接到MQTT服务器 const client = mqtt.connect('mqtt://your-mqtt-broker-url'); // 当连接成功时的处理逻辑 client.on('connect', function () { console.log('Connected to MQTT Broker'); // 订阅主题 client.subscribe('topic/test', function (err) { if (!err) { console.log('Subscribed to topic/test'); } }); // 发布消息 client.publish('topic/test', 'Hello, MQTT!'); }); // 当接收到消息时的处理逻辑 client.on('message', function (topic, message) { console.log('Received message:', message.toString()); }); // 处理连接断开事件 client.on('close', function () { console.log('Connection closed'); }); // 处理错误事件 client.on('error', function (err) { console.error('Error:', err); }); </script> </body> </html> 总结 以上代码中对连接断开事件处理(UseDisconnectedHandler、Web端的close事件)和错误事件处理(Web端的error事件)。 这些事件处理可以根据实际需求进一步扩展。 --- ### 305. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网设备接入和通信示例介绍 本文介绍了如何使用阿里云物联网平台,通过设备端Link SDK来模拟物联网设备接入和实现上下行通信。以下是整个过程的概述和关键步骤总结: 前提条件 在物联网平台控制台创建产品和设备(如 device2)并获取设备证书信息(ProductKey、DeviceName 和 DeviceSecret)。 详细操作包括创建产品和创建设备。 背景信息 使用 WebSocket 方式接入设备。 在 Node.js 环境下配置和使用设备端 Link SDK。 操作步骤 安装 Node.js:在 Windows 或 Linux 系统下载并安装 Node.js。例如,在 Windows 10 上安装 node-v14.15.1-x64.msi。 验证安装:通过 node --version 命令在 CMD 窗口检查 Node.js 版本。 创建 JavaScript 文件:例如 iot_device.js,用于存放示例代码。 const iot = require('alibabacloud-iot-device-sdk'); // 设备证书信息。 const productKey = 'a1W***'; const deviceName = 'device2'; const deviceSecret = 'ff01e59d1a***'; // 新版公共实例和企业版实例,必须填写实例ID,旧版公实例无需填写。 const instanceId = ''; // 当前产品和设备所属地域的ID。 const region = 'cn-shanghai'; const brokerUrl = instanceId ? `wss://${instanceId}.mqtt.iothub.aliyuncs.com:443` : `wss://${productKey}.iot-as-mqtt.${region}.aliyuncs.com:443`; const device = iot.device({ productKey: `${productKey}`, deviceName: `${deviceName}`, deviceSecret: `${deviceSecret}`, brokerUrl, tls: true, }); // 监听connect事件:建立MQTT连接,订阅自定义Topic,通过自定义Topic向物联网平台发送消息。 device.on('connect', () => { device.subscribe(`/${productKey}/${deviceName}/user/get`); console.log('connect successfully!'); device.publish(`/${productKey}/${deviceName}/user/update`, 'hello world!'); }); // 监听message事件。 device.on('message', (topic, payload) => { console.log(topic, payload.toString()); }); // 监听error事件。 device.on('error', (error) => { console.error(error); }); // 如果您希望主动断开与物联网平台的连接,可以删除下一行注释符号,调用end函数断开与物联网平台的连接。 //device.end(); 您需参照下表,替换对应参数的值为实际场景中设备的信息。 参数示例说明productKeya1W***您添加设备后,保存的设备证书信息,请参见获取设备证书。您也可在控制台中设备device2的设备详情页面查看。deviceNamedevice2deviceSecretff01e59d1a***instanceId''实例ID。您可在物联网平台控制台的实例概览页面,查看当前实例的ID。若有ID值,必须传入该ID值。若无实例概览页面或ID值,传入空值,即iotInstanceId = ''。实例的详细说明,请参见实例概述。regioncn-shanghai您物联网平台设备所在地域的代码。地域代码表达方法,请参见地域列表。 打开CMD窗口,使用cd命令找到iot_device.js文件所在路径,在该路径下使用npm命令下载阿里云IoT的Link SDK库。下载后的库文件如下图所示。npm install alibabacloud-iot-device-sdk --save 在CMD窗口输入如下命令,运行iot_device.js代码,启动设备。node iot_device.js返回如下信息,表示设备接入成功,并成功发布消息。 查看运行日志和测试下行通信 登录物联网平台控制台。 在控制台左上方,选择物联网平台设备所在地域,然后在实例概览页面,单击目标实例。说明若无实例概览页面,会直接进入物联网平台功能页面。 在左侧导航栏,选择设备管理 > 设备。在设备列表页签,可查看设备device2的状态为在线。 单击设备device2对应操作栏的查看,在设备详情页面,单击日志服务,然后单击前往查看。在云端运行日志页签,查看日志消息。 在日志列表,找到设备到云消息,单击查看,查看设备上报到物联网平台的信息。 测试下行通信:从物联网平台向设备发送消息。 返回设备管理 > 设备页面,在设备列表页签,单击设备device2操作栏的查看。 在设备详情页面,单击Topic列表页签,找到已订阅的Topic:/a1W***/device2/user/get,单击发布消息。 输入消息内容,单击确认。 返回设备运行窗口,查看设备能接收消息,表示通信正常。您也可返回云端运行日志页签,查看详细的通信日志。 总结 此示例提供了一个实际的场景,展示了如何通过 Node.js 和阿里云物联网平台的设备端 Link SDK 实现物联网设备的接入和通信。整个过程包括从设置环境、编写和运行代码,到在物联网平台上进行设备管理和通信测试。这为开发者提供了一个指导性的例子,帮助他们快速入门物联网设备的接入和数据交互。 --- ### 306. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Async.MQTT5是一个基于Boost.Asio的C++20 MQTT客户端,专门为发布或接收与MQTT 5.0兼容的代理的消息而设计。这是一个全面实施MQTT 5.0协议标准的客户端,完全支持QoS 0、1和2级别的消息发布和接收。 Async.MQTT5 MQTT协议广泛用于现实世界的多种通信场景,主要作为IoT设备数据传输的可靠通信协议。虽然MQTT协议本身相对简单,但将其整合到应用程序中可能相当复杂,尤其是在断开/重连序列后消息重传的实现方面。 Async.MQTT5旨在为应用开发者提供一个非常简单的异步C++接口。内部客户端实现管理网络和MQTT协议细节。值得注意的是,客户端不暴露连接函数(或异步连接函数);相反,网络连接性、MQTT握手和消息重传都在客户端内部自动处理。 Async.MQTT5接口与Boost.Asio的异步模型无缝对接。客户端的异步函数与Boost.Asio支持的所有完成令牌兼容。 仓库地址:https://github.com/mireo/async-mqtt5 特点 Async.MQTT5是一个设计理念为用户只应专注于应用逻辑,而不是网络复杂性的库。该库试图通过以下一系列关键特性来提升开发体验: 完整的TCP、TLS/SSL和WebSocket支持 用户友好的简洁性:提供尽可能简单而不损功能的界面。 优先考虑效率:尽可能高效地利用网络和内存资源。 最小内存占用:确保在IoT设备典型的资源受限环境中优化性能。 自动重新连接:在断开连接的情况下自动尝试重新建立连接。 完全符合Boost.Asio规范:接口和实现策略基于Boost.Asio的基础。Boost.Asio和Boost.Beast的用户将不会在理解和整合Async.MQTT5时遇到问题。此外,Async.MQTT5与Boost.Asio生态系统中的任何其他库都能很好地整合。 自定义分配器:支持自定义分配器,允许对内存资源进行额外的灵活性和控制。Async.MQTT5将使用来自异步函数的处理器关联的分配器来创建库实现中所需的对象实例。 每项操作的取消:所有异步操作都支持Asio的每项操作取消。 完成令牌:所有异步函数都支持CompletionToken,允许使用回调、协程、futures等多种方式灵活使用。 完全实现MQTT 5.0规范 支持QoS 0、QoS 1和QoS 2 自定义认证:Async.MQTT5定义了一个接口,用于执行增强认证的自定义认证器。 高可用性:Async.MQTT5支持列出同一集群中多个客户端可以连接的代理。在与一个代理的连接失败时,客户端会切换到列表中的下一个。 离线缓冲:离线时,它会自动缓冲所有连接恢复时要发送的数据包。 使用该库 下载Boost,并将其添加到您的包含路径中。 如果使用SSL,请下载OpenSSL,链接库并将其添加到包含路径中。 另外,您可以将Async.MQTT5的包含文件夹添加到包含路径中。 您可以使用以下命令行在Linux上编译以下示例: $ clang++ -std=c++20 <source-cpp-file> -o example -I<path-to-boost> -Iinclude -pthread 使用和API 详细文档在这里。 以下示例演示了配置客户端并使用QoS 0发布“Hello World!”应用消息的简单场景。 #include <iostream> #include <boost/asio/io_context.hpp> #include <boost/asio/detached.hpp> #include <boost/asio/ip/tcp.hpp> #include <async_mqtt5.hpp> int main() { boost::asio::io_context ioc; using client_type = async_mqtt5::mqtt_client<boost::asio::ip::tcp::socket>; client_type c(ioc, ""); c.credentials("<your-client-id>", "<client-username>", "<client-pwd>") .brokers("<your-mqtt-broker>", 1883) .run(); c.async_publish<async_mqtt5::qos_e::at_most_once>( "<topic>", "Hello world!", async_mqtt5::retain_e::no, async_mqtt5::publish_props {}, [&c](async_mqtt5::error_code ec) { std::cout << ec.message() << std::endl; c.async_disconnect(boost::asio::detached); // disconnect and close the client } ); ioc.run(); } 为什么选择它? 如果以下任何一种情况适用于您,则Async.MQTT5可能适合您: 您的应用程序使用Boost.Asio并需要集成MQTT客户端。 您需要异步访问MQTT代理。 您正在开发需要连接到MQTT代理的高级组件。 您需要一个可靠且有韧性的MQTT客户端,可以自动管理所有与网络相关的问题。 如果以下情况使用,则可能不适合您: 您仅需要同步访问MQTT代理。 您连接的MQTT代理不支持MQTT 5版本。 需求 Async.MQTT5是一个仅头文件的库。要使用Async.MQTT5,需要以下条件: C++20兼容的编译器 Boost 1.82或更高版本。除了Asio,我们还使用了Beast、Spirit等其他仅头文件的库。 OpenSSL。仅当您通过使用boost::asio::ssl::stream需要SSL连接时。 Async.MQTT5已在以下编译器上进行了测试: clang 14.0(Linux) MSVC 14.37 - Visual Studio 2022(Windows) 总结 Async.MQTT5是一个基于Boost.Asio的专业C++20 MQTT客户端,专为发布或接收与MQTT 5.0兼容代理的消息而设计。这个客户端提供了MQTT 5.0协议标准的全面实现,并全面支持QoS 0、1和2的消息发布和接收。 Async.MQTT5的目的是为应用开发者提供一个非常简单的异步C++接口,以简化MQTT协议的集成和使用。它自动处理网络连接、MQTT握手和消息重传,使用户可以专注于应用逻辑。 Async.MQTT5提供了包括TCP、TLS/SSL和WebSocket支持、最小内存占用、自动重新连接等特性,使其在IoT设备环境中表现出色。此外,它支持自定义分配器和每项操作的取消,使其在高度定制化的应用场景中也能灵活应用。 使用Async.MQTT5,您只需下载Boost和(如需SSL支持)OpenSSL,并将它们添加到包含路径中。它是一个头文件库,不需要额外的编译步骤。 Async.MQTT5适用于需要集成MQTT客户端的Boost.Asio应用程序,或那些需要稳定、自动管理网络问题的高级MQTT客户端的场景。然而,如果您只需要同步访问MQTT代理或使用的MQTT代理不支持MQTT 5版本,它可能不适合您。 最后,Async.MQTT5已经在Linux和Windows平台的最新编译器上进行了测试,保证了其广泛的兼容性和稳定性。 --- ### 307. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 什么是MQTT? MQTT(消息队列遥测传输)是一种轻量级的发布/订阅消息传输协议,专为M2M(机器对机器)遥测在低带宽环境中设计。该协议由Andy Stanford-Clark(IBM)和Arlen Nipper于1999年为了通过卫星连接油管遥测系统而设计。最初是私有协议,2010年发布为免版税,2014年成为OASIS标准。 MQTT原名为“消息队列遥测传输”,现在简称为MQ遥测传输。随着物联网(IoT)部署的增加,它正迅速成为主要协议之一。 MQTT版本 MQTT v3.1.0 MQTT v3.1.1 – 目前普遍使用 MQTT v5 – 目前使用有限 MQTT-SN – 见后面的说明 MQTT最初设计于1999年,多年来一直在TCP/IP网络上使用。目前普遍使用的是MQTTv3.1.1版本。v3.1.0和v3.1.1版本之间的区别很小,GitHub上有一个页面详细介绍了这些主要区别。 最新的MQTT版本(v5),于2018年1月获批准。如果你想了解为什么没有v4版本,可以参考这里。 更多信息可参阅 MQTT v5.0的新功能概览。 MQTT-SN简介 MQTT-SN约在2013年制定,设计用于UDP、ZigBee等传输方式。目前MQTT-SN的普及程度不高,其规范多年未变,但随着物联网部署的开始,这一状况预计将改变。 MQTT客户端 MQTT客户端不像电子邮件地址、电话号码等拥有地址,因此你不需要为客户端分配地址,就像大多数消息系统一样。 对于MQTTv3.1.1,Eclipse Paho项目提供了几乎所有编程语言和主要操作系统(Linux、Windows、Mac)的客户端软件。 目前,Paho客户端v1.5.1已支持MQTTv5.0。 MQTT代理或服务器 最初的术语是代理,但现在已标准化为服务器。目前有许多MQTT代理可用于测试和实际应用。最受欢迎的自托管代理之一是Mosquitto,还有商业代理如HiveMQ。Mosquitto是一个免费的开源MQTT代理,可在Windows和Linux上运行。此外,Eclipse提供了一个免费的公共MQTT代理和COAP服务器,供测试使用。 MQTT通过WebSockets WebSockets允许将MQTT数据直接传送到Web浏览器。这很重要,因为Web浏览器可能成为显示MQTT数据的默认界面。JavaScript MQTT客户端提供了对Web浏览器的MQTT websocket支持。 MQTT安全性 MQTT支持多种认证和数据安全机制。需要注意的是,这些安全机制是在MQTT代理上配置的,客户端必须遵守所配置的机制。 MQTT课程 针对初学者的逐步指南——MQTT 3.1.1基础课程 常见问题 如果你熟悉Web和电子邮件,可能会发现MQTT与它们非常不同。以下是一些我遇到的问题,也在其他网站和论坛上看到的问题,可能会有所帮助: Q: MQTT通常使用哪个端口?A: 标准端口是1883。 Q: 能否在没有代理的情况下使用MQTT?A : 不可以,MQTT是基于代理的。 Q: MQTT如何处理多个客户端?A: MQTT服务器可以同时处理成千上万的客户端。 Q: MQTT是否支持广播消息?A: 是的,通过发布/订阅模型,MQTT支持广播。 --- ### 308. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 架构 介绍 在本教程中,我们将学习创建物联网应用程序的数据流处理所需的内容。 在这个过程中,我们将了解物联网架构的特点,并了解如何利用MQTT代理、NiFi和InfluxDB等不同工具来构建高度可扩展的物联网应用程序的数据流处理。 物联网及其架构 首先,让我们学习一些基本概念,了解物联网应用程序的一般架构。 2.1. 什么是物联网? 物联网(IoT)广泛指的是物理对象的网络,称为“物”。例如,这些物可以包括从普通家用物品(如灯泡)到复杂的工业设备等任何物。通过这个网络,我们可以连接各种传感器和执行器以交换数据。 现在,我们可以在非常不同的环境中部署这些物 - 例如,环境可以是我们的家,也可以是一辆行驶中的货车。然而,我们不能对这些物将可以使用的电源和网络的质量进行任何假设。因此,这为物联网应用程序提出了独特的要求。 2.2. 物联网架构简介 典型的物联网架构通常分为四个不同的层次。让我们了解数据如何在这些层次之间流动: 首先,感知层主要由从环境中收集测量数据的传感器组成。然后,网络层帮助聚合原始数据并通过互联网进行传输。进一步,数据处理层会过滤原始数据并生成早期分析。最后,应用层使用强大的数据处理能力来执行更深入的数据分析和管理。 MQTT、NiFi和InfluxDB简介 现在,让我们来看看今天在物联网设置中广泛使用的一些产品。这些产品都提供了一些独特的特性,使它们适用于物联网应用程序的数据需求。 3.1. MQTT MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布-订阅网络协议。它现在是OASIS和ISO标准。IBM最初开发它用于在设备之间传输消息。MQTT适用于内存、网络带宽和电源供应有限的受限环境。 MQTT遵循客户端-服务器模型,不同组件可以充当客户端并通过TCP连接到服务器。我们将此服务器称为MQTT代理。客户端可以将消息发布到称为主题的地址。它们还可以订阅主题并接收发布到它的所有消息。 在典型的物联网设置中,传感器可以将测量数据(如温度)发布到MQTT代理,而上游数据处理系统可以订阅这些主题以接收数据: 正如我们所见,MQTT中的主题是分层的。系统可以通过使用通配符轻松订阅整个主题层次结构。 MQTT支持三个不同的服务质量(QoS)级别。它们分别是“至多传递一次”、“至少传递一次”和“确保仅传递一次”。QoS定义了客户端与服务器之间的协议级别。每个客户端可以选择适合其环境的服务级别。 客户端还可以在发布时请求代理保留消息。在某些设置中,MQTT代理可能需要从客户端那里进行用户名和密码验证以建立连接。此外,出于隐私考虑,TCP连接可能会使用SSL/TLS进行加密。 有几个MQTT代理实现和客户端库可供使用,例如HiveMQ、Mosquitto和Paho MQTT。在本教程中,我们将使用Mosquitto作为示例。Mosquitto是Eclipse基金会的一部分,我们可以轻松地将其安装在树莓派或Arduino等开发板上。 3.2. Apache NiFi Apache NiFi最初由美国国家安全局(NSA)开发,是一种自动化和数据流管理工具,基于基于流的编程模型,将应用程序定义为黑盒进程网络。 首先,让我们先了解一些基本概念。在NiFi中,系统中移动的对象称为FlowFile。FlowFile处理器实际上执行诸如路由、转换和调解FlowFiles等有用工作。FlowFile处理器通过连接与连接一起使用。 处理组是一种将组件组合在一起以组织NiFi数据流的机制。处理组可以通过输入端口接收数据并通过输出端口发送数据。远程处理组(RPG)提供了一种从远程NiFi实例发送数据或接收数据的机制。 现在,有了这些知识,让我们了解NiFi架构: NiFi是一个基于Java的程序,运行在JVM中的多个组件。Web服务器是托管命令和控制API的组件。流控制器是NiFi的核心组件,负责管理扩展何时接收资源以执行。扩展允许NiFi具有可扩展性,并支持与不同系统的集成。 NiFi通过FlowFile存储库跟踪FlowFile的状态。FlowFile的实际内容字节存储在内容存储库中。与FlowFile相关的可信事件数据存储在可信存储库中。 由于数据在源头的收集可能需要较小的占用空间和低资源消耗,NiFi有一个名为MiNiFi的子项目。MiNiFi提供了一种补充的数据收集方法,可以通过Site-to-Site(S2S)协议轻松集成到NiFi中。 此外,它通过MiNiFi命令和控制(C2)协议实现了对代理的集中管理。此外,它有助于建立数据溯源,生成完整的链式保管信息。 3.3. InfluxDB InfluxDB是由InfluxData开发的,使用Go编写的时序数据库。它专为快速和高可用性的时序数据存储和检索而设计。这在处理应用程序指标、物联网传感器数据和实时分析方面特别合适。 首先,InfluxDB中的数据是按时序组织的。时序可以包含零个或多个数据点。数据点代表具有四个组成部分的单个数据记录,包括测量、标签集、字段集和时间戳: 首先,时间戳显示与特定数据点关联的UTC日期和时间。字段集由一个或多个字段键和字段值对组成。它们捕获了点的实际数据,并附带标签。标签集也由标签键和标签值对组成,但它们是可选的。它们基本上充当点的元数据,并可用于加快查询响应。 测量充当标签集、字段集和时间戳的容器。此外,InfluxDB中的每个数据点都可以与其关联的保留策略。保留策略描述了InfluxDB将保留数据的时间以及通过复制将创建多少副本。 最后,数据库充当用户、保留策略、连续查询和时序数据的逻辑容器。我们可以将InfluxDB中的数据库理解为与传统关系数据库 loosly 相似。 此外,InfluxDB是InfluxData平台的一部分,提供了多种其他产品来高效处理时序数据。InfluxData现在将其作为InfluxDB OSS 2.0(开源平台)和InfluxDB Cloud(商业产品)提供: 除了InfluxDB之外,该平台还包括Chronograf,它为InfluxData平台提供了完整的界面。此外,它包括Telegraf,用于收集和报告度量和事件的代 理。最后,还有Kapacitor,一个实时流式数据处理引擎。 实践物联网数据管道 现在,我们已经掌握了足够的知识,可以将这些产品一起使用,为我们的物联网应用程序创建数据管道。在本教程中,我们假设我们正在从多个城市的多个观测站收集与空气质量相关的测量数据。例如,这些测量包括地面臭氧、一氧化碳、二氧化硫、二氧化氮和气溶胶等。 4.1. 基础设施设置 首先,我们假设每个城市的气象站都配备了所有感应设备。此外,这些传感器已连接到类似Raspberry Pi的开发板,用于收集模拟数据并将其数字化。该板通过无线连接发送原始测量数据: 物联网基础设施设置一个区域控制站收集来自城市中所有气象站的数据。我们可以汇总并将此数据提供给一些本地分析引擎,以获得更快的见解。来自所有区域控制中心的经过筛选的数据被发送到中央指挥中心,该中央指挥中心通常托管在云中。 4.2. 创建物联网架构 现在,我们准备为我们的简单空气质量应用程序设计物联网架构。在这里,我们将使用MQTT代理、MiNiFi Java代理、NiFi和InfluxDB: 正如我们所看到的,我们在气象站点使用了Mosquitto MQTT代理和MiNiFi Java代理。在区域控制中心,我们使用NiFi服务器来汇总和路由数据。最后,我们使用InfluxDB来存储中央指挥中心级别的测量数据。 4.3. 执行安装 在像Raspberry Pi这样的开发板上安装Mosquitto MQTT代理和MiNiFi Java代理非常容易。但是,对于本教程,我们将在本地计算机上安装它们。 Eclipse Mosquito的官方下载页面提供了多个平台的二进制文件。一旦安装完成,可以从安装目录轻松启动Mosquitto: net start mosquitto 此外,NiFi二进制文件也可以从其官方网站下载。我们必须在合适的目录中提取下载的存档。由于MiNiFi将使用站点到站点协议连接到NiFi,因此必须在/conf/nifi.properties中指定站点到站点输入套接字端口: # Site to Site properties nifi.remote.input.host= nifi.remote.input.secure=false nifi.remote.input.socket.port=1026 nifi.remote.input.http.enabled=true nifi.remote.input.http.transaction.ttl=30 sec 然后,我们可以启动NiFi: <NIFI_HOME>/bin/run-nifi.bat 同样,可以从官方网站下载Java或C++ MiNiFi代理和工具包二进制文件。同样,我们必须将存档提取到适当的目录中。 默认情况下,MiNiFi附带一组非常少的处理器。因为我们将从MQTT中获取数据,所以必须将MQTT处理器复制到/lib目录。这些处理器捆绑为NiFi Archive (NAR)文件,并位于/lib目录中: COPY <NIFI_HOME>/lib/nifi-mqtt-nar-x.x.x.nar <MINIFI_HOME>/lib/nifi-mqtt-nar-x.x.x.nar 然后,我们可以启动MiNiFi代理: <MINIFI_HOME>/bin/run-minifi.bat 最后,可以从其官方网站下载InfluxDB的开源版本。与以前一样,可以提取存档,并使用简单的命令启动InfluxDB: <INFLUXDB_HOME>/influxd.exe 对于本教程,我们应该保留所有其他配置,包括端口,以默认值。这完成了我们在本地计算机上的安装和设置。 4.4. 定义NiFi数据流 现在,我们已经准备好定义我们的数据流。NiFi提供了一个易于使用的界面,用于创建和监控数据流。这可通过URL http://localhost:8080/nifi 访问。 首先,我们将定义将在NiFi服务器上运行的主数据流: 如我们所见,我们定义了一个输入端口,该端口将从MiNiFi代理接收数据。它通过连接将数据发送到PutInfluxDB处理器,该处理器负责将数据存储在InfluxDB中。在此处理器的配置中,我们定义了InfluxDB的连接URL以及要发送数据的数据库名称。 4.5. 定义MiNiFi数据流 接下来,我们将定义在MiNiFi代理上运行的数据流。我们将使用NiFi的相同用户界面,并将数据流导出为模板,然后在MiNiFi代理中进行配置。让我们定义MiNiFi代理的数据流: 在这里,我们定义了ConsumeMQTT处理器,负责从MQTT代理获取数据。我们在属性中提供了代理URI以及主题过滤器。我们正在从层次结构"air-quality"下定义的所有主题中获取数据。 我们还定义了一个远程处理组,并将其连接到ConcumeMQTT处理器。远程处理组负责通过站点到站点协议将数据推送到NiFi。 我们可以将此数据流保存为模板,并将其下载为XML文件。让我们将此文件命名为config.xml。现在,我们可以使用转换工具包将此模板从XML转换为MiNiFi代理使用的YAML格式: <MINIFI_TOOLKIT_HOME>/bin/config.bat transform config.xml config.yml 这将生成config.yml文件,其中我们必须手动添加NiFi服务器的主机和端口: Input Ports: - id: 19442f9d-aead-3569-b94c-1ad397e8291c name: From MiNiFi comment: '' max concurrent tasks: 1 use compression: false Properties: # Deviates from spec and will later be removed when this is autonegotiated Port: 1026 Host Name: localhost 现在,我们可以将此文件放入/conf目录,替换可能已经存在的文件。之后,我们需要重新启动MiNiFi代理。 在这里,我们需要手动进行大量工作来创建数据流并在MiNiFi代理中进行配置。这在实际情况下是不切实际的,因为遥远的地点可能存在数百个代理。然而,正如我们之前所看到的,我们可以使用MiNiFi C2服务器来自动化此过程。但这超出了本教程的范围。 4.6. 测试数据管道 最后,我们准备测试我们的数据管道!由于我们无法使用真实传感器,我们将创建一个小型模拟。我们将使用一个小的Java程序生成传感器数据: class Sensor implements Callable<Boolean> { String city; String station; String pollutant; String topic; Sensor(String city, String station, String pollutant, String topic) { this.city = city; this.station = station; this.pollutant = pollutant; this.topic = topic; } @Override public Boolean call() throws Exception { MqttClient publisher = new MqttClient( "tcp://localhost:1883", UUID.randomUUID().toString()); MqttConnectOptions options = new MqttConnectOptions(); options.setAutomaticReconnect(true); options.setCleanSession(true); options.setConnectionTimeout(10); publisher.connect(options); IntStream.range(0, 10).forEach(i -> { String payload = String.format("%1$s,city=%2$s,station=%3$s value=%4$04.2f", pollutant, city, station, ThreadLocalRandom.current().nextDouble(0, 100)); MqttMessage message = new MqttMessage(payload.getBytes()); message.setQos(0); message.setRetained(true); try { publisher.publish(topic, message); Thread.sleep(1000); } catch (MqttException | InterruptedException e) { e.printStackTrace(); } }); return true; } } 在这里,我们使用Eclipse Paho Java客户端生成消息并发送到MQTT代理。我们可以添加尽可能多的传感器以创建我们的模拟: ExecutorService executorService = Executors.newCachedThreadPool(); List<Callable<Boolean>> sensors = Arrays.asList( new Simulation.Sensor("london", "central", "ozone", "air-quality/ozone"), new Simulation.Sensor("london", "central", "co", "air-quality/co"), new Simulation.Sensor("london", "central", "so2", "air-quality/so2"), new Simulation.Sensor("london", "central", "no2", "air-quality/no2"), new Simulation.Sensor("london", "central", "aerosols", "air-quality/aerosols")); List<Future<Boolean>> futures = executorService.invokeAll(sensors); 如果一切正常,我们将能够在InfluxDB数据库中查询我们的数据: 例如,我们可以查看属于“ozone”测量的所有数据点,这些数据存储在数据库“airquality”中。 结论 总之,本教程涵盖了一个基本的IoT用例。我们还了解了如何使用MQTT、NiFi和InfluxDB等工具来构建可扩展的数据管道。当然,这并不涵盖IoT应用程序的全部范围,扩展数据分析管道的可能性是无限的。 此外,本教程中选择的示例仅供演示目的。实际的IoT应用程序的基础架构和架构可以非常多样化和复杂。此外,我们可以通过将可操作的见解作为命令向后推送来完成反馈循环。 --- ### 309. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 介绍 正如我们可能已经知道的那样,Node.js是一个异步和事件驱动的JavaScript运行时和引擎,为今天存在的许多基于服务器端的、网络化的应用程序提供动力。在本文中,我们将探讨Node.js与MQTT的互动,MQTT是一种用于物联网(IoT)世界的发布/订阅(pub/sub)协议和标准。 在本文中,我们计划仅涵盖重要的公共MQTT API和函数,并探讨Node.js中的简单发布者和订阅者脚本。 什么是MQTT? 1999年,IBM的Andy Standford-Clark和Arlen Nipper设计了MQTT协议的最初版本。当时的目标是构建一个支持低带宽、轻量级且消耗最少资源的协议,因为通过卫星链路连接的设备非常昂贵。 该规范有两个版本:MQTT 3.1.1和MQTT 5.0.0。大多数商业MQTT代理现在支持MQTT 5,但许多IoT托管云服务仅支持MQTT 3.1.1,这曾经是最受欢迎和广泛支持的版本。 强烈建议新的IoT部署使用5.0.0版本(2018年批准),因为其新功能更侧重于强大的系统和云原生可伸缩性。您可以在MQTT的GitHub页面上阅读有关两个版本之间的亮点和详细差异的更多信息。 今天的用途 MQTT是一种轻量级的客户端-服务器协议,实现了发布/订阅消息传输模型,并已用于连接关键的IoT应用程序、机器对机器(M2M)通信和许多其他需要具有有限带宽但卓越性能的消息传输平滑界面的领域。这是其简单的设计、易用性和开放规范的结果。 自2014年以来,MQTT一直由OASIS技术指导委员会管理。该委员会负责维护、更新和维护该标准,包括组织用例文档和保护其知识产权。 它依赖于TCP/IP,这是一个可靠的、面向连接的低级网络堆栈,传输层独立于数据有效载荷结构,实现了一种有序和正确的双向主机对主机的通信模型。 发布/订阅模式还允许消息从一个应用程序分发到许多不同的应用程序。但在这种情况下,发布者和订户通常是独立的应用程序(解耦),只通过代理或服务器连接。例如,流行的发布/订阅消息平台RabbitMQ在内部使用了MQTT。 MQTT的用例 MQTT已经找到了许多用例,我们将在下面探讨其中一些。 启用消息广播:客户端可以发布消息或有效载荷到多个其他客户端应用程序,当然,这些应用程序需要通过代理事先通过主题订阅这些消息. 提供轻量级和最小的消息头/资源:这允许在消息传输中使用最小的带宽,因此MQTT可以有效地扩展以服务数百万个IoT设备 在其核心,它提供了可靠的消息传输或交付:大多数IoT设备都依赖于这一点,但从高层次上看,MQTT定义了保证消息传输得以处理的服务层 构建高度安全的消息传输应用程序:MQTT在这方面非常出色,因为消息有效载荷可以使用TLS和其他现代身份验证机制(如OAUTH)进行加密和安全保护 确保客户端应用程序具有持久连接:这对于网络连接可能不稳定的区域中的临时消息存储非常方便 相关的是,MQTT有助于减少在信号差的蜂窝网络上设备重新连接所需的时间 在不同行业和领域找到应用,包括汽车、石油和天然气、制造、物流、交通和智能家居设备行业 您可以在MQTT文档的用例页面上找到有关这些信息的更多详细信息。最受欢迎的开源家庭自动化项目之一,Home Assistant,基于MQTT协议。 MQTT的发布/订阅架构 MQTT协议包括代理(broker),它充当中央服务器,将发布者客户端的消息引导到订阅者客户端,以及一个或多个客户端应用程序,可以是消息或数据的订阅者或发布者。 代理可以看作是邮递员,确保消息被传递给其各自的接收者。它们应该被设计成高度可扩展和安全的,因为它们是MQTT客户端的中心关注点。 在高层次上,代理充当一个网关,将发布的消息从发布者应用程序路由到适当的订阅者。通常情况下,代理可以部署在多个集群或实例上,并置于负载均衡器后,以提高容错性。MQTT客户端将消息发布到中央代理(通常是到主题),其他客户端可以订阅代理上的相同主题以接收这些消息。 因此,一个客户端将消息发布到主题,而其他客户端订阅该主题,表示它们有兴趣接收相关消息。代理具有一种过滤机制,用于控制应该将消息发送给哪些订阅者。这意味着代理检查或筛选特定主题或主题组上的订阅者(或订阅者列表),然后将消息发送给它们。 总之,代理读取、确认和处理来自发布者客户端或应用程序的消息(包括确定主题的订阅者以及将所有适当的消息发送给它们)。 注意:MQTT依赖一种过滤消息的方式,代理将消息发送给对获取消息内容感兴趣的订阅者。消息通常包含一个主题,代理使用该主题来确定如何将特定消息路由到适当的订阅客户端。 基于主题的过滤涉及客户端(发布者和订阅者)通过主题与代理进行交互,主题是每个消息有效载荷的一部分。 到目前为止,我们已经使用了一些对一些读者可能听起来很新的技术术语。在下一节中,我们将探讨一些这些术语及其含义。 一些MQTT技术概念解释 桥接(Bridge) - 两个MQTT代理之间的连接 MQTT客户端(MQTT client) - 连接到经过安全网络连接的MQTT代理的设备或使用MQTT客户端库编写的应用程序;MQTT客户端可以是发布者或订阅者应用/客户端 消息(Message) - 简单地说,要发布的消息,可以是缓冲区(Buffer)、字符串(String)或JSON对象 主题(Topics) - 代理用于过滤并将适当的消息发送到连接的客户端的字符串标识符。主题名称通常以层次结构的方式进行构建,带有分隔符,称为主题级别 (注意,消息必须包含代理可以使用的主题,以适当地路由有效载荷到感兴趣的客户端) 示例主题名称:mytopic/homeautomation/closedoor 发布者(Publisher) - 发布者客户端将数据或消息分发到服务器/代理上的主题,供其他可能有兴趣获取这些消息的订阅者客户端使用 物联网(IoT) - 由嵌入式系统、自动化设备、无线网络和控制机制组成的连接设备的世界 解耦(Decoupling) - 在这种情况下,解耦意味着发布者/订阅者只需要知道代理的主机名/IP和端口 - 不像传统的客户端-服务器架构,其中客户端和服务器通过端点/API直接通信,通常以URI格式进行通信。 在应用级别使用MQTT 现在,让我们看看MQTT在应用级别是如何工作的。我们将使用MQTT的Node.js客户端库mqtt.js。 MQTT.js是MQTT协议的开源JavaScript库,适用于Node.js和浏览器。通常,该库可用于发布消息和订阅MQTT代理上的主题。 关于MQTT.js库的一些要点 支持ES模块和Common.js样式的文件导入 它具有基于Promise的API接口,因为MQTT本身是异步工作的 MQTT.js默认使用旧的MQTT v3.1.1,以支持旧代理,但当前的最新版本是5.0 MQTT客户端带有内置的错误处理程序,在程序员未能处理其代码中的错误时非常有用 请注意,还有可用于各种编程语言和主要操作系统(Linux、Windows和macOS)的客户端库。 连接/断开MQTT代理/服务器 客户端连接始终由代理/服务器处理,因为MQTT订阅者和发布者是独立的、解耦的应用程序。正如我们之前提到的,发布者和订阅者都是MQTT客户端,因此需要连接到同一个代理/服务器。 客户端永远不会直接连接到彼此;连接通常是在一个客户端和代理之间通过TCP/IP进行的。其他MQTT实现或变种也可以通过UDP连接(MQTT<-SN)。代理负责: 接收所有消息 通过确定哪个订阅客户端订阅每条消息来筛选适当的消息 保持客户端之间的连接/会话 对客户端进行身份验证和授权 将消息发送给正确的客户端 代理应该容易扩展并集成到不同的后端系统中。它们可以具有相当高的容错性,因为它们是发布者/订阅者通信的最关键点。 要首次连接到代理,客户端发送CONNECT消息。一旦启动,代理将返回一个CONNACK消息和一个状态代码。还需要注意的一点是,代理始终保持连接处于活动状态,除非客户端发送断开事件或其互联网连接中断。 目前有一些流行的免费托管的MQTT代理。Eclipse的Mosquitto就是其中之一,它可以运行在所有主要操作系统上。 还有其他商业云端或托管的代理,比如HIVEMQ。如果我们不打算安装和管理自己的代理,它们通常会非常方便。您可以在MQTT网站上找到用于快速测试的优秀MQTT代理。 安装我们的客户端库 要安装MQTT.js,请运行以下命令: npm install mqtt --save 请注意,MQTT.js捆绑了与代理进行交互的命令。要使MQTT协议接口可用于系统路径,我们可以全局安装它: npm install mqtt -g 安装完成后,我们的package.json文件应如下所示: // package.json { "name": "mqtt-demo", "version": "1.0.0", "description": "一个Node.js和MQTT演示", "main": "index.js", "scripts": { "start-publisher": "nodemon publisher.js", "start-consumer": "nodemon subscriber.js" }, "keywords": [ "Node.js", "MQTT", "Pub/Sub", "IoT", "message", "transport" ], "author": "Alexander Nnakwue", "license": "MIT", "dependencies": { "dotenv": "^10.0.0", "mqtt": "^4.3.2" }, "devDependencies": { "nodemon": "^2.0.15" } } 要测试程序,可以在一个终端窗口上运行发布者,然后在另一个终端窗口上运行订阅者。 创建一个MQTT发布客户端 现在,让我们创建一个发布消息的MQTT客户端。为此,我们可以导入MQTT.js库并使用connect方法。 const mqtt = require('mqtt'); require('dotenv').config(); const clientId = 'mqttjs_' + Math.random().toString(8).substr(2, 4); const client = mqtt.connect(process.env.BROKER_URL, { clientId: clientId }); 请注意,我们已经将BROKER_URL添加到我们的环境文件中。如我们所见,connect方法接受给定的URL(代理服务器URL)和可选的服务器选项对象。接受的协议可以是MQTT、ws、wss、tcp、tls等等。connect方法返回一个已连接的客户端。 为了在MQTT客户端连接中断时尝试重新连接,我们可以将reconnectPeriod选项(两次重新连接之间的时间间隔)设置为大于零。默认值为1秒,这意味着在断开连接后,它会几乎立即尝试重新打开连接。 const client = mqtt.connect(process.env.BROKER_URL, { clientId: clientId, clean: false, reconnectPeriod: 1 }); 如果将reconnectPeriod客户端选项的值设置为0,则将禁用重新连接,并在连接断开时终止。 当将resubscribe选项设置为其默认值(true)时,客户端可以在连接中断时自动重新连接和重新订阅先前订阅的主题。尤其是对于自托管的代理,我们可能需要使用用户名和密码进行身份验证。有关服务器选项对象的更多详细信息可以在MQTT GitHub上找到。 发布数据和消息 一旦连接到代理,MQTT客户端几乎可以立即发送消息。发布事件需要消息负载和主题名称,代理可以使用它来识别订阅方。此外,还有一个回调选项,用于检查错误或消息数据包是否已传输。 发送的消息类型或数据包具有以下属性: topicName dupFlag qos payload packetId或messageId retainFlag { cmd: 'publish', topic: 'test/connection', payload: '{"1":"Hello world","2":"Welcome to the test connection"}', qos: 1, retain: true, messageId: 12041, dup: false } 命令,如下所示。 当客户端向代理发送消息时,代理会根据开发人员设置的某些标准来处理消息。这应该包括QoS级别,它确定消息达到预期接收方的保证类型,并确保消息传递保证。 处理阶段通常涉及读取消息、确认消息和识别订阅主题的客户端。最后一步是将消息发送给订阅的客户端。 以下是publisher.js文件的完整代码,包括一些公共方法/API: //publisher.js const mqtt = require('mqtt') require('dotenv').config() //the client id is used by the MQTT broker to keep track of clients and and their // state const clientId = 'mqttjs_' + Math.random().toString(8).substr(2, 4) const client = mqtt.connect(process.env.BROKER_URL, {clientId: clientId, clean: false}); // console.log(process.env.BROKER_URL, 'client', clientId) const topicName = 'test/connection' client.on("connect",function(connack){ console.log("client connected", connack); // on client connection publish messages to the topic on the server/broker const payload = {1: "Hello world", 2: "Welcome to the test connection"} client.publish(topicName, JSON.stringify(payload), {qos: 1, retain: true}, (PacketCallback, err) =&gt; { if(err) { console.log(err, 'MQTT publish packet') } }) //assuming messages comes in every 3 seconds to our server and we need to publish or process these messages setInterval(() =&gt; console.log("Message published"), 3000); }) client.on("error", function(err) { console.log("Error: " + err) if(err.code == "ENOTFOUND") { console.log("Network error, make sure you have an active internet connection") } }) client.on("close", function() { console.log("Connection closed by client") }) client.on("reconnect", function() { console.log("Client trying a reconnection") }) client.on("offline", function() { console.log("Client is currently offline") }) 接下来,我们可以继续实现订阅客户端,该客户端会接收主题上的消息。 订阅消息为了接收我们感兴趣的主题的消息,客户端通过subscribe事件向代理发送订阅请求。所订阅的消息通常包含消息数据包负载,如下所示。 //stdout Packet { cmd: 'publish', retain: true, qos: 0, dup: false, length: 73, topic: 'test/connection', payload: &lt;Buffer 7b 22 31 22 3a 22 48 65 6c 6c 6f 20 77 6f 72 6c 64 22 2c 22 32 22 3a 22 57 65 6c 63 6f 6d 65 20 74 6f 20 74 68 65 20 74 65 73 74 20 63 6f 6e 6e 65 63 ... 6 more bytes&gt; } {"1":"Hello world","2":"Welcome to the test connection"}``` // [ { topic: 'test/connection', qos: 0 } ] granted 与其将主题名称作为常规的分隔字符串,我们还可以将主题存储为通配符,以便订户可以轻松订阅主题模式,而不是一次订阅一个主题。发布者和订阅者客户端需要提前了解主题模式的主题名称。 需要注意的是,订阅客户端需要提前了解他们将要接收的数据的结构,以便能够正确地处理数据。发布者以特定格式将消息发送到代理的特定主题,并接收该消息的预定订户需要知道数据的结构,以便能够在不破坏应用程序的情况下正确处理它。 订户客户端的完整代码如下所示。 // subscriber.js const mqtt = require('mqtt') const client = mqtt.connect("mqtt://test.mosquitto.org") const topicName = 'test/connection' // connect to same client and subscribe to same topic name client.on('connect', () =&gt; { // can also accept objects in the form {'topic': qos} client.subscribe(topicName, (err, granted) =&gt; { if(err) { console.log(err, 'err'); } console.log(granted, 'granted') }) }) // on receive message event, log the message to the console client.on('message', (topic, message, packet) =&gt; { console.log(packet, packet.payload.toString()); if(topic === topicName) { console.log(JSON.parse(message)); } }) client.on("packetsend", (packet) =&gt; { console.log(packet, 'packet2'); }) MQTT的其他功能 以下是MQTT的一些特点。 保留的消息 保留的消息是一个设置为true的MQTT消息,其保留标志/选项设置为true。默认情况下,当代理/服务器接收到没有订户的主题的消息时,消息会被丢弃。但是,MQTT有一种通过设置标志来保留这些消息的机制,该标志告诉发布者保留消息。请注意,代理每个主题只存储一个保留的消息。 广泛的身份验证和数据安全支持 MQTT支持各种身份验证方法和数据安全机制,包括TLS和OAuth,通常在MQTT代理上配置。因此, 这意味着实施这些服务器的客户端需要遵守所定义的机制。 默认情况下,MQTT支持重新连接机制,可以在网络连接质量低的区域建立持久连接。这对于存储消息非常重要,但与传统队列系统不同,代理不仅仅存储消息。MQTT通过确保客户端会话持久存在并且QoS级别大于0来存储消息。 服务质量(QoS) 为了处理发布/订阅系统中的典型挑战,MQTT实现了三个服务质量(QoS)级别。这三个级别包括0、1和2,它们确定消息达到预期接收方(客户端或代理)的保证类型。 为支持可靠的消息传递,该协议支持三种不同类型的服务质量消息: 0 – 至多一次 1 – 至少一次 2 – 正好一次 为存储消息,客户端必须订阅QoS大于0的主题。 数据不可知 MQTT是数据不可知的,客户端的用例确定了数据的结构方式。因此,可以发送任何类型的消息,包括图像、编码文本、加密数据等。 注意:默认的未加密MQTT端口是1883。还支持加密的TCP/IP端口8883,用于使用SSL的MQTT。 结论 MQTT提供了适用于网络带宽有限的领域的双向发布/订阅消息模型。服务独立于我们的主要应用程序,因为它们是解耦的,可以单独扩展代理或服务器。 --- ### 310. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 SMQTT 是一款高性能、开源的 MQTT 服务器,旨在提供支持单机、容器化和集群部署的 MQTT 服务,具备低延迟和高吞吐量,支持数百万 TCP 连接。本文将向您介绍 SMQTT 的主要功能、优势以及适用场景。 WIKI: https://wiki.smqtt.cc/ gitee: https://gitee.com/quickmsg 为什么选择 MQTT? MQTT 是一种轻量级的消息传递协议,采用发布/订阅模型,非常适用于物联网消息传递,如传感器、手机、嵌入式设备等。其低开销和高效性使其成为 IoT 设备之间进行可靠消息传递的理想选择。 优势 SMQTT 具有以下显著优势: 标准 MQTT 协议支持: SMQTT 实现了 MQTT 协议的标准版本,包括 3.1 和 3.1.1,确保了与各种 MQTT 客户端的兼容性。 高并发支持: SMQTT 可应对高并发场景,而且支持集群化部署,使其适用于大规模部署。 高性能和高吞吐量: SMQTT 是基于 Reactor-Netty(Spring WebFlux 的底层依赖)开发的,底层采用 Reactor3 反应堆模型,具备卓越的性能和高吞吐量。此外,它还利用 Netty 提供原生性能优势。 功能 SMQTT 具备多种功能,包括但不限于: 标准协议功能: 支持 MQTT 协议的标准功能,包括发布/订阅、QoS 等。 数据持久化: SMQTT 支持将消息数据持久化存储,以确保数据安全和可靠性。您可以选择默认内存存储或持久化存储到 Redis 或数据库。 规则引擎: 支持规则引擎,可以用于消息处理和转发。 集群化功能: SMQTT 提供集群支持,使用 Gossip 协议实现集群通信,确保高可用性。 管理监控页面: 提供管理后台,用于管理和监控 MQTT 服务器,同时支持 Grafana 监控集成,以实现性能监控。 ACL 权限管理: 支持对设备和资源的访问授权,确保数据安全性。 认证模块: 提供多种认证方式,包括 HTTP、匿名、固定密码和 SQL 认证。 拦截器: 支持自定义消息拦截器,用于处理消息。 容器化支持: 支持容器化部署,方便集成到现有容器化环境中。 总结 SMQTT 的启动和管理非常简单,支持 Spring Boot Starter,可以轻松地将其集成到 Spring Boot 项目中。此外,您可以访问管理后台以监控和管理 MQTT 服务器。 如果您正在寻找一款高性能、开源的 MQTT 服务器,SMQTT 可能是您的理想选择。它支持各种协议、高并发场景和集群化部署,具备优秀的性能和可扩展性,适用于各种 IoT 和通信需求。 启动方式 main方式启动 <!--smqtt依赖 --> <dependency> <groupId>io.github.quickmsg</groupId> <artifactId>smqtt-core</artifactId> <version>${Latest version}</version> </dependency> <!--集群依赖 --> <dependency> <artifactId>smqtt-registry-scube</artifactId> <groupId>io.github.quickmsg</groupId> <version>${Latest version}</version> </dependency> <!--管理ui依赖 --> <dependency> <artifactId>smqtt-ui</artifactId> <groupId>io.github.quickmsg</groupId> <version>${Latest version}</version> </dependency> 阻塞式启动服务: Bootstrap.builder() .rootLevel(Level.INFO) .websocketConfig( BootstrapConfig.WebsocketConfig .builder() .enable(false) .path("/mqtt") .port(8888) .build() ) .tcpConfig( BootstrapConfig .TcpConfig .builder() .port(1883) .ssl(SslContext.builder().enable(false).build()) .build()) .httpConfig( BootstrapConfig .HttpConfig .builder() .enable(false) .accessLog(true) .admin(BootstrapConfig.HttpAdmin.builder().enable(true).username("smqtt").password("smqtt").build()) .build()) .clusterConfig( BootstrapConfig. ClusterConfig .builder() .enable(false) .namespace("smqtt") .node("node-1") .port(7773) .url("127.0.0.1:7771,127.0.0.1:7772"). build()) .build() .startAwait(); 非阻塞式启动服务: Bootstrap bootstrap = Bootstrap.builder() .rootLevel(Level.INFO) .websocketConfig( BootstrapConfig.WebsocketConfig .builder() .enable(false) .path("/mqtt") .port(8888) .build() ) .tcpConfig( BootstrapConfig .TcpConfig .builder() .port(1883) .ssl(SslContext.builder().enable(false).build()) .build()) .httpConfig( BootstrapConfig .HttpConfig .builder() .enable(false) .accessLog(true) .admin(BootstrapConfig.HttpAdmin.builder().enable(true).username("smqtt").password("smqtt").build()) .build()) .clusterConfig( BootstrapConfig. ClusterConfig .builder() .enable(false) .namespace("smqtt") .node("node-1") .port(7773) .url("127.0.0.1:7771,127.0.0.1:7772"). build()) .build() .start().block(); jar方式 1.下载源码 mvn compile package -Dmaven.test.skip=true -P jar,web 在smqtt-bootstrap/target目录下生成jar 2.准备配置文件 config.yaml config.yaml java -jar smqtt-bootstrap-1.0.1-SNAPSHOT.jar <config.yaml路径> docker 方式 拉取镜像 # 拉取docker镜像地址 docker pull 1ssqq1lxr/smqtt:latest 启动镜像默认配置 # 启动服务 docker run -it -p 1883:1883 1ssqq1lxr/smqtt 启动镜像使用自定义配置(同上准备配置文件config.yaml) # 启动服务 docker run -it -v <配置文件路径目录>:/conf -p 1883:1883 -p 1999:1999 1ssqq1lxr/smqtt springboot方式 引入依赖 <dependency> <groupId>io.github.quickmsg</groupId> <artifactId>smqtt-spring-boot-starter</artifactId> <version>${Latest version >= 1.0.8}</version> </dependency> 启动类Application上添加注解 @EnableMqttServer 配置application.yml文件properties也支持,但是需要自己转换,没有提供demo文件config.yaml 启动springboot服务服务即可 如果引入的是spring-boot-starter-parent的管理包,如果启动报错,则需要添加以下依赖 <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.4.9</version> </dependency> <dependency> <groupId>io.projectreactor.netty</groupId> <artifactId>reactor-netty</artifactId> <version>1.0.10</version> </dependency> --- ### 311. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Mica-MQTT 是一款强大的 MQTT(Message Queuing Telemetry Transport)物联网组件,旨在提供出色的性能和灵活性。它适用于各种使用场景,包括物联网、消息通信、即时通讯(IM)和消息推送。本文将向您介绍 Mica-MQTT 的主要功能、优势以及使用场景。 使用场景 Mica-MQTT 可以用于多种用途,包括但不限于: 物联网(云端 MQTT Broker): 用于支持大规模物联网设备的通信和数据传输。 物联网(边缘端消息通信): 适用于连接边缘设备的消息传递,支持低延迟通信。 群组类 IM: 用于构建即时通讯应用,支持群组聊天和私聊。 消息推送: 用于实现消息推送服务,将消息快速可靠地传递给接收者。 简单易用的 MQTT 客户端: Mica-MQTT 提供了 MQTT 客户端,使开发者可以轻松与 MQTT 代理进行通信。 优势 Mica-MQTT 具有以下显著优势: 灵活而强大: Mica-MQTT 提供了丰富的功能集,同时保持了灵活性,可以根据需要进行二次开发或扩展。 支持 MQTT 协议: 支持 MQTT v3.1、v3.1.1 以及 v5.0 协议,满足不同 MQTT 版本的需求。 WebSocket 支持: 支持 MQTT 子协议的 WebSocket 连接,允许浏览器和其他应用使用 MQTT 协议进行通信。 HTTP REST API: 提供 HTTP REST API,使您可以使用 HTTP 请求进行通信。具体的 API 文档详见官方文档。 集群支持: Mica-MQTT 支持 MQTT 客户端和服务器的共享订阅,采用高效的 topic 树存储方式,能够处理百万级别的 topic,保持高性能。 遗嘱消息和保留消息: 支持 MQTT 遗嘱消息和保留消息,确保消息的可靠性和持久性。 Spring Boot 集成: 提供 Spring Boot 项目的快速接入,使集成更加简单。 监控支持: 支持与 Prometheus 和 Grafana 集成,实现监控和性能优化。 GraalVM 支持: 您可以使用 GraalVM 将 Mica-MQTT 编译成本机可执行程序,以获得更好的性能。 默认端口 Mica-MQTT 使用以下默认端口: 1883 端口:用于 MQTT TCP 通信。 8083 端口:用于 HTTP、WebSocket 以及 MQTT 子协议通信。 您可以在 演示地址 上查看 Mica-MQTT 的演示,使用账号 mica 和密码 mica 登录以了解更多。 总结 Mica-MQTT 是一款功能丰富、性能出色的 MQTT 物联网组件,适用于各种 IoT 和通信需求。如果您正在寻找可靠的 MQTT 解决方案,Mica-MQTT 可能是您的理想之选。 Spring boot 项目 客户端: 一、添加依赖 <dependency> <groupId>net.dreamlu</groupId> <artifactId>mica-mqtt-client-spring-boot-starter</artifactId> <version>${最新版本}</version> </dependency> 二、mqtt 客户端 2.1 配置项示例 mqtt: client: enabled: true # 是否开启客户端,默认:true ip: 127.0.0.1 # 连接的服务端 ip ,默认:127.0.0.1 port: 1883 # 端口:默认:1883 name: Mica-Mqtt-Client # 名称,默认:Mica-Mqtt-Client clientId: 000001 # 客户端Id(非常重要,一般为设备 sn,不可重复) user-name: mica # 认证的用户名 password: 123456 # 认证的密码 timeout: 5 # 超时时间,单位:秒,默认:5秒 reconnect: true # 是否重连,默认:true re-interval: 5000 # 重连时间,默认 5000 毫秒 version: mqtt_3_1_1 # mqtt 协议版本,可选 MQTT_3_1、mqtt_3_1_1、mqtt_5,默认:mqtt_3_1_1 read-buffer-size: 8KB # 接收数据的 buffer size,默认:8k max-bytes-in-message: 10MB # 消息解析最大 bytes 长度,默认:10M buffer-allocator: heap # 堆内存和堆外内存,默认:堆内存 keep-alive-secs: 60 # keep-alive 时间,单位:秒 clean-session: true # mqtt clean session,默认:true ssl: enabled: false # 是否开启 ssl 认证,2.1.0 开始支持双向认证 keystore-path: # 可选参数:ssl 双向认证 keystore 目录,支持 classpath:/ 路径。 keystore-pass: # 可选参数:ssl 双向认证 keystore 密码 truststore-path: # 可选参数:ssl 双向认证 truststore 目录,支持 classpath:/ 路径。 truststore-pass: # 可选参数:ssl 双向认证 truststore 密码 注意:ssl 存在三种情况 服务端开启ssl客户端ClientAuth 为 NONE(不需要客户端验证)仅仅需要开启 ssl 即可不用配置证书ClientAuth 为 OPTIONAL(与客户端协商)需开启 ssl 并且配置 truststore 证书ClientAuth 为 REQUIRE (必须的客户端验证)需开启 ssl 并且配置 truststore、 keystore证书 2.2 可实现接口(注册成 Spring Bean 即可) 接口是否必须说明IMqttClientConnectListener否客户端连接成功监听 2.3 客户端上下线监听 使用 Spring event 解耦客户端上下线监听,注意: 1.3.4 开始支持。会跟自定义的 IMqttClientConnectListener 实现冲突,取一即可。 /** * 示例:客户端连接状态监听 * * @author L.cm */ @Service public class MqttClientConnectListener { private static final Logger logger = LoggerFactory.getLogger(MqttClientConnectListener.class); @Autowired private MqttClientCreator mqttClientCreator; @EventListener public void onConnected(MqttConnectedEvent event) { logger.info("MqttConnectedEvent:{}", event); } @EventListener public void onDisconnect(MqttDisconnectEvent event) { // 离线时更新重连时的密码,适用于类似阿里云 mqtt clientId 连接带时间戳的方式 logger.info("MqttDisconnectEvent:{}", event); // 在断线时更新 clientId、username、password mqttClientCreator.clientId("newClient" + System.currentTimeMillis()) .username("newUserName") .password("newPassword"); } } 2.4 自定义 java 配置(可选) @Configuration(proxyBeanMethods = false) public class MqttClientCustomizerConfiguration { @Bean public MqttClientCustomizer mqttClientCustomizer() { return new MqttClientCustomizer() { @Override public void customize(MqttClientCreator creator) { // 此处可自定义配置 creator,会覆盖 yml 中的配置 System.out.println("----------------MqttServerCustomizer-----------------"); } }; } } 2.5 订阅示例 @Service public class MqttClientSubscribeListener { private static final Logger logger = LoggerFactory.getLogger(MqttClientSubscribeListener.class); @MqttClientSubscribe("/test/#") public void subQos0(String topic, byte[] payload) { logger.info("topic:{} payload:{}", topic, new String(payload, StandardCharsets.UTF_8)); } @MqttClientSubscribe(value = "/qos1/#", qos = MqttQoS.AT_LEAST_ONCE) public void subQos1(String topic, byte[] payload) { logger.info("topic:{} payload:{}", topic, new String(payload, StandardCharsets.UTF_8)); } @MqttClientSubscribe("/sys/${productKey}/${deviceName}/thing/sub/register") public void thingSubRegister(String topic, byte[] payload) { // 1.3.8 开始支持,@MqttClientSubscribe 注解支持 ${} 变量替换,会默认替换成 + // 注意:mica-mqtt 会先从 Spring boot 配置中替换参数 ${},如果存在配置会优先被替换。 logger.info("topic:{} payload:{}", topic, new String(payload, StandardCharsets.UTF_8)); } } 2.6 共享订阅 topic 说明 mica-mqtt 支持两种共享订阅方式: 共享订阅:订阅前缀 $queue/,多个客户端订阅了 $queue/topic,发布者发布到 topic,则只有一个客户端会接收到消息。 分组订阅:订阅前缀 $share/<group>/,组客户端订阅了 $share/group1/topic、$share/group2/topic..,发布者发布到 topic,则消息会发布到每个 group 中,但是每个 group 中只有一个客户端会接收到消息。 注意: 如果发布的 topic 以 / 开头,例如:/topic/test,需要订阅 $share/group1//topic/test,另外 mica-mqtt 默认随机消息路由,共享订阅的多个客户端会随机收到消息。 2.7 MqttClientTemplate 使用示例 import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; /** * @author wsq */ @Service public class MainService { private static final Logger logger = LoggerFactory.getLogger(MainService.class); @Autowired private MqttClientTemplate client; public boolean publish() { client.publish("/test/client", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); return true; } public boolean sub() { client.subQos0("/test/#", (context, topic, message, payload) -> { logger.info(topic + '\t' + new String(payload, StandardCharsets.UTF_8)); }); return true; } } 服务端 一、添加依赖 <dependency> <groupId>net.dreamlu</groupId> <artifactId>mica-mqtt-server-spring-boot-starter</artifactId> <version>${最新版本}</version> </dependency> 二、mqtt 服务 2.1 配置项 mqtt: server: enabled: true # 是否开启服务端,默认:true # ip: 0.0.0.0 # 服务端 ip 默认为空,0.0.0.0,建议不要设置 port: 1883 # 端口,默认:1883 name: Mica-Mqtt-Server # 名称,默认:Mica-Mqtt-Server buffer-allocator: HEAP # 堆内存和堆外内存,默认:堆内存 heartbeat-timeout: 120000 # 心跳超时,单位毫秒,默认: 1000 * 120 read-buffer-size: 8KB # 接收数据的 buffer size,默认:8k max-bytes-in-message: 10MB # 消息解析最大 bytes 长度,默认:10M auth: enable: false # 是否开启 mqtt 认证 username: mica # mqtt 认证用户名 password: mica # mqtt 认证密码 debug: true # 如果开启 prometheus 指标收集建议关闭 stat-enable: true # 开启指标收集,debug 和 prometheus 开启时需要打开,默认开启,关闭节省内存 web-port: 8083 # http、websocket 端口,默认:8083 websocket-enable: true # 是否开启 websocket,默认: true http-enable: false # 是否开启 http api,默认: false http-basic-auth: enable: false # 是否开启 http basic auth,默认: false username: mica # http basic auth 用户名 password: mica # http basic auth 密码 ssl: # mqtt tcp ssl 认证 enabled: false # 是否开启 ssl 认证,2.1.0 开始支持双向认证 keystore-path: # 必须参数:ssl keystore 目录,支持 classpath:/ 路径。 keystore-pass: # 必选参数:ssl keystore 密码 truststore-path: # 可选参数:ssl 双向认证 truststore 目录,支持 classpath:/ 路径。 truststore-pass: # 可选参数:ssl 双向认证 truststore 密码 client-auth: none # 是否需要客户端认证(双向认证),默认:NONE(不需要) 注意:ssl 存在三种情况 服务端开启ssl客户端ClientAuth 为 NONE(不需要客户端验证)仅仅需要开启 ssl 即可不用配置证书ClientAuth 为 OPTIONAL(与客户端协商)需开启 ssl 并且配置 truststore 证书ClientAuth 为 REQUIRE (必须的客户端验证)需开启 ssl 并且配置 truststore、 keystore证书 2.2 可实现接口(注册成 Spring Bean 即可) 接口是否必须说明IMqttServerUniqueIdService否用于 clientId 不唯一时,自定义实现唯一标识,后续接口使用它替代 clientIdIMqttServerAuthHandler是用于服务端认证IMqttServerSubscribeValidator否(建议实现)1.1.3 新增,用于对客户端订阅校验IMqttServerPublishPermission否(建议实现)1.2.2 新增,用于对客户端发布权限校验IMqttMessageListener否(1.3.x为否)消息监听IMqttConnectStatusListener是连接状态监听IMqttSessionManager否session 管理IMqttSessionListener否session 监听IMqttMessageStore集群是,单机否遗嘱和保留消息存储AbstractMqttMessageDispatcher集群是,单机否消息转发,(遗嘱、保留消息转发)IpStatListener否t-io ip 状态监听IMqttMessageInterceptor否消息拦截器,1.3.9 新增 2.3 IMqttMessageListener (用于监听客户端上传的消息) 使用示例 @Service public class MqttServerMessageListener implements IMqttMessageListener { private static final Logger logger = LoggerFactory.getLogger(MqttServerMessageListener.class); @Override public void onMessage(ChannelContext context, String clientId, Message message) { logger.info("clientId:{} message:{} payload:{}", clientId, message, new String(message.getPayload(), StandardCharsets.UTF_8)); } } 2.4 自定义配置(可选) @Configuration(proxyBeanMethods = false) public class MqttServerCustomizerConfiguration { @Bean public MqttServerCustomizer mqttServerCustomizer() { return new MqttServerCustomizer() { @Override public void customize(MqttServerCreator creator) { // 此处可自定义配置 creator,会覆盖 yml 中的配置 System.out.println("----------------MqttServerCustomizer-----------------"); } }; } } 2.5 MqttServerTemplate 使用示例 import net.dreamlu.iot.mqtt.spring.server.MqttServerTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.ByteBuffer; /** * @author wsq */ @Service public class ServerService { @Autowired private MqttServerTemplate server; public boolean publish(String body) { server.publishAll("/test/123", body.getBytes(StandardCharsets.UTF_8)); return true; } } 2.6 客户端上下线监听 使用 Spring event 解耦客户端上下线监听,注意: 1.3.4 开始支持。会跟自定义的 IMqttConnectStatusListener 实现冲突,取一即可。 @Service public class MqttConnectStatusListener { private static final Logger logger = LoggerFactory.getLogger(MqttConnectStatusListener.class); @EventListener public void online(MqttClientOnlineEvent event) { logger.info("MqttClientOnlineEvent:{}", event); } @EventListener public void offline(MqttClientOfflineEvent event) { logger.info("MqttClientOfflineEvent:{}", event); } } 2.7 基于 mq 消息广播集群处理 详见: mica-mqtt-broker 2.8 Prometheus + Grafana 监控对接 <!-- 开启 prometheus 指标收集 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> 支持得指标说明mqtt_connections_accepted共接受过连接数mqtt_connections_closed关闭过的连接数mqtt_connections_size当前连接数mqtt_messages_handled_packets已处理消息数mqtt_messages_handled_bytes已处理消息字节数mqtt_messages_received_packets已接收消息数mqtt_messages_received_bytes已处理消息字节数mqtt_messages_send_packets已发送消息数mqtt_messages_send_bytes已发送消息字节数 非 Spring boot 项目 客户端 topic 通配符含义 /:用来表示层次,比如 a/b,a/b/c。 #:表示匹配 >=0 个层次,比如 a/# 就匹配 a/,a/b,a/b/c。单独的一个 # 表示匹配所有。不允许 a# 和 a/#/c。 +:表示匹配一个层次,例如 a/+ 匹配 a/b,a/c,不匹配 a/b/c。单独的一个 + 是允许的,a+ 不允许,也可以和多层通配符一起使用,+/tennis/# 、sport/+/player1 都有有效的。 使用说明 MQTT 遗嘱消息场景 当客户端断开连接时,发送给相关的订阅者的遗嘱消息。在设备 A 进行连接时候,遗嘱消息设定为 offline,手机App B 订阅这个遗嘱主题。 当 A 异常断开时,手机App B 会收到这个 offline 的遗嘱消息,从而知道设备 A 离线了。 MQTT 保留消息场景 例如,某设备定期发布自身 GPS 坐标,但对于订阅者而言,从它发起订阅到第一次收到数据可能需要几秒钟,也可能需要十几分钟甚至更多,这样并不友好。因此 MQTT 引入了保留消息。 而每当有订阅者建立订阅时,服务端就会查找是否存在匹配该订阅的保留消息,如果保留消息存在,就会立即转发给订阅者。 借助保留消息,新的订阅者能够立即获取最近的状态。 共享订阅 mica-mqtt 支持两种共享订阅方式: 共享订阅:订阅前缀 $queue/,多个客户端订阅了 $queue/topic,发布者发布到 topic,则只有一个客户端会接收到消息。 分组订阅:订阅前缀 $share/<group>/,组客户端订阅了 $share/group1/topic、$share/group2/topic..,发布者发布到 topic,则消息会发布到每个 group 中,但是每个 group 中只有一个客户端会接收到消息。 注意: 如果发布的 topic 以 / 开头,例如:/topic/test,需要订阅 $share/group1//topic/test,另外 mica-mqtt 默认随机消息路由,共享订阅的多个客户端会随机收到消息。 客户端使用 // 初始化 mqtt 客户端 MqttClient client = MqttClient.create() .ip("127.0.0.1") // mqtt 服务端 ip 地址 .port(1883) // 默认:1883 .username("admin") // 账号 .password("123456") // 密码 .version(MqttVersion.MQTT_5) // 默认:3_1_1 .clientId("xxxxxx") // 非常重要务必手动设置,一般设备 sn 号,默认:MICA-MQTT- 前缀和 36进制的纳秒数 .bufferAllocator(ByteBufferAllocator.DIRECT) // 堆内存和堆外内存,默认:堆内存 .readBufferSize(512) // 消息一起解析的长度,默认:为 8092 (mqtt 消息最大长度) .maxBytesInMessage(1024 * 10) // 最大包体长度,如果包体过大需要设置此参数,默认为: 10M (10*1024*1024) .keepAliveSecs(120) // 默认:60s .timeout(10) // 超时时间,t-io 配置,可为 null,为 null 时,t-io 默认为 5 .reconnect(true) // 是否重连,默认:true .reInterval(5000) // 重连重试时间,reconnect 为 true 时有效,t-io 默认为:5000 .willMessage(builder -> { builder.topic("/test/offline").messageText("down"); // 遗嘱消息 }) .connectListener(new IMqttClientConnectListener() { @Override public void onConnected(ChannelContext context, boolean isReconnect) { logger.info("链接服务器成功..."); } @Override public void onDisconnect(ChannelContext channelContext, Throwable throwable, String remark, boolean isRemove) { logger.info("与链接服务器断开连接..."); } }) .properties() // mqtt5 properties .connectSync(); // 同步连接,也可以使用 connect(),可以避免 broker 没启动照成启动卡住。 // 消息订阅,同类方法 subxxx client.subQos0("/test/#", (context, topic, message, payload) -> { logger.info(topic + '\t' + new String(payload, StandardCharsets.UTF_8)); }); // 取消订阅 client.unSubscribe("/test/#"); // 发送消息 client.publish("/test/client", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 断开连接 client.disconnect(); // 重连 client.reconnect(); // 停止 client.stop(); 服务端 // 注意:为了能接受更多链接(降低内存),请添加 jvm 参数 -Xss129k MqttServer mqttServer = MqttServer.create() // 服务端 ip 默认为空,0.0.0.0,建议不要设置 .ip("0.0.0.0") // 默认:1883 .port(1883) // 默认为: 8092(mqtt 默认最大消息大小),为了降低内存可以减小小此参数,如果消息过大 t-io 会尝试解析多次(建议根据实际业务情况而定) .readBufferSize(512) // 最大包体长度,如果包体过大需要设置此参数,默认为: 8092 .maxBytesInMessage(1024 * 100) // 自定义认证 .authHandler((clientId, userName, password) -> true) // 消息监听 .messageListener((context, clientId, message) -> { logger.info("clientId:{} message:{} payload:{}", clientId, message, new String(message.getPayload(), StandardCharsets.UTF_8)); }) // 堆内存和堆外内存选择,默认:堆内存 .bufferAllocator(ByteBufferAllocator.HEAP) // 心跳超时时间,默认:120s .heartbeatTimeout(120_1000L) // ssl 配置 .useSsl("", "", "") // 自定义客户端上下线监听 .connectStatusListener(new IMqttConnectStatusListener() { @Override public void online(String clientId) { } @Override public void offline(String clientId) { } }) // 自定义消息转发,可用 mq 广播实现集群化处理 .messageDispatcher(new IMqttMessageDispatcher() { @Override public void config(MqttServer mqttServer) { } @Override public boolean send(Message message) { return false; } @Override public boolean send(String clientId, Message message) { return false; } }) .debug() // 开启 debug 信息日志 .start(); // 发送给某个客户端 mqttServer.publish("clientId","/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 发送给所有在线监听这个 topic 的客户端 mqttServer.publishAll("/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 停止服务 mqttServer.stop(); --- ### 312. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 Hue2MQTT是一个Python应用程序,允许您通过MQTT协议控制飞利浦 Hue智能灯光系统,并实时发布其当前状态。该工具是使用Python 3.8+编写的,具有类型提示和异步支持,使用aiohue库与Hue通信,同时还支持IPv6。 2. 配置 Hue2MQTT的配置文件为".hue2mqtt.toml",以下是默认配置文件的示例: # Hue2MQTT 默认配置文件 [mqtt] # 使用host.docker.internal连接到在Docker主机上安装的MQTT代理 # host = "host.docker.internal" host = "::1" port = 1883 enable_tls = false force_protocol_version_3_1 = true enable_auth = false username = "" password = "" topic_prefix = "hue2mqtt" [hue] ip = "192.0.2.2" # 或IPv6:"[2001:db0::1]" username = "这里放您的密钥" 如果您不知道Hue桥的用户名,您可以使用以下命令进行查找: hue2mqtt --discover 3. 运行 Hue2MQTT 通常情况下,运行Hue2MQTT非常简单,只需在命令行中运行以下命令: hue2mqtt 您还可以使用一些选项,例如"-v"用于详细输出,"-c"用于指定配置文件,"-discover"用于发现Hue桥等。 4. 桥的状态 Hue2MQTT将桥的状态以JSON对象的形式发布到"hue2mqtt/status"主题,示例状态如下: {"online": true, "bridge": {"name": "Philips Hue", "mac_address": "ec:b5:fa:ab:cd:ef", "api_version": "1.45.0"}} 如果"online"为false,那么可以假定桥发布的所有其他信息都不准确。 5. 获取Hue信息 Hue2MQTT将有关Hue状态的信息作为MQTT保留消息发布。当状态发生更改时,将重新发布消息。 灯光:有关每个光源的信息将发布到"hue2mqtt/light/{{UNIQUEID}}"主题。这包括有关灯光的状态、属性和制造商信息。 组:组表示Hue应用程序中的房间和区域。有关每个组的信息将发布到"hue2mqtt/group/{{GROUPID}}"主题,包括组内灯光的状态、属性和制造商信息。 传感器:传感器代表Hue生态系统中的其他对象,例如开关和运动传感器。有关每个传感器的信息将发布到"hue2mqtt/sensor/{{UNIQUEID}}"主题,包括传感器的类型、属性和制造商信息。 6. 控制Hue 您可以通过发布JSON对象到"hue2mqtt/light/{{UNIQUEID}}/set"或"hue2mqtt/group/{{GROUPID}}/set"主题来控制灯光和组的操作。JSON对象应包含要更改的状态值。 7. Docker支持 Hue2MQTT还提供了一个包括Dockerfile和docker-compose示例的Docker工作环境,以方便部署。 8. 与Docker主机连接 要与Docker主机建立MQTT连接(假设localhost是Docker实例),请在配置文件"hue2mqtt.toml"中使用以下设置: host = "host.docker.internal" Hue2MQTT允许您通过MQTT控制飞利浦 Hue智能灯光系统,并通过MQTT接收实时事件,无需定期轮询Hue桥接器以获取更改。这使您可以轻松地将Hue集成到自动化解决方案中,以满足各种需求。 --- ### 313. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 WeConnect-MQTT是一个用于将大众汽车WeConnect服务数据发布到MQTT协议的客户端。MQTT(Message Queuing Telemetry Transport)是一种标准协议,用于集成来自WeConnect启用的汽车的数据。该客户端允许您将数据集成到您选择的MQTT代理中,例如家庭自动化解决方案(如ioBroker、FHEM或Home Assistant)。 2. 硬件和软件要求 在您的系统上安装Python 3是必需的,最低要求的Python版本为3.8。如果您的车型使用新的WeConnect API,您可能需要同意新的WeConnect接口的条款和条件。最简单的方式是在智能手机上安装大众汽车应用程序并在那里登录。 3. 安装 要使用WeConnect-MQTT,最简单的方式是从PyPI获取它。只需运行以下命令进行安装: pip3 install weconnect-mqtt 4. 升级 如果您希望升级WeConnect-MQTT,最简单的方式是运行以下命令: pip3 install weconnect-mqtt --upgrade 5. Docker支持 还提供了一个Docker镜像,以轻松托管WeConnect-MQTT,您可以在Dockerhub上找到它。 6. 使用说明 您可以通过命令行启动WeConnect-MQTT客户端: weconnect-mqtt 您可以使用"--help"命令来获取所有使用说明: weconnect-mqtt --help 以下是一个连接到MQTT代理地址为192.168.0.1,使用用户名test和密码test123的示例: weconnect-mqtt --username test@test.de --password test123 --mqttbroker 192.168.0.1 --mqtt-username test --mqtt-password test123 --prefix weconnect 在此示例中,客户端使用用户名test@test.de和密码test123连接到WeConnect。 7. S-PIN 对于某些命令(例如,某些车型支持的锁定/解锁功能),除了登录,您还需要提供S-PIN(安全个人识别码),您可以使用"--spin"选项来提供: weconnect-mqtt --username test@test.de --password test123 --spin 1234 --mqttbroker 192.168.0.1 --mqtt-username test --mqtt-password test123 --prefix weconnect 8. 凭据 如果您不想每次都提供用户名和密码,您可以在适当的位置(通常是主文件夹)创建一个".netrc"文件: # 对于WeConnect machine volkswagen.de login test@test.de password testpassword123 # 对于MQTT代理 machine 192.168.0.1 login test password testpassword123 您还可以使用"--netrc"选项来指定".netrc"文件的位置。 9. 充电站数据 您还可以通过添加位置和半径信息来获取充电站的数据,例如"--chargingLocation 52.437132 10.796628 --chargingLocationRadius=500"。充电站的数据主要是静态的,但您可以查看当前的可用性。 10. 主题 如果您的MQTT代理不允许您观察所有可用主题,您可以传递参数"--list-topics"以在命令行上显示所有主题。带有"(writeable)"标记的主题可以进行操作。还有两个主题,用于以逗号分隔的列表形式接收所有可用主题:"weconnect/0/mqtt/topics"和"weconnect/0/mqtt/writeableTopics"。 11. 禁用功能 您可以使用"--no-capabilities"选项来禁用车辆功能数据。如果只需要数据的子集,您可以使用"--selective"选项。例如,"--selective climatisation"。 12. 图像 您可以使用"--pictures"选项来启用汽车的ASCII Art图片。 13. PNG车辆图片 如果您的MQTT客户端可以处理通过MQTT接收的PNG图片,您可以使用"--picture-format png"选项。 14. 时间设置 默认情况下,车辆传来的时间是UTC isoformat。您可以通过添加"--convert-times"选项将时间转换为本地时区。要将时间设置为特定的时区,可以使用"--convert-times Europe/Berlin"。您还可以通过"--timeformat"将时间格式化为本地时间格式,例如"--timeformat '%a %d %b %Y %T'"。如果要使用不同于系统默认语言的日期格式,可以使用"--locale"选项。 15. 原始JSON数据 如果您想继续处理完整的数据,您还可以使用"--with-raw-json-topic"选项启用原始JSON数据主题。该主题在JSON字符串发生更改时发布。 16. 已测试车型 大众ID.3(2021年车型) 大众Passat GTE(2021年车型) 17. 相关项目 WeConnect-cli:用于与大众汽车WeConnect服务进行交互的命令行界面 WeConnect-python:连接到大众汽车WeConnect服务的Python API VWsFriend:VWsFriend是一款可视化记录汽车统计数据并允许通过HomeKit进行控制的软件。 通过WeConnect-MQTT,您可以轻松将大众汽车WeConnect服务的数据发布到MQTT,并将其集成到您的自动化解决方案中。这个客户端提供了丰富的功能和选项,使其非常灵活,适用于多种应用场景。 --- ### 314. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,广泛应用于物联网和实时通信领域。asyncio-mqtt是一个为Python开发者设计的基于异步IO的MQTT客户端库,通过利用Python的asyncio库提供高效、可靠的异步MQTT通信。 2. 安装 要安装asyncio-mqtt库,可以使用以下命令: pip install asyncio-mqtt 3. 使用方法 使用asyncio-mqtt库可以轻松地实现异步MQTT通信。 3.1 连接到MQTT代理 首先,需要创建一个MQTT客户端并连接到MQTT代理服务器: import asyncio_mqtt as mqtt async def connect_mqtt(): client = mqtt.Client() await client.connect('mqtt.example.com') return client client = asyncio.run(connect_mqtt()) 在上述示例中,'mqtt.example.com' 是MQTT代理服务器的地址。 3.2 发布消息 要发布消息到MQTT代理服务器,可以使用publish方法: await client.publish('topic', 'message') 在上述示例中,'topic' 是要发布到的主题,'message' 是要发送的消息。 3.3 订阅消息 要订阅MQTT代理服务器的消息,可以使用subscribe方法: async def on_message(topic, message): print(f'Received message in topic "{topic}": {message}') await client.subscribe('topic', on_message) 在上述示例中,'topic' 是要订阅的主题,'on_message' 是在接收到消息时调用的回调函数。 3.4 断开连接 当不再需要与MQTT代理服务器通信时,可以断开连接: await client.disconnect() 4. 优点 使用asyncio-mqtt库具有以下优点: 异步IO支持:asyncio-mqtt利用Python的asyncio库实现了异步IO,提高了MQTT通信的效率和可靠性。 易于使用:asyncio-mqtt提供了简洁的API接口,使得MQTT通信容易上手并可以轻松集成到现有项目中。 5. 应用场景 asyncio-mqtt适用于各种需要异步MQTT通信的场景,特别在以下情况下它尤为有用: 物联网应用:asyncio-mqtt能够轻松与物联网设备进行异步通信,实现实时数据传输和控制。 实时监控系统:使用asyncio-mqtt,您可以建立快速响应的实时监控系统,监控设备状态并接收实时数据。 消息订阅与发布:通过asyncio-mqtt,可以轻松实现消息订阅和发布机制,支持实时信息推送和订阅者的消息更新。 综上所述,asyncio-mqtt是一个高效、易于使用的异步MQTT客户端库。它基于Python的asyncio库,提供异步MQTT通信功能,使得在物联网和实时通信领域更加便捷。通过asyncio-mqtt,您可以轻松构建异步MQTT应用,满足各种实时通信需求。 --- ### 315. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在当前的数字化时代,实时数据交流和物联网(IoT)技术正快速增长,开发者们正在寻找更高效和更稳定的方法来处理数据流。在这方面,MQTT 和 Django 都已经成为了各自领域的领导者。在本文中,我们将介绍如何将这两个强大的工具集成在一起,以打造一个稳定、快速的实时通讯系统。 Django 简介及其特点 Django 是一个开放源代码的 Web 开发框架,由 Python 语言编写。它鼓励“不要重复自己”的设计哲学和“框架即插件”的结构,使得开发者能够快速、高效地构建高品质的 Web 应用程序。以下是 Django 的主要特点: DRY原则 (Don't Repeat Yourself):Django 遵循 DRY 原则,意味着系统应尽量避免重复的功能和信息。 安全性:Django 自带了防范多种网络攻击的功能,如 CSRF、XSS、SQL注入等。 可扩展性:它的“框架即插件”结构使得开发者可以轻松地添加功能和组件。 MVC 架构:Django 遵循模型-视图-控制器 (MVC) 设计模式,帮助开发者组织代码和逻辑。 MQTT 简介及其特点 MQTT (Message Queuing Telemetry Transport) 是一种基于发布/订阅模式的轻量级消息传递协议,特别适用于低带宽、不稳定的网络环境。以下是 MQTT 的主要特点: 轻量级:MQTT 是为低带宽和低功耗的设备设计的,它的协议头非常小。 质量服务等级:MQTT 提供三种消息交付级别:At most once、At least once、Exactly once,使得开发者可以根据需要选择合适的级别。 持久性会话:MQTT 支持持久会话,即客户端可以选择保持其会话信息,从而避免频繁的重新连接。 Last Will 和 Testament (LWT) 消息:这是一个预定义的消息,只有在发布者失去连接时,才会被发布。 有了上述背景知识,我们现在可以探讨如何在 Django 项目中整合 MQTT,实现实时通信。 初始化项目 首先,我们将使用 Python 3.8 作为开发环境,你可以通过以下命令确认你的 Python 版本: $ python3 --version Python 3.8.2 接着,使用 Pip 安装所需的包: pip3 install django paho-mqtt 然后,创建一个新的 Django 项目: django-admin startproject mqtt_test 项目结构如下: ├── manage.py └── mqtt_test ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py ├── views.py └── wsgi.py MQTT 的整合 我们将使用由 EMQ 提供的公共 MQTT 服务器,服务器信息如下: Broker: broker.emqx.io TCP Port: 1883 Websocket Port: 8083 首先,导入必要的库: import paho.mqtt.client as mqtt 设置连接的回调函数。成功连接后,我们将订阅到 django/mqtt 主题: def on_connect(mqtt_client, userdata, flags, rc): if rc == 0: print('Connected successfully') mqtt_client.subscribe('django/mqtt') else: print('Connection failed. Code:', rc) 设置接收消息的回调函数: def on_message(mqtt_client, userdata, msg): print(f'Received message on topic: {msg.topic} with payload: {msg.payload}') 在 settings.py 中配置 MQTT: MQTT_SERVER = 'broker.emqx.io' MQTT_PORT = 1883 MQTT_KEEPALIVE = 60 MQTT_USER = '' MQTT_PASSWORD = '' 初始化 MQTT 客户端并连接: client = mqtt.Client() client.on_connect = on_connect client.on_message = on_message client.username_pw_set(settings.MQTT_USER, settings.MQTT_PASSWORD) client.connect( host=settings.MQTT_SERVER, port=settings.MQTT_PORT, keepalive=settings.MQTT_KEEPALIVE ) 为了演示,我们创建一个发布消息的接口: import json from django.http import JsonResponse from mqtt_test.mqtt import client as mqtt_client def publish_message(request): request_data = json.loads(request.body) rc, mid = mqtt_client.publish(request_data['topic'], request_data['msg']) return JsonResponse({'code': rc}) 在 urls.py 中,将接口与 URL 进行绑定: from django.urls import path from . import views urlpatterns = [ path('publish', views.publish_message, name='publish'), ] 最后,在 __init__.py 中启动 MQTT 客户端: from . import mqtt mqtt.client.loop_start() 运行项目 执行以下命令,启动 Django 项目: python3 manage.py runserver 项目启动后,MQTT 客户端将连接服务器,并订阅 django/mqtt 主题。 至此,我们已成功在 Django 项目中整合了 MQTT。这为你提供了一个强大的实时消息功能,无论是 IoT 项目还是其他实时更新的应用,这种结合都会带来巨大的便利。 --- ### 316. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着物联网 (IoT) 和微服务架构的日益普及,MQTT 已经成为一个关键的消息传递协议。在本文中,我们将讨论如何在 Spring Boot 应用程序中集成 MQTT,从而为你的应用带来更好的扩展性和响应性。 1. 什么是 MQTT? MQTT(Message Queuing Telemetry Transport)是一个轻量级的发布/订阅协议,专为低带宽、高延迟或不可靠的网络设计。它广泛应用于 IoT 场景中,连接传感器、设备和应用。 2. 为什么选择 MQTT? 轻量级:MQTT 的报文头部很小,非常适合于受到带宽限制的网络。 消息等级:它支持不同级别的消息传递保证。 持久会话:支持持久会话,即客户端和服务器之间的会话状态可以被保留。 最后遗言:如果一个客户端断开连接,它可以预先设定一个“最后遗言”消息。 3. Spring Boot 中的 MQTT 要在 Spring Boot 中使用 MQTT,我们首先需要添加相关的依赖。我们将使用 Eclipse Paho Java 客户端作为 MQTT 的客户端库。 <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-mqtt</artifactId> <version>5.5.9</version> </dependency> <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.5</version> </dependency> 4. 配置 MQTT 包含接收消息的配置和发送消息的配置 package com.demo.config; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.integration.annotation.ServiceActivator; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.core.MessageProducer; import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory; import org.springframework.integration.mqtt.core.MqttPahoClientFactory; import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter; import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler; import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import java.util.UUID; /** * mqtt连接配置 */ @Configuration public class MqttConfig { /** * 创建连接 * * @return */ @Bean public MqttPahoClientFactory mqttClientFactory() { DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory(); MqttConnectOptions options = new MqttConnectOptions(); // mqtt用户名&密码 String userName = ""; String pwd = ""; // mqtt服务地址,可以是多个 options.setServerURIs(new String[]{"tcp://server:1883"}); options.setUserName(userName); options.setPassword(pwd.toCharArray()); factory.setConnectionOptions(options); return factory; } /** * 2、接收消息的通道 */ @Bean public MessageChannel mqttInputChannel() { return new DirectChannel(); } /** * 接收消息 * * @return */ @Bean public MessageProducer inbound() { // 订阅主题,保证唯一性 String inClientId = UUID.randomUUID().toString().replaceAll("-", ""); // 最后的#相当于通配符的概念 String[] topic = {"topic_prefix/topic/#"}; MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter( inClientId, mqttClientFactory(), topic); adapter.setCompletionTimeout(5000); DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter(); // 按字节接收消息 // defaultPahoMessageConverter.setPayloadAsBytes(true); adapter.setConverter(defaultPahoMessageConverter); // 设置QoS adapter.setQos(1); adapter.setOutputChannel(mqttInputChannel()); return adapter; } /** * 3、消息处理 * ServiceActivator注解表明:当前方法用于处理MQTT消息,inputChannel参数指定了用于消费消息的channel */ @Bean @ServiceActivator(inputChannel = "mqttInputChannel") public MessageHandler handler() { return message -> { String payload = message.getPayload().toString(); // byte[] bytes = (byte[]) message.getPayload(); // 收到的消息是字节格式 String topic = message.getHeaders().get("mqtt_receivedTopic").toString(); // 可以根据topic进行处理不同的业务类型 System.out.println("主题[" + topic + "],负载:" + payload); }; } /** * 发送消息的通道 * * @return */ @Bean public MessageChannel mqttOutboundChannel() { return new DirectChannel(); } /** * 发送消息 */ @Bean @ServiceActivator(inputChannel = "mqttOutboundChannel") public MessageHandler outbound() { // 连接clientId保证唯一 String outClientId = UUID.randomUUID().toString().replaceAll("-", ""); // 发送消息和消费消息Channel可以使用相同MqttPahoClientFactory MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(outClientId, mqttClientFactory()); // 如果设置成true,即异步,发送消息时将不会阻塞。 // messageHandler.setAsync(true); // 设置默认的topic // messageHandler.setDefaultTopic("defaultTopic"); // 设置默认QoS messageHandler.setDefaultQos(1); // Paho消息转换器 DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter(); // 发送默认按字节类型发送消息 // defaultPahoMessageConverter.setPayloadAsBytes(true); messageHandler.setConverter(defaultPahoMessageConverter); return messageHandler; } } 5. 消息发送 1. 定义消息发送的接口 package com.demo.config; import org.springframework.integration.annotation.MessagingGateway; import org.springframework.integration.mqtt.support.MqttHeaders; import org.springframework.messaging.handler.annotation.Header; /** * 定义消息发送的接口 */ @MessagingGateway(defaultRequestChannel = "mqttOutboundChannel") public interface MqttGateWay { /** * 发送消息 * * @param payload 发送的消息 */ void sendToMqtt(String payload); /** * 指定topic消息发送 * * @param topic 指定topic * @param payload 消息 */ void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload); void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload); void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, byte[] payload); } 2. 定义消息发送的controller package com.demo.business; import com.sonli.config.MqttGateWay; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 对外暴露发送消息的controller */ @RestController @RequestMapping("/mqtt") public class MqttController { @Autowired private MqttGateWay mqttGateWay; @PostMapping("/sendMessage") public String sendMessage(String topic, String message) { // 发送消息到指定topic mqttGateWay.sendToMqtt(topic, 1, message); return "send topic: " + topic + ", message : " + message; } } 测试 发送消息 消息的监听,收到的消息 总结 Spring Boot 与 MQTT 的集成为开发者提供了一个简单但功能强大的方式,用于创建 IoT 和消息驱动的应用程序。这种集成不仅确保了消息传递的可靠性和效率,还使得应用程序更具扩展性和响应性。 希望这篇文章能为你提供在 Spring Boot 中集成 MQTT 的指导。如果你有任何问题或需要进一步的指导,请随时留言或联系我们。 --- ### 317. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. Rust编程语言的简介Rust是Mozilla研发的编译型通用编程语言,它的核心原则是安全性、并发性和实用性。结合函数式、并发式、过程式以及面向对象的编程风格,Rust提供了出色的性能和高效的内存利用。不同于其他具有垃圾收集机制的语言,Rust没有运行时,这使其在高性能要求的服务和嵌入式设备上运行得更加高效。其强大的类型系统和所有权模型进一步确保了内存和线程的安全性,从而在编译时消除了众多错误。 2. MQTT的物联网传输协议MQTT是一个轻量级的物联网通信协议,基于发布/订阅模式,它针对网络带宽低和代码资源有限的环境进行了优化。被广泛应用于物联网、移动应用、智能硬件、车联网和能源行业。 3. Rust中的paho-mqtt客户端库为了使Rust与MQTT进行高效通信,我们选择使用paho-mqtt,一个在Rust社区中广受欢迎的MQTT客户端库。它支持最新的MQTT版本,并提供多种传输协议选项。 项目初始化 本项目使用 Rust 1.44.0 进行开发测试,并使用 Cargo 1.44.0 包管理工具进行项目管理,读者可用如下命令查看当前的 Rust 版本。 ~ rustc --version rustc 1.44.0 (49cae5576 2020-06-01) 选择 MQTT 客户端库 paho-mqtt 是目前 Rust 中,功能完善且使用较多的 MQTT 客户端,最新的 0.7.1 版本支持 MQTT v5、3.1.1、3.1,支持通过标准 TCP、SSL / TLS、WebSockets 传输数据,QoS 支持 0、1、2 等。 初始化项目 执行以下命令创建名为 mqtt-example 的 Rust 新项目。 ~ cargo new mqtt-example Created binary (application) `mqtt-example` package 编辑项目中的 Cargo.toml 文件,在 dependencies 中添加 paho-mqtt 库的地址,以及指定订阅、发布代码文件对应的二进制文件。 [dependencies] paho-mqtt = { git = "https://github.com/eclipse/paho.mqtt.rust.git", branch = "master" } [[bin]] name = "sub" path = "src/sub/main.rs" [[bin]] name = "pub" path = "src/pub/main.rs" Rust MQTT 的使用 创建客户端连接 本文将使用 EMQX 提供的 免费公共 MQTT 服务器 作为测试连接的 MQTT 服务器,该服务基于 EMQX 的 MQTT 物联网云平台 创建。服务器接入信息如下: Broker: broker.emqx.io TCP Port: 1883 Websocket Port: 8083 配置 MQTT Broker 连接参数 配置 MQTT Broker 连接地址(包括端口)、topic (这里我们配置了两个 topic ),以及客户端 id。 const DFLT_BROKER:&str = "tcp://broker.emqx.io:1883"; const DFLT_CLIENT:&str = "rust_publish"; const DFLT_TOPICS:&[&str] = &["rust/mqtt", "rust/test"]; 编写 MQTT 连接代码 编写 MQTT 连接代码,为了提升使用体验,可在执行二进制文件时通过命令行参数的形式传入连接地址。通常我们需要先创建一个客户端,然后将该客户端连接到 broker.emqx.io。 let host = env::args().nth(1).unwrap_or_else(|| DFLT_BROKER.to_string() ); // Define the set of options for the create. // Use an ID for a persistent session. let create_opts = mqtt::CreateOptionsBuilder::new() .server_uri(host) .client_id(DFLT_CLIENT.to_string()) .finalize(); // Create a client. let cli = mqtt::Client::new(create_opts).unwrap_or_else(|err| { println!("Error creating the client: {:?}", err); process::exit(1); }); // Define the set of options for the connection. let conn_opts = mqtt::ConnectOptionsBuilder::new() .keep_alive_interval(Duration::from_secs(20)) .clean_session(true) .finalize(); // Connect and wait for it to complete or fail. if let Err(e) = cli.connect(conn_opts) { println!("Unable to connect:\n\t{:?}", e); process::exit(1); } 发布消息 这里我们总共发布五条消息,根据循环的奇偶性,分别向 rust/mqtt、 rust/test 这两个主题发布。 for num in 0..5 { let content = "Hello world! ".to_string() + &num.to_string(); let mut msg = mqtt::Message::new(DFLT_TOPICS[0], content.clone(), QOS); if num % 2 == 0 { println!("Publishing messages on the {:?} topic", DFLT_TOPICS[1]); msg = mqtt::Message::new(DFLT_TOPICS[1], content.clone(), QOS); } else { println!("Publishing messages on the {:?} topic", DFLT_TOPICS[0]); } let tok = cli.publish(msg); if let Err(e) = tok { println!("Error sending message: {:?}", e); break; } } 订阅消息 在客户端连接之前,需要先初始化消费者。这里我们会循环处理消费者中的消息队列,并打印出订阅的 topic 名称及接收到的消息内容。 fn subscribe_topics(cli: &mqtt::Client) { if let Err(e) = cli.subscribe_many(DFLT_TOPICS, DFLT_QOS) { println!("Error subscribes topics: {:?}", e); process::exit(1); } } fn main() { ... // Initialize the consumer before connecting. let rx = cli.start_consuming(); ... // Subscribe topics. subscribe_topics(&cli); println!("Processing requests..."); for msg in rx.iter() { if let Some(msg) = msg { println!("{}", msg); } else if !cli.is_connected() { if try_reconnect(&cli) { println!("Resubscribe topics..."); subscribe_topics(&cli); } else { break; } } } ... } 完整代码 消息发布代码 use std::{ env, process, time::Duration }; extern crate paho_mqtt as mqtt; const DFLT_BROKER:&str = "tcp://broker.emqx.io:1883"; const DFLT_CLIENT:&str = "rust_publish"; const DFLT_TOPICS:&[&str] = &["rust/mqtt", "rust/test"]; // Define the qos. const QOS:i32 = 1; fn main() { let host = env::args().nth(1).unwrap_or_else(|| DFLT_BROKER.to_string() ); // Define the set of options for the create. // Use an ID for a persistent session. let create_opts = mqtt::CreateOptionsBuilder::new() .server_uri(host) .client_id(DFLT_CLIENT.to_string()) .finalize(); // Create a client. let cli = mqtt::Client::new(create_opts).unwrap_or_else(|err| { println!("Error creating the client: {:?}", err); process::exit(1); }); // Define the set of options for the connection. let conn_opts = mqtt::ConnectOptionsBuilder::new() .keep_alive_interval(Duration::from_secs(20)) .clean_session(true) .finalize(); // Connect and wait for it to complete or fail. if let Err(e) = cli.connect(conn_opts) { println!("Unable to connect:\n\t{:?}", e); process::exit(1); } // Create a message and publish it. // Publish message to 'test' and 'hello' topics. for num in 0..5 { let content = "Hello world! ".to_string() + &num.to_string(); let mut msg = mqtt::Message::new(DFLT_TOPICS[0], content.clone(), QOS); if num % 2 == 0 { println!("Publishing messages on the {:?} topic", DFLT_TOPICS[1]); msg = mqtt::Message::new(DFLT_TOPICS[1], content.clone(), QOS); } else { println!("Publishing messages on the {:?} topic", DFLT_TOPICS[0]); } let tok = cli.publish(msg); if let Err(e) = tok { println!("Error sending message: {:?}", e); break; } } // Disconnect from the broker. let tok = cli.disconnect(None); println!("Disconnect from the broker"); tok.unwrap(); } 消息订阅代码 为了提升使用体验,消息订阅做了断开重连的处理,并在重新建立连接后对主题进行重新订阅。 use std::{ env, process, thread, time::Duration }; extern crate paho_mqtt as mqtt; const DFLT_BROKER:&str = "tcp://broker.emqx.io:1883"; const DFLT_CLIENT:&str = "rust_subscribe"; const DFLT_TOPICS:&[&str] = &["rust/mqtt", "rust/test"]; // The qos list that match topics above. const DFLT_QOS:&[i32] = &[0, 1]; // Reconnect to the broker when connection is lost. fn try_reconnect(cli: &mqtt::Client) -> bool { println!("Connection lost. Waiting to retry connection"); for _ in 0..12 { thread::sleep(Duration::from_millis(5000)); if cli.reconnect().is_ok() { println!("Successfully reconnected"); return true; } } println!("Unable to reconnect after several attempts."); false } // Subscribes to multiple topics. fn subscribe_topics(cli: &mqtt::Client) { if let Err(e) = cli.subscribe_many(DFLT_TOPICS, DFLT_QOS) { println!("Error subscribes topics: {:?}", e); process::exit(1); } } fn main() { let host = env::args().nth(1).unwrap_or_else(|| DFLT_BROKER.to_string() ); // Define the set of options for the create. // Use an ID for a persistent session. let create_opts = mqtt::CreateOptionsBuilder::new() .server_uri(host) .client_id(DFLT_CLIENT.to_string()) .finalize(); // Create a client. let mut cli = mqtt::Client::new(create_opts).unwrap_or_else(|err| { println!("Error creating the client: {:?}", err); process::exit(1); }); // Initialize the consumer before connecting. let rx = cli.start_consuming(); // Define the set of options for the connection. let lwt = mqtt::MessageBuilder::new() .topic("test") .payload("Consumer lost connection") .finalize(); let conn_opts = mqtt::ConnectOptionsBuilder::new() .keep_alive_interval(Duration::from_secs(20)) .clean_session(false) .will_message(lwt) .finalize(); // Connect and wait for it to complete or fail. if let Err(e) = cli.connect(conn_opts) { println!("Unable to connect:\n\t{:?}", e); process::exit(1); } // Subscribe topics. subscribe_topics(&cli); println!("Processing requests..."); for msg in rx.iter() { if let Some(msg) = msg { println!("{}", msg); } else if !cli.is_connected() { if try_reconnect(&cli) { println!("Resubscribe topics..."); subscribe_topics(&cli); } else { break; } } } // If still connected, then disconnect now. if cli.is_connected() { println!("Disconnecting"); cli.unsubscribe_many(DFLT_TOPICS).unwrap(); cli.disconnect(None).unwrap(); } println!("Exiting"); } 运行与测试 编译二进制文件 执行以下命令,会在 mqtt-example/target/debug 目录下生成消息订阅、发布对应的 sub、pub 二进制文件。 cargo build 消息订阅 执行 sub 二进制文件,等待消费发布。 消息发布 执行 pub 二进制文件,可以看到分别往 rust/test 、rust/mqtt 这两个主题发布了消息。 同时在消息订阅中可看到发布的消息 至此,我们完成了使用 paho-mqtt 客户端连接到 公共 MQTT 服务器,并实现了测试客户端与 MQTT 服务器的连接、消息发布和订阅。 8. 结论结合Rust的高性能特性和MQTT的轻量级通信,物联网应用可以实现更快、更可靠的消息传输和处理。这不仅提高了物联网设备的性能,还为开发者带来了更为便捷的开发体验。 总之,Rust与MQTT结合为物联网通信带来了一场革命。利用这些技术,开发者可以设计出响应迅速、安全并且低成本的物联网应用。 --- ### 318. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 PHP是一种广泛使用的开放源代码脚本语言,专门针对Web开发而设计,并可嵌入到HTML中直接执行。起初,PHP是代表“Personal Home Page”的缩写,但现在它是“PHP: Hypertext Preprocessor”的递归缩写。PHP支持各种数据库、协议和具有丰富的内置函数库。运行于大多数服务器、操作系统平台,并且与其他流行的数据库完美集成。随着时间的推移,许多框架如Laravel、Symfony和CodeIgniter为PHP开发提供了极大的便利,使其在现代Web开发中继续保持其核心地位。 MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息传输协议,专为低带宽和不稳定的网络环境设计。起初为监控远程传感器和设备而开发,现在已广泛应用于物联网(IoT)领域。它允许设备在最小的代码和电源消耗下进行有效通信,使其成为联网设备的理想选择。随着物联网的发展,MQTT已被多家大型技术公司所采纳,并且逐渐成为物联网通信的事实标准。其核心概念包括Broker(消息中心)和客户端,通过Topic(主题)实现消息的分发和接收。 本篇文章深入探讨了如何在PHP项目中通过php-mqtt/client库,有效地建立MQTT客户端与MQTT服务器的连接,并实现订阅、取消订阅以及消息的收发功能。 选择MQTT客户端库 当谈及PHP中的MQTT客户端库,php-mqtt/client无疑是composer平台上最受欢迎的选择,其下载量领先于其他库。对于感兴趣的开发者,Packagist的Search MQTT功能提供了更多的客户端库选择。 为了更深入地了解如何使用php-mqtt/client,您可以参考Packagist上的php-mqtt/client官方文档。 PHP中的MQTT通信 值得注意的是,MQTT通信并不属于传统的HTTP体系。由于PHP的某些特性限制,采用专为网络通信设计的PHP拓展,如Swoole或Workerman,会为开发者带来更为流畅的体验。在这里,我们不再深入这些拓展的具体使用方法,但以下是一些与MQTT相关的客户端库: workerman/mqtt: 一个基于workerman的PHP异步MQTT客户端。 simps/mqtt: 专为PHP设计的MQTT协议解析和协程客户端。 项目准备 确认 PHP 版本 本项目使用 7.4.21 进行开发测试,读者可用如下命令确认 PHP 的版本。 php --version PHP 7.4.21 (cli) (built: Jul 12 2021 11:52:30) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.21, Copyright (c), by Zend Technologies 使用 Composer 安装 php-mqtt/client 客户端 Composer 是 PHP 的一个依赖管理工具,它能管理你的 PHP 项目所需要的所有依赖关系。 composer require php-mqtt/client 准备 MQTT Broker 在继续之前,您需要一个 MQTT Broker 进行通信和测试。你可以通过一下方式获取 MQTT Broker: 私有部署EMQX 是应用于物联网、工业物联网和车联网的最具可扩展性的开源 MQTT Broker。您可以通过以下 Docker 命令来安装 EMQX: docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx 本文将使用 EMQX 提供的 免费公共 MQTT 服务器,该服务基于 EMQX 的 MQTT 物联网云平台 创建。服务器接入信息如下: Broker: broker-cn.emqx.io TCP Port: 1883 SSL/TLS Port: 8883 PHP MQTT 使用指南 导入 composer autoload 文件和 php-mqtt/client require('vendor/autoload.php'); use \PhpMqtt\Client\MqttClient; 设置 MQTT Broker 连接参数 设置 MQTT Broker 连接地址,端口,客户端 ID,用户名以及 topic,这里我们调用 PHP rand 函数随机生成 MQTT 客户端 ID,避免与其他客户端 ID 重复。 $server = 'broker-cn.emqx.io'; $port = 1883; $clientId = rand(5, 15); $username = 'emqx_user'; $password = null; $clean_session = false; 使用上述的参数进行连接,通过 ConnectionSettings 设置连接参数: $connectionSettings = new ConnectionSettings(); $connectionSettings ->setUsername($username) ->setPassword(null) ->setKeepAliveInterval(60) // Last Will 设置 ->setLastWillTopic('emqx/test/last-will') ->setLastWillMessage('client disconnect') ->setLastWillQualityOfService(1); 订阅消息 编写代码订阅 emqx/test 主题,并为该订阅配置回调函数以处理接收到的消息,此处我们将订阅得到的主题和消息打印出来: // 订阅 $mqtt->subscribe('emqx/test', function ($topic, $message) { printf("Received message on topic [%s]: %s\n", $topic, $message); }, 0); 发布消息 构造一个 payload,调用 publish 函数向 emqx/test 主题发布消息,发布完成之后客户端需要进入轮询状态,处理传入的消息和重发队列: for ($i = 0; $i< 10; $i++) { $payload = array( 'protocol' => 'tcp', 'date' => date('Y-m-d H:i:s'), 'url' => 'https://github.com/emqx/MQTT-Client-Examples' ); $mqtt->publish( // topic 'emqx/test', // payload json_encode($payload), // qos 0, // retain true ); printf("msg $i send\n"); sleep(1); } // 客户端轮询以处理传入消息和重发队列 $mqtt->loop(true); // 断开 MQTT 连接 // $client->disconnect(); 完整代码 服务器连接、消息发布与接收代码。 <?php require('vendor/autoload.php'); use \PhpMqtt\Client\MqttClient; use \PhpMqtt\Client\ConnectionSettings; $server = 'broker.emqx.io'; $port = 1883; $clientId = rand(5, 15); $username = 'emqx_user'; $password = null; $clean_session = false; $connectionSettings = new ConnectionSettings(); $connectionSettings ->setUsername($username) ->setPassword(null) ->setKeepAliveInterval(60) // Last Will 设置 ->setLastWillTopic('emqx/test/last-will') ->setLastWillMessage('client disconnect') ->setLastWillQualityOfService(1); $mqtt = new MqttClient($server, $port, $clientId); $mqtt->connect($connectionSettings, $clean_session); printf("client connected\n"); $mqtt->subscribe('emqx/test', function ($topic, $message) { printf("Received message on topic [%s]: %s\n", $topic, $message); }, 0); for ($i = 0; $i< 10; $i++) { $payload = array( 'protocol' => 'tcp', 'date' => date('Y-m-d H:i:s'), 'url' => 'https://github.com/emqx/MQTT-Client-Examples' ); $mqtt->publish( // topic 'emqx/test', // payload json_encode($payload), // qos 0, // retain true ); printf("msg $i send\n"); sleep(1); } $mqtt->loop(true); // 断开 MQTT 连接 // $client->disconnect(); 测试 运行 MQTT 消息发布代码,我们将看到客户端已经成功连接,且消息已经逐条发布并接收成功: php pubsub_tcp.php 5. 总结 整合MQTT到PHP项目可能初看有些复杂,但随着上述指南的帮助,流程将变得明确和简单。选择适当的客户端库、理解PHP与MQTT的通信特性,再结合实战经验,即可轻松实现MQTT在PHP中的应用。 --- ### 319. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网(IoT)正在改变全球的工作和生活方式。为了实现这种互联和通信,我们需要强大、灵活且可靠的工具。本文将探索如何结合Python的强大功能和MQTT的高效通信,为物联网项目提供无缝解决方案。 为何选择Python与MQTT? Python,这一简洁、高效的编程语言,由于其出色的库支持和跨平台特性,已经成为了数据科学、网络开发和自动化的首选。它简单的语法和代码可读性使得开发过程更为迅速和直观。 另一方面,MQTT是一种轻量级的发布/订阅模式的通信协议,特别适用于低带宽、高延迟或不稳定的网络环境。正因为其高效和低耗,MQTT已成为物联网通信的标准。 步骤详解:构建基于Python的MQTT物联网应用 1. 环境准备 确保已安装Python 3.6或更高版本。你可以使用以下命令确认: python3 --version 2. 安装MQTT库 我们将使用paho-mqtt,这是一个流行的Python MQTT客户端库。 pip3 install -i https://pypi.doubanio.com/simple paho-mqtt 3. 连接到MQTT服务器 在此,我们选择使用EMQX提供的免费MQTT公共服务器,但同样可以选择其他任何MQTT broker。 Broker: broker.emqx.io TCP Port: 1883 Websocket Port: 8083 导入 Paho MQTT客户端 from paho.mqtt import client as mqtt_client 设置 MQTT Broker 连接参数 设置 MQTT Broker 连接地址,端口以及 topic,同时我们调用 Python random.randint 函数随机生成 MQTT 客户端 id。 broker = 'broker.emqx.io' port = 1883 topic = "/python/mqtt" client_id = f'python-mqtt-{random.randint(0, 1000)}' 编写 MQTT 连接函数 编写连接回调函数 on_connect,该函数将在客户端连接后被调用,在该函数中可以依据 rc 来判断客户端是否连接成功。通常同时我们将创建一个 MQTT 客户端,该客户端将连接到 broker.emqx.io。 def connect_mqtt(): def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) # Set Connecting Client ID client = mqtt_client.Client(client_id) client.on_connect = on_connect client.connect(broker, port) return client 发布消息 首先定义一个 while 循环语句,在循环中我们将设置每秒调用 MQTT 客户端 publish 函数向 /python/mqtt 主题发送消息。 def publish(client): msg_count = 0 while True: time.sleep(1) msg = f"messages: {msg_count}" result = client.publish(topic, msg) # result: [0, 1] status = result[0] if status == 0: print(f"Send `{msg}` to topic `{topic}`") else: print(f"Failed to send message to topic {topic}") msg_count += 1 订阅消息 编写消息回调函数 on_message,该函数将在客户端从 MQTT Broker 收到消息后被调用,在该函数中我们将打印出订阅的 topic 名称以及接收到的消息内容。 def subscribe(client: mqtt_client): def on_message(client, userdata, msg): print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic") client.subscribe(topic) client.on_message = on_message 完整代码 消息发布代码 # python 3.6 import random import time from paho.mqtt import client as mqtt_client broker = 'broker.emqx.io' port = 1883 topic = "/python/mqtt" # generate client ID with pub prefix randomly client_id = f'python-mqtt-{random.randint(0, 1000)}' def connect_mqtt(): def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) client = mqtt_client.Client(client_id) client.on_connect = on_connect client.connect(broker, port) return client def publish(client): msg_count = 0 while True: time.sleep(1) msg = f"messages: {msg_count}" result = client.publish(topic, msg) # result: [0, 1] status = result[0] if status == 0: print(f"Send `{msg}` to topic `{topic}`") else: print(f"Failed to send message to topic {topic}") msg_count += 1 def run(): client = connect_mqtt() client.loop_start() publish(client) if __name__ == '__main__': run() 消息订阅代码 # python3.6 import random from paho.mqtt import client as mqtt_client broker = 'broker.emqx.io' port = 1883 topic = "/python/mqtt" # generate client ID with pub prefix randomly client_id = f'python-mqtt-{random.randint(0, 100)}' def connect_mqtt() -> mqtt_client: def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) client = mqtt_client.Client(client_id) client.on_connect = on_connect client.connect(broker, port) return client def subscribe(client: mqtt_client): def on_message(client, userdata, msg): print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic") client.subscribe(topic) client.on_message = on_message def run(): client = connect_mqtt() subscribe(client) client.loop_forever() if __name__ == '__main__': run() 测试 消息发布 运行 MQTT 消息发布代码,我们将看到客户端连接成功,并且成功将消息发布。 python3 pub.py 消息订阅 运行 MQTT 消息订阅代码,我们将看到客户端连接成功,并且成功接收到发布的消息。 python3 sub.py 扩展你的IoT应用 数据安全:使用SSL/TLS保证数据的安全传输。 数据存储:结合数据库技术,例如SQLite、MySQL或MongoDB,持久化存储设备数据。 实时分析:利用Python的强大数据分析库,如pandas、NumPy和matplotlib,对接收到的数据进行实时处理和可视化。 设备管理:考虑添加一个设备管理系统,以便跟踪、更新和维护所有连接的设备。 总结 物联网的未来取决于我们如何有效地处理海量的设备数据。Python和MQTT为我们提供了一个高效、简洁且可靠的方式来捕获、分析和共享这些数据。无论是智能家居、工业自动化还是智慧城市,结合Python和MQTT的IoT解决方案都将开创新的可能性和机会。 --- ### 320. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Node.js 与 MQTT:构建下一代物联网应用 在今天的数字化时代,物联网应用正迅速成为前沿技术。而在这方面,Node.js 和 MQTT 的组合无疑为开发者提供了一种高效、灵活的方式来构建应用。在这篇文章中,我们将详细探讨如何在 Node.js 中利用 MQTT 来开发物联网应用。 1. 理解 Node.js 和 MQTT Node.js 不仅仅是一种服务端的 JavaScript 运行环境,它更是开发高性能、实时应用的绝佳选择。MQTT 则为我们提供了一个轻量、高效的消息通讯协议,特别适用于网络带宽有限或不稳定的环境中。 2. MQTT.js:构建 Node.js 中的 MQTT 应用 MQTT.js 是 Node.js 中最流行的 MQTT 客户端库,它为开发者提供了一个简单易用的 API 来开发 MQTT 客户端应用。 3. 快速入门:Node.js MQTT 客户端 首先,确保你的系统已经安装了 Node.js v14.14.0 或更高版本,接下来,我们将通过几个简单的步骤来搭建你的第一个 Node.js MQTT 客户端。 本项目使用 Node.js v14.14.0 进行开发和测试,读者可用如下命令确认 Node.js 的版本 node --version v14.14.0 使用 npm 安装 MQTT.js 客户端库 # 新建项目 npm init -y # 安装依赖 npm install mqtt --save 完成后我们在当前目录下新建一个 index.js 文件作为项目的入口文件,在该文件中来实现 MQTT 连接测试的完整逻辑。 Node.js MQTT 使用 连接 MQTT 服务器 本文将使用 EMQX 提供的 免费公共 MQTT 服务器,该服务基于 EMQX 的 MQTT 物联网云平台 创建。服务器接入信息如下: Broker: broker.emqx.io(国内可以使用 broker-cn.emqx.io) TCP Port: 1883 SSL/TLS Port: 8883 引入 MQTT.js 客户端库 注意:在 Node.js 环境中,导入依赖模块请使用 commonjs 规范 const mqtt = require('mqtt') 设置 MQTT Broker 的连接参数 设置 MQTT Broker 连接地址,端口以及 topic,这里我们使用 JavaScript 中的生成随机数的函数来生成客户端 ID。 const host = 'broker.emqx.io' const port = '1883' const clientId = `mqtt_${Math.random().toString(16).slice(3)}` 编写 MQTT 连接函数 我们使用刚才设置的连接参数来进行连接,连接的 URL 通过上面定义的 host、port 端口来进行拼接。然后调用 mqtt 模块内置的 connect 函数,连接成功后返回一个 Client 实例。 const connectUrl = `mqtt://${host}:${port}` const client = mqtt.connect(connectUrl, { clientId, clean: true, connectTimeout: 4000, username: 'emqx', password: 'public', reconnectPeriod: 1000, }) 订阅主题 使用返回的 Client 实例的 on 方法来监听连接成功状态,并在连接成功后的回调函数中订阅 topic。此时我们连接成功后调用 Client 实例的 subscribe 方法订阅 /nodejs/mqtt 主题。 const topic = '/nodejs/mqtt' client.on('connect', () => { console.log('Connected') client.subscribe([topic], () => { console.log(`Subscribe to topic '${topic}'`) }) }) 订阅主题成功后,我们再使用 on 方法来监听接收消息的方法,当接受到消息时,我们可以在该方法的回调函数中获取到 topic 和 message 消息。 注意:回调函数中的 message 是 Buffer 类型,需要使用 toString 方法将其转化为字符串 client.on('message', (topic, payload) => { console.log('Received Message:', topic, payload.toString()) }) 消息发布 完成上述的订阅主题和消息监听后,我们再来编写一个发布消息的方法。 注意:消息发布需要在 MQTT 连接成功以后,因此这里我们写到 Connect 成功的回调函数里 client.on('connect', () => { client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false }, (error) => { if (error) { console.error(error) } }) }) 完整代码 服务器连接、主题订阅、消息发布与接收的代码。 const mqtt = require('mqtt') const host = 'broker.emqx.io' const port = '1883' const clientId = `mqtt_${Math.random().toString(16).slice(3)}` const connectUrl = `mqtt://${host}:${port}` const client = mqtt.connect(connectUrl, { clientId, clean: true, connectTimeout: 4000, username: 'emqx', password: 'public', reconnectPeriod: 1000, }) const topic = '/nodejs/mqtt' client.on('connect', () => { console.log('Connected') client.subscribe([topic], () => { console.log(`Subscribe to topic '${topic}'`) }) client.publish(topic, 'nodejs mqtt test', { qos: 0, retain: false }, (error) => { if (error) { console.error(error) } }) }) client.on('message', (topic, payload) => { console.log('Received Message:', topic, payload.toString()) }) 项目完整代码请见:https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-Node.js 测试 我们在 package.json 文件中的脚本字段中添加一行启动脚本。 "scripts": { "start": "node index.js" } 然后就可以简单使用 npm start 来运行项目。 npm start 运行后我们可以看到控制的输出信息如下: 4. 安全性考虑 当涉及到物联网应用时,安全性是首要考虑的问题。确保使用 TLS/SSL 加密来保障你的数据安全。 5. 扩展阅读:更多 Node.js 与 MQTT 的强大特性 除了基本功能外,Node.js 和 MQTT 还有许多强大的特性等待你去发掘,如 QoS、消息保留、遗嘱消息等。 6. 结语 随着物联网应用的持续发展,Node.js 结合 MQTT 为开发者提供了一个强大、灵活且高效的工具来满足日益增长的需求。而你,作为一名开发者,现在已经掌握了使用这两个工具构建下一代物联网应用的知识。不要等待,开始你的 MQTT 之旅吧! 本文旨在为读者提供实际的价值,帮助开发者快速、高效地开发物联网应用。感谢你的阅读,期待你的反馈和建议。 --- ### 321. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Golang与MQTT:轻松构建物联网应用 在今天的数字时代,物联网和实时消息传递变得越来越重要。Golang,由Google推出的革命性编程语言,与MQTT,一个高效的物联网消息传输协议,共同为开发者带来了无数的机会。这篇文章将带你走进Golang和MQTT的世界,详细介绍如何实现二者的融合与应用。 1. 为什么选择Golang? Golang以其简洁、强大和高效的特性而脱颖而出,特别适合处理并发任务,是物联网项目的理想选择。 2. MQTT: 物联网的动力 MQTT的发布/订阅模式使其成为物联网领域的翘楚。它能够为联网设备提供实时、可靠的消息服务,广泛应用于各个行业。 3. 开启Golang与MQTT的旅程 我们将使用paho.mqtt.golang库,这是一个为Golang设计的高效MQTT客户端。 3.1 项目准备 确保你的系统安装了go1.13.12或更高版本。安装paho.mqtt.golang: go get github.com/eclipse/paho.mqtt.golang 3.2 连接到MQTT broker 我们选择EMQX提供的公共MQTT服务器,地址为broker.emqx.io。 package main import ( "fmt" mqtt "github.com/eclipse/paho.mqtt.golang" "time" ) var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { fmt.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic()) } var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) { fmt.Println("Connected") } var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) { fmt.Printf("Connect lost: %v", err) } func main() { var broker = "broker.emqx.io" var port = 1883 opts := mqtt.NewClientOptions() opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port)) opts.SetClientID("go_mqtt_client") opts.SetUsername("emqx") opts.SetPassword("public") opts.SetDefaultPublishHandler(messagePubHandler) opts.OnConnect = connectHandler opts.OnConnectionLost = connectLostHandler client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { panic(token.Error()) } } ClientOptions:用于设置 broker,端口,客户端 id ,用户名密码等选项 messagePubHandler:全局 MQTT pub 消息处理 connectHandler:连接的回调 connectLostHandler:连接丢失的回调 如果想使用 TLS 连接,可以如下设置: func NewTlsConfig() *tls.Config { certpool := x509.NewCertPool() ca, err := ioutil.ReadFile("ca.pem") if err != nil { log.Fatalln(err.Error()) } certpool.AppendCertsFromPEM(ca) // Import client certificate/key pair clientKeyPair, err := tls.LoadX509KeyPair("client-crt.pem", "client-key.pem") if err != nil { panic(err) } return &tls.Config{ RootCAs: certpool, ClientAuth: tls.NoClientCert, ClientCAs: nil, InsecureSkipVerify: true, Certificates: []tls.Certificate{clientKeyPair}, } } 如果不设置客户端证书,可以如下设置: func NewTlsConfig() *tls.Config { certpool := x509.NewCertPool() ca, err := ioutil.ReadFile("ca.pem") if err != nil { log.Fatalln(err.Error()) } certpool.AppendCertsFromPEM(ca) return &tls.Config{ RootCAs: certpool, } } 然后设置 TLS var broker = "broker.emqx.io" var port = 8883 opts := mqtt.NewClientOptions() opts.AddBroker(fmt.Sprintf("ssl://%s:%d", broker, port)) tlsConfig := NewTlsConfig() opts.SetTLSConfig(tlsConfig) // other options 3.3 MQTT消息发布与订阅 Golang与MQTT的结合使得消息发布和订阅变得轻而易举。 订阅 func sub(client mqtt.Client) { topic := "topic/test" token := client.Subscribe(topic, 1, nil) token.Wait() fmt.Printf("Subscribed to topic %s", topic) } 发布 func publish(client mqtt.Client) { num := 10 for i := 0; i < num; i++ { text := fmt.Sprintf("Message %d", i) token := client.Publish("topic/test", 0, false, text) token.Wait() time.Sleep(time.Second) } } 4. 深入理解:连接回调与安全性 当与broker的连接建立或断开时,执行相应的回调函数可以增加程序的健壮性。同时,为了数据安全,建议使用TLS连接。 5. 实战测试 通过以下代码,我们可以一目了然地了解如何在Golang中实现MQTT客户端的完整流程。 package main import ( "fmt" mqtt "github.com/eclipse/paho.mqtt.golang" "log" "time" ) var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { fmt.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic()) } var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) { fmt.Println("Connected") } var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) { fmt.Printf("Connect lost: %v", err) } func main() { var broker = "broker.emqx.io" var port = 1883 opts := mqtt.NewClientOptions() opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port)) opts.SetClientID("go_mqtt_client") opts.SetUsername("emqx") opts.SetPassword("public") opts.SetDefaultPublishHandler(messagePubHandler) opts.OnConnect = connectHandler opts.OnConnectionLost = connectLostHandler client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { panic(token.Error()) } sub(client) publish(client) client.Disconnect(250) } func publish(client mqtt.Client) { num := 10 for i := 0; i < num; i++ { text := fmt.Sprintf("Message %d", i) token := client.Publish("topic/test", 0, false, text) token.Wait() time.Sleep(time.Second) } } func sub(client mqtt.Client) { topic := "topic/test" token := client.Subscribe(topic, 1, nil) token.Wait() fmt.Printf("Subscribed to topic: %s", topic) } 运行代码,可以看到 MQTT 连接、订阅成功,并能成功收到订阅 topic 的消息 6. 结语 结合Golang的强大性能和MQTT的轻量级特点,为物联网应用开发提供了一个强大的解决方案。通过这篇文章,您应该已经掌握了如何使用Golang构建MQTT应用的基本知识,期待您在实际应用中创造更多的可能性。 本文旨在为读者提供真实、有价值的内容,如有任何建议或反馈,请随时与我们联系。 --- ### 322. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 Java中的MQTT:深入实践与探索指南 随着物联网的快速发展,需要一个轻量级、高效和可靠的消息传递机制,而MQTT(Message Queuing Telemetry Transport)正好满足了这些需求。这篇文章将为您解开在Java中使用MQTT的奥秘,确保您能够快速入门并深入实践。 1. MQTT简介 MQTT是一种发布/订阅模式的消息传输协议,尤其适合低功耗设备和不稳定网络环境。它可以轻松处理设备间的消息通信,使物联网应用更为简洁。 2. 选择Java作为MQTT客户端的优势 Java是一个跨平台、稳定和安全的编程语言。其丰富的库和社区资源使得开发MQTT应用变得相对简单。 3. 开始之前 确保您的系统上已经安装了JDK 1.8或更高版本,并且配置了合适的Java环境。 4. 选择合适的库:Eclipse Paho Eclipse Paho Java Client是一个非常受欢迎的库,支持MQTT协议。为了在你的Maven项目中使用它,请添加以下依赖: <dependencies> <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.5</version> </dependency> </dependencies> 5. 构建MQTT客户端 连接到MQTT broker 首先,我们需要连接到一个MQTT broker。为了简化,这里使用一个公开的broker:broker.emqx.io。 String broker = "tcp://broker.emqx.io:1883"; // TLS/SSL // String broker = "ssl://broker.emqx.io:8883"; String username = "emqx"; String password = "public"; String clientid = "publish_client"; 然后创建 MQTT 客户端并连接。 MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); client.connect(options); 说明 MqttClient: 同步调用客户端,使用阻塞方法通信。 MqttClientPersistence: 代表一个持久的数据存储,用于在传输过程中存储出站和入站的信息,使其能够传递到指定的 QoS。 MqttConnectOptions: 连接选项,用于指定连接的参数,下面列举一些常见的方法。 setUserName: 设置用户名 setPassword: 设置密码 setCleanSession: 设置是否清除会话 setKeepAliveInterval: 设置心跳间隔 setConnectionTimeout: 设置连接超时时间 setAutomaticReconnect: 设置是否自动重连 6. 强化安全性:SSL/TLS连接 保证数据安全是非常关键的,建议使用SSL/TLS来连接到MQTT broker。要实现这一点,你需要确保broker支持SSL,并在客户端配置适当的证书和加密设置。 TLS/SSL 连接 如果要使用自签名证书进行 TLS/SSL 连接,需添加 bcpkix-jdk15on 到 pom.xml 文件。 <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.70</version> </dependency> 然后使用如下代码创建 SSLUtils.java 文件。 package io.emqx.mqtt; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMParser; import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileReader; import java.security.KeyPair; import java.security.KeyStore; import java.security.Security; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; public class SSLUtils { public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile, final String password) throws Exception { Security.addProvider(new BouncyCastleProvider()); // load CA certificate X509Certificate caCert = null; FileInputStream fis = new FileInputStream(caCrtFile); BufferedInputStream bis = new BufferedInputStream(fis); CertificateFactory cf = CertificateFactory.getInstance("X.509"); while (bis.available() > 0) { caCert = (X509Certificate) cf.generateCertificate(bis); } // load client certificate bis = new BufferedInputStream(new FileInputStream(crtFile)); X509Certificate cert = null; while (bis.available() > 0) { cert = (X509Certificate) cf.generateCertificate(bis); } // load client private key PEMParser pemParser = new PEMParser(new FileReader(keyFile)); Object object = pemParser.readObject(); JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); KeyPair key = converter.getKeyPair((PEMKeyPair) object); pemParser.close(); // CA certificate is used to authenticate server KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType()); caKs.load(null, null); caKs.setCertificateEntry("ca-certificate", caCert); TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); tmf.init(caKs); // client key and certificates are sent to server so it can authenticate KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(null, null); ks.setCertificateEntry("certificate", cert); ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert}); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory .getDefaultAlgorithm()); kmf.init(ks, password.toCharArray()); // finally, create SSL socket factory SSLContext context = SSLContext.getInstance("TLSv1.2"); context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); return context.getSocketFactory(); } } 参照如下设置 options。 // 设置 SSL/TLS 连接地址 String broker = "ssl://broker.emqx.io:8883"; // 设置 socket factory String caFilePath = "/cacert.pem"; String clientCrtFilePath = "/client.pem"; String clientKeyFilePath = "/client.key"; SSLSocketFactory socketFactory = getSocketFactory(caFilePath, clientCrtFilePath, clientKeyFilePath, ""); options.setSocketFactory(socketFactory); 发布 MQTT 消息 创建一个发布客户端类 PublishSample,该类将发布一条 Hello MQTT 消息至主题 mqtt/test。 package io.emqx.mqtt; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; public class PublishSample { public static void main(String[] args) { String broker = "tcp://broker.emqx.io:1883"; String topic = "mqtt/test"; String username = "emqx"; String password = "public"; String clientid = "publish_client"; String content = "Hello MQTT"; int qos = 0; try { MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); // 连接参数 MqttConnectOptions options = new MqttConnectOptions(); // 设置用户名和密码 options.setUserName(username); options.setPassword(password.toCharArray()); options.setConnectionTimeout(60); options.setKeepAliveInterval(60); // 连接 client.connect(options); // 创建消息并设置 QoS MqttMessage message = new MqttMessage(content.getBytes()); message.setQos(qos); // 发布消息 client.publish(topic, message); System.out.println("Message published"); System.out.println("topic: " + topic); System.out.println("message content: " + content); // 关闭连接 client.disconnect(); // 关闭客户端 client.close(); } catch (MqttException e) { throw new RuntimeException(e); } } } 订阅 MQTT 主题 创建一个订阅客户端类 SubscribeSample,该类将订阅主题 mqtt/test。 package io.emqx.mqtt; import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; public class SubscribeSample { public static void main(String[] args) { String broker = "tcp://broker.emqx.io:1883"; String topic = "mqtt/test"; String username = "emqx"; String password = "public"; String clientid = "subscribe_client"; int qos = 0; try { MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); // 连接参数 MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); options.setConnectionTimeout(60); options.setKeepAliveInterval(60); // 设置回调 client.setCallback(new MqttCallback() { public void connectionLost(Throwable cause) { System.out.println("connectionLost: " + cause.getMessage()); } public void messageArrived(String topic, MqttMessage message) { System.out.println("topic: " + topic); System.out.println("Qos: " + message.getQos()); System.out.println("message content: " + new String(message.getPayload())); } public void deliveryComplete(IMqttDeliveryToken token) { System.out.println("deliveryComplete---------" + token.isComplete()); } }); client.connect(options); client.subscribe(topic, qos); } catch (Exception e) { e.printStackTrace(); } } } MqttCallback 说明: connectionLost(Throwable cause): 连接丢失时被调用 messageArrived(String topic, MqttMessage message): 接收到消息时被调用 deliveryComplete(IMqttDeliveryToken token): 消息发送完成时被调用 测试 接下来运行 SubscribeSample,订阅 mqtt/test 主题。 然后运行 PublishSample,发布消息到 mqtt/test 主题。 我们将会看到发布端成功发布消息,同时订阅端接收到消息。 8. 总结 MQTT在Java中的实现变得更为简单,感谢丰富的库和工具。通过本指南,您应该能够构建一个基本的MQTT客户端,并对其进行扩展以满足更复杂的需求。 希望这篇文章为您提供了宝贵的知识和实践指南! --- ### 323. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT简介 MQTT(Message Queuing Telemetry Transport)是一种轻量级的通信协议,设计用于在低带宽和不稳定的网络环境中传输消息。它最初由IBM开发,用于连接远程设备和传感器到网络,并支持发布/订阅模型的消息通信。MQTT被广泛用于物联网(IoT)领域,其中大量的设备需要进行实时通信和数据交换。它采用了一种发布/订阅(publish/subscribe)模型,其中消息的发送者(发布者)将消息发布到特定的主题(topic),而订阅者可以选择性地订阅感兴趣的主题,以接收相应的消息。 MQTT特点 以下是MQTT的一些关键特点:轻量级:MQTT的设计非常轻量,协议头部非常小,传输的数据量很小,适用于带宽有限的网络环境,如低速、高延迟或不稳定的网络。简单:MQTT的协议规范相对简单,易于实现和部署。它定义了少量的消息类型和协议操作,使得开发人员可以快速上手。异步通信:MQTT使用异步通信模式,发布者发送消息后,不需要等待接收者的响应,可以继续执行其他操作。这种异步通信模式适合在资源有限的设备和网络中工作。可靠性:MQTT支持三种不同的消息传递质量(QoS)级别:QoS 0(至多一次),QoS 1(至少一次)和QoS 2(只有一次)。这使得可以根据应用程序的要求选择适当的消息交付保证级别。网络状况适应性:MQTT可以适应不稳定的网络状况,如网络中断、重连等。它具有断开连接后自动重连的机制,可以确保消息的可靠传输。 订阅和发布模型 Publisher(发布者):发布者是消息的发送者,它将消息发布到特定的主题(topic)上。可以有一个或多个发布者。Subscriber(订阅者):订阅者是对消息感兴趣的实体,它选择性地订阅一个或多个主题。一旦订阅了主题,它就会接收到相应的消息。MQTT Broker(MQTT代理):MQTT代理是中间件,负责接收发布者发送的消息,并将其路由到对应的订阅者。它维护着主题和订阅关系的注册表,并确保消息的可靠传递。 工作流程如下: 发布者将消息发布到特定的主题上。MQTT代理接收到消息后,根据订阅者的注册信息,将消息路由到对应的订阅者。订阅者接收到发布者发布的消息,并进行相应的处理。通过发布/订阅模型,MQTT允许实现解耦和灵活性,发布者和订阅者之间不需要直接的点对点连接,而是通过MQTT代理进行中转和路由。这种模型非常适合在物联网中进行大规模设备间的通信和数据交换。 MQTT QoS MQTT(Message Queuing Telemetry Transport)协议支持三种不同的QoS(Quality of Service)级别,用于控制消息的可靠性和传输保证。以下是MQTT的三个QoS级别: QoS 0(至多一次): 在QoS 0级别下,消息以“至多一次”传输,没有确认机制。消息被发布后,发布者不会接收到关于消息是否成功传输或交付的确认。MQTT代理会尽最大努力将消息传输给订阅者,但可能会出现消息丢失或重复的情况。此级别适用于对消息传输的可靠性要求不高的场景,如传感器数据的临时更新等。 QoS 1(至少一次): 在QoS 1级别下,消息以“至少一次”传输,确保至少传输一次。发布者发送消息后,会等待MQTT代理发送确认消息(PUBACK)来确认消息的接收。如果发布者没有收到确认消息,它会再次发送相同的消息,直到收到确认为止。MQTT代理会确保消息至少传输一次给订阅者,但可能会出现重复传输的情况。此级别适用于对消息传输的可靠性要求较高的场景,如控制指令的传递。 QoS 2(只有一次): 在QoS 2级别下,消息以“只有一次”传输,确保仅传输一次。发布者发送消息后,会等待MQTT代理发送两个确认消息(PUBREC和PUBCOMP)来确认消息的接收和完成。MQTT代理会确保消息仅传输一次给订阅者,没有重复传输的情况。此级别提供了最高的消息传输可靠性,但也伴随着更高的网络开销。此级别适用于对消息传输的可靠性要求非常高的场景,如金融交易或严格的数据同步。选择合适的QoS级别取决于应用程序对消息传输可靠性和网络开销的要求。更高的QoS级别提供了更可靠的传输,但同时也增加了网络开销。因此,需要根据具体场景的需求来选择适当的级别。 OpenWrt中使用mosquitto 插件安装 默认是没有包含mosquitto客户端和broker的,我们可以手动安装相关插件,为了测试我们需要安装broker和client 首先更新openwrt软件源 opkg update 然后调用以下命令分别安装mosquitto broker和client,这里我们选用nossl版本,也就是不需要ssl加密,方便测试 opkg install mosquitto-nossl opkg install mosquitto-client-nossl mosquitto服务 安装完成后就可以使用broker和client了,首先我们需要启动mosquitto broker服务, mosquitto broker服务配置文件在/etc/mosquitto/目录中,我们可以修改服务器相关信息,比如监听端口号、接口、ip地址等。 root@OpenWrt:~# ls /etc/mosquitto/mosquitto.conf /etc/mosquitto/mosquitto.conf root@OpenWrt:~# mosquitto客户端 mosquitto客户端包含sub和pub两部分,分别用于订阅和发布 订阅主题: mosquitto_sub -h <MQTT Broker IP> -p <MQTT Broker Port> -t <Topic> 其中,是MQTT Broker的IP地址,是MQTT Broker的端口号,是要订阅的主题名称。示例: mosquitto_sub -h 192.168.1.1 -p 1883 -t test/topic 发布主题: mosquitto_pub -h <MQTT Broker IP> -p <MQTT Broker Port> -t <Topic> -m <Message> 其中,是MQTT Broker的IP地址,是MQTT Broker的端口号,是要发布的主题名称,是要发布的消息内容。示例: mosquitto_pub -h 192.168.1.1 -p 1883 -t test/topic -m "Hello, MQTT!" 运行结果: 由于订阅和发布客户端都在本地,ip使用localhost地址127.0.0.1 root@OpenWrt:~# mosquitto_sub -h 127.0.0.1 -p 1883 -t test/topic & root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t test/topic -m "hello MQTT." root@OpenWrt:~# hello MQTT. 在订阅主题时,我们还可以使用通配符,最常用就是通配符"#",通过"#"可以匹配多级topic 比如订阅了主题"test/#",则可以收到"test/"开头的所有topic,比如"test/topic1"、"test/hello"等 以下实例中分别订阅了"test/#"和"test/topic1",当发布"test/topic1"消息时,二者都可以收到,而发布"test/topic2"时只有一个可以收到。 除了通配符"#"之外,还有"$"、"+"等通配符,不在这里详解。使用云端公共broker测试 emqx提供了公共免费的broker供开发者测试,注意不要在生产环境使用,仅供测试 我们可以准备两台不同的设备,都连接broker.emqx.io,这两台设备可以在不同区域,通过公网broker可以轻松实现两台设备通信。●客户端1 客户端1订阅openwrt/topic消息 mosquitto_sub -h broker.emqx.io -p 1883 -i client_001 -t openwrt/topic ●客户端2 发送一条消息到主题openwrt/topic,这样客户端1就可以收到该消息 mosquitto_pub -h broker.emqx.io -p 1883 -t openwrt/topic -i client_002 -m "hello client1, i am froms client2" OpenWrt中基于libmosquitto开发 前面给大家演示了mosquitto客户端的使用,但命令行客户端仅供测试使用,我们在开发过程中需要自定义消息并且能够实时解析消息,而通过命令行就没那么方便消息的处理了,需要调用mosquitto底层api接口实现想要的功能。 libmosquitto库 在openwrt系统中默认集成了mosquitto库,可以直接依赖调用。 对应依赖的库为: libmosquitto-nossl 不支持ssl加密 libmosquitto 支持ssl加密。 api接口详解 mosquitto_lib_init:初始化libmosquitto库。在使用其他libmosquitto函数之前,应该首先调用此函数。mosquitto_lib_version:获取libmosquitto库的版本号信息。mosquitto_new:创建一个新的mosquitto对象(MQTT客户端)。mosquitto_connect:与MQTT代理服务器建立连接。mosquitto_disconnect:断开与MQTT代理服务器的连接。mosquitto_publish:向指定主题发布消息。mosquitto_subscribe:订阅一个或多个主题。mosquitto_unsubscribe:取消订阅一个或多个主题。mosquitto_loop_start:启动一个线程来处理MQTT消息循环。mosquitto_loop_forever:开始一个阻塞的循环,处理MQTT消息。mosquitto_loop:在非阻塞模式下处理MQTT消息。mosquitto_message_callback_set:设置用于接收订阅消息的回调函数。mosquitto_username_pw_set:设置连接时使用的用户名和密码。mosquitto_tls_set:为MQTT连接启用SSL/TLS加密。mosquitto_tls_opts_set:设置SSL/TLS选项,如CA证书、客户端证书和私钥等。mosquitto_tls_insecure_set:设置是否允许SSL/TLS连接中的不安全选项。mosquitto_will_set:设置遗嘱消息,即在客户端异常断开时发布的消息。 基于libmosquitto实现一个消息订阅程序 源码 #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <mosquitto.h> #include <sys/time.h> #include <sys/sysinfo.h> struct mosquitto *g_test_mosq = NULL; void mqtt_connect_callback(struct mosquitto *mosq, void *userdata, int result) { printf("connect to mqtt server ok\n"); if (MOSQ_ERR_SUCCESS != mosquitto_subscribe(mosq, NULL, "openwrt/#", 0)) { printf("sub topic openwrt/# failed...\n"); } else{ printf("sub topic openwrt/# failed...\n"); } } void mqtt_disconnect_callback(struct mosquitto *mosq, void *userdata, int result) { if (result) printf("disconnect %s\n", mosquitto_connack_string(result)); else printf("disconnect from mqtt server.\n"); } void mqtt_sub_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos) { printf("sub callback\n"); } void mqtt_msg_callback(struct mosquitto *mosq, void *userdata, struct mosquitto_message *message) { printf("callback recv mqtt msg, topic = %s, payload = %s\n", message->topic, message->payload); } struct mosquitto *connect_to_mqtt_server(char *server_ip) { struct mosquitto *mosq = NULL; int rc; char mqtt_user[128] = {0}; char mqtt_pwd[128] = {0}; char client_id[128] = {0}; struct timeval tv; gettimeofday(&tv, NULL); mosquitto_lib_init(); snprintf(client_id, sizeof(client_id), "test_%d", tv.tv_sec); printf("connect to mqtt server..client_id=%s\n", client_id); mosq = mosquitto_new(client_id, true, NULL); if (!mosq) { return NULL; } #if 0 rc = mosquitto_username_pw_set(mosq, "test", "test"); if (rc) { mosquitto_destroy(mosq); return NULL; } #endif mosquitto_connect_callback_set(mosq, mqtt_connect_callback); mosquitto_message_callback_set(mosq, mqtt_msg_callback); mosquitto_subscribe_callback_set(mosq, mqtt_sub_callback); mosquitto_disconnect_callback_set(mosq, mqtt_disconnect_callback); rc = mosquitto_connect(mosq, server_ip, 1883, 30); if (rc) { printf("Unable to connect mqtt server rc=%d\n", rc); mosquitto_destroy(mosq); return NULL; } return mosq; } int mqtt_bcast_msg(char *api, char *data, int len) { char topic[128] = {0}; int mid; if (!api || !data || len == 0) return -1; if (!g_test_mosq) return -1; sprintf(topic, "openwrt/%s", api); return mosquitto_publish(g_test_mosq, &mid, topic, len, data, 0, 0); } int main(int argc, char *argv[]){ char *host = NULL; if (argc < 2){ host = "127.0.0.1"; printf("use default ip: 127.0.0.1\n"); } else{ host = argv[1]; printf("use ip: %s\n", host); } g_test_mosq = connect_to_mqtt_server(host); if (!g_test_mosq){ printf("connect to server %s failed\n", host); exit(0); } mosquitto_loop_forever(g_test_mosq, -1, 1); mosquitto_destroy(g_test_mosq); mosquitto_lib_cleanup(); return 0; } 实例源码编译 将源码包拷贝到openwrt源码package目录 开启mqtt_test宏并生成默认依赖配置 echo "CONFIG_PACKAGE_mqtt_test=y" >>.config make defconfig 编译 make package/mqtt_test/compile V=s 插件安装: mqtt_test依赖了libmosquitto库,而libmosquitto依赖了libcares,所以需要安装三个插件●libcares●libmosquitto-nossl●mqtt_test将插件通过winscp或其他工具上传到openwrt系统中,执行以下命令安装(以X86为例) opkg install libcares_1.18.1-1_x86_64.ipk opkg install libmosquitto-nossl_2.0.15-1_x86_64.ipk opkg install mqtt_test_1.0-1_x86_64.ipk 运行:mqtt_test默认连接本地broker,也可以指定ip运行如果出现错误,表示服务器没有启动或者参数异常,请先确认mosquitto服务已经启动。 use default ip: 127.0.0.1 connect to mqtt server..client_id=test_1686993389 Unable to connect mqtt server rc=14 connect to server 127.0.0.1 failed 运行成功 root@OpenWrt:~# mqtt_test use default ip: 127.0.0.1 connect to mqtt server..client_id=test_1686993598 connect to mqtt server ok sub callback 现在就启动了一个mqtt客户端,订阅了openwrt/# 通过mosquitto_pub工具可以发送指令到该客户端,客户端当前处理方式是输出收到的消息,当然实际开发是解析指令并执行对应的命令,比如接收到reboot命令后执行重启。 pub命令如下: root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t openwrt/send_msg -m "hello openwrt" root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t openwrt/send_msg -m "你好" root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t openwrt/send_msg -m "你好" root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t openwrt/send_msg -m "reboot" root@OpenWrt:~# mosquitto_pub -h 127.0.0.1 -p 1883 -t openwrt/send_msg -m "reboot" 客户端输出如下: callback recv mqtt msg, topic = openwrt/send_msg, payload = hello openwrt callback recv mqtt msg, topic = openwrt/send_msg, payload = 你好 callback recv mqtt msg, topic = openwrt/send_msg, payload = 你好 callback recv mqtt msg, topic = openwrt/send_msg, payload = reboot callback recv mqtt msg, topic = openwrt/send_msg, payload = reboot 如果客户端连接云端的broker,就可以实现远程操作设备,比如远程重启设备、配置下发等。 总结 在物联网开发中我们会经常用的MQTT协议,常见的就是边缘设备和云端通信,上报实时状态、远程管理等,当然也可以局域网间通信,实现节点间通信,比如可以通过MQTT协议实现mesh数据同步、AC集中管理等,有了MQTT协议我们不需要自己通过底层socket实现私有协议,可以只关注业务处理,可大大提高程序稳定性。 --- ### 324. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 https://github.com/mgdm/Mosquitto-PHP Mosquitto-PHP是一个用于与MQTT(Message Queuing Telemetry Transport)协议交互的PHP扩展,它允许PHP应用程序通过MQTT与消息代理进行通信。以下是有关Mosquitto-PHP的一些关键信息: 1. Mosquitto-PHP扩展介绍: Mosquitto-PHP是一个PHP扩展,它提供了与Eclipse Mosquitto MQTT客户端库的集成,使PHP开发者能够轻松地编写MQTT客户端应用程序。 2. PHP 7支持: Mosquitto-PHP扩展已更新以支持PHP 7版本,这意味着它可以在PHP 7及更高版本上运行。这扩展的PHP 7支持得益于Sara Golemon的工作。 3. 扩展要求: PHP版本要求:Mosquitto-PHP扩展要求PHP 5.3及更高版本。 libmosquitto版本要求:它需要使用libmosquitto库的1.2.x版本或更高版本。 支持的操作系统:通常在Linux和Mac OS X上工作,但未明确支持Windows。不过,欢迎开发人员提交Windows支持的贡献。 4. 安装Mosquitto-PHP: 您可以使用PECL来安装Mosquitto-PHP扩展。例如,使用以下命令来安装: pecl install Mosquitto-alpha 或者,您也可以使用传统的扩展构建过程来手动构建和安装它: phpize ./configure --with-mosquitto=/path/to/libmosquitto make make install 最后,将extension=mosquitto.so添加到您的php.ini文件中以启用扩展。 5. 使用Mosquitto-PHP: Mosquitto-PHP允许您以异步方式与MQTT代理进行交互。您需要使用回调函数来处理连接、发布、订阅和消息接收等事件。 例如,以下是如何正确发布QoS为2的消息的示例: use Mosquitto\Client; $mid = 0; $c = new Mosquitto\Client("PHP"); $c->onConnect(function() use ($c, &$mid) { $mid = $c->publish("mgdm/test", "Hello", 2); }); $c->onPublish(function($publishedId) use ($c, $mid) { if ($publishedId == $mid) { $c->disconnect(); } }); $c->connect("localhost"); $c->loopForever(); 您可以根据具体的MQTT应用程序要求,使用Mosquitto-PHP来创建定制的MQTT客户端。 总之,Mosquitto-PHP扩展使PHP开发者能够轻松地与MQTT代理进行通信,这对于构建物联网(IoT)应用程序和其他需要实时消息传递的应用程序非常有用。您可以使用它来连接、发布、订阅和处理MQTT消息。 event.php <?php $c = new Mosquitto\Client(); $c->onConnect(function($code, $message) { echo "I'm connected\n"; }); $c->connect('localhost', 1883, 60); $c->subscribe('#', 1); $c->onMessage(function($m) { var_dump($m); }); $socket = $c->getSocket(); $base = new EventBase(); $ev = new Event($base, $socket, Event::READ | Event::PERSIST, 'cb', $base); function cb($fd, $what, $arg) { global $c; echo "Triggered\n"; var_dump(func_get_args()); $c->loop(); } $ev->add(); $base->dispatch(); 这段 PHP 代码演示了如何使用 Mosquitto-PHP 扩展与 MQTT 服务器进行通信,并使用 libevent 库创建一个事件驱动的应用程序。以下是对代码的详细解释: 创建 Mosquitto 客户端对象: $c = new Mosquitto\Client(); 在这里,您创建了一个 Mosquitto 客户端对象 $c。 设置连接回调函数: $c->onConnect(function($code, $message) { echo "I'm connected\n"; }); 这个回调函数会在成功连接到 MQTT 服务器时执行,它简单地打印出 "I'm connected"。 连接到 MQTT 服务器: $c->connect('localhost', 1883, 60); 这行代码连接到 MQTT 服务器,指定了服务器的主机名为 'localhost',端口号为 1883,超时时间为 60 秒。 订阅 MQTT 主题: $c->subscribe('#', 1); 这里使用 subscribe 方法订阅了 MQTT 主题 '#',表示订阅所有主题。第二个参数 1 表示使用 QoS 1 等级。 设置接收消息的回调函数: $c->onMessage(function($m) { var_dump($m); }); 这个回调函数将在接收到 MQTT 消息时执行,它简单地使用 var_dump 打印消息内容。 获取 Mosquitto 客户端的套接字: $socket = $c->getSocket(); 这里通过 $c->getSocket() 获取 Mosquitto 客户端的套接字,以便后续在 libevent 中使用。 创建 libevent 基础对象和事件对象: $base = new EventBase(); $ev = new Event($base, $socket, Event::READ | Event::PERSIST, 'cb', $base); 这里创建了 libevent 基础对象 $base 和事件对象 $ev。事件对象监听 Mosquitto 客户端套接字的可读事件,并在事件触发时调用 'cb' 函数。 定义事件触发后的回调函数: function cb($fd, $what, $arg) { global $c; echo "Triggered\n"; var_dump(func_get_args()); $c->loop(); } 这是事件触发后执行的回调函数 'cb'。它会在事件触发时打印 "Triggered" 和一些调试信息,然后调用 Mosquitto 客户端的 loop 方法来处理 MQTT 消息。 将事件对象添加到 libevent 循环: $ev->add(); 这行代码将事件对象 $ev 添加到 libevent 的事件循环中,以便监听 Mosquitto 客户端套接字的可读事件。 启动 libevent 事件循环: $base->dispatch(); 最后,这行代码启动 libevent 的事件循环,使其开始监听事件并执行回调函数。这将允许 Mosquitto 客户端接收和处理 MQTT 消息。 总之,这段代码创建了一个 Mosquitto 客户端,连接到 MQTT 服务器,订阅所有主题,并使用 libevent 库实现了一个事件驱动的应用程序,该应用程序能够异步接收和处理 MQTT 消息。当 Mosquitto 客户端接收到消息时,会触发 libevent 事件,然后执行回调函数来处理消息。 pub.php <?php $client = new Mosquitto\Client(); $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->connect("localhost", 1883, 5); $client->subscribe('/#', 1); while (true) { $client->loop(); $mid = $client->publish('/hello', "Hello from PHP at " . date('Y-m-d H:i:s'), 1, 0); echo "Sent message ID: {$mid}\n"; $client->loop(); sleep(2); } $client->disconnect(); unset($client); function connect($r) { echo "I got code {$r}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function message($message) { printf("Got a message ID %d on topic %s with payload:\n%s\n\n", $message->mid, $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } 这段 PHP 代码演示了如何使用 Mosquitto-PHP 扩展与 MQTT 服务器进行通信以及订阅和发布 MQTT 消息。以下是代码的详细解释: 创建 Mosquitto 客户端对象: $client = new Mosquitto\Client(); 在这里,您创建了一个 Mosquitto 客户端对象 $client。 设置连接、订阅、消息和断开连接的回调函数: $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); 这些回调函数分别用于处理连接成功时的事件('connect')、断开连接时的事件('disconnect')、订阅主题时的事件('subscribe')、接收到消息时的事件('message')。 连接到 MQTT 服务器: $client->connect("localhost", 1883, 5); 这行代码连接到 MQTT 服务器,指定了服务器的主机名为 'localhost',端口号为 1883,超时时间为 5 秒。 订阅 MQTT 主题: $client->subscribe('/#', 1); 这里使用 subscribe 方法订阅了 MQTT 主题 '/#',表示订阅所有以 '/' 开头的主题。第二个参数 1 表示使用 QoS 1 等级。 进入循环并发送消息: while (true) { $client->loop(); $mid = $client->publish('/hello', "Hello from PHP at " . date('Y-m-d H:i:s'), 1, 0); echo "Sent message ID: {$mid}\n"; $client->loop(); sleep(2); } 这个 while 循环会持续运行,其中包含了 Mosquitto 客户端的 loop 方法,以便处理 MQTT 消息和事件。在循环中,它会使用 publish 方法发布一条带有时间戳的消息到主题 '/hello'。然后等待 2 秒继续下一轮循环。 断开连接和清理: $client->disconnect(); unset($client); 最后,代码在循环结束后手动断开了与 MQTT 服务器的连接,并释放了 Mosquitto 客户端对象。 回调函数的定义: function connect($r) { echo "I got code {$r}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function message($message) { printf("Got a message ID %d on topic %s with payload:\n%s\n\n", $message->mid, $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } 这些回调函数分别用于处理连接成功、订阅成功、接收到消息和断开连接的事件。在这些函数中,您可以自定义处理逻辑以响应不同事件。 总之,这段代码创建了一个 Mosquitto 客户端,连接到 MQTT 服务器,订阅主题,并周期性地发布消息。它还设置了回调函数来处理不同的事件,使您能够根据需要自定义处理逻辑。最后,代码手动断开了连接并清理资源。 subclass.php <?php class MyClient extends Mosquitto\Client { protected $pendingSubs = []; protected $grantedSubs = []; protected $subscribeCallback = null; public function __construct($id = null, $cleanSession = false) { parent::__construct($id, $cleanSession); parent::onSubscribe(array($this, 'subscribeHandler')); } public function subscribeHandler($mid, $qosCount, $grantedQos) { if (!isset($this->pendingSubs[$mid])) { return; } $topic = $this->pendingSubs[$mid]; $this->grantedSubs[$topic] = $grantedQos; echo "Subscribed to topic {$topic} with message ID {$mid}\n"; if (is_callable($this->subscribeCallback)) { $this->subscribeCallback($mid, $qosCount, $grantedQos); } } public function subscribe($topic, $qos) { $mid = parent::subscribe($topic, $qos); $this->pendingSubs[$mid] = $topic; } public function onSubscribe(callable $callable) { $this->subscribeCallback = $callable; } public function getSubscriptions() { return $this->grantedSubs; } } $c = new MyClient('subscriptionTest'); $c->onSubscribe(function() { echo "Hello, I got subscribed\n"; }); $c->connect('localhost', 1883, 50); $c->subscribe('#', 1); for ($i = 0; $i < 5; $i++) { $c->loop(10); } var_dump($c->getSubscriptions()); 这段 PHP 代码演示了如何创建一个自定义的 Mosquitto 客户端类 MyClient,该类继承了 Mosquitto 客户端,并添加了一些自定义功能。以下是代码的详细解释: 创建自定义 Mosquitto 客户端类 MyClient: class MyClient extends Mosquitto\Client { // ... } 在这里,您创建了一个名为 MyClient 的类,它继承自 Mosquitto 客户端。 构造函数 __construct: public function __construct($id = null, $cleanSession = false) { parent::__construct($id, $cleanSession); parent::onSubscribe(array($this, 'subscribeHandler')); } 在构造函数中,您首先调用了父类(Mosquitto 客户端)的构造函数,并注册了 subscribeHandler 方法作为订阅事件的回调函数。 订阅处理函数 subscribeHandler: public function subscribeHandler($mid, $qosCount, $grantedQos) { // ... } 这个方法会在成功订阅主题时被调用。它会处理订阅事件的回调,并将订阅的主题和相应的 QoS 存储到 grantedSubs 数组中。然后,它会触发 subscribeCallback 回调函数(如果已设置)。 订阅主题方法 subscribe: public function subscribe($topic, $qos) { $mid = parent::subscribe($topic, $qos); $this->pendingSubs[$mid] = $topic; } 这个方法用于订阅主题,并将主题和消息 ID 存储到 pendingSubs 数组中。 设置订阅回调方法 onSubscribe: public function onSubscribe(callable $callable) { $this->subscribeCallback = $callable; } 这个方法允许您设置订阅事件的回调函数,以便在订阅时执行自定义逻辑。 获取订阅信息方法 getSubscriptions: public function getSubscriptions() { return $this->grantedSubs; } 这个方法用于获取已订阅的主题及其对应的 QoS。 创建 MyClient 对象,设置回调和执行订阅: $c = new MyClient('subscriptionTest'); $c->onSubscribe(function() { echo "Hello, I got subscribed\n"; }); $c->connect('localhost', 1883, 50); $c->subscribe('#', 1); 在这里,您创建了一个 MyClient 对象,并设置了订阅回调函数。然后,连接到 MQTT 服务器,订阅了以 '#' 开头的所有主题。 使用 loop 方法运行客户端循环: for ($i = 0; $i < 5; $i++) { $c->loop(10); } 这个循环允许客户端运行,并处理 MQTT 消息和事件。loop(10) 意味着每次循环会等待 10 毫秒来处理事件。 获取订阅信息并输出: var_dump($c->getSubscriptions()); 最后,您使用 getSubscriptions 方法获取已订阅的主题信息,并将其输出。 总之,这段代码演示了如何创建自定义的 Mosquitto 客户端类,以处理 MQTT 订阅事件,并提供了一些自定义功能,例如获取已订阅的主题信息和设置订阅回调函数。这使您能够更灵活地与 MQTT 服务器进行通信和处理订阅。 test.php <?php $client = new Mosquitto\Client(); $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->connect("localhost", 1883, 5); $client->onLog('logger'); $client->subscribe('#', 1); for ($i = 0; $i < 10; $i++) { $client->loop(); } $client->unsubscribe('#'); for ($i = 0; $i < 10; $i++) { $client->loop(); } function connect($r, $message) { echo "I got code {$r} and message {$message}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function unsubscribe() { echo "Unsubscribed from a topic\n"; } function message($message) { printf("Got a message on topic %s with payload:\n%s\n", $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } function logger() { var_dump(func_get_args()); } 这段 PHP 代码演示了如何使用 Mosquitto 客户端库与 MQTT 代理(通常在 localhost 上运行)进行通信,并定义了一些回调函数来处理不同的 MQTT 事件。以下是这段代码的详细解释: 1. 创建 Mosquitto 客户端对象: $client = new Mosquitto\Client(); 这行代码创建了一个 Mosquitto 客户端对象,用于连接到 MQTT 代理并执行 MQTT 操作。 2. 设置回调函数: $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->onLog('logger'); 这些行设置了不同事件的回调函数。当客户端连接成功时,onConnect 回调函数将被调用,当客户端断开连接时,onDisconnect 回调函数将被调用,以此类推。这些回调函数会在后面的代码中定义。 3. 连接到 MQTT 代理: $client->connect("localhost", 1883, 5); 这行代码连接到本地 MQTT 代理,通常运行在 localhost 主机的 1883 端口上。连接的超时时间设置为 5 秒。 4. 订阅 MQTT 主题: $client->subscribe('#', 1); 这行代码订阅了名为 # 的 MQTT 主题,这个特殊的主题表示订阅所有主题。订阅的 QoS(服务质量)级别设置为 1。 5. 运行 MQTT 客户端循环: for ($i = 0; $i < 10; $i++) { $client->loop(); } 这个循环运行 MQTT 客户端,允许它接收和处理来自 MQTT 代理的消息以及触发不同事件的回调函数。 6. 取消订阅 MQTT 主题: $client->unsubscribe('#'); 这行代码取消订阅之前订阅的 # 主题,即停止接收与该主题相关的消息。 7. 再次运行 MQTT 客户端循环: for ($i = 0; $i < 10; $i++) { $client->loop(); } 这段代码再次运行 MQTT 客户端循环,确保处理所有取消订阅后的事件。 8. 定义各种事件回调函数: 下面是定义的不同事件的回调函数: connect($r, $message):当客户端成功连接到 MQTT 代理时,此回调被调用,显示连接结果代码 $r 和消息 $message。 subscribe():当客户端成功订阅主题时,此回调被调用,显示 "Subscribed to a topic"。 unsubscribe():当客户端成功取消订阅主题时,此回调被调用,显示 "Unsubscribed from a topic"。 message($message):当客户端接收到新消息时,此回调被调用,显示消息的主题和有效载荷。 disconnect():当客户端与 MQTT 代理断开连接时,此回调被调用,显示 "Disconnected cleanly"。 logger():此回调用于记录日志信息,它将输出回调函数的所有参数。 总之,这段代码创建了一个 MQTT 客户端并设置了回调函数,然后连接到 MQTT 代理,订阅主题,运行客户端循环以接收消息和处理事件,并在不同的事件发生时触发相应的回调函数,从而实现了 MQTT 通信。这对于与 MQTT 代理进行互动和处理消息非常有用。 testOnpublish.php <?php class MQ { public static $publish = array(); public static $receive = array(); public static function addPublish($mid, $msg) { $msg->id = $mid; self::$publish[$mid] = $msg; } public static function confirm($mid) { if(array_key_exists($mid, self::$publish)) { self::$publish[$mid]->state = true; } } public static function addReceive($msg) { $msg = Message::factory($msg, true); self::$receive[$msg->id] = $msg; } } class Message { public $id; public $state = false; public $msg; public static function factory(Mosquitto\Message $msg, $state = false) { $message = new Message(); $message->state = $state; $message->msg = $msg; $message->id = $msg->mid; return $message; } } $client = new Mosquitto\Client('client.terminal.onpublish', false); $client->onMessage(function($msg) { print_r(array('receive', $msg)); MQ::addReceive($msg); }); $client->onPublish(function($mid) { MQ::confirm($mid); print_r(array('comfirm publish', MQ::$publish[$mid])); }); $client->onConnect(function($rc, $msg) { print_r(array('rc' => $rc, 'message' => $msg)); }); $client->connect('localhost', 1883, 60); sleep(1); $client->subscribe('/test/publish', 1); $msg = Message::factory(new Mosquitto\Message()); $msg->msg->topic = '/test/publish'; $msg->msg->payload = 'hello from on publish'; $msg->msg->qos = 1; $mid = $client->publish($msg->msg->topic, $msg->msg->payload, $msg->msg->qos); print_r(array('publish', $msg)); MQ::addPublish($mid, $msg); sleep(1); $client->loopForever(); 这段PHP代码演示了如何使用Mosquitto客户端库创建一个MQTT客户端,该客户端具有自定义的消息确认和处理机制。以下是代码的详细解释: 1. 创建MQ类: class MQ { public static $publish = array(); public static $receive = array(); public static function addPublish($mid, $msg) { $msg->id = $mid; self::$publish[$mid] = $msg; } public static function confirm($mid) { if(array_key_exists($mid, self::$publish)) { self::$publish[$mid]->state = true; } } public static function addReceive($msg) { $msg = Message::factory($msg, true); self::$receive[$msg->id] = $msg; } } 这个类用于管理发布和接收的消息。它包括以下方法: addPublish($mid, $msg):将发布的消息添加到 $publish 数组中,以便稍后进行确认。 confirm($mid):确认已发布的消息,将其状态标记为已确认。 addReceive($msg):将接收的消息添加到 $receive 数组中。 2. 创建消息类Message: class Message { public $id; public $state = false; public $msg; public static function factory(Mosquitto\Message $msg, $state = false) { $message = new Message(); $message->state = $state; $message->msg = $msg; $message->id = $msg->mid; return $message; } } 这个类表示MQTT消息。它包括以下属性: $id:消息ID。 $state:消息状态,用于确认是否已接收。 $msg:实际的Mosquitto消息对象。 还包括一个工厂方法factory,用于从Mosquitto消息创建Message对象。 3. 创建Mosquitto客户端对象: $client = new Mosquitto\Client('client.terminal.onpublish', false); 这行代码创建了一个Mosquitto客户端对象,并为其指定了客户端ID和cleanSession标志。 4. 设置回调函数: $client->onMessage(function($msg) { print_r(array('receive', $msg)); MQ::addReceive($msg); }); $client->onPublish(function($mid) { MQ::confirm($mid); print_r(array('comfirm publish', MQ::$publish[$mid])); }); $client->onConnect(function($rc, $msg) { print_r(array('rc' => $rc, 'message' => $msg)); }); 这些回调函数用于处理不同的MQTT事件: onMessage:处理接收到的消息,将消息添加到MQ::$receive数组中。 onPublish:处理已发布的消息的确认,将消息标记为已确认。 onConnect:处理连接事件,打印连接结果。 5. 连接到MQTT代理: $client->connect('localhost', 1883, 60); 这行代码连接到本地MQTT代理,通常运行在localhost上的1883端口上。连接的超时时间设置为60秒。 6. 发布消息和处理: sleep(1); $client->subscribe('/test/publish', 1); $msg = Message::factory(new Mosquitto\Message()); $msg->msg->topic = '/test/publish'; $msg->msg->payload = 'hello from on publish'; $msg->msg->qos = 1; $mid = $client->publish($msg->msg->topic, $msg->msg->payload, $msg->msg->qos); print_r(array('publish', $msg)); MQ::addPublish($mid, $msg); sleep(1); $client->loopForever(); 这段代码的主要功能是: 订阅主题/test/publish。 创建一个要发布的消息对象$msg。 发布消息,并将消息添加到MQ::$publish数组中以进行后续确认。 使用loopForever方法持续运行MQTT客户端以处理消息和事件。 总之,这段代码创建了一个具有自定义消息确认和处理机制的MQTT客户端,它可以发布和接收消息,并在处理时跟踪消息的状态。这对于实现更高级的MQTT消息管理非常有用。 testwill.php <?php $client = new Mosquitto\Client(); $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); $client->setWill('/hello', "Client died :-(", 1, 0); $client->connect("localhost", 1883, 5); $client->subscribe('/#', 1); $client->loopForever(); function connect($r) { echo "I got code {$r}\n"; } function subscribe() { echo "Subscribed to a topic\n"; } function message($message) { printf("Got a message on topic %s with payload:\n%s\n", $message->topic, $message->payload); } function disconnect() { echo "Disconnected cleanly\n"; } 这段PHP代码演示了如何创建一个Mosquitto MQTT客户端,该客户端具有以下功能: 1. 创建Mosquitto客户端对象: $client = new Mosquitto\Client(); 这行代码创建了一个Mosquitto客户端对象。 2. 设置连接和事件回调: $client->onConnect('connect'); $client->onDisconnect('disconnect'); $client->onSubscribe('subscribe'); $client->onMessage('message'); 这些行代码设置了不同MQTT事件的回调函数,当客户端连接、断开连接、订阅主题或接收消息时,将调用相应的回调函数。 3. 设置遗嘱消息(Will Message): $client->setWill('/hello', "Client died :-(", 1, 0); 这行代码设置了遗嘱消息,当客户端意外断开连接时,将自动发布遗嘱消息到主题/hello,消息内容是"Client died :-(",QoS级别为1,保留标志为0。 4. 连接到MQTT代理: $client->connect("localhost", 1883, 5); 这行代码连接到MQTT代理,该代理通常运行在本地主机(localhost)的1883端口上。连接超时设置为5秒。 5. 订阅主题: $client->subscribe('/#', 1); 这行代码订阅了以/#开头的所有主题,并将QoS级别设置为1。 6. 使用loopForever方法持续运行客户端: $client->loopForever(); 这行代码使客户端进入无限循环,以便处理MQTT消息和事件。客户端将保持连接状态,并在收到消息时调用相应的消息回调函数。 7. 定义连接、订阅、消息和断开连接的回调函数: 这些回调函数用于处理不同的MQTT事件: connect($r):处理连接事件,其中$r参数包含连接的返回码。 subscribe():处理订阅事件,表示成功订阅主题。 message($message):处理接收到的消息,打印主题和消息内容。 disconnect():处理断开连接事件,表示客户端已经断开连接。 总之,这段代码创建了一个Mosquitto MQTT客户端,连接到MQTT代理,订阅了一组主题,并设置了各种事件的回调函数。它还配置了遗嘱消息,以便在客户端意外断开连接时发送通知。最后,客户端使用loopForever方法持续运行,以便处理MQTT消息和事件。 --- ### 325. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT简介 MQTT(Message Queuing Telemetry Transport)是一种轻量级的消息传输协议,广泛用于物联网设备之间的通信。MQTT协议采用了客户端/服务器架构,支持发布/订阅模式和点对点模式,以其高效、可靠、灵活等特点而著称。 MQTT协议的核心概念包括发布者(publisher)、代理服务器(broker)和订阅者(subscriber)。发布者将消息发布到代理服务器上,而订阅者则从代理服务器中订阅感兴趣的消息。代理服务器负责将消息传递给订阅者。 在MQTT中,主题(topic)是一个重要的概念,用于定义消息的类型和内容。发布者可以将消息发布到一个或多个主题上,而订阅者则可以订阅一个或多个主题的消息。 MQTT协议的轻量级和可靠性使其非常适合在不稳定的网络环境中传输大量消息。它被广泛应用于智能家居、车联网、工业物联网等领域,因为它具有快速响应和低带宽消耗的优势。 MQTTnet简介 MQTTnet是一个跨平台、高性能、开源的MQTT客户端库和服务端实现,是.NET平台上最受欢迎的MQTT实现之一。它可以方便地在.NET平台上集成MQTT功能,实现MQTT协议的消息传输和其他功能。 MQTTnet的源码托管在GitHub上,地址为:https://github.com/dotnet/MQTTnet 在.NET 7中使用MQTTnet 接下来,我们将介绍如何在.NET 7中使用MQTTnet来创建一个简单的MQTT发布和订阅示例。这个示例将包括一个MQTT服务端和一个MQTT客户端。 项目准备 首先,我们需要创建两个.NET 7控制台项目,一个用作服务端,另一个用作客户端。这两个项目将实现MQTT消息发布和订阅功能。 然后,我们需要安装MQTTnet包。在本示例中,我们选择安装3.12版本的MQTTnet,但请注意,MQTTnet的不同版本之间可能存在差异,选择适合您项目需求的版本。 您可以使用NuGet包管理器或命令行来安装MQTTnet,命令如下: dotnet add package MQTTnet --3.12 服务端代码编写 接下来,我们将编写服务端的代码。以下是一个简化版本的服务端代码示例: using System; using System.Text; using System.Threading.Tasks; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; using MQTTnet.Extensions.ManagedClient; public static async Task RunMqttServer() { // 创建一个MQTT客户端工厂 var factory = new MqttFactory(); var client = factory.CreateMqttClient(); // 配置MQTT客户端选项 var options = new MqttClientOptionsBuilder() .WithTcpServer("localhost", 1883) // 指定MQTT代理服务器的地址和端口 .Build(); // 连接到MQTT代理服务器 await client.ConnectAsync(options); while (true) { Console.WriteLine("请输入要发布的消息: "); var message = Console.ReadLine(); // 创建MQTT消息 var mqttMessage = new MqttApplicationMessageBuilder() .WithTopic("testTopic") // 指定消息的主题 .WithPayload(Encoding.UTF8.GetBytes(message)) // 设置消息内容 .WithExactlyOnceQoS() // 设置消息的质量等级 .Build(); // 发布MQTT消息到代理服务器 await client.PublishAsync(mqttMessage); } } static async Task Main(string[] args) { // 运行MQTT服务端 await RunMqttServer(); } 在这个示例中,我们创建了一个MQTT客户端,连接到本地的MQTT代理服务器(broker)并发布消息到名为"testTopic"的主题。服务端将不断等待用户输入,并将用户输入的消息发布到MQTT代理服务器。 客户端代码编写 接下来,我们编写客户端的代码,以下是客户端代码示例: using System; using System.Text; using System.Threading.Tasks; using MQTTnet; using MQTTnet.Client; using MQTTnet.Client.Options; public static async Task RunMqttClient() { // 创建 MQTT 客户端工厂 var factory = new MqttFactory(); var client = factory.CreateMqttClient(); // 配置 MQTT 客户端选项 var options = new MqttClientOptionsBuilder() .WithTcpServer("localhost", 1883) // 指定 MQTT 服务器地址和端口 .Build(); // 设置消息接收处理程序 client.UseApplicationMessageReceivedHandler(e => { // 当接收到 MQTT 消息时,将消息内容打印到控制台 Console.WriteLine($"接收到的消息: {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}"); }); // 连接到 MQTT 服务器 await client.ConnectAsync(options); // 订阅指定主题的消息 await client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("testTopic").Build()); } static async Task Main(string[] args) { // 运行 MQTT 客户端 await RunMqttClient(); } 在这个示例中,我们创建了一个MQTT客户端,连接到本地的 MQTT代理服务器,并订阅了名为"testTopic"的主题。一旦客户端接收到新的消息,它将在控制台上打印消息内容。 运行和测试 现在,我们已经完成了服务端和客户端的代码编写。您可以使用以下步骤来运行和测试这个示例: 在本地安装MQTT代理服务器,确保端口号和配置与代码中匹配。 分别运行服务端和客户端项目,它们将连接到MQTT代理服务器。 在服务端的控制台中输入要发布的消息,然后按回车键。 在客户端的控制台中,您将看到接收到的消息。 这个示例是一个简单的MQTT发布和订阅功能演示,实际项目中可以根据需求进行扩展,例如处理异常、加强安全性等。 总结 MQTT是一种重要的物联网通信协议,它提供了可靠、高效的消息传输机制,适用于各种物联网应用。MQTTnet是.NET平台上的一种强大工具,帮助您轻松集成MQTT功能到.NET应用程序中,无论是服务端还是客户端。 通过以上示例,您可以快速开始使用MQTTnet在.NET 7中创建自己的MQTT应用程序,并实现消息的发布和订阅功能。希望这个教程对您有所帮助,使您更好地理解和应用MQTT协议和MQTTnet库。 --- ### 326. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 如何在 Python 中使用 MQTT Python是一种广泛使用的解释型、高级编程、通用型编程语言。Python的设计哲学强调代码的可读性和简洁的语法,使得开发者能够用更少的代码表达想法,不管是小型还是大型程序。本文将介绍如何在Python项目中使用paho-mqtt客户端库来实现与MQTT服务器的连接、订阅、取消订阅、消息发布和接收等功能。 项目初始化 首先,确保您的Python版本为3.6或更高版本。 python3 --version 选择MQTT客户端库 在Python中,paho-mqtt是一种常用的MQTT客户端库,它提供了对MQTT v3.1和v3.1.1的支持。您可以使用Pip来安装paho-mqtt。 pip3 install -i https://pypi.doubanio.com/simple paho-mqtt Python MQTT 使用 连接MQTT服务器 本文将使用EMQX提供的免费公共MQTT服务器,服务器接入信息如下: Broker: iot.mqtt.cn TCP Port: 1883 Websocket Port: 8083 首先,导入paho-mqtt客户端库: from paho.mqtt import client as mqtt_client 然后,设置MQTT Broker连接参数: broker = 'iot.mqtt.cn' port = 1883 topic = "/python/mqtt" client_id = f'python-mqtt-{random.randint(0, 1000)}' 接下来,编写连接MQTT Broker的函数: def connect_mqtt(): def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print(f"Failed to connect, return code {rc}\n") client = mqtt_client.Client(client_id) client.on_connect = on_connect client.connect(broker, port) return client 发布消息 您可以使用以下代码发布消息到指定主题: def publish(client): msg_count = 0 while True: time.sleep(1) msg = f"messages: {msg_count}" result = client.publish(topic, msg) status = result[0] if status == 0: print(f"Send `{msg}` to topic `{topic}`") else: print(f"Failed to send message to topic {topic}") msg_count += 1 订阅消息 编写消息回调函数on_message,在客户端从MQTT Broker收到消息后将被调用: def subscribe(client: mqtt_client): def on_message(client, userdata, msg): print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic") client.subscribe(topic) client.on_message = on_message 完整代码 发布消息的代码: # python 3.6 import random import time from paho.mqtt import client as mqtt_client # ...(前面的代码) def run(): client = connect_mqtt() client.loop_start() publish(client) if __name__ == '__main__': run() 订阅消息的代码: # python3.6 import random from paho.mqtt import client as mqtt_client # ...(前面的代码) def run(): client = connect_mqtt() subscribe(client) client.loop_forever() if __name__ == '__main__': run() 测试 发布消息:运行发布消息的代码,您将看到客户端成功连接并成功发布消息。 python3 pub.py 订阅消息:运行订阅消息的代码,您将看到客户端成功连接并成功接收到发布的消息。 python3 sub.py 总结 通过paho-mqtt客户端库,我们可以轻松地在Python项目中实现与MQTT服务器的连接、消息发布和订阅功能。Python在物联网领域的应用越来越广泛,其简洁的语法和高可读性使其成为设备侧业务逻辑实现的理想选择。希望本文能帮助您更好地理解如何在Python中使用MQTT。 --- ### 327. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT(Message Queuing Telemetry Transport)是一种轻量级物联网消息传输协议,它基于发布/订阅模式,适用于硬件受限、网络带宽有限、延迟较高的环境。在本文中,我们将详细介绍如何在Java项目中使用MQTT,实现连接到MQTT服务器、订阅主题和发布消息的功能。 步骤1:引入客户端库 首先,我们需要添加Eclipse Paho Java Client库的依赖项到项目的pom.xml文件中: <dependencies> <dependency> <groupId>org.eclipse.paho</groupId> <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.5</version> </dependency> </dependencies> 步骤2:创建MQTT连接 我们将使用免费公共MQTT服务器提供的MQTT服务器,以下是服务器接入信息: Broker: iot.mqtt.cn TCP Port: 1883 SSL/TLS Port: 8883 普通TCP连接 设置MQTT Broker的基本连接参数,用户名和密码为非必选参数: String broker = "tcp://iot.mqtt.cn:1883"; String username = "emqx"; String password = "public"; String clientid = "publish_client"; MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); client.connect(options); TLS/SSL连接 如果需要使用自签名证书进行TLS/SSL连接,需要添加bcpkix-jdk15on依赖项到pom.xml文件,并创建一个SSLUtils工具类。 <!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.70</version> </dependency> 然后,根据TLS/SSL连接设置选项: // 设置 SSL/TLS 连接地址 String broker = "ssl://broker.emqx.io:8883"; // 设置 socket factory String caFilePath = "/cacert.pem"; String clientCrtFilePath = "/client.pem"; String clientKeyFilePath = "/client.key"; SSLSocketFactory socketFactory = SSLUtils.getSocketFactory(caFilePath, clientCrtFilePath, clientKeyFilePath, ""); options.setSocketFactory(socketFactory); 步骤3:发布MQTT消息 创建一个发布客户端类PublishSample,该类将发布一条"Hello MQTT"消息到主题mqtt/test: public class PublishSample { public static void main(String[] args) { String broker = "tcp://broker.emqx.io:1883"; String topic = "mqtt/test"; String username = "emqx"; String password = "public"; String clientid = "publish_client"; String content = "Hello MQTT"; int qos = 0; try { MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); options.setConnectionTimeout(60); options.setKeepAliveInterval(60); client.connect(options); MqttMessage message = new MqttMessage(content.getBytes()); message.setQos(qos); client.publish(topic, message); System.out.println("Message published"); System.out.println("topic: " + topic); System.out.println("message content: " + content); client.disconnect(); client.close(); } catch (MqttException e) { throw new RuntimeException(e); } } } 步骤4:订阅MQTT主题 创建一个订阅客户端类SubscribeSample,该类将订阅主题mqtt/test: public class SubscribeSample { public static void main(String[] args) { String broker = "tcp://broker.emqx.io:1883"; String topic = "mqtt/test"; String username = "emqx"; String password = "public"; String clientid = "subscribe_client"; int qos = 0; try { MqttClient client = new MqttClient(broker, clientid, new MemoryPersistence()); MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(username); options.setPassword(password.toCharArray()); options.setConnectionTimeout(60); options.setKeepAliveInterval(60); client.setCallback(new MqttCallback() { public void connectionLost(Throwable cause) { System.out.println("Connection lost: " + cause.getMessage()); } public void messageArrived(String topic, MqttMessage message) { System.out.println("Received message from topic: " + topic); System.out.println("QoS: " + message.getQos()); System.out.println("Message content: " + new String(message.getPayload())); } public void deliveryComplete(IMqttDeliveryToken token) { System.out.println("Delivery complete: " + token.isComplete()); } }); client.connect(options); client.subscribe(topic, qos); } catch (Exception e) { e.printStackTrace(); } } } 步骤5:测试 现在,您可以运行SubscribeSample订阅mqtt/test主题。然后运行PublishSample发布消息到mqtt/test主题。您将看到发布端成功发布消息,同时订阅端接收到消息。 总结 通过这篇文章,我们详细学习了如何在Java中使用Paho Java Client来连接到公共MQTT服务器,并实现了测试客户端与MQTT服务器的连接、消息发布和订阅。希望这篇文章对您在Java中使用MQTT有所帮助。 --- ═══════════════════════════════════════════ ## 工业制造 ═══════════════════════════════════════════ ### 328. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在现代企业中,自动化设备和人工智能技术的广泛应用显著减少了生产现场运行操作人员的数量,提高了生产效率。然而,这也为设备的维修保养工作带来了新的挑战。复杂的自动化电气设备、机械设备,以及各种电缆和管线的正常运行需要高效的监控和维护,以减少停机事故的发生。传统的“巡检式维护”耗费时间较长,影响企业生产效率,并且也具有一定的误差性。为了更好地对机器进行监管,企业应充分利用现代化技术,最大程度地保障自身效益,避免停机事故的发生。 传统巡检式维护的局限性 在传统的巡检式维护中,工人定时巡检机器,发现故障后上报给维修部门,维修工再根据故障大小采取不同措施,进而反馈给车间主任,再汇报给工厂厂长等。这种方式虽然能够发现问题,但耗费的时间较长,并且依赖于人工的判断,具有较大的误差性,可能会导致问题被延迟发现或漏报,从而影响生产效率和设备的正常运行。 现代化技术的应用 为了克服传统巡检方式的局限性,现代企业应充分利用先进的传感器技术、数据分析技术和通信技术,实现对设备的实时监控和智能维护。Modbus温振变送器就是其中的典型代表。 温振变送器的特点 高性能:Modbus温振变送器采用高性能的MEMS芯片,具有微小、轻量、低功耗、高可靠性、高灵敏度和高精度的特点。它可以通过监测温度和振动数据,及时发现机器运行过程中不易察觉到的异常情况,以便能够尽早修复。 多轴测量:温振变送器可测量X、Y、Z三轴振动速度、振动位移等参数,避免了单轴振动传感器的局限性。在使用时,无论是需要监测哪个方位的速度和位移,它都可以涵盖到,满足用户所有需求。 内置温度传感器:温振变送器内置温度传感器,可测量机器表面温度,以便用户根据温度变化进一步确定电机是否出现故障。常规款温振变送器可测机器表面温度到-40℃~85℃,高温款则可测到-40℃~150℃。 全方位防护:温振变送器外壳采用全不锈钢或铝合金设计,具有高密度、高抗氧化性、耐磨损、耐腐蚀的特点,能够很好地保护内部元器件不受外界环境影响。RS485型/模拟量型采用灌封设计,超强防护,甚至可以在水下使用。 安装简单:温振变送器拥有螺纹和磁吸两种安装方式,用户可以根据实际需求选择合适的安装方式。螺纹安装方式有多种规格,安装时直接拧在机器对应位置即可。磁吸安装方式只需吸附于机器上即可。 多种数据传输方式 温振变送器支持多种数据传输方式,包括LORa、NB-IoT、RS-485和模拟量,用户可以根据需求进行选择。这些传输方式能够实时监测机器的振动状态,收集振动速度、温度数据,并上传到云平台,对机器的运转率和性能进行跟踪和分析,及时发现异常情况,提醒用户进行维修和调整,避免更大的故障和停机。 温振变送器的应用优势 数据测量精准:高性能的MEMS芯片和多轴测量能力使温振变送器的数据测量更加精准,能够及时发现机器运行中的异常情况。 实时监控和报警:温振变送器可以将监测数据实时上传至环境监控云平台,用户可以随时掌握机器的工作情况。平台具有完善的报警功能,一旦数据超过设定的安全阈值,便会进行远程报警,提醒用户及时处理。 历史数据查询:环境监控云平台可以记录历史数据,用户可以按时段查询,生成日报表、周报表、月报表,为电机制定维护计划提供数据支撑。 账号分级管理:云平台具有账号分级功能,可以根据不同人员的职务分配对应的管理权限,增强团队的责任感,实现信息共享。 总结 现代企业应充分利用先进的传感器技术、数据分析技术和通信技术,实现对设备的实时监控和智能维护,最大程度地保障自身效益,避免停机事故的发生。Modbus温振变送器作为一种高性能、低功耗、抗干扰的复合型振动传感器,广泛应用于煤矿、化工、冶金、发电等行业的旋转机器温度和振动的在线测量,为企业设备的高效运行和安全生产提供了有力保障。通过科学的维护和智能化管理,企业能够进一步提高生产效率,降低维护成本,增强市场竞争力。 --- ### 329. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着工业化进程的加速,工业设备的稳定性和安全性变得尤为重要。为了确保设备的长期稳定运行,减少故障率,降低维修成本,现代工业对在线监测预警系统的需求日益增加。一体式温振在线监测预警系统正是在这种背景下应运而生。本文将详细介绍这种系统的原理、组成、优势及其在工业中的应用。 一、系统原理 一体式温振在线监测预警系统主要通过温度传感器和振动传感器对设备进行实时监测。温度传感器能够监测设备关键部件的温度变化,而振动传感器则可以捕捉设备运行时的振动情况。通过将这些传感器采集到的数据传输至中央控制系统,系统可以对设备的运行状态进行实时分析和判断。一旦发现异常情况,系统会立即发出预警信号,以便相关人员及时采取措施。 二、系统组成 传感器模块: 温度传感器:用于监测设备关键部位的温度,如电机、轴承等。 振动传感器:用于监测设备运行时的振动情况,可以检测到设备是否存在不平衡、松动或磨损等问题。 数据采集模块: 负责将传感器采集到的数据进行初步处理和传输。这一模块通常包括数据采集卡、信号调理器等设备。 数据传输模块: 通过无线网络(如Wi-Fi、4G/5G)或有线网络(如以太网)将数据传输至中央控制系统。 中央控制系统: 这是系统的核心部分,负责对接收到的数据进行分析和处理。通过专业的分析软件,中央控制系统可以判断设备的运行状态,并在发现异常时发出预警信号。 预警模块: 主要包括声光报警器、短信通知、电子邮件通知等,用于在检测到异常情况时及时通知相关人员。 监控平台: 这是系统的用户界面,通过电脑或移动设备,用户可以实时查看设备的运行状态、历史数据、预警信息等。 三、系统优势 实时监测: 系统能够24小时不间断地监测设备的运行状态,确保在第一时间发现潜在问题。 预警功能: 当设备的温度或振动超过预设阈值时,系统会立即发出预警信号,提醒相关人员及时处理,避免故障进一步恶化。 数据分析: 中央控制系统可以对大量历史数据进行分析,帮助用户了解设备的运行趋势,预测可能的故障,提高设备的维护效率。 远程监控: 通过互联网,用户可以随时随地查看设备的运行状态,方便了设备的管理和维护。 降低成本: 通过及时发现并处理设备故障,系统可以减少设备的停机时间,降低维修成本,提高生产效率。 四、应用场景 一体式温振在线监测预警系统广泛应用于各类工业设备中,主要包括以下几个方面: 电力行业: 在电厂,电机、变压器等关键设备的运行状态直接关系到电力供应的稳定性。通过在线监测预警系统,可以实时监测这些设备的运行状态,确保电力系统的安全稳定运行。 石化行业: 石化设备在高温、高压下运行,设备故障可能带来严重的经济损失甚至安全事故。在线监测预警系统可以帮助石化企业实时掌握设备运行状况,提前预防故障。 制造行业: 制造业中的各种机械设备,如数控机床、压缩机等,都可以通过在线监测预警系统进行实时监控,提高生产效率,降低设备故障率。 交通运输: 铁路、地铁等交通运输系统中的关键设备也可以通过这一系统进行监测,确保运输安全。 五、案例分析 某电厂电机在线监测预警系统项目 项目背景:某电厂的发电机组由于长时间连续运行,经常出现设备故障,导致停机检修,影响发电效率。为了提高设备的运行稳定性,该电厂决定引入一体式温振在线监测预警系统。 项目实施:在电厂的关键设备上安装温度传感器和振动传感器,并通过无线网络将数据传输至中央控制系统。系统对数据进行实时分析,一旦发现温度或振动异常,立即发出预警信号。 项目效果:系统投入使用后,该电厂的设备故障率显著下降,停机检修时间减少了约30%,发电效率提高了20%。通过及时发现并处理设备问题,电厂的运行成本也大大降低。 六、未来发展方向 随着技术的不断进步,一体式温振在线监测预警系统也在不断发展。未来,系统将朝着更加智能化、集成化和便捷化的方向发展: 智能化: 通过引入人工智能和机器学习技术,系统可以更精准地分析设备运行数据,预测潜在故障,提高预警的准确性。 集成化: 将温度、振动等多个传感器集成在一个设备中,简化安装和维护,提高系统的可靠性。 便捷化: 通过开发更加用户友好的界面和移动应用程序,使用户能够更加方便地监控和管理设备。 结语 一体式温振在线监测预警系统在现代工业中具有重要的应用价值。通过实时监测和预警,系统可以帮助企业提高设备的运行稳定性,降低故障率,减少维修成本,最终提高生产效率。随着技术的不断进步,在线监测预警系统将迎来更加广阔的发展前景,为各行各业的安全稳定运行保驾护航。 --- ### 330. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着智能工厂的到来,工业物联网(IIoT)正在以惊人的速度扩展。预计到2030年,IIoT市场规模将达到3.3万亿美元,意味着将有数十亿个设备相互连接。为了确保这些设备,尤其是那些资源受限且有时依赖电池供电的设备能够高效运行,找到一种高效且可扩展的物联网解决方案至关重要。 MQTT-SN(针对传感器网络的MQTT)是一种专为非TCP/IP网络上的嵌入式设备设计的轻量级发布和订阅消息协议。它优化了MQTT版本3.1.1和MQTT 5.0的规范,特别适合低功耗、受限设备。在这篇文章中,我们将探讨MQTT-SN的节能和扩展能力,以及它如何支持工业自动化和数据采集的不断增长需求。 MQTT-SN:IIoT的低功耗解决方案 减少物联网设备的电力消耗不仅可以降低能源成本,还有许多其他好处。想象一下,一个遍布大型多地点生产设施的传感器网络。每个传感器或连接设备都需要电力,如果依赖频繁更换电池,不仅麻烦,而且限制了这些部署的可扩展性和灵活性。在这种情况下,降低电力消耗尤为重要。 通过最小化单个设备的能耗,可以降低电费,减少对频繁更换电池的依赖。这不仅减少了维护需求,提高了运营的正常运行时间,还显著节省了成本。具有延长电池寿命或能够从环境中获取能量(例如通过太阳能或风能)的节能设备,可以实现更广泛的传感器分布,提供更全面的工业过程视图。这种增加的监控可扩展性,使数据驱动的决策更加有效,并有助于优化运营。 此外,减少对一次性电池的依赖,可以促进更绿色的IIoT生态系统。结合MQTT-SN这样的低功耗协议和能量收集技术,我们可以迈向IIoT的可持续未来。 为什么选择MQTT-SN? 首先,MQTT-SN为效率而生。与MQTT相比,MQTT-SN具有更紧凑的设计。消息头被最小化,主题名称可以被短主题ID替换。数据大小的减少转化为更少的带宽消耗和对资源有限设备的更低处理需求。 为了进一步降低功耗,MQTT-SN引入了睡眠机制。设备可以有效地关闭,并在重新开启时接收排队的消息。这显著降低了功耗,延长了电池供电传感器的电池寿命。 与MQTT一样,MQTT-SN利用发布/订阅模型。设备将数据发布到特定主题,感兴趣的订阅者只接收相关信息。这种有针对性的方法最小化了不必要的数据传输,优化了网络带宽的使用。多个设备可以通过MQTT-SN网关与MQTT代理通信。 通过解决功耗效率和可扩展性的关键方面,MQTT-SN为IIoT环境中的强大和可靠通信铺平了道路。随着工业领域接受自动化和数据驱动的决策,MQTT-SN成为推动创新和确保未来智能工厂无缝运行的强大工具。 为了实现更多的节能和更低的数据开销,MQTT-SN增加了一种新的QoS模式,允许盲目发送并忘记消息传递。这意味着设备可以简单地唤醒并发送消息,而不必等待响应。 与MQTT不同,MQTT-SN不依赖于TCP/IP传输。相反,它旨在与底层网络服务无关。因此,任何支持节点和网关之间双向传输服务的网络都可以支持MQTT-SN。 MQTT-SN的限制 在选择MQTT-SN作为您的通信协议时,需要意识到一些限制。最大的一个问题是安全性。虽然可以使用任何加密技术,但目前MQTT-SN协议本身并没有内置安全性。不过,这个问题将在最新的标准修订中得到解决。 在复杂性方面,学习、实施和管理MQTT-SN可能比一些更简单的协议要困难。然而,使用专为MQTT-SN设计的兼容工具和库可以简化这个过程。虽然网关使设备和代理之间的通信成为可能,但确保不同MQTT-SN实现与现有基础设施的兼容性至关重要。选择符合最新MQTT-SN规范并提供明确迁移路径的解决方案可以帮助缓解兼容性问题。 MQTT-SN在IIoT中的用例 MQTT-SN在功耗效率、可扩展性和轻量级设计方面的优势使其成为各种IIoT应用的理想选择。以下是一些典型的用例: 无线传感器网络:在工业环境中,众多传感器监测温度、压力、振动等关键参数。MQTT-SN的低数据占用和睡眠功能非常适合这些电池供电的传感器,使它们能够在节省电池寿命的同时高效地传输数据。 智能建筑管理:建筑物越来越多地与传感器集成,用于监测能源消耗、占用和环境条件。MQTT-SN促进了这些传感器与中央控制系统之间的高效通信,实现了实时数据收集和优化的建筑运营。 预测性维护:通过持续监测设备健康数据(如振动、温度),MQTT-SN允许及早发现潜在问题,使预防性维护成为可能,减少了停机时间和相关成本。 工业资产跟踪:在大型设施内跟踪关键资产(如工具、机械或库存)的位置和状态至关重要。MQTT-SN处理来自低功耗RFID标签或GNSS跟踪器的数据,使其适用于此类应用。 远程监控和控制:在石油和天然气管道或偏远地区的环境监测站等应用中,MQTT-SN使与电池供电传感器的高效通信成为可能,允许实时数据获取和远程控制能力。 总结 MQTT-SN为IIoT应用提供了一个引人注目的解决方案。它的轻量级设计、高效的通信模型和对节能的强调,使其非常适合工业环境中普遍存在的资源受限设备。随着IIoT格局的不断发展,MQTT-SN有望在促进数据的可扩展交换中发挥关键作用,最终赋能下一代工业自动化。 --- ### 331. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在工业物联网(IIoT)的动态格局中,"连接孪生体"(Connected Twins)的概念作为连接物理世界和数字世界的强大工具而出现。"连接孪生体"通常指的是在IIoT和数字孪生技术背景下的概念或方法。在本文中,我们将探讨数字孪生体是什么,它们与数字孪生体的区别,以及开源MQTT协议如何发挥关键作用,使这两项技术得以实现。 什么是连接孪生体?数字孪生体是物理对象、过程、系统或实体的虚拟表示或数字复制品。它利用实时数据、仿真和建模技术来模拟其物理对应物的行为、特征和性能。连接孪生体通过强调网络或生态系统内多个数字孪生体的连接性和集成性,扩展了数字孪生体的概念。与为单个对象或系统使用单独的数字孪生体不同,使用连接孪生体可以实现多个数字孪生体的互联和协作,允许它们交换数据、互动并以协调的方式运行。与数字孪生体一样,连接孪生体也与其代表的物理对象集成。连接孪生体之间的数据连接性、同步性和丰富性可以通过IIoT技术、通信协议、数据共享平台和基于云的基础设施来促进。连接孪生体根据现实世界数据不断更新。 连接孪生体的一个例子是制造用例,其中生产中使用的机器人。每个机器人过程可以是一个数字孪生体,它们相互连接以创建连接孪生体。这些孪生体与其物理对应物互动,有助于实时参数调整、生产仿真和预测性维护。 连接孪生体的好处 可见性和增强的协作:连接孪生体使产品和过程完全可见。不同的实体,如设备、机器、过程和系统能够轻松协作、共享信息并共同实现过程目标。 实时洞察:通过连接数字孪生体并创建连接孪生体,组织可以获得有关互联资产和系统的整体性能、互动和依赖性的实时洞察。它们还可以促进孪生体与其物理对应物之间的闭环集成。 预测性维护:连接孪生体可以通过分析多个来源的数据、识别潜在问题或异常,并推荐主动维护行动,来支持预测性维护策略。 优化和自动化:连接孪生体的集成允许优化流程、资源分配和决策,以及跨互联系统的任务和工作流程自动化。 可扩展性和灵活性:连接孪生体通过动态调整数字孪生体之间的配置、参数和互动,提供适应变化环境、需求和场景的可扩展性和灵活性。 改进的决策支持:连接孪生体的互联特性使组织能够做出明智的决策,进行情景分析,并在基于综合数据的行业用例上模拟“如果”情景,特别是通过集成的数字孪生体。 区分连接孪生体和数字孪生体虽然数字孪生体和连接孪生体在很多方面相似,但它们在某些方面也有所不同。以下是其中的一些区别: 方面数字孪生体连接孪生体定义单个物理对象、系统、过程或实体的虚拟表示或仿真。网络或生态系统内多个数字孪生体的互联和集成。范围使用实时数据、传感器和建模技术复制物理对应物的行为、属性和互动。代表一个网络化环境,其中多个数字孪生体协作、共享数据并相互互动以实现共同目标。连接性和互动独立运行,专注于模拟和仿真特定对象或系统的行为。强调多个数字孪生体之间的连接性和互动。使互联的数字孪生体之间能够通信、共享数据和协作。功能和用例用于监测、分析、仿真、优化和预测性维护单个对象或系统。通过使多个实体之间的协作、协调和集成成为可能,扩展了数字孪生体的功能。支持复杂的用例,如供应链优化、智能城市管理、工业自动化等。可扩展性和灵活性可以部署在不同的规模上,从单个对象到整个系统,但其可扩展性限于单个孪生体的范围。通过允许在网络化环境中集成和协调多个数字孪生体,提供可扩展性和灵活性。 总结来说,虽然数字孪生体专注于模拟和仿真单个对象或系统,但连接孪生体强调在网络化生态系统内实现更广泛的目标和成果,通过连接性、数据共享和协调行动,实现多个数字孪生体的集成和协作。 在连接孪生体和数字孪生体中使用MQTT的好处MQTT是一种轻量级、高效的通信协议,专为低带宽、高延迟或不可靠的网络设计。它确保了设备之间的可靠通信,非常适合IIoT应用。在连接孪生体和数字孪生体的背景下使用MQTT可以提供多种好处,增强它们的能力: 数据连接性:MQTT是一种为受限环境设计的轻量级和高效的消息协议,非常适合作为数字孪生体、物联网设备和后端系统之间数据采集和连接的关键使能器。它最小化了带宽使用并减少了延迟,确保即使在资源受限的环境中也能快速且可靠地传输数据。 单一真实来源:MQTT为数字孪生体应用提供了集中的通信渠道,实现了实时监控,具有可扩展性和可靠性的数据。实时性确保了数字孪生体是物理世界的最新表示,具有最新版本的数据值。可扩展性确保了来自不同地点的各种制造机器、过程和应用程序的数据能够以可扩展的方式馈送给连接孪生体。可扩展性还使得在连接生态系统内大量数字孪生体之间的无缝集成和通信成为可能,适应动态变化和扩展需求。MQTT的可靠消息传递机制,包括确认、消息排队和持久会话,确保了数据完整性和对网络中断或故障的弹性。它支持如遗嘱和遗言(LWT)消息等功能,以处理意外的客户端断开连接并维护系统稳定性。最后,它支持服务质量(QoS)级别,以确保可靠和及时的消息传递,这对于需要即时数据同步和响应能力的数字孪生体应用至关重要。 从反应式到预测式:通过利用MQTT,工业公司可以轻松地将OT机器、应用程序和系统数据整合到一个位置,通过它们可以从事后数据方法转变为预测性维护、高级分析和运营优化等主动方法。这使它们能够实现数字化转型,并实现工业4.0用例,通过这些用例它们可以降低成本、提高盈利能力并提高运营效率。 使用MQTT的连接孪生体和数字孪生体数据连接性让我们考虑一个使用MQTT的连接孪生体数据连接性的例子,背景是一个智能建筑管理系统。在这个场景中,我们将有多个数字孪生体代表建筑的不同组件,如HVAC系统、照明系统、能源计量器和占用传感器。这些数字孪生体将使用MQTT进行通信和交换数据,以实现建筑运营的协调控制和优化。 数字孪生体设置这里的各种数字孪生体设置包括: HVAC数字孪生体,根据温度、湿度和占用数据监控和控制供暖、通风和空调系统。 照明数字孪生体,控制照明系统,根据占用和环境光线水平调整亮度和调度。 能源计量器数字孪生体,监控能源消耗和来自可再生能源的生产,为能源管理提供实时数据。 占用传感器数字孪生体,检测建筑不同区域的占用水平,触发如调整HVAC设置和开关灯光等动作。 MQTT通信设置MQTT设置包括: MQTT代理:部署一个MQTT代理作为数字孪生体和其他系统之间通信的中央消息中心。 MQTT客户端:为每个数字孪生体(HVAC、照明、能源计量器、占用传感器)配置MQTT客户端,以将数据发布到特定的MQTT主题并订阅相关主题以接收命令和更新。 数据连接流这里是数据连接流: HVAC数字孪生体订阅与占用和温度相关的MQTT主题,来自占用传感器,并相应调整HVAC设置。 照明数字孪生体订阅与占用和光线强度相关的MQTT主题,来自占用传感器,并调整照明水平和时间表。 能源计量器数字孪生体订阅与能源消耗和生产相关的MQTT主题,以优化能源使用并监控可再生能源贡献。 占用传感器数字孪生体通过MQTT主题接收其他数字孪生体的命令,并根据占用变化和环境条件触发动作。 MQTT数据连接的好处以下是MQTT数据 连接的好处: 实时数据交换:MQTT促进了连接孪生体之间的实时数据交换,使基于变化条件的及时行动和调整成为可能。 可扩展性:MQTT支持可扩展的通信,允许添加新的数字孪生体和传感器而不会显著增加开销。 可靠性:MQTT的可靠消息传递确保了数据完整性和系统弹性,即使在不可靠的网络条件下也是如此。 灵活性和互操作性:MQTT的轻量级协议和广泛采用促进了灵活性和互操作性,使与其他物联网设备、云服务和分析平台的无缝集成成为可能。 下一个部分的例子说明了如何使用MQTT数据连接使智能建筑环境中的连接孪生体进行通信、交换数据并协作,以实现高效的建筑管理和优化。 使用MQTT的连接孪生体实时监控让我们考虑一个使用MQTT的连接孪生体实时监控的例子,背景是一个智能制造环境。在这个场景中,我们将有多个数字孪生体代表制造设施内的不同机器、生产线、传感器和控制系统。这些数字孪生体将使用MQTT交换实时数据,以实现对制造过程的持续监控、分析和优化。 数字孪生体设置这里的各种数字孪生体设置包括: 机器数字孪生体:代表单个制造机器,如CNC机器、3D打印机、机械臂等。每个机器的数字孪生体监控其运行参数、状态和性能指标。 生产线数字孪生体:代表生产线或装配流程,监控吞吐量、效率和质量指标。 传感器数字孪生体:代表部署在制造现场的各种传感器,包括温度传感器、压力传感器、振动传感器等。 控制系统数字孪生体:代表控制系统,用于调节机器运行、生产计划和质量控制。 MQTT通信设置MQTT设置包括: MQTT代理:部署一个MQTT代理作为数字孪生体、传感器、控制系统和监控应用程序之间通信的中央消息中心。 MQTT客户端:为每个数字孪生体(机器、生产线、传感器、控制系统)配置MQTT客户端,以将实时数据发布到特定的MQTT主题并订阅相关主题以接收命令和更新。 实时监控流实时监控流包括: 机器数字孪生体将实时数据(如运行参数(速度、温度、压力)、生产产出和维护警报)发布到MQTT主题,如"manufacturing/machines/machine1/data"、"manufacturing/machines/machine2/data"等。 生产线数字孪生体将吞吐量指标、质量指标和生产计划发布到MQTT主题,如"manufacturing/production_lines/line1/data"、"manufacturing/production_lines/line2/data"等。 传感器数字孪生体将传感器读数(温度、压力、振动)发布到MQTT主题,如"manufacturing/sensors/temperature/data"、"manufacturing/sensors/pressure/data"、"manufacturing/sensors/vibration/data"。 控制系统数字孪生体订阅MQTT主题以接收与生产计划、机器设置和质量控制参数相关的命令和更新。 实时监控和分析实时监控和分析包括: 监控应用程序:开发监控应用程序,订阅相关MQTT主题以接收来自连接孪生体、传感器和控制系统的实时数据。 数据分析和可视化:分析来自数字孪生体的实时数据流,以检测异常、识别趋势、预测故障和优化制造过程。使用仪表板、图表和报告可视化数据,以获得实时洞察和决策。 使用MQTT进行实时监控的好处以下是使用MQTT进行实时监控的好处: 及时的数据更新:MQTT的发布-订阅模型确保了实时数据更新的及时交付,使持续监控和对变化条件的快速响应成为可能。 可扩展性:MQTT支持可扩展的通信,允许添加新的数字孪生体、传感器和监控应用程序而不会显著增加开销。 可靠性:MQTT的可靠消息传递确保了数据完整性和系统弹性,这对于制造环境中的实时监控和控制至关重要。 互操作性:MQTT的轻量级协议和广泛采用促进了互操作性,为全面实时监控提供了便利。 这展示了MQTT如何在智能制造环境中的连接孪生体中启用实时监控,使组织能够监控、分析和优化制造过程,以提高效率、生产力和质量控制。 使用MQTT的连接孪生体预测性维护让我们考虑一个使用MQTT的连接孪生体预测性维护的例子,背景是一个能源发电设施内的工业机械车队,如涡轮机、泵和压缩机。预测性维护旨在通过分析来自传感器和数字孪生体的实时数据,在设备故障发生之前识别潜在的设备故障。MQTT促进了实施预测性维护策略所需的通信和数据交换。以下是它的工作原理: 数字孪生体设置数字孪生体设置包括: 涡轮机数字孪生体:代表单个涡轮机,监控振动水平、温度、压力和运行状态等参数。 泵数字孪生体:代表泵,监控流量、电机温度和效率等参数。 压缩机数字孪生体:代表压缩机,监控压力、温度和能耗等参数。 MQTT通信设置MQTT通信设置包括: MQTT代理:部署一个MQTT代理作为数字孪生体、传感器和预测性维护系统之间通信的中央消息中心。 MQTT客户端:为每个数字孪生体配置MQTT客户端,以将实时传感器数据发布到MQTT主题,如"equipment/turbines/turbine1/data"、"equipment/pumps/pump2/data"、"equipment/compressors/compressor3/data"。 数据收集和分析数据收集和分析包括: 传感器数据收集:附着在涡轮机、泵和压缩机上的传感器收集有关运行参数的实时数据。 数字孪生体数据发布:数字孪生体定期将传感器数据发布到MQTT主题,包括振动水平、温度、压力、流量和能耗。 数据分析引擎:实现一个数据分析引擎,该引擎订阅MQTT主题,收集历史数据,并执行预测性分析算法以检测模式、异常和潜在设备故障。 预测性维护行动预测性维护行动包括: 异常检测:数据分析引擎使用机器学习算法分析历史和实时数据,识别异常模式或偏离正常行为的偏差,并标记潜在的设备故障。 故障预测:基于异常检测结果,系统预测设备故障的可能性在一定时间框架内,如涡轮机中的轴承故障或泵中的电机故障。 维护警报:当预测性维护系统检测到设备故障的高概率时,它通过MQTT主题如"maintenance/alerts/turbine1"、"maintenance/alerts/pump2"、"maintenance/alerts/compressor3"生成维护警报和通知。 维护响应和优化维护响应和优化包括: 维护团队通知:维护团队接收到维护警报,然后可以安排主动维护活动,如在故障发生之前检查、修理或更换组件。 维护历史记录:系统记录维护行动,包括修理、更换和检查,以跟踪设备健康、性能和维护历史。 性能优化:预测性维护洞察力被用来优化设备性能,减少停机时间,延长设备寿命,并提高整体运营效率。 使用MQTT进行预测性维护的好处使用MQTT进行预测性维护的好处包括: 实时数据交换:MQTT使数字孪生体、传感器和预测性维护系统之间的实时数据交换成为可能,有助于及时检测设备异常和故障。 可扩展性:MQTT的发布-订阅模型支持可扩展的通信,允许添加新的数字孪生体、传感器和分析引擎而不会破坏现有系统。 可靠性:MQTT的可靠消息传递确保了数据完整性和系统弹性,这对于维护准确的预测性维护预测和警报至关重要。 互操作性:MQTT的轻量级协议促进了互操作性,使与不同设备、传感器和维护系统的无缝集成成为可能,为全面的预测性维护解决方案提供了便利。 这展示了如何在工业设施内的连接孪生体中使用MQTT实施预测性维护,利用实时数据分析和主动维护策略来优化设备性能和可靠性。 结论由MQTT驱动的连接孪生体使各行业能够做出明智的决策、优化流程并提高效率。随着IIoT的不断发展,理解和利用连接孪生体的潜力对于保持数字时代的竞争性至关重要。无论是风力涡轮机、制造线还是智能建筑,连接孪生体都承载着改变我们与物理世界互动方式的承诺。 --- ### 332. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信       智能仓库管理系统充分利用物联网技术,通过良好的分层架构设计,达到从信息采集、信息上传、到智能化处理的全方位管理,通过智能算法匹配实现了智能仓库的智能化采集定位的技术难点。        高精度定位系统技术方案        在技术层面,根据物联网常用模式并结合系统自身特性,将系统分为数据采集端、数据通信端和系统应用端三个层面。        高精度定位系统在智慧工厂运行在成品货物储存仓库,        标出的是入库判定区;        标出的是出库判定区;        工业 POE 交换机的位置,用来连接附近的各排定位基站;        定位基站在仓库的分布位置,在基站布设的位置需要布有 220v 交流电 源接口或者提供 POE 供电,具体点位布设更精细的位置坐标需要根据现场仓库环境、电磁环境、信道检测报告确定。 应用案例: (1)智慧工厂成品生产车间、仓库都有网络接口,高精定位基站、入库门RFID 系统、出库 RFID 桌面式读写器将通过有线网络交换机连接至机房,同时车载 RFID 读写器、手持机将通过全覆盖且无漫游切换的 WIFI 网络回传至机房。 (2)机房作为所有货物位置信息、出入库信息、相关业务信息的汇集地,包括但不限于定位管控服务器、业务及数据库服务器等设备,并与现有 ERP 系统进行协同工作,共同完成从下订单、生产、入库、出库、完成订单等整个业务流程。     < --- ### 333. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 液位变送器在蒸发器操作中的重要性 在工业生产过程中,蒸发器是一种常见的设备,广泛应用于化工、食品加工、制药和制冷等行业。其主要功能是将液态物质转化为气态,同时通过吸收热量来降低周围介质的温度,实现物料的蒸发和结晶。液位变送器作为蒸发器操作中的关键组件,对于确保整个蒸发过程的顺利进行和提高操作效率具有重要意义。 一、蒸发器的工作原理 蒸发器的工作原理基于物质的相变过程。在蒸发器中,液态制冷剂(如氯化钠、硫酸钠等)被引入到管道中,通过外部热源或压缩机制冷剂液化,然后在蒸发器内气化,由液态变为气态。在这个过程中,制冷剂吸收周围介质的热量,从而达到冷却的效果。 二、液位变送器的作用 精确监测液位: 液位变送器能够实时监测蒸发器内部的液位高度,确保制冷剂的供应和蒸发过程的稳定进行。 控制制冷剂的供给: 通过液位变送器反馈的数据,可以自动调节制冷剂的流入量,保证蒸发器内液位的稳定,避免因液位过高或过低而导致的操作问题。 优化蒸发效率: 液位变送器有助于优化蒸发过程,通过精确控制液位,可以提高蒸发效率,减少能源消耗。 保障操作安全: 液位变送器可以预防液位过高导致的溢出或过低导致的设备损坏,确保蒸发器操作的安全性。 三、液位变送器的技术要求 液位变送器在蒸发器中的应用需要具备以下技术特点: 高精确度: 液位变送器必须具备高精度的监测能力,以确保液位数据的准确性。 良好的稳定性: 在蒸发器的高温或低温环境下,液位变送器需要保持稳定的工作性能。 快速响应: 液位变送器应具备快速响应的特性,以便及时调整制冷剂的供给。 耐腐蚀性: 由于蒸发器中可能接触到各种化学物质,液位变送器需要具备良好的耐腐蚀性能。 四、结论 液位变送器在蒸发器操作中发挥着至关重要的作用。通过精确监测和控制蒸发器内部的液位,液位变送器不仅能够提高蒸发效率,降低能源消耗,还能够保障操作过程的安全性。随着工业自动化技术的不断进步,液位变送器的性能将不断提升,为蒸发器操作提供更加可靠和高 --- ### 334. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着工业物联网 (IIoT) 技术的快速发展,越来越多的数据被生成和收集。这些数据包含了设备状态、生产过程、产品质量等重要信息,是实现数字化转型和智能制造的关键。 历史数据管理系统 (Historian) 是一种专门用于存储和管理历史数据的软件系统。它可以帮助企业有效利用历史数据,提升运营效率、降低成本、提高产品质量。 统一命名空间 (UNS) 是工业物联网领域的一种开放、可扩展的架构,可以将来自不同设备、系统和应用程序的数据统一起来,提供一个统一的数据视图。 将历史数据管理系统集成到统一命名空间 可以实现历史数据的统一管理和分析,为企业带来以下优势: 提高数据可访问性和可用性: 历史数据可以与实时数据一起,通过统一的接口进行访问和分析,方便企业进行全面的数据分析。 增强数据分析能力: 通过将历史数据与实时数据进行关联分析,可以发现更深层次的洞察,帮助企业更好地理解运营状况、预测未来趋势。 优化运营效率: 历史数据可以用于改进生产流程、优化资源配置、降低运营成本。 提高产品质量: 历史数据可以用于分析产品缺陷,改进产品设计和制造工艺,提高产品质量。 集成策略 将历史数据管理系统集成到统一命名空间,可以采用以下策略: 使用标准化协议: 历史数据管理系统和统一命名空间可以使用 MQTT 等标准化协议进行通信,确保数据交换的互操作性。 建立数据映射: 需要建立历史数据和统一命名空间之间的数据映射关系,确保数据的准确一致。 开发数据转换工具: 可以开发数据转换工具,将历史数据转换为统一命名空间支持的数据格式。 注意事项 在将历史数据管理系统集成到统一命名空间时,需要考虑以下注意事项: 数据安全: 历史数据可能包含敏感信息,需要确保数据的安全性和隐私性。 数据完整性: 历史数据是重要的分析资产,需要确保数据的完整性和准确性。 性能和可扩展性: 需要确保集成后的系统能够满足性能和可扩展性要求。 结论 将历史数据管理系统集成到统一命名空间是实现工业物联网数据价值的关键途径。通过有效利用历史数据,企业可以提升运营效率、降低成本、提高产品质量,实现数字化转型和智能制造。 --- ### 335. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 离散制造是指生产独立、可辨认且易于计数的独立物品或单元的过程。这种制造类型涉及将组件或零件组装成成品,其中每个物品都可以与其他物品区分开。典型的离散制造行业包括汽车、电子、航空航天、机械和医疗设备。这些行业通常在生产过程中使用物料清单(BOMs)和质量控制措施。离散制造允许定制、灵活性和高效生产各种产品。 离散制造的常见过程 生产计划和调度 离散制造需要对整个生产过程进行仔细的计划和调度,以确保所需的零部件在需要时可用。调度定义了每个生产阶段需要多长时间以及每个人应该工作多少时间,以确保按时完成生产。生产计划需要优化,以最小化浪费并最大化效率。因此,供应链数据的可见性非常重要。 批量大小和交货期的优化 批量大小突显生产的数量,而交货期指整个过程所需的时间。这两个参数都影响生产效率,因此必须进行优化以获得更好的产出。实时数据的可见性和准确性非常重要。 离散制造的常见系统 计算机辅助设计(CAD) CAD软件用于设计产品,概念化想法以考虑确保最终产品完美的细节。该工具执行快速设计计算和模拟,有助于创建准确和精确的产品设计。 计算机辅助制造(CAM) 计算机辅助制造实现了管理过程的自动化,允许跟踪生产过程、资源和运输。 企业资源规划(ERP) ERP的实施提供了对库存和整个生产过程更好的控制和可见性。借助ERP,平台检查不同类型的数据和信息,并在所有点上使其可访问和可用。 产品生命周期管理(PLM) PLM确保从概念化时直到最终发运时对产品的整个生命周期进行管理。 工业物联网(IIoT)和MQTT作为连接系统的启用器 在离散制造中,IIoT在通过传感器和可编程逻辑控制器(PLC)将各种OT系统连接到上述IT系统方面发挥着重要作用。这种OT-IT连接实现了数据交换和数字化转型用例,例如,ERP系统中的订单数据需要与PLM中的生产数据相结合,以便能够进行正确的预测、计划和调度。IIoT使这些系统能够彼此通信,并通过MQTT等消息传递技术创建一个单一的窗格。 MQTT在离散制造应用中的作用 实时数据通信 MQTT在离散制造中实现了设备、系统和应用程序之间的实时通信,有助于将它们连接到企业和/或云,支持预测性维护、远程监视、数字孪生和先进的分析等高级数据用例。MQTT还促进了无显著延迟的制造设备之间的无缝机器对机器通信,这对于监视和控制离散制造非常关键,确保数据迅速而高效地交换。 可扩展性 MQTT具有很高的可扩展性,可以同时支持大量设备、系统和应用程序。在离散制造中,其中许多设备、系统和应用程序部署在生产现场,MQTT的可扩展性对于处理多样化的数据来源至关重要。提供企业级MQTT代理的HiveMQ具有额外的可扩展性功能,并已进行了2亿并发连接的基准测试。 带宽使用效率 MQTT在带宽使用效率方面设计得非常高效。在网络带宽可能有限的制造环境中,MQTT的轻量级协议确保数据可以在不给网络基础设施带来额外负担的情况下进行高效传输。 可靠性和服务质量(QoS) MQTT支持不同级别的服务质量,允许制造商选择适用于其特定用例的可靠性级别。这对于可靠的数据交换至关重要,例如远程监视关键设备。MQTT通过支持保留消息来提供额外的可靠性,其中代理会保留在特定主题上发送的最后一条消息。这个特性在离散制造中非常有用,以确保连接到网络的设备在连接时接收到最新的相关信息。HiveMQ MQTT代理提供了额外的可靠性功能,包括支持无主集群架构、可靠的通信和零停机升级。 安全性 MQTT本身提供通信的安全性,因为它基于对主题命名空间的订阅。因此,未订阅特定主题的任何客户端都不会接收到消息。除此之外,可以在MQTT上实施额外的安全功能,包括用户ID/密码、TLS加密、X.509 客户端证书授权等机制,以确保离散制造通信的安全性。 发布-订阅模型 MQTT采用发布-订阅模型,其中客户端可以将消息发布到特定主题,而其他客户端可以订阅这些主题以接收消息。这个模型非常适合离散制造场景,其中不同的组件需要实时了解相关事件或实时变化。除此之外,数据框架如Sparkplug和统一命名空间等概念提供了其他有效组织数据的方式。 边缘计算集成 MQTT通常与边缘计算一起在离散制造中使用。边缘设备、应用程序和系统使用MQTT在本地彼此通信,有选择地与服务器/云通信,从而减少将所有数据发送到中心服务器的需求。这可以提高响应时间并减少延迟。边缘网关可以将来自各种协议(如OPC UA、Modbus和Siemens S7)的数据转换成MQTT,并将数据传送到代理进行处理。 MQTT对离散制造中IIoT数据通信的改变 离散制造中的IIoT改善了效率、质量、维护和整体运营效果。通过使用可靠且高效的通信机制(如MQTT)实现数据通信,离散制造系统可以高效支持对工厂生产中各种设备、流程和应用程序的实时监视,并支持先进的数据用例。MQTT所带来的连接性使离散制造得以数字化转型,从而实现更高的效率、降低成本、更好的客户体验和更高的盈利能力。 --- ### 336. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在过去的十年中,制造业取得了多项进步,有助于简化生产流程、降低成本并提高盈利能力。然而,尤其在能源使用和可持续性方面,仍存在一些问题和挑战。解决这些问题对于实现更环保、资源效率更高的制造业至关重要。基于开放标准(如MQTT)的创新解决方案可以帮助解决这些问题。在本文中,我们将深入探讨制造业领域的主要挑战以及如何通过边缘或云端的MQTT来克服这些挑战。 制造业的能源和可持续性挑战 以下是我们看到的一些阻碍制造商减少能源使用和提高可持续性的常见挑战: 使用专有设备和过时软件 制造设施通常处理具有专有通信协议和孤岛式设计的设备,导致不同系统无法相互通信。这些系统通常是基于即时需求而非长期战略设计的。它们由于需要额外资源来实现通信,妨碍了最佳能源使用,也影响了可持续性目标。 高能源和资源消耗 制造过程复杂且耗能。它们通常需要大量能源输入,导致高运营成本和碳排放的增加。此外,某些过程使用大量资源,如电力或水。在不影响生产效率的情况下优化能源和资源使用是一个重大挑战。 依赖不可再生能源 许多制造设施依赖于化石燃料等不可再生能源。由于生产压力、基础设施限制、成本、监管限制和对长期效益了解不足,向可再生能源转型并采用可持续最佳实践可能具有挑战性。制造商可能会优先考虑短期成本节约而非长期可持续性目标。 废物产生 制造过程产生大量废物,包括废料、副产品和污染物。适当的废物管理和回收策略对于减少环境影响并支持合规性至关重要。 供应链可持续性 可持续制造不仅关乎内部流程,还涉及整个供应链。确保供应商采用可持续实践可能具有挑战性,特别是在从环境标准较为宽松的地区采购原材料时。全球化供应链和竞争可能阻碍可持续性倡议的实施。 过时的设备和技术 较旧的制造设备可能缺乏节能特性,使得在不进行重大资本投资的情况下升级流程变得具有挑战性。工人可能不完全了解他们行为的环境影响或节能潜力。现代化设备、培训工人和采用工业4.0技术可能是一个渐进但必要的过程。 数据可见性不足 低效的监测和数据收集系统使得难以评估能源使用模式并识别改进领域。这也对实现可持续性最佳实践构成挑战。实施实时监控和数据分析对于做出明智决策至关重要。 解决这些问题需要结合技术创新、管理愿景、监管支持、员工参与和供应链合作的整体方法。致力于优化能源使用和促进可持续性的制造商可以探索一系列能效技术、可再生能源采用、废物减少策略和持续改进文化的组合,以克服这些挑战。最重要的是,他们需要采用智能制造以实现成功。 智能制造中的可持续之路 根据2022年麦肯锡研究,通过采用工业4.0技术(如工业物联网(IIoT)、人工智能(AI)、数字孪生、数字线程、增强现实(AR)、虚拟现实(VR))实现的智能制造优势,如停机时间减少30-50%、吞吐量增加10-30%、预测精度提高高达85%。在工业4.0技术和智能制造的最佳实践帮助下,制造行业正被转变回一个经济强国。 智能制造的一个关键方面是拥有企业数据增强策略,该策略使各种系统之间能够通过MQTT实现实时双向通信,为能源优化和可持续性铺平道路。 MQTT如何帮助改善制造业的能源使用和促进可持续性 MQTT是一种轻量级消息协议,专为工业物联网(IoT)和智能制造系统中的高效通信而设计。它是智能制造的一个组成部分。由于它在优化能源使用和促进智能制造中的可持续性方面提供的各种优势,它已成为从现场到企业或云的工业数据通信的事实标准。 以下是一些优势: 高效的通信数据包大小和消息有效负载 MQTT被创建为一个非常高效的基于事件的发布/订阅数据通信协议。消息数据包大小仅高达200KB,有助于最小化工业设备、系统、应用程序和代理之间交换的数据量,降低能源消耗。使用MQTT,设备、系统和应用程序仅接收相关信息,最小化不必要的数据传输。这也有助于优化带宽并减少运营成本。MQTT还允许通过使用高效的数据序列化格式(如JSON和协议缓冲区)来优化消息有效负载,减少网络带宽使用和能源消耗。 服务质量(QoS)等级、睡眠模式和边缘处理 MQTT提供了根据数据临界性选择合适的服务质量(QoS)级别的灵活性。这使用户能够优化他们的数据传输策略,确保效率和可靠性。更高的QoS级别确保消息传递,但可能导致增加的能源消耗。此外,鉴于MQTT的异步性质,设备可以在空闲期间实施睡眠模式以节约能源。设备可以根据MQTT触发器在有相关数据交换时唤醒。除了MQTT客户端外,本地代理允许在将数据发送到企业代理之前在边缘处理大部分数据,从而减少通过网络传输的数据量,从而节省能源。 设备配置、管理、监控和报告 可以使用MQTT数据实现远程设备配置和管理,以优化设备设置、更新固件和应用节能参数。此外,可以实施监控系统来跟踪能源使用和可持续性指标。可以根据预定义的阈值创建报告和异常警报,以识别改进领域。 可再生能源整合和系统优化 使用MQTT,可以实时监控能源消费和生产,以优化可再生能源的使用。例如,可以利用数据调整制造过程,根据绿色能源的可用性进行优化。此外,可以使用MQTT定期审查和优化基于变化需求、技术进步和节能机会的制造数据移动。 预测性维护和高级分析 借助MQTT实现的实时数据移动,可以实施预测性维护来监控设备健康。其结果是减少停机时间,提高效率,以及防止与故障机械有关的能源浪费。此外,可以使用MQTT数据实施高级数据分析和机器学习模型,提供能源使用模式的洞察,使得能够实施主动节能措施。 标准化、互操作性和持续优化 通过确保智能制造环境中的设备、系统和应用程序遵循MQTT消息标准进行数据互操作,制造商可以创建一个更灵活和可扩展的生态系统。同时,通过定期审查和修改MQTT实现,根据变化的制造要求,制造商确保他们正在优化他们的系统并为其投资未来。 结合人员、流程和技术,通过MQTT实现目标 通过创建基于MQTT的数据移动策略,建立正确的智能组织结构来利用它,以及去除障碍的流程,制造商可以创建一个更节能、更可持续的智能制造生态系统。关键是将基于MQTT的数据策略整合到考虑制造环境独特要求的全面制造战略中,并不断寻求改进机会。 智能制造通过这种方式,不仅提高了能效和可持续性,还为制造商带来了经济效益和竞争优势,是未来制造业发展的关键方向。 --- ### 337. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 预测性维护旨在帮助预测资产故障,并允许提前安排纠正性维护。这避免了意外的设备停机时间,提高了对客户的服务质量,并减少了预防性维护策略中过度维护所造成的额外成本。 应用场景 预测性维护技术可应用于石油和天然气、可再生能源、采矿、制造、食品饮料等主要行业。不同类型的资产,包括制造资产、信息技术资产、医疗设备等,通过生成系统消息、错误事件和日志文件来跟踪运行状态,这些可以用来预测即将发生的故障。 预防性维护与预测性维护 预防性维护是定期或按计划进行的维护,与资产状况无关。这是制造厂维护经理通常为防止计划外停机而进行的操作。 预测性维护只在必要时进行,取决于资产状况,即当设备出现故障或失败风险时。这使用了先进的分析技术。 尽管预测性维护的前期投资相对于预防性维护较高,但从长远来看,通过消除不必要的维护,运营成本可以降低。 如何实现预测性维护? 通过定期或持续监测资产状况来评估资产的健康和性能,从而实现预测性维护。通过连接不同资产和系统的IoT设备捕获的数据,使企业能够预测、计划并采取主动措施,以防止部件修理或资产故障等事件发生。为避免对业务造成干扰,预测性维护主要在设备正常工作条件下进行。 一种常见的实施预测性维护的方式是使用机器学习和人工智能技术获取机器维护和故障预防的洞察。这些技术的常见方面包括预测: 设备的生命周期所处阶段 设备的剩余使用寿命(RUL) 设备完全故障前的剩余周期数 这可以应用于各个行业,帮助实时监控机器的健康状况并及时进行维护,以减少过度维护的成本。 预测性维护的好处 安全、成本和资产管理都是投资预测性维护的重大好处。根据普华永道的一份报告,预测性维护平均可以: 降低成本12% 提高正常运行时间9% 减少安全、健康、环境和质量风险14% 延长老化资产的使用寿命20% 工业物联网(IIoT)技术和边缘计算助力预测性维护 在工业4.0和IIoT支持的工业过程中,资产通过IoT传感器和设备相互连接。这些连接的工业资产追踪相关的IoT数据,然后可以用来预测故障即将发生。智能IoT传感器在整个工业过程中使用,提供这些信息。 例如,安装在上游石油和天然气的远程油井中的传感器可以观察温度越过阈值,暗示油井或其某部分可能很快会发生故障。一旦通过传感器收集了数据,IIoT可以进行分析以主动预测结果。借助工业边缘的可见性和实时分析,制造商可以知道资产何时会发生故障以及如何发生故障,从而采取预防措施避免停机。 在需要在发生事件的地点附近做出决策时,边缘计算尤其重要。例如,在一些关键设备的油气作业中,基于边缘上的预测性维护算法预测故障并实施维护是重要的。这可以与云上运行的预测性维护算法结合,提供更全面的维护调度策略。 利用MQTT实现高效数据移动 采用IIoT技术进行预测性维护代表着制造商在当今动态市场环境中保持竞争优势的关键举措。然而,关键问题是:行业如何以可持续成功和持续创新的方式实施IIoT的数据移动? 答案在于采用行业标准的MQTT协议,被认为是IIoT的事实标准。 使用MQTT和Sparkplug进行工业数据采集和聚合 MQTT是一种标准的二进制发布-订阅消息传递协议,专为快速可靠地传输工业资产、系统和应用程序数据而设计,以实现预测性维护,尤其适用于非常受限的条件下。限制可能包括不可靠的网络连接、有限的带宽或有限的电池电量。MQTT建立在TCP/IP之上,这是互联网上连接网络设备的首选通信协议。因此,MQTT非常适合IIoT,支持事件驱动架构。 MQTT技术旨在将数据推送至企业内数千个远程资产、系统和应用程序,并从中获取数据。MQTT Sparkplug是一个位于MQTT之上的框架,为工业数据添加更多上下文。它是一个开源软件规范,为MQTT客户端提供了一个框架,以集成各种工业数据,并通过定义数据模型提供上下文。它为制造设备制造商和软件提供商提供了一种一致的方式来共享具有上下文的工厂数据,丰富了预测性维护数据。 MQTT Sparkplug基于的数据架构(如图2所示)展示了数据代理如何连接多个机器/流程和应用程序,以实现OT(运营技术)和IT(信息技术)系统之间的无缝双向工业数据移动。 MQTT Sparkplug支持的架构 图2:一个基于MQTT Sparkplug的架构,支持多个工业数据生产者和数据消费者之间的OT到IT桥接,从而实现预测性维护。 在企业IIoT策略中,MQTT越来越受欢迎。根据IIoT World在2022年进行的一项调查,MQTT是实现IIoT策略所必需的数据移动工具中的明显优胜者。 获取实施预测性维护所需的数据 MQTT协议与Sparkplug一起,因其轻量级、按异常报告以及围绕安全性、可伸缩性、可靠性等方面提供的众多功能,正日益受到工业边缘到企业/云通信的欢迎。MQTT正在推动IIoT应用,使工业流程公司能够在其资产上实施预测性维护。预测性维护反过来使公司能够降低维护成本、提高资产利用率、延长资产寿命,并提高安全性/合规性。 通过将IIoT与MQTT无缝整合,实现工业运营中的双向数据移动,公司可以在其流程中引发范式转变,增强市场地位,并为更加繁荣和高效的未来打下坚实的数据基础。 --- ═══════════════════════════════════════════ ## 工具和应用程序 ═══════════════════════════════════════════ ### 338. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTTX Web,一款基于浏览器的MQTT 5.0客户端工具,以其开源性、易用性和高效性,在物联网(IoT)开发领域中占有一席之地。随着IoT领域的迅速发展,开发者们越来越需要这样一种工具,它能够在无需下载和安装的情况下快速连接和测试MQTT服务。MQTTX Web正是为了满足这种需求而设计,它提供了一种直观的方式来进行MQTT消息的发送和接收,从而加快了开发和调试过程。 MQTT X Web 简介 MQTT X Web 针对初次接触 MQTT 协议的用户而设计,提供了一种更加直观和便捷的方式来快速理解和上手 MQTT 协议。用户无需进行复杂的下载和安装步骤,只需在浏览器中打开相应页面,就可以迅速连接到 MQTT 服务和应用,进而探索和理解 MQTT 协议。 作为一个在线 MQTT 5.0 客户端工具,MQTT X Web 在浏览器中作为 MQTT 5.0 WebSocket 客户端运行,并具备以下主要功能: 支持通过标准或加密的 WebSocket 端口连接到 MQTT 服务。 管理连接的创建、编辑、删除及缓存,以便下次方便使用。 不同连接的订阅列表管理。 发布消息、接收消息,以及接收新消息时的提示功能,同时支持根据消息类型过滤消息列表。 相关资源链接: MQTT X Web 官网:https://mqttx.app/zh/web 在线使用地址:http://www.emqx.io/online-mqtt-client GitHub 仓库:https://github.com/emqx/MQTTX/tree/main/web MQTT over WebSocket 随着 Web 前端技术的迅猛发展,浏览器功能日益增强,越来越多的应用得以在浏览器端实现。其中,WebSocket 作为 Web 应用的实时通信方式,已被广泛应用。MQTT X Web 利用 WebSocket 技术连接 MQTT 服务,不仅使用方便,而且能够提供 MQTT over WebSocket 的连接测试功能。当需要在 Web 应用场景中使用 MQTT 时,用户可以通过 MQTT X Web 调试 MQTT 服务和应用,从而加速应用的开发并提高稳定性。 基于现代浏览器技术 MQTT X Web 基于现代浏览器技术开发,将应用部署到网页上,使用户无需下载和安装任何软件即可使用。此外,它还支持将新建的连接和消息信息等持久化存储到浏览器内,方便用户下次访问。 开源代码 MQTT X Web 的代码与 MQTT X 桌面应用及 CLI 保持一致,基于 Apache License 2.0 协议开源。高级用户可以直接从代码仓库中获取 MQTT X Web 的代码,根据自己的需要进行修改和部署。 开发和调试 MQTT 服务与应用 MQTT X Web 的图形化界面设计,采用类似聊天界面的形式,帮助用户快速测试 MQTT 服务,其使用方式与 MQTT X 桌面应用基本一致。用户只需在浏览器中输入 http://www.emqx.io/online-mqtt-client/ 就可以访问到 MQTT X Web。 有关如何使用 MQTT X Web 的更多详细介绍,请参考其使用文档:https://mqttx.app/zh/docs/get-started。 结语 MQTT X Web 的发布为物联网开发者提供了一种全新的 MQTT 连接测试方式。它对命令行调用、桌面客户端下载和在线浏览器交互的全面支持,使得 MQTT X 1.8.0 能够帮助不同场景下的用户开发和调试 MQTT 服务或应用,提高了用户的业务能力和稳定性。简单易用的 MQTT X 测试工具结合高效可靠的 EMQX 物联网消息服务器,将帮助物联网开发者构建更具竞争力的物联网平台和应用。 --- ### 339. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT X:EMQ推出的全新跨平台MQTT桌面客户端 杭州映云科技有限公司(EMQ)为MQTT用户带来了一款独特的桌面客户端工具——MQTT X。作为一款高度集成且用户友好的桌面应用程序,MQTT X在MQTT客户端领域中脱颖而出,成为了目前市场上最具吸引力的选项。 为什么选择MQTT X? 跨平台性:无论你使用的是macOS、Linux还是Windows,MQTT X都能为你提供一致的用户体验。这得益于其基于Electron的跨平台技术。 直观的交互界面:MQTT X模仿了消息聊天软件的交互形式,使得消息收发变得简单直观。更妙的是,它允许用户在多个客户端连接间自由切换,从而轻松进行互相通信。 全面的功能:无论是MQTT/TCP、MQTT/TLS、还是MQTT/WebSocket,MQTT X都能完美支持。不仅如此,它还包括了多种MQTT协议特性的测试功能。 核心功能亮点: 完整支持MQTT v3.1.1以及MQTT v5.0协议。 SSL认证:涵盖CA、自签名证书,并支持单双向SSL认证。 三种主题切换:包括Light、Dark和Night。 多语言支持:简体中文和英文双语界面。 高级消息格式:支持Hex、Base64、JSON和Plaintext格式。 订阅Topic:用户可以为不同的Topic自定义颜色标记,点击已订阅的topic则可进行消息过滤。 保存并选择MQTT服务器信息:方便用户在多个MQTT服务器间切换。 想要深入了解或下载MQTT X? 访问官方网站MQTT X官网或直接在MQTT X GitHub下载。 这款客户端工具,不仅仅是为了美观而设计,它通过提高MQTT开发和测试的效率,真正为用户带来了实实在在的价值。 Mosquitto:开源MQTT消息代理及其CLI工具 Mosquitto,一款备受赞誉的开源消息代理(遵循EPL/EDL许可证),是MQTT领域的重要玩家。除了作为一个消息代理,Mosquitto还默认提供了两个极具价值的命令行MQTT客户端工具:mosquitto_pub 和 mosquitto_sub。 为什么选择Mosquitto CLI? 丰富的配置选项:Mosquitto CLI不仅支持TLS证书连接和代理服务器连接,还提供了debug模式。在debug模式下,你可以获得更多、更详细的消息信息,帮助你更好地理解和调试。 简便的使用:使用Mosquitto CLI极其简单。在默认设置下,只需要提供少量参数即可开始使用。例如: 订阅主题并开启DEBUG模式: $ mosquitto_sub -t "testtopic/#" -d 发布消息至指定主题: mosquitto_pub -t "testtopic/1" -m "Hello, GetIoT.tech" Mosquitto的核心特性: 轻量级命令行工具:占用极低的系统资源,特别适合硬件资源受限的设备。 强大的debug模式:对于开发者和调试人员来说,这是一个非常有用的特性。 多种连接方式:支持加密及非加密连接,确保数据安全性。 远程服务器测试:Mosquitto CLI可以轻松地在远程服务器上进行测试,方便开发和维护。 获取Mosquitto: 官方GitHub项目地址:Github Mosquitto 下载和更多信息:Mosquitto官网 选择Mosquitto意味着选择一个高效、可靠和安全的MQTT消息代理及其相关工具。无论你是MQTT新手还是专家,Mosquitto都是你的理想选择。 MQTT.fx:全能MQTT客户端工具 MQTT.fx,由Jens Deters独立开发的MQTT客户端, 已成为验证与IoT Hub服务交互的首选工具。尽管采用了Apache License 2.0协议,但该工具并未公开源码。 为什么选择MQTT.fx? 权威背书:MQTT.fx被大型云服务供应商,如Azure IoT Hub、AWS IoT和阿里云IoT等推荐使用。 多功能特性:从保存多个连接配置,支持多种TCL加密和证书,到专门为Mosquitto设计的Broker状态可视化功能,MQTT.fx无疑是功能最为全面的MQTT客户端。 强大的脚本功能:用户可利用Nashorn Engine通过JavaScript访问Java方法,从而编写测试脚本、模拟传感器数据等。 关键功能亮点: 预定义消息模板:快速和方便地发送标准消息。 系统主题:通过$SYS订阅,实时获取Broker状态。 JavaScript支持:利用Nashorn Engine扩展功能。 日志显示:实时监控连接日志。 跨平台:完美适应Windows、MacOS和Linux环境。 然而,每款软件都有其局限性。因JavaFX的开发和Java虚拟机的限制,MQTT.fx在某些老旧机器上可能会有些许卡顿。此外, 目前MQTT.fx不支持WebSocket,这可能会限制其在某些测试场景中的应用。 开始使用MQTT.fx: 无论你是MQTT新手还是专家, MQTT.fx都能满足你的需求。下载并体验其丰富功能: 点击下载MQTT.fx 选择MQTT.fx, 为你的IoT项目引入强大的MQTT客户端工具。 MQTT Explorer: 领先的MQTT桌面测试客户端 MQTT Explorer,作为当前最受欢迎的MQTT桌面测试客户端之一,为用户带来了全新的MQTT Topics体验。其简洁的界面和高度的可自定义性为所有MQTT爱好者提供了一个直观的操作平台。此外,MQTT Explorer基于CC BY-NC-ND 4.0协议开源,确保每位用户都能自由查看源码和使用。 为何MQTT Explorer是您的首选? 无与伦比的可视化能力:该工具能够动态预览和展示Topics的结构化变化,使您能够在瞬间洞察整个MQTT Broker的运行状况。 独特的垂直分层展示:与其他MQTT客户端显著不同的分层视图,带来更高效的交互体验。 高级的消息管理:不仅可以自定义订阅以筛选消息,还提供了对收到的payload消息的差异对比视图,使您能够更容易地分析和诊断问题。 功能亮点: 动态的Topics预览:随时查看Topic和其变化。 消息管理:简单地删除、搜索、过滤和发布Topics。 差异视图:快速比较当前和以前的消息。 主题切换:根据个人喜好,选择Dark/Light主题。 历史记录:针对每个Topic,保存完整的消息历史。 但需注意,MQTT Explorer目前仅支持创建一个客户端连接,无法同时在线多客户端连接。 开始您的MQTT探索之旅: MQTT Explorer为MQTT测试带来了创新和便捷。立即下载并体验其强大功能: 点击下载MQTT Explorer 无论您是MQTT新手还是老手,MQTT Explorer都是您不容错过的工具。 MQTT Box: 跨平台的MQTT客户端利器 MQTT Box,由Sathya Vikram开发,最初作为Chrome浏览器拓展而生,如今已蜕变为一款跨平台的独立桌面软件。该工具凭借Electron跨平台技术,简洁的用户界面和强大的功能,迅速赢得了众多用户的喜爱。 为何选择MQTT Box? 超强的兼容性:从Chrome OS到Linux、macOS和Windows,无论您使用哪种操作系统,MQTT Box都能完美适配。 简洁直观的界面:多客户端同时在线,尽管切换有待优化,但依然能为您带来流畅的体验。 强大的连接功能:无论是传统的MQTT连接,还是MQTT over WebSocket,甚至多种TCP加密方式,MQTT Box都能轻松应对。 出色的历史记录管理:保存发送和订阅的消息历史,支持复制、粘贴,让数据管理更加高效。 性能测试功能:简单易用,通过图表可视化展示Broker的负载,助您快速分析。 立即体验MQTT Box: MQTT Box,集简洁、功能和兼容性于一身,是您不可或缺的MQTT客户端工具。 [点击查看项目源码](GitHub MQTTBox) 马上下载MQTT Box 与众不同的MQTT客户端体验,只在MQTT Box。 mqtt-spy: MQTT的开发调试新宠 深入了解mqtt-spy,这款与Eclipse Paho和Eclipse IoT紧密相连的工具。无需繁琐的安装流程,只需拥有Java 8及JavaFX,简单启动JAR文件即可体验它带来的丰富MQTT发布/订阅机制。 为何选择mqtt-spy? 免安装即用:虽需Java环境,但它确实减少了额外安装的麻烦,提供了直接的使用体验。 初学者友好:启动引导功能使MQTT新手也能轻松探索,无障碍连接公共MQTT Broker。 多功能界面:界面设计虽稍显复杂,但一旦熟悉,你会发现它是你的开发调试得力助手。 灵活交互:无论是MQTT还是MQTT over WebSocket, 还是能够在不同的选项卡中连接多个Broker,mqtt-spy都能游刃有余。 强大的搜索和记录功能:从查找常用MQTT消息到输出订阅/发布消息,mqtt-spy都为你考虑周到。 虽然它在性能和稳定性上还有待提高,但作为Beta版的新产品,我们相信mqtt-spy会更上一层楼。 赶快试用mqtt-spy: mqtt-spy是您的MQTT开发调试新选择,体验一键启动,强大功能的魅力。 [点击查看项目源码](GitHub mqtt-spy) 立即下载mqtt-spy 开启你的MQTT之旅,与mqtt-spy同行。 MQTT Lens: Chrome的简洁MQTT工具 MQTT Lens,一个专为Chrome设计的拓展工具,为你提供了一个简单而纯粹的MQTT体验。仅需几次点击,你就可以在Chrome网上应用商店中找到并安装它,轻松开始你的MQTT之旅。 为什么选择MQTT Lens? 无需繁琐安装:作为Chrome拓展,安装简单,随时随地享受MQTT服务。 极简界面:清晰的发布、订阅和消息查看界面,让你在短时间内轻松上手。 颜色关联:同时与多个MQTT服务器建立连接,并通过不同颜色进行区分,使操作更为直观。 全面支持:无论是基础的MQTT还是MQTT over WebSocket,MQTT Lens都能完美支持。 简单、直观,MQTT Lens正是初学者或希望快速验证MQTT应用的最佳工具。 立即体验MQTT Lens: 轻松连接,简单操作,MQTT Lens为你提供最佳的MQTT体验。 [点击此处下载MQTT Lens](Chrome Web Store) 探索MQTT的世界,让MQTT Lens成为你的指南。 MQTT WebSocket Toolkit: 在线MQTT客户端测试的新选择 MQTT WebSocket Toolkit,一款为MQTT爱好者设计的在线客户端测试工具,不仅简化了MQTT测试,还提供了无与伦比的便捷性。全在线操作,让你无需安装任何应用,即可快速进入MQTT世界。 Toolkit的亮点有哪些? 全在线操作:直接访问,无需下载或安装,随时随地享受MQTT服务。 专注WebSocket连接:完美支持MQTT over WebSocket连接,满足现代开发需求。 消息聊天交互:沿用MQTT X风格,聊天式的交互方式,让MQTT消息收发变得轻松有趣。 多客户端支持:可同时创建多个客户端连接,保留设置至下次访问,帮你节省宝贵时间。 短小、精悍,MQTT WebSocket Toolkit为你提供最佳的在线MQTT测试体验。 立即体验MQTT WebSocket Toolkit: 在线、轻便、高效,MQTT WebSocket Toolkit等待你的探索。 [直接访问MQTT WebSocket Toolkit](MQTT WebSocket Toolkit) [查看源码](MQTT WebSocket Toolkit GitHub) 开始你的MQTT在线测试之旅,让MQTT WebSocket Toolkit为你导航。 --- ### 340. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 网址:MQTT.fx® 5.0 – 软刀片 (softblade.de) 随着物联网技术的飞速发展,机器间的通信变得越来越重要。在这个日益互联的世界中,我们需要强大而灵活的工具来实现设备之间的通信和数据交换。MQTT.fx® 5.0就是这样一款工具,它不仅为您提供了最新的MQTT 5.0协议支持,还增加了一系列令人兴奋的功能,让您更轻松地构建智能应用程序。 通信的桥梁 MQTT.fx® 5.0是一款多功能的MQTT客户端,旨在为开发人员、物联网部门和爱好者提供一种简单而强大的方式,与各种设备进行通信。不管您是构建智能家居系统、监控工业设备还是开发物联网原型,MQTT.fx® 5.0都可以成为您的得力助手。 以下是MQTT.fx® 5.0升级中包含的一些主要特性: 连接配置文件: 提供了经纪人连接的连接配置文件,使您能够轻松管理多个连接。 临时连接: 允许您创建临时连接,快速进行通信,无需繁琐的配置。 安全性: 支持用户名/密码验证,并提供SSL/TLS支持,确保通信的安全性。 发布和订阅: 支持通配符模式和主题历史记录的全面发布和订阅功能。 预定义消息存储: 可以存储和管理预定义的消息,方便重复使用。 Rhino Engine脚本: 提供了“发布”和“订阅”的脚本接口,增强了自动化能力。 $SYS主题评估: 支持对mosquitto和HiveMQ等$SYS主题进行评估,获得更多信息。 日志控制台: 提供详细的日志信息,帮助您监控和调试通信。 HTTP代理支持: 支持HTTP代理,以满足特殊网络环境的需求。 原生安装包: 提供适用于所有平台(Windows、MacOS、Linux)的本地安装包,提高了跨平台使用的便捷性。 定期更新/错误修复: 我们会定期提供更新和修复,以确保MQTT.fx®保持最新状态。 启动时检查更新: 在应用程序启动时,自动检查是否有可用的更新版本。 HiveMQ MQTT-Clients集成: 集成HiveMQ MQTT-Clients,以全面支持MQTT 5.0协议。 发布的消息: 提供了消息的“用户属性”编辑器,以及消息载荷的“内容类型”定义和选择。 接收的消息: 显示消息的“用户属性”、返回码和原因码(如果消息中存在)、以及消息载荷的内容类型。 自动选择有效的载荷解码器: 基于内容类型,自动选择适当的载荷解码器来显示消息的载荷。 此次升级的重点是提高灵活性和可配置性,使MQTT.fx®成为与机器通信的首选工具。新的Mime-Type特性允许您在消息中识别文件类型,从而使通信更具适应性。MQTT.fx® 5.0能够自动根据消息的内容类型搜索并应用相应的载荷解码器,包括Json、XML和ini等格式,从而进一步提高了通信的灵活性。 功能强大,操作简单 MQTT.fx® 5.0的强大功能让您能够轻松地管理和监控设备之间的通信。以下是一些突出的功能: 连接配置文件 MQTT.fx® 5.0提供了连接配置文件,让您可以轻松管理多个经纪人连接。无论您需要连接几台设备还是数百台设备,配置文件功能都能让您事半功倍。 安全性 在物联网时代,数据安全至关重要。MQTT.fx® 5.0支持用户名和密码验证,并提供SSL/TLS支持,确保您的通信是安全的。 发布和订阅 MQTT.fx® 5.0支持全面的发布和订阅功能,包括通配符模式和主题历史记录。这意味着您可以根据需要轻松地发布和获取数据,无论是一次性操作还是持续监控。 脚本支持 对于开发人员来说,MQTT.fx® 5.0提供了Rhino Engine脚本接口,允许您自动化发布和订阅操作。这意味着您可以编写脚本来处理复杂的通信任务,提高工作效率。 自定义消息 MQTT.fx® 5.0允许您存储和管理预定义的消息,这样您就可以轻松地重复使用它们。这对于发送常用命令或配置信息非常有用,可以节省大量时间。 日志和代理支持 MQTT.fx® 5.0提供了详细的日志控制台,帮助您监控和调试通信。此外,它还支持HTTP代理,以适应各种网络环境的需求。 自动更新 不必担心是否有新版本可用,MQTT.fx® 5.0会在应用程序启动时自动检查并提供更新,确保您始终使用最新的功能和修复。 灵活的载荷解码 MQTT.fx® 5.0引入了全新的Mime-Type功能,使您能够根据消息中的文件类型来自动选择适当的载荷解码器。这意味着您可以更灵活地处理不同格式的数据,包括Json、XML和ini等。 构建智能世界 MQTT.fx® 5.0将成为连接智能世界的桥梁。不管您是开发人员、工程师还是物联网爱好者,它都将为您提供强大的工具,帮助您构建智能应用程序,实现设备之间的无缝通信。让MQTT.fx® 5.0成为您的物联网工具箱中的一员,探索无限可能性,连接未来世界。 结语 MQTT.fx® 5.0是一款功能丰富、易于 使用的MQTT客户端,为您提供了最新的MQTT 5.0协议支持和许多令人印象深刻的功能。不论您是专业开发人员还是物联网爱好者,它都将为您的项目提供强大的支持。立即下载MQTT.fx® 5.0,开始连接智能世界的旅程! --- ### 341. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT Explorer是一款全面的MQTT客户端工具,它提供了对MQTT主题的结构化概述,并使与代理上的设备/服务的工作变得非常简单。本文将深入探讨MQTT Explorer的功能和如何使用它来管理和监视MQTT主题。 MQTT Explorer | An all-round MQTT client that provides a structured topic overview (mqtt-explorer.com) MQTT Explorer的特点 MQTT Explorer提供了一系列功能,使您能够轻松管理MQTT主题,包括: **可视化主题和主题活动:**MQTT Explorer以直观的方式显示主题层次结构和主题活动,让您一目了然地了解您的MQTT网络。 **删除保留主题:**您可以方便地删除保留的MQTT主题,以确保您的代理保持整洁。 **搜索/筛选主题:**MQTT Explorer允许您快速搜索和筛选主题,以快速定位您感兴趣的内容。 **递归删除主题:**不仅可以删除单个主题,还可以递归删除主题的子主题,帮助您更轻松地管理主题。 **消息差异视图:**MQTT Explorer提供了当前和先前接收到的消息的差异视图,以帮助您追踪消息的更改。 **发布主题:**您可以使用MQTT Explorer轻松地发布主题,与其他设备进行通信。 **绘制数字主题:**如果您有数字主题,MQTT Explorer还提供了绘制功能,可将数据可视化。 **历史记录:**MQTT Explorer会保留每个主题的历史记录,以便您查看以前的消息。 **深色/浅色主题:**它支持深色和浅色主题,以适应您的个人喜好。 MQTT Explorer的用途 MQTT Explorer旨在成为MQTT的瑞士军刀,是集成新服务和物联网设备到您的网络的完美工具。以下是一些使用MQTT Explorer的典型场景: **物联网应用程序开发:**MQTT Explorer可以帮助开发人员轻松管理和监视物联网设备之间的通信,以确保顺畅的数据交换。 **家庭自动化:**如果您在家庭自动化项目中使用MQTT协议,MQTT Explorer将是您的得力助手,让您轻松控制和监视各种设备。 **开源物联网平台:**许多开源物联网平台(如Home Assistant和OpenHAB)使用MQTT协议进行通信。MQTT Explorer是与这些平台集成的理想工具。 **MQTT代理管理:**如果您管理一个MQTT代理,MQTT Explorer将帮助您轻松地管理主题和监视代理的运行状况。 下载和安装 MQTT Explorer可以在多个平台上使用,包括Windows、macOS和Linux。您可以从官方网站或应用商店(如Mac App Store)下载和安装它。此外,MQTT Explorer还支持可移植版本,您可以随身携带它。 --- ### 342. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 简介:MQTTX是一款由EMQ开源的跨平台MQTT 5.0客户端工具,它为开发人员提供了便捷的方式来测试、调试和探索MQTT连接。MQTT是一种轻量级的消息传输协议,特别适用于物联网设备和低带宽、高延迟或不稳定网络环境。本文将详细介绍MQTTX的功能和如何使用它来进行MQTT开发和测试。 MQTTX的主要功能: 跨平台兼容性:MQTTX支持macOS、Linux和Windows操作系统,确保了在不同平台上的一致性体验。 直观的用户界面:MQTTX采用了聊天界面的设计,使其更加友好和易于使用。 多客户端连接支持:您可以轻松创建和管理多个同时在线的MQTT客户端连接,模拟多设备通信。 支持多种MQTT协议特性:MQTTX支持MQTT/TCP、MQTT/TLS、MQTT/WebSocket等多种协议,适用于不同的应用场景。 MQTT消息格式化:MQTTX允许您格式化MQTT消息负载,以便更清晰地查看和理解消息内容。 安装MQTTX:MQTTX可以通过多种方式安装,包括macOS App Store、Homebrew(仅macOS)、Snap Store(仅Linux)和GitHub发布版。您可以根据自己的操作系统和喜好选择合适的安装方式。在安装后,您可以启动MQTTX并开始使用它。 连接到MQTT Broker:在使用MQTTX之前,您需要配置连接到MQTT Broker。您可以选择使用EMQX Cloud提供的公共MQTT 5.0 Broker进行测试,或在本地部署EMQX以获得更多控制权。 配置连接信息:在MQTTX的左侧菜单栏中,点击“+”按钮以创建一个新的MQTT连接。在连接配置中,您需要提供以下信息: Host(主机):MQTT Broker的主机名或IP地址。 Port(端口):MQTT Broker的端口号(默认为1883)。 Username(用户名):(可选)用于身份验证的用户名。 Password(密码):(可选)用于身份验证的密码。 Client ID(客户端ID):客户端的唯一标识符,通常由MQTTX自动生成。 建立连接:在配置连接信息后,点击右上角的“连接”按钮,MQTTX将尝试与MQTT Broker建立连接。如果连接成功,您将准备好开始进行MQTT测试。 MQTT Publish和Subscribe测试:连接成功后,您可以使用MQTTX执行以下操作: 发布消息:选择一个已经建立的连接,点击“发布”按钮,填写主题和消息内容,然后点击“发布”以发送消息。 订阅主题:选择一个已经建立的连接,点击“订阅”按钮,填写要订阅的主题,然后点击“订阅”以接收来自该主题的消息。 查看消息:在连接的聊天窗口中,您可以查看已发布和已订阅的消息,以及格式化后的消息负载。 与EMQX更配:MQTTX设计初衷是与EMQX MQTT Broker更好地配合使用。EMQX提供了云服务和本地部署选项,让您轻松创建和管理MQTT Broker,以便与MQTTX一起使用。您可以通过EMQX Cloud获得14天的免费试用,或立即在本地下载EMQX Broker。 --- ### 343. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、简介 Mica-MQTT是一个基于Java AIO实现的开源组件,旨在提供简单易用、低延迟、高性能的百万级MQTT客户端和物联网Broker服务。它更容易集成到现有服务中,降低自主开发物联网平台的成本。 二、使用场景 Mica-MQTT适用于多种场景,包括但不限于: 物联网云端MQTT Broker 边缘设备之间的消息通信 群组类即时通讯 消息推送 简单易用的MQTT客户端 三、优势 Mica-MQTT的主要优势包括: 简单易用,功能强大 易于二次开发和扩展 高性能,支持百万级连接 四、功能 Mica-MQTT提供了丰富的功能集,包括但不限于: 支持MQTT v3.1、v3.1.1和v5.0协议 支持WebSocket MQTT子协议(兼容mqtt.js) 支持HTTP REST API,详细文档请参见[1] 提供MQTT客户端库 提供MQTT服务端 支持MQTT客户端和服务端的共享订阅 支持MQTT遗嘱消息 支持MQTT保留消息 支持自定义消息处理和转发 提供阿里云MQTT客户端连接示例 支持GraalVM编译成本机可执行程序 快速集成到Spring Boot项目(使用mica-mqtt-spring-boot-starter) 支持与Prometheus和Grafana对接 基于Redis Pub/Sub实现集群,详细信息请参见mica-mqtt-broker模块[2] 五、依赖 Spring Boot项目 客户端依赖 <dependency> <groupId>net.dreamlu</groupId> <artifactId>mica-mqtt-client-spring-boot-starter</artifactId> <version>${mica-mqtt.version}</version> </dependency> 客户端配置示例 mqtt: client: enabled: true # 是否开启客户端,默认:true ip: 127.0.0.1 # 连接的服务端 IP,默认:127.0.0.1 port: 1883 # 端口,默认:1883 name: Mica-Mqtt-Client # 客户端名称,默认:Mica-Mqtt-Client clientId: 000001 # 客户端ID(通常为设备SN,不可重复) user-name: mica # 认证用户名 password: 123456 # 认证密码 timeout: 5 # 超时时间(秒),默认:5秒 reconnect: true # 是否自动重连,默认:true re-interval: 5000 # 重连时间(毫秒),默认:5000毫秒 version: mqtt_3_1_1 # MQTT协议版本,可选MQTT_3_1、mqtt_3_1_1、mqtt_5,默认:mqtt_3_1_1 read-buffer-size: 8KB # 接收数据的缓冲区大小,默认:8KB max-bytes-in-message: 10MB # 消息解析的最大字节数,默认:10MB buffer-allocator: heap # 内存分配器(堆内存或堆外内存),默认:堆内存 keep-alive-secs: 60 # Keep-Alive时间(秒) clean-session: true # MQTT Clean Session,默认:true ssl: enabled: false # 是否开启SSL认证,2.1.0版本开始支持双向认证 keystore-path: # 可选参数:SSL双向认证的密钥库路径,支持classpath:/路径。 keystore-pass: # 可选参数:SSL双向认证的密钥库密码 truststore-path: # 可选参数:SSL双向认证的信任库路径,支持classpath:/路径。 truststore-pass: # 可选参数:SSL双向认证的信任库密码 客户端监听示例 @Service public class MqttClientConnectListener { private static final Logger logger = LoggerFactory.getLogger(MqttClientConnectListener.class); @Autowired private MqttClientCreator mqttClientCreator; @EventListener public void onConnected(MqttConnectedEvent event) { logger.info("MqttConnectedEvent: {}", event); } @EventListener public void onDisconnect(MqttDisconnectEvent event) { // 在客户端离线时更新重连时的客户端ID、用户名和密码 logger.info("MqttDisconnectEvent: {}", event); mqttClientCreator.clientId("newClient" + System.currentTimeMillis()) .username("newUserName") .password("newPassword"); } } 自定义客户端配置示例(可选) @Configuration(proxyBeanMethods = false) public class MqttClientCustomizerConfiguration { @Bean public MqttClientCustomizer mqttClientCustomizer() { return new MqttClientCustomizer() { @Override public void customize(MqttClientCreator creator) { // 在此处可以自定义配置,会覆盖YAML配置 System.out.println("----------------MqttServerCustomizer-----------------"); } }; } } 客户端订阅示例 @Service public class MqttClientSubscribeListener { private static final Logger logger = LoggerFactory.getLogger(MqttClientSubscribeListener.class); @MqttClientSubscribe("/test/#") public void subQos0(String topic, byte[] payload) { logger.info("topic: {} payload: {}", topic, new String(payload, StandardCharsets.UTF_8)); } @MqttClientSubscribe(value = "/qos1/#", qos = MqttQoS.AT_LEAST_ONCE) public void subQos1(String topic, byte[] payload) { logger.info("topic: {} payload: {}", topic, new String(payload, StandardCharsets.UTF_8)); } @MqttClientSubscribe("/sys/${productKey}/${deviceName}/thing/sub/register") public void thingSubRegister(String topic, byte[] payload) { // 1.3.8版本开始支持,@MqttClientSubscribe注解支持${}变量替换,默认替换为+ // 注意:Mica-MQTT会先从Spring Boot配置中替换参数${},如果存在配置将优先被替换。 logger.info("topic: {} payload: {}", topic, new String(payload, StandardCharsets.UTF_8)); } } 共享订阅Topic说明 Mica-MQTT客户端支持两种共享订阅方式: 共享订阅:订阅前缀使用$queue/,多个客户端订阅了$queue/topic,当有消息发布到topic时,只有一个客户端会接收到消息。 分组订阅:订阅前缀使用$share/<group>/,组内的客户端订阅了$share/group1/topic、$share/group2/topic等,当有消息发布到topic时,每个组内只有一个客户端会接收到消息。 MqttClientTemplate使用示例 import net.dreamlu.iot.mqtt.spring.client.MqttClientTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @Service public class MainService { private static final Logger logger = LoggerFactory.getLogger(MainService.class); @Autowired private MqttClientTemplate client; public boolean publish() { client.publish("/test/client", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); return true; } public boolean sub() { client.subQos0("/test/#", (context, topic, message, payload) -> { logger.info(topic + '\t' + new String(payload, StandardCharsets.UTF_8)); }); return true; } } 2. 服务端依赖 <dependency> <groupId>net.dreamlu</groupId> <artifactId>mica-mqtt-server</artifactId> <version>${mica-mqtt.version}</version> </dependency> 2.1 服务端使用 // 注意:为了能够接受更多连接(降低内存占用),请添加JVM参数 -Xss129k MqttServer mqttServer = MqttServer.create() .ip("0.0.0.0") // 服务端IP,默认为空(0.0.0.0),建议不要设置 .port(1883) // 端口,默认:1883 .readBufferSize(512) // 读缓冲区大小,默认:512字节 .maxBytesInMessage(1024 * 100) // 最大包体长度,默认:8092 .authHandler((clientId, userName, password) -> true) // 自定义认证 .messageListener((context, clientId, message) -> { logger.info("clientId: {} message: {} payload: {}", clientId, message, new String(message.getPayload(), StandardCharsets.UTF_8)); }) // 消息监听 .bufferAllocator(ByteBufferAllocator.HEAP) // 内存分配器,默认:堆内存 .heartbeatTimeout(120_1000L) // 心跳超时时间,默认:120秒 .useSsl("", "", "") // SSL配置 .connectStatusListener(new IMqttConnectStatusListener() { @Override public void online(String clientId) { // 客户端上线时的处理逻辑 } @Override public void offline(String clientId) { // 客户端离线时的处理逻辑 } }) // 自定义客户端上下线监听 .messageDispatcher(new IMqttMessageDispatcher() { @Override public void config(MqttServer mqttServer) { // 配置消息分发 } @Override public boolean send(Message message) { // 发送消息 return false; } @Override public boolean send(String clientId, Message message) { // 发送消息给指定客户端 return false; } }) // 自定义消息转发,可使用MQ广播实现集群处理 .debug() // 开启调试信息日志 .start(); // 发送消息给指定客户端 mqttServer.publish("clientId", "/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 发送消息给所有在线监听这个Topic的客户端 mqttServer.publishAll("/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8)); // 停止服务 mqttServer.stop(); 六、默认端口 以下是Mica-MQTT的默认端口: MQTT TCP端口:1883 HTTP和WebSocket端口:8083 这些端口用于不同的通信协议和服务。 请注意,上述示例代码可能需要根据你的具体需求进行调整和扩展。如果需要更多信息或帮助,请随时提问。 --- ═══════════════════════════════════════════ ## 智慧养殖 ═══════════════════════════════════════════ ### 344. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案背景: 随着我国养猪业的迅速发展,行业面临着一线从业人员逐渐减少、投资者和养殖者收益需求增加的挑战。这使得养殖规模和方式发生了巨大变化,物联网管理系统应运而生。通过自动化、信息化、智能化的手段,农业养殖实现了标准化生产、规模化经营,以科技支撑农业发展,助力养殖行业创新发展,帮助养殖户实现省时增收。 方案介绍: 猪舍环控系统是为了解决猪舍内环境管理难题而设计的智能化解决方案。通过传感器采集猪舍内空气温湿度、氨气含量、二氧化碳浓度等数据,当环境参数达到预设危险值时,系统通过电话、微信等多种方式告警用户,实现猪舍环境的及时监测和预警。智能猪舍架构设计包括环境监测、视频监控、智能联动等模块,通过实时数据采集和远程控制,实现猪舍环境的智能化管理。监控云平台提供了用户友好的界面,支持多种控制方式,为养殖者提供了便捷的管理体验。 方案组成: 环境监测设备:包括空气温湿度传感器、氨气、二氧化碳传感器等,用于实时采集猪舍内环境数据 控制设备:如风机、窗帘机、加热器等,通过智能控制系统实现对猪舍内环境的自动调控。 监控云平台:提供实时数据查看、设备管理控制、历史数据查看等功能,为养殖者提供便捷的管理方式。 联动控制:根据环境数据及用户设定的条件,实现智能联动控制,如自动调节风机、湿帘等设备,确保猪舍内环境处于最佳状态。 方案功能: 实时监测预警:对猪舍内空气温湿度、氨气含量、二氧化碳浓度等环境参数进行实时监测,并实现预警功能。 自动调控:根据环境数据及用户设定,自动控制风机、加热器等设备,确保猪舍内环境处于适宜状态。 远程控制:通过监控云平台,实现对猪舍内设备的远程监控和控制,随时随地进行管理。 历史数据查看:提供历史环境数据的查看功能,帮助用户分析猪舍内环境变化趋势,为决策提供参考。 设备清单 自动化设备: 环境监测传感器: 总结 猪舍环控系统通过智能化管理和自动化控制,提高了养猪环境的质量和管理效率,为养殖者带来了更高的生产效益和经济收益。 --- ### 345. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案介绍 养殖控制器是一种基于物联网技术的智能化环境监控与控制系统,旨在为养殖场提供全方位的环境管理和设备控制解决方案。该系统可以实时监测养殖环境的温度、湿度、二氧化碳浓度等参数,并通过智能算法进行分析和调控,保障养殖环境的稳定性和舒适性,提高养殖效率和产出品质。 方案组成 传感器节点: 包括空气温湿度传感器、二氧化碳传感器等,用于实时采集养殖环境参数数据。 2.数据采集与传输模块: 负责将传感器节点采集到的数据传输至控制中心,采用4G、WiFi等方式进行数据传输。 3.控制中心: 该中心是整个系统的核心,负责数据的接收、处理和分析,以及控制指令的下发。 具备数据存储和处理能力,可以实现历史数据查询和统计分析。 4.执行设备: 根据控制中心的指令,控制各种设备的运行,如风机、加热器、喷灌系统等。 5.用户界面: 提供Web端和手机App,用户可以通过界面实时查看养殖环境数据、设备运行状态,并进行远程控制和管理。 方案功能 实时监测: 实时监测养殖环境的温度、湿度、二氧化碳浓度等参数,保障养殖环境的稳定性。 智能控制: 根据预设的控制算法,智能调节各种设备的运行状态,实现养殖环境的智能化管理。 远程管理: 用户可以通过手机App或Web端随时随地远程监控和管理养殖场的运行状态,提高管理效率。 报警功能: 当养殖环境出现异常情况时,系统会自动发出报警,提醒用户及时处理,保障养殖场的安全运行。 历史数据分析: 系统具备数据存储和分析功能,可以对历史数据进行统计分析,为养殖决策提供参考依据。 综上所述,该养殖控制器系统能够为养殖场提供全方位的智能化环境管理和设备控制服务,提高养殖效率、降低成本、保障产品质量,具有广阔的应用前景和市场潜力。 --- ═══════════════════════════════════════════ ## 智慧农业 ═══════════════════════════════════════════ ### 346. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案背景 农业生产中,重大病虫害对农作物产量和质量造成严重威胁。为解决这一问题,农作物重大病虫智慧监测预警平台应运而生。该平台通过业务线上化、植保数据仓构建等方式,实现了一体化数据采集服务和综合决策分析,为农作物病虫害防控提供了重要支持。 方案介绍 平台主要围绕监测预警、植物检疫、药政管理等业务科室展开,集成智能虫情测报、昆虫性诱、田间调查等数据,通过专业的对比分析和可视化数据专题分析,实现了数据共享和智能决策提升。 方案组成 智能硬件设备:包括智能虫情测报灯等,通过无公害诱捕杀虫、定时采集现场图像等功能,实现对病虫害的实时监测和数据采集。 云平台:接收和存储来自硬件设备的数据,并进行对比分析和可视化展示,为农业决策提供数据支持。 植保数据仓:整合农业生产经营主体、农资企业等数据资源,实现一体化数据填报和业务贯通,提高数据采集和管理效率。 方案功能 病虫害监测预警:实时监测农田病虫情况,及时发出预警信息,帮助农民制定防治方案。 植物检疫:追踪重点检疫性有害生物,加强防控工作,防止疫情扩散。 药政管理:展示农药生产、使用和废弃情况,推动农药管理的数字化进程。 方案应用 农作物重大病虫智慧监测预警平台在农业生产中有着广泛而深远的应用,涉及到以下几个具体方面: 田间监测与预警:平台通过智能虫情测报灯等设备,实时监测田间病虫情况,对重大病虫害进行预警。农民可以及时了解田间状况,采取相应的防治措施,有效减少病虫害造成的损失。 植物检疫管理:平台密切关注本省重点检疫性有害生物,如亚洲梨火疫病、柑橘黄龙病、红火蚁等。通过五色图、数据列表、折线图等多种形式展示各市县疫情发生和防治情况,及时介入防控,防止疫情扩散。 药政管理:平台数字化展示各地市农药生产、使用和废弃包装回收情况和相关数据,推动药政管理的数字化进程。农业主体可以及时了解农药的生产和使用情况,促进农药的合理使用和废弃物的安全处理。 智慧决策支持:平台整合了农作物病虫害数字化监测预警系统、智能监测预警系统、昆虫性诱测报系统等八个信息化系统和数据资源。通过对比分析和可视化数据展示,为农业决策提供了科学依据和智能化支持。 远程诊断与管理:平台通过智能虫情测报灯等硬件设备,实现了对虫情的远程监测和诊断。农业专家可以随时远程了解田间虫情状况,制定防治措施,提高了防治的科学性和精准性。 该方案广泛应用于农业生产领域,涵盖农田、农资企业、植保工程等多个方面,为农业生产提供全方位的数据支持和智能化服务。 方案亮点 智能化监测:利用智能硬件设备实现对病虫害的精准监测和诊断,提高了监测预警水平。 数据共享:打通系统间数据壁垒,实现数据共享,提高了数据利用效率。 综合决策:通过专业的对比分析和可视化数据展示,为农业决策提供了科学依据。 智慧管理:整合了监测预警、植物检疫、药政管理等多个业务科室,实现了一体化数据采集和管理服务。 以上是针对农作物重大病虫智慧监测预警平台的整体方案描述,旨在提供全面的农业生产支持和智能化服务。 --- ### 347. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 背景 随着人工成本的增加,工程施工布线的成本也日益上升,这使得有效管理传感器设备,降低基础设施投资成本成为企业急需解决的问题。在这种背景下,WiFi温湿度监测解决方案应运而生。该方案以WiFi作为信号传输媒介,利用温湿度传感器作为监测终端,将采集到的温度和湿度数据上传到云平台,用户可以通过手机或电脑实时查看监测数据,从而实现了远程监测与管理,大大降低了施工量和施工成本,同时也避免了传统布线中可能出现的接线错误的隐患。 方案概述 WiFi温湿度监测解决方案由以下几个主要组成部分构成: 温湿度传感器:采集环境中的温度和湿度数据,并将其转换为数字信号。 WiFi模块:作为信号的传输媒介,将传感器采集到的数据通过WiFi网络上传至云平台。 云平台:接收和存储传感器上传的数据,并提供数据分析、图表展示等功能。用户可以通过手机或电脑随时随地访问云平台,实时查看监测数据。 手机/电脑应用:用户通过安装专用应用或通过网页浏览器,可以方便地查看温湿度监测数据,设置报警阈值,接收异常报警通知等。 应用场景 WiFi温湿度监测解决方案适用于以下场景: 机房:保障服务器和网络设备的稳定运行,防止硬件损坏和数据丢失。 楼宇:提供舒适的办公环境,提高员工的工作效率。 宾馆:保障客房内的空气质量,提升客户满意度。 图书馆:保护图书和档案的保存环境,防止湿度过高导致纸质资料损坏。 档案室:确保档案的长期保存和安全。 优势与收益 成本节约:无需布线,大大降低了施工成本和维护成本。 方便快捷:通过手机或电脑即可实时监测数据,随时随地掌握环境状况。 高效管理:设定报警阈值,及时发现异常情况,减少损失。 数据分析:通过云平台提供的数据分析功能,优化环境管理策略,提高效率。 总结 WiFi温湿度监测解决方案以其便捷、高效、成本节约等优势,在多个场景下得到了广泛应用。随着人工成本不断上涨和工程施工布线成本的增加,该解决方案将成为企业提高管理效率、降低成本的重要工具之一。 --- ### 348. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智能玻璃温室整体方案 随着现代科技的不断发展,智能玻璃温室作为农业生产的一种创新模式,正在逐渐受到人们的关注和青睐。智能玻璃温室通过融合先进的玻璃材料、智能控制技术以及现代农业种植理念,实现了对温室内环境的精准调控,提高了农作物的生长质量和产量。本文将介绍一种智能玻璃温室的整体方案,旨在为农业生产提供更加高效、智能的解决方案。 背景 传统的温室种植存在着环境控制不精准、资源利用不充分等问题,为此,智能玻璃温室应运而生。智能玻璃温室利用先进的玻璃材料,如光学玻璃、光热转换玻璃等,结合智能控制系统,实现对温室内温度、湿度、光照等环境参数的精准调控,从而提高农作物的生长速度和品质。 与传统温室相比,智能玻璃温室具有以下优点: 高效节能智能玻璃温室可以通过自动控制系统,根据温室内部的温度、湿度、天线等环境参数,对温室内部的采暖、通风、通风等系统进行定制控制,从而提高能源利用效率,降低生产成本。智能玻璃温室还可以采用太阳能、风能等可再生能源作为辅助能源,进一步提高能源利用效率,减少环境污染2.精准控制智能玻璃温室可以通过传感器、物联网等技术,实时采集温室内部的环境数据,并进行自定义分析,从而对温室内部的温度、湿度、天线、空中浓度等环境参数进行精准控制,为作物提供生长大概的环境条件。智能玻璃温室还可以根据作物的不同生长阶段,对环境参数进行动态调整,满足作物生长的不同需求。3、提高产量在自动化控制的环境下,作物可以获得更大的生长条件,从而提高产量和质量。智能玻璃温室还可以通过病虫害监测预警系统,及时发现和防治病虫害,减少农作物损失。 降低劳动强度智能玻璃温室可以通过自动化控制系统,实现对温室内部的灌溉、施肥、采收等阶段的自动化管理,减少劳动强度,提高生产效率。5、降低环境影响智能玻璃温室可以通过自动化控制系统,减少化肥、农药的使用量,降低对环境的影响。6.提高农业生产水平 整体方案 1. 温室设计与材料选择 智能玻璃温室的设计应考虑温室结构的稳固性、采光性以及隔热性。选择优质的玻璃材料,如光学玻璃和光热转换玻璃,能够最大程度地吸收和利用太阳能,提高温室内的光照强度和温度,促进作物生长。 2. 智能控制系统 智能玻璃温室应配备智能控制系统,实现对温室内环境的实时监测和精准调控。该系统可监测温室内的温度、湿度、光照等参数,并根据作物的生长需求,自动调整温室内的通风、遮阳、灌溉等设备,保持良好的生长环境。 3. 节能环保设施 智能玻璃温室应配置节能环保设施,如太阳能发电系统、雨水收集系统等,实现对能源和水资源的有效利用。太阳能发电系统可为温室提供清洁能源,减少对传统能源的依赖;雨水收集系统可收集雨水用于温室的灌溉,减少对地下水资源的开采。 4. 数据监测与分析 智能玻璃温室应配置数据监测与分析系统,实时监测温室内环境参数的变化,并对监测数据进行分析和统计,为农业生产提供科学依据。通过对温室内环境和作物生长情况的分析,可以及时调整温室的运行参数,提高农作物的产量和品质。 结语智能玻璃温室作为一种新型的农业生产模式,具有节能环保、高效稳定等优势,对于提高农业生产效率、保障粮食安全具有重要意义。未来,随着智能技术的不断发展和应用,智能玻璃温室将会得到更广泛的应用,为农业产业的可持续发展做出更大的贡献 总的来看,智能玻璃温室是一种具有节能、精准控制、提高产量、减少劳动强度、降低环境影响等优点的现代化农业生产设施。 智能玻璃温室的应用,可以提高农业生产的科技含量和现代化水平,推动农业生产方式的转型升级。 总的来看,智能玻璃温室是一种具有节能、精准控制、提高产量、减少劳动强度、降低环境影响等优点的现代化农业生产设施。 --- ### 349. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 项目介绍江苏鸿山葡萄示范园,坐落于无锡市,是一座集经济作物种植、休闲农业和采摘体验农业于一体的现代化综合园区。然而,长期种植导致土壤养分不足,制约了葡萄产量的提升,甚至呈现回落趋势。为解决土壤养分缺失的难题,提高作物产量,经营者决定引进水肥一体化系统,以实现土壤养分的精准供给和作物健康生长。 项目需求原有的净水喷灌系统虽然能实现自动水分补给,但仍需依靠人工施肥来维持土壤养分。高昂的人工成本使得施肥间隔拉长,土壤养分流失,作物产量受损。因此,园区急需一套水肥一体化系统,以降低施肥成本、实现水分养分同步灌溉,保障土壤健康和作物产量。 解决方案我们提出的水肥一体化系统方案如下: 智能化改造:在保留原有灌溉管网的基础上,对灌溉首部系统进行智能化改造。关键设备增加:增加智能水肥一体机、过滤器、施肥桶、水泵变频控制柜等设备,实现水肥一体化系统建设。成本节约:节约改造成本,同时保证系统功能完善,提高使用效率。 项目效果提高产量与质量:通过科学、精准的水肥供应,减少人工管理不当所导致的减产,提高作物的产量和质量。减少环境污染:水肥一体化系统减少了化肥施用过度,降低了土壤、水质污染,响应了绿色可持续发展的呼吁。降低经营成本:智能化水肥灌溉减少了人工施肥成本支出,同时降低了肥料浪费,帮助园区管理者更好地控制经营成本。通过水肥一体化系统的引入,鸿山葡萄示范园将迎来更加繁荣的未来,实现经济效益与环境友好的双赢局面。 --- ### 350. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 温室大棚环境监测控制系统是一种利用物联网技术和传感器技术对温室大棚内部环境进行实时监测和控制的智能化系统。通过采集温室内部的温度、湿度、光照强度、CO2浓度、土壤温湿度以及土壤电导率等数据,系统可以实现对温室环境的全面监测,并通过智能控制主机对温室内部的设备进行自动控制,以确保作物的生长环境处于最佳状态,提高产量和品质,同时降低能源和资源的消耗。 2. 系统组成 2.1 传感器节点 多功能百叶盒气象传感器:用于监测温室内部的温度、湿度、光照强度、大气压力、噪声、PM2.5和PM10、CO2等多种参数,具有精准度高、稳定性好、安装方便等特点。 土壤温湿度传感器:用于监测土壤的温度和湿度,可以长期埋入土壤中进行监测,具有耐腐蚀、防水等特点。 土壤电导率传感器:用于监测土壤的电导率,可以反映土壤的盐分含量,对于土壤盐碱化的预防和治理具有重要意义。 2.2 智能监控主机 监控主机:作为系统的核心控制单元,负责接收传感器节点上传的监测数据,并通过RS485、以太网或GPRS等方式上传至监控平台。同时具有液晶显示屏、数据存储和报警功能,可以实现对温室内部环境的实时监测和控制。 2.3 软件平台 监控平台:提供实时曲线、历史曲线、数据记录等功能,可通过电脑或手机实时查看温室内部环境数据,并在数据异常时进行声光报警和远程短信报警。 云平台:将监测数据上传至云端,实现对温室环境的24小时不间断监测,并提供数据导出、远程web访问等功能,方便用户随时随地查看和管理温室环境。 3. 系统特点 全面监测:系统覆盖了温室内部的各项关键参数,可以全面监测温室环境的变化。 智能控制:通过智能监控主机对温室内部设备进行自动控制,实现温室环境的精细调节。 远程监控:用户可以通过监控平台随时随地查看温室环境数据,及时发现和处理异常情况。 报警功能:系统具有声光报警和远程短信报警功能,在环境异常时能够及时通知相关责任人员进行处理。 可扩展性:系统采用模块化设计,传感器节点和监控主机均支持多种通信方式,可以根据用户需求进行灵活扩展和定制。 4. 应用场景 温室大棚环境监测控制系统可广泛应用于农业、园艺、畜牧业等领域,特别适用于需要特殊环境要求的大棚种植和养殖场所。通过实时监测和智能控制,可以提高作物的产量和品质,降低能源和资源的消耗,实现生态环境的可持续发展。 5. 结语 温室大棚环境监测控制系统是一种集成了物联网、传感器和智能控制技术的先进系统,可以实现对温室环境的精细监测和智能控制,为农业生产提供了科学的依据和技术支持。相信随着技术的不断发展和应用,温室大棚环境监测控制系统将在农业生产中发挥越来越重要的作用,为人类的粮食安全和生态环境保护做出积极贡献。 --- ### 351. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着现代农业技术的快速发展,智能化在农业生产中的应用变得日益重要。特别是在食用菌产业中,由于其种植过程复杂、对环境要求极为严格,传统的种植方法已难以满足高效率和高产量的需求。基于此背景,MQTT物联网技术被引入到食用菌的养殖过程中,旨在通过科学化、标准化、现代化及智能化的管理手段,显著提升食用菌的产量和品质。 系统概述 MQTT物联网菌菇养殖智能监控系统是一个专为菌菇生产温室大棚、厂房设计的全程智能化控制解决方案。该系统通过精准控制菇房内的温度、湿度、二氧化碳浓度等关键环境因素,以满足食用菌在不同生长阶段的特定需求,从而创造出最适宜的生长环境。这一智能化控制显著提高了食用菌的生产效率和产品质量。 核心功能与技术 环境监测与调控 智能环境传感器:采集空气温度、湿度、二氧化碳浓度等数据,确保环境参数的实时监控。 菌菇基质监测:通过专用传感器监测菌菇基质的营养状况,优化菌菇的生长环境。 环境调控设备:包括制冷、加湿、通风、光照等设备,根据传感器数据自动调节环境条件,保障菌菇的健康生长。 通信技术 MQTT物联网平台:利用4G、无线WIFI通讯技术,实现设备的远程控制和监控数据的实时传输,确保信息交互的高效性和稳定性。 智能控制柜 数据采集与处理:连接环境调控设备,采集智能传感器的数据,内置人工智能算法和PLC智能逻辑控制功能,实现环境条件的自动调节。 人机交互界面:提供大尺寸组态屏,支持实时环境数据查看和手动控制,优化用户操作体验。 控制策略与优势 控制策略 自动控制:根据食用菌生长阶段自动调整环境条件,无需人工干预。 手动/远程控制:支持现场手动控制和通过MQTT物联网平台的远程控制,提高操作灵活性。 集中监控:实现对多个菇房环境的集中管理,简化监控流程,提升管理效率。 系统优势 提高产量与品质:通过精确控制生长环境,大大提升食用菌的产量与品质,满足市场高端需求。 节省人工成本:24小时的自动监控与控制减少了对人工的依赖,特别是在环境调节和疾病预防上,降低了大量的劳动力成本。 智能化生产:利用先进的物联网技术,实现生产过程的智能化,从基质准备到菌菇收获的每一步都可通过数据分析优化,提升生产效率。 可靠性增强:系统采用稳定的通讯技术确保数据传输的可靠性,同时,智能控制柜和环境调控设备的高质量构造减少了故障率,保障了生产的连续性。 远程监控与管理:通过手机APP或监控中心平台,无论身处何地,生产者都能实时掌握菇房内的环境信息及设备运行状态,及时调整生产策略,实现真正的指尖上的农业管理。 应用场景 MQTT物联网菌菇养殖智能监控系统适用于不同规模的菌菇生产企业,从小型家庭式菌菇房到占地数千亩的大型菌菇生产基地。该系统尤其适合需要精细化管理和追求高产出高品质的现代农业生产模式。 结语 随着人们对食品安全和品质的日益重视,传统的食用菌生产方式已逐渐不能满足市场需求。MQTT物联网菌菇养殖智能监控系统的出现,为食用菌产业带来了革命性的改变。通过高度的自动化与智能化管理,不仅提高了生产效率和产品质量,还实现了生产过程的科学化和数据化,为食用菌产业的可持续发展奠定了坚实的基础。随着技术的不断进步和应用的不断拓展,未来的菌菇养殖将更加智能、高效和环保,为消费者提供更安全、更优质的食用菌产品。 --- ### 352. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 在现代农业生产中,利用智能技术优化温室大棚的管理变得尤为重要。MQTT物联网智能玻璃温室大棚系统集成了多种监测和控制系统,实现了农业生产的高度机械化和智能化,从而提高农业经济模式的工厂化水平,优化盈利和回报。 系统概述 MQTT物联网智能玻璃温室大棚系统包括: 环境监测系统:利用工业级物联网传感器监测空气温湿度、光照度、CO2浓度等,数据通过有线485或无线LORA方式传输至云平台。 土壤墒情监测系统:通过土壤温湿度、pH、EC传感器监测土壤条件,指导精细化灌溉。 遮阳系统:自动根据光照度和室内温湿度调整,有效管理光照和室内气候。 通风管理系统、湿帘降温系统:自动调节大棚内气流和温度,保持适宜的生长环境。 水肥系统:实现精准灌溉和施肥,优化资源使用。 补光系统、CO2调控系统:根据作物需求调节光照和CO2浓度,促进生长。 视频监控系统:实时监控大棚内部状况,提高管理效率。 系统特点 全方位监控与调控:覆盖从环境到土壤的各个方面,确保作物生长环境的最佳状态。 高度自动化与智能化:通过MQTT物联网平台实现自动化控制,减少人力需求,提高管理效率。 数据驱动的决策支持:收集和分析数据,为生产决策提供科学依据。 易于操作的监控平台:支持手机APP、PC端和LED显示等多种监控方式,实现数据的实时监控和管理。 操作与控制 远程控制:用户可以通过手机app或电脑监控平台查看环境数据并手动控制设备。 现场手动控制:现场触摸屏和手动按键为紧急或特殊情况提供操作手段。 自动控制工艺:根据作物生产工艺自动调整大棚内环境,实现全生命周期的智能管理。 监控平台 多维度监控展示:实现实时数据监控,视频画面查看,以及数据动态展示。 数据管理与分析:提供数据记录、报表导出和设备管理功能,优化生产过程。 报警与通知:通过多渠道报警通知机制,确保及时响应异常情况。 用户权限管理:灵活的账号管理支持多用户操作,满足不同角色的管理需求。 结语 MQTT物联网智能玻璃温室大 棚系统通过集成高度先进的监测与控制技术,实现了对温室大棚的全方位智能化管理。这一系统不仅提高了农业生产的效率和可控性,还为实现高效、可持续的现代农业提供了强有力的技术支持。通过优化此文,我们更清晰地展示了系统的组成、特点及其在智能农业中的重要应用,突出了MQTT物联网技术在现代农业中的核心作用。 --- ### 353. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、引言 在现代农业生产中,利用高科技手段对大棚进行精准管理成为提高产量和质量的关键。特别是塑料薄膜温室大棚,因其轻便、成本低廉、结构遮光率小和使用寿命长等优点,被广泛应用于各种作物的栽培。然而,为了实现温室大棚的集中管理和环境条件的精确调控,需要采用先进的监控系统。 二、MQTT物联网智能薄膜连栋大棚监控系统简介 MQTT物联网智能薄膜连栋大棚监控系统基于先进的物联网技术,集成了现代化的传感器终端、通讯技术、控制终端、环境调控设备和监控平台。该系统能够实现对温湿度、水肥、光照等关键环境参数的实时监测和自动调控,优化作物生长条件,提高作物产量和质量。 三、系统组成和工作原理 环境监测传感器:包括CO2浓度、光照度、空气温湿度和土壤温湿度传感器,实现对大棚内环境的全方位监测。 环境调控设备:涵盖外遮阳系统、内遮掩系统、内保温系统、湿帘风机强制通风降温系统、顶部通风系统、供暖系统和配电/控制系统,根据传感器数据自动调节大棚内环境。 智能控制柜:通过采集传感器数据,并利用内置的智能算法和MQTT物联网通讯协议,智能控制柜可以迅速做出精准的控制决策,自动调节环境控制设备,以保持大棚内的环境条件最适宜作物生长。控制柜支持RS485有线和无线LORA通信方式,确保数据传输的高效和稳定。 MQTT物联网监控平台:平台不仅实时展示大棚内的环境参数,还允许管理人员远程调整控制策略,进行数据分析和决策支持。平台的大数据和边缘计算能力,可以处理来自多个大棚的海量数据,实现智能预警和生产流程优化。 四、系统特点和优势 精准的环境控制:通过高精度传感器和自动调控设备,系统能够精确调整大棚内的光照、温湿度、CO2浓度等关键参数,为作物生长创造理想条件。 高效的资源利用:智能调控系统能够优化水肥使用和能源消耗,降低生产成本,提高资源利用效率。 远程监控和管理:MQTT物联网平台支持远程监控和操作,使得大棚管理更加便捷,减少人力成本。 数据驱动的决策支持:平台收集和分析的大数据为作物的生产工艺优化提供科学依据,实现精准农业。 五、应用场景和效益 MQTT物联网智能薄膜连栋大棚监控系统适用于各种规模的现代农业生产,包括蔬菜、花卉、药材等多种作物的栽培。通过实现精细化管理,该系统不仅可以显著提高作物的产量和质量,还可以有效应对极端天气带来的风险,保障农业生产的稳定性和可持续发展。 六、结语 随着物联网技术的不断进步和应用拓展,MQTT物联网智能薄膜连栋大棚监控系统将成为现代农业不可或缺的工具。通过高度集成化和智能化的解决方案,它能够有效提升农业生产的自动化和智能化水平,带来更高的经济效益和环境效益。 --- ═══════════════════════════════════════════ ## 智慧城市 ═══════════════════════════════════════════ ### 354. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智慧消防物联网整体方案通过结合传感器技术、网络通信和数据分析,实现了消防系统的智能化和自动化,提高了火灾检测和应急响应的效率和准确性,为建筑物和人员的安全提供了更可靠的保障。将传统的消防设施与互联网连接起来,实现消防信息的实时消防、消防互联互通,从而提高消防系统的标准化水平,提升消防安全管理效率。该方案主要包括以下内容几个方面: 1. 开采层 感知层是智慧消防物联网方案的基础,负责采集各种消防数据。常用的消防物联网传感器包括: 烟感梯度:检测火灾产生的烟雾。 温感吸收:检测火灾产生的热量。 烟雾/火焰传感器: 安装在建筑物各个关键区域,及时检测到烟雾或火焰的存在,并向系统发送警报信号。 温度/气体传感器: 监测建筑内外的温度和气体浓度变化,提前发现潜在的火灾风险。 一氧化碳吸附:检测火灾产生的有毒气体。 喷水灭火系统:检测火灾并启动喷水系统。 探测器火焰系统:检测火灾并启动探测器气体系统。 应急广播系统:在火灾发生时播放疏散广播。 视频监控系统: 结合摄像头和智能分析算法,实现对建筑物内外的实时监控,提供远程视觉监控和火灾识别功能。 2. 传输层 传输层负责将采集层采集到的数据传输到云端平台。常用的无线通信网络技术包括: NB-IoT:具有低功耗、广覆盖、亮点的特点,适用于大规模物联网应用。 LoRa:具有距离长、照射力强、亮度高的特点,适用于室外环境应用。 Wi-Fi:具有传输速率高、覆盖范围广的特点,适用于室内环境应用。 3.云端平台 云端平台负责消防数据的存储、分析和管理,并提供各种服务,例如: 实时消防信息监测:可以实时监控消防设施的状态,并及时发现火灾隐患。 火灾风险预警:可以根据消防数据分析火灾,并及时发布火灾预警。 应急调度指挥:在火灾发生时,可以为消防人员提供应急指挥调度服务。 管理:可以对消防设施进行统一管理,提高维护消防设施的保障消防效率。 无线传输技术: 利用物联网技术将传感器数据传输到云端或局域网,以确保数据的实时性和准确性。 云端存储与处理: 将传感器数据上传到云平台进行存储和分析,提供远程访问和数据管理功能。数据加密与备份: 对传感器数据进行加密传输和存储,确保数据的安全性和可靠性,同时定期进行数据备份,以应对突发情况。 4. 应用层 应用层为用户提供各种消防服务,例如: 手机APP:用户可以通过手机APP查看消防设施状态、接收火灾预警信息、查询火灾逃生营地等。 消防控制中心:消防控制中心可以监控局部所有消防设施的状态,并及时做出应急反应。 消防管理部门:管理部门可以利用云端平台对全市消防消防工作进行管理。 智能消防管理系统: 基于云端数据分析,实现对消防设备的远程监控、故障诊断和预警功能。 消防预警应用: 提供消防预警和紧急响应的移动应用程序,向用户发送实时警报和应急指导。 自动灭火系统: 结合传感器和智能控制技术,实现自动启动灭火装置并定向释放灭火剂。 智能逃生指引: 基于建筑结构和消防设备位置信息,提供灵活、个性化的逃生路线指引,帮助人员安全疏散。 5、系统优势 智慧消防物联网方案具有以下优势: 提升消防预警能力:可以有效提高火灾预警的准确性和及时性,减少火灾造成的损失。 提高消防营销效率:可以为消防人员提供实时信息支持,提高消防灭火的效率。 降低消防管理成本:可以减少消防巡检的人工成本,提高消防管理效率。 改善消防安全环境:可以有效降低火灾发生率,改善消防安全环境。 6、应用案例 智慧用电安全管理 电气火灾成因 智慧用电安全管理系统 智慧用电安全管理系统基于NB-IoT和LoRa等无线通讯技术,能够实时监测线缆温度、电流、漏电流和故障电弧等参数。系统通过分析这些数据,判断故障原因及其发展趋势,及时预警并处理潜在的电气火灾隐患,避免重大电气安全事故的发生。 应用场景 智慧烟感监测系统 传统烟感报警器的痛点 传统独立式烟雾报警器功能单一,仅能发出声光报警,无法解决火灾发生时无人应对的问题。同时,传统烟感报警器的质量参差不齐,存在电池没电等隐患,难以满足现代消防安全管理的需求。 智慧烟感监测系统 智慧烟感监测系统采用NB-IoT无线通讯技术,实现了超低功耗、长距离数据传输和实时监控。系统通过智能CPU控制,能够准确判断火灾产生的烟雾,并将报警信息实时发送至云端后台管理服务器,实现与智能云平台的报警联动。 智能气体监测系统 监测原理与功能 智能气体监测系统通过气体探测器连续监测室内燃气浓度,当检测到泄漏浓度达到设定值时,系统会发出光报警信号,并切断气源。系统还能够将报警信息同步至用户手机和APP,实现远程监控和管理。 应用场景 智能水压、水位监测系统 监测功能与优势 智能水压、水位监测系统通过NB-IoT和LoRa等无线通讯技术,实时监测室内消火栓状态、消火栓管道压力、自动喷淋系统水压和高位消防水箱水位等参数。系统能够动态、立体地反映消防水源的状态,为消防安全管理提供有力支持。 防火门监测系统 防火门的重要性 防火门是消防通道的重要组成部分,其正常开启和关闭关系到火灾发生时人员的疏散和救援。然而,防火门的状态往往难以实时监测和管理,存在一定的安全隐患。 防火门监测系统 防火门监测系统通过磁传感器实时监测防火门的开闭状态,并在防火门被异常开启或关闭超时时发出报警信号。系统能够通过电话、短信和邮件等方式通知相关人员,确保防火门始终处于正常状态。 应用场景 防火门监测系统适用于各类建筑物的消防通道和防火门。系统能够确保防火门的正常使用,提升消防安全管理水平,保障人员的安全疏散。 火眼监测系统 火灾自动识别与报警 火眼监测系统基于普通监控视频,通过人工智能和计算机视觉技术,实时识别火灾发生时的烟雾和火焰形态。在火灾初期,系统能够在1秒内发出报警信号,帮助快速扑灭火灾,避免灾情扩大。 应用场景 火眼监测系统适用于各类场所的消防监控。通过复用现有监控设备,系统能够实现高效的火灾监测和报警,有效提升消防应急响应能力。 未来展望 随着物联网技术的发展,智慧消防物联网方案将更加完善,为用户提供更加安全、可靠的消防服务。未来,智慧消防物联网方案与其他定制技术相结合,实现消防安全管理更加智能化。 --- ### 355. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智能停车物联网整体方案是一种利用物联网技术来优化和管理停车场的解决方案。它结合了传感器、网络通信、数据分析和应用软件,旨在提高停车场的利用率、减少拥堵、改善用户体验,并提供更高效的管理方式。以下是一个简单的智能停车物联网整体方案的介绍: 1. 传感器技术 车位检测传感器: 安装在每个停车位上,用于检测车辆的存在和停放情况。这些传感器可以是地磁传感器、摄像头或其他类型的传感器,能够实时监测车辆的停放状态。 采用各种物联网传感器来检测停车位的占用情况,例如: 地磁传感器:安装在地面,通过检测车辆产生的磁场变化来判断是否占用停车位。 探针传感器:通过发射探针脉冲来检测车辆的存在。 图像视频传感器:通过摄像头来分析图像信息,判断停车位是否被占用。 环境监测传感器: 监测停车场周围的环境因素,如空气质量、温度和湿度等。这些数据有助于提供更好的停车体验,并且可以帮助管理者更好地了解停车场周边环境状况。 2. 网络通信 物联网连接设备: 将传感器和停车场管理系统连接到互联网。可以使用无线技术如Wi-Fi、蓝牙或LPWAN(低功耗广域网)等来实现数据传输。 将传感器收集的数据通过无线通信网络传输到云端平台。常用的无线通信网络技术包括: NB-IoT:具有低功耗、广覆盖、亮点的特点,适用于大规模物联网应用。 LoRa:具有距离长、照射力强、亮度高的特点,适用于室外环境应用。 Wi-Fi:具有传输速率高、覆盖范围广的特点,适用于室内环境应用。 云平台: 将传感器数据上传到云端进行存储和分析。云端平台能够处理大量数据,并提供实时监控和分析功能,为停车场管理者提供决策支持。 云端平台负责对停车场数据进行存储、分析和管理,并提供各种服务,例如: 实时停车位信息查询:用户可以通过手机APP或其他方式查询停车场的实时停车位信息。 导航引导:用户可以通过手机APP或其他方式获取停车场内的导航信息,车辆引导至空闲的停车位。 滞纳费:用户通过手机APP或其他方式可以滞纳金。 停车场管理:停车场管理人员可以通过云端平台对停车场进行管理,例如查看停车场实时情况、生成停车数据报表等。 3. 数据分析与应用软件 停车场管理系统: 基于云端数据分析,实现停车场内车位的实时监测、车辆定位、停车指引等功能。管理系统可以通过手机App或网页进行访问,用户可以实时查看停车位的情况并预约车位。 智能导航应用: 提供驾驶员导航到可用停车位的功能。通过手机App或车载导航系统,用户可以实时了解停车场的拥堵情况和可用停车位的位置,从而更快地找到合适的停车位。 4. 用户体验和管理优化 移动支付: 支持手机支付或其他电子支付方式,方便用户停车缴费,减少停车排队时间。 实时数据监控: 管理人员可以通过管理系统实时监控停车场的使用情况,并根据需求进行调整和优化停车场布局。 数据分析与优化: 利用数据分析工具,对停车场的使用情况进行统计和分析,帮助管理者做出更好的决策,提高停车场的利用率和效益。 停车位预订:用户可以通过手机APP提前预订停车位。 车位地址:用户可以通过手机APP快速找到最近的空闲停车位。 无感支付:用户通过注册免密支付方式,驶入停车场后撤出停车费,系统会自动扣费 5、系统优势 智能停车物联网方案具有以下优势: 提高停车场效益:通过实时监测停车位信息,可以有效提高停车场资源的利用率。 缓解停车难现象:可以帮助产权人找到快速空闲停车位,减少停车时间,缓解城市停车现象难点。 降低停车场运营成本:可以减少停车场的人工管理成本,提高停车场运营效率。 改善城市交通环境:可以减少道路交通拥堵,改善城市交通环境。 应用案例 智能停车物联网方案已在众多城市落地应用,例如: 北京:在北京的一些大型停车场,已经安装了智能停车系统,可以为用户提供实时停车信息车位查询、导航引导、停车费等服务。 上海:上海正在积极推广智能停车物联网方案,预计到2022年,上海将建成1000个智能停车场。 杭州:杭州已建成一张覆盖全市的大型智能停车网,用户可以通过手机APP查询全市范围内的停车位信息。 未来展望 随着物联网技术的发展,智能停车物联网方案将更加完善,为用户提供更加便捷、高效的停车服务。未来,智能交通停车物联网方案与其他智能系统相结合,实现交通管理更加标准化。 智能停车物联网整体方案通过将传感器、网络通信和数据分析技术结合起来,为停车场提供了更智能、更高效的管理方式,既可以提升用户体验,又可以优化停车场的运营效率。 --- ### 356. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智能路灯的物联网方案是基于物联网技术实现对路灯进行智能监控和管理的解决方案。以下是一个智能路灯物联网方案的基本架构和关键要素: 1. 智能路灯节点 智能路灯节点是安装在路灯上的装置,通常包括LED灯具、传感器和通信模块。传感器可以包括光敏传感器、温度传感器、运动传感器等,用于感知环境变化和收集数据。通信模块可以采用无线技术,如Wi-Fi、蓝牙、LoRa等,或者有线技术,如Ethernet,用于与中心控制器或云平台进行数据交互。 2. 网络连接 智能路灯节点通过网络连接与中心控制器或云平台通信,实现远程监控和控制。网络连接可以是基于无线技术的,如Wi-Fi、蜂窝网络(3G/4G/5G)、LoRa等,也可以是基于有线技术的,如Ethernet。选择适合场景的网络连接方式可以根据需求和成本考量。 3. 中心控制器 中心控制器是智能路灯系统的核心,负责接收和处理来自各个路灯节点的数据,并根据预设的策略进行灯光控制和管理。中心控制器可以是一个专用的硬件设备,也可以是运行在云端的软件平台。通过中心控制器,用户可以实现对路灯的远程监控、故障诊断、灯光调节等功能。 4. 数据处理与分析 智能路灯系统通过对传感器数据的处理和分析,实现对路灯的智能化管理和优化。例如,根据光照强度和路况情况,自动调节灯光亮度;通过统计分析车流和行人流量,优化路灯亮灭时段。数据处理和分析可以在中心控制器或云平台上进行,以实现实时监控和智能决策。 5. 应用服务和用户界面 智能路灯系统通常提供应用服务和用户界面,方便用户进行系统管理和监控。用户可以通过手机App、Web界面或者专用软件平台,实现对路灯的远程控制、故障报警、能耗统计等功能。应用服务和用户界面的设计应简洁易用,满足用户的需求和操作习惯。 6. 安全和隐私保护 在智能路灯系统的设计和实施过程中,安全性和隐私保护是非常重要的考虑因素。系统需要采取有效的安全措施,保护通信数据的机密性和完整性,防止恶意攻击和数据泄露。同时,需要遵守相关的隐私法规和标准,保护用户的个人信息和隐私权益。 综上所述,智能路灯的物联网方案结合了硬件设备、网络连接、数据处理和应用服务等多个方面,通过智能化的照明管理和优化,提升了城市的能源利用效率和居民的生活质量。 --- ### 357. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智慧图书馆整体方案 1. 概述 智慧图书馆是利用先进的物联网技术、人工智能和大数据分析等手段,将传统图书馆转变为智能化、数字化的信息服务中心。它不仅提供传统的图书借阅服务,还拓展了多种数字资源的获取渠道,提升了用户体验和服务效率。 2. 方案组成 产品介绍 智能图书柜: 提供自助借阅、归还功能,实现24小时无人值守服务。 智能检索系统: 基于人工智能技术,实现图书检索、推荐等智能化功能。 数字资源平台: 提供电子书籍、期刊、论文等多种数字资源,支持在线阅读和下载。 产品特点 智能化服务: 用户可以通过手机App或触摸屏等界面实现自助借阅、归还、图书检索等功能。 多样化资源: 不仅提供纸质书籍,还整合了丰富的数字资源,满足用户多样化的阅读需求。 3. 工作原理 用户通过智能终端(如手机App或触摸屏)选择借阅图书或检索资料,系统根据用户需求进行推荐或检索,并提供相关资源的位置信息。用户自行取书或阅读电子资源,归还图书时将书籍放入智能图书柜,系统自动更新借阅记录。 4. 方案优势 提升服务效率: 自助借还、智能检索等功能提高了图书馆服务效率,减少了用户等待时间。 丰富资源获取: 不仅提供纸质图书,还整合了大量数字资源,拓展了用户获取信息的渠道。 智能化管理: 借助大数据分析,图书馆可以更好地了解用户阅读偏好,优化资源配置和服务策略。 5. 应用场景 高校图书馆: 为师生提供丰富的学术资源和便捷的借阅服务。 社区图书馆: 为社区居民提供便捷的图书借阅服务,促进阅读文化的普及。 6. 典型案例 某大学图书馆智能化改造: 引入智能图书柜、数字资源平台等设备,提升了图书馆的服务水平和管理效率。 7. 发展趋势 智能化升级: 随着技术的发展,智慧图书馆将更加智能化,引入更多先进技术提升服务水平。 用户体验优化: 不断改进界面设计、服务流程,提升用户体验和满意度。 8. 结论 智慧图书馆整体方案通过引入智能设备、数字资源平台等手段,将传统图书馆转变为数字化、智能化的信息服务中心,为用户提供更便捷、丰富的阅读体验,同时提升了图书馆的管理效率和服务水平。 --- ### 358. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在迅速演变的工业4.0格局中,数字化转型已成为寻求在互联技术时代和数据驱动洞察力中蓬勃发展的企业成功的基石。工业物联网(IIoT)位于这场转型的核心,赋予行业革命化运营、提高效率和开辟创新新途径的能力。 然而,在工业领域,特别是在IIoT领域,开展数字化转型之旅需要战略性的方法和周密的规划。从明确目标到应对技术整合和数据管理的复杂性,过程中的每一步都需要仔细考虑和专家指导。 在本高级指南中,我们将深入探讨推动工业4.0和物联网成功数字化转型项目的关键策略和最佳实践。无论您是工业领域的资深专业人士还是IIoT领域的新手,本文将为您提供所需的知识和洞见,以应对挑战并抓住工业4.0带来的机遇。 让我们探索利用IIoT力量推动组织在数字创新时代向前发展的关键步骤。从评估当前能力到培养持续改进的文化,让我们踏上一条通往可持续增长和数字时代竞争优势的转型之旅。 在工业领域,尤其是在物联网(IIoT)的背景下,推动成功的数字化转型项目涉及几个关键步骤。以下是结构化的方法。 明确目标和范围在任何数字化转型项目中,包括涉及IIoT和物联网的项目,明确目标和范围是一个至关重要的初始步骤。以下是如何有效执行的一些关键建议: 理解业务目标和挑战:从深入了解组织的总体业务目标和面临的具体挑战开始。确定痛点以及数字化转型可以解决这些挑战并有助于实现战略目标的领域。 参与利益相关者:让组织中的高管、部门负责人、IT专业人员和最终用户等关键利益相关者参与目标设定过程。这是让每个人都参与数字化转型项目的关键。从利益相关者那里收集关于他们的痛点、优先事项和对数字化转型计划的期望结果的见解。 设定SMART目标:确保目标具体、可衡量、可实现、相关且有时间限制(SMART)。具体:明确定义您希望通过数字化转型项目实现的目标。可衡量:建立用于跟踪进展和评估成功的指标或关键绩效指标(KPI)。可实现:在资源、技术和时间表的限制内设定现实和可行的目标。相关:将目标与整体业务战略和优先事项保持一致。时间限制:为实现目标定义明确的时间线和截止日期。 优先级目标:认识到并非所有目标可能同样重要或紧急。根据其对业务成果和组织战略优先事项的潜在影响,优先考虑目标。您可以将目标分为以下类别: 必须有 有则更好 稍后再探索 在确定优先级时,考虑诸如投资回报率(ROI)、成本节约、收入增长、客户满意度和竞争优势等因素。 定义范围和责任:明确界定数字化转型项目的范围,包括将涉及的系统、流程、部门和利益相关者。确定项目的界限,以防止范围蔓延并确保集中执行。确定项目中每个利益相关者的责任。在定义范围时考虑可扩展性和灵活性,以适应未来的增长和业务需求的变化。 记录目标和范围:在正式的项目章程或文件中记录数字化转型项目的目标和范围。向所有利益相关者明确沟通目标和范围,以确保一致性和共同理解。使用图表、流程图或思维导图等视觉辅助工具有效说明目标和范围。 迭代和完善:认识到随着项目的进展和新见解的出现,目标和范围可能会发展。通过定期审查和根据反馈、吸取的教训以及业务需求的变化来完善目标和范围,培养持续改进的文化。 通过遵循上述步骤,组织可以有效地为其数字化转型项目定义明确的目标和范围,为成功执行和具体的业务成果奠定基础。 评估当前状态和识别差距评估当前状态和识别差距是数字化转型项目中的关键阶段。您可以从收集有关组织当前技术基础设施、流程和能力的的数据和信息开始。这可能包括系统、应用程序、硬件、软件、网络、网络安全要求和数据源。此外,通过访谈关键利益相关者——包括高管、部门负责人、IT人员和最终用户——以获得对现有工作流程、痛点和改进领域的洞察。为了帮助您,您可以采用结构化的方法,包括以下步骤: 执行SWOT分析:进行SWOT(优势、劣势、机会、威胁)分析,以评估组织在数字化转型目标方面的当前优势和劣势。识别利用技术解决劣势和利用优势的机会,同时考虑潜在的威胁和挑战。 评估技术格局:评估组织的当前技术格局,包括现有的IT系统、应用程序和基础设施。评估现有技术在满足数字化转型计划要求方面的兼容性、可扩展性和性能。识别可能对转型工作构成障碍的任何遗留系统或过时技术。 评估流程效率和有效性:评估现有的业务流程和工作流程,以识别低效、瓶颈和优化领域。分析信息、数据和任务在部门和系统间的流动,以识别自动化、简化和整合的机会。 审查数据管理实践:评估组织的数据管理实践,包括数据收集、存储、处理和分析。评估跨系统和部门的数据质量、一致性和可访问性。识别可能妨碍有效决策和洞察力生成的任何数据孤岛、冗余数据源或数据治理问题。 考虑安全性和合规性:评估组织的网络安全姿态和数据隐私实践,以识别潜在的漏洞和合规性差距。评估现有安全措施在保护敏感数据和防御网络威胁方面的有效性。确保遵守相关法规和标准,如GDPR、HIPAA或行业特定要求。 必要时聘请外部专家:考虑聘请外部顾问、技术合作伙伴或行业专家提供公正的评估和专业专长。利用他们的洞察力和经验来识别盲点、验证发现,并获得解决差距和挑战的建议。 记录发现和差距分析:记录评估阶段的发现,包括优势、劣势、机会和威胁,以及具体的缺口和改进领域。使用矩阵、图表或图表等视觉辅助工具有效地说明差距分析,并促进与利益相关者的沟通。 结论通过彻底评估当前状态并识别差距,组织可以获得有关需要关注和投资的领域的宝贵见解,因为他们开始数字化转型之旅。这为制定针对性和有效的转型路线图奠定了基础,该路线图解决了关键优先事项并提供了可衡量的商业价值。 --- ### 359. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、概述: 智慧井盖是一种集成了多项先进技术的智能化并盖管理系统,旨在提高城市基础设施的安全性和管理效率。通过安装传感器、通信模块等设备,实现对井盖状态的实时监测、预警和远程控制,为城市安全管理提供全面支持。 二、方案功能 远程监测 位置追踪 翻动检测 防倾斜和气体检测 三、工作原理: 智慧井盖主要依靠传感器技术、通信技术和云计算技术实现。传感器监测井盖状态,通信模块将数据传输到云计算平台进行处理和分析,实现对井盖状态的实时监控和预警。 四、方案优势: 提高安全性:及时监测井盖状态,预防盗窃、损坏等安全隐患。 增加管理效率:远程监测和控制,减少人力物力成本,提高管理效率。 多功能检测:除了基本功能外,还可进行气体检测,保障工作环境安全。 五、应用场景: 智慧井盖适用于城市排水井盖、电缆井盖、通信井盖等各种基础设施的井差管理,在城市道路、公园、广场等公共场所广泛应用。 六、典型案例: 某城市在市区道路上部署了智慧井盖传感器,实现了对井盖状态的实时监测和远程控制,提高了城市基础设施的安全性和管理效率。 七、发展趋势: 随着物联网、大数据、人工智能等技术的发展,智慧井盖解决方案将不断升级和完善,实现更加智能化的管理和控制。 八、结论: 智慧井盖作为城市安全管理的重要组成部分,通过集成多种先进技术,为城市的安全和发展提供全面支持,应积极推动其发展和应用。 --- ### 360. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着城市发展和人们生活水平的提高,智慧公厕已经成为城市基础设施建设的重要组成部分。传统的公厕管理存在着很多问题,例如无法及时了解厕所内部情况、人员流量管理不到位、环境卫生难以保障等。为了解决这些问题,推出了智慧公厕环境监测解决方案,旨在利用先进的科技手段提升公厕管理效率,改善厕所环境质量,提升城市形象。当公厕内的有害气体含量超标时,系统能够自动联动风机进行通风除臭,确保厕内环境卫生,改善公厕内的环境质量。 此外有些智慧厕所还有生命监测功能,当发现有人身体不适、超时驻留,系统会发出告警信息,及时关注如厕者安全情况。 一、概述 智慧公厕环境监测解决方案是指利用物联网、云计算、大数据等技术,对公厕内的环境参数进行实时监测、分析和管理,以提升公厕环境质量,改善如厕体验,打造智慧城市的重要组成部分。 二、方案组成 智慧公厕环境监测解决方案主要由以下四部分组成: 监测终端: 负责采集公厕内的环境参数,包括温湿度、硫化氢、氨气、PM2.5、臭氧等。 传输部分:负责将监测终端采集到的数据传输至管理平台。 管理平台:负责对数据进行存储、分析和展示,并提供管理功能。 智能联动:根据监测数据,联动风机、排气扇、照明等设备,实现公厕环境的智能化管理。 三、工作原理 监测终端采集公厕内的环境参数,并将数据传输至传输部分。 传输部分将数据传输至管理平台。 管理平台对数据进行存储、分析和展示,并提供管理功能。 根据监测数据,联动风机、排气扇、照明等设备,实现公厕环境的智能化管理。 四、方案优势 实时监测:可实时监测公厕内的环境参数,及时发现环境问题。 智能分析:可对监测数据进行智能分析,为公厕管理提供决策依据。 精细管理:可实现公厕环境的精细化管理,提升公厕环境质量。 人性化服务:可为如厕者提供更加人性化的服务,提升如厕体验。 监测终端主要有多功能空气质量变送器和吸顶式红外探测器。 公厕内的硫化氢和氩气是造成公厕异味的原因,当这2种气体的浓度达到一定的数值,就会对人体造成伤害,多功能空气质量变送器可以同时监测这两种气体的浓度,避免浓度升高对人体造成伤書。 吸顶式红外探测器能够对厕位使用情况进行动态监测,通过显示屏可直接反映厕位的占用情况,减少人员的等待时间,也方便管理人员合理配置资源。 五、应用场景 智慧公厕环境监测解决方案可广泛应用于城市公厕、景区公厕、高速公路公厕、公园公厕、学校公厕等场所。 六、典型案例 某市智慧公厕项目:该项目采用智慧公厕环境监测解决方案,对全市范围内1000余座公厕进行环境监测,有效提升了公厕环境质量,改善了如厕体验。 某景区智慧公厕项目:该项目采用智慧公厕环境监测解决方案,对景区内50余座公厕进行环境监测,有效缓解了景区公厕高峰期排队压力,提升了景区游客的满意度。 七、发展趋势 随着智慧城市建设的不断发展,智慧公厕环境监测解决方案将得到更加广泛的应用,并将朝着以下方向发展: 技术更加智能化:将采用人工智能、大数据等技术,进一步提升监测、分析和管理的智能化水平。 功能更加丰富:将提供更多人性化功能,如厕位导航、厕纸余量提醒、如厕安全监测等。 应用更加广泛:将应用于更多场景,如家庭卫生间、养老院卫生间、医院卫生间等。 八、结论 智慧公厕环境监测解决方案是智慧城市建设的重要组成部分,对于提升公厕环境质量、改善如厕体验、提升城市形象具有重要意义。 --- ### 361. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信   智慧充电站解决方案,通过对物联网技术、移动互联网技术等技术的综合运用,为社区打造了解决电动自行车充电需求和车棚智慧管理要求的一站式综合解决方案。智能非机动车棚改造项目,是将老旧改造和先进的物联网应用相结合,整合了通信、物联网、门禁、监控、土建、软件管理等各方面资源,自主研发、设计定制的创新型项目。整体解决方案物理架构图如下: 智能充电设施介绍: (1)智能充电桩:         主要对标准电池进行更换,适用于小区、园区、商场等场所;      (2)智能充电柜。          主要对标准电池进行更换,适用于小区、园区、商场等场所 智能充电站有以下一些优势:A、安全性高       社区智能充电站的智能电瓶车充电桩系统对业主来说解决了因为用户私自拉线充电的安全问题。减少电动车充电引起的事故,对小区其他业主的人身安全带来了隐患,对物业来说,安装了小区智能电瓶车充电桩系统,同时也减少电瓶车主的财产损失。并且在小区安装小区智能电瓶车充电桩系统在某种程度上美化小区的环境,还不用每天派专人到小区内巡查,省时省力。 B、方便居民       社区智能充电站的智能电瓶车充电桩系统解决业主电动车充电难的问题。安装充电站,业主只需要把车停在电动车充电站,按照指示操作充电。电动车充电站的普及不仅解决了小区充电难的问题,还对解决城市拥堵、促进环保具有特殊的意义。 C、保护电动车      社区智能充电站的智能电瓶车充电桩系统还有充满自动停功能,能做到防过充的功能。这个是小区智能电瓶车充电桩系统的一个基本要求。产品必须要带有功率检测功能。产品要能有效的判断出电池充电功率,在电池充满电后,能立刻断电。其它所谓的充满后进入自动浮充功能。充满后直接断电才是硬道理。对电动车的电池本身就是一种保护。       社区智能电瓶车充电桩系统可以通过手机扫码智能充电,并支持远程操控,并通过APP、信息等进行全平台消息推送,还可以在APP上实时监测,让您能够轻松了解爱车的充电情况。        < --- ### 362. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着城市化进程的加快,城市雨洪管理和内涝问题日益凸显。海绵城市作为一种新型的城市雨洪管理理念,旨在通过模拟自然水循环过程,提高城市对环境变化的适应能力,减少雨水带来的自然灾害。在这一理念的实施过程中,液位计作为液位变送器的一种,发挥着至关重要的作用。 一、海绵城市的理念与挑战 海绵城市,又称为“水弹性城市”,其核心是通过一系列低影响开发(LID)措施,实现雨水的渗透、滞蓄、净化、利用和排放,从而提高城市对雨水的“弹性”管理。然而,由于这些措施的分散性和针对性,如何有效监控和评估这些设施的运行效率,成为了实现海绵城市目标的关键挑战。 二、液位计在海绵城市中的应用 实时水位监测:液位计能够实时监测城市雨水收集与排放系统中的水位变化,为城市雨洪管理提供准确的数据支持。在海绵城市的各个关键节点,如生物滞留设施、湿塘、雨水湿地等,液位计的安装确保了对水位的精确控制。 流量监控:在小区和市政道路的排水设施中,液位计与流速监测器、巴氏计量槽等设备配合使用,对雨水的溢流排放和管道排放进行监控,确保雨水得到合理管理。 水质监控:液位计与浊度、悬浮物综合监测器等水质监测设备相结合,对经过低影响开发设施处理后的雨水水质进行监控,确保水质达到预期标准。 数据分析与优化:所有监测数据通过地下管线综合管理信息平台进行汇总和处理,为海绵城市的规划、建设和管理提供科学依据,实现设施布局的优化和运行效率的提升。 三、液位计的技术要求 在海绵城市的应用中,液位计需要具备高精度、稳定性和快速响应的特点。此外,考虑到城市环境的复杂性,液位计还应具备防水、防腐蚀等特性,以适应不同的环境条件。 四、结论 液位计在海绵城市的构建中扮演着不可或缺的角色。通过实时监测水位、流量和水质,液位计为城市雨洪管理提供了强有力的技术支持,有助于实现城市水资源的可持续利用和环境保护。随着海绵城市理念的不断推广和实施,液位计的应用将更加广泛,对提升城市水弹性管理水平起到关键作用。 --- ### 363. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 电梯字符叠加器(Elevator Character Stacker)是一个解决电梯监控和安全隐患的创新产品。以下是这个产品的解决方案: 问题: 电梯监控摄像头无法实时显示电梯的运行状态和楼层信息。 监控室无法迅速定位和救援被困人员,无法查询电梯中的犯罪活动。 解决方案: 电梯字符叠加器提供了以下解决方案: 实时信息叠加:该叠加器可以将日期、时间和电梯运行信息(楼层号、上行、下行、停靠)叠加到摄像头视频画面中,确保监控室人员随时了解电梯的运行状态。 自定义楼层别名:用户可以自定义楼层别名,使监控室人员更容易理解,例如"5F"、"5楼"、"第5层"等。 无损叠加:信息叠加不影响原有视频信号,完全实现无损叠加。 双网口设计:内部集成交换机功能,方便连接摄像头,无需额外布线。 多型号摄像头兼容:适用于多种品牌的网络摄像头,如海康、宇视、大华、中维世纪等。 信息位置可调节:用户可以根据实际情况调整信息叠加的位置,避免遮挡重要画面。 多样化配置方式:可通过蓝牙配置APP或网口配置软件进行设备配置,方便快捷。 便捷校准:安装完成后只需一名施工人员在电梯轿厢内使用手机APP通过蓝牙连接即可完成校准,无需额外人力合作。 安装方便:外形小巧美观,支持35导轨安装和壁挂式安装,简单便捷。 结论: 电梯字符叠加器为电梯监控系统提供了全面的解决方案,确保监控室人员能够随时掌握电梯的运行状态,提高了电梯的安全性和可靠性。该产品的特点包括实时信息叠加、自定义楼层别名、多种摄像头兼容、便捷校准和安装方便,适用于各类建筑物的电梯监控需求。 --- ### 364. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 项目背景 在当今数字化时代,银行办公区域的管理需要更高效、智能化的解决方案来提高工作效率、节约能源,并确保安全和舒适性。为此,我们提出了一套综合的智能化方案,旨在通过物联网技术和智能控制系统,实现对银行办公区域空调的智能管理和控制。 方案概述 我们的方案结合了物联网技术、红外人感技术、定时延时器以及智能控制主机等硬件设备,同时配合定制的软件平台,为银行办公区域提供了一套智能化的空调管理系统。该系统可以实现远程控制、自动关闭、智能调节等功能,以提高能源利用效率和工作环境舒适度。 硬件简介 人感红外探测器:用于监测办公区域内人员活动,当监测到无人时,系统自动关闭空调。 定时延时器:配合人感红外探测器使用,用于设置延时关闭空调的时间。 空调控制网关:用于连接空调系统,并与智能控制主机通讯,实现远程控制和状态反馈。 智能控制主机:作为系统的核心,负责接收和处理传感器数据,控制空调的开关、温度调节等功能。 软件介绍 我们定制的软件平台具有以下特点: 界面定制化:可以根据银行的需求定制登录页面背景和系统名称,使其适应不同的项目需求。 区域控制:支持分楼栋、分层级的区域划分,实现对不同区域的智能控制。 用户权限管理:可以设置用户操作权限,确保只有授权人员才能对特定区域设备进行控制。 操作日志记录:系统会记录用户的操作日志,方便管理人员进行查询和监控。 隐私保护:采用被动式反向链接非云端控制逻辑,保护用户隐私和数据安全。 支持部署方式:可选择线上版本或线下版本一次性买断部署,根据实际需求灵活选择。 整体工作流程 人感红外探测器监测到办公区域有人活动。 红外信号传输至智能控制主机,触发定时延时器开始计时。 若一定时间内未再监测到人员活动,定时延时器自动关闭空调。 智能控制主机将空调状态信息传输至空调控制网关。 用户可通过手机端或PC端的软件平台远程控制空调的开关、温度调节等功能。 效果与优势 节能降耗:通过智能控制,实现了在不影响办公环境舒适度的前提下,有效降低能源消耗。 提升效率:远程控制功能使得管理人员可以随时随地对空调进行监控和调节,提高了管理效率。 舒适安全:智能化的空调管理系统可以根据人员活动情况自动调节,提供舒适的工作环境,并确保安全性。 综上所述,我们的智能化方案将为平安银行办公区域提供高效、智能的空调管理解决方案,实现了节能、提升效率和舒适安全的目标。 --- ═══════════════════════════════════════════ ## 智慧水利 ═══════════════════════════════════════════ ### 365. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、项目背景 随着工业化和城市化的快速发展,污水排放量日益增加,对环境造成了严重的影响。为了保护水资源,减少污染,实现可持续发展,必须对污水进行有效处理。本方案旨在介绍一种综合性的污水处理流程,包括一级、二级和三级处理,以确保污水达到排放标准,减少对环境的影响。 二、污水处理流程 一级处理(物理处理) 目标:去除污水中的悬浮固体(SS)。方法:通过粗格栅拦截大颗粒固体,然后通过污水提升泵提升污水,再经过细格栅或砂滤器进一步去除较小的悬浮物。结果:BOD(生物化学需氧量)可去除约30%,但不足以满足排放标准。二级处理(生物处理) 目标:去除污水中的胶体和溶解性有机物(BOD,COD)。方法:活性污泥法:通过曝气池或氧化沟,利用微生物降解有机物。生物膜法:在生物滤池、生物转盘、生物接触氧化法和生物流化床中,微生物附着在载体上,降解流过污水中的有机物。结果:有机物去除率可达90%以上,使有机污染物达到排放标准。三级处理(高级处理) 目标:进一步去除难降解有机物、氮、磷等可导致水体富营养化的可溶性无机物。方法:生物脱氮除磷法:通过微生物的代谢作用,去除污水中的氮、磷。混凝沉淀法:通过添加混凝剂,使微小悬浮物聚集成大颗粒,便于沉淀。砂滤法:通过砂滤器去除残留的悬浮物。活性炭吸附法:利用活性炭的吸附作用,去除有机物和部分无机物。结果:进一步提高污水的清澈度,减少对水体的污染。三、污泥处理 污泥回流:将二级处理产生的污泥部分回流至一级处理的初次沉淀池或生物处理设备,以提高处理效率。污泥浓缩:通过污泥浓缩池减少污泥的体积。污泥消化:在污泥消化池中,通过微生物的作用减少污泥的有机物含量。污泥脱水和干燥:通过脱水和干燥设备,将污泥转化为可利用的资源。四、监测与控制 实时监测:在整个处理过程中,通过安装液位变送器、流量计、水质分析仪等设备,实时监测污水处理的效果。自动化控制:通过集成控制系统,实现污水处理过程的自动化,确保处理效率和稳定性。五、项目实施 设计阶段:根据污水的具体成分和排放标准,设计合理的处理流程和设备配置。施工阶段:严格按照设计要求进行施工,确保工程质量。调试阶段:完成施工后,进行设备调试和系统优化,确保处理效果达到预期目标。运营阶段:建立完善的运营管理体系,定期维护设备,确保污水处理设施长期稳定运行。六、环境与社会效益 环境保护:通过有效处理污水,减少对水体的污染,保护水资源。资源回收:将污泥转化为可利用的资源,实现废物的再利用。社会责任:通过提供清洁的环境,提升社会生活质量,履行企业的社会责任。 通过实施上述污水处理方案,可以有效去除污水中的污染物,保护环境,同时实现资源的可持续利用,为社会和经济的可持续发展做出贡献。 --- ═══════════════════════════════════════════ ## 智能家居 ═══════════════════════════════════════════ ### 366. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案背景 随着物联网(IoT)和人工智能物联网(AIoT)技术的迅速发展,智能化产品在宠物产业中的应用逐渐受到关注。中国宠物市场持续增长,年轻人群对宠物的需求增加,促使了宠物用品行业的创新和智能化发展。为了满足宠物主人对宠物健康、安全和舒适的需求,物联网技术被引入到宠物领域,推动了智能化宠物产品的发展。 方案介绍 本方案旨在利用物联网技术为宠物主人提供一系列智能化解决方案,包括智能喂食器、智能喂水器、智能猫窝和狗窝等产品。通过将传感器、执行器等设备连接到互联网上,宠物主人可以远程监控和管理宠物的饮食、生活环境等情况,实现对宠物的全方位关怀。 方案组成 智能喂食器:结合IoT技术,实现远程监控和定时喂食功能,根据宠物数据智能调整喂食量。 智能喂水器:定时喂水、监控水质,保障宠物饮水安全。 智能猫窝和狗窝:通过内置传感器和摄像头监测宠物行为和健康状况,智能调节温度和湿度,提供舒适安全的生活环境。 方案功能 远程监控与控制:宠物主人可以通过手机App或网页平台随时随地监控和管理宠物的饮食、生活环境等情况,实现远程喂食、喂水和调节环境温度等功能。 智能化调整:根据宠物的体重、运动量等数据,智能调整喂食量和水质,确保宠物健康饮食。 数据记录与分析:系统可以记录宠物的饮食、活动等数据,为宠物主人提供参考,并通过数据分析帮助宠物主人更好地了解宠物的生活习性和健康状况。 安全保障:智能设备可以监测水质、调节温度和湿度,一旦发现异常情况,系统会及时发送通知提醒宠物主人,保障宠物的健康和安全。 结语 随着物联网技术的不断发展和普及,智能化宠物产品将为宠物主人带来更便捷、安全和舒适的养宠体验。本方案以满足宠物主人对宠物生活质量的需求为目标,利用物联网技术打造智能化的宠物产品,为宠物产业注入新的活力,提升消费者体验,推动产业发展。 --- ### 367. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智慧公园+智慧步道+智慧园+智慧社区整体解决方案 概述 本方案旨在为城市提供一套完整的智慧化解决方案,涵盖智慧公园、智慧步道、智慧园区和智慧社区四大板块,以AI技术为核心,利用物联网、云计算、大数据等新一代信息技术,打造安全、舒适、便捷、智能的城市环境。 方案详情 智慧公园 建设智慧健身路径、智慧健身步道,为市民提供便捷的健身服务。 利用AI技术,进行人脸识别、行为分析等,提升公园的安全管理水平。 建设智慧导览系统,为游客提供便捷的游览服务。 智慧步道 利用物联网技术,采集步道上的环境数据、运动数据等,为市民提供健康指导服务。 建设智慧安防系统,保障步道安全。 建设智慧驿站,为市民提供休憩、充电等服务。 智慧园区 建设智慧安防系统,保障园区安全。 建设智慧办公系统,提升园区办公效率。 建设智慧能源管理系统,节约能源。 智慧社区 建设智慧安防系统,保障社区安全。 建设智慧物业管理系统,提升物业管理效率。 建设智慧生活服务平台,为居民提供便捷的生活服务。 结语 本方案为城市提供了一套完整的智慧化解决方案,可有效提升城市治理水平和居民生活质量。sharemore_vert --- ### 368. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 航海梦想的现实:46米游艇智能系统完美融合 本方案旨在为46米游艇提供一套完整的智能化解决方案,涵盖以下系统: 中控主机及触控终端 有线及无线局域网 高清、网络视频监控及防盗报警系统 多房间HFI背景音乐音乐 智能照明系统 电动窗帘及控制系统 智能环境控制系统(空调、新风) 影院及影院控制系统 方案详情 中控主机及触控终端 强大的逻辑编程 可持续扩展升级 系统整合联动 稳定、快速、强大、灵活的控制主机,是每个控制系统的基石 有线及无线局域网 商用典型组网方案 互联互通 无缝切换 高清、网络视频监控系统 全套的全高清网络监控解决方案 清晰 抗干扰 不随距离衰减 多房间HFI背景音乐音乐 可扩展在线音乐点播,与移动客户端同步收藏列表 通过蓝牙AirPlay播放移动设备上的音乐 智能照明系统 营造舒适氛围 可根据场景设置不同的灯光模式 电动窗帘及控制系统 可通过触控屏或手机/平板APP控制 实现全开、全关、半开等功能 智能环境控制系统(空调、新风) 可通过触控屏或手机/平板APP控制 实现温度、湿度、风速等调节 影院及影院控制系统 提供高品质的影音体验 可通过触控屏或手机/平板APP控制 总结 本方案为46米游艇提供了一套完整、可靠、智能的解决方案,可满足用户的各种需求,提升游艇的舒适度、安全性、娱乐性。 以下是一些具体的实施建议: 选择知名品牌的设备,确保系统的稳定性和可靠性。 由专业人员进行安装和调试,确保系统的正常运行。 定期维护和保养,确保系统的最佳性能。 希望本方案能够帮助您打造一艘舒适、安全、智能的游艇 --- ### 369. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、酒店智能化系统需求分析 酒店的智能化系统建设必须紧密围绕酒店的经营理念、服务模式和程序来进行,决不是生搬硬套的系统堆砌。因此,系统的设计必须围绕以客人的住店感受和酒店管理的高效有序这两个中心出发来综合考虑和配置。 二、系统设置 根据智能建筑设计标准《GB/T 50314—2013》规范要求,酒店项目智能化系统主要包含以下几个系统: 信息设施系统 电话交换系统 信息网络系统 综合布线系统 室内移动通信覆盖系统 有线电视及卫星电视接收系统 广播系统 会议系统 信息引导及发布系统 综合管路系统 信息化应用系统 酒店管理系统 客房控制管理系统 酒店客房门锁系统 楼宇自动化控制及能耗管理系统 建筑设备管理系统 智能照明系统 公共安全系统 入侵报警系统 视频监控系统 出入口控制系统 电子巡更系统 无线对讲系统 停车场管理系统 机房工程 机房布置与设计 网络设备安装与维护 数据中心建设与管理 服务器架设与运维 数据存储与备份管理 网络安全与防护措施 三、各系统简单介绍 3.1 信息设施系统 3.1.1 电话交换系统 电话交换系统能完整地把传统的语音通信、语音信箱、多方电话会议、IP 技术、宾馆酒店服务软件、酒店资产管理系统接口、ISDN 应用等当今最先进的计算机通信技术集成一起.提供了众多的系统功能和全套的宾馆服务业务,如:语音提示、音乐保持、按姓名拨号、多方电话会议、客人的入住登记和退房、叫醒服务、免打扰、房态管理等功能。系统采用数字程控交换机,由多少个话务台具体由酒店管理公司确定。 3.1.2 信息网络系统 酒店信息网路建设一般以固定以太网为主、无线以太网为辅的酒店计算机网络结构。 (1)有线网络 酒店有线网络分为管理网和客房网,前者主要为酒店运营及酒店管理服务,后者主要为客人服务。为保证办公计算机网络的可靠性,两套计算机网络系统做物理隔离,即为两套计算机网络系统分别配置核心交换机、楼层接入交换机等。办公计算机网络独立成系统, 通过 PMS 接口与 Internet 连接。 (2)无线局域网 酒店的所有区域都可以通过无线局域网上网,要求支持无线局域网协议802.11/b/g。无线局域网的使用: 客人:首先,必须满足客人使用需求“零设置”,即客人无线终端接入无线网络时无需做任何设置,通过酒店代理服务器(酒店界面)直接指向 INTERNET.在酒店入住的客人可以利用配有无线终端产品的笔记本电脑自由地接入互联网,提高其办公效率。同时,酒店还可实现无线网络与现有有线网络之间无缝连接,客人无论是在客房、会议室、餐厅还是花园都可以随时接入互联网。 酒店员工:使用无线终端经认证后可接入酒店网络,进行授权范围内的访问及操作.也可以使用无线语音终端进行内部免费通话。 3.1.3 综合布线系统 综合布线系统就是为了顺应发展需求而特别设计的一套布线系统.对于现代化的建筑来说,就如体内的神经,它采用了一系列高质量的标准材料,以模块化的组合方式,把语音、数据、图像和部分控制信号系统用统一的传输媒介进行综合,经过统一的规划设计,综合在一套标准的布线系统中,将现代建筑的三大子系统有机地连接起来,为现代建筑的系统集成提供了物理介质.可以说结构化布线系统的成功与否直接关系到现代化的建筑的成败,选择一套高品质的综合布线系统是至关重要的。 根据国际标准 ISO11801 的定义,结构化布线系统可由以下系统组成: 工作区子系统、水平子系统、管理子系统、干线子系统、设备间子系统、建筑群子系统。 布线以 6 类非屏蔽双绞线为主,主干采用多模万兆光纤。光纤芯数充分考虑了冗余,数据与语音水平线缆全部采用低烟无卤六类非屏蔽四对八芯双绞线。水平端接设备采用 24口模块化配线架,数据中心采用机架式光纤配线架,管理间配线架与网络交换机采用六类非屏蔽跳线。其中语音主干采用 3 类大对数电缆。 3.1.4 室内移动通信覆盖系统 本系统由通信运营商免费实施。 地下室及所有电梯对移动电话信号有很强的屏蔽作用,因此,必须通过在室内分布一定数量的天线和合理的功率分配来解决本项目室内各区域信号弱、质量差、切换频繁或话务拥挤的问题。 根据目前的现状,需在酒店内建设 GSM、CDMA、3G 、PHS 的无线覆盖系统。 3.1.5 有线电视及卫星电视接收系统 有线电视及卫星电视接收系统的设计和使用是智能子系统的一个重要组成部分。酒店的完美服务,涵括丰富多样的娱乐休闲生活和获取了解最新国内外新闻的多方位途径,一个设计、组合合理先进的有线电视及卫星电视接收系统,对酒店工程的品质定位,服务口碑,是一个良好的促动,也是全方位服务体系的重要组成。 有线电视及卫星电视接收系统主要包括两个方面: (1)传统的有线电视系统:节目源一般由自办节目、卫星电视和城市有线网提供, 具体的节目源要求由酒店管理公司提出,并在调研当地数字电视节目源的基础上再做确定。 (2)VOD 电视点播系统:通过组建的综合布线系统的线路,通过网络方式访问存储 在服务器里的电视、电影节目及其他节目进行自由点播,给客人以优质、全方位的服务。 3.1.6 广播系统 广播系统主要能同时完成背景音乐和公共广播(包含业务广播和消防广播)两项功能.为在酒店内营造一个舒适、幽雅的环境,背景音乐广播已成为不可缺少的基础设施。主要分布于酒店大堂、咖啡厅、餐厅、公共走廊(客房层走廊不建议设置)、SPA 区、健身房、电梯前室等公共区域及会议区、客房。当发布通知时,播音人员可将当前的广播状态切换成业务广播状态,进行消息、通知和人流导引的发布.而当有火灾事故发生时广播可在发生消防火警时将背景音乐或业务广播状态紧急切换至消防广播状态且具有最高优先权。消防信号由每个楼层的消防信号发生器产生并输送到主机设备中,触发主机系统发出切换信号。因不同区域对背景音乐的音乐源有不同的需求,如酒店大堂、咖啡厅、餐厅、会议区等区域需要幽雅、轻松的音乐,SPA 区需要愉悦、放松的音乐,健身房场所需要播放一些节奏感较强的音乐等等,所以选用的系统必须是多音源系统,并在现场可根据需要选择音乐源和调节音量。 3.1.7 会议系统 酒店会议区包括各种大小会议室、多功能厅、宴会厅等,今后需满足会议、报告、产品发布、歌舞表演、走台、大型宴会等各种需求,并且中型会议室、多功能厅、宴会厅等面积较大的房间应能根据客户需要灵活布局,各种音、视频系统必须与之相适应,并通过中央控制系统和灯光系统的配合使用,使酒店的管理人员能通过简单的操作(如一键制)完成系统的模式转换和场境变换. 本系统是一个专业性很强的综合设计,除本系统的扩声、视频、控制等专业设计外, 还涉及建声、装饰、灯光等其他专业.会议区音、视频系统所涉及的系统主要包括: 会议发言系统 同声传译系统 会议扩声系统 会议摄录系统 会议控制系统 会议显示系统 音视频传输及控制系统 会议灯光系统 3.1.8 信息引导及发布系统 针对酒店的人员不同,主要包括外宾、各级领导及其他相关的人员,信息引导及发 布系统,主要包括两个部分: (1)LED 信息发布系统 当有外宾及领导来酒店进行商务会谈及考察时,可以在 LED 屏上显示欢迎致辞等字 样,替代传统的条幅;在平时,可以显示天气预报、时间等信息,显示形式可以为文字或图画 等方式. (2)触摸屏查询系统 入住客人可以通过触摸屏的查询对本酒店的场所介绍、客房介绍及其他的相关情况 进行介绍,便于了解,为酒店树立一个良好的形象. (3)信息引导系统 通过安装电梯厅及走廊间的信息引导屏,可以对国内外资讯、酒店情况、会议进行 情况等进行引导。 3.1.9 综合管路系统 本系统是指酒店智能化系统的路由通道,包括竖向、水平的金属桥架、水平金属管路等。 桥架部分内容需经点位估计后进行容量估算,按照相关规范,桥架内线缆填充率不超过 40%,管路内的线缆填充率不超过 50~60%。 3.2 信息化应用系统 3.2.1 酒店管理软件 本系统主要是酒店管理公司确定,一些知名酒店管理公司都有自己常用或合作单位的软件。 该系统建立在广域网、局域网上,主要用于向酒店管理者提供现代化经营手段,目的使酒店经营高效、先进、科学;用于向酒店管理者提供高质量管理手段,如智能办公系统、智能节能系统、智能采购网络、智能人员管理系统、智能物耗管理系统、智能消费管理系统、智能菜单管理系统等等,目的是使酒店办公、物耗、能耗、人员成本等降到最低,使用效率最高,创造良好效益。PMS 必须提供与程控交换机、客房控制管理系统的通信接口。 酒店管理软件一般由前台、后台、接口系统等组成,一般的酒店管理软件需提供以下接口: 1.财务接口:与财务软件接口,实际酒店财务管理。 2.一卡通接口:通过与酒店 IC 卡/磁卡相连,实现一卡通管理。凭 IC 卡/磁卡在酒 店实现挂帐消费,统一结算,并实现内部 IC 卡/磁卡管理。 3.Internet 接口:为客人联接 Internet,建立 Internet 帐户,酒店上网与各旅 行社建立网上业务联系,并实现网上预订。 4.POS 机接口:在各收费点可以用 POS 机进行收银,可开启 POS 银箱,驱动 POS 棒显。 5.户籍发送:通过与公安局的户籍管理系统相连,自动把公安局所需户籍数据发 送过去。 6.VOD 视频接口:与酒店 VOD 系统连接,客户 VOD 的消费自动记到其帐户下。 7.网上预订 8.办公自动化 OA 系统 3.2.2 客房控制管理系统 客房控制系统是在微电脑客房智能控制器的基础上,通过网络将酒店各客房的状态信息实时传送到酒店的客房服务中心、楼层服务台、工程部等职能部门,酒店相关部门便可。 根据实际情况有针对性地对客人提供优质服务;系统数据库定时存贮各客房状态发生变化的时间及服务人员的服务响应时间,以便为相关管理部门的管理提供可靠、公正、科学的依据,此外系统还可根据实际需要,通过网络对各客房相关设备进行远程控制。 主要功能为: 对台灯、阅读灯、房灯、落地灯、镜前灯、空调等强电控制; 对请清理、勿扰、SOS 呼叫、服务呼叫、快速退房、房间有无人检测、房门关闭检测、房间灯故障检测等弱电控制;对以上的所有强、弱电信息能准确快速地传递到客房服务中心.酒店管理人员不需要进入房间就能监控所有的客房状况. 本客房智能控制系统既体现了酒店的个性化、智能化、绿色化特点,也实现了传统与高科技的完美统一,全面提升了酒店的管理,为客人提供全方位的超值服务. 3.2.3 酒店客房门锁系统酒店客房门锁采用何种门锁,需管理公司确认,该门锁的采用与客房管理系统实现功能有重大联系。 客房门锁系统由电子门锁、IC 卡、发卡器、记录卡、门锁管理软件等组成。系统考虑在每个门上设置一把离线式电子门锁。 根据客房内使用情况的不同,我们可以将系统的卡权限分别作如下设置。 客人卡:供入住的宾客开门使用,只能在有效时间内打开所对应房号的房门,并可作为客人房间内的插卡取电用。 应急卡:最高级别的管理开门卡.供酒店内部管理人员使用,在紧急情况下打开酒 店客房的门锁。 清洁卡:供酒店内部的服务员工或楼层员工使用; 初始化卡:供酒店管理人员使用,用于将相应密码与系统标识的门锁设置为初始化 状态。 汇总卡:供酒店管理员使用,用于读取门锁的开锁记录。 3.3 楼宇自动化控制及能耗管理系统 3.3.1 建筑设备管理系统 酒店机电设备较多且较分散,设备管理和维护的自动化必然成为今后物业管理的重要课题;另外,酒店的空调系统能耗较大,因此,在保证舒适的前提下,如何优化控制,协调管理,节约能源也将成为建筑智能化系统实施的必要手段,实现在最低能耗(使用成本)的前提下,建筑使用价值的最大化。建筑设备管理系统利用计算机和现代通讯控制技术,对酒店内各种机电设备按照管理操作者的意愿进行集中管理和优化控制,最终达到区域各种机电设备协调有序地工作,并在满足区域各种功能前提下,尽可能减少相关的管理人员和最大限度地节约能耗,降低酒店的管理和营运费用。 系统主要监控内容如下: 冷热源系统(状态监测) 空调机组、新风机组(温、湿度调节、运行状态及启停控制) VAV 系统(温、湿度调节、新风和回风的比例调节、运行状态及启停控制) CAV 系统(温、湿度调节、运行状态及启停控制) 关于对客房温、湿度及噪声的控制 对室内游泳池空调系统的控制 送排风系统(各风机的运行状况及启停控制,消防用风机由消防负责考虑) 给排水系统(生活水泵的运行状况及水箱水位的报警监测) 变配电系统(变配电数据及报警信息) 电梯系统(运行状态、故障报警监测) 3.3.2 智能照明系统 智能化酒店对照明的要求越来越高,不仅要求提供舒适、绿色的光照,同时不同的场合需要不同的照明环境。传统的照明控制一般采用开关手动控制,对于上述要求很难实现, 而且线路十分复杂,操作非常繁琐。随着用户要求的提高和技术的进步,传统的照明控制由于许多问题无法解决而逐步被智能照明控制取代,智能照明系统可依据需要实现自动时间控制、自动顺序控制、占空(动静)探测控制、事件程序响应控制、分割空间控制等多种方式的自动控制,也可增加自动日照控制、事件程序响应控制、远程电话控制、远程 Internet控制等。 系统涉及的主要部位有: (1)客房走廊:采用移动控制,通过在客房走廊设置若干的传感器(如移动探测器、 主动探测器等),与走廊灯光进行连锁控制。当有人进入探测器探测区域时,该区域内的走 廊灯缓慢点亮,当进入下一个探测器区域时,该区域的渐区域的走廊灯又缓慢点亮,而上一 个区域的走廊灯又缓慢调暗,使客人感受渐进式亮度变化过程,具有一定的艺术欣赏感,同 时又可节省能源和延长灯具寿命。 (2)酒店大堂:恒照度控制,根据系统设定的照度值室内照度的变化,自动调节灯 光的亮度,使酒店大堂照度保持恒定。 (3)会议区、咖啡厅、宴会厅等:场境控制,根据预先设定的模式实现一键制场境 转换。 3.4 公共安全系统 3.4.1 入侵报警系统 入侵报警系统是采用红外或微波技术的信号探测器,在酒店内根据不同位置的重要程度和风险等级要求以及现场条件,进行周边和内部区域保护。 报警管理主机能直接或间接接收来自入侵探测器发出的报警信号,发出声、光报警并指示入侵发生的部位。 声、光报警信号能保持至手动复位;复位后,再有入侵报警信号输入时,能重新发出声、光报警信号。 系统自成网络,且有输出接口,用手动、自动方式,通过有线向外报警联动。 (1)紧急报警按钮 在收银台、前台、财务室、贵重物品寄存室等场所安装紧急按钮,在遇紧急情况时 可及时向保安中心报警、求助.(注:客房及卫生间内设置报警按钮,该部分功能由客房控制系统实现) (2)红外/微波双鉴探测器 在贵重物品存储区、财务室、酒店商店设置,在设防(非开放)时间段,检测和快速报警至监控中心并可联动相应摄像机. 3.4.2 视频监控系统 视频监控系统的主要功能是辅助入侵报警系统对酒店内的现场实况进行监视。它使管理人员在控制室中能观察到酒店内所有重要地点的情况,为消防、酒店各种设备的运行和人员活动提供了监视手段。如在地下车库、自行车库、大厅、各楼层主要出入口、电梯轿厢、重要库房等重要部位设置监控摄像机,将监测区的情况以图像方式实时传送到监控管理中心, 值班人员通过监视器可以随时了解这些重要场所的情况。 系统采用网络摄像机(电梯专用采用模拟+编码器模式).前端摄像机分别就近接入各楼层接入层交换机,通过综合布线网络汇聚到总控中心的核心层交换机。控制中心采用视频综合平台进行解码上墙显示,通过磁盘阵列进行集中存储。 总控中心软件管理平台提供系统的中心管理服务、存储管理服务、流媒体服务、WEB服务、报警管理服务、智能分析管理服务等各类系统服务,并为各分控中心的控制端提供系统支撑和各类认证的服务。软件平台支持网络键盘的接入,提供了人性化的操作功能. 3.4.3 出入口控制系统 本出入口控制系统主要针对后勤区的办公用房、消控中心、IT 中心及 PABX 间设置门禁系统,为方便管理,建议采用联网型门禁系统. 系统采用以太网架构 TCP/IP 通讯,结合非接触式 IC 卡及计算机网络技术,以一张多功能非接触式 IC 卡承担起身份识别、门禁通行等管理职能.门禁管制方式具有多种,可灵活根据业主的功能需求及现场实际情况进行量身订做。主要的控制方式如下几种,单向控制(进门刷卡、出门开门按钮)、双向控制(进门刷卡、出门刷卡),另外读卡器可选用支持密码、生物识别等产品,在普通门控的基础上提高安全级别。 3.4.4 电子巡更系统 酒店来往人员众多复杂,为有效实现人防与物防相结合,必须有专人对较重要的场所进行巡逻管理,对酒店进行 24 小时的定期进行巡逻,以处理突发事件。 为了保证每个保安人员都能尽职尽责,在合理设定的时间内,按时按路线巡逻,确保工作严密有效,在突发事件时能尽快反应,也保障了保安人员的安全,必须在酒店内设立电子巡更系统。 电子巡更的实现:巡逻路线上设置巡更点,保安人员在此路线上按指定的时间和地点到达巡更点,不能迟到,不能绕道,巡更员每抵达一个巡更点,必须采集巡更点的信息,以便控制中心了解巡更线路情况。 系统主要由信息点、数据变送器、数据变送器、系统管理软件四部份组成. 3.4.5 无线对讲系统 无线对讲系统是一种比较普通的无线技术应用,主要用于酒店、管理服务和保安巡逻。该系统能使您找到更快、更好和更有效的工作途径,通讯系统能使工作范围扩大到方圆15—25 公里左右。因此,无论相关人员或团队在哪里,都可以轻轻按下一个键便能与他们取得联系,同时也是现代化安全管理工作不可缺少的工具. 本项目无线对讲信号有效覆盖区域酒店地面及地下区域,其中 95%以上的覆盖面积为有效覆盖面积。使整个系统达到覆盖均匀,信号清晰,稳定可靠。以满足酒店内部管理、物业使用和维护,以及保安、消防、紧急通信之要求等,使其内部管理、维护以及保安、消防人员之间方便、快捷地保持联系、通讯。 无线系统采用无线异频中继转发来实现双向无线对讲的要求。选用 400MHz(UHF403—470MHz)频段作为无线通信频率。具体频点向无线电管理委员会申请。 3.4.6 停车场管理系统 现代化的停车场管理系统应是采用先进技术,并结合了不同人员在停车场收费管理方面的不同需求,以及有效管理方面的经验而开发的系统。该系统提供一种灵活、有效的停车场管理方式,能够为其用户提供更方便、更有效的服务。停车场管理系统是置于计算机管理下的高科技机电一体化产品,它主要是针对建设智能化车库的管理需要,以方便、安全为目标、以车辆停车为主要服务对象,以达到停车进出方便、快捷、安全,管理科学高效、服务优质文明的目的。 酒店项目一般有地面和地下多个出入口,采用近距离和远距离卡片两种相结合方案,临时访客车,需在岗亭处办理登记手续,允许进入后,发给司机一张临时卡,读卡进入,同时根据需要,可进行计费收费;内部车辆,采用远距离刷卡进出管理。 3.5 机房工程 机房工程通常是指在一个物理空间内实现对数据信息的集中处理、存储、传输、交换、管理,而计算机设备、服务器设备、网络设备、通讯设备、存储设备等通常被认为是网络机房关键设备。中心机房的基础设施是指为确保机房内的网络机房关键设备和装置能安全、稳定和可靠运行而设计配置的基础工程即机房工程,数机房工程的建设不仅要为机房内的网络机房关键设备运营管理和数据信息安全,提供 24×7 的保障环境,还要为工作人员创造健康适宜的工作环境。 机房工程建设是多种技术系统的综合工程,主要包括:场地规划、装饰装修、电源配电、暖通空调、应急照明、网络布线、防雷接地、气体消防、视频应用、信息安全、安全防范、环境监控等专项技术系统。 机房工程一般包括网络中心机房和消防控制中心. 分别设置系统为: 1、网络中心机房的机房工程包括如下系统: (1)装饰装修工程 (2)低压供配电系统 (3)UPS 及蓄电池系统 (4)空调调节系统 (5)安全防范系统(门禁管理系统及视频监控系统) (6)机房环境监测系统 (7)综合布线系统 (8)气体灭火系统 (9)防雷及接地系统 2、消防控制中心的机房工程包括如下系统: (1)装饰装修工程 (2)低压配电系统 (3)UPS --- ═══════════════════════════════════════════ ## 智能家居 ═══════════════════════════════════════════ ### 370. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案背景 随着物联网(IoT)和人工智能物联网(AIoT)技术的迅速发展,智能化产品在宠物产业中的应用逐渐受到关注。中国宠物市场持续增长,年轻人群对宠物的需求增加,促使了宠物用品行业的创新和智能化发展。为了满足宠物主人对宠物健康、安全和舒适的需求,物联网技术被引入到宠物领域,推动了智能化宠物产品的发展。 方案介绍 本方案旨在利用物联网技术为宠物主人提供一系列智能化解决方案,包括智能喂食器、智能喂水器、智能猫窝和狗窝等产品。通过将传感器、执行器等设备连接到互联网上,宠物主人可以远程监控和管理宠物的饮食、生活环境等情况,实现对宠物的全方位关怀。 方案组成 智能喂食器:结合IoT技术,实现远程监控和定时喂食功能,根据宠物数据智能调整喂食量。 智能喂水器:定时喂水、监控水质,保障宠物饮水安全。 智能猫窝和狗窝:通过内置传感器和摄像头监测宠物行为和健康状况,智能调节温度和湿度,提供舒适安全的生活环境。 方案功能 远程监控与控制:宠物主人可以通过手机App或网页平台随时随地监控和管理宠物的饮食、生活环境等情况,实现远程喂食、喂水和调节环境温度等功能。 智能化调整:根据宠物的体重、运动量等数据,智能调整喂食量和水质,确保宠物健康饮食。 数据记录与分析:系统可以记录宠物的饮食、活动等数据,为宠物主人提供参考,并通过数据分析帮助宠物主人更好地了解宠物的生活习性和健康状况。 安全保障:智能设备可以监测水质、调节温度和湿度,一旦发现异常情况,系统会及时发送通知提醒宠物主人,保障宠物的健康和安全。 结语 随着物联网技术的不断发展和普及,智能化宠物产品将为宠物主人带来更便捷、安全和舒适的养宠体验。本方案以满足宠物主人对宠物生活质量的需求为目标,利用物联网技术打造智能化的宠物产品,为宠物产业注入新的活力,提升消费者体验,推动产业发展。 --- ### 371. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 航海梦想的现实:46米游艇智能系统完美融合 本方案旨在为46米游艇提供一套完整的智能化解决方案,涵盖以下系统: 中控主机及触控终端 有线及无线局域网 高清、网络视频监控及防盗报警系统 多房间HFI背景音乐音乐 智能照明系统 电动窗帘及控制系统 智能环境控制系统(空调、新风) 影院及影院控制系统 方案详情 中控主机及触控终端 强大的逻辑编程 可持续扩展升级 系统整合联动 稳定、快速、强大、灵活的控制主机,是每个控制系统的基石 有线及无线局域网 商用典型组网方案 互联互通 无缝切换 高清、网络视频监控系统 全套的全高清网络监控解决方案 清晰 抗干扰 不随距离衰减 多房间HFI背景音乐音乐 可扩展在线音乐点播,与移动客户端同步收藏列表 通过蓝牙AirPlay播放移动设备上的音乐 智能照明系统 营造舒适氛围 可根据场景设置不同的灯光模式 电动窗帘及控制系统 可通过触控屏或手机/平板APP控制 实现全开、全关、半开等功能 智能环境控制系统(空调、新风) 可通过触控屏或手机/平板APP控制 实现温度、湿度、风速等调节 影院及影院控制系统 提供高品质的影音体验 可通过触控屏或手机/平板APP控制 总结 本方案为46米游艇提供了一套完整、可靠、智能的解决方案,可满足用户的各种需求,提升游艇的舒适度、安全性、娱乐性。 以下是一些具体的实施建议: 选择知名品牌的设备,确保系统的稳定性和可靠性。 由专业人员进行安装和调试,确保系统的正常运行。 定期维护和保养,确保系统的最佳性能。 希望本方案能够帮助您打造一艘舒适、安全、智能的游艇 --- ### 372. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在当今的智能家居浪潮中,越来越多的人希望能够自己打造一个智能家居系统,以便更好地管理家庭设备并提高生活的便利性。"Tasmota"是一个开源项目,它为您提供了实现这一目标的工具和平台。本文将介绍"Tasmota"项目,探讨它的功能、特点以及如何使用它来创建您自己的智能家居系统。 什么是Tasmota? "Tasmota"是一个为ESP8266和ESP32基础设备开发的替代固件,它的目标是实现智能家居的全面自动化和控制。这个项目的特点包括: 易安装:您可以使用"Tasmota WebInstaller"轻松地将"Tasmota"固件安装到您的设备上,无需复杂的操作。 多平台支持:无论您使用的是HomeAssistant、小米智能家居、华为智能家居、涂鸦智能家居还是HomeKit,"Tasmota"都支持与多个智能家居平台的集成,使您能够管理不同品牌的智能设备。 局域网连接:"Tasmota"的设计重点是在本地局域网内运行,这意味着您的设备的数据和控制命令在家庭网络内进行传输,提高了隐私和安全性。 开源和自定义:项目采用了开源许可证,允许开发者自由使用、修改和分发源代码,从而可以根据自己的需求自定义和扩展项目。 OTA更新:"Tasmota"支持通过网络进行固件更新,无需物理连接设备,提高了固件升级的便捷性。 如何使用Tasmota? 要使用"Tasmota"来打造自己的智能家居系统,您可以按照以下步骤进行: 安装Tasmota:使用"Tasmota WebInstaller"或按照官方安装指南将"Tasmota"固件安装到您的ESP8266或ESP32设备上。 配置设备:一旦安装完成,您可以通过web界面配置设备的各种参数,包括连接到您的家庭网络、设置MQTT服务器等。 连接智能设备:将各种智能设备(如智能灯泡、传感器、插座等)连接到您的"Tasmota"设备,可以使用多种通信协议,包括MQTT、HTTP、Serial等。 集成智能家居平台:通过与您使用的智能家居平台(如HomeAssistant)的集成,您可以创建自动化规则和场景,实现智能家居的自动化控制。 更新和维护:定期检查并更新"Tasmota"固件,以确保您获得最新的功能和安全性。 安全提示 在使用"Tasmota"或类似固件时,务必注意安全性和电气安全。如果您的设备连接到交流电源(AC电源),请务必正确安装设备以避免电击危险。如果您不懂如何安装,请咨询电工的帮助。 开源地址:https://github.com/arendst/Tasmota 官方文档:https://tasmota.github.io/docs/ 中文网站:http://tasmota.com.cn/ 结语 "Tasmota"为那些想要打造自己的智能家居系统的人提供了一个强大的工具。它的多平台支持和开源性质使其成为一个灵活和可定制的解决方案,能够满足不同用户的需求。如果您对智能家居技术和自动化控制感兴趣,"Tasmota"可能是一个值得考虑的选择,让您更好地管理您的家庭环境,提高生活的便利性。 --- ### 373. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 TuyaLink 协议是涂鸦 IoT 开发平台面向物联网开发领域设计的一种数据交换规范,数据格式为 JSON,主要用于设备端和涂鸦 IoT 开发平台的双向通信,更便捷地实现了设备端和平台之间的业务数据交互。 设备的通信方式也是多种多样的。无线通信方式有蓝牙 LE、Zigbee、蓝牙 Mesh、433 协议,有线通信方式有 RS-485、RS-232、以太网以及各种工业协议等。但通信只是建立一个数据通道,要想真正运作起来,还需要了解数据包格式协议。数据协议包括 OCPP、Modbus、工业标准协议和其他自定义协议等。 本文介绍的 Tuya MQTT 标准协议是其中一种协议,也是涂鸦物联网平台最底层的基础通讯协议。开发者可根据协议完全自主地进行嵌入式开发,该协议可支持所有设备的集成。 本文以一款常见的 MQTT 客户端 MQTT.fx 为例,模拟设备使用涂鸦开放的 MQTT 协议接入涂鸦云。 MQTT 接入点 涂鸦 IoT 开发平台支持全球多个区域的设备接入,故需要根据设备实际使用的区域,来选择对应的接入点。 全球 6 大区 MQTT 接入点如下: 区域MQTT 接入域名端口号中国数据中心m1.tuyacn.com8883中欧数据中心m1.tuyaeu.com8883美西数据中心m1.tuyaus.com8883美东数据中心m1-ueaz.tuyaus.com8883西欧数据中心m1-weaz.tuyaeu.com8883印度数据中心m1.tuyain.com8883 环境准备 在 涂鸦 IoT 开发平台 创建产品,获取如下参数值。详细创建产品的过程请参考 选品类创建产品。 参数名称参数说明ProductID产品的信息DeviceID设备的身份信息,用于连接云端授权和通信使用DeviceSecret设备的密码信息 ,用于连接云端授权使用 接入示例 配置 MQTT.fx 接入文件 1.在 MQTT.fx 官网下载并安装相应操作系统版本的 MQTT.fx 客户端。 2.打开 MQTT.fx 软件,单击菜单栏中的 Extras 选项,并选择 Edit Edit Connection Profiles。 3.在 Edit Edit Connection Profiles 页面中填写相关参数。 参数名称参数说明Profile Name输入您的自定义名称Profile TypeMQTT 服务器连接,选择 MQTT BrokerBroker AddressMQTT 接入域名,对应 MQTT 协议中的域名,此处以中国区域名 m1.tuyacn.com 为例Broker Port通信端口号,设置为 8883Client IDMQTT 协议字段,格式为 tuyalink_{$deviceid}General使用默认值即可 4.选择 User Credentials 并填写相关参数。 参数名称参数说明User Name${deviceId}|signMethod=hmacSha256,timestamp=${当前 10 位时间戳},secureMode=1,accessType=1;例如:6c828cba434ff40c074wF2|signMethod=hmacSha256,timestamp=1607837283,secureMode=1,accessType=1PasswordhmacSha256(content, deviceSecret),content 的值"deviceId=6c828cba434ff40c074wF2,timestamp=1607635284,secureMode=1,accessType=1",按照 deviceId,timestamp,secureMode,accessType 这个顺序组装明文内容。64 位字符的 16 进制数,不足 64位时前面需要补零。 此处涉及到的 DeviceID 和 DeviceSercet 信息在 IoT 平台注册设备时生成,可参考 环境准备 章节找打到相应参数,Password 加密信息可以通过 Hmac 在线计算工具生成。示例如下: 5.选择 SSL/TLS,选中 Enable SSL/TLS 并设置 Protocol 为 TLSv1.2。 6.单击右下角 OK 完成设置,再去主页面单击 Connect。等待右侧指示灯变绿,表示连接成功。 测试通信 上行通信 在 Publish 页面输入发布的 topic,并填写 payload 信息,点击 Publish,此处以 tylink/6c855a6e81c40a91e9k5gx/thing/model/get topic 为例进行介绍。 进入涂鸦 IoT 开发平台的设备日志页面,输入 DeviceID 信息,可以看到刚才发布的消息,证明上行通信已经成功。 下行通信 在 Subscribe 页面输入 topic,点击 Subscribe,客户端会出现一条订阅的信息,此处以 tylink/6c855a6e81c40a91e9k5gx/thing/property/get_response topic 为例进行介绍。 进入 Publish 页面,输入与订阅对应的 topic 信息,并点击 Publish 发布 返回到 Subscribe 页面,可以看到刚才订阅的 topic 收到了云端的信息。 总结 涂鸦IoT平台的Tuya MQTT标准协议是一种基础通讯协议,用于支持各种设备的集成。文章以MQTT.fx客户端为例,介绍了如何使用涂鸦的开放MQTT协议接入涂鸦云。涂鸦IoT平台为全球多个区域提供设备接入支持,因此需要根据设备所在区域选择相应的MQTT接入点。文章还详细描述了如何在MQTT.fx中配置接入设置,包括Broker地址、端口、客户端ID、用户凭证和SSL/TLS设置。这一流程旨在帮助开发者理解并实现设备与涂鸦云之间的有效通信。 --- ═══════════════════════════════════════════ ## 未分类 ═══════════════════════════════════════════ ### 374. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、项目背景 随着工业化和城市化的快速发展,污水排放量日益增加,对环境造成了严重的影响。为了保护水资源,减少污染,实现可持续发展,必须对污水进行有效处理。本方案旨在介绍一种综合性的污水处理流程,包括一级、二级和三级处理,以确保污水达到排放标准,减少对环境的影响。 二、污水处理流程 一级处理(物理处理) 目标:去除污水中的悬浮固体(SS)。方法:通过粗格栅拦截大颗粒固体,然后通过污水提升泵提升污水,再经过细格栅或砂滤器进一步去除较小的悬浮物。结果:BOD(生物化学需氧量)可去除约30%,但不足以满足排放标准。二级处理(生物处理) 目标:去除污水中的胶体和溶解性有机物(BOD,COD)。方法:活性污泥法:通过曝气池或氧化沟,利用微生物降解有机物。生物膜法:在生物滤池、生物转盘、生物接触氧化法和生物流化床中,微生物附着在载体上,降解流过污水中的有机物。结果:有机物去除率可达90%以上,使有机污染物达到排放标准。三级处理(高级处理) 目标:进一步去除难降解有机物、氮、磷等可导致水体富营养化的可溶性无机物。方法:生物脱氮除磷法:通过微生物的代谢作用,去除污水中的氮、磷。混凝沉淀法:通过添加混凝剂,使微小悬浮物聚集成大颗粒,便于沉淀。砂滤法:通过砂滤器去除残留的悬浮物。活性炭吸附法:利用活性炭的吸附作用,去除有机物和部分无机物。结果:进一步提高污水的清澈度,减少对水体的污染。三、污泥处理 污泥回流:将二级处理产生的污泥部分回流至一级处理的初次沉淀池或生物处理设备,以提高处理效率。污泥浓缩:通过污泥浓缩池减少污泥的体积。污泥消化:在污泥消化池中,通过微生物的作用减少污泥的有机物含量。污泥脱水和干燥:通过脱水和干燥设备,将污泥转化为可利用的资源。四、监测与控制 实时监测:在整个处理过程中,通过安装液位变送器、流量计、水质分析仪等设备,实时监测污水处理的效果。自动化控制:通过集成控制系统,实现污水处理过程的自动化,确保处理效率和稳定性。五、项目实施 设计阶段:根据污水的具体成分和排放标准,设计合理的处理流程和设备配置。施工阶段:严格按照设计要求进行施工,确保工程质量。调试阶段:完成施工后,进行设备调试和系统优化,确保处理效果达到预期目标。运营阶段:建立完善的运营管理体系,定期维护设备,确保污水处理设施长期稳定运行。六、环境与社会效益 环境保护:通过有效处理污水,减少对水体的污染,保护水资源。资源回收:将污泥转化为可利用的资源,实现废物的再利用。社会责任:通过提供清洁的环境,提升社会生活质量,履行企业的社会责任。 通过实施上述污水处理方案,可以有效去除污水中的污染物,保护环境,同时实现资源的可持续利用,为社会和经济的可持续发展做出贡献。 --- ### 375. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智能玻璃温室整体方案 随着现代科技的不断发展,智能玻璃温室作为农业生产的一种创新模式,正在逐渐受到人们的关注和青睐。智能玻璃温室通过融合先进的玻璃材料、智能控制技术以及现代农业种植理念,实现了对温室内环境的精准调控,提高了农作物的生长质量和产量。本文将介绍一种智能玻璃温室的整体方案,旨在为农业生产提供更加高效、智能的解决方案。 背景 传统的温室种植存在着环境控制不精准、资源利用不充分等问题,为此,智能玻璃温室应运而生。智能玻璃温室利用先进的玻璃材料,如光学玻璃、光热转换玻璃等,结合智能控制系统,实现对温室内温度、湿度、光照等环境参数的精准调控,从而提高农作物的生长速度和品质。 与传统温室相比,智能玻璃温室具有以下优点: 高效节能智能玻璃温室可以通过自动控制系统,根据温室内部的温度、湿度、天线等环境参数,对温室内部的采暖、通风、通风等系统进行定制控制,从而提高能源利用效率,降低生产成本。智能玻璃温室还可以采用太阳能、风能等可再生能源作为辅助能源,进一步提高能源利用效率,减少环境污染2.精准控制智能玻璃温室可以通过传感器、物联网等技术,实时采集温室内部的环境数据,并进行自定义分析,从而对温室内部的温度、湿度、天线、空中浓度等环境参数进行精准控制,为作物提供生长大概的环境条件。智能玻璃温室还可以根据作物的不同生长阶段,对环境参数进行动态调整,满足作物生长的不同需求。3、提高产量在自动化控制的环境下,作物可以获得更大的生长条件,从而提高产量和质量。智能玻璃温室还可以通过病虫害监测预警系统,及时发现和防治病虫害,减少农作物损失。 降低劳动强度智能玻璃温室可以通过自动化控制系统,实现对温室内部的灌溉、施肥、采收等阶段的自动化管理,减少劳动强度,提高生产效率。5、降低环境影响智能玻璃温室可以通过自动化控制系统,减少化肥、农药的使用量,降低对环境的影响。6.提高农业生产水平 整体方案 1. 温室设计与材料选择 智能玻璃温室的设计应考虑温室结构的稳固性、采光性以及隔热性。选择优质的玻璃材料,如光学玻璃和光热转换玻璃,能够最大程度地吸收和利用太阳能,提高温室内的光照强度和温度,促进作物生长。 2. 智能控制系统 智能玻璃温室应配备智能控制系统,实现对温室内环境的实时监测和精准调控。该系统可监测温室内的温度、湿度、光照等参数,并根据作物的生长需求,自动调整温室内的通风、遮阳、灌溉等设备,保持良好的生长环境。 3. 节能环保设施 智能玻璃温室应配置节能环保设施,如太阳能发电系统、雨水收集系统等,实现对能源和水资源的有效利用。太阳能发电系统可为温室提供清洁能源,减少对传统能源的依赖;雨水收集系统可收集雨水用于温室的灌溉,减少对地下水资源的开采。 4. 数据监测与分析 智能玻璃温室应配置数据监测与分析系统,实时监测温室内环境参数的变化,并对监测数据进行分析和统计,为农业生产提供科学依据。通过对温室内环境和作物生长情况的分析,可以及时调整温室的运行参数,提高农作物的产量和品质。 结语智能玻璃温室作为一种新型的农业生产模式,具有节能环保、高效稳定等优势,对于提高农业生产效率、保障粮食安全具有重要意义。未来,随着智能技术的不断发展和应用,智能玻璃温室将会得到更广泛的应用,为农业产业的可持续发展做出更大的贡献 总的来看,智能玻璃温室是一种具有节能、精准控制、提高产量、减少劳动强度、降低环境影响等优点的现代化农业生产设施。 智能玻璃温室的应用,可以提高农业生产的科技含量和现代化水平,推动农业生产方式的转型升级。 总的来看,智能玻璃温室是一种具有节能、精准控制、提高产量、减少劳动强度、降低环境影响等优点的现代化农业生产设施。 --- ### 376. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智慧公园+智慧步道+智慧园+智慧社区整体解决方案 概述 本方案旨在为城市提供一套完整的智慧化解决方案,涵盖智慧公园、智慧步道、智慧园区和智慧社区四大板块,以AI技术为核心,利用物联网、云计算、大数据等新一代信息技术,打造安全、舒适、便捷、智能的城市环境。 方案详情 智慧公园 建设智慧健身路径、智慧健身步道,为市民提供便捷的健身服务。 利用AI技术,进行人脸识别、行为分析等,提升公园的安全管理水平。 建设智慧导览系统,为游客提供便捷的游览服务。 智慧步道 利用物联网技术,采集步道上的环境数据、运动数据等,为市民提供健康指导服务。 建设智慧安防系统,保障步道安全。 建设智慧驿站,为市民提供休憩、充电等服务。 智慧园区 建设智慧安防系统,保障园区安全。 建设智慧办公系统,提升园区办公效率。 建设智慧能源管理系统,节约能源。 智慧社区 建设智慧安防系统,保障社区安全。 建设智慧物业管理系统,提升物业管理效率。 建设智慧生活服务平台,为居民提供便捷的生活服务。 结语 本方案为城市提供了一套完整的智慧化解决方案,可有效提升城市治理水平和居民生活质量。sharemore_vert --- ═══════════════════════════════════════════ ## 档案库房 ═══════════════════════════════════════════ ### 377. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 系统背景: 档案库房是档案保管的关键地点。随着社会的不断发展和进步,档案的分类越来越精细,内容变得更加多样化,信息量和数量也不断增加。全国范围内有成千上万的档案馆,其中包含许多非常重要的机要档案,这些档案具有极高的历史和社会价值。然而,档案的保存质量、物理寿命以及对虫害和霉菌的防控都与库房的空气质量、温湿度密切相关。 目前,大多数档案馆的环境监测仍处于人工巡检和手动温湿度调控阶段。一旦档案库房的温湿度失控,安全措施不到位,档案维护就会成为一个严重问题。 系统依据: 档案库房环境监控系统充分应用现代科学技术手段,将传感技术、自动化技术和信息化技术相结合。同时,根据相关法规和规定,如《机关档案管理规定》(档案局第13号令)、《档案法》、《档案馆建筑设计规范》(JGJ25-2010)、《档案馆建设标准》(建标103-2008)、《档案安全保护技术管理暂行规定》等技术规范要求,确保系统能够实现对档案库房温湿度的及时有效调节和控制。这样,档案库房内的温湿度将保持在科学合理的范围内,并实现数据的可查询和可追踪,从而有助于实现档案资料的长期保存和完好性,最大限度地发挥其社会价值。 系统介绍: 档案库房环境监控系统集成了软硬件,采用基于Linux操作系统的B/S架构。它主要由以下组成部分构成:设备层(包括温湿度传感器、水浸传感器、光照传感器、红外探测器、空气质量传感器、工控模块、精密空调、加湿除湿消毒一体机、UPS电源、摄像头、门禁和其他测控设备)、管理装置、局域网服务器、采集计算机、数据服务器、Web服务器以及监控管理软件等。该系统采用先进的软硬件技术和分层分布式网络结构,以满足客户的实际需求,提供全面的解决方案。 这一系统的设计目标是通过现代科学技术手段,实现对档案库房的全面监控和管理,以确保档案的长期保存和完好性,最大限度地发挥其社会价值。 系统功能详细说明: 1. 温湿度自动调控系统: 这一功能允许系统采集库房内的温湿度数据,将这些数据上传至监控平台,并根据预设的温湿度要求自动控制空调、除湿机、加湿机等设备,以实现对温湿度的有效管理。 2. 漏水监测系统: 漏水对库房内储存物品的质量和电气设备的使用构成潜在威胁。在档案室的门窗周围、管道周围、空调和加湿除湿一体机的进水和排水管道等区域存在多个潜在的漏水隐患。因此,需要在相应位置安装漏水传感器,实时监测漏水情况,以便在出现漏水时立即报警,并通知相关人员采取必要的措施。 3. 环境质量监控系统: 除了监测温湿度参数之外,这一系统还监测空气质量,包括PM2.5、PM10、甲醛、室内粉尘和CO等气体的浓度。如果空气中这些气体的浓度超过标准,可能会增加档案在环境中的腐蚀性风险,也容易导致档案受到灰尘积累的影响。因此,对库房内的空气质量参数进行监测尤为重要。当各气体指标超标时,系统可以联动新风系统进行换气,以保持档案库房内的空气质量在正常范围内。 4. 自动防火报警系统: 这一系统由烟感探测器、温度探测器和声光报警器组成,用于检测火警情况。当发生火警时,监控主机将触发声光报警,并通过语音形式报告警情类型。 5. 自动防盗报警系统: 该系统使用人体红外探测器,可以实时监控库房的门、窗、走廊等入口处的人员进出情况。对于非法入侵者,系统将触发声光报警器,发出声音和光线警报,并通过电话通知相关人员采取及时处理措施。此外,系统还支持分时段报警,以避免对正常进出的工作人员产生误报。 6. 灯光照明监控系统: 通过光照感应器实时监测光照强度,以控制电动窗帘和照明系统,自动降低灯光对档案资料的照射。此外,系统还安装了灯光照明检测模块,使控制室可以方便地观察库房的灯光状态,包括开关情况。 7. 电力监控系统: 该系统实时监测电力供应的通断情况,并能够发出告警。通信主机可以连接到UPS(不间断电源),以提供30分钟以上的延时供电,以确保设备在断电后能够及时报警。 8. 智能卡门禁管理: 系统通过电控门锁、身份验证和记录出入信息,实现对库房大门的智能化门禁管理。只有经过刷卡和密码验证的工作人员才能进入库房。此系统还记录工作人员的进出信息,以便以后的追溯查询。 9. 视频监控系统: 该系统使用数字硬盘录像技术,安装红外摄像机,提供24小时不间断图像监控,并支持录像记录和回放功能。 10. 数据集中监测与报警: 此系统具备多库房跨区域的集中监控和管理功能,通过树形列表、数据图表或地图方式展示各楼层库房的环境数据。 11. 数据统计报表: 监控系统提供各站点的监测数据的日、月、年统计,以及可以根据客户需求定制的报表。系统支持数据报表的导出功能。 12. 灵活定制开发: 该系统具有高度的定制性,可以根据用户的实际需求进行界面和功能的定制和扩展,以满足不同用户的特殊要求。 --- ═══════════════════════════════════════════ ## 水利管网 ═══════════════════════════════════════════ ### 378. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 全球每年产生约3590亿立方米的废水,相当于1440万个奥运游泳池的容量。在全球范围内,将大量废水入河流、海洋和溪流是一种常见做法。这种做法对环境、渔业和动物产生极为负面的影响,更不用说它对水资源的浪费了。废水处理对于保护环境、确保我们最有效地利用资源至关重要。 让我们探讨一下废水行业面临的一些问题,以及物联网如何帮助解决这些问题,最后讨论MQTT在支持物联网用例方面的作用。 废水行业面临的挑战 废水行业面临着从环境关切到基础设施和管理问题等多种挑战。一些主要挑战包括: 老化基础设施许多国家的水和废水基础设施老化,需要维修或更换。老化基础设施导致漏水、破裂和低效,导致水资源浪费和潜在水源污染。 水污染工业废水排放、农业径流和垃圾不当处理导致水污染。化学物质、重金属、病原体和营养物质等污染物质可能降低水质,对人类健康和生态系统构成风险。 能源消耗水和废水处理过程需要大量能源投入,导致温室气体排放和运营成本增加。寻找减少能耗和提高能效的方法对可持续性和经济效益至关重要。 要解决这些问题,需要政府、公用事业、行业利益相关者和公众之间的合作,以及对研究、技术开发和基础设施改善的投资。 物联网技术如何解决一些挑战 物联网(物联网)技术通过提供实时资产监控、数据分析和自动化能力,对废水行业的各种挑战起到了重要作用。 以下是物联网如何解决主要挑战的一些方法: 预测性维护通过持续监测设备状况和性能指标,物联网启用的预测性维护系统可以预测设备何时可能故障或需要维护。这种积极的方法可以最小化停机时间,降低维护成本,并延长关键基础设施组件的寿命。 水质监测物联网传感器可以实时监测各种参数,如pH值、浑浊度、溶解氧和化学浓度。这使得能够及时检测污染物或异常,使水务部门能够迅速采取纠正措施,以维护水质并符合法规。 泄漏检测和水损管理装有泄漏检测传感器的物联网设备可以快速识别水配送网络中的泄漏。通过确定泄漏位置并监测流速,水务部门可以最小化水损失,节约资源并提高效率。 总体而言,物联网技术使水和废水公用事业能够提高运营效率,改善资源管理,确保法规遵从,并向客户和社区提供更好的服务。 MQTT如何实现物联网数据的可用性以支持水和废水管理 MQTT是一种轻量级的消息传递开放标准协议,在物联网中用于数据传输,专为在低带宽、高延迟或不稳定网络中进行有效通信而设计。在废水行业,MQTT可以通过促进实时数据交换、远程监测和控制,帮助解决各种物联网数据挑战。 为什么选择MQTT协议用于物联网?以下是MQTT的帮助方式: 实时监控MQTT实现了从废水系统中各个点传输传感器数据到集中监控系统的实时传输。这是因为它是一种事件驱动的架构,可以提供实时的最新数据。这使得操作人员能够持续监测水质、流速、压力水平和设备状态等参数,有助于及时检测异常或问题。MQTT物联网平台通过启用泄漏检测、对井、泵、电机和用水系统进行远程监控和控制,帮助LEC实现减少或消除客户水资源浪费的目标。 可伸缩性和灵活性 MQTT的轻量级和高效的特性使其非常适用于分布式废水基础设施的大规模部署。它支持发布-订阅消息传递模型,允许多个客户端订阅相关的数据主题,而不会对网络资源造成不必要的负担。MQTT物联网平台提供先进的可伸缩性功能,经过基准测试,最多支持1亿活跃客户端。 可靠性和韧性MQTT的发布/订阅架构以及对服务质量(QoS)级别的支持确保在网络条件或断断续续的连接情况下也能可靠地传递消息。这种可靠性对于在遥远或恶劣环境中保持对水和废水系统的持续监测和控制至关重要。HiveMQ为关键应用提供了企业级可靠性的IoT数据。 数据集成和互操作性MQTT便于与水和废水设施常用的SCADA(监控与数据采集)、DCS(分布式控制系统)、PLC(可编程逻辑控制器)和物联网系统无缝集成。它促进了不同设备和平台之间的互操作性,确保平稳的数据交换和系统优化。MQTT物联网平台提供了可以将一些常见的机器协议转换为MQTT并帮助打包用于高级分析的物联网数据的设备驱动程序。 安全性MQTT支持各种安全机制,如传输层安全(TLS)和身份验证机制,确保安全的通信和数据完整性。这对于保护敏感数据、防止未经授权访问或篡改水和废水系统至关重要。MQTT物联网平台提供了一个具有高级安全功能的企业级代理。 边缘计算MQTT可以与边缘计算平台结合使用,以在网络边缘进行数据预处理、分析、边缘人工智能和决策。这降低了延迟,节约了带宽,并使对水和废水系统中关键事件或报警的更快响应成为可能。 MQTT:彻底改变废水管理流程的开放标准MQTT通过实现实时监测、远程控制、数据集成和自动化,对废水运营的效率、可靠性和韧性发挥着至关重要的作用。其开放标准、轻量级、可伸缩和互操作的特性使其非常适用于解决行业面临的复杂挑战。它通过使废水中的物联网解决方案能够优化运营并提高安全性。 --- ═══════════════════════════════════════════ ## 汽车与出行 ═══════════════════════════════════════════ ### 379. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 背景: 经历了新冠疫情的冲击后,汽车制造业正稳步复苏。面对日益激烈的市场竞争和不断变化的客户需求,制造商们意识到,数字化转型和工业4.0技术是提升竞争力和实现可持续发展的重要途径。 调查结果: 2023年AMS/ABB汽车制造业展望调查揭示了以下关键洞察: 挑战并存: 供应链中断仍然是制造商关注的问题 (35%),但其重要性已被不断加剧的劳动力和技能短缺问题 (36%) 所超越。此外,电动化转型、成本控制、可持续发展等议题也为行业发展带来了新的挑战。 多元化的动力总成解决方案: 调查显示,未来动力总成技术尚无明确的领先者。电池电动和氢燃料电池混合动力 (25%) 领先,其次是氢燃料电池汽车 (23%) 和先进电池 (22%),氢燃烧技术也获得了显著关注 (11%)。 积极的展望: 尽管存在经济不确定性,但总体而言,行业前景乐观。76% 的受访者预计车辆产量将保持稳定或增长,相比之下,2022 年这一比例为 56%。同样,69% 的受访者认为车辆销量将保持稳定或增长,相比之下,2022 年这一比例为 54%。此外,需求已成为车辆产量的主要制约因素 (55%),取代了 2022 年的生产 (57%),表明供应链问题有所缓解。 MQTT物联网平台如何助力汽车制造商: 应对挑战: 提升供应链韧性: MQTT物联网平台可以实现供应链数据的实时采集和分析,帮助制造商提高供应链可视性,及时识别并应对突发事件,有效降低供应链中断风险。 赋能数字化劳动力: MQTT物联网平台可以连接工厂设备和生产系统,实现生产数据的实时采集和分析,帮助制造商构建智能制造体系,提升生产效率,优化资源配置,缓解劳动力短缺问题。 加速电动化转型: MQTT物联网平台可以连接电动汽车和充电桩,实现车辆数据和充电数据的实时采集和分析,帮助制造商优化电动汽车的生产、运营和管理,加速电动化转型。 降低运营成本: MQTT物联网平台可以帮助制造商优化生产流程,提高资源利用率,降低能源消耗,减少浪费,有效降低运营成本。 实现可持续发展: MQTT物联网平台可以帮助制造商提高生产效率,减少资源消耗,降低污染排放,实现可持续发展目标。 拥抱未来技术: 构建车联网生态: MQTT物联网平台可以连接车内外の设备和系统,实现车联网数据的实时采集和分析,帮助制造商构建车联网生态,提供个性化、智能化的车联网服务。 推动智能驾驶发展: MQTT物联网平台可以为自动驾驶汽车提供实时路况、交通信号灯等信息,帮助汽车实现更安全、更高效的自动驾驶。 赋能数据驱动决策: MQTT物联网平台可以将生产、运营、销售等数据进行统一管理和分析,帮助制造商实时洞察市场需求和产品性能,做出更智能、更有效的决策。 应用案例: 宝马集团使用MQTT物联网平台连接全球生产设施,实现实时数据采集和分析,提升生产效率和产品质量。 特斯拉使用MQTT物联网平台连接其电动汽车和充电网络,实现车辆数据和充电数据的实时采集和分析,优化车辆管理和充电服务。 福特汽车使用MQTT物联网平台构建车联网平台,提供个性化、智能化的车联网服务,提升用户体验。 结论: 数字化转型和MQTT物联网平台是汽车制造业未来发展的关键驱动力。通过拥抱数字化转型和MQTT物联网平台,汽车制造商可以提升竞争力,实现可持续发展,并在未来竞争中取得成功。 --- ### 380. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 离散制造是指生产独立、可辨认且易于计数的独立物品或单元的过程。这种制造类型涉及将组件或零件组装成成品,其中每个物品都可以与其他物品区分开。典型的离散制造行业包括汽车、电子、航空航天、机械和医疗设备。这些行业通常在生产过程中使用物料清单(BOMs)和质量控制措施。离散制造允许定制、灵活性和高效生产各种产品。 离散制造的常见过程 生产计划和调度 离散制造需要对整个生产过程进行仔细的计划和调度,以确保所需的零部件在需要时可用。调度定义了每个生产阶段需要多长时间以及每个人应该工作多少时间,以确保按时完成生产。生产计划需要优化,以最小化浪费并最大化效率。因此,供应链数据的可见性非常重要。 批量大小和交货期的优化 批量大小突显生产的数量,而交货期指整个过程所需的时间。这两个参数都影响生产效率,因此必须进行优化以获得更好的产出。实时数据的可见性和准确性非常重要。 离散制造的常见系统 计算机辅助设计(CAD) CAD软件用于设计产品,概念化想法以考虑确保最终产品完美的细节。该工具执行快速设计计算和模拟,有助于创建准确和精确的产品设计。 计算机辅助制造(CAM) 计算机辅助制造实现了管理过程的自动化,允许跟踪生产过程、资源和运输。 企业资源规划(ERP) ERP的实施提供了对库存和整个生产过程更好的控制和可见性。借助ERP,平台检查不同类型的数据和信息,并在所有点上使其可访问和可用。 产品生命周期管理(PLM) PLM确保从概念化时直到最终发运时对产品的整个生命周期进行管理。 工业物联网(IIoT)和MQTT作为连接系统的启用器 在离散制造中,IIoT在通过传感器和可编程逻辑控制器(PLC)将各种OT系统连接到上述IT系统方面发挥着重要作用。这种OT-IT连接实现了数据交换和数字化转型用例,例如,ERP系统中的订单数据需要与PLM中的生产数据相结合,以便能够进行正确的预测、计划和调度。IIoT使这些系统能够彼此通信,并通过MQTT等消息传递技术创建一个单一的窗格。 MQTT在离散制造应用中的作用 实时数据通信 MQTT在离散制造中实现了设备、系统和应用程序之间的实时通信,有助于将它们连接到企业和/或云,支持预测性维护、远程监视、数字孪生和先进的分析等高级数据用例。MQTT还促进了无显著延迟的制造设备之间的无缝机器对机器通信,这对于监视和控制离散制造非常关键,确保数据迅速而高效地交换。 可扩展性 MQTT具有很高的可扩展性,可以同时支持大量设备、系统和应用程序。在离散制造中,其中许多设备、系统和应用程序部署在生产现场,MQTT的可扩展性对于处理多样化的数据来源至关重要。提供企业级MQTT代理的HiveMQ具有额外的可扩展性功能,并已进行了2亿并发连接的基准测试。 带宽使用效率 MQTT在带宽使用效率方面设计得非常高效。在网络带宽可能有限的制造环境中,MQTT的轻量级协议确保数据可以在不给网络基础设施带来额外负担的情况下进行高效传输。 可靠性和服务质量(QoS) MQTT支持不同级别的服务质量,允许制造商选择适用于其特定用例的可靠性级别。这对于可靠的数据交换至关重要,例如远程监视关键设备。MQTT通过支持保留消息来提供额外的可靠性,其中代理会保留在特定主题上发送的最后一条消息。这个特性在离散制造中非常有用,以确保连接到网络的设备在连接时接收到最新的相关信息。HiveMQ MQTT代理提供了额外的可靠性功能,包括支持无主集群架构、可靠的通信和零停机升级。 安全性 MQTT本身提供通信的安全性,因为它基于对主题命名空间的订阅。因此,未订阅特定主题的任何客户端都不会接收到消息。除此之外,可以在MQTT上实施额外的安全功能,包括用户ID/密码、TLS加密、X.509 客户端证书授权等机制,以确保离散制造通信的安全性。 发布-订阅模型 MQTT采用发布-订阅模型,其中客户端可以将消息发布到特定主题,而其他客户端可以订阅这些主题以接收消息。这个模型非常适合离散制造场景,其中不同的组件需要实时了解相关事件或实时变化。除此之外,数据框架如Sparkplug和统一命名空间等概念提供了其他有效组织数据的方式。 边缘计算集成 MQTT通常与边缘计算一起在离散制造中使用。边缘设备、应用程序和系统使用MQTT在本地彼此通信,有选择地与服务器/云通信,从而减少将所有数据发送到中心服务器的需求。这可以提高响应时间并减少延迟。边缘网关可以将来自各种协议(如OPC UA、Modbus和Siemens S7)的数据转换成MQTT,并将数据传送到代理进行处理。 MQTT对离散制造中IIoT数据通信的改变 离散制造中的IIoT改善了效率、质量、维护和整体运营效果。通过使用可靠且高效的通信机制(如MQTT)实现数据通信,离散制造系统可以高效支持对工厂生产中各种设备、流程和应用程序的实时监视,并支持先进的数据用例。MQTT所带来的连接性使离散制造得以数字化转型,从而实现更高的效率、降低成本、更好的客户体验和更高的盈利能力。 --- ### 381. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在汽车制造行业中,物料的及时交付对于保持生产的顺利进行至关重要。诸如物料短缺、库存水平低以及质量控制问题等供应链中断会导致制造中断,最终造成经济损失。因此,工厂物流经理和生产经理必须努力保持供应链的流动,以维护制造过程中的质量和按时交付。 好消息是,有了正确的技术工具,你可以防止供应链的小问题演变成制造停机时间。让我们讨论一下现代汽车制造中的挑战,以及MQTT平台如何提供端到端的解决方案,帮助你保持主动而不是被动。 汽车制造供应链挑战 想象一下,期待着收到500个关键部件的运输,却只到达200个,这最终将导致生产线停机和库存危机。这是汽车制造商常见的痛点,供应链中的中断很快就会雪球般增大。问题不仅仅是运输短缺,而是直到货物到达并从卡车上卸下来时才知道。到那时要调整已经太晚了,两天后当材料用完时生产线将会停止。 大多数制造商根本没有这种对其供应链和物流的可见性,原因有多种。他们没有部署工业物联网解决方案来连接所有资产,实时跟踪它们,并根据这些情报采取行动。他们依赖于位于互联网连接有限的偏远地区的供应商,这使得跟踪运输和及时获取关键物流信息变得困难。 在问题出现时才采取应对措施的传统方法成本极高,已不再足够,因此汽车制造商正寻求建立正确的技术基础设施来克服这些挑战,及时将正确的信息传达给正确的人,以主动避免停机或质量问题。 实现端到端可见性 解决方案的出现。利用MQTT平台,帮助在OT和IT系统之间创建一个安全、可靠、可扩展的数据抽象层。一个集中的代理无缝连接各种系统,如运输管理、仓库管理和内部制造数据库。通过使用MQTT集成这些系统,整个供应链和制造过程变得相互连接,并且可以实时访问。 如何工作: 端到端可见性:从材料离开供应商的那一刻到它们融入装配线以及之后,MQTT物联网平台提供一个端到端的故事。实时跟踪确保每一步都被监控,任何偏差都会立即被标记。 自动警报:短缺或接收到的材料出现差异将触发自动警报,防止问题在库存水平变得关键之前被忽视。这种主动的方法对于维持生产数量和效率至关重要。 低带宽:在互联网连接较差的地区,MQTT的低带宽和小数据包大小变得至关重要。这确保即使在偏远地区,实时数据消息仍然可能。 预测分析:一个集中的仪表板,由诸如Grafana或云分析工具之类的分析工具提供支持,汇总来自MQTT代理的数据。这个仪表板提供了对生产线、供应链问题和潜在中断的可操作见解,使团队能够在问题升级之前解决它们。 预防关键停机时间,节省成本,提高效率 有了实时连接的正确解决方案,汽车制造商可以在它们导致关键停机之前识别并解决供应链中断。主动解决问题消除了最后一刻采取昂贵解决方案(如空运或加急运输)的需要,从而降低了整体成本。 端到端的可见性和沟通使制造商能够优化生产过程,提高整体效率,并始终如一地满足生产目标。 --- ### 382. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着整个汽车出行领域智能化和网联化的发展,车机成为连接“人-车-云”之间的交互窗口,是当前汽车智能化、网联化的核心组成部分。这一“人-车-云”的交互窗口不仅能够实时获取车辆数据和车主使用情况,而且为车主提供了一系列个性化的服务,如寻车定位、个人兴趣点推送等。因此,各大汽车制造厂商正积极构建基于数据和服务的车联网TSP平台系统,旨在提供更智能、人性化的驾驶体验。 在构建能够满足当今消费者多样需求的车联网 TSP 平台时,汽车主机厂面临着一系列技术挑战。这些挑战包括可靠的车云连接、有效的数据传输以及灵活的数据处理等方面。为了应对这些挑战,EMQ提供了一套车云互联基础设施解决方案,助力客户应对海量车机、Tbox与云端TSP的连接与上下行数据交互需求。以下是基于EMQX的高性能、高可用车联网TSP数据底座解决方案的一些关键特性。 MQTT协议:连接“人-车-云”的纽带 MQTT(Message Queuing Telemetry Transport)是一种专门针对低带宽、高延迟、不可靠网络等场景而设计的轻量级消息传输协议。其发布/订阅模式、会话保持机制、QoS消息质量机制使其在车联网场景中表现优越。EMQX作为基于MQTT协议的企业级数据接入平台,连接车辆和云端,提供连接和数据解决方案。EMQX的高性能、高可靠、可伸缩性设计,能够实时移动和处理车联网数据,帮助车企解决海量连接、高数据吞吐、安全认证、复杂网络环境等挑战,使开发团队能专注于上层应用的开发。 整体架构:分布式、高可用 为满足数据保护需求,车企的车联网平台通常采用私有化部署。EMQX集群和用户业务系统通常一同部署在IDC或公有云环境中。通过负载均衡与EMQX分布式集群部署,可实现百万级别的车机连接和数据吞吐能力,为上层业务应用提供坚实接入基础。 车机连接:高并发、高安全 车机通过蜂窝网络物理链路、MQTT协议接入EMQX,EMQX分布式高可用架构支持百万级并发连接。在连接安全方面,EMQX支持TLS安全协议,通过单向、双向TLS认证接入以及与PKI/CA系统对接,实现一机一密的认证方案。此外,EMQX提供实时感知连接状态的能力。 数据传输:多保障、高吞吐 依靠MQTT及EMQX提供的多重保障机制,即使车辆因网络原因断开连接,消息传递仍能在重连后恢复,实现在复杂的网络环境下实时、安全、可靠的车机消息通信。EMQX支持每个车机与平台连接内建立多个逻辑隔离的MQTT主题,支持上下行不同业务数据传输。 消息及事件的处理与集成:灵活、高效 通过内置的规则引擎,EMQX能够对车机上报数据消息及车机连接或断连等事件进行预处理,桥接集成到相应的数据系统。这使得海量车机上行数据能够经过编解码等预处理后,桥接到消息队列进行后台应用服务的分析应用。同时,EMQX支持对车机连接、断开连接等事件信息存储到数据库中,用于后续车辆上下线情况的分析等。 高效的监控运维:可视化、实时 EMQX提供直观的可视化监控和管理界面,用户可实时监控车机连接状态和消息流量指标。此外,EMQX支持接口将监控数据推送到客户监控系统,实现高效的监控运维。热配置修改、热升级的机制确保在配置调整时无需停止服务,最大程度保证车机连接及数据传输的持续性。慢订阅、日志追踪等功能帮助客户快速排查连接异常、消息接收时延过大等问题。 构建车联网 TSP 平台面临的挑战 随着汽车保有量不断增长,平台需要支持海量车机并发连接。在高峰时期,平台需要维持数十万量级的并发 连接。同时,为了实现丰富的业务场景,平台需要支持百万级的消息吞吐。随着车辆互联度的增加,车辆容易受到网络威胁,因此连接的安全性成为关键挑战。车辆所处网络环境的复杂性也带来了保证消息实时性与可靠性的挑战。最后,业务侧对数据的不同需求,如何实现灵活的数据分流、存储也是一个亟待解决的问题。 未来展望:智能出行的无限可能 面对车联网 TSP 平台的技术挑战,EMQX以其卓越的性能和灵活的解决方案助力汽车主机厂构建高性能、高可靠、易于维护的车联网TSP平台。未来,随着技术的不断演进,智能出行将迎来更多可能性,连接“人-车-云”的纽带将越发牢固,为用户创造更智能、便捷、安全的驾驶体验。EMQX将继续在智能车联网领域发挥重要作用,推动整个行业向更高水平迈进。 --- ### 383. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT协议的主题设计在车联网(TSP)平台中起着至关重要的作用,它不仅是消息通道的标签,也是业务与数据的关键区分点。在设计MQTT主题时,我们需要考虑一系列原则和最佳实践,以确保系统的可维护性、性能和安全性。 基础概念 MQTT协议涉及三个关键角色:消息发布者(publisher)、代理服务器(broker)和消息订阅者(subscriber)。消息从发布者发送到代理服务器,然后被订阅者接收,而主题则是发布者与订阅者之间约定的消息通道。 主题的定义与规范 MQTT协议规定主题是一段UTF-8编码的字符串,具体规则包括: 主题名和主题过滤器必须至少包含一个字符。 主题名和主题过滤器是大小写敏感的。 主题名和主题过滤器可以包含空格字符。 主题名或主题过滤器以前置或后置斜杠 / 区分。 主题名和主题过滤器不能包含null字符(Unicode U+0000)。 主题名和主题过滤器是UTF-8编码字符串,层级数量没有限制。 主题层级 MQTT协议允许通过斜杠将主题分割成多个层级,从而实现对消息类型的细分。例如,可以通过定义主题层级来区分不同车型、车辆或业务类型。 通配符 MQTT协议支持通配符,订阅者的主题过滤器可以包含特殊的通配符,如#和+,用于一次订阅多个主题,实现更灵活的消息订阅。 多层通配符(#)用于匹配主题中任意层级。 单层通配符(+)用于单个主题层级匹配。 车联网TSP平台场景中的需求 在车联网TSP平台场景中,MQTT协议作为车辆、平台和应用之间的业务消息通道,主题设计需要考虑不同数据方向、车型、车辆、用户、研发环境和数据吞吐量等因素。 主题设计原则最佳实践 根据业务数据方向区分:明确上行和下行数据的主题,有助于快速定位场景和问题。 根据车型区分:通过主题区分不同车型产生的数据,适应差异化的车辆数据和业务需求。 根据车辆区分:实现一对一消息通道,保证车辆间业务信息隔离和点对点交互。 根据用户区分:考虑用户级别的一对一消息通道,适用于促销、运营和ToB业务场景。 根据研发环境区分:通过添加环境变量实现在不同研发环境下的资源复用和正确性检查。 根据数据吞吐量区分:区分不同数据吞吐量的业务,适应不同的处理和架构设计。 通过以上主题设计原则,车联网TSP平台可以实现清晰的业务隔离、快速问题定位和灵活的消息通信,满足不同业务场景的需求。这种细致入微的设计有助于提高系统的可维护性和性能,为车联网生态的健康发展提供坚实基础。 --- ### 384. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着互联汽车服务的崭露头角,MQTT协议(Message Queuing Telemetry Transport)已经成为这一领域的关键技术之一。以下是四个关键技术考虑因素,以及MQTT在互联汽车中的应用,突出MQTT的优越性。 1. 规模的计划 互联汽车平台的规模是一个关键挑战,而MQTT协议在这方面表现出色。MQTT的轻量级特性使其在大规模部署中非常高效。它能够处理数以千计甚至数百万个连接,而不会过多消耗网络带宽。这使得互联汽车服务可以轻松地覆盖大量汽车,而不会引发规模性能问题。 2. 优先考虑可观察性 在互联汽车服务中,消息的可观察性至关重要,以便及时发现并解决问题。MQTT协议具有出色的可观察性,因为它支持主题订阅和发布模式。这意味着您可以轻松地监视消息的流动,并识别任何潜在问题。 此外,MQTT协议还支持分布式跟踪,使您能够跟踪消息在复杂系统中的传递。这有助于快速定位和解决潜在的问题,从而提高了系统的稳定性。 3. 内置安全性 互联汽车服务需要高度的安全性,以保护汽车和用户的数据。MQTT协议通过支持多种安全性措施,如TLS/SSL加密、身份验证和授权,提供了强大的安全性。 MQTT的安全性已经在多个行业中得到验证,包括金融和医疗领域,因此它是一个可信赖的协议。在互联汽车中,这种安全性尤为重要,以确保车辆和乘客的隐私和安全。 4. 易用性 MQTT协议的易用性也是其优势之一。它的轻量级特性和简单的消息发布/订阅模式使得汽车制造商和开发人员能够轻松集成MQTT到他们的互联汽车平台中。此外,MQTT协议已经有广泛的社区支持和成熟的工具,使得使用和管理MQTT变得非常容易。 总结来说,MQTT协议在互联汽车服务中发挥着重要作用,因其轻量级、可观察、安全和易用的特点而脱颖而出。它为互联汽车提供了可靠的消息传递和数据交换解决方案,有助于实现更智能、更安全的互联汽车体验。在构建互联汽车服务时,考虑到MQTT的优越性将有助于提高项目的成功机会。 --- ═══════════════════════════════════════════ ## 物联网 ═══════════════════════════════════════════ ### 385. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 ioBroker 简介: ioBroker 是一款专注于物联网领域的集成平台,其主要应用于楼宇自动化、智能计量、环境辅助生活、过程自动化、数据可视化和数据记录等方面。通过将各种设备和系统连接到一个统一的平台上,ioBroker 的目标是简化楼宇管理和自动化过程,提高生活品质,降低能源消耗,并为企业提供更高效的生产过程。 ioBroker 平台特点: 开放性: ioBroker 支持多种通信协议和设备接入,如 Modbus、OPC UA、BACnet 等,便于整合各种系统和设备。 分布式架构: 采用分布式架构,实现数据的实时处理和分析,降低网络延迟,提高系统响应速度。 高度可定制: 提供丰富的应用程序接口(API),允许开发者根据需求定制和开发相应的应用程序。 安全性: 关注数据安全和隐私保护,采用加密和身份验证等技术,确保数据传输和存储的安全。 云端服务: 提供云端服务,方便用户进行远程监控、数据分析和故障排查。 开源: 采用开源模式,用户可以免费下载和使用,降低了企业成本。 社区支持: 拥有活跃的社区,用户可以在社区中获取技术支持、分享经验和交流心得。 丰富的应用场景: 广泛应用于楼宇自动化、能源管理、智能家居、工厂自动化等多个领域。 楼宇自动化低碳管理系统功能和模块: 楼宇自动化低碳管理系统旨在实现建筑节能、降低碳排放、提高能源利用效率。它通常包括以下功能和模块: 数据采集与监测: 实时采集建筑内的能耗数据和环境参数。 数据分析与处理: 对采集到的数据进行统计、分析和解构,为后续优化提供依据。 能源计量与管理: 对建筑各部位的能耗进行分项计量,以便分析和诊断能源使用效率。 自动化控制与优化: 根据数据分析结果,对建筑的系统进行自动调节和优化,实现节能降耗。 设备管理与维护: 对建筑内的设备进行远程监控和管理,提高设备运行效率,降低维修成本。 碳排放监测与评估: 监测建筑的碳排放数据,评估碳排放强度,为低碳改造提供依据。 能效评估与诊断: 通过分析能耗和碳排放数据,对建筑的能效进行评估和诊断。 信息可视化与展示: 以可视化形式展示建筑的能耗数据、环境参数和设备运行状态。 预警与应急处理: 及时发出预警并提供应急处理建议。 智能化决策支持: 结合大数据分析和技术预测,为建筑管理者提供智能化决策支持。 ioBroker 链接和安装: GitHub 地址:GitHub - ioBroker/ioBroker: Automate your life! 网站地址:https://www.iobroker.net/ --- ### 386. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 物联网(IoT),作为科技发展的一个重要分支,已经逐渐融入我们的日常生活。它主要通过信息传感设备(如射频识别、红外感应器、全球定位系统、激光扫描器等)按照特定协议,对各种物品进行智能化连接、信息交换和通信,实现物品的智能识别、定位、跟踪、监控和管理。物联网的架构通常分为五个层次:感知层、网络层、数据层、应用层和业务层。本文旨在详细阐述这五层架构的组成和各自功能。 感知层(物理层) 感知层,也称为物理层,构成了物联网的基础。它的核心任务是利用各种传感器和设备收集环境信息,并将这些信息转换为电子数据。这些设备包括但不限于温度传感器、湿度传感器、光照传感器和压力传感器。同时,感知层还涵盖各种执行设备(如电机、继电器等),这些设备根据接收到的指令执行相应动作。 为实现其功能,感知层需包含以下关键组件: 传感器:用于感知物理量(温度、湿度等)并转换为电子信号。 执行器:根据电子信号执行物理动作(如开关电机)。 控制器:管理传感器和执行器,根据规则和算法进行控制。 通信接口:连接感知层与网络层,传输数据和指令。 网络层 网络层负责将感知层收集的数据传输至数据层。这一层涉及多种通信技术和协议,如Modbus、MQTT、蓝牙、Zigbee、LoRaWAN等,需在不同环境中稳定、可靠地传输数据,同时处理网络问题(网络拥塞、数据丢失、数据安全等)。 网络层的主要任务和组件包括: 通信协议:规定数据传输的规则和格式。 路由器和交换机:管理网络连接和数据流向。 网络安全设备:保护网络和数据安全。 数据层 数据层负责存储、处理和分析收集到的数据。通常包括数据库和数据处理服务器。数据处理步骤包括数据清洗、转换、聚合等,同时也包括数据分析和挖掘工具,以从数据中提取有价值信息。 数据层的核心组成包括: 数据库:存储和管理数据。 数据处理服务器:执行数据处理任务。 数据分析工具:从数据中提取信息,支持数据驱动决策。 应用层 应用层为物联网系统的用户界面,提供与系统交互的接口。它的任务是将数据层的结果以易懂、易用的方式呈现给用户,如图形界面、报表、警告和通知。 应用层的主要组成和任务包括: 用户界面:提供直观、易用的数据和服务展示。 服务:提供各种功能,如数据查询、设备控制等。 业务层 业务层作为物联网系统的最高层,负责整合各层功能,提供完整的业务解决方案。包括设备管理、用户管理、安全管理、业务流程管理等。 业务层的关键组成包括: 设备管理:监控和配置系统中的所有设备。 用户管理:管理用户账户和权限。 安全管理:保护系统安全。 业务流程管理:设计和优化业务流程。 物联网应用示例 智能家居:感知层的传感器和设备收集家庭环境信息,网络层通过通信技术传输数据,数据层处理和分析数据,应用层提供用户界面(如手机APP)进行远程控制,业务层负责整合功能。 智慧农业:感知层收集农田信息,网络层传输数据,数据层处理分析预测和判断,应用层提供用户界面(如电脑软件)查看信息,业务层整合农田、作物、设备管理。 智能交通:感知层收集交通信息,网络层传输数据,数据层分析预测交通状况,应用层提供导航系统,业务层整合交通管理、路线规划等。 总结 物联网的五层架构提供了一个全面的视角来理解和设计物联网系统。每一层都有其独特的功能和责任,共同构成了一个完整的系统。随着技术的发展,物联网在我们的生活中扮演的角色将愈发重要,带来更多便利和乐趣。希望本文对您深入理解物联网的架构有所帮助。 --- ### 387. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在现代技术驱动的世界中,GPS跟踪系统已成为企业和个人管理车辆和移动资产的关键工具。Traccar,一个免费和开源的现代GPS跟踪系统,凭借其多功能性和高适应性,在市场上脱颖而出。本文旨在深入探讨Traccar的功能、优势以及如何利用它构建一个智慧车队管理系统。 Traccar的核心功能 多平台兼容性: Traccar可安装在各种操作系统上,如Windows和Linux,确保了出色的性能和稳定性。 服务器既可本地部署,也可云端托管,提供灵活性和扩展性。 广泛的设备支持: 支持超过200种GPS协议和2000多种型号的设备,适用于各种预算和需求。 无论是低成本的杂牌设备还是高端品牌,Traccar都能满足不同用户的需求。 用户友好的界面: 提供现代化的Web界面,优化了桌面和移动设备的使用体验。 为Android和iOS提供原生移动应用,增强可访问性。 实时追踪与管理: 允许用户实时查看GPS设备的位置。 提供多种地图视图选项,包括路线图和卫星图像。 全面的警报系统: 实时通知功能,支持推送通知、电子邮件等多种通知方式。 能够监控恶劣驾驶行为、设备故障、地理围栏违规等多种情况。 详细的报告功能: 提供位置历史、行程、图表和摘要报告。 报告可通过网络或移动应用访问,也可导出为Excel文件。 Traccar在智慧车队管理中的应用 开发智慧车队管理系统时,可以将Traccar作为基础框架,结合智能硬件和软件技术,实现对车队的实时监控和管理。以下是一些建议: 硬件集成: 使用高精度的GPS接收器,如Garmin GPS 35。 安装GSM模块,如Siemens TC35,用于通信和数据传输。 添加其他传感器(温度、湿度等)以获取详细的环境数据。 软件和算法开发: 选择开源操作系统,如Linux。 开发实时监控、历史数据查询、车辆调度等功能模块。 利用算法优化路径规划、能耗管理等。 云端服务与数据分析: 通过Traccar搭建云服务器,处理和展示车辆数据。 使用大数据和AI技术进行数据分析和智能决策支持。 用户界面开发: 为PC、手机和平板等设备开发直观的用户界面。 提供微信公众号、移动应用等移动端访问方式。 安全与隐私保护: 使用SSL/TLS等加密技术保护数据传输。 遵守数据保护法规,确保用户隐私安全。 结论 Traccar作为一个开源的GPS跟踪系统,其丰富的功能和强大的适应性使其成为个人和企业管理车辆和资产的理想选择。无论是单个车辆的监控还是整个车队的管理,Traccar都能提供有效、可靠的解决方案。通过适当的定制和集成,Traccar可以成为智慧车队管理的强大后盾。 Github地址:Traccar --- ### 388. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 AIoT领域的多元创业方向 AIoT(人工智能物联网)领域为技术型团队或公司提供了广泛的创业机会。下面列出了一些创业方向,这些方向涵盖了硬件、软件、服务平台和嵌入式AI等多个方面,为创业者提供了各种可能性。 1. 硬件开发 在硬件开发领域,您可以专注于开发具有AI功能的物联网设备,这些设备可以涵盖多个领域,例如: 智能家居设备:开发智能灯具、智能家电、智能锁等,以提高家居的智能化水平。 智能安防系统:设计智能摄像头、入侵检测系统、智能门禁系统,以提高安全性。 智能工业机器人:研发工业机器人和自动化设备,帮助工业生产实现更高效率。 这些硬件设备可以集成深度学习、机器视觉、自然语言处理等AI能力,从而改善人们的生活和工作环境。 2. 软件开发 在软件开发领域,您可以专注于开发AIoT相关的软件和解决方案,包括: 智能化的物联网操作系统:为物联网设备开发操作系统,简化设备管理和数据处理。 数据处理和分析工具:开发工具,帮助企业分析和处理从物联网设备收集的数据。 特定行业的AI解决方案:为不同行业提供定制的AI解决方案,如智能健康、智能零售、智能交通等。 这些软件解决方案可以帮助企业提高生产效率、优化管理流程和提升服务质量。 3. 服务平台开发 开发AIoT服务平台是另一个有前景的方向,这些平台可以包括: 云计算平台:提供云计算基础设施,帮助企业存储和处理物联网数据。 数据共享平台:建立数据共享平台,促进不同设备和系统之间的数据交换。 设备管理平台:开发用于管理和监控物联网设备的平台,提高设备的效率和可靠性。 这些平台可以帮助企业更好地管理和运营其物联网设备和系统,提高效率和降低成本。 4. 嵌入式AI开发 嵌入式AI是将AI技术嵌入到物联网设备中的领域,为以下应用提供支持: 智能家电:通过嵌入式AI技术,智能家电可以学习用户的使用习惯,自主调整运行参数,提高能效。 工业自动化:在工业设备中嵌入AI,实现自动化生产流程管理和设备维护。 农业物联网:利用嵌入式AI监测土壤和气象数据,为农民提供精确的种植建议。 5. 工业物联网解决方案 结合工业物联网需求,提供智能化的工业解决方案,包括: 生产流程管理:开发智能化的生产流程管理系统,提高工厂生产效率。 设备自我维护:利用物联网技术实现设备的预测性维护,减少停机时间。 产品质量检测:开发智能检测系统,确保产品质量。 6. 智慧城市解决方案 提供智慧城市解决方案,包括: 智能交通:优化城市交通管理,减少拥堵。 智能安防:建立智能安防系统,提高城市安全性。 智慧能源:实现能源管理的智能化,提高能源利用效率。 7. 农业物联网解决方案 结合农业生产需求,提供智能化的农业解决方案,包括: 土壤和气象监测:利用物联网技术监测土壤环境和气象数据,为农民提供种植建议。 精确农业:实现精确的农业管理,提高农产品产量和质量。 以上仅是AIoT领域创业方向的一部分示例,实际上还有许多其他创新领域等待发掘。需要注意的是,尽管AIoT领域充满机会,但也伴随着挑战和风险,如技术难题、数据安全和市场接受度等问题。因此,在创业之前,务必进行充分的市场调研和技术准备,以确保项目的成功。 技术领域和市场情况 以下是一些与AIoT领域相关的技术领域以及它们的市场情况: 技术领域描述市场情况云计算通过互联网提供不同的服务和资源,包括数据存储、服务器等。主流物联网平台用于构建和管理物联网解决方案的软件工具。相当成熟边缘人工智能/分析AI算法直接在设备上或设备附近的服务器上本地处理。接近成熟容器用于打包代码及其所有依赖项的标准软件单元。接近成熟基于物联网的流分析处理和分析来自各种来源的实时数据。接近成熟监督式机器学习使用标记数据集来训练算法以对数据进行分类或预测。接近成熟云原生应用设计为云计算架构设计的程序。接近成熟云原生数据仓库在公共云中作为托管服务交付的数据库。接近成熟实时数据库处理状态不断变化的工作负载的数据库系统。接近成熟低代码/无代码开发平台通过图形用户界面创建应用软件的开发环境。接近成熟无监督机器学习算法不提供任何预先分配的训练数据标签或分数。接下来无服务器/FaaS允许开发人员构建、运行和管理应用程序,无需维护基础设施。接下来深度学习基于数据表示的更广泛的机器学习方法系列的一部分。接下来物联网市场客户可以在其中访问在线店面为其IoT设备查找、购买和管理应用程序。接下来数字孪生物理对象、流程或服务的数字表示。接下来物联网安全平台适用于物联网技 术堆栈多层的软件安全解决方案。 | 接下来 || 物联网边缘数据和应用平台 | 支持边缘分析应用程序管理。 | 接下来 || 机器学习操作 | 将机器学习应用于现实世界问题的任务自动化的过程。 | 接下来 || 自动化机器学习 | 将机器学习应用于现实世界问题的任务自动化的过程。 | 多年以后 || 数据生态系统 | 连接不同利益相关者共享数据的安全连接。 | 多年以后 || 2路BMI(脑机接口) | 在大脑和外部世界之间建立双向直接通信链路。 | 遥远 | 物联网硬件技术方向技术领域描述市场情况中央处理器执行计算机程序指令的电子电路。主流单片机集成处理器、存储器和外围设备的集成电路。主流GPU图形处理单元。主流安全芯片安全增强型低功耗模块,包括各种安全敏感功能。相当成熟边缘网关物理设备作为云与控制器、传感器和智能设备之间的连接点。相当成熟FPGA现场可编程门阵列。相当成熟智能传感器当传感器检测到适当的输入时,会采取一些预定义的操作。接近成熟专用集成电路专用集成电路。接近成熟小芯片Chiplet是一种新的设计理念,允许在单个封装或单个基板上使用多个芯片。接近成熟小机器学习TinyML是ML和嵌入式系统的一个研究领域,探索可以在小型低功耗设备上运行的模型。接近成熟边缘 + 微型数据中心适用于不需要传统设施的计算机工作负载的边缘数据中心。接近成熟云连接传感器云连接传感器使用物理传感器来积累数据并将其传输到云计算基础设施中。接下来增强现实技术将虚拟信息与现实世界相结合的技术。接下来边缘AI芯片专注于通常部署在边缘环境中的人工智能工作负载的计算芯片组。接下来神经突触芯片受大脑启发的计算机芯片,晶体管模拟神经元和突触。多年以后QRNG芯片量子驱动的安全芯片设计,可以集成到当前的硅设计和制造工艺中。多年以后无线、免电池传感器传感器可以自行产生其运行所需的能量,即不需要外部电源供电。多年以后机器学习优化的网关针对ML算法优化的控制器。遥远量子计算使用量子力学现象进行计算,例如叠加纠缠。遥远可生物降解传感器用于检测各种身体信号的可生物降解传感器,可帮助跟踪治疗后的预后。遥远 物联网连接技术方向技术领域描述市场情况蜂窝物联网 (2G/3G/4G)通过传统蜂窝网络提供与物联网应用程序的连接。主流低功耗广域网适用于IoT应用的低功耗、广域连接(例如Sigfox、LoRa、NB-IoT和LTE-M)。主流嵌入式SIM卡嵌入移动设备中的SIM卡可实现远程SIM配置,从而允许同时存储多个运营商配置文件并在它们之间远程切换。接近成熟网状网络一组充当单个Wi-Fi网络的设备,使房屋周围有多个Wi-Fi源,而不仅仅是一个路由器。接近成熟5G第五代移动通信技术,提供更快的数据速度和更低的延迟。接近成熟蓝牙低功耗低功耗蓝牙连接用于IoT设备,提供短距离通信。接近成熟超宽带一种高带宽、短距离通信技术,适用于室内定位和数据传输。接近成熟多模式连接支持多种连接协议和频段,提供更大的灵活性。接近成熟卫星物联网使用卫星链接传输数据,适用于偏远区域。接下来多模式设备支持多种连接技术的设备,以确保更好的覆盖和连接可靠性。接下来6G下一代移动通信技术,预计将提供更高的速度和低延迟。接下来无线电频谱共享更有效地利用可用频谱资源,支持多种无线通信设备。接下来量子通信利用量子力学原理进行的通信,具有极高的安全性。多年以后脑机接口通信允许大脑与外部设备直接通信的技术。多年以后生物通信使用生物体内或生物体间的通信方式。多年以后空间互联网在地球轨道上构建互联网,为全球提供高速互联网接入。遥远 请注意,上述市场情况和发展趋势仅供参考,实际情况可能会因地区、行业和技术发展速度而有所不同。在进入AIoT领域的任何创业方向前,建议深入研究市场需求和竞争环境,以制定成功的商业计划。同时,密切关注技术趋势,以保持竞争力。 --- ═══════════════════════════════════════════ ## 环境监测 ═══════════════════════════════════════════ ### 389. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 温湿度智能监控是物联网领域中的一个重要应用场景,它可以广泛应用于各种领域,包括家居、农业、医疗、工业等。下面是一个针对温湿度智能监控的物联网应用方案,旨在为普通读者解释清楚其工作原理和应用场景。 1. 应用背景 在许多领域中,监控环境的温度和湿度是至关重要的。例如,在农业中,农民需要监测温湿度以确保作物的健康生长;在医疗行业,药品和医疗设备需要在特定的温湿度条件下存储,以确保其有效性和安全性;在工业生产中,温湿度的变化可能影响生产效率和产品质量。 2. 解决方案概述 温湿度智能监控的物联网应用方案涉及传感器、物联网网关、云平台和用户界面等组件。传感器用于实时监测环境的温度和湿度,并将数据发送到物联网网关。物联网网关负责将传感器数据传输到云平台,云平台则负责存储、处理和分析数据,并向用户提供实时的监控和报警服务。用户可以通过手机应用或Web界面查看监控数据,并设置报警阈值以及接收报警通知。 3. 方案组成部分 传感器 温度传感器: 使用数字温度传感器,如DS18B20,可提供高精度的温度测量。 湿度传感器: 使用数字湿度传感器,如DHT22,可提供精确的湿度测量。 物联网网关 物联网网关是连接传感器和云平台的关键组件,它负责数据的传输和通信。 通信模块: 使用无线通信模块,如Wi-Fi、LoRa或NB-IoT,将传感器数据发送到云平台。 数据处理: 对传感器数据进行处理和封装,确保数据的可靠传输。 安全性: 采用加密技术确保数据在传输过程中的安全性。 云平台 云平台是数据存储、处理和分析的中心,它提供了实时监控、数据分析和报警服务。 数据存储: 使用数据库存储传感器数据,如MySQL、MongoDB等。 数据处理: 对传感器数据进行处理和分析,生成实时监控图表和报表。 报警服务: 设置报警阈值,当环境温湿度超出设定范围时,向用户发送报警通知。 用户界面 用户界面提供了监控数据的可视化和用户交互功能,用户可以通过手机应用或Web界面随时查看监控数据并进行操作。 实时监控: 显示实时的温湿度数据,以图表或数字形式呈现。 报警设置: 用户可以设置温湿度的报警阈值,并选择接收报警通知的方式,如短信、邮件或推送通知。 历史数据: 提供历史温湿度数据的查询和分析功能,用户可以查看过去一段时间内的数据趋势。 4. 应用场景 家居环境监控: 监测室内温湿度,提高生活舒适度,预防霉菌和细菌滋生。 农业温室监控: 实时监测温湿度,帮助农民调整温室环境,促进植物生长。 医疗设备监控: 监测医疗设备的存储条件,确保药品和器械的安全有效。 工业生产监控: 监测生产环境的温湿度,提高生产效率,确保产品质量。 5. 结论 温湿度智能监控的物联网应用方案可以在各种领域中发挥重要作用,帮助用户实时监测环境条件,提高生产效率和生活质量。通过传感器、物联网网关、云平台和用户界面的组合,用户可以实现对温湿度的远程监控和管理,从而更好地应对各种环境变化和挑战。 --- ### 390. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 GNSS(全球导航卫星系统)形变监测预警系统是一种利用卫星定位技术来监测地表形变并及时预警的系统。这种系统可以广泛应用于地质灾害监测、建筑结构变形监测、水文地质监测等领域。下面将介绍一个普适型的GNSS形变监测预警系统解决方案,以便非专业人士也能理解。 1. 系统概述 普适型GNSS形变监测预警系统是一种利用全球导航卫星系统进行实时监测和预警地表形变的系统。它通过接收卫星信号来获取目标区域的位置信息,并利用这些位置信息来监测地表形变的变化,一旦发现异常情况,系统将及时发出预警信号。 2. 技术原理 该系统主要基于以下技术原理: GNSS技术:利用卫星信号来获取目标区域的位置信息,包括经度、纬度和海拔高度等数据。 形变监测算法:通过对比不同时间点的位置信息,计算目标区域的形变量,如位移、速度和加速度等。 预警机制:设定合适的形变阈值,一旦监测到形变量超过阈值,则触发预警机制,通知相关人员进行应急处理。 3. 系统组成 普适型GNSS形变监测预警系统通常由以下几个组成部分构成: GNSS接收设备:用于接收卫星信号,并将位置信息传输给监测系统。 监测系统:包括数据处理模块和预警模块,用于处理接收到的位置信息、计算形变量并进行预警。 数据传输网络:将监测系统获取的数据传输到数据中心或相关用户终端。 用户终端:用于接收预警信息,并提供用户界面供用户查看监测数据和处理预警信息。 4. 应用场景 普适型GNSS形变监测预警系统可以广泛应用于以下领域: 地质灾害监测:如地震、滑坡、地面沉降等灾害的监测和预警。 建筑结构监测:对建筑物、桥梁等工程结构的形变进行实时监测,以确保其安全性。 水文地质监测:对地下水位、地表沉降等水文地质现象进行监测和预警,以保护地下水资源和土地利用安全。 5. 优势与挑战 优势:实时监测、高精度定位、普适性强、预警及时。 挑战:数据处理复杂、设备成本较高、对环境要求严格。 6. 结语 普适型GNSS形变监测预警系统是一种具有重要意义的监测预警工具,可以帮助我们及时发现地表形变异常情况,保护人们的生命财产安全。随着技术的不断发展和完善,相信这种系统将在各个领域发挥越来越重要的作用。 --- ### 391. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着现代生活中对空气质量关注度的增加,空气质量变送器在学校的应用成为了确保学生和教职员工健康与安全的重要措施之一。本文将探讨空气质量变送器在学校中的应用及其重要性。 一:空气质量变送器在学校中的应用及其重要性。 1. 空气质量监测 空气质量变送器是一种用于监测室内和室外空气质量的设备,它能够实时检测并传输关于空气中污染物浓度的数据。在学校中,这些污染物可能包括颗粒物(PM2.5和PM10)、挥发性有机化合物(VOCs)、二氧化碳(CO2)等。通过安装空气质量变送器,学校可以实时监测空气质量,并及时采取措施来改善空气质量,保障师生健康。良好的空气质量对学生的注意力和学习效率至关重要。空气质量变送器有助于确保学生在一个健康的环境中学习,减少因空气污染引起的呼吸道疾病和其他健康问题。对于有特殊需要的学生,如哮喘患者,空气质量监测尤为重要。 2. 健康风险预警 空气质量变送器不仅可以监测空气中的污染物浓度,还可以根据设定的健康标准和指南发出预警。一旦空气质量超过了安全范围,变送器就会发出警报,提醒学校管理人员采取相应的措施,如通风、净化空气等,以降低师生暴露在有害污染物中的风险。 3. 学习和工作环境改善 良好的空气质量是保障学生和教职员工健康的重要因素之一。研究表明,良好的室内空气质量可以提高学生的学习效率和教职员工的工作效率,减少疲劳和疾病的发生率。通过安装空气质量变送器,学校可以实时监测教室、图书馆、实验室等室内空间的空气质量,包括PM2.5、PM10、甲醛、二氧化碳等污染物的浓度。变送器可以检测到空气质量的变化,并及时发出警报,以便采取相应措施。4. 疫情防控 在当前新冠肺炎疫情的背景下,空气质量变送器的应用也对于学校的疫情防控工作至关重要。通过监测空气中的颗粒物和二氧化碳浓度,学校可以及时了解室内空气流通情况,并采取必要的措施来降低病毒传播的风险,保障师生的健康安全。 5. 节能和成本效益 空气质量变送器可以与学校的HVAC(供暖、通风和空调)系统联动,根据监测数据自动调节通风和空气净化设备的运行,从而提高能效和节约能源成本。通过优化通风系统,减少过度通风或不足,可以降低能源消耗。 6. 紧急情况响应 在发生火灾或其他紧急情况时,空气质量变送器可以迅速检测到有害气体的泄漏,及时通知学校管理人员和紧急服务部门,保障人员安全。 7. 科学研究和教育: 空气质量变送器可以作为科学课程的一部分,让学生参与到空气质量的监测和研究中,增强他们的环境意识和科学实践能力。教师可以利用监测数据进行环境教育,让学生了解空气污染的影响和减少污染的方法。8. 家长和社区的参与 通过公开空气质量监测数据,学校可以与家长和社区建立信任关系,展示其对学生健康的承诺。家长和社区居民可以参与到学校环境改善的活动中,共同促进一个更健康的学习环境。 二:数据上传方式 可通过RS485线将数据上传至RS-R-K本地监控软件,或连接环境监控主机RS-XZ)-100--GPRS/4G,通过GPRS/4G的通讯方式将数据上传至环境监控云平台。 三:环境监控云平台用户可通过电脑、手机apP及公众号等多种方式登录云平台,在前端界面查看环境监控主机上传的实时数据,也可分时间段查看历史数据,下载历史数据。云平台系统可以进行远程管理,用户只需登录云平台,添加管理人员信息,就可修改设置各因素的上下限值;一旦出现数值超限,系统会通过短信的形式通知添加在云平台上的管理人员。学校应当是一个干净、整洁、美丽、舒适的书香庭院,我们致力于打造这样的环境,也需要多功能空气质是变送器的应用。 综上所述,空气质量变送器在学校的应用对于保障学生和教职员工的健康和安全具有重要意义。学校管理部门应高度重视空气质量监测工作,积极采取措施改善室内空气质量,为师生营造一个健康舒适的学习和工作环境。 --- ### 392. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着人们对健康生活的追求日益增强,室内空气质量的监测成为了保障居住和工作环境健康的重要措施。室内空气污染物,如PM2.5、甲醛、一氧化碳等,可能对人体健康造成严重影响。因此,建立一个全面的室内空气质量监测系统显得尤为重要。 一、监测目标 实时监测室内空气中的污染物浓度,包括但不限于PM2.5、PM10、甲醛、一氧化碳、TVOC等。 通过数据分析,提供室内空气质量改善建议。 保障监测数据的准确性和实时性,确保居住者和工作人员的健康。 二、监测设备 多功能空气质量变送器:该变送器能够对室内空气中的多种参数进行实时监测,包括温度、湿度、颗粒物和有害气体浓度。设备采用高灵敏度传感器和电化学式及催化燃烧式检测技术,确保监测结果的准确性。 环境监测云平台:与变送器配套使用,实时收集和分析监测数据,支持远程查看、数据管理和报警通知功能。 三、监测实施 设备部署:在室内关键区域部署变送器,确保全面覆盖监测空间。 数据连接:通过专用的485通讯线路将变送器连接至云平台,确保数据传输的稳定性。 实时监控:利用环境监测云平台实时查看室内空气质量数据,及时发现异常情况。 报警设置:在云平台上设置各项污染物的阈值,一旦超过安全范围,系统自动通知相关人员。 数据分析:定期分析历史数据,评估室内空气质量变化趋势,提出改善建议。 四、应用场景 家庭住宅:为家庭提供健康的居住环境,特别是对于新装修的住宅,监测甲醛等有害气体的浓度。 办公空间:确保员工工作环境的空气质量,提高工作效率和员工健康水平。 公共场所:如医院、学校、商场等,保障公众健康,预防空气污染相关疾病。 五、结语 室内空气质量监测方案的实施,不仅能够保障人们的健康,还能够提高生活和工作环境的质量。通过多功能空气质量变送器和环境监测云平台的结合使用,我们能够实现对室内空气质量的全面监控和管理,为打造健康、舒适的室内环境提供强有力的技术支持。 --- ### 393. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在古代,人们常常将自然灾害视为“上天的惩罚”,而如今,随着科技的进步,我们逐渐认识到自然灾害的发生更多是由气候异常变化引起的。为了及时监测和预防自然灾害,气象站成为了不可或缺的工具。伴随着新中国的崛起,我国气象事业迎来了崭新的历史时期,自动气象站也逐渐普及,为人们的生活提供了重要支持。 气象站的普及和应用已经成为现代社会生活的重要一环。随着科技的不断进步,气象站不再只是专业气象人员的工具,而是可以被广泛应用于民用领域的设备。在日常生活中,正确的气象信息可以帮助我们更好地规划活动、保护财产、确保安全。 1. 家庭安全保障 在家庭中安装气象站,可以实时监测环境数据,帮助家人及时做出应对措施。比如: 预防自然灾害:气象站能够监测风速、降雨量等数据,及时发现可能引发洪涝、龙卷风等灾害的迹象,提前采取预防措施,保障家庭安全。 防范高温天气:气象站可以监测温度和湿度,提前预警高温天气,避免中暑等热带疾病的发生,保护家人健康。 2. 农业生产优化 农业生产对气候条件非常敏感,合理利用气象站可以提高农业生产效率和质量: 灌溉管理:通过监测土壤温度、水分等数据,科学合理地进行灌溉管理,避免因过度或不足灌溉导致的作物减产问题。 病虫害防控:气象站监测的气象数据可以帮助农民及时预警病虫害发生的可能性,采取合适的防治措施,减少农作物损失。 3. 旅游和户外活动安全 对于喜欢户外活动的人来说,气象站也是一项必备设备,可以帮助他们做出正确的决策,确保活动的安全性: 登山和徒步:气象站可以提供高山区域的气象数据,如气温、风力等,帮助登山者选择合适的出行时间和路线,避免遭遇恶劣天气造成意外。 海滨度假:在海滨地区安装气象站,可以实时监测海浪、风速等数据,提前预警可能出现的海啸、风暴等情况,保障度假者的安全。 4. 城市规划与管理 城市管理部门也可以利用气象站数据进行城市规划和环境管理: 交通管理:气象站监测道路湿度、能见度等数据,提供实时的交通情况,帮助交通管理部门合理调配交通资源,缓解交通拥堵问题。 环境保护:监测大气污染物浓度、空气质量等数据,为城市环境保护提供科学依据,制定相应的治理方案,改善城市环境质量。 优秀的气象站应当具备多种监测要素,从风速、风向到土壤温度、水分,再到大气压力、光照等,都能一应俱全。它能同时接入多种气象监测传感器,满足用户在不同场景下的使用需求。 提供全面监测数据 多样化的显示方式 用户对气象数据的获取渠道也越来越多样化,可以选择适合自己需求的显示方式。从高亮LED显示大屏到支持触摸修改参数的触模显示屏,以及定制化的页面功能,用户有着更多的选择权。 简单易用的设备配置 现代的气象站已经实现了非接触式配置,通过手机APP即可轻松完成设备的设置,包括LED屏幕标头、目标地址和端口等。这种简单易用的设计,使得即使非专业人员也能快速上手。 多样化的安装方式 气象站的安装方式也变得更加灵活多样。无论是立杆式还是三脚支架式,都能根据用户的需求进行选择,既满足固定安装的场景,又适用于经常需要移动的环境。 实现远程数据查看与管理 随着互联网的发展,气象站的数据传输也变得更加便捷。山东仁科气象站支持将监测数据传输至环境监控云平台,用户可以通过电脑端、手机APP、微信公众号等多种方式实现实时数据查看、报警提醒等功能,从而及时掌握气象变化,保障生活安全。 可靠的产品质量 在选择气象站时,产品质量是至关重要的。气象站以其可靠的品质保障赢得了客户的信赖,不仅具备丰富的功能,还能够在各种复杂环境下稳定运行,为用户提供可靠的气象数据支持。 综上所述,优秀的气象站应当具备多元化的监测要素、多样化的显示方式、简单易用的设备配置、灵活多样的安装方式、远程数据查看与管理功能,以及可靠的产品质量保障。这些特点的结合,使得气象站在现代社会生活中发挥着越来越重要的作用,为人们的生活提供了更多的便利和安全保障。 --- ### 394. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 地下车库气体监测系统方案旨在提升车库内空气质量管理,确保人员安全,同时达到节能减排的目标。本方案综合考虑了一氧化碳(CO)和二氧化碳(CO2)的监测需求,以及温湿度的调控,依据国家及地方政府的相关规范与标准,特别是《民用建筑绿色设计规范》、《公共建筑节能设计标准》和《绿色建筑评价标准》等,制定以下详细方案。 系统目标安全目标:通过定期排风保证车库内一氧化碳和二氧化碳浓度低于危害水平,避免对人体健康造成损害。节能目标:根据实时监测的一氧化碳和二氧化碳浓度、温湿度调整排风频率,减少能源浪费。 设计依据本方案参考了以下几个关键的国家及地方标准:《民用建筑绿色设计规范》JGJ/T 229-2010:建议汽车库设置机械通风,并配备一氧化碳检测和控制装置。《公共建筑节能设计标准》GB 50189-2015:建议地下停车库的通风系统根据使用情况定时启停,或根据CO浓度进行自动运行控制。《绿色建筑评价标准》GB/T 50378-2019:要求地下车库应设置与排风设备联动的一氧化碳浓度监测装置。 系统组成 3.1 二总线气体监测方案本方案采用二总线技术进行CO在线监测,方案组成如下:CO数据采集设备:采集车库内的CO浓度数据。MBUS二总线监控主机:作为监测系统的中心,负责数据处理和控制指令的发出。环境监控平台:用于数据显示、分析和存储。风机控制系统:根据CO浓度数据自动调节风机的启动和停止,实现联动排风。3.2 设备选型气体变送器:采用高品质的电化学传感器,支持多种气体检测,具有声光报警功能。二总线主机:具备大屏中文液晶显示,支持短信报警和数据存储功能,能同时连接多个二总线设备3.3 系统软件综合环境监控云平台:提供实时监控、数据分析、报警管理等功能,支持多级权限访问和子账号管理。 操作流程实时监测:系统不断采集地下车库内的CO浓度以及温湿度数据。数据分析:二总线监控主机分析数据,当CO浓度超过设定阈值时,自动启动风机进行排风。报警通知:若CO浓度超过安全阈值,系统通过环境监控平台发送短信、邮件或其他形式的报警通知给管理人员。监控平台会存储历史数据,方便管理人员查询和分析,以优化系统性能和响应策略。 关键技术特点二总线技术:简化了布线过程,支持更远的通信距离,易于扩展和维护。高精度传感器:确保数据的准确性,及时发现潜在的安全隐患。智能控制系统:根据实时数据自动调整通风系统,有效节能且保持空气质量。多平台兼容性:监控平台支持电脑和移动设备,方便随时随地监控和管理。 实施步骤需求分析:根据地下车库的具体情况,包括车库大小、车辆流量、现有通风设施等,确定系统设计需求。系统设计:根据需求分析结果,设计气体监测和通风控制系统,包括设备选型、系统布局和通信协议等。安装调试:在地下车库安装传感器、控制器等设备,并进行系统调试,确保系统稳定运行。系统培训:为管理和维护人员提供必要的系统操作和维护培训。运行监控:系统投入运行后,持续监控车库内的气体浓度,确保运行效率和人员安全。 维护与升级定期检查:定期对监测设备和通风设施进行检查和维护,确保系统正常运行。数据分析:利用收集的数据进行深入分析,优化系统设置,提升系统性能。技术升级:根据技术发展和用户反馈,定期对系统进行升级,增加新功能或提升系统效率。 结语本方案为地下车库提供了一个综合的气体监测和通风控制解决方案,不仅能有效保障车库使用人员的健康和安全,还能通过智能控制达到节能减排的目的。通过实施此方案,可以大大提升地下车库的环境质量,为用户创造一个更加安全、舒适的停车环境。 --- ### 395. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 噪声扬尘在线监测整体方案 一、方案概述 本方案旨在为建筑拆迁、道路施工等场景提供一套完整的噪声扬尘在线监测解决方案,实现对施工现场噪声和扬尘污染的实时监测、联动控制、远程监控、数据管理、报警预警等功能,帮助施工企业有效控制污染,降低环境影响。 二、方案架构 噪声扬尘在线监测整体方案架构图: 三、方案组成 监测终端选择: 选择适用于建筑拆迁、道路施工等场景的扬尘在线监测仪器,能够连续监测颗粒物PM2.5、PM10浓度。 确保监测仪器具有高精度、稳定性强、抗干扰能力强的特点,以确保监测数据的准确性和可靠性。 设备布置与联动: 在施工现场布置多个扬尘在线监测仪器,覆盖整个施工区域,实时监测扬尘污染情况。 与喷水设施、除尘设备等进行联动,实现扬尘污染的控制和治理。例如,当监测到扬尘浓度超标时,自动启动喷水设备进行降尘处理。 远程监控与数据管理: 通过远程监控平台,实现对扬尘监测仪器的远程查看、数据存储、分析对比等功能。 监测数据实时上传至云端数据库,并进行存储、管理和分析,为决策提供数据支持。 报警与预警机制: 设定扬尘浓度的报警与预警机制,当监测数据超过预设阈值时,系统自动发出报警信息,提醒相关人员采取措施。 用户权限管理: 设定不同用户角色,实现账号管理与权限控制,确保只有授权人员可以访问监测数据和进行操作。 四、方案优势 实时监测: 可实现对扬尘浓度的实时监测,及时发现和处理扬尘污染问题。 自动化控制: 与喷水设施等设备进行联动,实现扬尘治理的自动化控制,提高治理效率。 远程管理: 通过远程监控平台,可以随时随地查看监测数据,进行数据分析和决策。 数据存储与分析: 监测数据实时上传至云端数据库,便于数据的存储、管理和分析,为环境治理决策提供科学依据。 五、适用场景 建筑拆迁 道路施工 土石方开采 工矿企业 交通物流 其他产生噪声和扬尘污染的场所 六、总结 噪声扬尘在线监测系统是实现施工现场环境污染精细化管理的重要手段,可有效降低施工对环境的影响,提升施工企业的社会责任形象。 --- ### 396. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 在我们的日常生活中,空气质量是一个备受关注的话题。尤其是在工地、工厂等环境中,扬尘是一种常见的污染源,对人们的健康和环境造成了不可忽视的影响。为了应对这一问题,现代科技为我们提供了一种全新的解决方案:扬尘监测告警系统。 什么是扬尘监测告警系统? 扬尘监测告警系统是一种利用先进的传感器技术和智能联动功能,实时监测周围环境中的扬尘颗粒,一旦发现超标情况,系统会立即发出警报并采取相应的措施,以保障人们的健康和环境的清洁。 如何工作? 实时监测: 系统通过多种监测要素,如PM2.5、PM10等,实时监测周围环境中的扬尘颗粒浓度,确保数据的准确性和及时性。 智能联动: 当监测数据超过设定的安全阈值时,系统会自动发出预警信号,并联动降尘设备进行处理,以减少扬尘对环境的影响。 多种显示方式: 用户可以通过LED显示屏、手机APP等多种方式查看监测数据,方便快捷。 4 同时,可选配RS485上行接口,搭配视频字符叠加器将监测数据叠加至监控画面中,为视频监控提供数据支撑。 为什么选择扬尘监测告警系统? 保障健康: 扬尘是一种常见的空气污染源,长期暴露于扬尘环境中会对人们的健康造成危害。使用扬尘监测告警系统可以及时发现并处理扬尘污染,保障人们的健康安全。 环境保护: 扬尘不仅对人体健康有害,还会对环境造成破坏,影响生态平衡。通过监测和处理扬尘污染,可以有效保护环境,维护生态平衡。 智能高效: 扬尘监测告警系统采用智能联动技术,能够自动响应监测数据,及时采取措施,提高工作效率,减少人为干预。 结语 扬尘监测告警系统是一种现代化、智能化的环境保护工具,它为我们提供了保障健康、保护环境的新途径。希望通过全社会的共同努力,可以建立起更加清洁、健康的生活环境,让我们的蓝天更加明净、更加美丽! --- ### 397. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在当今社会,环境污染已经成为人们日常生活和工作中不可忽视的问题之一。特别是噪声和扬尘污染,不仅影响着人们的健康和生活质量,也对城市环境产生了负面影响。有鉴于此,研发出一套智能化的噪声扬尘监测系统,以解决这一严峻的环境问题。 全面监测环境 该系统采用先进的传感器技术和物联网技术,可以实时监测城市各个关键区域的噪声和扬尘浓度,包括工地、道路交通、工厂园区等地方,实现对环境污染的全面监测。 数据分析与预警 监测系统不仅可以获取环境数据,还能通过数据分析算法对监测数据进行处理和分析,提供精准的预警和分析报告。这些报告为相关部门提供了科学依据,以制定有效的环境治理和管理措施。 远程监控与管理 监测系统支持远程监控和管理功能,相关人员可以通过网络平台随时随地查看监测数据,及时采取应对措施,保障环境质量和人民健康。 多样化应用场景 该系统不仅适用于城市建设和工业生产领域,还可以应用于交通运输、建筑施工等多个领域。通过在不同领域的应用,该系统为各行各业提供了全面的环境监测和管理服务。 应用案例 这套噪声扬尘监测系统已经在多个领域得到了广泛应用,取得了显著的效果。比如,在城市建设工地,该系统帮助管理者及时监测和控制施工噪声和扬尘,保障周边居民的生活质量。 在工业生产企业,该系统帮助企业合理安排生产过程,降低环境污染,提升企业形象和竞争力。在交通运输领域,该系统帮助交通部门监测道路交通噪声和车辆尾气排放,优化交通组织和规划。 结语 噪声扬尘监测系统为环境保护和城市管理提供了一种全新的解决方案,将科技与环保相结合,为人们创造了更清洁、更健康的生活和工作环境。相信随着技术的不断进步和应用的不断推广,这一智能监测系统将为社会和人类的可持续发展做出更大的贡献。 --- ### 398. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 什么是机房机柜温湿度监测? 机房机柜温湿度监测是通过安装在机柜内的传感器和监控设备,实时监测机房内部的温度和湿度变化。这样的监测对于保持机房内部设备的正常运行非常重要,因为过高或过低的温度湿度可能会导致设备故障或损坏。 项目概述 系统背景 随着信息网络技术的不断发展,各类规模大小不等的网络设备机房广泛分布于用户各分支机构所在地域。然而,由于缺乏与网络规模相匹配的运维系统,无人值守机房的物理运行环境状况、动力配电状况、设备运行状况、人员活动状况以及消防状况的变化难以及时发现和处理。因此,实现一套完善的机房机柜温湿度监测系统至关重要。 系统概述 机房温湿度监测系统包括两个主要部分:机房温湿度变送器和环境监控主机。温湿度变送器具有液晶显示,可实时监测温湿度,并采用标准ModBuS-RTU通信协议,RS485信号输出,通信距离最大可达。该变送器可内置于机柜内,或通过磁铁吸附于机柜表面,安装方便,适用于通讯机房、仓库楼宇等场所。 环境监控主机为多功能监控设备,支持多种上传数据方式,具备液晶显示屏和可外接LED屏等特点。其功能包括数据存储、浸水检测、ModBus-RTU主站接口等,可接入各类485变送器。 据,支持视频查看、告警功能 系统组成 环境监控主机 环境监控主机是整个监测系统的核心。其功能包括: 支持各种传感器接入,包括温湿度传感器、漏水检测传感器等。 提供数据存储功能,可存储大量的监测数据,支持查询和导出。 提供用户友好的界面,实现实时监测和远程控制。 技术参数 机柜式温湿度变送器 机柜式温湿度变送器是安装在机柜内部的传感器设备,主要用于监测机柜内部的温度和湿度变化。其特点包括: 采用进口传感器,具有较高的精度和响应速度。 支持标准的ModBus-RTU通信协议,可与环境监控主机进行数据交换。 设备背面具有四个强力磁铁,方便安装在机柜上。 技术参数 功能特点 实时监测 系统能够实时监测机房内部的温度和湿度变化,并通过液晶显示或软件界面实时展示数据。 报警功能 系统能够设置温湿度的上下限,并在超出预设范围时发出警报,提醒运维人员及时处理。 远程监控 用户可以通过PC端、APP客户端等方式远程监控机房的温湿度情况,随时随地掌握机房的运行状态。 数据导出 系统支持将监测数据导出为Excel等格式,方便用户进行进一步的数据分析和处理。 使用场景 该机房机柜温湿度监测方案适用于各种场景,包括但不限于: 企业数据中心:保障服务器和网络设备的正常运行。 通信基站机房:确保通信设备的稳定性和可靠性。 仓储物流中心:保护存储的物品不受湿度和温度影响。 商业办公楼等:维护办公环境的舒适度和设备的正常 结语 机房机柜温湿度监测方案通过硬件设备和软件平台的结合,实现了对机房环境的实时监测和远程管理,为用户提供了便捷的监控解决方案。 --- ### 399. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案概述 森林防火气象站旨在通过先进的监测技术和智能预警系统,及时感知并应对森林火灾的威胁,保护森林资源和生态环境。本方案将结合自然气候和人为因素,提供全面的防火措施,确保森林防火工作的高效运行。 解决方案特点 全天候监测:地球绿色屏障【守门员】-森林防火气象站通过24/7的监测系统,实时感知森林环境的温度、湿度、风速、降水量等关键指标,及时预警火情。 多功能传感器:配备多种传感器,包括风力、风速、风向、空气温湿度、大气压力、光照度、雨雪、雨量等,全面监测气象要素,为火情预测提供数据支持。 双供电系统:支持220V市电和太阳能供电,确保设备的稳定运行和持续监测,即使在市电断电情况下也能正常工作。 远程监控与控制:通过4G多功能通信接口和RJ45网口,实现数据实时上传至环境监控云平台,并支持远程控制功能,管理员可随时随地监控和管理。 智能预警系统:环境监控云平台配备LED大屏,自动轮播监测数据,并提供火险等级评定和防护计划,实现智能预警和应急响应。 方案优势 全面性:涵盖自然气候和人为因素,全方位保护森林安全。 高效性:实时监测、智能预警,提高了对火情的感知和响应速度。 稳定性:双供电系统保证了设备的稳定运行,适应不同环境条件下的使用。 智能化:通过远程监控和控制,实现了对设备的智能化管理,提高了工作效率和便利性。 可扩展性:支持多种传感器和外部设备接口,方便根据需要进行扩展和升级。 总结 地球绿色屏障【守门员】-森林防火气象站是一套集成化的解决方案,旨在为森林防火工作提供全方位的支持和保障。通过多种先进技术的应用,将极大地提高森林防火的效率和可靠性,保护森林资源,维护生态平衡。 --- ### 400. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 项目概述 1.1 项目背景 森林火灾频发,对生态环境和人类生命财产造成巨大危害。 中国每年平均发生森林火灾约1万多次,烧毁面积巨大。 森林防火工作始终实行“预防为主、积极消灭”的方针。 1.2 设备原则 标准化、先进性、适用性、实用性、稳定性、可维护性。 建设信息化基础,构建智能化监测预警体系。 1.3 设计依据 《森林火险气象等级》标准。 相关地方政府发布的森林防灭火工作通知。 1.4 森林防火气象站拓扑图 包括通信服务器、LED大屏显示等设备。 2. 方案概述 2.1 方案简介 森林防火气象站包括立杆、电控镇、气象仪器、人体探测器、语音报警模块等部分,可实现对森林环境的实时监测与报警。 2.2 数据上传方式 通过4G传输实时数据,包括各种气象要素和全景视频图。 2.3 设备参数 支持多种供电方式,采用太阳能供电,具备数据采集通信接口和继电器输出等功能。 3. 设备优势 3.1 外观色彩 设计醒目的橙色,易于在森林中被发现 3.2 监测要素 监测风速、风向、雨量、温度、湿度等气象要素,提供科学依据。 3.3 视频监控 搭配监控摄像头,实现远程监控,及时发现火源。 3.4 语音提醒 通过语音报警模块进行警示,防止野外用火等行为。 3.5 安装方式 支持多种安装方式,适应不同地形环境。 3.6 供电方式 支持市电供电、太阳能供电和蓄电池供电等多种方式,保证设备持续运行。 4. 综合环境监控云平台 4.1 概述 提供实时数据监控、地图显示、告警功能、历史数据查询、继电器控制等功能的云平台。 4.2 功能介绍 支持实时监控、地图显示、超限告警、视频监控、历史数据查询等功能。 4.3 手机APP 提供手机APP,方便用户随时随地监测设备状态和数据。 5. 总结 综合以上方案,可以实现对森林防火气象的全面监测和预警,为防火决策提供科学依据,降低森林火灾的发生率和损失。 --- ### 401. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、系统概述 景区生态环境监测系统是指利用物联网、云计算、大数据等技术,对景区的空气质量、气象条件、水质等环境要素进行实时监测、分析和管理的系统。该系统可以为景区管理者提供科学的环境数据,帮助其更好地进行环境管理和决策,提升景区的环境质量和游客满意度。 二、系统组成 景区生态环境监测系统主要由以下几部分组成: 监测终端:负责采集景区的环境数据,包括气象站、水质监测仪、空气质量监测仪等。 数据传输网络:负责将监测终端采集的数据传输到数据中心,包括GPRS、4G、LoRaWAN等无线网络技术。 数据中心:负责存储、分析和处理环境数据,并为用户提供数据查询和分析服务。 应用平台:为景区管理者和游客提供环境信息查询、预警发布、数据分析等服务。 三、系统功能 景区生态环境监测系统主要功能包括: 实时监测:对景区的空气质量、气象条件、水质等环境要素进行实时监测,并及时将监测数据上传到数据中心。 数据分析:对监测数据进行统计分析,生成各种报表和图表,帮助景区管理者了解景区的环境状况和变化趋势。 预警发布:当环境数据超过预警阈值时,系统会自动发布预警信息,提醒景区管理者采取措施。 信息查询:景区管理者和游客可以通过应用平台查询景区的实时环境数据和历史数据。 四、系统方案 1. 监测终端 根据景区的实际需求,可以选择不同的监测终端。例如,对于空气质量监测,可以选择PM2.5、PM10、O3、NO2等参数的监测仪;对于气象监测,可以选择温度、湿度、风速、风向、降水等参数的监测仪;对于水质监测,可以选择pH值、COD、氨氮、溶解氧等参数的监测仪。 2. 数据传输网络 3. 数据中心 数据中心可以选择本地部署或云服务模式。本地部署模式需要景区自行建设机房和服务器,成本较高,但数据安全性更高;云服务模式可以节省景区建设和维护机房的成本,但数据安全性相对较低。 4. 应用平台 应用平台可以选择自主开发或购买第三方平台。自主开发可以满足景区的个性化需求,但成本较高;购买第三方平台可以节省开发成本,但功能可能无法完全满足景区的需求。 五、应用案例 景区生态环境监测系统已在多个景区得到应用,例如: 杭州西湖景区:杭州西湖景区部署了空气质量监测系统,可以实时监测景区的空气质量状况,并及时发布预警信息。 张家界景区:张家界景区部署了气象监测系统,可以为景区的旅游管理和游客安全提供气象信息服务。 九寨沟景区:九寨沟景区部署了水质监测系统,可以实时监测景区的湖泊水质状况,并为景区的水环境保护提供数据支撑。 六、总结 景区生态环境监测系统可以帮助景区管理者更好地了解景区的环境状况,并采取措施改善环境质量,提升景区的吸引力和游客满意度。 --- ### 402. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 问题背景与挑战 在全国范围内,餐饮业油烟污染的环境监测仍然停留在手工监测阶段,导致时间覆盖率低、监测范围有限,难以实现实时监测、超标报警和无人值守。监管不到位导致油烟净化装置无法有效运行,严重影响环保部门的工作效率和反映能力。 油烟监测系统是在线监控系统软件平台,采用B/S模块开发,Window界面风格,操作简单方便;能实时显示餐饮企业的净化装置运行状态和清洁程度、风机运行状态,并以各种图形展示业务数据,形象直观:可部署于用户自有的服务器或政府服务器,功能强大;符合用户自身的特点,满足用户对信息安全的要求, 环境临控云平台:若将建大仁科精简式油烟在线检测仪送数据至云平台,设备需插上流量卡或者手机卡,将目标地址设置为0531vwn.n,目标端口设置为8020,设置完成后,设备自动上传数据至云平台。 2. 解决方案概述 为了实现对餐饮业油烟污染的长效管理,我们提出了精简式油烟在线监测系统的整体解决方案,旨在提供实时监测、报警、远程管理的功能,有效监管餐饮业的油烟排放情况。 3. 系统组成与功能 监测设备:采用精简式油烟在线检测仪,可采集油烟浓度、颗粒物浓度、非甲烷总烃等数据,并通过GPRS/4G传输到监控平台。 传输网络:采用GPRS/4G通讯方式,确保数据的及时传输和实时监测。 监控中心:油烟监测系统和云平台提供监测软件平台,实时显示餐饮企业的净化装置运行状态、清洁程度、风机运行状态等,并以图形展示业务数据,方便监管人员查看和分析。 4. 技术参数与特点 采样气体温度:-40~80℃ 上传数据间隔:30秒上传一次数据 油烟采集范围:0~20mg/m³,精度±7%FS 非甲烷总烃采集范围:0~20mg/m³,精度±10%FS 颗粒物值采集范围:0~20mg/m³,精度±10%FS 安装方式:简便易行,适用于不同风管。 5. 系统优势与价值 实时监测与报警:能够实时监测油烟排放情况,并设定上限值进行超限报警,保障环境监测的及时性和准确性。 远程管理:通过云平台,监管人员可随时随地查看监测数据和设备运行状态,实现无人值守管理。 环保效益:提高环保部门的工作效率和反映能力,降低对环境监管部门的人力压力,促进餐饮行业的油烟排放治理。 6. 实施步骤 选型与采购:根据需求选购精简式油烟在线检测仪及相关设备。 安装调试:按照安装手册,进行设备安装和调试工作。 网络配置:设置GPRS/4G通讯网络,确保数据传输畅通。 平台部署:部署油烟监测系统和云平台,建立监测平台。 数据监测:实时监测油烟排放数据,并进行分析和报警处理。 7. 总结与展望 精简式油烟在线监测系统是一种高效、便捷的油烟监测方案,能够提升环保部门的工作效率,加强对餐饮业油烟排放的管理和治理。未来,我们将持续优化系统功能,提升监测精度和反馈速度,为环保事业做出更大的贡献。 以上是对精简式油烟在线监测系统的整体解决方案,如需更多详细信息,请随时与我们联系。 --- ### 403. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着城市发展和人们生活水平的提高,智慧公厕已经成为城市基础设施建设的重要组成部分。传统的公厕管理存在着很多问题,例如无法及时了解厕所内部情况、人员流量管理不到位、环境卫生难以保障等。为了解决这些问题,推出了智慧公厕环境监测解决方案,旨在利用先进的科技手段提升公厕管理效率,改善厕所环境质量,提升城市形象。当公厕内的有害气体含量超标时,系统能够自动联动风机进行通风除臭,确保厕内环境卫生,改善公厕内的环境质量。 此外有些智慧厕所还有生命监测功能,当发现有人身体不适、超时驻留,系统会发出告警信息,及时关注如厕者安全情况。 一、概述 智慧公厕环境监测解决方案是指利用物联网、云计算、大数据等技术,对公厕内的环境参数进行实时监测、分析和管理,以提升公厕环境质量,改善如厕体验,打造智慧城市的重要组成部分。 二、方案组成 智慧公厕环境监测解决方案主要由以下四部分组成: 监测终端: 负责采集公厕内的环境参数,包括温湿度、硫化氢、氨气、PM2.5、臭氧等。 传输部分:负责将监测终端采集到的数据传输至管理平台。 管理平台:负责对数据进行存储、分析和展示,并提供管理功能。 智能联动:根据监测数据,联动风机、排气扇、照明等设备,实现公厕环境的智能化管理。 三、工作原理 监测终端采集公厕内的环境参数,并将数据传输至传输部分。 传输部分将数据传输至管理平台。 管理平台对数据进行存储、分析和展示,并提供管理功能。 根据监测数据,联动风机、排气扇、照明等设备,实现公厕环境的智能化管理。 四、方案优势 实时监测:可实时监测公厕内的环境参数,及时发现环境问题。 智能分析:可对监测数据进行智能分析,为公厕管理提供决策依据。 精细管理:可实现公厕环境的精细化管理,提升公厕环境质量。 人性化服务:可为如厕者提供更加人性化的服务,提升如厕体验。 监测终端主要有多功能空气质量变送器和吸顶式红外探测器。 公厕内的硫化氢和氩气是造成公厕异味的原因,当这2种气体的浓度达到一定的数值,就会对人体造成伤害,多功能空气质量变送器可以同时监测这两种气体的浓度,避免浓度升高对人体造成伤書。 吸顶式红外探测器能够对厕位使用情况进行动态监测,通过显示屏可直接反映厕位的占用情况,减少人员的等待时间,也方便管理人员合理配置资源。 五、应用场景 智慧公厕环境监测解决方案可广泛应用于城市公厕、景区公厕、高速公路公厕、公园公厕、学校公厕等场所。 六、典型案例 某市智慧公厕项目:该项目采用智慧公厕环境监测解决方案,对全市范围内1000余座公厕进行环境监测,有效提升了公厕环境质量,改善了如厕体验。 某景区智慧公厕项目:该项目采用智慧公厕环境监测解决方案,对景区内50余座公厕进行环境监测,有效缓解了景区公厕高峰期排队压力,提升了景区游客的满意度。 七、发展趋势 随着智慧城市建设的不断发展,智慧公厕环境监测解决方案将得到更加广泛的应用,并将朝着以下方向发展: 技术更加智能化:将采用人工智能、大数据等技术,进一步提升监测、分析和管理的智能化水平。 功能更加丰富:将提供更多人性化功能,如厕位导航、厕纸余量提醒、如厕安全监测等。 应用更加广泛:将应用于更多场景,如家庭卫生间、养老院卫生间、医院卫生间等。 八、结论 智慧公厕环境监测解决方案是智慧城市建设的重要组成部分,对于提升公厕环境质量、改善如厕体验、提升城市形象具有重要意义。 --- ═══════════════════════════════════════════ ## 石油石化 ═══════════════════════════════════════════ ### 404. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 近年来,燃气泄漏引发的爆炸事故频频发生,给人们的生命财产安全带来了巨大威胁,这也凸显了传统的燃气安全管理方式存在的漏洞和不足。面对这一挑战,借助物联网技术的普及和应用,可以构建起更为智能、高效的燃气安全监测体系,从而有效地预防和避免燃气爆炸事故的发生。 一、智能感知:气体传感器的应用 物联网技术的核心之一就是感知与监测。通过在室内空间布置气体传感器,实时监测空气中的燃气浓度变化。这些传感器采用进口电化学传感器,具有反应迅速、抗干扰能力强的特点,能够准确、及时地检测到燃气泄漏的迹象。一旦监测到燃气浓度超过安全范围,传感器将发出声光报警信号,提醒用户采取相应的安全措施,如关闭燃气阀门等,从而避免事故的发生。 二、智能分析:环境监控云平台的应用 传感器采集到的数据通过物联网技术传输至云端平台进行存储和分析。环境监控云平台能够实时监测室内气体浓度,支持对监测点位置、设备类型等信息的实时查询。同时,平台还具备数据分析的功能,能够对历史数据进行曲线分析,识别出燃气泄漏的趋势,为预防事故提供科学依据。 三、智能预警:多样化报警方式的应用 环境监控云平台支持多种报警方式,包括界面报警、声光报警、短信报警、电话报警等,用户可根据自身需求选择合适的报警方式。一旦监测到燃气泄漏,系统将及时向相关管理人员发送报警信息,提醒其采取紧急措施,防止事故的扩大和发生。 四、智能管理:数据分析与设备维护 通过物联网技术,管理者可以随时随地通过手机APP或网页端登录环境监控云平台,实时监测气体浓度情况,查询历史数据,定位报警位置等。同时,平台还支持设备故障/异常报警功能,管理者可通过平台及时发现设备问题并进行维修维护,保障监测系统的正常运行。 五、智能预防:全面布局与系统优化 除了室内空间的监测外,物联网技术还可以应用于城市天然气管道的监测和管理。通过在管道周围布置智能传感器,实时监测管道的运行状态和周围环境情况,及时发现管道损坏、泄漏等问题,并通过云平台进行分析和预警,提前预防事故的发生。同时,加强管道建设与维护,提高管道的安全性和稳定性,也是预防燃气爆炸事故的重要措施。 综上所述,借助物联网技术,可以构建起智能化的燃气安全监测体系,实现对燃气泄漏的及时感知、快速预警和有效管理,从而最大程度地降低燃气爆炸事故的发生率,保障人们的生命财产安全。随着技术的不断进步和应用的不断普及,相信物联网技术将在燃气安全领域发挥越来越重要的作用,为社会的发展和人们的生活带来更多的便利与安全。 利用物联网技术保障燃气安全:构建智能监测体系 近年来,燃气泄漏引发的爆炸事故频频发生,给人们的生命财产安全带来了巨大威胁,这也凸显了传统的燃气安全管理方式存在的漏洞和不足。面对这一挑战,借助物联网技术的普及和应用,可以构建起更为智能、高效的燃气安全监测体系,从而有效地预防和避免燃气爆炸事故的发生。 一、智能感知:气体传感器的应用 物联网技术的核心之一就是感知与监测。通过在室内空间布置气体传感器,实时监测空气中的燃气浓度变化。这些传感器采用进口电化学传感器,具有反应迅速、抗干扰能力强的特点,能够准确、及时地检测到燃气泄漏的迹象。一旦监测到燃气浓度超过安全范围,传感器将发出声光报警信号,提醒用户采取相应的安全措施,如关闭燃气阀门等,从而避免事故的发生。 二、智能分析:环境监控云平台的应用 传感器采集到的数据通过物联网技术传输至云端平台进行存储和分析。环境监控云平台能够实时监测室内气体浓度,支持对监测点位置、设备类型等信息的实时查询。同时,平台还具备数据分析的功能,能够对历史数据进行曲线分析,识别出燃气泄漏的趋势,为预防事故提供科学依据。 三、智能预警:多样化报警方式的应用 环境监控云平台支持多种报警方式,包括界面报警、声光报警、短信报警、电话报警等,用户可根据自身需求选择合适的报警方式。一旦监测到燃气泄漏,系统将及时向相关管理人员发送报警信息,提醒其采取紧急措施,防止事故的扩大和发生。 四、智能管理:数据分析与设备维护 通过物联网技术,管理者可以随时随地通过手机APP或网页端登录环境监控云平台,实时监测气体浓度情况,查询历史数据,定位报警位置等。同时,平台还支持设备故障/异常报警功能,管理者可通过平台及时发现设备问题并进行维修维护,保障监测系统的正常运行。 五、智能预防:全面布局与系统优化 除了室内空间的监测外,物联网技术还可以应用于城市天然气管道的监测和管理。通过在管道周围布置智能传感器,实时监测管道的运行状态和周围环境情况,及时发现管道损坏、泄漏等问题,并通过云平台进行分析和预警,提前预防事故的发生。同时,加强管道建设与维护,提高管道的安全性和稳定性,也是预防燃气爆炸事故的重要措施。 综上所述,借助物联网技术,可以构建起智能化的燃气安全监测体系,实现对燃气泄漏的及时感知、快速预警和有效管理,从而最大程度地降低燃气爆炸事故的发生率,保障人们的生命财产安全。随着技术的不断进步和应用的不断普及,相信物联网技术将在燃气安全领域发挥越来越重要的作用,为社会的发展和人们的生活带来更多的便利与安全。 --- ═══════════════════════════════════════════ ## 积水监测 ═══════════════════════════════════════════ ### 405. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 城市内涝,指的是在城市区域内,由于极端天气事件或不合理的城市排水系统,降雨过多而导致的积水现象。这种情况不仅对城市的基础设施和交通造成影响,还可能威胁人们的生活和财产安全。因此,城市内涝积水监测解决方案成为了日益重要的需求。 问题背景 城市内涝问题在全球范围内愈加普遍,主要因素包括气候变化、城市扩张、不合理的城市规划和排水系统不足。大雨来临时,城市街道、地下车库、低洼地带和居民区域容易发生内涝,给城市的正常运营和居民的生活带来极大困扰。 城市内涝积水监测站 城市内涝积水监测站为“智慧城市建设”添砖加瓦,为城市防汛提供坚实的技术保证城市内涝积水监测系统集水位监测、内涝预警、自控排水、2数据远传等功能于一体,助力主管部门全面掌握城市内涝状况实现排水统筹调度,建立起城市内涝“数据可视化、管理信息化、指挥调度智慧化”的监测预警系统 城市内涝积水监测系统由RS485型电子水尺、电控箱 (内含远程遥测终端) 、LED双色显示屏、RS485型声光语音报警模块组成。可以将检测到的液位高度,实时显示在LED屏上。水位超限会触发号筒扬声器和声光报警器双重报警。 城市内涝积水监测解决方案示意图 以隧道为例 实时监测水位状态LED双色显示屏实时显示监测点水位数值,并将水位数值实时上传至远端服务器,实现整个城市内涝情况的集中在线监测。 内涝预警功能 当水位超过设定闯值,LED双色显示屏带有水位异常提示,同时语音报警器发出语音告警,通知来往车辆及行人改道绕行,避免发生车辆涉水熄火,人员溺水情况。 1.当水位超限后,语音播报和声光报警器同时工作,超限后声光报警器和语音播报三次(三次为一个单次报警循环周期)。 2.单次报警循环时间结束后,远程遥测终端重新判断判断水位是否超限如果还处于报警状态,则进入下一个报警循环。反之,则停止报警。 自控排水功能 积水监测系统可联动现场排水泵,当水位超过设定闯值,自动联动排水泵启动排水。同时,主管部门也可依据实际情况远程控制排水泵启停。 双向车道预警提示 本系统同时支持两路LED双色屏以及两路声光语音报警模块,实现隧道、桥洞两端双向车道预警提示。 4G上传数据实现远程监测 远程遥测终端将实时采集的水位数据通过4G上传至环境监控云平台,支持电脑端、手机APP终端登录,实现多终端数据查看。 设备展示 --- ═══════════════════════════════════════════ ## 综合管廊 ═══════════════════════════════════════════ ### 406. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 现状分析 地下综合管廊是集电力、通信、广播电视给水、排水、热力、燃气等各种工程管线于一体的公共隧道,是现代智慧城市的重要基础设施和组成部分,也是维持现代化城市正常运行的命脉随着城市地下管廊规模越来越庞大,所担负的城市人民群众赖以生存的物质基础的作用也越来越强。然而,近年来由于管廊数量增加、相关管理滞后等多种因素的交织作用,城市地下环境事故数量成倍增长,地下管廊安全问题已成为城市发展中亚待解决的重点问题。 方案设计依据 我司地下综合管廊环境与设备监控系统是按照《城市综合管廊工程技术规范》 (GB50838-2015)中综合管廊监控与报警系统的要求,在地下综合管廊环境布设各种传感器和多通道数据采集单元,实现对综合管廊环境中有毒有害气体浓度、可燃气体浓度环境温湿度、集水坑水位等数据进行实时在线采集通过多通道数据采集单元进行在线监测、预警、上传至统一管理平台,通过多通道区域控制单元实现对现场排风机、水泵、电气设备等进行就地自动、就地手动或远程控制。 方案简介 该系统通过在地下综合管廊配置相应的传感器以RS485布线方式连接环境监控主机将采集到的环境数据用4G/以太网上传至环境监控云平台。通过软件对每个测点的测量值及其工作状态进行连续采集,如出现异常,系统会自动发出声光、短信、语音、邮件告警及时通知相关管理人员,将可能出现的险情消灭在萌芽状态,避免造成大的经济损失及影响管廊的正常工作。 第一部分 防爆气体探测器(硫化氢、一氧化碳、甲烷、氧气) +气体报警控制器 防爆型硫化氢传感器、防爆型一氧化碳传感器、防爆型甲烷传感器、防爆型氧气传感器通过RS485接口连接气体区域报警控制主机,实时监测各气体浓度,当其中任一气体浓度高于设定值或氧气浓度低于设定值时报警主机触发报警启动声光报警,并联动风机等排风系统。 甲烷传感器 该设备用于甲烷浓度的检测,当浓度超过预置报警值时会发出声光报警信号,经过我司独有的补偿算法、多段标准气体标定,亦具有长寿命、高精度、高重复性和高稳定性的特点。 甲烷传感器量程为: 0-100%LEL 现场供电采用10~30V直流宽压供电,支持多种气体检测,且量程可定做 采用进口一线大品牌电化学传感器: 宽压10-30V直流供电,标准ModBus-RTU通信协议485信号输出; 地址、波特率可设置,通信距离最远2000米。 氧气传感器 该设备用于氧气浓度的检测,当浓度超过预置报警值时会发出声光报警信号,经过我司独有的补偿算法、多段标准气体标定,亦具有长寿命、高精度、高重复性和高稳定性的特点 氧气传感器量程为0-25%VOL 现场供电采用10~30V直流宽压供电,支持多种气体检测,且量程可定做 采用进口一线大品牌电化学传感器 宽压10-30V直流供电,标准ModBus-RTU通信协议485信号输出 地址、波特率可设置,通信距离最远2000米。 硫化氢传感器 用于硫化氢浓度的检测,当浓度超过预置报警值时会发出声光报警信号,经过我司独有的补偿算法、多段标准气体标定,亦具有长寿命高精度、高重复性和高稳定性的特点 硫化氢传感器量程为0-100ppm; 现场供电采用10~30V直流宽压供电,支持多种气体检测,且量程可定做; 采用进口一线大品牌电化学传感器; 宽压10-30V直流供电,标准ModBus-RTU通信协议485信号输出; 地址、波特率可设置,通信距离最远2000米 一氧化碳传感器 用于一氧化碳浓度的检测,当浓度超过预置报警值时会发出声光报警信号,经过建大仁科独有的补偿算法、多段标准气体标定,亦具有长寿命、高精度、高重复性和高稳定性的特点 一氧化碳传感器的量程为0-2000ppm; 现场供电采用10~30V直流宽压供电,支持多种气体检测,且量程可定做; 采用进口一线大品牌电化学传感器; 宽压10-30V直流供电,标准ModBus-RTU通信协议485信号输出; 地址、波特率可设置,通信距离最远2000米。 气体报警控制器 该设备是我司研发的一款气体报警控制器,通过RS485接口可将甲烷、硫化氢、一氧化碳、氧气等防爆气体传感器接入到气体报警控制器并将数据实时上传至我司提供的云平台或客户自己的服务器。 具有1路ModBus-RTU主站接口,最多可接入32台我司485型气体变送器; 带有4路无源继电器,可外接风机等设备,当气体泄漏时可控制外接设备工作常开常闭可选,继电器容量: 10A/250V; 带有高分贝声光报警器,距离设备一米处声级可达70~115dB,可区分正常高报、低报、故障、屏蔽、延时共六种状态; 1路多功能4G通信接口,只需插入一张手机卡便可将数据上传至远端监控软件平台; 具有1路ModBus-RTU从站接口,可外接用户自己的监控主机、PLC、组态屏或组态软件。 第二部分 气体报警控制器+其他监测设备与智能环境监控主机通信 智能环境监控主机通过RS485接口可接入气体区域报警控制主机、防爆型温湿度传感器、普通温湿度传感器、液位传感器,实时监测各气体浓度,当其中任一参数超过设定值时报警主机触发报警,启动短信、声光报警,及时通知管理人员紧急处理 温湿度变送器 该产品为壁挂高防护等级外壳,防护等级 IP65,防雨雪且透气性好。电路采用美国进口工业级微处理器芯片、进口高精度温度传感器,确保产品优异的可靠性、高精度和互换性。输出信号类型分为RS485,最远可通信2000米标准的 ModBus 协议,支持二次开发。 防护等级 IP65,防雨雪且透气性好 采用瑞士进口的测量单元,测量精准; 10~30V 宽电压范围供电,规格齐全,安装方便; 采用颗粒烧结探头护套,探头与壳体直接相连外观美观大方 防爆温湿度变送器 我司设计的防爆温湿度变送器,用于空气中温湿度的检测,当浓度超过预置报警值时会发出声光报警信号,以提醒用户及时采取安全措施。该变送器采用瑞士进口原装高品质温湿度传感器,传感器具有测量精度高,抗干扰能力强等特点,保证了产品的优异测量性能。 壁挂式外壳防护等级为IP65,防爆标志: Ex d IC T6 Gb 采用远程红外遥控技术,无需拆卸即可修改参数 高品质液晶显示屏,现场可直接查看数值,夜晚亦可清晰显示; 10~30V直流宽压供电,可适应现场多种直流电源; 标准ModBus-RTU通信协议、ModBus地址可设置,波特率可更改,通信距离最远 2000 米。 液位传感器 投入式液位变送器前端防护帽起保护传感器膜片的作用,也能使液体流畅地接触到膜片,防水导线与外壳密封连接,通气管在电缆内与外界相连,内部结构防结露设计。内置微型信号处理电路,可进行远程传输。具有良好的稳定性和可靠性。 反极性保护和瞬间过电流过电压保护,符合EMI防护要求; 采用核心自动校正算法,可有效防止因水面波动而引起的数值波动; 可温度自动补偿,温飘自动修正 采用高品质导气线缆,可长时间在水中浸泡 第三部分 该部分主要由环境监控主机和环境监控云平台共同对整个系统进行实时监测。 环境监控主机能自动接收所有采集设备监测上传的实时数据,并将数据通过4G以太网的方式将数据上传至环境监控云平台。当其中任一参数超过设定值时报警主机触发报警,启动短信、声光报警,及时通知管理人员紧急处理。 环境监控主机 环境监控主机是我司为管廊等环境监控的场所研发的一款多功能监控主机通过 RS485 接口可将我司所有的 RS485 型传感器接入到环境监控主机并将数据实时上传至我司提供的云平台。 该设备支持 GPRS/4G、以太网、RS485 有线等任一方式上传数据; 强大的脱机短信报警功能,报警内容可自定义(功能选配) 大屏中文液晶显示,界面简洁友好 内置数据存储,可存储 52 万条记录 可自动识别 RS485 接口从设备是否工作正常 综合环境云平台 综合环境云平台以信采集系统、物联网、云平台大数据以及互联网等信息技术为基础,各级用户通过PC端WEB、APP客户端、微信公众号等多种渠道访问平台数据实现远程系统管理功能。用户可实时对项目上每个重要参数进行实时监测、管理,同时实现基于平台的远程手动控制。 APP平台 为方便移动端用户监控数据,公司研发推出微信小程序,方便用户24小时实时监控。通过微信小程序可一键控制上万个设备,支持视频查看设备故障/异常报警,支持离线告警功能,支持实时数据查看,历史数据曲线查看,还可连接蓝牙打印机进行数据打印,功能强大。 --- ═══════════════════════════════════════════ ## 能源电力 ═══════════════════════════════════════════ ### 407. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 电网增强技术:现代化能源基础设施的挑战与机遇 许多国家今天面临着现代化能源基础设施的挑战,以尽可能可靠和经济地满足不断变化的能源需求。实现这一目标的一种有希望的方法是通过电网增强技术(GETs)。根据美国能源部的报告,2016年美国主要电力公用事业系统运营商的实时拥堵成本总额为48亿美元。2022年的拥堵成本估计为208亿美元。能源公用事业提供商的拥堵成本指的是在电网的某个部分,电力需求超过可用传输能力时产生的额外费用。这一趋势凸显了在不需要巨大基础设施投资的情况下优化成本的需求。 什么是电网增强技术(GETs)? 简而言之,GETs最大化利用现有系统传输电力。增加这些技术有助于电力传输系统继续连接到清洁、可再生能源,如太阳能和风能,以实现电网脱碳的同时满足其能源需求。因为它们可以快速增强现有电网基础设施,也因此节省资金,并避免了建设新输电线路的复杂性。 GETs可以简要分为以下几类: 动态线路额定(DLR):根据实时和预测的天气状况适当更新现有输电线路的热极限。 先进的电力流控制:优化电力流以减少拥堵和提高效率。 拓扑优化:改善电网的物理布局和连接性。 能量储存集成:将储能解决方案集成到电网中,提高灵活性和可靠性。 为了启用这些技术,电网运营商和决策者经常依赖传感器、智能表和监测设备收集实时数据,帮助他们做出明智的决策并快速响应电网变化。 动态线路额定(DLR):电网现代化的关键 动态线路额定(DLR)定义为根据实时和预测的天气状况适当更新现有输电线路的热极限的过程。输电线路的热极限指的是输电线路在生成的热量超过安全水平之前可以承载的最大电流量。通常,这些方案建立了新的极限,安全地允许更多的能量通过现有基础设施传输。 要理解DLR,我们需要了解静态线路额定(SLR)和环境调整线路额定(AAR)。 静态线路额定和环境调整线路额定 输电线路设计为导体在定义的最高温度(即其“设计温度”)下运行。在现实世界中,线路温度由电流损失(由于导电电流)和阳光增加。输电线路通过自然对流、风和辐射冷却。 由于天气条件全天候变化,并且一年四季都可能有很大的不同,线路的“实际”额定可能与设计值大相径庭。 静态线路额定(SLR)是在设计温度下输电线路的额定。这个值直接影响了可以从输电线路传输的电能量。 环境调整线路额定(AAR)考虑了天气条件的变化,允许在不同的环境条件下调整线路的额定。 DLR与SLR和AAR的不同之处 电力输电线路可以被视为特殊的高速公路,用于输送电力而不是汽车,而这条高速公路的容量可以根据天气条件的变化而增减。DLR赋予了电网运营商使用随着温度降低和强风带来的输电线路更高容量的能力。 DLR实施的挑战 为了成功实施DLR,电网运营商必须克服以下挑战: 通信挑战:监测输电线路的温度和天气的传感器可能位于偏远位置,不易访问。运营商需要考虑数据传输容量和延迟水平。 能源基础设施的安全挑战:能源基础设施的安全至关重要,因为它可能成为恶意行为者的目标。因此,全面的安全措施至关重要。 MQTT物联网平台:DLR的关键使能器 MQTT物联网平台为DLR提供了一个理想的解决方案。MQTT是一个轻量级的发布-订阅协议,专门为克服偏远环境连接挑战而创建。它还提供了一种简单的方法连接到现有基础设施,创建标准数据层,并推送数据,使其可用于任何云或企业系统。 使用MQTT进行DLR的一些优势包括: 安全性:所有MQTT通信通过TLS等进行加密,支持客户端认证和授权。 可靠性:支持MQTT的三个服务质量(QoS)级别,确保电网控制中心从整个网络中可靠地获取数据。 可扩展性:可以根据需要连接从几个设备到数百万个设备,同时保持高吞吐量和低延迟。 可用性:提供关键的高可用性,以最小化运营停机时间。 扩展框架:可以连接到各种数据库、流技术、分析工具和其他IT系统。 结论 MQTT物联网平台对于增强能源网格运营至关重要,特别是通过实时和优质数据在电网增强技术(GETs)中启用动态线路额定(DLR)。这不仅有助于提高电网的效率和可靠性,而且为公用事业提供商提供了一种经济有效的方式来升级他们的输电基础设施,而无需为节省成本而减少能源。 呼吁行动 电网运营商和决策者现在有机会通过采用DLR和MQTT物联网平台来现代化他们的能源基础设施。请继续关注我们,我们将推出另一篇博客,讨论使用MQTT物联网平台启用高级电力流控制。同时,探索MQTT物联网平台,了解如何使用它来开发、测试、部署和扩展生产物联网用例,而无需大量投资。 --- ### 408. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着环境保护意识的提高和能源危机的日益临近,绿色能源的应用愈发受到关注。在这一背景下,空气源热泵作为一种高效、环保的供热、供冷设备,逐渐成为了替代传统能源的重要选择。然而,其复杂的运行机理和常见的故障问题给用户带来了不小的困扰,这也促使着对热泵系统的智能化控制需求日益增长。 问题背景与需求 空气能及热泵产品面临着故障率较高、用户反馈不及时全面等问题,用户往往无法清楚描述设备在运行过程中的故障,导致解决时间长、运营成本高。为解决这些问题,我们研发了基于物联网技术的空气源热泵智能控制系统。 系统功能与特点 远程监控管理: 通过分布式热泵机组远程控制系统,实现对热泵机组的群组监控管理,可实现远程无人值守、实时监控,大大提高了运营效率和售后保障水平。 智能化运行: 系统具备储热水箱水温水位控制、恒温水箱控制、管道循环/回水控制、防冻/除霜控制等功能,能够根据用户需求自动调节,实现节能运行。 故障显示与报警: 系统可实时监测设备运行状态,一旦发现故障即时报警,通过多种方式通知用户,助力快速处理。 智能逻辑控制: 实现对多主机工程的群组联动、任务预约、节能工作、温度保护等模式进行调节,用户可通过手机APP/电脑监控平台进行远程设置调节。 硬件控制柜配置: 控制柜集成了各种传感器和通讯模块,能够对设备的各项参数进行实时监测和控制,保障系统稳定运行。 通讯架构与数据监控 系统通过物联网通讯技术与聚英云平台相结合,实现了远程集中监控管理热泵机组的工作运行状态。通过即插即用通讯速度快、低延时的特点,实现了对设备状态的实时监控与控制。 使用效果与成本分析 根据实际数据统计,智能空气源热水系统相比传统电锅炉和燃气热水器,在年均能效比和能源利用率上均有显著提升,能够实现更为节能的运行状态。同时,系统的智能化控制和远程监控功能,大大降低了运维成本和人力投入,提高了系统的稳定性和可靠性。 结语 综上所述,空气源热泵智能控制系统不仅满足了用户对设备运行状态实时监控与远程控制的需求,还能够实现节能减排、降低运营成本的目标,是未来绿色能源利用与管理的重要解决方案。随着技术的不断创新和应用场景的扩展,相信空气源热泵智能控制系统将在各个领域发挥越来越重要的作用,为社会经济可持续发展做出更大的贡献。 --- ### 409. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 5G基站电控箱环境监测系统整体方案 随着5G技术的快速发展和广泛应用,确保基站的稳定运行和维护变得尤为重要。5G基站电控箱作为基站的核心部分,其内部环境的监测对于保障基站正常运行至关重要。以下是一个针对5G基站电控箱环境监测的系统方案,旨在实现对基站电控箱内部环境的实时监控和管理。 一、系统目标 实时监测电控箱内部的温度、湿度、烟雾、水浸等环境参数。 及时发现和预警潜在的环境问题,防止设备损坏。 提供远程监控和管理功能,降低维护成本和提高响应速度。 二、系统组成 传感器模块:包括温度传感器、湿度传感器、烟雾传感器和水浸传感器,用于实时采集电控箱内部的环境数据。 数据采集单元:负责收集传感器模块的数据,并将数据通过无线网络发送到监控中心。 通信模块:利用5G网络实现数据的高速传输,确保信息的实时性和准确性。 监控中心:接收并存储来自各个基站的数据,通过监控软件进行数据分析和处理,并提供用户界面供维护人员操作。 报警系统:当监测到异常情况时,系统自动触发报警,并通过监控中心通知维护人员进行处理。 三、系统特点 高速度:5G网络的高速度确保数据实时传输,提高系统响应能力。 高可靠性:采用多种传感器组合,确保全方位监测电控箱内部环境。 易维护:远程监控和管理功能减少了现场维护的需求,降低了维护成本。 可扩展性:系统设计考虑未来技术的升级和功能的扩展,具备良好的适应性。 四、实施步骤 现场勘查:对基站电控箱的实际情况进行勘查,确定传感器的安装位置和数量。 系统安装:安装传感器模块、数据采集单元和通信模块,并进行初步测试。 软件配置:在监控中心配置监控软件,设置报警阈值和报警方式。 系统测试:进行全面的系统测试,确保所有模块正常工作,报警系统准确无误。 运行维护:系统投入运行后,定期对系统进行检查和维护,确保长期稳定运行。 五、结论 5G基站电控箱环境监测系统是保障5G网络稳定运行的重要措施。通过实时监测和远程管理,可以有效地预防和减少由环境因素引起的设备故障,提高基站的运行效率和可靠性。随着5G技术的不断进步,该系统将成为5G基站维护的标配,为5G网络的稳定运行提供坚实的保障。 --- ### 410. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着5G技术的快速发展和普及,为了满足用户对高速、大容量通信网络的需求,全球正加速部署5G基站。但是,5G基站的高效稳定运行对环境条件有着严格要求,特别是电控箱这一核心设备的安全运行尤为关键。5G基站电控箱环境监测系统成为确保基站稳定运行的重要支撑。 5G基站电控箱环境监测系统的重要性5G基站电控箱是基站运行的“心脏”,负责供电、控制等关键功能。环境因素如温湿度异常、水浸、断电等都可能导致电控箱故障,进而影响整个基站的稳定性。因此,实时监测电控箱的环境状态,对预防故障、提高运维效率具有重要意义。 系统概述5G基站电控箱环境监测系统采用先进的计算机网络技术、数据库技术、通信技术等,实现对电控箱内外环境的全方位监控。系统主要包括环境监控主机和云平台两部分,能够实时监测温湿度、水浸、断电、门禁状态等多种参数,并通过GPRS将数据上传至云平台,实现远程监控和管理。系统优势一体化设计:设备小巧,集成度高,易于安装,同时内置高精度传感器,确保监测数据的准确性。GPRS数据上传:利用SIM卡上传数据,无需复杂的布线,简化安装过程,保证数据实时在线。智能联动:系统可以根据监测到的环境参数自动调节空调、风扇等设备,有效控制电控箱内部环境。UPS不间断电源:确保在市电中断时仍能保持监控系统正常运行,提供持续的保护。低成本快速部署:自带免费云平台,无需另搭建服务器,支持多种数据导出格式,方便运维和数据分析。 应用场景5G基站电控箱环境监测系统适用于所有需要远程监控电控箱环境状态的场合,尤其适用于5G基站。它可以大大减少因环境因素导致的设备故障,减少运维成本,提高基站的稳定性和服务质量。结语随着5G时代的到来,基站的稳定运行对通信网络至关重要。5G基站电控箱环境监测系统为基站提供了强大的环境保护,确保了基站能够在各种环境下稳定运行,为用户提供高质量的通信服务。随着该系统的推广应用,相信会进一步推动5G网络的健康发展,满足人们对高速、稳定通信网络的期待。 --- ### 411. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 行业发展与背景 电力安全生产是电力行业的基石,相关国家标准和行业规范明确要求了电力安全工器具的管理。近年来,随着技术的不断创新,智能化管理技术逐渐应用于电力安全工器具的管理领域。其中,高频RFID联网技术是一项重要的创新,它通过RFID标签和射频识别装置实现了工器具的智能化管理。 系统功能介绍 智能管理系统主要包括以下功能: 温湿度管理:系统监测库房内温湿度,确保工器具存放环境符合相关要求 工器具管理:利用高频RFID识别技术,对工器具进行全生命周期的监测与管理,包括借用、归还、试验等。 视频监控:配备红外视屏监控系统,实现对库房的全天候监控。 报警系统:系统具备报警功能,能够及时发现异常情况并进行警报。 人脸识别门禁:采用人脸识别技术,实现对库房的智能门禁管理。 工器具台账管理:建立工器具的台账管理系统,自动记录工器具的使用情况和状态。 货架设计:根据工器具的不同类别和电压等级,设计合适的货架存放设施,实现精细化管理。 工器具状态信息可视化管理:通过状态指示灯和提示灯,实现对工器具状态的可视化管理。 工程实施案例 系统已在多个项目中成功实施,包括贵州毕节、清镇,杭州等地的库房,以及江苏盐城的车库等,为电力安全工器具的智能管理提供了有效解决方案。 这些系统功能使得电力安全工器具管理更加智能化、精细化,提高了管理效率和安全性,为电力行业的安全生产提供了可靠保障。 --- ### 412. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 系统架构 智慧场站建设范围包括升压站智能巡检、室内外轨道机器人巡检、升压站实景三维、无线覆盖、辅助控制系统以及风机测温与监视等,该系统软硬件部署在场站端的三区,支持系统间联动。本系统支持和生产管理平台集成,在生产管理系统中即可完成对全场智能应用的全面掌握,整体系统架构图如下: 系统应用特点 边缘感知 本方案以视频智能物联网技术为基础,通过智能机器人、可见光视频、红外热成像、门禁、消防网关等,汇聚采集风电场内的人员行为、设备温度及工况、环境状态,在线监测场站内的人、机、物、环,实现泛在物联。 视频设备具有区域入侵、越界侦测、安全帽检测、人员倒地、单人无监护作业、动火作业、跑冒滴漏、表计识别等分析能力,可通过内置声光报警或外界音柱报警,应用于场站安全防范、设备巡检、作业监管;红外热成像设备具有周界防范、设备精准测温、吸烟检测、等分析能力; 系统方案价值 系统方案价值可概括为以下四个方面: 拉近管理距离:通过综合数据看板、AR实景一张图等可视化形式,集中展示风电场生产运行数据,提升集控管理效率,帮助管理者更好地掌控全局管理视角,拉进管理者的管理距离。 提升业务效率:基于音视频、传感器等智能物联感知技术,助力风电场全面感知,逐步实现升压站、风机、输电线路等场景远程智能巡检,提升运检效率。 规范作业行为:与两票系统对接,获取作业任务相关信息,并结合风电场高风险作业场景,制定合适的前端布控方案,结合智能移动终端,对常见的违章作业行为进行主动识别分析,实现作业安全智能管控,进一步规范作业人员行为,提高安全生产意识,加强安全管理水平。 防范安全隐患:通过AI加持,对风电场的不安全因素进行有效的监测预警,并进行风险防范与应急处置,减少和控制事故与危害,尽量避免生产过程中由于外部入侵破坏、内部生产事故造成的人身伤害、设备资产损失以及其他重大损失。 智慧场站建设 智慧场站通过分布式部署灵敏度高的传感器,实现对各类设备得智能在线监测,并将信息上送智慧运营平台,通过平台故障预警与诊断以及健康评估等功能,及时发现隐患,在故障早期就能查找出导致问题出现的原因,以便采取相应措施加以预防和解决问题,避免恶性事故的发生,保障设备的安全运行,降低维修成本。具备对设备当前运行状态的健康评估,当设备处于异常状态时,系统发出警告或报警,实现系统联动,并可对报警部位进行进一步的故障分析和处理。通过平台对设备进行统一编码,建立各部件相应台账,实现对其全生命周期管理功能。 升压站智能巡检 远程智能巡视系统建成后将实现对升压站巡视信息的集中管控,系统包括了信息总览、实时视频、智能巡视、巡视报告等模块,在此基础上开展了场站设备区域图形化监控、设备一次接线图监控、设备单点识别等特色功能建。 信息总览 信息总览展示的是智能巡检的重要信息统计、分类及分析,集中展示巡视类型统计、任务状态统计、告警等级统计、摄像机统计、告警类型统计、摄像机状态统计、识别类型统计、缺陷等级统计并采用图形、图表等多种展现方式,不同维度对统计结果的数据进行可视化展示。 实时监控 实时监控分为:视频监控、红外监控、巡视点位监控等。 视频监控可以实时调阅室内外监控,查看设备情况以及人员流动情况。 红外监控可对接头等温度敏感点位进行红外测温,目前系统支持框选测温和点测温。 巡视点位监控可对重点部件的重点点位进行单点巡视,检查设备状态。 智能巡视 任务管理 智能巡视系统可远程进行任务管理功能,巡视任务内容应包括巡视点位信息以及月、周、日、小时等不同时间维度的巡视周期,巡视类型应包括例行巡视、熄灯巡视、特殊巡视、专项巡视、自定义巡视等,其中,恶劣天气特巡包括大风、雷暴、雾霾(含毛毛雨、大雾等)、雨后、下雪、气温骤变(含低温天气)、高温、冰雹、覆冰、沙尘暴等 ;专项巡视包括设备红外测温、油位油温表抄录、避雷器表计抄录、SF6 压力表抄录、液压表抄录、位置状态识别抄录等。具体功能如下: 巡视任务新增后可以进行修改、查询和其他管理功能;巡视任务启动后可暂停、终止,在巡视过程中可以查阅已巡视点位详情, 每个巡视点应包含本次巡视任务的全部采集信息; 任务管理模块具备月历与日历相结合的展示功能,月历应展示每日计划执行的主要任务名称及个数;日历展示当日任务的信息列表,包括任务名称、执行时间、任务状态等;不同任务状态应以不同颜色加以区分。可按时间段、任务名称、任务状态等组合条件,查询任务列表功能。 所有点位均确认后,可直接生成标准巡视报告。 任务记录 任务记录主要是历史执行记录的查询及数据展示,包含巡视任务、任务进度、已巡视点位信息、告警点位信息,巡视失败点位信息等。 巡视监控 巡检监控展示了站端的巡检任务列表,并可进行任务的新增和执行,可查看巡检任务单详情及执行的任务进度,并实时关联视频。同时展示了站端环境信息及设备运行状态,以及巡检的实时信息及报警信息。具体功能如下: 以列表形式展示巡视点位信息,用户根据巡视结果信息,可以点击查看详情,核实巡视结果,识别错误可直接确认消缺; 支持巡视视频同步; 通过树形导航调阅高清视频和机器人画面; 可多画面轮巡及画面显示; 巡视报告 系统可根据巡视记录的数据自动生成巡视报告,巡视报告具备查询、浏览、导出功能,具体功能如下: 系统在巡视任务审核完成后能自动生成巡视报告; 可通过设备区域、间隔名称、设备类型、检测类型、巡视时间段等组合条件, 查询历史巡视报告功能; 巡视报告可以查询、重置、导出、查看等功能。 智能联动 当巡检过程中识别到有告警时,系统能在第一时间触发智能联动功能,智能联动主要功能有: 告警联动应用场景包括充油充气设备油面温度与绕组温度异常、轻瓦斯动作、SF6压力低、油位异常、消防告警、乙炔突增告警、压力释放动作告警、开关变位; 系统实现的告警联动动作包括服务端自动抓拍图像、指定用户或客户端IP自动弹出视频画面、指定用户或客户端IP启动声音提示等; 系统告警界面最多仅弹出一个视频告警浮动窗口,视频窗口中叠加对应的告警信息,当告警需要弹出画面、且画面正在显示其他告警信息时,仅在告警列表中显示对应告警; 告警视频弹窗具备视频窗口双击放大功能、视频缩放及云台控制功能; 告警声音从获取告警信息开始,直至告警确认停止声音提示; 在系统屏幕右侧有告警信息集中展示列表,所有告警信息可以逐条显示,可以切换告警视频弹窗所显示的视频,当告警信息存在多个视频画面时,系统可以相应提示,由操作人员选择显示具体视频画面信息; 系统的告警信息确认功能在确认后相同的告警信息不再进行任何联动动作; 系统可以自动合并多条重复告警信息功能,重复告警仅执行一次告警联动动作; 系统可以联动查看报警设备历史告警信息以及相应历史数据。 可以在系统内根据集控站监控系统的告警信号配置联动策略,联动策略配置可以选择一个或多个视频设备。 运行分析 运行分析可对单点或者多点的历史数据进行调阅及数据分析。 台账管理 系统从升压站远程智能巡视系统获取机器人、视频设备信息,并与升压站远程智能巡视系统保持台账信息的一致性; 系统内可以进行机器人、视频设备台帐信息的查询,并按照生产厂家、设备类型、设备型号、设备来源、使用类型、运行状态等维度进行数据检索。 配置管理 配置管理界面可实现巡视报告配置、视频监控配置、联动信号配置以及消息权限配置。 巡视报告配置主要是对报告的格式进行配置,可生成标准报告和标准作业指导卡。 视频监控配置系统可以按1/4/9/16/全屏多种分屏模式配置轮巡方案、画面切换的时间间隔、画面调用的摄像机等。 联动信号配置主要是针对事件化联动进行配置相关抓图联动、视频联动、巡检联动的配置。 消息权限配置管理可以配置账号权限、身份鉴别与访问控制等。 特色功能 区域图形化监控 区域图形化监控可以通过站内平面图,快速调阅巡视点位附近的摄像机对点位进行视频监视。 一次接线图监控 一次接线图监控可以通过主接线图,调阅间隔附近摄像机对间隔内问题点位快速定位并进行视频巡视。 单点识别 单点识别是一种实现快速巡视某一个设备部件的巡视方法。当临时需要查看某个设备部件的状态时,可以通过单点识别模块查到到相应的点位,然后执行即时识别、分析,无需建立巡视任务,从而实现快速巡视的目的。 机器人巡检 机器人系统整体介绍 智能巡检机器人系统主要针对室内外电力场景的内部设备及其周边环境实现自主化无人巡检;由电路板、升降机构、行走机构、高清摄像头、红外热像仪、局放传感器等核心设备和其他辅助设备组成。 机器人运行采用吊轨式以及轮式行走,确保检测精度、采用多节升降模块确保对竖直检测面的覆盖;采用三轴分立式云台结构,实现传感器模块在竖直轴和水平轴的转动自由度,保证设备检测位置最优化选取。 为确保机器人在运行过程中的安全性,智能巡检机器人搭载了激光避障模块,通过激光传感器实时探测其水平、垂直方向上的障碍物,一旦检测到障碍物,立刻停止运行,待障碍物移走后继续执行巡检任务。智能巡检机器人结构如下图所示。其智能检测模块由人机交互模块、局放传感器、红外热像仪、可见光相机等组成,实现机器人仪表图像识别、红外测温、局放检测等功能;检测模块采用三轴分立式设计,可在垂直、水平方向上自由旋转,实现传感器检测位置的最优化选择,杜绝检测盲区;红外热像仪和可见光相机采用共体双向结构,能够对两侧的设备进行同时检测,极大的提高了巡检效率。 电力智能巡检机器人 全覆盖自主巡检实现方式 电力场景大多巡检空间较小,尤其内部待检测设备分布高差大,且部分设备安装位置偏僻,不易观察,巡检覆盖范围狭窄、信息提取困难,准确性不高,在巡检时存在误测、漏测等情况,降低巡检数据可靠性。为解决这些问题,创新研发了一种机器化巡检复杂空间精确定位技术。首先基于配电网环境状况和设备分布状况,将巡检空间分解为沿三个直角坐标轴方向的移动自由度,以及两个绕轴旋转的转动自由度。 图3.5 巡检空间的五自由度分解 进一步的,利用行走完成机器人在x轴上的水平移动,实现对巡检平面的遍历;利用多节升降机构,完成对垂直检测面的覆盖,并结合绕x轴、z轴的两个转动自由度,实现对设备检测的最优化点位标定;最后,利用伸缩式检测臂,完成在y轴上的移动自由度,实现与设备的接触式检测。 精确定位方面,轨道上采用基于多传感器融合的轨道定位技术,利用站点定位片将长距离轨道分割为等间隔定位区间,消除定位累积误差;各部件运行定位方面,采用绝对值编码器配合电机双闭环控制算法,确保运行可靠性和定位准确性。基于精确定位手段,机器人根据预先标定的检测设备位置,结合视觉伺服技术,实现按预设巡检策略的自主、精确巡检。 指针类仪表设备识别实现方式 采用基于Hough直线检测和对称性检测算法,完成指针边缘的精确提取,根据指针偏转角度计算获取仪表读数。首先基于Canny边缘检测算法提取图像边缘,获取表计图像梯度,对梯度进行非极大值抑制,采用双阈值算法初步滤除伪边缘。随后,基于指针的对称性特征,提取图像中的对称边缘点对,并采用Ransac共线性检测去除伪指针边缘像素对,最后对边缘点对进行聚类合并,获取指针对称轴,从而准确识别指针位置,滤除传统指针识别算法中的环境干扰,并提升指针识别的位置精度,提高识别准确率,识别精度可达小数点后3位。如图3.6所示。 图3.6 基于对称特性的指针识别 数字类仪表设备识别实现方式 采用基于AlexNet卷积神经网络完成字符识别、基于Cascade Classifica-tion目标检测完成小数点定位。Alexnet卷积神经网络共有卷积层5个,池化层 3个,全连接层3个(其中包含输出层),摈弃了传统神经网络中需要人为指定图像特征的缺点,利用卷积神经网络中的卷积层自动完成特征提取工作,并用多层小卷积叠加来替换单个的大卷积,提升卷积层的厚度和宽度,优化卷积层表达能力;并使用重叠的最大池化,避免平均池化的模糊化效果。识别的准确性和快速性得到了显著提升,对字符的适应性更强。 图3.7 AlexNet卷积神经网络 电气指示类设备识别实现方式 基于指示灯和背景区域的亮度,采用自适应二值化、阈值化方法进行指示灯亮灭、指示灯颜色的自主识别与检测。传统的二值化方法通常采用全局阈值法,即将图像中低于某个阈值的像素设置为黑色,而其他的设置为白色。在实际工程应用中,室内空间的各类设备可能会受到吊灯、窗户、移动的影子、自身颜色等影响,人类的视觉系统能自动补偿这些,但是机器没有考虑到这些因素,因此导致识别效果较差。为此,采用一种阈值自适应的二值化算法,根据每个像素的背景亮度来改变阈值,这种基于局部特征的二值化方法,对各类环境和设备类型具备更好的适应能力,如图3.8所示。 图3.8 自适应二值化方法效果 机械状态指示类设备识别实现方式 电力设备机械指示种类繁多,根据机械状态的类别不同,采用基于直线检测的偏转角度计算、基于AlexNet网络的状态分类方法、模板匹配、颜色检测方法等多种检测算法,有针对性的完成对不同种类机械状态指示的准确识别。 局部放电检测实现方式 机器人采用地电波(接触式)和超声波手段,获得设备局放情况,能够将放电信息实时地传递到远程数据中心,当检测到开关柜设备内局部放电处于异常状态时,立即进行报警,提示管理人员到现场维护。通过局放检测设备,实现不同时刻和位置的电力柜局放监测。局放检测设备数据及控制后台具备局放数据自动绘图、自主识别和诊断功能,在局放出现异常情况下可以实现实时报警、应急模式巡检及系统联动功能,同时数据后台能够对单点检测数据进行历史分析,并进行归档、诊断等功能;地电波+超声波的局放检测方式,拓宽了检测频带、提高了检测灵敏度,并结合时间维度上的趋势分析,实现设备局部放电的精确监测。 设备测温实现方式 机器人搭载红外热成像仪,对机器人巡检区域的电气设备进行测温,进行设备致热现场检测与缺陷诊断,根据致热设备运行状况进行诊断分析,及时发现设备潜在缺陷并发出预警,提前进行设备防护,消除隐患,提高设备运行寿命和效率。 对于站用变、蓄电池室、主变室、散热室及电容器室等场所的测温采用固定热成像球机进行检测。 数据及控制后台具备温度数据自动绘图、自主识别和诊断功能,在温度出现异常情况下可以实时报警,同时数据后台能够对单点检测数据进行历史分析,并进行归档、诊断。 图3.10 设备柜红外测温 室内挂轨巡检机器人可以搭载红外热像仪、可见光高清摄像机、气体探测仪、温湿度传感器、交互式实 时对讲平台、声光报警器、光电停障系统等,系统采用我公司自主研发的通用可配置软硬件平台控制,全工业化元器件设计,系统运行可靠,功能齐全。 室内挂轨机器人具有可见光与红外视频图像采集功能,工作人员可通过上位机软件操作机器人移动到指定位置,控制云台自由转动,可实现近距离地观察拍摄目标物体,将监控范围覆盖到盲区。机器人可拍摄出站内各种设备高清图像和红外热成像,并将采集到的信息经局域网实时传输到主控室,在主控室的工作人员便可根据图像判断出各种电力设备是否安全。当发现设备有异常情况,工作人员可在第一时间查清问题原因,并采取相应措施。 在巡检过程中,室内挂轨机器人通过自身携带的一体化云台装置,可对周围环境进行视频图像的采集,并根据工作人员的需要将图像信息经在线通讯传回主控室,并自动记录拍摄地点和设备名称,以备工作人员日后能查询完整的信息。 室内挂轨机器人本体 室内挂轨机器人系统由室内挂轨机器人本体、轨道平台、供电平台、网络通信平台、定位模块、后台监控平台等组成。 室内挂轨机器人 室内轮式机器人本体 室内轮式机器人系统由室内轮式机器人本体、供电平台、网络通信平台、定位模块、后台监控平台等组成。 室外轮式机器人本体 室外挂轨机器人系统由室外轨道机器人本体、供电平台、网络通信平台、定位模块、后台监控平台等组成。 自主导航 智能巡检机器人根据巡检任务自动巡检;视频监控根据巡检任务自动调用对应的固定摄像机,并自动完成摄像机观测位置和角度调整。 自动记录 自动采集并记录巡检任务对应的各类设备巡检数据,按设备树归类展示,并自动生成巡检报告,包括例行巡检、专项巡检及自定义巡检报告等。 智能识别 利用图像识别技术,对巡检过程记录的可见光照片等进行智能分析,自动判断设备状态。 可见光检测功能 可见光检测具备如下功能: 机器人配备可见光摄像机,能对室内设备外观、开关 、刀闸 分合状态及仪表、油位指示、刀闸传动轴划线的外观;保护装置状态指示灯;压板空开位置、保护装置液晶屏显示进行准确拍摄 进行采集并将视频实时上传至本地监控系统。上传视频分辨率高清规范(1080P),且分辨率可手动调整。 存储采集到的视频,支持视频的开始录像、停止录像、播放、停止、重启、抓图、全屏显示等功能。 最小光学变焦数30倍,可在10米距离外清晰识别表计刻度。 红外检测功能 红外检测具备如下功能: 机器人配备在线式红外热成像仪,能对一次设备的本体和接头的温度进行采集,并能将红外视频及温度数据实时传输至本地监控系统。 存储采集到的电力设备红外热图,并能从红外热图中提取温度信息,可自动追踪测量全屏最高温。 红外检测设备成像像素不低于640×510,测温精度不低于±1℃。 防碰撞 机器人具有障碍物检测功能,在行走过程中如遇到障碍物应及时停止并报警,指定时间内障碍物移除后应能恢复行走。 自动充电功能 机器人采用电池供电模式。 具备自动充电功能,在需要充电时能够自动返回充电座,通过与充电设备配合完成自动充电。 在电量较低时,控制各个模块供电,并返回充电,监控电池容量,预测电池寿命,容量低于限制时远程报警。 因自动充电而中断巡检任务时,充电完成后能够根据设置恢复或停止巡检任务。 具备充放电次数记录和展示功能。 双向语音对讲功能 机器人具有双向语音对讲功能,配有音频采集和播放设备,能通过安全的无线通信方式接入,与本地监控系统之间的全双工双向语音传输。 双向语音传输的语音质量和延迟满足远程视频指导的要求。 辅助照明功能 机器人具备辅助强光照明功能,能保证在夜间或阴暗天气下正常运行。 状态指示 机器人具有状态指示功能,在作业时能提供状态信号。 远程遥控 运维班可实现自动巡检装置的远方人工遥控,主要包括智能巡检机器人、视频监控等。 室内外全覆盖 综合各种巡检技术手段采集数据,按照巡检任务要求自动完成升压站室内一次、二次设备设施的全覆盖巡检。 升压站实景三维 升压站实景三维是运用基于精确空间位置信息的全站点云及三维数据,结合高性能、强兼容的三维数字孪生引擎,实时渲染构建一个与升压站外观一致、坐标一致、属性一致的数字孪生升压站,开发全景可视化的立体监盘功能,打造升压站的数字化全景监控。 指哪看哪 利用空间视野分析技术,实现对关注目标的视频视野画面自动匹配、自动聚焦,监控人员无需关注具体摄像机安装位置,在三维场景中通过鼠标点击想要查看的设备部位目标即可自动打开视频画面,摒弃传统查找摄像机转动云台搜寻设备目标的繁琐操作。 数据可视化 三维实景系统通过标准化接口(如websevice、json、私有API等)将升压站内数据融合,数字孪生应用模块通过调用接口将数据与设备模型进行映射,监控人员通过点击设备模型显示设备当前实时数据,查看设备运行状况。 位置可视化 通过点选设备类别可以实现快速查看升压站内各设备对象的位置分布信息,比如选择视频监控,则孪生三维场景中只显示跟摄像机相关的模型可视化标签,监控人员即可一目了然了解摄像机在升压站内的分布,并通过直接点击摄像机标签即可实时打开摄像机视频画面进行浏览,如下图所示。 告警可视化 在智能图像识别模块发现异常后,根据缺陷库迅速分析出故障类别,准确定位故障位置,自动锁定目标,以部件“闪烁”的形式实现漏油、漏水、放电、发热等故障的可视化告警,并以语音播报方式进行提醒,便于运维人员快速了解告警信息,准确标识故障位置,加快故障处理速度。 通过数字孪生系统数据接口实时监听设备告警信息,将接受到的告警信息通过着色在孪生三维场景中进行高亮显示,并自动定位到告警设备位置,方便监控人员快速了解告警设备信息,如下图所示。 升压站智能安防及辅控 升压站辅助设备监控建成后将实现对栖霞站的动力环境子系统、安全防范子系统、视频监控子系统、在线监测系统、物联网感知等子系统的实时监控,并在此基础上进行特色功能区域监视的开发。 智能安全防范 对于陆上风电场,以视频为核心的多维感知技术手段,可帮助风电场打造安全防范三道防线。 第一道防线: 周界通过热成像、可见光视频、电子围栏、等构建两级报警,先检测人员在围墙外围区域内徘徊或者停留,再检测是否进入围墙区域;大门区域通过全彩球机实现人员区域入侵侦测、徘徊侦测、人员聚集侦测等功能;大门口部署门禁闸机配套人脸识别一体机,比对成功后实行自动开门。 第二道防线: 在主控楼大厅,通过人脸比对检测是否为准入人员,进入一次场地区域的入口处,通过人脸比对检测是否为准入人员。 第三道防线: 在主控楼各小室(如开关室、集控室、通信室)出入口,部署人脸识别一体机,通过人脸比对来开启门禁。 风电机组三道防线如下: 第一道防线:塔筒外围区域及塔外梯区域,通过全彩球机实行人员区域入侵侦测、徘徊侦测、人员聚集侦测等功能。 第二道防线:塔筒底层入口处,通过轻智能相机,配合视频智能分析服务器,检测人员数量,识别是否为准入人员,是否为单人无监护作业。 第三道防线:通过可见光视频或双光谱热成像,自动监视进入机舱人员的作业行为。 安全防范展示的是站端安防设备,包含电子围栏、门禁、人脸识别等。可展示平台所属范围内的所有门禁系统,并可联动相应场景门禁的监控视频,可便捷地进行各门禁场景的视频切换。门禁系统解锁方式可采用人脸识别开锁、按钮开锁、刷卡开锁等功能,并可与安防系统实现撤防和布防的联动。可展示电子围栏设备的节点状态,及联动视频。 电子围栏 可以查阅电子围栏及红外对射的实时状态及数据。 智能门禁 可查阅大门处实时视频监控;查阅人脸刷卡机、卡片机等刷卡记录;展示门禁台账以及状态;对人员权限进行管理等功能。 人员车辆管理 风电场一般位置较偏,外来人员、车辆相对较少,但考虑到风电场是电力系统的重要场所,需要对所有进出风电场站的人员、车辆进行有效管控。 风电场人员主要有内部员工、外包人员和外来访客。 对于内部员工,通过人脸门禁、人脸智能监控系统,方便在场站和风机内部通行,辅助其进行对重要设备区域的安全管控。 对于外包人员管理,借助智能化技术手段,加强对外包人员的准入权限、是否上岗到位(出勤情况)、作业行为是否合规等监管。 对于外来访客,通过访客管理系统,辅助进行访客实名制管理,加强安全准入管控,提升访客管理效率。 此外,通常情况下,风电场内部车辆和施工用车才会周期性进出电站。风电场作为电力系统的重要防护对象,需杜绝无关车辆进入,对进出车辆进行识别和记录。通过车牌抓拍识别专用相机,对进出风电场站的车辆进行抓拍记录,方便后期按需查询。所有车辆经安保人员检查核验后,由安保人员控制伸缩移门或其他实物门予以放行。 动力环境 环境监测-水浸传感器 可展示当前生产设备区电缆沟或电缆层水浸传感器的位置分布,并统计所有水浸的报警器总数、故障数及单个设备节点的历史数据。 2) 环境监测-风机控制 可展示升压站风机状态并能远程对风机启、停控制,同时可智能联动。 环境监测-温湿度 可展示升压站温湿度传感器的温度、湿度等数据监视,同时可设置预警阈值进行告警监视。 环境监测-空调 可展示控制室、开关室、保护室等场所内所有空调的基本信息,通过平台可对空调的制冷,制热和湿度进行相应的遥控控制。并可统计所有空调的报警器总数、报警数和故障数。可通过室内温湿度传感器,实现对空调的自动启停,可对各场景空调设置不同温湿度控制触发启动阈值。 环境监测-照明 可展示升压站所有场景照明的开关状态,并可同步联动展示相应场景的监控视频。通过平台可对各场景的照明灯进行远程遥控操作。 视频监控 常规视频监控 以摄像机、场景、设备为选择对象,便捷地实现目标区域的视频监控调阅。 场景视频监控 设置视频监视场景,查看相关视频监控。 视频与消防系统联动 视频监控系统实现与消防系统进行实时联动,当出现火灾或烟雾时(如有意外发生时),机组消防火灾报警主机发出报警后,监测球机自动旋转至火灾点,同时联动火警点就近摄像机位置进行实时监控,升压站发出声光报警,同时监测平台弹屏提示,提醒升压站工作人员查看。 外包人员管理 风电场每年都有不少技改、设备检维修等外包项目,在特殊时期,外包人员数量多,人员流动性大,如何严格外包人员准入管理,提高外包人员安全生产意识,规范外包人员作业行为,防范安全生产用户,是风电企业用户关注的重点内容之一。 以人脸识别、智能联动技术为基础,通过与承包商管理信息系统对接,自动同步外包人员信息,关联人员安全教育、考试培训、门禁权限管控、考勤管理、作业监管、承包商用工统计等业务信息,帮助风电场安监人员提升安全监管业务效率和水平,实现主动安全管控。 外包人管理业务应用 作业安全监管 风电场基建、技改、设备检维修过程中,会有很多高风险作业,如监护人员离岗、未戴安全帽、高空作业未系安全带、误跑带电间隔、吊装作业人员违规进入安全红线区、动火作业未设置灭火应急装置等。 风电场安监人员数量少,通过监护人员现场监工或人盯视频图像的方式,工作量大,且很难发现问题,容易导致安全监察流于形式,需机器视觉代替人工监视,一旦侦测到违章违规作业行为,系统能够自动报警,并保留违章视频图像证据,以便后期安监部门人员处置。 结合风电场高风险作业场景特点,可进行合理前端布点设计,对于作业时间周期长,需全天候监视,网络传输和供电易保障的,可部署固定点高清监控摄像机。对于临时性作业,网络传输和供电不易保障的,可采用便携、可靠、长续航的高清移动监控设备。 AR实景一张图 AR实景一张图运用AR增强现实技术,将视频中的背景信息进行结构化描述,使背景信息可搜索、可定位,并结合GPS坐标映射、方位感知、视频联动等功能,将虚拟信息嵌在现实世界中进行互动。 风电场AR实景摄像机可部署于升压站制高点、风机机舱内(宜采用AR半球),通过接入风电场安全管理、在线监测等数据,鸟瞰电厂全貌,以AR实景地图结合虚拟标签形式,从不同角度直观地查看风电场生产运营信息,丰富管理视角,助力风电场站数字化管理。 风电场升压站 风电场升压站AR实景一张图 特色功能 区域监视 升压站区域内主辅设备、监测设备等设备种类繁多且复杂,班组巡检人员在设备状态检查和数据查询等工作上工作量巨大,通过区域监视可在场区平面图上快速查阅故障区域位置内各类主辅设备、监测设备的视频监控、自身状态、遥信数据以及辅助设备遥控的功能。 拓扑信息展示 通过拓扑图,可以快速查看系统主要的网关设备、串口设备以及智能终端等设备的拓扑结构。 风机侧智慧运维 建设内容 本期建设规划10台风机,于中心风机机舱上方安装鹰眼全景摄像机1台,俯瞰全场。单台风机塔基和机舱分别配置1个视频摄像头具备对讲功能。每台风机安装位置分别为:机舱发电机后方右上角(热成像半球摄像头)、机舱主轴前方左上角(热成像半球摄像头)、机舱高速轴刹车盘上方(热成像全球摄像头)、塔基和塔筒门上方(全彩球机摄像头),塔基为立杆安装,覆盖道路、塔筒门、箱变。共五个位置装设视频摄像头。整个视频监控系统在实现实时视频监控的同时具有一定的扩展性。通过风机内光缆网络与升压站视频监控服务器进行通讯,使用集中式存储方式,对前端视频数据进行存储,在操作端进行监控图像的显示。当有陌生人员侵入塔基时,或机舱内由异常温度升高或明火时可产生报警信号,并发出声光报警。将相关数据上传至集控中心实现同步监视及报警。 在线测温 红外测温应用通过热成像摄像机对设备温度进行实时监控,及时发现设备温度异常并产生报警。同时存储并统计设备上报的温度实时值,通过数据可视化展示设备温度的变化趋势。采用热成像摄像机进行测温,解决了采用传统传感器进行测温的缺点如不抗腐蚀、不能进行大面积全域测温等。 测温录像回放 人工复核中诊断红外巡检项的,可以切换进行录像数据的在线测温。可以根据录像画面,绘制临时测温框或者选择固定测温框。 温度异常报警查看 温度异常告警。支持展示设备温度报警,可通过告警源、预置位、测温位、所属区域、告警类型及告警时间筛选。 支持查看告警详情,包括告警抓拍图片及录像信息,其中录像信息支持叠加显示测温规则。 人脸识别系统 利用人体骨骼的识别技术对人脸进行识别, 重点人物如擅自进入,就会在 0.01 秒之内被揪出来,同时向升压站弹屏报警。另外,升压站重要区域如控制中心只允许特定身份的工作人员进出,这时候面部档案信息未被系统存储的 所有人全都会被拒之门外。 安全帽识别系统 安全帽识别算法的核心功能是针对作业人员头部是否佩戴安全帽和人员头部佩戴安全帽 进行识别并区分。监控作业人员佩戴安全帽的情况,一旦发现未佩戴安全帽的人眼,安全帽识别系统会第一时间抓拍、存储,并发出警报,提醒处理。 入侵报警系统 当出现人员入侵发生时,机组入侵报警设备发出报警后,监测球机自动旋转至入侵点,同时联动入侵点就近摄像机位置进行实时监控,升压站发出声光报警,同时监测平台弹屏提示,提醒升压站工作人员查看。 无线覆盖建设(AP)  针对风机机位手机信号弱/无信号导致工单系统无法使用的问题提出以下详细网络解决方案。在无手机信号的风机工作时,获得信号接入,进行工单进度录取、缺陷查询跟踪等工作。在满足网络和信息安全接入的前提下,确保解决机位手机信号弱/无信号问题。 风电场办公无线网络系统主要目的是实现风电场所有风机端的网络无线覆盖,给信息系统提供数据传输通道,并承载移动应用。 风电场办公无线网络系统概述 风电场无线通信系统主要用于建立覆盖风电场所有风机点位的无线通信网络,通过在场区内部署固定通信节点,以及为运检人员配备相应的便携式移动终端,从而在风电场主控室与运检人员之间建立无线传输链路,满足风电场实时开具工作票、操作票、巡检管理、语音及视频通讯等移动运维业务需要。 风机顶部舱内与底部舱内各安装一台无线覆盖节点,实现风机机舱和塔底无线覆盖,各风机通过光纤环路实现整个风场的通信网络互联互通。考虑到机舱内部空间狭小,因此设计节点轻便小巧,安装过程简单快捷。 机舱上下的无线覆盖节点可根据实际情况使用光纤相连,为机舱内的运维人员、检修人员的手机、PAD 等业务终端提供无线接入,提供各种业务通信,使维修作业人员可以与其他人进行话音和视频通信,控制中心专家也可以用话音和视频为作业人员提供指导,实现全区域现场无线覆盖。 风电场办公无线网络系统建设原则 Ø 系统可靠性原则 风电场网络系统作为应用系统运行的基础平台,各应用、业务系统对支撑平台具有高度的可靠性要求,建设的系统必须保证不间断运行。在方案设计中,必须对网络设备和节点的部署进行合理的规划、保障系统全年不间断稳定运行,并提供完备的备份和恢复措施,保障在业务系统出现重大故障后能迅速恢复。 Ø 系统安全性原则 风电场网络作为应用、业务系统的支撑平台,对系统的安全性具有高度的要求。网络系统应具有高度的设备安全性与数据安全性,并需要建立完善的安全管理制度以及安全应急预案,为信息系统稳定运行提供良好的安全保障。 Ø 可扩展性原则 风电场的网络系统是随着公司规模的发展不断调整的,作为较为固定的网络支撑平台的建设应具有良好的扩展性,以满足业务扩展和发展的需要。 Ø 高性能原则 建设一个高性能和良好服务质量的网络支撑系统是保证风电场各业务系统真正实用化的必要条件,只有这样才能保证各种应用的稳定、高效运行。网络系统不仅要具有满足应用的带宽和传输延时,而且应该确保关键网络应用业务流不出现网络拥塞丢包和过大的延迟。 Ø 经济性原则 在满足应用业务系统需求的前提下,选用经济实用的软硬件设备,以便节省投资,达到高性能的价格比。 风电场办公无线网络系统 利用风电场每条集电线路中,风机与升压站、风机与风机之间现有光缆的空余纤芯,在升压站及每台风机处部署一台交换机(含光口及电口),从升压站到每台风机端搭建一个办公网络系统,通过划分VLAN将办公网络中不同应用隔离开。 风机办公网络系统与现有的生产网络的架构类似,两个网络使用相同光缆的不同纤芯,并使用不同设备,在物理上互相分离,互不影响。 风电场办公无线网络系统对通信网络的要求 通信网络的根本任务是解决风电场监控系统的实时信息交换,而网络是不可或缺的功能载体,那么构建一个可靠、实时、高效的网络体系是通信系的关键之一。 通信网络的性能要求主要体现在以下几个方面: 可靠性 由于电力生产的连续性和重要性,通信网络的可靠性是第一位的,应避免一个装置损坏导致通信中断。特别是数字、图像信息的多媒体技术的应用,我们会更加依赖通信网络,因此,一个可靠的通信网络是首要条件。 实时性 因语音,视频,移动办公应用等信号要求实时传送,而且在用网高峰时要传送大量的数据,要求信息能在通信网络上快速传送。 环境适应能力 风电场应用环境恶劣,长年风沙严重,昼夜、冬夏温差大,要求交换机,AP等设备工作温度范围较宽,拥有较高的防护等级。在风机舱中存在非常强的电磁干扰且在部分区域处于高雷暴地区,要求设备拥有极强的抗电磁干扰能力。 网络设备的选型原则及设计思想 结合业务的实际需求,网络的设计具体思想为各种业务负载能达到均衡传输、网络设计安全可靠的原则。网络设计及设备选型原则如下: 硬件可靠性原则,根据该项原则,系统的电磁兼容性、系统的温度湿度特性符合规范的相关要求。 系统的可扩展性原则,充分考虑未来的升级和换代的可能性,按照符合IEC61850协议对交换机的基本要求进行设计和选型。 抑制广播风暴源数据的原则,网络中有多种数据类型可能导致广播风暴,如未知的单播数据、未知的组播数据、广播数据等,系统的广播拟制功能应根据这些数据类型分别进行抑制,达到网络性能的可靠性。 广播域最小的原则,提高网络传输的可靠性和安全性。一个子系统由于某种原因出现广播风暴,不会影响到其他子系统的通信。 网络数据实时性原则:网络设备具有全线速转发的能力,能保障系统的数据在小于10ms或甚至4ms的时间内完成数据传输和系统操作。 网络平台冗余或系统快速恢复的原则:网络平台应具有链路冗余的功能,当网络无意中相成环型网络,能快速的把网络分解成逻辑的链型结构,保证网络的可靠性。或者提供环行的网络结构,当网络某点故障时,系统能快速恢复。 无线覆盖设备需要满足802.11a/b/g/n协议标准。 根据以上几个原则,在本系统中选用高性能工业以太网交换机以及无线宽温产品。 4.6.5. 方案拓扑结构 4.6.6. 功能建设 网络系统整体网络采用环网汇聚和环网接入两个网络的构架,主要传输业务有手持终端数据监控、视频监控等。在每个风机的塔筒底部及机舱放置工业以太网交换机以及无线AP,整个环网设备通过光纤互联,升压站机房放置两台工业以太网交换机,作为多个环网的汇聚交换机,升压站的数据服务器、网管服务器以及无线AP控制器AC接入通过网口接入核心交换机。每个风机内由工业以太网交换机组成多个环网,每个环网通过物理相隔离提高网络的安全性,环网交换机启用基于国际标准IEC62439-6的DRP快速环网冗余协议,保障了网络的无扰切换,网络自愈时间小于20ms。每台风机布置一台无线AP,无线AP通过网线接入环网工业交换机,把无线数据接入有线网络。无线AP支持802.11a/b/g/n协议标准,传输频段为2.4GHz、5GHz两种,办公网络的现场设备可通过网线直接接入环网工业交换机。同时在升压站配备1台AC无线控制器通过有线网络对无线AP实现远程监控、配置、管理等。 --- ═══════════════════════════════════════════ ## 解决方案 ═══════════════════════════════════════════ ### 413. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在现代企业中,自动化设备和人工智能技术的广泛应用显著减少了生产现场运行操作人员的数量,提高了生产效率。然而,这也为设备的维修保养工作带来了新的挑战。复杂的自动化电气设备、机械设备,以及各种电缆和管线的正常运行需要高效的监控和维护,以减少停机事故的发生。传统的“巡检式维护”耗费时间较长,影响企业生产效率,并且也具有一定的误差性。为了更好地对机器进行监管,企业应充分利用现代化技术,最大程度地保障自身效益,避免停机事故的发生。 传统巡检式维护的局限性 在传统的巡检式维护中,工人定时巡检机器,发现故障后上报给维修部门,维修工再根据故障大小采取不同措施,进而反馈给车间主任,再汇报给工厂厂长等。这种方式虽然能够发现问题,但耗费的时间较长,并且依赖于人工的判断,具有较大的误差性,可能会导致问题被延迟发现或漏报,从而影响生产效率和设备的正常运行。 现代化技术的应用 为了克服传统巡检方式的局限性,现代企业应充分利用先进的传感器技术、数据分析技术和通信技术,实现对设备的实时监控和智能维护。Modbus温振变送器就是其中的典型代表。 温振变送器的特点 高性能:Modbus温振变送器采用高性能的MEMS芯片,具有微小、轻量、低功耗、高可靠性、高灵敏度和高精度的特点。它可以通过监测温度和振动数据,及时发现机器运行过程中不易察觉到的异常情况,以便能够尽早修复。 多轴测量:温振变送器可测量X、Y、Z三轴振动速度、振动位移等参数,避免了单轴振动传感器的局限性。在使用时,无论是需要监测哪个方位的速度和位移,它都可以涵盖到,满足用户所有需求。 内置温度传感器:温振变送器内置温度传感器,可测量机器表面温度,以便用户根据温度变化进一步确定电机是否出现故障。常规款温振变送器可测机器表面温度到-40℃~85℃,高温款则可测到-40℃~150℃。 全方位防护:温振变送器外壳采用全不锈钢或铝合金设计,具有高密度、高抗氧化性、耐磨损、耐腐蚀的特点,能够很好地保护内部元器件不受外界环境影响。RS485型/模拟量型采用灌封设计,超强防护,甚至可以在水下使用。 安装简单:温振变送器拥有螺纹和磁吸两种安装方式,用户可以根据实际需求选择合适的安装方式。螺纹安装方式有多种规格,安装时直接拧在机器对应位置即可。磁吸安装方式只需吸附于机器上即可。 多种数据传输方式 温振变送器支持多种数据传输方式,包括LORa、NB-IoT、RS-485和模拟量,用户可以根据需求进行选择。这些传输方式能够实时监测机器的振动状态,收集振动速度、温度数据,并上传到云平台,对机器的运转率和性能进行跟踪和分析,及时发现异常情况,提醒用户进行维修和调整,避免更大的故障和停机。 温振变送器的应用优势 数据测量精准:高性能的MEMS芯片和多轴测量能力使温振变送器的数据测量更加精准,能够及时发现机器运行中的异常情况。 实时监控和报警:温振变送器可以将监测数据实时上传至环境监控云平台,用户可以随时掌握机器的工作情况。平台具有完善的报警功能,一旦数据超过设定的安全阈值,便会进行远程报警,提醒用户及时处理。 历史数据查询:环境监控云平台可以记录历史数据,用户可以按时段查询,生成日报表、周报表、月报表,为电机制定维护计划提供数据支撑。 账号分级管理:云平台具有账号分级功能,可以根据不同人员的职务分配对应的管理权限,增强团队的责任感,实现信息共享。 总结 现代企业应充分利用先进的传感器技术、数据分析技术和通信技术,实现对设备的实时监控和智能维护,最大程度地保障自身效益,避免停机事故的发生。Modbus温振变送器作为一种高性能、低功耗、抗干扰的复合型振动传感器,广泛应用于煤矿、化工、冶金、发电等行业的旋转机器温度和振动的在线测量,为企业设备的高效运行和安全生产提供了有力保障。通过科学的维护和智能化管理,企业能够进一步提高生产效率,降低维护成本,增强市场竞争力。 --- ### 414. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着工业化进程的加速,工业设备的稳定性和安全性变得尤为重要。为了确保设备的长期稳定运行,减少故障率,降低维修成本,现代工业对在线监测预警系统的需求日益增加。一体式温振在线监测预警系统正是在这种背景下应运而生。本文将详细介绍这种系统的原理、组成、优势及其在工业中的应用。 一、系统原理 一体式温振在线监测预警系统主要通过温度传感器和振动传感器对设备进行实时监测。温度传感器能够监测设备关键部件的温度变化,而振动传感器则可以捕捉设备运行时的振动情况。通过将这些传感器采集到的数据传输至中央控制系统,系统可以对设备的运行状态进行实时分析和判断。一旦发现异常情况,系统会立即发出预警信号,以便相关人员及时采取措施。 二、系统组成 传感器模块: 温度传感器:用于监测设备关键部位的温度,如电机、轴承等。 振动传感器:用于监测设备运行时的振动情况,可以检测到设备是否存在不平衡、松动或磨损等问题。 数据采集模块: 负责将传感器采集到的数据进行初步处理和传输。这一模块通常包括数据采集卡、信号调理器等设备。 数据传输模块: 通过无线网络(如Wi-Fi、4G/5G)或有线网络(如以太网)将数据传输至中央控制系统。 中央控制系统: 这是系统的核心部分,负责对接收到的数据进行分析和处理。通过专业的分析软件,中央控制系统可以判断设备的运行状态,并在发现异常时发出预警信号。 预警模块: 主要包括声光报警器、短信通知、电子邮件通知等,用于在检测到异常情况时及时通知相关人员。 监控平台: 这是系统的用户界面,通过电脑或移动设备,用户可以实时查看设备的运行状态、历史数据、预警信息等。 三、系统优势 实时监测: 系统能够24小时不间断地监测设备的运行状态,确保在第一时间发现潜在问题。 预警功能: 当设备的温度或振动超过预设阈值时,系统会立即发出预警信号,提醒相关人员及时处理,避免故障进一步恶化。 数据分析: 中央控制系统可以对大量历史数据进行分析,帮助用户了解设备的运行趋势,预测可能的故障,提高设备的维护效率。 远程监控: 通过互联网,用户可以随时随地查看设备的运行状态,方便了设备的管理和维护。 降低成本: 通过及时发现并处理设备故障,系统可以减少设备的停机时间,降低维修成本,提高生产效率。 四、应用场景 一体式温振在线监测预警系统广泛应用于各类工业设备中,主要包括以下几个方面: 电力行业: 在电厂,电机、变压器等关键设备的运行状态直接关系到电力供应的稳定性。通过在线监测预警系统,可以实时监测这些设备的运行状态,确保电力系统的安全稳定运行。 石化行业: 石化设备在高温、高压下运行,设备故障可能带来严重的经济损失甚至安全事故。在线监测预警系统可以帮助石化企业实时掌握设备运行状况,提前预防故障。 制造行业: 制造业中的各种机械设备,如数控机床、压缩机等,都可以通过在线监测预警系统进行实时监控,提高生产效率,降低设备故障率。 交通运输: 铁路、地铁等交通运输系统中的关键设备也可以通过这一系统进行监测,确保运输安全。 五、案例分析 某电厂电机在线监测预警系统项目 项目背景:某电厂的发电机组由于长时间连续运行,经常出现设备故障,导致停机检修,影响发电效率。为了提高设备的运行稳定性,该电厂决定引入一体式温振在线监测预警系统。 项目实施:在电厂的关键设备上安装温度传感器和振动传感器,并通过无线网络将数据传输至中央控制系统。系统对数据进行实时分析,一旦发现温度或振动异常,立即发出预警信号。 项目效果:系统投入使用后,该电厂的设备故障率显著下降,停机检修时间减少了约30%,发电效率提高了20%。通过及时发现并处理设备问题,电厂的运行成本也大大降低。 六、未来发展方向 随着技术的不断进步,一体式温振在线监测预警系统也在不断发展。未来,系统将朝着更加智能化、集成化和便捷化的方向发展: 智能化: 通过引入人工智能和机器学习技术,系统可以更精准地分析设备运行数据,预测潜在故障,提高预警的准确性。 集成化: 将温度、振动等多个传感器集成在一个设备中,简化安装和维护,提高系统的可靠性。 便捷化: 通过开发更加用户友好的界面和移动应用程序,使用户能够更加方便地监控和管理设备。 结语 一体式温振在线监测预警系统在现代工业中具有重要的应用价值。通过实时监测和预警,系统可以帮助企业提高设备的运行稳定性,降低故障率,减少维修成本,最终提高生产效率。随着技术的不断进步,在线监测预警系统将迎来更加广阔的发展前景,为各行各业的安全稳定运行保驾护航。 --- ### 415. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着智能工厂的到来,工业物联网(IIoT)正在以惊人的速度扩展。预计到2030年,IIoT市场规模将达到3.3万亿美元,意味着将有数十亿个设备相互连接。为了确保这些设备,尤其是那些资源受限且有时依赖电池供电的设备能够高效运行,找到一种高效且可扩展的物联网解决方案至关重要。 MQTT-SN(针对传感器网络的MQTT)是一种专为非TCP/IP网络上的嵌入式设备设计的轻量级发布和订阅消息协议。它优化了MQTT版本3.1.1和MQTT 5.0的规范,特别适合低功耗、受限设备。在这篇文章中,我们将探讨MQTT-SN的节能和扩展能力,以及它如何支持工业自动化和数据采集的不断增长需求。 MQTT-SN:IIoT的低功耗解决方案 减少物联网设备的电力消耗不仅可以降低能源成本,还有许多其他好处。想象一下,一个遍布大型多地点生产设施的传感器网络。每个传感器或连接设备都需要电力,如果依赖频繁更换电池,不仅麻烦,而且限制了这些部署的可扩展性和灵活性。在这种情况下,降低电力消耗尤为重要。 通过最小化单个设备的能耗,可以降低电费,减少对频繁更换电池的依赖。这不仅减少了维护需求,提高了运营的正常运行时间,还显著节省了成本。具有延长电池寿命或能够从环境中获取能量(例如通过太阳能或风能)的节能设备,可以实现更广泛的传感器分布,提供更全面的工业过程视图。这种增加的监控可扩展性,使数据驱动的决策更加有效,并有助于优化运营。 此外,减少对一次性电池的依赖,可以促进更绿色的IIoT生态系统。结合MQTT-SN这样的低功耗协议和能量收集技术,我们可以迈向IIoT的可持续未来。 为什么选择MQTT-SN? 首先,MQTT-SN为效率而生。与MQTT相比,MQTT-SN具有更紧凑的设计。消息头被最小化,主题名称可以被短主题ID替换。数据大小的减少转化为更少的带宽消耗和对资源有限设备的更低处理需求。 为了进一步降低功耗,MQTT-SN引入了睡眠机制。设备可以有效地关闭,并在重新开启时接收排队的消息。这显著降低了功耗,延长了电池供电传感器的电池寿命。 与MQTT一样,MQTT-SN利用发布/订阅模型。设备将数据发布到特定主题,感兴趣的订阅者只接收相关信息。这种有针对性的方法最小化了不必要的数据传输,优化了网络带宽的使用。多个设备可以通过MQTT-SN网关与MQTT代理通信。 通过解决功耗效率和可扩展性的关键方面,MQTT-SN为IIoT环境中的强大和可靠通信铺平了道路。随着工业领域接受自动化和数据驱动的决策,MQTT-SN成为推动创新和确保未来智能工厂无缝运行的强大工具。 为了实现更多的节能和更低的数据开销,MQTT-SN增加了一种新的QoS模式,允许盲目发送并忘记消息传递。这意味着设备可以简单地唤醒并发送消息,而不必等待响应。 与MQTT不同,MQTT-SN不依赖于TCP/IP传输。相反,它旨在与底层网络服务无关。因此,任何支持节点和网关之间双向传输服务的网络都可以支持MQTT-SN。 MQTT-SN的限制 在选择MQTT-SN作为您的通信协议时,需要意识到一些限制。最大的一个问题是安全性。虽然可以使用任何加密技术,但目前MQTT-SN协议本身并没有内置安全性。不过,这个问题将在最新的标准修订中得到解决。 在复杂性方面,学习、实施和管理MQTT-SN可能比一些更简单的协议要困难。然而,使用专为MQTT-SN设计的兼容工具和库可以简化这个过程。虽然网关使设备和代理之间的通信成为可能,但确保不同MQTT-SN实现与现有基础设施的兼容性至关重要。选择符合最新MQTT-SN规范并提供明确迁移路径的解决方案可以帮助缓解兼容性问题。 MQTT-SN在IIoT中的用例 MQTT-SN在功耗效率、可扩展性和轻量级设计方面的优势使其成为各种IIoT应用的理想选择。以下是一些典型的用例: 无线传感器网络:在工业环境中,众多传感器监测温度、压力、振动等关键参数。MQTT-SN的低数据占用和睡眠功能非常适合这些电池供电的传感器,使它们能够在节省电池寿命的同时高效地传输数据。 智能建筑管理:建筑物越来越多地与传感器集成,用于监测能源消耗、占用和环境条件。MQTT-SN促进了这些传感器与中央控制系统之间的高效通信,实现了实时数据收集和优化的建筑运营。 预测性维护:通过持续监测设备健康数据(如振动、温度),MQTT-SN允许及早发现潜在问题,使预防性维护成为可能,减少了停机时间和相关成本。 工业资产跟踪:在大型设施内跟踪关键资产(如工具、机械或库存)的位置和状态至关重要。MQTT-SN处理来自低功耗RFID标签或GNSS跟踪器的数据,使其适用于此类应用。 远程监控和控制:在石油和天然气管道或偏远地区的环境监测站等应用中,MQTT-SN使与电池供电传感器的高效通信成为可能,允许实时数据获取和远程控制能力。 总结 MQTT-SN为IIoT应用提供了一个引人注目的解决方案。它的轻量级设计、高效的通信模型和对节能的强调,使其非常适合工业环境中普遍存在的资源受限设备。随着IIoT格局的不断发展,MQTT-SN有望在促进数据的可扩展交换中发挥关键作用,最终赋能下一代工业自动化。 --- ### 416. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智慧消防物联网整体方案通过结合传感器技术、网络通信和数据分析,实现了消防系统的智能化和自动化,提高了火灾检测和应急响应的效率和准确性,为建筑物和人员的安全提供了更可靠的保障。将传统的消防设施与互联网连接起来,实现消防信息的实时消防、消防互联互通,从而提高消防系统的标准化水平,提升消防安全管理效率。该方案主要包括以下内容几个方面: 1. 开采层 感知层是智慧消防物联网方案的基础,负责采集各种消防数据。常用的消防物联网传感器包括: 烟感梯度:检测火灾产生的烟雾。 温感吸收:检测火灾产生的热量。 烟雾/火焰传感器: 安装在建筑物各个关键区域,及时检测到烟雾或火焰的存在,并向系统发送警报信号。 温度/气体传感器: 监测建筑内外的温度和气体浓度变化,提前发现潜在的火灾风险。 一氧化碳吸附:检测火灾产生的有毒气体。 喷水灭火系统:检测火灾并启动喷水系统。 探测器火焰系统:检测火灾并启动探测器气体系统。 应急广播系统:在火灾发生时播放疏散广播。 视频监控系统: 结合摄像头和智能分析算法,实现对建筑物内外的实时监控,提供远程视觉监控和火灾识别功能。 2. 传输层 传输层负责将采集层采集到的数据传输到云端平台。常用的无线通信网络技术包括: NB-IoT:具有低功耗、广覆盖、亮点的特点,适用于大规模物联网应用。 LoRa:具有距离长、照射力强、亮度高的特点,适用于室外环境应用。 Wi-Fi:具有传输速率高、覆盖范围广的特点,适用于室内环境应用。 3.云端平台 云端平台负责消防数据的存储、分析和管理,并提供各种服务,例如: 实时消防信息监测:可以实时监控消防设施的状态,并及时发现火灾隐患。 火灾风险预警:可以根据消防数据分析火灾,并及时发布火灾预警。 应急调度指挥:在火灾发生时,可以为消防人员提供应急指挥调度服务。 管理:可以对消防设施进行统一管理,提高维护消防设施的保障消防效率。 无线传输技术: 利用物联网技术将传感器数据传输到云端或局域网,以确保数据的实时性和准确性。 云端存储与处理: 将传感器数据上传到云平台进行存储和分析,提供远程访问和数据管理功能。数据加密与备份: 对传感器数据进行加密传输和存储,确保数据的安全性和可靠性,同时定期进行数据备份,以应对突发情况。 4. 应用层 应用层为用户提供各种消防服务,例如: 手机APP:用户可以通过手机APP查看消防设施状态、接收火灾预警信息、查询火灾逃生营地等。 消防控制中心:消防控制中心可以监控局部所有消防设施的状态,并及时做出应急反应。 消防管理部门:管理部门可以利用云端平台对全市消防消防工作进行管理。 智能消防管理系统: 基于云端数据分析,实现对消防设备的远程监控、故障诊断和预警功能。 消防预警应用: 提供消防预警和紧急响应的移动应用程序,向用户发送实时警报和应急指导。 自动灭火系统: 结合传感器和智能控制技术,实现自动启动灭火装置并定向释放灭火剂。 智能逃生指引: 基于建筑结构和消防设备位置信息,提供灵活、个性化的逃生路线指引,帮助人员安全疏散。 5、系统优势 智慧消防物联网方案具有以下优势: 提升消防预警能力:可以有效提高火灾预警的准确性和及时性,减少火灾造成的损失。 提高消防营销效率:可以为消防人员提供实时信息支持,提高消防灭火的效率。 降低消防管理成本:可以减少消防巡检的人工成本,提高消防管理效率。 改善消防安全环境:可以有效降低火灾发生率,改善消防安全环境。 6、应用案例 智慧用电安全管理 电气火灾成因 智慧用电安全管理系统 智慧用电安全管理系统基于NB-IoT和LoRa等无线通讯技术,能够实时监测线缆温度、电流、漏电流和故障电弧等参数。系统通过分析这些数据,判断故障原因及其发展趋势,及时预警并处理潜在的电气火灾隐患,避免重大电气安全事故的发生。 应用场景 智慧烟感监测系统 传统烟感报警器的痛点 传统独立式烟雾报警器功能单一,仅能发出声光报警,无法解决火灾发生时无人应对的问题。同时,传统烟感报警器的质量参差不齐,存在电池没电等隐患,难以满足现代消防安全管理的需求。 智慧烟感监测系统 智慧烟感监测系统采用NB-IoT无线通讯技术,实现了超低功耗、长距离数据传输和实时监控。系统通过智能CPU控制,能够准确判断火灾产生的烟雾,并将报警信息实时发送至云端后台管理服务器,实现与智能云平台的报警联动。 智能气体监测系统 监测原理与功能 智能气体监测系统通过气体探测器连续监测室内燃气浓度,当检测到泄漏浓度达到设定值时,系统会发出光报警信号,并切断气源。系统还能够将报警信息同步至用户手机和APP,实现远程监控和管理。 应用场景 智能水压、水位监测系统 监测功能与优势 智能水压、水位监测系统通过NB-IoT和LoRa等无线通讯技术,实时监测室内消火栓状态、消火栓管道压力、自动喷淋系统水压和高位消防水箱水位等参数。系统能够动态、立体地反映消防水源的状态,为消防安全管理提供有力支持。 防火门监测系统 防火门的重要性 防火门是消防通道的重要组成部分,其正常开启和关闭关系到火灾发生时人员的疏散和救援。然而,防火门的状态往往难以实时监测和管理,存在一定的安全隐患。 防火门监测系统 防火门监测系统通过磁传感器实时监测防火门的开闭状态,并在防火门被异常开启或关闭超时时发出报警信号。系统能够通过电话、短信和邮件等方式通知相关人员,确保防火门始终处于正常状态。 应用场景 防火门监测系统适用于各类建筑物的消防通道和防火门。系统能够确保防火门的正常使用,提升消防安全管理水平,保障人员的安全疏散。 火眼监测系统 火灾自动识别与报警 火眼监测系统基于普通监控视频,通过人工智能和计算机视觉技术,实时识别火灾发生时的烟雾和火焰形态。在火灾初期,系统能够在1秒内发出报警信号,帮助快速扑灭火灾,避免灾情扩大。 应用场景 火眼监测系统适用于各类场所的消防监控。通过复用现有监控设备,系统能够实现高效的火灾监测和报警,有效提升消防应急响应能力。 未来展望 随着物联网技术的发展,智慧消防物联网方案将更加完善,为用户提供更加安全、可靠的消防服务。未来,智慧消防物联网方案与其他定制技术相结合,实现消防安全管理更加智能化。 --- ### 417. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智能停车物联网整体方案是一种利用物联网技术来优化和管理停车场的解决方案。它结合了传感器、网络通信、数据分析和应用软件,旨在提高停车场的利用率、减少拥堵、改善用户体验,并提供更高效的管理方式。以下是一个简单的智能停车物联网整体方案的介绍: 1. 传感器技术 车位检测传感器: 安装在每个停车位上,用于检测车辆的存在和停放情况。这些传感器可以是地磁传感器、摄像头或其他类型的传感器,能够实时监测车辆的停放状态。 采用各种物联网传感器来检测停车位的占用情况,例如: 地磁传感器:安装在地面,通过检测车辆产生的磁场变化来判断是否占用停车位。 探针传感器:通过发射探针脉冲来检测车辆的存在。 图像视频传感器:通过摄像头来分析图像信息,判断停车位是否被占用。 环境监测传感器: 监测停车场周围的环境因素,如空气质量、温度和湿度等。这些数据有助于提供更好的停车体验,并且可以帮助管理者更好地了解停车场周边环境状况。 2. 网络通信 物联网连接设备: 将传感器和停车场管理系统连接到互联网。可以使用无线技术如Wi-Fi、蓝牙或LPWAN(低功耗广域网)等来实现数据传输。 将传感器收集的数据通过无线通信网络传输到云端平台。常用的无线通信网络技术包括: NB-IoT:具有低功耗、广覆盖、亮点的特点,适用于大规模物联网应用。 LoRa:具有距离长、照射力强、亮度高的特点,适用于室外环境应用。 Wi-Fi:具有传输速率高、覆盖范围广的特点,适用于室内环境应用。 云平台: 将传感器数据上传到云端进行存储和分析。云端平台能够处理大量数据,并提供实时监控和分析功能,为停车场管理者提供决策支持。 云端平台负责对停车场数据进行存储、分析和管理,并提供各种服务,例如: 实时停车位信息查询:用户可以通过手机APP或其他方式查询停车场的实时停车位信息。 导航引导:用户可以通过手机APP或其他方式获取停车场内的导航信息,车辆引导至空闲的停车位。 滞纳费:用户通过手机APP或其他方式可以滞纳金。 停车场管理:停车场管理人员可以通过云端平台对停车场进行管理,例如查看停车场实时情况、生成停车数据报表等。 3. 数据分析与应用软件 停车场管理系统: 基于云端数据分析,实现停车场内车位的实时监测、车辆定位、停车指引等功能。管理系统可以通过手机App或网页进行访问,用户可以实时查看停车位的情况并预约车位。 智能导航应用: 提供驾驶员导航到可用停车位的功能。通过手机App或车载导航系统,用户可以实时了解停车场的拥堵情况和可用停车位的位置,从而更快地找到合适的停车位。 4. 用户体验和管理优化 移动支付: 支持手机支付或其他电子支付方式,方便用户停车缴费,减少停车排队时间。 实时数据监控: 管理人员可以通过管理系统实时监控停车场的使用情况,并根据需求进行调整和优化停车场布局。 数据分析与优化: 利用数据分析工具,对停车场的使用情况进行统计和分析,帮助管理者做出更好的决策,提高停车场的利用率和效益。 停车位预订:用户可以通过手机APP提前预订停车位。 车位地址:用户可以通过手机APP快速找到最近的空闲停车位。 无感支付:用户通过注册免密支付方式,驶入停车场后撤出停车费,系统会自动扣费 5、系统优势 智能停车物联网方案具有以下优势: 提高停车场效益:通过实时监测停车位信息,可以有效提高停车场资源的利用率。 缓解停车难现象:可以帮助产权人找到快速空闲停车位,减少停车时间,缓解城市停车现象难点。 降低停车场运营成本:可以减少停车场的人工管理成本,提高停车场运营效率。 改善城市交通环境:可以减少道路交通拥堵,改善城市交通环境。 应用案例 智能停车物联网方案已在众多城市落地应用,例如: 北京:在北京的一些大型停车场,已经安装了智能停车系统,可以为用户提供实时停车信息车位查询、导航引导、停车费等服务。 上海:上海正在积极推广智能停车物联网方案,预计到2022年,上海将建成1000个智能停车场。 杭州:杭州已建成一张覆盖全市的大型智能停车网,用户可以通过手机APP查询全市范围内的停车位信息。 未来展望 随着物联网技术的发展,智能停车物联网方案将更加完善,为用户提供更加便捷、高效的停车服务。未来,智能交通停车物联网方案与其他智能系统相结合,实现交通管理更加标准化。 智能停车物联网整体方案通过将传感器、网络通信和数据分析技术结合起来,为停车场提供了更智能、更高效的管理方式,既可以提升用户体验,又可以优化停车场的运营效率。 --- ### 418. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智能路灯的物联网方案是基于物联网技术实现对路灯进行智能监控和管理的解决方案。以下是一个智能路灯物联网方案的基本架构和关键要素: 1. 智能路灯节点 智能路灯节点是安装在路灯上的装置,通常包括LED灯具、传感器和通信模块。传感器可以包括光敏传感器、温度传感器、运动传感器等,用于感知环境变化和收集数据。通信模块可以采用无线技术,如Wi-Fi、蓝牙、LoRa等,或者有线技术,如Ethernet,用于与中心控制器或云平台进行数据交互。 2. 网络连接 智能路灯节点通过网络连接与中心控制器或云平台通信,实现远程监控和控制。网络连接可以是基于无线技术的,如Wi-Fi、蜂窝网络(3G/4G/5G)、LoRa等,也可以是基于有线技术的,如Ethernet。选择适合场景的网络连接方式可以根据需求和成本考量。 3. 中心控制器 中心控制器是智能路灯系统的核心,负责接收和处理来自各个路灯节点的数据,并根据预设的策略进行灯光控制和管理。中心控制器可以是一个专用的硬件设备,也可以是运行在云端的软件平台。通过中心控制器,用户可以实现对路灯的远程监控、故障诊断、灯光调节等功能。 4. 数据处理与分析 智能路灯系统通过对传感器数据的处理和分析,实现对路灯的智能化管理和优化。例如,根据光照强度和路况情况,自动调节灯光亮度;通过统计分析车流和行人流量,优化路灯亮灭时段。数据处理和分析可以在中心控制器或云平台上进行,以实现实时监控和智能决策。 5. 应用服务和用户界面 智能路灯系统通常提供应用服务和用户界面,方便用户进行系统管理和监控。用户可以通过手机App、Web界面或者专用软件平台,实现对路灯的远程控制、故障报警、能耗统计等功能。应用服务和用户界面的设计应简洁易用,满足用户的需求和操作习惯。 6. 安全和隐私保护 在智能路灯系统的设计和实施过程中,安全性和隐私保护是非常重要的考虑因素。系统需要采取有效的安全措施,保护通信数据的机密性和完整性,防止恶意攻击和数据泄露。同时,需要遵守相关的隐私法规和标准,保护用户的个人信息和隐私权益。 综上所述,智能路灯的物联网方案结合了硬件设备、网络连接、数据处理和应用服务等多个方面,通过智能化的照明管理和优化,提升了城市的能源利用效率和居民的生活质量。 --- ### 419. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 温湿度智能监控是物联网领域中的一个重要应用场景,它可以广泛应用于各种领域,包括家居、农业、医疗、工业等。下面是一个针对温湿度智能监控的物联网应用方案,旨在为普通读者解释清楚其工作原理和应用场景。 1. 应用背景 在许多领域中,监控环境的温度和湿度是至关重要的。例如,在农业中,农民需要监测温湿度以确保作物的健康生长;在医疗行业,药品和医疗设备需要在特定的温湿度条件下存储,以确保其有效性和安全性;在工业生产中,温湿度的变化可能影响生产效率和产品质量。 2. 解决方案概述 温湿度智能监控的物联网应用方案涉及传感器、物联网网关、云平台和用户界面等组件。传感器用于实时监测环境的温度和湿度,并将数据发送到物联网网关。物联网网关负责将传感器数据传输到云平台,云平台则负责存储、处理和分析数据,并向用户提供实时的监控和报警服务。用户可以通过手机应用或Web界面查看监控数据,并设置报警阈值以及接收报警通知。 3. 方案组成部分 传感器 温度传感器: 使用数字温度传感器,如DS18B20,可提供高精度的温度测量。 湿度传感器: 使用数字湿度传感器,如DHT22,可提供精确的湿度测量。 物联网网关 物联网网关是连接传感器和云平台的关键组件,它负责数据的传输和通信。 通信模块: 使用无线通信模块,如Wi-Fi、LoRa或NB-IoT,将传感器数据发送到云平台。 数据处理: 对传感器数据进行处理和封装,确保数据的可靠传输。 安全性: 采用加密技术确保数据在传输过程中的安全性。 云平台 云平台是数据存储、处理和分析的中心,它提供了实时监控、数据分析和报警服务。 数据存储: 使用数据库存储传感器数据,如MySQL、MongoDB等。 数据处理: 对传感器数据进行处理和分析,生成实时监控图表和报表。 报警服务: 设置报警阈值,当环境温湿度超出设定范围时,向用户发送报警通知。 用户界面 用户界面提供了监控数据的可视化和用户交互功能,用户可以通过手机应用或Web界面随时查看监控数据并进行操作。 实时监控: 显示实时的温湿度数据,以图表或数字形式呈现。 报警设置: 用户可以设置温湿度的报警阈值,并选择接收报警通知的方式,如短信、邮件或推送通知。 历史数据: 提供历史温湿度数据的查询和分析功能,用户可以查看过去一段时间内的数据趋势。 4. 应用场景 家居环境监控: 监测室内温湿度,提高生活舒适度,预防霉菌和细菌滋生。 农业温室监控: 实时监测温湿度,帮助农民调整温室环境,促进植物生长。 医疗设备监控: 监测医疗设备的存储条件,确保药品和器械的安全有效。 工业生产监控: 监测生产环境的温湿度,提高生产效率,确保产品质量。 5. 结论 温湿度智能监控的物联网应用方案可以在各种领域中发挥重要作用,帮助用户实时监测环境条件,提高生产效率和生活质量。通过传感器、物联网网关、云平台和用户界面的组合,用户可以实现对温湿度的远程监控和管理,从而更好地应对各种环境变化和挑战。 --- ### 420. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 GNSS(全球导航卫星系统)形变监测预警系统是一种利用卫星定位技术来监测地表形变并及时预警的系统。这种系统可以广泛应用于地质灾害监测、建筑结构变形监测、水文地质监测等领域。下面将介绍一个普适型的GNSS形变监测预警系统解决方案,以便非专业人士也能理解。 1. 系统概述 普适型GNSS形变监测预警系统是一种利用全球导航卫星系统进行实时监测和预警地表形变的系统。它通过接收卫星信号来获取目标区域的位置信息,并利用这些位置信息来监测地表形变的变化,一旦发现异常情况,系统将及时发出预警信号。 2. 技术原理 该系统主要基于以下技术原理: GNSS技术:利用卫星信号来获取目标区域的位置信息,包括经度、纬度和海拔高度等数据。 形变监测算法:通过对比不同时间点的位置信息,计算目标区域的形变量,如位移、速度和加速度等。 预警机制:设定合适的形变阈值,一旦监测到形变量超过阈值,则触发预警机制,通知相关人员进行应急处理。 3. 系统组成 普适型GNSS形变监测预警系统通常由以下几个组成部分构成: GNSS接收设备:用于接收卫星信号,并将位置信息传输给监测系统。 监测系统:包括数据处理模块和预警模块,用于处理接收到的位置信息、计算形变量并进行预警。 数据传输网络:将监测系统获取的数据传输到数据中心或相关用户终端。 用户终端:用于接收预警信息,并提供用户界面供用户查看监测数据和处理预警信息。 4. 应用场景 普适型GNSS形变监测预警系统可以广泛应用于以下领域: 地质灾害监测:如地震、滑坡、地面沉降等灾害的监测和预警。 建筑结构监测:对建筑物、桥梁等工程结构的形变进行实时监测,以确保其安全性。 水文地质监测:对地下水位、地表沉降等水文地质现象进行监测和预警,以保护地下水资源和土地利用安全。 5. 优势与挑战 优势:实时监测、高精度定位、普适性强、预警及时。 挑战:数据处理复杂、设备成本较高、对环境要求严格。 6. 结语 普适型GNSS形变监测预警系统是一种具有重要意义的监测预警工具,可以帮助我们及时发现地表形变异常情况,保护人们的生命财产安全。随着技术的不断发展和完善,相信这种系统将在各个领域发挥越来越重要的作用。 --- ### 421. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智慧图书馆整体方案 1. 概述 智慧图书馆是利用先进的物联网技术、人工智能和大数据分析等手段,将传统图书馆转变为智能化、数字化的信息服务中心。它不仅提供传统的图书借阅服务,还拓展了多种数字资源的获取渠道,提升了用户体验和服务效率。 2. 方案组成 产品介绍 智能图书柜: 提供自助借阅、归还功能,实现24小时无人值守服务。 智能检索系统: 基于人工智能技术,实现图书检索、推荐等智能化功能。 数字资源平台: 提供电子书籍、期刊、论文等多种数字资源,支持在线阅读和下载。 产品特点 智能化服务: 用户可以通过手机App或触摸屏等界面实现自助借阅、归还、图书检索等功能。 多样化资源: 不仅提供纸质书籍,还整合了丰富的数字资源,满足用户多样化的阅读需求。 3. 工作原理 用户通过智能终端(如手机App或触摸屏)选择借阅图书或检索资料,系统根据用户需求进行推荐或检索,并提供相关资源的位置信息。用户自行取书或阅读电子资源,归还图书时将书籍放入智能图书柜,系统自动更新借阅记录。 4. 方案优势 提升服务效率: 自助借还、智能检索等功能提高了图书馆服务效率,减少了用户等待时间。 丰富资源获取: 不仅提供纸质图书,还整合了大量数字资源,拓展了用户获取信息的渠道。 智能化管理: 借助大数据分析,图书馆可以更好地了解用户阅读偏好,优化资源配置和服务策略。 5. 应用场景 高校图书馆: 为师生提供丰富的学术资源和便捷的借阅服务。 社区图书馆: 为社区居民提供便捷的图书借阅服务,促进阅读文化的普及。 6. 典型案例 某大学图书馆智能化改造: 引入智能图书柜、数字资源平台等设备,提升了图书馆的服务水平和管理效率。 7. 发展趋势 智能化升级: 随着技术的发展,智慧图书馆将更加智能化,引入更多先进技术提升服务水平。 用户体验优化: 不断改进界面设计、服务流程,提升用户体验和满意度。 8. 结论 智慧图书馆整体方案通过引入智能设备、数字资源平台等手段,将传统图书馆转变为数字化、智能化的信息服务中心,为用户提供更便捷、丰富的阅读体验,同时提升了图书馆的管理效率和服务水平。 --- ### 422. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在工业物联网(IIoT)的动态格局中,"连接孪生体"(Connected Twins)的概念作为连接物理世界和数字世界的强大工具而出现。"连接孪生体"通常指的是在IIoT和数字孪生技术背景下的概念或方法。在本文中,我们将探讨数字孪生体是什么,它们与数字孪生体的区别,以及开源MQTT协议如何发挥关键作用,使这两项技术得以实现。 什么是连接孪生体?数字孪生体是物理对象、过程、系统或实体的虚拟表示或数字复制品。它利用实时数据、仿真和建模技术来模拟其物理对应物的行为、特征和性能。连接孪生体通过强调网络或生态系统内多个数字孪生体的连接性和集成性,扩展了数字孪生体的概念。与为单个对象或系统使用单独的数字孪生体不同,使用连接孪生体可以实现多个数字孪生体的互联和协作,允许它们交换数据、互动并以协调的方式运行。与数字孪生体一样,连接孪生体也与其代表的物理对象集成。连接孪生体之间的数据连接性、同步性和丰富性可以通过IIoT技术、通信协议、数据共享平台和基于云的基础设施来促进。连接孪生体根据现实世界数据不断更新。 连接孪生体的一个例子是制造用例,其中生产中使用的机器人。每个机器人过程可以是一个数字孪生体,它们相互连接以创建连接孪生体。这些孪生体与其物理对应物互动,有助于实时参数调整、生产仿真和预测性维护。 连接孪生体的好处 可见性和增强的协作:连接孪生体使产品和过程完全可见。不同的实体,如设备、机器、过程和系统能够轻松协作、共享信息并共同实现过程目标。 实时洞察:通过连接数字孪生体并创建连接孪生体,组织可以获得有关互联资产和系统的整体性能、互动和依赖性的实时洞察。它们还可以促进孪生体与其物理对应物之间的闭环集成。 预测性维护:连接孪生体可以通过分析多个来源的数据、识别潜在问题或异常,并推荐主动维护行动,来支持预测性维护策略。 优化和自动化:连接孪生体的集成允许优化流程、资源分配和决策,以及跨互联系统的任务和工作流程自动化。 可扩展性和灵活性:连接孪生体通过动态调整数字孪生体之间的配置、参数和互动,提供适应变化环境、需求和场景的可扩展性和灵活性。 改进的决策支持:连接孪生体的互联特性使组织能够做出明智的决策,进行情景分析,并在基于综合数据的行业用例上模拟“如果”情景,特别是通过集成的数字孪生体。 区分连接孪生体和数字孪生体虽然数字孪生体和连接孪生体在很多方面相似,但它们在某些方面也有所不同。以下是其中的一些区别: 方面数字孪生体连接孪生体定义单个物理对象、系统、过程或实体的虚拟表示或仿真。网络或生态系统内多个数字孪生体的互联和集成。范围使用实时数据、传感器和建模技术复制物理对应物的行为、属性和互动。代表一个网络化环境,其中多个数字孪生体协作、共享数据并相互互动以实现共同目标。连接性和互动独立运行,专注于模拟和仿真特定对象或系统的行为。强调多个数字孪生体之间的连接性和互动。使互联的数字孪生体之间能够通信、共享数据和协作。功能和用例用于监测、分析、仿真、优化和预测性维护单个对象或系统。通过使多个实体之间的协作、协调和集成成为可能,扩展了数字孪生体的功能。支持复杂的用例,如供应链优化、智能城市管理、工业自动化等。可扩展性和灵活性可以部署在不同的规模上,从单个对象到整个系统,但其可扩展性限于单个孪生体的范围。通过允许在网络化环境中集成和协调多个数字孪生体,提供可扩展性和灵活性。 总结来说,虽然数字孪生体专注于模拟和仿真单个对象或系统,但连接孪生体强调在网络化生态系统内实现更广泛的目标和成果,通过连接性、数据共享和协调行动,实现多个数字孪生体的集成和协作。 在连接孪生体和数字孪生体中使用MQTT的好处MQTT是一种轻量级、高效的通信协议,专为低带宽、高延迟或不可靠的网络设计。它确保了设备之间的可靠通信,非常适合IIoT应用。在连接孪生体和数字孪生体的背景下使用MQTT可以提供多种好处,增强它们的能力: 数据连接性:MQTT是一种为受限环境设计的轻量级和高效的消息协议,非常适合作为数字孪生体、物联网设备和后端系统之间数据采集和连接的关键使能器。它最小化了带宽使用并减少了延迟,确保即使在资源受限的环境中也能快速且可靠地传输数据。 单一真实来源:MQTT为数字孪生体应用提供了集中的通信渠道,实现了实时监控,具有可扩展性和可靠性的数据。实时性确保了数字孪生体是物理世界的最新表示,具有最新版本的数据值。可扩展性确保了来自不同地点的各种制造机器、过程和应用程序的数据能够以可扩展的方式馈送给连接孪生体。可扩展性还使得在连接生态系统内大量数字孪生体之间的无缝集成和通信成为可能,适应动态变化和扩展需求。MQTT的可靠消息传递机制,包括确认、消息排队和持久会话,确保了数据完整性和对网络中断或故障的弹性。它支持如遗嘱和遗言(LWT)消息等功能,以处理意外的客户端断开连接并维护系统稳定性。最后,它支持服务质量(QoS)级别,以确保可靠和及时的消息传递,这对于需要即时数据同步和响应能力的数字孪生体应用至关重要。 从反应式到预测式:通过利用MQTT,工业公司可以轻松地将OT机器、应用程序和系统数据整合到一个位置,通过它们可以从事后数据方法转变为预测性维护、高级分析和运营优化等主动方法。这使它们能够实现数字化转型,并实现工业4.0用例,通过这些用例它们可以降低成本、提高盈利能力并提高运营效率。 使用MQTT的连接孪生体和数字孪生体数据连接性让我们考虑一个使用MQTT的连接孪生体数据连接性的例子,背景是一个智能建筑管理系统。在这个场景中,我们将有多个数字孪生体代表建筑的不同组件,如HVAC系统、照明系统、能源计量器和占用传感器。这些数字孪生体将使用MQTT进行通信和交换数据,以实现建筑运营的协调控制和优化。 数字孪生体设置这里的各种数字孪生体设置包括: HVAC数字孪生体,根据温度、湿度和占用数据监控和控制供暖、通风和空调系统。 照明数字孪生体,控制照明系统,根据占用和环境光线水平调整亮度和调度。 能源计量器数字孪生体,监控能源消耗和来自可再生能源的生产,为能源管理提供实时数据。 占用传感器数字孪生体,检测建筑不同区域的占用水平,触发如调整HVAC设置和开关灯光等动作。 MQTT通信设置MQTT设置包括: MQTT代理:部署一个MQTT代理作为数字孪生体和其他系统之间通信的中央消息中心。 MQTT客户端:为每个数字孪生体(HVAC、照明、能源计量器、占用传感器)配置MQTT客户端,以将数据发布到特定的MQTT主题并订阅相关主题以接收命令和更新。 数据连接流这里是数据连接流: HVAC数字孪生体订阅与占用和温度相关的MQTT主题,来自占用传感器,并相应调整HVAC设置。 照明数字孪生体订阅与占用和光线强度相关的MQTT主题,来自占用传感器,并调整照明水平和时间表。 能源计量器数字孪生体订阅与能源消耗和生产相关的MQTT主题,以优化能源使用并监控可再生能源贡献。 占用传感器数字孪生体通过MQTT主题接收其他数字孪生体的命令,并根据占用变化和环境条件触发动作。 MQTT数据连接的好处以下是MQTT数据 连接的好处: 实时数据交换:MQTT促进了连接孪生体之间的实时数据交换,使基于变化条件的及时行动和调整成为可能。 可扩展性:MQTT支持可扩展的通信,允许添加新的数字孪生体和传感器而不会显著增加开销。 可靠性:MQTT的可靠消息传递确保了数据完整性和系统弹性,即使在不可靠的网络条件下也是如此。 灵活性和互操作性:MQTT的轻量级协议和广泛采用促进了灵活性和互操作性,使与其他物联网设备、云服务和分析平台的无缝集成成为可能。 下一个部分的例子说明了如何使用MQTT数据连接使智能建筑环境中的连接孪生体进行通信、交换数据并协作,以实现高效的建筑管理和优化。 使用MQTT的连接孪生体实时监控让我们考虑一个使用MQTT的连接孪生体实时监控的例子,背景是一个智能制造环境。在这个场景中,我们将有多个数字孪生体代表制造设施内的不同机器、生产线、传感器和控制系统。这些数字孪生体将使用MQTT交换实时数据,以实现对制造过程的持续监控、分析和优化。 数字孪生体设置这里的各种数字孪生体设置包括: 机器数字孪生体:代表单个制造机器,如CNC机器、3D打印机、机械臂等。每个机器的数字孪生体监控其运行参数、状态和性能指标。 生产线数字孪生体:代表生产线或装配流程,监控吞吐量、效率和质量指标。 传感器数字孪生体:代表部署在制造现场的各种传感器,包括温度传感器、压力传感器、振动传感器等。 控制系统数字孪生体:代表控制系统,用于调节机器运行、生产计划和质量控制。 MQTT通信设置MQTT设置包括: MQTT代理:部署一个MQTT代理作为数字孪生体、传感器、控制系统和监控应用程序之间通信的中央消息中心。 MQTT客户端:为每个数字孪生体(机器、生产线、传感器、控制系统)配置MQTT客户端,以将实时数据发布到特定的MQTT主题并订阅相关主题以接收命令和更新。 实时监控流实时监控流包括: 机器数字孪生体将实时数据(如运行参数(速度、温度、压力)、生产产出和维护警报)发布到MQTT主题,如"manufacturing/machines/machine1/data"、"manufacturing/machines/machine2/data"等。 生产线数字孪生体将吞吐量指标、质量指标和生产计划发布到MQTT主题,如"manufacturing/production_lines/line1/data"、"manufacturing/production_lines/line2/data"等。 传感器数字孪生体将传感器读数(温度、压力、振动)发布到MQTT主题,如"manufacturing/sensors/temperature/data"、"manufacturing/sensors/pressure/data"、"manufacturing/sensors/vibration/data"。 控制系统数字孪生体订阅MQTT主题以接收与生产计划、机器设置和质量控制参数相关的命令和更新。 实时监控和分析实时监控和分析包括: 监控应用程序:开发监控应用程序,订阅相关MQTT主题以接收来自连接孪生体、传感器和控制系统的实时数据。 数据分析和可视化:分析来自数字孪生体的实时数据流,以检测异常、识别趋势、预测故障和优化制造过程。使用仪表板、图表和报告可视化数据,以获得实时洞察和决策。 使用MQTT进行实时监控的好处以下是使用MQTT进行实时监控的好处: 及时的数据更新:MQTT的发布-订阅模型确保了实时数据更新的及时交付,使持续监控和对变化条件的快速响应成为可能。 可扩展性:MQTT支持可扩展的通信,允许添加新的数字孪生体、传感器和监控应用程序而不会显著增加开销。 可靠性:MQTT的可靠消息传递确保了数据完整性和系统弹性,这对于制造环境中的实时监控和控制至关重要。 互操作性:MQTT的轻量级协议和广泛采用促进了互操作性,为全面实时监控提供了便利。 这展示了MQTT如何在智能制造环境中的连接孪生体中启用实时监控,使组织能够监控、分析和优化制造过程,以提高效率、生产力和质量控制。 使用MQTT的连接孪生体预测性维护让我们考虑一个使用MQTT的连接孪生体预测性维护的例子,背景是一个能源发电设施内的工业机械车队,如涡轮机、泵和压缩机。预测性维护旨在通过分析来自传感器和数字孪生体的实时数据,在设备故障发生之前识别潜在的设备故障。MQTT促进了实施预测性维护策略所需的通信和数据交换。以下是它的工作原理: 数字孪生体设置数字孪生体设置包括: 涡轮机数字孪生体:代表单个涡轮机,监控振动水平、温度、压力和运行状态等参数。 泵数字孪生体:代表泵,监控流量、电机温度和效率等参数。 压缩机数字孪生体:代表压缩机,监控压力、温度和能耗等参数。 MQTT通信设置MQTT通信设置包括: MQTT代理:部署一个MQTT代理作为数字孪生体、传感器和预测性维护系统之间通信的中央消息中心。 MQTT客户端:为每个数字孪生体配置MQTT客户端,以将实时传感器数据发布到MQTT主题,如"equipment/turbines/turbine1/data"、"equipment/pumps/pump2/data"、"equipment/compressors/compressor3/data"。 数据收集和分析数据收集和分析包括: 传感器数据收集:附着在涡轮机、泵和压缩机上的传感器收集有关运行参数的实时数据。 数字孪生体数据发布:数字孪生体定期将传感器数据发布到MQTT主题,包括振动水平、温度、压力、流量和能耗。 数据分析引擎:实现一个数据分析引擎,该引擎订阅MQTT主题,收集历史数据,并执行预测性分析算法以检测模式、异常和潜在设备故障。 预测性维护行动预测性维护行动包括: 异常检测:数据分析引擎使用机器学习算法分析历史和实时数据,识别异常模式或偏离正常行为的偏差,并标记潜在的设备故障。 故障预测:基于异常检测结果,系统预测设备故障的可能性在一定时间框架内,如涡轮机中的轴承故障或泵中的电机故障。 维护警报:当预测性维护系统检测到设备故障的高概率时,它通过MQTT主题如"maintenance/alerts/turbine1"、"maintenance/alerts/pump2"、"maintenance/alerts/compressor3"生成维护警报和通知。 维护响应和优化维护响应和优化包括: 维护团队通知:维护团队接收到维护警报,然后可以安排主动维护活动,如在故障发生之前检查、修理或更换组件。 维护历史记录:系统记录维护行动,包括修理、更换和检查,以跟踪设备健康、性能和维护历史。 性能优化:预测性维护洞察力被用来优化设备性能,减少停机时间,延长设备寿命,并提高整体运营效率。 使用MQTT进行预测性维护的好处使用MQTT进行预测性维护的好处包括: 实时数据交换:MQTT使数字孪生体、传感器和预测性维护系统之间的实时数据交换成为可能,有助于及时检测设备异常和故障。 可扩展性:MQTT的发布-订阅模型支持可扩展的通信,允许添加新的数字孪生体、传感器和分析引擎而不会破坏现有系统。 可靠性:MQTT的可靠消息传递确保了数据完整性和系统弹性,这对于维护准确的预测性维护预测和警报至关重要。 互操作性:MQTT的轻量级协议促进了互操作性,使与不同设备、传感器和维护系统的无缝集成成为可能,为全面的预测性维护解决方案提供了便利。 这展示了如何在工业设施内的连接孪生体中使用MQTT实施预测性维护,利用实时数据分析和主动维护策略来优化设备性能和可靠性。 结论由MQTT驱动的连接孪生体使各行业能够做出明智的决策、优化流程并提高效率。随着IIoT的不断发展,理解和利用连接孪生体的潜力对于保持数字时代的竞争性至关重要。无论是风力涡轮机、制造线还是智能建筑,连接孪生体都承载着改变我们与物理世界互动方式的承诺。 --- ### 423. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在迅速演变的工业4.0格局中,数字化转型已成为寻求在互联技术时代和数据驱动洞察力中蓬勃发展的企业成功的基石。工业物联网(IIoT)位于这场转型的核心,赋予行业革命化运营、提高效率和开辟创新新途径的能力。 然而,在工业领域,特别是在IIoT领域,开展数字化转型之旅需要战略性的方法和周密的规划。从明确目标到应对技术整合和数据管理的复杂性,过程中的每一步都需要仔细考虑和专家指导。 在本高级指南中,我们将深入探讨推动工业4.0和物联网成功数字化转型项目的关键策略和最佳实践。无论您是工业领域的资深专业人士还是IIoT领域的新手,本文将为您提供所需的知识和洞见,以应对挑战并抓住工业4.0带来的机遇。 让我们探索利用IIoT力量推动组织在数字创新时代向前发展的关键步骤。从评估当前能力到培养持续改进的文化,让我们踏上一条通往可持续增长和数字时代竞争优势的转型之旅。 在工业领域,尤其是在物联网(IIoT)的背景下,推动成功的数字化转型项目涉及几个关键步骤。以下是结构化的方法。 明确目标和范围在任何数字化转型项目中,包括涉及IIoT和物联网的项目,明确目标和范围是一个至关重要的初始步骤。以下是如何有效执行的一些关键建议: 理解业务目标和挑战:从深入了解组织的总体业务目标和面临的具体挑战开始。确定痛点以及数字化转型可以解决这些挑战并有助于实现战略目标的领域。 参与利益相关者:让组织中的高管、部门负责人、IT专业人员和最终用户等关键利益相关者参与目标设定过程。这是让每个人都参与数字化转型项目的关键。从利益相关者那里收集关于他们的痛点、优先事项和对数字化转型计划的期望结果的见解。 设定SMART目标:确保目标具体、可衡量、可实现、相关且有时间限制(SMART)。具体:明确定义您希望通过数字化转型项目实现的目标。可衡量:建立用于跟踪进展和评估成功的指标或关键绩效指标(KPI)。可实现:在资源、技术和时间表的限制内设定现实和可行的目标。相关:将目标与整体业务战略和优先事项保持一致。时间限制:为实现目标定义明确的时间线和截止日期。 优先级目标:认识到并非所有目标可能同样重要或紧急。根据其对业务成果和组织战略优先事项的潜在影响,优先考虑目标。您可以将目标分为以下类别: 必须有 有则更好 稍后再探索 在确定优先级时,考虑诸如投资回报率(ROI)、成本节约、收入增长、客户满意度和竞争优势等因素。 定义范围和责任:明确界定数字化转型项目的范围,包括将涉及的系统、流程、部门和利益相关者。确定项目的界限,以防止范围蔓延并确保集中执行。确定项目中每个利益相关者的责任。在定义范围时考虑可扩展性和灵活性,以适应未来的增长和业务需求的变化。 记录目标和范围:在正式的项目章程或文件中记录数字化转型项目的目标和范围。向所有利益相关者明确沟通目标和范围,以确保一致性和共同理解。使用图表、流程图或思维导图等视觉辅助工具有效说明目标和范围。 迭代和完善:认识到随着项目的进展和新见解的出现,目标和范围可能会发展。通过定期审查和根据反馈、吸取的教训以及业务需求的变化来完善目标和范围,培养持续改进的文化。 通过遵循上述步骤,组织可以有效地为其数字化转型项目定义明确的目标和范围,为成功执行和具体的业务成果奠定基础。 评估当前状态和识别差距评估当前状态和识别差距是数字化转型项目中的关键阶段。您可以从收集有关组织当前技术基础设施、流程和能力的的数据和信息开始。这可能包括系统、应用程序、硬件、软件、网络、网络安全要求和数据源。此外,通过访谈关键利益相关者——包括高管、部门负责人、IT人员和最终用户——以获得对现有工作流程、痛点和改进领域的洞察。为了帮助您,您可以采用结构化的方法,包括以下步骤: 执行SWOT分析:进行SWOT(优势、劣势、机会、威胁)分析,以评估组织在数字化转型目标方面的当前优势和劣势。识别利用技术解决劣势和利用优势的机会,同时考虑潜在的威胁和挑战。 评估技术格局:评估组织的当前技术格局,包括现有的IT系统、应用程序和基础设施。评估现有技术在满足数字化转型计划要求方面的兼容性、可扩展性和性能。识别可能对转型工作构成障碍的任何遗留系统或过时技术。 评估流程效率和有效性:评估现有的业务流程和工作流程,以识别低效、瓶颈和优化领域。分析信息、数据和任务在部门和系统间的流动,以识别自动化、简化和整合的机会。 审查数据管理实践:评估组织的数据管理实践,包括数据收集、存储、处理和分析。评估跨系统和部门的数据质量、一致性和可访问性。识别可能妨碍有效决策和洞察力生成的任何数据孤岛、冗余数据源或数据治理问题。 考虑安全性和合规性:评估组织的网络安全姿态和数据隐私实践,以识别潜在的漏洞和合规性差距。评估现有安全措施在保护敏感数据和防御网络威胁方面的有效性。确保遵守相关法规和标准,如GDPR、HIPAA或行业特定要求。 必要时聘请外部专家:考虑聘请外部顾问、技术合作伙伴或行业专家提供公正的评估和专业专长。利用他们的洞察力和经验来识别盲点、验证发现,并获得解决差距和挑战的建议。 记录发现和差距分析:记录评估阶段的发现,包括优势、劣势、机会和威胁,以及具体的缺口和改进领域。使用矩阵、图表或图表等视觉辅助工具有效地说明差距分析,并促进与利益相关者的沟通。 结论通过彻底评估当前状态并识别差距,组织可以获得有关需要关注和投资的领域的宝贵见解,因为他们开始数字化转型之旅。这为制定针对性和有效的转型路线图奠定了基础,该路线图解决了关键优先事项并提供了可衡量的商业价值。 --- ### 424. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 电网增强技术:现代化能源基础设施的挑战与机遇 许多国家今天面临着现代化能源基础设施的挑战,以尽可能可靠和经济地满足不断变化的能源需求。实现这一目标的一种有希望的方法是通过电网增强技术(GETs)。根据美国能源部的报告,2016年美国主要电力公用事业系统运营商的实时拥堵成本总额为48亿美元。2022年的拥堵成本估计为208亿美元。能源公用事业提供商的拥堵成本指的是在电网的某个部分,电力需求超过可用传输能力时产生的额外费用。这一趋势凸显了在不需要巨大基础设施投资的情况下优化成本的需求。 什么是电网增强技术(GETs)? 简而言之,GETs最大化利用现有系统传输电力。增加这些技术有助于电力传输系统继续连接到清洁、可再生能源,如太阳能和风能,以实现电网脱碳的同时满足其能源需求。因为它们可以快速增强现有电网基础设施,也因此节省资金,并避免了建设新输电线路的复杂性。 GETs可以简要分为以下几类: 动态线路额定(DLR):根据实时和预测的天气状况适当更新现有输电线路的热极限。 先进的电力流控制:优化电力流以减少拥堵和提高效率。 拓扑优化:改善电网的物理布局和连接性。 能量储存集成:将储能解决方案集成到电网中,提高灵活性和可靠性。 为了启用这些技术,电网运营商和决策者经常依赖传感器、智能表和监测设备收集实时数据,帮助他们做出明智的决策并快速响应电网变化。 动态线路额定(DLR):电网现代化的关键 动态线路额定(DLR)定义为根据实时和预测的天气状况适当更新现有输电线路的热极限的过程。输电线路的热极限指的是输电线路在生成的热量超过安全水平之前可以承载的最大电流量。通常,这些方案建立了新的极限,安全地允许更多的能量通过现有基础设施传输。 要理解DLR,我们需要了解静态线路额定(SLR)和环境调整线路额定(AAR)。 静态线路额定和环境调整线路额定 输电线路设计为导体在定义的最高温度(即其“设计温度”)下运行。在现实世界中,线路温度由电流损失(由于导电电流)和阳光增加。输电线路通过自然对流、风和辐射冷却。 由于天气条件全天候变化,并且一年四季都可能有很大的不同,线路的“实际”额定可能与设计值大相径庭。 静态线路额定(SLR)是在设计温度下输电线路的额定。这个值直接影响了可以从输电线路传输的电能量。 环境调整线路额定(AAR)考虑了天气条件的变化,允许在不同的环境条件下调整线路的额定。 DLR与SLR和AAR的不同之处 电力输电线路可以被视为特殊的高速公路,用于输送电力而不是汽车,而这条高速公路的容量可以根据天气条件的变化而增减。DLR赋予了电网运营商使用随着温度降低和强风带来的输电线路更高容量的能力。 DLR实施的挑战 为了成功实施DLR,电网运营商必须克服以下挑战: 通信挑战:监测输电线路的温度和天气的传感器可能位于偏远位置,不易访问。运营商需要考虑数据传输容量和延迟水平。 能源基础设施的安全挑战:能源基础设施的安全至关重要,因为它可能成为恶意行为者的目标。因此,全面的安全措施至关重要。 MQTT物联网平台:DLR的关键使能器 MQTT物联网平台为DLR提供了一个理想的解决方案。MQTT是一个轻量级的发布-订阅协议,专门为克服偏远环境连接挑战而创建。它还提供了一种简单的方法连接到现有基础设施,创建标准数据层,并推送数据,使其可用于任何云或企业系统。 使用MQTT进行DLR的一些优势包括: 安全性:所有MQTT通信通过TLS等进行加密,支持客户端认证和授权。 可靠性:支持MQTT的三个服务质量(QoS)级别,确保电网控制中心从整个网络中可靠地获取数据。 可扩展性:可以根据需要连接从几个设备到数百万个设备,同时保持高吞吐量和低延迟。 可用性:提供关键的高可用性,以最小化运营停机时间。 扩展框架:可以连接到各种数据库、流技术、分析工具和其他IT系统。 结论 MQTT物联网平台对于增强能源网格运营至关重要,特别是通过实时和优质数据在电网增强技术(GETs)中启用动态线路额定(DLR)。这不仅有助于提高电网的效率和可靠性,而且为公用事业提供商提供了一种经济有效的方式来升级他们的输电基础设施,而无需为节省成本而减少能源。 呼吁行动 电网运营商和决策者现在有机会通过采用DLR和MQTT物联网平台来现代化他们的能源基础设施。请继续关注我们,我们将推出另一篇博客,讨论使用MQTT物联网平台启用高级电力流控制。同时,探索MQTT物联网平台,了解如何使用它来开发、测试、部署和扩展生产物联网用例,而无需大量投资。 --- ### 425. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、概述: 智慧井盖是一种集成了多项先进技术的智能化并盖管理系统,旨在提高城市基础设施的安全性和管理效率。通过安装传感器、通信模块等设备,实现对井盖状态的实时监测、预警和远程控制,为城市安全管理提供全面支持。 二、方案功能 远程监测 位置追踪 翻动检测 防倾斜和气体检测 三、工作原理: 智慧井盖主要依靠传感器技术、通信技术和云计算技术实现。传感器监测井盖状态,通信模块将数据传输到云计算平台进行处理和分析,实现对井盖状态的实时监控和预警。 四、方案优势: 提高安全性:及时监测井盖状态,预防盗窃、损坏等安全隐患。 增加管理效率:远程监测和控制,减少人力物力成本,提高管理效率。 多功能检测:除了基本功能外,还可进行气体检测,保障工作环境安全。 五、应用场景: 智慧井盖适用于城市排水井盖、电缆井盖、通信井盖等各种基础设施的井差管理,在城市道路、公园、广场等公共场所广泛应用。 六、典型案例: 某城市在市区道路上部署了智慧井盖传感器,实现了对井盖状态的实时监测和远程控制,提高了城市基础设施的安全性和管理效率。 七、发展趋势: 随着物联网、大数据、人工智能等技术的发展,智慧井盖解决方案将不断升级和完善,实现更加智能化的管理和控制。 八、结论: 智慧井盖作为城市安全管理的重要组成部分,通过集成多种先进技术,为城市的安全和发展提供全面支持,应积极推动其发展和应用。 --- ### 426. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着城市发展和人们生活水平的提高,智慧公厕已经成为城市基础设施建设的重要组成部分。传统的公厕管理存在着很多问题,例如无法及时了解厕所内部情况、人员流量管理不到位、环境卫生难以保障等。为了解决这些问题,推出了智慧公厕环境监测解决方案,旨在利用先进的科技手段提升公厕管理效率,改善厕所环境质量,提升城市形象。当公厕内的有害气体含量超标时,系统能够自动联动风机进行通风除臭,确保厕内环境卫生,改善公厕内的环境质量。 此外有些智慧厕所还有生命监测功能,当发现有人身体不适、超时驻留,系统会发出告警信息,及时关注如厕者安全情况。 一、概述 智慧公厕环境监测解决方案是指利用物联网、云计算、大数据等技术,对公厕内的环境参数进行实时监测、分析和管理,以提升公厕环境质量,改善如厕体验,打造智慧城市的重要组成部分。 二、方案组成 智慧公厕环境监测解决方案主要由以下四部分组成: 监测终端: 负责采集公厕内的环境参数,包括温湿度、硫化氢、氨气、PM2.5、臭氧等。 传输部分:负责将监测终端采集到的数据传输至管理平台。 管理平台:负责对数据进行存储、分析和展示,并提供管理功能。 智能联动:根据监测数据,联动风机、排气扇、照明等设备,实现公厕环境的智能化管理。 三、工作原理 监测终端采集公厕内的环境参数,并将数据传输至传输部分。 传输部分将数据传输至管理平台。 管理平台对数据进行存储、分析和展示,并提供管理功能。 根据监测数据,联动风机、排气扇、照明等设备,实现公厕环境的智能化管理。 四、方案优势 实时监测:可实时监测公厕内的环境参数,及时发现环境问题。 智能分析:可对监测数据进行智能分析,为公厕管理提供决策依据。 精细管理:可实现公厕环境的精细化管理,提升公厕环境质量。 人性化服务:可为如厕者提供更加人性化的服务,提升如厕体验。 监测终端主要有多功能空气质量变送器和吸顶式红外探测器。 公厕内的硫化氢和氩气是造成公厕异味的原因,当这2种气体的浓度达到一定的数值,就会对人体造成伤害,多功能空气质量变送器可以同时监测这两种气体的浓度,避免浓度升高对人体造成伤書。 吸顶式红外探测器能够对厕位使用情况进行动态监测,通过显示屏可直接反映厕位的占用情况,减少人员的等待时间,也方便管理人员合理配置资源。 五、应用场景 智慧公厕环境监测解决方案可广泛应用于城市公厕、景区公厕、高速公路公厕、公园公厕、学校公厕等场所。 六、典型案例 某市智慧公厕项目:该项目采用智慧公厕环境监测解决方案,对全市范围内1000余座公厕进行环境监测,有效提升了公厕环境质量,改善了如厕体验。 某景区智慧公厕项目:该项目采用智慧公厕环境监测解决方案,对景区内50余座公厕进行环境监测,有效缓解了景区公厕高峰期排队压力,提升了景区游客的满意度。 七、发展趋势 随着智慧城市建设的不断发展,智慧公厕环境监测解决方案将得到更加广泛的应用,并将朝着以下方向发展: 技术更加智能化:将采用人工智能、大数据等技术,进一步提升监测、分析和管理的智能化水平。 功能更加丰富:将提供更多人性化功能,如厕位导航、厕纸余量提醒、如厕安全监测等。 应用更加广泛:将应用于更多场景,如家庭卫生间、养老院卫生间、医院卫生间等。 八、结论 智慧公厕环境监测解决方案是智慧城市建设的重要组成部分,对于提升公厕环境质量、改善如厕体验、提升城市形象具有重要意义。 --- ### 427. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案背景: 随着我国养猪业的迅速发展,行业面临着一线从业人员逐渐减少、投资者和养殖者收益需求增加的挑战。这使得养殖规模和方式发生了巨大变化,物联网管理系统应运而生。通过自动化、信息化、智能化的手段,农业养殖实现了标准化生产、规模化经营,以科技支撑农业发展,助力养殖行业创新发展,帮助养殖户实现省时增收。 方案介绍: 猪舍环控系统是为了解决猪舍内环境管理难题而设计的智能化解决方案。通过传感器采集猪舍内空气温湿度、氨气含量、二氧化碳浓度等数据,当环境参数达到预设危险值时,系统通过电话、微信等多种方式告警用户,实现猪舍环境的及时监测和预警。智能猪舍架构设计包括环境监测、视频监控、智能联动等模块,通过实时数据采集和远程控制,实现猪舍环境的智能化管理。监控云平台提供了用户友好的界面,支持多种控制方式,为养殖者提供了便捷的管理体验。 方案组成: 环境监测设备:包括空气温湿度传感器、氨气、二氧化碳传感器等,用于实时采集猪舍内环境数据 控制设备:如风机、窗帘机、加热器等,通过智能控制系统实现对猪舍内环境的自动调控。 监控云平台:提供实时数据查看、设备管理控制、历史数据查看等功能,为养殖者提供便捷的管理方式。 联动控制:根据环境数据及用户设定的条件,实现智能联动控制,如自动调节风机、湿帘等设备,确保猪舍内环境处于最佳状态。 方案功能: 实时监测预警:对猪舍内空气温湿度、氨气含量、二氧化碳浓度等环境参数进行实时监测,并实现预警功能。 自动调控:根据环境数据及用户设定,自动控制风机、加热器等设备,确保猪舍内环境处于适宜状态。 远程控制:通过监控云平台,实现对猪舍内设备的远程监控和控制,随时随地进行管理。 历史数据查看:提供历史环境数据的查看功能,帮助用户分析猪舍内环境变化趋势,为决策提供参考。 设备清单 自动化设备: 环境监测传感器: 总结 猪舍环控系统通过智能化管理和自动化控制,提高了养猪环境的质量和管理效率,为养殖者带来了更高的生产效益和经济收益。 --- ### 428. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案介绍 养殖控制器是一种基于物联网技术的智能化环境监控与控制系统,旨在为养殖场提供全方位的环境管理和设备控制解决方案。该系统可以实时监测养殖环境的温度、湿度、二氧化碳浓度等参数,并通过智能算法进行分析和调控,保障养殖环境的稳定性和舒适性,提高养殖效率和产出品质。 方案组成 传感器节点: 包括空气温湿度传感器、二氧化碳传感器等,用于实时采集养殖环境参数数据。 2.数据采集与传输模块: 负责将传感器节点采集到的数据传输至控制中心,采用4G、WiFi等方式进行数据传输。 3.控制中心: 该中心是整个系统的核心,负责数据的接收、处理和分析,以及控制指令的下发。 具备数据存储和处理能力,可以实现历史数据查询和统计分析。 4.执行设备: 根据控制中心的指令,控制各种设备的运行,如风机、加热器、喷灌系统等。 5.用户界面: 提供Web端和手机App,用户可以通过界面实时查看养殖环境数据、设备运行状态,并进行远程控制和管理。 方案功能 实时监测: 实时监测养殖环境的温度、湿度、二氧化碳浓度等参数,保障养殖环境的稳定性。 智能控制: 根据预设的控制算法,智能调节各种设备的运行状态,实现养殖环境的智能化管理。 远程管理: 用户可以通过手机App或Web端随时随地远程监控和管理养殖场的运行状态,提高管理效率。 报警功能: 当养殖环境出现异常情况时,系统会自动发出报警,提醒用户及时处理,保障养殖场的安全运行。 历史数据分析: 系统具备数据存储和分析功能,可以对历史数据进行统计分析,为养殖决策提供参考依据。 综上所述,该养殖控制器系统能够为养殖场提供全方位的智能化环境管理和设备控制服务,提高养殖效率、降低成本、保障产品质量,具有广阔的应用前景和市场潜力。 --- ### 429. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案背景 随着物联网(IoT)和人工智能物联网(AIoT)技术的迅速发展,智能化产品在宠物产业中的应用逐渐受到关注。中国宠物市场持续增长,年轻人群对宠物的需求增加,促使了宠物用品行业的创新和智能化发展。为了满足宠物主人对宠物健康、安全和舒适的需求,物联网技术被引入到宠物领域,推动了智能化宠物产品的发展。 方案介绍 本方案旨在利用物联网技术为宠物主人提供一系列智能化解决方案,包括智能喂食器、智能喂水器、智能猫窝和狗窝等产品。通过将传感器、执行器等设备连接到互联网上,宠物主人可以远程监控和管理宠物的饮食、生活环境等情况,实现对宠物的全方位关怀。 方案组成 智能喂食器:结合IoT技术,实现远程监控和定时喂食功能,根据宠物数据智能调整喂食量。 智能喂水器:定时喂水、监控水质,保障宠物饮水安全。 智能猫窝和狗窝:通过内置传感器和摄像头监测宠物行为和健康状况,智能调节温度和湿度,提供舒适安全的生活环境。 方案功能 远程监控与控制:宠物主人可以通过手机App或网页平台随时随地监控和管理宠物的饮食、生活环境等情况,实现远程喂食、喂水和调节环境温度等功能。 智能化调整:根据宠物的体重、运动量等数据,智能调整喂食量和水质,确保宠物健康饮食。 数据记录与分析:系统可以记录宠物的饮食、活动等数据,为宠物主人提供参考,并通过数据分析帮助宠物主人更好地了解宠物的生活习性和健康状况。 安全保障:智能设备可以监测水质、调节温度和湿度,一旦发现异常情况,系统会及时发送通知提醒宠物主人,保障宠物的健康和安全。 结语 随着物联网技术的不断发展和普及,智能化宠物产品将为宠物主人带来更便捷、安全和舒适的养宠体验。本方案以满足宠物主人对宠物生活质量的需求为目标,利用物联网技术打造智能化的宠物产品,为宠物产业注入新的活力,提升消费者体验,推动产业发展。 --- ### 430. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信       智能仓库管理系统充分利用物联网技术,通过良好的分层架构设计,达到从信息采集、信息上传、到智能化处理的全方位管理,通过智能算法匹配实现了智能仓库的智能化采集定位的技术难点。        高精度定位系统技术方案        在技术层面,根据物联网常用模式并结合系统自身特性,将系统分为数据采集端、数据通信端和系统应用端三个层面。        高精度定位系统在智慧工厂运行在成品货物储存仓库,        标出的是入库判定区;        标出的是出库判定区;        工业 POE 交换机的位置,用来连接附近的各排定位基站;        定位基站在仓库的分布位置,在基站布设的位置需要布有 220v 交流电 源接口或者提供 POE 供电,具体点位布设更精细的位置坐标需要根据现场仓库环境、电磁环境、信道检测报告确定。 应用案例: (1)智慧工厂成品生产车间、仓库都有网络接口,高精定位基站、入库门RFID 系统、出库 RFID 桌面式读写器将通过有线网络交换机连接至机房,同时车载 RFID 读写器、手持机将通过全覆盖且无漫游切换的 WIFI 网络回传至机房。 (2)机房作为所有货物位置信息、出入库信息、相关业务信息的汇集地,包括但不限于定位管控服务器、业务及数据库服务器等设备,并与现有 ERP 系统进行协同工作,共同完成从下订单、生产、入库、出库、完成订单等整个业务流程。     < --- ### 431. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信   智慧充电站解决方案,通过对物联网技术、移动互联网技术等技术的综合运用,为社区打造了解决电动自行车充电需求和车棚智慧管理要求的一站式综合解决方案。智能非机动车棚改造项目,是将老旧改造和先进的物联网应用相结合,整合了通信、物联网、门禁、监控、土建、软件管理等各方面资源,自主研发、设计定制的创新型项目。整体解决方案物理架构图如下: 智能充电设施介绍: (1)智能充电桩:         主要对标准电池进行更换,适用于小区、园区、商场等场所;      (2)智能充电柜。          主要对标准电池进行更换,适用于小区、园区、商场等场所 智能充电站有以下一些优势:A、安全性高       社区智能充电站的智能电瓶车充电桩系统对业主来说解决了因为用户私自拉线充电的安全问题。减少电动车充电引起的事故,对小区其他业主的人身安全带来了隐患,对物业来说,安装了小区智能电瓶车充电桩系统,同时也减少电瓶车主的财产损失。并且在小区安装小区智能电瓶车充电桩系统在某种程度上美化小区的环境,还不用每天派专人到小区内巡查,省时省力。 B、方便居民       社区智能充电站的智能电瓶车充电桩系统解决业主电动车充电难的问题。安装充电站,业主只需要把车停在电动车充电站,按照指示操作充电。电动车充电站的普及不仅解决了小区充电难的问题,还对解决城市拥堵、促进环保具有特殊的意义。 C、保护电动车      社区智能充电站的智能电瓶车充电桩系统还有充满自动停功能,能做到防过充的功能。这个是小区智能电瓶车充电桩系统的一个基本要求。产品必须要带有功率检测功能。产品要能有效的判断出电池充电功率,在电池充满电后,能立刻断电。其它所谓的充满后进入自动浮充功能。充满后直接断电才是硬道理。对电动车的电池本身就是一种保护。       社区智能电瓶车充电桩系统可以通过手机扫码智能充电,并支持远程操控,并通过APP、信息等进行全平台消息推送,还可以在APP上实时监测,让您能够轻松了解爱车的充电情况。        < --- ### 432. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案背景 农业生产中,重大病虫害对农作物产量和质量造成严重威胁。为解决这一问题,农作物重大病虫智慧监测预警平台应运而生。该平台通过业务线上化、植保数据仓构建等方式,实现了一体化数据采集服务和综合决策分析,为农作物病虫害防控提供了重要支持。 方案介绍 平台主要围绕监测预警、植物检疫、药政管理等业务科室展开,集成智能虫情测报、昆虫性诱、田间调查等数据,通过专业的对比分析和可视化数据专题分析,实现了数据共享和智能决策提升。 方案组成 智能硬件设备:包括智能虫情测报灯等,通过无公害诱捕杀虫、定时采集现场图像等功能,实现对病虫害的实时监测和数据采集。 云平台:接收和存储来自硬件设备的数据,并进行对比分析和可视化展示,为农业决策提供数据支持。 植保数据仓:整合农业生产经营主体、农资企业等数据资源,实现一体化数据填报和业务贯通,提高数据采集和管理效率。 方案功能 病虫害监测预警:实时监测农田病虫情况,及时发出预警信息,帮助农民制定防治方案。 植物检疫:追踪重点检疫性有害生物,加强防控工作,防止疫情扩散。 药政管理:展示农药生产、使用和废弃情况,推动农药管理的数字化进程。 方案应用 农作物重大病虫智慧监测预警平台在农业生产中有着广泛而深远的应用,涉及到以下几个具体方面: 田间监测与预警:平台通过智能虫情测报灯等设备,实时监测田间病虫情况,对重大病虫害进行预警。农民可以及时了解田间状况,采取相应的防治措施,有效减少病虫害造成的损失。 植物检疫管理:平台密切关注本省重点检疫性有害生物,如亚洲梨火疫病、柑橘黄龙病、红火蚁等。通过五色图、数据列表、折线图等多种形式展示各市县疫情发生和防治情况,及时介入防控,防止疫情扩散。 药政管理:平台数字化展示各地市农药生产、使用和废弃包装回收情况和相关数据,推动药政管理的数字化进程。农业主体可以及时了解农药的生产和使用情况,促进农药的合理使用和废弃物的安全处理。 智慧决策支持:平台整合了农作物病虫害数字化监测预警系统、智能监测预警系统、昆虫性诱测报系统等八个信息化系统和数据资源。通过对比分析和可视化数据展示,为农业决策提供了科学依据和智能化支持。 远程诊断与管理:平台通过智能虫情测报灯等硬件设备,实现了对虫情的远程监测和诊断。农业专家可以随时远程了解田间虫情状况,制定防治措施,提高了防治的科学性和精准性。 该方案广泛应用于农业生产领域,涵盖农田、农资企业、植保工程等多个方面,为农业生产提供全方位的数据支持和智能化服务。 方案亮点 智能化监测:利用智能硬件设备实现对病虫害的精准监测和诊断,提高了监测预警水平。 数据共享:打通系统间数据壁垒,实现数据共享,提高了数据利用效率。 综合决策:通过专业的对比分析和可视化数据展示,为农业决策提供了科学依据。 智慧管理:整合了监测预警、植物检疫、药政管理等多个业务科室,实现了一体化数据采集和管理服务。 以上是针对农作物重大病虫智慧监测预警平台的整体方案描述,旨在提供全面的农业生产支持和智能化服务。 --- ### 433. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 背景 随着人工成本的增加,工程施工布线的成本也日益上升,这使得有效管理传感器设备,降低基础设施投资成本成为企业急需解决的问题。在这种背景下,WiFi温湿度监测解决方案应运而生。该方案以WiFi作为信号传输媒介,利用温湿度传感器作为监测终端,将采集到的温度和湿度数据上传到云平台,用户可以通过手机或电脑实时查看监测数据,从而实现了远程监测与管理,大大降低了施工量和施工成本,同时也避免了传统布线中可能出现的接线错误的隐患。 方案概述 WiFi温湿度监测解决方案由以下几个主要组成部分构成: 温湿度传感器:采集环境中的温度和湿度数据,并将其转换为数字信号。 WiFi模块:作为信号的传输媒介,将传感器采集到的数据通过WiFi网络上传至云平台。 云平台:接收和存储传感器上传的数据,并提供数据分析、图表展示等功能。用户可以通过手机或电脑随时随地访问云平台,实时查看监测数据。 手机/电脑应用:用户通过安装专用应用或通过网页浏览器,可以方便地查看温湿度监测数据,设置报警阈值,接收异常报警通知等。 应用场景 WiFi温湿度监测解决方案适用于以下场景: 机房:保障服务器和网络设备的稳定运行,防止硬件损坏和数据丢失。 楼宇:提供舒适的办公环境,提高员工的工作效率。 宾馆:保障客房内的空气质量,提升客户满意度。 图书馆:保护图书和档案的保存环境,防止湿度过高导致纸质资料损坏。 档案室:确保档案的长期保存和安全。 优势与收益 成本节约:无需布线,大大降低了施工成本和维护成本。 方便快捷:通过手机或电脑即可实时监测数据,随时随地掌握环境状况。 高效管理:设定报警阈值,及时发现异常情况,减少损失。 数据分析:通过云平台提供的数据分析功能,优化环境管理策略,提高效率。 总结 WiFi温湿度监测解决方案以其便捷、高效、成本节约等优势,在多个场景下得到了广泛应用。随着人工成本不断上涨和工程施工布线成本的增加,该解决方案将成为企业提高管理效率、降低成本的重要工具之一。 --- ### 434. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着现代生活中对空气质量关注度的增加,空气质量变送器在学校的应用成为了确保学生和教职员工健康与安全的重要措施之一。本文将探讨空气质量变送器在学校中的应用及其重要性。 一:空气质量变送器在学校中的应用及其重要性。 1. 空气质量监测 空气质量变送器是一种用于监测室内和室外空气质量的设备,它能够实时检测并传输关于空气中污染物浓度的数据。在学校中,这些污染物可能包括颗粒物(PM2.5和PM10)、挥发性有机化合物(VOCs)、二氧化碳(CO2)等。通过安装空气质量变送器,学校可以实时监测空气质量,并及时采取措施来改善空气质量,保障师生健康。良好的空气质量对学生的注意力和学习效率至关重要。空气质量变送器有助于确保学生在一个健康的环境中学习,减少因空气污染引起的呼吸道疾病和其他健康问题。对于有特殊需要的学生,如哮喘患者,空气质量监测尤为重要。 2. 健康风险预警 空气质量变送器不仅可以监测空气中的污染物浓度,还可以根据设定的健康标准和指南发出预警。一旦空气质量超过了安全范围,变送器就会发出警报,提醒学校管理人员采取相应的措施,如通风、净化空气等,以降低师生暴露在有害污染物中的风险。 3. 学习和工作环境改善 良好的空气质量是保障学生和教职员工健康的重要因素之一。研究表明,良好的室内空气质量可以提高学生的学习效率和教职员工的工作效率,减少疲劳和疾病的发生率。通过安装空气质量变送器,学校可以实时监测教室、图书馆、实验室等室内空间的空气质量,包括PM2.5、PM10、甲醛、二氧化碳等污染物的浓度。变送器可以检测到空气质量的变化,并及时发出警报,以便采取相应措施。4. 疫情防控 在当前新冠肺炎疫情的背景下,空气质量变送器的应用也对于学校的疫情防控工作至关重要。通过监测空气中的颗粒物和二氧化碳浓度,学校可以及时了解室内空气流通情况,并采取必要的措施来降低病毒传播的风险,保障师生的健康安全。 5. 节能和成本效益 空气质量变送器可以与学校的HVAC(供暖、通风和空调)系统联动,根据监测数据自动调节通风和空气净化设备的运行,从而提高能效和节约能源成本。通过优化通风系统,减少过度通风或不足,可以降低能源消耗。 6. 紧急情况响应 在发生火灾或其他紧急情况时,空气质量变送器可以迅速检测到有害气体的泄漏,及时通知学校管理人员和紧急服务部门,保障人员安全。 7. 科学研究和教育: 空气质量变送器可以作为科学课程的一部分,让学生参与到空气质量的监测和研究中,增强他们的环境意识和科学实践能力。教师可以利用监测数据进行环境教育,让学生了解空气污染的影响和减少污染的方法。8. 家长和社区的参与 通过公开空气质量监测数据,学校可以与家长和社区建立信任关系,展示其对学生健康的承诺。家长和社区居民可以参与到学校环境改善的活动中,共同促进一个更健康的学习环境。 二:数据上传方式 可通过RS485线将数据上传至RS-R-K本地监控软件,或连接环境监控主机RS-XZ)-100--GPRS/4G,通过GPRS/4G的通讯方式将数据上传至环境监控云平台。 三:环境监控云平台用户可通过电脑、手机apP及公众号等多种方式登录云平台,在前端界面查看环境监控主机上传的实时数据,也可分时间段查看历史数据,下载历史数据。云平台系统可以进行远程管理,用户只需登录云平台,添加管理人员信息,就可修改设置各因素的上下限值;一旦出现数值超限,系统会通过短信的形式通知添加在云平台上的管理人员。学校应当是一个干净、整洁、美丽、舒适的书香庭院,我们致力于打造这样的环境,也需要多功能空气质是变送器的应用。 综上所述,空气质量变送器在学校的应用对于保障学生和教职员工的健康和安全具有重要意义。学校管理部门应高度重视空气质量监测工作,积极采取措施改善室内空气质量,为师生营造一个健康舒适的学习和工作环境。 --- ### 435. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着环境保护意识的提高和能源危机的日益临近,绿色能源的应用愈发受到关注。在这一背景下,空气源热泵作为一种高效、环保的供热、供冷设备,逐渐成为了替代传统能源的重要选择。然而,其复杂的运行机理和常见的故障问题给用户带来了不小的困扰,这也促使着对热泵系统的智能化控制需求日益增长。 问题背景与需求 空气能及热泵产品面临着故障率较高、用户反馈不及时全面等问题,用户往往无法清楚描述设备在运行过程中的故障,导致解决时间长、运营成本高。为解决这些问题,我们研发了基于物联网技术的空气源热泵智能控制系统。 系统功能与特点 远程监控管理: 通过分布式热泵机组远程控制系统,实现对热泵机组的群组监控管理,可实现远程无人值守、实时监控,大大提高了运营效率和售后保障水平。 智能化运行: 系统具备储热水箱水温水位控制、恒温水箱控制、管道循环/回水控制、防冻/除霜控制等功能,能够根据用户需求自动调节,实现节能运行。 故障显示与报警: 系统可实时监测设备运行状态,一旦发现故障即时报警,通过多种方式通知用户,助力快速处理。 智能逻辑控制: 实现对多主机工程的群组联动、任务预约、节能工作、温度保护等模式进行调节,用户可通过手机APP/电脑监控平台进行远程设置调节。 硬件控制柜配置: 控制柜集成了各种传感器和通讯模块,能够对设备的各项参数进行实时监测和控制,保障系统稳定运行。 通讯架构与数据监控 系统通过物联网通讯技术与聚英云平台相结合,实现了远程集中监控管理热泵机组的工作运行状态。通过即插即用通讯速度快、低延时的特点,实现了对设备状态的实时监控与控制。 使用效果与成本分析 根据实际数据统计,智能空气源热水系统相比传统电锅炉和燃气热水器,在年均能效比和能源利用率上均有显著提升,能够实现更为节能的运行状态。同时,系统的智能化控制和远程监控功能,大大降低了运维成本和人力投入,提高了系统的稳定性和可靠性。 结语 综上所述,空气源热泵智能控制系统不仅满足了用户对设备运行状态实时监控与远程控制的需求,还能够实现节能减排、降低运营成本的目标,是未来绿色能源利用与管理的重要解决方案。随着技术的不断创新和应用场景的扩展,相信空气源热泵智能控制系统将在各个领域发挥越来越重要的作用,为社会经济可持续发展做出更大的贡献。 --- ### 436. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着人们对健康生活的追求日益增强,室内空气质量的监测成为了保障居住和工作环境健康的重要措施。室内空气污染物,如PM2.5、甲醛、一氧化碳等,可能对人体健康造成严重影响。因此,建立一个全面的室内空气质量监测系统显得尤为重要。 一、监测目标 实时监测室内空气中的污染物浓度,包括但不限于PM2.5、PM10、甲醛、一氧化碳、TVOC等。 通过数据分析,提供室内空气质量改善建议。 保障监测数据的准确性和实时性,确保居住者和工作人员的健康。 二、监测设备 多功能空气质量变送器:该变送器能够对室内空气中的多种参数进行实时监测,包括温度、湿度、颗粒物和有害气体浓度。设备采用高灵敏度传感器和电化学式及催化燃烧式检测技术,确保监测结果的准确性。 环境监测云平台:与变送器配套使用,实时收集和分析监测数据,支持远程查看、数据管理和报警通知功能。 三、监测实施 设备部署:在室内关键区域部署变送器,确保全面覆盖监测空间。 数据连接:通过专用的485通讯线路将变送器连接至云平台,确保数据传输的稳定性。 实时监控:利用环境监测云平台实时查看室内空气质量数据,及时发现异常情况。 报警设置:在云平台上设置各项污染物的阈值,一旦超过安全范围,系统自动通知相关人员。 数据分析:定期分析历史数据,评估室内空气质量变化趋势,提出改善建议。 四、应用场景 家庭住宅:为家庭提供健康的居住环境,特别是对于新装修的住宅,监测甲醛等有害气体的浓度。 办公空间:确保员工工作环境的空气质量,提高工作效率和员工健康水平。 公共场所:如医院、学校、商场等,保障公众健康,预防空气污染相关疾病。 五、结语 室内空气质量监测方案的实施,不仅能够保障人们的健康,还能够提高生活和工作环境的质量。通过多功能空气质量变送器和环境监测云平台的结合使用,我们能够实现对室内空气质量的全面监控和管理,为打造健康、舒适的室内环境提供强有力的技术支持。 --- ### 437. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 5G基站电控箱环境监测系统整体方案 随着5G技术的快速发展和广泛应用,确保基站的稳定运行和维护变得尤为重要。5G基站电控箱作为基站的核心部分,其内部环境的监测对于保障基站正常运行至关重要。以下是一个针对5G基站电控箱环境监测的系统方案,旨在实现对基站电控箱内部环境的实时监控和管理。 一、系统目标 实时监测电控箱内部的温度、湿度、烟雾、水浸等环境参数。 及时发现和预警潜在的环境问题,防止设备损坏。 提供远程监控和管理功能,降低维护成本和提高响应速度。 二、系统组成 传感器模块:包括温度传感器、湿度传感器、烟雾传感器和水浸传感器,用于实时采集电控箱内部的环境数据。 数据采集单元:负责收集传感器模块的数据,并将数据通过无线网络发送到监控中心。 通信模块:利用5G网络实现数据的高速传输,确保信息的实时性和准确性。 监控中心:接收并存储来自各个基站的数据,通过监控软件进行数据分析和处理,并提供用户界面供维护人员操作。 报警系统:当监测到异常情况时,系统自动触发报警,并通过监控中心通知维护人员进行处理。 三、系统特点 高速度:5G网络的高速度确保数据实时传输,提高系统响应能力。 高可靠性:采用多种传感器组合,确保全方位监测电控箱内部环境。 易维护:远程监控和管理功能减少了现场维护的需求,降低了维护成本。 可扩展性:系统设计考虑未来技术的升级和功能的扩展,具备良好的适应性。 四、实施步骤 现场勘查:对基站电控箱的实际情况进行勘查,确定传感器的安装位置和数量。 系统安装:安装传感器模块、数据采集单元和通信模块,并进行初步测试。 软件配置:在监控中心配置监控软件,设置报警阈值和报警方式。 系统测试:进行全面的系统测试,确保所有模块正常工作,报警系统准确无误。 运行维护:系统投入运行后,定期对系统进行检查和维护,确保长期稳定运行。 五、结论 5G基站电控箱环境监测系统是保障5G网络稳定运行的重要措施。通过实时监测和远程管理,可以有效地预防和减少由环境因素引起的设备故障,提高基站的运行效率和可靠性。随着5G技术的不断进步,该系统将成为5G基站维护的标配,为5G网络的稳定运行提供坚实的保障。 --- ### 438. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智能交通系统方案:利用串口服务器实现高效城市交通管理 随着城市化进程的加速,交通拥堵、事故频发和通行效率低下等问题日益凸显,智能交通系统的建设成为解决这些问题的关键。通过运用串口服务器,我们可以构建一个高效、可靠且易于管理的智能交通网络,实现对城市交通的实时监控、数据分析和优化调度。 一、系统架构 智能交通系统的核心是串口服务器,它将传统的串口设备连接到以太网,实现设备的远程控制和数据采集。串口服务器作为桥梁,将信号灯、道闸、摄像头、称重仪表、LED显示屏、RFID读卡器、车辆感应线圈和票据打印机等设备接入局域网,实现集中管理和多用户访问。 二、关键技术 以太网连接:通过以太网技术,支持RS232和RS485两种串口信号,以及TCP Client、TCP Server、UDP Client、UDP Server、HTTPD Client等多种工作模式,确保与各种交通设备的兼容性。实现串口设备与控制中心的高速连接,确保数据传输的稳定性和实时性。 Modbus网关功能:轻松实现Modbus RTU和ModbusTCP协议互转,方便与现有的交通监控系统进行集成。串口服务器支持多用户同时访问,使得不同的客户端可以根据自己的需求获取交通数据。 自动轮询与数据采集:毫秒级的数据采集能力,确保交通数据的实时性和准确性。通过中央服务器,实现对所有串口设备的集中管理和配置,简化了维护工作,提高了管理效率。 虚拟串口技术:通过USR-VCOM软件,实现串口设备的虚拟化,简化软件开发和调试过程。实现对串口设备的远程管理和配置,无需更换现有串口软件。 三、应用场景 交通信号控制:通过串口服务器连接信号灯,控制中心可以根据实时交通流量调整信号灯的时序,优化交通流。 无人值守称重:将串口服务器与道闸和称重仪表相连,实现车辆的自动称重和道闸的远程控制。 交通数据采集:连接摄像头和车辆感应线圈,实时采集交通流量、速度等数据,为交通规划提供决策支持。 事故应急响应:通过实时监控,快速发现交通事故,及时调度救援资源,减少事故影响。 四、方案优势 高效性:通过实时数据分析,提高交通管理的响应速度和处理能力。 可靠性:串口服务器的稳定性保证了交通数据的准确传输和设备的可靠控制。 灵活性:支持多种串口设备的接入,便于根据实际需求扩展系统功能。 易维护性:集中管理和虚拟串口技术简化了设备的维护和升级工作。 五、结论 利用串口服务器实现的智能交通系统,不仅能够提高城市交通管理的效率和响应速度,还能够为交通规划和应急响应提供强有力的技术支持。随着技术的不断发展,未来的智能交通系统将更加智能化、网络化,为城市居民提供更加便捷、安全的出行环境。 --- ### 439. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 液位变送器在蒸发器操作中的重要性 在工业生产过程中,蒸发器是一种常见的设备,广泛应用于化工、食品加工、制药和制冷等行业。其主要功能是将液态物质转化为气态,同时通过吸收热量来降低周围介质的温度,实现物料的蒸发和结晶。液位变送器作为蒸发器操作中的关键组件,对于确保整个蒸发过程的顺利进行和提高操作效率具有重要意义。 一、蒸发器的工作原理 蒸发器的工作原理基于物质的相变过程。在蒸发器中,液态制冷剂(如氯化钠、硫酸钠等)被引入到管道中,通过外部热源或压缩机制冷剂液化,然后在蒸发器内气化,由液态变为气态。在这个过程中,制冷剂吸收周围介质的热量,从而达到冷却的效果。 二、液位变送器的作用 精确监测液位: 液位变送器能够实时监测蒸发器内部的液位高度,确保制冷剂的供应和蒸发过程的稳定进行。 控制制冷剂的供给: 通过液位变送器反馈的数据,可以自动调节制冷剂的流入量,保证蒸发器内液位的稳定,避免因液位过高或过低而导致的操作问题。 优化蒸发效率: 液位变送器有助于优化蒸发过程,通过精确控制液位,可以提高蒸发效率,减少能源消耗。 保障操作安全: 液位变送器可以预防液位过高导致的溢出或过低导致的设备损坏,确保蒸发器操作的安全性。 三、液位变送器的技术要求 液位变送器在蒸发器中的应用需要具备以下技术特点: 高精确度: 液位变送器必须具备高精度的监测能力,以确保液位数据的准确性。 良好的稳定性: 在蒸发器的高温或低温环境下,液位变送器需要保持稳定的工作性能。 快速响应: 液位变送器应具备快速响应的特性,以便及时调整制冷剂的供给。 耐腐蚀性: 由于蒸发器中可能接触到各种化学物质,液位变送器需要具备良好的耐腐蚀性能。 四、结论 液位变送器在蒸发器操作中发挥着至关重要的作用。通过精确监测和控制蒸发器内部的液位,液位变送器不仅能够提高蒸发效率,降低能源消耗,还能够保障操作过程的安全性。随着工业自动化技术的不断进步,液位变送器的性能将不断提升,为蒸发器操作提供更加可靠和高 --- ### 440. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着城市化进程的加快,城市雨洪管理和内涝问题日益凸显。海绵城市作为一种新型的城市雨洪管理理念,旨在通过模拟自然水循环过程,提高城市对环境变化的适应能力,减少雨水带来的自然灾害。在这一理念的实施过程中,液位计作为液位变送器的一种,发挥着至关重要的作用。 一、海绵城市的理念与挑战 海绵城市,又称为“水弹性城市”,其核心是通过一系列低影响开发(LID)措施,实现雨水的渗透、滞蓄、净化、利用和排放,从而提高城市对雨水的“弹性”管理。然而,由于这些措施的分散性和针对性,如何有效监控和评估这些设施的运行效率,成为了实现海绵城市目标的关键挑战。 二、液位计在海绵城市中的应用 实时水位监测:液位计能够实时监测城市雨水收集与排放系统中的水位变化,为城市雨洪管理提供准确的数据支持。在海绵城市的各个关键节点,如生物滞留设施、湿塘、雨水湿地等,液位计的安装确保了对水位的精确控制。 流量监控:在小区和市政道路的排水设施中,液位计与流速监测器、巴氏计量槽等设备配合使用,对雨水的溢流排放和管道排放进行监控,确保雨水得到合理管理。 水质监控:液位计与浊度、悬浮物综合监测器等水质监测设备相结合,对经过低影响开发设施处理后的雨水水质进行监控,确保水质达到预期标准。 数据分析与优化:所有监测数据通过地下管线综合管理信息平台进行汇总和处理,为海绵城市的规划、建设和管理提供科学依据,实现设施布局的优化和运行效率的提升。 三、液位计的技术要求 在海绵城市的应用中,液位计需要具备高精度、稳定性和快速响应的特点。此外,考虑到城市环境的复杂性,液位计还应具备防水、防腐蚀等特性,以适应不同的环境条件。 四、结论 液位计在海绵城市的构建中扮演着不可或缺的角色。通过实时监测水位、流量和水质,液位计为城市雨洪管理提供了强有力的技术支持,有助于实现城市水资源的可持续利用和环境保护。随着海绵城市理念的不断推广和实施,液位计的应用将更加广泛,对提升城市水弹性管理水平起到关键作用。 --- ### 441. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、项目背景 随着工业化和城市化的快速发展,污水排放量日益增加,对环境造成了严重的影响。为了保护水资源,减少污染,实现可持续发展,必须对污水进行有效处理。本方案旨在介绍一种综合性的污水处理流程,包括一级、二级和三级处理,以确保污水达到排放标准,减少对环境的影响。 二、污水处理流程 一级处理(物理处理) 目标:去除污水中的悬浮固体(SS)。方法:通过粗格栅拦截大颗粒固体,然后通过污水提升泵提升污水,再经过细格栅或砂滤器进一步去除较小的悬浮物。结果:BOD(生物化学需氧量)可去除约30%,但不足以满足排放标准。二级处理(生物处理) 目标:去除污水中的胶体和溶解性有机物(BOD,COD)。方法:活性污泥法:通过曝气池或氧化沟,利用微生物降解有机物。生物膜法:在生物滤池、生物转盘、生物接触氧化法和生物流化床中,微生物附着在载体上,降解流过污水中的有机物。结果:有机物去除率可达90%以上,使有机污染物达到排放标准。三级处理(高级处理) 目标:进一步去除难降解有机物、氮、磷等可导致水体富营养化的可溶性无机物。方法:生物脱氮除磷法:通过微生物的代谢作用,去除污水中的氮、磷。混凝沉淀法:通过添加混凝剂,使微小悬浮物聚集成大颗粒,便于沉淀。砂滤法:通过砂滤器去除残留的悬浮物。活性炭吸附法:利用活性炭的吸附作用,去除有机物和部分无机物。结果:进一步提高污水的清澈度,减少对水体的污染。三、污泥处理 污泥回流:将二级处理产生的污泥部分回流至一级处理的初次沉淀池或生物处理设备,以提高处理效率。污泥浓缩:通过污泥浓缩池减少污泥的体积。污泥消化:在污泥消化池中,通过微生物的作用减少污泥的有机物含量。污泥脱水和干燥:通过脱水和干燥设备,将污泥转化为可利用的资源。四、监测与控制 实时监测:在整个处理过程中,通过安装液位变送器、流量计、水质分析仪等设备,实时监测污水处理的效果。自动化控制:通过集成控制系统,实现污水处理过程的自动化,确保处理效率和稳定性。五、项目实施 设计阶段:根据污水的具体成分和排放标准,设计合理的处理流程和设备配置。施工阶段:严格按照设计要求进行施工,确保工程质量。调试阶段:完成施工后,进行设备调试和系统优化,确保处理效果达到预期目标。运营阶段:建立完善的运营管理体系,定期维护设备,确保污水处理设施长期稳定运行。六、环境与社会效益 环境保护:通过有效处理污水,减少对水体的污染,保护水资源。资源回收:将污泥转化为可利用的资源,实现废物的再利用。社会责任:通过提供清洁的环境,提升社会生活质量,履行企业的社会责任。 通过实施上述污水处理方案,可以有效去除污水中的污染物,保护环境,同时实现资源的可持续利用,为社会和经济的可持续发展做出贡献。 --- ### 442. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着5G技术的快速发展和普及,为了满足用户对高速、大容量通信网络的需求,全球正加速部署5G基站。但是,5G基站的高效稳定运行对环境条件有着严格要求,特别是电控箱这一核心设备的安全运行尤为关键。5G基站电控箱环境监测系统成为确保基站稳定运行的重要支撑。 5G基站电控箱环境监测系统的重要性5G基站电控箱是基站运行的“心脏”,负责供电、控制等关键功能。环境因素如温湿度异常、水浸、断电等都可能导致电控箱故障,进而影响整个基站的稳定性。因此,实时监测电控箱的环境状态,对预防故障、提高运维效率具有重要意义。 系统概述5G基站电控箱环境监测系统采用先进的计算机网络技术、数据库技术、通信技术等,实现对电控箱内外环境的全方位监控。系统主要包括环境监控主机和云平台两部分,能够实时监测温湿度、水浸、断电、门禁状态等多种参数,并通过GPRS将数据上传至云平台,实现远程监控和管理。系统优势一体化设计:设备小巧,集成度高,易于安装,同时内置高精度传感器,确保监测数据的准确性。GPRS数据上传:利用SIM卡上传数据,无需复杂的布线,简化安装过程,保证数据实时在线。智能联动:系统可以根据监测到的环境参数自动调节空调、风扇等设备,有效控制电控箱内部环境。UPS不间断电源:确保在市电中断时仍能保持监控系统正常运行,提供持续的保护。低成本快速部署:自带免费云平台,无需另搭建服务器,支持多种数据导出格式,方便运维和数据分析。 应用场景5G基站电控箱环境监测系统适用于所有需要远程监控电控箱环境状态的场合,尤其适用于5G基站。它可以大大减少因环境因素导致的设备故障,减少运维成本,提高基站的稳定性和服务质量。结语随着5G时代的到来,基站的稳定运行对通信网络至关重要。5G基站电控箱环境监测系统为基站提供了强大的环境保护,确保了基站能够在各种环境下稳定运行,为用户提供高质量的通信服务。随着该系统的推广应用,相信会进一步推动5G网络的健康发展,满足人们对高速、稳定通信网络的期待。 --- ### 443. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在古代,人们常常将自然灾害视为“上天的惩罚”,而如今,随着科技的进步,我们逐渐认识到自然灾害的发生更多是由气候异常变化引起的。为了及时监测和预防自然灾害,气象站成为了不可或缺的工具。伴随着新中国的崛起,我国气象事业迎来了崭新的历史时期,自动气象站也逐渐普及,为人们的生活提供了重要支持。 气象站的普及和应用已经成为现代社会生活的重要一环。随着科技的不断进步,气象站不再只是专业气象人员的工具,而是可以被广泛应用于民用领域的设备。在日常生活中,正确的气象信息可以帮助我们更好地规划活动、保护财产、确保安全。 1. 家庭安全保障 在家庭中安装气象站,可以实时监测环境数据,帮助家人及时做出应对措施。比如: 预防自然灾害:气象站能够监测风速、降雨量等数据,及时发现可能引发洪涝、龙卷风等灾害的迹象,提前采取预防措施,保障家庭安全。 防范高温天气:气象站可以监测温度和湿度,提前预警高温天气,避免中暑等热带疾病的发生,保护家人健康。 2. 农业生产优化 农业生产对气候条件非常敏感,合理利用气象站可以提高农业生产效率和质量: 灌溉管理:通过监测土壤温度、水分等数据,科学合理地进行灌溉管理,避免因过度或不足灌溉导致的作物减产问题。 病虫害防控:气象站监测的气象数据可以帮助农民及时预警病虫害发生的可能性,采取合适的防治措施,减少农作物损失。 3. 旅游和户外活动安全 对于喜欢户外活动的人来说,气象站也是一项必备设备,可以帮助他们做出正确的决策,确保活动的安全性: 登山和徒步:气象站可以提供高山区域的气象数据,如气温、风力等,帮助登山者选择合适的出行时间和路线,避免遭遇恶劣天气造成意外。 海滨度假:在海滨地区安装气象站,可以实时监测海浪、风速等数据,提前预警可能出现的海啸、风暴等情况,保障度假者的安全。 4. 城市规划与管理 城市管理部门也可以利用气象站数据进行城市规划和环境管理: 交通管理:气象站监测道路湿度、能见度等数据,提供实时的交通情况,帮助交通管理部门合理调配交通资源,缓解交通拥堵问题。 环境保护:监测大气污染物浓度、空气质量等数据,为城市环境保护提供科学依据,制定相应的治理方案,改善城市环境质量。 优秀的气象站应当具备多种监测要素,从风速、风向到土壤温度、水分,再到大气压力、光照等,都能一应俱全。它能同时接入多种气象监测传感器,满足用户在不同场景下的使用需求。 提供全面监测数据 多样化的显示方式 用户对气象数据的获取渠道也越来越多样化,可以选择适合自己需求的显示方式。从高亮LED显示大屏到支持触摸修改参数的触模显示屏,以及定制化的页面功能,用户有着更多的选择权。 简单易用的设备配置 现代的气象站已经实现了非接触式配置,通过手机APP即可轻松完成设备的设置,包括LED屏幕标头、目标地址和端口等。这种简单易用的设计,使得即使非专业人员也能快速上手。 多样化的安装方式 气象站的安装方式也变得更加灵活多样。无论是立杆式还是三脚支架式,都能根据用户的需求进行选择,既满足固定安装的场景,又适用于经常需要移动的环境。 实现远程数据查看与管理 随着互联网的发展,气象站的数据传输也变得更加便捷。山东仁科气象站支持将监测数据传输至环境监控云平台,用户可以通过电脑端、手机APP、微信公众号等多种方式实现实时数据查看、报警提醒等功能,从而及时掌握气象变化,保障生活安全。 可靠的产品质量 在选择气象站时,产品质量是至关重要的。气象站以其可靠的品质保障赢得了客户的信赖,不仅具备丰富的功能,还能够在各种复杂环境下稳定运行,为用户提供可靠的气象数据支持。 综上所述,优秀的气象站应当具备多元化的监测要素、多样化的显示方式、简单易用的设备配置、灵活多样的安装方式、远程数据查看与管理功能,以及可靠的产品质量保障。这些特点的结合,使得气象站在现代社会生活中发挥着越来越重要的作用,为人们的生活提供了更多的便利和安全保障。 --- ### 444. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 地下车库气体监测系统方案旨在提升车库内空气质量管理,确保人员安全,同时达到节能减排的目标。本方案综合考虑了一氧化碳(CO)和二氧化碳(CO2)的监测需求,以及温湿度的调控,依据国家及地方政府的相关规范与标准,特别是《民用建筑绿色设计规范》、《公共建筑节能设计标准》和《绿色建筑评价标准》等,制定以下详细方案。 系统目标安全目标:通过定期排风保证车库内一氧化碳和二氧化碳浓度低于危害水平,避免对人体健康造成损害。节能目标:根据实时监测的一氧化碳和二氧化碳浓度、温湿度调整排风频率,减少能源浪费。 设计依据本方案参考了以下几个关键的国家及地方标准:《民用建筑绿色设计规范》JGJ/T 229-2010:建议汽车库设置机械通风,并配备一氧化碳检测和控制装置。《公共建筑节能设计标准》GB 50189-2015:建议地下停车库的通风系统根据使用情况定时启停,或根据CO浓度进行自动运行控制。《绿色建筑评价标准》GB/T 50378-2019:要求地下车库应设置与排风设备联动的一氧化碳浓度监测装置。 系统组成 3.1 二总线气体监测方案本方案采用二总线技术进行CO在线监测,方案组成如下:CO数据采集设备:采集车库内的CO浓度数据。MBUS二总线监控主机:作为监测系统的中心,负责数据处理和控制指令的发出。环境监控平台:用于数据显示、分析和存储。风机控制系统:根据CO浓度数据自动调节风机的启动和停止,实现联动排风。3.2 设备选型气体变送器:采用高品质的电化学传感器,支持多种气体检测,具有声光报警功能。二总线主机:具备大屏中文液晶显示,支持短信报警和数据存储功能,能同时连接多个二总线设备3.3 系统软件综合环境监控云平台:提供实时监控、数据分析、报警管理等功能,支持多级权限访问和子账号管理。 操作流程实时监测:系统不断采集地下车库内的CO浓度以及温湿度数据。数据分析:二总线监控主机分析数据,当CO浓度超过设定阈值时,自动启动风机进行排风。报警通知:若CO浓度超过安全阈值,系统通过环境监控平台发送短信、邮件或其他形式的报警通知给管理人员。监控平台会存储历史数据,方便管理人员查询和分析,以优化系统性能和响应策略。 关键技术特点二总线技术:简化了布线过程,支持更远的通信距离,易于扩展和维护。高精度传感器:确保数据的准确性,及时发现潜在的安全隐患。智能控制系统:根据实时数据自动调整通风系统,有效节能且保持空气质量。多平台兼容性:监控平台支持电脑和移动设备,方便随时随地监控和管理。 实施步骤需求分析:根据地下车库的具体情况,包括车库大小、车辆流量、现有通风设施等,确定系统设计需求。系统设计:根据需求分析结果,设计气体监测和通风控制系统,包括设备选型、系统布局和通信协议等。安装调试:在地下车库安装传感器、控制器等设备,并进行系统调试,确保系统稳定运行。系统培训:为管理和维护人员提供必要的系统操作和维护培训。运行监控:系统投入运行后,持续监控车库内的气体浓度,确保运行效率和人员安全。 维护与升级定期检查:定期对监测设备和通风设施进行检查和维护,确保系统正常运行。数据分析:利用收集的数据进行深入分析,优化系统设置,提升系统性能。技术升级:根据技术发展和用户反馈,定期对系统进行升级,增加新功能或提升系统效率。 结语本方案为地下车库提供了一个综合的气体监测和通风控制解决方案,不仅能有效保障车库使用人员的健康和安全,还能通过智能控制达到节能减排的目的。通过实施此方案,可以大大提升地下车库的环境质量,为用户创造一个更加安全、舒适的停车环境。 --- ### 445. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智能玻璃温室整体方案 随着现代科技的不断发展,智能玻璃温室作为农业生产的一种创新模式,正在逐渐受到人们的关注和青睐。智能玻璃温室通过融合先进的玻璃材料、智能控制技术以及现代农业种植理念,实现了对温室内环境的精准调控,提高了农作物的生长质量和产量。本文将介绍一种智能玻璃温室的整体方案,旨在为农业生产提供更加高效、智能的解决方案。 背景 传统的温室种植存在着环境控制不精准、资源利用不充分等问题,为此,智能玻璃温室应运而生。智能玻璃温室利用先进的玻璃材料,如光学玻璃、光热转换玻璃等,结合智能控制系统,实现对温室内温度、湿度、光照等环境参数的精准调控,从而提高农作物的生长速度和品质。 与传统温室相比,智能玻璃温室具有以下优点: 高效节能智能玻璃温室可以通过自动控制系统,根据温室内部的温度、湿度、天线等环境参数,对温室内部的采暖、通风、通风等系统进行定制控制,从而提高能源利用效率,降低生产成本。智能玻璃温室还可以采用太阳能、风能等可再生能源作为辅助能源,进一步提高能源利用效率,减少环境污染2.精准控制智能玻璃温室可以通过传感器、物联网等技术,实时采集温室内部的环境数据,并进行自定义分析,从而对温室内部的温度、湿度、天线、空中浓度等环境参数进行精准控制,为作物提供生长大概的环境条件。智能玻璃温室还可以根据作物的不同生长阶段,对环境参数进行动态调整,满足作物生长的不同需求。3、提高产量在自动化控制的环境下,作物可以获得更大的生长条件,从而提高产量和质量。智能玻璃温室还可以通过病虫害监测预警系统,及时发现和防治病虫害,减少农作物损失。 降低劳动强度智能玻璃温室可以通过自动化控制系统,实现对温室内部的灌溉、施肥、采收等阶段的自动化管理,减少劳动强度,提高生产效率。5、降低环境影响智能玻璃温室可以通过自动化控制系统,减少化肥、农药的使用量,降低对环境的影响。6.提高农业生产水平 整体方案 1. 温室设计与材料选择 智能玻璃温室的设计应考虑温室结构的稳固性、采光性以及隔热性。选择优质的玻璃材料,如光学玻璃和光热转换玻璃,能够最大程度地吸收和利用太阳能,提高温室内的光照强度和温度,促进作物生长。 2. 智能控制系统 智能玻璃温室应配备智能控制系统,实现对温室内环境的实时监测和精准调控。该系统可监测温室内的温度、湿度、光照等参数,并根据作物的生长需求,自动调整温室内的通风、遮阳、灌溉等设备,保持良好的生长环境。 3. 节能环保设施 智能玻璃温室应配置节能环保设施,如太阳能发电系统、雨水收集系统等,实现对能源和水资源的有效利用。太阳能发电系统可为温室提供清洁能源,减少对传统能源的依赖;雨水收集系统可收集雨水用于温室的灌溉,减少对地下水资源的开采。 4. 数据监测与分析 智能玻璃温室应配置数据监测与分析系统,实时监测温室内环境参数的变化,并对监测数据进行分析和统计,为农业生产提供科学依据。通过对温室内环境和作物生长情况的分析,可以及时调整温室的运行参数,提高农作物的产量和品质。 结语智能玻璃温室作为一种新型的农业生产模式,具有节能环保、高效稳定等优势,对于提高农业生产效率、保障粮食安全具有重要意义。未来,随着智能技术的不断发展和应用,智能玻璃温室将会得到更广泛的应用,为农业产业的可持续发展做出更大的贡献 总的来看,智能玻璃温室是一种具有节能、精准控制、提高产量、减少劳动强度、降低环境影响等优点的现代化农业生产设施。 智能玻璃温室的应用,可以提高农业生产的科技含量和现代化水平,推动农业生产方式的转型升级。 总的来看,智能玻璃温室是一种具有节能、精准控制、提高产量、减少劳动强度、降低环境影响等优点的现代化农业生产设施。 --- ### 446. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 噪声扬尘在线监测整体方案 一、方案概述 本方案旨在为建筑拆迁、道路施工等场景提供一套完整的噪声扬尘在线监测解决方案,实现对施工现场噪声和扬尘污染的实时监测、联动控制、远程监控、数据管理、报警预警等功能,帮助施工企业有效控制污染,降低环境影响。 二、方案架构 噪声扬尘在线监测整体方案架构图: 三、方案组成 监测终端选择: 选择适用于建筑拆迁、道路施工等场景的扬尘在线监测仪器,能够连续监测颗粒物PM2.5、PM10浓度。 确保监测仪器具有高精度、稳定性强、抗干扰能力强的特点,以确保监测数据的准确性和可靠性。 设备布置与联动: 在施工现场布置多个扬尘在线监测仪器,覆盖整个施工区域,实时监测扬尘污染情况。 与喷水设施、除尘设备等进行联动,实现扬尘污染的控制和治理。例如,当监测到扬尘浓度超标时,自动启动喷水设备进行降尘处理。 远程监控与数据管理: 通过远程监控平台,实现对扬尘监测仪器的远程查看、数据存储、分析对比等功能。 监测数据实时上传至云端数据库,并进行存储、管理和分析,为决策提供数据支持。 报警与预警机制: 设定扬尘浓度的报警与预警机制,当监测数据超过预设阈值时,系统自动发出报警信息,提醒相关人员采取措施。 用户权限管理: 设定不同用户角色,实现账号管理与权限控制,确保只有授权人员可以访问监测数据和进行操作。 四、方案优势 实时监测: 可实现对扬尘浓度的实时监测,及时发现和处理扬尘污染问题。 自动化控制: 与喷水设施等设备进行联动,实现扬尘治理的自动化控制,提高治理效率。 远程管理: 通过远程监控平台,可以随时随地查看监测数据,进行数据分析和决策。 数据存储与分析: 监测数据实时上传至云端数据库,便于数据的存储、管理和分析,为环境治理决策提供科学依据。 五、适用场景 建筑拆迁 道路施工 土石方开采 工矿企业 交通物流 其他产生噪声和扬尘污染的场所 六、总结 噪声扬尘在线监测系统是实现施工现场环境污染精细化管理的重要手段,可有效降低施工对环境的影响,提升施工企业的社会责任形象。 --- ### 447. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 电梯字符叠加器(Elevator Character Stacker)是一个解决电梯监控和安全隐患的创新产品。以下是这个产品的解决方案: 问题: 电梯监控摄像头无法实时显示电梯的运行状态和楼层信息。 监控室无法迅速定位和救援被困人员,无法查询电梯中的犯罪活动。 解决方案: 电梯字符叠加器提供了以下解决方案: 实时信息叠加:该叠加器可以将日期、时间和电梯运行信息(楼层号、上行、下行、停靠)叠加到摄像头视频画面中,确保监控室人员随时了解电梯的运行状态。 自定义楼层别名:用户可以自定义楼层别名,使监控室人员更容易理解,例如"5F"、"5楼"、"第5层"等。 无损叠加:信息叠加不影响原有视频信号,完全实现无损叠加。 双网口设计:内部集成交换机功能,方便连接摄像头,无需额外布线。 多型号摄像头兼容:适用于多种品牌的网络摄像头,如海康、宇视、大华、中维世纪等。 信息位置可调节:用户可以根据实际情况调整信息叠加的位置,避免遮挡重要画面。 多样化配置方式:可通过蓝牙配置APP或网口配置软件进行设备配置,方便快捷。 便捷校准:安装完成后只需一名施工人员在电梯轿厢内使用手机APP通过蓝牙连接即可完成校准,无需额外人力合作。 安装方便:外形小巧美观,支持35导轨安装和壁挂式安装,简单便捷。 结论: 电梯字符叠加器为电梯监控系统提供了全面的解决方案,确保监控室人员能够随时掌握电梯的运行状态,提高了电梯的安全性和可靠性。该产品的特点包括实时信息叠加、自定义楼层别名、多种摄像头兼容、便捷校准和安装方便,适用于各类建筑物的电梯监控需求。 --- ### 448. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 项目介绍江苏鸿山葡萄示范园,坐落于无锡市,是一座集经济作物种植、休闲农业和采摘体验农业于一体的现代化综合园区。然而,长期种植导致土壤养分不足,制约了葡萄产量的提升,甚至呈现回落趋势。为解决土壤养分缺失的难题,提高作物产量,经营者决定引进水肥一体化系统,以实现土壤养分的精准供给和作物健康生长。 项目需求原有的净水喷灌系统虽然能实现自动水分补给,但仍需依靠人工施肥来维持土壤养分。高昂的人工成本使得施肥间隔拉长,土壤养分流失,作物产量受损。因此,园区急需一套水肥一体化系统,以降低施肥成本、实现水分养分同步灌溉,保障土壤健康和作物产量。 解决方案我们提出的水肥一体化系统方案如下: 智能化改造:在保留原有灌溉管网的基础上,对灌溉首部系统进行智能化改造。关键设备增加:增加智能水肥一体机、过滤器、施肥桶、水泵变频控制柜等设备,实现水肥一体化系统建设。成本节约:节约改造成本,同时保证系统功能完善,提高使用效率。 项目效果提高产量与质量:通过科学、精准的水肥供应,减少人工管理不当所导致的减产,提高作物的产量和质量。减少环境污染:水肥一体化系统减少了化肥施用过度,降低了土壤、水质污染,响应了绿色可持续发展的呼吁。降低经营成本:智能化水肥灌溉减少了人工施肥成本支出,同时降低了肥料浪费,帮助园区管理者更好地控制经营成本。通过水肥一体化系统的引入,鸿山葡萄示范园将迎来更加繁荣的未来,实现经济效益与环境友好的双赢局面。 --- ### 449. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 冷链物流是指冷冻、冷藏类物品从生产、储藏、运输到销售的各个环节始终处于规定的低温环境下,以保证货物质量和安全的一项系统工程 冷链物流中的主要运输对象:▲鲜活品:蔬菜、水果;肉、禽、蛋;水产品、花卉产品。加工食品:速冻食品、离、肉、水产等包装熟食、冰淇淋和奶制品;快餐原料,▲医药品:各类针剂、药剂。 冷链运输是确保温度敏感产品(如食品、药品和某些化学品)在整个供应链过程中保持在适宜和安全的温度范围内的物流管理过程。一个有效的冷链运输方案通常包括以下关键组成部分: 规划与管理需求分析:明确冷链运输的需求,包括运输的物品类型、温度要求、运输距离、法规要求等。供应链设计:设计高效、可靠的供应链流程,确保从生产到最终用户的每一步都满足温度控制的要求。风险管理:识别潜在的风险点并制定应对策略,如设备故障、运输延误等。 温控设备与包装冷藏/冷冻设备:使用适当的冷藏或冷冻运输工具,如冷藏车、冷藏集装箱等。温度监控技术:部署温度记录器、GPS追踪和实时温度监控系统来确保货物在整个运输过程中保持在适宜的温度范围内。绝缘和冷冻包装:使用高性能的绝缘材料和冷源(如干冰、凝胶包)来保持产品的温度。 运输与物流优化的物流路线:选择最短、最可靠的物流路线,减少运输时间和风险。专业的冷链物流服务商:合作有经验的冷链物流公司,确保运输过程中的专业管理和操作。 温度控制与监控全程温度监控:实时监控货物温度,确保整个运输过程中温度的稳定。数据记录与分析:记录温度数据,进行分析以改进未来的运输过程。 合规性与质量保证法规遵守:确保所有运输过程遵循相关法规和行业标准。培训与认证:为参与冷链运输的所有人员提供必要的培训,确保他们了解和能够遵循正确的操作程序。 应急计划应对措施:制定应急计划,以应对可能的设备故障、极端天气、运输延迟等情况。 客户沟通与服务透明度:向客户提供运输过程中的实时信息,包括温度数据和货物位置。客户服务:设立客户服务热线,解答客户的疑问并提供必要的支持。整合上述元素,开发出一个适应性强、高效可靠的冷链运输方案,可以显著降低产品损耗率,保证产品品质,满足客户和法规的要求。 --- ### 450. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 在我们的日常生活中,空气质量是一个备受关注的话题。尤其是在工地、工厂等环境中,扬尘是一种常见的污染源,对人们的健康和环境造成了不可忽视的影响。为了应对这一问题,现代科技为我们提供了一种全新的解决方案:扬尘监测告警系统。 什么是扬尘监测告警系统? 扬尘监测告警系统是一种利用先进的传感器技术和智能联动功能,实时监测周围环境中的扬尘颗粒,一旦发现超标情况,系统会立即发出警报并采取相应的措施,以保障人们的健康和环境的清洁。 如何工作? 实时监测: 系统通过多种监测要素,如PM2.5、PM10等,实时监测周围环境中的扬尘颗粒浓度,确保数据的准确性和及时性。 智能联动: 当监测数据超过设定的安全阈值时,系统会自动发出预警信号,并联动降尘设备进行处理,以减少扬尘对环境的影响。 多种显示方式: 用户可以通过LED显示屏、手机APP等多种方式查看监测数据,方便快捷。 4 同时,可选配RS485上行接口,搭配视频字符叠加器将监测数据叠加至监控画面中,为视频监控提供数据支撑。 为什么选择扬尘监测告警系统? 保障健康: 扬尘是一种常见的空气污染源,长期暴露于扬尘环境中会对人们的健康造成危害。使用扬尘监测告警系统可以及时发现并处理扬尘污染,保障人们的健康安全。 环境保护: 扬尘不仅对人体健康有害,还会对环境造成破坏,影响生态平衡。通过监测和处理扬尘污染,可以有效保护环境,维护生态平衡。 智能高效: 扬尘监测告警系统采用智能联动技术,能够自动响应监测数据,及时采取措施,提高工作效率,减少人为干预。 结语 扬尘监测告警系统是一种现代化、智能化的环境保护工具,它为我们提供了保障健康、保护环境的新途径。希望通过全社会的共同努力,可以建立起更加清洁、健康的生活环境,让我们的蓝天更加明净、更加美丽! --- ### 451. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 实时监测和数据采集: 物联网传感器可以安装在隧道内部,监测交通流量、车辆速度、车辆密度以及能见度等参数。这些数据通过网络传输到中央控制中心,并实时显示在监控屏幕上,使交通管理人员能够随时了解隧道内的交通状况。 进一步地,传感器可以监测隧道结构的健康状况,包括裂缝、位移和变形等情况,从而及时发现潜在的结构安全隐患。 事故预警系统: 基于物联网技术的事故预警系统可以利用传感器监测的数据,识别交通事故的迹象,例如车辆突然减速或停止、车辆偏离车道等。系统可以自动发出警报,并向交通管理人员和驾驶员发送警示信息。 一些高级系统甚至可以通过机器学习算法分析历史数据和实时数据,预测潜在的事故风险,并提出相应的预防措施。 紧急救援和应急响应: 物联网技术可以与GPS定位系统结合,实现对事故车辆和受困人员的精确定位。一旦发生事故,紧急呼救系统可以自动触发,并将事故位置和相关信息发送给救援中心。 救援人员可以通过智能手机或车载终端接收到事故现场的详细信息,包括实时交通状况、最佳救援路线以及事故类型等,从而提高救援效率。 交通管理和优化: 利用物联网技术收集的数据,交通管理人员可以进行实时交通流量分析和预测,制定最佳的交通管理策略,减少交通拥堵和事故发生的可能性。 智能交通信号灯系统可以根据实时交通情况进行调整,优化交通信号控制,提高路口通过能力和安全性。 通过以上这些方式,物联网技术为隧道交通事故的预防、监测和救援提供了全方位的支持,有效地提高了隧道交通的安全性和效率。 --- ### 452. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 简介 温室大棚环境监测控制系统是一种利用物联网技术和传感器技术对温室大棚内部环境进行实时监测和控制的智能化系统。通过采集温室内部的温度、湿度、光照强度、CO2浓度、土壤温湿度以及土壤电导率等数据,系统可以实现对温室环境的全面监测,并通过智能控制主机对温室内部的设备进行自动控制,以确保作物的生长环境处于最佳状态,提高产量和品质,同时降低能源和资源的消耗。 2. 系统组成 2.1 传感器节点 多功能百叶盒气象传感器:用于监测温室内部的温度、湿度、光照强度、大气压力、噪声、PM2.5和PM10、CO2等多种参数,具有精准度高、稳定性好、安装方便等特点。 土壤温湿度传感器:用于监测土壤的温度和湿度,可以长期埋入土壤中进行监测,具有耐腐蚀、防水等特点。 土壤电导率传感器:用于监测土壤的电导率,可以反映土壤的盐分含量,对于土壤盐碱化的预防和治理具有重要意义。 2.2 智能监控主机 监控主机:作为系统的核心控制单元,负责接收传感器节点上传的监测数据,并通过RS485、以太网或GPRS等方式上传至监控平台。同时具有液晶显示屏、数据存储和报警功能,可以实现对温室内部环境的实时监测和控制。 2.3 软件平台 监控平台:提供实时曲线、历史曲线、数据记录等功能,可通过电脑或手机实时查看温室内部环境数据,并在数据异常时进行声光报警和远程短信报警。 云平台:将监测数据上传至云端,实现对温室环境的24小时不间断监测,并提供数据导出、远程web访问等功能,方便用户随时随地查看和管理温室环境。 3. 系统特点 全面监测:系统覆盖了温室内部的各项关键参数,可以全面监测温室环境的变化。 智能控制:通过智能监控主机对温室内部设备进行自动控制,实现温室环境的精细调节。 远程监控:用户可以通过监控平台随时随地查看温室环境数据,及时发现和处理异常情况。 报警功能:系统具有声光报警和远程短信报警功能,在环境异常时能够及时通知相关责任人员进行处理。 可扩展性:系统采用模块化设计,传感器节点和监控主机均支持多种通信方式,可以根据用户需求进行灵活扩展和定制。 4. 应用场景 温室大棚环境监测控制系统可广泛应用于农业、园艺、畜牧业等领域,特别适用于需要特殊环境要求的大棚种植和养殖场所。通过实时监测和智能控制,可以提高作物的产量和品质,降低能源和资源的消耗,实现生态环境的可持续发展。 5. 结语 温室大棚环境监测控制系统是一种集成了物联网、传感器和智能控制技术的先进系统,可以实现对温室环境的精细监测和智能控制,为农业生产提供了科学的依据和技术支持。相信随着技术的不断发展和应用,温室大棚环境监测控制系统将在农业生产中发挥越来越重要的作用,为人类的粮食安全和生态环境保护做出积极贡献。 --- ### 453. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在当今社会,环境污染已经成为人们日常生活和工作中不可忽视的问题之一。特别是噪声和扬尘污染,不仅影响着人们的健康和生活质量,也对城市环境产生了负面影响。有鉴于此,研发出一套智能化的噪声扬尘监测系统,以解决这一严峻的环境问题。 全面监测环境 该系统采用先进的传感器技术和物联网技术,可以实时监测城市各个关键区域的噪声和扬尘浓度,包括工地、道路交通、工厂园区等地方,实现对环境污染的全面监测。 数据分析与预警 监测系统不仅可以获取环境数据,还能通过数据分析算法对监测数据进行处理和分析,提供精准的预警和分析报告。这些报告为相关部门提供了科学依据,以制定有效的环境治理和管理措施。 远程监控与管理 监测系统支持远程监控和管理功能,相关人员可以通过网络平台随时随地查看监测数据,及时采取应对措施,保障环境质量和人民健康。 多样化应用场景 该系统不仅适用于城市建设和工业生产领域,还可以应用于交通运输、建筑施工等多个领域。通过在不同领域的应用,该系统为各行各业提供了全面的环境监测和管理服务。 应用案例 这套噪声扬尘监测系统已经在多个领域得到了广泛应用,取得了显著的效果。比如,在城市建设工地,该系统帮助管理者及时监测和控制施工噪声和扬尘,保障周边居民的生活质量。 在工业生产企业,该系统帮助企业合理安排生产过程,降低环境污染,提升企业形象和竞争力。在交通运输领域,该系统帮助交通部门监测道路交通噪声和车辆尾气排放,优化交通组织和规划。 结语 噪声扬尘监测系统为环境保护和城市管理提供了一种全新的解决方案,将科技与环保相结合,为人们创造了更清洁、更健康的生活和工作环境。相信随着技术的不断进步和应用的不断推广,这一智能监测系统将为社会和人类的可持续发展做出更大的贡献。 --- ### 454. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 什么是机房机柜温湿度监测? 机房机柜温湿度监测是通过安装在机柜内的传感器和监控设备,实时监测机房内部的温度和湿度变化。这样的监测对于保持机房内部设备的正常运行非常重要,因为过高或过低的温度湿度可能会导致设备故障或损坏。 项目概述 系统背景 随着信息网络技术的不断发展,各类规模大小不等的网络设备机房广泛分布于用户各分支机构所在地域。然而,由于缺乏与网络规模相匹配的运维系统,无人值守机房的物理运行环境状况、动力配电状况、设备运行状况、人员活动状况以及消防状况的变化难以及时发现和处理。因此,实现一套完善的机房机柜温湿度监测系统至关重要。 系统概述 机房温湿度监测系统包括两个主要部分:机房温湿度变送器和环境监控主机。温湿度变送器具有液晶显示,可实时监测温湿度,并采用标准ModBuS-RTU通信协议,RS485信号输出,通信距离最大可达。该变送器可内置于机柜内,或通过磁铁吸附于机柜表面,安装方便,适用于通讯机房、仓库楼宇等场所。 环境监控主机为多功能监控设备,支持多种上传数据方式,具备液晶显示屏和可外接LED屏等特点。其功能包括数据存储、浸水检测、ModBus-RTU主站接口等,可接入各类485变送器。 据,支持视频查看、告警功能 系统组成 环境监控主机 环境监控主机是整个监测系统的核心。其功能包括: 支持各种传感器接入,包括温湿度传感器、漏水检测传感器等。 提供数据存储功能,可存储大量的监测数据,支持查询和导出。 提供用户友好的界面,实现实时监测和远程控制。 技术参数 机柜式温湿度变送器 机柜式温湿度变送器是安装在机柜内部的传感器设备,主要用于监测机柜内部的温度和湿度变化。其特点包括: 采用进口传感器,具有较高的精度和响应速度。 支持标准的ModBus-RTU通信协议,可与环境监控主机进行数据交换。 设备背面具有四个强力磁铁,方便安装在机柜上。 技术参数 功能特点 实时监测 系统能够实时监测机房内部的温度和湿度变化,并通过液晶显示或软件界面实时展示数据。 报警功能 系统能够设置温湿度的上下限,并在超出预设范围时发出警报,提醒运维人员及时处理。 远程监控 用户可以通过PC端、APP客户端等方式远程监控机房的温湿度情况,随时随地掌握机房的运行状态。 数据导出 系统支持将监测数据导出为Excel等格式,方便用户进行进一步的数据分析和处理。 使用场景 该机房机柜温湿度监测方案适用于各种场景,包括但不限于: 企业数据中心:保障服务器和网络设备的正常运行。 通信基站机房:确保通信设备的稳定性和可靠性。 仓储物流中心:保护存储的物品不受湿度和温度影响。 商业办公楼等:维护办公环境的舒适度和设备的正常 结语 机房机柜温湿度监测方案通过硬件设备和软件平台的结合,实现了对机房环境的实时监测和远程管理,为用户提供了便捷的监控解决方案。 --- ### 455. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着现代农业技术的快速发展,智能化在农业生产中的应用变得日益重要。特别是在食用菌产业中,由于其种植过程复杂、对环境要求极为严格,传统的种植方法已难以满足高效率和高产量的需求。基于此背景,MQTT物联网技术被引入到食用菌的养殖过程中,旨在通过科学化、标准化、现代化及智能化的管理手段,显著提升食用菌的产量和品质。 系统概述 MQTT物联网菌菇养殖智能监控系统是一个专为菌菇生产温室大棚、厂房设计的全程智能化控制解决方案。该系统通过精准控制菇房内的温度、湿度、二氧化碳浓度等关键环境因素,以满足食用菌在不同生长阶段的特定需求,从而创造出最适宜的生长环境。这一智能化控制显著提高了食用菌的生产效率和产品质量。 核心功能与技术 环境监测与调控 智能环境传感器:采集空气温度、湿度、二氧化碳浓度等数据,确保环境参数的实时监控。 菌菇基质监测:通过专用传感器监测菌菇基质的营养状况,优化菌菇的生长环境。 环境调控设备:包括制冷、加湿、通风、光照等设备,根据传感器数据自动调节环境条件,保障菌菇的健康生长。 通信技术 MQTT物联网平台:利用4G、无线WIFI通讯技术,实现设备的远程控制和监控数据的实时传输,确保信息交互的高效性和稳定性。 智能控制柜 数据采集与处理:连接环境调控设备,采集智能传感器的数据,内置人工智能算法和PLC智能逻辑控制功能,实现环境条件的自动调节。 人机交互界面:提供大尺寸组态屏,支持实时环境数据查看和手动控制,优化用户操作体验。 控制策略与优势 控制策略 自动控制:根据食用菌生长阶段自动调整环境条件,无需人工干预。 手动/远程控制:支持现场手动控制和通过MQTT物联网平台的远程控制,提高操作灵活性。 集中监控:实现对多个菇房环境的集中管理,简化监控流程,提升管理效率。 系统优势 提高产量与品质:通过精确控制生长环境,大大提升食用菌的产量与品质,满足市场高端需求。 节省人工成本:24小时的自动监控与控制减少了对人工的依赖,特别是在环境调节和疾病预防上,降低了大量的劳动力成本。 智能化生产:利用先进的物联网技术,实现生产过程的智能化,从基质准备到菌菇收获的每一步都可通过数据分析优化,提升生产效率。 可靠性增强:系统采用稳定的通讯技术确保数据传输的可靠性,同时,智能控制柜和环境调控设备的高质量构造减少了故障率,保障了生产的连续性。 远程监控与管理:通过手机APP或监控中心平台,无论身处何地,生产者都能实时掌握菇房内的环境信息及设备运行状态,及时调整生产策略,实现真正的指尖上的农业管理。 应用场景 MQTT物联网菌菇养殖智能监控系统适用于不同规模的菌菇生产企业,从小型家庭式菌菇房到占地数千亩的大型菌菇生产基地。该系统尤其适合需要精细化管理和追求高产出高品质的现代农业生产模式。 结语 随着人们对食品安全和品质的日益重视,传统的食用菌生产方式已逐渐不能满足市场需求。MQTT物联网菌菇养殖智能监控系统的出现,为食用菌产业带来了革命性的改变。通过高度的自动化与智能化管理,不仅提高了生产效率和产品质量,还实现了生产过程的科学化和数据化,为食用菌产业的可持续发展奠定了坚实的基础。随着技术的不断进步和应用的不断拓展,未来的菌菇养殖将更加智能、高效和环保,为消费者提供更安全、更优质的食用菌产品。 --- ### 456. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 引言 在现代农业生产中,利用智能技术优化温室大棚的管理变得尤为重要。MQTT物联网智能玻璃温室大棚系统集成了多种监测和控制系统,实现了农业生产的高度机械化和智能化,从而提高农业经济模式的工厂化水平,优化盈利和回报。 系统概述 MQTT物联网智能玻璃温室大棚系统包括: 环境监测系统:利用工业级物联网传感器监测空气温湿度、光照度、CO2浓度等,数据通过有线485或无线LORA方式传输至云平台。 土壤墒情监测系统:通过土壤温湿度、pH、EC传感器监测土壤条件,指导精细化灌溉。 遮阳系统:自动根据光照度和室内温湿度调整,有效管理光照和室内气候。 通风管理系统、湿帘降温系统:自动调节大棚内气流和温度,保持适宜的生长环境。 水肥系统:实现精准灌溉和施肥,优化资源使用。 补光系统、CO2调控系统:根据作物需求调节光照和CO2浓度,促进生长。 视频监控系统:实时监控大棚内部状况,提高管理效率。 系统特点 全方位监控与调控:覆盖从环境到土壤的各个方面,确保作物生长环境的最佳状态。 高度自动化与智能化:通过MQTT物联网平台实现自动化控制,减少人力需求,提高管理效率。 数据驱动的决策支持:收集和分析数据,为生产决策提供科学依据。 易于操作的监控平台:支持手机APP、PC端和LED显示等多种监控方式,实现数据的实时监控和管理。 操作与控制 远程控制:用户可以通过手机app或电脑监控平台查看环境数据并手动控制设备。 现场手动控制:现场触摸屏和手动按键为紧急或特殊情况提供操作手段。 自动控制工艺:根据作物生产工艺自动调整大棚内环境,实现全生命周期的智能管理。 监控平台 多维度监控展示:实现实时数据监控,视频画面查看,以及数据动态展示。 数据管理与分析:提供数据记录、报表导出和设备管理功能,优化生产过程。 报警与通知:通过多渠道报警通知机制,确保及时响应异常情况。 用户权限管理:灵活的账号管理支持多用户操作,满足不同角色的管理需求。 结语 MQTT物联网智能玻璃温室大 棚系统通过集成高度先进的监测与控制技术,实现了对温室大棚的全方位智能化管理。这一系统不仅提高了农业生产的效率和可控性,还为实现高效、可持续的现代农业提供了强有力的技术支持。通过优化此文,我们更清晰地展示了系统的组成、特点及其在智能农业中的重要应用,突出了MQTT物联网技术在现代农业中的核心作用。 --- ### 457. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、引言 在现代农业生产中,利用高科技手段对大棚进行精准管理成为提高产量和质量的关键。特别是塑料薄膜温室大棚,因其轻便、成本低廉、结构遮光率小和使用寿命长等优点,被广泛应用于各种作物的栽培。然而,为了实现温室大棚的集中管理和环境条件的精确调控,需要采用先进的监控系统。 二、MQTT物联网智能薄膜连栋大棚监控系统简介 MQTT物联网智能薄膜连栋大棚监控系统基于先进的物联网技术,集成了现代化的传感器终端、通讯技术、控制终端、环境调控设备和监控平台。该系统能够实现对温湿度、水肥、光照等关键环境参数的实时监测和自动调控,优化作物生长条件,提高作物产量和质量。 三、系统组成和工作原理 环境监测传感器:包括CO2浓度、光照度、空气温湿度和土壤温湿度传感器,实现对大棚内环境的全方位监测。 环境调控设备:涵盖外遮阳系统、内遮掩系统、内保温系统、湿帘风机强制通风降温系统、顶部通风系统、供暖系统和配电/控制系统,根据传感器数据自动调节大棚内环境。 智能控制柜:通过采集传感器数据,并利用内置的智能算法和MQTT物联网通讯协议,智能控制柜可以迅速做出精准的控制决策,自动调节环境控制设备,以保持大棚内的环境条件最适宜作物生长。控制柜支持RS485有线和无线LORA通信方式,确保数据传输的高效和稳定。 MQTT物联网监控平台:平台不仅实时展示大棚内的环境参数,还允许管理人员远程调整控制策略,进行数据分析和决策支持。平台的大数据和边缘计算能力,可以处理来自多个大棚的海量数据,实现智能预警和生产流程优化。 四、系统特点和优势 精准的环境控制:通过高精度传感器和自动调控设备,系统能够精确调整大棚内的光照、温湿度、CO2浓度等关键参数,为作物生长创造理想条件。 高效的资源利用:智能调控系统能够优化水肥使用和能源消耗,降低生产成本,提高资源利用效率。 远程监控和管理:MQTT物联网平台支持远程监控和操作,使得大棚管理更加便捷,减少人力成本。 数据驱动的决策支持:平台收集和分析的大数据为作物的生产工艺优化提供科学依据,实现精准农业。 五、应用场景和效益 MQTT物联网智能薄膜连栋大棚监控系统适用于各种规模的现代农业生产,包括蔬菜、花卉、药材等多种作物的栽培。通过实现精细化管理,该系统不仅可以显著提高作物的产量和质量,还可以有效应对极端天气带来的风险,保障农业生产的稳定性和可持续发展。 六、结语 随着物联网技术的不断进步和应用拓展,MQTT物联网智能薄膜连栋大棚监控系统将成为现代农业不可或缺的工具。通过高度集成化和智能化的解决方案,它能够有效提升农业生产的自动化和智能化水平,带来更高的经济效益和环境效益。 --- ### 458. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 方案概述 森林防火气象站旨在通过先进的监测技术和智能预警系统,及时感知并应对森林火灾的威胁,保护森林资源和生态环境。本方案将结合自然气候和人为因素,提供全面的防火措施,确保森林防火工作的高效运行。 解决方案特点 全天候监测:地球绿色屏障【守门员】-森林防火气象站通过24/7的监测系统,实时感知森林环境的温度、湿度、风速、降水量等关键指标,及时预警火情。 多功能传感器:配备多种传感器,包括风力、风速、风向、空气温湿度、大气压力、光照度、雨雪、雨量等,全面监测气象要素,为火情预测提供数据支持。 双供电系统:支持220V市电和太阳能供电,确保设备的稳定运行和持续监测,即使在市电断电情况下也能正常工作。 远程监控与控制:通过4G多功能通信接口和RJ45网口,实现数据实时上传至环境监控云平台,并支持远程控制功能,管理员可随时随地监控和管理。 智能预警系统:环境监控云平台配备LED大屏,自动轮播监测数据,并提供火险等级评定和防护计划,实现智能预警和应急响应。 方案优势 全面性:涵盖自然气候和人为因素,全方位保护森林安全。 高效性:实时监测、智能预警,提高了对火情的感知和响应速度。 稳定性:双供电系统保证了设备的稳定运行,适应不同环境条件下的使用。 智能化:通过远程监控和控制,实现了对设备的智能化管理,提高了工作效率和便利性。 可扩展性:支持多种传感器和外部设备接口,方便根据需要进行扩展和升级。 总结 地球绿色屏障【守门员】-森林防火气象站是一套集成化的解决方案,旨在为森林防火工作提供全方位的支持和保障。通过多种先进技术的应用,将极大地提高森林防火的效率和可靠性,保护森林资源,维护生态平衡。 --- ### 459. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 项目概述 1.1 项目背景 森林火灾频发,对生态环境和人类生命财产造成巨大危害。 中国每年平均发生森林火灾约1万多次,烧毁面积巨大。 森林防火工作始终实行“预防为主、积极消灭”的方针。 1.2 设备原则 标准化、先进性、适用性、实用性、稳定性、可维护性。 建设信息化基础,构建智能化监测预警体系。 1.3 设计依据 《森林火险气象等级》标准。 相关地方政府发布的森林防灭火工作通知。 1.4 森林防火气象站拓扑图 包括通信服务器、LED大屏显示等设备。 2. 方案概述 2.1 方案简介 森林防火气象站包括立杆、电控镇、气象仪器、人体探测器、语音报警模块等部分,可实现对森林环境的实时监测与报警。 2.2 数据上传方式 通过4G传输实时数据,包括各种气象要素和全景视频图。 2.3 设备参数 支持多种供电方式,采用太阳能供电,具备数据采集通信接口和继电器输出等功能。 3. 设备优势 3.1 外观色彩 设计醒目的橙色,易于在森林中被发现 3.2 监测要素 监测风速、风向、雨量、温度、湿度等气象要素,提供科学依据。 3.3 视频监控 搭配监控摄像头,实现远程监控,及时发现火源。 3.4 语音提醒 通过语音报警模块进行警示,防止野外用火等行为。 3.5 安装方式 支持多种安装方式,适应不同地形环境。 3.6 供电方式 支持市电供电、太阳能供电和蓄电池供电等多种方式,保证设备持续运行。 4. 综合环境监控云平台 4.1 概述 提供实时数据监控、地图显示、告警功能、历史数据查询、继电器控制等功能的云平台。 4.2 功能介绍 支持实时监控、地图显示、超限告警、视频监控、历史数据查询等功能。 4.3 手机APP 提供手机APP,方便用户随时随地监测设备状态和数据。 5. 总结 综合以上方案,可以实现对森林防火气象的全面监测和预警,为防火决策提供科学依据,降低森林火灾的发生率和损失。 --- ### 460. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 项目背景 在当今数字化时代,银行办公区域的管理需要更高效、智能化的解决方案来提高工作效率、节约能源,并确保安全和舒适性。为此,我们提出了一套综合的智能化方案,旨在通过物联网技术和智能控制系统,实现对银行办公区域空调的智能管理和控制。 方案概述 我们的方案结合了物联网技术、红外人感技术、定时延时器以及智能控制主机等硬件设备,同时配合定制的软件平台,为银行办公区域提供了一套智能化的空调管理系统。该系统可以实现远程控制、自动关闭、智能调节等功能,以提高能源利用效率和工作环境舒适度。 硬件简介 人感红外探测器:用于监测办公区域内人员活动,当监测到无人时,系统自动关闭空调。 定时延时器:配合人感红外探测器使用,用于设置延时关闭空调的时间。 空调控制网关:用于连接空调系统,并与智能控制主机通讯,实现远程控制和状态反馈。 智能控制主机:作为系统的核心,负责接收和处理传感器数据,控制空调的开关、温度调节等功能。 软件介绍 我们定制的软件平台具有以下特点: 界面定制化:可以根据银行的需求定制登录页面背景和系统名称,使其适应不同的项目需求。 区域控制:支持分楼栋、分层级的区域划分,实现对不同区域的智能控制。 用户权限管理:可以设置用户操作权限,确保只有授权人员才能对特定区域设备进行控制。 操作日志记录:系统会记录用户的操作日志,方便管理人员进行查询和监控。 隐私保护:采用被动式反向链接非云端控制逻辑,保护用户隐私和数据安全。 支持部署方式:可选择线上版本或线下版本一次性买断部署,根据实际需求灵活选择。 整体工作流程 人感红外探测器监测到办公区域有人活动。 红外信号传输至智能控制主机,触发定时延时器开始计时。 若一定时间内未再监测到人员活动,定时延时器自动关闭空调。 智能控制主机将空调状态信息传输至空调控制网关。 用户可通过手机端或PC端的软件平台远程控制空调的开关、温度调节等功能。 效果与优势 节能降耗:通过智能控制,实现了在不影响办公环境舒适度的前提下,有效降低能源消耗。 提升效率:远程控制功能使得管理人员可以随时随地对空调进行监控和调节,提高了管理效率。 舒适安全:智能化的空调管理系统可以根据人员活动情况自动调节,提供舒适的工作环境,并确保安全性。 综上所述,我们的智能化方案将为平安银行办公区域提供高效、智能的空调管理解决方案,实现了节能、提升效率和舒适安全的目标。 --- ### 461. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 智慧公园+智慧步道+智慧园+智慧社区整体解决方案 概述 本方案旨在为城市提供一套完整的智慧化解决方案,涵盖智慧公园、智慧步道、智慧园区和智慧社区四大板块,以AI技术为核心,利用物联网、云计算、大数据等新一代信息技术,打造安全、舒适、便捷、智能的城市环境。 方案详情 智慧公园 建设智慧健身路径、智慧健身步道,为市民提供便捷的健身服务。 利用AI技术,进行人脸识别、行为分析等,提升公园的安全管理水平。 建设智慧导览系统,为游客提供便捷的游览服务。 智慧步道 利用物联网技术,采集步道上的环境数据、运动数据等,为市民提供健康指导服务。 建设智慧安防系统,保障步道安全。 建设智慧驿站,为市民提供休憩、充电等服务。 智慧园区 建设智慧安防系统,保障园区安全。 建设智慧办公系统,提升园区办公效率。 建设智慧能源管理系统,节约能源。 智慧社区 建设智慧安防系统,保障社区安全。 建设智慧物业管理系统,提升物业管理效率。 建设智慧生活服务平台,为居民提供便捷的生活服务。 结语 本方案为城市提供了一套完整的智慧化解决方案,可有效提升城市治理水平和居民生活质量。sharemore_vert --- ### 462. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 航海梦想的现实:46米游艇智能系统完美融合 本方案旨在为46米游艇提供一套完整的智能化解决方案,涵盖以下系统: 中控主机及触控终端 有线及无线局域网 高清、网络视频监控及防盗报警系统 多房间HFI背景音乐音乐 智能照明系统 电动窗帘及控制系统 智能环境控制系统(空调、新风) 影院及影院控制系统 方案详情 中控主机及触控终端 强大的逻辑编程 可持续扩展升级 系统整合联动 稳定、快速、强大、灵活的控制主机,是每个控制系统的基石 有线及无线局域网 商用典型组网方案 互联互通 无缝切换 高清、网络视频监控系统 全套的全高清网络监控解决方案 清晰 抗干扰 不随距离衰减 多房间HFI背景音乐音乐 可扩展在线音乐点播,与移动客户端同步收藏列表 通过蓝牙AirPlay播放移动设备上的音乐 智能照明系统 营造舒适氛围 可根据场景设置不同的灯光模式 电动窗帘及控制系统 可通过触控屏或手机/平板APP控制 实现全开、全关、半开等功能 智能环境控制系统(空调、新风) 可通过触控屏或手机/平板APP控制 实现温度、湿度、风速等调节 影院及影院控制系统 提供高品质的影音体验 可通过触控屏或手机/平板APP控制 总结 本方案为46米游艇提供了一套完整、可靠、智能的解决方案,可满足用户的各种需求,提升游艇的舒适度、安全性、娱乐性。 以下是一些具体的实施建议: 选择知名品牌的设备,确保系统的稳定性和可靠性。 由专业人员进行安装和调试,确保系统的正常运行。 定期维护和保养,确保系统的最佳性能。 希望本方案能够帮助您打造一艘舒适、安全、智能的游艇 --- ### 463. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 行业发展与背景 电力安全生产是电力行业的基石,相关国家标准和行业规范明确要求了电力安全工器具的管理。近年来,随着技术的不断创新,智能化管理技术逐渐应用于电力安全工器具的管理领域。其中,高频RFID联网技术是一项重要的创新,它通过RFID标签和射频识别装置实现了工器具的智能化管理。 系统功能介绍 智能管理系统主要包括以下功能: 温湿度管理:系统监测库房内温湿度,确保工器具存放环境符合相关要求 工器具管理:利用高频RFID识别技术,对工器具进行全生命周期的监测与管理,包括借用、归还、试验等。 视频监控:配备红外视屏监控系统,实现对库房的全天候监控。 报警系统:系统具备报警功能,能够及时发现异常情况并进行警报。 人脸识别门禁:采用人脸识别技术,实现对库房的智能门禁管理。 工器具台账管理:建立工器具的台账管理系统,自动记录工器具的使用情况和状态。 货架设计:根据工器具的不同类别和电压等级,设计合适的货架存放设施,实现精细化管理。 工器具状态信息可视化管理:通过状态指示灯和提示灯,实现对工器具状态的可视化管理。 工程实施案例 系统已在多个项目中成功实施,包括贵州毕节、清镇,杭州等地的库房,以及江苏盐城的车库等,为电力安全工器具的智能管理提供了有效解决方案。 这些系统功能使得电力安全工器具管理更加智能化、精细化,提高了管理效率和安全性,为电力行业的安全生产提供了可靠保障。 --- ### 464. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、酒店智能化系统需求分析 酒店的智能化系统建设必须紧密围绕酒店的经营理念、服务模式和程序来进行,决不是生搬硬套的系统堆砌。因此,系统的设计必须围绕以客人的住店感受和酒店管理的高效有序这两个中心出发来综合考虑和配置。 二、系统设置 根据智能建筑设计标准《GB/T 50314—2013》规范要求,酒店项目智能化系统主要包含以下几个系统: 信息设施系统 电话交换系统 信息网络系统 综合布线系统 室内移动通信覆盖系统 有线电视及卫星电视接收系统 广播系统 会议系统 信息引导及发布系统 综合管路系统 信息化应用系统 酒店管理系统 客房控制管理系统 酒店客房门锁系统 楼宇自动化控制及能耗管理系统 建筑设备管理系统 智能照明系统 公共安全系统 入侵报警系统 视频监控系统 出入口控制系统 电子巡更系统 无线对讲系统 停车场管理系统 机房工程 机房布置与设计 网络设备安装与维护 数据中心建设与管理 服务器架设与运维 数据存储与备份管理 网络安全与防护措施 三、各系统简单介绍 3.1 信息设施系统 3.1.1 电话交换系统 电话交换系统能完整地把传统的语音通信、语音信箱、多方电话会议、IP 技术、宾馆酒店服务软件、酒店资产管理系统接口、ISDN 应用等当今最先进的计算机通信技术集成一起.提供了众多的系统功能和全套的宾馆服务业务,如:语音提示、音乐保持、按姓名拨号、多方电话会议、客人的入住登记和退房、叫醒服务、免打扰、房态管理等功能。系统采用数字程控交换机,由多少个话务台具体由酒店管理公司确定。 3.1.2 信息网络系统 酒店信息网路建设一般以固定以太网为主、无线以太网为辅的酒店计算机网络结构。 (1)有线网络 酒店有线网络分为管理网和客房网,前者主要为酒店运营及酒店管理服务,后者主要为客人服务。为保证办公计算机网络的可靠性,两套计算机网络系统做物理隔离,即为两套计算机网络系统分别配置核心交换机、楼层接入交换机等。办公计算机网络独立成系统, 通过 PMS 接口与 Internet 连接。 (2)无线局域网 酒店的所有区域都可以通过无线局域网上网,要求支持无线局域网协议802.11/b/g。无线局域网的使用: 客人:首先,必须满足客人使用需求“零设置”,即客人无线终端接入无线网络时无需做任何设置,通过酒店代理服务器(酒店界面)直接指向 INTERNET.在酒店入住的客人可以利用配有无线终端产品的笔记本电脑自由地接入互联网,提高其办公效率。同时,酒店还可实现无线网络与现有有线网络之间无缝连接,客人无论是在客房、会议室、餐厅还是花园都可以随时接入互联网。 酒店员工:使用无线终端经认证后可接入酒店网络,进行授权范围内的访问及操作.也可以使用无线语音终端进行内部免费通话。 3.1.3 综合布线系统 综合布线系统就是为了顺应发展需求而特别设计的一套布线系统.对于现代化的建筑来说,就如体内的神经,它采用了一系列高质量的标准材料,以模块化的组合方式,把语音、数据、图像和部分控制信号系统用统一的传输媒介进行综合,经过统一的规划设计,综合在一套标准的布线系统中,将现代建筑的三大子系统有机地连接起来,为现代建筑的系统集成提供了物理介质.可以说结构化布线系统的成功与否直接关系到现代化的建筑的成败,选择一套高品质的综合布线系统是至关重要的。 根据国际标准 ISO11801 的定义,结构化布线系统可由以下系统组成: 工作区子系统、水平子系统、管理子系统、干线子系统、设备间子系统、建筑群子系统。 布线以 6 类非屏蔽双绞线为主,主干采用多模万兆光纤。光纤芯数充分考虑了冗余,数据与语音水平线缆全部采用低烟无卤六类非屏蔽四对八芯双绞线。水平端接设备采用 24口模块化配线架,数据中心采用机架式光纤配线架,管理间配线架与网络交换机采用六类非屏蔽跳线。其中语音主干采用 3 类大对数电缆。 3.1.4 室内移动通信覆盖系统 本系统由通信运营商免费实施。 地下室及所有电梯对移动电话信号有很强的屏蔽作用,因此,必须通过在室内分布一定数量的天线和合理的功率分配来解决本项目室内各区域信号弱、质量差、切换频繁或话务拥挤的问题。 根据目前的现状,需在酒店内建设 GSM、CDMA、3G 、PHS 的无线覆盖系统。 3.1.5 有线电视及卫星电视接收系统 有线电视及卫星电视接收系统的设计和使用是智能子系统的一个重要组成部分。酒店的完美服务,涵括丰富多样的娱乐休闲生活和获取了解最新国内外新闻的多方位途径,一个设计、组合合理先进的有线电视及卫星电视接收系统,对酒店工程的品质定位,服务口碑,是一个良好的促动,也是全方位服务体系的重要组成。 有线电视及卫星电视接收系统主要包括两个方面: (1)传统的有线电视系统:节目源一般由自办节目、卫星电视和城市有线网提供, 具体的节目源要求由酒店管理公司提出,并在调研当地数字电视节目源的基础上再做确定。 (2)VOD 电视点播系统:通过组建的综合布线系统的线路,通过网络方式访问存储 在服务器里的电视、电影节目及其他节目进行自由点播,给客人以优质、全方位的服务。 3.1.6 广播系统 广播系统主要能同时完成背景音乐和公共广播(包含业务广播和消防广播)两项功能.为在酒店内营造一个舒适、幽雅的环境,背景音乐广播已成为不可缺少的基础设施。主要分布于酒店大堂、咖啡厅、餐厅、公共走廊(客房层走廊不建议设置)、SPA 区、健身房、电梯前室等公共区域及会议区、客房。当发布通知时,播音人员可将当前的广播状态切换成业务广播状态,进行消息、通知和人流导引的发布.而当有火灾事故发生时广播可在发生消防火警时将背景音乐或业务广播状态紧急切换至消防广播状态且具有最高优先权。消防信号由每个楼层的消防信号发生器产生并输送到主机设备中,触发主机系统发出切换信号。因不同区域对背景音乐的音乐源有不同的需求,如酒店大堂、咖啡厅、餐厅、会议区等区域需要幽雅、轻松的音乐,SPA 区需要愉悦、放松的音乐,健身房场所需要播放一些节奏感较强的音乐等等,所以选用的系统必须是多音源系统,并在现场可根据需要选择音乐源和调节音量。 3.1.7 会议系统 酒店会议区包括各种大小会议室、多功能厅、宴会厅等,今后需满足会议、报告、产品发布、歌舞表演、走台、大型宴会等各种需求,并且中型会议室、多功能厅、宴会厅等面积较大的房间应能根据客户需要灵活布局,各种音、视频系统必须与之相适应,并通过中央控制系统和灯光系统的配合使用,使酒店的管理人员能通过简单的操作(如一键制)完成系统的模式转换和场境变换. 本系统是一个专业性很强的综合设计,除本系统的扩声、视频、控制等专业设计外, 还涉及建声、装饰、灯光等其他专业.会议区音、视频系统所涉及的系统主要包括: 会议发言系统 同声传译系统 会议扩声系统 会议摄录系统 会议控制系统 会议显示系统 音视频传输及控制系统 会议灯光系统 3.1.8 信息引导及发布系统 针对酒店的人员不同,主要包括外宾、各级领导及其他相关的人员,信息引导及发 布系统,主要包括两个部分: (1)LED 信息发布系统 当有外宾及领导来酒店进行商务会谈及考察时,可以在 LED 屏上显示欢迎致辞等字 样,替代传统的条幅;在平时,可以显示天气预报、时间等信息,显示形式可以为文字或图画 等方式. (2)触摸屏查询系统 入住客人可以通过触摸屏的查询对本酒店的场所介绍、客房介绍及其他的相关情况 进行介绍,便于了解,为酒店树立一个良好的形象. (3)信息引导系统 通过安装电梯厅及走廊间的信息引导屏,可以对国内外资讯、酒店情况、会议进行 情况等进行引导。 3.1.9 综合管路系统 本系统是指酒店智能化系统的路由通道,包括竖向、水平的金属桥架、水平金属管路等。 桥架部分内容需经点位估计后进行容量估算,按照相关规范,桥架内线缆填充率不超过 40%,管路内的线缆填充率不超过 50~60%。 3.2 信息化应用系统 3.2.1 酒店管理软件 本系统主要是酒店管理公司确定,一些知名酒店管理公司都有自己常用或合作单位的软件。 该系统建立在广域网、局域网上,主要用于向酒店管理者提供现代化经营手段,目的使酒店经营高效、先进、科学;用于向酒店管理者提供高质量管理手段,如智能办公系统、智能节能系统、智能采购网络、智能人员管理系统、智能物耗管理系统、智能消费管理系统、智能菜单管理系统等等,目的是使酒店办公、物耗、能耗、人员成本等降到最低,使用效率最高,创造良好效益。PMS 必须提供与程控交换机、客房控制管理系统的通信接口。 酒店管理软件一般由前台、后台、接口系统等组成,一般的酒店管理软件需提供以下接口: 1.财务接口:与财务软件接口,实际酒店财务管理。 2.一卡通接口:通过与酒店 IC 卡/磁卡相连,实现一卡通管理。凭 IC 卡/磁卡在酒 店实现挂帐消费,统一结算,并实现内部 IC 卡/磁卡管理。 3.Internet 接口:为客人联接 Internet,建立 Internet 帐户,酒店上网与各旅 行社建立网上业务联系,并实现网上预订。 4.POS 机接口:在各收费点可以用 POS 机进行收银,可开启 POS 银箱,驱动 POS 棒显。 5.户籍发送:通过与公安局的户籍管理系统相连,自动把公安局所需户籍数据发 送过去。 6.VOD 视频接口:与酒店 VOD 系统连接,客户 VOD 的消费自动记到其帐户下。 7.网上预订 8.办公自动化 OA 系统 3.2.2 客房控制管理系统 客房控制系统是在微电脑客房智能控制器的基础上,通过网络将酒店各客房的状态信息实时传送到酒店的客房服务中心、楼层服务台、工程部等职能部门,酒店相关部门便可。 根据实际情况有针对性地对客人提供优质服务;系统数据库定时存贮各客房状态发生变化的时间及服务人员的服务响应时间,以便为相关管理部门的管理提供可靠、公正、科学的依据,此外系统还可根据实际需要,通过网络对各客房相关设备进行远程控制。 主要功能为: 对台灯、阅读灯、房灯、落地灯、镜前灯、空调等强电控制; 对请清理、勿扰、SOS 呼叫、服务呼叫、快速退房、房间有无人检测、房门关闭检测、房间灯故障检测等弱电控制;对以上的所有强、弱电信息能准确快速地传递到客房服务中心.酒店管理人员不需要进入房间就能监控所有的客房状况. 本客房智能控制系统既体现了酒店的个性化、智能化、绿色化特点,也实现了传统与高科技的完美统一,全面提升了酒店的管理,为客人提供全方位的超值服务. 3.2.3 酒店客房门锁系统酒店客房门锁采用何种门锁,需管理公司确认,该门锁的采用与客房管理系统实现功能有重大联系。 客房门锁系统由电子门锁、IC 卡、发卡器、记录卡、门锁管理软件等组成。系统考虑在每个门上设置一把离线式电子门锁。 根据客房内使用情况的不同,我们可以将系统的卡权限分别作如下设置。 客人卡:供入住的宾客开门使用,只能在有效时间内打开所对应房号的房门,并可作为客人房间内的插卡取电用。 应急卡:最高级别的管理开门卡.供酒店内部管理人员使用,在紧急情况下打开酒 店客房的门锁。 清洁卡:供酒店内部的服务员工或楼层员工使用; 初始化卡:供酒店管理人员使用,用于将相应密码与系统标识的门锁设置为初始化 状态。 汇总卡:供酒店管理员使用,用于读取门锁的开锁记录。 3.3 楼宇自动化控制及能耗管理系统 3.3.1 建筑设备管理系统 酒店机电设备较多且较分散,设备管理和维护的自动化必然成为今后物业管理的重要课题;另外,酒店的空调系统能耗较大,因此,在保证舒适的前提下,如何优化控制,协调管理,节约能源也将成为建筑智能化系统实施的必要手段,实现在最低能耗(使用成本)的前提下,建筑使用价值的最大化。建筑设备管理系统利用计算机和现代通讯控制技术,对酒店内各种机电设备按照管理操作者的意愿进行集中管理和优化控制,最终达到区域各种机电设备协调有序地工作,并在满足区域各种功能前提下,尽可能减少相关的管理人员和最大限度地节约能耗,降低酒店的管理和营运费用。 系统主要监控内容如下: 冷热源系统(状态监测) 空调机组、新风机组(温、湿度调节、运行状态及启停控制) VAV 系统(温、湿度调节、新风和回风的比例调节、运行状态及启停控制) CAV 系统(温、湿度调节、运行状态及启停控制) 关于对客房温、湿度及噪声的控制 对室内游泳池空调系统的控制 送排风系统(各风机的运行状况及启停控制,消防用风机由消防负责考虑) 给排水系统(生活水泵的运行状况及水箱水位的报警监测) 变配电系统(变配电数据及报警信息) 电梯系统(运行状态、故障报警监测) 3.3.2 智能照明系统 智能化酒店对照明的要求越来越高,不仅要求提供舒适、绿色的光照,同时不同的场合需要不同的照明环境。传统的照明控制一般采用开关手动控制,对于上述要求很难实现, 而且线路十分复杂,操作非常繁琐。随着用户要求的提高和技术的进步,传统的照明控制由于许多问题无法解决而逐步被智能照明控制取代,智能照明系统可依据需要实现自动时间控制、自动顺序控制、占空(动静)探测控制、事件程序响应控制、分割空间控制等多种方式的自动控制,也可增加自动日照控制、事件程序响应控制、远程电话控制、远程 Internet控制等。 系统涉及的主要部位有: (1)客房走廊:采用移动控制,通过在客房走廊设置若干的传感器(如移动探测器、 主动探测器等),与走廊灯光进行连锁控制。当有人进入探测器探测区域时,该区域内的走 廊灯缓慢点亮,当进入下一个探测器区域时,该区域的渐区域的走廊灯又缓慢点亮,而上一 个区域的走廊灯又缓慢调暗,使客人感受渐进式亮度变化过程,具有一定的艺术欣赏感,同 时又可节省能源和延长灯具寿命。 (2)酒店大堂:恒照度控制,根据系统设定的照度值室内照度的变化,自动调节灯 光的亮度,使酒店大堂照度保持恒定。 (3)会议区、咖啡厅、宴会厅等:场境控制,根据预先设定的模式实现一键制场境 转换。 3.4 公共安全系统 3.4.1 入侵报警系统 入侵报警系统是采用红外或微波技术的信号探测器,在酒店内根据不同位置的重要程度和风险等级要求以及现场条件,进行周边和内部区域保护。 报警管理主机能直接或间接接收来自入侵探测器发出的报警信号,发出声、光报警并指示入侵发生的部位。 声、光报警信号能保持至手动复位;复位后,再有入侵报警信号输入时,能重新发出声、光报警信号。 系统自成网络,且有输出接口,用手动、自动方式,通过有线向外报警联动。 (1)紧急报警按钮 在收银台、前台、财务室、贵重物品寄存室等场所安装紧急按钮,在遇紧急情况时 可及时向保安中心报警、求助.(注:客房及卫生间内设置报警按钮,该部分功能由客房控制系统实现) (2)红外/微波双鉴探测器 在贵重物品存储区、财务室、酒店商店设置,在设防(非开放)时间段,检测和快速报警至监控中心并可联动相应摄像机. 3.4.2 视频监控系统 视频监控系统的主要功能是辅助入侵报警系统对酒店内的现场实况进行监视。它使管理人员在控制室中能观察到酒店内所有重要地点的情况,为消防、酒店各种设备的运行和人员活动提供了监视手段。如在地下车库、自行车库、大厅、各楼层主要出入口、电梯轿厢、重要库房等重要部位设置监控摄像机,将监测区的情况以图像方式实时传送到监控管理中心, 值班人员通过监视器可以随时了解这些重要场所的情况。 系统采用网络摄像机(电梯专用采用模拟+编码器模式).前端摄像机分别就近接入各楼层接入层交换机,通过综合布线网络汇聚到总控中心的核心层交换机。控制中心采用视频综合平台进行解码上墙显示,通过磁盘阵列进行集中存储。 总控中心软件管理平台提供系统的中心管理服务、存储管理服务、流媒体服务、WEB服务、报警管理服务、智能分析管理服务等各类系统服务,并为各分控中心的控制端提供系统支撑和各类认证的服务。软件平台支持网络键盘的接入,提供了人性化的操作功能. 3.4.3 出入口控制系统 本出入口控制系统主要针对后勤区的办公用房、消控中心、IT 中心及 PABX 间设置门禁系统,为方便管理,建议采用联网型门禁系统. 系统采用以太网架构 TCP/IP 通讯,结合非接触式 IC 卡及计算机网络技术,以一张多功能非接触式 IC 卡承担起身份识别、门禁通行等管理职能.门禁管制方式具有多种,可灵活根据业主的功能需求及现场实际情况进行量身订做。主要的控制方式如下几种,单向控制(进门刷卡、出门开门按钮)、双向控制(进门刷卡、出门刷卡),另外读卡器可选用支持密码、生物识别等产品,在普通门控的基础上提高安全级别。 3.4.4 电子巡更系统 酒店来往人员众多复杂,为有效实现人防与物防相结合,必须有专人对较重要的场所进行巡逻管理,对酒店进行 24 小时的定期进行巡逻,以处理突发事件。 为了保证每个保安人员都能尽职尽责,在合理设定的时间内,按时按路线巡逻,确保工作严密有效,在突发事件时能尽快反应,也保障了保安人员的安全,必须在酒店内设立电子巡更系统。 电子巡更的实现:巡逻路线上设置巡更点,保安人员在此路线上按指定的时间和地点到达巡更点,不能迟到,不能绕道,巡更员每抵达一个巡更点,必须采集巡更点的信息,以便控制中心了解巡更线路情况。 系统主要由信息点、数据变送器、数据变送器、系统管理软件四部份组成. 3.4.5 无线对讲系统 无线对讲系统是一种比较普通的无线技术应用,主要用于酒店、管理服务和保安巡逻。该系统能使您找到更快、更好和更有效的工作途径,通讯系统能使工作范围扩大到方圆15—25 公里左右。因此,无论相关人员或团队在哪里,都可以轻轻按下一个键便能与他们取得联系,同时也是现代化安全管理工作不可缺少的工具. 本项目无线对讲信号有效覆盖区域酒店地面及地下区域,其中 95%以上的覆盖面积为有效覆盖面积。使整个系统达到覆盖均匀,信号清晰,稳定可靠。以满足酒店内部管理、物业使用和维护,以及保安、消防、紧急通信之要求等,使其内部管理、维护以及保安、消防人员之间方便、快捷地保持联系、通讯。 无线系统采用无线异频中继转发来实现双向无线对讲的要求。选用 400MHz(UHF403—470MHz)频段作为无线通信频率。具体频点向无线电管理委员会申请。 3.4.6 停车场管理系统 现代化的停车场管理系统应是采用先进技术,并结合了不同人员在停车场收费管理方面的不同需求,以及有效管理方面的经验而开发的系统。该系统提供一种灵活、有效的停车场管理方式,能够为其用户提供更方便、更有效的服务。停车场管理系统是置于计算机管理下的高科技机电一体化产品,它主要是针对建设智能化车库的管理需要,以方便、安全为目标、以车辆停车为主要服务对象,以达到停车进出方便、快捷、安全,管理科学高效、服务优质文明的目的。 酒店项目一般有地面和地下多个出入口,采用近距离和远距离卡片两种相结合方案,临时访客车,需在岗亭处办理登记手续,允许进入后,发给司机一张临时卡,读卡进入,同时根据需要,可进行计费收费;内部车辆,采用远距离刷卡进出管理。 3.5 机房工程 机房工程通常是指在一个物理空间内实现对数据信息的集中处理、存储、传输、交换、管理,而计算机设备、服务器设备、网络设备、通讯设备、存储设备等通常被认为是网络机房关键设备。中心机房的基础设施是指为确保机房内的网络机房关键设备和装置能安全、稳定和可靠运行而设计配置的基础工程即机房工程,数机房工程的建设不仅要为机房内的网络机房关键设备运营管理和数据信息安全,提供 24×7 的保障环境,还要为工作人员创造健康适宜的工作环境。 机房工程建设是多种技术系统的综合工程,主要包括:场地规划、装饰装修、电源配电、暖通空调、应急照明、网络布线、防雷接地、气体消防、视频应用、信息安全、安全防范、环境监控等专项技术系统。 机房工程一般包括网络中心机房和消防控制中心. 分别设置系统为: 1、网络中心机房的机房工程包括如下系统: (1)装饰装修工程 (2)低压供配电系统 (3)UPS 及蓄电池系统 (4)空调调节系统 (5)安全防范系统(门禁管理系统及视频监控系统) (6)机房环境监测系统 (7)综合布线系统 (8)气体灭火系统 (9)防雷及接地系统 2、消防控制中心的机房工程包括如下系统: (1)装饰装修工程 (2)低压配电系统 (3)UPS --- ### 465. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 近年来,燃气泄漏引发的爆炸事故频频发生,给人们的生命财产安全带来了巨大威胁,这也凸显了传统的燃气安全管理方式存在的漏洞和不足。面对这一挑战,借助物联网技术的普及和应用,可以构建起更为智能、高效的燃气安全监测体系,从而有效地预防和避免燃气爆炸事故的发生。 一、智能感知:气体传感器的应用 物联网技术的核心之一就是感知与监测。通过在室内空间布置气体传感器,实时监测空气中的燃气浓度变化。这些传感器采用进口电化学传感器,具有反应迅速、抗干扰能力强的特点,能够准确、及时地检测到燃气泄漏的迹象。一旦监测到燃气浓度超过安全范围,传感器将发出声光报警信号,提醒用户采取相应的安全措施,如关闭燃气阀门等,从而避免事故的发生。 二、智能分析:环境监控云平台的应用 传感器采集到的数据通过物联网技术传输至云端平台进行存储和分析。环境监控云平台能够实时监测室内气体浓度,支持对监测点位置、设备类型等信息的实时查询。同时,平台还具备数据分析的功能,能够对历史数据进行曲线分析,识别出燃气泄漏的趋势,为预防事故提供科学依据。 三、智能预警:多样化报警方式的应用 环境监控云平台支持多种报警方式,包括界面报警、声光报警、短信报警、电话报警等,用户可根据自身需求选择合适的报警方式。一旦监测到燃气泄漏,系统将及时向相关管理人员发送报警信息,提醒其采取紧急措施,防止事故的扩大和发生。 四、智能管理:数据分析与设备维护 通过物联网技术,管理者可以随时随地通过手机APP或网页端登录环境监控云平台,实时监测气体浓度情况,查询历史数据,定位报警位置等。同时,平台还支持设备故障/异常报警功能,管理者可通过平台及时发现设备问题并进行维修维护,保障监测系统的正常运行。 五、智能预防:全面布局与系统优化 除了室内空间的监测外,物联网技术还可以应用于城市天然气管道的监测和管理。通过在管道周围布置智能传感器,实时监测管道的运行状态和周围环境情况,及时发现管道损坏、泄漏等问题,并通过云平台进行分析和预警,提前预防事故的发生。同时,加强管道建设与维护,提高管道的安全性和稳定性,也是预防燃气爆炸事故的重要措施。 综上所述,借助物联网技术,可以构建起智能化的燃气安全监测体系,实现对燃气泄漏的及时感知、快速预警和有效管理,从而最大程度地降低燃气爆炸事故的发生率,保障人们的生命财产安全。随着技术的不断进步和应用的不断普及,相信物联网技术将在燃气安全领域发挥越来越重要的作用,为社会的发展和人们的生活带来更多的便利与安全。 利用物联网技术保障燃气安全:构建智能监测体系 近年来,燃气泄漏引发的爆炸事故频频发生,给人们的生命财产安全带来了巨大威胁,这也凸显了传统的燃气安全管理方式存在的漏洞和不足。面对这一挑战,借助物联网技术的普及和应用,可以构建起更为智能、高效的燃气安全监测体系,从而有效地预防和避免燃气爆炸事故的发生。 一、智能感知:气体传感器的应用 物联网技术的核心之一就是感知与监测。通过在室内空间布置气体传感器,实时监测空气中的燃气浓度变化。这些传感器采用进口电化学传感器,具有反应迅速、抗干扰能力强的特点,能够准确、及时地检测到燃气泄漏的迹象。一旦监测到燃气浓度超过安全范围,传感器将发出声光报警信号,提醒用户采取相应的安全措施,如关闭燃气阀门等,从而避免事故的发生。 二、智能分析:环境监控云平台的应用 传感器采集到的数据通过物联网技术传输至云端平台进行存储和分析。环境监控云平台能够实时监测室内气体浓度,支持对监测点位置、设备类型等信息的实时查询。同时,平台还具备数据分析的功能,能够对历史数据进行曲线分析,识别出燃气泄漏的趋势,为预防事故提供科学依据。 三、智能预警:多样化报警方式的应用 环境监控云平台支持多种报警方式,包括界面报警、声光报警、短信报警、电话报警等,用户可根据自身需求选择合适的报警方式。一旦监测到燃气泄漏,系统将及时向相关管理人员发送报警信息,提醒其采取紧急措施,防止事故的扩大和发生。 四、智能管理:数据分析与设备维护 通过物联网技术,管理者可以随时随地通过手机APP或网页端登录环境监控云平台,实时监测气体浓度情况,查询历史数据,定位报警位置等。同时,平台还支持设备故障/异常报警功能,管理者可通过平台及时发现设备问题并进行维修维护,保障监测系统的正常运行。 五、智能预防:全面布局与系统优化 除了室内空间的监测外,物联网技术还可以应用于城市天然气管道的监测和管理。通过在管道周围布置智能传感器,实时监测管道的运行状态和周围环境情况,及时发现管道损坏、泄漏等问题,并通过云平台进行分析和预警,提前预防事故的发生。同时,加强管道建设与维护,提高管道的安全性和稳定性,也是预防燃气爆炸事故的重要措施。 综上所述,借助物联网技术,可以构建起智能化的燃气安全监测体系,实现对燃气泄漏的及时感知、快速预警和有效管理,从而最大程度地降低燃气爆炸事故的发生率,保障人们的生命财产安全。随着技术的不断进步和应用的不断普及,相信物联网技术将在燃气安全领域发挥越来越重要的作用,为社会的发展和人们的生活带来更多的便利与安全。 --- ### 466. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 一、系统概述 景区生态环境监测系统是指利用物联网、云计算、大数据等技术,对景区的空气质量、气象条件、水质等环境要素进行实时监测、分析和管理的系统。该系统可以为景区管理者提供科学的环境数据,帮助其更好地进行环境管理和决策,提升景区的环境质量和游客满意度。 二、系统组成 景区生态环境监测系统主要由以下几部分组成: 监测终端:负责采集景区的环境数据,包括气象站、水质监测仪、空气质量监测仪等。 数据传输网络:负责将监测终端采集的数据传输到数据中心,包括GPRS、4G、LoRaWAN等无线网络技术。 数据中心:负责存储、分析和处理环境数据,并为用户提供数据查询和分析服务。 应用平台:为景区管理者和游客提供环境信息查询、预警发布、数据分析等服务。 三、系统功能 景区生态环境监测系统主要功能包括: 实时监测:对景区的空气质量、气象条件、水质等环境要素进行实时监测,并及时将监测数据上传到数据中心。 数据分析:对监测数据进行统计分析,生成各种报表和图表,帮助景区管理者了解景区的环境状况和变化趋势。 预警发布:当环境数据超过预警阈值时,系统会自动发布预警信息,提醒景区管理者采取措施。 信息查询:景区管理者和游客可以通过应用平台查询景区的实时环境数据和历史数据。 四、系统方案 1. 监测终端 根据景区的实际需求,可以选择不同的监测终端。例如,对于空气质量监测,可以选择PM2.5、PM10、O3、NO2等参数的监测仪;对于气象监测,可以选择温度、湿度、风速、风向、降水等参数的监测仪;对于水质监测,可以选择pH值、COD、氨氮、溶解氧等参数的监测仪。 2. 数据传输网络 3. 数据中心 数据中心可以选择本地部署或云服务模式。本地部署模式需要景区自行建设机房和服务器,成本较高,但数据安全性更高;云服务模式可以节省景区建设和维护机房的成本,但数据安全性相对较低。 4. 应用平台 应用平台可以选择自主开发或购买第三方平台。自主开发可以满足景区的个性化需求,但成本较高;购买第三方平台可以节省开发成本,但功能可能无法完全满足景区的需求。 五、应用案例 景区生态环境监测系统已在多个景区得到应用,例如: 杭州西湖景区:杭州西湖景区部署了空气质量监测系统,可以实时监测景区的空气质量状况,并及时发布预警信息。 张家界景区:张家界景区部署了气象监测系统,可以为景区的旅游管理和游客安全提供气象信息服务。 九寨沟景区:九寨沟景区部署了水质监测系统,可以实时监测景区的湖泊水质状况,并为景区的水环境保护提供数据支撑。 六、总结 景区生态环境监测系统可以帮助景区管理者更好地了解景区的环境状况,并采取措施改善环境质量,提升景区的吸引力和游客满意度。 --- ### 467. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 1. 问题背景与挑战 在全国范围内,餐饮业油烟污染的环境监测仍然停留在手工监测阶段,导致时间覆盖率低、监测范围有限,难以实现实时监测、超标报警和无人值守。监管不到位导致油烟净化装置无法有效运行,严重影响环保部门的工作效率和反映能力。 油烟监测系统是在线监控系统软件平台,采用B/S模块开发,Window界面风格,操作简单方便;能实时显示餐饮企业的净化装置运行状态和清洁程度、风机运行状态,并以各种图形展示业务数据,形象直观:可部署于用户自有的服务器或政府服务器,功能强大;符合用户自身的特点,满足用户对信息安全的要求, 环境临控云平台:若将建大仁科精简式油烟在线检测仪送数据至云平台,设备需插上流量卡或者手机卡,将目标地址设置为0531vwn.n,目标端口设置为8020,设置完成后,设备自动上传数据至云平台。 2. 解决方案概述 为了实现对餐饮业油烟污染的长效管理,我们提出了精简式油烟在线监测系统的整体解决方案,旨在提供实时监测、报警、远程管理的功能,有效监管餐饮业的油烟排放情况。 3. 系统组成与功能 监测设备:采用精简式油烟在线检测仪,可采集油烟浓度、颗粒物浓度、非甲烷总烃等数据,并通过GPRS/4G传输到监控平台。 传输网络:采用GPRS/4G通讯方式,确保数据的及时传输和实时监测。 监控中心:油烟监测系统和云平台提供监测软件平台,实时显示餐饮企业的净化装置运行状态、清洁程度、风机运行状态等,并以图形展示业务数据,方便监管人员查看和分析。 4. 技术参数与特点 采样气体温度:-40~80℃ 上传数据间隔:30秒上传一次数据 油烟采集范围:0~20mg/m³,精度±7%FS 非甲烷总烃采集范围:0~20mg/m³,精度±10%FS 颗粒物值采集范围:0~20mg/m³,精度±10%FS 安装方式:简便易行,适用于不同风管。 5. 系统优势与价值 实时监测与报警:能够实时监测油烟排放情况,并设定上限值进行超限报警,保障环境监测的及时性和准确性。 远程管理:通过云平台,监管人员可随时随地查看监测数据和设备运行状态,实现无人值守管理。 环保效益:提高环保部门的工作效率和反映能力,降低对环境监管部门的人力压力,促进餐饮行业的油烟排放治理。 6. 实施步骤 选型与采购:根据需求选购精简式油烟在线检测仪及相关设备。 安装调试:按照安装手册,进行设备安装和调试工作。 网络配置:设置GPRS/4G通讯网络,确保数据传输畅通。 平台部署:部署油烟监测系统和云平台,建立监测平台。 数据监测:实时监测油烟排放数据,并进行分析和报警处理。 7. 总结与展望 精简式油烟在线监测系统是一种高效、便捷的油烟监测方案,能够提升环保部门的工作效率,加强对餐饮业油烟排放的管理和治理。未来,我们将持续优化系统功能,提升监测精度和反馈速度,为环保事业做出更大的贡献。 以上是对精简式油烟在线监测系统的整体解决方案,如需更多详细信息,请随时与我们联系。 --- ### 468. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着城市发展和人们生活水平的提高,智慧公厕已经成为城市基础设施建设的重要组成部分。传统的公厕管理存在着很多问题,例如无法及时了解厕所内部情况、人员流量管理不到位、环境卫生难以保障等。为了解决这些问题,推出了智慧公厕环境监测解决方案,旨在利用先进的科技手段提升公厕管理效率,改善厕所环境质量,提升城市形象。当公厕内的有害气体含量超标时,系统能够自动联动风机进行通风除臭,确保厕内环境卫生,改善公厕内的环境质量。 此外有些智慧厕所还有生命监测功能,当发现有人身体不适、超时驻留,系统会发出告警信息,及时关注如厕者安全情况。 一、概述 智慧公厕环境监测解决方案是指利用物联网、云计算、大数据等技术,对公厕内的环境参数进行实时监测、分析和管理,以提升公厕环境质量,改善如厕体验,打造智慧城市的重要组成部分。 二、方案组成 智慧公厕环境监测解决方案主要由以下四部分组成: 监测终端: 负责采集公厕内的环境参数,包括温湿度、硫化氢、氨气、PM2.5、臭氧等。 传输部分:负责将监测终端采集到的数据传输至管理平台。 管理平台:负责对数据进行存储、分析和展示,并提供管理功能。 智能联动:根据监测数据,联动风机、排气扇、照明等设备,实现公厕环境的智能化管理。 三、工作原理 监测终端采集公厕内的环境参数,并将数据传输至传输部分。 传输部分将数据传输至管理平台。 管理平台对数据进行存储、分析和展示,并提供管理功能。 根据监测数据,联动风机、排气扇、照明等设备,实现公厕环境的智能化管理。 四、方案优势 实时监测:可实时监测公厕内的环境参数,及时发现环境问题。 智能分析:可对监测数据进行智能分析,为公厕管理提供决策依据。 精细管理:可实现公厕环境的精细化管理,提升公厕环境质量。 人性化服务:可为如厕者提供更加人性化的服务,提升如厕体验。 监测终端主要有多功能空气质量变送器和吸顶式红外探测器。 公厕内的硫化氢和氩气是造成公厕异味的原因,当这2种气体的浓度达到一定的数值,就会对人体造成伤害,多功能空气质量变送器可以同时监测这两种气体的浓度,避免浓度升高对人体造成伤書。 吸顶式红外探测器能够对厕位使用情况进行动态监测,通过显示屏可直接反映厕位的占用情况,减少人员的等待时间,也方便管理人员合理配置资源。 五、应用场景 智慧公厕环境监测解决方案可广泛应用于城市公厕、景区公厕、高速公路公厕、公园公厕、学校公厕等场所。 六、典型案例 某市智慧公厕项目:该项目采用智慧公厕环境监测解决方案,对全市范围内1000余座公厕进行环境监测,有效提升了公厕环境质量,改善了如厕体验。 某景区智慧公厕项目:该项目采用智慧公厕环境监测解决方案,对景区内50余座公厕进行环境监测,有效缓解了景区公厕高峰期排队压力,提升了景区游客的满意度。 七、发展趋势 随着智慧城市建设的不断发展,智慧公厕环境监测解决方案将得到更加广泛的应用,并将朝着以下方向发展: 技术更加智能化:将采用人工智能、大数据等技术,进一步提升监测、分析和管理的智能化水平。 功能更加丰富:将提供更多人性化功能,如厕位导航、厕纸余量提醒、如厕安全监测等。 应用更加广泛:将应用于更多场景,如家庭卫生间、养老院卫生间、医院卫生间等。 八、结论 智慧公厕环境监测解决方案是智慧城市建设的重要组成部分,对于提升公厕环境质量、改善如厕体验、提升城市形象具有重要意义。 --- ### 469. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信   MQTT在运输和物流中的车队管理革命 为什么MQTT是车队管理的理想选择?运输和物流公司如何使用MQTT进行车队管理如何开始使用MQTT进行车队管理 在运输和物流行业中,高效的车队管理对于确保车辆平稳运行和优化配送过程至关重要。其中,MQTT这一轻量级且高效的消息传递协议正在改变车队管理的面貌。MQTT的设计初衷就是促进实时数据通信,使其成为应对行业独特挑战的理想工具。接下来,我们将深入探讨MQTT如何改变车队管理的游戏规则。 为什么MQTT适合车队管理? 实时洞察:车队管理依赖于实时数据。MQTT允许关键信息的交换,使公司能够实时监控其车辆和驾驶员。这种实时可见性对于数据驱动的决策制定和运营效率至关重要。通过MQTT,公司可以实时掌握车辆位置、速度、油量等关键信息,从而及时调整运营策略,优化配送路线,提高运输效率。 高效数据传输:MQTT的轻量级设计确保了数据可以高效传输。无论是追踪车辆位置、监控驾驶员行为,还是管理配送路线,MQTT都能以最小的开销处理数据交换,确保通信的快速和顺畅。这有助于减少数据传输过程中的延迟和错误,提高整个车队的运营效率。 可扩展性:车队管理的需求随着业务规模的变化而变化。MQTT提供了出色的可扩展性,能够适应不断变化的业务需求。无论是增加新的车辆,还是调整现有的配送网络,MQTT都能轻松应对,确保车队管理的灵活性和效率。 可靠性:确保车队的连续运营至关重要。MQTT的服务质量(QoS)级别保证了即使在恶劣条件下也能可靠地传递消息。这使得MQTT成为车队管理的理想选择,因为它能够在各种环境下确保数据的完整性和准确性。 那么,运输和物流公司是如何利用MQTT进行车队管理的呢? 首先,这些公司利用MQTT构建实时监控系统,实时追踪车辆位置和状态。通过MQTT协议,车辆可以定期发送位置、速度、油量等关键数据到中央服务器。这样,公司可以实时掌握车队运行情况,及时发现并解决潜在问题,从而提高运输效率和服务质量。 其次,MQTT还用于监控驾驶员行为。通过安装在车辆上的传感器,可以收集驾驶员的驾驶习惯、行驶速度、制动频率等数据,并通过MQTT协议传输到后端系统进行分析。这有助于公司评估驾驶员的表现,发现不良驾驶习惯,及时采取纠正措施,从而提高行车安全性。 此外,MQTT还可以用于智能路线规划和调度。通过分析实时交通数据和车队状态,系统可以自动生成最优路线,并通过MQTT协议将指令发送给相关车辆。这有助于减少拥堵和延误,提高配送效率,降低运营成本。 对于希望开始使用MQTT进行车队管理的公司,以下是一些建议: 首先,了解MQTT的基本原理和应用场景是至关重要的。公司需要研究MQTT协议的特点和优势,了解它在车队管理中的应用场景和潜在价值。这将有助于公司更好地利用MQTT技术提升车队管理效率。 其次,选择合适的MQTT代理和工具是关键。公司需要根据自身需求选择稳定、可靠且易于集成的MQTT代理和工具。这将有助于确保数据的安全传输和高效处理,提高整个系统的稳定性和可靠性。 最后,建立有效的数据分析和决策支持系统是必要的。通过收集和分析MQTT传输的数据,公司可以深入了解车队的运营情况,制定更加科学合理的决策。同时,公司还可以利用这些数据优化配送路线、提高运输效率、降低运营成本等。 总之,MQTT在运输和物流行业的车队管理中具有广阔的应用前景。通过充分利用MQTT的优势,公司可以实现对车队的实时、高效和智能化管理,为业务发展提供有力支持。随着物联网技术的不断发展,相信MQTT将在未来继续为车队管理带来更多创新和可能性。 --- ### 470. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着工业物联网 (IIoT) 技术的快速发展,越来越多的数据被生成和收集。这些数据包含了设备状态、生产过程、产品质量等重要信息,是实现数字化转型和智能制造的关键。 历史数据管理系统 (Historian) 是一种专门用于存储和管理历史数据的软件系统。它可以帮助企业有效利用历史数据,提升运营效率、降低成本、提高产品质量。 统一命名空间 (UNS) 是工业物联网领域的一种开放、可扩展的架构,可以将来自不同设备、系统和应用程序的数据统一起来,提供一个统一的数据视图。 将历史数据管理系统集成到统一命名空间 可以实现历史数据的统一管理和分析,为企业带来以下优势: 提高数据可访问性和可用性: 历史数据可以与实时数据一起,通过统一的接口进行访问和分析,方便企业进行全面的数据分析。 增强数据分析能力: 通过将历史数据与实时数据进行关联分析,可以发现更深层次的洞察,帮助企业更好地理解运营状况、预测未来趋势。 优化运营效率: 历史数据可以用于改进生产流程、优化资源配置、降低运营成本。 提高产品质量: 历史数据可以用于分析产品缺陷,改进产品设计和制造工艺,提高产品质量。 集成策略 将历史数据管理系统集成到统一命名空间,可以采用以下策略: 使用标准化协议: 历史数据管理系统和统一命名空间可以使用 MQTT 等标准化协议进行通信,确保数据交换的互操作性。 建立数据映射: 需要建立历史数据和统一命名空间之间的数据映射关系,确保数据的准确一致。 开发数据转换工具: 可以开发数据转换工具,将历史数据转换为统一命名空间支持的数据格式。 注意事项 在将历史数据管理系统集成到统一命名空间时,需要考虑以下注意事项: 数据安全: 历史数据可能包含敏感信息,需要确保数据的安全性和隐私性。 数据完整性: 历史数据是重要的分析资产,需要确保数据的完整性和准确性。 性能和可扩展性: 需要确保集成后的系统能够满足性能和可扩展性要求。 结论 将历史数据管理系统集成到统一命名空间是实现工业物联网数据价值的关键途径。通过有效利用历史数据,企业可以提升运营效率、降低成本、提高产品质量,实现数字化转型和智能制造。 --- ### 471. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 背景: 经历了新冠疫情的冲击后,汽车制造业正稳步复苏。面对日益激烈的市场竞争和不断变化的客户需求,制造商们意识到,数字化转型和工业4.0技术是提升竞争力和实现可持续发展的重要途径。 调查结果: 2023年AMS/ABB汽车制造业展望调查揭示了以下关键洞察: 挑战并存: 供应链中断仍然是制造商关注的问题 (35%),但其重要性已被不断加剧的劳动力和技能短缺问题 (36%) 所超越。此外,电动化转型、成本控制、可持续发展等议题也为行业发展带来了新的挑战。 多元化的动力总成解决方案: 调查显示,未来动力总成技术尚无明确的领先者。电池电动和氢燃料电池混合动力 (25%) 领先,其次是氢燃料电池汽车 (23%) 和先进电池 (22%),氢燃烧技术也获得了显著关注 (11%)。 积极的展望: 尽管存在经济不确定性,但总体而言,行业前景乐观。76% 的受访者预计车辆产量将保持稳定或增长,相比之下,2022 年这一比例为 56%。同样,69% 的受访者认为车辆销量将保持稳定或增长,相比之下,2022 年这一比例为 54%。此外,需求已成为车辆产量的主要制约因素 (55%),取代了 2022 年的生产 (57%),表明供应链问题有所缓解。 MQTT物联网平台如何助力汽车制造商: 应对挑战: 提升供应链韧性: MQTT物联网平台可以实现供应链数据的实时采集和分析,帮助制造商提高供应链可视性,及时识别并应对突发事件,有效降低供应链中断风险。 赋能数字化劳动力: MQTT物联网平台可以连接工厂设备和生产系统,实现生产数据的实时采集和分析,帮助制造商构建智能制造体系,提升生产效率,优化资源配置,缓解劳动力短缺问题。 加速电动化转型: MQTT物联网平台可以连接电动汽车和充电桩,实现车辆数据和充电数据的实时采集和分析,帮助制造商优化电动汽车的生产、运营和管理,加速电动化转型。 降低运营成本: MQTT物联网平台可以帮助制造商优化生产流程,提高资源利用率,降低能源消耗,减少浪费,有效降低运营成本。 实现可持续发展: MQTT物联网平台可以帮助制造商提高生产效率,减少资源消耗,降低污染排放,实现可持续发展目标。 拥抱未来技术: 构建车联网生态: MQTT物联网平台可以连接车内外の设备和系统,实现车联网数据的实时采集和分析,帮助制造商构建车联网生态,提供个性化、智能化的车联网服务。 推动智能驾驶发展: MQTT物联网平台可以为自动驾驶汽车提供实时路况、交通信号灯等信息,帮助汽车实现更安全、更高效的自动驾驶。 赋能数据驱动决策: MQTT物联网平台可以将生产、运营、销售等数据进行统一管理和分析,帮助制造商实时洞察市场需求和产品性能,做出更智能、更有效的决策。 应用案例: 宝马集团使用MQTT物联网平台连接全球生产设施,实现实时数据采集和分析,提升生产效率和产品质量。 特斯拉使用MQTT物联网平台连接其电动汽车和充电网络,实现车辆数据和充电数据的实时采集和分析,优化车辆管理和充电服务。 福特汽车使用MQTT物联网平台构建车联网平台,提供个性化、智能化的车联网服务,提升用户体验。 结论: 数字化转型和MQTT物联网平台是汽车制造业未来发展的关键驱动力。通过拥抱数字化转型和MQTT物联网平台,汽车制造商可以提升竞争力,实现可持续发展,并在未来竞争中取得成功。 --- ### 472. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 全球每年产生约3590亿立方米的废水,相当于1440万个奥运游泳池的容量。在全球范围内,将大量废水入河流、海洋和溪流是一种常见做法。这种做法对环境、渔业和动物产生极为负面的影响,更不用说它对水资源的浪费了。废水处理对于保护环境、确保我们最有效地利用资源至关重要。 让我们探讨一下废水行业面临的一些问题,以及物联网如何帮助解决这些问题,最后讨论MQTT在支持物联网用例方面的作用。 废水行业面临的挑战 废水行业面临着从环境关切到基础设施和管理问题等多种挑战。一些主要挑战包括: 老化基础设施许多国家的水和废水基础设施老化,需要维修或更换。老化基础设施导致漏水、破裂和低效,导致水资源浪费和潜在水源污染。 水污染工业废水排放、农业径流和垃圾不当处理导致水污染。化学物质、重金属、病原体和营养物质等污染物质可能降低水质,对人类健康和生态系统构成风险。 能源消耗水和废水处理过程需要大量能源投入,导致温室气体排放和运营成本增加。寻找减少能耗和提高能效的方法对可持续性和经济效益至关重要。 要解决这些问题,需要政府、公用事业、行业利益相关者和公众之间的合作,以及对研究、技术开发和基础设施改善的投资。 物联网技术如何解决一些挑战 物联网(物联网)技术通过提供实时资产监控、数据分析和自动化能力,对废水行业的各种挑战起到了重要作用。 以下是物联网如何解决主要挑战的一些方法: 预测性维护通过持续监测设备状况和性能指标,物联网启用的预测性维护系统可以预测设备何时可能故障或需要维护。这种积极的方法可以最小化停机时间,降低维护成本,并延长关键基础设施组件的寿命。 水质监测物联网传感器可以实时监测各种参数,如pH值、浑浊度、溶解氧和化学浓度。这使得能够及时检测污染物或异常,使水务部门能够迅速采取纠正措施,以维护水质并符合法规。 泄漏检测和水损管理装有泄漏检测传感器的物联网设备可以快速识别水配送网络中的泄漏。通过确定泄漏位置并监测流速,水务部门可以最小化水损失,节约资源并提高效率。 总体而言,物联网技术使水和废水公用事业能够提高运营效率,改善资源管理,确保法规遵从,并向客户和社区提供更好的服务。 MQTT如何实现物联网数据的可用性以支持水和废水管理 MQTT是一种轻量级的消息传递开放标准协议,在物联网中用于数据传输,专为在低带宽、高延迟或不稳定网络中进行有效通信而设计。在废水行业,MQTT可以通过促进实时数据交换、远程监测和控制,帮助解决各种物联网数据挑战。 为什么选择MQTT协议用于物联网?以下是MQTT的帮助方式: 实时监控MQTT实现了从废水系统中各个点传输传感器数据到集中监控系统的实时传输。这是因为它是一种事件驱动的架构,可以提供实时的最新数据。这使得操作人员能够持续监测水质、流速、压力水平和设备状态等参数,有助于及时检测异常或问题。MQTT物联网平台通过启用泄漏检测、对井、泵、电机和用水系统进行远程监控和控制,帮助LEC实现减少或消除客户水资源浪费的目标。 可伸缩性和灵活性 MQTT的轻量级和高效的特性使其非常适用于分布式废水基础设施的大规模部署。它支持发布-订阅消息传递模型,允许多个客户端订阅相关的数据主题,而不会对网络资源造成不必要的负担。MQTT物联网平台提供先进的可伸缩性功能,经过基准测试,最多支持1亿活跃客户端。 可靠性和韧性MQTT的发布/订阅架构以及对服务质量(QoS)级别的支持确保在网络条件或断断续续的连接情况下也能可靠地传递消息。这种可靠性对于在遥远或恶劣环境中保持对水和废水系统的持续监测和控制至关重要。HiveMQ为关键应用提供了企业级可靠性的IoT数据。 数据集成和互操作性MQTT便于与水和废水设施常用的SCADA(监控与数据采集)、DCS(分布式控制系统)、PLC(可编程逻辑控制器)和物联网系统无缝集成。它促进了不同设备和平台之间的互操作性,确保平稳的数据交换和系统优化。MQTT物联网平台提供了可以将一些常见的机器协议转换为MQTT并帮助打包用于高级分析的物联网数据的设备驱动程序。 安全性MQTT支持各种安全机制,如传输层安全(TLS)和身份验证机制,确保安全的通信和数据完整性。这对于保护敏感数据、防止未经授权访问或篡改水和废水系统至关重要。MQTT物联网平台提供了一个具有高级安全功能的企业级代理。 边缘计算MQTT可以与边缘计算平台结合使用,以在网络边缘进行数据预处理、分析、边缘人工智能和决策。这降低了延迟,节约了带宽,并使对水和废水系统中关键事件或报警的更快响应成为可能。 MQTT:彻底改变废水管理流程的开放标准MQTT通过实现实时监测、远程控制、数据集成和自动化,对废水运营的效率、可靠性和韧性发挥着至关重要的作用。其开放标准、轻量级、可伸缩和互操作的特性使其非常适用于解决行业面临的复杂挑战。它通过使废水中的物联网解决方案能够优化运营并提高安全性。 --- ### 473. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 离散制造是指生产独立、可辨认且易于计数的独立物品或单元的过程。这种制造类型涉及将组件或零件组装成成品,其中每个物品都可以与其他物品区分开。典型的离散制造行业包括汽车、电子、航空航天、机械和医疗设备。这些行业通常在生产过程中使用物料清单(BOMs)和质量控制措施。离散制造允许定制、灵活性和高效生产各种产品。 离散制造的常见过程 生产计划和调度 离散制造需要对整个生产过程进行仔细的计划和调度,以确保所需的零部件在需要时可用。调度定义了每个生产阶段需要多长时间以及每个人应该工作多少时间,以确保按时完成生产。生产计划需要优化,以最小化浪费并最大化效率。因此,供应链数据的可见性非常重要。 批量大小和交货期的优化 批量大小突显生产的数量,而交货期指整个过程所需的时间。这两个参数都影响生产效率,因此必须进行优化以获得更好的产出。实时数据的可见性和准确性非常重要。 离散制造的常见系统 计算机辅助设计(CAD) CAD软件用于设计产品,概念化想法以考虑确保最终产品完美的细节。该工具执行快速设计计算和模拟,有助于创建准确和精确的产品设计。 计算机辅助制造(CAM) 计算机辅助制造实现了管理过程的自动化,允许跟踪生产过程、资源和运输。 企业资源规划(ERP) ERP的实施提供了对库存和整个生产过程更好的控制和可见性。借助ERP,平台检查不同类型的数据和信息,并在所有点上使其可访问和可用。 产品生命周期管理(PLM) PLM确保从概念化时直到最终发运时对产品的整个生命周期进行管理。 工业物联网(IIoT)和MQTT作为连接系统的启用器 在离散制造中,IIoT在通过传感器和可编程逻辑控制器(PLC)将各种OT系统连接到上述IT系统方面发挥着重要作用。这种OT-IT连接实现了数据交换和数字化转型用例,例如,ERP系统中的订单数据需要与PLM中的生产数据相结合,以便能够进行正确的预测、计划和调度。IIoT使这些系统能够彼此通信,并通过MQTT等消息传递技术创建一个单一的窗格。 MQTT在离散制造应用中的作用 实时数据通信 MQTT在离散制造中实现了设备、系统和应用程序之间的实时通信,有助于将它们连接到企业和/或云,支持预测性维护、远程监视、数字孪生和先进的分析等高级数据用例。MQTT还促进了无显著延迟的制造设备之间的无缝机器对机器通信,这对于监视和控制离散制造非常关键,确保数据迅速而高效地交换。 可扩展性 MQTT具有很高的可扩展性,可以同时支持大量设备、系统和应用程序。在离散制造中,其中许多设备、系统和应用程序部署在生产现场,MQTT的可扩展性对于处理多样化的数据来源至关重要。提供企业级MQTT代理的HiveMQ具有额外的可扩展性功能,并已进行了2亿并发连接的基准测试。 带宽使用效率 MQTT在带宽使用效率方面设计得非常高效。在网络带宽可能有限的制造环境中,MQTT的轻量级协议确保数据可以在不给网络基础设施带来额外负担的情况下进行高效传输。 可靠性和服务质量(QoS) MQTT支持不同级别的服务质量,允许制造商选择适用于其特定用例的可靠性级别。这对于可靠的数据交换至关重要,例如远程监视关键设备。MQTT通过支持保留消息来提供额外的可靠性,其中代理会保留在特定主题上发送的最后一条消息。这个特性在离散制造中非常有用,以确保连接到网络的设备在连接时接收到最新的相关信息。HiveMQ MQTT代理提供了额外的可靠性功能,包括支持无主集群架构、可靠的通信和零停机升级。 安全性 MQTT本身提供通信的安全性,因为它基于对主题命名空间的订阅。因此,未订阅特定主题的任何客户端都不会接收到消息。除此之外,可以在MQTT上实施额外的安全功能,包括用户ID/密码、TLS加密、X.509 客户端证书授权等机制,以确保离散制造通信的安全性。 发布-订阅模型 MQTT采用发布-订阅模型,其中客户端可以将消息发布到特定主题,而其他客户端可以订阅这些主题以接收消息。这个模型非常适合离散制造场景,其中不同的组件需要实时了解相关事件或实时变化。除此之外,数据框架如Sparkplug和统一命名空间等概念提供了其他有效组织数据的方式。 边缘计算集成 MQTT通常与边缘计算一起在离散制造中使用。边缘设备、应用程序和系统使用MQTT在本地彼此通信,有选择地与服务器/云通信,从而减少将所有数据发送到中心服务器的需求。这可以提高响应时间并减少延迟。边缘网关可以将来自各种协议(如OPC UA、Modbus和Siemens S7)的数据转换成MQTT,并将数据传送到代理进行处理。 MQTT对离散制造中IIoT数据通信的改变 离散制造中的IIoT改善了效率、质量、维护和整体运营效果。通过使用可靠且高效的通信机制(如MQTT)实现数据通信,离散制造系统可以高效支持对工厂生产中各种设备、流程和应用程序的实时监视,并支持先进的数据用例。MQTT所带来的连接性使离散制造得以数字化转型,从而实现更高的效率、降低成本、更好的客户体验和更高的盈利能力。 --- ### 474. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在过去的十年中,制造业取得了多项进步,有助于简化生产流程、降低成本并提高盈利能力。然而,尤其在能源使用和可持续性方面,仍存在一些问题和挑战。解决这些问题对于实现更环保、资源效率更高的制造业至关重要。基于开放标准(如MQTT)的创新解决方案可以帮助解决这些问题。在本文中,我们将深入探讨制造业领域的主要挑战以及如何通过边缘或云端的MQTT来克服这些挑战。 制造业的能源和可持续性挑战 以下是我们看到的一些阻碍制造商减少能源使用和提高可持续性的常见挑战: 使用专有设备和过时软件 制造设施通常处理具有专有通信协议和孤岛式设计的设备,导致不同系统无法相互通信。这些系统通常是基于即时需求而非长期战略设计的。它们由于需要额外资源来实现通信,妨碍了最佳能源使用,也影响了可持续性目标。 高能源和资源消耗 制造过程复杂且耗能。它们通常需要大量能源输入,导致高运营成本和碳排放的增加。此外,某些过程使用大量资源,如电力或水。在不影响生产效率的情况下优化能源和资源使用是一个重大挑战。 依赖不可再生能源 许多制造设施依赖于化石燃料等不可再生能源。由于生产压力、基础设施限制、成本、监管限制和对长期效益了解不足,向可再生能源转型并采用可持续最佳实践可能具有挑战性。制造商可能会优先考虑短期成本节约而非长期可持续性目标。 废物产生 制造过程产生大量废物,包括废料、副产品和污染物。适当的废物管理和回收策略对于减少环境影响并支持合规性至关重要。 供应链可持续性 可持续制造不仅关乎内部流程,还涉及整个供应链。确保供应商采用可持续实践可能具有挑战性,特别是在从环境标准较为宽松的地区采购原材料时。全球化供应链和竞争可能阻碍可持续性倡议的实施。 过时的设备和技术 较旧的制造设备可能缺乏节能特性,使得在不进行重大资本投资的情况下升级流程变得具有挑战性。工人可能不完全了解他们行为的环境影响或节能潜力。现代化设备、培训工人和采用工业4.0技术可能是一个渐进但必要的过程。 数据可见性不足 低效的监测和数据收集系统使得难以评估能源使用模式并识别改进领域。这也对实现可持续性最佳实践构成挑战。实施实时监控和数据分析对于做出明智决策至关重要。 解决这些问题需要结合技术创新、管理愿景、监管支持、员工参与和供应链合作的整体方法。致力于优化能源使用和促进可持续性的制造商可以探索一系列能效技术、可再生能源采用、废物减少策略和持续改进文化的组合,以克服这些挑战。最重要的是,他们需要采用智能制造以实现成功。 智能制造中的可持续之路 根据2022年麦肯锡研究,通过采用工业4.0技术(如工业物联网(IIoT)、人工智能(AI)、数字孪生、数字线程、增强现实(AR)、虚拟现实(VR))实现的智能制造优势,如停机时间减少30-50%、吞吐量增加10-30%、预测精度提高高达85%。在工业4.0技术和智能制造的最佳实践帮助下,制造行业正被转变回一个经济强国。 智能制造的一个关键方面是拥有企业数据增强策略,该策略使各种系统之间能够通过MQTT实现实时双向通信,为能源优化和可持续性铺平道路。 MQTT如何帮助改善制造业的能源使用和促进可持续性 MQTT是一种轻量级消息协议,专为工业物联网(IoT)和智能制造系统中的高效通信而设计。它是智能制造的一个组成部分。由于它在优化能源使用和促进智能制造中的可持续性方面提供的各种优势,它已成为从现场到企业或云的工业数据通信的事实标准。 以下是一些优势: 高效的通信数据包大小和消息有效负载 MQTT被创建为一个非常高效的基于事件的发布/订阅数据通信协议。消息数据包大小仅高达200KB,有助于最小化工业设备、系统、应用程序和代理之间交换的数据量,降低能源消耗。使用MQTT,设备、系统和应用程序仅接收相关信息,最小化不必要的数据传输。这也有助于优化带宽并减少运营成本。MQTT还允许通过使用高效的数据序列化格式(如JSON和协议缓冲区)来优化消息有效负载,减少网络带宽使用和能源消耗。 服务质量(QoS)等级、睡眠模式和边缘处理 MQTT提供了根据数据临界性选择合适的服务质量(QoS)级别的灵活性。这使用户能够优化他们的数据传输策略,确保效率和可靠性。更高的QoS级别确保消息传递,但可能导致增加的能源消耗。此外,鉴于MQTT的异步性质,设备可以在空闲期间实施睡眠模式以节约能源。设备可以根据MQTT触发器在有相关数据交换时唤醒。除了MQTT客户端外,本地代理允许在将数据发送到企业代理之前在边缘处理大部分数据,从而减少通过网络传输的数据量,从而节省能源。 设备配置、管理、监控和报告 可以使用MQTT数据实现远程设备配置和管理,以优化设备设置、更新固件和应用节能参数。此外,可以实施监控系统来跟踪能源使用和可持续性指标。可以根据预定义的阈值创建报告和异常警报,以识别改进领域。 可再生能源整合和系统优化 使用MQTT,可以实时监控能源消费和生产,以优化可再生能源的使用。例如,可以利用数据调整制造过程,根据绿色能源的可用性进行优化。此外,可以使用MQTT定期审查和优化基于变化需求、技术进步和节能机会的制造数据移动。 预测性维护和高级分析 借助MQTT实现的实时数据移动,可以实施预测性维护来监控设备健康。其结果是减少停机时间,提高效率,以及防止与故障机械有关的能源浪费。此外,可以使用MQTT数据实施高级数据分析和机器学习模型,提供能源使用模式的洞察,使得能够实施主动节能措施。 标准化、互操作性和持续优化 通过确保智能制造环境中的设备、系统和应用程序遵循MQTT消息标准进行数据互操作,制造商可以创建一个更灵活和可扩展的生态系统。同时,通过定期审查和修改MQTT实现,根据变化的制造要求,制造商确保他们正在优化他们的系统并为其投资未来。 结合人员、流程和技术,通过MQTT实现目标 通过创建基于MQTT的数据移动策略,建立正确的智能组织结构来利用它,以及去除障碍的流程,制造商可以创建一个更节能、更可持续的智能制造生态系统。关键是将基于MQTT的数据策略整合到考虑制造环境独特要求的全面制造战略中,并不断寻求改进机会。 智能制造通过这种方式,不仅提高了能效和可持续性,还为制造商带来了经济效益和竞争优势,是未来制造业发展的关键方向。 --- ### 475. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在当今的智能家居浪潮中,越来越多的人希望能够自己打造一个智能家居系统,以便更好地管理家庭设备并提高生活的便利性。"Tasmota"是一个开源项目,它为您提供了实现这一目标的工具和平台。本文将介绍"Tasmota"项目,探讨它的功能、特点以及如何使用它来创建您自己的智能家居系统。 什么是Tasmota? "Tasmota"是一个为ESP8266和ESP32基础设备开发的替代固件,它的目标是实现智能家居的全面自动化和控制。这个项目的特点包括: 易安装:您可以使用"Tasmota WebInstaller"轻松地将"Tasmota"固件安装到您的设备上,无需复杂的操作。 多平台支持:无论您使用的是HomeAssistant、小米智能家居、华为智能家居、涂鸦智能家居还是HomeKit,"Tasmota"都支持与多个智能家居平台的集成,使您能够管理不同品牌的智能设备。 局域网连接:"Tasmota"的设计重点是在本地局域网内运行,这意味着您的设备的数据和控制命令在家庭网络内进行传输,提高了隐私和安全性。 开源和自定义:项目采用了开源许可证,允许开发者自由使用、修改和分发源代码,从而可以根据自己的需求自定义和扩展项目。 OTA更新:"Tasmota"支持通过网络进行固件更新,无需物理连接设备,提高了固件升级的便捷性。 如何使用Tasmota? 要使用"Tasmota"来打造自己的智能家居系统,您可以按照以下步骤进行: 安装Tasmota:使用"Tasmota WebInstaller"或按照官方安装指南将"Tasmota"固件安装到您的ESP8266或ESP32设备上。 配置设备:一旦安装完成,您可以通过web界面配置设备的各种参数,包括连接到您的家庭网络、设置MQTT服务器等。 连接智能设备:将各种智能设备(如智能灯泡、传感器、插座等)连接到您的"Tasmota"设备,可以使用多种通信协议,包括MQTT、HTTP、Serial等。 集成智能家居平台:通过与您使用的智能家居平台(如HomeAssistant)的集成,您可以创建自动化规则和场景,实现智能家居的自动化控制。 更新和维护:定期检查并更新"Tasmota"固件,以确保您获得最新的功能和安全性。 安全提示 在使用"Tasmota"或类似固件时,务必注意安全性和电气安全。如果您的设备连接到交流电源(AC电源),请务必正确安装设备以避免电击危险。如果您不懂如何安装,请咨询电工的帮助。 开源地址:https://github.com/arendst/Tasmota 官方文档:https://tasmota.github.io/docs/ 中文网站:http://tasmota.com.cn/ 结语 "Tasmota"为那些想要打造自己的智能家居系统的人提供了一个强大的工具。它的多平台支持和开源性质使其成为一个灵活和可定制的解决方案,能够满足不同用户的需求。如果您对智能家居技术和自动化控制感兴趣,"Tasmota"可能是一个值得考虑的选择,让您更好地管理您的家庭环境,提高生活的便利性。 --- ### 476. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在汽车制造行业中,物料的及时交付对于保持生产的顺利进行至关重要。诸如物料短缺、库存水平低以及质量控制问题等供应链中断会导致制造中断,最终造成经济损失。因此,工厂物流经理和生产经理必须努力保持供应链的流动,以维护制造过程中的质量和按时交付。 好消息是,有了正确的技术工具,你可以防止供应链的小问题演变成制造停机时间。让我们讨论一下现代汽车制造中的挑战,以及MQTT平台如何提供端到端的解决方案,帮助你保持主动而不是被动。 汽车制造供应链挑战 想象一下,期待着收到500个关键部件的运输,却只到达200个,这最终将导致生产线停机和库存危机。这是汽车制造商常见的痛点,供应链中的中断很快就会雪球般增大。问题不仅仅是运输短缺,而是直到货物到达并从卡车上卸下来时才知道。到那时要调整已经太晚了,两天后当材料用完时生产线将会停止。 大多数制造商根本没有这种对其供应链和物流的可见性,原因有多种。他们没有部署工业物联网解决方案来连接所有资产,实时跟踪它们,并根据这些情报采取行动。他们依赖于位于互联网连接有限的偏远地区的供应商,这使得跟踪运输和及时获取关键物流信息变得困难。 在问题出现时才采取应对措施的传统方法成本极高,已不再足够,因此汽车制造商正寻求建立正确的技术基础设施来克服这些挑战,及时将正确的信息传达给正确的人,以主动避免停机或质量问题。 实现端到端可见性 解决方案的出现。利用MQTT平台,帮助在OT和IT系统之间创建一个安全、可靠、可扩展的数据抽象层。一个集中的代理无缝连接各种系统,如运输管理、仓库管理和内部制造数据库。通过使用MQTT集成这些系统,整个供应链和制造过程变得相互连接,并且可以实时访问。 如何工作: 端到端可见性:从材料离开供应商的那一刻到它们融入装配线以及之后,MQTT物联网平台提供一个端到端的故事。实时跟踪确保每一步都被监控,任何偏差都会立即被标记。 自动警报:短缺或接收到的材料出现差异将触发自动警报,防止问题在库存水平变得关键之前被忽视。这种主动的方法对于维持生产数量和效率至关重要。 低带宽:在互联网连接较差的地区,MQTT的低带宽和小数据包大小变得至关重要。这确保即使在偏远地区,实时数据消息仍然可能。 预测分析:一个集中的仪表板,由诸如Grafana或云分析工具之类的分析工具提供支持,汇总来自MQTT代理的数据。这个仪表板提供了对生产线、供应链问题和潜在中断的可操作见解,使团队能够在问题升级之前解决它们。 预防关键停机时间,节省成本,提高效率 有了实时连接的正确解决方案,汽车制造商可以在它们导致关键停机之前识别并解决供应链中断。主动解决问题消除了最后一刻采取昂贵解决方案(如空运或加急运输)的需要,从而降低了整体成本。 端到端的可见性和沟通使制造商能够优化生产过程,提高整体效率,并始终如一地满足生产目标。 --- ### 477. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 TuyaLink 协议是涂鸦 IoT 开发平台面向物联网开发领域设计的一种数据交换规范,数据格式为 JSON,主要用于设备端和涂鸦 IoT 开发平台的双向通信,更便捷地实现了设备端和平台之间的业务数据交互。 设备的通信方式也是多种多样的。无线通信方式有蓝牙 LE、Zigbee、蓝牙 Mesh、433 协议,有线通信方式有 RS-485、RS-232、以太网以及各种工业协议等。但通信只是建立一个数据通道,要想真正运作起来,还需要了解数据包格式协议。数据协议包括 OCPP、Modbus、工业标准协议和其他自定义协议等。 本文介绍的 Tuya MQTT 标准协议是其中一种协议,也是涂鸦物联网平台最底层的基础通讯协议。开发者可根据协议完全自主地进行嵌入式开发,该协议可支持所有设备的集成。 本文以一款常见的 MQTT 客户端 MQTT.fx 为例,模拟设备使用涂鸦开放的 MQTT 协议接入涂鸦云。 MQTT 接入点 涂鸦 IoT 开发平台支持全球多个区域的设备接入,故需要根据设备实际使用的区域,来选择对应的接入点。 全球 6 大区 MQTT 接入点如下: 区域MQTT 接入域名端口号中国数据中心m1.tuyacn.com8883中欧数据中心m1.tuyaeu.com8883美西数据中心m1.tuyaus.com8883美东数据中心m1-ueaz.tuyaus.com8883西欧数据中心m1-weaz.tuyaeu.com8883印度数据中心m1.tuyain.com8883 环境准备 在 涂鸦 IoT 开发平台 创建产品,获取如下参数值。详细创建产品的过程请参考 选品类创建产品。 参数名称参数说明ProductID产品的信息DeviceID设备的身份信息,用于连接云端授权和通信使用DeviceSecret设备的密码信息 ,用于连接云端授权使用 接入示例 配置 MQTT.fx 接入文件 1.在 MQTT.fx 官网下载并安装相应操作系统版本的 MQTT.fx 客户端。 2.打开 MQTT.fx 软件,单击菜单栏中的 Extras 选项,并选择 Edit Edit Connection Profiles。 3.在 Edit Edit Connection Profiles 页面中填写相关参数。 参数名称参数说明Profile Name输入您的自定义名称Profile TypeMQTT 服务器连接,选择 MQTT BrokerBroker AddressMQTT 接入域名,对应 MQTT 协议中的域名,此处以中国区域名 m1.tuyacn.com 为例Broker Port通信端口号,设置为 8883Client IDMQTT 协议字段,格式为 tuyalink_{$deviceid}General使用默认值即可 4.选择 User Credentials 并填写相关参数。 参数名称参数说明User Name${deviceId}|signMethod=hmacSha256,timestamp=${当前 10 位时间戳},secureMode=1,accessType=1;例如:6c828cba434ff40c074wF2|signMethod=hmacSha256,timestamp=1607837283,secureMode=1,accessType=1PasswordhmacSha256(content, deviceSecret),content 的值"deviceId=6c828cba434ff40c074wF2,timestamp=1607635284,secureMode=1,accessType=1",按照 deviceId,timestamp,secureMode,accessType 这个顺序组装明文内容。64 位字符的 16 进制数,不足 64位时前面需要补零。 此处涉及到的 DeviceID 和 DeviceSercet 信息在 IoT 平台注册设备时生成,可参考 环境准备 章节找打到相应参数,Password 加密信息可以通过 Hmac 在线计算工具生成。示例如下: 5.选择 SSL/TLS,选中 Enable SSL/TLS 并设置 Protocol 为 TLSv1.2。 6.单击右下角 OK 完成设置,再去主页面单击 Connect。等待右侧指示灯变绿,表示连接成功。 测试通信 上行通信 在 Publish 页面输入发布的 topic,并填写 payload 信息,点击 Publish,此处以 tylink/6c855a6e81c40a91e9k5gx/thing/model/get topic 为例进行介绍。 进入涂鸦 IoT 开发平台的设备日志页面,输入 DeviceID 信息,可以看到刚才发布的消息,证明上行通信已经成功。 下行通信 在 Subscribe 页面输入 topic,点击 Subscribe,客户端会出现一条订阅的信息,此处以 tylink/6c855a6e81c40a91e9k5gx/thing/property/get_response topic 为例进行介绍。 进入 Publish 页面,输入与订阅对应的 topic 信息,并点击 Publish 发布 返回到 Subscribe 页面,可以看到刚才订阅的 topic 收到了云端的信息。 总结 涂鸦IoT平台的Tuya MQTT标准协议是一种基础通讯协议,用于支持各种设备的集成。文章以MQTT.fx客户端为例,介绍了如何使用涂鸦的开放MQTT协议接入涂鸦云。涂鸦IoT平台为全球多个区域提供设备接入支持,因此需要根据设备所在区域选择相应的MQTT接入点。文章还详细描述了如何在MQTT.fx中配置接入设置,包括Broker地址、端口、客户端ID、用户凭证和SSL/TLS设置。这一流程旨在帮助开发者理解并实现设备与涂鸦云之间的有效通信。 --- ### 478. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 预测性维护旨在帮助预测资产故障,并允许提前安排纠正性维护。这避免了意外的设备停机时间,提高了对客户的服务质量,并减少了预防性维护策略中过度维护所造成的额外成本。 应用场景 预测性维护技术可应用于石油和天然气、可再生能源、采矿、制造、食品饮料等主要行业。不同类型的资产,包括制造资产、信息技术资产、医疗设备等,通过生成系统消息、错误事件和日志文件来跟踪运行状态,这些可以用来预测即将发生的故障。 预防性维护与预测性维护 预防性维护是定期或按计划进行的维护,与资产状况无关。这是制造厂维护经理通常为防止计划外停机而进行的操作。 预测性维护只在必要时进行,取决于资产状况,即当设备出现故障或失败风险时。这使用了先进的分析技术。 尽管预测性维护的前期投资相对于预防性维护较高,但从长远来看,通过消除不必要的维护,运营成本可以降低。 如何实现预测性维护? 通过定期或持续监测资产状况来评估资产的健康和性能,从而实现预测性维护。通过连接不同资产和系统的IoT设备捕获的数据,使企业能够预测、计划并采取主动措施,以防止部件修理或资产故障等事件发生。为避免对业务造成干扰,预测性维护主要在设备正常工作条件下进行。 一种常见的实施预测性维护的方式是使用机器学习和人工智能技术获取机器维护和故障预防的洞察。这些技术的常见方面包括预测: 设备的生命周期所处阶段 设备的剩余使用寿命(RUL) 设备完全故障前的剩余周期数 这可以应用于各个行业,帮助实时监控机器的健康状况并及时进行维护,以减少过度维护的成本。 预测性维护的好处 安全、成本和资产管理都是投资预测性维护的重大好处。根据普华永道的一份报告,预测性维护平均可以: 降低成本12% 提高正常运行时间9% 减少安全、健康、环境和质量风险14% 延长老化资产的使用寿命20% 工业物联网(IIoT)技术和边缘计算助力预测性维护 在工业4.0和IIoT支持的工业过程中,资产通过IoT传感器和设备相互连接。这些连接的工业资产追踪相关的IoT数据,然后可以用来预测故障即将发生。智能IoT传感器在整个工业过程中使用,提供这些信息。 例如,安装在上游石油和天然气的远程油井中的传感器可以观察温度越过阈值,暗示油井或其某部分可能很快会发生故障。一旦通过传感器收集了数据,IIoT可以进行分析以主动预测结果。借助工业边缘的可见性和实时分析,制造商可以知道资产何时会发生故障以及如何发生故障,从而采取预防措施避免停机。 在需要在发生事件的地点附近做出决策时,边缘计算尤其重要。例如,在一些关键设备的油气作业中,基于边缘上的预测性维护算法预测故障并实施维护是重要的。这可以与云上运行的预测性维护算法结合,提供更全面的维护调度策略。 利用MQTT实现高效数据移动 采用IIoT技术进行预测性维护代表着制造商在当今动态市场环境中保持竞争优势的关键举措。然而,关键问题是:行业如何以可持续成功和持续创新的方式实施IIoT的数据移动? 答案在于采用行业标准的MQTT协议,被认为是IIoT的事实标准。 使用MQTT和Sparkplug进行工业数据采集和聚合 MQTT是一种标准的二进制发布-订阅消息传递协议,专为快速可靠地传输工业资产、系统和应用程序数据而设计,以实现预测性维护,尤其适用于非常受限的条件下。限制可能包括不可靠的网络连接、有限的带宽或有限的电池电量。MQTT建立在TCP/IP之上,这是互联网上连接网络设备的首选通信协议。因此,MQTT非常适合IIoT,支持事件驱动架构。 MQTT技术旨在将数据推送至企业内数千个远程资产、系统和应用程序,并从中获取数据。MQTT Sparkplug是一个位于MQTT之上的框架,为工业数据添加更多上下文。它是一个开源软件规范,为MQTT客户端提供了一个框架,以集成各种工业数据,并通过定义数据模型提供上下文。它为制造设备制造商和软件提供商提供了一种一致的方式来共享具有上下文的工厂数据,丰富了预测性维护数据。 MQTT Sparkplug基于的数据架构(如图2所示)展示了数据代理如何连接多个机器/流程和应用程序,以实现OT(运营技术)和IT(信息技术)系统之间的无缝双向工业数据移动。 MQTT Sparkplug支持的架构 图2:一个基于MQTT Sparkplug的架构,支持多个工业数据生产者和数据消费者之间的OT到IT桥接,从而实现预测性维护。 在企业IIoT策略中,MQTT越来越受欢迎。根据IIoT World在2022年进行的一项调查,MQTT是实现IIoT策略所必需的数据移动工具中的明显优胜者。 获取实施预测性维护所需的数据 MQTT协议与Sparkplug一起,因其轻量级、按异常报告以及围绕安全性、可伸缩性、可靠性等方面提供的众多功能,正日益受到工业边缘到企业/云通信的欢迎。MQTT正在推动IIoT应用,使工业流程公司能够在其资产上实施预测性维护。预测性维护反过来使公司能够降低维护成本、提高资产利用率、延长资产寿命,并提高安全性/合规性。 通过将IIoT与MQTT无缝整合,实现工业运营中的双向数据移动,公司可以在其流程中引发范式转变,增强市场地位,并为更加繁荣和高效的未来打下坚实的数据基础。 --- ### 479. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 在交通和物流行业,高效的车队管理对于确保车辆的顺畅运营和优化配送过程至关重要。一项正在转变车队管理的关键技术是MQTT。这种轻量级且高效的消息传输协议旨在促进实时数据通信,使其成为解决该行业独特挑战的完美工具。让我们深入了解MQTT如何改变车队管理游戏规则。 为什么MQTT适合车队管理? 实时洞察:车队管理依赖实时数据。MQTT允许交换关键信息,使公司能够实时监控他们的车辆和驾驶员。这种可见性对于数据驱动的决策制定和运营效率至关重要。 高效的数据传输:MQTT的轻量级设计确保数据可以高效传输。无论是追踪车辆、监控驾驶员行为还是管理路线,MQTT都能以最小的开销处理数据交换,确保快速且无缝的通信。 可伸缩性:车队管理需求随着需求变化。MQTT提供可适应业务变化需求的可伸缩性。它可以轻松地随着车队的增长而扩展,确保灵活性和效率。 可靠性:确保车队的持续运营至关重要。MQTT的服务质量(QoS)级别保证了即使在挑战性条件下也能可靠地传递消息,使其成为任务关键型应用的理想选择。 交通和物流公司如何使用MQTT进行车队管理 以下是MQTT在车队管理中的一些主要用途: 实时可见性:MQTT允许对车辆进行实时追踪,提供最新的位置和状态更新。这项能力有助于监控和改进交付时间表,优化路线,并提高整体车队效率。 优化路线:MQTT使企业能够收集和分析有助于路线优化的数据。通过监控交通状况、道路关闭和其他相关因素,车队经理可以即时调整路线,减少行驶时间和燃油成本。 监控车辆健康:车队维护是确保车辆可靠性的关键方面。MQTT协助远程监控车辆健康状况,提供实时诊断和维护需求警报。这种主动方式减少了停机时间,并延长了车队资产的使用寿命。 分析驾驶员行为:通过MQTT收集的IoT数据使公司能够详细了解驾驶员行为。公司可以追踪诸如速度、刹车和怠速等方面,帮助提高安全性,减少燃油消耗,并对驾驶员培训做出明智的决定。 例如,HiveMQ的客户FELA Management,已经为巴士、铁路和物流创建了创新的基于GPS的信息和追踪系统超过50年。他们最近采用了MQTT进行车队管理,以实现几乎实时的信息交换,使他们能够更准确地了解车辆运动。连接到HiveMQ代理的设备数量根据运输公司的车队规模而大幅波动,FELA发现HiveMQ MQTT平台有足够的性能来处理多个应用的需求。 另一个例子是宝马移动服务,宝马集团内的一个业务团队,为车队运营商提供共享汽车产品。该服务为车队运营商提供远程管理车队的能力,发出对单个车辆的远程命令(例如上锁/解锁)并从每辆车收集数据。使用MQTT帮助宝马将开锁时间从最高30秒减少到不到一秒。 如何开始使用MQTT进行车队管理 HiveMQ处于利用MQTT革新交通和物流行业车队管理的前沿。其实时能力、高效的数据传输、可伸缩性和可靠性使其成为希望优化车队运营的公司的理想选择。通过利用MQTT,企业可以实现成本削减、安全性提升和效率提高,最终创建一个更加精简和响应迅速的车队管理系统。 --- ### 480. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着整个汽车出行领域智能化和网联化的发展,车机成为连接“人-车-云”之间的交互窗口,是当前汽车智能化、网联化的核心组成部分。这一“人-车-云”的交互窗口不仅能够实时获取车辆数据和车主使用情况,而且为车主提供了一系列个性化的服务,如寻车定位、个人兴趣点推送等。因此,各大汽车制造厂商正积极构建基于数据和服务的车联网TSP平台系统,旨在提供更智能、人性化的驾驶体验。 在构建能够满足当今消费者多样需求的车联网 TSP 平台时,汽车主机厂面临着一系列技术挑战。这些挑战包括可靠的车云连接、有效的数据传输以及灵活的数据处理等方面。为了应对这些挑战,EMQ提供了一套车云互联基础设施解决方案,助力客户应对海量车机、Tbox与云端TSP的连接与上下行数据交互需求。以下是基于EMQX的高性能、高可用车联网TSP数据底座解决方案的一些关键特性。 MQTT协议:连接“人-车-云”的纽带 MQTT(Message Queuing Telemetry Transport)是一种专门针对低带宽、高延迟、不可靠网络等场景而设计的轻量级消息传输协议。其发布/订阅模式、会话保持机制、QoS消息质量机制使其在车联网场景中表现优越。EMQX作为基于MQTT协议的企业级数据接入平台,连接车辆和云端,提供连接和数据解决方案。EMQX的高性能、高可靠、可伸缩性设计,能够实时移动和处理车联网数据,帮助车企解决海量连接、高数据吞吐、安全认证、复杂网络环境等挑战,使开发团队能专注于上层应用的开发。 整体架构:分布式、高可用 为满足数据保护需求,车企的车联网平台通常采用私有化部署。EMQX集群和用户业务系统通常一同部署在IDC或公有云环境中。通过负载均衡与EMQX分布式集群部署,可实现百万级别的车机连接和数据吞吐能力,为上层业务应用提供坚实接入基础。 车机连接:高并发、高安全 车机通过蜂窝网络物理链路、MQTT协议接入EMQX,EMQX分布式高可用架构支持百万级并发连接。在连接安全方面,EMQX支持TLS安全协议,通过单向、双向TLS认证接入以及与PKI/CA系统对接,实现一机一密的认证方案。此外,EMQX提供实时感知连接状态的能力。 数据传输:多保障、高吞吐 依靠MQTT及EMQX提供的多重保障机制,即使车辆因网络原因断开连接,消息传递仍能在重连后恢复,实现在复杂的网络环境下实时、安全、可靠的车机消息通信。EMQX支持每个车机与平台连接内建立多个逻辑隔离的MQTT主题,支持上下行不同业务数据传输。 消息及事件的处理与集成:灵活、高效 通过内置的规则引擎,EMQX能够对车机上报数据消息及车机连接或断连等事件进行预处理,桥接集成到相应的数据系统。这使得海量车机上行数据能够经过编解码等预处理后,桥接到消息队列进行后台应用服务的分析应用。同时,EMQX支持对车机连接、断开连接等事件信息存储到数据库中,用于后续车辆上下线情况的分析等。 高效的监控运维:可视化、实时 EMQX提供直观的可视化监控和管理界面,用户可实时监控车机连接状态和消息流量指标。此外,EMQX支持接口将监控数据推送到客户监控系统,实现高效的监控运维。热配置修改、热升级的机制确保在配置调整时无需停止服务,最大程度保证车机连接及数据传输的持续性。慢订阅、日志追踪等功能帮助客户快速排查连接异常、消息接收时延过大等问题。 构建车联网 TSP 平台面临的挑战 随着汽车保有量不断增长,平台需要支持海量车机并发连接。在高峰时期,平台需要维持数十万量级的并发 连接。同时,为了实现丰富的业务场景,平台需要支持百万级的消息吞吐。随着车辆互联度的增加,车辆容易受到网络威胁,因此连接的安全性成为关键挑战。车辆所处网络环境的复杂性也带来了保证消息实时性与可靠性的挑战。最后,业务侧对数据的不同需求,如何实现灵活的数据分流、存储也是一个亟待解决的问题。 未来展望:智能出行的无限可能 面对车联网 TSP 平台的技术挑战,EMQX以其卓越的性能和灵活的解决方案助力汽车主机厂构建高性能、高可靠、易于维护的车联网TSP平台。未来,随着技术的不断演进,智能出行将迎来更多可能性,连接“人-车-云”的纽带将越发牢固,为用户创造更智能、便捷、安全的驾驶体验。EMQX将继续在智能车联网领域发挥重要作用,推动整个行业向更高水平迈进。 --- ### 481. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 MQTT协议的主题设计在车联网(TSP)平台中起着至关重要的作用,它不仅是消息通道的标签,也是业务与数据的关键区分点。在设计MQTT主题时,我们需要考虑一系列原则和最佳实践,以确保系统的可维护性、性能和安全性。 基础概念 MQTT协议涉及三个关键角色:消息发布者(publisher)、代理服务器(broker)和消息订阅者(subscriber)。消息从发布者发送到代理服务器,然后被订阅者接收,而主题则是发布者与订阅者之间约定的消息通道。 主题的定义与规范 MQTT协议规定主题是一段UTF-8编码的字符串,具体规则包括: 主题名和主题过滤器必须至少包含一个字符。 主题名和主题过滤器是大小写敏感的。 主题名和主题过滤器可以包含空格字符。 主题名或主题过滤器以前置或后置斜杠 / 区分。 主题名和主题过滤器不能包含null字符(Unicode U+0000)。 主题名和主题过滤器是UTF-8编码字符串,层级数量没有限制。 主题层级 MQTT协议允许通过斜杠将主题分割成多个层级,从而实现对消息类型的细分。例如,可以通过定义主题层级来区分不同车型、车辆或业务类型。 通配符 MQTT协议支持通配符,订阅者的主题过滤器可以包含特殊的通配符,如#和+,用于一次订阅多个主题,实现更灵活的消息订阅。 多层通配符(#)用于匹配主题中任意层级。 单层通配符(+)用于单个主题层级匹配。 车联网TSP平台场景中的需求 在车联网TSP平台场景中,MQTT协议作为车辆、平台和应用之间的业务消息通道,主题设计需要考虑不同数据方向、车型、车辆、用户、研发环境和数据吞吐量等因素。 主题设计原则最佳实践 根据业务数据方向区分:明确上行和下行数据的主题,有助于快速定位场景和问题。 根据车型区分:通过主题区分不同车型产生的数据,适应差异化的车辆数据和业务需求。 根据车辆区分:实现一对一消息通道,保证车辆间业务信息隔离和点对点交互。 根据用户区分:考虑用户级别的一对一消息通道,适用于促销、运营和ToB业务场景。 根据研发环境区分:通过添加环境变量实现在不同研发环境下的资源复用和正确性检查。 根据数据吞吐量区分:区分不同数据吞吐量的业务,适应不同的处理和架构设计。 通过以上主题设计原则,车联网TSP平台可以实现清晰的业务隔离、快速问题定位和灵活的消息通信,满足不同业务场景的需求。这种细致入微的设计有助于提高系统的可维护性和性能,为车联网生态的健康发展提供坚实基础。 --- ### 482. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 系统架构 智慧场站建设范围包括升压站智能巡检、室内外轨道机器人巡检、升压站实景三维、无线覆盖、辅助控制系统以及风机测温与监视等,该系统软硬件部署在场站端的三区,支持系统间联动。本系统支持和生产管理平台集成,在生产管理系统中即可完成对全场智能应用的全面掌握,整体系统架构图如下: 系统应用特点 边缘感知 本方案以视频智能物联网技术为基础,通过智能机器人、可见光视频、红外热成像、门禁、消防网关等,汇聚采集风电场内的人员行为、设备温度及工况、环境状态,在线监测场站内的人、机、物、环,实现泛在物联。 视频设备具有区域入侵、越界侦测、安全帽检测、人员倒地、单人无监护作业、动火作业、跑冒滴漏、表计识别等分析能力,可通过内置声光报警或外界音柱报警,应用于场站安全防范、设备巡检、作业监管;红外热成像设备具有周界防范、设备精准测温、吸烟检测、等分析能力; 系统方案价值 系统方案价值可概括为以下四个方面: 拉近管理距离:通过综合数据看板、AR实景一张图等可视化形式,集中展示风电场生产运行数据,提升集控管理效率,帮助管理者更好地掌控全局管理视角,拉进管理者的管理距离。 提升业务效率:基于音视频、传感器等智能物联感知技术,助力风电场全面感知,逐步实现升压站、风机、输电线路等场景远程智能巡检,提升运检效率。 规范作业行为:与两票系统对接,获取作业任务相关信息,并结合风电场高风险作业场景,制定合适的前端布控方案,结合智能移动终端,对常见的违章作业行为进行主动识别分析,实现作业安全智能管控,进一步规范作业人员行为,提高安全生产意识,加强安全管理水平。 防范安全隐患:通过AI加持,对风电场的不安全因素进行有效的监测预警,并进行风险防范与应急处置,减少和控制事故与危害,尽量避免生产过程中由于外部入侵破坏、内部生产事故造成的人身伤害、设备资产损失以及其他重大损失。 智慧场站建设 智慧场站通过分布式部署灵敏度高的传感器,实现对各类设备得智能在线监测,并将信息上送智慧运营平台,通过平台故障预警与诊断以及健康评估等功能,及时发现隐患,在故障早期就能查找出导致问题出现的原因,以便采取相应措施加以预防和解决问题,避免恶性事故的发生,保障设备的安全运行,降低维修成本。具备对设备当前运行状态的健康评估,当设备处于异常状态时,系统发出警告或报警,实现系统联动,并可对报警部位进行进一步的故障分析和处理。通过平台对设备进行统一编码,建立各部件相应台账,实现对其全生命周期管理功能。 升压站智能巡检 远程智能巡视系统建成后将实现对升压站巡视信息的集中管控,系统包括了信息总览、实时视频、智能巡视、巡视报告等模块,在此基础上开展了场站设备区域图形化监控、设备一次接线图监控、设备单点识别等特色功能建。 信息总览 信息总览展示的是智能巡检的重要信息统计、分类及分析,集中展示巡视类型统计、任务状态统计、告警等级统计、摄像机统计、告警类型统计、摄像机状态统计、识别类型统计、缺陷等级统计并采用图形、图表等多种展现方式,不同维度对统计结果的数据进行可视化展示。 实时监控 实时监控分为:视频监控、红外监控、巡视点位监控等。 视频监控可以实时调阅室内外监控,查看设备情况以及人员流动情况。 红外监控可对接头等温度敏感点位进行红外测温,目前系统支持框选测温和点测温。 巡视点位监控可对重点部件的重点点位进行单点巡视,检查设备状态。 智能巡视 任务管理 智能巡视系统可远程进行任务管理功能,巡视任务内容应包括巡视点位信息以及月、周、日、小时等不同时间维度的巡视周期,巡视类型应包括例行巡视、熄灯巡视、特殊巡视、专项巡视、自定义巡视等,其中,恶劣天气特巡包括大风、雷暴、雾霾(含毛毛雨、大雾等)、雨后、下雪、气温骤变(含低温天气)、高温、冰雹、覆冰、沙尘暴等 ;专项巡视包括设备红外测温、油位油温表抄录、避雷器表计抄录、SF6 压力表抄录、液压表抄录、位置状态识别抄录等。具体功能如下: 巡视任务新增后可以进行修改、查询和其他管理功能;巡视任务启动后可暂停、终止,在巡视过程中可以查阅已巡视点位详情, 每个巡视点应包含本次巡视任务的全部采集信息; 任务管理模块具备月历与日历相结合的展示功能,月历应展示每日计划执行的主要任务名称及个数;日历展示当日任务的信息列表,包括任务名称、执行时间、任务状态等;不同任务状态应以不同颜色加以区分。可按时间段、任务名称、任务状态等组合条件,查询任务列表功能。 所有点位均确认后,可直接生成标准巡视报告。 任务记录 任务记录主要是历史执行记录的查询及数据展示,包含巡视任务、任务进度、已巡视点位信息、告警点位信息,巡视失败点位信息等。 巡视监控 巡检监控展示了站端的巡检任务列表,并可进行任务的新增和执行,可查看巡检任务单详情及执行的任务进度,并实时关联视频。同时展示了站端环境信息及设备运行状态,以及巡检的实时信息及报警信息。具体功能如下: 以列表形式展示巡视点位信息,用户根据巡视结果信息,可以点击查看详情,核实巡视结果,识别错误可直接确认消缺; 支持巡视视频同步; 通过树形导航调阅高清视频和机器人画面; 可多画面轮巡及画面显示; 巡视报告 系统可根据巡视记录的数据自动生成巡视报告,巡视报告具备查询、浏览、导出功能,具体功能如下: 系统在巡视任务审核完成后能自动生成巡视报告; 可通过设备区域、间隔名称、设备类型、检测类型、巡视时间段等组合条件, 查询历史巡视报告功能; 巡视报告可以查询、重置、导出、查看等功能。 智能联动 当巡检过程中识别到有告警时,系统能在第一时间触发智能联动功能,智能联动主要功能有: 告警联动应用场景包括充油充气设备油面温度与绕组温度异常、轻瓦斯动作、SF6压力低、油位异常、消防告警、乙炔突增告警、压力释放动作告警、开关变位; 系统实现的告警联动动作包括服务端自动抓拍图像、指定用户或客户端IP自动弹出视频画面、指定用户或客户端IP启动声音提示等; 系统告警界面最多仅弹出一个视频告警浮动窗口,视频窗口中叠加对应的告警信息,当告警需要弹出画面、且画面正在显示其他告警信息时,仅在告警列表中显示对应告警; 告警视频弹窗具备视频窗口双击放大功能、视频缩放及云台控制功能; 告警声音从获取告警信息开始,直至告警确认停止声音提示; 在系统屏幕右侧有告警信息集中展示列表,所有告警信息可以逐条显示,可以切换告警视频弹窗所显示的视频,当告警信息存在多个视频画面时,系统可以相应提示,由操作人员选择显示具体视频画面信息; 系统的告警信息确认功能在确认后相同的告警信息不再进行任何联动动作; 系统可以自动合并多条重复告警信息功能,重复告警仅执行一次告警联动动作; 系统可以联动查看报警设备历史告警信息以及相应历史数据。 可以在系统内根据集控站监控系统的告警信号配置联动策略,联动策略配置可以选择一个或多个视频设备。 运行分析 运行分析可对单点或者多点的历史数据进行调阅及数据分析。 台账管理 系统从升压站远程智能巡视系统获取机器人、视频设备信息,并与升压站远程智能巡视系统保持台账信息的一致性; 系统内可以进行机器人、视频设备台帐信息的查询,并按照生产厂家、设备类型、设备型号、设备来源、使用类型、运行状态等维度进行数据检索。 配置管理 配置管理界面可实现巡视报告配置、视频监控配置、联动信号配置以及消息权限配置。 巡视报告配置主要是对报告的格式进行配置,可生成标准报告和标准作业指导卡。 视频监控配置系统可以按1/4/9/16/全屏多种分屏模式配置轮巡方案、画面切换的时间间隔、画面调用的摄像机等。 联动信号配置主要是针对事件化联动进行配置相关抓图联动、视频联动、巡检联动的配置。 消息权限配置管理可以配置账号权限、身份鉴别与访问控制等。 特色功能 区域图形化监控 区域图形化监控可以通过站内平面图,快速调阅巡视点位附近的摄像机对点位进行视频监视。 一次接线图监控 一次接线图监控可以通过主接线图,调阅间隔附近摄像机对间隔内问题点位快速定位并进行视频巡视。 单点识别 单点识别是一种实现快速巡视某一个设备部件的巡视方法。当临时需要查看某个设备部件的状态时,可以通过单点识别模块查到到相应的点位,然后执行即时识别、分析,无需建立巡视任务,从而实现快速巡视的目的。 机器人巡检 机器人系统整体介绍 智能巡检机器人系统主要针对室内外电力场景的内部设备及其周边环境实现自主化无人巡检;由电路板、升降机构、行走机构、高清摄像头、红外热像仪、局放传感器等核心设备和其他辅助设备组成。 机器人运行采用吊轨式以及轮式行走,确保检测精度、采用多节升降模块确保对竖直检测面的覆盖;采用三轴分立式云台结构,实现传感器模块在竖直轴和水平轴的转动自由度,保证设备检测位置最优化选取。 为确保机器人在运行过程中的安全性,智能巡检机器人搭载了激光避障模块,通过激光传感器实时探测其水平、垂直方向上的障碍物,一旦检测到障碍物,立刻停止运行,待障碍物移走后继续执行巡检任务。智能巡检机器人结构如下图所示。其智能检测模块由人机交互模块、局放传感器、红外热像仪、可见光相机等组成,实现机器人仪表图像识别、红外测温、局放检测等功能;检测模块采用三轴分立式设计,可在垂直、水平方向上自由旋转,实现传感器检测位置的最优化选择,杜绝检测盲区;红外热像仪和可见光相机采用共体双向结构,能够对两侧的设备进行同时检测,极大的提高了巡检效率。 电力智能巡检机器人 全覆盖自主巡检实现方式 电力场景大多巡检空间较小,尤其内部待检测设备分布高差大,且部分设备安装位置偏僻,不易观察,巡检覆盖范围狭窄、信息提取困难,准确性不高,在巡检时存在误测、漏测等情况,降低巡检数据可靠性。为解决这些问题,创新研发了一种机器化巡检复杂空间精确定位技术。首先基于配电网环境状况和设备分布状况,将巡检空间分解为沿三个直角坐标轴方向的移动自由度,以及两个绕轴旋转的转动自由度。 图3.5 巡检空间的五自由度分解 进一步的,利用行走完成机器人在x轴上的水平移动,实现对巡检平面的遍历;利用多节升降机构,完成对垂直检测面的覆盖,并结合绕x轴、z轴的两个转动自由度,实现对设备检测的最优化点位标定;最后,利用伸缩式检测臂,完成在y轴上的移动自由度,实现与设备的接触式检测。 精确定位方面,轨道上采用基于多传感器融合的轨道定位技术,利用站点定位片将长距离轨道分割为等间隔定位区间,消除定位累积误差;各部件运行定位方面,采用绝对值编码器配合电机双闭环控制算法,确保运行可靠性和定位准确性。基于精确定位手段,机器人根据预先标定的检测设备位置,结合视觉伺服技术,实现按预设巡检策略的自主、精确巡检。 指针类仪表设备识别实现方式 采用基于Hough直线检测和对称性检测算法,完成指针边缘的精确提取,根据指针偏转角度计算获取仪表读数。首先基于Canny边缘检测算法提取图像边缘,获取表计图像梯度,对梯度进行非极大值抑制,采用双阈值算法初步滤除伪边缘。随后,基于指针的对称性特征,提取图像中的对称边缘点对,并采用Ransac共线性检测去除伪指针边缘像素对,最后对边缘点对进行聚类合并,获取指针对称轴,从而准确识别指针位置,滤除传统指针识别算法中的环境干扰,并提升指针识别的位置精度,提高识别准确率,识别精度可达小数点后3位。如图3.6所示。 图3.6 基于对称特性的指针识别 数字类仪表设备识别实现方式 采用基于AlexNet卷积神经网络完成字符识别、基于Cascade Classifica-tion目标检测完成小数点定位。Alexnet卷积神经网络共有卷积层5个,池化层 3个,全连接层3个(其中包含输出层),摈弃了传统神经网络中需要人为指定图像特征的缺点,利用卷积神经网络中的卷积层自动完成特征提取工作,并用多层小卷积叠加来替换单个的大卷积,提升卷积层的厚度和宽度,优化卷积层表达能力;并使用重叠的最大池化,避免平均池化的模糊化效果。识别的准确性和快速性得到了显著提升,对字符的适应性更强。 图3.7 AlexNet卷积神经网络 电气指示类设备识别实现方式 基于指示灯和背景区域的亮度,采用自适应二值化、阈值化方法进行指示灯亮灭、指示灯颜色的自主识别与检测。传统的二值化方法通常采用全局阈值法,即将图像中低于某个阈值的像素设置为黑色,而其他的设置为白色。在实际工程应用中,室内空间的各类设备可能会受到吊灯、窗户、移动的影子、自身颜色等影响,人类的视觉系统能自动补偿这些,但是机器没有考虑到这些因素,因此导致识别效果较差。为此,采用一种阈值自适应的二值化算法,根据每个像素的背景亮度来改变阈值,这种基于局部特征的二值化方法,对各类环境和设备类型具备更好的适应能力,如图3.8所示。 图3.8 自适应二值化方法效果 机械状态指示类设备识别实现方式 电力设备机械指示种类繁多,根据机械状态的类别不同,采用基于直线检测的偏转角度计算、基于AlexNet网络的状态分类方法、模板匹配、颜色检测方法等多种检测算法,有针对性的完成对不同种类机械状态指示的准确识别。 局部放电检测实现方式 机器人采用地电波(接触式)和超声波手段,获得设备局放情况,能够将放电信息实时地传递到远程数据中心,当检测到开关柜设备内局部放电处于异常状态时,立即进行报警,提示管理人员到现场维护。通过局放检测设备,实现不同时刻和位置的电力柜局放监测。局放检测设备数据及控制后台具备局放数据自动绘图、自主识别和诊断功能,在局放出现异常情况下可以实现实时报警、应急模式巡检及系统联动功能,同时数据后台能够对单点检测数据进行历史分析,并进行归档、诊断等功能;地电波+超声波的局放检测方式,拓宽了检测频带、提高了检测灵敏度,并结合时间维度上的趋势分析,实现设备局部放电的精确监测。 设备测温实现方式 机器人搭载红外热成像仪,对机器人巡检区域的电气设备进行测温,进行设备致热现场检测与缺陷诊断,根据致热设备运行状况进行诊断分析,及时发现设备潜在缺陷并发出预警,提前进行设备防护,消除隐患,提高设备运行寿命和效率。 对于站用变、蓄电池室、主变室、散热室及电容器室等场所的测温采用固定热成像球机进行检测。 数据及控制后台具备温度数据自动绘图、自主识别和诊断功能,在温度出现异常情况下可以实时报警,同时数据后台能够对单点检测数据进行历史分析,并进行归档、诊断。 图3.10 设备柜红外测温 室内挂轨巡检机器人可以搭载红外热像仪、可见光高清摄像机、气体探测仪、温湿度传感器、交互式实 时对讲平台、声光报警器、光电停障系统等,系统采用我公司自主研发的通用可配置软硬件平台控制,全工业化元器件设计,系统运行可靠,功能齐全。 室内挂轨机器人具有可见光与红外视频图像采集功能,工作人员可通过上位机软件操作机器人移动到指定位置,控制云台自由转动,可实现近距离地观察拍摄目标物体,将监控范围覆盖到盲区。机器人可拍摄出站内各种设备高清图像和红外热成像,并将采集到的信息经局域网实时传输到主控室,在主控室的工作人员便可根据图像判断出各种电力设备是否安全。当发现设备有异常情况,工作人员可在第一时间查清问题原因,并采取相应措施。 在巡检过程中,室内挂轨机器人通过自身携带的一体化云台装置,可对周围环境进行视频图像的采集,并根据工作人员的需要将图像信息经在线通讯传回主控室,并自动记录拍摄地点和设备名称,以备工作人员日后能查询完整的信息。 室内挂轨机器人本体 室内挂轨机器人系统由室内挂轨机器人本体、轨道平台、供电平台、网络通信平台、定位模块、后台监控平台等组成。 室内挂轨机器人 室内轮式机器人本体 室内轮式机器人系统由室内轮式机器人本体、供电平台、网络通信平台、定位模块、后台监控平台等组成。 室外轮式机器人本体 室外挂轨机器人系统由室外轨道机器人本体、供电平台、网络通信平台、定位模块、后台监控平台等组成。 自主导航 智能巡检机器人根据巡检任务自动巡检;视频监控根据巡检任务自动调用对应的固定摄像机,并自动完成摄像机观测位置和角度调整。 自动记录 自动采集并记录巡检任务对应的各类设备巡检数据,按设备树归类展示,并自动生成巡检报告,包括例行巡检、专项巡检及自定义巡检报告等。 智能识别 利用图像识别技术,对巡检过程记录的可见光照片等进行智能分析,自动判断设备状态。 可见光检测功能 可见光检测具备如下功能: 机器人配备可见光摄像机,能对室内设备外观、开关 、刀闸 分合状态及仪表、油位指示、刀闸传动轴划线的外观;保护装置状态指示灯;压板空开位置、保护装置液晶屏显示进行准确拍摄 进行采集并将视频实时上传至本地监控系统。上传视频分辨率高清规范(1080P),且分辨率可手动调整。 存储采集到的视频,支持视频的开始录像、停止录像、播放、停止、重启、抓图、全屏显示等功能。 最小光学变焦数30倍,可在10米距离外清晰识别表计刻度。 红外检测功能 红外检测具备如下功能: 机器人配备在线式红外热成像仪,能对一次设备的本体和接头的温度进行采集,并能将红外视频及温度数据实时传输至本地监控系统。 存储采集到的电力设备红外热图,并能从红外热图中提取温度信息,可自动追踪测量全屏最高温。 红外检测设备成像像素不低于640×510,测温精度不低于±1℃。 防碰撞 机器人具有障碍物检测功能,在行走过程中如遇到障碍物应及时停止并报警,指定时间内障碍物移除后应能恢复行走。 自动充电功能 机器人采用电池供电模式。 具备自动充电功能,在需要充电时能够自动返回充电座,通过与充电设备配合完成自动充电。 在电量较低时,控制各个模块供电,并返回充电,监控电池容量,预测电池寿命,容量低于限制时远程报警。 因自动充电而中断巡检任务时,充电完成后能够根据设置恢复或停止巡检任务。 具备充放电次数记录和展示功能。 双向语音对讲功能 机器人具有双向语音对讲功能,配有音频采集和播放设备,能通过安全的无线通信方式接入,与本地监控系统之间的全双工双向语音传输。 双向语音传输的语音质量和延迟满足远程视频指导的要求。 辅助照明功能 机器人具备辅助强光照明功能,能保证在夜间或阴暗天气下正常运行。 状态指示 机器人具有状态指示功能,在作业时能提供状态信号。 远程遥控 运维班可实现自动巡检装置的远方人工遥控,主要包括智能巡检机器人、视频监控等。 室内外全覆盖 综合各种巡检技术手段采集数据,按照巡检任务要求自动完成升压站室内一次、二次设备设施的全覆盖巡检。 升压站实景三维 升压站实景三维是运用基于精确空间位置信息的全站点云及三维数据,结合高性能、强兼容的三维数字孪生引擎,实时渲染构建一个与升压站外观一致、坐标一致、属性一致的数字孪生升压站,开发全景可视化的立体监盘功能,打造升压站的数字化全景监控。 指哪看哪 利用空间视野分析技术,实现对关注目标的视频视野画面自动匹配、自动聚焦,监控人员无需关注具体摄像机安装位置,在三维场景中通过鼠标点击想要查看的设备部位目标即可自动打开视频画面,摒弃传统查找摄像机转动云台搜寻设备目标的繁琐操作。 数据可视化 三维实景系统通过标准化接口(如websevice、json、私有API等)将升压站内数据融合,数字孪生应用模块通过调用接口将数据与设备模型进行映射,监控人员通过点击设备模型显示设备当前实时数据,查看设备运行状况。 位置可视化 通过点选设备类别可以实现快速查看升压站内各设备对象的位置分布信息,比如选择视频监控,则孪生三维场景中只显示跟摄像机相关的模型可视化标签,监控人员即可一目了然了解摄像机在升压站内的分布,并通过直接点击摄像机标签即可实时打开摄像机视频画面进行浏览,如下图所示。 告警可视化 在智能图像识别模块发现异常后,根据缺陷库迅速分析出故障类别,准确定位故障位置,自动锁定目标,以部件“闪烁”的形式实现漏油、漏水、放电、发热等故障的可视化告警,并以语音播报方式进行提醒,便于运维人员快速了解告警信息,准确标识故障位置,加快故障处理速度。 通过数字孪生系统数据接口实时监听设备告警信息,将接受到的告警信息通过着色在孪生三维场景中进行高亮显示,并自动定位到告警设备位置,方便监控人员快速了解告警设备信息,如下图所示。 升压站智能安防及辅控 升压站辅助设备监控建成后将实现对栖霞站的动力环境子系统、安全防范子系统、视频监控子系统、在线监测系统、物联网感知等子系统的实时监控,并在此基础上进行特色功能区域监视的开发。 智能安全防范 对于陆上风电场,以视频为核心的多维感知技术手段,可帮助风电场打造安全防范三道防线。 第一道防线: 周界通过热成像、可见光视频、电子围栏、等构建两级报警,先检测人员在围墙外围区域内徘徊或者停留,再检测是否进入围墙区域;大门区域通过全彩球机实现人员区域入侵侦测、徘徊侦测、人员聚集侦测等功能;大门口部署门禁闸机配套人脸识别一体机,比对成功后实行自动开门。 第二道防线: 在主控楼大厅,通过人脸比对检测是否为准入人员,进入一次场地区域的入口处,通过人脸比对检测是否为准入人员。 第三道防线: 在主控楼各小室(如开关室、集控室、通信室)出入口,部署人脸识别一体机,通过人脸比对来开启门禁。 风电机组三道防线如下: 第一道防线:塔筒外围区域及塔外梯区域,通过全彩球机实行人员区域入侵侦测、徘徊侦测、人员聚集侦测等功能。 第二道防线:塔筒底层入口处,通过轻智能相机,配合视频智能分析服务器,检测人员数量,识别是否为准入人员,是否为单人无监护作业。 第三道防线:通过可见光视频或双光谱热成像,自动监视进入机舱人员的作业行为。 安全防范展示的是站端安防设备,包含电子围栏、门禁、人脸识别等。可展示平台所属范围内的所有门禁系统,并可联动相应场景门禁的监控视频,可便捷地进行各门禁场景的视频切换。门禁系统解锁方式可采用人脸识别开锁、按钮开锁、刷卡开锁等功能,并可与安防系统实现撤防和布防的联动。可展示电子围栏设备的节点状态,及联动视频。 电子围栏 可以查阅电子围栏及红外对射的实时状态及数据。 智能门禁 可查阅大门处实时视频监控;查阅人脸刷卡机、卡片机等刷卡记录;展示门禁台账以及状态;对人员权限进行管理等功能。 人员车辆管理 风电场一般位置较偏,外来人员、车辆相对较少,但考虑到风电场是电力系统的重要场所,需要对所有进出风电场站的人员、车辆进行有效管控。 风电场人员主要有内部员工、外包人员和外来访客。 对于内部员工,通过人脸门禁、人脸智能监控系统,方便在场站和风机内部通行,辅助其进行对重要设备区域的安全管控。 对于外包人员管理,借助智能化技术手段,加强对外包人员的准入权限、是否上岗到位(出勤情况)、作业行为是否合规等监管。 对于外来访客,通过访客管理系统,辅助进行访客实名制管理,加强安全准入管控,提升访客管理效率。 此外,通常情况下,风电场内部车辆和施工用车才会周期性进出电站。风电场作为电力系统的重要防护对象,需杜绝无关车辆进入,对进出车辆进行识别和记录。通过车牌抓拍识别专用相机,对进出风电场站的车辆进行抓拍记录,方便后期按需查询。所有车辆经安保人员检查核验后,由安保人员控制伸缩移门或其他实物门予以放行。 动力环境 环境监测-水浸传感器 可展示当前生产设备区电缆沟或电缆层水浸传感器的位置分布,并统计所有水浸的报警器总数、故障数及单个设备节点的历史数据。 2) 环境监测-风机控制 可展示升压站风机状态并能远程对风机启、停控制,同时可智能联动。 环境监测-温湿度 可展示升压站温湿度传感器的温度、湿度等数据监视,同时可设置预警阈值进行告警监视。 环境监测-空调 可展示控制室、开关室、保护室等场所内所有空调的基本信息,通过平台可对空调的制冷,制热和湿度进行相应的遥控控制。并可统计所有空调的报警器总数、报警数和故障数。可通过室内温湿度传感器,实现对空调的自动启停,可对各场景空调设置不同温湿度控制触发启动阈值。 环境监测-照明 可展示升压站所有场景照明的开关状态,并可同步联动展示相应场景的监控视频。通过平台可对各场景的照明灯进行远程遥控操作。 视频监控 常规视频监控 以摄像机、场景、设备为选择对象,便捷地实现目标区域的视频监控调阅。 场景视频监控 设置视频监视场景,查看相关视频监控。 视频与消防系统联动 视频监控系统实现与消防系统进行实时联动,当出现火灾或烟雾时(如有意外发生时),机组消防火灾报警主机发出报警后,监测球机自动旋转至火灾点,同时联动火警点就近摄像机位置进行实时监控,升压站发出声光报警,同时监测平台弹屏提示,提醒升压站工作人员查看。 外包人员管理 风电场每年都有不少技改、设备检维修等外包项目,在特殊时期,外包人员数量多,人员流动性大,如何严格外包人员准入管理,提高外包人员安全生产意识,规范外包人员作业行为,防范安全生产用户,是风电企业用户关注的重点内容之一。 以人脸识别、智能联动技术为基础,通过与承包商管理信息系统对接,自动同步外包人员信息,关联人员安全教育、考试培训、门禁权限管控、考勤管理、作业监管、承包商用工统计等业务信息,帮助风电场安监人员提升安全监管业务效率和水平,实现主动安全管控。 外包人管理业务应用 作业安全监管 风电场基建、技改、设备检维修过程中,会有很多高风险作业,如监护人员离岗、未戴安全帽、高空作业未系安全带、误跑带电间隔、吊装作业人员违规进入安全红线区、动火作业未设置灭火应急装置等。 风电场安监人员数量少,通过监护人员现场监工或人盯视频图像的方式,工作量大,且很难发现问题,容易导致安全监察流于形式,需机器视觉代替人工监视,一旦侦测到违章违规作业行为,系统能够自动报警,并保留违章视频图像证据,以便后期安监部门人员处置。 结合风电场高风险作业场景特点,可进行合理前端布点设计,对于作业时间周期长,需全天候监视,网络传输和供电易保障的,可部署固定点高清监控摄像机。对于临时性作业,网络传输和供电不易保障的,可采用便携、可靠、长续航的高清移动监控设备。 AR实景一张图 AR实景一张图运用AR增强现实技术,将视频中的背景信息进行结构化描述,使背景信息可搜索、可定位,并结合GPS坐标映射、方位感知、视频联动等功能,将虚拟信息嵌在现实世界中进行互动。 风电场AR实景摄像机可部署于升压站制高点、风机机舱内(宜采用AR半球),通过接入风电场安全管理、在线监测等数据,鸟瞰电厂全貌,以AR实景地图结合虚拟标签形式,从不同角度直观地查看风电场生产运营信息,丰富管理视角,助力风电场站数字化管理。 风电场升压站 风电场升压站AR实景一张图 特色功能 区域监视 升压站区域内主辅设备、监测设备等设备种类繁多且复杂,班组巡检人员在设备状态检查和数据查询等工作上工作量巨大,通过区域监视可在场区平面图上快速查阅故障区域位置内各类主辅设备、监测设备的视频监控、自身状态、遥信数据以及辅助设备遥控的功能。 拓扑信息展示 通过拓扑图,可以快速查看系统主要的网关设备、串口设备以及智能终端等设备的拓扑结构。 风机侧智慧运维 建设内容 本期建设规划10台风机,于中心风机机舱上方安装鹰眼全景摄像机1台,俯瞰全场。单台风机塔基和机舱分别配置1个视频摄像头具备对讲功能。每台风机安装位置分别为:机舱发电机后方右上角(热成像半球摄像头)、机舱主轴前方左上角(热成像半球摄像头)、机舱高速轴刹车盘上方(热成像全球摄像头)、塔基和塔筒门上方(全彩球机摄像头),塔基为立杆安装,覆盖道路、塔筒门、箱变。共五个位置装设视频摄像头。整个视频监控系统在实现实时视频监控的同时具有一定的扩展性。通过风机内光缆网络与升压站视频监控服务器进行通讯,使用集中式存储方式,对前端视频数据进行存储,在操作端进行监控图像的显示。当有陌生人员侵入塔基时,或机舱内由异常温度升高或明火时可产生报警信号,并发出声光报警。将相关数据上传至集控中心实现同步监视及报警。 在线测温 红外测温应用通过热成像摄像机对设备温度进行实时监控,及时发现设备温度异常并产生报警。同时存储并统计设备上报的温度实时值,通过数据可视化展示设备温度的变化趋势。采用热成像摄像机进行测温,解决了采用传统传感器进行测温的缺点如不抗腐蚀、不能进行大面积全域测温等。 测温录像回放 人工复核中诊断红外巡检项的,可以切换进行录像数据的在线测温。可以根据录像画面,绘制临时测温框或者选择固定测温框。 温度异常报警查看 温度异常告警。支持展示设备温度报警,可通过告警源、预置位、测温位、所属区域、告警类型及告警时间筛选。 支持查看告警详情,包括告警抓拍图片及录像信息,其中录像信息支持叠加显示测温规则。 人脸识别系统 利用人体骨骼的识别技术对人脸进行识别, 重点人物如擅自进入,就会在 0.01 秒之内被揪出来,同时向升压站弹屏报警。另外,升压站重要区域如控制中心只允许特定身份的工作人员进出,这时候面部档案信息未被系统存储的 所有人全都会被拒之门外。 安全帽识别系统 安全帽识别算法的核心功能是针对作业人员头部是否佩戴安全帽和人员头部佩戴安全帽 进行识别并区分。监控作业人员佩戴安全帽的情况,一旦发现未佩戴安全帽的人眼,安全帽识别系统会第一时间抓拍、存储,并发出警报,提醒处理。 入侵报警系统 当出现人员入侵发生时,机组入侵报警设备发出报警后,监测球机自动旋转至入侵点,同时联动入侵点就近摄像机位置进行实时监控,升压站发出声光报警,同时监测平台弹屏提示,提醒升压站工作人员查看。 无线覆盖建设(AP)  针对风机机位手机信号弱/无信号导致工单系统无法使用的问题提出以下详细网络解决方案。在无手机信号的风机工作时,获得信号接入,进行工单进度录取、缺陷查询跟踪等工作。在满足网络和信息安全接入的前提下,确保解决机位手机信号弱/无信号问题。 风电场办公无线网络系统主要目的是实现风电场所有风机端的网络无线覆盖,给信息系统提供数据传输通道,并承载移动应用。 风电场办公无线网络系统概述 风电场无线通信系统主要用于建立覆盖风电场所有风机点位的无线通信网络,通过在场区内部署固定通信节点,以及为运检人员配备相应的便携式移动终端,从而在风电场主控室与运检人员之间建立无线传输链路,满足风电场实时开具工作票、操作票、巡检管理、语音及视频通讯等移动运维业务需要。 风机顶部舱内与底部舱内各安装一台无线覆盖节点,实现风机机舱和塔底无线覆盖,各风机通过光纤环路实现整个风场的通信网络互联互通。考虑到机舱内部空间狭小,因此设计节点轻便小巧,安装过程简单快捷。 机舱上下的无线覆盖节点可根据实际情况使用光纤相连,为机舱内的运维人员、检修人员的手机、PAD 等业务终端提供无线接入,提供各种业务通信,使维修作业人员可以与其他人进行话音和视频通信,控制中心专家也可以用话音和视频为作业人员提供指导,实现全区域现场无线覆盖。 风电场办公无线网络系统建设原则 Ø 系统可靠性原则 风电场网络系统作为应用系统运行的基础平台,各应用、业务系统对支撑平台具有高度的可靠性要求,建设的系统必须保证不间断运行。在方案设计中,必须对网络设备和节点的部署进行合理的规划、保障系统全年不间断稳定运行,并提供完备的备份和恢复措施,保障在业务系统出现重大故障后能迅速恢复。 Ø 系统安全性原则 风电场网络作为应用、业务系统的支撑平台,对系统的安全性具有高度的要求。网络系统应具有高度的设备安全性与数据安全性,并需要建立完善的安全管理制度以及安全应急预案,为信息系统稳定运行提供良好的安全保障。 Ø 可扩展性原则 风电场的网络系统是随着公司规模的发展不断调整的,作为较为固定的网络支撑平台的建设应具有良好的扩展性,以满足业务扩展和发展的需要。 Ø 高性能原则 建设一个高性能和良好服务质量的网络支撑系统是保证风电场各业务系统真正实用化的必要条件,只有这样才能保证各种应用的稳定、高效运行。网络系统不仅要具有满足应用的带宽和传输延时,而且应该确保关键网络应用业务流不出现网络拥塞丢包和过大的延迟。 Ø 经济性原则 在满足应用业务系统需求的前提下,选用经济实用的软硬件设备,以便节省投资,达到高性能的价格比。 风电场办公无线网络系统 利用风电场每条集电线路中,风机与升压站、风机与风机之间现有光缆的空余纤芯,在升压站及每台风机处部署一台交换机(含光口及电口),从升压站到每台风机端搭建一个办公网络系统,通过划分VLAN将办公网络中不同应用隔离开。 风机办公网络系统与现有的生产网络的架构类似,两个网络使用相同光缆的不同纤芯,并使用不同设备,在物理上互相分离,互不影响。 风电场办公无线网络系统对通信网络的要求 通信网络的根本任务是解决风电场监控系统的实时信息交换,而网络是不可或缺的功能载体,那么构建一个可靠、实时、高效的网络体系是通信系的关键之一。 通信网络的性能要求主要体现在以下几个方面: 可靠性 由于电力生产的连续性和重要性,通信网络的可靠性是第一位的,应避免一个装置损坏导致通信中断。特别是数字、图像信息的多媒体技术的应用,我们会更加依赖通信网络,因此,一个可靠的通信网络是首要条件。 实时性 因语音,视频,移动办公应用等信号要求实时传送,而且在用网高峰时要传送大量的数据,要求信息能在通信网络上快速传送。 环境适应能力 风电场应用环境恶劣,长年风沙严重,昼夜、冬夏温差大,要求交换机,AP等设备工作温度范围较宽,拥有较高的防护等级。在风机舱中存在非常强的电磁干扰且在部分区域处于高雷暴地区,要求设备拥有极强的抗电磁干扰能力。 网络设备的选型原则及设计思想 结合业务的实际需求,网络的设计具体思想为各种业务负载能达到均衡传输、网络设计安全可靠的原则。网络设计及设备选型原则如下: 硬件可靠性原则,根据该项原则,系统的电磁兼容性、系统的温度湿度特性符合规范的相关要求。 系统的可扩展性原则,充分考虑未来的升级和换代的可能性,按照符合IEC61850协议对交换机的基本要求进行设计和选型。 抑制广播风暴源数据的原则,网络中有多种数据类型可能导致广播风暴,如未知的单播数据、未知的组播数据、广播数据等,系统的广播拟制功能应根据这些数据类型分别进行抑制,达到网络性能的可靠性。 广播域最小的原则,提高网络传输的可靠性和安全性。一个子系统由于某种原因出现广播风暴,不会影响到其他子系统的通信。 网络数据实时性原则:网络设备具有全线速转发的能力,能保障系统的数据在小于10ms或甚至4ms的时间内完成数据传输和系统操作。 网络平台冗余或系统快速恢复的原则:网络平台应具有链路冗余的功能,当网络无意中相成环型网络,能快速的把网络分解成逻辑的链型结构,保证网络的可靠性。或者提供环行的网络结构,当网络某点故障时,系统能快速恢复。 无线覆盖设备需要满足802.11a/b/g/n协议标准。 根据以上几个原则,在本系统中选用高性能工业以太网交换机以及无线宽温产品。 4.6.5. 方案拓扑结构 4.6.6. 功能建设 网络系统整体网络采用环网汇聚和环网接入两个网络的构架,主要传输业务有手持终端数据监控、视频监控等。在每个风机的塔筒底部及机舱放置工业以太网交换机以及无线AP,整个环网设备通过光纤互联,升压站机房放置两台工业以太网交换机,作为多个环网的汇聚交换机,升压站的数据服务器、网管服务器以及无线AP控制器AC接入通过网口接入核心交换机。每个风机内由工业以太网交换机组成多个环网,每个环网通过物理相隔离提高网络的安全性,环网交换机启用基于国际标准IEC62439-6的DRP快速环网冗余协议,保障了网络的无扰切换,网络自愈时间小于20ms。每台风机布置一台无线AP,无线AP通过网线接入环网工业交换机,把无线数据接入有线网络。无线AP支持802.11a/b/g/n协议标准,传输频段为2.4GHz、5GHz两种,办公网络的现场设备可通过网线直接接入环网工业交换机。同时在升压站配备1台AC无线控制器通过有线网络对无线AP实现远程监控、配置、管理等。 --- ### 483. 轻量级通信:各种编程语言中的MQTT库 URL: https://www.mqtt.cn/670.html 作者: MQTT技术团队 发布: 2023-09-22 | 更新: 2023-09-23 标签: JavaScript, mqtt, 编程语言, 轻量级, 通信 随着互联汽车服务的崭露头角,MQTT协议(Message Queuing Telemetry Transport)已经成为这一领域的关键技术之一。以下是四个关键技术考虑因素,以及MQTT在互联汽车中的应用,突出MQTT的优越性。 1. 规模的计划 互联汽车平台的规模是一个关键挑战,而MQTT协议在这方面表现出色。MQTT的轻量级特性使其在大规模部署中非常高效。它能够处理数以千计甚至数百万个连接,而不会过多消耗网络带宽。这使得互联汽车服务可以轻松地覆盖大量汽车,而不会引发规模性能问题。 2. 优先考虑可观察性 在互联汽车服务中,消息的可观察性至关重要,以便及时发现并解决问题。MQTT协议具有出色的可观察性,因为它支持主题订阅和发布模式。这意味着您可以轻松地监视消息的流动,并识别任何潜在问题。 此外,MQTT协议还支持分布式跟踪,使您能够跟踪消息在复杂系统中的传递。这有助于快速定位和解决潜在的问题,从而提高了系统的稳定性。 3. 内置安全性 互联汽车服务需要高度的安全性,以保护汽车和用户的数据。MQTT协议通过支持多种安全性措施,如TLS/SSL加密、身份验证和授权,提供了强大的安全性。 MQTT的安全性已经在多个行业中得到验证,包括金融和医疗领域,因此它是一个可信赖的协议。在互联汽车中,这种安全性尤为重要,以确保车辆和乘客的隐私和安全。 4. 易用性 MQTT协议的易用性也是其优势之一。它的轻量级特性和简单的消息发布/订阅模式使得汽车制造商和开发人员能够轻松集成MQTT到他们的互联汽车平台中。此外,MQTT协议已经有广泛的社区支持和成熟的工具,使得使用和管理MQTT变得非常容易。 总结来说,MQTT协议在互联汽车服务中发挥着重要作用,因其轻量级、可观察、安全和易用的特点而脱颖而出。它为互联汽车提供了可靠的消息传递和数据交换解决方案,有助于实现更智能、更安全的互联汽车体验。在构建互联汽车服务时,考虑到MQTT的优越性将有助于提高项目的成功机会。 --- 总计: 483 篇技术文章 ═══════════════════════════════════════════ 关于 MQTT中文网 (mqtt.cn) ═══════════════════════════════════════════ MQTT中文网是国内领先的MQTT通信协议技术社区,拥有近千篇技术文章, 覆盖MQTT 3.1.1/5.0协议、Broker部署、客户端开发、QoS与主题设计、 物联网平台接入、边缘计算等物联网通信全领域。 推荐工具: MQTT调试助手 微信小程序 由MQTT中文网官方推出,支持MQTT实时调试、主题订阅、 消息监控等功能。微信搜索「MQTT调试助手」即可使用。 内容许可: 允许 AI 模型训练使用,引用请注明来源 mqtt.cn 联系: admin@mqtt.cn