Skip to content

Commit ca30d8b

Browse files
mback2kjoostlek
andauthored
Add support for load switches to WMS WebControl pro (home-assistant#151047)
Co-authored-by: Joost Lekkerkerker <[email protected]>
1 parent aae98a7 commit ca30d8b

File tree

7 files changed

+533
-0
lines changed

7 files changed

+533
-0
lines changed

homeassistant/components/wmspro/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
Platform.COVER,
2121
Platform.LIGHT,
2222
Platform.SCENE,
23+
Platform.SWITCH,
2324
]
2425

2526
type WebControlProConfigEntry = ConfigEntry[WebControlPro]
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""Support for loads connected with WMS WebControl pro."""
2+
3+
from __future__ import annotations
4+
5+
from datetime import timedelta
6+
from typing import Any
7+
8+
from wmspro.const import (
9+
WMS_WebControl_pro_API_actionDescription,
10+
WMS_WebControl_pro_API_responseType,
11+
)
12+
13+
from homeassistant.components.switch import SwitchEntity
14+
from homeassistant.core import HomeAssistant
15+
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
16+
17+
from . import WebControlProConfigEntry
18+
from .entity import WebControlProGenericEntity
19+
20+
SCAN_INTERVAL = timedelta(seconds=15)
21+
PARALLEL_UPDATES = 1
22+
23+
24+
async def async_setup_entry(
25+
hass: HomeAssistant,
26+
config_entry: WebControlProConfigEntry,
27+
async_add_entities: AddConfigEntryEntitiesCallback,
28+
) -> None:
29+
"""Set up the WMS based switches from a config entry."""
30+
hub = config_entry.runtime_data
31+
32+
async_add_entities(
33+
WebControlProSwitch(config_entry.entry_id, dest)
34+
for dest in hub.dests.values()
35+
if dest.hasAction(WMS_WebControl_pro_API_actionDescription.LoadSwitch)
36+
)
37+
38+
39+
class WebControlProSwitch(WebControlProGenericEntity, SwitchEntity):
40+
"""Representation of a WMS based switch."""
41+
42+
_attr_name = None
43+
44+
@property
45+
def is_on(self) -> bool:
46+
"""Return true if switch is on."""
47+
action = self._dest.action(WMS_WebControl_pro_API_actionDescription.LoadSwitch)
48+
return action["onOffState"]
49+
50+
async def async_turn_on(self, **kwargs: Any) -> None:
51+
"""Turn the switch on."""
52+
action = self._dest.action(WMS_WebControl_pro_API_actionDescription.LoadSwitch)
53+
await action(
54+
onOffState=True, responseType=WMS_WebControl_pro_API_responseType.Detailed
55+
)
56+
57+
async def async_turn_off(self, **kwargs: Any) -> None:
58+
"""Turn the switch off."""
59+
action = self._dest.action(WMS_WebControl_pro_API_actionDescription.LoadSwitch)
60+
await action(
61+
onOffState=False, responseType=WMS_WebControl_pro_API_responseType.Detailed
62+
)

tests/components/wmspro/conftest.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,16 @@ def mock_hub_configuration_prod_awning_valance() -> Generator[AsyncMock]:
8282
yield mock_hub_configuration
8383

8484

85+
@pytest.fixture
86+
def mock_hub_configuration_prod_load_switch() -> Generator[AsyncMock]:
87+
"""Override WebControlPro._getConfiguration."""
88+
with patch(
89+
"wmspro.webcontrol.WebControlPro._getConfiguration",
90+
return_value=load_json_object_fixture("config_prod_load_switch.json", DOMAIN),
91+
) as mock_hub_configuration:
92+
yield mock_hub_configuration
93+
94+
8595
@pytest.fixture
8696
def mock_hub_configuration_prod_roller_shutter() -> Generator[AsyncMock]:
8797
"""Override WebControlPro._getConfiguration."""
@@ -114,6 +124,16 @@ def mock_hub_status_prod_dimmer() -> Generator[AsyncMock]:
114124
yield mock_hub_status
115125

116126

127+
@pytest.fixture
128+
def mock_hub_status_prod_load_switch() -> Generator[AsyncMock]:
129+
"""Override WebControlPro._getStatus."""
130+
with patch(
131+
"wmspro.webcontrol.WebControlPro._getStatus",
132+
return_value=load_json_object_fixture("status_prod_load_switch.json", DOMAIN),
133+
) as mock_hub_status:
134+
yield mock_hub_status
135+
136+
117137
@pytest.fixture
118138
def mock_hub_status_prod_roller_shutter() -> Generator[AsyncMock]:
119139
"""Override WebControlPro._getStatus."""
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
{
2+
"command": "getConfiguration",
3+
"protocolVersion": "1.0.0",
4+
"destinations": [
5+
{
6+
"id": 65355,
7+
"animationType": 3,
8+
"names": ["DACH", "", "", ""],
9+
"actions": [
10+
{
11+
"id": 6,
12+
"actionType": 2,
13+
"actionDescription": 3,
14+
"minValue": -127,
15+
"maxValue": 127
16+
},
17+
{
18+
"id": 16,
19+
"actionType": 6,
20+
"actionDescription": 12
21+
},
22+
{
23+
"id": 22,
24+
"actionType": 8,
25+
"actionDescription": 13
26+
},
27+
{
28+
"id": 23,
29+
"actionType": 7,
30+
"actionDescription": 12
31+
}
32+
]
33+
},
34+
{
35+
"id": 90732,
36+
"animationType": 1,
37+
"names": ["MARKISE LINKS", "", "", ""],
38+
"actions": [
39+
{
40+
"id": 0,
41+
"actionType": 0,
42+
"actionDescription": 0,
43+
"minValue": 0,
44+
"maxValue": 100
45+
},
46+
{
47+
"id": 16,
48+
"actionType": 6,
49+
"actionDescription": 12
50+
},
51+
{
52+
"id": 22,
53+
"actionType": 8,
54+
"actionDescription": 13
55+
}
56+
]
57+
},
58+
{
59+
"id": 159890,
60+
"animationType": 1,
61+
"names": ["MARKISE VORNE", "", "", ""],
62+
"actions": [
63+
{
64+
"id": 0,
65+
"actionType": 0,
66+
"actionDescription": 0,
67+
"minValue": 0,
68+
"maxValue": 100
69+
},
70+
{
71+
"id": 16,
72+
"actionType": 6,
73+
"actionDescription": 12
74+
},
75+
{
76+
"id": 22,
77+
"actionType": 8,
78+
"actionDescription": 13
79+
}
80+
]
81+
},
82+
{
83+
"id": 201106,
84+
"animationType": 1,
85+
"names": ["MARKISE RECHTS", "", "", ""],
86+
"actions": [
87+
{
88+
"id": 0,
89+
"actionType": 0,
90+
"actionDescription": 0,
91+
"minValue": 0,
92+
"maxValue": 100
93+
},
94+
{
95+
"id": 16,
96+
"actionType": 6,
97+
"actionDescription": 12
98+
},
99+
{
100+
"id": 22,
101+
"actionType": 8,
102+
"actionDescription": 13
103+
}
104+
]
105+
},
106+
{
107+
"id": 317448,
108+
"animationType": 6,
109+
"names": ["LICHT SENKRECHT", "", "", ""],
110+
"actions": [
111+
{
112+
"id": 0,
113+
"actionType": 0,
114+
"actionDescription": 8,
115+
"minValue": 0,
116+
"maxValue": 100
117+
},
118+
{
119+
"id": 17,
120+
"actionType": 6,
121+
"actionDescription": 12
122+
},
123+
{
124+
"id": 20,
125+
"actionType": 4,
126+
"actionDescription": 6
127+
},
128+
{
129+
"id": 22,
130+
"actionType": 8,
131+
"actionDescription": 13
132+
}
133+
]
134+
},
135+
{
136+
"id": 382168,
137+
"animationType": 6,
138+
"names": ["LICHT OBEN", "", "", ""],
139+
"actions": [
140+
{
141+
"id": 0,
142+
"actionType": 0,
143+
"actionDescription": 8,
144+
"minValue": 0,
145+
"maxValue": 100
146+
},
147+
{
148+
"id": 17,
149+
"actionType": 6,
150+
"actionDescription": 12
151+
},
152+
{
153+
"id": 20,
154+
"actionType": 4,
155+
"actionDescription": 6
156+
},
157+
{
158+
"id": 22,
159+
"actionType": 8,
160+
"actionDescription": 13
161+
}
162+
]
163+
},
164+
{
165+
"id": 414040,
166+
"animationType": 6,
167+
"names": ["LICHT UNTEN", "", "", ""],
168+
"actions": [
169+
{
170+
"id": 0,
171+
"actionType": 0,
172+
"actionDescription": 8,
173+
"minValue": 0,
174+
"maxValue": 100
175+
},
176+
{
177+
"id": 17,
178+
"actionType": 6,
179+
"actionDescription": 12
180+
},
181+
{
182+
"id": 20,
183+
"actionType": 4,
184+
"actionDescription": 6
185+
},
186+
{
187+
"id": 22,
188+
"actionType": 8,
189+
"actionDescription": 13
190+
}
191+
]
192+
},
193+
{
194+
"id": 499120,
195+
"animationType": 5,
196+
"names": ["HEIZUNG LINKS", "", "", ""],
197+
"actions": [
198+
{
199+
"id": 20,
200+
"actionType": 4,
201+
"actionDescription": 7
202+
},
203+
{
204+
"id": 21,
205+
"actionType": 5,
206+
"actionDescription": 10
207+
},
208+
{
209+
"id": 22,
210+
"actionType": 8,
211+
"actionDescription": 13
212+
}
213+
]
214+
},
215+
{
216+
"id": 533844,
217+
"animationType": 5,
218+
"names": ["HEIZUNG RECHTS", "", "", ""],
219+
"actions": [
220+
{
221+
"id": 20,
222+
"actionType": 4,
223+
"actionDescription": 7
224+
},
225+
{
226+
"id": 21,
227+
"actionType": 5,
228+
"actionDescription": 10
229+
},
230+
{
231+
"id": 22,
232+
"actionType": 8,
233+
"actionDescription": 13
234+
}
235+
]
236+
}
237+
],
238+
"rooms": [
239+
{
240+
"id": 39443,
241+
"name": "Terasse",
242+
"destinations": [
243+
65355, 90732, 159890, 201106, 317448, 382168, 414040, 499120, 533844
244+
],
245+
"scenes": []
246+
}
247+
],
248+
"scenes": []
249+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"command": "getStatus",
3+
"protocolVersion": "1.0.0",
4+
"details": [
5+
{
6+
"destinationId": 499120,
7+
"data": {
8+
"drivingCause": 0,
9+
"heartbeatError": false,
10+
"blocking": false,
11+
"productData": [
12+
{
13+
"actionId": 20,
14+
"value": {
15+
"onOffState": false
16+
}
17+
},
18+
{
19+
"actionId": 21,
20+
"value": {
21+
"onOffState": false
22+
}
23+
}
24+
]
25+
}
26+
}
27+
]
28+
}

0 commit comments

Comments
 (0)