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
The following commit(s) were added to refs/heads/master by this push: new f9073a2 added support for proprietary protocol messages. f9073a2 is described below commit f9073a21a9df2eb50f5c81d451771bd4c0c794ec Author: Sebastian Rühl <sru...@apache.org> AuthorDate: Fri Apr 13 14:04:30 2018 +0200 added support for proprietary protocol messages. --- .../java/api/connection/PlcProprietarySender.java | 41 ++++++++++++++++++ .../java/api/messages/PlcProprietaryRequest.java | 48 ++++++++++++++++++++++ .../java/api/messages/PlcProprietaryResponse.java | 48 ++++++++++++++++++++++ .../ads/connection/AdsAbstractPlcConnection.java | 15 ++++++- .../plc4x/java/ads/protocol/Plc4x2AdsProtocol.java | 40 +++++++++++++----- 5 files changed, 181 insertions(+), 11 deletions(-) diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/connection/PlcProprietarySender.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/connection/PlcProprietarySender.java new file mode 100644 index 0000000..b24493e --- /dev/null +++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/connection/PlcProprietarySender.java @@ -0,0 +1,41 @@ +/* + 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.connection; + +import org.apache.plc4x.java.api.messages.PlcProprietaryRequest; +import org.apache.plc4x.java.api.messages.PlcProprietaryResponse; + +import java.util.concurrent.CompletableFuture; + +/** + * Interface implemented by all PlcConnections that are able to send custom commands to resources. + */ +@FunctionalInterface +public interface PlcProprietarySender { + + /** + * Sends a given custom request to a PLC. + * + * @param request request to be send. + * @param <T> the request type + * @param <R> the response type + * @return a {@link CompletableFuture} giving async access to the response of the send operation. + */ + <T, R> CompletableFuture<PlcProprietaryResponse<R>> send(PlcProprietaryRequest<T> request); +} diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcProprietaryRequest.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcProprietaryRequest.java new file mode 100644 index 0000000..359ed03 --- /dev/null +++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcProprietaryRequest.java @@ -0,0 +1,48 @@ +/* + 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.messages; + +import org.apache.plc4x.java.api.messages.items.RequestItem; +import org.apache.plc4x.java.api.model.Address; + +/** + * This request can be used to pass proprietary protocol specific messages to the underlying layers. + * + * @param <CUSTOM_REQUEST> request + */ +public class PlcProprietaryRequest<CUSTOM_REQUEST> extends PlcRequest<PlcProprietaryRequest.DummyRequestItem> { + + private final CUSTOM_REQUEST request; + + public PlcProprietaryRequest(CUSTOM_REQUEST request) { + this.request = request; + } + + public CUSTOM_REQUEST getRequest() { + return request; + } + + protected static class DummyRequestItem extends RequestItem<Void> { + + public DummyRequestItem() { + super(Void.class, new Address() { + }); + } + } +} diff --git a/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcProprietaryResponse.java b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcProprietaryResponse.java new file mode 100644 index 0000000..3c3d159 --- /dev/null +++ b/plc4j/api/src/main/java/org/apache/plc4x/java/api/messages/PlcProprietaryResponse.java @@ -0,0 +1,48 @@ +/* + 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.messages; + +import org.apache.plc4x.java.api.messages.items.ResponseItem; +import org.apache.plc4x.java.api.types.ResponseCode; + +import java.util.Collections; + +/** + * This response can be used to pass proprietary protocol specific messages from the underlying layers. + */ +public class PlcProprietaryResponse<CUSTOM_RESPONSE> extends PlcResponse<PlcProprietaryRequest, PlcProprietaryResponse.DummyResponseItem, PlcProprietaryRequest.DummyRequestItem> { + + private final CUSTOM_RESPONSE response; + + public PlcProprietaryResponse(PlcProprietaryRequest request, CUSTOM_RESPONSE response) { + super(request, Collections.emptyList()); + this.response = response; + } + + public CUSTOM_RESPONSE getResponse() { + return response; + } + + protected static class DummyResponseItem extends ResponseItem<PlcProprietaryRequest.DummyRequestItem> { + + public DummyResponseItem() { + super(new PlcProprietaryRequest.DummyRequestItem(), ResponseCode.OK); + } + } +} diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java index 1e0d8c9..cf70f22 100644 --- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java +++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/connection/AdsAbstractPlcConnection.java @@ -22,6 +22,7 @@ import io.netty.channel.ChannelFuture; import org.apache.plc4x.java.ads.api.generic.types.AmsNetId; import org.apache.plc4x.java.ads.api.generic.types.AmsPort; import org.apache.plc4x.java.ads.model.AdsAddress; +import org.apache.plc4x.java.api.connection.PlcProprietarySender; import org.apache.plc4x.java.api.connection.PlcReader; import org.apache.plc4x.java.api.connection.PlcWriter; import org.apache.plc4x.java.api.exceptions.PlcException; @@ -32,7 +33,7 @@ import org.apache.plc4x.java.base.connection.ChannelFactory; import java.util.concurrent.CompletableFuture; -public abstract class AdsAbstractPlcConnection extends AbstractPlcConnection implements PlcReader, PlcWriter { +public abstract class AdsAbstractPlcConnection extends AbstractPlcConnection implements PlcReader, PlcWriter, PlcProprietarySender { protected final AmsNetId targetAmsNetId; @@ -100,6 +101,18 @@ public abstract class AdsAbstractPlcConnection extends AbstractPlcConnection imp return writeFuture; } + @Override + public <T, R> CompletableFuture<PlcProprietaryResponse<R>> send(PlcProprietaryRequest<T> request) { + CompletableFuture<PlcProprietaryResponse<R>> sendFuture = new CompletableFuture<>(); + ChannelFuture channelFuture = channel.writeAndFlush(new PlcRequestContainer<>(request, sendFuture)); + channelFuture.addListener(future -> { + if (!future.isSuccess()) { + sendFuture.completeExceptionally(future.cause()); + } + }); + return sendFuture; + } + protected static AmsNetId generateAMSNetId() { return AmsNetId.of("0.0.0.0.0.0"); } diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java index ce8f627..2f4ef45 100644 --- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java +++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/Plc4x2AdsProtocol.java @@ -85,12 +85,16 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque encodeReadRequest(msg, out); } else if (request instanceof PlcWriteRequest) { encodeWriteRequest(msg, out); + } else if (request instanceof PlcProprietaryRequest) { + encodeProprietaryRequest(msg, out); + } else { + throw new PlcProtocolException("Unknown type " + request.getClass()); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if((cause instanceof IOException) && (cause.getMessage().contains("Connection reset by peer") || + if ((cause instanceof IOException) && (cause.getMessage().contains("Connection reset by peer") || cause.getMessage().contains("Operation timed out"))) { String reason = cause.getMessage().contains("Connection reset by peer") ? "Connection terminated unexpectedly" : "Remote host not responding"; @@ -149,11 +153,21 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque requests.put(invokeId.getAsLong(), msg); } + private void encodeProprietaryRequest(PlcRequestContainer<PlcRequest, PlcResponse> msg, List<Object> out) throws PlcProtocolException { + PlcProprietaryRequest plcProprietaryRequest = (PlcProprietaryRequest) msg.getRequest(); + if (!(plcProprietaryRequest.getRequest() instanceof AmsPacket)) { + throw new PlcProtocolException("Unsupported proprietary type for this driver " + plcProprietaryRequest.getRequest().getClass()); + } + AmsPacket amsPacket = (AmsPacket) plcProprietaryRequest.getRequest(); + requests.put(amsPacket.getAmsHeader().getInvokeId().getAsLong(), msg); + out.add(amsPacket); + } + @Override - protected void decode(ChannelHandlerContext channelHandlerContext, AmsPacket AmsPacket, List<Object> out) throws Exception { - PlcRequestContainer<PlcRequest, PlcResponse> plcRequestContainer = requests.remove(AmsPacket.getAmsHeader().getInvokeId().getAsLong()); + protected void decode(ChannelHandlerContext channelHandlerContext, AmsPacket amsPacket, List<Object> out) throws Exception { + PlcRequestContainer<PlcRequest, PlcResponse> plcRequestContainer = requests.remove(amsPacket.getAmsHeader().getInvokeId().getAsLong()); if (plcRequestContainer == null) { - LOGGER.info("Unmapped packet received {}", AmsPacket); + LOGGER.info("Unmapped packet received {}", amsPacket); return; } PlcRequest request = plcRequestContainer.getRequest(); @@ -161,17 +175,19 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque // Handle the response to a read request. if (request instanceof PlcReadRequest) { - if (AmsPacket instanceof AdsReadResponse) { - response = decodeReadResponse((AdsReadResponse) AmsPacket, plcRequestContainer); + if (amsPacket instanceof AdsReadResponse) { + response = decodeReadResponse((AdsReadResponse) amsPacket, plcRequestContainer); } else { - throw new PlcProtocolException("Wrong type correlated " + AmsPacket); + throw new PlcProtocolException("Wrong type correlated " + amsPacket); } } else if (request instanceof PlcWriteRequest) { - if (AmsPacket instanceof AdsWriteResponse) { - response = decodeWriteResponse((AdsWriteResponse) AmsPacket, plcRequestContainer); + if (amsPacket instanceof AdsWriteResponse) { + response = decodeWriteResponse((AdsWriteResponse) amsPacket, plcRequestContainer); } else { - throw new PlcProtocolException("Wrong type correlated " + AmsPacket); + throw new PlcProtocolException("Wrong type correlated " + amsPacket); } + } else if (request instanceof PlcProprietaryRequest) { + response = decodeProprietaryResponse(amsPacket, plcRequestContainer); } // Confirm the response being handled. @@ -210,6 +226,10 @@ public class Plc4x2AdsProtocol extends MessageToMessageCodec<AmsPacket, PlcReque } } + private PlcResponse decodeProprietaryResponse(AmsPacket amsPacket, PlcRequestContainer<PlcRequest, PlcResponse> plcRequestContainer) { + return new PlcProprietaryResponse<>((PlcProprietaryRequest) plcRequestContainer.getRequest(), amsPacket); + } + private ResponseCode decodeResponseCode(Result result) { switch (result.toAdsReturnCode()) { case ADS_CODE_0: -- To stop receiving notification emails like this one, please contact sru...@apache.org.