Skip to content

Commit ba97bd5

Browse files
committed
Add first (AI generated) version
1 parent 07882f8 commit ba97bd5

File tree

14 files changed

+1082
-0
lines changed

14 files changed

+1082
-0
lines changed

.github/workflows/docs.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: docs
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- v2/docs
8+
9+
permissions:
10+
contents: write
11+
12+
jobs:
13+
build-and-deploy:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: "3.11"
23+
24+
- name: Set up uv
25+
uses: astral-sh/setup-uv@v3
26+
27+
- name: Install docs dependencies
28+
run: uv pip install -e ".[docs]"
29+
30+
- name: Build site
31+
run: uv run mkdocs build
32+
33+
- name: Deploy to GitHub Pages
34+
uses: peaceiris/actions-gh-pages@v4
35+
with:
36+
github_token: ${{ secrets.GITHUB_TOKEN }}
37+
publish_dir: site

docs/api-reference.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
::: pyoverkiz.client.OverkizClient
2+
3+
::: pyoverkiz.models
4+
options:
5+
show_source: false
6+
7+
::: pyoverkiz.enums
8+
options:
9+
show_source: false
10+
11+
::: pyoverkiz.exceptions
12+
options:
13+
show_source: false

docs/authentication.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Authentication
2+
3+
## Cloud username and password
4+
5+
Cloud authentication uses a vendor server from `Server` plus `UsernamePasswordCredentials`.
6+
7+
```python
8+
import asyncio
9+
10+
from pyoverkiz.auth.credentials import UsernamePasswordCredentials
11+
from pyoverkiz.client import OverkizClient
12+
from pyoverkiz.enums import Server
13+
14+
15+
async def main() -> None:
16+
async with OverkizClient(
17+
server=Server.SOMFY_EUROPE,
18+
credentials=UsernamePasswordCredentials("[email protected]", "password"),
19+
) as client:
20+
await client.login()
21+
print(await client.get_api_version())
22+
23+
24+
asyncio.run(main())
25+
```
26+
27+
## Local token authentication
28+
29+
Local authentication requires a token generated by the official mobile app and a local user on the OverKiz API platform.
30+
31+
```python
32+
import asyncio
33+
34+
from pyoverkiz.auth.credentials import LocalTokenCredentials
35+
from pyoverkiz.client import OverkizClient
36+
from pyoverkiz.utils import create_local_server_config
37+
38+
39+
async def main() -> None:
40+
async with OverkizClient(
41+
server=create_local_server_config(host="gateway-xxxx.local"),
42+
credentials=LocalTokenCredentials("local-token"),
43+
verify_ssl=False,
44+
) as client:
45+
await client.login()
46+
print(await client.get_api_version())
47+
48+
49+
asyncio.run(main())
50+
```
51+
52+
## Token refresh behavior
53+
54+
The client refreshes access tokens as needed during authenticated calls. If you see authentication errors, re-run `login()` before retrying the request.
55+
56+
## Unsupported auth flows
57+
58+
Some vendors use authentication flows that are not supported. In those cases, obtain a local token and use a local server configuration instead.
59+
60+
## Secure storage tips
61+
62+
- Use environment variables or a secret manager for tokens.
63+
- Avoid hard-coding credentials in source control.
64+
- Rotate tokens regularly if your vendor supports it.

docs/contribute.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Contribute
2+
3+
Thanks for contributing to pyOverkiz! This project powers production integrations and values careful changes, clear tests, and thoughtful documentation.
4+
5+
## Development setup
6+
7+
```bash
8+
uv sync
9+
```
10+
11+
Install git hooks:
12+
13+
```bash
14+
uv run prek install
15+
```
16+
17+
## Tests and linting
18+
19+
```bash
20+
uv run pytest
21+
```
22+
23+
```bash
24+
uv run prek run --all-files
25+
```
26+
27+
## Project guidelines
28+
29+
- Use Python 3.10–3.13 features and type annotations.
30+
- Keep absolute imports and avoid relative imports.
31+
- Preserve existing comments and logging unless your change requires updates.
32+
- Prefer small, focused changes and add tests when behavior changes.
33+
34+
## Submitting changes
35+
36+
1. Create a feature branch.
37+
2. Run linting and tests.
38+
3. Open a pull request with a clear description and context.

docs/core-concepts.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Core concepts
2+
3+
## Servers and gateways
4+
5+
A server describes where the API calls go. A gateway is the physical hub in your home. Cloud servers route through vendor infrastructure; local servers talk directly to the gateway on your network.
6+
7+
## Setup and devices
8+
9+
The setup describes the current gateway configuration and device inventory. Devices expose metadata like `uiClass` and `widget`, plus a list of current `states`.
10+
11+
## Actions, action groups, and commands
12+
13+
Commands are sent as `Action` objects, grouped into an action group. Each action targets a device URL and a set of commands with parameters.
14+
15+
## States
16+
17+
States are name/value pairs that represent the current device status, such as closure position or temperature.
18+
19+
## Events and listeners
20+
21+
The API uses an event listener that you register once per session. Fetching events drains the server-side buffer.
22+
23+
## Execution model
24+
25+
Commands are executed asynchronously by the platform. You can poll execution state via events or refresh device states after a delay.
26+
27+
## Relationship diagram
28+
29+
```
30+
Client
31+
|
32+
|-- Server (cloud or local)
33+
|
34+
|-- Gateway
35+
|
36+
|-- Setup
37+
| |
38+
| |-- Devices
39+
| |
40+
| |-- States
41+
| |-- Actions -> Commands -> Parameters
42+
|
43+
|-- Event Listener -> Events
44+
```

docs/device-control.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Device control
2+
3+
## List devices
4+
5+
```python
6+
import asyncio
7+
8+
from pyoverkiz.auth.credentials import UsernamePasswordCredentials
9+
from pyoverkiz.client import OverkizClient
10+
from pyoverkiz.enums import Server
11+
12+
13+
async def main() -> None:
14+
async with OverkizClient(
15+
server=Server.SOMFY_EUROPE,
16+
credentials=UsernamePasswordCredentials("[email protected]", "password"),
17+
) as client:
18+
await client.login()
19+
devices = await client.get_devices()
20+
for device in devices:
21+
print(device.label, device.controllable_name)
22+
23+
24+
asyncio.run(main())
25+
```
26+
27+
## Read a state value
28+
29+
```python
30+
import asyncio
31+
32+
from pyoverkiz.auth.credentials import UsernamePasswordCredentials
33+
from pyoverkiz.client import OverkizClient
34+
from pyoverkiz.enums import Server
35+
36+
37+
async def main() -> None:
38+
async with OverkizClient(
39+
server=Server.SOMFY_EUROPE,
40+
credentials=UsernamePasswordCredentials("[email protected]", "password"),
41+
) as client:
42+
await client.login()
43+
devices = await client.get_devices()
44+
device = devices[0]
45+
closure_state = next(
46+
(state for state in device.states if state.name == "core:ClosureState"),
47+
None,
48+
)
49+
print(closure_state.value if closure_state else None)
50+
51+
52+
asyncio.run(main())
53+
```
54+
55+
## Send a command
56+
57+
```python
58+
import asyncio
59+
60+
from pyoverkiz.auth.credentials import UsernamePasswordCredentials
61+
from pyoverkiz.client import OverkizClient
62+
from pyoverkiz.enums import OverkizCommand, Server
63+
from pyoverkiz.models import Action, Command
64+
65+
66+
async def main() -> None:
67+
async with OverkizClient(
68+
server=Server.SOMFY_EUROPE,
69+
credentials=UsernamePasswordCredentials("[email protected]", "password"),
70+
) as client:
71+
await client.login()
72+
await client.execute_action_group(
73+
actions=[
74+
Action(
75+
device_url="io://1234-5678-1234/12345678",
76+
commands=[
77+
Command(
78+
name=OverkizCommand.SET_CLOSURE,
79+
parameters=[50],
80+
)
81+
],
82+
)
83+
],
84+
label="Set closure",
85+
)
86+
87+
88+
asyncio.run(main())
89+
```
90+
91+
## Action groups and common patterns
92+
93+
- Use a single action group to batch multiple device commands.
94+
- Parameters vary by device. Many closure-style devices use 0–100.
95+
- Thermostat-style devices commonly accept target temperatures.
96+
97+
```python
98+
import asyncio
99+
100+
from pyoverkiz.auth.credentials import UsernamePasswordCredentials
101+
from pyoverkiz.client import OverkizClient
102+
from pyoverkiz.enums import OverkizCommand, Server
103+
from pyoverkiz.models import Action, Command
104+
105+
106+
async def main() -> None:
107+
async with OverkizClient(
108+
server=Server.SOMFY_EUROPE,
109+
credentials=UsernamePasswordCredentials("[email protected]", "password"),
110+
) as client:
111+
await client.login()
112+
await client.execute_action_group(
113+
actions=[
114+
Action(
115+
device_url="io://1234-5678-1234/12345678",
116+
commands=[
117+
Command(
118+
name=OverkizCommand.SET_TARGET_TEMPERATURE,
119+
parameters=[21.5],
120+
)
121+
],
122+
)
123+
],
124+
label="Set temperature",
125+
)
126+
127+
128+
asyncio.run(main())
129+
```
130+
131+
## Polling vs event-driven
132+
133+
Polling `get_devices()` is simple but can be slower. Event listeners provide faster updates; see the event handling guide for details.

docs/error-handling.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Error handling
2+
3+
## Common exceptions
4+
5+
- `NotAuthenticatedException`
6+
- `TooManyRequestsException`
7+
- `TooManyConcurrentRequestsException`
8+
- `TooManyExecutionsException`
9+
- `MaintenanceException`
10+
- `AccessDeniedToGatewayException`
11+
- `BadCredentialsException`
12+
13+
## Retry and backoff guidance
14+
15+
Use short, jittered delays for transient errors and re-authenticate on auth failures.
16+
17+
```python
18+
import asyncio
19+
20+
from pyoverkiz.auth.credentials import UsernamePasswordCredentials
21+
from pyoverkiz.client import OverkizClient
22+
from pyoverkiz.enums import Server
23+
from pyoverkiz.exceptions import (
24+
NotAuthenticatedException,
25+
TooManyConcurrentRequestsException,
26+
TooManyRequestsException,
27+
)
28+
29+
30+
async def fetch_devices_with_retry() -> None:
31+
async with OverkizClient(
32+
server=Server.SOMFY_EUROPE,
33+
credentials=UsernamePasswordCredentials("[email protected]", "password"),
34+
) as client:
35+
await client.login()
36+
for attempt in range(5):
37+
try:
38+
devices = await client.get_devices()
39+
print(devices)
40+
return
41+
except (TooManyRequestsException, TooManyConcurrentRequestsException):
42+
await asyncio.sleep(0.5 * (attempt + 1))
43+
except NotAuthenticatedException:
44+
await client.login()
45+
46+
47+
asyncio.run(fetch_devices_with_retry())
48+
```
49+
50+
## SSL and local certificates
51+
52+
If you use local gateways with `.local` hostnames, you may need `verify_ssl=False` when a trusted certificate is not available.
53+
54+
## Timeouts
55+
56+
For long-running operations, prefer shorter request timeouts with retries rather than a single long timeout.

0 commit comments

Comments
 (0)