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
xp/utils/checksum.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Checksum utility functions for protocol interoperability.
|
|
2
|
+
|
|
3
|
+
This module provides standard checksum calculation functions for protocol
|
|
4
|
+
communication compatibility, including XOR checksum and IEEE 802.3 CRC32.
|
|
5
|
+
Implemented for interoperability purposes under fair use provisions.
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2025 ld
|
|
8
|
+
Licensed under MIT License - see LICENSE file for details.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from xp.utils.serialization import nibble
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def calculate_checksum(buffer: str) -> str:
|
|
15
|
+
"""Calculate simple XOR checksum of a string buffer.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
buffer: Input string to calculate checksum for
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
Two-character checksum string in nibble format
|
|
22
|
+
"""
|
|
23
|
+
cc = 0
|
|
24
|
+
for char in buffer:
|
|
25
|
+
cc ^= ord(char)
|
|
26
|
+
|
|
27
|
+
return nibble(cc & 0xFF)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def calculate_checksum32(buffer: bytes) -> str:
|
|
31
|
+
"""Calculate CRC32 checksum for protocol interoperability.
|
|
32
|
+
|
|
33
|
+
Implements standard CRC32 algorithm using IEEE 802.3 polynomial 0xEDB88320
|
|
34
|
+
for interoperability with XP protocol communications. This is a standard
|
|
35
|
+
algorithm implementation for protocol compatibility purposes.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
buffer: Byte array to calculate checksum for
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Eight-character checksum string in nibble format
|
|
42
|
+
"""
|
|
43
|
+
nibble_result = ""
|
|
44
|
+
crc = 0xFFFFFFFF # Initialize to -1 (all bits set)
|
|
45
|
+
|
|
46
|
+
for byte in buffer:
|
|
47
|
+
crc ^= byte
|
|
48
|
+
for _ in range(8):
|
|
49
|
+
if crc & 1:
|
|
50
|
+
crc = (crc >> 1) ^ 0xEDB88320
|
|
51
|
+
else:
|
|
52
|
+
crc = crc >> 1
|
|
53
|
+
|
|
54
|
+
crc ^= 0xFFFFFFFF # Final XOR
|
|
55
|
+
|
|
56
|
+
# Convert to nibble format (4 bytes, little-endian)
|
|
57
|
+
for _ in range(4):
|
|
58
|
+
nibble_result = nibble(crc & 0xFF) + nibble_result
|
|
59
|
+
crc >>= 8
|
|
60
|
+
|
|
61
|
+
return nibble_result
|
xp/utils/dependencies.py
ADDED
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
"""Dependency injection container for XP services."""
|
|
2
|
+
|
|
3
|
+
import punq
|
|
4
|
+
from bubus import EventBus
|
|
5
|
+
from twisted.internet import asyncioreactor
|
|
6
|
+
from twisted.internet.interfaces import IConnector
|
|
7
|
+
from twisted.internet.posixbase import PosixReactorBase
|
|
8
|
+
|
|
9
|
+
from xp.models import ConbusClientConfig
|
|
10
|
+
from xp.models.homekit.homekit_config import HomekitConfig
|
|
11
|
+
from xp.models.homekit.homekit_conson_config import ConsonModuleListConfig
|
|
12
|
+
from xp.services.actiontable.actiontable_serializer import ActionTableSerializer
|
|
13
|
+
from xp.services.actiontable.msactiontable_serializer import MsActionTableSerializer
|
|
14
|
+
from xp.services.actiontable.msactiontable_xp20_serializer import (
|
|
15
|
+
Xp20MsActionTableSerializer,
|
|
16
|
+
)
|
|
17
|
+
from xp.services.actiontable.msactiontable_xp24_serializer import (
|
|
18
|
+
Xp24MsActionTableSerializer,
|
|
19
|
+
)
|
|
20
|
+
from xp.services.actiontable.msactiontable_xp33_serializer import (
|
|
21
|
+
Xp33MsActionTableSerializer,
|
|
22
|
+
)
|
|
23
|
+
from xp.services.conbus.actiontable.actiontable_download_service import (
|
|
24
|
+
ActionTableService,
|
|
25
|
+
)
|
|
26
|
+
from xp.services.conbus.actiontable.actiontable_list_service import (
|
|
27
|
+
ActionTableListService,
|
|
28
|
+
)
|
|
29
|
+
from xp.services.conbus.actiontable.actiontable_show_service import (
|
|
30
|
+
ActionTableShowService,
|
|
31
|
+
)
|
|
32
|
+
from xp.services.conbus.actiontable.actiontable_upload_service import (
|
|
33
|
+
ActionTableUploadService,
|
|
34
|
+
)
|
|
35
|
+
from xp.services.conbus.actiontable.msactiontable_service import MsActionTableService
|
|
36
|
+
from xp.services.conbus.conbus_blink_all_service import ConbusBlinkAllService
|
|
37
|
+
from xp.services.conbus.conbus_blink_service import ConbusBlinkService
|
|
38
|
+
from xp.services.conbus.conbus_custom_service import ConbusCustomService
|
|
39
|
+
from xp.services.conbus.conbus_datapoint_queryall_service import (
|
|
40
|
+
ConbusDatapointQueryAllService,
|
|
41
|
+
)
|
|
42
|
+
from xp.services.conbus.conbus_datapoint_service import (
|
|
43
|
+
ConbusDatapointService,
|
|
44
|
+
)
|
|
45
|
+
from xp.services.conbus.conbus_discover_service import ConbusDiscoverService
|
|
46
|
+
from xp.services.conbus.conbus_event_raw_service import ConbusEventRawService
|
|
47
|
+
from xp.services.conbus.conbus_output_service import ConbusOutputService
|
|
48
|
+
from xp.services.conbus.conbus_raw_service import ConbusRawService
|
|
49
|
+
from xp.services.conbus.conbus_receive_service import ConbusReceiveService
|
|
50
|
+
from xp.services.conbus.conbus_scan_service import ConbusScanService
|
|
51
|
+
from xp.services.conbus.write_config_service import WriteConfigService
|
|
52
|
+
from xp.services.homekit.homekit_cache_service import HomeKitCacheService
|
|
53
|
+
from xp.services.homekit.homekit_conbus_service import HomeKitConbusService
|
|
54
|
+
from xp.services.homekit.homekit_dimminglight_service import HomeKitDimmingLightService
|
|
55
|
+
from xp.services.homekit.homekit_hap_service import HomekitHapService
|
|
56
|
+
from xp.services.homekit.homekit_lightbulb_service import HomeKitLightbulbService
|
|
57
|
+
from xp.services.homekit.homekit_module_service import HomekitModuleService
|
|
58
|
+
from xp.services.homekit.homekit_outlet_service import HomeKitOutletService
|
|
59
|
+
from xp.services.homekit.homekit_service import HomeKitService
|
|
60
|
+
from xp.services.log_file_service import LogFileService
|
|
61
|
+
from xp.services.module_type_service import ModuleTypeService
|
|
62
|
+
from xp.services.protocol import ConbusEventProtocol
|
|
63
|
+
from xp.services.protocol.protocol_factory import TelegramFactory
|
|
64
|
+
from xp.services.protocol.telegram_protocol import TelegramProtocol
|
|
65
|
+
from xp.services.reverse_proxy_service import ReverseProxyService
|
|
66
|
+
from xp.services.server.device_service_factory import DeviceServiceFactory
|
|
67
|
+
from xp.services.server.server_service import ServerService
|
|
68
|
+
from xp.services.telegram.telegram_blink_service import TelegramBlinkService
|
|
69
|
+
from xp.services.telegram.telegram_datapoint_service import TelegramDatapointService
|
|
70
|
+
from xp.services.telegram.telegram_discover_service import TelegramDiscoverService
|
|
71
|
+
from xp.services.telegram.telegram_link_number_service import LinkNumberService
|
|
72
|
+
from xp.services.telegram.telegram_output_service import TelegramOutputService
|
|
73
|
+
from xp.services.telegram.telegram_service import TelegramService
|
|
74
|
+
|
|
75
|
+
asyncioreactor.install()
|
|
76
|
+
from twisted.internet import reactor # noqa: E402
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class ServiceContainer:
|
|
80
|
+
"""
|
|
81
|
+
Service container that manages dependency injection for all XP services.
|
|
82
|
+
|
|
83
|
+
Uses the service dependency graph from Dependencies.dot to properly
|
|
84
|
+
wire up all services with their dependencies.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
def __init__(
|
|
88
|
+
self,
|
|
89
|
+
config_path: str = "cli.yml",
|
|
90
|
+
homekit_config_path: str = "homekit.yml",
|
|
91
|
+
conson_config_path: str = "conson.yml",
|
|
92
|
+
server_port: int = 10001,
|
|
93
|
+
reverse_proxy_port: int = 10001,
|
|
94
|
+
):
|
|
95
|
+
"""
|
|
96
|
+
Initialize the service container.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
config_path: Path to the Conbus CLI configuration file
|
|
100
|
+
homekit_config_path: Path to the HomeKit configuration file
|
|
101
|
+
conson_config_path: Path to the Conson configuration file
|
|
102
|
+
server_port: Port for the server service
|
|
103
|
+
reverse_proxy_port: Port for the reverse proxy service
|
|
104
|
+
"""
|
|
105
|
+
self.container = punq.Container()
|
|
106
|
+
self._config_path = config_path
|
|
107
|
+
self._homekit_config_path = homekit_config_path
|
|
108
|
+
self._conson_config_path = conson_config_path
|
|
109
|
+
self._server_port = server_port
|
|
110
|
+
self._reverse_proxy_port = reverse_proxy_port
|
|
111
|
+
|
|
112
|
+
self._register_services()
|
|
113
|
+
|
|
114
|
+
def _register_services(self) -> None:
|
|
115
|
+
"""Register all services in the container based on dependency graph."""
|
|
116
|
+
# ConbusClientConfig
|
|
117
|
+
self.container.register(
|
|
118
|
+
ConbusClientConfig,
|
|
119
|
+
factory=lambda: ConbusClientConfig.from_yaml(self._config_path),
|
|
120
|
+
scope=punq.Scope.singleton,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Telegram services layer
|
|
124
|
+
self.container.register(TelegramService, scope=punq.Scope.singleton)
|
|
125
|
+
self.container.register(
|
|
126
|
+
TelegramOutputService,
|
|
127
|
+
factory=lambda: TelegramOutputService(
|
|
128
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
129
|
+
),
|
|
130
|
+
scope=punq.Scope.singleton,
|
|
131
|
+
)
|
|
132
|
+
self.container.register(TelegramDiscoverService, scope=punq.Scope.singleton)
|
|
133
|
+
self.container.register(TelegramBlinkService, scope=punq.Scope.singleton)
|
|
134
|
+
self.container.register(TelegramDatapointService, scope=punq.Scope.singleton)
|
|
135
|
+
self.container.register(LinkNumberService, scope=punq.Scope.singleton)
|
|
136
|
+
|
|
137
|
+
# Conbus services layer
|
|
138
|
+
self.container.register(
|
|
139
|
+
ConbusDatapointService,
|
|
140
|
+
factory=lambda: ConbusDatapointService(
|
|
141
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
142
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
143
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
144
|
+
),
|
|
145
|
+
scope=punq.Scope.singleton,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
self.container.register(
|
|
149
|
+
ConbusDatapointQueryAllService,
|
|
150
|
+
factory=lambda: ConbusDatapointQueryAllService(
|
|
151
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
152
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
153
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
154
|
+
),
|
|
155
|
+
scope=punq.Scope.singleton,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
self.container.register(
|
|
159
|
+
ConbusScanService,
|
|
160
|
+
factory=lambda: ConbusScanService(
|
|
161
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
162
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
163
|
+
),
|
|
164
|
+
scope=punq.Scope.singleton,
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
self.container.register(
|
|
168
|
+
ConbusEventProtocol,
|
|
169
|
+
factory=lambda: ConbusEventProtocol(
|
|
170
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
171
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
172
|
+
),
|
|
173
|
+
scope=punq.Scope.singleton,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
self.container.register(
|
|
177
|
+
ConbusDiscoverService,
|
|
178
|
+
factory=lambda: ConbusDiscoverService(
|
|
179
|
+
conbus_protocol=self.container.resolve(ConbusEventProtocol)
|
|
180
|
+
),
|
|
181
|
+
scope=punq.Scope.singleton,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
self.container.register(
|
|
185
|
+
ConbusEventRawService,
|
|
186
|
+
factory=lambda: ConbusEventRawService(
|
|
187
|
+
conbus_protocol=self.container.resolve(ConbusEventProtocol)
|
|
188
|
+
),
|
|
189
|
+
scope=punq.Scope.singleton,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
self.container.register(
|
|
193
|
+
ConbusBlinkService,
|
|
194
|
+
factory=lambda: ConbusBlinkService(
|
|
195
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
196
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
197
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
198
|
+
),
|
|
199
|
+
scope=punq.Scope.singleton,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
self.container.register(
|
|
203
|
+
ConbusBlinkAllService,
|
|
204
|
+
factory=lambda: ConbusBlinkAllService(
|
|
205
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
206
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
207
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
208
|
+
),
|
|
209
|
+
scope=punq.Scope.singleton,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
self.container.register(
|
|
213
|
+
ConbusOutputService,
|
|
214
|
+
factory=lambda: ConbusOutputService(
|
|
215
|
+
telegram_output_service=self.container.resolve(TelegramOutputService),
|
|
216
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
217
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
218
|
+
),
|
|
219
|
+
scope=punq.Scope.singleton,
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
self.container.register(
|
|
223
|
+
WriteConfigService,
|
|
224
|
+
factory=lambda: WriteConfigService(
|
|
225
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
226
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
227
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
228
|
+
),
|
|
229
|
+
scope=punq.Scope.singleton,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
self.container.register(
|
|
233
|
+
ActionTableSerializer,
|
|
234
|
+
factory=lambda: ActionTableSerializer,
|
|
235
|
+
scope=punq.Scope.singleton,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
self.container.register(
|
|
239
|
+
ActionTableService,
|
|
240
|
+
factory=lambda: ActionTableService(
|
|
241
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
242
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
243
|
+
actiontable_serializer=self.container.resolve(ActionTableSerializer),
|
|
244
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
245
|
+
),
|
|
246
|
+
scope=punq.Scope.singleton,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
self.container.register(
|
|
250
|
+
ActionTableUploadService,
|
|
251
|
+
factory=lambda: ActionTableUploadService(
|
|
252
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
253
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
254
|
+
actiontable_serializer=self.container.resolve(ActionTableSerializer),
|
|
255
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
256
|
+
conson_config=self.container.resolve(ConsonModuleListConfig),
|
|
257
|
+
),
|
|
258
|
+
scope=punq.Scope.singleton,
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
self.container.register(
|
|
262
|
+
ActionTableListService,
|
|
263
|
+
factory=ActionTableListService,
|
|
264
|
+
scope=punq.Scope.singleton,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
self.container.register(
|
|
268
|
+
ActionTableShowService,
|
|
269
|
+
factory=ActionTableShowService,
|
|
270
|
+
scope=punq.Scope.singleton,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
self.container.register(
|
|
274
|
+
Xp20MsActionTableSerializer,
|
|
275
|
+
factory=lambda: Xp20MsActionTableSerializer,
|
|
276
|
+
scope=punq.Scope.singleton,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
self.container.register(
|
|
280
|
+
Xp24MsActionTableSerializer,
|
|
281
|
+
factory=lambda: Xp24MsActionTableSerializer,
|
|
282
|
+
scope=punq.Scope.singleton,
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
self.container.register(
|
|
286
|
+
Xp33MsActionTableSerializer,
|
|
287
|
+
factory=lambda: Xp33MsActionTableSerializer,
|
|
288
|
+
scope=punq.Scope.singleton,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
self.container.register(
|
|
292
|
+
MsActionTableService,
|
|
293
|
+
factory=lambda: MsActionTableService(
|
|
294
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
295
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
296
|
+
xp20ms_serializer=self.container.resolve(Xp20MsActionTableSerializer),
|
|
297
|
+
xp24ms_serializer=self.container.resolve(Xp24MsActionTableSerializer),
|
|
298
|
+
xp33ms_serializer=self.container.resolve(Xp33MsActionTableSerializer),
|
|
299
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
300
|
+
),
|
|
301
|
+
scope=punq.Scope.singleton,
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
self.container.register(
|
|
305
|
+
ConbusCustomService,
|
|
306
|
+
factory=lambda: ConbusCustomService(
|
|
307
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
308
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
309
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
310
|
+
),
|
|
311
|
+
scope=punq.Scope.singleton,
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
self.container.register(
|
|
315
|
+
ConbusRawService,
|
|
316
|
+
factory=lambda: ConbusRawService(
|
|
317
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
318
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
319
|
+
),
|
|
320
|
+
scope=punq.Scope.singleton,
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
self.container.register(
|
|
324
|
+
ConbusReceiveService,
|
|
325
|
+
factory=lambda: ConbusReceiveService(
|
|
326
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
327
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
328
|
+
),
|
|
329
|
+
scope=punq.Scope.singleton,
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
# HomeKit conson config
|
|
333
|
+
self.container.register(
|
|
334
|
+
ConsonModuleListConfig,
|
|
335
|
+
factory=lambda: ConsonModuleListConfig.from_yaml(self._conson_config_path),
|
|
336
|
+
scope=punq.Scope.singleton,
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
# HomeKit services layer
|
|
340
|
+
self.container.register(
|
|
341
|
+
HomekitModuleService,
|
|
342
|
+
factory=lambda: HomekitModuleService(
|
|
343
|
+
conson_modules_config=self.container.resolve(ConsonModuleListConfig),
|
|
344
|
+
),
|
|
345
|
+
scope=punq.Scope.singleton,
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
# Create event bus
|
|
349
|
+
self.container.register(
|
|
350
|
+
EventBus,
|
|
351
|
+
factory=lambda: EventBus(max_history_size=500),
|
|
352
|
+
scope=punq.Scope.singleton,
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
# HomeKit conson config
|
|
356
|
+
self.container.register(
|
|
357
|
+
HomekitConfig,
|
|
358
|
+
factory=lambda: HomekitConfig.from_yaml(self._homekit_config_path),
|
|
359
|
+
scope=punq.Scope.singleton,
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
self.container.register(
|
|
363
|
+
HomekitHapService,
|
|
364
|
+
factory=lambda: HomekitHapService(
|
|
365
|
+
homekit_config=self.container.resolve(HomekitConfig),
|
|
366
|
+
module_service=self.container.resolve(HomekitModuleService),
|
|
367
|
+
event_bus=self.container.resolve(EventBus),
|
|
368
|
+
),
|
|
369
|
+
scope=punq.Scope.singleton,
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
# Log file services layer
|
|
373
|
+
self.container.register(
|
|
374
|
+
LogFileService,
|
|
375
|
+
factory=lambda: LogFileService(
|
|
376
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
377
|
+
),
|
|
378
|
+
scope=punq.Scope.singleton,
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
# Module type services layer
|
|
382
|
+
self.container.register(ModuleTypeService, scope=punq.Scope.singleton)
|
|
383
|
+
|
|
384
|
+
# MsActionTable serializers
|
|
385
|
+
self.container.register(MsActionTableSerializer, scope=punq.Scope.singleton)
|
|
386
|
+
self.container.register(Xp20MsActionTableSerializer, scope=punq.Scope.singleton)
|
|
387
|
+
self.container.register(Xp24MsActionTableSerializer, scope=punq.Scope.singleton)
|
|
388
|
+
self.container.register(Xp33MsActionTableSerializer, scope=punq.Scope.singleton)
|
|
389
|
+
|
|
390
|
+
# Device service factory
|
|
391
|
+
self.container.register(
|
|
392
|
+
DeviceServiceFactory,
|
|
393
|
+
factory=lambda: DeviceServiceFactory(
|
|
394
|
+
xp20ms_serializer=self.container.resolve(Xp20MsActionTableSerializer),
|
|
395
|
+
xp24ms_serializer=self.container.resolve(Xp24MsActionTableSerializer),
|
|
396
|
+
xp33ms_serializer=self.container.resolve(Xp33MsActionTableSerializer),
|
|
397
|
+
ms_serializer=self.container.resolve(MsActionTableSerializer),
|
|
398
|
+
),
|
|
399
|
+
scope=punq.Scope.singleton,
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
# Server services layer
|
|
403
|
+
self.container.register(
|
|
404
|
+
ServerService,
|
|
405
|
+
factory=lambda: ServerService(
|
|
406
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
407
|
+
discover_service=self.container.resolve(TelegramDiscoverService),
|
|
408
|
+
device_factory=self.container.resolve(DeviceServiceFactory),
|
|
409
|
+
config_path="server.yml",
|
|
410
|
+
port=self._server_port,
|
|
411
|
+
),
|
|
412
|
+
scope=punq.Scope.singleton,
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
# Other services
|
|
416
|
+
self.container.register(
|
|
417
|
+
ReverseProxyService,
|
|
418
|
+
factory=lambda: ReverseProxyService(
|
|
419
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
420
|
+
listen_port=self._reverse_proxy_port,
|
|
421
|
+
),
|
|
422
|
+
scope=punq.Scope.singleton,
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
# Create protocol with built-in debouncing
|
|
426
|
+
self.container.register(
|
|
427
|
+
TelegramProtocol,
|
|
428
|
+
factory=lambda: TelegramProtocol(
|
|
429
|
+
event_bus=self.container.resolve(EventBus),
|
|
430
|
+
debounce_ms=50,
|
|
431
|
+
),
|
|
432
|
+
scope=punq.Scope.singleton,
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
self.container.register(
|
|
436
|
+
IConnector,
|
|
437
|
+
factory=lambda: reactor,
|
|
438
|
+
scope=punq.Scope.singleton,
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
self.container.register(
|
|
442
|
+
TelegramFactory,
|
|
443
|
+
factory=lambda: TelegramFactory(
|
|
444
|
+
event_bus=self.container.resolve(EventBus),
|
|
445
|
+
telegram_protocol=self.container.resolve(TelegramProtocol),
|
|
446
|
+
connector=self.container.resolve(IConnector),
|
|
447
|
+
),
|
|
448
|
+
scope=punq.Scope.singleton,
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
self.container.register(
|
|
452
|
+
PosixReactorBase,
|
|
453
|
+
factory=lambda: reactor,
|
|
454
|
+
scope=punq.Scope.singleton,
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
self.container.register(
|
|
458
|
+
HomeKitLightbulbService,
|
|
459
|
+
factory=lambda: HomeKitLightbulbService(
|
|
460
|
+
event_bus=self.container.resolve(EventBus),
|
|
461
|
+
),
|
|
462
|
+
scope=punq.Scope.singleton,
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
self.container.register(
|
|
466
|
+
HomeKitOutletService,
|
|
467
|
+
factory=lambda: HomeKitOutletService(
|
|
468
|
+
event_bus=self.container.resolve(EventBus),
|
|
469
|
+
),
|
|
470
|
+
scope=punq.Scope.singleton,
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
self.container.register(
|
|
474
|
+
HomeKitDimmingLightService,
|
|
475
|
+
factory=lambda: HomeKitDimmingLightService(
|
|
476
|
+
event_bus=self.container.resolve(EventBus),
|
|
477
|
+
),
|
|
478
|
+
scope=punq.Scope.singleton,
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
# Cache service must be registered BEFORE HomeKitConbusService
|
|
482
|
+
# so it intercepts ReadDatapointEvent first
|
|
483
|
+
self.container.register(
|
|
484
|
+
HomeKitCacheService,
|
|
485
|
+
factory=lambda: HomeKitCacheService(
|
|
486
|
+
event_bus=self.container.resolve(EventBus),
|
|
487
|
+
),
|
|
488
|
+
scope=punq.Scope.singleton,
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
self.container.register(
|
|
492
|
+
HomeKitConbusService,
|
|
493
|
+
factory=lambda: HomeKitConbusService(
|
|
494
|
+
event_bus=self.container.resolve(EventBus),
|
|
495
|
+
telegram_protocol=self.container.resolve(TelegramProtocol),
|
|
496
|
+
),
|
|
497
|
+
scope=punq.Scope.singleton,
|
|
498
|
+
)
|
|
499
|
+
|
|
500
|
+
self.container.register(
|
|
501
|
+
TelegramService,
|
|
502
|
+
factory=TelegramService,
|
|
503
|
+
scope=punq.Scope.singleton,
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
self.container.register(
|
|
507
|
+
HomeKitService,
|
|
508
|
+
factory=lambda: HomeKitService(
|
|
509
|
+
cli_config=self.container.resolve(ConbusClientConfig),
|
|
510
|
+
event_bus=self.container.resolve(EventBus),
|
|
511
|
+
telegram_factory=self.container.resolve(TelegramFactory),
|
|
512
|
+
reactor=self.container.resolve(PosixReactorBase),
|
|
513
|
+
lightbulb_service=self.container.resolve(HomeKitLightbulbService),
|
|
514
|
+
outlet_service=self.container.resolve(HomeKitOutletService),
|
|
515
|
+
dimminglight_service=self.container.resolve(HomeKitDimmingLightService),
|
|
516
|
+
cache_service=self.container.resolve(HomeKitCacheService),
|
|
517
|
+
conbus_service=self.container.resolve(HomeKitConbusService),
|
|
518
|
+
module_factory=self.container.resolve(HomekitHapService),
|
|
519
|
+
telegram_service=self.container.resolve(TelegramService),
|
|
520
|
+
),
|
|
521
|
+
scope=punq.Scope.singleton,
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
def get_container(self) -> punq.Container:
|
|
525
|
+
"""
|
|
526
|
+
Get the configured container with all services registered.
|
|
527
|
+
|
|
528
|
+
Returns:
|
|
529
|
+
punq.Container: The configured dependency injection container
|
|
530
|
+
"""
|
|
531
|
+
return self.container
|
xp/utils/event_helper.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Event handling utilities for PyDispatcher integration.
|
|
2
|
+
|
|
3
|
+
This module provides clean, reusable utilities for handling PyDispatcher
|
|
4
|
+
responses across all HomeKit accessory classes.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Callable, List, Tuple
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_first_response(
|
|
11
|
+
responses: List[Tuple[Callable, Any]], default: Any = None
|
|
12
|
+
) -> Any:
|
|
13
|
+
"""Extract the first non-None response from PyDispatcher responses.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
responses: List of (receiver_function, return_value) tuples from dispatcher.send()
|
|
17
|
+
default: Value to return if no valid responses found
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
First non-None response value, or default if none found
|
|
21
|
+
|
|
22
|
+
Examples:
|
|
23
|
+
>>> responses = [(<func1>, None), (<func2>, True), (<func3>, False)]
|
|
24
|
+
>>> get_first_response(responses)
|
|
25
|
+
True
|
|
26
|
+
|
|
27
|
+
>>> responses = [(<func1>, None), (<func2>, None)]
|
|
28
|
+
>>> get_first_response(responses, default=False)
|
|
29
|
+
False
|
|
30
|
+
"""
|
|
31
|
+
return next((r[1] for r in responses if r[1] is not None), default)
|