Merge branch 'master' of github.com:espruino/BangleApps
commit
178ae2e532
|
|
@ -1,2 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: Actually upload correct code
|
||||
0.03: Display sea-level pressure, too, and allow calibration
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Bangle.setBarometerPower(true, "app");
|
||||
Bangle.setBarometerPower(true, "altimeter");
|
||||
|
||||
g.clear(1);
|
||||
Bangle.loadWidgets();
|
||||
|
|
@ -10,21 +10,62 @@ var MEDIANLENGTH = 20;
|
|||
var avr = [], median;
|
||||
var value = 0;
|
||||
|
||||
function getStandardPressure(altitude) {
|
||||
const P0 = 1013.25; // standard pressure at sea level in hPa
|
||||
const T0 = 288.15; // standard temperature at sea level in K
|
||||
const g0 = 9.80665; // standard gravitational acceleration in m/s^2
|
||||
const R = 8.31432; // gas constant in J/(mol*K)
|
||||
const M = 0.0289644; // molar mass of air in kg/mol
|
||||
const L = -0.0065; // temperature lapse rate in K/m
|
||||
|
||||
const temperature = T0 + L * altitude; // temperature at the given altitude
|
||||
const pressure = P0 * Math.pow((temperature / T0), (-g0 * M) / (R * L)); // pressure at the given altitude
|
||||
|
||||
return pressure;
|
||||
}
|
||||
|
||||
function convertToSeaLevelPressure(pressure, altitude) {
|
||||
return 1013.25 * (pressure / getStandardPressure(altitude));
|
||||
}
|
||||
|
||||
Bangle.on('pressure', function(e) {
|
||||
while (avr.length>MEDIANLENGTH) avr.pop();
|
||||
avr.unshift(e.altitude);
|
||||
median = avr.slice().sort();
|
||||
g.reset().clearRect(0,y-30,g.getWidth()-10,y+30);
|
||||
g.reset().clearRect(0,y-30,g.getWidth()-10,R.h);
|
||||
if (median.length>10) {
|
||||
var mid = median.length>>1;
|
||||
value = E.sum(median.slice(mid-4,mid+5)) / 9;
|
||||
g.setFont("Vector",50).setFontAlign(0,0).drawString((value-zero).toFixed(1), g.getWidth()/2, y);
|
||||
t = value-zero;
|
||||
if ((t > -100) && (t < 1000))
|
||||
t = t.toFixed(1);
|
||||
else
|
||||
t = t.toFixed(0);
|
||||
g.setFont("Vector",50).setFontAlign(0,0).drawString(t, g.getWidth()/2, y);
|
||||
sea = convertToSeaLevelPressure(e.pressure, value-zero);
|
||||
t = sea.toFixed(1) + " " + e.temperature.toFixed(1);
|
||||
if (0) {
|
||||
print("alt raw:", value.toFixed(1));
|
||||
print("temperature:", e.temperature);
|
||||
print("pressure:", e.pressure);
|
||||
print("sea pressure:", sea);
|
||||
print("std pressure:", getStandardPressure(value-zero));
|
||||
}
|
||||
g.setFont("Vector",25).setFontAlign(-1,0).drawString(t,
|
||||
10, R.y+R.h - 35);
|
||||
}
|
||||
});
|
||||
|
||||
print(g.getFonts());
|
||||
g.reset();
|
||||
g.setFont("6x8").setFontAlign(0,0).drawString(/*LANG*/"ALTITUDE (m)", g.getWidth()/2, y-40);
|
||||
g.setFont("Vector:15");
|
||||
g.setFontAlign(0,0);
|
||||
g.drawString(/*LANG*/"ALTITUDE (m)", g.getWidth()/2, y-40);
|
||||
g.drawString(/*LANG*/"SEA L (hPa) TEMP (C)", g.getWidth()/2, y+62);
|
||||
g.flip();
|
||||
g.setFont("6x8").setFontAlign(0,0,3).drawString(/*LANG*/"ZERO", g.getWidth()-5, g.getHeight()/2);
|
||||
setWatch(function() {
|
||||
zero = value;
|
||||
}, (process.env.HWVERSION==2) ? BTN1 : BTN2, {repeat:true});
|
||||
Bangle.setUI("updown", btn=> {
|
||||
if (!btn) zero=value;
|
||||
if (btn<0) zero-=5;
|
||||
if (btn>0) zero+=5;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{ "id": "altimeter",
|
||||
"name": "Altimeter",
|
||||
"version":"0.02",
|
||||
"version":"0.03",
|
||||
"description": "Simple altimeter that can display height changed using Bangle.js 2's built in pressure sensor.",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,outdoors",
|
||||
|
|
|
|||
|
|
@ -5,3 +5,4 @@
|
|||
0.05: Improved colors (connected vs disconnected)
|
||||
0.06: Tell clock widgets to hide.
|
||||
0.07: Convert Yes/No On/Off in settings to checkboxes
|
||||
0.08: Fixed typo in settings.js for DRAGDOWN to make option work
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "clockcal",
|
||||
"name": "Clock & Calendar",
|
||||
"version": "0.07",
|
||||
"version": "0.08",
|
||||
"description": "Clock with Calendar",
|
||||
"readme":"README.md",
|
||||
"icon": "app.png",
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@
|
|||
value: actions.indexOf(settings.DRAGDOWN),
|
||||
format: v => actions[v],
|
||||
onchange: v => {
|
||||
settings.DRGDOWN = actions[v];
|
||||
settings.DRAGDOWN = actions[v];
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -16,3 +16,4 @@
|
|||
Support for zooming in on map
|
||||
Satellite count moved to widget bar to leave more room for the map
|
||||
0.15: Make track drawing an option (default off)
|
||||
0.16: Draw waypoints, too.
|
||||
|
|
|
|||
|
|
@ -17,20 +17,20 @@ To add a map:
|
|||
* Scroll and zoom to the area of interest or use the Search button in the top left
|
||||
* Now choose the size you want to upload (Small/Medium/etc)
|
||||
* On Bangle.js 1 you can choose if you want a 3 bits per pixel map (this is lower
|
||||
quality but uploads faster and takes less space). On Bangle.js 2 you only have a 3bpp
|
||||
display so can only use 3bpp.
|
||||
quality, but uploads faster and takes less space). Bangle.js 2 is limited to 3bpp.
|
||||
* Click `Get Map`, and a preview will be displayed. If you need to adjust the area you
|
||||
can change settings, move the map around, and click `Get Map` again.
|
||||
* When you're ready, click `Upload`
|
||||
|
||||
## Bangle.js App
|
||||
|
||||
The Bangle.js app allows you to view a map - it also turns the GPS on and marks
|
||||
the path that you've been travelling (if enabled).
|
||||
The Bangle.js app allows you to view a map. It also turns the GPS on
|
||||
and marks the path that you've been travelling (if enabled), and
|
||||
displays waypoints in the watch (if dependencies exist).
|
||||
|
||||
* Drag on the screen to move the map
|
||||
* Press the button to bring up a menu, where you can zoom, go to GPS location
|
||||
, put the map back in its default location, or choose whether to draw the currently
|
||||
* Press the button to bring up a menu, where you can zoom, go to GPS location,
|
||||
put the map back in its default location, or choose whether to draw the currently
|
||||
recording GPS track (from the `Recorder` app).
|
||||
|
||||
**Note:** If enabled, drawing the currently recorded GPS track can take a second
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ var settings = require("Storage").readJSON("openstmap.json",1)||{};
|
|||
function redraw() {
|
||||
g.setClipRect(R.x,R.y,R.x2,R.y2);
|
||||
m.draw();
|
||||
drawPOI();
|
||||
drawMarker();
|
||||
// if track drawing is enabled...
|
||||
if (settings.drawTrack) {
|
||||
|
|
@ -25,6 +26,26 @@ function redraw() {
|
|||
g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1);
|
||||
}
|
||||
|
||||
// Draw the POIs
|
||||
function drawPOI() {
|
||||
try {
|
||||
var waypoints = require("waypoints").load();
|
||||
} catch (ex) {
|
||||
// Waypoints module not available.
|
||||
return;
|
||||
}
|
||||
g.setFont("Vector", 18);
|
||||
waypoints.forEach((wp, idx) => {
|
||||
var p = m.latLonToXY(wp.lat, wp.lon);
|
||||
var sz = 2;
|
||||
g.setColor(0,0,0);
|
||||
g.fillRect(p.x-sz, p.y-sz, p.x+sz, p.y+sz);
|
||||
g.setColor(0,0,0);
|
||||
g.drawString(wp.name, p.x, p.y);
|
||||
print(wp.name);
|
||||
})
|
||||
}
|
||||
|
||||
// Draw the marker for where we are
|
||||
function drawMarker() {
|
||||
if (!fix.fix) return;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"id": "openstmap",
|
||||
"name": "OpenStreetMap",
|
||||
"shortName": "OpenStMap",
|
||||
"version": "0.15",
|
||||
"version": "0.16",
|
||||
"description": "Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are. Once installed this also adds map functionality to `GPS Recorder` and `Recorder` apps",
|
||||
"readme": "README.md",
|
||||
"icon": "app.png",
|
||||
|
|
|
|||
|
|
@ -21,3 +21,4 @@
|
|||
0.22: Automatic translation of strings, some left untranslated.
|
||||
0.23: Update clock_info to avoid a redraw
|
||||
0.24: Redraw clock_info on update and provide color field for condition
|
||||
0.25: Added monochrome parameter to drawIcon in lib
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
function weatherIcon(code) {
|
||||
var ovr = Graphics.createArrayBuffer(24,24,1,{msb:true});
|
||||
weatherLib.drawIcon({code:code},12,12,12,ovr);
|
||||
weatherLib.drawIcon({code:code},12,12,12,ovr,true);
|
||||
var img = ovr.asImage();
|
||||
img.transparent = 0;
|
||||
return img;
|
||||
|
|
|
|||
|
|
@ -155,14 +155,11 @@ exports.getColor = function(code) {
|
|||
* @param y Top
|
||||
* @param r Icon Size
|
||||
* @param ovr Graphics instance (or undefined for g)
|
||||
* @param monochrome If true, produce a monochromatic icon
|
||||
*/
|
||||
exports.drawIcon = function(cond, x, y, r, ovr) {
|
||||
exports.drawIcon = function(cond, x, y, r, ovr, monochrome) {
|
||||
var palette;
|
||||
var monochrome=1;
|
||||
if(!ovr) {
|
||||
ovr = g;
|
||||
monochrome=0;
|
||||
}
|
||||
if(!ovr) ovr = g;
|
||||
|
||||
palette = getPalette(monochrome, ovr);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "weather",
|
||||
"name": "Weather",
|
||||
"version": "0.24",
|
||||
"version": "0.25",
|
||||
"description": "Show Gadgetbridge weather report",
|
||||
"icon": "icon.png",
|
||||
"screenshots": [{"url":"screenshot.png"}],
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"id": "widbtstates",
|
||||
"name": "Bluetooth States",
|
||||
"version": "0.01",
|
||||
"description": "If active, shows a white bluetooth icon, if connected, a blue one (nothing if sleeping)",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
"tags": "widget,bluetooth,clkinfo",
|
||||
"provides_widgets" : ["bluetooth"],
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"widbtstates.wid.js","url":"widget.js"}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
"use strict";
|
||||
(function () {
|
||||
"ram";
|
||||
var _a;
|
||||
var state = (function () {
|
||||
var status = NRF.getSecurityStatus();
|
||||
if (status.connected)
|
||||
return 2;
|
||||
if (status.advertising)
|
||||
return 1;
|
||||
return 0;
|
||||
})();
|
||||
var width = function () { return state > 0 ? 15 : 0; };
|
||||
var update = function (newState) {
|
||||
state = newState;
|
||||
WIDGETS["bluetooth"].width = width();
|
||||
setTimeout(Bangle.drawWidgets, 50);
|
||||
};
|
||||
var colours = (_a = {},
|
||||
_a[1] = {
|
||||
false: "#fff",
|
||||
true: "#fff",
|
||||
},
|
||||
_a[2] = {
|
||||
false: "#0ff",
|
||||
true: "#00f",
|
||||
},
|
||||
_a);
|
||||
WIDGETS["bluetooth"] = {
|
||||
area: "tl",
|
||||
sortorder: -1,
|
||||
draw: function () {
|
||||
if (state == 0)
|
||||
return;
|
||||
g.reset();
|
||||
g.setColor(colours[state]["".concat(g.theme.dark)]);
|
||||
g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="), this.x + 2, this.y + 2);
|
||||
},
|
||||
width: width(),
|
||||
};
|
||||
NRF.on("connect", update.bind(null, 2));
|
||||
NRF.on("disconnect", update.bind(null, 1));
|
||||
var origWake = NRF.wake;
|
||||
var origSleep = NRF.sleep;
|
||||
NRF.wake = function () {
|
||||
update(1);
|
||||
return origWake.apply(this, arguments);
|
||||
};
|
||||
NRF.sleep = function () {
|
||||
update(0);
|
||||
return origSleep.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,77 @@
|
|||
(() => {
|
||||
"ram";
|
||||
|
||||
const enum State {
|
||||
Asleep,
|
||||
Active,
|
||||
Connected
|
||||
}
|
||||
|
||||
let state: State = (() => {
|
||||
const status = NRF.getSecurityStatus();
|
||||
|
||||
if (status.connected) return State.Connected;
|
||||
if (status.advertising) return State.Active;
|
||||
return State.Asleep;
|
||||
})();
|
||||
|
||||
const width = () => state > State.Asleep ? 15 : 0;
|
||||
|
||||
const update = (newState: State) => {
|
||||
state = newState;
|
||||
WIDGETS["bluetooth"]!.width = width();
|
||||
setTimeout(Bangle.drawWidgets, 50); // no need for .bind()
|
||||
};
|
||||
|
||||
type DarkTheme = `${boolean}`;
|
||||
const colours: {
|
||||
[key in State.Active | State.Connected]: {
|
||||
[key in DarkTheme]: ColorResolvable
|
||||
}
|
||||
} = {
|
||||
[State.Active]: {
|
||||
false: "#fff",
|
||||
true: "#fff",
|
||||
},
|
||||
[State.Connected]: {
|
||||
false: "#0ff",
|
||||
true: "#00f",
|
||||
},
|
||||
};
|
||||
|
||||
WIDGETS["bluetooth"] = {
|
||||
area: "tl",
|
||||
sortorder: -1,
|
||||
draw: function() {
|
||||
if (state == State.Asleep)
|
||||
return;
|
||||
|
||||
g.reset();
|
||||
|
||||
g.setColor(colours[state][`${g.theme.dark}`]);
|
||||
|
||||
g.drawImage(
|
||||
atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="),
|
||||
this.x! + 2,
|
||||
this.y! + 2
|
||||
);
|
||||
},
|
||||
width: width(),
|
||||
};
|
||||
|
||||
NRF.on("connect", update.bind(null, State.Connected));
|
||||
NRF.on("disconnect", update.bind(null, State.Active));
|
||||
|
||||
const origWake = NRF.wake;
|
||||
const origSleep = NRF.sleep;
|
||||
|
||||
NRF.wake = function() {
|
||||
update(State.Active);
|
||||
return origWake.apply(this, arguments);
|
||||
};
|
||||
|
||||
NRF.sleep = function() {
|
||||
update(State.Asleep);
|
||||
return origSleep.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
|
@ -183,6 +183,23 @@ type NRFFilters = {
|
|||
manufacturerData?: object;
|
||||
};
|
||||
|
||||
type NRFSecurityStatus = {
|
||||
advertising: boolean,
|
||||
} & (
|
||||
{
|
||||
connected: true,
|
||||
encrypted: boolean,
|
||||
mitm_protected: boolean,
|
||||
bonded: boolean,
|
||||
connected_addr?: string,
|
||||
} | {
|
||||
connected: false,
|
||||
encrypted: false,
|
||||
mitm_protected: false,
|
||||
bonded: false,
|
||||
}
|
||||
);
|
||||
|
||||
type ImageObject = {
|
||||
width: number;
|
||||
height: number;
|
||||
|
|
@ -721,7 +738,7 @@ declare class NRF {
|
|||
* @returns {any} An object
|
||||
* @url http://www.espruino.com/Reference#l_NRF_getSecurityStatus
|
||||
*/
|
||||
static getSecurityStatus(): any;
|
||||
static getSecurityStatus(): NRFSecurityStatus;
|
||||
|
||||
/**
|
||||
* @returns {any} An object
|
||||
|
|
@ -1898,6 +1915,7 @@ declare class NRF {
|
|||
* encrypted // Communication on this link is encrypted.
|
||||
* mitm_protected // The encrypted communication is also protected against man-in-the-middle attacks.
|
||||
* bonded // The peer is bonded with us
|
||||
* advertising // Are we currently advertising?
|
||||
* connected_addr // If connected=true, the MAC address of the currently connected device
|
||||
* }
|
||||
* ```
|
||||
|
|
@ -1906,7 +1924,7 @@ declare class NRF {
|
|||
* @returns {any} An object
|
||||
* @url http://www.espruino.com/Reference#l_NRF_getSecurityStatus
|
||||
*/
|
||||
static getSecurityStatus(): any;
|
||||
static getSecurityStatus(): NRFSecurityStatus;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -4553,7 +4571,7 @@ declare class BluetoothRemoteGATTServer {
|
|||
* @returns {any} An object
|
||||
* @url http://www.espruino.com/Reference#l_BluetoothRemoteGATTServer_getSecurityStatus
|
||||
*/
|
||||
getSecurityStatus(): any;
|
||||
getSecurityStatus(): NRFSecurityStatus;
|
||||
|
||||
/**
|
||||
* See `NRF.connect` for usage examples.
|
||||
|
|
|
|||
Loading…
Reference in New Issue