Skip to content

Commit 8cb16f2

Browse files
authored
Raise InvalidServerVersion when Server is too old too (home-assistant-libs#772)
1 parent 08b1335 commit 8cb16f2

File tree

4 files changed

+46
-28
lines changed

4 files changed

+46
-28
lines changed

matter_server/client/client.py

+20-23
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
SuccessResultMessage,
3838
)
3939
from .connection import MatterClientConnection
40-
from .exceptions import ConnectionClosed, InvalidServerVersion, InvalidState
40+
from .exceptions import ConnectionClosed, InvalidState, ServerVersionTooOld
4141
from .models.node import (
4242
MatterFabricData,
4343
MatterNode,
@@ -509,31 +509,42 @@ async def interview_node(self, node_id: int) -> None:
509509
"""Interview a node."""
510510
await self.send_command(APICommand.INTERVIEW_NODE, node_id=node_id)
511511

512-
async def send_command(
512+
def _prepare_message(
513513
self,
514514
command: str,
515515
require_schema: int | None = None,
516516
**kwargs: Any,
517-
) -> Any:
518-
"""Send a command and get a response."""
519-
if not self.connection.connected or not self._loop:
517+
) -> CommandMessage:
518+
if not self.connection.connected:
520519
raise InvalidState("Not connected")
521520

522521
if (
523522
require_schema is not None
524523
and self.server_info is not None
525524
and require_schema > self.server_info.schema_version
526525
):
527-
raise InvalidServerVersion(
526+
raise ServerVersionTooOld(
528527
"Command not available due to incompatible server version. Update the Matter "
529-
f"Server to a version that supports at least api schema {require_schema}."
528+
f"Server to a version that supports at least api schema {require_schema}.",
530529
)
531530

532-
message = CommandMessage(
531+
return CommandMessage(
533532
message_id=uuid.uuid4().hex,
534533
command=command,
535534
args=kwargs,
536535
)
536+
537+
async def send_command(
538+
self,
539+
command: str,
540+
require_schema: int | None = None,
541+
**kwargs: Any,
542+
) -> Any:
543+
"""Send a command and get a response."""
544+
if not self._loop:
545+
raise InvalidState("Not connected")
546+
547+
message = self._prepare_message(command, require_schema, **kwargs)
537548
future: asyncio.Future[Any] = self._loop.create_future()
538549
self._result_futures[message.message_id] = future
539550
await self.connection.send_message(message)
@@ -549,22 +560,8 @@ async def send_command_no_wait(
549560
**kwargs: Any,
550561
) -> None:
551562
"""Send a command without waiting for the response."""
552-
if not self.server_info:
553-
raise InvalidState("Not connected")
554563

555-
if (
556-
require_schema is not None
557-
and require_schema > self.server_info.schema_version
558-
):
559-
raise InvalidServerVersion(
560-
"Command not available due to incompatible server version. Update the Matter "
561-
f"Server to a version that supports at least api schema {require_schema}."
562-
)
563-
message = CommandMessage(
564-
message_id=uuid.uuid4().hex,
565-
command=command,
566-
args=kwargs,
567-
)
564+
message = self._prepare_message(command, require_schema, **kwargs)
568565
await self.connection.send_message(message)
569566

570567
async def get_diagnostics(self) -> ServerDiagnostics:

matter_server/client/connection.py

+14-5
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@
2626
ConnectionClosed,
2727
ConnectionFailed,
2828
InvalidMessage,
29-
InvalidServerVersion,
3029
InvalidState,
3130
NotConnected,
31+
ServerVersionTooNew,
32+
ServerVersionTooOld,
3233
)
3334

3435
LOGGER = logging.getLogger(f"{__package__}.connection")
@@ -79,14 +80,22 @@ async def connect(self) -> None:
7980
info = cast(ServerInfoMessage, await self.receive_message_or_raise())
8081
self.server_info = info
8182

82-
# basic check for server schema version compatibility
83+
if info.schema_version < SCHEMA_VERSION:
84+
# The client schema is too new, the server can't handle it yet
85+
await self._ws_client.close()
86+
raise ServerVersionTooOld(
87+
f"Matter schema version is incompatible: {SCHEMA_VERSION}, "
88+
f"the server supports at most {info.schema_version} "
89+
"- update the Matter server to a more recent version or downgrade the client."
90+
)
91+
8392
if info.min_supported_schema_version > SCHEMA_VERSION:
84-
# our schema version is too low and can't be handled by the server anymore.
93+
# The client schema version is too low and can't be handled by the server anymore
8594
await self._ws_client.close()
86-
raise InvalidServerVersion(
95+
raise ServerVersionTooNew(
8796
f"Matter schema version is incompatible: {SCHEMA_VERSION}, "
8897
f"the server requires at least {info.min_supported_schema_version} "
89-
" - update the Matter client to a more recent version or downgrade the server."
98+
"- update the Matter client to a more recent version or downgrade the server."
9099
)
91100

92101
LOGGER.info(

matter_server/client/exceptions.py

+8
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,11 @@ class InvalidMessage(MatterClientException):
5353

5454
class InvalidServerVersion(MatterClientException):
5555
"""Exception raised when connected to server with incompatible version."""
56+
57+
58+
class ServerVersionTooOld(InvalidServerVersion):
59+
"""Exception raised when connected to server with is too old to support this client."""
60+
61+
62+
class ServerVersionTooNew(InvalidServerVersion):
63+
"""Exception raised when connected to server with is too new for this client."""

matter_server/server/server.py

+4
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ def __init__(
131131
self.command_handlers: dict[str, APICommandHandler] = {}
132132
self._device_controller: MatterDeviceController | None = None
133133
self._subscribers: set[EventCallBackType] = set()
134+
if MIN_SCHEMA_VERSION > SCHEMA_VERSION:
135+
raise RuntimeError(
136+
"Minimum supported schema version can't be higher than current schema version."
137+
)
134138

135139
@cached_property
136140
def device_controller(self) -> MatterDeviceController:

0 commit comments

Comments
 (0)