| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- using System;
- using System.Drawing;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- using APS7100TestTool.Controllers;
- using APS7100TestTool.Models;
- using APS7100TestTool.Libraries;
- namespace APS7100TestTool.Forms
- {
- public partial class ManualTestForm : Form
- {
- private IPowerSupplyController? _controller;
- private DeviceType _deviceType;
- private System.Windows.Forms.Timer _measureTimer;
-
- // 防止测量操作重叠
- private volatile bool _isMeasuring = false;
-
- // 回调:暂停/恢复 Modbus 轮询
- // 当发送本地模式命令时,需要同时暂停 Modbus 轮询,否则设备会立即切换回远程模式
- public Action? OnSuspendModbusPolling { get; set; }
- public Action? OnResumeModbusPolling { get; set; }
- public ManualTestForm(IPowerSupplyController? controller, DeviceType deviceType)
- {
- InitializeComponent();
-
- // 启用双缓冲减少闪烁
- this.DoubleBuffered = true;
- this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
- ControlStyles.AllPaintingInWmPaint |
- ControlStyles.UserPaint, true);
- this.UpdateStyles();
-
- _controller = controller;
- _deviceType = deviceType;
- _measureTimer = new System.Windows.Forms.Timer();
- _measureTimer.Interval = 1000;
- _measureTimer.Tick += MeasureTimer_Tick;
- InitializeUI();
- }
- private void InitializeUI()
- {
- // 设置窗口标题
- string deviceName = _deviceType == DeviceType.APS7100 ? "APS-7100 (AC)" : "PSW-250 (DC)";
- this.Text = $"手动测试 - {deviceName}";
- // 根据设备类型调整UI
- UpdateDeviceTypeUI();
- // 初始化命令库
- InitializeCommandLibrary();
- // 更新连接状态
- UpdateConnectionState(_controller != null);
- if (_controller != null)
- {
- ReadCurrentSettings();
- // ⚠ 不自动启动测量定时器!
- // APS7100 收到任何 SCPI 命令后会自动进入远程模式
- // 用户需要手动点击"恢复测量"按钮来启动定时测量
- // _measureTimer.Start(); // 注释掉,不自动启动
- UpdateMeasureButtonState(false); // 初始状态:测量已暂停
- LogMessage("ℹ 测量已暂停。点击「恢复测量」按钮可开始自动测量。");
- if (_deviceType == DeviceType.APS7100)
- {
- LogMessage("⚠ 注意:启动测量后 APS7100 将自动切换到远程模式");
- }
- }
- else
- {
- UpdateMeasureButtonState(false);
- }
- }
- private void UpdateDeviceTypeUI()
- {
- bool isAC = (_deviceType == DeviceType.APS7100);
- // AC电源独有控件
- lblFrequency.Visible = isAC;
- numFrequency.Visible = isAC;
- btnSetFrequency.Visible = isAC;
- lblWaveform.Visible = isAC;
- cmbWaveform.Visible = isAC;
- lblVoltageRange.Visible = isAC;
- cmbVoltageRange.Visible = isAC;
- // AC电源独有的测量值
- lblFrequencyLabel.Visible = isAC;
- lblFrequencyValue.Visible = isAC;
- lblPFLabel.Visible = isAC;
- lblPFValue.Visible = isAC;
- // 调整电压/电流的范围
- if (isAC)
- {
- numVoltage.Maximum = 350;
- numVoltage.Value = 220;
- numCurrent.Maximum = 20;
- numCurrent.Value = 5;
- lblCurrent.Text = "电流限值(A):";
- }
- else
- {
- numVoltage.Maximum = 72;
- numVoltage.Value = 12;
- numCurrent.Maximum = 4.5m;
- numCurrent.Value = 1;
- lblCurrent.Text = "电流设定(A):";
- }
- }
- private void InitializeCommandLibrary()
- {
- cmbCommandCategory.Items.Clear();
- cmbCommandCategory.Items.Add("全部命令");
- var categories = _deviceType == DeviceType.APS7100
- ? ScpiCommandLibrary.GetCategories()
- : PSW250CommandLibrary.GetCategories();
- foreach (string category in categories)
- {
- cmbCommandCategory.Items.Add(category);
- }
- if (cmbCommandCategory.Items.Count > 0)
- cmbCommandCategory.SelectedIndex = 0;
- }
- private void UpdateConnectionState(bool connected)
- {
- grpControl.Enabled = connected;
- grpMeasure.Enabled = connected;
- grpScpi.Enabled = connected;
- if (!connected)
- {
- lblStatus.Text = "未连接";
- lblStatus.ForeColor = Color.Red;
- }
- else
- {
- lblStatus.Text = "已连接";
- lblStatus.ForeColor = Color.Green;
- }
- }
- /// <summary>
- /// 更新控制器(当主窗体连接/断开设备时调用)
- /// </summary>
- public void UpdateController(IPowerSupplyController? controller)
- {
- _controller = controller;
- UpdateConnectionState(_controller != null);
- if (_controller != null)
- {
- ReadCurrentSettings();
- // ⚠ 不自动启动测量定时器
- // _measureTimer.Start();
- UpdateMeasureButtonState(false);
- }
- else
- {
- _measureTimer.Stop();
- UpdateMeasureButtonState(false);
- }
- }
- private async void ReadCurrentSettings()
- {
- if (_controller == null) return;
- try
- {
- var controller = _controller;
- var deviceType = _deviceType;
-
- // 在后台线程执行读取操作,避免阻塞UI
- // 使用 try-catch 保护每个查询,避免不支持的命令导致整体失败
- var settings = await Task.Run(() =>
- {
- double voltage = 0, frequency = 0, current = 0;
- VoltageRange voltageRange = VoltageRange.Low;
- Waveform waveform = Waveform.Sine;
- bool outputOn = false;
-
- try { voltage = controller.GetVoltage(); } catch { }
- try { frequency = deviceType == DeviceType.APS7100 ? controller.GetFrequency() : 0; } catch { }
- try { current = controller.GetCurrent(); } catch { }
- try { voltageRange = deviceType == DeviceType.APS7100 ? controller.GetVoltageRange() : VoltageRange.Low; } catch { }
- try { waveform = deviceType == DeviceType.APS7100 ? controller.GetWaveform() : Waveform.Sine; } catch { }
- try { outputOn = controller.GetOutputState(); } catch { }
-
- return new
- {
- Voltage = voltage,
- Frequency = frequency,
- Current = current,
- VoltageRange = voltageRange,
- Waveform = waveform,
- OutputOn = outputOn
- };
- });
-
- // 在UI线程更新控件
- numVoltage.Value = (decimal)settings.Voltage;
- if (_deviceType == DeviceType.APS7100)
- {
- numFrequency.Value = (decimal)settings.Frequency;
- cmbVoltageRange.SelectedIndex = settings.VoltageRange == VoltageRange.Low ? 0 : 1;
- cmbWaveform.SelectedIndex = (int)settings.Waveform;
- }
- numCurrent.Value = (decimal)settings.Current;
- chkOutput.Checked = settings.OutputOn;
- }
- catch (Exception ex)
- {
- LogMessage($"读取设置失败: {ex.Message}");
- }
- }
- private async void MeasureTimer_Tick(object? sender, EventArgs e)
- {
- if (_controller == null || _isMeasuring) return;
-
- _isMeasuring = true;
- try
- {
- var controller = _controller;
- var deviceType = _deviceType;
-
- // 在后台线程执行测量操作,避免阻塞UI
- var measurements = await Task.Run(() =>
- {
- var result = new
- {
- Voltage = controller.MeasureVoltage(),
- Current = controller.MeasureCurrent(),
- Power = controller.MeasurePower(),
- Frequency = deviceType == DeviceType.APS7100 ? controller.MeasureFrequency() : 0,
- PowerFactor = deviceType == DeviceType.APS7100 ? controller.MeasurePowerFactor() : 0
- };
- return result;
- });
-
- // 在UI线程更新显示
- lblVoltageValue.Text = $"{measurements.Voltage:F2} V";
- lblCurrentValue.Text = $"{measurements.Current:F3} A";
- lblPowerValue.Text = $"{measurements.Power:F2} W";
- if (_deviceType == DeviceType.APS7100)
- {
- lblFrequencyValue.Text = $"{measurements.Frequency:F2} Hz";
- lblPFValue.Text = $"{measurements.PowerFactor:F3}";
- }
- }
- catch { }
- finally
- {
- _isMeasuring = false;
- }
- }
- #region Control Events
- private void btnSetVoltage_Click(object sender, EventArgs e)
- {
- if (_controller == null) return;
- try
- {
- _controller.SetVoltage((double)numVoltage.Value);
- LogMessage($"设置电压: {numVoltage.Value} V");
- }
- catch (Exception ex) { MessageBox.Show(ex.Message); }
- }
- private void btnSetFrequency_Click(object sender, EventArgs e)
- {
- if (_controller == null) return;
- try
- {
- _controller.SetFrequency((double)numFrequency.Value);
- LogMessage($"设置频率: {numFrequency.Value} Hz");
- }
- catch (Exception ex) { MessageBox.Show(ex.Message); }
- }
- private void btnSetCurrent_Click(object sender, EventArgs e)
- {
- if (_controller == null) return;
- try
- {
- _controller.SetCurrent((double)numCurrent.Value);
- LogMessage($"设置电流: {numCurrent.Value} A");
- }
- catch (Exception ex) { MessageBox.Show(ex.Message); }
- }
- private void cmbVoltageRange_SelectedIndexChanged(object sender, EventArgs e)
- {
- if (_controller == null || cmbVoltageRange.SelectedIndex < 0) return;
- try
- {
- var range = cmbVoltageRange.SelectedIndex == 0 ? VoltageRange.Low : VoltageRange.High;
- _controller.SetVoltageRange(range);
- LogMessage($"设置量程: {range}");
- }
- catch (Exception ex) { MessageBox.Show(ex.Message); }
- }
- private void cmbWaveform_SelectedIndexChanged(object sender, EventArgs e)
- {
- if (_controller == null || cmbWaveform.SelectedIndex < 0) return;
- try
- {
- var wave = (Waveform)cmbWaveform.SelectedIndex;
- _controller.SetWaveform(wave);
- LogMessage($"设置波形: {wave}");
- }
- catch (Exception ex) { MessageBox.Show(ex.Message); }
- }
- private void chkOutput_CheckedChanged(object sender, EventArgs e)
- {
- if (_controller == null) return;
- try
- {
- _controller.SetOutput(chkOutput.Checked);
- chkOutput.Text = chkOutput.Checked ? "输出 ON" : "输出 OFF";
- chkOutput.BackColor = chkOutput.Checked ? Color.LightGreen : SystemColors.Control;
- LogMessage($"输出: {chkOutput.Text}");
- }
- catch { }
- }
- private void btnReset_Click(object sender, EventArgs e)
- {
- if (_controller == null) return;
- if (MessageBox.Show("确定重置?", "确认", MessageBoxButtons.YesNo) == DialogResult.Yes)
- {
- try
- {
- _controller.Reset();
- LogMessage("设备已重置");
- ReadCurrentSettings();
- }
- catch (Exception ex) { MessageBox.Show(ex.Message); }
- }
- }
- #endregion
- #region SCPI Events
- private void cmbCommandCategory_SelectedIndexChanged(object sender, EventArgs e)
- {
- if (cmbCommandCategory.SelectedIndex < 0) return;
- lstCommands.Items.Clear();
- txtCommandDesc.Text = "";
- string? cat = cmbCommandCategory.SelectedItem?.ToString();
- if (cat == null) return;
- var cmds = cat == "全部命令"
- ? (_deviceType == DeviceType.APS7100 ? ScpiCommandLibrary.GetAllCommands() : PSW250CommandLibrary.GetAllCommands())
- : (_deviceType == DeviceType.APS7100 ? ScpiCommandLibrary.GetCommandsByCategory(cat) : PSW250CommandLibrary.GetCommandsByCategory(cat));
- foreach (var c in cmds) lstCommands.Items.Add(c);
- lstCommands.DisplayMember = "Command";
- }
- private void lstCommands_SelectedIndexChanged(object sender, EventArgs e)
- {
- if (lstCommands.SelectedItem is ScpiCommandInfo cmd)
- txtCommandDesc.Text = cmd.FullDescription;
- }
- private void btnUseCommand_Click(object sender, EventArgs e)
- {
- if (lstCommands.SelectedItem is ScpiCommandInfo cmd)
- txtScpiCommand.Text = cmd.Command;
- }
- private async void btnSendCommand_Click(object sender, EventArgs e)
- {
- if (_controller == null) return;
- string cmd = txtScpiCommand.Text.Trim();
- if (string.IsNullOrEmpty(cmd)) return;
-
- // 暂停定时器,避免与手动命令冲突
- _measureTimer.Stop();
-
- // 检测是否是"本地模式"命令
- // APS7100 收到任何 SCPI 命令后都会自动进入远程模式
- // 如果用户发送本地模式命令,就不应该恢复测量定时器
- bool isLocalModeCommand = IsLocalModeCommand(cmd);
-
- try
- {
- // 等待当前测量完成
- while (_isMeasuring)
- {
- await Task.Delay(50);
- }
-
- // 在后台线程执行命令,避免阻塞UI
- var result = await Task.Run(() =>
- {
- if (cmd.EndsWith("?"))
- {
- return new { IsQuery = true, Response = _controller.SendCustomQuery(cmd) };
- }
- else
- {
- _controller.SendCustomCommand(cmd);
- return new { IsQuery = false, Response = "" };
- }
- });
-
- if (result.IsQuery)
- {
- LogMessage($"Send: {cmd}, Resp: {result.Response}");
- }
- else
- {
- LogMessage($"Sent: {cmd}");
- }
-
- // 如果是本地模式命令,提示用户并保持定时器暂停
- if (isLocalModeCommand)
- {
- // 暂停 Modbus 轮询(这是关键!否则 Modbus 服务会继续发送命令)
- OnSuspendModbusPolling?.Invoke();
-
- LogMessage("⚠ 已发送本地模式命令");
- LogMessage(" ✓ 手动测试页测量已暂停");
- LogMessage(" ✓ Modbus 服务轮询已暂停");
- LogMessage(" 设备将保持本地模式,点击「恢复测量」可恢复");
- UpdateMeasureButtonState(false);
- }
- }
- catch (Exception ex)
- {
- LogMessage($"Error: {ex.Message}");
- }
- finally
- {
- // 只有非本地模式命令才恢复定时器
- if (_controller != null && !isLocalModeCommand)
- {
- _measureTimer.Start();
- }
- }
- }
-
- /// <summary>
- /// 检测是否是切换到本地模式的命令
- /// </summary>
- private bool IsLocalModeCommand(string cmd)
- {
- if (string.IsNullOrEmpty(cmd)) return false;
-
- string upperCmd = cmd.ToUpper().Trim();
-
- // 常见的本地模式命令
- return upperCmd.Contains("SYST:LOC") ||
- upperCmd.Contains("SYST:COMM:RLST") && upperCmd.Contains("LOCAL") ||
- upperCmd.Contains("RLSTATE") && upperCmd.Contains("LOCAL") ||
- upperCmd == "GTL"; // IEEE 488.2 Go To Local
- }
-
- /// <summary>
- /// 更新测量按钮状态
- /// </summary>
- private void UpdateMeasureButtonState(bool isMeasuring)
- {
- if (btnToggleMeasure != null)
- {
- btnToggleMeasure.Text = isMeasuring ? "暂停测量" : "恢复测量";
- btnToggleMeasure.BackColor = isMeasuring ? Color.LightCoral : Color.LightGreen;
- }
- }
- #endregion
- private void btnClearLog_Click(object sender, EventArgs e) => txtLog.Clear();
-
- private void btnToggleMeasure_Click(object sender, EventArgs e)
- {
- if (_measureTimer.Enabled)
- {
- // 暂停测量
- _measureTimer.Stop();
- OnSuspendModbusPolling?.Invoke();
- UpdateMeasureButtonState(false);
- LogMessage("✓ 测量已暂停");
- LogMessage(" ✓ Modbus 服务轮询已暂停");
- LogMessage(" 设备将保持本地模式");
- }
- else
- {
- // 恢复测量
- // ⚠ 恢复测量会使 APS7100 自动切换到远程模式
- if (_deviceType == DeviceType.APS7100)
- {
- LogMessage("⚠ 恢复测量后,APS7100 将自动切换到远程模式");
- }
- OnResumeModbusPolling?.Invoke();
- _measureTimer.Start();
- UpdateMeasureButtonState(true);
- LogMessage("✓ 测量已恢复");
- LogMessage(" ✓ Modbus 服务轮询已恢复");
- }
- }
- private void LogMessage(string msg)
- {
- if (this.InvokeRequired)
- {
- this.Invoke(new Action<string>(LogMessage), msg);
- return;
- }
- txtLog.AppendText($"[{DateTime.Now:HH:mm:ss}] {msg}\r\n");
- }
- protected override void OnFormClosing(FormClosingEventArgs e)
- {
- _measureTimer?.Stop();
- base.OnFormClosing(e);
- }
- }
- }
|