Kbsa 通过蓝牙与 Shelly 设备通信

通过RPC使用Bluetooth低功耗(BLE)与Shelly设备通信

Communicating with Shelly Devices via Bluetooth Low Energy (BLE) Using RPC.png

概述

Bluetooth低功耗(BLE)已成为现代智能设备无线通信的核心技术,提供高效且低功耗的连接。Shelly设备作为智能家居生态系统的重要组成部分,利用BLE实现无缝通信与控制。Shelly的BLE通信的一个关键方面是通过BLE实现远程过程调用(RPC)协议,使设备与控制器之间能够进行复杂的交互。本文将深入探讨使用BLE与Shelly设备通信的技术细节,重点介绍通用属性配置文件(GATT)、句柄以及基于RPC的读写操作机制。

先决条件

在深入探讨通过 BLE 和 RPC 与 Shelly 设备通信的技术细节之前,首先需要对以下概念有基本的了解:

  1. Bluetooth低功耗(BLE): 一种为低功耗和低成本设计的无线个人区域网络技术。BLE被广泛应用于物联网设备,实现高效通信。

  2. 通用属性配置文件 (GATT): 一种BLE协议,定义了设备间数据的结构和交换方式。GATT将数据组织为服务和特征。

  3. 远程过程调用 (RPC): 一种协议,允许程序像本地调用一样在远程设备上执行过程(子程序)。

  4. JSON: 一种用于构建RPC请求和响应的轻量级数据交换格式。

Shelly 的 BLE RPC 架构

通过 BLE 和 RPC 与 Shelly 设备通信涉及到建立连接、与特定 GATT 服务和特征交互、构建并发送 RPC 请求、接收和解析响应的无缝集成。这个统一的工作流程确保了与 Shelly 设备的高效可靠通信,使其能够在不同系统和编程语言之间实现多样化集成。

Shelly 设备中的关键 GATT 组件
  1. Shelly GATT 服务 UUID: 标识负责RPC通信的主服务。

BASH
SHELLY_GATT_SERVICE_UUID = "5f6d4f53-5f52-5043-5f53-56435f49445f"
  1. RPC数据特征UUID: 处理RPC请求和响应数据的传输。

BASH
RPC_CHAR_DATA_UUID = "5f6d4f53-5f52-5043-5f64-6174615f5f5f"
  1. RPC发送控制特征UUID: 管理传输控制,特别是用于向 Shelly 设备发送数据长度信息。

BASH
RPC_CHAR_TX_CTL_UUID = "5f6d4f53-5f52-5043-5f74-785f63746c5f"
  1. RPC接收控制特征UUID: 处理接收控制,主要用于从 Shelly 设备接收数据长度信息。

BASH
RPC_CHAR_RX_CTL_UUID = "5f6d4f53-5f52-5043-5f72-785f63746c5f"

注意:这些 UUID 是 Shelly 设备专用的,请参考 Shelly 官方文档或使用 BLE 扫描工具以识别相应的 UUID。

Shelly 的 BLE 上 RPC 关键要素

JSON-RPC 2.0 协议

Shelly 的 Gen2+ 设备使用 JSON-RPC 2.0 用于监控和控制功能的协议。该协议是对称的,允许双方——客户端和设备——互相调用方法并发送通知。JSON-RPC 2.0 确保了结构化和标准化的通信,促进了客户端应用与 Shelly 设备之间的可靠交互。

命名空间约定

Shelly 将其 RPC 方法组织在 命名空间 用于分类功能,提升清晰度和可维护性。以下是一些主要命名空间及示例方法:

  • Shelly 命名空间: 处理系统管理、配置和状态。

    • Shelly.FactoryReset

    • Shelly.ResetWiFiConfig

    • Shelly.ListTimezones

  • 开关命名空间: 管理离散电源输出,通常是继电器。

    • Switch.Set

    • Switch.GetConfig

注意:上述命名空间和方法仅为示例。Shelly 的 RPC 实现还包含许多其他命名空间下的丰富方法,以支持多样化的设备功能。

帧类型

用户与设备之间的通信由三种类型的帧组成:

  1. 请求帧: 用于向设备发送命令。

  2. 响应帧: 用于接收设备的回复。

  3. 通知帧: 用于接收设备的非请求更新。

Shelly RPC 协议中的帧结构
  1. 请求帧

请求帧是一个用于在 Shelly 设备上调用方法的 JSON 对象。它包含以下属性:

  • jsonrpc (字符串):指定使用的JSON-RPC版本,通常为"2.0"。此字段可省略。

  • id (数字或字符串):请求的标识符,用于匹配响应帧。必需。

  • src (字符串):请求来源的名称(例如"user_1")。必需。

  • method(字符串):要调用的过程名称(例如:"Shelly.GetDeviceInfo")。必需。

  • params (对象):方法所需的参数(例如{"id":1})。可选。

  1. 响应帧

响应帧是 Shelly 设备针对请求帧返回的 JSON 对象。它包含以下属性:

  • id (数字或字符串):通信的标识符。必需。

  • src(字符串):响应来源的名称(通常为 Shelly 设备)。必需。

  • dst (字符串):目标名称(通常是请求者)。必需。

  • result (对象):如果请求成功,调用过程的结果。与error字段互斥。

  • error (对象):如果请求失败,包含错误描述。与result字段互斥。

  1. 通知帧

通知帧是 Shelly 设备发送给客户端,用于通知某些事件或状态变化且不期望响应的 JSON 对象。它包含以下属性:

  • src(字符串):通知来源的名称(例如 Shelly 设备)。必需。

  • dst (字符串):目标名称(例如"user_1")。必需。

  • method (字符串):调用的方法(例如"NotifyStatus")。必需。

  • params (对象):包含相关数据的通知参数。必需。

与 Shelly 设备通信的分步指南

1. 建立BLE连接

目标: 使用 Shelly 设备的唯一 BLE 地址进行连接。

流程:

  • 设备发现: 首先扫描附近的 BLE 设备以识别 Shelly 设备。这可以通过你所选编程环境中的 BLE 扫描工具或库实现。Shelly 设备可通过其名称或 BLE 地址识别。

  • 发起连接: 识别后,使用其 BLE 地址发起与 Shelly 设备的连接。该连接为后续所有交互奠定基础。请确保系统的 BLE 硬件正常,且 Shelly 设备处于可接受连接的状态。

注意事项:

  • 连接超时: BLE连接有时不稳定或耗时较长。应实现超时机制,处理连接尝试超过合理时间的情况。

  • 重连逻辑: 在意外断开时,重连策略确保应用能自动恢复,无需手动干预。

2. 交互GATT服务和特征

目标: 访问并使用RPC通信所需的特定GATT服务和特征。

流程:

  • 服务发现: 连接后,执行服务发现以获取 Shelly 设备提供的可用 GATT 服务列表。通过其预定义的 UUID 定位 Shelly GATT 服务。

  • 特征发现: 在 Shelly GATT 服务中,通过各自的 UUID 确认 RPC Data、RPC TX Control 和 RPC RX Control 特征。这些特征对于发送 RPC 请求和接收响应至关重要。请参考 Shelly 设备中的关键 GATT 组件.

注意事项:

  • UUID准确性: 确保使用正确的UUID,避免通信错误。错误的UUID会导致读取或写入失败。

  • 特征可用性: 某些 Shelly 设备可能因型号或固件版本不同而存在 GATT 配置差异。请实现检查以确认所有所需特征均已存在后再继续操作。

3. 构建RPC请求

目标: 按正确格式创建 RPC 请求,以实现与 Shelly 设备的期望操作。

流程:

  • JSON结构: RPC请求结构为包含特定字段的JSON对象:

  • id:请求的唯一标识符,确保响应能够与各自的请求相关联。

  • src: 来源标识,如“user_1”,表示请求的起点。

  • method:要调用的 RPC 方法,例如 “Shelly.GetDeviceInfo”。

  • params: RPC方法所需的可选参数。

JSON
{ "id": 123456789, "src": "user_1", "method": "Shelly.GetDeviceInfo", "params": {} }
  • 编码:JSON对象转换为UTF-8编码的字节数组。该字节数组将通过 BLE 发送到 Shelly 设备。

  • 计算长度: 确定编码RPC请求的字节长度。该长度信息对于告知 Shelly 设备即将接收数据的大小至关重要。

  • 打包长度: 将计算的长度转换为4字节大端整数。此打包长度写入RPC发送控制特征以指示即将传输的数据大小。

注意事项:

  • 唯一请求ID: 每个RPC请求应有唯一id,以准确匹配响应。

  • 参数验证: 请确保传递给 RPC 方法的参数有效且符合预期格式。无效参数可能导致请求格式错误并引发 Shelly 设备的错误。

4. 发送RPC请求

目标: 通过 BLE 将构建好的 RPC 请求发送给 Shelly 设备。

流程:

  • 写入长度到发送控制特征: 首先将RPC请求的打包长度写入RPC发送控制特征。这会告知 Shelly 设备即将接收数据的大小,使其准备好接收实际的 RPC 请求。

  • 引入短暂延迟: 写入长度后,等待短暂延迟(例如1秒) 以便 Shelly 设备处理长度信息。这样可确保在发送实际数据前,客户端与设备之间的同步。

  • 写入RPC请求到数据特征: 接着将编码的RPC请求字节写入RPC数据特征。此操作将实际命令或查询发送至 Shelly 设备,促使其执行指定的 RPC 方法。

注意事项:

  • 带响应的写操作: 使用期望 Shelly 设备响应(确认)的写操作。这可确保设备已成功接收并处理写入请求。

  • 错误处理: 实现确认写操作成功的机制。处理写入失败的情况,如连接问题或设备无响应,通过重试或提示用户。

5. 接收和解析RPC响应

目标: 接收来自 Shelly 设备的响应,确保数据完整性和正确性。

流程:

  • 从接收控制特征读取响应长度: 首先从RPC接收控制特征读取响应长度。该长度指示即将接收的响应数据大小,帮助客户端确定预期字节数。

  • 解包长度: 将接收到的4字节大端整数转换为实际字节长度。此解包长度决定需读取的响应数据总大小。

  • 分块读取响应数据: 由于BLE的MTU(最大传输单元)限制,RPC数据特征分块读取响应数据(通常为20字节)。持续读取直到接收完整响应(由响应长度指示)。

  • 累积响应数据: 每读取一块,将其追加到缓冲区或字节数组中,重建完整响应。

  • 解码并解析响应: 全部块接收完毕后,将累积字节解码为UTF-8字符串并解析JSON对象。解析后的响应包含RPC调用结果或错误字段。

  • 验证响应: 确认响应中的id与原请求id匹配,确保响应对应正确请求。同时检查result字段确认成功执行,或处理错误信息。

注意事项:

  • 分块读取: BLE有限的MTU大小要求分块读取数据,避免截断或丢失。实现逻辑处理部分读取并累积数据,直到完整响应接收完毕。

  • 超时: 实现读取超时机制,以防 Shelly 设备未响应或连接中断时出现无限等待。

  • 数据完整性: 验证完整响应已接收并正确解析,确保通信准确可靠。

常见挑战处理

通过 BLE 和 RPC 与 Shelly 设备通信是一种强大的方式,但也存在一些挑战。有效应对这些挑战可确保集成的健壮性和可靠性。

  1. MTU大小管理

问题: BLE的最大传输单元(MTU)定义单次传输的数据包最大尺寸。超出MTU会导致数据截断或传输失败。

解决方案:

  • 分块读写: 实现逻辑将大数据负载拆分为符合MTU大小(通常20字节)的小块,确保数据可靠传输且不超出BLE限制。

示例方法:

  • 确定待发送数据总长度。

  • 将数据分割为不超过20字节的块。

  • 依次写入每个块到相应特征。

  • 动态MTU调整: 部分BLE库和设备支持协商更大MTU。若支持,可调整MTU以优化传输效率。

示例考虑:

  • 在开始传输前,如库和设备支持,申请更大MTU。

  • 协商失败时回退至标准块大小。

最佳实践:

  • 确定MTU能力: 验证 Shelly 设备和 BLE 客户端是否都支持更大的 MTU,以最大化数据吞吐量。

  • 实现回退机制: 动态MTU协商失败时,默认使用标准块大小以保持兼容性。

  1. 超时与重试

问题: BLE连接可能不稳定,导致超时或通信中断,尤其在干扰多或多设备连接环境中。

解决方案:

  • 实现超时机制: 为连接尝试、读写操作和数据处理设置合理超时,防止应用无限等待响应。

示例方法:

  • 定义各操作最大等待时间。

  • 操作超时后,优雅处理,重试或通知用户。

  • 重试逻辑: 针对临时失败(如连接断开或写入失败)实现重试机制。限制重试次数,避免无限循环和资源浪费。

示例方法:

  • 失败后等待短暂时间再重试。

  • 采用指数退避策略,逐渐延长重试间隔。

最佳实践:

  • 指数退避: 逐步增加重试间隔,减少重复失败概率,尤其在高干扰环境。

  • 用户通知: 在重试耗尽后通知用户,便于手动干预。

  1. 错误处理

问题: BLE通信中可能出现特征不可用、响应格式错误或RPC特定错误等多种问题。

解决方案:

  • 全面异常处理: 在通信各阶段实现健壮的错误捕获机制,包括处理BLE异常、JSON解析错误和RPC相关问题。

示例方法:

  • 关键操作使用try-catch块包裹。

  • 记录详细错误信息,便于调试和问题解决。

  • 验证检查: 彻底验证响应数据完整性,包括匹配响应ID与请求ID,确认存在预期字段如result或error。

示例方法:

  • 接收响应后,检查id是否匹配原请求。

  • 确保响应包含result字段或error字段以判断结果。

最佳实践:

  • 日志记录: 维护详细通信日志,记录尝试、成功和失败,有助于排查和理解系统行为。

  • 优雅降级: 对非关键错误,允许系统继续运行,优雅处理失败,避免崩溃或影响其他操作。

结论

通过 BLE 和 RPC 与 Shelly 设备通信,为打造先进的智能家居集成和自动化解决方案提供了强大途径。通过理解 BLE 架构、GATT 服务和 RPC 机制,开发者可以根据自身需求构建健壮高效的通信框架。本指南为建立无缝通信提供了详细路线图,助你充分发挥 Shelly 智能功能在各类编程语言和平台上的潜力。

我们重视您的反馈!

感谢您花时间阅读我们的文章!内容是否对您有帮助或有趣?

您的见解能帮助我们改进。若方便,

请通过以下邮箱与我们分享您的反馈:

Integration@shelly.com