autostart

This commit is contained in:
Aron Petau 2025-11-20 12:38:05 +01:00
parent 65235d8c9a
commit ca110918b4
6 changed files with 243 additions and 22 deletions

104
SERVICE_README.md Normal file
View file

@ -0,0 +1,104 @@
# AutoKanban Service Setup
This directory contains files to run AutoKanban as a system service that starts automatically on boot.
## Quick Setup (Raspberry Pi)
1. **Run the setup script:**
```bash
cd ~/autokanban
chmod +x setup_service.sh
./setup_service.sh
```
2. **The app will now start automatically on boot!**
## Service Management Commands
```bash
# Check if service is running
sudo systemctl status autokanban
# Stop the service
sudo systemctl stop autokanban
# Start the service
sudo systemctl start autokanban
# Restart the service
sudo systemctl restart autokanban
# View live logs
sudo journalctl -u autokanban -f
# View recent logs
sudo journalctl -u autokanban -n 50
# Disable autostart on boot
sudo systemctl disable autokanban
# Enable autostart on boot
sudo systemctl enable autokanban
```
## Manual Service Installation
If the setup script doesn't work, install manually:
```bash
# Copy service file
sudo cp autokanban.service /etc/systemd/system/
# Edit paths if needed
sudo nano /etc/systemd/system/autokanban.service
# Reload systemd
sudo systemctl daemon-reload
# Enable and start
sudo systemctl enable autokanban
sudo systemctl start autokanban
```
## Updating the App
After pulling new code:
```bash
cd ~/autokanban
git pull
sudo systemctl restart autokanban
```
## Troubleshooting
**Service won't start:**
```bash
# Check logs for errors
sudo journalctl -u autokanban -n 50
# Check Python path
which python
# Update ExecStart in service file if needed
```
**Permission issues:**
```bash
# Make sure user is in dialout group (for printer)
sudo usermod -a -G dialout $USER
# Reboot for group changes to take effect
sudo reboot
```
**Port already in use:**
```bash
# Check what's using port 8000
sudo lsof -i :8000
# Kill the process or change port in start_app.py
```

View file

@ -147,11 +147,11 @@ def print_task(request: Request, task_id: str):
draw = ImageDraw.Draw(img) draw = ImageDraw.Draw(img)
draw.rectangle([(0,0),(CARD_WIDTH_PX-1,CARD_HEIGHT_PX-1)], outline=0, width=4) draw.rectangle([(0,0),(CARD_WIDTH_PX-1,CARD_HEIGHT_PX-1)], outline=0, width=4)
# Robust font loading # Robust font loading - increased sizes for physical printer readability
font_title = load_font(FONT_BOLD, 36, font_label="title") font_title = load_font(FONT_BOLD, 42, font_label="title")
font_label_f = load_font(FONT_BOLD, 18, font_label="label") font_label_f = load_font(FONT_BOLD, 24, font_label="label")
font_text = load_font(FONT_REGULAR, 22, font_label="text") font_text = load_font(FONT_REGULAR, 28, font_label="text")
font_icon = load_font(FA_FONT, 48, font_label="icon") font_icon = load_font(FA_FONT, 60, font_label="icon")
# Prepare content for line wrapping # Prepare content for line wrapping
import textwrap import textwrap
@ -159,7 +159,7 @@ def print_task(request: Request, task_id: str):
max_text_width = CARD_WIDTH_PX - 40 max_text_width = CARD_WIDTH_PX - 40
content_lines = [] content_lines = []
if font_title: if font_title:
wrapper = textwrap.TextWrapper(width=24) wrapper = textwrap.TextWrapper(width=20) # Reduced from 24 due to larger font
lines = wrapper.wrap(task.content) lines = wrapper.wrap(task.content)
for line in lines: for line in lines:
# Check pixel width, wrap further if needed # Check pixel width, wrap further if needed

View file

@ -151,6 +151,22 @@ button:hover {
color: #1C1C1E; color: #1C1C1E;
} }
footer {
width: 100%;
background-color: #E9EEF5;
color: #1C1C1E;
padding: 1.5em 0;
text-align: center;
box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.1);
margin-top: 2em;
}
footer .footer-logo {
height: 40px;
vertical-align: middle;
margin-right: 0.5em;
}
@media (max-width: 1024px) { @media (max-width: 1024px) {
.container { .container {
width: 95%; width: 95%;

24
autokanban.service Normal file
View file

@ -0,0 +1,24 @@
[Unit]
Description=AutoKanban Thermal Printer Web App
After=network.target
[Service]
Type=simple
User=pi
Group=pi
WorkingDirectory=/home/pi/autokanban
Environment="PATH=/home/pi/.pyenv/versions/autokanban/bin:/usr/local/bin:/usr/bin:/bin"
Environment="PYENV_ROOT=/home/pi/.pyenv"
ExecStart=/home/pi/.pyenv/versions/autokanban/bin/python /home/pi/autokanban/start_app.py
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
# Graceful shutdown
TimeoutStopSec=10
KillMode=mixed
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target

58
setup_service.sh Normal file
View file

@ -0,0 +1,58 @@
#!/bin/bash
# AutoKanban Systemd Service Setup Script
# Run this on the Raspberry Pi to enable autostart on boot
set -e
echo "🚀 Setting up AutoKanban service..."
# Check if running as regular user
if [ "$EUID" -eq 0 ]; then
echo "❌ Please run as regular user (not sudo)"
exit 1
fi
# Get the directory where this script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SERVICE_FILE="$SCRIPT_DIR/autokanban.service"
echo "📁 Working directory: $SCRIPT_DIR"
# Update the service file with actual paths
echo "🔧 Updating service file paths..."
sed -i "s|/home/pi/autokanban|$SCRIPT_DIR|g" "$SERVICE_FILE"
sed -i "s|User=pi|User=$USER|g" "$SERVICE_FILE"
sed -i "s|Group=pi|Group=$USER|g" "$SERVICE_FILE"
# Copy service file to systemd
echo "📋 Installing systemd service..."
sudo cp "$SERVICE_FILE" /etc/systemd/system/autokanban.service
# Reload systemd
echo "🔄 Reloading systemd..."
sudo systemctl daemon-reload
# Enable the service
echo "✅ Enabling autokanban service..."
sudo systemctl enable autokanban.service
# Start the service
echo "▶️ Starting autokanban service..."
sudo systemctl start autokanban.service
# Show status
echo ""
echo "✨ Setup complete! Service status:"
sudo systemctl status autokanban.service --no-pager
echo ""
echo "📝 Useful commands:"
echo " sudo systemctl status autokanban - Check service status"
echo " sudo systemctl stop autokanban - Stop the service"
echo " sudo systemctl start autokanban - Start the service"
echo " sudo systemctl restart autokanban - Restart the service"
echo " sudo journalctl -u autokanban -f - View live logs"
echo " sudo systemctl disable autokanban - Disable autostart"
echo ""
echo "🌐 AutoKanban should now be running at http://$(hostname -I | awk '{print $1}'):8000"

View file

@ -1,23 +1,42 @@
import subprocess import subprocess
import sys import sys
import os import os
import signal
# Activate venv if not already active # Handle graceful shutdown
def activate_venv(): def signal_handler(sig, frame):
venv_path = os.path.join(os.path.dirname(__file__), '.venv', 'bin', 'activate_this.py') print("\n[INFO] Shutting down gracefully...")
if os.path.exists(venv_path): sys.exit(0)
with open(venv_path) as f:
exec(f.read(), {'__file__': venv_path}) signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
if __name__ == "__main__": if __name__ == "__main__":
# Optionally activate venv (works on Linux/macOS) # Use pyenv python if available, otherwise fall back to venv or system python
venv_python = os.path.join(os.path.dirname(__file__), '.venv', 'bin', 'python') python_exec = sys.executable
if os.path.exists(venv_python):
python_exec = venv_python
else:
python_exec = sys.executable
# Launch the FastAPI app with uvicorn # Check for pyenv virtualenv
subprocess.run([ pyenv_root = os.environ.get('PYENV_ROOT')
python_exec, '-m', 'uvicorn', 'app.main:app', '--host', '0.0.0.0', '--port', '8000', '--reload' if pyenv_root:
]) pyenv_python = os.path.join(pyenv_root, 'versions', 'autokanban', 'bin', 'python')
if os.path.exists(pyenv_python):
python_exec = pyenv_python
# Fall back to local venv
if python_exec == sys.executable:
venv_python = os.path.join(os.path.dirname(__file__), '.venv', 'bin', 'python')
if os.path.exists(venv_python):
python_exec = venv_python
print(f"[INFO] Using Python: {python_exec}")
print(f"[INFO] Starting AutoKanban on http://0.0.0.0:8000")
# Launch the FastAPI app with uvicorn (no --reload for production)
try:
subprocess.run([
python_exec, '-m', 'uvicorn', 'app.main:app',
'--host', '0.0.0.0', '--port', '8000'
])
except KeyboardInterrupt:
print("\n[INFO] Shutting down gracefully...")
sys.exit(0)