diff --git a/ROADMAP.md b/ROADMAP.md index f21193c..e0a5b7f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -161,9 +161,11 @@ Using relative paths for portability across systems: --- -### Phase 3: Configuration Migration ✓ TODO +### Phase 3: Configuration Migration ✅ DONE (2025-12-27) **Goal**: Replace .ini file with JSON and environment variables +**Notes**: Templates created in Phase 1, successfully tested on Raspberry Pi + #### Tasks: 1. Create sensor mapping converter script - Read sensorer.ini @@ -234,9 +236,11 @@ config/sensorpajen.env debian/files debian/*.log debian/*.substvars -### Phase 4: Virtual Environment & Dependencies ✓ TODO +### Phase 4: Virtual Environment & Dependencies ✅ DONE (2025-12-27) **Goal**: Set up isolated Python environment +**Notes**: Tested on Raspberry Pi, paho-mqtt v2.x compatibility fixed + #### Tasks: 1. Create virtual environment: ```bash @@ -262,75 +266,34 @@ config/sensorpajen.env 4. Document virtual environment usage in README ---- - -### Phase 5: Bluetooth Permissions ✓ TODO +---✅ DONE (2025-12-27) **Goal**: Allow non-root user to access Bluetooth +**Notes**: Tested on Raspberry Pi with setcap on actual Python binary +### Phase 5: Bluetooth Permissions ✅ DONE (2025-12-27) +**Goal**: Allow non-root user to access Bluetooth + +**Notes**: Tested on Raspberry Pi with setcap on actual Python binary + #### Tasks: -1. Add user to bluetooth group: - ```bash - sudo usermod -a -G bluetooth fredrik - ``` +- ✅ Bluetooth capabilities set with setcap +- ✅ Documented in SETUP_ON_PI.md with correct readlink -f usage +- ✅ Tested successfully on Raspberry Pi -2. Set capabilities on Python interpreter (if needed): - ```bash - sudo setcap 'cap_net_raw,cap_net_admin+eip' .venv/bin/python3 - ```%h/sensorpajen - EnvironmentFile=%h/sensorpajen/config/sensorpajen.env - ExecStart=%h/sensorpajen/.venv/bin/python -m sensorpajen.main - Restart=always - RestartSec=10 - - # Bluetooth capabilities - AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN - - # Logging - StandardOutput=journal - StandardError=journal - SyslogIdentifier=sensorpajen - - [Install] - WantedBy=default.target - ``` - - Note: `%h` expands to the user's home directorycription=Sensorpajen - Bluetooth Temperature Sensor Monitor - After=network.target bluetooth.target - Wants=bluetooth.target - - [Service] - Type=simple - WorkingDirectory=/home/fredrik/dev/sensorpajen - EnvironmentFile=/home/fredrik/.config/sensorpajen/sensorpajen.env - ExecStart=/home/fredrik/dev/sensorpajen/.venv/bin/python -m sensorpajen.main - Restart=always - RestartSec=10 - - # Bluetooth capabilities - AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN - - # Logging - StandardOutput=journal - StandardError=journal - SyslogIdentifier=sensorpajen - - [Install] - WantedBy=default.target - ``` +--- -2. Install service (user service): - ```bash - mkdir -p ~/.config/systemd/user/ - cp systemd/sensorpajen.service ~/.config/systemd/user/ - systemctl --user daemon-reload - ``` +### Phase 6: Systemd Service Creation ✅ DONE (2025-12-27) +**Goal**: Create and configure systemd user service -3. Enable lingering (service runs without login): - ```bash - sudo loginctl enable-linger fredrik - ``` +**Notes**: +- User service for easier management (no sudo required) +- Service ready for installation on Raspberry Pi +- Comprehensive documentation provided -4. Document systemd commands in README +#### Tasks: +- ✅ Created systemd/sensorpajen.service +- ✅ Created systemd/README.md with full documentation +- ✅ Service management and troubleshooting guides included --- diff --git a/systemd/README.md b/systemd/README.md new file mode 100644 index 0000000..f80f01a --- /dev/null +++ b/systemd/README.md @@ -0,0 +1,254 @@ +# Systemd Service Installation + +## Installing Sensorpajen as a User Service + +This allows sensorpajen to run automatically on boot as your user (no sudo required for management). + +### Installation Steps + +#### 1. Install the Service File + +```bash +cd ~/sensorpajen + +# Create user systemd directory if it doesn't exist +mkdir -p ~/.config/systemd/user/ + +# Copy service file +cp systemd/sensorpajen.service ~/.config/systemd/user/ + +# Reload systemd to recognize the new service +systemctl --user daemon-reload +``` + +#### 2. Enable Lingering (Run Without Login) + +This allows your user services to run even when you're not logged in: + +```bash +# Enable lingering for your user +sudo loginctl enable-linger $USER + +# Verify it's enabled +loginctl show-user $USER | grep Linger +# Should show: Linger=yes +``` + +#### 3. Start and Enable the Service + +```bash +# Start the service now +systemctl --user start sensorpajen + +# Enable it to start on boot +systemctl --user enable sensorpajen + +# Check status +systemctl --user status sensorpajen +``` + +### Service Management Commands + +```bash +# Start the service +systemctl --user start sensorpajen + +# Stop the service +systemctl --user stop sensorpajen + +# Restart the service +systemctl --user restart sensorpajen + +# Check status +systemctl --user status sensorpajen + +# View logs (all) +journalctl --user -u sensorpajen + +# View logs (follow/tail) +journalctl --user -u sensorpajen -f + +# View logs (last 100 lines) +journalctl --user -u sensorpajen -n 100 + +# View logs (since specific time) +journalctl --user -u sensorpajen --since "1 hour ago" +journalctl --user -u sensorpajen --since "2025-12-27 10:00" + +# Enable service (start on boot) +systemctl --user enable sensorpajen + +# Disable service (don't start on boot) +systemctl --user disable sensorpajen +``` + +### Viewing Logs + +The service logs to systemd journal. View them with: + +```bash +# Live view (like tail -f) +journalctl --user -u sensorpajen -f + +# With timestamps +journalctl --user -u sensorpajen -f -o short-iso + +# Just today's logs +journalctl --user -u sensorpajen --since today +``` + +### Updating the Service + +After making changes to the code: + +```bash +# Pull latest changes +cd ~/sensorpajen +git pull origin master + +# Restart the service to apply changes +systemctl --user restart sensorpajen + +# Check it started correctly +systemctl --user status sensorpajen +``` + +After editing `sensorpajen.service`: + +```bash +# Copy updated service file +cp systemd/sensorpajen.service ~/.config/systemd/user/ + +# Reload systemd configuration +systemctl --user daemon-reload + +# Restart the service +systemctl --user restart sensorpajen +``` + +After editing configuration files: + +```bash +# Edit config +nano ~/sensorpajen/config/sensorpajen.env +# or +nano ~/sensorpajen/config/sensors.json + +# Restart service to reload config +systemctl --user restart sensorpajen +``` + +### Troubleshooting + +#### Service Won't Start + +```bash +# Check detailed status +systemctl --user status sensorpajen + +# Check logs for errors +journalctl --user -u sensorpajen -n 50 + +# Test the command manually +cd ~/sensorpajen +source .venv/bin/activate +export $(cat config/sensorpajen.env | grep -v '^#' | xargs) +python -m sensorpajen.main +``` + +#### Bluetooth Permission Errors + +Make sure capabilities are set on the Python binary: + +```bash +getcap $(readlink -f ~/.venv/bin/python3) +# Should show: cap_net_raw,cap_net_admin+eip + +# If not set: +sudo setcap 'cap_net_raw,cap_net_admin+eip' $(readlink -f ~/sensorpajen/.venv/bin/python3) +``` + +#### Service Doesn't Start on Boot + +```bash +# Check if service is enabled +systemctl --user is-enabled sensorpajen +# Should show: enabled + +# Check if lingering is enabled +loginctl show-user $USER | grep Linger +# Should show: Linger=yes + +# If not enabled: +systemctl --user enable sensorpajen +sudo loginctl enable-linger $USER +``` + +#### Environment Variables Not Loading + +```bash +# Verify environment file exists and is readable +cat ~/sensorpajen/config/sensorpajen.env + +# Check file permissions +ls -la ~/sensorpajen/config/sensorpajen.env + +# Test loading manually +export $(cat ~/sensorpajen/config/sensorpajen.env | grep -v '^#' | xargs) +env | grep MQTT +``` + +### Verifying Everything Works + +After installation: + +```bash +# 1. Check service is running +systemctl --user status sensorpajen + +# 2. Check logs show sensor data +journalctl --user -u sensorpajen -f + +# 3. Check MQTT messages are being published +mosquitto_sub -h 192.168.0.114 -u hasse -P casablanca -t "MiTemperature2/#" -v + +# 4. Reboot and verify it starts automatically +sudo reboot +# After reboot: +systemctl --user status sensorpajen +``` + +### Uninstalling the Service + +If you need to remove the service: + +```bash +# Stop and disable +systemctl --user stop sensorpajen +systemctl --user disable sensorpajen + +# Remove service file +rm ~/.config/systemd/user/sensorpajen.service + +# Reload systemd +systemctl --user daemon-reload + +# Optionally disable lingering +sudo loginctl disable-linger $USER +``` + +## Notes + +- **User Service**: Runs as your user, not root - more secure and easier to manage +- **Lingering**: Required for services to run when not logged in +- **Logs**: All output goes to systemd journal (journalctl) +- **Auto-restart**: Service restarts automatically on crashes +- **Environment**: Config loaded from `config/sensorpajen.env` +- **Working Directory**: Service runs from `~/sensorpajen` + +## Next Steps + +Once the service is working: +1. Monitor for a few days to ensure stability +2. Check logs occasionally: `journalctl --user -u sensorpajen --since yesterday` +3. Service will survive reboots and automatically restart on failures diff --git a/systemd/sensorpajen.service b/systemd/sensorpajen.service new file mode 100644 index 0000000..9a6942a --- /dev/null +++ b/systemd/sensorpajen.service @@ -0,0 +1,30 @@ +[Unit] +Description=Sensorpajen - Bluetooth Temperature Sensor Monitor +Documentation=https://github.com/yourusername/sensorpajen +After=network.target bluetooth.target +Wants=bluetooth.target + +[Service] +Type=simple +WorkingDirectory=%h/sensorpajen +EnvironmentFile=%h/sensorpajen/config/sensorpajen.env +ExecStart=%h/sensorpajen/.venv/bin/python -m sensorpajen.main +Restart=always +RestartSec=10 + +# Bluetooth capabilities (alternative to setcap) +# Note: This requires systemd to be run with proper permissions +# If this doesn't work, use setcap on the Python binary instead +#AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN + +# Logging +StandardOutput=journal +StandardError=journal +SyslogIdentifier=sensorpajen + +# Security +NoNewPrivileges=true +PrivateTmp=true + +[Install] +WantedBy=default.target