按照 TOKEN_REFACTOR.md / FIX_CONFIG.md 方案重构核心层: - miot: Init() 优先读 storage token,新增 RefreshAuthInfo() 和刷新回调 - xiaomi: Config 改用 AuthInfo 结构体(含 UUID/UID/DataDir/OnTokenRefreshed) - xiaomi: NewClient(ctx, Config) 新签名,新增 RefreshToken(),后台自动刷新 - xiaomi/devices: 设备控制接口重构 - 新增示例 12_ac_subscribe,其余示例适配新 Config
280 lines
9.7 KiB
Go
280 lines
9.7 KiB
Go
// Package miot provides MIoT core client for Xiaomi Home devices.
|
|
// This file is a direct port of py-miot/const.py constants system.
|
|
package miot
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// ============================================================================
|
|
// String constants (aligned with Python miot/const.py)
|
|
// ============================================================================
|
|
|
|
const (
|
|
DOMAIN = "xiaomi_home"
|
|
DEFAULT_NAME = "Xiaomi Home"
|
|
DEFAULT_NICK_NAME = "Xiaomi"
|
|
OAUTH2_CLIENT_ID = "2882303761520251711"
|
|
OAUTH2_AUTH_URL = "https://account.xiaomi.com/oauth2/authorize"
|
|
DEFAULT_OAUTH2_API_HOST = "ha.api.io.mi.com"
|
|
DEFAULT_CLOUD_BROKER_HOST = "ha.mqtt.io.mi.com"
|
|
DEFAULT_CLOUD_SERVER = "cn"
|
|
DEFAULT_CTRL_MODE = "auto"
|
|
DEFAULT_INTEGRATION_LANGUAGE = "en"
|
|
OAUTH_REDIRECT_URL = "http://homeassistant.local:8123"
|
|
)
|
|
|
|
// ============================================================================
|
|
// Numeric constants (aligned with Python miot/const.py)
|
|
// ============================================================================
|
|
|
|
const (
|
|
MIHOME_HTTP_API_TIMEOUT = 30
|
|
MIHOME_MQTT_KEEPALIVE = 60
|
|
// seconds, 3 days
|
|
MIHOME_CERT_EXPIRE_MARGIN = 3600 * 24 * 3
|
|
// seconds, 1 hour — token 过期前刷新(比 Python 60s 更保守)
|
|
MIHOME_REFRESH_THRESHOLD = 3600 * 6
|
|
NETWORK_REFRESH_INTERVAL = 30
|
|
// seconds, 14 days
|
|
SPEC_STD_LIB_EFFECTIVE_TIME = 3600 * 24 * 14
|
|
// seconds, 14 days
|
|
MANUFACTURER_EFFECTIVE_TIME = 3600 * 24 * 14
|
|
)
|
|
|
|
// ============================================================================
|
|
// Variables — slices, maps, and configurable values (aligned with Python miot/const.py)
|
|
// ============================================================================
|
|
|
|
var (
|
|
// SUPPORTED_PLATFORMS lists Home Assistant platforms supported by MIoT integration.
|
|
SUPPORTED_PLATFORMS = []string{
|
|
"binary_sensor",
|
|
"button",
|
|
"climate",
|
|
"cover",
|
|
"device_tracker",
|
|
"event",
|
|
"fan",
|
|
"humidifier",
|
|
"light",
|
|
"media_player",
|
|
"notify",
|
|
"number",
|
|
"select",
|
|
"sensor",
|
|
"switch",
|
|
"text",
|
|
"vacuum",
|
|
"water_heater",
|
|
}
|
|
|
|
// UNSUPPORTED_MODELS lists device models explicitly not supported.
|
|
UNSUPPORTED_MODELS = []string{
|
|
"chuangmi.ir.v2",
|
|
"era.airp.cwb03",
|
|
"hmpace.motion.v6nfc",
|
|
"k0918.toothbrush.t700",
|
|
}
|
|
|
|
// CLOUD_SERVERS maps cloud server region codes to human-readable names.
|
|
CLOUD_SERVERS = map[string]string{
|
|
"cn": "中国大陆",
|
|
"de": "Europe",
|
|
"i2": "India",
|
|
"ru": "Russia",
|
|
"sg": "Singapore",
|
|
"us": "United States",
|
|
}
|
|
|
|
// SUPPORT_CENTRAL_GATEWAY_CTRL lists regions that support central gateway control.
|
|
SUPPORT_CENTRAL_GATEWAY_CTRL = []string{"cn"}
|
|
|
|
// INTEGRATION_LANGUAGES maps language codes to human-readable names.
|
|
INTEGRATION_LANGUAGES = map[string]string{
|
|
"de": "Deutsch",
|
|
"en": "English",
|
|
"es": "Español",
|
|
"fr": "Français",
|
|
"it": "Italiano",
|
|
"ja": "日本語",
|
|
"nl": "Nederlands",
|
|
"pt": "Português",
|
|
"pt-BR": "Português (Brasil)",
|
|
"ru": "Русский",
|
|
"tr": "Türkçe",
|
|
"zh-Hans": "简体中文",
|
|
"zh-Hant": "繁體中文",
|
|
}
|
|
)
|
|
|
|
// Cover dead zone width — configurable at runtime.
|
|
var (
|
|
DEFAULT_COVER_DEAD_ZONE_WIDTH = 0
|
|
MIN_COVER_DEAD_ZONE_WIDTH = 0
|
|
MAX_COVER_DEAD_ZONE_WIDTH = 5
|
|
)
|
|
|
|
// ============================================================================
|
|
// CA Certificate constants (aligned with Python miot/const.py)
|
|
// ============================================================================
|
|
|
|
// MIHOME_CA_CERT_STR is the MIoT CA certificate in PEM format.
|
|
// Contains: Mijia Root CA + MIOT Central Gateway CA.
|
|
const MIHOME_CA_CERT_STR = `-----BEGIN CERTIFICATE-----
|
|
MIIBazCCAQ+gAwIBAgIEA/UKYDAMBggqhkjOPQQDAgUAMCIxEzARBgNVBAoTCk1p
|
|
amlhIFJvb3QxCzAJBgNVBAYTAkNOMCAXDTE2MTEyMzAxMzk0NVoYDzIwNjYxMTEx
|
|
MDEzOTQ1WjAiMRMwEQYDVQQKEwpNaWppYSBSb290MQswCQYDVQQGEwJDTjBZMBMG
|
|
ByqGSM49AgEGCCqGSM49AwEHA0IABL71iwLa4//4VBqgRI+6xE23xpovqPCxtv96
|
|
2VHbZij61/Ag6jmi7oZ/3Xg/3C+whglcwoUEE6KALGJ9vccV9PmjLzAtMAwGA1Ud
|
|
EwQFMAMBAf8wHQYDVR0OBBYEFJa3onw5sblmM6n40QmyAGDI5sURMAwGCCqGSM49
|
|
BAMCBQADSAAwRQIgchciK9h6tZmfrP8Ka6KziQ4Lv3hKfrHtAZXMHPda4IYCIQCG
|
|
az93ggFcbrG9u2wixjx1HKW4DUA5NXZG0wWQTpJTbQ==
|
|
-----END CERTIFICATE-----
|
|
-----BEGIN CERTIFICATE-----
|
|
MIIBjzCCATWgAwIBAgIBATAKBggqhkjOPQQDAjAiMRMwEQYDVQQKEwpNaWppYSBS
|
|
b290MQswCQYDVQQGEwJDTjAgFw0yMjA2MDkxNDE0MThaGA8yMDcyMDUyNzE0MTQx
|
|
OFowLDELMAkGA1UEBhMCQ04xHTAbBgNVBAoMFE1JT1QgQ0VOVFJBTCBHQVRFV0FZ
|
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdYrzbnp/0x/cZLZnuEDXTFf8mhj4
|
|
CVpZPwgj9e9Ve5r3K7zvu8Jjj7JF1JjQYvEC6yhp1SzBgglnK4L8xQzdiqNQME4w
|
|
HQYDVR0OBBYEFCf9+YBU7pXDs6K6CAQPRhlGJ+cuMB8GA1UdIwQYMBaAFJa3onw5
|
|
sblmM6n40QmyAGDI5sURMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIh
|
|
AKUv+c8v98vypkGMTzMwckGjjVqTef8xodsy6PhcSCq+AiA/n9mDs62hAo5zXyJy
|
|
Bs1s7mqXPf1XgieoxIvs1MqyiA==
|
|
-----END CERTIFICATE-----`
|
|
|
|
// MIHOME_CA_CERT_SHA256 is the SHA256 hash of the MIoT CA certificate.
|
|
const MIHOME_CA_CERT_SHA256 = "8b7bf306be3632e08b0ead308249e5f2b2520dc921ad143872d5fcc7c68d6759"
|
|
|
|
// ============================================================================
|
|
// CtrlMode — control mode enum (migrated from deleted constants.go)
|
|
// ============================================================================
|
|
|
|
// CtrlMode represents the control mode for devices.
|
|
type CtrlMode int
|
|
|
|
const (
|
|
// CtrlModeCloud represents cloud control mode.
|
|
CtrlModeCloud CtrlMode = iota
|
|
// CtrlModeGateway represents gateway control mode.
|
|
CtrlModeGateway
|
|
// CtrlModeLAN represents LAN control mode.
|
|
CtrlModeLAN
|
|
// CtrlModeAuto represents auto control mode.
|
|
CtrlModeAuto
|
|
)
|
|
|
|
// String returns the string representation of CtrlMode.
|
|
func (m CtrlMode) String() string {
|
|
switch m {
|
|
case CtrlModeAuto:
|
|
return "auto"
|
|
case CtrlModeCloud:
|
|
return "cloud"
|
|
case CtrlModeGateway:
|
|
return "gateway"
|
|
case CtrlModeLAN:
|
|
return "lan"
|
|
default:
|
|
return "unknown"
|
|
}
|
|
}
|
|
|
|
// ParseCtrlMode parses a string into a CtrlMode value.
|
|
// "cloud" → CtrlModeCloud, "gateway" → CtrlModeGateway, "lan" → CtrlModeLAN.
|
|
// Returns an error for unknown strings.
|
|
// Aligns with Python: CtrlMode.load(mode).
|
|
func ParseCtrlMode(s string) (CtrlMode, error) {
|
|
switch strings.ToLower(s) {
|
|
case "auto":
|
|
return CtrlModeAuto, nil
|
|
case "cloud":
|
|
return CtrlModeCloud, nil
|
|
case "gateway":
|
|
return CtrlModeGateway, nil
|
|
case "lan":
|
|
return CtrlModeLAN, nil
|
|
default:
|
|
return 0, fmt.Errorf("unknown ctrl mode: %s", s)
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// Refresh / retry timings (migrated from deleted constants.go)
|
|
// ============================================================================
|
|
|
|
// RefreshPropsDelay is the delay before executing property refresh (200ms, aligns with Python).
|
|
const RefreshPropsDelay = 200
|
|
|
|
// RefreshPropsRetryMax is the maximum number of retries for property refresh (3, aligns with Python).
|
|
const RefreshPropsRetryMax = 3
|
|
|
|
// RefreshPropsRetryDelay is the delay between property refresh retries (3s, aligns with Python).
|
|
const RefreshPropsRetryDelay = 3 * 1000 // 3 seconds in milliseconds
|
|
|
|
// RefreshCloudDevicesDelay is the delay before refreshing cloud devices (6s, aligns with Python).
|
|
const RefreshCloudDevicesDelay = 6 * 1000 // 6 seconds in milliseconds
|
|
|
|
// RefreshCloudDevicesRetryDelay is the delay before retrying cloud device refresh (60s, aligns with Python).
|
|
const RefreshCloudDevicesRetryDelay = 60 * 1000 // 60 seconds in milliseconds
|
|
|
|
// TokenRefreshInterval is the interval for refreshing OAuth token (aligns with Python).
|
|
const TokenRefreshInterval = 3600 * 1000 // 1 hour in milliseconds
|
|
|
|
// CertRefreshInterval is the interval for refreshing certificate (aligns with Python).
|
|
const CertRefreshInterval = 24 * 3600 * 1000 // 24 hours in milliseconds
|
|
|
|
// RefreshAuthRetryDelay is the delay before retrying token refresh (3600s, aligns with Python).
|
|
const RefreshAuthRetryDelay = 3600
|
|
|
|
// RefreshCertRetryDelay is the delay before retrying cert refresh (300s, aligns with Python).
|
|
const RefreshCertRetryDelay = 300
|
|
|
|
// ============================================================================
|
|
// MQTT topics (migrated from deleted constants.go)
|
|
// ============================================================================
|
|
|
|
// TopicProp is the MQTT topic for property changes.
|
|
const TopicProp = "properties_changed"
|
|
|
|
// TopicEvent is the MQTT topic for event occurrences.
|
|
const TopicEvent = "event_occured"
|
|
|
|
// TopicState is the MQTT topic for device state changes.
|
|
const TopicState = "state"
|
|
|
|
// ============================================================================
|
|
// API paths / defaults (migrated from deleted constants.go)
|
|
// ============================================================================
|
|
|
|
// APIPathGetDevices is the API path for getting devices.
|
|
const APIPathGetDevices = "/v2/home/device/list"
|
|
|
|
// APIPathGetProps is the API path for getting properties.
|
|
const APIPathGetProps = "/v2/home/device/prop/get"
|
|
|
|
// APIPathSetProps is the API path for setting properties.
|
|
const APIPathSetProps = "/v2/home/device/prop/set"
|
|
|
|
// APIPathDoAction is the API path for executing actions.
|
|
const APIPathDoAction = "/v2/home/device/action"
|
|
|
|
// DefaultCloudServer is the default cloud server.
|
|
const DefaultCloudServer = "cn"
|
|
|
|
// DefaultOAUTH2APIHost is the default OAuth2 API host (aligned with Python).
|
|
const DefaultOAUTH2APIHost = "ha.api.io.mi.com"
|
|
|
|
// MHomeHTTPAPITimeout is the HTTP API timeout in seconds (aligned with Python).
|
|
const MHomeHTTPAPITimeout = 30
|
|
|
|
// DefaultMQTTBroker is the default MQTT broker address.
|
|
const DefaultMQTTBroker = "ssl://cn-ha.mqtt.io.mi.com:8883"
|
|
|
|
// DefaultMQTTKeepAlive is the default MQTT keep-alive interval in seconds.
|
|
const DefaultMQTTKeepAlive = 60
|
|
|
|
// DefaultMQTTQoS is the default MQTT QoS level.
|
|
const DefaultMQTTQoS = 1
|