69 lines
2.8 KiB
C#
69 lines
2.8 KiB
C#
using System;
|
|
using System.Runtime.InteropServices;
|
|
using ArchestrA.MxAccess;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Backend.MxAccess;
|
|
|
|
/// <summary>
|
|
/// Concrete <see cref="IMxProxy"/> backed by a real <c>LMXProxyServer</c> COM object.
|
|
/// Port of v1 <c>MxProxyAdapter</c>. <strong>Must only be constructed on an STA thread</strong>
|
|
/// — the StaPump owns this instance.
|
|
/// </summary>
|
|
public sealed class MxProxyAdapter : IMxProxy, IDisposable
|
|
{
|
|
private LMXProxyServer? _lmxProxy;
|
|
|
|
public event MxDataChangeHandler? OnDataChange;
|
|
public event MxWriteCompleteHandler? OnWriteComplete;
|
|
|
|
public int Register(string clientName)
|
|
{
|
|
_lmxProxy = new LMXProxyServer();
|
|
_lmxProxy.OnDataChange += ProxyOnDataChange;
|
|
_lmxProxy.OnWriteComplete += ProxyOnWriteComplete;
|
|
|
|
var handle = _lmxProxy.Register(clientName);
|
|
if (handle <= 0)
|
|
throw new InvalidOperationException($"LMXProxyServer.Register returned invalid handle: {handle}");
|
|
return handle;
|
|
}
|
|
|
|
public void Unregister(int handle)
|
|
{
|
|
if (_lmxProxy is null) return;
|
|
try
|
|
{
|
|
_lmxProxy.OnDataChange -= ProxyOnDataChange;
|
|
_lmxProxy.OnWriteComplete -= ProxyOnWriteComplete;
|
|
_lmxProxy.Unregister(handle);
|
|
}
|
|
finally
|
|
{
|
|
// ReleaseComObject loop until refcount = 0 — the Tier C SafeHandle wraps this in
|
|
// production; here the lifetime is owned by the surrounding MxAccessHandle.
|
|
while (Marshal.IsComObject(_lmxProxy) && Marshal.ReleaseComObject(_lmxProxy) > 0) { }
|
|
_lmxProxy = null;
|
|
}
|
|
}
|
|
|
|
public int AddItem(int handle, string address) => _lmxProxy!.AddItem(handle, address);
|
|
|
|
public void RemoveItem(int handle, int itemHandle) => _lmxProxy!.RemoveItem(handle, itemHandle);
|
|
|
|
public void AdviseSupervisory(int handle, int itemHandle) => _lmxProxy!.AdviseSupervisory(handle, itemHandle);
|
|
|
|
public void UnAdviseSupervisory(int handle, int itemHandle) => _lmxProxy!.UnAdvise(handle, itemHandle);
|
|
|
|
public void Write(int handle, int itemHandle, object value, int securityClassification) =>
|
|
_lmxProxy!.Write(handle, itemHandle, value, securityClassification);
|
|
|
|
private void ProxyOnDataChange(int hLMXServerHandle, int phItemHandle, object pvItemValue,
|
|
int pwItemQuality, object pftItemTimeStamp, ref MXSTATUS_PROXY[] ItemStatus)
|
|
=> OnDataChange?.Invoke(hLMXServerHandle, phItemHandle, pvItemValue, pwItemQuality, pftItemTimeStamp, ref ItemStatus);
|
|
|
|
private void ProxyOnWriteComplete(int hLMXServerHandle, int phItemHandle, ref MXSTATUS_PROXY[] ItemStatus)
|
|
=> OnWriteComplete?.Invoke(hLMXServerHandle, phItemHandle, ref ItemStatus);
|
|
|
|
public void Dispose() => Unregister(0);
|
|
}
|