#! /usr/bin/python2
#######################################################
# File: ben.py
# Author: Benjamin Bordonaro
# Copyright: copyright 2011-2012
# Source: http://www.benjaminbordonaro.com
# Version: 12.09.19
# Features:
# – Integration of PogoPlug ArchLinuxARM, Arduino Uno
# – Compatibility with Temperature Sensor Readings
# – Bi-directional communication for LCD display
# – Email and Text Alerts for High and Low Temperatures
# – Bidirectional communication between PogoPlug Linux server
# and Arduino
# – Web access from Apple iPhone and iPad
# – Data Logging and Analysis using RRDTool
# – Webcam support
# – Email Support (POP and SMTP)
# – FTP Support
# – Weather Support (upgraded to xml.dom)
# – Data file for most recent information
# – Reporting Module
# – Custom Configuration Options
#
# Code Credits:
# – Weather upgrade to use xml.dom
# Matthew Petroff (http://www.mpetroff.net/)
#######################################################
# Import Libaries
import datetime # datetime library
import serial # pyserial
from smtplib import SMTP # email/smtp
import ftplib # ftp (file transfer)
import poplib # pop email access
import time # date time
import rrdtool # rrdtool
import platform # platform info
import urllib2 # http url library
import ConfigParser # to read ini file
from email.MIMEText import MIMEText # email format
from xml.dom import minidom # XML Library
import codecs # Codec Library
#######################################################
# Read in configuration file using Config Parser
aConfig = ConfigParser.RawConfigParser()
aConfig.read(‘/srv/arduino/settings.cfg’)
#aConfig.get(‘prd’, ‘config’)
#######################################################
#Program Name – used for messages, alerts, etc.
myPN = aConfig.get(‘prd’, ‘appname’)
myVer = aConfig.get(‘prd’, ‘appversion’)
myAppVer = aConfig.get(‘prd’, ‘appversion’)
myAppLabel = aConfig.get(‘prd’, ‘applabel’)
myAppServer = aConfig.get(‘prd’, ‘appserver’)
#######################################################
# App Configuation
#######################################################
# 12.03.08 moved configuration to settings.cfg
#Alerts level for Temperature
alertHighTemp = aConfig.getfloat(‘prd’, ‘alerthightemp’)
alertLowTemp = aConfig.getfloat(‘prd’, ‘alertlowtemp’)
# Web Camera (Enable = 1, Disable = 0)
myWebcamera = aConfig.getint(‘prd’, ‘webcamera’)
# Arduino (Enable = 1, Disable = 0)
myArduino = aConfig.getint(‘prd’, ‘arduino’)
mySerial = aConfig.getint(‘prd’, ‘serial’)
# Debugging (Enable = 1, Disable = 0
myDebug = aConfig.getint(‘prd’, ‘debug’)
# Email Checking (Enable = 1, Disable = 0)
myEmail = aConfig.getint(‘prd’, ’email’)
# FTP (Enable = 1, Disable = 0)
myFTP = aConfig.getint(‘prd’, ‘ftp’)
# Internet IP Checking (Enable = 1, Disable = 0)
myIP = aConfig.getint(‘prd’, ‘ip’)
myIPPort = aConfig.get(‘prd’, ‘hostipport’)
# Write Message File (Enable = 1, Disable = 0)
myMsg = aConfig.getint(‘prd’, ‘messages’)
# Retrieve Weather from Google (Enable = 1, Disable = 0)
myWeather = aConfig.getint(‘prd’, ‘weather’)
myWeatherLon = aConfig.get(‘prd’, ‘weatherlon’)
myWeatherLat = aConfig.get(‘prd’, ‘weatherlat’)
# Build and save report (Enable = 1, Disable = 0)
# Text Alerts (Enable = 1, Disable = 0)
myReport = aConfig.getint(‘prd’, ‘reports’)
myTxtAlerts = aConfig.getint(‘prd’, ‘txtalerts’)
myAlertsAll = aConfig.getint(‘prd’, ‘alertsall’)
# Time to Send Report via Email
myReportTime = aConfig.get(‘prd’, ‘reporttime’)
#######################################################
# Variables
logdata1 = “”
msg1 = “”
myReportBody = “”
myReportBreak = “——————————————-“
#######################################################
# serial port of Arduino on ArchLinux ARM server
# Usually it is /dev/ttyACM0
if mySerial == 1:
ser = serial.Serial(‘/dev/ttyACM0’, 9600)
#######################################################
#Functions
#######################################################
def ams_email_check():
mprt = 110
mbox = poplib.POP3_SSL(aConfig.get(‘prd’, ’emailpopsrvr1′))
mbox.getwelcome()
mbox.user(aConfig.get(‘prd’, ’emailuser1′))
mbox.pass_(aConfig.get(‘prd’, ’emailpass1′))
mstat = mbox.stat()
print(mstat)
messageCount = len(mbox.list()[1])
print(str(messageCount) + ” Email Message(s)”)
rvalue = str(messageCount)
for mList in range(messageCount):
eSub = “”
eFrom = “”
for msgl in mbox.retr(mList+1)[1]:
if msgl.startswith(“Subject”):
#print msgl
eSub = msgl[8:].strip()
if msgl.startswith(“From”):
#print msgl
eFrom = msgl.strip()
if eFrom.find(eusr2) > -1:
rvalue = eSub
else:
rvalue = “No Message”
mbox.quit()
return rvalue
def ams_ftp_upload(ftpsdir1, file1):
# Using Config File settings.cfg
ftpuser1 = aConfig.get(‘prd’, ‘ftpuser1’)
ftppass1 = aConfig.get(‘prd’, ‘ftppass1’)
ftpsite1 = aConfig.get(‘prd’, ‘ftpsite1’)
#ftpsourcedir1 = aConfig.get(‘prd’, ‘ftpsourcedir1’)
ftpdestdir1 = aConfig.get(‘prd’, ‘ftpdestdir1’)
try:
connftp = ftplib.FTP(ftpsite1)
connftp.login(ftpuser1,ftppass1)
connftp.cwd(ftpdestdir1)
fhandle1 = open(ftpsdir1 + file1, “rb”)
connftp.storbinary(‘STOR ‘ + file1, fhandle1)
fhandle1.close()
finally:
connftp.quit()
def ams_email_alert(subject, message, sendto):
# Using Config File settings.cfg
msg = MIMEText(message)
# msg[‘Subject’] = myPN + ” ” + subject
msg[‘Subject’] = subject
msg[‘From’] = aConfig.get(‘prd’, ’emailuser2′)
msg[‘To’] = aConfig.get(‘prd’, ’emailuser2′)
smtpObj = SMTP(aConfig.get(‘prd’, ’emailsmtpsrvr2′),587)
smtpObj.ehlo()
smtpObj.starttls()
smtpObj.ehlo()
smtpObj.login(aConfig.get(‘prd’, ’emailuser2′), aConfig.get(‘prd’, ’emailpass2′))
try:
if len(sendto) > 1:
smtpObj.sendmail(aConfig.get(‘prd’, ’emailuser2′), sendto, msg.as_string())
else:
smtpObj.sendmail(aConfig.get(‘prd’, ’emailuser2′), aConfig.get(‘prd’, ’emailuser2′), msg.as_string())
finally:
smtpObj.close()
def ams_write_to_log(file1, rw, line_to_write):
if rw == “a”:
datafile1=open(file1,’a’)
if rw == “w”:
datafile1=open(file1,’w’)
datafile1.write(line_to_write + “n”)
datafile1.close()
def ams_write_html_file(line_to_write):
html_header = “””
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”content-type” content=”text/html; charset=utf-8″ />
<meta name=”viewport” content=”width=device-width, user-scalable=no” />
<title>Arduino Monitor</title>
<link rel =”stylesheet” href = “/iPhoneIntegration.css” />
</head>
<body>
“””
html_footer = “<br><h2>Last Updated: ” + tdnow + “</h2>n</body></html>”
html_all = html_header + line_to_write + html_footer
ams_write_to_log(‘/srv/http/index.html’,’w’,html_all)
def ams_getWeather2():
# Fetch data (change lat and lon to desired location)
try:
weather_xml = urllib2.urlopen(‘http://graphical.weather.gov/xml/SOAP_server/ndfdSOAPclientByDay.php?whichClient=NDFDgenByDay&lat=’ + myWeatherLat + ‘&lon=’ + myWeatherLon + ‘&format=24+hourly&numDays=4&Unit=e’).read()
except:
return “Error: weather”
dom = minidom.parseString(weather_xml)
# Parse temperatures
xml_temperatures = dom.getElementsByTagName(‘temperature’)
highs = [None]*4
lows = [None]*4
for item in xml_temperatures:
if item.getAttribute(‘type’) == ‘maximum’:
values = item.getElementsByTagName(‘value’)
for i in range(len(values)):
highs[i] = int(values[i].firstChild.nodeValue)
if item.getAttribute(‘type’) == ‘minimum’:
values = item.getElementsByTagName(‘value’)
for i in range(len(values)):
lows[i] = int(values[i].firstChild.nodeValue)
# Parse icons
xml_icons = dom.getElementsByTagName(‘icon-link’)
icons = [None]*4
for i in range(len(xml_icons)):
icons[i] = xml_icons[i].firstChild.nodeValue.split(‘/’)[-1].split(‘.’)[0].rstrip(‘0123456789’)
# Parse dates
xml_day_one = dom.getElementsByTagName(‘start-valid-time’)[0].firstChild.nodeValue[0:10]
day_one = datetime.datetime.strptime(xml_day_one, ‘%Y-%m-%d’)
tdnow3 = time.strftime(‘%a’, (time.localtime(time.time())))
weather = “Current|High: ” + str(highs[0]) + “F Low: ” + str(lows[0]) + “F”
# if there was an error getting the condition, the city is invalid
if weather == “<?xml version=”:
return “Invalid city”
#return the weather condition
return weather
def buildReport(rHeading, rText):
myB = rHeading + “n” + rText + “n” + myReportBreak + “n”
return myB
#######################################################
# Begin main program
#######################################################
#Store current date and time
tdnow = time.strftime(‘%m-%d-%Y %H:%M:%S’, (time.localtime(time.time())))
tdnow2 = time.strftime(‘%b %d, %Y %I:%M%p’, (time.localtime(time.time())))
tdreport = time.strftime(‘%H%M’, (time.localtime(time.time())))
tdmin = time.strftime(‘%M’, (time.localtime(time.time())))
print(tdnow2)
if myAlertsAll == 1:
print(“Alerts On”)
else:
print(“Alerts Off”)
# Begin data file
datasave = ConfigParser.SafeConfigParser()
datasave.add_section(‘data’)
if myReport == 1:
myReportBody = myReportBody + buildReport(“Report Created:”,tdnow)
timeforweather = 0
if myWeather == 1:
# Only retrieve weather once an hour
if tdreport == myReportTime:
print(“Time to retrieve the weather”)
timeforweather = 1
weather1 = ams_getWeather2()
datasave.set(‘data’,’weather’,weather1)
print(weather1)
fweather1 = “Current: ” + weather1.replace(“|”,”n”)
if myMsg == 1:
msgOut = tdnow2 + “|” + weather1
ams_write_to_log(‘/srv/arduino/messages.cfg’,’w’,msgOut)
if myReport == 1:
myReportBody = myReportBody + buildReport(“Weather Conditions:”, fweather1)
if myTxtAlerts == 1:
if tdreport == myReportTime:
ams_email_alert(“Weather”,fweather1,aConfig.get(‘prd’, ‘smstextuser1’))
else:
print(“Not time to send weather email”)
else:
print(“Text alerts are not enabled”)
# For timing reasons check email first and then
# write it to the serial port later
if myEmail == 3:
retEmail = ams_email_check()
# Check Internet IP Address
if myIP == 1:
pub_ip = urllib2.urlopen(“http://automation.whatismyip.com/n09230945.asp”).read()
print pub_ip
datasave.set(‘data’,’ip’,pub_ip)
if myReport == 1:
myReportBody = myReportBody + buildReport(“My Internet IP:”, pub_ip)
# Read the temperature from the Arduino
if myArduino == 1:
# flush the serial input and read the data from Arduino
ser.flushInput()
sresult = ser.readline().strip()
datasave.set(‘data’,’temperature’,sresult)
#############################################################
# Write to RRD Round Robin Database for analytics
#############################################################
ret = rrdtool.update(“/srv/arduino/ttemp.rrd”,”N:” + sresult)
#############################################################
print(“Temperature: ” + sresult)
#Alerts checking for high and low temp
#If temp is exactly 32 degrees or less something is wrong with
#reading the sensor
if myAlertsAll == 1:
if float(sresult) > 32.00:
if float(sresult) < alertLowTemp:
print(“Alert: Low Temp”)
ams_email_alert(“Temperature”, “High Temperature: ” + str(sresult),”0″)
if float(sresult) > alertHighTemp:
print(“Alert: High Temp”)
ams_email_alert(“Temperature”,”Low Temperature: ” + str(sresult),”0″)
# used for debugging
#sresult = “00.00”
if myReport == 1:
myReportBody = myReportBody + buildReport(myAppLabel + ” Temperature:”, str(sresult) + “F”)
logdata1 = “<h1>” + myAppLabel + ” Temperature</h1><ul><li><a href=”rrdgraph.html”>” + sresult + “</a></ul>”
if myWebcamera == 1:
logdata1 = logdata1 + “<h1>Camera</h1><ul><li><img width=”260″ src=”webcam.jpg”></ul>”
else:
print(“Arduino is not enabled”)
# If we are not checking email and the Arduino is active
# then write the contents of messages.cfg to the Arduino
if myArduino == 1:
pfile = open(“/srv/arduino/messages.cfg”,”r”)
msg1 = pfile.readline().strip()
pfile.close()
ser.flushOutput()
ser.write(msg1 + “rn”)
print(msg1)
# Prints out ArchLinux debug information
if myDebug == 1:
myReportBody = myReportBody + “System Information:n”
print(“Debugging is enabled”)
print ‘system :’, platform.system()
myReportBody = myReportBody + platform.system() + ” “
print ‘release :’, platform.release()
myReportBody = myReportBody + platform.release() + “n”
print ‘machine :’, platform.machine()
myReportBody = myReportBody + platform.machine() + “n”
#print ‘processor:’, platform.processor()
#myReportBody = myReportBody + platform.processor() + “n”
myReportBody = myReportBody + myReportBreak + “n”
print(tdreport)
# Write Application Version to the footer of the report
myReportBody = myReportBody + buildReport(myPN + ” Version”, myVer)
if myReport == 1:
ams_write_to_log(‘/srv/arduino/report.txt’,’w’,myReportBody)
# Email Report out at myReporTime
if tdreport == myReportTime:
print(“Sending Report”)
ams_email_alert(“System Report”,myReportBody,”0″)
else:
print(“Not sending report”)
#Write HTML File – index.html
if myWeather == 1:
if tdreport == myReportTime:
logdata1 = logdata1 + “<h1>Weather</h1><ul><li><a href=”message.html”>” + fweather1 + “</a></ul>”
ams_write_html_file(logdata1)
# Write Data File and Close
datafile = open(‘/srv/arduino/data.dat’,’w’)
datasave.write(datafile)
datafile.close()
#FTP functionality added in v2012.09.11
if myFTP == 1:
if tdmin == “05”:
print(“FTPing images to website”)
ams_ftp_upload(‘/srv/http/img/’,’temp1h.png’)
ams_ftp_upload(‘/srv/http/img/’,’temp1d.png’)
ams_ftp_upload(‘/srv/http/img/’,’temp7d.png’)
ams_ftp_upload(‘/srv/http/img/’,’temp30d.png’)
#The following lines are used for debugging to a log file
#logdata2 = tdnow + “,success,temperature reading,” + sresult
#ams_write_to_log(‘/srv/arduino/log.txt’,’a’,logdata2)
No Comments