diff --git a/.coveragerc b/.coveragerc index bfefbdd116e..3a8672bebe8 100644 --- a/.coveragerc +++ b/.coveragerc @@ -638,6 +638,7 @@ omit = homeassistant/components/smappee/* homeassistant/components/smarty/* homeassistant/components/smarthab/* + homeassistant/components/sms/* homeassistant/components/smtp/notify.py homeassistant/components/snapcast/media_player.py homeassistant/components/snmp/* diff --git a/CODEOWNERS b/CODEOWNERS index 69572c8b5c8..65b0e98b3cf 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -305,6 +305,7 @@ homeassistant/components/sma/* @kellerza homeassistant/components/smarthab/* @outadoc homeassistant/components/smartthings/* @andrewsayre homeassistant/components/smarty/* @z0mbieprocess +homeassistant/components/sms/* @ocalvo homeassistant/components/smtp/* @fabaff homeassistant/components/solaredge_local/* @drobtravels @scheric homeassistant/components/solarlog/* @Ernst79 diff --git a/homeassistant/components/sms/__init__.py b/homeassistant/components/sms/__init__.py new file mode 100644 index 00000000000..4897ef2844b --- /dev/null +++ b/homeassistant/components/sms/__init__.py @@ -0,0 +1,33 @@ +"""The sms component.""" +import logging + +import gammu # pylint: disable=import-error, no-member +import voluptuous as vol + +from homeassistant.const import CONF_DEVICE +from homeassistant.helpers import config_validation as cv + +from .const import DOMAIN + +_LOGGER = logging.getLogger(__name__) + +CONFIG_SCHEMA = vol.Schema( + {DOMAIN: vol.Schema({vol.Required(CONF_DEVICE): cv.isdevice})}, + extra=vol.ALLOW_EXTRA, +) + + +async def async_setup(hass, config): + """Configure Gammu state machine.""" + conf = config[DOMAIN] + device = conf.get(CONF_DEVICE) + gateway = gammu.StateMachine() # pylint: disable=no-member + try: + gateway.SetConfig(0, dict(Device=device, Connection="at")) + gateway.Init() + except gammu.GSMError as exc: # pylint: disable=no-member + _LOGGER.error("Failed to initialize, error %s", exc) + return False + else: + hass.data[DOMAIN] = gateway + return True diff --git a/homeassistant/components/sms/const.py b/homeassistant/components/sms/const.py new file mode 100644 index 00000000000..aff2b704e05 --- /dev/null +++ b/homeassistant/components/sms/const.py @@ -0,0 +1,3 @@ +"""Constants for sms Component.""" + +DOMAIN = "sms" diff --git a/homeassistant/components/sms/manifest.json b/homeassistant/components/sms/manifest.json new file mode 100644 index 00000000000..c58139993bb --- /dev/null +++ b/homeassistant/components/sms/manifest.json @@ -0,0 +1,8 @@ +{ + "domain": "sms", + "name": "SMS notifications via GSM-modem", + "documentation": "https://www.home-assistant.io/integrations/sms", + "requirements": ["python-gammu==2.12"], + "dependencies": [], + "codeowners": ["@ocalvo"] +} diff --git a/homeassistant/components/sms/notify.py b/homeassistant/components/sms/notify.py new file mode 100644 index 00000000000..0a47e0aad25 --- /dev/null +++ b/homeassistant/components/sms/notify.py @@ -0,0 +1,47 @@ +"""Support for SMS notification services.""" +import logging + +import gammu # pylint: disable=import-error, no-member +import voluptuous as vol + +from homeassistant.components.notify import PLATFORM_SCHEMA, BaseNotificationService +from homeassistant.const import CONF_NAME, CONF_RECIPIENT +import homeassistant.helpers.config_validation as cv + +from .const import DOMAIN + +_LOGGER = logging.getLogger(__name__) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( + {vol.Required(CONF_RECIPIENT): cv.string, vol.Optional(CONF_NAME): cv.string} +) + + +def get_service(hass, config, discovery_info=None): + """Get the SMS notification service.""" + gateway = hass.data[DOMAIN] + number = config[CONF_RECIPIENT] + return SMSNotificationService(gateway, number) + + +class SMSNotificationService(BaseNotificationService): + """Implement the notification service for SMS.""" + + def __init__(self, gateway, number): + """Initialize the service.""" + self.gateway = gateway + self.number = number + + def send_message(self, message="", **kwargs): + """Send SMS message.""" + # Prepare message data + # We tell that we want to use first SMSC number stored in phone + gammu_message = { + "Text": message, + "SMSC": {"Location": 1}, + "Number": self.number, + } + try: + self.gateway.SendSMS(gammu_message) + except gammu.GSMError as exc: # pylint: disable=no-member + _LOGGER.error("Sending to %s failed: %s", self.number, exc) diff --git a/requirements_all.txt b/requirements_all.txt index 047585515b7..3933d684778 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1565,6 +1565,9 @@ python-family-hub-local==0.0.2 # homeassistant.components.darksky python-forecastio==1.4.0 +# homeassistant.components.sms +# python-gammu==2.12 + # homeassistant.components.gc100 python-gc100==1.0.3a diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index fc539a97f9f..3b30bf04363 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -33,6 +33,7 @@ COMMENT_REQUIREMENTS = ( "PySwitchbot", "pySwitchmate", "python-eq3bt", + "python-gammu", "python-lirc", "pyuserinput", "raspihats",