mirror of https://github.com/espruino/BangleApps
Merge branch 'espruino:master' into master
commit
02489ac0f6
|
@ -0,0 +1 @@
|
|||
0.01: Change log created
|
|
@ -0,0 +1,18 @@
|
|||
Tyreid
|
||||
|
||||
Tyreid is a Bluetooth war-driving app for the Bangle.js 2.
|
||||
|
||||
Menu options:
|
||||
- Start: This turns on the Bluetooth and starts logging Bluetooth packets with time, latitude, and longitude information to a CSV file.
|
||||
- Pause/Continue: These functions pause the capture and then allow it to resume.
|
||||
- Devices: When paused this menu option will display the MAC addresses of discovered Bluetooth devices. Selecting a device will then display the MAC, Manufacturer code, the time it was first seen, and the RSSI of the first sighting.
|
||||
- Marker: This command adds a 'marker' to the CSV log, which consists of the time and location information, but the Bluetooth packet information is replaced with the word MARKER. Markers can also be added by pressing the watch's button.
|
||||
- Exit: This exits the app.
|
||||
|
||||
The current number of discovered devices is displayed in the top left corner.
|
||||
This value is displayed in green when the GPS has a fix, or red otherwise.
|
||||
|
||||
To retrieve the CSV file, connect to the watch through the Espruino web IDE (https://www.espruino.com/ide/). From there the files stored on the watch can be downloaded by clicking the storage icon in the IDE's central column.
|
||||
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
E.toArrayBuffer(atob("MDACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAtAAAAAAAAAAAAAAB/QAAAAAAAAAAAAAD/0AAAAAAAAAAAAAH+9AAAAAAAAAAAAAPtfQAAAAAAAAAAAAudH0AAAAAAAAAAAB8tB9AAAAAAAAAAAD0tAfQAAAAAAAAAAHgtAH0AAAAAAAAAAPAtAB9AAAAAAAAAAtAtAAfQAAAAAAAAB8AtAAH0AAAAAAAAD0AtAAB9AAAAAAAALgAtAAAfQAAAAAAAfAAtAAAH0AAAAAAA9AAtAAAB9AAAAAAC4AAtAAAAfQAAAAADwAAtAAAALwAAAAAAQAAtAAAAvgAAAAAAAAAsAAAC9AAAAAAAAAAsAAAP0AAAAAAAAAAsAAB/AAAAAAAAAAAsAAH4AAAAAAAAAAAsAAvQAAAAAAAAAAAsAD9AAAAAAAAAAAAsAD0AAAAAAAAAAAAsAB8AAAAAAAAAAAAsAAtAAAAAAAAAAAAsAAPQAAAAAAAAAAAsAAHwAAAAAAAAAAAsAAC4AAAAAAAAAAAsAAA9AAAAAAAAAAAsAAAPAAAAAAAAAAAsAAAHgAAAAAAAAAA8AAAC0AAAAAAAAAA8AAAA8AAAAAAAAAA8AAAAEAAAAAAAAAA8AAAAAAAAAAAAAAA8AAAAAAAAAAAAAAA8AAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,14 @@
|
|||
{ "id": "Tyreid",
|
||||
"name": "Tyreid",
|
||||
"shortName":"Tyreid",
|
||||
"version":"0.01",
|
||||
"description": "Bluetooth war-driving app for Bangle.js 2",
|
||||
"icon": "small_logo.png",
|
||||
"tags": "",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"Tyreid.app.js","url":"app.js"},
|
||||
{"name":"Tyreid.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
|
@ -0,0 +1,4 @@
|
|||
0.1: Initial release
|
||||
0.2: Added more descriptive approximations
|
||||
0.2f: Bug fixes: Incorrect hour drawn after 50 mins, incorrect quarter minute drawn after 50 mins
|
||||
0.3: Added touch interaction to display exact time and date.
|
|
@ -0,0 +1 @@
|
|||
atob("MDAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArgVYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABW19cAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsrNcrAACBVoGsVgAAgVaBrFYAAKzXK4GsKwAAgayBAAAAgVYAVoEAAAAAAAAAAADXVqyBAACs14Gs1ysArNeBrNcrAIHX14HXgQCB14HXrAAAVtdW11YAAAAAAAAAAFbXK4GsAACs1wAr11YArNcAK9dWAADXrABWVgDXgQCB1wAAAKzXgQAAAAAAAAAAAKzXrNfXKwCs1wAA14EArKwAK9dWAADXVgAAAADXgQBW1ysAAIHXVgAAAAAAAAAAANfXgYHXVgCs11aB11YArNcrgddWACvXgSsAAACsrCus1wAAK9es1ysAAAAAAAAAK9dWAACsrACsrKzXrAAArKzX16wAVtfX16wAAAAr19fXKwAArKwArKwAAAAAAAAAAAAAAAAAAACsrAArAAAArIEAKwAAAAAAAAAAAAAAACsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsrAAAAAAArIEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWVgAAAAAAVlYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArVoErAAAAAAAAAAAAAAAAAAAAAAArVgAAAAAAAAAAAAAAAAAAAAAAAAArrNfXgQCBrNdWAAAAAAAAAAAAAAAAAAAAAABW1wAAAAAAAAAAAAAAAAAAAAAAACvXrCtWgQAAANdWAAAAAAArKwAAAAAAACsAAABW1wAAAAAAAAAAAAAAAAAAAAAAAFbXKwAAAAAAANdWAAAAAIHX16wAAACB19fXVgBW1wAA14EAAAAAAAAAAAAAAAAAAIGsAAAAAAAAANdWAAAAK9eBVteBACvXgSuBVgBW1wBW1ysAAAAAAAAAAAAAAAAAAIHXAAAAAAAAANdWAAAAVtcrAKyBAFbXKwAAAABW16zX1wAAAAAAAAAAAAAAAAAAAFbXVgAAAAAAANeBAAAAVtcrANeBAFbXKwAAAABW14HXrAAAAAAAAAAAAAAAAAAAAACs14GBrAAAAKzXrIEAK9esrNdWACvX14GBVgBW1wAr11YAAAAAAAAAAAAAAAAAAAAAVoGBgQAAACusrIEAACusrFYAAAArgaysVgBWgQAAgYEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
|
|
@ -0,0 +1,156 @@
|
|||
//load fonts
|
||||
require("FontSinclair").add(Graphics);
|
||||
require("FontTeletext5x9Ascii").add(Graphics);
|
||||
|
||||
//const
|
||||
|
||||
const numbers = {
|
||||
"0": "Twelve",
|
||||
"1": "One",
|
||||
"2": "Two",
|
||||
"3": "Three",
|
||||
"4": "Four",
|
||||
"5": "Five",
|
||||
"6": "Six",
|
||||
"7": "Seven",
|
||||
"8": "Eight",
|
||||
"9": "Nine",
|
||||
"10": "Ten",
|
||||
"11": "Eleven",
|
||||
"12": "Twelve",
|
||||
"13": "One",
|
||||
"14": "Two",
|
||||
"15": "Three",
|
||||
"16": "Four",
|
||||
"17": "Five",
|
||||
"18": "Six",
|
||||
"19": "Seven",
|
||||
"20": "Eight",
|
||||
"21": "Nine",
|
||||
"22": "Ten",
|
||||
"23": "Eleven",
|
||||
"24": "Twelve",
|
||||
};
|
||||
|
||||
const minutesByQuarterString = {
|
||||
0: "O'Clock",
|
||||
15: "Fifteen",
|
||||
30: "Thirty",
|
||||
45: "Fourty-Five"
|
||||
};
|
||||
|
||||
const width = g.getWidth();
|
||||
const height = g.getHeight();
|
||||
let drawTimeout;
|
||||
|
||||
const getNearestHour = (hours, minutes) => {
|
||||
if (minutes > 54) {
|
||||
return hours + 1;
|
||||
}
|
||||
return hours;
|
||||
};
|
||||
|
||||
const getApproximatePrefix = (minutes, minutesByQuarter) => {
|
||||
if (minutes === minutesByQuarter) {
|
||||
return " exactly";
|
||||
} else if (minutesByQuarter - minutes < -54) {
|
||||
return " nearly";
|
||||
} else if (minutesByQuarter - minutes < -5) {
|
||||
return " after";
|
||||
} else if (minutesByQuarter - minutes < 0) {
|
||||
return " just after";
|
||||
} else if (minutesByQuarter - minutes > 5) {
|
||||
return " before";
|
||||
} else {
|
||||
return " nearly";
|
||||
}
|
||||
};
|
||||
|
||||
const getMinutesByQuarter = minutes => {
|
||||
if (minutes < 10) {
|
||||
return 0;
|
||||
} else if (minutes < 20) {
|
||||
return 15;
|
||||
} else if (minutes < 40) {
|
||||
return 30;
|
||||
} else if (minutes < 55) {
|
||||
return 45;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// schedule a draw for the next minute
|
||||
function queueDraw() {
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = setTimeout(function () {
|
||||
drawTimeout = undefined;
|
||||
drawTime();
|
||||
}, 60000 - (Date.now() % 60000));
|
||||
}
|
||||
|
||||
const drawTimeExact = () => {
|
||||
var dateTime = Date();
|
||||
var hours = dateTime.getHours();
|
||||
var minutes = dateTime.getMinutes().toString().padStart(2,0);
|
||||
var day = dateTime.getDay();
|
||||
var date = dateTime.getDate();
|
||||
var month = dateTime.getMonth();
|
||||
var year = dateTime.getFullYear();
|
||||
g.clear();
|
||||
g.setBgColor(0,0,0);
|
||||
g.clearRect(0,0,width, height);
|
||||
g.setColor(1,1,1);
|
||||
g.setFont("Vector", 30);
|
||||
g.drawString(hours + ":" + minutes, (width - g.stringWidth(hours + ":" + minutes))/2, height * 0.3, false);
|
||||
g.setFont("Vector", 26);
|
||||
g.drawString(month + 1 + "/" + date + "/" + year, (width - g.stringWidth(month + 1 + "/" + date + "/" + year))/2, height * 0.6, false);
|
||||
};
|
||||
|
||||
const drawTime = () => {
|
||||
//Grab time vars
|
||||
var date = Date();
|
||||
var hour = date.getHours();
|
||||
var minutes = date.getMinutes();
|
||||
var minutesByQuarter = getMinutesByQuarter(minutes);
|
||||
|
||||
//reset graphics
|
||||
g.clear();
|
||||
g.reset();
|
||||
|
||||
//Build watch face
|
||||
g.setBgColor(0, 0, 0);
|
||||
g.clearRect(0, 0, width, height);
|
||||
g.setFont("Vector", 22);
|
||||
g.setColor(1, 1, 1);
|
||||
g.drawString("It's" + getApproximatePrefix(minutes, minutesByQuarter), (width - g.stringWidth("It's" + getApproximatePrefix(minutes, minutesByQuarter))) / 2, height * 0.25, false);
|
||||
g.setFont("Vector", 30);
|
||||
g.drawString(numbers[getNearestHour(hour, minutes)], (width - g.stringWidth(numbers[getNearestHour(hour, minutes)])) / 2, height * 0.45, false);
|
||||
g.setFont("Vector", 22);
|
||||
g.drawString(minutesByQuarterString[minutesByQuarter], (width - g.stringWidth(minutesByQuarterString[minutesByQuarter])) / 2, height * 0.7, false);
|
||||
|
||||
queueDraw();
|
||||
};
|
||||
|
||||
g.clear();
|
||||
drawTime();
|
||||
|
||||
Bangle.on('lcdPower', function (on) {
|
||||
if (on) {
|
||||
drawTime();
|
||||
} else {
|
||||
if (idTimeout) {
|
||||
clearTimeout(idTimeout);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Bangle.on('touch', function(button, xy){
|
||||
drawTimeExact();
|
||||
setTimeout(drawTime, 7000);
|
||||
});
|
||||
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clock");
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
|
@ -0,0 +1,18 @@
|
|||
{ "id": "approxclock",
|
||||
"name": "Approximate Clock",
|
||||
"shortName" : "Approx Clock",
|
||||
"version": "0.3",
|
||||
"icon": "app.png",
|
||||
"description": "A really basic spelled out time display for people looking for the vague time at a glance.",
|
||||
"readme": "readme.md",
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"approxclock.app.js","url":"app.js"},
|
||||
{"name":"approxclock.img","url":"app-icon.js","evaluate":true}
|
||||
],
|
||||
"screenshots": [
|
||||
{"url": "screenshot.png"}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
## Approximate Clock
|
||||
|
||||
### Description
|
||||
|
||||
Get a rough idea of the time at a quick glance, mostly made for myself based on a similar watchface on pebble. I find this keeps me from checking my watch too often and also saves me from moments of severe brainfart staring at these mysterious symbols we call numbers.
|
||||
|
||||
Exact time and date can be viewed temporarily by touching the screen.
|
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
|
@ -5,3 +5,4 @@
|
|||
0.05: Added adjustment for Bangle.js magnetometer heading fix
|
||||
0.06: optimized to update much faster
|
||||
0.07: added support for bangle.js 2
|
||||
0.08: call setUI before loading widgets to indicate we're a clock
|
||||
|
|
|
@ -850,6 +850,8 @@ g.setBgColor(0, 0, 0);
|
|||
g.fillRect(0, 0, 175, 175);
|
||||
current_moonphase = getMoonPhase();
|
||||
|
||||
Bangle.setUI("clock");
|
||||
|
||||
// Load widgets
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
@ -865,8 +867,6 @@ Bangle.setGPSPower(1);
|
|||
|
||||
var secondInterval;
|
||||
|
||||
Bangle.setUI("clock");
|
||||
|
||||
autoUpdate();
|
||||
|
||||
setWatch(SwitchSensorState, BTN1, { repeat: true });
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "astral",
|
||||
"name": "Astral Clock",
|
||||
"version": "0.07",
|
||||
"version": "0.08",
|
||||
"description": "Clock that calculates and displays Alt Az positions of all planets, Sun as well as several other astronomy targets (customizable) and current Moon phase. Coordinates are calculated by GPS & time and onscreen compass assists orienting. See Readme before using.",
|
||||
"icon": "app-icon.png",
|
||||
"type": "clock",
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
0.01: Simple app to display loyalty cards
|
||||
0.02: Hiding widgets while showing the code
|
||||
|
|
|
@ -18,9 +18,8 @@ Bangle.drawWidgets();
|
|||
const WHITE=-1
|
||||
const BLACK=0
|
||||
|
||||
var FILE = "android.cards.json";
|
||||
|
||||
var Locale = require("locale");
|
||||
const Locale = require("locale");
|
||||
const widget_utils = require('widget_utils');
|
||||
|
||||
var fontSmall = "6x8";
|
||||
var fontMedium = g.getFonts().includes("6x15")?"6x15":"6x8:2";
|
||||
|
@ -90,6 +89,7 @@ function printLinearCode(binary) {
|
|||
}
|
||||
|
||||
function showCode(card) {
|
||||
widget_utils.hide();
|
||||
E.showScroller();
|
||||
// keeping it on rising edge would come back twice..
|
||||
setWatch(()=>showCard(card), BTN, {edge:"falling"});
|
||||
|
@ -151,6 +151,7 @@ function showCard(card) {
|
|||
var titleColor = g.theme.fg2;
|
||||
if (card.color)
|
||||
titleColor = isLight(titleBgColor) ? BLACK : WHITE;
|
||||
widget_utils.show();
|
||||
E.showScroller({
|
||||
h : g.getFontHeight(), // height of each menu item in pixels
|
||||
c : lines.length, // number of menu items
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "cards",
|
||||
"name": "Cards",
|
||||
"version": "0.01",
|
||||
"version": "0.02",
|
||||
"description": "Display loyalty cards",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screenshot_cards_overview.png"}, {"url":"screenshot_cards_card1.png"}, {"url":"screenshot_cards_card2.png"}, {"url":"screenshot_cards_barcode.png"}, {"url":"screenshot_cards_qrcode.png"}],
|
||||
|
|
|
@ -37,4 +37,5 @@
|
|||
0.29: When plotting with OpenStMap scale map to track width & height
|
||||
0.30: Add clock info for showing and toggling recording state
|
||||
0.31: Ensure that background-drawn tracks can get cancelled, and draw less at a time to make updates smoother
|
||||
plotTrack now draws the current track even if you're not actively recording
|
||||
plotTrack now draws the current track even if you're not actively recording
|
||||
0.32: Add cadence data to output files
|
|
@ -95,17 +95,27 @@ function saveGPX(track, title) {
|
|||
<trk>
|
||||
<name>${title}</name>
|
||||
<trkseg>`;
|
||||
let lastTime = 0;
|
||||
track.forEach(pt=>{
|
||||
let cadence;
|
||||
if (pt.Steps && lastTime != 0){
|
||||
cadence = pt.Steps * 60000 / (pt.Time.getTime() - lastTime);
|
||||
cadence = cadence / 2; /*Convert from rpm to spm (one cycle is two steps), see https://github.com/espruino/BangleApps/pull/3068#issuecomment-1790041058*/
|
||||
}
|
||||
lastTime = pt.Time.getTime();
|
||||
|
||||
gpx += `
|
||||
<trkpt lat="${pt.Latitude}" lon="${pt.Longitude}">
|
||||
<ele>${pt.Altitude}</ele>
|
||||
<time>${pt.Time.toISOString()}</time>
|
||||
<extensions>
|
||||
<gpxtpx:TrackPointExtension>
|
||||
${pt.Heartrate ? `<gpxtpx:hr>${pt.Heartrate}</gpxtpx:hr>`:``}${""/*<gpxtpx:distance>...</gpxtpx:distance><gpxtpx:cad>65</gpxtpx:cad>*/}
|
||||
${pt.Heartrate ? `<gpxtpx:hr>${pt.Heartrate}</gpxtpx:hr>`:``}
|
||||
${cadence ? `<gpxtpx:cad>${cadence}</gpxtpx:cad>`:``} ${""/*<gpxtpx:distance>...</gpxtpx:distance><gpxtpx:cad>65</gpxtpx:cad>*/}
|
||||
</gpxtpx:TrackPointExtension>
|
||||
</extensions>
|
||||
</trkpt>`;
|
||||
|
||||
});
|
||||
// https://www8.garmin.com/xmlschemas/TrackPointExtensionv1.xsd
|
||||
gpx += `
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "recorder",
|
||||
"name": "Recorder",
|
||||
"shortName": "Recorder",
|
||||
"version": "0.31",
|
||||
"version": "0.32",
|
||||
"description": "Record GPS position, heart rate and more in the background, then download to your PC.",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,outdoors,gps,widget,clkinfo",
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
0.01: attempt to import
|
||||
0.02: better GPS support, adding altitude and temperature support
|
||||
|
|
|
@ -25,8 +25,9 @@ minutes, real distance will be usually higher than approximation.
|
|||
Useful gestures:
|
||||
|
||||
F -- disable GPS.
|
||||
G -- enable GPS for 4 hours.
|
||||
G -- enable GPS for 4 hours in low power mode.
|
||||
N -- take a note and write it to the log.
|
||||
S -- enable GPS for 30 minutes in high power mode.
|
||||
|
||||
When application detects watch is being worn, it will use vibrations
|
||||
to communicate back to the user.
|
||||
|
@ -48,4 +49,10 @@ night.
|
|||
|
||||
I'd like to make display nicer, and likely more dynamic, displaying
|
||||
whatever application believes is most important at the time (and
|
||||
possibly allowing scrolling).
|
||||
possibly allowing scrolling).
|
||||
|
||||
Todo:
|
||||
|
||||
*) only turn on compass when needed
|
||||
|
||||
*) adjust draw timeouts to save power
|
|
@ -1,13 +1,15 @@
|
|||
{ "id": "sixths",
|
||||
"name": "Sixth sense",
|
||||
"version":"0.01",
|
||||
"version":"0.02",
|
||||
"description": "Clock for outdoor use with GPS support",
|
||||
"icon": "app.png",
|
||||
"readme": "README.md",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"tags": "",
|
||||
"allow_emulator": true,
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"storage": [
|
||||
{"name":"sixths.app.js","url":"app.js"},
|
||||
{"name":"sixths.app.js","url":"sixths.app.js"},
|
||||
{"name":"sixths.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,20 +1,53 @@
|
|||
// Sixth sense
|
||||
|
||||
// Options you'll want to edit
|
||||
const rest_altitude = 354;
|
||||
const geoid_to_sea_level = 0; // Maybe BangleJS2 already compensates?
|
||||
|
||||
const W = g.getWidth();
|
||||
const H = g.getHeight();
|
||||
|
||||
var cx = 100; cy = 105; sc = 70;
|
||||
var buzz = "", msg = "";
|
||||
temp = 0; alt = 0; bpm = 0;
|
||||
var buzz = "", msg = "", inm = "", l = "", note = "(NOTEHERE)";
|
||||
var mode = 0, mode_time = 0; // 0 .. normal, 1 .. note
|
||||
var buzz = "", /* Set this to transmit morse via vibrations */
|
||||
inm = "", l = "", /* For incoming morse handling */
|
||||
in_str = "",
|
||||
note = "(NOTEHERE)",
|
||||
debug = "v930", debug2 = "(otherdb)", debug3 = "(short)";
|
||||
var mode = 0, mode_time = 0; // 0 .. normal, 1 .. note, 2.. mark name
|
||||
var disp_mode = 0; // 0 .. normal, 1 .. small time
|
||||
|
||||
var gps_on = 0, last_fix = 0, last_restart = 0, last_pause = 0, last_fstart = 0; // utime
|
||||
var gps_needed = 0, gps_limit = 0; // seconds
|
||||
// GPS handling
|
||||
var gps_on = 0, // time GPS was turned on
|
||||
last_fix = 0, // time of last fix
|
||||
last_restart = 0, last_pause = 0, last_fstart = 0; // utime
|
||||
var gps_needed = 0, // how long to wait for a fix
|
||||
gps_limit = 0, // timeout -- when to stop recording
|
||||
gps_speed_limit = 0;
|
||||
var prev_fix = null;
|
||||
var gps_dist = 0;
|
||||
|
||||
var is_active = false;
|
||||
var cur_altitude = 0, cur_temperature = 0, alt_adjust = 0;
|
||||
const rest_altitude = 354;
|
||||
var mark_heading = -1;
|
||||
|
||||
// Is the human present?
|
||||
var is_active = false, last_active = getTime();
|
||||
var is_level = false;
|
||||
|
||||
// For altitude handling.
|
||||
var cur_altitude = 0;
|
||||
var cur_temperature = 0, alt_adjust = 0;
|
||||
var alt_adjust_mode = "";
|
||||
|
||||
// Marks
|
||||
var cur_mark = null;
|
||||
|
||||
// Icons
|
||||
|
||||
icon_alt = "\0\x08\x1a\1\x00\x00\x00\x20\x30\x78\x7C\xFE\xFF\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
icon_m = "\0\x08\x1a\1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
icon_km = "\0\x08\x1a\1\xC3\xC6\xCC\xD8\xF0\xD8\xCC\xC6\xC3\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
icon_kph = "\0\x08\x1a\1\xC3\xC6\xCC\xD8\xF0\xD8\xCC\xC6\xC3\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\xFF\x00\xC3\xC3\xFF\xC3\xC3";
|
||||
icon_c = "\0\x08\x1a\1\x00\x00\x60\x90\x90\x60\x00\x7F\xFF\xC0\xC0\xC0\xC0\xC0\xFF\x7F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
|
||||
function toMorse(x) {
|
||||
r = "";
|
||||
|
@ -28,12 +61,10 @@ function toMorse(x) {
|
|||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function aload(s) {
|
||||
buzz += toMorse(' E');
|
||||
load(s);
|
||||
}
|
||||
|
||||
function gpsRestart() {
|
||||
print("gpsRestart");
|
||||
Bangle.setGPSPower(1, "sixths");
|
||||
|
@ -41,33 +72,155 @@ function gpsRestart() {
|
|||
last_pause = 0;
|
||||
last_fstart = 0;
|
||||
}
|
||||
|
||||
function gpsPause() {
|
||||
print("gpsPause");
|
||||
Bangle.setGPSPower(0, "sixths");
|
||||
last_restart = 0;
|
||||
last_pause = getTime();
|
||||
}
|
||||
|
||||
function gpsOn() {
|
||||
gps_on = getTime();
|
||||
gps_needed = 1000;
|
||||
gps_limit = 60*60*4;
|
||||
last_fix = 0;
|
||||
prev_fix = null;
|
||||
gps_dist = 0;
|
||||
gpsRestart();
|
||||
}
|
||||
|
||||
function gpsOff() {
|
||||
Bangle.setGPSPower(0, "sixths");
|
||||
gps_on = 0;
|
||||
}
|
||||
function fmtDist(km) { return km.toFixed(1) + icon_km; }
|
||||
function fmtSteps(n) { return fmtDist(0.001 * 0.719 * n); }
|
||||
function fmtAlt(m) { return m.toFixed(0) + icon_alt; }
|
||||
function fmtTimeDiff(d) {
|
||||
if (d < 180)
|
||||
return ""+d.toFixed(0);
|
||||
d = d/60;
|
||||
return ""+d.toFixed(0)+"m";
|
||||
}
|
||||
function gpsHandleFix(fix) {
|
||||
if (!prev_fix) {
|
||||
show("GPS acquired", 10);
|
||||
buzz += " .";
|
||||
prev_fix = fix;
|
||||
}
|
||||
if (0) {
|
||||
/* GPS altitude fluctuates a lot, not really usable */
|
||||
alt_adjust = cur_altitude - (fix.alt + geoid_to_sea_level);
|
||||
alt_adjust_mode = "g";
|
||||
}
|
||||
if (1) {
|
||||
debug = ""+fix.alt+"m "+alt_adjust;
|
||||
}
|
||||
if (1) {
|
||||
let now1 = Date();
|
||||
let now2 = fix.time;
|
||||
n1 = now1.getMinutes() * 60 + now1.getSeconds();
|
||||
n2 = now2.getMinutes() * 60 + now2.getSeconds();
|
||||
debug2 = "te "+(n2-n1)+"s";
|
||||
}
|
||||
loggps(fix);
|
||||
d = calcDistance(fix, prev_fix);
|
||||
if (d > 30) {
|
||||
prev_fix = fix;
|
||||
gps_dist += d/1000;
|
||||
}
|
||||
}
|
||||
function gpsHandle() {
|
||||
let msg = "";
|
||||
if (!last_restart) {
|
||||
d = (getTime()-last_pause);
|
||||
if (last_fix)
|
||||
msg = "PL"+ fmtTimeDiff(getTime()-last_fix);
|
||||
else
|
||||
msg = "PN"+ fmtTimeDiff(getTime()-gps_on);
|
||||
|
||||
print("gps on, paused ", d, gps_needed);
|
||||
if (d > gps_needed * 2) {
|
||||
gpsRestart();
|
||||
}
|
||||
} else {
|
||||
fix = Bangle.getGPSFix();
|
||||
if (fix && fix.fix && fix.lat) {
|
||||
gpsHandleFix(fix);
|
||||
msg = fix.speed.toFixed(1) + icon_kph;
|
||||
print("GPS FIX", msg);
|
||||
|
||||
if (!last_fstart)
|
||||
last_fstart = getTime();
|
||||
last_fix = getTime();
|
||||
gps_needed = 60;
|
||||
} else {
|
||||
if (last_fix)
|
||||
msg = "L"+ fmtTimeDiff(getTime()-last_fix);
|
||||
else {
|
||||
msg = "N"+ fmtTimeDiff(getTime()-gps_on);
|
||||
if (fix) {
|
||||
msg += " " + fix.satellites + "sats";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d = (getTime()-last_restart);
|
||||
d2 = (getTime()-last_fstart);
|
||||
print("gps on, restarted ", d, gps_needed, d2, fix.lat);
|
||||
if (getTime() > gps_speed_limit &&
|
||||
(d > gps_needed || (last_fstart && d2 > 10))) {
|
||||
gpsPause();
|
||||
gps_needed = gps_needed * 1.5;
|
||||
print("Pausing, next try", gps_needed);
|
||||
}
|
||||
}
|
||||
msg += " "+gps_dist.toFixed(1)+icon_km;
|
||||
return msg;
|
||||
}
|
||||
function markNew() {
|
||||
let r = {};
|
||||
r.time = getTime();
|
||||
r.fix = prev_fix;
|
||||
r.steps = Bangle.getHealthStatus("day").steps;
|
||||
r.gps_dist = gps_dist;
|
||||
r.altitude = cur_altitude;
|
||||
r.name = "auto";
|
||||
return r;
|
||||
}
|
||||
function markHandle() {
|
||||
let m = cur_mark;
|
||||
msg = m.name + ">" + fmtTimeDiff(getTime()- m.time);
|
||||
if (m.fix && m.fix.fix) {
|
||||
let s = fmtDist(calcDistance(m.fix, prev_fix)/1000) + icon_km;
|
||||
msg += " " + s;
|
||||
debug = "wp>" + s;
|
||||
mark_heading = 180 + calcBearing(m.fix, prev_fix);
|
||||
debug2 = "wp>" + mark_heading;
|
||||
} else {
|
||||
msg += " w" + fmtDist(gps_dist - m.gps_dist);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
function entryDone() {
|
||||
show(":" + in_str);
|
||||
buzz += " .";
|
||||
switch (mode) {
|
||||
case 1: logstamp(">" + in_str); break;
|
||||
case 2: cur_mark.name = in_str; break;
|
||||
}
|
||||
in_str = 0;
|
||||
mode = 0;
|
||||
}
|
||||
function inputHandler(s) {
|
||||
print("Ascii: ", s);
|
||||
if (mode == 1) {
|
||||
note = note + s;
|
||||
print("Ascii: ", s, s[0], s[1]);
|
||||
if (s[0] == '^') {
|
||||
switch (s[1]) {
|
||||
case 'E': mode = 0; break;
|
||||
case 'T': entryDone(); break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((mode == 1) || (mode == 2)){
|
||||
in_str = in_str + s;
|
||||
show(">"+in_str, 10);
|
||||
mode_time = getTime();
|
||||
return;
|
||||
}
|
||||
|
@ -80,12 +233,21 @@ function inputHandler(s) {
|
|||
else
|
||||
s = s+(bat/5);
|
||||
buzz += toMorse(s);
|
||||
show("Bat "+bat+"%", 60);
|
||||
break;
|
||||
case 'F': gpsOff(); show("GPS off", 3); break;
|
||||
case 'G': gpsOn(); gps_limit = getTime() + 60*60*4; show("GPS on", 3); break;
|
||||
case 'I':
|
||||
disp_mode += 1;
|
||||
if (disp_mode == 2) {
|
||||
disp_mode = 0;
|
||||
}
|
||||
break;
|
||||
case 'F': gpsOff(); break;
|
||||
case 'G': gpsOn(); break;
|
||||
case 'L': aload("altimeter.app.js"); break;
|
||||
case 'N': mode = 1; note = ">"; mode_time = getTime(); break;
|
||||
case 'M': mode = 2; show("M>", 10); cur_mark = markNew(); mode_time = getTime(); break;
|
||||
case 'N': mode = 1; show(">", 10); mode_time = getTime(); break;
|
||||
case 'O': aload("orloj.app.js"); break;
|
||||
case 'S': gpsOn(); gps_limit = getTime() + 60*30; gps_speed_limit = gps_limit; show("GPS on", 3); break;
|
||||
case 'T':
|
||||
s = ' T';
|
||||
d = new Date();
|
||||
|
@ -94,9 +256,9 @@ function inputHandler(s) {
|
|||
buzz += toMorse(s);
|
||||
break;
|
||||
case 'R': aload("run.app.js"); break;
|
||||
case 'Y': buzz += " ."; Bangle.resetCompass(); break;
|
||||
}
|
||||
}
|
||||
|
||||
const morseDict = {
|
||||
'.-': 'A',
|
||||
'-...': 'B',
|
||||
|
@ -135,37 +297,46 @@ const morseDict = {
|
|||
'-....': '6',
|
||||
'-----': '0',
|
||||
};
|
||||
|
||||
let asciiDict = {};
|
||||
|
||||
for (let k in morseDict) {
|
||||
print(k, morseDict[k]);
|
||||
asciiDict[morseDict[k]] = k;
|
||||
}
|
||||
|
||||
|
||||
function morseToAscii(morse) {
|
||||
return morseDict[morse];
|
||||
}
|
||||
|
||||
function asciiToMorse(char) {
|
||||
return asciiDict[char];
|
||||
}
|
||||
|
||||
function morseHandler() {
|
||||
inputHandler(morseToAscii(inm));
|
||||
if (inm[0] == "^") {
|
||||
inputHandler("^"+morseToAscii(inm.substr(1)));
|
||||
} else {
|
||||
inputHandler(morseToAscii(inm));
|
||||
}
|
||||
|
||||
inm = "";
|
||||
l = "";
|
||||
}
|
||||
|
||||
function touchHandler(d) {
|
||||
let x = Math.floor(d.x);
|
||||
let y = Math.floor(d.y);
|
||||
|
||||
g.setColor(0.25, 0, 0);
|
||||
g.fillCircle(W-x, W-y, 5);
|
||||
|
||||
if (d.b) {
|
||||
if (1) { /* Just a debugging feature */
|
||||
g.setColor(0.25, 0, 0);
|
||||
if (0)
|
||||
g.fillCircle(W-x, W-y, 5);
|
||||
else
|
||||
g.fillCircle(x, y, 5);
|
||||
}
|
||||
if (!d.b) {
|
||||
morseHandler();
|
||||
l = "";
|
||||
return;
|
||||
}
|
||||
if (y > H/2 && l == "") {
|
||||
inm = "^";
|
||||
}
|
||||
if (x < W/2 && y < H/2 && l != ".u") {
|
||||
inm = inm + ".";
|
||||
l = ".u";
|
||||
|
@ -181,14 +352,10 @@ function touchHandler(d) {
|
|||
if (x > W/2 && y > H/2 && l != "-d") {
|
||||
inm = inm + "-";
|
||||
l = "-d";
|
||||
}
|
||||
}
|
||||
|
||||
} else
|
||||
morseHandler();
|
||||
|
||||
print(inm, "drag:", d);
|
||||
//print(inm, "drag:", d);
|
||||
}
|
||||
|
||||
function add0(i) {
|
||||
if (i > 9) {
|
||||
return ""+i;
|
||||
|
@ -196,18 +363,14 @@ function add0(i) {
|
|||
return "0"+i;
|
||||
}
|
||||
}
|
||||
|
||||
var lastHour = -1, lastMin = -1;
|
||||
|
||||
function logstamp(s) {
|
||||
logfile.write("utime=" + getTime() + " " + s + "\n");
|
||||
}
|
||||
|
||||
function loggps(fix) {
|
||||
logfile.write(fix.lat + " " + fix.lon + " ");
|
||||
logstamp("");
|
||||
}
|
||||
|
||||
function hourly() {
|
||||
print("hourly");
|
||||
s = ' T';
|
||||
|
@ -215,31 +378,35 @@ function hourly() {
|
|||
buzz += toMorse(s);
|
||||
logstamp("");
|
||||
}
|
||||
|
||||
function show(msg, timeout) {
|
||||
note = msg;
|
||||
}
|
||||
function fivemin() {
|
||||
print("fivemin");
|
||||
s = ' B';
|
||||
bat = E.getBattery();
|
||||
if (bat < 45) {
|
||||
s = s+(bat/5);
|
||||
if (bat < 25) {
|
||||
if (is_active)
|
||||
buzz += toMorse(s);
|
||||
show("Bat "+bat+"%", 60);
|
||||
}
|
||||
if (0)
|
||||
try {
|
||||
Bangle.getPressure().then((x) => { cur_altitude = x.altitude;
|
||||
cur_temperature = x.temperature; },
|
||||
print)
|
||||
.catch(print);
|
||||
print);
|
||||
} catch (e) {
|
||||
print("Altimeter error", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function every(now) {
|
||||
if ((mode > 0) && (mode_time - getTime() > 60)) {
|
||||
if ((mode > 0) && (getTime() - mode_time > 10)) {
|
||||
if (mode == 1) {
|
||||
logstamp(">" + note);
|
||||
entryDone();
|
||||
}
|
||||
mode = 0;
|
||||
}
|
||||
if (gps_on && getTime() - gps_on > gps_limit) {
|
||||
if (gps_on && getTime() > gps_limit && getTime() > gps_speed_limit) {
|
||||
Bangle.setGPSPower(0, "sixths");
|
||||
gps_on = 0;
|
||||
}
|
||||
|
@ -255,96 +422,136 @@ function every(now) {
|
|||
|
||||
}
|
||||
|
||||
function radians(a) { return a*Math.PI/180; }
|
||||
function degrees(a) { return a*180/Math.PI; }
|
||||
// distance between 2 lat and lons, in meters, Mean Earth Radius = 6371km
|
||||
// https://www.movable-type.co.uk/scripts/latlong.html
|
||||
// (Equirectangular approximation)
|
||||
function calcDistance(a,b) {
|
||||
function radians(a) { return a*Math.PI/180; }
|
||||
var x = radians(b.lon-a.lon) * Math.cos(radians((a.lat+b.lat)/2));
|
||||
var y = radians(b.lat-a.lat);
|
||||
return Math.sqrt(x*x + y*y) * 6371000;
|
||||
}
|
||||
// thanks to waypointer
|
||||
function calcBearing(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 testBearing() {
|
||||
let p1 = {}, p2 = {};
|
||||
p1.lat = 40; p2.lat = 50;
|
||||
p1.lon = 14; p2.lon = 14;
|
||||
print("bearing = ", calcBearing(p1, p2));
|
||||
}
|
||||
|
||||
function radA(p) { return p*(Math.PI*2); }
|
||||
function radD(d) { return d*(H/2); }
|
||||
function radX(p, d) {
|
||||
let a = radA(p);
|
||||
return H/2 + Math.sin(a)*radD(d);
|
||||
}
|
||||
function radY(p, d) {
|
||||
let a = radA(p);
|
||||
return W/2 - Math.cos(a)*radD(d);
|
||||
}
|
||||
function drawDot(h, d, s) {
|
||||
let x = radX(h/360, d);
|
||||
let y = radY(h/360, d);
|
||||
g.fillCircle(x,y, 10);
|
||||
}
|
||||
function drawBackground() {
|
||||
acc = Bangle.getAccel();
|
||||
is_level = (acc.z < -0.95);
|
||||
if (is_level) {
|
||||
let obj = Bangle.getCompass();
|
||||
if (obj) {
|
||||
let h = 360-obj.heading;
|
||||
print("Compass", h);
|
||||
g.setColor(0.5, 0.5, 1);
|
||||
drawDot(h, 0.7, 10);
|
||||
}
|
||||
}
|
||||
if (prev_fix && prev_fix.fix) {
|
||||
g.setColor(0.5, 1, 0.5);
|
||||
drawDot(prev_fix.course, 0.5, 6);
|
||||
}
|
||||
if (mark_heading != -1) {
|
||||
g.setColor(1, 0.5, 0.5);
|
||||
drawDot(mark_heading, 0.6, 8);
|
||||
}
|
||||
}
|
||||
function drawTime(now) {
|
||||
if (disp_mode == 0)
|
||||
g.setFont('Vector', 60);
|
||||
else
|
||||
g.setFont('Vector', 26);
|
||||
g.setFontAlign(1, 1);
|
||||
g.drawString(now.getHours() + ":" + add0(now.getMinutes()), W, 90);
|
||||
}
|
||||
function draw() {
|
||||
if (disp_mode == 2) {
|
||||
draw_all();
|
||||
return;
|
||||
}
|
||||
g.setColor(1, 1, 1);
|
||||
g.fillRect(0, 25, W, H);
|
||||
g.setFont('Vector', 60);
|
||||
g.fillRect(0, 24, W, H);
|
||||
|
||||
if (0) {
|
||||
g.setColor(0.25, 1, 1);
|
||||
g.fillPoly([ W/2, 24, W, 80, 0, 80 ]);
|
||||
}
|
||||
let msg = "";
|
||||
if (gps_on) {
|
||||
msg = gpsHandle();
|
||||
} else {
|
||||
msg = note;
|
||||
}
|
||||
drawBackground();
|
||||
|
||||
g.setColor(0, 0, 0);
|
||||
g.setFontAlign(-1, 1);
|
||||
let now = new Date();
|
||||
g.drawString(now.getHours() + ":" + add0(now.getMinutes()), 10, 90);
|
||||
g.setColor(0, 0, 0);
|
||||
drawTime(now);
|
||||
|
||||
every(now);
|
||||
|
||||
let km = 0.001 * 0.719 * Bangle.getHealthStatus("day").steps;
|
||||
|
||||
g.setFontAlign(-1, 1);
|
||||
g.setFont('Vector', 26);
|
||||
|
||||
const weekday = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
||||
|
||||
g.drawString(weekday[now.getDay()] + "" + now.getDate() + ". " + km.toFixed(1) + "km", 10, 115);
|
||||
g.drawString(weekday[now.getDay()] + "" + now.getDate() + ". "
|
||||
+ fmtSteps(Bangle.getHealthStatus("day").steps), 10, 115);
|
||||
|
||||
if (gps_on) {
|
||||
if (!last_restart) {
|
||||
d = (getTime()-last_pause);
|
||||
if (last_fix)
|
||||
msg = "PL"+ (getTime()-last_fix).toFixed(0);
|
||||
else
|
||||
msg = "PN"+ (getTime()-gps_on).toFixed(0);
|
||||
|
||||
print("gps on, paused ", d, gps_needed);
|
||||
if (d > gps_needed * 2) {
|
||||
gpsRestart();
|
||||
}
|
||||
} else {
|
||||
fix = Bangle.getGPSFix();
|
||||
if (fix.fix && fix.lat) {
|
||||
if (!prev_fix) {
|
||||
prev_fix = fix;
|
||||
}
|
||||
msg = fix.speed.toFixed(1) + " km/h";
|
||||
if (!last_fstart)
|
||||
last_fstart = getTime();
|
||||
last_fix = getTime();
|
||||
gps_needed = 60;
|
||||
loggps(fix);
|
||||
print("GPS FIX", msg);
|
||||
d = calcDistance(fix, prev_fix);
|
||||
if (d > 30) {
|
||||
prev_fix = fix;
|
||||
gps_dist += d/1000;
|
||||
}
|
||||
} else {
|
||||
if (last_fix)
|
||||
msg = "L"+ (getTime()-last_fix).toFixed(0);
|
||||
else
|
||||
msg = "N"+ (getTime()-gps_on).toFixed(0);
|
||||
}
|
||||
|
||||
d = (getTime()-last_restart);
|
||||
d2 = (getTime()-last_fstart);
|
||||
print("gps on, restarted ", d, gps_needed, d2, fix.lat);
|
||||
if (d > gps_needed || (last_fstart && d2 > 10)) {
|
||||
gpsPause();
|
||||
gps_needed = gps_needed * 1.5;
|
||||
print("Pausing, next try", gps_needed);
|
||||
}
|
||||
}
|
||||
msg += " "+gps_dist.toFixed(1)+"km";
|
||||
} else {
|
||||
msg = note;
|
||||
}
|
||||
g.drawString(msg, 10, 145);
|
||||
if (is_active) {
|
||||
g.drawString("act " + (cur_altitude - alt_adjust).toFixed(0), 10, 175);
|
||||
} else {
|
||||
|
||||
if (getTime() - last_active > 15*60) {
|
||||
alt_adjust = cur_altitude - rest_altitude;
|
||||
g.drawString(alt_adjust.toFixed(0) + "m " + cur_temperature.toFixed(1)+"C", 10, 175);
|
||||
alt_adjust_mode = "h";
|
||||
msg = "H)" + fmtAlt(alt_adjust);
|
||||
} else {
|
||||
msg = alt_adjust_mode+")"+fmtAlt(cur_altitude - alt_adjust);
|
||||
}
|
||||
msg = msg + " " + cur_temperature.toFixed(1)+icon_c;
|
||||
if (cur_mark) {
|
||||
msg = markHandle();
|
||||
}
|
||||
g.drawString(msg, 10, 175);
|
||||
|
||||
if (disp_mode == 1) {
|
||||
g.drawString(debug, 10, 45);
|
||||
g.drawString(debug2, 10, 65);
|
||||
g.drawString(debug3, 10, 85);
|
||||
}
|
||||
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
function draw_all() {
|
||||
g.setColor(0, 0, 0);
|
||||
g.fillRect(0, 0, W, H);
|
||||
|
@ -394,14 +601,13 @@ function draw_all() {
|
|||
|
||||
g.setFont('Vector', 22);
|
||||
g.drawString(now.getDate()+"."+(now.getMonth()+1)+" "+now.getDay(), 3, 60);
|
||||
g.drawString(msg, 3, 80);
|
||||
g.drawString("(message here)", 3, 80);
|
||||
g.drawString("S" + step + " B" + Math.round(bat/10) + (Bangle.isCharging()?"c":""), 3, 100);
|
||||
g.drawString("A" + Math.round(alt) + " T" + Math.round(temp), 3, 120);
|
||||
g.drawString("C" + Math.round(co.heading) + " B" + bpm, 3, 140);
|
||||
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
function accelTask() {
|
||||
tm = 100;
|
||||
acc = Bangle.getAccel();
|
||||
|
@ -424,7 +630,6 @@ function accelTask() {
|
|||
|
||||
setTimeout(accelTask, tm);
|
||||
}
|
||||
|
||||
function buzzTask() {
|
||||
if (buzz != "") {
|
||||
now = buzz[0];
|
||||
|
@ -442,9 +647,8 @@ function buzzTask() {
|
|||
setTimeout(buzzTask, 6*dot);
|
||||
} else print("Unknown character -- ", now, buzz);
|
||||
} else
|
||||
setTimeout(buzzTask, 60000);
|
||||
setTimeout(buzzTask, 1000);
|
||||
}
|
||||
|
||||
function aliveTask() {
|
||||
function cmp(s) {
|
||||
let d = acc[s] - last_acc[s];
|
||||
|
@ -456,6 +660,7 @@ function aliveTask() {
|
|||
if (cmp("x") || cmp("y") || cmp("z")) {
|
||||
print("active");
|
||||
is_active = true;
|
||||
last_active = getTime();
|
||||
}
|
||||
last_acc = acc;
|
||||
|
||||
|
@ -476,14 +681,15 @@ function queueDraw() {
|
|||
}, next - (Date.now() % next));
|
||||
|
||||
}
|
||||
|
||||
function start() {
|
||||
Bangle.on("drag", touchHandler);
|
||||
if (0)
|
||||
Bangle.on("accel", accelHandler);
|
||||
if (0) {
|
||||
if (1) {
|
||||
Bangle.setCompassPower(1, "sixths");
|
||||
Bangle.setBarometerPower(1, "sixths");
|
||||
}
|
||||
if (0) {
|
||||
Bangle.setHRMPower(1, "sixths");
|
||||
Bangle.setGPSPower(1, "sixths");
|
||||
Bangle.on("HRM", (hrm) => { bpm = hrm.bpm; } );
|
||||
|
@ -500,9 +706,14 @@ function start() {
|
|||
}
|
||||
|
||||
g.reset();
|
||||
Bangle.setUI();
|
||||
Bangle.setUI({
|
||||
mode : "clock"
|
||||
});
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
let logfile = require("Storage").open("sixths.egt", "a");
|
||||
|
||||
start();
|
||||
if (0) {
|
||||
testBearing();
|
||||
} else
|
||||
start();
|
|
@ -5,7 +5,8 @@ A simple game of stacking cubes.
|
|||
|
||||
## Usage
|
||||
|
||||
Press the button to stack!
|
||||
Boxes move horizontally. Use button to stack them on top of existing
|
||||
boxes. You win when you reach top of the screen.
|
||||
|
||||
## Creator
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"icon": "app.png",
|
||||
"tags": "game",
|
||||
"supports" : ["BANGLEJS", "BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"stacker.app.js","url":"app.js"},
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
0.01: New app!
|
||||
0.02: Better controls, implement game over.
|
||||
0.03: Implement mode and level selection screens.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ "id": "tetris",
|
||||
"name": "Tetris",
|
||||
"shortName":"Tetris",
|
||||
"version":"0.02",
|
||||
"version":"0.03",
|
||||
"description": "Tetris",
|
||||
"icon": "tetris.png",
|
||||
"readme": "README.md",
|
||||
|
|
|
@ -36,11 +36,27 @@ const tiles = [
|
|||
const ox = 176/2 - 5*8;
|
||||
const oy = 8;
|
||||
|
||||
var pf = Array(23).fill().map(()=>Array(12).fill(0)); // field is really 10x20, but adding a border for collision checks
|
||||
pf[20].fill(1);
|
||||
pf[21].fill(1);
|
||||
pf[22].fill(1);
|
||||
pf.forEach((x,i) => { pf[i][0] = 1; pf[i][11] = 1; });
|
||||
/* 0 .. simulated arrows
|
||||
1 .. drag piece
|
||||
2 .. accelerometer. 12 lines record.
|
||||
3 .. altimeter
|
||||
*/
|
||||
var control = 0, level = 0;
|
||||
var alt_start = -9999; /* For altimeter control */
|
||||
/* 0 .. menu
|
||||
1 .. game
|
||||
2 .. game over */
|
||||
var state = 0;
|
||||
|
||||
var pf;
|
||||
|
||||
function initGame() {
|
||||
pf = Array(23).fill().map(()=>Array(12).fill(0)); // field is really 10x20, but adding a border for collision checks
|
||||
pf[20].fill(1);
|
||||
pf[21].fill(1);
|
||||
pf[22].fill(1);
|
||||
pf.forEach((x,i) => { pf[i][0] = 1; pf[i][11] = 1; });
|
||||
}
|
||||
|
||||
function rotateTile(t, r) {
|
||||
var nt = JSON.parse(JSON.stringify(t));
|
||||
|
@ -98,6 +114,8 @@ function redrawPF(ly) {
|
|||
function gameOver() {
|
||||
g.setColor(1, 1, 1).setFontAlign(0, 1, 0).setFont("Vector",22)
|
||||
.drawString("Game Over", 176/2, 76);
|
||||
state = 0;
|
||||
E.showAlert("Game Over").then(selectGame, print);
|
||||
}
|
||||
|
||||
function insertAndCheck() {
|
||||
|
@ -138,6 +156,8 @@ function moveOk(t, dx, dy) {
|
|||
}
|
||||
|
||||
function gameStep() {
|
||||
if (state != 1)
|
||||
return;
|
||||
if (Date.now()-time > dropInterval) { // drop one step
|
||||
time = Date.now();
|
||||
if (moveOk(ct, 0, 1)) {
|
||||
|
@ -169,12 +189,50 @@ function move(x, y) {
|
|||
}
|
||||
}
|
||||
|
||||
Bangle.setUI();
|
||||
Bangle.on("drag", (e) => {
|
||||
let h = 176/2;
|
||||
if (!e.b)
|
||||
function linear(x) {
|
||||
print("Linear: ", x);
|
||||
let now = px / 10;
|
||||
if (x < now-0.06)
|
||||
move(-1, 0);
|
||||
if (x > now+0.06)
|
||||
move(1, 0);
|
||||
}
|
||||
|
||||
function newGame() {
|
||||
E.showMenu();
|
||||
Bangle.setUI();
|
||||
if (control == 2) {
|
||||
Bangle.on("accel", (e) => {
|
||||
if (state != 1) return;
|
||||
if (control != 2) return;
|
||||
print(e.x);
|
||||
linear((0.2-e.x) * 2.5);
|
||||
});
|
||||
}
|
||||
if (control == 3) {
|
||||
Bangle.setBarometerPower(true);
|
||||
Bangle.on("pressure", (e) => {
|
||||
if (state != 1) return;
|
||||
if (control != 3) return;
|
||||
let a = e.altitude;
|
||||
if (alt_start == -9999)
|
||||
alt_start = a;
|
||||
a = a - alt_start;
|
||||
print(e.altitude, a);
|
||||
linear(a);
|
||||
});
|
||||
}
|
||||
Bangle.on("drag", (e) => {
|
||||
let h = 176/2;
|
||||
if (state == 2) {
|
||||
if (e.b)
|
||||
selectGame();
|
||||
return;
|
||||
}
|
||||
if (!e.b)
|
||||
return;
|
||||
if (e.y < h) {
|
||||
if (state == 0) return;
|
||||
if (e.y < h) {
|
||||
if (e.x < h)
|
||||
rotate();
|
||||
else {
|
||||
|
@ -184,21 +242,60 @@ Bangle.on("drag", (e) => {
|
|||
g.flip();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
if (control == 1)
|
||||
linear((e.x - 20) / 156);
|
||||
if (control != 0)
|
||||
return;
|
||||
if (e.x < h)
|
||||
move(-1, 0);
|
||||
else
|
||||
move(1, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Bangle.on("swipe", (x,y) => {
|
||||
if (y<0) y = 0;
|
||||
move(x, y);
|
||||
});
|
||||
initGame();
|
||||
drawGame();
|
||||
state = 1;
|
||||
var step = 450 - 50*level;
|
||||
if (control == 3)
|
||||
step = step*2;
|
||||
dropInterval = step;
|
||||
var gi = setInterval(gameStep, 50);
|
||||
}
|
||||
|
||||
drawBoundingBox();
|
||||
g.setColor(1, 1, 1).setFontAlign(0, 1, 0).setFont("6x15", 1).drawString("Lines", 22, 30).drawString("Next", 176-22, 30);
|
||||
showNext(ntn, ntr);
|
||||
g.setColor(0).fillRect(5, 30, 41, 80).setColor(1, 1, 1).drawString(nlines.toString(), 22, 50);
|
||||
var gi = setInterval(gameStep, 20);
|
||||
function drawGame() {
|
||||
drawBoundingBox();
|
||||
g.setColor(1, 1, 1).setFontAlign(0, 1, 0)
|
||||
.setFont("6x15", 1).drawString("Lines", 22, 30)
|
||||
.drawString("Next", 176-22, 30);
|
||||
showNext(ntn, ntr);
|
||||
g.setColor(0).fillRect(5, 30, 41, 80)
|
||||
.setColor(1, 1, 1).drawString(nlines.toString(), 22, 50);
|
||||
}
|
||||
|
||||
function selectLevel() {
|
||||
print("Level selection menu");
|
||||
|
||||
var menu = {};
|
||||
menu["Level 1"] = () => { level = 0; selectGame(); };
|
||||
menu["Level 2"] = () => { level = 1; selectGame(); };
|
||||
menu["Level 3"] = () => { level = 2; selectGame(); };
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function selectGame() {
|
||||
state = 0;
|
||||
print("Game selection menu");
|
||||
//for (let i = 0; i < 100000; i++) ;
|
||||
|
||||
var menu = {};
|
||||
menu["Normal"] = () => { control = 0; newGame(); };
|
||||
menu["Drag"] = () => { control = 1; newGame(); };
|
||||
menu["Tilt"] = () => { control = 2; newGame(); };
|
||||
menu["Move"] = () => { control = 3; newGame(); };
|
||||
menu["Level"] = () => { selectLevel(); };
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
selectGame();
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: Display waypoint name instead of its index in remove menu and fix icon
|
||||
0.03: Use text input for waypoint names, allow marking waypoint with current GPS position
|
||||
|
|
|
@ -13,6 +13,10 @@ var wp = require('Storage').readJSON("waypoints.json", true) || [];
|
|||
2 .. DD MM'ss"
|
||||
*/
|
||||
var mode = 1;
|
||||
var key; /* Shared between functions, typically wp name */
|
||||
var fix; /* GPS fix */
|
||||
var cancel_gps;
|
||||
var gps_start;
|
||||
|
||||
function writeWP() {
|
||||
require('Storage').writeJSON("waypoints.json", wp);
|
||||
|
@ -22,28 +26,94 @@ function mainMenu() {
|
|||
var menu = {
|
||||
"< Back" : Bangle.load
|
||||
};
|
||||
if (Object.keys(wp).length==0) Object.assign(menu, {"NO WPs":""});
|
||||
else for (let id in wp) {
|
||||
if (Object.keys(wp).length==0) {
|
||||
//Object.assign(menu, {"NO WPs":""});
|
||||
print("(no waypoints)");
|
||||
} else for (let id in wp) {
|
||||
let i = id;
|
||||
menu[wp[id]["name"]]=()=>{ decode(i); };
|
||||
menu[wp[id]["name"]]=()=>{ show(i); };
|
||||
}
|
||||
menu["Add"]=addCard;
|
||||
menu["Remove"]=removeCard;
|
||||
menu["Format"]=setFormat;
|
||||
menu["Mark GPS"]=markGps;
|
||||
g.clear();
|
||||
E.showMenu(menu);
|
||||
}
|
||||
|
||||
function setFormat() {
|
||||
var confirmRemove = new Layout (
|
||||
{type:"v", c: [
|
||||
{type:"txt", font:"15%", pad:1, fillx:1, filly:1, label:"Format"},
|
||||
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: "DD.dddd", cb:l=>{ mode = 0; mainMenu(); }},
|
||||
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: "DD MM.mmm'", cb:l=>{ mode = 1; mainMenu(); }},
|
||||
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: "DD MM'ss"+'"', cb:l=>{ mode = 2; mainMenu(); }},
|
||||
], lazy:true});
|
||||
function updateGps() {
|
||||
let have = false, lat = "lat", lon = "lon", alt = "alt", speed = "speed";
|
||||
|
||||
if (cancel_gps)
|
||||
return;
|
||||
fix = Bangle.getGPSFix();
|
||||
|
||||
speed = "no fix for " + (getTime() - gps_start).toFixed(0) + "s";
|
||||
|
||||
if (fix && fix.fix && fix.lat) {
|
||||
lat = "" + lat(fix.lat);
|
||||
lon = "" + lon(fix.lon);
|
||||
alt = "alt " + fix.alt.toFixed(0) + "m";
|
||||
speed = "speed " + fix.speed.toFixed(1) + "kt";
|
||||
have = true;
|
||||
}
|
||||
|
||||
g.reset().setFont("Vector", 20)
|
||||
.setColor(1,1,1)
|
||||
.fillRect(0, 0, 176, 120)
|
||||
.setColor(0,0,0)
|
||||
.drawString(key, 0, 0)
|
||||
.drawString(lat, 0, 20)
|
||||
.drawString(lon, 0, 40)
|
||||
.drawString(alt, 0, 60)
|
||||
.drawString(speed, 0, 80);
|
||||
|
||||
setTimeout(updateGps, 100);
|
||||
}
|
||||
|
||||
function stopGps() {
|
||||
cancel_gps=true;
|
||||
Bangle.setGPSPower(0, "waypoint_editor");
|
||||
}
|
||||
|
||||
function confirmGps(s) {
|
||||
key = s;
|
||||
var la = new Layout (
|
||||
{type:"v", c: [
|
||||
{type:"txt", font:"15%", pad:1, fillx:1, filly:1, label:""},
|
||||
{type:"txt", font:"15%", pad:1, fillx:1, filly:1, label:""},
|
||||
{type:"txt", font:"15%", pad:1, fillx:1, filly:1, label:""},
|
||||
{type:"h", c: [
|
||||
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: "YES", cb:l=>{
|
||||
print("should mark", key, fix); createWP(fix.lat, fix.lon, key); cancel_gps=true; mainMenu();
|
||||
}},
|
||||
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: " NO", cb:l=>{ cancel_gps=true; mainMenu(); }}
|
||||
]}
|
||||
], lazy:true});
|
||||
g.clear();
|
||||
confirmRemove.render();
|
||||
la.render();
|
||||
updateGps();
|
||||
}
|
||||
|
||||
function markGps() {
|
||||
cancel_gps = false;
|
||||
Bangle.setGPSPower(1, "waypoint_editor");
|
||||
gps_start = getTime();
|
||||
require("textinput").input({text:"wp"}).then(key => {
|
||||
confirmGps(key);
|
||||
});
|
||||
}
|
||||
|
||||
function setFormat() {
|
||||
var la = new Layout (
|
||||
{type:"v", c: [
|
||||
{type:"txt", font:"15%", pad:1, fillx:1, filly:1, label:"Format"},
|
||||
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: "DD.dddd", cb:l=>{ mode = 0; mainMenu(); }},
|
||||
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: "DD MM.mmm'", cb:l=>{ mode = 1; mainMenu(); }},
|
||||
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: "DD MM'ss"+'"', cb:l=>{ mode = 2; mainMenu(); }},
|
||||
], lazy:true});
|
||||
g.clear();
|
||||
la.render();
|
||||
}
|
||||
|
||||
function format(x) {
|
||||
|
@ -65,7 +135,6 @@ function format(x) {
|
|||
return "" + d + " " + mf + "'" + s + '"';
|
||||
}
|
||||
}
|
||||
|
||||
function lat(x) {
|
||||
c = "N";
|
||||
if (x<0) {
|
||||
|
@ -74,7 +143,6 @@ function lat(x) {
|
|||
}
|
||||
return c+format(x);
|
||||
}
|
||||
|
||||
function lon(x) {
|
||||
c = "E";
|
||||
if (x<0) {
|
||||
|
@ -84,17 +152,17 @@ function lon(x) {
|
|||
return c+format(x);
|
||||
}
|
||||
|
||||
function decode(pin) {
|
||||
print(pin);
|
||||
var i = wp[pin];
|
||||
var pinDecrypted=i["name"] + "\n" + lat(i["lat"]) + "\n" + lon(i["lon"]);
|
||||
var showPin = new Layout ({
|
||||
type:"v", c: [
|
||||
{type:"txt", font:"10%", pad:1, fillx:1, filly:1, label: pinDecrypted},
|
||||
{type:"btn", font:"10%", pad:1, fillx:1, filly:1, label:"OK", cb:l=>{mainMenu();}}
|
||||
], lazy:true});
|
||||
g.clear();
|
||||
showPin.render();
|
||||
function show(pin) {
|
||||
print(pin);
|
||||
var i = wp[pin];
|
||||
var l = i["name"] + "\n" + lat(i["lat"]) + "\n" + lon(i["lon"]);
|
||||
var la = new Layout ({
|
||||
type:"v", c: [
|
||||
{type:"txt", font:"10%", pad:1, fillx:1, filly:1, label: l},
|
||||
{type:"btn", font:"10%", pad:1, fillx:1, filly:1, label:"OK", cb:l=>{mainMenu();}}
|
||||
], lazy:true});
|
||||
g.clear();
|
||||
la.render();
|
||||
}
|
||||
|
||||
function showNumpad(text, key_, callback) {
|
||||
|
@ -155,10 +223,10 @@ function showNumpad(text, key_, callback) {
|
|||
|
||||
function removeCard() {
|
||||
var menu = {
|
||||
"" : {title : "select card"},
|
||||
"" : {title : "Select WP"},
|
||||
"< Back" : mainMenu
|
||||
};
|
||||
if (Object.keys(wp).length==0) Object.assign(menu, {"NO CARDS":""});
|
||||
if (Object.keys(wp).length==0) Object.assign(menu, {"No WPs":""});
|
||||
else {
|
||||
wp.forEach((val, card) => {
|
||||
const name = wp[card].name;
|
||||
|
@ -186,17 +254,16 @@ function removeCard() {
|
|||
}
|
||||
|
||||
function ask01(t, cb) {
|
||||
var confirmRemove = new Layout (
|
||||
var la = new Layout (
|
||||
{type:"v", c: [
|
||||
{type:"txt", font:"15%", pad:1, fillx:1, filly:1, label:"Format"},
|
||||
{type:"txt", font:"15%", pad:1, fillx:1, filly:1, label:"Select"},
|
||||
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: t[0], cb:l=>{ cb(1); }},
|
||||
{type:"btn", font:"15%", pad:1, fillx:1, filly:1, label: t[1], cb:l=>{ cb(-1); }},
|
||||
], lazy:true});
|
||||
g.clear();
|
||||
confirmRemove.render();
|
||||
la.render();
|
||||
}
|
||||
|
||||
|
||||
function askCoordinate(t1, t2, callback) {
|
||||
let sign = 1;
|
||||
ask01(t1, function(sign) {
|
||||
|
@ -237,8 +304,27 @@ function askPosition(callback) {
|
|||
});
|
||||
}
|
||||
|
||||
function createWP(lat, lon, name) {
|
||||
let n = {};
|
||||
n["name"] = name;
|
||||
n["lat"] = lat;
|
||||
n["lon"] = lon;
|
||||
wp.push(n);
|
||||
print("add -- waypoints", wp);
|
||||
writeWP();
|
||||
}
|
||||
|
||||
function addCardName(name) {
|
||||
g.clear();
|
||||
askPosition(function(lat, lon) {
|
||||
print("position -- ", lat, lon);
|
||||
createWP(lat, lon, result);
|
||||
mainMenu();
|
||||
});
|
||||
}
|
||||
|
||||
function addCard() {
|
||||
showNumpad("wpXX", "wp", function() {
|
||||
require("textinput").input({text:"wp"}).then(key => {
|
||||
result = key;
|
||||
if (wp[result]!=undefined) {
|
||||
E.showMenu();
|
||||
|
@ -247,29 +333,17 @@ function addCard() {
|
|||
{type:"txt", font:Math.min(15,100/result.length)+"%", pad:1, fillx:1, filly:1, label:result},
|
||||
{type:"txt", font:"12%", pad:1, fillx:1, filly:1, label:"already exists."},
|
||||
{type:"h", c: [
|
||||
{type:"btn", font:"10%", pad:1, fillx:1, filly:1, label: "REPLACE", cb:l=>{encodeCard(result);}},
|
||||
{type:"btn", font:"10%", pad:1, fillx:1, filly:1, label: "REPLACE", cb:l=>{addCardName(result);}},
|
||||
{type:"btn", font:"10%", pad:1, fillx:1, filly:1, label: "CANCEL", cb:l=>{mainMenu();}}
|
||||
]}
|
||||
], lazy:true});
|
||||
g.clear();
|
||||
alreadyExists.render();
|
||||
}
|
||||
g.clear();
|
||||
askPosition(function(lat, lon) {
|
||||
print("position -- ", lat, lon);
|
||||
let n = {};
|
||||
n["name"] = result;
|
||||
n["lat"] = lat;
|
||||
n["lon"] = lon;
|
||||
wp.push(n);
|
||||
print("add -- waypoints", wp);
|
||||
writeWP();
|
||||
mainMenu();
|
||||
});
|
||||
}
|
||||
addCardName(result);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
g.reset();
|
||||
Bangle.setUI();
|
||||
mainMenu();
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
{ "id": "waypoint_editor",
|
||||
"name": "Waypoint editor",
|
||||
"version":"0.02",
|
||||
"version":"0.03",
|
||||
"description": "Allows editing waypoints on device",
|
||||
"icon": "app.png",
|
||||
"readme": "README.md",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"tags": "tool,outdoors,gps",
|
||||
"dependencies": {"textinput":"type"},
|
||||
"storage": [
|
||||
{"name":"waypoint_editor.app.js","url":"app.js"},
|
||||
{"name":"waypoint_editor.img","url":"app-icon.js","evaluate":true}
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
0.05: Don't show clock widget if already showing clock app
|
||||
0.06: Use 7 segment font, update *on* the minute, use less memory
|
||||
0.07: allow turning on/off when quick-switching apps
|
||||
0.08: Ensure we clear the whole rect so we don't end up leaving old text when time changes (fix #3073)
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "widclk",
|
||||
"name": "Digital clock widget",
|
||||
"version": "0.07",
|
||||
"version": "0.08",
|
||||
"description": "A simple digital clock widget that appears when not showing a fullscreen clock",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
|
|
|
@ -7,13 +7,13 @@ WIDGETS["wdclk"]={area:"tl",width:Bangle.CLOCK?0:52/* g.stringWidth("00:00") */,
|
|||
return setTimeout(Bangle.drawWidgets,1); // widget changed size - redraw
|
||||
}
|
||||
if (!this.width) return; // if not visible, return
|
||||
g.reset().setFontCustom(atob("AAAAAAAAAAIAAAQCAQAAAd0BgMBdwAAAAAAAdwAB0RiMRcAAAERiMRdwAcAQCAQdwAcERiMRBwAd0RiMRBwAAEAgEAdwAd0RiMRdwAcERiMRdwAFAAd0QiEQdwAdwRCIRBwAd0BgMBAAABwRCIRdwAd0RiMRAAAd0QiEQAAAAAAAAAA="), 32, atob("BgAAAAAAAAAAAAAAAAYCAAYGBgYGBgYGBgYCAAAAAAAABgYGBgYG"), 512+9);
|
||||
g.reset().setFontCustom(atob("AAAAAAAAAAIAAAQCAQAAAd0BgMBdwAAAAAAAdwAB0RiMRcAAAERiMRdwAcAQCAQdwAcERiMRBwAd0RiMRBwAAEAgEAdwAd0RiMRdwAcERiMRdwAFAAd0QiEQdwAdwRCIRBwAd0BgMBAAABwRCIRdwAd0RiMRAAAd0QiEQAAAAAAAAAA="), 32, atob("BgAAAAAAAAAAAAAAAAYCAAYGBgYGBgYGBgYCAAAAAAAABgYGBgYG"), 512+9).setFontAlign(0,0);
|
||||
var time = require("locale").time(new Date(),1);
|
||||
g.drawString(time, this.x, this.y+3, true); // 5 * 6*2 = 60
|
||||
g.clearRect(this.x, this.y, this.x+this.width-1, this.y+23).drawString(time, this.x+this.width/2, this.y+12); // 5 * 6*2 = 60
|
||||
// queue draw in one minute
|
||||
if (this.drawTimeout) clearTimeout(this.drawTimeout);
|
||||
this.drawTimeout = setTimeout(()=>{
|
||||
this.drawTimeout = undefined;
|
||||
this.draw();
|
||||
}, 60000 - (Date.now() % 60000));
|
||||
}};
|
||||
}};
|
|
@ -3,4 +3,4 @@
|
|||
0.03: based in widclk v0.05 compatible at same time, bottom area and color
|
||||
0.04: refactored to use less memory, and allow turning on/off when quick-switching apps
|
||||
0.05: Remove cyan color, use theme foreground instead
|
||||
|
||||
0.06: Ensure we clear the whole rect so we don't end up leaving old text when time changes
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "widclkbttm",
|
||||
"name": "Digital clock (Bottom) widget",
|
||||
"shortName": "Digital clock Bottom Widget",
|
||||
"version": "0.05",
|
||||
"version": "0.06",
|
||||
"description": "Displays time HH:mm in the bottom of the screen (may not be compatible with some apps)",
|
||||
"icon": "widclkbttm.png",
|
||||
"type": "widget",
|
||||
|
|
|
@ -4,7 +4,7 @@ WIDGETS["wdclkbttm"]={area:"br",width:Bangle.CLOCK?0:60,draw:function() {
|
|||
return setTimeout(Bangle.drawWidgets,1); // widget changed size - redraw
|
||||
}
|
||||
if (!this.width) return; // if not visible, return
|
||||
g.reset().setFont("6x8", 2).setFontAlign(-1, 0);
|
||||
g.reset().setFont("6x8", 2).setFontAlign(-1, 0).clearRect(this.x, this.y, this.x+this.width-1, this.y+23);
|
||||
var time = require("locale").time(new Date(),1);
|
||||
g.drawString(time, this.x, this.y+11, true); // 5 * 6*2 = 60
|
||||
// queue draw in one minute
|
||||
|
|
Loading…
Reference in New Issue