single register write functions should now work; better device response handling

This commit is contained in:
nikzori
2024-12-18 11:28:20 +03:00
parent 61546de4ca
commit 255e866b86
2 changed files with 138 additions and 38 deletions

97
Main.cs
View File

@@ -449,18 +449,90 @@ namespace Gidrolock_Modbus_Scanner
void OnResponseReceived(object sender, ModbusResponseEventArgs e) void OnResponseReceived(object sender, ModbusResponseEventArgs e)
{ {
isAwaitingResponse = false; isAwaitingResponse = false;
TextBox_Log.Invoke((MethodInvoker)delegate { AddLog("Получен ответ: " + Modbus.ByteArrayToString(e.Message)); }); AddLog("Получен ответ: " + Modbus.ByteArrayToString(e.Message));
TextBox_Log.Invoke((MethodInvoker)delegate { AddLog("UTF-8: " + e.Text); }); 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) void AddLog(string message)
{ {
dateTime = DateTime.Now; 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) 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; int functionCode = CBox_Function.SelectedIndex + 1;
short address; short address;
ushort length = (ushort)UpDown_RegLength.Value; ushort length = (ushort)UpDown_RegLength.Value;
@@ -507,10 +579,7 @@ namespace Gidrolock_Modbus_Scanner
} }
if (canWrite) if (canWrite)
{ {
byte[] _value = BitConverter.GetBytes(value); _ = Modbus.WriteSingleAsync(port, (FunctionCode)functionCode, (byte)UpDown_ModbusID.Value, (ushort)address,
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,
(ushort)value); (ushort)value);
} }
else MessageBox.Show("Неподходящие значения для регистра типа Input Register"); else MessageBox.Show("Неподходящие значения для регистра типа Input Register");
@@ -621,6 +690,20 @@ namespace Gidrolock_Modbus_Scanner
} }
return true; 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<char> result = new List<char>(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());
}
} }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.IO.Ports; using System.IO.Ports;
using System.Runtime.Remoting.Messaging;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
@@ -55,7 +56,6 @@ namespace Gidrolock_Modbus_Scanner
GetCRC(_message, ref CRC); GetCRC(_message, ref CRC);
_message[6] = CRC[0]; _message[6] = CRC[0];
_message[7] = CRC[1]; _message[7] = CRC[1];
Console.WriteLine("Message: " + ByteArrayToString(_message));
return _message; return _message;
} }
else return new byte[1] { 0xFF }; else return new byte[1] { 0xFF };
@@ -77,7 +77,8 @@ namespace Gidrolock_Modbus_Scanner
//Build outgoing modbus message: //Build outgoing modbus message:
BuildReadMessage(slaveID, (byte)functionCode, address, length, ref message); BuildReadMessage(slaveID, (byte)functionCode, address, length, ref message);
if (message.Length > 1)
{
//Send modbus message to Serial Port: //Send modbus message to Serial Port:
try try
{ {
@@ -91,6 +92,8 @@ namespace Gidrolock_Modbus_Scanner
return false; return false;
} }
} }
else return false;
}
else else
{ {
MessageBox.Show("Порт не открыт"); MessageBox.Show("Порт не открыт");
@@ -125,12 +128,11 @@ namespace Gidrolock_Modbus_Scanner
Array.Reverse(_value); Array.Reverse(_value);
byte[] message = BuildWriteSingleMessage(slaveID, (byte)functionCode, address, _value); byte[] message = BuildWriteSingleMessage(slaveID, (byte)functionCode, address, _value);
//Send modbus message to Serial Port: //Send modbus message to Serial Port:
try try
{ {
port.Write(message, 0, message.Length); port.Write(message, 0, message.Length);
Console.WriteLine("Write message sent successfully"); Console.WriteLine("Message sent successfully.");
return true; return true;
} }
catch (Exception err) catch (Exception err)
@@ -236,28 +238,32 @@ namespace Gidrolock_Modbus_Scanner
try try
{ {
byte[] message = new byte[port.BytesToRead]; byte[] message = new byte[port.BytesToRead];
port.Read(message, 0, 3); port.Read(message, 0, port.BytesToRead);
int length = (int)message[2]; Console.WriteLine("Incoming message: " + ByteArrayToString(message));
for (int i = 0; i < length + 2; i++) 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));
} }
else
byte[] data = new byte[length];
for (int i = 0; i < length; i++)
{ {
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) catch (Exception err)
{ {
MessageBox.Show(err.Message); MessageBox.Show(err.Message);
} }
port.DiscardInBuffer();
} }
} }
@@ -266,13 +272,24 @@ namespace Gidrolock_Modbus_Scanner
{ {
public byte[] Message { get; set; } public byte[] Message { get; set; }
public byte[] Data { get; set; } public byte[] Data { get; set; }
public string Text { get; set; } public ModbusStatus Status { get; set; }
public ModbusResponseEventArgs(byte[] message, byte[] data, string text) public ModbusResponseEventArgs(byte[] message, ModbusStatus status)
{ {
this.Message = message; this.Message = message;
this.Data = data; this.Status = status;
this.Text = text; 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 };
} }