Questo sito utilizza cookie di profilazione di terze parti. Se prosegui nella navigazione o clicchi X acconsenti all’uso di cookie.
Clicca qui per più informazioni sui cookie.
Site mapHomeElettronicaRaspberry PiC64

Manage RPi using Whatsapp


Enable javascript to use this site!

>>> Take a look at my new RPi blog! <<<

yowsup In this page We will see how to communicate with our Raspberry using Yowsup library.
I wrote a python script (download it here) that waits for a Whatsapp message from me, analyze the text and in case of a specific command anwsers me using Whatsapp (and executing some task).

This is a simple script and can be improved quite a lot. Anyway You can use it as a starting platform for home automation system.

Just a small note: the best solution would be to use the library directly inside the script, but to keep it simple I preferred using the command line script that comes along Yowsup, and just modify some small parts as I specify below.

For this description I assume the installation folder is /home/pi/yowsup (the one used in the installation and configuration page).

The first thing to do is to modify the file yowsup/src/Example/ListenerClient.py so that it does not stops waiting for a message and to save the received message in a text file.


You have to modify the following sections (my changes are in boldface):

def login(self, username, password):
    self.username = username
    self.methodsInterface.call("auth_login", (username, password))
    time.sleep(1)
    #while True:
        #raw_input()

and

def onMessageReceived(self, messageId, jid, messageContent, timestamp, wantsReceipt, pushName, isBroadCast):
    formattedDate = datetime.datetime.fromtimestamp(timestamp).strftime('%d-%m-%Y %H:%M')
    #print("%s [%s]:%s"%(jid, formattedDate, messageContent))
    with open ("/home/pi/message.msg","w") as mss: mss.write(jid[:12]+messageContent)
    if wantsReceipt and self.sendReceipts:
        self.methodsInterface.call("message_ack", (jid, messageId))


If You use a different installation folder, just change the saving path in the second definition.

Now let's see my script. The first section is for variables (I will not describe the import of the modules):

base="/home/pi/"
recipient="390000000000"
mac="00:00:00:00:00:00"
iprange="192.168.0.1-50"
counter=0
status=0
starting="Raspberry Pi started."
phonewaiting=360
#tempo=0.0


base is the installation folder. If You followed instructions on my site this can be left unmodified.
recipient the phone number used to exchange the messages. Must have the country code without the '+' sign.
mac MAC address of my phone. Used to check if the phone is connected to my lan.
iprange IP addresses to check for when searching my phone in the lan.
counter e status used by the script. Leave unchanged.
starting this is the message sent when starting the script. If You start the script at boot, it will notify You that Your RPi has been started.
phonewaiting number of cycles to wait after phone disconnection before sending a new welcome message.
tempo (usually commented) used to know cycle duration to properly configure the value of phonewaiting.

Next You can find the function that actually sends the answer and eventually deletes the file with the received message. You do not need to modify it.

Under this function there is the command to send the starting message. If You comment out starting nothing will be sent.

try:
    Answer(starting)
except:
    pass


Next there is the main loop that runs indefinitely thanks to this command:

while(1):


The first three rows in the loop are used to check for cycle duration. You can display or store in the log file the elapsed time by removing the comments in the rows (the first row shows the time, the second store it in the file and the third makes the calculation):

#print time.time()-tempo
#with open(base+"whatsapp.log", "a") as myfile: myfile.write(str(time.time()-tempo)+"\n")
#tempo=time.time()


Next row tries to connect to Whatsapp to receive a message:

os.system("python "+base+"yowsup/src/yowsup-cli -c "+base+"yowsup/src/config -l -a -k")


The heart of the script is inside the try: statement. The clause except: is just to avoid errors if there is no text file (message not yet received). Of course the same goal can be obtained using different methods.

Next statements try to read the message from the file and then convert it to lowercase. This allows us to ignore for example commands with a capital first letter.

with open(base+"message.msg") as mss: received=mss.readline()
received=received.lower()


Next the script checks if the sender is the right one. Otherwise an error is stored in the file whatsapp.log to keep record of this.

if received[:len(recipient)]==recipient:
    received=received[len(recipient):]
    .
    .
    .
else:
    with open(base+"whatsapp.log", "a") as myfile: myfile.write("Message from wrong sender: "+received[:len(recipient)]+"\n")
    if os.path.exists(base+"message.msg"): os.remove(base+"message.msg")


If everything is ok, We now have to check for a valid command by just comparing the message with a text. Let's see some example.

The first one checks for a greeting and answers with the same greeting. The number inside the brackets (in this example [:5]) is the number of characters to check. This way the command also works with messages like "Hello my RPi!".

if received[:5]=="hello":
    Answer("Hello!")


Next tests use the elif command to proceed with the check only if the previous one failed.

The second test allows us to reboot the RPi:

elif received[:7]=="restart":
    Answer("I am restarting...")
    os.system("sudo reboot")


Of course We can use more complex tests, answering the same thing for different commands:

elif received[:11]=="goodmorning" or received[:12]=="good morning":
    Answer("Goodmorning to You!")


Next two tests allow us to check SD card space and RPi temperature:

elif received[:6]=="memory":
    result=subprocess.check_output("df -h .", shell=True)
    righe=result.split()
    Answer("Main memory:\nTotal: "+righe[9]+"\nUsed: "+righe[10]+" ("+righe[12]+")\nFree: "+righe[11])
elif received[:11]=="temperature":
    t=float(subprocess.check_output(["/opt/vc/bin/vcgencmd measure_temp | cut -c6-9"], shell=True)[:-1])
    ts=str(t)
    Answer("My temperature is "+ts+" °C")


At last, if no valid command has been found, RPi will inform us of the problem.

else:
    Answer("Sorry, I cannot understand what You mean!")


The last part is for checking if the phone is connected to the lan at home. When the phone connects a welcome message is sent from RPi. For this message to be sent again, the phone must stay disconnected for at least the specified number of cycles (in my case about one hour).
Please note that some phone disconnects from wi-fi when in stand-by.

finally:
    result=subprocess.check_output("sudo nmap -sn "+iprange, shell=True)
    if (mac in result) and (status==0):
        Answer("Welcome back!")
        status=1
    if (mac in result) and (status==1):
        counter=0
    if (mac not in result) and (status==1):
        counter=counter+1
    if (status==1) and (counter>phonewaiting):
        status=0
        counter=0
    time.sleep(4.5)


These are simple commands and You can do much more! For example by adding some electronics You can use this script to turn on/turn off a lamp, or to set a thermostat.

Now I'm trying to make it send me an image from the webcam (and it can also be an automatic behaviour if a motion is detected).

As You can see there are endless possibilities.





These are the RPi sections:
F.A.Q.
Base
SiriProxy
C64 emulator
Web server
Installing Yowsup
Using Whatsapp