From 8918bdd6b928d9b2d1f83327a3374fe4ce10d35b Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Tue, 9 Sep 2025 14:33:18 -0400 Subject: [PATCH] [bin] Fixing bin scripts and adding bus check --- bin/.bin/checkschoolbus.py | 111 +++++++++++++++++++++++++++++++ bin/.bin/checkworkmail.py | 2 +- bin/.bin/nyt | 2 +- bin/.bin/webcam-build-timelapses | 16 ++--- bin/.bin/webcam-capture | 14 ++-- 5 files changed, 128 insertions(+), 17 deletions(-) create mode 100755 bin/.bin/checkschoolbus.py diff --git a/bin/.bin/checkschoolbus.py b/bin/.bin/checkschoolbus.py new file mode 100755 index 0000000..dbc8d48 --- /dev/null +++ b/bin/.bin/checkschoolbus.py @@ -0,0 +1,111 @@ +#!/usr/bin/env -S uv run --script +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "requests", +# "opencv-python", +# "numpy", +# "ntfy", +# ] +# /// +import requests +import cv2 +import numpy as np +import time + +# URL for the video stream +stream_url = 'http://loge.local:8083/stream' +public_url = "https://mail.see.unbl.ink/stream" + +# Load a template image of a school bus (you need to have this template) +template = cv2.imread('/home/powellc/var/inbox/school_bus_template.jpg', 0) +w, h = template.shape[::-1] + +# Open the stream using OpenCV +cap = cv2.VideoCapture(stream_url) + +# Check if the stream opened successfully +if not cap.isOpened(): + print("Error: Could not open video stream.") + exit() + + # Configure ntfy server and topic +ntfy_server = "https://ntfy.unbl.ink" # Replace with your ntfy server +topic = "school-bus-alert" # Replace with your desired topic + +# Send notification function with custom server and topic +def send_ntfy_notification(title, message): + # Construct the full URL with topic (this is how ntfy expects the URL) + url = f"{ntfy_server}" + + # Payload for the notification + headers = {"Title": title} + payload = { + "topic": topic, + "message": message, + } + + # Send the POST request to the ntfy server + response = requests.post(url, json=payload, headers=headers) + + if response.status_code == 200: + print("Notification sent successfully.") + else: + print(f"Failed to send notification: {response.status_code} - {response.text}") + +while True: + # Read a frame from the stream + ret, frame = cap.read() + + if not ret: + print("Failed to capture frame.") + continue + + # Convert the frame to grayscale for template matching + gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + + # Perform template matching on the current frame + res = cv2.matchTemplate(gray_frame, template, cv2.TM_CCOEFF_NORMED) + threshold = 0.80 # Set your threshold for matching + loc = np.where(res >= threshold) + + # If a match is found, send a notification + if len(loc[0]) > 0: + print("Bus detected!") + + # Save the frame with bounding boxes to a file in /tmp + timestamp = time.strftime("%Y%m%d_%H%M") + filename = f"school_bus_detection_{timestamp}.jpg" + output_path = f"/media/photos/misc/school_bus/{filename}" + + cv2.imwrite(output_path, frame) + print(f"Frame with match locations saved to {output_path}") + + # Send notification using ntfy (with both title and message) + title = "School Bus Detected!" + message = f"Check the video feed at: {public_url}\nMatched image at https://files.lab.unbl.ink/school_bus/{filename}" + + # Send the notification with both title and message + send_ntfy_notification(title, message) + + # Draw bounding boxes on the detected matches + for pt in zip(*loc[::-1]): # Switch x and y for rectangle drawing + cv2.rectangle(frame, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2) + + + print("Pausing for 3 minutes to let the bus leave...") + time.sleep(180) # Sleep for 3 minutes (180 seconds) + else: + print("No bus found, sleeping for 2 seconds") + + # Optional: Display the frame with the match location (for debugging) + #for pt in zip(*loc[::-1]): + # cv2.rectangle(frame, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2) + + ## Display the frame (for debugging) + #cv2.imshow('Frame', frame) + + time.sleep(2) # two seconds so we don't spam the camera + # Break the loop on key press (e.g., 'q' to quit) + if cv2.waitKey(1) & 0xFF == ord('q'): + break diff --git a/bin/.bin/checkworkmail.py b/bin/.bin/checkworkmail.py index f57108a..6146906 100755 --- a/bin/.bin/checkworkmail.py +++ b/bin/.bin/checkworkmail.py @@ -22,7 +22,7 @@ import re # ---------------------- GMAIL_USER = os.getenv("GMAIL_USER", "your-email@gmail.com") GMAIL_APP_PASSWORD = os.getenv("GMAIL_APP_PASSWORD", "your-app-password") -NTFY_TOPIC = os.getenv("NTFY_TOPIC", "dev-notifications") +NTFY_TOPIC = os.getenv("NTFY_TOPIC", "KKddGQxVm2LoP0JF") NTFY_SERVER = os.getenv("NTFY_SERVER", "https://ntfy.sh") CHECK_INTERVAL = int(os.getenv("CHECK_INTERVAL", "60")) JIRA_SENDERS = ["jira@yourcompany.com", "jira@atlassian.net"] diff --git a/bin/.bin/nyt b/bin/.bin/nyt index dfd0acf..48a8b7c 100755 --- a/bin/.bin/nyt +++ b/bin/.bin/nyt @@ -1,5 +1,5 @@ #!/bin/bash -BASEDIR="/var/photos/misc/nytimes" +BASEDIR="/media/photos/misc/nytimes" DATE=$(date +"%Y-%m-%d") TMPFILE=/tmp/nyt.pdf OUTFILE=$BASEDIR/$DATE.jpg diff --git a/bin/.bin/webcam-build-timelapses b/bin/.bin/webcam-build-timelapses index c4134db..10282af 100755 --- a/bin/.bin/webcam-build-timelapses +++ b/bin/.bin/webcam-build-timelapses @@ -64,7 +64,7 @@ for cam in "${WEBCAMS[@]}"; do done # --- Update index.html --- -INDEX_HTML="$BASE_DIR/index.html" +INDEX_HTML="$BASE_DIR/timelapses.html" # Ensure file exists with basic structure if [[ ! -f "$INDEX_HTML" ]]; then @@ -87,19 +87,19 @@ fi # Build new day's section NEW_SECTION="

$YESTERDAY

" # Insert at the top of
-tmpfile=\$(mktemp) -awk -v section="\$NEW_SECTION" ' +tmpfile=$(mktemp) +awk -v section="$NEW_SECTION" ' /
/ { print; print section; next } { print } -' "\$INDEX_HTML" > "\$tmpfile" -mv "\$tmpfile" "\$INDEX_HTML" +' "$INDEX_HTML" > "$tmpfile" +mv "$tmpfile" "$INDEX_HTML" echo "📝 Updated index with $YESTERDAY timelapses (newest on top)" diff --git a/bin/.bin/webcam-capture b/bin/.bin/webcam-capture index 85dbd58..d17632b 100755 --- a/bin/.bin/webcam-capture +++ b/bin/.bin/webcam-capture @@ -5,11 +5,11 @@ if [ "$1" = "mailbox" ]; then fi if [ "$1" = "basement_table" ]; then host="loge.local" - port=8081 + port=8082 fi if [ "$1" = "frontyard" ]; then host="loge.local" - port=8082 + port=8081 fi if [ "$1" = "basement_tv" ]; then port=8081 @@ -24,19 +24,19 @@ if [ "$1" = "bulkhead" ]; then host="kiviuq.local" fi if [ "$1" = "backyard" ]; then - port=8082 + port=8081 host="mundilfari.local" fi if [ "$1" = "backyard_low" ]; then - port=8083 + port=8082 host="mundilfari.local" fi if [ "$1" = "backyard_north" ]; then - port=8084 + port=8083 host="mundilfari.local" fi if [ "$1" = "basement_extension" ]; then - port=8081 + port=8084 host="mundilfari.local" fi if [ "$1" = "orchard" ]; then @@ -72,7 +72,7 @@ if [ "$1" = "diningroom" ]; then host="kari.local" fi -ROOT="/var/photos/misc/webcams" +ROOT="/media/photos/misc/webcams" filepath="$1/$(date +%Y)/$(date +%m)/$(date +%d)/$(date +%Y%m%d%H%M%S).jpg" mkdir -p /$ROOT/$1/$(date +%Y)/$(date +%m)/$(date +%d)/ curl $host:$port/snapshot -o /$ROOT/$filepath