using Toybox.Graphics as Gfx; using Toybox.System as Sys; using Toybox.Lang as Lang; using Toybox.Math as Math; using Toybox.Time as Time; using Toybox.Time.Gregorian as Calendar; using Toybox.WatchUi as Ui; using Toybox.Application as App; using Toybox.ActivityMonitor as ActMon; using Toybox.SensorHistory as Sensor; using Toybox.Activity as Activity; using Toybox.UserProfile as User; enum { LAT, LON } class SnapshotWatchView extends Ui.WatchFace { var usePreferences = true; var showHeartRate = true; var showSteps = true; var showRiseSet = false; var showSecondTime = false; var secondTimeOffset = 0; var graphLength = 240; var arrayColours = new [11]; var graphColour = 0; var useZonesColour = true; var heartRateZones; var showMoveBar = false; var background_color = Gfx.COLOR_BLACK; // var background_color = Gfx.COLOR_BLUE; var mainTextColor = Gfx.COLOR_WHITE; var showSeconds = false; var width_screen, height_screen; var hashMarksArray = new [60]; var heartNow; var heartMin = 1000; var heartMax = 0; // var proFeatures = true; public function initialize() { Ui.WatchFace.initialize(); } //! Load your resources here function onLayout(dc) { //get screen dimensions width_screen = dc.getWidth(); height_screen = dc.getHeight(); //colours and zones arrayColours = [Gfx.COLOR_DK_GRAY, Gfx.COLOR_RED, Gfx.COLOR_DK_RED, Gfx.COLOR_ORANGE, Gfx.COLOR_YELLOW, Gfx.COLOR_GREEN, Gfx.COLOR_DK_GREEN, Gfx.COLOR_BLUE, Gfx.COLOR_DK_BLUE, Gfx.COLOR_PURPLE, Gfx.COLOR_PINK]; heartRateZones = User.getHeartRateZones(User.getCurrentSport()); // heartRateZones = [98, 127, 146, 166, 185, 195]; //get hash marks position for(var i = 0; i < 60; i+=1) { hashMarksArray[i] = new [2]; hashMarksArray[i][0] = (i / 60.0) * Math.PI * 2; if(i != 0 && i != 15 && i != 30 && i != 45) { hashMarksArray[i][1] = -95; } else { hashMarksArray[i][1] = -85; } } setLayout(Rez.Layouts.WatchFace(dc)); } //! Restore the state of the app and prepare the view to be shown function onShow() { } //! Update the view function onUpdate(dc) { //var bgImage = Ui.loadResource(Rez.Drawables.BackgroundImage); var code = "0"; if (usePreferences) { code = Application.getApp().getProperty("code"); showHeartRate = Application.getApp().getProperty("showHeartRate"); graphLength = Application.getApp().getProperty("graphLength"); graphColour = Application.getApp().getProperty("graphColour"); useZonesColour = Application.getApp().getProperty("useZonesColour"); showMoveBar = Application.getApp().getProperty("showMoveBar"); showSteps = Application.getApp().getProperty("showSteps"); showRiseSet = Application.getApp().getProperty("showRiseSet"); showSecondTime = Application.getApp().getProperty("showSecondTime"); secondTimeOffset = Application.getApp().getProperty("secondTimeOffset"); } // authenticate(code); // if (!proFeatures) // { // showSteps = true; // showRiseSet = false; // showSecondTime = false; // } // if (showSecondTime) // { // if (secondTimeOffset <= 24 && secondTimeOffset >= -24) // { // secondTimeOffset = secondTimeOffset.toNumber(); // } // else // { // showSecondTime = false; // secondTimeOffset = 0; // } // } // Clear screen dc.setColor(background_color, Gfx.COLOR_WHITE); dc.fillRectangle(0,0, width_screen, height_screen); //dc.drawBitmap(0, 0, Ui.loadResource(Rez.Drawables.BackgroundImage)); //var myActivity = Activity.getActivityInfo(); heartNow = Activity.getActivityInfo().currentHeartRate; // Plot heart rate graph //plotHRgraph(dc); // Draw hash marks drawHashMarks(dc); // Set text colour for the remaining information dc.setColor(mainTextColor, Gfx.COLOR_TRANSPARENT); // Show cur/min/max HR values (recorded when plotting graph, above) if (showHeartRate) { if (heartNow == null) { dc.drawText(width_screen/2, height_screen/2 + 70, Gfx.FONT_SMALL, "-- bpm", Graphics.TEXT_JUSTIFY_CENTER|Graphics.TEXT_JUSTIFY_VCENTER); } else { dc.drawText(width_screen/2, height_screen/2 + 70, Gfx.FONT_SMALL, Lang.format("$1$ bpm", [heartNow]), Graphics.TEXT_JUSTIFY_CENTER|Graphics.TEXT_JUSTIFY_VCENTER); } } // Show date dc.setColor(Gfx.COLOR_DK_BLUE, Gfx.COLOR_TRANSPARENT); dc.drawCircle(width_screen/2-50, height_screen/2, 32); dc.setColor(mainTextColor, Gfx.COLOR_TRANSPARENT); drawDate(dc); // Show Status Icons var offset = 8; var heightOffset = 75; var spreadOffset = offset*2; dc.setColor(Gfx.COLOR_DK_BLUE, Gfx.COLOR_TRANSPARENT); dc.drawEllipse(width_screen/2, height_screen/2-heightOffset+6, 37, 12); dc.setColor(mainTextColor, Gfx.COLOR_TRANSPARENT); // Show bluetooth icon if (Sys.getDeviceSettings().phoneConnected) { dc.drawBitmap(width_screen/2-offset-4, height_screen/2-heightOffset, Ui.loadResource(Rez.Drawables.BluetoothCon)); } else { dc.drawBitmap(width_screen/2-offset-4, height_screen/2-heightOffset, Ui.loadResource(Rez.Drawables.BluetoothDC)); } // Show alarm icon if (Sys.getDeviceSettings().alarmCount > 0) { dc.drawBitmap(width_screen/2-offset-spreadOffset-4, height_screen/2-heightOffset, Ui.loadResource(Rez.Drawables.AlarmIconSet)); } else { dc.drawBitmap(width_screen/2-offset-spreadOffset-4, height_screen/2-heightOffset, Ui.loadResource(Rez.Drawables.AlarmIconClr)); } // Show do not disturb icon if (Sys.getDeviceSettings().doNotDisturb) { dc.drawBitmap(width_screen/2+offset+spreadOffset-4, height_screen/2-heightOffset, Ui.loadResource(Rez.Drawables.MuteIcon)); } else { dc.drawBitmap(width_screen/2+offset+spreadOffset-4, height_screen/2-heightOffset, Ui.loadResource(Rez.Drawables.VolumeIcon)); } // Show notification count icon var numNotifications = Sys.getDeviceSettings().notificationCount; if (numNotifications >= 10) { spreadOffset += 2; } dc.drawBitmap(width_screen/2+offset-4, height_screen/2-heightOffset, Ui.loadResource(Rez.Drawables.NotificationIcon)); if (numNotifications > 0) { dc.setColor(Gfx.COLOR_RED, Gfx.COLOR_TRANSPARENT); dc.drawText(width_screen/2+offset+10-4, height_screen/2-heightOffset+5, Gfx.FONT_XTINY, numNotifications, Graphics.TEXT_JUSTIFY_RIGHT|Graphics.TEXT_JUSTIFY_VCENTER); dc.setColor(mainTextColor, Gfx.COLOR_TRANSPARENT); } // Show Battery var battery = Sys.getSystemStats().battery; offset = 40; heightOffset = 7; dc.setColor(Gfx.COLOR_DK_BLUE, Gfx.COLOR_TRANSPARENT); dc.drawCircle(width_screen/2+offset+13, height_screen/2, 26); dc.setColor(mainTextColor, Gfx.COLOR_TRANSPARENT); // if (battery == 100) { offset -= 2; } if (battery >= 90) { // offset += 4; dc.drawBitmap(width_screen/2+offset+1, height_screen/2+3-heightOffset, Ui.loadResource(Rez.Drawables.BatteryFullIcon)); } else if (battery >= 80) { dc.drawBitmap(width_screen/2+offset+1, height_screen/2+3-heightOffset, Ui.loadResource(Rez.Drawables.Battery80Icon)); } else if (battery >= 60) { dc.drawBitmap(width_screen/2+offset+1, height_screen/2+3-heightOffset, Ui.loadResource(Rez.Drawables.Battery60Icon)); } else if (battery >= 40) { dc.drawBitmap(width_screen/2+offset+1, height_screen/2+3-heightOffset, Ui.loadResource(Rez.Drawables.Battery40Icon)); } else if (battery >= 20) { dc.drawBitmap(width_screen/2+offset+1, height_screen/2+3-heightOffset, Ui.loadResource(Rez.Drawables.Battery20Icon)); } else { dc.drawBitmap(width_screen/2+offset+1, height_screen/2+3-heightOffset, Ui.loadResource(Rez.Drawables.Battery0Icon)); } dc.drawText(width_screen/2+offset+15, height_screen/2-3-heightOffset, Gfx.FONT_XTINY, Lang.format("$1$%", [battery.format("%2d")]), Graphics.TEXT_JUSTIFY_CENTER|Graphics.TEXT_JUSTIFY_VCENTER); // Show steps dc.drawBitmap(width_screen/2-37, height_screen/2 - 58, Ui.loadResource(Rez.Drawables.ShoeIcon)); dc.drawText(width_screen/2, height_screen/2 - 45, Gfx.FONT_SMALL, ActMon.getInfo().steps, Graphics.TEXT_JUSTIFY_LEFT|Graphics.TEXT_JUSTIFY_VCENTER); //dc.drawText(width_screen/2, height_screen/2 + 30, Gfx.FONT_SMALL, ActMon.getInfo().stepGoal, Graphics.TEXT_JUSTIFY_RIGHT|Graphics.TEXT_JUSTIFY_VCENTER); if (showRiseSet) { // Show sunrise and sunset drawSunriseSunset(dc); } // Show second (digital) time drawDigitalTime(dc, Sys.getClockTime()); // Draw analogue clock hands drawHands(dc, Sys.getClockTime().hour, Sys.getClockTime().min, Sys.getClockTime().sec); } //! The user has just looked at their watch. Timers and animations may be started here. function onExitSleep() { showSeconds = true; } //! Terminate any active timers and prepare for slow updates. function onEnterSleep() { showSeconds = false; requestUpdate(); } //! Draw the watch hand function drawHand(dc, angle, whichHand, width, handColour) { dc.setColor(handColour, Gfx.COLOR_TRANSPARENT); var length, r1, r2, r3, r4, deflect1, deflect2; var centerX = width_screen/2; var centerY = height_screen/2; if (whichHand == 0) //hour hand { length = 0.6*centerX; r1 = 0.0*length; r2 = 0.39*length; r3 = 0.49*length; r4 = 1.1*length; deflect1 = 0.10*width; deflect2 = 0.08*width; } else //minute hand { length = 1.0*centerX; r1 = 0.0*length; r2 = 0.37*length; r3 = 0.47*length; r4 = 1.2*length; deflect1 = 0.10*width; deflect2 = 0.08*width; } var coords = [ [centerX + r1 * Math.sin(angle) , centerY - r1 * Math.cos(angle)], [centerX + r2 * Math.sin(angle+deflect1) , centerY - r2 * Math.cos(angle+deflect1)], [centerX + r3 * Math.sin(angle+deflect2) , centerY - r3 * Math.cos(angle+deflect2)], [centerX + r4 * Math.sin(angle) , centerY - r4 * Math.cos(angle)], [centerX + r3 * Math.sin(angle-deflect2) , centerY - r3 * Math.cos(angle-deflect2)], [centerX + r2 * Math.sin(angle-deflect1) , centerY - r2 * Math.cos(angle-deflect1)], [centerX + r1 * Math.sin(angle) , centerY - r1 * Math.cos(angle)] ]; dc.fillPolygon(coords); } function drawHands(dc, clock_hour, clock_min, clock_sec) { var hour, min, sec; // Draw the hour hand - convert to minutes then compute angle hour = ( ( ( clock_hour % 12 ) * 60 ) + clock_min ); // hour = 2*60.0; hour = hour / (12 * 60.0) * Math.PI * 2; drawHand(dc, hour, 0, 2.5, Gfx.COLOR_DK_BLUE); drawHand(dc, hour, 0, 1.6, Gfx.COLOR_LT_GRAY); // Draw the minute hand min = ( clock_min / 60.0); // min = 40/60.0; min = min * Math.PI * 2; drawHand(dc, min, 1, 1.7, Gfx.COLOR_DK_BLUE); drawHand(dc, min, 1, 1.0, Gfx.COLOR_LT_GRAY); // Draw the seconds hand (use hash graphic here) if(showSeconds) { sec = ( clock_sec / 60.0) * Math.PI * 2; drawHash(dc, sec, width_screen/2, 4, 25, Gfx.COLOR_DK_BLUE); drawHash(dc, sec, width_screen/2, 2, 25, Gfx.COLOR_LT_GRAY); } // Draw the inner circle dc.setColor(Gfx.COLOR_DK_BLUE, background_color); dc.fillCircle(width_screen/2, height_screen/2, 6); dc.setColor(background_color,background_color); dc.drawCircle(width_screen/2, height_screen/2, 6); dc.fillCircle(width_screen/2, height_screen/2, 2); } function drawHash(dc, angle, length, width, overheadLine, handColour) { dc.setColor(handColour, Gfx.COLOR_TRANSPARENT); var centerX = width_screen/2; var centerY = height_screen/2; var result = new [4]; var cos = Math.cos(angle); var sin = Math.sin(angle); var coords = [ [-(width/2), 0 + overheadLine], [-(width/2), -length], [width/2, -length], [width/2, 0 + overheadLine] ]; for (var i = 0; i < 4; i += 1) { var x = (coords[i][0] * cos) - (coords[i][1] * sin); var y = (coords[i][0] * sin) + (coords[i][1] * cos); result[i] = [ centerX + x, centerY + y]; } dc.fillPolygon(result); } //! Draw the hash mark symbols function drawHashMarks(dc) { drawHash(dc, hashMarksArray[5][0], 110, 3, hashMarksArray[5][1], Gfx.COLOR_WHITE); drawHash(dc, hashMarksArray[10][0], 110, 3, hashMarksArray[10][1], Gfx.COLOR_WHITE); drawHash(dc, hashMarksArray[20][0], 110, 3, hashMarksArray[20][1], Gfx.COLOR_WHITE); drawHash(dc, hashMarksArray[25][0], 110, 3, hashMarksArray[25][1], Gfx.COLOR_WHITE); drawHash(dc, hashMarksArray[35][0], 110, 3, hashMarksArray[35][1], Gfx.COLOR_WHITE); drawHash(dc, hashMarksArray[40][0], 110, 3, hashMarksArray[40][1], Gfx.COLOR_WHITE); drawHash(dc, hashMarksArray[50][0], 110, 3, hashMarksArray[50][1], Gfx.COLOR_WHITE); drawHash(dc, hashMarksArray[55][0], 110, 3, hashMarksArray[55][1], Gfx.COLOR_WHITE); drawHash(dc, hashMarksArray[0][0], 110, 5, hashMarksArray[0][1], Gfx.COLOR_WHITE); drawHash(dc, hashMarksArray[15][0], 110, 5, hashMarksArray[15][1], Gfx.COLOR_WHITE); drawHash(dc, hashMarksArray[45][0], 110, 5, hashMarksArray[45][1], Gfx.COLOR_WHITE); drawHash(dc, Math.PI, 110, 5, hashMarksArray[0][1], Gfx.COLOR_WHITE); if(!showHeartRate) { drawHash(dc, hashMarksArray[30][0], 110, 5, hashMarksArray[30][1], Gfx.COLOR_WHITE); } } function drawDate(dc) { var info = Calendar.info(Time.now(), Time.FORMAT_LONG); var dateStr = Lang.format("$1$ $2$", [info.month, info.day]); dc.drawText(width_screen/2-50, height_screen/2 - 30, Gfx.FONT_TINY, info.day_of_week, Gfx.TEXT_JUSTIFY_CENTER); dc.drawText(width_screen/2-50, height_screen/2 - 13, Gfx.FONT_TINY, dateStr, Gfx.TEXT_JUSTIFY_CENTER); dc.drawText(width_screen/2-50, height_screen/2 + 6, Gfx.FONT_TINY, info.year-2000, Gfx.TEXT_JUSTIFY_CENTER); } function drawDigitalTime(dc, clockTime) { if (showSecondTime) { var offsetHour = clockTime.hour + secondTimeOffset; if (offsetHour > 23) { offsetHour -= 24; } else if (offsetHour < 0) { offsetHour += 24; } var ampm = "AM"; if (offsetHour >= 12) { ampm = "PM"; } var timeString = Lang.format("$1$:$2$ $3$", [to12hourFormat(offsetHour), clockTime.min.format("%02d"), ampm]); dc.drawText(width_screen/2, height_screen/2 + 50, Gfx.FONT_SMALL, timeString, Gfx.TEXT_JUSTIFY_CENTER|Graphics.TEXT_JUSTIFY_VCENTER); } } function drawSunriseSunset(dc) { var sc = new SunCalc(); var lat; var lon; var timeStringRise = " --:--"; var timeStringSet = " --:--"; var loc = Activity.getActivityInfo().currentLocation; if (loc == null) { lat = App.getApp().getProperty(LAT); lon = App.getApp().getProperty(LON); } else { lat = loc.toDegrees()[0] * Math.PI / 180.0; App.getApp().setProperty(LAT, lat); lon = loc.toDegrees()[1] * Math.PI / 180.0; App.getApp().setProperty(LON, lon); } // lat = -37.81400 * Math.PI / 180.0; // lon = 144.96332 * Math.PI / 180.0; if(lat != null && lon != null) { var ampm; var now = new Time.Moment(Time.now().value()); var sunrise_moment = sc.calculate(now, lat.toDouble(), lon.toDouble(), SUNRISE); var sunset_moment = sc.calculate(now, lat.toDouble(), lon.toDouble(), SUNSET); var timeInfoSunrise = Calendar.info(sunrise_moment, Time.FORMAT_SHORT); var timeInfoSunset = Calendar.info(sunset_moment, Time.FORMAT_SHORT); ampm = "a"; if (timeInfoSunrise.hour >= 12) { ampm = "p"; } timeStringRise = Lang.format("$1$:$2$$3$", [to12hourFormat(timeInfoSunrise.hour), timeInfoSunrise.min.format("%02d"), ampm]); ampm = "a"; if (timeInfoSunset.hour >= 12) { ampm = "p"; } timeStringSet = Lang.format("$1$:$2$$3$", [to12hourFormat(timeInfoSunset.hour), timeInfoSunset.min.format("%02d"), ampm]); } dc.drawText(3, height_screen/2 - 14, Gfx.FONT_SMALL, timeStringRise, Gfx.TEXT_JUSTIFY_LEFT|Graphics.TEXT_JUSTIFY_VCENTER); dc.drawText(3, height_screen/2 + 11, Gfx.FONT_SMALL, timeStringSet, Gfx.TEXT_JUSTIFY_LEFT|Graphics.TEXT_JUSTIFY_VCENTER); } function to12hourFormat(hour) { var hour12 = hour % 12; if (hour12 == 0) { hour12 = 12; } return hour12; } // function authenticate(code) { // proFeatures = true; // // set proFeatures=false // // insert your authentication requirements here // // then change proFeatures=true if "code" variable is valid // } }