use of org.apache.plc4x.java.api.exceptions.PlcRuntimeException in project plc4x by apache.
the class PooledPlcDriverManager method getStatistics.
// TODO: maybe export to jmx // generic poolKey has builtin jmx too
public Map<String, Number> getStatistics() {
HashMap<String, Number> statistics = new HashMap<>();
statistics.put("numActive", keyedObjectPool.getNumActive());
statistics.put("numIdle", keyedObjectPool.getNumIdle());
if (keyedObjectPool instanceof GenericKeyedObjectPool) {
GenericKeyedObjectPool<PoolKey, PlcConnection> genericKeyedObjectPool = (GenericKeyedObjectPool<PoolKey, PlcConnection>) this.keyedObjectPool;
// Thats pretty ugly and we really should't do that...
try {
Map poolMap = (Map) FieldUtils.getField(GenericKeyedObjectPool.class, "poolMap", true).get(this.keyedObjectPool);
statistics.put("pools.count", poolMap.size());
} catch (IllegalAccessException e) {
throw new PlcRuntimeException(e);
}
Map<String, Integer> numActivePerKey = genericKeyedObjectPool.getNumActivePerKey();
for (Map.Entry<String, Integer> entry : numActivePerKey.entrySet()) {
statistics.put(entry.getKey() + ".numActive", entry.getValue());
}
}
return statistics;
}
use of org.apache.plc4x.java.api.exceptions.PlcRuntimeException in project plc4x by apache.
the class LittleEndianEncoder method encodeData.
public static byte[] encodeData(AdsDataType adsDataType, Object... values) throws PlcProtocolException {
if (values.length == 0) {
return new byte[] {};
}
Class<?> valueType = values[0].getClass();
Stream<byte[]> result;
if (valueType == Boolean.class) {
result = encodeBoolean(adsDataType, Arrays.stream(values).map(Boolean.class::cast));
} else if (valueType == Byte.class) {
result = encodeByte(adsDataType, Arrays.stream(values).map(Byte.class::cast));
} else if (valueType == Short.class) {
result = encodeShort(adsDataType, Arrays.stream(values).map(Short.class::cast));
} else if (valueType == Integer.class) {
result = encodeInteger(adsDataType, Arrays.stream(values).map(Integer.class::cast));
} else if (valueType == Long.class) {
result = encodeLong(adsDataType, Arrays.stream(values).map(Long.class::cast));
} else if (valueType == BigInteger.class) {
result = encodeBigInteger(adsDataType, Arrays.stream(values).map(BigInteger.class::cast));
} else if (valueType == LocalTime.class) {
result = encodeLocalTime(adsDataType, Arrays.stream(values).map(LocalTime.class::cast));
} else if (valueType == LocalDate.class) {
result = encodeLocalDate(adsDataType, Arrays.stream(values).map(LocalDate.class::cast));
} else if (valueType == LocalDateTime.class) {
result = encodeLocalDateTime(adsDataType, Arrays.stream(values).map(LocalDateTime.class::cast));
} else if (valueType == Float.class) {
result = encodeFloat(adsDataType, Arrays.stream(values).map(Float.class::cast));
} else if (valueType == Double.class) {
result = encodeDouble(adsDataType, Arrays.stream(values).map(Double.class::cast));
} else if (valueType == String.class) {
result = encodeString(adsDataType, Arrays.stream(values).map(String.class::cast));
} else if (valueType == byte[].class) {
result = encodeByteArray(adsDataType, Arrays.stream(values).map(byte[].class::cast));
} else if (valueType == Byte[].class) {
result = encodeBigByteArray(adsDataType, Arrays.stream(values).map(Byte[].class::cast));
} else {
throw new PlcUnsupportedDataTypeException(valueType);
}
// TODO: maybe we can replace this by a smarter flatmap
try {
return result.collect(ByteArrayOutputStream::new, (bos, byteValue) -> {
try {
bos.write(byteValue);
} catch (IOException e) {
throw new PlcRuntimeException(e);
}
}, (a, b) -> {
}).toByteArray();
} catch (PlcRuntimeException e) {
throw new PlcProtocolException("Error encoding data", e);
}
}
use of org.apache.plc4x.java.api.exceptions.PlcRuntimeException in project plc4x by apache.
the class Payload2SerialProtocol method decode.
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> out) throws Exception {
LOGGER.trace("(-->IN): {}, {}, {}", channelHandlerContext, byteBuf, out);
if (byteBuf.readableBytes() < MagicCookie.NUM_BYTES + TransmitterAddress.NUM_BYTES + ReceiverAddress.NUM_BYTES + FragmentNumber.NUM_BYTES) {
return;
}
MagicCookie magicCookie = MagicCookie.of(byteBuf);
TransmitterAddress transmitterAddress = TransmitterAddress.of(byteBuf);
ReceiverAddress receiverAddress = ReceiverAddress.of(byteBuf);
FragmentNumber fragmentNumber = FragmentNumber.of(byteBuf);
int expectedFrameNumber = fragmentCounter.get() - 1;
if (expectedFrameNumber < 0) {
expectedFrameNumber = 255;
}
if (fragmentNumber.getAsByte() != expectedFrameNumber) {
LOGGER.warn("Unexpected fragment {} received. Expected {}", fragmentNumber, expectedFrameNumber);
}
UserDataLength userDataLength = UserDataLength.of(byteBuf);
UserData userData;
byte userDataLengthAsByte = userDataLength.getAsByte();
if (byteBuf.readableBytes() < userDataLengthAsByte) {
return;
}
if (userDataLengthAsByte > 0) {
byte[] userDataByteArray = new byte[userDataLengthAsByte];
byteBuf.readBytes(userDataByteArray);
userData = UserData.of(userDataByteArray);
} else {
userData = UserData.EMPTY;
}
CRC crc = CRC.of(byteBuf);
// we don't need to retransmit
ScheduledFuture<?> scheduledFuture = currentRetryer.get();
if (scheduledFuture != null) {
scheduledFuture.cancel(false);
}
Runnable postAction = null;
switch(magicCookie.getAsInt()) {
case AmsSerialFrame.ID:
AmsSerialFrame amsSerialFrame = AmsSerialFrame.of(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, userData, crc);
LOGGER.debug("Ams Serial Frame received {}", amsSerialFrame);
postAction = () -> {
// TODO: check if this is the right way to ack a package.
ChannelFuture channelFuture = channelHandlerContext.writeAndFlush(AmsSerialAcknowledgeFrame.of(transmitterAddress, receiverAddress, fragmentNumber).getByteBuf());
// waiting for the ack-frame to be transmitted before we forward the package
try {
channelFuture.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new PlcRuntimeException(e);
}
out.add(userData.getByteBuf());
};
break;
case AmsSerialAcknowledgeFrame.ID:
AmsSerialAcknowledgeFrame amsSerialAcknowledgeFrame = AmsSerialAcknowledgeFrame.of(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, crc);
LOGGER.debug("Ams Serial ACK Frame received {}", amsSerialAcknowledgeFrame);
ReferenceCountUtil.release(byteBuf);
break;
case AmsSerialResetFrame.ID:
// TODO: how to react to a reset
AmsSerialResetFrame amsSerialResetFrame = AmsSerialResetFrame.of(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, crc);
LOGGER.debug("Ams Serial Reset Frame received {}", amsSerialResetFrame);
ReferenceCountUtil.release(byteBuf);
break;
default:
throw new PlcProtocolException("Unknown type: " + magicCookie);
}
CRC calculatedCrc = CRC.of(DigestUtil.calculateCrc16(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, userData));
if (!crc.equals(calculatedCrc)) {
throw new PlcProtocolException("CRC checksum wrong. Got " + crc + " expected " + calculatedCrc);
}
if (postAction != null) {
postAction.run();
}
if (byteBuf.readableBytes() > 0) {
throw new IllegalStateException("Unread bytes left: " + byteBuf.readableBytes());
}
}
use of org.apache.plc4x.java.api.exceptions.PlcRuntimeException in project plc4x by apache.
the class BacNetIpProtocolLogic method setConfiguration.
@Override
public void setConfiguration(BacNetIpConfiguration configuration) {
if (configuration.getEdeFilePath() != null) {
File edeFile = new File(configuration.getEdeFilePath());
if (!edeFile.exists() || !edeFile.isFile()) {
throw new PlcRuntimeException(String.format("File specified with 'ede-file-path' does not exist or is not a file: '%s'", configuration.getEdeFilePath()));
}
edeModel = new EdeParser().parseFile(edeFile);
} else if (configuration.getEdeDirectoryPath() != null) {
File edeDirectory = new File(configuration.getEdeDirectoryPath());
if (!edeDirectory.exists() || !edeDirectory.isDirectory()) {
throw new PlcRuntimeException(String.format("File specified with 'ede-directory-path' does not exist or is not a directory: '%s'", configuration.getEdeDirectoryPath()));
}
edeModel = new EdeParser().parseDirectory(edeDirectory);
}
}
use of org.apache.plc4x.java.api.exceptions.PlcRuntimeException in project plc4x by apache.
the class AdsProtocolLogic method multiWrite.
protected CompletableFuture<PlcWriteResponse> multiWrite(PlcWriteRequest writeRequest, List<DirectAdsField> directAdsFields) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
// Calculate the size of all fields together.
// Calculate the expected size of the response data.
int expectedRequestDataSize = directAdsFields.stream().mapToInt(field -> field.getAdsDataType().getNumBytes() * field.getNumberOfElements()).sum();
byte[] writeBuffer = new byte[expectedRequestDataSize];
int pos = 0;
for (String fieldName : writeRequest.getFieldNames()) {
final AdsField field = (AdsField) writeRequest.getField(fieldName);
final PlcValue plcValue = writeRequest.getPlcValue(fieldName);
final int stringLength;
if (field.getAdsDataType() == AdsDataType.STRING) {
stringLength = plcValue.getString().length() + 1;
} else {
if (field.getAdsDataType() == AdsDataType.WSTRING) {
stringLength = (plcValue.getString().length() + 1) * 2;
} else {
stringLength = 0;
}
}
try {
WriteBufferByteBased itemWriteBuffer = new WriteBufferByteBased(DataItem.getLengthInBytes(plcValue, field.getAdsDataType().getDataFormatName(), stringLength));
DataItem.staticSerialize(itemWriteBuffer, plcValue, field.getAdsDataType().getDataFormatName(), stringLength, ByteOrder.LITTLE_ENDIAN);
int numBytes = itemWriteBuffer.getPos();
System.arraycopy(itemWriteBuffer.getData(), 0, writeBuffer, pos, numBytes);
pos += numBytes;
} catch (Exception e) {
throw new PlcRuntimeException("Error serializing data", e);
}
}
// With multi-requests, the index-group is fixed and the index offset indicates the number of elements.
AdsData adsData = new AdsReadWriteRequest(ReservedIndexGroups.ADSIGRP_MULTIPLE_WRITE.getValue(), directAdsFields.size(), (long) directAdsFields.size() * 4, directAdsFields.stream().map(directAdsField -> new AdsMultiRequestItemWrite(directAdsField.getIndexGroup(), directAdsField.getIndexOffset(), ((long) directAdsField.getAdsDataType().getNumBytes() * directAdsField.getNumberOfElements()))).collect(Collectors.toList()), writeBuffer);
AmsPacket amsPacket = new AmsPacket(configuration.getTargetAmsNetId(), configuration.getTargetAmsPort(), configuration.getSourceAmsNetId(), configuration.getSourceAmsPort(), CommandId.ADS_READ_WRITE, DEFAULT_COMMAND_STATE, 0, getInvokeId(), adsData);
AmsTCPPacket amsTCPPacket = new AmsTCPPacket(amsPacket);
// Start a new request-transaction (Is ended in the response-handler)
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(amsTCPPacket).expectResponse(AmsTCPPacket.class, Duration.ofMillis(configuration.getTimeoutRequest())).onTimeout(future::completeExceptionally).onError((p, e) -> future.completeExceptionally(e)).check(responseAmsPacket -> responseAmsPacket.getUserdata().getInvokeId() == amsPacket.getInvokeId()).unwrap(response -> (AdsReadWriteResponse) response.getUserdata().getData()).handle(responseAdsData -> {
if (responseAdsData.getResult() == ReturnCode.OK) {
final PlcWriteResponse plcWriteResponse = convertToPlc4xWriteResponse(writeRequest, responseAdsData);
// Convert the response from the PLC into a PLC4X Response ...
future.complete(plcWriteResponse);
} else {
// TODO: Implement this correctly.
future.completeExceptionally(new PlcException("Error"));
}
// Finish the request-transaction.
transaction.endRequest();
}));
return future;
}
Aggregations