From 8e45725adce1543faed4a2fe96533367371f3db5 Mon Sep 17 00:00:00 2001 From: storm64 Date: Sun, 28 Aug 2022 21:56:59 +0200 Subject: [PATCH] [gpsnav] Add support for b2 Add support for Bangle.js 2: - Change button mapping - Remove custom graphics object and flip function - Use theme colors - Adjust sizes - Add screenshot --- apps/gpsnav/ChangeLog | 1 + apps/gpsnav/app_b2.js | 246 ++++++++++++++++++++++++++++++++++ apps/gpsnav/metadata.json | 8 +- apps/gpsnav/screenshot-b2.png | Bin 0 -> 3131 bytes 4 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 apps/gpsnav/app_b2.js create mode 100644 apps/gpsnav/screenshot-b2.png diff --git a/apps/gpsnav/ChangeLog b/apps/gpsnav/ChangeLog index 304e94690..6f327f364 100644 --- a/apps/gpsnav/ChangeLog +++ b/apps/gpsnav/ChangeLog @@ -4,3 +4,4 @@ 0.04: Fix great circle formula 0.05: Use locale for speed and distance + fix Vector font sizes 0.06: Move waypoints.json (and editor) to 'waypoints' app +0.07: Add support for b2 \ No newline at end of file diff --git a/apps/gpsnav/app_b2.js b/apps/gpsnav/app_b2.js new file mode 100644 index 000000000..d91eacef1 --- /dev/null +++ b/apps/gpsnav/app_b2.js @@ -0,0 +1,246 @@ +const Ypos = 24 - 6; // 6 offset because of the smaller labels font +var candraw = true; +var brg = 0; +var wpindex = 0; +const labels = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"]; +var loc = require("locale"); + +function drawCompass(course) { + if (!candraw) return; + g.setColor(g.theme.fg); + g.setFont("Vector", 18); + var start = course - 90; + if (start < 0) start += 360; + g.fillRect(14, Ypos + 45, 162, Ypos + 49); + var xpos = 16; + var frag = 15 - start % 15; + if (frag < 15) xpos += Math.floor((frag * 4) / 5); + else frag = 0; + for (var i = frag; i <= 180 - frag; i += 15) { + var res = start + i; + if (res % 90 == 0) { + g.drawString(labels[Math.floor(res / 45) % 8], xpos - 6, Ypos + 6); + g.fillRect(xpos - 2, Ypos + 25, xpos + 2, Ypos + 45); + } else if (res % 45 == 0) { + g.drawString(labels[Math.floor(res / 45) % 8], xpos - 9, Ypos + 6); + g.fillRect(xpos - 2, Ypos + 30, xpos + 2, Ypos + 45); + } else if (res % 15 == 0) { + g.fillRect(xpos, Ypos + 36, xpos + 1, Ypos + 45); + } + xpos += 12; + } + if (wpindex != 0) { + var bpos = brg - course; + if (bpos > 180) bpos -= 360; + if (bpos < -180) bpos += 360; + bpos = Math.round((bpos * 4) / 5) + 88; + if (bpos < 16) bpos = 7; + if (bpos > 160) bpos = 169; + g.setColor(g.theme.bgH); + g.fillCircle(bpos, Ypos + 43, 6); + } +} + +//displayed heading +var heading = 0; + +function newHeading(m, h) { + var s = Math.abs(m - h); + var delta = (m > h) ? 1 : -1; + if (s >= 180) { + s = 360 - s; + delta = -delta; + } + if (s < 2) return h; + var hd = h + delta * (1 + Math.round(s / 5)); + if (hd < 0) hd += 360; + if (hd > 360) hd -= 360; + return hd; +} + +var course = 0; +var speed = 0; +var satellites = 0; +var wp; +var dist = 0; + +function radians(a) { + return a * Math.PI / 180; +} + +function degrees(a) { + var d = a * 180 / Math.PI; + return (d + 360) % 360; +} + +function bearing(a, b) { + var delta = radians(b.lon - a.lon); + var alat = radians(a.lat); + var blat = radians(b.lat); + var y = Math.sin(delta) * Math.cos(blat); + var x = Math.cos(alat) * Math.sin(blat) - + Math.sin(alat) * Math.cos(blat) * Math.cos(delta); + return Math.round(degrees(Math.atan2(y, x))); +} + +function distance(a, b) { + var x = radians(a.lon - b.lon) * Math.cos(radians((a.lat + b.lat) / 2)); + var y = radians(b.lat - a.lat); + return Math.round(Math.sqrt(x * x + y * y) * 6371000); +} + +var selected = false; + +function drawN() { + var txt = loc.speed(speed); + g.setColor(g.theme.fg); + g.setFont("6x8", 2); + g.drawString("o", 68, Ypos + 68); + g.setFont("6x8", 1); + g.drawString(txt.substring(txt.length - 3), 156, Ypos + 70 + 30); + g.setFont("Vector", 36); + var cs = course.toString().padStart(3, "0"); + g.drawString(cs, 2, Ypos + 70); + g.drawString(txt.substring(0, txt.length - 3), 92, Ypos + 70); + g.setColor(g.theme.fg); + g.setFont("Vector", 18); + var bs = brg.toString().padStart(3, "0"); + g.setColor(g.theme.fg2); + g.drawString("Brg:", 1, Ypos + 110); + g.drawString("Dist:", 1, Ypos + 130); + g.setColor(selected ? g.theme.bgH : g.theme.bg); + g.fillRect(90, Ypos + 109, 175, Ypos + 125); + g.setColor(selected ? g.theme.fgH : g.theme.fg); + g.drawString(wp.name, 92, Ypos + 110); + g.setColor(g.theme.fg); + g.drawString(bs, 42, Ypos + 110); + g.drawString(loc.distance(dist), 42, Ypos + 130); + g.setFont("6x8", 1); + g.setColor(satellites ? g.theme.bg : g.theme.bgH); + g.fillRect(0, 167, 75, 175); + g.setColor(satellites ? g.theme.fg : g.theme.fgH); + g.drawString("Sats:", 1, 168); + g.drawString(satellites.toString(), 42, 168); +} + +var savedfix; + +function onGPS(fix) { + savedfix = fix; + if (fix !== undefined) { + course = isNaN(fix.course) ? course : Math.round(fix.course); + speed = isNaN(fix.speed) ? speed : fix.speed; + satellites = fix.satellites; + } + if (candraw) { + if (fix !== undefined && fix.fix == 1) { + dist = distance(fix, wp); + if (isNaN(dist)) dist = 0; + brg = bearing(fix, wp); + if (isNaN(brg)) brg = 0; + } + drawN(); + } +} + +var intervalRef; + +function stopdraw() { + candraw = false; + if (intervalRef) { + clearInterval(intervalRef); + } +} + +function startTimers() { + candraw = true; + intervalRefSec = setInterval(function() { + heading = newHeading(course, heading); + if (course != heading) drawCompass(heading); + }, 200); +} + +function drawAll() { + g.setColor(1, 0, 0); //red + g.fillPoly([88, Ypos + 48, 78, Ypos + 70, 98, Ypos + 70]); + drawN(); + drawCompass(heading); +} + +function startdraw() { + g.clear(); + Bangle.drawWidgets(); + startTimers(); + drawAll(); +} + +function setButtons() { + Bangle.setUI("leftright", btn => { + if (btn == 0) { + doselect(); + } else { + nextwp.bind(null, btn); + } + }); +} + +var SCREENACCESS = { + withApp: true, + request: function() { + this.withApp = false; + stopdraw(); + clearWatch(); + }, + release: function() { + this.withApp = true; + startdraw(); + setButtons(); + } +}; + +Bangle.on('lcdPower', function(on) { + if (!SCREENACCESS.withApp) return; + if (on) { + startdraw(); + } else { + stopdraw(); + } +}); + +var waypoints = require("waypoints").load(); +wp = waypoints[0]; + +function nextwp(inc) { + if (!selected) return; + wpindex += inc; + if (wpindex >= waypoints.length) wpindex = 0; + if (wpindex < 0) wpindex = waypoints.length - 1; + wp = waypoints[wpindex]; + drawN(); +} + +function doselect() { + if (selected && wpindex != 0 && waypoints[wpindex].lat === undefined && savedfix.fix) { + waypoints[wpindex] = { + name: "@" + wp.name, + lat: savedfix.lat, + lon: savedfix.lon + }; + wp = waypoints[wpindex]; + require("waypoints").save(waypoints); + } + selected = !selected; + drawN(); +} + +g.clear(); +Bangle.setLCDBrightness(1); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +// load widgets can turn off GPS +Bangle.setGPSPower(1); +drawAll(); +startTimers(); +Bangle.on('GPS', onGPS); +// Toggle selected +setButtons(); \ No newline at end of file diff --git a/apps/gpsnav/metadata.json b/apps/gpsnav/metadata.json index f1e0c92c0..dce80112f 100644 --- a/apps/gpsnav/metadata.json +++ b/apps/gpsnav/metadata.json @@ -1,15 +1,17 @@ { "id": "gpsnav", "name": "GPS Navigation", - "version": "0.06", + "version": "0.07", "description": "Displays GPS Course and Speed, + Directions to waypoint and waypoint recording, now with waypoint editor", + "screenshots": [{"url":"screenshot-b2.png"}], "icon": "icon.png", "tags": "tool,outdoors,gps", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "dependencies" : { "waypoints":"type" }, "storage": [ - {"name":"gpsnav.app.js","url":"app.min.js"}, + {"name":"gpsnav.app.js","url":"app.min.js","supports":["BANGLEJS"]}, + {"name":"gpsnav.app.js","url":"app_b2.js","supports":["BANGLEJS2"]}, {"name":"gpsnav.img","url":"app-icon.js","evaluate":true} ] } diff --git a/apps/gpsnav/screenshot-b2.png b/apps/gpsnav/screenshot-b2.png new file mode 100644 index 0000000000000000000000000000000000000000..34ad236798f9adb8e787a0b6b4d926f61b3fe5b5 GIT binary patch literal 3131 zcma)9c{JOL68wLY5Ki!`dZwi3G%wAL!F+8P!6+BU+k z+N($_sGX9!w6&EkcIvtB{rmoSXU@#`$DH$>Idjf@Gjq?z3eCwb$_@Yk=M@W6yHjlX z$Kfoev9WW>;}jrw?9eEnVMu%h064aN4ocx;re6^NZblk~^@Nja5d_@3wLr?1K zrkV6+KZgX3>1yry>yx>QnrrV4iPB)f+!aM4dxJrO7FD46K~OSl^62Q$s>vooDC|&r z{PS{`d0z-q9h?4Qp0}I6sU^8fs7C!PIj}D(-pA*$Birr3#(g6~+}GrGCL)Xe!E?vI zD}YInu7+ycxTq})%I|%>4Xq^((HJ)A_oP4ZlBIF^@)J_ezDgtvy6W}*R+Tl%r6y-l z?`k;cSN|(Zltdzrr;1Q|!+}X7Z*R@Er2DI6NAm|A?-iR=rZ0Qlo)qb6*B`qh2a4q( z>{9YucHPxX3k?;R=G<&-mzhJjz7c(puiGyM>}BhW^0Pdj0bKtzL-M;)CC-IUNuWAb}V65i3y!{P0T?W1#x2I(NM?P z#KW24!Aa?D%~v7NuB%a8;^hP}>=Fc(lt`L+j6Ci)TQMQzI$Agoa^~D_=~zlZOZW$C z0J-O#b3u7XnBMt3TZm-{{`s`xU3jpaVkIx*oxjBAzv^2m=5cM4e$kG zH%iB&hWw*96HprqvE>^pbTaLQQ`z+x=bkYa))uX_t|KDU2zvm;)FNTddO>G1HdoWt zjPNPO8+;5r^Ao8>Vd=W?PYJ!XIH<}|aOXLx7eGTP(5u)imK1;w3!T%miNJJ^@j~@=TLc9Bl?i!Tu!lc`$N*$sM=SJJ`A4~!A0lJ}P&l~yIlieh zAQAPKwk&At>dIKYp=KE-xwx1ICn=w}R6KGMbfJoJ;M$a54ah-A(tsg)Fi z72zp2fJi#thIyb2)GkZOaR*osSeeDwhIluY1j^nsebz=lpRC?BCCa z`$6)nS$kg&HuId^*XaSw6?~ZY`6)B>djVy#71wbsKaKjX|E9B8R?P`%7#jt~k?6m! zvyBWk+uj`xKLOTDrxwU>cP;!v*g^^d{zc>FFB^0GC&6Y^ zAW6y2-1EczV8v$C>`GfmRbAWA8fCqy>FMP5Y~mH!Of!4Ig3+pF(l-u zqr1w+MM$ z_@eyA9Q(8FEC_o>h@vkuia0xnLwum$%EXVi zU`<|7C+bv*P+?i;m4YW%og7s^<^@F5clfaxPd!lzHc>uykyH!pZ=|mhuM$Wp*@-;= z*@T7!x5+LTziK7U2IeZ{R+0+n8dELfa!Lt+wquGXymmHG2+8H%Z6M;2@^ z*0#DKRaM_~#kw&sT~Zm9swmcAQnEap*d_LsV1b7Dw(!Q~&@@>v zeE)%Rx8w6+49qU_h6F~e(y4DMKW(KPN-R0xakA8)vgS{8JXMv!40ztmc>8?ZoP07u zuP!Bt^RLiYPkl4W?Bjh={l6?9w5i@K%KcaYO@rEd_?IjuZ#H}~O;ZzfdM?v#5+ zwWqcA+Z$dfc+jn3_ueuEx=2BUft3x^E&x-+*Q`6LYZ5v`v^Tn2q!2|jBLsRlbH{A6 zMplWo8~u$k!K6W9&sx%zlk&4)HalN zChD}su-+eUR?}KXroFX}vUqVKXmr|h^bbU?y>} zy?xM(u72br$=NH|->?0s4Y*HkPV26ZbonGIp*M5rNNBXrN%|j$>weq?{L|E05QBTk zqA9S&6hlqfJLn3IohSM&`b(`{0GE3{5D3qqSaNo_;g}@MIp04Z5l@I#?|A(5q&$ar zPtsdFVCZm(D$^ul9JomcDBG34vs-^6&JWI%0&W5{+(JXV+w|9+ zzf&9&Gy;niz~|@01E}sO3l}RI*bdiTsubC4X;gi@WTeidz!9X?ScoWy>YUsO34$>w zaa2BG1%sIqAX`azb|EfPaP5u81boY*{6H#vVfEGUJonM*Hvn8QvodW!VH5rhV}Qfb literal 0 HcmV?d00001