Hass-Custom-Alarm
Hass-Custom-Alarm copied to clipboard
MQTT ARM_AWAY does not work
Hi, I am on HA v0.81.0 and bwalarm v1.0.4.
When sending an MQTT message to arm the alarm, I am getting this error in the logs:
2018-10-29 10:45:14 ERROR (MainThread) [homeassistant.core] Error doing job: Exception in callback <bound method MQTT._mqtt_handle_message of <homeassistant.components.mqtt.MQTT object at 0x7fd5e41695f8>>
Traceback (most recent call last):
File "uvloop/cbhandles.pyx", line 66, in uvloop.loop.Handle._run
File "/usr/src/app/homeassistant/components/mqtt/__init__.py", line 775, in _mqtt_handle_message
subscription.callback, msg.topic, payload, msg.qos)
File "/usr/src/app/homeassistant/core.py", line 327, in async_run_job
target(*args)
File "/config/custom_components/alarm_control_panel/bwalarm.py", line 668, in message_received
self.alarm_arm_away('')
File "/config/custom_components/alarm_control_panel/bwalarm.py", line 485, in alarm_arm_away
self.process_event(Events.ArmAway)
File "/config/custom_components/alarm_control_panel/bwalarm.py", line 577, in process_event
self._hass.services.call("switch", "turn_on", {self._warning})
File "/usr/src/app/homeassistant/core.py", line 1070, in call
self._hass.loop
File "/usr/src/app/homeassistant/util/async_.py", line 138, in run_coroutine_threadsafe
raise RuntimeError('Cannot be called from within the event loop')
RuntimeError: Cannot be called from within the event loop
The MQTT message is send from within a script:
alarm_arm_away:
alias: Alarm Arm Away
sequence:
- service: mqtt.publish
data:
topic: 'home/alarm/set'
payload: 'ARM_AWAY'
alarm_disarm:
alias: Disarm Alarm
sequence:
- service: mqtt.publish
data:
topic: 'home/alarm/set'
payload: 'DISARM'
My configuration is based on the default:
##[MQTT RELATED]
#[OPTIONAL] - False by default. Settings this to True will enable MQTT Mode. Uncomment options below to use See the README for guidance.
mqtt: True
#[OPTIONAL] False by default. if true allows MQTT commands to disarm the alarm without a valid code.
override_code: True
#[OPTIONAL] The MQTT topic HA will publish state updates to.
#state_topic: 'home/alarm'
#[OPTIONAL] The MQTT topic HA will subscribe to, to receive commands from a remote device to change the alarm state.
command_topic: 'home/alarm/set'
#[OPTIONAL] The maximum QoS level for subscribing and publishing to MQTT messages. Default is 0.
#qos: 0
#[OPTIONAL] The payload to disarm this Alarm Panel. Default is “DISARM”.
payload_disarm: "DISARM"
#[OPTIONAL] The payload to set armed-home mode on this Alarm Panel. Default is “ARM_HOME”.
payload_arm_home: "ARM_HOME"
#[OPTIONAL] The payload to set armed-away mode on this Alarm Panel. Default is “ARM_AWAY”.
payload_arm_away: "ARM_AWAY"
#[OPTIONAL] The payload to set armed-night mode on this Alarm Panel. Default is “ARM_NIGHT”.
payload_arm_night: "ARM_NIGHT"
Can confirm the alarm_disarm
script works as expected. Calling the alarm_arm_away
script causes this error. Tried isolating the problem as well by calling the MQTT publish service directly using these parameters:
{
"topic":"home/alarm/set",
"payload":"ARM_AWAY"
}
Same error:
2018-10-29T11:04:11.236237936Z 2018-10-29 11:04:11 ERROR (MainThread) [homeassistant.core] Error doing job: Exception in callback <bound method MQTT._mqtt_handle_message of <homeassistant.components.mqtt.MQTT object at 0x7faf183d4f28>>
2018-10-29T11:04:11.236292353Z Traceback (most recent call last):
2018-10-29T11:04:11.236304191Z File "uvloop/cbhandles.pyx", line 66, in uvloop.loop.Handle._run
2018-10-29T11:04:11.236312654Z File "/usr/src/app/homeassistant/components/mqtt/__init__.py", line 775, in _mqtt_handle_message
2018-10-29T11:04:11.236320738Z subscription.callback, msg.topic, payload, msg.qos)
2018-10-29T11:04:11.236328408Z File "/usr/src/app/homeassistant/core.py", line 327, in async_run_job
2018-10-29T11:04:11.236336480Z target(*args)
2018-10-29T11:04:11.236343735Z File "/config/custom_components/alarm_control_panel/bwalarm.py", line 668, in message_received
2018-10-29T11:04:11.236351601Z self.alarm_arm_away('')
2018-10-29T11:04:11.236359243Z File "/config/custom_components/alarm_control_panel/bwalarm.py", line 485, in alarm_arm_away
2018-10-29T11:04:11.236368628Z self.process_event(Events.ArmAway)
2018-10-29T11:04:11.236376610Z File "/config/custom_components/alarm_control_panel/bwalarm.py", line 577, in process_event
2018-10-29T11:04:11.236384942Z self._hass.services.call("switch", "turn_on", {self._warning})
2018-10-29T11:04:11.236391272Z File "/usr/src/app/homeassistant/core.py", line 1070, in call
2018-10-29T11:04:11.236395969Z self._hass.loop
2018-10-29T11:04:11.236400297Z File "/usr/src/app/homeassistant/util/async_.py", line 138, in run_coroutine_threadsafe
2018-10-29T11:04:11.236404850Z raise RuntimeError('Cannot be called from within the event loop')
2018-10-29T11:04:11.236409428Z RuntimeError: Cannot be called from within the event loop
2018-10-29T11:04:11.237437077Z /usr/src/app/homeassistant/util/async_.py:29: RuntimeWarning: coroutine 'ServiceRegistry.async_call' was never awaited
2018-10-29T11:04:11.237453721Z return loop.run_until_complete(main)
This is a critical error because HA is unable to recognise the alarm panel afterwards. (the following log is generated when clicking on the ARM Away button in the alarm panel frontend.
2018-10-29T11:05:00.034213092Z 2018-10-29 11:05:00 WARNING (MainThread) [homeassistant.core] Unable to find service alarm_control_panel/
Same issue here
The issue would seem to be the syntax changes for async functions in .82. I was able to avoid the bug by updating as follows:
--- tmp\bwalarm.py 2018-11-12 21:47:39.000000000 -0800
+++ bwalarm.py 2018-11-13 00:12:27.000000000 -0800
@@ -214,14 +214,13 @@
vol.Optional(CONF_OVERRIDE_CODE, default=False): cv.boolean,
#-----------------------------END------------------------------------
}, _state_validator))
_LOGGER = logging.getLogger(__name__)
[email protected]
-def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
+async def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
#Setup MQTT if enabled
mqtt = None
if (config[CONF_MQTT]):
import homeassistant.components.mqtt as mqtt
alarm = BWAlarm(hass, config, mqtt)
hass.bus.async_listen(EVENT_STATE_CHANGED, alarm.state_change_listener)
@@ -638,14 +637,13 @@
if now() > self._passcode_timeoutat:
self._panel_locked = False
self._passcode_timeoutat = None
self._passcodeAttemptNo = 0
self.schedule_update_ha_state()
- @asyncio.coroutine
- def async_added_to_hass(self):
+ async def async_added_to_hass(self):
"""Subscribe mqtt events.
This method must be run in the event loop and returns a coroutine.
"""
if (self._mqtt):
async_track_state_change(
self.hass, self.entity_id, self._async_state_changed_listener
@@ -672,13 +670,12 @@
_LOGGER.warning("[ALARM/MQTT] Received unexpected payload: %s", payload)
return
if (self._mqtt):
return self.mqtt.async_subscribe(
self.hass, self._command_topic, message_received, self._qos)
- @asyncio.coroutine
- def _async_state_changed_listener(self, entity_id, old_state, new_state):
+ async def _async_state_changed_listener(self, entity_id, old_state, new_state):
"""Publish state change to MQTT."""
if (self._mqtt):
self.mqtt.async_publish(self.hass, self._state_topic, new_state.state,
self._qos, True)
_LOGGER.debug("[ALARM/MQTT] State changed")
@adipose Are you able to PR this fix? Happy to test on my system as well
@danobot I could do that, but I have to be honest: my alarm is not updating when the mqtt messages arrive. I believe my update is correct, insofar as the new syntax for async has changed. If this change is not made, HA will not even boot because it gets stuck in the event loop.
What's very strange, though, is the manual_mqtt alarm does not have the async_setup_platform set up as an async method. Everywhere else in the code base async_setup_platform is type async, except for manual_mqtt. Thus I speculated that bwalarm would also need to be non-async, but doing that results in the hang of HA.
I will PR my fix, if I get mqtt working. For now, if you want to use my patch, you simply need to edit your bwalarm.py and remove all the lines that say:
@asyncio.coroutine
Then the "def" that immediately follows should be prefixed with "async."
It's working now.
https://github.com/gazoscalvertos/Hass-Custom-Alarm/pull/52
I had to turn all the internal calls to async_ but leave the outer async_setup_platform without the async prefix.
It's working now with override_code aswell.
#65
I needed that since my mqtt alarm panel doesn't have code for arming, only for disarming.