我正在通过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?
答案 0 :(得分:1)
引导我的是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'字段非空