PyUnit is a custom firmware for iDryer Unit written in Python.
- ๐ก๏ธ Real-time monitoring of temperature and humidity
- ๐ฏ PID temperature control with configurable parameters
- ๐ Multiple drying presets with timer and storage modes
- ๐ Interactive charts with adaptive downsampling
- ๐ Klipper integration via Moonraker API
- ๐จ LED control for visual status indicators
- ๐ช Servo control for automated door operation
- ๐ฑ Responsive web interface built with Angular
- ๐ WebSocket real-time updates
- ๐ Embed pages for Klipper HTTP camera integration
- ๐ค G-code macro generation for Klipper
- ๐ณ Multi-platform Docker images (amd64, arm64, arm/v7, arm/v8)
Main dashboard with all dryers overview and real-time monitoring
Detailed dryer view with temperature/humidity charts and control panel
Preset configuration with timer and storage modes
PyUnit embedded control panel in Fluidd/Mainsail interface
git clone https://github.com/xatang/PyUnit.git
cd PyUnit
chmod +x run.sh
./run.shThat's it! Access PyUnit at http://YOUR_IP:5000
The script will automatically:
- โ Install Docker and Docker Compose (if needed)
- โ Detect your IP address
- โ Configure the environment
- โ Download pre-built Docker image
- โ Start the application
Installation time: 1-3 minutes (no compilation required!)
On your first visit to PyUnit, you'll be greeted by a 3-step setup wizard that guides you through initial configuration:
- Enter your Moonraker IP address
- For Docker users: Use your machine's network IP (e.g.,
192.168.1.100) - For local installations: You can use
127.0.0.1
- For Docker users: Use your machine's network IP (e.g.,
- Default port:
7125 - Test connection before saving
- Configure all hardware components:
- Heater (must be configured in Klipper)
- Fan (PWM control)
- Temperature and humidity sensor
- LED indicators
- Servo door control
- All components must be pre-configured in your Klipper configuration
- Once configured, access the dashboard
- Monitor and control your dryer units
Note: The wizard can be skipped using "Skip setup for now" if you want to configure manually later.
- OS: Linux (Ubuntu, Debian, Raspbian, Armbian)
- Architecture:
- amd64 (x86_64) - Intel/AMD 64-bit
- arm64 (aarch64) - ARM 64-bit
- arm/v7 - ARMv7 32-bit
- arm/v8 - ARMv8 32-bit
- RAM: 256MB minimum (512MB recommended)
- Disk: ~1GB for Docker image
Additionally, you can add the following commands to the Fluidd or Mainsail console filters to avoid a flood of messages during firmware operation.
SET_LED LED=[led_name] INDEX=
SET_HEATER_TEMPERATURE HEATER=[heater_name]
SET_SERVO SERVO=[servo_name]To update to the latest version:
cd PyUnit
./run.shUpdates preserve your configuration and IP settings automatically.
To completely remove PyUnit (container, volumes, images, network):
cd PyUnit
chmod +x uninstall.sh
./uninstall.shThis will remove:
- Docker container
pyunit - Docker volume
pyunit_pyunit_data(all data will be lost!) - Docker network
pyunit_pyunit_network - Docker images
xatang/pyunit:*
Note: Local files (pyunit.db, logs) are NOT deleted automatically. To remove them:
rm -f pyunit.db pyunit.db-wal pyunit.db-shm app.log dryer.log- FastAPI - Modern async web framework
- SQLAlchemy - ORM with SQLite database
- Alembic - Database migrations
- WebSockets - Real-time bidirectional communication
- Uvicorn - ASGI server (hardcoded:
0.0.0.0:5000) - Simple-PID - PID controller for temperature regulation
- aiohttp - Async HTTP client for Moonraker API
Key Components:
api/endpoints/- Modular REST API endpointsapi/cruds/- Database CRUD operationsapi/workers/- Background status monitoringapi/tools/- Dryer control & Moonraker integrationmain.py- Application entry point (fixed host/port)
- Angular 18 - Standalone components architecture
- Runtime Configuration - IP/URLs set at container startup
- Highcharts - Interactive data visualization
- Bootstrap 5 - Dark theme UI
- RxJS - Reactive state management
- WebSocket - Real-time data subscriptions
Port Mapping:
- Internal: Always
5000(hardcoded inmain.py) - External: Configurable via
.envPORTvariable - Example:
PORT=8080maps8080:5000(host:container)
The .env file is automatically created with your detected IP:
# Backend Configuration
LOG_LEVEL=INFO # Logging verbosity
DRYER_LOG_LEVEL=INFO # Dryer-specific logging
CLEAR_LOGS_ON_STARTUP=True # Clear logs on startup
# External Access (auto-configured by run.sh)
PORT=5000 # External port (host side)
API_URL=http://192.168.1.100:5000/api # Frontend API URL
WS_URL=ws://192.168.1.100:5000/api # WebSocket URLNote: HOST=0.0.0.0 and internal PORT=5000 are hardcoded in main.py and not configurable.
docker-compose.yml uses .env automatically:
services:
pyunit:
image: xatang/pyunit:latest # Auto-detected by run.sh
ports:
- "${PORT:-5000}:5000" # External:Internal
environment:
- API_URL=${API_URL} # For runtime config.js
- WS_URL=${WS_URL}
volumes:
- ./pyunit.db:/app/pyunit.db
- ./app.log:/app/app.log
- ./dryer.log:/app/dryer.logEdit .env:
PORT=8080
API_URL=http://192.168.1.100:8080/api
WS_URL=ws://192.168.1.100:8080/apiThen restart:
sudo docker compose up -dReal-time Monitoring:
- Live temperature and humidity charts
- Current dryer status and remaining time
- Heater and servo state indicators
- Historical data with time range selector (5m, 10m, 1h, 6h, 12h, All)
Starting a Drying Cycle:
- Select a dryer from the list
- Choose a preset
- Click Start - the dryer will begin the drying process
Moonraker Integration:
- Go to Config โ Moonraker
- Set Moonraker IP
- Add API key (if authentication enabled)
- Save configuration
- Add new dryer
- Assign presets to new dryer
Example Configuration:
A complete Klipper configuration example is available in config_and_macros/U1.cfg.example. This file contains:
- Heater configuration (
[heater_generic]) - Temperature sensor setup (
[temperature_sensor]) - LED control (
[neopixel]) - Servo configuration (
[servo]) - G-code macros for dryer control
- โ
Correct:
idryer_u1_heater,idryer_u1_air,srv_u1 - โ Wrong:
IDryer_U1_Heater,IDRYER_U1_AIR,SRV_U1
G-code Macros:
- To control the drying process via gcode macro, your printer must have the gcode_shell_command extension installed.
- After installation gcode_shell_command go to dryer detail page
- Expand Klipper G-code Macros
- Configure Python script path
- Copy macros to
printer.cfg - Use in Klipper:
OFF_DRYER ID=1 PRESET_DRYER ID=1 PRESET_ID=5
HTTP Camera Embed:
- Expand Klipper Embed Pages
- Copy embed URLs
- Add to Moonraker config:
[camera pyunit_control] location: dryer service: http aspect_ratio: 4:3 stream_url: http://192.168.1.100:5000/embed/dryer/1/control [camera pyunit_chart] location: dryer service: http aspect_ratio: 4:3 stream_url: http://192.168.1.100:5000/embed/dryer/1/chart
# View status
sudo docker compose ps
# Start/stop/restart
sudo docker compose up -d
sudo docker compose down
sudo docker compose restart
# View logs (live)
sudo docker compose logs -f
# View logs (last 100 lines)
sudo docker compose logs --tail=100
# Check resource usage
sudo docker stats pyunitInteractive documentation available at:
- Swagger UI:
http://192.168.1.100:5000/docs - ReDoc:
http://192.168.1.100:5000/redoc
Dashboard:
GET /api/dashboard- Overview of all dryersGET /api/dashboard/dryer/{id}- Dryer details with chart dataPOST /api/dashboard/dryer/{id}/preset- Start preset on dryerPOST /api/dashboard/dryer/{id}/reset- Reset dryer to pending
Configuration:
GET /api/config/dryers- List all dryersGET /api/config/moonraker- Moonraker settingsPUT /api/config/moonraker- Update Moonraker config
Presets:
GET /api/presets- List all presetsPOST /api/presets- Create new presetPUT /api/presets/{id}- Update presetDELETE /api/presets/{id}- Delete preset
Logs:
GET /api/logs- Retrieve application logs
WebSocket:
WS /api/ws- Real-time status updates
PyUnit/
โโโ .github/
โ โโโ workflows/
โ โโโ docker-build.yml # CI/CD pipeline for multi-platform builds
โโโ .venv/ # Python virtual environment (local dev)
โโโ __pycache__/ # Python bytecode cache
โโโ alembic/ # Database migrations
โ โโโ versions/ # Migration scripts
โ โ โโโ 5a91b07ca6c5_initdb.py
โ โโโ env.py # Alembic environment
โ โโโ README # Alembic documentation
โ โโโ script.py.mako # Migration template
โโโ api/ # Backend API
โ โโโ cruds/ # Database CRUD operations
โ โ โโโ common_crud.py # Common operations (logs cleanup)
โ โ โโโ dryer_crud.py # Dryer management
โ โ โโโ moonraker_config_crud.py # Moonraker config
โ โ โโโ preset_crud.py # Preset management
โ โโโ endpoints/ # API route handlers
โ โ โโโ __init__.py # Router aggregation
โ โ โโโ common.py # Health check, WebSocket
โ โ โโโ config_page.py # Dryer & Moonraker config
โ โ โโโ dashboard_page.py # Dashboard & dryer control
โ โ โโโ logs_page.py # Logs retrieval
โ โ โโโ presets_page.py # Preset CRUD
โ โโโ schemas/ # Pydantic validation models
โ โ โโโ dryer_schema.py
โ โ โโโ dryer_config_schema.py
โ โ โโโ heater_config_schema.py
โ โ โโโ humidity_config_schema.py
โ โ โโโ led_config_schema.py
โ โ โโโ moonraker_config_schema.py
โ โ โโโ preset_schema.py
โ โ โโโ servo_config_schema.py
โ โ โโโ temperature_config_schema.py
โ โโโ tools/ # Core control logic
โ โ โโโ dryer_control.py # Dryer state machine & PID control
โ โ โโโ moonraker_api.py # Moonraker HTTP client
โ โโโ workers/ # Background tasks
โ โ โโโ status_worker.py # Periodic status polling & control
โ โโโ database.py # SQLAlchemy setup & migrations
โ โโโ logger.py # Logging configuration
โ โโโ models.py # SQLAlchemy ORM models
โ โโโ websocket_manager.py # WebSocket connection manager
โโโ config_and_macros/
โ โโโ idryer_api.py # Python script for Klipper G-code integration
โโโ web/ # Frontend (Angular 18)
โ โโโ public/ # Static assets
โ โ โโโ assets/
โ โ โโโ imgs/ # Images
โ โโโ src/
โ โ โโโ app/
โ โ โ โโโ common-ui/ # Shared UI components
โ โ โ โโโ guards/ # Route guards
โ โ โ โ โโโ setup.guard.ts # Setup completion check
โ โ โ โโโ pages/
โ โ โ โ โโโ configs/ # Configuration pages
โ โ โ โ โ โโโ dryer-config/
โ โ โ โ โ โโโ moonraker-config/
โ โ โ โ โโโ dashboard/ # Dashboard & dryer details
โ โ โ โ โ โโโ dashboard/
โ โ โ โ โ โโโ dryer-detail/
โ โ โ โ โโโ embed/ # Klipper embed pages
โ โ โ โ โ โโโ dryer-chart/
โ โ โ โ โ โโโ dryer-control/
โ โ โ โ โโโ logs/ # Logs viewer
โ โ โ โ โโโ presets/ # Preset CRUD
โ โ โ โ โ โโโ preset-editor/
โ โ โ โ โ โโโ presets-list/
โ โ โ โ โโโ welcome/ # First-time setup wizard
โ โ โ โ โโโ welcome.html
โ โ โ โ โโโ welcome.scss
โ โ โ โ โโโ welcome.ts
โ โ โ โโโ services/ # Angular services
โ โ โ โ โโโ dryer-config.service.ts
โ โ โ โ โโโ moonraker-config.service.ts
โ โ โ โ โโโ presets.service.ts
โ โ โ โ โโโ websocket.service.ts
โ โ โ โโโ app.config.ts # Angular app configuration
โ โ โ โโโ app.html # Root component template
โ โ โ โโโ app.initializer.ts # Runtime config loader
โ โ โ โโโ app.routes.ts # Route definitions
โ โ โ โโโ app.scss # Global styles
โ โ โ โโโ app.ts # Root component
โ โ โโโ environments.ts # Runtime config (auto-generated by update-env.js)
โ โ โโโ index.html # HTML entry point
โ โ โโโ main.ts # Bootstrap with APP_INITIALIZER
โ โ โโโ styles.scss # Global SCSS styles
โ โโโ angular.json # Angular CLI configuration
โ โโโ package.json # NPM dependencies
โ โโโ tsconfig.json # TypeScript configuration
โ โโโ tsconfig.app.json # App-specific TS config
โ โโโ tsconfig.spec.json # Test TS config
โ โโโ update-env.js # Pre-build script (generates environments.ts)
โโโ .dockerignore # Docker build exclusions
โโโ .env # Environment config (auto-created by run.sh)
โโโ .gitignore # Git ignore patterns
โโโ alembic.ini # Alembic configuration
โโโ build.sh # Local Docker image build script
โโโ docker-compose.yml # Docker Compose service definition
โโโ Dockerfile # Multi-stage Docker build (Node + Python)
โโโ entrypoint.sh # Container startup script (creates config.js)
โโโ main.py # FastAPI application entry point
โโโ pyunit.db # SQLite database (created by run.sh)
โโโ requirements.txt # Python dependencies
โโโ run.sh # Installation/update script
โโโ README.md # This file
- FastAPI 0.104+ - Modern async web framework
- Python 3.11 - Programming language
- SQLAlchemy 2.0+ - SQL toolkit and ORM
- Alembic 1.12+ - Database migration tool
- Pydantic 2.0+ - Data validation using Python type hints
- simple-pid 2.0+ - PID controller implementation
- aiohttp 3.9+ - Async HTTP client for Moonraker
- uvicorn 0.24+ - ASGI server implementation
- WebSockets - Real-time bidirectional communication
- Angular 18 - Modern web application framework
- TypeScript 5.0+ - Typed JavaScript superset
- Highcharts 11+ - Interactive charting library
- Bootstrap 5.3 - Responsive UI framework
- Bootstrap Icons 1.11+ - Icon library
- RxJS 7.8+ - Reactive programming library
- Standalone Components - Modern Angular architecture
- Docker - Containerization
- Docker Compose - Multi-container orchestration
- GitHub Actions - CI/CD automation
- Docker Buildx - Multi-platform image builds
- SQLite - Embedded database