Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cameras/cameras.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (c *CamerasClient) GetCameras() ([]Camera, error) {
}

q := req.URL.Query()
q.Add(wsdot.ParamAccessCode, c.wsdot.ApiKey)
q.Add(wsdot.ParamCamerasAccessCodeKey, c.wsdot.ApiKey)
req.URL.RawQuery = q.Encode()
req.Header.Set("Content-Type", "application/json")

Expand Down Expand Up @@ -92,7 +92,7 @@ func (c *CamerasClient) GetCamera(cameraID int) (*Camera, error) {
}

q := req.URL.Query()
q.Add(wsdot.ParamAccessCode, c.wsdot.ApiKey)
q.Add(wsdot.ParamCamerasAccessCodeKey, c.wsdot.ApiKey)
q.Add(ParamCameraID, strconv.Itoa(cameraID))
req.URL.RawQuery = q.Encode()
req.Header.Set("Content-Type", "application/json")
Expand Down
3 changes: 2 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ var (
)

const (
ParamAccessCode = "AccessCode"
ParamCamerasAccessCodeKey = "AccessCode"
ParamFerriesAccessCodeKey = "apiaccesscode"
)

func NewWSDOTClient(options ...WSDOTClientOption) (*WSDOTClient, error) {
Expand Down
File renamed without changes.
54 changes: 54 additions & 0 deletions example/vessels/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package main

import (
"fmt"
"os"

"alpineworks.io/wsdot"
"alpineworks.io/wsdot/ferries"
)

func main() {
apiKey := os.Getenv("API_KEY")
if apiKey == "" {
panic("API_KEY environment variable is required")
}

// Create a new WSDOT client
wsdotClient, err := wsdot.NewWSDOTClient(
wsdot.WithAPIKey(apiKey),
)

if err != nil {
panic(err)
}

// Create a new Ferries client
ferriesClient, err := ferries.NewFerriesClient(wsdotClient)
if err != nil {
panic(err)
}

// Get the vessel basics
vessels, err := ferriesClient.GetVesselBasics()
if err != nil {
panic(err)
}

if len(vessels) > 0 {
fmt.Println(vessels[0].VesselName)
fmt.Println(vessels[0].VesselID)
fmt.Println(vessels[0].Class.ClassName)
}

// Get the vessel locations
vesselLocations, err := ferriesClient.GetVesselLocations()
if err != nil {
panic(err)
}

if len(vesselLocations) > 0 {
fmt.Println(vesselLocations[1].VesselName)
fmt.Printf("%f°N, %f°W\n", vesselLocations[1].Latitude, vesselLocations[1].Longitude)
}
}
136 changes: 136 additions & 0 deletions ferries/ferries.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package ferries

import (
"encoding/json"
"fmt"
"net/http"

"alpineworks.io/wsdot"
)

const (
getVesselBasicsAsJsonURL = "https://www.wsdot.wa.gov/Ferries/API/Vessels/rest/vesselbasics"
getVesselLocationsAsJsonURL = "https://www.wsdot.wa.gov/Ferries/API/Vessels/rest/vessellocations"
)

type FerriesClient struct {
wsdot *wsdot.WSDOTClient
}

func NewFerriesClient(wsdotClient *wsdot.WSDOTClient) (*FerriesClient, error) {
if wsdotClient == nil {
return nil, wsdot.ErrNoClient
}

return &FerriesClient{
wsdot: wsdotClient,
}, nil
}

type VesselBasic struct {
VesselID int `json:"VesselID"`
VesselSubjectID int `json:"VesselSubjectID"`
VesselName string `json:"VesselName"`
VesselAbbrev string `json:"VesselAbbrev"`
Class struct {
ClassID int `json:"ClassID"`
ClassSubjectID int `json:"ClassSubjectID"`
ClassName string `json:"ClassName"`
SortSeq int `json:"SortSeq"`
DrawingImg string `json:"DrawingImg"`
SilhouetteImg string `json:"SilhouetteImg"`
PublicDisplayName string `json:"PublicDisplayName"`
} `json:"Class"`
Status int `json:"Status"`
OwnedByWSF bool `json:"OwnedByWSF"`
}

func (f *FerriesClient) GetVesselBasics() ([]VesselBasic, error) {
req, err := http.NewRequest(http.MethodGet, getVesselBasicsAsJsonURL, nil)
if err != nil {
return nil, fmt.Errorf("error creating request: %v", err)
}

q := req.URL.Query()
q.Add(wsdot.ParamFerriesAccessCodeKey, f.wsdot.ApiKey)
req.URL.RawQuery = q.Encode()
req.Header.Set("Content-Type", "application/json")

resp, err := f.wsdot.Client.Do(req)
if err != nil {
return nil, fmt.Errorf("error making request: %v", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}

var vessels []VesselBasic
if err := json.NewDecoder(resp.Body).Decode(&vessels); err != nil {
return nil, fmt.Errorf("error decoding response: %v", err)
}

return vessels, nil
}

type VesselLocation struct {
VesselID int `json:"VesselID"`
VesselName string `json:"VesselName"`
Mmsi int `json:"Mmsi"`
DepartingTerminalID int `json:"DepartingTerminalID"`
DepartingTerminalName string `json:"DepartingTerminalName"`
DepartingTerminalAbbrev string `json:"DepartingTerminalAbbrev"`
ArrivingTerminalID int `json:"ArrivingTerminalID"`
ArrivingTerminalName string `json:"ArrivingTerminalName"`
ArrivingTerminalAbbrev string `json:"ArrivingTerminalAbbrev"`
Latitude float64 `json:"Latitude"`
Longitude float64 `json:"Longitude"`
Speed float64 `json:"Speed"`
Heading int `json:"Heading"`
InService bool `json:"InService"`
AtDock bool `json:"AtDock"`
LeftDock string `json:"LeftDock"`
Eta string `json:"Eta"`
EtaBasis string `json:"EtaBasis"`
ScheduledDeparture string `json:"ScheduledDeparture"`
OpRouteAbbrev []string `json:"OpRouteAbbrev"`
VesselPositionNum int `json:"VesselPositionNum"`
SortSeq int `json:"SortSeq"`
ManagedBy int `json:"ManagedBy"`
TimeStamp string `json:"TimeStamp"`
VesselWatchShutID int `json:"VesselWatchShutID"`
VesselWatchShutMsg string `json:"VesselWatchShutMsg"`
VesselWatchShutFlag string `json:"VesselWatchShutFlag"`
VesselWatchStatus string `json:"VesselWatchStatus"`
VesselWatchMsg string `json:"VesselWatchMsg"`
}

func (f *FerriesClient) GetVesselLocations() ([]VesselLocation, error) {
req, err := http.NewRequest(http.MethodGet, getVesselLocationsAsJsonURL, nil)
if err != nil {
return nil, fmt.Errorf("error creating request: %v", err)
}

q := req.URL.Query()
q.Add(wsdot.ParamFerriesAccessCodeKey, f.wsdot.ApiKey)
req.URL.RawQuery = q.Encode()
req.Header.Set("Content-Type", "application/json")

resp, err := f.wsdot.Client.Do(req)
if err != nil {
return nil, fmt.Errorf("error making request: %v", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}

var vessels []VesselLocation
if err := json.NewDecoder(resp.Body).Decode(&vessels); err != nil {
return nil, fmt.Errorf("error decoding response: %v", err)
}

return vessels, nil
}
Loading