satellite-gtk/satellite/util.py

82 lines
2.4 KiB
Python

# Copyright 2021-2022 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
import os
from datetime import datetime, timezone
import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk # noqa: E402
gps_epoch = datetime(1980, 1, 6, 0, 0, tzinfo=timezone.utc)
now = datetime.now(timezone.utc)
one_week = 7 * 24 * 60 * 60
week_now = int((now.timestamp() - gps_epoch.timestamp()) / one_week)
def have_touchscreen():
"""Return True if the default seat of default display has touch capability."""
return bool(Gdk.Display.get_default_seat(
Gdk.Display.get_default()).get_capabilities() & Gdk.SeatCapabilities.TOUCH)
def datetime_from_gpstime(week, millisecs, fix_week=False):
"""Return a datetime from GPS week number and milliseconds from week start.
If fix_week is True, set the bits above 10 in week number from
current date, see
https://en.wikipedia.org/wiki/GPS_week_number_rollover
"""
if fix_week:
week = (week & 0b1111111111) + ((week_now >> 10) << 10)
return datetime.fromtimestamp(
gps_epoch.timestamp() + week * one_week + (millisecs / 1000),
timezone.utc)
def gpstime_from_datetime(dt):
"""Return a (gps_week, millisec) tuple from a datetime object."""
if dt < gps_epoch:
raise ValueError("Time cannot be less than GPS epoch")
ts = dt.timestamp()
epoch_ts = gps_epoch.timestamp()
gps_week = int((ts - epoch_ts) / one_week)
millisecs = 1000 * int(ts - epoch_ts - (gps_week * one_week))
return gps_week, millisecs
def unique_filename(namestem, ext, timestamp=False):
if timestamp:
namestem += "-" + datetime.now().isoformat(
'_', 'seconds').replace(':', '.')
name = None
for count in ('~%d' % n if n > 0 else '' for n in range(100)):
test = namestem + count + ext
if os.path.exists(test):
continue
else:
name = test
break
return name
def bearing_to_arrow(bearing):
# Arrows in bearing order, with up arrow (north) repeating at the end
arrows = [
'\u2191',
'\u2197',
'\u2192',
'\u2198',
'\u2193',
'\u2199',
'\u2190',
'\u2196',
'\u2191',
]
edges = [22.5 + 45.0 * n for n in range(0, 8)] + [360.0]
angle = bearing - (bearing // 360) * 360
index = next(ind for (ind, e) in enumerate(edges) if angle < e)
return arrows[index]