This commit introduces several enhancements across multiple files to improve maintainability, functionality, and overall code quality. Key updates are as follows:
1. .gitignore
• Added exclusion for kindle/data/* to prevent Kindle-specific data from being tracked.
2. Dockerfile
• Added installation of OpenMoji font:
• Downloads and unzips OpenMoji font to /usr/share/fonts/openmoji.
• Updates font cache with fc-cache.
• Verifies installation with fc-list | grep "OpenMoji".
• Improves container setup for rendering Kindle dashboards with proper font support.
3. compose.yml
• Port mapping now uses an environment variable ${HOST_PORT} instead of hardcoding 56733:80.
• Enhances flexibility for port management.
4. kindle/ascwebdash.py
• Significant refactoring and cleanup:
• Removed unused signal handling and daemonization logic.
• Simplified logging configuration and added optional arguments using argparse for flexibility.
• Abstracted repetitive paths using constants for maintainability.
• Consolidated functionality for fetching images and refreshing the screen.
• Removed unused Wi-Fi and GUI toggling code.
• Focused the script’s functionality on image fetching and display for Kindle extensions.
5. CSS (style.css)
• Removed visual debugging borders (red, green, yellow).
• Improved layout styles:
• Set fixed widths for better rendering of event columns.
• Adjusted margins and paddings for cleaner alignment.
• Added a new .day .events class for consistent padding.
6. views.py
• Added error handling when fetching calendar data:
• Ensures the application doesn’t crash if calendar URLs are inaccessible.
• Logs errors to console for debugging.
Impact:
• Maintainability: Refactored scripts, improved code structure, and enhanced readability.
• Flexibility: Environment variable support for ports and dynamic script arguments.
• Functionality: Added OpenMoji font support in the Docker container.
• UI/UX: Cleaned up CSS for better layout and appearance.
• Resilience: Improved error handling in views.py to handle calendar fetch failures gracefully.
Files Modified:
• .gitignore
• Dockerfile
• compose.yml
• kindle/ascwebdash/bin/asc-webdash.py
• server/app/templates/style.css
• server/app/views.py
This ensures better extensibility and robustness across the codebase.
135 lines
4.9 KiB
Python
Executable File
135 lines
4.9 KiB
Python
Executable File
# bin/python3
|
|
# encoding: utf-8
|
|
|
|
import os
|
|
import time
|
|
import requests
|
|
import logging
|
|
import subprocess
|
|
import argparse
|
|
|
|
# Configuration Defaults
|
|
EXTENSION_NAME="ascwebdash"
|
|
EXTENSION_DIR=f"/mnt/us/extensions/{EXTENSION_NAME}"
|
|
LOG_FILE = f"{EXTENSION_DIR}/asc-webdash.py.log"
|
|
IMG_URL = "http://10.0.1.113:56733/image"
|
|
IMAGE_PATH = f"{EXTENSION_DIR}/received_image.png"
|
|
REFRESH_SECONDS=1800
|
|
|
|
# Configure logging
|
|
# logging.basicConfig(
|
|
# filename=LOG_FILE,
|
|
# level=logging.INFO,
|
|
# format="%(asctime)s [%(levelname)s] %(message)s",
|
|
# datefmt="%Y-%m-%d %H:%M:%S",
|
|
# )
|
|
|
|
def fetch_image_from_server(url, save_path):
|
|
"""Fetch a IMG file from an HTTP server."""
|
|
logging.info(f"Fetching IMG from {url}")
|
|
try:
|
|
response = requests.get(url, stream=True)
|
|
response.raise_for_status() # Raise HTTP errors
|
|
with open(save_path, "wb") as image_file:
|
|
for chunk in response.iter_content(1024):
|
|
image_file.write(chunk)
|
|
logging.info(f"Image saved to {save_path}")
|
|
return True
|
|
except Exception as e:
|
|
logging.error(f"Failed to fetch IMG: {e}")
|
|
return False
|
|
|
|
def refresh_screen_with_image(image_path):
|
|
"""Display the IMG image on the Kindle using FBInk."""
|
|
logging.info(f"Displaying image: {image_path}")
|
|
try:
|
|
os.system(f"fbink -i {image_path} > /dev/null 2>&1")
|
|
logging.info("Image displayed successfully.")
|
|
except Exception as e:
|
|
logging.error(f"Failed to display image: {e}")
|
|
|
|
def set_deep_sleep(enable: bool):
|
|
"""
|
|
Enable or disable deep sleep on the Kindle.
|
|
|
|
Args:
|
|
enable (bool): If True, enables deep sleep. If False, disables deep sleep.
|
|
"""
|
|
try:
|
|
# Map boolean argument to corresponding lipc-set-prop value
|
|
lipc_bin = "lipc-set-prop"
|
|
service = "com.lab126.powerd"
|
|
prop = "preventScreenSaver"
|
|
value = "0" if enable else "1"
|
|
subprocess.run(
|
|
[lipc_bin, service, prop, value],
|
|
check=True,
|
|
)
|
|
action = "enabled" if enable else "disabled"
|
|
logging.info(f"Deep sleep {action} successfully.")
|
|
logging.debug(f"Deep sleep {action} successfully.")
|
|
except subprocess.CalledProcessError as e:
|
|
action = "enable" if enable else "disable"
|
|
logging.error(f"Failed to {action} deep sleep: {e}")
|
|
logging.debug(f"Failed to {action} deep sleep: {e}")
|
|
|
|
def get_battery_percentage():
|
|
"""Retrieve the Kindle's battery percentage."""
|
|
try:
|
|
# Run the command to get battery percentage
|
|
lipc_bin = "lipc-get-prop"
|
|
service = "com.lab126.powerd"
|
|
prop = "preventScreenSaver"
|
|
result = subprocess.run(
|
|
[lipc_bin, service, prop],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
# Extract and return the percentage as an integer
|
|
return int(result.stdout.strip())
|
|
except Exception as e:
|
|
logging.debug(f"Error retrieving battery percentage: {e}")
|
|
return None
|
|
|
|
def display_battery_percentage(battery_percentage):
|
|
"""Display the battery percentage on the screen using FBInk."""
|
|
try:
|
|
# Construct the message
|
|
message = f"{battery_percentage}%"
|
|
|
|
# Display the message using FBInk
|
|
os.system(f"fbink -p {message} > /dev/null 2>&1")
|
|
logging.debug("Battery percentage displayed successfully.")
|
|
except Exception as e:
|
|
logging.debug(f"Error displaying battery percentage: {e}")
|
|
|
|
def main():
|
|
"""Main daemon process."""
|
|
parser = argparse.ArgumentParser()
|
|
# Define optional arguments
|
|
parser.add_argument("--extension-dir", type=str, default=EXTENSION_DIR,
|
|
help=f"Directory for extensions (default: {EXTENSION_DIR})")
|
|
parser.add_argument("--log-file", type=str, default=LOG_FILE,
|
|
help=f"Path to the log file (default: {LOG_FILE})")
|
|
parser.add_argument("--img-url", type=str, default=IMG_URL,
|
|
help=f"URL of the image to download (optional default:{IMG_URL})")
|
|
parser.add_argument("--image-path", type=str, default=IMAGE_PATH,
|
|
help=f"Path to save the image (default: {IMAGE_PATH})")
|
|
parser.add_argument("--refresh-seconds", type=int, default=REFRESH_SECONDS,
|
|
help=f"Time in seconds between refreshes (default: {REFRESH_SECONDS})")
|
|
|
|
logging.info("Script started")
|
|
while True:
|
|
if fetch_image_from_server(IMG_URL, IMAGE_PATH):
|
|
logging.info("Fetching image")
|
|
refresh_screen_with_image(IMAGE_PATH)
|
|
display_battery_percentage(get_battery_percentage())
|
|
else:
|
|
logging.error("Could not fetch or display image.")
|
|
time.sleep(REFRESH_SECONDS) # Sleep before fetching again
|
|
|
|
if __name__ == "__main__":
|
|
# Process command-line arguments
|
|
set_deep_sleep(False)
|
|
main() |