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 Label _lblBle;
readonly Label _lblWs;
readonly Label _lblStrength;
readonly Label _lblDeviceName;
readonly TextBox _txtDeviceName;
readonly Button _btnConnect;
@@ -25,10 +24,14 @@ public class MainForm : Form
bool _closingFromTray;
readonly ProgressBar _gaugeA;
readonly ProgressBar _gaugeB;
readonly Label _lblGaugeA;
readonly Label _lblGaugeB;
readonly ProgressBar _gaugeSendA;
readonly ProgressBar _gaugeSendB;
readonly ProgressBar _gaugeRecvA;
readonly ProgressBar _gaugeRecvB;
readonly Label _lblSendA;
readonly Label _lblSendB;
readonly Label _lblRecvA;
readonly Label _lblRecvB;
readonly TrackBar _limitBar;
readonly Label _lblLimit;
readonly CheckBox _chkScale;
@@ -52,7 +55,7 @@ public class MainForm : Form
_loopCts = new CancellationTokenSource();
Text = "Substation";
ClientSize = new Size(360, 340);
ClientSize = new Size(420, 360);
FormBorderStyle = FormBorderStyle.FixedSingle;
MaximizeBox = false;
StartPosition = FormStartPosition.CenterScreen;
@@ -62,7 +65,7 @@ public class MainForm : Form
{
Text = "BLE: searching...",
Location = new Point(16, 16),
Size = new Size(328, 20),
Size = new Size(388, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
};
@@ -70,34 +73,27 @@ public class MainForm : Form
{
Text = "WS: idle",
Location = new Point(16, 40),
Size = new Size(328, 20),
Size = new Size(388, 20),
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
{
Text = "Device:",
Location = new Point(16, 90),
Location = new Point(16, 66),
Size = new Size(48, 20)
};
_txtDeviceName = new TextBox
{
Text = "47L121000",
Location = new Point(68, 88),
Location = new Point(68, 64),
Size = new Size(160, 20)
};
_btnConnect = new Button
{
Text = "Connect",
Location = new Point(236, 88),
Location = new Point(296, 64),
Size = new Size(108, 24)
};
_btnConnect.Click += OnConnect;
@@ -105,7 +101,7 @@ public class MainForm : Form
_btnTest = new Button
{
Text = "Test",
Location = new Point(16, 120),
Location = new Point(16, 96),
Size = new Size(100, 32)
};
_btnTest.Click += OnTest;
@@ -113,7 +109,7 @@ public class MainForm : Form
_btnMusic = new Button
{
Text = "Music",
Location = new Point(130, 120),
Location = new Point(130, 96),
Size = new Size(100, 32)
};
_btnMusic.Click += OnMusic;
@@ -121,7 +117,7 @@ public class MainForm : Form
_btnStop = new Button
{
Text = "Stop All",
Location = new Point(244, 120),
Location = new Point(244, 96),
Size = new Size(100, 32)
};
_btnStop.Click += OnStop;
@@ -129,37 +125,67 @@ public class MainForm : Form
_lblTrack = new Label
{
Text = "",
Location = new Point(16, 158),
Size = new Size(328, 16),
Location = new Point(16, 134),
Size = new Size(388, 16),
ForeColor = Color.DimGray
};
_lblGaugeA = new Label
_lblSendA = new Label
{
Text = "A",
Location = new Point(16, 180),
Size = new Size(16, 20),
Text = "Send A",
Location = new Point(16, 160),
Size = new Size(48, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
};
_gaugeA = new ProgressBar
_gaugeSendA = new ProgressBar
{
Location = new Point(40, 180),
Size = new Size(304, 20),
Location = new Point(72, 160),
Size = new Size(332, 20),
Minimum = 0,
Maximum = 200,
Style = ProgressBarStyle.Continuous
};
_lblGaugeB = new Label
_lblSendB = new Label
{
Text = "B",
Location = new Point(16, 208),
Size = new Size(16, 20),
Text = "Send B",
Location = new Point(16, 184),
Size = new Size(48, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
};
_gaugeB = new ProgressBar
_gaugeSendB = new ProgressBar
{
Location = new Point(40, 208),
Size = new Size(304, 20),
Location = new Point(72, 184),
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,
Maximum = 200,
Style = ProgressBarStyle.Continuous
@@ -168,14 +194,14 @@ public class MainForm : Form
_lblLimit = new Label
{
Text = "Limit: 30",
Location = new Point(16, 248),
Location = new Point(16, 272),
Size = new Size(64, 20),
Font = new Font(Font.FontFamily, 9, FontStyle.Bold)
};
_limitBar = new TrackBar
{
Location = new Point(80, 244),
Size = new Size(180, 45),
Location = new Point(80, 268),
Size = new Size(240, 45),
Minimum = 0,
Maximum = 200,
TickFrequency = 50,
@@ -185,14 +211,14 @@ public class MainForm : Form
_chkScale = new CheckBox
{
Text = "Scale",
Location = new Point(268, 248),
Location = new Point(328, 272),
Size = new Size(76, 24),
Checked = false
};
_chkScale.CheckedChanged += OnLimitChanged;
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
_iconNeutral = CreateVoltageIcon(Color.Gray);
@@ -242,9 +268,9 @@ public class MainForm : Form
{
try
{
var (modeA, valA, modeB, valB, freqA, intA, freqB, intB) = _state.ConsumeTick();
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);
await _device.SendB0(frame);
}
@@ -331,9 +357,10 @@ public class MainForm : Form
_lblBle.Text = _device.IsConnected
? $"BLE: connected ({_device.DeviceName})"
: "BLE: disconnected";
_lblStrength.Text = $"Strength: A={_device.StrengthA} B={_device.StrengthB}";
_gaugeA.Value = Math.Clamp(_device.StrengthA, 0, 200);
_gaugeB.Value = Math.Clamp(_device.StrengthB, 0, 200);
_gaugeSendA.Value = Math.Clamp(_state.LastSentA, 0, 200);
_gaugeSendB.Value = Math.Clamp(_state.LastSentB, 0, 200);
_gaugeRecvA.Value = Math.Clamp(_device.StrengthA, 0, 200);
_gaugeRecvB.Value = Math.Clamp(_device.StrengthB, 0, 200);
_btnTest.Enabled = !_server.HasClient && !IsTestRunning;
_btnMusic.Enabled = !_server.HasClient && !_isMusicRunning;
_btnStop.Enabled = true;
+3
View File
@@ -16,6 +16,7 @@ public class State
public readonly ConcurrentQueue<WaveFrame> StreamB = new();
public int ActualA, ActualB;
public int LastSentA, LastSentB;
public int MaxStrength = 200;
public LimitMode LimitMode = LimitMode.Clamp;
@@ -99,6 +100,8 @@ public class State
: (byte)Math.Clamp(desired, 0, limit);
var valA = ApplyLimit(DesiredA);
var valB = ApplyLimit(DesiredB);
LastSentA = valA;
LastSentB = valB;
DirtyA = false;
DirtyB = false;