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

DMM Related Code

This file is a reference-only extraction. It is not compiled by the Housing app.

Source Files

  • Services/EquipmentMeasurementSettings.cs
  • Services/EquipmentMeasurementService.cs
  • Services/IScpiClient.cs
  • Services/TcpScpiClient.cs
  • Services/SerialScpiClient.cs
  • Services/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);
}