mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
XMPP async (#17283)
* new lib dependencies, working old xmpp * non working aioxmpp * reverting to sync xmpp will try slixmpp instead of aioxmpp reasons: echo bot example of aioxmpp had blocking behavior (slixmpp echo bot works fine) closer API to sleekxmpp less dependencies than aioxmpp * first working slixmpp version * DEBUG messages, changed MUC call the joinMUC method changed from sleekxmpp to slixmpp added debug messages better name for cleanup callback * flake8 * little cleanup, tested MUC * requirements_all * dependencies managed by slixmpp, removed debug messages * resource configurable by user, requirements updated * changed __init__ parameter code format * removed trailing dots from LOG messages * changed super call to python3 format
This commit is contained in:
parent
db536797be
commit
d4b092706a
@ -12,12 +12,9 @@ import homeassistant.helpers.config_validation as cv
|
|||||||
from homeassistant.components.notify import (
|
from homeassistant.components.notify import (
|
||||||
ATTR_TITLE, ATTR_TITLE_DEFAULT, PLATFORM_SCHEMA, BaseNotificationService)
|
ATTR_TITLE, ATTR_TITLE_DEFAULT, PLATFORM_SCHEMA, BaseNotificationService)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_PASSWORD, CONF_SENDER, CONF_RECIPIENT, CONF_ROOM)
|
CONF_PASSWORD, CONF_SENDER, CONF_RECIPIENT, CONF_ROOM, CONF_RESOURCE)
|
||||||
|
|
||||||
REQUIREMENTS = ['sleekxmpp==1.3.2',
|
REQUIREMENTS = ['slixmpp==1.4.0']
|
||||||
'dnspython3==1.15.0',
|
|
||||||
'pyasn1==0.3.7',
|
|
||||||
'pyasn1-modules==0.1.5']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -31,84 +28,94 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
vol.Optional(CONF_TLS, default=True): cv.boolean,
|
vol.Optional(CONF_TLS, default=True): cv.boolean,
|
||||||
vol.Optional(CONF_VERIFY, default=True): cv.boolean,
|
vol.Optional(CONF_VERIFY, default=True): cv.boolean,
|
||||||
vol.Optional(CONF_ROOM, default=''): cv.string,
|
vol.Optional(CONF_ROOM, default=''): cv.string,
|
||||||
|
vol.Optional(CONF_RESOURCE, default="home-assistant"): cv.string,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def get_service(hass, config, discovery_info=None):
|
async def async_get_service(hass, config, discovery_info=None):
|
||||||
"""Get the Jabber (XMPP) notification service."""
|
"""Get the Jabber (XMPP) notification service."""
|
||||||
return XmppNotificationService(
|
return XmppNotificationService(
|
||||||
config.get(CONF_SENDER), config.get(CONF_PASSWORD),
|
config.get(CONF_SENDER), config.get(CONF_RESOURCE),
|
||||||
config.get(CONF_RECIPIENT), config.get(CONF_TLS),
|
config.get(CONF_PASSWORD), config.get(CONF_RECIPIENT),
|
||||||
config.get(CONF_VERIFY), config.get(CONF_ROOM))
|
config.get(CONF_TLS), config.get(CONF_VERIFY),
|
||||||
|
config.get(CONF_ROOM), hass.loop)
|
||||||
|
|
||||||
|
|
||||||
class XmppNotificationService(BaseNotificationService):
|
class XmppNotificationService(BaseNotificationService):
|
||||||
"""Implement the notification service for Jabber (XMPP)."""
|
"""Implement the notification service for Jabber (XMPP)."""
|
||||||
|
|
||||||
def __init__(self, sender, password, recipient, tls, verify, room):
|
def __init__(self, sender, resource, password,
|
||||||
|
recipient, tls, verify, room, loop):
|
||||||
"""Initialize the service."""
|
"""Initialize the service."""
|
||||||
|
self._loop = loop
|
||||||
self._sender = sender
|
self._sender = sender
|
||||||
|
self._resource = resource
|
||||||
self._password = password
|
self._password = password
|
||||||
self._recipient = recipient
|
self._recipient = recipient
|
||||||
self._tls = tls
|
self._tls = tls
|
||||||
self._verify = verify
|
self._verify = verify
|
||||||
self._room = room
|
self._room = room
|
||||||
|
|
||||||
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."""
|
||||||
title = kwargs.get(ATTR_TITLE, ATTR_TITLE_DEFAULT)
|
title = kwargs.get(ATTR_TITLE, ATTR_TITLE_DEFAULT)
|
||||||
data = '{}: {}'.format(title, message) if title else message
|
data = '{}: {}'.format(title, message) if title else message
|
||||||
|
|
||||||
send_message('{}/home-assistant'.format(self._sender),
|
await async_send_message(
|
||||||
self._password, self._recipient, self._tls,
|
'{}/{}'.format(self._sender, self._resource),
|
||||||
self._verify, self._room, data)
|
self._password, self._recipient, self._tls,
|
||||||
|
self._verify, self._room, self._loop, data)
|
||||||
|
|
||||||
|
|
||||||
def send_message(sender, password, recipient, use_tls,
|
async def async_send_message(sender, password, recipient, use_tls,
|
||||||
verify_certificate, room, message):
|
verify_certificate, room, loop, message):
|
||||||
"""Send a message over XMPP."""
|
"""Send a message over XMPP."""
|
||||||
import sleekxmpp
|
import slixmpp
|
||||||
|
|
||||||
class SendNotificationBot(sleekxmpp.ClientXMPP):
|
class SendNotificationBot(slixmpp.ClientXMPP):
|
||||||
"""Service for sending Jabber (XMPP) messages."""
|
"""Service for sending Jabber (XMPP) messages."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialize the Jabber Bot."""
|
"""Initialize the Jabber Bot."""
|
||||||
super(SendNotificationBot, self).__init__(sender, password)
|
super().__init__(sender, password)
|
||||||
|
|
||||||
self.use_tls = use_tls
|
# need hass.loop!!
|
||||||
|
self.loop = loop
|
||||||
|
|
||||||
|
self.force_starttls = use_tls
|
||||||
self.use_ipv6 = False
|
self.use_ipv6 = False
|
||||||
self.add_event_handler('failed_auth', self.check_credentials)
|
self.add_event_handler(
|
||||||
|
'failed_auth', self.disconnect_on_login_fail)
|
||||||
self.add_event_handler('session_start', self.start)
|
self.add_event_handler('session_start', self.start)
|
||||||
|
|
||||||
if room:
|
if room:
|
||||||
self.register_plugin('xep_0045') # MUC
|
self.register_plugin('xep_0045') # MUC
|
||||||
if not verify_certificate:
|
if not verify_certificate:
|
||||||
self.add_event_handler('ssl_invalid_cert',
|
self.add_event_handler('ssl_invalid_cert',
|
||||||
self.discard_ssl_invalid_cert)
|
self.discard_ssl_invalid_cert)
|
||||||
|
|
||||||
self.connect(use_tls=self.use_tls, use_ssl=False)
|
self.connect(force_starttls=self.force_starttls, use_ssl=False)
|
||||||
self.process()
|
|
||||||
|
|
||||||
def start(self, event):
|
def start(self, event):
|
||||||
"""Start the communication and sends the message."""
|
"""Start the communication and sends the message."""
|
||||||
self.send_presence()
|
|
||||||
self.get_roster()
|
self.get_roster()
|
||||||
|
self.send_presence()
|
||||||
if room:
|
if room:
|
||||||
_LOGGER.debug("Joining room %s.", room)
|
_LOGGER.debug("Joining room %s", room)
|
||||||
self.plugin['xep_0045'].joinMUC(room, sender, wait=True)
|
self.plugin['xep_0045'].join_muc(room, sender, wait=True)
|
||||||
self.send_message(mto=room, mbody=message, mtype='groupchat')
|
self.send_message(mto=room, mbody=message, mtype='groupchat')
|
||||||
else:
|
else:
|
||||||
self.send_message(mto=recipient, mbody=message, mtype='chat')
|
self.send_message(mto=recipient, mbody=message, mtype='chat')
|
||||||
self.disconnect(wait=True)
|
self.disconnect(wait=True)
|
||||||
|
|
||||||
def check_credentials(self, event):
|
def disconnect_on_login_fail(self, event):
|
||||||
"""Disconnect from the server if credentials are invalid."""
|
"""Disconnect from the server if credentials are invalid."""
|
||||||
|
_LOGGER.warning('Login failed')
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def discard_ssl_invalid_cert(event):
|
def discard_ssl_invalid_cert(event):
|
||||||
"""Do nothing if ssl certificate is invalid."""
|
"""Do nothing if ssl certificate is invalid."""
|
||||||
_LOGGER.info('Ignoring invalid ssl certificate as requested.')
|
_LOGGER.info('Ignoring invalid ssl certificate as requested')
|
||||||
|
|
||||||
SendNotificationBot()
|
SendNotificationBot()
|
||||||
|
@ -302,9 +302,6 @@ distro==1.3.0
|
|||||||
# homeassistant.components.switch.digitalloggers
|
# homeassistant.components.switch.digitalloggers
|
||||||
dlipower==0.7.165
|
dlipower==0.7.165
|
||||||
|
|
||||||
# homeassistant.components.notify.xmpp
|
|
||||||
dnspython3==1.15.0
|
|
||||||
|
|
||||||
# homeassistant.components.sensor.dovado
|
# homeassistant.components.sensor.dovado
|
||||||
dovado==0.4.1
|
dovado==0.4.1
|
||||||
|
|
||||||
@ -797,12 +794,6 @@ pyalarmdotcom==0.3.2
|
|||||||
# homeassistant.components.arlo
|
# homeassistant.components.arlo
|
||||||
pyarlo==0.2.0
|
pyarlo==0.2.0
|
||||||
|
|
||||||
# homeassistant.components.notify.xmpp
|
|
||||||
pyasn1-modules==0.1.5
|
|
||||||
|
|
||||||
# homeassistant.components.notify.xmpp
|
|
||||||
pyasn1==0.3.7
|
|
||||||
|
|
||||||
# homeassistant.components.netatmo
|
# homeassistant.components.netatmo
|
||||||
pyatmo==1.2
|
pyatmo==1.2
|
||||||
|
|
||||||
@ -1358,12 +1349,12 @@ skybellpy==0.1.2
|
|||||||
# homeassistant.components.notify.slack
|
# homeassistant.components.notify.slack
|
||||||
slacker==0.9.65
|
slacker==0.9.65
|
||||||
|
|
||||||
# homeassistant.components.notify.xmpp
|
|
||||||
sleekxmpp==1.3.2
|
|
||||||
|
|
||||||
# homeassistant.components.sleepiq
|
# homeassistant.components.sleepiq
|
||||||
sleepyq==0.6
|
sleepyq==0.6
|
||||||
|
|
||||||
|
# homeassistant.components.notify.xmpp
|
||||||
|
slixmpp==1.4.0
|
||||||
|
|
||||||
# homeassistant.components.smappee
|
# homeassistant.components.smappee
|
||||||
smappy==0.2.16
|
smappy==0.2.16
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user