Browse Source

fix(infrared): 修复数据解析异常并优化解析逻辑

-增加数据长度检查,避免解析不完整的消息
- 添加错误处理,捕获并记录 NumberFormatException
- 优化能量值解析,处理 null 值并使用 BigInteger 进行精确计算
-改进仪表编号解析,增加异常处理和长度检查
- 修复 getStringList 方法,处理数据不足的情况并优化日志记录
林仔 8 tháng trước cách đây
mục cha
commit
f4237883c3

+ 61 - 14
infrared-reading-meter-service/src/main/java/com/zksy/infrared/utils/DataParser.java

@@ -25,15 +25,35 @@ public class DataParser {
                 int end = Math.min(i + 2, msgString.length());
                 dataParts.add(msgString.substring(i, end));
             }
-            String res1 = getStringList(dataParts,1);
+
+            // 检查数据部分是否足够
+            if (dataParts.size() < 1 + 1 + 1 + 4) { // address(1) + function(1) + 跳过(1) + energy(4)
+                logger.error("数据长度不足,无法解析: {}", msgString);
+                return result;
+            }
+
+            String res1 = getStringList(dataParts, 1);
             result.setAddressCode(String.valueOf(Integer.parseInt(res1, 16)));
-            String res2 = getStringList(dataParts,1);
+
+            String res2 = getStringList(dataParts, 1);
             result.setFunctionCode(String.valueOf(Integer.parseInt(res2, 16)));
-            getStringList(dataParts,1);
-            String res3 = getStringList(dataParts,4);
-            result.setElectricEnergy(Integer.parseInt(DecimalConversion.hexToDecimalExample(res3), 16) / 100.00);
+
+            // 跳过一个部分
+            getStringList(dataParts, 1);
+
+            String res3 = getStringList(dataParts, 4);
+            // 检查是否有null值
+            if (res3.contains("null")) {
+                logger.error("解析得到的电能数据包含无效值: {}", res3);
+                return result;
+            }
+
+            BigInteger energyValue = new BigInteger(res3, 16);
+            result.setElectricEnergy(energyValue.divide(BigInteger.valueOf(100)).doubleValue());
             result.setCreateTime(new Date());
 
+        } catch (NumberFormatException e) {
+            logger.error("解析数字时出错,输入字符串无效", e);
         } catch (Exception e) {
             logger.error("解析消息时出错", e);
         }
@@ -41,23 +61,50 @@ public class DataParser {
     }
 
     public static String parseMeterNumber(String msgString) {
-        String hexString = msgString.substring(6, msgString.length() - 4);
-        // 转换为BigInteger并获取无符号十进制表示
-       BigInteger bigInteger = new BigInteger(hexString, 16);
-        return bigInteger.toString();
+        try {
+            // 检查字符串长度是否足够
+            if (msgString.length() < 10) { // 6 + 4,确保有足够的长度
+                logger.error("消息字符串太短,无法解析仪表编号: {}", msgString);
+                return null;
+            }
+
+            String hexString = msgString.substring(6, msgString.length() - 4);
+            // 转换为BigInteger并获取无符号十进制表示
+            BigInteger bigInteger = new BigInteger(hexString, 16);
+            return bigInteger.toString();
+        } catch (Exception e) {
+            logger.error("解析仪表编号时出错", e);
+            return null;
+        }
     }
+
     public static String shiftFromList(List<String> list) {
         if (list == null || list.isEmpty()) {
-            return null; // 或者抛出异常,根据需求决定
+            logger.warn("尝试从空列表中获取元素");
+            return null;
         }
         return list.remove(0);
     }
 
-    private static String getStringList(List<String> dataParts,Integer q) {
-        StringBuilder res1 = new StringBuilder();
+    private static String getStringList(List<String> dataParts, Integer q) {
+        if (dataParts == null || dataParts.size() < q) {
+            logger.warn("数据部分不足,需要{}个,实际只有{}个", q, dataParts == null ? 0 : dataParts.size());
+            // 返回空字符串或处理不足的情况
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < q; i++) {
+                sb.append(shiftFromList(dataParts));
+            }
+            return sb.toString();
+        }
+
+        StringBuilder res = new StringBuilder();
         for (int i = 0; i < q; i++) {
-            res1.append(shiftFromList(dataParts));
+            String part = shiftFromList(dataParts);
+            if (part == null) {
+                logger.warn("获取第{}个元素时为null", i);
+            }
+            res.append(part);
         }
-        return res1.toString();
+        return res.toString();
     }
 }