Remove old system ID format from SimpliSafe base stations (#82993)

This commit is contained in:
Aaron Bach 2022-11-30 14:10:56 -07:00 committed by GitHub
parent 4239923ea2
commit 671e6b3832
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 379 additions and 325 deletions

View File

@ -296,7 +296,8 @@ def _async_register_base_station(
) -> None: ) -> None:
"""Register a new bridge.""" """Register a new bridge."""
device_registry = dr.async_get(hass) device_registry = dr.async_get(hass)
device_registry.async_get_or_create(
base_station = device_registry.async_get_or_create(
config_entry_id=entry.entry_id, config_entry_id=entry.entry_id,
identifiers={(DOMAIN, str(system.system_id))}, identifiers={(DOMAIN, str(system.system_id))},
manufacturer="SimpliSafe", manufacturer="SimpliSafe",
@ -304,6 +305,20 @@ def _async_register_base_station(
name=system.address, name=system.address,
) )
# Check for an old system ID format and remove it:
if old_base_station := device_registry.async_get_device(
{(DOMAIN, system.system_id)} # type: ignore[arg-type]
):
# Update the new base station with any properties the user might have configured
# on the old base station:
device_registry.async_update_device(
base_station.id,
area_id=old_base_station.area_id,
disabled_by=old_base_station.disabled_by,
name_by_user=old_base_station.name_by_user,
)
device_registry.async_remove_device(old_base_station.id)
@callback @callback
def _async_standardize_config_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: def _async_standardize_config_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:

View File

@ -15,7 +15,7 @@ from tests.common import MockConfigEntry, load_fixture
CODE = "12345" CODE = "12345"
PASSWORD = "password" PASSWORD = "password"
SYSTEM_ID = "system_123" SYSTEM_ID = 12345
@pytest.fixture(name="api") @pytest.fixture(name="api")
@ -79,7 +79,8 @@ def data_settings_fixture():
@pytest.fixture(name="data_subscription", scope="package") @pytest.fixture(name="data_subscription", scope="package")
def data_subscription_fixture(): def data_subscription_fixture():
"""Define subscription data.""" """Define subscription data."""
return json.loads(load_fixture("subscription_data.json", "simplisafe")) data = json.loads(load_fixture("subscription_data.json", "simplisafe"))
return {SYSTEM_ID: data}
@pytest.fixture(name="reauth_config") @pytest.fixture(name="reauth_config")

View File

@ -1,335 +1,333 @@
{ {
"system_123": { "uid": 12345,
"sid": 12345,
"sStatus": 20,
"activated": 1445034752,
"planSku": "SSEDSM2",
"planName": "Interactive Monitoring",
"price": 24.99,
"currency": "USD",
"country": "US",
"expires": 1602887552,
"canceled": 0,
"extraTime": 0,
"creditCard": {
"lastFour": "",
"type": "",
"ppid": "ABCDE12345",
"uid": 12345
},
"time": 2628000,
"paymentProfileId": "ABCDE12345",
"features": {
"monitoring": true,
"alerts": true,
"online": true,
"hazard": true,
"video": true,
"cameras": 10,
"dispatch": true,
"proInstall": false,
"discount": 0,
"vipCS": false,
"medical": true,
"careVisit": false,
"storageDays": 30
},
"status": {
"hasBaseStation": true,
"isActive": true,
"monitoring": "Active"
},
"subscriptionFeatures": {
"monitoredSensorsTypes": [
"Entry",
"Motion",
"GlassBreak",
"Smoke",
"CO",
"Freeze",
"Water"
],
"monitoredPanicConditions": ["Fire", "Medical", "Duress"],
"dispatchTypes": ["Police", "Fire", "Medical", "Guard"],
"remoteControl": [
"ArmDisarm",
"LockUnlock",
"ViewSettings",
"ConfigureSettings"
],
"cameraFeatures": {
"liveView": true,
"maxRecordingCameras": 10,
"recordingStorageDays": 30,
"videoVerification": true
},
"support": {
"level": "Basic",
"annualVisit": false,
"professionalInstall": false
},
"cellCommunicationBackup": true,
"alertChannels": ["Push", "SMS", "Email"],
"alertTypes": ["Alarm", "Error", "Activity", "Camera"],
"alarmModes": ["Alarm", "SecretAlert", "Disabled"],
"supportedIntegrations": ["GoogleAssistant", "AmazonAlexa", "AugustLock"],
"timeline": {}
},
"dispatcher": "cops",
"dcid": 0,
"location": {
"sid": 12345,
"uid": 12345, "uid": 12345,
"sid": "system_123", "lStatus": 10,
"sStatus": 20, "account": "1234ABCD",
"activated": 1445034752, "street1": "1234 Main Street",
"planSku": "SSEDSM2", "street2": "",
"planName": "Interactive Monitoring", "locationName": "",
"price": 24.99, "city": "Atlantis",
"currency": "USD", "county": "SEA",
"state": "UW",
"zip": "12345",
"country": "US", "country": "US",
"expires": 1602887552, "crossStreet": "River 1 and River 2",
"canceled": 0, "notes": "",
"extraTime": 0, "residenceType": 2,
"creditCard": { "numAdults": 2,
"lastFour": "", "numChildren": 0,
"type": "", "locationOffset": -360,
"ppid": "ABCDE12345", "safeWord": "TRITON",
"uid": 12345 "signature": "Atlantis Citizen 1",
}, "timeZone": 2,
"time": 2628000, "primaryContacts": [
"paymentProfileId": "ABCDE12345", {
"features": { "name": "John Doe",
"monitoring": true, "phone": "1234567890"
"alerts": true, }
"online": true, ],
"hazard": true, "secondaryContacts": [
"video": true, {
"cameras": 10, "name": "Jane Doe",
"dispatch": true, "phone": "9876543210"
"proInstall": false, }
"discount": 0, ],
"vipCS": false, "copsOptIn": false,
"medical": true, "certificateUri": "https://simplisafe.com/account2/12345/alarm-certificate/12345",
"careVisit": false, "nestStructureId": "",
"storageDays": 30 "system": {
}, "serial": "1234ABCD",
"status": { "alarmState": "OFF",
"hasBaseStation": true, "alarmStateTimestamp": 0,
"isActive": true, "isAlarming": false,
"monitoring": "Active" "version": 3,
}, "capabilities": {
"subscriptionFeatures": { "setWifiOverCell": true,
"monitoredSensorsTypes": [ "setDoorbellChimeVolume": true,
"Entry", "outdoorBattCamera": true
"Motion",
"GlassBreak",
"Smoke",
"CO",
"Freeze",
"Water"
],
"monitoredPanicConditions": ["Fire", "Medical", "Duress"],
"dispatchTypes": ["Police", "Fire", "Medical", "Guard"],
"remoteControl": [
"ArmDisarm",
"LockUnlock",
"ViewSettings",
"ConfigureSettings"
],
"cameraFeatures": {
"liveView": true,
"maxRecordingCameras": 10,
"recordingStorageDays": 30,
"videoVerification": true
}, },
"support": { "temperature": 67,
"level": "Basic", "exitDelayRemaining": 60,
"annualVisit": false, "cameras": [
"professionalInstall": false
},
"cellCommunicationBackup": true,
"alertChannels": ["Push", "SMS", "Email"],
"alertTypes": ["Alarm", "Error", "Activity", "Camera"],
"alarmModes": ["Alarm", "SecretAlert", "Disabled"],
"supportedIntegrations": ["GoogleAssistant", "AmazonAlexa", "AugustLock"],
"timeline": {}
},
"dispatcher": "cops",
"dcid": 0,
"location": {
"sid": 12345,
"uid": 12345,
"lStatus": 10,
"account": "1234ABCD",
"street1": "1234 Main Street",
"street2": "",
"locationName": "",
"city": "Atlantis",
"county": "SEA",
"state": "UW",
"zip": "12345",
"country": "US",
"crossStreet": "River 1 and River 2",
"notes": "",
"residenceType": 2,
"numAdults": 2,
"numChildren": 0,
"locationOffset": -360,
"safeWord": "TRITON",
"signature": "Atlantis Citizen 1",
"timeZone": 2,
"primaryContacts": [
{ {
"name": "John Doe", "staleSettingsTypes": [],
"phone": "1234567890" "upgradeWhitelisted": false,
} "model": "SS001",
], "uuid": "1234567890",
"secondaryContacts": [ "uid": 12345,
{ "sid": 12345,
"name": "Jane Doe", "cameraSettings": {
"phone": "9876543210" "cameraName": "Camera",
} "pictureQuality": "720p",
], "nightVision": "auto",
"copsOptIn": false, "statusLight": "off",
"certificateUri": "https://simplisafe.com/account2/12345/alarm-certificate/12345", "micSensitivity": 100,
"nestStructureId": "", "micEnable": true,
"system": { "speakerVolume": 75,
"serial": "1234ABCD", "motionSensitivity": 0,
"alarmState": "OFF", "shutterHome": "closedAlarmOnly",
"alarmStateTimestamp": 0, "shutterAway": "open",
"isAlarming": false, "shutterOff": "closedAlarmOnly",
"version": 3, "wifiSsid": "",
"capabilities": { "canStream": false,
"setWifiOverCell": true, "canRecord": false,
"setDoorbellChimeVolume": true, "pirEnable": true,
"outdoorBattCamera": true "vaEnable": true,
}, "notificationsEnable": false,
"temperature": 67, "enableDoorbellNotification": true,
"exitDelayRemaining": 60, "doorbellChimeVolume": "off",
"cameras": [ "privacyEnable": false,
{ "hdr": false,
"staleSettingsTypes": [], "vaZoningEnable": false,
"upgradeWhitelisted": false, "vaZoningRows": 0,
"model": "SS001", "vaZoningCols": 0,
"uuid": "1234567890", "vaZoningMask": [],
"uid": 12345, "maxDigitalZoom": 10,
"sid": 12345, "supportedResolutions": ["480p", "720p"],
"cameraSettings": { "admin": {
"cameraName": "Camera", "IRLED": 0,
"pictureQuality": "720p", "pirSens": 0,
"nightVision": "auto", "statusLEDState": 1,
"statusLight": "off", "lux": "lowLux",
"micSensitivity": 100, "motionDetectionEnabled": false,
"micEnable": true, "motionThresholdZero": 0,
"speakerVolume": 75, "motionThresholdOne": 10000,
"motionSensitivity": 0, "levelChangeDelayZero": 30,
"shutterHome": "closedAlarmOnly", "levelChangeDelayOne": 10,
"shutterAway": "open", "audioDetectionEnabled": false,
"shutterOff": "closedAlarmOnly", "audioChannelNum": 2,
"wifiSsid": "", "audioSampleRate": 16000,
"canStream": false, "audioChunkBytes": 2048,
"canRecord": false, "audioSampleFormat": 3,
"pirEnable": true, "audioSensitivity": 50,
"vaEnable": true, "audioThreshold": 50,
"notificationsEnable": false, "audioDirection": 0,
"enableDoorbellNotification": true, "bitRate": 284,
"doorbellChimeVolume": "off", "longPress": 2000,
"privacyEnable": false, "kframe": 1,
"hdr": false, "gopLength": 40,
"vaZoningEnable": false, "idr": 1,
"vaZoningRows": 0, "fps": 20,
"vaZoningCols": 0,
"vaZoningMask": [],
"maxDigitalZoom": 10,
"supportedResolutions": ["480p", "720p"],
"admin": {
"IRLED": 0,
"pirSens": 0,
"statusLEDState": 1,
"lux": "lowLux",
"motionDetectionEnabled": false,
"motionThresholdZero": 0,
"motionThresholdOne": 10000,
"levelChangeDelayZero": 30,
"levelChangeDelayOne": 10,
"audioDetectionEnabled": false,
"audioChannelNum": 2,
"audioSampleRate": 16000,
"audioChunkBytes": 2048,
"audioSampleFormat": 3,
"audioSensitivity": 50,
"audioThreshold": 50,
"audioDirection": 0,
"bitRate": 284,
"longPress": 2000,
"kframe": 1,
"gopLength": 40,
"idr": 1,
"fps": 20,
"firmwareVersion": "2.6.1.107",
"netConfigVersion": "",
"camAgentVersion": "",
"lastLogin": 1600639997,
"lastLogout": 1600639944,
"pirSampleRateMs": 800,
"pirHysteresisHigh": 2,
"pirHysteresisLow": 10,
"pirFilterCoefficient": 1,
"logEnabled": true,
"logLevel": 3,
"logQDepth": 20,
"firmwareGroup": "public",
"irOpenThreshold": 445,
"irCloseThreshold": 840,
"irOpenDelay": 3,
"irCloseDelay": 3,
"irThreshold1x": 388,
"irThreshold2x": 335,
"irThreshold3x": 260,
"rssi": [[1600935204, -43]],
"battery": [],
"dbm": 0,
"vmUse": 161592,
"resSet": 10540,
"uptime": 810043.74,
"wifiDisconnects": 1,
"wifiDriverReloads": 1,
"statsPeriod": 3600000,
"sarlaccDebugLogTypes": 0,
"odProcessingFps": 8,
"odObjectMinWidthPercent": 6,
"odObjectMinHeightPercent": 24,
"odEnableObjectDetection": true,
"odClassificationMask": 2,
"odClassificationConfidenceThreshold": 0.95,
"odEnableOverlay": false,
"odAnalyticsLib": 2,
"odSensitivity": 85,
"odEventObjectMask": 2,
"odLuxThreshold": 445,
"odLuxHysteresisHigh": 4,
"odLuxHysteresisLow": 4,
"odLuxSamplingFrequency": 30,
"odFGExtractorMode": 2,
"odVideoScaleFactor": 1,
"odSceneType": 1,
"odCameraView": 3,
"odCameraFOV": 2,
"odBackgroundLearnStationary": true,
"odBackgroundLearnStationarySpeed": 15,
"odClassifierQualityProfile": 1,
"odEnableVideoAnalyticsWhileStreaming": false,
"wlanMac": "XX:XX:XX:XX:XX:XX",
"region": "us-east-1",
"enableWifiAnalyticsLib": false,
"ivLicense": ""
},
"pirLevel": "medium",
"odLevel": "medium"
},
"__v": 0,
"cameraStatus": {
"firmwareVersion": "2.6.1.107", "firmwareVersion": "2.6.1.107",
"netConfigVersion": "", "netConfigVersion": "",
"camAgentVersion": "", "camAgentVersion": "",
"lastLogin": 1600639997, "lastLogin": 1600639997,
"lastLogout": 1600639944, "lastLogout": 1600639944,
"pirSampleRateMs": 800,
"pirHysteresisHigh": 2,
"pirHysteresisLow": 10,
"pirFilterCoefficient": 1,
"logEnabled": true,
"logLevel": 3,
"logQDepth": 20,
"firmwareGroup": "public",
"irOpenThreshold": 445,
"irCloseThreshold": 840,
"irOpenDelay": 3,
"irCloseDelay": 3,
"irThreshold1x": 388,
"irThreshold2x": 335,
"irThreshold3x": 260,
"rssi": [[1600935204, -43]],
"battery": [],
"dbm": 0,
"vmUse": 161592,
"resSet": 10540,
"uptime": 810043.74,
"wifiDisconnects": 1,
"wifiDriverReloads": 1,
"statsPeriod": 3600000,
"sarlaccDebugLogTypes": 0,
"odProcessingFps": 8,
"odObjectMinWidthPercent": 6,
"odObjectMinHeightPercent": 24,
"odEnableObjectDetection": true,
"odClassificationMask": 2,
"odClassificationConfidenceThreshold": 0.95,
"odEnableOverlay": false,
"odAnalyticsLib": 2,
"odSensitivity": 85,
"odEventObjectMask": 2,
"odLuxThreshold": 445,
"odLuxHysteresisHigh": 4,
"odLuxHysteresisLow": 4,
"odLuxSamplingFrequency": 30,
"odFGExtractorMode": 2,
"odVideoScaleFactor": 1,
"odSceneType": 1,
"odCameraView": 3,
"odCameraFOV": 2,
"odBackgroundLearnStationary": true,
"odBackgroundLearnStationarySpeed": 15,
"odClassifierQualityProfile": 1,
"odEnableVideoAnalyticsWhileStreaming": false,
"wlanMac": "XX:XX:XX:XX:XX:XX", "wlanMac": "XX:XX:XX:XX:XX:XX",
"fwDownloadVersion": "", "region": "us-east-1",
"fwDownloadPercentage": 0, "enableWifiAnalyticsLib": false,
"recovered": false, "ivLicense": ""
"recoveredFromVersion": "",
"_id": "1234567890",
"initErrors": [],
"speedTestTokenCreated": 1600235629
}, },
"supportedFeatures": { "pirLevel": "medium",
"providers": { "odLevel": "medium"
"webrtc": "none", },
"recording": "simplisafe", "__v": 0,
"live": "simplisafe" "cameraStatus": {
}, "firmwareVersion": "2.6.1.107",
"audioEncodings": ["speex"], "netConfigVersion": "",
"resolutions": ["480p", "720p"], "camAgentVersion": "",
"_id": "1234567890", "lastLogin": 1600639997,
"pir": true, "lastLogout": 1600639944,
"videoAnalytics": false, "wlanMac": "XX:XX:XX:XX:XX:XX",
"privacyShutter": true, "fwDownloadVersion": "",
"microphone": true, "fwDownloadPercentage": 0,
"fullDuplexAudio": false, "recovered": false,
"wired": true, "recoveredFromVersion": "",
"networkSpeedTest": false, "_id": "1234567890",
"videoEncoding": "h264" "initErrors": [],
"speedTestTokenCreated": 1600235629
},
"supportedFeatures": {
"providers": {
"webrtc": "none",
"recording": "simplisafe",
"live": "simplisafe"
}, },
"subscription": { "audioEncodings": ["speex"],
"enabled": true, "resolutions": ["480p", "720p"],
"freeTrialActive": false, "_id": "1234567890",
"freeTrialUsed": true, "pir": true,
"freeTrialEnds": 0, "videoAnalytics": false,
"freeTrialExpires": 0, "privacyShutter": true,
"planSku": "SSVM1", "microphone": true,
"price": 0, "fullDuplexAudio": false,
"expires": 0, "wired": true,
"storageDays": 30, "networkSpeedTest": false,
"trialUsed": true, "videoEncoding": "h264"
"trialActive": false, },
"trialExpires": 0 "subscription": {
}, "enabled": true,
"status": "online" "freeTrialActive": false,
} "freeTrialUsed": true,
], "freeTrialEnds": 0,
"connType": "wifi", "freeTrialExpires": 0,
"stateUpdated": 1601502948, "planSku": "SSVM1",
"messages": [ "price": 0,
{ "expires": 0,
"_id": "xxxxxxxxxxxxxxxxxxxxxxxx", "storageDays": 30,
"id": "xxxxxxxxxxxxxxxxxxxxxxxx", "trialUsed": true,
"textTemplate": "Power Outage - Backup battery in use.", "trialActive": false,
"data": { "trialExpires": 0
"time": "2020-02-16T03:20:28+00:00" },
}, "status": "online"
"text": "Power Outage - Backup battery in use.", }
"code": "2000", ],
"filters": [], "connType": "wifi",
"link": "http://link.to.info", "stateUpdated": 1601502948,
"linkLabel": "More Info", "messages": [
"expiration": 0, {
"category": "error", "_id": "xxxxxxxxxxxxxxxxxxxxxxxx",
"timestamp": 1581823228 "id": "xxxxxxxxxxxxxxxxxxxxxxxx",
} "textTemplate": "Power Outage - Backup battery in use.",
], "data": {
"powerOutage": false, "time": "2020-02-16T03:20:28+00:00"
"lastPowerOutage": 1581991064, },
"lastSuccessfulWifiTS": 1601424776, "text": "Power Outage - Backup battery in use.",
"isOffline": false "code": "2000",
} "filters": [],
}, "link": "http://link.to.info",
"pinUnlocked": true, "linkLabel": "More Info",
"billDate": 1602887552, "expiration": 0,
"billInterval": 2628000, "category": "error",
"pinUnlockedBy": "pin", "timestamp": 1581823228
"autoActivation": null }
} ],
"powerOutage": false,
"lastPowerOutage": 1581991064,
"lastSuccessfulWifiTS": 1601424776,
"isOffline": false
}
},
"pinUnlocked": true,
"billDate": 1602887552,
"billInterval": 2628000,
"pinUnlockedBy": "pin",
"autoActivation": null
} }

View File

@ -21,7 +21,7 @@ async def test_entry_diagnostics(hass, config_entry, hass_client, setup_simplisa
"disabled_by": None, "disabled_by": None,
}, },
"subscription_data": { "subscription_data": {
"system_123": { "12345": {
"uid": REDACTED, "uid": REDACTED,
"sid": REDACTED, "sid": REDACTED,
"sStatus": 20, "sStatus": 20,

View File

@ -0,0 +1,40 @@
"""Define tests for SimpliSafe setup."""
from unittest.mock import patch
from homeassistant.components.simplisafe import DOMAIN
from homeassistant.helpers import device_registry as dr
from homeassistant.setup import async_setup_component
async def test_base_station_migration(hass, api, config, config_entry):
"""Test that errors are shown when duplicates are added."""
old_identifers = (DOMAIN, 12345)
new_identifiers = (DOMAIN, "12345")
device_registry = dr.async_get(hass)
device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
identifiers={old_identifers},
manufacturer="SimpliSafe",
name="old",
)
with patch(
"homeassistant.components.simplisafe.config_flow.API.async_from_auth",
return_value=api,
), patch(
"homeassistant.components.simplisafe.API.async_from_auth",
return_value=api,
), patch(
"homeassistant.components.simplisafe.API.async_from_refresh_token",
return_value=api,
), patch(
"homeassistant.components.simplisafe.SimpliSafe._async_start_websocket_loop"
), patch(
"homeassistant.components.simplisafe.PLATFORMS", []
):
assert await async_setup_component(hass, DOMAIN, config)
await hass.async_block_till_done()
assert device_registry.async_get_device(identifiers={old_identifers}) is None
assert device_registry.async_get_device(identifiers={new_identifiers}) is not None