mirror of https://github.com/home-assistant/core
Add binary sensor entities to Traccar Server (#114719)
This commit is contained in:
parent
2beab34de8
commit
f83ee963bf
|
@ -30,7 +30,11 @@ from .const import (
|
|||
)
|
||||
from .coordinator import TraccarServerCoordinator
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.DEVICE_TRACKER, Platform.SENSOR]
|
||||
PLATFORMS: list[Platform] = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.DEVICE_TRACKER,
|
||||
Platform.SENSOR,
|
||||
]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
"""Support for Traccar server binary sensors."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Generic, Literal, TypeVar, cast
|
||||
|
||||
from pytraccar import DeviceModel
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorDeviceClass,
|
||||
BinarySensorEntity,
|
||||
BinarySensorEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import TraccarServerCoordinator
|
||||
from .entity import TraccarServerEntity
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class TraccarServerBinarySensorEntityDescription(
|
||||
Generic[_T], BinarySensorEntityDescription
|
||||
):
|
||||
"""Describe Traccar Server sensor entity."""
|
||||
|
||||
data_key: Literal["position", "device", "geofence", "attributes"]
|
||||
entity_registry_enabled_default = False
|
||||
entity_category = EntityCategory.DIAGNOSTIC
|
||||
value_fn: Callable[[_T], bool | None]
|
||||
|
||||
|
||||
TRACCAR_SERVER_BINARY_SENSOR_ENTITY_DESCRIPTIONS = (
|
||||
TraccarServerBinarySensorEntityDescription[DeviceModel](
|
||||
key="attributes.motion",
|
||||
data_key="position",
|
||||
translation_key="motion",
|
||||
device_class=BinarySensorDeviceClass.MOTION,
|
||||
value_fn=lambda x: x["attributes"].get("motion", False),
|
||||
),
|
||||
TraccarServerBinarySensorEntityDescription[DeviceModel](
|
||||
key="status",
|
||||
data_key="device",
|
||||
translation_key="status",
|
||||
value_fn=lambda x: None if (s := x["status"]) == "unknown" else s == "online",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up binary sensor entities."""
|
||||
coordinator: TraccarServerCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
async_add_entities(
|
||||
TraccarServerBinarySensor(
|
||||
coordinator=coordinator,
|
||||
device=entry["device"],
|
||||
description=cast(TraccarServerBinarySensorEntityDescription, description),
|
||||
)
|
||||
for entry in coordinator.data.values()
|
||||
for description in TRACCAR_SERVER_BINARY_SENSOR_ENTITY_DESCRIPTIONS
|
||||
)
|
||||
|
||||
|
||||
class TraccarServerBinarySensor(TraccarServerEntity, BinarySensorEntity):
|
||||
"""Represent a traccar server binary sensor."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
entity_description: TraccarServerBinarySensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: TraccarServerCoordinator,
|
||||
device: DeviceModel,
|
||||
description: TraccarServerBinarySensorEntityDescription[_T],
|
||||
) -> None:
|
||||
"""Initialize the Traccar Server sensor."""
|
||||
super().__init__(coordinator, device)
|
||||
self.entity_description = description
|
||||
self._attr_unique_id = (
|
||||
f"{device['uniqueId']}_{description.data_key}_{description.key}"
|
||||
)
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return if the binary sensor is on or not."""
|
||||
return self.entity_description.value_fn(
|
||||
getattr(self, f"traccar_{self.entity_description.data_key}")
|
||||
)
|
|
@ -9,14 +9,7 @@ from homeassistant.config_entries import ConfigEntry
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import (
|
||||
ATTR_CATEGORY,
|
||||
ATTR_MOTION,
|
||||
ATTR_STATUS,
|
||||
ATTR_TRACCAR_ID,
|
||||
ATTR_TRACKER,
|
||||
DOMAIN,
|
||||
)
|
||||
from .const import ATTR_CATEGORY, ATTR_TRACCAR_ID, ATTR_TRACKER, DOMAIN
|
||||
from .coordinator import TraccarServerCoordinator
|
||||
from .entity import TraccarServerEntity
|
||||
|
||||
|
@ -46,8 +39,6 @@ class TraccarServerDeviceTracker(TraccarServerEntity, TrackerEntity):
|
|||
return {
|
||||
**self.traccar_attributes,
|
||||
ATTR_CATEGORY: self.traccar_device["category"],
|
||||
ATTR_MOTION: self.traccar_position["attributes"].get("motion", False),
|
||||
ATTR_STATUS: self.traccar_device["status"],
|
||||
ATTR_TRACCAR_ID: self.traccar_device["id"],
|
||||
ATTR_TRACKER: DOMAIN,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
{
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"status": {
|
||||
"default": "mdi:access-point-minus",
|
||||
"state": {
|
||||
"off": "mdi:access-point-off",
|
||||
"on": "mdi:access-point"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"altitude": {
|
||||
"default": "mdi:altimeter"
|
||||
|
|
|
@ -43,6 +43,22 @@
|
|||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"motion": {
|
||||
"name": "Motion",
|
||||
"state": {
|
||||
"off": "Stopped",
|
||||
"on": "Moving"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"name": "Status",
|
||||
"state": {
|
||||
"off": "Offline",
|
||||
"on": "Online"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"address": {
|
||||
"name": "Address"
|
||||
|
|
|
@ -82,9 +82,7 @@
|
|||
'gps_accuracy': 3.5,
|
||||
'latitude': '**REDACTED**',
|
||||
'longitude': '**REDACTED**',
|
||||
'motion': False,
|
||||
'source_type': 'gps',
|
||||
'status': 'online',
|
||||
'traccar_id': 0,
|
||||
'tracker': 'traccar_server',
|
||||
}),
|
||||
|
@ -92,6 +90,29 @@
|
|||
}),
|
||||
'unit_of_measurement': None,
|
||||
}),
|
||||
dict({
|
||||
'disabled': False,
|
||||
'enity_id': 'binary_sensor.x_wing_motion',
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
'device_class': 'motion',
|
||||
'friendly_name': 'X-Wing Motion',
|
||||
}),
|
||||
'state': 'off',
|
||||
}),
|
||||
'unit_of_measurement': None,
|
||||
}),
|
||||
dict({
|
||||
'disabled': False,
|
||||
'enity_id': 'binary_sensor.x_wing_status',
|
||||
'state': dict({
|
||||
'attributes': dict({
|
||||
'friendly_name': 'X-Wing Status',
|
||||
}),
|
||||
'state': 'on',
|
||||
}),
|
||||
'unit_of_measurement': None,
|
||||
}),
|
||||
dict({
|
||||
'disabled': False,
|
||||
'enity_id': 'sensor.x_wing_battery',
|
||||
|
@ -231,6 +252,18 @@
|
|||
}),
|
||||
}),
|
||||
'entities': list([
|
||||
dict({
|
||||
'disabled': True,
|
||||
'enity_id': 'binary_sensor.x_wing_motion',
|
||||
'state': None,
|
||||
'unit_of_measurement': None,
|
||||
}),
|
||||
dict({
|
||||
'disabled': True,
|
||||
'enity_id': 'binary_sensor.x_wing_status',
|
||||
'state': None,
|
||||
'unit_of_measurement': None,
|
||||
}),
|
||||
dict({
|
||||
'disabled': True,
|
||||
'enity_id': 'sensor.x_wing_battery',
|
||||
|
@ -343,6 +376,18 @@
|
|||
}),
|
||||
}),
|
||||
'entities': list([
|
||||
dict({
|
||||
'disabled': True,
|
||||
'enity_id': 'binary_sensor.x_wing_motion',
|
||||
'state': None,
|
||||
'unit_of_measurement': None,
|
||||
}),
|
||||
dict({
|
||||
'disabled': True,
|
||||
'enity_id': 'binary_sensor.x_wing_status',
|
||||
'state': None,
|
||||
'unit_of_measurement': None,
|
||||
}),
|
||||
dict({
|
||||
'disabled': True,
|
||||
'enity_id': 'sensor.x_wing_battery',
|
||||
|
@ -384,9 +429,7 @@
|
|||
'gps_accuracy': 3.5,
|
||||
'latitude': '**REDACTED**',
|
||||
'longitude': '**REDACTED**',
|
||||
'motion': False,
|
||||
'source_type': 'gps',
|
||||
'status': 'online',
|
||||
'traccar_id': 0,
|
||||
'tracker': 'traccar_server',
|
||||
}),
|
||||
|
|
Loading…
Reference in New Issue