Add zap step mode (zaps get stronger as more awareness alarms are failed); remove nudge setting (nudge is always on now); fix nudge being missed if wakeup occurs while in setter; fix force-exiting an awareness alarm triggering a main alarm
This commit is contained in:
+4
-2
@@ -34,11 +34,13 @@
|
||||
"messageKeys": [
|
||||
"PKJS_READY",
|
||||
"PKJS_PAVLOK_ENABLE",
|
||||
"PKJS_PAVLOK_ZAP_MIN",
|
||||
"PKJS_PAVLOK_ZAP_STEP",
|
||||
"PKJS_PAVLOK_ZAP_MAX",
|
||||
"PKJS_PAVLOK_ZAP_INTERVAL",
|
||||
"PKJS_PAVLOK_ZAP",
|
||||
"PKJS_AWARENESS_TIME_GAP",
|
||||
"PKJS_AWARENESS_TIME_LIMIT",
|
||||
"PKJS_AWARENESS_NUDGE_ENABLE"
|
||||
"PKJS_AWARENESS_TIME_LIMIT"
|
||||
],
|
||||
"resources": {
|
||||
"media": [
|
||||
|
||||
+73
-46
@@ -62,7 +62,8 @@ static uint8_t s_solution_indices[3] = {8, 8, 8};
|
||||
static uint8_t s_selected_indices[3] = {9, 9, 9};
|
||||
static uint8_t s_awareness_countdown_int = 0;
|
||||
static char s_awareness_countdown_buf[4];
|
||||
static uint8_t s_zap_repeat_countdown = 0;
|
||||
static uint8_t s_awareness_zap_repeat_countdown = 0;
|
||||
static uint8_t s_awareness_zap_intensity = 0;
|
||||
static bool s_hide_countdown = true;
|
||||
static uint32_t s_vibe_segments[5];
|
||||
static VibePattern s_vibe_pattern;
|
||||
@@ -195,13 +196,22 @@ static void inbox_received_handler(DictionaryIterator *iter, void *context) {
|
||||
}
|
||||
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);
|
||||
apply_uint8_from_tuple(iter, MESSAGE_KEY_PKJS_AWARENESS_NUDGE_ENABLE, &settings.AwarenessNudgeEnabled);
|
||||
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() {
|
||||
static void send_zap(uint8_t intensity) {
|
||||
if (!settings.PavlokEnabled) {
|
||||
return;
|
||||
}
|
||||
@@ -211,7 +221,7 @@ static void send_zap() {
|
||||
if (result != APP_MSG_OK) {
|
||||
return;
|
||||
}
|
||||
dict_write_uint8(out, MESSAGE_KEY_PKJS_PAVLOK_ZAP, 1);
|
||||
dict_write_uint8(out, MESSAGE_KEY_PKJS_PAVLOK_ZAP, intensity);
|
||||
result = app_message_outbox_send();
|
||||
if (result != APP_MSG_OK) {
|
||||
return;
|
||||
@@ -225,16 +235,6 @@ static bool schedule_alarm(WakeupReason schedule_reason) {
|
||||
WakeupId status;
|
||||
|
||||
switch (schedule_reason) {
|
||||
case WAKE_RECOVERY_ALARM:
|
||||
target = time(NULL) + 15;
|
||||
// no need to cancel alarms, as RECOVERY_ALARM is short-lived and is expired by the time another is being scheduled
|
||||
status = wakeup_schedule_simple_robust(target, 15, schedule_reason);
|
||||
break;
|
||||
case WAKE_AWARENESS_ALARM:
|
||||
target = time(NULL) + settings.AwarenessTimeGapMinutes * SECONDS_PER_MINUTE;
|
||||
wakeup_cancel_all();
|
||||
status = wakeup_schedule_simple_robust(target, SECONDS_PER_MINUTE, schedule_reason);
|
||||
break;
|
||||
case WAKE_MAIN_ALARM: {
|
||||
time_t now = time(NULL);
|
||||
struct tm target_tm = *localtime(&now);
|
||||
@@ -247,7 +247,28 @@ static bool schedule_alarm(WakeupReason schedule_reason) {
|
||||
}
|
||||
wakeup_cancel_all();
|
||||
status = wakeup_schedule_simple_robust(target, SECONDS_PER_MINUTE, schedule_reason);
|
||||
if (settings.PavlokEnabled) {
|
||||
persist_write_int(STORAGE_KEY_PAVLOK_INTENSITY, settings.PavlokMin);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WAKE_AWARENESS_ALARM:
|
||||
target = time(NULL) + settings.AwarenessTimeGapMinutes * SECONDS_PER_MINUTE;
|
||||
wakeup_cancel_all();
|
||||
status = wakeup_schedule_simple_robust(target, SECONDS_PER_MINUTE, schedule_reason);
|
||||
if (settings.PavlokEnabled && (s_alarm_reason == WAKE_AWARENESS_ALARM || s_alarm_reason == WAKE_RECOVERY_AWARENESS_ALARM)) {
|
||||
uint8_t next_intensity = s_awareness_zap_intensity + settings.PavlokStep;
|
||||
if (next_intensity <= settings.PavlokMax && next_intensity <= 100) {
|
||||
// only boost next intensity if it is within the allowed bounds
|
||||
persist_write_int(STORAGE_KEY_PAVLOK_INTENSITY, s_awareness_zap_intensity + settings.PavlokStep);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WAKE_RECOVERY_MAIN_ALARM:
|
||||
case WAKE_RECOVERY_AWARENESS_ALARM:
|
||||
target = time(NULL) + 15;
|
||||
// no need to cancel alarms, as recovery alarms short-lived and is expired by the time another is being scheduled
|
||||
status = wakeup_schedule_simple_robust(target, 15, schedule_reason);
|
||||
}
|
||||
if (status < 0) {
|
||||
push_status_window(STATUS_SET_FAILURE);
|
||||
@@ -295,15 +316,15 @@ static void awareness_alarm_seconds_handler(struct tm *tick_time, TimeUnits unit
|
||||
snprintf(s_awareness_countdown_buf, sizeof(s_awareness_countdown_buf), "%03u", s_awareness_countdown_int);
|
||||
text_layer_set_text(s_countdown_txt_layer, s_awareness_countdown_buf);
|
||||
if (s_awareness_countdown_int == 0) {
|
||||
send_zap();
|
||||
s_zap_repeat_countdown = settings.PavlokIntervalSeconds;
|
||||
send_zap(s_awareness_zap_intensity);
|
||||
s_awareness_zap_repeat_countdown = settings.PavlokIntervalSeconds;
|
||||
}
|
||||
} else {
|
||||
if (s_zap_repeat_countdown > 0) {
|
||||
s_zap_repeat_countdown--;
|
||||
if (s_zap_repeat_countdown == 0) {
|
||||
send_zap();
|
||||
s_zap_repeat_countdown = settings.PavlokIntervalSeconds;
|
||||
if (s_awareness_zap_repeat_countdown > 0) {
|
||||
s_awareness_zap_repeat_countdown--;
|
||||
if (s_awareness_zap_repeat_countdown == 0) {
|
||||
send_zap(s_awareness_zap_intensity);
|
||||
s_awareness_zap_repeat_countdown = settings.PavlokIntervalSeconds;
|
||||
}
|
||||
}
|
||||
layer_set_hidden(text_layer_get_layer(s_countdown_txt_layer), s_hide_countdown);
|
||||
@@ -396,8 +417,9 @@ static void drop_menu_window_unload(Window *window) {
|
||||
}
|
||||
|
||||
static void live_wakeup_handler_for_alarm(WakeupId id, int32_t wakeup_reason) {
|
||||
if (wakeup_reason == WAKE_RECOVERY_ALARM) { // if recovery alarm, re-schedule it
|
||||
schedule_alarm(WAKE_RECOVERY_ALARM); // output is not captured, as it is not actionable
|
||||
if (wakeup_reason == WAKE_RECOVERY_MAIN_ALARM || wakeup_reason == WAKE_RECOVERY_AWARENESS_ALARM) {
|
||||
// if recovery alarm, re-schedule it
|
||||
schedule_alarm(wakeup_reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -623,13 +645,10 @@ static void alarm_window_load() {
|
||||
text_layer_set_background_color(s_countdown_txt_layer, GColorClear);
|
||||
text_layer_set_text_color(s_countdown_txt_layer, GColorWhite);
|
||||
text_layer_set_text_alignment(s_countdown_txt_layer, GTextAlignmentCenter);
|
||||
// this code forces recovery alarms to act as main alarms, even if the force quit was an awareness alarm;
|
||||
// this is a "bug" I'm willing to accept for the sake of simplicity - all it does is punish the user more
|
||||
// for force-quitting
|
||||
if (s_alarm_reason == WAKE_AWARENESS_ALARM) {
|
||||
if (s_alarm_reason == WAKE_AWARENESS_ALARM || s_alarm_reason == WAKE_RECOVERY_AWARENESS_ALARM) {
|
||||
text_layer_set_font(s_countdown_txt_layer, s_font_lecoish_small);
|
||||
s_awareness_countdown_int = settings.AwarenessTimeLimitSeconds;
|
||||
s_zap_repeat_countdown = 0;
|
||||
s_awareness_zap_repeat_countdown = 0;
|
||||
snprintf(s_awareness_countdown_buf, sizeof(s_awareness_countdown_buf), "%03u", s_awareness_countdown_int);
|
||||
text_layer_set_text(s_countdown_txt_layer, s_awareness_countdown_buf);
|
||||
} else {
|
||||
@@ -649,10 +668,11 @@ static void alarm_window_load() {
|
||||
.num_segments = ARRAY_LENGTH(s_vibe_segments),
|
||||
};
|
||||
|
||||
schedule_alarm(WAKE_RECOVERY_ALARM); // output is not captured, as it is not actionable
|
||||
if (s_alarm_reason == WAKE_AWARENESS_ALARM) {
|
||||
if (s_alarm_reason == WAKE_AWARENESS_ALARM || s_alarm_reason == WAKE_RECOVERY_AWARENESS_ALARM) {
|
||||
schedule_alarm(WAKE_RECOVERY_AWARENESS_ALARM);
|
||||
tick_timer_service_subscribe(SECOND_UNIT, awareness_alarm_seconds_handler);
|
||||
} else {
|
||||
schedule_alarm(WAKE_RECOVERY_MAIN_ALARM);
|
||||
tick_timer_service_subscribe(SECOND_UNIT, main_alarm_seconds_handler);
|
||||
}
|
||||
}
|
||||
@@ -758,6 +778,23 @@ static void alarm_click_config_provider(void *ctx) {
|
||||
}
|
||||
|
||||
static void push_alarm_window() {
|
||||
s_alarm_reason = persist_read_int(STORAGE_KEY_ALARM_REASON);
|
||||
|
||||
switch (s_alarm_reason) {
|
||||
case WAKE_RECOVERY_MAIN_ALARM:
|
||||
send_zap(settings.PavlokMax);
|
||||
break;
|
||||
case WAKE_RECOVERY_AWARENESS_ALARM:
|
||||
send_zap(settings.PavlokMax);
|
||||
[[fallthrough]];
|
||||
case WAKE_AWARENESS_ALARM:
|
||||
s_awareness_zap_intensity = persist_read_int(STORAGE_KEY_PAVLOK_INTENSITY);
|
||||
vibes_short_pulse();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
window_set_window_handlers(
|
||||
s_window,
|
||||
(WindowHandlers){.load = alarm_window_load, .unload = alarm_window_unload});
|
||||
@@ -867,7 +904,7 @@ static void setter_down_click_handler(void *recognizer, void *ctx) {
|
||||
static void setter_select_click_handler(void *recognizer, void *ctx) {
|
||||
if (s_highlight_pos == 2) {
|
||||
if (s_alarm_reason != WAKE_MAIN_ALARM) {
|
||||
send_zap();
|
||||
send_zap(settings.PavlokMax);
|
||||
vibes_double_pulse();
|
||||
return; // early return to avoid overwriting recovery/awareness alarm
|
||||
}
|
||||
@@ -910,7 +947,6 @@ static void setter_click_config_provider(void *ctx) {
|
||||
}
|
||||
|
||||
static void live_wakeup_handler_for_setter(WakeupId id, int32_t reason) {
|
||||
s_alarm_reason = persist_read_int(STORAGE_KEY_ALARM_REASON);
|
||||
s_highlight_pos = 0;
|
||||
window_stack_pop_all(false);
|
||||
push_alarm_window();
|
||||
@@ -981,6 +1017,8 @@ static void setter_window_unload() {
|
||||
}
|
||||
|
||||
static void push_setter_window() {
|
||||
s_alarm_reason = persist_read_int(STORAGE_KEY_ALARM_REASON);
|
||||
|
||||
window_set_window_handlers(
|
||||
s_window,
|
||||
(WindowHandlers){.load = setter_window_load, .unload = setter_window_unload});
|
||||
@@ -1007,26 +1045,15 @@ static void init() {
|
||||
settings.TutorialEnabled = true;
|
||||
settings.PavlokEnabled = false;
|
||||
settings.PavlokIntervalSeconds = 10;
|
||||
settings.PavlokMin = 30;
|
||||
settings.PavlokStep = 10;
|
||||
settings.PavlokMax = 60;
|
||||
settings.AwarenessTimeGapMinutes = 9;
|
||||
settings.AwarenessTimeLimitSeconds = 30;
|
||||
settings.AwarenessNudgeEnabled = true;
|
||||
}
|
||||
|
||||
s_alarm_reason = persist_read_int(STORAGE_KEY_ALARM_REASON);
|
||||
switch (launch_reason()) {
|
||||
case APP_LAUNCH_WAKEUP:
|
||||
switch (s_alarm_reason) {
|
||||
case WAKE_RECOVERY_ALARM:
|
||||
send_zap();
|
||||
break;
|
||||
case WAKE_AWARENESS_ALARM:
|
||||
if (settings.AwarenessNudgeEnabled) {
|
||||
vibes_short_pulse();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
push_alarm_window();
|
||||
break;
|
||||
default:
|
||||
|
||||
+2
-1
@@ -5,7 +5,8 @@ typedef enum
|
||||
{
|
||||
WAKE_MAIN_ALARM = 0,
|
||||
WAKE_AWARENESS_ALARM = 1,
|
||||
WAKE_RECOVERY_ALARM = 2
|
||||
WAKE_RECOVERY_MAIN_ALARM = 2,
|
||||
WAKE_RECOVERY_AWARENESS_ALARM = 3
|
||||
} WakeupReason;
|
||||
|
||||
typedef struct TheTime {
|
||||
|
||||
+4
-1
@@ -8,14 +8,17 @@
|
||||
|
||||
#define STORAGE_KEY_ALARM_HOUR 0
|
||||
#define STORAGE_KEY_ALARM_MINUTE 1
|
||||
#define STORAGE_KEY_PAVLOK_INTENSITY 2
|
||||
|
||||
typedef struct AppSettings {
|
||||
bool TutorialEnabled;
|
||||
bool PavlokEnabled;
|
||||
uint8_t PavlokMin;
|
||||
uint8_t PavlokStep;
|
||||
uint8_t PavlokMax;
|
||||
uint8_t PavlokIntervalSeconds;
|
||||
uint8_t AwarenessTimeGapMinutes;
|
||||
uint8_t AwarenessTimeLimitSeconds;
|
||||
uint8_t AwarenessNudgeEnabled;
|
||||
} __attribute__((__packed__)) AppSettings;
|
||||
|
||||
_Static_assert(sizeof(AppSettings) <= 256, "AppSettings exceeds Pebble 256-byte persist limit!");
|
||||
|
||||
+42
-21
@@ -16,23 +16,54 @@ module.exports = [
|
||||
"type": "toggle",
|
||||
"messageKey": "PKJS_PAVLOK_ENABLE",
|
||||
"defaultValue": false,
|
||||
"label": "Enabled"
|
||||
"label": "Enabled",
|
||||
"description": "Toggle integration w/Pavlok shockers."
|
||||
},
|
||||
{
|
||||
"id": "pavlok_api_key",
|
||||
"type": "input",
|
||||
"messageKey": "PKJS_PAVLOK_API_KEY",
|
||||
"label": "API Key"
|
||||
"label": "API Key",
|
||||
"description": 'API bearer token, starting with "ey".'
|
||||
},
|
||||
{
|
||||
"id": "pavlok_zap_intensity",
|
||||
"id": "pavlok_test_beep",
|
||||
"type": "button",
|
||||
"messageKey": "PKJS_PAVLOK_TEST_BEEP",
|
||||
"defaultValue": "Test API Key w/Beep"
|
||||
},
|
||||
{
|
||||
"id": "pavlok_zap_min",
|
||||
"type": "slider",
|
||||
"messageKey": "PKJS_PAVLOK_ZAP_INTENSITY",
|
||||
"messageKey": "PKJS_PAVLOK_ZAP_MIN",
|
||||
"defaultValue": 30,
|
||||
"min": 5,
|
||||
"max": 100,
|
||||
"step": 5,
|
||||
"label": "Zap Intensity"
|
||||
"label": "Zap Intensity (Base)",
|
||||
"description": "% intensity of base zap."
|
||||
},
|
||||
{
|
||||
"id": "pavlok_zap_step",
|
||||
"type": "slider",
|
||||
"messageKey": "PKJS_PAVLOK_ZAP_STEP",
|
||||
"defaultValue": 10,
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"step": 5,
|
||||
"label": "Zap Step",
|
||||
"description": "% to increase base zap intensity by after each failed awareness alarm; set to 0 to disable."
|
||||
},
|
||||
{
|
||||
"id": "pavlok_zap_max",
|
||||
"type": "slider",
|
||||
"messageKey": "PKJS_PAVLOK_ZAP_MAX",
|
||||
"defaultValue": 60,
|
||||
"min": 10,
|
||||
"max": 100,
|
||||
"step": 5,
|
||||
"label": "Zap Intensity (Max)",
|
||||
"description": "% intensity of maximum zap; only takes effect if greater than base and step is enabled. Also used for force exit/alarm overwrite penalties."
|
||||
},
|
||||
{
|
||||
"id": "pavlok_zap_interval",
|
||||
@@ -42,13 +73,8 @@ module.exports = [
|
||||
"min": 1,
|
||||
"max": 60,
|
||||
"step": 1,
|
||||
"label": "Zap Repeat Interval"
|
||||
},
|
||||
{
|
||||
"id": "pavlok_test_button",
|
||||
"type": "button",
|
||||
"messageKey": "PKJS_PAVLOK_TEST_BUTTON",
|
||||
"defaultValue": "Test Beep"
|
||||
"label": "Zap Repeat Interval",
|
||||
"description": "Seconds between zaps after awareness alarm counter expires."
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -67,7 +93,8 @@ module.exports = [
|
||||
"defaultValue": 9,
|
||||
"min": 1,
|
||||
"max": 30,
|
||||
"label": "Gap From Main Alarm (Minutes)"
|
||||
"label": "Gap (Minutes)",
|
||||
"description": "Time gap between main alarm and subsequent awareness alarms."
|
||||
},
|
||||
{
|
||||
"id": "awareness_time_limit",
|
||||
@@ -76,14 +103,8 @@ module.exports = [
|
||||
"defaultValue": 30,
|
||||
"min": 3,
|
||||
"max": 120,
|
||||
"label": "Time Limit (Seconds)"
|
||||
},
|
||||
{
|
||||
"id": "awareness_nudge_enable",
|
||||
"type": "toggle",
|
||||
"messageKey": "PKJS_AWARENESS_NUDGE_ENABLE",
|
||||
"defaultValue": true,
|
||||
"label": "Awareness Nudge"
|
||||
"label": "Time Limit (Seconds)",
|
||||
"description": "Time limit the awareness alarm must be solved within to disarm Trigalarm."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -7,14 +7,18 @@ module.exports = function (minified) {
|
||||
function togglePavlokIntegration() {
|
||||
if (this.get()) {
|
||||
clayConfig.getItemById('pavlok_api_key').show();
|
||||
clayConfig.getItemById('pavlok_zap_intensity').show();
|
||||
clayConfig.getItemById('pavlok_test_beep').show();
|
||||
clayConfig.getItemById('pavlok_zap_min').show();
|
||||
clayConfig.getItemById('pavlok_zap_step').show();
|
||||
clayConfig.getItemById('pavlok_zap_max').show();
|
||||
clayConfig.getItemById('pavlok_zap_interval').show();
|
||||
clayConfig.getItemById('pavlok_test_button').show();
|
||||
} else {
|
||||
clayConfig.getItemById('pavlok_api_key').hide();
|
||||
clayConfig.getItemById('pavlok_zap_intensity').hide();
|
||||
clayConfig.getItemById('pavlok_test_beep').hide();
|
||||
clayConfig.getItemById('pavlok_zap_min').hide();
|
||||
clayConfig.getItemById('pavlok_zap_step').hide();
|
||||
clayConfig.getItemById('pavlok_zap_max').hide();
|
||||
clayConfig.getItemById('pavlok_zap_interval').hide();
|
||||
clayConfig.getItemById('pavlok_test_button').hide();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +44,6 @@ module.exports = function (minified) {
|
||||
togglePavlokIntegration.call(pavlokIntegrationToggle);
|
||||
pavlokIntegrationToggle.on('change', togglePavlokIntegration);
|
||||
|
||||
clayConfig.getItemById('pavlok_test_button').on('click', sendTestBeep);
|
||||
clayConfig.getItemById('pavlok_test_beep').on('click', sendTestBeep);
|
||||
});
|
||||
};
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ Pebble.addEventListener("ready", function () {
|
||||
Pebble.addEventListener("appmessage", function (dict) {
|
||||
if (dict.payload["PKJS_PAVLOK_ZAP"]) {
|
||||
const cfg = JSON.parse(localStorage.getItem('clay-settings'));
|
||||
callAPI(cfg.PKJS_PAVLOK_API_KEY, cfg.PKJS_PAVLOK_ZAP_INTENSITY);
|
||||
callAPI(cfg.PKJS_PAVLOK_API_KEY, parseInt(dict.payload["PKJS_PAVLOK_ZAP"]));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user