dreader-hal/examples/rtc_demo.py
2025-11-10 18:06:11 +01:00

241 lines
7.0 KiB
Python
Executable File

#!/usr/bin/env python3
"""
RTC (Real-Time Clock) Demo.
Demonstrates PCF8523 RTC functionality:
- Read current date/time
- Set RTC time
- Sync with system time
- Set and monitor alarms
- Display continuous time updates
This example requires actual PCF8523 RTC hardware connected via I2C.
"""
import asyncio
import sys
import os
import time
# Add src to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../src'))
from dreader_hal import EReaderDisplayHAL
def format_time(t: time.struct_time) -> str:
"""Format struct_time as readable string."""
return time.strftime("%Y-%m-%d %H:%M:%S %A", t)
async def display_current_time(hal: EReaderDisplayHAL):
"""Display current RTC time continuously."""
print("\nDisplaying current time (Ctrl+C to stop)...\n")
try:
while True:
current = await hal.get_datetime()
if current:
print(f"\rCurrent time: {format_time(current)}", end="", flush=True)
else:
print("\rRTC not available", end="", flush=True)
await asyncio.sleep(1.0)
except KeyboardInterrupt:
print("\n")
async def set_time_demo(hal: EReaderDisplayHAL):
"""Demonstrate setting RTC time."""
print("\n=== Setting RTC Time ===")
# Show current time
current = await hal.get_datetime()
if current:
print(f"Current RTC time: {format_time(current)}")
# Set to system time
print("\nSetting RTC to current system time...")
system_time = time.localtime()
await hal.set_datetime(system_time)
print(f"System time: {format_time(system_time)}")
# Verify
await asyncio.sleep(0.5)
new_time = await hal.get_datetime()
if new_time:
print(f"New RTC time: {format_time(new_time)}")
print("✓ Time updated successfully!")
async def alarm_demo(hal: EReaderDisplayHAL):
"""Demonstrate RTC alarm functionality."""
print("\n=== RTC Alarm Demo ===")
# Get current time
current = await hal.get_datetime()
if not current:
print("Error: RTC not available")
return
print(f"Current time: {format_time(current)}")
# Set alarm for 2 minutes from now
alarm_minute = (current.tm_min + 2) % 60
alarm_hour = current.tm_hour
if alarm_minute < current.tm_min:
alarm_hour = (alarm_hour + 1) % 24
print(f"\nSetting alarm for {alarm_hour:02d}:{alarm_minute:02d}...")
await hal.set_alarm(hour=alarm_hour, minute=alarm_minute)
print("✓ Alarm set!")
print("\nNote: Alarm functionality requires checking alarm status")
print("via the low-level RTC driver (hal.rtc.check_alarm())")
async def interactive_menu(hal: EReaderDisplayHAL):
"""Interactive menu for RTC operations."""
while True:
print("\n" + "="*50)
print("RTC Demo Menu")
print("="*50)
print("1. Display current time")
print("2. Set time to system time")
print("3. Set custom time")
print("4. Set alarm")
print("5. Display time continuously")
print("6. Exit")
print("="*50)
choice = input("\nEnter choice (1-6): ").strip()
if choice == "1":
current = await hal.get_datetime()
if current:
print(f"\nCurrent RTC time: {format_time(current)}")
else:
print("\nRTC not available")
elif choice == "2":
await set_time_demo(hal)
elif choice == "3":
print("\nEnter date/time (or press Enter to cancel):")
year = input("Year (YYYY): ").strip()
if not year:
continue
try:
year = int(year)
month = int(input("Month (1-12): "))
day = int(input("Day (1-31): "))
hour = int(input("Hour (0-23): "))
minute = int(input("Minute (0-59): "))
second = int(input("Second (0-59): "))
# Create struct_time (weekday and yearday are calculated)
custom_time = time.struct_time((
year, month, day, hour, minute, second, 0, 0, -1
))
print(f"\nSetting RTC to: {format_time(custom_time)}")
await hal.set_datetime(custom_time)
# Verify
await asyncio.sleep(0.5)
new_time = await hal.get_datetime()
if new_time:
print(f"Verified: {format_time(new_time)}")
print("✓ Time updated successfully!")
except (ValueError, OverflowError) as e:
print(f"\nError: Invalid date/time - {e}")
elif choice == "4":
await alarm_demo(hal)
elif choice == "5":
await display_current_time(hal)
elif choice == "6":
print("\nExiting...")
break
else:
print("\nInvalid choice. Please enter 1-6.")
async def main():
"""Main example function."""
# Create HAL with RTC enabled
hal = EReaderDisplayHAL(
width=800,
height=1200,
virtual_display=True, # Virtual display for testing
enable_orientation=False,
enable_rtc=True, # Enable RTC
enable_power_monitor=False,
)
print("="*50)
print("DReader HAL - RTC Demo")
print("="*50)
print("\nInitializing HAL with RTC...")
try:
await hal.initialize()
print("✓ HAL initialized!")
if not hal.rtc:
print("\n⚠️ Warning: RTC not available!")
print("\nThis example requires PCF8523 RTC hardware on I2C bus.")
print("RTC should be at address 0x68 on I2C bus 1.")
print("\nCheck connections:")
print(" - VCC → 3.3V (Pin 1)")
print(" - GND → GND (Pin 6)")
print(" - SDA → GPIO2 (Pin 3)")
print(" - SCL → GPIO3 (Pin 5)")
print("\nVerify with: i2cdetect -y 1")
return
print("✓ RTC initialized!")
# Show initial time
current = await hal.get_datetime()
if current:
print(f"\nCurrent RTC time: {format_time(current)}")
system_time = time.localtime()
print(f"System time: {format_time(system_time)}")
# Check if times differ
time_diff = abs(time.mktime(current) - time.mktime(system_time))
if time_diff > 2: # More than 2 seconds difference
print(f"\n⚠️ RTC differs from system time by {time_diff:.0f} seconds")
# Run interactive menu
await interactive_menu(hal)
except RuntimeError as e:
print(f"\n❌ Error: {e}")
print("\nNote: This example requires PCF8523 RTC hardware on I2C bus.")
return
except KeyboardInterrupt:
print("\n\nInterrupted by user")
finally:
# Cleanup
print("\nCleaning up...")
await hal.cleanup()
print("Done!")
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
print("\nExiting...")