conson-xp 1.1.0__py3-none-any.whl → 1.3.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.
Files changed (174) hide show
  1. {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/METADATA +1 -5
  2. conson_xp-1.3.0.dist-info/RECORD +164 -0
  3. xp/__init__.py +4 -3
  4. xp/cli/__init__.py +1 -1
  5. xp/cli/commands/__init__.py +1 -2
  6. xp/cli/commands/conbus/conbus.py +9 -37
  7. xp/cli/commands/conbus/conbus_actiontable_commands.py +26 -4
  8. xp/cli/commands/conbus/conbus_autoreport_commands.py +58 -30
  9. xp/cli/commands/conbus/conbus_blink_commands.py +61 -29
  10. xp/cli/commands/conbus/conbus_config_commands.py +10 -5
  11. xp/cli/commands/conbus/conbus_custom_commands.py +16 -5
  12. xp/cli/commands/conbus/conbus_datapoint_commands.py +32 -10
  13. xp/cli/commands/conbus/conbus_discover_commands.py +20 -7
  14. xp/cli/commands/conbus/conbus_lightlevel_commands.py +114 -39
  15. xp/cli/commands/conbus/conbus_linknumber_commands.py +50 -25
  16. xp/cli/commands/conbus/conbus_msactiontable_commands.py +36 -5
  17. xp/cli/commands/conbus/conbus_output_commands.py +52 -14
  18. xp/cli/commands/conbus/conbus_raw_commands.py +17 -6
  19. xp/cli/commands/conbus/conbus_receive_commands.py +20 -10
  20. xp/cli/commands/conbus/conbus_scan_commands.py +17 -4
  21. xp/cli/commands/file_commands.py +35 -18
  22. xp/cli/commands/homekit/homekit.py +14 -8
  23. xp/cli/commands/homekit/homekit_start_commands.py +8 -6
  24. xp/cli/commands/module_commands.py +38 -23
  25. xp/cli/commands/reverse_proxy_commands.py +27 -19
  26. xp/cli/commands/server/server_commands.py +18 -18
  27. xp/cli/commands/telegram/telegram.py +4 -12
  28. xp/cli/commands/telegram/telegram_blink_commands.py +10 -8
  29. xp/cli/commands/telegram/telegram_checksum_commands.py +19 -8
  30. xp/cli/commands/telegram/telegram_discover_commands.py +2 -4
  31. xp/cli/commands/telegram/telegram_linknumber_commands.py +11 -8
  32. xp/cli/commands/telegram/telegram_parse_commands.py +10 -9
  33. xp/cli/commands/telegram/telegram_version_commands.py +8 -4
  34. xp/cli/main.py +5 -3
  35. xp/cli/utils/click_tree.py +23 -3
  36. xp/cli/utils/datapoint_type_choice.py +20 -0
  37. xp/cli/utils/decorators.py +165 -14
  38. xp/cli/utils/error_handlers.py +49 -18
  39. xp/cli/utils/formatters.py +95 -10
  40. xp/cli/utils/serial_number_type.py +18 -0
  41. xp/cli/utils/system_function_choice.py +20 -0
  42. xp/cli/utils/xp_module_type.py +20 -0
  43. xp/connection/__init__.py +1 -1
  44. xp/connection/exceptions.py +5 -5
  45. xp/models/__init__.py +1 -1
  46. xp/models/actiontable/__init__.py +1 -0
  47. xp/models/actiontable/actiontable.py +17 -1
  48. xp/models/actiontable/msactiontable_xp20.py +10 -0
  49. xp/models/actiontable/msactiontable_xp24.py +20 -3
  50. xp/models/actiontable/msactiontable_xp33.py +27 -4
  51. xp/models/conbus/__init__.py +1 -0
  52. xp/models/conbus/conbus.py +34 -4
  53. xp/models/conbus/conbus_autoreport.py +20 -2
  54. xp/models/conbus/conbus_blink.py +22 -2
  55. xp/models/conbus/conbus_client_config.py +22 -1
  56. xp/models/conbus/conbus_connection_status.py +16 -2
  57. xp/models/conbus/conbus_custom.py +21 -2
  58. xp/models/conbus/conbus_datapoint.py +25 -2
  59. xp/models/conbus/conbus_discover.py +18 -2
  60. xp/models/conbus/conbus_lightlevel.py +20 -2
  61. xp/models/conbus/conbus_linknumber.py +20 -2
  62. xp/models/conbus/conbus_output.py +22 -2
  63. xp/models/conbus/conbus_raw.py +17 -2
  64. xp/models/conbus/conbus_receive.py +16 -2
  65. xp/models/conbus/conbus_writeconfig.py +60 -0
  66. xp/models/homekit/__init__.py +1 -0
  67. xp/models/homekit/homekit_accessory.py +15 -1
  68. xp/models/homekit/homekit_config.py +52 -0
  69. xp/models/homekit/homekit_conson_config.py +32 -0
  70. xp/models/log_entry.py +49 -9
  71. xp/models/protocol/__init__.py +1 -0
  72. xp/models/protocol/conbus_protocol.py +130 -21
  73. xp/models/telegram/__init__.py +1 -0
  74. xp/models/telegram/action_type.py +16 -2
  75. xp/models/telegram/datapoint_type.py +36 -2
  76. xp/models/telegram/event_telegram.py +46 -10
  77. xp/models/telegram/event_type.py +8 -1
  78. xp/models/telegram/input_action_type.py +34 -2
  79. xp/models/telegram/input_type.py +9 -1
  80. xp/models/telegram/module_type.py +69 -19
  81. xp/models/telegram/module_type_code.py +43 -1
  82. xp/models/telegram/output_telegram.py +30 -6
  83. xp/models/telegram/reply_telegram.py +56 -11
  84. xp/models/telegram/system_function.py +35 -3
  85. xp/models/telegram/system_telegram.py +18 -4
  86. xp/models/telegram/telegram.py +12 -3
  87. xp/models/telegram/telegram_type.py +8 -1
  88. xp/models/telegram/timeparam_type.py +27 -0
  89. xp/models/write_config_type.py +17 -2
  90. xp/services/__init__.py +1 -1
  91. xp/services/conbus/__init__.py +1 -0
  92. xp/services/conbus/actiontable/__init__.py +1 -0
  93. xp/services/conbus/actiontable/actiontable_service.py +33 -2
  94. xp/services/conbus/actiontable/msactiontable_service.py +40 -3
  95. xp/services/conbus/actiontable/msactiontable_xp24_serializer.py +36 -4
  96. xp/services/conbus/actiontable/msactiontable_xp33_serializer.py +45 -5
  97. xp/services/conbus/conbus_blink_all_service.py +40 -21
  98. xp/services/conbus/conbus_blink_service.py +37 -13
  99. xp/services/conbus/conbus_custom_service.py +29 -13
  100. xp/services/conbus/conbus_datapoint_queryall_service.py +40 -16
  101. xp/services/conbus/conbus_datapoint_service.py +42 -18
  102. xp/services/conbus/conbus_discover_service.py +43 -7
  103. xp/services/conbus/conbus_output_service.py +33 -13
  104. xp/services/conbus/conbus_raw_service.py +36 -16
  105. xp/services/conbus/conbus_receive_service.py +38 -6
  106. xp/services/conbus/conbus_scan_service.py +44 -18
  107. xp/services/conbus/write_config_service.py +193 -0
  108. xp/services/homekit/__init__.py +1 -0
  109. xp/services/homekit/homekit_cache_service.py +31 -6
  110. xp/services/homekit/homekit_conbus_service.py +33 -2
  111. xp/services/homekit/homekit_config_validator.py +97 -15
  112. xp/services/homekit/homekit_conson_validator.py +51 -7
  113. xp/services/homekit/homekit_dimminglight.py +47 -1
  114. xp/services/homekit/homekit_dimminglight_service.py +35 -1
  115. xp/services/homekit/homekit_hap_service.py +71 -18
  116. xp/services/homekit/homekit_lightbulb.py +35 -1
  117. xp/services/homekit/homekit_lightbulb_service.py +30 -2
  118. xp/services/homekit/homekit_module_service.py +23 -1
  119. xp/services/homekit/homekit_outlet.py +47 -1
  120. xp/services/homekit/homekit_outlet_service.py +44 -2
  121. xp/services/homekit/homekit_service.py +113 -19
  122. xp/services/log_file_service.py +37 -41
  123. xp/services/module_type_service.py +26 -5
  124. xp/services/protocol/__init__.py +1 -1
  125. xp/services/protocol/conbus_protocol.py +110 -16
  126. xp/services/protocol/protocol_factory.py +40 -0
  127. xp/services/protocol/telegram_protocol.py +38 -7
  128. xp/services/reverse_proxy_service.py +79 -14
  129. xp/services/server/__init__.py +1 -0
  130. xp/services/server/base_server_service.py +102 -14
  131. xp/services/server/cp20_server_service.py +12 -4
  132. xp/services/server/server_service.py +26 -11
  133. xp/services/server/xp130_server_service.py +11 -3
  134. xp/services/server/xp20_server_service.py +11 -3
  135. xp/services/server/xp230_server_service.py +11 -3
  136. xp/services/server/xp24_server_service.py +33 -6
  137. xp/services/server/xp33_server_service.py +41 -8
  138. xp/services/telegram/__init__.py +1 -0
  139. xp/services/telegram/telegram_blink_service.py +19 -31
  140. xp/services/telegram/telegram_checksum_service.py +10 -10
  141. xp/services/telegram/telegram_datapoint_service.py +70 -0
  142. xp/services/telegram/telegram_discover_service.py +58 -29
  143. xp/services/telegram/telegram_link_number_service.py +27 -40
  144. xp/services/telegram/telegram_output_service.py +46 -49
  145. xp/services/telegram/telegram_service.py +41 -41
  146. xp/services/telegram/telegram_version_service.py +4 -2
  147. xp/utils/__init__.py +1 -1
  148. xp/utils/dependencies.py +4 -47
  149. xp/utils/serialization.py +6 -0
  150. xp/utils/time_utils.py +6 -11
  151. conson_xp-1.1.0.dist-info/RECORD +0 -181
  152. xp/api/__init__.py +0 -1
  153. xp/api/main.py +0 -110
  154. xp/api/models/__init__.py +0 -1
  155. xp/api/models/api.py +0 -20
  156. xp/api/models/discover.py +0 -21
  157. xp/api/routers/__init__.py +0 -17
  158. xp/api/routers/conbus.py +0 -5
  159. xp/api/routers/conbus_blink.py +0 -105
  160. xp/api/routers/conbus_custom.py +0 -63
  161. xp/api/routers/conbus_datapoint.py +0 -67
  162. xp/api/routers/conbus_output.py +0 -147
  163. xp/api/routers/errors.py +0 -37
  164. xp/cli/commands/api.py +0 -16
  165. xp/cli/commands/api_start_commands.py +0 -126
  166. xp/services/conbus/conbus_autoreport_get_service.py +0 -85
  167. xp/services/conbus/conbus_autoreport_set_service.py +0 -128
  168. xp/services/conbus/conbus_lightlevel_get_service.py +0 -101
  169. xp/services/conbus/conbus_lightlevel_set_service.py +0 -205
  170. xp/services/conbus/conbus_linknumber_get_service.py +0 -86
  171. xp/services/conbus/conbus_linknumber_set_service.py +0 -155
  172. {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/WHEEL +0 -0
  173. {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/entry_points.txt +0 -0
  174. {conson_xp-1.1.0.dist-info → conson_xp-1.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,3 +1,5 @@
1
+ """Conbus output response model."""
2
+
1
3
  from dataclasses import dataclass
2
4
  from datetime import datetime
3
5
  from typing import Any, Dict, Optional
@@ -9,7 +11,20 @@ from xp.models.telegram.reply_telegram import ReplyTelegram
9
11
 
10
12
  @dataclass
11
13
  class ConbusOutputResponse:
12
- """Represents a response from Conbus send operation"""
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
+ output_number: Output number controlled.
20
+ action_type: Type of action performed.
21
+ timestamp: Timestamp of the response.
22
+ output_telegram: Output telegram sent.
23
+ sent_telegram: Raw telegram sent to device.
24
+ received_telegrams: List of telegrams received.
25
+ datapoint_telegram: Datapoint telegram received.
26
+ error: Error message if operation failed.
27
+ """
13
28
 
14
29
  success: bool
15
30
  serial_number: str
@@ -23,11 +38,16 @@ class ConbusOutputResponse:
23
38
  error: Optional[str] = None
24
39
 
25
40
  def __post_init__(self) -> None:
41
+ """Initialize received_telegrams if not provided."""
26
42
  if self.received_telegrams is None:
27
43
  self.received_telegrams = []
28
44
 
29
45
  def to_dict(self) -> Dict[str, Any]:
30
- """Convert to dictionary for JSON serialization"""
46
+ """Convert to dictionary for JSON serialization.
47
+
48
+ Returns:
49
+ Dictionary representation of the response.
50
+ """
31
51
  return {
32
52
  "success": self.success,
33
53
  "sent_telegram": self.sent_telegram,
@@ -1,3 +1,5 @@
1
+ """Conbus raw response model."""
2
+
1
3
  from dataclasses import dataclass
2
4
  from datetime import datetime
3
5
  from typing import Any, Dict, List, Optional
@@ -5,7 +7,15 @@ from typing import Any, Dict, List, Optional
5
7
 
6
8
  @dataclass
7
9
  class ConbusRawResponse:
8
- """Represents a response from Conbus raw telegram send operation"""
10
+ """Represents a response from Conbus raw telegram send operation.
11
+
12
+ Attributes:
13
+ success: Whether the operation was successful.
14
+ sent_telegrams: Raw telegrams sent.
15
+ received_telegrams: List of telegrams received.
16
+ error: Error message if operation failed.
17
+ timestamp: Timestamp of the response.
18
+ """
9
19
 
10
20
  success: bool
11
21
  sent_telegrams: Optional[str] = None
@@ -14,13 +24,18 @@ class ConbusRawResponse:
14
24
  timestamp: Optional[datetime] = None
15
25
 
16
26
  def __post_init__(self) -> None:
27
+ """Initialize timestamp and received_telegrams if not provided."""
17
28
  if self.timestamp is None:
18
29
  self.timestamp = datetime.now()
19
30
  if self.received_telegrams is None:
20
31
  self.received_telegrams = []
21
32
 
22
33
  def to_dict(self) -> Dict[str, Any]:
23
- """Convert to dictionary for JSON serialization"""
34
+ """Convert to dictionary for JSON serialization.
35
+
36
+ Returns:
37
+ Dictionary representation of the response.
38
+ """
24
39
  return {
25
40
  "success": self.success,
26
41
  "sent_telegrams": self.sent_telegrams,
@@ -1,3 +1,5 @@
1
+ """Conbus receive response model."""
2
+
1
3
  from dataclasses import dataclass
2
4
  from datetime import datetime
3
5
  from typing import Any, Dict, List, Optional
@@ -5,7 +7,14 @@ from typing import Any, Dict, List, Optional
5
7
 
6
8
  @dataclass
7
9
  class ConbusReceiveResponse:
8
- """Represents a response from Conbus receive operation"""
10
+ """Represents a response from Conbus receive operation.
11
+
12
+ Attributes:
13
+ success: Whether the operation was successful.
14
+ received_telegrams: List of telegrams received.
15
+ error: Error message if operation failed.
16
+ timestamp: Timestamp of the response.
17
+ """
9
18
 
10
19
  success: bool
11
20
  received_telegrams: Optional[List[str]] = None
@@ -13,13 +22,18 @@ class ConbusReceiveResponse:
13
22
  timestamp: Optional[datetime] = None
14
23
 
15
24
  def __post_init__(self) -> None:
25
+ """Initialize timestamp and received_telegrams if not provided."""
16
26
  if self.timestamp is None:
17
27
  self.timestamp = datetime.now()
18
28
  if self.received_telegrams is None:
19
29
  self.received_telegrams = []
20
30
 
21
31
  def to_dict(self) -> Dict[str, Any]:
22
- """Convert to dictionary for JSON serialization"""
32
+ """Convert to dictionary for JSON serialization.
33
+
34
+ Returns:
35
+ Dictionary representation of the response.
36
+ """
23
37
  return {
24
38
  "success": self.success,
25
39
  "received_telegrams": self.received_telegrams,
@@ -0,0 +1,60 @@
1
+ """Conbus link number 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.datapoint_type import DataPointType
8
+ from xp.models.telegram.system_function import SystemFunction
9
+
10
+
11
+ @dataclass
12
+ class ConbusWriteConfigResponse:
13
+ """Represents a response from Conbus write config operations (set/get).
14
+
15
+ Attributes:
16
+ success: Whether the operation was successful.
17
+ serial_number: Serial number of the device.
18
+ datapoint_type: the datapoint to write.
19
+ system_function: ACK or NAK received.
20
+ sent_telegram: Telegram sent to device.
21
+ received_telegrams: List of telegrams received.
22
+ data_value: written value.
23
+ error: Error message if operation failed.
24
+ timestamp: Timestamp of the response.
25
+ """
26
+
27
+ success: bool
28
+ serial_number: str
29
+ datapoint_type: Optional[DataPointType] = None
30
+ system_function: Optional[SystemFunction] = None
31
+ sent_telegram: Optional[str] = None
32
+ received_telegrams: Optional[list] = None
33
+ data_value: Optional[str] = None
34
+ error: Optional[str] = None
35
+ timestamp: Optional[datetime] = None
36
+
37
+ def __post_init__(self) -> None:
38
+ """Initialize timestamp and received_telegrams if not provided."""
39
+ if self.timestamp is None:
40
+ self.timestamp = datetime.now()
41
+ if self.received_telegrams is None:
42
+ self.received_telegrams = []
43
+
44
+ def to_dict(self) -> Dict[str, Any]:
45
+ """Convert to dictionary for JSON serialization.
46
+
47
+ Returns:
48
+ Dictionary representation of the response.
49
+ """
50
+ return {
51
+ "success": self.success,
52
+ "system_function": self.system_function,
53
+ "datapoint_type": self.datapoint_type,
54
+ "data_value": self.data_value,
55
+ "serial_number": self.serial_number,
56
+ "sent_telegram": self.sent_telegram,
57
+ "received_telegrams": self.received_telegrams,
58
+ "error": self.error,
59
+ "timestamp": self.timestamp.isoformat() if self.timestamp else None,
60
+ }
@@ -0,0 +1 @@
1
+ """HomeKit integration models."""
@@ -1,3 +1,5 @@
1
+ """HomeKit configuration models."""
2
+
1
3
  import random
2
4
  from typing import Any
3
5
 
@@ -6,11 +8,22 @@ from pyhap.const import CATEGORY_SENSOR
6
8
 
7
9
 
8
10
  class TemperatureSensor(Accessory):
9
- """Fake Temperature sensor, measuring every 3 seconds."""
11
+ """Fake Temperature sensor, measuring every 3 seconds.
12
+
13
+ Attributes:
14
+ category: HomeKit category for sensor.
15
+ char_temp: Temperature characteristic.
16
+ """
10
17
 
11
18
  category = CATEGORY_SENSOR
12
19
 
13
20
  def __init__(self, *args: Any, **kwargs: Any) -> None:
21
+ """Initialize temperature sensor accessory.
22
+
23
+ Args:
24
+ args: Positional arguments passed to parent Accessory.
25
+ kwargs: Keyword arguments passed to parent Accessory.
26
+ """
14
27
  super().__init__(*args, **kwargs)
15
28
 
16
29
  serv_temp = self.add_preload_service("TemperatureSensor")
@@ -18,4 +31,5 @@ class TemperatureSensor(Accessory):
18
31
 
19
32
  @Accessory.run_at_interval(30)
20
33
  async def run(self) -> None:
34
+ """Update temperature value every 30 seconds."""
21
35
  self.char_temp.set_value(random.randint(-25, 25))
@@ -1,3 +1,5 @@
1
+ """HomeKit configuration models."""
2
+
1
3
  import logging
2
4
  from ipaddress import IPv4Address, IPv6Address
3
5
  from pathlib import Path
@@ -8,21 +10,54 @@ from pydantic import BaseModel, Field, IPvAnyAddress
8
10
 
9
11
 
10
12
  class NetworkConfig(BaseModel):
13
+ """Network configuration settings.
14
+
15
+ Attributes:
16
+ ip: IP address for the network connection.
17
+ port: Port number for the network connection.
18
+ """
19
+
11
20
  ip: Union[IPvAnyAddress, IPv4Address, IPv6Address, str] = "127.0.0.1"
12
21
  port: int = 51826
13
22
 
14
23
 
15
24
  class RoomConfig(BaseModel):
25
+ """Room configuration settings.
26
+
27
+ Attributes:
28
+ name: Name of the room.
29
+ accessories: List of accessory identifiers in the room.
30
+ """
31
+
16
32
  name: str
17
33
  accessories: List[str]
18
34
 
19
35
 
20
36
  class BridgeConfig(BaseModel):
37
+ """HomeKit bridge settings.
38
+
39
+ Attributes:
40
+ name: Name of the HomeKit bridge.
41
+ rooms: List of room configurations.
42
+ """
43
+
21
44
  name: str = "Conson Bridge"
22
45
  rooms: List[RoomConfig] = []
23
46
 
24
47
 
25
48
  class HomekitAccessoryConfig(BaseModel):
49
+ """HomeKit accessory configuration.
50
+
51
+ Attributes:
52
+ name: Name of the accessory.
53
+ id: Unique identifier for the accessory.
54
+ serial_number: Serial number of the accessory.
55
+ output_number: Output number for the accessory.
56
+ description: Description of the accessory.
57
+ service: Service type for the accessory.
58
+ hap_accessory: Optional HAP accessory identifier.
59
+ """
60
+
26
61
  name: str
27
62
  id: str
28
63
  serial_number: str
@@ -33,6 +68,15 @@ class HomekitAccessoryConfig(BaseModel):
33
68
 
34
69
 
35
70
  class HomekitConfig(BaseModel):
71
+ """HomeKit bridge configuration.
72
+
73
+ Attributes:
74
+ homekit: Network configuration for HomeKit.
75
+ conson: Network configuration for Conson.
76
+ bridge: Bridge configuration settings.
77
+ accessories: List of accessory configurations.
78
+ """
79
+
36
80
  homekit: NetworkConfig = Field(default_factory=NetworkConfig)
37
81
  conson: NetworkConfig = Field(default_factory=NetworkConfig)
38
82
  bridge: BridgeConfig = Field(default_factory=BridgeConfig)
@@ -40,6 +84,14 @@ class HomekitConfig(BaseModel):
40
84
 
41
85
  @classmethod
42
86
  def from_yaml(cls, file_path: str) -> "HomekitConfig":
87
+ """Load configuration from YAML file.
88
+
89
+ Args:
90
+ file_path: Path to the YAML configuration file.
91
+
92
+ Returns:
93
+ HomekitConfig instance loaded from file or default config.
94
+ """
43
95
  if not Path(file_path).exists():
44
96
  logger = logging.getLogger(__name__)
45
97
  logger.error(f"File {file_path} does not exist, loading default")
@@ -1,3 +1,5 @@
1
+ """HomeKit configuration models."""
2
+
1
3
  import logging
2
4
  from pathlib import Path
3
5
  from typing import List, Optional
@@ -6,6 +8,22 @@ from pydantic import BaseModel, IPvAnyAddress
6
8
 
7
9
 
8
10
  class ConsonModuleConfig(BaseModel):
11
+ """Configuration for a Conson module.
12
+
13
+ Attributes:
14
+ name: Name of the module.
15
+ serial_number: Serial number of the module.
16
+ module_type: Type of the module.
17
+ module_type_code: Numeric code for the module type.
18
+ link_number: Link number for the module.
19
+ enabled: Whether the module is enabled.
20
+ module_number: Optional module number.
21
+ conbus_ip: Optional Conbus IP address.
22
+ conbus_port: Optional Conbus port number.
23
+ sw_version: Optional software version.
24
+ hw_version: Optional hardware version.
25
+ """
26
+
9
27
  name: str
10
28
  serial_number: str
11
29
  module_type: str
@@ -20,10 +38,24 @@ class ConsonModuleConfig(BaseModel):
20
38
 
21
39
 
22
40
  class ConsonModuleListConfig(BaseModel):
41
+ """Configuration list for Conson modules.
42
+
43
+ Attributes:
44
+ root: List of Conson module configurations.
45
+ """
46
+
23
47
  root: List[ConsonModuleConfig] = []
24
48
 
25
49
  @classmethod
26
50
  def from_yaml(cls, file_path: str) -> "ConsonModuleListConfig":
51
+ """Load configuration from YAML file.
52
+
53
+ Args:
54
+ file_path: Path to the YAML configuration file.
55
+
56
+ Returns:
57
+ ConsonModuleListConfig instance loaded from file or default config.
58
+ """
27
59
  import yaml
28
60
 
29
61
  if not Path(file_path).exists():
xp/models/log_entry.py CHANGED
@@ -11,11 +11,23 @@ from xp.models.telegram.system_telegram import SystemTelegram
11
11
 
12
12
  @dataclass
13
13
  class LogEntry:
14
- """
15
- Represents a single entry in a console bus log file.
14
+ """Represents a single entry in a console bus log file.
16
15
 
17
16
  Format: HH:MM:SS,mmm [TX/RX] <telegram>
18
17
  Examples: 22:44:20,352 [TX] <S0012345008F27D00AAFN>
18
+
19
+ Attributes:
20
+ timestamp: Timestamp of the log entry.
21
+ direction: Direction of telegram ("TX" or "RX").
22
+ raw_telegram: Raw telegram string.
23
+ parsed_telegram: Parsed telegram object if successfully parsed.
24
+ parse_error: Error message if parsing failed.
25
+ line_number: Line number in the log file.
26
+ is_transmitted: True if this is a transmitted telegram.
27
+ is_received: True if this is a received telegram.
28
+ telegram_type: Telegram type (event, system, reply, unknown).
29
+ is_valid_parse: True if the telegram was successfully parsed.
30
+ checksum_validated: Checksum validation status if available.
19
31
  """
20
32
 
21
33
  timestamp: datetime
@@ -29,17 +41,29 @@ class LogEntry:
29
41
 
30
42
  @property
31
43
  def is_transmitted(self) -> bool:
32
- """True if this is a transmitted telegram"""
44
+ """True if this is a transmitted telegram.
45
+
46
+ Returns:
47
+ True if direction is TX, False otherwise.
48
+ """
33
49
  return self.direction == "TX"
34
50
 
35
51
  @property
36
52
  def is_received(self) -> bool:
37
- """True if this is a received telegram"""
53
+ """True if this is a received telegram.
54
+
55
+ Returns:
56
+ True if direction is RX, False otherwise.
57
+ """
38
58
  return self.direction == "RX"
39
59
 
40
60
  @property
41
61
  def telegram_type(self) -> str:
42
- """Get the telegram type (event, system, reply, unknown)"""
62
+ """Get the telegram type (event, system, reply, unknown).
63
+
64
+ Returns:
65
+ Telegram type string.
66
+ """
43
67
  if self.parsed_telegram is None:
44
68
  return "unknown"
45
69
 
@@ -47,18 +71,30 @@ class LogEntry:
47
71
 
48
72
  @property
49
73
  def is_valid_parse(self) -> bool:
50
- """True if the telegram was successfully parsed"""
74
+ """True if the telegram was successfully parsed.
75
+
76
+ Returns:
77
+ True if parsed without errors, False otherwise.
78
+ """
51
79
  return self.parsed_telegram is not None and self.parse_error is None
52
80
 
53
81
  @property
54
82
  def checksum_validated(self) -> Optional[bool]:
55
- """Get checksum validation status if available"""
83
+ """Get checksum validation status if available.
84
+
85
+ Returns:
86
+ Checksum validation status or None if not available.
87
+ """
56
88
  if self.parsed_telegram and hasattr(self.parsed_telegram, "checksum_validated"):
57
89
  return self.parsed_telegram.checksum_validated
58
90
  return None
59
91
 
60
92
  def to_dict(self) -> dict[str, Any]:
61
- """Convert to dictionary for JSON serialization"""
93
+ """Convert to dictionary for JSON serialization.
94
+
95
+ Returns:
96
+ Dictionary representation of the log entry.
97
+ """
62
98
  result: dict[str, Any] = {
63
99
  "line_number": self.line_number,
64
100
  "timestamp": self.timestamp.strftime("%H:%M:%S.%f")[
@@ -79,7 +115,11 @@ class LogEntry:
79
115
  return result
80
116
 
81
117
  def __str__(self) -> str:
82
- """Human-readable string representation"""
118
+ """Human-readable string representation.
119
+
120
+ Returns:
121
+ Formatted string representation of the log entry.
122
+ """
83
123
  timestamp_str = self.timestamp.strftime("%H:%M:%S,%f")[:-3] # HH:MM:SS,mmm
84
124
  status = "✓" if self.is_valid_parse else "✗"
85
125
  checksum_status = ""
@@ -0,0 +1 @@
1
+ """Protocol models and interfaces."""