113 lines
4.7 KiB
Python
113 lines
4.7 KiB
Python
import json
|
|
import logging
|
|
from homeassistant.components.device_tracker.config_entry import TrackerEntity as DeviceTrackerEntity
|
|
from homeassistant.components.device_tracker.const import SourceType
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from .const import DOMAIN, BATTERY_LEVELS
|
|
from .utils import get_sub_location, get_battery_level
|
|
|
|
_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"]
|
|
entities = []
|
|
for device in devices:
|
|
if 'subType' in device['data'] and device['data']['subType'] == 'CANAL2':
|
|
entities += [SmartThingsDeviceTracker(hass, coordinator, device, "left")]
|
|
entities += [SmartThingsDeviceTracker(hass, coordinator, device, "right")]
|
|
entities += [SmartThingsDeviceTracker(hass, coordinator, device)]
|
|
async_add_entities(entities)
|
|
|
|
class SmartThingsDeviceTracker(DeviceTrackerEntity):
|
|
"""Representation of a SmartTag device tracker."""
|
|
|
|
def __init__(self, hass: HomeAssistant, coordinator, device, subDeviceName=None):
|
|
"""Initialize the device tracker."""
|
|
|
|
self.coordinator = coordinator
|
|
self.hass = hass
|
|
self.device = device['data']
|
|
self.device_id = device['data']['dvceID']
|
|
self.subDeviceName = subDeviceName
|
|
|
|
self._attr_unique_id = f"stf_device_tracker_{device['data']['dvceID']}{'_' + subDeviceName if subDeviceName else ''}"
|
|
self._attr_name = device['data']['modelName'] + (' ' + subDeviceName.capitalize() if subDeviceName else '')
|
|
self._attr_device_info = device['ha_dev_info']
|
|
self._attr_latitude = None
|
|
self._attr_longitude = None
|
|
|
|
if 'icons' in device['data'] and 'coloredIcon' in device['data']['icons']:
|
|
self._attr_entity_picture = device['data']['icons']['coloredIcon']
|
|
|
|
self.async_update = coordinator.async_add_listener(self.async_write_ha_state)
|
|
|
|
@property
|
|
def available(self) -> bool:
|
|
"""Return true if the device is available."""
|
|
tag_data = self.coordinator.data.get(self.device_id, {})
|
|
if not tag_data:
|
|
_LOGGER.info(f"tag_data none for '{self.name}'; rendering state unavailable")
|
|
return False
|
|
if not tag_data['update_success']:
|
|
_LOGGER.info(f"Last update for '{self.name}' failed; rendering state unavailable")
|
|
return False
|
|
return True
|
|
|
|
@property
|
|
def source_type(self) -> str:
|
|
return SourceType.GPS
|
|
|
|
@property
|
|
def latitude(self):
|
|
"""Return the latitude of the device."""
|
|
data = self.coordinator.data.get(self.device_id, {})
|
|
if not self.subDeviceName:
|
|
if data['location_found']: return data.get('used_loc', {}).get('latitude', None)
|
|
return None
|
|
else:
|
|
_, loc = get_sub_location(data['ops'], self.subDeviceName)
|
|
return loc.get('latitude', None)
|
|
|
|
@property
|
|
def longitude(self):
|
|
"""Return the longitude of the device."""
|
|
data = self.coordinator.data.get(self.device_id, {})
|
|
if not self.subDeviceName:
|
|
if data['location_found']: return data.get('used_loc', {}).get('longitude', None)
|
|
return None
|
|
else:
|
|
_, loc = get_sub_location(data['ops'], self.subDeviceName)
|
|
return loc.get('longitude', None)
|
|
|
|
@property
|
|
def location_accuracy(self):
|
|
"""Return the location accuracy of the device."""
|
|
data = self.coordinator.data.get(self.device_id, {})
|
|
if not self.subDeviceName:
|
|
if data['location_found']: return data.get('used_loc', {}).get('gps_accuracy', None)
|
|
return None
|
|
else:
|
|
_, loc = get_sub_location(data['ops'], self.subDeviceName)
|
|
return loc.get('gps_accuracy', None)
|
|
|
|
@property
|
|
def battery_level(self):
|
|
"""Return the battery level of the device."""
|
|
data = self.coordinator.data.get(self.device_id, {})
|
|
if self.subDeviceName:
|
|
return None
|
|
return get_battery_level(self.name, data['ops'])
|
|
|
|
@property
|
|
def extra_state_attributes(self):
|
|
tag_data = self.coordinator.data.get(self.device_id, {})
|
|
device_data = self.device
|
|
if self.subDeviceName:
|
|
used_op, used_loc = get_sub_location(tag_data['ops'], self.subDeviceName)
|
|
tag_data = tag_data | used_op | used_loc
|
|
return tag_data | device_data
|