mirror of
https://github.com/ClassicDIY/ModbusTool.git
synced 2026-10-18 22:00:29 +08:00
285 lines
9.6 KiB
C#
285 lines
9.6 KiB
C#
using System;
|
|
using System.IO.Ports;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Reflection;
|
|
using System.Windows.Forms;
|
|
using Modbus.Common;
|
|
using ModbusLib;
|
|
using ModbusLib.Protocols;
|
|
|
|
namespace ModbusMaster
|
|
{
|
|
public partial class MasterForm : BaseForm
|
|
{
|
|
private int _transactionId;
|
|
private ModbusClient _driver;
|
|
private ICommClient _portClient;
|
|
private SerialPort _uart;
|
|
|
|
private byte _lastReadCommand = 0;
|
|
|
|
#region Form
|
|
|
|
public MasterForm()
|
|
{
|
|
InitializeComponent();
|
|
this.Text += String.Format(" ({0})", Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
|
}
|
|
|
|
private void MasterFormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
DoDisconnect();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Connect/disconnect
|
|
|
|
private void DoDisconnect()
|
|
{
|
|
if (_socket != null)
|
|
{
|
|
_socket.Close();
|
|
_socket.Dispose();
|
|
_socket = null;
|
|
}
|
|
if (_uart != null)
|
|
{
|
|
_uart.Close();
|
|
_uart.Dispose();
|
|
_uart = null;
|
|
}
|
|
_portClient = null;
|
|
_driver = null;
|
|
}
|
|
|
|
private void BtnConnectClick(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
switch (CommunicationMode)
|
|
{
|
|
case CommunicationMode.RTU:
|
|
_uart = new SerialPort(PortName, Baud, Parity, DataBits, StopBits);
|
|
_uart.Open();
|
|
_portClient = _uart.GetClient();
|
|
_driver = new ModbusClient(new ModbusRtuCodec()) { Address = SlaveId };
|
|
_driver.OutgoingData += DriverOutgoingData;
|
|
_driver.IncommingData += DriverIncommingData;
|
|
AppendLog(String.Format("Connected using RTU to {0}", PortName));
|
|
break;
|
|
|
|
case CommunicationMode.UDP:
|
|
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
|
_socket.Connect(new IPEndPoint(IPAddress, TCPPort));
|
|
_portClient = _socket.GetClient();
|
|
_driver = new ModbusClient(new ModbusTcpCodec()) { Address = SlaveId };
|
|
_driver.OutgoingData += DriverOutgoingData;
|
|
_driver.IncommingData += DriverIncommingData;
|
|
AppendLog(String.Format("Connected using UDP to {0}", _socket.RemoteEndPoint));
|
|
break;
|
|
|
|
case CommunicationMode.TCP:
|
|
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
_socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
|
|
_socket.SendTimeout = 2000;
|
|
_socket.ReceiveTimeout = 2000;
|
|
_socket.Connect(new IPEndPoint(IPAddress, TCPPort));
|
|
_portClient = _socket.GetClient();
|
|
_driver = new ModbusClient(new ModbusTcpCodec()) { Address = SlaveId };
|
|
_driver.OutgoingData += DriverOutgoingData;
|
|
_driver.IncommingData += DriverIncommingData;
|
|
AppendLog(String.Format("Connected using TCP to {0}", _socket.RemoteEndPoint));
|
|
break;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
AppendLog(ex.Message);
|
|
return;
|
|
}
|
|
btnConnect.Enabled = false;
|
|
buttonDisconnect.Enabled = true;
|
|
groupBoxFunctions.Enabled = true;
|
|
groupBoxTCP.Enabled = false;
|
|
groupBoxRTU.Enabled = false;
|
|
groupBoxMode.Enabled = false;
|
|
grpExchange.Enabled = false;
|
|
}
|
|
|
|
private void ButtonDisconnectClick(object sender, EventArgs e)
|
|
{
|
|
DoDisconnect();
|
|
btnConnect.Enabled = true;
|
|
buttonDisconnect.Enabled = false;
|
|
groupBoxFunctions.Enabled = false;
|
|
groupBoxMode.Enabled = true;
|
|
grpExchange.Enabled = true;
|
|
SetMode();
|
|
AppendLog("Disconnected");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Functions buttons
|
|
|
|
private void BtnReadCoilsClick(object sender, EventArgs e)
|
|
{
|
|
ExecuteReadCommand(ModbusCommand.FuncReadCoils);
|
|
}
|
|
|
|
private void BtnReadDisInpClick(object sender, EventArgs e)
|
|
{
|
|
ExecuteReadCommand(ModbusCommand.FuncReadInputDiscretes);
|
|
}
|
|
|
|
private void BtnReadHoldRegClick(object sender, EventArgs e)
|
|
{
|
|
ExecuteReadCommand(ModbusCommand.FuncReadMultipleRegisters);
|
|
}
|
|
|
|
private void BtnReadInpRegClick(object sender, EventArgs e)
|
|
{
|
|
ExecuteReadCommand(ModbusCommand.FuncReadInputRegisters);
|
|
}
|
|
|
|
private void ExecuteReadCommand(byte function)
|
|
{
|
|
_lastReadCommand = function;
|
|
|
|
try
|
|
{
|
|
var command = new ModbusCommand(function) {Offset = StartAddress, Count = DataLength, TransId = _transactionId++};
|
|
var result = _driver.ExecuteGeneric(_portClient, command);
|
|
if (result.Status == CommResponse.Ack)
|
|
{
|
|
command.Data.CopyTo(_registerData, StartAddress);
|
|
UpdateDataTable();
|
|
AppendLog(String.Format("Read succeeded: Function code:{0}.", function));
|
|
}
|
|
else
|
|
{
|
|
AppendLog(String.Format("Failed to execute Read: Error code:{0}", result.Status));
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
AppendLog(ex.Message);
|
|
}
|
|
}
|
|
|
|
private void ExecuteWriteCommand(byte function)
|
|
{
|
|
try
|
|
{
|
|
var command = new ModbusCommand(function)
|
|
{
|
|
Offset = StartAddress,
|
|
Count = DataLength,
|
|
TransId = _transactionId++,
|
|
Data = new ushort[DataLength]
|
|
};
|
|
for (int i = 0; i < DataLength; i++)
|
|
{
|
|
var index = StartAddress + i;
|
|
if (index > _registerData.Length)
|
|
{
|
|
break;
|
|
}
|
|
command.Data[i] = _registerData[index];
|
|
}
|
|
var result = _driver.ExecuteGeneric(_portClient, command);
|
|
AppendLog(result.Status == CommResponse.Ack
|
|
? String.Format("Write succeeded: Function code:{0}", function)
|
|
: String.Format("Failed to execute Write: Error code:{0}", result.Status));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
AppendLog(ex.Message);
|
|
}
|
|
}
|
|
|
|
|
|
private void BtnWriteSingleCoilClick(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
var command = new ModbusCommand(ModbusCommand.FuncWriteCoil)
|
|
{
|
|
Offset = StartAddress,
|
|
Count = 1,
|
|
TransId = _transactionId++,
|
|
Data = new ushort[1]
|
|
};
|
|
command.Data[0] = (ushort)(_registerData[StartAddress] & 0x0100);
|
|
var result = _driver.ExecuteGeneric(_portClient, command);
|
|
AppendLog(result.Status == CommResponse.Ack
|
|
? String.Format("Write succeeded: Function code:{0}", ModbusCommand.FuncWriteCoil)
|
|
: String.Format("Failed to execute Write: Error code:{0}", result.Status));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
AppendLog(ex.Message);
|
|
}
|
|
}
|
|
|
|
private void BtnWriteSingleRegClick(object sender, EventArgs e)
|
|
{
|
|
ExecuteWriteCommand(ModbusCommand.FuncWriteSingleRegister);
|
|
}
|
|
|
|
private void BtnWriteMultipleCoilsClick(object sender, EventArgs e)
|
|
{
|
|
ExecuteWriteCommand(ModbusCommand.FuncForceMultipleCoils);
|
|
}
|
|
|
|
private void BtnWriteMultipleRegClick(object sender, EventArgs e)
|
|
{
|
|
ExecuteWriteCommand(ModbusCommand.FuncWriteMultipleRegisters);
|
|
}
|
|
|
|
private void ButtonReadExceptionStatusClick(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void txtPollDelay_Leave(object sender, EventArgs e)
|
|
{
|
|
var textBox = (TextBox)sender;
|
|
if (int.TryParse(textBox.Text, out var parsedMillisecs))
|
|
{
|
|
pollTimer.Interval = parsedMillisecs;
|
|
}
|
|
else
|
|
{
|
|
textBox.Text = "0";
|
|
cbPoll.Checked = false;
|
|
pollTimer.Enabled = false;
|
|
}
|
|
|
|
}
|
|
|
|
private void cbPoll_CheckStateChanged(object sender, EventArgs e)
|
|
{
|
|
pollTimer.Enabled = cbPoll.Checked;
|
|
|
|
if (!pollTimer.Enabled)
|
|
_lastReadCommand = 0;
|
|
}
|
|
|
|
private void pollTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
if (_lastReadCommand != 0)
|
|
ExecuteReadCommand(_lastReadCommand);
|
|
}
|
|
|
|
private void MasterForm_Load(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|