#!/usr/bin/env python3
"""
gnss_info.py - Retrieve GNSS (GPS) information from a GRX receiver.

This example queries the Monitoring API for the device's GNSS status,
including position fix, satellite count, timing accuracy, and location.

Usage:
    python gnss_info.py [HOST]

Arguments:
    HOST    IP address or hostname of the GRX (default: YOUR_GRX_IP)

Prerequisites:
    pip install grpcio grpcio-tools
    Run gen_pb.sh to generate the Python bindings.
"""

import sys

import grpc
from google.protobuf.empty_pb2 import Empty

# Import the generated gRPC stubs for the Monitoring API
import Monitord_pb2 as monitord_pb2
import Monitord_pb2_grpc

# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------

host = sys.argv[1] if len(sys.argv) >= 2 else "YOUR_GRX_IP"

# The Monitoring API listens on TCP port 5305
MONITORD_PORT = 5305

# ---------------------------------------------------------------------------
# Connect to the GRX receiver
# ---------------------------------------------------------------------------

print(f"Connecting to {host}:{MONITORD_PORT}...")
channel = grpc.insecure_channel(f"{host}:{MONITORD_PORT}")
monitord = Monitord_pb2_grpc.MonitordStub(channel)

# ---------------------------------------------------------------------------
# Query GNSS information
# ---------------------------------------------------------------------------

info = monitord.GetGNSSInformation(Empty())

# Map fix type enum values to human-readable strings.
# Values are defined in GNSSInformation.Position.FixType:
#   None=0, Pos2D=2, Pos3D=3, TimeOnly=5
fix_type_names = {
    0: "No fix",
    2: "2D position fix",
    3: "3D position fix",
    5: "Time only (stationary mode)",
}

# Position
pos = info.position
fix_name = fix_type_names.get(pos.fix_type, f"Unknown ({pos.fix_type})")

print(f"\nGNSS Position:")
print(f"  Fix type:              {fix_name}")
print(f"  Satellites used:       {pos.sats_used}")

if pos.fix_type >= 2:  # Pos2D or better
    print(f"  Latitude:              {pos.latitude:.6f}°")
    print(f"  Longitude:             {pos.longitude:.6f}°")
    print(f"  Horizontal accuracy:   {pos.horizontal_accuracy:.1f} m")

if pos.fix_type >= 3:  # Pos3D or better
    print(f"  Height (WGS-84):       {pos.height:.1f} m")
    print(f"  Vertical accuracy:     {pos.vertical_accuracy:.1f} m")

# Timing
timing = info.timing
print(f"\nGNSS Timing:")
if timing.utc.valid:
    print(f"  UTC:                   {timing.utc.year:04d}-{timing.utc.month:02d}-"
          f"{timing.utc.day:02d} {timing.utc.hour:02d}:{timing.utc.min:02d}:"
          f"{timing.utc.sec:02d}")

print(f"  Time pulse locked:     {'yes' if timing.time_pulse_locked else 'no'}")
print(f"  Time pulse in tol.:    {'yes' if timing.time_pulse_within_tolerance else 'no'}")
print(f"  GNSS time accuracy:    {timing.gnss_time_accuracy} ns")

# Hardware monitoring
hw = info.hardware
print(f"\nGNSS Hardware:")
print(f"  Noise level:           {hw.noise_level}")
print(f"  AGC monitor:           {hw.agc_monitor}")
print(f"  Jamming indicator:     {hw.jamming_indicator}")

# ---------------------------------------------------------------------------
# Clean up
# ---------------------------------------------------------------------------

channel.close()
