Initial commit
This commit is contained in:
commit
1e9c24262b
7 changed files with 248 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
build/
|
||||||
|
compile_commands.json
|
||||||
|
.lock*
|
||||||
|
node_modules/
|
||||||
|
.cache/
|
||||||
36
README.md
Normal file
36
README.md
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
# eatordonteat
|
||||||
|
|
||||||
|
A Pebble watchapp/watchface written in C using the Pebble SDK.
|
||||||
|
|
||||||
|
## Building & running
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pebble build # build for all targetPlatforms
|
||||||
|
pebble install --emulator emery # install on the emery emulator
|
||||||
|
pebble install --phone <ip> # install to a paired phone
|
||||||
|
```
|
||||||
|
|
||||||
|
## Target platforms
|
||||||
|
|
||||||
|
`targetPlatforms` in `package.json` controls which watches you build for. The
|
||||||
|
modern Pebble hardware is **emery** (Pebble Time 2), **gabbro** (Pebble Round
|
||||||
|
2), and **flint** (Pebble 2 Duo); the original Pebble platforms (aplite,
|
||||||
|
basalt, chalk, diorite) are included by default for backwards compatibility.
|
||||||
|
|
||||||
|
## Project layout
|
||||||
|
|
||||||
|
```
|
||||||
|
src/c/ C source for the watchapp
|
||||||
|
src/pkjs/ PebbleKit JS (phone-side) source, if any
|
||||||
|
worker_src/c/ Background worker source, if any
|
||||||
|
resources/ Images, fonts, and other bundled resources
|
||||||
|
package.json Project metadata (UUID, platforms, resources, message keys)
|
||||||
|
wscript Build rules — usually no need to edit
|
||||||
|
```
|
||||||
|
|
||||||
|
By default this project is configured as a watchapp. To make it a watchface,
|
||||||
|
set `pebble.watchapp.watchface` to `true` in `package.json`.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Full SDK docs, tutorials, and API reference: <https://developer.repebble.com>
|
||||||
21
package-lock.json
generated
Normal file
21
package-lock.json
generated
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "eatordonteat",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "eatordonteat",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@rebble/clay": "^1.0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@rebble/clay": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rebble/clay/-/clay-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-84EL9J6egrnWk/FzqCxRa9/vqO4fx7SBxdttthLEpBro+FVqUg+rMlqOzT8+zl4PkBQKAWdnqHwlHaS4heiXKg==",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
package.json
Normal file
36
package.json
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"name": "eatordonteat",
|
||||||
|
"author": "MakeAwesomeHappen",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"keywords": [
|
||||||
|
"pebble-app"
|
||||||
|
],
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@rebble/clay": "^1.0.10"
|
||||||
|
},
|
||||||
|
"pebble": {
|
||||||
|
"displayName": "Eat / Don't Eat watchface",
|
||||||
|
"uuid": "34fbfd25-b227-49fd-9c90-7f71b9731131",
|
||||||
|
"sdkVersion": "3",
|
||||||
|
"enableMultiJS": true,
|
||||||
|
"targetPlatforms": [
|
||||||
|
"aplite",
|
||||||
|
"basalt",
|
||||||
|
"chalk",
|
||||||
|
"diorite",
|
||||||
|
"emery",
|
||||||
|
"flint",
|
||||||
|
"gabbro"
|
||||||
|
],
|
||||||
|
"watchapp": {
|
||||||
|
"watchface": true
|
||||||
|
},
|
||||||
|
"messageKeys": [
|
||||||
|
"dummy"
|
||||||
|
],
|
||||||
|
"resources": {
|
||||||
|
"media": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
86
src/c/eatordonteat.c
Normal file
86
src/c/eatordonteat.c
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <pebble.h>
|
||||||
|
|
||||||
|
static Window *s_main_window;
|
||||||
|
static TextLayer *s_time_layer;
|
||||||
|
static TextLayer *s_date_layer;
|
||||||
|
|
||||||
|
static void update_time() {
|
||||||
|
// Get a tm structure
|
||||||
|
time_t temp = time(NULL);
|
||||||
|
struct tm *tick_time = localtime(&temp);
|
||||||
|
|
||||||
|
// Write the current hours and minutes into a buffer
|
||||||
|
static char s_time_buffer[8];
|
||||||
|
strftime(s_time_buffer, sizeof(s_time_buffer),
|
||||||
|
clock_is_24h_style() ? "%H:%M" : "%I:%M", tick_time);
|
||||||
|
|
||||||
|
// Display this time on the TextLayer
|
||||||
|
text_layer_set_text(s_time_layer, s_time_buffer);
|
||||||
|
|
||||||
|
// Write the current date into a buffer
|
||||||
|
static char s_date_buffer[16];
|
||||||
|
strftime(s_date_buffer, sizeof(s_date_buffer), "%a %b %d", tick_time);
|
||||||
|
|
||||||
|
// Display the date
|
||||||
|
text_layer_set_text(s_date_layer, s_date_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tick_handler(struct tm *tick_time, TimeUnits units_changed) {
|
||||||
|
update_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void main_window_load(Window *window) {
|
||||||
|
Layer *window_layer = window_get_root_layer(window);
|
||||||
|
GRect bounds = layer_get_bounds(window_layer);
|
||||||
|
|
||||||
|
// Create the time TextLayer
|
||||||
|
s_time_layer =
|
||||||
|
text_layer_create(GRect(0, PBL_IF_ROUND_ELSE(58, 52), bounds.size.w, 50));
|
||||||
|
text_layer_set_background_color(s_time_layer, GColorClear);
|
||||||
|
text_layer_set_text_color(s_time_layer, GColorWhite);
|
||||||
|
text_layer_set_font(s_time_layer,
|
||||||
|
fonts_get_system_font(FONT_KEY_BITHAM_42_BOLD));
|
||||||
|
text_layer_set_text_alignment(s_time_layer, GTextAlignmentCenter);
|
||||||
|
|
||||||
|
// Add it as a child layer to the Window's root layer
|
||||||
|
layer_add_child(window_layer, text_layer_get_layer(s_time_layer));
|
||||||
|
|
||||||
|
// Create the date TextLayer
|
||||||
|
s_date_layer = text_layer_create(
|
||||||
|
GRect(0, PBL_IF_ROUND_ELSE(110, 104), bounds.size.w, 30));
|
||||||
|
text_layer_set_background_color(s_date_layer, GColorClear);
|
||||||
|
text_layer_set_text_color(s_date_layer, GColorWhite);
|
||||||
|
text_layer_set_font(s_date_layer,
|
||||||
|
fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD));
|
||||||
|
text_layer_set_text_alignment(s_date_layer, GTextAlignmentCenter);
|
||||||
|
|
||||||
|
// Add to Window
|
||||||
|
layer_add_child(window_layer, text_layer_get_layer(s_date_layer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void main_window_unload(Window *window) {
|
||||||
|
text_layer_destroy(s_date_layer);
|
||||||
|
text_layer_destroy(s_time_layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init() {
|
||||||
|
s_main_window = window_create();
|
||||||
|
window_set_background_color(s_main_window, GColorBlack);
|
||||||
|
|
||||||
|
window_set_window_handlers(
|
||||||
|
s_main_window,
|
||||||
|
(WindowHandlers){.load = main_window_load, .unload = main_window_unload});
|
||||||
|
|
||||||
|
window_stack_push(s_main_window, true);
|
||||||
|
|
||||||
|
update_time();
|
||||||
|
tick_timer_service_subscribe(MINUTE_UNIT, tick_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deinit() { window_destroy(s_main_window); }
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
init();
|
||||||
|
app_event_loop();
|
||||||
|
deinit();
|
||||||
|
}
|
||||||
10
src/pkjs/config.json
Normal file
10
src/pkjs/config.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "heading",
|
||||||
|
"defaultValue": "Example Header Item"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"defaultValue": "Example text item."
|
||||||
|
}
|
||||||
|
]
|
||||||
54
wscript
Normal file
54
wscript
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#
|
||||||
|
# This file is the default set of rules to compile a Pebble application.
|
||||||
|
#
|
||||||
|
# Feel free to customize this to your needs.
|
||||||
|
#
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
top = '.'
|
||||||
|
out = 'build'
|
||||||
|
|
||||||
|
|
||||||
|
def options(ctx):
|
||||||
|
ctx.load('pebble_sdk')
|
||||||
|
|
||||||
|
|
||||||
|
def configure(ctx):
|
||||||
|
"""
|
||||||
|
This method is used to configure your build. ctx.load(`pebble_sdk`) automatically configures
|
||||||
|
a build for each valid platform in `targetPlatforms`. Platform-specific configuration: add your
|
||||||
|
change after calling ctx.load('pebble_sdk') and make sure to set the correct environment first.
|
||||||
|
Universal configuration: add your change prior to calling ctx.load('pebble_sdk').
|
||||||
|
"""
|
||||||
|
ctx.load('pebble_sdk')
|
||||||
|
|
||||||
|
|
||||||
|
def build(ctx):
|
||||||
|
ctx.load('pebble_sdk')
|
||||||
|
|
||||||
|
build_worker = os.path.exists('worker_src')
|
||||||
|
binaries = []
|
||||||
|
|
||||||
|
cached_env = ctx.env
|
||||||
|
for platform in ctx.env.TARGET_PLATFORMS:
|
||||||
|
ctx.env = ctx.all_envs[platform]
|
||||||
|
ctx.set_group(ctx.env.PLATFORM_NAME)
|
||||||
|
app_elf = '{}/pebble-app.elf'.format(ctx.env.BUILD_DIR)
|
||||||
|
ctx.pbl_build(source=ctx.path.ant_glob('src/c/**/*.c'), target=app_elf, bin_type='app')
|
||||||
|
|
||||||
|
if build_worker:
|
||||||
|
worker_elf = '{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR)
|
||||||
|
binaries.append({'platform': platform, 'app_elf': app_elf, 'worker_elf': worker_elf})
|
||||||
|
ctx.pbl_build(source=ctx.path.ant_glob('worker_src/c/**/*.c'),
|
||||||
|
target=worker_elf,
|
||||||
|
bin_type='worker')
|
||||||
|
else:
|
||||||
|
binaries.append({'platform': platform, 'app_elf': app_elf})
|
||||||
|
ctx.env = cached_env
|
||||||
|
|
||||||
|
ctx.set_group('bundle')
|
||||||
|
ctx.pbl_bundle(binaries=binaries,
|
||||||
|
js=ctx.path.ant_glob(['src/pkjs/**/*.js',
|
||||||
|
'src/pkjs/**/*.json',
|
||||||
|
'src/common/**/*.js']),
|
||||||
|
js_entry_file='src/pkjs/index.js')
|
||||||
Loading…
Reference in a new issue