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.
165 lines
5.4 KiB
165 lines
5.4 KiB
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;
|
|
}
|
|
|
|
public async Task<BoardMeasurementResult> RunAsync(
|
|
Func<string, Task>? onIcSnReadAsync = null,
|
|
DateTime? measurementNotBeforeUtc = null)
|
|
{
|
|
var log = new StringBuilder();
|
|
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);
|
|
log.AppendLine($"> BOARD PORT: {boardClient.PortName} @ {_boardSettings.BaudRate}");
|
|
|
|
var postReadIdCommandSent = false;
|
|
try
|
|
{
|
|
await SendOnlyAndLogAsync(boardClient, "PRE_CONNECT", _boardSettings.PreConnectCommand, log);
|
|
|
|
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 읽기 실패");
|
|
}
|
|
|
|
await SendOnlyAndLogAsync(boardClient, "POST_READ_ID", _boardSettings.PostReadIdCommand, log);
|
|
postReadIdCommandSent = true;
|
|
|
|
if (onIcSnReadAsync is not null)
|
|
{
|
|
await onIcSnReadAsync(icSn);
|
|
}
|
|
|
|
await SendAndLogAsync(boardClient, "CAL_DEFAULT", _boardSettings.CalDefaultCommand, _boardSettings.ReadTimeout, false, log);
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
var equipmentResult = await equipmentService.ReadAsync();
|
|
log.Append(equipmentResult.RawLog);
|
|
|
|
return new BoardMeasurementResult
|
|
{
|
|
IcSn = icSn,
|
|
Voltage = equipmentResult.Voltage,
|
|
Current = equipmentResult.Current,
|
|
RawLog = log.ToString()
|
|
};
|
|
}
|
|
finally
|
|
{
|
|
if (!postReadIdCommandSent)
|
|
{
|
|
await SendFinalBoardOffAsync(boardClient, log);
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task SendFinalBoardOffAsync(SerialBoardClient boardClient, StringBuilder log)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(_boardSettings.PostReadIdCommand))
|
|
{
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
await SendOnlyAndLogAsync(boardClient, "FINAL_OFF", _boardSettings.PostReadIdCommand, log);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.AppendLine($"> BOARD FINAL_OFF FAILED: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|