Die Java-Implementierung verwendet jlibmodbus zum Lesen von Modbus-TCP-Daten

Tipp: Mit dem Modbus-Slave-Tool können Sie eine Modbus-Datenstation simulieren und einige Daten hinzufügen.
1. Pom führt Abhängigkeiten ein

<dependency>
	 <groupId>com.intelligt.modbus</groupId>
	 <artifactId>jlibmodbus</artifactId>
	 <version>1.2.9.7</version>
</dependency>

2. Erstellen Sie eine Modbus-Hostverbindung

public class JlibModbusBase {
    static ModbusMaster modbusMaster;
    public static void initJlibModbusMaster(String ip) {
        // 如果连接不存在,创建一个主机连接
        if (ObjectUtils.isEmpty(modbusMaster)) {
            // 设置主机TCP参数
            TcpParameters tcpParameters = new TcpParameters();
            // 设置TCP的ip地址-本地地址
            InetAddress address = null;
            try {
                address = InetAddress.getByName(ip);
            } catch (UnknownHostException e) {
                throw new RuntimeException(e);
            }
            tcpParameters.setHost(address);
            // TCP设置长连接
            tcpParameters.setKeepAlive(true);
            // TCP设置端口,这里设置是默认端口502
            tcpParameters.setPort(502);
            modbusMaster = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
            Modbus.setAutoIncrementTransactionId(true);
        }
    }
    public static void release() {
        if (modbusMaster != null) {
            try {
                modbusMaster.disconnect();
            } catch (ModbusIOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

3. Erhalten Sie die Daten der Funktionscodes 0x04 und 0x03 durch Verbindung

public class JlibModbusBaseTool {
    /**
     * "功能码0x04"
     * 读取HoldingRegister数据
     *
     * @param slaveId  寄存器地址ID
     * @param offset   寄存器读取开始地址
     * @param quantity 读取寄存器数量
     * @return int数组
     */
    public static int[] readInputRegisters(int slaveId, int offset, int quantity) {
        try {
            return modbusMaster.readInputRegisters(slaveId, offset, quantity);
        } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException e) {
            throw new RuntimeException(e);
        } finally {
            release();
        }
    }
    /**
     * "功能码0x03"
     * 读取HoldingRegister数据
     *
     * @param slaveId  寄存器地址ID
     * @param offset   寄存器读取开始地址
     * @param quantity 读取寄存器数量
     * @return int数组
     */
    public static int[] readHoldingRegisters(int slaveId, int offset, int quantity) {
        try {
            return modbusMaster.readHoldingRegisters(slaveId, offset, quantity);
        } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException e) {
            throw new RuntimeException(e);
        } finally {
            release();
        }
    }

4. Führen Sie den Methodenaufruf und die Datenanalyse gemäß den spezifischen Geschäftsbedingungen durch. In meinem eigentlichen Unternehmen gibt es zwei IP-Adressen (tatsächlich kann die obige Hostverbindung basierend auf unterschiedlichen IPs in Echtzeit unterschiedliche Verbindungen herstellen). Denn beim Lesen der Registeranzahl können bis zu 124 Register gelesen werden. Daher werden mehrere Datenabrufzyklen basierend auf der tatsächlichen Geschäftssituation durchgeführt.

//读取的寄存器数量,一次读取两台设备寄存器数据
//因为实际使用中数据为float数据,下文还会进行数据的转换
int quantity = 96;
int[] result = null;
int salveId = 0;
//获取数据
result = JlibModbusBaseTool.readInputRegisters(salveId,offset,quantity);
//首先将int[]转化为集合,然后将读取到的数据集合,分成两个集合
List<Integer> intList = Arrays.stream(result).boxed().toList();
int LIMIT_TOW = 48;
ArrayList<List<Integer>> dataList = new ArrayList<>();
Stream.iterate(0, n -> n + 1).limit(countStep(intList.size(), LIMIT_TOW)).forEach(i -> {
  dataList.add(intList.stream().skip(i * LIMIT_TOW).limit(LIMIT_TOW).collect(Collectors.toList()));
});
//计算分组数量
public static Integer countStep(Integer size,int limt) {
   return (size + limt - 1) / limt;
}
//然后读取int[]数据,转化为浮点类型
// 两个数据一组,组成16进制字符转,转化为float数据类型
public static CcElectricityMeterNew convertFloat(int[] array, CcElectricityMeterNew meterNew){
   for (int i = 0; i < array.length; i++) {
       if ((i+1)%2==0) {
           int first = array[i-1];
           int second = array[i];
           //在进行字符串转化时,转化的16进制会存在缺少一位的情况,进行左侧补零操作
           String hexStr = addZeroForStr(Integer.toHexString(first),4,1)+""+addZeroForStr(Integer.toHexString(second),4,1);
           System.out.println(new BigDecimal(sfloat(hexStr)));
       }
   }
   return meterNew;
}
//将字符串类型的16进制数据,转化为float字符串
private static String sfloat(String str){
      Float value =  Float.intBitsToFloat(new BigInteger(str, 16).intValue());
      return String.valueOf(value);
  }

/**
  * 给字符串的左补0或右补0
  * @param str  要处理的字符串
  * @param length 补0后字符串总长度
  * @return 返回补零字符串
  */
 public static String addZeroForStr(String str, int length,int type) {
     int strLen = str.length();
     if (strLen < length) {
         while (strLen < length) {
             StringBuffer sb = new StringBuffer();
           		if(type==1){
                    // 左补0
                    sb.append("0").append(str);
                }else if(type==2){
                    //右补0
                    sb.append(str).append("0");
                }
             str = sb.toString();
             strLen = str.length();
         }
     }
     return str;
 }

Anmerkungen: Es ist sehr einfach, jlibmodbus zum Lesen von Modbus-TCP-Daten zu verwenden. Sie müssen diese entsprechend dem Datentyp konvertieren, den Sie während der Verwendung benötigen. Gleichzeitig müssen Sie auf die Anzahl der zu erfassenden Register achten zu einem bestimmten Zeitpunkt durchzuführen und Daten in einem angemessenen Zyklus zu erhalten. Beim Erfassen von Modbus-Daten ist ein Problem aufgetreten. Beim Erfassen einer großen Anzahl wiederholter Verbindungsdaten tritt bei Modbus das Problem auf, dass die Verbindung zurückgesetzt wird, was dazu führt, dass die Datenerfassung die nachfolgende Datenerfassung nicht unterbrechen kann. Die Ursache des Problems wurde nicht gefunden vorerst. Wenn jemand das Prinzip Gott kennt, hoffe ich, dass Sie mir eine Antwort geben können! ! !

Supongo que te gusta

Origin blog.csdn.net/weixin_38863607/article/details/128629785
Recomendado
Clasificación