Search in sources :

Example 1 with PlcProtocolException

use of org.apache.plc4x.java.api.exceptions.PlcProtocolException 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());
    }
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) AmsSerialFrame(org.apache.plc4x.java.ads.api.serial.AmsSerialFrame) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) AmsSerialResetFrame(org.apache.plc4x.java.ads.api.serial.AmsSerialResetFrame) PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) AmsSerialAcknowledgeFrame(org.apache.plc4x.java.ads.api.serial.AmsSerialAcknowledgeFrame)

Example 2 with PlcProtocolException

use of org.apache.plc4x.java.api.exceptions.PlcProtocolException in project plc4x by apache.

the class Plc4x2AdsProtocol method encodeWriteRequest.

private void encodeWriteRequest(PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> msg, List<Object> out) throws PlcException {
    InternalPlcWriteRequest writeRequest = (InternalPlcWriteRequest) msg.getRequest();
    if (writeRequest.getFields().size() != 1) {
        throw new PlcProtocolException("Only one item supported");
    }
    PlcField field = writeRequest.getFields().get(0);
    if (field instanceof SymbolicAdsField) {
        DirectAdsField mappedField = fieldMapping.get(field);
        LOGGER.debug("Replacing {} with {}", field, mappedField);
        field = mappedField;
    }
    if (!(field instanceof DirectAdsField)) {
        throw new PlcProtocolException("PlcField not of type DirectAdsField: " + field.getClass());
    }
    DirectAdsField directAdsField = (DirectAdsField) field;
    Invoke invokeId = Invoke.of(correlationBuilder.incrementAndGet());
    IndexGroup indexGroup = IndexGroup.of(directAdsField.getIndexGroup());
    IndexOffset indexOffset = IndexOffset.of(directAdsField.getIndexOffset());
    Object[] plcValues;
    PlcValue plcValue = writeRequest.getPlcValues().get(0);
    if (plcValue instanceof PlcList) {
        plcValues = ((PlcList) plcValue).getList().toArray(new Object[0]);
    } else {
        plcValues = new Object[] { plcValue.getObject() };
    }
    byte[] bytes = encodeData(directAdsField.getAdsDataType(), plcValues);
    int bytesToBeWritten = bytes.length;
    int maxTheoreticalSize = directAdsField.getAdsDataType().getTargetByteSize() * directAdsField.getNumberOfElements();
    if (bytesToBeWritten > maxTheoreticalSize) {
        LOGGER.debug("Requested AdsDatatype {} is exceeded by number of bytes {}. Limit {}.", directAdsField.getAdsDataType(), bytesToBeWritten, maxTheoreticalSize);
        throw new PlcProtocolPayloadTooBigException("ADS", maxTheoreticalSize, bytesToBeWritten, plcValues);
    }
    Data data = Data.of(bytes);
    AmsPacket amsPacket = AdsWriteRequest.of(targetAmsNetId, targetAmsPort, sourceAmsNetId, sourceAmsPort, invokeId, indexGroup, indexOffset, data);
    LOGGER.debug("encoded write request {}", amsPacket);
    out.add(amsPacket);
    requests.put(invokeId.getAsLong(), msg);
}
Also used : PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) SymbolicAdsField(org.apache.plc4x.java.ads.model.SymbolicAdsField) PlcField(org.apache.plc4x.java.api.model.PlcField) LittleEndianEncoder.encodeData(org.apache.plc4x.java.ads.protocol.util.LittleEndianEncoder.encodeData) Invoke(org.apache.plc4x.java.ads.api.generic.types.Invoke) PlcList(org.apache.plc4x.java.api.value.PlcList) PlcValue(org.apache.plc4x.java.api.value.PlcValue) DirectAdsField(org.apache.plc4x.java.ads.model.DirectAdsField) PlcProtocolPayloadTooBigException(org.apache.plc4x.java.api.exceptions.PlcProtocolPayloadTooBigException) AmsPacket(org.apache.plc4x.java.ads.api.generic.AmsPacket)

Example 3 with PlcProtocolException

use of org.apache.plc4x.java.api.exceptions.PlcProtocolException in project plc4x by apache.

the class Plc4x2AdsProtocol method encodeProprietaryRequest.

private void encodeProprietaryRequest(PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> msg, List<Object> out) throws PlcProtocolException {
    PlcProprietaryRequest plcProprietaryRequest = (PlcProprietaryRequest) msg.getRequest();
    if (!(plcProprietaryRequest.getProprietaryRequest() instanceof AmsPacket)) {
        throw new PlcProtocolException("Unsupported proprietary type for this driver " + plcProprietaryRequest.getProprietaryRequest().getClass());
    }
    AmsPacket amsPacket = (AmsPacket) plcProprietaryRequest.getProprietaryRequest();
    LOGGER.debug("encoded proprietary request {}", amsPacket);
    out.add(amsPacket);
    requests.put(amsPacket.getAmsHeader().getInvokeId().getAsLong(), msg);
}
Also used : PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) AmsPacket(org.apache.plc4x.java.ads.api.generic.AmsPacket)

Example 4 with PlcProtocolException

use of org.apache.plc4x.java.api.exceptions.PlcProtocolException in project plc4x by apache.

the class Plc4x2AdsProtocol method decode.

@Override
protected void decode(ChannelHandlerContext channelHandlerContext, AmsPacket amsPacket, List<Object> out) throws Exception {
    LOGGER.trace("(-->IN): {}, {}, {}", channelHandlerContext, amsPacket, out);
    if (amsPacket instanceof AdsDeviceNotificationRequest) {
        LOGGER.debug("Received notification {}", amsPacket);
        handleAdsDeviceNotificationRequest((AdsDeviceNotificationRequest) amsPacket);
        return;
    }
    PlcRequestContainer<InternalPlcRequest, InternalPlcResponse> plcRequestContainer = requests.remove(amsPacket.getAmsHeader().getInvokeId().getAsLong());
    if (plcRequestContainer == null) {
        LOGGER.info("Unmapped packet received {}", amsPacket);
        return;
    }
    PlcRequest request = plcRequestContainer.getRequest();
    final InternalPlcResponse response;
    // Handle the response to a read request.
    if (request instanceof PlcReadRequest) {
        if (amsPacket instanceof AdsReadResponse) {
            response = decodeReadResponse((AdsReadResponse) amsPacket, plcRequestContainer);
        } else {
            throw new PlcProtocolException("Wrong type correlated " + amsPacket);
        }
    } else if (request instanceof PlcWriteRequest) {
        if (amsPacket instanceof AdsWriteResponse) {
            response = decodeWriteResponse((AdsWriteResponse) amsPacket, plcRequestContainer);
        } else {
            throw new PlcProtocolException("Wrong type correlated " + amsPacket);
        }
    } else if (request instanceof PlcProprietaryRequest) {
        response = decodeProprietaryResponse(amsPacket, plcRequestContainer);
    } else {
        response = null;
    }
    LOGGER.debug("Plc4x response {}", response);
    // Confirm the response being handled.
    if (response != null) {
        plcRequestContainer.getResponseFuture().complete(response);
    }
}
Also used : PlcWriteRequest(org.apache.plc4x.java.api.messages.PlcWriteRequest) PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) PlcRequest(org.apache.plc4x.java.api.messages.PlcRequest) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest)

Example 5 with PlcProtocolException

use of org.apache.plc4x.java.api.exceptions.PlcProtocolException 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);
    }
}
Also used : Arrays(java.util.Arrays) ByteArrayOutputStream(java.io.ByteArrayOutputStream) PlcUnsupportedDataTypeException(org.apache.plc4x.java.api.exceptions.PlcUnsupportedDataTypeException) PlcProtocolPayloadTooBigException(org.apache.plc4x.java.api.exceptions.PlcProtocolPayloadTooBigException) ArrayUtils(org.apache.commons.lang3.ArrayUtils) IOException(java.io.IOException) java.time(java.time) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) ChronoUnit(java.time.temporal.ChronoUnit) Stream(java.util.stream.Stream) Charset(java.nio.charset.Charset) BigInteger(java.math.BigInteger) AdsDataType(org.apache.plc4x.java.ads.model.AdsDataType) PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) PlcProtocolException(org.apache.plc4x.java.api.exceptions.PlcProtocolException) IOException(java.io.IOException) BigInteger(java.math.BigInteger) PlcUnsupportedDataTypeException(org.apache.plc4x.java.api.exceptions.PlcUnsupportedDataTypeException) BigInteger(java.math.BigInteger)

Aggregations

PlcProtocolException (org.apache.plc4x.java.api.exceptions.PlcProtocolException)15 PlcReadRequest (org.apache.plc4x.java.api.messages.PlcReadRequest)7 PlcRuntimeException (org.apache.plc4x.java.api.exceptions.PlcRuntimeException)5 PlcField (org.apache.plc4x.java.api.model.PlcField)5 PlcRequest (org.apache.plc4x.java.api.messages.PlcRequest)4 PlcWriteRequest (org.apache.plc4x.java.api.messages.PlcWriteRequest)4 PlcResponseCode (org.apache.plc4x.java.api.types.PlcResponseCode)4 PlcValue (org.apache.plc4x.java.api.value.PlcValue)4 ResponseItem (org.apache.plc4x.java.spi.messages.utils.ResponseItem)4 ByteBuf (io.netty.buffer.ByteBuf)3 TimeoutException (java.util.concurrent.TimeoutException)3 PlcResponse (org.apache.plc4x.java.api.messages.PlcResponse)3 S7Field (org.apache.plc4x.java.s7.readwrite.field.S7Field)3 S7SubscriptionField (org.apache.plc4x.java.s7.readwrite.field.S7SubscriptionField)3 DefaultPlcReadResponse (org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse)3 DefaultPlcSubscriptionResponse (org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionResponse)3 DefaultPlcWriteResponse (org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse)3 DefaultPlcSubscriptionField (org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField)3 PlcNull (org.apache.plc4x.java.spi.values.PlcNull)3 Unpooled (io.netty.buffer.Unpooled)2