-
Notifications
You must be signed in to change notification settings - Fork 1
New Websocket API
- path - the unique id for a transport, is a string
- model - always "Transport"
- latitude/longitude - floats indicating the gps position of the transport
- metadata - a json object used to store information
- status - indicates the status of the transport
- Offline - transport is not being routed, is the default status
- Online - transport can be routed
- path - the unique id for the commodity
- model - always "Commodity"
- startLatitude/startLongitude - floats indicating the position the commodity is being picked up from
- endLatitude/endLongitude - floats indicating the position the commodity is to be dropped off at
- metadata - a json object used to store information
- status - indicates the status of the commodity
- Inactive - commodity is to be ignored by the router, is the default status
- Waiting - commodity is waiting for a transport, it should be routed
- PickedUp - commodity is travelling in a transport
- DroppedOff - commodity was dropped off at its destination
- Cancelled - commodity was cancelled and should be ignored by the router
In order to read a transport, you use read, specifying the transport model and its path. The response stores the requested transport in the value field, here is how to read the transport from a socket
var transport;
socket.onmessage = function(msg){
var resp = msg.data;
transport = resp.model.value;
};
var msg = {
{
"type":"read",
"path":"/default/child/transport1",
"model":"Transport"
}
};
socket.send(Json.stringify(msg));
For the request, you specify the transport type and provide the id of the desired transport
{
"type":"read",
"path":"/default/child/transport1",
"model":"Transport"
}
The response has a model object that contains the transport as the value
{
"type":"model",
"path":"/default/child/transport1",
"model":"Transport",
"value":{
"path":"/default/child/transport1",
"model":"Transport",
"longitude":2.9,
"latitude":7.2,
"status":"Online",
"metadata":{"capacity":6}
}
}
A new transport requires a path, latitude, longitude, status, and metadata
{
"type":"create",
"path":"/default/child/transport1",
"model":"Transport",
"value":{
"path":"/default/child/transport1",
"model":"Transport",
"latitude":0.123,
"longitude":0.456,
"metadata":{"capacity":4},
"status":"Online"
}
}
The response is an object with created which has the transport as the value
{
"type":"created",
"path":"/default/child/transport1",
"model":"Transport",
"value":{
"path":"/default/child/transport1",
"model":"Transport",
"latitude":0.123,
"longitude":0.456,
"status":"Online",
"metadata":{"capacity":4}
}
}
An update is similar to a create except you need so specify the path of the row that you are updating, for an update, no fields are required for a transport.
{
"type":"update",
"path":"/default/child/anotherTransport",
"model":"Transport",
"value":{
"latitude":1.2,
"longitude":66,
"metadata":{"capacity":10,"email":"[email protected]"}
}
}
{
"type":"updated",
"path:"/default/child/anotherTransport",
"model":"Transport",
"value":{
"path":"/default/child/anotherTransport",
"model":"Transport",
"latitude":1.2,
"longitude":66,
"status":"Online",
"metadata":{"capacity":10,"email":"[email protected]"}
}
}
{
"type":"delete",
"path":"/default/child/transport1",
"model":"Transport"
}
{
"type":"deleted",
"path":"/default/child/transport1",
"model":"Transport",
"value":{
"path":"/default/child/transport1",
"model":"Transport",
"latitude":40,
"longitude":30,
"status":"Offline",
"metadata":{"capacity":11}
}
}
If you create a message that will cause an error on Pathfinder-server, it will send a response in the form
{
"type":"error",
"path":"/default/child/transport1",
"model":"Transport",
"value":{
"reason":"Model with that path already exists"
}
}
Reading Commodities is similar to reading transports, you just use Commodity instead of Transport for the type field
{
"type":"read",
"path":"/defaut/myCluster/milk",
"model":"Commodity"
}
The response has a model object that contains the commodity
{
"type":"model",
"path":"/default/myCluster/milk",
"model":"Commodity",
"value":{
"path":"/default/myCluster/milk",
"model":"Commodity",
"startLongitude":2.9,
"startLatitude":7.4,
"endLongitude":3.2,
"endLatitude":2.5,
"status":"PickedUp",
"metadata":{"param":6}
}
}
A new commodity requires a startLatitude, startLongitude, endLatitude, endLongitude, metadata, and a path
{
"type":"create",
"path":"/default/cluster932/pizza",
"model":"Commodity",
"value":{
"path":"/default/cluster932/pizza",
"model":"Commodity",
"startLatitude":0.123,
"startLongitude":0.456,
"endLatitude":0.789,
"endLongitude":0.101,
"metadata":{"param":4},
"status":"Waiting"
}
}
The response is an object with created which has the Commodity
{
"type":"created",
"path":"/default/cluster932/pizza",
"model":"Commodity",
"value":{
"path":"/default/cluster932/pizza",
"model":"Commodity",
"startLatitude":0.123,
"startLongitude":0.456,
"endLatitude":0.789,
"endLongitude":0.101,
"status":"Waiting",
"metadata":{"param":4}
}
}
An update is similar to a create except you need so specify the path of the row that you are updating, for an update, no fields are required for a commodity.
{
"type":"update",
"path":"/default/clus/turkey",
"model":"Commodity",
"value":{
"endLatitude":1.2,
"endLongitude":66,
"status":"DroppedOff"
}
}
{
"type":"updated",
"path":"/default/clus/turkey",
"model":"Commodity",
"value":{
"path":"/default/clus/turkey",
"model":"Commodity",
"startLatitude":0.123,
"startLongitude":0.456,
"endLatitude":1.2,
"endLongitude":66,
"status":"DroppedOff",
"metadata":{"param":4}
}
}
Like a transport, you delete the commodity by specifying its path
{
"type":"delete",
"path":"/default/myPizzaPlace/pizza329",
"model":"Commodity"
}
{
"type":"deleted",
"path":"/default/myPizzaPlace/pizza329",
"model":"Commodity",
"value":{
"path":"/default/myPizzaPlace/pizza329",
"model":"Commodity",
"startLatitude":0.123,
"startLongitude":0.456,
"endLatitude":1.2,
"endLongitude":66,
"status":"Cancelled",
"metadata":{"param":4}
}
}
If you create a message that will cause an error on Pathfinder-server, it will send a response in the form
{
"type":"error",
"path":"/default/child/c1",
"model":"Commodity",
"value": {
"reason":"Model with that path already exists"
}
}
Clusters can read, created and deleted
When reading a cluster you will receive all of the cluster's fields. Note, you will receive all levels of subclusters.
{
"type":"read",
"path":"/default/myCluster",
"model":"Cluster"
}
{
"type":"model",
"path":"/default/myCluster",
"model":"Cluster",
"value":{
"path":"/default/myCluster",
"model":"Cluster",
"transports":[
{"path":"/default/myCluster/t1", "model":"Transport", "latitude":19, "longitude":77, "metadata":{"capacity":3}, "status":"Offline"},
{"path":"/default/myCluster/t2", "model":"Transport", "latitude":10, "longitude":22, "metadata":{"capacity":4}, "status":"Offline"},
{"path":"/default/myCluster/t2", "model":"Transport", "latitude":21, "longitude":31, "metadata":{"capacity":2}, "status":"Offline"}
],
"commodities":[
{"path":"/default/myCluster/c1", "model":"Commodity", "metadata":{"param":4},
"startLatitude":0.123, "startLongitude":0.456,
"endLatitude":1.2, "endLongitude":66,
"status":"Inactive"},
{"path":"/default/myCluster/c1", "model":"Commodity", "metadata":{"param":3},
"startLatitude":923, "startLongitude":5.756,
"endLatitude":77, "endLongitude":606,
"status":"Inactive" }
],
"subClusters":[]
}
}
clusters can be created from an empty object
{
"type":"create",
"path":"/default/clusterName",
"model":"Cluster",
"value":{
"path":"/default/clusterName",
"model":"Cluster"
}
}
{
"type":"created",
"path":"/default/clusterName",
"model":"Cluster",
"value":{
"path":"/default/clusterName",
"model":"Cluster",
"commodities":[],
"transports":[],
"subClusters":[]
}
}
A sub cluster is created by specifying the parent cluster's path plus a cluster name
{
"type":"create",
"path":"/default/parentCluster/mySubclusterName",
"model":"Cluster",
"value":{
"path":"/default/parentCluster/mySubclusterName",
"model":"Cluster"
}
}
Deleting a cluster is similar to deleting a commodity or a transport
{
"type":"delete",
"path":"/default/myCluster",
"model":"Cluster"
}
{
"type":"deleted",
"path":"/default/myCluster",
"model":"Cluster",
"value":{
"path":"/default/myCluster",
"model":"Cluster",
"transports":[
{"path":"/default/myCluster/t1", "model":"Transport", "latitude":19, "longitude":77, "metadata":{"capacity":3}, "status":"Offline"},
{"path":"/default/myCluster/t2", "model":"Transport", "latitude":10, "longitude":22, "metadata":{"capacity":4}, "status":"Online"},
{"path":"/default/myCluster/t3", "model":"Transport", "latitude":21, "longitude":31, "metadata":{"capacity":2}, "status":"Offline"}
],
"commodities":[
{"path":"/default/myCluster/c1", "model":"Commodity", "metadata":{"param":4},
"startLatitude":0.123, "startLongitude":0.456,
"endLatitude":1.2, "endLongitude":66,
"status":"Waiting"},
{"path":"/default/myCluster/c2", "model":"Commodity", "metadata":{"param":3},
"startLatitude":923, "startLongitude":5.756,
"endLatitude":77, "endLongitude":606,
"status":"DroppedOff"}
],
"subclusters":[]
}
}
If you create a message that will cause an error on Pathfinder-server, it will send a response in the form
{
"type":"error",
"path":"/default/myCluster",
"model":"Cluster",
"value": {
"reason":"Model with that path already exists"
}
}
The user can obtain a route for any transport or commodity
The route request requires the model type and its path
{
"type":"route",
"path":"/default/cluster1/t1",
"model":"Transport"
}
The route contains an array of actions which each have a position and a commodity, note that if a Route request is made for a cluster, the route value is an array of all the routes in the cluster.
{
"type":"routed",
"path":"/default/c1/t1",
"model":"Transport",
"value":{"path":"/default/c1/t1", "model":"Transport", "latitude":100, "longitude":-150, "metadata":{capacity":3}, "status":"Online"},
"route":{
"model":{"path":"/default/c1/t1", "model":"Transport", "latitude":100, "longitude":-150, "metadata":{"capacity":3}, "status":"Online"},
"actions":[
{"action":"start","latitude":100,"longitude":-150,"model":{"path":"/default/c1/t1", "model":"Transport", "latitude":100, "longitude":-150, "metadata":{"capacity":3}, "status":"Online"}},
{"action":"pickup","latitude":20,"longitude":5,"model":{"path":"/default/clus/com1", "model":"Commodity", "startLatitude":20, "startLongitude":5, "endLatitude":5, "endLongitude":12, "metadata":{"param":3}, "status":"Waiting"},
{"action":"pickup","latitude":12,"longitude":20,"model":{"path":"/default/clus/com2", \\ other commodity fields }},
{"action":"dropoff","latitude":2,"longitude":30,"model":{"path":"/default/clus/com2", \\ other commodity fields }},
{"action":"dropoff","latitude":5,"longitude":12,"model":{"path":"/default/clus/com1", \\ other commodity fields }}
]
}
}
{
"type":"routed",
"path":"/default/cluster1",
"model":"Cluster",
"value":{
"path":"/default/cluster1",
"model":"Cluster",
"transports":[
{"path":"/default/cluster1/t1", "model":"Transport", "latitude":100, "longitude":-150, "metadata":{"capacity":3}, "status":"Online"},
{"path":"/default/cluster1/t2", "model":"Transport", "latitude":90, "longitude":-160, "metadata":{"capacity":2}, "status":"Online"}
],
"commodities":[
{"path":"/default/cluster1/com1", "model":"Commodity", "startLatitude":20, "startLongitude":5, "endLatitude":5, "endLongitude":12, "metadata":{"param":3}, "status":"Waiting"},
{"path":"/default/cluster1/com2", ... },
{"path":"/default/cluster1/com3", ... }
],
"subClusters":[
{"path":"/default/cluster1/mySubcluster", "model":"Cluster", "transports":[], "commodities":[], "subClusters":[] }
]
},
"route":[
{
"model":{"path":"/default/cluster/t1", "model":"Transport", "latitude":100, "longitude":-150, "metadata":{"capacity":3}, "status":"Online"},
"actions":[
{"action":"start","latitude":100,"longitude":-150,"model":{"path":"/default/cluster/t1", "model":"Transport", "latitude":100, "longitude":-150, "metadata":{"capacity":3}, "status":"Online"}},
{"action":"pickup","latitude":20,"longitude":5,
"model":{"path":"/default/cluster1/com1", "model":"Commodity", "startLatitude":20, "startLongitude":5, "endLatitude":5, "endLongitude":12, "metadata":{"param":3}, "status":"Waiting" },
{ "action":"pickup","latitude":12,"longitude":20,"model":{"path":"/default/cluster1/com2", /* other commodity fields */} },
{ "action":"dropoff","latitude":2,"longitude":30,"model":{"path":"/default/cluster1/com2", /* other commodity fields */} },
{ "action":"dropoff","latitude":5,"longitude":12,"model":{"path":"/default/cluster1/com1", /* other commodity fields */} }
]
},
{
"model":{"path":"/default/cluster1/t2","model":"Transport","latitude":90, "longitude":-160, "metadata":{"capacity":2}, "status":"Online"},
"actions":[
/* Actions for "/default/cluster1/t2" */
]
}
]
}
You may want to subscribe to clusters or to models so that you are notified of relevant changes. This can be done through subscriptions. When subscribing to a model, you receive Updated messages for whenever it is changed, or a Deleted message when it is deleted. You can also subscribe to clusters to receive notifications on the transports or commodities in it
Here is how to get notifications for whenever a commodity or transport is created, updated, or deleted in a cluster.
{
"type":"subscribe",
"path":"/default/clusterName",
"model":"Cluster"
}
{
"type":"subscribed",
"path":"/default/clusterName",
"model":"Cluster"
}
You now will receive either a Created, Updated or Deleted message whenever a transport or a commodity is created, updated, or deleted in the cluster
Sometimes you may want to subscribe to a specific transport or commodity, such as if you want to receive a transport's position in real time. A model level subscription request is similar to a cluster level subscription request.
{
"type":"subscribe",
"path":"/default/clusterName/t1",
"model":"Transport"
}
{
"type":"subscribed",
"path":"/default/clusterName/t1",
"model":"Transport"
}
You now will receive Update messages whenever the transport is modified
Route subscriptions are similar to subscriptions except you receive the subscribed route whenever it changes. You can subscribe to the routes for transports, commodities, and clusters. After subscribing, the socket will receive Routed messages whenever the subscribed route changes. Note that after subscribing, the socket is immediately sent the most up to date route even if it has not changed since subscribing.
{
"type":"routeSubscribe",
"path":"/default/clusterName/t1",
"model":"Transport"
}
{
"type":"routeSubscribed",
"path":"/default/clusterName/t1",
"model":"Transport"
}