Skip to content

Commit

Permalink
Modbus SunSpec: split modbus tasks with more than 126 registers (#2336)
Browse files Browse the repository at this point in the history
This PR solves issue #2311. Similar to the Edge2Edge-component, if a modbus task is longer than the limit of j2mod (= 126), it is split.
  • Loading branch information
tsicking authored Sep 6, 2023
1 parent 7a2c6ba commit ac7ddc8
Showing 1 changed file with 41 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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<ModbusElement> 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);
Expand Down Expand Up @@ -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<ModbusElement> elements, Priority priority) throws OpenemsException {
var length = 0;
var taskElements = new ArrayDeque<ModbusElement>();
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()])));
}

/**
Expand Down

0 comments on commit ac7ddc8

Please sign in to comment.