conson-xp 1.18.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- conson_xp-1.18.0.dist-info/METADATA +412 -0
- conson_xp-1.18.0.dist-info/RECORD +176 -0
- conson_xp-1.18.0.dist-info/WHEEL +4 -0
- conson_xp-1.18.0.dist-info/entry_points.txt +5 -0
- conson_xp-1.18.0.dist-info/licenses/LICENSE +29 -0
- xp/__init__.py +9 -0
- xp/cli/__init__.py +5 -0
- xp/cli/__main__.py +6 -0
- xp/cli/commands/__init__.py +153 -0
- xp/cli/commands/conbus/__init__.py +25 -0
- xp/cli/commands/conbus/conbus.py +128 -0
- xp/cli/commands/conbus/conbus_actiontable_commands.py +233 -0
- xp/cli/commands/conbus/conbus_autoreport_commands.py +108 -0
- xp/cli/commands/conbus/conbus_blink_commands.py +163 -0
- xp/cli/commands/conbus/conbus_config_commands.py +29 -0
- xp/cli/commands/conbus/conbus_custom_commands.py +57 -0
- xp/cli/commands/conbus/conbus_datapoint_commands.py +113 -0
- xp/cli/commands/conbus/conbus_discover_commands.py +61 -0
- xp/cli/commands/conbus/conbus_event_commands.py +81 -0
- xp/cli/commands/conbus/conbus_lightlevel_commands.py +207 -0
- xp/cli/commands/conbus/conbus_linknumber_commands.py +102 -0
- xp/cli/commands/conbus/conbus_modulenumber_commands.py +104 -0
- xp/cli/commands/conbus/conbus_msactiontable_commands.py +94 -0
- xp/cli/commands/conbus/conbus_output_commands.py +163 -0
- xp/cli/commands/conbus/conbus_raw_commands.py +62 -0
- xp/cli/commands/conbus/conbus_receive_commands.py +59 -0
- xp/cli/commands/conbus/conbus_scan_commands.py +58 -0
- xp/cli/commands/file_commands.py +186 -0
- xp/cli/commands/homekit/__init__.py +3 -0
- xp/cli/commands/homekit/homekit.py +118 -0
- xp/cli/commands/homekit/homekit_start_commands.py +43 -0
- xp/cli/commands/module_commands.py +187 -0
- xp/cli/commands/reverse_proxy_commands.py +178 -0
- xp/cli/commands/server/__init__.py +3 -0
- xp/cli/commands/server/server_commands.py +135 -0
- xp/cli/commands/telegram/__init__.py +5 -0
- xp/cli/commands/telegram/telegram.py +41 -0
- xp/cli/commands/telegram/telegram_blink_commands.py +79 -0
- xp/cli/commands/telegram/telegram_checksum_commands.py +112 -0
- xp/cli/commands/telegram/telegram_discover_commands.py +41 -0
- xp/cli/commands/telegram/telegram_linknumber_commands.py +86 -0
- xp/cli/commands/telegram/telegram_parse_commands.py +75 -0
- xp/cli/commands/telegram/telegram_version_commands.py +52 -0
- xp/cli/main.py +87 -0
- xp/cli/utils/__init__.py +1 -0
- xp/cli/utils/click_tree.py +57 -0
- xp/cli/utils/datapoint_type_choice.py +57 -0
- xp/cli/utils/decorators.py +351 -0
- xp/cli/utils/error_handlers.py +201 -0
- xp/cli/utils/formatters.py +312 -0
- xp/cli/utils/module_type_choice.py +56 -0
- xp/cli/utils/serial_number_type.py +52 -0
- xp/cli/utils/system_function_choice.py +57 -0
- xp/cli/utils/xp_module_type.py +53 -0
- xp/connection/__init__.py +13 -0
- xp/connection/exceptions.py +22 -0
- xp/models/__init__.py +36 -0
- xp/models/actiontable/__init__.py +1 -0
- xp/models/actiontable/actiontable.py +43 -0
- xp/models/actiontable/msactiontable_xp20.py +53 -0
- xp/models/actiontable/msactiontable_xp24.py +58 -0
- xp/models/actiontable/msactiontable_xp33.py +65 -0
- xp/models/conbus/__init__.py +1 -0
- xp/models/conbus/conbus.py +87 -0
- xp/models/conbus/conbus_autoreport.py +67 -0
- xp/models/conbus/conbus_blink.py +80 -0
- xp/models/conbus/conbus_client_config.py +55 -0
- xp/models/conbus/conbus_connection_status.py +40 -0
- xp/models/conbus/conbus_custom.py +58 -0
- xp/models/conbus/conbus_datapoint.py +89 -0
- xp/models/conbus/conbus_discover.py +64 -0
- xp/models/conbus/conbus_event_raw.py +47 -0
- xp/models/conbus/conbus_lightlevel.py +52 -0
- xp/models/conbus/conbus_linknumber.py +54 -0
- xp/models/conbus/conbus_output.py +57 -0
- xp/models/conbus/conbus_raw.py +45 -0
- xp/models/conbus/conbus_receive.py +42 -0
- xp/models/conbus/conbus_writeconfig.py +60 -0
- xp/models/homekit/__init__.py +1 -0
- xp/models/homekit/homekit_accessory.py +35 -0
- xp/models/homekit/homekit_config.py +106 -0
- xp/models/homekit/homekit_conson_config.py +86 -0
- xp/models/log_entry.py +130 -0
- xp/models/protocol/__init__.py +1 -0
- xp/models/protocol/conbus_protocol.py +312 -0
- xp/models/response.py +42 -0
- xp/models/telegram/__init__.py +1 -0
- xp/models/telegram/action_type.py +31 -0
- xp/models/telegram/datapoint_type.py +82 -0
- xp/models/telegram/event_telegram.py +140 -0
- xp/models/telegram/event_type.py +15 -0
- xp/models/telegram/input_action_type.py +69 -0
- xp/models/telegram/input_type.py +17 -0
- xp/models/telegram/module_type.py +188 -0
- xp/models/telegram/module_type_code.py +205 -0
- xp/models/telegram/output_telegram.py +103 -0
- xp/models/telegram/reply_telegram.py +297 -0
- xp/models/telegram/system_function.py +116 -0
- xp/models/telegram/system_telegram.py +94 -0
- xp/models/telegram/telegram.py +28 -0
- xp/models/telegram/telegram_type.py +19 -0
- xp/models/telegram/timeparam_type.py +51 -0
- xp/models/write_config_type.py +33 -0
- xp/services/__init__.py +26 -0
- xp/services/actiontable/__init__.py +1 -0
- xp/services/actiontable/actiontable_serializer.py +273 -0
- xp/services/actiontable/msactiontable_serializer.py +7 -0
- xp/services/actiontable/msactiontable_xp20_serializer.py +169 -0
- xp/services/actiontable/msactiontable_xp24_serializer.py +120 -0
- xp/services/actiontable/msactiontable_xp33_serializer.py +239 -0
- xp/services/conbus/__init__.py +1 -0
- xp/services/conbus/actiontable/__init__.py +1 -0
- xp/services/conbus/actiontable/actiontable_download_service.py +158 -0
- xp/services/conbus/actiontable/actiontable_list_service.py +91 -0
- xp/services/conbus/actiontable/actiontable_show_service.py +89 -0
- xp/services/conbus/actiontable/actiontable_upload_service.py +211 -0
- xp/services/conbus/actiontable/msactiontable_service.py +232 -0
- xp/services/conbus/conbus_blink_all_service.py +181 -0
- xp/services/conbus/conbus_blink_service.py +158 -0
- xp/services/conbus/conbus_custom_service.py +156 -0
- xp/services/conbus/conbus_datapoint_queryall_service.py +182 -0
- xp/services/conbus/conbus_datapoint_service.py +170 -0
- xp/services/conbus/conbus_discover_service.py +312 -0
- xp/services/conbus/conbus_event_raw_service.py +181 -0
- xp/services/conbus/conbus_output_service.py +194 -0
- xp/services/conbus/conbus_raw_service.py +122 -0
- xp/services/conbus/conbus_receive_service.py +115 -0
- xp/services/conbus/conbus_scan_service.py +150 -0
- xp/services/conbus/write_config_service.py +194 -0
- xp/services/homekit/__init__.py +1 -0
- xp/services/homekit/homekit_cache_service.py +307 -0
- xp/services/homekit/homekit_conbus_service.py +93 -0
- xp/services/homekit/homekit_config_validator.py +310 -0
- xp/services/homekit/homekit_conson_validator.py +121 -0
- xp/services/homekit/homekit_dimminglight.py +182 -0
- xp/services/homekit/homekit_dimminglight_service.py +148 -0
- xp/services/homekit/homekit_hap_service.py +342 -0
- xp/services/homekit/homekit_lightbulb.py +120 -0
- xp/services/homekit/homekit_lightbulb_service.py +86 -0
- xp/services/homekit/homekit_module_service.py +56 -0
- xp/services/homekit/homekit_outlet.py +168 -0
- xp/services/homekit/homekit_outlet_service.py +121 -0
- xp/services/homekit/homekit_service.py +359 -0
- xp/services/log_file_service.py +309 -0
- xp/services/module_type_service.py +257 -0
- xp/services/protocol/__init__.py +21 -0
- xp/services/protocol/conbus_event_protocol.py +360 -0
- xp/services/protocol/conbus_protocol.py +318 -0
- xp/services/protocol/protocol_factory.py +78 -0
- xp/services/protocol/telegram_protocol.py +264 -0
- xp/services/reverse_proxy_service.py +435 -0
- xp/services/server/__init__.py +1 -0
- xp/services/server/base_server_service.py +366 -0
- xp/services/server/cp20_server_service.py +65 -0
- xp/services/server/device_service_factory.py +94 -0
- xp/services/server/server_service.py +428 -0
- xp/services/server/xp130_server_service.py +67 -0
- xp/services/server/xp20_server_service.py +92 -0
- xp/services/server/xp230_server_service.py +58 -0
- xp/services/server/xp24_server_service.py +245 -0
- xp/services/server/xp33_server_service.py +535 -0
- xp/services/telegram/__init__.py +1 -0
- xp/services/telegram/telegram_blink_service.py +138 -0
- xp/services/telegram/telegram_checksum_service.py +149 -0
- xp/services/telegram/telegram_datapoint_service.py +82 -0
- xp/services/telegram/telegram_discover_service.py +277 -0
- xp/services/telegram/telegram_link_number_service.py +216 -0
- xp/services/telegram/telegram_output_service.py +322 -0
- xp/services/telegram/telegram_service.py +380 -0
- xp/services/telegram/telegram_version_service.py +288 -0
- xp/utils/__init__.py +12 -0
- xp/utils/checksum.py +61 -0
- xp/utils/dependencies.py +531 -0
- xp/utils/event_helper.py +31 -0
- xp/utils/serialization.py +205 -0
- xp/utils/time_utils.py +134 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""Event telegram model for console bus communication."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
from xp.models.telegram.event_type import EventType
|
|
8
|
+
from xp.models.telegram.input_type import InputType
|
|
9
|
+
from xp.models.telegram.module_type import ModuleType
|
|
10
|
+
from xp.models.telegram.telegram import Telegram
|
|
11
|
+
from xp.models.telegram.telegram_type import TelegramType
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class EventTelegram(Telegram):
|
|
16
|
+
r"""Represent a parsed event telegram from the console bus.
|
|
17
|
+
|
|
18
|
+
Format: <[EO]{module_type}L{link_number}I{input_number}{event_type}{checksum}>
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
<E14L00I02MAK>
|
|
22
|
+
|
|
23
|
+
Attributes:
|
|
24
|
+
event_telegram_type: Event telegram type (E or O).
|
|
25
|
+
module_type: Module type code.
|
|
26
|
+
link_number: Link number.
|
|
27
|
+
input_number: Input number.
|
|
28
|
+
event_type: Type of event (press or release).
|
|
29
|
+
module_info: Module type information if found.
|
|
30
|
+
input_type: Input type based on input number.
|
|
31
|
+
is_button_press: True if this is a button press event.
|
|
32
|
+
is_button_release: True if this is a button release event.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
event_telegram_type: str = "E" # E or O
|
|
36
|
+
module_type: int = 0
|
|
37
|
+
link_number: int = 0
|
|
38
|
+
input_number: int = 0
|
|
39
|
+
event_type: Optional[EventType] = None
|
|
40
|
+
|
|
41
|
+
def __post_init__(self) -> None:
|
|
42
|
+
"""Initialize timestamp and telegram type."""
|
|
43
|
+
if self.timestamp is None:
|
|
44
|
+
self.timestamp = datetime.now()
|
|
45
|
+
self.telegram_type = TelegramType.EVENT
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def module_info(self) -> Optional[ModuleType]:
|
|
49
|
+
"""Get module type information for this telegram.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
ModuleType instance if found, None otherwise.
|
|
53
|
+
"""
|
|
54
|
+
return ModuleType.from_code(self.module_type)
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def input_type(self) -> InputType:
|
|
58
|
+
"""Determines the input type based on input number.
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
InputType enum value.
|
|
62
|
+
"""
|
|
63
|
+
if 0 <= self.input_number <= 9:
|
|
64
|
+
return InputType.PUSH_BUTTON
|
|
65
|
+
elif 10 <= self.input_number <= 89:
|
|
66
|
+
return InputType.IR_REMOTE
|
|
67
|
+
elif self.input_number == 90:
|
|
68
|
+
return InputType.PROXIMITY_SENSOR
|
|
69
|
+
else:
|
|
70
|
+
raise ValueError(f"Invalid input number: {self.input_number}")
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def is_button_press(self) -> bool:
|
|
74
|
+
"""True if this is a button press event.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
True if event is a button press, False otherwise.
|
|
78
|
+
"""
|
|
79
|
+
return self.event_type == EventType.BUTTON_PRESS
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def is_button_release(self) -> bool:
|
|
83
|
+
"""True if this is a button release event.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
True if event is a button release, False otherwise.
|
|
87
|
+
"""
|
|
88
|
+
return self.event_type == EventType.BUTTON_RELEASE
|
|
89
|
+
|
|
90
|
+
def to_dict(self) -> dict[str, Any]:
|
|
91
|
+
"""Convert to dictionary for JSON serialization.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Dictionary representation of the event telegram.
|
|
95
|
+
"""
|
|
96
|
+
result: dict[str, Any] = {
|
|
97
|
+
"module_type": self.module_type,
|
|
98
|
+
"link_number": self.link_number,
|
|
99
|
+
"output_number": self.input_number,
|
|
100
|
+
"event_type": self.event_type.value if self.event_type else None,
|
|
101
|
+
"event_type_name": (
|
|
102
|
+
"button_press" if self.is_button_press else "button_release"
|
|
103
|
+
),
|
|
104
|
+
"input_type": self.input_type.value,
|
|
105
|
+
"checksum": self.checksum,
|
|
106
|
+
"checksum_validated": self.checksum_validated,
|
|
107
|
+
"raw_telegram": self.raw_telegram,
|
|
108
|
+
"timestamp": self.timestamp.isoformat() if self.timestamp else None,
|
|
109
|
+
"telegram_type": self.telegram_type.value,
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Add module information if available
|
|
113
|
+
if self.module_info:
|
|
114
|
+
result["module_info"] = {
|
|
115
|
+
"name": self.module_info.name,
|
|
116
|
+
"description": self.module_info.description,
|
|
117
|
+
"category": self.module_info.category,
|
|
118
|
+
}
|
|
119
|
+
else:
|
|
120
|
+
result["module_info"] = None
|
|
121
|
+
|
|
122
|
+
return result
|
|
123
|
+
|
|
124
|
+
def __str__(self) -> str:
|
|
125
|
+
"""Human-readable string representation.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Formatted string representation.
|
|
129
|
+
"""
|
|
130
|
+
event_desc = "pressed" if self.is_button_press else "released"
|
|
131
|
+
|
|
132
|
+
# Include module name if available
|
|
133
|
+
module_desc = f"Module {self.module_type}"
|
|
134
|
+
if self.module_info:
|
|
135
|
+
module_desc = f"{self.module_info.name} (Type {self.module_type})"
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
f"{module_desc} Link {self.link_number:02d} "
|
|
139
|
+
f"Input {self.input_number:02d} ({self.input_type.value}) {event_desc}"
|
|
140
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Event type enumeration for telegram events."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class EventType(Enum):
|
|
7
|
+
"""Event types for telegraph events.
|
|
8
|
+
|
|
9
|
+
Attributes:
|
|
10
|
+
BUTTON_PRESS: Button make (press) event.
|
|
11
|
+
BUTTON_RELEASE: Button break (release) event.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
BUTTON_PRESS = "M" # Make
|
|
15
|
+
BUTTON_RELEASE = "B" # Break
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Input action types for XP24 module based on Feature-Action-Table.md."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class InputActionType(Enum):
|
|
7
|
+
"""Input action types for XP24 module (based on Feature-Action-Table.md).
|
|
8
|
+
|
|
9
|
+
Attributes:
|
|
10
|
+
VOID: No action.
|
|
11
|
+
ON: Turn on action.
|
|
12
|
+
OFF: Turn off action.
|
|
13
|
+
TOGGLE: Toggle action.
|
|
14
|
+
BLOCK: Block action.
|
|
15
|
+
AUXRELAY: Auxiliary relay action.
|
|
16
|
+
MUTUALEX: Mutual exclusion action.
|
|
17
|
+
LEVELUP: Level up action.
|
|
18
|
+
LEVELDOWN: Level down action.
|
|
19
|
+
LEVELINC: Level increment action.
|
|
20
|
+
LEVELDEC: Level decrement action.
|
|
21
|
+
LEVELSET: Level set action.
|
|
22
|
+
FADETIME: Fade time action.
|
|
23
|
+
SCENESET: Scene set action.
|
|
24
|
+
SCENENEXT: Scene next action.
|
|
25
|
+
SCENEPREV: Scene previous action.
|
|
26
|
+
CTRLMETHOD: Control method action.
|
|
27
|
+
RETURNDATA: Return data action.
|
|
28
|
+
DELAYEDON: Delayed on action.
|
|
29
|
+
EVENTTIMER1: Event timer 1 action.
|
|
30
|
+
EVENTTIMER2: Event timer 2 action.
|
|
31
|
+
EVENTTIMER3: Event timer 3 action.
|
|
32
|
+
EVENTTIMER4: Event timer 4 action.
|
|
33
|
+
STEPCTRL: Step control action.
|
|
34
|
+
STEPCTRLUP: Step control up action.
|
|
35
|
+
STEPCTRLDOWN: Step control down action.
|
|
36
|
+
LEVELSETINTERN: Level set internal action.
|
|
37
|
+
FADE: Fade action.
|
|
38
|
+
LEARN: Learn action.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
VOID = 0
|
|
42
|
+
ON = 1
|
|
43
|
+
OFF = 2
|
|
44
|
+
TOGGLE = 3
|
|
45
|
+
BLOCK = 4
|
|
46
|
+
AUXRELAY = 5
|
|
47
|
+
MUTUALEX = 6
|
|
48
|
+
LEVELUP = 7
|
|
49
|
+
LEVELDOWN = 8
|
|
50
|
+
LEVELINC = 9
|
|
51
|
+
LEVELDEC = 10
|
|
52
|
+
LEVELSET = 11
|
|
53
|
+
FADETIME = 12
|
|
54
|
+
SCENESET = 13
|
|
55
|
+
SCENENEXT = 14
|
|
56
|
+
SCENEPREV = 15
|
|
57
|
+
CTRLMETHOD = 16
|
|
58
|
+
RETURNDATA = 17
|
|
59
|
+
DELAYEDON = 18
|
|
60
|
+
EVENTTIMER1 = 19
|
|
61
|
+
EVENTTIMER2 = 20
|
|
62
|
+
EVENTTIMER3 = 21
|
|
63
|
+
EVENTTIMER4 = 22
|
|
64
|
+
STEPCTRL = 23
|
|
65
|
+
STEPCTRLUP = 24
|
|
66
|
+
STEPCTRLDOWN = 25
|
|
67
|
+
LEVELSETINTERN = 29
|
|
68
|
+
FADE = 30
|
|
69
|
+
LEARN = 31
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Input type enumeration based on input number ranges."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class InputType(Enum):
|
|
7
|
+
"""Input types based on input number ranges.
|
|
8
|
+
|
|
9
|
+
Attributes:
|
|
10
|
+
PUSH_BUTTON: Push button input (range 00-09).
|
|
11
|
+
IR_REMOTE: IR remote input (range 10-89).
|
|
12
|
+
PROXIMITY_SENSOR: Proximity sensor input (input 90).
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
PUSH_BUTTON = "push_button" # Input 00-09
|
|
16
|
+
IR_REMOTE = "ir_remote" # Input 10-89
|
|
17
|
+
PROXIMITY_SENSOR = "proximity_sensor" # Input 90
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"""Module type models for the XP system."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Dict, List, Optional
|
|
5
|
+
|
|
6
|
+
from xp.models.telegram.module_type_code import MODULE_TYPE_REGISTRY
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class ModuleType:
|
|
11
|
+
"""Represents a module type in the XP system.
|
|
12
|
+
|
|
13
|
+
Contains the module code, name, and description.
|
|
14
|
+
|
|
15
|
+
Attributes:
|
|
16
|
+
code: Numeric module type code.
|
|
17
|
+
name: Module name.
|
|
18
|
+
description: Module description.
|
|
19
|
+
module_category: Module category.
|
|
20
|
+
is_reserved: True if module type is reserved.
|
|
21
|
+
is_push_button_panel: True if module is a push button panel.
|
|
22
|
+
is_ir_capable: True if module has IR capabilities.
|
|
23
|
+
category: Module category based on its type.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
code: int
|
|
27
|
+
name: str
|
|
28
|
+
description: str
|
|
29
|
+
module_category: str = ""
|
|
30
|
+
|
|
31
|
+
@classmethod
|
|
32
|
+
def from_code(cls, code: int) -> Optional["ModuleType"]:
|
|
33
|
+
"""Create ModuleType from a numeric code.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
code: The numeric module type code.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
ModuleType instance or None if code is invalid.
|
|
40
|
+
"""
|
|
41
|
+
module_info = MODULE_TYPE_REGISTRY.get(code)
|
|
42
|
+
if module_info:
|
|
43
|
+
return cls(code=code, **module_info)
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def from_name(cls, name: str) -> Optional["ModuleType"]:
|
|
48
|
+
"""Create ModuleType from a module name.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
name: The module name (case-insensitive).
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
ModuleType instance or None if name is invalid.
|
|
55
|
+
"""
|
|
56
|
+
name_upper = name.upper()
|
|
57
|
+
for code, info in MODULE_TYPE_REGISTRY.items():
|
|
58
|
+
if info["name"].upper() == name_upper:
|
|
59
|
+
return cls(code=code, **info)
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def is_reserved(self) -> bool:
|
|
64
|
+
"""Check if this module type is reserved.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
True if module type is reserved, False otherwise.
|
|
68
|
+
"""
|
|
69
|
+
return self.name in ("XP26X1", "XP26X2")
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def is_push_button_panel(self) -> bool:
|
|
73
|
+
"""Check if this module type is a push button panel.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
True if module is a push button panel, False otherwise.
|
|
77
|
+
"""
|
|
78
|
+
return self.name in (
|
|
79
|
+
"XP2606",
|
|
80
|
+
"XP2606A",
|
|
81
|
+
"XP2606B",
|
|
82
|
+
"XP2506",
|
|
83
|
+
"XP2506A",
|
|
84
|
+
"XP2506B",
|
|
85
|
+
"XPX1_8",
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def is_ir_capable(self) -> bool:
|
|
90
|
+
"""Check if this module type has IR capabilities.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
True if module has IR capabilities, False otherwise.
|
|
94
|
+
"""
|
|
95
|
+
return any(ir_type in self.name for ir_type in ("38kHz", "B&O")) or any(
|
|
96
|
+
ir_code in self.name
|
|
97
|
+
for ir_code in (
|
|
98
|
+
"CP70A",
|
|
99
|
+
"CP70B",
|
|
100
|
+
"XP2606A",
|
|
101
|
+
"XP2606B",
|
|
102
|
+
"XP2506A",
|
|
103
|
+
"XP2506B",
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def category(self) -> str:
|
|
109
|
+
"""Get the module category based on its type.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Module category string.
|
|
113
|
+
"""
|
|
114
|
+
if self.code <= 1:
|
|
115
|
+
return "System"
|
|
116
|
+
elif 2 <= self.code <= 6:
|
|
117
|
+
return "CP Link Modules"
|
|
118
|
+
elif 7 <= self.code <= 13:
|
|
119
|
+
return "XP Control Modules"
|
|
120
|
+
elif 14 <= self.code <= 24:
|
|
121
|
+
return "Interface Panels"
|
|
122
|
+
return "Unknown"
|
|
123
|
+
|
|
124
|
+
def to_dict(self) -> Dict:
|
|
125
|
+
"""Convert to dictionary for JSON serialization.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Dictionary representation of the module type.
|
|
129
|
+
"""
|
|
130
|
+
return {
|
|
131
|
+
"code": self.code,
|
|
132
|
+
"name": self.name,
|
|
133
|
+
"description": self.description,
|
|
134
|
+
"category": self.category,
|
|
135
|
+
"is_reserved": self.is_reserved,
|
|
136
|
+
"is_push_button_panel": self.is_push_button_panel,
|
|
137
|
+
"is_ir_capable": self.is_ir_capable,
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
def __str__(self) -> str:
|
|
141
|
+
"""Return human-readable string representation.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Formatted string representation.
|
|
145
|
+
"""
|
|
146
|
+
return f"{self.name} (Code {self.code}): {self.description}"
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def get_all_module_types() -> List[ModuleType]:
|
|
150
|
+
"""Get all available module types.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
List of all ModuleType instances.
|
|
154
|
+
"""
|
|
155
|
+
return [
|
|
156
|
+
module_type
|
|
157
|
+
for module_type in [
|
|
158
|
+
ModuleType.from_code(code) for code in sorted(MODULE_TYPE_REGISTRY.keys())
|
|
159
|
+
]
|
|
160
|
+
if module_type is not None
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def get_module_types_by_category() -> Dict[str, List[ModuleType]]:
|
|
165
|
+
"""Get module types grouped by category.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
Dictionary mapping category names to lists of ModuleType instances.
|
|
169
|
+
"""
|
|
170
|
+
categories: Dict[str, List[ModuleType]] = {}
|
|
171
|
+
for module_type in get_all_module_types():
|
|
172
|
+
category = module_type.category
|
|
173
|
+
if category not in categories:
|
|
174
|
+
categories[category] = []
|
|
175
|
+
categories[category].append(module_type)
|
|
176
|
+
return categories
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def is_valid_module_code(code: int) -> bool:
|
|
180
|
+
"""Check if a module code is valid.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
code: Module code to validate.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
True if code is valid, False otherwise.
|
|
187
|
+
"""
|
|
188
|
+
return code in MODULE_TYPE_REGISTRY
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""Module type code enumeration for XP system modules."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Dict
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ModuleTypeCode(Enum):
|
|
8
|
+
"""Enum representing all XP system module type codes.
|
|
9
|
+
|
|
10
|
+
Attributes:
|
|
11
|
+
NOMOD: No module (code 0).
|
|
12
|
+
ALLMOD: Matches every module type (code 1).
|
|
13
|
+
CP20: CP switch link module (code 2).
|
|
14
|
+
CP70A: CP 38kHz IR link module (code 3).
|
|
15
|
+
CP70B: CP B&O IR link module (code 4).
|
|
16
|
+
CP70C: CP UHF link module (code 5).
|
|
17
|
+
CP70D: CP timer link module (code 6).
|
|
18
|
+
XP24: XP relay module (code 7).
|
|
19
|
+
XP31UNI: XP universal load light dimmer (code 8).
|
|
20
|
+
XP31BCU: XP ballast controller 0-10V (code 9).
|
|
21
|
+
XP31DD: XP ballast controller DSI/DALI (code 10).
|
|
22
|
+
XP33: XP 3-channel light dimmer (code 11).
|
|
23
|
+
CP485: CP RS485 interface module (code 12).
|
|
24
|
+
XP130: Ethernet/TCP/IP interface module (code 13).
|
|
25
|
+
XP2606: 5-way push button panel with sesam (code 14).
|
|
26
|
+
XP2606A: 5-way push button with IR receiver (code 15).
|
|
27
|
+
XP2606B: 5-way push button with B&O IR (code 16).
|
|
28
|
+
XP26X1: Reserved (code 17).
|
|
29
|
+
XP26X2: Reserved (code 18).
|
|
30
|
+
XP2506: 5-way push button panel with sesam Conson design (code 19).
|
|
31
|
+
XP2506A: 5-way push button panel with sesam and 38kHz IR Conson design (code 20).
|
|
32
|
+
XP2506B: 5-way push button panel with sesam and B&O IR Conson design (code 21).
|
|
33
|
+
XPX1_8: 8-way push button panel interface (code 22).
|
|
34
|
+
XP134: Junctionbox interlink (code 23).
|
|
35
|
+
XP24P: XP24P module (code 24).
|
|
36
|
+
XP28A: XP28A module (code 25).
|
|
37
|
+
XP28B: XP28B module (code 26).
|
|
38
|
+
CONTOOL: CONTOOL module (code 27).
|
|
39
|
+
XP28: XP28 module (code 28).
|
|
40
|
+
XP31LR: XP 1-channel lightdimmer (code 29).
|
|
41
|
+
XP33LR: XP 33 3-channel lightdimmer (code 30).
|
|
42
|
+
XP31CR: XP 31 1-channel dimmer (code 31).
|
|
43
|
+
XP31BC: XP 31 1-channel dimmer (code 32).
|
|
44
|
+
XP20: XP switch link module (code 33).
|
|
45
|
+
XP230: Ethernet/TCPIP interface module (code 34).
|
|
46
|
+
XP33LED: XP 3-channel LED dimmer (code 35).
|
|
47
|
+
XP31LED: XP 1-channel LED dimmer (code 36).
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
NOMOD = 0 # No module
|
|
51
|
+
ALLMOD = 1 # Code matching every moduletype
|
|
52
|
+
CP20 = 2 # CP switch link module
|
|
53
|
+
CP70A = 3 # CP 38kHz IR link module
|
|
54
|
+
CP70B = 4 # CP B&O IR link module
|
|
55
|
+
CP70C = 5 # CP UHF link module
|
|
56
|
+
CP70D = 6 # CP timer link module
|
|
57
|
+
XP24 = 7 # XP relay module
|
|
58
|
+
XP31UNI = 8 # XP universal load light dimmer
|
|
59
|
+
XP31BCU = 9 # XP ballast controller, 0-10VActions
|
|
60
|
+
XP31DD = 10 # XP ballast controller DSI/DALI
|
|
61
|
+
XP33 = 11 # XP 33 3 channel lightdimmer
|
|
62
|
+
CP485 = 12 # CP RS485 interface module
|
|
63
|
+
XP130 = 13 # Ethernet/TCPIP interface module
|
|
64
|
+
XP2606 = 14 # 5 way push button panel with sesam, L-Team design
|
|
65
|
+
XP2606A = 15 # 5 way push button panel with sesam,
|
|
66
|
+
# L-Team design and 38kHz IR receiver
|
|
67
|
+
XP2606B = 16 # 5 way push button panel with sesam,
|
|
68
|
+
# L-Team design and B&O IR receiver
|
|
69
|
+
XP26X1 = 17 # Reserved
|
|
70
|
+
XP26X2 = 18 # Reserved
|
|
71
|
+
XP2506 = 19 # 5 way push button panel with sesam, Conson design
|
|
72
|
+
XP2506A = 20 # 5 way push button panel with sesam and 38kHz IR, Conson design
|
|
73
|
+
XP2506B = 21 # 5 way push button panel with sesam and B&O IR, Conson design
|
|
74
|
+
XPX1_8 = 22 # 8 way push button panel interface
|
|
75
|
+
XP134 = 23 # Junctionbox interlink
|
|
76
|
+
XP24P = 24 # XP24P module
|
|
77
|
+
XP28A = 25 #
|
|
78
|
+
XP28B = 26 #
|
|
79
|
+
CONTOOL = 27 #
|
|
80
|
+
XP28 = 28 #
|
|
81
|
+
XP31LR = 29 # XP 1 channel lightdimmer
|
|
82
|
+
XP33LR = 30 # XP 33 3 channel lightdimmer
|
|
83
|
+
XP31CR = 31 # XP 31 1 channel dimmer
|
|
84
|
+
XP31BC = 32 # XP 31 1 channel dimmer
|
|
85
|
+
XP20 = 33 # XP switch link module
|
|
86
|
+
XP230 = 34 # Ethernet/TCPIP interface module
|
|
87
|
+
XP33LED = 35 # XP 3 channel LED dimmer
|
|
88
|
+
XP31LED = 36 # XP 1 channel LED dimmer
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# Registry mapping module codes to their information
|
|
92
|
+
MODULE_TYPE_REGISTRY: Dict[int, Dict[str, str]] = {
|
|
93
|
+
ModuleTypeCode.NOMOD.value: {"name": "NOMOD", "description": "No module"},
|
|
94
|
+
ModuleTypeCode.ALLMOD.value: {
|
|
95
|
+
"name": "ALLMOD",
|
|
96
|
+
"description": "Code matching every moduletype",
|
|
97
|
+
},
|
|
98
|
+
ModuleTypeCode.CP20.value: {"name": "CP20", "description": "CP switch link module"},
|
|
99
|
+
ModuleTypeCode.CP70A.value: {
|
|
100
|
+
"name": "CP70A",
|
|
101
|
+
"description": "CP 38kHz IR link module",
|
|
102
|
+
},
|
|
103
|
+
ModuleTypeCode.CP70B.value: {
|
|
104
|
+
"name": "CP70B",
|
|
105
|
+
"description": "CP B&O IR link module",
|
|
106
|
+
},
|
|
107
|
+
ModuleTypeCode.CP70C.value: {"name": "CP70C", "description": "CP UHF link module"},
|
|
108
|
+
ModuleTypeCode.CP70D.value: {
|
|
109
|
+
"name": "CP70D",
|
|
110
|
+
"description": "CP timer link module",
|
|
111
|
+
},
|
|
112
|
+
ModuleTypeCode.XP24.value: {"name": "XP24", "description": "XP relay module"},
|
|
113
|
+
ModuleTypeCode.XP31UNI.value: {
|
|
114
|
+
"name": "XP31UNI",
|
|
115
|
+
"description": "XP universal load light dimmer",
|
|
116
|
+
},
|
|
117
|
+
ModuleTypeCode.XP31BCU.value: {
|
|
118
|
+
"name": "XP31BC",
|
|
119
|
+
"description": "XP ballast controller, 0-10VActions",
|
|
120
|
+
},
|
|
121
|
+
ModuleTypeCode.XP31DD.value: {
|
|
122
|
+
"name": "XP31DD",
|
|
123
|
+
"description": "XP ballast controller DSI/DALI",
|
|
124
|
+
},
|
|
125
|
+
ModuleTypeCode.XP33.value: {
|
|
126
|
+
"name": "XP33",
|
|
127
|
+
"description": "XP 33 3 channel lightdimmer",
|
|
128
|
+
},
|
|
129
|
+
ModuleTypeCode.CP485.value: {
|
|
130
|
+
"name": "CP485",
|
|
131
|
+
"description": "CP RS485 interface module",
|
|
132
|
+
},
|
|
133
|
+
ModuleTypeCode.XP130.value: {
|
|
134
|
+
"name": "XP130",
|
|
135
|
+
"description": "Ethernet/TCPIP interface module",
|
|
136
|
+
},
|
|
137
|
+
ModuleTypeCode.XP2606.value: {
|
|
138
|
+
"name": "XP2606",
|
|
139
|
+
"description": "5 way push button panel with sesam, L-Team design",
|
|
140
|
+
},
|
|
141
|
+
ModuleTypeCode.XP2606A.value: {
|
|
142
|
+
"name": "XP2606A",
|
|
143
|
+
"description": "5 way push button panel with sesam, L-Team design and 38kHz IR receiver",
|
|
144
|
+
},
|
|
145
|
+
ModuleTypeCode.XP2606B.value: {
|
|
146
|
+
"name": "XP2606B",
|
|
147
|
+
"description": "5 way push button panel with sesam, L-Team design and B&O IR receiver",
|
|
148
|
+
},
|
|
149
|
+
ModuleTypeCode.XP26X1.value: {"name": "XP26X1", "description": "Reserved"},
|
|
150
|
+
ModuleTypeCode.XP26X2.value: {"name": "XP26X2", "description": "Reserved"},
|
|
151
|
+
ModuleTypeCode.XP2506.value: {
|
|
152
|
+
"name": "XP2506",
|
|
153
|
+
"description": "5 way push button panel with sesam, Conson design",
|
|
154
|
+
},
|
|
155
|
+
ModuleTypeCode.XP2506A.value: {
|
|
156
|
+
"name": "XP2506A",
|
|
157
|
+
"description": "5 way push button panel with sesam and 38kHz IR, Conson design",
|
|
158
|
+
},
|
|
159
|
+
ModuleTypeCode.XP2506B.value: {
|
|
160
|
+
"name": "XP2506B",
|
|
161
|
+
"description": "5 way push button panel with sesam and B&O IR, Conson design",
|
|
162
|
+
},
|
|
163
|
+
ModuleTypeCode.XPX1_8.value: {
|
|
164
|
+
"name": "XPX1_8",
|
|
165
|
+
"description": "8 way push button panel interface",
|
|
166
|
+
},
|
|
167
|
+
ModuleTypeCode.XP134.value: {
|
|
168
|
+
"name": "XP134",
|
|
169
|
+
"description": "Junctionbox interlink",
|
|
170
|
+
},
|
|
171
|
+
ModuleTypeCode.XP24P.value: {"name": "XP24P", "description": "XP24P module"},
|
|
172
|
+
ModuleTypeCode.XP28A.value: {"name": "XP28A", "description": "XP28A module"},
|
|
173
|
+
ModuleTypeCode.XP28B.value: {"name": "XP28B", "description": "XP28B module"},
|
|
174
|
+
ModuleTypeCode.CONTOOL.value: {"name": "CONTOOL", "description": "CONTOOL module"},
|
|
175
|
+
ModuleTypeCode.XP28.value: {"name": "XP28", "description": "XP28 module"},
|
|
176
|
+
ModuleTypeCode.XP31LR.value: {
|
|
177
|
+
"name": "XP31LR",
|
|
178
|
+
"description": "XP 1 channel lightdimmer",
|
|
179
|
+
},
|
|
180
|
+
ModuleTypeCode.XP33LR.value: {
|
|
181
|
+
"name": "XP33LR",
|
|
182
|
+
"description": "XP 33 3 channel lightdimmer",
|
|
183
|
+
},
|
|
184
|
+
ModuleTypeCode.XP31CR.value: {
|
|
185
|
+
"name": "XP31CR",
|
|
186
|
+
"description": "XP 31 1 channel dimmer",
|
|
187
|
+
},
|
|
188
|
+
ModuleTypeCode.XP31BC.value: {
|
|
189
|
+
"name": "XP31BC",
|
|
190
|
+
"description": "XP 31 1 channel dimmer",
|
|
191
|
+
},
|
|
192
|
+
ModuleTypeCode.XP20.value: {"name": "XP20", "description": "XP switch link module"},
|
|
193
|
+
ModuleTypeCode.XP230.value: {
|
|
194
|
+
"name": "XP230",
|
|
195
|
+
"description": "Ethernet/TCPIP interface module",
|
|
196
|
+
},
|
|
197
|
+
ModuleTypeCode.XP33LED.value: {
|
|
198
|
+
"name": "XP33LED",
|
|
199
|
+
"description": "XP 3 channel LED dimmer",
|
|
200
|
+
},
|
|
201
|
+
ModuleTypeCode.XP31LED.value: {
|
|
202
|
+
"name": "XP31LED",
|
|
203
|
+
"description": "XP 1 channel LED dimmer",
|
|
204
|
+
},
|
|
205
|
+
}
|