forked from Project-OSRM/osrm-backend
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: initial implementation for oasis api
issue: #128
- Loading branch information
1 parent
a5c7887
commit 0babe83
Showing
7 changed files
with
301 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
) | ||
|
||
var flags struct { | ||
listenPort int | ||
osrmBackendEndpoint string | ||
} | ||
|
||
func init() { | ||
flag.IntVar(&flags.listenPort, "p", 8090, "Listen port.") | ||
flag.StringVar(&flags.osrmBackendEndpoint, "osrm", "", "Backend OSRM-backend endpoint") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package main | ||
|
||
import ( | ||
"net/http" | ||
"strconv" | ||
|
||
"github.com/Telenav/osrm-backend/integration/oasis" | ||
"github.com/golang/glog" | ||
) | ||
|
||
func main() { | ||
mux := http.NewServeMux() | ||
|
||
oasisService := oasis.New(flags.osrmBackendEndpoint) | ||
mux.Handle("/oasis", oasisService) | ||
|
||
// listen | ||
listening := ":" + strconv.Itoa(flags.listenPort) | ||
glog.Infof("Listening on %s", listening) | ||
glog.Fatal(http.ListenAndServe(listening, mux)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package oasis | ||
|
||
import ( | ||
"encoding/json" | ||
"net/http" | ||
|
||
"github.com/Telenav/osrm-backend/integration/pkg/api/oasis" | ||
) | ||
|
||
type Handler struct { | ||
osrmBackend string | ||
} | ||
|
||
func New(osrmBackend string) *Handler { | ||
return &Handler{ | ||
osrmBackend, | ||
} | ||
} | ||
|
||
func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
w.WriteHeader(200) | ||
json.NewEncoder(w).Encode(generateFakeOasisResponse()) | ||
} | ||
|
||
func generateFakeOasisResponse() *oasis.Response { | ||
fakeSolution1 := new(oasis.Solution) | ||
fakeSolution1.Distance = 90.0 | ||
fakeSolution1.Duration = 300.0 | ||
fakeSolution1.Weight = 300.0 | ||
fakeSolution1.WeightName = "duration" | ||
|
||
fakeStation1 := new(oasis.ChargeStation) | ||
fakeStation1.Location[0] = 13.39677 | ||
fakeStation1.Location[1] = 52.54366 | ||
fakeStation1.WaitTime = 30.0 | ||
fakeStation1.ChargeTime = 100.0 | ||
fakeStation1.ChargeRange = 100.0 | ||
fakeSolution1.ChargeStations = append(fakeSolution1.ChargeStations, fakeStation1) | ||
|
||
fakeStation2 := new(oasis.ChargeStation) | ||
fakeStation2.Location[0] = 13.40677 | ||
fakeStation2.Location[1] = 52.53333 | ||
fakeStation2.WaitTime = 100.0 | ||
fakeStation2.ChargeTime = 100.0 | ||
fakeStation2.ChargeRange = 100.0 | ||
fakeSolution1.ChargeStations = append(fakeSolution1.ChargeStations, fakeStation2) | ||
|
||
r := new(oasis.Response) | ||
r.Code = "200" | ||
r.Message = "Optimized charge station selection result:" | ||
r.Solutions = append(r.Solutions, fakeSolution1) | ||
|
||
return r | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package genericoptions | ||
|
||
const ( | ||
InvalidMaxRangeValue = -1.0 // default | ||
InvalidCurrentRangeValue = -1.0 // default | ||
DefaultPreferLevel = 100000 // unit:meters | ||
DefaultSafeLevel = 100000 // unit:meters | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package options | ||
|
||
const ( | ||
KeyMaxRange = "max_range" | ||
KeyCurrRange = "curr_range" | ||
KeyPreferLevel = "prefer_level" | ||
KeySafeLevel = "safe_level" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
package oasis | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"math" | ||
"net/url" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/Telenav/osrm-backend/integration/pkg/api" | ||
"github.com/Telenav/osrm-backend/integration/pkg/api/oasis/genericoptions" | ||
"github.com/Telenav/osrm-backend/integration/pkg/api/oasis/options" | ||
"github.com/Telenav/osrm-backend/integration/pkg/api/osrm/coordinate" | ||
"github.com/golang/glog" | ||
) | ||
|
||
// Request for oasis service | ||
type Request struct { | ||
Service string | ||
Version string | ||
Profile string | ||
Coordinates coordinate.Coordinates | ||
|
||
MaxRange float64 | ||
CurrRange float64 | ||
PreferLevel float64 | ||
SafeLevel float64 | ||
} | ||
|
||
// NewRequest create an empty oasis Request. | ||
func NewRequest() *Request { | ||
return &Request{ | ||
// Path | ||
Service: "oasis", | ||
Version: "v1", | ||
Profile: "earliest", | ||
Coordinates: coordinate.Coordinates{}, | ||
|
||
// generic options | ||
MaxRange: genericoptions.InvalidMaxRangeValue, | ||
CurrRange: genericoptions.InvalidCurrentRangeValue, | ||
PreferLevel: genericoptions.DefaultPreferLevel, | ||
SafeLevel: genericoptions.DefaultSafeLevel, | ||
} | ||
} | ||
|
||
// ParseRequestURL parse Request URL to Request. | ||
func ParseRequestURL(u *url.URL) (*Request, error) { | ||
if u == nil { | ||
return nil, fmt.Errorf("empty URL input") | ||
} | ||
|
||
req := NewRequest() | ||
|
||
if err := req.parsePath(u.Path); err != nil { | ||
return nil, err | ||
} | ||
|
||
params, err := url.ParseQuery(u.RawQuery) | ||
if err != nil { | ||
glog.Warning(err) | ||
return nil, err | ||
} | ||
|
||
if err := req.parseQuery(params); err != nil { | ||
glog.Warning(err) | ||
return nil, err | ||
} | ||
|
||
if err := req.validate(); err != nil { | ||
glog.Warning(err) | ||
return nil, err | ||
} | ||
|
||
return req, nil | ||
} | ||
|
||
func (r *Request) parsePath(path string) error { | ||
p := path | ||
p = strings.TrimPrefix(p, api.Slash) | ||
p = strings.TrimSuffix(p, api.Slash) | ||
|
||
s := strings.Split(p, api.Slash) | ||
if len(s) < 4 { | ||
return fmt.Errorf("invalid path values %v parsed from %s", s, path) | ||
} | ||
r.Service = s[0] | ||
r.Version = s[1] | ||
r.Profile = s[2] | ||
|
||
var err error | ||
if r.Coordinates, err = coordinate.ParseCoordinates(s[3]); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (r *Request) parseQuery(params url.Values) error { | ||
for k, v := range params { | ||
if len(v) <= 0 { | ||
continue | ||
} | ||
|
||
var valfloat float64 | ||
if s, err := strconv.ParseFloat(v[0], 64); err != nil { | ||
return err | ||
} else { | ||
valfloat = float64(s) | ||
} | ||
|
||
switch k { | ||
case options.KeyMaxRange: | ||
r.MaxRange = valfloat | ||
case options.KeyCurrRange: | ||
r.CurrRange = valfloat | ||
case options.KeyPreferLevel: | ||
r.PreferLevel = valfloat | ||
case options.KeySafeLevel: | ||
r.SafeLevel = valfloat | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (r *Request) validate() error { | ||
// MaxRange must be set | ||
if floatEquals(r.MaxRange, genericoptions.InvalidMaxRangeValue) || isFloatNegative(r.MaxRange) { | ||
return errors.New("Invalid value for " + options.KeyMaxRange + ".") | ||
} | ||
|
||
// CurrRange must be set | ||
if floatEquals(r.CurrRange, genericoptions.InvalidCurrentRangeValue) || isFloatNegative(r.CurrRange) { | ||
return errors.New("Invalid value for " + options.KeyCurrRange + ".") | ||
} | ||
|
||
// CurrRange must be smaller or equal to MaxRange | ||
if r.CurrRange > r.MaxRange { | ||
return errors.New(options.KeyCurrRange + " must be smaller or equal to " + options.KeyMaxRange + ".") | ||
} | ||
|
||
// CurrRange must be smaller or equal to MaxRange | ||
if r.PreferLevel > r.MaxRange { | ||
return errors.New(options.KeyPreferLevel + " must be smaller or equal to " + options.KeyMaxRange + ".") | ||
} | ||
|
||
// CurrRange must be smaller or equal to MaxRange | ||
if r.SafeLevel > r.MaxRange { | ||
return errors.New(options.KeySafeLevel + " must be smaller or equal to " + options.KeyMaxRange + ".") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
var epsilon float64 = 0.00000001 | ||
|
||
func floatEquals(a, b float64) bool { | ||
if (a-b) < epsilon && (b-a) < epsilon { | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
func isFloatNegative(a float64) bool { | ||
return !floatEquals(math.Abs(a), a) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package oasis | ||
|
||
import "github.com/Telenav/osrm-backend/integration/pkg/api/osrm/route" | ||
|
||
// Response for oasis service | ||
type Response struct { | ||
Code string `json:"code"` | ||
Message string `json:"message,omitempty"` | ||
Solutions []*Solution `json:"solutions,omitempty"` | ||
} | ||
|
||
// Solution contains recommended charge stations | ||
type Solution struct { | ||
Distance float64 `json:"distance"` | ||
Duration float64 `json:"duration"` | ||
Weight float64 `json:"weight"` | ||
WeightName string `json:"weight_name"` | ||
ChargeStations []*ChargeStation `json:"charge_station"` | ||
} | ||
|
||
// ChargeStation contains location, time and energy level, could be used as waypoints for routing request | ||
type ChargeStation struct { | ||
route.Waypoint | ||
WaitTime float64 `json:"wait_time"` | ||
ChargeTime float64 `json:"charge_time"` | ||
ChargeRange float64 `json:"charge_range"` | ||
} |