2024-05-21 20:53:50 +00:00
/* global GB */
2024-05-24 08:02:32 +00:00
{
let gbSend = function ( message ) {
2021-11-04 17:16:02 +00:00
Bluetooth . println ( "" ) ;
Bluetooth . println ( JSON . stringify ( message ) ) ;
}
2024-05-24 08:02:32 +00:00
let lastMsg ; // for music messages - may not be needed now...
let actInterval ; // Realtime activity reporting interval when `act` is true
let actHRMHandler ; // For Realtime activity reporting
let gpsState = { } ; // keep information on GPS via Gadgetbridge
2021-11-04 17:16:02 +00:00
2023-01-25 09:29:34 +00:00
// this settings var is deleted after this executes to save memory
2024-05-24 08:02:32 +00:00
let settings = require ( "Storage" ) . readJSON ( "android.settings.json" , 1 ) || { } ;
2022-04-24 07:24:43 +00:00
//default alarm settings
if ( settings . rp == undefined ) settings . rp = true ;
if ( settings . as == undefined ) settings . as = true ;
if ( settings . vibrate == undefined ) settings . vibrate = ".." ;
require ( 'Storage' ) . writeJSON ( "android.settings.json" , settings ) ;
2024-05-24 08:02:32 +00:00
let _GB = global . GB ;
2023-06-13 19:41:45 +00:00
let fetchRecInterval ;
2021-11-04 17:16:02 +00:00
global . GB = ( event ) => {
// feed a copy to other handlers if there were any
if ( _GB ) setTimeout ( _GB , 0 , Object . assign ( { } , event ) ) ;
2023-06-13 19:41:45 +00:00
2021-11-04 17:16:02 +00:00
/* TODO: Call handling, fitness */
var HANDLERS = {
// {t:"notify",id:int, src,title,subject,body,sender,tel:string} add
2022-05-24 12:08:43 +00:00
"notify" : function ( ) {
Object . assign ( event , { t : "add" , positive : true , negative : true } ) ;
// Detect a weird GadgetBridge bug and fix it
// For some reason SMS messages send two GB notifications, with different sets of info
if ( lastMsg && event . body == lastMsg . body && lastMsg . src == undefined && event . src == "Messages" ) {
// Mutate the other message
event . id = lastMsg . id ;
}
lastMsg = event ;
require ( "messages" ) . pushMessage ( event ) ;
} ,
2021-11-04 17:16:02 +00:00
// {t:"notify~",id:int, title:string} // modified
"notify~" : function ( ) { event . t = "modify" ; require ( "messages" ) . pushMessage ( event ) ; } ,
// {t:"notify-",id:int} // remove
"notify-" : function ( ) { event . t = "remove" ; require ( "messages" ) . pushMessage ( event ) ; } ,
// {t:"find", n:bool} // find my phone
"find" : function ( ) {
if ( Bangle . findDeviceInterval ) {
clearInterval ( Bangle . findDeviceInterval ) ;
delete Bangle . findDeviceInterval ;
}
if ( event . n ) // Ignore quiet mode: we always want to find our watch
Bangle . findDeviceInterval = setInterval ( _ => Bangle . buzz ( ) , 1000 ) ;
} ,
// {t:"musicstate", state:"play/pause",position,shuffle,repeat}
"musicstate" : function ( ) {
require ( "messages" ) . pushMessage ( { t : "modify" , id : "music" , title : "Music" , state : event . state } ) ;
} ,
// {t:"musicinfo", artist,album,track,dur,c(track count),n(track num}
"musicinfo" : function ( ) {
require ( "messages" ) . pushMessage ( Object . assign ( event , { t : "modify" , id : "music" , title : "Music" } ) ) ;
2021-11-23 16:28:34 +00:00
} ,
// {"t":"call","cmd":"incoming/end","name":"Bob","number":"12421312"})
2021-11-23 16:31:42 +00:00
"call" : function ( ) {
2021-11-23 20:20:37 +00:00
Object . assign ( event , {
t : event . cmd == "incoming" ? "add" : "remove" ,
id : "call" , src : "Phone" ,
positive : true , negative : true ,
2022-12-02 21:45:10 +00:00
title : event . name || /*LANG*/ "Call" , body : /*LANG*/ "Incoming call\n" + event . number } ) ;
2021-11-23 16:28:34 +00:00
require ( "messages" ) . pushMessage ( event ) ;
} ,
2024-09-03 21:57:35 +00:00
"canned_responses_sync" : function ( ) {
require ( "Storage" ) . writeJSON ( "replies.json" , event . d ) ;
} ,
2023-01-25 09:29:34 +00:00
// {"t":"alarm", "d":[{h:int,m:int,rep:int},... }
2022-04-24 07:24:43 +00:00
"alarm" : function ( ) {
//wipe existing GB alarms
2022-04-25 13:02:12 +00:00
var sched ;
try { sched = require ( "sched" ) ; } catch ( e ) { }
if ( ! sched ) return ; // alarms may not be installed
var gbalarms = sched . getAlarms ( ) . filter ( a => a . appid == "gbalarms" ) ;
for ( var i = 0 ; i < gbalarms . length ; i ++ )
sched . setAlarm ( gbalarms [ i ] . id , undefined ) ;
var alarms = sched . getAlarms ( ) ;
2022-04-25 12:42:00 +00:00
var time = new Date ( ) ;
var currentTime = time . getHours ( ) * 3600000 +
time . getMinutes ( ) * 60000 +
time . getSeconds ( ) * 1000 ;
for ( var j = 0 ; j < event . d . length ; j ++ ) {
// prevents all alarms from going off at once??
var dow = event . d [ j ] . rep ;
2024-01-31 18:39:56 +00:00
var rp = false ;
if ( ! dow ) {
dow = 127 ; //if no DOW selected, set alarm to all DOW
} else {
rp = true ;
}
2022-04-25 12:42:00 +00:00
var last = ( event . d [ j ] . h * 3600000 + event . d [ j ] . m * 60000 < currentTime ) ? ( new Date ( ) ) . getDate ( ) : 0 ;
2022-05-18 07:08:11 +00:00
var a = require ( "sched" ) . newDefaultAlarm ( ) ;
2022-05-18 08:09:12 +00:00
a . id = "gb" + j ;
a . appid = "gbalarms" ;
2023-08-05 23:23:40 +00:00
a . on = event . d [ j ] . on !== undefined ? event . d [ j ] . on : true ;
2022-05-18 08:09:12 +00:00
a . t = event . d [ j ] . h * 3600000 + event . d [ j ] . m * 60000 ;
a . dow = ( ( dow & 63 ) << 1 ) | ( dow >> 6 ) ; // Gadgetbridge sends DOW in a different format
2024-01-31 18:39:56 +00:00
a . rp = rp ;
2022-05-18 08:09:12 +00:00
a . last = last ;
2022-04-24 07:24:43 +00:00
alarms . push ( a ) ;
}
2022-04-25 13:02:12 +00:00
sched . setAlarms ( alarms ) ;
sched . reload ( ) ;
2022-04-24 07:24:43 +00:00
} ,
2022-05-26 13:29:38 +00:00
//TODO perhaps move those in a library (like messages), used also for viewing events?
2022-06-03 06:44:13 +00:00
//add and remove events based on activity on phone (pebble-like)
2023-01-25 09:29:34 +00:00
// {t:"calendar", id:int, type:int, timestamp:seconds, durationInSeconds, title:string, description:string,location:string,calName:string.color:int,allDay:bool
2022-05-26 13:29:38 +00:00
"calendar" : function ( ) {
2022-05-30 19:36:07 +00:00
var cal = require ( "Storage" ) . readJSON ( "android.calendar.json" , true ) ;
if ( ! cal || ! Array . isArray ( cal ) ) cal = [ ] ;
2022-06-01 15:39:09 +00:00
var i = cal . findIndex ( e => e . id == event . id ) ;
if ( i < 0 )
cal . push ( event ) ;
else
cal [ i ] = event ;
2022-05-26 13:29:38 +00:00
require ( "Storage" ) . writeJSON ( "android.calendar.json" , cal ) ;
} ,
2023-01-25 09:29:34 +00:00
// {t:"calendar-", id:int}
2022-05-26 13:29:38 +00:00
"calendar-" : function ( ) {
2022-05-30 19:36:07 +00:00
var cal = require ( "Storage" ) . readJSON ( "android.calendar.json" , true ) ;
//if any of those happen we are out of sync!
2022-11-24 09:44:48 +00:00
if ( ! cal || ! Array . isArray ( cal ) ) cal = [ ] ;
2024-05-24 08:10:51 +00:00
if ( Array . isArray ( event . id ) )
cal = cal . filter ( e => ! event . id . includes ( e . id ) ) ;
else
cal = cal . filter ( e => e . id != event . id ) ;
2022-05-26 13:29:38 +00:00
require ( "Storage" ) . writeJSON ( "android.calendar.json" , cal ) ;
2022-06-08 15:45:39 +00:00
} ,
//triggered by GB, send all ids
2023-01-25 09:29:34 +00:00
// { t:"force_calendar_sync_start" }
2022-06-08 15:45:39 +00:00
"force_calendar_sync_start" : function ( ) {
var cal = require ( "Storage" ) . readJSON ( "android.calendar.json" , true ) ;
if ( ! cal || ! Array . isArray ( cal ) ) cal = [ ] ;
gbSend ( { t : "force_calendar_sync" , ids : cal . map ( e => e . id ) } ) ;
2022-06-28 14:31:57 +00:00
} ,
2023-01-25 09:29:34 +00:00
// {t:"http",resp:"......",[id:"..."]}
2022-06-28 14:31:57 +00:00
"http" : function ( ) {
//get the promise and call the promise resolve
if ( Bangle . httpRequest === undefined ) return ;
2022-07-02 15:00:23 +00:00
var request = Bangle . httpRequest [ event . id ] ;
if ( request === undefined ) return ; //already timedout or wrong id
2022-06-28 14:31:57 +00:00
delete Bangle . httpRequest [ event . id ] ;
2022-07-02 15:00:23 +00:00
clearTimeout ( request . t ) ; //t = timeout variable
2022-06-28 14:31:57 +00:00
if ( event . err !== undefined ) //if is error
2022-07-02 15:00:23 +00:00
request . j ( event . err ) ; //r = reJect function
2022-06-28 14:31:57 +00:00
else
2022-07-02 15:00:23 +00:00
request . r ( event ) ; //r = resolve function
2022-11-06 11:31:13 +00:00
} ,
2023-01-25 09:29:34 +00:00
// {t:"gps", lat, lon, alt, speed, course, time, satellites, hdop, externalSource:true }
2022-11-06 11:31:13 +00:00
"gps" : function ( ) {
2022-11-06 18:25:25 +00:00
if ( ! settings . overwriteGps ) return ;
2023-01-28 08:34:27 +00:00
// modify event for using it as Bangle GPS event
2022-11-06 11:31:13 +00:00
delete event . t ;
2023-02-20 07:17:42 +00:00
if ( ! isFinite ( event . satellites ) ) event . satellites = NaN ;
2023-01-25 08:34:10 +00:00
if ( ! isFinite ( event . course ) ) event . course = NaN ;
2022-11-06 11:31:13 +00:00
event . fix = 1 ;
2023-01-25 09:29:34 +00:00
if ( event . long !== undefined ) { // for earlier Gadgetbridge implementations
2023-01-09 10:51:30 +00:00
event . lon = event . long ;
delete event . long ;
}
2023-02-19 19:37:25 +00:00
if ( event . time ) {
event . time = new Date ( event . time ) ;
}
2023-01-28 08:34:27 +00:00
2023-02-23 19:39:37 +00:00
if ( ! gpsState . lastGPSEvent ) {
2023-01-28 08:34:27 +00:00
// this is the first event, save time of arrival and deactivate internal GPS
Bangle . moveGPSPower ( 0 ) ;
} else {
2023-02-23 19:39:37 +00:00
// this is the second event, store the intervall for expecting the next GPS event
gpsState . interval = Date . now ( ) - gpsState . lastGPSEvent ;
2023-01-28 08:34:27 +00:00
}
2023-02-23 19:39:37 +00:00
gpsState . lastGPSEvent = Date . now ( ) ;
2023-01-28 08:34:27 +00:00
// in any case, cleanup the GPS state in case no new events arrive
if ( gpsState . timeoutGPS ) clearTimeout ( gpsState . timeoutGPS ) ;
gpsState . timeoutGPS = setTimeout ( ( ) => {
// reset state
2023-02-23 19:39:37 +00:00
gpsState . lastGPSEvent = undefined ;
2023-01-28 08:34:27 +00:00
gpsState . timeoutGPS = undefined ;
gpsState . interval = undefined ;
// did not get an expected GPS event but have GPS clients, switch back to internal GPS
if ( Bangle . isGPSOn ( ) ) Bangle . moveGPSPower ( 1 ) ;
} , ( gpsState . interval || 10000 ) + 1000 ) ;
2022-12-29 14:10:23 +00:00
Bangle . emit ( 'GPS' , event ) ;
2022-11-21 19:39:41 +00:00
} ,
2023-01-25 09:29:34 +00:00
// {t:"is_gps_active"}
2022-11-21 19:39:41 +00:00
"is_gps_active" : function ( ) {
2023-01-13 09:31:42 +00:00
gbSend ( { t : "gps_power" , status : Bangle . isGPSOn ( ) } ) ;
2023-01-25 09:29:34 +00:00
} ,
// {t:"act", hrm:bool, stp:bool, int:int}
"act" : function ( ) {
if ( actInterval ) clearInterval ( actInterval ) ;
actInterval = undefined ;
if ( actHRMHandler )
actHRMHandler = undefined ;
Bangle . setHRMPower ( event . hrm , "androidact" ) ;
if ( ! ( event . hrm || event . stp ) ) return ;
if ( ! isFinite ( event . int ) ) event . int = 1 ;
var lastSteps = Bangle . getStepCount ( ) ;
var lastBPM = 0 ;
actHRMHandler = function ( e ) {
lastBPM = e . bpm ;
} ;
Bangle . on ( 'HRM' , actHRMHandler ) ;
actInterval = setInterval ( function ( ) {
var steps = Bangle . getStepCount ( ) ;
2023-08-09 07:50:49 +00:00
gbSend ( { t : "act" , stp : steps - lastSteps , hrm : lastBPM , rt : 1 } ) ;
2023-01-25 09:29:34 +00:00
lastSteps = steps ;
} , event . int * 1000 ) ;
2023-05-19 10:09:16 +00:00
} ,
2023-08-09 07:50:49 +00:00
// {t:"actfetch", ts:long}
"actfetch" : function ( ) {
gbSend ( { t : "actfetch" , state : "start" } ) ;
var actCount = 0 ;
var actCb = function ( r ) {
// The health lib saves the samples at the start of the 10-minute block
// However, GB expects them at the end of the block, so let's offset them
// here to keep a consistent API in the health lib
var sampleTs = r . date . getTime ( ) + 600000 ;
if ( sampleTs >= event . ts ) {
gbSend ( {
t : "act" ,
ts : sampleTs ,
stp : r . steps ,
hrm : r . bpm ,
mov : r . movement
} ) ;
actCount ++ ;
}
}
if ( event . ts != 0 ) {
require ( "health" ) . readAllRecordsSince ( new Date ( event . ts - 600000 ) , actCb ) ;
} else {
require ( "health" ) . readFullDatabase ( actCb ) ;
}
gbSend ( { t : "actfetch" , state : "end" , count : actCount } ) ;
} ,
2023-06-13 19:41:45 +00:00
//{t:"listRecs", id:"20230616a"}
"listRecs" : function ( ) {
let recs = require ( "Storage" ) . list ( /^recorder\.log.*\.csv$/ , { sf : true } ) . map ( s => s . slice ( 12 , 21 ) ) ;
if ( event . id . length > 2 ) { // Handle if there was no id supplied. Then we send a list all available recorder logs back.
let firstNonsyncedIdx = recs . findIndex ( ( logId ) => logId > event . id ) ;
if ( - 1 == firstNonsyncedIdx ) {
recs = [ ]
} else {
recs = recs . slice ( firstNonsyncedIdx ) ;
}
}
gbSend ( { t : "actTrksList" , list : recs } ) ; // TODO: split up in multiple transmissions?
} ,
//{t:"fetchRec", id:"20230616a"}
"fetchRec" : function ( ) {
// TODO: Decide on what names keys should have.
if ( fetchRecInterval ) {
clearInterval ( fetchRecInterval ) ;
fetchRecInterval = undefined ;
}
if ( event . id == "stop" ) {
return
} else {
let log = require ( "Storage" ) . open ( "recorder.log" + event . id + ".csv" , "r" ) ;
let lines = "init" ; // = log.readLine();
let pkgcnt = 0 ;
gbSend ( { t : "actTrk" , log : event . id , lines : "erase" , cnt : pkgcnt } ) ; // "erase" will prompt Gadgetbridge to erase the contents of a already fetched log so we can rewrite it without keeping lines from the previous (probably failed) fetch.
let sendlines = ( ) => {
lines = log . readLine ( ) ;
for ( var i = 0 ; i < 3 ; i ++ ) {
let line = log . readLine ( ) ;
if ( line ) lines += line ;
}
pkgcnt ++ ;
gbSend ( { t : "actTrk" , log : event . id , lines : lines , cnt : pkgcnt } ) ;
if ( ! lines && fetchRecInterval ) {
clearInterval ( fetchRecInterval ) ;
fetchRecInterval = undefined ;
}
}
fetchRecInterval = setInterval ( sendlines , 50 )
}
} ,
2023-05-19 10:09:16 +00:00
"nav" : function ( ) {
event . id = "nav" ;
if ( event . instr ) {
event . t = "add" ;
2023-05-19 13:09:20 +00:00
event . src = "maps" ; // for the icon
event . title = "Navigation" ;
2023-06-22 09:04:46 +00:00
if ( require ( "messages" ) . getMessages ( ) . find ( m => m . id == "nav" ) )
event . t = "modify" ;
2023-05-19 10:09:16 +00:00
} else {
event . t = "remove" ;
}
require ( "messages" ) . pushMessage ( event ) ;
2023-08-19 09:56:29 +00:00
} ,
"cards" : function ( ) {
// we receive all, just override what we have
if ( Array . isArray ( event . d ) )
require ( "Storage" ) . writeJSON ( "android.cards.json" , event . d ) ;
2024-05-18 21:54:21 +00:00
} ,
2024-05-19 14:51:14 +00:00
"accelsender" : function ( ) {
require ( "Storage" ) . writeJSON ( "accelsender.json" , { enabled : event . enable , interval : event . interval } ) ;
2024-05-18 21:54:21 +00:00
load ( ) ;
2022-05-26 13:29:38 +00:00
}
2021-11-04 17:16:02 +00:00
} ;
var h = HANDLERS [ event . t ] ;
if ( h ) h ( ) ; else console . log ( "GB Unknown" , event ) ;
} ;
2022-06-28 14:31:57 +00:00
// HTTP request handling - see the readme
// options = {id,timeout,xpath}
Bangle . http = ( url , options ) => {
options = options || { } ;
2022-09-28 08:15:04 +00:00
if ( ! NRF . getSecurityStatus ( ) . connected )
2022-12-02 21:45:10 +00:00
return Promise . reject ( /*LANG*/ "Not connected to Bluetooth" ) ;
2022-06-28 14:31:57 +00:00
if ( Bangle . httpRequest === undefined )
Bangle . httpRequest = { } ;
if ( options . id === undefined ) {
// try and create a unique ID
do {
options . id = Math . random ( ) . toString ( ) . substr ( 2 ) ;
} while ( Bangle . httpRequest [ options . id ] !== undefined ) ;
}
//send the request
var req = { t : "http" , url : url , id : options . id } ;
if ( options . xpath ) req . xpath = options . xpath ;
2023-06-30 10:28:43 +00:00
if ( options . return ) req . return = options . return ; // for xpath
2022-08-01 09:19:59 +00:00
if ( options . method ) req . method = options . method ;
if ( options . body ) req . body = options . body ;
if ( options . headers ) req . headers = options . headers ;
2022-06-28 14:31:57 +00:00
gbSend ( req ) ;
//create the promise
var promise = new Promise ( function ( resolve , reject ) {
//save the resolve function in the dictionary and create a timeout (30 seconds default)
Bangle . httpRequest [ options . id ] = { r : resolve , j : reject , t : setTimeout ( ( ) => {
//if after "timeoutMillisec" it still hasn't answered -> reject
delete Bangle . httpRequest [ options . id ] ;
reject ( "Timeout" ) ;
} , options . timeout || 30000 ) } ;
} ) ;
return promise ;
2023-01-13 12:32:28 +00:00
} ;
2021-11-04 17:16:02 +00:00
// Battery monitor
2024-05-24 08:02:32 +00:00
let sendBattery = function ( ) { gbSend ( { t : "status" , bat : E . getBattery ( ) , chg : Bangle . isCharging ( ) ? 1 : 0 } ) ; }
2023-01-25 09:29:34 +00:00
Bangle . on ( "charging" , sendBattery ) ;
2022-11-24 09:44:48 +00:00
NRF . on ( "connect" , ( ) => setTimeout ( function ( ) {
sendBattery ( ) ;
2023-08-04 22:13:31 +00:00
gbSend ( { t : "ver" , fw : process . env . VERSION , hw : process . env . HWVERSION } ) ;
2022-11-24 09:44:48 +00:00
GB ( { t : "force_calendar_sync_start" } ) ; // send a list of our calendar entries to start off the sync process
} , 2000 ) ) ;
2023-01-25 09:29:34 +00:00
NRF . on ( "disconnect" , ( ) => {
// disable HRM/activity monitoring ('act' message)
GB ( { t : "act" , stp : 0 , hrm : 0 , int : 0 } ) ; // just call the handler to save duplication
// remove all messages on disconnect (if enabled)
var settings = require ( "Storage" ) . readJSON ( "android.settings.json" , 1 ) || { } ;
if ( ! settings . keep )
require ( "messages" ) . clearAll ( ) ;
} ) ;
2021-11-04 17:16:02 +00:00
setInterval ( sendBattery , 10 * 60 * 1000 ) ;
2023-08-09 08:16:33 +00:00
// Health tracking - if 'realtime' data is sent with 'rt:1', but let's still send our activity log every 10 mins
Bangle . on ( 'health' , h => {
gbSend ( { t : "act" , stp : h . steps , hrm : h . bpm , mov : h . movement } ) ;
2021-11-04 17:16:02 +00:00
} ) ;
// Music control
Bangle . musicControl = cmd => {
// play/pause/next/previous/volumeup/volumedown
2021-11-23 16:28:34 +00:00
gbSend ( { t : "music" , n : cmd } ) ;
2021-11-23 20:20:37 +00:00
} ;
// Message response
Bangle . messageResponse = ( msg , response ) => {
if ( msg . id == "call" ) return gbSend ( { t : "call" , n : response ? "ACCEPT" : "REJECT" } ) ;
2021-12-13 18:42:14 +00:00
if ( isFinite ( msg . id ) ) return gbSend ( { t : "notify" , n : response ? "OPEN" : "DISMISS" , id : msg . id } ) ;
2021-11-23 20:20:37 +00:00
// error/warn here?
} ;
2023-05-22 14:11:21 +00:00
Bangle . messageIgnore = msg => {
if ( isFinite ( msg . id ) ) return gbSend ( { t : "notify" , n : "MUTE" , id : msg . id } ) ;
} ;
2022-11-06 12:41:49 +00:00
// GPS overwrite logic
2023-01-28 11:42:38 +00:00
if ( settings . overwriteGps ) { // if the overwrite option is set..
2023-01-07 10:41:01 +00:00
const origSetGPSPower = Bangle . setGPSPower ;
2023-01-28 08:34:27 +00:00
Bangle . moveGPSPower = ( state ) => {
2023-01-13 12:32:28 +00:00
if ( Bangle . isGPSOn ( ) ) {
let orig = Bangle . _PWR . GPS ;
delete Bangle . _PWR . GPS ;
origSetGPSPower ( state ) ;
Bangle . _PWR . GPS = orig ;
}
2023-01-07 10:41:01 +00:00
} ;
2023-01-13 08:34:11 +00:00
2023-01-28 08:34:27 +00:00
// work around Serial1 for GPS not working when connected to something
2023-01-14 00:01:05 +00:00
let serialTimeout ;
2023-01-13 20:45:20 +00:00
let wrap = function ( f ) {
return ( s ) => {
2023-01-14 00:01:05 +00:00
if ( serialTimeout ) clearTimeout ( serialTimeout ) ;
2023-02-23 19:39:37 +00:00
origSetGPSPower ( 1 , "androidgpsserial" ) ;
2023-01-13 20:45:20 +00:00
f ( s ) ;
2023-01-14 00:01:05 +00:00
serialTimeout = setTimeout ( ( ) => {
serialTimeout = undefined ;
2023-01-28 11:42:38 +00:00
origSetGPSPower ( 0 , "androidgpsserial" ) ;
2023-01-14 08:25:05 +00:00
} , 10000 ) ;
2023-01-13 20:45:20 +00:00
} ;
2023-01-14 00:01:05 +00:00
} ;
Serial1 . println = wrap ( Serial1 . println ) ;
Serial1 . write = wrap ( Serial1 . write ) ;
2023-01-13 08:34:11 +00:00
2023-01-28 08:34:27 +00:00
// replace set GPS power logic to suppress activation of gps (and instead request it from the phone)
2023-02-23 19:39:37 +00:00
Bangle . setGPSPower = ( ( isOn , appID ) => {
2023-01-28 08:34:27 +00:00
let pwr ;
2023-02-23 19:39:37 +00:00
if ( ! this . lastGPSEvent ) {
2023-01-28 08:34:27 +00:00
// use internal GPS power function if no gps event has arrived from GadgetBridge
pwr = origSetGPSPower ( isOn , appID ) ;
} else {
2023-01-28 11:42:38 +00:00
// we are currently expecting the next GPS event from GadgetBridge, keep track of GPS state per app
2023-01-28 08:34:27 +00:00
if ( ! Bangle . _PWR ) Bangle . _PWR = { } ;
if ( ! Bangle . _PWR . GPS ) Bangle . _PWR . GPS = [ ] ;
if ( ! appID ) appID = "?" ;
if ( isOn && ! Bangle . _PWR . GPS . includes ( appID ) ) Bangle . _PWR . GPS . push ( appID ) ;
if ( ! isOn && Bangle . _PWR . GPS . includes ( appID ) ) Bangle . _PWR . GPS . splice ( Bangle . _PWR . GPS . indexOf ( appID ) , 1 ) ;
pwr = Bangle . _PWR . GPS . length > 0 ;
// stop internal GPS, no clients left
if ( ! pwr ) origSetGPSPower ( 0 ) ;
}
// always update Gadgetbridge on current power state
2022-11-28 14:22:35 +00:00
gbSend ( { t : "gps_power" , status : pwr } ) ;
return pwr ;
2023-02-23 19:39:37 +00:00
} ) . bind ( gpsState ) ;
2023-01-28 08:34:27 +00:00
// allow checking for GPS via GadgetBridge
2022-11-28 14:22:35 +00:00
Bangle . isGPSOn = ( ) => {
2023-01-13 09:31:42 +00:00
return ! ! ( Bangle . _PWR && Bangle . _PWR . GPS && Bangle . _PWR . GPS . length > 0 ) ;
2023-01-07 10:41:01 +00:00
} ;
2023-01-06 17:37:38 +00:00
// stop GPS on boot if not activated
setTimeout ( ( ) => {
2023-01-13 09:31:42 +00:00
if ( ! Bangle . isGPSOn ( ) ) gbSend ( { t : "gps_power" , status : false } ) ;
2023-01-06 17:37:38 +00:00
} , 3000 ) ;
2022-11-06 12:41:49 +00:00
}
2022-01-12 10:58:47 +00:00
// remove settings object so it's not taking up RAM
delete settings ;
2024-05-24 08:02:32 +00:00
}