Files
HawkeyeVision/Plugins/Siemens/B24SiemensEmulator/MainForm.cs
2025-07-28 09:52:29 +02:00

607 lines
20 KiB
C#

using System;
using System.Drawing;
using System.Windows.Forms;
namespace B24SiemensEmulator
{
public partial class MainForm : Form
{
private GroupBox inputGroupBox;
private GroupBox outputGroupBox;
private GroupBox controlGroupBox;
private GroupBox statusGroupBox;
// Input controls
private CheckBox lifebitCheckBox;
private CheckBox kameraStartCheckBox;
private NumericUpDown materialnummerNumeric;
private NumericUpDown artikelnummerBallNumeric;
private NumericUpDown materialnummerFoilNumeric;
private TextBox chargennummerTextBox;
// Output controls (read-only)
private Label lifebitResponseLabel;
private Label kameraStartResponseLabel;
private Label materialnummerResponseLabel;
private Label artikelnummerBallResponseLabel;
private Label materialnummerFoilResponseLabel;
private Label chargennummerResponseLabel;
// Control buttons
private Button startStopButton;
private Button saveConfigButton;
private Button loadConfigButton;
private Button applyButton;
// Status controls
private Label connectionStatusLabel;
private Label errorMessageLabel;
private bool isRunning = false;
private SiemensTcpClient? tcpClient;
private PLCPacket currentPacket = new PLCPacket();
public MainForm()
{
InitializeComponent();
InitializeTcpClient();
WireUpEventHandlers();
// Initialize current packet with form default values
currentPacket = GetInputPacket();
}
private void InitializeTcpClient()
{
tcpClient = new SiemensTcpClient();
tcpClient.GetPacketToSend = GetCurrentPacket;
tcpClient.ConnectionStatusChanged += OnConnectionStatusChanged;
tcpClient.ResponseReceived += OnResponseReceived;
tcpClient.ErrorOccurred += OnErrorOccurred;
}
private void WireUpEventHandlers()
{
startStopButton.Click += OnStartStopButtonClick;
saveConfigButton.Click += OnSaveConfigButtonClick;
loadConfigButton.Click += OnLoadConfigButtonClick;
applyButton.Click += OnApplyButtonClick;
// Form closing event
this.FormClosing += OnFormClosing;
}
private async void OnStartStopButtonClick(object? sender, EventArgs e)
{
if (tcpClient == null) return;
if (!isRunning)
{
// Start
var connected = await tcpClient.ConnectAsync();
if (connected)
{
tcpClient.StartSending();
SetRunningState(true);
}
}
else
{
// Stop
tcpClient.StopSending();
await tcpClient.DisconnectAsync();
SetRunningState(false);
}
}
private void OnSaveConfigButtonClick(object? sender, EventArgs e)
{
var config = PacketConfiguration.FromPLCPacket(currentPacket);
bool saved = ConfigurationManager.SaveConfiguration(config);
if (saved)
{
MessageBox.Show("Current applied configuration saved successfully.", "Save Complete",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void OnLoadConfigButtonClick(object? sender, EventArgs e)
{
var config = ConfigurationManager.LoadConfiguration();
if (config != null)
{
LoadConfigurationToForm(config);
MessageBox.Show("Configuration loaded successfully. Click Apply to use the loaded values.", "Load Complete",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void OnApplyButtonClick(object? sender, EventArgs e)
{
currentPacket = GetInputPacket();
// Provide visual feedback by briefly changing the button text
applyButton.Text = "Applied!";
applyButton.BackColor = Color.LightGreen;
var timer = new System.Windows.Forms.Timer();
timer.Interval = 1000; // 1 second
timer.Tick += (s, args) =>
{
applyButton.Text = "Apply";
applyButton.BackColor = SystemColors.Control;
timer.Stop();
timer.Dispose();
};
timer.Start();
}
private void LoadConfigurationToForm(PacketConfiguration config)
{
lifebitCheckBox.Checked = config.Lifebit;
kameraStartCheckBox.Checked = config.KameraStart;
materialnummerNumeric.Value = config.Materialnummer;
artikelnummerBallNumeric.Value = config.ArtikelnummerBall;
materialnummerFoilNumeric.Value = config.MaterialnummerFoil;
chargennummerTextBox.Text = config.Chargennummer;
}
private void OnConnectionStatusChanged(bool connected)
{
UpdateConnectionStatus(connected);
if (connected)
{
HideErrorMessage();
}
}
private void OnResponseReceived(PLCPacket packet)
{
UpdateResponseDisplay(packet);
}
private void OnErrorOccurred(string error)
{
ShowErrorMessage(error);
}
private void OnFormClosing(object? sender, FormClosingEventArgs e)
{
tcpClient?.Dispose();
}
private void InitializeComponent()
{
this.SuspendLayout();
// Form properties
this.Text = "B24 Siemens PLC Emulator";
this.Size = new Size(800, 640);
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.StartPosition = FormStartPosition.CenterScreen;
// Status Group Box (Top)
statusGroupBox = new GroupBox
{
Text = "Status",
Location = new Point(12, 12),
Size = new Size(760, 80)
};
connectionStatusLabel = new Label
{
Text = "Disconnected",
Location = new Point(15, 25),
Size = new Size(200, 20),
Font = new Font("Microsoft Sans Serif", 9F, FontStyle.Bold)
};
errorMessageLabel = new Label
{
Text = "",
Location = new Point(15, 50),
Size = new Size(720, 20),
ForeColor = Color.Red,
Font = new Font("Microsoft Sans Serif", 8.25F)
};
statusGroupBox.Controls.Add(connectionStatusLabel);
statusGroupBox.Controls.Add(errorMessageLabel);
// Control Group Box
controlGroupBox = new GroupBox
{
Text = "Controls",
Location = new Point(12, 100),
Size = new Size(760, 60)
};
startStopButton = new Button
{
Text = "Start",
Location = new Point(15, 25),
Size = new Size(100, 30),
UseVisualStyleBackColor = true
};
saveConfigButton = new Button
{
Text = "Save Config",
Location = new Point(130, 25),
Size = new Size(100, 30),
UseVisualStyleBackColor = true
};
loadConfigButton = new Button
{
Text = "Load Config",
Location = new Point(245, 25),
Size = new Size(100, 30),
UseVisualStyleBackColor = true
};
controlGroupBox.Controls.Add(startStopButton);
controlGroupBox.Controls.Add(saveConfigButton);
controlGroupBox.Controls.Add(loadConfigButton);
// Input Group Box (Left Panel)
inputGroupBox = new GroupBox
{
Text = "Input Packet",
Location = new Point(12, 180),
Size = new Size(370, 390)
};
// Output Group Box (Right Panel)
outputGroupBox = new GroupBox
{
Text = "Response Packet",
Location = new Point(400, 180),
Size = new Size(370, 390)
};
CreateInputControls();
CreateOutputControls();
// Add all controls to form
this.Controls.Add(statusGroupBox);
this.Controls.Add(controlGroupBox);
this.Controls.Add(inputGroupBox);
this.Controls.Add(outputGroupBox);
this.ResumeLayout();
}
private void CreateInputControls()
{
int yPos = 30;
int spacing = 45;
// Lifebit
var lifebitLabel = new Label
{
Text = "Lifebit:",
Location = new Point(15, yPos),
Size = new Size(80, 20)
};
lifebitCheckBox = new CheckBox
{
Location = new Point(120, yPos),
Size = new Size(20, 20)
};
inputGroupBox.Controls.Add(lifebitLabel);
inputGroupBox.Controls.Add(lifebitCheckBox);
yPos += spacing;
// KameraStart
var kameraStartLabel = new Label
{
Text = "KameraStart:",
Location = new Point(15, yPos),
Size = new Size(80, 20)
};
kameraStartCheckBox = new CheckBox
{
Location = new Point(120, yPos),
Size = new Size(20, 20)
};
inputGroupBox.Controls.Add(kameraStartLabel);
inputGroupBox.Controls.Add(kameraStartCheckBox);
yPos += spacing;
// Materialnummer
var materialnummerLabel = new Label
{
Text = "Materialnummer:",
Location = new Point(15, yPos),
Size = new Size(100, 20)
};
materialnummerNumeric = new NumericUpDown
{
Location = new Point(120, yPos),
Size = new Size(120, 20),
Minimum = int.MinValue,
Maximum = int.MaxValue
};
inputGroupBox.Controls.Add(materialnummerLabel);
inputGroupBox.Controls.Add(materialnummerNumeric);
yPos += spacing;
// ArtikelnummerBall
var artikelnummerBallLabel = new Label
{
Text = "ArtikelnummerBall:",
Location = new Point(15, yPos),
Size = new Size(100, 20)
};
artikelnummerBallNumeric = new NumericUpDown
{
Location = new Point(120, yPos),
Size = new Size(120, 20),
Minimum = int.MinValue,
Maximum = int.MaxValue
};
inputGroupBox.Controls.Add(artikelnummerBallLabel);
inputGroupBox.Controls.Add(artikelnummerBallNumeric);
yPos += spacing;
// MaterialnummerFoil
var materialnummerFoilLabel = new Label
{
Text = "MaterialnummerFoil:",
Location = new Point(15, yPos),
Size = new Size(100, 20)
};
materialnummerFoilNumeric = new NumericUpDown
{
Location = new Point(120, yPos),
Size = new Size(120, 20),
Minimum = int.MinValue,
Maximum = int.MaxValue
};
inputGroupBox.Controls.Add(materialnummerFoilLabel);
inputGroupBox.Controls.Add(materialnummerFoilNumeric);
yPos += spacing;
// Chargennummer
var chargennummerLabel = new Label
{
Text = "Chargennummer:",
Location = new Point(15, yPos),
Size = new Size(100, 20)
};
chargennummerTextBox = new TextBox
{
Location = new Point(120, yPos),
Size = new Size(120, 20),
MaxLength = 5
};
inputGroupBox.Controls.Add(chargennummerLabel);
inputGroupBox.Controls.Add(chargennummerTextBox);
yPos += spacing;
// Apply button
applyButton = new Button
{
Text = "Apply",
Location = new Point(120, yPos),
Size = new Size(120, 30),
UseVisualStyleBackColor = true,
Font = new Font("Microsoft Sans Serif", 8.25F, FontStyle.Bold)
};
inputGroupBox.Controls.Add(applyButton);
}
private void CreateOutputControls()
{
int yPos = 30;
int spacing = 45;
// Lifebit Response
var lifebitResponseTitle = new Label
{
Text = "Lifebit:",
Location = new Point(15, yPos),
Size = new Size(80, 20)
};
lifebitResponseLabel = new Label
{
Text = "False",
Location = new Point(120, yPos),
Size = new Size(100, 20),
BorderStyle = BorderStyle.FixedSingle,
BackColor = SystemColors.Control
};
outputGroupBox.Controls.Add(lifebitResponseTitle);
outputGroupBox.Controls.Add(lifebitResponseLabel);
yPos += spacing;
// KameraStart Response
var kameraStartResponseTitle = new Label
{
Text = "KameraStart:",
Location = new Point(15, yPos),
Size = new Size(80, 20)
};
kameraStartResponseLabel = new Label
{
Text = "False",
Location = new Point(120, yPos),
Size = new Size(100, 20),
BorderStyle = BorderStyle.FixedSingle,
BackColor = SystemColors.Control
};
outputGroupBox.Controls.Add(kameraStartResponseTitle);
outputGroupBox.Controls.Add(kameraStartResponseLabel);
yPos += spacing;
// Materialnummer Response
var materialnummerResponseTitle = new Label
{
Text = "Materialnummer:",
Location = new Point(15, yPos),
Size = new Size(100, 20)
};
materialnummerResponseLabel = new Label
{
Text = "0",
Location = new Point(120, yPos),
Size = new Size(120, 20),
BorderStyle = BorderStyle.FixedSingle,
BackColor = SystemColors.Control
};
outputGroupBox.Controls.Add(materialnummerResponseTitle);
outputGroupBox.Controls.Add(materialnummerResponseLabel);
yPos += spacing;
// ArtikelnummerBall Response
var artikelnummerBallResponseTitle = new Label
{
Text = "ArtikelnummerBall:",
Location = new Point(15, yPos),
Size = new Size(100, 20)
};
artikelnummerBallResponseLabel = new Label
{
Text = "0",
Location = new Point(120, yPos),
Size = new Size(120, 20),
BorderStyle = BorderStyle.FixedSingle,
BackColor = SystemColors.Control
};
outputGroupBox.Controls.Add(artikelnummerBallResponseTitle);
outputGroupBox.Controls.Add(artikelnummerBallResponseLabel);
yPos += spacing;
// MaterialnummerFoil Response
var materialnummerFoilResponseTitle = new Label
{
Text = "MaterialnummerFoil:",
Location = new Point(15, yPos),
Size = new Size(100, 20)
};
materialnummerFoilResponseLabel = new Label
{
Text = "0",
Location = new Point(120, yPos),
Size = new Size(120, 20),
BorderStyle = BorderStyle.FixedSingle,
BackColor = SystemColors.Control
};
outputGroupBox.Controls.Add(materialnummerFoilResponseTitle);
outputGroupBox.Controls.Add(materialnummerFoilResponseLabel);
yPos += spacing;
// Chargennummer Response
var chargennummerResponseTitle = new Label
{
Text = "Chargennummer:",
Location = new Point(15, yPos),
Size = new Size(100, 20)
};
chargennummerResponseLabel = new Label
{
Text = "",
Location = new Point(120, yPos),
Size = new Size(120, 20),
BorderStyle = BorderStyle.FixedSingle,
BackColor = SystemColors.Control
};
outputGroupBox.Controls.Add(chargennummerResponseTitle);
outputGroupBox.Controls.Add(chargennummerResponseLabel);
}
public PLCPacket GetInputPacket()
{
return new PLCPacket
{
Lifebit = lifebitCheckBox.Checked,
KameraStart = kameraStartCheckBox.Checked,
Materialnummer = (int)materialnummerNumeric.Value,
ArtikelnummerBall = (int)artikelnummerBallNumeric.Value,
MaterialnummerFoil = (int)materialnummerFoilNumeric.Value,
Chargennummer = chargennummerTextBox.Text
};
}
public PLCPacket GetCurrentPacket()
{
return currentPacket;
}
public void UpdateResponseDisplay(PLCPacket packet)
{
if (InvokeRequired)
{
Invoke(new Action<PLCPacket>(UpdateResponseDisplay), packet);
return;
}
lifebitResponseLabel.Text = packet.Lifebit.ToString();
kameraStartResponseLabel.Text = packet.KameraStart.ToString();
materialnummerResponseLabel.Text = packet.Materialnummer.ToString();
artikelnummerBallResponseLabel.Text = packet.ArtikelnummerBall.ToString();
materialnummerFoilResponseLabel.Text = packet.MaterialnummerFoil.ToString();
chargennummerResponseLabel.Text = packet.Chargennummer;
}
public void UpdateConnectionStatus(bool connected)
{
if (InvokeRequired)
{
Invoke(new Action<bool>(UpdateConnectionStatus), connected);
return;
}
connectionStatusLabel.Text = connected ? "Connected" : "Disconnected";
connectionStatusLabel.ForeColor = connected ? Color.Green : Color.Red;
}
public void ShowErrorMessage(string message)
{
if (InvokeRequired)
{
Invoke(new Action<string>(ShowErrorMessage), message);
return;
}
errorMessageLabel.Text = message;
}
public void HideErrorMessage()
{
if (InvokeRequired)
{
Invoke(new Action(HideErrorMessage));
return;
}
errorMessageLabel.Text = "";
}
// Event handlers will be wired up later
public Button StartStopButton => startStopButton;
public Button SaveConfigButton => saveConfigButton;
public Button LoadConfigButton => loadConfigButton;
public bool IsRunning => isRunning;
public void SetRunningState(bool running)
{
isRunning = running;
startStopButton.Text = running ? "Stop" : "Start";
}
}
}