DXLite implemented as a Zero Message Queue (JSON)

dxlite is a popular little tool I wrote about 5 years ago, designed to provide lightweight HTML access to the latest DX Cluster spots. The number of pages served by DXLite is sometimes thousands an hour, mainly from mobile phone clients but also from PCs and Macs. DXLite has some minimal searching filters which are explained in the docs, so if you’ve never come across it before and wonder what the big deal is then you can start here.

What’s wrong with DXLite?

It’s certainly working as designed, but one of the biggest weaknessess of DXLite is the difficulty of making it useful and accessible to other programmers. I provide a handy XML version of the DX Cluster (rather easier to work with than the raw telnet streams), but this raises new problems. DXLite is based on clients pulling down spots periodically, but for practical reasons I don’t want people to call DXLite every second in order to get a “nearly real-time” cluster. However, DX spots are very much real-time information! What to do?

Making DXLite Synchronous

Essentially, DXLite is not synchronous with the DX Cluster and I can’t solve that problem without sacrificing the super-light nature of DXLite that has made it popular with mobile users. So, instead, I have been working on making a new variant of DXLite (written in Go, of course!) which is specifically designed for software developers to use. It doesn’t replace DXLite, but runs along side it.

Some of the server code was very interesting to write. A quick way to sum up what is does is roughly this:

  1. Connects to the CDXC DX Cluster via telnet
  2. Parses the telnet stream for DX spots (applying strong typing along the way)
  3. Obtains an MD5 hash of new spots, and uses this to de-duplicate the feed
  4. Uses the Club Log HTTP API to get the DXCC entity number for DX callsigns spotted
  5. Determines the band, based on the frequency of the spot
  6. Publishs a JSON version of the spot to 0MQ (see below)
  7. Inserts a row into a MySQL database (for use by Club Log)

As this is a persistent Go daemon, it is easy to expose it to the web and add extra “outlets” for the spot data, so the new Go-based DXLite server implements a TCP socket based Zero Message Queue (also known as 0MQ) to give direct, synchronous access to spot data in JSON format. I’ve picked these two technologies – 0MQ and JSON – because they are most appropriate to the problem of sharing a lot of synchronous messages with a wide range of client technologies, as well as being useful and easily-consumable technologies in Javascript and server-side languages.

Connection Details

  • 0MQ server address: clublog.org:7373
  • Published data: Synchronous, near real-time JSON spots

The data that is being presented in JSON originates in a struct internally in my server:

type DXSpot struct {
        Call    string
        Spotter string
        Comment string
        Freq    float64
        Band    int
        Dxcc    int
        Date    time.Time // This is a datatype for the Go time package
}

Once you have connected, here is an example of the output you will get from the server:


{"Call":"A45WH","Spotter":"EC7JA","Comment":"low , tu 73","Freq":18084,"Band":17,"Dxcc":370,"Date":"2013-09-14T18:20:41.342307Z"}
{"Call":"OE6JFG","Spotter":"SP8MTA","Comment":"CQ CQ in BPSK31","Freq":1839.6,"Band":160,"Dxcc":206,"Date":"2013-09-14T18:20:42.152273Z"}
{"Call":"AL9A","Spotter":"ON7ZJ","Comment":"Tnx for the contact","Freq":14274.6,"Band":20,"Dxcc":6,"Date":"2013-09-14T18:20:42.453337Z"}
{"Call":"EA5/OO4CAU/P","Spotter":"W5WMU","Comment":"","Freq":14154,"Band":20,"Dxcc":281,"Date":"2013-09-14T18:20:57.601895Z"}

As you can see, the calls, comments, frequency, band, DXCC country number (as looked up from Club Log) and the spot date are available, now in JSON format for ease of interoperability.

I’m assuming you’re a developer, and hoping you might be interested in having access to this (perhaps just to experiment, or perhaps because you’ve run into the problems I described with getting data out of DXLite as it stands). If you’re not sure about how to implement a 0MQ client, there are a lot of examples available in almost every popular language. The documentation for 0MQ is here: http://zguide.zeromq.org/page:all.

Example Client

To get you started, here is a simple Go client for the DXLite message queue:

package main

import (
        "fmt"
        zmq "github.com/alecthomas/gozmq"
        "os"
)

func main() {
        context, _ := zmq.NewContext()
        socket, _ := context.NewSocket(zmq.SUB)
        defer context.Close()
        defer socket.Close()

        var filter string

        // If you want, you can filter using this logic
        if len(os.Args) > 1 {
                filter := string(os.Args[1])
                socket.SetSockOptString(zmq.SUBSCRIBE, filter)
        } else {
                socket.SetSockOptString(zmq.SUBSCRIBE, "")
        }

        socket.SetSockOptString(zmq.SUBSCRIBE, filter)
        socket.Connect("tcp://clublog.org:7373")
        // A little more error handling would be advisable here.

        for {
                datapt, _ := socket.Recv(0)
                fmt.Printf("%s\n", string(datapt))
        }
}

This is all rather experimental at the moment but I’d be delighted to hear from you if you are planning to use this service – otherwise, it’s served a purpose for me (learning some more Go) and may get merged back into Club Log as a way to do the cluster-based filtering in some of the tools.

Coming up next, I will be starting on the Club Log DXCC lookup routine, armed with more knowledge of Go after this short project!

73,
Michael G7VJR

Comments are closed.