This repository was archived by the owner on Apr 8, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathexercise1.flow
More file actions
1 lines (1 loc) · 14.2 KB
/
exercise1.flow
File metadata and controls
1 lines (1 loc) · 14.2 KB
1
[{"id":"b64bf7d2.49b408","type":"mqtt-broker","broker":"broker.mqtt-dashboard.com","port":"1883","clientid":""},{"id":"35333943.caccc6","type":"websocket-listener","path":"/ws/patient/location","wholemsg":"false"},{"id":"5cd1191e.a32ee8","type":"twilio-api","sid":"ACa7efa1361521eea5bbb3e4d0c38ad7c9","from":"+1 267-415-4623","name":""},{"id":"2f670ec8.d098f2","type":"http in","name":"","url":"/client/:number","method":"get","x":121,"y":214,"z":"bcecc395.43134","wires":[["bbb4fe5c.444b"]]},{"id":"bbb4fe5c.444b","type":"template","name":"PatientView","template":"<!DOCTYPE HTML>\n<html>\n <head>\n <meta charset=\"UTF-8\">\n <title>Patient Helper</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0\">\n\n <link rel=\"stylesheet\" href=\"//ajax.googleapis.com/ajax/libs/jquerymobile/1.4.2/jquery.mobile.min.css\" />\n <script src=\"https://code.jquery.com/jquery-1.7.2.min.js\"></script> \n <script src=\"https://glassproxy.mybluemix.net/javascript/mqttws31.js\"></script>\n <script src=\"https://ajax.googleapis.com/ajax/libs/jquerymobile/1.4.2/jquery.mobile.js \"></script>\n <script>\n var init = function(){\t\t\n\t\tvar server = \"broker.mqtt-dashboard.com\"\n\t\tvar port = 8000;\n\t\tvar client;\n\t\tvar clientId = \"\"+{{req.params.number}};\n\t\tvar topic = \"/patient/phone/\"+clientId+\"/location\";\n\n\t\tvar onConnect = function() { \n\t\t if (navigator.geolocation){\n\t\t navigator.geolocation.getCurrentPosition(onSuccess);\n\t\t }else{alert(\"Støtter ikke geoPos\");}\n\t\t};\n\t\tvar onError = function(error) {\n\t\t\t\talert('code: ' + error.code + '\\n' +\n\t\t\t\t\t 'message: ' + error.message + '\\n');\n\t\t};\t\n\t\tvar\tonConnectionLost = function(responseObject) {\n\t\t if (responseObject.errorCode !== 0)\n\t\t\tconsole.log(\"onConnectionLost:\"+responseObject.errorMessage);\n\t\t\tclient.disconnect();\n\t\t};\n\t\tvar onMessageArrived = function(message) {\n\t\t // We do not receive message, only send\n\t\t};\n\t\tvar onSuccess = function(position){\n\t\t // oppdaterer GUI\n\t\t\tvar now = new Date();\n\t\t\tvar akknow = (now.getHours() + ':' + now.getMinutes());\n\t\t\tvar element = document.getElementById('geolocation');\n\t\t\t\t element.innerHTML = 'Latitude: ' + position.coords.latitude + '<br />' +\n\t\t\t\t\t\t\t\t\t 'Longitude: ' + position.coords.longitude + '<br />' +\n\t\t\t\t\t\t\t\t\t 'Name: '+ $('#uname').val() + '<br />' +\n\t\t\t\t\t\t\t\t\t 'Time:' + now.getHours() + ':' + now.getMinutes() + '<br />' +\n\t\t\t\t\t\t\t\t\t '<hr />' + element.innerHTML;\n\t\t\t\n\t\t\t // Send MQTT message to topic /patient/phone/{{phoneNumber}}/location\n\t\t\t var obj={\"d\": {\"myName\": $('#uname').val(),\"Latitude\": position.coords.latitude,\"Longitude\": position.coords.longitude , \"Time\": akknow}};\t\t\t \n\t\t\t message = new Paho.MQTT.Message(JSON.stringify(obj));\n\t\t\t message.destinationName = topic;\n\t\t\t message.qos = parseInt(\"0\"); \n\t\t\t message.retained = false; \t\t \n\t\t\t client.send(message);\n\t\t\t setTimeout(onConnect, 3000);\n\t\t};\t\t\n\t\t// Make connection to the server.\n\t\tclient = new Paho.MQTT.Client(server, port, \"\", clientId);\n\t\t// Set up a callBacks used when the connection is completed,\n\t\t// when a message arrives for this client and when the connection is lost.\n\t\tclient.onConnectionLost = onConnectionLost;\n\t\tclient.onMessageArrived = onMessageArrived;\n\t\tclient.connect({onSuccess:onConnect, onFailure: function(error) {\n\t\t\tconsole.log(\"Failed to connect to message broker\");\n\t\t}}); \n\t};\n\t</script>\n</head>\n<body>\n\t<div data-role=\"page\" id=\"one\" data-theme=\"a\" class=\"type-interior\">\n\t\t<div data-role=\"header\" data-theme=\"b\">\n\t\t\t<br>\n\t\t\t<h1>Patient Helper</h1>\n\t\t\t<a href=\"index.html\" data-icon=\"home\" data-iconpos=\"top\" data-direction=\"reverse\">Home</a>\n\t\t</div>\n\t\t<div data-role=\"main\" class=\"ui-content\">\n\t\t\t<input type=\"text\" id=\"uname\" data-clear-btn=\"true\" onfocus=\"this.value=''\" value=\"Skriv inn navn:\" />\n\t\t\t<input type=\"submit\" id=\"conn\" value=\"Start Sporing\" onClick=\"init()\" />\n\t\t\t<form id=\"basic\">\n\t\t\t\t<p id=\"geolocation\">venter på lokasjonsdata...</p>\n \t\t\t</form>\n\t\t</div>\n </div> \n</body>\n</html>","x":310,"y":214,"z":"bcecc395.43134","wires":[["186b1c12.e794e4"]]},{"id":"186b1c12.e794e4","type":"http response","name":"","x":504,"y":214,"z":"bcecc395.43134","wires":[]},{"id":"2e488f0f.d1b77","type":"debug","name":"","active":false,"console":"true","complete":"true","x":1601,"y":673,"z":"bcecc395.43134","wires":[]},{"id":"56aaad27.a95554","type":"http in","name":"","url":"/map","method":"get","x":92,"y":166,"z":"bcecc395.43134","wires":[["d409ddd9.2bf62"]]},{"id":"b3f154c.f4c0ea8","type":"http response","name":"","x":502,"y":167,"z":"bcecc395.43134","wires":[]},{"id":"d409ddd9.2bf62","type":"template","name":"OperationsView","template":"<!DOCTYPE html>\n<html>\n<head>\n <title>Ambulance Dispatcher</title>\n <script type=\"text/javascript\" src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js\"></script>\n <script type=\"text/javascript\" src=\"https://maps.google.com/maps/api/js?sensor=true\"></script>\n <script type=\"text/javascript\" src=\"//cdnjs.cloudflare.com/ajax/libs/gmaps.js/0.4.12/gmaps.min.js\"></script>\n \n <style type=\"text/css\" media=\"screen\">\n #map {\n position:absolute;\n top: 0; bottom: 0; left: 0; right: 0;\n }\n </style>\n</head>\n<body>\n \n <div id=\"map\"></div>\n <script type=\"text/javascript\"> \n // Address pointing to the WebSocket that patient GPS coordinates are retrieved from\n var server = window.location.hostname;\n var socketaddy = \"wss://\"+server+\"/ws/patient/location\";\n \n var map;\n var sock;\n \n $(document).ready(function(){\n \n // Create a new map centered on Oslo\n map = new GMaps({\n div: '#map',\n lat: 58.699776,\n lng: 10.546875,\n zoom: 6\n });\n \n \n // Connect to Location websocket\n sock = new WebSocket(socketaddy);\n sock.onopen = function(){ console.log(\"Connected websocket\");\n console.log(\"Sender ping..\");\n sock.send(\"Ping!\");\n console.log(\"Ping sent..\");\n };\n sock.onerror = function(){ console.log(\"Websocket error\"); };\n \n // When GPS coordinates are received\n sock.onmessage = function(evt){\n var latlng = JSON.parse(evt.data);\n console.log(latlng.d.myName);\n console.log(latlng.d.Latitude);\n \n // Remove previous marker\n map.removeMarkers(); \n \n console.log(\"Creating marker at \" + latlng.d.Latitude + \", \" + latlng.d.Longitude);\n \n map.setZoom(18);\n map.setCenter(latlng.d.Latitude, latlng.d.Longitude);\n map.addMarker({\n \tlat: latlng.d.Latitude,\n \tlng: latlng.d.Longitude,\n title: 'Navn: ' + latlng.d.myName + '\\n' + 'Latitude: ' + latlng.d.Latitude + '\\n' + 'Longitude: ' + latlng.d.Longitude + '\\n' + 'Time: ' + latlng.d.Time,\n click: function(e) { \n \tvar alert = confirm(\"Send navigation details to ambulance personel?\");\t\n \tif(alert) {\n \t\t$.post('dispatchAmbulance',{\n \t\t\t\tname: latlng.d.myName,\n \t\t\t\tlat: latlng.d.Latitude,\n \t\t\t\tlng: latlng.d.Longitude\n \t\t\t}, function (){\n \t\t\t\twindow.alert(\"Ambulance has been dispatched\");\n \t\t\t}\n \t\t);\n \t}\n \t}\n });\n }\n });\n </script>\n</body>\n</html>","x":299,"y":167,"z":"bcecc395.43134","wires":[["b3f154c.f4c0ea8"]]},{"id":"d98b1a04.2674e8","type":"twilio out","service":"_ext_","twilio":"5cd1191e.a32ee8","from":"","number":"","name":"SMS","x":501,"y":115,"z":"bcecc395.43134","wires":[]},{"id":"3130686a.cecf98","type":"inject","name":"Send SMS to patient","topic":"+4792040032","payload":"http://olaconnyhelpertalent.mybluemix.net/client/92040032","payloadType":"string","repeat":"","crontab":"","once":false,"x":125,"y":115,"z":"bcecc395.43134","wires":[["d98b1a04.2674e8"]]},{"id":"e2e41556.1d1be8","type":"function","name":"Store patient location","func":"msg.patientLat = msg.payload.lat;\nmsg.patientLng = msg.payload.lng;\nmsg.patientName = msg.payload.name;\nreturn msg;","outputs":"1","x":355,"y":402,"z":"bcecc395.43134","wires":[["df0ce7d0.20f318"]]},{"id":"326a75e7.cd958a","type":"http request","name":"Get patient address","method":"GET","url":"https://maps.googleapis.com/maps/api/geocode/json?latlng={{patientLat}},{{patientLng}}&key=AIzaSyCGBvmim4kx0yem7iKdOghmtMk5XFD49uc","x":1075,"y":577,"z":"bcecc395.43134","wires":[["82fecb54.7d0138"]]},{"id":"8d10678c.72ef98","type":"function","name":"Construct Glass Notification","func":"var ambuLat = msg.ambuLat;\nvar ambuLng = msg.ambuLng;\nvar patientLat = msg.patientLat;\nvar patientLng = msg.patientLng;\nvar addr = \"glass://map?w=240&h=360&marker=0;\" + ambuLat + \",\" + ambuLng + \"&marker=1;\" + patientLat + \",\" + patientLng;\n\n/* Insert payload into Google Glass Timeline\n * https://developers.google.com/glass/v1/reference/timeline/insert\n*/\nmsg.payload = {\n \"notification\": {\n \"level\": \"DEFAULT\"\n },\n \"callbackUrl\": \"https://mirrornotifications.appspot.com/forward?url=http://localhost:8081/reply\",\n \"menuItems\": [{\n \"action\": \"NAVIGATE\"\n }],\n \"html\": \"<article><figure><img src=\\\"\" + addr + \"\\\" height=\\\"360\\\" width=\\\"240\\\"></figure><section><div class=\\\"text-auto-size\\\"><p class=\\\"yellow\\\">Kjappeste vei til</p><p>pasienten \" + msg.patientName + \"</p></div></section></article>\",\n \"location\": {\n \"latitude\": msg.payload.results[0].latitude,\n \"longitude\": msg.payload.results[0].longitude,\n \"displayName\": msg.payload.results[0].formatted_address\n }\n};\n\nreturn [msg, addr]; ","outputs":"1","x":1377,"y":674,"z":"bcecc395.43134","wires":[["8eb2953.f714d68","2e488f0f.d1b77"]]},{"id":"82fecb54.7d0138","type":"json","name":"","x":1212,"y":626,"z":"bcecc395.43134","wires":[["8d10678c.72ef98"]]},{"id":"8eb2953.f714d68","type":"http request","name":"Send notification to ambulance","method":"POST","url":"http://glassproxy.mybluemix.net/timeline/117059099648984892989","x":1594,"y":719,"z":"bcecc395.43134","wires":[["34ee58d7.cb11a8"]]},{"id":"256da1bc.da925e","type":"websocket out","name":"WS Output coords to OperationsView","server":"35333943.caccc6","x":430,"y":269,"z":"bcecc395.43134","wires":[]},{"id":"37499139.c8b66e","type":"debug","name":"","active":true,"console":"false","complete":"true","x":337,"y":312,"z":"bcecc395.43134","wires":[]},{"id":"e9289d00.16d76","type":"http in","name":"","url":"/dispatchAmbulance","method":"post","x":141,"y":355,"z":"bcecc395.43134","wires":[["e2e41556.1d1be8"]]},{"id":"8693c56b.796c38","type":"comment","name":"README","info":"=============== Usage flow ===============\n1. Ambulance Dispatcher opens OperationsView that displays Oslo\n2. Using the Node-RED Inject button: Send SMS to patient. This sends a personalized URL pointing to PatientView to a preregistered (trial account) number in Twilio.\n3. Patient receives SMS and opens URL to PatientView\n4. Patient inputs his/her name and clicks \"Sporing\" which starts to send GPS-coords to OperationsView\n5. Ambulance Dispatcher sees the Patient's location in OperationsView\n6. Ambulance Dispatcher clicks on the Patient's marker in the OperationsView to dispatch an Ambulance to the location\n7. Ambulance Driver receives a Google Glass Timeline Notification with navigation instructions to the Patient\n\n=============== TODOs ====================\n\nChallenge 1:\nThe dispatcher shall be able to input the patient's cellphone number in the OperationsView, \nand send an SMS to the patient containing the PatientView URL.\nHint 1: You might need to register a cellphone number in a Twilio trial account.\nHint 2: You will need to create a new HTTP API for this\n\nChallenge 2:\nThe dispatcher shall be able to input the patient's name in the OperationsView, \nso that the user does not have to input it themselves.\nHint 1: Multiple possible solutions: correlate patient name with MQTT topic name? Embedd patient name in the PatientView URL?\n\nChallenge 3:\nThe patient shall be able to describe their symptoms in the PatientView, and Ambulance drivers shall \nreceive information about these symptoms on Google Glass along with the navigation route to the patient. \nHint 1: When sending cards to Google Glass in \"Send notification to ambulance\"; the HTML may contain multiple <article> tags\n\nChallenge 4:\nThe dispatcher shall be able to view the location of the ambulance in the OperationsView. The position of the ambulance\nshall update every 30 seconds.\nHint 1: The node named \"Get ambulance location\" gets the location of the Ambulance (Google Glass), but this data is not actually\nused by anything. \nHint 2: We do not have a stream of the ambulance location, but need to pull the data via a HTTP request. See if any of the Node-RED\nnodes may help you to create a timed pull\nHint 3: You might want to create a new WebSocket namespace","x":92,"y":67,"z":"bcecc395.43134","wires":[]},{"id":"df0ce7d0.20f318","type":"http request","name":"Get ambulance location","method":"GET","url":"http://glassproxy.mybluemix.net/location/117059099648984892989","x":556,"y":445,"z":"bcecc395.43134","wires":[["650b15f0.9af4ec"]]},{"id":"e3bb944c.1c4468","type":"function","name":"Store ambulance location","func":"msg.ambuLat = msg.payload.latitude;\nmsg.ambuLng = msg.payload.longitude;\nreturn msg;","outputs":"1","x":871,"y":532,"z":"bcecc395.43134","wires":[["326a75e7.cd958a"]]},{"id":"650b15f0.9af4ec","type":"json","name":"","x":710,"y":486,"z":"bcecc395.43134","wires":[["e3bb944c.1c4468"]]},{"id":"34ee58d7.cb11a8","type":"http response","name":"Send response to OperationsView ","x":1920,"y":719,"z":"bcecc395.43134","wires":[]},{"id":"a791c440.586e38","type":"mqtt in","name":"","topic":"/patient/phone/+/location","broker":"b64bf7d2.49b408","x":133,"y":269,"z":"bcecc395.43134","wires":[["37499139.c8b66e","256da1bc.da925e"]]}]