diff --git a/Datasheet.cs b/Datasheet.cs index 5422fb5..041ecfc 100644 --- a/Datasheet.cs +++ b/Datasheet.cs @@ -23,9 +23,10 @@ namespace Gidrolock_Modbus_Scanner SerialPort port = Modbus.port; bool isPolling = false; static bool isAwaitingResponse = false; + static bool responseReceived = false; - bool isValveClosed = false; + bool isValveClosed = false; bool alarmStatus = false; bool cleaningStatus = false; @@ -80,7 +81,7 @@ namespace Gidrolock_Modbus_Scanner labelBattery.Text = "Нет"; else labelBattery.Text = "???%"; - Modbus.ResponseReceived += (sndr, msg) => { isAwaitingResponse = false; latestMessage = msg; }; + Modbus.ResponseReceived += (sndr, msg) => { responseReceived = true; latestMessage = msg; isAwaitingResponse = false; }; for (int i = 0; i < device.wiredSensors; i++) { @@ -246,7 +247,6 @@ namespace Gidrolock_Modbus_Scanner bool res = false; isAwaitingResponse = true; Modbus.ReadRegAsync(modbusID, (FunctionCode)entry.registerType, entry.address, entry.length); - stopwatch.Restart(); @@ -396,7 +396,7 @@ namespace Gidrolock_Modbus_Scanner { try { - fileThread.TrySetApartmentState(ApartmentState.STA); + fileThread.SetApartmentState(ApartmentState.STA); fileThread.Start(); while (!fileThread.IsAlive) { Thread.Sleep(1); } Thread.Sleep(1); @@ -414,7 +414,8 @@ namespace Gidrolock_Modbus_Scanner MessageBox.Show("Выберите файл прошивки."); return; } - + int cntr = 0; + FileStream fileStream = File.OpenRead(firmwarePath); long bytesLeft = fileStream.Length; long bytesTotal = fileStream.Length; @@ -425,15 +426,13 @@ namespace Gidrolock_Modbus_Scanner byte[] flashAddr = new byte[2]; byte[] CRC; List message; - bool responseReceived = false; - Modbus.ResponseReceived += (sndr, msg) => { responseReceived = true; }; bool firstMessageSent = false; long bytesWritten = 0; await Task.Run(() => { while (bytesLeft > 0) { - if (firstMessageSent) // after first message the device is sent into recovery mode which only supports 9600 bps + if (firstMessageSent && port.BaudRate != 9600) // after first message the device is sent into recovery mode which only supports 9600 bps { port.Close(); port.BaudRate = 9600; @@ -477,50 +476,64 @@ namespace Gidrolock_Modbus_Scanner message[message.Count - 2] = CRC[0]; message[message.Count - 1] = CRC[1]; - Console.WriteLine("Outgoing firmware message: " + Modbus.ByteArrayToString(message.ToArray())); + responseReceived = false; + + + while (true) + { + if (cntr > 3) + { + Console.WriteLine("Response timed out 4 times in a row, aborting. Check connection."); + return; + } + isAwaitingResponse = true; + Console.WriteLine("Outgoing firmware message: " + Modbus.ByteArrayToString(message.ToArray())); + port.Write(message.ToArray(), 0, message.Count); + stopwatch.Restart(); + + while (isAwaitingResponse) + { + if (stopwatch.ElapsedMilliseconds > 1000) + { + Console.WriteLine("Response timed out."); + cntr++; + break; + } + } + + if (responseReceived) + { + if (latestMessage.Status == ModbusStatus.Error) + Console.WriteLine("Response received: Error!"); + else + { + Console.WriteLine("Response received: all good;"); + break; + } + } + } + cntr = 0; + bytesLeft -= count; + bytesWritten += count; + firmwareProgressBar.Invoke((MethodInvoker)delegate { firmwareProgressBar.Increment((int)(bytesWritten / bytesTotal) * 100); }); + + _flashAddr += (short)count; + if (port.BaudRate != 9600) + firstMessageSent = true; + + if (bytesLeft <= 0) + Console.WriteLine("Reached the end of firmware file."); } catch (Exception ex) { - MessageBox.Show(ex.Message); + MessageBox.Show(ex.Message, "Firmware writing error"); return; } - responseReceived = false; - - - while (true) - { - - isAwaitingResponse = true; - port.Write(message.ToArray(), 0, message.Count); - stopwatch.Restart(); - - while (isAwaitingResponse) - { - if (stopwatch.ElapsedMilliseconds > 1000) - { - Console.WriteLine("Response timed out."); - break; - } - } - - if (responseReceived) - break; - } - bytesLeft -= count; - bytesWritten += count; - firmwareProgressBar.Increment( (int)(bytesWritten / bytesTotal) * 100 ); - - _flashAddr += (short)count; - if (port.BaudRate != 9600) - firstMessageSent = true; - - if (bytesLeft <= 0) - Console.WriteLine("Reached the end of firmware file."); } /* Final Message */ - message = new List(); + message = new List(); message.Add(modbusID); // device ID message.Add(0x10); // function code message.Add(0xFF); // register address @@ -534,24 +547,32 @@ namespace Gidrolock_Modbus_Scanner Modbus.GetCRC(message.ToArray(), ref CRC); message[message.Count - 2] = CRC[0]; message[message.Count - 1] = CRC[1]; - Console.WriteLine("Outgoing firmware message: " + Modbus.ByteArrayToString(message.ToArray())); - while (true) { isAwaitingResponse = true; + Console.WriteLine("Outgoing firmware message: " + Modbus.ByteArrayToString(message.ToArray())); port.Write(message.ToArray(), 0, message.Count); stopwatch.Restart(); while (isAwaitingResponse) { - if (stopwatch.ElapsedMilliseconds > 250) + if (stopwatch.ElapsedMilliseconds > 1000) { Console.WriteLine("Response timed out."); break; } } + if (responseReceived) - break; + { + if (latestMessage.Status == ModbusStatus.Error) + Console.WriteLine("Response received: Error!"); + else + { + Console.WriteLine("Response received: all good;"); + break; + } + } } }); diff --git a/Main.cs b/Main.cs index e06acd6..37ebec0 100644 --- a/Main.cs +++ b/Main.cs @@ -59,12 +59,6 @@ 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) => - { - latestMessage = msg; - isAwaitingResponse = false; - }; } void App_FormClosed(object sender, FormClosedEventArgs e) @@ -129,17 +123,27 @@ namespace Gidrolock_Modbus_Scanner isAwaitingResponse = true; var send = Modbus.ReadRegAsync((byte)upDownModbusID.Value, FunctionCode.ReadInput, 200, 6); stopwatch.Restart(); + int counter = 0; while (isAwaitingResponse) { if (stopwatch.ElapsedMilliseconds > 1000) { - Console.WriteLine("Response timed out."); - break; + AddLog("Истекло время ожидания ответа от устройства. Повторный запрос..."); + isAwaitingResponse = false; + counter++; + if (counter > 3) + { + AddLog("Устройство не отвечает. Проверьте соединение с устройством."); + return; + } } } if (latestMessage is null) + { + Console.WriteLine("Latest message is null;"); return; + } if (latestMessage.Status == ModbusStatus.Error) return; @@ -194,6 +198,7 @@ namespace Gidrolock_Modbus_Scanner void OnResponseReceived(object sender, ModbusResponseEventArgs e) { + latestMessage = e; isAwaitingResponse = false; AddLog("Получен ответ: " + Modbus.ByteArrayToString(e.Message)); switch (e.Status) diff --git a/Modbus.cs b/Modbus.cs index 708f791..e7d6952 100644 --- a/Modbus.cs +++ b/Modbus.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using System.Windows.Forms; using System.Collections.Generic; using static System.Net.Mime.MediaTypeNames; +using System.Diagnostics; namespace Gidrolock_Modbus_Scanner { @@ -267,39 +268,68 @@ namespace Gidrolock_Modbus_Scanner port.DiscardInBuffer(); })); */ + + static Stopwatch stopwatch = new Stopwatch(); + static byte[] buffer = new byte[255]; + static int offset = 0; + static int count = 0; static void PortDataReceived(object sender, EventArgs e) { try { - Thread.Sleep(50); - byte[] message = new byte[port.BytesToRead]; - //Console.WriteLine("Bytes to read:" + port.BytesToRead); - port.Read(message, 0, port.BytesToRead); - if (message.Length == 0) - return; - Console.WriteLine("Incoming message: " + ByteArrayToString(message, false)); - if (!CheckResponse(message)) + stopwatch.Restart(); + while (stopwatch.ElapsedMilliseconds < 10) { - Console.WriteLine("Bad CRC or not a modbus message!"); - return; + if (port.BytesToRead > 0) + { + stopwatch.Restart(); + count = offset; + port.Read(buffer, offset, port.BytesToRead); + offset += count; + } + } + // assume that the message ended + List message = new List (); + int endOfMessage = buffer.Length - 1; + for (int i = buffer.Length-1; i >= 0; i--) + { + if (buffer[i] != 0x00) + { + endOfMessage = i; + break; + } + } + for (int i = 0; i < endOfMessage + 1; i++) + { + message.Add(buffer[i]); } + if (message.Count == 0) + return; + + Console.WriteLine("Incoming message: " + ByteArrayToString(message.ToArray(), false)); + /* + if (!CheckResponse(message.ToArray())) + { + Console.WriteLine("Bad CRC or not a modbus message!"); + } + */ if (message[1] <= 0x04) // read functions { //Console.WriteLine("It's a read message"); - ResponseReceived.Invoke(null, new ModbusResponseEventArgs(message, ModbusStatus.ReadSuccess)); + ResponseReceived.Invoke(null, new ModbusResponseEventArgs(message.ToArray(), ModbusStatus.ReadSuccess)); } else { if (message[1] <= 0x10) // write functions { //Console.WriteLine("It's a write message"); - ResponseReceived.Invoke(null, new ModbusResponseEventArgs(message, ModbusStatus.WriteSuccess)); + ResponseReceived.Invoke(null, new ModbusResponseEventArgs(message.ToArray(), ModbusStatus.WriteSuccess)); } else // error codes { //Console.WriteLine("It's an error"); - ResponseReceived.Invoke(null, new ModbusResponseEventArgs(message, ModbusStatus.Error)); + ResponseReceived.Invoke(null, new ModbusResponseEventArgs(message.ToArray(), ModbusStatus.Error)); } } }