A while back I posted about using Twilio and Node-Red to send/receive SMS messages. I was fiddling around with some older project stuff (uncompleted) earlier today and bounced into the IVR setup I had. Wondering if it was working I called it, and no it wasn’t. So I had to fix it. It took me a minute to come across all the related pages needed to get it working again so I decided to compile them here.
What is an IVR?
Well if you Google IVR you get: Interactive voice response (IVR) is a technology that allows a computer to interact with humans through the use of voice and DTMF tones input via keypad.
And that basically sums it up. It allows you the person, to call a computer and have the computer know what you want when pressing 1, or 5. Similar to a phone switching system but they are usually used to report some kind of information instead of route calls. IVRs basically cut out someones job once upon a time.
A better example is of a field technician calling an IVR system to read back what signals were received on the clients security system he just tested.
What we are doing here?
Were are going to get a basic IVR running on our Node-Red server to interact with and read back data or to activate/deactivate things over MQTT. If you would rather (and/or) use SMS to achieve kinda the same thing read here.
Prerequisites
- A server of some kind running Node-Red.
- Twilio node.
- That NR install to be behind a reverse proxy (your biggest hurdle).
- A Twilio account, and number with voice capabilities.
The Flow!
Here is the glorious flow!
1 |
[{"id":"4868a284.66517c","type":"http response","z":"feaafa48.a34f88","name":"Send TwiML","x":870,"y":200,"wires":[]},{"id":"1444c0f8.9e1bff","type":"http in","z":"feaafa48.a34f88","name":"Incomming Twilio Call","url":"/twiliovoice","method":"post","upload":false,"swaggerDoc":"","x":316,"y":202,"wires":[["8cebf57a.769bc8","a77ee63.fbb7618"]]},{"id":"8cebf57a.769bc8","type":"function","z":"feaafa48.a34f88","name":"Process Call","func":"var twiml_response = \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?> \\\n <Response> \\\n <Gather action=\\\"https://yourserver.com/twilioivr\\\" numDigits=\\\"1\\\"> \\\n <Say voice=\\\"woman\\\">Welcome to Node-Red. For power usage press 1. To ring the bell press 2. For anything else press 3</Say> \\\n </Gather> \\\n <Say voice=\\\"woman\\\">Sorry, I didn't get your response.</Say> \\\n </Response>\";\nmsg.payload = twiml_response;\nreturn msg;","outputs":1,"noerr":0,"x":630,"y":200,"wires":[["4868a284.66517c","daf3c74e.9d90e8"]]},{"id":"2e446272.06064e","type":"http in","z":"feaafa48.a34f88","name":"IVR Data Call","url":"/twilioivr","method":"post","upload":false,"swaggerDoc":"","x":290,"y":280,"wires":[["f769d46d.3e7fc8","a306c4e8.68fd58"]]},{"id":"daf3c74e.9d90e8","type":"debug","z":"feaafa48.a34f88","name":"","active":true,"complete":false,"x":870,"y":280,"wires":[]},{"id":"f769d46d.3e7fc8","type":"debug","z":"feaafa48.a34f88","name":"","active":true,"complete":false,"x":630,"y":320,"wires":[]},{"id":"a77ee63.fbb7618","type":"debug","z":"feaafa48.a34f88","name":"","active":false,"console":false,"complete":"payload","x":630,"y":160,"wires":[]},{"id":"a306c4e8.68fd58","type":"function","z":"feaafa48.a34f88","name":"handleGather","func":"// Use 2 outputs, 2nd is for mqtt topic/payload combination\n// Could be useful to post other caller info to a topic\nvar mqttOut = null;\nvar responseMsg = \"\";\n\nvar name = \"wholehouse\";\nvar reading = context.global[name];\nvar digit = msg.payload.Digits;\nif( digit == \"1\" ) {\n var twiml_response = \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?> \\\n <Response> \\\n <Say voice=\\\"woman\\\">Power usage is \" + reading + \"</Say> \\\n </Response>\";\n msg.payload = twiml_response;\n} else if( digit == \"2\" ) {\n\tmqttOut = {topic: \"bellduino/ring\", payload: \"ringmybell\" };\n var twiml_response = \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?> \\\n <Response> \\\n <Say voice=\\\"woman\\\">Turing on the bell</Say> \\\n </Response>\";\n msg.payload = twiml_response;\n} else {\n\tresponseMsg = \"You pressed \" + digit;\n}\n\nreturn [msg, mqttOut];","outputs":"2","noerr":0,"x":640,"y":280,"wires":[["4868a284.66517c","daf3c74e.9d90e8"],["a023a81c.a3e318","442a4b04.0c3c64"]]},{"id":"413a0cf4.24b0e4","type":"globalGetSet","z":"feaafa48.a34f88","name":"Text Global","topic":"","context":"msg","variable":"payload","outContext":"global","outVar":"wholehouse","x":490,"y":380,"wires":[[]]},{"id":"390ea068.1c8f8","type":"inject","z":"feaafa48.a34f88","name":"","topic":"","payload":"42.1","payloadType":"num","repeat":"","crontab":"","once":true,"x":290,"y":380,"wires":[["413a0cf4.24b0e4"]]},{"id":"a023a81c.a3e318","type":"mqtt out","z":"feaafa48.a34f88","name":"","topic":"","qos":"","retain":"","broker":"bdbaaa3f.072c48","x":850,"y":400,"wires":[]},{"id":"442a4b04.0c3c64","type":"debug","z":"feaafa48.a34f88","name":"","active":true,"console":"false","complete":"true","x":850,"y":360,"wires":[]},{"id":"bdbaaa3f.072c48","type":"mqtt-broker","z":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""}] |
You will need to create a global and have its value set so the IVR can read it back (in this example).
Drop a line in the comments if you have a question.
What helped:
https://flows.nodered.org/node/node-red-node-twilio
old outdated flow https://flows.nodered.org/flow/637b5f6128a8d423503f
https://groups.google.com/d/topic/node-red/yAEx5k2UHJw/discussion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[{"id":"4868a284.66517c","type":"http response","z":"feaafa48.a34f88","name":"Send TwiML","x":870,"y":200,"wires":[]},{"id":"1444c0f8.9e1bff","type":"http in","z":"feaafa48.a34f88","name":"Incomming Twilio Call","url":"/twiliovoice","method":"post","upload":false,"swaggerDoc":"","x":316,"y":202,"wires":[["8cebf57a.769bc8","a77ee63.fbb7618"]]},{"id":"8cebf57a.769bc8","type":"function","z":"feaafa48.a34f88","name":"Process Call","func":"var twiml_response = \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?> \\\n <Response> \\\n <Gather action=\\\"https://yourserver.com/twilioivr\\\" numDigits=\\\"1\\\"> \\\n <Say voice=\\\"woman\\\">Welcome to Node-Red. For power usage press 1. To ring the bell press 2. For anything else press 3</Say> \\\n </Gather> \\\n <Say voice=\\\"woman\\\">Sorry, I didn't get your response.</Say> \\\n </Response>\";\nmsg.payload = twiml_response;\nreturn msg;","outputs":1,"noerr":0,"x":630,"y":200,"wires":[["4868a284.66517c","daf3c74e.9d90e8"]]},{"id":"2e446272.06064e","type":"http in","z":"feaafa48.a34f88","name":"IVR Data Call","url":"/twilioivr","method":"post","upload":false,"swaggerDoc":"","x":290,"y":280,"wires":[["f769d46d.3e7fc8","a306c4e8.68fd58"]]},{"id":"daf3c74e.9d90e8","type":"debug","z":"feaafa48.a34f88","name":"","active":true,"complete":false,"x":870,"y":280,"wires":[]},{"id":"f769d46d.3e7fc8","type":"debug","z":"feaafa48.a34f88","name":"","active":true,"complete":false,"x":630,"y":320,"wires":[]},{"id":"a77ee63.fbb7618","type":"debug","z":"feaafa48.a34f88","name":"","active":false,"console":false,"complete":"payload","x":630,"y":160,"wires":[]},{"id":"a306c4e8.68fd58","type":"function","z":"feaafa48.a34f88","name":"handleGather","func":"// Use 2 outputs, 2nd is for mqtt topic/payload combination\n// Could be useful to post other caller info to a topic\nvar mqttOut = null;\nvar responseMsg = \"\";\n\nvar name = \"wholehouse\";\nvar reading = context.global[name];\nvar digit = msg.payload.Digits;\nif( digit == \"1\" ) {\n var twiml_response = \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?> \\\n <Response> \\\n <Say voice=\\\"woman\\\">Power usage is \" + reading + \"</Say> \\\n </Response>\";\n msg.payload = twiml_response;\n} else if( digit == \"2\" ) {\n\tmqttOut = {topic: \"bellduino/ring\", payload: \"ringmybell\" };\n var twiml_response = \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\" standalone=\\\"yes\\\"?> \\\n <Response> \\\n <Say voice=\\\"woman\\\">Turing on the bell</Say> \\\n </Response>\";\n msg.payload = twiml_response;\n} else {\n\tresponseMsg = \"You pressed \" + digit;\n}\n\nreturn [msg, mqttOut];","outputs":"2","noerr":0,"x":640,"y":280,"wires":[["4868a284.66517c","daf3c74e.9d90e8"],["a023a81c.a3e318","442a4b04.0c3c64"]]},{"id":"413a0cf4.24b0e4","type":"globalGetSet","z":"feaafa48.a34f88","name":"Text Global","topic":"","context":"msg","variable":"payload","outContext":"global","outVar":"wholehouse","x":490,"y":380,"wires":[[]]},{"id":"390ea068.1c8f8","type":"inject","z":"feaafa48.a34f88","name":"","topic":"","payload":"42.1","payloadType":"num","repeat":"","crontab":"","once":true,"x":290,"y":380,"wires":[["413a0cf4.24b0e4"]]},{"id":"a023a81c.a3e318","type":"mqtt out","z":"feaafa48.a34f88","name":"","topic":"","qos":"","retain":"","broker":"bdbaaa3f.072c48","x":850,"y":400,"wires":[]},{"id":"442a4b04.0c3c64","type":"debug","z":"feaafa48.a34f88","name":"","active":true,"console":"false","complete":"true","x":850,"y":360,"wires":[]},{"id":"bdbaaa3f.072c48","type":"mqtt-broker","z":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""}] |
SEND IT.
Discover more from Its_All.Lost
Subscribe to get the latest posts sent to your email.