single register write functions should now work; better device response handling
This commit is contained in:
97
Main.cs
97
Main.cs
@@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
59
Modbus.cs
59
Modbus.cs
@@ -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 };
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user