-
Notifications
You must be signed in to change notification settings - Fork 2
Routing Service
Routing service is the main service you will use. It provides a wrapper for most of the route4me functionality:
- Managing(running, updating, fetching) optimizations
- Managing(updating, fetching) routes
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
}
Examples written below assume that you have an []*Address under addresses
variable. It's a recurrent theme.
You can find the struct definition here. Member names should be self-descriptive. If something's unclear leave an issue or contact support.
In order to get an address you have to acquire route-id
and route-destination-id
. You can extract that data from here.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
address, err = service.GetAddress(&routing.AddressQuery{RouteID: "route-id",
RouteDestinationID: "route-destination-id",
Notes: true, //If this is set to true all notes associated with this address will be returned.
})
if err != nil {
//handle errors
return
}
}
In order to update an address you have to have it's object first. You can get it by calling either GetRoute
or GetAddress
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
updated, err := service.UpdateAddress(address)
if err != nil {
//handle errors
return
}
//do something with updated address
}
The example refers to the process of marking an address as Detected as Visited.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
var address *routing.Address //fetch address
address.IsVisited = true
updated, err := service.UpdateAddress(address)
if err != nil {
//handle errors
return
}
//do something with updated address
}
The example refers to the process of marking an address as Detected as Departed.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
var address *routing.Address //fetch address
address.IsDeparted = true
updated, err := service.UpdateAddress(address)
if err != nil {
//handle errors
return
}
//do something with updated address
}
The example refers to the process of marking an address as departed.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
var address *routing.Address //fetch address
address.IsDeparted = true
updated, err := service.MarkAddressAsDeparted(address)
if err != nil {
//handle errors
return
}
//do something with updated address
}
The example refers to the process of marking an address as visited.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
var address *routing.Address //fetch address
address.IsVisited = true
updated, err := service.MarkAddressAsVisited(address)
if err != nil {
//handle errors
return
}
//do something with updated address
}
Remove a destination (an address) with specified route_destination_id from an optimization problem with specified optimization_problem_id.
Removing an optimization from an optimization problem is different from removing it from a route. The optimization problem is a container for all locations that are being optimized simultaneously When an address is removed from an optimization, the sub-routes get rebalanced as a result of the modification However, when an address is removed from a sub-route, that is the same as a manual override (i.e. order cancellation).
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
deletedRouteDestinationID, err := service.DeleteAddress(optimizationProblemId,routeID)
if err != nil {
//handle errors
return
}
//do something with deleted id
}
- A Route is a collection of addresses usually sorted in the most optimal sequence
- One route can have many addresses
- Each address can have attributes, constraints, and metadata which influence the way the route is sequenced
The example refers to the process of searching for the specified text throughout all routes belonging to the user's account.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
routes, err := service.GetTeamRoutes(&RouteQuery{Query: "Tbilisi"})
if err != nil {
//handle errors
return
}
//do something with routes
}
In order to get a route you need its ID (route-id
). Not specifying the ID field will result in an error being returned.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
route, err = service.GetRoute(&routing.RouteQuery{ID: route-id})
if err != nil {
//handle errors
return
}
}
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
routes, err := service.GetRoute(&routing.RouteQuery{ID: "routeID", PathOutput: routing.Points})
if err != nil {
//handle errors
return
}
//do something with route
}
Edge by edge turn-by-turn directions. Note: For round-trip routes (parameters.rt = true), the return to the start address is returned as well.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
routes, err := service.GetRoute(&routing.RouteQuery{ID: "routeID", Directions: true})
if err != nil {
//handle errors
return
}
//do something with routes
}
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
routeID, err := service.GetRouteID("problem-id")
if err != nil {
t.Error(err)
return
}
//Do something with routeID
}
In order to delete routes You need to know their ids (route-id
). You can fetch them by calling GetTeamRoutes()
.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
routes, err = service.DeleteRoutes([]string{"route-id"})
if err != nil {
//handle errors
return
}
}
In order to update the Route you need to have it's id(route-id
). It's recommended to use GetTeamRoutes to fetch instances.
- Updating a route supports the Reoptimize: True parameter, which reoptimizes only that route. Also supports the parameters from GET.
- By sending RecomputeDirections=1 we request that the route directions be recomputed (note that this does happen automatically if certain properties of the route are updated, such as stop sequence_no changes or round-tripness)
- After updating the route there is no guarantee that the route_destination_id values are preserved! It may create copies resulting in new destination IDs, especially when dealing with multiple depots.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
route.Field = "updated value"
updated, err := service.UpdateRoute(route)
if err != nil {
//handle errors
return
}
//do something with updated route
}
In order to update the Route you need to have it's id(route-id
). It's recommended to use GetTeamRoutes to fetch instances.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
updated, err := service.UpdateRoute(&routing.Route{
ID: "route-id",
Addresses: []Address{
//addresses to add
},
OptimalPosition: true,
})
if err != nil {
//handle errors
return
}
//do something with updated route
}
In order to update the Route you need to have it's id(route-id
). It's recommended to use GetTeamRoutes to fetch instances.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
updated, err := service.UpdateRoute(&routing.Route{
ID: "route-id",
Addresses: []Address{
//addresses to add
},
OptimalPosition: false,
})
if err != nil {
//handle errors
return
}
//do something with updated route
}
In order to resequence the Route you need to have it's id(route-id
). It's recommended to use GetTeamRoutes to fetch instances.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
updated, err := service.UpdateRoute(&routing.Route{
ID: "route-id",
Addresses: []Address{
RouteDestinationID: json.Number{`route-destination-id`),
SequenceNo: 2,
},
})
if err != nil {
//handle errors
return
}
//do something with updated route
}
Duplicates the route by accepting route-id
. The duplicated route has all the same metadata and account ownership information as the original route. However, route notes and visited status flags are not copied into the new route. The name of the new route is automatically appended with the string " (Duplicate)" to indicate that the route is a duplicate route. There is currently no special designation inside the database to indicate that a route originated from another route.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
duplicated, err := service.DuplicateRoute(`route-id`)
if err != nil {
//handle errors
return
}
}
Accepts an array of valid route ID’s which exist in the Route4Me database and merges all the route destinations into a single new route. A new route ID is generated and it is a union of all the routes in the provided list of route IDs. The new route’s destinations are all in the sequence of the route ID’s that are being merged. The merged route has all the same metadata and account ownership information as the original routes, however route notes and visited status flags are not copied into the new route.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
//fetch routes to merge
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
err := service.MergeRoutes(&routing.MergeRequest{
RouteIDs: routes[0].ID + "," + routes[1].ID,
RemoveOrigin: false,
DepotAddress: depot.Addresses[0].AddressString,
DepotLatitude: depot.Addresses[0].Latitude,
DepotLongitude: depot.Addresses[0].Longitude,
})
if err != nil {
//handle errors
return
}
}
Share a route via email.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
err := service.ShareRoute("route-id","[email protected]")
if err != nil {
//handle errors
return
}
}
In order to add destinations to a route You need to know its ids (route-id
). You can fetch them by calling GetTeamRoutes()
.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
addresses := []routing.Address{
//address to be added
routing.Address{
AddressString: "717 5th Ave New York, NY 10021",
Alias: "Giorgio Armani",
Latitude: 40.7669692,
Longitude: -73.9693864,
Time: 0,
},
}
do, err = service.AddRouteDestinations("route-id", addresses)
if err != nil {
//handle errors
return
}
// do is DataObject
}
In order to remove a destination from a route you need to acquire route's route-id
and destination's route-destination-id
You can do that by calling GetTeamRoutes()
and GetRoute()
respectively.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
boolean, err := service.RemoveRouteDestination("route-id", "route-destination-id")
if err != nil {
// handle error
return
}
}
In order to move a destination between routes you have to acquire their ids.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
query := routing.DestinationMoveRequest {
ToRouteID: "route-id",
RouteDestinationID: "route-destination-id",
AfterDestinationID: "after-destination-id",
}
success, err := service.MoveDestinationToRoute(query)
if err != nil {
// handle error
return
}
if !success {
// handle failed attempt
return
}
}
In order to get address notes you have to acquire route_id
and address_id
. You can do that by calling GetRoute()
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
query := &NoteQuery{
RouteID: "route_id",
AddressID: "address_id",
}
notes, err := service.GetAddressNotes(query)
if err != nil {
//handle errors
return
}
// do something with address notes
}
In order to add a note to an address you have to acquire route_id
and address_id
. You can do that by calling GetRoute()
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
query := &NoteQuery{
RouteID: get.ID,
AddressID: get.Addresses[0].RouteDestinationID.String(),
Latitude: 33.132675170898,
Longitude: -83.244743347168,
ActivityType: DropOff,
}
addedNote, err = service.AddAddressNote(query, "Note Contents")
if err != nil {
//handle errors
return
}
}
- An Optimization Problem is a collection of addresses that need to be visited.
- The optimization problem takes into consideration all of the addresses that need to be visited and all the constraints associated with each address and depot.
- It is preferable to create an optimization problem with as many orders in it as possible, so that the optimization engine is able to consider the entire problem set.
- This is different from a Route, which is a sequence of addresses that need to be visited by a single vehicle and a single driver in a fixed time period. Solving an Optimization Problem results in a number of routes. Possibly in the future they may also be recurring.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
optimizations, err := service.GetOptimizations(&RouteQuery{Limit: 5})
if err != nil {
//handle errors
return
}
//do something with optimizations
}
In order to get a single optimization you need to obtain the ID. You can do it by calling GetOptimizations
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
optimization, err = service.GetOptimization(&OptimizationParameters{ProblemID: optimizations[0].ProblemID})
if err != nil {
//handler errors
return
}
//do something with optimization
}
This currently is not implemented on the Route4Me side.
In order to delete a single optimization you need to obtain the ID. You can do it by calling GetOptimizations
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
err = service.DeleteOptimization({optimizationId})
if err != nil {
//handler errors
return
}
}
Updating optimization allows you to add addresses to the process. You have to acquire problem_id
in order to update it. Setting reoptimize
to true will reoptimize the whole optimization.
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
addresses := []routing.Address{
//address to be added
routing.Address{
AddressString: "717 5th Ave New York, NY 10021",
Alias: "Giorgio Armani",
Latitude: 40.7669692,
Longitude: -73.9693864,
Time: 0,
},
}
updated, err := service.UpdateOptimization(&OptimizationParameters{ProblemID: "problem_id", Addresses: addresses, Reoptimize: true})
if err != nil {
//handle errors
return
}
// do something with updated optimization
}
There are multiple configurations of running the route. Examples from C# SDK might be helpful to understand the whole process.
Let's take a look at AlgorithmType:
//AlgorithmType is a type of algorithm used for optimization
type AlgorithmType uint
const (
//TSP stands for single depot, single driver route
TSP AlgorithmType = iota + 1
//VRP stands for single depot, multiple driver, no constraints, no time windows, no capacities
VRP
//CVRP_TW_SD stands for single depot, multiple driver, capacitated, time windows
CVRP_TW_SD
//CVRP_TW_MD stands for multiple depot, multiple driver, capacitated, time windows
CVRP_TW_MD
//TSP_TW stands for single depot, single driver, time windows
TSP_TW
//TSP_TW_CR stands for single depot, single driver, time windows, continuous optimization (minimal location shifting)
TSP_TW_CR
//BBCVRP stands for shifts addresses from one route to another over time on a recurring schedule
BBCVRP
)
These options describe what type of optimization should be created.
We need to specify RouteParameters
routeParams := &routing.RouteParameters{
AlgorithmType: routing.CVRP_TW_MD,
Name: "Multiple Depot, Multiple Driver",
RouteDate: time.Now().Unix(),
RouteTime: 60 * 60 * 7,
RouteMaxDuration: 86400,
VehicleCapacity: 1,
VehicleMaxDistanceMI: 1000,
Optimize: routing.Distance,
DistanceUnit: routing.Miles,
DeviceType: routing.Web,
TravelMode: routing.Driving,
}
Members should be self-descriptive, they correspond to the route4me web UI.
Once route parameters are set up we need to wrap it with addresses and execute the optimization.
Specifying ProblemID in OptimizationParameters will create a route.
optParams := &routing.OptimizationParameters{
Addresses: addresses,
Parameters: routeParams,
}
optimization, err := service.RunOptimization(optParams)
if err != nil {
//handle errors
return
}
//do something with optimization
Complete example:
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
routeParams := &routing.RouteParameters{
AlgorithmType: routing.CVRP_TW_MD,
Name: "Multiple Depot, Multiple Driver",
RouteDate: time.Now().Unix(),
RouteTime: 60 * 60 * 7,
RouteMaxDuration: 86400,
VehicleCapacity: 1,
VehicleMaxDistanceMI: 1000,
Optimize: routing.Distance,
DistanceUnit: routing.Miles,
DeviceType: routing.Web,
TravelMode: routing.Driving,
}
optParams := &routing.OptimizationParameters{
Addresses: addresses,
Parameters: routeParams,
}
optimization, err := service.RunOptimization(optParams)
if err != nil {
//handle errors
return
}
//do something with optimization
}
import (
"github.com/route4me/route4me-go-sdk"
"github.com/route4me/route4me-go-sdk/routing"
)
func main() {
client := route4me.NewClient("your-api-key")
service := &routing.Service{Client: client}
success, err := service.ResequenceRoute(`route-id`)
if err != nil {
//handle error
}
if !success {
//something went wrong
return
}
// all okay!
}
The returned object will not contain the optimized route, you have to keep calling GetOptimization to fetch the current status.
You can look at service's test file for more implementation details.
- Activity
- Addressbook
- Routing
- Single Driver Route 10 Stops
- Single Driver Round Trip
- Single Depot Multiple Driver No Time Windows
- Single Depot Multiple Driver Time Windows
- Multiple Depot Multiple Driver
- Multiple Depot Multiple Driver With Time Windows
- Multiple Depot Multiple Driver With Time Windows (24 Stops)
- Tracking
- Geocoding
- Users
- Territories
- Orders
- Vehicles
- Telematics