Skip to content

Commit 7cea4ed

Browse files
committed
Fixup Rocky tutorial part 2
Signed-off-by: C-D-Lewis <[email protected]>
1 parent 58afc10 commit 7cea4ed

File tree

1 file changed

+192
-28
lines changed
  • source/tutorials/js-watchface-tutorial

1 file changed

+192
-28
lines changed

source/tutorials/js-watchface-tutorial/part2.md

Lines changed: 192 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ To send a message from the smartwatch to the mobile device, use the
6969
object:
7070

7171
```js
72-
// rocky index.js
72+
// File: rocky/index.js
73+
7374
var 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
8687
Pebble.postMessage({'test': 'hello from mobile device'});
@@ -92,7 +93,7 @@ We can create a message listener in our smartwatch code using the ``rocky.on``
9293
method:
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
9899
rocky.on('message', function(event) {
@@ -105,7 +106,7 @@ We can also create a message listener in our `pkjs` code using the ``Pebble.on``
105106
method:
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
111112
Pebble.on('message', function(event) {
@@ -126,12 +127,12 @@ In order to use this functionality, your application must include the
126127
array 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

137138
Once 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

145146
Pebble.on('message', function(event) {
146147
// Get the message that was passed
@@ -166,14 +167,14 @@ services.
166167

167168
In 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

171172
The `XMLHttpRequest` object is quite powerful, but can be intimidating to get
172173
started with. To make things a bit simpler, we'll wrap the object with a helper
173174
function which makes the request, then raises a callback:
174175

175176
```js
176-
// pkjs index.js
177+
// File: pkjs/index.js
177178

178179
function 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+
203205
var 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' +
209211
All 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

216218
Pebble.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
242244
smartwatch using ``Pebble.postMessage``:
243245

244246
```js
245-
// pkjs index.js
247+
// File: pkjs/index.js
246248

247249
// ...
248250
request(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+
267270
var rocky = require('rocky');
268271

272+
// ...
273+
269274
// Global object to store weather data
270275
var weather;
271276

@@ -287,21 +292,21 @@ We also need to send the 'fetch' command from the smartwatch to ask for weather
287292
data when the application starts, then every hour:
288293

289294
```js
290-
// rocky index.js
295+
// File: rocky/index.js
291296

292297
// ...
293298

294299
rocky.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

300305
Finally, we'll need some new code in our Rocky `draw` handler to display the
301306
temperature and conditions:
302307

303308
```js
304-
// rocky index.js
309+
// File: rocky/index.js
305310
var 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

339509
So 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.
352522
8. Then finally we drew the weather conditions on the screen as text.
353523

354524
If 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

361529
We hope you enjoyed this tutorial and that it inspires you to make something
362530
awesome!
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

Comments
 (0)