Timeout after 10 seconds on FetchDepartures

Also apply gofmt
This commit is contained in:
Paul Brinkmeier 2024-07-17 07:35:11 +02:00
parent 330e5923af
commit 3fe42e1ff0
2 changed files with 102 additions and 100 deletions

View File

@ -2,7 +2,7 @@
## TODO ## TODO
- [ ] Use timeout for fetching departures - [x] Use timeout for fetching departures
- [ ] Write ESP8266 client - [ ] Write ESP8266 client
- [ ] Add basic auth - [ ] Add basic auth
- [ ] Create Nix package - [ ] Create Nix package

200
main.go
View File

@ -7,134 +7,136 @@ import "net/http"
import "net/url" import "net/url"
import "slices" import "slices"
import "strconv" import "strconv"
import "time"
type DMResponse struct { type DMResponse struct {
Departures []DMDeparture `json:"departureList"` Departures []DMDeparture `json:"departureList"`
} }
type DMDeparture struct { type DMDeparture struct {
StopName string `json:"stopName"` StopName string `json:"stopName"`
Platform string `json:"platform"` Platform string `json:"platform"`
Countdown string `json:"countdown"` Countdown string `json:"countdown"`
DateTime DMDateTime `json:"dateTime"` DateTime DMDateTime `json:"dateTime"`
RealDateTime *DMDateTime `json:"realDateTime"` RealDateTime *DMDateTime `json:"realDateTime"`
ServingLine DMServingLine `json:"servingLine"` ServingLine DMServingLine `json:"servingLine"`
OnwardStopSeq []DMStop `json:"onwardStopSeq"` OnwardStopSeq []DMStop `json:"onwardStopSeq"`
} }
type DMServingLine struct { type DMServingLine struct {
Symbol string `json:"symbol"` Symbol string `json:"symbol"`
Direction string `json:"direction"` Direction string `json:"direction"`
} }
type DMStop struct { type DMStop struct {
PlaceID string `json:"placeID"` PlaceID string `json:"placeID"`
Place string `json:"place"` Place string `json:"place"`
NameWO string `json:"nameWO"` NameWO string `json:"nameWO"`
} }
type DMDateTime struct { type DMDateTime struct {
Hour string `json:"hour"` Hour string `json:"hour"`
Minute string `json:"minute"` Minute string `json:"minute"`
} }
// TODO: Use different client (with timeout)
func FetchDepartures(stopId string) (*DMResponse, error) { func FetchDepartures(stopId string) (*DMResponse, error) {
// Create request object // Create request object
req, err := http.NewRequest("GET", "https://www.vrn.de/mngvrn/XML_DM_REQUEST", nil) req, err := http.NewRequest("GET", "https://www.vrn.de/mngvrn/XML_DM_REQUEST", nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Configure our request // Configure our request
query := url.Values{} query := url.Values{}
query.Set("coordOutputFormat", "EPSG:4326") query.Set("coordOutputFormat", "EPSG:4326")
query.Set("depType", "stopEvents") query.Set("depType", "stopEvents")
query.Set("includeCompleteStopSeq", "1") query.Set("includeCompleteStopSeq", "1")
query.Set("limit", "10") query.Set("limit", "10")
query.Set("locationServerActive", "0") query.Set("locationServerActive", "0")
query.Set("mode", "direct") query.Set("mode", "direct")
query.Set("name_dm", stopId) query.Set("name_dm", stopId)
query.Set("outputFormat", "json") query.Set("outputFormat", "json")
query.Set("type_dm", "stop") query.Set("type_dm", "stop")
query.Set("useOnlyStops", "1") query.Set("useOnlyStops", "1")
query.Set("useRealtime", "1") query.Set("useRealtime", "1")
req.URL.RawQuery = query.Encode() req.URL.RawQuery = query.Encode()
// Send the request // Send the request, wait max 10 seconds
res, err := http.DefaultClient.Do(req) client := http.Client{
if err != nil { Timeout: 10 * time.Second,
return nil, err }
} res, err := client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close() defer res.Body.Close()
var dmResponse DMResponse var dmResponse DMResponse
err = json.NewDecoder(res.Body).Decode(&dmResponse) err = json.NewDecoder(res.Body).Decode(&dmResponse)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &dmResponse, nil return &dmResponse, nil
} }
func main() { func main() {
http.HandleFunc("/departures", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/departures", func(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query() query := r.URL.Query()
if query["stop_id"] == nil || len(query["stop_id"]) < 1 { if query["stop_id"] == nil || len(query["stop_id"]) < 1 {
http.Error(w, "Missing query parameter: stop_id", http.StatusBadRequest) http.Error(w, "Missing query parameter: stop_id", http.StatusBadRequest)
return return
} }
stopId := query["stop_id"][0] stopId := query["stop_id"][0]
var platform *string = nil var platform *string = nil
if query["platform"] != nil && len(query["platform"]) != 0 { if query["platform"] != nil && len(query["platform"]) != 0 {
platform = &query["platform"][0] platform = &query["platform"][0]
} }
ds, err := FetchDepartures(stopId) ds, err := FetchDepartures(stopId)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
for _, d := range ds.Departures { for _, d := range ds.Departures {
if platform != nil { if platform != nil {
if d.Platform != *platform { if d.Platform != *platform {
continue continue
} }
} }
direction := d.ServingLine.Direction direction := d.ServingLine.Direction
if len(d.OnwardStopSeq) != 0 { if len(d.OnwardStopSeq) != 0 {
last := d.OnwardStopSeq[len(d.OnwardStopSeq) - 1] last := d.OnwardStopSeq[len(d.OnwardStopSeq)-1]
if slices.Contains([]string{"5", "6"}, last.PlaceID) { if slices.Contains([]string{"5", "6"}, last.PlaceID) {
direction = last.NameWO direction = last.NameWO
} }
} }
leaving := fmt.Sprintf("%s min", d.Countdown) leaving := fmt.Sprintf("%s min", d.Countdown)
countdown, err := strconv.Atoi(d.Countdown) countdown, err := strconv.Atoi(d.Countdown)
if err == nil { if err == nil {
if countdown == 0 { if countdown == 0 {
leaving = "sofort" leaving = "sofort"
} }
if countdown > 20 { if countdown > 20 {
dt := d.DateTime dt := d.DateTime
if d.RealDateTime != nil { if d.RealDateTime != nil {
dt = *d.RealDateTime dt = *d.RealDateTime
} }
leaving = fmt.Sprintf("%02s:%02s", dt.Hour, dt.Minute) leaving = fmt.Sprintf("%02s:%02s", dt.Hour, dt.Minute)
} }
} }
fmt.Fprintf(w, "%2s %-22s %6s\n", fmt.Fprintf(w, "%2s %-22s %6s\n",
d.ServingLine.Symbol, d.ServingLine.Symbol,
direction[:min(len(direction), 22)], direction[:min(len(direction), 22)],
leaving, leaving,
) )
} }
}) })
log.Fatal(http.ListenAndServe(":8000", nil)) log.Fatal(http.ListenAndServe(":8000", nil))
} }