diff --git a/defaults/main.yaml b/defaults/main.yaml index fadbb3d..beca6c9 100644 --- a/defaults/main.yaml +++ b/defaults/main.yaml @@ -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" diff --git a/files/create_timelapse.sh b/files/create_timelapse.sh deleted file mode 100644 index 09b8cfc..0000000 --- a/files/create_timelapse.sh +++ /dev/null @@ -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 - diff --git a/files/docker-compose-php.yaml b/files/docker-compose-php.yaml new file mode 100644 index 0000000..ef52ffb --- /dev/null +++ b/files/docker-compose-php.yaml @@ -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 diff --git a/files/getImage.php b/files/getImage.php new file mode 100644 index 0000000..8b88b9d --- /dev/null +++ b/files/getImage.php @@ -0,0 +1,17 @@ + + + + +Dynamic Image Update + + + + Refreshed Image + + + \ No newline at end of file diff --git a/files/image_refresh/Dockerfile b/files/image_refresh/Dockerfile new file mode 100644 index 0000000..0afa7c8 --- /dev/null +++ b/files/image_refresh/Dockerfile @@ -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"] \ No newline at end of file diff --git a/files/image_refresh/package.json b/files/image_refresh/package.json new file mode 100644 index 0000000..acfd1a6 --- /dev/null +++ b/files/image_refresh/package.json @@ -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" + } +} \ No newline at end of file diff --git a/files/image_refresh/server.js b/files/image_refresh/server.js new file mode 100644 index 0000000..c7644c0 --- /dev/null +++ b/files/image_refresh/server.js @@ -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}`); +}); \ No newline at end of file diff --git a/files/index.php b/files/index.php new file mode 100644 index 0000000..7ad2677 --- /dev/null +++ b/files/index.php @@ -0,0 +1,22 @@ + \ No newline at end of file diff --git a/tasks/kiosk.yaml b/tasks/kiosk.yaml index ef385ff..ace19f1 100644 --- a/tasks/kiosk.yaml +++ b/tasks/kiosk.yaml @@ -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 - ignore_errors: true +- 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: Chrome Kiosk - Kill chrome if running otherwise - command: pkill chrome - ignore_errors: true +- name: configure kiosks + block: -- name: Chrome Kiosk - Copy chrome service file - template: - src: chrome-app.service.j2 - dest: /home/cosmos/.config/systemd/user/chrome.service - owner: cosmos - group: cosmos - mode: 0600 + - name: Chrome Kiosk - user stop service + command: "systemctl --user -M cosmos@ stop {{ service_name }}.service" + ignore_errors: true -- name: Chrome Kiosk - user daemon reload - command: systemctl --user -M cosmos@ daemon-reload - register: user_daemon_reload - ignore_errors: true + - name: Chrome Kiosk - Kill chrome if running otherwise + command: pkill chrome + 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 - Copy chrome service file + template: + src: chrome-app.service.j2 + dest: "/home/cosmos/.config/systemd/user/{{ service_name }}.service" + owner: cosmos + group: cosmos + mode: 0600 -- name: Chrome Kiosk - user start service - command: systemctl --user -M cosmos@ start chrome.service - register: user_start_chrome - ignore_errors: true + - name: Chrome Kiosk - user daemon reload + command: "systemctl --user -M cosmos@ daemon-reload" + register: user_daemon_reload + + - 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 }}" + ... \ No newline at end of file diff --git a/tasks/main.yaml b/tasks/main.yaml index 27b48b3..8e0275a 100644 --- a/tasks/main.yaml +++ b/tasks/main.yaml @@ -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 ... \ No newline at end of file diff --git a/tasks/photo_refresh.yaml b/tasks/photo_refresh.yaml new file mode 100644 index 0000000..c57fa4f --- /dev/null +++ b/tasks/photo_refresh.yaml @@ -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 }}" + + +... \ No newline at end of file diff --git a/tasks/php_site.yaml b/tasks/php_site.yaml deleted file mode 100644 index e69de29..0000000 diff --git a/tasks/timelapse.yaml b/tasks/timelapse.yaml index 57890d4..e6aefc2 100644 --- a/tasks/timelapse.yaml +++ b/tasks/timelapse.yaml @@ -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 ... \ No newline at end of file diff --git a/templates/chrome-app.service.j2 b/templates/chrome-app.service.j2 index 1d5f249..b385f14 100755 --- a/templates/chrome-app.service.j2 +++ b/templates/chrome-app.service.j2 @@ -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] diff --git a/templates/create_timelapse.sh.j2 b/templates/create_timelapse.sh.j2 new file mode 100644 index 0000000..8edb1b0 --- /dev/null +++ b/templates/create_timelapse.sh.j2 @@ -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 + diff --git a/templates/docker-compose-node.yaml.j2 b/templates/docker-compose-node.yaml.j2 new file mode 100644 index 0000000..a4f86d7 --- /dev/null +++ b/templates/docker-compose-node.yaml.j2 @@ -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 diff --git a/templates/record_snapshots.sh b/templates/record_snapshots.sh deleted file mode 100644 index 56c69f2..0000000 --- a/templates/record_snapshots.sh +++ /dev/null @@ -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 \ No newline at end of file diff --git a/templates/record_snapshots.sh.j2 b/templates/record_snapshots.sh.j2 new file mode 100644 index 0000000..2513c55 --- /dev/null +++ b/templates/record_snapshots.sh.j2 @@ -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 \ No newline at end of file diff --git a/files/timelapse.service b/templates/timelapse.service.j2 similarity index 99% rename from files/timelapse.service rename to templates/timelapse.service.j2 index 46db2cb..7f98f37 100644 --- a/files/timelapse.service +++ b/templates/timelapse.service.j2 @@ -4,7 +4,6 @@ After=network.target [Service] ExecStart=/opt/carputer/timelapse/timelapse_service.sh - Restart=always User=timelapse Group=timelapse diff --git a/templates/timelapse_service.sh.j2 b/templates/timelapse_service.sh.j2 index 8e9348b..cd802c5 100644 --- a/templates/timelapse_service.sh.j2 +++ b/templates/timelapse_service.sh.j2 @@ -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