Skip to content

Commit 41c6f07

Browse files
committed
Enhance Protocol handling: add ProtocolType model, update Protocol enum with labels, and implement protocol enum generation script
1 parent f208497 commit 41c6f07

4 files changed

Lines changed: 162 additions & 31 deletions

File tree

pyoverkiz/client.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
Option,
6262
OptionParameter,
6363
Place,
64+
ProtocolType,
6465
ServerConfig,
6566
Setup,
6667
State,
@@ -669,9 +670,17 @@ async def search_reference_devices_model(self, payload: JSON) -> JSON:
669670
return await self.__post("reference/devices/search", payload)
670671

671672
@retry_on_auth_error
672-
async def get_reference_protocol_types(self) -> JSON:
673-
"""Get details about supported protocol types on that server instance."""
674-
return await self.__get("reference/protocolTypes")
673+
async def get_reference_protocol_types(self) -> list[ProtocolType]:
674+
"""Get details about supported protocol types on that server instance.
675+
676+
Returns a list of protocol type definitions, each containing:
677+
- id: Numeric protocol identifier
678+
- prefix: URL prefix used in device addresses
679+
- name: Internal protocol name
680+
- label: Human-readable protocol label
681+
"""
682+
response = await self.__get("reference/protocolTypes")
683+
return [ProtocolType(**protocol) for protocol in response]
675684

676685
@retry_on_auth_error
677686
async def get_reference_timezones(self) -> JSON:

pyoverkiz/enums/protocol.py

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
"""Protocol enums describe device URL schemes used by Overkiz."""
1+
"""Protocol enums describe device URL schemes used by Overkiz.
2+
3+
THIS FILE IS AUTO-GENERATED. DO NOT EDIT MANUALLY.
4+
Run `uv run utils/generate_enums.py` to regenerate.
5+
"""
26

37
from enum import StrEnum, unique
48

@@ -14,33 +18,33 @@ class Protocol(UnknownEnumMixin, StrEnum):
1418

1519
UNKNOWN = "unknown"
1620

17-
AUGUST = "august"
18-
CAMERA = "camera"
19-
ELIOT = "eliot"
20-
ENOCEAN = "enocean"
21+
AUGUST = "august" # 59: August Webservices
22+
CAMERA = "camera" # 13: Generic Camera Control Protocol
23+
ELIOT = "eliot" # 45: Eliot Webservices
24+
ENOCEAN = "enocean" # 7: EnOcean
2125
HLRR_WIFI = "hlrrwifi"
22-
HOMEKIT = "homekit"
23-
HUE = "hue"
24-
INTERNAL = "internal"
25-
IO = "io"
26-
JSW = "jsw"
27-
MODBUS = "modbus"
26+
HOMEKIT = "homekit" # 48: HOMEKIT
27+
HUE = "hue" # 22: Philips HUE - Personal Wireless Lighting
28+
INTERNAL = "internal" # 29: Kizbox Internal Modules
29+
IO = "io" # 1: IO HomeControl©
30+
JSW = "jsw" # 30: JSW Webservices
31+
MODBUS = "modbus" # 20: Modbus
2832
MODBUSLINK = "modbuslink"
29-
MYFOX = "myfox"
30-
NETATMO = "netatmo"
31-
OGCP = "ogcp"
32-
OGP = "ogp"
33-
OPENDOORS = "opendoors"
34-
OVP = "ovp"
35-
PROFALUX_868 = "profalux868"
36-
RAMSES = "ramses"
37-
RTD = "rtd"
38-
RTDS = "rtds"
33+
MYFOX = "myfox" # 25: MyFox Webservices
34+
NETATMO = "netatmo" # 38: Netatmo Webservices
35+
OGCP = "ogcp" # 62: Overkiz Generic Cloud Protocol
36+
OGP = "ogp" # 56: Overkiz Generic Protocol
37+
OPENDOORS = "opendoors" # 35: OpenDoors Webservices
38+
OVP = "ovp" # 14: OVERKIZ Radio Protocol
39+
PROFALUX_868 = "profalux868" # 50: Profalux 868
40+
RAMSES = "ramses" # 6: Ramses II (Honeywell)
41+
RTD = "rtd" # 5: Domis RTD - Actuator
42+
RTDS = "rtds" # 11: Domis RTD - Sensor
3943
RTN = "rtn"
40-
RTS = "rts"
41-
SOMFY_THERMOSTAT = "somfythermostat"
42-
UPNP_CONTROL = "upnpcontrol"
43-
VERISURE = "verisure"
44-
WISER = "wiser"
45-
ZIGBEE = "zigbee"
46-
ZWAVE = "zwave"
44+
RTS = "rts" # 2: Somfy RTS
45+
SOMFY_THERMOSTAT = "somfythermostat" # 39: Somfy Thermostat Webservice
46+
UPNP_CONTROL = "upnpcontrol" # 43: UPnP Control
47+
VERISURE = "verisure" # 23: Verisure Webservices
48+
WISER = "wiser" # 54: Schneider Wiser
49+
ZIGBEE = "zigbee" # 3: Zigbee
50+
ZWAVE = "zwave" # 8: Z-Wave

pyoverkiz/models.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,3 +1030,20 @@ def __init__(
10301030
self.parameters = (
10311031
[OptionParameter(**p) for p in parameters] if parameters else []
10321032
)
1033+
1034+
1035+
@define(init=False, kw_only=True)
1036+
class ProtocolType:
1037+
"""Protocol type definition from the reference API."""
1038+
1039+
id: int
1040+
prefix: str
1041+
name: str
1042+
label: str
1043+
1044+
def __init__(self, id: int, prefix: str, name: str, label: str, **_: Any):
1045+
"""Initialize ProtocolType from API data."""
1046+
self.id = id
1047+
self.prefix = prefix
1048+
self.name = name
1049+
self.label = label

utils/generate_enums.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
"""Generate enum files from the Overkiz API reference data."""
2+
3+
# ruff: noqa: T201
4+
5+
from __future__ import annotations
6+
7+
import asyncio
8+
import os
9+
from pathlib import Path
10+
11+
from pyoverkiz.auth.credentials import UsernamePasswordCredentials
12+
from pyoverkiz.client import OverkizClient
13+
from pyoverkiz.enums import Server
14+
15+
# Hardcoded protocols that may not be available on all servers
16+
# Format: (name, prefix)
17+
ADDITIONAL_PROTOCOLS = [
18+
("HLRR_WIFI", "hlrrwifi"),
19+
("MODBUSLINK", "modbuslink"),
20+
("RTN", "rtn"),
21+
]
22+
23+
24+
async def generate_protocol_enum() -> None:
25+
"""Generate the Protocol enum from the Overkiz API."""
26+
username = os.environ["OVERKIZ_USERNAME"]
27+
password = os.environ["OVERKIZ_PASSWORD"]
28+
29+
async with OverkizClient(
30+
server=Server.SOMFY_EUROPE,
31+
credentials=UsernamePasswordCredentials(username, password),
32+
) as client:
33+
await client.login()
34+
35+
protocol_types = await client.get_reference_protocol_types()
36+
37+
# Build list of protocol entries (name, prefix, id, label)
38+
protocols: list[tuple[str, str, int | None, str | None]] = [
39+
(p.name, p.prefix, p.id, p.label) for p in protocol_types
40+
]
41+
42+
# Add hardcoded protocols that may not be on all servers (avoid duplicates)
43+
fetched_prefixes = {p.prefix for p in protocol_types}
44+
for name, prefix in ADDITIONAL_PROTOCOLS:
45+
if prefix not in fetched_prefixes:
46+
protocols.append((name, prefix, None, None))
47+
48+
# Sort by name for consistent output
49+
protocols.sort(key=lambda p: p[0])
50+
51+
# Generate the enum file content
52+
lines = [
53+
'"""Protocol enums describe device URL schemes used by Overkiz.',
54+
"",
55+
"THIS FILE IS AUTO-GENERATED. DO NOT EDIT MANUALLY.",
56+
"Run `uv run utils/generate_enums.py` to regenerate.",
57+
'"""',
58+
"",
59+
"from enum import StrEnum, unique",
60+
"",
61+
"from pyoverkiz.enums.base import UnknownEnumMixin",
62+
"",
63+
"",
64+
"@unique",
65+
"class Protocol(UnknownEnumMixin, StrEnum):",
66+
' """Protocol used by Overkiz.',
67+
"",
68+
" Values have been retrieved from /reference/protocolTypes",
69+
' """',
70+
"",
71+
' UNKNOWN = "unknown"',
72+
"",
73+
]
74+
75+
# Add each protocol as an enum value with label comment
76+
for name, prefix, protocol_id, label in protocols:
77+
if protocol_id is not None:
78+
lines.append(f' {name} = "{prefix}" # {protocol_id}: {label}')
79+
else:
80+
lines.append(f' {name} = "{prefix}"')
81+
82+
lines.append("") # End with newline
83+
84+
# Write to the protocol.py file
85+
output_path = (
86+
Path(__file__).parent.parent / "pyoverkiz" / "enums" / "protocol.py"
87+
)
88+
output_path.write_text("\n".join(lines))
89+
90+
fetched_count = len(protocol_types)
91+
additional_count = len(
92+
[p for p in ADDITIONAL_PROTOCOLS if p[1] not in fetched_prefixes]
93+
)
94+
95+
print(f"✓ Generated {output_path}")
96+
print(f"✓ Added {fetched_count} protocols from API")
97+
print(f"✓ Added {additional_count} additional hardcoded protocols")
98+
print(f"✓ Total: {len(protocols)} protocols")
99+
100+
101+
asyncio.run(generate_protocol_enum())

0 commit comments

Comments
 (0)