Skip to content

Commit 2a6de4a

Browse files
authored
Support for humidifier entity (#19)
Includes additional fixes: * Fix YAML schema * Style fixes
1 parent f3589ad commit 2a6de4a

File tree

16 files changed

+385
-127
lines changed

16 files changed

+385
-127
lines changed

custom_components/connectlife/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@
1010
from .const import DOMAIN
1111
from .coordinator import ConnectLifeCoordinator
1212

13-
PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.CLIMATE, Platform.SENSOR, Platform.SELECT, Platform.SWITCH]
13+
PLATFORMS: list[Platform] = [
14+
Platform.BINARY_SENSOR,
15+
Platform.CLIMATE,
16+
Platform.HUMIDIFIER,
17+
Platform.SENSOR,
18+
Platform.SELECT,
19+
Platform.SWITCH
20+
]
1421

1522

1623
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

custom_components/connectlife/binary_sensor.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ def __init__(
5151
self.status = status
5252
self.entity_description = BinarySensorEntityDescription(
5353
key=self._attr_unique_id,
54-
entity_registry_visible_default = not dd_entry.hide,
54+
entity_registry_visible_default=not dd_entry.hide,
5555
icon=dd_entry.icon,
5656
name=status.replace("_", " "),
57-
translation_key = status,
58-
device_class = dd_entry.binary_sensor.device_class
57+
translation_key=status,
58+
device_class=dd_entry.binary_sensor.device_class
5959
)
6060
self.update_state()
6161

@@ -68,4 +68,4 @@ def update_state(self):
6868
else:
6969
self._attr_is_on = None
7070
_LOGGER.warning("Unknown value %d for %s", value, self.status)
71-
self._attr_available = self.coordinator.appliances[self.device_id]._offline_state == 1
71+
self._attr_available = self.coordinator.appliances[self.device_id].offline_state == 1

custom_components/connectlife/climate.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
TEMPERATURE_UNIT,
2525
)
2626
from .coordinator import ConnectLifeCoordinator
27-
from .dictionaries import Dictionaries, Property, Climate
27+
from .dictionaries import Dictionaries, Property
2828
from .entity import ConnectLifeEntity
2929
from connectlife.appliance import ConnectLifeAppliance
3030

@@ -47,8 +47,8 @@ async def async_setup_entry(
4747

4848

4949
def is_climate(dictionary: dict[str, Property]):
50-
for property in dictionary.values():
51-
if hasattr(property, Platform.CLIMATE):
50+
for prop in dictionary.values():
51+
if hasattr(prop, Platform.CLIMATE):
5252
return True
5353
return False
5454

@@ -64,7 +64,7 @@ class ConnectLifeClimate(ConnectLifeEntity, ClimateEntity):
6464
target_map = {}
6565
fan_mode_map: dict[int, str] = {}
6666
fan_mode_reverse_map: dict[str, int] = {}
67-
hvac_action_map: dict[int, HVACMode] = {}
67+
hvac_action_map: dict[int, HVACAction] = {}
6868
swing_mode_map: dict[int, str] = {}
6969
swing_mode_reverse_map: dict[str, int] = {}
7070
temperature_unit_map: dict[int, UnitOfTemperature] = {}
@@ -146,7 +146,7 @@ def update_state(self) -> None:
146146
if value in self.hvac_action_map:
147147
self._attr_hvac_action = self.hvac_action_map[value]
148148
else:
149-
# Map to None as we canot add custom HVAC actions.
149+
# Map to None as we cannot add custom HVAC actions.
150150
self._attr_hvac_action = None
151151
elif target == FAN_MODE:
152152
if value in self.fan_mode_map:
@@ -167,7 +167,7 @@ def update_state(self) -> None:
167167
_LOGGER.warning("Got unexpected value %d for %s", value, status)
168168
else:
169169
setattr(self, f"_attr_{target}", value)
170-
self._attr_available = self.coordinator.appliances[self.device_id]._offline_state == 1
170+
self._attr_available = self.coordinator.appliances[self.device_id].offline_state == 1
171171

172172
async def async_set_humidity(self, humidity):
173173
"""Set new target humidity."""
@@ -180,22 +180,28 @@ async def async_set_temperature(self, **kwargs) -> None:
180180
"""Set new target temperature."""
181181
if ATTR_TEMPERATURE in kwargs and TARGET_TEMPERATURE in self.target_map:
182182
target_temperature = round(kwargs[ATTR_TEMPERATURE])
183-
await self.coordinator.api.update_appliance(self.puid, {self.target_map[TARGET_TEMPERATURE]: target_temperature})
183+
await self.coordinator.api.update_appliance(
184+
self.puid,
185+
{
186+
self.target_map[TARGET_TEMPERATURE]:
187+
target_temperature
188+
}
189+
)
184190
self._attr_target_temperature = target_temperature
185191
self.async_write_ha_state()
186192

187193
async def async_turn_on(self):
188194
"""Turn the entity on."""
189195
# TODO: Support value mapping
190196
await self.coordinator.api.update_appliance(self.puid, {self.target_map[IS_ON]: 1})
191-
self.hvac_mode = HVACMode.AUTO
197+
self._attr_hvac_mode = HVACMode.AUTO
192198
self.async_write_ha_state()
193199

194200
async def async_turn_off(self):
195201
"""Turn the entity off."""
196202
# TODO: Support value mapping
197203
await self.coordinator.api.update_appliance(self.puid, {self.target_map[IS_ON]: 0})
198-
self.hvac_mode = HVACMode.OFF
204+
self._attr_hvac_mode = HVACMode.OFF
199205
self.async_write_ha_state()
200206

201207
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
@@ -208,7 +214,7 @@ async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
208214

209215
async def async_set_fan_mode(self, fan_mode: str) -> None:
210216
"""Set the fan mode."""
211-
await self.coordinator.api.update_appliance(self.puid, {
217+
await self.coordinator.api.update_appliance(self.puid, {
212218
self.target_map[FAN_MODE]: self.fan_mode_reverse_map[fan_mode]
213219
})
214220
self._attr_fan_mode = fan_mode

custom_components/connectlife/const.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
ATTR_DESC = "desc"
77
ATTR_KEY = "key"
88

9+
ACTION = "action"
910
HVAC_ACTION = "hvac_action"
1011
FAN_MODE = "fan_mode"
1112
IS_ON = "is_on"
13+
MODE = "mode"
1214
SWING_MODE = "swing_mode"
1315
TARGET_HUMIDITY = "target_humidity"
1416
TARGET_TEMPERATURE = "target_temperature"

custom_components/connectlife/data_dictionaries/007-400.yaml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,24 @@ properties:
2828
binary_sensor:
2929
device_class: problem
3030
- property: f_humidity
31-
climate:
31+
humidifier:
3232
target: current_humidity
3333
- property: t_fan_speed
34-
climate:
35-
target: fan_mode
34+
select:
3635
options:
3736
0: low
3837
1: high
3938
2: auto
4039
- property: t_humidity
41-
climate:
40+
humidifier:
4241
target: target_humidity
42+
device_class: dehumidifier
4343
- property: t_power
44-
climate:
44+
humidifier:
4545
target: is_on
4646
- property: t_work_mode
47-
select:
47+
humidifier:
48+
target: mode
4849
options:
4950
0: continuous
5051
1: manual

custom_components/connectlife/data_dictionaries/009-109.yaml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
device_type: aircondition
1+
device_type: airconditioner
22
properties:
33
- property: f_temp_in
44
climate:
55
target: current_temperature
6-
- property: oem_host_version
7-
sensor:
8-
hide: true
96
- property: t_beep
10-
switch:
7+
switch: {}
118
- property: t_eco
12-
switch:
9+
switch: {}
1310
- property: t_fan_mute
14-
switch:
11+
switch: {}
1512
- property: t_fan_speed
1613
climate:
1714
target: fan_mode

custom_components/connectlife/data_dictionaries/README.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ To make a property visible by default, just add the property to the list (withou
77

88
File name: `<deviceTypeCode>-<deviceFeatureCode>.yaml`
99

10-
The file containse to top level items:
10+
The file contains two top level items:
1111
- `device_type`: string
1212
- `properties`: list of [`Property`](#property):
1313

@@ -20,11 +20,12 @@ The file containse to top level items:
2020
| `icon` | `mdi:eye`, etc. | Icon to use for the entity. |
2121
| `binary_sensor` | [BinarySensor](#type-binarysensor) | Create a binary sensor of the property. |
2222
| `climate` | [Climate](#type-climate) | Map the property to a climate entity for the device. |
23+
| `humidifier` | [Humidifier](#type-climate) | Map the property to a humidifier entity for the device. |
2324
| `select` | [Select](#type-select) | Create a selector of the property. |
2425
| `sensor` | [Sensor](#type-sensor) | Create a sensor of the property. This is the default. |
2526
| `switch` | [Switch](#type-switch) | Create a Switch of the property. |
2627

27-
If a entity mapping is not given, the property is mapped to a sensor entity.
28+
If an entity mapping is not given, the property is mapped to a sensor entity.
2829

2930
It is not necessary to include items with empty values. A [JSON schema](properties-schema.json) is provided so data dictionaries can be
3031
validated.
@@ -41,21 +42,34 @@ Domain `binary_sensor` can be used for read only properties where `0` is not ava
4142

4243
## Type `Climate`:
4344

44-
Domain `climate` can be used to map the property to a target propery in a climate entity. If at least one property has
45+
Domain `climate` can be used to map the property to a target property in a climate entity. If at least one property has
4546
type `climate`, a climate entity is created for the appliance.
4647

47-
| Item | Type | Description |
48-
|-----------|---------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
49-
| `target` | string | Any of these [climate entity](https://developers.home-assistant.io/docs/core/entity/climate#properties) attributes: `fan_mode`, `hvac_action`, `swing_mode`, `temperature`, `target_temperature`, `temperature_unit`, or the special target `is_on` |
50-
| `options` | dictionary of integer to string | Required for `fan_mode`, `hvac_action`, `swing_mode`, and `temperature_unit` |
48+
| Item | Type | Description |
49+
|-----------|---------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
50+
| `target` | string | Any of these [climate entity](https://developers.home-assistant.io/docs/core/entity/climate#properties) attributes: `current_humidity`, `fan_mode`, `hvac_action`, `swing_mode`, `current_temperature`, `target_humidity`, `target_temperature`, `temperature_unit`, or the special target `is_on` |
51+
| `options` | dictionary of integer to string | Required for `fan_mode`, `hvac_action`, `swing_mode`, and `temperature_unit` |
5152

5253
`temperature_unit` defaults to Celsius.
5354

5455
Note that `hvac_action` can only be mapped to [pre-defined actions](https://developers.home-assistant.io/docs/core/entity/climate#hvac-action).
5556
If a value does not have a sensible mapping, leave it out to set `hvac_action` to `None` for that value, or consider
5657
mapping to a sensor `enum` instead.
5758

58-
For `fan_mode` and `swing_mode`, remember to add [transalation string](#translation-strings).
59+
For `fan_mode` and `swing_mode`, remember to add [translation string](#translation-strings).
60+
61+
## Type `Humidifier`:
62+
63+
Domain `humidifier` can be used to map the property to a target property in a humidifier entity. If at least one property has
64+
type `humidifier`, a humidifier entity is created for the appliance.
65+
66+
| Item | Type | Description |
67+
|----------------|---------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
68+
| `target` | string | Any of these [climate entity](https://developers.home-assistant.io/docs/core/entity/humidifier#properties) attributes: `is_on`, `current_humidity`, or `target_humidity` |
69+
| `options` | dictionary of integer to string | |
70+
| `device_class` | string | Name of any [HumidifierDeviceClass enum](https://developers.home-assistant.io/docs/core/entity/humidifier#available-device-classes) |
71+
72+
It is sufficient to set `device_class` on one property. The value of the first encountered property is used.
5973

6074
## Type `Select`
6175

@@ -123,7 +137,7 @@ This goes into [strings.json](../strings.json) and [en.json](../translations/e
123137
}
124138
```
125139

126-
Climate modes must be registered as `state_attributes`.
140+
Climate and humidifier modes must be registered as `state_attributes`.
127141

128142
For example, given the following data dictionary:
129143
```yaml

0 commit comments

Comments
 (0)