first commit
This commit is contained in:
commit
6811f87281
8 changed files with 218 additions and 0 deletions
1
.dockerignore
Normal file
1
.dockerignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
db/
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
db/
|
12
Dockerfile
Normal file
12
Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM golang:1.19
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN go build -o main .
|
||||||
|
|
||||||
|
CMD ["./main"]
|
49
docker-compose.yml
Normal file
49
docker-compose.yml
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
build: .
|
||||||
|
depends_on:
|
||||||
|
- mariadb
|
||||||
|
- db-rest
|
||||||
|
environment:
|
||||||
|
- DB_HOST=mariadb
|
||||||
|
- DB_USER=root
|
||||||
|
- DB_PASSWORD=password
|
||||||
|
- DB_NAME=traindb
|
||||||
|
- DB_DSN=root:password@tcp(mariadb:3306)/traindb
|
||||||
|
- API_BASE_URL=http://db-rest:3000
|
||||||
|
- MAX_RESULTS=100
|
||||||
|
- BUS=false
|
||||||
|
# Hildesheim HBF, Braunschweig HBF, Hannover HBF
|
||||||
|
- STATION_IDS=8000169,8000049,8000152
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
|
||||||
|
mariadb:
|
||||||
|
image: mariadb:10.5
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: password
|
||||||
|
MYSQL_DATABASE: traindb
|
||||||
|
volumes:
|
||||||
|
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||||
|
- ./db:/var/lib/mysql
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
dns:
|
||||||
|
ipv4_address: 172.28.0.65
|
||||||
|
|
||||||
|
db-rest:
|
||||||
|
image: docker.io/derhuerst/db-rest:6
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:3010:3000
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
dns:
|
||||||
|
name: dns
|
||||||
|
external: true
|
10
go.mod
Normal file
10
go.mod
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
module train-tracker
|
||||||
|
|
||||||
|
go 1.19
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require filippo.io/edwards25519 v1.1.0 // indirect
|
6
go.sum
Normal file
6
go.sum
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
8
init.sql
Normal file
8
init.sql
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS trips (
|
||||||
|
id VARCHAR(36) PRIMARY KEY,
|
||||||
|
latitude DOUBLE,
|
||||||
|
longitude DOUBLE,
|
||||||
|
timestamp DATETIME,
|
||||||
|
train_name VARCHAR(50),
|
||||||
|
fahrt_nr VARCHAR(20)
|
||||||
|
);
|
131
main.go
Normal file
131
main.go
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Departure struct {
|
||||||
|
CurrentTripPosition struct {
|
||||||
|
Latitude float64 `json:"latitude"`
|
||||||
|
Longitude float64 `json:"longitude"`
|
||||||
|
} `json:"currentTripPosition"`
|
||||||
|
When time.Time `json:"when"`
|
||||||
|
Line struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
FahrtNr string `json:"fahrtNr"`
|
||||||
|
} `json:"line"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type APIResponse struct {
|
||||||
|
Departures []Departure `json:"departures"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
log.SetOutput(os.Stdout)
|
||||||
|
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
||||||
|
log.Println("Anwendung gestartet")
|
||||||
|
|
||||||
|
dbDSN := os.Getenv("DB_DSN")
|
||||||
|
apiBaseURL := os.Getenv("API_BASE_URL")
|
||||||
|
maxResults, err := strconv.Atoi(os.Getenv("MAX_RESULTS"))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Ungültiger Wert für MAX_RESULTS: %v", err)
|
||||||
|
}
|
||||||
|
includeBus, err := strconv.ParseBool(os.Getenv("BUS"))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Ungültiger Wert für BUS: %v", err)
|
||||||
|
}
|
||||||
|
stationIDs := strings.Split(os.Getenv("STATION_IDS"), ",")
|
||||||
|
|
||||||
|
db, err := sql.Open("mysql", dbDSN)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Fehler beim Verbinden mit der Datenbank: ", err)
|
||||||
|
}
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
for {
|
||||||
|
for _, stationID := range stationIDs {
|
||||||
|
departures := fetchDepartures(apiBaseURL, stationID, maxResults, includeBus)
|
||||||
|
for _, dep := range departures {
|
||||||
|
savePosition(db, dep)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Minute)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchDepartures(apiBaseURL, stationID string, maxResults int, includeBus bool) []Departure {
|
||||||
|
url := fmt.Sprintf("%s/stops/%s/departures?results=%d&bus=%t", apiBaseURL, stationID, maxResults, includeBus)
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Fehler beim Abrufen der Abfahrten für Station %s: %v\n", stationID, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Fehler beim Lesen der Antwort für Station %s: %v\n", stationID, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(body) == 0 {
|
||||||
|
log.Printf("Leere Antwort vom Server für Station %s erhalten\n", stationID)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var response APIResponse
|
||||||
|
err = json.Unmarshal(body, &response)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Fehler beim Dekodieren der Abfahrten für Station %s: %v\nAntwort-Body: %s\n", stationID, err, string(body))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Erfolgreich %d Abfahrten für Station %s abgerufen\n", len(response.Departures), stationID)
|
||||||
|
return response.Departures
|
||||||
|
}
|
||||||
|
|
||||||
|
func savePosition(db *sql.DB, dep Departure) {
|
||||||
|
if dep.CurrentTripPosition.Latitude == 0 && dep.CurrentTripPosition.Longitude == 0 {
|
||||||
|
log.Println("Keine gültige Position verfügbar")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
today := time.Now().Format("2006-01-02")
|
||||||
|
|
||||||
|
var existingID string
|
||||||
|
err := db.QueryRow("SELECT id FROM trips WHERE fahrt_nr = ? AND DATE(timestamp) = ?", dep.Line.FahrtNr, today).Scan(&existingID)
|
||||||
|
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
id := uuid.New().String()
|
||||||
|
_, err = db.Exec("INSERT INTO trips (id, latitude, longitude, timestamp, train_name, fahrt_nr) VALUES (?, ?, ?, ?, ?, ?)",
|
||||||
|
id, dep.CurrentTripPosition.Latitude, dep.CurrentTripPosition.Longitude, dep.When, dep.Line.Name, dep.Line.FahrtNr)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Fehler beim Speichern der neuen Position: %v\n", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("Neue Position gespeichert (ID: %s, Zug: %s, FahrtNr: %s)\n", id, dep.Line.Name, dep.Line.FahrtNr)
|
||||||
|
}
|
||||||
|
} else if err == nil {
|
||||||
|
_, err = db.Exec("UPDATE trips SET latitude = ?, longitude = ?, timestamp = ?, train_name = ? WHERE id = ?",
|
||||||
|
dep.CurrentTripPosition.Latitude, dep.CurrentTripPosition.Longitude, dep.When, dep.Line.Name, existingID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Fehler beim Aktualisieren der Position: %v\n", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("Position aktualisiert (ID: %s, Zug: %s, FahrtNr: %s)\n", existingID, dep.Line.Name, dep.Line.FahrtNr)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("Fehler bei der Überprüfung des existierenden Eintrags: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue