// Package miot provides MIoT core client for Xiaomi Home devices. // It's a Golang port of MIoTClient from xiaomihome-py/miot/. package miot import ( "fmt" ) // ============================================================================ // Cloud API calls (aligned with Python miot_client.py) // ============================================================================ // SetProp sets a device property via cloud API. // Aligns with Python: set_prop_async. // did: device ID // siid: service IID // piid: property IID // value: property value // Returns: error if failed. func (c *MIoTClient) SetProp(did string, siid, piid int, value interface{}) error { if c.http == nil { return fmt.Errorf("HTTP client not available") } params := []PropParam{ {DID: did, Siid: siid, Piid: piid, Value: value}, } results, err := c.http.SetProp(params) if err != nil { return err } // Aligns with Python: 空 result 视为失败(Python 会 raise device_exec_error) if len(results) == 0 { return fmt.Errorf("set property failed: empty result (device may be offline)") } // code=0 或 code=1 均视为成功(0=读取成功,1=设置成功) if results[0].Code != 0 && results[0].Code != 1 { // 设备移除或离线:刷新设备列表(Aligns with Python) if results[0].Code == -704010000 || results[0].Code == -704042011 { c.lgr.Errorf("[MIoTClient] device may be removed or offline, %s\n", did) if devs, rerr := c.http.GetDevices(nil); rerr == nil { c.deviceListMu.Lock() for k := range c.deviceListCloud { if _, ok := devs[k]; !ok { delete(c.deviceListCloud, k) } } c.deviceListMu.Unlock() } } return fmt.Errorf("set property failed, code=%d", results[0].Code) } c.lgr.Infof("[MIoTClient] SetProp: %s/%d/%d = %v\n", did, siid, piid, value) return nil } // GetProp gets a device property via cloud API. // Aligns with Python: get_prop_async. // did: device ID // siid: service IID // piid: property IID // Returns: property value and error. func (c *MIoTClient) GetProp(did string, siid, piid int) (interface{}, error) { if c.http == nil { return nil, fmt.Errorf("HTTP client not available") } params := []PropParam{ {DID: did, Siid: siid, Piid: piid}, } results, err := c.http.GetProps(params) if err != nil { return nil, err } if len(results) == 0 { return nil, fmt.Errorf("no result for property %d.%d", siid, piid) } if results[0].Code != 0 { return nil, fmt.Errorf("get property failed, code=%d", results[0].Code) } c.lgr.Infof("[MIoTClient] GetProp: %s/%d/%d = %v\n", did, siid, piid, results[0].Value) return results[0].Value, nil } // Action executes a device action via cloud API. // Aligns with Python: action_async. // did: device ID // siid: service IID // aiid: action IID // inList: input parameters // Returns: action result and error. func (c *MIoTClient) Action(did string, siid, aiid int, inList []interface{}) (map[string]interface{}, error) { if c.http == nil { return nil, fmt.Errorf("HTTP client not available") } result, err := c.http.DoAction(did, siid, aiid, inList) if err != nil { return nil, err } c.lgr.Infof("[MIoTClient] Action: %s/%d/%d, result=%v\n", did, siid, aiid, result) return result, nil } // ============================================================================ // Batch operations (aligned with Python miot_client.py) // ============================================================================ // SetProps sets multiple device properties in batch. // Aligns with Python: set_props_async. // params: slice of PropParam // Returns: slice of PropResult and error. func (c *MIoTClient) SetProps(params []PropParam) ([]PropResult, error) { if c.http == nil { return nil, fmt.Errorf("HTTP client not available") } return c.http.SetProp(params) } // GetProps gets multiple device properties in batch. // Aligns with Python: get_props_async. // params: slice of PropParam // Returns: slice of PropResult and error. func (c *MIoTClient) GetProps(params []PropParam) ([]PropResult, error) { if c.http == nil { return nil, fmt.Errorf("HTTP client not available") } return c.http.GetProps(params) }