Files
DevToolsAvalonia/常用工具集/Utility/Network/Modbus/EasyModbus/ModbusServer.cs
2025-08-26 08:37:44 +08:00

2277 lines
91 KiB
C#

/*
Copyright (c) 2018-2020 Rossmann-Engineering
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software
and associated documentation files (the "Software"),
to deal in the Software without restriction,
including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission
notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Net.NetworkInformation;
using System.IO.Ports;
namespace EasyModbus
{
#region class ModbusProtocol
/// <summary>
/// Modbus Protocol informations.
/// </summary>
public class ModbusProtocol
{
public enum ProtocolType { ModbusTCP = 0, ModbusUDP = 1, ModbusRTU = 2 };
public DateTime timeStamp;
public bool request;
public bool response;
public UInt16 transactionIdentifier;
public UInt16 protocolIdentifier;
public UInt16 length;
public byte unitIdentifier;
public byte functionCode;
public UInt16 startingAdress;
public UInt16 startingAddressRead;
public UInt16 startingAddressWrite;
public UInt16 quantity;
public UInt16 quantityRead;
public UInt16 quantityWrite;
public byte byteCount;
public byte exceptionCode;
public byte errorCode;
public UInt16[] receiveCoilValues;
public UInt16[] receiveRegisterValues;
public Int16[] sendRegisterValues;
public bool[] sendCoilValues;
public UInt16 crc;
}
#endregion
#region structs
struct NetworkConnectionParameter
{
public NetworkStream stream; //For TCP-Connection only
public Byte[] bytes;
public int portIn; //For UDP-Connection only
public IPAddress ipAddressIn; //For UDP-Connection only
}
#endregion
#region TCPHandler class
internal class TCPHandler
{
public delegate void DataChanged(object networkConnectionParameter);
public event DataChanged dataChanged;
public delegate void NumberOfClientsChanged();
public event NumberOfClientsChanged numberOfClientsChanged;
TcpListener server = null;
private List<Client> tcpClientLastRequestList = new List<Client>();
public int NumberOfConnectedClients { get; set; }
public string ipAddress = null;
/// When making a server TCP listen socket, will listen to this IP address.
public IPAddress LocalIPAddress
{
get { return localIPAddress; }
}
private IPAddress localIPAddress = IPAddress.Any;
/// <summary>
/// Listen to all network interfaces.
/// </summary>
/// <param name="port">TCP port to listen</param>
public TCPHandler(int port)
{
server = new TcpListener(LocalIPAddress, port);
server.Start();
server.BeginAcceptTcpClient(AcceptTcpClientCallback, null);
}
/// <summary>
/// Listen to a specific network interface.
/// </summary>
/// <param name="localIPAddress">IP address of network interface to listen</param>
/// <param name="port">TCP port to listen</param>
public TCPHandler(IPAddress localIPAddress, int port)
{
this.localIPAddress = localIPAddress;
server = new TcpListener(LocalIPAddress, port);
server.Start();
server.BeginAcceptTcpClient(AcceptTcpClientCallback, null);
}
private void AcceptTcpClientCallback(IAsyncResult asyncResult)
{
TcpClient tcpClient = new TcpClient();
try
{
tcpClient = server.EndAcceptTcpClient(asyncResult);
tcpClient.ReceiveTimeout = 4000;
if (ipAddress != null)
{
string ipEndpoint = tcpClient.Client.RemoteEndPoint.ToString();
ipEndpoint = ipEndpoint.Split(':')[0];
if (ipEndpoint != ipAddress)
{
tcpClient.Client.Disconnect(false);
return;
}
}
}
catch (Exception) { }
try
{
server.BeginAcceptTcpClient(AcceptTcpClientCallback, null);
Client client = new Client(tcpClient);
NetworkStream networkStream = client.NetworkStream;
networkStream.ReadTimeout = 4000;
networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, ReadCallback, client);
}
catch (Exception) { }
}
private int GetAndCleanNumberOfConnectedClients(Client client)
{
lock (this)
{
int i = 0;
bool objetExists = false;
foreach (Client clientLoop in tcpClientLastRequestList)
{
if (client.Equals(clientLoop))
objetExists = true;
}
try
{
tcpClientLastRequestList.RemoveAll(delegate (Client c)
{
return ((DateTime.Now.Ticks - c.Ticks) > 40000000);
}
);
}
catch (Exception) { }
if (!objetExists)
tcpClientLastRequestList.Add(client);
return tcpClientLastRequestList.Count;
}
}
private void ReadCallback(IAsyncResult asyncResult)
{
NetworkConnectionParameter networkConnectionParameter = new NetworkConnectionParameter();
Client client = asyncResult.AsyncState as Client;
client.Ticks = DateTime.Now.Ticks;
NumberOfConnectedClients = GetAndCleanNumberOfConnectedClients(client);
if (numberOfClientsChanged != null)
numberOfClientsChanged();
if (client != null)
{
int read;
NetworkStream networkStream = null;
try
{
networkStream = client.NetworkStream;
read = networkStream.EndRead(asyncResult);
}
catch (Exception ex)
{
return;
}
if (read == 0)
{
//OnClientDisconnected(client.TcpClient);
//connectedClients.Remove(client);
return;
}
byte[] data = new byte[read];
Buffer.BlockCopy(client.Buffer, 0, data, 0, read);
networkConnectionParameter.bytes = data;
networkConnectionParameter.stream = networkStream;
if (dataChanged != null)
dataChanged(networkConnectionParameter);
try
{
networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, ReadCallback, client);
}
catch (Exception)
{
}
}
}
public void Disconnect()
{
try
{
foreach (Client clientLoop in tcpClientLastRequestList)
{
clientLoop.NetworkStream.Close(00);
}
}
catch (Exception) { }
server.Stop();
}
internal class Client
{
private readonly TcpClient tcpClient;
private readonly byte[] buffer;
public long Ticks { get; set; }
public Client(TcpClient tcpClient)
{
this.tcpClient = tcpClient;
int bufferSize = tcpClient.ReceiveBufferSize;
buffer = new byte[bufferSize];
}
public TcpClient TcpClient
{
get { return tcpClient; }
}
public byte[] Buffer
{
get { return buffer; }
}
public NetworkStream NetworkStream
{
get
{
return tcpClient.GetStream();
}
}
}
}
#endregion
/// <summary>
/// Modbus TCP Server.
/// </summary>
public class ModbusServer : IDisposable
{
private bool debug = false;
int port;
ModbusProtocol receiveData;
ModbusProtocol sendData = new ModbusProtocol();
byte[] bytes = new byte[2100];
public HoldingRegisters holdingRegisters;
public InputRegisters inputRegisters;
public Coils coils;
public DiscreteInputs discreteInputs;
private int numberOfConnections = 0;
private bool udpFlag;
private bool serialFlag;
private int baudrate = 9600;
private Parity parity = Parity.Even;
private StopBits stopBits = StopBits.One;
private string serialPort = "COM1";
private SerialPort serialport;
private byte unitIdentifier = 1;
private int portIn;
private IPAddress ipAddressIn;
private UdpClient udpClient;
private IPEndPoint iPEndPoint;
private TCPHandler tcpHandler;
Thread listenerThread;
Thread clientConnectionThread;
private ModbusProtocol[] modbusLogData = new ModbusProtocol[100];
public bool FunctionCode1Disabled { get; set; }
public bool FunctionCode2Disabled { get; set; }
public bool FunctionCode3Disabled { get; set; }
public bool FunctionCode4Disabled { get; set; }
public bool FunctionCode5Disabled { get; set; }
public bool FunctionCode6Disabled { get; set; }
public bool FunctionCode15Disabled { get; set; }
public bool FunctionCode16Disabled { get; set; }
public bool FunctionCode23Disabled { get; set; }
public bool PortChanged { get; set; }
object lockCoils = new object();
object lockHoldingRegisters = new object();
private volatile bool shouldStop;
private bool stop;
private IPAddress localIPAddress = IPAddress.Any;
/// <summary>
/// When creating a TCP or UDP socket, the local IP address to attach to.
/// </summary>
public IPAddress LocalIPAddress
{
get { return localIPAddress; }
set { if (listenerThread == null) localIPAddress = value; }
}
public ModbusServer(int port = 502)
{
this.port = port;
holdingRegisters = new HoldingRegisters(this);
inputRegisters = new InputRegisters(this);
coils = new Coils(this);
discreteInputs = new DiscreteInputs(this);
}
#region events
public delegate void CoilsChangedHandler(int coil, int numberOfCoils);
public event CoilsChangedHandler CoilsChanged;
public delegate void HoldingRegistersChangedHandler(int register, int numberOfRegisters);
public event HoldingRegistersChangedHandler HoldingRegistersChanged;
public delegate void NumberOfConnectedClientsChangedHandler();
public event NumberOfConnectedClientsChangedHandler NumberOfConnectedClientsChanged;
public delegate void LogDataChangedHandler();
public event LogDataChangedHandler LogDataChanged;
#endregion
public void Start()
{
listenerThread = new Thread(ListenerThread);
listenerThread.Start();
}
public void Dispose()
{
Stop();
}
public void Stop()
{
if (SerialFlag & (serialport != null))
{
if (serialport.IsOpen)
serialport.Close();
shouldStop = true;
}
try
{
tcpHandler.Disconnect();
stop = true;
listenerThread.Interrupt();
}
catch (Exception) { }
listenerThread.Join();
try
{
stop = true;
clientConnectionThread.Interrupt();
}
catch (Exception) { }
}
private void ListenerThread()
{
if (!udpFlag & !serialFlag)
{
if (udpClient != null)
{
try
{
udpClient.Close();
}
catch (Exception) { }
}
tcpHandler = new TCPHandler(LocalIPAddress, port);
if (debug) StoreLogData.Instance.Store($"EasyModbus Server listing for incomming data at Port {port}, local IP {LocalIPAddress}", System.DateTime.Now);
tcpHandler.dataChanged += new TCPHandler.DataChanged(ProcessReceivedData);
tcpHandler.numberOfClientsChanged += new TCPHandler.NumberOfClientsChanged(numberOfClientsChanged);
}
else if (serialFlag)
{
if (serialport == null)
{
if (debug) StoreLogData.Instance.Store("EasyModbus RTU-Server listing for incomming data at Serial Port " + serialPort, System.DateTime.Now);
serialport = new SerialPort();
serialport.PortName = serialPort;
serialport.BaudRate = this.baudrate;
serialport.Parity = this.parity;
serialport.StopBits = stopBits;
serialport.WriteTimeout = 10000;
serialport.ReadTimeout = 1000;
serialport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
serialport.Open();
}
}
else
while (!shouldStop)
{
if (stop)
break;
if (udpFlag)
{
if (udpClient == null | PortChanged)
{
IPEndPoint localEndoint = new IPEndPoint(LocalIPAddress, port);
udpClient = new UdpClient(localEndoint);
if (debug) StoreLogData.Instance.Store($"EasyModbus Server listing for incomming data at Port {port}, local IP {LocalIPAddress}", System.DateTime.Now);
udpClient.Client.ReceiveTimeout = 1000;
iPEndPoint = new IPEndPoint(IPAddress.Any, port);
PortChanged = false;
}
if (tcpHandler != null)
tcpHandler.Disconnect();
try
{
bytes = udpClient.Receive(ref iPEndPoint);
portIn = iPEndPoint.Port;
NetworkConnectionParameter networkConnectionParameter = new NetworkConnectionParameter();
networkConnectionParameter.bytes = bytes;
ipAddressIn = iPEndPoint.Address;
networkConnectionParameter.portIn = portIn;
networkConnectionParameter.ipAddressIn = ipAddressIn;
ParameterizedThreadStart pts = new ParameterizedThreadStart(this.ProcessReceivedData);
Thread processDataThread = new Thread(pts);
processDataThread.Start(networkConnectionParameter);
}
catch (Exception ex)
{
if (ex is ThreadInterruptedException)
break;
}
}
}
}
#region SerialHandler
private bool dataReceived = false;
private byte[] readBuffer = new byte[2094];
private DateTime lastReceive;
private int nextSign = 0;
private void DataReceivedHandler(object sender,
SerialDataReceivedEventArgs e)
{
int silence = 4000 / baudrate;
if ((DateTime.Now.Ticks - lastReceive.Ticks) > TimeSpan.TicksPerMillisecond * silence)
nextSign = 0;
SerialPort sp = (SerialPort)sender;
int numbytes = sp.BytesToRead;
byte[] rxbytearray = new byte[numbytes];
sp.Read(rxbytearray, 0, numbytes);
Array.Copy(rxbytearray, 0, readBuffer, nextSign, rxbytearray.Length);
lastReceive = DateTime.Now;
nextSign = numbytes + nextSign;
if (ModbusClient.DetectValidModbusFrame(readBuffer, nextSign))
{
dataReceived = true;
nextSign = 0;
NetworkConnectionParameter networkConnectionParameter = new NetworkConnectionParameter();
networkConnectionParameter.bytes = readBuffer;
ParameterizedThreadStart pts = new ParameterizedThreadStart(this.ProcessReceivedData);
Thread processDataThread = new Thread(pts);
processDataThread.Start(networkConnectionParameter);
dataReceived = false;
}
else
dataReceived = false;
}
#endregion
#region Method numberOfClientsChanged
private void numberOfClientsChanged()
{
numberOfConnections = tcpHandler.NumberOfConnectedClients;
if (NumberOfConnectedClientsChanged != null)
NumberOfConnectedClientsChanged();
}
#endregion
object lockProcessReceivedData = new object();
#region Method ProcessReceivedData
private void ProcessReceivedData(object networkConnectionParameter)
{
lock (lockProcessReceivedData)
{
Byte[] bytes = new byte[((NetworkConnectionParameter)networkConnectionParameter).bytes.Length];
if (debug) StoreLogData.Instance.Store("Received Data: " + BitConverter.ToString(bytes), System.DateTime.Now);
NetworkStream stream = ((NetworkConnectionParameter)networkConnectionParameter).stream;
int portIn = ((NetworkConnectionParameter)networkConnectionParameter).portIn;
IPAddress ipAddressIn = ((NetworkConnectionParameter)networkConnectionParameter).ipAddressIn;
Array.Copy(((NetworkConnectionParameter)networkConnectionParameter).bytes, 0, bytes, 0, ((NetworkConnectionParameter)networkConnectionParameter).bytes.Length);
ModbusProtocol receiveDataThread = new ModbusProtocol();
ModbusProtocol sendDataThread = new ModbusProtocol();
try
{
UInt16[] wordData = new UInt16[1];
byte[] byteData = new byte[2];
receiveDataThread.timeStamp = DateTime.Now;
receiveDataThread.request = true;
if (!serialFlag)
{
//Lese Transaction identifier
byteData[1] = bytes[0];
byteData[0] = bytes[1];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.transactionIdentifier = wordData[0];
//Lese Protocol identifier
byteData[1] = bytes[2];
byteData[0] = bytes[3];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.protocolIdentifier = wordData[0];
//Lese length
byteData[1] = bytes[4];
byteData[0] = bytes[5];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.length = wordData[0];
}
//Lese unit identifier
receiveDataThread.unitIdentifier = bytes[6 - 6 * Convert.ToInt32(serialFlag)];
//Check UnitIdentifier
if ((receiveDataThread.unitIdentifier != this.unitIdentifier) & (receiveDataThread.unitIdentifier != 0))
return;
// Lese function code
receiveDataThread.functionCode = bytes[7 - 6 * Convert.ToInt32(serialFlag)];
// Lese starting address
byteData[1] = bytes[8 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[9 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.startingAdress = wordData[0];
if (receiveDataThread.functionCode <= 4)
{
// Lese quantity
byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.quantity = wordData[0];
}
if (receiveDataThread.functionCode == 5)
{
receiveDataThread.receiveCoilValues = new ushort[1];
// Lese Value
byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, receiveDataThread.receiveCoilValues, 0, 2);
}
if (receiveDataThread.functionCode == 6)
{
receiveDataThread.receiveRegisterValues = new ushort[1];
// Lese Value
byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, receiveDataThread.receiveRegisterValues, 0, 2);
}
if (receiveDataThread.functionCode == 15)
{
// Lese quantity
byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.quantity = wordData[0];
receiveDataThread.byteCount = bytes[12 - 6 * Convert.ToInt32(serialFlag)];
if ((receiveDataThread.byteCount % 2) != 0)
receiveDataThread.receiveCoilValues = new ushort[receiveDataThread.byteCount / 2 + 1];
else
receiveDataThread.receiveCoilValues = new ushort[receiveDataThread.byteCount / 2];
// Lese Value
Buffer.BlockCopy(bytes, 13 - 6 * Convert.ToInt32(serialFlag), receiveDataThread.receiveCoilValues, 0, receiveDataThread.byteCount);
}
if (receiveDataThread.functionCode == 16)
{
// Lese quantity
byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.quantity = wordData[0];
receiveDataThread.byteCount = bytes[12 - 6 * Convert.ToInt32(serialFlag)];
receiveDataThread.receiveRegisterValues = new ushort[receiveDataThread.quantity];
for (int i = 0; i < receiveDataThread.quantity; i++)
{
// Lese Value
byteData[1] = bytes[13 + i * 2 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[14 + i * 2 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, receiveDataThread.receiveRegisterValues, i * 2, 2);
}
}
if (receiveDataThread.functionCode == 23)
{
// Lese starting Address Read
byteData[1] = bytes[8 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[9 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.startingAddressRead = wordData[0];
// Lese quantity Read
byteData[1] = bytes[10 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[11 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.quantityRead = wordData[0];
// Lese starting Address Write
byteData[1] = bytes[12 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[13 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.startingAddressWrite = wordData[0];
// Lese quantity Write
byteData[1] = bytes[14 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[15 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, wordData, 0, 2);
receiveDataThread.quantityWrite = wordData[0];
receiveDataThread.byteCount = bytes[16 - 6 * Convert.ToInt32(serialFlag)];
receiveDataThread.receiveRegisterValues = new ushort[receiveDataThread.quantityWrite];
for (int i = 0; i < receiveDataThread.quantityWrite; i++)
{
// Lese Value
byteData[1] = bytes[17 + i * 2 - 6 * Convert.ToInt32(serialFlag)];
byteData[0] = bytes[18 + i * 2 - 6 * Convert.ToInt32(serialFlag)];
Buffer.BlockCopy(byteData, 0, receiveDataThread.receiveRegisterValues, i * 2, 2);
}
}
}
catch (Exception exc)
{ }
this.CreateAnswer(receiveDataThread, sendDataThread, stream, portIn, ipAddressIn);
//this.sendAnswer();
this.CreateLogData(receiveDataThread, sendDataThread);
if (LogDataChanged != null)
LogDataChanged();
}
}
#endregion
#region Method CreateAnswer
private void CreateAnswer(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
switch (receiveData.functionCode)
{
// Read Coils
case 1:
if (!FunctionCode1Disabled)
this.ReadCoils(receiveData, sendData, stream, portIn, ipAddressIn);
else
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 1;
sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn);
}
break;
// Read Input Registers
case 2:
if (!FunctionCode2Disabled)
this.ReadDiscreteInputs(receiveData, sendData, stream, portIn, ipAddressIn);
else
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 1;
sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn);
}
break;
// Read Holding Registers
case 3:
if (!FunctionCode3Disabled)
this.ReadHoldingRegisters(receiveData, sendData, stream, portIn, ipAddressIn);
else
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 1;
sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn);
}
break;
// Read Input Registers
case 4:
if (!FunctionCode4Disabled)
this.ReadInputRegisters(receiveData, sendData, stream, portIn, ipAddressIn);
else
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 1;
sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn);
}
break;
// Write single coil
case 5:
if (!FunctionCode5Disabled)
this.WriteSingleCoil(receiveData, sendData, stream, portIn, ipAddressIn);
else
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 1;
sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn);
}
break;
// Write single register
case 6:
if (!FunctionCode6Disabled)
this.WriteSingleRegister(receiveData, sendData, stream, portIn, ipAddressIn);
else
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 1;
sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn);
}
break;
// Write Multiple coils
case 15:
if (!FunctionCode15Disabled)
this.WriteMultipleCoils(receiveData, sendData, stream, portIn, ipAddressIn);
else
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 1;
sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn);
}
break;
// Write Multiple registers
case 16:
if (!FunctionCode16Disabled)
this.WriteMultipleRegisters(receiveData, sendData, stream, portIn, ipAddressIn);
else
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 1;
sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn);
}
break;
// Error: Function Code not supported
case 23:
if (!FunctionCode23Disabled)
this.ReadWriteMultipleRegisters(receiveData, sendData, stream, portIn, ipAddressIn);
else
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 1;
sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn);
}
break;
// Error: Function Code not supported
default:
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 1;
sendException(sendData.errorCode, sendData.exceptionCode, receiveData, sendData, stream, portIn, ipAddressIn);
break;
}
sendData.timeStamp = DateTime.Now;
}
#endregion
private void ReadCoils(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
sendData.response = true;
sendData.transactionIdentifier = receiveData.transactionIdentifier;
sendData.protocolIdentifier = receiveData.protocolIdentifier;
sendData.unitIdentifier = this.unitIdentifier;
sendData.functionCode = receiveData.functionCode;
if ((receiveData.quantity < 1) | (receiveData.quantity > 0x07D0)) //Invalid quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 3;
}
if (((receiveData.startingAdress + 1 + receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 2;
}
if (sendData.exceptionCode == 0)
{
if ((receiveData.quantity % 8) == 0)
sendData.byteCount = (byte)(receiveData.quantity / 8);
else
sendData.byteCount = (byte)(receiveData.quantity / 8 + 1);
sendData.sendCoilValues = new bool[receiveData.quantity];
lock (lockCoils)
Array.Copy(coils.localArray, receiveData.startingAdress + 1, sendData.sendCoilValues, 0, receiveData.quantity);
}
if (true)
{
Byte[] data;
if (sendData.exceptionCode > 0)
data = new byte[9 + 2 * Convert.ToInt32(serialFlag)];
else
data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)];
Byte[] byteData = new byte[2];
sendData.length = (byte)(data.Length - 6);
//Send Transaction identifier
byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier);
data[0] = byteData[1];
data[1] = byteData[0];
//Send Protocol identifier
byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier);
data[2] = byteData[1];
data[3] = byteData[0];
//Send length
byteData = BitConverter.GetBytes((int)sendData.length);
data[4] = byteData[1];
data[5] = byteData[0];
//Unit Identifier
data[6] = sendData.unitIdentifier;
//Function Code
data[7] = sendData.functionCode;
//ByteCount
data[8] = sendData.byteCount;
if (sendData.exceptionCode > 0)
{
data[7] = sendData.errorCode;
data[8] = sendData.exceptionCode;
sendData.sendCoilValues = null;
}
if (sendData.sendCoilValues != null)
for (int i = 0; i < (sendData.byteCount); i++)
{
byteData = new byte[2];
for (int j = 0; j < 8; j++)
{
byte boolValue;
if (sendData.sendCoilValues[i * 8 + j] == true)
boolValue = 1;
else
boolValue = 0;
byteData[1] = (byte)((byteData[1]) | (boolValue << j));
if ((i * 8 + j + 1) >= sendData.sendCoilValues.Length)
break;
}
data[9 + i] = byteData[1];
}
try
{
if (serialFlag)
{
if (!serialport.IsOpen)
throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
//Create CRC
sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6);
byteData = BitConverter.GetBytes((int)sendData.crc);
data[data.Length - 2] = byteData[0];
data[data.Length - 1] = byteData[1];
serialport.Write(data, 6, data.Length - 6);
if (debug)
{
byte[] debugData = new byte[data.Length - 6];
Array.Copy(data, 6, debugData, 0, data.Length - 6);
if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
}
}
else if (udpFlag)
{
//UdpClient udpClient = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
udpClient.Send(data, data.Length, endPoint);
}
else
{
stream.Write(data, 0, data.Length);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
}
}
catch (Exception) { }
}
}
private void ReadDiscreteInputs(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
sendData.response = true;
sendData.transactionIdentifier = receiveData.transactionIdentifier;
sendData.protocolIdentifier = receiveData.protocolIdentifier;
sendData.unitIdentifier = this.unitIdentifier;
sendData.functionCode = receiveData.functionCode;
if ((receiveData.quantity < 1) | (receiveData.quantity > 0x07D0)) //Invalid quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 3;
}
if (((receiveData.startingAdress + 1 + receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 2;
}
if (sendData.exceptionCode == 0)
{
if ((receiveData.quantity % 8) == 0)
sendData.byteCount = (byte)(receiveData.quantity / 8);
else
sendData.byteCount = (byte)(receiveData.quantity / 8 + 1);
sendData.sendCoilValues = new bool[receiveData.quantity];
Array.Copy(discreteInputs.localArray, receiveData.startingAdress + 1, sendData.sendCoilValues, 0, receiveData.quantity);
}
if (true)
{
Byte[] data;
if (sendData.exceptionCode > 0)
data = new byte[9 + 2 * Convert.ToInt32(serialFlag)];
else
data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)];
Byte[] byteData = new byte[2];
sendData.length = (byte)(data.Length - 6);
//Send Transaction identifier
byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier);
data[0] = byteData[1];
data[1] = byteData[0];
//Send Protocol identifier
byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier);
data[2] = byteData[1];
data[3] = byteData[0];
//Send length
byteData = BitConverter.GetBytes((int)sendData.length);
data[4] = byteData[1];
data[5] = byteData[0];
//Unit Identifier
data[6] = sendData.unitIdentifier;
//Function Code
data[7] = sendData.functionCode;
//ByteCount
data[8] = sendData.byteCount;
if (sendData.exceptionCode > 0)
{
data[7] = sendData.errorCode;
data[8] = sendData.exceptionCode;
sendData.sendCoilValues = null;
}
if (sendData.sendCoilValues != null)
for (int i = 0; i < (sendData.byteCount); i++)
{
byteData = new byte[2];
for (int j = 0; j < 8; j++)
{
byte boolValue;
if (sendData.sendCoilValues[i * 8 + j] == true)
boolValue = 1;
else
boolValue = 0;
byteData[1] = (byte)((byteData[1]) | (boolValue << j));
if ((i * 8 + j + 1) >= sendData.sendCoilValues.Length)
break;
}
data[9 + i] = byteData[1];
}
try
{
if (serialFlag)
{
if (!serialport.IsOpen)
throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
//Create CRC
sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6);
byteData = BitConverter.GetBytes((int)sendData.crc);
data[data.Length - 2] = byteData[0];
data[data.Length - 1] = byteData[1];
serialport.Write(data, 6, data.Length - 6);
if (debug)
{
byte[] debugData = new byte[data.Length - 6];
Array.Copy(data, 6, debugData, 0, data.Length - 6);
if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
}
}
else if (udpFlag)
{
//UdpClient udpClient = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn);
udpClient.Send(data, data.Length, endPoint);
}
else
{
stream.Write(data, 0, data.Length);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
}
}
catch (Exception) { }
}
}
private void ReadHoldingRegisters(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
sendData.response = true;
sendData.transactionIdentifier = receiveData.transactionIdentifier;
sendData.protocolIdentifier = receiveData.protocolIdentifier;
sendData.unitIdentifier = this.unitIdentifier;
sendData.functionCode = receiveData.functionCode;
if ((receiveData.quantity < 1) | (receiveData.quantity > 0x007D)) //Invalid quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 3;
}
if (((receiveData.startingAdress + 1 + receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 2;
}
if (sendData.exceptionCode == 0)
{
sendData.byteCount = (byte)(2 * receiveData.quantity);
sendData.sendRegisterValues = new Int16[receiveData.quantity];
lock (lockHoldingRegisters)
Buffer.BlockCopy(holdingRegisters.localArray, receiveData.startingAdress * 2 + 2, sendData.sendRegisterValues, 0, receiveData.quantity * 2);
}
if (sendData.exceptionCode > 0)
sendData.length = 0x03;
else
sendData.length = (ushort)(0x03 + sendData.byteCount);
if (true)
{
Byte[] data;
if (sendData.exceptionCode > 0)
data = new byte[9 + 2 * Convert.ToInt32(serialFlag)];
else
data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)];
Byte[] byteData = new byte[2];
sendData.length = (byte)(data.Length - 6);
//Send Transaction identifier
byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier);
data[0] = byteData[1];
data[1] = byteData[0];
//Send Protocol identifier
byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier);
data[2] = byteData[1];
data[3] = byteData[0];
//Send length
byteData = BitConverter.GetBytes((int)sendData.length);
data[4] = byteData[1];
data[5] = byteData[0];
//Unit Identifier
data[6] = sendData.unitIdentifier;
//Function Code
data[7] = sendData.functionCode;
//ByteCount
data[8] = sendData.byteCount;
if (sendData.exceptionCode > 0)
{
data[7] = sendData.errorCode;
data[8] = sendData.exceptionCode;
sendData.sendRegisterValues = null;
}
if (sendData.sendRegisterValues != null)
for (int i = 0; i < (sendData.byteCount / 2); i++)
{
byteData = BitConverter.GetBytes((Int16)sendData.sendRegisterValues[i]);
data[9 + i * 2] = byteData[1];
data[10 + i * 2] = byteData[0];
}
try
{
if (serialFlag)
{
if (!serialport.IsOpen)
throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
//Create CRC
sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6);
byteData = BitConverter.GetBytes((int)sendData.crc);
data[data.Length - 2] = byteData[0];
data[data.Length - 1] = byteData[1];
serialport.Write(data, 6, data.Length - 6);
if (debug)
{
byte[] debugData = new byte[data.Length - 6];
Array.Copy(data, 6, debugData, 0, data.Length - 6);
if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
}
}
else if (udpFlag)
{
//UdpClient udpClient = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn);
udpClient.Send(data, data.Length, endPoint);
}
else
{
stream.Write(data, 0, data.Length);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
}
}
catch (Exception) { }
}
}
private void ReadInputRegisters(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
sendData.response = true;
sendData.transactionIdentifier = receiveData.transactionIdentifier;
sendData.protocolIdentifier = receiveData.protocolIdentifier;
sendData.unitIdentifier = this.unitIdentifier;
sendData.functionCode = receiveData.functionCode;
if ((receiveData.quantity < 1) | (receiveData.quantity > 0x007D)) //Invalid quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 3;
}
if (((receiveData.startingAdress + 1 + receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 2;
}
if (sendData.exceptionCode == 0)
{
sendData.byteCount = (byte)(2 * receiveData.quantity);
sendData.sendRegisterValues = new Int16[receiveData.quantity];
Buffer.BlockCopy(inputRegisters.localArray, receiveData.startingAdress * 2 + 2, sendData.sendRegisterValues, 0, receiveData.quantity * 2);
}
if (sendData.exceptionCode > 0)
sendData.length = 0x03;
else
sendData.length = (ushort)(0x03 + sendData.byteCount);
if (true)
{
Byte[] data;
if (sendData.exceptionCode > 0)
data = new byte[9 + 2 * Convert.ToInt32(serialFlag)];
else
data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)];
Byte[] byteData = new byte[2];
sendData.length = (byte)(data.Length - 6);
//Send Transaction identifier
byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier);
data[0] = byteData[1];
data[1] = byteData[0];
//Send Protocol identifier
byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier);
data[2] = byteData[1];
data[3] = byteData[0];
//Send length
byteData = BitConverter.GetBytes((int)sendData.length);
data[4] = byteData[1];
data[5] = byteData[0];
//Unit Identifier
data[6] = sendData.unitIdentifier;
//Function Code
data[7] = sendData.functionCode;
//ByteCount
data[8] = sendData.byteCount;
if (sendData.exceptionCode > 0)
{
data[7] = sendData.errorCode;
data[8] = sendData.exceptionCode;
sendData.sendRegisterValues = null;
}
if (sendData.sendRegisterValues != null)
for (int i = 0; i < (sendData.byteCount / 2); i++)
{
byteData = BitConverter.GetBytes((Int16)sendData.sendRegisterValues[i]);
data[9 + i * 2] = byteData[1];
data[10 + i * 2] = byteData[0];
}
try
{
if (serialFlag)
{
if (!serialport.IsOpen)
throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
//Create CRC
sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6);
byteData = BitConverter.GetBytes((int)sendData.crc);
data[data.Length - 2] = byteData[0];
data[data.Length - 1] = byteData[1];
serialport.Write(data, 6, data.Length - 6);
if (debug)
{
byte[] debugData = new byte[data.Length - 6];
Array.Copy(data, 6, debugData, 0, data.Length - 6);
if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
}
}
else if (udpFlag)
{
//UdpClient udpClient = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn);
udpClient.Send(data, data.Length, endPoint);
}
else
{
stream.Write(data, 0, data.Length);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
}
}
catch (Exception) { }
}
}
private void WriteSingleCoil(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
sendData.response = true;
sendData.transactionIdentifier = receiveData.transactionIdentifier;
sendData.protocolIdentifier = receiveData.protocolIdentifier;
sendData.unitIdentifier = this.unitIdentifier;
sendData.functionCode = receiveData.functionCode;
sendData.startingAdress = receiveData.startingAdress;
sendData.receiveCoilValues = receiveData.receiveCoilValues;
if ((receiveData.receiveCoilValues[0] != 0x0000) & (receiveData.receiveCoilValues[0] != 0xFF00)) //Invalid Value
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 3;
}
if (((receiveData.startingAdress + 1) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 2;
}
if (sendData.exceptionCode == 0)
{
if (receiveData.receiveCoilValues[0] == 0xFF00)
{
lock (lockCoils)
coils[receiveData.startingAdress + 1] = true;
}
if (receiveData.receiveCoilValues[0] == 0x0000)
{
lock (lockCoils)
coils[receiveData.startingAdress + 1] = false;
}
}
if (sendData.exceptionCode > 0)
sendData.length = 0x03;
else
sendData.length = 0x06;
if (true)
{
Byte[] data;
if (sendData.exceptionCode > 0)
data = new byte[9 + 2 * Convert.ToInt32(serialFlag)];
else
data = new byte[12 + 2 * Convert.ToInt32(serialFlag)];
Byte[] byteData = new byte[2];
sendData.length = (byte)(data.Length - 6);
//Send Transaction identifier
byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier);
data[0] = byteData[1];
data[1] = byteData[0];
//Send Protocol identifier
byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier);
data[2] = byteData[1];
data[3] = byteData[0];
//Send length
byteData = BitConverter.GetBytes((int)sendData.length);
data[4] = byteData[1];
data[5] = byteData[0];
//Unit Identifier
data[6] = sendData.unitIdentifier;
//Function Code
data[7] = sendData.functionCode;
if (sendData.exceptionCode > 0)
{
data[7] = sendData.errorCode;
data[8] = sendData.exceptionCode;
sendData.sendRegisterValues = null;
}
else
{
byteData = BitConverter.GetBytes((int)receiveData.startingAdress);
data[8] = byteData[1];
data[9] = byteData[0];
byteData = BitConverter.GetBytes((int)receiveData.receiveCoilValues[0]);
data[10] = byteData[1];
data[11] = byteData[0];
}
try
{
if (serialFlag)
{
if (!serialport.IsOpen)
throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
//Create CRC
sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6);
byteData = BitConverter.GetBytes((int)sendData.crc);
data[data.Length - 2] = byteData[0];
data[data.Length - 1] = byteData[1];
serialport.Write(data, 6, data.Length - 6);
if (debug)
{
byte[] debugData = new byte[data.Length - 6];
Array.Copy(data, 6, debugData, 0, data.Length - 6);
if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
}
}
else if (udpFlag)
{
//UdpClient udpClient = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn);
udpClient.Send(data, data.Length, endPoint);
}
else
{
stream.Write(data, 0, data.Length);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
}
}
catch (Exception) { }
if (CoilsChanged != null)
CoilsChanged(receiveData.startingAdress + 1, 1);
}
}
private void WriteSingleRegister(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
sendData.response = true;
sendData.transactionIdentifier = receiveData.transactionIdentifier;
sendData.protocolIdentifier = receiveData.protocolIdentifier;
sendData.unitIdentifier = this.unitIdentifier;
sendData.functionCode = receiveData.functionCode;
sendData.startingAdress = receiveData.startingAdress;
sendData.receiveRegisterValues = receiveData.receiveRegisterValues;
if ((receiveData.receiveRegisterValues[0] < 0x0000) | (receiveData.receiveRegisterValues[0] > 0xFFFF)) //Invalid Value
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 3;
}
if (((receiveData.startingAdress + 1) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 2;
}
if (sendData.exceptionCode == 0)
{
lock (lockHoldingRegisters)
holdingRegisters[receiveData.startingAdress + 1] = unchecked((ushort)receiveData.receiveRegisterValues[0]);
}
if (sendData.exceptionCode > 0)
sendData.length = 0x03;
else
sendData.length = 0x06;
if (true)
{
Byte[] data;
if (sendData.exceptionCode > 0)
data = new byte[9 + 2 * Convert.ToInt32(serialFlag)];
else
data = new byte[12 + 2 * Convert.ToInt32(serialFlag)];
Byte[] byteData = new byte[2];
sendData.length = (byte)(data.Length - 6);
//Send Transaction identifier
byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier);
data[0] = byteData[1];
data[1] = byteData[0];
//Send Protocol identifier
byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier);
data[2] = byteData[1];
data[3] = byteData[0];
//Send length
byteData = BitConverter.GetBytes((int)sendData.length);
data[4] = byteData[1];
data[5] = byteData[0];
//Unit Identifier
data[6] = sendData.unitIdentifier;
//Function Code
data[7] = sendData.functionCode;
if (sendData.exceptionCode > 0)
{
data[7] = sendData.errorCode;
data[8] = sendData.exceptionCode;
sendData.sendRegisterValues = null;
}
else
{
byteData = BitConverter.GetBytes((int)receiveData.startingAdress);
data[8] = byteData[1];
data[9] = byteData[0];
byteData = BitConverter.GetBytes((int)receiveData.receiveRegisterValues[0]);
data[10] = byteData[1];
data[11] = byteData[0];
}
try
{
if (serialFlag)
{
if (!serialport.IsOpen)
throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
//Create CRC
sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6);
byteData = BitConverter.GetBytes((int)sendData.crc);
data[data.Length - 2] = byteData[0];
data[data.Length - 1] = byteData[1];
serialport.Write(data, 6, data.Length - 6);
if (debug)
{
byte[] debugData = new byte[data.Length - 6];
Array.Copy(data, 6, debugData, 0, data.Length - 6);
if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
}
}
else if (udpFlag)
{
//UdpClient udpClient = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn);
udpClient.Send(data, data.Length, endPoint);
}
else
{
stream.Write(data, 0, data.Length);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
}
}
catch (Exception) { }
if (HoldingRegistersChanged != null)
HoldingRegistersChanged(receiveData.startingAdress + 1, 1);
}
}
private void WriteMultipleCoils(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
sendData.response = true;
sendData.transactionIdentifier = receiveData.transactionIdentifier;
sendData.protocolIdentifier = receiveData.protocolIdentifier;
sendData.unitIdentifier = this.unitIdentifier;
sendData.functionCode = receiveData.functionCode;
sendData.startingAdress = receiveData.startingAdress;
sendData.quantity = receiveData.quantity;
if ((receiveData.quantity == 0x0000) | (receiveData.quantity > 0x07B0)) //Invalid Quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 3;
}
if ((((int)receiveData.startingAdress + 1 + (int)receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 2;
}
if (sendData.exceptionCode == 0)
{
lock (lockCoils)
for (int i = 0; i < receiveData.quantity; i++)
{
int shift = i % 16;
/* if ((i == receiveData.quantity - 1) & (receiveData.quantity % 2 != 0))
{
if (shift < 8)
shift = shift + 8;
else
shift = shift - 8;
}*/
int mask = 0x1;
mask = mask << (shift);
if ((receiveData.receiveCoilValues[i / 16] & (ushort)mask) == 0)
coils[receiveData.startingAdress + i + 1] = false;
else
coils[receiveData.startingAdress + i + 1] = true;
}
}
if (sendData.exceptionCode > 0)
sendData.length = 0x03;
else
sendData.length = 0x06;
if (true)
{
Byte[] data;
if (sendData.exceptionCode > 0)
data = new byte[9 + 2 * Convert.ToInt32(serialFlag)];
else
data = new byte[12 + 2 * Convert.ToInt32(serialFlag)];
Byte[] byteData = new byte[2];
sendData.length = (byte)(data.Length - 6);
//Send Transaction identifier
byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier);
data[0] = byteData[1];
data[1] = byteData[0];
//Send Protocol identifier
byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier);
data[2] = byteData[1];
data[3] = byteData[0];
//Send length
byteData = BitConverter.GetBytes((int)sendData.length);
data[4] = byteData[1];
data[5] = byteData[0];
//Unit Identifier
data[6] = sendData.unitIdentifier;
//Function Code
data[7] = sendData.functionCode;
if (sendData.exceptionCode > 0)
{
data[7] = sendData.errorCode;
data[8] = sendData.exceptionCode;
sendData.sendRegisterValues = null;
}
else
{
byteData = BitConverter.GetBytes((int)receiveData.startingAdress);
data[8] = byteData[1];
data[9] = byteData[0];
byteData = BitConverter.GetBytes((int)receiveData.quantity);
data[10] = byteData[1];
data[11] = byteData[0];
}
try
{
if (serialFlag)
{
if (!serialport.IsOpen)
throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
//Create CRC
sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6);
byteData = BitConverter.GetBytes((int)sendData.crc);
data[data.Length - 2] = byteData[0];
data[data.Length - 1] = byteData[1];
serialport.Write(data, 6, data.Length - 6);
if (debug)
{
byte[] debugData = new byte[data.Length - 6];
Array.Copy(data, 6, debugData, 0, data.Length - 6);
if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
}
}
else if (udpFlag)
{
//UdpClient udpClient = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn);
udpClient.Send(data, data.Length, endPoint);
}
else
{
stream.Write(data, 0, data.Length);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
}
}
catch (Exception) { }
if (CoilsChanged != null)
CoilsChanged(receiveData.startingAdress + 1, receiveData.quantity);
}
}
private void WriteMultipleRegisters(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
sendData.response = true;
sendData.transactionIdentifier = receiveData.transactionIdentifier;
sendData.protocolIdentifier = receiveData.protocolIdentifier;
sendData.unitIdentifier = this.unitIdentifier;
sendData.functionCode = receiveData.functionCode;
sendData.startingAdress = receiveData.startingAdress;
sendData.quantity = receiveData.quantity;
if ((receiveData.quantity == 0x0000) | (receiveData.quantity > 0x07B0)) //Invalid Quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 3;
}
if ((((int)receiveData.startingAdress + 1 + (int)receiveData.quantity) > 65535) | (receiveData.startingAdress < 0)) //Invalid Starting adress or Starting address + quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 2;
}
if (sendData.exceptionCode == 0)
{
lock (lockHoldingRegisters)
for (int i = 0; i < receiveData.quantity; i++)
{
holdingRegisters[receiveData.startingAdress + i + 1] = unchecked((ushort)receiveData.receiveRegisterValues[i]);
}
}
if (sendData.exceptionCode > 0)
sendData.length = 0x03;
else
sendData.length = 0x06;
if (true)
{
Byte[] data;
if (sendData.exceptionCode > 0)
data = new byte[9 + 2 * Convert.ToInt32(serialFlag)];
else
data = new byte[12 + 2 * Convert.ToInt32(serialFlag)];
Byte[] byteData = new byte[2];
sendData.length = (byte)(data.Length - 6);
//Send Transaction identifier
byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier);
data[0] = byteData[1];
data[1] = byteData[0];
//Send Protocol identifier
byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier);
data[2] = byteData[1];
data[3] = byteData[0];
//Send length
byteData = BitConverter.GetBytes((int)sendData.length);
data[4] = byteData[1];
data[5] = byteData[0];
//Unit Identifier
data[6] = sendData.unitIdentifier;
//Function Code
data[7] = sendData.functionCode;
if (sendData.exceptionCode > 0)
{
data[7] = sendData.errorCode;
data[8] = sendData.exceptionCode;
sendData.sendRegisterValues = null;
}
else
{
byteData = BitConverter.GetBytes((int)receiveData.startingAdress);
data[8] = byteData[1];
data[9] = byteData[0];
byteData = BitConverter.GetBytes((int)receiveData.quantity);
data[10] = byteData[1];
data[11] = byteData[0];
}
try
{
if (serialFlag)
{
if (!serialport.IsOpen)
throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
//Create CRC
sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6);
byteData = BitConverter.GetBytes((int)sendData.crc);
data[data.Length - 2] = byteData[0];
data[data.Length - 1] = byteData[1];
serialport.Write(data, 6, data.Length - 6);
if (debug)
{
byte[] debugData = new byte[data.Length - 6];
Array.Copy(data, 6, debugData, 0, data.Length - 6);
if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
}
}
else if (udpFlag)
{
//UdpClient udpClient = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn);
udpClient.Send(data, data.Length, endPoint);
}
else
{
stream.Write(data, 0, data.Length);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
}
}
catch (Exception) { }
if (HoldingRegistersChanged != null)
HoldingRegistersChanged(receiveData.startingAdress + 1, receiveData.quantity);
}
}
private void ReadWriteMultipleRegisters(ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
sendData.response = true;
sendData.transactionIdentifier = receiveData.transactionIdentifier;
sendData.protocolIdentifier = receiveData.protocolIdentifier;
sendData.unitIdentifier = this.unitIdentifier;
sendData.functionCode = receiveData.functionCode;
if ((receiveData.quantityRead < 0x0001) | (receiveData.quantityRead > 0x007D) | (receiveData.quantityWrite < 0x0001) | (receiveData.quantityWrite > 0x0079) | (receiveData.byteCount != (receiveData.quantityWrite * 2))) //Invalid Quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 3;
}
if ((((int)receiveData.startingAddressRead + 1 + (int)receiveData.quantityRead) > 65535) | (((int)receiveData.startingAddressWrite + 1 + (int)receiveData.quantityWrite) > 65535) | (receiveData.quantityWrite < 0) | (receiveData.quantityRead < 0)) //Invalid Starting adress or Starting address + quantity
{
sendData.errorCode = (byte)(receiveData.functionCode + 0x80);
sendData.exceptionCode = 2;
}
if (sendData.exceptionCode == 0)
{
sendData.sendRegisterValues = new Int16[receiveData.quantityRead];
lock (lockHoldingRegisters)
Buffer.BlockCopy(holdingRegisters.localArray, receiveData.startingAddressRead * 2 + 2, sendData.sendRegisterValues, 0, receiveData.quantityRead * 2);
lock (holdingRegisters)
for (int i = 0; i < receiveData.quantityWrite; i++)
{
holdingRegisters[receiveData.startingAddressWrite + i + 1] = unchecked((ushort)receiveData.receiveRegisterValues[i]);
}
sendData.byteCount = (byte)(2 * receiveData.quantityRead);
}
if (sendData.exceptionCode > 0)
sendData.length = 0x03;
else
sendData.length = Convert.ToUInt16(3 + 2 * receiveData.quantityRead);
if (true)
{
Byte[] data;
if (sendData.exceptionCode > 0)
data = new byte[9 + 2 * Convert.ToInt32(serialFlag)];
else
data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)];
Byte[] byteData = new byte[2];
//Send Transaction identifier
byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier);
data[0] = byteData[1];
data[1] = byteData[0];
//Send Protocol identifier
byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier);
data[2] = byteData[1];
data[3] = byteData[0];
//Send length
byteData = BitConverter.GetBytes((int)sendData.length);
data[4] = byteData[1];
data[5] = byteData[0];
//Unit Identifier
data[6] = sendData.unitIdentifier;
//Function Code
data[7] = sendData.functionCode;
//ByteCount
data[8] = sendData.byteCount;
if (sendData.exceptionCode > 0)
{
data[7] = sendData.errorCode;
data[8] = sendData.exceptionCode;
sendData.sendRegisterValues = null;
}
else
{
if (sendData.sendRegisterValues != null)
for (int i = 0; i < (sendData.byteCount / 2); i++)
{
byteData = BitConverter.GetBytes((Int16)sendData.sendRegisterValues[i]);
data[9 + i * 2] = byteData[1];
data[10 + i * 2] = byteData[0];
}
}
try
{
if (serialFlag)
{
if (!serialport.IsOpen)
throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
//Create CRC
sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6);
byteData = BitConverter.GetBytes((int)sendData.crc);
data[data.Length - 2] = byteData[0];
data[data.Length - 1] = byteData[1];
serialport.Write(data, 6, data.Length - 6);
if (debug)
{
byte[] debugData = new byte[data.Length - 6];
Array.Copy(data, 6, debugData, 0, data.Length - 6);
if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
}
}
else if (udpFlag)
{
//UdpClient udpClient = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn);
udpClient.Send(data, data.Length, endPoint);
}
else
{
stream.Write(data, 0, data.Length);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
}
}
catch (Exception) { }
if (HoldingRegistersChanged != null)
HoldingRegistersChanged(receiveData.startingAddressWrite + 1, receiveData.quantityWrite);
}
}
private void sendException(int errorCode, int exceptionCode, ModbusProtocol receiveData, ModbusProtocol sendData, NetworkStream stream, int portIn, IPAddress ipAddressIn)
{
sendData.response = true;
sendData.transactionIdentifier = receiveData.transactionIdentifier;
sendData.protocolIdentifier = receiveData.protocolIdentifier;
sendData.unitIdentifier = receiveData.unitIdentifier;
sendData.errorCode = (byte)errorCode;
sendData.exceptionCode = (byte)exceptionCode;
if (sendData.exceptionCode > 0)
sendData.length = 0x03;
else
sendData.length = (ushort)(0x03 + sendData.byteCount);
if (true)
{
Byte[] data;
if (sendData.exceptionCode > 0)
data = new byte[9 + 2 * Convert.ToInt32(serialFlag)];
else
data = new byte[9 + sendData.byteCount + 2 * Convert.ToInt32(serialFlag)];
Byte[] byteData = new byte[2];
sendData.length = (byte)(data.Length - 6);
//Send Transaction identifier
byteData = BitConverter.GetBytes((int)sendData.transactionIdentifier);
data[0] = byteData[1];
data[1] = byteData[0];
//Send Protocol identifier
byteData = BitConverter.GetBytes((int)sendData.protocolIdentifier);
data[2] = byteData[1];
data[3] = byteData[0];
//Send length
byteData = BitConverter.GetBytes((int)sendData.length);
data[4] = byteData[1];
data[5] = byteData[0];
//Unit Identifier
data[6] = sendData.unitIdentifier;
data[7] = sendData.errorCode;
data[8] = sendData.exceptionCode;
try
{
if (serialFlag)
{
if (!serialport.IsOpen)
throw new EasyModbus.Exceptions.SerialPortNotOpenedException("serial port not opened");
//Create CRC
sendData.crc = ModbusClient.calculateCRC(data, Convert.ToUInt16(data.Length - 8), 6);
byteData = BitConverter.GetBytes((int)sendData.crc);
data[data.Length - 2] = byteData[0];
data[data.Length - 1] = byteData[1];
serialport.Write(data, 6, data.Length - 6);
if (debug)
{
byte[] debugData = new byte[data.Length - 6];
Array.Copy(data, 6, debugData, 0, data.Length - 6);
if (debug) StoreLogData.Instance.Store("Send Serial-Data: " + BitConverter.ToString(debugData), System.DateTime.Now);
}
}
else if (udpFlag)
{
//UdpClient udpClient = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(ipAddressIn, portIn);
udpClient.Send(data, data.Length, endPoint);
}
else
{
stream.Write(data, 0, data.Length);
if (debug) StoreLogData.Instance.Store("Send Data: " + BitConverter.ToString(data), System.DateTime.Now);
}
}
catch (Exception) { }
}
}
private void CreateLogData(ModbusProtocol receiveData, ModbusProtocol sendData)
{
for (int i = 0; i < 98; i++)
{
modbusLogData[99 - i] = modbusLogData[99 - i - 2];
}
modbusLogData[0] = receiveData;
modbusLogData[1] = sendData;
}
public int NumberOfConnections
{
get
{
return numberOfConnections;
}
}
public ModbusProtocol[] ModbusLogData
{
get
{
return modbusLogData;
}
}
public int Port
{
get
{
return port;
}
set
{
port = value;
}
}
public bool UDPFlag
{
get
{
return udpFlag;
}
set
{
udpFlag = value;
}
}
public bool SerialFlag
{
get
{
return serialFlag;
}
set
{
serialFlag = value;
}
}
public int Baudrate
{
get
{
return baudrate;
}
set
{
baudrate = value;
}
}
public System.IO.Ports.Parity Parity
{
get
{
return parity;
}
set
{
parity = value;
}
}
public System.IO.Ports.StopBits StopBits
{
get
{
return stopBits;
}
set
{
stopBits = value;
}
}
public string SerialPort
{
get
{
return serialPort;
}
set
{
serialPort = value;
if (serialPort != null)
serialFlag = true;
else
serialFlag = false;
}
}
public byte UnitIdentifier
{
get
{
return unitIdentifier;
}
set
{
unitIdentifier = value;
}
}
/// <summary>
/// Gets or Sets the Filename for the LogFile
/// </summary>
public string LogFileFilename
{
get
{
return StoreLogData.Instance.Filename;
}
set
{
StoreLogData.Instance.Filename = value;
if (StoreLogData.Instance.Filename != null)
debug = true;
else
debug = false;
}
}
public class HoldingRegisters
{
public ushort[] localArray = new ushort[65535];
ModbusServer modbusServer;
public HoldingRegisters(EasyModbus.ModbusServer modbusServer)
{
this.modbusServer = modbusServer;
}
public ushort this[int x]
{
get { return this.localArray[x]; }
set
{
this.localArray[x] = value;
}
}
}
public class InputRegisters
{
public ushort[] localArray = new ushort[65535];
ModbusServer modbusServer;
public InputRegisters(EasyModbus.ModbusServer modbusServer)
{
this.modbusServer = modbusServer;
}
public ushort this[int x]
{
get { return this.localArray[x]; }
set
{
this.localArray[x] = value;
}
}
}
public class Coils
{
public bool[] localArray = new bool[65535];
ModbusServer modbusServer;
public Coils(EasyModbus.ModbusServer modbusServer)
{
this.modbusServer = modbusServer;
}
public bool this[int x]
{
get { return this.localArray[x]; }
set
{
this.localArray[x] = value;
}
}
}
public class DiscreteInputs
{
public bool[] localArray = new bool[65535];
ModbusServer modbusServer;
public DiscreteInputs(EasyModbus.ModbusServer modbusServer)
{
this.modbusServer = modbusServer;
}
public bool this[int x]
{
get { return this.localArray[x]; }
set
{
this.localArray[x] = value;
}
}
}
}
}