added upload?

This commit is contained in:
henne 2025-08-10 19:52:49 +01:00
parent 31ba099dc6
commit 852b612374
No known key found for this signature in database
6 changed files with 185 additions and 13 deletions

View file

@ -9,16 +9,22 @@ import (
) )
var camera *gphoto2.Camera var camera *gphoto2.Camera
var cameraInit = false
func init() { func init() {
var err error var err error
camera, err = gphoto2.NewCamera("") camera, err = gphoto2.NewCamera("")
if err != nil { if err != nil {
log.Printf("could not connect to camera") log.Printf("could not connect to camera")
return
} }
cameraInit = true
} }
func TakePhoto(id string) error { func TakePhoto(id string) error {
if !cameraInit {
return nil
}
filename := fmt.Sprintf("images/original/ticket-%s.jpg", id) filename := fmt.Sprintf("images/original/ticket-%s.jpg", id)
file, err := os.Create(filename) file, err := os.Create(filename)
if err != nil { if err != nil {

View file

@ -1,14 +1,16 @@
package printer package printer
import ( import (
"fmt"
"image" "image"
_ "image/jpeg"
"log"
"net"
"os" "os"
"git.ctdo.de/henne/blitzer-v2/config" "git.ctdo.de/henne/blitzer-v2/config"
"git.ctdo.de/henne/blitzer-v2/db" "git.ctdo.de/henne/blitzer-v2/db"
"github.com/hennedo/escpos" "github.com/hennedo/escpos"
"github.com/sirupsen/logrus"
"go.bug.st/serial"
) )
var printer *escpos.Escpos var printer *escpos.Escpos
@ -18,23 +20,18 @@ func init() {
if config.C.PrinterPort == "" { if config.C.PrinterPort == "" {
return return
} }
socket, err := serial.Open(config.C.PrinterPort, &serial.Mode{ socket, err := net.Dial("tcp", config.C.PrinterPort)
BaudRate: 19200,
StopBits: serial.OneStopBit,
DataBits: 8,
Parity: serial.NoParity,
})
if err != nil { if err != nil {
logrus.Panicf("printer error serial port: %s", err) log.Printf("printer error serial port: %s", err)
} }
printer = escpos.New(socket) printer = escpos.New(socket)
imageFile, err := os.Open("webserver/assets/img/traffic_police.jpg") imageFile, err := os.Open("webserver/assets/img/traffic_police.jpg")
if err != nil { if err != nil {
logrus.Errorf("error loading image: %s", err) log.Printf("error loading image: %s", err)
} }
whyImage, _, err = image.Decode(imageFile) whyImage, _, err = image.Decode(imageFile)
if err != nil { if err != nil {
logrus.Errorf("image decoding error: %s", err) log.Printf("image decoding error: %s", err)
} }
} }
@ -44,5 +41,36 @@ func PrintTicket(ticket db.SpeedingTicket) {
return return
} }
printer.Initialize() printer.Initialize()
printer.PrintImage(whyImage) //printer.PrintImage(whyImage)
printer.Justify(escpos.JustifyCenter)
printer.Bold(true).Size(2, 2).Write("WHY Traffic Police")
printer.LineFeed()
printer.LineFeed()
printer.Bold(false).Size(1, 1).WriteWEU("Traffic Violation")
printer.LineFeed()
printer.LineFeed()
printer.Bold(false).Size(1, 1).WriteWEU("Dear being,")
printer.LineFeed()
time := ticket.CreatedAt
speed := ticket.Speed
limit := ticket.AllowedSpeed
printer.Bold(false).Size(1, 1).WriteWEU("we have found that you have violated")
printer.LineFeed()
printer.Bold(true).WriteWEU("WHY2025 traffic rules")
printer.LineFeed()
printer.Bold(false).WriteWEU(fmt.Sprintf("At %s on the %s", time.Format("03:04:05"), time.Format("02.01.2006")))
printer.LineFeed()
printer.WriteWEU("you exceeded the maximum allowed Speed of")
printer.LineFeed()
printer.WriteWEU(fmt.Sprintf("%dkm/h by %dkm/h", limit, speed-limit))
printer.LineFeed()
printer.WriteWEU(fmt.Sprintf("reaching a speed of %dkm/h", speed))
printer.LineFeed()
printer.QRCode("https://traffic.dre.li/ticket/"+ticket.ID.String(), true, 10, escpos.QRCodeErrorCorrectionLevelH)
printer.LineFeed()
printer.WriteWEU("find your ticket including proof online.")
printer.LineFeed()
printer.LineFeed()
printer.LineFeed()
printer.PrintAndCut()
} }

View file

@ -11,6 +11,7 @@ import (
"git.ctdo.de/henne/blitzer-v2/printer" "git.ctdo.de/henne/blitzer-v2/printer"
"git.ctdo.de/henne/blitzer-v2/radar_lib" "git.ctdo.de/henne/blitzer-v2/radar_lib"
"git.ctdo.de/henne/blitzer-v2/speedsign" "git.ctdo.de/henne/blitzer-v2/speedsign"
"git.ctdo.de/henne/blitzer-v2/upload"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -18,10 +19,16 @@ var r *radar_lib.Radar
var speedFree = true var speedFree = true
var eventFree = true var eventFree = true
var radarInit = false
func init() { func init() {
if config.C.Radar.Port == "" {
return
}
r = radar_lib.New(config.C.Radar.Port, config.C.Radar.Baud) r = radar_lib.New(config.C.Radar.Port, config.C.Radar.Baud)
r.SetEventHandler(onEvent) r.SetEventHandler(onEvent)
r.SetSpeedHandler(onSpeedEvent) r.SetSpeedHandler(onSpeedEvent)
radarInit = true
} }
func onSpeedEvent(speed int) { func onSpeedEvent(speed int) {
@ -54,9 +61,13 @@ func onEvent(speed int) {
} }
printer.PrintTicket(speedingTicket) printer.PrintTicket(speedingTicket)
eventFree = true eventFree = true
go upload.UploadTicket(speedingTicket)
} }
func SetConfig(height int, angle int, waveform bool) { func SetConfig(height int, angle int, waveform bool) {
if !radarInit {
return
}
if waveform { if waveform {
err := r.SetBaseConfig(height, angle, 1) err := r.SetBaseConfig(height, angle, 1)
if err != nil { if err != nil {
@ -71,6 +82,9 @@ func SetConfig(height int, angle int, waveform bool) {
} }
func SetSpeedConfig(speed int, minDistance, maxDistance, minSpeed, maxSpeed, triggerDistance int) { func SetSpeedConfig(speed int, minDistance, maxDistance, minSpeed, maxSpeed, triggerDistance int) {
if !radarInit {
return
}
err := r.SetTargetSpeedConfig(radar_lib.DirectionIncoming, minDistance*2, maxDistance*2, minSpeed, maxSpeed, speed, radar_lib.OutputLogicMostPlausible) err := r.SetTargetSpeedConfig(radar_lib.DirectionIncoming, minDistance*2, maxDistance*2, minSpeed, maxSpeed, speed, radar_lib.OutputLogicMostPlausible)
if err != nil { if err != nil {
log.Printf("%v", err) log.Printf("%v", err)
@ -83,6 +97,9 @@ func SetSpeedConfig(speed int, minDistance, maxDistance, minSpeed, maxSpeed, tri
} }
func SetCommunicationConfig(speedOutput, targetOutput, triggerOutput int) { func SetCommunicationConfig(speedOutput, targetOutput, triggerOutput int) {
if !radarInit {
return
}
err := r.SetCommunicationConfig(radar_lib.PortRS485, radar_lib.Baud115200, radar_lib.OutputType(speedOutput), radar_lib.OutputType(targetOutput), radar_lib.OutputType(triggerOutput), 1000) err := r.SetCommunicationConfig(radar_lib.PortRS485, radar_lib.Baud115200, radar_lib.OutputType(speedOutput), radar_lib.OutputType(targetOutput), radar_lib.OutputType(triggerOutput), 1000)
if err != nil { if err != nil {
log.Printf("%v", err) log.Printf("%v", err)

119
upload/main.go Normal file
View file

@ -0,0 +1,119 @@
package upload
import (
"bytes"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"git.ctdo.de/henne/blitzer-v2/db"
"github.com/gin-gonic/gin"
)
// var uploadHost string = "https://traffic.dre.li/api/"
var uploadHost string = "http://localhost:3000/api/"
func UploadTicket(ticket db.SpeedingTicket) error {
// Buffer für den Request-Body
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
filePath := fmt.Sprintf("images/original/ticket-%s.jpg", ticket.ID.String())
// 1⃣ JSON-Payload als Form-Feld hinzufügen
jsonData, err := json.Marshal(ticket)
if err != nil {
return fmt.Errorf("fehler beim Marshallen: %w", err)
}
err = writer.WriteField("payload", string(jsonData))
if err != nil {
return fmt.Errorf("fehler beim Hinzufügen des JSON-Feldes: %w", err)
}
// 2⃣ Datei hinzufügen
file, err := os.Open(filePath)
if err != nil {
return fmt.Errorf("fehler beim Öffnen der Datei: %w", err)
}
defer file.Close()
filePart, err := writer.CreateFormFile("file", filePath)
if err != nil {
return fmt.Errorf("fehler beim Erstellen des Datei-Feldes: %w", err)
}
_, err = io.Copy(filePart, file)
if err != nil {
return fmt.Errorf("fehler beim Kopieren der Datei: %w", err)
}
// Multipart-Writer schließen (setzt den Boundary korrekt)
err = writer.Close()
if err != nil {
return fmt.Errorf("fehler beim Schließen des Writers: %w", err)
}
// 3⃣ Request erstellen & senden
req, err := http.NewRequest("POST", uploadHost+"ticket", body)
if err != nil {
return fmt.Errorf("fehler beim Erstellen des Requests: %w", err)
}
req.Header.Set("Content-Type", writer.FormDataContentType())
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("fehler beim Senden: %w", err)
}
defer resp.Body.Close()
// Optional: Antwort prüfen
if resp.StatusCode != http.StatusOK {
respBody, _ := io.ReadAll(resp.Body)
return fmt.Errorf("server returned %s: %s", resp.Status, string(respBody))
}
return nil
}
func HandleUpload(c *gin.Context) {
// 1⃣ JSON-Feld "payload" auslesen
payloadStr := c.PostForm("payload")
if payloadStr == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "payload fehlt"})
return
}
var payload db.SpeedingTicket
if err := json.Unmarshal([]byte(payloadStr), &payload); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "ungültiges JSON", "details": err.Error()})
return
}
db.DB.Create(&payload)
fmt.Println("Empfangene Daten:", payload)
// 2⃣ Datei auslesen
file, err := c.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Datei fehlt", "details": err.Error()})
return
}
// Datei speichern
filename := fmt.Sprintf("images/original/ticket-%s.jpg", payload.ID.String())
if err := c.SaveUploadedFile(file, filename); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Fehler beim Speichern", "details": err.Error()})
return
}
// 3⃣ Antwort
c.JSON(http.StatusOK, gin.H{
"status": "ok",
"file": filename,
"data": payload,
})
}

View file

@ -13,6 +13,7 @@ import (
"git.ctdo.de/henne/blitzer-v2/config" "git.ctdo.de/henne/blitzer-v2/config"
"git.ctdo.de/henne/blitzer-v2/db" "git.ctdo.de/henne/blitzer-v2/db"
"git.ctdo.de/henne/blitzer-v2/upload"
"git.ctdo.de/henne/blitzer-v2/webserver/template_functions" "git.ctdo.de/henne/blitzer-v2/webserver/template_functions"
"github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/gorm" "github.com/gin-contrib/sessions/gorm"
@ -93,6 +94,7 @@ func Init() {
r.GET("test", HandleTest) r.GET("test", HandleTest)
r.GET("ticket/:id/delete", HandleDelete) r.GET("ticket/:id/delete", HandleDelete)
r.GET("ticket/:id", HandleTicket) r.GET("ticket/:id", HandleTicket)
r.POST("api/ticket", upload.HandleUpload)
//r.POST("/login", loginHandler) //r.POST("/login", loginHandler)
//r.GET("/logout", helper.LoggedIn, logoutHandler) //r.GET("/logout", helper.LoggedIn, logoutHandler)

View file

@ -22,7 +22,7 @@
<div class="grid"> <div class="grid">
<div> <div>
Dear beeing,<br /> Dear being,<br />
<p>we have found that you have violated WHY2025 traffic rules. At {{.Ticket.CreatedAt.Format "15:04:05"}} on the <p>we have found that you have violated WHY2025 traffic rules. At {{.Ticket.CreatedAt.Format "15:04:05"}} on the
{{.Ticket.CreatedAt.Format "02.01.2006" }} you exceeded the maximum allowed Speed of <b>{{.Ticket.AllowedSpeed}}km/h</b> by {{.Ticket.CreatedAt.Format "02.01.2006" }} you exceeded the maximum allowed Speed of <b>{{.Ticket.AllowedSpeed}}km/h</b> by
{{.Exceeded}}km/h, reaching a speed of <b>{{.Ticket.Speed}}km/h</b></p> {{.Exceeded}}km/h, reaching a speed of <b>{{.Ticket.Speed}}km/h</b></p>