add 'reporter' for weekly/daily/whatever Galileo statistics, plus additional URL for F9P manual.
parent
9471b3758a
commit
7f10b8f5b9
6
Makefile
6
Makefile
|
@ -6,7 +6,7 @@ CXXFLAGS:= -std=gnu++17 -Wall -O3 -MMD -MP -ggdb -fno-omit-frame-pointer -Iext/C
|
||||||
|
|
||||||
# CXXFLAGS += -Wno-delete-non-virtual-dtor
|
# CXXFLAGS += -Wno-delete-non-virtual-dtor
|
||||||
|
|
||||||
PROGRAMS = navparse ubxtool navnexus navcat navrecv navdump testrunner navdisplay tlecatch
|
PROGRAMS = navparse ubxtool navnexus navcat navrecv navdump testrunner navdisplay tlecatch reporter
|
||||||
|
|
||||||
all: navmon.pb.cc $(PROGRAMS)
|
all: navmon.pb.cc $(PROGRAMS)
|
||||||
|
|
||||||
|
@ -25,6 +25,10 @@ clean:
|
||||||
navparse: navparse.o ext/fmt-5.2.1/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
|
navparse: navparse.o ext/fmt-5.2.1/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
|
||||||
$(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -L/usr/local/opt/openssl/lib/ -lh2o-evloop -lssl -lcrypto -lz -lcurl -lprotobuf $(WSLAY)
|
$(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-5.2.1/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
|
||||||
|
$(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -L/usr/local/opt/openssl/lib/ -lh2o-evloop -lssl -lcrypto -lz -lcurl -lprotobuf $(WSLAY)
|
||||||
|
|
||||||
|
|
||||||
navdump: navdump.o ext/fmt-5.2.1/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
|
navdump: navdump.o ext/fmt-5.2.1/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
|
||||||
$(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf
|
$(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,7 @@ Documents
|
||||||
* [GPS](https://www.gps.gov/technical/icwg/IS-GPS-200K.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 9 integration manual](https://www.u-blox.com/sites/default/files/ZED-F9P_IntegrationManual_%28UBX-18010802%29.pdf)
|
||||||
|
|
||||||
Data sources
|
Data sources
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -182,3 +182,12 @@ void MiniCurl::setHeaders(const MiniCurlHeaders& headers)
|
||||||
curl_easy_setopt(d_curl, CURLOPT_HTTPHEADER, d_header_list);
|
curl_easy_setopt(d_curl, CURLOPT_HTTPHEADER, d_header_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string MiniCurl::urlEncode(string_view str)
|
||||||
|
{
|
||||||
|
char *ptr= curl_easy_escape(d_curl , &str[0] , str.size() );
|
||||||
|
string ret(ptr);
|
||||||
|
curl_free(ptr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,8 @@ public:
|
||||||
MiniCurl& operator=(const MiniCurl&) = delete;
|
MiniCurl& operator=(const MiniCurl&) = delete;
|
||||||
std::string getURL(const std::string& str, const ComboAddress* rem=0, const ComboAddress* src=0);
|
std::string getURL(const std::string& str, const ComboAddress* rem=0, const ComboAddress* src=0);
|
||||||
std::string postURL(const std::string& str, const std::string& postdata, MiniCurlHeaders& headers);
|
std::string postURL(const std::string& str, const std::string& postdata, MiniCurlHeaders& headers);
|
||||||
|
|
||||||
|
std::string urlEncode(std::string_view str);
|
||||||
private:
|
private:
|
||||||
CURL *d_curl;
|
CURL *d_curl;
|
||||||
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
|
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
#include "ext/powerblog/h2o-pp.hh"
|
||||||
|
#include "minicurl.hh"
|
||||||
|
#include <iostream>
|
||||||
|
#include "navmon.hh"
|
||||||
|
#include "fmt/format.h"
|
||||||
|
#include "fmt/printf.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Goal: generate statistics from influxdb.
|
||||||
|
|
||||||
|
Method: per x minute interval, determine status for all SVs.
|
||||||
|
We only count minutes in which we have data
|
||||||
|
|
||||||
|
We do only positive measurements, and report absence of data in neutral terms - either there was no reception or no transmission, we don't know.
|
||||||
|
|
||||||
|
If an interval has no data: unobserved
|
||||||
|
If interval has any data, it counts as observed
|
||||||
|
If interval has a single unhealthy status, it is entirely unhealthy
|
||||||
|
If interval is NAPA, but otherwise healthy, status is NAPA
|
||||||
|
If observed and nothing else, status is healthy
|
||||||
|
|
||||||
|
Input: time range, width if interval
|
||||||
|
Internal: per SV, interval, bitfield
|
||||||
|
Output: per SV, number of intervals healthy, number of intervals NAPA, number of intervals unhealthy, number of intervals unobserved
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct IntervalStat
|
||||||
|
{
|
||||||
|
std::optional<int> unhealthy;
|
||||||
|
std::optional<int> sisa;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
map<SatID, map<time_t,IntervalStat>> g_stats;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
MiniCurl mc;
|
||||||
|
MiniCurl::MiniCurlHeaders mch;
|
||||||
|
string dbname("galileo3");
|
||||||
|
|
||||||
|
string url="http://127.0.0.1:8086/query?db="+dbname+"&epoch=s&q=";
|
||||||
|
string period="time > now() - 1w";
|
||||||
|
int sigid=1;
|
||||||
|
if(argc == 2)
|
||||||
|
period = "time > now() - "+string(argv[1]);
|
||||||
|
if(argc == 3) {
|
||||||
|
period = "time > '"+string(argv[1]) +"' and time <= '" + string(argv[2])+"'";
|
||||||
|
}
|
||||||
|
auto res = mc.getURL(url + mc.urlEncode("select distinct(value) from sisa where "+period+" and sigid='"+to_string(sigid)+"' group by gnssid,sv,sigid,time(10m)"));
|
||||||
|
|
||||||
|
|
||||||
|
auto j = nlohmann::json::parse(res);
|
||||||
|
// cout<<j<<endl;
|
||||||
|
|
||||||
|
for(const auto& sv : j["results"][0]["series"]) {
|
||||||
|
const auto& tags=sv["tags"];
|
||||||
|
SatID id{(unsigned int)std::stoi((string)tags["gnssid"]), (unsigned int)std::stoi((string)tags["sv"]), (unsigned int)std::stoi((string)tags["sigid"])};
|
||||||
|
|
||||||
|
for(const auto& v : sv["values"]) {
|
||||||
|
auto sisa = (int)v[1];
|
||||||
|
|
||||||
|
g_stats[id][(int)v[0]].sisa = sisa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
res = mc.getURL(url + mc.urlEncode("select distinct(value) from e1bhs where "+period+" and sigid='"+to_string(sigid)+"' group by gnssid,sv,sigid,time(10m)"));
|
||||||
|
j = nlohmann::json::parse(res);
|
||||||
|
|
||||||
|
for(const auto& sv : j["results"][0]["series"]) {
|
||||||
|
const auto& tags=sv["tags"];
|
||||||
|
SatID id{(unsigned int)std::stoi((string)tags["gnssid"]), (unsigned int)std::stoi((string)tags["sv"]), (unsigned int)std::stoi((string)tags["sigid"])};
|
||||||
|
|
||||||
|
|
||||||
|
for(const auto& v : sv["values"]) {
|
||||||
|
auto healthy = (int)v[1];
|
||||||
|
g_stats[id][(int)v[0]].unhealthy = healthy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_stats.erase({2,14,1});
|
||||||
|
g_stats.erase({2,18,1});
|
||||||
|
//g_stats[{2,11,1}];
|
||||||
|
|
||||||
|
unsigned int maxintervals=0;
|
||||||
|
time_t start=time(0), stop=0;
|
||||||
|
for(const auto& sv : g_stats) {
|
||||||
|
if(sv.second.size()) {
|
||||||
|
if(sv.second.begin()->first < start)
|
||||||
|
start = sv.second.begin()->first;
|
||||||
|
if(sv.second.rbegin()->first > stop)
|
||||||
|
stop = sv.second.rbegin()->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sv.second.size() > maxintervals)
|
||||||
|
maxintervals = sv.second.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
cout<<"Report on "<<g_stats.size()<<" SVs from "<<humanTime(start) <<" to " <<humanTime(stop) << endl;
|
||||||
|
int totnapa=0, totunhealthy=0, tothealthy=0, tottesting=0;
|
||||||
|
int totunobserved=0;
|
||||||
|
for(const auto& sv : g_stats) {
|
||||||
|
|
||||||
|
int napa=0, unhealthy=0, healthy=0, testing=0;
|
||||||
|
for(const auto& i : sv.second) {
|
||||||
|
if(i.second.unhealthy) {
|
||||||
|
if(*i.second.unhealthy==1)
|
||||||
|
unhealthy++;
|
||||||
|
else if(*i.second.unhealthy==3)
|
||||||
|
testing++;
|
||||||
|
else {
|
||||||
|
if(i.second.sisa) {
|
||||||
|
if(*i.second.sisa == 255)
|
||||||
|
napa++;
|
||||||
|
else
|
||||||
|
healthy++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
healthy++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(i.second.sisa) {
|
||||||
|
if(*i.second.sisa == 255)
|
||||||
|
napa++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totnapa += napa;
|
||||||
|
totunhealthy += unhealthy;
|
||||||
|
tottesting += testing;
|
||||||
|
tothealthy += healthy;
|
||||||
|
totunobserved += maxintervals-sv.second.size();
|
||||||
|
|
||||||
|
cout<<fmt::sprintf("E%02d: %6.2f%% unobserved, %6.2f%% unhealthy, %6.2f%% healthy, %6.2f%% testing, %6.2f%% napa",
|
||||||
|
sv.first.sv,
|
||||||
|
100.0*(maxintervals-sv.second.size())/maxintervals,
|
||||||
|
100.0*unhealthy/maxintervals,
|
||||||
|
100.0*healthy/maxintervals,
|
||||||
|
100.0*testing/maxintervals,
|
||||||
|
100.0*napa/maxintervals
|
||||||
|
)<<endl;
|
||||||
|
}
|
||||||
|
cout<<"------------------------------------------------------------------------------------------"<<endl;
|
||||||
|
cout<<fmt::sprintf("Tot: %6.2f%% unobserved, %6.2f%% unhealthy, %6.2f%% healthy, %6.2f%% testing, %6.2f%% napa",
|
||||||
|
100.0*(totunobserved)/maxintervals/g_stats.size(),
|
||||||
|
100.0*totunhealthy/maxintervals/g_stats.size(),
|
||||||
|
100.0*tothealthy/maxintervals/g_stats.size(),
|
||||||
|
100.0*tottesting/maxintervals/g_stats.size(),
|
||||||
|
100.0*totnapa/maxintervals/g_stats.size()
|
||||||
|
)<<endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue