This is an automated email from the ASF dual-hosted git repository. sruehl pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
commit d7159aa447e85c50440a1ceb36dfd30181a07d08 Author: Sebastian Rühl <sru...@apache.org> AuthorDate: Thu Jul 26 16:59:13 2018 +0200 added PlcNotImplementedException to mark not yet implemented code parts. --- .../api/exceptions/PlcNotImplementedException.java | 28 ++++ .../java/ads/connection/AdsTcpPlcConnection.java | 175 +++++++++++---------- .../java/modbus/netty/Plc4XModbusProtocol.java | 7 +- .../plc4x/java/s7/netty/Plc4XS7Protocol.java | 7 +- .../plc4x/java/s7/netty/util/S7TypeDecoder.java | 2 +- .../plc4x/java/s7/netty/util/S7TypeEncoder.java | 9 +- 6 files changed, 132 insertions(+), 96 deletions(-) diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/exceptions/PlcNotImplementedException.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/exceptions/PlcNotImplementedException.java new file mode 100644 index 0000000..04e2fe3 --- /dev/null +++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/exceptions/PlcNotImplementedException.java @@ -0,0 +1,28 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.plc4x.java.api.exceptions; + +/** + * indicates that a functionality is not implemented yet. + */ +public class PlcNotImplementedException extends PlcRuntimeException { + public PlcNotImplementedException(String message) { + super(message); + } +} diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java index 124d8d6..e4458df 100644 --- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java +++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsTcpPlcConnection.java @@ -35,6 +35,7 @@ import org.apache.plc4x.java.ads.protocol.Payload2TcpProtocol; import org.apache.plc4x.java.ads.protocol.Plc4x2AdsProtocol; import org.apache.plc4x.java.ads.protocol.util.LittleEndianDecoder; import org.apache.plc4x.java.api.connection.PlcSubscriber; +import org.apache.plc4x.java.api.exceptions.PlcNotImplementedException; import org.apache.plc4x.java.api.exceptions.PlcProtocolException; import org.apache.plc4x.java.api.exceptions.PlcRuntimeException; import org.apache.plc4x.java.api.messages.*; @@ -51,7 +52,10 @@ import org.slf4j.LoggerFactory; import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.*; +import java.util.Calendar; +import java.util.Collections; +import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; @@ -133,92 +137,93 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionRequest subscriptionRequest) { // TODO: Make this multi-value CompletableFuture<PlcSubscriptionResponse> future = new CompletableFuture<>(); - if(subscriptionRequest.getNumberOfItems() == 1) { - SubscriptionRequestItem<?> subscriptionRequestItem = subscriptionRequest.getRequestItem().orElse(null); - - Objects.requireNonNull(subscriptionRequestItem); - Objects.requireNonNull(subscriptionRequestItem.getConsumer()); - Objects.requireNonNull(subscriptionRequestItem.getAddress()); - Objects.requireNonNull(subscriptionRequestItem.getDatatype()); - - Address address = subscriptionRequestItem.getAddress(); - Class<?> datatype = subscriptionRequestItem.getDatatype(); - - IndexGroup indexGroup; - IndexOffset indexOffset; - // If this is a symbolic address, it has to be resolved first. - // TODO: This is blocking, should be changed to be async. - if (address instanceof SymbolicAdsAddress) { - mapAddress((SymbolicAdsAddress) address); - AdsAddress adsAddress = addressMapping.get(address); - if (adsAddress == null) { - throw new PlcRuntimeException("Unresolvable address" + address); - } - indexGroup = IndexGroup.of(adsAddress.getIndexGroup()); - indexOffset = IndexOffset.of(adsAddress.getIndexOffset()); - } - // If it's no symbolic address, we can continue immediately - // without having to do any resolving. - else if (address instanceof AdsAddress) { - AdsAddress adsAddress = (AdsAddress) address; - indexGroup = IndexGroup.of(adsAddress.getIndexGroup()); - indexOffset = IndexOffset.of(adsAddress.getIndexOffset()); - } else { - throw new IllegalArgumentException("Unsupported address type " + address.getClass()); - } + if (subscriptionRequest.getNumberOfItems() != 1) { + throw new PlcNotImplementedException("Multirequest on subscribe not implemented yet"); + } + + SubscriptionRequestItem<?> subscriptionRequestItem = subscriptionRequest.getRequestItem().orElseThrow(NullPointerException::new); - // Prepare the subscription request itself. - AdsAddDeviceNotificationRequest adsAddDeviceNotificationRequest = AdsAddDeviceNotificationRequest.of( - targetAmsNetId, - targetAmsPort, - sourceAmsNetId, - sourceAmsPort, - Invoke.NONE, - indexGroup, - indexOffset, - LittleEndianDecoder.getLengthFor(datatype, 1), - TransmissionMode.DefinedValues.ADSTRANS_SERVERCYCLE, - MaxDelay.of(0), - CycleTime.of(4000000) - ); - - // Send the request to the plc and wait for a response - // TODO: This is blocking, should be changed to be async. - CompletableFuture<PlcProprietaryResponse<AdsAddDeviceNotificationResponse>> addDeviceFuture = new CompletableFuture<>(); - channel.writeAndFlush(new PlcRequestContainer<>(new PlcProprietaryRequest<>(adsAddDeviceNotificationRequest), addDeviceFuture)); - PlcProprietaryResponse<AdsAddDeviceNotificationResponse> addDeviceResponse = getFromFuture(addDeviceFuture, ADD_DEVICE_TIMEOUT); - AdsAddDeviceNotificationResponse response = addDeviceResponse.getResponse(); - - // Abort if we got anything but a successful response. - if (response.getResult().toAdsReturnCode() != AdsReturnCode.ADS_CODE_0) { - throw new PlcRuntimeException("Error code received " + response.getResult()); + Objects.requireNonNull(subscriptionRequestItem.getConsumer()); + Objects.requireNonNull(subscriptionRequestItem.getAddress()); + Objects.requireNonNull(subscriptionRequestItem.getDatatype()); + + Address address = subscriptionRequestItem.getAddress(); + Class<?> datatype = subscriptionRequestItem.getDatatype(); + + IndexGroup indexGroup; + IndexOffset indexOffset; + // If this is a symbolic address, it has to be resolved first. + // TODO: This is blocking, should be changed to be async. + if (address instanceof SymbolicAdsAddress) { + mapAddress((SymbolicAdsAddress) address); + AdsAddress adsAddress = addressMapping.get(address); + if (adsAddress == null) { + throw new PlcRuntimeException("Unresolvable address" + address); } - AdsSubscriptionHandle adsSubscriptionHandle = new AdsSubscriptionHandle(response.getNotificationHandle()); - future.complete(new PlcSubscriptionResponse(subscriptionRequest, Collections.singletonList( - new SubscriptionResponseItem<>(subscriptionRequestItem, adsSubscriptionHandle, ResponseCode.OK)))); - - Consumer<AdsDeviceNotificationRequest> adsDeviceNotificationRequestConsumer = - adsDeviceNotificationRequest -> adsDeviceNotificationRequest.getAdsStampHeaders().forEach(adsStampHeader -> { - Calendar timeStamp = Calendar.getInstance(); - timeStamp.setTime(adsStampHeader.getTimeStamp().getAsDate()); - - adsStampHeader.getAdsNotificationSamples() - .forEach(adsNotificationSample -> { - Data data = adsNotificationSample.getData(); - try { - @SuppressWarnings("unchecked") - List<?> decodeData = LittleEndianDecoder.decodeData(datatype, data.getBytes()); - SubscriptionEventItem subscriptionEventItem = - new SubscriptionEventItem(subscriptionRequestItem, timeStamp, decodeData); - subscriptionRequestItem.getConsumer().accept(subscriptionEventItem); - } catch (PlcProtocolException | RuntimeException e) { - LOGGER.error("Can't decode {}", data, e); - } - }); - }); - // TODO: What's this for? Is this still needed if we use the consumers in the subscriptions? - getChannel().pipeline().get(Plc4x2AdsProtocol.class).addConsumer(adsDeviceNotificationRequestConsumer); + indexGroup = IndexGroup.of(adsAddress.getIndexGroup()); + indexOffset = IndexOffset.of(adsAddress.getIndexOffset()); + } + // If it's no symbolic address, we can continue immediately + // without having to do any resolving. + else if (address instanceof AdsAddress) { + AdsAddress adsAddress = (AdsAddress) address; + indexGroup = IndexGroup.of(adsAddress.getIndexGroup()); + indexOffset = IndexOffset.of(adsAddress.getIndexOffset()); + } else { + throw new IllegalArgumentException("Unsupported address type " + address.getClass()); + } + + // Prepare the subscription request itself. + AdsAddDeviceNotificationRequest adsAddDeviceNotificationRequest = AdsAddDeviceNotificationRequest.of( + targetAmsNetId, + targetAmsPort, + sourceAmsNetId, + sourceAmsPort, + Invoke.NONE, + indexGroup, + indexOffset, + LittleEndianDecoder.getLengthFor(datatype, 1), + TransmissionMode.DefinedValues.ADSTRANS_SERVERCYCLE, + MaxDelay.of(0), + CycleTime.of(4000000) + ); + + // Send the request to the plc and wait for a response + // TODO: This is blocking, should be changed to be async. + CompletableFuture<PlcProprietaryResponse<AdsAddDeviceNotificationResponse>> addDeviceFuture = new CompletableFuture<>(); + channel.writeAndFlush(new PlcRequestContainer<>(new PlcProprietaryRequest<>(adsAddDeviceNotificationRequest), addDeviceFuture)); + PlcProprietaryResponse<AdsAddDeviceNotificationResponse> addDeviceResponse = getFromFuture(addDeviceFuture, ADD_DEVICE_TIMEOUT); + AdsAddDeviceNotificationResponse response = addDeviceResponse.getResponse(); + + // Abort if we got anything but a successful response. + if (response.getResult().toAdsReturnCode() != AdsReturnCode.ADS_CODE_0) { + throw new PlcRuntimeException("Error code received " + response.getResult()); } + AdsSubscriptionHandle adsSubscriptionHandle = new AdsSubscriptionHandle(response.getNotificationHandle()); + future.complete(new PlcSubscriptionResponse(subscriptionRequest, Collections.singletonList( + new SubscriptionResponseItem<>(subscriptionRequestItem, adsSubscriptionHandle, ResponseCode.OK)))); + + Consumer<AdsDeviceNotificationRequest> adsDeviceNotificationRequestConsumer = + adsDeviceNotificationRequest -> adsDeviceNotificationRequest.getAdsStampHeaders().forEach(adsStampHeader -> { + Calendar timeStamp = Calendar.getInstance(); + timeStamp.setTime(adsStampHeader.getTimeStamp().getAsDate()); + + adsStampHeader.getAdsNotificationSamples() + .forEach(adsNotificationSample -> { + Data data = adsNotificationSample.getData(); + try { + @SuppressWarnings("unchecked") + List<?> decodeData = LittleEndianDecoder.decodeData(datatype, data.getBytes()); + SubscriptionEventItem subscriptionEventItem = + new SubscriptionEventItem(subscriptionRequestItem, timeStamp, decodeData); + subscriptionRequestItem.getConsumer().accept(subscriptionEventItem); + } catch (PlcProtocolException | RuntimeException e) { + LOGGER.error("Can't decode {}", data, e); + } + }); + }); + // TODO: What's this for? Is this still needed if we use the consumers in the subscriptions? + getChannel().pipeline().get(Plc4x2AdsProtocol.class).addConsumer(adsDeviceNotificationRequestConsumer); return future; } @@ -226,7 +231,7 @@ public class AdsTcpPlcConnection extends AdsAbstractPlcConnection implements Plc public CompletableFuture<PlcUnsubscriptionResponse> unsubscribe(PlcUnsubscriptionRequest unsubscriptionRequest) { for (UnsubscriptionRequestItem unsubscriptionRequestItem : unsubscriptionRequest.getRequestItems()) { Objects.requireNonNull(unsubscriptionRequestItem); - if(unsubscriptionRequestItem.getSubscriptionHandle() instanceof AdsSubscriptionHandle) { + if (unsubscriptionRequestItem.getSubscriptionHandle() instanceof AdsSubscriptionHandle) { AdsSubscriptionHandle adsSubscriptionHandle = (AdsSubscriptionHandle) unsubscriptionRequestItem.getSubscriptionHandle(); AdsDeleteDeviceNotificationRequest adsDeleteDeviceNotificationRequest = diff --git a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java index 3c9e98b..3d5a1f6 100644 --- a/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java +++ b/plc4j/protocols/modbus/src/main/java/org/apache/plc4x/java/modbus/netty/Plc4XModbusProtocol.java @@ -28,6 +28,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageCodec; import org.apache.commons.lang3.ArrayUtils; import org.apache.plc4x.java.api.exceptions.PlcException; +import org.apache.plc4x.java.api.exceptions.PlcNotImplementedException; import org.apache.plc4x.java.api.exceptions.PlcProtocolException; import org.apache.plc4x.java.api.exceptions.PlcRuntimeException; import org.apache.plc4x.java.api.messages.*; @@ -72,7 +73,7 @@ public class Plc4XModbusProtocol extends MessageToMessageCodec<ModbusTcpPayload, private void encodeWriteRequest(PlcRequestContainer<PlcRequest, PlcResponse> msg, List<Object> out) throws PlcException { PlcWriteRequest request = (PlcWriteRequest) msg.getRequest(); // TODO: support multiple requests - WriteRequestItem<?> writeRequestItem = request.getRequestItem().orElseThrow(() -> new PlcProtocolException("Only single message supported for now")); + WriteRequestItem<?> writeRequestItem = request.getRequestItem().orElseThrow(() -> new PlcNotImplementedException("Only single message supported for now")); // TODO: check if we can map like this. Implication is that we can only work with int, short, byte and boolean // TODO: for higher datatypes float, double etc we might need to split the bytes into chunks int quantity = writeRequestItem.getSize(); @@ -129,7 +130,7 @@ public class Plc4XModbusProtocol extends MessageToMessageCodec<ModbusTcpPayload, private void encodeReadRequest(PlcRequestContainer<PlcRequest, PlcResponse> msg, List<Object> out) throws PlcException { PlcReadRequest request = (PlcReadRequest) msg.getRequest(); // TODO: support multiple requests - ReadRequestItem<?> readRequestItem = request.getRequestItem().orElseThrow(() -> new PlcProtocolException("Only single message supported for now")); + ReadRequestItem<?> readRequestItem = request.getRequestItem().orElseThrow(() -> new PlcNotImplementedException("Only single message supported for now")); // TODO: check if we can map like this. Implication is that we can only work with int, short, byte and boolean // TODO: for higher datatypes float, double etc we might need to split the bytes into chunks int quantity = readRequestItem.getSize(); @@ -175,7 +176,7 @@ public class Plc4XModbusProtocol extends MessageToMessageCodec<ModbusTcpPayload, // TODO: only single Item supported for now PlcRequest<?> request = plcRequestContainer.getRequest(); - RequestItem requestItem = request.getRequestItem().orElseThrow(() -> new PlcProtocolException("Only single message supported for now")); + RequestItem requestItem = request.getRequestItem().orElseThrow(() -> new PlcNotImplementedException("Only single message supported for now")); Class<?> dataType = requestItem.getDatatype(); ModbusPdu modbusPdu = msg.getModbusPdu(); diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java index 1aa4c5f..894a560 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/Plc4XS7Protocol.java @@ -19,10 +19,7 @@ under the License. package org.apache.plc4x.java.s7.netty; import io.netty.channel.ChannelHandlerContext; -import org.apache.plc4x.java.api.exceptions.PlcException; -import org.apache.plc4x.java.api.exceptions.PlcIoException; -import org.apache.plc4x.java.api.exceptions.PlcProtocolException; -import org.apache.plc4x.java.api.exceptions.PlcProtocolPayloadTooBigException; +import org.apache.plc4x.java.api.exceptions.*; import org.apache.plc4x.java.api.messages.*; import org.apache.plc4x.java.api.messages.items.ReadRequestItem; import org.apache.plc4x.java.api.messages.items.ReadResponseItem; @@ -268,7 +265,7 @@ public class Plc4XS7Protocol extends PlcMessageToMessageCodec<S7Message, PlcRequ return DataTransportSize.BYTE_WORD_DWORD; } else if (datatype == Calendar.class) { // TODO: Decide what to do here ... - return null; + throw new PlcNotImplementedException("Calender support in S7 not yet implemented"); } else if (datatype == Float.class) { return DataTransportSize.REAL; } else if (datatype == Double.class) { diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeDecoder.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeDecoder.java index 08b5c91..68b85a5 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeDecoder.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeDecoder.java @@ -92,7 +92,7 @@ public class S7TypeDecoder { } i += s7Data.length; } else { - throw new PlcProtocolException("Unsupported datatype " + datatype.getSimpleName()); + throw new PlcProtocolException("Unsupported data type " + datatype.getSimpleName()); } } return (List<T>) result; diff --git a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeEncoder.java b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeEncoder.java index 5c50e50..4ff0f4b 100644 --- a/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeEncoder.java +++ b/plc4j/protocols/s7/src/main/java/org/apache/plc4x/java/s7/netty/util/S7TypeEncoder.java @@ -18,6 +18,9 @@ */ package org.apache.plc4x.java.s7.netty.util; +import org.apache.plc4x.java.api.exceptions.PlcNotImplementedException; +import org.apache.plc4x.java.api.exceptions.PlcProtocolException; + import java.util.Calendar; public class S7TypeEncoder { @@ -26,7 +29,7 @@ public class S7TypeEncoder { // Utility class } - public static byte[] encodeData(Object[] values) { + public static byte[] encodeData(Object[] values) throws PlcProtocolException { final int length = values.length; if (length == 0) { return new byte[]{}; @@ -43,11 +46,13 @@ public class S7TypeEncoder { result = encodeInteger(values, length); } else if (valueType == Calendar.class) { // TODO: Decide what to do here ... - result = null; + throw new PlcNotImplementedException("calender not yet implemented in s7"); } else if (valueType == Float.class) { result = encodeFloat(values, length); } else if (valueType == String.class) { result = encodeString(values, length); + } else { + throw new PlcProtocolException("Unsupported data type " + valueType); } return result; }