Skip to content

Commit ef2277f

Browse files
committed
Add migration guide for upgrading from pyOverkiz v1 to v2
1 parent 896f34b commit ef2277f

3 files changed

Lines changed: 277 additions & 0 deletions

File tree

docs/getting-started.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ This guide will help you install the library, connect to your hub, and perform y
44

55
> Need the official Overkiz cloud API reference? Visit the [Overkiz API Documentation](https://ha101-1.overkiz.com/enduser-mobile-web/enduserAPI/doc) ([mirror](/api)). Most endpoints are accessible via the pyOverkiz package.
66
7+
> Upgrading from pyOverkiz 1.x? See the [migration guide](migration-v2.md) for a full list of breaking changes.
8+
79
## Prerequisites
810

911
- Python 3.12+

docs/migration-v2.md

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# Migrating from v1 to v2
2+
3+
This guide covers every breaking change in pyOverkiz 2.0 and shows how to update your code.
4+
5+
## Python version
6+
7+
pyOverkiz 2.0 requires **Python 3.12 or later**. If you are on an older version, upgrade Python first.
8+
9+
## Client constructor
10+
11+
The `OverkizClient` constructor is now keyword-only and uses dedicated credential classes instead of positional `username`/`password` arguments.
12+
13+
=== "v1"
14+
15+
```python
16+
from pyoverkiz.client import OverkizClient
17+
from pyoverkiz.const import SUPPORTED_SERVERS
18+
from pyoverkiz.enums import Server
19+
20+
client = OverkizClient("user@example.com", "password", SUPPORTED_SERVERS[Server.SOMFY_EUROPE])
21+
```
22+
23+
=== "v2"
24+
25+
```python
26+
from pyoverkiz.auth.credentials import UsernamePasswordCredentials
27+
from pyoverkiz.client import OverkizClient
28+
from pyoverkiz.enums import Server
29+
30+
client = OverkizClient(
31+
server=Server.SOMFY_EUROPE,
32+
credentials=UsernamePasswordCredentials("user@example.com", "password"),
33+
)
34+
```
35+
36+
Key differences:
37+
38+
- `server` accepts a `Server` enum, a server key string, or a `ServerConfig` instance directly — no need to look up `SUPPORTED_SERVERS` yourself.
39+
- Authentication details are wrapped in a `Credentials` subclass: `UsernamePasswordCredentials`, `TokenCredentials`, `LocalTokenCredentials`, or `RexelOAuthCodeCredentials`.
40+
- The `token` parameter is removed. Use `TokenCredentials` or `LocalTokenCredentials` instead.
41+
42+
### Local API
43+
44+
=== "v1"
45+
46+
```python
47+
from pyoverkiz.client import OverkizClient
48+
from pyoverkiz.utils import generate_local_server
49+
50+
server = generate_local_server(host="gateway-xxxx-xxxx-xxxx.local:8443")
51+
client = OverkizClient("", "", server, token="your-token")
52+
```
53+
54+
=== "v2"
55+
56+
```python
57+
from pyoverkiz.auth.credentials import LocalTokenCredentials
58+
from pyoverkiz.client import OverkizClient
59+
from pyoverkiz.utils import create_local_server_config
60+
61+
client = OverkizClient(
62+
server=create_local_server_config(host="gateway-xxxx-xxxx-xxxx.local:8443"),
63+
credentials=LocalTokenCredentials("your-token"),
64+
)
65+
```
66+
67+
## Server configuration
68+
69+
| v1 | v2 |
70+
|----|-----|
71+
| `OverkizServer` | `ServerConfig` |
72+
| `generate_local_server()` | `create_local_server_config()` |
73+
| `client.api_type` | `client.server_config.api_type` |
74+
75+
`ServerConfig` adds a `server` field (the `Server` enum key) and an explicit `api_type` field (`APIType.CLOUD` or `APIType.LOCAL`).
76+
77+
## Executing commands
78+
79+
The command execution API has been consolidated into a single method.
80+
81+
| v1 | v2 |
82+
|----|-----|
83+
| `client.execute_command(device_url, command)` | `client.execute_action_group(actions=[...])` |
84+
| `client.execute_commands(device_url, commands)` | `client.execute_action_group(actions=[...])` |
85+
| `Command` | `Action` wrapping one or more `Command` objects |
86+
87+
=== "v1"
88+
89+
```python
90+
from pyoverkiz.models import Command
91+
92+
await client.execute_command(
93+
"io://1234-5678-1234/12345678",
94+
Command("open", []),
95+
)
96+
```
97+
98+
=== "v2"
99+
100+
```python
101+
from pyoverkiz.models import Action, Command
102+
103+
await client.execute_action_group(
104+
actions=[
105+
Action(
106+
device_url="io://1234-5678-1234/12345678",
107+
commands=[Command(name="open")],
108+
)
109+
],
110+
)
111+
```
112+
113+
v2 also supports sending actions to **multiple devices** in a single call and choosing an `ExecutionMode` (`HIGH_PRIORITY`, `GEOLOCATED`, `INTERNAL`).
114+
115+
## Scenarios → Action groups
116+
117+
| v1 | v2 |
118+
|----|-----|
119+
| `Scenario` | `ActionGroup` |
120+
| `client.get_scenarios()` | `client.get_action_groups()` |
121+
| `client.execute_scenario(oid)` | `client.execute_persisted_action_group(oid)` |
122+
| `client.execute_scheduled_scenario(oid, ts)` | `client.schedule_persisted_action_group(oid, ts)` |
123+
124+
`ActionGroup.id` and `ActionGroup.oid` are now `str | None` instead of `str`. `ActionGroup.creation_time` and `ActionGroup.metadata` are now optional.
125+
126+
## Execution methods
127+
128+
| v1 | v2 |
129+
|----|-----|
130+
| `CommandMode` | `ExecutionMode` |
131+
| `client.cancel_command(exec_id)` | `client.cancel_execution(exec_id)` |
132+
| `client.get_current_execution(exec_id)` returns `Execution` | Returns `Execution | None` |
133+
| `Execution.state` is `str` | `Execution.state` is `ExecutionState` |
134+
135+
## Device model
136+
137+
### Removed fields
138+
139+
- `Device.id` — was a duplicate of `device_url`.
140+
- `Device.data_properties` — was never populated by the API.
141+
142+
### Moved fields
143+
144+
Device URL components are now grouped under `device.identifier`:
145+
146+
| v1 | v2 |
147+
|----|-----|
148+
| `device.protocol` | `device.identifier.protocol` |
149+
| `device.gateway_id` | `device.identifier.gateway_id` |
150+
| `device.device_address` | `device.identifier.device_address` |
151+
| `device.subsystem_id` | `device.identifier.subsystem_id` |
152+
| `device.is_sub_device` | `device.identifier.is_sub_device` |
153+
154+
The identifier also provides `device.identifier.base_device_url`.
155+
156+
### New helper methods
157+
158+
The `Device` class now provides convenience methods — see the [device control guide](device-control.md) for details:
159+
160+
- `device.get_state_value()`, `device.select_first_state_value()`, `device.has_state_value()`
161+
- `device.supports_command()`, `device.supports_any_command()`, `device.select_first_command()`
162+
- `device.get_attribute_value()`, `device.select_first_attribute_value()`
163+
- `device.get_state_definition()`, `device.select_first_state_definition()`
164+
165+
## Exceptions
166+
167+
All exception classes have been renamed from `*Exception` to `*Error` following [PEP 8](https://peps.python.org/pep-0008/#exception-names):
168+
169+
| v1 | v2 |
170+
|----|-----|
171+
| `BaseOverkizException` | `BaseOverkizError` |
172+
| `OverkizException` | `OverkizError` |
173+
| `BadCredentialsException` | `BadCredentialsError` |
174+
| `NotAuthenticatedException` | `NotAuthenticatedError` |
175+
| `TooManyRequestsException` | `TooManyRequestsError` |
176+
| `MaintenanceException` | `MaintenanceError` |
177+
| `NotSuchTokenException` | `NoSuchTokenError` (typo fixed) |
178+
| ... | _(all other exceptions follow the same pattern)_ |
179+
180+
New exception types in v2: `NoSuchDeviceError`, `NoSuchActionGroupError`, `UnsupportedOperationError`.
181+
182+
A quick way to update all imports:
183+
184+
```bash
185+
# Find and replace across your codebase
186+
find . -name "*.py" -exec sed -i '' 's/Exception\b/Error/g' {} +
187+
```
188+
189+
!!! warning
190+
The sed command above is intentionally broad. Review the result to avoid renaming unrelated exception classes in your own code.
191+
192+
## Enum renames
193+
194+
All enums with an `UNKNOWN` fallback now inherit from `UnknownEnumMixin`. Unrecognized values returned by the API produce an `UNKNOWN` member with a logged warning instead of raising a `ValueError`.
195+
196+
Several enum members have been renamed for consistent `UPPER_SNAKE_CASE` or to fix typos. The tables below list every rename.
197+
198+
### UIClass
199+
200+
??? note "Renamed members"
201+
202+
| v1 | v2 | Note |
203+
|----|-----|------|
204+
| `VENTILATION_SYTEM` | `VENTILATION_SYSTEM` | Typo fix |
205+
206+
### UIWidget
207+
208+
??? note "Renamed members"
209+
210+
| v1 | v2 | Note |
211+
|----|-----|------|
212+
| `CYCLIC_SWINGING_GATE_OPENER` | `CYCLIC_SWINGING_GATE_OPENER` | Trailing space removed from value |
213+
| `DIMMER_RGBCOLOURED_LIGHT` | `DIMMER_RGB_COLOURED_LIGHT` | |
214+
| `EWATTCH_TICCOUNTER` | `EWATTCH_TIC_COUNTER` | |
215+
| `GENERIC_16_CHANNELS_COUNTER` | `GENERIC16_CHANNELS_COUNTER` | |
216+
| `GENERIC_1_CHANNEL_COUNTER` | `GENERIC1_CHANNEL_COUNTER` | |
217+
| `IOGENERIC` | `IO_GENERIC` | |
218+
| `IOSIREN` | `IO_SIREN` | |
219+
| `IOSTACK` | `IO_STACK` | |
220+
| `IRBLASTER` | `IR_BLASTER` | |
221+
| `JSWCAMERA` | `JSW_CAMERA` | |
222+
| `OPEN_CLOSE_GATE_4T` | `OPEN_CLOSE_GATE4_T` | |
223+
| `OPEN_CLOSE_SLIDING_GARAGE_DOOR_4T` | `OPEN_CLOSE_SLIDING_GARAGE_DOOR4_T` | |
224+
| `OPEN_CLOSE_SLIDING_GATE_4T` | `OPEN_CLOSE_SLIDING_GATE4_T` | |
225+
| `OVPGENERIC` | `OVP_GENERIC` | |
226+
| `RTS_GENERIC_4T` | `RTS_GENERIC4_T` | |
227+
| `ROCKER_SWITCHX_1_CONTROLLER` | `ROCKER_SWITCHX1_CONTROLLER` | |
228+
| `ROCKER_SWITCHX_2_CONTROLLER` | `ROCKER_SWITCHX2_CONTROLLER` | |
229+
| `ROCKER_SWITCHX_4_CONTROLLER` | `ROCKER_SWITCHX4_CONTROLLER` | |
230+
| `TSKALARM_CONTROLLER` | `TSK_ALARM_CONTROLLER` | |
231+
| `UP_DOWN_GARAGE_DOOR_4T` | `UP_DOWN_GARAGE_DOOR4_T` | |
232+
| `VOCSENSOR` | `VOC_SENSOR` | |
233+
| `ZWAVE_DANFOSS_RSLINK` | `ZWAVE_DANFOSS_RS_LINK` | |
234+
| `ZWAVE_SEDEVICE_CONFIGURATION` | `ZWAVE_SE_DEVICE_CONFIGURATION` | |
235+
236+
### Protocol
237+
238+
??? note "New members"
239+
240+
| Member | Value |
241+
|--------|-------|
242+
| `SONOS` | `sonos` |
243+
244+
### GatewaySubType
245+
246+
??? note "New members"
247+
248+
| Member | Value |
249+
|--------|-------|
250+
| `TAHOMA_BOX_C_IO` | `17` |
251+
252+
### New enums in v2
253+
254+
- `UIProfile` — auto-generated from server definitions.
255+
- `UIClassifier` — categorizes device types (e.g. `SENSOR`, `EMITTER`, `GENERATOR`).
256+
- `ExecutionState` — typed states for `Execution.state`.
257+
- `UpdateCriticityLevel` — criticity level of gateway updates.
258+
259+
## Other changes
260+
261+
| v1 | v2 |
262+
|----|-----|
263+
| `Setup.id` always set | `Setup.id` is `None` for Local API |
264+
| `get_diagnostic_data()` | `get_diagnostic_data(mask_sensitive_data=True)` — opt out of PII masking |
265+
266+
## New features in v2
267+
268+
These are not breaking, but worth knowing about when migrating:
269+
270+
- **Action queue** — batch device executions automatically. See the [action queue guide](action-queue.md).
271+
- **Reference endpoints** — query server metadata: `get_reference_ui_classes()`, `get_reference_ui_widgets()`, `get_reference_ui_profile()`, `get_reference_controllable_types()`, etc.
272+
- **Firmware management**`get_devices_not_up_to_date()`, `get_device_firmware_status()`, `update_device_firmware()`.
273+
- **boto3 lazy import**`boto3` is only imported when the Nexity auth strategy is actually used.

mkdocs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ markdown_extensions:
3636
- pymdownx.superfences
3737
- pymdownx.tasklist
3838
- admonition
39+
- pymdownx.details
3940
- pymdownx.superfences
4041
- pymdownx.tabbed:
4142
alternate_style: true
@@ -49,5 +50,6 @@ nav:
4950
- Action queue: action-queue.md
5051
- Event handling: event-handling.md
5152
- Troubleshooting: troubleshooting.md
53+
- Migrating from v1: migration-v2.md
5254
- API Reference: api-reference.md
5355
- Contribute: contribute.md

0 commit comments

Comments
 (0)