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,53 @@
|
|
|
1
|
+
"""XP20 Action Table models for input actions and settings."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class InputChannel:
|
|
8
|
+
"""Configuration for a single input channel in XP20 action table.
|
|
9
|
+
|
|
10
|
+
Attributes:
|
|
11
|
+
invert: Input inversion flag
|
|
12
|
+
short_long: Short/long press detection flag
|
|
13
|
+
group_on_off: Group on/off function flag
|
|
14
|
+
and_functions: 8-bit AND function configuration array
|
|
15
|
+
sa_function: SA function flag
|
|
16
|
+
ta_function: TA function flag
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
invert: bool = False
|
|
20
|
+
short_long: bool = False
|
|
21
|
+
group_on_off: bool = False
|
|
22
|
+
and_functions: list[bool] = field(default_factory=lambda: [False] * 8)
|
|
23
|
+
sa_function: bool = False
|
|
24
|
+
ta_function: bool = False
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class Xp20MsActionTable:
|
|
29
|
+
"""XP20 Action Table for managing 8 input channels.
|
|
30
|
+
|
|
31
|
+
Contains configuration for 8 input channels (input1 through input8),
|
|
32
|
+
each with flags for inversion, short/long press detection, group functions,
|
|
33
|
+
AND functions, SA functions, and TA functions.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
input1: Configuration for input channel 1.
|
|
37
|
+
input2: Configuration for input channel 2.
|
|
38
|
+
input3: Configuration for input channel 3.
|
|
39
|
+
input4: Configuration for input channel 4.
|
|
40
|
+
input5: Configuration for input channel 5.
|
|
41
|
+
input6: Configuration for input channel 6.
|
|
42
|
+
input7: Configuration for input channel 7.
|
|
43
|
+
input8: Configuration for input channel 8.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
input1: InputChannel = field(default_factory=InputChannel)
|
|
47
|
+
input2: InputChannel = field(default_factory=InputChannel)
|
|
48
|
+
input3: InputChannel = field(default_factory=InputChannel)
|
|
49
|
+
input4: InputChannel = field(default_factory=InputChannel)
|
|
50
|
+
input5: InputChannel = field(default_factory=InputChannel)
|
|
51
|
+
input6: InputChannel = field(default_factory=InputChannel)
|
|
52
|
+
input7: InputChannel = field(default_factory=InputChannel)
|
|
53
|
+
input8: InputChannel = field(default_factory=InputChannel)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""XP24 Action Table models for input actions and settings."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
|
|
5
|
+
from xp.models.telegram.input_action_type import InputActionType
|
|
6
|
+
from xp.models.telegram.timeparam_type import TimeParam
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class InputAction:
|
|
11
|
+
"""Represents an input action with type and parameter.
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
type: The input action type.
|
|
15
|
+
param: Time parameter for the action.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
type: InputActionType = InputActionType.TOGGLE
|
|
19
|
+
param: TimeParam = TimeParam.NONE
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class Xp24MsActionTable:
|
|
24
|
+
"""XP24 Action Table for managing input actions and settings.
|
|
25
|
+
|
|
26
|
+
Each input has an action type (TOGGLE, ON, LEVELSET, etc.)
|
|
27
|
+
with an optional parameter string.
|
|
28
|
+
|
|
29
|
+
Attributes:
|
|
30
|
+
MS300: Timing constant for 300ms.
|
|
31
|
+
MS500: Timing constant for 500ms.
|
|
32
|
+
input1_action: Action configuration for input 1.
|
|
33
|
+
input2_action: Action configuration for input 2.
|
|
34
|
+
input3_action: Action configuration for input 3.
|
|
35
|
+
input4_action: Action configuration for input 4.
|
|
36
|
+
mutex12: Mutual exclusion between inputs 1-2.
|
|
37
|
+
mutex34: Mutual exclusion between inputs 3-4.
|
|
38
|
+
curtain12: Curtain setting for inputs 1-2.
|
|
39
|
+
curtain34: Curtain setting for inputs 3-4.
|
|
40
|
+
mutual_deadtime: Master timing (MS300=12 or MS500=20).
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
# MS timing constants
|
|
44
|
+
MS300 = 12
|
|
45
|
+
MS500 = 20
|
|
46
|
+
|
|
47
|
+
# Input actions for each input (default to TOGGLE with None parameter)
|
|
48
|
+
input1_action: InputAction = field(default_factory=InputAction)
|
|
49
|
+
input2_action: InputAction = field(default_factory=InputAction)
|
|
50
|
+
input3_action: InputAction = field(default_factory=InputAction)
|
|
51
|
+
input4_action: InputAction = field(default_factory=InputAction)
|
|
52
|
+
|
|
53
|
+
# Boolean settings
|
|
54
|
+
mutex12: bool = False # Mutual exclusion between inputs 1-2
|
|
55
|
+
mutex34: bool = False # Mutual exclusion between inputs 3-4
|
|
56
|
+
curtain12: bool = False # Curtain setting for inputs 1-2
|
|
57
|
+
curtain34: bool = False # Curtain setting for inputs 3-4
|
|
58
|
+
mutual_deadtime: int = MS300 # Master timing (MS300=12 or MS500=20)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""XP33 Action Table models for output and scene configuration."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
|
|
5
|
+
from xp.models.telegram.timeparam_type import TimeParam
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class Xp33Output:
|
|
10
|
+
"""Represents an XP33 output configuration.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
min_level: Minimum output level (0-100).
|
|
14
|
+
max_level: Maximum output level (0-100).
|
|
15
|
+
scene_outputs: Enable scene outputs.
|
|
16
|
+
start_at_full: Start at full brightness.
|
|
17
|
+
leading_edge: Use leading edge dimming.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
min_level: int = 0
|
|
21
|
+
max_level: int = 100
|
|
22
|
+
scene_outputs: bool = False
|
|
23
|
+
start_at_full: bool = False
|
|
24
|
+
leading_edge: bool = False
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class Xp33Scene:
|
|
29
|
+
"""Represents a scene configuration.
|
|
30
|
+
|
|
31
|
+
Attributes:
|
|
32
|
+
output1_level: Output level for output 1 (0-100).
|
|
33
|
+
output2_level: Output level for output 2 (0-100).
|
|
34
|
+
output3_level: Output level for output 3 (0-100).
|
|
35
|
+
time: Time parameter for scene transition.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
output1_level: int = 0
|
|
39
|
+
output2_level: int = 0
|
|
40
|
+
output3_level: int = 0
|
|
41
|
+
time: TimeParam = TimeParam.NONE
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class Xp33MsActionTable:
|
|
46
|
+
"""XP33 Action Table for managing outputs and scenes.
|
|
47
|
+
|
|
48
|
+
Attributes:
|
|
49
|
+
output1: Configuration for output 1.
|
|
50
|
+
output2: Configuration for output 2.
|
|
51
|
+
output3: Configuration for output 3.
|
|
52
|
+
scene1: Configuration for scene 1.
|
|
53
|
+
scene2: Configuration for scene 2.
|
|
54
|
+
scene3: Configuration for scene 3.
|
|
55
|
+
scene4: Configuration for scene 4.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
output1: Xp33Output = field(default_factory=Xp33Output)
|
|
59
|
+
output2: Xp33Output = field(default_factory=Xp33Output)
|
|
60
|
+
output3: Xp33Output = field(default_factory=Xp33Output)
|
|
61
|
+
|
|
62
|
+
scene1: Xp33Scene = field(default_factory=Xp33Scene)
|
|
63
|
+
scene2: Xp33Scene = field(default_factory=Xp33Scene)
|
|
64
|
+
scene3: Xp33Scene = field(default_factory=Xp33Scene)
|
|
65
|
+
scene4: Xp33Scene = field(default_factory=Xp33Scene)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Conbus communication models."""
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Conbus request and response models."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict, Optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class ConbusRequest:
|
|
10
|
+
"""Represents a Conbus send request.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
serial_number: Serial number of the target device.
|
|
14
|
+
function_code: Function code for the operation.
|
|
15
|
+
data: Data payload for the request.
|
|
16
|
+
telegram: Raw telegram string.
|
|
17
|
+
timestamp: Timestamp of the request.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
serial_number: Optional[str] = None
|
|
21
|
+
function_code: Optional[str] = None
|
|
22
|
+
data: Optional[str] = None
|
|
23
|
+
telegram: Optional[str] = None
|
|
24
|
+
timestamp: Optional[datetime] = None
|
|
25
|
+
|
|
26
|
+
def __post_init__(self) -> None:
|
|
27
|
+
"""Initialize timestamp if not provided."""
|
|
28
|
+
if self.timestamp is None:
|
|
29
|
+
self.timestamp = datetime.now()
|
|
30
|
+
|
|
31
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
32
|
+
"""Convert to dictionary for JSON serialization.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Dictionary representation of the request.
|
|
36
|
+
"""
|
|
37
|
+
return {
|
|
38
|
+
"serial_number": self.serial_number,
|
|
39
|
+
"function_code": self.function_code,
|
|
40
|
+
"data": self.data,
|
|
41
|
+
"timestamp": self.timestamp.isoformat() if self.timestamp else None,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class ConbusResponse:
|
|
47
|
+
"""Represents a response from Conbus send operation.
|
|
48
|
+
|
|
49
|
+
Attributes:
|
|
50
|
+
success: Whether the operation was successful.
|
|
51
|
+
sent_telegrams: List of telegrams sent.
|
|
52
|
+
received_telegrams: List of telegrams received.
|
|
53
|
+
timestamp: Timestamp of the response.
|
|
54
|
+
error: Error message if operation failed.
|
|
55
|
+
serial_number: Serial number of the device.
|
|
56
|
+
function_code: Function code used.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
success: bool
|
|
60
|
+
sent_telegrams: list[str]
|
|
61
|
+
received_telegrams: list[str]
|
|
62
|
+
timestamp: datetime
|
|
63
|
+
error: str = ""
|
|
64
|
+
serial_number: str = ""
|
|
65
|
+
function_code: str = ""
|
|
66
|
+
|
|
67
|
+
def __post_init__(self) -> None:
|
|
68
|
+
"""Initialize timestamp and telegram lists."""
|
|
69
|
+
self.timestamp = datetime.now()
|
|
70
|
+
self.sent_telegrams = []
|
|
71
|
+
self.received_telegrams = []
|
|
72
|
+
|
|
73
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
74
|
+
"""Convert to dictionary for JSON serialization.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Dictionary representation of the response.
|
|
78
|
+
"""
|
|
79
|
+
return {
|
|
80
|
+
"success": self.success,
|
|
81
|
+
"serial_number": self.serial_number,
|
|
82
|
+
"function_code": self.function_code,
|
|
83
|
+
"sent_telegrams": self.sent_telegrams,
|
|
84
|
+
"received_telegrams": self.received_telegrams,
|
|
85
|
+
"error": self.error,
|
|
86
|
+
"timestamp": self.timestamp.isoformat() if self.timestamp else None,
|
|
87
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Conbus auto report response model."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict, Optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class ConbusAutoreportResponse:
|
|
10
|
+
"""Represents a response from Conbus auto report operations (get/set).
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
success: Whether the operation was successful.
|
|
14
|
+
serial_number: Serial number of the device.
|
|
15
|
+
auto_report_status: Current auto report status.
|
|
16
|
+
result: Result message from set operation.
|
|
17
|
+
sent_telegram: Telegram sent to device.
|
|
18
|
+
received_telegrams: List of telegrams received.
|
|
19
|
+
error: Error message if operation failed.
|
|
20
|
+
timestamp: Timestamp of the response.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
success: bool
|
|
24
|
+
serial_number: str
|
|
25
|
+
auto_report_status: Optional[str] = None
|
|
26
|
+
result: Optional[str] = None
|
|
27
|
+
sent_telegram: Optional[str] = None
|
|
28
|
+
received_telegrams: Optional[list[str]] = None
|
|
29
|
+
error: Optional[str] = None
|
|
30
|
+
timestamp: Optional[datetime] = None
|
|
31
|
+
|
|
32
|
+
def __post_init__(self) -> None:
|
|
33
|
+
"""Initialize timestamp and received_telegrams if not provided."""
|
|
34
|
+
if self.timestamp is None:
|
|
35
|
+
self.timestamp = datetime.now()
|
|
36
|
+
if self.received_telegrams is None:
|
|
37
|
+
self.received_telegrams = []
|
|
38
|
+
|
|
39
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
40
|
+
"""Convert to dictionary for JSON serialization.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Dictionary representation of the response.
|
|
44
|
+
"""
|
|
45
|
+
result_dict: Dict[str, Any] = {
|
|
46
|
+
"success": self.success,
|
|
47
|
+
"serial_number": self.serial_number,
|
|
48
|
+
"error": self.error,
|
|
49
|
+
"timestamp": self.timestamp.isoformat() if self.timestamp else None,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Include auto_report_status if available
|
|
53
|
+
if self.auto_report_status is not None:
|
|
54
|
+
result_dict["auto_report_status"] = self.auto_report_status
|
|
55
|
+
|
|
56
|
+
# Include result for set operations
|
|
57
|
+
if self.result is not None:
|
|
58
|
+
result_dict["result"] = self.result
|
|
59
|
+
|
|
60
|
+
# Include telegram details
|
|
61
|
+
if self.sent_telegram is not None:
|
|
62
|
+
result_dict["sent_telegram"] = self.sent_telegram
|
|
63
|
+
|
|
64
|
+
if self.received_telegrams is not None:
|
|
65
|
+
result_dict["received_telegrams"] = self.received_telegrams
|
|
66
|
+
|
|
67
|
+
return result_dict
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Conbus blink response model."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict, Optional
|
|
6
|
+
|
|
7
|
+
from xp.models import ConbusResponse
|
|
8
|
+
from xp.models.telegram.reply_telegram import ReplyTelegram
|
|
9
|
+
from xp.models.telegram.system_function import SystemFunction
|
|
10
|
+
from xp.models.telegram.system_telegram import SystemTelegram
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class ConbusBlinkResponse:
|
|
15
|
+
"""Represents a response from Conbus send operation.
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
success: Whether the operation was successful.
|
|
19
|
+
serial_number: Serial number of the device.
|
|
20
|
+
operation: Operation type (get or set).
|
|
21
|
+
system_function: System function used.
|
|
22
|
+
response: Response from Conbus operation.
|
|
23
|
+
reply_telegram: Reply telegram received.
|
|
24
|
+
sent_telegram: System telegram sent.
|
|
25
|
+
received_telegrams: List of telegrams received.
|
|
26
|
+
error: Error message if operation failed.
|
|
27
|
+
timestamp: Timestamp of the response.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
success: bool
|
|
31
|
+
serial_number: str
|
|
32
|
+
operation: str
|
|
33
|
+
system_function: SystemFunction
|
|
34
|
+
response: Optional[ConbusResponse] = None
|
|
35
|
+
reply_telegram: Optional[ReplyTelegram] = None
|
|
36
|
+
sent_telegram: Optional[SystemTelegram] = None
|
|
37
|
+
received_telegrams: Optional[list] = None
|
|
38
|
+
error: Optional[str] = None
|
|
39
|
+
timestamp: Optional[datetime] = None
|
|
40
|
+
|
|
41
|
+
def __post_init__(self) -> None:
|
|
42
|
+
"""Initialize timestamp and received_telegrams if not provided."""
|
|
43
|
+
if self.timestamp is None:
|
|
44
|
+
self.timestamp = datetime.now()
|
|
45
|
+
if self.received_telegrams is None:
|
|
46
|
+
self.received_telegrams = []
|
|
47
|
+
|
|
48
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
49
|
+
"""Convert to dictionary for JSON serialization.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Dictionary representation of the response.
|
|
53
|
+
"""
|
|
54
|
+
result = {
|
|
55
|
+
"success": self.success,
|
|
56
|
+
"serial_number": self.serial_number,
|
|
57
|
+
"operation": self.operation,
|
|
58
|
+
"system_function": (
|
|
59
|
+
self.system_function.name if self.system_function else None
|
|
60
|
+
),
|
|
61
|
+
"sent_telegram": (
|
|
62
|
+
self.sent_telegram.to_dict()
|
|
63
|
+
if self.sent_telegram and hasattr(self.sent_telegram, "to_dict")
|
|
64
|
+
else str(self.sent_telegram) if self.sent_telegram else None
|
|
65
|
+
),
|
|
66
|
+
"reply_telegram": (
|
|
67
|
+
self.reply_telegram.to_dict()
|
|
68
|
+
if self.reply_telegram and hasattr(self.reply_telegram, "to_dict")
|
|
69
|
+
else str(self.reply_telegram) if self.reply_telegram else None
|
|
70
|
+
),
|
|
71
|
+
"timestamp": self.timestamp.isoformat() if self.timestamp else None,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# Only include these if they have values
|
|
75
|
+
if self.received_telegrams:
|
|
76
|
+
result["received_telegrams"] = self.received_telegrams
|
|
77
|
+
if self.error:
|
|
78
|
+
result["error"] = self.error
|
|
79
|
+
|
|
80
|
+
return result
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Conbus client configuration models."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import yaml
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ClientConfig(BaseModel):
|
|
11
|
+
"""Client connection configuration.
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
ip: IP address of the Conbus server.
|
|
15
|
+
port: Port number for the connection.
|
|
16
|
+
timeout: Connection timeout in seconds.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
ip: str = "192.168.1.100"
|
|
20
|
+
port: int = 10001
|
|
21
|
+
timeout: float = 0.1
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ConbusClientConfig(BaseModel):
|
|
25
|
+
"""Configuration for Conbus client connection.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
conbus: Client configuration settings.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
conbus: ClientConfig = Field(default_factory=ClientConfig)
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def from_yaml(cls, file_path: str) -> "ConbusClientConfig":
|
|
35
|
+
"""Load configuration from YAML file.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
file_path: Path to the YAML configuration file.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
ConbusClientConfig instance loaded from file or default config.
|
|
42
|
+
"""
|
|
43
|
+
logger = logging.getLogger(__name__)
|
|
44
|
+
try:
|
|
45
|
+
with Path(file_path).open("r") as file:
|
|
46
|
+
data = yaml.safe_load(file)
|
|
47
|
+
return cls(**data)
|
|
48
|
+
|
|
49
|
+
except FileNotFoundError:
|
|
50
|
+
logger.error(f"File {file_path} does not exist, loading default")
|
|
51
|
+
return cls()
|
|
52
|
+
except yaml.YAMLError:
|
|
53
|
+
logger.error(f"File {file_path} is not valid")
|
|
54
|
+
# Return default config if YAML parsing fails
|
|
55
|
+
return cls()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Conbus connection status model."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict, Optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class ConbusConnectionStatus:
|
|
10
|
+
"""Represents the current connection status.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
connected: Whether currently connected.
|
|
14
|
+
ip: IP address of the connection.
|
|
15
|
+
port: Port number of the connection.
|
|
16
|
+
last_activity: Timestamp of last activity.
|
|
17
|
+
error: Error message if connection failed.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
connected: bool
|
|
21
|
+
ip: str
|
|
22
|
+
port: int
|
|
23
|
+
last_activity: Optional[datetime] = None
|
|
24
|
+
error: Optional[str] = None
|
|
25
|
+
|
|
26
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
27
|
+
"""Convert to dictionary for JSON serialization.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Dictionary representation of the connection status.
|
|
31
|
+
"""
|
|
32
|
+
return {
|
|
33
|
+
"connected": self.connected,
|
|
34
|
+
"ip": self.ip,
|
|
35
|
+
"port": self.port,
|
|
36
|
+
"last_activity": (
|
|
37
|
+
self.last_activity.isoformat() if self.last_activity else None
|
|
38
|
+
),
|
|
39
|
+
"error": self.error,
|
|
40
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Conbus custom response model."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict, Optional
|
|
6
|
+
|
|
7
|
+
from xp.models.telegram.reply_telegram import ReplyTelegram
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class ConbusCustomResponse:
|
|
12
|
+
"""Represents a response from Conbus send operation.
|
|
13
|
+
|
|
14
|
+
Attributes:
|
|
15
|
+
success: Whether the operation was successful.
|
|
16
|
+
serial_number: Serial number of the device.
|
|
17
|
+
function_code: Function code used.
|
|
18
|
+
data: Data payload.
|
|
19
|
+
sent_telegram: Telegram sent to device.
|
|
20
|
+
received_telegrams: List of telegrams received.
|
|
21
|
+
reply_telegram: Parsed reply telegram.
|
|
22
|
+
error: Error message if operation failed.
|
|
23
|
+
timestamp: Timestamp of the response.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
success: bool
|
|
27
|
+
serial_number: Optional[str] = None
|
|
28
|
+
function_code: Optional[str] = None
|
|
29
|
+
data: Optional[str] = None
|
|
30
|
+
sent_telegram: Optional[str] = None
|
|
31
|
+
received_telegrams: Optional[list] = None
|
|
32
|
+
reply_telegram: Optional[ReplyTelegram] = None
|
|
33
|
+
error: Optional[str] = None
|
|
34
|
+
timestamp: Optional[datetime] = None
|
|
35
|
+
|
|
36
|
+
def __post_init__(self) -> None:
|
|
37
|
+
"""Initialize timestamp and received_telegrams if not provided."""
|
|
38
|
+
if self.timestamp is None:
|
|
39
|
+
self.timestamp = datetime.now()
|
|
40
|
+
if self.received_telegrams is None:
|
|
41
|
+
self.received_telegrams = []
|
|
42
|
+
|
|
43
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
44
|
+
"""Convert to dictionary for JSON serialization.
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
Dictionary representation of the response.
|
|
48
|
+
"""
|
|
49
|
+
return {
|
|
50
|
+
"success": self.success,
|
|
51
|
+
"serial_number": self.serial_number,
|
|
52
|
+
"function_code": self.function_code,
|
|
53
|
+
"data": self.data,
|
|
54
|
+
"sent_telegram": self.sent_telegram,
|
|
55
|
+
"received_telegrams": self.received_telegrams,
|
|
56
|
+
"error": self.error,
|
|
57
|
+
"timestamp": self.timestamp.isoformat() if self.timestamp else None,
|
|
58
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Conbus datapoint response model."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
from xp.models.telegram.datapoint_type import DataPointType
|
|
8
|
+
from xp.models.telegram.reply_telegram import ReplyTelegram
|
|
9
|
+
from xp.models.telegram.system_function import SystemFunction
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class ConbusDatapointResponse:
|
|
14
|
+
"""Represents a response from Conbus send operation.
|
|
15
|
+
|
|
16
|
+
Attributes:
|
|
17
|
+
success: Whether the operation was successful.
|
|
18
|
+
serial_number: Serial number of the device.
|
|
19
|
+
system_function: System function used for query.
|
|
20
|
+
datapoint_type: Type of datapoint queried.
|
|
21
|
+
sent_telegram: Telegram sent to device.
|
|
22
|
+
received_telegrams: List of telegrams received.
|
|
23
|
+
datapoint_telegram: Parsed datapoint telegram.
|
|
24
|
+
data_value: Value of the datapoint telegram.
|
|
25
|
+
datapoints: List of datapoint values.
|
|
26
|
+
error: Error message if operation failed.
|
|
27
|
+
timestamp: Timestamp of the response.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
success: bool
|
|
31
|
+
serial_number: Optional[str] = None
|
|
32
|
+
system_function: Optional[SystemFunction] = None
|
|
33
|
+
datapoint_type: Optional[DataPointType] = None
|
|
34
|
+
sent_telegram: Optional[str] = None
|
|
35
|
+
received_telegrams: Optional[list] = None
|
|
36
|
+
datapoint_telegram: Optional[ReplyTelegram] = None
|
|
37
|
+
data_value: str = ""
|
|
38
|
+
datapoints: Optional[List[Dict[str, str]]] = None
|
|
39
|
+
error: Optional[str] = None
|
|
40
|
+
timestamp: Optional[datetime] = None
|
|
41
|
+
|
|
42
|
+
def __post_init__(self) -> None:
|
|
43
|
+
"""Initialize timestamp, received_telegrams, and datapoints if not provided."""
|
|
44
|
+
if self.timestamp is None:
|
|
45
|
+
self.timestamp = datetime.now()
|
|
46
|
+
if self.received_telegrams is None:
|
|
47
|
+
self.received_telegrams = []
|
|
48
|
+
if self.datapoints is None:
|
|
49
|
+
self.datapoints = []
|
|
50
|
+
|
|
51
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
52
|
+
"""Convert to dictionary for JSON serialization.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Dictionary representation of the response.
|
|
56
|
+
"""
|
|
57
|
+
result: Dict[str, Any] = {
|
|
58
|
+
"success": self.success,
|
|
59
|
+
"serial_number": self.serial_number,
|
|
60
|
+
"data_value": self.data_value,
|
|
61
|
+
"error": self.error,
|
|
62
|
+
"timestamp": self.timestamp.isoformat() if self.timestamp else None,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Include system_function for single datapoint queries
|
|
66
|
+
if self.system_function is not None:
|
|
67
|
+
result["system_function"] = str(self.system_function)
|
|
68
|
+
|
|
69
|
+
# Include datapoint_type for single datapoint queries
|
|
70
|
+
if self.datapoint_type is not None:
|
|
71
|
+
result["datapoint_type"] = str(self.datapoint_type)
|
|
72
|
+
|
|
73
|
+
# Include sent_telegram for single datapoint queries
|
|
74
|
+
if self.sent_telegram is not None:
|
|
75
|
+
result["sent_telegram"] = self.sent_telegram
|
|
76
|
+
|
|
77
|
+
# Include received_telegrams for single datapoint queries
|
|
78
|
+
if self.received_telegrams is not None:
|
|
79
|
+
result["received_telegrams"] = self.received_telegrams
|
|
80
|
+
|
|
81
|
+
# Include datapoint_telegram for single datapoint queries
|
|
82
|
+
if self.datapoint_telegram is not None:
|
|
83
|
+
result["datapoint_telegram"] = self.datapoint_telegram.to_dict()
|
|
84
|
+
|
|
85
|
+
# Include datapoints for all datapoints queries
|
|
86
|
+
if self.datapoints is not None and len(self.datapoints) > 0:
|
|
87
|
+
result["datapoints"] = self.datapoints
|
|
88
|
+
|
|
89
|
+
return result
|