mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Add Call Data Log platform. Mailboxes no longer require media (#16579)
* Add multiple mailbox support * Fix extraneous debugging * Add cdr support * liniting errors * Mailbox log messages should mostly be debug. Fix race condition with initializing CDR * async decorators to async * Lint fixes * Typo * remove unneeded parameter * Fix variable names * Fix async calls from worker thread. Other minor cleanups * more variable renames
This commit is contained in:
parent
df67093441
commit
98b92c78c0
@ -42,6 +42,7 @@ omit =
|
|||||||
|
|
||||||
homeassistant/components/asterisk_mbox.py
|
homeassistant/components/asterisk_mbox.py
|
||||||
homeassistant/components/*/asterisk_mbox.py
|
homeassistant/components/*/asterisk_mbox.py
|
||||||
|
homeassistant/components/*/asterisk_cdr.py
|
||||||
|
|
||||||
homeassistant/components/august.py
|
homeassistant/components/august.py
|
||||||
homeassistant/components/*/august.py
|
homeassistant/components/*/august.py
|
||||||
|
@ -13,7 +13,7 @@ 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, async_dispatcher_send)
|
async_dispatcher_send, dispatcher_connect)
|
||||||
|
|
||||||
REQUIREMENTS = ['asterisk_mbox==0.5.0']
|
REQUIREMENTS = ['asterisk_mbox==0.5.0']
|
||||||
|
|
||||||
@ -21,8 +21,11 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
DOMAIN = 'asterisk_mbox'
|
DOMAIN = 'asterisk_mbox'
|
||||||
|
|
||||||
|
SIGNAL_DISCOVER_PLATFORM = "asterisk_mbox.discover_platform"
|
||||||
SIGNAL_MESSAGE_REQUEST = 'asterisk_mbox.message_request'
|
SIGNAL_MESSAGE_REQUEST = 'asterisk_mbox.message_request'
|
||||||
SIGNAL_MESSAGE_UPDATE = 'asterisk_mbox.message_updated'
|
SIGNAL_MESSAGE_UPDATE = 'asterisk_mbox.message_updated'
|
||||||
|
SIGNAL_CDR_UPDATE = 'asterisk_mbox.message_updated'
|
||||||
|
SIGNAL_CDR_REQUEST = 'asterisk_mbox.message_request'
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: vol.Schema({
|
DOMAIN: vol.Schema({
|
||||||
@ -41,9 +44,7 @@ def setup(hass, config):
|
|||||||
port = conf.get(CONF_PORT)
|
port = conf.get(CONF_PORT)
|
||||||
password = conf.get(CONF_PASSWORD)
|
password = conf.get(CONF_PASSWORD)
|
||||||
|
|
||||||
hass.data[DOMAIN] = AsteriskData(hass, host, port, password)
|
hass.data[DOMAIN] = AsteriskData(hass, host, port, password, config)
|
||||||
|
|
||||||
discovery.load_platform(hass, 'mailbox', DOMAIN, {}, config)
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -51,31 +52,71 @@ def setup(hass, config):
|
|||||||
class AsteriskData:
|
class AsteriskData:
|
||||||
"""Store Asterisk mailbox data."""
|
"""Store Asterisk mailbox data."""
|
||||||
|
|
||||||
def __init__(self, hass, host, port, password):
|
def __init__(self, hass, host, port, password, config):
|
||||||
"""Init the Asterisk data object."""
|
"""Init the Asterisk data object."""
|
||||||
from asterisk_mbox import Client as asteriskClient
|
from asterisk_mbox import Client as asteriskClient
|
||||||
|
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.client = asteriskClient(host, port, password, self.handle_data)
|
self.config = config
|
||||||
self.messages = []
|
self.messages = None
|
||||||
|
self.cdr = None
|
||||||
|
|
||||||
async_dispatcher_connect(
|
dispatcher_connect(
|
||||||
self.hass, SIGNAL_MESSAGE_REQUEST, self._request_messages)
|
self.hass, SIGNAL_MESSAGE_REQUEST, self._request_messages)
|
||||||
|
dispatcher_connect(
|
||||||
|
self.hass, SIGNAL_CDR_REQUEST, self._request_cdr)
|
||||||
|
dispatcher_connect(
|
||||||
|
self.hass, SIGNAL_DISCOVER_PLATFORM, self._discover_platform)
|
||||||
|
# Only connect after signal connection to ensure we don't miss any
|
||||||
|
self.client = asteriskClient(host, port, password, self.handle_data)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _discover_platform(self, component):
|
||||||
|
_LOGGER.debug("Adding mailbox %s", component)
|
||||||
|
self.hass.async_create_task(discovery.async_load_platform(
|
||||||
|
self.hass, "mailbox", component, {}, self.config))
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def handle_data(self, command, msg):
|
def handle_data(self, command, msg):
|
||||||
"""Handle changes to the mailbox."""
|
"""Handle changes to the mailbox."""
|
||||||
from asterisk_mbox.commands import CMD_MESSAGE_LIST
|
from asterisk_mbox.commands import (CMD_MESSAGE_LIST,
|
||||||
|
CMD_MESSAGE_CDR_AVAILABLE,
|
||||||
|
CMD_MESSAGE_CDR)
|
||||||
|
|
||||||
if command == CMD_MESSAGE_LIST:
|
if command == CMD_MESSAGE_LIST:
|
||||||
_LOGGER.debug("AsteriskVM sent updated message list")
|
_LOGGER.debug("AsteriskVM sent updated message list: Len %d",
|
||||||
|
len(msg))
|
||||||
|
old_messages = self.messages
|
||||||
self.messages = sorted(
|
self.messages = sorted(
|
||||||
msg, key=lambda item: item['info']['origtime'], reverse=True)
|
msg, key=lambda item: item['info']['origtime'], reverse=True)
|
||||||
async_dispatcher_send(
|
if not isinstance(old_messages, list):
|
||||||
self.hass, SIGNAL_MESSAGE_UPDATE, self.messages)
|
async_dispatcher_send(self.hass, SIGNAL_DISCOVER_PLATFORM,
|
||||||
|
DOMAIN)
|
||||||
|
async_dispatcher_send(self.hass, SIGNAL_MESSAGE_UPDATE,
|
||||||
|
self.messages)
|
||||||
|
elif command == CMD_MESSAGE_CDR:
|
||||||
|
_LOGGER.debug("AsteriskVM sent updated CDR list: Len %d",
|
||||||
|
len(msg.get('entries', [])))
|
||||||
|
self.cdr = msg['entries']
|
||||||
|
async_dispatcher_send(self.hass, SIGNAL_CDR_UPDATE, self.cdr)
|
||||||
|
elif command == CMD_MESSAGE_CDR_AVAILABLE:
|
||||||
|
if not isinstance(self.cdr, list):
|
||||||
|
_LOGGER.debug("AsteriskVM adding CDR platform")
|
||||||
|
self.cdr = []
|
||||||
|
async_dispatcher_send(self.hass, SIGNAL_DISCOVER_PLATFORM,
|
||||||
|
"asterisk_cdr")
|
||||||
|
async_dispatcher_send(self.hass, SIGNAL_CDR_REQUEST)
|
||||||
|
else:
|
||||||
|
_LOGGER.debug("AsteriskVM sent unknown message '%d' len: %d",
|
||||||
|
command, len(msg))
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _request_messages(self):
|
def _request_messages(self):
|
||||||
"""Handle changes to the mailbox."""
|
"""Handle changes to the mailbox."""
|
||||||
_LOGGER.debug("Requesting message list")
|
_LOGGER.debug("Requesting message list")
|
||||||
self.client.messages()
|
self.client.messages()
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _request_cdr(self):
|
||||||
|
"""Handle changes to the CDR."""
|
||||||
|
_LOGGER.debug("Requesting CDR list")
|
||||||
|
self.client.get_cdr()
|
||||||
|
@ -23,36 +23,34 @@ from homeassistant.setup import async_prepare_setup_platform
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONTENT_TYPE_MPEG = 'audio/mpeg'
|
|
||||||
|
|
||||||
DEPENDENCIES = ['http']
|
DEPENDENCIES = ['http']
|
||||||
DOMAIN = 'mailbox'
|
DOMAIN = 'mailbox'
|
||||||
|
|
||||||
EVENT = 'mailbox_updated'
|
EVENT = 'mailbox_updated'
|
||||||
|
CONTENT_TYPE_MPEG = 'audio/mpeg'
|
||||||
|
CONTENT_TYPE_NONE = 'none'
|
||||||
|
|
||||||
SCAN_INTERVAL = timedelta(seconds=30)
|
SCAN_INTERVAL = timedelta(seconds=30)
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_setup(hass, config):
|
||||||
def async_setup(hass, config):
|
|
||||||
"""Track states and offer events for mailboxes."""
|
"""Track states and offer events for mailboxes."""
|
||||||
mailboxes = []
|
mailboxes = []
|
||||||
yield from hass.components.frontend.async_register_built_in_panel(
|
await hass.components.frontend.async_register_built_in_panel(
|
||||||
'mailbox', 'mailbox', 'mdi:mailbox')
|
'mailbox', 'mailbox', 'mdi:mailbox')
|
||||||
hass.http.register_view(MailboxPlatformsView(mailboxes))
|
hass.http.register_view(MailboxPlatformsView(mailboxes))
|
||||||
hass.http.register_view(MailboxMessageView(mailboxes))
|
hass.http.register_view(MailboxMessageView(mailboxes))
|
||||||
hass.http.register_view(MailboxMediaView(mailboxes))
|
hass.http.register_view(MailboxMediaView(mailboxes))
|
||||||
hass.http.register_view(MailboxDeleteView(mailboxes))
|
hass.http.register_view(MailboxDeleteView(mailboxes))
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_setup_platform(p_type, p_config=None, discovery_info=None):
|
||||||
def async_setup_platform(p_type, p_config=None, discovery_info=None):
|
|
||||||
"""Set up a mailbox platform."""
|
"""Set up a mailbox platform."""
|
||||||
if p_config is None:
|
if p_config is None:
|
||||||
p_config = {}
|
p_config = {}
|
||||||
if discovery_info is None:
|
if discovery_info is None:
|
||||||
discovery_info = {}
|
discovery_info = {}
|
||||||
|
|
||||||
platform = yield from async_prepare_setup_platform(
|
platform = await async_prepare_setup_platform(
|
||||||
hass, config, DOMAIN, p_type)
|
hass, config, DOMAIN, p_type)
|
||||||
|
|
||||||
if platform is None:
|
if platform is None:
|
||||||
@ -63,10 +61,10 @@ def async_setup(hass, config):
|
|||||||
mailbox = None
|
mailbox = None
|
||||||
try:
|
try:
|
||||||
if hasattr(platform, 'async_get_handler'):
|
if hasattr(platform, 'async_get_handler'):
|
||||||
mailbox = yield from \
|
mailbox = await \
|
||||||
platform.async_get_handler(hass, p_config, discovery_info)
|
platform.async_get_handler(hass, p_config, discovery_info)
|
||||||
elif hasattr(platform, 'get_handler'):
|
elif hasattr(platform, 'get_handler'):
|
||||||
mailbox = yield from hass.async_add_job(
|
mailbox = await hass.async_add_executor_job(
|
||||||
platform.get_handler, hass, p_config, discovery_info)
|
platform.get_handler, hass, p_config, discovery_info)
|
||||||
else:
|
else:
|
||||||
raise HomeAssistantError("Invalid mailbox platform.")
|
raise HomeAssistantError("Invalid mailbox platform.")
|
||||||
@ -81,21 +79,20 @@ def async_setup(hass, config):
|
|||||||
return
|
return
|
||||||
|
|
||||||
mailboxes.append(mailbox)
|
mailboxes.append(mailbox)
|
||||||
mailbox_entity = MailboxEntity(hass, mailbox)
|
mailbox_entity = MailboxEntity(mailbox)
|
||||||
component = EntityComponent(
|
component = EntityComponent(
|
||||||
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)
|
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL)
|
||||||
yield from component.async_add_entities([mailbox_entity])
|
await component.async_add_entities([mailbox_entity])
|
||||||
|
|
||||||
setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config
|
setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config
|
||||||
in config_per_platform(config, DOMAIN)]
|
in config_per_platform(config, DOMAIN)]
|
||||||
|
|
||||||
if setup_tasks:
|
if setup_tasks:
|
||||||
yield from asyncio.wait(setup_tasks, loop=hass.loop)
|
await asyncio.wait(setup_tasks, loop=hass.loop)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_platform_discovered(platform, info):
|
||||||
def async_platform_discovered(platform, info):
|
|
||||||
"""Handle for discovered platform."""
|
"""Handle for discovered platform."""
|
||||||
yield from async_setup_platform(platform, discovery_info=info)
|
await async_setup_platform(platform, discovery_info=info)
|
||||||
|
|
||||||
discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered)
|
discovery.async_listen_platform(hass, DOMAIN, async_platform_discovered)
|
||||||
|
|
||||||
@ -103,19 +100,21 @@ def async_setup(hass, config):
|
|||||||
|
|
||||||
|
|
||||||
class MailboxEntity(Entity):
|
class MailboxEntity(Entity):
|
||||||
"""Entity for each mailbox platform."""
|
"""Entity for each mailbox platform to provide a badge display."""
|
||||||
|
|
||||||
def __init__(self, hass, mailbox):
|
def __init__(self, mailbox):
|
||||||
"""Initialize mailbox entity."""
|
"""Initialize mailbox entity."""
|
||||||
self.mailbox = mailbox
|
self.mailbox = mailbox
|
||||||
self.hass = hass
|
|
||||||
self.message_count = 0
|
self.message_count = 0
|
||||||
|
|
||||||
|
async def async_added_to_hass(self):
|
||||||
|
"""Complete entity initialization."""
|
||||||
@callback
|
@callback
|
||||||
def _mailbox_updated(event):
|
def _mailbox_updated(event):
|
||||||
self.async_schedule_update_ha_state(True)
|
self.async_schedule_update_ha_state(True)
|
||||||
|
|
||||||
hass.bus.async_listen(EVENT, _mailbox_updated)
|
self.hass.bus.async_listen(EVENT, _mailbox_updated)
|
||||||
|
self.async_schedule_update_ha_state(True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
@ -127,10 +126,9 @@ class MailboxEntity(Entity):
|
|||||||
"""Return the name of the entity."""
|
"""Return the name of the entity."""
|
||||||
return self.mailbox.name
|
return self.mailbox.name
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_update(self):
|
||||||
def async_update(self):
|
|
||||||
"""Retrieve messages from platform."""
|
"""Retrieve messages from platform."""
|
||||||
messages = yield from self.mailbox.async_get_messages()
|
messages = await self.mailbox.async_get_messages()
|
||||||
self.message_count = len(messages)
|
self.message_count = len(messages)
|
||||||
|
|
||||||
|
|
||||||
@ -151,13 +149,21 @@ class Mailbox:
|
|||||||
"""Return the supported media type."""
|
"""Return the supported media type."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@asyncio.coroutine
|
@property
|
||||||
def async_get_media(self, msgid):
|
def can_delete(self):
|
||||||
|
"""Return if messages can be deleted."""
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_media(self):
|
||||||
|
"""Return if messages have attached media files."""
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def async_get_media(self, msgid):
|
||||||
"""Return the media blob for the msgid."""
|
"""Return the media blob for the msgid."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_get_messages(self):
|
||||||
def async_get_messages(self):
|
|
||||||
"""Return a list of the current messages."""
|
"""Return a list of the current messages."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@ -193,12 +199,16 @@ class MailboxPlatformsView(MailboxView):
|
|||||||
url = "/api/mailbox/platforms"
|
url = "/api/mailbox/platforms"
|
||||||
name = "api:mailbox:platforms"
|
name = "api:mailbox:platforms"
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def get(self, request):
|
||||||
def get(self, request):
|
|
||||||
"""Retrieve list of platforms."""
|
"""Retrieve list of platforms."""
|
||||||
platforms = []
|
platforms = []
|
||||||
for mailbox in self.mailboxes:
|
for mailbox in self.mailboxes:
|
||||||
platforms.append(mailbox.name)
|
platforms.append(
|
||||||
|
{
|
||||||
|
'name': mailbox.name,
|
||||||
|
'has_media': mailbox.has_media,
|
||||||
|
'can_delete': mailbox.can_delete
|
||||||
|
})
|
||||||
return self.json(platforms)
|
return self.json(platforms)
|
||||||
|
|
||||||
|
|
||||||
@ -208,11 +218,10 @@ class MailboxMessageView(MailboxView):
|
|||||||
url = "/api/mailbox/messages/{platform}"
|
url = "/api/mailbox/messages/{platform}"
|
||||||
name = "api:mailbox:messages"
|
name = "api:mailbox:messages"
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def get(self, request, platform):
|
||||||
def get(self, request, platform):
|
|
||||||
"""Retrieve messages."""
|
"""Retrieve messages."""
|
||||||
mailbox = self.get_mailbox(platform)
|
mailbox = self.get_mailbox(platform)
|
||||||
messages = yield from mailbox.async_get_messages()
|
messages = await mailbox.async_get_messages()
|
||||||
return self.json(messages)
|
return self.json(messages)
|
||||||
|
|
||||||
|
|
||||||
@ -222,8 +231,7 @@ class MailboxDeleteView(MailboxView):
|
|||||||
url = "/api/mailbox/delete/{platform}/{msgid}"
|
url = "/api/mailbox/delete/{platform}/{msgid}"
|
||||||
name = "api:mailbox:delete"
|
name = "api:mailbox:delete"
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def delete(self, request, platform, msgid):
|
||||||
def delete(self, request, platform, msgid):
|
|
||||||
"""Delete items."""
|
"""Delete items."""
|
||||||
mailbox = self.get_mailbox(platform)
|
mailbox = self.get_mailbox(platform)
|
||||||
mailbox.async_delete(msgid)
|
mailbox.async_delete(msgid)
|
||||||
@ -235,8 +243,7 @@ class MailboxMediaView(MailboxView):
|
|||||||
url = r"/api/mailbox/media/{platform}/{msgid}"
|
url = r"/api/mailbox/media/{platform}/{msgid}"
|
||||||
name = "api:asteriskmbox:media"
|
name = "api:asteriskmbox:media"
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def get(self, request, platform, msgid):
|
||||||
def get(self, request, platform, msgid):
|
|
||||||
"""Retrieve media."""
|
"""Retrieve media."""
|
||||||
mailbox = self.get_mailbox(platform)
|
mailbox = self.get_mailbox(platform)
|
||||||
|
|
||||||
@ -244,7 +251,7 @@ class MailboxMediaView(MailboxView):
|
|||||||
with suppress(asyncio.CancelledError, asyncio.TimeoutError):
|
with suppress(asyncio.CancelledError, asyncio.TimeoutError):
|
||||||
with async_timeout.timeout(10, loop=hass.loop):
|
with async_timeout.timeout(10, loop=hass.loop):
|
||||||
try:
|
try:
|
||||||
stream = yield from mailbox.async_get_media(msgid)
|
stream = await mailbox.async_get_media(msgid)
|
||||||
except StreamError as err:
|
except StreamError as err:
|
||||||
error_msg = "Error getting media: %s" % (err)
|
error_msg = "Error getting media: %s" % (err)
|
||||||
_LOGGER.error(error_msg)
|
_LOGGER.error(error_msg)
|
||||||
|
64
homeassistant/components/mailbox/asterisk_cdr.py
Normal file
64
homeassistant/components/mailbox/asterisk_cdr.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
"""
|
||||||
|
Asterisk CDR interface.
|
||||||
|
|
||||||
|
For more details about this platform, please refer to the documentation at
|
||||||
|
https://home-assistant.io/components/mailbox.asterisk_cdr/
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
import hashlib
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from homeassistant.core import callback
|
||||||
|
from homeassistant.components.asterisk_mbox import SIGNAL_CDR_UPDATE
|
||||||
|
from homeassistant.components.asterisk_mbox import DOMAIN as ASTERISK_DOMAIN
|
||||||
|
from homeassistant.components.mailbox import Mailbox
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
|
||||||
|
DEPENDENCIES = ['asterisk_mbox']
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
MAILBOX_NAME = "asterisk_cdr"
|
||||||
|
|
||||||
|
|
||||||
|
async def async_get_handler(hass, config, discovery_info=None):
|
||||||
|
"""Set up the Asterix CDR platform."""
|
||||||
|
return AsteriskCDR(hass, MAILBOX_NAME)
|
||||||
|
|
||||||
|
|
||||||
|
class AsteriskCDR(Mailbox):
|
||||||
|
"""Asterisk VM Call Data Record mailbox."""
|
||||||
|
|
||||||
|
def __init__(self, hass, name):
|
||||||
|
"""Initialize Asterisk CDR."""
|
||||||
|
super().__init__(hass, name)
|
||||||
|
self.cdr = []
|
||||||
|
async_dispatcher_connect(
|
||||||
|
self.hass, SIGNAL_CDR_UPDATE, self._update_callback)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _update_callback(self, msg):
|
||||||
|
"""Update the message count in HA, if needed."""
|
||||||
|
self._build_message()
|
||||||
|
self.async_update()
|
||||||
|
|
||||||
|
def _build_message(self):
|
||||||
|
"""Build message structure."""
|
||||||
|
cdr = []
|
||||||
|
for entry in self.hass.data[ASTERISK_DOMAIN].cdr:
|
||||||
|
timestamp = datetime.datetime.strptime(
|
||||||
|
entry['time'], "%Y-%m-%d %H:%M:%S").timestamp()
|
||||||
|
info = {
|
||||||
|
'origtime': timestamp,
|
||||||
|
'callerid': entry['callerid'],
|
||||||
|
'duration': entry['duration'],
|
||||||
|
}
|
||||||
|
sha = hashlib.sha256(str(entry).encode('utf-8')).hexdigest()
|
||||||
|
msg = "Destination: {}\nApplication: {}\n Context: {}".format(
|
||||||
|
entry['dest'], entry['application'], entry['context'])
|
||||||
|
cdr.append({'info': info, 'sha': sha, 'text': msg})
|
||||||
|
self.cdr = cdr
|
||||||
|
|
||||||
|
async def async_get_messages(self):
|
||||||
|
"""Return a list of the current messages."""
|
||||||
|
if not self.cdr:
|
||||||
|
self._build_message()
|
||||||
|
return self.cdr
|
@ -4,10 +4,9 @@ Asterisk Voicemail interface.
|
|||||||
For more details about this platform, please refer to the documentation at
|
For more details about this platform, please refer to the documentation at
|
||||||
https://home-assistant.io/components/mailbox.asteriskvm/
|
https://home-assistant.io/components/mailbox.asteriskvm/
|
||||||
"""
|
"""
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from homeassistant.components.asterisk_mbox import DOMAIN
|
from homeassistant.components.asterisk_mbox import DOMAIN as ASTERISK_DOMAIN
|
||||||
from homeassistant.components.mailbox import (
|
from homeassistant.components.mailbox import (
|
||||||
CONTENT_TYPE_MPEG, Mailbox, StreamError)
|
CONTENT_TYPE_MPEG, Mailbox, StreamError)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
@ -21,10 +20,9 @@ SIGNAL_MESSAGE_REQUEST = 'asterisk_mbox.message_request'
|
|||||||
SIGNAL_MESSAGE_UPDATE = 'asterisk_mbox.message_updated'
|
SIGNAL_MESSAGE_UPDATE = 'asterisk_mbox.message_updated'
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_get_handler(hass, config, discovery_info=None):
|
||||||
def async_get_handler(hass, config, async_add_entities, discovery_info=None):
|
|
||||||
"""Set up the Asterix VM platform."""
|
"""Set up the Asterix VM platform."""
|
||||||
return AsteriskMailbox(hass, DOMAIN)
|
return AsteriskMailbox(hass, ASTERISK_DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
class AsteriskMailbox(Mailbox):
|
class AsteriskMailbox(Mailbox):
|
||||||
@ -46,24 +44,32 @@ class AsteriskMailbox(Mailbox):
|
|||||||
"""Return the supported media type."""
|
"""Return the supported media type."""
|
||||||
return CONTENT_TYPE_MPEG
|
return CONTENT_TYPE_MPEG
|
||||||
|
|
||||||
@asyncio.coroutine
|
@property
|
||||||
def async_get_media(self, msgid):
|
def can_delete(self):
|
||||||
|
"""Return if messages can be deleted."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_media(self):
|
||||||
|
"""Return if messages have attached media files."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def async_get_media(self, msgid):
|
||||||
"""Return the media blob for the msgid."""
|
"""Return the media blob for the msgid."""
|
||||||
from asterisk_mbox import ServerError
|
from asterisk_mbox import ServerError
|
||||||
client = self.hass.data[DOMAIN].client
|
client = self.hass.data[ASTERISK_DOMAIN].client
|
||||||
try:
|
try:
|
||||||
return client.mp3(msgid, sync=True)
|
return client.mp3(msgid, sync=True)
|
||||||
except ServerError as err:
|
except ServerError as err:
|
||||||
raise StreamError(err)
|
raise StreamError(err)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_get_messages(self):
|
||||||
def async_get_messages(self):
|
|
||||||
"""Return a list of the current messages."""
|
"""Return a list of the current messages."""
|
||||||
return self.hass.data[DOMAIN].messages
|
return self.hass.data[ASTERISK_DOMAIN].messages
|
||||||
|
|
||||||
def async_delete(self, msgid):
|
def async_delete(self, msgid):
|
||||||
"""Delete the specified messages."""
|
"""Delete the specified messages."""
|
||||||
client = self.hass.data[DOMAIN].client
|
client = self.hass.data[ASTERISK_DOMAIN].client
|
||||||
_LOGGER.info("Deleting: %s", msgid)
|
_LOGGER.info("Deleting: %s", msgid)
|
||||||
client.delete(msgid)
|
client.delete(msgid)
|
||||||
return True
|
return True
|
||||||
|
@ -4,7 +4,6 @@ Asterisk Voicemail interface.
|
|||||||
For more details about this platform, please refer to the documentation at
|
For more details about this platform, please refer to the documentation at
|
||||||
https://home-assistant.io/components/mailbox.asteriskvm/
|
https://home-assistant.io/components/mailbox.asteriskvm/
|
||||||
"""
|
"""
|
||||||
import asyncio
|
|
||||||
from hashlib import sha1
|
from hashlib import sha1
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -15,13 +14,12 @@ from homeassistant.util import dt
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOMAIN = "DemoMailbox"
|
MAILBOX_NAME = "DemoMailbox"
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_get_handler(hass, config, discovery_info=None):
|
||||||
def async_get_handler(hass, config, discovery_info=None):
|
|
||||||
"""Set up the Demo mailbox."""
|
"""Set up the Demo mailbox."""
|
||||||
return DemoMailbox(hass, DOMAIN)
|
return DemoMailbox(hass, MAILBOX_NAME)
|
||||||
|
|
||||||
|
|
||||||
class DemoMailbox(Mailbox):
|
class DemoMailbox(Mailbox):
|
||||||
@ -54,8 +52,17 @@ class DemoMailbox(Mailbox):
|
|||||||
"""Return the supported media type."""
|
"""Return the supported media type."""
|
||||||
return CONTENT_TYPE_MPEG
|
return CONTENT_TYPE_MPEG
|
||||||
|
|
||||||
@asyncio.coroutine
|
@property
|
||||||
def async_get_media(self, msgid):
|
def can_delete(self):
|
||||||
|
"""Return if messages can be deleted."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_media(self):
|
||||||
|
"""Return if messages have attached media files."""
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def async_get_media(self, msgid):
|
||||||
"""Return the media blob for the msgid."""
|
"""Return the media blob for the msgid."""
|
||||||
if msgid not in self._messages:
|
if msgid not in self._messages:
|
||||||
raise StreamError("Message not found")
|
raise StreamError("Message not found")
|
||||||
@ -65,8 +72,7 @@ class DemoMailbox(Mailbox):
|
|||||||
with open(audio_path, 'rb') as file:
|
with open(audio_path, 'rb') as file:
|
||||||
return file.read()
|
return file.read()
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_get_messages(self):
|
||||||
def async_get_messages(self):
|
|
||||||
"""Return a list of the current messages."""
|
"""Return a list of the current messages."""
|
||||||
return sorted(self._messages.values(),
|
return sorted(self._messages.values(),
|
||||||
key=lambda item: item['info']['origtime'],
|
key=lambda item: item['info']['origtime'],
|
||||||
|
@ -29,7 +29,7 @@ def test_get_platforms_from_mailbox(mock_http_client):
|
|||||||
req = yield from mock_http_client.get(url)
|
req = yield from mock_http_client.get(url)
|
||||||
assert req.status == 200
|
assert req.status == 200
|
||||||
result = yield from req.json()
|
result = yield from req.json()
|
||||||
assert len(result) == 1 and "DemoMailbox" in result
|
assert len(result) == 1 and "DemoMailbox" == result[0].get('name', None)
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
|
Loading…
x
Reference in New Issue
Block a user