当我用netty实现gpsd tcp feed时,我做错了什么?

时间:2013-09-02 21:31:32

标签: tcp netty nmea gpsd

我正在通过TCP / IP嘲笑伪造的GPS设备NMEA-0183。

我在Netty(http://netty.io/)和Java Marine API(http://ktuukkan.github.io/marine-api/)的顶部编写了一个轻量级服务器。服务器等待通道激活,一旦gpsd激活通道,它就开始将NMEA语句写入缓冲区。请参阅下面的代码(通常取自Netty示例):

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
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.nio.NioServerSocketChannel;

/**
 * Discards any incoming data.
 */
public class TCPSentenceGenerator {

    private int port;

    public TCPSentenceGenerator(int port) {
        this.port = port;
    }

    public void run() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap(); // (2)
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class) // (3)
                    .childHandler(new ChannelInitializer<SocketChannel>() { // (4)
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new TCPSentenceGeneratorHandler());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)          // (5)
                    .childOption(ChannelOption.SO_KEEPALIVE, true); // (6)

            // Bind and start to accept incoming connections.
            ChannelFuture f = b.bind(port).sync(); // (7)

            // Wait until the server socket is closed.
            // In this example, this does not happen, but you can do that to gracefully
            // shut down your server.
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws Exception {
        int port;
        if (args.length > 0) {
            port = Integer.parseInt(args[0]);
        } else {
            port = 9090;
        }
        new TCPSentenceGenerator (port).run();
    }
}

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import net.sf.marineapi.nmea.parser.*;
import net.sf.marineapi.nmea.sentence.*;
import net.sf.marineapi.nmea.util.Time;

public class TCPSentenceGeneratorHandler extends ChannelInboundHandlerAdapter { // (1)

@Override
public void channelActive(final ChannelHandlerContext ctx) {
    while (true) {
        RMCSentence rmcs = new RMCParser("$GPRMC,154653,V,4428.2011,N,00440.5161,W,000.5,342.8,050407,,,N*7F");

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace(); 
        }

        String RMCsentenceString = rmcs.toSentence();

        System.out.println("Char number is " + RMCsentenceString.length());
        System.out.println("Byte number is " + RMCsentenceString.getBytes().length);

        final ByteBuf outtext = ctx.alloc().buffer(RMCsentenceString.getBytes().length); // (2)
        outtext.writeBytes(RMCsentenceString.getBytes());

        ctx.writeAndFlush(outtext); // (3)

        System.out.println(rmcs.toString());

    }
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4)
    // Close the connection when an exception is raised.
    cause.printStackTrace();
    ctx.close();
}
}

当我启动服务器运行时,然后通过

将gpsd附加到它上面
gpsd -N -n -D8 tcp://localhost:9090

我得到调试日志的奇怪输出:

gpsd:UNK: ISGPS preamble ok, parity fail
gpsd:UNK: ISGPS lock never achieved
gpsd:UNK: Character discarded, buffer 69 chars = *7F$GPRMC,154653,V,4428.2011,N,00440.5161,W,000.5,342.8,050407,,,N*7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
gpsd:UNK: ISGPS word tag not correct, skipping byte
gpsd:UNK: Character discarded, buffer 68 chars = 7F$GPRMC,154653,V,4428.2011,N,00440.5161,W,000.5,342.8,050407,,,N*7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
gpsd:UNK: ISGPS word tag not correct, skipping byte
gpsd:UNK: Character discarded, buffer 67 chars = F$GPRMC,154653,V,4428.2011,N,00440.5161,W,000.5,342.8,050407,,,N*7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
gpsd:UNK: ISGPS lock never achieved
gpsd:UNK: Character discarded, buffer 66 chars = $GPRMC,154653,V,4428.2011,N,00440.5161,W,000.5,342.8,050407,,,N*7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
gpsd:RAW: packet sniff on tcp://localhost:9090 finds type -1
gpsd:PROG: no /etc/gpsd/device-hook present, skipped running DEACTIVATE hook
gpsd:INFO: hunt on tcp://localhost:9090 failed (15.019291 sec since data)
gpsd:WARN: device read of tcp://localhost:9090 returned error or packet sniffer failed sync (flags {ERROR})
gpsd:INFO: closing GPS=tcp://localhost:9090 (6)
gpsd:SPIN: close(6) in gpsd_close(tcp://localhost:9090)
gpsd:PROG: no /etc/gpsd/device-hook present, skipped running DEACTIVATE hook
gpsd:INFO: reconnection attempt on device 0
gpsd:PROG: no /etc/gpsd/device-hook present, skipped running ACTIVATE hook
gpsd:INFO: opening TCP feed at localhost, port 9090.
gpsd:SPIN: TCP device opened on fd 6
gpsd:INFO: gpsd_activate(): activated GPS (fd 6)
gpsd:RAW: flagging descriptor 6 in assign_channel()

第一部分没问题,它只显示如何从缓冲区中提取句子。但是有什么问题     gpsd:RAW:tcp上的数据包嗅探:// localhost:9090找到类型-1

为什么数据包在正确读取时会输入-1?

2 个答案:

答案 0 :(得分:1)

我是个白痴。我忘了在写之前在句子中添加“\ r \ n”并将其刷新。有了这个,一切都有效。

引导我的是Gpsd使用的gpsfeed + GPS模拟器(http://gpsfeed.sourceforge.net/),调试级别为8.它显示了接受句子中的字符,并显示这些句子对于gpsfeed是可以的。

答案 1 :(得分:1)

最后,如果你想让gpsd工作,你应该提供至少两种类型的句子:

  GGASentence ggas= new GGAParser("$GPGGA,084603,3806.0267,N,02348.1719,E,1,04,5.6,1454.0,M,34.5,M,,*77");
  RMCSentence rmcs= new RMCParser("$GPRMC,084603,A,3806.0267,N,02348.1719,E,8315.7,213.5,040913,5,E,A*36");

RMC应该有'date'字段非空