Use entry_id for local data (fixes #10, #13)

This commit is contained in:
freybene 2024-06-19 09:11:56 +02:00
parent a2a9150a9b
commit 6e4285f824
6 changed files with 24 additions and 21 deletions

View file

@ -82,7 +82,7 @@ For support, please create an issue on the GitHub repository.
- ~~HACS support~~
- Service to let a device ring
- Service to make a device stop ringing (for devices that support this feature)
- Allow adding two instances of this integration (two Samsung Accounts)
- ~~Allow adding two instances of this integration (two Samsung Accounts)~~ ✅
## Disclaimer

View file

@ -23,6 +23,9 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up SmartThings Find from a config entry."""
hass.data[DOMAIN][entry.entry_id] = {}
# Load the jsessionid from the config and create a session from it
jsessionid = entry.data[CONF_JSESSIONID]
session = async_get_clientsession(hass)
@ -30,10 +33,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# This raises ConfigEntryAuthFailed-exception if failed. So if we
# can continue after fetch_csrf, we know that authentication was ok
await fetch_csrf(hass, session)
await fetch_csrf(hass, session, entry.entry_id)
# Load all SmartThings-Find devices from the users account
devices = await get_devices(hass, session)
devices = await get_devices(hass, session, entry.entry_id)
# Create an update coordinator. This is responsible to regularly
# fetch data from STF and update the device_tracker and sensor
@ -44,9 +47,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# seconds for my 15 devices) but it is the right way to do it. Only if
# it succeeds, the integration will be marked as successfully loaded.
await coordinator.async_config_entry_first_refresh()
hass.data[DOMAIN].update({
hass.data[DOMAIN][entry.entry_id].update({
CONF_JSESSIONID: jsessionid,
"session": session,
"coordinator": coordinator,
@ -62,7 +64,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
unload_success = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_success:
del hass.data[DOMAIN]
hass.data[DOMAIN].pop(entry.entry_id)
else:
_LOGGER.error(f"Unload failed: {unload_success}")
return unload_success
@ -90,7 +92,7 @@ class SmartThingsFindCoordinator(DataUpdateCoordinator):
_LOGGER.debug(f"Updating locations...")
for device in self.devices:
dev_data = device['data']
tag_data = await get_device_location(self.hass, self.session, dev_data)
tag_data = await get_device_location(self.hass, self.session, dev_data, self.config_entry.entry_id)
tags[dev_data['dvceID']] = tag_data
_LOGGER.debug(f"Fetched {len(tags)} locations")
return tags

View file

@ -13,7 +13,7 @@ _LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback) -> None:
"""Set up SmartThings Find button entities."""
devices = hass.data[DOMAIN]["devices"]
devices = hass.data[DOMAIN][entry.entry_id]["devices"]
entities = []
for device in devices:
entities += [RingButton(hass, device)]
@ -37,8 +37,9 @@ class RingButton(ButtonEntity):
async def async_press(self):
"""Handle the button press."""
session = self.hass.data[DOMAIN]["session"]
csrf_token = self.hass.data[DOMAIN]["_csrf"]
entry_id = self.registry_entry.config_entry_id
session = self.hass.data[DOMAIN][entry_id]["session"]
csrf_token = self.hass.data[DOMAIN][entry_id]["_csrf"]
ring_payload = {
"dvceId": self.device['dvceID'],
"operation": "RING",
@ -57,6 +58,6 @@ class RingButton(ButtonEntity):
_LOGGER.debug(f"Response: {await response.text()}")
else:
# Fetch a new CSRF token to make sure we're still logged in
await fetch_csrf(self.hass, session)
await fetch_csrf(self.hass, session, entry_id)
except Exception as e:
_LOGGER.error(f"Exception occurred while ringing '{self.device['modelName']}': %s", e)

View file

@ -13,8 +13,8 @@ _LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback) -> None:
"""Set up SmartThings Find device tracker entities."""
devices = hass.data[DOMAIN]["devices"]
coordinator = hass.data[DOMAIN]["coordinator"]
devices = hass.data[DOMAIN][entry.entry_id]["devices"]
coordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]
entities = []
for device in devices:
if 'subType' in device['data'] and device['data']['subType'] == 'CANAL2':

View file

@ -13,8 +13,8 @@ _LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback) -> None:
"""Set up SmartThings Find sensor entities."""
devices = hass.data[DOMAIN]["devices"]
coordinator = hass.data[DOMAIN]["coordinator"]
devices = hass.data[DOMAIN][entry.entry_id]["devices"]
coordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]
entities = []
for device in devices:
entities += [DeviceBatterySensor(hass, coordinator, device)]

View file

@ -193,7 +193,7 @@ async def do_login_stage_two(session: aiohttp.ClientSession) -> str:
_LOGGER.error(f"An error occurred during the login process (stage 2): {e}", exc_info=True)
return None
async def fetch_csrf(hass: HomeAssistant, session: aiohttp.ClientSession):
async def fetch_csrf(hass: HomeAssistant, session: aiohttp.ClientSession, entry_id: str):
"""
Retrieves the _csrf-Token which needs to be sent with each following request.
@ -212,7 +212,7 @@ async def fetch_csrf(hass: HomeAssistant, session: aiohttp.ClientSession):
if response.status == 200:
csrf_token = response.headers.get("_csrf")
if csrf_token:
hass.data[DOMAIN]["_csrf"] = csrf_token
hass.data[DOMAIN][entry_id]["_csrf"] = csrf_token
_LOGGER.info("Successfully fetched new CSRF Token")
return
else:
@ -226,7 +226,7 @@ async def fetch_csrf(hass: HomeAssistant, session: aiohttp.ClientSession):
raise ConfigEntryAuthFailed(err_msg)
async def get_devices(hass: HomeAssistant, session: aiohttp.ClientSession) -> list:
async def get_devices(hass: HomeAssistant, session: aiohttp.ClientSession, entry_id: str) -> list:
"""
Sends a request to the SmartThings Find API to retrieve a list of devices associated with the user's account.
@ -237,7 +237,7 @@ async def get_devices(hass: HomeAssistant, session: aiohttp.ClientSession) -> li
Returns:
list: A list of devices if successful, empty list otherwise.
"""
url = f"{URL_DEVICE_LIST}?_csrf={hass.data[DOMAIN]['_csrf']}"
url = f"{URL_DEVICE_LIST}?_csrf={hass.data[DOMAIN][entry_id]['_csrf']}"
async with session.post(url, headers = {'Accept': 'application/json'}, data={}) as response:
if response.status != 200:
_LOGGER.error(f"Failed to retrieve devices [{response.status}]: {await response.text()}")
@ -265,7 +265,7 @@ async def get_devices(hass: HomeAssistant, session: aiohttp.ClientSession) -> li
_LOGGER.debug(f"Adding device: {device['modelName']}")
return devices
async def get_device_location(hass: HomeAssistant, session: aiohttp.ClientSession, dev_data: dict) -> dict:
async def get_device_location(hass: HomeAssistant, session: aiohttp.ClientSession, dev_data: dict, entry_id: str) -> dict:
"""
Sends requests to update the device's location and retrieves the current location data for the specified device.
@ -291,7 +291,7 @@ async def get_device_location(hass: HomeAssistant, session: aiohttp.ClientSessio
"usrId": dev_data['usrId']
}
csrf_token = hass.data[DOMAIN]["_csrf"]
csrf_token = hass.data[DOMAIN][entry_id]["_csrf"]
try:
async with session.post(f"{URL_REQUEST_LOC_UPDATE}?_csrf={csrf_token}", json=update_payload) as response: