Skip to content

Commit dbcf2ca

Browse files
committed
Major Update
1 parent 593bfe4 commit dbcf2ca

File tree

21 files changed

+504
-552
lines changed

21 files changed

+504
-552
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[![hacs_badge](https://img.shields.io/badge/HACS-Custom-41BDF5.svg?style=for-the-badge)](https://github.com/hacs/integration)
22

3-
# Kocom WallPad Integration for Home Assistant
4-
Home Assistant를 위한 Kocom WallPad 통합구성요소
3+
# Kocom Wallpad Integration for Home Assistant
4+
Home Assistant를 위한 Kocom Wallpad 통합구성요소
55

66
## 기여
77
문제가 있나요? [Issues](https://github.com/lunDreame/kocom-wallpad/issues) 탭에 작성해 주세요.

custom_components/kocom_wallpad/binary_sensor.py

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
from homeassistant.helpers.dispatcher import async_dispatcher_connect
1515

1616
from .pywallpad.const import STATE, ERROR_CODE, TIME
17+
from .pywallpad.enums import DeviceType
1718
from .pywallpad.packet import (
1819
KocomPacket,
1920
ThermostatPacket,
2021
FanPacket,
21-
MotionPacket
22+
MotionPacket,
2223
)
2324

2425
from .gateway import KocomGateway
@@ -37,12 +38,8 @@ async def async_setup_entry(
3738
@callback
3839
def async_add_binary_sensor(packet: KocomPacket) -> None:
3940
"""Add new binary sensor entity."""
40-
if isinstance(packet, (ThermostatPacket, FanPacket)):
41+
if isinstance(packet, (ThermostatPacket, FanPacket, MotionPacket)):
4142
async_add_entities([KocomBinarySensorEntity(gateway, packet)])
42-
elif isinstance(packet, MotionPacket):
43-
async_add_entities([KocomMotionEntity(gateway, packet)])
44-
else:
45-
LOGGER.warning(f"Unsupported packet type: {packet}")
4643

4744
for entity in gateway.get_entities(Platform.BINARY_SENSOR):
4845
async_add_binary_sensor(entity)
@@ -64,40 +61,15 @@ def __init__(
6461
) -> None:
6562
"""Initialize the binary sensor."""
6663
super().__init__(gateway, packet)
64+
self._attr_is_on = self.device.state[STATE]
6765
self._attr_extra_state_attributes = {
6866
DEVICE_TYPE: self.device.device_type,
6967
ROOM_ID: self.device.room_id,
7068
SUB_ID: self.device.sub_id,
7169
ERROR_CODE: self.device.state[ERROR_CODE],
7270
}
7371

74-
@property
75-
def is_on(self) -> bool:
76-
"""Return true if the binary sensor is on."""
77-
return self.device.state[STATE]
78-
79-
80-
class KocomMotionEntity(KocomEntity, BinarySensorEntity):
81-
"""Representation of a Kocom binary sensor."""
82-
83-
_attr_device_class = BinarySensorDeviceClass.MOTION
84-
85-
def __init__(
86-
self,
87-
gateway: KocomGateway,
88-
packet: KocomPacket,
89-
) -> None:
90-
"""Initialize the binary sensor."""
91-
super().__init__(gateway, packet)
92-
self._attr_extra_state_attributes = {
93-
DEVICE_TYPE: self.device.device_type,
94-
ROOM_ID: self.device.room_id,
95-
SUB_ID: self.device.sub_id,
96-
TIME: self.device.state[TIME],
97-
}
98-
99-
@property
100-
def is_on(self) -> bool:
101-
"""Return true if the binary sensor is on."""
102-
return self.device.state[STATE]
103-
72+
if self.packet.device_type == DeviceType.MOTION:
73+
self._attr_device_class = BinarySensorDeviceClass.MOTION
74+
del self._attr_extra_state_attributes[ERROR_CODE]
75+
self._attr_extra_state_attributes[TIME] = self.device.state[TIME]

custom_components/kocom_wallpad/climate.py

Lines changed: 99 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ def async_add_climate(packet: KocomPacket) -> None:
5050
async_add_entities([KocomThermostatEntity(gateway, packet)])
5151
elif isinstance(packet, AcPacket):
5252
async_add_entities([KocomAcEntity(gateway, packet)])
53-
else:
54-
LOGGER.warning(f"Unsupported packet type: {packet}")
5553

5654
for entity in gateway.get_entities(Platform.CLIMATE):
5755
async_add_climate(entity)
@@ -62,45 +60,35 @@ def async_add_climate(packet: KocomPacket) -> None:
6260

6361

6462
class KocomThermostatEntity(KocomEntity, ClimateEntity):
65-
"""Representation of a Kocom climate."""
63+
"""Representation of a Kocom thermostat."""
6664

6765
_enable_turn_on_off_backwards_compatibility = False
6866
_attr_hvac_modes = [HVACMode.OFF, HVACMode.HEAT]
6967
_attr_preset_modes = [PRESET_AWAY, PRESET_NONE]
7068
_attr_supported_features = (
71-
ClimateEntityFeature.TARGET_TEMPERATURE |
72-
ClimateEntityFeature.TURN_OFF |
73-
ClimateEntityFeature.TURN_ON |
74-
ClimateEntityFeature.PRESET_MODE
69+
ClimateEntityFeature.TARGET_TEMPERATURE
70+
| ClimateEntityFeature.TURN_OFF
71+
| ClimateEntityFeature.TURN_ON
72+
| ClimateEntityFeature.PRESET_MODE
7573
)
7674
_attr_temperature_unit = UnitOfTemperature.CELSIUS
7775
_attr_max_temp = 40
7876
_attr_min_temp = 5
7977
_attr_target_temperature_step = 1
80-
81-
def __init__(
82-
self,
83-
gateway: KocomGateway,
84-
packet: KocomPacket,
85-
) -> None:
86-
"""Initialize the climate."""
78+
79+
def __init__(self, gateway: KocomGateway, packet: KocomPacket) -> None:
80+
"""Initialize the thermostat."""
8781
super().__init__(gateway, packet)
8882

8983
@property
9084
def hvac_mode(self) -> HVACMode:
91-
"""Return hvac operation ie. heat, cool mode."""
92-
if self.device.state[POWER]:
93-
return HVACMode.HEAT
94-
else:
95-
return HVACMode.OFF
96-
85+
"""Return the current HVAC mode."""
86+
return HVACMode.HEAT if self.device.state[POWER] else HVACMode.OFF
87+
9788
@property
9889
def preset_mode(self) -> str:
99-
"""Return the current preset mode, e.g., home, away, temp."""
100-
if self.device.state[AWAY_MODE]:
101-
return PRESET_AWAY
102-
else:
103-
return PRESET_NONE
90+
"""Return the current preset mode."""
91+
return PRESET_AWAY if self.device.state[AWAY_MODE] else PRESET_NONE
10492

10593
@property
10694
def current_temperature(self) -> int:
@@ -109,42 +97,43 @@ def current_temperature(self) -> int:
10997

11098
@property
11199
def target_temperature(self) -> int:
112-
"""Return the temperature we try to reach."""
100+
"""Return the target temperature."""
113101
return self.device.state[TARGET_TEMP]
114-
102+
115103
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
116-
"""Set new target hvac mode."""
117-
if hvac_mode == HVACMode.OFF:
118-
power = False
119-
elif hvac_mode == HVACMode.HEAT:
120-
power = True
121-
else:
104+
"""Set the HVAC mode."""
105+
hvac_to_power = {
106+
HVACMode.OFF: False,
107+
HVACMode.HEAT: True,
108+
}
109+
power = hvac_to_power.get(hvac_mode)
110+
if power is None:
122111
raise ValueError(f"Unknown HVAC mode: {hvac_mode}")
123-
124-
packet = self.packet.make_status(power=power)
125-
await self.send(packet)
112+
113+
make_packet = self.packet.make_power_status(power)
114+
await self.send_packet(make_packet)
126115

127116
async def async_set_preset_mode(self, preset_mode: str) -> None:
128-
"""Set new target preset mode."""
129-
if preset_mode == PRESET_AWAY:
130-
away_mode = True
131-
elif preset_mode == PRESET_NONE:
132-
away_mode = False
133-
else:
117+
"""Set the preset mode."""
118+
preset_to_away = {
119+
PRESET_AWAY: True,
120+
PRESET_NONE: False,
121+
}
122+
away_mode = preset_to_away.get(preset_mode)
123+
if away_mode is None:
134124
raise ValueError(f"Unknown preset mode: {preset_mode}")
135-
136-
packet = self.packet.make_status(away_mode=away_mode)
137-
await self.send(packet)
125+
126+
make_packet = self.packet.make_away_status(away_mode)
127+
await self.send_packet(make_packet)
138128

139129
async def async_set_temperature(self, **kwargs) -> None:
140-
"""Set new target temperature."""
141-
target_temp = kwargs.get(ATTR_TEMPERATURE)
142-
if target_temp is None:
143-
LOGGER.warning("Missing temperature")
144-
return
130+
"""Set the target temperature."""
131+
if ATTR_TEMPERATURE not in kwargs:
132+
raise ValueError("Missing temperature")
145133

146-
packet = self.packet.make_status(target_temp=target_temp)
147-
await self.send(packet)
134+
target_temp = int(kwargs[ATTR_TEMPERATURE])
135+
make_packet = self.packet.make_target_temp(target_temp)
136+
await self.send_packet(make_packet)
148137

149138

150139
class KocomAcEntity(KocomEntity, ClimateEntity):
@@ -156,105 +145,92 @@ class KocomAcEntity(KocomEntity, ClimateEntity):
156145
HVACMode.COOL,
157146
HVACMode.FAN_ONLY,
158147
HVACMode.DRY,
159-
HVACMode.AUTO
148+
HVACMode.AUTO,
160149
]
161150
_attr_fan_modes = [FAN_LOW, FAN_MEDIUM, FAN_HIGH]
162151
_attr_supported_features = (
163-
ClimateEntityFeature.TARGET_TEMPERATURE |
164-
ClimateEntityFeature.TURN_OFF |
165-
ClimateEntityFeature.TURN_ON |
166-
ClimateEntityFeature.FAN_MODE
152+
ClimateEntityFeature.TARGET_TEMPERATURE
153+
| ClimateEntityFeature.TURN_OFF
154+
| ClimateEntityFeature.TURN_ON
155+
| ClimateEntityFeature.FAN_MODE
167156
)
168157
_attr_temperature_unit = UnitOfTemperature.CELSIUS
169158
_attr_max_temp = 30
170159
_attr_min_temp = 18
171160
_attr_target_temperature_step = 1
172-
173-
def __init__(
174-
self,
175-
gateway: KocomGateway,
176-
packet: KocomPacket,
177-
) -> None:
161+
162+
def __init__(self, gateway: KocomGateway, packet: KocomPacket) -> None:
178163
"""Initialize the climate."""
179164
super().__init__(gateway, packet)
180-
165+
181166
@property
182167
def hvac_mode(self) -> HVACMode:
183-
"""Return hvac operation ie. heat, cool mode."""
184-
if self.device.state[POWER] and (op_mode := self.device.state[OP_MODE]):
185-
if op_mode == OpMode.COOL:
186-
return HVACMode.COOL
187-
elif op_mode == OpMode.FAN_ONLY:
188-
return HVACMode.FAN_ONLY
189-
elif op_mode == OpMode.DRY:
190-
return HVACMode.DRY
191-
elif op_mode == OpMode.AUTO:
192-
return HVACMode.AUTO
193-
else:
194-
return HVACMode.OFF
195-
168+
"""Return current HVAC mode."""
169+
if self.device.state[POWER]:
170+
op_mode = self.device.state[OP_MODE]
171+
return {
172+
OpMode.COOL: HVACMode.COOL,
173+
OpMode.FAN_ONLY: HVACMode.FAN_ONLY,
174+
OpMode.DRY: HVACMode.DRY,
175+
OpMode.AUTO: HVACMode.AUTO,
176+
}.get(op_mode, HVACMode.OFF)
177+
return HVACMode.OFF
178+
196179
@property
197180
def fan_mode(self) -> str:
198-
"""Return the fan setting."""
199-
fan_mode = self.device.state[FAN_MODE]
200-
if fan_mode == FanMode.LOW:
201-
return FAN_LOW
202-
elif fan_mode == FanMode.MEDIUM:
203-
return FAN_MEDIUM
204-
elif fan_mode == FanMode.HIGH:
205-
return FAN_HIGH
206-
181+
"""Return current fan mode."""
182+
return {
183+
FanMode.LOW: FAN_LOW,
184+
FanMode.MEDIUM: FAN_MEDIUM,
185+
FanMode.HIGH: FAN_HIGH,
186+
}.get(self.device.state[FAN_MODE])
187+
207188
@property
208189
def current_temperature(self) -> int:
209190
"""Return the current temperature."""
210191
return self.device.state[CURRENT_TEMP]
211192

212193
@property
213194
def target_temperature(self) -> int:
214-
"""Return the temperature we try to reach."""
195+
"""Return the target temperature."""
215196
return self.device.state[TARGET_TEMP]
216-
197+
217198
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
218-
"""Set new target hvac mode."""
199+
"""Set a new target HVAC mode."""
219200
if hvac_mode == HVACMode.OFF:
220-
op_mode = OpMode.OFF
221-
elif hvac_mode == HVACMode.COOL:
222-
op_mode = OpMode.COOL
223-
elif hvac_mode == HVACMode.FAN_ONLY:
224-
op_mode = OpMode.FAN_ONLY
225-
elif hvac_mode == HVACMode.DRY:
226-
op_mode = OpMode.DRY
227-
elif hvac_mode == HVACMode.AUTO:
228-
op_mode = OpMode.AUTO
201+
make_packet = self.packet.make_power_status(False)
229202
else:
230-
raise ValueError(f"Unknown HVAC mode: {hvac_mode}")
231-
232-
packet = self.packet.make_status(op_mode=op_mode)
233-
await self.send(packet)
203+
hvac_to_op_mode = {
204+
HVACMode.COOL: OpMode.COOL,
205+
HVACMode.FAN_ONLY: OpMode.FAN_ONLY,
206+
HVACMode.DRY: OpMode.DRY,
207+
HVACMode.AUTO: OpMode.AUTO,
208+
}
209+
op_mode = hvac_to_op_mode.get(hvac_mode)
210+
if op_mode is None:
211+
raise ValueError(f"Unknown HVAC mode: {hvac_mode}")
212+
make_packet = self.packet.make_op_mode(op_mode)
213+
214+
await self.send_packet(make_packet)
234215

235216
async def async_set_fan_mode(self, fan_mode: str) -> None:
236-
"""Set new target fan mode."""
237-
if fan_mode == FAN_LOW:
238-
fan_speed = FanMode.LOW
239-
elif fan_mode == FAN_MEDIUM:
240-
fan_speed = FanMode.MEDIUM
241-
elif fan_mode == FAN_HIGH:
242-
fan_speed = FanMode.HIGH
243-
else:
217+
"""Set a new target fan mode."""
218+
fan_speed = {
219+
FAN_LOW: FanMode.LOW,
220+
FAN_MEDIUM: FanMode.MEDIUM,
221+
FAN_HIGH: FanMode.HIGH,
222+
}.get(fan_mode)
223+
if fan_speed is None:
244224
raise ValueError(f"Unknown fan mode: {fan_mode}")
245-
246-
packet = self.packet.make_status(fan_mode=fan_speed)
247-
await self.send(packet)
248-
249-
async def async_set_preset_mode(self, preset_mode: str) -> None:
250-
"""Set new target preset mode."""
225+
226+
make_packet = self.packet.make_fan_mode(fan_speed)
227+
await self.send_packet(make_packet)
251228

252229
async def async_set_temperature(self, **kwargs) -> None:
253-
"""Set new target temperature."""
254-
target_temp = kwargs.get(ATTR_TEMPERATURE)
255-
if target_temp is None:
256-
LOGGER.warning("Missing temperature")
257-
return
230+
"""Set a new target temperature."""
231+
if ATTR_TEMPERATURE not in kwargs:
232+
raise ValueError("Missing temperature")
258233

259-
packet = self.packet.make_status(target_temp=target_temp)
260-
await self.send(packet)
234+
target_temp = int(kwargs[ATTR_TEMPERATURE])
235+
make_packet = self.packet.make_target_temp(target_temp)
236+
await self.send_packet(make_packet)

0 commit comments

Comments
 (0)