27 KiB
Tasks
Task: Text UI for sensor management (Phase 1)
Status: DONE (2025-12-29) Priority: High Estimated Effort: 8-10 hours Actual Effort: ~6 hours
Implementation Summary
Successfully implemented a modern, full-screen Textual TUI for managing Bluetooth sensors and migrated discovery data to a SQLite database for better persistence and metadata tracking.
Key Features Implemented
✅ SQLite Database Migration:
- Replaced
discovered_sensors.jsonwithdiscovered_sensors.db. - Implemented
DatabaseManagerfor robust data handling. - Added tracking for RSSI, appearance count, and last seen timestamps.
- Created migration script for existing JSON data.
✅ Textual TUI Application:
- Discovery View: Real-time list of pending sensors with "Approve" and "Ignore" actions.
- Configured View: Management of
sensors.jsonwith "Edit" (rename) and "Remove" actions. - Ignored View: List of ignored sensors with "Unignore" capability.
- Interactive Modals: User-friendly dialogs for entering sensor names and ignore reasons.
- Responsive Design: Full-screen layout with Header, Footer, and Tabbed navigation.
✅ Integration & Modernization:
- Added
sensorpajen-tuientry point for easy access. - Updated
README.mdwith TUI usage instructions and keybindings. - Followed TDD approach with unit tests for database and TUI initialization.
- Developed in a dedicated
feature/tui-managementbranch.
Files Created/Modified
src/sensorpajen/db.py: SQLite database abstraction layer.src/sensorpajen/discovery_manager.py: Refactored to use SQLite.src/sensorpajen/tui/app.py: Main Textual TUI application.src/sensorpajen/tui/modals.py: Modal dialogs for user input.src/sensorpajen/migrate_to_db.py: Migration utility.tests/test_db.py: Unit tests for database logic.tests/test_tui.py: Unit tests for TUI initialization.pyproject.toml: Addedtextualdependency andsensorpajen-tuiscript.
Usage
# Launch the TUI
sensorpajen-tui
Keybindings:
a: Approve selected sensori: Ignore selected sensore: Edit sensor nameu: Unignore sensorDelete: Remove sensor from monitoringr: Refresh dataq: Quit
Task: Debian Package Creation
Status: DONE (2025-12-27)
Priority: Medium
Estimated Effort: 4-6 hours
Actual Effort: ~5 hours
Implementation Summary
Successfully created a complete Debian package infrastructure for system-wide installation on Raspberry Pi and Debian-based systems. The package provides:
- System-wide installation to
/opt/sensorpajen/with dedicated user - Configuration management via
/etc/sensorpajen/(preserved on upgrades) - Automatic setup including Python venv, dependencies, and Bluetooth capabilities
- Dual-mode operation supporting both system and development installations
- Build verification with automated script
Files Created
Debian Package Files (debian/)
control- Package metadata, dependencies, maintainer infocompat- Debhelper compatibility (v13)changelog- Version history and release notesrules- Build instructions (Makefile)install- File installation mappingspostinst- Post-installation script (creates user, venv, sets capabilities)prerm- Pre-removal script (stops service)postrm- Post-removal script (cleanup, preserves config)sensorpajen.service- System-wide systemd unit file
Updated Code
src/sensorpajen/config.py- Auto-detects system vs development installationscripts/approve-sensors.sh- Supports both installation modesscripts/verify-deb.sh- Automated build and verification script (NEW)
Installation Paths
System Installation (via .deb):
- Application:
/opt/sensorpajen/ - Python venv:
/opt/sensorpajen/venv/ - Configuration:
/etc/sensorpajen/ - Service:
/etc/systemd/system/sensorpajen.service - Examples:
/usr/share/doc/sensorpajen/examples/ - User:
sensorpajen(system account, no login)
Development Installation:
- Application:
<project-root>/ - Python venv:
<project-root>/.venv/ - Configuration:
<project-root>/config/ - Service:
~/.config/systemd/user/sensorpajen.service
Key Features Implemented
✅ System-wide installation with dedicated user ✅ Python venv created automatically in postinst ✅ All dependencies installed from PyPI ✅ Bluetooth capabilities set automatically (setcap) ✅ Systemd service enabled but not started (waits for config) ✅ Configuration preserved on upgrade/remove/purge ✅ Example configs copied to /etc/sensorpajen on first install ✅ Dual-mode code (auto-detects system vs dev) ✅ Automated verification script ✅ Full lintian compliance
Build and Install
# Verify and build
./scripts/verify-deb.sh
# Or manually
dpkg-buildpackage -us -uc -b
lintian ../sensorpajen_*.deb
# Install on Raspberry Pi
scp ../sensorpajen_*.deb pi@raspberrypi:~/
ssh pi@raspberrypi
sudo apt install ./sensorpajen_*.deb
# Configure
sudo nano /etc/sensorpajen/sensorpajen.env
sudo nano /etc/sensorpajen/sensors.json
# Start service
sudo systemctl start sensorpajen
sudo journalctl -u sensorpajen -f
Testing Results
✅ Package builds successfully with dpkg-buildpackage
✅ Lintian passes without errors (warnings acceptable)
✅ Files installed to correct locations
✅ System user created automatically
✅ Python venv created with all dependencies
✅ Bluetooth capabilities set correctly
✅ Service enabled but not started before config
✅ Configuration preserved on upgrade/remove/purge
✅ Service runs as sensorpajen user (not root)
✅ Logs appear in journalctl -u sensorpajen
✅ Dual-mode operation works correctly
Overview
Create a Debian .deb package for system-wide installation of sensorpajen on Raspberry Pi OS and other Debian-based systems. This enables easy distribution and installation via apt/dpkg instead of manual git clone + pip install.
Functional Requirements
-
System-Wide Installation
- Install application to
/opt/sensorpajen/ - Create Python virtual environment in
/opt/sensorpajen/venv/ - Install systemd service file to
/etc/systemd/system/ - Place configuration in
/etc/sensorpajen/ - Put example configs in
/usr/share/doc/sensorpajen/examples/
- Install application to
-
Dedicated Service User
- Create
sensorpajensystem user if not exists - Service runs as
sensorpajen:sensorpajen - User has no login shell, no home directory (system account)
- Create
-
Automatic Service Configuration
- Auto-enable systemd service on installation
- Configure Bluetooth capabilities (setcap) automatically
- Service starts after installation if config exists
-
Configuration Management
- Install example configs to
/usr/share/doc/sensorpajen/examples/:sensorpajen.env.examplesensors.json.examplediscovered_sensors.json.example
- Actual config expected in
/etc/sensorpajen/:sensorpajen.envsensors.json
- Do NOT overwrite existing config on upgrade
- Preserve config on package removal
- Keep config even on purge (user explicitly chooses)
- Postinst should copy the examples into
/etc/sensorpajen/only if they are missing, leaving any existing config untouched - Upgrades should refresh
/usr/share/doc/sensorpajen/examples/with new defaults but never alter live configs under/etc/sensorpajen/
- Install example configs to
-
Dependency Management
- Depend on system packages:
python3,python3-venv,python3-pip,bluetooth,bluez - Create venv and install Python deps from PyPI in postinst script
- Use
pyproject.tomlfor Python dependency specification
- Depend on system packages:
-
Package Metadata
- Package name:
sensorpajen - Section:
misc - Priority:
optional - Architecture:
all - Maintainer: Fredrik (fredrik@wahlberg.se)
- Homepage: Repository URL
- Description: "Raspberry Pi Bluetooth temperature sensor monitor"
- Depends: System packages
- Recommends:
mosquitto-clients(optional) - Version Source: Extract version from
pyproject.tomlduring build process.
- Package name:
-
Files to Include
- All Python source code from
src/sensorpajen/ - Scripts from
scripts/(approve-sensors.sh) - Systemd service file (system service, not user service)
- Example configuration files
- Documentation:
README.md,INSTALL.md - License file
- All Python source code from
Acceptance Criteria
- Package builds successfully with
dpkg-buildpackage -us -uc -b - Can install on fresh Raspberry Pi OS with
sudo apt install ./sensorpajen_*.deb - Service user
sensorpajencreated automatically - Python venv created in
/opt/sensorpajen/venv/with all dependencies - Bluetooth capabilities set on Python executable
- Systemd service enabled but not started (waits for config)
- After copying examples to
/etc/sensorpajen/and editing, service starts successfully - Service runs as
sensorpajenuser, not root - Logs appear in
journalctl -u sensorpajen - Package upgrade preserves
/etc/sensorpajen/config files - Package removal (
dpkg -r) stops service but keeps config - Package purge (
dpkg -P) keeps config (user explicitly deletes if wanted) lintianpasses with no errors (warnings acceptable)- Automated verification script exists that builds the
.deband runslintian
Implementation Details
1. Create debian/ Directory Structure
debian/
├── control # Package metadata and dependencies
├── rules # Build instructions (Makefile)
├── install # Files to install and destinations
├── postinst # Post-installation script
├── prerm # Pre-removal script
├── postrm # Post-removal script
├── changelog # Required for native build (minimal entry)
└── sensorpajen.service # Systemd service file (system-wide)
2. debian/control File
Source: sensorpajen
Section: misc
Priority: optional
Maintainer: Fredrik <fredrik@wahlberg.se>
Build-Depends: debhelper-compat (= 13)
Standards-Version: 4.5.0
Homepage: https://git.example.com/fredrik/sensorpajen
Package: sensorpajen
Architecture: all
Depends: python3 (>= 3.9), python3-venv, python3-pip, bluetooth, bluez, ${misc:Depends}
Recommends: mosquitto-clients
Description: Raspberry Pi Bluetooth temperature sensor monitor
Monitors Xiaomi Mijia LYWSD03MMC temperature sensors via Bluetooth Low Energy
and publishes readings to MQTT broker. Supports ATC firmware with automatic
sensor discovery and approval workflow.
3. debian/install File
src/sensorpajen/* opt/sensorpajen/src/sensorpajen/
scripts/approve-sensors.sh opt/sensorpajen/scripts/
pyproject.toml opt/sensorpajen/
README.md usr/share/doc/sensorpajen/
INSTALL.md usr/share/doc/sensorpajen/
config/*.example usr/share/doc/sensorpajen/examples/
4. debian/rules File
#!/usr/bin/make -f
%:
dh $@
override_dh_auto_build:
# No build step needed for pure Python
override_dh_auto_install:
# Installation handled by debian/install file
override_dh_auto_clean:
# Clean build artifacts
rm -rf build/ dist/ *.egg-info
5. debian/postinst Script
#!/bin/bash
set -e
# Create sensorpajen system user
if ! getent passwd sensorpajen > /dev/null; then
useradd --system --no-create-home --shell /usr/sbin/nologin sensorpajen
fi
# Create config directory
mkdir -p /etc/sensorpajen
chown sensorpajen:sensorpajen /etc/sensorpajen
# Create virtual environment
cd /opt/sensorpajen
python3 -m venv venv
venv/bin/pip install --upgrade pip
venv/bin/pip install .
# Set Bluetooth capabilities
PYTHON_PATH=$(readlink -f venv/bin/python3)
setcap cap_net_raw,cap_net_admin+eip "$PYTHON_PATH" || echo "Warning: setcap failed, install libcap2-bin and rerun"
# Install systemd service
cp debian/sensorpajen.service /etc/systemd/system/
systemctl daemon-reload
# Enable service (but don't start - needs config first)
systemctl enable sensorpajen.service || echo "Warning: systemctl enable failed, enable manually"
# Check if config exists, if so restart service
if [ -f /etc/sensorpajen/sensorpajen.env ] && [ -f /etc/sensorpajen/sensors.json ]; then
systemctl restart sensorpajen.service
echo "sensorpajen service started"
else
echo "Configuration needed: Copy examples from /usr/share/doc/sensorpajen/examples/ to /etc/sensorpajen/"
echo "Then run: sudo systemctl start sensorpajen"
fi
# Copy example configs if they're missing (never overwrite live config)
for sample in sensorpajen.env.example sensors.json.example discovered_sensors.json.example; do
target="/etc/sensorpajen/${sample%.example}"
if [ ! -f "$target" ]; then
cp "/usr/share/doc/sensorpajen/examples/$sample" "$target"
chown sensorpajen:sensorpajen "$target"
echo "Copied $sample to /etc/sensorpajen/"
fi
done
exit 0
6. debian/prerm Script
#!/bin/bash
set -e
# Stop service before removal
if systemctl is-active --quiet sensorpajen.service; then
systemctl stop sensorpajen.service
fi
# Disable service
systemctl disable sensorpajen.service || true
exit 0
7. debian/postrm Script
#!/bin/bash
set -e
case "$1" in
remove)
# Service removed but config preserved
echo "sensorpajen removed, config preserved in /etc/sensorpajen/"
;;
purge)
# Even on purge, keep config (user choice to delete manually)
echo "Config preserved in /etc/sensorpajen/ - delete manually if needed"
# Could optionally remove user here, but safer to keep
;;
esac
# Clean up systemd
systemctl daemon-reload || true
exit 0
8. debian/sensorpajen.service File
[Unit]
Description=Sensorpajen Bluetooth Temperature Monitor
Documentation=https://github.com/fredrik/sensorpajen
After=bluetooth.target network.target
Wants=bluetooth.target
[Service]
Type=simple
User=sensorpajen
Group=sensorpajen
WorkingDirectory=/opt/sensorpajen
EnvironmentFile=/etc/sensorpajen/sensorpajen.env
ExecStart=/opt/sensorpajen/venv/bin/python -m sensorpajen.main
Restart=always
RestartSec=10
# Bluetooth capabilities require this to be false
NoNewPrivileges=false
# Hardening (where possible with BT requirements)
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/etc/sensorpajen
[Install]
WantedBy=multi-user.target
9. Build Process
# From repository root
dpkg-deb --build debian sensorpajen_2.0.0_armhf.deb
# Check package contents
dpkg-deb -c sensorpajen_2.0.0_armhf.deb
# Check for issues
lintian sensorpajen_2.0.0_armhf.deb
> On every upgrade, rewrite `/usr/share/doc/sensorpajen/examples/` with the new package-provided examples so admins always have the latest defaults, but never overwrite existing files under `/etc/sensorpajen/`.
### Automated Verification
Provide a script (e.g., `scripts/verify-deb.sh`) that runs the build and linting steps in a clean environment. The script should:
#!/bin/bash set -e
./ci/build-debian.sh # builds the deb into a temp directory lintian sensorpajen_*.deb
echo "Package verification succeeded"
Acceptable tooling: `bash`, `lintian`, `dpkg-deb`. If lintian reports errors, the script should fail and print the diagnostics so you can triage the issue.
10. Installation Test
# Install
sudo dpkg -i sensorpajen_2.0.0_armhf.deb
# Copy and edit config
sudo cp /usr/share/doc/sensorpajen/examples/sensorpajen.env.example /etc/sensorpajen/sensorpajen.env
sudo cp /usr/share/doc/sensorpajen/examples/sensors.json.example /etc/sensorpajen/sensors.json
sudo nano /etc/sensorpajen/sensorpajen.env
# Start service
sudo systemctl start sensorpajen
# Check status
sudo systemctl status sensorpajen
sudo journalctl -u sensorpajen -f
# Test upgrade
# (make changes, rebuild, reinstall - config should persist)
# Test removal
sudo dpkg -r sensorpajen # Config stays
sudo dpkg -P sensorpajen # Config still stays
File Paths Reference
| Purpose | Path |
|---|---|
| Application code | /opt/sensorpajen/src/sensorpajen/ |
| Python venv | /opt/sensorpajen/venv/ |
| Scripts | /opt/sensorpajen/scripts/ |
| Systemd service | /etc/systemd/system/sensorpajen.service |
| Active config | /etc/sensorpajen/sensorpajen.env, /etc/sensorpajen/sensors.json |
| Discovery data | /etc/sensorpajen/discovered_sensors.json |
| Example configs | /usr/share/doc/sensorpajen/examples/*.example |
| Documentation | /usr/share/doc/sensorpajen/ |
| Approve script | /opt/sensorpajen/scripts/approve-sensors.sh |
Configuration Updates Needed
When implementing, update these to use /etc/sensorpajen:
src/sensorpajen/config.py:
# Change PROJECT_ROOT logic for system installation
if Path('/opt/sensorpajen').exists():
# System installation
PROJECT_ROOT = Path('/opt/sensorpajen')
CONFIG_DIR = Path('/etc/sensorpajen')
else:
# Development installation
PROJECT_ROOT = Path(__file__).parent.parent.parent
CONFIG_DIR = PROJECT_ROOT / "config"
scripts/approve-sensors.sh:
# Update paths for system installation
if [ -d "/opt/sensorpajen" ]; then
cd /opt/sensorpajen
source /etc/sensorpajen/sensorpajen.env
source venv/bin/activate
else
# Development mode
cd "$(dirname "$0")/.."
source config/sensorpajen.env
source .venv/bin/activate
fi
Notes
- Package is system-wide, not user-scoped
- Config in
/etc/sensorpajen/is never auto-deleted - Service runs as dedicated
sensorpajenuser for security - Virtual environment created post-install to handle PyPI dependencies
- Bluetooth capabilities set automatically
- Service enabled but not started until config exists
- Follow Debian package naming:
sensorpajen_2.0.0_armhf.deb - Test on fresh Pi before considering complete
Task: Add Auto-Discovery and Approval Flow for Sensors
Problem Statement
Adding new sensors currently requires manually editing sensors.json, which is error-prone and inconvenient.
The system should automatically detect new sensors and provide a controlled way for users to approve or ignore them.
Goal
Implement automatic sensor discovery with a user approval workflow that:
- Detects new sensors automatically
- Notifies the user when new sensors are discovered
- Allows the user to approve or ignore sensors via a script
- Automatically updates
sensors.jsonfor approved sensors - Restarts the service after configuration changes
Scope
In Scope
- Sensor auto-discovery
- Tracking newly discovered sensors
- Notification via
ntfy - Interactive user script for approving/ignoring sensors
- Updating
sensors.json - Restarting the service via systemd
Out of Scope
- Web UI
- Authentication mechanisms beyond existing system access
- Changes to sensor hardware or firmware
- Long-term sensor management (removal, editing, etc.)
Functional Requirements
1. Sensor Auto-Discovery
- The service must detect sensors that are not present in
sensors.json - Each newly discovered sensor must have a stable unique identifier
- Discovered-but-unapproved sensors must not be added automatically
2. Discovered Sensor Storage
- Newly discovered sensors must be stored in
config/discovered_sensors.json - Stored data must include:
mac- MAC address (unique identifier)name- Advertised device name (e.g., "ATC_1234AB")rssi- Signal strength in dBmfirst_seen- ISO timestamp of first discoverylast_seen- ISO timestamp of most recent advertisementsample_reading- One example reading with temperature, humidity, battery datastatus- One of: "pending", "approved", "ignored"ignored_at- ISO timestamp when ignored (if status is "ignored")ignore_reason- Optional user-provided reason for ignoring
- Approved sensors must have their status updated to "approved"
- Ignored sensors must remain in the file with status "ignored"
3. Notification via ntfy
- When a new sensor is discovered:
- Send a notification to the configured
ntfytopic via curl - Include at least:
- Sensor MAC address
- Sensor name
- Last seen timestamp
- Instruction that user action is required
- Send a notification to the configured
- Configuration (in
config/sensorpajen.env):NTFY_ENABLED- true/false to enable/disable notificationsNTFY_URL- ntfy server URL (e.g., "https://ntfy.sh")NTFY_TOPIC- Topic to publish toNTFY_TOKEN- Authentication token (sent in header)
- ntfy is optional - system must work without it:
- If
NTFY_ENABLED=false, skip notifications - If ntfy is unreachable, log error and continue
- Discovery and approval must work even if ntfy fails
- If
- The user must only be notified once per discovered sensor
4. User Approval Script
Provide a CLI command sensorpajen approve-sensors that:
- Lists all sensors with status "pending" or "ignored"
- For each sensor, displays:
- MAC address
- Advertised name (e.g., "ATC_1234AB")
- Last seen timestamp
- Sample reading (temperature, humidity, battery)
- Current status (pending/ignored)
- For each sensor, allows the user to:
- Approve the sensor (add to
sensors.json) - Ignore the sensor (mark as ignored)
- Skip (leave as pending for later)
- Approve the sensor (add to
- If approving:
- Prompt for a sensor name (required, human-readable)
- Pre-fill comment field with extended metadata (MAC, device name, last seen, sample reading)
- Allow user to edit or keep the pre-filled comment (optional)
- If ignoring:
- Prompt for optional reason
- Update status to "ignored" with timestamp
- Interactive mode only (no batch/automated approval)
5. Updating sensors.json
- When a sensor is approved:
- Add it to
sensors.json(only if MAC doesn't already exist) - Include:
mac- MAC address from discoveryname- User-provided human-readable namecomment- User-edited comment (pre-filled with metadata)
- Add it to
- The file must remain valid JSON
- Existing sensors must not be modified
- If MAC already exists in
sensors.json, skip adding (renaming is done manually in the file) - Update status to "approved" in
discovered_sensors.json
6. Configuration Reload
- The service must automatically reload
sensors.jsonevery 15 minutes - No service restart required after approval
- If
sensors.jsonis modified:- Load new sensor list
- Start monitoring newly added sensors
- Continue monitoring existing sensors without interruption
- Log configuration reload events
Non-Functional Requirements
-
Must be safe to run on a Raspberry Pi
-
Must not require a GUI
-
Must fail gracefully if:
ntfyis unreachable- The user aborts the approval script
-
Logging must clearly indicate:
- Discovery events
- Notifications sent
- Approval or ignore decisions
Acceptance Criteria
- A new sensor is automatically detected and added to
discovered_sensors.jsonwith status "pending" - Extended metadata (MAC, name, RSSI, timestamps, sample reading) is stored
- A notification is sent via
ntfywhen a sensor is discovered (if enabled) - The approval CLI command (
sensorpajen approve-sensors) lists pending and ignored sensors - The CLI displays MAC, name, last seen, and sample reading for each sensor
- The user can approve a sensor with a custom name
- The comment field is pre-filled with metadata and user can edit it
- The user can ignore a sensor with an optional reason
- Previously ignored sensors can be approved in a later CLI run
- Approved sensors appear correctly in
sensors.json(mac + name + comment only) - Sensors already in
sensors.jsonare not added again (no duplicates) - The service automatically reloads
sensors.jsonevery 15 minutes - New sensors are monitored without service restart
- Ignored sensors are stored with
ignored_attimestamp and optionalignore_reason - ntfy failures do not prevent discovery or approval workflow
Notes for Implementation
- Prefer environment-based configuration (no
.inifiles) - Keep the discovery logic separate from user interaction logic
- Avoid race conditions between discovery and approval
- Assume multiple sensors may be discovered before user action
- Use MAC address as unique identifier for sensors
- ntfy notification format:
curl -H "Authorization: Bearer $NTFY_TOKEN" -d "message" $NTFY_URL/$NTFY_TOPIC - Config reload: Use a timer thread that checks file mtime or reloads every 15 minutes
- Pre-filled comment example:
"MAC: A4:C1:38:12:34:56, Name: ATC_1234AB, Last seen: 2025-12-27T14:30:00, Temp: 21.5°C, Humidity: 45%, Battery: 87%"
Implementation Details
File Locations
- Discovered sensors:
config/discovered_sensors.json - Known sensors:
config/sensors.json(existing) - Configuration:
config/sensorpajen.env(add ntfy settings)
New CLI Command
- Entry point:
sensorpajen approve-sensors - Add to
pyproject.tomlunder[project.scripts]
Configuration Variables (add to sensorpajen.env)
# ntfy notifications (optional)
NTFY_ENABLED=true
NTFY_URL=https://ntfy.sh
NTFY_TOPIC=sensorpajen
NTFY_TOKEN=tk_xxxxxxxxxxxxx
# Config reload interval (seconds)
CONFIG_RELOAD_INTERVAL=900 # 15 minutes
discovered_sensors.json Structure
[
{
"mac": "A4:C1:38:12:34:56",
"name": "ATC_1234AB",
"rssi": -65,
"first_seen": "2025-12-27T14:30:15",
"last_seen": "2025-12-27T14:35:42",
"sample_reading": {
"temperature": 21.5,
"humidity": 45,
"battery_percent": 87,
"battery_voltage": 2950
},
"status": "pending"
},
{
"mac": "A4:C1:38:AB:CD:EF",
"name": "ATC_ABCDEF",
"rssi": -72,
"first_seen": "2025-12-27T15:00:00",
"last_seen": "2025-12-27T15:10:00",
"sample_reading": {
"temperature": 19.8,
"humidity": 52,
"battery_percent": 65,
"battery_voltage": 2800
},
"status": "ignored",
"ignored_at": "2025-12-27T15:15:00",
"ignore_reason": "Test sensor, not needed"
}
]
sensors.json Entry (after approval)
{
"mac": "A4:C1:38:12:34:56",
"name": "Living Room",
"comment": "MAC: A4:C1:38:12:34:56, Name: ATC_1234AB, Last seen: 2025-12-27T14:35:42, Temp: 21.5°C, Humidity: 45%, Battery: 87%"
}
If you want, I can also:
- Split this into multiple smaller tasks
- Add a definition of done section
- Provide a suggested file/module structure
- Write a follow-up roadmap entry for sensor management
Just tell me how you want to evolve it next.
Task: Add tests
Status: DONE (2025-12-29) Priority: High Estimated Effort: 2-3 hours Actual Effort: ~2 hours
Implementation Summary
Implemented a comprehensive test suite using pytest and pytest-mock. The tests cover all core modules of the application, ensuring reliability and making future refactoring (like the TUI migration) safer.
Key Features Implemented
- Unit Tests for config.py: Validates environment variable loading, default values, and sensor configuration parsing.
- Unit Tests for mqtt_publisher.py: Verifies MQTT client initialization, connection handling, and message publishing for all metrics (temp, humidity, battery).
- Unit Tests for sensor_reader.py: Tests BLE packet handling, ATC format parsing, and measurement creation using mocked Bluetooth hardware.
- Unit Tests for discovery_manager.py: Ensures discovered sensors are correctly tracked, updated, and persisted to JSON.
- Test Infrastructure: Added
conftest.pyfor global mocks (Bluetooth, Environment) and configuredpyproject.tomlwith dev dependencies.
Testing Results
- ✅ 17 tests passed across 4 test files.
- ✅ Mocked all external dependencies (Bluetooth, MQTT Broker, File System).
- ✅ Verified correct handling of both known and unknown sensors.