Merge branch 'espruino:master' into master

pull/925/head
Ronin0000 2021-09-29 08:06:54 -07:00 committed by GitHub
commit 59aa99092d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 97 additions and 880 deletions

View File

@ -4,7 +4,7 @@
"tags": "tool,system,b2",
"type":"bootloader",
"icon": "bootloader.png",
"version":"0.29",
"version":"0.30",
"description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings",
"storage": [
{"name":".boot0","url":"boot0.js"},
@ -258,7 +258,7 @@
{ "id": "slidingtext",
"name": "Sliding Clock",
"icon": "slidingtext.png",
"version":"0.06",
"version":"0.07",
"description": "Inspired by the Pebble sliding clock, old times are scrolled off the screen and new times on. You are also able to change language on the fly so you can see the time written in other languages using button 1. Currently English, French, Japanese, Spanish and German are supported",
"tags": "clock",
"type":"clock",
@ -1139,7 +1139,7 @@
"version":"0.01",
"description": "Downloads assisted GPS (AGPS) data to Bangle.js for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.",
"custom": "custom.html",
"tags": "tool,outdoors,agps",
"tags": "tool,outdoors,agps,bno2",
"type": "RAM",
"storage": [ ]
},
@ -2893,24 +2893,6 @@
{"name":"de-stress.img","url":"app-icon.js","evaluate":true}
]
},
{ "id": "gpsservice",
"name": "Low power GPS Service",
"shortName":"GPS Service",
"icon": "gpsservice.png",
"version":"0.04",
"description": "low power GPS widget",
"tags": "gps outdoors navigation",
"readme": "README.md",
"storage": [
{"name":"gpsservice.app.js","url":"app.js"},
{"name":"gpsservice.settings.js","url":"settings.js"},
{"name":"gpsservice.wid.js","url":"widget.js"},
{"name":"gpsservice.img","url":"gpsservice-icon.js","evaluate":true}
],
"data": [
{"name":"gpsservice.settings.json","url":"settings.json"}
]
},
{ "id": "mclockplus",
"name": "Morph Clock+",
"shortName":"Morph Clock+",
@ -3000,7 +2982,7 @@
"icon": "gpssetup.png",
"version":"0.02",
"description": "Configure the GPS power options and store them in the GPS nvram",
"tags": "gps, tools, outdoors",
"tags": "gps,tools,outdoors,bno2",
"readme": "README.md",
"storage": [
{"name":"gpssetup","url":"gpssetup.js"},

View File

@ -46,7 +46,6 @@ function getData() {
});
return new Promise(resolve=>{
Puck.eval(`require("Storage").read(${JSON.stringify(fn)})`,csv=>{
fileData[fn] = csv.trim();
var el = document.querySelector(`.card-body[fn='${fn}']`);
el.innerHTML = '<canvas width="400" height="100"></canvas>';
var c = el.firstChild;

View File

@ -29,3 +29,4 @@
0.28: Fix double clock load after settings are changed
0.29: Update boot0 to avoid code block (faster execution)
Fix issues where 'Uncaught Error: Function not found' could happen with multiple .boot.js
0.30: Remove 'Get GPS time' at boot. Latest firmwares keep time through reboots, so this is not needed now

View File

@ -15,25 +15,5 @@ if (!clockApp) {
clockApp = require("Storage").read(clockApp.src);
}
if (!clockApp) clockApp=`E.showMessage("No Clock Found");setWatch(()=>{Bangle.showLauncher();}, BTN2, {repeat:false,edge:"falling"});`;
// check to see if our clock is wrong - if it is use GPS time
if ((new Date()).getFullYear()<2000) {
E.showMessage("Searching for\nGPS time");
Bangle.on("GPS",function cb(g) {
Bangle.setGPSPower(0);
Bangle.removeListener("GPS",cb);
if (!g.time || (g.time.getFullYear()<2000) ||
(g.time.getFullYear()>2200)) {
// GPS receiver's time not set - just boot clock anyway
eval(clockApp);
delete clockApp;
return;
}
// We have a GPS time. Set time and reboot (to load alarms properly)
setTime(g.time.getTime()/1000);
load();
});
Bangle.setGPSPower(1);
} else {
eval(clockApp);
delete clockApp;
}
eval(clockApp);
delete clockApp;

View File

@ -1,4 +0,0 @@
0.01: New App
0.02: Restore to SuperE mode on power off.
0.03: dont reset to SuperE mode on power, as it prevents its general use
0.04: Only turn GPS off if it was previously on (stops other apps/widgets that use GPS getting broken)

View File

@ -1,141 +0,0 @@
# GPS Service
A configurable, low power GPS widget that runs in the background.
NOTE: This app has been superceded by [gpssetup](https://github.com/espruino/BangleApps/blob/master/apps/gpssetup/README.md)
## Goals
To develop a low power GPS widget that runs in the background and to
facilitate an OS grid reference display in a watch face.
* An app that turns on the GPS and constantly displays the screen
will use around 75mA, the battery will last between 3-4 hours.
* Using the GPS in a Widget in Super-E Power Saving Mode (PSM) with
the screen off most of the time, will consume around 35mA and you
might get 10hrs before a recharge.
* Using the GPS in Power Saving Mode On/Off (PSMOO) with suitable
settings can reduce the average consumption to around 15mA. A
simple test using a 120s update period, 6s search period was still
running with 45% battery 20 hours after it started.
## Settings
The Settings App enables you set the following options for the GPS
Service. Go to Settings, select App/Widgets and then 'GPS Service'.
- GPS - On/Off. When this value is changed the GPS Service will be
powered on or off and the GPS Widget will be displayed.
- Power Mode:
- SuperE - the factory default setup for the GPS. The recommended
power saving mode.
- PSMOO - On/Off power saving mode. Configured by interval and
search time. Choose this mode if you are happy to get a GPS
position update less often (say every 1 or 2 minutes). The longer
the interval the more time the GPS will spend sleeping in low
power mode (7mA) between obtaining fixes (35mA). For walking in
open country an update once every 60 seconds is adequate to put
you within a 6 digit grid refernce sqaure.
- update - the time between two position fix attempts.
- search - the time between two acquisition attempts if the receiver
is unable to get a position fix.
## Screenshots
### GPS Watch face
* The Age value is the number of seconds since the last position fix was received.
![](gps_face.jpg)
### Grid Reference Watch face
* The time shown is the timestamp of the last position fix.
* The age value is shown at the bottom of the screen.
![](osref_face.jpg)
## Interface for Apps
The code below demonstrates how you can setup and start the gpsservice from your own App.
```js
function test_gps_on() {
var settings = WIDGETS.gpsservice.gps_get_settings();
// change the settings to what you require
settings.gpsservice = true;
settings.update = 65;
settings.search = 5;
settings.power_mode = "PSMOO";
WIDGETS.gpsservice.gps_set_settings(settings);
WIDGETS.gpsservice.reload(); // will power on
}
```
In your app can retrieve the last fix as and when required.
```js
var fix = {
fix: 0,
alt: 0,
lat: 0,
lon: 0,
speed: 0,
time: 0,
satellites: 0
};
// only attempt to get gps fix if gpsservice is loaded
if (WIDGETS.gpsservice !== undefined) {
fix = WIDGETS.gpsservice.gps_get_fix();
gps_on = WIDGETS.gpsservice.gps_get_status();
}
if (fix.fix) {
var time = formatTime(fix.time);
var age = timeSince(time);
```
When done you can turn the gpsservice off using the code below.
```js
function test_gps_off() {
var settings = WIDGETS.gpsservice.gps_get_settings();
settings.gpsservice = false;
settings.power_mode = "SuperE";
WIDGETS.gpsservice.gps_set_settings(settings);
WIDGETS.gpsservice.reload(); // will power off
}
```
## To Do List
* add a logging option with options for interval between log points
* add graphics and icons to the watch faces to make them look nicer
## References
* [UBLOX M8 Receiver Data Sheet](https://www.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_%28UBX-13003221%29.pdf)
* [UBLOX Power Management App Note](https://www.u-blox.com/sites/default/files/products/documents/PowerManagement_AppNote_%28UBX-13005162%29.pdf)
* Some useful code on Github and be found [here](https://portal.u-blox.com/s/question/0D52p0000925T00CAE/ublox-max-m8q-getting-stuck-when-sleeping-with-extint-pin-control)
and [here](https://github.com/thasti/utrak/blob/master/gps.c)

View File

@ -1,70 +0,0 @@
Bangle.loadWidgets();
Bangle.drawWidgets();
const SETTINGS_FILE = "gpsservice.settings.json";
let settings = require("Storage").readJSON(SETTINGS_FILE,1)||{};
function updateSettings() {
require("Storage").write(SETTINGS_FILE, settings);
}
function reloadWidget() {
if (WIDGETS.gpsservice)
WIDGETS.gpsservice.reload();
}
function showMainMenu() {
var power_options = ["SuperE","PSMOO"];
const mainmenu = {
'': { 'title': 'GPS Service' },
'< Exit': ()=>{load();},
'GPS': {
value: !!settings.gpsservice,
format: v =>v?'On':'Off',
onchange: v => {
settings.gpsservice = v;
updateSettings();
reloadWidget(); // only when we change On/Off status
},
},
'Power Mode': {
value: 0 | power_options.indexOf(settings.power_mode),
min: 0, max: 1,
format: v => power_options[v],
onchange: v => {
settings.power_mode = power_options[v];
updateSettings();
},
},
'Update (s)': {
value: settings.update,
min: 10,
max: 1800,
step: 10,
onchange: v => {
settings.period =v;
updateSettings();
}
},
'Search (s)': {
value: settings.search,
min: 1,
max: 65,
step: 1,
onchange: v => {
settings.search = v;
updateSettings();
}
},
'< Back': ()=>{load();}
};
return E.showMenu(mainmenu);
}
showMainMenu();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

View File

@ -1 +0,0 @@
require("heatshrink").decompress(atob("mEwghC/AH4AKg9wC6t3u4uVC6wWBI6t3uJeVuMQCqcBLisAi4XLxAABFxAXKgc4DBAuBRhQXEDAq7MmYXEwBHEXZYXFGAOqAAKDMmczC4mIC62CC50PC4JIBkQABiIvRmURAAUSjQXSFwMoxGKC6CRFwUSVYgXLPIgXXwMYegoXLJAYXCGBnzGA0hPQIwMgYwGC6gwCC4ZIMC4gYBC604C4ZISmcRVgapQAAMhC6GIJIwXCMBcIxGDDBAuLC4IwGAARGMAAQWGmAXPJQoWMC4pwCCpoXJAB4XXAH4A/ABQA="))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

View File

@ -1,4 +0,0 @@
(function(back) {
// just go right to our app
load("gpsservice.app.js");
})();

View File

@ -1 +0,0 @@
{"gpsservice":false, "power_mode":"SuperE", "update":120, "search":6}

View File

@ -1,259 +0,0 @@
/*
test bed for working out lowest power consumption, with workable GPS
Load into IDE and upload code to RAM when connected to watch
*/
Bangle.on('GPS-raw',function (d) {
if (d[0]=="$") return;
if (d.startsWith("\xB5\x62\x05\x01")) print("GPS ACK");
else if (d.startsWith("\xB5\x62\x05\x00")) print("GPS NACK");
// 181,98 sync chars
else print("GPS",E.toUint8Array(d).join(","));
});
function writeGPScmd(cmd) {
var d = [0xB5,0x62]; // sync chars
d = d.concat(cmd);
var a=0,b=0;
for (var i=2;i<d.length;i++) {
a += d[i];
b += a;
}
d.push(a&255,b&255);
console.log(d);
Serial1.write(d);
}
// quick hack
function wait(ms){
var start = new Date().getTime();
var end = start;
while(end < start + ms) {
end = new Date().getTime();
}
}
/*
* gps_disable_nmea_output
*
* disables all NMEA messages to be output from the GPS.
* even though the parser can cope with NMEA messages and ignores them, it
* may save power to disable them completely.
*
*
* DO NOT USE
* HB: This is a bad idea on a Bangle JS
* You wont get any fixes if you call this function
*
*
*/
function UBX_CFG_DISABLE_NMEA() {
writeGPScmd([0x06, 0x00, /* UBX-CFG-PRT */
20, 0x00,
0x01, 0x00, 0x00, 0x00, /* UART1, reserved, no TX ready */
0xe0, 0x08, 0x00, 0x00, /* UART mode (8N1) */
0x80, 0x25, 0x00, 0x00, /* UART baud rate (9600) */
0x01, 0x00, /* input protocols (uBx only) */
0x01, 0x00, /* output protocols (uBx only) */
0x00, 0x00, /* flags */
0x00, 0x00]); /* reserved */
}
/*
* gps_disable_nmea_output
*
* disables all NMEA messages to be output from the GPS.
* even though the parser can cope with NMEA messages and ignores them, it
* may save power to disable them completely.
*
* Can use this to switch NMEA back on if you call
* UBX_CFG_DISABLE_NMEA()
*
*/
function UBX_CFG_RESTORE_NMEA() {
writeGPScmd([0x06, 0x00, /* UBX-CFG-PRT */
20, 0x00,
0x01, 0x00, 0x00, 0x00, /* UART1, reserved, no TX ready */
0xe0, 0x08, 0x00, 0x00, /* UART mode (8N1) */
0x80, 0x25, 0x00, 0x00, /* UART baud rate (9600) */
0x03, 0x00, /* input protocols (uBx only) */
0x03, 0x00, /* output protocols (uBx only) */
0x00, 0x00, /* flags */
0x00, 0x00]); /* reserved */
}
function UBX_CFG_PMS() {
// UBX-CFG-PMS - enable power management - Super-E
writeGPScmd([0x06,0x86, // msg class + type
8,0,//length
0x00,0x03, 0,0, 0,0, 0,0]);
}
function UBX_CFG_INTERVAL(period, ontime) {
writeGPScmd([0x06,0x86, // msg class + type
8,0, //length
//v0, interval period ontime reserved
0x00, 0x02, period, 0, ontime, 0, 0, 0 ]);
// the values are little endian, least significant byte first
}
/*
* set update baud rate
*
* the setting is in milliseconds in 2 bytes, max 65 seconds
* we are passing in a value in seconds
* we set the most significant byte only
* 8 seconds ~ 8192ms 0x2000, 0x20 = 32 = 4*8
*
*/
function UBX_CFG_RATE(rate) {
rate = (rate * 4) % 256;
//console.log("rate=" + rate);
writeGPScmd([0x06,0x08, // class, id
0x06, 0, // length
0x00, rate, // b0: 8192ms 0x2000, 0x00FF (~65sec)
0x01, 0x00, // b2:
0x01, 0x00]); // b4: timeref GPS
}
/*
* Save configuration otherwise it will reset when the GPS wakes up
*
*/
function UBX_CFG_SAVE() {
writeGPScmd([0x06, 0x09, // class id
0x0D, 0x00, // length
0x00, 0x00, 0x00, 0x00, // clear mask
0xFF, 0xFF, 0x00, 0x00, // save mask
0x00, 0x00, 0x00, 0x00, // load mask
0x07]); // b2=eeprom b1=flash b0=bat backed ram
// code on github had 7 - all 3 set ?
}
/*
* Reset to factory settings using clear mask in UBX_CFG_CFG
* https://portal.u-blox.com/s/question/0D52p0000925T00CAE/ublox-max-m8q-getting-stuck-when-sleeping-with-extint-pin-control
*/
function UBX_CFG_RESET() {
writeGPScmd([0x06, 0x09, // class id
0x0D, 0x00,
0xFF, 0xFB, 0x00, 0x00, // clear mask
0x00, 0x00, 0x00, 0x00, // save mask
0xFF, 0xFF, 0x00, 0x00, // load mask
0x17]);
}
// convert an integer to an array of bytes
function int_2_bytes( x ){
var bytes = [];
var i = 4;
do {
bytes[--i] = x & (255);
x = x>>8;
} while (i);
return bytes;
}
/*
* Extended Power Management
* update and search are in seconds
*
* https://github.com/thasti/utrak/blob/master/gps.c
*/
function UBX_CFG_PM2(update,search) {
var u = int_2_bytes(update*1000);
var s = int_2_bytes(search*1000);
writeGPScmd([0x06, 0x3B, /* class id */
44, 0, /* length */
0x01, 0x00, 0x00, 0x00, /* v1, reserved 1..3 */
0x00, 0x10, 0x00, 0x00, /* on/off-mode, update ephemeris */
// little endian, lsb first
//0x30, 0x75, 0x00, 0x00, /* update period, ms, 120s=00 01 D4 C0, 30s= 00 00 75 30 */
//0x88, 0x13, 0x00, 0x00, /* search period, ms, 120s, 20s = 00 00 4E 20, 5s = 13 88 */
u[3], u[2], u[1], u[0], /* update period, ms, 120s=00 01 D4 C0, 30s= 00 00 75 30 */
s[3], s[2], s[1], s[0], /* search period, ms, 120s, 20s = 00 00 4E 20, 5s = 13 88 */
0x00, 0x00, 0x00, 0x00, /* grid offset */
0x00, 0x00, /* on-time after first fix */
0x01, 0x00, /* minimum acquisition time */
0x00, 0x00, 0x00, 0x00, /* reserved 4,5 */
0x00, 0x00, 0x00, 0x00, /* reserved 6 */
0x00, 0x00, 0x00, 0x00, /* reserved 7 */
0x00, 0x00, 0x00, 0x00, /* reserved 8,9,10 */
0x00, 0x00, 0x00, 0x00]); /* reserved 11 */
}
// enable power saving mode, after configured with PM2
function UBX_CFG_RXM() {
writeGPScmd([0x06, 0x11, /* UBX-CFG-RXM */
2, 0, /* length */
0x08, 0x01]); /* reserved, enable power save mode */
}
function onGPS(fix) {
console.log(fix);
}
function setupGPS() {
Bangle.setGPSPower(1);
UBX_CFG_RESET();
wait(100);
//UBX_CFG_RESTORE_NMEA();
//wait(20);
UBX_CFG_PM2(120,5);
wait(20);
UBX_CFG_RXM();
wait(20);
UBX_CFG_SAVE();
wait(20);
Bangle.on('GPS',onGPS);
}
function test_gps_on() {
var settings = WIDGETS.gpsservice.gps_get_settings();
settings.gpsservice = true;
settings.update = 65;
settings.search = 5;
settings.power_mode = "PSMOO";
WIDGETS.gpsservice.gps_set_settings(settings);
WIDGETS.gpsservice.reload(); // will power on
}
function test_gps_off() {
var settings = WIDGETS.gpsservice.gps_get_settings();
settings.gpsservice = false;
settings.power_mode = "SuperE";
WIDGETS.gpsservice.gps_set_settings(settings);
WIDGETS.gpsservice.reload(); // will power off
}
// test_gps_on();
// test_gps_off();

View File

@ -1,287 +0,0 @@
(() => {
var settings = {};
var fixToggle = false; // toggles once for each reading
var have_fix = false;
var debug = false;
var gpsPowerEnabled = false;
var last_fix = {
fix: 0,
alt: 0,
lat: 0,
lon: 0,
speed: 0,
time: 0,
satellites: 0
};
function gps_get_fix() { return last_fix; }
function gps_get_status() { return WIDGETS.gpsservice.width === 24 ? true : false;}
function gps_get_version() { return "0.03"; }
function log_debug(o) {
if (debug) console.log(o);
}
function gps_set_debug(v) {
debug = v;
}
// Called by the GPS widget settings to reload settings and decide what to do
function reload() {
settings = gps_get_settings();
log_debug(settings);
Bangle.removeListener('GPS',onGPS);
if (settings.gpsservice) {
gps_power_on();
} else {
gps_power_off();
}
}
// retrieve the settings from Storage, can be called by external apps
function gps_get_settings() {
var sets = require("Storage").readJSON("gpsservice.settings.json",1)||{};
sets.gpsservice = sets.gpsservice||false;
sets.update = sets.update||120;
sets.search = sets.search||5;
sets.power_mode = sets.power_mode||"SuperE";
return sets;
}
// pass in the required settings, can be called by external apps
function gps_set_settings(sets) {
settings.gpsservice = sets.gpsservice||false;
settings.update = sets.update||120;
settings.search = sets.search||5;
settings.power_mode = sets.power_mode||"SuperE";
require("Storage").write("gpsservice.settings.json", settings);
}
// issue: currently possible to call this without having set settings.gpsservice in settings file
function gps_power_on() {
have_fix = false;
fixToggle = false;
setupGPS();
WIDGETS.gpsservice.width = 24;
}
function gps_power_off() {
//setupSuperE(); // return to expected setup for other apps
if (gpsPowerEnabled) {
gpsPowerEnabled = false;
Bangle.setGPSPower(0);
}
have_fix = false;
fixToggle = false;
last_fix.fix = 0;
WIDGETS.gpsservice.width = 0;
}
// quick hack
function wait(ms){
var start = new Date().getTime();
var end = start;
while(end < start + ms) {
end = new Date().getTime();
}
}
function setupGPS() {
Bangle.setGPSPower(1);
gpsPowerEnabled = true;
if (settings.power_mode === "PSMOO") {
setupPSMOO();
} else {
setupSuperE();
}
Bangle.on('GPS',onGPS);
}
function setupPSMOO() {
log_debug("setupGPS() PSMOO");
UBX_CFG_RESET();
wait(100);
UBX_CFG_PM2(settings.update, settings.search);
wait(20);
UBX_CFG_RXM();
wait(20);
UBX_CFG_SAVE();
wait(20);
}
function setupSuperE() {
log_debug("setupGPS() Super-E");
UBX_CFG_RESET();
wait(100);
UBX_CFG_PMS();
wait(20);
UBX_CFG_SAVE();
wait(20);
}
function writeGPScmd(cmd) {
var d = [0xB5,0x62]; // sync chars
d = d.concat(cmd);
var a=0,b=0;
for (var i=2;i<d.length;i++) {
a += d[i];
b += a;
}
d.push(a&255,b&255);
Serial1.write(d);
}
// UBX-CFG-PMS - enable power management - Super-E
function UBX_CFG_PMS() {
writeGPScmd([0x06,0x86, // msg class + type
8,0,//length
0x00,0x03, 0,0, 0,0, 0,0]);
}
// convert an integer to an array of bytes
function int_2_bytes( x ){
var bytes = [];
var i = 4;
do {
bytes[--i] = x & (255);
x = x>>8;
} while (i);
return bytes;
}
/*
* Extended Power Management
* update and search are in milli seconds
* settings are loaded little endian, lsb first
*
* https://github.com/thasti/utrak/blob/master/gps.c
*/
function UBX_CFG_PM2(update,search) {
var u = int_2_bytes(update*1000);
var s = int_2_bytes(search*1000);
writeGPScmd([0x06, 0x3B, /* class id */
44, 0, /* length */
0x01, 0x00, 0x00, 0x00, /* v1, reserved 1..3 */
0x00, 0x10, 0x00, 0x00, /* on/off-mode, update ephemeris */
u[3], u[2], u[1], u[0], /* update period, ms, 120s=00 01 D4 C0, 30s= 00 00 75 30 */
s[3], s[2], s[1], s[0], /* search period, ms, 120s, 20s = 00 00 4E 20, 5s = 13 88 */
0x00, 0x00, 0x00, 0x00, /* grid offset */
0x00, 0x00, /* on-time after first fix */
0x01, 0x00, /* minimum acquisition time */
0x00, 0x00, 0x00, 0x00, /* reserved 4,5 */
0x00, 0x00, 0x00, 0x00, /* reserved 6 */
0x00, 0x00, 0x00, 0x00, /* reserved 7 */
0x00, 0x00, 0x00, 0x00, /* reserved 8,9,10 */
0x00, 0x00, 0x00, 0x00]); /* reserved 11 */
}
// enable power saving mode, after configured with PM2
function UBX_CFG_RXM() {
writeGPScmd([0x06, 0x11, /* UBX-CFG-RXM */
2, 0, /* length */
0x08, 0x01]); /* reserved, enable power save mode */
}
/*
* Save configuration otherwise it will reset when the GPS wakes up
*
*/
function UBX_CFG_SAVE() {
writeGPScmd([0x06, 0x09, // class id
0x0D, 0x00, // length
0x00, 0x00, 0x00, 0x00, // clear mask
0xFF, 0xFF, 0x00, 0x00, // save mask
0x00, 0x00, 0x00, 0x00, // load mask
0x07]); // b2=eeprom b1=flash b0=bat backed ram
}
/*
* Reset to factory settings using clear mask in UBX_CFG_CFG
* https://portal.u-blox.com/s/question/0D52p0000925T00CAE/ublox-max-m8q-getting-stuck-when-sleeping-with-extint-pin-control
*/
function UBX_CFG_RESET() {
writeGPScmd([0x06, 0x09, // class id
0x0D, 0x00,
0xFF, 0xFB, 0x00, 0x00, // clear mask
0x00, 0x00, 0x00, 0x00, // save mask
0xFF, 0xFF, 0x00, 0x00, // load mask
0x17]);
}
// draw the widget
function draw() {
if (!settings.gpsservice) return;
g.reset();
g.drawImage(atob("GBgCAAAAAAAAAAQAAAAAAD8AAAAAAP/AAAAAAP/wAAAAAH/8C9AAAB/8L/QAAAfwv/wAAAHS//wAAAAL//gAAAAf/+AAAAAf/4AAAAL//gAAAAD/+DwAAAB/Uf8AAAAfA//AAAACAf/wAAAAAH/0AAAAAB/wAAAAAAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),this.x,this.y);
if (gps_get_status() === true && have_fix) {
g.setColor("#00FF00");
g.drawImage(fixToggle ? atob("CgoCAAAAA0AAOAAD5AAPwAAAAAAAAAAAAAAAAA==") : atob("CgoCAAABw0AcOAHj5A8PwHwAAvgAB/wABUAAAA=="),this.x,this.y+14);
} else {
g.setColor("#0000FF");
if (fixToggle) g.setFont("6x8").drawString("?",this.x,this.y+14);
}
}
function onGPS(fix) {
fixToggle = !fixToggle;
WIDGETS.gpsservice.draw();
log_debug(fix);
last_fix.satellites = fix.satellites;
/*
* If we have a fix record it, we will get another soon. Apps
* will see the timestamp of the last fix and be able to work out
* if it is stale. This means an App will always have the last
* known fix, and we avoid saying no fix all the time.
*
*/
if (fix.fix) {
last_fix.fix = fix.fix;
last_fix.alt = fix.alt;
last_fix.lat = fix.lat;
last_fix.lon = fix.lon;
last_fix.speed = fix.speed;
last_fix.time = fix.time;
}
}
// redraw when the LCD turns on
Bangle.on('lcdPower', function(on) {
if (on) WIDGETS.gpsservice.draw();
});
// add the widget
WIDGETS.gpsservice = {
area:"tl",
width:24,
draw:draw,
gps_power_on:gps_power_on,
gps_power_off:gps_power_off,
gps_get_status:gps_get_status,
gps_get_fix:gps_get_fix,
gps_get_version:gps_get_version,
gps_get_settings:gps_get_settings,
gps_set_settings:gps_set_settings,
gps_set_debug:gps_set_debug,
reload:function() {
reload();
Bangle.drawWidgets(); // relayout all widgets
}};
// load settings, set correct widget width
reload();
})();

View File

@ -496,6 +496,24 @@ var locales = {
day: "Vasárnap,Hétfő,Kedd,Szerda,Csütörtök,Péntek,Szombat",
trans: { yes: "igen", Yes: "Igen", no: "nem", No: "Nem", ok: "ok", on: "be", off: "ki" }
},
"oc_FR": {
lang: "oc_FR",
decimal_point: ",",
thousands_sep: " ",
currency_symbol: "€",
int_curr_symbol: "EUR",
speed: "km/h",
distance: { 0: "m", 1: "km" },
temperature: "°C",
ampm: { 0: "", 1: "" },
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
datePattern: { 0: "%A %d %B de %Y", "1": "%d/%m/%Y" }, // dimenge 1 de març de 2020 // 01/03/2020
abmonth: "gen.,febr.,març,abril,mai,junh,julh,ago.,set.,oct.,nov.,dec.",
month: "genièr,febrièr,març,abril,mai,junh,julhet,agost,setembre,octòbre,novembre,decembre",
abday: "dg,dl,dm,dc,dj,dv,ds",
day: "dimenge,diluns,dimars,dimècres,dijòus,divendres,dissabte",
trans: { yes: "òc", Yes: "Òc", no: "non", No: "Non", ok: "ok", on: "on", off: "off" }
},
"pt_BR": {
lang: "pt_BR",
decimal_point: ",",

View File

@ -4,3 +4,4 @@
0.04: Added German Language
0.05: BUGFIX: pedometer widget interfered with the clock Font Alignment
0.06: Use Bangle.setUI for button/launcher handling
0.07: Support for Bangle.js 2 and themes

View File

@ -146,12 +146,6 @@ class ShiftText {
//console.log("bgcolor:" + this.bg_color);
g.setColor(this.bg_color[0],this.bg_color[1],this.bg_color[2]);
g.drawString(this.txt, this.x, this.y);
/*g.fillPoly([this.x - 1, this.y,
240, this.y,
240, this.y + this.font_size,
this.x -1 , this.y + this.font_size,
]);
*/
}
setText(txt){
this.txt = txt;
@ -239,13 +233,21 @@ class ShiftText {
const CLOCK_TEXT_SPEED_X = 10;
// a list of display rows
let row_displays = [
new ShiftText(240,50,'',"Vector",40,CLOCK_TEXT_SPEED_X,1,10,main_color(),bg_color()),
new ShiftText(240,90,'',"Vector",30,CLOCK_TEXT_SPEED_X,1,10,other_color(),bg_color()),
new ShiftText(240,120,'',"Vector",30,CLOCK_TEXT_SPEED_X,1,10,other_color(),bg_color()),
new ShiftText(240,150,'',"Vector",30,CLOCK_TEXT_SPEED_X,1,10,other_color(),bg_color()),
new ShiftText(240,180,'',"Vector",40,CLOCK_TEXT_SPEED_X,1,10,main_color(),bg_color())
];
let row_displays;
function setRowDisplays(y, heights) {
var cols = [
main_color(), other_color(), other_color(), other_color(), main_color()
];
row_displays = [];
for (var i=0;i<heights.length;i++) {
row_displays.push(new ShiftText(g.getWidth(),y,'',"Vector",heights[i],CLOCK_TEXT_SPEED_X,1,10,cols[i],bg_color()));
y += heights[i];
}
}
if (g.getHeight()>200)
setRowDisplays(50, [40,30,30,30,40]);
else
setRowDisplays(34, [35,25,25,25,35]);
function nextColorTheme(){
//console.log("next color theme");
@ -274,11 +276,7 @@ function setColor(main_color,other_color,bg_color){
row_displays[row_displays.length - 1].setColor(main_color);
row_displays[row_displays.length - 1].setBgColor(bg_color);
g.setColor(bg_color[0],bg_color[1],bg_color[2]);
g.fillPoly([0,25,
0,240,
240,240,
240,25
]);
g.fillRect(0,24, g.getWidth(), g.getHeight());
}
// load the date formats and laguages required
@ -510,12 +508,14 @@ const PREFERENCE_FILE = "slidingtext.settings.json";
* Called on startup to set the watch to the last preference settings
*/
function load_settings(){
var setScheme = false;
try{
settings = require("Storage").readJSON(PREFERENCE_FILE);
if(settings != null){
console.log("loaded:" + JSON.stringify(settings));
if(settings.color_scheme != null){
set_colorscheme(settings.color_scheme);
setScheme = true;
}
if(settings.date_format != null){
set_dateformat(settings.date_format);
@ -526,6 +526,9 @@ function load_settings(){
} catch(e){
console.log("failed to load settings:" + e);
}
// just set up as default
if (!setScheme)
setColorScheme(color_schemes[color_scheme_index]);
}
/**
@ -636,11 +639,7 @@ Bangle.drawWidgets();
startTimers();
// Show launcher when button pressed
Bangle.setUI("clock");
// Handle button 1 being pressed
setWatch(button1pressed, BTN1,{repeat:true,edge:"falling"});
// Handle button 3 being pressed
setWatch(button3pressed, BTN3,{repeat:true,edge:"falling"});
Bangle.setUI("clockupdown", d=>{
if (d<0) button1pressed();
if (d>0) button3pressed();
});

View File

@ -87,6 +87,13 @@ function Layout(layout, buttons, options) {
if (buttons) {
if (this.physBtns >= buttons.length) {
// Handler for button watch events
function pressHandler(btn,e) {
if (e.time-e.lastTime > 0.75 && this.b[btn].cbl)
this.b[btn].cbl(e);
else
if (this.b[btn].cb) this.b[btn].cb(e);
}
// enough physical buttons
let btnHeight = Math.floor((g.getHeight()-this.yOffset) / this.physBtns);
if (Bangle.btnWatch) Bangle.btnWatch.forEach(clearWatch);
@ -113,6 +120,12 @@ function Layout(layout, buttons, options) {
}
}
if (process.env.HWVERSION==2) {
// Handler for touch events
function touchHandler(l,e) {
if (l.type=="btn" && l.cb && e.x>=l.x && e.y>=l.y && e.x<=l.x+l.w && e.y<=l.y+l.h)
l.cb(e);
if (l.c) l.c.forEach(n => touchHandler(n,e));
}
Bangle.touchHandler = function(_,e){touchHandler(layout,e)};
Bangle.on('touch',Bangle.touchHandler);
}
@ -139,21 +152,6 @@ Layout.prototype.remove = function (l) {
}
};
// Handler for button watch events
function pressHandler(btn,e) {
if (e.time-e.lastTime > 0.75 && this.b[btn].cbl)
this.b[btn].cbl(e);
else
if (this.b[btn].cb) this.b[btn].cb(e);
}
// Handler for touch events
function touchHandler(l,e) {
if (l.type=="btn" && l.cb && e.x>=l.x && e.y>=l.y && e.x<=l.x+l.w && e.y<=l.y+l.h)
l.cb(e);
if (l.c) l.c.forEach(n => touchHandler(n,e));
}
function prepareLazyRender(l, rectsToClear, drawList, rects, parentBg) {
var bgCol = l.bgCol == null ? parentBg : g.toColor(l.bgCol);
if (bgCol != parentBg || l.type == "txt" || l.type == "btn" || l.type == "img" || l.type == "custom") {
@ -164,10 +162,8 @@ function prepareLazyRender(l, rectsToClear, drawList, rects, parentBg) {
if (c) l.c = c;
if (!delete rectsToClear[hash]) {
rects[hash] = {
bg: parentBg == null ? g.theme.bg : parentBg,
r: [l.x,l.y,l.x+l.w-1,l.y+l.h-1]
};
var r = rects[hash] = [l.x,l.y,l.x+l.w-1,l.y+l.h-1];
r.bg = parentBg == null ? g.theme.bg : parentBg;
if (drawList) {
drawList.push(l);
drawList = null; // Prevent children from being redundantly added to the drawList
@ -227,7 +223,7 @@ Layout.prototype.render = function (l) {
prepareLazyRender(l, rectsToClear, drawList, this.rects, null);
for (var h in rectsToClear) delete this.rects[h];
var clearList = Object.keys(rectsToClear).map(k=>rectsToClear[k]).reverse(); // Rects are cleared in reverse order so that the original bg color is restored
for (var r of clearList) g.setBgColor(r.bg).clearRect.apply(g, r.r);
for (var r of clearList) g.setBgColor(r.bg).clearRect.apply(g, r);
drawList.forEach(render);
} else { // non-lazy
render(l);
@ -239,29 +235,37 @@ Layout.prototype.layout = function (l) {
// exw,exh = extra width/height available
switch (l.type) {
case "h": {
var x = l.x + (0|l.pad);
var acc_w = l.x + (0|l.pad);
var accfillx = 0;
var fillx = l.c && l.c.reduce((a,l)=>a+(0|l.fillx),0);
if (!fillx) { x += (l.w-l._w)/2; }
if (!fillx) { acc_w += (l.w-l._w)>>1; fillx=1; }
var x = acc_w;
l.c.forEach(c => {
c.w = c._w + ((0|c.fillx)*(l.w-l._w)/(fillx||1));
c.h = c.filly ? l.h - (l.pad<<1) : c._h;
c.x = x;
c.y = l.y + (0|l.pad) + (1+(0|c.valign))*(l.h-(l.pad<<1)-c.h)/2;
x += c.w;
c.x = 0|x;
acc_w += c._w;
accfillx += 0|c.fillx;
x = acc_w + Math.floor(accfillx*(l.w-l._w)/fillx);
c.w = 0|(x - c.x);
c.h = 0|(c.filly ? l.h - (l.pad<<1) : c._h);
c.y = 0|(l.y + (0|l.pad) + ((1+(0|c.valign))*(l.h-(l.pad<<1)-c.h)>>1));
if (c.c) this.layout(c);
});
break;
}
case "v": {
var y = l.y + (0|l.pad);;
var acc_h = l.y + (0|l.pad);
var accfilly = 0;
var filly = l.c && l.c.reduce((a,l)=>a+(0|l.filly),0);
if (!filly) { y += (l.h-l._h)/2 }
if (!filly) { acc_h += (l.h-l._h)>>1; filly=1; }
var y = acc_h;
l.c.forEach(c => {
c.w = c.fillx ? l.w - (l.pad<<1) : c._w;
c.h = c._h + ((0|c.filly)*(l.h-l._h)/(filly||1));
c.y = y;
c.x = l.x + (0|l.pad) + (1+(0|c.halign))*(l.w-(l.pad<<1)-c.w)/2;
y += c.h;
c.y = 0|y;
acc_h += c._h;
accfilly += 0|c.filly;
y = acc_h + Math.floor(accfilly*(l.h-l._h)/filly);
c.h = 0|(y - c.y);
c.w = 0|(c.fillx ? l.w - (l.pad<<1) : c._w);
c.x = 0|(l.x + (0|l.pad) + ((1+(0|c.halign))*(l.w-(l.pad<<1)-c.w)>>1));
if (c.c) this.layout(c);
});
break;
@ -288,8 +292,8 @@ Layout.prototype.update = function() {
if (l.r&1) { // rotation
var t = l._w;l._w=l._h;l._h=t;
}
l._w = Math.max(l._w + (l.pad<<1), 0|l.width);
l._h = Math.max(l._h + (l.pad<<1), 0|l.height);
l._w = 0|Math.max(l._w + (l.pad<<1), 0|l.width);
l._h = 0|Math.max(l._h + (l.pad<<1), 0|l.height);
}
var cb = {
"txt" : function(l) {
@ -349,8 +353,8 @@ Layout.prototype.update = function() {
} else {
l.w = l._w;
l.h = l._h;
l.x = (w-l.w)/2;
l.y = y+(h-l.h)/2;
l.x = (w-l.w)>>1;
l.y = y+((h-l.h)>>1);
}
// layout children
this.layout(l);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB