motion_reader.py is a Motion event integration wrapper that processes Vaillant LCD display images and outputs structured JSON for easy integration into bash scripts and event handlers.
Features:
- Single-line JSON output (stdout only)
- Comprehensive error handling
- Bash-friendly design (command substitution compatible)
- Confidence threshold support
- Exit code signals (0=success, 1=error)
# Activate virtual environment
source venv/bin/activate # Linux/macOS
# or
venv\Scripts\activate # Windows
# Ensure dependencies are installed
pip install -r requirements.txtmotion_reader.py- Main wrapper scriptlcd_reader/- Deep learning inference systemlcd_reader/models_sklearn/- Trained models (7 .pkl files)
# Basic usage
python motion_reader.py --filename /path/to/image.jpg
# With confidence threshold (optional)
python motion_reader.py --filename /path/to/image.jpg --min-confidence 0.95#!/bin/bash
# Capture JSON output
METADATA=$(python motion_reader.py --filename "${IMAGE_PATH}" 2>/dev/null)
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "Success: ${METADATA}"
# Parse with jq (if available)
TEMP=$(echo "${METADATA}" | jq -r '.temperature')
echo "Temperature: ${TEMP}°C"
else
echo "Error: ${METADATA}"
ERROR_MSG=$(echo "${METADATA}" | jq -r '.error.message')
echo "Error: ${ERROR_MSG}"
fi#!/bin/bash
# Motion on_picture_save event handler
PYTHON_BIN="/path/to/venv/bin/python"
READER_SCRIPT="/path/to/motion_reader.py"
IMAGE_PATH="$1" # Motion passes filename as first argument
# Process LCD reading
METADATA=$("${PYTHON_BIN}" "${READER_SCRIPT}" --filename "${IMAGE_PATH}" 2>/dev/null)
# Log to syslog with metadata
logger -t "camera/event" "{\"event\":\"motion_detected\",\"metadata\":${METADATA}}"
# Send to monitoring system
curl -X POST http://monitoring.local/api/events \
-H "Content-Type: application/json" \
-d "{\"source\":\"heater_cam\",\"data\":${METADATA}}"{
"temperature": 45,
"isGasBurning": true,
"isHeating": true,
"isHotWater": true,
"isInternalPumpRunning": true,
"isGasValveOpened": true
}Field Descriptions:
temperature: Integer (degrees Celsius)isGasBurning: Boolean - Burn/flame icon stateisHeating: Boolean - Heating radiator icon stateisHotWater: Boolean - Hot water faucet icon stateisInternalPumpRunning: Boolean - Pump/circulation icon stateisGasValveOpened: Boolean - Gas valve icon state
Exit Code: 0
{
"error": {
"message": "File not found",
"description": "The specified image file does not exist: /path/to/image.jpg",
"filename": "/path/to/image.jpg",
"context": {
"error_type": "FileNotFoundError"
}
}
}Field Descriptions:
error.message: Brief error summaryerror.description: Detailed error explanationerror.filename: Path to the problematic fileerror.context: Additional debugging information
Exit Code: 1
| Error Type | Message | Cause |
|---|---|---|
| FileNotFoundError | File not found | Image file doesn't exist |
| PermissionError | Permission denied | Cannot read image file |
| ConfigurationError | LCD reader not found | Missing lcd_reader directory |
| ImportError | Cannot import LCD reader | Missing Python dependencies |
| InitializationError | Cannot initialize LCD reader | Missing model files |
| ProcessingError | Image processing failed | Invalid image or processing error |
| Low confidence | Recognition confidence below threshold | Predictions don't meet --min-confidence |
Full path to the LCD image file.
python motion_reader.py --filename /var/lib/motion/snapshot.jpgMinimum confidence threshold for predictions (0.0-1.0). If any prediction falls below this threshold, returns an error.
# Require 95% confidence
python motion_reader.py --filename image.jpg --min-confidence 0.95Default: 0.0 (no filtering)
| Metric | Value |
|---|---|
| Inference time | <10ms per image |
| Model loading time | ~2 seconds (one-time) |
| Overall accuracy | 95% |
| Per-task accuracy | 98.6% |
| Average confidence | 98-99% |
Cause: Python dependencies not installed or wrong Python interpreter
Solution:
# Ensure virtual environment is active
source venv/bin/activate
python motion_reader.py --filename image.jpg
# Or use the venv Python directly
/path/to/venv/bin/python motion_reader.py --filename image.jpgCause: Missing trained models
Solution:
# Check models exist
ls lcd_reader/models_sklearn/*.pkl
# Should show 7 files:
# digit1_mlp.pkl, digit2_mlp.pkl, burn_mlp.pkl,
# heating_mlp.pkl, hotwater_mlp.pkl, pump_mlp.pkl, gasvalve_mlp.pkl
# If missing, retrain:
python lcd_reader/train_sklearn.py --task allCause: Image doesn't contain a visible LCD display, or display detection failed
Solution:
- Verify image contains clear LCD display
- Check image quality and lighting
- Manually extract LCD region if needed
Cause: OpenCV or other libraries printing to stderr
Solution:
# Redirect stderr to suppress warnings
METADATA=$(python motion_reader.py --filename image.jpg 2>/dev/null)Cause: Predictions don't meet confidence threshold
Solution:
- Lower the threshold (e.g., 0.90 instead of 0.95)
- Improve image quality (better lighting, clearer LCD)
- Retrain models with more diverse data
- Check which specific fields have low confidence in error context
Add to /etc/motion/motion.conf:
# Execute on picture save
on_picture_save /path/to/process_lcd.sh %f
/path/to/process_lcd.sh:
#!/bin/bash
METADATA=$(/path/to/venv/bin/python /path/to/motion_reader.py --filename "$1" 2>/dev/null)
if [ $? -eq 0 ]; then
logger -t "heater_monitor" "LCD reading: ${METADATA}"
fi*/5 * * * * /path/to/capture_and_process.shcapture_and_process.sh:
#!/bin/bash
IMAGE="/tmp/heater_snapshot_$(date +%s).jpg"
fswebcam -r 1920x1080 --no-banner "$IMAGE"
RESULT=$(/path/to/venv/bin/python /path/to/motion_reader.py --filename "$IMAGE" 2>/dev/null)
echo "$RESULT" >> /var/log/heater_readings.jsonl
rm "$IMAGE"- Virtual environment created and dependencies installed
- All 7 model files present in
lcd_reader/models_sklearn/ - Integration script tested with sample images
- Error handling tested (missing files, invalid images)
- Logging configured (successful readings and errors)
- Monitoring alerts set up (for low confidence or errors)