oscillatord/monitoring.go (143 lines of code) (raw):
/*
Copyright (c) Facebook, Inc. and its affiliates.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package oscillatord implements monitoring protocol used by Orolia's oscillatord,
daemon for disciplining an oscillator.
All references throughout the code relate to the https://github.com/Orolia2s/oscillatord code.
*/
package oscillatord
import (
"encoding/json"
"fmt"
"io"
)
// AntennaStatus is an enum describing antenna status as reported by oscillatord
type AntennaStatus int
// from oscillatord src/gnss.c
const (
AntStatusInit AntennaStatus = iota
AntStatusDontKnow
AntStatusOK
AntStatusSHORT
AntStatusOpen
AntStatusUndefined
)
var antennaStatusToString = map[AntennaStatus]string{
AntStatusInit: "INIT",
AntStatusDontKnow: "DONTKNOW",
AntStatusOK: "OK",
AntStatusSHORT: "SHORT",
AntStatusOpen: "OPEN",
AntStatusUndefined: "UNDEFINED",
}
func (a AntennaStatus) String() string {
s, found := antennaStatusToString[a]
if !found {
return "UNSUPPORTED VALUE"
}
return s
}
// AntennaPower is an enum describing antenna power status as reported by oscillatord
type AntennaPower int
// from oscillatord src/gnss.c
const (
AntPowerOff AntennaPower = iota
AntPowerOn
AntPowerDontKnow
AntPowerIdle
AntPowerUndefined
)
var antennaPowerToString = map[AntennaPower]string{
AntPowerOff: "OFF",
AntPowerOn: "ON",
AntPowerDontKnow: "DONTKNOW",
AntPowerIdle: "IDLE",
AntPowerUndefined: "UNDEFINED",
}
func (p AntennaPower) String() string {
s, found := antennaPowerToString[p]
if !found {
return "UNSUPPORTED VALUE"
}
return s
}
// GNSSFix is an enum describing GNSS fix status as reported by oscillatord
type GNSSFix int
// from oscillatord src/gnss.c
const (
FixUnknown GNSSFix = iota
FixNoFix
FixDROnly
FixTime
Fix2D
Fix3D
Fix3DDr
FixRTKFloat
FixRTKFixed
FixFloatDr
FixFixedDr
)
var gnssFixToString = map[GNSSFix]string{
FixUnknown: "Unknown",
FixNoFix: "No fix",
FixDROnly: "DR only",
FixTime: "Time",
Fix2D: "2D",
Fix3D: "3D",
Fix3DDr: "3D_DR",
FixRTKFloat: "RTK_FLOAT",
FixRTKFixed: "RTK_FIXED",
FixFloatDr: "RTK_FLOAT_DR",
FixFixedDr: "RTK_FIXED_DR",
}
func (f GNSSFix) String() string {
s, found := gnssFixToString[f]
if !found {
return "UNSUPPORTED VALUE"
}
return s
}
// LeapSecondChange is enum that oscillatord uses to indicate leap second change
type LeapSecondChange int
// from oscillatord src/gnss.c
const (
LeapNoWarning LeapSecondChange = 0
LeapAddSecond LeapSecondChange = 1
LeapDelSecond LeapSecondChange = -1
)
var leapSecondChangeToString = map[LeapSecondChange]string{
LeapNoWarning: "NO WARNING",
LeapAddSecond: "ADD SECOND",
LeapDelSecond: "DEL SECOND",
}
func (c LeapSecondChange) String() string {
s, found := leapSecondChangeToString[c]
if !found {
return "UNSUPPORTED VALUE"
}
return s
}
// Oscillator describes structure that oscillatord returns for oscillator
type Oscillator struct {
Model string `json:"model"`
FineCtrl int `json:"fine_ctrl"`
CoarseCtrl int `json:"coarse_ctrl"`
Lock bool `json:"lock"`
Temperature float64 `json:"temperature"`
}
// GNSS describes structure that oscillatord returns for gnss
type GNSS struct {
Fix GNSSFix `json:"fix"`
FixOK bool `json:"fixOk"`
AntennaPower AntennaPower `json:"antenna_power"`
AntennaStatus AntennaStatus `json:"antenna_status"`
LSChange LeapSecondChange `json:"lsChange"`
LeapSeconds int `json:"leap_seconds"`
SatellitesCount int `json:"satellites_count"`
}
// Status is whole structure that oscillatord returns for monitoring
type Status struct {
Oscillator Oscillator `json:"oscillator"`
GNSS GNSS `json:"gnss"`
}
// ReadStatus talks to oscillatord via monitoring port connection and reads reported Status
func ReadStatus(conn io.ReadWriter) (*Status, error) {
// send newline to make oscillatord send us data
_, err := conn.Write([]byte{'\n'})
if err != nil {
return nil, fmt.Errorf("writing to oscillatord conn: %w", err)
}
buf := make([]byte, 1000)
n, err := conn.Read(buf)
if err != nil {
return nil, fmt.Errorf("reading from oscillatord conn: %w", err)
}
if n == 0 {
return nil, fmt.Errorf("read 0 bytes from oscillatord")
}
var status Status
if err := json.Unmarshal(buf[:n], &status); err != nil {
return nil, fmt.Errorf("unmarshalling JSON: %w", err)
}
return &status, nil
}