mirror of
https://github.com/home-assistant/core.git
synced 2025-07-26 06:37:52 +00:00
Xiaomi MiIO Switch: Support for the Xiaomi Chuangmi Plug V3 (#13271)
* Device support of the Xiaomi Chuangmi Plug V3 added * Refactoring. * Additional attributes added. * New miio device class used
This commit is contained in:
parent
979a8f8772
commit
9cfcd38c1e
@ -24,6 +24,7 @@ DATA_KEY = 'switch.xiaomi_miio'
|
|||||||
|
|
||||||
CONF_MODEL = 'model'
|
CONF_MODEL = 'model'
|
||||||
MODEL_POWER_STRIP_V2 = 'zimi.powerstrip.v2'
|
MODEL_POWER_STRIP_V2 = 'zimi.powerstrip.v2'
|
||||||
|
MODEL_PLUG_V3 = 'chuangmi.plug.v3'
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Required(CONF_HOST): cv.string,
|
vol.Required(CONF_HOST): cv.string,
|
||||||
@ -34,7 +35,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
'qmi.powerstrip.v1',
|
'qmi.powerstrip.v1',
|
||||||
'zimi.powerstrip.v2',
|
'zimi.powerstrip.v2',
|
||||||
'chuangmi.plug.m1',
|
'chuangmi.plug.m1',
|
||||||
'chuangmi.plug.v2']),
|
'chuangmi.plug.v2',
|
||||||
|
'chuangmi.plug.v3']),
|
||||||
})
|
})
|
||||||
|
|
||||||
REQUIREMENTS = ['python-miio==0.3.9', 'construct==2.9.41']
|
REQUIREMENTS = ['python-miio==0.3.9', 'construct==2.9.41']
|
||||||
@ -51,18 +53,20 @@ ATTR_PRICE = 'price'
|
|||||||
|
|
||||||
SUCCESS = ['ok']
|
SUCCESS = ['ok']
|
||||||
|
|
||||||
SUPPORT_SET_POWER_MODE = 1
|
FEATURE_SET_POWER_MODE = 1
|
||||||
SUPPORT_SET_WIFI_LED = 2
|
FEATURE_SET_WIFI_LED = 2
|
||||||
SUPPORT_SET_POWER_PRICE = 4
|
FEATURE_SET_POWER_PRICE = 4
|
||||||
|
|
||||||
ADDITIONAL_SUPPORT_FLAGS_GENERIC = 0
|
FEATURE_FLAGS_GENERIC = 0
|
||||||
|
|
||||||
ADDITIONAL_SUPPORT_FLAGS_POWER_STRIP_V1 = (SUPPORT_SET_POWER_MODE |
|
FEATURE_FLAGS_POWER_STRIP_V1 = (FEATURE_SET_POWER_MODE |
|
||||||
SUPPORT_SET_WIFI_LED |
|
FEATURE_SET_WIFI_LED |
|
||||||
SUPPORT_SET_POWER_PRICE)
|
FEATURE_SET_POWER_PRICE)
|
||||||
|
|
||||||
ADDITIONAL_SUPPORT_FLAGS_POWER_STRIP_V2 = (SUPPORT_SET_WIFI_LED |
|
FEATURE_FLAGS_POWER_STRIP_V2 = (FEATURE_SET_WIFI_LED |
|
||||||
SUPPORT_SET_POWER_PRICE)
|
FEATURE_SET_POWER_PRICE)
|
||||||
|
|
||||||
|
FEATURE_FLAGS_PLUG_V3 = (FEATURE_SET_WIFI_LED)
|
||||||
|
|
||||||
SERVICE_SET_WIFI_LED_ON = 'xiaomi_miio_set_wifi_led_on'
|
SERVICE_SET_WIFI_LED_ON = 'xiaomi_miio_set_wifi_led_on'
|
||||||
SERVICE_SET_WIFI_LED_OFF = 'xiaomi_miio_set_wifi_led_off'
|
SERVICE_SET_WIFI_LED_OFF = 'xiaomi_miio_set_wifi_led_off'
|
||||||
@ -124,29 +128,27 @@ async def async_setup_platform(hass, config, async_add_devices,
|
|||||||
except DeviceException:
|
except DeviceException:
|
||||||
raise PlatformNotReady
|
raise PlatformNotReady
|
||||||
|
|
||||||
if model in ['chuangmi.plug.v1']:
|
if model in ['chuangmi.plug.v1', 'chuangmi.plug.v3']:
|
||||||
from miio import PlugV1
|
from miio import ChuangmiPlug
|
||||||
plug = PlugV1(host, token)
|
plug = ChuangmiPlug(host, token, model=model)
|
||||||
|
|
||||||
# The device has two switchable channels (mains and a USB port).
|
# The device has two switchable channels (mains and a USB port).
|
||||||
# A switch device per channel will be created.
|
# A switch device per channel will be created.
|
||||||
for channel_usb in [True, False]:
|
for channel_usb in [True, False]:
|
||||||
device = ChuangMiPlugV1Switch(
|
device = ChuangMiPlugSwitch(
|
||||||
name, plug, model, unique_id, channel_usb)
|
name, plug, model, unique_id, channel_usb)
|
||||||
devices.append(device)
|
devices.append(device)
|
||||||
hass.data[DATA_KEY][host] = device
|
hass.data[DATA_KEY][host] = device
|
||||||
|
|
||||||
elif model in ['qmi.powerstrip.v1',
|
elif model in ['qmi.powerstrip.v1', 'zimi.powerstrip.v2']:
|
||||||
'zimi.powerstrip.v2']:
|
|
||||||
from miio import PowerStrip
|
from miio import PowerStrip
|
||||||
plug = PowerStrip(host, token)
|
plug = PowerStrip(host, token)
|
||||||
device = XiaomiPowerStripSwitch(name, plug, model, unique_id)
|
device = XiaomiPowerStripSwitch(name, plug, model, unique_id)
|
||||||
devices.append(device)
|
devices.append(device)
|
||||||
hass.data[DATA_KEY][host] = device
|
hass.data[DATA_KEY][host] = device
|
||||||
elif model in ['chuangmi.plug.m1',
|
elif model in ['chuangmi.plug.m1', 'chuangmi.plug.v2']:
|
||||||
'chuangmi.plug.v2']:
|
from miio import ChuangmiPlug
|
||||||
from miio import Plug
|
plug = ChuangmiPlug(host, token, model=model)
|
||||||
plug = Plug(host, token)
|
|
||||||
device = XiaomiPlugGenericSwitch(name, plug, model, unique_id)
|
device = XiaomiPlugGenericSwitch(name, plug, model, unique_id)
|
||||||
devices.append(device)
|
devices.append(device)
|
||||||
hass.data[DATA_KEY][host] = device
|
hass.data[DATA_KEY][host] = device
|
||||||
@ -204,7 +206,7 @@ class XiaomiPlugGenericSwitch(SwitchDevice):
|
|||||||
ATTR_TEMPERATURE: None,
|
ATTR_TEMPERATURE: None,
|
||||||
ATTR_MODEL: self._model,
|
ATTR_MODEL: self._model,
|
||||||
}
|
}
|
||||||
self._additional_supported_features = ADDITIONAL_SUPPORT_FLAGS_GENERIC
|
self._device_features = FEATURE_FLAGS_GENERIC
|
||||||
self._skip_update = False
|
self._skip_update = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -251,6 +253,10 @@ class XiaomiPlugGenericSwitch(SwitchDevice):
|
|||||||
|
|
||||||
_LOGGER.debug("Response received from plug: %s", result)
|
_LOGGER.debug("Response received from plug: %s", result)
|
||||||
|
|
||||||
|
# The Chuangmi Plug V3 returns 0 on success on usb_on/usb_off.
|
||||||
|
if func in ['usb_on', 'usb_off'] and result == 0:
|
||||||
|
return True
|
||||||
|
|
||||||
return result == SUCCESS
|
return result == SUCCESS
|
||||||
except DeviceException as exc:
|
except DeviceException as exc:
|
||||||
_LOGGER.error(mask_error, exc)
|
_LOGGER.error(mask_error, exc)
|
||||||
@ -300,7 +306,7 @@ class XiaomiPlugGenericSwitch(SwitchDevice):
|
|||||||
|
|
||||||
async def async_set_wifi_led_on(self):
|
async def async_set_wifi_led_on(self):
|
||||||
"""Turn the wifi led on."""
|
"""Turn the wifi led on."""
|
||||||
if self._additional_supported_features & SUPPORT_SET_WIFI_LED == 0:
|
if self._device_features & FEATURE_SET_WIFI_LED == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
await self._try_command(
|
await self._try_command(
|
||||||
@ -309,7 +315,7 @@ class XiaomiPlugGenericSwitch(SwitchDevice):
|
|||||||
|
|
||||||
async def async_set_wifi_led_off(self):
|
async def async_set_wifi_led_off(self):
|
||||||
"""Turn the wifi led on."""
|
"""Turn the wifi led on."""
|
||||||
if self._additional_supported_features & SUPPORT_SET_WIFI_LED == 0:
|
if self._device_features & FEATURE_SET_WIFI_LED == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
await self._try_command(
|
await self._try_command(
|
||||||
@ -318,7 +324,7 @@ class XiaomiPlugGenericSwitch(SwitchDevice):
|
|||||||
|
|
||||||
async def async_set_power_price(self, price: int):
|
async def async_set_power_price(self, price: int):
|
||||||
"""Set the power price."""
|
"""Set the power price."""
|
||||||
if self._additional_supported_features & SUPPORT_SET_POWER_PRICE == 0:
|
if self._device_features & FEATURE_SET_POWER_PRICE == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
await self._try_command(
|
await self._try_command(
|
||||||
@ -331,26 +337,24 @@ class XiaomiPowerStripSwitch(XiaomiPlugGenericSwitch):
|
|||||||
|
|
||||||
def __init__(self, name, plug, model, unique_id):
|
def __init__(self, name, plug, model, unique_id):
|
||||||
"""Initialize the plug switch."""
|
"""Initialize the plug switch."""
|
||||||
XiaomiPlugGenericSwitch.__init__(self, name, plug, model, unique_id)
|
super().__init__(name, plug, model, unique_id)
|
||||||
|
|
||||||
if self._model == MODEL_POWER_STRIP_V2:
|
if self._model == MODEL_POWER_STRIP_V2:
|
||||||
self._additional_supported_features = \
|
self._device_features = FEATURE_FLAGS_POWER_STRIP_V2
|
||||||
ADDITIONAL_SUPPORT_FLAGS_POWER_STRIP_V2
|
|
||||||
else:
|
else:
|
||||||
self._additional_supported_features = \
|
self._device_features = FEATURE_FLAGS_POWER_STRIP_V1
|
||||||
ADDITIONAL_SUPPORT_FLAGS_POWER_STRIP_V1
|
|
||||||
|
|
||||||
self._state_attrs.update({
|
self._state_attrs.update({
|
||||||
ATTR_LOAD_POWER: None,
|
ATTR_LOAD_POWER: None,
|
||||||
})
|
})
|
||||||
|
|
||||||
if self._additional_supported_features & SUPPORT_SET_POWER_MODE == 1:
|
if self._device_features & FEATURE_SET_POWER_MODE == 1:
|
||||||
self._state_attrs[ATTR_POWER_MODE] = None
|
self._state_attrs[ATTR_POWER_MODE] = None
|
||||||
|
|
||||||
if self._additional_supported_features & SUPPORT_SET_WIFI_LED == 1:
|
if self._device_features & FEATURE_SET_WIFI_LED == 1:
|
||||||
self._state_attrs[ATTR_WIFI_LED] = None
|
self._state_attrs[ATTR_WIFI_LED] = None
|
||||||
|
|
||||||
if self._additional_supported_features & SUPPORT_SET_POWER_PRICE == 1:
|
if self._device_features & FEATURE_SET_POWER_PRICE == 1:
|
||||||
self._state_attrs[ATTR_POWER_PRICE] = None
|
self._state_attrs[ATTR_POWER_PRICE] = None
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
@ -373,16 +377,16 @@ class XiaomiPowerStripSwitch(XiaomiPlugGenericSwitch):
|
|||||||
ATTR_LOAD_POWER: state.load_power,
|
ATTR_LOAD_POWER: state.load_power,
|
||||||
})
|
})
|
||||||
|
|
||||||
if self._additional_supported_features & \
|
if self._device_features & FEATURE_SET_POWER_MODE == 1 and \
|
||||||
SUPPORT_SET_POWER_MODE == 1 and state.mode:
|
state.mode:
|
||||||
self._state_attrs[ATTR_POWER_MODE] = state.mode.value
|
self._state_attrs[ATTR_POWER_MODE] = state.mode.value
|
||||||
|
|
||||||
if self._additional_supported_features & \
|
if self._device_features & FEATURE_SET_WIFI_LED == 1 and \
|
||||||
SUPPORT_SET_WIFI_LED == 1 and state.wifi_led:
|
state.wifi_led:
|
||||||
self._state_attrs[ATTR_WIFI_LED] = state.wifi_led
|
self._state_attrs[ATTR_WIFI_LED] = state.wifi_led
|
||||||
|
|
||||||
if self._additional_supported_features & \
|
if self._device_features & FEATURE_SET_POWER_PRICE == 1 and \
|
||||||
SUPPORT_SET_POWER_PRICE == 1 and state.power_price:
|
state.power_price:
|
||||||
self._state_attrs[ATTR_POWER_PRICE] = state.power_price
|
self._state_attrs[ATTR_POWER_PRICE] = state.power_price
|
||||||
|
|
||||||
except DeviceException as ex:
|
except DeviceException as ex:
|
||||||
@ -391,7 +395,7 @@ class XiaomiPowerStripSwitch(XiaomiPlugGenericSwitch):
|
|||||||
|
|
||||||
async def async_set_power_mode(self, mode: str):
|
async def async_set_power_mode(self, mode: str):
|
||||||
"""Set the power mode."""
|
"""Set the power mode."""
|
||||||
if self._additional_supported_features & SUPPORT_SET_POWER_MODE == 0:
|
if self._device_features & FEATURE_SET_POWER_MODE == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
from miio.powerstrip import PowerMode
|
from miio.powerstrip import PowerMode
|
||||||
@ -401,8 +405,8 @@ class XiaomiPowerStripSwitch(XiaomiPlugGenericSwitch):
|
|||||||
self._plug.set_power_mode, PowerMode(mode))
|
self._plug.set_power_mode, PowerMode(mode))
|
||||||
|
|
||||||
|
|
||||||
class ChuangMiPlugV1Switch(XiaomiPlugGenericSwitch):
|
class ChuangMiPlugSwitch(XiaomiPlugGenericSwitch):
|
||||||
"""Representation of a Chuang Mi Plug V1."""
|
"""Representation of a Chuang Mi Plug V1 and V3."""
|
||||||
|
|
||||||
def __init__(self, name, plug, model, unique_id, channel_usb):
|
def __init__(self, name, plug, model, unique_id, channel_usb):
|
||||||
"""Initialize the plug switch."""
|
"""Initialize the plug switch."""
|
||||||
@ -411,9 +415,16 @@ class ChuangMiPlugV1Switch(XiaomiPlugGenericSwitch):
|
|||||||
if unique_id is not None and channel_usb:
|
if unique_id is not None and channel_usb:
|
||||||
unique_id = "{}-{}".format(unique_id, 'usb')
|
unique_id = "{}-{}".format(unique_id, 'usb')
|
||||||
|
|
||||||
XiaomiPlugGenericSwitch.__init__(self, name, plug, model, unique_id)
|
super().__init__(name, plug, model, unique_id)
|
||||||
self._channel_usb = channel_usb
|
self._channel_usb = channel_usb
|
||||||
|
|
||||||
|
if self._model == MODEL_PLUG_V3:
|
||||||
|
self._device_features = FEATURE_FLAGS_PLUG_V3
|
||||||
|
self._state_attrs.update({
|
||||||
|
ATTR_WIFI_LED: None,
|
||||||
|
ATTR_LOAD_POWER: None,
|
||||||
|
})
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs):
|
||||||
"""Turn a channel on."""
|
"""Turn a channel on."""
|
||||||
if self._channel_usb:
|
if self._channel_usb:
|
||||||
@ -463,6 +474,12 @@ class ChuangMiPlugV1Switch(XiaomiPlugGenericSwitch):
|
|||||||
ATTR_TEMPERATURE: state.temperature
|
ATTR_TEMPERATURE: state.temperature
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if state.wifi_led:
|
||||||
|
self._state_attrs[ATTR_WIFI_LED] = state.wifi_led
|
||||||
|
|
||||||
|
if state.load_power:
|
||||||
|
self._state_attrs[ATTR_LOAD_POWER] = state.load_power
|
||||||
|
|
||||||
except DeviceException as ex:
|
except DeviceException as ex:
|
||||||
self._available = False
|
self._available = False
|
||||||
_LOGGER.error("Got exception while fetching the state: %s", ex)
|
_LOGGER.error("Got exception while fetching the state: %s", ex)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user