mirror of https://github.com/espruino/BangleApps
Delete apps/suw directory
parent
4b60adbb73
commit
4d51eff081
|
@ -1,30 +0,0 @@
|
|||
# Seaside utility watch
|
||||
|
||||
A watch that does just what I want when I am at the seaside, showing day, date, month, year, sunrise, sunset, location and approximate high and low tide times.
|
||||
|
||||
Touch to toggle between sunrise / sunset and tide times.
|
||||
|
||||
Very much a work in progress. Sunrise/set requires location to have already been set in mylocation.json using MyLocation app.
|
||||
|
||||
DO NOT RELY ON THESE TIDE TIMES! This is in development.
|
||||
|
||||
When working, you will set the next tide time (high or low) in application settings, the watch will then calculate approximate next tide time by adding 6 hours and 12 minutes to the tide time and keep doing so until reset.
|
||||
|
||||
This may become very unreliable over time and will need periodic realignment.
|
||||
|
||||

|
||||

|
||||
|
||||
## Many faults
|
||||
|
||||
- [ ] bug fix to prevent cascading tide time flipping causes it to halt completely - tide time never updates
|
||||
- [ ] when watch closed and reloaded it reloads tide times from setting file which may be out of date - need to write new times to settings file when swapping occurs
|
||||
|
||||
|
||||
## Many of the to-dos
|
||||
|
||||
- [ ] handle tide time not being set and remove default time which is just for testing
|
||||
- [ ] write tide data back to json file when flipped to keep it up to date when app reloaded
|
||||
- [ ] tidy up code in general
|
||||
- [ ] no need to check sunrise and sunset times so often
|
||||
- [ ] consider a web app for setting next tide time or entering real data
|
|
@ -1 +0,0 @@
|
|||
require("heatshrink").decompress(atob("mEwhHXAH4A1wOBF9tRqImkvesBA1Xq4IG1l7F7dQKw4vIqNQF7emqBgGR4+sqGmSDlQPw17A45ecMBReleJTtc01RExgAR1lRNBh3BQ5ms02CwWmCBgfNbAhAHQYMmkweBqFKAoKbIaoKXRGAIdEFoNKqGkAAOp1Oj0eAGYIxFLoLGTDQmmFoXO5oAH0aGGbjAuBvXOFw+kvWp5movVKc5hiPFxQvBpUC0fM5gwBLjHX6IuB56MJGIXN1PNGANQ6KDO02teRBdJAAtQvXMYYLsH1opBEotQqN7Ogesk2k6gvO0ZgC0cmDgl7qInBHIo3BGQIJDLwXUFxoAD5miDg17Q5AAGqOA6peOF4jBBqLtU1lK0gvTSAVKSAYvqqAvVqGqF/4vdR8uBqF7BwvRqGk5+kvVQvV6FRINBBwOj5l/qHRKAt7qGBAodRqGCB4lRFQMmvYABpVQ0YtFK4NKBwUmCoNRLA1RLIwJBG4QAB01KpQPD6A/BGAguBqPQUwlK0wkKAAmCSYWs0x8BU4xiBwGp1OALgLXGC4OmDoKLBQgoAF0xTBAAJtGJYdKk0mpROIFYQABqJkEABJBBFpD7DBoLjFDiQnLFAOtE5YOPFQZsBqKZI6J5DSxKIEvYxIwS0BaQXR0wVBbJOBewIVBVQ2mWgWswITBH4wmC0w7FDAIwEFwWtDAowEwQVF1owGCoxYIMwVRPQxJCwWCOpHRQwWmMxKpJwIOISYSLCBxAsCapQAucAJoM0zTGRQoNBDhoNCNgV7EQ+sQ4QABwQfHeIIACqIxH6KzCWQet0wHBGAoIBDgPRZQToGBAQOCIQLIF6IlB02tKwz8FFwIoFA4wuBFAoHFEYyHIq97AYJXGGAQKBPgQuFGAdRvdXAYJcGVQwuBPgI/JBoIOOq7UIAH4AeA=="))
|
246
apps/suw/app.js
246
apps/suw/app.js
|
@ -1,246 +0,0 @@
|
|||
var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js");
|
||||
const LOCATION_FILE = "mylocation.json";
|
||||
let location;
|
||||
|
||||
// load tide times from settings file
|
||||
var settings = Object.assign({
|
||||
// default values
|
||||
nextTideType: "high",
|
||||
nextTideHour: 0,
|
||||
nextTideMin: 0,
|
||||
}, require('Storage').readJSON("suw.json", true) || {});
|
||||
|
||||
// flag to see if next tide time has crossed midnight and need to halt tide time swapping
|
||||
var tideNextDay = false;
|
||||
|
||||
// assume next tide is 6h 12m later
|
||||
var tide1h = settings.nextTideHour;
|
||||
var tide1m = settings.nextTideMin;
|
||||
var tide1type = settings.nextTideType;
|
||||
var tide2m = tide1m +12;
|
||||
if (tide2m > 59) {
|
||||
tide2m = tide2m - 60;
|
||||
var tide2h = tide1h + 7;
|
||||
}
|
||||
else {
|
||||
var tide2h = tide1h + 6;
|
||||
}
|
||||
if (tide2h > 23) {
|
||||
tide2h = tide2h - 24;
|
||||
}
|
||||
if (tide1type === "low ") {
|
||||
var tide2type = "high";
|
||||
}
|
||||
else {
|
||||
var tide2type = "low ";
|
||||
}
|
||||
|
||||
// print(settings.nextTideHour,settings.nextTideMin,settings.nextTideType);
|
||||
// print(tide2h);
|
||||
|
||||
const big = g.getWidth()>200;
|
||||
const timeFontSize = big?6:5;
|
||||
const dateFontSize = big?3:2;
|
||||
//const locationFontSize = 2;
|
||||
const sunFontSize = 2;
|
||||
const tideFontSize = 1;
|
||||
const font = "6x8";
|
||||
|
||||
const xyCenter = g.getWidth() / 2;
|
||||
const yposTime = xyCenter*0.7;
|
||||
const yposDate = xyCenter*1.1;
|
||||
const yposSunrise = xyCenter*1.5;
|
||||
const yposLat = xyCenter*1.7;
|
||||
const yposLon = xyCenter*1.9;
|
||||
|
||||
let showSun = true;
|
||||
|
||||
var sunImg = require("heatshrink").decompress(atob("j0ewIIFhgDCmADC4ACBgYCBjEMg0AuEAnEA8EB4EBx/GB4N/wAVB/4GBj/+AYP//gKC+EH5//5+fn//nwOGgEH/4hBh4KBEIPggEGn8YHIVwHII9Bg0DgIWBLJoADA=="));
|
||||
|
||||
var seaImg =
|
||||
require("heatshrink").decompress(atob("kEgwRC/ABH8gE/4EDAgX/4f//gEDh//+H/AgcA/8Ah4EDE/4nXAH4A=="));
|
||||
|
||||
// Check settings for what type our clock should be
|
||||
var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"];
|
||||
|
||||
|
||||
function numToString(num) {
|
||||
returnString = String(num);
|
||||
if (returnString.length === 1) {
|
||||
returnString = "0"+returnString;
|
||||
}
|
||||
return returnString;
|
||||
}
|
||||
|
||||
// requires the myLocation app
|
||||
function loadLocation() {
|
||||
location = require("Storage").readJSON(LOCATION_FILE,1)||{};
|
||||
location.lat = location.lat||51.5072;
|
||||
location.lon = location.lon||0.1276;
|
||||
location.location = location.location||"London";
|
||||
}
|
||||
|
||||
|
||||
// this is from Pastel - perhaps can be replaced with other function
|
||||
function extractTime(d){
|
||||
var h = d.getHours(), m = d.getMinutes();
|
||||
return(("0"+h).substr(-2) + ":" + ("0"+m).substr(-2));
|
||||
}
|
||||
|
||||
|
||||
var sunRise = "00:00";
|
||||
var sunSet = "00:00";
|
||||
|
||||
function updateSunRiseSunSet(now, lat, lon, line){
|
||||
// get today's sunlight times for lat/lon
|
||||
var times = SunCalc.getTimes(new Date(), lat, lon);
|
||||
|
||||
// format sunrise time from the Date object
|
||||
sunRise = extractTime(times.sunrise);
|
||||
sunSet = extractTime(times.sunset);
|
||||
}
|
||||
|
||||
|
||||
// timeout used to update every minute
|
||||
var drawTimeout;
|
||||
|
||||
// schedule a draw for the next minute
|
||||
function queueDraw() {
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = setTimeout(function() {
|
||||
drawTimeout = undefined;
|
||||
draw();
|
||||
}, 60000 - (Date.now() % 60000));
|
||||
}
|
||||
|
||||
function draw() {
|
||||
// get date
|
||||
var d = new Date();
|
||||
var da = d.toString().split(" ");
|
||||
|
||||
g.reset(); // default draw styles
|
||||
// drawSting centered
|
||||
g.setFontAlign(0, 0);
|
||||
|
||||
// draw time
|
||||
var time = da[4].substr(0, 5).split(":");
|
||||
var hours = time[0],
|
||||
minutes = time[1];
|
||||
var meridian = "";
|
||||
if (is12Hour) {
|
||||
hours = parseInt(hours,10);
|
||||
meridian = "AM";
|
||||
if (hours == 0) {
|
||||
hours = 12;
|
||||
meridian = "AM";
|
||||
} else if (hours >= 12) {
|
||||
meridian = "PM";
|
||||
if (hours>12) hours -= 12;
|
||||
}
|
||||
hours = (" "+hours).substr(-2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
g.setFont("Vector",64); // vector font, 64px
|
||||
g.drawString(`${hours}:${minutes}`, xyCenter, yposTime, true);
|
||||
|
||||
// draw Day, name of month, Date
|
||||
var date = [da[0], da[2], da[1], da[3].substr(-2)].join(" ");
|
||||
g.setFont(font, dateFontSize);
|
||||
g.drawString(date, xyCenter, yposDate, true);
|
||||
|
||||
// recalc sunrise / sunset every hour - needs putting in correct place
|
||||
// if (drawCount % 60 == 0)
|
||||
updateSunRiseSunSet(new Date(), location.lat, location.lon);
|
||||
// drawCount++;
|
||||
|
||||
|
||||
|
||||
// draw sunrise or tide times
|
||||
g.setFont(font, sunFontSize);
|
||||
if (showSun) {
|
||||
g.clearRect(0, xyCenter+17, 175, 175);
|
||||
g.drawString(sunRise+" "+sunSet , xyCenter, yposSunrise, true);
|
||||
g.drawImage(sunImg, xyCenter-15, xyCenter+17);
|
||||
var latitude = location.lat;
|
||||
latitude = Math.round(latitude * 100) / 100;
|
||||
var longitude = location.lon;
|
||||
longitude = Math.round(longitude * 100) / 100;
|
||||
g.drawString("Lat "+latitude, xyCenter, yposLat, true);
|
||||
g.drawString("Lon "+longitude, xyCenter, yposLon, true);
|
||||
}
|
||||
else {
|
||||
var textTime = hours + minutes; // use this for making simple time comparisons
|
||||
var textNextTide = numToString(tide1h)+numToString(tide1m);
|
||||
print(textNextTide);
|
||||
if (Number(textTime) > Number(textNextTide) && (!tideNextDay)) {
|
||||
print("time swap needed");
|
||||
tide1h = tide2h;
|
||||
tide1m = tide2m;
|
||||
tide1type = tide2type;
|
||||
tide2m = tide2m +12;
|
||||
if (tide2m > 59) {
|
||||
tide2m = tide2m - 60;
|
||||
tide2h = tide2h + 7;
|
||||
}
|
||||
else {
|
||||
tide2h = tide2h + 6;
|
||||
}
|
||||
if (tide2h > 23) {
|
||||
tide2h = tide2h - 24;
|
||||
}
|
||||
if (tide2type === "low ") {
|
||||
tide2type = "high";
|
||||
}
|
||||
else {
|
||||
tide2type = "low ";
|
||||
}
|
||||
if (Number(textNextTide) < Number(textTime)) {
|
||||
tideNextDay = true;
|
||||
}
|
||||
else {
|
||||
tideNextDay = false;
|
||||
}
|
||||
|
||||
}
|
||||
g.clearRect(0, xyCenter+17, 175, 175);
|
||||
g.drawString(numToString(tide1h)+numToString(tide1m)+" "+numToString(tide2h)+numToString(tide2m) , xyCenter, 138, true);
|
||||
g.drawString(tide1type+" "+tide2type , xyCenter, 156, true);
|
||||
g.drawImage(seaImg, xyCenter-16, xyCenter+17);
|
||||
}
|
||||
|
||||
// print(tide1h,tide1m,tide1type,tide2h,tide2m,tide2type);
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
function toggleDisplay() {
|
||||
showSun = ! showSun;
|
||||
draw();
|
||||
}
|
||||
|
||||
// adding this as it's not getting called at start
|
||||
loadLocation();
|
||||
|
||||
Bangle.on('touch', () => toggleDisplay());
|
||||
|
||||
// Stop updates when LCD is off, restart when on
|
||||
Bangle.on('lcdPower',on=>{
|
||||
if (on) {
|
||||
draw(); // draw immediately, queue redraw
|
||||
} else { // stop draw timer
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
// clean app screen
|
||||
g.clear();
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clock");
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
// draw now
|
||||
draw();
|
BIN
apps/suw/app.png
BIN
apps/suw/app.png
Binary file not shown.
Before Width: | Height: | Size: 5.1 KiB |
|
@ -1,19 +0,0 @@
|
|||
{ "id": "suw",
|
||||
"name": "Seaside Utility Watch",
|
||||
"shortName":"SeaWatch",
|
||||
"icon": "app.png",
|
||||
"version":"0.01",
|
||||
"description": "A watch useful at the seaside",
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"screenshots": [{"url":"screenshot.png"}],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": false,
|
||||
"storage": [
|
||||
{"name":"suw.app.js","url":"app.js"},
|
||||
{"name":"suw.settings.js","url":"settings.js"},
|
||||
{"name":"suw.img","url":"app-icon.js","evaluate":true}
|
||||
],
|
||||
"data": [{"name":"suw.json"}]
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js");
|
||||
const LOCATION_FILE = "mylocation.json";
|
||||
let location;
|
||||
|
||||
const big = g.getWidth()>200;
|
||||
const timeFontSize = big?6:5;
|
||||
const dateFontSize = big?3:2;
|
||||
const locationFontSize = 2;
|
||||
const sunFontSize = 2;
|
||||
const tideFontSize = 1;
|
||||
const font = "6x8";
|
||||
|
||||
const xyCenter = g.getWidth() / 2;
|
||||
const yposTime = xyCenter*0.7;
|
||||
const yposDate = xyCenter*1.1;
|
||||
const yposSunrise = xyCenter*1.5;
|
||||
//const yposSunset = xyCenter*1.4;
|
||||
const yposLat = xyCenter*1.7;
|
||||
const yposLon = xyCenter*1.9;
|
||||
//const yposTide1 = xyCenter*1.6;
|
||||
//const yposTide2 = xyCenter*1.7;
|
||||
//const yposTide3 = xyCenter*1.8;
|
||||
//const yposTide4 = xyCenter*1.9;
|
||||
|
||||
var sunImg = require("heatshrink").decompress(atob("j0ewIIFhgDCmADC4ACBgYCBjEMg0AuEAnEA8EB4EBx/GB4N/wAVB/4GBj/+AYP//gKC+EH5//5+fn//nwOGgEH/4hBh4KBEIPggEGn8YHIVwHII9Bg0DgIWBLJoADA=="));
|
||||
|
||||
|
||||
// Check settings for what type our clock should be
|
||||
var is12Hour = (require("Storage").readJSON("setting.json",1)||{})["12hour"];
|
||||
|
||||
// requires the myLocation app
|
||||
function loadLocation() {
|
||||
location = require("Storage").readJSON(LOCATION_FILE,1)||{};
|
||||
location.lat = location.lat||51.5072;
|
||||
location.lon = location.lon||0.1276;
|
||||
location.location = location.location||"London";
|
||||
}
|
||||
|
||||
// this is from Pastel - perhaps not needed
|
||||
function extractTime(d){
|
||||
var h = d.getHours(), m = d.getMinutes();
|
||||
return(("0"+h).substr(-2) + ":" + ("0"+m).substr(-2));
|
||||
}
|
||||
|
||||
|
||||
var sunRise = "00:00";
|
||||
var sunSet = "00:00";
|
||||
|
||||
function updateSunRiseSunSet(now, lat, lon, line){
|
||||
// get today's sunlight times for lat/lon
|
||||
var times = SunCalc.getTimes(new Date(), lat, lon);
|
||||
|
||||
// format sunrise time from the Date object
|
||||
sunRise = extractTime(times.sunrise);
|
||||
sunSet = extractTime(times.sunset);
|
||||
}
|
||||
|
||||
|
||||
// timeout used to update every minute
|
||||
var drawTimeout;
|
||||
|
||||
// schedule a draw for the next minute
|
||||
function queueDraw() {
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = setTimeout(function() {
|
||||
drawTimeout = undefined;
|
||||
draw();
|
||||
}, 60000 - (Date.now() % 60000));
|
||||
}
|
||||
|
||||
function draw() {
|
||||
// get date
|
||||
var d = new Date();
|
||||
var da = d.toString().split(" ");
|
||||
|
||||
g.reset(); // default draw styles
|
||||
// drawSting centered
|
||||
g.setFontAlign(0, 0);
|
||||
|
||||
// draw time
|
||||
var time = da[4].substr(0, 5).split(":");
|
||||
var hours = time[0],
|
||||
minutes = time[1];
|
||||
var meridian = "";
|
||||
if (is12Hour) {
|
||||
hours = parseInt(hours,10);
|
||||
meridian = "AM";
|
||||
if (hours == 0) {
|
||||
hours = 12;
|
||||
meridian = "AM";
|
||||
} else if (hours >= 12) {
|
||||
meridian = "PM";
|
||||
if (hours>12) hours -= 12;
|
||||
}
|
||||
hours = (" "+hours).substr(-2);
|
||||
}
|
||||
|
||||
// g.setFont(font, timeFontSize);
|
||||
g.setFont("Vector",66); // vector font, 80px
|
||||
g.drawString(`${hours}:${minutes}`, xyCenter, yposTime, true);
|
||||
// g.setFont(font, tideFontSize);
|
||||
// g.drawString(meridian, xyCenter + 102, yposTime + 10, true);
|
||||
|
||||
// draw Day, name of month, Date
|
||||
var date = [da[0], da[2], da[1], da[3].substr(-2)].join(" ");
|
||||
g.setFont(font, dateFontSize);
|
||||
|
||||
g.drawString(date, xyCenter, yposDate, true);
|
||||
|
||||
// recalc sunrise / sunset every hour - needs putting in correct place
|
||||
// if (drawCount % 60 == 0)
|
||||
updateSunRiseSunSet(new Date(), location.lat, location.lon);
|
||||
// drawCount++;
|
||||
|
||||
// draw sunrise
|
||||
g.setFont(font, sunFontSize);
|
||||
g.drawString(sunRise+" "+sunSet , xyCenter, yposSunrise, true);
|
||||
// g.drawString("Sunset "+sunSet, xyCenter, yposSunset, true);
|
||||
|
||||
// draw sun icon
|
||||
g.drawImage(sunImg, xyCenter-15, xyCenter+17);
|
||||
|
||||
// draw location
|
||||
g.setFont(font, locationFontSize);
|
||||
var latitude = location.lat;
|
||||
latitude = Math.round(latitude * 100) / 100;
|
||||
var longitude = location.lon;
|
||||
longitude = Math.round(longitude * 100) / 100;
|
||||
g.drawString("Lat "+latitude, xyCenter, yposLat, true);
|
||||
g.drawString("Lon "+longitude, xyCenter, yposLon, true);
|
||||
|
||||
|
||||
// draw tides
|
||||
// g.setFont(font, tideFontSize);
|
||||
// g.drawString("High tide 0017 5.58m", xyCenter, yposTide1, true);
|
||||
|
||||
// g.setFont(font, tideFontSize);
|
||||
// g.drawString("Low tide 0651 2.25m", xyCenter, yposTide2, true);
|
||||
|
||||
// g.setFont(font, tideFontSize);
|
||||
// g.drawString("High tide 1302 5.44m", xyCenter, yposTide3, true);
|
||||
|
||||
// g.setFont(font, tideFontSize);
|
||||
// g.drawString("Low tide 1931 2.26m", xyCenter, yposTide4, true);
|
||||
|
||||
|
||||
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
// Stop updates when LCD is off, restart when on
|
||||
Bangle.on('lcdPower',on=>{
|
||||
if (on) {
|
||||
draw(); // draw immediately, queue redraw
|
||||
} else { // stop draw timer
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
// clean app screen
|
||||
g.clear();
|
||||
// Show launcher when button pressed
|
||||
Bangle.setUI("clock");
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
// draw now
|
||||
draw();
|
Binary file not shown.
Before Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB |
|
@ -1,57 +0,0 @@
|
|||
(function(back) {
|
||||
var FILE = "suw.json";
|
||||
// Load settings
|
||||
var settings = Object.assign({
|
||||
nextTideType: "high",
|
||||
nextTideHour: 0,
|
||||
nextTideMin: 0,
|
||||
}, require('Storage').readJSON(FILE, true) || {});
|
||||
|
||||
function writeSettings() {
|
||||
require('Storage').writeJSON(FILE, settings);
|
||||
}
|
||||
|
||||
// Helper method which uses int-based menu item for set of string values
|
||||
function stringItems(startvalue, writer, values) {
|
||||
return {
|
||||
value: (startvalue === undefined ? 0 : values.indexOf(startvalue)),
|
||||
format: v => values[v],
|
||||
min: 0,
|
||||
max: values.length - 1,
|
||||
wrap: true,
|
||||
step: 1,
|
||||
onchange: v => {
|
||||
writer(values[v]);
|
||||
writeSettings();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Helper method which breaks string set settings down to local settings object
|
||||
function stringInSettings(name, values) {
|
||||
return stringItems(settings[name], v => settings[name] = v, values);
|
||||
}
|
||||
|
||||
// Show the menu
|
||||
E.showMenu({
|
||||
"" : { "title" : "Seaside Watch" },
|
||||
"< Back" : () => back(),
|
||||
"Tide type": stringInSettings("nextTideType", ["high", "low "]),
|
||||
'Hour': {
|
||||
value: 0|settings.nextTideHour, // 0| converts undefined to 0
|
||||
min: 0, max: 23,
|
||||
onchange: v => {
|
||||
settings.nextTideHour = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Minutes': {
|
||||
value: 0|settings.nextTideMin, // 0| converts undefined to 0
|
||||
min: 0, max: 59,
|
||||
onchange: v => {
|
||||
settings.nextTideMin = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue