Skip to content

Commit e477241

Browse files
committed
Add support remote_car from cloud #735
1 parent a5d7467 commit e477241

File tree

9 files changed

+129
-2
lines changed

9 files changed

+129
-2
lines changed

custom_components/yandex_station/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
]
5151
# for import section
5252
PLATFORMS = [
53+
"binary_sensor",
5354
"button",
5455
"calendar",
5556
"camera",
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from homeassistant.components.binary_sensor import (
2+
BinarySensorDeviceClass,
3+
BinarySensorEntity,
4+
)
5+
6+
from .core.entity import YandexCustomEntity
7+
from .hass import hass_utils
8+
9+
INCLUDE_CAPABILITIES = ("devices.capabilities.lock",)
10+
11+
ENTITY_DESCRIPTIONS = {
12+
"lock": BinarySensorDeviceClass.LOCK,
13+
}
14+
15+
16+
async def async_setup_entry(hass, entry, async_add_entities):
17+
entities = []
18+
19+
for quasar, device, config in hass_utils.incluce_devices(hass, entry):
20+
for instance in device["capabilities"]:
21+
if instance["type"] in INCLUDE_CAPABILITIES:
22+
entities.append(YandexBinarySensor(quasar, device, instance))
23+
24+
async_add_entities(entities)
25+
26+
27+
# noinspection PyAbstractClass
28+
class YandexBinarySensor(BinarySensorEntity, YandexCustomEntity):
29+
30+
def internal_init(self, capabilities: dict, properties: dict):
31+
# {'access_methods': None, 'instance': 'lock', 'retrievable': True, 'values': ['closed', 'open']}
32+
if desc := ENTITY_DESCRIPTIONS.get(self.instance):
33+
self._attr_device_class = desc
34+
35+
def internal_update(self, capabilities: dict, properties: dict):
36+
if value := capabilities.get(self.instance):
37+
if self.instance == "lock":
38+
# On means open (unlocked), Off means closed (locked)
39+
self._attr_is_on = value == "open"

custom_components/yandex_station/climate.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ async def async_setup_entry(hass, entry, async_add_entities):
2828
for quasar, device, config in hass_utils.incluce_devices(hass, entry)
2929
if device["type"] in INCLUDE_TYPES
3030
)
31+
# this should be fixed someday
32+
async_add_entities(
33+
YandexRemoteCarSeat(quasar, device, config)
34+
for quasar, device, config in hass_utils.incluce_devices(hass, entry)
35+
if device["type"] == "devices.types.remote_car.seat"
36+
)
3137

3238

3339
# HA: auto, cool, dry, fan_only, heat; heat_cool, off
@@ -203,3 +209,35 @@ async def internal_set_hvac_mode(self, value: str) -> bool:
203209
raise e
204210

205211
return False
212+
213+
214+
class YandexRemoteCarSeat(ClimateEntity, YandexEntity):
215+
_attr_temperature_unit = UnitOfTemperature.CELSIUS
216+
_attr_supported_features = (
217+
ClimateEntityFeature.TURN_ON
218+
| ClimateEntityFeature.TURN_OFF
219+
| ClimateEntityFeature.PRESET_MODE
220+
)
221+
_attr_hvac_modes = [HVACMode.OFF, HVACMode.HEAT]
222+
223+
def internal_init(self, capabilities: dict, properties: dict):
224+
# {'instance': 'heating_mode', 'looped': False, 'name': 'режим обогрева', 'random_access': True, 'range': {'max': 3, 'min': 1, 'precision': 1}, 'retrievable': True, 'unit': ''}
225+
if mode := capabilities.get("heating_mode"):
226+
modes = range(mode["range"]["min"], mode["range"]["max"] + 1)
227+
self._attr_preset_modes = [str(i) for i in modes]
228+
229+
def internal_update(self, capabilities: dict, properties: dict):
230+
if (value := capabilities.get("on")) is not None:
231+
self._attr_hvac_mode = HVACMode.HEAT if value else HVACMode.OFF
232+
233+
if value := capabilities.get("heating_mode"):
234+
self._attr_preset_mode = str(value)
235+
236+
async def async_set_hvac_mode(self, hvac_mode: HVACMode):
237+
if hvac_mode == HVACMode.OFF:
238+
await self.device_action("on", False)
239+
elif hvac_mode == HVACMode.HEAT:
240+
await self.device_action("on", True)
241+
242+
async def async_set_preset_mode(self, preset_mode: str):
243+
await self.device_action("heating_mode", int(preset_mode))

custom_components/yandex_station/core/entity.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
def extract_instance(item: dict) -> str:
1313
if item["type"] == "devices.capabilities.on_off":
1414
return "on"
15+
if item["type"] == "devices.capabilities.lock":
16+
return "lock"
1517
return item["parameters"].get("instance")
1618

1719

@@ -112,7 +114,7 @@ async def device_actions(self, **kwargs):
112114
class YandexCustomEntity(YandexEntity):
113115
def __init__(self, quasar: YandexQuasar, device: dict, config: dict):
114116
self.instance = extract_instance(config)
115-
super().__init__(quasar, device)
117+
super().__init__(quasar, device, config)
116118
if name := config["parameters"].get("name"):
117119
self._attr_name += " " + name
118120
self._attr_unique_id += " " + self.instance

custom_components/yandex_station/core/yandex_quasar.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
"camera_pan": "devices.capabilities.range",
4040
"camera_tilt": "devices.capabilities.range",
4141
"get_stream": "devices.capabilities.video_stream",
42+
# "devices.types.remote_car.seat"
43+
"heating_mode": "devices.capabilities.range",
4244
# don't work
4345
"hsv": "devices.capabilities.color_setting",
4446
"rgb": "devices.capabilities.color_setting",

custom_components/yandex_station/hass/hass_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,6 @@ async def load_fake_devies(hass: HomeAssistant, quasar: YandexQuasar):
102102

103103
def job():
104104
with open(path, "rb") as f:
105-
quasar.devices += json.load(f)
105+
quasar.devices = json.load(f)
106106

107107
await hass.async_add_executor_job(job)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import logging
2+
3+
from homeassistant.components.lock import LockEntity
4+
5+
from .core.entity import YandexEntity
6+
from .hass import hass_utils
7+
8+
_LOGGER = logging.getLogger(__name__)
9+
10+
INCLUDE_CAPABILITIES = ("devices.capabilities.lock",)
11+
12+
async def async_setup_entry(hass, entry, async_add_entities):
13+
entities = []
14+
15+
for quasar, device, config in hass_utils.incluce_devices(hass, entry):
16+
for instance in device["capabilities"]:
17+
if instance["type"] not in INCLUDE_CAPABILITIES:
18+
continue
19+
entities.append(YandexLock(quasar, device, instance))
20+
21+
async_add_entities(entities)
22+
23+
24+
# noinspection PyAbstractClass
25+
class YandexLock(LockEntity, YandexEntity):
26+
def internal_update(self, capabilities: dict, properties: dict):
27+
if value := capabilities.get("lock"):
28+
self._attr_is_locked = value == "closed"
29+
30+
async def async_unlock(self):
31+
await self.device_action("lock", "open")
32+
33+
async def async_lock(self):
34+
await self.device_action("lock", "closed")

custom_components/yandex_station/sensor.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
UnitOfElectricCurrent,
1414
UnitOfElectricPotential,
1515
UnitOfEnergy,
16+
UnitOfLength,
1617
UnitOfPower,
1718
UnitOfPressure,
1819
UnitOfTemperature,
@@ -26,6 +27,7 @@
2627

2728
# https://yandex.ru/dev/dialogs/smart-home/doc/concepts/device-type-sensor.html
2829
INCLUDE_TYPES = (
30+
"devices.types.remote_car",
2931
"devices.types.sensor",
3032
"devices.types.sensor.button",
3133
"devices.types.sensor.climate",
@@ -79,6 +81,9 @@
7981
"electricity_meter": {"class": SENSOR.ENERGY, "units": UnitOfEnergy.KILO_WATT_HOUR},
8082
"gas_meter": {"class": SENSOR.GAS, "units": UnitOfVolume.CUBIC_METERS},
8183
"water_meter": {"class": SENSOR.WATER, "units": UnitOfVolume.CUBIC_METERS},
84+
# there is no better option than a battery for fuel_level
85+
"fuel_level": {"class": SENSOR.BATTERY, "units": PERCENTAGE},
86+
"petrol_mileage": {"class": SENSOR.DISTANCE, "units": UnitOfLength.KILOMETERS},
8287
}
8388

8489

@@ -110,6 +115,11 @@ def internal_init(self, capabilities: dict, properties: dict):
110115
if "units" in desc:
111116
self._attr_native_unit_of_measurement = desc["units"]
112117
self._attr_state_class = SensorStateClass.MEASUREMENT
118+
try:
119+
if self.config["parameters"]["range"]["precision"] == 1:
120+
self._attr_suggested_display_precision = 0
121+
except KeyError:
122+
pass
113123

114124
def internal_update(self, capabilities: dict, properties: dict):
115125
if self.instance in properties:

custom_components/yandex_station/switch.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
_LOGGER = logging.getLogger(__name__)
1010

1111
INCLUDE_TYPES = (
12+
"devices.types.remote_car",
1213
"devices.types.switch",
1314
"devices.types.socket",
1415
"devices.types.ventilation",

0 commit comments

Comments
 (0)