Hydration watch face

This watch face monitors daily hydration by tracking and logging water intake.

In tracking mode: Display current water intake and percentage
- Alarm button: +100ml (or configured glass size)
- Light button: -100ml (or configured glass size)
- Alarm long press: Display deviation from estimate
- Light long press: Switch to settings mode
- Alarm really long press: Switch to log mode

In settings mode: Configure glass size, daily goal, wake time, sleep time, alert interval
- Light button: Switch to next setting
- Alarm button: Advance current setting
- Alarm long press: Reset to default value
- Mode button: Switch to tracking mode

In log mode: Display log entries of water intake, date and deviation from goal
- Alarm button: Switch to next log entry
- Light button: Cycle through intake, date and deviation
- Mode button: Switch to tracking mode

Background tasks:
- Automatic reset at wake time
- Alert if intake below estimate at sleep time
- Alert at interval if intake below estimate, waking the watch if asleep
This commit is contained in:
Konrad Rieck
2026-07-27 21:47:04 +02:00
parent b2589bebcd
commit 705e4be13a
4 changed files with 847 additions and 0 deletions
+126
View File
@@ -0,0 +1,126 @@
/*
* MIT License
*
* Copyright (c) 2025 Konrad Rieck
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* This watch face monitors daily hydration by tracking and logging water intake.
*
* In tracking mode: Display current water intake and percentage
* - Alarm button: +100ml (or configured glass size)
* - Light button: -100ml (or configured glass size)
* - Alarm long press: Display deviation from estimate
* - Light long press: Switch to settings mode
* - Alarm really long press: Switch to log mode
*
* In settings mode: Configure glass size, daily goal, wake time, sleep time, alert interval
* - Light button: Switch to next setting
* - Alarm button: Advance current setting
* - Alarm long press: Reset to default value
* - Mode button: Switch to tracking mode
* In log mode: Display log entries of water intake, date and deviation from goal
* - Alarm button: Switch to next log entry
* - Light button: Cycle through intake, date and deviation
* - Mode button: Switch to tracking mode
*
* Background tasks:
* - Automatic reset at wake time
* - Alert if intake below estimate at sleep time
* - Alert at interval if intake below estimate
*
*/
#include "movement.h"
/* Number of log entries */
#define HYDRATION_LOG_ENTRIES 30
/* Number of log types */
#define HYDRATION_LOG_TYPES 3
typedef enum {
PAGE_HYDRATION_TRACKING,
PAGE_HYDRATION_SETTINGS,
PAGE_HYDRATION_LOG
} hydration_page_t;
typedef enum {
HYDRATION_SETTING_WATER_GLASS,
HYDRATION_SETTING_WATER_GOAL,
HYDRATION_SETTING_WAKE_TIME,
HYDRATION_SETTING_SLEEP_TIME,
HYDRATION_SETTING_ALERT_INTERVAL,
} hydration_setting_t;
typedef enum {
HYDRATION_LOG_INTAKE,
HYDRATION_LOG_DATE,
HYDRATION_LOG_DEVIATION,
} hydration_log_type_t;
typedef struct {
void (*display)(void *, uint8_t);
void (*advance)(void *);
} hydration_settings_t;
typedef struct {
uint8_t water_intake; /* Logged intake (intake / 100) */
uint16_t date; /* Logged date (ts / 86400) */
} hydration_log_t;
typedef struct {
uint16_t water_intake; /* Current water intake in ml */
uint16_t water_glass; /* Glass size in ml (default 100ml) */
uint16_t water_goal; /* Target daily water intake (default 1600ml) */
uint8_t wake_hour; /* Hour for wake time (default 7) */
uint8_t sleep_hour; /* Hour for sleep time (default 22) */
uint8_t alert_interval; /* Alert interval in hours (default 2) */
uint8_t face_index; /* Face index */
uint8_t display_deviation; /* Display deviation from estimate */
bool alert_enabled; /* Alert enabled */
hydration_page_t page; /* Current page */
/* Log */
hydration_log_t log[HYDRATION_LOG_ENTRIES]; /* Log entries */
hydration_log_type_t log_type; /* Log type */
uint8_t log_index; /* Log index */
uint8_t log_head; /* Log head */
/* Settings */
hydration_setting_t settings_page; /* Current settings page */
hydration_settings_t *settings; /* Settings configuration */
} hydration_state_t;
void hydration_face_setup(uint8_t watch_face_index, void **context_ptr);
void hydration_face_activate(void *context);
bool hydration_face_loop(movement_event_t event, void *context);
void hydration_face_resign(void *context);
movement_watch_face_advisory_t hydration_face_advise(void *context);
#define hydration_face ((const watch_face_t){ \
hydration_face_setup, \
hydration_face_activate, \
hydration_face_loop, \
hydration_face_resign, \
hydration_face_advise, \
})