1. Introduction
In this demo, I will show you how to create a Facebook Messenger chat bot for monitoring and controlling home devices using Raspberry/Orange Pi and ESP32/8266. This is not a full solution so you need to improve it by yourself.
In this demo, I will show you how to create a Facebook Messenger chat bot for monitoring and controlling home devices using Raspberry/Orange Pi and ESP32/8266. This is not a full solution so you need to improve it by yourself.
Figure: Facebook Messenger chat bot for monitoring and controlling home devices
There are 2 steps to make this demo:
- How to setup a Facebook chat bot
- How to setup local system (Raspberry/Orange Pi, ESP32/8266)
This is the model of the demo:
Figure: The model of the demo
2. Setup
2.1 Create Facebook page
You can refer to this guideline. And choose type of Page is Business, Brand or Place. In my demo, I created a page named IoT Sharing.
2.2 Setup Facebook chat bot
In order to develop or use Facebook services for Software development you need to register a Facebook developer account here.
After created a FB developer account choose My Apps -> Add a new App -> Fill Display name
Choose Webhooks -> Setup Webhooks
Note: We do not do this step now. This step will be done after running the Raspbbery/Orange Pi software. Because after filled Callback URL, Verify Token and press Verify and Save, FB will send a GET request with "hub.challenge=value of Verify Token" (in this case Verify Token is "iotsharing.com" string) to Pi. Pi need to check the value of hub.challenge must match the value that we filled in Verify Token field (in this case Verify Token is "iotsharing.com" string). And then send this hub.challenge back to FB to finish the verification.
Fill information like below and choose Verify and Save.
1 2 3 4 5 6 | @app.route('/', methods=['GET']) def handle_verification(): if(request.args['hub.challenge'] == 'iotsharing.com'): return request.args['hub.challenge'] else: return 'not match' |
choose the Page that you created in previous step and Subscribe/Unsubscribe.
Finally, extract the ACCESS_TOKEN of the FB app so that our application can authenticate to use FB services.
It is done for Facebook setup step.
2.2 Setup local system (Raspberry/Orange Pi, ESP32/8266)
In this demo, Pi will keep some roles:
- Communicate with Facebook server to receive and respond message.
- Parse Facebook message and then using MQTT protocol to publish the commands to ESP32/8266 clients and subscribe responses from ESP32/8266 clients.
- Refer to this post to setup MQTT for Pi.
- We use Python Paho MQTT for local communication. Refer to this post to install it.
- Besides we need to install some packages (Flask, ngrok) on Raspberry/Orange Pi for our demo.
+ Flask is a Python web framework. In our demo, It is a web server to handle Facebook https request.
+ ngrok secure introspect-able tunnels to local host web hook development tool and debugging tool. This tool helps Facebook server can see our Flask local web server.
From Pi Terminal running the commands:
+ Install Flask Python server: "sudo pip install Flask"
+ Download ngrok: "wget https://bin.equinox.io/a/26q6mq7ddJR/ngrok-2.2.9-linux-arm.zip"
+ Unzip zip file for executable app: "unzip ngrok-2.2.9-linux-arm.zip"
3. Hardware
- 1 ESP32 or ESP8266
- 1 Raspberry Pi or Orange Pi
- 1 LED connect to ESP
- 1 temperature sensor connect to ESP.
In this demo I do not use temperature sensor. I used random(min, max) function to generate temperature.
- Pi send MQTT request topics to ESP:
Temperature topic: "floor1/room1/temp1" to measure temperature
Led topic: "floor1/room1/led1" to set "0" (off) or "1" (on)
Led topic: "floor1/room1/led1" to set "0" (off) or "1" (on)
- ESP send MQTT response topics to Pi:
Temperature response topic: "floor1/room1/temp1/res" with temperature value
Led response topic: "floor1/room1/led1/res" to inform that the request was executed
Led response topic: "floor1/room1/led1/res" to inform that the request was executed
- The template for Facebook message:
"set floor1/room1/led1 on" -> turn on LED and get response
"set floor1/room1/led1 off" -> turn off LED and get response
"get floor1/room1/temp1" -> request temperature measurement and get response
ESP code I reused the post (esp32chatbot.ino)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | #include <WiFi.h> #include <PubSubClient.h> const char* ssid = "dd-wrt"; const char* password = "0000000000"; //ip address of Raspberry/orange pi const char* mqtt_server = "192.168.1.106"; char msg[20]; /* create an instance of PubSubClient client */ WiFiClient espClient; PubSubClient client(espClient); /*LED GPIO pin*/ const char led = 4; /* topics */ #define TEMP_TOPIC "floor1/room1/temp1" #define LED_TOPIC "floor1/room1/led1" /* on, off */ void receivedCallback(char* topic, byte* payload, unsigned int length) { Serial.print("topic: "); Serial.println(topic); if(strcmp(topic, LED_TOPIC) == 0){ Serial.print("payload: "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); /* we got '1' -> on */ if ((char)payload[0] == '1') { digitalWrite(led, HIGH); snprintf (msg, 20, "%s", "on"); /* publish the response */ client.publish(LED_TOPIC "/res", msg); } else { /* we got '0' -> on */ digitalWrite(led, LOW); snprintf (msg, 20, "%s", "off"); client.publish(LED_TOPIC "/res", msg); } }else { snprintf (msg, 20, "%d", random(0, 40)); client.publish(TEMP_TOPIC "/res", msg); } } void mqttconnect() { /* Loop until reconnected */ while (!client.connected()) { Serial.print("MQTT connecting ..."); /* client ID */ String clientId = "ESP32Client"; /* connect now */ if (client.connect(clientId.c_str())) { Serial.println("connected"); /* subscribe topic */ client.subscribe(LED_TOPIC); client.subscribe(TEMP_TOPIC); } else { Serial.print("failed, status code ="); Serial.print(client.state()); Serial.println("try again in 5 seconds"); /* Wait 5 seconds before retrying */ delay(5000); } } } void setup() { Serial.begin(115200); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } /* set led as output to control led on-off */ pinMode(led, OUTPUT); Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); /* configure the MQTT server with IPaddress and port */ client.setServer(mqtt_server, 1883); /* this receivedCallback function will be invoked when client received subscribed topic */ client.setCallback(receivedCallback); } void loop() { /* if client was disconnected then try to reconnect again */ if (!client.connected()) { mqttconnect(); } /* this function will listen for incomming subscribed topic-process-invoke receivedCallback */ client.loop(); } |
Pi code (chatbot.py):
We use variable history to hold the id of Facebook messenger sender while waiting for the response from ESP. This sender id is used in reply() function to send response back to Facebook messenger sender.
5. Steps to deploy
- MQTT broker run on Pi
- Open 2 Terminal on Pi:
+ Run "python chatbot.py" with Flask in it.
+ Run ngrok (5000 is the port Flask listen on): "./ngrok http 5000"
Copy the url in red box to Callback URL field that mention in step 2.2 Setup Facebook chat bot
Note: in case we shutdown ngrok and run it again the new url will be generated. We have to re-register this url to Facebook.
Choose Webhooks -> Edit Subscription
And then Unsubcribe and Subscribe the page again:
Now go to the Page that we created, choose About and Send Message
And type one of commands:
"set floor1/room1/led1 on"
"set floor1/room1/led1 off"
"get floor1/room1/temp1"
6. Result
We use variable history to hold the id of Facebook messenger sender while waiting for the response from ESP. This sender id is used in reply() function to send response back to Facebook messenger sender.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | from flask import Flask, request import requests import paho.mqtt.publish as publish import paho.mqtt.client as mqtt import thread ACCESS_TOKEN = "your_fb_access token_here"; #hold sender id history = dict() set_cmd = 'floor1/room1/led1' get_cmd = 'floor1/room1/temp1' #respond to FB messenger def reply(user_id, msg): data = { "recipient": {"id": user_id}, "message": {"text": msg} } resp = requests.post("https://graph.facebook.com/v2.6/me/messages?access_token=" + ACCESS_TOKEN, json=data) print(resp.content) #MQTT handler def on_connect(mqttc, obj, flags, rc): print("rc: "+str(rc)) def on_message(mqttc, obj, msg): print(msg.topic+": "+str(msg.payload)) if msg.topic in history: user_id = history[msg.topic] #reply FB messenger reply(user_id, msg.payload) history.pop(msg.topic, None) mqttc = mqtt.Client() mqttc.on_connect = on_connect mqttc.on_message = on_message mqttc.connect("localhost", 1883, 60) mqttc.subscribe("floor1/#", 0) #MQTT subscribe thread def mqtt_thread( threadName, delay): mqttc.loop_forever() try: thread.start_new_thread( mqtt_thread, ("mqtt-thread", 0, ) ) except: print "Error: unable to start thread" #Flask web server instance app = Flask(__name__) #handle GET request from Facebook @app.route('/', methods=['GET']) def handle_verification(): if(request.args['hub.challenge'] == 'iotsharing.com'): return request.args['hub.challenge'] else: return 'not matched' #handle POST request from Facebook @app.route('/', methods=['POST']) def handle_incoming_messages(): data = request.json print(data) sender = data['entry'][0]['messaging'][0]['sender']['id'] message = data['entry'][0]['messaging'][0]['message']['text'] print(message) if(message.startswith('set')): arr = message.split() l = len(arr) if(l == 3 and set_cmd == arr[1]): cmd = arr[1] val = '1' if arr[2]=='on' else '0' publish.single(cmd, val, hostname="localhost") #record command with sender id history[cmd+'/res'] = sender return 'ok' elif(message.startswith('get')): arr = message.split() l = len(arr) if(l == 2 and get_cmd == arr[1]): cmd = arr[1] publish.single(cmd, '', hostname="localhost") #record command with sender id history[cmd+'/res'] = sender return 'ok' reply(sender, 'invalid query') return "ok" if __name__ == '__main__': app.run(debug=True) |
- MQTT broker run on Pi
- Open 2 Terminal on Pi:
+ Run "python chatbot.py" with Flask in it.
+ Run ngrok (5000 is the port Flask listen on): "./ngrok http 5000"
Copy the url in red box to Callback URL field that mention in step 2.2 Setup Facebook chat bot
Note: in case we shutdown ngrok and run it again the new url will be generated. We have to re-register this url to Facebook.
Choose Webhooks -> Edit Subscription
And then Unsubcribe and Subscribe the page again:
Now go to the Page that we created, choose About and Send Message
And type one of commands:
"set floor1/room1/led1 on"
"set floor1/room1/led1 off"
"get floor1/room1/temp1"
6. Result
4 Comments
Final Year Projects in Python
Python Training in Chennai
FInal Year Project Centers in Chennai
Python Training in Chennai