1+ // Tea Timer Application for Bangle.js 2 using sched library
2+
3+ let timerDuration = ( ( ) => {
4+ let file = require ( "Storage" ) . open ( "ateatimer.data" , "r" ) ;
5+ let data = file . read ( 4 ) ; // Assuming 4 bytes for storage
6+ return data ? parseInt ( data , 10 ) : 4 * 60 ; // Default to 4 minutes
7+ } ) ( ) ;
8+ let timeRemaining = timerDuration ;
9+ let timerRunning = false ;
10+
11+ function saveDefaultDuration ( ) {
12+ let file = require ( "Storage" ) . open ( "ateatimer.data" , "w" ) ;
13+ file . write ( timerDuration . toString ( ) ) ;
14+ }
15+
16+ function drawTime ( ) {
17+ g . clear ( ) ;
18+ g . setFont ( "Vector" , 40 ) ;
19+ g . setFontAlign ( 0 , 0 ) ; // Center align
20+
21+ const minutes = Math . floor ( Math . abs ( timeRemaining ) / 60 ) ;
22+ const seconds = Math . abs ( timeRemaining ) % 60 ;
23+ const sign = timeRemaining < 0 ? "-" : "" ;
24+ const timeStr = `${ sign } ${ minutes } :${ seconds . toString ( ) . padStart ( 2 , '0' ) } ` ;
25+
26+ g . drawString ( timeStr , g . getWidth ( ) / 2 , g . getHeight ( ) / 2 ) ;
27+
28+ // Draw Increase button (triangle pointing up)
29+ g . fillPoly ( [
30+ g . getWidth ( ) / 2 , g . getHeight ( ) / 2 - 80 , // Top vertex
31+ g . getWidth ( ) / 2 - 20 , g . getHeight ( ) / 2 - 60 , // Bottom-left vertex
32+ g . getWidth ( ) / 2 + 20 , g . getHeight ( ) / 2 - 60 // Bottom-right vertex
33+ ] ) ;
34+
35+ // Draw Decrease button (triangle pointing down)
36+ g . fillPoly ( [
37+ g . getWidth ( ) / 2 , g . getHeight ( ) / 2 + 80 , // Bottom vertex
38+ g . getWidth ( ) / 2 - 20 , g . getHeight ( ) / 2 + 60 , // Top-left vertex
39+ g . getWidth ( ) / 2 + 20 , g . getHeight ( ) / 2 + 60 // Top-right vertex
40+ ] ) ;
41+
42+ g . flip ( ) ;
43+ }
44+
45+ function startTimer ( ) {
46+ if ( timerRunning ) return ;
47+ if ( timeRemaining == 0 ) return ;
48+ timerRunning = true ;
49+
50+ // Save the default duration on timer start
51+ timerDuration = timeRemaining ;
52+ saveDefaultDuration ( ) ;
53+ scheduleTimer ( ) ;
54+
55+ // Start the secondary timer to update the display
56+ setInterval ( updateDisplay , 1000 ) ;
57+ }
58+
59+ function scheduleTimer ( ) {
60+ // Schedule a new timer using the sched library
61+ require ( "sched" ) . setAlarm ( "ateatimer" , {
62+ msg : "Tea is ready!" ,
63+ timer : timeRemaining * 1000 , // Convert to milliseconds
64+ vibrate : ".." // Default vibration pattern
65+ } ) ;
66+
67+ // Ensure the scheduler updates
68+ require ( "sched" ) . reload ( ) ;
69+ }
70+
71+ function resetTimer ( ) {
72+ // Cancel the existing timer
73+ require ( "sched" ) . setAlarm ( "ateatimer" , undefined ) ;
74+ require ( "sched" ) . reload ( ) ;
75+
76+ timerRunning = false ;
77+ timeRemaining = timerDuration ;
78+ drawTime ( ) ;
79+ }
80+
81+ function adjustTime ( amount ) {
82+ if ( - amount > timeRemaining ) {
83+ // Return if result will be negative
84+ return ;
85+ }
86+ timeRemaining += amount ;
87+ timeRemaining = Math . max ( 0 , timeRemaining ) ; // Ensure time doesn't go negative
88+ if ( timerRunning ) {
89+ // Update the existing timer with the new remaining time
90+ let alarm = require ( "sched" ) . getAlarm ( "ateatimer" ) ;
91+ if ( alarm ) {
92+ // Cancel the current alarm
93+ require ( "sched" ) . setAlarm ( "ateatimer" , undefined ) ;
94+
95+ // Set a new alarm with the updated time
96+ scheduleTimer ( ) ;
97+ }
98+ }
99+
100+ drawTime ( ) ;
101+ }
102+
103+ function handleTouch ( x , y ) {
104+ const centerY = g . getHeight ( ) / 2 ;
105+
106+ if ( y < centerY - 40 ) {
107+ // Increase button area
108+ adjustTime ( 60 ) ;
109+ } else if ( y > centerY + 40 ) {
110+ // Decrease button area
111+ adjustTime ( - 60 ) ;
112+ } else {
113+ // Center area
114+ if ( ! timerRunning ) {
115+ startTimer ( ) ;
116+ }
117+ }
118+ }
119+
120+ // Function to update the display every second
121+ function updateDisplay ( ) {
122+ if ( timerRunning ) {
123+ let alarm = require ( "sched" ) . getAlarm ( "ateatimer" ) ;
124+ timeRemaining = Math . floor ( require ( "sched" ) . getTimeToAlarm ( alarm ) / 1000 ) ;
125+ drawTime ( ) ;
126+ if ( timeRemaining <= 0 ) {
127+ timeRemaining = 0 ;
128+ clearInterval ( updateDisplay ) ;
129+ timerRunning = false ;
130+ }
131+ }
132+ }
133+
134+ // Handle physical button press for resetting timer
135+ setWatch ( ( ) => {
136+ if ( timerRunning ) {
137+ resetTimer ( ) ;
138+ } else {
139+ startTimer ( ) ;
140+ }
141+ } , BTN1 , { repeat : true , edge : "falling" } ) ;
142+
143+ // Handle touch
144+ Bangle . on ( "touch" , ( zone , xy ) => {
145+ handleTouch ( xy . x , xy . y , false ) ;
146+ } ) ;
147+
148+ let isRunning = require ( "sched" ) . getAlarm ( "ateatimer" ) ;
149+ if ( isRunning ) {
150+ timerRunning = true ;
151+ // Start the timer to update the display
152+ setInterval ( updateDisplay , 1000 ) ;
153+ } else {
154+ // Draw the initial timer display
155+ drawTime ( ) ;
156+ }
0 commit comments