Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/mtnclock/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
0.04: Adding settings and the ability to show the widgets bar
0.05: Fix the widgets disappearing on weather update
0.06: Fix weather not correctly updating with Weather data v2
0.07: Add clockinfo slots
46 changes: 25 additions & 21 deletions apps/mtnclock/README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
# Mountain Pass Clock

Based on the Pebble watchface Weather Land.

Mountain Pass Clock changes depending on time (day/night) and weather conditions.

This clock requires Gadgetbridge and an app that Gadgetbridge can use to get the current weather from OpenWeatherMap (e.g. Weather Notification), or a Bangle app that will update weather.json such as OWM Weather. To set up Gadgetbridge and weather, see https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather.

The scene will change according to the following OpenWeatherMap conditions: clear, cloudy, overcast, lightning, drizzle, rain, fog and snow. Each weather condition has night/day scenes.

If you choose not to set up weather (or are not connected to Gadgetbridge, for that matter), this clock will default to clear weather, and the scenery will still change from night to day.

Special thanks to Serj for testing this on the original Bangle.

## Images

![](screenshot1.png)
![](screenshot2.png)
![](screenshot3.png)
![](screenshot4.png)
![](screenshot5.png)
# Mountain Pass Clock

Based on the Pebble watchface Weather Land.

Mountain Pass Clock changes depending on time (day/night) and weather conditions.

This clock requires Gadgetbridge and an app that Gadgetbridge can use to get the current weather from OpenWeatherMap (e.g. Weather Notification), or a Bangle app that will update weather.json such as OWM Weather. To set up Gadgetbridge and weather, see https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather.

The scene will change according to the following OpenWeatherMap conditions: clear, cloudy, overcast, lightning, drizzle, rain, fog and snow. Each weather condition has night/day scenes.

If you choose not to set up weather (or are not connected to Gadgetbridge, for that matter), this clock will default to clear weather, and the scenery will still change from night to day.

You can add up to three clockinfos under the time, date, and weather. Accessing the menu to do so is done by tapping, or long-tapping on the Bangle.js 2.

Special thanks to Serj for testing this on the original Bangle.

## Images

![](screenshot1.png)
![](screenshot2.png)
![](screenshot3.png)
![](screenshot4.png)
![](screenshot5.png)
![](screenshot6.png)
![](screenshot7.png)
206 changes: 121 additions & 85 deletions apps/mtnclock/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
var data = require("Storage").readJSON("mtnclock.json", 1) || {};

if (! Array.isArray(data.rows)) {
data.rows = [];
require("Storage").writeJSON("mtnclock.json", data);
}

let clockinfosMain = {};
let clockinfos = require("clock_info").load();

let weather;
try {
weather = require('weather');
Expand All @@ -9,17 +17,17 @@ try {

//seeded RNG to generate stars, snow, etc
function sfc32(a, b, c, d) {
return function() {
a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0;
var t = (a + b) | 0;
a = b ^ b >>> 9;
b = c + (c << 3) | 0;
c = (c << 21 | c >>> 11);
d = d + 1 | 0;
t = t + d | 0;
c = c + t | 0;
return (t >>> 0) / 4294967296;
};
return function() {
a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0;
var t = (a + b) | 0;
a = b ^ b >>> 9;
b = c + (c << 3) | 0;
c = (c << 21 | c >>> 11);
d = d + 1 | 0;
t = t + d | 0;
c = c + t | 0;
return (t >>> 0) / 4294967296;
};
}

//scale x, y coords to screen
Expand Down Expand Up @@ -79,12 +87,11 @@ function drawSnow(color, coord, size) {
}

function draw(color) {
var seed;
var rand;

var seed;
var rand;

g.clear();
//background
g.clear();
//background
g.setColor(color.bg1).fillRect(
px(0),py(0),
px(100),py(45)
Expand All @@ -96,28 +103,28 @@ g.clear();
//lightning
if (color.ltn) {
g.setColor(color.ltn).fillPoly([
px(70),py(20),
px(60),py(28),
px(71),py(29),
px(63),py(40),
px(75),py(28),
px(64),py(27)
px(70),py(20),
px(60),py(28),
px(71),py(29),
px(63),py(40),
px(75),py(28),
px(64),py(27)
]);
g.fillPoly([
px(40),py(20),
px(30),py(28),
px(41),py(29),
px(33),py(40),
px(45),py(28),
px(34),py(27)
px(40),py(20),
px(30),py(28),
px(41),py(29),
px(33),py(40),
px(45),py(28),
px(34),py(27)
]);
}
//stars
if (color.star) {
seed = 4;
rand = sfc32(0x9E3779B9, 0x243F6A88, 0xB7E15162, seed);
for (let i = 0; i < 40; i++) {
g.setColor(color.star).drawCircle(Math.floor(rand() * px(100)),Math.floor(rand() * py(33)),Math.floor(rand() * 2));
g.setColor(color.star).drawCircle(Math.floor(rand() * px(100)),Math.floor(rand() * py(33)),Math.floor(rand() * 2));
}
}
//birds
Expand Down Expand Up @@ -167,7 +174,7 @@ g.clear();
}
}
//mountains
drawMtn({mtn1:color.mtn2, mtn2:color.mtn1}, {x:px(35), y:py(30)}, {w:px(38), h:py(17)});
drawMtn({mtn1:color.mtn2, mtn2:color.mtn1}, {x:px(43), y:py(28)}, {w:px(38), h:py(19)});
drawMtn({mtn1:color.mtn2, mtn2:color.mtn1}, {x:px(10), y:py(20)}, {w:px(50), h:py(30)});
drawMtn({mtn1:color.mtn1, mtn2:color.mtn2}, {x:px(90), y:py(20)}, {w:px(70), h:py(30)});
//lake
Expand Down Expand Up @@ -201,8 +208,25 @@ g.clear();

//clock text
(color.clock == undefined) ? g.setColor(0xFFFF) : g.setColor(color.clock);
g.setFont("Vector", py(20)).setFontAlign(-1, -1).drawString((require("locale").time(new Date(), 1).replace(" ", "")), px(2), py(67));
g.setFont("Vector", py(10)).drawString(require('locale').dow(new Date(), 1)+" "+new Date().getDate()+" "+require('locale').month(new Date(), 1)+((data.temp == undefined) ? "" : " | "+require('locale').temp(Math.round(data.temp-273.15)).replace(".0", "")), px(2), py(87));
const start = 87;
data.rows.forEach(function(row, r) {
let a = row.menuA;
let b = row.menuB;
if (clockinfos[a] && clockinfos[a].items[b]) {
let ci = clockinfos[a].items[b];
let text = ci.get().text;
if (!(clockinfosMain[a] && clockinfosMain[a][b])) {
clockinfosMain[a] = clockinfosMain[a] || {};
clockinfosMain[a][b] = true;
ci.show();
ci.on("redraw", clockinfoRedraw);
}
g.setFont("Vector", py(10)).setFontAlign(-1, -1).drawString(text, px(2), py((start - (data.rows.length - 1) * 10) + r * 10));
}
});

g.setFont("Vector", py(20)).setFontAlign(-1, -1).drawString((require("locale").time(new Date(), 1).replace(" ", "")), px(2), py(start - ((data.rows.length + 2)*10)));
g.setFont("Vector", py(10)).drawString(require('locale').dow(new Date(), 1)+" "+new Date().getDate()+" "+require('locale').month(new Date(), 1)+((data.temp == undefined) ? "" : " | "+require('locale').temp(Math.round(data.temp-273.15)).replace(".0", "")), px(2), py(start - data.rows.length * 10));

if (data.showWidgets) {
Bangle.drawWidgets();
Expand All @@ -216,27 +240,27 @@ function setWeather() {
if (new Date().getHours() >= 7 && new Date().getHours() <= 19) {
//day-clear
a = {
bg1:0x4FFF, bg2:0x03E0,
sun:0xFD20,
path:0x8200,
mtn1:0x045f, mtn2:0x000F,
lake:0x000F,
tree1:0x07E0, tree2:0, tree3:0x7BE0,
bird:0xFFFF
bg1:0x4FFF, bg2:0x03E0,
sun:0xFD20,
path:0x8200,
mtn1:0x045f, mtn2:0x000F,
lake:0x000F,
tree1:0x07E0, tree2:0, tree3:0x7BE0,
bird:0xFFFF
};
//day-cloudy
if (data.code == 801 || data.code == 802) a.cloud1 = 0xFFFF;
}
else {
//night-clear
a = {
bg1:0, bg2:0x0005,
sun:0xC618,
path:0,
mtn1:0x0210, mtn2:0x0010,
lake:0x000F,
tree1:0x0200, tree2:0, tree3:0x59E0,
star:0xFFFF
bg1:0, bg2:0x0005,
sun:0xC618,
path:0,
mtn1:0x0210, mtn2:0x0010,
lake:0x000F,
tree1:0x0200, tree2:0, tree3:0x59E0,
star:0xFFFF
};
//night-cloudy
if (data.code == 801 || data.code == 802) a.cloud1 = 0x4208;
Expand All @@ -246,12 +270,12 @@ function setWeather() {
if (new Date().getHours() >= 7 && new Date().getHours() <= 19) {
//day-overcast
a = {
bg1:0xC618, bg2:0x0200,
path:0x3000,
mtn1:0x3B38, mtn2:0x0005,
lake:0x000F,
tree1:0x03E0, tree2:0, tree3:0x59E0,
cloud1:0x7BEF, cloud2:1
bg1:0xC618, bg2:0x0200,
path:0x3000,
mtn1:0x3B38, mtn2:0x0005,
lake:0x000F,
tree1:0x03E0, tree2:0, tree3:0x59E0,
cloud1:0x7BEF, cloud2:1
};
//day-lightning
if (data.code >= 200 && data.code < 300) a.ltn = 0xFFFF;
Expand All @@ -263,12 +287,12 @@ function setWeather() {
else {
//night-overcast
a = {
bg1:0, bg2:0x0005,
path:0,
mtn1:0x0010, mtn2:0x000F,
lake:0x000F,
tree1:0x0200, tree2:0, tree3:0x59E0,
cloud1:0x4208, cloud2:1
bg1:0, bg2:0x0005,
path:0,
mtn1:0x0010, mtn2:0x000F,
lake:0x000F,
tree1:0x0200, tree2:0, tree3:0x59E0,
cloud1:0x4208, cloud2:1
};
//night-lightning
if (data.code >= 200 && data.code < 300) a.ltn = 0xFFFF;
Expand All @@ -282,50 +306,50 @@ function setWeather() {
if (new Date().getHours() >= 7 && new Date().getHours() <= 19) {
//day-fog
a = {
bg1:0xC618, bg2:0x0200,
path:0x3000,
mtn1:0x3B38, mtn2:0x0005,
lake:0x000F,
tree1:0x03E0, tree2:0, tree3:0x59E0,
fog:0xFFFF
bg1:0xC618, bg2:0x0200,
path:0x3000,
mtn1:0x3B38, mtn2:0x0005,
lake:0x000F,
tree1:0x03E0, tree2:0, tree3:0x59E0,
fog:0xFFFF
};
}
else {
//night-fog
a = {
bg1:0, bg2:0x0005,
path:0,
mtn1:0x0010, mtn2:0x000F,
lake:0x000F,
tree1:0x0200, tree2:0, tree3:0x59E0,
fog:0x7BEF
bg1:0, bg2:0x0005,
path:0,
mtn1:0x0010, mtn2:0x000F,
lake:0x000F,
tree1:0x0200, tree2:0, tree3:0x59E0,
fog:0x7BEF
};
}
}
else if ((data.code >= 600) && (data.code < 700)) {
if (new Date().getHours() >= 7 && new Date().getHours() <= 19) {
//day-snow
a = {
bg1:0, bg2:0x7BEF,
path:0xC618,
mtn1:0xFFFF, mtn2:0x7BEF,
lake:0x07FF,
tree1:0xC618, tree2:0xC618, tree3:0x59E0,
cloud1:0x7BEF, cloud2:1,
snow:0xFFFF,
clock: 0
bg1:0, bg2:0x7BEF,
path:0xC618,
mtn1:0xFFFF, mtn2:0x7BEF,
lake:0x07FF,
tree1:0xC618, tree2:0xC618, tree3:0x59E0,
cloud1:0x7BEF, cloud2:1,
snow:0xFFFF,
clock: 0
};
}
else {
//night-snow
a = {
bg1:0, bg2:0x0005,
path:0,
mtn1:0x0010, mtn2:0x000F,
lake:0x000F,
tree1:0x39E7, tree2:0x39E7, tree3:0x59E0,
cloud1:0x4208, cloud2:1,
snow:0xFFFF
bg1:0, bg2:0x0005,
path:0,
mtn1:0x0010, mtn2:0x000F,
lake:0x000F,
tree1:0x39E7, tree2:0x39E7, tree3:0x59E0,
cloud1:0x4208, cloud2:1,
snow:0xFFFF
};
}
}
Expand Down Expand Up @@ -372,6 +396,18 @@ global.GB = (event) => {
};

var drawTimeout;
var redrawTimeout;

function clockinfoRedraw() {
// Limit redraws to every second
if (!redrawTimeout) {
redrawTimeout = setTimeout(function() {
setWeather();
clearTimeout(redrawTimeout);
redrawTimeout = undefined;
}, 1000);
}
}

//update watchface in next minute
function queueDraw() {
Expand Down
Loading