diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 8ada8b5..9815a2d 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -4,15 +4,15 @@ on: [push] jobs: build: + runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v2 - with: - submodules: "recursive" + - uses: actions/checkout@v1 - name: deps - run: | - sudo apt-get update - sudo apt-get install protobuf-compiler libh2o-dev libcurl4-openssl-dev libssl-dev libprotobuf-dev libh2o-evloop-dev libwslay-dev libncurses5-dev libeigen3-dev libzstd-dev libfec-dev libfmt-dev + run: sudo apt-get install protobuf-compiler libh2o-dev libcurl4-openssl-dev libssl-dev libprotobuf-dev libh2o-evloop-dev libwslay-dev libncurses5-dev libeigen3-dev libzstd-dev + - name: submodules + run: git submodule update --init --recursive - name: config run: echo WSLAY=-lwslay > Makefile.local - name: make diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index d5184c7..0000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Build and publish Docker image - -on: - push: - branches: master - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Checkout submodules - run: git submodule update --init --recursive - - name: Set up docker buildx - id: buildx - uses: crazy-max/ghaction-docker-buildx@v3 - with: - buildx-version: latest - qemu-version: latest - - name: Login to docker registry - run: | - docker login --username ${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_TOKEN }} - - name: Run buildx - run: | - docker buildx build \ - --tag berthubert/galmon \ - --platform linux/386,linux/amd64,linux/arm/v7,linux/arm64/v8 \ - --output "type=registry" \ - --build-arg MAKE_FLAGS=-j1 \ - --file Dockerfile \ - . diff --git a/Dockerfile b/Dockerfile index b212e55..7081bbc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,38 +1,25 @@ -# -# First stage - builder -# -FROM debian:10-slim AS builder +FROM ubuntu:disco ENV DEBIAN_FRONTEND noninteractive ENV LC_ALL C.UTF-8 -# This allows you to use a local Debian mirror -ARG APT_URL=http://deb.debian.org/debian/ -ARG MAKE_FLAGS=-j2 +# This allows you to use a local Ubuntu mirror +ARG APT_URL= +ENV APT_URL ${APT_URL:-http://archive.ubuntu.com/ubuntu/} +RUN sed -i "s%http://archive.ubuntu.com/ubuntu/%${APT_URL}%" /etc/apt/sources.list -RUN sed -i "s%http://deb.debian.org/debian/%${APT_URL}%" /etc/apt/sources.list \ - && apt-get update && apt-get -y upgrade \ - && apt-get install -y protobuf-compiler libh2o-dev libcurl4-openssl-dev \ - libssl-dev libprotobuf-dev libh2o-evloop-dev libwslay-dev \ - libeigen3-dev libzstd-dev libfmt-dev libncurses-dev \ - make gcc g++ git build-essential curl autoconf automake help2man + +# Update packages and install dependencies +RUN apt-get update && apt-get -y upgrade && apt-get -y clean +RUN apt-get install -y protobuf-compiler libh2o-dev libcurl4-openssl-dev \ + libssl-dev libprotobuf-dev libh2o-evloop-dev libwslay-dev libeigen3-dev libzstd-dev \ + make gcc g++ git build-essential curl autoconf automake libfmt-dev libncurses5-dev \ + && apt-get -y clean # Build -ADD . /galmon-src/ -RUN cd /galmon-src/ \ - && make $MAKE_FLAGS \ - && prefix=/galmon make install +ARG MAKE_FLAGS=-j2 +ADD . /galmon/ +WORKDIR /galmon/ +RUN make $MAKE_FLAGS +ENV PATH=/galmon:${PATH} -# -# Second stage - contains just the binaries -# -FROM debian:10-slim -RUN apt-get update && apt-get -y upgrade \ - && apt-get install -y libcurl4 libssl1.1 libprotobuf17 libh2o-evloop0.13 \ - libncurses6 \ - && apt-get -y clean \ - && rm -rf /var/lib/apt/lists/* -COPY --from=builder /galmon/ /galmon/ -ENV PATH=/galmon/bin:${PATH} -ENV LC_ALL C.UTF-8 -WORKDIR /galmon/bin diff --git a/Dockerfile-pi b/Dockerfile-pi new file mode 100644 index 0000000..c55f030 --- /dev/null +++ b/Dockerfile-pi @@ -0,0 +1,18 @@ +#FROM ubuntu:disco +FROM arm32v7/debian:unstable + +ENV DEBIAN_FRONTEND noninteractive +ENV LC_ALL C.UTF-8 + +# Update packages and install dependencies +RUN apt-get update && apt-get -y upgrade && apt-get -y clean +RUN apt-get install -y protobuf-compiler libh2o-dev libcurl4-openssl-dev \ + libssl-dev libprotobuf-dev libh2o-evloop-dev libwslay-dev libeigen3-dev libzstd-dev \ + make clang-9 git build-essential curl autoconf automake libfmt-dev libncurses5-dev \ + && apt-get -y clean + +# Build +ADD . /galmon/ +WORKDIR /galmon/ +RUN make +ENV PATH=/galmon:${PATH} diff --git a/Makefile b/Makefile index 075d143..ebf2c4b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CFLAGS = -O3 -Wall -ggdb -CXXFLAGS:= -std=gnu++17 -Wall -O3 -ggdb -MMD -MP -fno-omit-frame-pointer -Iext/CLI11 \ - -Iext/powerblog/ext/simplesocket -Iext/powerblog/ext/ \ +CXXFLAGS:= -std=gnu++17 -Wall -O0 -ggdb -MMD -MP -fno-omit-frame-pointer -Iext/CLI11 \ + -Iext/fmt-6.1.2/include/ -Iext/powerblog/ext/simplesocket -Iext/powerblog/ext/ \ -I/usr/local/opt/openssl/include/ \ -Iext/sgp4/libsgp4/ \ -I/usr/local/include @@ -21,10 +21,11 @@ else ifneq (,$(wildcard ubxsec.o)) EXTRADEP = ubxsec.o endif + CHEAT_ARG := $(shell ./update-git-hash-if-necessary) PROGRAMS = navparse ubxtool navnexus navcat navrecv navdump testrunner navdisplay tlecatch reporter sp3feed \ - galmonmon rinreport rinjoin rtcmtool gndate septool navmerge + galmonmon rinreport rtcmtool all: navmon.pb.cc $(PROGRAMS) @@ -39,12 +40,12 @@ navmon.pb.cc: navmon.proto protoc --cpp_out=./ navmon.proto +H2OPP=ext/powerblog/h2o-pp.o SIMPLESOCKETS=ext/powerblog/ext/simplesocket/swrappers.o ext/powerblog/ext/simplesocket/sclasses.o ext/powerblog/ext/simplesocket/comboaddress.o - clean: - rm -f *~ *.o *.d ext/*/*.o ext/*/*.d $(PROGRAMS) navmon.pb.h navmon.pb.cc $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) $(SIMPLESOCKETS) - rm -f ext/sgp4/libsgp4/*.d ext/powerblog/ext/simplesocket/*.d + rm -f *~ *.o *.d ext/*/*.o ext/*/*.d $(PROGRAMS) navmon.pb.h navmon.pb.cc $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) $(H2OPP) $(SIMPLESOCKETS) + rm -f ext/fmt-6.1.2/src/format.[do] ext/sgp4/libsgp4/*.d ext/powerblog/ext/simplesocket/*.d help2man: $(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/share/man/man1 @@ -62,76 +63,69 @@ install: $(PROGRAMS) help2man mkdir -p $(DESTDIR)$(prefix)$(htdocs)/galmon cp -a html $(DESTDIR)$(prefix)$(htdocs)/galmon/ -decrypt: decrypt.o bits.o - $(CXX) -std=gnu++17 $^ -o $@ -lfmt +download-debian-package: + apt-key adv --fetch-keys https://ota.bike/public-package-signing-keys/86E7F51C04FBAAB0.asc + echo "deb https://ota.bike/debian/ buster main" > /etc/apt/sources.list.d/galmon.list + apt-get update && apt-get install -y galmon -navparse: navparse.o $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o trkmeas.o influxpush.o ${EXTRADEP} githash.o sbas.o rtcm.o galileo.o - $(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -L/usr/local/opt/openssl/lib/ -lz -lcurl -lprotobuf -lfmt +download-raspbian-package: + apt-key adv --fetch-keys https://ota.bike/public-package-signing-keys/86E7F51C04FBAAB0.asc + echo "deb https://ota.bike/raspbian/ buster main" > /etc/apt/sources.list.d/galmon.list + apt-get update && apt-get install -y galmon -reporter: reporter.o $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o githash.o influxpush.o - $(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -lprotobuf -lcurl -lfmt +decrypt: decrypt.o bits.o ext/fmt-6.1.2/src/format.o + $(CXX) -std=gnu++17 $^ -o $@ -sp3feed: sp3feed.o $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o influxpush.o githash.o sp3.o - $(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -lprotobuf -lcurl -lfmt +navparse: navparse.o ext/fmt-6.1.2/src/format.o $(H2OPP) $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o trkmeas.o influxpush.o ${EXTRADEP} githash.o sbas.o rtcm.o + $(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -L/usr/local/opt/openssl/lib/ -lh2o-evloop -lssl -lcrypto -lz -lcurl -lprotobuf $(WSLAY) + +reporter: reporter.o ext/fmt-6.1.2/src/format.o $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o githash.o + $(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -lprotobuf -lcurl + +sp3feed: sp3feed.o ext/fmt-6.1.2/src/format.o $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o influxpush.o githash.o sp3.o + $(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -lprotobuf -lcurl -tracker: tracker.o $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o githash.o - $(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -lprotobuf -lcurl -lfmt +tracker: tracker.o ext/fmt-6.1.2/src/format.o $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o githash.o + $(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -lprotobuf -lcurl -galmonmon: galmonmon.o $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o githash.o - $(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -lprotobuf -lcurl -lfmt +galmonmon: galmonmon.o ext/fmt-6.1.2/src/format.o $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o githash.o + $(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -lprotobuf -lcurl -# rs.o fixhunter.o -navdump: navdump.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o navmon.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o sp3.o osen.o trkmeas.o githash.o rinex.o sbas.o rtcm.o galileo.o ${EXTRADEP} - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -lz -lfmt -# -lfec +navdump: navdump.o ext/fmt-6.1.2/src/format.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o navmon.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o sp3.o osen.o trkmeas.o githash.o rinex.o sbas.o rtcm.o ${EXTRADEP} + $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -lz -navdisplay: navdisplay.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o ephemeris.o navmon.o osen.o githash.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -lncurses -lfmt +navdisplay: navdisplay.o ext/fmt-6.1.2/src/format.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o ephemeris.o navmon.o osen.o githash.o + $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -lncurses -navnexus: navnexus.o $(SIMPLESOCKETS) bits.o navmon.pb.o storage.o githash.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -lfmt +navnexus: navnexus.o ext/fmt-6.1.2/src/format.o $(SIMPLESOCKETS) ubx.o bits.o navmon.pb.o storage.o githash.o + $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -navcat: navcat.o $(SIMPLESOCKETS) ubx.o bits.o navmon.pb.o storage.o navmon.o githash.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -lfmt +navcat: navcat.o ext/fmt-6.1.2/src/format.o $(SIMPLESOCKETS) ubx.o bits.o navmon.pb.o storage.o navmon.o githash.o + $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -navrecv: navrecv.o $(SIMPLESOCKETS) navmon.pb.o storage.o githash.o zstdwrap.o navmon.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -lzstd -lfmt - -navmerge: navmerge.o $(SIMPLESOCKETS) navmon.pb.o storage.o githash.o zstdwrap.o navmon.o nmmsender.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -lzstd -lfmt - +navrecv: navrecv.o ext/fmt-6.1.2/src/format.o $(SIMPLESOCKETS) navmon.pb.o storage.o githash.o zstdwrap.o navmon.o + $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -lzstd tlecatch: tlecatch.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) githash.o $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -rinreport: rinreport.o rinex.o githash.o navmon.o ephemeris.o osen.o - $(CXX) -std=gnu++17 $^ -o $@ -lz -pthread -lfmt +rinreport: rinreport.o rinex.o githash.o navmon.o ext/fmt-6.1.2/src/format.o ephemeris.o osen.o + $(CXX) -std=gnu++17 $^ -o $@ -lz -pthread -rinjoin: rinjoin.o rinex.o githash.o navmon.o ephemeris.o osen.o - $(CXX) -std=gnu++17 $^ -o $@ -lz -pthread -lfmt +rtcmtool: rtcmtool.o navmon.pb.o githash.o ext/fmt-6.1.2/src/format.o bits.o nmmsender.o $(SIMPLESOCKETS) navmon.o rtcm.o zstdwrap.o + $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lz -pthread -lprotobuf -lzstd -rtcmtool: rtcmtool.o navmon.pb.o githash.o bits.o nmmsender.o $(SIMPLESOCKETS) navmon.o rtcm.o zstdwrap.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lz -pthread -lprotobuf -lzstd -lfmt +ubxtool: navmon.pb.o ubxtool.o ubx.o bits.o ext/fmt-6.1.2/src/format.o galileo.o gps.o beidou.o navmon.o ephemeris.o $(SIMPLESOCKETS) osen.o githash.o nmmsender.o zstdwrap.o + $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf -pthread -lzstd - -ubxtool: navmon.pb.o ubxtool.o ubx.o bits.o galileo.o gps.o beidou.o navmon.o ephemeris.o $(SIMPLESOCKETS) osen.o githash.o nmmsender.o zstdwrap.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf -pthread -lzstd -lfmt - -septool: navmon.pb.o septool.o bits.o galileo.o gps.o beidou.o navmon.o ephemeris.o $(SIMPLESOCKETS) osen.o githash.o nmmsender.o zstdwrap.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf -pthread -lzstd -lfmt - - -testrunner: navmon.pb.o testrunner.o ubx.o bits.o galileo.o gps.o beidou.o ephemeris.o sp3.o osen.o navmon.o rinex.o githash.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf -lz -pthread -lfmt - -gndate: gndate.o githash.o navmon.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lfmt +testrunner: navmon.pb.o testrunner.o ubx.o bits.o ext/fmt-6.1.2/src/format.o galileo.o gps.o beidou.o ephemeris.o sp3.o osen.o navmon.o rinex.o githash.o + $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf -lz check: testrunner ./testrunner diff --git a/README.md b/README.md index 9eedc99..e53f083 100644 --- a/README.md +++ b/README.md @@ -4,17 +4,14 @@ galileo/GPS/GLONASS/BeiDou open source monitoring. GPL3 licensed. Live website: https://galmon.eu/ -Multi-vendor, with support for U-blox 8 and 9 chipsets and many Septentrio -devices. Navilock NL-8012U receiver works really well, as does the U-blox -evaluation kit for the 8MT. In addition, many stations have reported -success with this very cheap [AliExpress sourced -device](https://www.aliexpress.com/item/32816656706.html). - -For ublox, there is good support for the F9P, several of us use the -[ArdusimpleRTK2B](https://www.ardusimple.com/simplertk2b/) board. It adds -the Galileo E5b band. - -Septentrio devices support even more bands. +Theoretically multi-vendor, although currently only the U-blox 8 and 9 +chipsets are supported. Navilock NL-8012U receiver works really well, as +does the U-blox evaluation kit for the 8MT. In addition, many stations have +reported success with this very cheap [AliExpress sourced +device](https://www.aliexpress.com/item/32816656706.html). The best and +most high-end receiver, which does all bands, all the time, is the Ublox +F9P, several of us use the +[ArdusimpleRTK2B](https://www.ardusimple.com/simplertk2b/) board. An annotated presentation about our project aimed at GNSS professionals can be found [here](https://berthub.eu/galileo/The%20galmon.eu%20project.pdf). @@ -27,15 +24,14 @@ be found [here](https://berthub.eu/galileo/The%20galmon.eu%20project.pdf). To deliver data to the project, please read [The Galmon GNSS Monitoring Project](https://berthub.eu/articles/posts/galmon-project/) and consult the rules outlined in [the operator -guidelines](https://github.com/berthubert/galmon/blob/master/Operator.md). +guidelines](https://github.com/ahupowerdns/galmon/blob/master/Operator.md). Highlights ---------- - * Support for Septentrio and U-blox. * Processes raw frames/strings/words from GPS, GLONASS, BeiDou and Galileo - * All-band support (E1, E5a, E5b, B1I, B2I, Glonass L1, Glonass L2, GPS L1C/A) - so far. + * All-band support (E1, E5b, B1I, B2I, Glonass L1, Glonass L2, GPS L1C/A) + so far, GPS L2C and Galileo E5a pending). * Calculate ephemeris positions * Comparison of ephemerides to independent SP3 data to determine SISE * Globally, locally, worst user location @@ -53,7 +49,7 @@ Highlights Data is made available as JSON, as a user-friendly website and as a time-series database. This time-series database is easily mated to the industry standard Matplotlib/Pandas/Jupyter combination (details -[here](https://github.com/berthubert/galmon/blob/master/influxdb.md). +[here](https://github.com/ahupowerdns/galmon/blob/master/influxdb.md). There is also tooling to extract raw frames/strings/words from specific timeframes. @@ -72,8 +68,8 @@ Goals: Works on Linux (including Raspbian Buster on Pi Zero W), OSX and OpenBSD. -Build locally (Linux, Debian, Ubuntu) -------------------------------------- +Build locally +------------- To get started, make sure you have a C++17 compiler (like g++ 8 or higher), git, protobuf-compiler. Then run 'make ubxtool navdump' to build the @@ -82,64 +78,43 @@ receiver-only tools. To build everything, including the webserver, try: ``` -apt-get install protobuf-compiler libcurl4-openssl-dev libssl-dev libprotobuf-dev \ -libncurses5-dev libeigen3-dev libzstd-dev g++ libfmt-dev -git clone https://github.com/berthubert/galmon.git --recursive +apt-get install protobuf-compiler libh2o-dev libcurl4-openssl-dev libssl-dev libprotobuf-dev \ +libh2o-evloop-dev libwslay-dev libncurses5-dev libeigen3-dev libzstd-dev +git clone https://github.com/ahupowerdns/galmon.git --recursive cd galmon make ``` -Building on OSX +If this doesn't succeed with an error about h2o, make sure you have this +library installed. If you get an error about 'wslay', do the following, and run make again: + +``` +echo WSLAY=-lwslay > Makefile.local +``` + +Build in Docker --------------- -With thanks to a contributor from Prague. First make sure you've installed -brew, which you can get [here](https://brew.sh/). Then do: + +To build it in Docker: ``` -brew install protobuf lzlib zstd eigen +git clone https://github.com/ahupowerdns/galmon.git --recursive +docker build -t galmon --build-arg MAKE_FLAGS=-j2 . ``` -And then: -``` -git clone https://github.com/berthubert/galmon.git --recursive -cd galmon -make -``` - -Running in Docker ------------------ - -We publish official Docker images for galmon on -[docker hub](https://hub.docker.com/r/berthubert/galmon) for multiple architectures. - -To run a container with a shell in there (this will also expose a port so you -can view the UI too and assumes a ublox GPS device too - -you may need to tweak as necessary): +To run a container with a shell in there (this will also expose a port so you can view the UI too and assumes a ublox GPS device too - you may need to tweak as necessary): ``` -docker run -it --rm --device=/dev/ttyACM0 -p 10000:10000 berthubert/galmon +docker run -it --rm --device=/dev/ttyACM0 -p 10000:10000 galmon ``` -Running a daemonized docker container reporting data to a remote server -might look like: - -``` -docker run -d --restart=always --device=/dev/ttyACM0 --name=galmon berthubert/galmon ubxtool --wait --port /dev/ttyACM0 --gps --galileo --glonass --destination [server] --station [station-id] --owner [owner] -``` - -To make your docker container update automatically you could use a tool such as -[watchtower](https://containrrr.github.io/watchtower/). Running ------- -On u-blox: + Once compiled, run for example `./ubxtool --wait --port /dev/ttyACM0 --station 1 --stdout --galileo | ./navparse --bind [::1]:10000` -For Septentrio, try: `nc 192.168.1.1 29000 | ./septool --station x --stdout | -./navparse --bind [::1]:10000`, assuming your Septentrio can be reached on -192.168.1.1.1 and you have defined an SBF stream on port 29000. For more -details, please see below. - Next up, browse to http://[::1]:10000 (or try http://localhost:10000/ and you should be in business. ubxtool changes (non-permanently) the configuration of your u-blox receiver so it emits the required frames for @@ -174,13 +149,9 @@ to stdout, add `--stdout`. Tooling: - * ubxtool: can configure a u-blox 8/9/10 chipset, parses its output & will + * ubxtool: can configure a u-blox 8 chipset, parses its output & will convert it into a protbuf stream of GNSS NAV frames + metadata Adds 64-bit timestamps plus origin information to each message - * septool: ingests the Septentrio binary format (SBF) and converts it to our - protobuf format. Supports same protocol as ubxtool. - * rtcmtool: ingest ntripclient output, decodes RTCM messages and converts - them to our protobuf format * xtool: if you have another chipset, build something that extracts NAV frames & metadata. Not done yet. * navrecv: receives GNSS NAV frames and stores them on disk, split out per @@ -193,11 +164,6 @@ Tooling: computations on ephemerides. * grafana dashboard: makes pretty graphs -Per device notes ----------------- -The "SparkFun GNSS L1/L5 Breakout - NEO-F10N, SMA" needs '-u1 -b 38400 ---wait'. - Linux Systemd ------------- First make sure 'ubxtool' has been compiled (run: make ubxtool). Then, as @@ -256,47 +222,6 @@ This also works for `navparse` for the pretty website and influx storage, `nc 12 if you have an influxdb running on localhost with a galileo database in there. The default URL is http://127.0.0.1:29599/ -Septentrio specifics --------------------- -Unlike `ubxtool`, our `septool` does not (re)configure your Septentrio -device. Instead, the tool expects Septentrio Binary Format (SBF) on input, -and that this stream includes at least the following messages: - - * MeasEpoch - * PVTCartesian - -We currently parse and understand: - * GALRawFNAV - * GALRawINAV - -Support will be added soon for: - * GPSRawCA - * GPSRawL2C - * GPSRawL5 - * GLORawCA - * BDSRaw - * BDSRawB1C - * BDSRawB2a - -A typical invocation of `septool` looks like this: - -``` -nc 192.168.1.1 29000 | ./septool --station x --destination galmon-eu-server.example.com -``` - -Or to test, try: - -``` -nc 192.168.1.1 29000 | ./septool --station x --stdout | ./navdump -``` - -This is assuming that you can reach your Septentrio on 192.168.1.1 and that -you have defined a TCP server stream on port 29000. - -Septool will also accept input from a serial port or basically anything that -can provide SBF. Please let us know if our tooling can make your life -easier. - Internals --------- The transport format consists of repeats of: @@ -321,10 +246,9 @@ Documents * [GLONASS CDMA](http://russianspacesystems.ru/wp-content/uploads/2016/08/ICD-GLONASS-CDMA-General.-Edition-1.0-2016.pdf) not actually relevant for the CDMA aspects, but has appendices on more precise orbit determinations. - * [GPS](https://www.navcen.uscg.gov/sites/default/files/pdf/gps/IS-GPS-200N.pdf) + * [GPS](https://www.gps.gov/technical/icwg/IS-GPS-200K.pdf) * [U-blox 8 interface specification](https://www.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_%28UBX-13003221%29_Public.pdf) * [U-blox 9 interface specification](https://www.u-blox.com/sites/default/files/u-blox_ZED-F9P_InterfaceDescription_%28UBX-18010854%29.pdf) - * [U-blox 10 interface specification](https://content.u-blox.com/sites/default/files/documents/u-blox-F10-SPG-6.00_InterfaceDescription_UBX-23002975.pdf) * [U-blox 9 integration manual](https://www.u-blox.com/sites/default/files/ZED-F9P_IntegrationManual_%28UBX-18010802%29.pdf) Data sources @@ -344,39 +268,17 @@ The software can interpret SP3 files, good sources: to have less of a delay than the ESA ESM series. * GBU = ultra rapid, still a few days delay, but much more recent. -To get SP3 GBM from GFZ Potsdam for GPS week number 2111: - -``` -WN=2111 -lftp -c "mget ftp://ftp.gfz-potsdam.de/GNSS/products/mgnss/${WN}/gbm*sp3.Z" -gunzip gbm*sp3.Z -``` - -To feed data, use: - -``` -./sp3feed --sp3src=gbm --influxdb=galileo gbm*sp3 -``` - -This will populate the sp3 tables in the database. A subsequent run of -`reporter`, while setting the `--sp3src` parameter, will provide SP3 -deviation statistics, and fill out the `sp3delta` table in there, which -stores deviations from the SP3 provided position, per sp3src. - -Further interesting (ephemeris) data is on http://mgex.igs.org/IGS_MGEX_Products.php +Uncompress and concatenate all downloaded files into 'all.sp3' and run +'navdump ' on collected protobuf, and it will output 'sp3.csv' with fit data. RTCM ---- RTCM is the Radio Technical Commission for Maritime Services, and -confusingly, also the name of a protocol. - -This protocol is proprietary, but search for a file called `RTCM3.2.pdf` or -`104-2013-SC104-STD - Vers. 3.2.docx` and you might find a copy. - -This project can parse RTCM 10403.1 messages, and currently processes State -Space Representation (SSR) messages, specifically types 1057/1240 -(GPS/Galileo Orbit corrections to broadcast ephemeris) and 1058/1241 -(GPS/Galileo Clock corrections to broadcast ephemeris). +confusingly, also the name of a protocol. This project can parse RTCM 10403.1 +messages, and currently processes State Space Representation (SSR) messages, +specifically types 1057/1240 (GPS/Galileo Orbit corrections to broadcast +ephemeris) and 1058/1241 (GPS/Galileo Clock corrections to broadcast +ephemeris). RTCM messages need to be converted to protobuf format, and the `rtcmtool` is provided for this purpose. @@ -390,17 +292,6 @@ $ ntripclient ntrip:CLKA0_DEU1/user:password@navcast.spaceopal.com:2101 | ./rtcm User and password can be obtained from https://spaceopal.com/navcast/ - the Galileo operating company. -The IGS also offers excellent streams, but without Galileo. Information is -[here](http://www.igs.org/rts/products). A typical commandline is: - -``` -$ ntripclient ntrip:IGS01/user:password@products.igs-ip.net:2101 | ./rtcmtool --station x --destination y -``` - -User and password can be requested through http://www.igs.org/rts/access - -An interesting list is here: http://products.igs-ip.net/ - There are many other sources of RTCM but currently not many offer the SSR messages we can use. diff --git a/beidou.cc b/beidou.cc index 1a56664..bb896d2 100644 --- a/beidou.cc +++ b/beidou.cc @@ -1,8 +1,6 @@ #include "beidou.hh" #include "bits.hh" #include -#include -#include "navmon.hh" using namespace std; @@ -31,7 +29,7 @@ static int checkbds(int bits) return 1; } -std::vector getCondensedBeidouMessage(const std::vector& payload) +std::basic_string getCondensedBeidouMessage(std::basic_string_view payload) { // payload consists of 32 bit words where we have to ignore the first 2 bits of every word @@ -58,7 +56,7 @@ std::vector getCondensedBeidouMessage(const std::vector& paylo setbitu(buffer, 26+22*(w-1), 22, getbitu(&payload[0], 2 + w*32, 22)); } - return makeVec(buffer, 28); + return std::basic_string(buffer, 28); } diff --git a/beidou.hh b/beidou.hh index b98daeb..0276a6f 100644 --- a/beidou.hh +++ b/beidou.hh @@ -4,10 +4,9 @@ #include "bits.hh" #include #include -#include #include "ephemeris.hh" -std::vector getCondensedBeidouMessage(const std::vector& payload); +std::basic_string getCondensedBeidouMessage(std::basic_string_view payload); int beidouBitconv(int their); /* Geostationary, so D2, so not to be parsed by this parser: @@ -22,7 +21,7 @@ struct BeidouMessage : GPSLikeEphemeris { uint8_t strtype; - std::vector g_cond; + std::basic_string_view g_cond; int bbitu(int bit, int len) { return getbitu(&g_cond[0], beidouBitconv(bit), len); @@ -35,7 +34,7 @@ struct BeidouMessage : GPSLikeEphemeris int fraid{-1}, sow{-1}; // part of every message (thanks!) - int parse(const std::vector& cond, uint8_t* pageno) + int parse(std::basic_string_view cond, uint8_t* pageno) { g_cond = cond; if(pageno) @@ -90,7 +89,7 @@ struct BeidouMessage : GPSLikeEphemeris return {factor * cur, factor * trend}; } - void parse1(const std::vector& cond) + void parse1(std::basic_string_view cond) { sath1 = bbitu(43,1); aodc = bbitu(31+13, 5); @@ -125,7 +124,7 @@ struct BeidouMessage : GPSLikeEphemeris return -1; } - void parse2(const std::vector& cond) + void parse2(std::basic_string_view cond) { deltan = bbits(43, 16); cuc = bbits(67, 18); @@ -152,7 +151,7 @@ struct BeidouMessage : GPSLikeEphemeris double getOmega0() const { return ldexp(Omega0 * M_PI, -31); } // radians double getIdot() const { return ldexp(idot * M_PI, -43); } // radians/s double getOmega() const { return ldexp(omega * M_PI, -31); } // radians - void parse3(const std::vector& cond) + void parse3(std::basic_string_view cond) { t0eLSB = bbitu(43, 15); i0 = bbits(66, 32); @@ -208,7 +207,7 @@ struct BeidouMessage : GPSLikeEphemeris } alma; // 4 is all almanac - int parse4(const std::vector& cond) + int parse4(std::basic_string_view cond) { alma.sqrtA = bbitu(51, 24); alma.a1 = bbits(91, 11); @@ -229,8 +228,7 @@ struct BeidouMessage : GPSLikeEphemeris // 2^-30 2^-50 int a0gps, a1gps, a0gal, a1gal, a0glo, a1glo, a0utc, a1utc; - int8_t deltaTLS, deltaTLSF; - uint8_t wnLSF, dn; + int8_t deltaTLS; // in Beidou the offset is a0utc + SOW * a1utc std::pair getUTCOffset(int tow) const @@ -255,7 +253,7 @@ struct BeidouMessage : GPSLikeEphemeris } - int parse5(const std::vector& cond) + int parse5(std::basic_string_view cond) { alma.pageno = bbitu(44, 7); if(alma.pageno == 9) { @@ -270,9 +268,6 @@ struct BeidouMessage : GPSLikeEphemeris a0utc = bbits(91, 32); a1utc = bbits(131, 24); deltaTLS = bbits(31+12+1+7, 8); - deltaTLSF = bbits(61+6, 8); - wnLSF = bbits(61+6+8, 8); - dn = bbits(151+12, 8); } else { alma.sqrtA = bbitu(51, 24); diff --git a/coverage.cc b/coverage.cc index f879621..9392761 100644 --- a/coverage.cc +++ b/coverage.cc @@ -87,7 +87,6 @@ covmap_t emitCoverage(const vector& sats) double phi = M_PI* latitude / 180; double longsteps = 1 + 360.0 * cos(phi); double step = 4*180.0 / longsteps; - // this does sorta equi-distanced measurements vector> latvect; for(double longitude = -180; longitude < 180; longitude += step) { // east - west Point p; diff --git a/ephemeris.hh b/ephemeris.hh index e3eb174..5b6eaae 100644 --- a/ephemeris.hh +++ b/ephemeris.hh @@ -89,7 +89,7 @@ double getCoordinates(double tow, const T& iod, Point* p, bool quiet=true) cerr << "sqrtA = "<< sqrtA << endl; cerr << "deltan = "<< deltan << endl; - cerr << "t0e = "<< t0e << "( rel "<<(tow - t0e)<<")"< -#include +#include #include #include -#include #include #include #include @@ -20,49 +16,28 @@ #include // CLI Library includes -#include "ConfigFwd.hpp" -#include "Error.hpp" -#include "FormatterFwd.hpp" -#include "Macros.hpp" -#include "Option.hpp" -#include "Split.hpp" -#include "StringTools.hpp" -#include "TypeTools.hpp" +#include "CLI/Error.hpp" +#include "CLI/Ini.hpp" +#include "CLI/Option.hpp" +#include "CLI/Split.hpp" +#include "CLI/StringTools.hpp" +#include "CLI/TypeTools.hpp" namespace CLI { -#ifndef CLI11_PARSE -#define CLI11_PARSE(app, argc, argv) \ - try { \ - (app).parse((argc), (argv)); \ - } catch(const CLI::ParseError &e) { \ - return (app).exit(e); \ - } -#endif - namespace detail { -enum class Classifier { NONE, POSITIONAL_MARK, SHORT, LONG, WINDOWS, SUBCOMMAND, SUBCOMMAND_TERMINATOR }; +enum class Classifer { NONE, POSITIONAL_MARK, SHORT, LONG, SUBCOMMAND }; struct AppFriend; -} // namespace detail - -namespace FailureMessage { -std::string simple(const App *app, const Error &e); -std::string help(const App *app, const Error &e); -} // namespace FailureMessage - -/// enumeration of modes of how to deal with extras in config files - -enum class config_extras_mode : char { error = 0, ignore, capture }; +} // namespace detail class App; -using App_p = std::shared_ptr; +using App_p = std::unique_ptr; -class Option_group; /// Creates a command line program, with very few defaults. /** To use, create a new `Program()` instance with `argc`, `argv`, and a help description. The templated - * add_option methods make it easy to prepare options. Remember to call `.start` before starting your - * program, so that the options can be evaluated and the help option doesn't accidentally run your program. */ +* add_option methods make it easy to prepare options. Remember to call `.start` before starting your +* program, so that the options can be evaluated and the help option doesn't accidentally run your program. */ class App { friend Option; friend detail::AppFriend; @@ -73,216 +48,87 @@ class App { /// @name Basics ///@{ - /// Subcommand name or program name (from parser if name is empty) - std::string name_{}; + /// Subcommand name or program name (from parser) + std::string name_{"program"}; /// Description of the current program/subcommand - std::string description_{}; + std::string description_; - /// If true, allow extra arguments (ie, don't throw an error). INHERITABLE + /// If true, allow extra arguments (ie, don't throw an error). bool allow_extras_{false}; - /// If ignore, allow extra arguments in the ini file (ie, don't throw an error). INHERITABLE - /// if error error on an extra argument, and if capture feed it to the app - config_extras_mode allow_config_extras_{config_extras_mode::ignore}; - - /// If true, return immediately on an unrecognized option (implies allow_extras) INHERITABLE + /// If true, return immediatly on an unrecognised option (implies allow_extras) bool prefix_command_{false}; - /// If set to true the name was automatically generated from the command line vs a user set name - bool has_automatic_name_{false}; - - /// If set to true the subcommand is required to be processed and used, ignored for main app - bool required_{false}; - - /// If set to true the subcommand is disabled and cannot be used, ignored for main app - bool disabled_{false}; - - /// Flag indicating that the pre_parse_callback has been triggered - bool pre_parse_called_{false}; - - /// Flag indicating that the callback for the subcommand should be executed immediately on parse completion which is - /// before help or ini files are processed. INHERITABLE - bool immediate_callback_{false}; - - /// This is a function that runs prior to the start of parsing - std::function pre_parse_callback_{}; - - /// This is a function that runs when parsing has finished. - std::function parse_complete_callback_{}; - /// This is a function that runs when all processing has completed - std::function final_callback_{}; + /// This is a function that runs when complete. Great for subcommands. Can throw. + std::function callback_; ///@} /// @name Options ///@{ - /// The default values for options, customizable and changeable INHERITABLE - OptionDefaults option_defaults_{}; - /// The list of options, stored locally - std::vector options_{}; + std::vector options_; - ///@} - /// @name Help - ///@{ - - /// Footer to put after all options in the help output INHERITABLE - std::string footer_{}; - - /// This is a function that generates a footer to put after all other options in help output - std::function footer_callback_{}; - - /// A pointer to the help flag if there is one INHERITABLE + /// A pointer to the help flag if there is one Option *help_ptr_{nullptr}; - /// A pointer to the help all flag if there is one INHERITABLE - Option *help_all_ptr_{nullptr}; - - /// This is the formatter for help printing. Default provided. INHERITABLE (same pointer) - std::shared_ptr formatter_{new Formatter()}; - - /// The error message printing function INHERITABLE - std::function failure_message_{FailureMessage::simple}; - ///@} /// @name Parsing ///@{ - using missing_t = std::vector>; + using missing_t = std::vector>; /// Pair of classifier, string for missing options. (extra detail is removed on returning from parse) /// /// This is faster and cleaner than storing just a list of strings and reparsing. This may contain the -- separator. - missing_t missing_{}; + missing_t missing_; - /// This is a list of pointers to options with the original parse order - std::vector