先说结论
Odoo IoT 最难的部分,不是“盒子能不能联网”,而是这四件事如何连续成立:
- 盒子如何先拿到 pairing code 并绑定数据库
- 前端监听 session 如何等到正确设备事件
- 新硬件插上后如何被 interface 发现并匹配 driver
- 某个动作如何执行一次、回一条结果、避免重复触发
从 /home/ubuntu/odoo-temp/addons/iot_drivers/connection_manager.py、event_manager.py、interface.py 和 driver.py 看,官方真正建的是一条 注册 → 发现 → 执行 → 回流 的设备生命周期。
第一层:配对码为什么不是装饰性验证码
ConnectionManager 启动后,会在满足条件时持续轮询:
- 本地还没配置 Odoo server URL
- 设备有 IP
- 不是热点模式阻塞态
- pairing code 还没过期
随后它会向 iot-proxy.odoo.com 请求:
pairing_codepairing_uuid- 再轮询是否拿到
url / token / db_uuid / enterprise_code
这说明 pairing code 不是一次性 UI 展示,而是整条“盒子注册到数据库”链的临时凭证。
也就是说,用户扫到的不是一个可爱数字,而是让云端代理暂时识别这台盒子的引导令牌。
第二层:为什么配对成功后要立刻重启
_connect_to_server() 在拿到数据库信息后会做三件很关键的事:
- 保存 server URL 与 token
- 把已检测到的设备一次性发送给数据库
- 检查 git branch 后重启 Odoo IoT 服务
很多人会觉得“都配对成功了,为什么还要重启”,但从架构上看这是合理的。
因为配对成功不等于系统状态已经完整切换。重启的意义在于:
- 重新带证书启动
- 正式加载对应 handler / 配置
- 让盒子进入绑定后的稳定运行态
所以这一步更像“接管完成后的切换”,而不是简单刷新页面。
第三层:为什么事件管理器要维护 session
EventManager 内部有:
eventssessionsadd_request()_delete_expired_sessions()device_changed()
前端长轮询或监听请求进来时,会创建一个 session,绑定:
session_id- 关注的 devices
- 一个线程事件
Event() - result 容器
- 最近请求时间
这意味着 IoT 事件不是“广播给所有监听者”,而是按 session 与目标设备路由。
这样设计很重要,因为同一台 IoT Box 可能同时服务多个页面或组件:
- POS 在等扫码枪
- 厨显在等打印反馈
- 某个设置页在等设备状态变更
如果没有 session 路由,事件很容易串台。
第四层:设备事件为什么既要回 controller,又要喂 WebRTC
device_changed() 在生成 event 后会:
- 调
send_to_controller() - 如果存在
webrtc_client,继续send(event) - 追加到本地
events - 再逐个 session 看谁应该收到结果
这说明 Odoo 并没有把事件回流只理解成“给当前页面返回 JSON”。
它实际上准备了多条消费路径:
- controller / longpolling
- webrtc 通道
- 本地 session 等待队列
这代表官方面对的是复杂前端设备交互,而不是简单同步 RPC。
第五层:为什么 Interface 是“发现层”,Driver 是“执行层”
Interface 线程会周期执行 get_devices(),然后:
- 算出新接入设备
added - 算出已移除设备
removed - 找到对应 connection type 下、按 priority 排序的 drivers
- 用第一个
supported(device)为真的 driver 来实例化设备线程
这里架构分层非常清楚:
- Interface 负责看“现在插着什么设备”
- Driver 负责看“这类设备能做什么动作”
如果只写 Driver 没有 Interface,你就无法稳定发现插拔变化;如果只有 Interface 没有 Driver,发现了设备也不知道怎么操作。
第六层:动作为什么要做防重复
Driver.action() 里有个很关键的细节:action_unique_id。
如果同一个唯一 ID 的动作重复到来,系统会直接忽略并记 warning。
这类设计看似小,实际非常重要。因为在 IoT 场景里,最怕的不是按钮点了没反应,而是:
- 网络重试导致重复打印
- 重复下发导致同一设备执行两次
- 用户误以为失败又点一次
所以 Odoo 在 driver 层就做幂等防重,是非常正确的架构位置。
第七层:为什么不是所有设备都通过统一事件回调
Driver.action() 里还有一个判断:
- 打印机和 payment 设备不走通用
event_manager.device_changed()回流 - 它们自己处理低纸、刷卡等待等特殊事件
这说明官方并没有为了统一而强行统一,而是承认某些设备类型的交互时序更复杂,需要专门处理。
这反而体现架构成熟:
- 通用链路覆盖大多数设备
- 特殊设备保留专门时序模型
最容易误解的三个点
误区一:IoT 配对成功就代表系统稳定了
不是。配对只是注册入口,后面还有配置落地、设备上报和服务重启。
误区二:发现设备就等于可用了
也不是。还得有匹配成功的 driver,设备线程真正跑起来才算进入可执行状态。
误区三:动作回调就是普通 RPC 返回
不是。它同时涉及 session 路由、controller 通知、可能的 WebRTC 分发,以及动作防重。
实战上怎么理解最稳
如果你在做 Odoo IoT 排障或集成,最稳的排查顺序是:
- 先看盒子是否已完成 pairing 并保存 server URL/token
- 再看 interface 有没有发现设备
- 再看是否成功挑中对应 driver
- 再看 action 是否有唯一 ID、是否被幂等拦截
- 最后再看 session 有没有收到正确事件
最后总结
Odoo IoT 的真正价值,不在“能显示配对码”,而在它把 数据库接管、设备发现、驱动执行和事件回流 串成了完整生命周期。
只有把这条链看完整,你才会明白 Odoo 为什么能把 ERP 前端动作真正落到现场硬件上。
DISCUSSION
评论区