diff --git a/.gitignore b/.gitignore index a88af74..00e73a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ /test.py +kindle/data/* + __pycache__ *.py[cod] *$py.class diff --git a/Dockerfile b/Dockerfile index 24f0179..42d0c57 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,4 +6,11 @@ RUN apt-get update && apt-get install -y \ && rm -rf /var/lib/apt/lists/* COPY ./requirements.txt /var/www/requirements.txt COPY ./server ./app -RUN pip install -r /var/www/requirements.txt \ No newline at end of file +RUN pip install -r /var/www/requirements.txt + +RUN wget -O /tmp/openmoji-font.zip https://github.com/hfg-gmuend/openmoji/releases/download/15.0.0/openmoji-font.zip \ + && unzip /tmp/openmoji-font.zip -d /usr/share/fonts/openmoji \ + && rm /tmp/openmoji-font.zip + +RUN fc-cache -f -v +RUN fc-list | grep "OpenMoji" \ No newline at end of file diff --git a/compose.yml b/compose.yml index 5886898..96bab6c 100644 --- a/compose.yml +++ b/compose.yml @@ -4,7 +4,7 @@ services: env_file: - .env ports: - - "56733:80" + - "${HOST_PORT}:80" volumes: - ./server:/app \ No newline at end of file diff --git a/kindle/ascwebdash/bin/asc-webdash.py b/kindle/ascwebdash/bin/asc-webdash.py index 8cac2dd..787687d 100755 --- a/kindle/ascwebdash/bin/asc-webdash.py +++ b/kindle/ascwebdash/bin/asc-webdash.py @@ -2,27 +2,27 @@ # encoding: utf-8 import os -import sys import time -import signal import requests import logging import subprocess +import argparse -# Configuration -LOG_FILE = "/tmp/daemon.log" +# 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 = "/mnt/us/extensions/ascwebdash/data/received_image.png" -PID_FILE = "/tmp/mydaemon.pid" +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", -) +# 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.""" @@ -39,31 +39,14 @@ def fetch_image_from_server(url, save_path): logging.error(f"Failed to fetch IMG: {e}") return False -def display_image_with_fbink(image_path): +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 write_pid(): - with open(PID_FILE, "w") as f: - f.write(str(os.getpid())) - -def handle_signal(signum, frame): - """Handle incoming signals.""" - if signum == signal.SIGHUP: - logging.info("Received SIGHUP signal: Refreshing state...") - set_wifi(True) - logging.info("Fetching image") - display_image_with_fbink(IMAGE_PATH) - display_battery_percentage(get_battery_percentage()) - set_wifi(False) - elif signum == signal.SIGTERM: - logging.info("Received SIGTERM signal: Exiting daemon...") - sys.exit(0) + logging.error(f"Failed to display image: {e}") def set_deep_sleep(enable: bool): """ @@ -74,9 +57,12 @@ def set_deep_sleep(enable: bool): """ 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-set-prop", "com.lab126.powerd", "preventScreenSaver", value], + [lipc_bin, service, prop, value], check=True, ) action = "enabled" if enable else "disabled" @@ -91,8 +77,11 @@ 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-get-prop", "com.lab126.powerd", "battLevel"], + [lipc_bin, service, prop], capture_output=True, text=True, check=True, @@ -110,124 +99,37 @@ def display_battery_percentage(battery_percentage): message = f"{battery_percentage}%" # Display the message using FBInk - os.system(f"fbink -x 10 -p {message} > /dev/null 2>&1") + 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 send_sighup(): - """Send SIGHUP signal to the daemon.""" - if not os.path.exists(PID_FILE): - logging.debug("Daemon is not running (PID file not found).") - return - - try: - # Read the PID from the file - with open(PID_FILE, "r") as f: - pid = int(f.read().strip()) - - # Send the SIGHUP signal - os.kill(pid, signal.SIGHUP) - logging.debug("SIGHUP signal sent to the daemon.") - except Exception as e: - logging.debug(f"Failed to send SIGHUP: {e}") - - -def set_gui(enable: bool): - """ - Start or stop the Kindle GUI based on the enable input. - - Args: - enable (bool): If True, starts the GUI. If False, stops the GUI. - """ - action = "start" if enable else "stop" - try: - subprocess.run([action, "lab126_gui"], check=True) - logging.info(f"GUI {action}ped successfully.") - except subprocess.CalledProcessError as e: - logging.info(f"Failed to {action} GUI: {e}") - -def set_wifi(enable: bool): - """ - Toggle Wi-Fi on or off based on the `enable` boolean input. - - Args: - enable (bool): If True, Wi-Fi will be turned on. If False, Wi-Fi will be turned off. - """ - try: - if enable: - # Enable Wi-Fi -# logging.info("Starting Wi-Fi...") -# subprocess.run(["lipc-set-prop", "com.lab126.cmd", "wirelessEnable", "1"], check=True) -# time.sleep(60) -# logging.info("Wi-Fi has been enabled.") - pass - else: - # Disable Wi-Fi -# subprocess.run(["lipc-set-prop", "com.lab126.cmd", "wirelessEnable", "0"], check=True) -# logging.info("Wi-Fi has been disabled.") - pass - except subprocess.CalledProcessError as e: - logging.error(f"Failed to toggle Wi-Fi: {e}") + logging.debug(f"Error displaying battery percentage: {e}") def main(): """Main daemon process.""" - logging.info("Daemon started") + 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): - set_wifi(True) logging.info("Fetching image") - display_image_with_fbink(IMAGE_PATH) + refresh_screen_with_image(IMAGE_PATH) display_battery_percentage(get_battery_percentage()) - set_wifi(False) else: logging.error("Could not fetch or display image.") - time.sleep(REFRESH_SECONDS) # Sleep before fetching again - + time.sleep(REFRESH_SECONDS) # Sleep before fetching again if __name__ == "__main__": - # Handle termination signals - signal.signal(signal.SIGTERM, handle_signal) - signal.signal(signal.SIGINT, handle_signal) - signal.signal(signal.SIGHUP, handle_signal) - # Process command-line arguments - if len(sys.argv) > 1: - if sys.argv[1] == "start": - # Write PID file and start the daemon - write_pid() - set_deep_sleep(False) - set_gui(False) - main() - elif sys.argv[1] == "stop": - # Stop the daemon - if os.path.exists(PID_FILE): - with open(PID_FILE, "r") as f: - pid = int(f.read()) - os.kill(pid, signal.SIGTERM) - os.remove(PID_FILE) - set_deep_sleep(True) - set_gui(True) - logging.debug("Daemon stopped.") - else: - logging.debug("PID file not found. Is the daemon running?") - elif sys.argv[1] == "refresh": - if os.path.exists(PID_FILE): - send_sighup() - else: - logging.debug("PID file not found. Is the daemon running?") - elif sys.argv[1] == "restart": - # Restart the daemon - if os.path.exists(PID_FILE): - with open(PID_FILE, "r") as f: - pid = int(f.read()) - os.kill(pid, signal.SIGTERM) - os.remove(PID_FILE) - logging.debug("Daemon stopped.") - # Start the daemon - write_pid() - main() - else: - logging.debug("Invalid command. Use 'start', 'stop', or 'restart'.") - else: - logging.debug("Usage: python3 mydaemon.py [start|stop|restart]") \ No newline at end of file + set_deep_sleep(False) + main() \ No newline at end of file diff --git a/server/app/templates/style.css b/server/app/templates/style.css index afea9f0..47e7022 100644 --- a/server/app/templates/style.css +++ b/server/app/templates/style.css @@ -10,12 +10,9 @@ html, body { body { width: 600px; height: 800px; - border: 2px solid red; /* Visual aid */ } .dashboard { - border: 2px solid green; /* Visual aid */ - display: -webkit-box; display: -webkit-flex; display: flex; @@ -77,7 +74,6 @@ body { } .panel.bottom.week .row { - border: 2px solid yellow; /* Visual aid */ display: -webkit-box; display: -webkit-flex; display: flex; @@ -102,6 +98,7 @@ body { justify-content: flex-start; /* Align children at the top */ text-align: left; flex: 1; + width: 148px; } .day .day-title { @@ -119,11 +116,15 @@ body { } .day .event { - margin: 3pt; background-color: white; border-style: solid; border-radius: 5px; padding: 2px; + margin-bottom: 2px; +} + +.day .events { + padding: 2px; } .footer { diff --git a/server/app/views.py b/server/app/views.py index d6783dd..e7fa7ac 100644 --- a/server/app/views.py +++ b/server/app/views.py @@ -56,10 +56,14 @@ def dashboard(): for url in [ 'https://www.calendarlabs.com/ical-calendar/ics/76/US_Holidays.ics', ]: - r = requests.get(url) - c = cal.Calendar.from_ical(r.content) + try: + raise Exception + r = requests.get(url) + c = cal.Calendar.from_ical(r.content) - events += Event.fromIcalendar(c) + events += Event.fromIcalendar(c) + except Exception as e: + print(f"Error: {e}") with caldav.DAVClient(url=caldav_url, username=username, password=password) as client: my_principal = client.principal()