152 lines
3.2 KiB
Go
152 lines
3.2 KiB
Go
package statusscreen
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"github.com/olekukonko/tablewriter"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// SL is my SL struct
|
|
type SL struct {
|
|
Config *Config
|
|
lastResponse SLResponse
|
|
nextRefresh int64
|
|
}
|
|
|
|
// SLResponse is a struct to get the interesting data from API Responses
|
|
type SLResponse struct {
|
|
StatusCode int
|
|
ExecutionTime int
|
|
|
|
ResponseData struct {
|
|
LatestUpdate string
|
|
Metros []struct {
|
|
LineNumber string
|
|
Destination string
|
|
TimeTabledDateTime string
|
|
ExpectedDateTime string
|
|
TransportMode string
|
|
}
|
|
StopPointDeviations []struct {
|
|
Deviation struct {
|
|
Text string
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetOutput returns a rendered result of this module
|
|
func (sl *SL) GetOutput() []string {
|
|
var b bytes.Buffer
|
|
|
|
// Prepare table
|
|
table := tablewriter.NewWriter(&b)
|
|
table.SetHeader([]string{
|
|
"Line",
|
|
"Destination",
|
|
"DisplayTime",
|
|
"Timetable",
|
|
"Expcted",
|
|
})
|
|
|
|
// Check if it's time to refresh yet
|
|
if sl.nextRefresh <= time.Now().Unix() {
|
|
// If it is, refresh the data
|
|
sldata, err := sl.getTimeTable()
|
|
|
|
// If no error occured, save the latest data to the struct
|
|
if err == nil {
|
|
sl.lastResponse = sldata
|
|
sl.nextRefresh = time.Now().Unix() + sl.Config.SL.RefreshDelay
|
|
} else {
|
|
// log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
for _, v := range sl.lastResponse.ResponseData.Metros {
|
|
formattedTime, err := sl.formatDisplayTime(v.ExpectedDateTime)
|
|
|
|
if err == nil {
|
|
table.Append([]string{
|
|
v.LineNumber,
|
|
v.Destination,
|
|
formattedTime,
|
|
v.TimeTabledDateTime[11:], // Remove YYYY-MM-DDT from the beginning of the string
|
|
v.ExpectedDateTime[11:], // Remove YYYY-MM-DDT from the beginning of the string
|
|
})
|
|
}
|
|
}
|
|
|
|
table.Render()
|
|
|
|
return strings.Split(b.String(), "\n")
|
|
}
|
|
|
|
func (sl *SL) getTimeTable() (SLResponse, error) {
|
|
parsedResponse := SLResponse{}
|
|
|
|
// Construct URL with APIKey and Site
|
|
url := fmt.Sprintf(sl.Config.SL.APIURL, sl.Config.SL.APIKey, sl.Config.SL.SiteID)
|
|
|
|
// Set up http client to talk to SL
|
|
client := http.Client{
|
|
Timeout: time.Second * 5,
|
|
}
|
|
|
|
// Do request
|
|
resp, err := client.Get(url)
|
|
if err != nil {
|
|
return parsedResponse, err
|
|
}
|
|
|
|
// Read response
|
|
body, readErr := ioutil.ReadAll(resp.Body)
|
|
if readErr != nil {
|
|
return parsedResponse, readErr
|
|
}
|
|
|
|
// Parse response from SL
|
|
parseErr := json.Unmarshal(body, &parsedResponse)
|
|
if parseErr != nil {
|
|
return parsedResponse, parseErr
|
|
}
|
|
|
|
return parsedResponse, nil
|
|
}
|
|
|
|
func (sl *SL) formatDisplayTime(expected string) (string, error) {
|
|
myTimeZone, _ := time.Now().Zone()
|
|
|
|
then, err := time.Parse("2006-01-02T15:04:05 MST", expected+" "+myTimeZone)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
timeLeft := time.Since(then).Seconds() * -1
|
|
|
|
// If time is less than zero
|
|
if timeLeft < 0 {
|
|
return "undefined", errors.New("Train is gone already")
|
|
}
|
|
|
|
// If time is less than one minute, show seconds
|
|
if timeLeft <= 60 && timeLeft > 0 {
|
|
return fmt.Sprintf("%d sec", int(timeLeft)), nil
|
|
}
|
|
|
|
// If time is less than one hour, show minutes
|
|
if timeLeft <= 3600 && timeLeft > 0 {
|
|
return fmt.Sprintf("%d min", int(timeLeft)/60), nil
|
|
}
|
|
|
|
// Otherwise, just return a timestamp: HH:MM:SS
|
|
return fmt.Sprintf("%02d:%02d:%02d", then.Hour(), then.Minute(), then.Second()), nil
|
|
}
|