modbus tcp通讯 modbus4j java实现

modbus协议内容网上已经很齐全了,这里就不赘述了。(此篇文章根据网上已有内容整理)

核心依赖: modbus4j-3.0.4-SNAPSHOT.jar

  • modbus tcp slave

1.获取tcp slave 

//springboot项目实现CommandLineRunner类和@Component注解,程序启动时就加载tcp slave
@Component
public class Slave implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        createSalve();
    }

    private void createSalve() {
        //创建modbus工厂
        ModbusFactory modbusFactory = new ModbusFactory();
        //创建TCP服务端
        final ModbusSlaveSet salve = modbusFactory.createTcpSlave(true);
        //向过程影像区添加数据
        salve.addProcessImage(Register.getModscanProcessImage(1));
        //获取寄存器
        salve.getProcessImage(1);
        try {
            salve.start();
        } catch (ModbusInitException e) {
            e.printStackTrace();
        }
    }

}

 2.创建线圈和寄存器

public class Register {
    static BasicProcessImage getModscanProcessImage(int slaveId) {
        BasicProcessImage processImage = new BasicProcessImage(slaveId);
        processImage.setInvalidAddressValue(Short.MIN_VALUE);
        //创建可读写开关量
        processImage.setCoil(0, true);
        processImage.setCoil(1, false);
        processImage.setCoil(2, true);
        processImage.setCoil(3, false);
        processImage.setCoil(4, true);
        processImage.setCoil(5, false);
        processImage.setCoil(6, true);
        processImage.setCoil(7, true);
        processImage.setCoil(8, true);
        processImage.setCoil(9, true);

        //创建只读开关量
        processImage.setInput(0, false);
        processImage.setInput(1, false);
        processImage.setInput(2, true);
        processImage.setInput(3, false);
        processImage.setInput(4, true);
        processImage.setInput(5, true);
        processImage.setInput(6, true);
        processImage.setInput(7, false);
        processImage.setInput(8, true);
        processImage.setInput(9, true);

        //创建 保持寄存器
        processImage.setHoldingRegister(0, (short) 1);
        processImage.setHoldingRegister(1, (short) 10);
        processImage.setHoldingRegister(2, (short) 100);
        processImage.setHoldingRegister(3, (short) 1000);
        processImage.setHoldingRegister(4, (short) 10000);
        processImage.setHoldingRegister(5, (short) 10000);
        processImage.setHoldingRegister(6, (short) 10000);
        processImage.setHoldingRegister(7, (short) 10000);
        processImage.setHoldingRegister(8, (short) 10000);
        processImage.setHoldingRegister(9, (short) 10000);

        //创建 只读寄存器
        processImage.setInputRegister(0, (short) 10000);
        processImage.setInputRegister(1, (short) 1000);
        processImage.setInputRegister(2, (short) 100);
        processImage.setInputRegister(3, (short) 10);
        processImage.setInputRegister(4, (short) 1);
        processImage.setInputRegister(5, (short) 1);
        processImage.setInputRegister(6, (short) 1);
        processImage.setInputRegister(7, (short) 1);
        processImage.setInputRegister(8, (short) 1);
        processImage.setInputRegister(9, (short) 1);

        processImage.addListener(new BasicProcessImageListener());
        return processImage;
    }


}

3.监听线圈和寄存器

public class BasicProcessImageListener implements ProcessImageListener {
    @Override
    public void coilWrite(int offset, boolean oldValue, boolean newValue) {
        System.out.println("Coil at " + offset + " was set from " + oldValue + " to " + newValue);
    }

    @Override
    public void holdingRegisterWrite(int offset, short oldValue, short newValue) {
        System.out.println("HoldRrgister at " + offset + " was set from " + oldValue + " to " + newValue);
    }

}
  • modbus tcp master

1.获取tcp master

public class TcpMaster {

    private static ModbusFactory modbusFactory;

    static {
        if (modbusFactory == null) {
            modbusFactory = new ModbusFactory();
        }
    }

    /**
     * 获取master
     *
     * @return master
     */
    public static ModbusMaster getMaster() {
        IpParameters params = new IpParameters();
        params.setHost("localhost");
        params.setPort(502);
        params.setEncapsulated(true);
        ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议
        try {
            //设置超时时间
            master.setTimeout(1000);
            //设置重连次数
            master.setRetries(3);
            //初始化
            master.init();
        } catch (ModbusInitException e) {
            e.printStackTrace();
        }
        return master;
    }
}

 2.读取线圈和寄存器中的数据

@Component
public class Modbus4jReadUtils {

    //获取master
    private static ModbusMaster master = TcpMaster.getMaster();

    /**
     * 读(线圈)开关量数据
     *
     * @param slaveId slaveId
     * @param offset  位置
     * @return 读取值
     */
    public boolean[] readCoilStatus(int slaveId, int offset, int numberOfBits)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {

        ReadCoilsRequest request = new ReadCoilsRequest(slaveId, offset, numberOfBits);
        ReadCoilsResponse response = (ReadCoilsResponse) master.send(request);
        boolean[] booleans = response.getBooleanData();
        return valueRegroup(numberOfBits, booleans);
    }

    /**
     * 开关数据 读取外围设备输入的开关量
     */
    public boolean[] readInputStatus(int slaveId, int offset, int numberOfBits)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, offset, numberOfBits);
        ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) master.send(request);
        boolean[] booleans = response.getBooleanData();
        return valueRegroup(numberOfBits, booleans);
    }

    /**
     * 读取保持寄存器数据
     *
     * @param slaveId slave Id
     * @param offset  位置
     */
    public short[] readHoldingRegister(int slaveId, int offset, int numberOfBits)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, offset, numberOfBits);
        ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);
        return response.getShortData();
    }

    /**
     * 读取外围设备输入的数据
     *
     * @param slaveId slaveId
     * @param offset  位置
     */
    public short[] readInputRegisters(int slaveId, int offset, int numberOfBits)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {

        ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, offset, numberOfBits);
        ReadInputRegistersResponse response = (ReadInputRegistersResponse) master.send(request);
        return response.getShortData();
    }

    /**
     * 批量读取 可以批量读取不同寄存器中数据
     */
    public void batchRead() throws ModbusTransportException, ErrorResponseException, ModbusInitException {

        BatchRead<Integer> batch = new BatchRead<Integer>();
        batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.TWO_BYTE_INT_SIGNED));
        batch.addLocator(1, BaseLocator.inputStatus(1, 0));
        batch.setContiguousRequests(true);
        BatchResults<Integer> results = master.send(batch);
        System.out.println("batchRead:" + results.getValue(0));
        System.out.println("batchRead:" + results.getValue(1));
    }

    private boolean[] valueRegroup(int numberOfBits, boolean[] values) {
        boolean[] bs = new boolean[numberOfBits];
        int temp = 1;
        for (boolean b : values) {
            bs[temp - 1] = b;
            temp++;
            if (temp > numberOfBits)
                break;
        }
        return bs;
    }
}

3.向线圈和寄存器中写数据

@Component
public class Modbus4jWriteUtils {
    // 获取Master
    private static ModbusMaster tcpMaster = TcpMaster.getMaster();

    /**
     * 写单个(线圈)开关量数据
     *
     * @param slaveId     slave的ID
     * @param writeOffset 位置
     * @param writeValue  值
     * @return 是否写入成功
     */
    public boolean writeCoil(int slaveId, int writeOffset, boolean writeValue)
            throws ModbusTransportException, ModbusInitException {
        // 创建请求
        WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
        // 发送请求并获取响应对象
        WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request);
        return !response.isException();
    }

    /**
     * 写多个开关量数据(线圈)
     *
     * @param slaveId     slaveId
     * @param startOffset 开始位置
     * @param bdata       写入的数据
     * @return 是否写入成功
     */
    public boolean writeCoils(int slaveId, int startOffset, boolean[] bdata)
            throws ModbusTransportException, ModbusInitException {
        // 创建请求
        WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata);
        // 发送请求并获取响应对象
        WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request);
        return !response.isException();

    }

    /***
     *  保持寄存器写单个
     *
     * @param slaveId slaveId
     * @param writeOffset 开始位置
     * @param writeValue 写入的数据
     */
    public boolean writeRegister(int slaveId, int writeOffset, short writeValue)
            throws ModbusTransportException, ModbusInitException {
        // 创建请求对象
        WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
        // 发送请求并获取响应对象
        WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request);
        return !response.isException();

    }

    /**
     * 保持寄存器写入多个模拟量数据
     *
     * @param slaveId     modbus的slaveID
     * @param startOffset 起始位置偏移量值
     * @param sdata       写入的数据
     * @return 返回是否写入成功
     */
    public boolean writeRegisters(int slaveId, int startOffset, short[] sdata)
            throws ModbusTransportException, ModbusInitException {
        // 创建请求对象
        WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata);
        // 发送请求并获取响应对象
        WriteRegistersResponse response = (WriteRegistersResponse) tcpMaster.send(request);
        return !response.isException();
    }

    /**
     * 根据类型写数据(如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long)
     *
     * @param value    写入值
     * @param dataType com.serotonin.modbus4j.code.DataType
     */
    public void writeHoldingRegister(int slaveId, int offset, Number value, int dataType)
            throws ModbusTransportException, ErrorResponseException, ModbusInitException {
        // 类型
        BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType);
        tcpMaster.setValue(locator, value);
    }

}

 

  • 7
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 28
    评论
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值