2023-01-01 14:09:07 +00:00
// (C) 2022 by Harald Welte <laforge@gnumonks.org>
// SPDX-License-Identifier: Apache-2.0
2022-12-31 17:40:54 +00:00
package main
import (
"fmt"
2022-12-31 18:54:17 +00:00
"flag"
2022-12-31 17:40:54 +00:00
"github.com/stratoberry/go-gpsd"
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
2022-12-31 18:54:17 +00:00
gpsd_tcp = flag . String ( "gpsd" , "localhost:2947" , "remote gpsd host:port" )
listen_http = flag . String ( "http" , ":2112" , "local HTTP listen host:port" )
gpsMode = promauto . NewGaugeVec (
2022-12-31 17:40:54 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 17:59:16 +00:00
Name : "fix_mode" ,
Help : "gpsd mode (0=NoValueSeen, 1=NoFix, 2=2D fix, 3=3D fix)" ,
2022-12-31 18:54:17 +00:00
} ,
[ ] string {
"device" ,
2022-12-31 17:40:54 +00:00
} )
2022-12-31 18:54:17 +00:00
gpsLat = promauto . NewGaugeVec (
2022-12-31 17:40:54 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 18:54:17 +00:00
Name : "latitude" ,
Help : "Latitude in degrees: +/- signifies North/South." ,
} ,
[ ] string {
"device" ,
2022-12-31 17:40:54 +00:00
} )
2022-12-31 18:54:17 +00:00
gpsLon = promauto . NewGaugeVec (
2022-12-31 17:40:54 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 18:54:17 +00:00
Name : "longitude" ,
Help : "Longitude in degrees: +/- signifies East/West." ,
} ,
[ ] string {
"device" ,
} )
gpsAlt = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "altitude" ,
} ,
[ ] string {
"device" ,
2022-12-31 17:40:54 +00:00
} )
2022-12-31 17:59:16 +00:00
2022-12-31 18:54:17 +00:00
gpsEpt = promauto . NewGaugeVec (
2022-12-31 17:59:16 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 18:54:17 +00:00
Name : "estimated_error_timestamp" ,
Help : "Estimated time stamp error in seconds. Certainty unknown." ,
2022-12-31 17:59:16 +00:00
} ,
[ ] string {
2022-12-31 18:54:17 +00:00
"device" ,
} )
gpsEpx = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "estimated_error_longitude" ,
Help : "Longitude error estimate in meters. Certainty unknown." ,
2022-12-31 17:59:16 +00:00
} ,
2022-12-31 18:54:17 +00:00
[ ] string {
"device" ,
} )
gpsEpy = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "estimated_error_latitude" ,
Help : "Latitude error estimate in meters. Certainty unknown." ,
} ,
[ ] string {
"device" ,
} )
gpsEpv = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "estimated_error_altitude" ,
Help : "Estimated vertical error in meters. Certainty unknown." ,
} ,
[ ] string {
"device" ,
} )
gpsTrack = promauto . NewGaugeVec (
2022-12-31 17:59:16 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 18:54:17 +00:00
Name : "track" ,
Help : "Course over ground, degrees from true north." ,
} ,
[ ] string {
"device" ,
2022-12-31 17:59:16 +00:00
} )
2022-12-31 18:54:17 +00:00
gpsSpeed = promauto . NewGaugeVec (
2022-12-31 17:59:16 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 18:54:17 +00:00
Name : "speed" ,
Help : "Speed over ground, meters per second." ,
} ,
[ ] string {
"device" ,
2022-12-31 17:59:16 +00:00
} )
2022-12-31 18:54:17 +00:00
gpsClimb = promauto . NewGaugeVec (
2022-12-31 17:59:16 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 18:54:17 +00:00
Name : "climb" ,
Help : "Climb (positive) or sink (negative) rate, meters per second." ,
} ,
[ ] string {
"device" ,
2022-12-31 17:59:16 +00:00
} )
2022-12-31 18:54:17 +00:00
gpsEpd = promauto . NewGaugeVec (
2022-12-31 17:59:16 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 18:54:17 +00:00
Name : "estimated_error_direction" ,
Help : "Estimated track (direction) error in degrees. Certainty unknown." ,
} ,
[ ] string {
"device" ,
2022-12-31 17:59:16 +00:00
} )
2022-12-31 18:54:17 +00:00
gpsEps = promauto . NewGaugeVec (
2022-12-31 17:59:16 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 18:54:17 +00:00
Name : "estimated_error_speed" ,
Help : "Estimated speed error in meters per second. Certainty unknown." ,
} ,
[ ] string {
"device" ,
2022-12-31 17:59:16 +00:00
} )
2022-12-31 18:54:17 +00:00
gpsEpc = promauto . NewGaugeVec (
2022-12-31 17:59:16 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 18:54:17 +00:00
Name : "estimated_error_climb" ,
Help : "Estimated climb error in meters per second. Certainty unknown." ,
} ,
[ ] string {
"device" ,
2022-12-31 17:59:16 +00:00
} )
2022-12-31 18:54:17 +00:00
gpsNumSats = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "space_vehicles_total" ,
Help : "Total number of space vehicles observed." ,
} ,
[ ] string {
"device" ,
} )
gpsNumSatsUsed = promauto . NewGaugeVec (
2022-12-31 17:59:16 +00:00
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
2022-12-31 18:54:17 +00:00
Name : "space_vehicles_used" ,
Help : "Number of space vehicles used in fix." ,
} ,
[ ] string {
"device" ,
2022-12-31 17:59:16 +00:00
} )
2022-12-31 18:54:17 +00:00
gpsSvAz = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "space_vehicle_azimuth" ,
Help : "Per-SV Azimuth, degrees from true north." ,
} ,
[ ] string {
"device" ,
"prn" ,
} ,
)
gpsSvEl = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "space_vehicle_elevation" ,
Help : "Per-SV Elevation in degrees." ,
} ,
[ ] string {
"device" ,
"prn" ,
} ,
)
gpsSvSs = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "space_vehicle_signal_noise_ratio" ,
Help : "Per-SV Signal to Noise ratio in dBHz." ,
} ,
[ ] string {
"device" ,
"prn" ,
} ,
)
gpsXdop = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "dilution_of_precision_longitude" ,
Help : "Longitudinal dilution of precision, a dimensionless factor which should be multiplied by a base UERE to get an error estimate." ,
} ,
[ ] string {
"device" ,
} ,
)
gpsYdop = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "dilution_of_precision_latitude" ,
Help : "Latitudinal dilution of precision, a dimensionless factor which should be multiplied by a base UERE to get an error estimate." ,
} ,
[ ] string {
"device" ,
} ,
)
gpsVdop = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "dilution_of_precision_altitude" ,
Help : "Vertical (altitude) dilution of precision, a dimensionless factor which should be multiplied by a base UERE to get an error estimate." ,
} ,
[ ] string {
"device" ,
} ,
)
gpsTdop = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "dilution_of_precision_time" ,
Help : "Time dilution of precision, a dimensionless factor which should be multiplied by a base UERE to get an error estimate." ,
} ,
[ ] string {
"device" ,
} ,
)
gpsHdop = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "dilution_of_precision_horizontal" ,
Help : "Horizontal dilution of precision, a dimensionless factor which should be multiplied by a base UERE to get a circular error estimate." ,
} ,
[ ] string {
"device" ,
} ,
)
gpsPdop = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "dilution_of_precision_position" ,
Help : "Position (spherical/3D) dilution of precision, a dimensionless factor which should be multiplied by a base UERE to get an error estimate." ,
} ,
[ ] string {
"device" ,
} ,
)
gpsGdop = promauto . NewGaugeVec (
prometheus . GaugeOpts {
Subsystem : "gpsd" ,
Name : "dilution_of_precision_geometric" ,
Help : "Geometric (hyperspherical) dilution of precision, a combination of PDOP and TDOP. A dimensionless factor which should be multiplied by a base UERE to get an error estimate." ,
} ,
[ ] string {
"device" ,
} ,
)
2022-12-31 17:40:54 +00:00
)
func main ( ) {
var gps * gpsd . Session
var err error
2022-12-31 18:54:17 +00:00
flag . Parse ( )
fmt . Println ( "Connecting to gpsd at" , * gpsd_tcp , "..." )
if gps , err = gpsd . Dial ( * gpsd_tcp ) ; err != nil {
2022-12-31 17:40:54 +00:00
panic ( fmt . Sprintf ( "Failed to connect to GPSD: %s" , err ) )
}
2022-12-31 18:54:17 +00:00
fmt . Println ( "Connected to gpsd!" )
2022-12-31 17:40:54 +00:00
gps . AddFilter ( "TPV" , func ( r interface { } ) {
tpv := r . ( * gpsd . TPVReport )
//fmt.Println("TPV", tpv.Mode, tpv.Time)
2022-12-31 18:54:17 +00:00
gpsMode . WithLabelValues ( tpv . Device ) . Set ( float64 ( tpv . Mode ) )
//time
gpsEpt . WithLabelValues ( tpv . Device ) . Set ( tpv . Ept )
gpsLat . WithLabelValues ( tpv . Device ) . Set ( tpv . Lat )
gpsLon . WithLabelValues ( tpv . Device ) . Set ( tpv . Lon )
gpsAlt . WithLabelValues ( tpv . Device ) . Set ( tpv . Alt )
gpsEpx . WithLabelValues ( tpv . Device ) . Set ( tpv . Epx )
gpsEpy . WithLabelValues ( tpv . Device ) . Set ( tpv . Epy )
gpsEpv . WithLabelValues ( tpv . Device ) . Set ( tpv . Epv )
gpsTrack . WithLabelValues ( tpv . Device ) . Set ( tpv . Track )
gpsClimb . WithLabelValues ( tpv . Device ) . Set ( tpv . Climb )
gpsEpd . WithLabelValues ( tpv . Device ) . Set ( tpv . Epd )
gpsEps . WithLabelValues ( tpv . Device ) . Set ( tpv . Eps )
gpsEpc . WithLabelValues ( tpv . Device ) . Set ( tpv . Epc )
2022-12-31 17:40:54 +00:00
} )
/ *
gps . AddFilter ( "DEVICE" , func ( r interface { } ) {
dev := r . ( * gpsd . DEVICEReport )
fmt . Println ( "DEVICE" , dev . Path , dev . Flags )
} )
* /
gps . AddFilter ( "SKY" , func ( r interface { } ) {
sky := r . ( * gpsd . SKYReport )
fmt . Println ( "SKY" , sky . Satellites )
2022-12-31 18:54:17 +00:00
gpsXdop . WithLabelValues ( sky . Device ) . Set ( sky . Xdop )
gpsYdop . WithLabelValues ( sky . Device ) . Set ( sky . Ydop )
gpsVdop . WithLabelValues ( sky . Device ) . Set ( sky . Vdop )
gpsTdop . WithLabelValues ( sky . Device ) . Set ( sky . Tdop )
gpsHdop . WithLabelValues ( sky . Device ) . Set ( sky . Hdop )
gpsPdop . WithLabelValues ( sky . Device ) . Set ( sky . Pdop )
gpsGdop . WithLabelValues ( sky . Device ) . Set ( sky . Gdop )
gpsNumSats . WithLabelValues ( sky . Device ) . Set ( float64 ( len ( sky . Satellites ) ) )
2022-12-31 17:59:16 +00:00
gpsSvSs . Reset ( )
2022-12-31 17:40:54 +00:00
num_sats_used := 0
for i := 0 ; i < len ( sky . Satellites ) ; i ++ {
num_sats_used += 1
2022-12-31 17:59:16 +00:00
prn_str := fmt . Sprintf ( "%.0f" , sky . Satellites [ i ] . PRN )
2022-12-31 18:54:17 +00:00
gpsSvAz . WithLabelValues ( sky . Device , prn_str ) . Set ( sky . Satellites [ i ] . Az )
gpsSvEl . WithLabelValues ( sky . Device , prn_str ) . Set ( sky . Satellites [ i ] . El )
gpsSvSs . WithLabelValues ( sky . Device , prn_str ) . Set ( sky . Satellites [ i ] . Ss )
2022-12-31 17:40:54 +00:00
}
2022-12-31 18:54:17 +00:00
gpsNumSatsUsed . WithLabelValues ( sky . Device ) . Set ( float64 ( num_sats_used ) )
2022-12-31 17:40:54 +00:00
} )
done := gps . Watch ( )
2022-12-31 18:54:17 +00:00
fmt . Println ( "Listening to HTTP requests at" , * listen_http )
2022-12-31 17:40:54 +00:00
http . Handle ( "/metrics" , promhttp . Handler ( ) )
2022-12-31 18:54:17 +00:00
http . ListenAndServe ( * listen_http , nil )
2022-12-31 17:40:54 +00:00
<- done
}