4

Long story short. I moved, put my home server is a closet and started worrying about temp and humidity, saw a guide online to make a network temperature and humidity monitor from a Raspberry Pi and an AM2302 sensor, bought the Raspberry Pi and AM2302 sensor, guide was not working part way through and wanted to be setup logged in as root, gave up and decided to make my own solution.

startup.sh - I do not yet know how I am going to have this start. Where everything is working I want it to log once a day to internal memory.

#!/bin/bash
sleep 10
sudo mkdir -p /ram
sudo mount -t tmpfs -o size=64m tmpfs /ram
sudo chown pi /ram

cp /scripts/dblogger.py /ram
cp /scripts/setupdb.py /ram
cd /ram

python setupdb.py

croncmd="sudo /ram/dblogger.py 2302 4 >> /scripts/job.log 2>&1"
cronjob="* * * * * $croncmd"
( crontab -l | grep -v "$croncmd" ; echo "$cronjob" ) | crontab -

Python setupdb.py

#!/usr/bin/python
import os
import sqlite3
os.chdir("/ram")
conn = sqlite3.connect('climate.db')
c = conn.cursor()
c.execute('CREATE TABLE climatelog ( Date text, Temperature text, Humidity text)')
conn.commit()
conn.close()

dblogger.py - This query's the sensor, logs it to the database, query's the database, and generates the output graph. Works when ran alone. Requires sudo to work. I hope to set thresholds so email me in the future.

#!/usr/bin/python
import sys
import os
import Adafruit_DHT
import sqlite3
import time
import datetime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

# Parse command line parameters.
sensor_args = { '11': Adafruit_DHT.DHT11,
        '22': Adafruit_DHT.DHT22,
        '2302': Adafruit_DHT.AM2302 }

if len(sys.argv) == 3 and sys.argv[1] in sensor_args:
    sensor = sensor_args[sys.argv[1]]
    pin = sys.argv[2]
else:
    print 'usage: sudo ./Adafruit_DHT.py [11|22|2302] GPIOpin#'
    print 'example: sudo ./Adafruit_DHT.py 2302 4 - Read from an AM2302 connected to GPIO #4'
    sys.exit(1)

os.chdir("/ram")
humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
if humidity is not None and temperature is not None:
    print 'Temp={0:0.1f}*F  Humidity={1:0.1f}%'.format(round((temperature*9/5+32), 2), humidity)
    now = datetime.datetime.now()
    con = sqlite3.connect('climate.db')
    c = con.cursor()
    c.execute('INSERT INTO climatelog VALUES (?,?,?)', (now.strftime("%Y-%m-%d %H:%M"), round((temperature*9/5+32), 2), round(humidity, 2)))
    con.commit()
    sql = "SELECT * FROM climatelog"
    # WHERE Date >= strftime('%s','now')-(60*60*24)
    grapharray = []
    for row in c.execute(sql):
        startinginfo = str(row).replace('(','').replace(')','').replace('u\'','').replace("'","")
        splitinfo = startinginfo.split(',')
        grapharrayappend = splitinfo[0]+','+splitinfo[1]+','+splitinfo[2]
        grapharray.append(grapharrayappend)
    datestamp, temp, humidity = np.loadtxt(grapharray,delimiter=',', unpack=True,converters={ 0: mdates.strpdate2num("%Y-%m-%d %H:%M")})
    fig = plt.figure(figsize=(16, 4))
    rect = fig.patch
    axl = fig.add_subplot(1,1,1, axisbg='white')
    plt.plot_date(x=datestamp, y=temp, fmt='r-', label = 'temp', linewidth=2)
    plt.plot_date(x=datestamp, y=humidity, fmt='b-', label = 'humidity', linewidth=2)
    #plt.show()
    plt.savefig('24.png')
    con.close()
else:
    print 'Failed to get reading. Try again!'

Ran alone everything works. Ran together and everything works except for dblogger.py. I added >> /scripts/job.log 2>&1 to the command calling dblogger.py to try and troubleshoot it.

job.log - Every minute it logs this error. With Temp and humidity changing slightly of course.

Temp=72.0*F  Humidity=20.8%
Traceback (most recent call last):
  File "/ram/dblogger.py", line 53, in <module>
    fig = plt.figure(figsize=(16, 4))
  File "/usr/lib/pymodules/python2.7/matplotlib/pyplot.py", line 343, in figure
    **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 80, in new_figure_manager
    window = Tk.Tk()
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1712, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable

I have worked on this till I went cross eyed. Last Friday I had 0 Python experience and my bash shell scripting experience was from a 2 week class on outdated Solaris two and a half years ago. I was going to follow a guide but it was not working at all. I have no idea what is wrong or how to start searching for the issue. I feel like I'm 98% to a working solution. Is there any bash/python/matplotlib users that can identify my issue?

If this is off topic please close the question. I am posting in a hurry due to needing to leave for work. Any help is appreciated.

  • Are you running X11? – Bex Feb 24 '15 at 15:16
  • I actually don't know what X11 is. So I can not answer this. – RetsamEvalsEht Feb 26 '15 at 8:24
4

If I remember correctly, Tk needs a window manager, so you probably need to export the DISPLAY variable. Try setting

DISPLAY=:0.0

before running your script.

  • When you set a shell variable, don't preface it with $ (corrected). – goldilocks Feb 24 '15 at 15:34
  • Thank you for the help. Your answer was unfortunately unable to fix my issue. I may have inserted it in the wrong place, but your answer did lead me to a solution on this page. stackoverflow.com/questions/2801882/… I have posted the changes that worked for me in another answer for anyone who happens across this post in the future. – RetsamEvalsEht Feb 25 '15 at 4:19
3

Thanks to Roberto's answer I began searching for information about DISPLAY and that particular part of my error. Where I found this page:

https://stackoverflow.com/questions/2801882/generating-a-png-with-matplotlib-when-display-is-undefined

For those interested the issue was in dblogger.py with matplotlib's default display back end.

Before:

#!/usr/bin/python
import sys
import os
import Adafruit_DHT
import sqlite3
import time
import datetime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

After:

#!/usr/bin/python
import sys
import os
import Adafruit_DHT
import sqlite3
import time
import datetime
import numpy as np

import matplotlib
matplotlib.use('Agg')

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

import matplotlib must proceed matplotlib.use('Agg'), which in turn must proceed import matplotlib.pyplot according to the previous link.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.