From d62e53baf88fd50664908200c11ec99f59538c61 Mon Sep 17 00:00:00 2001 From: marko Date: Wed, 16 Feb 2022 18:01:49 -0500 Subject: [PATCH] Add seachart app --- apps/seachart/.#custom.html | 1 + apps/seachart/ChangeLog | 12 ++ apps/seachart/app-48.png | Bin 0 -> 5317 bytes apps/seachart/app-icon.js | 1 + apps/seachart/app.js | 71 ++++++++++ apps/seachart/app.png | Bin 0 -> 16122 bytes apps/seachart/custom.html | 244 ++++++++++++++++++++++++++++++++++ apps/seachart/metadata.json | 18 +++ apps/seachart/openseachart.js | 71 ++++++++++ apps/seachart/screenshot.png | Bin 0 -> 5711 bytes 10 files changed, 418 insertions(+) create mode 120000 apps/seachart/.#custom.html create mode 100644 apps/seachart/ChangeLog create mode 100644 apps/seachart/app-48.png create mode 100644 apps/seachart/app-icon.js create mode 100644 apps/seachart/app.js create mode 100644 apps/seachart/app.png create mode 100644 apps/seachart/custom.html create mode 100644 apps/seachart/metadata.json create mode 100644 apps/seachart/openseachart.js create mode 100644 apps/seachart/screenshot.png diff --git a/apps/seachart/.#custom.html b/apps/seachart/.#custom.html new file mode 120000 index 000000000..b3aca0673 --- /dev/null +++ b/apps/seachart/.#custom.html @@ -0,0 +1 @@ +marko@MBP2.29782 \ No newline at end of file diff --git a/apps/seachart/ChangeLog b/apps/seachart/ChangeLog new file mode 100644 index 000000000..6cb9d061e --- /dev/null +++ b/apps/seachart/ChangeLog @@ -0,0 +1,12 @@ +0.01: New App! +0.02: Fix marker position, color, and map scaling +0.03: Show widgets (mainly so we can use the GPS recorder widget) +0.04: Move map rendering to a module (fix #396) +0.05: Show currently active gpsrec GPS trace (fix #395) +0.06: Add support for scrolling, option for 3 bit maps +0.07: Move to 96px tiles - less files (64 -> 25) and speed up rendering +0.08: Update for drag event refactor +0.09: Use current theme cols when drawing GPS info +0.10: Improve scale factor calculation to fix scaling issues (#984) +0.11: Add slight offset to OSM data to align it properly (fix #984) + Fix alignment of satellite info text diff --git a/apps/seachart/app-48.png b/apps/seachart/app-48.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e3c1047ea4c4ca97dd40abd8b5acd0f1f01ed8 GIT binary patch literal 5317 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 XCl}wwp@q(E00000NkvXXu0mjfcN$n& literal 0 HcmV?d00001 diff --git a/apps/seachart/app-icon.js b/apps/seachart/app-icon.js new file mode 100644 index 000000000..be06afe32 --- /dev/null +++ b/apps/seachart/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AAOxAAIFCABmrwwRP/2yBJAvCAAYZJ2Wr1eHAAYSLAAQwP1YYHF4xEGCQovT2IYGFwIwDCIWAq1cwIABrtWwAaETZIuFCgIVDA4QvEBoNcq2s6/X2ezCQIDBwIKB2QBBF5ulAYQvI2IvBEQQAD1gACGQVXwKQPLwQwERwmrwFXLAJTDGAoACxFWF55VCGYSqCXYKOBrqHCAAXXAIQyExABBrjAOFQKSDMYQIBw9W2a7CFYiUGw4wBwTwPSQhmCGAJ7BAB4wDqwvIcwTnFYggFBrrjDRonX2ZnCSImHAQMrF5IAFLQQ3DrgtCRoYvDAQLJDF4ZgJOpAvBFgLtBXoIvHLgQCBF4QuCMAeIF5otCLwIuCw2B1mzEwQBB2etAAouEFoJgBSAwtE2IBCRYQvCwGIE4wACGQI0DGAwvGLopaBMIQvDwztBFQopBMQRkEF47AFRoy8Ga4KOBGAgpCSBoABF5mxRous1eBR4jmCSpAvHR4qJBAAYtCAYIvCAgWBEYZDDF4+yFwuyF4gmBGA4zD1gvCrovHE4JeFF4gNCLwgwBLQYvFAoOsw+rwQvDDwQwHBQ2y69dF4wnCGIelAga+B1bwBSAYkGLQQHF2fX2a+FSAoEB0oDCDwQvDlbxCKo4AGFwPXq4uFeAwuCF4RNBR4OswUslYvPFoPXxAuHF4ruEbAgvBq8rlgvN6wuB1iNGSAwrBMAitCcQOIq0rGBgtC2YTB1gvIQQLpDd4esAoIfCFwUrAYOBRZWzrtdVAIvISA+lFwIEBwGk1YuCF4IABEQIvG2eBq2I1eHF5RfCAAeIMIOxrgqBGIMrmNWrlcwAhBrmBAAdWwAWBxAMB1ZfLFoWsxBkCFwQABv9/qweBwAwDagQABAwIACwIgBLxLkCAAKSDFwiMCwWr2SACLYQ2BHIQACHIKRBF5CiBVIguIldcxGsJwIPCLAYsCwwABF4OswIvJc4QuLq2BfIIwDCYaRBRwiaCqwvILoIWB2IDBFxGAWoOIZgIUDa4YtEMQQuJCoYdBqwuIcoWrxJgBCwaVCFgQBCAALuJPQYuLAARDBSIJdBaoYuDAAdcF5QYB1guJLgOlFwKKCGAaUCXwxeJL4ZdJwLhCLoQAD1jDBF4ZeFF5mHFxGHRghdCGAg3C1YuGF5SbCFw1cFwexwFWCYJnBGAgvCFgmGXpIAD0mrFworB1YsDAAr4CGAQDBJoIsNAAfP1QuCg8AlcGC51cHxIAN1Wjg4wBDSoAUldVF1gA/AH4A5A")) diff --git a/apps/seachart/app.js b/apps/seachart/app.js new file mode 100644 index 000000000..4ef57f50b --- /dev/null +++ b/apps/seachart/app.js @@ -0,0 +1,71 @@ +var m = require("openseachart"); +var HASWIDGETS = true; +var y1,y2; +var fix = {}; + +function redraw() { + g.setClipRect(0,y1,g.getWidth()-1,y2); + m.draw(); + drawMarker(); + if (WIDGETS["gpsrec"] && WIDGETS["gpsrec"].plotTrack) { + g.flip(); // force immediate draw on double-buffered screens - track will update later + g.setColor(0.75,0.2,0); + WIDGETS["gpsrec"].plotTrack(m); + } + g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1); +} + +function drawMarker() { + if (!fix.fix) return; + var p = m.latLonToXY(fix.lat, fix.lon); + g.setColor(1,0,0); + g.fillRect(p.x-2, p.y-2, p.x+2, p.y+2); +} + +var fix; +Bangle.on('GPS',function(f) { + fix=f; + g.reset().clearRect(0,y1,g.getWidth()-1,y1+8).setFont("6x8").setFontAlign(0,0); + var txt = fix.satellites+" satellites"; + if (!fix.fix) + txt += " - NO FIX"; + g.drawString(txt,g.getWidth()/2,y1 + 4); + drawMarker(); +}); +Bangle.setGPSPower(1, "app"); + +if (HASWIDGETS) { + Bangle.loadWidgets(); + Bangle.drawWidgets(); + y1 = 24; + var hasBottomRow = Object.keys(WIDGETS).some(w=>WIDGETS[w].area[0]=="b"); + y2 = g.getHeight() - (hasBottomRow ? 24 : 1); +} else { + y1=0; + y2=g.getHeight()-1; +} + +redraw(); + +function recenter() { + if (!fix.fix) return; + m.lat = fix.lat; + m.lon = fix.lon; + redraw(); +} + +setWatch(recenter, global.BTN2?BTN2:BTN1, {repeat:true}); + +var hasScrolled = false; +Bangle.on('drag',e=>{ + if (e.b) { + g.setClipRect(0,y1,g.getWidth()-1,y2); + g.scroll(e.dx,e.dy); + m.scroll(e.dx,e.dy); + g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1); + hasScrolled = true; + } else if (hasScrolled) { + hasScrolled = false; + redraw(); + } +}); diff --git a/apps/seachart/app.png b/apps/seachart/app.png new file mode 100644 index 0000000000000000000000000000000000000000..9047fce3378f85074b4b4d5831f1c50ed73968d8 GIT binary patch literal 16122 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 + + + + + + + + +
+
+
+

3 bit
+
+ + +
+ + + + + + + + + + + diff --git a/apps/seachart/metadata.json b/apps/seachart/metadata.json new file mode 100644 index 000000000..130f33e31 --- /dev/null +++ b/apps/seachart/metadata.json @@ -0,0 +1,18 @@ +{ + "id": "openseachart", + "name": "OpenSeaChart", + "shortName": "Openseachart", + "version": "0.11", + "description": "Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are. Once installed this also adds map functionality to `GPS Recorder` and `Recorder` apps", + "icon": "app.png", + "tags": "outdoors,gps,osm", + "supports": ["BANGLEJS","BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], + "custom": "custom.html", + "customConnect": true, + "storage": [ + {"name":"openseachart","url":"openseachart.js"}, + {"name":"openseachart.app.js","url":"app.js"}, + {"name":"openseachart.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/seachart/openseachart.js b/apps/seachart/openseachart.js new file mode 100644 index 000000000..db1f3524b --- /dev/null +++ b/apps/seachart/openseachart.js @@ -0,0 +1,71 @@ +/* OpenStreetMap plotting module. + +Usage: + +var m = require("openseachart"); +// m.lat/lon are now the center of the loaded map +m.draw(); // draw centered on the middle of the loaded map + +// plot gps position on map +Bangle.on('GPS',function(f) { + if (!f.fix) return; + var p = m.latLonToXY(fix.lat, fix.lon); + g.fillRect(p.x-2, p.y-2, p.x+2, p.y+2); +}); + +// recenter and redraw map! +function center() { + m.lat = fix.lat; + m.lon = fix.lon; + m.draw(); +} + +*/ + +var map = require("Storage").readJSON("openseachart.json"); +map.center = Bangle.project({lat:map.lat,lon:map.lon}); +exports.map = map; +exports.lat = map.lat; // actual position of middle of screen +exports.lon = map.lon; // actual position of middle of screen +var m = exports; + +exports.draw = function() { + var s = require("Storage"); + var cx = g.getWidth()/2; + var cy = g.getHeight()/2; + var p = Bangle.project({lat:m.lat,lon:m.lon}); + var ix = (p.x-map.center.x)/map.scale + (map.imgx/2) - cx; + var iy = (map.center.y-p.y)/map.scale + (map.imgy/2) - cy; + //console.log(ix,iy); + var tx = 0|(ix/map.tilesize); + var ty = 0|(iy/map.tilesize); + var ox = (tx*map.tilesize)-ix; + var oy = (ty*map.tilesize)-iy; + for (var x=ox,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 B!2|#R literal 0 HcmV?d00001