diff --git a/mapservice.py b/mapservice.py index 7ab3095..eeb5c15 100644 --- a/mapservice.py +++ b/mapservice.py @@ -1,5 +1,7 @@ """ -Map access inspired by Norbert Walter +Map access inspired by Norbert Walter (mapconverter) + +- North always up no rotation """ @@ -15,6 +17,10 @@ class MapService(): def __init__(self, logger, cfg): self.cachepath = os.path.join(cfg['histpath'], "tilecache") + self.server = "freenauticalchart.net" + self.serverpath = "/qmap-de/{2}/{0}/{1}.png" # 0:x, 1:y, 2:zoom + self.apikey = None # future use + self.useragent = "OBP/1.0 (X11; Linux x86_64; rv:0.1) OBP60v/0.1" self.lat = 53.56938345759218 self.lon = 9.679658234303275 self.dither_type = Image.FLOYDSTEINBERG @@ -27,12 +33,16 @@ class MapService(): self.width = width self.height = height + def get_px_meters(self, lat, zoom): + # Erdumfang am Äquator: 40075016 m + return 40075016 * math.cos(math.radians(lat)) / (2 ** (zoom + 8)) + def web_get_tile(self, domain, path): ssl_context = ssl.create_default_context() conn = http.client.HTTPSConnection(domain, 443, context=ssl_context) headers = { #"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0" - "User-Agent": "OBP/1.0 (X11; Linux x86_64; rv:0.1) OBP60v/0.1" + "User-Agent": self.useragent } data = None try: @@ -85,10 +95,10 @@ class MapService(): #print(f"Tile {x}, {y} loaded from disk cache.") with open(tile_path, 'rb') as f: tile_data = f.read() - #ram_cache.set(cache_key, tile_data) # Load into RAM cache return Image.open(tile_path) - data = self.web_get_tile("freenauticalchart.net", f"/qmap-de/{zoom}/{x}/{y}.png") + print(self.serverpath.format(x, y, zoom)) + data = self.web_get_tile(self.server, self.serverpath.format(x, y, zoom)) if data: tile = Image.open(BytesIO(data)) tile.save(tile_path) diff --git a/pages/anchor.py b/pages/anchor.py index 4ba01de..8e370b3 100644 --- a/pages/anchor.py +++ b/pages/anchor.py @@ -48,6 +48,14 @@ class Anchor(Page): self.scale = 425 # Radius of display circle in meter self._bd = boatdata + self.zoom = 15 + self.app.mapsrv.set_output_size(260, 260) + self.app.mapsrv.get_px_meters(self._bd.lat.getRawValue(), self.zoom) + self.bgimage = None + self._map_tick = 10 + # Vor Hafeneinfahrt Wedel + #self.lat = 53.56938345759218 + #self.lon = 9.679658234303275 # Der sinnvolle Abstand ist abhängig von der Länge der gesteckten Kette # Die initial eingegebene Position des Ankers sollte nactträglich justiert @@ -60,8 +68,6 @@ class Anchor(Page): self.anchor_lon = 0 self.anchor_depth = -1 self.anchor_ts = None # Timestamp of dropped anchor - self.lat = 0 - self.lon = 0 self.heading = -1 self.depth = -1 self.alarm_range = 20 @@ -69,10 +75,6 @@ class Anchor(Page): self.alarm = False # Alarm ist ausgelöst und aktiv self.wind_angle = -1 - # Seekarte, mit Hintergrund wie das Display - self.app.mapsrv.set_output_size(260, 260) - self.bgimage = self.app.mapsrv.get_round_bwmap_cairo(53.56938345759218, 9.679658234303275, 15, (220, 220, 220)) - # Menüsteuerung für Konfiguration self._menu = Menu("Options", 20, 80) self._menu.setItemDimension(120, 20) @@ -80,7 +82,7 @@ class Anchor(Page): newitem.setRange(0, 200, (1, 5, 10)) newitem = self._menu.addItem("chainmax", "Chain max", "int", self.chain_length, "m") newitem.setRange(0, 200, (1, 5, 10)) - newitem = self._menu.addItem("zoom", "Zoom", "int", 2) + newitem = self._menu.addItem("zoom", "Zoom", "int", 15) newitem.setRange(1, 8, (1,)) newitem = self._menu.addItem("range", "Alarm range", "int", 40, "m") newitem.setRange(1, 200, (1, 5, 10)) @@ -88,6 +90,10 @@ class Anchor(Page): self._test = 0 + def display_new(self): + if self._bd.lat.valid and self._bd.lon.valid: + self.bgimage = self.app.mapsrv.get_round_bwmap_cairo(self._bd.lat.getValueRaw(), self._bd.lon.getValueRaw(), self.zoom, (220, 220, 220)) + def handle_key(self, buttonid): if buttonid == 1: if self.mode == 'N': @@ -110,8 +116,8 @@ class Anchor(Page): # Normal if buttonid == 2: if not self.anchor_set: - self.anchor_lat = self._bd.lat - self.anchor_lon = self._bd.lon + self.anchor_lat = self._bd.lat.getValueRaw() + self.anchor_lon = self._bd.lon.getValueRaw() self.anchor_set = True self.anchor_ts = time.time() self.buttonlabel[2] = 'RISE' @@ -185,10 +191,15 @@ class Anchor(Page): # self.anchor_lat = # Seekarte als Hintergrundbild - ctx.save() - ctx.set_source_surface(self.bgimage, (400 - 260) // 2, 20) - ctx.paint() - ctx.restore() + if self._bd.lat.valid and self._bd.lon.valid: + self._map_tick -= 1 + if not self.bgimage or self._map_tick == 0: + self.bgimage = self.app.mapsrv.get_round_bwmap_cairo(self._bd.lat.getValueRaw(), self._bd.lon.getValueRaw(), self.zoom, (220, 220, 220)) + self._map_tick = 10 + ctx.save() + ctx.set_source_surface(self.bgimage, (400 - 260) // 2, 20) + ctx.paint() + ctx.restore() # Name ctx.select_font_face("Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD) @@ -212,8 +223,13 @@ class Anchor(Page): ctx.show_text(f"{self.chain} m") ctx.move_to(10, 220) - if self._bd.dbs.valid: - ctx.show_text(self._bd.dbs.format()) + #if self._bd.dbs.valid: + ctx.show_text(self._bd.dbs.format()) + + # Aktuelle Koordinaten + self.draw_text_ralign(ctx, 396, 235, "Boat") + self.draw_text_ralign(ctx, 396, 255, self._bd.lat.format()) + self.draw_text_ralign(ctx, 396, 275, self._bd.lon.format()) ctx.stroke() diff --git a/pages/page.py b/pages/page.py index 5ecaddb..793ef2d 100644 --- a/pages/page.py +++ b/pages/page.py @@ -64,6 +64,24 @@ class Page(): c = 2 * asin(sqrt(a)) return c * 3440 + @staticmethod + def format_lat(latitude, decpl=4): + if not latitude: + return '---' + degrees = int(latitude) + minutes = (latitude - degrees) * 60 + direction = 'N' if latitude > 0 else 'S' + return "{0}° {1:.{3}f}' {2}".format(degrees, minutes, direction, decpl) + + @staticmethod + def format_lon(longitude, decpl=4): + if not longitude: + return '---' + degrees = int(longitude) + minutes = (longitude - degrees) * 60 + direction = 'E' if longitude > 0 else 'W' + return "{0}° {1:.{3}f}' {2}".format(degrees, minutes, direction, decpl) + def __init__(self, pageno, cfg, appdata, boatdata): self.pageno = pageno self.cfg = cfg