diff --git a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponent.java b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponent.java index ff19b82f577..d78b6dee4e7 100644 --- a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponent.java +++ b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponent.java @@ -1,6 +1,8 @@ package io.openems.edge.bridge.modbus.sunspec; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -21,6 +23,7 @@ import io.openems.edge.bridge.modbus.api.ElementToChannelScaleFactorConverter; import io.openems.edge.bridge.modbus.api.ModbusProtocol; import io.openems.edge.bridge.modbus.api.ModbusUtils; +import io.openems.edge.bridge.modbus.api.element.AbstractModbusElement; import io.openems.edge.bridge.modbus.api.element.DummyRegisterElement; import io.openems.edge.bridge.modbus.api.element.ModbusElement; import io.openems.edge.bridge.modbus.api.element.ModbusRegisterElement; @@ -37,6 +40,11 @@ */ public abstract class AbstractOpenemsSunSpecComponent extends AbstractOpenemsModbusComponent { + /** + * Limit of a task length in j2mod. + */ + private static final int MAXIMUM_TASK_LENGTH = 126; + private final Logger log = LoggerFactory.getLogger(AbstractOpenemsSunSpecComponent.class); // The active SunSpec-Models and their reading-priority @@ -283,13 +291,13 @@ public boolean isSunSpecInitializationCompleted() { protected void addBlock(int startAddress, SunSpecModel model, Priority priority) throws OpenemsException { this.logInfo(this.log, "Adding SunSpec-Model [" + model.getBlockId() + ":" + model.label() + "] starting at [" + startAddress + "]"); - var elements = new ModbusElement[model.points().length]; + Deque elements = new ArrayDeque<>(); startAddress += 2; for (var i = 0; i < model.points().length; i++) { var point = model.points()[i]; var element = point.get().generateModbusElement(startAddress); startAddress += element.length; - elements[i] = element; + elements.add(element); var channelId = point.getChannelId(); this.addChannel(channelId); @@ -348,8 +356,37 @@ protected void addBlock(int startAddress, SunSpecModel model, Priority priority) } } - final Task readTask = new FC3ReadRegistersTask(elements[0].startAddress, priority, elements); - this.modbusProtocol.addTask(readTask); + this.addReadTasks(elements, priority); + } + + /** + * Splits the task if it is too long and adds the read tasks. + * + * @param elements the Deque of {@link ModbusElement}s for one block. + * @param priority the reading priority + * @throws OpenemsException on error + */ + private void addReadTasks(Deque elements, Priority priority) throws OpenemsException { + var length = 0; + var taskElements = new ArrayDeque(); + var element = elements.pollFirst(); + while (element != null) { + if (length + element.length > MAXIMUM_TASK_LENGTH) { + this.modbusProtocol.addTask(// + new FC3ReadRegistersTask(// + taskElements.peekFirst().startAddress, priority, // + taskElements.toArray(new AbstractModbusElement[taskElements.size()]))); + length = 0; + taskElements.clear(); + } + taskElements.add(element); + length += element.length; + element = elements.pollFirst(); + } + this.modbusProtocol.addTask(// + new FC3ReadRegistersTask(// + taskElements.peekFirst().startAddress, priority, // + taskElements.toArray(new AbstractModbusElement[taskElements.size()]))); } /**