{"_id":"571e9a5fd8667f0e00a3c341","parentDoc":null,"project":"56a83b979ec7660d002e07be","user":"56a83a6070a9440d00ef5ef8","__v":3,"category":{"_id":"56a83b989ec7660d002e07c2","pages":["56a83b999ec7660d002e07c4","56a83c1011d0390d00a3d107","56a83c6ded52570d0001a1e8","56a83cba70a9440d00ef5ef9","56a83f1470a9440d00ef5efb","56a83f5b70a9440d00ef5efd","56a97284f834950d0037b35e","56a973312bb3910d000ee937"],"project":"56a83b979ec7660d002e07be","version":"56a83b989ec7660d002e07c1","__v":8,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-01-27T03:38:00.961Z","from_sync":false,"order":1,"slug":"documentation","title":"General"},"version":{"_id":"56a83b989ec7660d002e07c1","project":"56a83b979ec7660d002e07be","__v":9,"createdAt":"2016-01-27T03:38:00.333Z","releaseDate":"2016-01-27T03:38:00.333Z","categories":["56a83b989ec7660d002e07c2","56a83c282036420d002d21e1","56a96de8f834950d0037b35a","56a9706013a69a0d00a778c3","56a970ec2d8fd90d0036eec7","56a971a62bb3910d000ee934","56a973372d8fd90d0036eece","56a978dc2bb3910d000ee93f","571d5ae118b3c10e003e55cd"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"Beta","version_clean":"1.0.0","version":"1.0"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-04-25T22:29:51.397Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"settings":"","results":{"codes":[]},"auth":"required","params":[],"url":""},"isReference":false,"order":999,"body":"<div class=\"corner-ribbon top-left sticky blue\"><a style=\"color: white;\" href=\"https://pathfinder.readme.io/blog/pathfinder-now-in-public-beta\">Public Beta!</a></div>\n\n# Models\n\n## Transport\n* path - the unique id for a transport, is a string\n* model - always \"Transport\"\n* latitude/longitude - floats indicating the gps position of the transport\n* metadata - a json object used to store information\n* status - indicates the status of the transport\n  * Offline - transport is not being routed, is the default status\n  * Online - transport can be routed\n\n## Commodity\n* path - the unique id for the commodity\n* model - always \"Commodity\"\n* startLatitude/startLongitude - floats indicating the position the commodity is being picked up from\n* endLatitude/endLongitude - floats indicating the position the commodity is to be dropped off at\n* metadata - a json object used to store information\n* status - indicates the status of the commodity\n  * Inactive - commodity is to be ignored by the router, is the default status\n  * Waiting - commodity is waiting for a transport, it should be routed\n  * PickedUp - commodity is travelling in a transport\n  * DroppedOff - commodity was dropped off at its destination\n  * Cancelled - commodity was cancelled and should be ignored by the router\n\n# Transports\n\n## Read Transport\n\nIn 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\n\n```\nvar transport;\n\nsocket.onmessage = function(msg){\n    var resp = msg.data;\n    transport = resp.model.value;\n};\n\nvar msg = {\n  {\n    \"type\":\"read\",\n    \"path\":\"/default/child/transport1\",\n    \"model\":\"Transport\"\n  }\n};\nsocket.send(Json.stringify(msg));\n```\n\n### Request\nFor the request, you specify the transport type and provide the id of the desired transport\n\n```\n{\n  \"type\":\"read\",\n  \"path\":\"/default/child/transport1\",\n  \"model\":\"Transport\"\n}\n```\n### Response\nThe response has a model object that contains the transport as the value\n\n```\n{\n  \"type\":\"model\",\n  \"path\":\"/default/child/transport1\",\n  \"model\":\"Transport\",\n  \"value\":{\n    \"path\":\"/default/child/transport1\",\n    \"model\":\"Transport\",\n    \"longitude\":2.9,\n    \"latitude\":7.2,\n    \"status\":\"Online\",\n    \"metadata\":{\"capacity\":6}\n  }\n}\n```\n## Create Transport\n\n### Request\nA new transport requires a path, latitude, longitude, status, and metadata\n```\n{\n  \"type\":\"create\",\n  \"path\":\"/default/child/transport1\",\n  \"model\":\"Transport\",\n  \"value\":{\n    \"path\":\"/default/child/transport1\",\n    \"model\":\"Transport\",\n    \"latitude\":0.123,\n    \"longitude\":0.456,\n    \"metadata\":{\"capacity\":4},\n    \"status\":\"Online\"\n  }\n}\n```\n### Response\nThe response is an object with created which has the transport as the value\n```\n{\n  \"type\":\"created\",\n  \"path\":\"/default/child/transport1\",\n  \"model\":\"Transport\",\n  \"value\":{\n    \"path\":\"/default/child/transport1\",\n    \"model\":\"Transport\",\n    \"latitude\":0.123,\n    \"longitude\":0.456,\n    \"status\":\"Online\",\n    \"metadata\":{\"capacity\":4}\n  }\n}\n```\n## Update Transport\n\n### Request\n\nAn 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.\n\n```\n{\n  \"type\":\"update\",\n  \"path\":\"/default/child/anotherTransport\",\n  \"model\":\"Transport\",\n  \"value\":{\n    \"latitude\":1.2,\n    \"longitude\":66,\n    \"metadata\":{\"capacity\":10,\"email\":\"myemail:::at:::gmail.com\"}\n  }\n}\n```\n### Response\n```\n{\n  \"type\":\"updated\",\n  \"path:\"/default/child/anotherTransport\",\n  \"model\":\"Transport\",\n  \"value\":{\n    \"path\":\"/default/child/anotherTransport\",\n    \"model\":\"Transport\",\n    \"latitude\":1.2,\n    \"longitude\":66,\n    \"status\":\"Online\",\n    \"metadata\":{\"capacity\":10,\"email\":\"myemail@gmail.com\"}\n  }\n}\n```\n## Delete Transport\n\n### Request\n```\n{\n  \"type\":\"delete\",\n  \"path\":\"/default/child/transport1\",\n  \"model\":\"Transport\"\n}\n```\n\n### Response\n```\n{\n  \"type\":\"deleted\",\n  \"path\":\"/default/child/transport1\",\n  \"model\":\"Transport\",\n  \"value\":{\n    \"path\":\"/default/child/transport1\",\n    \"model\":\"Transport\",\n    \"latitude\":40,\n    \"longitude\":30,\n    \"status\":\"Offline\",\n    \"metadata\":{\"capacity\":11}\n  }\n}\n```\n## Error Transport\n\nIf you create a message that will cause an error on Pathfinder-server, it will send a response in the form\n```\n{\n  \"type\":\"error\",\n  \"path\":\"/default/child/transport1\",\n  \"model\":\"Transport\",\n  \"value\":{\n    \"reason\":\"Model with that path already exists\"\n  }\n}\n```\n# Commodities\n\n## Read Commodities\n\nReading Commodities is similar to reading transports, you just use Commodity instead of Transport for the type field\n\n### Request\n\n```\n{\n  \"type\":\"read\",\n  \"path\":\"/defaut/myCluster/milk\",\n  \"model\":\"Commodity\"\n}\n```\n### Response\nThe response has a model object that contains the commodity\n\n```\n{\n  \"type\":\"model\",\n  \"path\":\"/default/myCluster/milk\",\n  \"model\":\"Commodity\",\n  \"value\":{\n    \"path\":\"/default/myCluster/milk\",\n    \"model\":\"Commodity\",\n    \"startLongitude\":2.9,\n    \"startLatitude\":7.4,\n    \"endLongitude\":3.2,\n    \"endLatitude\":2.5,\n    \"status\":\"PickedUp\",\n    \"metadata\":{\"param\":6}\n  }\n}\n```\n## Create Commodity\n\n### Request\nA new commodity requires a startLatitude, startLongitude, endLatitude, endLongitude, metadata, and a path\n```\n{\n  \"type\":\"create\",\n  \"path\":\"/default/cluster932/pizza\",\n  \"model\":\"Commodity\",\n  \"value\":{\n    \"path\":\"/default/cluster932/pizza\",\n    \"model\":\"Commodity\",\n    \"startLatitude\":0.123,\n    \"startLongitude\":0.456,\n    \"endLatitude\":0.789,\n    \"endLongitude\":0.101,\n    \"metadata\":{\"param\":4},\n    \"status\":\"Waiting\"\n  }\n}\n```\n### Response\nThe response is an object with created which has the Commodity\n```\n{\n  \"type\":\"created\",\n  \"path\":\"/default/cluster932/pizza\",\n  \"model\":\"Commodity\",\n  \"value\":{\n    \"path\":\"/default/cluster932/pizza\",\n    \"model\":\"Commodity\",\n    \"startLatitude\":0.123,\n    \"startLongitude\":0.456,\n    \"endLatitude\":0.789,\n    \"endLongitude\":0.101,\n    \"status\":\"Waiting\",\n    \"metadata\":{\"param\":4}\n  }\n}\n```\n## Update Commodity\n\n### Request\n\nAn 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.\n\n```\n{\n  \"type\":\"update\",\n  \"path\":\"/default/clus/turkey\",\n  \"model\":\"Commodity\",\n  \"value\":{\n    \"endLatitude\":1.2,\n    \"endLongitude\":66,\n    \"status\":\"DroppedOff\"\n  }\n}\n```\n### Response\n```\n{\n  \"type\":\"updated\",\n  \"path\":\"/default/clus/turkey\",\n  \"model\":\"Commodity\",\n  \"value\":{\n    \"path\":\"/default/clus/turkey\",\n    \"model\":\"Commodity\",\n    \"startLatitude\":0.123,\n    \"startLongitude\":0.456,\n    \"endLatitude\":1.2,\n    \"endLongitude\":66,\n    \"status\":\"DroppedOff\",\n    \"metadata\":{\"param\":4}\n  }\n}\n```\n## Deleting a Commodity\n\nLike a transport, you delete the commodity by specifying its path\n\n### Request\n```\n{\n  \"type\":\"delete\",\n  \"path\":\"/default/myPizzaPlace/pizza329\",\n  \"model\":\"Commodity\"\n}\n```\n\n### Response\n```\n{\n  \"type\":\"deleted\",\n  \"path\":\"/default/myPizzaPlace/pizza329\",\n  \"model\":\"Commodity\",\n  \"value\":{\n    \"path\":\"/default/myPizzaPlace/pizza329\",\n    \"model\":\"Commodity\",\n    \"startLatitude\":0.123,\n    \"startLongitude\":0.456,\n    \"endLatitude\":1.2,\n    \"endLongitude\":66,\n    \"status\":\"Cancelled\",\n    \"metadata\":{\"param\":4}\n  }\n}\n```\n\n## Error Commodity\n\nIf you create a message that will cause an error on Pathfinder-server, it will send a response in the form\n```\n{\n  \"type\":\"error\",\n  \"path\":\"/default/child/c1\",\n  \"model\":\"Commodity\",\n  \"value\": {\n    \"reason\":\"Model with that path already exists\"\n  }\n}\n```\n\n# Clusters\n\nClusters can read, created and deleted\n\n## Reading a cluster\n\nWhen reading a cluster you will receive all of the cluster's fields. Note, you will receive all levels of subclusters.\n\n### Request\n\n```\n{\n  \"type\":\"read\",\n  \"path\":\"/default/myCluster\",\n  \"model\":\"Cluster\"\n}\n```\n### Response\n```\n{\n  \"type\":\"model\",\n  \"path\":\"/default/myCluster\",\n  \"model\":\"Cluster\",\n  \"value\":{\n    \"path\":\"/default/myCluster\",\n    \"model\":\"Cluster\",\n    \"transports\":[\n      {\"path\":\"/default/myCluster/t1\", \"model\":\"Transport\", \"latitude\":19, \"longitude\":77, \"metadata\":{\"capacity\":3}, \"status\":\"Offline\"},\n      {\"path\":\"/default/myCluster/t2\", \"model\":\"Transport\", \"latitude\":10, \"longitude\":22, \"metadata\":{\"capacity\":4}, \"status\":\"Offline\"},\n      {\"path\":\"/default/myCluster/t2\", \"model\":\"Transport\", \"latitude\":21, \"longitude\":31, \"metadata\":{\"capacity\":2}, \"status\":\"Offline\"}\n    ],\n    \"commodities\":[\n      {\"path\":\"/default/myCluster/c1\", \"model\":\"Commodity\", \"metadata\":{\"param\":4},\n        \"startLatitude\":0.123, \"startLongitude\":0.456,\n        \"endLatitude\":1.2, \"endLongitude\":66,\n        \"status\":\"Inactive\"},\n      {\"path\":\"/default/myCluster/c1\", \"model\":\"Commodity\", \"metadata\":{\"param\":3},\n        \"startLatitude\":923, \"startLongitude\":5.756,\n        \"endLatitude\":77, \"endLongitude\":606,\n        \"status\":\"Inactive\" }\n    ],\n      \"subClusters\":[]\n  }\n}\n```\n## Creating a cluster\n\nclusters can be created from an empty object\n\n### Request\n```\n{\n  \"type\":\"create\",\n  \"path\":\"/default/clusterName\",\n  \"model\":\"Cluster\",\n  \"value\":{\n    \"path\":\"/default/clusterName\",\n    \"model\":\"Cluster\"\n  }\n}\n```\n### Response\n```\n{\n  \"type\":\"created\",\n  \"path\":\"/default/clusterName\",\n  \"model\":\"Cluster\",\n  \"value\":{\n    \"path\":\"/default/clusterName\",\n    \"model\":\"Cluster\",\n    \"commodities\":[],\n    \"transports\":[],\n    \"subClusters\":[]\n  }\n}\n```\n\n## Creating a subcluster\n\nA sub cluster is created by specifying the parent cluster's path plus a cluster name \n\n### Request\n```\n{\n  \"type\":\"create\",\n  \"path\":\"/default/parentCluster/mySubclusterName\",\n  \"model\":\"Cluster\",\n  \"value\":{\n    \"path\":\"/default/parentCluster/mySubclusterName\",\n    \"model\":\"Cluster\"\n  }\n}\n```\n\n## Deleting a cluster\nDeleting a cluster is similar to deleting a commodity or a transport\n\n### Request\n```\n{\n  \"type\":\"delete\",\n  \"path\":\"/default/myCluster\",\n  \"model\":\"Cluster\"\n}\n```\n### Response\n```\n{\n  \"type\":\"deleted\",\n  \"path\":\"/default/myCluster\",\n  \"model\":\"Cluster\",\n  \"value\":{\n    \"path\":\"/default/myCluster\",\n    \"model\":\"Cluster\",\n    \"transports\":[\n      {\"path\":\"/default/myCluster/t1\", \"model\":\"Transport\", \"latitude\":19, \"longitude\":77, \"metadata\":{\"capacity\":3}, \"status\":\"Offline\"},\n      {\"path\":\"/default/myCluster/t2\", \"model\":\"Transport\", \"latitude\":10, \"longitude\":22, \"metadata\":{\"capacity\":4}, \"status\":\"Online\"},\n      {\"path\":\"/default/myCluster/t3\", \"model\":\"Transport\", \"latitude\":21, \"longitude\":31, \"metadata\":{\"capacity\":2}, \"status\":\"Offline\"}\n    ],\n    \"commodities\":[\n      {\"path\":\"/default/myCluster/c1\", \"model\":\"Commodity\", \"metadata\":{\"param\":4},\n        \"startLatitude\":0.123, \"startLongitude\":0.456,\n        \"endLatitude\":1.2, \"endLongitude\":66,\n        \"status\":\"Waiting\"},\n      {\"path\":\"/default/myCluster/c2\", \"model\":\"Commodity\", \"metadata\":{\"param\":3},\n        \"startLatitude\":923, \"startLongitude\":5.756,\n        \"endLatitude\":77, \"endLongitude\":606,\n        \"status\":\"DroppedOff\"}\n    ],\n    \"subclusters\":[]\n  }\n}\n```\n\n## Error Commodity\n\nIf you create a message that will cause an error on Pathfinder-server, it will send a response in the form\n```\n{\n  \"type\":\"error\",\n  \"path\":\"/default/myCluster\",\n  \"model\":\"Cluster\",\n  \"value\": {\n    \"reason\":\"Model with that path already exists\"\n  }\n}\n```\n\n# Routes\n\nThe user can obtain a route for any transport or commodity\n\n## Get a route\n\nThe route request requires the model type and its path\n\n### Request\n```\n{\n  \"type\":\"route\",\n  \"path\":\"/default/cluster1/t1\",\n  \"model\":\"Transport\"\n}\n```\n### Response\nThe 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.\n```\n{\n  \"type\":\"routed\",\n  \"path\":\"/default/c1/t1\",\n  \"model\":\"Transport\",\n  \"value\":{\"path\":\"/default/c1/t1\", \"model\":\"Transport\", \"latitude\":100, \"longitude\":-150, \"metadata\":{capacity\":3}, \"status\":\"Online\"},\n  \"route\":{\n    \"model\":{\"path\":\"/default/c1/t1\", \"model\":\"Transport\", \"latitude\":100, \"longitude\":-150, \"metadata\":{\"capacity\":3}, \"status\":\"Online\"},\n    \"actions\":[\n      {\"action\":\"start\",\"latitude\":100,\"longitude\":-150,\"model\":{\"path\":\"/default/c1/t1\", \"model\":\"Transport\", \"latitude\":100, \"longitude\":-150, \"metadata\":{\"capacity\":3}, \"status\":\"Online\"}},\n      {\"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\"},\n      {\"action\":\"pickup\",\"latitude\":12,\"longitude\":20,\"model\":{\"path\":\"/default/clus/com2\", \\\\ other commodity fields }},\n      {\"action\":\"dropoff\",\"latitude\":2,\"longitude\":30,\"model\":{\"path\":\"/default/clus/com2\", \\\\ other commodity fields }},\n      {\"action\":\"dropoff\",\"latitude\":5,\"longitude\":12,\"model\":{\"path\":\"/default/clus/com1\", \\\\ other commodity fields }}\n    ]\n  }\n}\n```\n### Routed message for a cluster\n```\n{\n  \"type\":\"routed\",\n  \"path\":\"/default/cluster1\",\n  \"model\":\"Cluster\",\n  \"value\":{\n    \"path\":\"/default/cluster1\",\n    \"model\":\"Cluster\",\n    \"transports\":[\n      {\"path\":\"/default/cluster1/t1\", \"model\":\"Transport\", \"latitude\":100, \"longitude\":-150, \"metadata\":{\"capacity\":3}, \"status\":\"Online\"},\n      {\"path\":\"/default/cluster1/t2\", \"model\":\"Transport\", \"latitude\":90, \"longitude\":-160, \"metadata\":{\"capacity\":2}, \"status\":\"Online\"}\n    ],\n    \"commodities\":[\n      {\"path\":\"/default/cluster1/com1\", \"model\":\"Commodity\", \"startLatitude\":20, \"startLongitude\":5, \"endLatitude\":5, \"endLongitude\":12, \"metadata\":{\"param\":3}, \"status\":\"Waiting\"},\n      {\"path\":\"/default/cluster1/com2\", ... },\n      {\"path\":\"/default/cluster1/com3\", ... }\n    ],\n    \"subClusters\":[\n      {\"path\":\"/default/cluster1/mySubcluster\", \"model\":\"Cluster\", \"transports\":[], \"commodities\":[], \"subClusters\":[] }\n    ]\n  },  \n  \"route\":[\n    {\n      \"model\":{\"path\":\"/default/cluster/t1\", \"model\":\"Transport\", \"latitude\":100, \"longitude\":-150, \"metadata\":{\"capacity\":3}, \"status\":\"Online\"},\n      \"actions\":[\n        {\"action\":\"start\",\"latitude\":100,\"longitude\":-150,\"model\":{\"path\":\"/default/cluster/t1\", \"model\":\"Transport\", \"latitude\":100, \"longitude\":-150, \"metadata\":{\"capacity\":3}, \"status\":\"Online\"}},\n        {\"action\":\"pickup\",\"latitude\":20,\"longitude\":5,\n          \"model\":{\"path\":\"/default/cluster1/com1\", \"model\":\"Commodity\", \"startLatitude\":20, \"startLongitude\":5, \"endLatitude\":5, \"endLongitude\":12, \"metadata\":{\"param\":3}, \"status\":\"Waiting\" },\n        { \"action\":\"pickup\",\"latitude\":12,\"longitude\":20,\"model\":{\"path\":\"/default/cluster1/com2\", /* other commodity fields */} },\n        { \"action\":\"dropoff\",\"latitude\":2,\"longitude\":30,\"model\":{\"path\":\"/default/cluster1/com2\", /* other commodity fields */} },\n        { \"action\":\"dropoff\",\"latitude\":5,\"longitude\":12,\"model\":{\"path\":\"/default/cluster1/com1\", /* other commodity fields */} }\n      ]\n    },\n    {\n      \"model\":{\"path\":\"/default/cluster1/t2\",\"model\":\"Transport\",\"latitude\":90, \"longitude\":-160, \"metadata\":{\"capacity\":2}, \"status\":\"Online\"},\n      \"actions\":[\n        /* Actions for \"/default/cluster1/t2\" */\n      ]\n    }\n  ]\n}\n```\n\n# Subscriptions\nYou 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\n\n## Cluster Level Subscription\nHere is how to get notifications for whenever a commodity or transport is created, updated, or deleted in a cluster.\n\n### Request\n```\n{\n  \"type\":\"subscribe\",\n  \"path\":\"/default/clusterName\",\n  \"model\":\"Cluster\"\n}\n```\n\n### Response\n```\n{\n  \"type\":\"subscribed\",\n  \"path\":\"/default/clusterName\",\n  \"model\":\"Cluster\"\n}\n```\nYou now will receive either a Created, Updated or Deleted message whenever a transport or a commodity is created, updated, or deleted in the cluster\n\n## Model Level Subscriptions\nSometimes 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.\n\n### Request\n```\n{\n  \"type\":\"subscribe\",\n  \"path\":\"/default/clusterName/t1\",\n  \"model\":\"Transport\"\n}\n```\n### Response\n```\n{\n  \"type\":\"subscribed\",\n  \"path\":\"/default/clusterName/t1\",\n  \"model\":\"Transport\"\n}\n```\nYou now will receive Update messages whenever the transport is modified\n\n# Route Subscriptions\nRoute 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.\n\n### Request\n```\n{\n  \"type\":\"routeSubscribe\",\n  \"path\":\"/default/clusterName/t1\",\n  \"model\":\"Transport\"\n}\n```\n### Response\n```\n{\n  \"type\":\"routeSubscribed\",\n  \"path\":\"/default/clusterName/t1\",\n  \"model\":\"Transport\"\n}\n```","excerpt":"","slug":"websocket-api","type":"basic","title":"Websocket API"}
<div class="corner-ribbon top-left sticky blue"><a style="color: white;" href="https://pathfinder.readme.io/blog/pathfinder-now-in-public-beta">Public Beta!</a></div> # Models ## Transport * 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 ## Commodity * 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 # Transports ## Read Transport 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)); ``` ### Request For the request, you specify the transport type and provide the id of the desired transport ``` { "type":"read", "path":"/default/child/transport1", "model":"Transport" } ``` ### Response 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} } } ``` ## Create Transport ### Request 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" } } ``` ### Response 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} } } ``` ## Update Transport ### Request 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":"myemail@gmail.com"} } } ``` ### Response ``` { "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":"myemail@gmail.com"} } } ``` ## Delete Transport ### Request ``` { "type":"delete", "path":"/default/child/transport1", "model":"Transport" } ``` ### Response ``` { "type":"deleted", "path":"/default/child/transport1", "model":"Transport", "value":{ "path":"/default/child/transport1", "model":"Transport", "latitude":40, "longitude":30, "status":"Offline", "metadata":{"capacity":11} } } ``` ## Error Transport 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" } } ``` # Commodities ## Read Commodities Reading Commodities is similar to reading transports, you just use Commodity instead of Transport for the type field ### Request ``` { "type":"read", "path":"/defaut/myCluster/milk", "model":"Commodity" } ``` ### Response 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} } } ``` ## Create Commodity ### Request 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" } } ``` ### Response 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} } } ``` ## Update Commodity ### Request 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" } } ``` ### Response ``` { "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} } } ``` ## Deleting a Commodity Like a transport, you delete the commodity by specifying its path ### Request ``` { "type":"delete", "path":"/default/myPizzaPlace/pizza329", "model":"Commodity" } ``` ### Response ``` { "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} } } ``` ## Error Commodity 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 Clusters can read, created and deleted ## Reading a cluster When reading a cluster you will receive all of the cluster's fields. Note, you will receive all levels of subclusters. ### Request ``` { "type":"read", "path":"/default/myCluster", "model":"Cluster" } ``` ### Response ``` { "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":[] } } ``` ## Creating a cluster clusters can be created from an empty object ### Request ``` { "type":"create", "path":"/default/clusterName", "model":"Cluster", "value":{ "path":"/default/clusterName", "model":"Cluster" } } ``` ### Response ``` { "type":"created", "path":"/default/clusterName", "model":"Cluster", "value":{ "path":"/default/clusterName", "model":"Cluster", "commodities":[], "transports":[], "subClusters":[] } } ``` ## Creating a subcluster A sub cluster is created by specifying the parent cluster's path plus a cluster name ### Request ``` { "type":"create", "path":"/default/parentCluster/mySubclusterName", "model":"Cluster", "value":{ "path":"/default/parentCluster/mySubclusterName", "model":"Cluster" } } ``` ## Deleting a cluster Deleting a cluster is similar to deleting a commodity or a transport ### Request ``` { "type":"delete", "path":"/default/myCluster", "model":"Cluster" } ``` ### Response ``` { "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":[] } } ``` ## Error Commodity 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" } } ``` # Routes The user can obtain a route for any transport or commodity ## Get a route The route request requires the model type and its path ### Request ``` { "type":"route", "path":"/default/cluster1/t1", "model":"Transport" } ``` ### Response 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 }} ] } } ``` ### Routed message for a cluster ``` { "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" */ ] } ] } ``` # Subscriptions 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 ## Cluster Level Subscription Here is how to get notifications for whenever a commodity or transport is created, updated, or deleted in a cluster. ### Request ``` { "type":"subscribe", "path":"/default/clusterName", "model":"Cluster" } ``` ### Response ``` { "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 ## Model Level Subscriptions 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. ### Request ``` { "type":"subscribe", "path":"/default/clusterName/t1", "model":"Transport" } ``` ### Response ``` { "type":"subscribed", "path":"/default/clusterName/t1", "model":"Transport" } ``` You now will receive Update messages whenever the transport is modified # Route Subscriptions 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. ### Request ``` { "type":"routeSubscribe", "path":"/default/clusterName/t1", "model":"Transport" } ``` ### Response ``` { "type":"routeSubscribed", "path":"/default/clusterName/t1", "model":"Transport" } ```