Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions test/model/test_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ def test_configuration_value_metadata(inovelli_switch_state):
assert metadata.no_bulk_support is None
assert metadata.value_size is None
assert metadata.format is None
assert metadata.allowed is None
assert metadata.purpose is None

value = ConfigurationValue(
inovelli_switch_state,
Expand All @@ -273,6 +275,8 @@ def test_configuration_value_metadata(inovelli_switch_state):
noBulkSupport=True,
valueSize=1,
format=0,
allowed=[{"value": 0}, {"from": 5, "to": 10, "step": 1}],
purpose="state_after_power_failure",
),
),
)
Expand All @@ -284,3 +288,5 @@ def test_configuration_value_metadata(inovelli_switch_state):
assert metadata.no_bulk_support
assert metadata.value_size == 1
assert metadata.format == ConfigurationValueFormat.SIGNED_INTEGER
assert metadata.allowed == [{"value": 0}, {"from": 5, "to": 10, "step": 1}]
assert metadata.purpose == "state_after_power_failure"
2 changes: 1 addition & 1 deletion zwave_js_server/const/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# minimal server schema version we can handle
MIN_SERVER_SCHEMA_VERSION = 44
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this needs to be bumped. We just added support for optional properties.

# max server schema version we can handle (and our code is compatible with)
MAX_SERVER_SCHEMA_VERSION = 44
MAX_SERVER_SCHEMA_VERSION = 46
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to process the other PR that adds support for schema 45 first.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at that - couldn't find anything requiring changes here. The existing code already expects dicts, and the upstream fix made sure those dicts are actually filled and not just {}.

zwave-js/zwave-js-server#1483

Bumping the schema there may have been overly cautious.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I don't think this changes anything at this point. We need to merge support for schema 45 before schema 46.

Copy link
Copy Markdown
Contributor Author

@AlCalzone AlCalzone Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh. I didn't see the other pending PR. The upstream work for that isn't even merged in zwave-js-server though.

@raman325 any suggestions on how to consolidate?

Copy link
Copy Markdown
Contributor

@raman325 raman325 Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed a PR for schema 45. I didn't see this one so I pushed one for schema 46 as well. I can close that in favor of this one or vice versa doesn't matter to me - thoughts @MartinHjelmare ?

Regardless I do have schema 47 started and will continue working through that once one of these PRs is merged


VALUE_UNKNOWN = "unknown"

Expand Down
31 changes: 29 additions & 2 deletions zwave_js_server/model/value.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from dataclasses import dataclass, field
from enum import IntEnum, StrEnum
from typing import TYPE_CHECKING, Any, TypedDict
from typing import TYPE_CHECKING, Any, NotRequired, TypedDict

from ..const import (
VALUE_UNKNOWN,
Expand All @@ -30,20 +30,37 @@ class ValueType(StrEnum):
STRING = "string"


class AllowedValueSingleDataType(TypedDict):
"""Represent a single value in a list of allowed values."""

value: int


AllowedValueRangeDataType = TypedDict(
Comment thread
MartinHjelmare marked this conversation as resolved.
"AllowedValueRangeDataType",
# not using class based definition as `from` is a reserved keyword
{"from": int, "to": int, "step": NotRequired[int]},
)

AllowedValueDataType = AllowedValueSingleDataType | AllowedValueRangeDataType


class MetaDataType(TypedDict, total=False):
"""Represent a metadata data dict type."""

type: str # required
purpose: str
readable: bool # required
writeable: bool # required
description: str
label: str
description: str
Comment thread
AlCalzone marked this conversation as resolved.
Outdated
min: int | None
max: int | None
unit: str | None
states: dict[str, str]
ccSpecific: dict[str, Any]
valueChangeOptions: list[str]
allowed: list[AllowedValueDataType]
allowManualEntry: bool
stateful: bool
secret: bool
Expand Down Expand Up @@ -164,6 +181,11 @@ def value_change_options(self) -> list[str]:
"""Return valueChangeOptions."""
return self.data.get("valueChangeOptions", [])

@property
def allowed(self) -> list[AllowedValueDataType] | None:
"""Return allowed."""
return self.data.get("allowed")

@property
def allow_manual_entry(self) -> bool | None:
"""Return allowManualEntry."""
Expand Down Expand Up @@ -216,6 +238,11 @@ def is_from_config(self) -> bool | None:
"""Return isFromConfig."""
return self.data.get("isFromConfig")

@property
def purpose(self) -> str | None:
"""Return purpose."""
return self.data.get("purpose")

def update(self, data: MetaDataType) -> None:
"""Update data."""
self.data.update(data)
Expand Down