Skip to content

Commit a5254ac

Browse files
authored
Merge pull request #231 from loopj/group-improvements
Improvements to 'group' objects
2 parents cf3e983 + 6cc4a14 commit a5254ac

File tree

11 files changed

+53
-93
lines changed

11 files changed

+53
-93
lines changed

src/aiovantage/_config_client/client.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ async def raw_request(self, request: str, separator: str) -> str:
131131

132132
return response
133133

134-
async def rpc_call(
134+
async def rpc(
135135
self,
136136
interface_cls: type[Interface],
137137
method_cls: type[Method[Call, Return]],

src/aiovantage/_config_client/interfaces/configuration.py

+15-38
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
"""IConfiguration interfaces."""
2-
31
from collections.abc import AsyncIterator
42
from contextlib import suppress
53
from dataclasses import dataclass, field
@@ -13,13 +11,16 @@
1311

1412

1513
@dataclass
16-
class OpenFilter:
17-
"""IConfiguration.OpenFilter method definition."""
14+
class WrappedObject:
15+
# Wildcard type that can be used to represent any object.
16+
vid: int = field(metadata={"name": "VID", "type": "Attribute"})
17+
obj: object = field(metadata={"type": "Wildcard"})
18+
1819

20+
@dataclass
21+
class OpenFilter:
1922
@dataclass
2023
class Params:
21-
"""Method parameters."""
22-
2324
object_types: list[str] | None = field(
2425
default=None,
2526
metadata={"wrapper": "Objects", "name": "ObjectType", "type": "Element"},
@@ -32,64 +33,40 @@ class Params:
3233

3334
@dataclass
3435
class GetFilterResults:
35-
"""IConfiguration.GetFilterResults method definition."""
36-
3736
@dataclass
3837
class Params:
39-
"""Method parameters."""
40-
4138
h_filter: int = field(metadata={"name": "hFilter"})
4239
count: int = 50
4340
whole_object: bool = True
4441

45-
@dataclass
46-
class Object:
47-
"""Wildcard type that can be used to represent any object."""
48-
49-
vid: int = field(metadata={"name": "VID", "type": "Attribute"})
50-
obj: object = field(metadata={"type": "Wildcard"})
51-
5242
call: Params | None = field(default=None, metadata={"name": "call"})
53-
result: list[Object] | None = field(
43+
result: list[WrappedObject] | None = field(
5444
default_factory=list,
5545
metadata={"wrapper": "return", "name": "Object", "type": "Element"},
5646
)
5747

5848

5949
@dataclass
6050
class CloseFilter:
61-
"""IConfiguration.CloseFilter method definition."""
62-
6351
call: int | None = field(default=None, metadata={"name": "call"})
6452
result: bool | None = field(default=None, metadata={"name": "return"})
6553

6654

6755
@dataclass
6856
class GetObject:
69-
"""IConfiguration.GetObject method definition."""
70-
71-
@dataclass
72-
class Object:
73-
"""Wildcard type that can be used to represent any object."""
74-
75-
vid: int = field(metadata={"name": "VID", "type": "Attribute"})
76-
obj: object = field(metadata={"type": "Wildcard"})
77-
7857
call: list[int] | None = field(
7958
default_factory=list,
8059
metadata={"wrapper": "call", "name": "VID", "type": "Element"},
8160
)
8261

83-
result: list[Object] | None = field(
62+
result: list[WrappedObject] | None = field(
8463
default_factory=list,
8564
metadata={"wrapper": "return", "name": "Object", "type": "Element"},
8665
)
8766

8867

8968
@dataclass(kw_only=True)
9069
class IConfiguration:
91-
"""IConfiguration interface."""
92-
9370
open_filter: OpenFilter | None = None
9471
get_filter_results: GetFilterResults | None = None
9572
close_filter: CloseFilter | None = None
@@ -113,7 +90,7 @@ async def open_filter(
11390
Returns:
11491
The handle of the opened filter
11592
"""
116-
return await client.rpc_call(
93+
return await client.rpc(
11794
IConfiguration,
11895
OpenFilter,
11996
OpenFilter.Params(object_types=list(object_types), xpath=xpath),
@@ -122,7 +99,7 @@ async def open_filter(
12299
@staticmethod
123100
async def get_filter_results(
124101
client: ConfigClient, h_filter: int, count: int = 50, whole_object: bool = True
125-
) -> list[GetFilterResults.Object]:
102+
) -> list[WrappedObject]:
126103
"""Get results from a filter handle previously opened with open_filter.
127104
128105
Args:
@@ -134,7 +111,7 @@ async def get_filter_results(
134111
Returns:
135112
A list of Vantage objects
136113
"""
137-
return await client.rpc_call(
114+
return await client.rpc(
138115
IConfiguration, GetFilterResults, GetFilterResults.Params(h_filter)
139116
)
140117

@@ -149,10 +126,10 @@ async def close_filter(client: ConfigClient, h_filter: int) -> bool:
149126
Returns:
150127
True if the filter was closed successfully, False otherwise
151128
"""
152-
return await client.rpc_call(IConfiguration, CloseFilter, h_filter)
129+
return await client.rpc(IConfiguration, CloseFilter, h_filter)
153130

154131
@staticmethod
155-
async def get_object(client: ConfigClient, *vids: int) -> list[GetObject.Object]:
132+
async def get_object(client: ConfigClient, *vids: int) -> list[WrappedObject]:
156133
"""Get one or more Vantage objects by their VIDs.
157134
158135
Args:
@@ -162,7 +139,7 @@ async def get_object(client: ConfigClient, *vids: int) -> list[GetObject.Object]
162139
Returns:
163140
A list of Vantage objects
164141
"""
165-
return await client.rpc_call(IConfiguration, GetObject, list(vids))
142+
return await client.rpc(IConfiguration, GetObject, list(vids))
166143

167144
# Convenience functions, not part of the interface
168145
@overload

src/aiovantage/_config_client/interfaces/introspection.py

+4-24
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1-
"""IIntrospection interface."""
2-
31
from dataclasses import dataclass, field
42

53
from ..client import ConfigClient
64

75

86
@dataclass
97
class GetInterfaces:
10-
"""IIntrospection.GetInterfaces method definition."""
11-
128
@dataclass
139
class Interface:
14-
"""Object interface definition."""
15-
1610
name: str
1711
version: str
1812
iid: int = field(metadata={"name": "IID"})
@@ -26,12 +20,8 @@ class Interface:
2620

2721
@dataclass
2822
class GetSysInfo:
29-
"""IIntrospection.GetSysInfo method definition."""
30-
3123
@dataclass
3224
class SysInfo:
33-
"""SysInfo class."""
34-
3525
master_number: int
3626
serial_number: int
3727

@@ -43,12 +33,8 @@ class SysInfo:
4333

4434
@dataclass
4535
class GetTypes:
46-
"""IIntrospection.GetTypes method definition."""
47-
4836
@dataclass
4937
class Type:
50-
"""Object type definition."""
51-
5238
name: str
5339
version: str
5440

@@ -60,12 +46,8 @@ class Type:
6046

6147
@dataclass
6248
class GetVersion:
63-
"""IIntrospection.GetVersion method definition."""
64-
6549
@dataclass
6650
class Version:
67-
"""Method return value."""
68-
6951
kernel: str | None = field(default=None, metadata={"name": "kernel"})
7052
rootfs: str | None = field(default=None, metadata={"name": "rootfs"})
7153
app: str | None = field(default=None, metadata={"name": "app"})
@@ -76,8 +58,6 @@ class Version:
7658

7759
@dataclass(kw_only=True)
7860
class IIntrospection:
79-
"""IIntrospection interface."""
80-
8161
get_interfaces: GetInterfaces | None = None
8262
get_sys_info: GetSysInfo | None = None
8363
get_types: GetTypes | None = None
@@ -97,7 +77,7 @@ async def get_interfaces(client: ConfigClient) -> list[GetInterfaces.Interface]:
9777
Returns:
9878
A list of interfaces.
9979
"""
100-
return await client.rpc_call(IIntrospection, GetInterfaces)
80+
return await client.rpc(IIntrospection, GetInterfaces)
10181

10282
@staticmethod
10383
async def get_sys_info(client: ConfigClient) -> GetSysInfo.SysInfo:
@@ -109,7 +89,7 @@ async def get_sys_info(client: ConfigClient) -> GetSysInfo.SysInfo:
10989
Returns:
11090
A system information object.
11191
"""
112-
return await client.rpc_call(IIntrospection, GetSysInfo)
92+
return await client.rpc(IIntrospection, GetSysInfo)
11393

11494
@staticmethod
11595
async def get_types(client: ConfigClient) -> list[GetTypes.Type]:
@@ -121,7 +101,7 @@ async def get_types(client: ConfigClient) -> list[GetTypes.Type]:
121101
Returns:
122102
A list of object types.
123103
"""
124-
return await client.rpc_call(IIntrospection, GetTypes)
104+
return await client.rpc(IIntrospection, GetTypes)
125105

126106
@staticmethod
127107
async def get_version(client: ConfigClient) -> GetVersion.Version:
@@ -133,4 +113,4 @@ async def get_version(client: ConfigClient) -> GetVersion.Version:
133113
Returns:
134114
A version information object.
135115
"""
136-
return await client.rpc_call(IIntrospection, GetVersion)
116+
return await client.rpc(IIntrospection, GetVersion)

src/aiovantage/_config_client/interfaces/login.py

+1-9
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
1-
"""ILogin.Login method definition."""
2-
31
from dataclasses import dataclass, field
42

53
from ..client import ConfigClient
64

75

86
@dataclass
97
class Login:
10-
"""ILogin.Login method definition."""
11-
128
@dataclass
139
class Params:
14-
"""Method parameters."""
15-
1610
user: str
1711
password: str
1812

@@ -22,8 +16,6 @@ class Params:
2216

2317
@dataclass(kw_only=True)
2418
class ILogin:
25-
"""ILogin interface."""
26-
2719
login: Login | None = None
2820

2921

@@ -42,6 +34,6 @@ async def login(client: ConfigClient, user: str, password: str) -> bool:
4234
Returns:
4335
True if the login was successful, False otherwise
4436
"""
45-
return await client.rpc_call(
37+
return await client.rpc(
4638
ILogin, Login, Login.Params(user=user, password=password)
4739
)

src/aiovantage/_controllers/blind_groups.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
from .base import BaseController
44

5+
BlindGroupTypes = BlindGroup | SomfyRS485GroupChild | SomfyURTSI2GroupChild
6+
"""Types managed by the blind groups controller."""
57

6-
class BlindGroupsController(
7-
BaseController[BlindGroup | SomfyRS485GroupChild | SomfyURTSI2GroupChild]
8-
):
8+
9+
class BlindGroupsController(BaseController[BlindGroupTypes]):
910
"""Blind groups controller."""
1011

1112
vantage_types = (

src/aiovantage/_controllers/blinds.py

+6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from aiovantage.objects import (
2+
BlindGroup,
23
QISBlind,
34
QubeBlind,
45
RelayBlind,
@@ -7,6 +8,7 @@
78
)
89

910
from .base import BaseController
11+
from .query import QuerySet
1012

1113
BlindTypes = (
1214
QISBlind | QubeBlind | RelayBlind | SomfyRS485ShadeChild | SomfyURTSI2ShadeChild
@@ -24,3 +26,7 @@ class BlindsController(BaseController[BlindTypes]):
2426
"Somfy.RS-485_Shade_CHILD",
2527
"Somfy.URTSI_2_Shade_CHILD",
2628
)
29+
30+
def in_blind_group(self, blind_group: BlindGroup) -> QuerySet[BlindTypes]:
31+
"""Return a queryset of all loads in the given blind group."""
32+
return self.filter(lambda load: load.vid in blind_group.blind_table)
+1-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from aiovantage._controllers.query import QuerySet
2-
from aiovantage.objects import Load, LoadGroup
1+
from aiovantage.objects import LoadGroup
32

43
from .base import BaseController
54

@@ -8,9 +7,3 @@ class LoadGroupsController(BaseController[LoadGroup]):
87
"""Load groups controller."""
98

109
vantage_types = ("LoadGroup",)
11-
12-
def loads(self, vid: int) -> QuerySet[Load]:
13-
"""Return a queryset of all loads in this load group."""
14-
load_group = self[vid]
15-
16-
return self._vantage.loads.filter(lambda load: load.id in load_group.load_table)

src/aiovantage/_controllers/loads.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from aiovantage._controllers.query import QuerySet
2-
from aiovantage.objects import Load
1+
from aiovantage.objects import Load, LoadGroup
32

43
from .base import BaseController
4+
from .query import QuerySet
55

66

77
class LoadsController(BaseController[Load]):
@@ -33,3 +33,7 @@ def motors(self) -> QuerySet[Load]:
3333
def lights(self) -> QuerySet[Load]:
3434
"""Return a queryset of all loads that are lights."""
3535
return self.filter(lambda load: load.is_light)
36+
37+
def in_load_group(self, load_group: LoadGroup) -> QuerySet[Load]:
38+
"""Return a queryset of all loads in the given load group."""
39+
return self.filter(lambda load: load.vid in load_group.load_table)

src/aiovantage/_controllers/rgb_loads.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from aiovantage._controllers.query import QuerySet
21
from aiovantage.objects import VantageDDGColorLoad, VantageDGColorLoad
32

43
from .base import BaseController
4+
from .query import QuerySet
55

66
RGBLoadTypes = VantageDDGColorLoad | VantageDGColorLoad
77
"""Types managed by the RGB loads controller."""

0 commit comments

Comments
 (0)