Git Product home page Git Product logo

gbfs's Introduction

GBFS

Go implementation of client, server and validator for GBFS (General Bikeshare Feed Specification).

Usage

Client

import "github.com/petoc/gbfs"
c, err := gbfs.NewClient(gbfs.ClientOptions{
    AutoDiscoveryURL: "http://127.0.0.1:8080/v3/system_id/gbfs.json",
    DefaultLanguage:  "en",
})
if err != nil {
    log.Fatal(err)
}

Get single feed

f := &gbfs.FeedSystemInformation{}
err := c.Get(f)
if err != nil {
    log.Println(err)
}
if f.Data != nil {
    log.Printf("feed=%s system_id=%s", f.Name(), *f.Data.SystemID)
}

Subscribe

Client provides built-in function to handle feed updates.

err := c.Subscribe(gbfs.ClientSubscribeOptions{
    // Languages: []string{"en"},
    // FeedNames: []string{gbfs.FeedNameStationInformation, gbfs.FeedNameFreeBikeStatus},
    Handler: func(c *gbfs.Client, f gbfs.Feed, err error) {
        if err != nil {
            log.Println(err)
            return
        }
        j, _ := json.Marshal(f)
        log.Printf("feed=%s data=%s", f.Name(), j)
    },
})
if err != nil {
    log.Println(err)
}

Subscription options Languages and FeedNames restrict subscription only to selected languages and feeds.

Server

import "github.com/petoc/gbfs"
s, err := gbfs.NewServer(gbfs.ServerOptions{
    SystemID:     "system_id",
    RootDir:      "public",
    BaseURL:      "http://127.0.0.1:8080",
    BasePath:     "v3/system_id",
    Version:      gbfs.V30,
    DefaultTTL:   60,
    FeedHandlers: []*gbfs.FeedHandler{
        // see example for how to add feed handlers
    },
    UpdateHandler: func(s *gbfs.Server, feed gbfs.Feed, path string, err error) {
        if err != nil {
            log.Println(err)
            return
        }
        log.Printf("system=%s ttl=%d version=%s updated=%s", s.Options.SystemID, feed.GetTTL(), feed.GetVersion(), path)
    },
})
if err != nil {
    log.Fatal(err)
}
log.Fatal(s.Start())

Main autodiscovery feed gbfs.json will be constructed from all available feeds in FeedHandlers. After that, all FeedHandlers will be regularly executed after configured TTL. If TTL is not set for individual feeds, it will be inherited from FeedHandler. If TTL is not set even for FeedHandler, DefaultTTL from ServerOptions will be used for feed.

Serving feeds

Feeds can be served as static files with standard webservers (Nginx, Apache, ...) or with simple built-in static file server.

fs, err := gbfs.NewFileServer("127.0.0.1:8080", "public")
if err != nil {
    log.Fatal(err)
}
log.Fatal(fs.ListenAndServe())

Validator

Validator validates feeds for common issues, such as missing required fields, invalid values, mutually exclusive fields, and so on. Validation result contains parsed feed in Feed struct and slices of Infos, Warnings and Errors. Important validation issues will be in Errors. Warnings usually comply with specification, but should be considered in order to be consistent with most of providers. Infos contains just notes, such as usage of field officialy available from newer versions of specification.

Not all invalid type issues will be reported, only common ones like coordinates or prices as strings, instead of float. Other uncommon type issues will prevent feed from being parsed. In such cases, some reasonable error should be returned from client.

import "github.com/petoc/gbfs/validator"
f := &gbfs.FeedSystemInformation{}
err := c.Get(f)
if err != nil {
    log.Fatal(err)
}
v := validator.New()
r := v.Validate(f, gbfs.V10)
log.Printf("infos=%v", r.Infos)
log.Printf("warnings=%v", r.Warnings)
log.Printf("errors=%v", r.Errors)

License

Licensed under MIT license.

gbfs's People

Contributors

petoc avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar

Forkers

wizardishungry

gbfs's Issues

Problem unmarshaling FeedStationInformationStation.data.stations.vehicle_capacity

json: cannot unmarshal object into Go struct field FeedStationInformationStation.data.stations.vehicle_capacity of type map[*gbfs.ID]int64

Seems to work if you change the map keys for VehicleTypeCapacity VehicleCapacity to be a non pointer, but I didn't want to monkey around too much because the validator example seems to depend on the keys being pointers.

diff --git a/feed_station_information.go b/feed_station_information.go
index 7a5f54e..673951e 100644
--- a/feed_station_information.go
+++ b/feed_station_information.go
@@ -25,8 +25,8 @@ type (
                IsVirtualStation            *Boolean         `json:"is_virtual_station,omitempty"` // (v2.1-RC)
                StationArea                 *GeoJSONGeometry `json:"station_area,omitempty"`       // (v2.1-RC)
                Capacity                    *int64           `json:"capacity,omitempty"`
-               VehicleCapacity             map[*ID]int64    `json:"vehicle_capacity,omitempty"`               // (v2.1-RC)
-               VehicleTypeCapacity         map[*ID]int64    `json:"vehicle_type_capacity,omitempty"`          // (v2.1-RC)
+               VehicleCapacity             map[ID]int64     `json:"vehicle_capacity,omitempty"`               // (v2.1-RC)
+               VehicleTypeCapacity         map[ID]int64     `json:"vehicle_type_capacity,omitempty"`          // (v2.1-RC)
                IsValetStation              *Boolean         `json:"is_valet_station,omitempty"`               // (v2.1-RC)
                RentalURIs                  *RentalURIs      `json:"rental_uris,omitempty"`                    // (v1.1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.