feat: add JoeAppEngine OPC UA nodes, fix DCL auto-reconnect and quality push

- Add JoeAppEngine folder to OPC UA nodes.json (BTCS, AlarmCntsBySeverity, Scheduler/ScanTime)
- Fix DataConnectionActor: capture Self in PreStart for use from non-actor threads,
  preventing Self.Tell failure in Disconnected event handler
- Implement InstanceActor.HandleConnectionQualityChanged to mark attributes Bad on disconnect
- Fix LmxFakeProxy TagMapper to serialize arrays as JSON instead of "System.Int32[]"
- Allow DataType and DataSourceReference updates in TemplateService.UpdateAttributeAsync
- Update test_infra_opcua.md with JoeAppEngine documentation
This commit is contained in:
Joseph Doherty
2026-03-19 13:27:54 -04:00
parent ffdda51990
commit 7740a3bcf9
70 changed files with 2684 additions and 541 deletions

View File

@@ -1,4 +1,5 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
# Build stage forced to amd64: Grpc.Tools protoc crashes on linux/arm64 (Apple Silicon)
FROM --platform=linux/amd64 mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
COPY LmxFakeProxy.csproj .
RUN dotnet restore

View File

@@ -1,3 +1,5 @@
using System.Collections;
using System.Text.Json;
using LmxFakeProxy.Grpc;
namespace LmxFakeProxy;
@@ -30,12 +32,20 @@ public class TagMapper
return "Uncertain";
}
public static string FormatValue(object? value)
{
if (value is null) return string.Empty;
if (value is Array or IList)
return JsonSerializer.Serialize(value);
return value.ToString() ?? string.Empty;
}
public static VtqMessage ToVtqMessage(string tag, object? value, DateTime timestampUtc, uint statusCode)
{
return new VtqMessage
{
Tag = tag,
Value = value?.ToString() ?? string.Empty,
Value = FormatValue(value),
TimestampUtcTicks = timestampUtc.Ticks,
Quality = MapQuality(statusCode)
};

View File

@@ -133,6 +133,43 @@
"Description": "Valve command (0=Close, 1=Open, 2=Stop)"
}
]
},
{
"Folder": "JoeAppEngine",
"NodeList": [
{
"NodeId": "JoeAppEngine.BTCS",
"Name": "BTCS",
"DataType": "String",
"ValueRank": -1,
"AccessLevel": "CurrentReadOrWrite",
"Description": "BTCS string value"
},
{
"NodeId": "JoeAppEngine.AlarmCntsBySeverity",
"Name": "AlarmCntsBySeverity",
"DataType": "Int32",
"ValueRank": 1,
"ArrayDimensions": [13],
"AccessLevel": "CurrentReadOrWrite",
"Description": "13-element alarm counts by severity level"
}
],
"FolderList": [
{
"Folder": "Scheduler",
"NodeList": [
{
"NodeId": "JoeAppEngine.Scheduler.ScanTime",
"Name": "ScanTime",
"DataType": "DateTime",
"ValueRank": -1,
"AccessLevel": "CurrentReadOrWrite",
"Description": "Current scan time (updates every second)"
}
]
}
]
}
]
}