{"record":{"id":"2f9da9db6be93854","repo":"YunaiV/yudao-cloud","slug":"error-2f9da9","errorCode":null,"errorMessage":"功能码 {} 不支持写操作","messagePattern":"功能码 (.+?) 不支持写操作","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbus/common/utils/IotModbusTcpClientUtils.java","lineNumber":110,"sourceCode":"     * 写入 Modbus 数据\n     *\n     * @param connection Modbus 连接\n     * @param slaveId    从站地址\n     * @param point      点位配置\n     * @param values     要写入的值\n     * @return 是否成功\n     */\n    public static Future<Boolean> write(IotModbusTcpClientConnectionManager.ModbusConnection connection,\n                                        Integer slaveId,\n                                        IotModbusPointRespDTO point,\n                                        int[] values) {\n        return connection.executeBlocking(tcpConnection -> {\n            try {\n                // 1. 创建请求\n                ModbusRequest request = createWriteRequest(point.getFunctionCode(),\n                        point.getRegisterAddress(), point.getRegisterCount(), values);\n                if (request == null) {\n                    throw new RuntimeException(\"功能码 \" + point.getFunctionCode() + \" 不支持写操作\");\n                }\n                request.setUnitID(slaveId);\n\n                // 2. 执行事务（请求）\n                ModbusTCPTransaction transaction = new ModbusTCPTransaction(tcpConnection);\n                transaction.setRequest(request);\n                transaction.execute();\n                return true;\n            } catch (Exception e) {\n                throw new RuntimeException(String.format(\"Modbus 写入失败 [slaveId=%d, identifier=%s, address=%d]\",\n                        slaveId, point.getIdentifier(), point.getRegisterAddress()), e);\n            }\n        });\n    }\n\n    /**\n     * 创建读取请求\n     */","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/YunaiV/yudao-cloud/blob/477be9dd49ab7223a972a6abdff0684d6423dec3/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/modbus/common/utils/IotModbusTcpClientUtils.java#L92-L128","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: point configured with read FC\n{\"identifier\":\"pump_switch\",\"functionCode\":2,\"accessMode\":\"rw\"} // write -> RuntimeException\n\n// after\n{\"identifier\":\"pump_switch\",\"functionCode\":5,\"accessMode\":\"rw\"} // FC5 = write single coil","handlingStrategy":"validation","validationCode":"Set<Integer> WRITABLE_FC = Set.of(5, 6, 15, 16);\nif (!WRITABLE_FC.contains(point.getFunctionCode())) {\n    throw new IllegalArgumentException(\"点位 functionCode=\" + point.getFunctionCode()\n        + \" 为只读，不能执行写操作 (需 05/06/0F/10)\");\n}","typeGuard":"boolean isWritableFunctionCode(Integer fc) {\n    return fc != null && Set.of(5, 6, 15, 16).contains(fc);\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["iot","modbus","function-code","write","thing-model"],"backgroundTag":null,"analyzedSha":"477be9dd49ab7223a972a6abdff0684d6423dec3","analyzedAt":"2026-08-14T13:35:31.121Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}