返回首页

Raspberry Pi 和 MIR S-05 电表:BLE GATT

开发者获取连接 Raspberry Pi 到 MIR S-05.10 电表通过蓝牙的说明。描述了 GATT 服务,通过 Android HCI 日志进行协议逆向,bleak 脚本用于读取读数。适合集成到智能家居系统。

MIR S-05 电表与 Raspberry Pi Zero 的 BLE 集成
Advertisement 728x90

通过蓝牙将 MIR C-05.10 电表接入树莓派:GATT 协议与逆向工程实战

树莓派 Zero 2W 内置蓝牙模块,无需 USB 红外探头即可直接读取 MIR C-05.10-230-5(80)-G2Z1B-KNQ-S-D 智能电表的数据。该通信基于 BLE 的 GATT 协议。首先安装必要的蓝牙依赖包:

sudo apt update
sudo apt install -y bluez bluez-tools bluetooth python3-pip
python3 -m pip install --break-system-packages bleak
sudo systemctl enable bluetooth
sudo systemctl restart bluetooth

bluetoothctl 工具中执行扫描(scan on),与设备配对(pair MAC),设为信任设备(trust MAC)并建立连接(connect MAC)。电表在列表中通常显示为 C05-序列号 格式。

连接成功后即可访问 GATT 服务。用于 SPP-over-BLE 通信的核心服务 UUID 为 4880c12c-fdcb-4077-8920-a450d7f9b907,其包含特征值 fec26ec4-6d71-4442-9f81-55bc21d658d6(支持通知与无响应写入)。Silicon Labs OTA 服务可安全忽略。

Google AdInline article slot

读取基础 GATT 特征值

使用 bleak 库编写的 Python 脚本可扫描可用特征值并开启通知通道:

import asyncio
from bleak import BleakClient

ADDR = "E4:06:BF:87:CD:69"

CHARS = [
    "00002a29-0000-1000-8000-00805f9b34fb",
    "00002a24-0000-1000-8000-00805f9b34fb",
    "00002a25-0000-1000-8000-00805f9b34fb",
    "00002a27-0000-1000-8000-00805f9b34fb",
    "00002a26-0000-1000-8000-00805f9b34fb",
    "2bb1d64f-451a-4541-ac89-24df683309dc",
    "d24a5138-1448-48ea-a983-f7df274c6d89",
    "4335a5be-fbbd-464e-8659-1a4212239e3e",
    "b3f7e595-2951-42fa-879e-0d9dfa5e846e",
    "fec26ec4-6d71-4442-9f81-55bc21d658d6",
    "f7bf3564-fb6d-4e53-88a4-5e37e0326063",
]

def fmt(data: bytes) -> str:
    try:
        txt = data.decode("utf-8", errors="strict")
        return f'hex={data.hex(" ")} | utf8={txt!r}'
    except Exception:
        return f'hex={data.hex(" ")}' 

async def main():
    def cb(sender, data):
        print(f"NOTIFY {sender}: {fmt(bytes(data))}")

    async with BleakClient(ADDR, timeout=20.0) as client:
        print("connected:", client.is_connected)

        for uuid in CHARS:
            try:
                data = await client.read_gatt_char(uuid)
                print(f"READ {uuid}: {fmt(bytes(data))}")
            except Exception as e:
                print(f"READ {uuid}: ERROR: {e}")

        try:
            await client.start_notify("fec26ec4-6d71-4442-9f81-55bc21d658d6", cb)
            print("notify enabled on fec26...")
        except Exception as e:
            print("notify fec26 error:", e)

        await asyncio.sleep(10)

asyncio.run(main())

运行脚本后,输出信息将显示设备详情:制造商为 NPO "MIR",型号 C05,序列号 50912525161818,固件版本 v2.81.9.0。其余特征值均处于锁定状态,需通过认证才能访问(返回 READ_NOT_PERMITTED)。

借助 Android HCI 日志逆向解析通信协议

若要深度分析通信流量,需准备一台已获取 Root 权限的 Android 设备。开启开发者选项,启用蓝牙 HCI 信息收集日志(HCI Snoop Log)及 USB 调试。与官方“MIR DP”应用配对后,可通过 adb bugreport 或以下命令提取日志:

Google AdInline article slot
adb shell su -c "cp /data/misc/bluetooth/logs/btsnoop_hci.log /sdcard/Download/btsnoop_hci.log && chmod 666 /sdcard/Download/btsnoop_hci.log"
adb pull /sdcard/Download/btsnoop_hci.log

生成的 btsnoop_hci.log 二进制文件可使用 Wireshark 或 AI 辅助工具进行解析。该过程能精准还原设备初始化与数据拉取的完整 BLE 指令序列,涵盖总用电量、T1/T2 分时费率读数、日期时间、实时电流与电压等关键指标。

电表数据顺序轮询脚本

该协议规定必须针对每个数据点单独发送 BLE 请求。以下为脚本基础模板:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Reading MIR C-05 meter data via BLE.
1. Connect and initialize.
2. Enable notifications.
3. Send sequential read commands.
"""

# Insert commands extracted from HCI logs here: write-without-response to fec26ec4...

脚本负责完成服务初始化、开启通知通道,并依次下发读取指令。返回的原始数据将被解析为标准单位:kWh(千瓦时)、A(安培)和 V(伏特)。

Google AdInline article slot

核心要点:

  • BLE 连接稳定,无需重复配对。
  • GATT 特征值受保护,完整访问需厂商专用 PIN 码。
  • HCI 日志是破解 SPP-over-BLE 协议的核心依据。
  • 可通过 MQTT 或直接运行脚本无缝接入 Home Assistant。
  • 必须采用顺序轮询机制;批量发送请求将导致连接中断。

— Editorial Team

Advertisement 728x90

继续阅读