Skip to content

Commit bf67bd1

Browse files
authored
Improve Device model (#1930)
## Breaking - The Device class no longer includes the `id` property, and the following fields have been moved into `device.identifier.{}`: `protocol`, `gateway_id`, `device_address`, and `subsystem_id`. - Device.data_properties has been removed, as it was a non-existent value. ## Enhancement - Device class now has helper methods for retrieving the state value, commands and definition. - Device class now has an `identifier` property with protocol, gateway_id, device_address, subsystem_id and base_device_url fields. - The Device class now includes additional fields (data_properties, ui_profiles, ui_classifiers, attributes) under device.definition. ## Full changelog Fixes #1923 This pull request refactors and enhances the device modeling logic in `pyoverkiz/models.py`, introducing a new `DeviceIdentifier` class to encapsulate device URL parsing and related properties. It also adds several helper methods to the `Device`, `States`, `Definition`, and `CommandDefinitions` classes, improving code clarity and testability. Extensive new tests are added to ensure the correctness of these helpers and the new identifier logic. **Device identifier and URL parsing improvements:** * Introduced a new `DeviceIdentifier` class to encapsulate parsing and properties of device URLs, replacing scattered parsing logic and related fields in the `Device` class. Device URL parsing now raises a `ValueError` for invalid formats. (`pyoverkiz/models.py`) * Refactored the `Device` class to use the new `identifier` property instead of separate protocol, gateway_id, device_address, and subsystem_id fields. (`pyoverkiz/models.py`) [[1]](diffhunk://#diff-abae13362160dc5f0aff1ba910ffe223a87f52dfda3a77f160ad13a6a9dbc92cL186-L194) [[2]](diffhunk://#diff-abae13362160dc5f0aff1ba910ffe223a87f52dfda3a77f160ad13a6a9dbc92cL207-R299) **Helper methods and API enhancements:** * Added helper methods to `Device`, `States`, `Definition`, and `CommandDefinitions` classes (e.g., `get_supported_command_name`, `has_supported_command`, `get_state_value`, `get_state_definition`, `select`, `has_any`) to simplify common queries and checks. (`pyoverkiz/models.py`) [[1]](diffhunk://#diff-abae13362160dc5f0aff1ba910ffe223a87f52dfda3a77f160ad13a6a9dbc92cL207-R299) [[2]](diffhunk://#diff-abae13362160dc5f0aff1ba910ffe223a87f52dfda3a77f160ad13a6a9dbc92cR355-R366) [[3]](diffhunk://#diff-abae13362160dc5f0aff1ba910ffe223a87f52dfda3a77f160ad13a6a9dbc92cR409-R418) [[4]](diffhunk://#diff-abae13362160dc5f0aff1ba910ffe223a87f52dfda3a77f160ad13a6a9dbc92cR557-R573) **Testing improvements:** * Updated and expanded tests to cover the new `DeviceIdentifier` logic, helper methods, and error handling for invalid device URLs. Added new test cases for the helper methods in `Device`, `States`, `Definition`, and `CommandDefinitions`. (`tests/test_client.py`, `tests/test_models.py`) [[1]](diffhunk://#diff-0d92063e88430a02df61616c5f16b148b64ac4539d9cb9b8d883d5a23351b110L279-R281) [[2]](diffhunk://#diff-0adb667cd397bd56edce10eec11e1b10821740a10d72bd148b09645fc9108968L9-R15) [[3]](diffhunk://#diff-0adb667cd397bd56edce10eec11e1b10821740a10d72bd148b09645fc9108968L154-L170) [[4]](diffhunk://#diff-0adb667cd397bd56edce10eec11e1b10821740a10d72bd148b09645fc9108968L190-R194) [[5]](diffhunk://#diff-0adb667cd397bd56edce10eec11e1b10821740a10d72bd148b09645fc9108968R203-R241) [[6]](diffhunk://#diff-0adb667cd397bd56edce10eec11e1b10821740a10d72bd148b09645fc9108968R273-R374) **Code cleanup:** * Removed legacy or redundant fields and parsing logic from the `Device` class, and improved fallback logic for `ui_class` and `widget` properties. (`pyoverkiz/models.py`) [[1]](diffhunk://#diff-abae13362160dc5f0aff1ba910ffe223a87f52dfda3a77f160ad13a6a9dbc92cL186-L194) [[2]](diffhunk://#diff-abae13362160dc5f0aff1ba910ffe223a87f52dfda3a77f160ad13a6a9dbc92cL207-R299) These changes improve the maintainability and usability of the device modeling code, making it easier to work with device URLs and query device capabilities in a robust and testable way.
1 parent c83c9c9 commit bf67bd1

File tree

4 files changed

+525
-61
lines changed

4 files changed

+525
-61
lines changed

docs/device-control.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ devices = await client.get_devices()
2424
# For demo purposes we take the first available device
2525
device = devices[0]
2626

27+
# Traditional approach
2728
availability_state = next(
2829
(state for state in device.states if state.name == OverkizState.CORE_AVAILABILITY),
2930
None,
@@ -32,6 +33,92 @@ availability_state = next(
3233
print(availability_state.value if availability_state else None)
3334
```
3435

36+
### Helper methods for device state queries
37+
38+
The `Device` class provides convenient helper methods for querying device states, commands, and their definitions:
39+
40+
#### Get state value
41+
42+
```python
43+
from pyoverkiz.enums import OverkizState
44+
45+
devices = await client.get_devices()
46+
device = devices[0]
47+
48+
# Get the value of the first matching state
49+
slats_orientation = device.get_state_value([OverkizState.CORE_SLATS_ORIENTATION, OverkizState.CORE_SLATE_ORIENTATION])
50+
print(f"Orientation: {slats_orientation}")
51+
52+
# Check if a state has a non-None value
53+
if device.has_state_value([OverkizState.CORE_SLATS_ORIENTATION, OverkizState.CORE_SLATE_ORIENTATION]):
54+
print("Device has a slats orientation")
55+
```
56+
57+
#### Get state definition
58+
59+
```python
60+
devices = await client.get_devices()
61+
device = devices[0]
62+
63+
# Get the state definition for querying type, valid values, etc.
64+
state_def = device.get_state_definition([OverkizState.CORE_OPEN_CLOSED, OverkizState.CORE_SLATS_OPEN_CLOSED])
65+
if state_def:
66+
print(f"Type: {state_def.type}")
67+
print(f"Valid values: {state_def.values}")
68+
```
69+
70+
#### Check supported commands
71+
72+
```python
73+
from pyoverkiz.enums import OverkizCommand
74+
75+
devices = await client.get_devices()
76+
device = devices[0]
77+
78+
# Check if device supports any of the given commands
79+
if device.has_supported_command([OverkizCommand.OPEN, OverkizCommand.CLOSE]):
80+
print("Device supports open/close commands")
81+
82+
# Get the first supported command from a list
83+
supported_cmd = device.get_supported_command_name(
84+
[OverkizCommand.SET_CLOSURE, OverkizCommand.OPEN, OverkizCommand.CLOSE]
85+
)
86+
if supported_cmd:
87+
print(f"Supported command: {supported_cmd}")
88+
```
89+
90+
#### Get attribute value
91+
92+
```python
93+
devices = await client.get_devices()
94+
device = devices[0]
95+
96+
# Get the value of device attributes (like firmware)
97+
firmware = device.get_attribute_value([
98+
OverkizAttribute.CORE_FIRMWARE_REVISION,
99+
])
100+
print(f"Firmware: {firmware}")
101+
```
102+
103+
#### Access device identifier
104+
105+
Device URLs are automatically parsed into structured identifier components for easier access:
106+
107+
```python
108+
devices = await client.get_devices()
109+
device = devices[0]
110+
111+
# Access parsed device URL components
112+
print(f"Protocol: {device.identifier.protocol}")
113+
print(f"Gateway ID: {device.identifier.gateway_id}")
114+
print(f"Device address: {device.identifier.device_address}")
115+
print(f"Base device URL: {device.identifier.base_device_url}")
116+
117+
# Check if this is a sub-device
118+
if device.identifier.is_sub_device:
119+
print(f"Sub-device ID: {device.identifier.subsystem_id}")
120+
```
121+
35122
## Send a command
36123

37124
```python

0 commit comments

Comments
 (0)