springboot中modbus使用

modbus在springboot中的使用,
本人在用,复制即可用

pom.xml配置:

	<!-- 辅助modbus4j:repository id:ias-snapshots id:ias-releases 两个 -->
    <repositories>
        <repository>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <id>ias-snapshots</id>
            <name>Infinite Automation Snapshot Repository</name>
            <url>https://maven.mangoautomation.net/repository/ias-snapshot/</url>
        </repository>
        <repository>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>ias-releases</id>
            <name>Infinite Automation Release Repository</name>
            <url>https://maven.mangoautomation.net/repository/ias-release/</url>
        </repository>
    </repositories>
    
        <!-- modbus -->
        <dependency>
            <groupId>com.infiniteautomation</groupId>
            <artifactId>modbus4j</artifactId>
            <version>3.0.3</version>
        </dependency>

modbus配置类:

package com.induo.common.modbus;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;


import com.induo.domain.mapper.IpControlMapper;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.ip.IpParameters;

import java.util.HashMap;

@Configuration
/*
 * 使用@Bean,就不用使用@Import来导入相应的类了,@Bean生成的bean的名字默认为方法名,由于hashMap使用很广泛,
 * 所以使用@Bean的方式引入依赖,这样在注入的时候可以指定名称,以免注入错误的对象
 * @Import({java.util.HashMap.class,com.serotonin.modbus4j.ModbusFactory.class})
 */
@Import(com.serotonin.modbus4j.ModbusFactory.class)
public class ModbusConfig {

    @Bean
    public HashMap<String, ModbusMaster> modbusMasterHashMap() {

        return new HashMap<>();
    }

    @Autowired
    IpControlMapper ipControlMapper;

    @Autowired
    private ModbusFactory modbusFactory;

    @Autowired
    @Qualifier("modbusMasterHashMap")
    private HashMap<String,ModbusMaster> masterMap;

    /**
     * @Title getMaster
     * @Description: 通过ip获取对应的modbus连接器
     * @params: [ip]
     * @return: com.serotonin.modbus4j.ModbusMaster
     * @author: caiwei
     * @date: 2019/5/1 13:58
     */
    public ModbusMaster getMaster(String ip) {

        ModbusMaster modbusMaster = masterMap.get(ip);
        if(modbusMaster == null) {
            setMaster(ip, ipControlMapper.queryControlByIp(ip).getPort());
            modbusMaster = masterMap.get(ip);
        }
        return modbusMaster;


    }

    /**
     * @Title setMaster
     * @Description: 设置ip对应的modbus连接器
     * @params: [ip, port]
     * @return: void
     * @author: caiwei
     * @date: 2019/5/1 13:59
     */
    private void setMaster(String ip, Integer port) {

        ModbusMaster master;
        IpParameters params = new IpParameters();
        params.setHost(ip);
        params.setPort(port);
        //设置为true,会导致TimeoutException: request=com.serotonin.modbus4j.ip.encap.EncapMessageRequest@774dfba5",
        //params.setEncapsulated(true);
        master = modbusFactory.createTcpMaster(params, false);// TCP 协议
        try {
            //设置超时时间
            master.setTimeout(3*1000);
            //设置重连次数
            master.setRetries(3);
            //初始化
            master.init();
        } catch (ModbusInitException e) {
            e.printStackTrace();
        }
        masterMap.put(ip, master);
    }

}

modbus工具类:

package com.induo.common.modbus;

import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.msg.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @ClassName: ModbusUtil
 * @Description: modbus读写工具类
 * @auther: caiwei
 * @date: 2019/5/1 15:44
 */
@Component
public class ModbusUtil {

    //从机默认值
    private Integer slaveId = 1;

    @Autowired
    private ModbusConfig modbusConfig;

    /**
     * @Title readCoilStatus
     * @Description: 读(线圈)开关量数据,相当于功能码:01H-读线圈状态
     * @params: [ip, slaveId, offset, numberOfRegister]
     * @return: boolean[]
     * @throws:
     * @author: caiwei
     * @date: 2019/5/1 14:32
     */
    public boolean[] readCoilStatus(String ip, int offset, int numberOfRegister) throws ModbusTransportException {

        ModbusMaster master = modbusConfig.getMaster(ip);
        ReadCoilsRequest request = new ReadCoilsRequest(slaveId, offset, numberOfRegister);
        ReadCoilsResponse response = (ReadCoilsResponse) master.send(request);
        boolean[] booleans = response.getBooleanData();

        return valueRegroup(numberOfRegister, booleans);
    }

    /**
     * @Title readInputStatus
     * @Description: 读取外围设备输入的开关量,相当于功能码:02H-读离散输入状态
     * @params: [ip, offset, numberOfRegister]
     * @return: boolean[]
     * @throws:
     * @author: caiwei
     * @date: 2019/5/1 14:49
     */
    public boolean[] readInputStatus(String ip, int offset, int numberOfRegister) throws ModbusTransportException {

        ModbusMaster master = modbusConfig.getMaster(ip);
        ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId,offset, numberOfRegister);
        ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) master.send(request);
        boolean[] booleans = response.getBooleanData();

        return valueRegroup(numberOfRegister, booleans);
    }

    /**
     * @Title readHoldingRegister
     * @Description: 读取保持寄存器数据,相当于功能码:03H-读保持寄存器
     * @params: [ip, offset, numberOfRegister]
     * @return: short[]
     * @throws:
     * @author: caiwei
     * @date: 2019/5/1 15:53
     */
    public short[] readHoldingRegister(String ip, int offset, int numberOfRegister) throws ModbusTransportException {

        ModbusMaster master = modbusConfig.getMaster(ip);
        ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, offset, numberOfRegister);
        ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);
        return response.getShortData();
    }

    /**
     * @Title readInputRegisters
     * @Description: 读取外围设备输入的数据,相当于功能码:04H-读输入寄存器
     * @params: [ip, offset, numberOfRegister]
     * @return: short[]
     * @throws:
     * @author: caiwei
     * @date: 2019/5/1 15:56
     */
    public short[] readInputRegisters(String ip, int offset, int numberOfRegister) throws ModbusTransportException {

        ModbusMaster master = modbusConfig.getMaster(ip);
        ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, offset, numberOfRegister);
        ReadInputRegistersResponse response = (ReadInputRegistersResponse) master.send(request);
        return response.getShortData();
    }

    /**
     * @Title writeCoil
     * @Description: 写单个(线圈)开关量数据,相当于功能码:05H-写单个线圈
     * @params: [ip, writeOffset, writeValue]
     * @return: boolean
     * @throws:
     * @author: caiwei
     * @date: 2019/5/1 16:00
     */
    public boolean writeCoil(String ip, int writeOffset, boolean writeValue) throws ModbusTransportException {

        ModbusMaster tcpMaster = modbusConfig.getMaster(ip);
        WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
        WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request);
        return !response.isException();
    }

    /**
     * @Title writeCoils
     * @Description: 写多个开关量数据(线圈),相当于功能码:0FH-写多个线圈
     * @params: [ip, startOffset, data]
     * @return: boolean
     * @throws:
     * @author: caiwei
     * @date: 2019/5/1 16:00
     */
    public boolean writeCoils(String ip, int startOffset, boolean[] data) throws ModbusTransportException {

        ModbusMaster tcpMaster = modbusConfig.getMaster(ip);
        WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, data);
        WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request);
        return !response.isException();

    }

    /**
     * @Title writeHoldingRegister
     * @Description: 写单个保持寄存器,相当于功能码:06H-写单个保持寄存器
     * @params: [ip, writeOffset, writeValue]
     * @return: boolean
     * @throws:
     * @author: caiwei
     * @date: 2019/5/1 16:02
     */
    public boolean writeHoldingRegister(String ip, int writeOffset, short writeValue) throws ModbusTransportException, ModbusInitException {

        ModbusMaster tcpMaster = modbusConfig.getMaster(ip);
        WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
        WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request);
        return !response.isException();

    }

    /**
     * @Title writeHoldingRegisters
     * @Description: 写多个保持寄存器,相当于功能码:10H-写多个保持寄存器
     * @params: [ip, slaveId, startOffset, data]
     * @return: boolean
     * @throws:
     * @author: caiwei
     * @date: 2019/5/1 16:03
     */
    public boolean writeHoldingRegisters(String ip, int startOffset, short[] data) throws ModbusTransportException, ModbusInitException {

        ModbusMaster tcpMaster = modbusConfig.getMaster(ip);
        WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, data);
        WriteRegistersResponse response = (WriteRegistersResponse) tcpMaster.send(request);
        return !response.isException();
    }

    /**
     * @Title valueRegroup
     * @Description: 转换工具,将Boolean转换成0,1
     * @params: [numberOfBits, values]
     * @return: boolean[]
     * @throws:
     * @author: caiwei
     * @date: 2019/5/1 15:55
     */
    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;
    }
}

ipControlMapper:

package com.induo.area.domain.mapper;

import java.util.List;


import com.induo.area.domain.entity.IpControl;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface IpControlMapper {


    @Results(id = "ipControlMap", value = {
            @Result(column = "ip", property = "ip", javaType = String.class),
            @Result(column = "port", property = "port", javaType = Integer.class),
            @Result(column = "ip_type", property = "ipType", javaType = Integer.class),
            @Result(column = "device_data_gather_cycle", property = "deviceDataGatherCycle", javaType = Integer.class),
            @Result(column = "device_data_gather_interval", property = "deviceDataGatherInterval", javaType = Integer.class),
            @Result(column = "note_alarm_data_gather_cycle", property = "noteAlarmDataGatherCycle", javaType = Integer.class),
            @Result(column = "environment_data_gather_cycle", property = "environmentDataRecordCycle", javaType = Integer.class)
    })
    //通过ip查询控制器
    @Select("select ip, port, ip_type, device_data_gather_cycle, device_data_gather_interval, note_alarm_data_gather_cycle, environment_data_gather_cycle " +
            "from control " +
            "where ip = #{ip}")
    IpControl queryControlByIp(String ip);

    //通过ip类型(0:区域控制器, 1:八防控制器)查询控制器
    @Select("select ip " +
            "from control " +
            "where ip_type = #{ipType}")
    List<String> queryAllIpControlIp(String ipType);

    //插入控制器
    @Insert("insert into control(ip, port, ip_type, device_data_gather_cycle, device_data_gather_interval, note_alarm_data_gather_cycle, environment_data_gather_cycle) " +
            "values (#{ip}, #{port}, #{ipType}, #{deviceDataGatherCycle}, #{deviceDataGatherInterval}, #{noteAlarmDataGatherCycle}, #{environmentDataRecordCycle})")
    void addIpControl(IpControl ipControl);

    //更新区域控制器
    @Update("<script>" +
            "update control " +
            "<set>" +
            "<if test='port !=null'>port = #{port},</if>" +
            "<if test='ipType !=null'>ip_type = #{ipType},</if>" +
            "<if test='pollInterval !=null'>device_data_gather_cycle  = #{deviceDataGatherCycle}, </if>" +
            "<if test='deviceInterval !=null'>device_data_gather_interval = #{deviceDataGatherInterval}, </if>" +
            "<if test='deviceInterval !=null'>note_alarm_data_gather_cycle = #{noteAlarmDataGatherCycle}, </if>" +
            "<if test='enviInterval !=null'>environment_data_gather_cycle = #{environmentDataRecordCycle}, </if>" +
            "</set> " +
            "where ip = #{ip}" +
            "</script>")
    void updateIpControl(IpControl ipControl);

    //通过ip删除相应的控制器
    @Delete("delete " +
            "from control " +
            "where ip = #{ip}")
    void deleteIpControl(String ip);
}

ipControl:

package com.induo.area.model;

import lombok.Data;

@Data
public class IpControl {

    private String storeName;
    private String ip;
    private Integer port;
    private Integer ipType;
    private Integer deviceDataGatherCycle;
    private Integer deviceDataGatherInterval;
    private Integer noteAlarmDataGatherCycle;
    private Integer environmentDataRecordCycle;

}

Spring Boot是一个用于快速搭建基于Spring框架的应用程序的开发框架,而Modbus4j则是一个用于在Java应用程序实现Modbus协议的库。 Modbus是一种用于不同设备之间通信的通信协议,包括RTU(串行通信)和TCP(基于IP网络通信)。Modbus4j是一个为了简化在Java应用程序使用Modbus协议进行通信而开发的库。 在使用Spring Boot集成Modbus4j RTU时,我们需要先引入Modbus4j的依赖,可以在项目的pom.xml文件添加如下依赖: ```xml <dependency> <groupId>com.serotonin</groupId> <artifactId>modbus4j</artifactId> <version>3.0.2</version> </dependency> ``` 接下来,我们可以创建一个Modbus4j的配置类,并在其进行相关配置。例如,指定Modbus RTU通信的串口及参数: ```java @Configuration public class ModbusConfig { @Bean public ModbusMaster modbusMaster() throws Exception { SerialParameters parameters = new SerialParameters(); parameters.setCommPortId("/dev/ttyUSB0"); // 串口号 parameters.setBaudRate(9600); // 波特率 parameters.setDataBits(8); // 数据位 parameters.setStopBits(1); // 停止位 parameters.setParity(Parity.NONE); // 校验位 ModbusMaster modbusMaster = new SerialModbusMaster(parameters); modbusMaster.init(); return modbusMaster; } } ``` 在上述配置,我们创建了一个ModbusMaster对象,并指定了串口号、波特率、数据位、停止位和校验位等参数。 在需要使用Modbus通信的业务逻辑,我们可以通过注入ModbusMaster对象来进行通信操作。例如,读取Modbus设备的寄存器值: ```java @Service public class ModbusService { @Autowired private ModbusMaster modbusMaster; public int readRegister(int slaveId, int register) throws ModbusTransportException { ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, register, 1); ReadInputRegistersResponse response = (ReadInputRegistersResponse) modbusMaster.send(request); return response.getRegisters()[0].toShort(); } } ``` 上述代码,我们通过注入ModbusMaster对象,并使用该对象发送读取寄存器请求,然后获取返回的寄存器值。 总之,通过在Spring Boot使用Modbus4j RTU,我们可以方便地实现与Modbus设备的通信,并轻松读写设备的寄存器等操作。以上只是一个简单的示例,实际使用还可以进行更多的功能扩展和定制化。
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值