writeAndFlush()之后的Java netty rxtx管道块

时间:2017-02-28 11:08:59

标签: java netty rxtx

我目前正在尝试使用netty 4.0.44.Final和rxtx在微控制器和Java应用程序之间实现一些稳定的连接。控制器会不时要求时间戳,否则它只是将传感器数据转发给我的应用程序。应用程序能够接收尽可能多的包,直到我在管道中的某个地方调用writeAndFlush()(即回答时间请求)。管道正确地在输出流上写入数据(当调用writeAndFlush()时),从那时起,我的应用程序永远不会再次接收数据,我不知道为什么。

public class WsnViaRxtxConnector extends AbstractWsnConnector{
private static final Logger LOG = LoggerFactory.getLogger(WsnViaRxtxConnector.class);
private String port;
private Provider<MessageDeserializer> deserializerProvider;
private ChannelFuture channelFuture;
public ChannelKeeper keeper;

@Inject
public WsnViaRxtxConnector(Provider<MessageDeserializer> deserializerProvider, ChannelKeeper keeper) {
    this.deserializerProvider = deserializerProvider;
    this.port = Configuration.getConfig().getString("rest.wsn.port");
    this.keeper = keeper;
    System.setProperty("gnu.io.rxtx.SerialPorts", this.port);
}

@Override
protected void run() throws Exception
{
    EventLoopGroup group = new OioEventLoopGroup();
    //final EventExecutorGroup group2 = new DefaultEventExecutorGroup(1500);

    try {
        Bootstrap b = new Bootstrap();
        b.group(group)
         .channel(RxtxChannel.class)
         .handler(new ChannelInitializer<RxtxChannel>() {
             @Override
             public void initChannel(RxtxChannel ch) throws Exception {
                 ch.pipeline().addLast(new DleStxEtxFrameDecoder(), new DleStxEtxFrameEncoder());   
                 ch.pipeline().addLast(new IntegrityCheck(),new IntegrityCalculation());
                 ch.pipeline().addLast(new AesCcmDecrypter(),new AesCcmEncrypter());
                 ch.pipeline().addLast(deserializerProvider.get(),new MessageSerializer());
                 ch.pipeline().addLast(new TimeStampJockel());
             }
         })
          .option(RxtxChannelOption.BAUD_RATE, 19200);
        ChannelFuture f = b.connect(new RxtxDeviceAddress(this.port)).sync();
        f.channel().closeFuture().sync();
    } finally {
        group.shutdownGracefully();
    }
}

处理程序都是非常标准的实现,并且在仅接收包时似乎有效。管道应该首先从原始数据生成一个对象,checkCRC,解密,反序列化,然后计算一些逻辑(也就是生成时间响应)。

public class TimeStampJockel extends ChannelInboundHandlerAdapter{
private static final Logger LOG = LoggerFactory.getLogger(TimeStampJockel.class);

private EventBus bus;
private ChannelKeeper keeper;

@Inject
public TimeStampJockel(){
    this.bus = GlobalEventBus.getInstance();
    this.keeper = keeper;
}

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg){
    LOG.debug("Creating packet from received data");

    RawPacket raw = (RawPacket)msg;

    //EventExecutor ex = ctx.executor();
    //LOG.debug("inexecutor.EventLoop(1):" + ex.inEventLoop());

    //keeper.addChannelHandlerContext(raw.getSource(),ctx);

    ByteBuf buf = raw.getContent();
    LOG.debug("\tBuffer: {}", HelperFunctions.getBufferAsHexString(buf));
    UnsignedLong mac = UnsignedLong.fromLongBits(21);
    while(buf.readerIndex()<buf.writerIndex())
    {
        int type = buf.readShort();
        int length = buf.readShort();
        ByteBuf value = buf.readBytes(length);
        if(PacketType.getEnum(type).equals(PacketType.MAC))
        {
            mac = UnsignedLong.valueOf(value.readLong());
        }
        else
        {
            AbstractPacket packet = PacketFactory.createPacket(PacketType.getEnum(type), raw.getVersion(), raw.getPacketType(), raw.getSource(), raw.getSource(), raw.getDestination(), mac, value);
            if(packet instanceof TimeReqPacket) {
                TimeReqPacket timeReqPacket = (TimeReqPacket) packet;
                Duration d = HelperFunctions.timeSinceYear2000();
                TimeRespPacket newPacket = new TimeRespPacket(Constants.PROTOCOL_VERSION, PacketType.TIME_RESP.getValue(), packet.getGatewayAdr(),UnsignedLong.valueOf(Configuration.getConfig().getLong("rest.wsn.mac", Long.MAX_VALUE)),timeReqPacket.getMac(),timeReqPacket.getMac(),d.getStandardSeconds(),HelperFunctions.getMillisOfDuration(d));

                ctx.write(newPacket);

            } else {
                bus.post(packet);
            }
        }
    }
}

接收到的传感器数据被推送到Guava总线(除非是时间请求)并由其他组件处理。如果传入的包是时间请求包,则先前显示的组件应生成时间戳包,并且writeAndFlush()在流水线下。可能导致该问题的任何想法?我几乎没有想法 - 我一直在谷歌搜索过去10个小时没有有意义的结果,我没有剩下未经检查的资源。我正在使用ubuntu 16.04,提前感谢。

[编辑]我尝试通过将以下代码片段添加到最后一个管道处理程序来检查ChannelFuture

ChannelFuture f = ctx.writeAndFlush(newPacket);
                f.addListener(new ChannelFutureListener() {

                    @Override
                    public void operationComplete(ChannelFuture future) throws Exception {
                        if (!future.isSuccess()) {
                            LOG.error("Server failed to send message", future.cause());
                            future.channel().close();
                        }
                    }

[EDIT2]发现我的错误。这是一个网络版本的冲突。我正在使用不同项目中的多个版本的netty,并使用较旧的netty版本(4.0.13)而不是netty 4.044.final。我不知道这些版本之间有什么变化,但我很高兴现在一切正常。

0 个答案:

没有答案