Skip to content

Commit

Permalink
Merge branch 'dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
MihVS committed Feb 11, 2024
2 parents 76fe495 + abb214e commit 68b646c
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 8 deletions.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
* Сенсоры
* Кастомные элементы (кнопка или сложная кнопка)
* Охранные зоны
* Состояние и местоположение автомобиля

### Контуры отопления.
Контур отопления добавляется в НА в виде термостата. Все, созданные в ZONT, режимы отопления добавляются в НА.
Expand All @@ -59,6 +60,31 @@
### Охранные зоны.
В НА добавляются все охранные зоны устройства. Можно поставить на охрану или снять с охраны охранную зону.

### Состояние и местоположение автомобиля.
Добавляются бинарные датчики автомобиля, его местоположение. Есть возможность постановки и снятия с охраны.
С помощью кастомного элемента можно организовать запуск двигателя и др.

<details>

<summary>Бинарные датчики автомобиля тут</summary>

- Двигатель заведён
- Состояние блокировки двигателя
- Состояние сирены
- Передняя левая дверь открыта
- Передняя правая дверь открыта
- Задняя левая дверь открыта
- Задняя правая дверь открыта
- Багажник открыт
- Капот открыт

</details>


> У меня нет автосигнализации ZONT, поэтому реальных тестов не проводилось.
> Если будет у когда желание и сигнализация, то пишите, проверим.

## Установка
**Способ 1.** [HACS](https://hacs.xyz/) -> Интеграции -> 3 точки в правом верхнем углу -> Пользовательские репозитории

Expand Down
68 changes: 62 additions & 6 deletions custom_components/zont_ha/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
)
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import ZontCoordinator
from .const import DOMAIN, MANUFACTURER, BINARY_SENSOR_TYPES
from .const import DOMAIN, MANUFACTURER, BINARY_SENSOR_TYPES, STATES_CAR
from .core.models_zont import SensorZONT, DeviceZONT
from .core.zont import type_binary_sensor, Zont

Expand All @@ -29,8 +27,18 @@ async def async_setup_entry(

for device in zont.data.devices:
binary_sensors = []
sensors = device.sensors
for sensor in sensors:
states = device.car_state
fields = []
if states:
fields = states.__fields__.keys()
for name_state in fields:
if isinstance(getattr(states, name_state), bool):
unique_id = f'{entry_id}{device.id}{name_state}'
binary_sensors.append(CarBinarySensor(
coordinator, device, name_state, unique_id
))

for sensor in device.sensors:
unique_id = f'{entry_id}{device.id}{sensor.id}'
if sensor.type in BINARY_SENSOR_TYPES:
binary_sensors.append(ZontBinarySensor(
Expand All @@ -41,6 +49,54 @@ async def async_setup_entry(
_LOGGER.debug(f'Добавлены бинарные сенсоры: {binary_sensors}')


class CarBinarySensor(CoordinatorEntity, BinarySensorEntity):

def __init__(
self, coordinator: ZontCoordinator, device: DeviceZONT,
sensor_name: str, unique_id: str
) -> None:
super().__init__(coordinator)
self._zont: Zont = coordinator.zont
self._device: DeviceZONT = device
self._sensor_name: str = sensor_name
self._unique_id: str = unique_id

@property
def name(self) -> str:
return f'{self._device.name}_{STATES_CAR[self._sensor_name]}'

@property
def unique_id(self) -> str:
return self._unique_id

@property
def is_on(self) -> bool | None:
"""Return true if the binary sensor is on."""
return getattr(self._device.car_state, self._sensor_name)

@property
def device_info(self):
return {
"identifiers": {(DOMAIN, self._device.id)},
"name": self._device.name,
"sw_version": None,
"model": self._device.model,
"manufacturer": MANUFACTURER,
}

def __repr__(self) -> str:
if not self.hass:
return f"<Binary sensor entity {self.name}>"
return super().__repr__()

@callback
def _handle_coordinator_update(self) -> None:
"""Обработка обновлённых данных от координатора"""

self._device = self.coordinator.data.get_device(self._device.id)
self.async_write_ha_state()


class ZontBinarySensor(CoordinatorEntity, BinarySensorEntity):

def __init__(
Expand Down
15 changes: 14 additions & 1 deletion custom_components/zont_ha/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
'button',
'switch',
'alarm_control_panel',
'binary_sensor'
'binary_sensor',
'device_tracker'
]

COUNTER_REPEAT = 18
Expand All @@ -66,3 +67,15 @@
TIME_UPDATE = 60

MODELS_THERMOSTAT_ZONT = ('T100', 'T102')

STATES_CAR = {
'engine_on': 'Двигатель заведён',
'engine_block': 'Состояние блокировки двигателя',
'siren': 'Состояние сирены',
'door_front_left': 'Передняя левая дверь открыта',
'door_front_right': 'Передняя правая дверь открыта',
'door_rear_left': 'Задняя левая дверь открыта',
'door_rear_right': 'Задняя правая дверь открыта',
'trunk': 'Багажник открыт',
'hood': 'Капот открыт'
}
44 changes: 44 additions & 0 deletions custom_components/zont_ha/core/models_zont.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import datetime

from pydantic import BaseModel, validator


Expand Down Expand Up @@ -78,6 +80,47 @@ class ScenarioZONT(ControlEntityZONT):
pass


class AutoStart(BaseModel):
"""Модель автостарта автомобиля"""

available: bool
status: str
until: datetime = None


class CarView(BaseModel):
"""Модель внешнего вида автомобиля"""

model: str


class Position(BaseModel):
"""Модель местонахождения автомобиля"""

x: float
y: float
time: datetime


class CarStateZONT(BaseModel):
"""Модель статуса автомобиля"""

engine_on: bool
autostart: AutoStart
engine_block: bool
siren: bool
door_front_left: bool
door_front_right: bool
door_rear_left: bool
door_rear_right: bool
trunk: bool
hood: bool
power_source: str
car_view: CarView
position: Position
address: str


class DeviceZONT(BaseEntityZONT):
"""Модель контроллера"""

Expand All @@ -92,6 +135,7 @@ class DeviceZONT(BaseEntityZONT):
guard_zones: list[GuardZoneZONT] | GuardZoneZONT = []
custom_controls: list[CustomControlZONT] = []
scenarios: list[ScenarioZONT] = []
car_state: CarStateZONT = []

@validator('guard_zones')
def guard_zones_should_be_list(
Expand Down
81 changes: 81 additions & 0 deletions custom_components/zont_ha/device_tracker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import logging

from homeassistant.components.device_tracker import TrackerEntity, SourceType
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import ZontCoordinator
from .const import DOMAIN
from .core.models_zont import DeviceZONT
from .core.zont import Zont

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback
) -> None:
entry_id = config_entry.entry_id

coordinator = hass.data[DOMAIN][entry_id]
zont = coordinator.zont

for device in zont.data.devices:
states = device.car_state
if states:
unique_id = f'{entry_id}{device.id}{"position"}'
device_tracker = CarPosition(coordinator, device, unique_id)
async_add_entities([device_tracker])
_LOGGER.debug(
f'Добавлено устройство отслеживания: {device_tracker}'
)


class CarPosition(CoordinatorEntity, TrackerEntity):

def __init__(
self, coordinator: ZontCoordinator, device: DeviceZONT,
unique_id: str
) -> None:
super().__init__(coordinator)
self._zont: Zont = coordinator.zont
self._device: DeviceZONT = device
self._unique_id: str = unique_id

@property
def name(self) -> str:
return f'{self._device.name}_device_tracker'

@property
def unique_id(self) -> str:
return self._unique_id

@property
def location_name(self) -> str | None:
"""Return a location name for the current location of the device."""
return self._device.car_state.address

@property
def latitude(self) -> float | None:
"""Return latitude value of the device."""
return self._device.car_state.position.y

@property
def longitude(self) -> float | None:
"""Return longitude value of the device."""
return self._device.car_state.position.x

@property
def source_type(self) -> SourceType | str:
"""Return the source type, eg gps or router, of the device."""
return SourceType.GPS

@callback
def _handle_coordinator_update(self) -> None:
"""Обработка обновлённых данных от координатора"""

self._device = self.coordinator.data.get_device(self._device.id)
self.async_write_ha_state()
2 changes: 1 addition & 1 deletion custom_components/zont_ha/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"integration_type": "hub",
"dependencies": ["http", "zeroconf"],
"requirements": [],
"version": "0.2.5"
"version": "0.3.0"
}

0 comments on commit 68b646c

Please sign in to comment.