A sophisticated Node.js orchestration system that transforms Linux-based e-paper devices (such as jailbroken Kindles) into intelligent, multi-functional information displays. The system seamlessly integrates web-based clock interfaces, real-time environmental sensor visualization, news aggregation, and emergency alert broadcasting through a centrally managed architecture.
- Overview
- Key Features
- System Architecture
- Prerequisites
- Installation
- Configuration
- Usage
- Display Modes
- Data Sources
- API Reference
- Scheduling System
- Troubleshooting
- Project Structure
- Contributing
- License
This project provides a complete solution for repurposing e-paper devices as smart displays with automatic content rotation, scheduled sleep/wake cycles, and resilient error handling. The system is designed for 24/7 operation with minimal maintenance requirements, making it ideal for:
- Home automation displays: Environmental monitoring and time display
- Information dashboards: News headlines and alerts
- Data visualization: Historical trend analysis for IoT sensors
- Emergency notification systems: Critical alert broadcasting
The orchestrator manages multiple display modes, handles SSH-based remote control, and ensures the device stays operational through automatic reconnection and recovery mechanisms.
The system dynamically switches between four distinct rendering modes:
| Mode | Description | Technology | Update Frequency |
|---|---|---|---|
| Browser Mode | Primary clock interface with modern web design | Puppeteer (headless Chromium) | Default state |
| Screen Text Mode | High-contrast news headlines and emergency alerts | Native fbink text rendering |
Every 15 minutes |
| Stats Mode | Real-time environmental metrics visualization | Puppeteer-generated PNG cards | Every 15 minutes |
| Plots Mode | Historical trend graphs for sensor data | Canvas-based chart generation | Every 15 minutes |
- Fetches curated news headlines from a Redis-backed data store
- External aggregator integration (configurable data source)
- Automatic content rotation with alerts
- Fallback handling for unavailable content
- Automated scheduling: Active hours from 7:00 AM to 11:00 PM (IST)
- Graceful sleep/wake cycles: Automatic display shutdown outside active hours
- Energy efficient: Minimizes e-paper refresh operations to preserve display longevity
- Quarter-hour alignment: Content rotation synchronized to :00, :15, :30, :45 minutes
- SSH-based control: Secure remote command execution
- Automatic reconnection: Handles network interruptions gracefully
- Device reboot detection: Recovers from Kindle restarts automatically
- Hardware control: Backlight, rotation, and display clearing capabilities
- Real-time sensor data visualization (Temperature, Humidity, Pressure)
- Historical trend tracking with graphical plots
- Configurable data source endpoints
- Automated image generation and transfer
graph TB
subgraph "Control System (Host Machine)"
Main[main.js<br/>Orchestrator]
Browser[browser.js<br/>Browser Mode Controller]
Screen[screen.js<br/>Text Mode Controller]
FetchAvg[fetch_avg/<br/>Sensor Module]
Server[server/server.js<br/>REST API Server]
Connect[connect.js<br/>SSH Manager]
end
subgraph "Data Layer"
Redis[(Redis<br/>Database)]
SensorAPI[Sensor Data<br/>API Endpoint]
end
subgraph "E-Paper Device (Kindle)"
Fbink[fbink<br/>Display Driver]
Display[E-Paper<br/>Display]
Browser_Process[Chromium<br/>Browser Process]
end
Main -->|Schedules & Manages| Browser
Main -->|Schedules & Manages| Screen
Main -->|Triggers Generation| FetchAvg
Main -->|Uses| Connect
Browser -->|SSH Commands| Connect
Screen -->|SSH Commands| Connect
FetchAvg -->|Uploads Images| Connect
Connect -->|SSH Connection| Fbink
Connect -->|SSH Connection| Browser_Process
Fbink -->|Renders| Display
Browser_Process -->|Renders| Display
Server -->|Reads| Redis
Screen -->|HTTP Request| Server
FetchAvg -->|HTTP Request| SensorAPI
Redis -.->|External Aggregator| Redis
style Main fill:#4CAF50,stroke:#333,stroke-width:3px,color:#fff
style Display fill:#FF9800,stroke:#333,stroke-width:2px
style Redis fill:#DC382D,stroke:#333,stroke-width:2px,color:#fff
sequenceDiagram
participant M as main.js
participant B as browser.js
participant S as screen.js
participant F as fetch_avg
participant K as Kindle Device
participant R as Redis
participant API as External APIs
Note over M: 7:00 AM - System Wakes
M->>K: SSH Connect
M->>B: Start Browser Mode
B->>K: Launch Chromium with Clock URL
K-->>K: Display Clock (Default State)
Note over M: Every 15 Minutes (on quarter hour)
M->>M: Check Active Hours (7AM-11PM)
M->>S: Activate Screen Mode
alt Screen Type: News
S->>R: Fetch News Headlines
R-->>S: Return News Array
S->>K: Render via fbink
else Screen Type: Alert
S->>R: Fetch Alert Data
R-->>S: Return Alert Object
F->>API: Request Sensor Data
API-->>F: Return Metrics
F->>F: Generate PNG Cards
F->>K: Upload & Display Images
else Screen Type: Alert-Plot
F->>API: Request Historical Data
API-->>F: Return Time Series
F->>F: Generate Trend Graphs
F->>K: Upload & Display Plots
end
S->>B: Return to Browser Mode
B->>K: Restore Clock Display
Note over M: 11:00 PM - System Sleeps
M->>B: Shutdown Browser
B->>K: Kill Chromium Process
M->>K: Clear Display
K-->>K: Enter Low-Power State
stateDiagram-v2
[*] --> BrowserMode: 7 AM Startup
BrowserMode --> NewsMode: At 00, 15, 30, 45 mins<br/>(Quarter Hour 1)
NewsMode --> BrowserMode: Display Complete
BrowserMode --> AlertStatsMode: Quarter Hour 2
AlertStatsMode --> BrowserMode: Display Complete
BrowserMode --> NewsMode2: Quarter Hour 3
NewsMode2 --> BrowserMode: Display Complete
BrowserMode --> AlertPlotsMode: Quarter Hour 4
AlertPlotsMode --> BrowserMode: Display Complete
BrowserMode --> [*]: 11 PM Shutdown
note right of BrowserMode
Default state showing
web-based clock interface
end note
note right of AlertStatsMode
Fetches sensor data
Generates stat cards
Shows current metrics
end note
note right of AlertPlotsMode
Generates trend graphs
Shows historical data
end note
| Component | Specification |
|---|---|
| E-Paper Device | Linux-based device with SSH access (e.g., Kindle Paperwhite, Kindle Touch) |
| Jailbreak | Device must be jailbroken to enable SSH and custom software |
| Display Driver | fbink binary installed at /mnt/us/usbnet/bin/fbink |
| Custom Fonts | TrueType fonts (e.g., InstrumentSerif-Regular.ttf) in /mnt/us/fonts/ |
| Network | WiFi connectivity for SSH access |
| Software | Version | Purpose |
|---|---|---|
| Node.js | v14.x or higher | Runtime environment |
| npm | 6.x or higher | Package management |
| Redis Server | Latest stable | Data persistence and caching |
| SSH Key Pair | N/A | Password-less authentication to device |
- Clock Web Application: A web page serving the clock interface (referenced as
BROWSER_URLin configuration) - Sensor Data API: HTTP endpoint providing environmental metrics (optional for sensor features)
- News Aggregator: External service populating Redis with news items (optional for news features)
git clone https://github.com/aneeshpatne/Clock.git
cd Clocknpm installThis installs the following core packages:
puppeteer- Headless browser automationssh2- SSH client for remote device controlioredis/redis- Redis client librariesexpress- REST API server frameworkcanvas- Server-side image generation
-
Jailbreak the Kindle: Follow community guides for your specific Kindle model (e.g., MobileRead Wiki)
-
Install USBNetwork: Enable SSH access over WiFi
# On Kindle, create USBNET configuration ;debugOn ~usbNetwork
-
Install fbink: Transfer the
fbinkbinary to the devicescp fbink root@<kindle-ip>:/mnt/us/usbnet/bin/fbink ssh root@<kindle-ip> "chmod +x /mnt/us/usbnet/bin/fbink"
-
Install Custom Fonts: Copy TrueType fonts to the device
ssh root@<kindle-ip> "mkdir -p /mnt/us/fonts" scp InstrumentSerif-Regular.ttf root@<kindle-ip>:/mnt/us/fonts/
# Generate SSH key pair (if not already done)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/kindle_key
# Copy public key to Kindle
ssh-copy-id -i ~/.ssh/kindle_key.pub root@<kindle-ip>
# Test connection
ssh -i ~/.ssh/kindle_key root@<kindle-ip> "echo Connected successfully"sudo apt update
sudo apt install redis-server
sudo systemctl enable redis-server
sudo systemctl start redis-serverredis-cli ping
# Expected output: PONGredis-cli
> SET alert '{"message":"System operational","severity":"info"}'
> SET news_items '[{"title":"Welcome to E-Paper Display","source":"System"}]'
> SET changes '{"temperature":{"trend":"stable"}}'
> EXITEdit the connection parameters for your e-paper device:
// connect.js
export const config = {
host: '192.168.1.100', // Kindle IP address
port: 22, // SSH port (default 22)
username: 'root', // SSH username
privateKey: '/home/user/.ssh/kindle_key', // Path to private key
readyTimeout: 30000, // Connection timeout (ms)
keepaliveInterval: 10000 // Keepalive interval (ms)
};Customize operational parameters:
// main.js
// Active hours (IST timezone)
const ACTIVE_START_HOUR = 7; // Wake up at 7:00 AM
const ACTIVE_END_HOUR = 23; // Sleep at 11:00 PM
// Browser mode settings
const BROWSER_URL = "http://192.168.1.36:8000"; // Clock web app URL
const BROWSER_LAUNCH_DELAY_MS = 100 * 1000; // Wait 100s after launch
// Reconnection settings
const RECONNECT_INITIAL_DELAY_MS = 5 * 1000; // Wait 5s before reconnect
const RECONNECT_POLL_INTERVAL_MS = 5 * 1000; // Poll every 5s
// Feature flags
const NEWS_ENABLED = true; // Enable news rotationConfigure sensor data endpoints:
// fetch_avg/main.js
const SENSOR_URL = "http://192.168.1.50:5000/api/sensors"; // Sensor API endpoint
const UPDATE_INTERVAL = 900000; // Update every 15 minutesThe system expects the following Redis keys:
| Key | Type | Schema | Example |
|---|---|---|---|
alert |
String (JSON) | {"message": "string", "severity": "info|warning|error"} |
{"message":"High temperature alert","severity":"warning"} |
news_items |
String (JSON Array) | [{"title": "string", "source": "string", "url": "string"}] |
[{"title":"Breaking News","source":"BBC","url":"..."}] |
changes |
String (JSON) | {"temperature": {"trend": "string", "value": number}} |
{"temperature":{"trend":"rising","value":0.5}} |
The system consists of two main processes that must run concurrently:
The REST API server provides news and alert data:
cd server
node server.jsOutput:
Server listening on port 3000
Connected to Redis
The main application manages the e-paper device:
node main.jsOutput:
[main] Connecting to Kindle at 192.168.1.100
[startup] Delegating to browser mode startup
[browser] Launching Chromium at http://192.168.1.36:8000
[schedule] Screen loop aligning in 847s
[main] System operational - browser mode active
For 24/7 operation, use a process manager like systemd or pm2:
# Install PM2 globally
npm install -g pm2
# Start server
pm2 start server/server.js --name epaper-server
# Start main application
pm2 start main.js --name epaper-main
# Enable auto-start on boot
pm2 startup
pm2 save
# Monitor processes
pm2 monitCreate /etc/systemd/system/epaper.service:
[Unit]
Description=E-Paper Display System
After=network.target redis-server.service
[Service]
Type=simple
User=youruser
WorkingDirectory=/path/to/Clock
ExecStart=/usr/bin/node main.js
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.targetEnable and start:
sudo systemctl enable epaper.service
sudo systemctl start epaper.service
sudo systemctl status epaper.service# If running in terminal, press Ctrl+C in both windows
# If using PM2
pm2 stop epaper-main epaper-server
# If using systemd
sudo systemctl stop epaper.serviceDescription: Displays a web-based clock interface using headless Chromium.
Technology: Puppeteer launches a full browser instance on the Kindle device, navigating to the configured BROWSER_URL.
Characteristics:
- High-quality rendering of HTML/CSS/JavaScript
- Supports animations and dynamic content
- Most CPU-intensive mode
- Default state (returns to this mode after other displays)
Configuration:
const BROWSER_URL = "http://192.168.1.36:8000"; // Your clock web appDescription: Native text rendering for news headlines and emergency alerts.
Technology: Uses fbink CLI tool for direct framebuffer manipulation.
Activation: Every 15 minutes (rotation cycle 1 and 3)
Display Format:
━━━━━━━━━━━━━━━━━━━━━━
📰 HEADLINES
━━━━━━━━━━━━━━━━━━━━━━
• Breaking: Major announcement
Source: BBC News
• Technology update released
Source: TechCrunch
━━━━━━━━━━━━━━━━━━━━━━
⚠️ ALERTS
━━━━━━━━━━━━━━━━━━━━━━
High temperature warning
Severity: WARNING
Characteristics:
- Ultra-low power consumption
- High contrast and readability
- Instant rendering (no page load)
- Ideal for critical information
Description: Visualizes current environmental metrics with generated cards.
Technology: Puppeteer renders HTML cards to PNG, then transfers to device.
Activation: Every 15 minutes (rotation cycle 2)
Metrics Displayed:
- Temperature (°C / °F)
- Humidity (%)
- Pressure (hPa)
Card Layout:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ TEMPERATURE │ │ HUMIDITY │ │ PRESSURE │
│ │ │ │ │ │
│ 22.5°C │ │ 65% │ │ 1013 hPa │
│ │ │ │ │ │
│ ▲ +0.5°C │ │ ▼ -2% │ │ ─ Stable │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Description: Historical trend graphs for environmental data.
Technology: Canvas-based chart generation with time-series data.
Activation: Every 15 minutes (rotation cycle 4)
Graph Types:
- Line charts for temperature trends (24-hour window)
- Bar charts for humidity changes
- Area charts for pressure variations
Features:
- Automatic scaling and axis generation
- Trend indicators (rising/falling/stable)
- Configurable time ranges
Connection: Localhost (default Redis port 6379)
Libraries: ioredis (primary), redis (fallback)
Data Persistence: Managed by external aggregators and APIs
graph LR
A[External News<br/>Aggregator] -->|Writes JSON| B[(Redis<br/>news_items)]
B -->|REST API| C[server.js<br/>Express Server]
C -->|HTTP Request| D[screen.js<br/>Text Mode]
D -->|Renders via fbink| E[E-Paper<br/>Display]
style A fill:#2196F3,stroke:#333,stroke-width:2px,color:#fff
style E fill:#FF9800,stroke:#333,stroke-width:2px
graph LR
A[IoT Sensors] -->|HTTP API| B[Sensor Data<br/>API Server]
B -->|fetch_avg/main.js<br/>HTTP Request| C[Node.js<br/>Canvas Renderer]
C -->|Generates| D[PNG Images]
D -->|SSH/SCP| E[Kindle Device]
E -->|fbink Display| F[E-Paper<br/>Display]
style A fill:#4CAF50,stroke:#333,stroke-width:2px,color:#fff
style F fill:#FF9800,stroke:#333,stroke-width:2px
Base URL: http://localhost:3000
Retrieve current emergency alerts.
Response:
{
"message": "High temperature detected",
"severity": "warning",
"timestamp": "2025-01-12T14:30:00Z"
}Status Codes:
200 OK- Alert retrieved successfully404 Not Found- No alert configured500 Internal Server Error- Redis connection error
Retrieve aggregated news headlines.
Response:
[
{
"title": "Breaking: Major technology announcement",
"source": "TechCrunch",
"url": "https://example.com/article",
"publishedAt": "2025-01-12T10:00:00Z"
},
{
"title": "Market update: Stocks reach new high",
"source": "Bloomberg",
"url": "https://example.com/market",
"publishedAt": "2025-01-12T09:30:00Z"
}
]Status Codes:
200 OK- News retrieved successfully404 Not Found- No news items available500 Internal Server Error- Redis connection error
Retrieve current sensor metrics (if external sensor API is configured).
Response:
{
"temperature": {
"value": 22.5,
"unit": "celsius",
"trend": "rising"
},
"humidity": {
"value": 65,
"unit": "percent",
"trend": "falling"
},
"pressure": {
"value": 1013,
"unit": "hPa",
"trend": "stable"
}
}All scheduling uses IST (Indian Standard Time, UTC+5:30). This is handled by the time.js module:
// time.js
export function getIstDate() {
const now = new Date();
return new Date(now.toLocaleString("en-US", { timeZone: "Asia/Kolkata" }));
}gantt
title E-Paper Display Daily Schedule
dateFormat HH:mm
axisFormat %H:%M
section Device State
Sleep Mode :done, sleep, 00:00, 7h
Active Mode :active, active, 07:00, 16h
Sleep Mode :done, sleep2, 23:00, 1h
section Display Modes
Browser Mode Startup :milestone, startup, 07:00, 0h
Content Rotation :crit, rotation, 07:00, 16h
Browser Shutdown :milestone, shutdown, 23:00, 0h
Rotation Interval: Every 15 minutes (on quarter hours: :00, :15, :30, :45)
Rotation Pattern (4-cycle loop):
| Cycle | Time Pattern | Display Mode | Duration |
|---|---|---|---|
| 1 | :00 minutes | News Headlines | ~60 seconds |
| 2 | :15 minutes | Alert + Stats Cards | ~90 seconds |
| 3 | :30 minutes | News Headlines | ~60 seconds |
| 4 | :45 minutes | Alert + Trend Plots | ~90 seconds |
Note: Between rotations, the system always returns to Browser Mode (clock display).
// Quarter-hour alignment algorithm
function msUntilNextQuarter() {
const now = getIstDate();
const minutes = now.getMinutes();
const seconds = now.getSeconds();
const ms = now.getMilliseconds();
const nextQuarter = Math.ceil((minutes * 60 + seconds + ms / 1000) / (15 * 60)) * (15 * 60);
// ... calculate milliseconds until next quarter hour
}Symptoms:
[main] Connection timeout after 30000ms
Error: ETIMEDOUT
Solutions:
- Verify Kindle IP address:
ip addr showon Kindle terminal - Check SSH service:
ps aux | grep sshdon Kindle - Test manual connection:
ssh -i ~/.ssh/kindle_key root@<kindle-ip> - Verify network connectivity:
ping <kindle-ip> - Check firewall rules on host machine
Symptoms:
[browser] Failed to launch Chromium
Error: Browser closed unexpectedly
Solutions:
- Verify Chromium is installed on Kindle
- Check available disk space:
df -hon Kindle - Increase
BROWSER_LAUNCH_DELAY_MSinmain.js - Verify
BROWSER_URLis accessible from Kindle - Check Kindle system logs:
/var/log/messages
Symptoms:
[server] Redis connection failed: ECONNREFUSED
Error: connect ECONNREFUSED 127.0.0.1:6379
Solutions:
- Check Redis is running:
sudo systemctl status redis-server - Start Redis:
sudo systemctl start redis-server - Verify Redis port:
redis-cli ping - Check Redis configuration:
/etc/redis/redis.conf - Ensure Redis binds to localhost:
bind 127.0.0.1in config
Symptoms:
[screen] Command failed: fbink: not found
Solutions:
- Verify fbink installation:
ssh root@<kindle-ip> "which fbink" - Expected location:
/mnt/us/usbnet/bin/fbink - Re-install fbink if missing
- Check executable permissions:
chmod +x /mnt/us/usbnet/bin/fbink - Update
helper.jsif fbink is in a different location
Symptoms:
- Clock shows but never rotates to other modes
- Stuck in one display mode
Solutions:
- Check system time alignment:
dateon host and Kindle - Verify active hours: Ensure current time is between 7 AM - 11 PM IST
- Check scheduling logs: Look for
[schedule]and[screen-schedule]entries - Restart the application:
pm2 restart epaper-main - Verify quarter-hour alignment: Should trigger at :00, :15, :30, :45
Symptoms:
[fetch_avg] Failed to fetch sensor data
Error: ENOTFOUND
Solutions:
- Verify
SENSOR_URLinfetch_avg/main.js - Test endpoint manually:
curl http://<sensor-url>/api/sensors - Check network connectivity to sensor API
- Review sensor API response format
- Ensure API returns JSON in expected schema
Modify main.js to add more detailed logs:
// Add at top of main.js
process.env.DEBUG = 'puppeteer:*,ssh2:*';Watch connection status in real-time:
watch -n 1 'ssh root@<kindle-ip> "ps aux | grep -E \"chromium|fbink\""'Inspect current Redis contents:
redis-cli
> KEYS *
> GET alert
> GET news_items
> GET changesSSH into Kindle and monitor system logs:
ssh root@<kindle-ip>
tail -f /var/log/messagesTest browser mode independently:
node -e "import('./browser.js').then(b => b.start())"Test screen mode independently:
node -e "import('./screen.js').then(s => s.createLegacyClockScreen({}).start('news'))"e-paper/
├── main.js # Core orchestrator and lifecycle manager
├── browser.js # Browser mode controller (Puppeteer)
├── screen.js # Screen text mode controller (fbink)
├── connect.js # SSH connection manager
├── helper.js # Hardware control utilities (backlight, display)
├── time.js # Timezone and scheduling utilities
├── executeWithRetry.js # Resilient command execution with retry logic
│
├── fetch_avg/ # Sensor data module
│ ├── main.js # PNG generation for stats and plots
│ └── traverse.js # Image upload and display on Kindle
│
├── server/ # REST API server
│ └── server.js # Express server for news and alerts
│
├── package.json # Node.js dependencies
└── README.md # This file
| Module | Responsibilities | Key Functions |
|---|---|---|
| main.js | Application lifecycle, scheduling, mode switching | main(), startup(), shutdown(), scheduleDailyAt(), scheduleScreenLoop() |
| browser.js | Browser mode management, Puppeteer orchestration | start(), shutdown(), launchBrowser() |
| screen.js | Text mode rendering, news/alert display | createLegacyClockScreen(), displayNews(), displayAlert() |
| connect.js | SSH connection pooling, remote command execution | connect(), executeCommand(), close() |
| helper.js | Hardware control, display utilities | clearScreen(), setBacklight(), blackDisplay(), rotateScreen() |
| time.js | Timezone conversion, schedule calculations | getIstDate(), isWithinHours() |
| executeWithRetry.js | Resilient command execution, error handling | executeWithRetry(), KindleRebootedError |
| fetch_avg/main.js | Sensor data fetching, image generation | generatePNGs(), fetchSensorData(), createStatCards() |
| fetch_avg/traverse.js | File transfer, image display | uploadAndDisplay(), scpTransfer() |
| server/server.js | REST API for news and alerts | Express routes: /api/alerts, /api/news |
Contributions are welcome! Please follow these guidelines:
- Use the GitHub issue tracker
- Provide detailed reproduction steps
- Include system information (Node.js version, Kindle model, OS)
- Attach relevant log snippets
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature-name - Make your changes with clear commit messages
- Test thoroughly on your e-paper device
- Submit a pull request with a detailed description
- Use ES6+ module syntax (
import/export) - Follow existing code formatting conventions
- Add comments for complex logic
- Update documentation for new features
Before submitting, verify:
- SSH connection works reliably
- All display modes render correctly
- Scheduled rotations trigger on time
- Error handling and recovery mechanisms function
- No memory leaks during 24-hour operation
- Redis data operations succeed
- Browser mode launches and shuts down cleanly
This project is licensed under the ISC License.
Copyright (c) 2025 Aneesh Patne
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- FBInk: E-paper display manipulation tool (NiLuJe/FBInk)
- MobileRead Community: Kindle hacking resources and support
- Puppeteer Team: Headless browser automation framework
- Redis Labs: High-performance data store
For questions, issues, or feature requests:
- GitHub Issues: https://github.com/aneeshpatne/Clock/issues
- Documentation: This README and inline code comments
- Community: MobileRead Kindle Hacking forums
Built with ❤️ for the e-paper hacking community