diff --git a/Form1.Designer.cs b/Form1.Designer.cs
index cb689e6..9906083 100644
--- a/Form1.Designer.cs
+++ b/Form1.Designer.cs
@@ -37,11 +37,28 @@
this.panel1 = new System.Windows.Forms.Panel();
this.CBox_Ports = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label();
- this.Label_Status = new System.Windows.Forms.Label();
+ this.TextBox_Log = new System.Windows.Forms.TextBox();
+ this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.panel5 = new System.Windows.Forms.Panel();
+ this.UpDown_RegLength = new System.Windows.Forms.NumericUpDown();
+ this.label5 = new System.Windows.Forms.Label();
+ this.Button_SendCommand = new System.Windows.Forms.Button();
+ this.panel3 = new System.Windows.Forms.Panel();
+ this.UpDown_RegAddress = new System.Windows.Forms.NumericUpDown();
+ this.label3 = new System.Windows.Forms.Label();
+ this.panel4 = new System.Windows.Forms.Panel();
+ this.CBox_Function = new System.Windows.Forms.ComboBox();
+ this.label4 = new System.Windows.Forms.Label();
this.groupBox1.SuspendLayout();
this.panel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.UpDown_ModbusID)).BeginInit();
this.panel1.SuspendLayout();
+ this.groupBox2.SuspendLayout();
+ this.panel5.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.UpDown_RegLength)).BeginInit();
+ this.panel3.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.UpDown_RegAddress)).BeginInit();
+ this.panel4.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
@@ -51,7 +68,7 @@
this.groupBox1.Controls.Add(this.panel1);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
- this.groupBox1.Size = new System.Drawing.Size(310, 63);
+ this.groupBox1.Size = new System.Drawing.Size(344, 63);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "Подключение";
@@ -60,7 +77,7 @@
//
this.ButtonConnect.Location = new System.Drawing.Point(162, 34);
this.ButtonConnect.Name = "ButtonConnect";
- this.ButtonConnect.Size = new System.Drawing.Size(146, 23);
+ this.ButtonConnect.Size = new System.Drawing.Size(176, 23);
this.ButtonConnect.TabIndex = 4;
this.ButtonConnect.Text = "Подключиться";
this.ButtonConnect.UseVisualStyleBackColor = true;
@@ -119,23 +136,126 @@
this.label1.TabIndex = 0;
this.label1.Text = "Порт";
//
- // Label_Status
+ // TextBox_Log
//
- this.Label_Status.Location = new System.Drawing.Point(15, 87);
- this.Label_Status.Name = "Label_Status";
- this.Label_Status.Size = new System.Drawing.Size(307, 40);
- this.Label_Status.TabIndex = 5;
- this.Label_Status.Text = "Статус: истекло время ожидания ответа. Проверьте указаный порт, Modbus ID и стату" +
- "с устройства.";
+ this.TextBox_Log.Location = new System.Drawing.Point(12, 82);
+ this.TextBox_Log.Multiline = true;
+ this.TextBox_Log.Name = "TextBox_Log";
+ this.TextBox_Log.ReadOnly = true;
+ this.TextBox_Log.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.TextBox_Log.Size = new System.Drawing.Size(417, 87);
+ this.TextBox_Log.TabIndex = 1;
+ //
+ // groupBox2
+ //
+ this.groupBox2.Controls.Add(this.panel5);
+ this.groupBox2.Controls.Add(this.Button_SendCommand);
+ this.groupBox2.Controls.Add(this.panel3);
+ this.groupBox2.Controls.Add(this.panel4);
+ this.groupBox2.Location = new System.Drawing.Point(12, 175);
+ this.groupBox2.Name = "groupBox2";
+ this.groupBox2.Size = new System.Drawing.Size(417, 63);
+ this.groupBox2.TabIndex = 5;
+ this.groupBox2.TabStop = false;
+ this.groupBox2.Text = "Команды";
+ //
+ // panel5
+ //
+ this.panel5.Controls.Add(this.UpDown_RegLength);
+ this.panel5.Controls.Add(this.label5);
+ this.panel5.Location = new System.Drawing.Point(259, 20);
+ this.panel5.Name = "panel5";
+ this.panel5.Size = new System.Drawing.Size(75, 43);
+ this.panel5.TabIndex = 3;
+ //
+ // UpDown_RegLength
+ //
+ this.UpDown_RegLength.Location = new System.Drawing.Point(6, 17);
+ this.UpDown_RegLength.Name = "UpDown_RegLength";
+ this.UpDown_RegLength.Size = new System.Drawing.Size(66, 20);
+ this.UpDown_RegLength.TabIndex = 1;
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(3, 0);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(40, 13);
+ this.label5.TabIndex = 0;
+ this.label5.Text = "Длина";
+ //
+ // Button_SendCommand
+ //
+ this.Button_SendCommand.Location = new System.Drawing.Point(337, 35);
+ this.Button_SendCommand.Name = "Button_SendCommand";
+ this.Button_SendCommand.Size = new System.Drawing.Size(71, 23);
+ this.Button_SendCommand.TabIndex = 4;
+ this.Button_SendCommand.Text = "Отправить";
+ this.Button_SendCommand.UseVisualStyleBackColor = true;
+ this.Button_SendCommand.Click += new System.EventHandler(this.Button_SendCommand_Click);
+ //
+ // panel3
+ //
+ this.panel3.Controls.Add(this.UpDown_RegAddress);
+ this.panel3.Controls.Add(this.label3);
+ this.panel3.Location = new System.Drawing.Point(162, 20);
+ this.panel3.Name = "panel3";
+ this.panel3.Size = new System.Drawing.Size(91, 43);
+ this.panel3.TabIndex = 2;
+ //
+ // UpDown_RegAddress
+ //
+ this.UpDown_RegAddress.Location = new System.Drawing.Point(6, 17);
+ this.UpDown_RegAddress.Name = "UpDown_RegAddress";
+ this.UpDown_RegAddress.Size = new System.Drawing.Size(82, 20);
+ this.UpDown_RegAddress.TabIndex = 1;
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(3, 0);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(38, 13);
+ this.label3.TabIndex = 0;
+ this.label3.Text = "Адрес";
+ //
+ // panel4
+ //
+ this.panel4.Controls.Add(this.CBox_Function);
+ this.panel4.Controls.Add(this.label4);
+ this.panel4.Location = new System.Drawing.Point(0, 20);
+ this.panel4.Name = "panel4";
+ this.panel4.Size = new System.Drawing.Size(156, 43);
+ this.panel4.TabIndex = 0;
+ //
+ // CBox_Function
+ //
+ this.CBox_Function.FormattingEnabled = true;
+ this.CBox_Function.Location = new System.Drawing.Point(6, 17);
+ this.CBox_Function.Name = "CBox_Function";
+ this.CBox_Function.Size = new System.Drawing.Size(147, 21);
+ this.CBox_Function.TabIndex = 1;
+ this.CBox_Function.Text = "01 - Read Coil";
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(3, 0);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(53, 13);
+ this.label4.TabIndex = 0;
+ this.label4.Text = "Функция";
//
// App
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(333, 84);
- this.Controls.Add(this.Label_Status);
+ this.ClientSize = new System.Drawing.Size(432, 242);
+ this.Controls.Add(this.groupBox2);
+ this.Controls.Add(this.TextBox_Log);
this.Controls.Add(this.groupBox1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.MaximizeBox = false;
this.Name = "App";
this.Text = "Gidrolock Modbus Scanner";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.App_FormClosed);
@@ -146,7 +266,17 @@
((System.ComponentModel.ISupportInitialize)(this.UpDown_ModbusID)).EndInit();
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
+ this.groupBox2.ResumeLayout(false);
+ this.panel5.ResumeLayout(false);
+ this.panel5.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.UpDown_RegLength)).EndInit();
+ this.panel3.ResumeLayout(false);
+ this.panel3.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.UpDown_RegAddress)).EndInit();
+ this.panel4.ResumeLayout(false);
+ this.panel4.PerformLayout();
this.ResumeLayout(false);
+ this.PerformLayout();
}
@@ -160,7 +290,18 @@
private System.Windows.Forms.ComboBox CBox_Ports;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button ButtonConnect;
- private System.Windows.Forms.Label Label_Status;
+ private System.Windows.Forms.TextBox TextBox_Log;
+ private System.Windows.Forms.GroupBox groupBox2;
+ private System.Windows.Forms.Panel panel5;
+ private System.Windows.Forms.NumericUpDown UpDown_RegLength;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.Button Button_SendCommand;
+ private System.Windows.Forms.Panel panel3;
+ private System.Windows.Forms.NumericUpDown UpDown_RegAddress;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Panel panel4;
+ private System.Windows.Forms.ComboBox CBox_Function;
+ private System.Windows.Forms.Label label4;
}
}
diff --git a/Form1.cs b/Form1.cs
index be2e7a6..b044d80 100644
--- a/Form1.cs
+++ b/Form1.cs
@@ -17,15 +17,28 @@ namespace Gidrolock_Modbus_Scanner
{
public partial class App : Form
{
+ int offset = 0;
+ byte[] data = new byte[255];
public bool isAwaitingResponse = false;
public short[] res = new short[12];
public SerialPort port = new SerialPort();
+ public int expectedLength = 0;
public App()
{
InitializeComponent();
this.port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(PortDataReceived);
this.UpDown_ModbusID.Value = 30;
+ TextBox_Log.Text = "Приложение готово к работе.";
+
+ CBox_Function.Items.Add("01 - Read Coil");
+ CBox_Function.Items.Add("02 - Read Discrete Input");
+ CBox_Function.Items.Add("03 - Read Holding Register");
+ CBox_Function.Items.Add("04 - Read Input Register");
+ CBox_Function.SelectedItem = CBox_Function.Items[0];
+
+ UpDown_RegAddress.Minimum = 0;
+ UpDown_RegAddress.Maximum = 65536;
}
void App_FormClosed(object sender, FormClosedEventArgs e)
{
@@ -49,13 +62,14 @@ namespace Gidrolock_Modbus_Scanner
else ButtonConnect.Text = "Подключиться";
}
- private async void ButtonConnect_Click(object sender, EventArgs e)
- {
+ async Task SendMessageAsync(FunctionCode functionCode, ushort address, ushort length)
+ {
if (CBox_Ports.Text == "")
MessageBox.Show("Необходимо выбрать COM порт.", "Ошибка", MessageBoxButtons.OK);
if (UpDown_ModbusID.Value == 0)
MessageBox.Show("Глобальное вещание пока не поддерживается");
- try
+
+ try
{
if (port.IsOpen)
port.Close();
@@ -67,19 +81,29 @@ namespace Gidrolock_Modbus_Scanner
port.DataBits = 8;
port.StopBits = StopBits.One;
- port.ReadTimeout = 10;
- port.WriteTimeout = 10;
+ port.ReadTimeout = 1000;
+ port.WriteTimeout = 1000;
-
+ offset = 0;
+ data = new byte[255];
port.Open();
- var send = await Modbus.ReadRegAsync(port, (byte)FunctionCode.HoldingRegister, (byte)UpDown_ModbusID.Value, 128, 1);
+
+ byte[] message = new byte[8];
+ Modbus.BuildMessage((byte)UpDown_ModbusID.Value, (byte)(1 + functionCode), address, length, ref message);
+ string messageParsed = Modbus.ParseByteArray(message);
+
+ var send = await Modbus.ReadRegAsync(port, functionCode, (byte)UpDown_ModbusID.Value, address, length);
+ AddLog("Отправка сообщения: " + messageParsed);
isAwaitingResponse = true;
Task timer = Task.Delay(2000);
- await timer.ContinueWith( _ =>
+ await timer.ContinueWith(_ =>
{
if (isAwaitingResponse)
+ {
MessageBox.Show("Истекло время ожидания ответа.", "Ошибка");
+ port.Close();
+ }
});
}
@@ -90,6 +114,11 @@ namespace Gidrolock_Modbus_Scanner
}
}
+ private async void ButtonConnect_Click(object sender, EventArgs e)
+ {
+ await SendMessageAsync(FunctionCode.HoldingRegister, 128, 1);
+ }
+
void CBox_Ports_Click(object sender, EventArgs e)
{
CBox_Ports.Items.Clear();
@@ -100,40 +129,37 @@ namespace Gidrolock_Modbus_Scanner
{
Console.WriteLine("Data receieved on Serial Port");
isAwaitingResponse = false;
- int len;
- byte rdxLen = 0;
-
try
{
- len = port.BytesToRead;
- byte[] data = new byte[len];
- port.Read(data, rdxLen, len);
- rdxLen += (byte)len;
- int lastByte = len - 1;
- for (int i = len - 1; i >= 0; i--)
- {
- if (data[i] != 0)
- {
- lastByte = i;
- break;
- }
- }
- string dataString = BitConverter.ToString(data);
- string dataCleaned = "";
- for (int i = 0; i < dataString.Length; i++)
- {
- if (dataString[i] == '-')
- dataCleaned += " ";
- else dataCleaned += dataString[i];
- }
- MessageBox.Show("Получен ответ от устройства: " + dataCleaned, "Успех", MessageBoxButtons.OK);
+ int len = port.BytesToRead;
+ Console.WriteLine("Data length: " + len);
+ port.Read(data, offset, len);
+ offset += len;
+ string dataCleaned = Modbus.ParseByteArray(data);
+
+ TextBox_Log.Invoke((MethodInvoker)delegate { AddLog("Получен ответ: " + dataCleaned); });
+ //MessageBox.Show("Получен ответ от устройства: " + dataCleaned, "Успех", MessageBoxButtons.OK);
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
+ //port.Close();
- port.Close();
+ }
+
+ void AddLog(string message)
+ {
+ TextBox_Log.AppendText(Environment.NewLine + message);
+ }
+
+ private async void Button_SendCommand_Click(object sender, EventArgs e)
+ {
+ FunctionCode functionCode = (FunctionCode)CBox_Function.SelectedIndex;
+ ushort address = (ushort)UpDown_RegAddress.Value;
+ ushort length = (ushort)UpDown_RegLength.Value;
+
+ await SendMessageAsync(functionCode, address, length);
}
}
}
diff --git a/Gidrolock Modbus Scanner.csproj b/Gidrolock Modbus Scanner.csproj
index d599bfd..fa5836e 100644
--- a/Gidrolock Modbus Scanner.csproj
+++ b/Gidrolock Modbus Scanner.csproj
@@ -83,6 +83,7 @@
True
Resources.resx
+
SettingsSingleFileGenerator
Settings.Designer.cs
@@ -92,6 +93,7 @@
Settings.settings
True
+
diff --git a/Modbus.cs b/Modbus.cs
index 583fe8b..8d94ac4 100644
--- a/Modbus.cs
+++ b/Modbus.cs
@@ -42,7 +42,7 @@ namespace Gidrolock_Modbus_Scanner
#endregion
#region Build Message
- static void BuildMessage(byte address, byte type, ushort start, ushort registers, ref byte[] message)
+ public static void BuildMessage(byte address, byte type, ushort start, ushort length, ref byte[] message)
{
//Array to receive CRC bytes:
byte[] CRC = new byte[2];
@@ -51,8 +51,8 @@ namespace Gidrolock_Modbus_Scanner
message[1] = type;
message[2] = (byte)(start >> 8);
message[3] = (byte)start;
- message[4] = (byte)(registers >> 8);
- message[5] = (byte)registers;
+ message[4] = (byte)(length >> 8);
+ message[5] = (byte)length;
GetCRC(message, ref CRC);
message[message.Length - 2] = CRC[0];
@@ -62,51 +62,22 @@ namespace Gidrolock_Modbus_Scanner
}
#endregion
- #region Check Response
- static bool CheckResponse(byte[] response)
- {
- //Perform a basic CRC check:
- byte[] CRC = new byte[2];
- GetCRC(response, ref CRC);
- if (CRC[0] == response[response.Length - 2] && CRC[1] == response[response.Length - 1])
- return true;
- else
- return false;
- }
- #endregion
-
- #region Get Response
- static void GetResponse(SerialPort port, ref byte[] response)
- {
- Console.WriteLine("Got response from port");
- if (port.BytesToRead == 0)
- return;
- //There is a bug in .Net 2.0 DataReceived Event that prevents people from using this
- //event as an interrupt to handle data (it doesn't fire all of the time). Therefore
- //we have to use the ReadByte command for a fixed length as it's been shown to be reliable.
- for (int i = 0; i < response.Length; i++)
- {
- response[i] = (byte)(port.ReadByte());
- }
- }
- #endregion
-
#region Function 3 - Read Holding Registers
- public static async Task ReadRegAsync(SerialPort port, byte regType, byte address, ushort start, ushort registers)
+ public static async Task ReadRegAsync(SerialPort port, FunctionCode functionCode, byte address, ushort start, ushort length)
{
- short[] values = new short[8];
//Ensure port is open:
if (port.IsOpen)
{
//Clear in/out buffers:
port.DiscardOutBuffer();
port.DiscardInBuffer();
- //Function 3 request is always 8 bytes:
+
+ //Read functions are always 8 bytes long
byte[] message = new byte[8];
- //Function 3 response buffer:
- byte[] response = new byte[5 + 2 * registers];
+
//Build outgoing modbus message:
- BuildMessage(address, (byte)3, start, registers, ref message);
+ BuildMessage(address, (byte)(1 + (int)functionCode), start, length, ref message);
+
//Send modbus message to Serial Port:
try
{
@@ -129,6 +100,39 @@ namespace Gidrolock_Modbus_Scanner
}
#endregion
+ ///
+ /// Parses a byte array into a string.
+ ///
+ ///
+ /// string
+ public static string ParseByteArray(byte[] bytes)
+ {
+ int length = bytes.Length - 1;
+ // snip off the empty bytes at the end
+ for (int i = length; i >= 0; i--)
+ {
+ if (bytes[i] != 0)
+ {
+ length = i + 1;
+ break;
+ }
+ }
+
+ byte[] res = new byte[length];
+ for (int i = 0; i < length; i++)
+ res[i] = bytes[i];
+
+ string dataString = BitConverter.ToString(res);
+ string result = "";
+ for (int i = 0; i < dataString.Length; i++)
+ {
+ if (dataString[i] == '-')
+ result += " ";
+ else result += dataString[i];
+ }
+
+ return result;
+ }
}
}