diff --git a/README.md b/README.md index 62ea4dd..61a130c 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Perhaps the most unique, Trigalarm features optional [Pavlok](https://pavlok.com ## Tips & Tricks - When you successfully disarm the alarm, you are prompted with the options to either exit and keep the same alarm time for tomorrow, or to select a new time. If choosing the latter, whatever time you select will assume you mean tomorrow. This avoids situations where you wake up at 6 on a Friday, set an alarm intended for 9 on Saturday, and end up with your wrist buzzing in three hours! +- If you are stuck waiting for an awareness alarm or there is a bug that schedules an alarm incorrectly, there is a "Reset Alarm" button in the phone-side settings that will set your alarm to 00:00. ## Some Neat Stuff - The vibration pattern is randomized. It derives the length of the three pulses from the angles in the generated triangle. Neat! diff --git a/package.json b/package.json index d4edc50..87673ef 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ }, "messageKeys": [ "PKJS_READY", + "PKJS_ALARM_RESET", "PKJS_PAVLOK_ENABLE", "PKJS_PAVLOK_ZAP_MIN", "PKJS_PAVLOK_ZAP_STEP", diff --git a/src/c/main.c b/src/c/main.c index ac9f4b3..dd6c9de 100644 --- a/src/c/main.c +++ b/src/c/main.c @@ -182,54 +182,6 @@ static void push_status_window(StatusWindowPurpose purpose) { window_stack_push(s_status_window, true); } -////////////////////// PKJS ////////////////////// - -static void apply_uint8_from_tuple(DictionaryIterator *iter, uint32_t key, void *dest) { - Tuple *t = dict_find(iter, key); - if (!t) - return; - *(uint8_t *)dest = t->value->uint8; -} - -static void inbox_received_handler(DictionaryIterator *iter, void *context) { - Tuple *ready_tuple = dict_find(iter, MESSAGE_KEY_PKJS_READY); - if (ready_tuple) { - return; - } - apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ENABLE, &settings.PavlokEnabled); - apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ZAP_INTERVAL, &settings.PavlokIntervalSeconds); - apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ZAP_MIN, &settings.PavlokMin); - apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ZAP_STEP, &settings.PavlokStep); - apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ZAP_MAX, &settings.PavlokMax); - apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_AWARENESS_TIME_GAP, &settings.AwarenessTimeGapMinutes); - apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_AWARENESS_TIME_LIMIT, &settings.AwarenessTimeLimitSeconds); - if (settings.PavlokStep == 0) { - // match min and max values if disabling step mode, as the max is used for force exit/overwrite punishments - settings.PavlokMax = settings.PavlokMin; - } else if (settings.PavlokMax <= settings.PavlokMin) { - // disable step mode if max is not higher than min - settings.PavlokStep = 0; - } - persist_write_data(STORAGE_KEY_SETTINGS, &settings, sizeof(settings)); -} - -static void send_zap(uint8_t intensity) { - if (!settings.PavlokEnabled) { - return; - } - - DictionaryIterator *out; - AppMessageResult result = app_message_outbox_begin(&out); - if (result != APP_MSG_OK) { - return; - } - dict_write_uint8(out, MESSAGE_KEY_PKJS_PAVLOK_ZAP, intensity); - result = app_message_outbox_send(); - if (result != APP_MSG_OK) { - return; - } -} - ////////////////////// MISC ////////////////////// static time_t compute_alarm_time(uint8_t hour, uint8_t minute) { @@ -317,6 +269,64 @@ static void add_bar_layers_to_window(Layer *window_layer, bool small_top) { layer_add_child(window_layer, s_bottom_bar_layer); } +////////////////////// PKJS ////////////////////// + +static void apply_uint8_from_tuple(DictionaryIterator *iter, uint32_t key, void *dest) { + Tuple *t = dict_find(iter, key); + if (!t) + return; + *(uint8_t *)dest = t->value->uint8; +} + +static void inbox_received_handler(DictionaryIterator *iter, void *context) { + Tuple *ready_tuple = dict_find(iter, MESSAGE_KEY_PKJS_READY); + if (ready_tuple) { + return; + } + + // handle alarm reset requests + if (dict_find(iter, MESSAGE_KEY_PKJS_ALARM_RESET)) { + the_time.HourWIP = 0; + the_time.MinuteWIP = 0; + s_alarm_reason = WAKE_MAIN_ALARM; + schedule_alarm(WAKE_MAIN_ALARM); + return; + } + + apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ENABLE, &settings.PavlokEnabled); + apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ZAP_INTERVAL, &settings.PavlokIntervalSeconds); + apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ZAP_MIN, &settings.PavlokMin); + apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ZAP_STEP, &settings.PavlokStep); + apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_PAVLOK_ZAP_MAX, &settings.PavlokMax); + apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_AWARENESS_TIME_GAP, &settings.AwarenessTimeGapMinutes); + apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_AWARENESS_TIME_LIMIT, &settings.AwarenessTimeLimitSeconds); + if (settings.PavlokStep == 0) { + // match min and max values if disabling step mode, as the max is used for force exit/overwrite punishments + settings.PavlokMax = settings.PavlokMin; + } else if (settings.PavlokMax <= settings.PavlokMin) { + // disable step mode if max is not higher than min + settings.PavlokStep = 0; + } + persist_write_data(STORAGE_KEY_SETTINGS, &settings, sizeof(settings)); +} + +static void send_zap(uint8_t intensity) { + if (!settings.PavlokEnabled) { + return; + } + + DictionaryIterator *out; + AppMessageResult result = app_message_outbox_begin(&out); + if (result != APP_MSG_OK) { + return; + } + dict_write_uint8(out, MESSAGE_KEY_PKJS_PAVLOK_ZAP, intensity); + result = app_message_outbox_send(); + if (result != APP_MSG_OK) { + return; + } +} + ////////////////////// ALARM ////////////////////// static void main_alarm_seconds_handler(struct tm *tick_time, TimeUnits units_changed) { @@ -1047,7 +1057,7 @@ static void init() { // initialize pkjs app_message_register_inbox_received(inbox_received_handler); - app_message_open(64, 64); // TODO tighten sizes + app_message_open(128, 128); // TODO tighten sizes // load settings from persist (or set defaults if not present) if (persist_exists(STORAGE_KEY_SETTINGS)) { diff --git a/src/pkjs/config.js b/src/pkjs/config.js index e85a5ab..12397dc 100644 --- a/src/pkjs/config.js +++ b/src/pkjs/config.js @@ -29,7 +29,6 @@ module.exports = [ { "id": "pavlok_test_beep", "type": "button", - "messageKey": "PKJS_PAVLOK_TEST_BEEP", "defaultValue": "Test API Key w/Beep" }, { @@ -108,6 +107,11 @@ module.exports = [ } ] }, + { + "id": "alarm_reset", + "type": "button", + "defaultValue": "Reset Alarm" + }, { "type": "submit", "defaultValue": "Save Settings" diff --git a/src/pkjs/customClay.js b/src/pkjs/customClay.js index 4b2fce0..89a67b0 100644 --- a/src/pkjs/customClay.js +++ b/src/pkjs/customClay.js @@ -39,11 +39,17 @@ module.exports = function (minified) { xhr.send(data); } + function sendResetSignal() { + window.location = 'pebblejs://close#' + + encodeURIComponent(JSON.stringify({ resetAlarm: 1 })); + } + clayConfig.on(clayConfig.EVENTS.AFTER_BUILD, function () { var pavlokIntegrationToggle = clayConfig.getItemById('pavlok_enable'); togglePavlokIntegration.call(pavlokIntegrationToggle); pavlokIntegrationToggle.on('change', togglePavlokIntegration); clayConfig.getItemById('pavlok_test_beep').on('click', sendTestBeep); + clayConfig.getItemById('alarm_reset').on('click', sendResetSignal); }); }; diff --git a/src/pkjs/index.js b/src/pkjs/index.js index 74d108c..f986933 100644 --- a/src/pkjs/index.js +++ b/src/pkjs/index.js @@ -2,7 +2,37 @@ var Clay = require('@rebble/clay'); var clayConfig = require('./config'); var customClay = require('./customClay'); -new Clay(clayConfig, customClay); +var clay = new Clay(clayConfig, customClay, { autoHandleEvents: false }); + +Pebble.addEventListener('showConfiguration', function () { + Pebble.openURL(clay.generateUrl()); +}); + +// custom listener so messages can be sent from customClay.js +Pebble.addEventListener('webviewclosed', function(e) { + if (e && !e.response) { + return; + } + + var data; + try { + data = JSON.parse(e.response.match(/^\{/) ? e.response : decodeURIComponent(e.response)); + } catch (err) { + return; + } + if (data.resetAlarm) { + Pebble.sendAppMessage({ PKJS_ALARM_RESET: 1 }); + return; + } + + var dict = clay.getSettings(e.response); + Pebble.sendAppMessage(dict, function(e) { + console.log('Sent config data to Pebble'); + }, function(e) { + console.log('Failed to send config data!'); + console.log(JSON.stringify(e)); + }); +}); Pebble.addEventListener("ready", function () { Pebble.sendAppMessage({ PKJS_READY: 1 });