fix(gateway): adapt DataValue construction to asyncua 2.x
main's requirements.txt unpins asyncua (PR #30), so CI installs 2.0.1, where DataValue's field was renamed StatusCode_ -> StatusCode. The old kwarg made every OPC write raise TypeError at runtime - masked locally by a stale asyncua 1.0.6 in the dev conda env. Also uses ua.DateTime (a datetime subclass) and ua.UInt32 to satisfy the new stricter types, with no behavior change (verified via binary encode/decode round-trip).
This commit is contained in:
@@ -89,7 +89,7 @@ class ActiveReadEngine(SientiaMonitoring):
|
||||
|
||||
@staticmethod
|
||||
def _extract(dv):
|
||||
status_name = dv.StatusCode_.name if dv.StatusCode_ is not None else None
|
||||
status_name = dv.StatusCode.name if dv.StatusCode is not None else None
|
||||
return dv.Value.Value, status_name, dv.SourceTimestamp, dv.ServerTimestamp
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -7,7 +7,6 @@ to the server, a rate-limit floor between writes, and OPC error typing.
|
||||
|
||||
import asyncio
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
|
||||
from asyncua import ua
|
||||
from asyncua.ua.uaerrors import UaStatusCodeError
|
||||
@@ -146,12 +145,12 @@ class WriteEngine(SientiaMonitoring):
|
||||
variant = ua.Variant(typed_value, self._variant_type(cmd['data_type']))
|
||||
write_quality = cmd.get('write_quality', self.write_quality)
|
||||
write_timestamp = cmd.get('write_timestamp', self.write_timestamp)
|
||||
# NOTE: DataValue.StatusCode_ default_factory populates a Good status
|
||||
# even when omitted, so "off" must pass StatusCode_=None explicitly
|
||||
# NOTE: DataValue.StatusCode default_factory populates a Good status
|
||||
# even when omitted, so "off" must pass StatusCode=None explicitly
|
||||
# or the flag silently no-ops.
|
||||
status_code = ua.StatusCode(ua.StatusCodes.Good) if write_quality else None
|
||||
source_ts = datetime.fromisoformat(cmd['timestamp']) if write_timestamp else None
|
||||
return ua.DataValue(variant, StatusCode_=status_code, SourceTimestamp=source_ts)
|
||||
status_code = ua.StatusCode(ua.UInt32(ua.StatusCodes.Good)) if write_quality else None
|
||||
source_ts = ua.DateTime.fromisoformat(cmd['timestamp']) if write_timestamp else None
|
||||
return ua.DataValue(variant, StatusCode=status_code, SourceTimestamp=source_ts)
|
||||
|
||||
def _is_session_bad(self, exc: Exception) -> bool:
|
||||
return isinstance(exc, UaStatusCodeError) and type(exc).__name__ in _SESSION_BAD_NAMES
|
||||
|
||||
@@ -25,7 +25,7 @@ def make_dv(value=42.0, status='Good', source_ts=None, server_ts=None):
|
||||
server_ts = server_ts or source_ts
|
||||
return ua.DataValue(
|
||||
ua.Variant(value),
|
||||
StatusCode_=ua.StatusCode(getattr(ua.StatusCodes, status)),
|
||||
StatusCode=ua.StatusCode(getattr(ua.StatusCodes, status)),
|
||||
SourceTimestamp=source_ts,
|
||||
ServerTimestamp=server_ts,
|
||||
)
|
||||
|
||||
@@ -108,8 +108,8 @@ async def test_write_defaults_carry_statuscode_and_timestamp():
|
||||
await eng.write(base_cmd())
|
||||
|
||||
dv = node.write_value.await_args.args[0]
|
||||
assert dv.StatusCode_ is not None
|
||||
assert dv.StatusCode_.is_good()
|
||||
assert dv.StatusCode is not None
|
||||
assert dv.StatusCode.is_good()
|
||||
assert dv.SourceTimestamp == datetime.fromisoformat('2026-07-13T12:00:00Z')
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ async def test_write_engine_flags_off_omit_statuscode_and_timestamp():
|
||||
await eng.write(base_cmd())
|
||||
|
||||
dv = node.write_value.await_args.args[0]
|
||||
assert dv.StatusCode_ is None
|
||||
assert dv.StatusCode is None
|
||||
assert dv.SourceTimestamp is None
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ async def test_per_message_flag_override_disables_timestamp():
|
||||
|
||||
dv = node.write_value.await_args.args[0]
|
||||
assert dv.SourceTimestamp is None
|
||||
assert dv.StatusCode_ is not None # write_quality untouched, stays on
|
||||
assert dv.StatusCode is not None # write_quality untouched, stays on
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
Reference in New Issue
Block a user