dreader-application/examples/demo_accelerometer_page_flip.py
Duncan Tourolle 70c0b4a1f2
All checks were successful
Python CI / test (3.12) (push) Successful in 7m1s
Python CI / test (3.13) (push) Successful in 7m10s
HW integratation
2025-11-11 11:57:39 +01:00

213 lines
6.8 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Demo: Accelerometer-based Page Flipping
This example demonstrates how to use the accelerometer for hands-free
page turning by tilting the device forward or backward.
Features:
- Tilt device forward to advance to next page
- Tilt device backward to go to previous page
- Touch gestures still work normally
- Configurable tilt threshold and debounce time
Prerequisites:
1. Run calibration first: python examples/calibrate_accelerometer.py
2. This creates accelerometer_config.json with calibration data
Usage:
python examples/demo_accelerometer_page_flip.py <epub_file>
"""
import asyncio
import sys
from pathlib import Path
# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))
from dreader.hal_hardware import HardwareDisplayHAL
from dreader.application import EbookReader
from dreader.gesture import GestureType
class AccelerometerPageFlipDemo:
"""Demo application with accelerometer-based page flipping"""
def __init__(self, epub_path: str):
self.epub_path = epub_path
# Create HAL with accelerometer enabled
print("Initializing hardware HAL...")
self.hal = HardwareDisplayHAL(
width=1872,
height=1404,
enable_orientation=True,
enable_rtc=False,
enable_power_monitor=False,
virtual_display=False # Set to True for testing without hardware
)
# Create reader
print("Creating ebook reader...")
self.reader = EbookReader(
page_size=(self.hal.width, self.hal.height),
margin=60
)
self.running = False
async def run(self):
"""Run the demo application"""
print("\n" + "="*60)
print("Accelerometer Page Flip Demo")
print("="*60)
# Initialize HAL
await self.hal.initialize()
# Load accelerometer calibration
print("\nLoading accelerometer calibration...")
calibrated = self.hal.load_accelerometer_calibration("accelerometer_config.json")
if not calibrated:
print("\nWARNING: Accelerometer not calibrated!")
print("Please run: python examples/calibrate_accelerometer.py")
print("\nProceeding with touch gestures only...\n")
else:
print("Accelerometer calibration loaded successfully!")
print(f" Up vector: {self.hal.accel_up_vector}")
print(f" Tilt threshold: {self.hal.accel_tilt_threshold:.2f} rad")
print(f" Debounce time: {self.hal.accel_debounce_time:.2f}s")
# Load EPUB
print(f"\nLoading EPUB: {self.epub_path}")
success = self.reader.load_epub(self.epub_path)
if not success:
print(f"ERROR: Failed to load {self.epub_path}")
await self.hal.cleanup()
return
print(f"Loaded: {self.reader.book_title}")
print(f"Author: {self.reader.book_author}")
# Display first page
print("\nDisplaying first page...")
img = self.reader.get_current_page()
await self.hal.show_image(img)
# Instructions
print("\n" + "="*60)
print("Controls:")
print(" - Tilt FORWARD to go to next page")
print(" - Tilt BACKWARD to go to previous page")
print(" - Swipe LEFT for next page (touch)")
print(" - Swipe RIGHT for previous page (touch)")
print(" - Long press to exit")
print("="*60 + "\n")
# Main event loop
self.running = True
try:
await self.event_loop()
finally:
await self.hal.cleanup()
print("\nDemo finished!")
async def event_loop(self):
"""Main event loop - poll for touch and accelerometer events"""
accel_poll_interval = 0.05 # Check accelerometer every 50ms
while self.running:
# Check for touch events
touch_event = await self.hal.get_touch_event()
if touch_event:
await self.handle_event(touch_event)
# Check for accelerometer tilt events (if calibrated)
if hasattr(self.hal, 'accel_up_vector'):
tilt_event = await self.hal.get_tilt_gesture()
if tilt_event:
await self.handle_event(tilt_event)
# Small delay to avoid busy-waiting
await asyncio.sleep(accel_poll_interval)
async def handle_event(self, event):
"""Handle a gesture event (touch or accelerometer)"""
gesture = event.gesture
print(f"Gesture: {gesture.value}")
# Navigation gestures
if gesture in [GestureType.SWIPE_LEFT, GestureType.TILT_FORWARD]:
await self.next_page()
elif gesture in [GestureType.SWIPE_RIGHT, GestureType.TILT_BACKWARD]:
await self.previous_page()
# Exit on long press
elif gesture == GestureType.LONG_PRESS:
print("\nLong press detected - exiting...")
self.running = False
# Word tap
elif gesture == GestureType.TAP:
# You could implement word selection here
print(f" Tap at ({event.x}, {event.y})")
async def next_page(self):
"""Go to next page"""
img = self.reader.next_page()
if img:
progress = self.reader.get_reading_progress()
chapter = self.reader.get_current_chapter_info()
print(f" -> Next page ({progress['percent']:.1f}% - {chapter['title']})")
await self.hal.show_image(img)
else:
print(" -> At end of book")
async def previous_page(self):
"""Go to previous page"""
img = self.reader.previous_page()
if img:
progress = self.reader.get_reading_progress()
chapter = self.reader.get_current_chapter_info()
print(f" -> Previous page ({progress['percent']:.1f}% - {chapter['title']})")
await self.hal.show_image(img)
else:
print(" -> At start of book")
async def main():
"""Main entry point"""
if len(sys.argv) < 2:
print("Usage: python demo_accelerometer_page_flip.py <epub_file>")
print("\nExample:")
print(" python demo_accelerometer_page_flip.py ~/Books/mybook.epub")
sys.exit(1)
epub_path = sys.argv[1]
# Check if file exists
if not Path(epub_path).exists():
print(f"ERROR: File not found: {epub_path}")
sys.exit(1)
# Run demo
demo = AccelerometerPageFlipDemo(epub_path)
await demo.run()
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
print("\nDemo interrupted by user")
sys.exit(0)
except Exception as e:
print(f"\nError: {e}")
import traceback
traceback.print_exc()
sys.exit(1)