mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 05:00:20 +00:00
downloader: make cgi-script functional and add documentation
Signed-off-by: Robert C. Helling <helling@atdotde.de>
This commit is contained in:
parent
40311362f3
commit
8934d9744a
3 changed files with 1663 additions and 12 deletions
47
packaging/headless/Setting-up-downloader
Normal file
47
packaging/headless/Setting-up-downloader
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
How to set up a Raspberry Pi to use as a Subsurface downloader
|
||||||
|
|
||||||
|
1) Get an image file for RaspianPi
|
||||||
|
|
||||||
|
2) Set up your local network according to https://www.raspberrypi.org/documentation/configuration/wireless/headless.md
|
||||||
|
You also need to create a file named "ssh" in the boot partition to enable the ssh server. Set the hostname to subsurfacepi
|
||||||
|
|
||||||
|
3) apt-get install some more packages. On my pi, the packages listed in downloader_packages are installed, you can install them with
|
||||||
|
sudo xargs -a downloader_packages apt install
|
||||||
|
|
||||||
|
4) Clone the subsurface repository and build it as for any Debian based system: Run build.sh, then cd to the build directory, run
|
||||||
|
ccamke .
|
||||||
|
and select SUBSURFACE_TARGET_EXECUTABLE as DownloaderExecutable and make once more
|
||||||
|
|
||||||
|
5) Add the following lines to /etc/apache2/sites-available/000-default.conf
|
||||||
|
|
||||||
|
ScriptAlias /pi-cgi-bin/ /home/pi/cgi-bin/
|
||||||
|
<Directory "/home/pi/cgi-bin">
|
||||||
|
AllowOverride None
|
||||||
|
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
|
||||||
|
Order allow,deny
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
|
<Directory "/usr/lib/cgi-bin">
|
||||||
|
AllowOverride None
|
||||||
|
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
|
||||||
|
Order allow,deny
|
||||||
|
Allow from all
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
and restart apache2
|
||||||
|
|
||||||
|
6) copy ~/src/subsurface/scripts/downloader.pl to /usr/lib/cgi-bin and run
|
||||||
|
sudo chmod a+x /usr/lib/cgi-bin/downloader.pl
|
||||||
|
It should then be there when you direct your browser to
|
||||||
|
subsurfacepi.local/cgi-bin/downloader.pl
|
||||||
|
|
||||||
|
7) Give the www user access to the serial interface
|
||||||
|
sudo adduser pi dialout
|
||||||
|
and restart apache2
|
||||||
|
|
||||||
|
8) Create a directory to store the data
|
||||||
|
sudo mkdir /opt/ssrf/
|
||||||
|
sudo touch /opt/ssrf/ssrf.conf
|
||||||
|
sudo chown -R www-data.www-data /opt/ssrf
|
||||||
|
|
||||||
|
9) If you want to use the pi with an iPhone where the iPhone provides the internet connectivity, follow https://gist.github.com/antronic/157e047cdefa98b3150195c2eacb56b8
|
1473
packaging/headless/downloader_packages
Normal file
1473
packaging/headless/downloader_packages
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,21 @@
|
||||||
#!/usr/bin/perl
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
use CGI;
|
use CGI;
|
||||||
|
use Git::Repository;
|
||||||
|
|
||||||
|
# File to store cloud credentials
|
||||||
|
my $config_file = "/opt/ssrf/ssrf.conf";
|
||||||
|
# Where to store the git repository
|
||||||
|
my $git_dir = "/opt/ssrf/gitdir";
|
||||||
|
# Downloader binary
|
||||||
|
my $downloader = "/home/pi/src/subsurface/build/subsurface-downloader";
|
||||||
|
|
||||||
|
my %conf;
|
||||||
|
|
||||||
|
# Use unbuffered output
|
||||||
|
$| = 1;
|
||||||
|
|
||||||
my $q = CGI->new;
|
my $q = CGI->new;
|
||||||
|
|
||||||
|
@ -8,32 +23,129 @@ print $q->header('text/html');
|
||||||
print $q->img({src => 'https://subsurface-divelog.org/wp-content/uploads/2015/10/subsurface-icon1.png'});
|
print $q->img({src => 'https://subsurface-divelog.org/wp-content/uploads/2015/10/subsurface-icon1.png'});
|
||||||
print $q->h1("Subsurface");
|
print $q->h1("Subsurface");
|
||||||
|
|
||||||
|
printf "Reading config file $config_file\n";
|
||||||
|
open CONF, $config_file || die "Cannot read $config_file:$!";
|
||||||
|
while (<CONF>) {
|
||||||
|
if (/^\s*(\w+)\s*=\s*(\w.*)$/) {
|
||||||
|
$conf{$1} = $2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close CONF;
|
||||||
|
|
||||||
my %dcs;
|
my %dcs;
|
||||||
&load_supported_dcs;
|
&load_supported_dcs;
|
||||||
|
|
||||||
print $q->start_form();
|
print $q->start_form();
|
||||||
if ($q->param("Manufacturer")) {
|
|
||||||
|
my $action = $q->param("action");
|
||||||
|
|
||||||
|
if ($action eq "config") {
|
||||||
|
|
||||||
|
# Enter cloud credentials
|
||||||
|
|
||||||
|
print "Subsurface cloud user name (typically your email address): ", $q->textfield(-name => 'username', -default => $conf{username});
|
||||||
|
print "<br>Subsurface cloud password: ", $q->password_field(-name => "password");
|
||||||
|
&next_action("writeconfig");
|
||||||
|
|
||||||
|
} elsif ($action eq "writeconfig") {
|
||||||
|
|
||||||
|
$conf{username} = $q->param("username");
|
||||||
|
$conf{username} =~ s/\s//g;
|
||||||
|
$conf{password} = $q->param("password");
|
||||||
|
$conf{password} =~ s/\s//g;
|
||||||
|
&write_conf;
|
||||||
|
&next_action("start");
|
||||||
|
|
||||||
|
} elsif ($action eq "setmanufacturer") {
|
||||||
|
|
||||||
|
# Now we know the manufacturer, ask for model
|
||||||
|
|
||||||
print $q->hidden(-name => "Manufacturer", -default => $q->param("Manufacturer"));
|
print $q->hidden(-name => "Manufacturer", -default => $q->param("Manufacturer"));
|
||||||
if ($q->param("Product")) {
|
print "Select ",$q->param("Manufacturer")," model:";
|
||||||
print $q->hidden(-name => "Product", -default => $q->param("Product"));
|
print $q->popup_menu("Product", $dcs{$q->param("Manufacturer")});
|
||||||
opendir DIR, "/dev";
|
&next_action("setproduct")
|
||||||
my @devices = map {"/dev/$_"} (grep {!/^\./} (readdir DIR));
|
|
||||||
closedir DIR;
|
} elsif ($action eq "setproduct") {
|
||||||
print "Select mount point:";
|
|
||||||
print $q->popup_menu("Mount point", \@devices);
|
# Now we know the model as well, ask for mount point
|
||||||
|
|
||||||
|
print $q->hidden(-name => "Manufacturer", -default => $q->param("Manufacturer"));
|
||||||
|
print $q->hidden(-name => "Product", -default => $q->param("Product"));
|
||||||
|
|
||||||
|
opendir DIR, "/dev";
|
||||||
|
my @devices = map {"/dev/$_"} (grep {!/^\./} (readdir DIR));
|
||||||
|
closedir DIR;
|
||||||
|
print "Select mount point:";
|
||||||
|
print $q->popup_menu(-name => "Mount point", -values => \@devices);
|
||||||
|
&next_action("startdownload");
|
||||||
|
|
||||||
|
} elsif ($action eq "startdownload") {
|
||||||
|
|
||||||
|
# Do the actual download
|
||||||
|
|
||||||
|
my $repo;
|
||||||
|
|
||||||
|
# Does the repo exist?
|
||||||
|
|
||||||
|
if (-d $git_dir) {
|
||||||
|
|
||||||
|
# ... yes, pull latest version
|
||||||
|
|
||||||
|
$repo = Git::Repository->new( work_tree => $git_dir);
|
||||||
|
print "Pulling latest version from cloud.";
|
||||||
|
print $q->pre($repo->run("pull"));
|
||||||
} else {
|
} else {
|
||||||
print "Select ",$q->param("Manufacturer")," model:";
|
|
||||||
print $q->popup_menu("Product", $dcs{$q->param("Manufacturer")});
|
# ... no, clone it
|
||||||
|
|
||||||
|
my $en_username = $conf{username};
|
||||||
|
|
||||||
|
# We need to escape the @ in the username to be able to encode it in the URL.
|
||||||
|
# Note: If we fail, the password gets written to /var/log/apache/error.log,
|
||||||
|
# Maybe there is a better way to pass the password to git...
|
||||||
|
|
||||||
|
$en_username =~ s/\@/%40/g;
|
||||||
|
my $git_url = 'https://' . $en_username . ':' . $conf{password} . '@cloud.subsurface-divelog.org//git/' . $conf{username};
|
||||||
|
print "Cloning repository";
|
||||||
|
print $q->pre(Git::Repository->run( clone => $git_url, $git_dir));
|
||||||
|
$repo = Git::Repository->new( work_tree => $git_dir );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Assemble the command with all arguments
|
||||||
|
|
||||||
|
my $command = "$downloader --dc-vendor=" . $q->param('Manufacturer') .
|
||||||
|
" --dc-product=" . $q->param('Product') .
|
||||||
|
" --device=" . $q->param("Mount point") .
|
||||||
|
' ' . $git_dir .
|
||||||
|
'/[' . $conf{username} . ']';
|
||||||
|
print $q->pre($command);
|
||||||
|
|
||||||
|
# ... and run it
|
||||||
|
|
||||||
|
print $q->pre(`$command`);
|
||||||
|
|
||||||
|
# Push back to the cloud
|
||||||
|
|
||||||
|
print "Checkout user branch";
|
||||||
|
print $q->pre($repo->run("checkout", $conf{username}));
|
||||||
|
print "Push changes to cloud";
|
||||||
|
print $q->pre($repo->run("push", "origin", $conf{username}));
|
||||||
|
&next_action("start");
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
# This is the mode we start up in
|
||||||
|
|
||||||
print "Select dive computer manufacturer:";
|
print "Select dive computer manufacturer:";
|
||||||
print $q->popup_menu("Manufacturer", [sort keys %dcs]);
|
print $q->popup_menu("Manufacturer", [sort keys %dcs]);
|
||||||
|
&next_action("setmanufacturer")
|
||||||
}
|
}
|
||||||
|
|
||||||
print $q->submit();
|
|
||||||
|
|
||||||
|
print $q->br(),$q->submit(-name => " OK ");
|
||||||
print $q->end_form();
|
print $q->end_form();
|
||||||
|
|
||||||
|
print $q->br(), $q->a({-href => $q->url() . "?action=config"}, "Configure cloud credentials");
|
||||||
|
|
||||||
sub load_supported_dcs {
|
sub load_supported_dcs {
|
||||||
open IN, "/home/pi/src/subsurface/build/subsurface-downloader --list-dc|";
|
open IN, "/home/pi/src/subsurface/build/subsurface-downloader --list-dc|";
|
||||||
|
|
||||||
|
@ -51,3 +163,22 @@ sub load_supported_dcs {
|
||||||
close IN;
|
close IN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sub write_conf {
|
||||||
|
print "Writing config file\n";
|
||||||
|
open CONFW, ">$config_file" || die "Cannot write $config_file:$!";
|
||||||
|
foreach my $key (keys %conf) {
|
||||||
|
print CONFW "$key = $conf{$key}\n";
|
||||||
|
}
|
||||||
|
close CONFW;
|
||||||
|
print "Done\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub next_action {
|
||||||
|
my $next = shift;
|
||||||
|
$q->param(action => $next);
|
||||||
|
print $q->hidden(
|
||||||
|
-name => "action",
|
||||||
|
-value => $next);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue