From 748c188d12cc7f9033a89c7f83270576125a32a3 Mon Sep 17 00:00:00 2001 From: kunmeng <811096647@qq.com> Date: Sat, 27 Apr 2024 22:50:40 +0800 Subject: [PATCH] First submission --- MiJia.go | 107 +++++++++++++++++++++++++++++ api/getDevices.go | 142 --------------------------------------- api/login.go => login.go | 26 +++---- main.go | 46 ------------- model.go | 59 ++++++++++++++++ model/miji.go | 53 +++++++++++++++ model/v.go | 18 +++++ test/login_test.go | 49 ++++++++++++++ 8 files changed, 294 insertions(+), 206 deletions(-) create mode 100644 MiJia.go delete mode 100644 api/getDevices.go rename api/login.go => login.go (89%) delete mode 100644 main.go create mode 100644 model.go create mode 100644 model/miji.go create mode 100644 model/v.go create mode 100644 test/login_test.go diff --git a/MiJia.go b/MiJia.go new file mode 100644 index 0000000..fe5e6c7 --- /dev/null +++ b/MiJia.go @@ -0,0 +1,107 @@ +package mijia_go_sdk + +import ( + "encoding/json" + "mijia-go-sdk/model" + "strconv" +) + +type MiJia struct { + Certificate Authorize + HomeData Home +} + +func NewMiJia(Certificate Authorize) MiJia { + return MiJia{ + Certificate: Certificate, + } +} + +// 获取设备列表 +func (mi *MiJia) Devices() { + data := map[string]interface{}{ + "getVirtualModel": false, + "getHuamiDevices": 0, + } + PostData("/home/device_list", data, mi.Certificate) +} + +// 获取房间列表 +func (mi *MiJia) Rooms() { + data := map[string]interface{}{ + "fg": false, + "fetch_share": true, + "fetch_share_dev": true, + "limit": 300, + "app_ver": 7, + } + jsonData := PostData("/v2/homeroom/gethome", data, mi.Certificate) + json.Unmarshal(jsonData, &mi.HomeData) +} + +// 获取场景列表 +func (mi *MiJia) Scenes(roomIdx int) { + HomeId := mi.HomeData.Result.Homelist[roomIdx].Id + data := map[string]interface{}{ + "home_id": HomeId, + } + PostData("/appgateway/miot/appsceneservice/AppSceneService/GetSceneList", data, mi.Certificate) +} + +// 根据房间获取耗材列表 +func (mi *MiJia) Consumables(roomIdx int) { + HomeId := mi.HomeData.Result.Homelist[roomIdx].Id + Homei, err := strconv.Atoi(HomeId) + if err != nil { + return + } + data := map[string]interface{}{ + "home_id": Homei, + "owner_id": mi.Certificate.UserId, + } + PostData("/v2/home/standard_consumable_items", data, mi.Certificate) +} + +// 执行场景 +func (mi *MiJia) RunScene(SceneId string) { + data := map[string]interface{}{ + "scene_id": SceneId, + "trigger_key": "user.click", + } + PostData("/appgateway/miot/appsceneservice/AppSceneService/RunScene", data, mi.Certificate) +} + +func (mi *MiJia) GetDeviceVar(devs []map[string]interface{}) ([]model.DeviceVarResult, error) { + data := map[string]interface{}{ + "params": devs, + } + res := PostData("/miotspec/prop/get", data, mi.Certificate) + var Var model.DeviceVar + err := json.Unmarshal(res, &Var) + if err != nil { + return []model.DeviceVarResult{}, err + } + return Var.Result, nil +} +func (mi *MiJia) SetDeviceVar(devs []map[string]interface{}) { + data := map[string]interface{}{ + "params": devs, + } + PostData("/miotspec/prop/set", data, mi.Certificate) +} + +func (mi *MiJia) RunAction(data map[string]interface{}) { + //uri = "/miotspec/action" + //params = dict(params={"did": self.device_id, "siid": sid, "piid": pid, "aiid": aid, "in": values}) + //result = self.http_request(uri, params) + //request_code = result.get("code") + //if not request_code: + //data = result.get("result") + //code = result.get("code") + //if not code: + //return dict(code=0, msg="success", data=data) + //else: + //return dict(code=code, msg="error", data=dict()) + //return dict(code=request_code, msg="request error", data=dict()) + +} diff --git a/api/getDevices.go b/api/getDevices.go deleted file mode 100644 index 25e6924..0000000 --- a/api/getDevices.go +++ /dev/null @@ -1,142 +0,0 @@ -package api - -import ( - "encoding/json" - "strconv" -) - -type MiJia struct { - Certificate Authorize - HomeData Home -} - -func NewMiJia(Certificate Authorize) MiJia { - return MiJia{ - Certificate: Certificate, - } -} - -// 获取设备列表 -func (mi *MiJia) Devices() { - data := map[string]interface{}{ - "getVirtualModel": false, - "getHuamiDevices": 0, - } - PostData("/home/device_list", data, mi.Certificate) -} - -func (mi *MiJia) Rooms() { - data := map[string]interface{}{ - "fg": false, - "fetch_share": true, - "fetch_share_dev": true, - "limit": 300, - "app_ver": 7, - } - jsonData := PostData("/v2/homeroom/gethome", data, mi.Certificate) - json.Unmarshal(jsonData, &mi.HomeData) -} - -// 获取场景列表 -func (mi *MiJia) Scenes(roomIdx int) { - HomeId := mi.HomeData.Result.Homelist[roomIdx].Id - data := map[string]interface{}{ - "home_id": HomeId, - } - PostData("/appgateway/miot/appsceneservice/AppSceneService/GetSceneList", data, mi.Certificate) -} - -// 根据房间获取耗材列表 -func (mi *MiJia) Consumables(roomIdx int) { - HomeId := mi.HomeData.Result.Homelist[roomIdx].Id - Homei, err := strconv.Atoi(HomeId) - if err != nil { - return - } - data := map[string]interface{}{ - "home_id": Homei, - "owner_id": mi.Certificate.UserId, - } - PostData("/v2/home/standard_consumable_items", data, mi.Certificate) -} - -func (mi *MiJia) RunScene(SceneId string) { - data := map[string]interface{}{ - "scene_id": SceneId, - "trigger_key": "user.click", - } - PostData("/appgateway/miot/appsceneservice/AppSceneService/RunScene", data, mi.Certificate) -} - -type HomeList struct { - Id string `json:"id"` - Name string `json:"name"` - Bssid string `json:"bssid"` - Dids []string `json:"dids"` - TempDids interface{} `json:"temp_dids"` - Icon string `json:"icon"` - Shareflag int `json:"shareflag"` - PermitLevel int `json:"permit_level"` - Status int `json:"status"` - Background string `json:"background"` - SmartRoomBackground string `json:"smart_room_background"` - Longitude float64 `json:"longitude"` - Latitude float64 `json:"latitude"` - CityId int `json:"city_id"` - Address string `json:"address"` - CreateTime int `json:"create_time"` - Roomlist []struct { - Id string `json:"id"` - Name string `json:"name"` - Bssid string `json:"bssid"` - Parentid string `json:"parentid"` - Dids []string `json:"dids"` - Icon string `json:"icon"` - Background string `json:"background"` - Shareflag int `json:"shareflag"` - CreateTime int `json:"create_time"` - } - Uid int64 `json:"uid"` - AppearHomeList interface{} `json:"appear_home_list"` - PopupFlag int `json:"popup_flag"` - PopupTimeStamp int `json:"popup_time_stamp"` - CarDid string `json:"car_did"` -} - -type Home struct { - Code int `json:"code"` - Message string `json:"message"` - Result struct { - Homelist []HomeList `json:"homelist"` - HasMore bool `json:"has_more"` - MaxId string `json:"max_id"` - } `json:"result"` -} - -func (mi *MiJia) GetDeviceVar(devs []map[string]interface{}) { - //参数说明 - //did: 设备ID - //siid: 功能分类ID - //piid: 设备属性ID - //aiid: 设备方法ID - //从下述网站查询 - //米家产品库,网站不稳定,不知道siid和piid无法使用`getDevAtt`和`setDevAtt` - //一个取巧的办法是使用在米家APP手动设置批量控制,然后使用`runScene` - //https://home.miot-spec.com/ - // - //获取全部设备列表函数`getDevices`返回结果说明 - //返回结果说明 - //name: 设备名称 - //did: 设备ID - //isOnline: 设备是否在线 - //model: 设备产品型号, 根据这个去米家产品库查该产品相关的信息 - // - //获取设备属性,一次可以请求多个 - //Atts = getDevAtt([{"did":"111111111","siid":2,"piid":1},{"did":"111111111","siid":2,"piid":2}, - // {"did":"111111111","siid":2,"piid":3},{"did":"111111111","siid":2,"piid":4}]) - //print(Atts) - data := map[string]interface{}{ - "params": devs, - } - PostData("/miotspec/prop/get", data, mi.Certificate) -} diff --git a/api/login.go b/login.go similarity index 89% rename from api/login.go rename to login.go index 33cfe6b..ea5bb12 100644 --- a/api/login.go +++ b/login.go @@ -1,4 +1,4 @@ -package api +package mijia_go_sdk import ( "crypto/hmac" @@ -15,10 +15,10 @@ import ( "strings" ) +// 生成随机设备ID func generateRandomDeviceId(size int) string { tempStr := "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" deviceId := make([]byte, size) - _, err := rand.Read(deviceId) if err != nil { panic(err) @@ -27,21 +27,9 @@ func generateRandomDeviceId(size int) string { for i := range deviceId { deviceId[i] = tempStr[deviceId[i]%byte(len(tempStr))] } - return string(deviceId) } -type Authorize struct { - CUserId string `json:"cUserId"` - Code int `json:"code"` - DeviceId string `json:"deviceId"` - Message string `json:"message"` - SecurityToken string `json:"securityToken"` - ServiceToken string `json:"serviceToken"` - Sid string `json:"sid"` - UserId int64 `json:"userId"` -} - func mapToStruct(data map[string]interface{}) (Authorize, error) { jsonStr, err := json.Marshal(data) if err != nil { @@ -57,15 +45,18 @@ func mapToStruct(data map[string]interface{}) (Authorize, error) { return myStruct, nil } +func SetReqHeader(req *http.Request) { + req.Header.Set("User-Agent", "APP/com.xiaomi.mihome APPV/6.0.103 iosPassportSDK/3.9.0 iOS/14.4 miHSTS") +} + func Login(user, pwd string) (Authorize, error) { msgURL := fmt.Sprintf("https://account.xiaomi.com/pass/serviceLogin?sid=xiaomiio&_json=true") loginURL := "https://account.xiaomi.com/pass/serviceLoginAuth2" deviceID := generateRandomDeviceId(16) authorize := make(map[string]interface{}) - userAgent := "APP/com.xiaomi.mihome APPV/6.0.103 iosPassportSDK/3.9.0 iOS/14.4 miHSTS" client := &http.Client{} req, _ := http.NewRequest("GET", msgURL, nil) - req.Header.Set("User-Agent", userAgent) + SetReqHeader(req) req.Header.Set("Accept", "*/*") req.Header.Set("Accept-Language", "zh-tw") req.Header.Set("Cookie", fmt.Sprintf("deviceId=%s; sdkVersion=3.4.1", deviceID)) @@ -162,11 +153,10 @@ func PostData(uri string, data map[string]interface{}, Certificate Authorize) [] body.Set("data", dataStr) body.Set("signature", signature) - userAgent := "APP/com.xiaomi.mihome APPV/6.0.103 iosPassportSDK/3.9.0 iOS/14.4 miHSTS" client := &http.Client{} req, _ := http.NewRequest("POST", "https://api.io.mi.com/app"+uri, strings.NewReader(body.Encode())) + SetReqHeader(req) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.Header.Set("User-Agent", userAgent) req.Header.Set("x-xiaomi-protocal-flag-cli", "PROTOCAL-HTTP2") req.Header.Set("Cookie", fmt.Sprintf("PassportDeviceId=%s;userId=%v;serviceToken=%s;", Certificate.DeviceId, Certificate.UserId, Certificate.ServiceToken)) resp, err := client.Do(req) diff --git a/main.go b/main.go deleted file mode 100644 index d240bbd..0000000 --- a/main.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "encoding/json" - "fmt" - "mijia-go-sdk/api" -) - -func main() { - user := "15542100924" - pwd := "1XAII@wsk" - result, _ := api.Login(user, pwd) - marshal, err := json.Marshal(result) - if err != nil { - return - } - Mi := api.NewMiJia(result) - //Mi.Rooms() - //Mi.Devices() - //Mi.Scenes(0) - //Mi.RunScene("1784216758920822784") - - var data []map[string]interface{} - - data = append(data, map[string]interface{}{ - "did": "538261193", - "siid": 2, - "piid": 1, - }) - data = append(data, map[string]interface{}{ - "did": "538261193", - "siid": 2, - "piid": 2, - }) - data = append(data, map[string]interface{}{ - "did": "538261193", - "siid": 2, - "piid": 3, - }) - - Mi.GetDeviceVar(data) - //Mi.Consumables(0) - //Mi.Scenes(0) - println(marshal) - fmt.Println(result) -} diff --git a/model.go b/model.go new file mode 100644 index 0000000..e2ea105 --- /dev/null +++ b/model.go @@ -0,0 +1,59 @@ +package mijia_go_sdk + +// 小米认证授权信息 +type Authorize struct { + CUserId string `json:"cUserId"` + Code int `json:"code"` + DeviceId string `json:"deviceId"` + Message string `json:"message"` + SecurityToken string `json:"securityToken"` + ServiceToken string `json:"serviceToken"` + Sid string `json:"sid"` + UserId int64 `json:"userId"` +} + +type HomeList struct { + Id string `json:"id"` + Name string `json:"name"` + Bssid string `json:"bssid"` + Dids []string `json:"dids"` + TempDids interface{} `json:"temp_dids"` + Icon string `json:"icon"` + Shareflag int `json:"shareflag"` + PermitLevel int `json:"permit_level"` + Status int `json:"status"` + Background string `json:"background"` + SmartRoomBackground string `json:"smart_room_background"` + Longitude float64 `json:"longitude"` + Latitude float64 `json:"latitude"` + CityId int `json:"city_id"` + Address string `json:"address"` + CreateTime int `json:"create_time"` + Roomlist []RoomList + Uid int64 `json:"uid"` + AppearHomeList interface{} `json:"appear_home_list"` + PopupFlag int `json:"popup_flag"` + PopupTimeStamp int `json:"popup_time_stamp"` + CarDid string `json:"car_did"` +} +type RoomList struct { + Id string `json:"id"` + Name string `json:"name"` + Bssid string `json:"bssid"` + Parentid string `json:"parentid"` + Dids []string `json:"dids"` + Icon string `json:"icon"` + Background string `json:"background"` + Shareflag int `json:"shareflag"` + CreateTime int `json:"create_time"` +} + +type Home struct { + Code int `json:"code"` + Message string `json:"message"` + Result struct { + Homelist []HomeList `json:"homelist"` + HasMore bool `json:"has_more"` + MaxId string `json:"max_id"` + } `json:"result"` +} diff --git a/model/miji.go b/model/miji.go new file mode 100644 index 0000000..8e819c0 --- /dev/null +++ b/model/miji.go @@ -0,0 +1,53 @@ +package model + +type T struct { + Code int `json:"code"` + Message string `json:"message"` + Result struct { + List []struct { + Did string `json:"did"` + Token string `json:"token"` + Longitude string `json:"longitude"` + Latitude string `json:"latitude"` + Name string `json:"name"` + Pid string `json:"pid"` + Localip string `json:"localip"` + Mac string `json:"mac"` + Ssid string `json:"ssid"` + Bssid string `json:"bssid"` + ParentId string `json:"parent_id"` + ParentModel string `json:"parent_model"` + ShowMode int `json:"show_mode"` + Model string `json:"model"` + AdminFlag int `json:"adminFlag"` + ShareFlag int `json:"shareFlag"` + PermitLevel int `json:"permitLevel"` + IsOnline bool `json:"isOnline"` + Desc string `json:"desc"` + Extra struct { + IsSetPincode int `json:"isSetPincode"` + PincodeType int `json:"pincodeType"` + FwVersion string `json:"fw_version,omitempty"` + NeedVerifyCode int `json:"needVerifyCode,omitempty"` + IsPasswordEncrypt int `json:"isPasswordEncrypt,omitempty"` + McuVersion string `json:"mcu_version,omitempty"` + Platform string `json:"platform,omitempty"` + } `json:"extra"` + Uid int64 `json:"uid"` + PdId int `json:"pd_id"` + Password string `json:"password"` + P2PId string `json:"p2p_id"` + Rssi int `json:"rssi"` + FamilyId int `json:"family_id"` + ResetFlag int `json:"reset_flag"` + Prop struct { + Status string `json:"status"` + } `json:"prop,omitempty"` + Owner struct { + Userid int `json:"userid"` + Nickname string `json:"nickname"` + Icon interface{} `json:"icon"` + } `json:"owner,omitempty"` + } `json:"list"` + } `json:"result"` +} diff --git a/model/v.go b/model/v.go new file mode 100644 index 0000000..e233bab --- /dev/null +++ b/model/v.go @@ -0,0 +1,18 @@ +package model + +type DeviceVar struct { + Code int `json:"code"` + Message string `json:"message"` + Result []DeviceVarResult `json:"result"` +} + +type DeviceVarResult struct { + Did string `json:"did"` + Iid string `json:"iid"` + Siid int `json:"siid"` + Piid int `json:"piid"` + Value interface{} `json:"value"` + Code int `json:"code"` + UpdateTime int `json:"updateTime"` + ExeTime int `json:"exe_time"` +} diff --git a/test/login_test.go b/test/login_test.go new file mode 100644 index 0000000..7162770 --- /dev/null +++ b/test/login_test.go @@ -0,0 +1,49 @@ +package test + +import ( + "encoding/json" + "fmt" + "mijia-go-sdk" + "testing" + "time" +) + +func Test_login(t *testing.T) { + + user := "15542100924" + pwd := "1XAII@wsk" + result, _ := mijia_go_sdk.Login(user, pwd) + _, err := json.Marshal(result) + if err != nil { + return + } + Mi := mijia_go_sdk.NewMiJia(result) + //Mi.Rooms() + Mi.Devices() + //Mi.Scenes(0) + //Mi.RunScene("1784216758920822784") + + var data []map[string]interface{} + + data = append(data, map[string]interface{}{ + "did": "740885802", + "siid": 9, + "piid": 1, + }) + data = append(data, map[string]interface{}{ + "did": "740885802", + "siid": 9, + "piid": 2, + }) + + deviceVar, err := Mi.GetDeviceVar(data) + if err != nil { + return + } + for _, v := range deviceVar { + fmt.Printf("%f", v.Value) + } + time.Sleep(10 * time.Second) + //Mi.Consumables(0) + //Mi.Scenes(0) +}