-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Call Data Log platform. Mailboxes no longer require media #16579
Changes from 10 commits
559c59b
8b65450
baa28fb
47fd776
52190d8
2bf8742
b1806a8
30d75ef
58f5531
fc359dd
31b0f97
2f80578
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,36 +23,34 @@ | |
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
CONTENT_TYPE_MPEG = 'audio/mpeg' | ||
|
||
DEPENDENCIES = ['http'] | ||
DOMAIN = 'mailbox' | ||
|
||
EVENT = 'mailbox_updated' | ||
CONTENT_TYPE_MPEG = 'audio/mpeg' | ||
CONTENT_TYPE_NONE = 'none' | ||
|
||
SCAN_INTERVAL = timedelta(seconds=30) | ||
|
||
|
||
@asyncio.coroutine | ||
def async_setup(hass, config): | ||
async def async_setup(hass, config): | ||
"""Track states and offer events for 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') | ||
hass.http.register_view(MailboxPlatformsView(mailboxes)) | ||
hass.http.register_view(MailboxMessageView(mailboxes)) | ||
hass.http.register_view(MailboxMediaView(mailboxes)) | ||
hass.http.register_view(MailboxDeleteView(mailboxes)) | ||
|
||
@asyncio.coroutine | ||
def async_setup_platform(p_type, p_config=None, discovery_info=None): | ||
async def async_setup_platform(p_type, p_config=None, discovery_info=None): | ||
"""Set up a mailbox platform.""" | ||
if p_config is None: | ||
p_config = {} | ||
if discovery_info is None: | ||
discovery_info = {} | ||
|
||
platform = yield from async_prepare_setup_platform( | ||
platform = await async_prepare_setup_platform( | ||
hass, config, DOMAIN, p_type) | ||
|
||
if platform is None: | ||
|
@@ -63,10 +61,10 @@ def async_setup_platform(p_type, p_config=None, discovery_info=None): | |
mailbox = None | ||
try: | ||
if hasattr(platform, 'async_get_handler'): | ||
mailbox = yield from \ | ||
mailbox = await \ | ||
platform.async_get_handler(hass, p_config, discovery_info) | ||
elif hasattr(platform, 'get_handler'): | ||
mailbox = yield from hass.async_add_job( | ||
mailbox = await hass.async_add_job( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
platform.get_handler, hass, p_config, discovery_info) | ||
else: | ||
raise HomeAssistantError("Invalid mailbox platform.") | ||
|
@@ -81,41 +79,42 @@ def async_setup_platform(p_type, p_config=None, discovery_info=None): | |
return | ||
|
||
mailboxes.append(mailbox) | ||
mailbox_entity = MailboxEntity(hass, mailbox) | ||
mailbox_entity = MailboxEntity(mailbox) | ||
component = EntityComponent( | ||
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 | ||
in config_per_platform(config, DOMAIN)] | ||
|
||
if setup_tasks: | ||
yield from asyncio.wait(setup_tasks, loop=hass.loop) | ||
await asyncio.wait(setup_tasks, loop=hass.loop) | ||
|
||
@asyncio.coroutine | ||
def async_platform_discovered(platform, info): | ||
async def async_platform_discovered(platform, info): | ||
"""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) | ||
|
||
return True | ||
|
||
|
||
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.""" | ||
self.mailbox = mailbox | ||
self.hass = hass | ||
self.message_count = 0 | ||
|
||
async def async_added_to_hass(self): | ||
"""Complete entity initialization.""" | ||
@callback | ||
def _mailbox_updated(event): | ||
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 | ||
def state(self): | ||
|
@@ -127,10 +126,9 @@ def name(self): | |
"""Return the name of the entity.""" | ||
return self.mailbox.name | ||
|
||
@asyncio.coroutine | ||
def async_update(self): | ||
async def async_update(self): | ||
"""Retrieve messages from platform.""" | ||
messages = yield from self.mailbox.async_get_messages() | ||
messages = await self.mailbox.async_get_messages() | ||
self.message_count = len(messages) | ||
|
||
|
||
|
@@ -151,13 +149,21 @@ def media_type(self): | |
"""Return the supported media type.""" | ||
raise NotImplementedError() | ||
|
||
@asyncio.coroutine | ||
def async_get_media(self, msgid): | ||
@property | ||
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.""" | ||
raise NotImplementedError() | ||
|
||
@asyncio.coroutine | ||
def async_get_messages(self): | ||
async def async_get_messages(self): | ||
"""Return a list of the current messages.""" | ||
raise NotImplementedError() | ||
|
||
|
@@ -193,12 +199,16 @@ class MailboxPlatformsView(MailboxView): | |
url = "/api/mailbox/platforms" | ||
name = "api:mailbox:platforms" | ||
|
||
@asyncio.coroutine | ||
def get(self, request): | ||
async def get(self, request): | ||
"""Retrieve list of platforms.""" | ||
platforms = [] | ||
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) | ||
|
||
|
||
|
@@ -208,11 +218,10 @@ class MailboxMessageView(MailboxView): | |
url = "/api/mailbox/messages/{platform}" | ||
name = "api:mailbox:messages" | ||
|
||
@asyncio.coroutine | ||
def get(self, request, platform): | ||
async def get(self, request, platform): | ||
"""Retrieve messages.""" | ||
mailbox = self.get_mailbox(platform) | ||
messages = yield from mailbox.async_get_messages() | ||
messages = await mailbox.async_get_messages() | ||
return self.json(messages) | ||
|
||
|
||
|
@@ -222,8 +231,7 @@ class MailboxDeleteView(MailboxView): | |
url = "/api/mailbox/delete/{platform}/{msgid}" | ||
name = "api:mailbox:delete" | ||
|
||
@asyncio.coroutine | ||
def delete(self, request, platform, msgid): | ||
async def delete(self, request, platform, msgid): | ||
"""Delete items.""" | ||
mailbox = self.get_mailbox(platform) | ||
mailbox.async_delete(msgid) | ||
|
@@ -235,16 +243,15 @@ class MailboxMediaView(MailboxView): | |
url = r"/api/mailbox/media/{platform}/{msgid}" | ||
name = "api:asteriskmbox:media" | ||
|
||
@asyncio.coroutine | ||
def get(self, request, platform, msgid): | ||
async def get(self, request, platform, msgid): | ||
"""Retrieve media.""" | ||
mailbox = self.get_mailbox(platform) | ||
|
||
hass = request.app['hass'] | ||
with suppress(asyncio.CancelledError, asyncio.TimeoutError): | ||
with async_timeout.timeout(10, loop=hass.loop): | ||
try: | ||
stream = yield from mailbox.async_get_media(msgid) | ||
stream = await mailbox.async_get_media(msgid) | ||
except StreamError as err: | ||
error_msg = "Error getting media: %s" % (err) | ||
_LOGGER.error(error_msg) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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.asteriskvm/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The url is wrong. |
||
""" | ||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This platform belongs to the mailbox domain. Import the asterix_mbox domain as another name. from homeassistant.components.asterisk_mbox import DOMAIN as ASTERIX_MBOX_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[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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This must be called from within the event loop but it's called from
setup
ie from a worker thread. Change to use the sync version.