package xiaomi import ( "context" "crypto/rand" "encoding/hex" "fmt" "xiaomihome/miot" ) // TokenResult OAuth token 交换结果 type TokenResult struct { AccessToken string `json:"access_token"` RefreshToken string `json:"refresh_token"` ExpiresIn int `json:"expires_in"` UID string `json:"uid"` } // AuthURL 生成小米 OAuth 授权页面 URL。 func AuthURL(cfg Config) string { oa := miot.NewMIoTOauthClient(miot.OAUTH2_CLIENT_ID, "", "cn", generateUUID()) return oa.GenAuthURL("", "", nil, false) } // ExchangeCode 用 authorization code 交换 access token。 func ExchangeCode(ctx context.Context, cfg Config, code string) (*TokenResult, error) { oa := miot.NewMIoTOauthClient(miot.OAUTH2_CLIENT_ID, "", "cn", generateUUID()) result, err := oa.GetAccessToken(code) if err != nil { return nil, fmt.Errorf("xiaomi: exchange token: %w", err) } return &TokenResult{ AccessToken: strVal(result, "access_token"), RefreshToken: strVal(result, "refresh_token"), ExpiresIn: intVal(result, "expires_in"), UID: strVal(result, "uid"), }, nil } func generateUUID() string { b := make([]byte, 16) rand.Read(b) buf := make([]byte, 36) hex.Encode(buf[:8], b[:4]) buf[8] = '-' hex.Encode(buf[9:13], b[4:6]) buf[13] = '-' hex.Encode(buf[14:18], b[6:8]) buf[18] = '-' hex.Encode(buf[19:23], b[8:10]) buf[23] = '-' hex.Encode(buf[24:], b[10:16]) return string(buf) }