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(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(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(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"; } } }