conv.go 2.2 KB
// Converter for Ubees-Tracker

package main

import (
	"bufio"
	"bytes"
	"encoding/binary"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"
	"strconv"
	"time"
)

type data struct {
	Time      uint32
	Msec      uint16
	Latitude  int32
	Longitude int32
	Checksum  uint16
}

const bytesPerLine = 128

var inputFileName string
var outputFileName string

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [OPTION] FILE\n", os.Args[0])
		flag.PrintDefaults()
	}

	flag.StringVar(&outputFileName, "o", "", "Specify output file path. Default is FILE.out")
	flag.Parse()

	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(2)
	}

	inputFileName = flag.Arg(0)

	if outputFileName == "" {
		outputFileName = inputFileName + ".out"
	}
}

func main() {
	fileIn, err := os.Open(inputFileName)
	check(err)

	defer fileIn.Close()

	fileOut, err := os.OpenFile(outputFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
	check(err)

	defer fileOut.Close()

	b := parse(fileIn)
	print(b, fileOut)
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func parse(r io.Reader) *bytes.Buffer {
	b := bytes.NewBuffer(nil)

	rLine := regexp.MustCompile(`:.*\|`)
	rByte := regexp.MustCompile(`[0-9A-Fa-f]{2}`)

	br := bufio.NewReader(r)
	for {
		l, _, err := br.ReadLine()
		if err != nil {
			if err == io.EOF {
				return b
			}

			log.Fatal(err)
		}

		mLine := rLine.Find(l)
		if mLine == nil {
			log.Printf("Line not matched %#v", string(l))
			continue
		}

		if bytes.HasPrefix(mLine, []byte(":FF")) {
			continue
		}

		mBytes := rByte.FindAll(mLine, -1)
		if len(mBytes) != bytesPerLine {
			log.Printf("Length not matched %v %#v\n", len(mBytes), string(l))
		}

		for _, mByte := range mBytes {
			i, err := strconv.ParseUint(string(mByte), 16, 8)
			check(err)

			b.WriteByte(byte(i))
		}
	}
}

func print(r io.Reader, w io.Writer) {
	bw := bufio.NewWriter(w)
	defer bw.Flush()

	var d data
	for {
		err := binary.Read(r, binary.LittleEndian, &d)
		if err != nil {
			if err == io.EOF {
				return
			}

			log.Fatal(err)
		}

		t := time.Unix(int64(d.Time), int64(d.Msec)*1e6)
		bw.WriteString(fmt.Sprintf("%v, %.4f, %.4f\n",
			t.Format("2006-01-02 15:04:05.000"),
			float64(d.Latitude)/10000,
			float64(d.Longitude)/10000))
	}
}