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.
4.5 KiB
4.5 KiB
DMM Related Code
This file is a reference-only extraction. It is not compiled by the Housing app.
Source Files
Services/EquipmentMeasurementSettings.csServices/EquipmentMeasurementService.csServices/IScpiClient.csServices/TcpScpiClient.csServices/SerialScpiClient.csServices/VisaScpiClient.cs
Hardware.ini Keys
[Equipment]
Timeout=5000
SettleMilliseconds=300
; 34465A DMM
VoltageConnection=LAN
VoltageResource=
VoltageIdnMatch=34465A
VoltageHost=192.168.10.13
VoltagePort=5025
VoltageSetupCommand=
VoltageReadCommand=MEAS:VOLT:DC?
Settings Load Code
Voltage = LoadChannel(
values,
"Voltage",
"MEAS:VOLT:DC?",
"34460,34461,34465,34470,3446,3447");
private static ScpiChannelSettings LoadChannel(
Dictionary<string, string> values,
string prefix,
string defaultReadCommand,
string defaultIdnMatch)
{
return new ScpiChannelSettings
{
Connection = GetString(values, prefix + "Connection", string.Empty),
ResourceName = GetString(values, prefix + "Resource", string.Empty),
IdnMatch = GetString(values, prefix + "IdnMatch", defaultIdnMatch),
Host = GetString(values, prefix + "Host", string.Empty),
Port = GetInt(values, prefix + "Port", 5025),
PortName = GetString(values, prefix + "PortName", string.Empty),
BaudRate = GetInt(values, prefix + "BaudRate", 115200),
Terminator = GetString(values, prefix + "Terminator", string.Empty),
SetupCommand = GetString(values, prefix + "SetupCommand", string.Empty),
CleanupCommand = GetString(values, prefix + "CleanupCommand", string.Empty),
ReadCommand = GetString(values, prefix + "ReadCommand", defaultReadCommand)
};
}
Voltage Read Flow
var voltage = await ReadChannelAsync("VOLTAGE", _settings.Voltage, log);
private async Task<decimal> ReadChannelAsync(
string label,
ScpiChannelSettings channel,
StringBuilder log,
bool skipSetupCommand = false)
{
if (IsDisabled(channel))
{
log.AppendLine($"> {label} SKIP: disabled in Hardware.ini");
return 0m;
}
if (string.IsNullOrWhiteSpace(channel.ReadCommand))
{
throw new InvalidOperationException($"Hardware.ini [Equipment] {label} ReadCommand 값을 확인하세요.");
}
using var client = await CreateClientAsync(label, channel);
return await ReadChannelWithClientAsync(label, channel, client, log, skipSetupCommand);
}
private static async Task<decimal> ReadChannelWithClientAsync(
string label,
ScpiChannelSettings channel,
IScpiClient client,
StringBuilder log,
bool skipSetupCommand = false)
{
if (string.IsNullOrWhiteSpace(channel.ReadCommand))
{
throw new InvalidOperationException($"Hardware.ini [Equipment] {label} ReadCommand 값을 확인하세요.");
}
log.AppendLine($"> {label} CONNECT: {DescribeClient(client, channel)}");
if (!skipSetupCommand && !string.IsNullOrWhiteSpace(channel.SetupCommand))
{
log.AppendLine($"> {label} SETUP: {channel.SetupCommand}");
await SendCommandListAsync(client, channel.SetupCommand);
}
log.AppendLine($"> {label} READ: {channel.ReadCommand}");
var response = await client.QueryAsync(channel.ReadCommand);
log.AppendLine(response);
return ExtractFirstDecimal(response, label);
}
Shared SCPI Connection Code
private Task<IScpiClient> CreateClientAsync(string label, ScpiChannelSettings channel)
{
var connection = GetConnectionType(channel);
return connection switch
{
"TCP" or "LAN" or "ETHERNET" => CreateTcpClientAsync(label, channel),
"SERIAL" or "COM" => Task.FromResult<IScpiClient>(
new SerialScpiClient(
channel.PortName,
channel.BaudRate,
_settings.Timeout,
channel.GetIdnMatches(),
channel.GetTerminator())),
"VISA" or "USB" => CreateVisaClientAsync(channel),
_ => throw new InvalidOperationException($"{label} 장비 연결 방식은 Visa, Serial, Tcp 중 하나로 설정하세요.")
};
}
private static decimal ExtractFirstDecimal(string response, string label)
{
var match = Regex.Match(response, @"[-+]?\d+(?:\.\d+)?(?:[Ee][-+]?\d+)?");
if (!match.Success)
{
throw new InvalidOperationException($"{label} 측정값 파싱 실패");
}
return decimal.Parse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture);
}