You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2022/11/04 15:45:30 UTC

[plc4x] 01/03: feat(plc-simulator/bacnet): bacnet simulator is now able to return a valid hard coded response

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit c1f1700932da9b2f0db523a8a2f10b1e85bde6e8
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Nov 4 14:27:55 2022 +0100

    feat(plc-simulator/bacnet): bacnet simulator is now able to return a valid hard coded response
---
 .../server/bacnet/BacnetServerModule.java          |  59 +++++----
 .../bacnet/protocol/BacnetServerAdapter.java       | 137 +++++++++++++++++++--
 2 files changed, 153 insertions(+), 43 deletions(-)

diff --git a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/BacnetServerModule.java b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/BacnetServerModule.java
index f5a504778..8c69793ed 100644
--- a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/BacnetServerModule.java
+++ b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/BacnetServerModule.java
@@ -19,35 +19,28 @@
 package org.apache.plc4x.simulator.server.bacnet;
 
 import io.netty.bootstrap.Bootstrap;
-import io.netty.bootstrap.ServerBootstrap;
 import io.netty.buffer.ByteBuf;
-import io.netty.channel.*;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.DatagramPacket;
 import io.netty.channel.socket.nio.NioDatagramChannel;
-import io.netty.channel.socket.nio.NioServerSocketChannel;
-import io.netty.handler.codec.DatagramPacketDecoder;
-import io.netty.handler.codec.DatagramPacketEncoder;
 import io.netty.handler.codec.MessageToMessageDecoder;
 import io.netty.handler.codec.MessageToMessageEncoder;
 import org.apache.plc4x.java.bacnetip.BacNetIpDriver;
 import org.apache.plc4x.java.bacnetip.readwrite.BVLC;
 import org.apache.plc4x.java.bacnetip.readwrite.BacnetConstants;
-import org.apache.plc4x.java.cbus.CBusDriver;
-import org.apache.plc4x.java.cbus.readwrite.CBusConstants;
-import org.apache.plc4x.java.cbus.readwrite.CBusMessage;
-import org.apache.plc4x.java.cbus.readwrite.CBusOptions;
-import org.apache.plc4x.java.cbus.readwrite.RequestContext;
 import org.apache.plc4x.java.spi.connection.GeneratedProtocolMessageCodec;
 import org.apache.plc4x.java.spi.generation.ByteOrder;
-import org.apache.plc4x.java.spi.generation.ReadBufferByteBased;
-import org.apache.plc4x.java.spi.generation.WriteBufferByteBased;
 import org.apache.plc4x.simulator.PlcSimulatorConfig;
 import org.apache.plc4x.simulator.exceptions.SimulatorException;
 import org.apache.plc4x.simulator.model.Context;
 import org.apache.plc4x.simulator.server.ServerModule;
 import org.apache.plc4x.simulator.server.bacnet.protocol.BacnetServerAdapter;
 
+import java.net.InetSocketAddress;
 import java.util.List;
 
 public class BacnetServerModule implements ServerModule {
@@ -88,24 +81,28 @@ public class BacnetServerModule implements ServerModule {
                 .handler(new ChannelInitializer<NioDatagramChannel>() {
                     @Override
                     public void initChannel(NioDatagramChannel channel) {
-                        ChannelPipeline pipeline = channel.pipeline();
-                        pipeline.addLast(new DatagramPacketDecoder(new MessageToMessageDecoder<ByteBuf>() {
-                            @Override
-                            protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
-                                byte[] bytes = new byte[msg.readableBytes()];
-                                msg.readBytes(bytes);
-                                out.add(BVLC.staticParse(new ReadBufferByteBased(bytes)));
-                            }
-                        }));
-                        pipeline.addLast(new DatagramPacketEncoder<>(new MessageToMessageEncoder<BVLC>() {
-                            @Override
-                            protected void encode(ChannelHandlerContext ctx, BVLC msg, List<Object> out) throws Exception {
-                                WriteBufferByteBased writeBuffer = new WriteBufferByteBased(msg.getLengthInBytes());
-                                msg.serialize(writeBuffer);
-                                out.add(writeBuffer.getBytes());
-                            }
-                        }));
-                        pipeline.addLast(new BacnetServerAdapter(context));
+                        channel.pipeline()
+                            .addLast(new MessageToMessageDecoder<DatagramPacket>() {
+                                @Override
+                                protected void decode(ChannelHandlerContext ctx, DatagramPacket msg, List<Object> out) throws Exception {
+                                    final ByteBuf content = msg.content();
+                                    out.add(content.retain());
+                                }
+                            })
+                            .addLast(new MessageToMessageEncoder<ByteBuf>() {
+                                @Override
+                                protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
+                                    msg.retain();
+                                    // TODO: find better way to implement request response
+                                    out.add(new DatagramPacket(msg, new InetSocketAddress("192.168.178.102", 47808)));
+                                }
+                            })
+                            .addLast(new GeneratedProtocolMessageCodec<>(BVLC.class,
+                                BVLC::staticParse, ByteOrder.BIG_ENDIAN,
+                                null,
+                                new BacNetIpDriver.ByteLengthEstimator(),
+                                new BacNetIpDriver.CorruptPackageCleaner()))
+                            .addLast(new BacnetServerAdapter(context));
                     }
                 });
 
diff --git a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/protocol/BacnetServerAdapter.java b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/protocol/BacnetServerAdapter.java
index 39da9a67a..92dfe3fb4 100644
--- a/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/protocol/BacnetServerAdapter.java
+++ b/plc4j/utils/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/bacnet/protocol/BacnetServerAdapter.java
@@ -18,24 +18,16 @@
  */
 package org.apache.plc4x.simulator.server.bacnet.protocol;
 
+import io.netty.channel.ChannelFutureListener;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
-import org.apache.plc4x.java.bacnetip.readwrite.BVLC;
-import org.apache.plc4x.java.cbus.readwrite.*;
+import org.apache.plc4x.java.bacnetip.readwrite.Error;
+import org.apache.plc4x.java.bacnetip.readwrite.*;
+import org.apache.plc4x.java.bacnetip.readwrite.utils.StaticHelper;
 import org.apache.plc4x.simulator.model.Context;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
 public class BacnetServerAdapter extends ChannelInboundHandlerAdapter {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(BacnetServerAdapter.class);
@@ -57,8 +49,129 @@ public class BacnetServerAdapter extends ChannelInboundHandlerAdapter {
         if (!(msg instanceof BVLC)) {
             return;
         }
+        BVLC bvlc = (BVLC) msg;
+        if (!(bvlc instanceof BVLCOriginalUnicastNPDU)) {
+            // TODO: write useful error
+            ctx.writeAndFlush(new BVLCOriginalUnicastNPDU(
+                new NPDU(
+                    (short) 1,
+                    new NPDUControl(true, false, false, false, NPDUNetworkPriority.NORMAL_MESSAGE),
+                    0,
+                    (short) 0,
+                    null,
+                    0,
+                    (short) 0,
+                    null,
+                    (short) 0,
+                    null,
+                    new APDUError(
+                        (short) 0,
+                        BACnetConfirmedServiceChoice.READ_PROPERTY,
+                        new BACnetErrorGeneral(new Error(
+                            new ErrorClassTagged(new BACnetTagHeader((byte) 0, TagClass.APPLICATION_TAGS, (byte) 1, (short) 0, (short) 0, 0, 0L), ErrorClass.COMMUNICATION, 0, (short) 0, TagClass.APPLICATION_TAGS),
+                            new ErrorCodeTagged(new BACnetTagHeader((byte) 0, TagClass.APPLICATION_TAGS, (byte) 1, (short) 0, (short) 0, 0, 0L), ErrorCode.VENDOR_PROPRIETARY_VALUE, 0, (short) 0, TagClass.APPLICATION_TAGS)
+                        )),
+                        0
+                    ),
+                    0
+                ),
+                0
+            )).addListener((ChannelFutureListener) f -> {
+                if (!f.isSuccess()) {
+                    f.cause().printStackTrace();
+                }
+            });
+            return;
+        }
+        BVLCOriginalUnicastNPDU bvlcOriginalUnicastNPDU = (BVLCOriginalUnicastNPDU) bvlc;
+        // TODO: get messageTypeField
+        APDU apdu = bvlcOriginalUnicastNPDU.getNpdu().getApdu();
+        if (!(apdu instanceof APDUConfirmedRequest)) {
+            // TODO: write useful error
+            ctx.writeAndFlush(new BVLCOriginalUnicastNPDU(
+                new NPDU(
+                    (short) 1,
+                    new NPDUControl(true, false, false, false, NPDUNetworkPriority.NORMAL_MESSAGE),
+                    0,
+                    (short) 0,
+                    null,
+                    0,
+                    (short) 0,
+                    null,
+                    (short) 0,
+                    null,
+                    new APDUError(
+                        (short) 0,
+                        BACnetConfirmedServiceChoice.READ_PROPERTY,
+                        new BACnetErrorGeneral(new Error(
+                            new ErrorClassTagged(new BACnetTagHeader((byte) 0, TagClass.APPLICATION_TAGS, (byte) 1, (short) 0, (short) 0, 0, 0L), ErrorClass.COMMUNICATION, 0, (short) 0, TagClass.APPLICATION_TAGS),
+                            new ErrorCodeTagged(new BACnetTagHeader((byte) 0, TagClass.APPLICATION_TAGS, (byte) 1, (short) 0, (short) 0, 0, 0L), ErrorCode.VENDOR_PROPRIETARY_VALUE, 0, (short) 0, TagClass.APPLICATION_TAGS)
+                        )),
+                        0
+                    ),
+                    0
+                ),
+                0
+            )).addListener((ChannelFutureListener) f -> {
+                if (!f.isSuccess()) {
+                    f.cause().printStackTrace();
+                }
+            });
+            return;
+        }
+        APDUConfirmedRequest apduConfirmedRequest = (APDUConfirmedRequest) apdu;
         // TODO: implement me
+        System.out.println("Got request");
         System.out.println(msg);
+        BVLCOriginalUnicastNPDU response = new BVLCOriginalUnicastNPDU(
+            new NPDU(
+                (short) 1,
+                new NPDUControl(false, false, false, false, NPDUNetworkPriority.NORMAL_MESSAGE),
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                null,
+                new APDUComplexAck(
+                    false,
+                    false,
+                    apduConfirmedRequest.getInvokeId(),
+                    null,
+                    null,
+                    new BACnetServiceAckReadProperty(
+                        StaticHelper.createBACnetContextTagObjectIdentifier((byte) 0, 2, 1L),
+                        StaticHelper.createBACnetPropertyIdentifierTagged((byte) 1, 85),
+                        null,
+                        new BACnetConstructedDataAnalogValuePresentValue(
+                            StaticHelper.createBACnetOpeningTag((short) 3),
+                            StaticHelper.createBACnetTagHeaderBalanced(true, (short) 3, 3L),
+                            StaticHelper.createBACnetClosingTag((short) 3),
+                            StaticHelper.createBACnetApplicationTagReal(101L),
+                            null,
+                            null
+                        ),
+                        0L
+                    ),
+                    null,
+                    null,
+                    0
+                ),
+                0
+            ),
+            0
+        );
+        System.out.println("Writing response");
+        System.out.println(response);
+        ctx.writeAndFlush(response).addListener((ChannelFutureListener) f -> {
+            if (!f.isSuccess()) {
+                f.cause().printStackTrace();
+            }
+        });
+        ;
     }
 
+
 }