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.

135 lines
4.6 KiB

2 months ago
using System.Text;
using System.Text.RegularExpressions;
using Housing.Models;
namespace Housing.Services;
public sealed class BoardTestService
{
private readonly BoardHardwareSettings _boardSettings;
private readonly EquipmentMeasurementSettings _equipmentSettings;
public BoardTestService(BoardHardwareSettings boardSettings, EquipmentMeasurementSettings equipmentSettings)
{
_boardSettings = boardSettings;
_equipmentSettings = equipmentSettings;
}
2 months ago
public async Task<BoardMeasurementResult> RunAsync(
Func<string, Task>? onIcSnReadAsync = null,
DateTime? measurementNotBeforeUtc = null)
2 months ago
{
var log = new StringBuilder();
2 months ago
var equipmentService = new EquipmentMeasurementService(_equipmentSettings);
log.Append(await equipmentService.RunPreBoardCommandAsync());
if (_equipmentSettings.PreBoardDelayMilliseconds > 0)
{
log.AppendLine($"> CURRENT PRE-BOARD DELAY: {_equipmentSettings.PreBoardDelayMilliseconds} ms");
await Task.Delay(_equipmentSettings.PreBoardDelayMilliseconds);
}
using var boardClient = new SerialBoardClient(_boardSettings);
2 months ago
log.AppendLine($"> BOARD PORT: {boardClient.PortName} @ {_boardSettings.BaudRate}");
2 months ago
await SendOnlyAndLogAsync(boardClient, "PRE_CONNECT", _boardSettings.PreConnectCommand, log);
2 months ago
var connectResponse = await SendAndLogAsync(boardClient, "CONNECT", _boardSettings.ConnectCommand, _boardSettings.ReadTimeout, true, log);
if (!ContainsSuccess(connectResponse))
{
throw new InvalidOperationException("시료 연결 확인 실패");
}
var idResponse = await SendAndLogAsync(boardClient, "READ_ID", _boardSettings.ReadIdCommand, _boardSettings.ReadTimeout, true, log);
var icSn = ExtractFirstHexLine(idResponse);
if (string.IsNullOrWhiteSpace(icSn))
{
throw new InvalidOperationException("IC_SN 읽기 실패");
}
2 months ago
if (onIcSnReadAsync is not null)
{
await onIcSnReadAsync(icSn);
}
2 months ago
await SendAndLogAsync(boardClient, "CAL_DEFAULT", _boardSettings.CalDefaultCommand, _boardSettings.ReadTimeout, false, log);
2 months ago
if (measurementNotBeforeUtc.HasValue)
{
var remainingDelay = measurementNotBeforeUtc.Value - DateTime.UtcNow;
if (remainingDelay > TimeSpan.Zero)
{
log.AppendLine($"> MEASUREMENT START DELAY: {(int)remainingDelay.TotalMilliseconds} ms");
await Task.Delay(remainingDelay);
}
}
2 months ago
var equipmentResult = await equipmentService.ReadAsync();
log.Append(equipmentResult.RawLog);
return new BoardMeasurementResult
{
IcSn = icSn,
Voltage = equipmentResult.Voltage,
Current = equipmentResult.Current,
RawLog = log.ToString()
};
}
private static async Task<string> SendAndLogAsync(
SerialBoardClient client,
string label,
string command,
int timeoutMilliseconds,
bool waitForEndToken,
StringBuilder log)
{
log.AppendLine($"> BOARD {label}: {command}");
var response = await client.SendCommandAsync(command, timeoutMilliseconds, waitForEndToken);
log.Append(response);
return response;
}
2 months ago
private static async Task SendOnlyAndLogAsync(
SerialBoardClient client,
string label,
string command,
StringBuilder log)
{
if (string.IsNullOrWhiteSpace(command))
{
return;
}
log.AppendLine($"> BOARD {label}: {command}");
await client.SendOnlyAsync(command);
}
2 months ago
private static bool ContainsSuccess(string response)
{
return response
.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)
.Any(line => string.Equals(line.Trim(), "Success", StringComparison.OrdinalIgnoreCase));
}
private static string ExtractFirstHexLine(string response)
{
foreach (var rawLine in response.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries))
{
var line = rawLine.Trim();
if (line.Equals("<end>", StringComparison.OrdinalIgnoreCase) ||
line.Equals("Fail", StringComparison.OrdinalIgnoreCase))
{
continue;
}
if (Regex.IsMatch(line, "^[0-9A-Fa-f]{8,32}$"))
{
return line.ToUpperInvariant();
}
}
return string.Empty;
}
}