YunaiV/yudao-cloud · error · RuntimeException
功能码 {} 不支持写操作
Error message
功能码 {} 不支持写操作 What it means
IotModbusTcpClientUtils.write builds a write request from the point's functionCode; createWriteRequest returns null for codes it cannot turn into a write operation (only coil-writing and register-writing codes are mapped), and this null becomes a RuntimeException '功能码 x 不支持写操作'. In other words the IoT point (thing model data point) is configured with a read-oriented function code (e.g. 02 read discrete inputs, 03/04 read registers) but a write command was issued against it.
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:110
* 写入 Modbus 数据
*
* @param connection Modbus 连接
* @param slaveId 从站地址
* @param point 点位配置
* @param values 要写入的值
* @return 是否成功
*/
public static Future<Boolean> write(IotModbusTcpClientConnectionManager.ModbusConnection connection,
Integer slaveId,
IotModbusPointRespDTO point,
int[] values) {
return connection.executeBlocking(tcpConnection -> {
try {
// 1. 创建请求
ModbusRequest request = createWriteRequest(point.getFunctionCode(),
point.getRegisterAddress(), point.getRegisterCount(), values);
if (request == null) {
throw new RuntimeException("功能码 " + point.getFunctionCode() + " 不支持写操作");
}
request.setUnitID(slaveId);
// 2. 执行事务(请求)
ModbusTCPTransaction transaction = new ModbusTCPTransaction(tcpConnection);
transaction.setRequest(request);
transaction.execute();
return true;
} catch (Exception e) {
throw new RuntimeException(String.format("Modbus 写入失败 [slaveId=%d, identifier=%s, address=%d]",
slaveId, point.getIdentifier(), point.getRegisterAddress()), e);
}
});
}
/**
* 创建读取请求
*/View on GitHub (pinned to 477be9dd49)
Solutions
- Set the point's function code to a writable one: 05/06 (single) or 0F/10 (multiple) for write operations
- Verify the downlink command maps to the correct point identifier (not a read-only sensor point)
- Expose writability in your thing-model metadata so the UI blocks write attempts on read-only points
Example fix
// before: point configured with read FC
{"identifier":"pump_switch","functionCode":2,"accessMode":"rw"} // write -> RuntimeException
// after
{"identifier":"pump_switch","functionCode":5,"accessMode":"rw"} // FC5 = write single coil Defensive patterns
Strategy: validation
Validate before calling
Set<Integer> WRITABLE_FC = Set.of(5, 6, 15, 16);
if (!WRITABLE_FC.contains(point.getFunctionCode())) {
throw new IllegalArgumentException("点位 functionCode=" + point.getFunctionCode()
+ " 为只读,不能执行写操作 (需 05/06/0F/10)");
} Type guard
boolean isWritableFunctionCode(Integer fc) {
return fc != null && Set.of(5, 6, 15, 16).contains(fc);
} Prevention
- Mark thing-model points read-only unless their FC is 05/06/15/16
- Block write commands in the UI/API for read-only points
- Validate FC on point create/import: 1-4 read-only, 5/6/15/16 writable
When it happens
Trigger: Calling a device thing-model service/property-set whose point has functionCode 02/03/04; point misconfigured at creation with a read FC where a write FC (05/06/0F/10) was intended; downlink command mapped to the wrong data point identifier.
Common situations: Thing model points imported with read FCs then reused as writable properties; UI letting users pick any FC for a writable point; device point identifier mismatch routing a write to a read-only point.
Related errors
AI-assisted analysis of YunaiV/yudao-cloud@477be9dd49 (2026-08-14).
Data as JSON: /api/errors/2f9da9db6be93854.
Report an issue: GitHub.