This is step number eight of the final project.
What we're going to do now is to so when we receive here a notification that someone is ringing the
bell.
We're going to handle the open command so we can open the door.
So we're going to open the door for 10s and then close it and come back to the initial state where the
user can ask another request.
Okay, so the first thing we need to do is to initialize the telegram updater.
So that's what I'm going to do now and I'm going to create a new file here for the step number eight.
Let's copy this inside the step number eight.
Let's close and let's save as.
Intercom.
Step.
Eight.
All right, Now let's start with the initialization of the updater.
So from telegram dot XT import.
Of data and also comment.
And we are going to initialize the data here when we initialize the telegram bot.
So we have bot here, I'm going to do a data is equal to a data.
Token is equal to telegram token.
So the same token and then let's create a dispatcher for our commands.
Dispatcher is equal to a data dot.
Dispatcher.
Then we are going to add handlers for the dispatcher.
So let's put to do add handlers that I'm just going to do after the initialization.
And then we need to do updater dot start polling.
So we need to start getting the updates from the Telegram chat and where we are going to do that.
Well, not just right now.
We are going to do that after the Time.sleep So here we do.
Um, actually, after we reset the input buffer, a data dot starts falling.
Okay.
Why do we do that after the time slip?
Because.
Well, we keep this time actually for the communication to be correctly initialized.
So if you start polling before the communication is correctly initialized and in some of the callbacks,
we're going to send some messages to the Arduino.
Well, you may have some problems at this time.
So we wait after the three seconds to start getting the telegram comments in our code.
And if I do start polling, also need to do stop.
So I'm going to do here print.
So we already have the structure.
Okay.
Nothing more to do.
The while loop with the try except so print.
Stopping telegram a.
Wait a few seconds and let's do a data dot stop.
And then when we have end of program, we know everything is correctly finished.
Okay, now let's add handlers.
And so to add handlers, we will need some callbacks.
I'm just going to create the callbacks on top of the telegram initialization here.
Let's put telegram callbacks here and def.
Let's create first a start handler with update context and let's say that we want to just greet the
user that uses the Start command.
So what we can do is to to send a is equal to, let's say, welcome
plus and how to get the user first name.
Well, that's something I'm going to show you here.
You can do update for example, update dot effective user dot first name.
Let's add an exclamation mark because we are very happy to send this message.
And let's do context.
Dot, dot, dot, send message with chat ID is equal to let's directly reply to update dot effective
chatted.
So as you can see we can get many information in a callback from the user, the chat, the message,
everything and text is equal to string to send.
All right.
And let's add an open door handler, which is going to be more interesting here.
Date context.
Let's put pass for now and we're going to implement that.
But first I'm going to add the handlers here.
So Dispatcher Dot add handler, command handler with start keyword and start handler function and Dispatcher
Dot add handler Command handler with open keyword.
Okay.
If you remember here.
So in the protocol we have defined, we want to send open and we also here send a message to ask to
send open or deny.
So let's use open and this is going to be open door.
Handler Okay, Let's actually start this just to check that the operator is working.
So waiting for three seconds.
Okay?
And let's go to Telegram.
Let's write start.
And you can see.
Welcome, Édouard.
Well, that's me.
And let's kill that Ctrl C.
You can see.
Wait a few seconds.
And then we should have.
End of program.
Okay.
So just be patient here.
And you can see with the three dashes here, it's very easy to see the end of the logs.
Okay, now let's write our open door handler.
So what do we want to do here?
First we want to.
So now we know that we need to open the door.
So we're going to send the command to the Arduino to open the door.
So with the servo motor to print the text that the door is opened to play a sound with the buzzer and
to change the Led to green.
Okay, so for actions we need to send to the Arduino.
We are also going to send the confirmation to Telegram so we can know in the chat that the door has
been opened and then we will wait for 10s.
And after 10s have passed, we are going to close the door.
So let's start.
I'm going to put print opening the door so we know in the log that this is happening and then we do
send.
So let's write the command to the Arduino, send to Arduino open door and then another send to Arduino.
So let's write actually four of them.
So we want to open the door.
We also want to print text and to say that the door is opened.
So that the user can go.
We also want to play.
Let's use 300 heads.
Okay, So the higher the heads, basically, the higher the tone.
And well, usually when you have a higher tone, a higher frequency, this is more welcoming.
Okay?
When you have a sound for a door.
So we're going to put 300 and play that for five.
So let's not put a space here 500 milliseconds and then we can do set led right is going to be zero
and then green, 255 and then blue 000.
Okay.
And with this, we open the door, but then we need a mechanism that is going to close the door after
10s.
All right.
Because the door is not going to close by itself.
And so we can do time.
Dot sleep ten.
Okay.
Don't worry about this time.
That sleep.
I'm going to explain to you just in a bit why use this here and how it's not going to be a problem.
And so after 10s we can do so print closing the door and we can send commands to the Arduino and we'll
just actually, after we have sent command to the Arduino here, we can also do bot dot send message
to the chat.
So chat ID is equal to update dot effective chat.id because we are in a callback.
We have the update with the chat id and text is equal to opening the door.
So we also have a confirmation on the telegram that our command was successfully processed.
Okay.
So then we wait for 10s and we close the door.
So to close the door we send to Arduino.
We're going to send also four commands.
Okay.
So we're going to send.
Close the door and then print text.
Let's go back to normal.
Push on.
Button to call.
We're going to play also.
Buzzer okay.
To inform that the door is actually closing.
Let's say 200.
So a lower pitch for also 500 milliseconds and then set back to blue.
So 000000 255.
Okay.
So as you can see, if you want to send comments to the Arduino, well, now that's very easy.
You just do send to Arduino with the correct command and parameters and everything is going to be taken
care of because you have written the code before to do that.
Okay.
And now if you remember, we still have a flag that we have set here, open door request.
So what we want to do is we want to say that at the end open door request is equal to false so we can
send a request.
And then when we open the door, so we send the message from Telegram to the Raspberry Pi.
This is going to open the door.
And then after 10s close the door and then the open door request is no false.
So we can send another request with another photo to telegram.
Okay.
And well, if we want actually to use the open door request boolean, which is a global variable, we
need to do global open door request here because we are inside a function.
So if you are inside a function in Python and you want to access a global variable to modify it, you
need to use global open door request inside the function.
Otherwise, well, you're just going to create a new variable open door request which is not going to
be the global one.
And one additional thing I'm going to do if open door request
and put that inside the if.
Why is that?
Because.
Well, let's open the three one.
A chat.
Thing is that if you send slash open command, so now the code is not running, so that's not going
to work.
But anytime you send open, that's going to go inside the open door.
Handler Right.
Like anytime you send start, it's going to say welcome.
So every time you send open, it's going to go here.
And so if you send open, it's going to open the door.
But what we want in this application is that you only open the door when you have a request.
So we check that what we have a request.
If we have a request, we open the door and then we close it.
And then we put the open door request to false.
So of course this kind of decision is depending on your real application.
Maybe you want to open the door at any time and then that's fine.
You just don't put that.
If here, here, just put it because well, I've decided in the application to do that.
But this will depend on what you want to really do.
Of course.
And one other thing I'm going to add here, because if you just run like this, you may have some weird
behaviors, for example, that if you send a request and then from telegram, you press, you send multiple
times open, well, what you will see is that this is first going to be executed and then it's going
to be executed again.
Why is that?
Because.
Well, how is the updater working basically with the dispatcher?
When you receive a keyword, it's going to directly call the callback function in a different thread.
Okay.
So that's why, for example, the time sleep is not a problem for the main thread because that's going
to be on a different thread.
Okay.
So now we are going to talk about Multithreading.
It's a bit more complex, but I'm going to keep things simple here so you can follow.
So you have the main thread here in the while loop, and when you receive a command in a different thread,
you're going to execute the callback.
But if you receive multiple comments, all the callbacks are going to be executed one by one in these
different threads.
So if you receive multiple open door handler comments, it's going to be executed once and then another
time, another time.
And because of the time sleep, then if you receive, for example, three comments, well it's going
to first spend 10s in that and then 10s in the second one and 10s in the third one.
So what we want to do basically is to say that instead of queuing the callbacks, we want to execute
them all inside different threads.
So every time you receive a new command, you, you execute it in yet another thread so you can run
multiple callbacks at the same time.
And to do this, this is actually very easy.
So it's a bit complicated to explain, but it's very easy to implement.
You put run async, so run asynchronously is equal to true in the command handler.
So you had a third optional argument here.
And now that we have this, we have yet another problem because so let's say now you request the opening
of the door, you receive that on Telegram and you send open three times.
So the three open door handler are going to be executed at the same time.
And the open door request is going to be true for all of them.
So from three different threads, we're going to send this and then send this.
So we don't want this.
And I'm going to add yet another flag here that I'm going to name, Let's name it.
Handling door is equal to false.
So whenever we handle the door, which means basically that we open the door, we close the door, we
deny the access.
Every time we handle the door, we're going to put this flag to true so that any other callback will
not be able to handle the door at the same time.
And so in our.
Open door handler I'm going to do also global handling though, so I can access the global variable
and modify it.
And so I'm going to check before I open the door, I'm going to check that I have an open door request
and that I don't have the handling door flag on.
And then if I open the door, I'm going to set the handling door flag to true.
And once I am done, I'm going to set it to false.
Okay, So that is maybe not the ideal best 100% solution to Multithreading, but this is going to be
fine for our application and I don't want to go too deep on Multithreading here.
That's out of the scope of this course, but we still need to work a bit on that.
So we have an application that works well.
So what's going to happen here?
Let's say you send three open comments from Telegram and you have the open door request on because you
have previously pressed on the push button.
So you're going to have three callbacks that are going to be called, let's say the first one is going
to see that, yes, we have a request and we don't have the handling door flag.
So it's going to enter here and put the flag to true directly and then it's going to do its thing and
sleep for 10s.
And then the second and the third callbacks are going to be called independently.
But when they are going to arrive at that, if they're going to see that, yes, we have the open door
request, but this flag is already true.
So we can't enter the if and we're going to exit.
And so you're going to only have one callback that is working at a time.
And finally, the last thing I'm going to add in the main loop here, I'm also going to add and not
handling door.
So basically we want to take a photo and send it to Telegram when we have at least five second passed
and when we don't have an open door request that is currently on and also when we are not handling the
door.
Okay.
Because if we are handling the door well, the button should not work.
The button should only work after the door is correctly handled.
All right.
So now we can test this code.
If you had some trouble about the Multithreading explanation, well, that's not a problem because this
is something we haven't talked about in this course that's a bit outside of the scope and you can come
back to it later and continue to make progress on the project.
Basically, you could do without the Multithreading, but here this is just so we can improve the code
to make it more robust.
And now I'm going to run that code.
Okay.
We have the starting here.
Waiting for three seconds.
Main loop is starting.
I open the telegram app.
I'm going to press on the push button.
You can see.
Please wait for a few seconds.
Someone is ringing the bell.
He and well, let's say we want to open.
So I'm going to send open or just click on open here.
Okay.
It's working.
Door is opened, green led.
The door is opened.
Let's wait 10s.
And we should have.
Okay.
Push on.
Button to call.
Blue led and the door is closed.
And with the few additions we did here on the code, you can also try to send multiple open command
here and you're going to see that they are not going to work.
And also, if I send open now, well, the callback is still working, but we can't open the door because
we don't have a request.
All right.
And that's the end of the step number eight.
We're almost done with the final project.