feat: State→Props 命名统一 + 新增 Plug/Gateway 设备 + 分类系统重构
**命名统一(State → Props)** - 所有设备类型:XxxState → XxxProps,GetState() → GetProps(),FetchState() → FetchProps() - 回调接口:OnStateChanged → OnPropsChanged - Bridge 层类型别名、示例代码、文档同步更名 **新增设备类型** - KindPlug + Plug 驱动:智能插座/插头(TurnOn/TurnOff/IsOn/OnPropsChanged) - KindGateway + Gateway 驱动:网关设备类型识别 - KindOccupancySensor 从 KindSensor 独立,添加 OccupancyProps **设备分类系统改进** - classifyByModel 改为按 key 长度降序匹配(防止 sensor 先于 sensor-occupy) - 新增下划线变体识别(sensor_occupy、sensor_temp 等) - outlet 重新归类为 Plug(非 Switch) - 新增 Or() 组合过滤器 **连接桥增强** - 设备创建成功后自动订阅属性变更 - 新增 nil 防护检查 - 支持 Plug/Speaker/Gateway/Occupancy 类型的 FetchProps 刷新 - 日志级别 Info → Debug **AC 驱动增强** - 新增 HasPower()、GetElectricPower()、GetPowerConsumption() 功率接口 - ACProps 新增 ElectricPower、PowerConsumption 字段 - valMapper:Desc 为空时 fallback 用 Name,key 统一小写 **MIoT 核心** - 设备列表刷新改用 reflect.DeepEqual 全字段变更检测 - 移除 BLE/代理设备默认在线 hack - RefreshDeviceAllProps 增加离线检查 - 新增 miot_errors.go:MIoT 错误码定义 - 全局日志级别 Info→Debug/Warn(降低噪音) **示例与文档** - 所有示例代码同步 API 变更 - 传感器示例改用 Or 组合过滤器 - ARCH_PLAN 等迁移文档同步更新
This commit is contained in:
+45
-33
@@ -4,6 +4,7 @@ package miot
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -103,12 +104,6 @@ func (c *MIoTClient) RefreshDevices(homeIDs []string) error {
|
||||
info[k] = v
|
||||
}
|
||||
|
||||
// BLE/proxy devices default online
|
||||
connectType := getConnectType(info)
|
||||
if connectType == 23 || connectType == 8 || connectType == 12 || connectType == 0 {
|
||||
info["online"] = true
|
||||
}
|
||||
|
||||
// Handle sub-devices: .s\d+ suffix
|
||||
match := subDevPattern.FindString(did)
|
||||
if match != "" {
|
||||
@@ -165,20 +160,21 @@ func (c *MIoTClient) RefreshDevices(homeIDs []string) error {
|
||||
} else {
|
||||
c.deviceListCache[did] = cloneMap(info)
|
||||
}
|
||||
c.lgr.Infof("[MIoTClient] Device added: %s (%v)\n", did, info["name"])
|
||||
c.lgr.Debugf("[MIoTClient] Device added: %s (%v)\n", did, info["name"])
|
||||
changed = true
|
||||
} else {
|
||||
// Check if online status changed
|
||||
newOnline := getOnline(info)
|
||||
oldOnline := getOnline(oldInfo)
|
||||
if newOnline != oldOnline {
|
||||
oldInfo["online"] = newOnline
|
||||
c.deviceListCloud[did] = oldInfo
|
||||
if cacheInfo, ok := c.deviceListCache[did]; ok {
|
||||
cacheInfo["online"] = newOnline
|
||||
// 检测并同步所有变更字段(name/model/nickname 等)
|
||||
for k, v := range info {
|
||||
if oldV, ok := oldInfo[k]; !ok || !reflect.DeepEqual(oldV, v) {
|
||||
oldInfo[k] = v
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
c.deviceListCloud[did] = oldInfo
|
||||
if cacheInfo, ok := c.deviceListCache[did]; ok {
|
||||
for k, v := range info {
|
||||
cacheInfo[k] = v
|
||||
}
|
||||
c.lgr.Infof("[MIoTClient] Device online changed: %s online=%v\n", did, newOnline)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,27 +273,43 @@ func (c *MIoTClient) aggregateDeviceState(did string) {
|
||||
return
|
||||
}
|
||||
|
||||
// Aggregate from three sources
|
||||
// OR 聚合:任一来源显式 online=true → 在线;
|
||||
// 否则任一来源显式 online=false → 离线;
|
||||
// 否则(无来源提供 online 字段)→ 保留缓存旧值,缓存也没有则默认在线。
|
||||
online := false
|
||||
explicitTrue := false
|
||||
explicitFalse := false
|
||||
|
||||
if cloudInfo, exists := c.deviceListCloud[did]; exists {
|
||||
if o, ok := cloudInfo["online"].(bool); ok && o {
|
||||
online = true
|
||||
sources := []map[string]interface{}{
|
||||
c.deviceListCloud[did],
|
||||
c.deviceListGateway[did],
|
||||
c.deviceListLan[did],
|
||||
}
|
||||
for _, info := range sources {
|
||||
if o, ok := info["online"].(bool); ok {
|
||||
if o {
|
||||
explicitTrue = true
|
||||
} else {
|
||||
explicitFalse = true
|
||||
}
|
||||
} else if _, exists := info["online"]; exists {
|
||||
c.lgr.Debugf("[MIoTClient] %s online type mismatch: %v (%T)\n", did, info["online"], info["online"])
|
||||
}
|
||||
}
|
||||
if !online {
|
||||
if gwInfo, exists := c.deviceListGateway[did]; exists {
|
||||
if o, ok := gwInfo["online"].(bool); ok && o {
|
||||
online = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !online {
|
||||
if lanInfo, exists := c.deviceListLan[did]; exists {
|
||||
if o, ok := lanInfo["online"].(bool); ok && o {
|
||||
online = true
|
||||
}
|
||||
|
||||
switch {
|
||||
case explicitTrue:
|
||||
online = true
|
||||
case explicitFalse:
|
||||
online = false
|
||||
default:
|
||||
if oldOnline, ok := cacheInfo["online"].(bool); ok {
|
||||
online = oldOnline
|
||||
} else {
|
||||
online = true // 云列表里有但没 online 字段,假设在线
|
||||
}
|
||||
c.lgr.Debugf("[MIoTClient] %s no online field from cloud/gw/lan, fallback online=%v (cache=%v)\n",
|
||||
did, online, cacheInfo["online"])
|
||||
}
|
||||
|
||||
cacheInfo["online"] = online
|
||||
|
||||
Reference in New Issue
Block a user