I'm trying to develop a client to communicate with a biometric device using a custom protocol but nothing seems to work. I'm using a MessageToByteEncoder and a MessageToByteDecoder to handle the input and output data:
public class PacketDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext context, ByteBuf input, List<Object> out) throws Exception {
System.out.println("readable bytes: " + input.readableBytes());
if (input.readableBytes() >= 1) {
if (input.getByte(0) != DataCodes.START_BYTE) {
input.readByte();
return;
}
}
if (input.readableBytes() >= 3) {
byte command = input.getByte(2);
boolean extendedLenght = (command & 0x80) == 0x80;
short dataLength;
int headerLength;
if (extendedLenght) {
byte[] dataLengthBytes = new byte[2];
input.getBytes(3, dataLengthBytes);
dataLength = Utils.getShort(dataLengthBytes);
headerLength = 5;
} else {
dataLength = input.getByte(3);
headerLength = 4;
}
int totalLength = headerLength + dataLength + 16;
if (input.readableBytes() >= totalLength) {
byte[] packetBytes = input.readBytes(totalLength).array();
Packet packet = PacketConverter.decode(packetBytes);
System.out.println("packet decoded");
out.add(packet);
}
}
}
}
public class PacketEncoder extends MessageToByteEncoder<Packet> {
@Override
protected void encode(ChannelHandlerContext context, Packet packet, ByteBuf out) throws Exception {
byte[] packetBytes = PacketConverter.encode(packet);
out.writeBytes(packetBytes);
}
}
and the connnection class:
public class Connection implements PacketListener {
private final byte deviceAddress;
private ChannelFuture channelFuture;
private EventLoopGroup workerGroup;
private final Object readLock = new Object();
private Packet responsePacket;
public Connection(byte deviceAddress) {
this.deviceAddress = deviceAddress;
}
public void connect(String address, int port) {
workerGroup = new NioEventLoopGroup();
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(
new PacketEncoder(),
new PacketDecoder(),
new PacketHandler(Connection.this)
);
}
});
channelFuture = b.connect(address, port);
}
public void disconnect() {
channelFuture.channel().disconnect().syncUninterruptibly();
workerGroup.shutdownGracefully();
}
@Override
public void receive(Packet packet) {
synchronized (readLock) {
this.responsePacket = packet;
readLock.notify();
}
}
public Response send(Command command, int responseTimeout) throws TimeOutException {
Packet packet = new Packet();
packet.setCommand(command.getCommandCode());
packet.setData(command.getCommandData());
packet.setAddress(deviceAddress);
synchronized (readLock) {
responsePacket = null;
channelFuture.channel().writeAndFlush(packet).syncUninterruptibly();
try {
readLock.wait(responseTimeout);
} catch (InterruptedException e) {
}
if (responsePacket == null)
throw new TimeOutException();
return Response.get(responsePacket);
}
}
}
On the decoder, it aways comes with 0 readableBytes and I not sure the enconder is sending any data at all. My only guess is that the server needs to be a Netty implementation.