Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 701 #776

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Fix issue-701 for S7 driver.
ceos01 committed Jan 28, 2023
commit 47ecbad7604a3fb169c3efacdb5f3355abf1b0bf
Original file line number Diff line number Diff line change
@@ -3912,6 +3912,23 @@ public static PlcValue staticParse(ReadBuffer readBuffer, KnxDatapointType datap
// Simple Field (value)
Float value = /*TODO: migrate me*/ /*TODO: migrate me*/ readBuffer.readFloat("", 32);

return new PlcREAL(value);
} else if (EvaluationHelper.equals(
datapointType, KnxDatapointType.DPT_Value_ApparentPower)) { // REAL

// Reserved Field (Compartmentalized so the "reserved" variable can't leak)
{
short reserved = /*TODO: migrate me*/ /*TODO: migrate me*/
readBuffer.readUnsignedShort("", 8);
if (reserved != (short) 0x00) {
LOGGER.info(
"Expected constant value " + 0x00 + " but got " + reserved + " for reserved field.");
}
}

// Simple Field (value)
Float value = /*TODO: migrate me*/ /*TODO: migrate me*/ readBuffer.readFloat("", 32);

return new PlcREAL(value);
} else if (EvaluationHelper.equals(
datapointType, KnxDatapointType.DPT_Volume_Flux_Meter)) { // REAL
@@ -10455,6 +10472,16 @@ public static void staticSerialize(
float value = (float) _value.getFloat();
/*TODO: migrate me*/
/*TODO: migrate me*/ writeBuffer.writeFloat("", 32, (value));
} else if (EvaluationHelper.equals(
datapointType, KnxDatapointType.DPT_Value_ApparentPower)) { // REAL
// Reserved Field
/*TODO: migrate me*/
/*TODO: migrate me*/ writeBuffer.writeUnsignedShort(
"", 8, ((Number) (short) 0x00).shortValue());
// Simple Field (value)
float value = (float) _value.getFloat();
/*TODO: migrate me*/
/*TODO: migrate me*/ writeBuffer.writeFloat("", 32, (value));
} else if (EvaluationHelper.equals(
datapointType, KnxDatapointType.DPT_Volume_Flux_Meter)) { // REAL
// Reserved Field
@@ -14655,6 +14682,12 @@ public static int getLengthInBits(PlcValue _value, KnxDatapointType datapointTyp
sizeInBits += 8;
// Simple Field (value)
sizeInBits += 32;
} else if (EvaluationHelper.equals(
datapointType, KnxDatapointType.DPT_Value_ApparentPower)) { // REAL
// Reserved Field
sizeInBits += 8;
// Simple Field (value)
sizeInBits += 32;
} else if (EvaluationHelper.equals(
datapointType, KnxDatapointType.DPT_Volume_Flux_Meter)) { // REAL
// Reserved Field

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -321,7 +321,7 @@ public enum KnxManufacturer {
M_GUANGZHOU_SEAWIN_ELECTRICAL_TECHNOLOGIES_CO___LTD_(
(int) 278, (int) 331, (String) "Guangzhou SeaWin Electrical Technologies Co., Ltd."),
M_ACREL((int) 279, (int) 332, (String) "Acrel"),
M_FRANKE_AQUAROTTER_GMBH((int) 280, (int) 333, (String) "Franke Aquarotter GmbH"),
M_KWC_AQUAROTTER_GMBH((int) 280, (int) 333, (String) "KWC Aquarotter GmbH"),
M_ORION_SYSTEMS((int) 281, (int) 334, (String) "Orion Systems"),
M_SCHRACK_TECHNIK_GMBH((int) 282, (int) 335, (String) "Schrack Technik GmbH"),
M_INSPRID((int) 283, (int) 336, (String) "INSPRID"),
@@ -439,7 +439,7 @@ public enum KnxManufacturer {
M_CODESYS_GMBH((int) 387, (int) 440, (String) "CODESYS GmbH"),
M_MOORGEN_DEUTSCHLAND_GMBH((int) 388, (int) 441, (String) "Moorgen Deutschland GmbH"),
M_CULLMANN_TECH((int) 389, (int) 442, (String) "CULLMANN TECH"),
M_MERCK_WINDOW_TECHNOLOGIES_B_V_((int) 390, (int) 443, (String) "Merck Window Technologies B.V."),
M_EYRISE_B_V((int) 390, (int) 443, (String) "eyrise B.V"),
M_ABEGO((int) 391, (int) 444, (String) "ABEGO"),
M_MYGEKKO((int) 392, (int) 445, (String) "myGEKKO"),
M_ERGO3_SARL((int) 393, (int) 446, (String) "Ergo3 Sarl"),
Original file line number Diff line number Diff line change
@@ -107,7 +107,7 @@ public static S7PayloadBuilder staticParseS7PayloadBuilder(
readCountArrayField(
"items",
new DataReaderComplexDefault<>(
() -> S7VarPayloadDataItem.staticParse(readBuffer), readBuffer),
() -> S7VarPayloadDataItem.staticParse(readBuffer, (boolean) (true)), readBuffer),
CAST(parameter, S7ParameterReadVarResponse.class).getNumItems());

readBuffer.closeContext("S7PayloadReadVarResponse");
Original file line number Diff line number Diff line change
@@ -42,12 +42,19 @@ public class S7VarPayloadDataItem implements Message {
protected final DataTransportSize transportSize;
protected final byte[] data;

// Arguments.
protected final Boolean hasNext;

public S7VarPayloadDataItem(
DataTransportErrorCode returnCode, DataTransportSize transportSize, byte[] data) {
DataTransportErrorCode returnCode,
DataTransportSize transportSize,
byte[] data,
Boolean hasNext) {
super();
this.returnCode = returnCode;
this.transportSize = transportSize;
this.data = data;
this.hasNext = hasNext;
}

public DataTransportErrorCode getReturnCode() {
@@ -102,7 +109,10 @@ public void serialize(WriteBuffer writeBuffer) throws SerializationException {

// Padding Field (padding)
writePaddingField(
"padding", (int) ((COUNT(data)) % (2)), (short) 0x00, writeUnsignedShort(writeBuffer, 8));
"padding",
(int) (((PADCOUNT(data, hasNext)) % (2))),
(short) 0x00,
writeUnsignedShort(writeBuffer, 8));

writeBuffer.popContext("S7VarPayloadDataItem");
}
@@ -132,7 +142,7 @@ public int getLengthInBits() {
}

// Padding Field (padding)
int _timesPadding = (int) ((COUNT(data)) % (2));
int _timesPadding = (int) (((PADCOUNT(data, hasNext)) % (2)));
while (_timesPadding-- > 0) {
lengthInBits += 8;
}
@@ -143,10 +153,25 @@ public int getLengthInBits() {
public static S7VarPayloadDataItem staticParse(ReadBuffer readBuffer, Object... args)
throws ParseException {
PositionAware positionAware = readBuffer;
return staticParse(readBuffer);
if ((args == null) || (args.length != 1)) {
throw new PlcRuntimeException(
"Wrong number of arguments, expected 1, but got " + args.length);
}
Boolean hasNext;
if (args[0] instanceof Boolean) {
hasNext = (Boolean) args[0];
} else if (args[0] instanceof String) {
hasNext = Boolean.valueOf((String) args[0]);
} else {
throw new PlcRuntimeException(
"Argument 0 expected to be of type Boolean or a string which is parseable but was "
+ args[0].getClass().getName());
}
return staticParse(readBuffer, hasNext);
}

public static S7VarPayloadDataItem staticParse(ReadBuffer readBuffer) throws ParseException {
public static S7VarPayloadDataItem staticParse(ReadBuffer readBuffer, Boolean hasNext)
throws ParseException {
readBuffer.pullContext("S7VarPayloadDataItem");
PositionAware positionAware = readBuffer;
int startPos = positionAware.getPos();
@@ -174,12 +199,12 @@ public static S7VarPayloadDataItem staticParse(ReadBuffer readBuffer) throws Par
Math.toIntExact(
((transportSize.getSizeInBits()) ? CEIL((dataLength) / (8.0)) : dataLength)));

readPaddingField(readUnsignedShort(readBuffer, 8), (int) ((COUNT(data)) % (2)));
readPaddingField(readUnsignedShort(readBuffer, 8), (int) (((PADCOUNT(data, hasNext)) % (2))));

readBuffer.closeContext("S7VarPayloadDataItem");
// Create the instance
S7VarPayloadDataItem _s7VarPayloadDataItem;
_s7VarPayloadDataItem = new S7VarPayloadDataItem(returnCode, transportSize, data);
_s7VarPayloadDataItem = new S7VarPayloadDataItem(returnCode, transportSize, data, hasNext);
return _s7VarPayloadDataItem;
}

Original file line number Diff line number Diff line change
@@ -279,12 +279,29 @@ public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
List<S7VarRequestParameterItem> parameterItems = new ArrayList<>(request.getNumberOfTags());
List<S7VarPayloadDataItem> payloadItems = new ArrayList<>(request.getNumberOfTags());
for (String tagName : request.getTagNames()) {

Iterator<String> iter = request.getTagNames().iterator();

String tagName = null;
while(iter.hasNext()) {
tagName = iter.next();
final S7Tag tag = (S7Tag) request.getTag(tagName);
final PlcValue plcValue = request.getPlcValue(tagName);
parameterItems.add(new S7VarRequestParameterItemAddress(encodeS7Address(tag)));
payloadItems.add(serializePlcValue(tag, plcValue));
payloadItems.add(serializePlcValue(tag, plcValue, iter.hasNext()));
}


// for (String tagName : request.getTagNames()) {
// final S7Tag tag = (S7Tag) request.getTag(tagName);
// final PlcValue plcValue = request.getPlcValue(tagName);
// parameterItems.add(new S7VarRequestParameterItemAddress(encodeS7Address(tag)));
// payloadItems.add(serializePlcValue(tag, plcValue));
//
// }



final int tpduId = tpduGenerator.getAndIncrement();
// If we've reached the max value for a 16 bit transaction identifier, reset back to 1
if (tpduGenerator.get() == 0xFFFF) {
@@ -303,7 +320,7 @@ public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
Integer.MAX_VALUE
)
);

// Start a new request-transaction (Is ended in the response-handler)
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(tpktPacket)
@@ -853,7 +870,7 @@ private PlcResponse decodeWriteResponse(S7Message responseMessage, PlcWriteReque
return new DefaultPlcWriteResponse(plcWriteRequest, responses);
}

private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue plcValue) {
private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue plcValue, Boolean hasNext) {
try {
DataTransportSize transportSize = tag.getDataType().getDataTransportSize();
int stringLength = (tag instanceof S7StringTag) ? ((S7StringTag) tag).getStringLength() : 254;
@@ -870,7 +887,7 @@ private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue plcValue) {
}
if (byteBuffer != null) {
byte[] data = byteBuffer.array();
return new S7VarPayloadDataItem(DataTransportErrorCode.OK, transportSize, data);
return new S7VarPayloadDataItem(DataTransportErrorCode.OK, transportSize, data, hasNext);
}
} catch (SerializationException e) {
logger.warn("Error serializing tag item of type: '{}'", tag.getDataType().name(), e);
3 changes: 2 additions & 1 deletion plc4j/drivers/s7/src/test/java/S7IoTest.java
Original file line number Diff line number Diff line change
@@ -340,7 +340,8 @@ void TestS7MessageBytes() throws Exception {
new S7VarPayloadDataItem(
DataTransportErrorCode.OK,
DataTransportSize.BIT,
new byte[]{0x1}
new byte[]{0x1},
false
)
),new S7ParameterReadVarResponse((short) 1)
),
Original file line number Diff line number Diff line change
@@ -121,5 +121,9 @@ public static <T> T CAST(Object obj, Class<T> clazz) {
public static int CEIL(double value) {
return (int) Math.ceil(value);
}

public static int PADCOUNT(Object obj, boolean hasNext) {
return hasNext ? COUNT(obj) : 0;
}

}
Original file line number Diff line number Diff line change
@@ -254,7 +254,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
final byte bitAddress = addressAny.getBitAddress();
switch (addressAny.getTransportSize()) {
case BOOL:
payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BIT, new byte[]{1}));
payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BIT, new byte[]{1}, true));
break;
case INT:
case UINT: {
@@ -264,7 +264,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
byte[] data = new byte[2];
data[1] = (byte) (shortValue & 0xff);
data[0] = (byte) ((shortValue >> 8) & 0xff);
payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, data));
payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, data, true));
break;
}
default: {
@@ -280,7 +280,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
addressAny.getNumberOfElements() : addressAny.getTransportSize().getSizeInBytes() * 8;
final BitSet bitSet = toBitSet(context.getDigitalInputs(), ioNumber, numElements);
final byte[] data = Arrays.copyOf(bitSet.toByteArray(), (numElements + 7) / 8);
payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, data));
payloadItems.add(new S7VarPayloadDataItem(DataTransportErrorCode.OK, DataTransportSize.BYTE_WORD_DWORD, data, true));
break;
}
}
9 changes: 6 additions & 3 deletions protocols/s7/src/main/resources/protocols/s7/s7.mspec
Original file line number Diff line number Diff line change
@@ -223,7 +223,7 @@
[discriminatedType S7Payload (uint 8 messageType, S7Parameter parameter)
[typeSwitch parameter.parameterType, messageType
['0x04','0x03' S7PayloadReadVarResponse
[array S7VarPayloadDataItem items count 'CAST(parameter, "S7ParameterReadVarResponse").numItems']
[array S7VarPayloadDataItem ('true') items count 'CAST(parameter, "S7ParameterReadVarResponse").numItems']
]
['0x05','0x01' S7PayloadWriteVarRequest
[array S7VarPayloadDataItem items count 'COUNT(CAST(parameter, "S7ParameterWriteVarRequest").items)']
@@ -238,12 +238,15 @@
]

// This is actually not quite correct as depending pon the transportSize the length is either defined in bits or bytes.
[type S7VarPayloadDataItem
//@param hasNext In the serialization process, if you have multiple write
// requests the last element does not require padding.
[type S7VarPayloadDataItem(bit 'hasNext')
[simple DataTransportErrorCode returnCode]
[simple DataTransportSize transportSize]
[implicit uint 16 dataLength 'COUNT(data) * ((transportSize == DataTransportSize.BIT) ? 1 : (transportSize.sizeInBits ? 8 : 1))']
[array byte data count 'transportSize.sizeInBits ? CEIL(dataLength / 8.0) : dataLength']
[padding uint 8 pad '0x00' 'COUNT(data) % 2']
//[padding uint 8 pad '0x00' '(COUNT(data) % 2)']
[padding uint 8 pad '0x00' '(PADCOUNT(data, hasNext) % 2)']
]

[type S7VarPayloadStatusItem