diff --git a/Main.cs b/Main.cs index 82eae58..e6c0695 100644 --- a/Main.cs +++ b/Main.cs @@ -449,18 +449,90 @@ namespace Gidrolock_Modbus_Scanner void OnResponseReceived(object sender, ModbusResponseEventArgs e) { isAwaitingResponse = false; - TextBox_Log.Invoke((MethodInvoker)delegate { AddLog("Получен ответ: " + Modbus.ByteArrayToString(e.Message)); }); - TextBox_Log.Invoke((MethodInvoker)delegate { AddLog("UTF-8: " + e.Text); }); + AddLog("Получен ответ: " + Modbus.ByteArrayToString(e.Message)); + switch(e.Status) + { + case (ModbusStatus.ReadSuccess): + if (e.Message[1] == 0x03 || e.Message[1] == 0x04) + { + AddLog("Unicode: " + ByteArrayToUnicode(e.Data)); + + } + break; + case (ModbusStatus.WriteSuccess): + AddLog("Write success;"); + break; + case (ModbusStatus.Error): + string errorDesc; + switch (e.Message[2]) + { + case (0x01): + errorDesc = "01 - Illegal Function"; + break; + case (0x02): + errorDesc = "02 - Illegal Data Address"; + break; + case (0x03): + errorDesc = "03 - Illegal Data Value"; + break; + case (0x04): + errorDesc = "04 - Slave Device Failure"; + break; + case (0x05): + errorDesc = "05 - Acknowledge"; + break; + case (0x06): + errorDesc = "06 - Slave Device Busy"; + break; + case (0x07): + errorDesc = "07 - Negative Acknowledge"; + break; + case (0x08): + errorDesc = "08 - Memory Parity Error"; + break; + case (0x0A): + errorDesc = "10 - Gateway Path Unavailable"; + break; + case (0x0B): + errorDesc = "11 - Gateway Target Device Failed to Respond"; + break; + default: + errorDesc = "Unknown error code"; + break; + } + AddLog("Error code: " + errorDesc); + break; + + } } void AddLog(string message) { dateTime = DateTime.Now; - TextBox_Log.AppendText(Environment.NewLine + "[" + dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second + "] " + message); + TextBox_Log.Invoke((MethodInvoker)delegate { TextBox_Log.AppendText(Environment.NewLine + "[" + dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second + "] " + message); }); } private async void Button_SendCommand_Click(object sender, EventArgs e) { + /* - Port Setup - */ + if (port.IsOpen) + port.Close(); + + port.Handshake = Handshake.None; + port.PortName = CBox_Ports.Text; + port.BaudRate = BaudRate[CBox_BaudRate.SelectedIndex]; + port.Parity = Parity.None; + port.DataBits = DataBits[CBox_DataBits.SelectedIndex]; + port.StopBits = (StopBits)CBox_StopBits.SelectedIndex; + + port.ReadTimeout = 3000; + port.WriteTimeout = 3000; + + + message = new byte[255]; + port.Open(); + + int functionCode = CBox_Function.SelectedIndex + 1; short address; ushort length = (ushort)UpDown_RegLength.Value; @@ -507,10 +579,7 @@ namespace Gidrolock_Modbus_Scanner } if (canWrite) { - byte[] _value = BitConverter.GetBytes(value); - Array.Reverse( _value ); - AddLog("Отправка сообщения: " + Modbus.ByteArrayToString(Modbus.BuildWriteSingleMessage((byte)UpDown_ModbusID.Value, (byte)functionCode, (ushort)address, _value))); - await Modbus.WriteSingleAsync(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, + _ = Modbus.WriteSingleAsync(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address, (ushort)value); } else MessageBox.Show("Неподходящие значения для регистра типа Input Register"); @@ -621,6 +690,20 @@ namespace Gidrolock_Modbus_Scanner } return true; } + public static string ByteArrayToUnicode(byte[] input) + { + // stupid fucking WinForm textbox breaks from null symbols + // stupid fucking Encoding class does byte-by-byte conversion + List result = new List(input.Length/2); + byte[] flip = input; + Array.Reverse(flip); + for (int i = 0; i < flip.Length; i += 2) + { + result.Add(BitConverter.ToChar(flip, i)); + } + result.Reverse(); + return new string(result.ToArray()); + } } } diff --git a/Modbus.cs b/Modbus.cs index 2c68b00..52f4abb 100644 --- a/Modbus.cs +++ b/Modbus.cs @@ -1,5 +1,6 @@ using System; using System.IO.Ports; +using System.Runtime.Remoting.Messaging; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; @@ -55,7 +56,6 @@ namespace Gidrolock_Modbus_Scanner GetCRC(_message, ref CRC); _message[6] = CRC[0]; _message[7] = CRC[1]; - Console.WriteLine("Message: " + ByteArrayToString(_message)); return _message; } else return new byte[1] { 0xFF }; @@ -77,19 +77,22 @@ namespace Gidrolock_Modbus_Scanner //Build outgoing modbus message: BuildReadMessage(slaveID, (byte)functionCode, address, length, ref message); - - //Send modbus message to Serial Port: - try + if (message.Length > 1) { - await Task.Run(() => { port.Write(message, 0, message.Length); }); - return true; - } - catch (Exception err) - { - MessageBox.Show(err.Message, "aeiou"); - port.Close(); - return false; + //Send modbus message to Serial Port: + try + { + await Task.Run(() => { port.Write(message, 0, message.Length); }); + return true; + } + catch (Exception err) + { + MessageBox.Show(err.Message, "aeiou"); + port.Close(); + return false; + } } + else return false; } else { @@ -125,12 +128,11 @@ namespace Gidrolock_Modbus_Scanner Array.Reverse(_value); byte[] message = BuildWriteSingleMessage(slaveID, (byte)functionCode, address, _value); - //Send modbus message to Serial Port: try { port.Write(message, 0, message.Length); - Console.WriteLine("Write message sent successfully"); + Console.WriteLine("Message sent successfully."); return true; } catch (Exception err) @@ -236,28 +238,32 @@ namespace Gidrolock_Modbus_Scanner try { byte[] message = new byte[port.BytesToRead]; - port.Read(message, 0, 3); - int length = (int)message[2]; - for (int i = 0; i < length + 2; i++) + port.Read(message, 0, port.BytesToRead); + Console.WriteLine("Incoming message: " + ByteArrayToString(message)); + if (message[1] <= 0x04) // read functions { - port.Read(message, i + 3, 1); + Console.WriteLine("It's a read message"); + ResponseReceived.Invoke(null, new ModbusResponseEventArgs(message, ModbusStatus.ReadSuccess)); } - - byte[] data = new byte[length]; - for (int i = 0; i < length; i++) + else { - data[i] = message[i + 3]; + if (message[1] <= 0x10) // write functions + { + Console.WriteLine("It's a write message"); + ResponseReceived.Invoke(null, new ModbusResponseEventArgs(message, ModbusStatus.WriteSuccess)); + } + else // error codes + { + Console.WriteLine("It's an error"); + ResponseReceived.Invoke(null, new ModbusResponseEventArgs(message, ModbusStatus.Error)); + } } - string dataCleaned = ByteArrayToString(message); - - port.DiscardInBuffer(); - - ResponseReceived.Invoke(null, new ModbusResponseEventArgs(message, data, Encoding.UTF8.GetString(data))); } catch (Exception err) { MessageBox.Show(err.Message); } + port.DiscardInBuffer(); } } @@ -266,13 +272,24 @@ namespace Gidrolock_Modbus_Scanner { public byte[] Message { get; set; } public byte[] Data { get; set; } - public string Text { get; set; } - public ModbusResponseEventArgs(byte[] message, byte[] data, string text) + public ModbusStatus Status { get; set; } + public ModbusResponseEventArgs(byte[] message, ModbusStatus status) { this.Message = message; - this.Data = data; - this.Text = text; + this.Status = status; + if (status == ModbusStatus.ReadSuccess) + { + int dataLength = message[2]; + Data = new byte[dataLength]; + for (int i = 0; i < dataLength; i++) + { + Data[i] = message[i + 3]; + } + Console.WriteLine("Read data: " + Modbus.ByteArrayToString(Data, false)); + } + else Data = new byte[1] {0x0F}; } } + public enum ModbusStatus { ReadSuccess, WriteSuccess, Error }; } \ No newline at end of file