Support incoming SMS messages via polling (#54237)
* Add support to incomming SMS via polling * Update dependencies * Only send notification for unread messages * Only inform if callback is not getting used * Update gateway.py * Apply PR feedback * Update homeassistant/components/sms/gateway.py Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Apply PR comments * Make black happy Co-authored-by: Martin Hjelmare <marhje52@gmail.com>pull/56026/head
parent
a47532c69b
commit
1b0e014783
|
@ -2,3 +2,4 @@
|
||||||
|
|
||||||
DOMAIN = "sms"
|
DOMAIN = "sms"
|
||||||
SMS_GATEWAY = "SMS_GATEWAY"
|
SMS_GATEWAY = "SMS_GATEWAY"
|
||||||
|
SMS_STATE_UNREAD = "UnRead"
|
||||||
|
|
|
@ -6,7 +6,7 @@ from gammu.asyncworker import GammuAsyncWorker # pylint: disable=import-error
|
||||||
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN, SMS_STATE_UNREAD
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -14,24 +14,39 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
class Gateway:
|
class Gateway:
|
||||||
"""SMS gateway to interact with a GSM modem."""
|
"""SMS gateway to interact with a GSM modem."""
|
||||||
|
|
||||||
def __init__(self, worker, hass):
|
def __init__(self, config, hass):
|
||||||
"""Initialize the sms gateway."""
|
"""Initialize the sms gateway."""
|
||||||
self._worker = worker
|
self._worker = GammuAsyncWorker(self.sms_pull)
|
||||||
|
self._worker.configure(config)
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
|
self._first_pull = True
|
||||||
|
|
||||||
async def init_async(self):
|
async def init_async(self):
|
||||||
"""Initialize the sms gateway asynchronously."""
|
"""Initialize the sms gateway asynchronously."""
|
||||||
|
await self._worker.init_async()
|
||||||
try:
|
try:
|
||||||
await self._worker.set_incoming_sms_async()
|
await self._worker.set_incoming_sms_async()
|
||||||
except gammu.ERR_NOTSUPPORTED:
|
except gammu.ERR_NOTSUPPORTED:
|
||||||
_LOGGER.warning("Your phone does not support incoming SMS notifications!")
|
_LOGGER.warning("Falling back to pulling method for SMS notifications")
|
||||||
except gammu.GSMError:
|
except gammu.GSMError:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"GSM error, your phone does not support incoming SMS notifications!"
|
"GSM error, falling back to pulling method for SMS notifications"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
await self._worker.set_incoming_callback_async(self.sms_callback)
|
await self._worker.set_incoming_callback_async(self.sms_callback)
|
||||||
|
|
||||||
|
def sms_pull(self, state_machine):
|
||||||
|
"""Pull device.
|
||||||
|
|
||||||
|
@param state_machine: state machine
|
||||||
|
@type state_machine: gammu.StateMachine
|
||||||
|
"""
|
||||||
|
state_machine.ReadDevice()
|
||||||
|
|
||||||
|
_LOGGER.debug("Pulling modem")
|
||||||
|
self.sms_read_messages(state_machine, self._first_pull)
|
||||||
|
self._first_pull = False
|
||||||
|
|
||||||
def sms_callback(self, state_machine, callback_type, callback_data):
|
def sms_callback(self, state_machine, callback_type, callback_data):
|
||||||
"""Receive notification about incoming event.
|
"""Receive notification about incoming event.
|
||||||
|
|
||||||
|
@ -45,7 +60,15 @@ class Gateway:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Received incoming event type:%s,data:%s", callback_type, callback_data
|
"Received incoming event type:%s,data:%s", callback_type, callback_data
|
||||||
)
|
)
|
||||||
entries = self.get_and_delete_all_sms(state_machine)
|
self.sms_read_messages(state_machine)
|
||||||
|
|
||||||
|
def sms_read_messages(self, state_machine, force=False):
|
||||||
|
"""Read all received SMS messages.
|
||||||
|
|
||||||
|
@param state_machine: state machine which invoked action
|
||||||
|
@type state_machine: gammu.StateMachine
|
||||||
|
"""
|
||||||
|
entries = self.get_and_delete_all_sms(state_machine, force)
|
||||||
_LOGGER.debug("SMS entries:%s", entries)
|
_LOGGER.debug("SMS entries:%s", entries)
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
|
@ -53,22 +76,25 @@ class Gateway:
|
||||||
decoded_entry = gammu.DecodeSMS(entry)
|
decoded_entry = gammu.DecodeSMS(entry)
|
||||||
message = entry[0]
|
message = entry[0]
|
||||||
_LOGGER.debug("Processing sms:%s,decoded:%s", message, decoded_entry)
|
_LOGGER.debug("Processing sms:%s,decoded:%s", message, decoded_entry)
|
||||||
if decoded_entry is None:
|
sms_state = message["State"]
|
||||||
text = message["Text"]
|
_LOGGER.debug("SMS state:%s", sms_state)
|
||||||
else:
|
if sms_state == SMS_STATE_UNREAD:
|
||||||
text = ""
|
if decoded_entry is None:
|
||||||
for inner_entry in decoded_entry["Entries"]:
|
text = message["Text"]
|
||||||
if inner_entry["Buffer"] is not None:
|
else:
|
||||||
text = text + inner_entry["Buffer"]
|
text = ""
|
||||||
|
for inner_entry in decoded_entry["Entries"]:
|
||||||
|
if inner_entry["Buffer"] is not None:
|
||||||
|
text += inner_entry["Buffer"]
|
||||||
|
|
||||||
event_data = {
|
event_data = {
|
||||||
"phone": message["Number"],
|
"phone": message["Number"],
|
||||||
"date": str(message["DateTime"]),
|
"date": str(message["DateTime"]),
|
||||||
"message": text,
|
"message": text,
|
||||||
}
|
}
|
||||||
|
|
||||||
_LOGGER.debug("Append event data:%s", event_data)
|
_LOGGER.debug("Append event data:%s", event_data)
|
||||||
data.append(event_data)
|
data.append(event_data)
|
||||||
|
|
||||||
self._hass.add_job(self._notify_incoming_sms, data)
|
self._hass.add_job(self._notify_incoming_sms, data)
|
||||||
|
|
||||||
|
@ -161,10 +187,7 @@ class Gateway:
|
||||||
async def create_sms_gateway(config, hass):
|
async def create_sms_gateway(config, hass):
|
||||||
"""Create the sms gateway."""
|
"""Create the sms gateway."""
|
||||||
try:
|
try:
|
||||||
worker = GammuAsyncWorker()
|
gateway = Gateway(config, hass)
|
||||||
worker.configure(config)
|
|
||||||
await worker.init_async()
|
|
||||||
gateway = Gateway(worker, hass)
|
|
||||||
await gateway.init_async()
|
await gateway.init_async()
|
||||||
return gateway
|
return gateway
|
||||||
except gammu.GSMError as exc:
|
except gammu.GSMError as exc:
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "SMS notifications via GSM-modem",
|
"name": "SMS notifications via GSM-modem",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/sms",
|
"documentation": "https://www.home-assistant.io/integrations/sms",
|
||||||
"requirements": ["python-gammu==3.1"],
|
"requirements": ["python-gammu==3.2.3"],
|
||||||
"codeowners": ["@ocalvo"],
|
"codeowners": ["@ocalvo"],
|
||||||
"iot_class": "local_polling"
|
"iot_class": "local_polling"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1856,7 +1856,7 @@ python-family-hub-local==0.0.2
|
||||||
python-forecastio==1.4.0
|
python-forecastio==1.4.0
|
||||||
|
|
||||||
# homeassistant.components.sms
|
# homeassistant.components.sms
|
||||||
# python-gammu==3.1
|
# python-gammu==3.2.3
|
||||||
|
|
||||||
# homeassistant.components.gc100
|
# homeassistant.components.gc100
|
||||||
python-gc100==1.0.3a0
|
python-gc100==1.0.3a0
|
||||||
|
|
Loading…
Reference in New Issue