☰
python-miio 版本演进全解析:从 miIO 协议库到全量 MIoT 设备支持的架构升级指南
2026/10/5 1:40:50 网站建设 项目流程
  • 智能家居
  • 物联网
  • IoT协议

【免费下载链接】python-miio

Python library & console tool for controlling Xiaomi smart appliances

项目地址:https://gitcode.com/gh_mirrors/py/python-miio
点击查看免费下载

python-miio 是用于控制小米智能家电的 Python 库与命令行工具,其 CHANGELOG.md 完整记录了从 2017 年 0.0.5 到 2024 年 0.6.0.dev0 的全部版本轨迹。本文以这份 2343 行的变更日志为主线,结合仓库源码,系统梳理该项目的核心架构演进——包括 integrations 目录重组、设备描述符(descriptors)体系、DeviceFactory工厂模式、genericmiot全量 MIoT 设备支持、推送服务器与模拟器等关键里程碑,并附上可直接运行的miiocli实战命令。读完本文,你将掌握 python-miio 的版本脉络、如何从日志信息中理解每次升级的破坏性变更,以及如何利用DeviceFactory与内省接口在自有项目中集成小米设备。

一、版本时间线总览

CHANGELOG 覆盖了项目从无到有的完整过程,可划分为四个明显阶段:

版本段时间范围核心主题
0.0.5 – 0.1.42017 年 4 月 – 8 月初代扫地机控制(python-mirobo 时期)、UDP 协议通信
0.2.0 – 0.3.x2017 年 9 月 – 2018 年更名为 python-miio、mDNS 发现、设备矩阵扩张
0.4.0 – 0.5.122018 年 – 2022 年 7 月统一 CLImiiocli、MIoT 协议初支持、推送服务与云端取 token
0.6.0.dev02024 年 3 月架构大重构:integrations 独立包、描述符体系、genericmiot、模拟器

早期版本的 CHANGELOG 由 github_changelog_generator 自动生成(见 CHANGELOG.md 末尾注释),后期转为基于 Pull Request 标签的半自动维护。理解这一时间线,有助于判断不同版本之间 API 的兼容关系——尤其是 0.5.x 与 0.6.0.dev0 之间存在显著的破坏性变更。

二、0.6.0.dev0:里程碑式预发布与架构重构

0.6.0.dev0(2024-03-13)是 CHANGELOG 中篇幅最大的版本条目。它被明确定位为“为测试与开发通过 PyPI 提供的预发布版本,尚不适合终端用户”,但同时是项目历史上规模最大的一次发布:超过 200 个 PR、364 个文件变更、13748 行新增与 5114 行删除,并首次实现对所有 miot/miotspec 设备的支持。

2.1 核心变更一:integrations 迁入独立包

日志明确指出,对大多数库使用者而言最直观的变化是:所有设备集成实现从主包下迁移到了miio.integrations之下的厂商专属目录。这一变动对应 PR #1697(Reorganize all integrations to vendor-specific dirs)。在仓库中可以看到其落地结果,例如:

  • miio/integrations/roborock/vacuum/vacuum.py
  • miio/integrations/zhimi/airpurifier/airpurifier.py
  • miio/integrations/yeelight/light/yeelight.py
  • miio/integrations/genericmiot/genericmiot.py

在此之前(0.5.9 起的过渡期),真空吸尘器模块曾短暂位于miio.integrations.vacuum.roborock,本次重构将“按设备类型”的组织方式最终统一为“按厂商(vendor)再按类型”的树形结构。这一调整也体现在 miio/integrations/init.py 的包结构上。

2.2 核心变更二:DeviceFactory 取代硬编码实例化

日志给出的迁移建议是:不再直接 import 具体实现类,而是使用DeviceFactory构造实例。仓库中的 miio/devicefactory.py 提供了这一机制的完整实现:

from miio import DeviceFactory dev = DeviceFactory.create("<ip address>", "<token>") dev.status()

其底层逻辑值得展开(对应 miio/devicefactory.py):

  1. 若未指定model,先构造一个基础Device实例并执行info()查询,自动探测设备型号;
  2. 通过class_for_model()在已注册的“型号 → 实现类”映射表中查找对应实现;
  3. 支持通配符型号(如GenericMiot注册的"*"或带前缀的xxx*),并按最长前缀匹配排序返回最具体实现(见 miio/devicefactory.py);
  4. 找不到实现时抛出DeviceException("No implementation found for model ...")。

设备类注册是自动完成的:Device.__init_subclass__会在每个实现类创建时将其注册到DeviceFactory(见 miio/device.py)。此外DeviceFactory还暴露了integrations与models两个 CLI 子命令,可列出当前支持的所有集成与型号。

2.3 核心变更三:可内省接口与描述符体系

0.6.0.dev0 最重要的功能特性是可内省接口(introspectable interfaces):status()、sensors()、settings()、actions()四个方法让下游用户(如 Home Assistant)无需在代码中硬编码设备细节即可动态支持设备。

这套机制建立在“设备描述符(descriptors)”之上,对应 miio/descriptors.py 与 miio/descriptorcollection.py。描述符体系在本次发布中还经历了一系列 API 重命名(详见 2.6 节),并配套了多个装饰器实现:

  • miio/devicestatus.py 中的@sensor、@setting、@action装饰器,用于在状态类上声明可内省的传感器、设置项与动作;
  • SettingDescriptor支持min_value/max_value/step/range_attribute、choices/choices_attribute等约束描述(对应 PR #1587、#1602);
  • 0.6.0 还实现了 DeviceStatus 容器的“嵌入”机制(embedding),即一个状态容器可作为另一个状态容器的子项挂载,通过__作为分隔符访问(PR #1526、#1573)。

2.4 核心变更四:genericmiot 全量 MIoT 设备支持

日志称这是“设备支持量最大的一次发布”:通过 genericmiot 集成,所有 miot/miotspec 设备均可被控制,对应命令为miiocli genericmiot。这是对库原始设计的一次重大改变——这类设备需要下载外部托管的规格文件(miot spec)才能工作,首次使用时自动下载并缓存一段时间(对应 PR #1581 Add generic miot support)。

源码印证了这一点:miio/integrations/genericmiot/genericmiot.py 中GenericMiot._supported_models = ["*"],即默认匹配所有型号。其工作流程为:

  1. initialize_model()通过MiotCloud按型号获取设备模型(见 miio/integrations/genericmiot/genericmiot.py);
  2. 依据模型创建属性(properties)与动作(actions)的描述符;
  3. status()使用get_properties查询所有可读属性,并限制单次最多 10 个属性以规避过大的 UDP 数据报(见 miio/integrations/genericmiot/genericmiot.py)。

规格文件的下拉与缓存逻辑位于 miio/miot_cloud.py:缓存目录使用platformdirs.user_cache_dir("python-miio"),缓存有效期为 6 小时(cache_hours=6,见 miio/miot_cloud.py),型号映射文件名为model-to-urn.json;当同一型号存在多个版本时,info_for_model会自动选择最新版本并记录警告(见 miio/miot_cloud.py)。日志中特别修复了若干相关缺陷,包括“确保缓存目录存在”“缓存文件损坏时的容错处理”等(PR #1798、#1819)。

genericmiot 还支持通过 miio/integrations/genericmiot/metadata/ 下的 YAML 元数据(如base.yaml、common.yaml、miotspec.yaml)对设备自带名称进行润色与修正。

2.5 核心变更五:miIO 与 MIoT 模拟器

日志提到新增了 miio 与 miot 两类模拟器,用于在没有实体设备的情况下进行开发,这也正是 MIoT 支持本身的开发工具。仓库中的实现位于:

  • miio/devtools/simulators/miiosimulator.py
  • miio/devtools/simulators/miotsimulator.py

配套的文档可参考 docs/simulator.rst。0.6.0 同时修复了 miio-simulator 启动失败(PR #1792)、miotsimulator 只读属性检查(PR #1690)等问题,并让模拟器对 info 查询返回 localhost 地址(PR #1657)。

2.6 破坏性变更清单

0.6.0.dev0 列出的破坏性变更如下,升级到 0.6 系列的既有代码需要逐一核对:

  • 引入基于设备描述符的公共接口(PR #1845);
  • 描述符的property重命名为status_attribute(PR #1759);
  • 移除{Light,Vacuum}Interfaces(PR #1743);
  • SettingDescriptor的type重命名为setting_type(PR #1715);
  • 允许为 push server 定义device_id(PR #1710);
  • 所有集成重组到厂商专属目录(PR #1697);
  • 移除长期废弃的miio.vacuum模块(PR #1607);
  • miotdevice.set_property_by允许传入自定义名称(PR #1576);
  • 改进 viomi.vacuum.v8(styj02ym)支持(PR #1559);
  • 清理库抛出的异常体系(PR #1558);
  • test-properties 迁移到 devtools 命令下(PR #1505);
  • 实现可内省的 settings(PR #1500);
  • 放弃 Python 3.7 支持(PR #1469)。

三、0.5.x 系列:事件推送、云端取 token 与设备矩阵扩张

3.1 0.5.12:PushServer 事件推送与云端 Token

0.5.12(2022-07-18)的两个亮点在 CHANGELOG 中占据了主导地位:

其一,事件推送支持。借助miio.PushServer,支持设备的事件回调(PR #1446)。其原理是利用场景(scene)功能订阅事件,当时已知仅网关类设备支持,文档见 docs/push_server.rst。仓库中的实现位于 miio/push_server/server.py,配套的示例位于 docs/examples/push_server/(如gateway_alarm_trigger.py、gateway_button_press.py)。0.6.0 进一步将 push server 泛化(PR #1531),并尽量使用 asyncio 设施(PR #1521)。

其二,云端获取 Token。通过可选的micloud依赖,可一次性从云账户获取所有设备的 token(PR #1460),命令为miiocli cloud,API 层则提供miio.CloudInterface(源码位于 miio/cloud.py):

miiocli cloud Username: example@example.com Password: == name of the device (Device offline ) == Model: example.device.v1 Token: b1946ac92492d2347c6235b4d2611184 IP: 192.168.xx.xx (mac: ab:cd:ef:12:34:56) DID: 123456789 Locale: cn

此外 0.5.12 还要求 click 8+(PR #1378)、新增device_id属性(PR #1384)、引入统一的真空吸尘器接口VacuumInterface与风扇速度预设(PR #1368、#1405)、支持 Roborock 自动集尘(PR #1188)。

3.2 0.5.11:流量解析器与废弃类清理

0.5.11(2022-03-07)引入网络流量解析器devtools/parse_pcap.py(即仓库中的 devtools/pcapparser.py,在 0.6.0 中并入devtools命令体系),给定 token 即可打印解密后的设备流量,是协议逆向与调试的重要工具。

该版本还一次性废弃/移除了大量旧类(PR #1343),迁移对照如下:

已废弃类替代
AirFreshVA4AirFresh
AirHumidifierCA1、AirHumidifierCB1、AirHumidifierCB2AirHumidifier
AirDogX5、AirDogX7SMAirDogX3
AirPurifierMB4AirPurifierMiot
Plug、PlugV1、PlugV3ChuangmiPlug
FanP9、FanP10、FanP11FanMiot
DreameVacuumMiotDreameVacuum
VacuumRoborockVacuum

同时wifi_led被废弃,改用led(PR #1342)。

3.3 0.5.0 起的 MIoT 初代支持

MIoT 协议支持始于 0.5.0(2020-06-04),当时的口号是“为了庆祝新协议集成,从 0.4 跳到 0.5”。首批 MIoT 设备为空气净化器 3/3H(zhimi.airpurifier.mb3、ma4),配套工具是 devtools/miottemplate.py,用于根据 miot spec 生成设备实现模板,并可“按型号下载 miot spec 文件”(PR #904)。0.5.5.2 出于兼容性重新加入了MiotDevice构造函数的mapping参数(PR #985),并允许限制单次查询属性数量max_properties(PR #981)。

MIoT 设备的核心 API 在 miio/miot_device.py 中实现,包括get_property_by(siid, piid)、set_property_by(siid, piid, value)、call_action_by(siid, aiid)等,这一“按 siid/piid 寻址”的模型正是 0.6.0 genericmiot 得以动态支持任意设备的基础。

3.4 0.5.x 新增设备一览

0.5.x 期间设备支持持续扩张,CHANGELOG 中明确列出的代表性新增包括:

  • 0.5.12:dmaker.fan.p33(米家智能落地扇 2 Pro)、zhimi.airpurifier.za1、Roborock G10S(roborock.vacuum.a46)、zhimi.airp.mb5(空气净化器 4)、Dreame 多款(dreame.vacuum.p2150o等);
  • 0.5.10:zhimi.heater.za2、Dreame F9(dreame.vacuum.p2008)、空气净化器 4 Pro(zhimi.airp.va2)、deerma.humidifier.jsq{s,5};
  • 0.5.9:mijia.vacuum.v2(米家 G1 扫地机)、mmgg.pet_waterer.s1(宠物饮水机);
  • 0.5.5:scishare.coffee.s1102(咖啡机)、dmaker.airfresh.a1、zhimi.heater.mc2、yeelink.switch.sw1、leshow.fan.ss4、airdog.airpurifier.{x3,x5,x7sm}、yunmi.waterpuri.lx9/lx11、xiaomi.aircondition.mc1/mc2/mc4/mc5、lumi.curtain.hagl05等。

四、0.4.x 时代:miiocli 统一 CLI 与设备矩阵成型

0.4.0(2018-12)的核心成就是miiocli统一命令行接口(PR #191,@yawor),它取代了此前零散的 mirobo/miplug 等工具,将所有已支持设备接入同一套 CLI 体系。此后每个设备模块均可用统一的参数风格调用:

miiocli roborockvacuum --help Usage: miiocli roborockvacuum [OPTIONS] COMMAND [ARGS]... Options: --ip TEXT [required] --token TEXT [required] --id-file FILE --help Show this message and exit. Commands: add_timer Add a timer. ..

0.4.x 期间每次发布都伴随新设备:0.4.1 加入新风机 VA2 与飞利浦床头灯;0.4.2 移除长期废弃的 mirobo 包、解除 construct 版本锁定;0.4.4 支持净化器 2s 与roborock.vacuum.e2/c1;0.4.5 支持 Chuangmi Plug M3、Air Purifier Pro V7、Aqara 摄像头;0.4.6 支持空气质量监测仪 S1、chuangmi.camera.ipc009、多款风扇、智能马桶盖与 16 路继电器;0.4.7 支持除湿机、小爱闹钟、空气质量监测仪 2 代与欧版智能插座;0.4.8 支持 STYJ02YM 扫地机、deerma.humidifier.mjjsq、新风机 T2017、飞利浦台灯等。

五、0.1–0.3 早期历史:更名、发现机制与 token 提取

CHANGELOG 清晰记录了项目起源:0.3.0(2017-10-21)从python-mirobo 更名为 python-miio(旧包继续兼容一段时间,但鼓励迁移到新的miio包)。同期加入的miio-extract-tokens工具可从米家 App 的 Android 备份或 iOS/Android 数据库(SQLite)中提取并解密 token(源码见 miio/extract_tokens.py),成为当时新用户上手的关键入口。

发现机制同样经历了迭代:0.1.3 起发现改用mDNS(zeroconf),旧握手协议仍可通过--handshake true使用;0.3.6 实现“按需懒发现”(lazy discovery);0.5.x 引入miiocli discover命令。仓库中的 miio/discovery.py 是这些演进的最终形态,且 0.6.0 移除了硬编码的型号信息(PR #1695)。

0.3.x 还沉淀了一批影响至今的工程决策:0.3.2 引入 Sphinx 文档(见 docs/);0.3.5 统一异常体系、所有设备异常派生自DeviceException(对应 miio/exceptions.py);0.3.8 加入固件更新与语音包安装能力(miio/updater.py)并放弃 Python 3.4。

六、贯穿版本史的主题:兼容性、质量与工具链

6.1 废弃与兼容策略

CHANGELOG 中最频繁出现的主题之一是“废弃 → 移除”的渐进式演进。典型链条包括:Strip→PowerStrip(0.3.1);Vacuum→RoborockVacuum(0.5.9 废弃、0.6.0 移除miio.vacuum);wifi_led→led(0.5.11);depth→water_level/water_tank_detached(0.5.7);clean_details的return_list参数移除(0.5.8)。0.6.0 还在主模块入口加入了对直接导入集成类的弃用警告(PR #1813),进一步引导用户转向DeviceFactory。

6.2 Python 版本与依赖管理

  • Python 支持下限逐步提升:3.4(0.3.8 放弃)→ 3.5(0.3.4 起)→ 3.6(0.4.7 起)→ 3.7 不再支持(0.6.0.dev0),CI 同步加入 Python 3.12(PR #1851);
  • 依赖管理在 0.5.1 转向poetry 与 pyproject.toml,0.5.9 改用 poetry-core 构建,仓库当前使用 uv(见 pyproject.toml 与 uv.lock);
  • 0.5.9 加入py.typed标记(miio/py.typed),0.5.7 起代码通过 mypy 检查;
  • 0.6.0 支持 pydantic v2 的 v1 垫片(PR #1816),并通过__cli_output__统一 CLI 输出(PR #1762、#1847)。

6.3 测试与工程质量

日志反复出现测试覆盖率的提升:0.3.3 起为各设备(净化器、加湿器、空气质量监测仪、飞利浦灯具等)补写单元测试;0.4.8 引入 Azure pipeline 与 black/flake8/isort pre-commit 钩子;0.5.x 增加 codeql、pre-commit hooks 更新与代码覆盖度看护;0.6.0 将模拟设备与状态对象移入 conftest(PR #1873)。仓库中每个集成目录下都带有tests/与test_*.py,例如 miio/integrations/zhimi/airpurifier/tests/、miio/integrations/roborock/vacuum/tests/,是学习各设备实现语义(命令名、参数取值、状态枚举)的最佳参考。

七、如何应用这份 CHANGELOG:实用指引

对于 python-miio 的开发者与集成者,这份 CHANGELOG 的实战价值在于:

  1. 判断升级影响:0.6.0.dev0 是唯一包含大规模破坏性变更的版本,升级前务必对照“Breaking changes”清单逐一迁移;0.5.x 内部的小版本升级主要影响类名与属性名,可用上文废弃对照表快速定位。
  2. 掌握统一控制入口:现代设备优先走miiocli genericmiot,其status/set/actions/call四类命令覆盖了传感器的读取、设置的修改与动作的执行:
miiocli genericmiot --ip 127.0.0.1 --token 00000000000000000000000000000000 status miiocli genericmiot --ip 127.0.0.1 --token 00000000000000000000000000000000 set light:brightness 60 miiocli genericmiot --ip 127.0.0.1 --token 00000000000000000000000000000000 call light:toggle
  1. 按图索骥阅读源码:CHANGELOG 中每个条目都对应 PR 与具体的源码模块——描述符体系看 miio/descriptors.py 与 miio/descriptorcollection.py,设备自动发现看 miio/devicefactory.py,MIoT 模型解析看 miio/miot_models.py,规格文件下载缓存看 miio/miot_cloud.py,协议加解密看 miio/protocol.py 与 miio/miioprotocol.py。

  2. 开发调试:无实体设备时使用 docs/simulator.rst 所述的模拟器;需要逆向协议时使用 devtools/pcapparser.py;获取 token 优先miiocli cloud,其他途径见 docs/discovery.rst 与 docs/legacy_token_extraction.rst。

结语

CHANGELOG.md 不仅仅是版本号的流水账,它实质上是 python-miio 技术架构的编年史:从单一扫地机控制工具,到覆盖全品类小米家电的协议库,再到以描述符、工厂与泛化集成(genericmiot)为核心的模块化架构。理解这条演进主线,就等于掌握了该库的设计哲学——渐进式废弃、接口内省化、设备支持泛化,这也为二次开发、集成贡献(如为既有设备补充描述符元数据)提供了清晰的路线图。

  • 智能家居
  • 物联网
  • IoT协议

【免费下载链接】python-miio

Python library & console tool for controlling Xiaomi smart appliances

项目地址:https://gitcode.com/gh_mirrors/py/python-miio
点击查看免费下载

相关推荐

上一篇:cppast诊断日志系统:构建可靠的C++代码分析工具
下一篇:图表绘制工具:Diagram——将ASCII艺术转变为手绘风格图表的神器

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询