mirror of
https://github.com/pebble-dev/clay.git
synced 2026-08-28 04:46:57 -04:00
[WIP] - Basic SimpleAppMessage integration for ints.
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
# We ignore everying except for what is actually used by the pebble tool.
|
||||
# We ignore everything except for what is actually used by the pebble tool.
|
||||
/**/*
|
||||
!/dist.zip
|
||||
!/src/**/*
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
cmake_minimum_required (VERSION 3.2)
|
||||
project (test-project)
|
||||
|
||||
set(CMAKE_C_FLAGS "-std=c11 -mthumb -ffunction-sections -g -fno-diagnostics-show-caret -D_REENT_SMALL=1 -Wall -Wextra -Werror -Wpointer-arith -Wno-unused-parameter -Wno-missing-field-initializers -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=unused-parameter -Wno-error=unused-but-set-variable -Wno-packed-bitfield-compat -mcpu=cortex-m3 -Os -Werror=return-type")
|
||||
|
||||
file(GLOB_RECURSE src "src/c/*")
|
||||
file(GLOB_RECURSE include "include/*")
|
||||
file(GLOB_RECURSE build "build/basalt/*.c")
|
||||
|
||||
set(SOURCES
|
||||
${src}
|
||||
${build}
|
||||
${include}
|
||||
)
|
||||
|
||||
set(INCLUDES
|
||||
~/Library/Application\ Support/Pebble\ SDK/SDKs/current/sdk-core/pebble/basalt/include
|
||||
./node_modules/pebble-events/dist/include
|
||||
./node_modules/@smallstoneapps/linked-list/dist/include
|
||||
./node_modules/@keegan-stoneware/simple-dict/dist/include
|
||||
./node_modules/@keegan-stoneware/simple-app-message/dist/include
|
||||
./build/include
|
||||
./build
|
||||
./include
|
||||
)
|
||||
|
||||
add_definitions(-DPEBBLE)
|
||||
add_definitions(-DPBL_COLOR)
|
||||
|
||||
include_directories(${INCLUDES})
|
||||
|
||||
add_executable(app ${SOURCES})
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
# Clay
|
||||
# Clay - Experimental
|
||||
|
||||
Welcome to the experimental branch of Clay. Expect this branch to be buggy, with incorrect docs, and with APIs that often change. DO NOT use this branch for your own projets but feel free to provide feedback via the Clay channel at http://discord.gg/aRUAYFN
|
||||
|
||||
---
|
||||
|
||||
Clay is a JavaScript library that makes it easy to add offline configuration pages to your Pebble apps. All you need to get started is a couple lines of JavaScript and a JSON file; no servers or HTML required.
|
||||
|
||||
Clay will by default automatically handle the 'showConfiguration' and 'webviewclosed' events traditionally implemented by developers to relay configuration settings to the watch side of the app. This step is not required when using Clay, since each config item is given the same `messageKey` as defined in `package.json` (or PebbleKit JS Message Keys on CloudPebble), and is automatically transmitted once the configuration page is submitted by the user. Developers can override this behavior by [handling the events manually](#handling-the-showconfiguration-and-webviewclosed-events-manually).
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# Ignore build generated files
|
||||
build/
|
||||
dist/
|
||||
dist.zip
|
||||
|
||||
# Ignore waf lock file
|
||||
.lock-waf*
|
||||
|
||||
# Ignore installed node modules
|
||||
node_modules/
|
||||
@@ -0,0 +1,30 @@
|
||||
cmake_minimum_required (VERSION 3.2)
|
||||
project (test-project)
|
||||
|
||||
set(CMAKE_C_FLAGS "-std=c11 -mthumb -ffunction-sections -g -fno-diagnostics-show-caret -D_REENT_SMALL=1 -Wall -Wextra -Werror -Wpointer-arith -Wno-unused-parameter -Wno-missing-field-initializers -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=unused-parameter -Wno-error=unused-but-set-variable -Wno-packed-bitfield-compat -mcpu=cortex-m3 -Os -Werror=return-type")
|
||||
|
||||
file(GLOB_RECURSE src "src/*")
|
||||
file(GLOB_RECURSE build "build/basalt/*.c")
|
||||
|
||||
set(SOURCES
|
||||
${src}
|
||||
${build}
|
||||
)
|
||||
|
||||
set(INCLUDES
|
||||
~/Library/Application\ Support/Pebble\ SDK/SDKs/current/sdk-core/pebble/basalt/include
|
||||
./node_modules/pebble-events/dist/include
|
||||
./node_modules/@keegan-stoneware/simple-dict/dist/include
|
||||
./node_modules/pebble-clay/dist/include
|
||||
./build/include
|
||||
./build
|
||||
./include
|
||||
)
|
||||
|
||||
add_definitions(-DPEBBLE)
|
||||
add_definitions(-DPBL_COLOR)
|
||||
|
||||
include_directories(${INCLUDES})
|
||||
|
||||
add_executable(app ${SOURCES})
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "clay-test",
|
||||
"author": "MakeAwesomeHappen",
|
||||
"version": "1.0.0",
|
||||
"keywords": [
|
||||
"pebble-app"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "./scripts/build.sh"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"pebble-clay": "../"
|
||||
},
|
||||
"pebble": {
|
||||
"displayName": "clay-test",
|
||||
"uuid": "3fff53d2-1b59-48d7-8187-0c2f3674c32d",
|
||||
"sdkVersion": "3",
|
||||
"enableMultiJS": true,
|
||||
"targetPlatforms": [
|
||||
"aplite",
|
||||
"basalt",
|
||||
"chalk",
|
||||
"diorite"
|
||||
],
|
||||
"watchapp": {
|
||||
"watchface": false
|
||||
},
|
||||
"messageKeys": [],
|
||||
"resources": {
|
||||
"media": []
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
test_app_folder_name="clay-test"
|
||||
if [ "$(basename $(pwd))" != "$test_app_folder_name" ]; then
|
||||
echo "Must be executed from $test_app_folder_name folder"
|
||||
exit
|
||||
fi
|
||||
|
||||
pebble clean && cd .. && npm run pebble-build || { cd $test_app_folder_name && exit; } && cd $test_app_folder_name && pebble build
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <inttypes.h>
|
||||
#include <pebble.h>
|
||||
#include <pebble-clay/clay.h>
|
||||
|
||||
#define CLAY_INBOX_SIZE (64)
|
||||
|
||||
static Window *s_window;
|
||||
static int s_background_color;
|
||||
|
||||
static void draw_background(Layer *layer, GContext *ctx) {
|
||||
graphics_context_set_fill_color(ctx, GColorFromHEX(s_background_color));
|
||||
graphics_fill_rect(ctx, layer_get_bounds(layer), 0, GCornerNone);
|
||||
}
|
||||
|
||||
static void prv_update_layer(Layer *layer, GContext *ctx) {
|
||||
draw_background(layer, ctx);
|
||||
}
|
||||
|
||||
|
||||
static void prv_window_unload(Window *window) {
|
||||
window_destroy(window);
|
||||
}
|
||||
|
||||
static void prv_window_load(Window *window) {
|
||||
layer_set_update_proc(window_get_root_layer(s_window), prv_update_layer);
|
||||
}
|
||||
|
||||
static void prv_clay_updated_handler(void *context) {
|
||||
int value_int;
|
||||
if (clay_get_int("test_int", &value_int)) {
|
||||
s_background_color = value_int;
|
||||
}
|
||||
|
||||
layer_mark_dirty(window_get_root_layer(s_window));
|
||||
}
|
||||
|
||||
static void prv_init(void) {
|
||||
|
||||
const ClayCallbacks clay_callbacks = (ClayCallbacks) {
|
||||
.settings_updated = prv_clay_updated_handler,
|
||||
};
|
||||
clay_register_callbacks(&clay_callbacks, NULL);
|
||||
|
||||
clay_init(CLAY_INBOX_SIZE);
|
||||
|
||||
s_window = window_create();
|
||||
window_set_window_handlers(s_window, (WindowHandlers) {
|
||||
.load = prv_window_load,
|
||||
.unload = prv_window_unload,
|
||||
});
|
||||
|
||||
window_stack_push(s_window, true);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
prv_init();
|
||||
app_event_loop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//int s_background_color = 0xffffff;
|
||||
//#define TEXT_SIZE 20;
|
||||
//char s_text [TEXT_SIZE];
|
||||
//
|
||||
//void clay_update_handler(void *ctx) {
|
||||
// clay_get_int("background_color", &s_background_color);
|
||||
// clay_get_string("background_color", &s_text, TEXT_SIZE - 1);
|
||||
//}
|
||||
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
var Clay = require('pebble-clay');
|
||||
var clay = new Clay({
|
||||
config: [
|
||||
{
|
||||
label: 'test',
|
||||
type: 'color',
|
||||
messageKey: 'test_int'
|
||||
},
|
||||
{
|
||||
type: 'submit',
|
||||
defaultValue: 'submit'
|
||||
}
|
||||
],
|
||||
closedCallback: function(response) {
|
||||
console.log('closedcallback: arguments' + JSON.stringify(arguments));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#
|
||||
# This file is the default set of rules to compile a Pebble application.
|
||||
#
|
||||
# Feel free to customize this to your needs.
|
||||
#
|
||||
import os.path
|
||||
import shutil
|
||||
import waflib
|
||||
|
||||
top = '.'
|
||||
out = 'build'
|
||||
|
||||
|
||||
def options(ctx):
|
||||
ctx.load('pebble_sdk')
|
||||
|
||||
|
||||
def distclean(ctx):
|
||||
node_modules_dir = ctx.path.find_node('node_modules')
|
||||
if node_modules_dir:
|
||||
shutil.rmtree(node_modules_dir.abspath())
|
||||
waflib.Scripting.distclean(ctx)
|
||||
|
||||
|
||||
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_program(source=ctx.path.ant_glob('src/**/*.c'), target=app_elf)
|
||||
|
||||
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_worker(source=ctx.path.ant_glob('worker_src/**/*.c'), target=worker_elf)
|
||||
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/js/**/*.js', 'src/js/**/*.json']),
|
||||
js_entry_file='src/js/app.js')
|
||||
@@ -12,6 +12,13 @@ module.exports = [
|
||||
"type": "text",
|
||||
"defaultValue": "This is config 2"
|
||||
},
|
||||
{
|
||||
type: 'thing',
|
||||
defaultValue: {
|
||||
en_US: 'foo',
|
||||
fr_FR: 'bar'
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "section",
|
||||
"items": [
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ module.exports = [
|
||||
"messageKey": "email",
|
||||
"defaultValue": "",
|
||||
"label": "Input Field",
|
||||
"description": "This is a description for the input component. " +
|
||||
"description": "{{i18n.foo}} This is a description for the input component. " +
|
||||
"You can add <strong>html</strong> in here too.",
|
||||
"attributes": {
|
||||
"placeholder": "Placeholder set with attributes"
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <@keegan-stoneware/simple-app-message/simple-app-message.h>
|
||||
|
||||
typedef void (*ClayUpdatedCallback)(void *context);
|
||||
|
||||
typedef struct ClayCallbacks {
|
||||
ClayUpdatedCallback settings_updated;
|
||||
} ClayCallbacks;
|
||||
|
||||
void clay_init(uint32_t inbox_size);
|
||||
|
||||
void clay_remove(const char *key);
|
||||
|
||||
void clay_clear();
|
||||
|
||||
void clay_set_bool(const char *key, bool value);
|
||||
|
||||
void clay_set_data(const char *key, const void *data, size_t n);
|
||||
|
||||
void clay_set_int(const char *key, int value);
|
||||
|
||||
void clay_set_string(const char *key, const char *value);
|
||||
|
||||
bool clay_get_bool(const char *key, bool *value_out);
|
||||
|
||||
bool clay_get_data(const char *key, void *value_out, size_t n);
|
||||
|
||||
bool clay_get_int(const char *key, int *value_out);
|
||||
|
||||
bool clay_get_string(const char *key, char *value_out, size_t n);
|
||||
|
||||
bool clay_register_callbacks(const ClayCallbacks *callbacks, void *context);
|
||||
@@ -5,34 +5,30 @@ var toSource = require('tosource');
|
||||
var standardComponents = require('./src/scripts/components');
|
||||
var deepcopy = require('deepcopy/build/deepcopy.min');
|
||||
var version = require('./package.json').version;
|
||||
var messageKeys = require('message_keys');
|
||||
var simpleAppMessage = require('@keegan-stoneware/simple-app-message');
|
||||
var utils = require('./src/scripts/lib/utils');
|
||||
|
||||
/**
|
||||
* @param {Array} config - the Clay config
|
||||
* @param {function} [customFn] - Custom code to run from the config page. Will run
|
||||
* with the ClayConfig instance as context
|
||||
* @param {Object} [options] - Additional options to pass to Clay
|
||||
* @param {boolean} [options.autoHandleEvents=true] - If false, Clay will not
|
||||
* automatically handle the 'showConfiguration' and 'webviewclosed' events
|
||||
* @param {*} [options.userData={}] - Arbitrary data to pass to the config page. Will
|
||||
* be available as `clayConfig.meta.userData`
|
||||
* @param {Object} options - Clay options
|
||||
* @param {Array} [options.config] - The config
|
||||
* @param {function} [options.openCallback]
|
||||
* @param {function} [options.closedCallback]
|
||||
* @param {Object} [options.locales]
|
||||
* @param {function} [options.customFunction] - Custom code to run from the config
|
||||
* page. Will run with the ClayConfig instance as context
|
||||
* @constructor
|
||||
*/
|
||||
function Clay(config, customFn, options) {
|
||||
function Clay(options) {
|
||||
var self = this;
|
||||
|
||||
if (!Array.isArray(config)) {
|
||||
throw new Error('config must be an Array');
|
||||
if (!options) {
|
||||
utils.throw('You must define options');
|
||||
}
|
||||
|
||||
if (customFn && typeof customFn !== 'function') {
|
||||
throw new Error('customFn must be a function or "null"');
|
||||
}
|
||||
options = deepcopy(options);
|
||||
|
||||
options = options || {};
|
||||
|
||||
self.config = deepcopy(config);
|
||||
self.customFn = customFn || function() {};
|
||||
self.config = options.config;
|
||||
self.customFn = options.customFn || function() {};
|
||||
self.components = {};
|
||||
self.meta = {
|
||||
activeWatchInfo: null,
|
||||
@@ -57,8 +53,6 @@ function Clay(config, customFn, options) {
|
||||
}
|
||||
|
||||
// Let Clay handle all the magic
|
||||
if (options.autoHandleEvents !== false && typeof Pebble !== 'undefined') {
|
||||
|
||||
Pebble.addEventListener('showConfiguration', function() {
|
||||
_populateMeta();
|
||||
Pebble.openURL(self.generateUrl());
|
||||
@@ -68,20 +62,22 @@ function Clay(config, customFn, options) {
|
||||
|
||||
if (!e || !e.response) { return; }
|
||||
|
||||
// Send settings to Pebble watchapp
|
||||
Pebble.sendAppMessage(self.getSettings(e.response), function() {
|
||||
console.log('Sent config data to Pebble');
|
||||
}, function(error) {
|
||||
console.log('Failed to send config data!');
|
||||
console.log(JSON.stringify(error));
|
||||
});
|
||||
});
|
||||
} else if (typeof Pebble !== 'undefined') {
|
||||
Pebble.addEventListener('ready', function() {
|
||||
_populateMeta();
|
||||
});
|
||||
var settings = self.getSettings(e.response);
|
||||
|
||||
if (options.closedCallback) {
|
||||
options.closedCallback(settings);
|
||||
}
|
||||
|
||||
simpleAppMessage.send('CLAY', settings, function(response) {
|
||||
if (response.error) {
|
||||
utils.log('Failed to send config data!');
|
||||
utils.log(response.error);
|
||||
} else {
|
||||
utils.log('Sent config data to Pebble');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* If this function returns true then the callback will be executed
|
||||
* @callback _scanConfig_testFn
|
||||
@@ -195,20 +191,21 @@ Clay.prototype.getSettings = function(response, convert) {
|
||||
try {
|
||||
settings = JSON.parse(response);
|
||||
} catch (e) {
|
||||
throw new Error('The provided response was not valid JSON');
|
||||
utils.error('The provided response was not valid JSON');
|
||||
}
|
||||
|
||||
// @todo do something with the persist flag here
|
||||
// flatten the settings for localStorage
|
||||
var settingsStorage = {};
|
||||
Object.keys(settings).forEach(function(key) {
|
||||
if (typeof settings[key] === 'object' && settings[key]) {
|
||||
settingsStorage[key] = settings[key].value;
|
||||
} else {
|
||||
settingsStorage[key] = settings[key];
|
||||
}
|
||||
});
|
||||
|
||||
localStorage.setItem('clay-settings', JSON.stringify(settingsStorage));
|
||||
// var settingsStorage = {};
|
||||
// Object.keys(settings).forEach(function(key) {
|
||||
// if (typeof settings[key] === 'object' && settings[key]) {
|
||||
// settingsStorage[key] = settings[key].value;
|
||||
// } else {
|
||||
// settingsStorage[key] = settings[key];
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// localStorage.setItem('clay-settings', JSON.stringify(settingsStorage));
|
||||
|
||||
return convert === false ? settings : Clay.prepareSettingsForAppMessage(settings);
|
||||
};
|
||||
@@ -321,13 +318,15 @@ Clay.prepareSettingsForAppMessage = function(settings) {
|
||||
|
||||
var result = {};
|
||||
Object.keys(flatSettings).forEach(function(key) {
|
||||
var messageKey = messageKeys[key];
|
||||
var settingArr = Clay.prepareForAppMessage(flatSettings[key]);
|
||||
settingArr = Array.isArray(settingArr) ? settingArr : [settingArr];
|
||||
// var messageKey = messageKeys[key];
|
||||
// var settingArr = Clay.prepareForAppMessage(flatSettings[key]);
|
||||
// settingArr = Array.isArray(settingArr) ? settingArr : [settingArr];
|
||||
//
|
||||
// settingArr.forEach(function(setting, index) {
|
||||
// result[messageKey + index] = setting;
|
||||
// });
|
||||
|
||||
settingArr.forEach(function(setting, index) {
|
||||
result[messageKey + index] = setting;
|
||||
});
|
||||
result[key] = Clay.prepareForAppMessage(flatSettings[key]);
|
||||
});
|
||||
|
||||
// validate the settings
|
||||
|
||||
+3
-1
@@ -87,5 +87,7 @@
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"watchify": "^3.7.0"
|
||||
},
|
||||
"dependencies": {}
|
||||
"dependencies": {
|
||||
"@keegan-stoneware/simple-app-message": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
#include "clay.h"
|
||||
#include "hash.h"
|
||||
|
||||
#define SIMPLE_APP_MESSAGE_NAMESPACE ("CLAY")
|
||||
|
||||
static ClayCallbacks s_callbacks;
|
||||
static void *s_context;
|
||||
|
||||
static bool prv_store_settings(const char *key, SimpleDictDataType type, const void *data,
|
||||
size_t data_size, void *context) {
|
||||
|
||||
uint32_t persist_key = hash((uint8_t *)key, strlen(key));
|
||||
|
||||
switch (type) {
|
||||
case SimpleDictDataType_Raw:
|
||||
persist_write_data(persist_key, data, data_size);
|
||||
return true;
|
||||
case SimpleDictDataType_Bool: {
|
||||
const bool value = *((bool *)data);
|
||||
persist_write_bool(persist_key, value);
|
||||
return true;
|
||||
}
|
||||
case SimpleDictDataType_Int: {
|
||||
const int value = *((int *)data);
|
||||
APP_LOG(APP_LOG_LEVEL_INFO, "CLAY: writing %d - %d to storage", (int)persist_key, value);
|
||||
persist_write_int(persist_key, value);
|
||||
return true;
|
||||
}
|
||||
case SimpleDictDataType_String: {
|
||||
const char *value = data;
|
||||
persist_write_string(persist_key, value);
|
||||
return true;
|
||||
}
|
||||
case SimpleDictDataTypeCount:
|
||||
break;
|
||||
}
|
||||
APP_LOG(APP_LOG_LEVEL_ERROR, "Unexpected type %d", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void prv_simple_app_message_received_callback(const SimpleDict *message, void *context) {
|
||||
if (!message) {
|
||||
return;
|
||||
}
|
||||
|
||||
APP_LOG(APP_LOG_LEVEL_INFO, "CLAY: Received SimpleAppMessage");
|
||||
simple_dict_foreach(message, prv_store_settings, NULL);
|
||||
s_callbacks.settings_updated(context);
|
||||
}
|
||||
|
||||
bool clay_register_callbacks(const ClayCallbacks *callbacks, void *context) {
|
||||
s_callbacks = *callbacks;
|
||||
s_context = context;
|
||||
return true;
|
||||
}
|
||||
|
||||
void clay_init(uint32_t inbox_size) {
|
||||
const SimpleAppMessageCallbacks simple_app_message_callbacks = (SimpleAppMessageCallbacks) {
|
||||
.message_received = prv_simple_app_message_received_callback,
|
||||
};
|
||||
const bool register_success = simple_app_message_register_callbacks(SIMPLE_APP_MESSAGE_NAMESPACE,
|
||||
&simple_app_message_callbacks,
|
||||
s_context);
|
||||
if (!register_success) {
|
||||
APP_LOG(APP_LOG_LEVEL_ERROR, "Failed to register callbacks for namespace %s", SIMPLE_APP_MESSAGE_NAMESPACE);
|
||||
return;
|
||||
}
|
||||
const bool request_inbox_size_success = simple_app_message_request_inbox_size(inbox_size);
|
||||
if (!request_inbox_size_success) {
|
||||
APP_LOG(APP_LOG_LEVEL_ERROR, "Failed to request inbox size of %d", (int)inbox_size);
|
||||
return;
|
||||
}
|
||||
|
||||
simple_app_message_open();
|
||||
}
|
||||
|
||||
bool clay_get_int(const char *key, int *value_out) {
|
||||
uint32_t persist_key = hash((uint8_t *)key, strlen(key));
|
||||
|
||||
if (persist_exists(persist_key)) {
|
||||
int value = persist_read_int(persist_key);
|
||||
APP_LOG(APP_LOG_LEVEL_INFO, "CLAY: reading %d - %d from storage", (int)persist_key, value);
|
||||
memcpy(value_out, &value, sizeof(&value));
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "hash.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Based on DJB2 Hash
|
||||
uint32_t hash(const uint8_t *bytes, const uint32_t length) {
|
||||
uint32_t hash = 5381;
|
||||
|
||||
if (length == 0) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint8_t c;
|
||||
const uint8_t *last_byte = bytes + length;
|
||||
while (bytes != last_byte) {
|
||||
c = *bytes;
|
||||
hash = ((hash << 5) + hash) + c;
|
||||
bytes++;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t hash(const uint8_t *bytes, const uint32_t length);
|
||||
@@ -133,3 +133,11 @@ module.exports.includesCapability = function(activeWatchInfo, capabilities) {
|
||||
|
||||
return result.indexOf(false) === -1;
|
||||
};
|
||||
|
||||
module.exports.log = function(message) {
|
||||
console.log('Clay: ' + JSON.stringify(message));
|
||||
};
|
||||
|
||||
module.exports.throw = function(error) {
|
||||
throw new Error('Clay: '+ error)
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user