Add Docker containerization and Raspberry Pi support

- Add Dockerfile with multi-architecture support (AMD64/ARM64/ARMv7)
- Add docker-compose.yml with continuous and manual run options
- Add comprehensive Docker documentation (README-DOCKER.md)
- Add CLAUDE.md for future development guidance
- Update README.md with Docker deployment and UniFi Protect future goals
- Configure individual door device support (vs door groups)
- Add Raspberry Pi compatibility and deployment instructions
- Include memory limits for Pi optimization

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
main
Cole Nicholas 2025-11-27 10:48:55 -06:00
parent ec9f997c73
commit e080aba000
8 changed files with 369 additions and 5 deletions

View File

@ -0,0 +1,13 @@
{
"permissions": {
"allow": [
"Bash(cp:*)",
"Bash(python3:*)",
"Bash(pip install:*)",
"Bash(mkdir:*)",
"Bash(git add:*)"
],
"deny": [],
"ask": []
}
}

29
.dockerignore Normal file
View File

@ -0,0 +1,29 @@
# Ignore log files
*.log
logs/
# Ignore git
.git
.gitignore
# Ignore Docker files
Dockerfile
docker-compose.yml
.dockerignore
# Ignore Python cache
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
# Ignore IDE files
.vscode/
.idea/
*.swp
*.swo
# Ignore OS files
.DS_Store
Thumbs.db

107
CLAUDE.md Normal file
View File

@ -0,0 +1,107 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a Python automation tool that integrates UniFi Access with Airbnb/Hostex reservations, automatically creating and managing visitor access for Airbnb guests. The system fetches reservations from either Hostex API or Airbnb ICS feed, creates UniFi Access visitor accounts with PIN codes based on phone numbers, and provides cross-verification between multiple booking systems.
## Core Commands
### Development and Execution
- **Run the application**: `python3 main.py`
- **Install dependencies**: `pip install -r requirements.txt`
- **Run with verbose logging**: `python3 main.py -v`
- **Specify custom log file**: `python3 main.py -l custom.log`
- **List available door groups**: `python3 main.py --list-door-groups`
### Configuration Setup
- **Setup configuration**: `cp unifi.conf.example unifi.conf` then edit with actual credentials
- **Configuration file**: `unifi.conf` (contains API tokens, URLs, and settings)
## Architecture Overview
### Core Components
1. **main.py** - Entry point and orchestration
- Handles command-line arguments and logging setup
- Coordinates all managers and performs cross-system verification
- Implements `verify_across_systems()` for data consistency checks
2. **unifi_access.py** - UniFi Access API integration
- `UnifiAccessManager` class handles all UniFi Access operations
- Creates/deletes visitors, assigns PIN codes, manages door group access
- Processes reservations and maintains visitor lifecycle
3. **hostex_api.py** - Hostex API integration
- `HostexManager` fetches reservations from Hostex booking platform
- Simple API wrapper for reservation data
4. **ics_parser.py** - Airbnb ICS calendar parsing
- `ICSParser` processes Airbnb calendar feeds
- Extracts reservation data and PIN codes from ICS events
5. **notification.py** - Simplepush notifications
- `NotificationManager` sends status updates and alerts
- Configurable notification system for operational updates
6. **config.py** - Configuration management
- Centralizes configuration loading from `unifi.conf`
- Handles API credentials, timing settings, and feature flags
7. **utils.py** - Shared utilities
- Logging setup and configuration
### Data Flow Architecture
```
Hostex API ──┐
├──► Cross-Verification ──► UniFi Access API
ICS Feed ────┘ (Visitor Management)
Simplepush Notifications
```
### Key Integration Points
- **Reservation Sources**: Supports both Hostex API and Airbnb ICS feeds
- **PIN Code Generation**: Uses last N digits of guest phone numbers
- **Cross-Verification**: Matches reservations across systems to detect discrepancies
- **Visitor Lifecycle**: Automatically creates visitors for upcoming stays, deletes past/completed visits
- **Door Access**: Assigns visitors to configurable door groups in UniFi Access
## Configuration Structure
The `unifi.conf` file contains these key sections:
- `[UniFi]`: Access controller API endpoint and authentication token
- `[Hostex]`: Hostex API credentials (optional if using ICS only)
- `[Airbnb]`: ICS calendar feed URL (optional if using Hostex only)
- `[Door]`: Default door group ID for visitor access
- `[Visitor]`: Check-in/out times and PIN code settings
- `[Simplepush]`: Notification service configuration
- `[General]`: Logging and PIN code digit count
## Development Notes
### Dependencies
- `requests`: HTTP API calls to UniFi Access and Hostex
- `icalendar`: Parsing Airbnb ICS calendar feeds
- `urllib3`: HTTP utilities (with SSL warning suppression)
- `configparser`: Configuration file parsing
### Logging Strategy
- Comprehensive debug logging available with `-v` flag
- File-based logging for operational history
- Different log levels for console vs file output
### API Integrations
- **UniFi Access**: RESTful API for visitor management, requires authentication token
- **Hostex**: Booking platform API for reservation data
- **Simplepush**: Simple HTTP-based notification service
- **Airbnb ICS**: Calendar feed parsing for reservation extraction
### Testing and Verification
- Use `--list-door-groups` to verify UniFi Access connectivity and available door groups
- Run with `-v` flag to see detailed operation logs
- Check log files for historical operation data and error analysis

22
Dockerfile Normal file
View File

@ -0,0 +1,22 @@
# Use Python 3.11 slim image (supports amd64, arm64, arm/v7)
FROM python:3.11-slim
# Set working directory
WORKDIR /app
# Copy requirements and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY *.py ./
COPY unifi.conf ./
# Create logs directory
RUN mkdir -p /app/logs
# Set environment variables
ENV PYTHONUNBUFFERED=1
# Default command (can be overridden)
CMD ["python", "main.py"]

99
README-DOCKER.md Normal file
View File

@ -0,0 +1,99 @@
# Docker Setup for UniFi Access Airbnb Integration
## Quick Start
1. **Build and run continuously** (checks every 6 hours):
```bash
docker-compose up -d
```
2. **Run once manually**:
```bash
docker-compose --profile manual up unifi-access-airbnb-once
```
3. **View logs**:
```bash
docker-compose logs -f
# Or check the logs directory: ./logs/unifi_access_airbnb.log
```
## Configuration
- **Config file**: Edit `unifi.conf` on the host - it's mounted read-only into the container
- **Logs**: Persistent in `./logs/` directory
- **Timezone**: Set in docker-compose.yml (default: America/New_York)
## Automation Options
### Option 1: Continuous Container (Recommended)
```bash
docker-compose up -d
```
Runs every 6 hours automatically. Change interval by modifying `sleep 21600` in docker-compose.yml.
### Option 2: Cron Job + Manual Container
```bash
# Add to crontab to run daily at 8 AM:
0 8 * * * cd /path/to/project && docker-compose --profile manual up unifi-access-airbnb-once
```
### Option 3: Windows Task Scheduler
Create a scheduled task that runs:
```cmd
docker-compose --profile manual up unifi-access-airbnb-once
```
## Commands
- **Stop**: `docker-compose down`
- **Rebuild**: `docker-compose build`
- **View container status**: `docker-compose ps`
- **Interactive shell**: `docker-compose exec unifi-access-airbnb sh`
## Raspberry Pi Deployment
### Compatibility
**Raspberry Pi 4/5** (ARM64) - Full support
**Raspberry Pi 3B+** (ARM32/ARMv7) - Full support
**Raspberry Pi Zero 2 W** (ARM64) - Works but slower
### Pi-Specific Setup
```bash
# 1. Install Docker (if not already installed)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker pi
# 2. Install docker-compose
sudo apt update
sudo apt install docker-compose-plugin
# 3. Clone and run your project
git clone <your-repo>
cd unifi-access-airbnb
docker-compose up -d
```
### Performance Notes
- **Pi 4/5**: Excellent performance, recommended for production
- **Pi 3B+**: Good performance, slightly slower container startup
- **Pi Zero 2**: Functional but slower, consider running less frequently
### Power Management
For reliable operation on Pi:
```yaml
# Add to docker-compose.yml services section:
restart: always
deploy:
resources:
limits:
memory: 128M
```
## Troubleshooting
- **Check logs**: `docker-compose logs unifi-access-airbnb`
- **Test config**: `docker-compose --profile manual up unifi-access-airbnb-once`
- **Network issues**: Ensure container can reach UniFi controller IP (10.0.1.20)
- **Pi-specific**: Check `docker --version` and ensure Docker is running: `sudo systemctl status docker`

View File

@ -84,6 +84,62 @@ The script performs several verification checks:
- Reports discrepancies in dates or guest information
- Monitors UniFi Access visitor status
## Docker Deployment
For easy deployment and automation, this project includes Docker support:
### Quick Start with Docker
```bash
# Build and run continuously (checks every 6 hours)
docker-compose up -d
# Run once manually
docker-compose --profile manual up unifi-access-airbnb-once
# View logs
docker-compose logs -f
```
See [README-DOCKER.md](README-DOCKER.md) for complete Docker setup instructions.
### Raspberry Pi Support
The Docker container runs perfectly on Raspberry Pi (ARM64/ARM32). Simply:
```bash
# On Raspberry Pi
docker-compose up -d
```
Docker automatically pulls the correct architecture. See [README-DOCKER.md](README-DOCKER.md) for Pi-specific notes.
## Future Goals
### UniFi Protect Integration
Plans to extend this project with UniFi Protect video recording capabilities:
**Required Hardware:**
- UniFi Gateway Max (UDM-Pro Max) with built-in NVR
- OR UniFi Cloud Key Gen2+ with Protect
**Planned Features:**
- **Guest Check-in Recording**: Automatically start recording when guests arrive
- **Stay Duration Recording**: Record during entire guest stay period
- **Checkout Verification**: Capture departure recordings
- **Incident Documentation**: Archive recordings for property protection
- **Guest Privacy**: Automatic recording pause/resume based on occupancy
**Implementation Ideas:**
- Integrate with UniFi Protect API for camera control
- Coordinate recording schedules with visitor access periods
- Provide guest notification of recording periods (legal compliance)
- Archive system for easy retrieval of guest-specific recordings
**Benefits:**
- Property protection during guest stays
- Incident documentation and liability protection
- Automated recording management tied to booking system
- Enhanced security without manual camera management
This would create a complete property automation ecosystem: **Access Control + Video Security** synchronized with your Airbnb bookings.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
@ -94,4 +150,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
If you encounter any issues or have questions:
1. Check the logs using verbose mode
2. Review your configuration file
3. Open an issue on GitHub with relevant logs and details```
3. Open an issue on GitHub with relevant logs and details

36
docker-compose.yml Normal file
View File

@ -0,0 +1,36 @@
version: '3.8'
services:
unifi-access-airbnb:
build: .
container_name: unifi-access-airbnb
restart: unless-stopped
volumes:
# Mount config file (edit this on host)
- ./unifi.conf:/app/unifi.conf:ro
# Mount logs directory for persistence
- ./logs:/app/logs
environment:
- TZ=America/New_York # Set your timezone
# Resource limits for Raspberry Pi compatibility
deploy:
resources:
limits:
memory: 128M
reservations:
memory: 64M
# Run every 6 hours by default
command: sh -c "while true; do python main.py; sleep 21600; done"
# Alternative: Run once and exit (for cron-like usage)
unifi-access-airbnb-once:
build: .
container_name: unifi-access-airbnb-once
profiles:
- manual # Only start with: docker-compose --profile manual up
volumes:
- ./unifi.conf:/app/unifi.conf:ro
- ./logs:/app/logs
environment:
- TZ=America/New_York
command: python main.py -v

View File

@ -16,10 +16,10 @@ class UnifiAccessManager:
self.logger.debug(f"Loaded default_door_group_id from config: {self.default_door_group_id}")
if not self.default_door_group_id:
self.logger.warning("default_door_group_id is not set in config. Attempting to fetch available door groups.")
self.set_default_door_group()
self.logger.error("default_group_id is not set in config. Please set it to your door device ID.")
raise ValueError("default_group_id is required in config")
else:
self.logger.debug(f"Initialized with default_door_group_id: {self.default_door_group_id}")
self.logger.debug(f"Initialized with door device ID: {self.default_door_group_id}")
def set_default_door_group(self):
door_groups = self.fetch_door_groups()
@ -50,7 +50,7 @@ class UnifiAccessManager:
"resources": [
{
"id": self.default_door_group_id,
"type": "door_group"
"type": "door"
}
]
}
@ -233,6 +233,7 @@ class UnifiAccessManager:
return bool(self.changes['added'] or self.changes['deleted'])
def fetch_door_groups(self):
# Try door_groups first, then user_groups if empty
url = f"{self.api_host}/api/v1/developer/door_groups"
headers = {
"Authorization": f"Bearer {self.api_token}",
@ -240,6 +241,7 @@ class UnifiAccessManager:
}
response = requests.get(url, headers=headers, verify=False)
self.logger.debug(f"Fetch door groups API response status code: {response.status_code}")
self.logger.debug(f"Fetch door groups API response content: {response.text}")
if response.status_code == 200:
data = response.json()