Initial commit
This commit is contained in:
commit
e0afabe358
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
pic/
|
||||
fbox.arm
|
||||
.vscode/
|
||||
config.json
|
7
BUILD.ps1
Normal file
7
BUILD.ps1
Normal file
@ -0,0 +1,7 @@
|
||||
echo "Build Linux/arm..."
|
||||
$env:GOOS="linux"; $env:GOARCH="arm"; go build -ldflags="-s -w" -o ./fbox.arm
|
||||
|
||||
#echo "UPX - Compress Static Binaries"
|
||||
#..\upx-3.95-win64\upx.exe -9 ./fbox.arm
|
||||
|
||||
pause
|
18
README.md
Normal file
18
README.md
Normal file
@ -0,0 +1,18 @@
|
||||
# GoFotoBox
|
||||
|
||||
Zum kompilieren folgende Go-Abhängigkeiten installieren:
|
||||
- `go get github.com/gorilla/mux`
|
||||
|
||||
Kompilieren:
|
||||
`$env:GOOS="linux"; $env:GOARCH="arm"; go build -o fbox.arm`
|
||||
|
||||
Beispiel config.json:
|
||||
```
|
||||
{
|
||||
"Host":"http://127.0.0.1",
|
||||
"Port":"8000",
|
||||
"Template":"default",
|
||||
"MQTTServer": "127.0.0.1",
|
||||
"MQTTPort": 8080
|
||||
}
|
||||
```
|
221
main.go
Normal file
221
main.go
Normal file
@ -0,0 +1,221 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var config = readConfig("")
|
||||
|
||||
// our main function
|
||||
func main() {
|
||||
|
||||
// Ausgeben der Config-Optionen
|
||||
fmt.Println("Host: " + config.Host)
|
||||
fmt.Println("Post: " + config.Port)
|
||||
fmt.Println("Template: " + config.Template)
|
||||
fmt.Println("MQTTServer: " + config.MQTTServer)
|
||||
fmt.Println("MQTTPort: " + strconv.Itoa(config.MQTTPort))
|
||||
fmt.Println("OS: " + config.OS)
|
||||
|
||||
router := mux.NewRouter()
|
||||
//router.HandleFunc("/_api/md/{pagename:.*}", getRawPage).Methods("GET")
|
||||
router.HandleFunc("/_api/config", getConfig).Methods("GET")
|
||||
router.HandleFunc("/_api/aufnahme", getAufnahme).Methods("GET")
|
||||
router.HandleFunc("/_api/aufnahme", postAufnahme).Methods("POST")
|
||||
router.HandleFunc("/_api/kamerabild", getKamerabild).Methods("GET")
|
||||
router.HandleFunc("/_api/fotoliste", getFotoliste).Methods("GET")
|
||||
router.PathPrefix("/pic/").Handler(http.StripPrefix("/pic/", http.FileServer(http.Dir("pic")))).Methods("GET")
|
||||
router.PathPrefix("/").Handler(http.FileServer(http.Dir("web"))).Methods("GET")
|
||||
|
||||
log.Fatal(http.ListenAndServe(":"+config.Port, router))
|
||||
|
||||
}
|
||||
|
||||
func getConfig(w http.ResponseWriter, r *http.Request) {
|
||||
json.NewEncoder(w).Encode(config)
|
||||
}
|
||||
|
||||
func getAufnahme(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// raspistill -t 99999999 -p '100,140,800,600'
|
||||
if config.OS == "linux" {
|
||||
cmd := exec.Command("killall", "raspistill")
|
||||
err := cmd.Run()
|
||||
check(err)
|
||||
|
||||
//cmd = exec.Command("/usr/bin/raspistill", "-t 1 -o /home/pi/fbox/pic/tmp.jpg")
|
||||
//cmd = exec.Command("bash", "-c", `/usr/bin/raspistill -p '100,140,800,600' -t 1 -o /home/pi/fbox/pic/tmp.jpg`)
|
||||
cmd = exec.Command("bash", "-c", `/usr/bin/raspistill -op 0 -p '100,140,800,600' -t 1 -o /home/pi/fbox/pic/tmp.jpg`)
|
||||
err = cmd.Run()
|
||||
check(err)
|
||||
} else {
|
||||
copyfile("./pic/Testbild.jpg", "./pic/tmp.jpg")
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode("tmp.jpg")
|
||||
}
|
||||
|
||||
func postAufnahme(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
//fmt.Println("YYYY-MM-DD : ", currentTime.Format("2006-01-02"))
|
||||
currentTime := time.Now()
|
||||
Ordner := currentTime.Format("2006-01-02")
|
||||
if !directoryExists(Ordner) {
|
||||
os.MkdirAll(path.Join("/home/pi/fbox/pic", Ordner), os.ModePerm)
|
||||
}
|
||||
|
||||
//fmt.Println("YYYY-MM-DD hh:mm:ss : ", currentTime.Format("2006-01-02 15:04:05"))
|
||||
Foto := currentTime.Format("150405")
|
||||
copyfile("./pic/tmp.jpg", path.Join("/home/pi/fbox/pic", Ordner, Foto+".jpg"))
|
||||
|
||||
json.NewEncoder(w).Encode(path.Join(Ordner, Foto+".jpg"))
|
||||
}
|
||||
|
||||
func getKamerabild(w http.ResponseWriter, r *http.Request) {
|
||||
if config.OS == "linux" {
|
||||
//cmd := exec.Command("/usr/bin/raspistill", "-t 99999999 -p '100,140,800,600'")
|
||||
cmd := exec.Command("bash", "-c", `/usr/bin/raspistill -t 99999999 -p '100,140,800,600'`)
|
||||
err := cmd.Run()
|
||||
check(err)
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode("OK")
|
||||
}
|
||||
|
||||
func getFotoliste(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
//Livestream der Kamera beenden
|
||||
if config.OS == "linux" {
|
||||
cmd := exec.Command("killall", "raspistill")
|
||||
err := cmd.Run()
|
||||
check(err)
|
||||
}
|
||||
|
||||
// Datum der config auslesen
|
||||
f, err := os.Open("./config.json")
|
||||
check(err)
|
||||
statinfo, err := f.Stat()
|
||||
check(err)
|
||||
ConfigTime := statinfo.ModTime()
|
||||
//fmt.Println(ConfigTime)
|
||||
|
||||
// Dateien herausfinden die neuer als das Config-Datm sind
|
||||
//picfiles, err := ioutil.ReadDir("./pic")
|
||||
//check(err)
|
||||
var files []string
|
||||
|
||||
filepath.Walk("./pic", func(filepath string, file os.FileInfo, err error) error {
|
||||
tmpPath := strings.Replace(filepath, "\\", "/", -1)
|
||||
|
||||
if file.Mode().IsRegular() {
|
||||
//if file.ModTime() > ConfigTime {
|
||||
//fmt.Print(file.Name() + ": ")
|
||||
//fmt.Println(file.ModTime())
|
||||
if file.Name() != "Testbild.jpg" && file.Name() != "TestbildKamera.jpg" && file.Name() != "tmp.jpg" {
|
||||
if inTimeSpan(ConfigTime, time.Now(), file.ModTime()) {
|
||||
files = append(files, tmpPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
/*
|
||||
for _, file := range picfiles {
|
||||
if file.Mode().IsRegular() {
|
||||
//if file.ModTime() > ConfigTime {
|
||||
fmt.Print(file.Name() + ": ")
|
||||
fmt.Println(file.ModTime())
|
||||
if inTimeSpan(ConfigTime, time.Now(), file.ModTime()) {
|
||||
files = append(files, file.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
json.NewEncoder(w).Encode(files)
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Typen
|
||||
//--------------------------------------------------------------------------
|
||||
type Configuration struct {
|
||||
Host string
|
||||
Port string
|
||||
Template string
|
||||
MQTTServer string
|
||||
MQTTPort int
|
||||
OS string
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Hilfsfunktionen
|
||||
//--------------------------------------------------------------------------
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
fmt.Println(e)
|
||||
}
|
||||
}
|
||||
|
||||
func fileExists(filename string) bool {
|
||||
info, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return !info.IsDir()
|
||||
}
|
||||
|
||||
func directoryExists(filename string) bool {
|
||||
info, err := os.Stat(filename)
|
||||
if os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return info.IsDir()
|
||||
}
|
||||
|
||||
func copyfile(source string, destination string) {
|
||||
input, err := ioutil.ReadFile(source)
|
||||
check(err)
|
||||
err = ioutil.WriteFile(destination, input, 0644)
|
||||
check(err)
|
||||
}
|
||||
|
||||
func readConfig(filename string) *Configuration {
|
||||
// initialize conf with default values.
|
||||
conf := &Configuration{
|
||||
Host: "http://127.0.0.1",
|
||||
Port: "8000",
|
||||
Template: "default",
|
||||
MQTTServer: "127.0.0.1",
|
||||
MQTTPort: 8080,
|
||||
OS: runtime.GOOS,
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadFile("./config.json")
|
||||
if err != nil {
|
||||
return conf
|
||||
}
|
||||
if err = json.Unmarshal(b, conf); err != nil {
|
||||
return conf
|
||||
}
|
||||
return conf
|
||||
}
|
||||
|
||||
func inTimeSpan(start, end, check time.Time) bool {
|
||||
return check.After(start) && check.Before(end)
|
||||
}
|
BIN
web/bilder/geburtstag/1.png
Normal file
BIN
web/bilder/geburtstag/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
BIN
web/bilder/geburtstag/2.png
Normal file
BIN
web/bilder/geburtstag/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
web/bilder/geburtstag/3.png
Normal file
BIN
web/bilder/geburtstag/3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 187 KiB |
278
web/index.html
Normal file
278
web/index.html
Normal file
@ -0,0 +1,278 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel=stylesheet href="/misc/bootstrap.min.css">
|
||||
<style>
|
||||
html {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
}
|
||||
body {
|
||||
margin-top: 60px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="TemplateTextHeader" style="position:fixed;top:0px;left:100px">
|
||||
<center>
|
||||
<p id="TemplateHeaderText" style="font-size:35px">
|
||||
Herzlich Willkommen zur Fotobox!<br>
|
||||
Drücke einfach auf "Aufnahme" und los geht es!
|
||||
</p>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
<!-- Template Bild Oben rechts / 1.png-->
|
||||
<div id="TemplatePicOR" style="position:fixed;top:0px;right:0px">
|
||||
<img src="/bilder/geburtstag/1.png">
|
||||
</div>
|
||||
|
||||
<!-- Template Bilder rechts / 2.png-->
|
||||
<div id="TemplatePicR1" style="position:fixed;top:300px;right:0px">
|
||||
<img src="/bilder/geburtstag/2.png">
|
||||
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);">
|
||||
<font size="12"><p id="TemplatePicR1Text">Aufnehmen</p></font>
|
||||
</div>
|
||||
</div>
|
||||
<div id="TemplatePicR2" style="position:fixed;top:450px;right:0px">
|
||||
<img src="/bilder/geburtstag/2.png">
|
||||
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);">
|
||||
<font size="12"><p id="TemplatePicR2Text">Ansehen</p></font>
|
||||
</div>
|
||||
</div>
|
||||
<div id="TemplatePicR3" style="position:fixed;top:600px;right:0px">
|
||||
<img src="/bilder/geburtstag/2.png">
|
||||
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);">
|
||||
<font size="12"><p id="TemplatePicR3Text"> - </p></font>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Template Bild unten / 3.png-->
|
||||
<div id="TemplatePicUN" style="position:fixed;bottom:0px;left:0px">
|
||||
<img src="/bilder/geburtstag/3.png">
|
||||
</div>
|
||||
|
||||
<!-- Bild Kamera / TestbildKamera.jpg-->
|
||||
<div id="TemplateKameraBild" style="position:fixed;top:140px;left:100px">
|
||||
<img id="TemplateKameraTestBild" src="/pic/TestbildKamera.jpg">
|
||||
</div>
|
||||
|
||||
|
||||
<script language=javascript src="/misc/jquery.min.js"></script>
|
||||
<script language=javascript src="/misc/mqttws31.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var PageMode = "start";
|
||||
var AnzeigeFoto = "";
|
||||
$(document).ready(function() {
|
||||
|
||||
// Laden der Config
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
contentType:'application/json; charset=utf-8',
|
||||
url: '/_api/config',
|
||||
dataType: "json",
|
||||
data: "",
|
||||
success: function(content){
|
||||
LoadTemplate(content.Template);
|
||||
MakeMQTTConnection(content.MQTTServer, content.MQTTPort);
|
||||
|
||||
// Wenn auf dem Pi ausgeführt wird, soll das Testbild nicht angezeigt werden
|
||||
if(content.OS!="windows") {
|
||||
$("#TemplateKameraTestBild").remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function LoadTemplate(TemplateName) {
|
||||
$("#TemplatePicOR").html('<img src="/bilder/'+TemplateName+'/1.png">');
|
||||
$("#TemplatePicR1").html(LoadTemplateButtonRechts(TemplateName,"TemplatePicR1Text","2.png","Aufnehmen"));
|
||||
$("#TemplatePicR2").html(LoadTemplateButtonRechts(TemplateName,"TemplatePicR2Text","2.png","Ansehen"));
|
||||
$("#TemplatePicR3").html(LoadTemplateButtonRechts(TemplateName,"TemplatePicR3Text","2.png","- - - - - "));
|
||||
$("#TemplatePicUN").html('<img src="/bilder/'+TemplateName+'/3.png">');
|
||||
}
|
||||
|
||||
function LoadTemplateButtonRechts(TemplateName, Pid, Bild, Text) {
|
||||
var html_ButtonRechts = '<img src="/bilder/'+TemplateName+'/'+Bild+'">'+
|
||||
'<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);">'+
|
||||
'<font size="12"><p id="'+Pid+'">'+Text+'</p></font>'+
|
||||
'</div>';
|
||||
return html_ButtonRechts;
|
||||
}
|
||||
|
||||
function MakeMQTTConnection(MQTTServer, MQTTPort) {
|
||||
var MQTTClient = new Messaging.Client(MQTTServer, MQTTPort, "myclientid_" + parseInt(Math.random() * 100, 10));
|
||||
|
||||
var options = {
|
||||
timeout: 3,
|
||||
onSuccess: function () {
|
||||
console.log("MQTT Client Connected!");
|
||||
MQTTClient.subscribe('/pin'+'/#', {qos: 2});
|
||||
},
|
||||
onFailure: function (message) {
|
||||
console.log("Connection failed: " + message.errorMessage);
|
||||
}
|
||||
};
|
||||
MQTTClient.connect(options);
|
||||
|
||||
MQTTClient.onConnectionLost = function (responseObject) {
|
||||
console.log("connection lost: " + responseObject.errorMessage);
|
||||
};
|
||||
|
||||
MQTTClient.onMessageArrived = function (message) {
|
||||
console.log('Payload: Topic: ' + message.destinationName + ' | ' + message.payloadString);
|
||||
if(message.destinationName=="/pin/17") {
|
||||
if(message.payloadString=="1") {
|
||||
if(PageMode=="vorschau") {
|
||||
Fotospeichern();
|
||||
} else if(PageMode=="FotosAnschauen") {
|
||||
FotosAnschauen("vor");
|
||||
} else {
|
||||
Aufnahme();
|
||||
}
|
||||
}
|
||||
} else if(message.destinationName=="/pin/21") {
|
||||
if(message.payloadString=="1") {
|
||||
if(PageMode=="start") {
|
||||
FotosAnschauen("start");
|
||||
} else if(PageMode=="vorschau") {
|
||||
Abbrechen();
|
||||
} else if(PageMode=="FotosAnschauen") {
|
||||
FotosAnschauen("zurueck");
|
||||
}else {
|
||||
//Aufnahme();
|
||||
}
|
||||
}
|
||||
} else if(message.destinationName=="/pin/22") {
|
||||
if(message.payloadString=="1") {
|
||||
if(PageMode=="FotosAnschauen") {
|
||||
Abbrechen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async function Aufnahme() {
|
||||
// x sec warten vor Aufnahme
|
||||
for (i = 5; i >0 ; i--) {
|
||||
console.log(i);
|
||||
$("#TemplateHeaderText").html('Foto wird in '+i+' sec aufgenommen.<br>Bitte lächeln!');
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
}
|
||||
|
||||
// Aufnahme starten
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
contentType:'application/json; charset=utf-8',
|
||||
url: '/_api/aufnahme',
|
||||
dataType: "json",
|
||||
data: "",
|
||||
success: function(content){
|
||||
$("#TemplateKameraBild").html('<img width="800px" src="/pic/'+content+'?'+parseInt(Math.random() * 100, 10)+'">');
|
||||
$("#TemplatePicR1Text").html('Speichern');
|
||||
$("#TemplatePicR2Text").html('Abbrechen');
|
||||
//$("#TemplatePicR3Text").html('<img src="/pic/'+content+'">');
|
||||
PageMode = "vorschau";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function Fotospeichern() {
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
contentType:'application/json; charset=utf-8',
|
||||
url: '/_api/aufnahme',
|
||||
dataType: "json",
|
||||
data: "",
|
||||
success: function(content){
|
||||
SetTemplateStart();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function FotosAnschauen(voroderzurueck) {
|
||||
console.log("FotosAnschauen");
|
||||
PageMode="FotosAnschauen";
|
||||
|
||||
$("#TemplatePicR1Text").html('Vor');
|
||||
$("#TemplatePicR2Text").html('Zurück');
|
||||
$("#TemplatePicR3Text").html('Abbrechen');
|
||||
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
contentType:'application/json; charset=utf-8',
|
||||
url: '/_api/fotoliste',
|
||||
dataType: "json",
|
||||
data: "",
|
||||
success: function(content){
|
||||
|
||||
console.log("voroderzurueck: "+voroderzurueck);
|
||||
|
||||
// Wenn der Menüpunkt "Anschauen" ausgewöhlt wird, muss as letzte Bild angezeigt werden
|
||||
if(voroderzurueck=="start") {
|
||||
var Foto = content[content.length-1];
|
||||
AnzeigeFoto=Foto;
|
||||
$("#TemplateKameraBild").html('<img id="TemplateKameraTestBild" width="800px" height="600px" src="/'+Foto+'">');
|
||||
}
|
||||
|
||||
if(voroderzurueck=="vor") {
|
||||
var Foto = content[content.indexOf(AnzeigeFoto)+1]
|
||||
if(Foto!==undefined) {
|
||||
AnzeigeFoto=Foto;
|
||||
$("#TemplateKameraBild").html('<img id="TemplateKameraTestBild" width="800px" height="600px" src="/'+Foto+'">');
|
||||
}
|
||||
}
|
||||
|
||||
if(voroderzurueck=="zurueck") {
|
||||
var Foto = content[content.indexOf(AnzeigeFoto)-1]
|
||||
if(Foto!==undefined) {
|
||||
AnzeigeFoto=Foto;
|
||||
$("#TemplateKameraBild").html('<img id="TemplateKameraTestBild" width="800px" height="600px" src="/'+Foto+'">');
|
||||
}
|
||||
}
|
||||
|
||||
console.log(AnzeigeFoto);
|
||||
console.log("PageMode: "+PageMode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function Abbrechen() {
|
||||
SetTemplateStart();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Hilsfunktionen
|
||||
function sleep(milliseconds) {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
}
|
||||
|
||||
function SetTemplateStart() {
|
||||
$("#TemplateHeaderText").html('Herzlich Willkommen zur Fotobox!<br>Drücke einfach auf "Aufnahme" und los geht es!');
|
||||
$("#TemplateKameraBild").html('<img src="/pic/TestbildKamera.jpg">');
|
||||
$("#TemplatePicR1Text").html('Aufnehmen');
|
||||
$("#TemplatePicR2Text").html('Ansehen');
|
||||
$("#TemplateKameraTestBild").remove();
|
||||
PageMode = "start";
|
||||
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
contentType:'application/json; charset=utf-8',
|
||||
url: '/_api/kamerabild',
|
||||
dataType: "json",
|
||||
data: "",
|
||||
success: function(content){
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
5
web/misc/bootstrap.min.css
vendored
Normal file
5
web/misc/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
7
web/misc/bootstrap.min.js
vendored
Normal file
7
web/misc/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
web/misc/jquery.min.js
vendored
Normal file
6
web/misc/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1958
web/misc/mqttws31.js
Normal file
1958
web/misc/mqttws31.js
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user