Skip to content

Commit

Permalink
Add support for lastSeen property (#705)
Browse files Browse the repository at this point in the history
* Add support for lastSeen property

* backport fromisoformat

* Remove backport since we are dropping python 3.10 support
  • Loading branch information
raman325 authored Aug 8, 2023
1 parent ec68675 commit 83bf6ce
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 7 deletions.
2 changes: 1 addition & 1 deletion test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def version_data_fixture():
"serverVersion": "test_server_version",
"homeId": "test_home_id",
"minSchemaVersion": 0,
"maxSchemaVersion": 29,
"maxSchemaVersion": 30,
}


Expand Down
22 changes: 21 additions & 1 deletion test/model/test_node.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Test the node model."""
import json
from copy import deepcopy
from datetime import datetime
from datetime import datetime, timezone
from unittest.mock import patch

import pytest
Expand Down Expand Up @@ -136,6 +136,26 @@ def test_from_state(client):
)
assert node.endpoints[0] != node.endpoints[0].index
assert hash(node.endpoints[0]) == hash((client.driver, node.node_id, 0))
assert node.last_seen is None
event = Event(
"statistics updated",
{
"source": "node",
"event": "statistics updated",
"nodeId": node.node_id,
"statistics": {
"commandsTX": 1,
"commandsRX": 2,
"commandsDroppedTX": 3,
"commandsDroppedRX": 4,
"timeoutResponse": 5,
"rssi": 7,
"lastSeen": "2023-07-18T15:42:34.701Z",
},
},
)
node.receive_event(event)
assert node.last_seen == datetime(2023, 7, 18, 15, 42, 34, 701000, timezone.utc)


async def test_highest_security_value(lock_schlage_be469, ring_keypad):
Expand Down
2 changes: 1 addition & 1 deletion test/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ async def test_additional_user_agent_components(client_session, url):
{
"command": "initialize",
"messageId": "initialize",
"schemaVersion": 29,
"schemaVersion": 30,
"additionalUserAgentComponents": {
"zwave-js-server-python": __version__,
"foo": "bar",
Expand Down
2 changes: 1 addition & 1 deletion test/test_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ async def test_dump_additional_user_agent_components(
{
"command": "initialize",
"messageId": "initialize",
"schemaVersion": 29,
"schemaVersion": 30,
"additionalUserAgentComponents": {
"zwave-js-server-python": __version__,
"foo": "bar",
Expand Down
2 changes: 1 addition & 1 deletion test/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def test_dump_state(
assert captured.out == (
"{'type': 'version', 'driverVersion': 'test_driver_version', "
"'serverVersion': 'test_server_version', 'homeId': 'test_home_id', "
"'minSchemaVersion': 0, 'maxSchemaVersion': 29}\n"
"'minSchemaVersion': 0, 'maxSchemaVersion': 30}\n"
"{'type': 'result', 'success': True, 'result': {}, 'messageId': 'initialize'}\n"
"test_result\n"
)
Expand Down
4 changes: 2 additions & 2 deletions zwave_js_server/const/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
__version__ = metadata.version(PACKAGE_NAME)

# minimal server schema version we can handle
MIN_SERVER_SCHEMA_VERSION = 29
MIN_SERVER_SCHEMA_VERSION = 30
# max server schema version we can handle (and our code is compatible with)
MAX_SERVER_SCHEMA_VERSION = 29
MAX_SERVER_SCHEMA_VERSION = 30

VALUE_UNKNOWN = "unknown"

Expand Down
9 changes: 9 additions & 0 deletions zwave_js_server/model/node/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,13 @@ def keep_awake(self) -> bool:
"""Return whether the node is set to keep awake."""
return self.data["keepAwake"]

@property
def last_seen(self) -> datetime | None:
"""Return when the node was last seen."""
if last_seen := self.data.get("lastSeen"):
return datetime.fromisoformat(last_seen)
return None

def update(self, data: NodeDataType) -> None:
"""Update the internal state data."""
self.data = copy.deepcopy(data)
Expand Down Expand Up @@ -969,3 +976,5 @@ def handle_statistics_updated(self, event: Event) -> None:
event.data["statistics_updated"] = self._statistics = NodeStatistics(
self.client, statistics
)
if last_seen := statistics.get("lastSeen"):
self.data["lastSeen"] = last_seen
1 change: 1 addition & 0 deletions zwave_js_server/model/node/data_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,4 @@ class NodeDataType(TypedDict, total=False):
statistics: NodeStatisticsDataType
highestSecurityClass: int
isControllerNode: bool
lastSeen: str
5 changes: 5 additions & 0 deletions zwave_js_server/model/node/statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from contextlib import suppress
from dataclasses import dataclass, field
from datetime import datetime
from typing import TYPE_CHECKING, TypedDict

from zwave_js_server.exceptions import RssiErrorReceived
Expand All @@ -27,6 +28,7 @@ class NodeStatisticsDataType(TypedDict, total=False):
rssi: int
lwr: RouteStatisticsDataType
nlwr: RouteStatisticsDataType
lastSeen: str


@dataclass
Expand All @@ -43,6 +45,7 @@ class NodeStatistics:
rtt: int | None = field(init=False)
lwr: RouteStatistics | None = field(init=False, default=None)
nlwr: RouteStatistics | None = field(init=False, default=None)
last_seen: datetime | None = field(init=False, default=None)

def __post_init__(self) -> None:
"""Post initialize."""
Expand All @@ -52,6 +55,8 @@ def __post_init__(self) -> None:
self.commands_dropped_tx = self.data["commandsDroppedTX"]
self.timeout_response = self.data["timeoutResponse"]
self.rtt = self.data.get("rtt")
if last_seen := self.data.get("lastSeen"):
self.last_seen = datetime.fromisoformat(last_seen)
if lwr := self.data.get("lwr"):
with suppress(ValueError):
self.lwr = RouteStatistics(self.client, lwr)
Expand Down

0 comments on commit 83bf6ce

Please sign in to comment.