Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grandfather Clock Widget #3724

Merged
merged 21 commits into from
Feb 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions apps/grandfatherclock/ChangeLog
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
0.01: New Widget!
0.02: rename, new icon, settings menu!
26 changes: 26 additions & 0 deletions apps/grandfatherclock/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Grandfather Clock

A widget that runs in the background and chimes on every (configurable) fraction of an hour, similar to Chimer, and counts out the fractions and the o'clock hour.

## Usage

Once installed, see the App Settings page for options.

Defaults:
- Twelve hour mode is ENABLED.
- Swap meridian is DISABLED. (in the AM, there will be a single buzz after counting the hours. in the PM, there will be two buzzes after counting the hours)
- The attention buzz for the hour chime is 1000ms long.
- The buzz for each hour count is 250ms long.
- The buzz for each fraction count is 250ms long.
- The widget will count out 4 fractions of an hour (a 15 min interval).
- The time between count buzzes is 500ms.
- The meridian buzzes are 50ms long.
- The time between meridian buzzes is 300ms.

## Requests

Drop me a message at @yogsoy on Discord if you need help / discover a bug that I can squash for you.

## Creator

Written by June B (yogsoy), inspired by aaronrolls' Chimer.
Binary file added apps/grandfatherclock/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions apps/grandfatherclock/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{ "id": "grandfatherclock",
"name": "Grandfather Clock Widget",
"shortName":"Grandfather Clock",
"version":"0.02",
"description": "A widget that chimes every fraction of an hour (similar to Chimer), and counts out the fractions and the o'clock hour.",
"icon": "icon.png",
"type": "widget",
"tags": "widget",
"supports" : ["BANGLEJS2"],
"readme": "README.md",
"storage": [
{"name":"grandfatherclock.wid.js","url":"widget.js"},
{"name":"grandfatherclock.settings.js","url":"settings.js"}
],
"data": [
{"name":"grandfatherclock.json"}
]
}
89 changes: 89 additions & 0 deletions apps/grandfatherclock/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
(function(back) {

const configFile = "grandfatherclock.json";

let config = Object.assign({
draw_widget: true,
twelve_hour: true,
swap_meridian: false,
hour_attention_buzz_ms: 1000,
hour_count_buzz_ms: 250,
fraction_count_buzz_ms: 250,
fractions_of_hour: 4, // 4 = 15min intervals, 6 = 10min intervals
wait_ms: 500,
meridian_buzz_ms: 50,
meridian_buzz_wait_ms: 300
}, require('Storage').readJSON("grandfatherclock.json", true) || {});

let writeConfig = function() {
require('Storage').writeJSON(configFile, config);
};

E.showMenu({
"": {"title" : "Grandfather Clock"},
"< Back": () => back(),
"Draw widget": {
value: config.draw_widget,
onchange: v => {
config.draw_widget = v;
writeConfig();
}
},
"12 hour": {
value: config.twelve_hour,
onchange: v => {
config.twelve_hour = v;
writeConfig();
}
},"Swap meridian": {
value: config.swap_meridian,
onchange: v => {
config.swap_meridian = v;
writeConfig();
}
},"Hr attn. buzz length (ms)": {
value: config.hour_attention_buzz_ms,
onchange: v => {
config.hour_attention_buzz_ms = v;
writeConfig();
}
},"Hr count buzz (ms)": {
value: config.hour_count_buzz_ms,
onchange: v => {
config.hour_count_buzz_ms = v;
writeConfig();
}
},"Frac. count buzz (ms)": {
value: config.fraction_count_buzz_ms,
onchange: v => {
config.fraction_count_buzz_ms = v;
writeConfig();
}
},"Fracs. of hour": {
value: config.fractions_of_hour,
onchange: v => {
config.fractions_of_hour = v;
writeConfig();
}
},"Count wait (ms)": {
value: config.wait_ms,
onchange: v => {
config.wait_ms = v;
writeConfig();
}
},"Meridian buzz (ms)": {
value: config.meridian_buzz_ms,
onchange: v => {
config.meridian_buzz_ms = v;
writeConfig();
}
},"Meridian wait (ms)": {
value: config.meridian_buzz_wait_ms,
onchange: v => {
config.meridian_buzz_wait_ms = v;
writeConfig();
}
}
});

})
81 changes: 81 additions & 0 deletions apps/grandfatherclock/widget.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
(() => {

// sensible defaults
let config = Object.assign({
draw_widget: true,
twelve_hour: true,
swap_meridian: false,
hour_attention_buzz_ms: 1000,
hour_count_buzz_ms: 250,
fraction_count_buzz_ms: 250,
fractions_of_hour: 4, // 4 = 15min intervals, 6 = 10min intervals
wait_ms: 500,
meridian_buzz_ms: 50,
meridian_buzz_wait_ms: 300
}, require('Storage').readJSON("grandfatherclock.json", true) || {}); // or, load the app settings file.

WIDGETS["grandfatherclock"] = {
area: "tr",
width: config.draw_widget ? 16 : 0,
draw: function() {
if (config.draw_widget) {
g.reset();
g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y);
}
}
};

let date;
let fractionMs = 3600000 / config.fractions_of_hour;

let chime = function () {
date = new Date();
let hourFrac = Math.floor(date.getMinutes() / (60 / config.fractions_of_hour));

if (hourFrac == 0) { // if it's an o'clock hour
let chimeHour = (config.twelve_hour ? date.getHours() % 12 : date.getHours());
if (chimeHour == 0) (config.twelve_hour ? chimeHour += 12 : chimeHour += 24);

Bangle.buzz(config.hour_attention_buzz_ms).then(() => { // initial buzz
setTimeout(hourChime, config.wait_ms, chimeHour); // wait a period before doing the first chime
});
} else { // if it's a fraction of an hour
fractionChime(hourFrac);
}

queueNextChime();
};

let hourChime = function (hoursLeftToChime) {
hoursLeftToChime--;
Bangle.buzz(config.hour_count_buzz_ms).then(() => { // recursive. buzz and wait to do the next buzz.
if (hoursLeftToChime > 0) {
setTimeout(hourChime, config.wait_ms, hoursLeftToChime);
} else if (config.twelve_hour) { // once finished with the hour count
setTimeout(meridianChime, config.wait_ms, (date.getHours() >= 12)); // if in twelve hour mode, queue up the meridian chime.
}
});
};

let fractionChime = function (fractionsLeftToChime) {
fractionsLeftToChime--;
Bangle.buzz(config.fraction_count_buzz_ms).then(() => { // recursive. buzz and wait to do the next buzz.
if (fractionsLeftToChime > 0) setTimeout(fractionChime, config.wait_ms, fractionsLeftToChime);
});
};

let meridianChime = function (meridian) {
if ((config.swap_meridian ? !meridian : meridian)) { // default: if PM
Bangle.buzz(config.meridian_buzz_ms).then(setTimeout(Bangle.buzz, config.meridian_buzz_wait_ms, config.meridian_buzz_ms)); // buzz once, wait, buzz again.
} else { // default: if AM
Bangle.buzz(config.meridian_buzz_ms); // buzz once.
}
};

let queueNextChime = function () {
let msUntilNextFraction = fractionMs - (Date.now() % fractionMs);
setTimeout(chime, msUntilNextFraction);
};

queueNextChime();
})()