update readme
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
---
|
||||
|
||||
packages:
|
||||
- ffmpeg
|
||||
- ethtool
|
||||
- python3
|
||||
- python3-venv
|
||||
@ -16,13 +17,15 @@ packages:
|
||||
- wayland-utils
|
||||
- xscreensaver
|
||||
|
||||
|
||||
|
||||
# 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
|
||||
## ===Disk Info=======================================
|
||||
## Filesystem Size Used Avail Use% Mounted on
|
||||
## /dev/mmcblk0p2 112G 3.0G 103G 3% /
|
||||
## /dev/sda1 939G 28K 892G 1% /opt/carputer
|
||||
working_folder: "/opt/carputer"
|
||||
working_folder: "/opt/carputer/timelapse"
|
||||
|
||||
# ustreamer variables
|
||||
video_device: "/dev/video0"
|
||||
|
||||
@ -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
|
||||
|
||||
11
files/docker-compose-php.yaml
Normal file
11
files/docker-compose-php.yaml
Normal 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
17
files/getImage.php
Normal 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>
|
||||
23
files/image_refresh/Dockerfile
Normal file
23
files/image_refresh/Dockerfile
Normal 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"]
|
||||
12
files/image_refresh/package.json
Normal file
12
files/image_refresh/package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
39
files/image_refresh/server.js
Normal file
39
files/image_refresh/server.js
Normal 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
22
files/index.php
Normal 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);
|
||||
?>
|
||||
@ -2,21 +2,10 @@
|
||||
###############################################
|
||||
# Chrome Kiosk Config
|
||||
# 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
|
||||
file:
|
||||
path: /home/cosmos/.config/systemd/user
|
||||
@ -25,37 +14,47 @@
|
||||
group: cosmos
|
||||
mode: '0700'
|
||||
|
||||
- name: Chrome Kiosk - user stop service
|
||||
command: systemctl --user -M cosmos@ stop chrome.service
|
||||
register: user_start_chrome
|
||||
- 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
|
||||
command: "systemctl --user -M cosmos@ stop {{ service_name }}.service"
|
||||
ignore_errors: true
|
||||
|
||||
- name: Chrome Kiosk - Kill chrome if running otherwise
|
||||
- name: Chrome Kiosk - Kill chrome if running otherwise
|
||||
command: pkill chrome
|
||||
ignore_errors: true
|
||||
|
||||
- name: Chrome Kiosk - Copy chrome service file
|
||||
- name: Chrome Kiosk - Copy chrome service file
|
||||
template:
|
||||
src: chrome-app.service.j2
|
||||
dest: /home/cosmos/.config/systemd/user/chrome.service
|
||||
dest: "/home/cosmos/.config/systemd/user/{{ service_name }}.service"
|
||||
owner: cosmos
|
||||
group: cosmos
|
||||
mode: 0600
|
||||
|
||||
- name: Chrome Kiosk - user daemon reload
|
||||
command: systemctl --user -M cosmos@ daemon-reload
|
||||
- name: Chrome Kiosk - user daemon reload
|
||||
command: "systemctl --user -M cosmos@ daemon-reload"
|
||||
register: user_daemon_reload
|
||||
ignore_errors: true
|
||||
|
||||
- name: Chrome Kiosk - user enable service
|
||||
command: systemctl --user -M cosmos@ enable chrome.service
|
||||
register: user_enable_chrome
|
||||
ignore_errors: true
|
||||
- name: Chrome Kiosk - user enable service
|
||||
command: "systemctl --user -M cosmos@ enable {{ service_name }}.service"
|
||||
|
||||
- name: Chrome Kiosk - user start service
|
||||
command: "systemctl --user -M cosmos@ start {{ service_name }}.service"
|
||||
|
||||
loop: "{{ timelapse_script_templates }}"
|
||||
|
||||
- name: Chrome Kiosk - user start service
|
||||
command: systemctl --user -M cosmos@ start chrome.service
|
||||
register: user_start_chrome
|
||||
ignore_errors: true
|
||||
|
||||
|
||||
...
|
||||
@ -12,12 +12,12 @@
|
||||
### Bottom Service Control Panel
|
||||
|
||||
# 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
|
||||
include_tasks:
|
||||
- ustreamer.yaml
|
||||
- timelapse.yaml
|
||||
- php_site.yaml
|
||||
- photo_refresh.yaml
|
||||
|
||||
...
|
||||
50
tasks/photo_refresh.yaml
Normal file
50
tasks/photo_refresh.yaml
Normal 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 }}"
|
||||
|
||||
|
||||
...
|
||||
@ -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
|
||||
user:
|
||||
@ -10,6 +18,29 @@
|
||||
shell: /bin/bash
|
||||
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
|
||||
|
||||
...
|
||||
@ -3,12 +3,17 @@ Description=Chrome
|
||||
After=lldp_api.service
|
||||
After=sddm.service
|
||||
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
RestartSec=3s
|
||||
#ExecStartPre=/bin/sleep 5
|
||||
ExecStartPre=/bin/sleep 5
|
||||
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 }}"
|
||||
|
||||
[Install]
|
||||
|
||||
6
templates/create_timelapse.sh.j2
Normal file
6
templates/create_timelapse.sh.j2
Normal 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
|
||||
|
||||
11
templates/docker-compose-node.yaml.j2
Normal file
11
templates/docker-compose-node.yaml.j2
Normal 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
|
||||
@ -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
|
||||
57
templates/record_snapshots.sh.j2
Normal file
57
templates/record_snapshots.sh.j2
Normal 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
|
||||
@ -4,7 +4,6 @@ After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/opt/carputer/timelapse/timelapse_service.sh
|
||||
|
||||
Restart=always
|
||||
User=timelapse
|
||||
Group=timelapse
|
||||
@ -3,7 +3,7 @@
|
||||
# initialize all the variables
|
||||
# basic things
|
||||
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
|
||||
WHERES_GALI=$(curl -s http://10.18.1.1:8184/wheres_gali?api_key={{ tesla_api_key }})
|
||||
# parse the one API call
|
||||
@ -20,10 +20,10 @@ echo $DISPLAY_NAME >> $WORKING_DIR/info.txt
|
||||
|
||||
# Set the run file and fork the loop
|
||||
touch $WORKING_DIR/run
|
||||
source ./record_snapshots.sh &
|
||||
source {{ working_folder }}/record_snapshots.sh &
|
||||
|
||||
# set the trap and wait
|
||||
trap "source ./record_timelapse" SIGINT SIGTERM
|
||||
trap "source {{ working_folder }}/create_timelapse.sh &" SIGINT SIGTERM
|
||||
while true; do
|
||||
echo "Running..."
|
||||
sleep 1
|
||||
|
||||
Reference in New Issue
Block a user