Add binary sensor entities to Traccar Server (#114719)

This commit is contained in:
Joakim Sørensen 2024-04-24 17:08:56 +02:00 committed by GitHub
parent 2beab34de8
commit f83ee963bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 177 additions and 15 deletions

View File

@ -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:

View File

@ -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}")
)

View File

@ -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,
}

View File

@ -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"

View File

@ -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"

View File

@ -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',
}),