Skip to content

Commit

Permalink
feat(plc-simulator/bacnet): bacnet simulator is now able to return a …
Browse files Browse the repository at this point in the history
…valid hard coded response
  • Loading branch information
sruehl committed Nov 4, 2022
1 parent 37d8880 commit c1f1700
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 43 deletions.
Expand Up @@ -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 {
Expand Down Expand Up @@ -88,24 +81,28 @@ public void start() throws SimulatorException {
.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));
}
});

Expand Down
Expand Up @@ -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);
Expand All @@ -57,8 +49,129 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
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();
}
});
;
}


}

0 comments on commit c1f1700

Please sign in to comment.