use of org.apache.plc4x.java.api.exceptions.PlcProtocolException in project plc4x by apache.
the class S7ProtocolLogic method decodeReadResponse.
private PlcResponse decodeReadResponse(S7Message responseMessage, PlcReadRequest plcReadRequest) throws PlcProtocolException {
Map<String, ResponseItem<PlcValue>> values = new HashMap<>();
short errorClass;
short errorCode;
if (responseMessage instanceof S7MessageResponseData) {
S7MessageResponseData messageResponseData = (S7MessageResponseData) responseMessage;
errorClass = messageResponseData.getErrorClass();
errorCode = messageResponseData.getErrorCode();
} else if (responseMessage instanceof S7MessageResponse) {
S7MessageResponse messageResponse = (S7MessageResponse) responseMessage;
errorClass = messageResponse.getErrorClass();
errorCode = messageResponse.getErrorCode();
} else {
throw new PlcProtocolException("Unsupported message type " + responseMessage.getClass().getName());
}
// If the result contains any form of non-null error code, handle this instead.
if ((errorClass != 0) || (errorCode != 0)) {
// This is usually the case if PUT/GET wasn't enabled on the PLC
if ((errorClass == 129) && (errorCode == 4)) {
logger.warn("Got an error response from the PLC. This particular response code usually indicates " + "that PUT/GET is not enabled on the PLC.");
for (String fieldName : plcReadRequest.getFieldNames()) {
ResponseItem<PlcValue> result = new ResponseItem<>(PlcResponseCode.ACCESS_DENIED, new PlcNull());
values.put(fieldName, result);
}
return new DefaultPlcReadResponse(plcReadRequest, values);
} else {
logger.warn("Got an unknown error response from the PLC. Error Class: {}, Error Code {}. " + "We probably need to implement explicit handling for this, so please file a bug-report " + "on https://issues.apache.org/jira/projects/PLC4X and ideally attach a WireShark dump " + "containing a capture of the communication.", errorClass, errorCode);
for (String fieldName : plcReadRequest.getFieldNames()) {
ResponseItem<PlcValue> result = new ResponseItem<>(PlcResponseCode.INTERNAL_ERROR, new PlcNull());
values.put(fieldName, result);
}
return new DefaultPlcReadResponse(plcReadRequest, values);
}
}
// In all other cases all went well.
S7PayloadReadVarResponse payload = (S7PayloadReadVarResponse) responseMessage.getPayload();
// items from the request as this information is not returned by the PLC.
if (plcReadRequest.getNumberOfFields() != payload.getItems().size()) {
throw new PlcProtocolException("The number of requested items doesn't match the number of returned items");
}
List<S7VarPayloadDataItem> payloadItems = payload.getItems();
int index = 0;
for (String fieldName : plcReadRequest.getFieldNames()) {
S7Field field = (S7Field) plcReadRequest.getField(fieldName);
S7VarPayloadDataItem payloadItem = payloadItems.get(index);
PlcResponseCode responseCode = decodeResponseCode(payloadItem.getReturnCode());
PlcValue plcValue = null;
ByteBuf data = Unpooled.wrappedBuffer(payloadItem.getData());
if (responseCode == PlcResponseCode.OK) {
try {
plcValue = parsePlcValue(field, data);
} catch (Exception e) {
throw new PlcProtocolException("Error decoding PlcValue", e);
}
}
ResponseItem<PlcValue> result = new ResponseItem<>(responseCode, plcValue);
values.put(fieldName, result);
index++;
}
return new DefaultPlcReadResponse(plcReadRequest, values);
}
use of org.apache.plc4x.java.api.exceptions.PlcProtocolException in project plc4x by apache.
the class S7ProtocolLogic method subscribe.
@Override
public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionRequest subscriptionRequest) {
CompletableFuture<PlcSubscriptionResponse> future = new CompletableFuture<>();
DefaultPlcSubscriptionRequest request = (DefaultPlcSubscriptionRequest) subscriptionRequest;
List<S7ParameterUserDataItem> parameterItems = new ArrayList<>(request.getNumberOfFields());
List<S7PayloadUserDataItem> payloadItems = new ArrayList<>(request.getNumberOfFields());
for (String fieldName : request.getFieldNames()) {
final DefaultPlcSubscriptionField sf = (DefaultPlcSubscriptionField) request.getField(fieldName);
final S7SubscriptionField field = (S7SubscriptionField) sf.getPlcField();
switch(field.getFieldType()) {
case EVENT_SUBSCRIPTION:
encodeEventSubscriptionRequest(request, parameterItems, payloadItems);
break;
case EVENT_UNSUBSCRIPTION:
// encodeEventUnSubscriptionRequest(msg, out);
break;
case ALARM_ACK:
// encodeAlarmAckRequest(msg, out);
break;
case ALARM_QUERY:
// encodeAlarmQueryRequest(msg, out);
break;
case CYCLIC_SUBSCRIPTION:
// encodeCycledSubscriptionRequest(msg, out);
break;
case CYCLIC_UNSUBSCRIPTION:
// encodeCycledUnSubscriptionRequest(msg, out);
break;
default:
}
// final PlcValue plcValue = request.getPlcValue(fieldName);
// parameterItems.add(new S7VarRequestParameterItemAddress(encodeS7Address(field)));
// payloadItems.add(serializePlcValue(field, 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) {
tpduGenerator.set(1);
}
TPKTPacket tpktPacket = new TPKTPacket(new COTPPacketData(null, new S7MessageUserData(tpduId, new S7ParameterUserData(parameterItems), new S7PayloadUserData(payloadItems, null)), true, (short) tpduId, null));
// Start a new request-transaction (Is ended in the response-handler)
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(tpktPacket).onTimeout(new TransactionErrorCallback<>(future, transaction)).onError(new TransactionErrorCallback<>(future, transaction)).expectResponse(TPKTPacket.class, REQUEST_TIMEOUT).check(p -> p.getPayload() instanceof COTPPacketData).unwrap(p -> ((COTPPacketData) p.getPayload())).unwrap(COTPPacket::getPayload).check(p -> p.getTpduReference() == tpduId).handle(p -> {
try {
future.complete(decodeEventSubscriptionRequest(p, subscriptionRequest));
} catch (PlcProtocolException e) {
logger.warn("Error sending 'write' message: '{}'", e.getMessage(), e);
}
// Finish the request-transaction.
transaction.endRequest();
}));
return future;
}
use of org.apache.plc4x.java.api.exceptions.PlcProtocolException in project plc4x by apache.
the class S7ProtocolLogic method decodeWriteResponse.
private PlcResponse decodeWriteResponse(S7Message responseMessage, PlcWriteRequest plcWriteRequest) throws PlcProtocolException {
Map<String, PlcResponseCode> responses = new HashMap<>();
short errorClass;
short errorCode;
if (responseMessage instanceof S7MessageResponseData) {
S7MessageResponseData messageResponseData = (S7MessageResponseData) responseMessage;
errorClass = messageResponseData.getErrorClass();
errorCode = messageResponseData.getErrorCode();
} else if (responseMessage instanceof S7MessageResponse) {
S7MessageResponse messageResponse = (S7MessageResponse) responseMessage;
errorClass = messageResponse.getErrorClass();
errorCode = messageResponse.getErrorCode();
} else {
throw new PlcProtocolException("Unsupported message type " + responseMessage.getClass().getName());
}
// If the result contains any form of non-null error code, handle this instead.
if ((errorClass != 0) || (errorCode != 0)) {
// This is usually the case if PUT/GET wasn't enabled on the PLC
if ((errorClass == 129) && (errorCode == 4)) {
logger.warn("Got an error response from the PLC. This particular response code usually indicates " + "that PUT/GET is not enabled on the PLC.");
for (String fieldName : plcWriteRequest.getFieldNames()) {
responses.put(fieldName, PlcResponseCode.ACCESS_DENIED);
}
return new DefaultPlcWriteResponse(plcWriteRequest, responses);
} else {
logger.warn("Got an unknown error response from the PLC. Error Class: {}, Error Code {}. " + "We probably need to implement explicit handling for this, so please file a bug-report " + "on https://issues.apache.org/jira/projects/PLC4X and ideally attach a WireShark dump " + "containing a capture of the communication.", errorClass, errorCode);
for (String fieldName : plcWriteRequest.getFieldNames()) {
responses.put(fieldName, PlcResponseCode.INTERNAL_ERROR);
}
return new DefaultPlcWriteResponse(plcWriteRequest, responses);
}
}
// In all other cases all went well.
S7PayloadWriteVarResponse payload = (S7PayloadWriteVarResponse) responseMessage.getPayload();
// items from the request as this information is not returned by the PLC.
if (plcWriteRequest.getNumberOfFields() != payload.getItems().size()) {
throw new PlcProtocolException("The number of requested items doesn't match the number of returned items");
}
List<S7VarPayloadStatusItem> payloadItems = payload.getItems();
int index = 0;
for (String fieldName : plcWriteRequest.getFieldNames()) {
S7VarPayloadStatusItem payloadItem = payloadItems.get(index);
PlcResponseCode responseCode = decodeResponseCode(payloadItem.getReturnCode());
responses.put(fieldName, responseCode);
index++;
}
return new DefaultPlcWriteResponse(plcWriteRequest, responses);
}
use of org.apache.plc4x.java.api.exceptions.PlcProtocolException in project plc4x by apache.
the class S7ProtocolLogic method write.
@Override
public CompletableFuture<PlcWriteResponse> write(PlcWriteRequest writeRequest) {
CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
DefaultPlcWriteRequest request = (DefaultPlcWriteRequest) writeRequest;
List<S7VarRequestParameterItem> parameterItems = new ArrayList<>(request.getNumberOfFields());
List<S7VarPayloadDataItem> payloadItems = new ArrayList<>(request.getNumberOfFields());
for (String fieldName : request.getFieldNames()) {
final S7Field field = (S7Field) request.getField(fieldName);
final PlcValue plcValue = request.getPlcValue(fieldName);
parameterItems.add(new S7VarRequestParameterItemAddress(encodeS7Address(field)));
payloadItems.add(serializePlcValue(field, 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) {
tpduGenerator.set(1);
}
TPKTPacket tpktPacket = new TPKTPacket(new COTPPacketData(null, new S7MessageRequest(tpduId, new S7ParameterWriteVarRequest(parameterItems), new S7PayloadWriteVarRequest(payloadItems, null)), true, (short) tpduId, Integer.MAX_VALUE));
// Start a new request-transaction (Is ended in the response-handler)
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(tpktPacket).onTimeout(new TransactionErrorCallback<>(future, transaction)).onError(new TransactionErrorCallback<>(future, transaction)).expectResponse(TPKTPacket.class, REQUEST_TIMEOUT).check(p -> p.getPayload() instanceof COTPPacketData).unwrap(p -> ((COTPPacketData) p.getPayload())).unwrap(COTPPacket::getPayload).check(p -> p.getTpduReference() == tpduId).handle(p -> {
try {
future.complete(((PlcWriteResponse) decodeWriteResponse(p, writeRequest)));
} catch (PlcProtocolException e) {
logger.warn("Error sending 'write' message: '{}'", e.getMessage(), e);
}
// Finish the request-transaction.
transaction.endRequest();
}));
return future;
}
use of org.apache.plc4x.java.api.exceptions.PlcProtocolException in project plc4x by apache.
the class Df1Protocol method decode.
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
DF1Symbol resp;
// do {
in.markReaderIndex();
short size = 0x00;
// Yes, it's a little complicated, but we need to find out if we've got enough data.
if (in.readableBytes() > 1) {
if (in.getUnsignedByte(0) != (short) 0x10) {
logger.warn("Expecting DF1 magic number: {}", 0x10);
if (logger.isDebugEnabled()) {
logger.debug("Got Data: {}", ByteBufUtil.hexDump(in));
}
exceptionCaught(ctx, new PlcProtocolException(String.format("Expecting DF1 magic number: %02X", 0x10)));
return;
}
short symbolType = in.getUnsignedByte(1);
switch(symbolType) {
case (short) 0x02:
{
if (in.readableBytes() < 5) {
return;
}
short commandType = in.getUnsignedByte(4);
switch(commandType) {
case (short) 0x01:
{
if (in.readableBytes() < 11) {
return;
}
break;
}
case (short) 0x41:
{
// TODO: Let's just assume all is good for now ...
break;
}
}
break;
}
case (short) 0x03:
{
if (in.readableBytes() < 4) {
return;
}
break;
}
}
}
// Parse the message received from the DF1 device
byte[] data = new byte[in.readableBytes()];
in.readBytes(data);
ReadBuffer readBuffer = new ReadBufferByteBased(data);
resp = DF1Symbol.staticParse(readBuffer);
// } while (readWasSucessfull);
// // TODO if unableto read
// in.resetReaderIndex();
// Add the received message to the output
out.add(resp);
}
Aggregations