1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
package atb
import (
"encoding/json"
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
// DefaultURL is the default AtB API URL.
const DefaultURL = "http://st.atb.no/New/InfoTransit/UserServices.asmx"
// Client represents a client which communicates with AtBs API.
type Client struct {
Username string
Password string
URL string
}
// BusStops represents a list of bus stops.
type BusStops struct {
Stops []BusStop `json:"Fermate"`
}
// BusStop represents a bus stop.
type BusStop struct {
StopID int `json:"cinFermata"`
NodeID string `json:"codAzNodo"`
Description string `json:"descrizione"`
Longitude string `json:"lon"`
Latitude int `json:"lat"`
MobileCode string `json:"codeMobile"`
MobileName string `json:"nomeMobile"`
}
// Forecasts represents a list of forecasts.
type Forecasts struct {
Nodes []NodeInfo `json:"InfoNodo"`
Forecasts []Forecast `json:"Orari"`
Total int `json:"total"`
}
// NodeInfo represents a bus stop, returned as a part of a forecast.
type NodeInfo struct {
Name string `json:"nome_Az"`
NodeID string `json:"codAzNodo"`
NodeName string `json:"nomeNodo"`
NodeDescription string `json:"descrNodo"`
BitMaskProperties string `json:"bitMaskProprieta"`
MobileCode string `json:"codeMobile"`
Longitude string `json:"coordLon"`
Latitude string `json:"coordLat"`
}
// Forecast represents a single forecast.
type Forecast struct {
LineID string `json:"codAzLinea"`
LineDescription string `json:"descrizioneLinea"`
RegisteredDepartureTime string `json:"orario"`
ScheduledDepartureTime string `json:"orarioSched"`
StationForecast string `json:"statoPrevisione"`
Destination string `json:"capDest"`
}
type busStopsRequest struct {
XMLName xml.Name `xml:"Envelope"`
Result []byte `xml:"Body>GetBusStopsListResponse>GetBusStopsListResult"`
}
type forecastRequest struct {
XMLName xml.Name `xml:"Envelope"`
Result []byte `xml:"Body>getUserRealTimeForecastByStopResponse>getUserRealTimeForecastByStopResult"`
}
// NewFromConfig creates a new client where name is the path to the config file.
func NewFromConfig(name string) (*Client, error) {
data, err := ioutil.ReadFile(name)
if err != nil {
return nil, err
}
var client Client
if err := json.Unmarshal(data, &client); err != nil {
return nil, err
}
if client.URL == "" {
client.URL = DefaultURL
}
return &client, nil
}
func (c *Client) postXML(body string, dst interface{}) error {
resp, err := http.Post(c.URL, "application/soap+xml", strings.NewReader(body))
if err != nil {
return err
}
defer resp.Body.Close()
dec := xml.NewDecoder(resp.Body)
if err := dec.Decode(&dst); err != nil {
return err
}
return nil
}
// BusStops retrieves bus stops from AtBs API.
func (c *Client) BusStops() (BusStops, error) {
req := fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<GetBusStopsList xmlns="http://miz.it/infotransit">
<auth>
<user>%s</user>
<password>%s</password>
</auth>
</GetBusStopsList>
</soap12:Body>
</soap12:Envelope>`, c.Username, c.Password)
var stopsRequest busStopsRequest
if err := c.postXML(req, &stopsRequest); err != nil {
return BusStops{}, err
}
var stops BusStops
if err := json.Unmarshal(stopsRequest.Result, &stops); err != nil {
return BusStops{}, err
}
return stops, nil
}
// Forecasts retrieves forecasts from AtBs API, using nodeID to identify the bus stop.
func (c *Client) Forecasts(nodeID int) (Forecasts, error) {
req := fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<getUserRealTimeForecastByStop xmlns="http://miz.it/infotransit">
<auth>
<user>%s</user>
<password>%s</password>
</auth>
<busStopId>%d</busStopId>
</getUserRealTimeForecastByStop>
</soap12:Body>
</soap12:Envelope>`, c.Username, c.Password, nodeID)
var forecastRequest forecastRequest
if err := c.postXML(req, &forecastRequest); err != nil {
return Forecasts{}, err
}
var forecasts Forecasts
if err := json.Unmarshal(forecastRequest.Result, &forecasts); err != nil {
return Forecasts{}, err
}
return forecasts, nil
}
|