conson-xp 1.2.0__py3-none-any.whl → 1.4.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 (62) hide show
  1. {conson_xp-1.2.0.dist-info → conson_xp-1.4.0.dist-info}/METADATA +1 -5
  2. {conson_xp-1.2.0.dist-info → conson_xp-1.4.0.dist-info}/RECORD +43 -60
  3. xp/__init__.py +1 -1
  4. xp/cli/commands/__init__.py +0 -2
  5. xp/cli/commands/conbus/conbus_actiontable_commands.py +5 -3
  6. xp/cli/commands/conbus/conbus_autoreport_commands.py +39 -21
  7. xp/cli/commands/conbus/conbus_blink_commands.py +8 -8
  8. xp/cli/commands/conbus/conbus_config_commands.py +3 -1
  9. xp/cli/commands/conbus/conbus_custom_commands.py +3 -1
  10. xp/cli/commands/conbus/conbus_datapoint_commands.py +4 -2
  11. xp/cli/commands/conbus/conbus_discover_commands.py +5 -3
  12. xp/cli/commands/conbus/conbus_lightlevel_commands.py +68 -32
  13. xp/cli/commands/conbus/conbus_linknumber_commands.py +32 -17
  14. xp/cli/commands/conbus/conbus_msactiontable_commands.py +11 -4
  15. xp/cli/commands/conbus/conbus_output_commands.py +6 -2
  16. xp/cli/commands/conbus/conbus_receive_commands.py +5 -3
  17. xp/cli/commands/file_commands.py +9 -3
  18. xp/cli/commands/homekit/homekit_start_commands.py +3 -1
  19. xp/cli/commands/module_commands.py +12 -4
  20. xp/cli/commands/reverse_proxy_commands.py +3 -1
  21. xp/cli/main.py +0 -2
  22. xp/models/conbus/conbus_datapoint.py +3 -0
  23. xp/models/conbus/conbus_discover.py +19 -3
  24. xp/models/conbus/conbus_writeconfig.py +60 -0
  25. xp/models/telegram/system_telegram.py +4 -4
  26. xp/services/conbus/conbus_datapoint_service.py +9 -6
  27. xp/services/conbus/conbus_discover_service.py +120 -2
  28. xp/services/conbus/conbus_scan_service.py +1 -1
  29. xp/services/conbus/{conbus_linknumber_set_service.py → write_config_service.py} +78 -66
  30. xp/services/protocol/telegram_protocol.py +4 -4
  31. xp/services/server/base_server_service.py +9 -4
  32. xp/services/server/cp20_server_service.py +2 -1
  33. xp/services/server/server_service.py +75 -4
  34. xp/services/server/xp130_server_service.py +2 -1
  35. xp/services/server/xp20_server_service.py +2 -1
  36. xp/services/server/xp230_server_service.py +2 -1
  37. xp/services/server/xp24_server_service.py +123 -50
  38. xp/services/server/xp33_server_service.py +150 -20
  39. xp/services/telegram/telegram_datapoint_service.py +70 -0
  40. xp/utils/dependencies.py +4 -46
  41. xp/api/__init__.py +0 -1
  42. xp/api/main.py +0 -125
  43. xp/api/models/__init__.py +0 -1
  44. xp/api/models/api.py +0 -31
  45. xp/api/models/discover.py +0 -31
  46. xp/api/routers/__init__.py +0 -17
  47. xp/api/routers/conbus.py +0 -5
  48. xp/api/routers/conbus_blink.py +0 -117
  49. xp/api/routers/conbus_custom.py +0 -71
  50. xp/api/routers/conbus_datapoint.py +0 -74
  51. xp/api/routers/conbus_output.py +0 -167
  52. xp/api/routers/errors.py +0 -38
  53. xp/cli/commands/api.py +0 -12
  54. xp/cli/commands/api_start_commands.py +0 -132
  55. xp/services/conbus/conbus_autoreport_get_service.py +0 -94
  56. xp/services/conbus/conbus_autoreport_set_service.py +0 -141
  57. xp/services/conbus/conbus_lightlevel_get_service.py +0 -109
  58. xp/services/conbus/conbus_lightlevel_set_service.py +0 -225
  59. xp/services/conbus/conbus_linknumber_get_service.py +0 -94
  60. {conson_xp-1.2.0.dist-info → conson_xp-1.4.0.dist-info}/WHEEL +0 -0
  61. {conson_xp-1.2.0.dist-info → conson_xp-1.4.0.dist-info}/entry_points.txt +0 -0
  62. {conson_xp-1.2.0.dist-info → conson_xp-1.4.0.dist-info}/licenses/LICENSE +0 -0
xp/cli/commands/api.py DELETED
@@ -1,12 +0,0 @@
1
- """API server management CLI commands."""
2
-
3
- import click
4
- from click_help_colors import HelpColorsGroup
5
-
6
-
7
- @click.group(
8
- cls=HelpColorsGroup, help_headers_color="yellow", help_options_color="green"
9
- )
10
- def api() -> None:
11
- """Manage the FastAPI server for XP Protocol operations."""
12
- pass
@@ -1,132 +0,0 @@
1
- """API server start command."""
2
-
3
- import sys
4
-
5
- import click
6
- import uvicorn
7
-
8
- from xp.api.main import create_app
9
- from xp.cli.commands.api import api
10
-
11
-
12
- @api.command("start")
13
- @click.option(
14
- "--host",
15
- default="127.0.0.1",
16
- help="Host to bind the server to (default: 127.0.0.1)",
17
- show_default=True,
18
- )
19
- @click.option(
20
- "--port",
21
- default=8000,
22
- type=int,
23
- help="Port to bind the server to (default: 8000)",
24
- show_default=True,
25
- )
26
- @click.option(
27
- "--reload",
28
- is_flag=True,
29
- default=True,
30
- help="Enable auto-reload for development",
31
- )
32
- @click.option(
33
- "--workers",
34
- default=1,
35
- type=int,
36
- help="Number of worker processes (default: 1)",
37
- show_default=True,
38
- )
39
- @click.option(
40
- "--log-level",
41
- default="info",
42
- type=click.Choice(["critical", "error", "warning", "info", "debug", "trace"]),
43
- help="Log level (default: info)",
44
- show_default=True,
45
- )
46
- @click.option(
47
- "--access-log/--no-access-log",
48
- default=True,
49
- help="Enable/disable access log (default: enabled)",
50
- )
51
- @click.pass_context
52
- def start_api_server(
53
- context: click.Context,
54
- host: str,
55
- port: int,
56
- reload: bool,
57
- workers: int,
58
- log_level: str,
59
- access_log: bool,
60
- ) -> None:
61
- r"""Start the FastAPI server.
62
-
63
- This command starts the XP Protocol FastAPI server using uvicorn.
64
- The server provides REST API endpoints for Conbus operations.
65
-
66
- Args:
67
- context: Click context object.
68
- host: Host to bind the server to.
69
- port: Port to bind the server to.
70
- reload: Enable auto-reload for development.
71
- workers: Number of worker processes.
72
- log_level: Log level for the server.
73
- access_log: Enable/disable access log.
74
-
75
- Examples:
76
- \b
77
- # Start server on default host and port
78
- xp api start
79
-
80
- \b
81
- # Start server on specific host and port
82
- xp api start --host 0.0.0.0 --port 8080
83
-
84
- \b
85
- # Start development server with auto-reload
86
- xp api start --reload
87
-
88
- \b
89
- # Start production server with multiple workers
90
- xp api start --host 0.0.0.0 --workers 4 --no-access-log
91
- """
92
- # Validate workers and reload options
93
- if reload and workers > 1:
94
- click.echo(
95
- click.style(
96
- "Warning: Auto-reload is enabled. Setting workers to 1.",
97
- fg="yellow",
98
- )
99
- )
100
- workers = 1
101
-
102
- click.echo("Starting XP Protocol API server...")
103
- click.echo(f"Server will be available at: https://{host}:{port}")
104
- click.echo(f"API documentation at: https://{host}:{port}/docs")
105
- click.echo(f"Health check at: https://{host}:{port}/health")
106
-
107
- if reload:
108
- click.echo(click.style("Development mode: Auto-reload enabled", fg="green"))
109
-
110
- # Get container from CLI context or create new one
111
- container = context.obj.get("container")
112
-
113
- try:
114
- # For production mode, create app instance with container
115
- app = create_app(container)
116
- uvicorn.run(
117
- app,
118
- host=host,
119
- port=port,
120
- reload=reload,
121
- workers=workers,
122
- log_level=log_level,
123
- access_log=access_log,
124
- )
125
- except KeyboardInterrupt:
126
- click.echo("\nShutting down server...")
127
- except Exception as e:
128
- click.echo(
129
- click.style(f"Error starting server: {e}", fg="red"),
130
- err=True,
131
- )
132
- sys.exit(1)
@@ -1,94 +0,0 @@
1
- """Conbus Auto Report Service for getting and setting module auto report status.
2
-
3
- This service handles auto report status operations for modules through Conbus telegrams.
4
- """
5
-
6
- import logging
7
- from typing import Callable, Optional
8
-
9
- from twisted.internet.posixbase import PosixReactorBase
10
-
11
- from xp.models import ConbusClientConfig, ConbusDatapointResponse
12
- from xp.models.conbus.conbus_autoreport import ConbusAutoreportResponse
13
- from xp.models.telegram.datapoint_type import DataPointType
14
- from xp.services.conbus.conbus_datapoint_service import ConbusDatapointService
15
- from xp.services.telegram.telegram_service import TelegramService
16
-
17
-
18
- class ConbusAutoreportGetService(ConbusDatapointService):
19
- """
20
- Service for getting auto report status from Conbus modules.
21
-
22
- Uses ConbusProtocol to provide auto report status query functionality
23
- for reading the current auto report configuration from modules.
24
- """
25
-
26
- def __init__(
27
- self,
28
- telegram_service: TelegramService,
29
- cli_config: ConbusClientConfig,
30
- reactor: PosixReactorBase,
31
- ) -> None:
32
- """Initialize the Conbus autoreport get service.
33
-
34
- Args:
35
- telegram_service: Telegram service for parsing.
36
- cli_config: Conbus client configuration.
37
- reactor: Twisted reactor instance.
38
- """
39
- super().__init__(telegram_service, cli_config, reactor)
40
- self.service_callback: Optional[Callable[[ConbusAutoreportResponse], None]] = (
41
- None
42
- )
43
-
44
- # Set up logging
45
- self.logger = logging.getLogger(__name__)
46
-
47
- def finish_service_callback(
48
- self, datapoint_response: ConbusDatapointResponse
49
- ) -> None:
50
- """Handle finished service callback.
51
-
52
- Args:
53
- datapoint_response: Datapoint response from service.
54
- """
55
- self.logger.debug("Parsing datapoint response")
56
- autoreport_status = ""
57
- if datapoint_response.success and datapoint_response.datapoint_telegram:
58
- autoreport_status = datapoint_response.datapoint_telegram.data_value
59
-
60
- service_response = ConbusAutoreportResponse(
61
- success=datapoint_response.success,
62
- serial_number=self.serial_number,
63
- auto_report_status=autoreport_status,
64
- error=datapoint_response.error,
65
- sent_telegram=datapoint_response.sent_telegram,
66
- received_telegrams=datapoint_response.received_telegrams,
67
- timestamp=datapoint_response.timestamp,
68
- )
69
-
70
- if self.service_callback:
71
- self.service_callback(service_response)
72
-
73
- def get_autoreport_status(
74
- self,
75
- serial_number: str,
76
- finish_callback: Callable[[ConbusAutoreportResponse], None],
77
- timeout_seconds: Optional[float] = None,
78
- ) -> None:
79
- """
80
- Get the current auto report status for a specific module.
81
-
82
- Args:
83
- serial_number: 10-digit module serial number
84
- finish_callback: callback function to call when the auto report status is received
85
- timeout_seconds: timeout in seconds
86
- """
87
- self.logger.info("Starting get_autoreport_status")
88
- if timeout_seconds:
89
- self.timeout_seconds = timeout_seconds
90
- self.serial_number = serial_number
91
- self.datapoint_type = DataPointType.AUTO_REPORT_STATUS
92
- self.finish_callback = self.finish_service_callback
93
- self.service_callback = finish_callback
94
- self.start_reactor()
@@ -1,141 +0,0 @@
1
- """Conbus Auto Report Service for getting and setting module auto report status.
2
-
3
- This service handles auto report status operations for modules through Conbus telegrams.
4
- """
5
-
6
- import logging
7
- from datetime import datetime
8
- from typing import Callable, Optional
9
-
10
- from twisted.internet.posixbase import PosixReactorBase
11
-
12
- from xp.models import ConbusClientConfig
13
- from xp.models.conbus.conbus_autoreport import ConbusAutoreportResponse
14
- from xp.models.protocol.conbus_protocol import TelegramReceivedEvent
15
- from xp.models.telegram.datapoint_type import DataPointType
16
- from xp.models.telegram.system_function import SystemFunction
17
- from xp.models.telegram.telegram_type import TelegramType
18
- from xp.services.protocol import ConbusProtocol
19
-
20
-
21
- class ConbusAutoreportSetService(ConbusProtocol):
22
- """
23
- Service for setting auto report status on Conbus modules.
24
-
25
- Uses ConbusProtocol to provide auto report configuration functionality
26
- for enabling/disabling automatic reporting on modules.
27
- """
28
-
29
- def __init__(
30
- self,
31
- cli_config: ConbusClientConfig,
32
- reactor: PosixReactorBase,
33
- ) -> None:
34
- """Initialize the Conbus autoreport set service.
35
-
36
- Args:
37
- cli_config: Conbus client configuration.
38
- reactor: Twisted reactor instance.
39
- """
40
- super().__init__(cli_config, reactor)
41
- self.serial_number: str = ""
42
- self.status: bool = False
43
- self.finish_callback: Optional[Callable[[ConbusAutoreportResponse], None]] = (
44
- None
45
- )
46
- self.service_response: ConbusAutoreportResponse = ConbusAutoreportResponse(
47
- success=False,
48
- serial_number=self.serial_number,
49
- )
50
-
51
- # Set up logging
52
- self.logger = logging.getLogger(__name__)
53
-
54
- def connection_established(self) -> None:
55
- """Handle connection established event."""
56
- # Convert boolean to appropriate value
57
- status_value = "PP" if self.status else "AA"
58
- status_text = "on" if self.status else "off"
59
-
60
- self.logger.debug("Connection established, set autoreport to %s", status_text)
61
- self.send_telegram(
62
- telegram_type=TelegramType.SYSTEM,
63
- serial_number=self.serial_number,
64
- system_function=SystemFunction.WRITE_CONFIG,
65
- data_value=f"{DataPointType.AUTO_REPORT_STATUS.value}{status_value}",
66
- )
67
-
68
- def telegram_sent(self, telegram_sent: str) -> None:
69
- """Handle telegram sent event.
70
-
71
- Args:
72
- telegram_sent: The telegram that was sent.
73
- """
74
- self.logger.debug("Autoreport reply telegram sent %s", telegram_sent)
75
- self.service_response.sent_telegram = telegram_sent
76
-
77
- def telegram_received(self, telegram_received: TelegramReceivedEvent) -> None:
78
- """Handle telegram received event.
79
-
80
- Args:
81
- telegram_received: The telegram received event.
82
- """
83
- self.logger.debug(f"Telegram received: {telegram_received}")
84
- if not self.service_response.received_telegrams:
85
- self.service_response.received_telegrams = []
86
- self.service_response.received_telegrams.append(telegram_received.frame)
87
-
88
- if not (
89
- telegram_received.checksum_valid
90
- and telegram_received.telegram_type == TelegramType.REPLY
91
- and telegram_received.serial_number == self.serial_number
92
- and telegram_received.system_function
93
- in (SystemFunction.ACK, SystemFunction.NAK)
94
- ):
95
- self.logger.debug(f"Not a reply telegram received: {telegram_received}")
96
- return
97
-
98
- self.service_response.success = True
99
- self.service_response.timestamp = datetime.now()
100
- self.service_response.result = telegram_received.system_function.name
101
- self.service_response.auto_report_status = "on" if self.status else "off"
102
-
103
- self.logger.debug("Received autoreport reply telegram")
104
- if self.finish_callback:
105
- self.finish_callback(self.service_response)
106
-
107
- def failed(self, message: str) -> None:
108
- """Handle failed connection event.
109
-
110
- Args:
111
- message: Failure message.
112
- """
113
- self.logger.debug(f"Failed with message: {message}")
114
- self.service_response.success = False
115
- self.service_response.error = message
116
- self.service_response.timestamp = datetime.now()
117
- if self.finish_callback:
118
- self.finish_callback(self.service_response)
119
-
120
- def set_autoreport_status(
121
- self,
122
- serial_number: str,
123
- status: bool,
124
- finish_callback: Callable[[ConbusAutoreportResponse], None],
125
- timeout_seconds: Optional[float] = None,
126
- ) -> None:
127
- """Set the auto report status for a specific module.
128
-
129
- Args:
130
- serial_number: 10-digit module serial number.
131
- status: True for ON, False for OFF.
132
- finish_callback: Callback function to call when operation completes.
133
- timeout_seconds: Timeout in seconds.
134
- """
135
- self.logger.info("Starting set_autoreport_status")
136
- if timeout_seconds:
137
- self.timeout_seconds = timeout_seconds
138
- self.finish_callback = finish_callback
139
- self.serial_number = serial_number
140
- self.status = status
141
- self.start_reactor()
@@ -1,109 +0,0 @@
1
- """Conbus Lightlevel Get Service for getting module light levels.
2
-
3
- This service handles light level query operations for modules through Conbus telegrams.
4
- """
5
-
6
- import logging
7
- from datetime import datetime
8
- from typing import Callable, Optional
9
-
10
- from twisted.internet.posixbase import PosixReactorBase
11
-
12
- from xp.models import ConbusClientConfig, ConbusDatapointResponse
13
- from xp.models.conbus.conbus_lightlevel import ConbusLightlevelResponse
14
- from xp.models.telegram.datapoint_type import DataPointType
15
- from xp.services.conbus.conbus_datapoint_service import ConbusDatapointService
16
- from xp.services.telegram.telegram_service import TelegramService
17
-
18
-
19
- class ConbusLightlevelGetService(ConbusDatapointService):
20
- """
21
- Service for getting light levels from Conbus modules.
22
-
23
- Uses ConbusProtocol to provide light level query functionality
24
- for reading the current light level configuration from module outputs.
25
- """
26
-
27
- def __init__(
28
- self,
29
- telegram_service: TelegramService,
30
- cli_config: ConbusClientConfig,
31
- reactor: PosixReactorBase,
32
- ) -> None:
33
- """Initialize the Conbus lightlevel get service.
34
-
35
- Args:
36
- telegram_service: Service for parsing telegrams.
37
- cli_config: Configuration for Conbus client connection.
38
- reactor: Twisted reactor for event loop.
39
- """
40
- super().__init__(telegram_service, cli_config, reactor)
41
- self.output_number: int = 0
42
- self.service_callback: Optional[Callable[[ConbusLightlevelResponse], None]] = (
43
- None
44
- )
45
-
46
- # Set up logging
47
- self.logger = logging.getLogger(__name__)
48
-
49
- def finish_service_callback(
50
- self, datapoint_response: ConbusDatapointResponse
51
- ) -> None:
52
- """Process datapoint response and extract light level.
53
-
54
- Args:
55
- datapoint_response: The datapoint response from the module.
56
- """
57
- self.logger.debug("Parsing datapoint response")
58
-
59
- level = 0
60
- if datapoint_response.success and datapoint_response.datapoint_telegram:
61
- for output_data in datapoint_response.datapoint_telegram.data_value.split(
62
- ","
63
- ):
64
- if ":" in output_data:
65
- output_str, level_str = output_data.split(":")
66
- if int(output_str) == self.output_number:
67
- level_str = level_str.replace("[%]", "")
68
- level = int(level_str)
69
- break
70
-
71
- service_response = ConbusLightlevelResponse(
72
- success=datapoint_response.success,
73
- serial_number=self.serial_number,
74
- output_number=self.output_number,
75
- level=level,
76
- error=datapoint_response.error,
77
- sent_telegram=datapoint_response.sent_telegram,
78
- received_telegrams=datapoint_response.received_telegrams,
79
- timestamp=datetime.now(),
80
- )
81
-
82
- if self.service_callback:
83
- self.service_callback(service_response)
84
-
85
- def get_light_level(
86
- self,
87
- serial_number: str,
88
- output_number: int,
89
- finish_callback: Callable[[ConbusLightlevelResponse], None],
90
- timeout_seconds: Optional[float] = None,
91
- ) -> None:
92
- """Get the current light level for a specific module output.
93
-
94
- Args:
95
- serial_number: 10-digit module serial number.
96
- output_number: Output module number.
97
- finish_callback: Callback function to call when the light level is received.
98
- timeout_seconds: Timeout in seconds.
99
- """
100
- self.logger.info("Starting get_light_level")
101
- if timeout_seconds:
102
- self.timeout_seconds = timeout_seconds
103
- self.serial_number = serial_number
104
- self.output_number = output_number
105
- self.datapoint_type = DataPointType.MODULE_LIGHT_LEVEL
106
-
107
- self.finish_callback = self.finish_service_callback
108
- self.service_callback = finish_callback
109
- self.start_reactor()