parent
a2a9150a9b
commit
6e4285f824
6 changed files with 24 additions and 21 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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':
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue