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
Oscar Calvo 2021-09-09 09:29:11 -07:00 committed by GitHub
parent a47532c69b
commit 1b0e014783
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 26 deletions

View File

@ -2,3 +2,4 @@
DOMAIN = "sms"
SMS_GATEWAY = "SMS_GATEWAY"
SMS_STATE_UNREAD = "UnRead"

View File

@ -6,7 +6,7 @@ from gammu.asyncworker import GammuAsyncWorker # pylint: disable=import-error
from homeassistant.core import callback
from .const import DOMAIN
from .const import DOMAIN, SMS_STATE_UNREAD
_LOGGER = logging.getLogger(__name__)
@ -14,24 +14,39 @@ _LOGGER = logging.getLogger(__name__)
class Gateway:
"""SMS gateway to interact with a GSM modem."""
def __init__(self, worker, hass):
def __init__(self, config, hass):
"""Initialize the sms gateway."""
self._worker = worker
self._worker = GammuAsyncWorker(self.sms_pull)
self._worker.configure(config)
self._hass = hass
self._first_pull = True
async def init_async(self):
"""Initialize the sms gateway asynchronously."""
await self._worker.init_async()
try:
await self._worker.set_incoming_sms_async()
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:
_LOGGER.warning(
"GSM error, your phone does not support incoming SMS notifications!"
"GSM error, falling back to pulling method for SMS notifications"
)
else:
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):
"""Receive notification about incoming event.
@ -45,7 +60,15 @@ class Gateway:
_LOGGER.debug(
"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)
data = []
@ -53,22 +76,25 @@ class Gateway:
decoded_entry = gammu.DecodeSMS(entry)
message = entry[0]
_LOGGER.debug("Processing sms:%s,decoded:%s", message, decoded_entry)
if decoded_entry is None:
text = message["Text"]
else:
text = ""
for inner_entry in decoded_entry["Entries"]:
if inner_entry["Buffer"] is not None:
text = text + inner_entry["Buffer"]
sms_state = message["State"]
_LOGGER.debug("SMS state:%s", sms_state)
if sms_state == SMS_STATE_UNREAD:
if decoded_entry is None:
text = message["Text"]
else:
text = ""
for inner_entry in decoded_entry["Entries"]:
if inner_entry["Buffer"] is not None:
text += inner_entry["Buffer"]
event_data = {
"phone": message["Number"],
"date": str(message["DateTime"]),
"message": text,
}
event_data = {
"phone": message["Number"],
"date": str(message["DateTime"]),
"message": text,
}
_LOGGER.debug("Append event data:%s", event_data)
data.append(event_data)
_LOGGER.debug("Append event data:%s", event_data)
data.append(event_data)
self._hass.add_job(self._notify_incoming_sms, data)
@ -161,10 +187,7 @@ class Gateway:
async def create_sms_gateway(config, hass):
"""Create the sms gateway."""
try:
worker = GammuAsyncWorker()
worker.configure(config)
await worker.init_async()
gateway = Gateway(worker, hass)
gateway = Gateway(config, hass)
await gateway.init_async()
return gateway
except gammu.GSMError as exc:

View File

@ -3,7 +3,7 @@
"name": "SMS notifications via GSM-modem",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/sms",
"requirements": ["python-gammu==3.1"],
"requirements": ["python-gammu==3.2.3"],
"codeowners": ["@ocalvo"],
"iot_class": "local_polling"
}

View File

@ -1856,7 +1856,7 @@ python-family-hub-local==0.0.2
python-forecastio==1.4.0
# homeassistant.components.sms
# python-gammu==3.1
# python-gammu==3.2.3
# homeassistant.components.gc100
python-gc100==1.0.3a0