Add Send/Recv gauges, fix tick loop to consume without BLE

- Four gauges: Send A/B (commanded) and Recv A/B (device-reported)
- State.LastSentA/B tracks what would be sent after limiting
- ConsumeTick always runs; only SendB0 gated on IsConnected
- Stream queues drain correctly in dev mode (no box)
- Tray icon hot state works without BLE connected
- Removed strength text label, widened form to 420x360
This commit is contained in:
2026-08-08 11:03:44 +00:00
parent 4ae5c397fd
commit 612385af7f
2 changed files with 76 additions and 46 deletions
+73 -46
View File
@@ -14,7 +14,6 @@ public class MainForm : Form
readonly NotifyIcon _tray; readonly NotifyIcon _tray;
readonly Label _lblBle; readonly Label _lblBle;
readonly Label _lblWs; readonly Label _lblWs;
readonly Label _lblStrength;
readonly Label _lblDeviceName; readonly Label _lblDeviceName;
readonly TextBox _txtDeviceName; readonly TextBox _txtDeviceName;
readonly Button _btnConnect; readonly Button _btnConnect;
@@ -25,10 +24,14 @@ public class MainForm : Form
bool _closingFromTray; bool _closingFromTray;
readonly ProgressBar _gaugeA; readonly ProgressBar _gaugeSendA;
readonly ProgressBar _gaugeB; readonly ProgressBar _gaugeSendB;
readonly Label _lblGaugeA; readonly ProgressBar _gaugeRecvA;
readonly Label _lblGaugeB; readonly ProgressBar _gaugeRecvB;
readonly Label _lblSendA;
readonly Label _lblSendB;
readonly Label _lblRecvA;
readonly Label _lblRecvB;
readonly TrackBar _limitBar; readonly TrackBar _limitBar;
readonly Label _lblLimit; readonly Label _lblLimit;
readonly CheckBox _chkScale; readonly CheckBox _chkScale;
@@ -52,7 +55,7 @@ public class MainForm : Form
_loopCts = new CancellationTokenSource(); _loopCts = new CancellationTokenSource();
Text = "Substation"; Text = "Substation";
ClientSize = new Size(360, 340); ClientSize = new Size(420, 360);
FormBorderStyle = FormBorderStyle.FixedSingle; FormBorderStyle = FormBorderStyle.FixedSingle;
MaximizeBox = false; MaximizeBox = false;
StartPosition = FormStartPosition.CenterScreen; StartPosition = FormStartPosition.CenterScreen;
@@ -62,7 +65,7 @@ public class MainForm : Form
{ {
Text = "BLE: searching...", Text = "BLE: searching...",
Location = new Point(16, 16), Location = new Point(16, 16),
Size = new Size(328, 20), Size = new Size(388, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold) Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
}; };
@@ -70,34 +73,27 @@ public class MainForm : Form
{ {
Text = "WS: idle", Text = "WS: idle",
Location = new Point(16, 40), Location = new Point(16, 40),
Size = new Size(328, 20), Size = new Size(388, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold) Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
}; };
_lblStrength = new Label
{
Text = "Strength: A=0 B=0",
Location = new Point(16, 64),
Size = new Size(328, 20)
};
_lblDeviceName = new Label _lblDeviceName = new Label
{ {
Text = "Device:", Text = "Device:",
Location = new Point(16, 90), Location = new Point(16, 66),
Size = new Size(48, 20) Size = new Size(48, 20)
}; };
_txtDeviceName = new TextBox _txtDeviceName = new TextBox
{ {
Text = "47L121000", Text = "47L121000",
Location = new Point(68, 88), Location = new Point(68, 64),
Size = new Size(160, 20) Size = new Size(160, 20)
}; };
_btnConnect = new Button _btnConnect = new Button
{ {
Text = "Connect", Text = "Connect",
Location = new Point(236, 88), Location = new Point(296, 64),
Size = new Size(108, 24) Size = new Size(108, 24)
}; };
_btnConnect.Click += OnConnect; _btnConnect.Click += OnConnect;
@@ -105,7 +101,7 @@ public class MainForm : Form
_btnTest = new Button _btnTest = new Button
{ {
Text = "Test", Text = "Test",
Location = new Point(16, 120), Location = new Point(16, 96),
Size = new Size(100, 32) Size = new Size(100, 32)
}; };
_btnTest.Click += OnTest; _btnTest.Click += OnTest;
@@ -113,7 +109,7 @@ public class MainForm : Form
_btnMusic = new Button _btnMusic = new Button
{ {
Text = "Music", Text = "Music",
Location = new Point(130, 120), Location = new Point(130, 96),
Size = new Size(100, 32) Size = new Size(100, 32)
}; };
_btnMusic.Click += OnMusic; _btnMusic.Click += OnMusic;
@@ -121,7 +117,7 @@ public class MainForm : Form
_btnStop = new Button _btnStop = new Button
{ {
Text = "Stop All", Text = "Stop All",
Location = new Point(244, 120), Location = new Point(244, 96),
Size = new Size(100, 32) Size = new Size(100, 32)
}; };
_btnStop.Click += OnStop; _btnStop.Click += OnStop;
@@ -129,37 +125,67 @@ public class MainForm : Form
_lblTrack = new Label _lblTrack = new Label
{ {
Text = "", Text = "",
Location = new Point(16, 158), Location = new Point(16, 134),
Size = new Size(328, 16), Size = new Size(388, 16),
ForeColor = Color.DimGray ForeColor = Color.DimGray
}; };
_lblGaugeA = new Label _lblSendA = new Label
{ {
Text = "A", Text = "Send A",
Location = new Point(16, 180), Location = new Point(16, 160),
Size = new Size(16, 20), Size = new Size(48, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold) Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
}; };
_gaugeA = new ProgressBar _gaugeSendA = new ProgressBar
{ {
Location = new Point(40, 180), Location = new Point(72, 160),
Size = new Size(304, 20), Size = new Size(332, 20),
Minimum = 0, Minimum = 0,
Maximum = 200, Maximum = 200,
Style = ProgressBarStyle.Continuous Style = ProgressBarStyle.Continuous
}; };
_lblGaugeB = new Label _lblSendB = new Label
{ {
Text = "B", Text = "Send B",
Location = new Point(16, 208), Location = new Point(16, 184),
Size = new Size(16, 20), Size = new Size(48, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold) Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
}; };
_gaugeB = new ProgressBar _gaugeSendB = new ProgressBar
{ {
Location = new Point(40, 208), Location = new Point(72, 184),
Size = new Size(304, 20), Size = new Size(332, 20),
Minimum = 0,
Maximum = 200,
Style = ProgressBarStyle.Continuous
};
_lblRecvA = new Label
{
Text = "Recv A",
Location = new Point(16, 212),
Size = new Size(48, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
};
_gaugeRecvA = new ProgressBar
{
Location = new Point(72, 212),
Size = new Size(332, 20),
Minimum = 0,
Maximum = 200,
Style = ProgressBarStyle.Continuous
};
_lblRecvB = new Label
{
Text = "Recv B",
Location = new Point(16, 236),
Size = new Size(48, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
};
_gaugeRecvB = new ProgressBar
{
Location = new Point(72, 236),
Size = new Size(332, 20),
Minimum = 0, Minimum = 0,
Maximum = 200, Maximum = 200,
Style = ProgressBarStyle.Continuous Style = ProgressBarStyle.Continuous
@@ -168,14 +194,14 @@ public class MainForm : Form
_lblLimit = new Label _lblLimit = new Label
{ {
Text = "Limit: 30", Text = "Limit: 30",
Location = new Point(16, 248), Location = new Point(16, 272),
Size = new Size(64, 20), Size = new Size(64, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold) Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
}; };
_limitBar = new TrackBar _limitBar = new TrackBar
{ {
Location = new Point(80, 244), Location = new Point(80, 268),
Size = new Size(180, 45), Size = new Size(240, 45),
Minimum = 0, Minimum = 0,
Maximum = 200, Maximum = 200,
TickFrequency = 50, TickFrequency = 50,
@@ -185,14 +211,14 @@ public class MainForm : Form
_chkScale = new CheckBox _chkScale = new CheckBox
{ {
Text = "Scale", Text = "Scale",
Location = new Point(268, 248), Location = new Point(328, 272),
Size = new Size(76, 24), Size = new Size(76, 24),
Checked = false Checked = false
}; };
_chkScale.CheckedChanged += OnLimitChanged; _chkScale.CheckedChanged += OnLimitChanged;
OnLimitChanged(null, EventArgs.Empty); OnLimitChanged(null, EventArgs.Empty);
Controls.AddRange(new Control[] { _lblBle, _lblWs, _lblStrength, _lblDeviceName, _txtDeviceName, _btnConnect, _btnTest, _btnMusic, _btnStop, _lblTrack, _lblGaugeA, _gaugeA, _lblGaugeB, _gaugeB, _lblLimit, _limitBar, _chkScale }); Controls.AddRange(new Control[] { _lblBle, _lblWs, _lblDeviceName, _txtDeviceName, _btnConnect, _btnTest, _btnMusic, _btnStop, _lblTrack, _lblSendA, _gaugeSendA, _lblSendB, _gaugeSendB, _lblRecvA, _gaugeRecvA, _lblRecvB, _gaugeRecvB, _lblLimit, _limitBar, _chkScale });
// Tray icon — three cached variants: neutral=gray, active=gold, hot=red-orange // Tray icon — three cached variants: neutral=gray, active=gold, hot=red-orange
_iconNeutral = CreateVoltageIcon(Color.Gray); _iconNeutral = CreateVoltageIcon(Color.Gray);
@@ -242,9 +268,9 @@ public class MainForm : Form
{ {
try try
{ {
var (modeA, valA, modeB, valB, freqA, intA, freqB, intB) = _state.ConsumeTick();
if (_device.IsConnected) if (_device.IsConnected)
{ {
var (modeA, valA, modeB, valB, freqA, intA, freqB, intB) = _state.ConsumeTick();
var frame = B0.Build(0, modeA, modeB, valA, valB, freqA, intA, freqB, intB); var frame = B0.Build(0, modeA, modeB, valA, valB, freqA, intA, freqB, intB);
await _device.SendB0(frame); await _device.SendB0(frame);
} }
@@ -331,9 +357,10 @@ public class MainForm : Form
_lblBle.Text = _device.IsConnected _lblBle.Text = _device.IsConnected
? $"BLE: connected ({_device.DeviceName})" ? $"BLE: connected ({_device.DeviceName})"
: "BLE: disconnected"; : "BLE: disconnected";
_lblStrength.Text = $"Strength: A={_device.StrengthA} B={_device.StrengthB}"; _gaugeSendA.Value = Math.Clamp(_state.LastSentA, 0, 200);
_gaugeA.Value = Math.Clamp(_device.StrengthA, 0, 200); _gaugeSendB.Value = Math.Clamp(_state.LastSentB, 0, 200);
_gaugeB.Value = Math.Clamp(_device.StrengthB, 0, 200); _gaugeRecvA.Value = Math.Clamp(_device.StrengthA, 0, 200);
_gaugeRecvB.Value = Math.Clamp(_device.StrengthB, 0, 200);
_btnTest.Enabled = !_server.HasClient && !IsTestRunning; _btnTest.Enabled = !_server.HasClient && !IsTestRunning;
_btnMusic.Enabled = !_server.HasClient && !_isMusicRunning; _btnMusic.Enabled = !_server.HasClient && !_isMusicRunning;
_btnStop.Enabled = true; _btnStop.Enabled = true;
+3
View File
@@ -16,6 +16,7 @@ public class State
public readonly ConcurrentQueue<WaveFrame> StreamB = new(); public readonly ConcurrentQueue<WaveFrame> StreamB = new();
public int ActualA, ActualB; public int ActualA, ActualB;
public int LastSentA, LastSentB;
public int MaxStrength = 200; public int MaxStrength = 200;
public LimitMode LimitMode = LimitMode.Clamp; public LimitMode LimitMode = LimitMode.Clamp;
@@ -99,6 +100,8 @@ public class State
: (byte)Math.Clamp(desired, 0, limit); : (byte)Math.Clamp(desired, 0, limit);
var valA = ApplyLimit(DesiredA); var valA = ApplyLimit(DesiredA);
var valB = ApplyLimit(DesiredB); var valB = ApplyLimit(DesiredB);
LastSentA = valA;
LastSentB = valB;
DirtyA = false; DirtyA = false;
DirtyB = false; DirtyB = false;