Using the RouteCloud Node to Build a Route
The RouteCloud node is used to access the powerful RouteCloud route optimization tool. With this node you can:
• | Build entirely new routes (collections of ordered jobs at customer sites). |
• | Sequence sets of existing routes. |
• | Request a recommendation for the "best" (top N potential) insertion positions for stops on routes. |
• | Insert a list of jobs onto routes without reordering existing stops. |
• | Evaluate existing routes to determine arrival times at stops, costs, distances, breaks, and violations if any. |
For information about the JSON formatting of requests, and for an in-depth overview of the features available to RouteCloud users, see the RouteCloud help. To use this node you must have suitable TDE authentication credentials.
Before we begin, it is important to understand the following:
|
Using the RouteCloud Node in a Flow
The following example demonstrates a basic "build routes" call. We supply a JSON file describing three empty routes, including their durations, start and end locations, completion dates, maximum duration, and several required driver lunch breaks. This file also describes twelve jobs (job0 to job11) with details of their locations, required attributes and constraints. The "build routes" operation generates entirely new routes using this supplied collection of empty routes and jobs, and returns them as a formatted array.
In our example, we trigger the operation manually, and supply credentials directly to the routecloud node. In a production environment, you would typically pass credentials to the routecloud node as part of the message payload, for example from an http node.
Using the details we supply, RouteCloud attempts to assign as many jobs as possible to the three empty routes, while also minimizing their cost and respecting the constraints that we apply on the routes and jobs. If a job cannot be placed on a route, it is placed in the unrouted_jobs list. The complete steps needed to complete this tutorial are listed below, together with full JSON source code at the bottom of the page.
1. | Sign in to Verizon Connect® Flows™ to open the Developer Console. |
2. | Click the Create flow button in the upper right corner of the screen. The Create Flow dialog box opens. |
3. | Select the Default button in the Revision Control section. |
4. | In the Flow name field, enter MyRouteCloud. |
5. | Select the Standard Flow radio button. |
6. | Click Create. The new flow is displayed at the top of the Developer Console. |
7. | Click the flow name (MyRouteCloud) to open it in the Flow Editor. |
8. | Drag an inject node from the utility section of the palette onto the canvas. We use this to manually launch the flow when it is finished. |
9. | Drag a template node from the advanced section of the palette onto the canvas. This node contains the JSON payload we pass to the RouteCloud optimizer. Connect the output of the inject node to the input of the template node. |
10. | Double-click the template node, and type a name into the Name field. For the purposes of this tutorial we use "routecloud json". Next, paste the following JSON text into the Template field. This message describes an array of empty routes, and an array of jobs to be assigned to these routes by the RouteCloud optimizer: |
{
"id": "routecloud_request",
"return_request": true,
"routes": [
{
"id": "route0",
"location": "39.718005, -104.969531",
"start_time": "09:00",
"max_working_time": "08:00",
"date": "2016-1-18",
"breaks": [
{ "id": "route0_lunch_break", "start": "12:00", "length": "00:30" }
]
}, {
"id": "route1",
"location": "39.718005, -104.969531",
"start_time": "09:00",
"max_working_time": "08:00",
"route_attributes": ["hazmat"],
"date": "2016-1-19",
"breaks": [
{ "id": "route1_lunch_break", "start": "12:00", "length": "00:30" }
]
}, {
"id": "route2",
"location": "39.718005, -104.969531",
"start_time": "09:00",
"max_working_time": "04:00",
"date": "2016-1-20",
"breaks": [
{ "id": "route2_lunch_break", "start": "12:00", "length": "00:30" }
]
}
],
"jobs": [
{ "id": "job0", "time_on_site": "00:10", "location": "39.635928, -105.049219" },
{ "id": "job1", "time_on_site": "00:10", "location": "39.725375, -104.791080", "date": "2016-1-18" },
{ "id": "job2", "time_on_site": "00:15", "location": "39.708990, -105.026954", "date": "2016-1-19" },
{ "id": "job3", "time_on_site": "00:10", "location": "39.653975, -105.093750", "allowed_dates": [ "2016-1-18", "2016-1-19" ] },
{ "id": "job4", "time_on_site": "00:15", "location": "39.590789, -105.084376", "allowed_dates": [ "2016-1-20" ] },
{ "id": "job5", "time_on_site": "00:10", "location": "39.638635, -105.128906", "required_route_attributes": [ "hazmat" ] },
{ "id": "job6", "time_on_site": "00:10", "location": "39.597111, -105.041015", "disallowed_route_attributes": [ "hazmat" ] },
{ "id": "job7", "time_on_site": "00:10", "location": "39.727919, -105.103126", "required_route_attributes": [ "heavy_truck" ] },
{ "id": "job8", "time_on_site": "00:10", "location": "39.615167, -104.887500", "time_window": { "start" : "13:00", "end" : "15:00" } },
{ "id": "job9", "time_on_site": "00:10", "location": "39.820688, -105.133594" },
{ "id": "job10", "time_on_site": "00:10", "location": "39.749546, -105.069141" },
{ "id": "job11", "time_on_site": "00:10", "location": "39.556465, -104.976563" }
]
}
The request defines three routes:
The request defines 12 jobs:
|
11. | Click Done. |
12. | Drag a json node from the parser section of the palette onto the canvas, and then connect the output from the template node to the input of the json node. This node converts the json into a format that can be accepted by the routecloud node. We could, if we wanted, now connect to the routecloud node to perform a route build operation. However, we would also like to time the RouteCloud operation to see how long the task takes to complete, so we instead place the routecloud node between two stopwatch nodes: one set as a start and the second set as an end. |
13. | Drag a stopwatch node from the advanced section of the palette onto the canvas, and then connect the output from the json node to the input of the stopwatch node. Double-click the stopwatch node, and check that the Timer drop-down menu is set to "Start", then click Done. |
14. | Drag a routecloud node from the telogis section of the palette onto the canvas, and then connect the output from the stopwatch node to the input of the routecloud node. Double-click the routecloud node, and then enter your platform credentials and the RouteCloud operation endpoint: |
|
12. | Drag another stopwatch node from the advanced section of the palette onto the canvas, and then connect the output from the routecloud node to the input of the stopwatch node. Double-click the stopwatch node, and check that the Timer drop-down menu is set to "End". Click Done to close the editor dialog box. These two nodes, together, add a message to the payload detailing the RouteCloud operation completion time, together with the output from that operation. To check that these results are being returned, we now add a debug node to send any messages created to the console and the debug tab. |
13. | Drag a debug node from the utility section of the palette onto the canvas, and then connect the output from the second stopwatch node to the input of the debug node. Double-click the debug node, and check that the to drop-down menu is set to "debug tab and console". Click Done to close the editor dialog box. |
14. | Click the Deploy button in the upper right corner of the screen to deploy the flow, and then run the flow by manually launching the inject node (that is, click the light blue circular button to the left of the inject node). Open the debug tab to view a string message describing the length of time the RouteCloud operation took to complete the operation. Below this, an array response object describes the results of the build operation. For a detailed description of the formatting of this response, see Buidling Routes > Response. For suitable example files for sequencing, recommendation, insertion and evaluation RouteCloud operations, see the RouteCloud Help. |
The flow created in this tutorial is described by the JSON below. To successfully execute this flow, you must edit the routecloud node Config to add your own platform authentication credentials before you deploy.
To import a flow into the Editor, copy the code provided, click the upper right ≡ Menu button, then select "Import" > "Clipboard". Paste the code in the Import nodes window, then click Import.
Code:
[
{
"id": "13547d16.9e25e3",
"type": "inject",
"z": "254cf119.69911e",
"name": "",
"topic": "",
"payload": "",
"payloadType": "date",
"crontab": "",
"timezone": "US/Pacific",
"once": false,
"x": 400,
"y": 260,
"wires": [
[
"2974edc5.1c7612"
]
]
},
{
"id": "4bfd05dd.67df4c",
"type": "debug",
"z": "254cf119.69911e",
"name": "",
"active": true,
"console": "true",
"complete": "payload",
"x": 1400,
"y": 460,
"wires": []
},
{
"id": "55d5cdbd.205c64",
"type": "telogis-routecloud-api",
"z": "254cf119.69911e",
"name": "",
"config": "fa8d5a03.d58ea8",
"endpoint": "/v1/build",
"x": 1120,
"y": 360,
"wires": [
[
"9a40074b.f494a8"
]
]
},
{
"id": "2974edc5.1c7612",
"type": "template",
"z": "254cf119.69911e",
"name": "routecloud json",
"field": "payload",
"fieldType": "msg",
"format": "handlebars",
"syntax": "mustache",
"template": "{\n \"id\": \"quick_start_build\",\n \"return_request\": true,\n \"routes\": [\n {\n \"id\": \"route0\",\n
\"location\": \"39.718005, -104.969531\",\n \"start_time\": \"09:00\",\n \"max_working_time\": \"08:00\",\n
\"date\": \"2016-1-18\",\n \"breaks\": [\n { \"id\": \"route0_lunch_break\", \"start\": \"12:00\", \"length\": \"00:30\" }\n ]\n }, {\n
\"id\": \"route1\",\n \"location\": \"39.718005, -104.969531\",\n \"start_time\": \"09:00\",\n \"max_working_time\": \"08:00\",\n
\"route_attributes\": [\"hazmat\"],\n \"date\": \"2016-1-19\",\n \"breaks\": [\n { \"id\": \"route1_lunch_break\", \"start\": \"12:00\",
\"length\": \"00:30\" }\n ]\n }, {\n \"id\": \"route2\",\n \"location\": \"39.718005, -104.969531\",\n \"start_time\": \"09:00\",\n
\"max_working_time\": \"04:00\",\n \"date\": \"2016-1-20\",\n \"breaks\": [\n { \"id\": \"route2_lunch_break\", \"start\": \"12:00\",
\"length\": \"00:30\" }\n ]\n }\n ],\n \"jobs\": [\n { \"id\": \"job0\", \"time_on_site\": \"00:10\", \"location\": \"39.635928, -105.049219\" },
\n { \"id\": \"job1\", \"time_on_site\": \"00:10\", \"location\": \"39.725375, -104.791080\", \"date\": \"2016-1-18\" },\n { \"id\": \"job2\",
\"time_on_site\": \"00:15\", \"location\": \"39.708990, -105.026954\", \"date\": \"2016-1-19\" },\n { \"id\": \"job3\", \"time_on_site\": \"00:10\",
\"location\": \"39.653975, -105.093750\", \"allowed_dates\": [ \"2016-1-18\", \"2016-1-19\" ] },\n { \"id\": \"job4\", \"time_on_site\": \"00:15\",
\"location\": \"39.590789, -105.084376\", \"allowed_dates\": [ \"2016-1-20\" ] },\n { \"id\": \"job5\", \"time_on_site\": \"00:10\", \"location\":
\"39.638635, -105.128906\", \"required_route_attributes\": [ \"hazmat\" ] },\n { \"id\": \"job6\", \"time_on_site\": \"00:10\", \"location\":
\"39.597111, -105.041015\", \"disallowed_route_attributes\": [ \"hazmat\" ] },\n { \"id\": \"job7\", \"time_on_site\": \"00:10\",
\"location\": \"39.727919, -105.103126\", \"required_route_attributes\": [ \"heavy_truck\" ] },\n { \"id\": \"job8\", \"time_on_site\": \"00:10\",
\"location\": \"39.615167, -104.887500\", \"time_window\": { \"start\" : \"13:00\", \"end\" : \"15:00\" } },\n { \"id\": \"job9\", \"time_on_site\":
\"00:10\", \"location\": \"39.820688, -105.133594\" },\n { \"id\": \"job10\", \"time_on_site\": \"00:10\", \"location\": \"39.749546, -105.069141\" },
\n { \"id\": \"job11\", \"time_on_site\": \"00:10\", \"location\": \"39.556465, -104.976563\" }\n ]\n}",
"x": 660,
"y": 260,
"wires": [
[
"b0349c4b.faa3e"
]
]
},
{
"id": "b0349c4b.faa3e",
"type": "json",
"z": "254cf119.69911e",
"name": "",
"x": 870,
"y": 260,
"wires": [
[
"a4380dd7.c7c76"
]
]
},
{
"id": "a4380dd7.c7c76",
"type": "stopwatch",
"z": "254cf119.69911e",
"action": "start",
"message": "",
"x": 920,
"y": 360,
"wires": [
[
"55d5cdbd.205c64"
]
]
},
{
"id": "9a40074b.f494a8",
"type": "stopwatch",
"z": "254cf119.69911e",
"action": "end",
"message": "RouteCloud",
"x": 1320,
"y": 360,
"wires": [
[
"4bfd05dd.67df4c"
]
]
},
{
"id": "fa8d5a03.d58ea8",
"type": "api-config",
"z": "",
"proxy": "",
"instance": "production",
"custominstance": "",
"labelValue": "production - acme123:main",
"useMessageCredentials": "false",
"credentialsCustomer": "acme123",
"credentialsUser": "main",
"createAuthServiceToken": true
}
]