FHEM & reconnecting client fixes
This commit is contained in:
parent
06f96cb2dc
commit
e6f5504181
|
@ -41,9 +41,7 @@ class FhemConnection(ReconnectingClient):
|
||||||
def register_device(self, id, d):
|
def register_device(self, id, d):
|
||||||
self._devices[id].append(d)
|
self._devices[id].append(d)
|
||||||
if self._writer:
|
if self._writer:
|
||||||
self._writer.writelines([
|
d.refresh()
|
||||||
"displayattr .*\n".encode(),
|
|
||||||
])
|
|
||||||
|
|
||||||
async def _update_all_devices(self, state):
|
async def _update_all_devices(self, state):
|
||||||
if state == 'connected':
|
if state == 'connected':
|
||||||
|
@ -51,6 +49,7 @@ class FhemConnection(ReconnectingClient):
|
||||||
self.write_line("inform on")
|
self.write_line("inform on")
|
||||||
for device_list in self._devices.values():
|
for device_list in self._devices.values():
|
||||||
for device in device_list:
|
for device in device_list:
|
||||||
|
device.refresh()
|
||||||
await device.async_update_ha_state()
|
await device.async_update_ha_state()
|
||||||
|
|
||||||
async def _process_line(self, line):
|
async def _process_line(self, line):
|
||||||
|
|
|
@ -64,6 +64,9 @@ class FhemBinarySensor(BinarySensorDevice):
|
||||||
def is_on(self):
|
def is_on(self):
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
pass
|
||||||
|
|
||||||
async def line_received(self, line):
|
async def line_received(self, line):
|
||||||
if self._type == 'motion' and line.startswith('motion'):
|
if self._type == 'motion' and line.startswith('motion'):
|
||||||
self._available = True
|
self._available = True
|
||||||
|
|
|
@ -58,6 +58,9 @@ class FhemCover(CoverDevice):
|
||||||
def current_cover_position(self):
|
def current_cover_position(self):
|
||||||
return self._position
|
return self._position
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self.connection.fhem_set(self._ids[0], 'statusRequest')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self):
|
def is_closed(self):
|
||||||
"""Return if the cover is closed."""
|
"""Return if the cover is closed."""
|
||||||
|
@ -88,8 +91,7 @@ class FhemCover(CoverDevice):
|
||||||
_, new_motor_state, new_position = line.split(':')
|
_, new_motor_state, new_position = line.split(':')
|
||||||
new_position = new_position.strip().lower()
|
new_position = new_position.strip().lower()
|
||||||
new_motor_state = new_motor_state.strip().lower()
|
new_motor_state = new_motor_state.strip().lower()
|
||||||
assert new_motor_state == 'stop' or new_motor_state == 'up' or new_motor_state == 'down', \
|
assert new_motor_state in ('up', 'down', 'stop', 'err'), 'Unknown motor state ' + new_motor_state
|
||||||
'Unknown motor state ' + new_motor_state
|
|
||||||
if new_motor_state == 'stop':
|
if new_motor_state == 'stop':
|
||||||
if new_position == 'on':
|
if new_position == 'on':
|
||||||
self._position = 100
|
self._position = 100
|
||||||
|
|
|
@ -72,6 +72,9 @@ class FhemLight(Light):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self.connection.fhem_set(self._ids[0], 'statusRequest')
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs):
|
||||||
brightness = kwargs.get(ATTR_BRIGHTNESS, None)
|
brightness = kwargs.get(ATTR_BRIGHTNESS, None)
|
||||||
transition_time = kwargs.get(ATTR_TRANSITION, 0.5)
|
transition_time = kwargs.get(ATTR_TRANSITION, 0.5)
|
||||||
|
@ -124,6 +127,7 @@ class FhemLight(Light):
|
||||||
pass
|
pass
|
||||||
await self.async_update_ha_state()
|
await self.async_update_ha_state()
|
||||||
elif line.startswith('ResndFail') or line.startswith('MISSING ACK'):
|
elif line.startswith('ResndFail') or line.startswith('MISSING ACK'):
|
||||||
|
_LOGGER.warning(f"FHEM light {self.name} became unavailable: '{line}'")
|
||||||
self._available = False
|
self._available = False
|
||||||
await self.async_update_ha_state()
|
await self.async_update_ha_state()
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -60,6 +60,9 @@ class FhemSensor(Entity):
|
||||||
def state(self):
|
def state(self):
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
pass
|
||||||
|
|
||||||
async def line_received(self, line):
|
async def line_received(self, line):
|
||||||
if self._type == 'brightness' and line.startswith('brightness'):
|
if self._type == 'brightness' and line.startswith('brightness'):
|
||||||
self._available = True
|
self._available = True
|
||||||
|
@ -69,7 +72,7 @@ class FhemSensor(Entity):
|
||||||
elif self._type == 'power' and line.startswith('power'):
|
elif self._type == 'power' and line.startswith('power'):
|
||||||
self._available = True
|
self._available = True
|
||||||
_, new_value = line.split(':')
|
_, new_value = line.split(':')
|
||||||
self._state = int(new_value)
|
self._state = float(new_value)
|
||||||
await self.async_update_ha_state()
|
await self.async_update_ha_state()
|
||||||
elif line.startswith('ResndFail') or line.startswith('MISSING ACK'):
|
elif line.startswith('ResndFail') or line.startswith('MISSING ACK'):
|
||||||
self._available = False
|
self._available = False
|
||||||
|
|
|
@ -53,24 +53,33 @@ class FhemSwitch(SwitchDevice):
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs):
|
||||||
"""Turn the device on."""
|
"""Turn the device on."""
|
||||||
|
self._on = True
|
||||||
self.connection.fhem_set(self._ids[0], 'on')
|
self.connection.fhem_set(self._ids[0], 'on')
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs):
|
async def async_turn_off(self, **kwargs):
|
||||||
"""Turn the device off."""
|
"""Turn the device off."""
|
||||||
|
self._on = False
|
||||||
self.connection.fhem_set(self._ids[0], 'off')
|
self.connection.fhem_set(self._ids[0], 'off')
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self.connection.fhem_set(self._ids[0], 'statusRequest')
|
||||||
|
|
||||||
async def line_received(self, line):
|
async def line_received(self, line):
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if line.startswith('level:'):
|
if line.startswith('level:'):
|
||||||
|
self._available = True
|
||||||
_, new_state = line.split(':')
|
_, new_state = line.split(':')
|
||||||
new_state = new_state.strip().lower()
|
new_state = new_state.strip().lower()
|
||||||
if new_state in ('on', '100'):
|
if new_state in ('on', '100'):
|
||||||
self._on = True
|
self._on = True
|
||||||
if new_state in ('off', '0'):
|
elif new_state in ('off', '0'):
|
||||||
self._on = False
|
self._on = False
|
||||||
await self.async_update_ha_state()
|
await self.async_update_ha_state()
|
||||||
elif line in ('on', 'off'):
|
elif line in ('on', 'off'):
|
||||||
|
self._available = True
|
||||||
|
prev = self._on
|
||||||
self._on = (line == 'on')
|
self._on = (line == 'on')
|
||||||
|
await self.async_update_ha_state()
|
||||||
elif line.startswith('ResndFail') or line.startswith('MISSING ACK'):
|
elif line.startswith('ResndFail') or line.startswith('MISSING ACK'):
|
||||||
self._available = False
|
self._available = False
|
||||||
await self.async_update_ha_state()
|
await self.async_update_ha_state()
|
||||||
|
|
|
@ -41,14 +41,14 @@ class ReconnectingClient:
|
||||||
self._writer.write(line.encode())
|
self._writer.write(line.encode())
|
||||||
else:
|
else:
|
||||||
_LOGGER.warning(f"Skipping line '{line}'' because _writer is None")
|
_LOGGER.warning(f"Skipping line '{line}'' because _writer is None")
|
||||||
except RuntimeError:
|
except RuntimeError as e:
|
||||||
|
_LOGGER.error("Writing failed " + str(e))
|
||||||
self._connection_task.cancel()
|
self._connection_task.cancel()
|
||||||
self._connection_task = self.hass.loop.create_task(self._connection())
|
self._connection_task = self.hass.loop.create_task(self._connection())
|
||||||
|
|
||||||
async def _connection(self):
|
async def _connection(self):
|
||||||
try:
|
try:
|
||||||
reader, writer = await asyncio.open_connection(self._host, self._port)
|
reader, writer = await asyncio.open_connection(self._host, self._port)
|
||||||
_LOGGER.info("Connected to {} {}:{}".format(self._connection_name, self._host, self._port))
|
|
||||||
self._connection_last_state = 'CONNECTED'
|
self._connection_last_state = 'CONNECTED'
|
||||||
|
|
||||||
self._writer = writer
|
self._writer = writer
|
||||||
|
@ -61,17 +61,16 @@ class ReconnectingClient:
|
||||||
if not line:
|
if not line:
|
||||||
raise OSError("Disconnect")
|
raise OSError("Disconnect")
|
||||||
line = line.decode()
|
line = line.decode()
|
||||||
_LOGGER.debug("{} received line: {}".format(self._connection_name, line))
|
_LOGGER.warning("{} received line: {}".format(self._connection_name, line))
|
||||||
await self._receive_line_callback(line)
|
await self._receive_line_callback(line)
|
||||||
except OSError:
|
except OSError as e:
|
||||||
if self._connection_last_state != 'FAILED':
|
if self._connection_last_state != 'FAILED':
|
||||||
notification_text = "{} connection to {}:{} failed".format(self._connection_name,self._host, self._port)
|
notification_text = "{} connection to {}:{} failed".format(self._connection_name,self._host, self._port)
|
||||||
self.hass.components.persistent_notification.async_create(notification_text, title="No connection")
|
self.hass.components.persistent_notification.async_create(notification_text, title="No connection")
|
||||||
_LOGGER.error("Connection to {} failed {}:{}".format(self._connection_name, self._host, self._port))
|
_LOGGER.error("Connection to {} failed {}:{}".format(self._connection_name, self._host, self._port))
|
||||||
await self._connection_status_changed_callback('disconnected')
|
await self._connection_status_changed_callback('disconnected')
|
||||||
self._connection_last_state = 'FAILED'
|
self._connection_last_state = 'FAILED'
|
||||||
|
|
||||||
self.connected = False
|
self.connected = False
|
||||||
await asyncio.sleep(self.reconnect_time)
|
await asyncio.sleep(self.reconnect_time)
|
||||||
self.reconnect_time = min(2 * self.reconnect_time, self.reconnect_time_max)
|
self.reconnect_time = min(2 * self.reconnect_time, self.reconnect_time_max)
|
||||||
self.hass.loop.create_task(self._connection())
|
self._connection_task = self.hass.loop.create_task(self._connection())
|
||||||
|
|
|
@ -239,6 +239,8 @@ class LogitechMediaServer(ReconnectingClient):
|
||||||
|
|
||||||
if player_id in self._players:
|
if player_id in self._players:
|
||||||
await self._players[player_id].on_receive(cmd, data)
|
await self._players[player_id].on_receive(cmd, data)
|
||||||
|
elif line.startswith('listen'):
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
_LOGGER.warning("LMS Ignoring line " + line)
|
_LOGGER.warning("LMS Ignoring line " + line)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue