update readme

This commit is contained in:
2025-07-26 17:25:18 -07:00
parent b81872440f
commit a29ec39252
20 changed files with 335 additions and 95 deletions

View File

@ -1,6 +1,7 @@
--- ---
packages: packages:
- ffmpeg
- ethtool - ethtool
- python3 - python3
- python3-venv - python3-venv
@ -16,13 +17,15 @@ packages:
- wayland-utils - wayland-utils
- xscreensaver - xscreensaver
# this will be the parent folder where the photos will be stored # this will be the parent folder where the photos will be stored
# it should be big, I'm using a 1TB SD card for the 2025 road trip # it should be big, I'm using a 1TB SD card for the 2025 road trip
## ===Disk Info======================================= ## ===Disk Info=======================================
## Filesystem Size Used Avail Use% Mounted on ## Filesystem Size Used Avail Use% Mounted on
## /dev/mmcblk0p2 112G 3.0G 103G 3% / ## /dev/mmcblk0p2 112G 3.0G 103G 3% /
## /dev/sda1 939G 28K 892G 1% /opt/carputer ## /dev/sda1 939G 28K 892G 1% /opt/carputer
working_folder: "/opt/carputer" working_folder: "/opt/carputer/timelapse"
# ustreamer variables # ustreamer variables
video_device: "/dev/video0" video_device: "/dev/video0"

View File

@ -1,12 +0,0 @@
#!/bin/bash
# create timelapse
# Check if the timestamp is provided
#if [ -z "$1" ]; then
# echo "Usage: ./test.sh --timestamp=\"2025-07-25 12:00:00\""
# exit 1
#fi
# Extract the timestamp from the argument
#TIMESTAMP=$(echo $1 | awk -F'=' '{print $2}')4

View File

@ -0,0 +1,11 @@
services:
photo_refresh:
container_name: photo_refresh
image: php:8.0-apache
ports:
- 8080:80
volumes:
- /opt/docker/photo_refresh/:/var/www/html/
network_mode: bridge
restart: always

17
files/getImage.php Normal file
View File

@ -0,0 +1,17 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dynamic Image Update</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<img id="refreshedImage" src="getImage.php" width="400" alt="Refreshed Image">
<script>
// Function to update the image every other second using AJAX
setInterval(function() {
$('#refreshedImage').attr('src', 'getImage.php?_=' + new Date().getTime()); // Adding timestamp to avoid caching
}, 2000);
</script>
</body>
</html>

View File

@ -0,0 +1,23 @@
# Use an official Node runtime as a parent image
FROM node:14
# Create and change to the app directory
WORKDIR /usr/src/app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install any needed packages specified in package.json
RUN npm install
# Bundle app source inside Docker container
COPY . .
# Make port 3000 available to the world outside this container
EXPOSE 3000
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["node", "server.js"]

View File

@ -0,0 +1,12 @@
{
"name": "docker_web_app",
"version": "1.0.0",
"description": "A simple Docker Web app",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.17.1"
}
}

View File

@ -0,0 +1,39 @@
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
const port = 3000;
app.use(express.static('public')); // Serve static files from the 'public' directory
// Endpoint to get the most recent image
app.get('/most-recent-image', (req, res) => {
const imagesDirectory = path.join(__dirname, 'images');
fs.readdir(imagesDirectory, (err, files) => {
if (err) {
return res.status(500).send('Unable to scan directory');
}
let mostRecentImage = null;
let maxDate = Date.now();
files.forEach(file => {
const filePath = path.join(imagesDirectory, file);
const stats = fs.statSync(filePath);
if (stats.isFile() && /\.(jpg|jpeg|png|gif)$/i.test(file)) {
const currentDate = new Date(stats.mtime).getTime();
if (currentDate < maxDate) {
mostRecentImage = file;
maxDate = currentDate;
}
}
});
if (mostRecentImage) {
res.json({ imagePath: `/images/${mostRecentImage}` });
} else {
res.status(404).send('No images found');
}
});
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});

22
files/index.php Normal file
View File

@ -0,0 +1,22 @@
<?php
header("Cache-Control: no-cache, must-revalidate");
// Path to the directory where the images are stored
$imageDirectory = 'capture/';
// Get the list of image files in the directory
$imageFiles = glob($imageDirectory . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
// If there are no image files, return a default image
if (empty($imageFiles)) {
$defaultImage = 'default.jpg'; // Provide path to your default image
header('Content-Type: image/jpeg'); // Adjust content type if default image type is different
readfile($defaultImage);
exit;
}
// Sort the image files by modification time, latest first
array_multisort(array_map('filemtime', $imageFiles), SORT_DESC, $imageFiles);
// Get the path to the latest image file
$latestImage = $imageFiles[0];
// Set header type
header('Content-Type: image/jpeg');
// Get the image
readfile($latestImage);
?>

View File

@ -2,21 +2,10 @@
############################################### ###############################################
# Chrome Kiosk Config # Chrome Kiosk Config
# This creates the service and configures the user profile # This creates the service and configures the user profile
# there are two chrome services with different variables
# so i can make a list of variables again
############################################### ###############################################
- name: lldp - apache - clear www
command: rm -R /var/www/html
# Copy Web Server Files
- name: lldp - apache - web - copy files
copy:
src: "{{ item }}"
dest: /var/www/html/
owner: www-data
mode: 0755
with_fileglob:
- "/var/jenkins_home/ansible/roles/lldp_scan/files/www/*"
- name: Chrome Kiosk - Create User Service Folder - name: Chrome Kiosk - Create User Service Folder
file: file:
path: /home/cosmos/.config/systemd/user path: /home/cosmos/.config/systemd/user
@ -25,9 +14,21 @@
group: cosmos group: cosmos
mode: '0700' mode: '0700'
- name: set kiosk template vars
set_fact:
kiosk_service_templates:
- chrome_resolution: "720,405"
chrome_website: "http://127.0.0.1:7123/stream"
service_name: chrome_webcam
- chrome_resolution: "720,595"
chrome_website: "http://127.0.0.1:3000"
service_name: chrome_timelapse_control
- name: configure kiosks
block:
- name: Chrome Kiosk - user stop service - name: Chrome Kiosk - user stop service
command: systemctl --user -M cosmos@ stop chrome.service command: "systemctl --user -M cosmos@ stop {{ service_name }}.service"
register: user_start_chrome
ignore_errors: true ignore_errors: true
- name: Chrome Kiosk - Kill chrome if running otherwise - name: Chrome Kiosk - Kill chrome if running otherwise
@ -37,25 +38,23 @@
- name: Chrome Kiosk - Copy chrome service file - name: Chrome Kiosk - Copy chrome service file
template: template:
src: chrome-app.service.j2 src: chrome-app.service.j2
dest: /home/cosmos/.config/systemd/user/chrome.service dest: "/home/cosmos/.config/systemd/user/{{ service_name }}.service"
owner: cosmos owner: cosmos
group: cosmos group: cosmos
mode: 0600 mode: 0600
- name: Chrome Kiosk - user daemon reload - name: Chrome Kiosk - user daemon reload
command: systemctl --user -M cosmos@ daemon-reload command: "systemctl --user -M cosmos@ daemon-reload"
register: user_daemon_reload register: user_daemon_reload
ignore_errors: true
- name: Chrome Kiosk - user enable service - name: Chrome Kiosk - user enable service
command: systemctl --user -M cosmos@ enable chrome.service command: "systemctl --user -M cosmos@ enable {{ service_name }}.service"
register: user_enable_chrome
ignore_errors: true
- name: Chrome Kiosk - user start service - name: Chrome Kiosk - user start service
command: systemctl --user -M cosmos@ start chrome.service command: "systemctl --user -M cosmos@ start {{ service_name }}.service"
register: user_start_chrome
ignore_errors: true loop: "{{ timelapse_script_templates }}"
... ...

View File

@ -12,12 +12,12 @@
### Bottom Service Control Panel ### Bottom Service Control Panel
# select display_name, city, state, postcode from addresses order by id desc limit 1; # select display_name, city, state, postcode from addresses order by id desc limit 1;
# curl -s http://10.18.1.1:8184/wheres_gali?api_key=srJraFFprHadzQTDZf5hrmXh # curl -s http://10.18.1.1:8184/wheres_gali?api_key=
- name: Carputer Early Tasks - name: Carputer Early Tasks
include_tasks: include_tasks:
- ustreamer.yaml - ustreamer.yaml
- timelapse.yaml - timelapse.yaml
- php_site.yaml - photo_refresh.yaml
... ...

50
tasks/photo_refresh.yaml Normal file
View File

@ -0,0 +1,50 @@
---
- name: photo_refresh - set folder variable
set_fact:
- docker_source: "/opt/cosmos/photo_refresh"
- name: photo_refresh - create docker folder
file:
path: "{{ docker_source }}"
state: directory
mode: '0755'
- name: photo_refresh - copy files for docker container
copy:
src: "image_refresh"
dest: "{{ docker_source }}"
recursive: yes
- name: photo_refresh - Build image
docker_image:
name: photo_refresh # Name of the Docker image
source: build
build:
path: /opt/cosmos/photo_refresh # Path to the directory containing your Dockerfile
state: present
tag: latest
###############################################
# Start photo_refresh
###############################################
- name: start photo_refresh
block:
- name: photo_refresh - Copy config
template:
source: docker-compose-node.yaml.j2
dest: "{{ docker_source }}docker-compose.yaml"
mode: 0644
- name: photo_refresh - Start container at 0.0.0.0:8080
shell: "docker-compose -f {{ docker_source }}/docker-compose.yaml up -d"
register: local_index_output
- debug: |
msg="{{ local_index_output.stdout_lines }}"
msg="{{ local_index_output.stderr_lines }}"
...

View File

View File

@ -1,7 +1,15 @@
--- ---
- name: set template vars
set_fact:
# timelapse related scripts
timelapse_script_templates:
- src: timelapse_service.sh.j2
dest: "{{ working_folder }}/timelapse_service.sh"
- src: record_snapshots.sh.j2
dest: "{{ working_folder }}/record_snapshots.sh"
- src: create_timelapse.sh.j2
dest: "{{ working_folder }}/create_timelapse.sh"
- name: Create user - name: Create user
user: user:
@ -10,6 +18,29 @@
shell: /bin/bash shell: /bin/bash
groups: video groups: video
- name: template scripts
template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
loop: "{{ timelapse_script_templates }}"
owner: root
group: root
mode: 0644
- name: template service file
template:
src: timelapse.service.j2
dest: /etc/systemd/system/timelapse.service
owner: root
group: root
mode: 0644
- name: Enable and start service
become: true
systemd:
daemon_reload: yes
state: started
enabled: yes
name: ustreamer
... ...

View File

@ -3,12 +3,17 @@ Description=Chrome
After=lldp_api.service After=lldp_api.service
After=sddm.service After=sddm.service
[Service] [Service]
Restart=always Restart=always
RestartSec=3s RestartSec=3s
#ExecStartPre=/bin/sleep 5 ExecStartPre=/bin/sleep 5
ExecStart=/usr/bin/google-chrome \ ExecStart=/usr/bin/google-chrome \
--disable-pinch \
--disable-translate \
--no-first-run \
--ignore-ssl-errors \
--disable-usb-keyboard-detect \
--window-size={{ chrome_resolution }}'
--app="{{ chrome_website }}" --app="{{ chrome_website }}"
[Install] [Install]

View File

@ -0,0 +1,6 @@
#!/bin/bash
# create timelapse
ffmpeg -r 30 -pattern_type glob -i "$WORKING_DIR/*.jpg" \
-vf "scale=1920x1080" -vcodec libx264 /$WORKING_DIR/00-timelapse.mp4

View File

@ -0,0 +1,11 @@
services:
photo_refresh:
container_name: photo_refresh
image: photo_refresh
ports:
- 3000:3000
volumes:
- {{ working_folder }}/small_thumbs:/usr/src/app/public
network_mode: bridge
restart: always

View File

@ -1,33 +0,0 @@
#!/bin/bash
# this saves a snapshot of the camera every second or so depending on how long all the other crap takes
# let's hope the vars make it otherwise imma need to parse a bollocksing file
i=1
while [ -f "$WORKING_DIR/run" ]
do
FILENAME=$(printf "img-%05d" "$i")
LATLON=$(curl -s http://10.18.1.1:8184/where_is?api_key={{ tesla_api_key }} )
LON=$(echo $LATLON | jq .lon)
LAT=$(echo $LATLON | jq .lat)
COORDINATES="$LAT, $LON"
curl http://127.0.0.1:7123/snapshot --output $WORKING_DIR/$BEGIN/$FILENAME.jpg
# This variable is for the timestamp
TIME=$(date +%Y%m%d-%H%M)xqa
# This should add the current time to the image and save it
convert $WORKING_DIR/$BEGIN/$FILENAME.jpg -gravity NorthWest -pointsize 22 \
-fill yellow -annotate +30+30 $TIME $WORKING_DIR/$BEGIN/$FILENAME-temp.jpg
# Delete original
rm $WORKING_DIR/$BEGIN/$FILENAME.jpg
# This should add the current latlon to the image and save it
convert $WORKING_DIR/$BEGIN/$FILENAME-temp.jpg -gravity NorthEast -pointsize 22 \
-fill yellow -annotate +30+30 $COORDINATES $WORKING_DIR/$BEGIN/$FILENAME.jpg
# Delete temp
rm $WORKING_DIR/$BEGIN/$FILENAME-temp.jpg
sleep 1
((i++))
done

View File

@ -0,0 +1,57 @@
#!/bin/bash
# this saves a snapshot of the camera every second or so depending on how long all the other crap takes
# let's hope the vars make it otherwise imma need to parse a bollocksing file
i=1
while [ -f "$WORKING_DIR/run" ]
do
FILENAME=$(printf "img-%05d" "$i")
LATLON=$(curl -s http://10.18.1.1:8184/where_is?api_key={{ tesla_api_key }} )
LON=$(echo $LATLON | jq .lon)
LAT=$(echo $LATLON | jq .lat)
COORDINATES="$LAT, $LON"
curl http://127.0.0.1:7123/snapshot --output $WORKING_DIR/$FILENAME.jpg
# This variable is for the timestamp
TIME=$(date +%c)
# this big boi should add both the timestamp and the coordinates
convert $WORKING_DIR/$FILENAME.jpg \( +clone -gravity NorthWest -pointsize 22 -fill yellow -annotate +30+30 "$TIME" \) \
\( +clone -gravity NorthEast -pointsize 22 -fill yellow -annotate +30+30 "$COORDINATES" \) \
-append $WORKING_DIR/$FILENAME.jpg
# This is for the tiny pic
# I'll make one every 5 seconds
# I have 1340x580. i think i will truncate the top
# Calculate the height to trim based on the aspect ratios of the input and output images
if (( $i % 5 == 0 )); then
input_width=1920
input_height=1080
output_width=1340
output_height=580
# Calculate the ratio for trimming the top part
trim_ratio=$(echo "scale=4; $output_height / $output_width * $input_width" | bc)
NOW=$(date +%Y%m%d%H%M%S)
convert $WORKING_DIR/$FILENAME.jpg -gravity North -crop x$trim_ratio +repage -resize 1340x580 {{ working_folder }}/small_thumbs/$NOW.jpg
fi
sleep 1
((i++))
done
# old one-at-a-time rubbish
# # This should add the current time to the image and save it
# convert $WORKING_DIR/$FILENAME.jpg -gravity NorthWest -pointsize 22 \
# -fill yellow -annotate +30+30 $TIME $WORKING_DIR/$FILENAME-temp.jpg
# # Delete original
# rm $WORKING_DIR/$FILENAME.jpg
#
# # This should add the current latlon to the image and save it
# convert $WORKING_DIR/$FILENAME-temp.jpg -gravity NorthEast -pointsize 22 \
# -fill yellow -annotate +30+30 $COORDINATES $WORKING_DIR/$FILENAME.jpg
# # Delete temp
# rm $WORKING_DIR/$FILENAME-temp.jpg

View File

@ -4,7 +4,6 @@ After=network.target
[Service] [Service]
ExecStart=/opt/carputer/timelapse/timelapse_service.sh ExecStart=/opt/carputer/timelapse/timelapse_service.sh
Restart=always Restart=always
User=timelapse User=timelapse
Group=timelapse Group=timelapse

View File

@ -3,7 +3,7 @@
# initialize all the variables # initialize all the variables
# basic things # basic things
BEGIN=$(date +%Y%m%d-%H%M%S) BEGIN=$(date +%Y%m%d-%H%M%S)
WORKING_DIR="/opt/carputer/timelapse/storage/$BEGIN" WORKING_DIR="{{ working_folder }}/storage/$BEGIN"
# be greedy about API calls # be greedy about API calls
WHERES_GALI=$(curl -s http://10.18.1.1:8184/wheres_gali?api_key={{ tesla_api_key }}) WHERES_GALI=$(curl -s http://10.18.1.1:8184/wheres_gali?api_key={{ tesla_api_key }})
# parse the one API call # parse the one API call
@ -20,10 +20,10 @@ echo $DISPLAY_NAME >> $WORKING_DIR/info.txt
# Set the run file and fork the loop # Set the run file and fork the loop
touch $WORKING_DIR/run touch $WORKING_DIR/run
source ./record_snapshots.sh & source {{ working_folder }}/record_snapshots.sh &
# set the trap and wait # set the trap and wait
trap "source ./record_timelapse" SIGINT SIGTERM trap "source {{ working_folder }}/create_timelapse.sh &" SIGINT SIGTERM
while true; do while true; do
echo "Running..." echo "Running..."
sleep 1 sleep 1