Raspberry PI – Doing Automation

… 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).

schema

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.

Advertisements
Tagged with: , , , ,
Posted in Raspberry PI
%d bloggers like this: