Java与Modbus通信

1、引入依赖

<dependency>
            <groupId>com.intelligt.modbus</groupId>
            <artifactId>jlibmodbus</artifactId>
            <!-- 版本号可依照maven仓库迭代升级 -->
            <version>1.2.9.7</version>
        </dependency>

 

2、获取Modbus连接

/**
     * 获取Modbus连接
     * @return
     */
    private Map<String, ModbusMaster> getModbusConn() throws UnknownHostException {
        ModbusMaster modbusMaster;
        TcpParameters tcpParameters = new TcpParameters();
        List<String> modbusIps = hfyProperties.getIps();
        Map<String, ModbusMaster> modbusMasterMap = new HashMap<>();
        for(String modbusIp : modbusIps){
            // TCP参数设置ip地址
            tcpParameters.setHost(InetAddress.getByName(modbusIp));
            // TCP设置长连接
            tcpParameters.setKeepAlive(true);
            // TCP设置端口,这里设置是默认端口502
            tcpParameters.setPort(Integer.valueOf(hfyProperties.getPort()));
            // 创建一个主机
            modbusMaster = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);
            modbusMasterMap.put(modbusIp, modbusMaster);
        }
        return modbusMasterMap;
    }
View Code

注:我这里是获得了3台modbus连接,因为有三台服务器。

3、根据功能码,实时读取Modbus数据

/**
     * 批量采集Modbus数据
     */
    //@RequestMapping("/")
    @Scheduled(fixedRate = 1, timeUnit = TimeUnit.SECONDS)
    public void batchReadHfyData() {
        long startTime = System.nanoTime();
        try {
            // 采集灰分仪数据
            Map<String, List<SlaveBlockDto>> slaveBlockDtoList = gatherSlaveData(slaveBlocks);
            // 发送kafka
            eventPublisher.publishEvent(new HfyMessageEvent(this, slaveBlockDtoList));
            log.info("读取数据耗时:{} 毫秒, 数据量:{}", Duration.ofNanos(System.nanoTime() - startTime).toMillis(), slaveBlockDtoList.size());
        } catch (ExecutionException | InterruptedException | UnknownHostException | ModbusIOException |
                 ModbusProtocolException | ModbusNumberException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 采集灰分仪数据
     */
    private Map<String, List<SlaveBlockDto>> gatherSlaveData(List<SlaveBlock> slaveBlocks) throws ExecutionException, InterruptedException, UnknownHostException, ModbusIOException, ModbusProtocolException, ModbusNumberException {
        List<SlaveBlockDto> dtoList;
        Map<String, ModbusMaster> modbusMasterMap = getModbusConn();
        Map<String, List<SlaveBlockDto>> resultMap = new HashMap<>();
        // 连接Modbus,实时获取料位仪的数据
        for(Map.Entry<String, ModbusMaster> modbusMaster : modbusMasterMap.entrySet()){
            ModbusMaster master = modbusMaster.getValue();
            String modbusIp = modbusMaster.getKey();
            // 开启连接
            master.connect();
            log.info("modbus, ip:{} 连接成功,连接为:{}", modbusIp, master);
            // 根据功能码读取实时数据
            dtoList = gatherImmDataByFuncCode(master);
            resultMap.put(modbusIp, dtoList);
        }
        return resultMap;
    }

    private List<SlaveBlockDto> gatherImmDataByFuncCode(ModbusMaster master) throws ModbusProtocolException, ModbusNumberException, ModbusIOException {
        List<SlaveBlockDto> dtoList = new ArrayList<>();
        int slaveId = hfyProperties.getSlaveId();
        int quantity = hfyProperties.getQuantity();
        for(SlaveBlock slaveBlock : slaveBlocks){
            if(slaveBlock.getFunctionCode().equalsIgnoreCase(FuncCodeEnum.CODE_FIVE.getCode()))
                continue;
            SlaveBlockDto slaveBlockDto = new SlaveBlockDto();
            // 功能码
            String code = slaveBlock.getFunctionCode();
            // 偏移地址
            int offset = slaveBlock.getOffset();
            FuncCodeEnum funcCodeEnum = FuncCodeEnum.fromFuncCodes(code);
            // 根据不同的功能码读取modbus数据
            switch(funcCodeEnum){
                case CODE_TWO:
                    boolean[] discreteInputs = master.readDiscreteInputs(slaveId, offset, quantity);
                    slaveBlockDto.setValue(String.valueOf(discreteInputs[0]));
                    break;
                case CODE_FOUR:
                    int[] inputRegisters = master.readInputRegisters(slaveId, offset, quantity);
                    slaveBlockDto.setValue(String.valueOf(inputRegisters[0]));
                    break;
                case CODE_FIVE:
                default:
                    break;
            }
            // 封装数据
            slaveBlockDto.setName(slaveBlock.getName());
            slaveBlockDto.setNameDesc(slaveBlock.getDesc());
            dtoList.add(slaveBlockDto);
        }
        return dtoList;
    }
View Code

源码:https://gitee.com/caesarthegreat/modbus-demo.git

posted @ 2023-01-27 19:03  Caesar_the_great  阅读(490)  评论(0编辑  收藏  举报