mirror of
https://github.com/google/pebble.git
synced 2025-03-19 10:31:21 +00:00
370 lines
11 KiB
Markdown
370 lines
11 KiB
Markdown
|
---
|
||
|
# Copyright 2025 Google LLC
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
|
||
|
title: Rocky.js Overview
|
||
|
description: |
|
||
|
Details of Rocky.js projects, available APIs, limitations, and how to get
|
||
|
started.
|
||
|
guide_group: rocky-js
|
||
|
order: 1
|
||
|
platform_choice: true
|
||
|
related_examples:
|
||
|
- title: Tutorial Part 1
|
||
|
url: https://github.com/pebble-examples/rocky-watchface-tutorial-part1
|
||
|
- title: Tutorial Part 2
|
||
|
url: https://github.com/pebble-examples/rocky-watchface-tutorial-part2
|
||
|
- title: Memory Pressure
|
||
|
url: https://github.com/pebble-examples/rocky-memorypressure
|
||
|
---
|
||
|
|
||
|
Rocky.js can be used to create Pebble 4.0 watchfaces using ECMAScript 5.1
|
||
|
JavaScript, which runs natively on the watch. Rocky.js is possible due to
|
||
|
[our collaboration](https://github.com/Samsung/jerryscript/wiki/JerryScriptWorkshopApril2016)
|
||
|
with [JerryScript](https://github.com/pebble/jerryscript).
|
||
|
|
||
|
> At this time, Rocky.js cannot be used to create watchapps, but we're currently
|
||
|
working towards this goal.
|
||
|
|
||
|
|
||
|
## It's JavaScript on the freakin' watch!
|
||
|
|
||
|
```javascript
|
||
|
var rocky = require('rocky');
|
||
|
|
||
|
rocky.on('minutechange', function(event) {
|
||
|
rocky.requestDraw();
|
||
|
});
|
||
|
|
||
|
rocky.on('draw', function(event) {
|
||
|
var ctx = event.context;
|
||
|
ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
|
||
|
ctx.fillStyle = 'white';
|
||
|
ctx.textAlign = 'center';
|
||
|
|
||
|
var w = ctx.canvas.unobstructedWidth;
|
||
|
var h = ctx.canvas.unobstructedHeight;
|
||
|
ctx.fillText('JavaScript\non the watch!', w / 2, h / 2);
|
||
|
});
|
||
|
```
|
||
|
|
||
|

|
||
|
|
||
|
|
||
|
## Rocky.js Projects
|
||
|
|
||
|
Rocky.js projects have a different structure from projects created using our C
|
||
|
SDK. There is a Rocky.js (rocky) component which runs on the watch, and a
|
||
|
{% guide_link communication/using-pebblekit-js "PebbleKit JS" %} (pkjs) component
|
||
|
which runs on the phone. The pkjs component allows developers to access web
|
||
|
services, use geolocation, and offload data processing tasks to the phone.
|
||
|
|
||
|
|
||
|
### Creating a Project
|
||
|
|
||
|
^CP^ Go to [CloudPebble]({{ site.links.cloudpebble }}) and click 'CREATE', enter
|
||
|
a project name, then select the 'Rocky.js' project type.
|
||
|
|
||
|
<div class="platform-specific" data-sdk-platform="local">
|
||
|
{% markdown {} %}
|
||
|
Once you've installed the Pebble SDK, you can create a new Rocky.js project
|
||
|
using the following command:
|
||
|
|
||
|
```nc|text
|
||
|
$ pebble new-project --rocky <strong><em>projectname</em></strong>
|
||
|
```
|
||
|
{% endmarkdown %}
|
||
|
</div>
|
||
|
|
||
|
|
||
|
### Rocky JS
|
||
|
|
||
|
^CP^ In [CloudPebble]({{ site.links.cloudpebble }}), add a new App Source, the
|
||
|
file type is JavaScript and the target is `Rocky JS`. `index.js` is now the main
|
||
|
entry point into the application on the watch.
|
||
|
|
||
|
^LC^ In the local SDK, our main entry point into the application on the watch is
|
||
|
`/src/rocky/index.js`.
|
||
|
|
||
|
This is file is where our Rocky.js JavaScript code resides. All code within this
|
||
|
file will be executed on the smartwatch. In addition to standard JavaScript,
|
||
|
developers have access to the [rocky](/docs/rockyjs/rocky/) object. Additional
|
||
|
scripts may also be added, see [below](#additional-scripts).
|
||
|
|
||
|
|
||
|
### PebbleKit JS
|
||
|
|
||
|
^CP^ In [CloudPebble]({{ site.links.cloudpebble }}), add a new App Source, the
|
||
|
file type is JavaScript and the target is [PebbleKit JS](/docs/pebblekit-js/).
|
||
|
This file should be named `index.js`.
|
||
|
|
||
|
^LC^ In the local SDK, our primary [PebbleKit JS](/docs/pebblekit-js/) script is
|
||
|
`/src/pkjs/index.js`.
|
||
|
|
||
|
All PebbleKit JS code will execute on the mobile device connected to the
|
||
|
smartwatch. In addition to standard JavaScript, developers have access to
|
||
|
[WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API),
|
||
|
[XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest),
|
||
|
[Geolocation](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation),
|
||
|
[LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/LocalStorage)
|
||
|
and the [Pebble](/docs/pebblekit-js/) object. Additional scripts may also be
|
||
|
added, see [below](#additional-scripts).
|
||
|
|
||
|
|
||
|
### Shared JS
|
||
|
|
||
|
If you need to share code between Rocky.js and PebbleKit JS, you can place
|
||
|
JavaScript files in a shared area.
|
||
|
|
||
|
^CP^ In [CloudPebble]({{ site.links.cloudpebble }}), add a new App Source, the
|
||
|
file type is JavaScript and the target is `Shared JS`.
|
||
|
|
||
|
^LC^ In the local SDK, place your shared files in `/src/common/`.
|
||
|
|
||
|
Shared JavaScript files can be referenced using the
|
||
|
[CommonJS Module](http://www.commonjs.org/specs/modules/1.0/) format.
|
||
|
|
||
|
```javascript
|
||
|
// Shared JS (index.js)
|
||
|
function test() {
|
||
|
console.log('Hello from shared code');
|
||
|
}
|
||
|
|
||
|
module.exports.test = test;
|
||
|
```
|
||
|
|
||
|
```javascript
|
||
|
// Rocky JS
|
||
|
var shared = require('../common/index');
|
||
|
shared.test();
|
||
|
```
|
||
|
|
||
|
```javascript
|
||
|
// PebbleKit JS
|
||
|
var shared = require('../common/index');
|
||
|
shared.test();
|
||
|
```
|
||
|
|
||
|
|
||
|
### Additional Scripts
|
||
|
|
||
|
Both the `Rocky JS` and ` PebbleKit JS` support the use of multiple .js files.
|
||
|
This helps to keep your code clean and modular. Use the
|
||
|
[CommonJS Module](http://www.commonjs.org/specs/modules/1.0/) format for
|
||
|
your additional scripts, then `require()` them within your script.
|
||
|
|
||
|
```javascript
|
||
|
// additional.js
|
||
|
function test() {
|
||
|
console.log('Additional File');
|
||
|
}
|
||
|
|
||
|
module.exports.test = test;
|
||
|
```
|
||
|
|
||
|
```javascript
|
||
|
var additional = require('./additional');
|
||
|
additional.test();
|
||
|
```
|
||
|
|
||
|
|
||
|
## Available APIs
|
||
|
|
||
|
In this initial release of Rocky.js, we have focused on the ability to create
|
||
|
watchfaces only. We will be adding more and more APIs as time progresses, and
|
||
|
we're determined for JavaScript to have feature parity with the rest of the
|
||
|
Pebble developer ecosystem.
|
||
|
|
||
|
We've developed our API in-line with standard
|
||
|
[Web APIs](https://developer.mozilla.org/en-US/docs/Web/API), which may appear
|
||
|
strange to existing Pebble developers, but we're confident that this will
|
||
|
facilitate code re-use and provide a better experience overall.
|
||
|
|
||
|
|
||
|
### System Events
|
||
|
|
||
|
We've provided a series of events which every watchface will likely require, and
|
||
|
each of these events allow you to provide a callback function that is called
|
||
|
when the event occurs.
|
||
|
|
||
|
Existing Pebble developers will be familiar with the tick style events,
|
||
|
including:
|
||
|
|
||
|
* [`secondchange`](/docs/rockyjs/rocky/#on)
|
||
|
* [`minutechange`](/docs/rockyjs/rocky/#on)
|
||
|
* [`hourchange`](/docs/rockyjs/rocky/#on)
|
||
|
* [`daychange`](/docs/rockyjs/rocky/#on)
|
||
|
|
||
|
By using these events, instead of
|
||
|
[`setInterval`](/docs/rockyjs), we're automatically kept in sync with the wall
|
||
|
clock time.
|
||
|
|
||
|
We also have a
|
||
|
[`message`](/docs/rockyjs/rocky/#on) event for
|
||
|
receiving JavaScript JSON objects from the `pkjs` component, a
|
||
|
[`memorypressure`](/docs/rockyjs/rocky/#on) event when there is a notable change
|
||
|
in available system memory, and a [`draw`](/docs/rockyjs/rocky/#on) event which
|
||
|
you'll use to control the screen updates.
|
||
|
|
||
|
```javascript
|
||
|
var rocky = require('rocky');
|
||
|
|
||
|
rocky.on('minutechange', function(event) {
|
||
|
// Request the screen to be redrawn on next pass
|
||
|
rocky.requestDraw();
|
||
|
});
|
||
|
```
|
||
|
|
||
|
|
||
|
### Drawing Canvas
|
||
|
|
||
|
The canvas is a 2D rendering context and represents the display of the Pebble
|
||
|
smartwatch. We use the canvas context for drawing text and shapes. We're aiming
|
||
|
to support standard Web API methods and properties where possible, so the canvas
|
||
|
has been made available as a
|
||
|
[CanvasRenderingContext2D](/docs/rockyjs/CanvasRenderingContext2D/).
|
||
|
|
||
|
> Please note that the canvas isn't fully implemented yet, so certain methods
|
||
|
and properties are not available at this time. We're still working on this, so
|
||
|
expect more features in future updates!
|
||
|
|
||
|
```javascript
|
||
|
rocky.on('draw', function(event) {
|
||
|
var ctx = event.context;
|
||
|
|
||
|
ctx.fillStyle = 'red';
|
||
|
ctx.textAlign = 'center';
|
||
|
ctx.font = '14px Gothic';
|
||
|
|
||
|
var w = ctx.canvas.unobstructedWidth;
|
||
|
var h = ctx.canvas.unobstructedHeight;
|
||
|
ctx.fillText('Rocky.js Rocks!', w / 2, h / 2);
|
||
|
});
|
||
|
```
|
||
|
|
||
|
|
||
|
### Messaging
|
||
|
|
||
|
For Rocky.js projects only, we've added a new simplified communication channel
|
||
|
[`postMessage()`](/docs/rockyjs/rocky/#postMessage) and
|
||
|
[`on('message', ...)`](/docs/rockyjs/rocky/#on) which allows you to send and
|
||
|
receive JavaScript JSON objects between the phone and smartwatch.
|
||
|
|
||
|
```javascript
|
||
|
// Rocky.js (rocky)
|
||
|
|
||
|
// Receive data from the phone (pkjs)
|
||
|
rocky.on('message', function(event) {
|
||
|
console.log(JSON.stringify(event.data));
|
||
|
});
|
||
|
|
||
|
// Send data to the phone (pkjs)
|
||
|
rocky.postMessage({command: 'fetch'});
|
||
|
```
|
||
|
|
||
|
```javascript
|
||
|
// PebbleKit JS (pkjs)
|
||
|
|
||
|
// Receive data from the watch (rocky)
|
||
|
Pebble.on('message', function(event) {
|
||
|
if(event.data.command === 'fetch') {
|
||
|
// doSomething();
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Send data to the watch (rocky)
|
||
|
Pebble.postMessage({
|
||
|
'temperature': 90,
|
||
|
'condition': 'Hot'
|
||
|
});
|
||
|
```
|
||
|
|
||
|
You can see an example of post message in action in
|
||
|
[part 2](https://github.com/pebble-examples/rocky-watchface-tutorial-part2) of
|
||
|
the Rocky.js tutorial.
|
||
|
|
||
|
|
||
|
### Memory Pressure
|
||
|
|
||
|
The [`memorypressure`](/docs/rockyjs/rocky/#on) event is emitted every time
|
||
|
there is a notable change in available system memory. This provides developers
|
||
|
with an opportunity to free some memory, in order to prevent their application
|
||
|
from being terminated when memory pressure is high.
|
||
|
|
||
|
```javascript
|
||
|
rocky.on('memorypressure', function(event) {
|
||
|
console.log(event.level);
|
||
|
});
|
||
|
```
|
||
|
|
||
|
A detailed example of the [`memorypressure`](/docs/rockyjs/rocky/#on) event
|
||
|
is provided [here](https://github.com/pebble-examples/rocky-memorypressure).
|
||
|
|
||
|
|
||
|
### Content Size
|
||
|
|
||
|
The [`contentSize`](/docs/rockyjs/rocky/#UserPreferences) property allows
|
||
|
developers to dynamically adapt their watchface design based upon the system
|
||
|
`Text Size` preference (*Settings > Notifications > Text Size*).
|
||
|
|
||
|
`contentSize` is exposed in Rocky.js via the
|
||
|
[`UserPreferences`](/docs/rockyjs/rocky/#UserPreferences) object.
|
||
|
|
||
|
```javascript
|
||
|
rocky.on('draw', function(event) {
|
||
|
var ctx = event.context;
|
||
|
// ...
|
||
|
if (rocky.userPreferences.contentSize === 'x-large') {
|
||
|
ctx.font = '42px bold numbers Leco-numbers';
|
||
|
} else {
|
||
|
ctx.font = '32px bold numbers Leco-numbers';
|
||
|
}
|
||
|
// ...
|
||
|
});
|
||
|
```
|
||
|
|
||
|
## App Configuration
|
||
|
|
||
|
[Clay](https://github.com/pebble/clay#) is a JavaScript library that makes it
|
||
|
easy to add offline configuration pages to your Pebble apps. Out of the box,
|
||
|
Clay is not currently compatible with Rocky.js, but it can be made to work by
|
||
|
manually including the clay.js file and overriding the default events.
|
||
|
|
||
|
You can find a community Rocky.js project which uses Clay
|
||
|
[here](https://github.com/orviwan/rocky-leco-clay).
|
||
|
|
||
|
|
||
|
## Limitations
|
||
|
|
||
|
Although Rocky.js is finally out of beta, there are still some limitations and
|
||
|
restrictions that you need to be aware of:
|
||
|
|
||
|
* No support for custom fonts, images and other resources, yet.
|
||
|
* No C code allowed.
|
||
|
* No messageKeys.
|
||
|
* Pebble Packages are not supported.
|
||
|
* There are file size and memory constraints for Rocky.js projects.
|
||
|
If you include a large JS library, it probably won't work.
|
||
|
|
||
|
|
||
|
## How to Get Started
|
||
|
|
||
|
We created a [2-part tutorial](/tutorials/js-watchface-tutorial/part1/) for
|
||
|
getting started with Rocky.js watchfaces. It explains everything you need to
|
||
|
know about creating digital and analog watchfaces, plus how to retrieve
|
||
|
weather conditions from the internet.
|
||
|
|
||
|
If you're looking for more detailed information, check out the
|
||
|
[API Documentation](/docs/rockyjs).
|