Merge remote-tracking branch 'upstream/master'

master
hughbarney 2021-06-24 20:38:08 +01:00
commit 48033a47b4
122 changed files with 1129 additions and 1061 deletions

157
apps.json
View File

@ -1,10 +1,10 @@
[
{ "id": "boot",
"name": "Bootloader",
"tags": "tool,system",
"tags": "tool,system,b2",
"type":"bootloader",
"icon": "bootloader.png",
"version":"0.26",
"version":"0.27",
"description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings",
"storage": [
{"name":".boot0","url":"boot0.js"},
@ -44,7 +44,7 @@
"icon": "app.png",
"version":"0.06",
"description": "This is needed by Bangle.js to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.",
"tags": "tool,system,launcher",
"tags": "tool,system,launcher,b2",
"type":"launch",
"storage": [
{"name":"launch.app.js","url":"app.js"}
@ -56,7 +56,7 @@
"icon": "app.png",
"version":"0.08",
"description": "Bangle.js About page - showing software version, stats, and a collaborative mural from the Bangle.js KickStarter backers",
"tags": "tool,system",
"tags": "tool,system,b2",
"allow_emulator":true,
"storage": [
{"name":"about.app.js","url":"app.js"},
@ -68,7 +68,7 @@
"icon": "locale.png",
"version":"0.09",
"description": "Translations for different countries",
"tags": "tool,system,locale,translate",
"tags": "tool,system,locale,translate,b2",
"type": "locale",
"custom":"locale.html",
"readme": "README.md",
@ -174,7 +174,7 @@
"icon": "settings.png",
"version":"0.26",
"description": "A menu for setting up Bangle.js",
"tags": "tool,system",
"tags": "tool,system,b2",
"readme": "README.md",
"storage": [
{"name":"setting.app.js","url":"settings.js"},
@ -191,7 +191,7 @@
"icon": "app.png",
"version":"0.11",
"description": "Set and respond to alarms",
"tags": "tool,alarm,widget",
"tags": "tool,alarm,widget,b2",
"storage": [
{"name":"alarm.app.js","url":"app.js"},
{"name":"alarm.boot.js","url":"boot.js"},
@ -206,9 +206,9 @@
{ "id": "wclock",
"name": "Word Clock",
"icon": "clock-word.png",
"version":"0.02",
"version":"0.03",
"description": "Display Time as Text",
"tags": "clock",
"tags": "clock,b2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -312,9 +312,9 @@
{ "id": "aclock",
"name": "Analog Clock",
"icon": "clock-analog.png",
"version": "0.14",
"version": "0.15",
"description": "An Analog Clock",
"tags": "clock",
"tags": "clock,b2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -325,9 +325,9 @@
{ "id": "clock2x3",
"name": "2x3 Pixel Clock",
"icon": "clock2x3.png",
"version":"0.04",
"version":"0.05",
"description": "This is a simple clock using minimalist 2x3 pixel numerical digits",
"tags": "clock",
"tags": "clock,b2",
"type": "clock",
"allow_emulator":true,
"storage": [
@ -338,9 +338,9 @@
{ "id": "geissclk",
"name": "Geiss Clock",
"icon": "clock.png",
"version":"0.02",
"version":"0.03",
"description": "7 segment clock with animated background in the style of Ryan Geiss' music visualisation. NOTE: The first run will take ~1 minute to do some precalculation",
"tags": "clock",
"tags": "clock,nob2",
"type":"clock",
"storage": [
{"name":"geissclk.app.js","url":"clock.js"},
@ -457,10 +457,11 @@
{ "id": "gpsrec",
"name": "GPS Recorder",
"icon": "app.png",
"version":"0.19",
"version":"0.21",
"interface": "interface.html",
"description": "Application that allows you to record a GPS track. Can run in background",
"tags": "tool,outdoors,gps,widget",
"readme": "README.md",
"storage": [
{"name":"gpsrec.app.js","url":"app.js"},
{"name":"gpsrec.img","url":"app-icon.js","evaluate":true},
@ -530,7 +531,7 @@
{ "id": "weather",
"name": "Weather",
"icon": "icon.png",
"version":"0.03",
"version":"0.05",
"description": "Show Gadgetbridge weather report",
"readme": "readme.md",
"tags": "widget,outdoors",
@ -575,9 +576,9 @@
{ "id": "widbat",
"name": "Battery Level Widget",
"icon": "widget.png",
"version":"0.06",
"version":"0.07",
"description": "Show the current battery level and charging status in the top right of the clock",
"tags": "widget,battery",
"tags": "widget,battery,b2",
"type":"widget",
"storage": [
{"name":"widbat.wid.js","url":"widget.js"}
@ -586,9 +587,9 @@
{ "id": "widlock",
"name": "Lock Widget",
"icon": "widget.png",
"version":"0.01",
"version":"0.03",
"description": "On devices with always-on display (Bangle.js 2) this displays lock icon whenever the display is locked",
"tags": "widget,lock",
"tags": "widget,lock,b2",
"type":"widget",
"storage": [
{"name":"widlock.wid.js","url":"widget.js"}
@ -631,9 +632,9 @@
{ "id": "widbt",
"name": "Bluetooth Widget",
"icon": "widget.png",
"version":"0.04",
"version":"0.05",
"description": "Show the current Bluetooth connection status in the top right of the clock",
"tags": "widget,bluetooth",
"tags": "widget,bluetooth,b2",
"type":"widget",
"storage": [
{"name":"widbt.wid.js","url":"widget.js"}
@ -851,9 +852,9 @@
{ "id": "sclock",
"name": "Simple Clock",
"icon": "clock-simple.png",
"version":"0.04",
"version":"0.05",
"description": "A Simple Digital Clock",
"tags": "clock",
"tags": "clock,b2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -864,9 +865,9 @@
{ "id": "s7clk",
"name": "Simple 7 segment Clock",
"icon": "icon.png",
"version":"0.02",
"version":"0.03",
"description": "A simple 7 segment Clock with date",
"tags": "clock",
"tags": "clock,b2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -877,7 +878,7 @@
{ "id": "vibrclock",
"name": "Vibrate Clock",
"icon": "app.png",
"version":"0.02",
"version":"0.03",
"description": "When BTN1 is pressed, vibrate out the time as a series of buzzes, one digit at a time. Hours, then Minutes. Zero is signified by one long buzz. Otherwise a simple digital clock.",
"tags": "clock",
"type":"clock",
@ -903,9 +904,9 @@
{ "id": "dclock",
"name": "Dev Clock",
"icon": "clock-dev.png",
"version":"0.09",
"version":"0.10",
"description": "A Digital Clock including timestamp (tst), beats(@), days in current month (dm) and days since new moon (l)",
"tags": "clock",
"tags": "clock,b2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -1029,7 +1030,7 @@
{ "id": "bclock",
"name": "Binary Clock",
"icon": "clock-binary.png",
"version":"0.02",
"version":"0.03",
"description": "A simple binary clock watch face",
"tags": "clock",
"type":"clock",
@ -1105,9 +1106,9 @@
"name": "Large Digit Blob Clock",
"shortName" : "Blob Clock",
"icon": "clock-blob.png",
"version":"0.05",
"version":"0.06",
"description": "A clock with big digits",
"tags": "clock",
"tags": "clock,b2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -1118,9 +1119,9 @@
{ "id": "boldclk",
"name": "Bold Clock",
"icon": "bold_clock.png",
"version":"0.03",
"version":"0.04",
"description": "Simple, readable and practical clock",
"tags": "clock",
"tags": "clock,b2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -1131,7 +1132,7 @@
{ "id": "widclk",
"name": "Digital clock widget",
"icon": "widget.png",
"version":"0.04",
"version":"0.05",
"description": "A simple digital clock widget",
"tags": "widget,clock",
"type":"widget",
@ -1142,9 +1143,9 @@
{ "id": "widpedom",
"name": "Pedometer widget",
"icon": "widget.png",
"version":"0.13",
"version":"0.14",
"description": "Daily pedometer widget",
"tags": "widget",
"tags": "widget,b2",
"type":"widget",
"storage": [
{"name":"widpedom.wid.js","url":"widget.js"},
@ -1154,7 +1155,7 @@
{ "id": "berlinc",
"name": "Berlin Clock",
"icon": "berlin-clock.png",
"version":"0.03",
"version":"0.04",
"description": "Berlin Clock (see https://en.wikipedia.org/wiki/Mengenlehreuhr)",
"tags": "clock",
"type":"clock",
@ -1167,9 +1168,9 @@
{ "id": "ctrclk",
"name": "Centerclock",
"icon": "app.png",
"version":"0.02",
"version":"0.03",
"description": "Watch-centered digital 24h clock with date in dd.mm.yyyy format.",
"tags": "clock",
"tags": "clock,nob2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -1207,9 +1208,9 @@
"id": "pipboy",
"name": "Pipboy",
"icon": "app.png",
"version": "0.03",
"version": "0.04",
"description": "Pipboy themed clock",
"tags": "clock",
"tags": "clock,nob2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -1288,9 +1289,9 @@
"name": "Commandline-Clock",
"shortName":"CLI-Clock",
"icon": "app.png",
"version":"0.12",
"version":"0.13",
"description": "Simple CLI-Styled Clock",
"tags": "clock,cli,command,bash,shell",
"tags": "clock,cli,command,bash,shell,b2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -1312,10 +1313,11 @@
{ "id": "barclock",
"name": "Bar Clock",
"icon": "clock-bar.png",
"version":"0.05",
"version":"0.07",
"description": "A simple digital clock showing seconds as a bar",
"tags": "clock",
"type":"clock",
"readme": "README.md",
"allow_emulator":true,
"storage": [
{"name":"barclock.app.js","url":"clock-bar.js"},
@ -1325,9 +1327,9 @@
{ "id": "dotclock",
"name": "Dot Clock",
"icon": "clock-dot.png",
"version":"0.02",
"version":"0.03",
"description": "A Minimal Dot Analog Clock",
"tags": "clock",
"tags": "clock,b2",
"type":"clock",
"allow_emulator":true,
"storage": [
@ -1462,9 +1464,9 @@
"name": "OpenStreetMap",
"shortName":"OpenStMap",
"icon": "app.png",
"version":"0.05",
"version":"0.08",
"description": "[BETA] Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are",
"tags": "outdoors,gps",
"tags": "outdoors,gps,b2",
"custom": "custom.html",
"storage": [
{"name":"openstmap","url":"openstmap.js"},
@ -1529,9 +1531,9 @@
"name": "Dev Stopwatch",
"shortName":"Dev Stopwatch",
"icon": "app.png",
"version":"0.02",
"version":"0.03",
"description": "Stopwatch with 5 laps supported (cyclically replaced)",
"tags": "stopwatch, chrono, timer, chronometer",
"tags": "stopwatch,chrono,timer,chronometer,b2",
"allow_emulator":true,
"storage": [
{"name":"devstopwatch.app.js","url":"app.js"},
@ -1570,7 +1572,7 @@
"name": "Numerals Clock",
"shortName": "Numerals Clock",
"icon": "numerals.png",
"version":"0.08",
"version":"0.09",
"description": "A simple big numerals clock",
"tags": "numerals,clock",
"type":"clock",
@ -1856,9 +1858,9 @@
{ "id": "calendar",
"name": "Calendar",
"icon": "calendar.png",
"version": "0.01",
"version": "0.02",
"description": "Simple calendar",
"tags": "calendar",
"tags": "calendar,b2",
"readme": "README.md",
"allow_emulator": true,
"storage": [
@ -1984,7 +1986,7 @@
"id": "beebclock",
"name": "Beeb Clock",
"icon": "beebclock.png",
"version":"0.03",
"version":"0.04",
"description": "Clock face that may be coincidentally familiar to BBC viewers",
"tags": "clock",
"type": "clock",
@ -2028,9 +2030,9 @@
"name": "Time Traveller's Chronometer",
"shortName": "Time Travel Clock",
"icon": "gallifr.png",
"version": "0.01",
"version": "0.02",
"description": "A clock for time travellers. The light pie segment shows the minutes, the black circle, the hour. The dial itself reads 'time' just in case you forget.",
"tags": "clock",
"tags": "clock,b2",
"readme": "README.md",
"type": "clock",
"allow_emulator":true,
@ -2112,7 +2114,7 @@
"name": "Binary Clock",
"shortName":"Binary Clock",
"icon": "app.png",
"version":"0.02",
"version":"0.03",
"description": "A binary clock with hours and minutes. BTN1 toggles a digital clock.",
"tags": "clock,binary",
"type": "clock",
@ -2139,9 +2141,9 @@
"name": "Animated Clock",
"shortName":"Anim Clock",
"icon": "app.png",
"version":"0.02",
"version":"0.03",
"description": "An animated clock face using Mark Ferrari's amazing 8 bit game art and palette cycling: http://www.markferrari.com/art/8bit-game-art",
"tags": "clock,animated",
"tags": "clock,animated,nob2",
"type": "clock",
"storage": [
{"name":"animclk.app.js","url":"app.js"},
@ -2155,9 +2157,9 @@
"name": "Analog Clock (Image background)",
"shortName":"Analog Clock",
"icon": "app.png",
"version":"0.02",
"version":"0.03",
"description": "An analog clock with an image background",
"tags": "clock",
"tags": "clock,nob2",
"type": "clock",
"storage": [
{"name":"analogimgclk.app.js","url":"app.js"},
@ -2475,7 +2477,7 @@
"name": "World Clock - 4 time zones",
"shortName":"World Clock",
"icon": "app.png",
"version":"0.03",
"version":"0.04",
"description": "Current time zone plus up to four others",
"tags": "clock",
"type" : "clock",
@ -2493,9 +2495,9 @@
"name": "Digital Clock Face",
"shortName":"Digi Clock",
"icon": "digiclock.png",
"version":"0.01",
"version":"0.02",
"description": "A simple digital clock with the time, day, month, and year",
"tags": "clock",
"tags": "clock,nob2",
"type" : "clock",
"storage": [
{"name":"digiclock.app.js","url":"digiclock.js"},
@ -2753,7 +2755,7 @@
{ "id": "astral",
"name": "Astral Clock",
"icon": "app-icon.png",
"version":"0.02",
"version":"0.03",
"readme": "README.md",
"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.",
"tags": "clock",
@ -2812,7 +2814,7 @@
"name": "De-Stress",
"shortName":"De-Stress",
"icon": "app.png",
"version":"0.01",
"version":"0.02",
"description": "Simple haptic heartbeat",
"storage": [
{"name":"de-stress.app.js","url":"app.js"},
@ -3049,7 +3051,7 @@
"version":"0.01",
"description": "Displays RGB565 and RGB888 colors, its name and code in screen.",
"readme": "README.md",
"tags": "Color, input,buttons,touch,UI",
"tags": "Color,input,buttons,touch,UI,nob2",
"storage": [
{"name":"color_catalog.app.js","url":"app.js"},
{"name":"color_catalog.img","url":"app-icon.js","evaluate":true}
@ -3212,7 +3214,6 @@
"readme": "README.md",
"description": "An Omnitrix Showpiece",
"tags": "game",
"readme": "README.md",
"storage": [
{"name":"omnitrix.app.js","url":"omnitrix.app.js"},
{"name":"omnitrix.img","url":"omnitrix.icon.js","evaluate":true}
@ -3222,7 +3223,7 @@
"name": "Bat Clock",
"shortName":"Bat Clock",
"icon": "bat-clock.png",
"version":"0.01",
"version":"0.02",
"description": "Morphing Clock, with an awesome \"The Dark Knight\" themed logo.",
"tags": "clock",
"type": "clock",
@ -3262,10 +3263,22 @@
{"name":"gbtwist.img","url":"app-icon.js","evaluate":true}
]
},
{ "id": "thermom",
"name": "Thermometer",
"icon": "app.png",
"version":"0.02",
"description": "Displays the current temperature, updated every 20 seconds",
"tags": "tool",
"allow_emulator":true,
"storage": [
{"name":"thermom.app.js","url":"app.js"},
{"name":"thermom.img","url":"app-icon.js","evaluate":true}
]
},
{ "id": "mysticdock",
"name": "Mystic Dock",
"icon": "mystic-dock.png",
"version":"1.0",
"version":"1.00",
"description": "A retro-inspired dockface that displays the current time and battery charge while plugged in, and which features an interactive mode that shows the time, date, and a rotating data display line.",
"tags": "dock",
"type":"dock",

View File

@ -9,3 +9,4 @@
0.12: Fix regression after 0.11
0.13: Fix broken date padding (fix #376)
0.14: Remove hardcoded hour buzz (you can install widchime if you miss it)
0.15: Add color scheme support

View File

@ -2,13 +2,16 @@
const locale = require('locale');
const p = Math.PI / 2;
const pRad = Math.PI / 180;
const faceWidth = 100; // watch face radius (240/2 - 24px for widget area)
const faceWidth = g.getWidth()/2 - 20; // watch face radius (240/2 - 24px for widget area)
const widgetHeight=24+1;
let timer = null;
let currentDate = new Date();
const centerX = g.getWidth() / 2;
const centerY = (g.getWidth() / 2) + widgetHeight/2;
g.theme.dark=false;
let colSecA = g.theme.dark ? "#00A" : "#58F"; // before the second
let colSecB = g.theme.dark ? "#58F" : "#00A"; // after the second
let colSec1 = g.theme.dark ? "#F83" : "#000"; // ON the second
const seconds = (angle) => {
const a = angle * pRad;
@ -46,40 +49,35 @@ const drawAll = () => {
// draw all secs
for (let i = 0; i < 60; i++) {
if (i > currentSec) {
g.setColor(0, 0, 0.6);
} else {
g.setColor(0.3, 0.3, 1);
}
g.setColor((i > currentSec) ? colSecA : colSecB);
seconds((360 * i) / 60);
}
onSecond();
};
const resetSeconds = () => {
g.setColor(0, 0, 0.6);
g.setColor(colSecA);
for (let i = 0; i < 60; i++) {
seconds((360 * i) / 60);
}
};
const onSecond = () => {
g.setColor(0.3, 0.3, 1);
g.setColor(colSecB);
seconds((360 * currentDate.getSeconds()) / 60);
if (currentDate.getSeconds() === 59) {
resetSeconds();
onMinute();
}
g.setColor(1, 0.7, 0.2);
g.setColor(colSec1);
currentDate = new Date();
seconds((360 * currentDate.getSeconds()) / 60);
g.setColor(1, 1, 1);
g.setColor(g.theme.fg);
};
const drawDate = () => {
g.reset();
g.setColor(1, 0, 0);
g.setColor("#f00");
g.setFont('6x8', 2);
const dayString = locale.dow(currentDate, true);
@ -89,7 +87,7 @@ const drawDate = () => {
// console.log(`${dayString}|${dateString}`);
// center date
const l = (g.getWidth() - g.stringWidth(dateDisplay)) / 2;
const t = centerY + 37;
const t = centerY + faceWidth*0.37;
g.drawString(dateDisplay, l, t, true);
// console.log(l, t);
};
@ -99,7 +97,7 @@ const onMinute = () => {
resetSeconds();
}
// clear existing hands
g.setColor(0, 0, 0);
g.setColor(g.theme.bg);
// Hour
hand((360 * (currentDate.getHours() + currentDate.getMinutes() / 60)) / 12, -8, faceWidth - 35);
// Minute
@ -107,10 +105,10 @@ const onMinute = () => {
// get new date, then draw new hands
currentDate = new Date();
g.setColor(1, 0.9, 0.9);
g.setColor(g.theme.fg);
// Hour
hand((360 * (currentDate.getHours() + currentDate.getMinutes() / 60)) / 12, -8, faceWidth - 35);
g.setColor(1, 1, 0.9);
g.setColor(g.theme.fg);
// Minute
hand((360 * currentDate.getMinutes()) / 60, -8, faceWidth - 10);
drawDate();
@ -137,8 +135,9 @@ g.clear();
resetSeconds();
startTimers();
drawAll();
// Show launcher when button pressed
Bangle.setUI("clock");
Bangle.loadWidgets();
Bangle.drawWidgets();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });

View File

@ -1,2 +1,3 @@
0.01: New App!
0.02: Add BTN2 -> launcher
0.03: Update to use setUI

View File

@ -114,5 +114,5 @@ if (g.drawImages) {
E.showMessage("Please update\nBangle.js firmware\nto use this clock","analogimgclk");
}
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
// Show launcher when button pressed
Bangle.setUI("clock");

View File

@ -1,2 +1,3 @@
0.01: New App!
0.02: Fix bug if image clock wasn't installed
0.03: Update to use setUI

View File

@ -102,5 +102,5 @@ if (g.drawImages) {
} else {
E.showMessage("Please update\nBangle.js firmware\nto use this clock","animclk");
}
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
// Show launcher when button pressed
Bangle.setUI("clock");

View File

@ -1,2 +1,3 @@
0.01: Create astral clock app
0.02: Fixed Whirlpool galaxy RA/DA, larger compass display, fixed moonphase overlapping battery widget
0.03: Update to use Bangle.setUI instead of setWatch

View File

@ -503,8 +503,8 @@ function coord_to_horizon(utc, ra, dec, lat, lon, h) {
}
//
// "mean_sidereal_time" returns the Mean Sidereal Time in units of degrees.
// Use lon = 0 to get the Greenwich MST.
// "mean_sidereal_time" returns the Mean Sidereal Time in units of degrees.
// Use lon = 0 to get the Greenwich MST.
// East longitudes are positive; West longitudes are negative
//
// returns: time in degrees
@ -523,7 +523,7 @@ function mean_sidereal_time(lon) {
var c = Math.floor(365.25 * year);
var da = Math.floor(30.6001 * (month + 1));
// days since J2000.0
// days since J2000.0
var jd = b + c + da - 730550.5 + day
+ (hour + mins / 60.0 + secs / 3600.0) / 24.0;
@ -796,10 +796,11 @@ Bangle.on('lcdPower', on => {
Bangle.setCompassPower(1);
Bangle.setGPSPower(1);
// Buttons
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
// Show launcher when button pressed
Bangle.setClockMode();
setWatch(function () {
Bangle.setUI("clockupdown", btn => {
if (btn==0) {
if (!processing) {
if (!modeswitch) {
modeswitch = true;
@ -809,12 +810,11 @@ setWatch(function () {
else
modeswitch = false;
}
}, BTN3, { repeat: true });
setWatch(function () {
} else {
if (!processing)
ready_to_compute = true;
}, BTN1, { repeat: true });
}
});
setWatch(function () {
if (!astral_settings.astral_default) {

0
apps/banglerun/ChangeLog Executable file → Normal file
View File

View File

@ -2,4 +2,6 @@
0.02: Apply locale, 12-hour setting
0.03: Fix dates drawing over each other at midnight
0.04: Small bugfix
0.05: Clock does not start if app Languages is not installed
0.05: Clock does not start if app Languages is not installed
0.06: Improve accuracy
0.07: Update to use Bangle.setUI instead of setWatch

6
apps/barclock/README.md Normal file
View File

@ -0,0 +1,6 @@
# Bar Clock
A simple digital clock showing seconds as a horizontal bar.
| 24hr style | 12hr style |
| --- | --- |
| ![24-hour bar clock](screenshot.png) | ![12-hour bar clock with meridian](screenshot_pm.png) |

View File

@ -2,170 +2,168 @@
/**
* A simple digital clock showing seconds as a bar
**/
{
// Check settings for what type our clock should be
const is12Hour = (require('Storage').readJSON('setting.json', 1) || {})['12hour']
let locale = require('locale')
{ // add some more info to locale
let date = new Date()
date.setFullYear(1111)
date.setMonth(1, 3) // februari: months are zero-indexed
const localized = locale.date(date, true)
locale.dayFirst = /3.*2/.test(localized)
locale.hasMeridian = false
if(typeof locale.meridian === 'function') { // function does not exists if languages app is not installed
locale.hasMeridian = (locale.meridian(date) !== '')
}
}
const screen = {
width: g.getWidth(),
height: g.getWidth(),
middle: g.getWidth() / 2,
center: g.getHeight() / 2,
// Check settings for what type our clock should be
const is12Hour = (require('Storage').readJSON('setting.json', 1) || {})['12hour']
let locale = require('locale')
{ // add some more info to locale
let date = new Date()
date.setFullYear(1111)
date.setMonth(1, 3) // februari: months are zero-indexed
const localized = locale.date(date, true)
locale.dayFirst = /3.*2/.test(localized)
locale.hasMeridian = false
if(typeof locale.meridian === 'function') { // function does not exists if languages app is not installed
locale.hasMeridian = (locale.meridian(date) !== '')
}
// hardcoded "settings"
const settings = {
time: {
}
const screen = {
width: g.getWidth(),
height: g.getWidth(),
middle: g.getWidth() / 2,
center: g.getHeight() / 2,
}
// hardcoded "settings"
const settings = {
time: {
color: -1,
font: '6x8',
size: (is12Hour && locale.hasMeridian) ? 6 : 8,
middle: screen.middle,
center: screen.center,
ampm: {
color: -1,
font: '6x8',
size: (is12Hour && locale.hasMeridian) ? 6 : 8,
middle: screen.middle,
center: screen.center,
ampm: {
color: -1,
font: '6x8',
size: 2,
},
size: 2,
},
date: {
color: -1,
font: 'Vector',
size: 20,
middle: screen.height - 20, // at bottom of screen
center: screen.center,
},
bar: {
color: -1,
top: 155, // just below time
thickness: 6, // matches 24h time "pixel" size
},
}
const SECONDS_PER_MINUTE = 60
const timeText = function (date) {
if (!is12Hour) {
return locale.time(date, true)
}
const date12 = new Date(date.getTime())
const hours = date12.getHours()
if (hours === 0) {
date12.setHours(12)
} else if (hours > 12) {
date12.setHours(hours - 12)
}
return locale.time(date12, true)
}
const ampmText = function (date) {
return is12Hour ? locale.meridian(date) : ''
}
const dateText = function (date) {
const dayName = locale.dow(date, true),
month = locale.month(date, true),
day = date.getDate()
const dayMonth = locale.dayFirst ? `${day} ${month}` : `${month} ${day}`
return `${dayName} ${dayMonth}`
}
const drawDateTime = function (date) {
const t = settings.time
g.setColor(t.color)
g.setFont(t.font, t.size)
g.setFontAlign(0, 0) // centered
g.drawString(timeText(date), t.center, t.middle, true)
if (is12Hour && locale.hasMeridian) {
const a = settings.time.ampm
g.setColor(a.color)
g.setFont(a.font, a.size)
g.setFontAlign(1, -1) // right top
// at right edge of screen, aligned with time bottom
const left = screen.width - a.size * 2,
top = t.middle + t.size - a.size
g.drawString(ampmText(date), left, top, true)
}
const d = settings.date
g.setColor(d.color)
g.setFont(d.font, d.size)
g.setFontAlign(0, 0) // centered
g.drawString(dateText(date), d.center, d.middle, true)
}
const drawBar = function (date) {
const b = settings.bar
const seconds = date.getSeconds()
if (seconds === 0) {
// zero-size rect stills draws one line of pixels, we don't want that
return
}
const fraction = seconds / SECONDS_PER_MINUTE,
width = fraction * screen.width
g.setColor(b.color)
g.fillRect(0, b.top, width, b.top + b.thickness)
}
const clearScreen = function () {
g.setColor(0)
const timeTop = settings.time.middle - (settings.time.size * 4)
g.fillRect(0, timeTop, screen.width, screen.height)
}
let lastSeconds
const tick = function () {
g.reset()
const date = new Date()
const seconds = date.getSeconds()
if (lastSeconds > seconds) {
// new minute
clearScreen()
drawDateTime(date)
}
// the bar only gets larger, so drawing on top of the previous one is fine
drawBar(date)
lastSeconds = seconds
}
let iTick
const start = function () {
lastSeconds = 99 // force redraw
tick()
iTick = setInterval(tick, 1000)
}
const stop = function () {
if (iTick) {
clearInterval(iTick)
iTick = undefined
}
}
// clean app screen
g.clear()
Bangle.loadWidgets()
Bangle.drawWidgets()
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {repeat: false, edge: 'falling'})
Bangle.on('lcdPower', function (on) {
if (on) {
start()
} else {
stop()
}
})
start()
},
date: {
color: -1,
font: 'Vector',
size: 20,
middle: screen.height - 20, // at bottom of screen
center: screen.center,
},
bar: {
color: -1,
top: 155, // just below time
thickness: 6, // matches 24h time "pixel" size
},
}
const SECONDS_PER_MINUTE = 60
const timeText = function (date) {
if (!is12Hour) {
return locale.time(date, true)
}
const date12 = new Date(date.getTime())
const hours = date12.getHours()
if (hours === 0) {
date12.setHours(12)
} else if (hours > 12) {
date12.setHours(hours - 12)
}
return locale.time(date12, true)
}
const ampmText = function (date) {
return is12Hour ? locale.meridian(date) : ''
}
const dateText = function (date) {
const dayName = locale.dow(date, true),
month = locale.month(date, true),
day = date.getDate()
const dayMonth = locale.dayFirst ? `${day} ${month}` : `${month} ${day}`
return `${dayName} ${dayMonth}`
}
const drawDateTime = function (date) {
const t = settings.time
g.setColor(t.color)
g.setFont(t.font, t.size)
g.setFontAlign(0, 0) // centered
g.drawString(timeText(date), t.center, t.middle, true)
if (is12Hour && locale.hasMeridian) {
const a = settings.time.ampm
g.setColor(a.color)
g.setFont(a.font, a.size)
g.setFontAlign(1, -1) // right top
// at right edge of screen, aligned with time bottom
const left = screen.width - a.size * 2,
top = t.middle + t.size - a.size
g.drawString(ampmText(date), left, top, true)
}
const d = settings.date
g.setColor(d.color)
g.setFont(d.font, d.size)
g.setFontAlign(0, 0) // centered
g.drawString(dateText(date), d.center, d.middle, true)
}
const drawBar = function (date) {
const b = settings.bar
const seconds = date.getSeconds()
if (seconds === 0) {
// zero-size rect stills draws one line of pixels, we don't want that
return
}
const fraction = seconds / SECONDS_PER_MINUTE,
width = fraction * screen.width
g.setColor(b.color)
g.fillRect(0, b.top, width, b.top + b.thickness)
}
const clearScreen = function () {
g.setColor(0)
const timeTop = settings.time.middle - (settings.time.size * 4)
g.fillRect(0, timeTop, screen.width, screen.height)
}
let lastSeconds, tTick
const tick = function () {
g.reset()
const date = new Date()
const seconds = date.getSeconds()
if (lastSeconds > seconds) {
// new minute
clearScreen()
drawDateTime(date)
}
// the bar only gets larger, so drawing on top of the previous one is fine
drawBar(date)
lastSeconds = seconds
// schedule next update
const millis = date.getMilliseconds()
tTick = setTimeout(tick, 1000-millis)
}
const start = function () {
lastSeconds = 99 // force redraw
tick()
}
const stop = function () {
if (tTick) {
clearTimeout(tTick)
tTick = undefined
}
}
// clean app screen
g.clear()
Bangle.loadWidgets()
Bangle.drawWidgets()
// Show launcher when button pressed
Bangle.setUI("clock");
Bangle.on('lcdPower', function (on) {
if (on) {
start()
} else {
stop()
}
})
start()

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1 +1,2 @@
0.01: App Created!
0.02: Update to use Bangle.setUI instead of setWatch

View File

@ -256,8 +256,5 @@ Bangle.drawWidgets();
timeInterval = setInterval(showTime, 1000);
showTime();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {
repeat: false,
edge: "falling"
});
// Show launcher when button pressed
Bangle.setUI("clock");

View File

@ -1 +1,2 @@
0.02: Modified for use with new bootloader and firmware
0.03: Update to use Bangle.setUI instead of setWatch

View File

@ -105,5 +105,5 @@ Bangle.loadWidgets();
Bangle.drawWidgets();
setInterval(() => { drawClock(); }, 1000);
drawClock();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
// Show launcher when button pressed
Bangle.setUI("clock");

View File

@ -1,3 +1,4 @@
0.01: Initial commit. Not very efficient, and widgets not working for some reason.
0.02: Fixes; widget support
0.03: Remove hardcoded hour buzz (you can install widchime if you miss it)
0.04: Update to use Bangle.setUI instead of setWatch

View File

@ -51,341 +51,332 @@ Graphics.prototype.drawRotLine = function (sina, cosa, cx, cy, r1, r2) {
);
};
// Display modes
//
// 0: full-screen
// 1: with widgets
// 2: centred on Bangle (v.1), no widgets or time/date
// 3: centred with time above
// 4: centred with date above
// 5: centred with time and date above
let mode;
(function(g) {
// Display modes
//
// 0: full-screen
// 1: with widgets
// 2: centred on Bangle (v.1), no widgets or time/date
// 3: centred with time above
// 4: centred with date above
// 5: centred with time and date above
let mode;
// R1, R2: Outer and inner radii of hour marks
// RC1, RC2: Outer and inner radii of hub
// CX, CY: Centre location, relative to buffer (not screen, necessarily)
// HW2, MW2: Half-width of hour and minute hand
// HR, MR: Length of hour and minute hand, relative to CX,CY
// M: Half-width of gap in hour marks
// HSCALE: Half-width of hour mark as function(0<h<13)
let R1, R2, RC1, RC2, CX, CY, HW2, MW2, HR, MR, M, HSCALE;
// R1, R2: Outer and inner radii of hour marks
// RC1, RC2: Outer and inner radii of hub
// CX, CY: Centre location, relative to buffer (not screen, necessarily)
// HW2, MW2: Half-width of hour and minute hand
// HR, MR: Length of hour and minute hand, relative to CX,CY
// M: Half-width of gap in hour marks
// HSCALE: Half-width of hour mark as function(0<h<13)
let R1, R2, RC1, RC2, CX, CY, HW2, MW2, HR, MR, M, HSCALE;
// Screen size
const GW = g.getWidth();
const GH = g.getHeight();
// Screen size
const GW = g.getWidth();
const GH = g.getHeight();
// Top margin: the gap taken from the top of the buffer, except when
// in mode 0 (full screen)
let TM;
// Top margin: the gap taken from the top of the buffer, except when
// in mode 0 (full screen)
let TM;
// Buffer image. undefined means it needs regenerating
let faceImg;
// Buffer image. undefined means it needs regenerating
let faceImg;
// with_seconds flag determines whether the face is updated every
// second or every minute, and to draw the hand or not.
let with_seconds = true;
// with_seconds flag determines whether the face is updated every
// second or every minute, and to draw the hand or not.
let with_seconds = true;
// Display flags, determined from `mode` by setMode()
let with_widgets = false;
let with_digital_time = true;
let with_digital_date = true;
// Display flags, determined from `mode` by setMode()
let with_widgets = false;
let with_digital_time = true;
let with_digital_date = true;
// Create offscreen buffer for the once-per-minute face draw
const G1 = Graphics.createArrayBuffer(g.getWidth(), g.getHeight(), 1, {msb:true});
// Create offscreen buffer for the once-per-minute face draw
const G1 = Graphics.createArrayBuffer(g.getWidth(), g.getHeight(), 1, {msb:true});
// Precalculate sin/cos for the hour marks. Might be premature
// optimisation, but might as well.
let ss = [], cs = [];
for (let h=1; h<=12; h++) {
const a = Math.PI * h / 6;
ss[h] = Math.sin(a);
cs[h] = Math.cos(a);
}
// Precalculate sin/cos for the hour marks. Might be premature
// optimisation, but might as well.
let ss = [], cs = [];
// Draw the face with hour and minute hand. Ideally, we'd separate
// the face from the hands and double-buffer, but memory is limited,
// so we buffer once and minute, and draw the second hand dynamically
// (with a bit of flicker)
const drawFace = (G) => {
const fw = R1 * 2;
const fh = R1 * 2;
const fw2 = R1;
const fh2 = R1;
let hs = [];
// Wipe the image and start with white
G.clear();
G.setColor(1,1,1);
// Draw the hour marks.
for (let h=1; h<=12; h++) {
const a = Math.PI * h / 6;
ss[h] = Math.sin(a);
cs[h] = Math.cos(a);
hs[h] = HSCALE(h);
G.fillRotRect(ss[h], cs[h], CX, CY, -hs[h], hs[h], R2, R1);
}
// Draw the face with hour and minute hand. Ideally, we'd separate
// the face from the hands and double-buffer, but memory is limited,
// so we buffer once and minute, and draw the second hand dynamically
// (with a bit of flicker)
const drawFace = (G) => {
const fw = R1 * 2;
const fh = R1 * 2;
const fw2 = R1;
const fh2 = R1;
let hs = [];
// Draw the hub
G.fillCircle(CX, CY, RC1);
// Wipe the image and start with white
G.clear();
G.setColor(1,1,1);
// Black
G.setColor(0,0,0);
// Draw the hour marks.
for (let h=1; h<=12; h++) {
hs[h] = HSCALE(h);
G.fillRotRect(ss[h], cs[h], CX, CY, -hs[h], hs[h], R2, R1);
// Clear the centre of the hub
G.fillCircle(CX, CY, RC2);
// Draw the gap in the hour marks
for (let h=1; h<=12; h++) {
G.fillRotRect(ss[h], cs[h], CX, CY, -M, M, R2-1, R1+1);
}
// Back to white for future draw operations
G.setColor(1,1,1);
// While the buffer remains full-screen, we may trim out the
// bottom of the image so we can shift the whole thing down for
// widgets.
const img = {width:GW,height:GH-TM,buffer:G.buffer};
return img;
};
let hours, minutes, seconds, date;
// Schedule event for calling at the start of the next second
const inOneSecond = (cb) => {
let now = new Date();
clearTimeout();
setTimeout(cb, 1000 - now.getMilliseconds());
};
// Schedule event for calling at the start of the next minute
const inOneMinute = (cb) => {
let now = new Date();
clearTimeout();
setTimeout(cb, 60000 - (now.getSeconds() * 1000 + now.getMilliseconds()));
};
// Draw a fat hour/minute hand
const drawHand = (G, a, w2, r1, r2) =>
G.fillRotRect(Math.sin(a), Math.cos(a), CX, CY, -w2, w2, r1, r2);
// Redraw function
const drawAll = (force) => {
let now = new Date();
if (!faceImg) force = true;
let face_changed = force;
let date_changed = false;
tmp = hours;
hours = now.getHours();
if (tmp !== hours)
face_changed = true;
tmp = minutes;
minutes = now.getMinutes();
if (tmp !== minutes)
face_changed = true;
// If the face has been updated and/or needs a redraw,
// face_changed is true.
let time_changed = face_changed;
// If the screen needs an update, regardless of whether the face
// needs a redraw, time_changed is true.
if (with_seconds) {
// If we're going by second, we always need an update.
seconds = now.getSeconds();
time_changed = true;
}
if (with_digital_date) {
// See if the date has changed. If it has, then we need a
// full-blown redraw of the screen and the face, plus text.
tmp = date;
date = now.getDate();
if (tmp !== date) {
date_changed = true;
face_changed = true; // Should have changed anyway with hour/minute rollover
}
}
if (face_changed) {
// Redraw the face and hands onto the buffer G1.
faceImg = drawFace(G1);
drawHand(G1, Math.PI*hours/6, HW2, RC1, HR);
drawHand(G1, Math.PI*minutes/30, MW2, RC1, MR);
}
// Has the time updated? If so, we'll need to draw something.
if (time_changed) {
// Are we adding text?
if (with_digital_date || with_digital_time) {
// Construct the date/time text to add above the face
let d = now.toString();
let da = d.toString().split(" ");
let txt;
if (with_digital_time) {
txt = da[4].substr(0, 5);
if (with_digital_date)
G1.drawStringDH(txt+',', 24, 0, 'L', GW);
else
G1.drawStringDH(txt, 0, 0, 'C', GW);
}
if (with_digital_date) {
let txt = [da[0], da[1], da[2]].join(" ");
if (with_digital_time)
G1.drawStringDH(txt, -24, 0, 'R', GW);
else
G1.drawStringDH(txt, 0, 0, 'C', GW);
}
}
// Draw the hub
G.fillCircle(CX, CY, RC1);
// Black
G.setColor(0,0,0);
// Clear the centre of the hub
G.fillCircle(CX, CY, RC2);
// Draw the gap in the hour marks
for (let h=1; h<=12; h++) {
G.fillRotRect(ss[h], cs[h], CX, CY, -M, M, R2-1, R1+1);
}
// Back to white for future draw operations
G.setColor(1,1,1);
// While the buffer remains full-screen, we may trim out the
// bottom of the image so we can shift the whole thing down for
// widgets.
const img = {width:GW,height:GH-TM,buffer:G.buffer};
return img;
};
let hours, minutes, seconds, date;
// Schedule event for calling at the start of the next second
const inOneSecond = (cb) => {
let now = new Date();
clearTimeout();
setTimeout(cb, 1000 - now.getMilliseconds());
};
// Schedule event for calling at the start of the next minute
const inOneMinute = (cb) => {
let now = new Date();
clearTimeout();
setTimeout(cb, 60000 - (now.getSeconds() * 1000 + now.getMilliseconds()));
};
// Draw a fat hour/minute hand
const drawHand = (G, a, w2, r1, r2) =>
G.fillRotRect(Math.sin(a), Math.cos(a), CX, CY, -w2, w2, r1, r2);
// Redraw function
const drawAll = (force) => {
let now = new Date();
if (!faceImg) force = true;
let face_changed = force;
let date_changed = false;
tmp = hours;
hours = now.getHours();
if (tmp !== hours)
face_changed = true;
tmp = minutes;
minutes = now.getMinutes();
if (tmp !== minutes)
face_changed = true;
// If the face has been updated and/or needs a redraw,
// face_changed is true.
let time_changed = face_changed;
// If the screen needs an update, regardless of whether the face
// needs a redraw, time_changed is true.
// If the time has updated, we need to _at least_ draw the
// image to the screen.
g.setColor(1,1,1);
g.drawImage({width:GW,
height:GH-TM,
buffer:G1.buffer}, 0, TM);
// and possibly add the second hand
if (with_seconds) {
// If we're going by second, we always need an update.
seconds = now.getSeconds();
time_changed = true;
let a = 2.0 * Math.PI * seconds / 60.0;
g.drawRotLine(Math.sin(a), Math.cos(a), CX, CY+TM, RC1, R1);
}
if (with_digital_date) {
// See if the date has changed. If it has, then we need a
// full-blown redraw of the screen and the face, plus text.
tmp = date;
date = now.getDate();
if (tmp !== date) {
date_changed = true;
face_changed = true; // Should have changed anyway with hour/minute rollover
}
}
// And draw widgets if we're in that mode
if (with_widgets)
Bangle.drawWidgets();
}
if (face_changed) {
// Redraw the face and hands onto the buffer G1.
faceImg = drawFace(G1);
drawHand(G1, Math.PI*hours/6, HW2, RC1, HR);
drawHand(G1, Math.PI*minutes/30, MW2, RC1, MR);
}
// Schedule to repeat this. A `setTimeout(1000)` isn't good
// enough, as all the above might've taken some milliseconds and
// we don't want to drift.
if (with_seconds)
inOneSecond(drawAll);
else
inOneMinute(drawAll);
};
// Has the time updated? If so, we'll need to draw something.
if (time_changed) {
const setButtons = () => {
// Show launcher when button pressed
Bangle.setUI("clockupdown", btn=> {
if (btn==0) changeSeconds();
if (btn==1) { ++mode; setMode(); drawAll(true); }
});
};
// Are we adding text?
if (with_digital_date || with_digital_time) {
// Load display parameters based on `mode`
const setMode = () => {
// Normalize mode to 0 <= mode <= 5
mode = (6+mode) % 6;
// Construct the date/time text to add above the face
let d = now.toString();
let da = d.toString().split(" ");
let txt;
// [R1, R2, RC1, RC2, HW2, MW3, HR, MR, M, HSCALE] =
const scales = [
[120, 84, 17, 12.4, 4.6, 2.2, 8, 2, 1, h => (3.0 + Math.ceil(h/1.5)) ],
[102, 70, 14.6, 10.7, 3.88, 1.8, 8, 2, 1, h => (2.4 + Math.ceil(h/1.6)) ],
];
if (with_digital_time) {
txt = da[4].substr(0, 5);
if (with_digital_date)
G1.drawStringDH(txt+',', 24, 0, 'L', GW);
else
G1.drawStringDH(txt, 0, 0, 'C', GW);
}
if (mode < 3) {
// Face without time/date text. Might have widgets though.
with_digital_time = with_digital_date = false;
with_widgets = (mode == 1);
}
else {
// Face with time/date text, but no widgets
with_digital_time = (mode-2)&1;
with_digital_date = (mode-2)&2;
with_widgets = false;
}
if (with_digital_date) {
let txt = [da[0], da[1], da[2]].join(" ");
if (with_digital_time)
G1.drawStringDH(txt, -24, 0, 'R', GW);
else
G1.drawStringDH(txt, 0, 0, 'C', GW);
}
}
// Destructure the array to the global display parameters
let arr = scales[mode > 0 ? 1 : 0];
R1 = arr[0];
R2 = arr[1];
RC1 = arr[2];
RC2 = arr[3];
HW2 = arr[4];
MW2 = arr[5];
HR = R2 - arr[6];
MR = R1 - arr[7];
M = arr[8];
HSCALE = arr[9];
TM = with_widgets ? 36 : 0;
// If the time has updated, we need to _at least_ draw the
// image to the screen.
g.setColor(1,1,1);
g.drawImage({width:GW,
height:GH-TM,
buffer:G1.buffer}, 0, TM);
CX = GW/2;
CY = R1;
// and possibly add the second hand
if (with_seconds) {
let a = 2.0 * Math.PI * seconds / 60.0;
g.drawRotLine(Math.sin(a), Math.cos(a), CX, CY+TM, RC1, R1);
}
// If we're in the small-face + text regime, we're going to buffer
// the full screen but draw the clock face further down to give
// space for the text.
//
// Compare with modes 0 (full-screen) and 1 (with_widgets==true)
// where the face is drawn at the top of the buffer, but drawn
// lower down the screen (so CY doesn't move)
if (mode > 1) {
CY += 36;
}
// And draw widgets if we're in that mode
if (with_widgets)
Bangle.drawWidgets();
}
// We only don't bother redrawing the face from modes 2 to 5, as
// they're the same.
if (!faceImg || mode<3) {
faceImg = undefined;
}
// Schedule to repeat this. A `setTimeout(1000)` isn't good
// enough, as all the above might've taken some milliseconds and
// we don't want to drift.
if (with_seconds)
inOneSecond(drawAll);
else
inOneMinute(drawAll);
};
const setButtons = () => {
const opts = { repeat: true, edge:'rising', debounce:30};
// BTN1: enable/disable second hand
setWatch(changeSeconds, BTN1, opts);
// BTN2: return to launcher
setWatch(Bangle.showLauncher, BTN2, { repeat:false, edge:'falling' });
// BTN3: change display mode
setWatch(function () { ++mode; setMode(); drawAll(true); }, BTN3, opts);
};
// Load display parameters based on `mode`
const setMode = () => {
// Normalize mode to 0 <= mode <= 5
mode = (6+mode) % 6;
// [R1, R2, RC1, RC2, HW2, MW3, HR, MR, M, HSCALE] =
const scales = [
[120, 84, 17, 12.4, 4.6, 2.2, 8, 2, 1, h => (3.0 + Math.ceil(h/1.5)) ],
[102, 70, 14.6, 10.7, 3.88, 1.8, 8, 2, 1, h => (2.4 + Math.ceil(h/1.6)) ],
];
if (mode < 3) {
// Face without time/date text. Might have widgets though.
with_digital_time = with_digital_date = false;
with_widgets = (mode == 1);
}
else {
// Face with time/date text, but no widgets
with_digital_time = (mode-2)&1;
with_digital_date = (mode-2)&2;
with_widgets = false;
}
// Destructure the array to the global display parameters
let arr = scales[mode > 0 ? 1 : 0];
R1 = arr[0];
R2 = arr[1];
RC1 = arr[2];
RC2 = arr[3];
HW2 = arr[4];
MW2 = arr[5];
HR = R2 - arr[6];
MR = R1 - arr[7];
M = arr[8];
HSCALE = arr[9];
TM = with_widgets ? 36 : 0;
CX = GW/2;
CY = R1;
// If we're in the small-face + text regime, we're going to buffer
// the full screen but draw the clock face further down to give
// space for the text.
//
// Compare with modes 0 (full-screen) and 1 (with_widgets==true)
// where the face is drawn at the top of the buffer, but drawn
// lower down the screen (so CY doesn't move)
if (mode > 1) {
CY += 36;
}
// We only don't bother redrawing the face from modes 2 to 5, as
// they're the same.
if (!faceImg || mode<3) {
faceImg = undefined;
}
// Store the settings for next time
try {
storage.writeJSON(filename, [mode,with_seconds]);
} catch (e) {
console.log(e);
}
// Clear the screen: we need to make sure all parts are cleaned off.
g.clear();
};
const changeSeconds = () => {
with_seconds = !with_seconds;
drawAll(true);
};
Bangle.loadWidgets();
// Restore mode
// Store the settings for next time
try {
conf = storage.readJSON(filename);
mode = conf[0];
with_seconds = conf[1];
storage.writeJSON(filename, [mode,with_seconds]);
} catch (e) {
console.log(e);
mode = 1;
}
setButtons();
setMode();
drawAll();
// Clear the screen: we need to make sure all parts are cleaned off.
g.clear();
};
Bangle.on('lcdPower', (on) => {
if (on) {
Bangle.loadWidgets();
Bangle.drawWidgets();
drawAll();
} else {
clearTimeout();
}
});
const changeSeconds = () => {
with_seconds = !with_seconds;
drawAll(true);
};
})(g);
Bangle.loadWidgets();
// Restore mode
try {
conf = storage.readJSON(filename);
mode = conf[0];
with_seconds = conf[1];
} catch (e) {
console.log(e);
mode = 1;
}
setButtons();
setMode();
drawAll();
Bangle.on('lcdPower', (on) => {
if (on) {
Bangle.loadWidgets();
Bangle.drawWidgets();
drawAll();
} else {
clearTimeout();
}
});

View File

@ -1,2 +1,3 @@
0.02: Modified for use with new bootloader and firmware
0.03: Shrinked size to avoid cut-off edges on the physical device. BTN3: show date. BTN1: show time in decimal.
0.04: Update to use Bangle.setUI instead of setWatch

View File

@ -16,7 +16,7 @@ time_digit = [];
function drawBerlinClock() {
g.clear();
var now = new Date();
// show date below the clock
if (show_date) {
var yr = now.getFullYear();
@ -28,7 +28,7 @@ function drawBerlinClock() {
g.setFontAlign(-1,-1);
g.drawString(dateString, ( g.getWidth() - strWidth ) / 2, height + offset + 4);
}
rowlights[0] = Math.floor(now.getHours() / 5);
rowlights[1] = now.getHours() % 5;
rowlights[2] = Math.floor(now.getMinutes() / 5);
@ -62,7 +62,7 @@ function drawBerlinClock() {
} else {
g.setColor(1, 0, 0);
}
g.fillRect(x1 + 2, y1 + 2, x2 - 2, y2 - 2);
g.fillRect(x1 + 2, y1 + 2, x2 - 2, y2 - 2);
}
if (row == 3 && show_time) {
g.setColor(1,1,1);
@ -100,9 +100,11 @@ g.clear();
Bangle.loadWidgets();
Bangle.drawWidgets();
drawBerlinClock();
// Toggle date display, when BTN3 is pressed
setWatch(toggleTime,BTN1, { repeat : true, edge: "falling"});
// Toggle date display, when BTN3 is pressed
setWatch(toggleDate,BTN3, { repeat : true, edge: "falling"});
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
if (BTN3) {
// Toggle date display, when BTN3 is pressed
setWatch(toggleTime,BTN1, { repeat : true, edge: "falling"});
// Toggle date display, when BTN3 is pressed
setWatch(toggleDate,BTN3, { repeat : true, edge: "falling"});
}
// Show launcher when button pressed
Bangle.setUI("clock");

View File

@ -1,2 +1,3 @@
0.01: New App!
0.02: Fixed bug where screen didn't clear so incorrect time displayed.
0.03: Update to use Bangle.setUI instead of setWatch

View File

@ -23,17 +23,17 @@ function drawTime(d) {
}
function updateHourArray(hours){
var j;
for(j=0;j<hourLED.length;j++){
prevHour[j] = hourLED[j];
}
var i;
for(i = 0;i < hourLED.length;i++){
hourLED[i]=0;
hourLED[i]=0;
}
if(hours > 15){
hourLED[0] = 1;
hours = hours - 16;
@ -53,9 +53,9 @@ function updateHourArray(hours){
if(hours > 0){
hourLED[4] = 1;
}
return hourLED;
}
function updateMinuteArray(minutes){
@ -63,12 +63,12 @@ function updateMinuteArray(minutes){
for(j=0;j<minuteLED.length;j++){
prevMinute[j] = minuteLED[j];
}
var i;
for(i = 0;i < minuteLED.length;i++){
minuteLED[i]=0;
minuteLED[i]=0;
}
if(minutes > 31){
minuteLED[0] = 1;
minutes = minutes - 32;
@ -92,20 +92,20 @@ function updateMinuteArray(minutes){
if(minutes > 0){
minuteLED[5] = 1;
}
return minuteLED;
}
function draw(){
// work out how to display the current time
var d = new Date();
var h = d.getHours(), m = d.getMinutes();
updateHourArray(h);
updateMinuteArray(m);
var i;
//Draw hour circles
for(i=0; i<hourLED.length; i++){
@ -118,10 +118,10 @@ function draw(){
g.fillCircle(24+i*48,50,10);
g.setColor(colour);
g.drawCircle(24+i*48,50,10);
}
}
}
}
}
for(i=0; i<minuteLED.length; i++){
if(prevMinute[i] == minuteLED[i]){
if(minuteLED[i] == 1){
@ -132,21 +132,21 @@ function draw(){
g.fillCircle(20+i*40,100,10);
g.setColor(colour);
g.drawCircle(20+i*40,100,10);
}
}
}
}
// draw the date, in a normal font
g.setFont("6x8");
g.setFontAlign(0,1); // align center bottom
// pad the date - this clears the background if the date were to change length
var dateStr = " "+require("locale").date(d)+" ";
g.drawString(dateStr, g.getWidth()/2, 130, true /*clear background*/);
if(displayTime){
drawTime(d);
}else{
g.clearRect(0,240,240,130);
g.clearRect(0,240,240,130);
}
}
@ -167,12 +167,12 @@ Bangle.on('lcdPower',on=>{
// Load widgets
Bangle.loadWidgets();
Bangle.drawWidgets();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
setWatch(function() {
// Show launcher when button pressed
Bangle.setUI("clockupdown", btn=>{
if (btn!=1) return;
if(displayTime == 0){
displayTime = 1;
} else{
displayTime = 0;
displayTime = 0;
}
}, BTN, {edge:"rising", debounce:50, repeat:true});
});

View File

@ -4,3 +4,4 @@
0.03: Modified for use with new bootloader and firmware
0.04: Modified to account for changes in the behavior of Graphics.fillPoly
0.05: Slight increase to draw speed after LCD on
0.06: Update to use Bangle.setUI instead of setWatch, allow themes and different size screens

View File

@ -1,4 +1,6 @@
const buf = Graphics.createArrayBuffer(144,200,1,{msb:true});
let big = g.getHeight() > 200;
const buf = Graphics.createArrayBuffer(big ? 144 : 120, big ? 180 : 150,1,{msb:true});
// TODO: convert these to Polys -> much faster and cleaner!
const NUMBERS = [
[1,1,1,1,3,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1],//0
[0,1,1,1,3,0,0,1,1,1,0,0,1,1,1,0,0,1,1,1,0,0,1,1,1],//1
@ -14,8 +16,10 @@ const NUMBERS = [
let intervalRef = null;
let digits = [-1,-1,-1,-1,-1,-1];
function flip() {
g.setColor(1,1,1);
g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},55,26);
g.reset();
g.drawImage({width:buf.getWidth(),height:buf.getHeight(),buffer:buf.buffer},
(g.getWidth() - buf.getWidth())/2,
26 + (g.getHeight() - (buf.getHeight()+24))/2);
}
function drawPixel(ox,oy,x,y,r,p) {
let x1 = ox+x*(r*2);
@ -53,26 +57,31 @@ function redraw() {
let newDigits = [Math.floor(hours/10),hours%10,Math.floor(mins/10),mins%10,Math.floor(secs/10),secs%10];
let s = big?6:5; // size of main digits
let y2 = big?72:55;
let y3 = big?144:110;
for (var p = 0;p<25;p++) {
var px = p%5;
var py = Math.floor(p/5);
if (digits[0] === -1 || NUMBERS[newDigits[0]][p] !== NUMBERS[digits[0]][p] ) {
drawPixel(0,20,px,py,6,NUMBERS[newDigits[0]][p]);
drawPixel(0,0,px,py,s,NUMBERS[newDigits[0]][p]);
}
if (digits[1] === -1 || NUMBERS[newDigits[1]][p] !== NUMBERS[digits[1]][p] ) {
drawPixel(78,20,px,py,6,NUMBERS[newDigits[1]][p]);
drawPixel(13*s,0,px,py,s,NUMBERS[newDigits[1]][p]);
}
if (digits[2] === -1 || NUMBERS[newDigits[2]][p] !== NUMBERS[digits[2]][p] ) {
drawPixel(0,92,px,py,6,NUMBERS[newDigits[2]][p]);
drawPixel(0,y2,px,py,s,NUMBERS[newDigits[2]][p]);
}
if (digits[3] === -1 || NUMBERS[newDigits[3]][p] !== NUMBERS[digits[3]][p] ) {
drawPixel(78,92,px,py,6,NUMBERS[newDigits[3]][p]);
drawPixel(13*s,y2,px,py,s,NUMBERS[newDigits[3]][p]);
}
if (digits[4] === -1 || NUMBERS[newDigits[4]][p] !== NUMBERS[digits[4]][p] ) {
drawPixel(69,164,px,py,3,NUMBERS[newDigits[4]][p]);
drawPixel(17*s - 3*12,y3,px,py,3,NUMBERS[newDigits[4]][p]);
}
if (digits[5] === -1 || NUMBERS[newDigits[5]][p] !== NUMBERS[digits[5]][p] ) {
drawPixel(108,164,px,py,3,NUMBERS[newDigits[5]][p]);
drawPixel(17*s,y3,px,py,3,NUMBERS[newDigits[5]][p]);
}
}
digits = newDigits;
@ -99,5 +108,5 @@ Bangle.on('lcdPower',function(on) {
clearTimers();
}
});
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
// Show launcher when button pressed
Bangle.setUI("clock");

View File

@ -1,2 +1,3 @@
0.02: Modified for use with new bootloader and firmware
0.03: Tweak for more efficient rendering, and firmware 2v06
0.04: Work with themes, smaller screens

View File

@ -12,9 +12,9 @@ var minute_hand = {
//g.fillRect(0,24,239,239); // Apps area
let intervalRef = null;
const p180 = Math.PI/180;
const clock_center = {x:Math.floor((240-1)/2), y:24+Math.floor((239-24)/2)};
const clock_center = {x:Math.floor((g.getWidth()-1)/2), y:24+Math.floor((g.getHeight()-25)/2)};
// ={ x: 119, y: 131 }
const radius = Math.floor((239-24+1)/2); // =108
const radius = Math.floor((g.getWidth()-24+1)/2); // =108
let tick0 = Graphics.createArrayBuffer(30,8,1,{msb:true});
tick0.fillRect(0,0,tick0.getWidth()-1, tick0.getHeight()-1);
@ -60,18 +60,15 @@ function hour_angle(date){
function draw_clock(){
//console.log("draw_clock");
let date = new Date();
//g.clear();
g.setBgColor(0,0,0);
g.setColor(0,0,0);
g.fillRect(0,24,239,239); // clear app area
g.setColor(1,1,1);
g.reset();
g.clearRect(0,24,239,239); // clear app area
// draw cross lines for testing
// g.setColor(1,0,0);
// g.drawLine(clock_center.x - radius, clock_center.y, clock_center.x + radius, clock_center.y);
// g.drawLine(clock_center.x, clock_center.y - radius, clock_center.x, clock_center.y + radius);
g.setColor(1,1,1);
g.setColor(g.theme.fg);
let ticks = [0, 90, 180, 270];
ticks.forEach((item)=>{
let agl = item+180;
@ -87,13 +84,13 @@ function draw_clock(){
let minute_agl = minute_angle(date);
g.drawImage(hour_hand, hour_pos_x(hour_agl), hour_pos_y(hour_agl), {rotate:hour_agl*p180}); //
g.drawImage(minute_hand, minute_pos_x(minute_agl), minute_pos_y(minute_agl), {rotate:minute_agl*p180}); //
g.setColor(1,1,1);
g.setColor(g.theme.fg);
g.fillCircle(clock_center.x, clock_center.y, 6);
g.setColor(0,0,0);
g.setColor(g.theme.bg);
g.fillCircle(clock_center.x, clock_center.y, 3);
// draw minute ticks. Takes long time to draw!
g.setColor(1,1,1);
g.setColor(g.theme.fg);
for (var i=0; i<60; i++){
let agl = i*6+180;
g.drawImage(tick1.asImage(), rotate_around_x(big_wheel_x(i*6), agl, tick1), rotate_around_y(big_wheel_y(i*6), agl, tick1), {rotate:agl*p180});
@ -141,5 +138,5 @@ g.clear();
Bangle.loadWidgets();
Bangle.drawWidgets();
startTimers();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
// Show launcher when button pressed
Bangle.setUI("clock");

View File

@ -25,3 +25,4 @@
0.24: Add Bangle.setUI polyfill
0.25: Fix error in 'no clock app' message
0.26: Remove buzz in setUI polyfill (#750)
0.27: Update polyfill for most recent changes

View File

@ -3,6 +3,7 @@ recalculates, but this avoids us doing a whole bunch of reconfiguration most
of the time. */
E.showMessage("Updating boot0...");
var s = require('Storage').readJSON('setting.json',1)||{};
var isB2 = process.env.HWVERSION; // Is Bangle.js 2
var boot = "";
var CRC = E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/));
boot += `if (E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/))!=${CRC}) { eval(require('Storage').read('bootupdate.js'));} else {\n`;
@ -81,9 +82,9 @@ if (s.passkey!==undefined && s.passkey.length==6) boot+=`NRF.setSecurity({passke
if (s.whitelist) boot+=`NRF.on('connect', function(addr) { if (!(require('Storage').readJSON('setting.json',1)||{}).whitelist.includes(addr)) NRF.disconnect(); });\n`;
// Pre-2v10 firmwares without a theme/setUI
if (!g.theme) {
boot += `g.theme={fg:-1,bg:0,fg2:-1,bg2:7,fgH:-1,bgH:0x02F7};\n`;
boot += `g.theme={fg:-1,bg:0,fg2:-1,bg2:7,fgH:-1,bgH:0x02F7,dark:true};\n`;
}
if (!Bangle.setUI) {
if (!Bangle.setUI) { // assume this is just for F18 - Q3 should already have it
boot += `Bangle.setUI=function(mode, cb) {
if (Bangle.btnWatches) {
Bangle.btnWatches.forEach(clearWatch);
@ -114,6 +115,18 @@ else if (mode=="updown") {
Bangle.on("swipe", Bangle.swipeHandler);
Bangle.touchHandler = d => {cb();};
Bangle.on("touch", Bangle.touchHandler);
} else if (mode=="clock") {
Bangle.CLOCK=1;
Bangle.btnWatches = [
setWatch(Bangle.showLauncher, BTN2, {repeat:1,edge:"falling"})
];
} else if (mode=="clockupdown") {
Bangle.CLOCK=1;
Bangle.btnWatches = [
setWatch(function() { cb(-1); }, BTN1, {repeat:1}),
setWatch(function() { cb(1); }, BTN3, {repeat:1}),
setWatch(Bangle.showLauncher, BTN2, {repeat:1,edge:"falling"})
];
} else
throw new Error("Unknown UI mode");
};\n`;

0
apps/buffgym/buffgym-scrn1.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

0
apps/buffgym/buffgym-scrn2.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

0
apps/buffgym/buffgym-scrn3.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

0
apps/buffgym/buffgym-scrn4.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

0
apps/buffgym/buffgym-scrn5.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

0
apps/buffgym/buffgym-scrn6.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

0
apps/buffgym/buffgym.app.js Executable file → Normal file
View File

0
apps/buffgym/buffgym.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -1 +1,2 @@
0.01: Basic calendar
0.02: Make Bangle 2 compatible

View File

@ -1,5 +1,6 @@
const maxX = 240;
const maxY = 240;
const maxX = g.getWidth();
const maxY = g.getHeight();
const fontSize = g.getWidth()>200?2:1;
const rowN = 7;
const colN = 7;
const headerH = maxY / 7;
@ -50,7 +51,7 @@ function drawCalendar(date) {
11: "December"
};
g.setFontAlign(0, 0);
g.setFont("6x8", 2);
g.setFont("6x8", fontSize);
g.setColor(white);
g.drawString(`${monthMap[month]} ${year}`, maxX / 2, headerH / 2);
g.drawPoly([10, headerH / 2, 20, 10, 20, headerH - 10], true);
@ -59,7 +60,7 @@ function drawCalendar(date) {
true
);
g.setFont("6x8", 2);
g.setFont("6x8", fontSize);
const dowLbls = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
dowLbls.forEach((lbl, i) => {
g.drawString(lbl, i * colW + colW / 2, headerH + rowH / 2);
@ -135,26 +136,21 @@ const today = {
};
drawCalendar(date);
clearWatch();
setWatch(
() => {
const month = date.getMonth();
const prevMonth = month > 0 ? month - 1 : 11;
Bangle.on("touch",area=>{
const month = date.getMonth();
let prevMonth;
if (area==1) {
let prevMonth = month > 0 ? month - 1 : 11;
if (prevMonth === 11) date.setFullYear(date.getFullYear() - 1);
date.setMonth(prevMonth);
drawCalendar(date);
},
BTN4,
{ repeat: true }
);
setWatch(
() => {
const month = date.getMonth();
const prevMonth = month < 11 ? month + 1 : 0;
} else {
let prevMonth = month < 11 ? month + 1 : 0;
if (prevMonth === 0) date.setFullYear(date.getFullYear() + 1);
date.setMonth(month + 1);
drawCalendar(date);
},
BTN5,
{ repeat: true }
);
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
}
drawCalendar(date);
});
// Show launcher when button pressed
Bangle.setUI("clock"); // TODO: ideally don't set 'clock' mode
// No space for widgets!

View File

@ -1,6 +1,7 @@
0.07: Submitted to App Loader
0.08: Fixes issue where face would redraw on wake leading to all memory being used and watch crashing.
0.08: Fixes issue where face would redraw on wake leading to all memory being used and watch crashing.
0.09: Add BTN1 status line with ID,Fw ver, mem %, battery %
0.10: Icon fixed for transparency
0.11: added Heart Rate Monitor status and ability to turn on/off
0.12: added support for different locales
0.13: Use setUI, work with smaller screens and themes

View File

@ -1,4 +1,5 @@
var fontsize = 3;
var fontsize = g.getWidth()>200 ? 3 : 2;
var fontheight = 10*fontsize;
var locale = require("locale");
var marginTop = 40;
var flag = false;
@ -39,22 +40,23 @@ function updateTime(){
updateRest(now);
}
function writeLineStart(line){
g.drawString(">",4,marginTop+line*30);
g.drawString(">",4,marginTop+line*fontheight);
}
function writeLine(str,line){
var y = marginTop+line*fontheight;
g.setFont("6x8",fontsize);
//g.setColor(0,1,0);
g.setColor(0,0x07E0,0);
g.setColor("#0f0");
g.setFontAlign(-1,-1);
g.clearRect(0,marginTop+line*30,((str.length+1)*20),marginTop+25+line*30);
g.clearRect(0,y,((str.length+1)*20),y+fontheight-1);
writeLineStart(line);
g.drawString(str,25,marginTop+line*30);
}
g.drawString(str,25,y);
}
function drawInfo(line) {
let val;
let str = "";
let col = 0x07E0; // green
let col = "#0f0"; // green
//console.log("drawInfo(), infoMode=" + infoMode + " funcMode=" + functionMode);
@ -62,15 +64,15 @@ function drawInfo(line) {
case NONE_FN_MODE:
break;
case HRT_FN_MODE:
col = 0x07FF; // cyan
col = "#0ff"; // cyan
str = "HRM: " + (hrtOn ? "ON" : "OFF");
drawModeLine(line,str,col);
return;
}
switch(infoMode) {
case NONE_MODE:
col = 0x0000;
col = "#fff";
str = "";
break;
case HRT_MODE:
@ -100,10 +102,11 @@ function drawInfo(line) {
function drawModeLine(line, str, col) {
g.setColor(col);
g.fillRect(0, marginTop-3+line*30, 239, marginTop+25+line*30);
g.setColor(0,0,0);
var y = marginTop+line*fontheight;
g.fillRect(0, y, 239, y+fontheight-1);
g.setColor(0);
g.setFontAlign(0, -1);
g.drawString(str, g.getWidth()/2, marginTop+line*30);
g.drawString(str, g.getWidth()/2, y);
}
function changeInfoMode() {
@ -160,7 +163,7 @@ function changeFunctionMode() {
functionMode = NONE_FN_MODE;
}
//console.log(functionMode);
}
function stepsWidget() {
@ -185,10 +188,12 @@ Bangle.loadWidgets();
Bangle.drawWidgets();
drawAll();
Bangle.on('lcdPower',function(on) {
if (on)
drawAll();
if (on) drawAll();
});
var click = setInterval(updateTime, 1000);
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
setWatch(() => { changeInfoMode(); drawAll(); }, BTN1, {repeat: true});
setWatch(() => { changeFunctionMode(); drawAll(); }, BTN3, {repeat: true});
// Show launcher when button pressed
Bangle.setUI("clockupdown", btn=>{
if (btn==0) changeInfoMode();
if (btn==1) changeFunctionMode();
drawAll();
});

View File

@ -1,3 +1,4 @@
0.02: Modified for use with new bootloader and firmware
0.03: Added 'reset' so we don't get the font color from widgets
0.04: Changed name from clck3x2 to clock2x3
0.05: Use setUI, work with smaller screens and themes

View File

@ -1,8 +1,10 @@
const big = g.getWidth()>200;
const ox=10; // x offset
const oy=80;
const pw=20; // pixel width
const ps=5; // pixel spacing
const ds=10; // digit spacing
const oy=big ? 80 : 70;
const pw=big ? 20 : 14; // pixel width
const ps=big ? 5 : 3; // pixel spacing
const ds=big ? 10 : 8; // digit spacing
const ms=20; // middle space
const x00=ox; // digit 0, pixel 0, x position
@ -90,7 +92,7 @@ Bangle.on('lcdPower', function(on){
}
});
// Show launcher when button pressed
Bangle.setUI("clock");
Bangle.loadWidgets();
drawTime();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});

View File

@ -1 +1,2 @@
0.02: Modified for use with new bootloader and firmware
0.03: Changed setWatch to Bangle.setUI

View File

@ -46,26 +46,25 @@ function drawSegment (align, base, str) {
point = base + (maxSegmentWidth / 2) -
(g.stringWidth(str) / 2);
}
g.setColor(1, 1, 1);
g.setColor(g.theme.fg);
g.drawString(str, point, middleY - 4, false);
}
function drawDots (center) {
g.setColor(0xFD20);
g.setColor("#FA0");
g.fillCircle(center, middleY + 10, 2);
g.fillCircle(center, middleY + 40, 2);
}
function drawLines () {
g.setColor(0.5, 0.5, 0.5);
g.setColor("#777");
g.drawLine(middleX - lineLength, lineY1, middleX + lineLength, lineY1);
g.drawLine(middleX - lineLength, lineY2, middleX + lineLength, lineY2);
}
function drawDate (str) {
let maxSegmentWidth = 236;
g.setColor(0.5, 0.5, 0.5);
g.setColor(0.5, 0.5, 0.5);
g.setColor("#777");
g.drawString(str, (maxSegmentWidth) - (g.stringWidth(str)), middleY - 22,
false);
}
@ -149,6 +148,9 @@ function start () {
}
start();
// Show launcher when middle button pressed
Bangle.setUI("clock");
Bangle.loadWidgets();
Bangle.drawWidgets();
Bangle.on('lcdPower', function (on) {
@ -158,6 +160,3 @@ Bangle.on('lcdPower', function (on) {
stop();
}
});
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});

View File

@ -7,3 +7,4 @@
0.07: add days in current month (md) and days since new moon (l)
0.08: update icon
0.09: Use localised month and day of the week from locale
0.10: Changed setWatch to Bangle.setUI and allow small screen

View File

@ -1,17 +1,18 @@
var locale = require("locale");
/* jshint esversion: 6 */
const timeFontSize = 4;
const dateFontSize = 3;
const smallFontSize = 2;
const big = g.getWidth()>200;
const timeFontSize = big?4:3;
const dateFontSize = big?3:2;
const smallFontSize = big?2:1;
const font = "6x8";
const xyCenter = g.getWidth() / 2;
const yposTime = 50;
const yposDate = 85;
const yposTst = 115;
const yposDml = 170;
const yposDayMonth = 195;
const yposGMT = 220;
const yposDate = big?85:75;
const yposTst = big?115:95;
const yposDml = big?170:130;
const yposDayMonth = big?195:140;
const yposGMT = big?220:150;
// Check settings for what type our clock should be
var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"];
@ -99,6 +100,8 @@ Bangle.on('lcdPower', function(on) {
// clean app screen
g.clear();
// Show launcher when button pressed
Bangle.setUI("clock");
Bangle.loadWidgets();
Bangle.drawWidgets();
@ -107,6 +110,3 @@ setInterval(drawSimpleClock, 100);
// draw now
drawSimpleClock();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});

2
apps/de-stress/ChangeLog Normal file
View File

@ -0,0 +1,2 @@
0.01: New App!
0.02: Adjust for different screen types and themes

View File

@ -1,29 +1,21 @@
g.setBgColor(0).clear();
//g.clear();
var img = {
width : 100, height : 100, bpp : 8,
transparent : 254,
buffer : require("heatshrink").decompress(atob("/wA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AglYAGE/44gHz4nnHKtPumez3C4WezFzp49ZLAgoCE4WeugnaHStPG4QAHzw9DE/Y6VHJQ9YMJwnEMk46CF4lzfglPug9WCAWYDQl0E4tzN4gLCMVC5Cp+YGoOezxBCubKHExxUEuiFCEoInECAhkjMQuYLArCFGwLLEHpjsGMIRpEfAsrMkwhBFAQ6BHJA9EKApDBHpAJBQYhPBE5iZBzAsDMb4gBEwg6MJhBkIYorgBPQiMMUAhkeHgkrug7ObI5qBHwhiGZYomOEojGeJQVzTx5kOMQ6JREAR3CDIJkcHobwEMiw+CAAYJEMSYWCAgRjcDgI4CYyiiDXopiFBooAWRwJkaHwjGVKwdzH4rADuhiXZAaICMbbtGHy2YBQ+YRDCiEMbidCULBkDLIwIIdqbmCp5jZPwIfDAYQAXXwNPzwACIQLQIACt0ZDIZBTwRFBHjWeHoSJCETlPc4ZjdAYYA7L4Jj/Mf5jCEYQDDAHhEEMbzH+McBfCMf4ADzxjep+YL/1PMb10MYQDCAHd0MYV0MbdzEYoA7UYdPMTBkCc4hj9leeAYRjbL4aIDAHN0UwRjeL4WYZHlPzBnCMbZkBQojtCAG6gEp5ibZARfCdwjG3ugDBzzGcMYTIEFAQA1ujGFMbjIFeAgA0HobGeZA9PAgYAyG4jGfZAyPBzBizf4LGjMggtCFAJpDAFw0FMURjCeAd0AgYAup90AgZjjMgWYFYZkwGImYMUhkDeYdPuZituZiDzximMYUrFwj6DAFF0TAg6CMcpkCSYpkqMQtPMVBkDuZktMQtzMVRkDLwZkoMQoFBMVZkJp5ijX4JizMhFPMkQjBMWpkHIAKjEADTrGMWZkDuY8DuZkdMQKKEMWpkDUIxFEACocGdoJi1MhCqBAwgATLYLkEMXJkDIY4GEAB+ep9PC4aDBMXRkJukruhiRCgxi+MglzJAtPMR7cGNIJi+MglPJYhSBzBhLzB0FzwWBMX5lGMghVGAAtzld0bwph/MhNzWYzKGNwR2Euhi/MhhTHA4ZrHA4Rh/Mp10YIlzA4JoCBQjE/ZTK8BA45i/MqtzX4jE/Mj0rYQjECBYZP/MrFPMoWep5h/ZT90ujE/MsZh/MsZB/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/ACg"))
};
var img = require("heatshrink").decompress(atob("plB4X/ln7A4OGmMs5dVAANa1WlAoQADBI9W1QAByoJNtWv4f61ISEtWrBI2q4EAgeqCQgJHq2sLoU6IYdaBIg5CrWAn2q2EDF4dq4EO1W8gQcCtUD1fP9cA9QSC1cA9f/9XADgWohxBBh2whQvBq2gAwMAh+wlQSB1k7IIXogYvBrXAlYJC9k6DYOw9gIChXA9JBC0AJCncOytWwAtBAAMDF4RBDAAMOgWVrXDwDjD9kKy2gIIcAgXD0taDYgvCRIJBDF4OA0trhwIDJgK2B4BKDAAXptcLA4kC4HrD4IJE8HptE4BAhfBLAJBEgEslISGL4JOBBAoSB1ksBIs6/70DBIgSHh+q+AIFnASIABASU0EgCR0IhWgEp4SBHCBxJLzusXowAIaBISLhYSO8EptcOCR2w9NagXACJkDwGlrXDwASMgXDCQOA2ASMh0C0tW2HgCRkLh2Vq2glASMlEKytV1iFN9k6qtVtEOORcD2EpCQNqOwJwL4GpCQNa4GgCRUKgelCQJyBlgSKnBwBCQWgnZdLOAQAB1BfKLoMqCIVVtYHBXZPA9ISDL4PsCRE7LoZfDnRKJLoYAC1kOTI8CDoIREJgMA1gSGFwJKEJgaGH9hKFTIaGGPQKVEAAeogbTFhXASogADtXAlYSE9cDeYRMG2A5EG4MOJQxMC1g5EG4M6JQ4AB1Q5E9ED1QRIHIatBG5Y5EVoM6G5Y5DnXDCwJvIHIsD32AG5Y5C1aUBgHqG5atDLwI3MHIReCG5hgD4aUKHI2+G5xgC1RcNAAdpBJA"))
function hr(){
Bangle.buzz(100,0.1).then(()=>{
g.clear();
return new Promise(resolve=>setTimeout(resolve,250)); // wait 250ms
}).then(()=>{
return Bangle.buzz(150);
}).then(()=>{
g.drawImage(img, 25, 40, {scale:2});
});
Bangle.buzz(100,0.1).then(()=>{
g.clear();
return new Promise(resolve=>setTimeout(resolve,250)); // wait 250ms
}).then(()=>{
return Bangle.buzz(150);
}).then(()=>{
g.drawImage(img, g.getWidth()/2 - 76, g.getHeight()/2 - 65, {scale:2});
});
}
setInterval(hr, 2000);
g.flip();
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
// TODO - not clock but we still want a press to show launcher when button pressed
Bangle.setUI("clock");

View File

@ -1,2 +1,3 @@
0.01: App created
0.02: Persist state to storage to enable stopwatch to continue in the background
0.03: Modified to use setUI, theme and different screens

View File

@ -2,13 +2,16 @@ const EMPTY_LAP = '--:--:---';
const EMPTY_H = '00:00:000';
const MAX_LAPS = 6;
const XY_CENTER = g.getWidth() / 2;
const big = g.getWidth()>200;
const Y_CHRONO = 40;
const Y_HEADER = 80;
const Y_LAPS = 125;
const Y_BTN3 = 225;
const Y_HEADER = big?80:60;
const Y_LAPS = big?125:90;
const H_LAPS = big?15:8;
const Y_BTN3 = big?225:165;
const FONT = '6x8';
const CHRONO = '/* C H R O N O */';
var reset = false;
var currentLap = '';
var chronoInterval;
@ -22,11 +25,11 @@ var state = require("Storage").readJSON("devstopwatch.state.json",1) || {
laps: [EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP],
};
// Set laps.
setWatch(() => {
// Show launcher when button pressed
Bangle.setUI("clockupdown", btn=>{
if (btn==0) {
reset = false;
if (state.started) {
changeLap();
} else {
@ -34,13 +37,9 @@ setWatch(() => {
chronoInterval = setInterval(chronometer, 10);
}
}
}, BTN1, { repeat: true, edge: 'rising' });
// Reset chronometre.
setWatch(() => { resetChrono(); }, BTN3, { repeat: true, edge: 'rising' });
// Show launcher when middle button pressed.
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: 'falling' });
}
if (btn==1) resetChrono();
});
function resetChrono() {
state.laps = [EMPTY_H, EMPTY_H, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP, EMPTY_LAP];
@ -106,33 +105,33 @@ function printChrono() {
var print = '';
g.setFont(FONT, 2);
g.setFont(FONT, big?2:1);
print = CHRONO;
g.drawString(print, XY_CENTER, Y_CHRONO, true);
g.setColor(0, 220, 0);
g.setFont(FONT, 3);
g.setColor("#0e0");
g.setFont(FONT, big?3:2);
print = ` T ${state.laps[0]}\n`;
print += ` C ${state.laps[1]}\n`;
g.drawString(print, XY_CENTER, Y_HEADER, true);
g.setColor(255, 255, 255);
g.setFont(FONT, 2);
g.setColor(g.theme.fg);
g.setFont(FONT, big?2:1);
for (var i = 2; i < MAX_LAPS + 1; i++) {
g.setColor(255, 255, 255);
g.setColor(g.theme.fg);
let suffix = ' ';
if (state.currentLapIndex === i) {
let suffix = '*';
g.setColor(255, 200, 0);
g.setColor("#f70");
}
const lapLine = `L${i - 1} ${state.laps[i]} ${suffix}\n`;
g.drawString(lapLine, XY_CENTER, Y_LAPS + (15 * (i - 1)), true);
g.drawString(lapLine, XY_CENTER, Y_LAPS + (H_LAPS * (i - 1)), true);
}
g.setColor(255, 255, 255);
g.setColor(g.theme.fg);
g.setFont(FONT, 1);
print = 'Press 3 to reset';
g.drawString(print, XY_CENTER, Y_BTN3, true);
@ -166,7 +165,7 @@ E.on('kill', function(){
});
if(state.started){
chronoInterval = setInterval(chronometer, 10);
chronoInterval = setInterval(chronometer, 10);
} else {
resetChrono();
resetChrono();
}

View File

@ -1 +1,2 @@
0.01: App Made!
0.02: Changed setWatch to Bangle.setUI, code tidy

View File

@ -1,141 +1,50 @@
//load fonts
require("Font7x11Numeric7Seg").add(Graphics);
require("FontHaxorNarrow7x17").add(Graphics);
require("FontHaxorNarrow7x17").add(Graphics);
//screen position
const X = 170;
const Y = 140;
const X = 170;
const Y = 140;
function draw() {
// Date Variables
var date = new Date();
var h = date.getHours();
var m = date.getMinutes();
var day = date.getDay();
var month = date.getMonth();
var dateNum = date.getDate();
var year = date.getFullYear();
var half = "AM";
var time = (" " + h).substr(-2) + ":" + ("0" + m).substr(-2);
//convert day into string
switch (day) {
case 0:
day = "Sunday";
break;
case 1:
day = "Monday";
break;
case 2:
day = "Tuesday";
break;
case 3:
day = "Wednesday";
break;
case 4:
day = "Thursday";
break;
case 5:
day = "Friday";
break;
case 6:
day = "Saturday";
break;
default:
day = "ERROR";
break;
}
//convert month into String
switch(month) {
case 0:
month = "Jan";
break;
case 1:
month = "Feb";
break;
case 2:
month = "Mar";
break;
case 3:
month = "Apr";
break;
case 4:
month = "May";
break;
case 5:
month = "Jun";
break;
case 6:
month = "Jul";
break;
case 7:
month = "Aug";
break;
case 8:
month = "Sep";
break;
case 9:
month = "Oct";
break;
case 10:
month = "Nov";
break;
case 11:
month = "Dec";
break;
default:
month = "ERROR";
break;
}
var date = new Date();
var h = date.getHours();
var m = date.getMinutes();
var day = require("locale").dow(date);
var month = require("locale").month(date,1);
var dateNum = date.getDate();
var year = date.getFullYear();
var half = "AM";
var time = (" " + h).substr(-2) + ":" + ("0" + m).substr(-2);
if (h > 12) {
half = "PM";
h = h - 12;
half = "PM";
h = h - 12;
}
//reset graphics
g.reset();
g.reset();
//draw the time
g.setFont("7x11Numeric7Seg", 5);
g.setFontAlign(1,1);
g.drawString(time, X, Y, true /*clear background*/);
g.setFont("7x11Numeric7Seg", 3);
g.drawString(("0"+date.getSeconds()).substr(-2), X+50, Y, true /*clear background*/);
g.setFont("7x11Numeric7Seg", 3);
g.drawString(("0"+date.getSeconds()).substr(-2), X+50, Y, true /*clear background*/);
g.setFontAlign(0,1);
g.setFont("HaxorNarrow7x17", 2);
g.drawString(half, X+30, Y-35, true);
g.setFont("HaxorNarrow7x17", 3);
g.drawString(day, X-60, Y+53, true);
g.drawString(month, X-100, Y+95, true);
g.drawString(dateNum, X-40, Y+95, true);
g.drawString(year, X-90, Y-55, true);
g.drawString(month, X-100, Y+95, true);
g.drawString(dateNum, X-40, Y+95, true);
g.drawString(year, X-90, Y-55, true);
}
//clear screen at startup
g.clear();
g.clear();
//draw immediatly
draw();
draw();
var secondInterval = setInterval(draw, 1000);
// Stop updates when LCD is off, restart when on
@ -148,7 +57,7 @@ Bangle.on('lcdPower',on=>{
}
});
// Show launcher when button pressed
Bangle.setUI("clock");
Bangle.loadWidgets();
Bangle.drawWidgets();
setWatch(Bangle.showLauncher, BTN2, {repeat : false, edge: "falling"});

View File

@ -1,2 +1,3 @@
0.01: Based on the Analog Clock app, minimal dot
0.02: Remove hardcoded hour buzz (you can install widchime if you miss it)
0.03: Use setUI, adjust for themes and different size screens

View File

@ -1,20 +1,22 @@
let g;
let Bangle;
const big = g.getWidth()>200;
const locale = require('locale');
const p = Math.PI / 2;
const pRad = Math.PI / 180;
const faceWidth = 100; // watch face radius
let timer = null;
let currentDate = new Date();
let hourRadius = 60;
let minRadius = 80;
const centerPx = g.getWidth() / 2;
const faceWidth = big?100:65; // watch face radius
let hourRadius = big?60:40;
let minRadius = big?80:55;
const centerX = g.getWidth() / 2;
const centerY = 24 + (g.getHeight()-24) / 2;
let colSecA = g.theme.dark ? "#00A" : "#58F"; // before the second
let colSecB = g.theme.dark ? "#58F" : "#00A"; // after the second
let colSec1 = g.theme.dark ? "#F83" : "#000"; // ON the second
const seconds = (angle) => {
const a = angle * pRad;
const x = centerPx + Math.sin(a) * faceWidth;
const y = centerPx - Math.cos(a) * faceWidth;
const x = centerX + Math.sin(a) * faceWidth;
const y = centerY - Math.cos(a) * faceWidth;
// if 15 degrees, make hour marker larger
const radius = (angle % 15) ? 2 : 4;
@ -23,15 +25,15 @@ const seconds = (angle) => {
const hourDot = (angle,radius) => {
const a = angle * pRad;
const x = centerPx + Math.sin(a) * hourRadius;
const y = centerPx - Math.cos(a) * hourRadius;
const x = centerX + Math.sin(a) * hourRadius;
const y = centerY - Math.cos(a) * hourRadius;
g.fillCircle(x, y, radius);
};
const minDot = (angle,radius) => {
const a = angle * pRad;
const x = centerPx + Math.sin(a) * minRadius;
const y = centerPx - Math.cos(a) * minRadius;
const x = centerX + Math.sin(a) * minRadius;
const y = centerY - Math.cos(a) * minRadius;
g.fillCircle(x, y, radius);
};
@ -45,54 +47,49 @@ const drawAll = () => {
// draw all secs
for (let i = 0; i < 60; i++) {
if (i > currentSec) {
g.setColor(0, 0, 0.6);
} else {
g.setColor(0.3, 0.3, 1);
}
g.setColor((i > currentSec) ? colSecA : colSecB);
seconds((360 * i) / 60);
}
onSecond();
};
const resetSeconds = () => {
g.setColor(0, 0, 0.6);
g.setColor(colSecA);
for (let i = 0; i < 60; i++) {
seconds((360 * i) / 60);
}
};
const drawMin = () => {
g.setColor(0.5, 0.5, 0.5);
g.setColor("#777");
for (let i = 0; i < 60; i++) {
minDot((360 * i) / 60,1);
}
};
const drawHour = () => {
g.setColor(0.5, 0.5, 0.5);
g.setColor("#777");
for (let i = 0; i < 12; i++) {
hourDot((360 * 5 * i) / 60,1);
}
};
const onSecond = () => {
g.setColor(0.3, 0.3, 1);
g.setColor(colSecB);
seconds((360 * currentDate.getSeconds()) / 60);
if (currentDate.getSeconds() === 59) {
resetSeconds();
onMinute();
}
g.setColor(1, 0.7, 0.2);
g.setColor(colSec1);
currentDate = new Date();
seconds((360 * currentDate.getSeconds()) / 60);
g.setColor(1, 1, 1);
g.setColor(g.theme.fg);
};
const drawDate = () => {
g.reset();
g.setColor(1, 1, 1);
g.setFont('6x8', 2);
g.setFont('6x8', big?2:1);
const dayString = locale.dow(currentDate, true);
// pad left date
@ -101,7 +98,7 @@ const drawDate = () => {
// console.log(`${dayString}|${dateString}`);
// center date
const l = (g.getWidth() - g.stringWidth(dateDisplay)) / 2;
const t = centerPx - 6 ;
const t = centerY - 6 ;
g.drawString(dateDisplay, l, t);
// console.log(l, t);
};
@ -111,7 +108,7 @@ const onMinute = () => {
resetSeconds();
}
// clear existing hands
g.setColor(0, 0, 0);
g.setColor(g.theme.bg);
hourDot((360 * currentDate.getHours()) / 12,4);
minDot((360 * currentDate.getMinutes()) / 60,3);
@ -125,7 +122,7 @@ const onMinute = () => {
g.setColor(1, 0, 0);
// Hour
hourDot((360 * currentDate.getHours()) / 12,4);
g.setColor(1, 0.9, 0.9);
g.setColor(g.theme.fg2);
// Minute
minDot((360 * currentDate.getMinutes()) / 60,3);
drawDate();
@ -152,8 +149,8 @@ g.clear();
resetSeconds();
startTimers();
drawAll();
// Show launcher when button pressed
Bangle.setUI("clock");
Bangle.loadWidgets();
Bangle.drawWidgets();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });

0
apps/dotmatrixclock/app.js Executable file → Normal file
View File

0
apps/dotmatrixclock/dotmatrix-clock-screen-shot.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

0
apps/dotmatrixclock/dotmatrixclock.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -1 +1,2 @@
0.01: First released version
0.02: Changed setWatch to Bangle.setUI

View File

@ -243,5 +243,5 @@ startTimers();
Bangle.loadWidgets();
drawAll();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
// Show launcher when button pressed
Bangle.setUI("clock");

View File

@ -1,2 +1,3 @@
0.01: New App!
0.02: BTN2->launcher, use smaller text to allow "20:00" to fit on screen
0.03: Changed setWatch to Bangle.setUI

View File

@ -148,4 +148,5 @@ Bangle.drawWidgets();
iterate();
animInterval = setInterval(iterate, 50);
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
// Show launcher when button pressed
Bangle.setUI("clock");

View File

@ -21,3 +21,5 @@
0.17: Disable recording if storage is full (fix #574)
0.18: Period counter now uses GPS time rather than counting packets (allows use with GPS Setup)
0.19: Fix memory usage issues inside track viewer app
0.20: Add documentation to explain time needed for getting a time fix
0.21: Fix issue where a period of 1s recorded every 2s, 5s every 6s, and so on

10
apps/gpsrec/README.md Normal file
View File

@ -0,0 +1,10 @@
# GPS Recorder
![icon](app.png)
This app allows you to record a GPS track. It can run in background. The data can later be exported as KML or GPX files via the BangleJS app store.
## Tips
When you turn on recording, a widget badge that looks like a satellite will appear immediately at the top of the screen. However, the recording does not begin immediately. It usually takes several minutes for the watch to get a [GPS fix](https://en.wikipedia.org/wiki/Time_to_first_fix). You will notice a blinking question mark at the lower left of the badge indicating currently getting a fix. The badge will change when a GPS fix is achieved and that is when the app actually starts writing data to the log file. You can [upload assistant files](https://banglejs.com/apps/#assisted%20gps%20update) to speed up the time spent on getting a GPS fix.

View File

@ -29,7 +29,7 @@
var period = 1000000;
if (lastFixTime!==undefined)
period = fix.time.getTime() - lastFixTime;
if (period > settings.period*1000) {
if (period+500 > settings.period*1000) { // round up
lastFixTime = fix.time.getTime();
try {
if (gpsTrack) gpsTrack.write([

0
apps/marioclock/mario-clock-screen-shot.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

0
apps/miclock/clock-mixed.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 707 B

After

Width:  |  Height:  |  Size: 707 B

0
apps/miclock2/clock-mixed.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 707 B

After

Width:  |  Height:  |  Size: 707 B

0
apps/minionclk/ChangeLog Executable file → Normal file
View File

0
apps/minionclk/app-icon.js Executable file → Normal file
View File

0
apps/minionclk/app.js Executable file → Normal file
View File

0
apps/minionclk/minionclk.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -11,11 +11,9 @@ function animate(seq,period) {
// Fade in to FG color with angled lines
function fade(col, callback) {
var n = 0;
function f() {
function f() {"ram"
g.setColor(col);
for (var i=n;i<240;i+=10) {
g.drawLine(i,0,0,i).drawLine(i,240,240,i);
}
for (var i=n;i<240;i+=10) g.drawLine(i,0,0,i).drawLine(i,240,240,i);
g.flip();
n++;
if (n<10) setTimeout(f,0);
@ -25,19 +23,22 @@ function fade(col, callback) {
}
var scenes = [
function() {
var SCENE_COUNT=11;
function getScene(n) {
if (n==0) return function() {
console.log("Start app");
g.clear(1);
eval(require("Storage").read("mywelcome.custom.js"));
},function() {
}
if (n==1) return function() {
g.clear(1);
g.setFont("4x6",2);
var n=0;
var l = Bangle.getLogo();
var i = setInterval(function() {
n+=0.04;
g.setColor(n,n,n);
g.drawImage(Bangle.getLogo(),(240-222)/2,(240-100)/2);
g.drawImage(l,(240-222)/2,(240-100)/2);
if (n>=1) {
clearInterval(i);
setTimeout(()=>g.drawString("Open",34,144), 500);
@ -45,7 +46,8 @@ var scenes = [
setTimeout(()=>g.drawString("Smart Watch",34,168), 1500);
}
},50);
},function() {
};
if (n==2) return function() {
var img = require("heatshrink").decompress(atob("ptRxH+qYAfvl70mj5gAC0ekvd8FkAAdz3HJAYAH4+eJXWkJJYAF0hK2vfNJaIAB5t7S3fN5/V6wAD6vOTg9SumXy2W3QAB3eXul2JdnO63XAApPEVYvAJQIACJoRQDzBLoJQ3W5/NIwr4GJohMFAAROgJYvVJQiPGABZNN3bsdvYyESwnWJSIAC3RNM3V1JjZAES4nVJSYAB4xMNJrbkE56WD5xLVdB5NbFofNJbgABJh26qREPrFXrlbAAWjFgfWJgRLaTQhMLy5KNJINhsJLDrYrD5xLC6pLa5nGTR7oLq9bJQJMKTAXWJbbnR3RLJSoRMHv4pC5rkec6SaIrBLGw2r2XW1epcoqYeJiOXJYziEsOH2RBBw7lF56Yg5nGc6FScZOGJQPX2TmDFIfVTEBMSc4hLEw5KB6+rsJMH63X6pMf5hMQzBLCq5LD1ZLEJhTlfJiWXTA2GJYpMIcwPNc2O6TAuGRIPX1igDJg/PJmyYDcgXWwxMH1ApC53XcsHAJiVYcg2HJYZME0YpC5vWJkhLNJgLlDTAeFJhF/FQfVJkG6JiGXcomyJgOrJYhMErYqD53NJj7lRzBMDcoeGJhzoBJb3GJiN1qZBCJgWyJYpNF1LigAAXAJiNSJgzlGJgt/JkZLRy9TJgeHJhznFcuSZGw5MHJomjcuhLBqdcJiSaiTChMV1CYxy5LCqdXIAWy6+rJhCalTCN2JgdYH4WHJiGpTF7kDc43W2RMJTUZLQzBLFc4mr6+GJh2jTFmXJYyaEwuyc5Sag4xLZTQmG2WFJhxNaJYZMLJZSaEJoOHTR9/Ja+6JbdTqRNETRRNF1JLV4BLcAANYI5ToK1BLYJhWYJZwABq5NoJZ91JaAABdAZNS0ZLey9SJaRNYv5KM426JZmXuxKUJrKcL0lTzBLKzBKYJrVXvfGSol7EYWXJI27zF1JLQADq5NUrgYB4wAEEIV0comXI7wAFrCcPJgYWBTIIAETIN2JYmWuhMkdSdYCgOeJgueqRLFyzhfTi9bq4TC45MF49TuuXJlpONcogAC0hKB0gHDvZMEqRMpAANSq9crlbJAYADqwRDxGk0mIA4eCTQOeveXJdYAHqxNFdAeIAAQGCrOI0oHEAGVXTRJMGvgGCwRM7TAZMHwQGCvhM1rBMERIhMGAwdZJmtSqVTwNcwJEDJg19cvIADa4d9JhANDJnSLHJgrl6AAhFFAwpZDegjn7vhMGcvwABrJAFJgjl/TQpBBI4jl/AAN8TQhHDcv4ADcJBMDvpM+IYaeDAAhL+qd9SgycEJn7iEAA18Jf7nEcv4AIrJLIcv6aMcv4ADvhMHrJJ/AAbl/c6ZM/AAt9cv7nSIv7nLcv4AHrLl/TRpJBvgnjA=="));
g.reset();
g.setBgColor("#6633ff");
@ -76,7 +78,8 @@ var scenes = [
},20);
},3500);
},function() {
};
if (n==3) return function() {
g.reset();
g.setBgColor("#ffa800");g.clear();
g.setFont("6x8",2);
@ -91,8 +94,8 @@ var scenes = [
()=>g.drawString("2",200,120),
()=>g.drawString("3",200,200)
],200);
},
function() {
};
if (n==4) return function() {
g.reset();
g.setBgColor("#00a8ff");g.clear();
g.setFontAlign(0,0);
@ -101,8 +104,8 @@ var scenes = [
g.setFontAlign(-1,-1);
g.setFont("6x8",2);
g.drawString("Move up\nin menus\n\nTurn Bangle.js on\nif it was off", 20,40);
},
function() {
};
if (n==5) return function() {
g.reset();
g.setBgColor("#00a8ff");g.clear();
g.setFontAlign(0,0);
@ -111,8 +114,8 @@ var scenes = [
g.setFontAlign(-1,-1);
g.setFont("6x8",2);
g.drawString("Select menu\nitem\n\nLaunch app\nwhen watch\nis showing", 20,70);
},
function() {
};
if (n==6) return function() {
g.reset();
g.setBgColor("#00a8ff");g.clear();
g.setFontAlign(0,0);
@ -121,8 +124,8 @@ var scenes = [
g.setFontAlign(-1,-1);
g.setFont("6x8",2);
g.drawString("Move down\nin menus\n\nLong press\nto exit app\nand go back\nto clock", 20,100);
},
function() {
};
if (n==7) return function() {
g.reset();
g.setBgColor("#ff3300");g.clear();
g.setFontAlign(0,0);
@ -132,8 +135,8 @@ var scenes = [
g.setFontAlign(-1,-1);
g.setFont("6x8",2);
g.drawString("If Bangle.js\never stops,\nhold buttons\n1 and 2 for\naround six\nseconds.\n\n\n\nBangle.js will\nthen reboot.", 20,20);
},
function() {
};
if (n==8) return function() {
g.reset();
g.setBgColor("#00a8ff");g.clear();
g.setFont("6x8",2);
@ -150,8 +153,8 @@ var scenes = [
g.drawString("work too. Try now",x,y+=h);
g.drawString("to change page.",x,y+=h);}
],300);
},
function() {
};
if (n==9) return function() {
g.reset();
g.setBgColor("#339900");g.clear();
g.setFont("6x8",2);
@ -168,8 +171,8 @@ var scenes = [
g.drawString("with a Bluetooth",x,y+=h);
g.drawString("capable device",x,y+=h);},
],400);
},
function() {
};
if (n==10) return function() {
g.reset();
g.setBgColor("#990066");g.clear();
g.setFont("6x8",2);
@ -182,6 +185,7 @@ var scenes = [
g.drawString("banglejs.com",x,y+=h);
var rx = 0, ry = 0;
E.defrag(); // rearrange memory to ensure we have space
var h = Graphics.createArrayBuffer(96,96,1,{msb:true});
// draw a cube
function draw() {
@ -230,8 +234,8 @@ var scenes = [
}
setInterval(draw,50);
},
function() {
};
if (n==11) return function() {
g.reset();
g.setBgColor("#660099");g.clear();
g.setFontAlign(0,0);
@ -248,20 +252,18 @@ var scenes = [
g.drawString("Bangle.js",x,y+=h);}
],400);
}
];
}
var sceneNumber = 0;
function move(dir) {
if (dir>0 && sceneNumber+1 == scenes.length) return; // at the end
sceneNumber = (sceneNumber+dir)%scenes.length;
if (dir>0 && sceneNumber+1 == SCENE_COUNT) return; // at the end
sceneNumber = (sceneNumber+dir)%SCENE_COUNT;
if (sceneNumber<0) sceneNumber=0;
clearInterval();
Bangle.setLCDMode();
g.clear();
scenes[sceneNumber]();
getScene(sceneNumber)();
if (sceneNumber>2) {
var l = scenes.length;
var l = SCENE_COUNT;
for (var i=0;i<l-2;i++) {
var x = 120+(i-(l-2)/2)*12;
if (i<sceneNumber-1) {
@ -275,7 +277,7 @@ function move(dir) {
}
}
}
if (sceneNumber < scenes.length-1)
if (sceneNumber < SCENE_COUNT-1)
setTimeout(function() {
move(1);
}, (sceneNumber==0) ? 20000 : 5000);

View File

@ -6,3 +6,4 @@
0.06: Improve rendering of Numeral 1, fix issue with alarms not showing up
0.07: Add date on touch and some improvements (see settings and readme)
0.08: Add new draw styles, tidy up draw functionality
0.09: Tweak for faster rendering

View File

@ -22,16 +22,17 @@ var _12hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"]||fal
var _hCol = ["#ff5555","#ffff00","#FF9901","#2F00FF"];
var _mCol = ["#55ff55","#ffffff","#00EFEF","#FFBF00"];
var _rCol = 0;
var scale = g.getWidth()/240;
var interval = 0;
const REFRESH_RATE = 10E3;
var drawFuncs = {
fill : function(poly,isHole){
if (isHole) g.setColor(0);
if (isHole) g.setColor(g.theme.bg);
g.fillPoly(poly,true);
},
framefill : function(poly,isHole){
var c = g.getColor();
g.setColor(isHole ? 0 : ((c&0b1111011111011110)>>1)); // 16 bit half bright
g.setColor(isHole ? g.theme.bg : ((c&0b1111011111011110)>>1)); // 16 bit half bright
g.fillPoly(poly,true);
g.setColor(c);
g.drawPoly(poly,true);
@ -48,7 +49,8 @@ var drawFuncs = {
};
function translate(tx, ty, p){
return p.map((x, i)=> x+((i&1)?ty:tx));
//return p.map((x, i)=> x+((i&1)?ty:tx));
return g.transformVertices(p, {x:tx,y:ty,scale:scale});
}
@ -57,15 +59,14 @@ if (!settings) {
settings = {
color:0,
drawMode:"fill",
menuButton:24,
showDate:0
};
}
function drawNum(num,col,x,y,func,funcName){
g.setColor(col);
let tx = x*100+25;
let ty = y*104+32;
let tx = (x*100+25) * scale;
let ty = (y*104+32) * scale;
for (let i=0;i<numerals[num].length;i++){
g.setColor(col);
func(translate(tx,ty,numerals[num][i]), i>0);
@ -98,9 +99,9 @@ function setUpdateInt(set){
if (set) interval=setInterval(draw, REFRESH_RATE);
}
Bangle.setLCDMode();
g.reset().clear();
setWatch(Bangle.showLauncher, settings.menuButton, {repeat:false,edge:"falling"});
g.clear(1);
// Show launcher when button pressed
Bangle.setUI("clock");
if (settings.color>0) _rCol=settings.color-1;
setUpdateInt(1);
draw();

View File

@ -6,14 +6,12 @@
numeralsSettings = {
color:0,
drawMode:"fill",
menuButton:22,
showDate:0
};
updateSettings();
}
let numeralsSettings = storage.readJSON('numerals.json',1);
if (!numeralsSettings) resetSettings();
if (numeralsSettings.menuButton===undefined) numeralsSettings.menuButton=22;
let dm = ["fill","frame","framefill","thickframe"];
let col = ["rnd","r/g","y/w","o/c","b/y"];
let btn = [[24,"BTN1"],[22,"BTN2"],[23,"BTN3"],[11,"BTN4"],[16,"BTN5"]];
@ -31,12 +29,6 @@
format: v=>dm[v],
onchange: v=> { numeralsSettings.drawMode=dm[v]; updateSettings();}
},
"Menu button": {
value: btn.findIndex(e=>e[0]==numeralsSettings.menuButton),
min:0,max:btn.length-1,
format: v=>btn[v][1],
onchange: v=> { numeralsSettings.menuButton=btn[v][0]; updateSettings();}
},
"Date on touch": {
value: 0|numeralsSettings.showDate,
min:0,max:1,

View File

@ -3,3 +3,6 @@
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

View File

@ -34,7 +34,7 @@ Bangle.on('GPS',function(f) {
g.drawString(txt,120,y1 + 4);
drawMarker();
});
Bangle.setGPSPower(1);
Bangle.setGPSPower(1, "app");
if (HASWIDGETS) {
Bangle.loadWidgets();
@ -49,9 +49,25 @@ if (HASWIDGETS) {
redraw();
setWatch(function() {
function recenter() {
if (!fix.fix) return;
m.lat = fix.lat;
m.lon = fix.lon;
redraw();
}, BTN2, {repeat:true});
}
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();
}
});

View File

@ -32,6 +32,7 @@
<div id="map">
</div>
<div id="controls">
<div style="display:inline-block;text-align:center;vertical-align: top;"> <input type="checkbox" id="3bit"></input><br/><span>3 bit</span></div>
<button id="getmap" class="btn btn-primary">Get Map</button><br/>
<canvas id="maptiles" style="display:none"></canvas>
<div id="uploadbuttons" style="display:none"><button id="upload" class="btn btn-primary">Upload</button>
@ -55,9 +56,10 @@ TODO:
* What is faster? Storing as a compressed image and decompressing, or storing decompressed?
*/
var TILESIZE = 64;
var OSMTILESIZE = 256;
var OSMSUBTILES = OSMTILESIZE / TILESIZE;
var TILESIZE = 96; // Size of our tiles
var OSMTILESIZE = 256; // Size of openstreetmap tiles
var MAPSIZE = TILESIZE*5; ///< 480 - Size of map we download
var OSMTILECOUNT = 3; // how many tiles do we download in each direction (Math.floor(MAPSIZE / OSMTILESIZE)+1)
/* Can see possible tiles on http://leaflet-extras.github.io/leaflet-providers/preview/
However some don't allow cross-origin use */
var TILELAYER = 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'; // simple, high contrast
@ -74,7 +76,17 @@ TODO:
tileLayer.addTo(map);
function tilesLoaded(ctx, width, height) {
var options = { compression:true, mode:"web", output:"string"};
var options = {
compression:false, output:"raw",
mode:"web"
};
if (document.getElementById("3bit").checked) {
options = {
compression:false, output:"raw",
mode:"3bit", brightness:-64,
};
}
console.log("Compression options", options);
var w = Math.round(width / TILESIZE);
var h = Math.round(height / TILESIZE);
var tiles = [];
@ -92,8 +104,7 @@ TODO:
imgstr = imgstr.slice(compress.length,-1);*/
tiles.push({
name:"openstmap-"+x+"-"+y+".img",
content:imgstr,
evaluate:true
content:imgstr
});
}
}
@ -114,10 +125,10 @@ TODO:
var canvas = document.getElementById("maptiles");
canvas.style.display="";
var ctx = canvas.getContext('2d');
canvas.width = OSMTILESIZE*2;
canvas.height = OSMTILESIZE*2;
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
canvas.width = MAPSIZE;
canvas.height = MAPSIZE;
for (var i = 0; i < OSMTILECOUNT; i++) {
for (var j = 0; j < OSMTILECOUNT; j++) {
(function(i,j){
var coords = new L.Point(center.x+i-1, center.y+j-1);
coords.z = zoom;

View File

@ -45,15 +45,12 @@ exports.draw = function() {
for (var y=oy,tty=ty;y<g.getHeight();y+=map.tilesize,tty++) {
var img = s.read("openstmap-"+ttx+"-"+tty+".img");
if (img) g.drawImage(img,x,y);
else {
g.clearRect(x,y,x+map.tilesize-1,y+map.tilesize-1);
g.drawLine(x,y,x+map.tilesize-1,y+map.tilesize-1);
g.drawLine(x,y+map.tilesize-1,x+map.tilesize-1,y);
}
else g.clearRect(x,y,x+map.tilesize-1,y+map.tilesize-1).drawLine(x,y,x+map.tilesize-1,y+map.tilesize-1).drawLine(x,y+map.tilesize-1,x+map.tilesize-1,y);
}
}
};
/// Convert lat/lon to pixels on the screen
exports.latLonToXY = function(lat, lon) {
var p = Bangle.project({lat:m.lat,lon:m.lon});
var q = Bangle.project({lat:lat, lon:lon});
@ -64,3 +61,11 @@ exports.latLonToXY = function(lat, lon) {
y : cy - (q.y-p.y)*4096/map.scale
};
};
/// Given an amount to scroll in pixels on the screen, adjust the lat/lon of the map to match
exports.scroll = function(x,y) {
var a = Bangle.project({lat:this.lat,lon:this.lon});
var b = Bangle.project({lat:this.lat+1,lon:this.lon+1});
this.lon += x * this.map.scale / ((a.x-b.x) * 4096);
this.lat -= y * this.map.scale / ((a.y-b.y) * 4096);
};

View File

@ -1,3 +1,4 @@
0.01: New Watch!
0.02: Changed colors for better readability and added current date
0.03: Added Info to HP (day in year) and LEVEL (day of week / progress bar show day progress)
0.04: Using setUI, portable colors

View File

@ -1,9 +1,9 @@
const bigFont = 4;
const smallFont = 2;
const tinyFont = 1;
const green = 0x0661;
const darkGreen = 0x0461;
const darkerGreen = 0x0261;
const green = "#0d1";
const darkGreen = "#091";
const darkerGreen = "#051";
const pip = require("heatshrink").decompress(atob("klQyAlihNhgNhNP5FC0MjokboUJ8JC64ABBgNAjdDifiikhjfjjekjcDgOhImMKoUbscTsUbwUT4QBC8UMkMMgUT8MLwcBS8/hiNiIo2DhkBgkhhfhHoMT0MT0RLBjYJCCIMTocBUoIAiiIvBgcKsMSG4KLChY1CjckgUhgOAhJDBocL4RTBAYMT0ZJliS9BwUDQIchgWAhXCgVAgUghWhiXihWBgUAhdjhYTBkEB8ELkUTgcA8BHfgNAZ4MT8UTwcCJIOjikjihVB8QDBAIcToUSRYNDkdjjWDgOhjdjhVBI8EAgVBiXhQ4MTkcb4ZPCTILLBAYPBjZDBAIUL8QBBd4KRBWIMboZHfiPCOIMKsK5BR4XChkBAIUChkiheibYMT0RPBBoJZBgWgiRfD0RHfhMhhPhjcjhcBiQrBwSHBRocLRINCgUAhWBR4SZBsatCI4IRBsRHfAAMKkJBBhYBCgfBgZDBAYQFC0Q3BicCgehgbRBscKoMCkBlBjXiI8IxBifDgVAidDhfiIoMLkMUgUb4USQ4MiAoLlDiejgVhI4L3BjUjIr8BIILPBwUBwEa8YzBhQ/BoTLBjejgOgiTVEhkChdhiXCI4MB4MA8BHgsAxBjkDP4MjskTgZ3BTIMMkMb8cKLINCS4KPEcIMChWiK4LVhgJ5EAIJJBOoKTBbIQLB4I9BA4QJDCoOigZLBocJ8JHiwELGoPAgfghdCBIJ7BH4mhAYXAAYMDAIQNE0UKwJHioETwZ/C8cT0cS4UDgCBC4UTHIKjCiaNChfiB4SVDoUA4BJhicjhVgjeEjfDifiikCiZPBwUS4MB4ES0Ub4UUgMMgJDBAYJTBiXjIsIABiPiaIK5BgWggXhhXhgQJB4Mi8kakRJBHoJHDLIViiWCWYJHjhNBhWCHoMK0MbgkbkkTgYHBKYMTgUC4DVCcYUbscB8BDjAArFBOoKLCoECgADBaoMToUTsMLwML0MLBIUJ4JFpAAK3BidDhfiQIXCQIIBBRIcEgJFC0UKoJFrbYnBjeDibHBAIUMgIFC8QBC4UKsEA8EZ4cRJd0BwDPC8Y/BI4IBBR4IHBheijXkgOBjcCjcDVoJHriUiiWigVhiY3BS4PBI4JLCwcKkUK0UMgULwSrBiPBRtEhidDQII3BgMgPoMKgRRBhVhgPAiWBieCiehhQBBoKpBJYJFjiPihPhhdChfBieiGIMKwEKkI5BJIMTsUL4UL4afBgUgidjBIMbscJsBFfhOhjdDicigUAhWBYYMT8MT4QBHcIMCwIVBU4TnCMIMbgarBaLkgIoML8UT8Q1BiViYYI/DikCAoRXCgOAiWCCoIbBAIRHBEIPjBoJHbiR7D8UMgQ9BIoMKbIIJCAIMLkMSoSjCIYUMgIBECYIFCKYL/BIq8KgMTwRtBXIcL0UKsELRIIJBBYUCwEK4UL4UD4MDCoPgCIITEEIYJBgUBsLTUsMTka1DAIS3B0UCoETQYIvCT4MKoLXBH4QXCAYIBDEInhSIIZCsTTUsQZBNIXigkBGIVjgUhZIQ7DTIIPBoSHESoRDFAIYlBT4MToUBkCNQsETsRFBgaFBAoPhEIUiR4WiB4QxBwK+BhYTCZojPDAIYJCgfgAoRjBkKNQ0UTZoLVBgMKOYPihiLBoYhBToQJBXocALYbTEEIJHFE4IJCUYQFBkUA8CNMPoOCGIIBCoLPC4aPCsTNCBoIvD4MCkC/BHYrZEAoKTGdIQDB0UJ4KNMsR9CDYeCgR9BwZ9CsQHBGYhHB4RHGJIT1CNoTdGMIQnC0MSwSNKgEbobBBYYQXCgQrBkYpCJ4T9BI4sKkELoQzEMoKtB0BhBQYKnCT4Z5EjdCHoIAHTYIbBZYIBBDIWihWBhWhhYBBI4UDsJPCDIOhI4TjBD4PBAIJ9C8SdCkQdBBYIbCEoITDwUJ0JHHhTLBe4xPBhUigVBA4TNBoIhBA4KjC8RZBhcCDoKvDC4cTgUCkMbwgPDXoIfDikCiWBIw3ggOAidjI4ZFBiXCBoWgS4JHEoRZDBYMK4MKB4Q1BI4YDC4USsUKAoOjF4TrCAIcbkSNGoQZCeoODFYMboZRBB4LvBicjjeDCoMLoSBER4PhhWCV4StDJ4UbscSkQhBiXjjZJCLIsTsUBsBHDGoWChVhgUBhVBiPiLAnAhPgB4MJNoLJCQoJHBichTYWjAIJXBKIMCsMKkLHBjWDhOhOYJHFLocB8A0BhNhLYMLwJTBjUjiPChNBIwYFBjXjiXhiVha4RLB4ADBDYMCkEB4ABCLoQZBCoL9BjcjfoILBDIMD8AhCAISBBGoMR0USDIIbCEoMS0ZlBI4cBIINjhkCNIXiOIZzCZoODc4IBBSYQJBCYUT4cTgcA0DLBieCBYTXCAoMSwZHCwSJBV4JJBN4MST4Mga4ngY4MLoMbGYJrDW4QtC4RLBAIRDBE4INB0UKOYNggEhgFgiWiCYQPB8BPBhUCYoTRBokCwEbskJ4KzBhUia4j/B4cCsC3CgKlBAIXCKIQvCIIIvBjcidoJvCkMa8UBgMAdYPBjahCjbPB8MKGYQ3BjUDgPhjcEhUhiWhV4MJwTXCsDDCBYMCiVjhUBTIL7BKIIBBgVAhQ3B4BDCOoPjDoa5CB4MAhWCGYI3BEoMjkkSoQ3CoMSkZJBgPgNYITBhIPDoELwUDV4PBidjidDiXihXChWBF4IxCSYMCidihehhfAgfADIL7Ba4JBCwMCDYInBoTZCoDJDiNikXkiQpBoUZ8YNDM4MLsUD8EEgAvBGYI3CHIgNBAIYVBC4cL4T3BEYKZBjdjNYIBBCYYjBWII5DAAMJ0MawbjDAAnAjcje4MLSIPiGIJrBegMTOIPhB4IFEAIITBBYUCgMSAIKDBgKLC0ULsJFBWoMJ4I7GABgXBFYMMgIBBJILNBXYMT0JDBHoTpCLYQDD4USW4gnCI4NhhSzBkMSwcBR4wANhViI4aRDV4MKKYRDBBogBEJ4RdCf4sTgUTIYJpBoMRwRFTcocTsR7E0UCkELgQHCAJo5CI4lgI4MCoMasZPBADHgbIIxEwUCgELkQHC0BDHgYDB0IBBgPhNosa4cBkEA4BGZbIUiieiYYWjgPgTIwBKieCRIIjDZoMR4ZDbWYmAidCI41jA4RJBAI6nBBoNiV4I/fABMSwUb4RHDjejikCAJphBI9cBoETGINigUAhbfBapkL4UK4UJ4MKDAIAohOgjXjgUgheBhfAgY9B0IBBAoIHCAIOihVCiXCiXDI9JJCwMCgKPCI4YBIieCgPhicjjWEI9YABhUhY4I9C8JDEAoIBCdYJHCLwJGtI4NCikDikCAIsMAIUT8RDBCYMbwapBR+iRFRoeihVhhWhdYMS0RHtgUhgY1B0EDAIPAAoQDB4MToUCgELgMDA4MiR+sDR4Q9BBIUhgPgieCgYDBoRHwaYoBD8DPDa4IJBhkAiXjI91BifihkCifhAoMUgUMgMb4cKgMSsQNBhkhJ4JHugKNCIoIBCA4cbocBsEJ4MT0RVBgUBI9sJHoOhaIQDB4EDBIUSsITDjWjkcjgMgI9sB4BHEAIPgSoVihOhLYkBiNCItpHC0CLDAYMDI4OijXjHt5HKwET4cL8UTAIPjiciTYMI8BH4gES4ULkcS8USkUJ8AJBiTPwAA8KsUKsMCoECsMK0MTgUTsZH1hPhhdChaNB4MT0RBC4cKTINCgMgImGghPihdigfBgeggfAhehhXBgHAZ+qLCwULAYPCiaNBoTbBgNAIuoABiOiiQBB0LJBhUhgKLBAEgA=="));
function isLeapYear(year)
@ -37,16 +37,16 @@ function bottomLine() {
var yy = today.getFullYear();
var day = today.getDay(); //day of week as number
var h = today.getHours();
var startDate = new Date(yy, 0, 0);
var oneDay = 1000 * 60 * 60 * 24;
var daysInYear = 0;
var diff = today - startDate;
var currDayInYear = Math.floor(diff / oneDay);
if (isLeapYear(yy)) daysInYear = 366;
else daysInYear = 365;
g.setFont("6x8", tinyFont);
//first line
@ -55,7 +55,7 @@ function bottomLine() {
g.fillRect(105, 175, 160, 185);//STIM
g.fillRect(166, 175, 239, 185); // RADAWAY
g.setColor(green);
g.drawString("DATE", 20, 177);
g.drawString("STIM (3)", 135, 177);
g.drawString("RADAWAY (8)", 205, 177);
@ -84,7 +84,7 @@ function drawClock() {
var mm = t.getMonth()+1; //month is zero-based
var yy = t.getFullYear();
var time = ("0" + h).substr(-2) + ":" + ("0" + m).substr(-2);
//create date string
if (dd.toString().length < 2) dd = '0' + dd;
if (mm.toString().length < 2) mm = '0' + mm;
@ -114,9 +114,9 @@ Bangle.on('lcdPower', function(on) {
});
g.clear();
// Show launcher when button pressed
Bangle.setUI("clock");
Bangle.loadWidgets();
Bangle.drawWidgets();
setInterval(drawClock, 1E4);
drawAll();
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});

0
apps/rpgdice/ChangeLog Executable file → Normal file
View File

0
apps/rpgdice/app-icon.js Executable file → Normal file
View File

0
apps/rpgdice/app.js Executable file → Normal file
View File

0
apps/rpgdice/rpgdice.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -1,2 +1,3 @@
0.01: New App!
0.02: Tweaks for Q3 watch
0.03: setUI

View File

@ -34,8 +34,7 @@ Bangle.on('lcdPower', function(on) {
g.clear();
var secondInterval = setInterval(draw, 1000);
draw();
// Show launcher when button pressed
Bangle.setUI("clock");
Bangle.loadWidgets();
Bangle.drawWidgets();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});

View File

@ -1,3 +1,4 @@
0.02: Modified for use with new bootloader and firmware
0.03: Actually make into 24h clock since there's a 12h variant
0.04: Make this clock do 12h and 24h
0.05: setUI, screen size changes

View File

@ -1,14 +1,15 @@
/* jshint esversion: 6 */
const timeFontSize = 6;
const dateFontSize = 3;
const big = g.getWidth()>200;
const timeFontSize = big?6:5;
const dateFontSize = big?3:2;
const gmtFontSize = 2;
const font = "6x8";
const xyCenter = g.getWidth() / 2;
const yposTime = 75;
const yposDate = 130;
const yposYear = 175;
const yposGMT = 220;
const yposTime = xyCenter*0.6;
const yposDate = xyCenter*1.1;
const yposYear = xyCenter*1.4;
const yposGMT = xyCenter*1.9;
// Check settings for what type our clock should be
var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"];
@ -77,5 +78,5 @@ setInterval(drawSimpleClock, 15E3);
// draw now
drawSimpleClock();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"});
// Show launcher when button pressed
Bangle.setUI("clock");

0
apps/sclock/clock-simple.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 590 B

After

Width:  |  Height:  |  Size: 590 B

0
apps/scolor/show-color.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 237 B

After

Width:  |  Height:  |  Size: 237 B

1
apps/thermom/app-icon.js Normal file
View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwYurgP/8AROh///gROv///+ACOtJkARhI/5H/I98SpMkwMkCZgRUGqJH/I/5HeyQRByAQMggRCyQRMBwIRCoARcgIREpAR/CMiPjYqTpRgECCIIQNADo="))

28
apps/thermom/app.js Normal file
View File

@ -0,0 +1,28 @@
function onTemperature(p) {
g.reset(1).clearRect(0,24,g.getWidth(),g.getHeight());
g.setFont("6x8",2).setFontAlign(0,0);
var x = g.getWidth()/2;
var y = g.getHeight()/2 + 10;
g.drawString("Temperature", x, y - 45);
g.setFontVector(70).setFontAlign(0,0);
g.drawString(p.temperature.toFixed(1), x, y);
}
function drawTemperature() {
if (Bangle.getPressure) {
Bangle.getPressure().then(onTemperature);
} else {
onTemperature({
temperature : E.getTemperature()
});
}
}
setInterval(function() {
drawTemperature();
}, 20000);
drawTemperature();
E.showMessage("Loading...");
Bangle.loadWidgets();
Bangle.drawWidgets();

BIN
apps/thermom/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 B

View File

@ -1,2 +1,3 @@
0.01: First commit
0.02: Made Date more visible
0.03: setUI and support for different screens

View File

@ -4,8 +4,9 @@ require("Font7x11Numeric7Seg").add(Graphics);
// Check settings for what type our clock should be
var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"];
// position on screen
const X = 160, Y = 140;
const big = g.getWidth()>200;
const X = big?160:135, Y = big?140:100;
function draw() {
// work out how to display the current time
var d = new Date();
@ -25,13 +26,13 @@ function draw() {
g.setFont("7x11Numeric7Seg",2);
g.drawString(("0"+d.getSeconds()).substr(-2), X+35, Y, true /*clear background*/);
// draw the date, in a normal font
g.setFont("6x8", 3);
g.setFont("6x8", big?3:2);
g.setFontAlign(0,1); // align center bottom
// pad the date - this clears the background if the date were to change length
var dateStr = " "+require("locale").date(d)+" ";
g.drawString(dateStr, g.getWidth()/2, Y+35, true /*clear background*/);
}
// Clear the screen once, at startup
g.clear();
// draw immediately at first
@ -46,12 +47,15 @@ Bangle.on('lcdPower',on=>{
draw(); // draw immediately
}
});
// Show launcher when button pressed
Bangle.setUI("clockupdown", btn=>{
if (btn==0) vibrateTime();
});
// Load widgets
Bangle.loadWidgets();
Bangle.drawWidgets();
// Show launcher when middle button pressed
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
// ====================================== Vibration
// vibrate 0..9
function vibrateDigit(num) {
@ -74,24 +78,21 @@ function vibrateNumber(num) {
});
});
}
var vibrateBusy;
function vibrateTime() {
if (vibrateBusy) return;
vibrateBusy = true;
var d = new Date();
var hours = d.getHours(), minutes = d.getMinutes();
if (is12Hour) {
if (hours == 0) hours = 12;
else if (hours>12) hours -= 12;
}
vibrateNumber(hours.toString()).
then(() => new Promise(resolve=>setTimeout(resolve,500))).
then(() => vibrateNumber(minutes.toString())).
then(() => vibrateBusy=false);
}
// when BTN1 pressed, vibrate
setWatch(vibrateTime, BTN1, {repeat:true,edge:"rising"});

View File

@ -1 +1,2 @@
0.02: Modified for use with new bootloader and firmware
0.03: setUI and support for different screens

Some files were not shown because too many files have changed in this diff Show More