Building a CCTV Spot Monitor with Weather Updates

A dedicated spot monitor for my front door CCTV camera feed, complete with a weather report overlay

Building a CCTV Spot Monitor with Weather Updates
Security Camera view with Weather overlay

Repurposing old technology is a fun and cost-effective hobby. One recent project involved converting an unused laptop into a dedicated spot monitor for my front door CCTV camera feed, complete with a weather report overlay. The result was both practical and customizable, and it all came together with a little Bash and PHP scripting.

When we replaced our main entrance door, certain family members opted against installing a peep-hole (door viewer). Due to our harsh Canadian winters, the peep-hole is an area for condensation build up, making the feature practically useless. We had installed security cameras around the property earlier, so I figured I would create an internal spot monitor to see outside while maintaining our privacy.

A spot monitor acts as a local, always-on display for your security camera feed - handy for checking live video at a glance. Rather than investing in new hardware, I wanted to use what I already had. Old laptops make ideal candidates: built-in screens, minimal power draw, and enough processing power for simple tasks.

The Hardware

The core of this CCTV spot monitor is a repurposed Lenovo 20BV000AUS T450 laptop, which underwent several unique physical modifications to meet the project’s needs and maximize compactness:

  • Bottom Panel & Hinges Removed: The bottom cover and the original display hinges were permanently removed, reducing unnecessary bulk and improving access to internal components for airflow and maintenance.
  • Screen Folded & Components Repositioned: By carefully folding the display a full 360 degrees, I was able to tuck the mainboard and components directly behind the screen itself—effectively condensing the laptop into a slim, monitor-like form factor perfect for mounting.
  • Custom Fastening: Holding the modified chassis together required drilling machine screws through both halves of the body, ensuring rigidity and long-term durability even after removing the standard fasteners and covers.
  • Minimalist Storage & Operating System:
    • Storage duties are handled by a KINGSTON SNV425S 64GB SSD—more than sufficient for the stripped-down requirements of our CCTV monitor. This was a component that wasn't getting any use before this project.
    • The software environment is equally lean: a minimal install of Ubuntu 24.10 (with no bulky desktop environment or graphical apps), just enough to reliably run the required scripts and video utilities.
  • Practical Mounting Solution: Instead of a bulky stand, three wide velcro strips were added across the keyboard area. This allowed me to easily secure the device directly onto the side of our refrigerator, transforming unused vertical space into a practical tech solution.
  • Wireless, mostly: The laptop has been configured to log in immediately and to use Wi-Fi. The only cable that is still required is the power/charging cord. When power is lost, my Wi-Fi access point has battery backup, as well as my security system. This means my window to the outside is accessible, even without internet.

These thoughtful hacks reimagined an outdated laptop and turned it into a robust, space-saving, always-on appliance dedicated solely to security and weather monitoring. This approach not only breathed new life into old gear but also ensured the project stayed budget-friendly and adaptable to any household setup.

The Bash Script

Here's the core securitymonitor.sh Bash script I used to bring it all together:

#!/bin/bash

cd /home/monitor/

# Function to handle errors
handle_error() {
    local command="$1"
    local error="$2"
    echo "An error occurred in command: $command" >&2
    echo "Error message: $error" >&2
    # Additional error handling logic
}

# Set the error handler function
trap 'handle_error "$BASH_COMMAND" "$?"' ERR

# Download the current weather snapshot
wget -O current_weather.png http://homeserver/weather/weather.php

# Display CCTV feed with weather overlay
mpv --profile=low-latency --video-rotate=180 --untimed --no-cache --audio-buffer=0 --lavfi-complex="[vid1][vid2]overlay=main_w-overlay_w-1[vo]" "rtsp://xxxx:yyyy@zz.zz.zz.zz:554/cam/realmonitor?channel=1&subtype=1" --external-file="current_weather.png"

# (Optional fallback) Display the CCTV feed without the weather overlay
mpv --profile=low-latency --video-rotate=180 --untimed --no-cache --audio-buffer=0 "rtsp://xxxx:yyyy@zz.zz.zz.zz:554/cam/realmonitor?channel=1&subtype=1"

# (Fallback image display) If the stream fails, show a placeholder image for 60 seconds
mpv --image-display-duration=60 --video-rotate=180 "/home/monitor/camera_not_connect.png"

First, I have configured error handling as this script is later set as a systemd service. If any of the commands fail, I need the command logged to review what went wrong. BUT I still want fall-back instead of the script failing and then systemd immediately trying to restart the service. The handle_error() function along with trap is used to make systemd operate the way I intend.

I use wget to fetch an image of the weather overlay from my home server, and save that to ~\current_weather.png

Next, I use mpv media player to load the RTSP video stream from my network video recorder, overlay the weather image, and rotate the video 180 degrees (more on that soon). mpv is an amazing open-source project: you do not need a desktop environment to display a file or feed, as the software can use direct hardware access to your display. What a champ! 🏆

Video rotation of 180 degrees (--video-rotate=180) was a software solution to a physical problem: The velcro strips were affixed to the palm area of the T450 keyboard. In the strange configuration, gravity would pull the top of the screen away from my mounting surface. Physically rotating the unit would prevent this issue, thus I needed to also rotate the video stream.

I have mpv called three times in this script: the first overlays the image with the RTSP feed, and displays. In case wget fails and my home server doesn't respond or is otherwise inaccessible, mpv will not be able to open current_weather.png, and fail. (Hence error handling!) The second mpv call is just the RTSP feed without the overlay. Finally, if my Wi-Fi access point is down, the laptop will not be able to reach anything on the network. In this third and final case, MPV is being used to display a "camera not connected" image for 60 seconds. After the 60 seconds, the script will exit cleanly to let systemd restart the service.

In both of the RTSP feeds, I am using subtype=1 in the URL. This is to load the lower-resolution video feed for displaying. I found this to be best for real-time video playback. I just dislike a pretty picture with a delay!

"Monitor could not connect" wallpaper

The Weather Service

Canada is a big place, and we have a lot of natural resources. Our provincial and federal governments have made it stupid easy for Canadians to access data about our lakes, landscapes, railways, - and what's more relevant to this post - Weather! 🌤️
If you are Canadian, access https://open.canada.ca/ to search for the data that would interest you. In my case, I accessed Environment Canada's Weather XML data service, found at https://dd.weather.gc.ca/. This link provides access to download current observations, forecasts, historical data, and even hurricane shapefiles!

It took a while to configure my home server PHP to read these XML files and generate a PNG image. Previously, Environment Canada provided one endpoint to receive the most current forecast and observations. As of June 2025 the service modified their directory scheme; now, forecasts are recorded by UTC date, then UTC hour, then by observation site code in English and French.

The PHP Script

As I have my securitymonitor.sh script executed every ten minutes by systemd, I do not need to download the same hourly forecast six times every hour. Therefore, I have configured my PHP script to read the last updated timestamp of the forecast file before fetching new data.

To avoid the horrors of looking at my janky code, I'm not going to post the PHP here. I would however like to acknowledge the very pretty icons found on GitHub made by 'Makin-Things': Makin-Things/weather-icons 🌟

Just a weather overlay

The Systemd Service

To ensure the CCTV and weather overlay run seamlessly and recover automatically from crashes or reboots, I created a dedicated systemd service. This simple service definition guarantees that the script launches at system startup, restarts if interrupted, and always runs in the correct environment:

[Unit]
Description=Security Camera Feed
#StartLimitIntervalSec=300
#StartLimitBurst=11

[Service]
ExecStart=bash /home/monitor/securitymonitor.sh
ExecStop=/usr/bin/killall mpv
Type=simple
Environment="DISPLAY=:0"
RuntimeMaxSec=600s
Restart=always
RestartSec=2
User=monitor
StandardOutput=null
StandardError=null

[Install]
WantedBy=graphical.target

This provides automatic startup and restart. The service is enabled so it will start at boot, and will always try to restart if it stops, ensuring nearly continuous operation. As this service doesn't require any privileges, the script is run user the monitor user. When the service is set to restart in 600s (10 Minutes), the service will killall mpv processes, then wait 2 seconds before re-executing securitymonitor.sh. I don't need the logs unless I'm debugging, so I have both stdout and stderr set to null.

Remember in the securitymonitor.sh script that the fallback mpv image would only run for 1 minute? The script along with the service work in tandem: if everything is running normally, the feed will restart every 10 minutes to ensure there is minimal video latency, and when the feed is unavailable, will retry every minute.

With these three software components in place, the 'spot monitor' acts like a low-maintenance appliance with no user interaction necessary. (That is, until Environment Canada decides to change their data scheme again 🙄)

Final Thoughts

This project was an enjoyable convergence of hardware hacking, minimalist Linux configuration, and a focus on practical, visible results. By boldly modifying an old Lenovo laptop, stripping down the software to the essentials, and automating everything with systemd, I created a no-nonsense spot monitor with a reliable live camera feed, supplemented with weather context, and mounted conveniently near the chocolate milk.