Make mysensors component async (#13641)

* Make mysensors component async

* Use async dispatcher and discovery.
* Run I/O in executor.
* Make mysensors actuator methods async.
* Upgrade pymysensors to 0.13.0.
* Use async serial gateway.
* Use async TCP gateway.
* Use async mqtt gateway.

* Start gateway before hass start event

* Make sure gateway is started after discovery of persistent devices
  and after corresponding platforms have been loaded.
* Don't wait to start gateway until after hass start.

* Bump pymysensors to 0.14.0
This commit is contained in:
Martin Hjelmare 2018-05-11 09:39:18 +02:00 committed by GitHub
parent ef8fc1f201
commit be3b227a87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 80 deletions

View file

@ -115,7 +115,7 @@ class MySensorsHVAC(mysensors.MySensorsEntity, ClimateDevice):
"""List of available fan modes.""" """List of available fan modes."""
return ['Auto', 'Min', 'Normal', 'Max'] return ['Auto', 'Min', 'Normal', 'Max']
def set_temperature(self, **kwargs): async def async_set_temperature(self, **kwargs):
"""Set new target temperature.""" """Set new target temperature."""
set_req = self.gateway.const.SetReq set_req = self.gateway.const.SetReq
temp = kwargs.get(ATTR_TEMPERATURE) temp = kwargs.get(ATTR_TEMPERATURE)
@ -143,9 +143,9 @@ class MySensorsHVAC(mysensors.MySensorsEntity, ClimateDevice):
if self.gateway.optimistic: if self.gateway.optimistic:
# Optimistically assume that device has changed state # Optimistically assume that device has changed state
self._values[value_type] = value self._values[value_type] = value
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
def set_fan_mode(self, fan_mode): async def async_set_fan_mode(self, fan_mode):
"""Set new target temperature.""" """Set new target temperature."""
set_req = self.gateway.const.SetReq set_req = self.gateway.const.SetReq
self.gateway.set_child_value( self.gateway.set_child_value(
@ -153,9 +153,9 @@ class MySensorsHVAC(mysensors.MySensorsEntity, ClimateDevice):
if self.gateway.optimistic: if self.gateway.optimistic:
# Optimistically assume that device has changed state # Optimistically assume that device has changed state
self._values[set_req.V_HVAC_SPEED] = fan_mode self._values[set_req.V_HVAC_SPEED] = fan_mode
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
def set_operation_mode(self, operation_mode): async def async_set_operation_mode(self, operation_mode):
"""Set new target temperature.""" """Set new target temperature."""
self.gateway.set_child_value( self.gateway.set_child_value(
self.node_id, self.child_id, self.value_type, self.node_id, self.child_id, self.value_type,
@ -163,7 +163,7 @@ class MySensorsHVAC(mysensors.MySensorsEntity, ClimateDevice):
if self.gateway.optimistic: if self.gateway.optimistic:
# Optimistically assume that device has changed state # Optimistically assume that device has changed state
self._values[self.value_type] = operation_mode self._values[self.value_type] = operation_mode
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
async def async_update(self): async def async_update(self):
"""Update the controller with the latest value from a sensor.""" """Update the controller with the latest value from a sensor."""

View file

@ -42,7 +42,7 @@ class MySensorsCover(mysensors.MySensorsEntity, CoverDevice):
set_req = self.gateway.const.SetReq set_req = self.gateway.const.SetReq
return self._values.get(set_req.V_DIMMER) return self._values.get(set_req.V_DIMMER)
def open_cover(self, **kwargs): async def async_open_cover(self, **kwargs):
"""Move the cover up.""" """Move the cover up."""
set_req = self.gateway.const.SetReq set_req = self.gateway.const.SetReq
self.gateway.set_child_value( self.gateway.set_child_value(
@ -53,9 +53,9 @@ class MySensorsCover(mysensors.MySensorsEntity, CoverDevice):
self._values[set_req.V_DIMMER] = 100 self._values[set_req.V_DIMMER] = 100
else: else:
self._values[set_req.V_LIGHT] = STATE_ON self._values[set_req.V_LIGHT] = STATE_ON
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
def close_cover(self, **kwargs): async def async_close_cover(self, **kwargs):
"""Move the cover down.""" """Move the cover down."""
set_req = self.gateway.const.SetReq set_req = self.gateway.const.SetReq
self.gateway.set_child_value( self.gateway.set_child_value(
@ -66,9 +66,9 @@ class MySensorsCover(mysensors.MySensorsEntity, CoverDevice):
self._values[set_req.V_DIMMER] = 0 self._values[set_req.V_DIMMER] = 0
else: else:
self._values[set_req.V_LIGHT] = STATE_OFF self._values[set_req.V_LIGHT] = STATE_OFF
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
def set_cover_position(self, **kwargs): async def async_set_cover_position(self, **kwargs):
"""Move the cover to a specific position.""" """Move the cover to a specific position."""
position = kwargs.get(ATTR_POSITION) position = kwargs.get(ATTR_POSITION)
set_req = self.gateway.const.SetReq set_req = self.gateway.const.SetReq
@ -77,9 +77,9 @@ class MySensorsCover(mysensors.MySensorsEntity, CoverDevice):
if self.gateway.optimistic: if self.gateway.optimistic:
# Optimistically assume that cover has changed state. # Optimistically assume that cover has changed state.
self._values[set_req.V_DIMMER] = position self._values[set_req.V_DIMMER] = position
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
def stop_cover(self, **kwargs): async def async_stop_cover(self, **kwargs):
"""Stop the device.""" """Stop the device."""
set_req = self.gateway.const.SetReq set_req = self.gateway.const.SetReq
self.gateway.set_child_value( self.gateway.set_child_value(

View file

@ -130,7 +130,7 @@ class MySensorsLight(mysensors.MySensorsEntity, Light):
self._white = white self._white = white
self._values[self.value_type] = hex_color self._values[self.value_type] = hex_color
def turn_off(self, **kwargs): async def async_turn_off(self, **kwargs):
"""Turn the device off.""" """Turn the device off."""
value_type = self.gateway.const.SetReq.V_LIGHT value_type = self.gateway.const.SetReq.V_LIGHT
self.gateway.set_child_value( self.gateway.set_child_value(
@ -139,7 +139,7 @@ class MySensorsLight(mysensors.MySensorsEntity, Light):
# optimistically assume that light has changed state # optimistically assume that light has changed state
self._state = False self._state = False
self._values[value_type] = STATE_OFF self._values[value_type] = STATE_OFF
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
def _async_update_light(self): def _async_update_light(self):
"""Update the controller with values from light child.""" """Update the controller with values from light child."""
@ -171,12 +171,12 @@ class MySensorsLightDimmer(MySensorsLight):
"""Flag supported features.""" """Flag supported features."""
return SUPPORT_BRIGHTNESS return SUPPORT_BRIGHTNESS
def turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
"""Turn the device on.""" """Turn the device on."""
self._turn_on_light() self._turn_on_light()
self._turn_on_dimmer(**kwargs) self._turn_on_dimmer(**kwargs)
if self.gateway.optimistic: if self.gateway.optimistic:
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
async def async_update(self): async def async_update(self):
"""Update the controller with the latest value from a sensor.""" """Update the controller with the latest value from a sensor."""
@ -196,13 +196,13 @@ class MySensorsLightRGB(MySensorsLight):
return SUPPORT_BRIGHTNESS | SUPPORT_COLOR return SUPPORT_BRIGHTNESS | SUPPORT_COLOR
return SUPPORT_COLOR return SUPPORT_COLOR
def turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
"""Turn the device on.""" """Turn the device on."""
self._turn_on_light() self._turn_on_light()
self._turn_on_dimmer(**kwargs) self._turn_on_dimmer(**kwargs)
self._turn_on_rgb_and_w('%02x%02x%02x', **kwargs) self._turn_on_rgb_and_w('%02x%02x%02x', **kwargs)
if self.gateway.optimistic: if self.gateway.optimistic:
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
async def async_update(self): async def async_update(self):
"""Update the controller with the latest value from a sensor.""" """Update the controller with the latest value from a sensor."""
@ -225,10 +225,10 @@ class MySensorsLightRGBW(MySensorsLightRGB):
return SUPPORT_BRIGHTNESS | SUPPORT_MYSENSORS_RGBW return SUPPORT_BRIGHTNESS | SUPPORT_MYSENSORS_RGBW
return SUPPORT_MYSENSORS_RGBW return SUPPORT_MYSENSORS_RGBW
def turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
"""Turn the device on.""" """Turn the device on."""
self._turn_on_light() self._turn_on_light()
self._turn_on_dimmer(**kwargs) self._turn_on_dimmer(**kwargs)
self._turn_on_rgb_and_w('%02x%02x%02x%02x', **kwargs) self._turn_on_rgb_and_w('%02x%02x%02x%02x', **kwargs)
if self.gateway.optimistic: if self.gateway.optimistic:
self.schedule_update_ha_state() self.async_schedule_update_ha_state()

View file

@ -4,6 +4,7 @@ Connect to a MySensors gateway via pymysensors API.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/mysensors/ https://home-assistant.io/components/mysensors/
""" """
import asyncio
from collections import defaultdict from collections import defaultdict
import logging import logging
import os import os
@ -16,17 +17,17 @@ import voluptuous as vol
from homeassistant.components.mqtt import ( from homeassistant.components.mqtt import (
valid_publish_topic, valid_subscribe_topic) valid_publish_topic, valid_subscribe_topic)
from homeassistant.const import ( from homeassistant.const import (
ATTR_BATTERY_LEVEL, CONF_NAME, CONF_OPTIMISTIC, EVENT_HOMEASSISTANT_START, ATTR_BATTERY_LEVEL, CONF_NAME, CONF_OPTIMISTIC,
EVENT_HOMEASSISTANT_STOP, STATE_OFF, STATE_ON) EVENT_HOMEASSISTANT_STOP, STATE_OFF, STATE_ON)
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import discovery from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import ( from homeassistant.helpers.dispatcher import (
async_dispatcher_connect, dispatcher_send) async_dispatcher_connect, async_dispatcher_send)
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.setup import setup_component from homeassistant.setup import async_setup_component
REQUIREMENTS = ['pymysensors==0.11.1'] REQUIREMENTS = ['pymysensors==0.14.0']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -280,67 +281,62 @@ MYSENSORS_CONST_SCHEMA = {
} }
def setup(hass, config): async def async_setup(hass, config):
"""Set up the MySensors component.""" """Set up the MySensors component."""
import mysensors.mysensors as mysensors import mysensors.mysensors as mysensors
version = config[DOMAIN].get(CONF_VERSION) version = config[DOMAIN].get(CONF_VERSION)
persistence = config[DOMAIN].get(CONF_PERSISTENCE) persistence = config[DOMAIN].get(CONF_PERSISTENCE)
def setup_gateway(device, persistence_file, baud_rate, tcp_port, in_prefix, async def setup_gateway(
out_prefix): device, persistence_file, baud_rate, tcp_port, in_prefix,
out_prefix):
"""Return gateway after setup of the gateway.""" """Return gateway after setup of the gateway."""
if device == MQTT_COMPONENT: if device == MQTT_COMPONENT:
if not setup_component(hass, MQTT_COMPONENT, config): if not await async_setup_component(hass, MQTT_COMPONENT, config):
return return None
mqtt = hass.components.mqtt mqtt = hass.components.mqtt
retain = config[DOMAIN].get(CONF_RETAIN) retain = config[DOMAIN].get(CONF_RETAIN)
def pub_callback(topic, payload, qos, retain): def pub_callback(topic, payload, qos, retain):
"""Call MQTT publish function.""" """Call MQTT publish function."""
mqtt.publish(topic, payload, qos, retain) mqtt.async_publish(topic, payload, qos, retain)
def sub_callback(topic, sub_cb, qos): def sub_callback(topic, sub_cb, qos):
"""Call MQTT subscribe function.""" """Call MQTT subscribe function."""
mqtt.subscribe(topic, sub_cb, qos) @callback
gateway = mysensors.MQTTGateway( def internal_callback(*args):
pub_callback, sub_callback, """Call callback."""
sub_cb(*args)
hass.async_add_job(
mqtt.async_subscribe(topic, internal_callback, qos))
gateway = mysensors.AsyncMQTTGateway(
pub_callback, sub_callback, in_prefix=in_prefix,
out_prefix=out_prefix, retain=retain, loop=hass.loop,
event_callback=None, persistence=persistence, event_callback=None, persistence=persistence,
persistence_file=persistence_file, persistence_file=persistence_file,
protocol_version=version, in_prefix=in_prefix, protocol_version=version)
out_prefix=out_prefix, retain=retain)
else: else:
try: try:
is_serial_port(device) await hass.async_add_job(is_serial_port, device)
gateway = mysensors.SerialGateway( gateway = mysensors.AsyncSerialGateway(
device, event_callback=None, persistence=persistence, device, baud=baud_rate, loop=hass.loop,
event_callback=None, persistence=persistence,
persistence_file=persistence_file, persistence_file=persistence_file,
protocol_version=version, baud=baud_rate) protocol_version=version)
except vol.Invalid: except vol.Invalid:
try: gateway = mysensors.AsyncTCPGateway(
socket.getaddrinfo(device, None) device, port=tcp_port, loop=hass.loop, event_callback=None,
# valid ip address persistence=persistence, persistence_file=persistence_file,
gateway = mysensors.TCPGateway( protocol_version=version)
device, event_callback=None, persistence=persistence,
persistence_file=persistence_file,
protocol_version=version, port=tcp_port)
except OSError:
# invalid ip address
return
gateway.metric = hass.config.units.is_metric gateway.metric = hass.config.units.is_metric
gateway.optimistic = config[DOMAIN].get(CONF_OPTIMISTIC) gateway.optimistic = config[DOMAIN].get(CONF_OPTIMISTIC)
gateway.device = device gateway.device = device
gateway.event_callback = gw_callback_factory(hass) gateway.event_callback = gw_callback_factory(hass)
if persistence:
def gw_start(event): await gateway.start_persistence()
"""Trigger to start of the gateway and any persistence."""
if persistence:
discover_persistent_devices(hass, gateway)
gateway.start()
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP,
lambda event: gateway.stop())
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, gw_start)
return gateway return gateway
@ -357,7 +353,7 @@ def setup(hass, config):
tcp_port = gway.get(CONF_TCP_PORT) tcp_port = gway.get(CONF_TCP_PORT)
in_prefix = gway.get(CONF_TOPIC_IN_PREFIX, '') in_prefix = gway.get(CONF_TOPIC_IN_PREFIX, '')
out_prefix = gway.get(CONF_TOPIC_OUT_PREFIX, '') out_prefix = gway.get(CONF_TOPIC_OUT_PREFIX, '')
ready_gateway = setup_gateway( ready_gateway = await setup_gateway(
device, persistence_file, baud_rate, tcp_port, in_prefix, device, persistence_file, baud_rate, tcp_port, in_prefix,
out_prefix) out_prefix)
if ready_gateway is not None: if ready_gateway is not None:
@ -371,9 +367,36 @@ def setup(hass, config):
hass.data[MYSENSORS_GATEWAYS] = gateways hass.data[MYSENSORS_GATEWAYS] = gateways
hass.async_add_job(finish_setup(hass, gateways))
return True return True
async def finish_setup(hass, gateways):
"""Load any persistent devices and platforms and start gateway."""
discover_tasks = []
start_tasks = []
for gateway in gateways.values():
discover_tasks.append(discover_persistent_devices(hass, gateway))
start_tasks.append(gw_start(hass, gateway))
if discover_tasks:
# Make sure all devices and platforms are loaded before gateway start.
await asyncio.wait(discover_tasks, loop=hass.loop)
if start_tasks:
await asyncio.wait(start_tasks, loop=hass.loop)
async def gw_start(hass, gateway):
"""Start the gateway."""
@callback
def gw_stop(event):
"""Trigger to stop the gateway."""
hass.async_add_job(gateway.stop())
await gateway.start()
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, gw_stop)
def validate_child(gateway, node_id, child): def validate_child(gateway, node_id, child):
"""Validate that a child has the correct values according to schema. """Validate that a child has the correct values according to schema.
@ -431,14 +454,18 @@ def validate_child(gateway, node_id, child):
return validated return validated
@callback
def discover_mysensors_platform(hass, platform, new_devices): def discover_mysensors_platform(hass, platform, new_devices):
"""Discover a MySensors platform.""" """Discover a MySensors platform."""
discovery.load_platform( task = hass.async_add_job(discovery.async_load_platform(
hass, platform, DOMAIN, {ATTR_DEVICES: new_devices, CONF_NAME: DOMAIN}) hass, platform, DOMAIN,
{ATTR_DEVICES: new_devices, CONF_NAME: DOMAIN}))
return task
def discover_persistent_devices(hass, gateway): async def discover_persistent_devices(hass, gateway):
"""Discover platforms for devices loaded via persistence file.""" """Discover platforms for devices loaded via persistence file."""
tasks = []
new_devices = defaultdict(list) new_devices = defaultdict(list)
for node_id in gateway.sensors: for node_id in gateway.sensors:
node = gateway.sensors[node_id] node = gateway.sensors[node_id]
@ -447,7 +474,9 @@ def discover_persistent_devices(hass, gateway):
for platform, dev_ids in validated.items(): for platform, dev_ids in validated.items():
new_devices[platform].extend(dev_ids) new_devices[platform].extend(dev_ids)
for platform, dev_ids in new_devices.items(): for platform, dev_ids in new_devices.items():
discover_mysensors_platform(hass, platform, dev_ids) tasks.append(discover_mysensors_platform(hass, platform, dev_ids))
if tasks:
await asyncio.wait(tasks, loop=hass.loop)
def get_mysensors_devices(hass, domain): def get_mysensors_devices(hass, domain):
@ -459,6 +488,7 @@ def get_mysensors_devices(hass, domain):
def gw_callback_factory(hass): def gw_callback_factory(hass):
"""Return a new callback for the gateway.""" """Return a new callback for the gateway."""
@callback
def mysensors_callback(msg): def mysensors_callback(msg):
"""Handle messages from a MySensors gateway.""" """Handle messages from a MySensors gateway."""
start = timer() start = timer()
@ -489,7 +519,7 @@ def gw_callback_factory(hass):
# Only one signal per device is needed. # Only one signal per device is needed.
# A device can have multiple platforms, ie multiple schemas. # A device can have multiple platforms, ie multiple schemas.
# FOR LATER: Add timer to not signal if another update comes in. # FOR LATER: Add timer to not signal if another update comes in.
dispatcher_send(hass, signal) async_dispatcher_send(hass, signal)
end = timer() end = timer()
if end - start > 0.1: if end - start > 0.1:
_LOGGER.debug( _LOGGER.debug(

View file

@ -42,7 +42,7 @@ class MySensorsNotificationService(BaseNotificationService):
"""Initialize the service.""" """Initialize the service."""
self.devices = mysensors.get_mysensors_devices(hass, DOMAIN) self.devices = mysensors.get_mysensors_devices(hass, DOMAIN)
def send_message(self, message="", **kwargs): async def async_send_message(self, message="", **kwargs):
"""Send a message to a user.""" """Send a message to a user."""
target_devices = kwargs.get(ATTR_TARGET) target_devices = kwargs.get(ATTR_TARGET)
devices = [device for device in self.devices.values() devices = [device for device in self.devices.values()

View file

@ -42,7 +42,7 @@ async def async_setup_platform(
hass, DOMAIN, discovery_info, device_class_map, hass, DOMAIN, discovery_info, device_class_map,
async_add_devices=async_add_devices) async_add_devices=async_add_devices)
def send_ir_code_service(service): async def async_send_ir_code_service(service):
"""Set IR code as device state attribute.""" """Set IR code as device state attribute."""
entity_ids = service.data.get(ATTR_ENTITY_ID) entity_ids = service.data.get(ATTR_ENTITY_ID)
ir_code = service.data.get(ATTR_IR_CODE) ir_code = service.data.get(ATTR_IR_CODE)
@ -58,10 +58,10 @@ async def async_setup_platform(
kwargs = {ATTR_IR_CODE: ir_code} kwargs = {ATTR_IR_CODE: ir_code}
for device in _devices: for device in _devices:
device.turn_on(**kwargs) await device.async_turn_on(**kwargs)
hass.services.async_register( hass.services.async_register(
DOMAIN, SERVICE_SEND_IR_CODE, send_ir_code_service, DOMAIN, SERVICE_SEND_IR_CODE, async_send_ir_code_service,
schema=SEND_IR_CODE_SERVICE_SCHEMA) schema=SEND_IR_CODE_SERVICE_SCHEMA)
@ -84,23 +84,23 @@ class MySensorsSwitch(mysensors.MySensorsEntity, SwitchDevice):
"""Return True if switch is on.""" """Return True if switch is on."""
return self._values.get(self.value_type) == STATE_ON return self._values.get(self.value_type) == STATE_ON
def turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
"""Turn the switch on.""" """Turn the switch on."""
self.gateway.set_child_value( self.gateway.set_child_value(
self.node_id, self.child_id, self.value_type, 1) self.node_id, self.child_id, self.value_type, 1)
if self.gateway.optimistic: if self.gateway.optimistic:
# optimistically assume that switch has changed state # optimistically assume that switch has changed state
self._values[self.value_type] = STATE_ON self._values[self.value_type] = STATE_ON
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
def turn_off(self, **kwargs): async def async_turn_off(self, **kwargs):
"""Turn the switch off.""" """Turn the switch off."""
self.gateway.set_child_value( self.gateway.set_child_value(
self.node_id, self.child_id, self.value_type, 0) self.node_id, self.child_id, self.value_type, 0)
if self.gateway.optimistic: if self.gateway.optimistic:
# optimistically assume that switch has changed state # optimistically assume that switch has changed state
self._values[self.value_type] = STATE_OFF self._values[self.value_type] = STATE_OFF
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
class MySensorsIRSwitch(MySensorsSwitch): class MySensorsIRSwitch(MySensorsSwitch):
@ -117,7 +117,7 @@ class MySensorsIRSwitch(MySensorsSwitch):
set_req = self.gateway.const.SetReq set_req = self.gateway.const.SetReq
return self._values.get(set_req.V_LIGHT) == STATE_ON return self._values.get(set_req.V_LIGHT) == STATE_ON
def turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
"""Turn the IR switch on.""" """Turn the IR switch on."""
set_req = self.gateway.const.SetReq set_req = self.gateway.const.SetReq
if ATTR_IR_CODE in kwargs: if ATTR_IR_CODE in kwargs:
@ -130,11 +130,11 @@ class MySensorsIRSwitch(MySensorsSwitch):
# optimistically assume that switch has changed state # optimistically assume that switch has changed state
self._values[self.value_type] = self._ir_code self._values[self.value_type] = self._ir_code
self._values[set_req.V_LIGHT] = STATE_ON self._values[set_req.V_LIGHT] = STATE_ON
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
# turn off switch after switch was turned on # turn off switch after switch was turned on
self.turn_off() await self.async_turn_off()
def turn_off(self, **kwargs): async def async_turn_off(self, **kwargs):
"""Turn the IR switch off.""" """Turn the IR switch off."""
set_req = self.gateway.const.SetReq set_req = self.gateway.const.SetReq
self.gateway.set_child_value( self.gateway.set_child_value(
@ -142,7 +142,7 @@ class MySensorsIRSwitch(MySensorsSwitch):
if self.gateway.optimistic: if self.gateway.optimistic:
# optimistically assume that switch has changed state # optimistically assume that switch has changed state
self._values[set_req.V_LIGHT] = STATE_OFF self._values[set_req.V_LIGHT] = STATE_OFF
self.schedule_update_ha_state() self.async_schedule_update_ha_state()
async def async_update(self): async def async_update(self):
"""Update the controller with the latest value from a sensor.""" """Update the controller with the latest value from a sensor."""

View file

@ -869,7 +869,7 @@ pymusiccast==0.1.6
pymyq==0.0.8 pymyq==0.0.8
# homeassistant.components.mysensors # homeassistant.components.mysensors
pymysensors==0.11.1 pymysensors==0.14.0
# homeassistant.components.lock.nello # homeassistant.components.lock.nello
pynello==1.5.1 pynello==1.5.1