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