HFOS is a fully-featured open-source firmware for the M5Stack Dial. It brings watch, alarm, timer, and settings apps in a lightweight, smooth, and responsive UI with OLED graphics, rotary encoder input, and tactile feedback.
NEW: Optional productivity tracking dashboard via HarborScale integration – track your focus sessions in real-time with beautiful Grafana visualizations! 📊
- ⌚ Smart Watch – Highly optimized, low-power clock with 12/24h toggle
- ⏱️ Timer – Set, start, pause, and ring timers with gauge progress
- ⏰ Alarm – Polling-based alarm with snooze and dynamic ringing alerts
- ⚙️ Settings – Wi-Fi NTP sync, 12/24h mode toggle, brightness control
- 📊 Productivity Dashboard (Optional) – Track timer sessions with HarborScale + Grafana
- 🎨 Industrial Palette UI – Modern, minimal, and vibrant design
- 📈 Smart Redraw & Efficient Background Tasks – Minimal CPU usage
- 🛠️ Extensible App System – Easy to add new apps via the
Appinterface - 🎵 Audio Alerts – Tone support via M5Dial speaker
- 🌙 AOD Mode – Screensaver with low-brightness display
- 💡 Rotary & Touch Input Support – Smooth, debounced interaction
- ⌨️ USB HID Control – Send Ctrl+1 (Start) and Ctrl+2 (Stop) to your computer
- Clone the repository:
git clone https://github.com/harborscale/HFOS-m5stack-dial.git
cd HFOS-m5stack-dial-
Open in Arduino IDE or PlatformIO.
-
Install required libraries:
M5DialM5GFXHTTPClient(for optional HarborScale integration)
-
Configure your Wi-Fi and timezone in
main.cpp:
const char* WIFI_SSID = "YOUR_SSID";
const char* WIFI_PASS = "YOUR_PASSWORD";
#define TIME_ZONE_OFFSET_HRS +3- (Optional) Enable productivity tracking:
const char* HARBOR_API_KEY = "your_harborscale_api_key";
const char* HARBOR_API_ENDPOINT = "https://harborscale.com/api/v2/ingest/your_harbor_id";
const char* HARBOR_SHIP_ID = "Productivity_Dial";- Build and upload to your M5Stack Dial.
HFOS can automatically track your timer sessions and visualize them in a beautiful dashboard using HarborScale and Grafana.
- When timer starts: Sends status
1to HarborScale - Every 60 seconds: Sends heartbeat status
1(shows continuous activity) - When timer stops/finishes: Sends status
0to HarborScale
- Create a free HarborScale account at harborscale.com
- Create a General Harbor and get your Harbor ID
- Generate an API Key from your dashboard
- Configure HFOS with your credentials (see Quick Start step 5)
- View a Grafana dashboard to visualize:
- Total productive time per day
- Session duration trends
- Focus time heatmaps
- Weekly/monthly productivity stats
Want to skip the setup? Just leave the HARBOR_* variables empty and HFOS works perfectly without tracking! 🎯
-
M5Stack Dial
- M5Core ESP32
- Built-in OLED 240×240
- Rotary encoder + button
- Speaker for alarms
- USB-C (HID keyboard support)
-
Menu Navigation
- Rotate encoder → Switch apps
- Tap screen → Select / confirm
- Rotart Press → Back / exit app
-
Watch App
- Smart redraw to save power
- Shows date, time, and AM/PM if 12h mode
-
Timer App
- Rotary = adjust time (coarse/fine)
- Tap = start/pause/stop
- Ringing = dynamic gauge + tone
- Sends USB keyboard commands (Ctrl+1/Ctrl+2)
- (Optional) Tracks sessions to HarborScale
-
Alarm App
- Rotary = toggle ON/OFF or adjust hour/min
- Tap = snooze when ringing
- Background polling every 500ms for accurate alarm trigger
-
Settings App
- Tap top half = NTP sync over Wi-Fi
- Tap bottom half = toggle 12/24h format
- Feedback tones for success/failure
| Parameter | Description | Default |
|---|---|---|
TIME_ZONE_OFFSET_HRS |
Offset from UTC | +3 |
BRIGHT_ACTIVE |
Active display brightness (0–255) | 200 |
BRIGHT_AOD |
Screensaver/AOD brightness (0–255) | 10 |
SCREENSAVER_TIMEOUT |
Inactivity before AOD (ms) | 20000 |
C_ACCENT |
Main accent color | 0xFB20 |
HARBOR_API_KEY |
HarborScale API key (optional) | "" |
HARBOR_API_ENDPOINT |
HarborScale ingest endpoint (optional) | "https://harborscale.com/api/v2/ingest/..." |
HARBOR_SHIP_ID |
Device identifier for tracking (optional) | "Productivity_Dial" |
HFOS uses an App interface for modularity.
Add your own app:
class MyApp : public App {
void setup() override {}
void loop() override {}
void draw() override {}
void onRotary(int delta) override {}
void onTouch(int x, int y) override {}
String getName() override { return "MY APP"; }
};Then register in setup():
apps.push_back(new MyApp());- Wi-Fi NTP sync may take a few seconds; firmware handles retry automatically.
- Timer & Alarm override menu for priority alerts.
- Rotary encoder sensitivity can be adjusted by changing
abs(rawDelta) >= 4threshold. - Productivity tracking is completely optional – device works perfectly without HarborScale credentials
- HarborScale integration uses minimal WiFi connections (only when timer state changes)
This project is licensed under Apache License 2.0.
- ✅ Free for personal and commercial use
- ✅ Modify and redistribute allowed
⚠️ Must include attribution
We welcome issues, pull requests, and feature ideas!
- Open a GitHub issue for bugs or enhancements
- Fork the repo and submit PRs
- Join discussions and improve HFOS together
- Inspired by the TimeChi Kickstarter project & salimbenbouz
- Powered by HarborScale for telemetry tracking
- Built for the amazing M5Stack Dial community