feat: AC 三合一设备支持 + 新增 Plug/Gateway 驱动 + Cover 结构化重构
**AC 驱动增强** - 支持 thermostat + air-conditioner + air-fresh 多服务三合一设备,属性跨服务合并解析 - 新增 specResolver.findValListInService/findInService/hasService/serviceShortName 方法 - 移除 KindThermostat,heater/electric-blanket/thermostat 重新归类为 KindAirConditioner **Cover 窗帘重构** - CoverProps 结构化:Position/Status/Fault 分离 - SetPosition 优先写 target-position,回退 current-position - OnPropsChanged/FetchProps 支持多属性同步刷新 **新增设备类型** - Plug 驱动:插座/插头,支持开合、在线状态、属性变更订阅 - Gateway 驱动:网关设备类型识别 - miot/miot_errors.go:新增 MIoT 云端错误码定义 **MIoT 客户端健壮性** - SetProp 空结果视为失败;设备被移除或离线时自动刷新设备列表 - GetDevices 的 has_more 改用 parseBool 严格解析 - MIPS SubscribeMany 批量订阅减少往返 - matchURN 改为按段精确匹配,避免 tofan 误匹配 fan **Bridge** - 移除 Thermostat case,Cover 改用结构化 CoverProps - 新增设备创建后自动订阅属性变更 **其他** - 日志整体 Info → Debug 降噪 - .gitignore 忽略 /.codebuddy/memory - 更新 devices_test 与 08_adv_filter_classify 示例
This commit is contained in:
+30
-30
@@ -156,7 +156,7 @@ func (c *MIoTClient) Init() error {
|
||||
if et, ok := authInfo["expires_ts"].(float64); ok {
|
||||
c.entryData["expires_ts"] = et
|
||||
}
|
||||
c.lgr.Infof("[MIoTClient] Loaded token from storage\n")
|
||||
c.lgr.Debugf("[MIoTClient] Loaded token from storage\n")
|
||||
} else if accessToken != "" {
|
||||
// First run: write entryData token to storage
|
||||
expiresTS := float64(time.Now().Unix()) + 3600*24*30 // default 30 days
|
||||
@@ -168,7 +168,7 @@ func (c *MIoTClient) Init() error {
|
||||
"refresh_token": refreshToken,
|
||||
"expires_ts": expiresTS,
|
||||
}, true)
|
||||
c.lgr.Infof("[MIoTClient] Saved initial token to storage\n")
|
||||
c.lgr.Debugf("[MIoTClient] Saved initial token to storage\n")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ func (c *MIoTClient) Init() error {
|
||||
oauthRedirectURL, _ := c.entryData["oauth_redirect_url"].(string)
|
||||
uuid, _ := c.entryData["uuid"].(string)
|
||||
c.oauth = NewMIoTOauthClient(OAUTH2_CLIENT_ID, oauthRedirectURL, c.cloudServer, uuid)
|
||||
c.lgr.Infof("[MIoTClient] OAuth client initialized\n")
|
||||
c.lgr.Debugf("[MIoTClient] OAuth client initialized\n")
|
||||
}
|
||||
|
||||
// 3.2 Initialize Cert client
|
||||
@@ -197,7 +197,7 @@ func (c *MIoTClient) Init() error {
|
||||
} else {
|
||||
c.cert = cert
|
||||
c.cert.VerifyCACert()
|
||||
c.lgr.Infof("[MIoTClient] Cert client initialized\n")
|
||||
c.lgr.Debugf("[MIoTClient] Cert client initialized\n")
|
||||
}
|
||||
|
||||
// 4. Initialize HTTP client (use token from storage if available)
|
||||
@@ -207,7 +207,7 @@ func (c *MIoTClient) Init() error {
|
||||
c.lgr.Warnf("[MIoTClient] Warning: failed to create HTTP client: %v\n", err)
|
||||
} else {
|
||||
c.http = httpClient
|
||||
c.lgr.Infof("[MIoTClient] HTTP client created\n")
|
||||
c.lgr.Debugf("[MIoTClient] HTTP client created\n")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ func (c *MIoTClient) Init() error {
|
||||
if err := mips.Connect(); err != nil {
|
||||
c.lgr.Warnf("[MIoTClient] Warning: MIPS cloud connect failed: %v\n", err)
|
||||
} else {
|
||||
c.lgr.Infof("[MIoTClient] MIPS cloud connected\n")
|
||||
c.lgr.Debugf("[MIoTClient] MIPS cloud connected\n")
|
||||
}
|
||||
c.mu.Lock()
|
||||
}
|
||||
@@ -239,7 +239,7 @@ func (c *MIoTClient) Init() error {
|
||||
nw.SubNetworkStatus(key, c.onNetworkStatusChanged)
|
||||
status := nw.GetNetworkStatus()
|
||||
c.onNetworkStatusChanged(status)
|
||||
c.lgr.Infof("[MIoTClient] Network status subscribed (online=%v)\n", status)
|
||||
c.lgr.Debugf("[MIoTClient] Network status subscribed (online=%v)\n", status)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,12 +258,12 @@ func (c *MIoTClient) Init() error {
|
||||
groupID, _ := info["group_id"].(string)
|
||||
if groupID != "" {
|
||||
svc.SubServiceChange(key, groupID, c.onMipsServiceStateChange)
|
||||
c.lgr.Infof("[MIoTClient] mDNS service subscribed: home=%s, group=%s\n", homeID, groupID)
|
||||
c.lgr.Debugf("[MIoTClient] mDNS service subscribed: home=%s, group=%s\n", homeID, groupID)
|
||||
|
||||
// Check if service already discovered
|
||||
serviceData := svc.GetServices(groupID)
|
||||
if sd, exists := serviceData[groupID]; exists && sd.validService() {
|
||||
c.lgr.Infof("[MIoTClient] Central mips service scanned: %s, %v\n", homeID, sd)
|
||||
c.lgr.Debugf("[MIoTClient] Central mips service scanned: %s, %v\n", homeID, sd)
|
||||
mips := NewMipsLocalClient(
|
||||
getVirtualDID(c.entryData),
|
||||
sd.Addresses[0],
|
||||
@@ -294,7 +294,7 @@ func (c *MIoTClient) Init() error {
|
||||
if lan.InitDone() {
|
||||
c.onMiotLanStateChange(true)
|
||||
}
|
||||
c.lgr.Infof("[MIoTClient] LAN control initialized\n")
|
||||
c.lgr.Debugf("[MIoTClient] LAN control initialized\n")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -324,7 +324,7 @@ func (c *MIoTClient) Init() error {
|
||||
}
|
||||
c.i18n = NewMIoTI18n(lang)
|
||||
c.i18n.Init()
|
||||
c.lgr.Infof("[MIoTClient] i18n initialized (lang=%s)\n", lang)
|
||||
c.lgr.Debugf("[MIoTClient] i18n initialized (lang=%s)\n", lang)
|
||||
|
||||
c.lgr.Infof("[MIoTClient] Initialized\n")
|
||||
return nil
|
||||
@@ -358,7 +358,7 @@ func (c *MIoTClient) Deinit() error {
|
||||
if c.mipsCloud != nil {
|
||||
c.mipsCloud.UnsubState(key)
|
||||
c.mipsCloud.Disconnect()
|
||||
c.lgr.Infof("[MIoTClient] MIPS cloud disconnected\n")
|
||||
c.lgr.Debugf("[MIoTClient] MIPS cloud disconnected\n")
|
||||
}
|
||||
|
||||
// 4. Cancel refresh cloud devices timer
|
||||
@@ -493,7 +493,7 @@ func (c *MIoTClient) loadCacheDevice() error {
|
||||
c.deviceListCache[did] = infoMap
|
||||
}
|
||||
}
|
||||
c.lgr.Infof("[MIoTClient] Loaded %d devices from cache\n", len(deviceList))
|
||||
c.lgr.Debugf("[MIoTClient] Loaded %d devices from cache\n", len(deviceList))
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -647,7 +647,7 @@ func (c *MIoTClient) RefreshAuthInfo() (map[string]interface{}, error) {
|
||||
c.mipsCloud.UpdateAccessToken(ac)
|
||||
}
|
||||
|
||||
c.lgr.Infof("[MIoTClient] RefreshAuthInfo: token refreshed\n")
|
||||
c.lgr.Debugf("[MIoTClient] RefreshAuthInfo: token refreshed\n")
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -690,7 +690,7 @@ func (c *MIoTClient) refreshUserCert() {
|
||||
nextDelay = 60
|
||||
}
|
||||
c.RequestRefreshUserCert(nextDelay)
|
||||
c.lgr.Infof("[MIoTClient] Cert still valid for %ds, recheck in %ds\n", remainSec, nextDelay)
|
||||
c.lgr.Debugf("[MIoTClient] Cert still valid for %ds, recheck in %ds\n", remainSec, nextDelay)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -720,7 +720,7 @@ func (c *MIoTClient) refreshUserCert() {
|
||||
}
|
||||
|
||||
// Save cert
|
||||
if err := c.cert.SaveUserCert(certPEM); err != nil {
|
||||
if err = c.cert.SaveUserCert(certPEM); err != nil {
|
||||
c.lgr.Errorf("[MIoTClient] Cert refresh: save cert FAILED: %v\n", err)
|
||||
return
|
||||
}
|
||||
@@ -783,13 +783,13 @@ func (c *MIoTClient) ShowCentralStateChangedNotify(connected bool) {
|
||||
// Aligns with Python: __on_mips_cloud_state_changed.
|
||||
func (c *MIoTClient) onMipsCloudStateChanged(key string, connected bool) {
|
||||
if connected {
|
||||
c.lgr.Infof("[MIoTClient] MIPS cloud connected\n")
|
||||
c.lgr.Debugf("[MIoTClient] MIPS cloud connected\n")
|
||||
// Refresh devices on reconnect
|
||||
c.ScheduleRefreshDevices(RefreshCloudDevicesDelay * time.Millisecond)
|
||||
return
|
||||
}
|
||||
|
||||
c.lgr.Infof("[MIoTClient] MIPS cloud disconnected\n")
|
||||
c.lgr.Debugf("[MIoTClient] MIPS cloud disconnected\n")
|
||||
|
||||
// Disconnect: mark all cloud devices offline
|
||||
c.deviceListMu.Lock()
|
||||
@@ -821,7 +821,7 @@ func (c *MIoTClient) onMipsCloudStateChanged(key string, connected bool) {
|
||||
// onNetworkStatusChanged handles network connectivity changes.
|
||||
// Aligns with Python: __on_network_status_changed.
|
||||
func (c *MIoTClient) onNetworkStatusChanged(status bool) {
|
||||
c.lgr.Infof("[MIoTClient] Network status changed: online=%v\n", status)
|
||||
c.lgr.Debugf("[MIoTClient] Network status changed: online=%v\n", status)
|
||||
if status {
|
||||
// Network is back; trigger device refresh and reconnect MIPS
|
||||
if c.mipsCloud != nil && !c.mipsCloud.IsConnected() {
|
||||
@@ -834,15 +834,15 @@ func (c *MIoTClient) onNetworkStatusChanged(status bool) {
|
||||
// onMipsServiceStateChange handles mDNS service discoveries for central gateways.
|
||||
// Aligns with Python: __on_mips_service_state_change.
|
||||
func (c *MIoTClient) onMipsServiceStateChange(groupID string, state MipsServiceState, data map[string]interface{}) {
|
||||
c.lgr.Infof("[MIoTClient] MIPS service change: group=%s, state=%s\n", groupID, state)
|
||||
c.lgr.Debugf("[MIoTClient] MIPS service change: group=%s, state=%s\n", groupID, state)
|
||||
|
||||
virtualDID := getVirtualDID(c.entryData)
|
||||
if virtualDID == "" {
|
||||
c.lgr.Infof("[MIoTClient] MIPS service: missing virtual_did, skip\n")
|
||||
c.lgr.Debugf("[MIoTClient] MIPS service: missing virtual_did, skip\n")
|
||||
return
|
||||
}
|
||||
if c.cert == nil {
|
||||
c.lgr.Infof("[MIoTClient] MIPS service: cert not initialized, skip\n")
|
||||
c.lgr.Debugf("[MIoTClient] MIPS service: cert not initialized, skip\n")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -851,7 +851,7 @@ func (c *MIoTClient) onMipsServiceStateChange(groupID string, state MipsServiceS
|
||||
// Create new MipsLocalClient
|
||||
host, _ := data["addresses"].([]interface{})
|
||||
if len(host) == 0 {
|
||||
c.lgr.Infof("[MIoTClient] MIPS service: no addresses for %s\n", groupID)
|
||||
c.lgr.Debugf("[MIoTClient] MIPS service: no addresses for %s\n", groupID)
|
||||
return
|
||||
}
|
||||
hostStr, _ := host[0].(string)
|
||||
@@ -872,7 +872,7 @@ func (c *MIoTClient) onMipsServiceStateChange(groupID string, state MipsServiceS
|
||||
mips.SubState(groupID, c.onMipsLocalStateChanged)
|
||||
mips.Connect()
|
||||
c.mipsLocal[groupID] = mips
|
||||
c.lgr.Infof("[MIoTClient] MIPS local client created: %s @ %s:%d\n", groupID, hostStr, int(port))
|
||||
c.lgr.Debugf("[MIoTClient] MIPS local client created: %s @ %s:%d\n", groupID, hostStr, int(port))
|
||||
|
||||
case MipsServiceUpdated:
|
||||
// Disconnect old, connect new
|
||||
@@ -902,7 +902,7 @@ func (c *MIoTClient) onMipsServiceStateChange(groupID string, state MipsServiceS
|
||||
mips.SubState(groupID, c.onMipsLocalStateChanged)
|
||||
mips.Connect()
|
||||
c.mipsLocal[groupID] = mips
|
||||
c.lgr.Infof("[MIoTClient] MIPS local client updated: %s @ %s:%d\n", groupID, hostStr, int(port))
|
||||
c.lgr.Debugf("[MIoTClient] MIPS local client updated: %s @ %s:%d\n", groupID, hostStr, int(port))
|
||||
|
||||
case MipsServiceRemoved:
|
||||
if mips, exists := c.mipsLocal[groupID]; exists {
|
||||
@@ -910,7 +910,7 @@ func (c *MIoTClient) onMipsServiceStateChange(groupID string, state MipsServiceS
|
||||
mips.UnsubState(groupID)
|
||||
mips.Disconnect()
|
||||
delete(c.mipsLocal, groupID)
|
||||
c.lgr.Infof("[MIoTClient] MIPS local client removed: %s\n", groupID)
|
||||
c.lgr.Debugf("[MIoTClient] MIPS local client removed: %s\n", groupID)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -919,7 +919,7 @@ func (c *MIoTClient) onMipsServiceStateChange(groupID string, state MipsServiceS
|
||||
// Aligns with Python: __on_mips_local_state_changed.
|
||||
// key is the groupID of the gateway.
|
||||
func (c *MIoTClient) onMipsLocalStateChanged(key string, connected bool) {
|
||||
c.lgr.Infof("[MIoTClient] MIPS local state changed: group=%s, connected=%v\n", key, connected)
|
||||
c.lgr.Debugf("[MIoTClient] MIPS local state changed: group=%s, connected=%v\n", key, connected)
|
||||
|
||||
if connected {
|
||||
// Reconnect: pull gateway device list
|
||||
@@ -966,7 +966,7 @@ func (c *MIoTClient) onMipsLocalStateChanged(key string, connected bool) {
|
||||
// onMiotLanStateChange handles LAN controller state transitions.
|
||||
// Aligns with Python: __on_miot_lan_state_change.
|
||||
func (c *MIoTClient) onMiotLanStateChange(initialized bool) {
|
||||
c.lgr.Infof("[MIoTClient] LAN state changed: initialized=%v\n", initialized)
|
||||
c.lgr.Debugf("[MIoTClient] LAN state changed: initialized=%v\n", initialized)
|
||||
if initialized {
|
||||
c.deviceListMu.Lock()
|
||||
lan, ok := c.miotLan.(*MIoTLan)
|
||||
@@ -1026,7 +1026,7 @@ func (c *MIoTClient) onLanDeviceStateChanged(did string, state map[string]interf
|
||||
// Aligns with Python: __on_gw_device_list_changed.
|
||||
// Called when a MipsLocalClient reports that its device list has changed.
|
||||
func (c *MIoTClient) onGWDeviceListChanged() {
|
||||
c.lgr.Infof("[MIoTClient] GW device list changed\n")
|
||||
c.lgr.Debugf("[MIoTClient] GW device list changed\n")
|
||||
|
||||
for groupID, mips := range c.mipsLocal {
|
||||
if mips == nil || !mips.IsConnected() {
|
||||
@@ -1090,7 +1090,7 @@ func (c *MIoTClient) updateDevicesFromGW(groupID string, devices map[string]inte
|
||||
}
|
||||
|
||||
if changed {
|
||||
c.lgr.Infof("[MIoTClient] GW devices updated: group=%s, count=%d\n", groupID, len(devices))
|
||||
c.lgr.Debugf("[MIoTClient] GW devices updated: group=%s, count=%d\n", groupID, len(devices))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user