Merge branch 'espruino:master' into Weather-Feels-Like-Updates
commit
54f8807af8
|
|
@ -19,3 +19,4 @@
|
|||
0.18: Fix UTF8 conversion (check for `font` library, not `fonts`)
|
||||
0.19: Convert numeric weather values to int from BangleDumpWeather shortcut
|
||||
0.20: Add feels-like temperature data field to weather parsing from BangleDumpWeather shortcut.
|
||||
0.21: Add BangleDumpLocation shortcut, to update location data on watch without needing to use the watch's GPS, and added more app names/ ids.
|
||||
|
|
|
|||
|
|
@ -35,20 +35,21 @@ for now. It's just a few bucks/pounds/euro's.
|
|||
If you like to try a free app first, you can always use NRF Toolbox or
|
||||
Bluetooth BLE Device Finder to find and connect your Bangle.
|
||||
|
||||
### Weather and Calendar
|
||||
### Weather, Calendar, and Location
|
||||
|
||||
By using the `Shortcuts` app on your phone, you can send weather and calendar data to your watch. This works by sending a notification, which is read by the watch through ANCS. The watch then parses the notification for the data.
|
||||
By using the `Shortcuts` app on your phone, you can send weather, calendar, and location data to your watch. This works by sending a notification, which is read by the watch through ANCS. The watch then parses the notification for the data.
|
||||
|
||||
While you may write your own shortcuts if you prefer (for example, to get weather from a different source), two are provided:
|
||||
While you may write your own shortcuts if you prefer (for example, to get weather from a different source), three are provided:
|
||||
|
||||
- Calendar shortcut: https://www.icloud.com/shortcuts/4eac12548b4c424dbcdb1bd58cff338f
|
||||
- Weather shortcut: https://www.icloud.com/shortcuts/106c68bfac3746fe9a55761a3be8d092
|
||||
- [Calendar shortcut](https://www.icloud.com/shortcuts/4eac12548b4c424dbcdb1bd58cff338f)
|
||||
- [Weather shortcut](https://www.icloud.com/shortcuts/106c68bfac3746fe9a55761a3be8d092)
|
||||
- [Location shortcut](https://www.icloud.com/shortcuts/853c41e09a8e491f893a63b464d73ea1)
|
||||
|
||||
The weather shortcut requires an OpenWeatherMap api key, which you can get for free from https://openweathermap.org/api. The shortcut will prompt you for this when you add it to your phone.
|
||||
Note: The shortcuts must keep the names defaulted by the shortcut in order for the watch to detect the weather, calender, or location data. If you rename it from `BangleDump...` to something else, it will no longer get the info, and just display it as a notification on the watch.
|
||||
|
||||
These shortcuts can also be automated to run periodically, for example every hour, using the `Automation` tab in the Shortcuts app.
|
||||
|
||||
The shortcuts will send a notification, which can be annoying. One potential workaround for this would be to create a focus mode, and have an automation:
|
||||
The shortcuts will send a notification. Even though the notification is deleted as soon as Bangle.js receives it, it can be quite annoying. One potential workaround for this would be to create a focus mode, and have an automation:
|
||||
- activate the focus mode (hiding notifications from the shortcut)
|
||||
- run the shortcut
|
||||
- deactivate the focus mode
|
||||
|
|
@ -60,4 +61,9 @@ Please file any issues on https://github.com/espruino/BangleApps/issues/new?titl
|
|||
|
||||
## Creator
|
||||
|
||||
Gordon Williams
|
||||
- Gordon Williams
|
||||
|
||||
## Contributors
|
||||
|
||||
- RKBoss6
|
||||
- stweedo
|
||||
|
|
|
|||
111
apps/ios/boot.js
111
apps/ios/boot.js
|
|
@ -78,28 +78,56 @@ E.on('notify',msg=>{
|
|||
"com.apple.reminders": "Reminders",
|
||||
"com.apple.shortcuts": "Shortcuts",
|
||||
"com.apple.TestFlight": "TestFlight",
|
||||
"com.apple.ScreenTimeNotifications": "ScreenTime",
|
||||
"com.apple.ScreenTimeNotifications": "Screen Time",
|
||||
"com.apple.wifid.usernotification": "WiFi",
|
||||
"com.apple.Maps": "Maps",
|
||||
"com.apple.Music": "Apple Music",
|
||||
"com.apple.AppStore": "App Store",
|
||||
"com.apple.Preferences": "Settings",
|
||||
"com.apple.calculator": "Calculator",
|
||||
"com.apple.camera": "Camera",
|
||||
"com.apple.weather": "Weather",
|
||||
"com.apple.VoiceMemos": "Voice Memos",
|
||||
"com.apple.News": "News",
|
||||
"com.apple.tv": "Apple TV",
|
||||
"com.apple.findmy": "Find My",
|
||||
"com.apple.compass": "Compass",
|
||||
"com.apple.measure": "Measure",
|
||||
"com.atebits.Tweetie2": "Twitter",
|
||||
"com.burbn.instagram" : "Instagram",
|
||||
"com.burbn.instagram": "Instagram",
|
||||
"com.facebook.Facebook": "Facebook",
|
||||
"com.facebook.Messenger": "Messenger",
|
||||
"com.google.Chromecast" : "Google Home",
|
||||
"com.google.Gmail" : "GMail",
|
||||
"com.google.hangouts" : "Hangouts",
|
||||
"com.google.ios.youtube" : "YouTube",
|
||||
"com.hammerandchisel.discord" : "Discord",
|
||||
"com.ifttt.ifttt" : "IFTTT",
|
||||
"com.jumbo.app" : "Jumbo",
|
||||
"com.linkedin.LinkedIn" : "LinkedIn",
|
||||
"com.google.Chromecast": "Google Home",
|
||||
"com.google.Gmail": "GMail",
|
||||
"com.google.hangouts": "Hangouts",
|
||||
"com.google.ios.youtube": "YouTube",
|
||||
"com.google.ios.chrome": "Google Chrome",
|
||||
"com.google.Maps": "Google Maps",
|
||||
"com.google.Drive": "Google Drive",
|
||||
"com.google.GoogleMobile": "Google",
|
||||
"com.hammerandchisel.discord": "Discord",
|
||||
"com.ifttt.ifttt": "IFTTT",
|
||||
"com.jumbo.app": "Jumbo",
|
||||
"com.linkedin.LinkedIn": "LinkedIn",
|
||||
"com.marktplaats.iphone": "Marktplaats",
|
||||
"com.microsoft.Office.Outlook" : "Outlook Mail",
|
||||
"com.nestlabs.jasper.release" : "Nest",
|
||||
"com.netflix.Netflix" : "Netflix",
|
||||
"com.reddit.Reddit" : "Reddit",
|
||||
"com.microsoft.Office.Outlook": "Outlook Mail",
|
||||
"com.microsoft.Office.Word": "Microsoft Word",
|
||||
"com.microsoft.Office.Excel": "Microsoft Excel",
|
||||
"com.microsoft.Office.Powerpoint": "Microsoft PowerPoint",
|
||||
"com.nestlabs.jasper.release": "Nest",
|
||||
"com.netflix.Netflix": "Netflix",
|
||||
"com.reddit.Reddit": "Reddit",
|
||||
"com.skype.skype": "Skype",
|
||||
"com.skype.SkypeForiPad": "Skype",
|
||||
"com.spotify.client": "Spotify",
|
||||
"com.soundcloud.TouchApp": "SoundCloud",
|
||||
"com.disney.disneyplus": "Disney+",
|
||||
"com.hbo.hbonow": "HBO Max",
|
||||
"com.amazon.Amazon": "Amazon Shopping",
|
||||
"com.amazon.AmazonVideo": "Prime Video",
|
||||
"com.dropbox.Dropbox": "Dropbox",
|
||||
"com.evernote.iPhone.Evernote": "Evernote",
|
||||
"com.trello": "Trello",
|
||||
"com.storytel.iphone": "Storytel",
|
||||
"com.strava.stravaride": "Strava",
|
||||
"com.tinyspeck.chatlyio": "Slack",
|
||||
|
|
@ -110,20 +138,22 @@ E.on('notify',msg=>{
|
|||
"com.valvesoftware.Steam": "Steam",
|
||||
"com.vilcsak.bitcoin2": "Coinbase",
|
||||
"com.wordfeud.free": "WordFeud",
|
||||
"com.yourcompany.PPClient": "PayPal",
|
||||
"com.paypal.PPClient": "PayPal",
|
||||
"com.zhiliaoapp.musically": "TikTok",
|
||||
"com.pinterest": "Pinterest",
|
||||
"com.tumblr.tumblr": "Tumblr",
|
||||
"de.no26.Number26": "N26",
|
||||
"io.robbie.HomeAssistant": "Home Assistant",
|
||||
"net.superblock.Pushover": "Pushover",
|
||||
"net.weks.prowl": "Prowl",
|
||||
"net.whatsapp.WhatsApp": "WhatsApp",
|
||||
"nl.ah.Appie": "Albert Heijn",
|
||||
"nl.postnl.TrackNTrace": "PostNL",
|
||||
"org.whispersystems.signal": "Signal",
|
||||
"ph.telegra.Telegraph": "Telegram",
|
||||
"tv.twitch": "Twitch",
|
||||
// could also use NRF.ancsGetAppInfo(msg.appId) here
|
||||
};
|
||||
"tv.twitch": "Twitch"
|
||||
};
|
||||
|
||||
|
||||
|
||||
//if (appNames[msg.appId]) msg.a
|
||||
if (msg.title === "BangleDumpCalendar") {
|
||||
|
|
@ -191,7 +221,7 @@ E.on('notify',msg=>{
|
|||
wind: d.wind,
|
||||
wdir: d.wdir,
|
||||
loc: d.loc
|
||||
}
|
||||
};
|
||||
// Convert string fields to numbers for iOS weather shortcut
|
||||
const numFields = ['code', 'wdir', 'temp','feels', 'hi', 'lo', 'hum', 'wind', 'uv', 'rain'];
|
||||
numFields.forEach(field => {
|
||||
|
|
@ -201,6 +231,47 @@ E.on('notify',msg=>{
|
|||
NRF.ancsAction(msg.uid, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.title === "BangleDumpLocation") {
|
||||
|
||||
const d = JSON.parse(msg.message);
|
||||
|
||||
/* Example:
|
||||
{"lat":"2912.0744", "lon":"2333.332", "city":"Chicago"}*/
|
||||
let locationJson = {
|
||||
t: "location",
|
||||
lat:d.lat,
|
||||
lon:d.lon,
|
||||
city:d.city
|
||||
|
||||
};
|
||||
// Convert string fields to numbers
|
||||
const numFields = ['lat', 'lon'];
|
||||
numFields.forEach(field => {
|
||||
if (locationJson[field] != null) locationJson[field] = +locationJson[field];
|
||||
});
|
||||
|
||||
//load mylocation file
|
||||
let myLocationJson = Object.assign({
|
||||
lat: d.lat,
|
||||
lon: d.lon,
|
||||
location:d.city
|
||||
}, require("Storage").readJSON("mylocation.json", true) || {});
|
||||
//remove notification from phone
|
||||
NRF.ancsAction(msg.uid, false);
|
||||
if(Math.abs(myLocationJson.lat - locationJson.lat) < 0.0001 && Math.abs(myLocationJson.lon -locationJson.lon) < 0.0001){
|
||||
//same location, do not write
|
||||
return;
|
||||
}
|
||||
|
||||
myLocationJson.lon=locationJson.lon;
|
||||
myLocationJson.lat=locationJson.lat;
|
||||
myLocationJson.location=locationJson.city;
|
||||
require("Storage").write("mylocation.json",myLocationJson);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
require("messages").pushMessage({
|
||||
t : msg.event,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"id": "ios",
|
||||
"name": "iOS Integration",
|
||||
"version": "0.20",
|
||||
"description": "Display/pull notifications, music, weather, and agenda from iOS devices",
|
||||
"version": "0.21",
|
||||
"description": "Display/pull notifications, music, weather, location, and agenda from iOS devices",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,system,ios,apple,messages,notifications",
|
||||
"dependencies": {"messages":"module"},
|
||||
"dependencies" : {"mylocation":"app" },
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -14,3 +14,4 @@
|
|||
Log additional timestamp for trace log
|
||||
0.11: Minor code improvements
|
||||
0.12: Round monotonic percentage, rename to stable percentage/voltage
|
||||
0.13: Fix stable percentage not updating
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
require('Storage').readJSON("powermanager.default.json", true) || {},
|
||||
require('Storage').readJSON("powermanager.json", true) || {}
|
||||
);
|
||||
|
||||
|
||||
if (settings.log) {
|
||||
let logFile = require('Storage').open("powermanager.log","a");
|
||||
let def = require('Storage').readJSON("powermanager.def.json", true) || {};
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
let hw = require('Storage').readJSON("powermanager.hw.json", true) || {};
|
||||
if (!hw.start) hw.start = Date.now();
|
||||
if (!hw.power) hw.power = {};
|
||||
|
||||
|
||||
const saveEvery = 1000 * 60 * 5;
|
||||
const TO_WRAP = ["GPS","Compass","Barometer","HRM","LCD"];
|
||||
|
||||
|
|
@ -28,9 +28,7 @@
|
|||
require('Storage').writeJSON("powermanager.hw.json", hw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
setInterval(save, saveEvery);
|
||||
|
||||
E.on("kill", ()=>{
|
||||
|
|
@ -77,7 +75,6 @@
|
|||
})(Bangle[functionName]);
|
||||
}
|
||||
|
||||
|
||||
let wrapDeferred = ((o,t) => (a) => {
|
||||
if (a == eval || typeof a == "string") {
|
||||
return o.apply(this, arguments);
|
||||
|
|
@ -133,25 +130,19 @@
|
|||
handleCharging(Bangle.isCharging());
|
||||
}
|
||||
|
||||
var savedBatPercent=E.getBattery();
|
||||
if (settings.forceMonoPercentage){
|
||||
var newPercent =Math.round((E.getBattery()+E.getBattery()+E.getBattery()+E.getBattery()+E.getBattery()+E.getBattery())/6);
|
||||
|
||||
var p = Math.round((E.getBattery()+E.getBattery()+E.getBattery()+E.getBattery())/4);
|
||||
var op = E.getBattery;
|
||||
E.getBattery = function() {
|
||||
|
||||
if(Bangle.isCharging()){
|
||||
if(newPercent > savedBatPercent)
|
||||
savedBatPercent = newPercent;
|
||||
}else{
|
||||
if(newPercent < savedBatPercent)
|
||||
savedBatPercent = newPercent;
|
||||
}
|
||||
return savedBatPercent;
|
||||
};
|
||||
var current = Math.round((op()+op()+op()+op())/4);
|
||||
if (Bangle.isCharging() && current > p) p = current;
|
||||
if (!Bangle.isCharging() && current < p) p = current;
|
||||
return p;
|
||||
};
|
||||
}
|
||||
|
||||
if (settings.forceMonoVoltage){
|
||||
var v = (NRF.getBattery()+NRF.getBattery()+NRF.getBattery()+NRF.getBattery()+NRF.getBattery()+NRF.getBattery())/6;
|
||||
var v = (NRF.getBattery()+NRF.getBattery()+NRF.getBattery()+NRF.getBattery())/4;
|
||||
var ov = NRF.getBattery;
|
||||
NRF.getBattery = function() {
|
||||
var current = (ov()+ov()+ov()+ov())/4;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"id": "powermanager",
|
||||
"name": "Power Manager",
|
||||
"shortName": "Power Manager",
|
||||
"version": "0.12",
|
||||
"version": "0.13",
|
||||
"description": "Allow configuration of warnings for battery charging, stabilization of voltage, stabilization of battery percentage, and battery logging.",
|
||||
"icon": "app.png",
|
||||
"type": "bootloader",
|
||||
|
|
|
|||
|
|
@ -60,4 +60,5 @@
|
|||
Lower accuracy of barometer data to ~1cm (saves about 15b/record)
|
||||
0.47: Fix 'blip' on speed map on some recordings
|
||||
Ensure Battery voltage is only stored to 0.01v
|
||||
Add graphs for Steps+Battery
|
||||
Add graphs for Steps+Battery
|
||||
0.48: Add ability to log average acceleration values
|
||||
|
|
@ -19,6 +19,7 @@ You can record
|
|||
* **BAT** Battery percentage and voltage
|
||||
* **Steps** Steps counted by the step counter
|
||||
* **Baro** (Bangle.js 2) Using the built-in barometer to record Temperature, Pressure and Altitude
|
||||
* **Accel** Average acceleration values in X,Y and Z
|
||||
* **Core** CoreTemp body temperature *if* you have a CoreTemp device and the https://banglejs.com/apps/?id=coretemp app installed
|
||||
|
||||
You can then start/stop recording from the Recorder app itself (and as long as widgets are
|
||||
|
|
@ -29,12 +30,29 @@ Some apps like the [Run app](https://banglejs.com/apps/?id=run) are able to auto
|
|||
as well. They need to define a `foobar.recorder.js` file - see the `getRecorders`
|
||||
function in `lib.js` for more information.
|
||||
|
||||
## Graphing
|
||||
## Viewing and Downloading Data
|
||||
|
||||
You can download the information to the PC using [the App Loader](https://banglejs.com/apps/?id=recorder). Connect
|
||||
to your Bangle, then in `My Apps` click the disk icon next to the `Recorder` app to download data.
|
||||
You can download and visualize the information using [the App Loader](https://banglejs.com/apps/?id=recorder). Connect
|
||||
to your Bangle, then in `My Apps` click the disk icon next to the `Recorder` app to access the download interface.
|
||||
|
||||
You can also view some information on the watch.
|
||||
### Interactive Web Interface
|
||||
|
||||
The download interface provides individual track visualization with:
|
||||
|
||||
* **Interactive Leaflet maps** - Each GPS track gets its own map using OpenStreetMap tiles
|
||||
* **Track statistics** - Distance, duration, and track points automatically calculated
|
||||
* **Start/End markers** - Green circles mark track start, red circles mark end points
|
||||
* **Interactive track points** - Click anywhere along the GPS track to see detailed data at that point
|
||||
* **Data popups** - View available data for each point (time, heart rate, altitude, speed, steps, battery, barometer - if recorded)
|
||||
* **Interactive charts** - Collapsible graphs for heart rate, battery, steps, elevation, speed, and barometer data with PNG export
|
||||
* **Download options** - KML, GPX, and CSV formats for individual tracks or all at once
|
||||
* **Settings** - Option to include/exclude entries without GPS coordinates
|
||||
* **Unit preferences** - Choose between metric, imperial, or auto-detect based on your locale
|
||||
* **Mobile responsive** - Works well on all devices
|
||||
|
||||
### On-Watch Visualization
|
||||
|
||||
You can also view some information on the watch:
|
||||
|
||||
* Tap `View Tracks`
|
||||
* Tap on the Track number you're interested in, and you'll see a page with information about that track...
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -114,6 +114,28 @@ exports.getRecorders = function() {
|
|||
stop : () => {},
|
||||
draw : (x,y) => g.reset().drawImage(atob("DAwBAAMMeeeeeeeecOMMAAMMMMAA"),x,y)
|
||||
};
|
||||
},
|
||||
accel:function() {
|
||||
var ax=0,ay=0,az=0,n=0;
|
||||
function onAccel(a) {
|
||||
ax += a.x;
|
||||
ay += a.y;
|
||||
az += a.z;
|
||||
n++;
|
||||
}
|
||||
return {
|
||||
name : "Accel",
|
||||
fields : ["Accel X", "Accel Y", "Accel Z"],
|
||||
getValues : () => {
|
||||
if (n<1) n=1;
|
||||
var r = [(ax/n).toFixed(2), (ay/n).toFixed(2), (az/n).toFixed(2)];
|
||||
n = ax = ay = az = 0;
|
||||
return r;
|
||||
},
|
||||
start : () => { Bangle.on('accel', onAccel); },
|
||||
stop : () => { Bangle.removeListener('accel', onAccel); },
|
||||
draw : (x,y) => g.reset().drawImage(atob("DAwBAAMMeeeeeeeecOMMAAMMMMAA"),x,y)
|
||||
};
|
||||
}
|
||||
};
|
||||
if (Bangle.getPressure){
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"id": "recorder",
|
||||
"name": "Recorder",
|
||||
"shortName": "Recorder",
|
||||
"version": "0.47",
|
||||
"version": "0.48",
|
||||
"description": "Record GPS position, heart rate and more in the background, then download to your PC.",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,outdoors,gps,widget,clkinfo",
|
||||
|
|
|
|||
Loading…
Reference in New Issue