java利用socket通信实现Modbus-RTU通信协议

Modbus

Modbus是一种串行通信协议。Modbus 一个工业上常用的通讯协议、一种通讯约定。Modbus协议包括RTU、ASCII、TCP。其中MODBUS-RTU最常用,比较简单,在单片机上很容易实现。

简单分析Modbus-RTU报文

37 10 00 14 00 0a 14 00 00 00 00 00 00 00 00 00 00 00 00 3f 80 00 00 3f 80 00 00 00 a0(十六进制)
37:从站地址 ,10:功能码,00 14:MODBUS起始地址40021,对应20,14:写入数据字节数,20个,00 a0:crc校验码。其它就是传送的数据。

37 10 00 14 00 0a 14 … 00 a0,中间的数据为功能数据,上面的报文按照两个字节拼接为一个实数,也就是对应float基本数据类型,其中00 00 00 00为一个实数,依次类推,上面的报文有5个实数。解析出来就是0.0、0.0、0.0、1.0、1.0。

4G DTU(ZHC4013)

ZHC4012是一款全网通七模4G DTU,支持2G/3G/4G信号透明传输。支持工业RS232/485等接口,直接连接设备传输。这个硬件是我项目中实践过的,该设备可以通过4G运营商网络与远程服务器进行数据通信。具体操作可以到官网联系客服。设备官网4G DTU(ZHC4013)

项目支持多个4G DTU设备数据上传,支持控制指定4G DTU设备。

附一个测试版本的源代码,按照上述报文模拟服务端与客户端通信。下面代码出现的注册包是 4G DTU(ZHC4013)连接是发送的数据,根据该注册包可以判断出是哪个设备发送数据。

服务端代码,SocketServer线程负责监听端口、ServerService线程负责读取发送数据

用原生Socket技术存在的一些问题项目不稳定,服务端负责监听的线程运行久了会挂掉。建议用Netty框架实现服务端的代码,后续会分享用Netty框架实现的源代码。

Netty实现服务端的源代码:Java使用Netty实现Modbus-RTU通信协议

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * TODO
 *
 * @author linfeng
 * @date 2022/12/8 15:55
 */
public class SocketServer implements Runnable{

    public static void main(String[] args) {
        ThreadPoolUtils.getThreadPoolExecutor().execute(new SocketServer());
    }

    public Map<String, Socket> clientMap = new ConcurrentHashMap<>();

    private ThreadPoolExecutor executor = ThreadPoolUtils.getThreadPoolExecutor();

    @Override
    public void run() {
        try {
            ServerSocket server = new ServerSocket(9666);
            while (true){
                Socket client = server.accept();
                //获取注册包
                InputStream is = client.getInputStream();
                byte[] bytes = ModBusUtils.readInputStream(is);
                String str = "";
                for(int i=0;i<bytes.length;i++) {
                    str=str+ModBusUtils.byteToASCLL(bytes[i]);
                }
                System.out.println("注册包: "+str);
                //添加客户端
                clientMap.put(str,client);
                ServerService service = new ServerService(clientMap);
                executor.execute(service);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
}


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * TODO
 *
 * @author linfeng
 * @date 2022/12/8 16:05
 */
public class ServerService implements Runnable {

    private Map<String, Socket> clientMap = new ConcurrentHashMap<>();

    public ServerService(){
    }

    public ServerService(Map<String,Socket> clientMap){
        this.clientMap=clientMap;
    }

    @Override
    public void run() {
        while (true){
            for(Map.Entry<String, Socket> entry : clientMap.entrySet()) {
                //注册包 节点编号
                String registrationPacket = entry.getKey();
                Socket socket = entry.getValue();
                try {
                    InputStream is = socket.getInputStream();
                    OutputStream os = socket.getOutputStream();
                    if(is.available()!=0){
                        byte[] bytes = ModBusUtils.readInputStream(is);
                        String str = ModBusUtils.bytes2HexString(bytes);
                        System.out.print(registrationPacket+": 十六进制: " + str);
                        // 截取对应的数据
                        List<Float> floatList = new ArrayList<>();
                        // 严格来说是要对数据CRC校验的,麻烦就不校验了。我就直接按照文档截取需要的数据了。
                        String[] arr = str.split(" ");
                        if(arr.length>=24 && "37".equals(arr[0]) && "10".equals(arr[1]) && "00".equals(arr[2])){
                            for(int i=7;i<arr.length-2;i+=4){
                                String a = arr[i]+arr[i+1]+arr[i+2]+arr[i+3];
                                // 这里是两个字节数据处理,转float
                                Float f = Float.intBitsToFloat(new BigInteger(a, 16).intValue());
                                floatList.add(f);
                                 if(floatList.size()==8) {
                                    // 这里是两个字节数据处理,转int
                                    floatList.set(7, Float.parseFloat(new BigInteger(a, 16).toString()));
                                }
                            }
                        }
                        System.out.println(registrationPacket+": 解析数据: "+floatList);

                        // 下面发送数据到客户端

                        byte[] by = new byte[19];
                        by[0] = 55;
                        by[1] = 3;
                        by[2] = 16;
                        by[3] = 63;
                        by[4] = -128;
                        by[5] = 0;
                        by[6] = 0;
                        by[7] = 0;
                        by[8] = 0;
                        by[9] = 0;
                        by[10] = 0;
                        by[11] = 0;
                        by[12] = 0;
                        by[13] = 0;
                        by[14] = 0;
                        String hexStr = Integer.toHexString(Float.floatToIntBits(Float.parseFloat("2.0")));
                        byte[] b = ModBusUtils.hexStringToByteArray(hexStr);
                        by[15] = b[0];
                        by[16] = b[1];
                        by[17] = b[2];
                        by[18] = b[3];
                        //crc3校验
                        String crc = ModBusUtils.getCRC3(by);
                        byte[] crcByte = ModBusUtils.hexStringToByteArray(crc);
                        byte[] data = new byte[21];
                        data[19] = crcByte[0];
                        data[20] = crcByte[1];
                        for (int i = 0; i < by.length; i++) {
                            data[i] = by[i];
                        }
                        os.write(data);
                        System.out.println(registrationPacket+": 写入数据: " + Arrays.toString(data));
                    }
                } catch (IOException e) {
                	e.printStackTrace();
                }
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
                      

服务端运行效果

在这里插入图片描述

客户端代码,SocketClient线程链接服务器发送数据、ClientService线程读取服务器发送的数据

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * TODO
 *
 * @author linfeng
 * @date 2022/12/8 16:25
 */
public class SocketClient implements Runnable {

    public static void main(String[] args) {
        ThreadPoolUtils.getThreadPoolExecutor().execute(new SocketClient());
    }

    private ThreadPoolExecutor executor = ThreadPoolUtils.getThreadPoolExecutor();

    @Override
    public void run() {
        try {
            Socket socket = new Socket("127.0.0.1",9666);
            OutputStream os = socket.getOutputStream();
            InputStream is = socket.getInputStream();
            os.write("54687956644".getBytes());
            Thread.sleep(100);
            ClientService clientService = new ClientService(is);
            executor.execute(clientService);
            // 利用out流发数据
            while (true){
                os.write(ModBusUtils.hexStringToByteArray("37 10 00 14 00 0a 14 00 00 00 00 00 00 00 00 00 00 00 00 3f 80 00 00 3f 80 00 00 00 a0"));
                Thread.sleep(1000);
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

import java.io.IOException;
import java.io.InputStream;

/**
 * TODO
 *
 * @author linfeng
 * @date 2022/12/8 16:57
 */
public class ClientService implements Runnable {

    private InputStream is;

    public ClientService(){}

    public ClientService(InputStream is){
        this.is = is;
    }

    @Override
    public void run() {
        while (true){
            try {
                if(is.available()!=0){
                    byte[] bytes = ModBusUtils.readInputStream(is);
                    String str = ModBusUtils.bytes2HexString(bytes);
                    System.out.println("服务端发送的十六进制数据: " + str);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

客户端运行效果

在这里插入图片描述

数据解析工具类

package hdo.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class ModBusUtils {

    public static byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        if((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }
    
    public static char byteToASCLL(byte b){
        return (char) b;
    }
   
    /*
     * 字节数组转16进制字符串
     */
    public static String bytes2HexString(byte[] b) {
        String r = "";
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            r += hex.toUpperCase()+" ";
        }
        return r;
    }

	/**
	 * @TODO : 计算CRC校验码
	 * @AUTH : linfeng
	 * @DATE : 2020年8月27日 下午2:11:30
	 * @return_type : String
	 * @param data
	 * @return
	 */
	public static String getCRC3(byte[] data) {
        byte[] crc16_h = {
                (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
                (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
                (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
                (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
                (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
                (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
                (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
                (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
                (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
                (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
                (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
                (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
                (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40,
                (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
                (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41,
                (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x01, (byte) 0xC0, (byte) 0x80, (byte) 0x41, (byte) 0x00, (byte) 0xC1, (byte) 0x81, (byte) 0x40
        };

        byte[] crc16_l = {
                (byte) 0x00, (byte) 0xC0, (byte) 0xC1, (byte) 0x01, (byte) 0xC3, (byte) 0x03, (byte) 0x02, (byte) 0xC2, (byte) 0xC6, (byte) 0x06, (byte) 0x07, (byte) 0xC7, (byte) 0x05, (byte) 0xC5, (byte) 0xC4, (byte) 0x04,
                (byte) 0xCC, (byte) 0x0C, (byte) 0x0D, (byte) 0xCD, (byte) 0x0F, (byte) 0xCF, (byte) 0xCE, (byte) 0x0E, (byte) 0x0A, (byte) 0xCA, (byte) 0xCB, (byte) 0x0B, (byte) 0xC9, (byte) 0x09, (byte) 0x08, (byte) 0xC8,
                (byte) 0xD8, (byte) 0x18, (byte) 0x19, (byte) 0xD9, (byte) 0x1B, (byte) 0xDB, (byte) 0xDA, (byte) 0x1A, (byte) 0x1E, (byte) 0xDE, (byte) 0xDF, (byte) 0x1F, (byte) 0xDD, (byte) 0x1D, (byte) 0x1C, (byte) 0xDC,
                (byte) 0x14, (byte) 0xD4, (byte) 0xD5, (byte) 0x15, (byte) 0xD7, (byte) 0x17, (byte) 0x16, (byte) 0xD6, (byte) 0xD2, (byte) 0x12, (byte) 0x13, (byte) 0xD3, (byte) 0x11, (byte) 0xD1, (byte) 0xD0, (byte) 0x10,
                (byte) 0xF0, (byte) 0x30, (byte) 0x31, (byte) 0xF1, (byte) 0x33, (byte) 0xF3, (byte) 0xF2, (byte) 0x32, (byte) 0x36, (byte) 0xF6, (byte) 0xF7, (byte) 0x37, (byte) 0xF5, (byte) 0x35, (byte) 0x34, (byte) 0xF4,
                (byte) 0x3C, (byte) 0xFC, (byte) 0xFD, (byte) 0x3D, (byte) 0xFF, (byte) 0x3F, (byte) 0x3E, (byte) 0xFE, (byte) 0xFA, (byte) 0x3A, (byte) 0x3B, (byte) 0xFB, (byte) 0x39, (byte) 0xF9, (byte) 0xF8, (byte) 0x38,
                (byte) 0x28, (byte) 0xE8, (byte) 0xE9, (byte) 0x29, (byte) 0xEB, (byte) 0x2B, (byte) 0x2A, (byte) 0xEA, (byte) 0xEE, (byte) 0x2E, (byte) 0x2F, (byte) 0xEF, (byte) 0x2D, (byte) 0xED, (byte) 0xEC, (byte) 0x2C,
                (byte) 0xE4, (byte) 0x24, (byte) 0x25, (byte) 0xE5, (byte) 0x27, (byte) 0xE7, (byte) 0xE6, (byte) 0x26, (byte) 0x22, (byte) 0xE2, (byte) 0xE3, (byte) 0x23, (byte) 0xE1, (byte) 0x21, (byte) 0x20, (byte) 0xE0,
                (byte) 0xA0, (byte) 0x60, (byte) 0x61, (byte) 0xA1, (byte) 0x63, (byte) 0xA3, (byte) 0xA2, (byte) 0x62, (byte) 0x66, (byte) 0xA6, (byte) 0xA7, (byte) 0x67, (byte) 0xA5, (byte) 0x65, (byte) 0x64, (byte) 0xA4,
                (byte) 0x6C, (byte) 0xAC, (byte) 0xAD, (byte) 0x6D, (byte) 0xAF, (byte) 0x6F, (byte) 0x6E, (byte) 0xAE, (byte) 0xAA, (byte) 0x6A, (byte) 0x6B, (byte) 0xAB, (byte) 0x69, (byte) 0xA9, (byte) 0xA8, (byte) 0x68,
                (byte) 0x78, (byte) 0xB8, (byte) 0xB9, (byte) 0x79, (byte) 0xBB, (byte) 0x7B, (byte) 0x7A, (byte) 0xBA, (byte) 0xBE, (byte) 0x7E, (byte) 0x7F, (byte) 0xBF, (byte) 0x7D, (byte) 0xBD, (byte) 0xBC, (byte) 0x7C,
                (byte) 0xB4, (byte) 0x74, (byte) 0x75, (byte) 0xB5, (byte) 0x77, (byte) 0xB7, (byte) 0xB6, (byte) 0x76, (byte) 0x72, (byte) 0xB2, (byte) 0xB3, (byte) 0x73, (byte) 0xB1, (byte) 0x71, (byte) 0x70, (byte) 0xB0,
                (byte) 0x50, (byte) 0x90, (byte) 0x91, (byte) 0x51, (byte) 0x93, (byte) 0x53, (byte) 0x52, (byte) 0x92, (byte) 0x96, (byte) 0x56, (byte) 0x57, (byte) 0x97, (byte) 0x55, (byte) 0x95, (byte) 0x94, (byte) 0x54,
                (byte) 0x9C, (byte) 0x5C, (byte) 0x5D, (byte) 0x9D, (byte) 0x5F, (byte) 0x9F, (byte) 0x9E, (byte) 0x5E, (byte) 0x5A, (byte) 0x9A, (byte) 0x9B, (byte) 0x5B, (byte) 0x99, (byte) 0x59, (byte) 0x58, (byte) 0x98,
                (byte) 0x88, (byte) 0x48, (byte) 0x49, (byte) 0x89, (byte) 0x4B, (byte) 0x8B, (byte) 0x8A, (byte) 0x4A, (byte) 0x4E, (byte) 0x8E, (byte) 0x8F, (byte) 0x4F, (byte) 0x8D, (byte) 0x4D, (byte) 0x4C, (byte) 0x8C,
                (byte) 0x44, (byte) 0x84, (byte) 0x85, (byte) 0x45, (byte) 0x87, (byte) 0x47, (byte) 0x46, (byte) 0x86, (byte) 0x82, (byte) 0x42, (byte) 0x43, (byte) 0x83, (byte) 0x41, (byte) 0x81, (byte) 0x80, (byte) 0x40
        };

        int crc = 0x0000ffff;
        int ucCRCHi = 0x00ff;
        int ucCRCLo = 0x00ff;
        int iIndex;
        for (int i = 0; i < data.length; ++i) {
            iIndex = (ucCRCLo ^ data[i]) & 0x00ff;
            ucCRCLo = ucCRCHi ^ crc16_h[iIndex];
            ucCRCHi = crc16_l[iIndex];
        }

        crc = ((ucCRCHi & 0x00ff) << 8) | (ucCRCLo & 0x00ff) & 0xffff;
        //高低位互换,输出符合相关工具对Modbus CRC16的运算
        crc = ((crc & 0xFF00) >> 8) | ((crc & 0x00FF) << 8);
        return String.format("%04X", crc);
    }
	
	 /**
     * 16进制表示的字符串转换为字节数组
     *
     * @param hexString 16进制表示的字符串
     * @return byte[] 字节数组
     */
    public static byte[] hexStringToByteArray(String hexString) {
        hexString = hexString.replaceAll(" ", "");
        int len = hexString.length();
        byte[] bytes = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            // 两位一组,表示一个字节,把这样表示的16进制字符串,还原成一个字节
            bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
                    .digit(hexString.charAt(i + 1), 16));
        }
        return bytes;
    }

}

线程池工具类

package com.ruoyi.socket;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * TODO
 *
 * @author linfeng
 * @date 2022/12/8 15:57
 */
public class ThreadPoolUtils {

    //核心线程数
    private static final int CORE_POOL_SIZE = 20;

    //最大线程数
    private static final int MAX_POOL_SIZE = 40;

    //队列数
    private static final int QUEUE_CAPACITY = 100;

    private static final Long KEEP_ALIVE_TIME = 1L;

    public static ThreadPoolExecutor getThreadPoolExecutor() {
        return new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                new ThreadPoolExecutor.CallerRunsPolicy());
    }
}

  • 10
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
使用Java利用socket通信可以实现Modbus-RTU通信协议实现空调对接。Modbus-RTU是一种常用的串行通信协议,可以实现设备之间的数据传输。 首先,需要在Java中使用socket实现网络通信。通过创建服务器端socket和客户端socket,可以建立通信连接。服务器端socket监听指定端口,等待客户端的连接请求,客户端socket则主动发起连接请求。 然后,根据Modbus-RTU通信协议,需要实现相应的功能码来进行数据的读取和写入。常用的功能码包括读功能码(0x03)和写功能码(0x06)。通过Java的输入输出流,可以向设备发送相应的Modbus-RTU命令,然后读取或写入数据。 在空调对接的过程中,需要调用空调设备的相关API来实现具体的操作。首先需要对空调进行初始化配置,如设置波特率、数据位、停止位等参数。然后可以通过发送读功能码来获取空调的状态信息,如温度、湿度等。通过发送写功能码,可以实现对空调进行控制,如调节温度、开关机等。 需要注意的是,Modbus-RTU通信协议是基于串行通信的,而Javasocket通信是基于网络通信的,两者之间存在差异。因此,在进行空调对接时,需要将串行通信转换为网络通信,将串行口转换为网络socket,并进行相应的协议转换和数据处理。 综上所述,利用Javasocket通信可以实现Modbus-RTU通信协议实现空调对接。通过实现相应的功能码和调用空调设备的API,可以实现空调的读取和控制操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值