Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
2 lines (1 sloc) 11.1 KB
[{"id":"e6be2839.1941d8","type":"mqtt-broker","broker":"m20.cloudmqtt.com","port":"15508","clientid":""},{"id":"68f917d6.f6285","type":"subflow","name":"take photo","in":[{"x":39,"y":148,"wires":[{"id":"f3176fef.b669b"}]}],"out":[{"x":598,"y":135,"wires":[{"id":"60d90b87.234904","port":0}]}]},{"id":"5bd0acbe.1a2234","type":"comment","name":"Use an external command-line tool to capture a photograph","info":"This subflow attempts to use an external command-line tool to capture a\nphotograph of the beacon and store it as a `Buffer` object in the `msg.media`\nproperty.\n","x":231,"y":71,"z":"68f917d6.f6285","wires":[]},{"id":"60d90b87.234904","type":"function","name":"set media property","func":"// The command was successful if and only if the type of the message payload\n// is a `Buffer` instance.\nif (msg.payload instanceof Buffer) {\n msg.media = msg.payload;\n msg.payload = null;\n} else {\n node.error(\"Could not capture photograph\", msg);\n}\n\n// Return the message for processing.\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":135,"z":"68f917d6.f6285","wires":[[]]},{"id":"f3176fef.b669b","type":"exec","command":"raspistill --output - --width 1280 --height 1024 --encoding jpg","addpay":false,"append":"","useSpawn":"","name":"execute raspistill command","x":212,"y":148,"z":"68f917d6.f6285","wires":[["60d90b87.234904"],[],[]]},{"id":"91fe65c2.1a0cd8","type":"comment","name":"Load colour definitions resource","info":"This path loads the colour definition file, which contains\nall of the HTML5 and CSS3 colours along with their RGB\ncolour codes into the global context. At the end of this\nflow two variables are created in the global context:\n\n* `context.global.colour` is a map from a colour name to\n a three-byte long encoding of the RGB value.\n* `context.global.colour_name` is a list of colour names\n sorted in descending length order.\n\nThese variables are used when attempting to find colour\nnames in incoming messages.","x":145,"y":36,"z":"aed4755.340c188","wires":[]},{"id":"4f76383e.ab1d38","type":"inject","name":"","topic":"","payload":"resources/messages.json","payloadType":"none","repeat":"","crontab":"","once":true,"x":94,"y":252,"z":"aed4755.340c188","wires":[["95cb569c.8cf1b"]]},{"id":"c35a473a.7230e8","type":"inject","name":"","topic":"","payload":"resources/response.json","payloadType":"none","repeat":"","crontab":"","once":true,"x":94,"y":201,"z":"aed4755.340c188","wires":[["5f5254f4.893524"]]},{"id":"f4277dff.ce2e","type":"json","name":"","x":433,"y":201,"z":"aed4755.340c188","wires":[["b70af20d.1f8998"]]},{"id":"a6ba1ecd.dc8628","type":"json","name":"","x":435,"y":252,"z":"aed4755.340c188","wires":[["19b2d335.7939fd"]]},{"id":"a2b67a2d.924f98","type":"comment","name":"Load response and message resources","info":"These two paths load the simple response and message\nresources into the global context. At the end of these\npaths two variables are created in the global context:\n\n* `context.global.response` a list of all response templates.\n* `context.global.message` a list of all message templates.\n\nThese variables are used when deciding which messages to\npost either periodically or in response to an incoming\nmessage.","x":169,"y":152,"z":"aed4755.340c188","wires":[]},{"id":"b70af20d.1f8998","type":"function","name":"store responses","func":"// Store the responses.\ncontext.global.response = msg.payload\n\n// Update the message payload for debugging.\nmsg.payload = \"Loaded \" + context.global.response.length + \" responses.\";\n\n// Forward the message for processing.\nreturn msg;","outputs":1,"noerr":0,"x":602,"y":201,"z":"aed4755.340c188","wires":[["eaff1af3.ffc388"]]},{"id":"19b2d335.7939fd","type":"function","name":"store messages","func":"// Store the responses.\ncontext.global.message = msg.payload\n\n// Update the message payload for debugging.\nmsg.payload = \"Loaded \" + context.global.message.length + \" messages.\";\n\n// Forward the message for processing.\nreturn msg;","outputs":1,"noerr":0,"x":603,"y":252,"z":"aed4755.340c188","wires":[["eaff1af3.ffc388"]]},{"id":"24465247.3bc126","type":"json","name":"","x":422,"y":84,"z":"aed4755.340c188","wires":[["160239db.031c1e"]]},{"id":"160239db.031c1e","type":"function","name":"convert colours","func":"// Update the value of every colour in the dictionary.\nfor (var key in msg.payload) {\n // Filter for only those keys that are not prototype properties.\n if (msg.payload.hasOwnProperty(key)) {\n msg.payload[key] = new Buffer(msg.payload[key]);\n }\n}\n\n// Continue processing the message.\nreturn msg;","outputs":1,"noerr":0,"x":585,"y":84,"z":"aed4755.340c188","wires":[["b593c6fb.5208d"]]},{"id":"b593c6fb.5208d","type":"function","name":"store names and colours","func":"// Store the colour dictionary in the global context.\ncontext.global.colour = msg.payload;\n\n// Store and sort the colour names in the global context.\ncontext.global.colour_name = Object.keys(context.global.colour);\ncontext.global.colour_name.sort(\n function (p, q) {\n p.length > q.length;\n } \n);\n\n// Update the message payload for debugging.\nvar count = context.global.colour_name.length;\nmsg.payload = \"Loaded \" + count + \" colour definitions from file.\";\n\n// Forward the message for processing.\nreturn msg;\n","outputs":1,"noerr":0,"x":802,"y":84,"z":"aed4755.340c188","wires":[["fdc4ed56.21f268"]]},{"id":"9435ccd7.52a98","type":"inject","name":"","topic":"","payload":"resources/colours.json","payloadType":"none","repeat":"","crontab":"","once":true,"x":93,"y":84,"z":"aed4755.340c188","wires":[["aaa9d5b.b67c9a8"]]},{"id":"aaa9d5b.b67c9a8","type":"http request","name":"fetch colours file","method":"GET","ret":"txt","url":"http://rawgit.com/brett-lempereur/beaconbot/master/resources/colours.json","x":258,"y":84,"z":"aed4755.340c188","wires":[["24465247.3bc126"]]},{"id":"5f5254f4.893524","type":"http request","name":"fetch response file","method":"GET","ret":"txt","url":"http://rawgit.com/brett-lempereur/beaconbot/master/resources/response.json","x":264,"y":201,"z":"aed4755.340c188","wires":[["f4277dff.ce2e"]]},{"id":"95cb569c.8cf1b","type":"http request","name":"fetch message file","method":"GET","ret":"txt","url":"http://rawgit.com/brett-lempereur/beaconbot/master/resources/message.json","x":262,"y":252,"z":"aed4755.340c188","wires":[["a6ba1ecd.dc8628"]]},{"id":"79d7ac9e.ebfe3c","type":"comment","name":"Periodically post updates","info":"This path is responsible for periodically posting an image\nof the beacon to Twitter along with a randomly selected\nmessage.","x":122,"y":320,"z":"aed4755.340c188","wires":[]},{"id":"89672180.e5c14","type":"inject","name":"every twenty minutes","topic":"","payload":"","payloadType":"none","repeat":"1200","crontab":"","once":false,"x":135,"y":368,"z":"aed4755.340c188","wires":[["5941e881.48e3f"]]},{"id":"fdc4ed56.21f268","type":"debug","name":"","active":true,"console":"true","complete":"payload","x":1010,"y":84,"z":"aed4755.340c188","wires":[]},{"id":"eaff1af3.ffc388","type":"debug","name":"","active":true,"console":"true","complete":"payload","x":801,"y":222,"z":"aed4755.340c188","wires":[]},{"id":"a61c2d14.62733","type":"function","name":"select random message","func":"// Select a random message template from the global context.\nvar index = Math.floor(Math.random() * context.global.message.length);\n\n// Store the message as the payload.\nmsg.payload = context.global.message[index];\n\n// Return the message for further processing.\nreturn msg;\n","outputs":1,"noerr":0,"x":517,"y":368,"z":"aed4755.340c188","wires":[["1f2c4155.8f8467"]]},{"id":"1f2c4155.8f8467","type":"twitter out","twitter":"","name":"Tweet","x":706,"y":368,"z":"aed4755.340c188","wires":[]},{"id":"5941e881.48e3f","type":"subflow:68f917d6.f6285","x":318,"y":368,"z":"aed4755.340c188","wires":[["a61c2d14.62733"]]},{"id":"dc5c58e2.f8ad18","type":"comment","name":"Respond to mentions","info":"This path is responsible for responding to mentions on Twitter\nby:\n\n1. Attempting to find a colour name in the mention.\n2. Updating the colour of the beacon to the corresponding value.\n3. Taking a picture of the beacon in its new colour.\n4. Selecting a random response.\n5. Tweeting the picture in response to the mention.\n\nIf no colour name is found in the mention, no action will be\ntaken.","x":110,"y":429,"z":"aed4755.340c188","wires":[]},{"id":"1cc1694f.e0a7f7","type":"twitter in","twitter":"","tags":"@doestower","user":"false","name":"","topic":"tweets","x":81,"y":479,"z":"aed4755.340c188","wires":[["8378df19.4fa408"]]},{"id":"41df2930.162158","type":"function","name":"find colour","func":"// Normalise the message.\nvar nm = msg.tweet.text.toLowerCase();\n\n// Begin by indicating that there is no colour.\nmsg.colour = null;\n\n// Try to find the first (i.e. most precise) matching colour in the global\n// colour name list.\nfor (var i in context.global.colour_name) {\n var cn = context.global.colour_name[i];\n if (nm.indexOf(cn) >= 0) {\n msg.colour = context.global.colour[cn];\n break;\n }\n}\n\n// Return the message for further processing.\nreturn msg;\n","outputs":1,"noerr":0,"x":409,"y":479,"z":"aed4755.340c188","wires":[["c9c0bd63.8087"]]},{"id":"c9c0bd63.8087","type":"switch","name":"only messages with a colour","property":"colour","rules":[{"t":"nnull"}],"checkall":"true","outputs":1,"x":615,"y":479,"z":"aed4755.340c188","wires":[["5db5298b.766048","3b099274.d6c47e"]]},{"id":"6b0413b1.7de994","type":"mqtt out","name":"","topic":"beacon/colour","qos":"0","retain":"","broker":"e6be2839.1941d8","x":1057,"y":500,"z":"aed4755.340c188","wires":[]},{"id":"5db5298b.766048","type":"function","name":"set payload to colour","func":"// Store the colour as the message payload.\nmsg.payload = msg.colour;\n\n// Return the message for further processing.\nreturn msg;","outputs":1,"noerr":0,"x":859,"y":500,"z":"aed4755.340c188","wires":[["6b0413b1.7de994"]]},{"id":"3b099274.d6c47e","type":"delay","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":822,"y":455,"z":"aed4755.340c188","wires":[["f58b4b9d.b870c"]]},{"id":"f58b4b9d.b870c","type":"subflow:68f917d6.f6285","x":971,"y":455,"z":"aed4755.340c188","wires":[["efc3fac7.8f1f3"]]},{"id":"efc3fac7.8f1f3","type":"function","name":"generate random response","func":"// Select a random response template from the global context.\nvar index = Math.floor(Math.random() * context.global.response.length);\nvar response = context.global.response[index];\n\n// Replace template parameters in the message.\nresponse = response.replace(\"$screen_name\", msg.tweet.user.screen_name);\n\n// Store the message as the payload.\nmsg.payload = response;\n\n// Return the message for further processing.\nreturn msg;\n","outputs":1,"noerr":0,"x":1177,"y":455,"z":"aed4755.340c188","wires":[["496fe4b3.468024"]]},{"id":"496fe4b3.468024","type":"twitter out","twitter":"","name":"Tweet","x":1375,"y":455,"z":"aed4755.340c188","wires":[]},{"id":"8378df19.4fa408","type":"switch","name":"ignore ourself","property":"tweet.user.screen_name","rules":[{"t":"neq","v":"\"doestower\""}],"checkall":"true","outputs":1,"x":247,"y":479,"z":"aed4755.340c188","wires":[["41df2930.162158"]]}]