Last time we saw how to install Yowsup on our Raspberry Pi and use the python script yowsup-cli to send and receive messages.
Now it's time to use it for something useful.
With the new Yowsup 2 you cannot use yowsup-cli to send and receive the messages. This is both a good and a bad news. The bad part is that you need to create the classes as described in the author's site, or to modify the existing demos.
The good part is that we will have much more control over the whole system we are creating and everything will be integrated in the script, without the need to execute something external.
The good part is that we will have much more control over the whole system we are creating and everything will be integrated in the script, without the need to execute something external.
To make it easier for my readers, I created two files (modifying the original Yowsup demos) with the needed classes for sending and for receiving Whatsapp messages via Yowsup. You can download them here:
http://www.mascal.it/public/wasend.py
http://www.mascal.it/public/wareceive.py
http://www.mascal.it/public/wasend.py
http://www.mascal.it/public/wareceive.py
To use Whatsapp for home automation we need to create a parser. There are many ways to create such task and some are smarter and more powerful than others. We will see just a simple one.
Before everything, let's put these functions to make things easier:
def credential():
return "391122334455","whatsapp_password"
def Answer(risp):
try:
stack=YowsupSendStack(credential(), ["390000000000", risp])
stack.start()
return
return "391122334455","whatsapp_password"
def Answer(risp):
try:
stack=YowsupSendStack(credential(), ["390000000000", risp])
stack.start()
return
The first function is used to return your RPi phone number and the password for Whatsapp, so there is no need to read the configuration file (just get the two strings from that file). The second function will send a text to the specified number using the Yowsup classes. Let's go on with the parser...
First of all an infinite loop that will contain our parser (note that at the top of the script there must be the header with the all the declarations that I will skip to concentrate only on the main parsing cycle):
while True:
Than let's check for a received message:
try:
stack=YowsupReceiveStack(credential())
stack.start()
except MessageReceived as rcvd:
stack=YowsupReceiveStack(credential())
stack.start()
except MessageReceived as rcvd:
The receiving class will execute and terminate after a few seconds if nothing has been received. In case of a message incoming, it raises a MessageReceived exception.
When this happens, we can just read the value of the exception that will contain what we are looking for. To make it easier to create the parser let's convert the whole string to lowercase:
received=rcvd.value.lower()
Now let's check if the message has been received by our phone number and not from someone else:
if received[:len("390000000000")]=="390000000000":
received=received[len("390000000000"):]
received=received[len("390000000000"):]
If the number is correct I will strip it off from the string to have just the message. In case the number is not the right one we could append to a log file for inspection. At the end of this post there is a full listing of the script, with the logging statements.
Now we can start parsing the message. We can just search for specific text inside the message and act consequently. Let's start with a simple test that will answer "Hello" when receiving "Hello":
if received[:5]=="hello": Answer("Hello!")
With this statements we are checking if the received message starts with "hello". Note that case is ignored because we converted everything to lowercase and also note that we could write whatever we like after "hello". We could have sent something like "hello my raspberry pi" and the message would have been correctly interpreted.
elif received[:6]=="update":
Answer("Updating...")
os.system("sudo apt-get -y update")
Answer("System updated!")
Answer("Updating...")
os.system("sudo apt-get -y update")
Answer("System updated!")
Here we check for the "update" text at the beginning of the received message. If found RPi answers with the text "Updating...", it performs an update without asking for confirmations and at the end it informs us that the update has been completed.
To keep the parser clean, it would be advisable to use functions. So before the main loop we could have something like
def UpdateFunc():
Answer("Updating...")
os.system("sudo apt-get -y update")
Answer("System updated!")
return
Answer("Updating...")
os.system("sudo apt-get -y update")
Answer("System updated!")
return
and the parser would become like this:
elif received[:6]=="update": UpdateFunc()
What if we wish to execute something by different words? For example we could wish to make the RPi restart by sending "restart" or by sending "reboot". Actually that's quite easy:
elif received[:7]=="restart" or received[:6]=="reboot": RestartFunc()
and we will have the following function declared:
def RestartFunc():
Answer("Restarting the system...")
os.system("sudo reboot")
return
Answer("Restarting the system...")
os.system("sudo reboot")
return
Now we try to manage a message where the expected word could not be at the beginning of the text. As an example we could ask fot the RPi internal temp with messages like these:
- Temperature?
- What is your temperature?
- Is your temperature too high?
and so on. To accomplish this task we can just check if the word "temperature" is inside the message with this test:
elif "temperature" in received: TempFunc()
and the function would be:
def TempFunc():
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")
return
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")
return
The word could be everywhere inside the message and the function will be executed anyway.
At the end of the parser there should be something to inform us about unrecognized statements, so we can put a statement like this:
else: Answer("Sorry, I cannot understand what you are asking for...")
This ends the first part about using Whatsapp for home automation. We saw how to make a simple parser to recognize words (or small sentences) and execute some task according to these words. Actually there is still no real home automation, but we will see something more complex on next post.
import os, subprocess, yowsup, logging
from wasend import YowsupSendStack
from wareceive import YowsupReceiveStack, MessageReceived
from wasend import YowsupSendStack
from wareceive import YowsupReceiveStack, MessageReceived
def credential():
return "391122334455","whatsapp_password"
def Answer(risp):
try:
stack=YowsupSendStack(credential(), ["390000000000", risp])
stack.start()
except:
pass
return
return "391122334455","whatsapp_password"
def Answer(risp):
try:
stack=YowsupSendStack(credential(), ["390000000000", risp])
stack.start()
except:
pass
return
def UpdateFunc():
Answer("Updating...")
os.system("sudo apt-get -y update")
Answer("System updated!")
return
def RestartFunc():
Answer("Restarting the system...")
os.system("sudo reboot")
return
def TempFunc():
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")
return
while True:
try:
stack=YowsupReceiveStack(credential())
stack.start()
except MessageReceived as rcvd:
stack.start()
except MessageReceived as rcvd:
received=rcvd.value.lower()
if received[:len("390000000000")]=="390000000000":
received=received[len("390000000000"):]
if received[:5]=="hello": Answer("Hello!")
elif received[:6]=="update": UpdateFunc()
elif received[:7]=="restart" or received[:6]=="reboot": RestartFunc()
elif "temperature" in received: TempFunc()
else: Answer("Sorry, I cannot understand what you are asking for...")
else: #message from wrong sender
with open("/home/pi/whatsapp.log","a") as mf: mf.write("Wrong sender: "+received[:len("390000000000")]+"\n")
Did I install wrong? I can not find out the directory "src" as you mentioned in modifying the file ListenerClient.py.
ReplyDeleteWhen I run ls command, it show below files and dirs:
"build config dist LICENSE README.md setup.py yowsup yowsup2.egg-info yowsup-cli "
Yowsup has been updated few days ago and it seems that several changes has been implemented.
ReplyDeleteI'm going to check this and I will put an updated guide for this version as soon as possible.
Thank you for quick response. Hope that you will fix it soon. I want to use rpi as a gate keeper and with a pi camera, it can send me an image every time there is a man in front of my house.
ReplyDeleteThe nice thing is that reading the new features it seems that you can send and receive images with yowsup-cli without the need to modify the source code.
ReplyDeleteI will try to update the guide in these days.
Updated for Yowsup 2! You should also take a look at the previous post (or at the Yowsup main site) for a correct installation.
ReplyDeleteHello friend, okay?
ReplyDeleteYour article is very good and I saw that can do what I'm trying to days.
I need to open the connection to yowsup order to get the status of the messages received, but my knowledge in python is not good about to rewrite things. Thus, I'm trying directly by the shell using a named pipe. Infezlimente, when sending the first message through the pipe, this error happened.
"Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 810, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 763, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/local/src/yowsup/yowsup/demos/cli/cli.py", line 150, in startInputThread
cmd = self._queuedCmds.pop(0) if len(self._queuedCmds) else input(self.getPrompt()).strip()
EOFError: EOF when reading a line"
You have no idea how to help me?
thank you very much!
Hi, unfortunately I never saw this error.
DeleteAnyway it seems cli is expecting to find some input text, but find nothing. Maybe the message is not arriving to cli.py through your pipe... How did you invoke yowsup in the pipe?
I found out this script is kind of easy to crash.
ReplyDeleteTraceback (most recent call last):
File "whatsapp_parser_from_me.py", line 43, in
stack.start()
File "/home/pi/parser/wareceive.py", line 67, in start
self.stack.loop(count=4)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/stacks/yowstack.py", line 170, in loop
asyncore.loop(*args, **kwargs)
File "/usr/lib/python2.7/asyncore.py", line 220, in loop
poll_fun(timeout, map)
File "/usr/lib/python2.7/asyncore.py", line 156, in poll
read(obj)
File "/usr/lib/python2.7/asyncore.py", line 83, in read
obj.handle_read_event()
File "/usr/lib/python2.7/asyncore.py", line 449, in handle_read_event
self.handle_read()
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/network/layer.py", line 48, in handle_read
self.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/network/layer.py", line 55, in receive
self.toUpper(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/__init__.py", line 55, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/stanzaregulator/layer.py", line 28, in receive
self.processReceived()
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/stanzaregulator/layer.py", line 48, in processReceived
self.toUpper(oneMessageData)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/__init__.py", line 55, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/auth/layer_crypt.py", line 63, in receive
self.toUpper(payload)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/__init__.py", line 55, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/coder/layer.py", line 35, in receive
self.toUpper(node)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/__init__.py", line 55, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/__init__.py", line 160, in receive
s.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/__init__.py", line 101, in receive
recv(node)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/protocol_acks/layer.py", line 17, in recvAckNode
self.toUpper(IncomingAckProtocolEntity.fromProtocolTreeNode(node))
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/__init__.py", line 55, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.2.78-py2.7.egg/yowsup/layers/interface/interface.py", line 71, in receive
self.callbacks[entityType](entity)
File "/home/pi/parser/wasend.py", line 43, in onAck
raise KeyboardInterrupt()
Above occasionally happens. I dont know the reason.
Do I have to study yowsup to solve this issue?
Hi, did you resolve it please somehow? I found the parser.py script a bit unstable. Mainly due to that wasend.py keyboard interception.
DeleteLet me please know if you have any solution for it
Actually, the script wasend.py uses the keyboardinterrupt exception to return to the parser. I agree that this is not the best way, but they are just examples...
ReplyDeleteYou should catch the exception in the parser if you whant to avoid the problem (the try...except statement could even do nothing after catching the exception, but it needs to exist).
If you wish, you can just modify the wasend.py to exit differently from the python class.
Anyway I wish to modify the scripts by myself to make them a bit better and probably I will upload the new ones when ready.
Carlo please can you modify the wasend.py in the way that it will not crash? i am not a programmer but I would like to use you perfect idea to send commands to raspi.
Deletethanks
Lately I've been quite busy with other thing, sorry. Anyway Im' testing a new version of that script that should work better.
DeleteAs soon as I finish all the testing I promise that I will make it available and I will change the parser above to use the new wasend (actually a really small change)!
Finally I managed to complete the tests. Now the new wasend.py is downloadable (from the link in the post) and I also changed the example script above (just the Answer function has been changed a little).
DeleteThe new script exits logging out from Whatsapp instead od raising an exception that should be catched. This way works much better!
Thank you for your advice.
ReplyDeleteActually using whatsapp instead of email or ssh to control raspi is even more convenient than I thought.
Thank you for your dedication.
You are genius.
This comment has been removed by the author.
DeleteI know it might be inappropriate to ask here.
ReplyDeleteBut I wonder how should I start learning about yowsup as I really enjoy using its function.
I have learned python for several months and ready for something real(such as creating a custom yowsup layer (like what you did),
but I still found yowsup tedious to start with. At least I want to create my own version of yowsup layer.
Any suggestion?
Unfortunately Yowsup is almost without documentation, so the only way to learn how it works is looking at the demos (I did this way).
DeleteAlso looking at the issues in the git page where you download Yowsup could help ( https://github.com/tgalal/yowsup/issues?q=is%3Aissue ).
Yes, it's quite tedious learning it this way (it took several month to me to make it works), but I do not think there are other choices...
wow several MONTHS, that require tons of patience and passion.
DeleteThank you for providing me this invaluable suggestion.
I assume this is a "must" path for anyone who wants to be a user or contributor.
I found it is kind of cool to build up a custom layer, I hope I can one day utilize yowsup and raspi to deploy some kind of home automation smoothly.
May be even build up a graphic interface, let my family members can monitor their home condition by just asking raspi through whatsapp
Anyway remember that I was also a Python "novice", so maybe it could take less for you. Moreover several months to have a complete Yowsup manager (so also sending images). Results came much earlier...
DeleteThe project you are thinking of is almost the same I wish to build and the main reason I started this blog! Actually it's constantly evolving, so changes happens quite often (soon you will see a post about my last "upgrade").
If you need help, I hope my blog (and me) can provide some help. Suggestions (and corrections) are of course always welcome!
Hey I have found something cool.
DeleteSomeone has the same idea!
https://github.com/tgalal/yowsup/issues/647
Sir,
ReplyDeleteIn this example using what's app to run a command in raspberry pi, the above like update reboot??
NameError: name 'received' is not defined
ReplyDeletehelp
Are you sure tha you copied all the parts? In the mani loop I assign a value to that var:
Deletereceived=rcvd.value.lower()
If you missed that line "received" cannot exists and the script will give such error...
Sir,
DeleteThis script is exist, and the error should come. How to solve this.
Replay me
Thanks
If that row is present I really do not know. Maybe indentation not correct? Anyway it's quite difficult without looking at that part of the script...
DeleteAny another way to define 'received' ?
ReplyDeleteThanks
"received" contains the received message. It will be defined getting the text from the MessageReceived exception that will be raised by the stack when a message arrives to the RPi.
DeleteIf the part of the script that runs the stack and manages the exception is in your script, it's really impossible to find the problem without looking at it.
Ok
ReplyDeleteThanks for your replays,
This blog is very useful to me.
Thanks.
i love u, thanks for the info
ReplyDeleteby from argentina
I do get the same error as: Anonymous15 March, 2015 10:46
ReplyDeleteI do get a Whatsapp message back, but always as a answer on my very first message send from my mobile. So it looks like, they are not deleted.
After a couple of times testing, is it working correct.
DeleteGlad to know that now it's working!
DeleteDear Carlo, yesterday you already helped me first time in this case - many thanks. Everything like mentioned in your post "WhatsApp Raspberry Pi / Yowsup" works exactly with my Pi - perfect!
ReplyDeleteToday I am here with another big problem for me:
Obviously it works while I'm using the RPI headless via a ssh-session. But if I end this session (I want to run the RPI totally headless), the listener obviously don't work anymore.
My goal is to execute a file with autostart of Rpi which listens permanently for received whatsapp-messages and reacts depending of the content of the received message. I try to understand this page but I really have no idea what to. In which file(type) to I have to put which code?
Maybe you are patient enough to help me again... Again many thanks for your very patient and professional cooperation with readers of your blog! Dirk
Starting a script at power on is not too difficult, but a bit long to write in a comment. Fortunately I'm going to write a new post about this topic, so soon you can find what you are asking for!
Delete...perfect! I will wait for that stuff, many thanks!
DeleteI published it few hours ago. Take a look at the last post!
ReplyDeleteHi, sorry for my bad programmimg skills...
DeleteI installed the yousup stuff -> ok
- learned how to make a *.py file ("testing.py" e.g.) automatic running with every new (re)boot (your post July 2015) -> ok.
- copied the two files "Wasend.py" & "wareceiver.py" mentioned above in the path "/home/pi" -> ok
To be honest - I did not understand, in which file I have to put the "Qestion and Answer"-code mentiones above... may you help me again? many thanks again
Hi, sorry for asking again, but I don't know how to run this stuff....What have I done:
ReplyDelete- Copied the file "wasend.py" to /home/pi/
- Copied the file "wareceive.py" to /home/pi/
- Created a file named "testing.py" and copied the long code above into.
- In row 6 I changed the phonenumber to mine and the password also
- In row 37 I changed the second number also to my phonenumber
- set the file executable with "sudo chmod 755 testing.py" and finaly try to run the file with
- ./testing.py
Then I got a few errors: ./testing.py: Zeile 1: import: Kommando nicht gefunden
from: can't read /var/mail/wasend
from: can't read /var/mail/wareceive
./testing.py: Zeile 5: Syntaxfehler beim unerwarteten Wort '('
./testing.py: Zeile 5: 'def credential():'
What am I doing wrong? Any help appreciated, many thanks for your patience!
The parser script can be downloaded from: http://www.mascal.it/public/parser.py
DeleteRemember to change phone numbers and password before launching it of course.
I'am getting nuts...
Deletealthough I created a new file called testing.py and copied your linked contend from your "parser.py"-file into my testing.py, and although I made it executable with "sudo chmod 755 testing.py" and although I changed the credentials and although the file ist visible in /home/pi/ I get after "./testing.py" an error: "Datei oder Verzeichnis nicht gefunden" (compared in english like "file or path not found").
Even after sudo reboot the same issue.....
What else might I have done wrong? Obviously is the trouble not the raspbery pi but me in front of it....
Do not copy the content, rename the downloaded file and try with it.
DeleteCarlo, sorry for my stupid questions - how can I download the file "http://www.mascal.it/public/parser.py" without a link....?
DeleteThat's a link! Copy and paste it in a browser or better just use the wget command from your rpi (wget http://www.mascal.it/public/parser.py)...
DeleteCarlo,
DeleteI give up!
Although downloaded this file via wget on my raspberry, changed the crendials and made the file again executable I got again the error: "File ./testing.py", line 14 return syntax error.
What ever - this stuff is unfortuntely to high for my mind, I will try my luck with telegram. Again, many thanks for your patience with me, I will follow your very interesting blog!
Sorry to hear this... Unfortunately solving these kind of errors remotely can be quite difficult
DeleteIt could be the same issue of testing.sh. As soon as possible I will try to provide the file for this script for you to download...
ReplyDeleteHey Carlo after setting up my script didn't reply to me also after debug i found it goes to answer function and returns `need more than 1 value to unpack` can you please help ?
ReplyDeleteTraceback (most recent call last):
DeleteFile "/home/pi/software/yowsup/pitalk.py", line 53, in
else: Answer("Eh? What was that?")
File "/home/pi/software/yowsup/pitalk.py", line 12, in Answer
stack.start()
File "/home/pi/software/yowsup/wasend.py", line 60, in start
self.stack.loop()
File "/home/pi/software/yowsup/yowsup/stacks/yowstack.py", line 175, in loop
asyncore.loop(*args, **kwargs)
File "/usr/lib/python2.7/asyncore.py", line 216, in loop
poll_fun(timeout, map)
File "/usr/lib/python2.7/asyncore.py", line 156, in poll
read(obj)
File "/usr/lib/python2.7/asyncore.py", line 87, in read
obj.handle_error()
File "/usr/lib/python2.7/asyncore.py", line 83, in read
obj.handle_read_event()
File "/usr/lib/python2.7/asyncore.py", line 449, in handle_read_event
self.handle_read()
File "/home/pi/software/yowsup/yowsup/layers/network/layer.py", line 72, in ha ndle_read
self.receive(data)
File "/home/pi/software/yowsup/yowsup/layers/network/layer.py", line 79, in re ceive
self.toUpper(data)
File "/home/pi/software/yowsup/yowsup/layers/__init__.py", line 55, in toUpper
self.__upper.receive(data)
File "/home/pi/software/yowsup/yowsup/layers/stanzaregulator/layer.py", line 2 8, in receive
self.processReceived()
File "/home/pi/software/yowsup/yowsup/layers/stanzaregulator/layer.py", line 4 8, in processReceived
self.toUpper(oneMessageData)
File "/home/pi/software/yowsup/yowsup/layers/__init__.py", line 55, in toUpper
self.__upper.receive(data)
File "/home/pi/software/yowsup/yowsup/layers/auth/layer_crypt.py", line 63, in receive
self.toUpper(payload)
File "/home/pi/software/yowsup/yowsup/layers/__init__.py", line 55, in toUpper
self.__upper.receive(data)
File "/home/pi/software/yowsup/yowsup/layers/coder/layer.py", line 35, in rece ive
self.toUpper(node)
File "/home/pi/software/yowsup/yowsup/layers/__init__.py", line 55, in toUpper
self.__upper.receive(data)
File "/home/pi/software/yowsup/yowsup/layers/__init__.py", line 160, in receiv e
s.receive(data)
File "/home/pi/software/yowsup/yowsup/layers/__init__.py", line 101, in receiv e
recv(node)
File "/home/pi/software/yowsup/yowsup/layers/auth/layer_authentication.py", li ne 61, in handleSuccess
self.toUpper(nodeEntity)
File "/home/pi/software/yowsup/yowsup/layers/__init__.py", line 55, in toUpper
self.__upper.receive(data)
File "/home/pi/software/yowsup/yowsup/layers/interface/interface.py", line 71, in receive
self.callbacks[entityType](entity)
File "/home/pi/software/yowsup/wasend.py", line 26, in onSuccess
phone, message = self.getProp(self.__class__.PROP_MESSAGES, [])
ValueError: need more than 1 value to unpack
I figured it out and fixed it, The problem with script is after first commands it takes time to reply for another command.
DeleteNice done!
DeleteThis comment has been removed by the author.
DeleteDownload WhatsApp Spy Hack Here:
ReplyDeletehttp://www.soulgaminghacks.com/whatsapp-hack-tool/
http://www.soulgaminghacks.com/whatsapp-hack-tool/
http://www.soulgaminghacks.com/whatsapp-hack-tool/
http://www.soulgaminghacks.com/whatsapp-hack-tool/
http://www.soulgaminghacks.com/whatsapp-hack-tool/
Hello I am getting error at Return as invalid syntax and unexpected indent if i remove return. Please help, i am using latest version files that you provided above.
ReplyDeletedef Answer(risp):
ReplyDeletetry:
stack=YowsupSendStack(credential(), ["390000000000", risp])
stack.start()
return
Everything is running great. The only issue is in the above stack. For return it shows invalid syntax. And if we remove return it shows unexpected indent. Please help me out with this.
Sorry for the delay, but I was on holiday...
DeletePython is quite sensible to code formatting ad the error you are getting seems related to this. Did you modify the code using windows notepad? If you did that, you should probably download again and use something different... If I need to change a text in a windows machine I always use Notepad++ as it's free and it doesn't change text coding.
The other solution is to change the text directly into the RPi using nano or another Debian text editor (maybe with ssh connection from another computer).
For the lines that give you the error, remember that the first line should be to the left border (no spaces before the "def..."). The second line and the last one should have 4 spaces before the text (spaces, NOT TABS) and the two "stack..." lines should be 8 spaces from the left border.
I also get this error message, but after I changed the syntax and gain except at the end, sometimes the message is not answered
DeleteThis is a problem I found several times using Yowsup and that's one of the reasons why I'm not using it anymore. Unfortunately Yowsup completely lacks documentation, so it could be quite difficult to find if a problem is due to it or your implementation or whatever...
DeleteIf you do not need to act in real-time, you can use emails (I will write a post about this as I'm using this way to communicate with my Sphaera).
i have same problem, have another solution ??
DeleteHi!
ReplyDeleteFirst of all, thanks for providing this tutorial! They way you explain everything is really helpful!
Unfortunately I running into the same problem as the users Karan makharia and dika. When I try to run the script it always complains about "return" (Line 14) as being invalid syntax. When I "solved" this by aligning it with the code from Line 13, it complains about def UpdateFunc(): in Line 16. Specifically it says "IndentationError: unexpected unindent".
First I just used the file with the script you provided, then I copied it by typing it into a new file, but the same error is always the same. I also tried to change the spaces to 4 and 8 instead of using tabs. I believe I did this right with the spaces but the error is still the same.
I am getting a little bit frustrated as this seems to be a "minor" problem, I expected to have other problems when the script actually runs and not this problem even before the script can actually run.
So I was hoping you can tell from my description what I am doing wrong.
Thanks in advance for your help!
Python is quite sensitive to indentation. In my script I used just spaces (4 for every level). Anyway it should not give a syntax error, but just an indentation error. Maybe you can try to add an empty exception management like this:
Deletedef Answer(risp):
____try:
________stack=YowsupSendStack(credential(), ["390000000000", risp])
________stack.start()
____except:
________pass
____return
Of course change the underlines with spaces. Here I put them just to show the correct indentation.
This should solve the problem. Tell me if this works, so that in case I will change the post and the downloadable script...
after i try, i have error:
DeleteNo handlers could be found for logger "yowsup.stacks.yowstack"
Traceback (most recent call last):
File "parser.py", line 38, in
stack.start()
File "/home/pi/yowsup/demos/wareceive.py", line 67, in start
self.stack.loop(count=4)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/stacks/yowstack.py", line 195, in loop
asyncore.loop(*args, **kwargs)
File "/usr/lib/python2.7/asyncore.py", line 220, in loop
poll_fun(timeout, map)
File "/usr/lib/python2.7/asyncore.py", line 156, in poll
read(obj)
File "/usr/lib/python2.7/asyncore.py", line 87, in read
obj.handle_error()
File "/usr/lib/python2.7/asyncore.py", line 83, in read
obj.handle_read_event()
File "/usr/lib/python2.7/asyncore.py", line 449, in handle_read_event
self.handle_read()
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/network/layer.py", line 86, in handle_read
self.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/network/layer.py", line 94, in receive
self.toUpper(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/__init__.py", line 59, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/stanzaregulator/layer.py", line 28, in receive
self.processReceived()
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/stanzaregulator/layer.py", line 48, in processReceived
self.toUpper(oneMessageData)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/__init__.py", line 59, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/auth/layer_crypt.py", line 63, in receive
self.toUpper(payload)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/__init__.py", line 59, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/coder/layer.py", line 35, in receive
self.toUpper(node)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/__init__.py", line 59, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/__init__.py", line 169, in receive
s.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/__init__.py", line 105, in receive
recv(node)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/protocol_messages/layer.py", line 20, in recvMessageStanza
entity = TextMessageProtocolEntity.fromProtocolTreeNode(node)
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/protocol_messages/protocolentities/message_text.py", line 38, in fromProtocolTreeNode
entity.setBody(node.getChild("body").getData())
AttributeError: 'NoneType' object has no attribute 'getData'
This seems a yowsup problem. Maybe the installation is corrupt or you deleted something from the parser...
DeleteHow do i use this script? When I open parser.py I get the error 'No handlers could be found for logger "yowsup.stacks.yowstack"
ReplyDeleteAuthentication Error: not-authorized'.
What am I doing wrong?
The warning about logger can be ignored without any problem.
DeleteThe other error just means that you did not register with whatsapp or that you made some mistake when copying the result of the registration process... You can take a look at the previous posts about yowsup to see how to proceed.
Ok, I set the credencials, now I get this:
DeleteNo handlers could be found for logger "yowsup.stacks.yowstack"
Traceback (most recent call last):
File "parser.py", line 37, in
stack.start()
File "/usr/local/bin/wareceive.py", line 67, in start
self.stack.loop(count=4)
File "/usr/local/lib/python2.7/dist-packages/yowsup/stacks/yowstack.py", line 195, in loop
asyncore.loop(*args, **kwargs)
File "/usr/lib/python2.7/asyncore.py", line 220, in loop
poll_fun(timeout, map)
File "/usr/lib/python2.7/asyncore.py", line 156, in poll
read(obj)
File "/usr/lib/python2.7/asyncore.py", line 87, in read
obj.handle_error()
File "/usr/lib/python2.7/asyncore.py", line 83, in read
obj.handle_read_event()
File "/usr/lib/python2.7/asyncore.py", line 449, in handle_read_event
self.handle_read()
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/network/layer.py", line 86, in handle_read
self.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/network/layer.py", line 94, in receive
self.toUpper(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/__init__.py", line 59, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/stanzaregulator/layer.py", line 28, in receive
self.processReceived()
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/stanzaregulator/layer.py", line 51, in processReceived
self.processReceived()
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/stanzaregulator/layer.py", line 51, in processReceived
self.processReceived()
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/stanzaregulator/layer.py", line 48, in processReceived
self.toUpper(oneMessageData)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/__init__.py", line 59, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/auth/layer_crypt.py", line 63, in receive
self.toUpper(payload)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/__init__.py", line 59, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/coder/layer.py", line 35, in receive
self.toUpper(node)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/__init__.py", line 59, in toUpper
self.__upper.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/__init__.py", line 169, in receive
s.receive(data)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/__init__.py", line 105, in receive
recv(node)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/protocol_messages/layer.py", line 20, in recvMessageStanza
entity = TextMessageProtocolEntity.fromProtocolTreeNode(node)
File "/usr/local/lib/python2.7/dist-packages/yowsup/layers/protocol_messages/protocolentities/message_text.py", line 38, in fromProtocolTreeNode
entity.setBody(node.getChild("body").getData())
AttributeError: 'NoneType' object has no attribute 'getData'
As I answered some comment above, this seems to be a yowsup issue. There could be some problem in the code or maybe whatsapp team changed something and in this case you need to install yowsup again to get the last updates...
Deleteto solve the problem add "YowAxolotlLayer" to wareceive.py
Deletelike...
(YowAuthenticationProtocolLayer, YowMessagesProtocolLayer, YowReceiptProtocolLayer, YowAckProtocolLayer),
YowAxolotlLayer,
...
Now it works, but when I send a message to the automation it creates a log whatsapp.log with my "Wrong sender: [myphonenumber]". How I set the number as trusted?
DeleteDid you changed the following lines with your phone number (smartphone, not rpi) in all the three places? Also remember that the number should start with your country code (in the example 39 is for Italy).
Deleteif received[:len("390000000000")]=="390000000000":
received=received[len("390000000000"):]
I changed now, it didn't write in the log anymore, but I didn't received an answer when I sent 'hello' .
DeleteYou can add the following line just before the if received[:5].... :
Deleteprint received
withe the same indentation. This way you can check the incoming message to see if there is something wrong. The if statement for the hello message checks the first characters, so if you put a space or something else before the "hello" when sending to the RPi, this message cannot be recognized.
Another problem could be the Answer routine. Did you changed the number there? It should be your smartphone number...
Hello Carlo,
DeleteI tried your code today but won't work.
I have the same problem as Geovani and tried your "print received".
When I send the message "Hello" the received message is than "49xxxxxxxxhello□□□□□□" (x is my phone number) and no answer appears, even not the " else: Answer("Sorry, I cannot understand what you are asking for...")" message appears.
I tried even to send a message by writing " Answer("Hallo") " directly beneath the if received[:len("49.... but tha won't work either.
Thanks for sharing beneficial information for the betterment of our knowledge about home automation and please keep sharing.
ReplyDeleteHome Automation Vancouver | vancouver security | Best Security Vancouver
Hi,
ReplyDeleteDo you notice with That kind of code using stack=YowsupSendStack and stack.start, sometimes it disconnect from Whatsapp, sometimes it keeps the connection 5 minutes, 20 minutes after that it does not response, And it is necessary to re-run the code (in order to receive all the messages or the answer that are on the stack or server). but it is problem of the whatsapp server, that sometimes avoid pings to the number, so the code keep blocked.
I use this stack on a thread, but it keeps blocked, I am trying to use some kind of options like /disconnect that it is implemented with yowsup-cli. using event_disconnect, in order to re-connect in eache iteration.
have you use this features of yowsup?have you explore a way to connect and disconnect in order to avoid the ping, or keeping the connection?
Actually the loop should iterates 4 times and than it returns back to the main python script (as you can see at the end of the wareceive.py script), so it should disconnect after the end of the loops and should reconnect when called again. I did this way so I could do other things inside the parser, while waiting for an incoming messages..
DeleteOK. thanks a lot. It is a good example.
DeleteHi,
ReplyDeletewhat do you think of this issue, It seems to be a Yowsup Problem, Sometimes it disconnect or it really difficult to get back the connection to the whatsapp server...
File "SM_AdminWhatsapp.py", line 99, in ReadWhats
stack.start()
File "/home/pi/concentrador/SrvMm/Whatsapp/wareceive.py", line 87, in start
self.stack.loop()
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/stacks/yowstack.py", line 195, in loop
asyncore.loop(*args, **kwargs)
File "/usr/lib/python2.7/asyncore.py", line 216, in loop
poll_fun(timeout, map)
File "/usr/lib/python2.7/asyncore.py", line 156, in poll
read(obj)
File "/usr/lib/python2.7/asyncore.py", line 87, in read
obj.handle_error()
File "/usr/lib/python2.7/asyncore.py", line 83, in read
obj.handle_read_event()
File "/usr/lib/python2.7/asyncore.py", line 449, in handle_read_event
self.handle_read()
File "/usr/local/lib/python2.7/dist-packages/yowsup2-2.4-py2.7.egg/yowsup/layers/network/layer.py", line 85, in handle_read
data = self.recv(readSize)
File "/usr/lib/python2.7/asyncore.py", line 387, in recv
data = self.socket.recv(buffer_size)
error: [Errno 11] Resource temporarily unavailable
What are your appreciations?, re-install maybe, mistakes using the module?
thanks.
It does not work every times but ... it works . Thank you.
ReplyDeletehi,
ReplyDeleteI modified the parser, ir order to connect and reconnect in every iteration. It means, that I used the event_Disconnect to stop the parser meanwhile I process other things.
try:
.....
stack.start()
except received..... :
do something
finally:
stack.stop()
I realized that the parser connects with stack.start() for 1 minute, waiting a Request, after that time, it pass to finally and disconnect the number, with the next iteration it runs again in order to process the request on the whatsapp server.
If there is not a request, it is waiting for 1 minute, after that disconnect and connect again... (a good process maybe not lose the ping).
Is possible to reduce or change that time (1 minute) ?, the time that the stack is still waiting (around 1 minute)
Thanks
Well, you could try to reduce it by changing the wareceive.py file.
DeleteAlmost at the end you can find this line:
self.stack.loop(count=4)
Just reduce the count value (keep it grater than 0) and try.
Carlo, which demo on echoclient do i have changing ?
ReplyDeleteHi Carlo, i need to know which folder i have to put the parser.py file and how i execute it .. thanks
ReplyDeleteI hope that you can help me
Best Regards
You can put the script where you prefer. It can be executed from every folder without problems.
DeleteOf course the other two scripts (wasend and wareceive) must be in the same folder with the parser.
As it's a normal python script, just launch it like every other python script:
python parser.py
Hi Carlo,
ReplyDeleteDo you know how Yowsup is stable?, I had the parser.py runs all the time, and suddenly stop sending messages from the interruptions on the Rpi pins. the output was "authorized error: UnAuthorized number".
when I try to ask for a new code with two SIM numbers, the result was:
INFO:yowsup.common.http.warequest:{"status":"fail, "reason": "old_version"},
maybe is there a new update?, I assume that yowsup is not stable to work with it.
what ddo you thing about it?
Unfortunately Whatsapp makes changes from time to time. Yowsup creator is quite fast to reproduce the updates in his code, but you need to install it again.
DeleteTo use it without too much trouble, you have to check quite often if there is an update and act consequently.
This is one of the reasons why I do not use it anymore.
I got it, yeah it is unstable, I fixed erasing the .yowsup folder
Deletefor example:
Another thing is, when I use the yowsup-cli demos -c config.conf --yowsup and I am logged, I have all the interactions with people, I add people with /contacts sync #'s, I received and send text messages.
BUT When I run the Answer code, I don't receive the text alarm or any message, only images. Why is that? or sometimes I send to 4 numbers but the message is only received by one or two numbers.
any ideas to fixed.
thanks.
My scripts have been created just for simple notifications between RPi and one smartphone and they have only a small subset of all the functions implemented within Yowsup.
DeleteIf you need more functionality you can go through the yowsup-cli code and see how to create a new script or how to modify mine.
When wareceive.py raise the message it doesnt enter on line: "except MessageReceived as rcvd:".
ReplyDeleteI put a print below but nothing.
On wareceive.py I put a print on class "MessageReceived(Exception):" and works.
Do you have some tip?
If the exception is raised and it doesn't enter the except... statement, then the script will stop. If it doesn't stop, the except is managed as the except statement is executed.
DeleteThe problems could be a wrong indentation of the print or maybe you are not printing the value of the exception...
Hello Carlo,
ReplyDeleteI updated yowsup some days ago, since than following error appears:
File "/home/pi/pywork/pitalk.py", line 35, in
stack=YowsupReceiveStack(credential())
File "/home/pi/pywork/wareceive.py", line 63, in __init__
self.stack.setProp(YowCoderLayer.PROP_RESOURCE, env.CURRENT_ENV.getResource())
AttributeError: 'module' object has no attribute 'CURRENT_ENV'
is it possible to update your files wasend.py & wareceive.py, too?
thank you for your work.
Fin
Sorry, but I don't think I will update. This year I'm quite busy with several different things (as you may have seen I'm not posting new articles quite often).
DeleteAlso I'm really not using yowsup anymore and what happened to you clearly explain why: Whatsapp staff makes changes, so Yowsup staff makes changes and you have to make changes. Most of your efforts are on keeping the things updated or they won't work.
Yowsup is ok for hobbists with spare time, but not for the final users.
There are other easier ways to communicate with a RPi and that do not need constant maintenance.
what are the easier ways? i tried mail, and i don't like it, sms needs an umts stick. any advice?
DeleteMost depends on what are your needs...
DeleteYou do not like emails, so we can leave these apart, even if they can also be used to voice-control your RPi (not exactly direct control, but today almost every smartphone allows to send an email by just telling them to do it and they also can read them aloud when received).
If you really need to "chat" with a RPi you can use different softwares. Telegram is a nice substitute, but I have not tried it.
MQTT is another nice way to try and I will definitely check this in the future.
For just receiving notifications on the smartphone you can use something like Pushover (not free, but the price is low) that is quite easy to use. This is my preferred way.
If you do not need almost real-time communication, a web interface will do the job. It's free and after you create it there is really few maintenance needed.
These are just examples, but cover many needs. Of course you could just wish to stay with Yowsup anyway. In this case I will suggest you to deeply study the yowsup-cli code and look at the developer site to see all the requests by other users (and you can also ask, of course).
It's not too easy and maybe it could take some time to really manage that software, but it's not an impossible task.
Please note that before starting with RPi I knew nothing about Python (even if I am an expert programmer with other languages) and in few months I managed to use Yowsup, so it's just a matter of study, trials and errors...
No handlers could be found for logger "yowsup.stacks.yowstack" ?????
ReplyDeleteWith Yowsup you can also create a log, to see what's happening. It's just a debugging feature.
DeleteYou can ignore this message, but if you wish to use this feature you can search on internet for "python logging" for more info as Yowsup should use the standard python logging system.
Hi carlo, I don't have raspi, but I want test it myself. is it possible to use the script on pc or laptop that running ubuntu?
ReplyDeleteThe answer is yes...and no.
DeleteIf you just wish to use yowsup, there should be no problem at all. You could have issues if you wish to use something specific to the RPi, like GPIOs for example.
hi, anyone can help me? i got my whatsapp to send message from raspberry but my whatsapp in phone is logout, i cant received message from rpi,pls help
ReplyDeleteAre you usIng the same phone number for yowsup and your phone? If this is the case stop immediately as you risk your number to be banned forever from whatsapp!
Deletewhat i must to do? can u help me pls, i need it for my little project
DeleteYou need to use a different number for the Raspberry, there are nothing else you can do. Unfortunately Whatsapp keeps track of the connections used by every number and the use on multiple devices at the same time is forbidden.
DeleteIf you cannot borrow a number from someone (I used the one from my ipad as on this device there isn't Whatsapp and of course you also need to access this number as you need to receive the sms for the password) the only solution is to use a different way to communicate with your RPi.
Also for this problem, I do not use Yowsup anymore. Now I'm using Telegram as you do not need a phone number for the RPi and the developer allows you to use this software on every device you wish. You can find some more info on newer posts.
Hello everybody, i am a new user for raspberry PI. I want use Raspberry PI is connected with WhatsApp. I used API Kay from twilio, I used pycharm app for editor in raspberry pi. I got message error when i start pycharm, here is message error box form application:
ReplyDeleteFailed to executed child process"./ pycharm.py"(no such file or directory).
I tried to fixed it but not succeed yet.
so i need some help from you guys who have got the same cases on mine now.
thanks guys for all of you.
I am really impressed with your blog article, such great & useful knowledge you mentioned here.Your post is very informative. I have read all your posts and all are very informative. Thanks for sharing and keep it up like this.
ReplyDeleteI can't find the wasend.py and wareceive.py files anywhere
DeleteYou can find them here: www.mascal.it/old/public/wasend.py and similar for the other file (just add the “old” folder in the link).
DeletePlease note that the article and the files are quite old, so I cannot guarantee that everything could work fine...
please send me a link to download the wasend.py and warecieve.py
ReplyDelete