diff -Nru satellite-gtk-0.2.8/data/appdata.xml satellite-gtk-0.3.1/data/appdata.xml --- satellite-gtk-0.2.8/data/appdata.xml 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/data/appdata.xml 2022-11-17 16:58:42.000000000 +0000 @@ -32,22 +32,42 @@ The main view with a GPS fix - https://codeberg.org/tpikonen/satellite/raw/branch/main/data/screenshots/screenshot3.png + https://github.com/flathub/page.codeberg.tpikonen.satellite/raw/master/screenshot-fix.png Logging - https://codeberg.org/tpikonen/satellite/raw/branch/main/data/screenshots/screenshot2.png + https://github.com/flathub/page.codeberg.tpikonen.satellite/raw/master/screenshot-log.png Expanded satellite SNR view - https://codeberg.org/tpikonen/satellite/raw/branch/main/data/screenshots/screenshot5.png + https://github.com/flathub/page.codeberg.tpikonen.satellite/raw/master/screenshot-snr.png Speedometer and track recording - https://codeberg.org/tpikonen/satellite/raw/branch/main/data/screenshots/screenshot-track.png + https://github.com/flathub/page.codeberg.tpikonen.satellite/raw/master/screenshot-track.png + + +

The quickfix release

+
    +
  • Fix screenshot links, so that flathub builds work
  • +
+
+
+ + +

The multiplatform release

+
    +
  • Add UnixNmeaSource and GnssShareNmeaSource, enabling support for devices which use gnss-share, like Librem 5 (thanks devrtz)
  • +
  • Allow specifying NmeaSource from the command line (thanks devrtz)
  • +
  • Prefilter NMEA sentences before parsing, enabling support for devices which emit proprietary sentences, like Oneplus 6
  • +
  • Display app menu on edge-overshot only on touchscreen devices
  • +
  • Flatpak: Update to Gnome runtime 43 (thanks ferenc)
  • +
+
+

Ageless no more

Binary files /tmp/tmptxi8o6up/kWWag_qMCH/satellite-gtk-0.2.8/data/screenshots/screenshot1.png and /tmp/tmptxi8o6up/p0LiSawEUJ/satellite-gtk-0.3.1/data/screenshots/screenshot1.png differ Binary files /tmp/tmptxi8o6up/kWWag_qMCH/satellite-gtk-0.2.8/data/screenshots/screenshot2.png and /tmp/tmptxi8o6up/p0LiSawEUJ/satellite-gtk-0.3.1/data/screenshots/screenshot2.png differ Binary files /tmp/tmptxi8o6up/kWWag_qMCH/satellite-gtk-0.2.8/data/screenshots/screenshot3.png and /tmp/tmptxi8o6up/p0LiSawEUJ/satellite-gtk-0.3.1/data/screenshots/screenshot3.png differ Binary files /tmp/tmptxi8o6up/kWWag_qMCH/satellite-gtk-0.2.8/data/screenshots/screenshot4.png and /tmp/tmptxi8o6up/p0LiSawEUJ/satellite-gtk-0.3.1/data/screenshots/screenshot4.png differ Binary files /tmp/tmptxi8o6up/kWWag_qMCH/satellite-gtk-0.2.8/data/screenshots/screenshot5.png and /tmp/tmptxi8o6up/p0LiSawEUJ/satellite-gtk-0.3.1/data/screenshots/screenshot5.png differ Binary files /tmp/tmptxi8o6up/kWWag_qMCH/satellite-gtk-0.2.8/data/screenshots/screenshot-track.png and /tmp/tmptxi8o6up/p0LiSawEUJ/satellite-gtk-0.3.1/data/screenshots/screenshot-track.png differ diff -Nru satellite-gtk-0.2.8/debian/changelog satellite-gtk-0.3.1/debian/changelog --- satellite-gtk-0.2.8/debian/changelog 2022-12-06 16:06:52.000000000 +0000 +++ satellite-gtk-0.3.1/debian/changelog 2023-01-22 15:06:59.000000000 +0000 @@ -1,3 +1,10 @@ +satellite-gtk (0.3.1-1) unstable; urgency=medium + + * New upstream release + * d/watch: Remove filename mangling + + -- Evangelos Ribeiro Tzaras Sun, 22 Jan 2023 16:06:59 +0100 + satellite-gtk (0.2.8-2) unstable; urgency=medium * Source-only upload to allow migration to testing diff -Nru satellite-gtk-0.2.8/debian/watch satellite-gtk-0.3.1/debian/watch --- satellite-gtk-0.2.8/debian/watch 2022-12-06 15:57:41.000000000 +0000 +++ satellite-gtk-0.3.1/debian/watch 2023-01-22 15:06:59.000000000 +0000 @@ -1,3 +1,2 @@ version=4 -opts=filenamemangle=s/.*\/archive\/(\d+\.\S+)\.tar\.gz/satellite-gtk-$1\.tar\.gz - https://codeberg.org/tpikonen/satellite/tags .*/archive/(\d+\.\S+)\.tar\.gz +https://codeberg.org/tpikonen/satellite/tags .*/archive/@ANY_VERSION@\.tar\.gz diff -Nru satellite-gtk-0.2.8/flatpak/page.codeberg.tpikonen.satellite.json satellite-gtk-0.3.1/flatpak/page.codeberg.tpikonen.satellite.json --- satellite-gtk-0.2.8/flatpak/page.codeberg.tpikonen.satellite.json 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/flatpak/page.codeberg.tpikonen.satellite.json 2022-11-17 16:58:42.000000000 +0000 @@ -1,7 +1,7 @@ { "app-id": "page.codeberg.tpikonen.satellite", "runtime": "org.gnome.Platform", - "runtime-version": "42", + "runtime-version": "43", "sdk": "org.gnome.Sdk", "command": "satellite", "rename-desktop-file": "satellite.desktop", diff -Nru satellite-gtk-0.2.8/README.md satellite-gtk-0.3.1/README.md --- satellite-gtk-0.2.8/README.md 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/README.md 2022-11-17 16:58:42.000000000 +0000 @@ -1,12 +1,13 @@ # Satellite -![The main view with a GPS fix](https://codeberg.org/tpikonen/satellite/raw/branch/main/data/screenshots/screenshot3.png) -![Logging](https://codeberg.org/tpikonen/satellite/raw/branch/main/data/screenshots/screenshot2.png) -![Expanded satellite SNR view](https://codeberg.org/tpikonen/satellite/raw/branch/main/data/screenshots/screenshot5.png) -![Speedometer and track recording](https://codeberg.org/tpikonen/satellite/raw/branch/main/data/screenshots/screenshot-track.png) +![The main view with a GPS fix](https://github.com/flathub/page.codeberg.tpikonen.satellite/raw/master/screenshot-fix.png) +![Logging](https://github.com/flathub/page.codeberg.tpikonen.satellite/raw/master/screenshot-log.png) +![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 -(GNSS: GPS et al.) data obtained from modemmanager API. It can also save your position to a GPX-file. +(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. ## License diff -Nru satellite-gtk-0.2.8/satellite/application.py satellite-gtk-0.3.1/satellite/application.py --- satellite-gtk-0.2.8/satellite/application.py 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/satellite/application.py 2022-11-17 16:58:42.000000000 +0000 @@ -22,8 +22,9 @@ ModemError, NmeaSourceNotFoundError, QuectelNmeaSource, + GnssShareNmeaSource, ) -from .util import now, unique_filename, bearing_to_arrow +from .util import bearing_to_arrow, have_touchscreen, now, unique_filename from .widgets import text_barchart, DataFrame from satellite import __version__ @@ -32,12 +33,15 @@ gi.require_version('Handy', '1') from gi.repository import Gdk, Gio, GLib, Gtk, Handy # noqa: E402 +appname = 'Satellite' +app_id = 'page.codeberg.tpikonen.satellite' + class SatelliteApp(Gtk.Application): def __init__(self, *args, **kwargs): Gtk.Application.__init__( - self, *args, application_id="page.codeberg.tpikonen.satellite", + self, *args, application_id=app_id, flags=Gio.ApplicationFlags.FLAGS_NONE, **kwargs) Handy.init() @@ -47,6 +51,12 @@ '-c', '--console-output', dest='console_output', action='store_true', default=False, help='Output satellite data to console') + 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') self.args = parser.parse_args() GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, @@ -71,7 +81,6 @@ self, widget_api_name)) else: setattr(self, widget_api_name, widget) - self.connect("activate", self.do_activate) self.app_menu = self.builder.get_object('app-menu') self.menu_popover = Gtk.Popover.new_from_model( @@ -99,10 +108,13 @@ self.set_speedlabel(None) self.leaflet.set_visible_child(self.databox) - self.datascroll.connect('edge-overshot', self.on_edge_overshot) + self.connect('startup', self.on_startup) + self.connect('activate', self.on_activate) + self.connect('shutdown', self.on_shutdown) # Internal state self.last_mode = 1 + self.last_data = None self.last_speed = None self.last_update = None self.source_lost = False @@ -147,20 +159,88 @@ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) - def do_startup(self): - Gtk.Application.do_startup(self) + def on_startup(self, app): self.create_actions() # Initialize modem after GUI startup GLib.idle_add(self.init_source) - def do_activate(self, *args): + def on_activate(self, app): self.setup_styles() self.add_window(self.window) self.window.show() - return True + if have_touchscreen(): + self.datascroll.connect('edge-overshot', self.on_edge_overshot) + + def on_shutdown(self, app): + """Called after main loop exits.""" + print("Cleaning up...") + self.gpx_write() + if self.source is not None: + self.source.close() + print("...done.") def init_source(self): - self.log_msg(f"Satellite version {__version__} started") + self.log_msg(f"{appname} version {__version__} started") + 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': + source_init = self.init_gnss_share_source() + + if not source_init: + self.log_msg('No NmeaSource initialized') + return False # Remove from idle_add + + self.log_msg( + f"Source is {self.source.manufacturer}, model {self.source.model}" + + f", revision {self.source.revision}" + if self.source.revision else "") + + if (self.source.model and self.source.model.startswith("QUECTEL")): + constellations = quectel.get_constellations(self.source) + if constellations is not None: + self.log_msg("Supported constellations: " + + ", ".join(constellations)) + + xtradates = quectel.get_xtradata_dates(self.source, fix_week=False) + if xtradates is not None: + dt1, dt2 = xtradates + self.log_msg("XTRA data is valid from %s to %s" % ( + dt1.isoformat(' ', 'minutes'), + dt2.isoformat(' ', 'minutes'))) + self.log_msg("XTRA data is " + + ("VALID" if now < dt2 else "NOT valid")) + + GLib.timeout_add(self.refresh_rate * 1000, self.timeout_cb, None) + + return GLib.SOURCE_REMOVE + + def init_gnss_share_source(self): + try: + self.source = GnssShareNmeaSource(self.location_update_cb) + self.source.initialize() + except Exception as e: + fatal = False + self.log_msg(str(e)) + dtext = 'Can you access "/var/run/gnss-share.sock"?\n' + str(e) + dialog = Gtk.MessageDialog( + parent=self.window, modal=True, + message_type=Gtk.MessageType.ERROR, + buttons=Gtk.ButtonsType.OK, text=dtext) + dialog.set_title("Error initializing NMEA source") + dialog.run() + dialog.destroy() + if fatal: + self.quit() + + return False + + return True + + def init_quectel_source(self): try: self.source = QuectelNmeaSource( self.location_update_cb, @@ -175,50 +255,26 @@ self.log_msg("Modem is locked") dtext = "Please unlock the Modem" else: + fatal = isinstance(e, gi.repository.GLib.GError) self.log_msg("Error initializing NMEA source") - dtext = e.message if hasattr(e, 'message') else ( + etext = str(e) + dtext = etext if etext else ( "Could not find or initialize NMEA source") dialog = Gtk.MessageDialog( parent=self.window, modal=True, message_type=Gtk.MessageType.ERROR, - buttons=Gtk.ButtonsType.OK, text=dtext) + buttons=Gtk.ButtonsType.CLOSE if fatal else Gtk.ButtonsType.OK, + text=dtext) dialog.set_title("Error initializing NMEA source") dialog.run() dialog.destroy() if fatal: self.quit() + return - self.log_msg( - f"Source is {self.source.manufacturer}, model {self.source.model}" - + f", revision {self.source.revision}" - if self.source.revision else "") - - if (self.source.model and self.source.model.startswith("QUECTEL")): - constellations = quectel.get_constellations(self.source) - if constellations is not None: - self.log_msg("Supported constellations: " - + ", ".join(constellations)) - - xtradates = quectel.get_xtradata_dates(self.source, fix_week=False) - if xtradates is not None: - dt1, dt2 = xtradates - self.log_msg("XTRA data is valid from %s to %s" % ( - dt1.isoformat(' ', 'minutes'), - dt2.isoformat(' ', 'minutes'))) - self.log_msg("XTRA data is " - + ("VALID" if now < dt2 else "NOT valid")) - - GLib.timeout_add(self.refresh_rate * 1000, self.timeout_cb, None) - - return False # Remove from idle_add + return False - def quit_function(self): - """Called after main loop exits.""" - print("Cleaning up...") - self.gpx_write() - if self.source is not None: - self.source.restore() - print("...done.") + return True def sigint_handler(self): if not self.sigint_received: @@ -240,8 +296,8 @@ adlg = Gtk.AboutDialog( transient_for=self.window, modal=True, - program_name="Satellite", - logo_icon_name="page.codeberg.tpikonen.satellite", + program_name=appname, + logo_icon_name=app_id, version=__version__, comments="A program for showing navigation satellite data", license_type=Gtk.License.GPL_3_0_ONLY, @@ -311,31 +367,31 @@ def leaflet_forward_cb(self, button): self.leaflet.navigate(Handy.NavigationDirection.FORWARD) - return True def leaflet_back_cb(self, button): self.leaflet.navigate(Handy.NavigationDirection.BACK) - return True def infolabel_released_cb(self, gesture, n_press, x, y): if n_press != 1 or self.carousel.get_position() > 0.5: - return False + return self.chart_size = self.chart_small if ( self.chart_size == self.chart_large) else self.chart_large - self.update(None) - return True + self.set_barchart(self.last_data) def carousel_page_changed_cb(self, carousel, index): if index == 1 and self.chart_size == self.chart_large: self.chart_size = self.chart_small - self.update(None) + self.set_barchart(self.last_data) return False - def format_satellite_data(self, d): - bchart = text_barchart( - ((e['prn'], e['snr']) for e in d['visibles']), - d['actives'], height=self.chart_size) - return bchart + def set_barchart(self, data): + if data is None: + return '' + barchart = text_barchart( + ((e['prn'], e['snr']) for e in data['visibles']), + data['actives'], height=self.chart_size) + self.infolabel.set_markup("" + barchart + "") + return barchart def set_values(self, data): def to_str(x, fmt="%s"): @@ -471,19 +527,22 @@ def timeout_cb(self, x): dt = (time.time() - self.last_update) if self.last_update else 100 if dt > 2 * self.refresh_rate: - self.update(None) - return True + self.main_box.set_sensitive(False) + self.update() + return GLib.SOURCE_CONTINUE def location_update_cb(self, *args): self.last_update = time.time() - self.update(None) + self.main_box.set_sensitive(True) + self.update() - def update(self, x): + def update(self): try: nmeas = self.source.get() except Exception as e: fatal = False show_dialog = False + etext = str(e) dtext = None if isinstance(e, ModemLockedError): dtext = "Please unlock the Modem" @@ -491,15 +550,14 @@ elif isinstance(e, ModemNoNMEAError): dtext = "NMEA info not received with location" elif isinstance(e, ModemError): - dtext = "Unspecified modem error" + dtext = "Modem error: " + str(e) elif isinstance(e, NmeaSourceNotFoundError): if not self.source_lost: - dtext = e.message if ( - hasattr(e, 'message')) else "Modem disappeared" + dtext = etext if etext else "Modem disappeared" self.source_lost = True self.main_box.set_sensitive(False) else: - dtext = e.message if hasattr(e, 'message') else "Unknown error" + dtext = etext if etext else "Unknown error" if show_dialog: dialog = Gtk.MessageDialog( parent=self.window, modal=True, @@ -510,25 +568,30 @@ dialog.destroy() if fatal: self.quit() + return elif dtext is not None: self.log_msg(dtext) - return True + return + + if not nmeas: + return if self.source_lost: self.log_msg("Modem appeared") self.main_box.set_sensitive(True) self.source_lost = False + data = nmea.parse(nmeas) data["updateage"] = ((time.time() - self.last_update) if self.last_update else None) - barchart = self.format_satellite_data(data) + + barchart = self.set_barchart(data) if self.args.console_output: print(barchart) - self.infolabel.set_markup("" + barchart + "") + self.set_values(data) - mode = data["mode"] - mode = int(mode) if mode else 0 + speed = data['speed'] bearing = data['true_course'] self.set_speedlabel(speed, bearing) @@ -537,13 +600,18 @@ elif not speed and self.last_speed: self.carousel.scroll_to(self.infolabel) self.last_speed = speed + # log + mode = data["mode"] + mode = int(mode) if mode else 0 if mode != self.last_mode: if mode > 1: self.log_msg(f"Got lock, mode: {mode}") elif mode <= 1: self.log_msg("Lock lost") self.last_mode = mode + if self.gpx is not None and data.get("valid"): self.gpx_update(data) - return True + + self.last_data = data diff -Nru satellite-gtk-0.2.8/satellite/__init__.py satellite-gtk-0.3.1/satellite/__init__.py --- satellite-gtk-0.2.8/satellite/__init__.py 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/satellite/__init__.py 2022-11-17 16:58:42.000000000 +0000 @@ -1,4 +1,4 @@ # Copyright 2021-2022 Teemu Ikonen # SPDX-License-Identifier: GPL-3.0-only -__version__ = "0.2.8" +__version__ = "0.3.1" diff -Nru satellite-gtk-0.2.8/satellite/__main__.py satellite-gtk-0.3.1/satellite/__main__.py --- satellite-gtk-0.2.8/satellite/__main__.py 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/satellite/__main__.py 2022-11-17 16:58:42.000000000 +0000 @@ -8,7 +8,6 @@ def main(): app = SatelliteApp() app.run() - app.quit_function() sys.exit(0) diff -Nru satellite-gtk-0.2.8/satellite/nmea.py satellite-gtk-0.3.1/satellite/nmea.py --- satellite-gtk-0.2.8/satellite/nmea.py 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/satellite/nmea.py 2022-11-17 16:58:42.000000000 +0000 @@ -3,6 +3,7 @@ import datetime import pynmea2 +import re MS_PER_KNOT = 0.514444 @@ -109,6 +110,7 @@ }, "valid": { 'RMC': lambda x: x.get('status') == 'A', + 'GSA': lambda x: iget('mode_fix_type', 1)(x) > 1, }, "speed": { 'RMC': fget('spd_over_grnd', MS_PER_KNOT), @@ -206,12 +208,13 @@ return "%s%02d" % (prefix, prn) - parsed = [pynmea2.parse(n) for n in nmeas.split('\n') if n] + # Prevent pynmea2 failing with unknown NMEA sentence types + supported_nmeas = ('GSV', 'GSA', 'GGA', 'RMC', 'VTG', 'GNS') + supported_re = re.compile( + r'^\$?..(?:' + '|'.join(f'(?:{s})' for s in supported_nmeas) + ')') + parsed = [pynmea2.parse(n) for n in nmeas.split('\n') + if re.match(supported_re, n)] for msg in parsed: - # print(repr(msg)) - keys = [] - for field in msg.fields: - keys.append(field[1]) if isinstance(msg, pynmea2.types.GSV): for n in range(1, (len(msg.data) - 4) // 4 + 1): prns = getattr(msg, f'sv_prn_num_{n}', None) diff -Nru satellite-gtk-0.2.8/satellite/nmeasource.py satellite-gtk-0.3.1/satellite/nmeasource.py --- satellite-gtk-0.2.8/satellite/nmeasource.py 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/satellite/nmeasource.py 2022-11-17 16:58:42.000000000 +0000 @@ -3,6 +3,8 @@ 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 @@ -57,10 +59,62 @@ self._maybe_save(nmeas) return nmeas - def restore(self): + def close(self): pass +class UnixSocketNmeaSource(NmeaSource): + def __init__(self, + update_callback, + socket_file_path=None, + **kwargs): + super().__init__(update_callback, **kwargs) + self.socket_file_path = socket_file_path + + def on_read_data_available(self, io_channel, condition, **unused): + self.update_callback() + + def initialize(self): + if self.socket_file_path is None or \ + not os.path.exists(self.socket_file_path): + return + + self.s = socket.socket(socket.AF_UNIX, + socket.SOCK_NONBLOCK | socket.SOCK_STREAM) + try: + self.s.connect(self.socket_file_path) + except Exception as e: + raise e + + self.channel = GLib.IOChannel.unix_new(self.s.fileno()) + self.channel.add_watch(GLib.IO_IN, self.on_read_data_available) + + self.old_nmea_buf = '' + self.initialized = True + + def _really_get(self): + if not self.initialized: + self.initialize() + + buf = '' + do_read = True + + while do_read: + read_buf = self.channel.readline() + buf += read_buf + if read_buf == '': + do_read = False + + return buf + + +class GnssShareNmeaSource(UnixSocketNmeaSource): + def __init__(self, update_callback, **kwargs): + super().__init__(update_callback, + socket_file_path='/var/run/gnss-share.sock', + **kwargs) + + class ModemManagerNmeaSource(NmeaSource): def __init__(self, update_callback, **kwargs): super().__init__(update_callback, **kwargs) @@ -70,6 +124,7 @@ 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() @@ -78,7 +133,6 @@ mstr = mkeys[0] else: raise NmeaSourceNotFoundError("No Modems Found") - print(f"Modem is: {mstr}") info = objs[mstr]['org.freedesktop.ModemManager1.Modem'] self.manufacturer = info.get('Manufacturer') self.model = info.get('Model') @@ -86,7 +140,6 @@ self.modem = self.bus.get('.ModemManager1', mstr) try: - print("Modem state is: %d" % self.modem.State) if self.modem.State > 0: if self.old_refresh_rate is None: self.old_refresh_rate = self.modem.GpsRefreshRate @@ -103,9 +156,8 @@ | (cap & mm.MM_MODEM_LOCATION_SOURCE_AGPS_MSB)), True) else: - print("Modem is in a bad state, retrying later...") + raise ModemError("Modem state is: %d" % self.modem.State) except AttributeError as e: - print("Error during initialization") if self.modem.State == mm.MM_MODEM_STATE_LOCKED: raise ModemLockedError from e else: @@ -114,7 +166,7 @@ raise e self.modem.SetGpsRefreshRate(self.refresh_rate) - self.bus.subscribe( + self.location_updated = self.bus.subscribe( sender='org.freedesktop.ModemManager1', iface='org.freedesktop.DBus.Properties', signal='PropertiesChanged', @@ -133,12 +185,13 @@ retval = loc.get(mm.MM_MODEM_LOCATION_SOURCE_GPS_NMEA) if retval is None: - print("Location does not have NMEA information") self.initialized = False raise ModemNoNMEAError return retval - def restore(self): + 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: @@ -201,6 +254,8 @@ return True def _really_get(self): + if not self.nmeas: + return None nmea = self.nmeas[self.counter] self.counter += 1 if self.counter >= len(self.nmeas): diff -Nru satellite-gtk-0.2.8/satellite/util.py satellite-gtk-0.3.1/satellite/util.py --- satellite-gtk-0.2.8/satellite/util.py 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/satellite/util.py 2022-11-17 16:58:42.000000000 +0000 @@ -1,16 +1,27 @@ # Copyright 2021-2022 Teemu Ikonen # SPDX-License-Identifier: GPL-3.0-only +import gi import os from datetime import datetime, timezone +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 object formed from GPS week number and milliseconds from week start. diff -Nru satellite-gtk-0.2.8/satellite/widgets.py satellite-gtk-0.3.1/satellite/widgets.py --- satellite-gtk-0.2.8/satellite/widgets.py 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/satellite/widgets.py 2022-11-17 16:58:42.000000000 +0000 @@ -52,32 +52,6 @@ return dstr -class LabelBarChart(Gtk.Label): - - def __init__(self): - super().__init__() -# self.connect("draw", self.draw_cb) -# self.connect("size-allocate", self.size_allocate_cb) - - def update_data(self, data, highlights): - xpx_per_char = 12 - width = self.get_allocated_width() - height = self.get_allocated_height() - cwidth = int(width / xpx_per_char) - 2 - cwidth = cwidth if cwidth < 40 else 40 - print(width) - print(height) - print(cwidth) - self.set_markup( - "\n%s" % text_barchart(data, highlights, cwidth)) - - def draw_cb(self, cr, *args): - print("Draw!") - - def size_allocate_cb(self, *args): - pass - - @Gtk.Template(string=resources.read_text('satellite', 'dataframe.ui')) class DataFrame(Gtk.Bin): __gtype_name__ = 'DataFrame' diff -Nru satellite-gtk-0.2.8/setup.cfg satellite-gtk-0.3.1/setup.cfg --- satellite-gtk-0.2.8/setup.cfg 2022-09-07 07:28:28.000000000 +0000 +++ satellite-gtk-0.3.1/setup.cfg 2022-11-17 16:58:42.000000000 +0000 @@ -1,2 +1,3 @@ [flake8] exclude=.git,__pycache__,build +max-line-length=88