From f15dd098e3d6bbeefd24b0f0fce1993251068c02 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Thu, 17 Nov 2022 21:04:47 +0200
Subject: [PATCH 01/50] More GLib.SOURCE_REMOVE usage in return values
---
satellite/application.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/satellite/application.py b/satellite/application.py
index 5888ff4..f863118 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -192,7 +192,7 @@ class SatelliteApp(Gtk.Application):
if not source_init:
self.log_msg('No NmeaSource initialized')
- return False # Remove from idle_add
+ return GLib.SOURCE_REMOVE
self.log_msg(
f"Source is {self.source.manufacturer}, model {self.source.model}"
From ffd3f29ae308faf370d325fa6f2d0699fd996cc8 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Thu, 17 Nov 2022 21:05:31 +0200
Subject: [PATCH 02/50] Log messages to the app window before initializing
Use GLib.timeout_add instead of idle_add to have the window drawn and
messages logged before starting source initialization.
---
satellite/application.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/satellite/application.py b/satellite/application.py
index f863118..d76493a 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -161,8 +161,6 @@ class SatelliteApp(Gtk.Application):
def on_startup(self, app):
self.create_actions()
- # Initialize modem after GUI startup
- GLib.idle_add(self.init_source)
def on_activate(self, app):
self.setup_styles()
@@ -171,6 +169,11 @@ class SatelliteApp(Gtk.Application):
if have_touchscreen():
self.datascroll.connect('edge-overshot', self.on_edge_overshot)
+ self.log_msg(f"{appname} version {__version__} started")
+ self.log_msg(f'Trying to initialize source "{self.args.source}"')
+ # Initialize modem after GUI startup
+ GLib.timeout_add(1000, self.init_source, None)
+
def on_shutdown(self, app):
"""Called after main loop exits."""
print("Cleaning up...")
@@ -179,12 +182,9 @@ class SatelliteApp(Gtk.Application):
self.source.close()
print("...done.")
- def init_source(self):
- self.log_msg(f"{appname} version {__version__} started")
+ def init_source(self, unused):
source_init = False
- self.log_msg(f'Trying to initialize source "{self.args.source}"')
-
if self.args.source == 'quectel':
source_init = self.init_quectel_source()
elif self.args.source == 'gnss-share':
From bef48e40560405c00586fa67b4d8b42cc02fc11f Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 18 Nov 2022 14:07:41 +0200
Subject: [PATCH 03/50] Update display also when new NMEAs are not received
---
satellite/application.py | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/satellite/application.py b/satellite/application.py
index d76493a..99db4bd 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -573,16 +573,19 @@ class SatelliteApp(Gtk.Application):
self.log_msg(dtext)
return
- if not nmeas:
+ if not nmeas and self.last_data is None:
return
- if self.source_lost:
- self.log_msg("Modem appeared")
- self.main_box.set_sensitive(True)
+ if nmeas:
+ if self.source_lost:
+ self.log_msg("Modem appeared")
+ self.main_box.set_sensitive(True)
- self.source_lost = False
+ self.source_lost = False
+ data = nmea.parse(nmeas)
+ else:
+ data = self.last_data
- data = nmea.parse(nmeas)
data["updateage"] = ((time.time() - self.last_update)
if self.last_update else None)
From 93cb27fb27aee6d0491380c8b2637860ab95b2ac Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 18 Nov 2022 14:21:32 +0200
Subject: [PATCH 04/50] Simplify error handling in update()
---
satellite/application.py | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/satellite/application.py b/satellite/application.py
index 99db4bd..0b0933c 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -540,7 +540,6 @@ class SatelliteApp(Gtk.Application):
try:
nmeas = self.source.get()
except Exception as e:
- fatal = False
show_dialog = False
etext = str(e)
dtext = None
@@ -563,15 +562,12 @@ class SatelliteApp(Gtk.Application):
parent=self.window, modal=True,
message_type=Gtk.MessageType.ERROR,
buttons=Gtk.ButtonsType.OK, text=dtext)
- dialog.set_title("Unrecoverable error" if fatal else "Error")
+ dialog.set_title("Error")
dialog.run()
dialog.destroy()
- if fatal:
- self.quit()
- return
elif dtext is not None:
self.log_msg(dtext)
- return
+ nmeas = None
if not nmeas and self.last_data is None:
return
From 0861c78c7656696ca8e2ebdfb66ee838fea2a53e Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 18 Nov 2022 15:43:01 +0200
Subject: [PATCH 05/50] Yet Another Error Handling Refactor
---
satellite/application.py | 53 ++++++++++++++++++++--------------------
1 file changed, 26 insertions(+), 27 deletions(-)
diff --git a/satellite/application.py b/satellite/application.py
index 0b0933c..8fc1b50 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -117,7 +117,7 @@ class SatelliteApp(Gtk.Application):
self.last_data = None
self.last_speed = None
self.last_update = None
- self.source_lost = False
+ self.had_error = False
self.sigint_received = False
self.refresh_rate = 1 # Really delay between updates in seconds
@@ -539,7 +539,14 @@ class SatelliteApp(Gtk.Application):
def update(self):
try:
nmeas = self.source.get()
+ if self.had_error:
+ self.log_msg("Getting updates")
+ self.main_box.set_sensitive(True)
+
+ self.had_error = False
+ data = nmea.parse(nmeas)
except Exception as e:
+ nmeas = None
show_dialog = False
etext = str(e)
dtext = None
@@ -551,36 +558,28 @@ class SatelliteApp(Gtk.Application):
elif isinstance(e, ModemError):
dtext = "Modem error: " + str(e)
elif isinstance(e, NmeaSourceNotFoundError):
- if not self.source_lost:
+ if not self.had_error:
dtext = etext if etext else "Modem disappeared"
- self.source_lost = True
+ self.had_error = True
self.main_box.set_sensitive(False)
else:
dtext = etext if etext else "Unknown error"
- if show_dialog:
- dialog = Gtk.MessageDialog(
- parent=self.window, modal=True,
- message_type=Gtk.MessageType.ERROR,
- buttons=Gtk.ButtonsType.OK, text=dtext)
- dialog.set_title("Error")
- dialog.run()
- dialog.destroy()
- elif dtext is not None:
- self.log_msg(dtext)
- nmeas = None
-
- if not nmeas and self.last_data is None:
- return
-
- if nmeas:
- if self.source_lost:
- self.log_msg("Modem appeared")
- self.main_box.set_sensitive(True)
-
- self.source_lost = False
- data = nmea.parse(nmeas)
- else:
- data = self.last_data
+ if not self.had_error:
+ if show_dialog:
+ dialog = Gtk.MessageDialog(
+ parent=self.window, modal=True,
+ message_type=Gtk.MessageType.ERROR,
+ buttons=Gtk.ButtonsType.OK, text=dtext)
+ dialog.set_title("Error")
+ dialog.run()
+ dialog.destroy()
+ elif dtext is not None:
+ self.log_msg(dtext)
+ self.had_error = True
+ if self.last_data is None:
+ return
+ else:
+ data = self.last_data
data["updateage"] = ((time.time() - self.last_update)
if self.last_update else None)
From 760f80fb49f103e6d940ae75f547b47e61c28dc0 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Mon, 16 Jan 2023 16:12:11 +0200
Subject: [PATCH 06/50] Split PyDBus based ModemManager source to its own file
---
satellite/application.py | 2 +-
satellite/mm_pydbus_source.py | 128 ++++++++++++++++++++++++++++++++++
satellite/nmeasource.py | 116 ------------------------------
3 files changed, 129 insertions(+), 117 deletions(-)
create mode 100644 satellite/mm_pydbus_source.py
diff --git a/satellite/application.py b/satellite/application.py
index 8fc1b50..0404f54 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -16,12 +16,12 @@ import importlib.resources as resources
import satellite.nmea as nmea
import satellite.quectel as quectel
+from .mm_pydbus_source import QuectelNmeaSource
from .nmeasource import (
ModemNoNMEAError,
ModemLockedError,
ModemError,
NmeaSourceNotFoundError,
- QuectelNmeaSource,
GnssShareNmeaSource,
)
from .util import bearing_to_arrow, have_touchscreen, now, unique_filename
diff --git a/satellite/mm_pydbus_source.py b/satellite/mm_pydbus_source.py
new file mode 100644
index 0000000..aa2fea1
--- /dev/null
+++ b/satellite/mm_pydbus_source.py
@@ -0,0 +1,128 @@
+# Copyright 2021-2023 Teemu Ikonen
+# SPDX-License-Identifier: GPL-3.0-only
+
+import re
+import satellite.modem_manager_defs as mm
+from satellite.nmeasource import (
+ NmeaSource,
+ NmeaSourceNotFoundError,
+ ModemError,
+ ModemLockedError,
+ ModemNoNMEAError,
+)
+
+from pydbus import SystemBus
+from pynmea2.nmea import NMEASentence
+
+
+class ModemManagerPyDBusNmeaSource(NmeaSource):
+
+ def __init__(self, update_callback, **kwargs):
+ super().__init__(update_callback, **kwargs)
+ self.bus = SystemBus()
+ self.manager = self.bus.get('.ModemManager1')
+ self.modem = None
+ self.old_refresh_rate = None
+ self.old_sources_enabled = None
+ self.old_signals = None
+ self.location_updated = None
+
+ def initialize(self):
+ objs = self.manager.GetManagedObjects()
+ mkeys = list(objs.keys())
+ if mkeys:
+ mstr = mkeys[0]
+ else:
+ raise NmeaSourceNotFoundError("No Modems Found")
+ info = objs[mstr]['org.freedesktop.ModemManager1.Modem']
+ self.manufacturer = info.get('Manufacturer')
+ self.model = info.get('Model')
+ self.revision = info.get('Revision')
+ self.modem = self.bus.get('.ModemManager1', mstr)
+
+ try:
+ if self.modem.State > 0:
+ if self.old_refresh_rate is None:
+ self.old_refresh_rate = self.modem.GpsRefreshRate
+ if self.old_sources_enabled is None:
+ self.old_sources_enabled = self.modem.Enabled
+ if self.old_signals is None:
+ self.old_signals = self.modem.SignalsLocation
+ cap = self.modem.Capabilities
+ if (cap & mm.MM_MODEM_LOCATION_SOURCE_GPS_NMEA) == 0:
+ raise NmeaSourceNotFoundError(
+ "Modem does not support NMEA")
+ self.modem.Setup(
+ (mm.MM_MODEM_LOCATION_SOURCE_GPS_NMEA
+ | (cap & mm.MM_MODEM_LOCATION_SOURCE_AGPS_MSB)),
+ True)
+ else:
+ raise ModemError("Modem state is: %d" % self.modem.State)
+ except AttributeError as e:
+ if self.modem.State == mm.MM_MODEM_STATE_LOCKED:
+ raise ModemLockedError from e
+ else:
+ raise ModemError from e
+ except Exception as e:
+ raise e
+
+ self.modem.SetGpsRefreshRate(self.refresh_rate)
+ self.location_updated = self.bus.subscribe(
+ sender='org.freedesktop.ModemManager1',
+ iface='org.freedesktop.DBus.Properties',
+ signal='PropertiesChanged',
+ arg0='org.freedesktop.ModemManager1.Modem.Location',
+ signal_fired=self.update_callback)
+ self.initialized = True
+
+ def _really_get(self):
+ if not self.initialized:
+ self.initialize()
+ try:
+ loc = self.modem.GetLocation()
+ except Exception as e:
+ self.initialized = False
+ raise e
+
+ retval = loc.get(mm.MM_MODEM_LOCATION_SOURCE_GPS_NMEA)
+ if retval is None:
+ self.initialized = False
+ raise ModemNoNMEAError
+ return retval
+
+ def close(self):
+ if self.location_updated is not None:
+ self.location_updated.disconnect()
+ if self.old_sources_enabled is not None:
+ self.modem.Setup(self.old_sources_enabled, self.old_signals)
+ if self.old_refresh_rate is not None:
+ self.modem.SetGpsRefreshRate(self.old_refresh_rate)
+
+
+class QuectelNmeaSource(ModemManagerPyDBusNmeaSource):
+
+ def _really_get(self):
+ return self.fix_talker(super()._really_get())
+
+ def fix_talker(self, nmeas):
+ pq_re = re.compile(r'''
+ ^\s*\$?
+ (?PPQ)
+ (?P\w{3})
+ (?P[^*]*)
+ (?:[*](?P[A-F0-9]{2}))$''', re.VERBOSE)
+ out = []
+ for nmea in (n for n in nmeas.split('\r\n') if n):
+ mo = pq_re.match(nmea)
+ if mo:
+ # The last extra data field is Signal ID, these are
+ # 1 = GPS, 2 = Glonass, 3 = Galileo, 4 = BeiDou, 5 = QZSS
+ # Determine talker from Signal ID
+ talker = 'QZ' if mo.group('data').endswith('5') else 'BD'
+ # Fake talker and checksum
+ fake = talker + "".join(mo.group(2, 3))
+ out.append('$' + fake + "*%02X" % NMEASentence.checksum(fake))
+ else:
+ out.append(nmea)
+
+ return "\r\n".join(out)
diff --git a/satellite/nmeasource.py b/satellite/nmeasource.py
index 835d682..e685e76 100644
--- a/satellite/nmeasource.py
+++ b/satellite/nmeasource.py
@@ -1,12 +1,8 @@
# Copyright 2021-2022 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
-import re
-import satellite.modem_manager_defs as mm
import os.path
import socket
-from pydbus import SystemBus
-from pynmea2.nmea import NMEASentence
from gi.repository import GLib
@@ -115,118 +111,6 @@ class GnssShareNmeaSource(UnixSocketNmeaSource):
**kwargs)
-class ModemManagerNmeaSource(NmeaSource):
- def __init__(self, update_callback, **kwargs):
- super().__init__(update_callback, **kwargs)
- self.bus = SystemBus()
- self.manager = self.bus.get('.ModemManager1')
- self.modem = None
- self.old_refresh_rate = None
- self.old_sources_enabled = None
- self.old_signals = None
- self.location_updated = None
-
- def initialize(self):
- objs = self.manager.GetManagedObjects()
- mkeys = list(objs.keys())
- if mkeys:
- mstr = mkeys[0]
- else:
- raise NmeaSourceNotFoundError("No Modems Found")
- info = objs[mstr]['org.freedesktop.ModemManager1.Modem']
- self.manufacturer = info.get('Manufacturer')
- self.model = info.get('Model')
- self.revision = info.get('Revision')
- self.modem = self.bus.get('.ModemManager1', mstr)
-
- try:
- if self.modem.State > 0:
- if self.old_refresh_rate is None:
- self.old_refresh_rate = self.modem.GpsRefreshRate
- if self.old_sources_enabled is None:
- self.old_sources_enabled = self.modem.Enabled
- if self.old_signals is None:
- self.old_signals = self.modem.SignalsLocation
- cap = self.modem.Capabilities
- if (cap & mm.MM_MODEM_LOCATION_SOURCE_GPS_NMEA) == 0:
- raise NmeaSourceNotFoundError(
- "Modem does not support NMEA")
- self.modem.Setup(
- (mm.MM_MODEM_LOCATION_SOURCE_GPS_NMEA
- | (cap & mm.MM_MODEM_LOCATION_SOURCE_AGPS_MSB)),
- True)
- else:
- raise ModemError("Modem state is: %d" % self.modem.State)
- except AttributeError as e:
- if self.modem.State == mm.MM_MODEM_STATE_LOCKED:
- raise ModemLockedError from e
- else:
- raise ModemError from e
- except Exception as e:
- raise e
-
- self.modem.SetGpsRefreshRate(self.refresh_rate)
- self.location_updated = self.bus.subscribe(
- sender='org.freedesktop.ModemManager1',
- iface='org.freedesktop.DBus.Properties',
- signal='PropertiesChanged',
- arg0='org.freedesktop.ModemManager1.Modem.Location',
- signal_fired=self.update_callback)
- self.initialized = True
-
- def _really_get(self):
- if not self.initialized:
- self.initialize()
- try:
- loc = self.modem.GetLocation()
- except Exception as e:
- self.initialized = False
- raise e
-
- retval = loc.get(mm.MM_MODEM_LOCATION_SOURCE_GPS_NMEA)
- if retval is None:
- self.initialized = False
- raise ModemNoNMEAError
- return retval
-
- def close(self):
- if self.location_updated is not None:
- self.location_updated.disconnect()
- if self.old_sources_enabled is not None:
- self.modem.Setup(self.old_sources_enabled, self.old_signals)
- if self.old_refresh_rate is not None:
- self.modem.SetGpsRefreshRate(self.old_refresh_rate)
-
-
-class QuectelNmeaSource(ModemManagerNmeaSource):
-
- def _really_get(self):
- return self.fix_talker(super()._really_get())
-
- def fix_talker(self, nmeas):
- pq_re = re.compile(r'''
- ^\s*\$?
- (?PPQ)
- (?P\w{3})
- (?P[^*]*)
- (?:[*](?P[A-F0-9]{2}))$''', re.VERBOSE)
- out = []
- for nmea in (n for n in nmeas.split('\r\n') if n):
- mo = pq_re.match(nmea)
- if mo:
- # The last extra data field is Signal ID, these are
- # 1 = GPS, 2 = Glonass, 3 = Galileo, 4 = BeiDou, 5 = QZSS
- # Determine talker from Signal ID
- talker = 'QZ' if mo.group('data').endswith('5') else 'BD'
- # Fake talker and checksum
- fake = talker + "".join(mo.group(2, 3))
- out.append('$' + fake + "*%02X" % NMEASentence.checksum(fake))
- else:
- out.append(nmea)
-
- return "\r\n".join(out)
-
-
class ReplayNmeaSource(NmeaSource):
def __init__(self, update_callback, replay_filename=None, refresh_rate=1,
**kwargs):
From 3ebf88d0f773681be640a33404fa994efa1b2ac9 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Thu, 19 Jan 2023 14:03:11 +0200
Subject: [PATCH 07/50] Linter config improvements, code style fixes
---
satellite/application.py | 45 ++++++++++++++++-------------------
satellite/mm_pydbus_source.py | 21 ++++++++--------
satellite/nmea.py | 11 +++++----
satellite/quectel.py | 1 -
satellite/util.py | 15 +++++-------
satellite/widgets.py | 12 ++++------
setup.cfg | 5 ++++
7 files changed, 54 insertions(+), 56 deletions(-)
diff --git a/satellite/application.py b/satellite/application.py
index 0404f54..908aadd 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -2,8 +2,7 @@
# SPDX-License-Identifier: GPL-3.0-only
import argparse
-import gi
-import gpxpy
+import importlib.resources as resources
import os
import re
import signal
@@ -12,26 +11,28 @@ import time
import tokenize
from datetime import datetime
-import importlib.resources as resources
+import gi
+import gpxpy
import satellite.nmea as nmea
import satellite.quectel as quectel
+from satellite import __version__
+
from .mm_pydbus_source import QuectelNmeaSource
from .nmeasource import (
- ModemNoNMEAError,
- ModemLockedError,
- ModemError,
- NmeaSourceNotFoundError,
GnssShareNmeaSource,
+ ModemError,
+ ModemLockedError,
+ ModemNoNMEAError,
+ NmeaSourceNotFoundError,
)
from .util import bearing_to_arrow, have_touchscreen, now, unique_filename
-from .widgets import text_barchart, DataFrame
-from satellite import __version__
+from .widgets import DataFrame, text_barchart
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
gi.require_version('Handy', '1')
-from gi.repository import Gdk, Gio, GLib, Gtk, Handy # noqa: E402
+from gi.repository import GLib, Gdk, Gio, Gtk, Handy # noqa: E402, I100
appname = 'Satellite'
app_id = 'page.codeberg.tpikonen.satellite'
@@ -54,9 +55,9 @@ class SatelliteApp(Gtk.Application):
parser.add_argument(
'-s', '--source', dest='source',
default='quectel',
- help='Select NMEA source. Options are '
- '\'quectel\' (default) for Quectel Modems or '
- '\'gnss-share\' when using gnss-share')
+ help="Select NMEA source. Options are "
+ "\'quectel\' (default) for Quectel Modems or "
+ "\'gnss-share\' when using gnss-share")
self.args = parser.parse_args()
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT,
@@ -90,7 +91,7 @@ class SatelliteApp(Gtk.Application):
self.source = None
- self.infolabel.set_markup("" + "\n"*10 + "")
+ self.infolabel.set_markup("" + "\n" * 10 + "")
self.dataframe = DataFrame()
# self.dataframe.header.set_text("Satellite info")
@@ -175,7 +176,6 @@ class SatelliteApp(Gtk.Application):
GLib.timeout_add(1000, self.init_source, None)
def on_shutdown(self, app):
- """Called after main loop exits."""
print("Cleaning up...")
self.gpx_write()
if self.source is not None:
@@ -418,16 +418,14 @@ class SatelliteApp(Gtk.Application):
("mode_indicator", "Modes (GP,GL,GA)", lambda x: str(x)),
("actives", "Active / in use sats", get_actives),
("visibles", "Receiving sats", lambda x: str(len(
- list(r for r in x if r['snr'] > 0.0)))),
+ [r for r in x if r['snr'] > 0.0]))),
("visibles", "Visible sats", lambda x: str(len(x))),
# ("fixage", "Age of fix", lambda x: to_str(x, "%0.0f s")),
("fixage", "Age of update / fix", get_ages),
("systime", "Sys. Time", lambda x: x.strftime(utcfmt)),
- ("latlon", "Latitude",
- lambda x: "%0.6f" % x[0] if x else "-"),
- ("latlon", "Longitude",
- lambda x: "%0.6f" % x[1] if x else "-"),
- ("altitude", "Altitude", lambda x: to_str(x, "%0.1f m")),
+ ("latlon", "Latitude", lambda x: "%0.6f" % x[0] if x else "-"),
+ ("latlon", "Longitude", lambda x: "%0.6f" % x[1] if x else "-"),
+ ("altitude", "Altitude", lambda x: to_str(x, "%0.1f m")),
# ("fixtime", "Time of fix",
# lambda x: x.strftime(utcfmt) if x else "-"),
# ("date", "Date of fix",
@@ -471,10 +469,9 @@ class SatelliteApp(Gtk.Application):
self.last_mode = mode
def set_speedlabel(self, speed, bearing=None):
- spd = str(int(3.6*speed)) if speed else "-"
+ spd = str(int(3.6 * speed)) if speed else "-"
arrow = bearing_to_arrow(bearing) if bearing is not None else ""
- speedfmt = ('%s%s\n' +
- '%s')
+ speedfmt = '%s%s\n%s'
speedstr = speedfmt % (spd, arrow, "km/h")
self.speedlabel.set_markup(speedstr)
diff --git a/satellite/mm_pydbus_source.py b/satellite/mm_pydbus_source.py
index aa2fea1..a946a92 100644
--- a/satellite/mm_pydbus_source.py
+++ b/satellite/mm_pydbus_source.py
@@ -2,18 +2,19 @@
# SPDX-License-Identifier: GPL-3.0-only
import re
-import satellite.modem_manager_defs as mm
-from satellite.nmeasource import (
- NmeaSource,
- NmeaSourceNotFoundError,
- ModemError,
- ModemLockedError,
- ModemNoNMEAError,
-)
from pydbus import SystemBus
from pynmea2.nmea import NMEASentence
+import satellite.modem_manager_defs as mm
+from satellite.nmeasource import (
+ ModemError,
+ ModemLockedError,
+ ModemNoNMEAError,
+ NmeaSource,
+ NmeaSourceNotFoundError,
+)
+
class ModemManagerPyDBusNmeaSource(NmeaSource):
@@ -105,12 +106,12 @@ class QuectelNmeaSource(ModemManagerPyDBusNmeaSource):
return self.fix_talker(super()._really_get())
def fix_talker(self, nmeas):
- pq_re = re.compile(r'''
+ pq_re = re.compile(r"""
^\s*\$?
(?PPQ)
(?P\w{3})
(?P[^*]*)
- (?:[*](?P[A-F0-9]{2}))$''', re.VERBOSE)
+ (?:[*](?P[A-F0-9]{2}))$""", re.VERBOSE)
out = []
for nmea in (n for n in nmeas.split('\r\n') if n):
mo = pq_re.match(nmea)
diff --git a/satellite/nmea.py b/satellite/nmea.py
index 650dce0..9d13847 100644
--- a/satellite/nmea.py
+++ b/satellite/nmea.py
@@ -2,9 +2,10 @@
# SPDX-License-Identifier: GPL-3.0-only
import datetime
-import pynmea2
import re
+import pynmea2
+
MS_PER_KNOT = 0.514444
lastfix_dt = None
@@ -61,9 +62,9 @@ def get_latlon(mdict):
lat_min = float(lat[2:])
lon_deg = float(lon[:3])
lon_min = float(lon[3:])
- flat = lat_deg + lat_min/60
+ flat = lat_deg + lat_min / 60
flat = -1 * flat if lat_dir == 'S' else flat
- flon = lon_deg + lon_min/60
+ flon = lon_deg + lon_min / 60
flon = -1 * flon if lon_dir == 'W' else flon
return (flat, flon)
@@ -182,7 +183,7 @@ def parse(nmeas, always_add_prefix=False):
return float(s) if s else empty_val
def add_prn_prefix(prns, talker, always=always_add_prefix):
- """Add constellation prefix to PRN string"""
+ """Add constellation prefix to PRN string."""
beidou_prefix = "C"
galileo_prefix = "E"
glonass_prefix = "R"
@@ -227,7 +228,7 @@ def parse(nmeas, always_add_prefix=False):
'snr': fl(getattr(msg, f'snr_{n}', None), 0.0),
})
elif isinstance(msg, pynmea2.types.GSA):
- for n in range(1, 12+1):
+ for n in range(1, 12 + 1):
prns = getattr(msg, f'sv_id{n:02d}')
if prns and prns.isdigit():
actives.append(add_prn_prefix(prns, msg.talker))
diff --git a/satellite/quectel.py b/satellite/quectel.py
index 79047f8..e009832 100644
--- a/satellite/quectel.py
+++ b/satellite/quectel.py
@@ -2,7 +2,6 @@
# SPDX-License-Identifier: GPL-3.0-only
import re
-
from datetime import datetime, timezone
from .util import (
diff --git a/satellite/util.py b/satellite/util.py
index 5f8b7e8..02881fd 100644
--- a/satellite/util.py
+++ b/satellite/util.py
@@ -1,11 +1,10 @@
# Copyright 2021-2022 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
-import gi
import os
-
from datetime import datetime, timezone
+import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk # noqa: E402
@@ -16,15 +15,13 @@ 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 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 object formed from GPS week number and
- milliseconds from week start.
+ """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
@@ -38,7 +35,7 @@ def datetime_from_gpstime(week, millisecs, fix_week=False):
def gpstime_from_datetime(dt):
- """Return a (gps_week, millisec) tuple from a datetime object"""
+ """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()
@@ -51,7 +48,7 @@ def gpstime_from_datetime(dt):
def unique_filename(namestem, ext, timestamp=False):
if timestamp:
namestem += "-" + datetime.now().isoformat(
- '_', 'seconds').replace(':', '.')
+ '_', 'seconds').replace(':', '.')
name = None
for count in ('~%d' % n if n > 0 else '' for n in range(100)):
test = namestem + count + ext
@@ -77,7 +74,7 @@ def bearing_to_arrow(bearing):
'\u2196',
'\u2191',
]
- edges = list(22.5 + 45.0 * n for n in range(0, 8)) + [360.0]
+ 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)
diff --git a/satellite/widgets.py b/satellite/widgets.py
index d421720..23f768c 100644
--- a/satellite/widgets.py
+++ b/satellite/widgets.py
@@ -1,10 +1,9 @@
# Copyright 2021-2022 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
-import gi
-
import importlib.resources as resources
+import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk # noqa: E402
@@ -18,8 +17,7 @@ def text_barchart(data, highlights, height=None, width=30):
height Number of lines in the generated bar chart
width Width of the generated bar chart in chars
"""
- sdata = list((d[0] if d[0] else '',
- int(d[1]) if d[1] else 0) for d in data)
+ sdata = [(d[0] if d[0] else '', int(d[1]) if d[1] else 0) for d in data]
sdata.sort(key=lambda x: x[1], reverse=True)
dstr = ''
@@ -41,14 +39,14 @@ def text_barchart(data, highlights, height=None, width=30):
cmax_xaxis = cmaxbar + 3
for d in sdata[:barlines]:
block = '\u2585' if d[0] in highlights else '='
- dstr += "%3s\u2502%s %d\n" % (d[0], block*int(scale*d[1]), d[1])
+ dstr += "%3s\u2502%s %d\n" % (d[0], block * int(scale * d[1]), d[1])
if barlines < len(sdata):
dstr += " \u256a\n"
elif (len(sdata) - axislines) < height:
# Add empty lines to y-axis
dstr += ' \u2502\n' * (height - len(sdata) - axislines)
- dstr += " \u251c" + '\u2500'*(cmax_xaxis) + '\u2524\n'
- dstr += " 0" + ' '*(cmax_xaxis - 1) + str(max_xaxis)
+ dstr += " \u251c" + '\u2500' * (cmax_xaxis) + '\u2524\n'
+ dstr += " 0" + ' ' * (cmax_xaxis - 1) + str(max_xaxis)
return dstr
diff --git a/setup.cfg b/setup.cfg
index f4b00fd..a98fb10 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,8 @@
[flake8]
exclude=.git,__pycache__,build
max-line-length=88
+ignore = B902, BLK100, CCR001, CNL100, D1, I201, Q000, W503
+
+[pycodestyle]
+count=1
+max-line-length = 88
From 58f4433cda669210db4e4e4d4c72689237f13c90 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sun, 29 Jan 2023 15:45:44 +0200
Subject: [PATCH 08/50] Add ModemManagerGLibNmeaSource, use it
---
satellite/application.py | 4 +-
satellite/mm_glib_source.py | 99 +++++++++++++++++++++++++++++++++++++
2 files changed, 101 insertions(+), 2 deletions(-)
create mode 100644 satellite/mm_glib_source.py
diff --git a/satellite/application.py b/satellite/application.py
index 908aadd..9c00da1 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -18,7 +18,7 @@ import satellite.nmea as nmea
import satellite.quectel as quectel
from satellite import __version__
-from .mm_pydbus_source import QuectelNmeaSource
+from .mm_glib_source import ModemManagerGLibNmeaSource
from .nmeasource import (
GnssShareNmeaSource,
ModemError,
@@ -242,7 +242,7 @@ class SatelliteApp(Gtk.Application):
def init_quectel_source(self):
try:
- self.source = QuectelNmeaSource(
+ self.source = ModemManagerGLibNmeaSource(
self.location_update_cb,
refresh_rate=self.refresh_rate,
# save_filename=unique_filename(self.gpx_save_dir + '/nmeas',
diff --git a/satellite/mm_glib_source.py b/satellite/mm_glib_source.py
new file mode 100644
index 0000000..3468ffe
--- /dev/null
+++ b/satellite/mm_glib_source.py
@@ -0,0 +1,99 @@
+# Copyright 2023 Teemu Ikonen
+# SPDX-License-Identifier: GPL-3.0-only
+
+import gi
+gi.require_version('ModemManager', '1.0')
+from gi.repository import Gio, ModemManager # noqa: E402
+
+from satellite.nmeasource import ( # noqa: E402
+ ModemError,
+ ModemLockedError,
+ ModemNoNMEAError,
+ NmeaSource,
+ NmeaSourceNotFoundError,
+)
+
+
+class ModemManagerGLibNmeaSource(NmeaSource):
+
+ def __init__(self, update_callback, **kwargs):
+ super().__init__(update_callback, **kwargs)
+ self.bus = None
+ self.manager = None
+ self.modem = None
+ self.mlocation = None
+ self.old_refresh_rate = None
+ self.old_sources_enabled = None
+ self.old_signals_location = None
+ self.location_updated = None
+
+ def initialize(self):
+ self.bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
+ self.manager = ModemManager.Manager.new_sync(
+ self.bus, Gio.DBusObjectManagerClientFlags.DO_NOT_AUTO_START, None)
+ if self.manager.get_name_owner() is None:
+ raise NmeaSourceNotFoundError("ModemManager is not running")
+ objs = self.manager.get_objects()
+ if objs:
+ self.modem = objs[0].get_modem()
+ self.mlocation = objs[0].get_modem_location()
+ else:
+ raise NmeaSourceNotFoundError("No Modems Found")
+ self.manufacturer = self.modem.get_manufacturer()
+ self.model = self.modem.get_model()
+ self.revision = self.modem.get_revision()
+
+ try:
+ state = self.modem.get_state()
+ if int(state) > 0:
+ if self.old_refresh_rate is None:
+ self.old_refresh_rate = self.mlocation.props.gps_refresh_rate
+ if self.old_sources_enabled is None:
+ self.old_sources_enabled = self.mlocation.props.enabled
+ if self.old_signals_location is None:
+ self.old_signals_location = self.mlocation.props.signals_location
+ caps = self.mlocation.get_capabilities()
+ if not caps & ModemManager.ModemLocationSource.GPS_NMEA:
+ raise NmeaSourceNotFoundError(
+ "Modem does not support NMEA")
+ self.mlocation.setup_sync(
+ (ModemManager.ModemLocationSource.GPS_NMEA
+ | ModemManager.ModemLocationSource.AGPS_MSB), True, None)
+ else:
+ raise ModemError("Modem state is: %d" % state)
+ except AttributeError as e:
+ if state == ModemManager.ModemState.LOCKED:
+ raise ModemLockedError from e
+ else:
+ raise e
+
+ self.mlocation.set_gps_refresh_rate_sync(self.refresh_rate, None)
+ self.mlocation.connect('notify::location', self.update_callback)
+
+ self.initialized = True
+
+ def _really_get(self):
+ if not self.initialized:
+ self.initialize()
+ try:
+ loc = self.mlocation.get_signaled_gps_nmea()
+ except Exception as e:
+ self.initialized = False
+ raise e
+
+ retval = loc.get_traces()
+ if retval is None:
+ self.initialized = False
+ raise ModemNoNMEAError
+ return '\r\n'.join(retval)
+
+ def close(self):
+ if self.mlocation is None:
+ return
+ self.mlocation.disconnect_by_func(self.update_callback)
+ if self.old_sources_enabled is not None:
+ self.mlocation.setup_sync(
+ ModemManager.ModemLocationSource(self.old_sources_enabled),
+ self.old_signals_location, None)
+ if self.old_refresh_rate is not None:
+ self.mlocation.set_gps_refresh_rate_sync(self.old_refresh_rate, None)
From 7115b1697c9962e04a23c8dd450747209189b19d Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sun, 29 Jan 2023 16:41:52 +0200
Subject: [PATCH 09/50] mm_glib_source: Support quirks, add QuectelTalker quirk
---
satellite/mm_glib_source.py | 44 ++++++++++++++++++++++++++++++++-----
1 file changed, 38 insertions(+), 6 deletions(-)
diff --git a/satellite/mm_glib_source.py b/satellite/mm_glib_source.py
index 3468ffe..419474b 100644
--- a/satellite/mm_glib_source.py
+++ b/satellite/mm_glib_source.py
@@ -1,9 +1,10 @@
# Copyright 2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
+import re
+
import gi
-gi.require_version('ModemManager', '1.0')
-from gi.repository import Gio, ModemManager # noqa: E402
+from pynmea2.nmea import NMEASentence
from satellite.nmeasource import ( # noqa: E402
ModemError,
@@ -13,10 +14,13 @@ from satellite.nmeasource import ( # noqa: E402
NmeaSourceNotFoundError,
)
+gi.require_version('ModemManager', '1.0')
+from gi.repository import Gio, ModemManager # noqa: E402, I100
+
class ModemManagerGLibNmeaSource(NmeaSource):
- def __init__(self, update_callback, **kwargs):
+ def __init__(self, update_callback, quirks=[], **kwargs):
super().__init__(update_callback, **kwargs)
self.bus = None
self.manager = None
@@ -26,6 +30,7 @@ class ModemManagerGLibNmeaSource(NmeaSource):
self.old_sources_enabled = None
self.old_signals_location = None
self.location_updated = None
+ self.quirks = quirks
def initialize(self):
self.bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
@@ -81,11 +86,15 @@ class ModemManagerGLibNmeaSource(NmeaSource):
self.initialized = False
raise e
- retval = loc.get_traces()
- if retval is None:
+ nmeas = loc.get_traces()
+ if nmeas is None:
self.initialized = False
raise ModemNoNMEAError
- return '\r\n'.join(retval)
+
+ if 'QuectelTalker' in self.quirks:
+ nmeas = self.quectel_talker_quirk(nmeas)
+
+ return '\r\n'.join(nmeas)
def close(self):
if self.mlocation is None:
@@ -97,3 +106,26 @@ class ModemManagerGLibNmeaSource(NmeaSource):
self.old_signals_location, None)
if self.old_refresh_rate is not None:
self.mlocation.set_gps_refresh_rate_sync(self.old_refresh_rate, None)
+
+ def quectel_talker_quirk(self, nmeas):
+ pq_re = re.compile(r"""
+ ^\s*\$?
+ (?PPQ)
+ (?P\w{3})
+ (?P[^*]*)
+ (?:[*](?P[A-F0-9]{2}))$""", re.VERBOSE)
+ out = []
+ for nmea in (n for n in nmeas if n):
+ mo = pq_re.match(nmea)
+ if mo:
+ # The last extra data field is Signal ID, these are
+ # 1 = GPS, 2 = Glonass, 3 = Galileo, 4 = BeiDou, 5 = QZSS
+ # Determine talker from Signal ID
+ talker = 'QZ' if mo.group('data').endswith('5') else 'BD'
+ # Fake talker and checksum
+ fake = talker + "".join(mo.group(2, 3))
+ out.append('$' + fake + "*%02X" % NMEASentence.checksum(fake))
+ else:
+ out.append(nmea)
+
+ return out
From 17baef902d4dc4cfefb9377326f21c905b03c8d4 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sun, 29 Jan 2023 16:43:10 +0200
Subject: [PATCH 10/50] Refactor '--source' CLI arg handling, add 'mm' source
Use QuectelTalker quirk in 'quectel' source, add a plain ModemManager
source 'mm' without quirks.
Fix '--source' arg help string formatting.
---
satellite/application.py | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/satellite/application.py b/satellite/application.py
index 9c00da1..6ec9d21 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -47,7 +47,8 @@ class SatelliteApp(Gtk.Application):
Handy.init()
desc = "Displays navigation satellite data and saves GPX tracks"
- parser = argparse.ArgumentParser(description=desc)
+ parser = argparse.ArgumentParser(
+ description=desc, formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument(
'-c', '--console-output', dest='console_output',
action='store_true', default=False,
@@ -55,9 +56,10 @@ class SatelliteApp(Gtk.Application):
parser.add_argument(
'-s', '--source', dest='source',
default='quectel',
- help="Select NMEA source. Options are "
- "\'quectel\' (default) for Quectel Modems or "
- "\'gnss-share\' when using gnss-share")
+ help="Select NMEA source. Options are:\n"
+ "'quectel' (default) ModemManager with Quectel quirks\n"
+ "'mm' ModemManager without quirks\n"
+ "'gnss-share' when using gnss-share\n")
self.args = parser.parse_args()
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT,
@@ -186,7 +188,9 @@ class SatelliteApp(Gtk.Application):
source_init = False
if self.args.source == 'quectel':
- source_init = self.init_quectel_source()
+ source_init = self.init_mm_source(quirks=['QuectelTalker'])
+ elif self.args.source == 'mm':
+ source_init = self.init_mm_source()
elif self.args.source == 'gnss-share':
source_init = self.init_gnss_share_source()
@@ -240,11 +244,12 @@ class SatelliteApp(Gtk.Application):
return True
- def init_quectel_source(self):
+ def init_mm_source(self, quirks=[]):
try:
self.source = ModemManagerGLibNmeaSource(
self.location_update_cb,
refresh_rate=self.refresh_rate,
+ quirks=quirks,
# save_filename=unique_filename(self.gpx_save_dir + '/nmeas',
# '.txt')
)
From 0b2cc896357f4402eed26e41f7f73473ae7508c9 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sun, 29 Jan 2023 16:48:33 +0200
Subject: [PATCH 11/50] Remove mm_pydbus_source.py
(ModemManagerPyDBusNmeaSource)
---
satellite/mm_pydbus_source.py | 129 ----------------------------------
1 file changed, 129 deletions(-)
delete mode 100644 satellite/mm_pydbus_source.py
diff --git a/satellite/mm_pydbus_source.py b/satellite/mm_pydbus_source.py
deleted file mode 100644
index a946a92..0000000
--- a/satellite/mm_pydbus_source.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# Copyright 2021-2023 Teemu Ikonen
-# SPDX-License-Identifier: GPL-3.0-only
-
-import re
-
-from pydbus import SystemBus
-from pynmea2.nmea import NMEASentence
-
-import satellite.modem_manager_defs as mm
-from satellite.nmeasource import (
- ModemError,
- ModemLockedError,
- ModemNoNMEAError,
- NmeaSource,
- NmeaSourceNotFoundError,
-)
-
-
-class ModemManagerPyDBusNmeaSource(NmeaSource):
-
- def __init__(self, update_callback, **kwargs):
- super().__init__(update_callback, **kwargs)
- self.bus = SystemBus()
- self.manager = self.bus.get('.ModemManager1')
- self.modem = None
- self.old_refresh_rate = None
- self.old_sources_enabled = None
- self.old_signals = None
- self.location_updated = None
-
- def initialize(self):
- objs = self.manager.GetManagedObjects()
- mkeys = list(objs.keys())
- if mkeys:
- mstr = mkeys[0]
- else:
- raise NmeaSourceNotFoundError("No Modems Found")
- info = objs[mstr]['org.freedesktop.ModemManager1.Modem']
- self.manufacturer = info.get('Manufacturer')
- self.model = info.get('Model')
- self.revision = info.get('Revision')
- self.modem = self.bus.get('.ModemManager1', mstr)
-
- try:
- if self.modem.State > 0:
- if self.old_refresh_rate is None:
- self.old_refresh_rate = self.modem.GpsRefreshRate
- if self.old_sources_enabled is None:
- self.old_sources_enabled = self.modem.Enabled
- if self.old_signals is None:
- self.old_signals = self.modem.SignalsLocation
- cap = self.modem.Capabilities
- if (cap & mm.MM_MODEM_LOCATION_SOURCE_GPS_NMEA) == 0:
- raise NmeaSourceNotFoundError(
- "Modem does not support NMEA")
- self.modem.Setup(
- (mm.MM_MODEM_LOCATION_SOURCE_GPS_NMEA
- | (cap & mm.MM_MODEM_LOCATION_SOURCE_AGPS_MSB)),
- True)
- else:
- raise ModemError("Modem state is: %d" % self.modem.State)
- except AttributeError as e:
- if self.modem.State == mm.MM_MODEM_STATE_LOCKED:
- raise ModemLockedError from e
- else:
- raise ModemError from e
- except Exception as e:
- raise e
-
- self.modem.SetGpsRefreshRate(self.refresh_rate)
- self.location_updated = self.bus.subscribe(
- sender='org.freedesktop.ModemManager1',
- iface='org.freedesktop.DBus.Properties',
- signal='PropertiesChanged',
- arg0='org.freedesktop.ModemManager1.Modem.Location',
- signal_fired=self.update_callback)
- self.initialized = True
-
- def _really_get(self):
- if not self.initialized:
- self.initialize()
- try:
- loc = self.modem.GetLocation()
- except Exception as e:
- self.initialized = False
- raise e
-
- retval = loc.get(mm.MM_MODEM_LOCATION_SOURCE_GPS_NMEA)
- if retval is None:
- self.initialized = False
- raise ModemNoNMEAError
- return retval
-
- def close(self):
- if self.location_updated is not None:
- self.location_updated.disconnect()
- if self.old_sources_enabled is not None:
- self.modem.Setup(self.old_sources_enabled, self.old_signals)
- if self.old_refresh_rate is not None:
- self.modem.SetGpsRefreshRate(self.old_refresh_rate)
-
-
-class QuectelNmeaSource(ModemManagerPyDBusNmeaSource):
-
- def _really_get(self):
- return self.fix_talker(super()._really_get())
-
- def fix_talker(self, nmeas):
- pq_re = re.compile(r"""
- ^\s*\$?
- (?PPQ)
- (?P\w{3})
- (?P[^*]*)
- (?:[*](?P[A-F0-9]{2}))$""", re.VERBOSE)
- out = []
- for nmea in (n for n in nmeas.split('\r\n') if n):
- mo = pq_re.match(nmea)
- if mo:
- # The last extra data field is Signal ID, these are
- # 1 = GPS, 2 = Glonass, 3 = Galileo, 4 = BeiDou, 5 = QZSS
- # Determine talker from Signal ID
- talker = 'QZ' if mo.group('data').endswith('5') else 'BD'
- # Fake talker and checksum
- fake = talker + "".join(mo.group(2, 3))
- out.append('$' + fake + "*%02X" % NMEASentence.checksum(fake))
- else:
- out.append(nmea)
-
- return "\r\n".join(out)
From 7206198321d175a7707d8090fe76e459c19b3044 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ferenc=20G=C3=A9czi?=
Date: Wed, 22 Mar 2023 00:00:00 +0000
Subject: [PATCH 12/50] Update to Gnome runtime 44
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Ferenc Géczi
---
flatpak/page.codeberg.tpikonen.satellite.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flatpak/page.codeberg.tpikonen.satellite.json b/flatpak/page.codeberg.tpikonen.satellite.json
index 9709a60..00fae45 100644
--- a/flatpak/page.codeberg.tpikonen.satellite.json
+++ b/flatpak/page.codeberg.tpikonen.satellite.json
@@ -1,7 +1,7 @@
{
"app-id": "page.codeberg.tpikonen.satellite",
"runtime": "org.gnome.Platform",
- "runtime-version": "43",
+ "runtime-version": "44",
"sdk": "org.gnome.Sdk",
"command": "satellite",
"rename-desktop-file": "satellite.desktop",
From 9de70b54469b95aa173e92aee029ec39f51adba0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ferenc=20G=C3=A9czi?=
Date: Wed, 22 Mar 2023 00:00:00 +0000
Subject: [PATCH 13/50] Add ModemManager to flatpak as module
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Ferenc Géczi
---
flatpak/page.codeberg.tpikonen.satellite.json | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/flatpak/page.codeberg.tpikonen.satellite.json b/flatpak/page.codeberg.tpikonen.satellite.json
index 00fae45..da906ec 100644
--- a/flatpak/page.codeberg.tpikonen.satellite.json
+++ b/flatpak/page.codeberg.tpikonen.satellite.json
@@ -18,6 +18,27 @@
],
"modules": [
"python3-requirements.json",
+ {
+ "name": "ModemManager",
+ "config-opts": [
+ "--without-udev",
+ "--with-udev-base-dir=/app/lib/udev",
+ "--with-systemdsystemunitdir=/app/lib/systemd/system",
+ "--without-examples",
+ "--without-tests",
+ "--without-mbim",
+ "--without-qmi",
+ "--without-qrtr",
+ "--without-man"
+ ],
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git",
+ "tag": "1.20.6"
+ }
+ ]
+ },
{
"name": "satellite",
"sources": [
From 7fd0d42f044e7cafa44dcecdd5c48ade77010354 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 1 Mar 2023 11:40:19 +0200
Subject: [PATCH 14/50] Add .editorconfig file
---
.editorconfig | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 .editorconfig
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..0f1deb2
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,26 @@
+# EditorConfig is awesome: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+charset = utf-8
+
+# 4 space indentation
+[*.{py,java,r,R}]
+indent_style = space
+indent_size = 4
+
+# 2 space indentation
+[*.{js,json,y{a,}ml,html,cwl}]
+indent_style = space
+indent_size = 2
+
+[*.{md,Rmd,rst}]
+trim_trailing_whitespace = false
+indent_style = space
+indent_size = 2
From 8c0f1587f46ed2f63c50eb3cd6f504e29501ba8d Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Thu, 16 Mar 2023 18:34:50 +0200
Subject: [PATCH 15/50] Remove modem_manager_defs.py
---
satellite/modem_manager_defs.py | 31 -------------------------------
1 file changed, 31 deletions(-)
delete mode 100644 satellite/modem_manager_defs.py
diff --git a/satellite/modem_manager_defs.py b/satellite/modem_manager_defs.py
deleted file mode 100644
index 6500509..0000000
--- a/satellite/modem_manager_defs.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2021-2022 Teemu Ikonen
-# SPDX-License-Identifier: GPL-3.0-only
-
-# flake8: noqa
-
-# See /usr/include/ModemManager/ModemManager-enums.h in modemmanager-dev
-MM_MODEM_LOCATION_SOURCE_NONE = 0
-MM_MODEM_LOCATION_SOURCE_3GPP_LAC_CI = 1 << 0
-MM_MODEM_LOCATION_SOURCE_GPS_RAW = 1 << 1
-MM_MODEM_LOCATION_SOURCE_GPS_NMEA = 1 << 2
-MM_MODEM_LOCATION_SOURCE_CDMA_BS = 1 << 3
-MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED = 1 << 4
-MM_MODEM_LOCATION_SOURCE_AGPS_MSA = 1 << 5
-MM_MODEM_LOCATION_SOURCE_AGPS_MSB = 1 << 6
-
-MM_MODEM_LOCATION_ASSISTANCE_DATA_TYPE_NONE = 0
-MM_MODEM_LOCATION_ASSISTANCE_DATA_TYPE_XTRA = 1 << 0
-
-MM_MODEM_STATE_FAILED = -1
-MM_MODEM_STATE_UNKNOWN = 0
-MM_MODEM_STATE_INITIALIZING = 1
-MM_MODEM_STATE_LOCKED = 2
-MM_MODEM_STATE_DISABLED = 3
-MM_MODEM_STATE_DISABLING = 4
-MM_MODEM_STATE_ENABLING = 5
-MM_MODEM_STATE_ENABLED = 6
-MM_MODEM_STATE_SEARCHING = 7
-MM_MODEM_STATE_REGISTERED = 8
-MM_MODEM_STATE_DISCONNECTING = 9
-MM_MODEM_STATE_CONNECTING = 10
-MM_MODEM_STATE_CONNECTED = 11
From 2bb1b7099420ae11b62707c08f5ef56ce76a3063 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Thu, 16 Mar 2023 18:45:27 +0200
Subject: [PATCH 16/50] mm_glib_source: Disconnect update cb in initialization
---
satellite/mm_glib_source.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/satellite/mm_glib_source.py b/satellite/mm_glib_source.py
index 419474b..f5c7db5 100644
--- a/satellite/mm_glib_source.py
+++ b/satellite/mm_glib_source.py
@@ -33,6 +33,9 @@ class ModemManagerGLibNmeaSource(NmeaSource):
self.quirks = quirks
def initialize(self):
+ # If reinitializing, disconnect old update cb
+ if self.mlocation is not None:
+ self.mlocation.disconnect_by_func(self.update_callback)
self.bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
self.manager = ModemManager.Manager.new_sync(
self.bus, Gio.DBusObjectManagerClientFlags.DO_NOT_AUTO_START, None)
From a4a599a6c513b5dc17198141a71355d66e3f6888 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Thu, 16 Mar 2023 18:46:21 +0200
Subject: [PATCH 17/50] mm_glib_source: Enable AGPS_MSB only if it's in modem
capabilities
---
satellite/mm_glib_source.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/satellite/mm_glib_source.py b/satellite/mm_glib_source.py
index f5c7db5..bcdad97 100644
--- a/satellite/mm_glib_source.py
+++ b/satellite/mm_glib_source.py
@@ -64,9 +64,10 @@ class ModemManagerGLibNmeaSource(NmeaSource):
if not caps & ModemManager.ModemLocationSource.GPS_NMEA:
raise NmeaSourceNotFoundError(
"Modem does not support NMEA")
- self.mlocation.setup_sync(
- (ModemManager.ModemLocationSource.GPS_NMEA
- | ModemManager.ModemLocationSource.AGPS_MSB), True, None)
+ enable = ModemManager.ModemLocationSource.GPS_NMEA
+ if caps & ModemManager.ModemLocationSource.AGPS_MSB:
+ enable |= ModemManager.ModemLocationSource.AGPS_MSB
+ self.mlocation.setup_sync(enable, True, None)
else:
raise ModemError("Modem state is: %d" % state)
except AttributeError as e:
From d6e4a71380f4d2f2686633ef02d430254ed5e6ae Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 17 Mar 2023 22:01:45 +0200
Subject: [PATCH 18/50] mm_glib_source: Ignore error in disconnect when closing
an uninitialized source
---
satellite/mm_glib_source.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/satellite/mm_glib_source.py b/satellite/mm_glib_source.py
index bcdad97..056c6bf 100644
--- a/satellite/mm_glib_source.py
+++ b/satellite/mm_glib_source.py
@@ -103,7 +103,10 @@ class ModemManagerGLibNmeaSource(NmeaSource):
def close(self):
if self.mlocation is None:
return
- self.mlocation.disconnect_by_func(self.update_callback)
+ try:
+ self.mlocation.disconnect_by_func(self.update_callback)
+ except TypeError:
+ pass # Ignore error when nothing is connected
if self.old_sources_enabled is not None:
self.mlocation.setup_sync(
ModemManager.ModemLocationSource(self.old_sources_enabled),
From e6205bd9e5cf438fb8d5e8d71b6217100bfa8681 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 17 Mar 2023 22:19:04 +0200
Subject: [PATCH 19/50] mm_glib_source: Ignore error when enabling AGPS MSB
AGPS enablement sometimes timeouts on Oneplus 6.
Also improve logging of NMEA initialization errors.
---
satellite/application.py | 2 +-
satellite/mm_glib_source.py | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/satellite/application.py b/satellite/application.py
index 6ec9d21..22f8776 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -261,8 +261,8 @@ class SatelliteApp(Gtk.Application):
dtext = "Please unlock the Modem"
else:
fatal = isinstance(e, gi.repository.GLib.GError)
- self.log_msg("Error initializing NMEA source")
etext = str(e)
+ self.log_msg(f"Error initializing NMEA source: {etext}")
dtext = etext if etext else (
"Could not find or initialize NMEA source")
dialog = Gtk.MessageDialog(
diff --git a/satellite/mm_glib_source.py b/satellite/mm_glib_source.py
index 056c6bf..6f23131 100644
--- a/satellite/mm_glib_source.py
+++ b/satellite/mm_glib_source.py
@@ -75,6 +75,10 @@ class ModemManagerGLibNmeaSource(NmeaSource):
raise ModemLockedError from e
else:
raise e
+ except gi.repository.GLib.GError as e:
+ # Ignore error on AGPS enablement by this hack
+ if 'agps-msb' not in str(e):
+ raise e
self.mlocation.set_gps_refresh_rate_sync(self.refresh_rate, None)
self.mlocation.connect('notify::location', self.update_callback)
From 4d73be8c73499a71fcb1ba287249c4e7b24e822a Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 22 Mar 2023 15:08:59 +0200
Subject: [PATCH 20/50] requirements.txt: Remove pydbus
---
requirements.txt | 1 -
1 file changed, 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index 643efb9..19855d4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,2 @@
gpxpy
pynmea2
-pydbus
From 83164bb80f86f7b4f40ba536f061be4ba9c3c800 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 22 Mar 2023 15:12:03 +0200
Subject: [PATCH 21/50] flatpak: Update python3-requirements
---
flatpak/python3-requirements.json | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/flatpak/python3-requirements.json b/flatpak/python3-requirements.json
index ad534ab..30f3cac 100644
--- a/flatpak/python3-requirements.json
+++ b/flatpak/python3-requirements.json
@@ -26,22 +26,8 @@
"sources": [
{
"type": "file",
- "url": "https://files.pythonhosted.org/packages/c9/13/6117f735c3e8083bfce0ccd31a1d561fc2adb0e0e2d1ab3ace12256a3513/pynmea2-1.18.0-py3-none-any.whl",
- "sha256": "098f9ffd89c4a6c5e137b8b59e5b38194888d4a557c50b003ebcf2c3c15ec22e"
- }
- ]
- },
- {
- "name": "python3-pydbus",
- "buildsystem": "simple",
- "build-commands": [
- "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"pydbus\" --no-build-isolation"
- ],
- "sources": [
- {
- "type": "file",
- "url": "https://files.pythonhosted.org/packages/92/56/27148014c2f85ce70332f18612f921f682395c7d4e91ec103783be4fce00/pydbus-0.6.0-py2.py3-none-any.whl",
- "sha256": "66b80106352a718d80d6c681dc2a82588048e30b75aab933e4020eb0660bf85e"
+ "url": "https://files.pythonhosted.org/packages/75/24/1f575eb17a8135e54b3c243ff87e2f4d6b2389942836021d0628ed837559/pynmea2-1.19.0-py3-none-any.whl",
+ "sha256": "5138558b4fb5daa587b2c17de99eb43df0297039de1c98010c996624abfb00eb"
}
]
}
From 51eb4bb71438f689fb9a048ac9c78ad05ee054b6 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 22 Mar 2023 15:58:33 +0200
Subject: [PATCH 22/50] flatpak: Use ModemManager release tarball
---
flatpak/page.codeberg.tpikonen.satellite.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/flatpak/page.codeberg.tpikonen.satellite.json b/flatpak/page.codeberg.tpikonen.satellite.json
index da906ec..9b765e9 100644
--- a/flatpak/page.codeberg.tpikonen.satellite.json
+++ b/flatpak/page.codeberg.tpikonen.satellite.json
@@ -33,9 +33,9 @@
],
"sources": [
{
- "type": "git",
- "url": "https://gitlab.freedesktop.org/mobile-broadband/ModemManager.git",
- "tag": "1.20.6"
+ "type": "archive",
+ "url": "https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/archive/1.20.6/ModemManager-1.20.6.tar.gz",
+ "sha256": "d3e8112810e48ba32e80757fced218cf65b135b5a2987dad6b431d8cfbba765f"
}
]
},
From fbfd588f78147e971b72af74b3aee70d4609a070 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 22 Mar 2023 16:31:09 +0200
Subject: [PATCH 23/50] appdata: Improve description
---
data/appdata.xml | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/data/appdata.xml b/data/appdata.xml
index 13bb5b2..82e31bc 100644
--- a/data/appdata.xml
+++ b/data/appdata.xml
@@ -9,10 +9,11 @@
Check your GPS reception and save your tracks
Satellite displays global navigation satellite system (GNSS: that's GPS,
- Galileo, Glonass etc.) data obtained from the ModemManager API. You can use
- it to check the navigation satellite signal strength in your location and
- see your speed, coordinates and other parameters once a fix is obtained.
- It can also save GPX-tracks of your travels.
+ Galileo, Glonass etc.) data obtained from an NMEA source in your device.
+ Currently the ModemManager and gnss-share APIs are supported. You can use
+ it to check the navigation satellite signal strength and see your speed,
+ coordinates and other parameters once a fix is obtained. It can also save
+ GPX-tracks of your travels.
page.codeberg.tpikonen.satellite.desktop
https://codeberg.org/tpikonen/satellite
From 782499e27bbe489a1fdaf8730cae44e2b30d9226 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 22 Mar 2023 17:41:25 +0200
Subject: [PATCH 24/50] nmea: Get system time as non-naive datetime object
---
satellite/nmea.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/satellite/nmea.py b/satellite/nmea.py
index 9d13847..6b2f001 100644
--- a/satellite/nmea.py
+++ b/satellite/nmea.py
@@ -249,7 +249,7 @@ def parse(nmeas, always_add_prefix=False):
}
out.update({k: msg_get(msgs, k) for k in getters.keys()})
- datenow = datetime.datetime.utcnow()
+ datenow = datetime.datetime.now(datetime.timezone.utc)
fixtime = out.get('fixtime')
fixdate = out.get('date')
if fixdate is None and fixtime is not None:
From c3115dd751b041b097c868ce2f530c609e459d74 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 22 Mar 2023 20:25:58 +0200
Subject: [PATCH 25/50] Output 'n/a' for missing mode_indicator
---
satellite/application.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/satellite/application.py b/satellite/application.py
index 22f8776..ec4e996 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -420,7 +420,8 @@ class SatelliteApp(Gtk.Application):
# Mapping: Data key, description, converter func
order = [
("mode", "Fix type", lambda x: mode2fix.get(x, "No Fix")),
- ("mode_indicator", "Modes (GP,GL,GA)", lambda x: str(x)),
+ ("mode_indicator", "Modes (GP,GL,GA)",
+ lambda x: str(x) if x is not None else "n/a"),
("actives", "Active / in use sats", get_actives),
("visibles", "Receiving sats", lambda x: str(len(
[r for r in x if r['snr'] > 0.0]))),
From 89f6ac85db92a57f2787c93f92e1fb57b28aa762 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 22 Mar 2023 20:27:06 +0200
Subject: [PATCH 26/50] nmea: Move GGA timestamp from 'fixtime' to 'time'
---
satellite/nmea.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/satellite/nmea.py b/satellite/nmea.py
index 6b2f001..9be0736 100644
--- a/satellite/nmea.py
+++ b/satellite/nmea.py
@@ -101,10 +101,10 @@ getters = {
},
"fixtime": {
'RMC': get_time,
- 'GGA': get_time,
},
"time": { # Reported also when no fix
'GNS': get_time,
+ 'GGA': get_time,
},
"date": {
'RMC': get_date,
From 88e53d34bba358e0c03f7a97ff4054c364406069 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 22 Mar 2023 20:28:00 +0200
Subject: [PATCH 27/50] nmea: Parse 'num_sats' also from GGA sentences
---
satellite/nmea.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/satellite/nmea.py b/satellite/nmea.py
index 9be0736..2843a7c 100644
--- a/satellite/nmea.py
+++ b/satellite/nmea.py
@@ -132,6 +132,7 @@ getters = {
},
"num_sats": {
'GNS': iget('num_sats', default=0),
+ 'GGA': iget('num_sats', default=0),
},
"pdop": {
'GSA': fget('pdop'),
From f77ce58ee878b319392bcd72c927185ad016308d Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 22 Mar 2023 16:32:34 +0200
Subject: [PATCH 28/50] Release 0.4.0
---
data/appdata.xml | 10 ++++++++++
satellite/__init__.py | 2 +-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/data/appdata.xml b/data/appdata.xml
index 82e31bc..5d83cd0 100644
--- a/data/appdata.xml
+++ b/data/appdata.xml
@@ -49,6 +49,16 @@
+
+
+ The managerial release
+
+ - Use mm-glib to talk to ModemManager, remove pydbus
+ - Support 'quirks' in the ModemManager source, e.g. Quectel talker fixes
+ - Various reliability fixes
+
+
+
The quickfix release
diff --git a/satellite/__init__.py b/satellite/__init__.py
index efd3dc7..24cfe9a 100644
--- a/satellite/__init__.py
+++ b/satellite/__init__.py
@@ -1,4 +1,4 @@
# Copyright 2021-2022 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
-__version__ = "0.3.1"
+__version__ = "0.4.0"
From 98da3e4ffac2fd7f86bbdd31011929313c682541 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Thu, 23 Mar 2023 13:53:08 +0200
Subject: [PATCH 29/50] mm_glib_source: Handle None from
get_signaled_gps_nmea()
---
satellite/mm_glib_source.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/satellite/mm_glib_source.py b/satellite/mm_glib_source.py
index 6f23131..ba51a4c 100644
--- a/satellite/mm_glib_source.py
+++ b/satellite/mm_glib_source.py
@@ -94,6 +94,9 @@ class ModemManagerGLibNmeaSource(NmeaSource):
self.initialized = False
raise e
+ if loc is None:
+ raise ModemNoNMEAError
+
nmeas = loc.get_traces()
if nmeas is None:
self.initialized = False
From 6d1a10f96a077e88a0afed8dae642d32817c811e Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 19 Apr 2023 14:22:12 +0300
Subject: [PATCH 30/50] nmea: Create a non-naive fix datetime
---
satellite/nmea.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/satellite/nmea.py b/satellite/nmea.py
index 2843a7c..5201149 100644
--- a/satellite/nmea.py
+++ b/satellite/nmea.py
@@ -256,7 +256,7 @@ def parse(nmeas, always_add_prefix=False):
if fixdate is None and fixtime is not None:
# We have a fix but no RMC sentence
fixdate = datenow.date()
- fixdt = (datetime.datetime.combine(fixdate, fixtime)
+ fixdt = (datetime.datetime.combine(fixdate, fixtime, datetime.timezone.utc)
if (fixtime and fixdate) else None)
out["datetime"] = fixdt
out["systime"] = datenow
From aec07d5fd4573e91b53fe45a780fbc76931904fd Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Wed, 19 Apr 2023 14:22:35 +0300
Subject: [PATCH 31/50] setup.py: set Development Status to Beta
---
setup.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index 1861be4..2f90ed5 100644
--- a/setup.py
+++ b/setup.py
@@ -29,7 +29,7 @@ setuptools.setup(
"Bug Tracker": "https://codeberg.org/tpikonen/satellite/issues",
},
classifiers=[
- "Development Status :: 3 - Alpha",
+ "Development Status :: 4 - Beta",
"Environment :: X11 Applications :: GTK",
"Intended Audience :: End Users/Desktop",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
From 38bc1f7eb539a440d9256c684ecf02e9b86c7d76 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 5 May 2023 11:50:32 +0300
Subject: [PATCH 32/50] flatpak: Add filesystem read permission to
/run/gnss-share.sock
---
flatpak/page.codeberg.tpikonen.satellite.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/flatpak/page.codeberg.tpikonen.satellite.json b/flatpak/page.codeberg.tpikonen.satellite.json
index 9b765e9..dfb0d11 100644
--- a/flatpak/page.codeberg.tpikonen.satellite.json
+++ b/flatpak/page.codeberg.tpikonen.satellite.json
@@ -12,7 +12,8 @@
"--device=dri",
"--talk-name=org.gtk.vfs.*",
"--system-talk-name=org.freedesktop.ModemManager1.*",
- "--filesystem=xdg-documents/satellite-tracks:create"
+ "--filesystem=xdg-documents/satellite-tracks:create",
+ "--filesystem=/run/gnss-share.sock:ro"
],
"cleanup": [
],
From 0af37d1dc39fd50cec978faa40c146e3e35bd994 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 5 May 2023 12:22:12 +0300
Subject: [PATCH 33/50] flatpak: Convert build manifest to YAML
---
README.md | 2 +-
flatpak/page.codeberg.tpikonen.satellite.json | 61 -------------------
flatpak/page.codeberg.tpikonen.satellite.yaml | 42 +++++++++++++
3 files changed, 43 insertions(+), 62 deletions(-)
delete mode 100644 flatpak/page.codeberg.tpikonen.satellite.json
create mode 100644 flatpak/page.codeberg.tpikonen.satellite.yaml
diff --git a/README.md b/README.md
index 619eb04..60e529f 100644
--- a/README.md
+++ b/README.md
@@ -55,7 +55,7 @@ This creates an executable Python script in `$HOME/.local/bin/satellite`.
Run
- flatpak-builder --install --user build-dir flatpak/page.codeberg.tpikonen.satellite.json
+ flatpak-builder --install --user build-dir flatpak/page.codeberg.tpikonen.satellite.yaml
in the source tree root to install a local build to the user flatpak repo.
diff --git a/flatpak/page.codeberg.tpikonen.satellite.json b/flatpak/page.codeberg.tpikonen.satellite.json
deleted file mode 100644
index dfb0d11..0000000
--- a/flatpak/page.codeberg.tpikonen.satellite.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
- "app-id": "page.codeberg.tpikonen.satellite",
- "runtime": "org.gnome.Platform",
- "runtime-version": "44",
- "sdk": "org.gnome.Sdk",
- "command": "satellite",
- "rename-desktop-file": "satellite.desktop",
- "finish-args": [
- "--socket=fallback-x11",
- "--socket=wayland",
- "--share=ipc",
- "--device=dri",
- "--talk-name=org.gtk.vfs.*",
- "--system-talk-name=org.freedesktop.ModemManager1.*",
- "--filesystem=xdg-documents/satellite-tracks:create",
- "--filesystem=/run/gnss-share.sock:ro"
- ],
- "cleanup": [
- ],
- "modules": [
- "python3-requirements.json",
- {
- "name": "ModemManager",
- "config-opts": [
- "--without-udev",
- "--with-udev-base-dir=/app/lib/udev",
- "--with-systemdsystemunitdir=/app/lib/systemd/system",
- "--without-examples",
- "--without-tests",
- "--without-mbim",
- "--without-qmi",
- "--without-qrtr",
- "--without-man"
- ],
- "sources": [
- {
- "type": "archive",
- "url": "https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/archive/1.20.6/ModemManager-1.20.6.tar.gz",
- "sha256": "d3e8112810e48ba32e80757fced218cf65b135b5a2987dad6b431d8cfbba765f"
- }
- ]
- },
- {
- "name": "satellite",
- "sources": [
- {
- "type": "git",
- "path": "../",
- "branch": "main"
- }
- ],
- "buildsystem": "simple",
- "build-commands": [
- "pip3 install --verbose --no-index --no-deps --no-build-isolation --prefix=${FLATPAK_DEST} ./"
- ],
- "post-install": [
- "install -Dm644 data/appdata.xml $FLATPAK_DEST/share/metainfo/$FLATPAK_ID.appdata.xml"
- ]
- }
- ]
-}
diff --git a/flatpak/page.codeberg.tpikonen.satellite.yaml b/flatpak/page.codeberg.tpikonen.satellite.yaml
new file mode 100644
index 0000000..6007aa5
--- /dev/null
+++ b/flatpak/page.codeberg.tpikonen.satellite.yaml
@@ -0,0 +1,42 @@
+app-id: page.codeberg.tpikonen.satellite
+runtime: org.gnome.Platform
+runtime-version: "44"
+sdk: org.gnome.Sdk
+command: satellite
+rename-desktop-file: satellite.desktop
+finish-args:
+ - --socket=fallback-x11
+ - --socket=wayland
+ - --share=ipc
+ - --device=dri
+ - --talk-name=org.gtk.vfs.*
+ - --system-talk-name=org.freedesktop.ModemManager1.*
+ - --filesystem=xdg-documents/satellite-tracks:create
+ - --filesystem=/run/gnss-share.sock:ro
+cleanup: []
+modules:
+ - python3-requirements.json
+ - name: ModemManager
+ config-opts:
+ - --without-udev
+ - --with-udev-base-dir=/app/lib/udev
+ - --with-systemdsystemunitdir=/app/lib/systemd/system
+ - --without-examples
+ - --without-tests
+ - --without-mbim
+ - --without-qmi
+ - --without-qrtr
+ - --without-man
+ sources:
+ - type: archive
+ url: https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/archive/1.20.6/ModemManager-1.20.6.tar.gz
+ sha256: d3e8112810e48ba32e80757fced218cf65b135b5a2987dad6b431d8cfbba765f
+ - name: satellite
+ sources:
+ - type: git
+ path: ../
+ branch: main
+ buildsystem: simple
+ build-commands:
+ - pip3 install --verbose --no-index --no-deps --no-build-isolation --prefix=${FLATPAK_DEST} ./
+ - install -Dm644 data/appdata.xml $FLATPAK_DEST/share/metainfo/$FLATPAK_ID.appdata.xml
From 0f49eb26702d4a9162f0b7f9c7031ffd717261b0 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sat, 13 May 2023 11:34:40 +0300
Subject: [PATCH 34/50] README.md: update
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 60e529f..4fa36f7 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
![Expanded satellite SNR view](https://github.com/flathub/page.codeberg.tpikonen.satellite/raw/master/screenshot-snr.png)
![Speedometer and track recording](https://github.com/flathub/page.codeberg.tpikonen.satellite/raw/master/screenshot-track.png)
-Satellite is an adaptive GTK / libhandy application which displays global navigation satellite system
+Satellite is an adaptive GTK3 / libhandy application which displays global navigation satellite system
(GNSS: GPS et al.) data obtained from [ModemManager](https://www.freedesktop.org/wiki/Software/ModemManager/)
or [gnss-share](https://gitlab.com/postmarketOS/gnss-share). It can also save your position to a GPX-file.
@@ -15,7 +15,7 @@ GPL-3.0
## Dependencies:
- python 3.6+, gi, Gtk, libhandy, pydbus, pynmea2, gpxpy
+ python 3.6+, gi, Gtk3, libhandy, libmm-glib, pynmea2, gpxpy
## Installing and running
@@ -45,9 +45,9 @@ Run the script `bin/satellite`.
Run
- pip3 install --user ./
+ pip install --user ./
-in the source tree root.
+in the source tree root (use `pipx` instead of `pip` if necessary).
This creates an executable Python script in `$HOME/.local/bin/satellite`.
From da78c02a68010f6ca44eb053bd2334e6be69865d Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sat, 13 May 2023 13:21:12 +0300
Subject: [PATCH 35/50] Add NMEA source autodetection
---
satellite/application.py | 77 ++++++++++++++++++++++++----------------
satellite/nmeasource.py | 6 ++--
2 files changed, 50 insertions(+), 33 deletions(-)
diff --git a/satellite/application.py b/satellite/application.py
index ec4e996..8289ed5 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -55,11 +55,13 @@ class SatelliteApp(Gtk.Application):
help='Output satellite data to console')
parser.add_argument(
'-s', '--source', dest='source',
- default='quectel',
+ choices=['auto', 'quectel', 'mm', 'gnss-share'],
+ default='auto',
help="Select NMEA source. Options are:\n"
- "'quectel' (default) ModemManager with Quectel quirks\n"
+ "'auto' (default) Automatic source detection\n"
+ "'quectel' ModemManager with Quectel quirks\n"
"'mm' ModemManager without quirks\n"
- "'gnss-share' when using gnss-share\n")
+ "'gnss-share' Read from gnss-share socket\n")
self.args = parser.parse_args()
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT,
@@ -173,7 +175,6 @@ class SatelliteApp(Gtk.Application):
self.datascroll.connect('edge-overshot', self.on_edge_overshot)
self.log_msg(f"{appname} version {__version__} started")
- self.log_msg(f'Trying to initialize source "{self.args.source}"')
# Initialize modem after GUI startup
GLib.timeout_add(1000, self.init_source, None)
@@ -187,21 +188,41 @@ class SatelliteApp(Gtk.Application):
def init_source(self, unused):
source_init = False
- if self.args.source == 'quectel':
- source_init = self.init_mm_source(quirks=['QuectelTalker'])
- elif self.args.source == 'mm':
- source_init = self.init_mm_source()
- elif self.args.source == 'gnss-share':
- source_init = self.init_gnss_share_source()
-
- if not source_init:
- self.log_msg('No NmeaSource initialized')
- return GLib.SOURCE_REMOVE
+ if self.args.source == 'auto':
+ self.log_msg("Detecting NMEA sources...")
+ if not source_init:
+ source_init = self.init_gnss_share_source(autodetect=True)
+ if not source_init:
+ source_init = self.init_mm_source(
+ quirks=['QuectelTalker'], autodetect=True)
+ if not source_init:
+ self.log_msg('NMEA source not found')
+ dialog = Gtk.MessageDialog(
+ parent=self.window, modal=True,
+ message_type=Gtk.MessageType.ERROR,
+ buttons=Gtk.ButtonsType.OK,
+ text="Could not find an NMEA source")
+ dialog.set_title("Error initializing NMEA source")
+ dialog.run()
+ dialog.destroy()
+ return GLib.SOURCE_REMOVE
+ else:
+ self.log_msg(f'NMEA source "{self.args.source}" selected')
+ if self.args.source == 'quectel':
+ source_init = self.init_mm_source(quirks=['QuectelTalker'])
+ elif self.args.source == 'mm':
+ source_init = self.init_mm_source()
+ elif self.args.source == 'gnss-share':
+ source_init = self.init_gnss_share_source()
+ if not source_init:
+ self.log_msg('Could not initialize NMEA source')
+ return GLib.SOURCE_REMOVE
self.log_msg(
f"Source is {self.source.manufacturer}, model {self.source.model}"
- + f", revision {self.source.revision}"
- if self.source.revision else "")
+ + (f", revision {self.source.revision}" if self.source.revision else "")
+ + (f" using {', '.join(self.source.quirks)} quirks"
+ if hasattr(self.source, "quirks") and self.source.quirks else ""))
if (self.source.model and self.source.model.startswith("QUECTEL")):
constellations = quectel.get_constellations(self.source)
@@ -222,14 +243,15 @@ class SatelliteApp(Gtk.Application):
return GLib.SOURCE_REMOVE
- def init_gnss_share_source(self):
+ def init_gnss_share_source(self, autodetect=False):
try:
self.source = GnssShareNmeaSource(self.location_update_cb)
self.source.initialize()
except Exception as e:
- fatal = False
+ if autodetect:
+ return False
self.log_msg(str(e))
- dtext = 'Can you access "/var/run/gnss-share.sock"?\n' + str(e)
+ dtext = str(e)
dialog = Gtk.MessageDialog(
parent=self.window, modal=True,
message_type=Gtk.MessageType.ERROR,
@@ -237,14 +259,12 @@ class SatelliteApp(Gtk.Application):
dialog.set_title("Error initializing NMEA source")
dialog.run()
dialog.destroy()
- if fatal:
- self.quit()
return False
return True
- def init_mm_source(self, quirks=[]):
+ def init_mm_source(self, quirks=[], autodetect=False):
try:
self.source = ModemManagerGLibNmeaSource(
self.location_update_cb,
@@ -255,27 +275,24 @@ class SatelliteApp(Gtk.Application):
)
self.source.initialize()
except Exception as e:
- fatal = False
+ if autodetect:
+ return False
if isinstance(e, ModemLockedError):
self.log_msg("Modem is locked")
dtext = "Please unlock the Modem"
else:
- fatal = isinstance(e, gi.repository.GLib.GError)
etext = str(e)
- self.log_msg(f"Error initializing NMEA source: {etext}")
+ self.log_msg(f"Error initializing ModemManager NMEA source: {etext}")
dtext = etext if etext else (
- "Could not find or initialize NMEA source")
+ "Could not initialize ModemManager NMEA source")
dialog = Gtk.MessageDialog(
parent=self.window, modal=True,
message_type=Gtk.MessageType.ERROR,
- buttons=Gtk.ButtonsType.CLOSE if fatal else Gtk.ButtonsType.OK,
+ buttons=Gtk.ButtonsType.OK,
text=dtext)
dialog.set_title("Error initializing NMEA source")
dialog.run()
dialog.destroy()
- if fatal:
- self.quit()
- return
return False
diff --git a/satellite/nmeasource.py b/satellite/nmeasource.py
index e685e76..130e1c7 100644
--- a/satellite/nmeasource.py
+++ b/satellite/nmeasource.py
@@ -71,9 +71,9 @@ class UnixSocketNmeaSource(NmeaSource):
self.update_callback()
def initialize(self):
- if self.socket_file_path is None or \
- not os.path.exists(self.socket_file_path):
- return
+ if (self.socket_file_path is None
+ or not os.path.exists(self.socket_file_path)):
+ raise FileNotFoundError(f"Could not open socket {self.socket_file_path}")
self.s = socket.socket(socket.AF_UNIX,
socket.SOCK_NONBLOCK | socket.SOCK_STREAM)
From a895bfc32ff9690ccda8b1d74ff103fcf2137866 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Thu, 25 May 2023 16:31:59 +0300
Subject: [PATCH 36/50] Also detect quirks when autodetecting source
---
satellite/application.py | 2 +-
satellite/mm_glib_source.py | 8 +++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/satellite/application.py b/satellite/application.py
index 8289ed5..bc06c63 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -194,7 +194,7 @@ class SatelliteApp(Gtk.Application):
source_init = self.init_gnss_share_source(autodetect=True)
if not source_init:
source_init = self.init_mm_source(
- quirks=['QuectelTalker'], autodetect=True)
+ quirks=['detect'], autodetect=True)
if not source_init:
self.log_msg('NMEA source not found')
dialog = Gtk.MessageDialog(
diff --git a/satellite/mm_glib_source.py b/satellite/mm_glib_source.py
index ba51a4c..f34914a 100644
--- a/satellite/mm_glib_source.py
+++ b/satellite/mm_glib_source.py
@@ -30,7 +30,7 @@ class ModemManagerGLibNmeaSource(NmeaSource):
self.old_sources_enabled = None
self.old_signals_location = None
self.location_updated = None
- self.quirks = quirks
+ self.quirks = set(quirks)
def initialize(self):
# If reinitializing, disconnect old update cb
@@ -51,6 +51,12 @@ class ModemManagerGLibNmeaSource(NmeaSource):
self.model = self.modem.get_model()
self.revision = self.modem.get_revision()
+ if 'detect' in self.quirks:
+ self.quirks.remove('detect')
+ if (self.model.startswith('QUECTEL')
+ and self.manufacturer == 'QUALCOMM INCORPORATED'):
+ self.quirks.add('QuectelTalker')
+
try:
state = self.modem.get_state()
if int(state) > 0:
From 69551fa7a5489d8fea57d3be8a4b674a7566bc8b Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Thu, 25 May 2023 17:21:29 +0300
Subject: [PATCH 37/50] mm_glib_source: Add a quirk to disable MSB in SDM845 /
OP6
---
satellite/mm_glib_source.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/satellite/mm_glib_source.py b/satellite/mm_glib_source.py
index f34914a..d2e4097 100644
--- a/satellite/mm_glib_source.py
+++ b/satellite/mm_glib_source.py
@@ -56,6 +56,12 @@ class ModemManagerGLibNmeaSource(NmeaSource):
if (self.model.startswith('QUECTEL')
and self.manufacturer == 'QUALCOMM INCORPORATED'):
self.quirks.add('QuectelTalker')
+ # Detect SDM845 GNSS unit and disable MSB assistance,
+ # which causes stalling at startup due to some bug somewhere
+ if (self.manufacturer == 'QUALCOMM INCORPORATED'
+ and self.model == '0'
+ and self.revision.find('SDM845') >= 0):
+ self.quirks.add('NoMSB')
try:
state = self.modem.get_state()
@@ -71,7 +77,8 @@ class ModemManagerGLibNmeaSource(NmeaSource):
raise NmeaSourceNotFoundError(
"Modem does not support NMEA")
enable = ModemManager.ModemLocationSource.GPS_NMEA
- if caps & ModemManager.ModemLocationSource.AGPS_MSB:
+ if (caps & ModemManager.ModemLocationSource.AGPS_MSB
+ and 'NoMSB' not in self.quirks):
enable |= ModemManager.ModemLocationSource.AGPS_MSB
self.mlocation.setup_sync(enable, True, None)
else:
From 84ea03f70439588387641fc770bd1e306f2bf1a3 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 26 May 2023 20:20:51 +0300
Subject: [PATCH 38/50] Release 0.4.1
---
data/appdata.xml | 9 +++++++++
satellite/__init__.py | 2 +-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/data/appdata.xml b/data/appdata.xml
index 5d83cd0..430ec35 100644
--- a/data/appdata.xml
+++ b/data/appdata.xml
@@ -49,6 +49,15 @@
+
+
+ The automatic release
+
+ - Autodetect sources and source quirks when --source option is not given
+ - Some small fixes to mm_glib_source, NMEA parsing, flatpak, etc.
+
+
+
The managerial release
diff --git a/satellite/__init__.py b/satellite/__init__.py
index 24cfe9a..7602d7c 100644
--- a/satellite/__init__.py
+++ b/satellite/__init__.py
@@ -1,4 +1,4 @@
# Copyright 2021-2022 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
-__version__ = "0.4.0"
+__version__ = "0.4.1"
From 8f863ae0425e228d8e66b3f578b423ea49210d9e Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 7 Jul 2023 15:43:29 +0300
Subject: [PATCH 39/50] Update copyright years
---
bin/satellite | 2 +-
data/appdata.xml | 2 +-
satellite/__init__.py | 2 +-
satellite/__main__.py | 2 +-
satellite/application.py | 4 ++--
satellite/nmea.py | 2 +-
satellite/nmeasource.py | 2 +-
satellite/quectel.py | 2 +-
satellite/util.py | 2 +-
satellite/widgets.py | 2 +-
10 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/bin/satellite b/bin/satellite
index 9c91f9b..6446213 100755
--- a/bin/satellite
+++ b/bin/satellite
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
-# Copyright 2021-2022 Teemu Ikonen
+# Copyright 2021-2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
import os
diff --git a/data/appdata.xml b/data/appdata.xml
index 430ec35..04614b6 100644
--- a/data/appdata.xml
+++ b/data/appdata.xml
@@ -1,5 +1,5 @@
-
+
page.codeberg.tpikonen.satellite
diff --git a/satellite/__init__.py b/satellite/__init__.py
index 7602d7c..2d554b9 100644
--- a/satellite/__init__.py
+++ b/satellite/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 Teemu Ikonen
+# Copyright 2021-2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
__version__ = "0.4.1"
diff --git a/satellite/__main__.py b/satellite/__main__.py
index b29c675..f956868 100644
--- a/satellite/__main__.py
+++ b/satellite/__main__.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 Teemu Ikonen
+# Copyright 2021-2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
import sys
diff --git a/satellite/application.py b/satellite/application.py
index bc06c63..f2eac92 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 Teemu Ikonen
+# Copyright 2021-2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
import argparse
@@ -323,7 +323,7 @@ class SatelliteApp(Gtk.Application):
version=__version__,
comments="A program for showing navigation satellite data",
license_type=Gtk.License.GPL_3_0_ONLY,
- copyright="Copyright 2021-2022 Teemu Ikonen",
+ copyright="Copyright 2021-2023 Teemu Ikonen",
)
adlg.present()
diff --git a/satellite/nmea.py b/satellite/nmea.py
index 5201149..b1f9a83 100644
--- a/satellite/nmea.py
+++ b/satellite/nmea.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 Teemu Ikonen
+# Copyright 2021-2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
import datetime
diff --git a/satellite/nmeasource.py b/satellite/nmeasource.py
index 130e1c7..6e248d9 100644
--- a/satellite/nmeasource.py
+++ b/satellite/nmeasource.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 Teemu Ikonen
+# Copyright 2021-2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
import os.path
diff --git a/satellite/quectel.py b/satellite/quectel.py
index e009832..0fcc1e4 100644
--- a/satellite/quectel.py
+++ b/satellite/quectel.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 Teemu Ikonen
+# Copyright 2021-2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
import re
diff --git a/satellite/util.py b/satellite/util.py
index 02881fd..a6bb387 100644
--- a/satellite/util.py
+++ b/satellite/util.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 Teemu Ikonen
+# Copyright 2021-2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
import os
diff --git a/satellite/widgets.py b/satellite/widgets.py
index 23f768c..151d855 100644
--- a/satellite/widgets.py
+++ b/satellite/widgets.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 Teemu Ikonen
+# Copyright 2021-2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
import importlib.resources as resources
From 2c5d3a7e9394c65e072b11b77e0c763ce2440efa Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 7 Jul 2023 15:49:28 +0300
Subject: [PATCH 40/50] nmeasource: Add manufacturer string to gnss-share
source
---
satellite/nmeasource.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/satellite/nmeasource.py b/satellite/nmeasource.py
index 6e248d9..842aa7a 100644
--- a/satellite/nmeasource.py
+++ b/satellite/nmeasource.py
@@ -109,6 +109,7 @@ class GnssShareNmeaSource(UnixSocketNmeaSource):
super().__init__(update_callback,
socket_file_path='/var/run/gnss-share.sock',
**kwargs)
+ self.manufacturer = "gnss-share"
class ReplayNmeaSource(NmeaSource):
From 41f4b196cc3f6784ad7240316fb4b0cb1d7f4bda Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 7 Jul 2023 15:50:40 +0300
Subject: [PATCH 41/50] Don't print source model if it does not exist
---
satellite/application.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/satellite/application.py b/satellite/application.py
index f2eac92..87090df 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -219,7 +219,8 @@ class SatelliteApp(Gtk.Application):
return GLib.SOURCE_REMOVE
self.log_msg(
- f"Source is {self.source.manufacturer}, model {self.source.model}"
+ f"Source is {self.source.manufacturer}"
+ + (f", model {self.source.model}" if self.source.model else "")
+ (f", revision {self.source.revision}" if self.source.revision else "")
+ (f" using {', '.join(self.source.quirks)} quirks"
if hasattr(self.source, "quirks") and self.source.quirks else ""))
From 2a5785292f44b6305b7985ec2c5b05fe53e59a85 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 7 Jul 2023 16:26:07 +0300
Subject: [PATCH 42/50] nmeasource: Keep update_cb running on
UnixSocketNmeaSource
---
satellite/nmeasource.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/satellite/nmeasource.py b/satellite/nmeasource.py
index 842aa7a..73891b5 100644
--- a/satellite/nmeasource.py
+++ b/satellite/nmeasource.py
@@ -69,6 +69,7 @@ class UnixSocketNmeaSource(NmeaSource):
def on_read_data_available(self, io_channel, condition, **unused):
self.update_callback()
+ return True
def initialize(self):
if (self.socket_file_path is None
From f1d04c6868e79b847cd852b55feece29496c51b8 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Fri, 7 Jul 2023 16:39:08 +0300
Subject: [PATCH 43/50] Use last_mode as default GSA mode to avoid 'Lock lost'
log spam
---
satellite/application.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/satellite/application.py b/satellite/application.py
index 87090df..439b100 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -622,7 +622,7 @@ class SatelliteApp(Gtk.Application):
# log
mode = data["mode"]
- mode = int(mode) if mode else 0
+ mode = int(mode) if mode else self.last_mode
if mode != self.last_mode:
if mode > 1:
self.log_msg(f"Got lock, mode: {mode}")
From c615a432f4fb45e0edf28d1d4ee62f6db77229bb Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sun, 6 Aug 2023 17:18:25 +0300
Subject: [PATCH 44/50] Parse 'fixtime' also from GNS and GGA, remove unused
'time' from data dict
---
satellite/nmea.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/satellite/nmea.py b/satellite/nmea.py
index b1f9a83..bc93e14 100644
--- a/satellite/nmea.py
+++ b/satellite/nmea.py
@@ -99,10 +99,8 @@ getters = {
'GGA': get_altitude_gga,
'GNS': fget('altitude'),
},
- "fixtime": {
+ "fixtime": { # Time of position report
'RMC': get_time,
- },
- "time": { # Reported also when no fix
'GNS': get_time,
'GGA': get_time,
},
From 85c6bfefd7f59858ba5e74fc7e79e207e972e1a1 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sat, 23 Sep 2023 12:34:22 +0300
Subject: [PATCH 45/50] nmea: Fix iget()
---
satellite/nmea.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/satellite/nmea.py b/satellite/nmea.py
index bc93e14..4141791 100644
--- a/satellite/nmea.py
+++ b/satellite/nmea.py
@@ -29,7 +29,7 @@ def fget(key, scale=1.0):
def iget(key, default=None):
def fn(d):
try:
- return int(d.get(key))
+ return int(d.get(key, default))
except ValueError:
return default
return fn
From 5d6059416e3af5bcba24bdf1db1fff8888daa623 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sat, 23 Sep 2023 13:02:56 +0300
Subject: [PATCH 46/50] nmea: Rename 'geo_sep' field to 'geoid_sep', parse it
also from GGA
---
satellite/nmea.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/satellite/nmea.py b/satellite/nmea.py
index 4141791..91660b6 100644
--- a/satellite/nmea.py
+++ b/satellite/nmea.py
@@ -143,7 +143,8 @@ getters = {
"vdop": {
'GSA': fget('vdop'),
},
- "geo_sep": {
+ "geoid_sep": {
+ 'GGA': fget('geo_sep'),
'GNS': fget('geo_sep'),
},
"sel_mode": {
From a5453cf85f8105ea81a0d5c1599332772f454b7e Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sat, 23 Sep 2023 13:03:38 +0300
Subject: [PATCH 47/50] Add 'Geoidal separation' field to dataframe
---
satellite/application.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/satellite/application.py b/satellite/application.py
index 439b100..187bd86 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -450,6 +450,7 @@ class SatelliteApp(Gtk.Application):
("latlon", "Latitude", lambda x: "%0.6f" % x[0] if x else "-"),
("latlon", "Longitude", lambda x: "%0.6f" % x[1] if x else "-"),
("altitude", "Altitude", lambda x: to_str(x, "%0.1f m")),
+ ("geoid_sep", "Geoidal separation", lambda x: to_str(x, "%0.1f m")),
# ("fixtime", "Time of fix",
# lambda x: x.strftime(utcfmt) if x else "-"),
# ("date", "Date of fix",
From 90384a0e276a5a26af59a08228a9135f90739664 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sat, 23 Sep 2023 13:27:33 +0300
Subject: [PATCH 48/50] Print DOPs (PDOP, HDOP, VDOP) on a single line
---
satellite/application.py | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/satellite/application.py b/satellite/application.py
index 187bd86..6dde3ee 100755
--- a/satellite/application.py
+++ b/satellite/application.py
@@ -430,6 +430,12 @@ class SatelliteApp(Gtk.Application):
fixage = to_str(data.get("fixage"), "%0.0f s")
return "%s / %s" % (up_age, fixage)
+ def get_dops(xkey):
+ pdop = to_str(data.get("pdop"), "%1.1f")
+ hdop = to_str(data.get("hdop"), "%1.1f")
+ vdop = to_str(data.get("vdop"), "%1.1f")
+ return f"{pdop} / {hdop} / {vdop}"
+
mode2fix = {
"2": "2 D",
"3": "3 D",
@@ -459,9 +465,7 @@ class SatelliteApp(Gtk.Application):
("true_course", "True Course",
lambda x: to_str(x, "%0.1f deg ")
+ (bearing_to_arrow(x) if x is not None else "")),
- ("pdop", "PDOP", lambda x: to_str(x)),
- ("hdop", "HDOP", lambda x: to_str(x)),
- ("vdop", "VDOP", lambda x: to_str(x)),
+ ("pdop", "PDOP/HDOP/VDOP", get_dops),
]
descs = []
vals = []
From ccaa2db75d6bb75005482a8cfdecd14e3d6621d6 Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sat, 23 Sep 2023 13:54:52 +0300
Subject: [PATCH 49/50] flatpak: Update Gnome runtime to version 45
---
flatpak/page.codeberg.tpikonen.satellite.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flatpak/page.codeberg.tpikonen.satellite.yaml b/flatpak/page.codeberg.tpikonen.satellite.yaml
index 6007aa5..6139184 100644
--- a/flatpak/page.codeberg.tpikonen.satellite.yaml
+++ b/flatpak/page.codeberg.tpikonen.satellite.yaml
@@ -1,6 +1,6 @@
app-id: page.codeberg.tpikonen.satellite
runtime: org.gnome.Platform
-runtime-version: "44"
+runtime-version: "45"
sdk: org.gnome.Sdk
command: satellite
rename-desktop-file: satellite.desktop
From 81569df8e28db1dcad589e91b297b9cde6b54d4b Mon Sep 17 00:00:00 2001
From: Teemu Ikonen
Date: Sat, 23 Sep 2023 14:31:05 +0300
Subject: [PATCH 50/50] Release 0.4.2
---
data/appdata.xml | 10 ++++++++++
satellite/__init__.py | 2 +-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/data/appdata.xml b/data/appdata.xml
index 04614b6..ce75e04 100644
--- a/data/appdata.xml
+++ b/data/appdata.xml
@@ -49,6 +49,16 @@
+
+
+ The geoidal release
+
+ - Add 'Geoidal separation' field to dataframe
+ - Display DOPs (PDOP, HDOP, VDOP) on a single dataframe line
+ - Various small fixes to gnss-share source, logging, NMEA parsing etc.
+
+
+
The automatic release
diff --git a/satellite/__init__.py b/satellite/__init__.py
index 2d554b9..4f97f0a 100644
--- a/satellite/__init__.py
+++ b/satellite/__init__.py
@@ -1,4 +1,4 @@
# Copyright 2021-2023 Teemu Ikonen
# SPDX-License-Identifier: GPL-3.0-only
-__version__ = "0.4.1"
+__version__ = "0.4.2"