diff --git a/files/app.py b/archive/app.py
similarity index 100%
rename from files/app.py
rename to archive/app.py
diff --git a/templates/docker-compose-node.yaml.j2 b/archive/docker-compose-node.yaml.j2
similarity index 100%
rename from templates/docker-compose-node.yaml.j2
rename to archive/docker-compose-node.yaml.j2
diff --git a/archive/gsysctl.yaml b/archive/gsysctl.yaml
new file mode 100644
index 0000000..03ff2e8
--- /dev/null
+++ b/archive/gsysctl.yaml
@@ -0,0 +1,80 @@
+---
+
+###############################################
+# Prepare for docker container
+# https://github.com/shakg/g-systemctl
+###############################################
+
+
+
+- name: set docker folder variable
+ set_fact:
+ docker_root: "/opt/cosmos/gsc"
+
+# clear folder first
+- name: gsc - delete old folder
+ shell: "rm -R {{ docker_root }}"
+
+# Create docker Folder
+- name: g-systemctl - create docker_root folder
+ file:
+ path: "{{ docker_root }}"
+ state: directory
+ mode: '0755'
+ owner: root
+ group: root
+
+- name: g-systemctl - clone the git
+ git:
+ repo: "https://github.com/shakg/g-systemctl"
+ dest: "{{ docker_root }}"
+
+###############################################
+# Start docker container
+###############################################
+
+
+- name: Replace golang version number
+ ansible.builtin.replace:
+ path: "{{ docker_root }}/backend/Dockerfile"
+ regexp: '^FROM golang:.*-alpine as development'
+ replace: 'FROM golang:1.24-alpine as development'
+
+# Replace g-systemctl docker-compose file
+- name: g-systemctl - replace docker-compose
+ copy:
+ dest: "{{ docker_root }}/docker-compose.yaml"
+ content: |
+ version: '3.8'
+
+ services:
+ frontend:
+ container_name: gsc-frontend
+ network_mode: bridge
+ restart: always
+ build:
+ context: ./frontend
+ target: production
+ ports:
+ - "80:80"
+
+ backend:
+ container_name: gsc-backend
+ network_mode: bridge
+ restart: always
+ build:
+ context: ./backend
+ target: production
+ ports:
+ - "8080:8080"
+ privileged: true
+
+- name: "g-systemctl - build and run containers"
+ shell: "docker-compose -f {{ docker_root }}/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/files/image_refresh_node/Dockerfile b/archive/image_refresh_node/Dockerfile
similarity index 100%
rename from files/image_refresh_node/Dockerfile
rename to archive/image_refresh_node/Dockerfile
diff --git a/files/image_refresh_node/package.json b/archive/image_refresh_node/package.json
similarity index 100%
rename from files/image_refresh_node/package.json
rename to archive/image_refresh_node/package.json
diff --git a/files/image_refresh_node/server.js b/archive/image_refresh_node/server.js
similarity index 100%
rename from files/image_refresh_node/server.js
rename to archive/image_refresh_node/server.js
diff --git a/archive/index.php.old b/archive/index.php.old
new file mode 100644
index 0000000..79033f2
--- /dev/null
+++ b/archive/index.php.old
@@ -0,0 +1,39 @@
+
+
+
+
+
+ API Call Example
+
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
+
+
+
\ No newline at end of file
diff --git a/archive/js_site/app.js b/archive/js_site/app.js
new file mode 100644
index 0000000..3c2aae4
--- /dev/null
+++ b/archive/js_site/app.js
@@ -0,0 +1,58 @@
+document.addEventListener('DOMContentLoaded', function () {
+ // Initially set button state to "Loading..."
+ updateButtonState("Loading...");
+
+ // Set an interval to check the API every second
+ setInterval(checkAPIStatus, 1000); // 1000 ms = 1 second
+});
+
+// Function to update the button text based on the API state
+function updateButtonState(status) {
+ const button = document.getElementById('statusButton');
+
+ if (status === "active") {
+ button.innerHTML = "Stop Service";
+ button.style.backgroundColor = "#FF6347"; // Red for stopping
+ button.onclick = stopService;
+ } else if (status === "inactive") {
+ button.innerHTML = "Start Service";
+ button.style.backgroundColor = "#32CD32"; // Green for starting
+ button.onclick = startService;
+ } else if (status === "failed") {
+ button.innerHTML = "Service Failed!";
+ button.style.backgroundColor = "#FF6347"; // Red for failed
+ button.onclick = null;
+ }else {
+ button.innerHTML = "Unknown";
+ button.style.backgroundColor = "#808080"; // Gray for error
+ button.onclick = null;
+ }
+}
+
+// Simulate API call and handle response
+function checkAPIStatus() {
+ // Replace with your actual API endpoint
+ fetch('http://172.17.0.1:5000/status')
+ .then(response => response.json())
+ .then(data => {
+ const apiStatus = data.Status;
+ updateButtonState(apiStatus);
+ })
+ .catch(error => {
+ console.error('Error fetching API status:', error);
+ updateButtonState('error');
+ });
+}
+
+
+// Function to start the service (this would make the API call to start it)
+function startService() {
+ console.log('Starting service...');
+ // You can call an API to start the service here
+}
+
+// Function to stop the service (this would make the API call to stop it)
+function stopService() {
+ console.log('Stopping service...');
+ // You can call an API to stop the service here
+}
diff --git a/archive/js_site/index.php b/archive/js_site/index.php
new file mode 100644
index 0000000..2cff265
--- /dev/null
+++ b/archive/js_site/index.php
@@ -0,0 +1,19 @@
+
+
+
+
+
+ API Status Button
+
+
+
+
+
+
+
+
+
+
diff --git a/archive/js_site/style.css b/archive/js_site/style.css
new file mode 100644
index 0000000..e65fdac
--- /dev/null
+++ b/archive/js_site/style.css
@@ -0,0 +1,26 @@
+body {
+ font-family: Arial, sans-serif;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ margin: 0;
+ background-color: #f4f4f9;
+}
+
+#app {
+ text-align: center;
+}
+
+button {
+ padding: 15px 30px;
+ font-size: 18px;
+ cursor: pointer;
+ border: none;
+ border-radius: 5px;
+ transition: background-color 0.3s ease;
+}
+
+button:active {
+ transform: scale(0.98);
+}
diff --git a/tasks/photo_refresh copy.yaml b/archive/photo_refresh copy.yaml
similarity index 100%
rename from tasks/photo_refresh copy.yaml
rename to archive/photo_refresh copy.yaml
diff --git a/templates/record_snapshots.sh.j2 b/archive/record_snapshots.sh.j2
similarity index 100%
rename from templates/record_snapshots.sh.j2
rename to archive/record_snapshots.sh.j2
diff --git a/defaults/main.yaml b/defaults/main.yaml
index 271848b..b7bdbcc 100644
--- a/defaults/main.yaml
+++ b/defaults/main.yaml
@@ -1,30 +1,58 @@
---
-packages:
+main_packages:
+ - gpsd
+ - gpsd-clients
+ - bc
+ - ffmpeg
+ - imagemagick
+ - ustreamer
- ffmpeg
- ethtool
- python3
- python3-venv
- pip
- python-is-python3
- - dbus-user-session
- apache2
- php
+
+autologin_packages:
- kde-plasma-desktop
- clinfo
- mesa-utils
- vulkan-tools
- wayland-utils
- xscreensaver
+ - dbus-user-session
# chrome kiosk variables
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"
+ extra_service_configs: |
+ After=ustreamer.service
+ Wants=ustreamer.service
+ user_data_dir: "/opt/chrome/one"
+ extra_chrome_configs: |
+ --user-data-dir=/opt/chrome/one \
+ - chrome_resolution: "720,550"
+ chrome_website: "http://127.0.0.1:8081"
service_name: chrome_timelapse_control
+ extra_service_configs: ""
+ user_data_dir: "/opt/chrome/two"
+ extra_chrome_configs: |
+ --window-position="0,410" \
+ --user-data-dir="/opt/chrome/two" \
+
+create_data_dir: true
+
+# timelapse scripts for templating
+timelapse_script_templates:
+ - src: timelapse_service.sh.j2
+ dest: "{{ working_folder }}/timelapse_service.sh"
+ - src: create_timelapse.sh.j2
+ dest: "{{ working_folder }}/create_timelapse.sh"
# this will be the parent folder where the photos will be stored
@@ -38,11 +66,15 @@ working_folder: "/opt/carputer/timelapse"
# other folder variables
gps_service_directory: "/opt/cosmos/gps_service"
photo_refresh_folder: "/opt/cosmos/photo_refresh"
+service_control_folder: "/opt/cosmos/timelapse_service_control"
# ustreamer variables
video_device: "/dev/video0"
resolution: "1920x1080"
ustreamer_port: "7123"
+# other rando vars
+cpu_architecture: "amd64"
+extra_volumes: ""
...
\ No newline at end of file
diff --git a/files/service_control_api/app.py b/files/service_control_api/app.py
new file mode 100644
index 0000000..68d4d4b
--- /dev/null
+++ b/files/service_control_api/app.py
@@ -0,0 +1,85 @@
+import subprocess
+import requests
+from lxml import html
+from flask import Flask, request, jsonify
+import json
+
+app = Flask(__name__)
+
+def start_service():
+ command = "systemctl start timelapse.service"
+ try:
+ # Run the command using subprocess.run()
+ process = subprocess.Popen(command, shell=True)
+
+ except subprocess.CalledProcessError as e:
+ return {"Error": e.strip('\n')}
+
+ command = "systemctl status timelapse.service | grep Active | cut -d ':' -f 2- | cut -b 2-"
+ try:
+ # Run the command using subprocess.run()
+ result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True)
+ return {"Message": result.stdout.strip('\n')}
+
+ except subprocess.CalledProcessError as e:
+ return {"Error": e.strip('\n')}
+
+def stop_service():
+ command = "systemctl stop timelapse.service"
+ try:
+ # Run the command using subprocess.run()
+ process = subprocess.Popen(command, shell=True)
+
+ except subprocess.CalledProcessError as e:
+ return {"Error": e.strip('\n')}
+
+ command = "systemctl status timelapse.service | grep Active | cut -d ':' -f 2- | cut -b 2-"
+ try:
+ # Run the command using subprocess.run()
+ result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True)
+ return {"Message": result.stdout.strip('\n')}
+ except subprocess.CalledProcessError as e:
+ return {"Error": e.strip('\n')}
+
+def service_status():
+ command = "systemctl status timelapse.service | grep Active | cut -d ':' -f 2- | cut -b 2-"
+ try:
+ # Run the command using subprocess.run()
+ result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True)
+ command = "systemctl status timelapse.service | grep Active | cut -d ':' -f 2 | cut -d ' ' -f 2"
+ status = subprocess.run(command, shell=True, check=True, capture_output=True, text=True)
+ return {"Message": result.stdout.strip('\n'), "Status": status.stdout.strip('\n')}
+ except subprocess.CalledProcessError as e:
+ return {"Error": e.strip('\n')}
+
+@app.route('/start', methods=['GET'])
+def start():
+ try:
+ return jsonify(start_service())
+ except ValueError as e:
+ print(e)
+ return jsonify({'error': e}), 400
+
+@app.route('/stop', methods=['GET'])
+def stop():
+ try:
+ return jsonify(stop_service())
+ except ValueError as e:
+ print(e)
+ return jsonify({'error': e}), 400
+
+@app.route('/status', methods=['GET'])
+def status():
+ try:
+ return jsonify(service_status())
+ except ValueError as e:
+ print(e)
+ return jsonify({'error': e}), 400
+
+@app.route('/test', methods=['GET'])
+def test():
+ return jsonify({'message': 'Hello there'})
+
+if __name__ == '__main__':
+ app.run(debug=True, host='0.0.0.0', port=5000)
+
\ No newline at end of file
diff --git a/files/service_control_api/website/index.php b/files/service_control_api/website/index.php
new file mode 100644
index 0000000..c1bd76d
--- /dev/null
+++ b/files/service_control_api/website/index.php
@@ -0,0 +1,203 @@
+";
+ $button_recent = true;
+ $button_result = runAPI($_GET['action']);
+ $debug_string = $debug_string."Button Result: ".$button_result." ";
+ sleep(1);
+}
+
+function runAPI($submitted_status) {
+ if(!isset($debug_string)){
+ $debug_string = "";
+ }
+ $debug_string = $debug_string."runAPI called, ".$submitted_status." ";
+ switch ($submitted_status) {
+ case "stop":
+ $apiUrl = "http://172.17.0.1:5000/stop";
+ break;
+ case "start":
+ $apiUrl = "http://172.17.0.1:5000/start";
+ break;
+ default:
+ $apiUrl = "http://172.17.0.1:5000/status";
+ break;
+ }
+ // API URL
+ $debug_string = $debug_string."After switch, apiUrl is ".$apiUrl." ";
+ // Use file_get_contents or cURL to fetch the API data
+ $response = file_get_contents($apiUrl);
+
+ if ($response === FALSE) {
+ $debug_string = $debug_string."Response ERROR!! ";
+ return "error"; // API error
+ }
+
+ // Decode the JSON response (assuming the API returns JSON)
+ $data = json_decode($response, true);
+ $debug_string = $debug_string."Data from API call: ".$data['Message']." ";
+ // Assuming the API returns a single word result (like "success", "failure", etc.)
+ return isset($data['Status']) ? $data['Status'] : 'unknown';
+}
+
+// Check if the button was clicked via AJAX request
+// if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+// $button_recent = true;
+// $status_at_submit = $_POST['status'];
+// echo "Set when clicked, second in code - ".$status_at_submit." ";
+// // Get the API result
+// $apiResult = runAPI($status_at_submit);
+// // Return the result as a JSON response
+// echo json_encode(['status' => $apiResult]);
+// exit;
+// }
+
+// URL of the external API
+$apiUrl = "http://172.17.0.1:5000/status";
+
+// Use file_get_contents to fetch data from the API
+$response = file_get_contents($apiUrl);
+
+// Check if the request was successful
+if ($response === FALSE) {
+ $data = "Failed to fetch data.";
+}
+else {
+ // Decode the JSON response (assuming the API returns JSON)
+ $data = json_decode($response, true);
+ // If you want to display specific data, adjust this part
+ // For example, if the API returns a 'message' key, display it
+ if (isset($data['Message'])) {
+ $message = $data['Message'];
+ } else {
+ $message = "No message found in the response.";
+ }
+ if (isset($data['Status'])) {
+ $status = $data['Status'];
+ } else {
+ $status = "None";
+ }
+}
+
+switch ($status) {
+ case "active":
+ $button_text = "Stop Service";
+ $button_active = true;
+ break;
+ case "inactive":
+ $button_text = "Start Service";
+ $button_active = true;
+ break;
+ case "failed":
+ $button_text = "Start Service - Warning";
+ $button_active = true;
+ break;
+ case "deactivating":
+ $button_text = "Service Stopping...";
+ $button_active = false;
+ break;
+ default:
+ $button_text = "Error, No Status";
+ $button_active = false;
+ $status="unknown";
+ break;
+}
+
+if($button_active && !$button_recent){
+ $action = "";
+ if($status == "active"){
+ $action = "stop";
+ }
+ else if($status == "inactive"){
+ $action = "start";
+ }
+ else if($status == "failed"){
+ $action = "start";
+ }
+ $button_action = ' onclick="location.href=\'/?action='.$action.'\'" ';
+}
+
+if($button_recent){
+ /*
+ $delay = 5; // Number of seconds before redirection
+ echo "You will be redirected in $delay seconds.";
+ header("Refresh: $delay; url=https://example.com");
+ exit();
+ */
+ header("Location: http://".$http_host);
+ exit(); // Always include exit() after headers are sent
+}
+
+?>
+
+
+
+
+
+
+
+ API Data Display
+
+
+
+
+
+