I'm mocking a fake GPS device NMEA-0183 feed via TCP/IP.
I've written a lightweight server on the top of Netty (http://netty.io/) and Java Marine API (http://ktuukkan.github.io/marine-api/). Server waits for the channel activation, and once channel is activated by the gpsd it starts writing NMEA sentences to buffer. Please see my code below (generally taken from Netty examples):
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();
}
}
and
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();
}
}
When I start my server running, and then attach gpsd to it via
gpsd -N -n -D8 tcp://localhost:9090
I'm getting strange output to the debug logs:
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()
First part is okay, it just displays how sentences are extracted from the buffer. But what is wrong with gpsd:RAW: packet sniff on tcp://localhost:9090 finds type -1
why the packet type -1 if it is correctly read?
and finally, if you want gpsd working, you should provide at least 2 types of sentences:
And RMC should have 'date' field non-empty