@@ -69,7 +69,8 @@ To send a message from the smartwatch to the mobile device, use the
6969object:
7070
7171``` js
72- // rocky index.js
72+ // File: rocky/index.js
73+
7374var rocky = require (' rocky' );
7475
7576// Send a message from the smartwatch
@@ -80,7 +81,7 @@ To send a message from the mobile device to the smartwatch, use the
8081`` Pebble.postMessage `` method:
8182
8283``` js
83- // pkjs index.js
84+ // File: pkjs/ index.js
8485
8586// Send a message from the mobile device
8687Pebble .postMessage ({' test' : ' hello from mobile device' });
@@ -92,7 +93,7 @@ We can create a message listener in our smartwatch code using the ``rocky.on``
9293method:
9394
9495``` js
95- // rocky index.js
96+ // File: rocky/ index.js
9697
9798// On the smartwatch, begin listening for a message from the mobile device
9899rocky .on (' message' , function (event ) {
@@ -105,7 +106,7 @@ We can also create a message listener in our `pkjs` code using the ``Pebble.on``
105106method:
106107
107108``` js
108- // pkjs index.js
109+ // File: pkjs/ index.js
109110
110111// On the phone, begin listening for a message from the smartwatch
111112Pebble .on (' message' , function (event ) {
@@ -126,12 +127,12 @@ In order to use this functionality, your application must include the
126127array of your ` package.json ` file.
127128
128129``` js
129- // file : package.json
130- // ...
131- " pebble" : {
132- " capabilities " : [ " location " ]
133- }
134- // ...
130+ // File : package.json
131+
132+ " pebble" : {
133+ // ...
134+ " capabilities " : [ " location " ]
135+ }
135136```
136137
137138Once we've added the ` location ` flag, we can access GPS coordinates using the
@@ -140,7 +141,7 @@ In this example, we're going to request the user's location when we receive the
140141"fetch" message from the smartwatch.
141142
142143``` js
143- // pkjs index.js
144+ // File: pkjs/ index.js
144145
145146Pebble .on (' message' , function (event ) {
146147 // Get the message that was passed
@@ -166,14 +167,14 @@ services.
166167
167168In this tutorial, we will interface with
168169[ Open Weather Map] ( http://openweathermap.org/ ) – a common weather API used by
169- the [ Pebble Developer Community ] ( https://forums.pebble.com/c/development ) .
170+ many Pebble watchfaces .
170171
171172The ` XMLHttpRequest ` object is quite powerful, but can be intimidating to get
172173started with. To make things a bit simpler, we'll wrap the object with a helper
173174function which makes the request, then raises a callback:
174175
175176``` js
176- // pkjs index.js
177+ // File: pkjs/ index.js
177178
178179function request (url , type , callback ) {
179180 var xhr = new XMLHttpRequest ();
@@ -199,7 +200,8 @@ followed by the API key:
199200{% include guides/owm-api-key-notice.html %}
200201
201202``` js
202- var myAPIKey = ' 1234567' ;
203+ var myAPIKey = ' your own key here!' ;
204+
203205var url = ' http://api.openweathermap.org/data/2.5/weather' +
204206 ' ?lat=' + pos .coords .latitude +
205207 ' &lon=' + pos .coords .longitude +
@@ -209,9 +211,9 @@ var url = 'http://api.openweathermap.org/data/2.5/weather' +
209211All together, our message handler should now look like the following:
210212
211213``` js
212- // pkjs index.js
214+ // File: pkjs/ index.js
213215
214- var myAPIKey = ' 1234567 ' ;
216+ var myAPIKey = ' your own key here! ' ;
215217
216218Pebble .on (' message' , function (event ) {
217219 // Get the message that was passed
@@ -242,7 +244,7 @@ Once we receive the weather data from OpenWeatherMap, we need to send it to the
242244smartwatch using `` Pebble.postMessage `` :
243245
244246``` js
245- // pkjs index.js
247+ // File: pkjs/ index.js
246248
247249// ...
248250request (url, ' GET' , function (respText ) {
@@ -263,9 +265,12 @@ On the smartwatch, we'll need to create a message handler to listen for a
263265` weather ` message, and store the information so it can be drawn on screen.
264266
265267``` js
266- // rocky index.js
268+ // File: rocky/index.js
269+
267270var rocky = require (' rocky' );
268271
272+ // ...
273+
269274// Global object to store weather data
270275var weather;
271276
@@ -287,21 +292,21 @@ We also need to send the 'fetch' command from the smartwatch to ask for weather
287292data when the application starts, then every hour:
288293
289294``` js
290- // rocky index.js
295+ // File: rocky/ index.js
291296
292297// ...
293298
294299rocky .on (' hourchange' , function (event ) {
295300 // Send a message to fetch the weather information (on startup and every hour)
296- rocky .postMessage ({' fetch' : true });
301+ rocky .postMessage ({ fetch: true });
297302});
298303```
299304
300305Finally, we'll need some new code in our Rocky ` draw ` handler to display the
301306temperature and conditions:
302307
303308``` js
304- // rocky index.js
309+ // File: rocky/ index.js
305310var rocky = require (' rocky' );
306311
307312// ...
@@ -334,6 +339,171 @@ rocky.on('draw', function(event) {
334339});
335340```
336341
342+ Once it is compiled and run, it should look something like the preview at the
343+ start of the tutorial section:
344+
345+ ![ rocky >{pebble-screenshot,pebble-screenshot--time-red}] ( /images/tutorials/js-watchface-tutorial/tictoc-weather.png )
346+
347+
348+ ### Putting It All Together
349+
350+ This is the complete code for this tutorial, separated by JS file. Compare it
351+ to yours if you have problems with any part of it or it is not working as
352+ expected.
353+
354+ ``` js
355+ // File: rocky/index.js
356+
357+ var rocky = require (' rocky' );
358+
359+ // Global object to store weather data
360+ var weather;
361+
362+ function fractionToRadian (fraction ) {
363+ return fraction * 2 * Math .PI ;
364+ }
365+
366+ function drawHand (ctx , cx , cy , angle , length , color ) {
367+ // Find the end points
368+ var x2 = cx + Math .sin (angle) * length;
369+ var y2 = cy - Math .cos (angle) * length;
370+
371+ // Configure how we want to draw the hand
372+ ctx .lineWidth = 8 ;
373+ ctx .strokeStyle = color;
374+
375+ // Begin drawing
376+ ctx .beginPath ();
377+
378+ // Move to the center point, then draw the line
379+ ctx .moveTo (cx, cy);
380+ ctx .lineTo (x2, y2);
381+
382+ // Stroke the line (output to display)
383+ ctx .stroke ();
384+ }
385+
386+ function drawWeather (ctx , weather ) {
387+ // Create a string describing the weather
388+ // var weatherString = weather.celcius + 'ºC, ' + weather.desc;
389+ var weatherString = weather .fahrenheit + ' ºF, ' + weather .desc ;
390+
391+ // Draw the text, top center
392+ ctx .fillStyle = ' lightgray' ;
393+ ctx .textAlign = ' center' ;
394+ ctx .font = ' 14px Gothic' ;
395+ ctx .fillText (weatherString, ctx .canvas .unobstructedWidth / 2 , 2 );
396+ }
397+
398+ rocky .on (' draw' , function (event ) {
399+ var ctx = event .context ;
400+ var d = new Date ();
401+
402+ // Clear the screen
403+ ctx .clearRect (0 , 0 , ctx .canvas .clientWidth , ctx .canvas .clientHeight );
404+
405+ // Draw the conditions (before clock hands, so it's drawn underneath them)
406+ if (weather) {
407+ drawWeather (ctx, weather);
408+ }
409+
410+ // Determine the width and height of the display
411+ var w = ctx .canvas .unobstructedWidth ;
412+ var h = ctx .canvas .unobstructedHeight ;
413+
414+ // Determine the center point of the display
415+ // and the max size of watch hands
416+ var cx = w / 2 ;
417+ var cy = h / 2 ;
418+
419+ // -20 so we're inset 10px on each side
420+ var maxLength = (Math .min (w, h) - 20 ) / 2 ;
421+
422+ // Calculate the minute hand angle
423+ var minuteFraction = (d .getMinutes ()) / 60 ;
424+ var minuteAngle = fractionToRadian (minuteFraction);
425+
426+ // Draw the minute hand
427+ drawHand (ctx, cx, cy, minuteAngle, maxLength, " white" );
428+
429+ // Calculate the hour hand angle
430+ var hourFraction = (d .getHours () % 12 + minuteFraction) / 12 ;
431+ var hourAngle = fractionToRadian (hourFraction);
432+
433+ // Draw the hour hand
434+ drawHand (ctx, cx, cy, hourAngle, maxLength * 0.6 , " lightblue" );
435+ });
436+
437+ rocky .on (' minutechange' , function (event ) {
438+ // Request the screen to be redrawn on next pass
439+ rocky .requestDraw ();
440+ });
441+
442+ rocky .on (' hourchange' , function (event ) {
443+ // Send a message to fetch the weather information (on startup and every hour)
444+ rocky .postMessage ({ fetch: true });
445+ });
446+
447+ rocky .on (' message' , function (event ) {
448+ // Receive a message from the mobile device (pkjs)
449+ var message = event .data ;
450+
451+ if (message .weather ) {
452+ // Save the weather data
453+ weather = message .weather ;
454+
455+ // Request a redraw so we see the information
456+ rocky .requestDraw ();
457+ }
458+ });
459+ ```
460+
461+ ``` js
462+ // File: pkjs/index.js
463+
464+ var myAPIKey = ' your own key here!' ;
465+
466+ function request (url , type , callback ) {
467+ var xhr = new XMLHttpRequest ();
468+ xhr .onload = function () {
469+ callback (this .responseText );
470+ };
471+ xhr .open (type, url);
472+ xhr .send ();
473+ }
474+
475+ Pebble .on (' message' , function (event ) {
476+ // Get the message that was passed
477+ var message = event .data ;
478+
479+ if (message .fetch ) {
480+ navigator .geolocation .getCurrentPosition (function (pos ) {
481+ var url = ' http://api.openweathermap.org/data/2.5/weather' +
482+ ' ?lat=' + pos .coords .latitude +
483+ ' &lon=' + pos .coords .longitude +
484+ ' &appid=' + myAPIKey;
485+
486+ request (url, ' GET' , function (respText ) {
487+ var weatherData = JSON .parse (respText);
488+
489+ Pebble .postMessage ({
490+ ' weather' : {
491+ // Convert from Kelvin
492+ ' celcius' : Math .round (weatherData .main .temp - 273.15 ),
493+ ' fahrenheit' : Math .round ((weatherData .main .temp - 273.15 ) * 9 / 5 + 32 ),
494+ ' desc' : weatherData .weather [0 ].main
495+ }
496+ });
497+ });
498+ }, function (err ) {
499+ console .error (' Error getting location' );
500+ },
501+ { timeout: 15000 , maximumAge: 60000 });
502+ }
503+ });
504+ ```
505+
506+
337507## Conclusion
338508
339509So there we have it, we successfully added web content to our JavaScript
@@ -352,15 +522,9 @@ request the weather data when the application starts and every hour.
3525228 . Then finally we drew the weather conditions on the screen as text.
353523
354524If you have problems with your code, check it against the sample source code
355- provided using the button below.
356-
357- [ View Source Code >{center,bg-lightblue,fg-white}] ( https://github.com/pebble-examples/rocky-watchface-tutorial-part2 )
525+ provided above.
358526
359527## What's Next
360528
361529We hope you enjoyed this tutorial and that it inspires you to make something
362530awesome!
363-
364- Why not let us know what you've created by tweeting
365- [ @pebbledev ] ( https://twitter.com/pebbledev ) , or join our epic developer
366- community on [ Discord] ({{ site.links.discord_invite }}).
0 commit comments