yeg
2026-08-26 e12439d1f4a94957d68cda653cb666702bc71040
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package com.ruoyi.web.controller.tool;
 
import com.intelligt.modbus.jlibmodbus.master.ModbusMaster;
import com.intelligt.modbus.jlibmodbus.master.ModbusMasterFactory;
import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters;
import com.ruoyi.common.core.domain.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
@Api(tags = "modbus测试")
@RestController
@RequestMapping("/base")
public class ModbusExample {
 
    @ApiOperation(value = "抓取700号段寄存器数据")
    @GetMapping(value = "/test")
    public R<List<Map<String, Object>>> test() {
        // 1. 设置 TCP 参数
        TcpParameters tcpParameters = new TcpParameters();
        try {
            // 这里的 IP 保持你之前的配置,端口 502
            tcpParameters.setHost(InetAddress.getByName("192.168.40.138"));
            tcpParameters.setKeepAlive(true);
            tcpParameters.setPort(502);
 
            // 2. 创建 Master 实例
            ModbusMaster master = ModbusMasterFactory.createModbusMasterTCP(tcpParameters);
//            master.setConnectTimeout(3000); // 设置3秒超时
 
            try {
                if (!master.isConnected()) {
                    master.connect();
                }
 
                // --- 关键参数修改区 (匹配你的 Modbus Poll 截图) ---
                int slaveId = 1;      // Slave ID: 1
                int offset = 700;     // Address: 700 (对应 PLC 40701)
                int quantity = 50;    // Quantity: 30
                // ----------------------------------------------
 
                // 3. 读取保持寄存器
                int[] registerValues = master.readHoldingRegisters(slaveId, offset, quantity);
 
                // 4. 解析并封装为 JSON 格式 (List<Map>)
                List<Map<String, Object>> dataList = new ArrayList<>();
                for (int i = 0; i < registerValues.length; i++) {
                    Map<String, Object> item = new HashMap<>();
                    int currentAddress = offset + i;
                    int rawValue = registerValues[i];
 
                    item.put("address", currentAddress); // 寄存器物理地址
                    item.put("value", rawValue);         // 寄存器原始数值
 
                    // 这里可以根据业务增加转换逻辑,例如:
                    // if(currentAddress == 700) item.put("comment", "设备运行状态");
 
                    dataList.add(item);
                }
 
                // 5. 返回带数据的成功响应
                return R.ok(dataList);
 
            } catch (Exception e) {
                e.printStackTrace();
                return R.fail("Modbus 读取异常: " + e.getMessage());
            } finally {
                // 必须断开连接,否则下次请求可能因为连接数占满而失败
                master.disconnect();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail("网络配置异常: " + e.getMessage());
        }
    }
 
    // 假设 regs[10] = 50880, regs[11] = 45 (这里假设 711 是高位)
    public static float registersToFloat(int low, int high) {
        // 1. 将两个 16 位整数合成一个 32 位整数
        int combined = (high << 16) | (low & 0xFFFF);
        // 2. 将 32 位整数按 IEEE 754 标准转为浮点数
        return Float.intBitsToFloat(combined);
    }
 
    private static float parseModbusFloat(int reg1, int reg2) {
        // 尝试 CDAB 顺序 (这是大多数 HMI 如 Delta/台达 屏幕常用的顺序)
        int bits = (reg1 << 16) | (reg2 & 0xFFFF);
 
        // 如果结果还是不对,试着把上面这行换成 ABCD:
//         int bits = (reg2 << 16) | (reg1 & 0xFFFF);
 
//        int bits = ((reg1 & 0xFF) << 24) | ((reg1 >> 8) << 16) | ((reg2 & 0xFF) << 8) | (reg2 >> 8);
        return Float.intBitsToFloat(bits);
    }
 
    public static void main(String[] args) {
        // 调用示例
        float value = parseModbusFloat(50880, 45);
//        float value = parseModbusFloat(45, 50880);
        System.out.println("解析后的真实数值: " + value);
    }
 
}