Compare commits
2
.github/workflows/ccpp.yml
vendored
|
|
@ -6,7 +6,7 @@ jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: "recursive"
|
submodules: "recursive"
|
||||||
- name: deps
|
- name: deps
|
||||||
|
|
|
||||||
10
.github/workflows/docker.yml
vendored
|
|
@ -9,15 +9,15 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v2
|
||||||
- name: Checkout submodules
|
- name: Checkout submodules
|
||||||
run: git submodule update --init --recursive
|
run: git submodule update --init --recursive
|
||||||
- name: Set up docker qemu
|
|
||||||
id: qemu
|
|
||||||
uses: docker/setup-qemu-action@v4
|
|
||||||
- name: Set up docker buildx
|
- name: Set up docker buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
uses: docker/setup-buildx-action@v4
|
uses: crazy-max/ghaction-docker-buildx@v3
|
||||||
|
with:
|
||||||
|
buildx-version: latest
|
||||||
|
qemu-version: latest
|
||||||
- name: Login to docker registry
|
- name: Login to docker registry
|
||||||
run: |
|
run: |
|
||||||
docker login --username ${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_TOKEN }}
|
docker login --username ${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_TOKEN }}
|
||||||
|
|
|
||||||
17
Dockerfile
|
|
@ -3,18 +3,18 @@
|
||||||
#
|
#
|
||||||
FROM debian:10-slim AS builder
|
FROM debian:10-slim AS builder
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
ENV LC_ALL=C.UTF-8
|
ENV LC_ALL C.UTF-8
|
||||||
|
|
||||||
# This allows you to use a local Debian mirror
|
# This allows you to use a local Debian mirror
|
||||||
ARG APT_URL=http://archive.debian.org/debian
|
ARG APT_URL=http://deb.debian.org/debian/
|
||||||
ARG MAKE_FLAGS=-j2
|
ARG MAKE_FLAGS=-j2
|
||||||
|
|
||||||
RUN sed -i "s%http://deb.debian.org/debian%${APT_URL}%" /etc/apt/sources.list
|
RUN sed -i "s%http://deb.debian.org/debian/%${APT_URL}%" /etc/apt/sources.list \
|
||||||
RUN apt-get update && apt-get -y upgrade \
|
&& apt-get update && apt-get -y upgrade \
|
||||||
&& apt-get install -y protobuf-compiler libh2o-dev libcurl4-openssl-dev \
|
&& apt-get install -y protobuf-compiler libh2o-dev libcurl4-openssl-dev \
|
||||||
libssl-dev libprotobuf-dev libh2o-evloop-dev libwslay-dev \
|
libssl-dev libprotobuf-dev libh2o-evloop-dev libwslay-dev \
|
||||||
libeigen3-dev libzstd-dev libfmt-dev libncurses-dev libfmt-dev \
|
libeigen3-dev libzstd-dev libfmt-dev libncurses-dev \
|
||||||
make gcc g++ git build-essential curl autoconf automake help2man
|
make gcc g++ git build-essential curl autoconf automake help2man
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
|
|
@ -27,9 +27,6 @@ RUN cd /galmon-src/ \
|
||||||
# Second stage - contains just the binaries
|
# Second stage - contains just the binaries
|
||||||
#
|
#
|
||||||
FROM debian:10-slim
|
FROM debian:10-slim
|
||||||
|
|
||||||
COPY --from=builder /etc/apt/sources.list /etc/apt/sources.list
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get -y upgrade \
|
RUN apt-get update && apt-get -y upgrade \
|
||||||
&& apt-get install -y libcurl4 libssl1.1 libprotobuf17 libh2o-evloop0.13 \
|
&& apt-get install -y libcurl4 libssl1.1 libprotobuf17 libh2o-evloop0.13 \
|
||||||
libncurses6 \
|
libncurses6 \
|
||||||
|
|
@ -37,5 +34,5 @@ RUN apt-get update && apt-get -y upgrade \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
COPY --from=builder /galmon/ /galmon/
|
COPY --from=builder /galmon/ /galmon/
|
||||||
ENV PATH=/galmon/bin:${PATH}
|
ENV PATH=/galmon/bin:${PATH}
|
||||||
ENV LC_ALL=C.UTF-8
|
ENV LC_ALL C.UTF-8
|
||||||
WORKDIR /galmon/bin
|
WORKDIR /galmon/bin
|
||||||
|
|
|
||||||
17
Makefile
|
|
@ -39,11 +39,12 @@ navmon.pb.cc: navmon.proto
|
||||||
protoc --cpp_out=./ 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
|
SIMPLESOCKETS=ext/powerblog/ext/simplesocket/swrappers.o ext/powerblog/ext/simplesocket/sclasses.o ext/powerblog/ext/simplesocket/comboaddress.o
|
||||||
|
|
||||||
|
|
||||||
clean:
|
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 *~ *.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/sgp4/libsgp4/*.d ext/powerblog/ext/simplesocket/*.d
|
rm -f ext/sgp4/libsgp4/*.d ext/powerblog/ext/simplesocket/*.d
|
||||||
|
|
||||||
help2man:
|
help2man:
|
||||||
|
|
@ -62,11 +63,21 @@ install: $(PROGRAMS) help2man
|
||||||
mkdir -p $(DESTDIR)$(prefix)$(htdocs)/galmon
|
mkdir -p $(DESTDIR)$(prefix)$(htdocs)/galmon
|
||||||
cp -a html $(DESTDIR)$(prefix)$(htdocs)/galmon/
|
cp -a html $(DESTDIR)$(prefix)$(htdocs)/galmon/
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
decrypt: decrypt.o bits.o
|
decrypt: decrypt.o bits.o
|
||||||
$(CXX) -std=gnu++17 $^ -o $@ -lfmt
|
$(CXX) -std=gnu++17 $^ -o $@ -lfmt
|
||||||
|
|
||||||
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
|
navparse: navparse.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 galileo.o
|
||||||
$(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -L/usr/local/opt/openssl/lib/ -lz -lcurl -lprotobuf -lfmt
|
$(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -L/usr/local/opt/openssl/lib/ -lh2o-evloop -lssl -lcrypto -lz -lcurl -lprotobuf $(WSLAY) -lfmt
|
||||||
|
|
||||||
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
|
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
|
$(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -lprotobuf -lcurl -lfmt
|
||||||
|
|
|
||||||
15
README.md
|
|
@ -82,20 +82,27 @@ receiver-only tools.
|
||||||
To build everything, including the webserver, try:
|
To build everything, including the webserver, try:
|
||||||
|
|
||||||
```
|
```
|
||||||
apt-get install protobuf-compiler libcurl4-openssl-dev libssl-dev libprotobuf-dev \
|
apt-get install protobuf-compiler libh2o-dev libcurl4-openssl-dev libssl-dev libprotobuf-dev \
|
||||||
libncurses5-dev libeigen3-dev libzstd-dev g++ libfmt-dev
|
libh2o-evloop-dev libwslay-dev libncurses5-dev libeigen3-dev libzstd-dev g++ libfmt-dev
|
||||||
git clone https://github.com/berthubert/galmon.git --recursive
|
git clone https://github.com/berthubert/galmon.git --recursive
|
||||||
cd galmon
|
cd galmon
|
||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
Building on OSX
|
Building on OSX
|
||||||
---------------
|
---------------
|
||||||
With thanks to a contributor from Prague. First make sure you've installed
|
With thanks to a contributor from Prague. First make sure you've installed
|
||||||
brew, which you can get [here](https://brew.sh/). Then do:
|
brew, which you can get [here](https://brew.sh/). Then do:
|
||||||
|
|
||||||
```
|
```
|
||||||
brew install protobuf lzlib zstd eigen
|
brew install protobuf lzlib zstd h2o eigen
|
||||||
```
|
```
|
||||||
|
|
||||||
And then:
|
And then:
|
||||||
|
|
@ -321,7 +328,7 @@ Documents
|
||||||
* [GLONASS CDMA](http://russianspacesystems.ru/wp-content/uploads/2016/08/ICD-GLONASS-CDMA-General.-Edition-1.0-2016.pdf)
|
* [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
|
not actually relevant for the CDMA aspects, but has appendices on more
|
||||||
precise orbit determinations.
|
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 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 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 10 interface specification](https://content.u-blox.com/sites/default/files/documents/u-blox-F10-SPG-6.00_InterfaceDescription_UBX-23002975.pdf)
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,11 @@
|
||||||
#include "navmon.hh"
|
#include "navmon.hh"
|
||||||
#include "fmt/format.h"
|
#include "fmt/format.h"
|
||||||
#include "fmt/printf.h"
|
#include "fmt/printf.h"
|
||||||
|
#include "ext/powerblog/h2o-pp.hh"
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
#include "CLI/CLI.hpp"
|
#include "CLI/CLI.hpp"
|
||||||
#include "version.hh"
|
#include "version.hh"
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
static char program[]="galmonmon";
|
static char program[]="galmonmon";
|
||||||
|
|
||||||
|
|
|
||||||
2
gps.cc
|
|
@ -38,8 +38,6 @@ int GPSState::parseGPSMessage(const std::vector<uint8_t>& cond, uint8_t* pageptr
|
||||||
wn = 2048 + getbitu(&cond[0], 2*24, 10);
|
wn = 2048 + getbitu(&cond[0], 2*24, 10);
|
||||||
ura = getbitu(&cond[0], 2*24+12, 4);
|
ura = getbitu(&cond[0], 2*24+12, 4);
|
||||||
gpshealth = getbitu(&cond[0], 2*24+16, 6);
|
gpshealth = getbitu(&cond[0], 2*24+16, 6);
|
||||||
iodc = getbitu(&cond[0], 2*24 +22, 2) * 256;
|
|
||||||
iodc += getbitu(&cond[0], 7*24, 8);
|
|
||||||
|
|
||||||
// cerr<<"GPS Week Number: "<< wn <<", URA: "<< (int)ura<<", health: "<<
|
// cerr<<"GPS Week Number: "<< wn <<", URA: "<< (int)ura<<", health: "<<
|
||||||
// (int)gpshealth <<endl;
|
// (int)gpshealth <<endl;
|
||||||
|
|
|
||||||
2
gps.hh
|
|
@ -134,10 +134,8 @@ struct GPSState : GPSLikeEphemeris
|
||||||
uint16_t wnLSF{0};
|
uint16_t wnLSF{0};
|
||||||
uint8_t dn; // leap second day number
|
uint8_t dn; // leap second day number
|
||||||
// 1 2^-31 2^-43 2^-55 16 second
|
// 1 2^-31 2^-43 2^-55 16 second
|
||||||
int iodc;
|
|
||||||
int ura;
|
int ura;
|
||||||
|
|
||||||
|
|
||||||
int gpsiod{-1};
|
int gpsiod{-1};
|
||||||
|
|
||||||
int getIOD() const
|
int getIOD() const
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
var repeat;
|
var repeat;
|
||||||
|
|
||||||
|
moment.relativeTimeThreshold('m', 120);
|
||||||
|
|
||||||
function maketable(str, arr)
|
function maketable(str, arr)
|
||||||
{
|
{
|
||||||
var table=d3.select(str);
|
var table=d3.select(str);
|
||||||
|
|
@ -102,7 +104,8 @@ function maketable(str, arr)
|
||||||
|
|
||||||
|
|
||||||
if(row[column] != null) {
|
if(row[column] != null) {
|
||||||
ret.value = row[column].toFixed(0) + " minutes ago";
|
var b = moment.duration(-row[column], 'm');
|
||||||
|
ret.value = b.humanize(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret.value="";
|
ret.value="";
|
||||||
|
|
@ -150,11 +153,8 @@ function maketable(str, arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(column == "last-seen-s") {
|
else if(column == "last-seen-s") {
|
||||||
var seconds = row[column].toFixed(0);
|
var b = moment.duration(row[column], 's');
|
||||||
if(seconds < 30)
|
ret.value = b.humanize();
|
||||||
ret.value = "a few seconds ago";
|
|
||||||
else
|
|
||||||
ret.value = (seconds/60) + " minutes ago";
|
|
||||||
}
|
}
|
||||||
else if(column == "best-tle") {
|
else if(column == "best-tle") {
|
||||||
ret.value = "<small>"+row[column]+"</small>";
|
ret.value = "<small>"+row[column]+"</small>";
|
||||||
|
|
@ -351,14 +351,9 @@ function update()
|
||||||
str += ", "+d["leap-seconds"]+"</b> leap seconds (GPS/Galileo)";
|
str += ", "+d["leap-seconds"]+"</b> leap seconds (GPS/Galileo)";
|
||||||
|
|
||||||
d3.select('#facts').html(str);
|
d3.select('#facts').html(str);
|
||||||
var ageSeconds = (Date.now() - 1000*d["last-seen"])/1000;
|
lastseen = moment(1000*d["last-seen"]);
|
||||||
var ageString;
|
d3.select("#freshness").html(lastseen.fromNow());
|
||||||
if(ageSeconds < 60)
|
|
||||||
ageString = "a few seconds ago";
|
|
||||||
else
|
|
||||||
ageString = (ageSeconds/60).toFixed(0) +" minutes ago";
|
|
||||||
|
|
||||||
d3.select("#freshness").html(ageString);
|
|
||||||
|
|
||||||
str = d["total-live-receivers"]+" receivers active, tracking ";
|
str = d["total-live-receivers"]+" receivers active, tracking ";
|
||||||
str += d["total-live-svs"] + " satellites via " ;
|
str += d["total-live-svs"] + " satellites via " ;
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 399 B |
|
Before Width: | Height: | Size: 399 B |
|
Before Width: | Height: | Size: 940 B |
|
Before Width: | Height: | Size: 297 B |
|
Before Width: | Height: | Size: 703 B |
|
Before Width: | Height: | Size: 332 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 820 B |
|
|
@ -143,9 +143,6 @@ var Tooltip;
|
||||||
|
|
||||||
function create_tooltop()
|
function create_tooltop()
|
||||||
{
|
{
|
||||||
if (Tooltip) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// create a tooltip
|
// create a tooltip
|
||||||
Tooltip = d3.select("#combined")
|
Tooltip = d3.select("#combined")
|
||||||
.append("span")
|
.append("span")
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
Last update: <span id="freshness"></span>. More information about this Galileo/GPS/BeiDou/Glonass open source monitor can be found <a href="https://berthub.eu/articles/posts/galmon-project/">here</a>. Live observer map <a href="geo">here</a>, status (coverage, DOP) map <a href="geo/coverage.html">here</a>. <b><strike>Experimental Grafana dashboard on <a href="https://public.galmon.eu/">public.galmon.eu</a> (user: guest, password: guest)</strike></b>. SBAS <a href="sbas.html">status</a>, <a href="sbstatus.html">per-satellite</a>. <a rel="me" href="https://bot.country/@GNSS_Changes">Mastodon</a>. <span id="allstats"></span><br/>
|
Last update: <span id="freshness"></span>. More information about this Galileo/GPS/BeiDou/Glonass open source monitor can be found <a href="https://berthub.eu/articles/posts/galmon-project/">here</a>. Live observer map <a href="geo">here</a>, status (coverage, DOP) map <a href="geo/coverage.html">here</a>. <b>Experimental Grafana dashboard on <a href="https://public.galmon.eu/">public.galmon.eu</a> (user: guest, password: guest)</b>. SBAS <a href="sbas.html">status</a>, <a href="sbstatus.html">per-satellite</a>. <span id="allstats"></span><br/>
|
||||||
<div class="centered">
|
<div class="centered">
|
||||||
<hr/>
|
<hr/>
|
||||||
<input type="checkbox" id="GalE1" onclick="updateSats();"> <label for="GalE1">Galileo E1</label>
|
<input type="checkbox" id="GalE1" onclick="updateSats();"> <label for="GalE1">Galileo E1</label>
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
<input type="checkbox" id="GPSL2C" onclick="updateSats();"> <label for="GPSL2C">GPS L2C</label>
|
<input type="checkbox" id="GPSL2C" onclick="updateSats();"> <label for="GPSL2C">GPS L2C</label>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
|
<a rel="me" href="https://bot.country/@GNSS_Changes">Mastodon</a>
|
||||||
<table id="svs"></table>
|
<table id="svs"></table>
|
||||||
<hr>
|
<hr>
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -75,9 +75,10 @@
|
||||||
Information on the status of BeiDou can be found on <a href="http://www.csno-tarc.cn/system/constellation&ce=english">this page</a> from the Chinese Test and Assessment Research Center of China Satellite Navigation Office.
|
Information on the status of BeiDou can be found on <a href="http://www.csno-tarc.cn/system/constellation&ce=english">this page</a> from the Chinese Test and Assessment Research Center of China Satellite Navigation Office.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Feedback is very welcome on bert@hubertnet.nl or via Mastodon <a href="https://eupolicy.social/@bert_hubert">@bert_hubert@eupolicy.social</a>.
|
Feedback is very welcome on bert@hubertnet.nl or <a href="https://twitter.com/bert_hu_bert">@bert_hu_bert</a>.
|
||||||
</p>
|
</p>
|
||||||
<script src="d3.v4.min.js"></script>
|
<script src="d3.v4.min.js"></script>
|
||||||
|
<script src="ext/moment-with-locales.js"></script>
|
||||||
<script src="doalles.js"></script>
|
<script src="doalles.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||