… Or how to eMail the PI to sprinkle your grass.
Welcome to the 3rd and last part of this integrated project I started with the Raspberry Pi – Surveillance WebCam in the Cloud and continued with the Raspberry PI – Temperature and Humidity sensor
Now let’s consider the following case: You left home for vacation. And you check on the dropbox and notice that the images uploaded by your Surveillance Camera show that the grass is no longer that green as when you left. And the weather chart shows also high temperature / low humidity over the last days. What’s the first thing which comes into your mind you’d like to do asap, right that evening already ? BINGO ! You’d like to be able to sprinkle your grass remotely from your vacation.
Well, this is the point on this project here. Control the PI over eMail and let it perform automation tasks, in this case to sprinkle the water, when you want it and for the duration you need.
I’ll again start with the acknowledgments and the hardware:
– Many thanks to my friend MHT for giving a helpful hand on the electronic part
– http://www.magnetventile-shop.de for their friendly and prompt service (This is the electro-valve I bought from them)
– yoctopuce.com for their Yocto-Relay (great quality and at least for me, idiot safe :))
And btw of hardware, the next step would be to present the schema for this project. Before doing it, please let me again explicitly point you to the License page and especially on this part, relevant also for the hardware-related points I present here:
THIS INFORMATION IS PROVIDED BY JASM.EU ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JASM.EU BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS INFORMATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Or shorter: “Use your head !; There is no guarantee for information I post here; It’s YOUR responsibility to make it right !”
Ok, that’s being said, this is what you’ll see in the schema below:
– A 12 V DC source (I took it for example from an old external DVD writer)
– a switch: In this case one port of the Yocto-Relay module
– a solenoid: The one from the above mentioned (12 DC !) electro-valve
– a diode. See details on why this diode is needed in the Yocto Relay User Manual on page 15, chapter 5.3. The diode I use is the one here P6KE15A. If you consider using another voltage on the source (and electro-valve), consider using a diode supporting that voltage ! (for example if you’ll play with 24 V, this diode here will burn).
I btw use 3 electro-valves and 2 Yocto-Relays, but I guess the idea for 1 Relay / 1 electro-valve is clear from the schema above.
As the most complex part is over, we’ll move ahead to easier aspects: the software.
There are many possibilities to control the Yocto Modules: using a web interface (called Virtual Hub), or using several libraries for most important programming languages or using small Linux applications provided by Yoctopuce. See Yoctopuce for details.
Taking into account that the PI is just a tiny machine whose resources should not be wasted, I ignored the Virtual Hub (who needs a web app on PI ?) and I considered the command line library provided by Yoctopuce.
and here are some commands you may want to use right after unpacking a new Yocto-Relay
sudo yocto_libs/lib/Binaries/linux/armhf/YModule inventory #-> shows you what Yocto Modules are connected to the system.
sudo yocto_libs/lib/Binaries/linux/armhf/YModule RELAYLO1-0D89F set_logicalName hugo1 #-> set a logical name to a module; Btw RELAYLO1-0D89F was the ID of the module as shown by the inventory
sudo yocto_libs/lib/Binaries/linux/armhf/YModule inventory #-> you may see the name was set
sudo yocto_libs/lib/Binaries/linux/armhf/YModule RELAYLO1-0D89F saveToFlash #-> you save the new name to module's flash, to have it available also for latter.
sudo yocto_libs/lib/Binaries/linux/armhf/YRelay inventory #-> see what Yocto Relays are connected to the system
sudo yocto_libs/lib/Binaries/linux/armhf/YRelay RELAYLO1-0D89F.relay1 set_logicalName p1 #-> set a logical name to one of the relays
sudo yocto_libs/lib/Binaries/linux/armhf/YRelay RELAYLO1-0D89F.relay2 set_logicalName p2 #-> Yup ! This sets the logical name for the second relay
sudo yocto_libs/lib/Binaries/linux/armhf/YModule RELAYLO1-0D89F saveToFlash #-> And again save everything to flash
sudo yocto_libs/lib/Binaries/linux/armhf/YRelay hugo1.p1 delayedPulse 10000 120000
This last command is THE ONE. It waits 10 seconds, and then switches the input of the “hugo1.p1” relay to the output B for 120 seconds. (By default the input is routed to the Output A, which stays in our schema unconnected) This command is the key command for the script below as it turns the solenoid on for n seconds, after waiting m seconds.
Ok, so here is the script. As always, the License applies to this script, too:
#!/bin/bash source /home/pi/dev/water/vars4parse echo "Received water command at: "$(date +"%Y%m%d_%H%M%S") > $tmpLog echo "And the protocol: " > $tmpLogCmd if [ -e $lockFile ]; then #we maybe have to stop a previous process for j in `seq $countm` do dev=m$j eval dev=\$$dev cmd="init" cmd_=$yoctodir"YModule "$dev" reboot 1" dev2="OK: "$dev until [[ "$cmd" == *"$dev2"* ]]; do echo "sudo "$cmd_ >> $tmpLogCmd cmd=$(sudo $cmd_) echo $cmd >> $tmpLogCmd done done oldDeadline=$(head -n 1 $lockFile) echo "I already had a running water process with end time on: "$(date -d @$oldDeadline +"%Y%m%d_%H%M%S")" so I had to reboot the modules" >> $tmpLog rm $lockFile fi countParams=-1 emailAdr="" for tmp in "$@" do let countParams=countParams+1 if [ $countParams -eq 0 ]; then emailAdr=$tmp else if echo $tmp | egrep -q '^[0-9]+$'; then #echo $tmp" is a number" param[$countParams]=$tmp else param[$countParams]=0 fi fi #echo ${param[$countParams]} done #ok, so far, so good; we stored all the input parameters let countParams=countParams-1 #we decrease by 1 because the first value must be the waitTime before start if [ $countParams -gt $counts ]; then let countParams=counts fi #This is what we must call: sudo ./YRelay hugo1.p1 delayedPulse 10000 120000 let waitTime=${param[1]}*60*1000 #we assume the input time is in minutes if [ $waitTime -eq 0 ]; then waitTime=5000 #5 second wait time before start fi #echo $waitTime echo "And here is what I do:" >> $tmpLog let maxmili=$maxminutes*60*1000 for jj in `seq $countParams` do let j=jj+1 let length=${param[$j]}*60*1000 #we assume the input time is in minutes if [ $length -gt $maxmili ]; then length=$maxmili #but no more than maxmili fi dev=s$jj eval dev=\$$dev cmd_=$yoctodir"YRelay "$dev" delayedPulse "$waitTime" "$length #echo $cmd_ if [ $length -gt 0 ]; then cmd="init" dev2="OK: "$dev until [[ "$cmd" == *"$dev2"* ]]; do echo "sudo "$cmd_ >> $tmpLogCmd cmd=$(sudo $cmd_) echo $cmd >> $tmpLogCmd done fi let waitMin=$waitTime/60/1000; let lengMin=$length/60/1000; echo $dev" waits "$waitMin" minutes and then runs "$lengMin" minutes." >> $tmpLog let waitTime=waitTime+length+5000 #we wait 5 seconds between one device and the next done myTime=$(date +"%s") #echo $myTime let myTime=myTime+waitTime/1000 echo $myTime > $lockFile echo $emailAdr >> $lockFile echo "Ok, all the timers are set. Everything will finish by "$(date -d @$myTime +"%Y%m%d_%H%M%S") >> $tmpLog let myTime=$myTime+3599 let myTime=$myTime/3600 let myTime=$myTime*3600 echo "At: "$(date -d @$myTime +"%Y%m%d_%H%M%S")" you will get another mail as confirmation that everything was stopped." >> $tmpLog tmpMail="/var/tmp/mailtxt3.txt" echo "To: "$emailAdr > $tmpMail echo "From: my_PI_email_address@gmail.com" >> $tmpMail echo "Subject: Feedback of Water" >> $tmpMail echo "" >> $tmpMail cat $tmpLog >> $tmpMail echo "-------------------------" >> $tmpMail cat $tmpLogCmd >> $tmpMail /usr/sbin/ssmtp $emailAdr < $tmpMail rm $tmpMail rm $tmpLog rm $tmpLogCmd
Several aspects on the code above:
– The script starts with parameters in the command line:
./script.sh email_add_to_send_confirmation_and_log@gmail.com wait_time duration_ON_for_the_first_relay duration_ON_for_the_second_relay duration_ON_for_the_nth_relay
– The script may get durations for n relays and apply them to the n relays. as I said, I use 3 relays and 3 electro-valves
– The script programs the relays to become active one after the other. That is, the first one waits “wait_time” and then becomes active for “duration_ON_for_the_first_relay”, the second one waits “wait_time + duration_ON_for_the_first_relay” and then becomes active for “duration_ON_for_the_second_relay” and so on.
The reason for this is that the water throughput in my pipe does not allow me to water 2 areas at the same time. So they must start one after the other.
– If the modules are active when a new command is received, the script will first reboot the modules and then will program them for the new session. Remember that a reboot means routing the input on the A output, that is to power off all the solenoids.
– In the end, a mail is sent to the “email_add_to_send_confirmation_and_log@gmail.com” mentioned as first line parameter containing details on what was done and also the log for the communication with the Yocto Modules.
Something like this will be sent via eMail:
Received water command at: 20130711_224604
I already had a running water process with end time on: 20130711_224858 so I had to reboot the modules
And here is what I do:
hugo1.p1 waits 0 minutes and then runs 1 minutes.
hugo1.p2 waits 1 minutes and then runs 1 minutes.
hugo2.p1 waits 2 minutes and then runs 1 minutes.
Ok, all the timers are set. Everything will finish by 20130711_224940
At: 20130711_230000 you will get another mail as confirmation that everything was stopped.
-------------------------
And the protocol:
sudo yocto_libs/lib/Binaries/linux/armhf/YModule hugo1 reboot 1
OK: hugo1.reboot = 1
sudo yocto_libs/lib/Binaries/linux/armhf/YModule hugo2 reboot 1
OK: hugo2.reboot = 1
sudo yocto_libs/lib/Binaries/linux/armhf/YRelay hugo1.p1 delayedPulse 5000 60000
OK: hugo1.p1.delayedPulse = 5000,60000
sudo yocto_libs/lib/Binaries/linux/armhf/YRelay hugo1.p2 delayedPulse 70000 60000
OK: hugo1.p2.delayedPulse = 70000,60000
sudo yocto_libs/lib/Binaries/linux/armhf/YRelay hugo2.p1 delayedPulse 135000 60000
OK: hugo2.p1.delayedPulse = 135000,60000
Here is the parameters file: source /home/pi/dev/water/vars4parse
#!/bin/bash yoctodir=/home/pi/dev/yocto_libs/lib/Binaries/linux/armhf/ lockFile=/home/pi/dev/water/lock.data tmpLog=/home/pi/dev/water/log.data tmpLogCmd=/home/pi/dev/water/log2.data countm=2 counts=3 m1=hugo1 #identified by calling sudo ./YModule inventory in the yoctodir m2=hugo2 s1=hugo1.p1 s2=hugo1.p2 #identified by calling sudo ./YRelay inventory s3=hugo2.p1 maxminutes=120
(Btw, I again use the CodeHTMLer service)
With countm I specify the number of modules, with counts the number of relays (switches), with m* the logical names for the modules and with s* the logical names for the relays. Feel free to adjust it to your needs. I hope the script above should work also with countm=1 and counts=1 🙂
And now, in the end, one more script.
Let’s think about the small story in the beginning of this post: Would you let your PI sprinkle your garden while you’re in vacation, and trust it also STOPS ? 24 h x 10 days of running water could not only provide you with a fat bill, but also may turn your house and garden into a small Venice till you come back home.
If not, here is the solution: A script is being started by cron every hour. If it runs just after a sprinkle sequence should have stopped, it reboots all the modules and then mails to the “email_add_to_send_confirmation_and_log@gmail.com” address mentioned above the status of the modules.
Here is the script:
#!/bin/bash source /home/pi/dev/water/vars4parse if [ ! -e $lockFile ]; then #nothing to do exit fi if [ -e $tmpLog ]; then #probably the process is running right now. exit fi oldDeadline=$(head -n 1 $lockFile) nowTime=$(date +"%s") if [ $nowTime -gt $oldDeadline ]; then #ok, so we are past the expected finish point for a process; we may restart everything echo "It's "$(date +"%Y%m%d_%H%M%S")" and we make sure the water process has finished" > $tmpLog echo "The water process was active till: "$(date -d @$oldDeadline +"%Y%m%d_%H%M%S") >> $tmpLog echo "And the protocol: " > $tmpLogCmd emailAdr=$(tail -n 1 $lockFile) for j in `seq $countm` do dev=m$j eval dev=\$$dev cmd="init" cmd_=$yoctodir"YModule "$dev" reboot 1" dev2="OK: "$dev until [[ "$cmd" == *"$dev2"* ]]; do echo "sudo "$cmd_ >> $tmpLogCmd cmd=$(sudo $cmd_) echo $cmd >> $tmpLogCmd done done for j in `seq $counts` do dev=s$j eval dev=\$$dev cmd="init" cmd_=$yoctodir"YRelay "$dev" get_State" dev2="OK: "$dev until [[ "$cmd" == *"$dev2"* ]]; do echo "sudo "$cmd_ >> $tmpLogCmd cmd=$(sudo $cmd_) echo $cmd >> $tmpLogCmd done if [[ "$cmd" == *'state = A'* ]]; then echo $dev" is OFF" >> $tmpLog else echo "WARNING !!! "$dev" is still ON" >> $tmpLog fi done tmpMail="/var/tmp/mailtxt3.txt" echo "To: "$emailAdr > $tmpMail echo "From: my_PI_email_address@gmail.com" >> $tmpMail echo "Subject: Confirmation of Water" >> $tmpMail echo "" >> $tmpMail cat $tmpLog >> $tmpMail echo "-------------------------" >> $tmpMail cat $tmpLogCmd >> $tmpMail /usr/sbin/ssmtp $emailAdr < $tmpMail rm $tmpMail rm $tmpLog rm $tmpLogCmd rm $lockFile fi
The mail it sends is like this:
It's 20130711_230001 and we make sure the water process has finished
The water process was active till: 20130711_224940
hugo1.p1 is OFF
hugo1.p2 is OFF
hugo2.p1 is OFF
-------------------------
And the protocol:
sudo yocto_libs/lib/Binaries/linux/armhf/YModule hugo1 reboot 1
OK: hugo1.reboot = 1
sudo yocto_libs/lib/Binaries/linux/armhf/YModule hugo2 reboot 1
OK: hugo2.reboot = 1
sudo yocto_libs/lib/Binaries/linux/armhf/YRelay hugo1.p1 get_State
OK: hugo1.p1.get_state = A
sudo yocto_libs/lib/Binaries/linux/armhf/YRelay hugo1.p2 get_State
OK: hugo1.p2.get_state = A
sudo yocto_libs/lib/Binaries/linux/armhf/YRelay hugo2.p1 get_State
OK: hugo2.p1.get_state = A
And really-really the last part is the integration into the mail receiving / parsing module (for details, see Raspberry Pi – Send and receive (g)Mail)
This code should parse the input mail and react correctly if the Subject starts with “Water “:
echo $task | grep "water" > /dev/null if [ $? -eq 0 ]; then echo $task | grep "waterstop" > /dev/null if [ $? -eq 0 ]; then #reboot the module sendMail $sender "WaterStop - Feature not yet implemented" else #we start the water /home/pi/dev/water/water_start $sender ${task:6} fi fi
Ok, the Waterstop command should still be implemented to provide a sort of “handbrake” for this project, but as workaround also a “water 0 1 0 0” should do the trick. It would reboot the modules, and then let only the first relay run for just one minute, which is in this case an acceptable workaround for the time being. Stay tuned for an update …
And last but not least, for questions, advices, requests, recommendations, please use the Raspberry PI forum.