Skip to content

Commit 0711710

Browse files
author
Jason Mechler
committed
made significant changes to stock google calendar demo, including
- add support for google api v3 - pull common config items from environment variables (can be set in /etc/default/ospi_gc if running as a service - add /etc/init.d/ospi_gc to run as a service - add example /etc/default/ospi_gc to configure calendar id, log levels, etc. - generate daily logs using standard python logging functionality - send email on startup/shutdown/fatal errors
1 parent 4859459 commit 0711710

File tree

4 files changed

+365
-66
lines changed

4 files changed

+365
-66
lines changed

OpenSprinkler Pi/software/demos/gcalendar/README.txt

+29-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
============================================
22
OpenSprinkler Pi (OSPi) Google Calendar Demo
3-
Feb 2013, http://rayshobby.net
3+
Feb 2015, http://rayshobby.net
44
============================================
55

66
SPECIAL NOTE
@@ -30,32 +30,53 @@ This demo makes use of a public Google calendar to program water events. To do s
3030
Using the Google calendar provides the advantage that you can easily set recurring events. Also, you can access Google calendar on both desktop and mobile computers. It is a convenient and suitable interface for programming complex water schedules.
3131

3232

33+
3334
Preparation
3435
-----------
3536
1. Before running this demo, it is assumed that you have the RPi.GPIO Python module installed (which should come by default with the latest raspbian distribution).
3637

38+
2. In addition, you need to install the Google Client Library using the instructions at
39+
https://developers.google.com/api-client-library/python/
3740

38-
2. In addition, you need to install the Google Data (gdata) API Python module, available at:
39-
http://code.google.com/p/gdata-python-client/downloads/list
41+
3. As of Nov 17, 2014, Google has deprecated the Google Calendar API v2. In order to use v3 of the API, you MUST obtain a google API key. See https://developers.google.com/console/help/new/?hl=en_US#generatingdevkeys for more information
4042

43+
4. The required settings below are controlled by environment variables. These can be set in /etc/default/ospi_gc if running as a service or just set in your profile or on the command line
4144

42-
3. As mentioned above, you need to create a Google calendar, set it to be public, and copy the calendar ID (available in the calendar settings page) to the correpsonding location in ospi_gc.py. For exmaple:
45+
4.a. OSPI_API_KEY: as mentioned in step 3.
4346

44-
CALENDAR_ID = 'ma2lg95i25jantdiciij85aq0s@group.calendar.google.com'
47+
export OSPI_API_KEY='abcdefghijklmnopqrstuvwxyz1234567890123'
4548

46-
The reason to set the calendar public is to avoid the complexity of account authentication. If you need, you can also use a private calendar, but in that case you should follow the Google Data API for the appropriate authentication procedure.
49+
4.b. OSPI_CALENDAR_ID: As mentioned above, you need to create a Google calendar, set it to be public, and set copy the calendar ID (available in the calendar settings page) to the correpsonding location in ospi_gc.py. For example:
4750

51+
export OSPI_CALENDAR_ID = 'abcdefghijklmnopqrstuvwxyz@group.calendar.google.com'
52+
53+
The reason to set the calendar public is to avoid the complexity of account authentication. If you need, you can also use a private calendar, but in that case you should follow the Google Data API for the appropriate authentication procedure.
4854

49-
4. Next, set desired station names in ospi_gc.py. For each station, provide the station name and the corresponding station index (the first station is indexed 0). The station name will be used to match the Google calendar event title, and if a match is found, the corresponding station will be set to open. For example, an event named 'Front Yard' scheduled for every Monday morning from 9am to 10am will trigger the Front Yard station weekly during the designated time.
55+
4.c. OSPI_MAX_STATION: The highest status number you will be using
56+
4.d. OSPI_STATION_0 - OSPI_STATION_N: Set desired station names. For each station, set an environment variable with a comma separate list of aliases you'd like to use for that station. (the first station is indexed 0). The station name will be used to match the Google calendar event title, and if a match is found, the corresponding station will be set to open. For example, an event named 'Front Yard' scheduled for every Monday morning from 9am to 10am will trigger the Front Yard station weekly during the designated time.
5057

5158
Note that the station names are ***case sensitive***. So 'Front Yard' is different from 'Front yard'. Also, 'Front Yard' is different from 'FrontYard'. So be careful, otherwise the program will not be able to match the calendar events correctly.
5259

5360
Note that you can map multiple names to the same station. For example, map 'Front Yard', 'FrontYard', 'Front_Yard' all to index 1. This can help avoid mismatches if you don't remember the name exactly.
5461

62+
export OSPI_MAX_STATION=5
63+
export OSPI_STATION_0="frontyard,front yard"
64+
export OSPI_STATION_1="backyard,back yard"
65+
export OSPI_STATION_2="northside,north side"
66+
export OSPI_STATION_3="southside,south side"
67+
export OSPI_STATION_4="frontflowers,front flowers"
68+
export OSPI_STATION_5="pool"
69+
70+
5. Optional configuration variables for logging and email notification.
71+
72+
5.a. OSPI_LOG_LEVEL: set to standard text or numeric values described at https://docs.python.org/2/library/logging.html#logging-levels. defaults to INFO.
73+
74+
5.b. OSPI_EMAIL_FROM, OSPI_EMAIL_TO: If these are set, you will receive an email when the application starts up, shuts down, or receives a fatal error during startup. You will need to have configured exim or some other MTA to be able to send mail.
75+
5576

5677
Running the Demo
5778
----------------
58-
To run the demo, type in command line:
79+
To run the demo, set the appropriate environment variables and type in command line:
5980
> sudo python ospi_gc.py
6081

6182
The program will check the specified Google calendar once every minute (60 seconds). The frequency can be increased or decreased by modifying the sleep() time in the source code. All events that overlap with the current time will trigger the corresponding stations.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# put your Google API Key here
2+
export OSPI_API_KEY='abcdefghijklmnopqrstuvwxyz1234567890123'
3+
4+
# put your public calendar id here
5+
export OSPI_CALENDAR_ID='abcdefghijklmnopqrstuvwxzy12345678901@group.calendar.google.com'
6+
7+
# Email Config
8+
# export OSPI_EMAIL_FROM="pi@ospi.yourdomain.ospi"
9+
# export OSPI_EMAIL_TO="you@wherever.you.get.email.com"
10+
11+
export OSPI_MAX_STATION=5
12+
export OSPI_STATION_0="frontyard,front yard"
13+
export OSPI_STATION_1="backyard,back yard"
14+
export OSPI_STATION_2="northside,north side"
15+
export OSPI_STATION_3="southside,south side"
16+
export OSPI_STATION_4="frontflowers,front flowers"
17+
export OSPI_STATION_5="pool"
18+
19+
export OSPI_LOG_LEVEL=DEBUG
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#! /bin/sh
2+
### BEGIN INIT INFO
3+
# Provides: ospi_gc
4+
# Required-Start: $remote_fs $syslog
5+
# Required-Stop: $remote_fs $syslog
6+
# Default-Start: 2 3 4 5
7+
# Default-Stop: 0 1 6
8+
# Short-Description: OpenSprinkler + Raspberry Pi + GoogleCalendar
9+
# Description: OpenSprinkler + Raspberry Pi + GoogleCalendar -
10+
# Raspberry Pi with OpenSprinkler Pi board from Ray's Hobby
11+
# and google calendar integratoin
12+
### END INIT INFO
13+
14+
#
15+
# To auto start on boot execute (once) as root
16+
#
17+
# update-rc.d ospi_gc defaults
18+
#
19+
# To stop auto start on boot execute
20+
#
21+
# update-rc.d ospi_gc remove
22+
#
23+
24+
# Author: Jason Mechler <github at jasonmechler.fastmail.fm>
25+
#
26+
# Please remove the "Author" lines above and replace them
27+
# with your own name if you copy and modify this script.
28+
29+
# Do NOT "set -e"
30+
31+
# PATH should only include /usr/* if it runs after the mountnfs.sh script
32+
PATH=/sbin:/usr/sbin:/bin:/usr/bin
33+
DESC="OpenSprinkler Raspberry Pi Google Calendar"
34+
NAME=ospi_gc
35+
DAEMON=/usr/bin/python
36+
DAEMON_ARGS="ospi_gc.py"
37+
HOMEDIR=/home/pi/demo/gcalendar # Edit if different on your Raspberry Pi
38+
PIDFILE=/var/run/$NAME.pid
39+
SCRIPTNAME=/etc/init.d/$NAME
40+
41+
# Exit if the package is not installed
42+
[ -x "$DAEMON" ] || exit 0
43+
44+
# Read configuration variable file if it is present
45+
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
46+
47+
# Load the VERBOSE setting and other rcS variables
48+
. /lib/init/vars.sh
49+
50+
# Define LSB log_* functions.
51+
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
52+
# and status_of_proc is working.
53+
. /lib/lsb/init-functions
54+
55+
#
56+
# Function that starts the daemon/service
57+
#
58+
do_start()
59+
{
60+
# Return
61+
# 0 if daemon has been started
62+
# 1 if daemon was already running
63+
# 2 if daemon could not be started
64+
start-stop-daemon --start --quiet --chdir $HOMEDIR --pidfile $PIDFILE --make-pidfile --background --exec $DAEMON --test > /dev/null \
65+
|| return 1
66+
start-stop-daemon --start --quiet --chdir $HOMEDIR --pidfile $PIDFILE --make-pidfile --background --exec $DAEMON -- \
67+
$DAEMON_ARGS \
68+
|| return 2
69+
# Add code here, if necessary, that waits for the process to be ready
70+
# to handle requests from services started subsequently which depend
71+
# on this one. As a last resort, sleep for some time.
72+
}
73+
74+
#
75+
# Function that stops the daemon/service
76+
#
77+
do_stop()
78+
{
79+
# Return
80+
# 0 if daemon has been stopped
81+
# 1 if daemon was already stopped
82+
# 2 if daemon could not be stopped
83+
# other if a failure occurred
84+
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
85+
RETVAL="$?"
86+
[ "$RETVAL" = 2 ] && return 2
87+
# Wait for children to finish too if this is a daemon that forks
88+
# and if the daemon is only ever run from this initscript.
89+
# If the above conditions are not satisfied then add some other code
90+
# that waits for the process to drop all resources that could be
91+
# needed by services started subsequently. A last resort is to
92+
# sleep for some time.
93+
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
94+
[ "$?" = 2 ] && return 2
95+
# Many daemons don't delete their pidfiles when they exit.
96+
rm -f $PIDFILE
97+
return "$RETVAL"
98+
}
99+
100+
#
101+
# Function that sends a SIGHUP to the daemon/service
102+
#
103+
do_reload() {
104+
#
105+
# If the daemon can reload its configuration without
106+
# restarting (for example, when it is sent a SIGHUP),
107+
# then implement that here.
108+
#
109+
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
110+
return 0
111+
}
112+
113+
case "$1" in
114+
start)
115+
log_daemon_msg "Starting $DESC" "$NAME"
116+
do_start
117+
case "$?" in
118+
0|1) log_end_msg 0 ;;
119+
2) log_end_msg 1 ;;
120+
esac
121+
;;
122+
stop)
123+
log_daemon_msg "Stopping $DESC" "$NAME"
124+
do_stop
125+
case "$?" in
126+
0|1) log_end_msg 0 ;;
127+
2) log_end_msg 1 ;;
128+
esac
129+
;;
130+
status)
131+
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
132+
;;
133+
#reload|force-reload)
134+
#
135+
# If do_reload() is not implemented then leave this commented out
136+
# and leave 'force-reload' as an alias for 'restart'.
137+
#
138+
#log_daemon_msg "Reloading $DESC" "$NAME"
139+
#do_reload
140+
#log_end_msg $?
141+
#;;
142+
restart|force-reload)
143+
#
144+
# If the "reload" option is implemented then remove the
145+
# 'force-reload' alias
146+
#
147+
log_daemon_msg "Restarting $DESC" "$NAME"
148+
do_stop
149+
case "$?" in
150+
0|1)
151+
do_start
152+
case "$?" in
153+
0) log_end_msg 0 ;;
154+
1) log_end_msg 1 ;; # Old process is still running
155+
*) log_end_msg 1 ;; # Failed to start
156+
esac
157+
;;
158+
*)
159+
# Failed to stop
160+
log_end_msg 1
161+
;;
162+
esac
163+
;;
164+
*)
165+
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
166+
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
167+
exit 3
168+
;;
169+
esac
170+
171+
:

0 commit comments

Comments
 (0)