1

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 になるのはなぜですか?

4

2 に答える 2

1

私はアホです。書き込んでフラッシュする前に、文に「\r\n」を追加するのを忘れていました。この追加により、すべてが機能します。

私を導いてくれたのは、gpsfeed+ GPS シミュレーター ( http://gpsfeed.sourceforge.net/ ) の gpsd がデバッグ レベル 8 で消費するフィードでした。

于 2013-09-03T05:50:44.867 に答える
1

最後に、gpsd を機能させたい場合は、少なくとも 2 種類の文を提供する必要があります。

  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 には「日付」フィールドが空でない必要があります

于 2013-09-04T05:09:26.210 に答える