diff --git a/homeassistant/components/smartthings/const.py b/homeassistant/components/smartthings/const.py index 9d779bf9d5b..03188411f07 100644 --- a/homeassistant/components/smartthings/const.py +++ b/homeassistant/components/smartthings/const.py @@ -24,6 +24,8 @@ SIGNAL_SMARTAPP_PREFIX = "smartthings_smartap_" SETTINGS_INSTANCE_ID = "hassInstanceId" +SUBSCRIPTION_WARNING_LIMIT = 40 + STORAGE_KEY = DOMAIN STORAGE_VERSION = 1 @@ -41,6 +43,12 @@ SUPPORTED_PLATFORMS = [ "scene", ] +IGNORED_CAPABILITIES = [ + "execute", + "healthCheck", + "ocf", +] + TOKEN_REFRESH_INTERVAL = timedelta(days=14) VAL_UID = "^(?:([0-9a-fA-F]{32})|([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}))$" diff --git a/homeassistant/components/smartthings/smartapp.py b/homeassistant/components/smartthings/smartapp.py index 918ee455c27..24d6e4ae18f 100644 --- a/homeassistant/components/smartthings/smartapp.py +++ b/homeassistant/components/smartthings/smartapp.py @@ -44,10 +44,12 @@ from .const import ( DATA_BROKERS, DATA_MANAGER, DOMAIN, + IGNORED_CAPABILITIES, SETTINGS_INSTANCE_ID, SIGNAL_SMARTAPP_PREFIX, STORAGE_KEY, STORAGE_VERSION, + SUBSCRIPTION_WARNING_LIMIT, ) _LOGGER = logging.getLogger(__name__) @@ -355,7 +357,26 @@ async def smartapp_sync_subscriptions( capabilities = set() for device in devices: capabilities.update(device.capabilities) + # Remove items not defined in the library capabilities.intersection_update(CAPABILITIES) + # Remove unused capabilities + capabilities.difference_update(IGNORED_CAPABILITIES) + capability_count = len(capabilities) + if capability_count > SUBSCRIPTION_WARNING_LIMIT: + _LOGGER.warning( + "Some device attributes may not receive push updates and there may be subscription " + "creation failures under app '%s' because %s subscriptions are required but " + "there is a limit of %s per app", + installed_app_id, + capability_count, + SUBSCRIPTION_WARNING_LIMIT, + ) + _LOGGER.debug( + "Synchronizing subscriptions for %s capabilities under app '%s': %s", + capability_count, + installed_app_id, + capabilities, + ) # Get current subscriptions and find differences subscriptions = await api.subscriptions(installed_app_id) diff --git a/tests/components/smartthings/test_smartapp.py b/tests/components/smartthings/test_smartapp.py index 458e5f8ce27..42215def82f 100644 --- a/tests/components/smartthings/test_smartapp.py +++ b/tests/components/smartthings/test_smartapp.py @@ -1,7 +1,7 @@ """Tests for the smartapp module.""" from uuid import uuid4 -from pysmartthings import AppEntity, Capability +from pysmartthings import CAPABILITIES, AppEntity, Capability from homeassistant.components.smartthings import smartapp from homeassistant.components.smartthings.const import ( @@ -89,7 +89,7 @@ async def test_smartapp_webhook(hass): async def test_smartapp_sync_subscriptions( hass, smartthings_mock, device_factory, subscription_factory ): - """Test synchronization adds and removes.""" + """Test synchronization adds and removes and ignores unused.""" smartthings_mock.subscriptions.return_value = [ subscription_factory(Capability.thermostat), subscription_factory(Capability.switch), @@ -98,7 +98,7 @@ async def test_smartapp_sync_subscriptions( devices = [ device_factory("", [Capability.battery, "ping"]), device_factory("", [Capability.switch, Capability.switch_level]), - device_factory("", [Capability.switch]), + device_factory("", [Capability.switch, Capability.execute]), ] await smartapp.smartapp_sync_subscriptions( @@ -134,6 +134,25 @@ async def test_smartapp_sync_subscriptions_up_to_date( assert smartthings_mock.create_subscription.call_count == 0 +async def test_smartapp_sync_subscriptions_limit_warning( + hass, smartthings_mock, device_factory, subscription_factory, caplog +): + """Test synchronization over the limit logs a warning.""" + smartthings_mock.subscriptions.return_value = [] + devices = [ + device_factory("", CAPABILITIES), + ] + + await smartapp.smartapp_sync_subscriptions( + hass, str(uuid4()), str(uuid4()), str(uuid4()), devices + ) + + assert ( + "Some device attributes may not receive push updates and there may be " + "subscription creation failures" in caplog.text + ) + + async def test_smartapp_sync_subscriptions_handles_exceptions( hass, smartthings_mock, device_factory, subscription_factory ):