IoTClient Development 4 - ModBusTcp end analog service agreement

Original: IoTClient development 4 - ModBusTcp end analog service agreement

Foreword

Part of the agreement we achieved ModBusTcp client to read and write, but in many cases there is no on-site business environment before writing the code. You can not write code to the customer's site, or write blindfolded and then pray without error, and the deployment of a hardware environment or in the office. How to say are not appropriate feeling, if we can use simulation software on hardware that is not perfect, and after a variety of different hardware protocol interfaces are simulated, instead of each set of hardware to buy back deployed to do the test.
Really use software simulation is also possible, the client is a request for protocol packets and response packets parsing, receive and respond to messages sending server is actually a request packet, just and client actions contrary.
In front of us write You can also write a chat program - C # Socket 1 learning time of writing there Socket server implementation, in fact, that far.

ModBusTcp packet analysis (Part copied a convenient time following implementation of the code to do comparison)

Understand and implement the agreement mainly is to understand the text of protocol packets. (Note: The following data packets are in hexadecimal)

Data [read - Request packet]: 19 B2 00 00 00 06 02 03 00 04 00 01

  • 19 B2 client verifying information is issued, arbitrarily defined.
  • 00 00 representatives are based on modbus tcp / ip protocols
  • 0006 behind identify how much longer bytes
  • 02 represents the station number address
  • 03 (holding register read) function code
  • 0004 to register address
  • 0001 is a register length (number of registers)

Data read [-] response message (Get twice)

First gets the first eight bytes (Map header): B2 19 00 00 00 05 02 03 02 00 20

  • 19 B2 test authentication information (copy of the client's hair accessories test)
  • 0000 representatives is based on the tcp / ip protocol modbus (client-side copy of the hair)
  • 0005 to the final length of the current position
  • 02 represents the station number address (copy of the client's hair)
  • 03 function code (copy of the client's hair)

The second acquisition message: 020020

  • 02 the number of bytes
  • Data 0020 responses

[Write data - Request packet]: 19 B2 00 00 00 09 02 10 00 04 00 01 02 00 20

  • 19 B2 client verifying information is issued, arbitrarily defined.
  • 00 00 representatives are based on modbus tcp / ip protocols
  • 0009 from the next to the last byte of the present
  • Station No. 02
  • Function code 10 (decimal is 16 rpm)
  • 0004 register address
  • Length register 0001 (register number)
  • 02 the number of bytes to write
  • 0020 value to be written (decimal 32 rpm)

Data written to [-] in response to message: 19 B2 00 00 00 06 02 10 00 04 00 01

And request packets difference

  • No data value request packet
  • 0009 turned into 0006 because the packet length changed
  • Other packets and request packets consistent meaning

achieve

//启动服务
public void Start()
{
    //1 创建Socket对象
    var socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    //2 绑定ip和端口 
    IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 502);
    socketServer.Bind(ipEndPoint);

    //3、开启侦听(等待客户机发出的连接),并设置最大客户端连接数为10
    socketServer.Listen(10);

    Task.Run(() => { Accept(socketServer); });
}

//客户端连接到服务端
void Accept(Socket socket)
{
    while (true)
    {
        //阻塞等待客户端连接
        Socket newSocket = socket.Accept();
        Task.Run(() => { Receive(newSocket); });
    }
}

All of the above and in front of us, like, this place is not the same request packet parsing and respond to assemble packets sent

//接收客户端发送的消息
void Receive(Socket newSocket)
{
    while (newSocket.Connected)
    {
        byte[] requetData1 = new byte[8];
        //读取客户端发送报文 报文头
        int readLeng = newSocket.Receive(requetData1, 0, requetData1.Length, SocketFlags.None);
        byte[] requetData2 = new byte[requetData1[5] - 2];
        //读取客户端发送报文 报文数据
        readLeng = newSocket.Receive(requetData2, 0, requetData2.Length, SocketFlags.None);
        var requetData = requetData1.Concat(requetData2).ToArray();

        byte[] responseData1 = new byte[8];
        //复制请求报文中的报文头
        Buffer.BlockCopy(requetData, 0, responseData1, 0, responseData1.Length);
        //这里可以自己实现一个对象,用来存储客户端写入的数据(也可以用redis等实现数据的持久化)
        DataPersist data = new DataPersist("");

        //根据协议,报文的第八个字节是功能码(前面我们有说过 03:读保持寄存器  16:写多个寄存器)
        switch (requetData[7])
        {
            //读保持寄存器
            case 3:
                {
                    var value = data.Read(requetData[9]);
                    short.TryParse(value, out short resultValue);
                    var bytes = BitConverter.GetBytes(resultValue);
                    //当前位置到最后的长度
                    responseData1[5] = (byte)(3 + bytes.Length);
                    byte[] responseData2 = new byte[3] { (byte)bytes.Length, bytes[1], bytes[0] };
                    var responseData = responseData1.Concat(responseData2).ToArray();
                    newSocket.Send(responseData);
                }
                break;
            //写多个寄存器
            case 16:
                {
                    data.Write(requetData[9], requetData[requetData.Length - 1].ToString());
                    var responseData = new byte[12];
                    Buffer.BlockCopy(requetData, 0, responseData, 0, responseData.Length);
                    responseData[5] = 6;
                    newSocket.Send(responseData);
                }
                break;
        }
    }
}

This point is obtained according to the function code request packet, then the packet data read or write operation. Of course, you can persistent storage (e.g., with Redis) of data is written, so that data still can be read correctly after power off or restart.
Of course, more than just a class of pseudo-code, in order to reduce the amount of code and ease of understanding, and in many cases do not correspond to the real possibility of processing.

Use IoTClient in ModBusTcp agreement

installation

Nuget installation Install-Package IoTClient
or graphical installation

use

//1、实例化客户端 - 输入正确的IP和端口
ModBusTcpClient client = new ModBusTcpClient("127.0.0.1", 502);

//2、写操作 - 参数依次是:地址 、值 、站号 、功能码
client.Write("4", (short)33, 2, 16);
client.Write("4", (short)3344, 2, 16);

//3、读操作 - 参数依次是:地址 、站号 、功能码
var value = client.ReadInt16("4", 2, 3).Value;
var value2 = client.ReadInt32("4", 2, 3).Value;

//4、如果没有主动Open,则会每次读写操作的时候自动打开自动和关闭连接,这样会使读写效率大大减低。所以建议手动Open和Close。
client.Open();

//5、读写操作都会返回操作结果对象Result
var result = client.ReadInt16("4", 2, 3);
//5.1 读取是否成功(true或false)
var isSucceed = result.IsSucceed;
//5.2 读取失败的异常信息
var errMsg = result.Err;
//5.3 读取操作实际发送的请求报文
var requst  = result.Requst;
//5.4 读取操作服务端响应的报文
var response = result.Response;
//5.5 读取到的值
var value3 = result.Value;

End

Guess you like

Origin www.cnblogs.com/lonelyxmas/p/12053910.html