Add Starlink status lines for the physical gateway pane (closes #3)
check / check (push) Failing after 1s
check / check (push) Failing after 1s
When the non-VPN physical gateway is a Starlink dish, two lines are shown under that pane: state, uptime, obstruction and alert count; then pop-ping latency and drop rate with downlink/uplink throughput. They turn red when the dish is not connected or an alert is active. Detection is a TCP connect to the dish's fixed endpoint 192.168.100.1:9200, bound to the physical interface the same way the latency probes bind. Until a dish answers nothing is drawn and no status is fetched, so an absent dish adds no noise. Status comes from the dish's local get_status gRPC call. Detection and the fetch sit behind a small Client interface; the loop and the pure Render function are tested with a fake, no dish and no network. Model: opus-4-8
This commit is contained in:
@@ -0,0 +1,629 @@
|
||||
// A minimal slice of the Starlink dish's local gRPC API: just the one
|
||||
// unary RPC (SpaceX.API.Device.Device/Handle) and the get_status request
|
||||
// and dish status response, reduced to the handful of fields rtnetmon
|
||||
// shows. The proto package name and field numbers must match the dish
|
||||
// exactly for the wire format to line up; every other field the dish sends
|
||||
// is ignored as an unknown field.
|
||||
//
|
||||
// Field numbers, message names and the DishState enum are transcribed from
|
||||
// the community-maintained pre-generated bindings at
|
||||
// github.com/starlink-community/starlink-grpc-go, commit
|
||||
// 2e89f3d7e3092adecbcc04e9e003e61ed5f7c6a3 (get_status = 1004,
|
||||
// dish_get_status = 2004). They are not verified against a live dish here.
|
||||
//
|
||||
// Regenerate with:
|
||||
// protoc --go_out=. --go_opt=paths=source_relative \
|
||||
// --go-grpc_out=. --go-grpc_opt=paths=source_relative \
|
||||
// internal/starlink/pb/starlink.proto
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v7.36.2
|
||||
// source: internal/starlink/pb/starlink.proto
|
||||
|
||||
package starlinkpb
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type DishState int32
|
||||
|
||||
const (
|
||||
DishState_UNKNOWN DishState = 0
|
||||
DishState_CONNECTED DishState = 1
|
||||
DishState_SEARCHING DishState = 2
|
||||
DishState_BOOTING DishState = 3
|
||||
)
|
||||
|
||||
// Enum value maps for DishState.
|
||||
var (
|
||||
DishState_name = map[int32]string{
|
||||
0: "UNKNOWN",
|
||||
1: "CONNECTED",
|
||||
2: "SEARCHING",
|
||||
3: "BOOTING",
|
||||
}
|
||||
DishState_value = map[string]int32{
|
||||
"UNKNOWN": 0,
|
||||
"CONNECTED": 1,
|
||||
"SEARCHING": 2,
|
||||
"BOOTING": 3,
|
||||
}
|
||||
)
|
||||
|
||||
func (x DishState) Enum() *DishState {
|
||||
p := new(DishState)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x DishState) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (DishState) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_internal_starlink_pb_starlink_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (DishState) Type() protoreflect.EnumType {
|
||||
return &file_internal_starlink_pb_starlink_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x DishState) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DishState.Descriptor instead.
|
||||
func (DishState) EnumDescriptor() ([]byte, []int) {
|
||||
return file_internal_starlink_pb_starlink_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Types that are valid to be assigned to Request:
|
||||
//
|
||||
// *Request_GetStatus
|
||||
Request isRequest_Request `protobuf_oneof:"request"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Request) Reset() {
|
||||
*x = Request{}
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Request) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Request) ProtoMessage() {}
|
||||
|
||||
func (x *Request) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Request.ProtoReflect.Descriptor instead.
|
||||
func (*Request) Descriptor() ([]byte, []int) {
|
||||
return file_internal_starlink_pb_starlink_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Request) GetRequest() isRequest_Request {
|
||||
if x != nil {
|
||||
return x.Request
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Request) GetGetStatus() *GetStatusRequest {
|
||||
if x != nil {
|
||||
if x, ok := x.Request.(*Request_GetStatus); ok {
|
||||
return x.GetStatus
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isRequest_Request interface {
|
||||
isRequest_Request()
|
||||
}
|
||||
|
||||
type Request_GetStatus struct {
|
||||
GetStatus *GetStatusRequest `protobuf:"bytes,1004,opt,name=get_status,json=getStatus,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*Request_GetStatus) isRequest_Request() {}
|
||||
|
||||
type GetStatusRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetStatusRequest) Reset() {
|
||||
*x = GetStatusRequest{}
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetStatusRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetStatusRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetStatusRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetStatusRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetStatusRequest) Descriptor() ([]byte, []int) {
|
||||
return file_internal_starlink_pb_starlink_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Types that are valid to be assigned to Response:
|
||||
//
|
||||
// *Response_DishGetStatus
|
||||
Response isResponse_Response `protobuf_oneof:"response"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Response) Reset() {
|
||||
*x = Response{}
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Response) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Response) ProtoMessage() {}
|
||||
|
||||
func (x *Response) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Response.ProtoReflect.Descriptor instead.
|
||||
func (*Response) Descriptor() ([]byte, []int) {
|
||||
return file_internal_starlink_pb_starlink_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *Response) GetResponse() isResponse_Response {
|
||||
if x != nil {
|
||||
return x.Response
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Response) GetDishGetStatus() *DishGetStatusResponse {
|
||||
if x != nil {
|
||||
if x, ok := x.Response.(*Response_DishGetStatus); ok {
|
||||
return x.DishGetStatus
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isResponse_Response interface {
|
||||
isResponse_Response()
|
||||
}
|
||||
|
||||
type Response_DishGetStatus struct {
|
||||
DishGetStatus *DishGetStatusResponse `protobuf:"bytes,2004,opt,name=dish_get_status,json=dishGetStatus,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*Response_DishGetStatus) isResponse_Response() {}
|
||||
|
||||
type DishGetStatusResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
DeviceState *DeviceState `protobuf:"bytes,2,opt,name=device_state,json=deviceState,proto3" json:"device_state,omitempty"`
|
||||
ObstructionStats *DishObstructionStats `protobuf:"bytes,1004,opt,name=obstruction_stats,json=obstructionStats,proto3" json:"obstruction_stats,omitempty"`
|
||||
Alerts *DishAlerts `protobuf:"bytes,1005,opt,name=alerts,proto3" json:"alerts,omitempty"`
|
||||
State DishState `protobuf:"varint,1006,opt,name=state,proto3,enum=SpaceX.API.Device.DishState" json:"state,omitempty"`
|
||||
PopPingDropRate float32 `protobuf:"fixed32,1003,opt,name=pop_ping_drop_rate,json=popPingDropRate,proto3" json:"pop_ping_drop_rate,omitempty"`
|
||||
DownlinkThroughputBps float32 `protobuf:"fixed32,1007,opt,name=downlink_throughput_bps,json=downlinkThroughputBps,proto3" json:"downlink_throughput_bps,omitempty"`
|
||||
UplinkThroughputBps float32 `protobuf:"fixed32,1008,opt,name=uplink_throughput_bps,json=uplinkThroughputBps,proto3" json:"uplink_throughput_bps,omitempty"`
|
||||
PopPingLatencyMs float32 `protobuf:"fixed32,1009,opt,name=pop_ping_latency_ms,json=popPingLatencyMs,proto3" json:"pop_ping_latency_ms,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DishGetStatusResponse) Reset() {
|
||||
*x = DishGetStatusResponse{}
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DishGetStatusResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DishGetStatusResponse) ProtoMessage() {}
|
||||
|
||||
func (x *DishGetStatusResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DishGetStatusResponse.ProtoReflect.Descriptor instead.
|
||||
func (*DishGetStatusResponse) Descriptor() ([]byte, []int) {
|
||||
return file_internal_starlink_pb_starlink_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *DishGetStatusResponse) GetDeviceState() *DeviceState {
|
||||
if x != nil {
|
||||
return x.DeviceState
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *DishGetStatusResponse) GetObstructionStats() *DishObstructionStats {
|
||||
if x != nil {
|
||||
return x.ObstructionStats
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *DishGetStatusResponse) GetAlerts() *DishAlerts {
|
||||
if x != nil {
|
||||
return x.Alerts
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *DishGetStatusResponse) GetState() DishState {
|
||||
if x != nil {
|
||||
return x.State
|
||||
}
|
||||
return DishState_UNKNOWN
|
||||
}
|
||||
|
||||
func (x *DishGetStatusResponse) GetPopPingDropRate() float32 {
|
||||
if x != nil {
|
||||
return x.PopPingDropRate
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DishGetStatusResponse) GetDownlinkThroughputBps() float32 {
|
||||
if x != nil {
|
||||
return x.DownlinkThroughputBps
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DishGetStatusResponse) GetUplinkThroughputBps() float32 {
|
||||
if x != nil {
|
||||
return x.UplinkThroughputBps
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DishGetStatusResponse) GetPopPingLatencyMs() float32 {
|
||||
if x != nil {
|
||||
return x.PopPingLatencyMs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type DeviceState struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UptimeS uint64 `protobuf:"varint,1,opt,name=uptime_s,json=uptimeS,proto3" json:"uptime_s,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DeviceState) Reset() {
|
||||
*x = DeviceState{}
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DeviceState) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DeviceState) ProtoMessage() {}
|
||||
|
||||
func (x *DeviceState) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DeviceState.ProtoReflect.Descriptor instead.
|
||||
func (*DeviceState) Descriptor() ([]byte, []int) {
|
||||
return file_internal_starlink_pb_starlink_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *DeviceState) GetUptimeS() uint64 {
|
||||
if x != nil {
|
||||
return x.UptimeS
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type DishObstructionStats struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
FractionObstructed float32 `protobuf:"fixed32,1,opt,name=fraction_obstructed,json=fractionObstructed,proto3" json:"fraction_obstructed,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DishObstructionStats) Reset() {
|
||||
*x = DishObstructionStats{}
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DishObstructionStats) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DishObstructionStats) ProtoMessage() {}
|
||||
|
||||
func (x *DishObstructionStats) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[5]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DishObstructionStats.ProtoReflect.Descriptor instead.
|
||||
func (*DishObstructionStats) Descriptor() ([]byte, []int) {
|
||||
return file_internal_starlink_pb_starlink_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *DishObstructionStats) GetFractionObstructed() float32 {
|
||||
if x != nil {
|
||||
return x.FractionObstructed
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type DishAlerts struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
MotorsStuck bool `protobuf:"varint,1,opt,name=motors_stuck,json=motorsStuck,proto3" json:"motors_stuck,omitempty"`
|
||||
ThermalShutdown bool `protobuf:"varint,2,opt,name=thermal_shutdown,json=thermalShutdown,proto3" json:"thermal_shutdown,omitempty"`
|
||||
ThermalThrottle bool `protobuf:"varint,3,opt,name=thermal_throttle,json=thermalThrottle,proto3" json:"thermal_throttle,omitempty"`
|
||||
UnexpectedLocation bool `protobuf:"varint,4,opt,name=unexpected_location,json=unexpectedLocation,proto3" json:"unexpected_location,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DishAlerts) Reset() {
|
||||
*x = DishAlerts{}
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DishAlerts) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DishAlerts) ProtoMessage() {}
|
||||
|
||||
func (x *DishAlerts) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_internal_starlink_pb_starlink_proto_msgTypes[6]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DishAlerts.ProtoReflect.Descriptor instead.
|
||||
func (*DishAlerts) Descriptor() ([]byte, []int) {
|
||||
return file_internal_starlink_pb_starlink_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *DishAlerts) GetMotorsStuck() bool {
|
||||
if x != nil {
|
||||
return x.MotorsStuck
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *DishAlerts) GetThermalShutdown() bool {
|
||||
if x != nil {
|
||||
return x.ThermalShutdown
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *DishAlerts) GetThermalThrottle() bool {
|
||||
if x != nil {
|
||||
return x.ThermalThrottle
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *DishAlerts) GetUnexpectedLocation() bool {
|
||||
if x != nil {
|
||||
return x.UnexpectedLocation
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var File_internal_starlink_pb_starlink_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_internal_starlink_pb_starlink_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"#internal/starlink/pb/starlink.proto\x12\x11SpaceX.API.Device\"[\n" +
|
||||
"\aRequest\x12E\n" +
|
||||
"\n" +
|
||||
"get_status\x18\xec\a \x01(\v2#.SpaceX.API.Device.GetStatusRequestH\x00R\tgetStatusB\t\n" +
|
||||
"\arequest\"\x12\n" +
|
||||
"\x10GetStatusRequest\"k\n" +
|
||||
"\bResponse\x12S\n" +
|
||||
"\x0fdish_get_status\x18\xd4\x0f \x01(\v2(.SpaceX.API.Device.DishGetStatusResponseH\x00R\rdishGetStatusB\n" +
|
||||
"\n" +
|
||||
"\bresponse\"\xea\x03\n" +
|
||||
"\x15DishGetStatusResponse\x12A\n" +
|
||||
"\fdevice_state\x18\x02 \x01(\v2\x1e.SpaceX.API.Device.DeviceStateR\vdeviceState\x12U\n" +
|
||||
"\x11obstruction_stats\x18\xec\a \x01(\v2'.SpaceX.API.Device.DishObstructionStatsR\x10obstructionStats\x126\n" +
|
||||
"\x06alerts\x18\xed\a \x01(\v2\x1d.SpaceX.API.Device.DishAlertsR\x06alerts\x123\n" +
|
||||
"\x05state\x18\xee\a \x01(\x0e2\x1c.SpaceX.API.Device.DishStateR\x05state\x12,\n" +
|
||||
"\x12pop_ping_drop_rate\x18\xeb\a \x01(\x02R\x0fpopPingDropRate\x127\n" +
|
||||
"\x17downlink_throughput_bps\x18\xef\a \x01(\x02R\x15downlinkThroughputBps\x123\n" +
|
||||
"\x15uplink_throughput_bps\x18\xf0\a \x01(\x02R\x13uplinkThroughputBps\x12.\n" +
|
||||
"\x13pop_ping_latency_ms\x18\xf1\a \x01(\x02R\x10popPingLatencyMs\"(\n" +
|
||||
"\vDeviceState\x12\x19\n" +
|
||||
"\buptime_s\x18\x01 \x01(\x04R\auptimeS\"G\n" +
|
||||
"\x14DishObstructionStats\x12/\n" +
|
||||
"\x13fraction_obstructed\x18\x01 \x01(\x02R\x12fractionObstructed\"\xb6\x01\n" +
|
||||
"\n" +
|
||||
"DishAlerts\x12!\n" +
|
||||
"\fmotors_stuck\x18\x01 \x01(\bR\vmotorsStuck\x12)\n" +
|
||||
"\x10thermal_shutdown\x18\x02 \x01(\bR\x0fthermalShutdown\x12)\n" +
|
||||
"\x10thermal_throttle\x18\x03 \x01(\bR\x0fthermalThrottle\x12/\n" +
|
||||
"\x13unexpected_location\x18\x04 \x01(\bR\x12unexpectedLocation*C\n" +
|
||||
"\tDishState\x12\v\n" +
|
||||
"\aUNKNOWN\x10\x00\x12\r\n" +
|
||||
"\tCONNECTED\x10\x01\x12\r\n" +
|
||||
"\tSEARCHING\x10\x02\x12\v\n" +
|
||||
"\aBOOTING\x10\x032K\n" +
|
||||
"\x06Device\x12A\n" +
|
||||
"\x06Handle\x12\x1a.SpaceX.API.Device.Request\x1a\x1b.SpaceX.API.Device.ResponseB<Z:git.eeqj.de/sneak/rtnetmon/internal/starlink/pb;starlinkpbb\x06proto3"
|
||||
|
||||
var (
|
||||
file_internal_starlink_pb_starlink_proto_rawDescOnce sync.Once
|
||||
file_internal_starlink_pb_starlink_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_internal_starlink_pb_starlink_proto_rawDescGZIP() []byte {
|
||||
file_internal_starlink_pb_starlink_proto_rawDescOnce.Do(func() {
|
||||
file_internal_starlink_pb_starlink_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_internal_starlink_pb_starlink_proto_rawDesc), len(file_internal_starlink_pb_starlink_proto_rawDesc)))
|
||||
})
|
||||
return file_internal_starlink_pb_starlink_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_internal_starlink_pb_starlink_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_internal_starlink_pb_starlink_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_internal_starlink_pb_starlink_proto_goTypes = []any{
|
||||
(DishState)(0), // 0: SpaceX.API.Device.DishState
|
||||
(*Request)(nil), // 1: SpaceX.API.Device.Request
|
||||
(*GetStatusRequest)(nil), // 2: SpaceX.API.Device.GetStatusRequest
|
||||
(*Response)(nil), // 3: SpaceX.API.Device.Response
|
||||
(*DishGetStatusResponse)(nil), // 4: SpaceX.API.Device.DishGetStatusResponse
|
||||
(*DeviceState)(nil), // 5: SpaceX.API.Device.DeviceState
|
||||
(*DishObstructionStats)(nil), // 6: SpaceX.API.Device.DishObstructionStats
|
||||
(*DishAlerts)(nil), // 7: SpaceX.API.Device.DishAlerts
|
||||
}
|
||||
var file_internal_starlink_pb_starlink_proto_depIdxs = []int32{
|
||||
2, // 0: SpaceX.API.Device.Request.get_status:type_name -> SpaceX.API.Device.GetStatusRequest
|
||||
4, // 1: SpaceX.API.Device.Response.dish_get_status:type_name -> SpaceX.API.Device.DishGetStatusResponse
|
||||
5, // 2: SpaceX.API.Device.DishGetStatusResponse.device_state:type_name -> SpaceX.API.Device.DeviceState
|
||||
6, // 3: SpaceX.API.Device.DishGetStatusResponse.obstruction_stats:type_name -> SpaceX.API.Device.DishObstructionStats
|
||||
7, // 4: SpaceX.API.Device.DishGetStatusResponse.alerts:type_name -> SpaceX.API.Device.DishAlerts
|
||||
0, // 5: SpaceX.API.Device.DishGetStatusResponse.state:type_name -> SpaceX.API.Device.DishState
|
||||
1, // 6: SpaceX.API.Device.Device.Handle:input_type -> SpaceX.API.Device.Request
|
||||
3, // 7: SpaceX.API.Device.Device.Handle:output_type -> SpaceX.API.Device.Response
|
||||
7, // [7:8] is the sub-list for method output_type
|
||||
6, // [6:7] is the sub-list for method input_type
|
||||
6, // [6:6] is the sub-list for extension type_name
|
||||
6, // [6:6] is the sub-list for extension extendee
|
||||
0, // [0:6] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_internal_starlink_pb_starlink_proto_init() }
|
||||
func file_internal_starlink_pb_starlink_proto_init() {
|
||||
if File_internal_starlink_pb_starlink_proto != nil {
|
||||
return
|
||||
}
|
||||
file_internal_starlink_pb_starlink_proto_msgTypes[0].OneofWrappers = []any{
|
||||
(*Request_GetStatus)(nil),
|
||||
}
|
||||
file_internal_starlink_pb_starlink_proto_msgTypes[2].OneofWrappers = []any{
|
||||
(*Response_DishGetStatus)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_internal_starlink_pb_starlink_proto_rawDesc), len(file_internal_starlink_pb_starlink_proto_rawDesc)),
|
||||
NumEnums: 1,
|
||||
NumMessages: 7,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_internal_starlink_pb_starlink_proto_goTypes,
|
||||
DependencyIndexes: file_internal_starlink_pb_starlink_proto_depIdxs,
|
||||
EnumInfos: file_internal_starlink_pb_starlink_proto_enumTypes,
|
||||
MessageInfos: file_internal_starlink_pb_starlink_proto_msgTypes,
|
||||
}.Build()
|
||||
File_internal_starlink_pb_starlink_proto = out.File
|
||||
file_internal_starlink_pb_starlink_proto_goTypes = nil
|
||||
file_internal_starlink_pb_starlink_proto_depIdxs = nil
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// A minimal slice of the Starlink dish's local gRPC API: just the one
|
||||
// unary RPC (SpaceX.API.Device.Device/Handle) and the get_status request
|
||||
// and dish status response, reduced to the handful of fields rtnetmon
|
||||
// shows. The proto package name and field numbers must match the dish
|
||||
// exactly for the wire format to line up; every other field the dish sends
|
||||
// is ignored as an unknown field.
|
||||
//
|
||||
// Field numbers, message names and the DishState enum are transcribed from
|
||||
// the community-maintained pre-generated bindings at
|
||||
// github.com/starlink-community/starlink-grpc-go, commit
|
||||
// 2e89f3d7e3092adecbcc04e9e003e61ed5f7c6a3 (get_status = 1004,
|
||||
// dish_get_status = 2004). They are not verified against a live dish here.
|
||||
//
|
||||
// Regenerate with:
|
||||
// protoc --go_out=. --go_opt=paths=source_relative \
|
||||
// --go-grpc_out=. --go-grpc_opt=paths=source_relative \
|
||||
// internal/starlink/pb/starlink.proto
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package SpaceX.API.Device;
|
||||
|
||||
option go_package = "git.eeqj.de/sneak/rtnetmon/internal/starlink/pb;starlinkpb";
|
||||
|
||||
service Device {
|
||||
rpc Handle(Request) returns (Response);
|
||||
}
|
||||
|
||||
message Request {
|
||||
oneof request {
|
||||
GetStatusRequest get_status = 1004;
|
||||
}
|
||||
}
|
||||
|
||||
message GetStatusRequest {}
|
||||
|
||||
message Response {
|
||||
oneof response {
|
||||
DishGetStatusResponse dish_get_status = 2004;
|
||||
}
|
||||
}
|
||||
|
||||
message DishGetStatusResponse {
|
||||
DeviceState device_state = 2;
|
||||
DishObstructionStats obstruction_stats = 1004;
|
||||
DishAlerts alerts = 1005;
|
||||
DishState state = 1006;
|
||||
float pop_ping_drop_rate = 1003;
|
||||
float downlink_throughput_bps = 1007;
|
||||
float uplink_throughput_bps = 1008;
|
||||
float pop_ping_latency_ms = 1009;
|
||||
}
|
||||
|
||||
message DeviceState {
|
||||
uint64 uptime_s = 1;
|
||||
}
|
||||
|
||||
message DishObstructionStats {
|
||||
float fraction_obstructed = 1;
|
||||
}
|
||||
|
||||
message DishAlerts {
|
||||
bool motors_stuck = 1;
|
||||
bool thermal_shutdown = 2;
|
||||
bool thermal_throttle = 3;
|
||||
bool unexpected_location = 4;
|
||||
}
|
||||
|
||||
enum DishState {
|
||||
UNKNOWN = 0;
|
||||
CONNECTED = 1;
|
||||
SEARCHING = 2;
|
||||
BOOTING = 3;
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
// A minimal slice of the Starlink dish's local gRPC API: just the one
|
||||
// unary RPC (SpaceX.API.Device.Device/Handle) and the get_status request
|
||||
// and dish status response, reduced to the handful of fields rtnetmon
|
||||
// shows. The proto package name and field numbers must match the dish
|
||||
// exactly for the wire format to line up; every other field the dish sends
|
||||
// is ignored as an unknown field.
|
||||
//
|
||||
// Field numbers, message names and the DishState enum are transcribed from
|
||||
// the community-maintained pre-generated bindings at
|
||||
// github.com/starlink-community/starlink-grpc-go, commit
|
||||
// 2e89f3d7e3092adecbcc04e9e003e61ed5f7c6a3 (get_status = 1004,
|
||||
// dish_get_status = 2004). They are not verified against a live dish here.
|
||||
//
|
||||
// Regenerate with:
|
||||
// protoc --go_out=. --go_opt=paths=source_relative \
|
||||
// --go-grpc_out=. --go-grpc_opt=paths=source_relative \
|
||||
// internal/starlink/pb/starlink.proto
|
||||
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v7.36.2
|
||||
// source: internal/starlink/pb/starlink.proto
|
||||
|
||||
package starlinkpb
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
Device_Handle_FullMethodName = "/SpaceX.API.Device.Device/Handle"
|
||||
)
|
||||
|
||||
// DeviceClient is the client API for Device service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type DeviceClient interface {
|
||||
Handle(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error)
|
||||
}
|
||||
|
||||
type deviceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewDeviceClient(cc grpc.ClientConnInterface) DeviceClient {
|
||||
return &deviceClient{cc}
|
||||
}
|
||||
|
||||
func (c *deviceClient) Handle(ctx context.Context, in *Request, opts ...grpc.CallOption) (*Response, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(Response)
|
||||
err := c.cc.Invoke(ctx, Device_Handle_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// DeviceServer is the server API for Device service.
|
||||
// All implementations must embed UnimplementedDeviceServer
|
||||
// for forward compatibility.
|
||||
type DeviceServer interface {
|
||||
Handle(context.Context, *Request) (*Response, error)
|
||||
mustEmbedUnimplementedDeviceServer()
|
||||
}
|
||||
|
||||
// UnimplementedDeviceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedDeviceServer struct{}
|
||||
|
||||
func (UnimplementedDeviceServer) Handle(context.Context, *Request) (*Response, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Handle not implemented")
|
||||
}
|
||||
func (UnimplementedDeviceServer) mustEmbedUnimplementedDeviceServer() {}
|
||||
func (UnimplementedDeviceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeDeviceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to DeviceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeDeviceServer interface {
|
||||
mustEmbedUnimplementedDeviceServer()
|
||||
}
|
||||
|
||||
func RegisterDeviceServer(s grpc.ServiceRegistrar, srv DeviceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedDeviceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&Device_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _Device_Handle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Request)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(DeviceServer).Handle(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Device_Handle_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(DeviceServer).Handle(ctx, req.(*Request))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Device_ServiceDesc is the grpc.ServiceDesc for Device service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var Device_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "SpaceX.API.Device.Device",
|
||||
HandlerType: (*DeviceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Handle",
|
||||
Handler: _Device_Handle_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "internal/starlink/pb/starlink.proto",
|
||||
}
|
||||
Reference in New Issue
Block a user