Skip to content

Commit e91c350

Browse files
authored
Merge pull request #4030 from RKBoss6/phoneRemind
[Phone Reminder] Create new app
2 parents 959777c + 0e9cf25 commit e91c350

File tree

6 files changed

+283
-0
lines changed

6 files changed

+283
-0
lines changed

apps/phoneremind/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Phone Reminder
2+
This app detects when bluetooth disconnects from the watch and shows you a prompt so you can check if you left your phone behind.
3+
When the prompt shows, you can choose to set the location you are currently at as a familiar location, so it won't alert you whenever you are nearby.
4+
5+
This app uses the `MyLocation` app. To set up dynamic location updating with an iOS device, you can use the `BangleDumpLocation` shortcut to push the lcoation.
6+
For more information on automating this and setup, look [here.](https://banglejs.com/apps/?id=ios&readme)
7+
8+
This app does not use the watch GPS.
9+
10+
## Settings
11+
* <b>Precision</b> - Change how close you need to be to a familiar location in order for it to not alert you.
12+
* <b>Check Delay</b> - Change how long after the phone is disconnected that it alerts you. If your phone randomly disconnects and then reconnects, adjusting this value will ensure it does not get triggered until that time is up and it is still disconnected.
13+
* <b>Delete Locations</b> - Deletes all familiar locations.
14+
15+
## TODO
16+
- Add a setting to use watch GPS to get the location instead of myLocation.
17+
- Make a way to save phone MAC address to know what device is connected
18+
19+
## Creator
20+
RKBoss6

apps/phoneremind/boot.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
{
2+
let locationsFile = "phoneremind.json";
3+
let connected;
4+
let buzzInterval;
5+
let promptShown = false;
6+
let addLocation = function (location) {
7+
8+
let locs = require("Storage").readJSON(locationsFile, 1) || [];
9+
locs.push(location);
10+
require("Storage").writeJSON(locationsFile, locs);
11+
12+
}
13+
let getSettings=function(){
14+
return Object.assign({
15+
precision: 30,
16+
timeDelay:30000
17+
}, require('Storage').readJSON("phoneremind.settings.json", true) || {});
18+
}
19+
let getAllLocations = function () {
20+
return require("Storage").readJSON(locationsFile, 1) || [];
21+
};
22+
23+
let getMyLocation = function () {
24+
if (!require("Storage").read("mylocation.json")) {
25+
require("Storage").writeJSON("mylocation.json", {
26+
location: "Unknown",
27+
lat: 0,
28+
lon: 0
29+
});
30+
}
31+
return require("Storage").readJSON("mylocation.json", 1);
32+
};
33+
34+
let buzz = function () {
35+
Bangle.buzz(230);
36+
}
37+
38+
let convertCoordsToMeters = function (lat, lon) {
39+
return {
40+
lat: 110574 * lat,
41+
lon: 111320 * Math.cos(lat * Math.PI / 180) * lon
42+
43+
}
44+
}
45+
46+
47+
48+
49+
let disconnected = function () {
50+
connected = false;
51+
var myLocation = getMyLocation();
52+
var locs = getAllLocations();
53+
print(locs);
54+
var useGPS = false;
55+
if (!useGPS) {
56+
57+
myLocation = getMyLocation();
58+
var convLoc = convertCoordsToMeters(myLocation.lat, myLocation.lon)
59+
myLocation.lat = convLoc.lat;
60+
myLocation.lon = convLoc.lon;
61+
62+
locs = getAllLocations();
63+
64+
print(myLocation);
65+
66+
for (let location of locs) {
67+
if (Math.abs(myLocation.lat - location.lat) < getSettings().precision && Math.abs(myLocation.lon - location.lon) < getSettings().precision) {
68+
//at a familiar location, no action needed.
69+
return;
70+
}
71+
}
72+
//no location matched the current one...
73+
74+
75+
76+
setTimeout(function(){
77+
if(connected==true)return;
78+
buzz();
79+
if (require("Storage").readJSON("setting.json", true).quiet != 2) {
80+
81+
setTimeout(function () {
82+
buzzInterval = setInterval(buzz, 850);
83+
}, 750);
84+
}
85+
promptShown = true;
86+
E.showPrompt("Phone was disconnected. It may have been left in " + myLocation.location + ".", {
87+
88+
title: "Phone Left Behind",
89+
buttons: { "Ok": true, "Save Location": false }
90+
91+
}).then(function (answer) {
92+
promptShown = false;
93+
clearInterval(buzzInterval);
94+
if (answer) {
95+
Bangle.load();
96+
} else {
97+
addLocation({
98+
city: myLocation.location,
99+
lat: myLocation.lat,
100+
lon: myLocation.lon
101+
});
102+
E.showPrompt("Added location in " + myLocation.location + " to familiar locations.", {
103+
title: "Location Saved",
104+
buttons: { "Ok": true }
105+
})
106+
.then(function () {
107+
Bangle.load();
108+
});
109+
}
110+
});
111+
},getSettings().timeDelay)
112+
113+
}
114+
}
115+
116+
let connectHandler = function () {
117+
connected = true;
118+
if (promptShown) {
119+
//prompt is shown, dismiss
120+
if (buzzInterval) clearInterval(buzzInterval);
121+
load();
122+
123+
}
124+
125+
}
126+
127+
NRF.on('disconnect', disconnected);
128+
NRF.on('connect', connectHandler);
129+
}

apps/phoneremind/icon.png

6.36 KB
Loading

apps/phoneremind/metadata.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"id": "phoneremind",
3+
"name": "Phone Reminder",
4+
"shortName":"PhoneRemind",
5+
"version":"0.01",
6+
"icon":"icon.png",
7+
"description": "Provides an alert when your phone disconnects, and allows you to set familiar locations where it will not alert. This uses `MyLocation` for location.",
8+
"type":"bootloader",
9+
"tags": "tool,bluetooth",
10+
"author":"RKBoss6",
11+
"supports": ["BANGLEJS2"],
12+
"screenshots" : [ { "url":"scr.png" }],
13+
"dependencies" : { "mylocation":"app"},
14+
"readme":"README.md",
15+
"storage": [
16+
{"name":"phoneremind.boot.js","url":"boot.js"},
17+
{"name":"phoneremind.settings.js","url":"settings.js"}
18+
],
19+
"data": [
20+
{"name":"phoneremind.json"}
21+
]
22+
}

apps/phoneremind/scr.png

26.3 KB
Loading

apps/phoneremind/settings.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
(function(back) {
2+
var FILE = "phoneremind.settings.json";
3+
// Load settings
4+
var settings = Object.assign({
5+
precision: 30,
6+
timeDelay:30000
7+
}, require('Storage').readJSON(FILE, true) || {});
8+
9+
function writeSettings() {
10+
require('Storage').writeJSON(FILE, settings);
11+
}
12+
function selectPrecisionLevel(lvl){
13+
settings.precision=lvl;
14+
writeSettings();
15+
showMainMenu();
16+
17+
}
18+
function formatTime(ms) {
19+
if (ms < 60000) {
20+
// Less than a minute → show seconds
21+
return Math.round(ms / 1000) + 's';
22+
} else {
23+
// One minute or more → show minutes
24+
return Math.round(ms / 60000) + 'm';
25+
}
26+
}
27+
28+
function showPrecisionMenu(back){
29+
30+
let menu = {
31+
'': { 'title': 'Precision' },
32+
'< Back': back,
33+
'Country': function(){
34+
35+
selectPrecisionLevel(20000);
36+
back();
37+
},
38+
'Large City': function(){
39+
40+
selectPrecisionLevel(1200);
41+
back();
42+
},
43+
'Small City': function(){
44+
45+
selectPrecisionLevel(230);
46+
back();
47+
},
48+
'City Block': function(){
49+
50+
selectPrecisionLevel(60);
51+
back();
52+
},
53+
'Building': function(){
54+
55+
selectPrecisionLevel(30);
56+
back();
57+
},
58+
'Meters': function(){
59+
60+
selectPrecisionLevel(1);
61+
back();
62+
},
63+
64+
}
65+
E.showMenu(menu)
66+
}
67+
68+
function showMainMenu(){
69+
// Show the menu
70+
E.showMenu({
71+
"" : { "title" : "Phone Reminder" },
72+
"< Back" : () => back(),
73+
'Check Delay': {
74+
value: 0|settings.timeDelay,
75+
min: 0, max: 600000,
76+
step:5000,
77+
onchange: v => {
78+
settings.timeDelay = v;
79+
writeSettings();
80+
},
81+
format : v => {
82+
return formatTime(v)
83+
}
84+
},
85+
'Precision Level': function(){
86+
showPrecisionMenu(showMainMenu);
87+
88+
// format: ... may be specified as a function which converts the value to a string
89+
// if the value is a boolean, showMenu() will convert this automatically, which
90+
// keeps settings menus consistent
91+
},
92+
93+
94+
95+
'Delete All Locations': function(){
96+
E.showPrompt("Are you sure you want to delete all familiar locations?", {title:"Confirm"})
97+
.then(function(v) {
98+
if (v) {
99+
require("Storage").erase("phoneremind.json");
100+
E.showMessage("Successfully deleted saved locations!","Cleared");
101+
} else {
102+
showMainMenu();
103+
104+
}
105+
});
106+
107+
}
108+
});
109+
}
110+
showMainMenu()
111+
112+
})

0 commit comments

Comments
 (0)