Question

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?

Was it helpful?

Solution 2

and finally, if you want gpsd working, you should provide at least 2 types of sentences:

  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");

And RMC should have 'date' field non-empty

OTHER TIPS

I'm an idiot. I have forgotten to add "\r\n" to the sentence before write and flush it. With this addition everything works.

The thing that guided me was the gpsfeed+ GPS simulator (http://gpsfeed.sourceforge.net/) feed consumed by gpsd with debug level 8. It showed that chars in the accepted sentence and displayed that such sentences are okay for gpsfeed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top