2024-12-23 13:44:58 +00:00
//Init
var Layout = require ( "Layout" ) ;
require ( "Font7x11Numeric7Seg" ) . add ( Graphics ) ;
require ( "FontTeletext5x9Ascii" ) . add ( Graphics ) ;
2024-12-25 22:02:01 +00:00
const Light _on = '#fff' ;
const Light _off = '#554' ;
const Light _warn = '#f90' ;
const Light _COMPACTY = '#0F0' ;
const Light _width = 43 ;
const Light _height = 25 ;
const EL7 _height = 30 ;
const LightFont = 'Teletext5x9Ascii' ;
const DataFont = '7x11Numeric7Seg:2' ;
var mode = 0 ;
2024-12-23 13:44:58 +00:00
2024-12-28 19:16:15 +00:00
if ( global . WIDGETS ) { require ( "widget_utils" ) . swipeOn ( ) ; } // If `dsky_clock` was fast loaded into we seemingly need to hide the widgets before setting the layout so elements are not moved down.
2024-12-23 13:44:58 +00:00
var layout = new Layout (
{ type : "h" , c : [
{ type : "" , width : 6 } ,
{ type : "v" , c : [
{ type : "txt" , font : LightFont , col : "#000" , bgCol : "#555" , id : 'L1' , label : "UPLINK\nACTY" , width : Light _width , height : Light _height } ,
{ type : "txt" , font : LightFont , col : "#000" , bgCol : "#555" , id : 'L2' , label : "TEMP" , width : Light _width , height : Light _height } ,
{ type : "txt" , font : LightFont , col : "#000" , bgCol : "#555" , id : 'L3' , label : "GIMBAL\nLOCK" , width : Light _width , height : Light _height } ,
{ type : "txt" , font : LightFont , col : "#000" , bgCol : "#555" , id : 'L4' , label : "STBY" , width : Light _width , height : Light _height } ,
{ type : "txt" , font : LightFont , col : "#000" , bgCol : "#555" , id : 'L5' , label : "PROG" , width : Light _width , height : Light _height } ,
{ type : "txt" , font : LightFont , col : "#000" , bgCol : "#eee" , id : 'L6' , label : "OPR ERR" , width : Light _width , height : Light _height } ,
] } ,
2024-12-31 19:40:18 +00:00
{ type : "" , width : 25 } ,
2024-12-23 13:44:58 +00:00
{ type : "v" , c : [
{ type : "" , height : 2 } ,
{ type : "h" , c : [
{ type : "" , width : 50 } , { type : "txt" , font : "6x8" , col : "#000" , bgCol : "#0F0" , label : "PROG" , width : 25 , height : 10 } ,
] } ,
{ type : "h" , c : [
{ type : "" , width : 10 } ,
{ type : "txt" , font : "6x8" , col : "#000" , bgCol : "#000" , id : "COMPACTY" , label : "COMP\nACTY" , width : 26 , height : 26 } ,
{ type : "" , width : 17 } ,
{ type : "txt" , font : DataFont , col : "#0F0" , bgCol : "#000" , label : "00" , id : "PROG" , fillx : 1 , height : EL7 _height } ,
] } ,
{ type : "" , height : 1 } ,
{ type : "h" , c : [
{ type : "txt" , font : "6x8" , col : "#000" , bgCol : "#0F0" , label : "VERB" , width : 25 , height : 10 } ,
{ type : "" , width : 30 } ,
{ type : "txt" , font : "6x8" , col : "#000" , bgCol : "#0F0" , label : "NOUN" , width : 25 , height : 10 } ,
] } ,
{ type : "h" , c : [
{ type : "txt" , font : DataFont , col : "#0F0" , bgCol : "#000" , label : "00" , id : "VERB" , fillx : 1 , height : EL7 _height } ,
{ type : "txt" , font : DataFont , col : "#0F0" , bgCol : "#000" , label : "00" , id : "NOUN" , fillx : 1 , height : EL7 _height } ,
] } ,
{ type : "" , bgCol : '#070' , width : 80 , height : 2 } ,
2024-12-24 17:38:01 +00:00
{ type : "txt" , font : DataFont , col : "#0F0" , bgCol : "#000" , label : "00000" , id : "R1" , halign : 1 , fillx : 1 , height : EL7 _height } ,
{ type : "txt" , font : DataFont , col : "#0F0" , bgCol : "#000" , label : "00000" , id : "R2" , halign : 1 , fillx : 1 , height : EL7 _height } ,
{ type : "txt" , font : DataFont , col : "#0F0" , bgCol : "#000" , label : "00000" , id : "R3" , halign : 1 , fillx : 1 , height : EL7 _height } ,
2024-12-23 13:44:58 +00:00
] } ,
{ type : "" , width : 5 } ,
2024-12-24 04:53:28 +00:00
] ,
2024-12-28 19:16:15 +00:00
lazy : true } ,
{ btns : [
{ label : "" , cb : Bangle . showLauncher }
] , lazy : true } ) ;
2024-12-23 13:44:58 +00:00
layout . update ( ) ;
2024-12-27 23:04:36 +00:00
//support functioe_ns
2024-12-23 13:44:58 +00:00
2024-12-24 04:53:28 +00:00
function getWeather ( ) {
2024-12-27 22:24:24 +00:00
var weather = { } ;
try {
weather = require ( "Storage" ) . readJSON ( 'weather.json' , 1 ) . weather ;
} catch ( e ) {
return { } ;
}
2024-12-24 04:53:28 +00:00
return weather ;
}
2024-12-23 13:44:58 +00:00
function getdatetime ( ) {
var datetime = [ ] ;
var d = new Date ( ) ;
2024-12-26 00:06:49 +00:00
// var offsets = require("Storage").readJSON("worldclock.settings.json") || [];
2024-12-23 13:44:58 +00:00
// var meridian = require("locale").meridian(d);
datetime . clock = require ( "locale" ) . time ( d , 1 ) ;
datetime . month = d . getMonth ( ) + 1 ;
datetime . day = d . getDate ( ) ;
2024-12-24 04:53:28 +00:00
datetime . localtime = String ( d . getHours ( ) ) . padStart ( 2 , '0' ) + String ( d . getMinutes ( ) ) . padStart ( 2 , '0' ) ;
2024-12-25 22:08:51 +00:00
let utchour = ( ( d . getHours ( ) + ( Math . round ( d . getTimezoneOffset ( ) / 60 ) ) ) % 24 ) ;
2024-12-24 04:53:28 +00:00
datetime . utctime = String ( utchour ) . padStart ( 2 , '0' ) + String ( d . getMinutes ( ) ) . padStart ( 2 , '0' ) ;
2024-12-23 13:44:58 +00:00
return datetime ;
}
function getSteps ( ) {
2024-12-25 22:02:01 +00:00
let steps = Bangle . getHealthStatus ( "day" ) . steps ;
2024-12-23 13:44:58 +00:00
steps = typeof steps !== 'undefined' ? steps : 0 ;
return steps ;
}
function getStepGoal ( ) {
let stepGoal = ( require ( "Storage" ) . readJSON ( "health.json" , 1 ) || 10000 ) . stepGoal ;
stepGoal = typeof stepGoal !== 'undefined' ? stepGoal : 10000 ;
return stepGoal ;
}
function isAlarmSet ( ) {
let alarmStatus = ( require ( 'Storage' ) . readJSON ( 'sched.json' , 1 ) || [ ] ) . some ( alarm => alarm . on ) ;
return alarmStatus ;
}
function isMessagesNotify ( ) {
if ( require ( "Storage" ) . read ( "messages.json" ) !== undefined ) {
return true ;
} else {
return false ;
}
}
2024-12-24 04:53:28 +00:00
function getHRM ( ) {
2024-12-25 22:02:01 +00:00
let hrm = Bangle . getHealthStatus ( 'last' ) ;
2024-12-24 04:53:28 +00:00
hrm = typeof hrm !== 'undefined' ? hrm : 0 ;
return hrm ;
}
2024-12-23 13:44:58 +00:00
function isBTConnected ( ) {
return NRF . getSecurityStatus ( ) . connected ;
}
function getBattery ( ) {
2024-12-25 22:02:01 +00:00
let battlevel = E . getBattery ( ) ;
2024-12-23 13:44:58 +00:00
if ( Bangle . isCharging ( ) ) {
battlevel = - 1 ;
} else if ( battlevel >= 100 ) {
battlevel = 99 ;
}
2024-12-24 04:53:28 +00:00
battlevel = String ( battlevel ) ;
2024-12-23 13:44:58 +00:00
return battlevel ;
}
function isActive ( ) {
2024-12-26 00:08:02 +00:00
if ( Bangle . isCompassOn ( ) || Bangle . isGPSOn ( ) || Bangle . isHRMOn ( ) || Bangle . isBarometerOn ( ) ) {
2024-12-23 13:44:58 +00:00
return true ;
} else {
return false ;
}
}
function setLight ( id , label , check , onColour , offColour ) {
2024-12-24 04:53:28 +00:00
// print('setlight:',id); //debug
layout . clear ( layout [ id ] ) ;
2024-12-23 13:44:58 +00:00
onColour = typeof onColour !== 'undefined' ? onColour : Light _on ;
offColour = typeof offColour !== 'undefined' ? offColour : Light _off ;
if ( label !== '' ) {
layout [ id ] . label = label ;
}
if ( check ) {
layout [ id ] . bgCol = onColour ;
} else {
layout [ id ] . bgCol = offColour ;
}
2024-12-24 04:53:28 +00:00
layout . render ( layout [ id ] ) ;
}
2024-12-24 17:38:01 +00:00
function setDATA ( id , label ) {
2024-12-24 04:53:28 +00:00
layout . clear ( layout [ id ] ) ;
2024-12-25 22:02:01 +00:00
let data = '-----' ;
2024-12-25 22:08:51 +00:00
let sign = '' ;
2024-12-24 04:53:28 +00:00
try {
2024-12-25 22:02:01 +00:00
if ( ! isNaN ( label ) ) {
2024-12-24 17:38:01 +00:00
if ( label < 0 ) {
label = Math . abs ( label ) ;
sign = '-' ;
}
2024-12-24 04:53:28 +00:00
data = String ( String ( label ) . toString ( 16 ) ) . toUpperCase ( ) . padStart ( 5 , '0' ) . substring ( 0 , 5 ) ;
2024-12-24 17:38:01 +00:00
data = sign + data ;
2024-12-24 04:53:28 +00:00
}
} catch ( e ) {
data = '-----' ;
}
layout [ id ] . label = data ;
layout . render ( layout [ id ] ) ;
}
function setWORD ( id , label ) {
layout . clear ( layout [ id ] ) ;
2024-12-26 00:06:49 +00:00
let data = '--' ;
if ( ! isNaN ( label ) ) {
2024-12-26 00:07:24 +00:00
data = String ( String ( label ) . toString ( 16 ) ) . toUpperCase ( ) . padStart ( 2 , '0' ) . substring ( 0 , 2 ) ;
2024-12-24 04:53:28 +00:00
}
2024-12-26 00:06:49 +00:00
// print(id, data); //debug
2024-12-24 04:53:28 +00:00
layout [ id ] . label = data ;
layout . render ( layout [ id ] ) ;
2024-12-23 13:44:58 +00:00
}
function draw _bg ( ) {
g . setColor ( '#666' ) ;
g . fillRect ( 0 , 0 , 176 , 176 ) ;
g . setColor ( '#000' ) ;
g . fillRect ( 69 , 2 , 172 , 174 ) ;
g . fillCircle ( 59 , 10 , 5 ) ;
g . fillCircle ( 59 , 166 , 5 ) ;
}
// actual display
2024-12-24 04:53:28 +00:00
function drawMain ( ) {
2024-12-25 22:02:01 +00:00
let datetime = getdatetime ( ) ;
2024-12-24 04:53:28 +00:00
setDATA ( 'R1' , datetime . localtime ) ;
setDATA ( 'R2' , datetime . utctime ) ;
setDATA ( 'R3' , getSteps ( ) ) ;
setWORD ( 'PROG' , getBattery ( ) ) ;
setWORD ( 'VERB' , datetime . month ) ;
setWORD ( 'NOUN' , datetime . day ) ;
2024-12-23 13:44:58 +00:00
setLight ( 'COMPACTY' , '' , isActive ( ) , Light _COMPACTY ) ;
setLight ( 'L1' , 'MSG' , isMessagesNotify ( ) ) ;
setLight ( 'L2' , 'LOCK' , Bangle . isLocked ( ) ) ;
setLight ( 'L3' , 'BT' , ! isBTConnected ( ) , Light _warn ) ;
setLight ( 'L4' , 'BATT' , ( getBattery ( ) <= 20 ) , Light _warn ) ;
setLight ( 'L5' , 'ALARM' , isAlarmSet ( ) , Light _warn ) ;
2024-12-24 04:53:28 +00:00
setLight ( 'L6' , 'STEP' , ( getSteps ( ) >= getStepGoal ( ) ) , '#0a0' ) ;
2024-12-27 23:04:36 +00:00
// layout.setUI();
2024-12-24 17:54:53 +00:00
layout . forgetLazyState ( ) ;
2024-12-23 13:44:58 +00:00
layout . render ( ) ;
2024-12-24 17:38:01 +00:00
queueDraw ( ) ;
2024-12-23 13:44:58 +00:00
}
2024-12-24 04:53:28 +00:00
////// ALT modes /////
2024-12-24 17:38:01 +00:00
var AltDrawTimer ;
2024-12-24 04:53:28 +00:00
function drawAlt ( mode ) {
2024-12-24 17:38:01 +00:00
if ( AltDrawTimer ) clearTimeout ( AltDrawTimer ) ;
2024-12-24 04:53:28 +00:00
mode = typeof mode !== 'undefined' ? mode : 0 ;
2024-12-24 17:38:01 +00:00
mode = Math . abs ( mode ) ;
2024-12-24 04:53:28 +00:00
// print('drawAlt: ', mode); // debug
// Show mode in PROG
setWORD ( 'PROG' , mode ) ;
setWORD ( 'NOUN' , '' ) ;
setWORD ( 'VERB' , '' ) ;
// Disable Battery warning light in to show PROG no longer shows battery level
setLight ( 'L4' , 'BATT' , false ) ;
2024-12-24 17:38:01 +00:00
setDATA ( 'R1' ) ;
setDATA ( 'R2' ) ;
setDATA ( 'R3' ) ;
2024-12-24 04:53:28 +00:00
switch ( mode ) {
case 1 :
setLight ( 'L6' , 'HRM' , true ) ;
mode _HRM ( ) ;
break ;
case 2 :
setLight ( 'L6' , 'TEMP' , true ) ;
mode _weather ( ) ;
break ;
2024-12-24 23:13:36 +00:00
case 3 :
setLight ( 'L6' , 'GPS' , true ) ;
mode _GPS ( ) ;
break ;
2024-12-24 04:53:28 +00:00
case 4 :
setLight ( 'L6' , 'ACCEL' , true ) ;
mode _accel ( ) ;
break ;
case 5 :
setLight ( 'L6' , 'HDG' , true ) ;
mode _compass ( ) ;
break ;
default :
drawMain ( ) ;
}
layout . render ( ) ;
}
2024-12-24 17:38:01 +00:00
function mode _HRM ( ) {
setLight ( 'COMPACTY' , '' , true , Light _COMPACTY ) ;
AltDrawTimer = setTimeout ( function ( ) {
Bangle . setHRMPower ( true , 'dsky_clock' ) ;
2024-12-25 22:08:51 +00:00
let hrm = getHRM ( ) ;
2024-12-24 17:38:01 +00:00
setDATA ( 'R1' , hrm . bpm ) ;
setDATA ( 'R2' , hrm . bpmConfidence ) ;
setDATA ( 'R3' , getSteps ( ) ) ;
mode _HRM ( ) ;
} , 5000 ) ;
Bangle . setHRMPower ( false ) ;
}
2024-12-24 04:53:28 +00:00
function mode _weather ( ) {
2024-12-25 22:02:01 +00:00
let weather = getWeather ( ) ;
2024-12-27 23:04:36 +00:00
try {
weather . temp = Math . round ( weather . temp - 273.15 ) ;
setDATA ( 'R1' , weather . temp ) ;
setDATA ( 'R2' , weather . hum ) ;
setDATA ( 'R3' , weather . code ) ;
setWORD ( 'NOUN' , weather . hum ) ;
setWORD ( 'VERB' , weather . rain ) ;
} catch ( e ) {
setDATA ( 'R1' , '-----' ) ;
setDATA ( 'R2' , '-----' ) ;
setDATA ( 'R3' , '-----' ) ;
setDATA ( 'R1' , '--' ) ;
setDATA ( 'R1' , '--' ) ;
}
2024-12-24 04:53:28 +00:00
}
function mode _compass ( ) {
2024-12-24 17:38:01 +00:00
AltDrawTimer = setTimeout ( function ( ) {
setLight ( 'COMPACTY' , '' , true , Light _COMPACTY ) ; //isCompassOn seems to be incorrect?
Bangle . setCompassPower ( 1 ) ;
2024-12-25 22:08:51 +00:00
let compass = Bangle . getCompass ( ) ;
2024-12-24 17:38:01 +00:00
setDATA ( 'R1' , compass . heading ) ;
setDATA ( 'R2' ) ;
setDATA ( 'R3' ) ;
mode _compass ( ) ;
} , 200 ) ;
Bangle . setCompassPower ( 0 ) ;
2024-12-24 04:53:28 +00:00
}
2024-12-24 17:38:01 +00:00
function mode _GPS ( ) {
setLight ( 'COMPACTY' , '' , true , Light _COMPACTY ) ;
AltDrawTimer = setTimeout ( function ( ) {
Bangle . setGPSPower ( 1 , 'dsky_clock' ) ;
2024-12-25 22:08:51 +00:00
let gps = Bangle . getGPSFix ( ) ;
2024-12-24 17:38:01 +00:00
setWORD ( 'NOUN' , gps . fix ) ;
setWORD ( 'VERB' , gps . satellites ) ;
setDATA ( 'R1' , gps . lat ) ;
setDATA ( 'R2' , gps . lon ) ;
setDATA ( 'R3' , gps . speed ) ;
mode _GPS ( ) ;
} , 5000 ) ;
Bangle . setGPSPower ( 0 ) ;
2024-12-24 04:53:28 +00:00
}
2024-12-24 17:38:01 +00:00
function mode _accel ( ) {
AltDrawTimer = setTimeout ( function ( ) {
setLight ( 'COMPACTY' , '' , isActive ( ) , Light _COMPACTY ) ;
2024-12-25 22:08:51 +00:00
let accel = Bangle . getAccel ( ) ;
2024-12-24 17:38:01 +00:00
setDATA ( 'R1' , accel . x ) ;
setDATA ( 'R2' , accel . y ) ;
setDATA ( 'R3' , accel . z ) ;
mode _accel ( ) ;
} , 100 ) ;
2024-12-24 04:53:28 +00:00
}
2024-12-24 17:38:01 +00:00
//////////// Main
2024-12-24 04:53:28 +00:00
2024-12-24 17:38:01 +00:00
var drawTimeout ;
// schedule a draw for the next minute
function queueDraw ( ) {
if ( drawTimeout ) clearTimeout ( drawTimeout ) ;
drawTimeout = setTimeout ( function ( ) {
drawTimeout = undefined ;
mode = 0 ;
if ( AltDrawTimer ) clearTimeout ( AltDrawTimer ) ;
drawMain ( ) ;
} , 60000 - ( Date . now ( ) % 60000 ) ) ;
2024-12-24 04:53:28 +00:00
}
2024-12-23 13:44:58 +00:00
Bangle . on ( 'lock' , on => {
2024-12-24 04:53:28 +00:00
mode = 0 ;
drawMain ( ) ; // draw immediately
2024-12-23 13:44:58 +00:00
} ) ;
2024-12-24 04:53:28 +00:00
Bangle . on ( "message" , function ( ) { setLight ( 'COMPACTY' , '' , isActive ( ) , Light _COMPACTY ) ; } ) ;
Bangle . on ( 'charging' , drawMain ) ;
2024-12-24 17:38:01 +00:00
NRF . on ( 'connect' , function ( ) { setLight ( 'L3' , 'BT' , ! isBTConnected ( ) , Light _warn ) ; } ) ;
NRF . on ( 'disconnect' , function ( ) { setLight ( 'L3' , 'BT' , ! isBTConnected ( ) , Light _warn ) ; } ) ;
Bangle . on ( 'swipe' , function ( directionLR ) {
if ( directionLR == 1 ) {
2024-12-24 18:03:04 +00:00
mode = mode - 1 ;
2024-12-24 17:38:01 +00:00
}
if ( directionLR == - 1 ) {
2024-12-24 18:03:04 +00:00
mode = mode + 1 ;
2024-12-24 04:53:28 +00:00
}
2024-12-24 17:38:01 +00:00
if ( mode < 0 ) { mode = 5 ; }
mode = ( mode % 6 ) ;
2024-12-24 04:53:28 +00:00
drawAlt ( mode ) ;
} ) ;
2024-12-23 13:44:58 +00:00
g . clear ( ) ;
draw _bg ( ) ;
2024-12-24 04:53:28 +00:00
drawMain ( ) ;
2024-12-28 19:16:15 +00:00
Bangle . CLOCK = 1 ;
Bangle . loadWidgets ( ) ; // loading widgets after drawing the layout in `drawMain()` to display the app UI ASAP.
require ( "widget_utils" ) . swipeOn ( ) ; // hide widgets, make them visible with a swipe