add 'reporter' for weekly/daily/whatever Galileo statistics, plus additional URL for F9P manual.

pull/48/head
bert hubert 2019-11-20 22:45:30 +01:00
parent 9471b3758a
commit 7f10b8f5b9
5 changed files with 174 additions and 1 deletions

View File

@ -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
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)
@ -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
$(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
$(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf

View File

@ -213,6 +213,7 @@ Documents
* [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 9 integration manual](https://www.u-blox.com/sites/default/files/ZED-F9P_IntegrationManual_%28UBX-18010802%29.pdf)
Data sources
------------

View File

@ -182,3 +182,12 @@ void MiniCurl::setHeaders(const MiniCurlHeaders& headers)
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;
}

View File

@ -44,6 +44,8 @@ public:
MiniCurl& operator=(const MiniCurl&) = delete;
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 urlEncode(std::string_view str);
private:
CURL *d_curl;
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);

157
reporter.cc 100644
View File

@ -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;
}