Automatically manages day/night mode transitions and triggers autofocus on Dahua cameras at optimal times.
Dahua cameras with motorized zoom lenses can go out of focus when switching between day and night modes (when the IR cut filter engages/disengages). This is especially problematic for LPR (License Plate Recognition) cameras where:
- The optimized exposure settings result in very dark night images
- The camera's auto day/night switch happens when it's too dark for autofocus to work properly
Instead of relying on the camera's automatic day/night switching, this script:
- Takes full control of day/night mode transitions via
DayNightColorsetting - Uses sunrise/sunset times (via astral library) to schedule transitions
- Triggers transitions early - before sunset and after sunrise when there's still good light
- Runs autofocus during each transition when lighting conditions are optimal
- Preserves your settings - your configured gain, exposure, aperture, etc. are not modified
- Cameras are set to forced Day or Night mode (
DayNightColor=1or2) - Script calculates optimal transition times based on your location's sunrise/sunset
- Before sunset (default: 30 min before, while still light): forces Night mode + autofocus
- After sunrise (default: 30 min after, with good light): forces Day mode + autofocus
- Your
VideoInOptionssettings (gain, exposure, etc.) are preserved - only the mode switching is controlled
DayNightColor=0→ Auto (camera decides - NOT used by this script)DayNightColor=1→ Day (Color mode, IR cut filter engaged)DayNightColor=2→ Night (B&W mode, IR cut filter disengaged)
- Python 3.9+ (for
zoneinfo) requestslibraryastrallibrary (for sunrise/sunset calculation)
pip install requests astralmkdir -p ~/.config/dahua-focus-managercp credentials.example ~/.config/dahua-focus-manager/credentials
# Edit with your actual credentialsThe credentials file format:
DAHUA_USER=admin
DAHUA_PASS=your_password_here
Credentials are searched in this order:
~/.config/dahua-focus-manager/credentials~/.dahua_creds/etc/dahua-focus-manager/credentials
cp config.example.json ~/.config/dahua-focus-manager/config.json
# Edit with your camera IPs and locationExample config:
{
"cameras": [
{"name": "front_door", "ip": "192.168.1.100"},
{"name": "back_yard", "ip": "192.168.1.101"}
],
"location": {
"latitude": 45.0,
"longitude": -93.0,
"timezone": "America/Chicago"
},
"night_transition_offset": -30,
"day_transition_offset": 30,
"poll_interval": 60,
"autofocus_wait": 15,
"session_refresh_interval": 120,
"health_check_file": "/tmp/dahua_focus_manager_health",
"brightness_log_file": "/tmp/dahua_brightness_log.csv"
}| Option | Default | Description |
|---|---|---|
cameras |
- | List of cameras with name and ip |
location.latitude |
45.0 | Your latitude for sunrise/sunset calculation |
location.longitude |
-93.0 | Your longitude (negative for West) |
location.timezone |
America/Chicago | Your timezone (IANA format) |
night_transition_offset |
-30 | Minutes relative to sunset (negative = before) |
day_transition_offset |
30 | Minutes relative to sunrise (positive = after) |
poll_interval |
60 | Seconds between time checks |
autofocus_wait |
15 | Seconds to wait for autofocus to complete |
session_refresh_interval |
120 | Seconds between session keepalives |
health_check_file |
/tmp/dahua_focus_manager_health | Path for health check JSON |
brightness_log_file |
/tmp/dahua_brightness_log.csv | Path for brightness sensor CSV log |
DAHUA_CONFIG_DIR- Override config directory (default:~/.config/dahua-focus-manager)
python3 dahua_focus_manager.py- Copy the script:
sudo cp dahua_focus_manager.py /usr/local/bin/- Copy and edit the service file:
sudo cp dahua-focus-manager.service /etc/systemd/system/
# Edit the service file to set the correct User
sudo nano /etc/systemd/system/dahua-focus-manager.service- Reload systemd and enable the service:
sudo systemctl daemon-reload
sudo systemctl enable dahua-focus-manager
sudo systemctl start dahua-focus-manager- Check status:
sudo systemctl status dahua-focus-manager
journalctl -u dahua-focus-manager -fThe script writes a JSON health check file (default: /tmp/dahua_focus_manager_health) every 60 seconds:
{
"timestamp": "2024-01-15T18:30:00.000000",
"sunrise": "2024-01-15T07:42:00.000000",
"sunset": "2024-01-15T17:10:00.000000",
"day_transition": "2024-01-15T08:12:00.000000",
"night_transition": "2024-01-15T16:40:00.000000",
"current_target_mode": "night",
"cameras": [
{
"name": "front_door",
"ip": "192.168.1.100",
"current_mode": "night",
"session_active": true,
"consecutive_failures": 0,
"last_autofocus": "2024-01-15T16:40:30.000000"
}
]
}The script logs brightness sensor data every 60 seconds to a CSV file (default: /tmp/dahua_brightness_log.csv). This data can be used to:
- Analyze light patterns throughout the day
- Optimize transition timing based on actual brightness levels
- Detect anomalies like storms that cause early darkness
CSV columns:
timestamp- ISO format timestamp with timezonecamera- Camera namebrightness_0,brightness_1- Brightness sensor values (0-100+)gain_0,gain_1- Current gain values (higher = darker conditions)exposure_0,exposure_1- Current exposure valuesdnc_mode- Current IR filter state (0=Night, 1=Day)need_fill_light- Camera's assessment if more light is needed (0/1)
Example analysis:
# View recent brightness data
tail -20 /tmp/dahua_brightness_log.csv
# Check readings around transition times
grep -E 'T(07|08|16|17):' /tmp/dahua_brightness_log.csv- Dahua IPC-HFW5442H-ZHE (and similar models with motorized zoom)
- Verify the camera IP is correct and reachable
- Check credentials in your credentials file
- Ensure the camera's web interface is accessible
- Adjust
night_transition_offsetto trigger earlier (e.g., -45 for 45 min before sunset) - Adjust
day_transition_offsetto trigger later (e.g., 45 for 45 min after sunrise) - Increase
autofocus_waitif autofocus needs more time
- Verify your latitude and longitude are correct
- Check timezone setting matches your location
- Longitude should be negative for Western Hemisphere
- This is expected! The script uses
DayNightColorto force day/night mode - Your configured settings (gain, exposure, etc.) are still applied
- The camera UI may show "Custom" but your Day/Night profile settings are preserved
MIT