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~~ - ~~HACS support~~
- Service to let a device ring - Service to let a device ring
- Service to make a device stop ringing (for devices that support this feature) - 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 ## 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: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up SmartThings Find from a config entry.""" """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 # Load the jsessionid from the config and create a session from it
jsessionid = entry.data[CONF_JSESSIONID] jsessionid = entry.data[CONF_JSESSIONID]
session = async_get_clientsession(hass) 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 # This raises ConfigEntryAuthFailed-exception if failed. So if we
# can continue after fetch_csrf, we know that authentication was ok # 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 # 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 # Create an update coordinator. This is responsible to regularly
# fetch data from STF and update the device_tracker and sensor # 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 # 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. # it succeeds, the integration will be marked as successfully loaded.
await coordinator.async_config_entry_first_refresh() await coordinator.async_config_entry_first_refresh()
hass.data[DOMAIN].update({ hass.data[DOMAIN][entry.entry_id].update({
CONF_JSESSIONID: jsessionid, CONF_JSESSIONID: jsessionid,
"session": session, "session": session,
"coordinator": coordinator, "coordinator": coordinator,
@ -62,7 +64,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry.""" """Unload a config entry."""
unload_success = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) unload_success = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_success: if unload_success:
del hass.data[DOMAIN] hass.data[DOMAIN].pop(entry.entry_id)
else: else:
_LOGGER.error(f"Unload failed: {unload_success}") _LOGGER.error(f"Unload failed: {unload_success}")
return unload_success return unload_success
@ -90,7 +92,7 @@ class SmartThingsFindCoordinator(DataUpdateCoordinator):
_LOGGER.debug(f"Updating locations...") _LOGGER.debug(f"Updating locations...")
for device in self.devices: for device in self.devices:
dev_data = device['data'] 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 tags[dev_data['dvceID']] = tag_data
_LOGGER.debug(f"Fetched {len(tags)} locations") _LOGGER.debug(f"Fetched {len(tags)} locations")
return tags 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: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback) -> None:
"""Set up SmartThings Find button entities.""" """Set up SmartThings Find button entities."""
devices = hass.data[DOMAIN]["devices"] devices = hass.data[DOMAIN][entry.entry_id]["devices"]
entities = [] entities = []
for device in devices: for device in devices:
entities += [RingButton(hass, device)] entities += [RingButton(hass, device)]
@ -37,8 +37,9 @@ class RingButton(ButtonEntity):
async def async_press(self): async def async_press(self):
"""Handle the button press.""" """Handle the button press."""
session = self.hass.data[DOMAIN]["session"] entry_id = self.registry_entry.config_entry_id
csrf_token = self.hass.data[DOMAIN]["_csrf"] session = self.hass.data[DOMAIN][entry_id]["session"]
csrf_token = self.hass.data[DOMAIN][entry_id]["_csrf"]
ring_payload = { ring_payload = {
"dvceId": self.device['dvceID'], "dvceId": self.device['dvceID'],
"operation": "RING", "operation": "RING",
@ -57,6 +58,6 @@ class RingButton(ButtonEntity):
_LOGGER.debug(f"Response: {await response.text()}") _LOGGER.debug(f"Response: {await response.text()}")
else: else:
# Fetch a new CSRF token to make sure we're still logged in # 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: except Exception as e:
_LOGGER.error(f"Exception occurred while ringing '{self.device['modelName']}': %s", 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: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback) -> None:
"""Set up SmartThings Find device tracker entities.""" """Set up SmartThings Find device tracker entities."""
devices = hass.data[DOMAIN]["devices"] devices = hass.data[DOMAIN][entry.entry_id]["devices"]
coordinator = hass.data[DOMAIN]["coordinator"] coordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]
entities = [] entities = []
for device in devices: for device in devices:
if 'subType' in device['data'] and device['data']['subType'] == 'CANAL2': 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: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback) -> None:
"""Set up SmartThings Find sensor entities.""" """Set up SmartThings Find sensor entities."""
devices = hass.data[DOMAIN]["devices"] devices = hass.data[DOMAIN][entry.entry_id]["devices"]
coordinator = hass.data[DOMAIN]["coordinator"] coordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]
entities = [] entities = []
for device in devices: for device in devices:
entities += [DeviceBatterySensor(hass, coordinator, device)] 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) _LOGGER.error(f"An error occurred during the login process (stage 2): {e}", exc_info=True)
return None 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. 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: if response.status == 200:
csrf_token = response.headers.get("_csrf") csrf_token = response.headers.get("_csrf")
if csrf_token: if csrf_token:
hass.data[DOMAIN]["_csrf"] = csrf_token hass.data[DOMAIN][entry_id]["_csrf"] = csrf_token
_LOGGER.info("Successfully fetched new CSRF Token") _LOGGER.info("Successfully fetched new CSRF Token")
return return
else: else:
@ -226,7 +226,7 @@ async def fetch_csrf(hass: HomeAssistant, session: aiohttp.ClientSession):
raise ConfigEntryAuthFailed(err_msg) 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. 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: Returns:
list: A list of devices if successful, empty list otherwise. 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: async with session.post(url, headers = {'Accept': 'application/json'}, data={}) as response:
if response.status != 200: if response.status != 200:
_LOGGER.error(f"Failed to retrieve devices [{response.status}]: {await response.text()}") _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']}") _LOGGER.debug(f"Adding device: {device['modelName']}")
return devices 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. 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'] "usrId": dev_data['usrId']
} }
csrf_token = hass.data[DOMAIN]["_csrf"] csrf_token = hass.data[DOMAIN][entry_id]["_csrf"]
try: try:
async with session.post(f"{URL_REQUEST_LOC_UPDATE}?_csrf={csrf_token}", json=update_payload) as response: async with session.post(f"{URL_REQUEST_LOC_UPDATE}?_csrf={csrf_token}", json=update_payload) as response: