From 7dc05785ccca02e2cf8428c871c316ddc142293e Mon Sep 17 00:00:00 2001 From: TimV Date: Mon, 27 Feb 2017 00:38:47 -0500 Subject: [PATCH] Analog modem callerid support (#5840) * analog-modem-callerid * analog-modem-callerid * analog-mod * Updates from latest review * Updates from latest review --- .coveragerc | 1 + .../components/sensor/modem_callerid.py | 122 ++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 126 insertions(+) create mode 100644 homeassistant/components/sensor/modem_callerid.py diff --git a/.coveragerc b/.coveragerc index 820c53d81ee..3f5ba7a35de 100644 --- a/.coveragerc +++ b/.coveragerc @@ -341,6 +341,7 @@ omit = homeassistant/components/sensor/loopenergy.py homeassistant/components/sensor/mhz19.py homeassistant/components/sensor/miflora.py + homeassistant/components/sensor/modem_callerid.py homeassistant/components/sensor/mqtt_room.py homeassistant/components/sensor/netdata.py homeassistant/components/sensor/neurio_energy.py diff --git a/homeassistant/components/sensor/modem_callerid.py b/homeassistant/components/sensor/modem_callerid.py new file mode 100644 index 00000000000..bb9a984c87b --- /dev/null +++ b/homeassistant/components/sensor/modem_callerid.py @@ -0,0 +1,122 @@ +""" +A sensor to monitor incoming calls using a USB modem that supports caller ID. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.modem_callerid/ +""" +import logging +import voluptuous as vol +from homeassistant.const import (STATE_IDLE, + EVENT_HOMEASSISTANT_STOP, + CONF_NAME, + CONF_DEVICE) +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.helpers.entity import Entity +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['https://github.com/vroomfonde1/basicmodem' + '/archive/0.7.zip' + '#basicmodem==0.7'] + +_LOGGER = logging.getLogger(__name__) +DEFAULT_NAME = 'Modem CallerID' +ICON = 'mdi:phone-clasic' +DEFAULT_DEVICE = '/dev/ttyACM0' + +STATE_RING = 'ring' +STATE_CALLERID = 'callerid' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_DEVICE, default=DEFAULT_DEVICE): cv.string +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup modem caller id sensor platform.""" + from basicmodem.basicmodem import BasicModem as bm + name = config.get(CONF_NAME) + port = config.get(CONF_DEVICE) + + modem = bm(port) + if modem.state == modem.STATE_FAILED: + _LOGGER.error('Unable to initialize modem.') + return + + add_devices([ModemCalleridSensor(hass, name, port, modem)]) + + +class ModemCalleridSensor(Entity): + """Implementation of USB modem callerid sensor.""" + + def __init__(self, hass, name, port, modem): + """Initialize the sensor.""" + self._attributes = {"cid_time": 0, "cid_number": '', "cid_name": ''} + self._name = name + self.port = port + self.modem = modem + self._state = STATE_IDLE + modem.registercallback(self._incomingcallcallback) + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, self._stop_modem) + + def set_state(self, state): + """Set the state.""" + self._state = state + + def set_attributes(self, attributes): + """Set the state attributes.""" + self._attributes = attributes + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def icon(self): + """Return icon.""" + return ICON + + @property + def state(self): + """Return the state of the device.""" + return self._state + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def device_state_attributes(self): + """Return the state attributes.""" + return self._attributes + + def _stop_modem(self, event): + """HA is shutting down, close modem port.""" + if self.modem: + self.modem.close() + self.modem = None + return + + def _incomingcallcallback(self, newstate): + """Callback from modem, process based on new state.""" + if newstate == self.modem.STATE_RING: + if self.state == self.modem.STATE_IDLE: + att = {"cid_time": self.modem.get_cidtime, + "cid_number": '', + "cid_name": ''} + self.set_attributes(att) + self._state = STATE_RING + self.schedule_update_ha_state() + elif newstate == self.modem.STATE_CALLERID: + att = {"cid_time": self.modem.get_cidtime, + "cid_number": self.modem.get_cidnumber, + "cid_name": self.modem.get_cidname} + self.set_attributes(att) + self._state = STATE_CALLERID + self.schedule_update_ha_state() + elif newstate == self.modem.STATE_IDLE: + self._state = STATE_IDLE + self.schedule_update_ha_state() + return diff --git a/requirements_all.txt b/requirements_all.txt index 2fe7c9046fa..c13b7952944 100755 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -287,6 +287,9 @@ https://github.com/thecynic/pylutron/archive/v0.1.0.zip#pylutron==0.1.0 # homeassistant.components.mysensors https://github.com/theolind/pymysensors/archive/0b705119389be58332f17753c53167f551254b6c.zip#pymysensors==0.8 +# homeassistant.components.sensor.modem_callerid +https://github.com/vroomfonde1/basicmodem/archive/0.7.zip#basicmodem==0.7 + # homeassistant.components.media_player.lg_netcast https://github.com/wokar/pylgnetcast/archive/v0.2.0.zip#pylgnetcast==0.2.0