modbus slave

依赖

<dependency>
    <groupId>com.intelligt.modbus</groupId>
    <artifactId>jlibmodbus</artifactId>
    <version>1.2.9.7</version>
</dependency>
public interface ModbusEventListener {
    int[] readHoldingRegisterRange(int offset, int quantity);

    int[] readInputRegisterRange(int offset, int quantity);

    void onWriteToSingleCoil(int address, boolean value);

    void onWriteToMultipleCoils(int address, int quantity, boolean[] values);

    void onWriteToSingleHoldingRegister(int address, int value);

    void onWriteToMultipleHoldingRegisters(int address, int quantity, int[] values);

}

import com.intelligt.modbus.jlibmodbus.Modbus;
import com.intelligt.modbus.jlibmodbus.data.ModbusHoldingRegisters;
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
import com.intelligt.modbus.jlibmodbus.slave.ModbusSlave;
import com.intelligt.modbus.jlibmodbus.slave.ModbusSlaveFactory;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.List;

//springboot启动时创建tcp slave
@Component
public class ModbusSlaveUtil implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        Thread.sleep(10000);
        new Thread(new Runnable() {

            @Override
            public void run() {
                createSalve();
            }
        }).start();
    }

//    public static void main(String[] args) {
//        ModbusSlaveUtil ModbusSlaveUtil = new ModbusSlaveUtil();
//        ModbusSlaveUtil.createSalve();
//    }

    private static int[] arr = new int[]{0, 0};

    public static ModbusSlave slave;

    public void createSalve() {
        try {
            initSlave();
            System.out.println("slave start...........");
            createDataHolder();
            closeSlave();
        } catch (Exception e) {
            System.out.println("启动异常........");
        }
    }

    public static void initSlave() throws UnknownHostException, ModbusIOException {
        TcpParameters tcpParameters = new TcpParameters();// 设置从机TCP参数
        InetAddress adress = InetAddress.getByName("127.0.0.1");// 设置TCP的ip地址
        // getLocalHost()返回的是本机地址
         tcpParameters.setHost(InetAddress.getLocalHost());
//        tcpParameters.setHost(adress); // 为从机TCP设置上述ip地址参数
        // 设置从机TCP的是否长连接,通俗点讲就是一直保持连接,一次连接完下次就不要在连接了
        tcpParameters.setKeepAlive(true);
        tcpParameters.setPort(Modbus.TCP_PORT);// 设置从机TCP的端口
        // 创建一个从机
        slave = ModbusSlaveFactory.createModbusSlaveTCP(tcpParameters);
        // 设置控制台输出主机和从机命令交互日志
        Modbus.setLogLevel(Modbus.LogLevel.LEVEL_DEBUG);

    }


    public void createDataHolder() throws ModbusIOException {
        // 创建从机的寄存器
        MyOwnDataHolder dh = new MyOwnDataHolder();

        // 为从机寄存器添加监听事件,这里的监听事件主要是主机如果发送写命令修改从机则控制台输出
        dh.addEventListener(new ModbusEventListener() {
            @Override
            public int[] readHoldingRegisterRange(int offset, int quantity) {
                System.out.println("readHoldingRegisterRange: 读取信息 offset = " + offset + ";quantity" + quantity);
                try {
                    updateHoldingRegisters(offset, quantity);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return arr;
            }

            @Override
            public int[] readInputRegisterRange(int offset, int quantity) {
                System.out.println("readInputRegisterRange: 读取信息 offset = " + offset + ";quantity" + quantity);
                try {
                    updateInputRegisters(offset, quantity);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return arr;
            }

            @Override
            public void onWriteToSingleCoil(int address, boolean value) {
                System.out
                        .print("onWriteToSingleCoil: address " + address + ", value " + value);
            }

            @Override
            public void onWriteToMultipleCoils(int address, int quantity, boolean[] values) {
                System.out.print("onWriteToMultipleCoils: address " + address + ", quantity "
                        + quantity);
            }

            @Override
            public void onWriteToSingleHoldingRegister(int address, int value) {
                System.out.print("onWriteToSingleHoldingRegister: address " + address
                        + ", value " + value);
            }

            @Override
            public void onWriteToMultipleHoldingRegisters(int address, int quantity,
                                                          int[] values) {
                System.out.print("onWriteToMultipleHoldingRegisters: address " + address
                        + ", quantity " + quantity);
            }

        });
        // 为从机设置寄存器
        slave.setDataHolder(dh);
        // 设置从机的读超时时间,建议主机读的超时时间小于该值
        slave.setReadTimeout(15000);
        // 为从机设置从机服务地址slaveid
        slave.setServerAddress(1);
        // 开启从机监听事件,必须要这一句
        slave.listen();
    }

    public static void closeSlave() throws InterruptedException, ModbusIOException {
        //这部分代码主要是设置Java虚拟机关闭的时候需要做的事情,即本程序关闭的时候需要做的事情,直接使用即可
        if (slave.isListening()) {
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                synchronized (slave) {
                    slave.notifyAll();
                }
            }));

            synchronized (slave) {
                slave.wait();
            }
            slave.shutdown();
            System.out.println("slave shutdown........");
        }
    }

    public void updateHoldingRegisters(int offset, int quantity) throws IllegalDataAddressException, IllegalDataValueException {
        List<Float> list = Arrays.asList(10.1f, 20.3f, 89.5f, 77.353f);
        ModbusHoldingRegisters hr = new ModbusHoldingRegisters(50000);
        // 修改数值寄存器对应位置的值,第一个参数代表寄存器地址,第二个代表修改的数值
        //hr.set有几个方法,根据自己要赋值的数据类型选择,此处示例的是赋值float类型,一个float是4个字节,32bit,对应2个寄存器所以i*2
        for (int i = 0; i < list.size(); i++) {
            hr.setFloat32At(i * 2, list.get(i));
        }
        hr.setInt16At(42, 0x64);
        hr.setInt16At(43, 50);
        hr.setInt16At(2200, 0x2000);
        slave.getDataHolder().setHoldingRegisters(hr);
    }

    public void updateInputRegisters(int offset, int quantity) throws IllegalDataAddressException, IllegalDataValueException, ModbusIOException {
        List<Float> list = Arrays.asList(10.1f, 20.3f, 89.5f, 77.353f);
        ModbusHoldingRegisters hr = new ModbusHoldingRegisters(10000);
        // 修改数值寄存器对应位置的值,第一个参数代表寄存器地址,第二个代表修改的数值
        for (int i = 0; i < list.size(); i++) {
            hr.setFloat32At(i * 2, list.get(i));
        }
        slave.getDataHolder().setInputRegisters(hr);
    }


}

import com.intelligt.modbus.jlibmodbus.data.DataHolder;
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException;
import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException;

import java.util.ArrayList;
import java.util.List;

public class MyOwnDataHolder extends DataHolder {

    final List<ModbusEventListener> modbusEventListenerList = new ArrayList<ModbusEventListener>();

    public MyOwnDataHolder() {
        // you can place the initialization code here
        /*
         * something like that: setHoldingRegisters(new
         * SimpleHoldingRegisters(10)); setCoils(new Coils(128)); ... etc.
         */
    }

    public void addEventListener(ModbusEventListener listener) {
        modbusEventListenerList.add(listener);
    }

    public boolean removeEventListener(ModbusEventListener listener) {
        return modbusEventListenerList.remove(listener);
    }

    @Override
    public int[] readHoldingRegisterRange(int offset, int quantity) throws IllegalDataAddressException {
        for (ModbusEventListener l : modbusEventListenerList) {
            l.readHoldingRegisterRange(offset, quantity);
        }
        return super.readHoldingRegisterRange(offset, quantity);
    }

    @Override
    public int[] readInputRegisterRange(int offset, int quantity) throws IllegalDataAddressException{
        for (ModbusEventListener l : modbusEventListenerList) {
            l.readInputRegisterRange(offset, quantity);
        }
        return super.readInputRegisterRange(offset, quantity);
    }

    @Override
    public void writeHoldingRegister(int offset, int value) throws IllegalDataAddressException,
            IllegalDataValueException {
        for (ModbusEventListener l : modbusEventListenerList) {
            l.onWriteToSingleHoldingRegister(offset, value);
        }
        super.writeHoldingRegister(offset, value);
    }

    @Override
    public void writeHoldingRegisterRange(int offset, int[] range)
            throws IllegalDataAddressException, IllegalDataValueException {
        for (ModbusEventListener l : modbusEventListenerList) {
            l.onWriteToMultipleHoldingRegisters(offset, range.length, range);
        }
        super.writeHoldingRegisterRange(offset, range);
    }

    @Override
    public void writeCoil(int offset, boolean value) throws IllegalDataAddressException,
            IllegalDataValueException {
        for (ModbusEventListener l : modbusEventListenerList) {
            l.onWriteToSingleCoil(offset, value);
        }
        super.writeCoil(offset, value);
    }

    @Override
    public void writeCoilRange(int offset, boolean[] range) throws IllegalDataAddressException,
            IllegalDataValueException {
        for (ModbusEventListener l : modbusEventListenerList) {
            l.onWriteToMultipleCoils(offset, range.length, range);
        }
        super.writeCoilRange(offset, range);
    }

}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值