리크 테스트 gui
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
8.1 KiB

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using leak_test_project.Models;
using leak_test_project.Utils;
namespace leak_test_project.Infrastructure
{
/// <summary>
/// 실제 ADLINK 하드웨어와 통신하는 DIO 보드 구현체.
/// Dask.cs 래퍼를 사용하여 PCIS-DASK API를 호출합니다.
/// </summary>
public class RealDioBoard : IDioBoard
{
private short _cardNumber = -1;
private readonly Dictionary<string, DioPoint> _inputs = new Dictionary<string, DioPoint>();
private readonly Dictionary<string, DioPoint> _outputs = new Dictionary<string, DioPoint>();
private bool _disposed = false;
private CancellationTokenSource _pollingCts;
private Task _pollingTask;
public event EventHandler<DioEventArgs> InputChanged;
public bool Initialize()
{
var config = DioConfigParser.LoadDefault();
if (config != null)
{
foreach (var p in config.InputPoints)
_inputs[p.Name] = p;
foreach (var p in config.OutputPoints)
_outputs[p.Name] = p;
ushort cardType = GetCardTypeFromConfig(config.BoardType);
ushort boardNumber = (ushort)config.BoardNumber;
try
{
short ret = DASK.Register_Card(cardType, boardNumber);
if (ret < 0)
{
Console.WriteLine($"[RealDioBoard] Error registering ADLINK Card {config.BoardType}. Error code: {ret}");
return false;
}
_cardNumber = ret;
Console.WriteLine($"[RealDioBoard] Registered ADLINK Card {config.BoardType} (Handle: {_cardNumber})");
}
catch (Exception ex)
{
Console.WriteLine($"[RealDioBoard] Critical error during HW Registration: {ex.Message}");
// 드라이버가 없거나 하드웨어 접근 오류 시 앱이 죽지 않도록 false 반환
return false;
}
}
else
{
Console.WriteLine("[RealDioBoard] No INI config found.");
return false;
}
// Start background polling task for inputs
_pollingCts = new CancellationTokenSource();
_pollingTask = Task.Run(() => InputPollingLoop(_pollingCts.Token));
return true;
}
private ushort GetCardTypeFromConfig(string boardType)
{
switch (boardType.ToUpper())
{
case "PCI_7230": return DASK.PCI_7230;
case "PCI_7432": return DASK.PCI_7432;
case "PCI_7433": return DASK.PCI_7433;
case "PCI_7434": return DASK.PCI_7434;
case "PCI_7250": return DASK.PCI_7250;
// Add more if needed. Default to 7432
default:
Console.WriteLine($"[RealDioBoard] Unknown BoardType {boardType}. Defaulting to PCI_7432.");
return DASK.PCI_7432;
}
}
public bool ReadInput(string pointName)
{
if (_cardNumber < 0) return false;
if (_inputs.TryGetValue(pointName, out var point))
{
// Find port and line mathematically (Wait, actually we should use DIO port mapping)
// Assuming simple 1-to-1 mapping where index == line in Port 0.
int index = new List<DioPoint>(_inputs.Values).IndexOf(point);
if (index >= 0)
{
ushort port = 0; // Usually port 0 for first 32 lines.
uint readValue;
short ret = DASK.DI_ReadPort((ushort)_cardNumber, port, out readValue);
if (ret >= 0)
{
bool isOn = (readValue & (1U << index)) != 0;
point.Value = isOn;
return isOn;
}
}
}
return false;
}
public void WriteOutput(string pointName, bool value)
{
if (_cardNumber < 0) return;
if (_outputs.TryGetValue(pointName, out var point))
{
int index = new List<DioPoint>(_outputs.Values).IndexOf(point);
if (index >= 0)
{
point.Value = value;
ushort port = 0;
// Actually, to safely write a single bit without affecting others:
uint outValue;
DASK.DO_ReadPort((ushort)_cardNumber, port, out outValue);
if (value)
{
outValue |= (1U << index);
}
else
{
outValue &= ~(1U << index);
}
DASK.DO_WritePort((ushort)_cardNumber, port, outValue);
Console.WriteLine($"[RealDioBoard] Set {pointName} (Line {index}) to {(value ? "ON" : "OFF")}");
}
}
}
private async Task InputPollingLoop(CancellationToken token)
{
try
{
while (!token.IsCancellationRequested)
{
if (_cardNumber >= 0)
{
ushort port = 0;
uint readValue;
short ret = DASK.DI_ReadPort((ushort)_cardNumber, port, out readValue);
if (ret >= 0)
{
var inputPoints = new List<DioPoint>(_inputs.Values);
for (int i = 0; i < inputPoints.Count; i++)
{
var point = inputPoints[i];
bool isCurrentlyOn = (readValue & (1U << i)) != 0;
// If changed from OFF to ON
if (isCurrentlyOn && !point.Value)
{
point.Value = true;
Console.WriteLine($"[RealDioBoard] Input {point.Name} triggered (OFF→ON)");
InputChanged?.Invoke(this, new DioEventArgs(point.Name, true));
}
else if (!isCurrentlyOn && point.Value)
{
point.Value = false;
}
}
}
}
// 10ms polling rate (approx)
await Task.Delay(10, token);
}
}
catch (TaskCanceledException)
{
// Expected when disposing
}
catch (Exception ex)
{
Console.WriteLine($"[RealDioBoard] Polling error: {ex.Message}");
}
}
public List<DioPoint> GetInputPoints()
{
return new List<DioPoint>(_inputs.Values);
}
public List<DioPoint> GetOutputPoints()
{
return new List<DioPoint>(_outputs.Values);
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
if (_pollingCts != null)
{
_pollingCts.Cancel();
_pollingCts.Dispose();
}
if (_cardNumber >= 0)
{
DASK.Release_Card((ushort)_cardNumber);
Console.WriteLine("[RealDioBoard] Released ADLINK Card.");
_cardNumber = -1;
}
}
}
}
}