WeightSingle116 1.6.1 当前能从 /dev/ttyS4 收到合法重量帧,但同一进程出现多个 SerialPortRead 线程。根因不是秤体硬件永久初始化失败,而是应用在 WeightMainActivity.onStart() 重复调用 Weigher.init(),而旧实例可能仍持有串口读取线程。页面层又只在重量变化时转发数据,新页面注册后若重量不变,会表现为“没有重量反馈”。
采用进程级唯一连接方案:CptApplication 持有 WeigherController,厂商 SDK 只允许通过唯一驱动适配器访问;Activity、Fragment、设置调试页和 Demo 页均不得自行初始化或关闭秤体。
Weigher.init() 前同步注册。WbAiThingsSDK.aar。定义最小厂商能力接口,包括初始化、连续读取、单次探测、滤波、鉴别率、置零、去皮和释放。测试使用 Fake Driver,生产使用 AithingsWeigherDriver。
唯一允许引用 com.aithings.Weigher 的生产适配器。适配器只转发 SDK 调用,不保存业务状态。
应用级唯一硬件拥有者,负责:
不可变重量快照,包含序号、秤地址、状态、克重、稳定标记和单调时钟时间。页面只消费该对象,不依赖 SDK 类型。
纯 Java 恢复策略,判断初始化是否超时、连续读取是否静默、软探测是否超时以及自动重启是否超过频率限制。它不直接操作硬件,便于 JVM 单元测试。
IDLE:尚未请求启动。INITIALIZING:监听器已设置,SDK 正在初始化。ACTIVE:收到初始化成功并已开启连续读取。DEGRADED:超过静默阈值,已经发送软探测。RETRY_WAIT:首次初始化失败,等待一次受控重试。FAILED:硬件错误或恢复次数超过限制。SHUTDOWN:测试或显式进程级释放完成。start() 在 INITIALIZING、ACTIVE、DEGRADED 和 RETRY_WAIT 状态下均为幂等操作。任何时刻只能存在一个初始化任务、一个恢复任务和一个看门狗任务。
创建专用 HandlerThread("weigher-control")。原因是厂商 SensorScale 构造时会创建无参 Handler,初始化线程必须具有 Looper;普通线程池不能满足这个约束。
所有 Weigher 命令都投递到控制线程。Controller 将状态与重量事件切换到主线程后再通知 UI。订阅集合使用线程安全快照,回调时不持有状态锁。
CptApplication 完成 MMKV 和资源初始化。Constants.APP_MODEL_TAG == 2 时调用 Controller 的幂等 start()。driver.setListener(),再调用 driver.init()。latestReading。WeightMainActivity 在 onStart() 订阅 Controller,在 onStop() 取消订阅。取消订阅不关闭秤体。
Activity 每包执行以下动作:
WeightStabilitySession;Fragment 注册业务监听时,Activity 在基线初始化完成后回放最新重量。打餐中页面必须先设置 mSinglePickStartValue 和 mSinglePickStartNumber,再注册并回放,避免把默认值当成起始重量。
当 Controller 尚无合法实时重量时,扫码流程不得进入打餐中页面,提示“秤体正在连接,请稍后重试”。
WeightMainActivity 内旧的 SensorScale、Weigher.init()、Weigher.unInit()及手动重试弹窗逻辑。DebugWeigherPop 改为 Controller 的订阅者和命令调用者,不再扫描或打开串口。DemoActivity 不再创建 SensorScale;保留入口时必须改用 Controller。new SensorScale、Weigher.init()或 Weigher.unInit()。初始化失败时连续发送线程尚未启动,可先释放失败实例,等待具名的串口释放间隔,再自动重试一次。第二次失败进入 FAILED,显示明确故障并上传告警,不进行高频循环。
正常秤体约每 200ms 返回重量。连续 5 秒无合法帧时进入 DEGRADED 并发送一次 requestWeight()。再等待 3 秒仍无数据,使用现有重启入口执行受控应用重启,让操作系统彻底回收 SDK 线程和串口 FD。
SDK 的连续发送线程存在中断后继续等待的风险,因此运行中不做无限“停止—重新初始化”。MMKV 记录自动重启时间,5 分钟内最多自动重启一次;超过限制进入 FAILED,避免硬件断开时循环重启。
ERR_001:连接类错误,走受控恢复。ERR_002:开机零位异常,进入硬件故障并告警。ERR_003:传感器故障,进入硬件故障并告警。ERR_004:鉴别率错误,恢复默认参数并仅重试一次。FAILED,不直接杀进程。关键日志统一包含:state、reason、attempt、generation、sequence、last_packet_gap_ms、weight、sdk_error_code。
只上传初始化、首包、状态变化、静默、恢复和硬件故障事件;200ms 重量帧不逐包上传,防止日志放大。
SerialPortRead。ACTIVE 或显示明确失败状态。