From cce7b2295c0146f6cd6c8ed2b8e369e88a24e01e Mon Sep 17 00:00:00 2001 From: nikzori Date: Tue, 21 Jan 2025 14:38:59 +0300 Subject: [PATCH] bro how tf did I make this work before --- Datasheet.Designer.cs | 170 +++++++++++++++++++++--------------------- Datasheet.cs | 73 +++++++++++++++--- Main.cs | 138 +++++++++++++++++++++++++++------- Model.cs | 72 +++++------------- 4 files changed, 277 insertions(+), 176 deletions(-) diff --git a/Datasheet.Designer.cs b/Datasheet.Designer.cs index 000d59c..961fc21 100644 --- a/Datasheet.Designer.cs +++ b/Datasheet.Designer.cs @@ -39,16 +39,16 @@ this.label2 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label(); this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.labelCleaning = new System.Windows.Forms.Label(); + this.buttonCleaning = new System.Windows.Forms.Button(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.button2 = new System.Windows.Forms.Button(); + this.buttonAlarm = new System.Windows.Forms.Button(); + this.buttonValve = new System.Windows.Forms.Button(); this.labelValve = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label(); - this.buttonValve = new System.Windows.Forms.Button(); - this.buttonAlarm = new System.Windows.Forms.Button(); - this.button2 = new System.Windows.Forms.Button(); - this.label5 = new System.Windows.Forms.Label(); - this.label6 = new System.Windows.Forms.Label(); - this.label7 = new System.Windows.Forms.Label(); - this.buttonCleaning = new System.Windows.Forms.Button(); - this.label8 = new System.Windows.Forms.Label(); this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); this.label9 = new System.Windows.Forms.Label(); this.label10 = new System.Windows.Forms.Label(); @@ -84,6 +84,7 @@ this.buttonPoll.TabIndex = 7; this.buttonPoll.Text = "Опрос"; this.buttonPoll.UseVisualStyleBackColor = true; + this.buttonPoll.Click += new System.EventHandler(this.buttonPoll_Click); // // buttonSetID // @@ -149,7 +150,7 @@ // // groupBox2 // - this.groupBox2.Controls.Add(this.label8); + this.groupBox2.Controls.Add(this.labelCleaning); this.groupBox2.Controls.Add(this.buttonCleaning); this.groupBox2.Controls.Add(this.label7); this.groupBox2.Controls.Add(this.label6); @@ -166,6 +167,81 @@ this.groupBox2.TabStop = false; this.groupBox2.Text = "Общее"; // + // labelCleaning + // + this.labelCleaning.AutoSize = true; + this.labelCleaning.Location = new System.Drawing.Point(52, 78); + this.labelCleaning.Name = "labelCleaning"; + this.labelCleaning.Size = new System.Drawing.Size(33, 13); + this.labelCleaning.TabIndex = 9; + this.labelCleaning.Text = "выкл"; + // + // buttonCleaning + // + this.buttonCleaning.Location = new System.Drawing.Point(192, 73); + this.buttonCleaning.Name = "buttonCleaning"; + this.buttonCleaning.Size = new System.Drawing.Size(73, 23); + this.buttonCleaning.TabIndex = 8; + this.buttonCleaning.Text = "Включить"; + this.buttonCleaning.UseVisualStyleBackColor = true; + this.buttonCleaning.Click += new System.EventHandler(this.buttonCleaning_Click); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(6, 78); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(48, 13); + this.label7.TabIndex = 7; + this.label7.Text = "Уборка:"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(61, 48); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(24, 13); + this.label6.TabIndex = 6; + this.label6.Text = "нет"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(6, 48); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(58, 13); + this.label5.TabIndex = 5; + this.label5.Text = "Протечка:"; + // + // button2 + // + this.button2.Location = new System.Drawing.Point(271, 14); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(73, 52); + this.button2.TabIndex = 4; + this.button2.Text = "Аварийное открытие"; + this.button2.UseVisualStyleBackColor = true; + // + // buttonAlarm + // + this.buttonAlarm.Location = new System.Drawing.Point(192, 43); + this.buttonAlarm.Name = "buttonAlarm"; + this.buttonAlarm.Size = new System.Drawing.Size(73, 23); + this.buttonAlarm.TabIndex = 3; + this.buttonAlarm.Text = "Авария"; + this.buttonAlarm.UseVisualStyleBackColor = true; + this.buttonAlarm.Click += new System.EventHandler(this.buttonAlarm_Click); + // + // buttonValve + // + this.buttonValve.Location = new System.Drawing.Point(192, 14); + this.buttonValve.Name = "buttonValve"; + this.buttonValve.Size = new System.Drawing.Size(73, 23); + this.buttonValve.TabIndex = 2; + this.buttonValve.Text = "Закрыть"; + this.buttonValve.UseVisualStyleBackColor = true; + this.buttonValve.Click += new System.EventHandler(this.buttonValve_Click); + // // labelValve // this.labelValve.AutoSize = true; @@ -184,80 +260,6 @@ this.label4.TabIndex = 0; this.label4.Text = "Кран:"; // - // buttonValve - // - this.buttonValve.Location = new System.Drawing.Point(192, 14); - this.buttonValve.Name = "buttonValve"; - this.buttonValve.Size = new System.Drawing.Size(73, 23); - this.buttonValve.TabIndex = 2; - this.buttonValve.Text = "Закрыть"; - this.buttonValve.UseVisualStyleBackColor = true; - this.buttonValve.Click += new System.EventHandler(this.buttonValve_Click); - // - // buttonAlarm - // - this.buttonAlarm.Location = new System.Drawing.Point(192, 43); - this.buttonAlarm.Name = "buttonAlarm"; - this.buttonAlarm.Size = new System.Drawing.Size(73, 23); - this.buttonAlarm.TabIndex = 3; - this.buttonAlarm.Text = "Авария"; - this.buttonAlarm.UseVisualStyleBackColor = true; - this.buttonAlarm.Click += new System.EventHandler(this.buttonAlarm_Click); - // - // button2 - // - this.button2.Location = new System.Drawing.Point(271, 14); - this.button2.Name = "button2"; - this.button2.Size = new System.Drawing.Size(73, 52); - this.button2.TabIndex = 4; - this.button2.Text = "Аварийное открытие"; - this.button2.UseVisualStyleBackColor = true; - // - // label5 - // - this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(6, 48); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(58, 13); - this.label5.TabIndex = 5; - this.label5.Text = "Протечка:"; - // - // label6 - // - this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(61, 48); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(24, 13); - this.label6.TabIndex = 6; - this.label6.Text = "нет"; - // - // label7 - // - this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(6, 78); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(48, 13); - this.label7.TabIndex = 7; - this.label7.Text = "Уборка:"; - // - // buttonCleaning - // - this.buttonCleaning.Location = new System.Drawing.Point(192, 73); - this.buttonCleaning.Name = "buttonCleaning"; - this.buttonCleaning.Size = new System.Drawing.Size(73, 23); - this.buttonCleaning.TabIndex = 8; - this.buttonCleaning.Text = "Включить"; - this.buttonCleaning.UseVisualStyleBackColor = true; - // - // label8 - // - this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(52, 78); - this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(33, 13); - this.label8.TabIndex = 9; - this.label8.Text = "выкл"; - // // flowLayoutPanel1 // this.flowLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) @@ -339,7 +341,7 @@ private System.Windows.Forms.Label label5; private System.Windows.Forms.Button button2; private System.Windows.Forms.Button buttonAlarm; - private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label labelCleaning; private System.Windows.Forms.Button buttonCleaning; private System.Windows.Forms.Label label7; private System.Windows.Forms.Label label6; diff --git a/Datasheet.cs b/Datasheet.cs index 7944bbc..7c644b1 100644 --- a/Datasheet.cs +++ b/Datasheet.cs @@ -20,10 +20,18 @@ namespace Gidrolock_Modbus_Scanner byte modbusID; Device device; + byte[] message; + byte[] data; + EventHandler handler; + SerialPort port = Modbus.port; bool isPolling = false; bool isAwaitingResponse = false; - byte[] message = new byte[255]; + + + bool isValveClosed = false; + bool alarmStatus = false; + bool cleaningStatus = false; public Datasheet(byte modbusID, Device device) { @@ -31,33 +39,80 @@ namespace Gidrolock_Modbus_Scanner nudModbusID.Maximum = 246; this.modbusID = modbusID; this.device = device; + + if (!device.hasCleaningMode) + { + labelCleaning.Text = "Недоступна."; + buttonCleaning.Enabled = false; + } + + handler = (sndr, msg) => + { + message = msg.Message; + data = msg.Data; + }; + } + private async void buttonPoll_Click(object sender, EventArgs e) + { + // hardcoded for now, probably easier to keep it like this in the future + if (await PollEntry(device.valveStatus)) + { + if (data.Last() > 0) + labelValve.Text = "Закрыт"; + else labelValve.Text = "Открыт"; + } + } + + async Task PollEntry(Entry entry) + { + var send = Modbus.ReadRegAsync(modbusID, (FunctionCode)entry.registerType, entry.address, entry.length); + isAwaitingResponse = true; + + Task delay = Task.WhenAny(Task.Delay(2000), Task.Run(() => { while (isAwaitingResponse) { } return true; })).ContinueWith((t) => + { + if (isAwaitingResponse) + { + Console.WriteLine("Response timed out."); + isAwaitingResponse = false; + } + return false; + }); + + return await delay; + } private async void buttonSetID_Click(object sender, EventArgs e) { Modbus.WriteSingleAsync(FunctionCode.WriteRegister, modbusID, 200, (byte)nudModbusID.Value); - byte[] data = null; - Modbus.ResponseReceived += (sndr, msg) => - { - data = msg.Data; - }; + await Task.Run(() => { while (data is null) { continue; } if (message[1] > 0x10) //exception code check return; - + this.modbusID = data[1]; //no exception, can just take the byte + message = null; + data = null; }); + } private void buttonValve_Click(object sender, EventArgs e) { - + ushort value = isValveClosed ? (ushort)0 : (ushort)1; + Modbus.WriteSingleAsync((FunctionCode)device.valveStatus.registerType, modbusID, device.valveStatus.address, value); } private void buttonAlarm_Click(object sender, EventArgs e) { - + ushort value = alarmStatus ? (ushort)0 : (ushort)1; + Modbus.WriteSingleAsync((FunctionCode)device.valveStatus.registerType, modbusID, device.alarmStatus.address, value); } + + private void buttonCleaning_Click(object sender, EventArgs e) + { + + } } } \ No newline at end of file diff --git a/Main.cs b/Main.cs index ace4d81..45c4a1b 100644 --- a/Main.cs +++ b/Main.cs @@ -19,8 +19,14 @@ namespace Gidrolock_Modbus_Scanner public byte[] latestMessage; public Dictionary models = new Dictionary(); + + byte[] message = null; + byte[] data = null; - DateTime dateTime; + + DateTime dateTime; + + Datasheet datasheet; #region Initialization public App() { @@ -32,8 +38,8 @@ namespace Gidrolock_Modbus_Scanner TextBox_Log.Text = "Приложение готово к работе."; cBoxDevice.Items.Add("Standard"); - cBoxDevice.Items.Add("Premium Plus"); cBoxDevice.Items.Add("Inteli"); + cBoxDevice.Items.Add("Premium Plus"); cBoxDevice.Items.Add("Premium"); cBoxDevice.SelectedIndex = 0; @@ -44,8 +50,8 @@ namespace Gidrolock_Modbus_Scanner UpDown_ModbusID.Maximum = 247; models.Add("Standard", "STW485"); - models.Add("Premuim Plus", "BUP485"); models.Add("Inteli", "INTELI"); + models.Add("Premuim Plus", "BUP485"); models.Add("Premium", "BUP485"); /* - Version Check - */ @@ -53,6 +59,12 @@ namespace Gidrolock_Modbus_Scanner System.Diagnostics.FileVersionInfo fvi = System.Diagnostics.FileVersionInfo.GetVersionInfo(assembly.Location); string version = fvi.FileVersion; Console.WriteLine("Version: " + version); + + Modbus.ResponseReceived += (sndr, msg) => + { + message = msg.Message; + data = msg.Data; + }; } void App_FormClosed(object sender, FormClosedEventArgs e) @@ -108,62 +120,89 @@ namespace Gidrolock_Modbus_Scanner // if matching model is found, instantiate device window // setup event listener - byte[] message = null; - byte[] data = null; - Modbus.ResponseReceived += (sndr, msg) => - { - message = msg.Message; - data = msg.Data; - }; + // send message AddLog("Проверка модели устройства."); - byte id = (byte)UpDown_ModbusID.Value; - Modbus.ReadRegAsync(id, FunctionCode.ReadInput, 200, 6); - await Task.Run(() => + if (await PollModel()) { - while (message is null) { continue; } - - if (message[1] > 0x10) //exception code check - return; - + Console.WriteLine("true"); // confirm the model string response = ByteArrayToUnicode(data); if (response != models[cBoxDevice.SelectedItem.ToString()]) { // response doesn't match expected model + AddLog("Ответ устройства не соответствует выбранной модели. Поиск подходящей модели."); // check whether it matches anything else, offer to open that model if it does string match = ""; + string model = ""; + int index = 0; foreach (string key in models.Keys) { if (models[key] == response) + { match = models[key]; + model = key; + break; + } + index++; } - // if no matches found, - if (match == "") + + if (match == "") // if no matches found + MessageBox.Show("Подключенное устройство не соответствует ни одной из поддерживаемых моделей."); + + else // match found, offer to switch to that model instead { - // report unknown device - } - else - { - // offer to switch to that model instead - // instantiate panel + DialogResult result = MessageBox.Show(("Подключенное устройство соответствует модели " + model + ". Нажмите ОК, чтобы открыть настройки для модели " + model), "Внимание", MessageBoxButtons.OKCancel); + if (result == DialogResult.OK) + { + // instantiate panel + AddLog("Открываю панель конфигурации."); + + Device device = GetDevice((DeviceType)index); + StartDatasheet(device); + } } } else { // model is correct, instantiate config panel + int index = cBoxDevice.SelectedIndex; + AddLog("Устройство соответстует модели, открываю панель конфигурации."); + Device device = GetDevice((DeviceType)index); + StartDatasheet(device); } - }); + } } catch (Exception ex) { MessageBox.Show(ex.Message); } } + async Task PollModel() + { + var send = Modbus.ReadRegAsync((byte)UpDown_ModbusID.Value, FunctionCode.ReadInput, 200, 6); + isAwaitingResponse = true; + Task delay = Task.WhenAny(Task.Delay(2000), Task.Run(() => { while (isAwaitingResponse) { } return true; })).ContinueWith((t) => + { + if (isAwaitingResponse) + { + Console.WriteLine("Response timed out."); + isAwaitingResponse = false; + } + return false; + }); + + return await delay; + } + void StartDatasheet(Device device) + { + datasheet = new Datasheet((byte)UpDown_ModbusID.Value, device); + datasheet.Show(); + } void CBox_Ports_Click(object sender, EventArgs e) @@ -292,8 +331,51 @@ namespace Gidrolock_Modbus_Scanner break; } } + + public Device GetDevice(DeviceType dt) + { + Device d = new Device(); + switch (dt) + { + case DeviceType.Standard: + d.modelName = "Standard"; + d.name = "Gidrolock Standard Wi-Fi RS485"; + d.id = 30; + d.modelName = "STW485"; + + d.valveStatus = new Entry(RegisterType.Coil, 1202); + d.alarmStatus = new Entry(RegisterType.Coil, 1201); + + d.hasCleaningMode = true; + d.cleaningMode = new Entry(RegisterType.Coil, 3); + + d.hasBattery = false; + + d.wiredSensors = 2; + d.hasScenarioSensor = true; + d.sensorsAlarm = new Entry(RegisterType.Discrete, 1343, 24); + + d.radioStatus = new Entry(RegisterType.Input, 1215, 21); + + break; + case DeviceType.Inteli: + d.modelName = "Inteli"; + break; + case DeviceType.PremiumPlus: + d.modelName = "Premium Plus"; + break; + case DeviceType.Premium: + d.modelName = "Premium"; + break; + default: + break; + + } + return d; + } } } public enum FunctionCode { ReadCoil = 1, ReadDiscrete = 2, ReadHolding = 3, ReadInput = 4, WriteCoil = 5, WriteRegister = 6, WriteMultCoils = 15, WriteMultRegisters = 16 }; -public enum SelectedPath { File, Folder }; +//public enum SelectedPath { File, Folder }; +public enum DeviceType { Standard, Inteli, PremiumPlus, Premium }; diff --git a/Model.cs b/Model.cs index 32180e4..3e6af8e 100644 --- a/Model.cs +++ b/Model.cs @@ -1,82 +1,44 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; - namespace Gidrolock_Modbus_Scanner { - public class Device : + public class Device { public string name; public byte id; public string modelName; - public List entries; - public Device(string name, string modelName) - { - this.name = name; - } + public Entry valveStatus; + public Entry alarmStatus; - } + public bool hasCleaningMode; + public Entry cleaningMode; - public interface IHasWiredSensors - { - Entry GetAlarmStatuses(); - Entry GetSignalLoss(); - } - public interface IHasWirelessSensors - { - Entry GetWirelessSensors(); - Entry GetSensors(); - } - public interface IHasEmergencyOpen - { - void EmergencyOpen(); + public bool hasBattery; + public Entry batteryCharge; + public Entry batteryUsed; // питание от баттареи/электросети для устройств с баттареями + + public int wiredSensors; + public bool hasScenarioSensor; + public Entry sensorsAlarm; + + public Entry wiredLineBreak; + + public Entry radioStatus; } public struct Entry { - public string name; public RegisterType registerType; public ushort address; public ushort length; - public string dataType; - public List labels; - public Dictionary valueParse; - public bool readOnce; - public bool isModbusID; - public Entry(string name, RegisterType registerType, ushort address, ushort length = 1, string dataType = "uint16", List labels = null, Dictionary valueParse = null, bool readOnce = false, bool isModbusID = false) + public Entry(RegisterType registerType, ushort address, ushort length = 1) { - this.name = name; this.registerType = registerType; this.address = address; this.length = length; - this.dataType = dataType; - this.labels = labels; - this.valueParse = valueParse; - - this.readOnce = readOnce; - this.isModbusID = isModbusID; - } - } - public struct CheckEntry - { - public RegisterType registerType; - public ushort address; - public ushort length; - public string dataType; - public string expectedValue; - public CheckEntry(RegisterType registerType, ushort address, ushort length, string dataType, string expectedValue) - { - this.registerType = registerType; - this.address = address; - this.length = length; - this.dataType = dataType; - this.expectedValue = expectedValue; } } public enum RegisterType { Coil = 1, Discrete = 2, Holding = 3, Input = 4}