using System; using System.Collections.Generic; using ArchestrA.MxAccess; using Serilog; using ZB.MOM.WW.LmxProxy.Host.Domain; namespace ZB.MOM.WW.LmxProxy.Host.MxAccess { public sealed partial class MxAccessClient { /// /// Callback invoked by the SubscriptionManager when it needs to deliver /// data change events. Set by the SubscriptionManager during initialization. /// public Action? OnTagValueChanged { get; set; } /// /// COM event handler for MxAccess OnDataChange events. /// Called on the STA thread when a subscribed tag value changes. /// Signature matches the ArchestrA.MxAccess ILMXProxyServerEvents interface. /// private void OnDataChange( int hLMXServerHandle, int phItemHandle, object pvItemValue, int pwItemQuality, object pftItemTimeStamp, ref MXSTATUS_PROXY[] ItemStatus) { try { var quality = MapQuality(pwItemQuality); var timestamp = ConvertTimestamp(pftItemTimeStamp); var vtq = new Vtq(pvItemValue, timestamp, quality); // We don't have the address from the COM callback — the reference code // looks it up from _subscriptionsByHandle. For the v2 design, the // SubscriptionManager's global handler receives (address, vtq) via // OnTagValueChanged. The actual address resolution will be implemented // when the full subscription tracking is wired up on windev. // Route to the SubscriptionManager's global handler OnTagValueChanged?.Invoke(phItemHandle.ToString(), vtq); } catch (Exception ex) { Log.Error(ex, "Error processing OnDataChange event for handle {Handle}", phItemHandle); } } /// /// COM event handler for MxAccess OnWriteComplete events. /// Signature matches the ArchestrA.MxAccess ILMXProxyServerEvents interface. /// private void OnWriteComplete( int hLMXServerHandle, int phItemHandle, ref MXSTATUS_PROXY[] ItemStatus) { // Write completion is currently fire-and-forget. // Log for diagnostics. try { Log.Debug("WriteCompleted: handle {Handle}", phItemHandle); } catch (Exception ex) { Log.Error(ex, "Error processing OnWriteComplete event for handle {Handle}", phItemHandle); } } /// /// Converts a timestamp object to DateTime in UTC. /// private static DateTime ConvertTimestamp(object timestamp) { if (timestamp is DateTime dt) { return dt.Kind == DateTimeKind.Utc ? dt : dt.ToUniversalTime(); } return DateTime.UtcNow; } } }