One feature that could be quite useful in home automation is the ability to send pictures took with a webcam to our smartphone.
This could happen on request, by just asking to take a photo with our parser, or automatically when the script is programmed to do that (at specified intervals or maybe when detecting movements).
Sending pictures using Yowsup is not too difficult, but to make it easier for all of you I created the file with class declaration. You can download it here:
With this script you will be able to send pictures. But there's more: you can use it to send also audio messages and videos!
If you wish you can examine that script, but you can use it as is without analyzing what's inside. If you have an updated Raspbian you should have all the dependecies already installed. Otherwise you should install Pillow
To use it you first need to import the script into your project, so at the beginning section of the parser add the following line:
from wamedia import *
To be able to take pictures from the camera module you should also add the following:
import picamera
and remember to enable the camera module using raspi-config.
I will not show you how to parse a command to take a photo as now you should be able to add it by yourself. You can always refer to http://rpihome.blogspot.com/2015/01/using-whatsapp-for-home-automation.html if you don't remember how to proceed.
Let's see a simple function to take a photo and send it to our smartphone:
def TakePhoto(received):
Answer("Your photo will be sent soon")
camera=picamera.PiCamera()
camera.rotation=180
camera.resolution=(640, 480)
time.sleep(2)
camera.capture("lastimage.jpg", format='jpeg', quality=75, thumbnail=None)
camera.close()
if os.path.exists("lastimage.jpg"):
try:
stack = SendMediaStack(credential(), [(["390000000000", "lastimage.jpg"])])
stack.start()
except ImageSent as e:
if ("ERROR" in e.value): Answer("Could not send the photo, sorry!")
else:
Answer("I found no photo to send!")
return
The first thing I'm doing is sending a message to inform that the photo is arriving, as the process could take some time. You can delete this if you want.
Then I create a camera object and set a couple of options. I rotate the image as my camera is upside down and set the resolution to values lower than the defaults, to keep the file small and speed up the things a bit.
There are several more options you could set. Just refer to the official documentation.
Now it's time to get the picture and save it to a file. You can save the image wherever you wish of course. You can also change the quality and the format of the resulting file. Just remember that Whatsapp accepts just jpeg and png images.
After closing the camera object I check if the picture file exists, just in case there were some problem with its creation. If there is no file I send an error message to the smartphone.
If the file exists we can try to send it. The statement is quite simple and you should just change the target phone number and the image filename to adapt to your system.
Afer the execution of the class an ImageSent exception is raised with the result of the operation. If there was any problem we can find the word "ERROR" inside the error value and we can send an error message.
Of course you can add some features by just checking for key words in the received message. For example you could add an option to take high resolution pictures or maybe one to take photos in low light conditions...
As i wrote, you can also send video and audio files. Just change the filename and the class will recognize what to send by checking the file extension.
These are the valid extension for the class:
So you could ask your RPi to make a video and send it to you, instead of a photo. Think about this setup:
A Raspberry Pi with a camera module mounted on a servo. You ask for a video and the script records it while rotating the camera. Then RPi will send a panoramic shot to your smartphone.
Another thing you could do (a bit less useful, bit nice!) is sending you vocal messages instead of text ones. You just need a tts engine able to create an audio file and change the Answer function to send the voice message.
In this case it would be useful to have the file in a compressed format to save space and reduce the time needed to send it (so avoid uncompressed wav if you can).
On one of the next posts I will describe how to install the Pico TTS engine from Android. This is a quite good engine, but unfortunately you can't install it in an easy way, so probably a post about its installation could be useful to some of you.
After closing the camera object I check if the picture file exists, just in case there were some problem with its creation. If there is no file I send an error message to the smartphone.
If the file exists we can try to send it. The statement is quite simple and you should just change the target phone number and the image filename to adapt to your system.
Afer the execution of the class an ImageSent exception is raised with the result of the operation. If there was any problem we can find the word "ERROR" inside the error value and we can send an error message.
Of course you can add some features by just checking for key words in the received message. For example you could add an option to take high resolution pictures or maybe one to take photos in low light conditions...
As i wrote, you can also send video and audio files. Just change the filename and the class will recognize what to send by checking the file extension.
These are the valid extension for the class:
- image: jpg, png
- audio: mp3, wav, aac, wma, ogg, oga
- video: mp4
So you could ask your RPi to make a video and send it to you, instead of a photo. Think about this setup:
A Raspberry Pi with a camera module mounted on a servo. You ask for a video and the script records it while rotating the camera. Then RPi will send a panoramic shot to your smartphone.
Another thing you could do (a bit less useful, bit nice!) is sending you vocal messages instead of text ones. You just need a tts engine able to create an audio file and change the Answer function to send the voice message.
In this case it would be useful to have the file in a compressed format to save space and reduce the time needed to send it (so avoid uncompressed wav if you can).
On one of the next posts I will describe how to install the Pico TTS engine from Android. This is a quite good engine, but unfortunately you can't install it in an easy way, so probably a post about its installation could be useful to some of you.
the code works fine, but no idea how to send image
ReplyDeletepls replay
thanks
You just need to have the image saved in the SD and then put the name of the file, with the full path if needed, in the SendMediaStack function. The script above is a bit more complex as I'm using the Raspberry camera to get the image file.
DeleteIn this function you also need to put the telephone number of the recipient an your credentials for Whatsapp connection (see the parser in a previous post to see the returned value of the credential()function).
The class for sending an image is a bit complex, but if you wish you can take a look inside the file wamedia.py...
thanks for your replay.
ReplyDeletein class SendMediaStack(object):
the name of the file, with the full path is put in the place of object?
pls replay
thanks
noufal
9744227909
Just look at the code above: create a new stack using the SendMediaStack with your Whatsapp credentials, the recipient number and the file path of the image, then you just start the stack. The rows are the following:
Deletestack = SendMediaStack(credential(), [(["390000000000", "lastimage.jpg"])])
stack.start()
stack = SendMediaStack(credential(), [(["390000000000", "lastimage.jpg"])])
Deletestack.start()
this code put inside the wamedia.py ?
lass SendMediaStack(object):
ReplyDeletedef __init__(self, credentials, messages):
layers=(SendMediaLayer,)+(YOWSUP_PROTOCOL_LAYERS_FULL,)+YOWSUP_CORE_LAYERS
self.stack=YowStack(layers)
self.stack.setProp(SendMediaLayer.PROP_MESSAGES,messages)
self.stack.setProp(YowAuthenticationProtocolLayer.PROP_PASSIVE,True)
self.stack.setProp(YowAuthenticationProtocolLayer.PROP_CREDENTIALS,credentials)
self.stack.setProp(YowNetworkLayer.PROP_ENDPOINT,YowConstants.ENDPOINTS[0])
self.stack.setProp(YowCoderLayer.PROP_DOMAIN,YowConstants.DOMAIN)
self.stack.setProp(YowCoderLayer.PROP_RESOURCE,env.CURRENT_ENV.getResource())
def start(self):
self.stack.broadcastEvent(YowLayerEvent(YowNetworkLayer.EVENT_STATE_CONNECT))
try:
self.stack.loop()
except AuthError as e:
print("Authentication Error: %s" % e.message)
this is your code and i put the code below this
stack = SendMediaStack(credential(), [(["390000000000", "lastimage.jpg"])])
stack.start()
this okey?
This comment has been removed by a blog administrator.
ReplyDeleteiam getting an error
ReplyDeletestack = SendMediaStack(credential(), [(["390000000000", "lastimage.jpg"])])
NameError: name 'credential' is not defined
no image is received
ReplyDeleteplease send a full working script to raspibian@gmail.com
ReplyDeletethanks
Example script (you should reading all the posts about Yowsup anyway):
Deletefrom wamedia import *
def credential():
return "391122334455","whatsapp_password" # Put your credentials here!
def sendphoto():
try:
stack = SendMediaStack(credential(), [(["390000000000", "/home/pi/image.jpg"])])
stack.start()
except ImageSent as e:
if ("ERROR" in e.value): print("Could not send the image!")
# Main program
sendphoto()
Note: unfortunately there is a problem with spaces. and the indentation was lost in the code above. Here I just replace them with underscores (of course you need to replace them with spaces!):
Deletefrom wamedia import *
def credential():
____return "391122334455","whatsapp_password" # Put your credentials here!
def sendphoto():
____try:
________stack = SendMediaStack(credential(), [(["390000000000", "/home/pi/image.jpg"])])
________stack.start()
____except ImageSent as e:
________if ("ERROR" in e.value): print("Could not send the image!")
# Main program
sendphoto()
pls replay
ReplyDeleteSorry, but I'm not always online, so I cannot always answer immediately...
Delete@Carlo Mascellani.
ReplyDeleteyour code wamedia.py works fine , i put receipt number and image file but no output,
This comment has been removed by a blog administrator.
ReplyDeletesir pls replay
ReplyDeleteNo handlers could be found for logger "ypwsup stscks yowstack"
Authentication Error: not-authorized
Just ignore the "No handlers..." message. This happens just because I'm not using any logging package for the script and it's just a warning.
DeleteThe problem is the Authentication Error message. There is something wrong in the credentials you put in the script. Are you sure you put the right phone number/password received when registering to Whatsapp?
thanks for ur replay
Deleteimage was sucessfully sended.
Sir,
ReplyDeleteOne more doubt, how to send a image to a group. It is possible?
If ur free then send a replay.
Thanks
This is possible, but I did not investigate how to make it and I do not think I will for now as it's not a feature that I need...
DeleteOk,
ReplyDeleteIn my project it's very use, but no idea how to get the group I'd. In above the number is replaced by group I'd ? It's possible?
Probably replacing the phone number with the group id will work...
ReplyDeletebut how to get the group id?
Deletepls replay
thanks
Actually I really do not know... Anyway you could try to:
Delete- After creating the group, try to send a message (from a smartphone included in the group of course) to the raspberry an look at the sender number. It should be the gid, but I cannot be really sure.
- Ask in the site of the creator of Yowsup (I'm just using this software and the people that coded it will surely know much better how it works)
- If still found nothing about the group id, you can always just send multiple messages with the same image to every needed recipient
ok , thanks for your replay.
ReplyDeleteone more help, in your previous post whatsapp for home automation the parser i get this error.
NameError: name 'received' is not defined
please replay
thanks
ok , thanks for your replay.
ReplyDeleteone more help, in your previous post whatsapp for home automation the parser i get this error.
NameError: name 'received' is not defined
please replay
thanks
Hi Carlo,
ReplyDeleteFirst of all thanks for these yowsup classes you wrote. I'm completely new to both python and yowsup, so this helped me an aweful lot to get something decent started in a relatively short amount of time.
In case you are still interested, I figured out how to send pictures (I guess this should work with any kind of media) to a group using your wamedia.py file. Like you said, you need the group id. To get it you need to get the phone number that was registered with yowsup to be invited to the group. Next, start up the yowsup client (yowsup-cli demos --config config --yowsup) and ask someone from the group to send a message. The yowsup-cli will listen for any incoming messages and print it along with the group ID in your terminal (it should look something like PHONENUMBER-TIMESTAMP@g-us.net).
Next you need to make a small edit to the wamedia.py file to get it to work. Line 106:
jid = ‘%s@s.whatsapp.net’ % jid
should be replaced by the following:
if '@' in jid:
____jid = jid
elif '-' in jid:
____jid = '%s@g.us' % jid
else:
____jid = '%s@s.whatsapp.net' % jid
Now you can just use the code as explained in the example and replace the target number by the group ID.
I am using yowsup and your classes for exactly that, sending pictures to a group and it has been working fine. I wanted to add a parser as well, so it could listen for incoming group message using your wareceive.py file, but I haven’t been able to get it to work yet. I keep receiving the same message(s) over and over again. Apparently wareceive is not able to send receipts to a group in a correct way. If you have any ideas how to fix it, let me know. Otherwise if you’re interested I can keep you updated in case I can figure it out myself. Either way, thanks again for the classes. Lots of fun :-)
cheers!
Francis
Thanks for sharing this info! This could surely help some other people searching how to to the same thing.
DeleteThanks carlo this thing work well for me. If anyone is using webcam instead of raspberry pi camera, try using fswebcam and change the code above like this:
ReplyDeletedef TakePhoto(received):
___Answer("Taking foto....")
___os.system("fswebcam -r 640x480 -S 20 foto.jpg")
___if os.path.exists("foto.jpg"):
_____try:
_______stack = SendMediaStack(credential(), [(["3900000000", "foto.jpg"])])
_______stack.start()
_____except ImageSent as e:
_______if ("ERROR" in e.value): Answer("Could not send the photo, sorry!")
__else:
_____Answer("I found no photo to send!")
__return
Well done! Thanks!
DeleteHelo,
ReplyDeleteYou have any idea about how to hack a wifi network??
Thanks
Sorry, no.
Deleteok
ReplyDeleteHi Carlo,
ReplyDeletehow I can receive messages on yowsup? that is sent from my smartphone to yowsup, help me please
Look at the other posts before this one. You will find how you can send and receive messages using yowsup.
DeleteAnyway note that yowsup seems to be a bit unstable and sometimes messages are lost. No documentation can be found for this library, so it's also difficult to use it.
hi,, Carlo Mascellani
ReplyDeletei try your wamedia.py
it works fine.. thanks for your work.
I try to modify your code to send the same image to many numbers (listed in .txt file)
i added following code in the main function
for line in cfile:
____number=line
____jid='%s@s.whatsapp.net' % number
____successFn=lambda successEntity, originalEntity: self.onRequestUploadResult(jid,path,successEntity,originalEntity)
____errorFn=lambda errorEntity,originalEntity: self.onRequestUploadError(jid,path,errorEntity,originalEntity)
____self._sendIq(entity,successFn,errorFn)
cfile.close()
but it doesn't work.
kindly reply..
how to send the same image to multiple number??
"successFn= ***** " in same line... it just preview problem..
DeleteGood Evening,
ReplyDeleteI try to run your examples, but in different ways, I got an error:
"bytearray object has no atributte tag"
due to, the image.jpg is not send to the whatsapp client.
it seems to conect to whatsapp server, and disconnect after that. I am doing debug with pdg, but I cant get the location or why that error appers, I got send text or any message, but not Image!!!
I reinstall twice, but It continues. Do you know something about that error??
Could someone help me.
Thanks.
Did you installed Pillow? This library is mandatory for managing images with Yowsup (I wrote about this at the beginning of the post).
DeleteIf this library is not available on your system there could be a issue like the one you see...
Thank you, It WORKS really fine, I installed everything in order. I received an image (on my smartphone, the photo looks dark, when I open I see the picture!!!).
DeleteI put this example on a loop to interact with the yowsup, in order to wait a word to send the photo when I want it, and sent a confirmation message. I am receiving only the photo. because in your example some atributes disconnect the comunication. and stop the whole program.
After debugging, I found that on the class associate to sendImage, an interruption occurs and I lose the connection. in order to keep ask for a photo. (send the photo and stop)
Do you know how I fix it?, I meant, Run the example code on a loop in order to wait for a word ("photo"), and after that, in my code execute a capture and send image to whatsapp, but continues on the loop waiting for other photo request.
I apprecite your help.
To exit from the stack loop an exception is raised with a text that tells why we exited.
DeleteMEDIA SENT means the image has been sent correctly, ERROR UPLOAD mean that something goes wrong.
In the main script (where your loop is) you should catch this exception (look at my example script above, you will see the try...except statements). You do not need to do something inside the except, but the statement must be there, otherwise your script will terminate because of the unhandled exception.
Hi there, first of all, congratulations for your library, it's working perfectly, but I need to put the function that sends images inside a python application, inside a loop, but when the command SendMediaStack is executed and the image is sent, it breaks the execution of the program. Any suggestions?
ReplyDeleteDid you installed also the Pillow library? Maybe that's the problem.
DeleteIn case they are installed, you should give some more info about the error or it would be impossible to find what's wrong...
every thing went well but i had an error ping thread stopped can some one here solve it
ReplyDeleteHello. I need help with this error:
ReplyDeletesudo python wamediasend.py
No handlers could be found for logger "yowsup.stacks.yowstack"
Traceback (most recent call last):
File "wamediasend.py", line 14, in
sendphoto()
File "wamediasend.py", line 8, in sendphoto
stack = SendMediaStack(credential(), [(["390000000000", "/home/pi/image.jpg"])])
File "/home/pi/yowsup/wamedia.py", line 130, in __init__
self.stack.setProp(YowCoderLayer.PROP_RESOURCE,env.CURRENT_ENV.getResource())
AttributeError: 'module' object has no attribute 'CURRENT_ENV'
Is Pillow installed? If not install it, if yes try updating yowsup.
DeleteI got the same error. yowsup is updated and pillow too.
Deletesudo python z_sendimage.py
No handlers could be found for logger "yowsup.stacks.yowstack"
Traceback (most recent call last):
File "z_sendimage.py", line 14, in
sendphoto()
File "z_sendimage.py", line 8, in sendphoto
stack = SendMediaStack(credential(), [(["491604111780", "/home/pi/yowsup/test.jpg"])])
File "/home/pi/yowsup/z_wamedia.py", line 130, in __init__
self.stack.setProp(YowCoderLayer.PROP_RESOURCE,env.CURRENT_ENV.getResource())
AttributeError: 'module' object has no attribute 'CURRENT_ENV'
I have the solution :)
DeleteChange
from yowsup.env import YowsupEnv
to
from yowsup import env
and
self.stack.setProp(YowCoderLayer.PROP_RESOURCE,env.CURRENT_ENV.getResource())
to
self.stack.setProp(YowCoderLayer.PROP_RESOURCE, YowsupEnv.getCurrent().getResource())
pls update your script :)
Probably something changed in Yowsup since I created the scripts. Thanks for you info. Now the script is updated.
DeleteIt seems related to the yowsup version. This happened to other people and the answer in the yowsup is:
ReplyDelete"Its related to the yowsup version you are using. the param order is different. just look at the error and debug it."
if your yowsup version is the latest, probably they changed something in the syntax. Otherwise you can try to update your yowsup
Really useful post. I am trying to send video. But getting exception ERROR REQUEST VIDEO.Please help me.
ReplyDeleteUnfortunately I'm not using yowsup anymore, so cannot help. You can check the following things:
Delete- is your yowsup updated to latest version?
- is the video in mp4 format?
- can you open with python (as a file, no need to actually play it)?
Also please note that since i wrote the article above something could have been changed, so it could be a good idea to check the developers page for news, guides and help.