feat(SIENTIAPDE-2202): write timestamp and quality per OPC server
- write_timestamp/write_quality come from the command, then the server document (connectors/opc-servers, read even when the reads have the connection open, same 60 s cache), then the WRITE_TIMESTAMP/WRITE_QUALITY env defaults. - The quality comes from the command's `quality` (the prediction status: Good/Bad/Uncertain, Good when absent); an unknown one is a bad_quality error. - A server that refuses them (BadWriteNotSupported, e.g. Kepware) gets the value written again alone and is remembered until restart: one warning and opc_write_value_only_fallback_total per server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -149,3 +149,67 @@ async def test_mongo_errors_propagate_to_the_caller():
|
||||
|
||||
with pytest.raises(RuntimeError, match='mongo down'):
|
||||
await resolver.resolve('1', {})
|
||||
|
||||
|
||||
# --- SIENTIAPDE-2202: write options on the server document ---
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_options_come_from_the_connector():
|
||||
resolver = make_resolver(
|
||||
connector={**CONNECTOR, 'write_timestamp': False, 'write_quality': True},
|
||||
opc_server={**OPC_SERVER, 'write_timestamp': True},
|
||||
)
|
||||
|
||||
assert await resolver.write_options('1') == {'write_timestamp': False, 'write_quality': True}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_options_come_from_opc_servers_without_tag_database():
|
||||
resolver = make_resolver(opc_server={**OPC_SERVER, 'write_quality': False})
|
||||
|
||||
assert await resolver.write_options('1') == {'write_quality': False}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_only_boolean_write_options_count():
|
||||
resolver = make_resolver(
|
||||
connector={**CONNECTOR, 'write_timestamp': 'false', 'write_quality': 0}
|
||||
)
|
||||
|
||||
assert await resolver.write_options('1') == {}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_options_are_read_even_with_a_live_pooled_connection():
|
||||
pooled = {'url': 'opc.tcp://read:1', 'server_uri': 'urn:read', 'use_security': True}
|
||||
resolver = make_resolver(connector={**CONNECTOR, 'write_timestamp': False}, pooled=pooled)
|
||||
|
||||
assert await resolver.resolve('1', {}) == pooled
|
||||
assert await resolver.write_options('1') == {'write_timestamp': False}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_options_share_the_lookup_cache():
|
||||
resolver = make_resolver(connector={**CONNECTOR, 'write_quality': False})
|
||||
|
||||
await resolver.resolve('1', {})
|
||||
await resolver.write_options('1')
|
||||
|
||||
assert resolver.mongo.find_one.await_count == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_options_of_an_unknown_server_are_empty():
|
||||
resolver = make_resolver()
|
||||
|
||||
assert await resolver.write_options('9') == {}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_options_never_raise():
|
||||
resolver = make_resolver()
|
||||
resolver.mongo.find_one = AsyncMock(side_effect=RuntimeError('mongo down'))
|
||||
|
||||
assert await resolver.write_options('1') == {}
|
||||
assert 'mongo down' in resolver.logger.warning.call_args.args[0]
|
||||
|
||||
Reference in New Issue
Block a user