Skip to content

Commit ba2dbc3

Browse files
committed
admin: add capture test for gphoto2
Change-Id: I6f88022ca76469817f3b0d91882660a9cfc3e8b9
1 parent 7179b71 commit ba2dbc3

File tree

2 files changed

+194
-0
lines changed

2 files changed

+194
-0
lines changed

admin/capturetest/index.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
require_once '../../lib/boot.php';
4+
5+
use Photobooth\PhotoboothCaptureTest;
6+
use Photobooth\Service\ApplicationService;
7+
use Photobooth\Service\LanguageService;
8+
use Photobooth\Utility\PathUtility;
9+
10+
// Login / Authentication check
11+
if (!(
12+
!$config['login']['enabled'] ||
13+
(!$config['protect']['localhost_admin'] && isset($_SERVER['SERVER_ADDR']) && $_SERVER['REMOTE_ADDR'] === $_SERVER['SERVER_ADDR']) ||
14+
(isset($_SESSION['auth']) && $_SESSION['auth'] === true) || !$config['protect']['admin']
15+
)) {
16+
header('location: ' . PathUtility::getPublicPath('login'));
17+
exit();
18+
}
19+
20+
$languageService = LanguageService::getInstance();
21+
$pageTitle = 'Capture test - ' . ApplicationService::getInstance()->getTitle();
22+
include PathUtility::getAbsolutePath('admin/components/head.admin.php');
23+
include PathUtility::getAbsolutePath('admin/helper/index.php');
24+
25+
?>
26+
<div class="w-full h-full grid place-items-center fixed bg-brand-1 overflow-x-hidden overflow-y-auto">
27+
<div class="w-full flex items-center justify-center flex-col px-6 py-12">
28+
29+
<div class="w-full max-w-xl h-144 rounded-lg p-4 md:p-8 bg-white flex flex-col shadow-xl">
30+
<div class="w-full flex items-center pb-3 mb-3 border-b border-solid border-gray-200">
31+
<a href="<?=PathUtility::getPublicPath('admin')?>" class="h-4 mr-4 flex items-center justify-center border-r border-solid border-black border-opacity-20 pr-3">
32+
<span class="fa fa-chevron-left text-brand-1 text-opacity-60 text-md hover:text-opacity-100 transition-all"></span>
33+
</a>
34+
<h2 class="text-brand-1 text-xl font-bold">
35+
<?= $languageService->translate('test_capture') ?>
36+
</h2>
37+
</div>
38+
<?php
39+
40+
$test = new PhotoboothCaptureTest();
41+
42+
foreach ($test->captureCmds as $index => $command) {
43+
// Set filename for each test command
44+
$test->fileName = sprintf('test-%d.jpg', $index + 1);
45+
$test->tmpFile = $test->tmpFolder . DIRECTORY_SEPARATOR . $test->fileName;
46+
47+
$test->addLog('debug', 'Executing Command #' . ($index + 1), ['command' => $command]);
48+
49+
// Execute the command
50+
$test->executeCmd($command);
51+
52+
foreach ($test->logData as $log) {
53+
$level = htmlspecialchars($log['level']);
54+
$message = htmlspecialchars($log['message']);
55+
$context = htmlspecialchars(json_encode($log['context'], JSON_PRETTY_PRINT));
56+
57+
echo '<div class="log-entry">
58+
<div class="log-level ' . $level . '">' . strtoupper($level) . '</div>
59+
<div class="log-message">' . $message . '</div>
60+
<div class="log-context"><pre>' . $context . '</pre></div>
61+
</div>';
62+
}
63+
$test->logData = [];
64+
}
65+
66+
?>
67+
</div>
68+
69+
</div>
70+
</div>
71+
72+
<?php
73+
74+
include PathUtility::getAbsolutePath('admin/components/footer.scripts.php');
75+
include PathUtility::getAbsolutePath('admin/components/footer.admin.php');

src/PhotoboothCaptureTest.php

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
3+
namespace Photobooth;
4+
5+
use Photobooth\Enum\FolderEnum;
6+
7+
/**
8+
* Class PhotoboothCaptureTest
9+
*/
10+
class PhotoboothCaptureTest
11+
{
12+
public string $fileName;
13+
public string $tmpFolder;
14+
public string $tmpFile;
15+
public array $logData = [];
16+
public array $captureCmds = [
17+
'gphoto2 --capture-image-and-download --filename=%s',
18+
'gphoto2 --set-config output=Off --capture-image-and-download --filename=%s',
19+
'gphoto2 --trigger-capture --wait-event-and-download=FILEADDED --filename=%s',
20+
'gphoto2 --set-config output=Off --trigger-capture --wait-event-and-download=FILEADDED --filename=%s',
21+
'gphoto2 --wait-event=300ms --capture-image-and-download --filename=%s',
22+
'gphoto2 --set-config output=Off --wait-event=300ms --capture-image-and-download --filename=%s',
23+
];
24+
25+
/**
26+
* PhotoboothCaptureTest constructor.
27+
*/
28+
public function __construct()
29+
{
30+
$this->tmpFolder = FolderEnum::TEMP->absolute();
31+
}
32+
33+
public function addLog(string $level, string $message, array $context = []): void
34+
{
35+
$this->logData[] = [
36+
'level' => $level,
37+
'message' => $message,
38+
'context' => $context
39+
];
40+
}
41+
42+
/**
43+
* Function to iterate through capture commands and execute them.
44+
*/
45+
public function executeCaptureTests(): void
46+
{
47+
foreach ($this->captureCmds as $index => $command) {
48+
// Set filename for each test command
49+
$this->fileName = sprintf('test-%d.jpg', $index + 1);
50+
$this->tmpFile = $this->tmpFolder . DIRECTORY_SEPARATOR . $this->fileName;
51+
52+
$this->addLog('debug', 'Executing Command #' . ($index + 1), ['command' => $command]);
53+
54+
// Execute the command
55+
$this->executeCmd($command);
56+
}
57+
}
58+
59+
/**
60+
* Function to execute a single command.
61+
*
62+
* @param string $command The command to execute
63+
*/
64+
public function executeCmd(string $command): void
65+
{
66+
// Change directory if using gphoto command
67+
if (substr($command, 0, strlen('gphoto')) === 'gphoto') {
68+
chdir(dirname($this->tmpFile));
69+
}
70+
71+
// Prepare the command and redirect stderr to stdout
72+
$cmd = sprintf($command, $this->tmpFile);
73+
$cmd .= ' 2>&1';
74+
$start_time = hrtime(true);
75+
exec($cmd, $output, $returnValue);
76+
77+
// Handle command errors
78+
if ($returnValue) {
79+
$this->addLog('error', 'Command failed', [
80+
'command' => $command,
81+
'output' => $output,
82+
'returnValue' => $returnValue
83+
]);
84+
return;
85+
} else {
86+
$this->addLog('info', 'Command executed successfully', [
87+
'command' => $command,
88+
'output' => $output
89+
]);
90+
}
91+
92+
// Wait for the file to be created, if necessary
93+
$i = 0;
94+
$processingTime = 300; // 30 seconds (300 * 100ms)
95+
while ($i < $processingTime) {
96+
if (file_exists($this->tmpFile)) {
97+
break;
98+
} else {
99+
$i++;
100+
usleep(100000); // Wait 100ms
101+
}
102+
}
103+
104+
// If the file does not exist, print the error and proceed
105+
if (!file_exists($this->tmpFile)) {
106+
$this->addLog('error', 'File was not created', [
107+
'command' => $command,
108+
'output' => $output,
109+
'returnValue' => $returnValue
110+
]);
111+
}
112+
$end_time = hrtime(true);
113+
$execution_time = $end_time - $start_time;
114+
$execution_time_in_seconds = $execution_time / 1e9;
115+
$this->addLog('info', 'Execution time', [
116+
'output' => $execution_time_in_seconds . ' seconds'
117+
]);
118+
}
119+
}

0 commit comments

Comments
 (0)