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);
|
}
|
|
}
|