This commit is contained in:
Tobias Hopp 2023-05-28 15:09:38 +02:00
parent 7f52850b2e
commit b8fffdb52d
7 changed files with 156 additions and 60 deletions

BIN
images/no-camera.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

71
install.sh Normal file
View File

@ -0,0 +1,71 @@
echo "Updating indexes"
apt update
echo "Installing xserver xinit openbox ufw xserver-xorg x11 unclutter make crontab cmake g++ gcc and git..."
apt install --no-install-recommends ufw xserver-xorg x11-xserver-utils xinit openbox -y || exit
apt install git gcc g++ make cmake unclutter iptables cron pigpio -y || exit
echo "Try to uninstall node and npm... (Can fail)"
apt purge node -y || true
apt purge npm -y || true
echo "Setup xserver..."
# XServer
echo "allowed_users=anybody" >/etc/X11/Xwrapper.config
#no-uncomment cp autostart.config /etc/xdg/openbox/autostart
echo "Adding apt keys..."
# Keys and stuff ---
# Nodejs
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash
# Yarn
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
echo "Updating indexes..."
# Final update
apt update
echo "Installing mongodb and yarn..."
apt install nodejs yarn mongodb-org -y
apt upgrade -y
echo "Installing autostart..."
# Autostart
cat <<EOT >/etc/xdg/openbox/autostart
xset s off
xset s noblank
xset -dpms
setxkbmap -option terminate:ctrl_alt_bksp
cd /home/photobox/photobox/
./mount.sh
yarn run start
EOT
echo "Setting to console autologin..."
raspi-config nonint do_boot_behaviour B2
echo "Installing bashrc"
echo "clear" >>/home/photobox/.bashrc
echo "[[ -z \$DISPLAY && \$XDG_VTNR -eq 1 ]] && startx -- -nocursor >/dev/null 2>&1" >>/home/photobox/.bashrc
echo "Setting no-logo..."
systemctl disable getty@tty1.service
if ! grep -w "logo.nologo" /boot/cmdline.txt; then
echo "Backing up /boot/cmdline.txt to /root/cmdline.txt.bak"
cp /boot/cmdline.txt /root/cmdline.txt.bak
sed -i '1 s_$_ loglevel=3 logo.nologo disable\_splash=1 splash quiet plymouth.ignore-serial-consoles logo.nologo vt.global\_cursor_default=0_' /boot/cmdline.txt
#cp /tmp/cmdline.txt /boot/cmdline.txt
sed -i "1 s|$| vt.global_cursor_default=0|" /boot/cmdline.txt
sed -i 's/console=tty0/console=tty3/' /boot/cmdline.txt
fi
chown photobox:photobox -R /home/photobox/

View File

@ -5,6 +5,7 @@ import * as process from "process";
import {GPIO} from "./gpio"; import {GPIO} from "./gpio";
import {PythonWebcam} from "./python_webcam"; import {PythonWebcam} from "./python_webcam";
import {FileHandler} from "./file_handler"; import {FileHandler} from "./file_handler";
import {Utils} from "./utils";
function createWindow() { function createWindow() {
// Create the browser window. // Create the browser window.
@ -45,6 +46,7 @@ app.on("window-all-closed", () => {
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.
Server.initServer().then(); Server.initServer().then();
PythonWebcam.startPythonService(); PythonWebcam.startPythonService();
/*setInterval(() => { /*setInterval(() => {
@ -52,16 +54,18 @@ PythonWebcam.startPythonService();
}, 1000*10);*/ }, 1000*10);*/
try { try {
Utils.load();
// Capture button // Capture button
GPIO.watchForButton(10, (pin) => { GPIO.watchForButton(10, (pin) => {
Main.capture() Utils.capture()
}); });
// Delete button // Delete button
GPIO.watchForButton(11, (pin) => { GPIO.watchForButton(11, (pin) => {
console.log("Delete fired!"); console.log("Delete fired!");
Utils.delete_last();
}); });
} catch (e) { } catch (e) {
@ -72,39 +76,3 @@ process.on("SIGINT", _ => {
GPIO.unexportAll(); GPIO.unexportAll();
}); });
export class Main {
private static port = GPIO.getPin(20, 'out')
static async delete_last() {
console.log("Delete fired!");
let last_shots = await FileHandler.getLastImages();
let last = last_shots[0];
if(last.locked) {
Server.io.emit("deleting", false);
}
else
{
Server.io.emit("deleting", true);
await FileHandler.deleteLastImage();
await Server.sendRecentPhotos();
}
}
static capture() {
console.log("Capture fired!");
Server.io.emit("capturing", 3);
setTimeout( async () => {
this.port.setHigh();
}, 2300 );
setTimeout(async () => {
let base64_string = await PythonWebcam.captureImage();
Server.io.emit("captured", base64_string);
this.port.setLow();
}, 3000);
}
}

View File

@ -9,14 +9,13 @@ export class PythonWebcam {
private static filename = __dirname + "/../capture.py"; private static filename = __dirname + "/../capture.py";
private static waitFor = "wrote_frame"; private static waitFor = "wrote_frame";
private static calls: Function[] = []; private static calls: Function[] = [];
private static noCamera = true; public static noCamera = true;
private static process: child_process.ChildProcess; private static process: child_process.ChildProcess;
public static startPythonService() { public static startPythonService() {
this.process = spawn("python", [this.filename], {stdio: 'pipe'}); this.process = spawn("python", [this.filename], {stdio: 'pipe'});
this.process.stdout.setEncoding('utf-8'); this.process.stdout.setEncoding('utf-8');
console.log("spawned")
this.process.stdout.on('data', (data) => { this.process.stdout.on('data', (data) => {
this.noCamera = false; this.noCamera = false;
@ -32,10 +31,10 @@ export class PythonWebcam {
this.process.on("exit", (code) => { this.process.on("exit", (code) => {
console.log("Subprocess exited! " + code) console.log("Subprocess exited! " + code)
this.noCamera = true;
if (code != 0) if (code != 0)
{ {
this.noCamera = true; //throw new Error("Could not open camera device/script - Code: " + code.toString());
throw new Error("Could not open camera device/script - Code: " + code.toString());
} }
}); });
@ -50,12 +49,14 @@ export class PythonWebcam {
this.waitForScriptFrame(() => { this.waitForScriptFrame(() => {
resolve(FileHandler.getTempPicture()); resolve(FileHandler.getTempPicture());
}); });
setTimeout(() => resolve(""), 1000 );
}); });
} }
public static captureImage(): Promise<string> { public static captureImage(): Promise<string> {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
let img = (await this.getImage()).toString(); let img = (await this.getImage()).toString();
if(img.length != 0 )
await FileHandler.saveBase64Photo(img); await FileHandler.saveBase64Photo(img);
resolve(img); resolve(img);
await Server.sendRecentPhotos(); await Server.sendRecentPhotos();

View File

@ -1,13 +1,13 @@
import {Socket} from "socket.io"; import {Socket} from "socket.io";
import {FileHandler} from "./file_handler"; import {FileHandler} from "./file_handler";
import {PythonWebcam} from "./python_webcam"; import {PythonWebcam} from "./python_webcam";
import {Main} from "./main";
import {Utils} from "./utils";
export class Server { export class Server {
private static app = require("express")(); private static app = require("express")();
private static server = require('http').createServer(this.app); private static server = require('http').createServer(this.app);
public static io = require('socket.io')(this.server); public static io = require('socket.io')(this.server);
private static interval : NodeJS.Timer;
public static initServer(): Promise<void> { public static initServer(): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -18,15 +18,10 @@ export class Server {
socket.on("do_shot", () => { socket.on("do_shot", () => {
console.log("Capture fired!"); console.log("Capture fired!");
Server.io.emit("capturing", ""); Utils.capture();
setTimeout(async () => {
let base64_string = await PythonWebcam.captureImage();
Server.io.emit("captured", base64_string);
}, 3000);
}); });
socket.on("do_delete", () => { socket.on("do_delete", () => {
Main.delete_last(); Utils.delete_last();
}) })
}); });
@ -36,7 +31,7 @@ export class Server {
//Webcam.startCameraStream(); //Webcam.startCameraStream();
this.server.listen(3000); this.server.listen(3000);
this.startInterval(); this.nextInterval();
}); });
} }
@ -49,14 +44,21 @@ export class Server {
} }
public static startInterval(){ public static nextInterval(){
setTimeout(async () => { setTimeout(async () => {
try { try {
if( PythonWebcam.noCamera )
{
this.io.emit("no_camera");
} else
{
this.io.emit("stream", (await PythonWebcam.getImage())); this.io.emit("stream", (await PythonWebcam.getImage()));
}
} catch( e ) } catch( e )
{ {
} }
this.startInterval(); this.nextInterval();
}, 1000/30); }, 1000/30);
} }

51
src/utils.ts Normal file
View File

@ -0,0 +1,51 @@
import {GPIO} from "./gpio";
import {FileHandler} from "./file_handler";
import {Server} from "./server";
import {PythonWebcam} from "./python_webcam";
export class Utils {
private static flashlight: GPIO;
static load() {
this.flashlight = GPIO.getPin(20, 'out');
}
static async delete_last() {
console.log("Delete fired!");
let last_shots = await FileHandler.getLastImages();
let last = last_shots[0];
if (last.locked) {
Server.io.emit("deleting", false);
} else {
Server.io.emit("deleting", true);
await FileHandler.deleteLastImage();
await Server.sendRecentPhotos();
}
}
public static capture() {
console.log("Capture fired!");
Server.io.emit("capturing", 3);
setTimeout(async () => {
try {
this.flashlight.setHigh();
} catch (e) {
}
}, 2500);
setTimeout(async () => {
let base64_string = await PythonWebcam.captureImage();
Server.io.emit("captured", base64_string);
try {
this.flashlight.setLow();
} catch (e) {
}
}, 3000);
}
}

View File

@ -36,11 +36,14 @@ document.addEventListener("DOMContentLoaded", () => {
let socket = io("http://localhost:3000"); let socket = io("http://localhost:3000");
socket.on("stream", (data) => { socket.on("stream", (data) => {
//console.log(data);
if (isShowingCaptured) return; if (isShowingCaptured) return;
imageElement.src = data; imageElement.src = data;
}); });
socket.on("no_camera", (data) => {
if (isShowingCaptured) return;
imageElement.src = "../images/no-camera.png";
});
socket.on("last_shots", (data: { image: string, locked: boolean }[]) => { socket.on("last_shots", (data: { image: string, locked: boolean }[]) => {
lastImages.innerHTML = ""; lastImages.innerHTML = "";
@ -84,9 +87,9 @@ document.addEventListener("DOMContentLoaded", () => {
countdown.innerText = "CHEESE!"; countdown.innerText = "CHEESE!";
setTimeout(() => { setTimeout(() => {
flash.style.display = "block"; flash.style.display = "block";
}, 150); }, 90);
}, 800); }, 900);
}, 950); }, 1000);
}, 1000) }, 1000)
}); });