YunaiV/yudao-cloud · error · IllegalArgumentException
不支持的功能码: {}
Error message
不支持的功能码: {} What it means
IotModbusTcpClientUtils.createReadRequest switches on the function code and only maps the four Modbus read codes — FC_READ_COILS (01), FC_READ_DISCRETE_INPUTS (02), FC_READ_HOLDING_REGISTERS (03), FC_READ_INPUT_REGISTERS (04). Any other value (write codes 05/06/0F/10, 0, null, or exotic codes) hits the default branch and throws IllegalArgumentException '不支持的功能码'. The code comes from the IoT thing-model point configuration.
Source
Thrown at yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbus/common/utils/IotModbusTcpClientUtils.java:141
});
}
/**
* 创建读取请求
*/
@SuppressWarnings("EnhancedSwitchMigration")
private static ModbusRequest createReadRequest(Integer functionCode, Integer address, Integer count) {
switch (functionCode) {
case FC_READ_COILS:
return new ReadCoilsRequest(address, count);
case FC_READ_DISCRETE_INPUTS:
return new ReadInputDiscretesRequest(address, count);
case FC_READ_HOLDING_REGISTERS:
return new ReadMultipleRegistersRequest(address, count);
case FC_READ_INPUT_REGISTERS:
return new ReadInputRegistersRequest(address, count);
default:
throw new IllegalArgumentException("不支持的功能码: " + functionCode);
}
}
/**
* 创建写入请求
*/
@SuppressWarnings("EnhancedSwitchMigration")
private static ModbusRequest createWriteRequest(Integer functionCode, Integer address, Integer count, int[] values) {
switch (functionCode) {
case FC_READ_COILS: // 写线圈(使用功能码 5 或 15)
if (count == 1) {
return new WriteCoilRequest(address, values[0] != 0);
} else {
BitVector bv = new BitVector(count);
for (int i = 0; i < Math.min(values.length, count); i++) {
bv.setBit(i, values[i] != 0);
}
return new WriteMultipleCoilsRequest(address, bv);View on GitHub (pinned to 477be9dd49)
Solutions
- Set the point's function code to one of 1, 2, 3, 4 for readable points
- Use write codes (5, 6, 15, 16) only for points that are written, and never route reads to them
- Validate the FC column when importing points in bulk (1-4 for read, 5/6/15/16 for write)
Example fix
// before: holding-register point given a write FC
{"identifier":"temp","functionCode":6}
// after
{"identifier":"temp","functionCode":3} // FC3 = read holding registers Defensive patterns
Strategy: type-guard
Validate before calling
Set<Integer> READABLE_FC = Set.of(1, 2, 3, 4);
if (!READABLE_FC.contains(point.getFunctionCode())) {
throw new IllegalArgumentException("点位 functionCode=" + point.getFunctionCode()
+ " 不支持读取 (需 01/02/03/04)");
} Type guard
boolean isReadableFunctionCode(Integer fc) {
return fc != null && Set.of(1, 2, 3, 4).contains(fc);
} Prevention
- Validate FC on point creation: reads only for FC 1-4, writes only via 5/6/15/16
- Bulk-import with a FC whitelist check per point
- Watch decimal-vs-hex confusion (16 vs 0x10) when transcribing device manuals
When it happens
Trigger: A read/poll issued against a point whose functionCode is a write code (05, 06, 15, 16); point created with functionCode 0/null; typo in the FC field during bulk point import; using a nonstandard vendor FC.
Common situations: Bulk-importing thing model points with wrong FC column; copy-pasting a register point and forgetting to change its FC; device doc listing decimal vs hex FCs (16 entered where 0x10=16 is meant inconsistently).
Related errors
AI-assisted analysis of YunaiV/yudao-cloud@477be9dd49 (2026-08-14).
Data as JSON: /api/errors/64d8749049be0da0.
Report an issue: GitHub.