Geek Out

Geeky things. Expect things about blog configuration, firewall stuff, computer hardware, geek jokes, Linux, e-mail, and other stuff.

This is the final post on configuring 1-Wire for temperature monitoring. In Part 1 I got all of the wiring figured out.  Part 2 was all about gathering the data into a log format.

This post is about getting that data stored and then rendered into a graphical format.

The first thing I did was slightly refactor my gathering. I wrote a bash script that queries the sensors in order and logs them to the same log file as before, but also puts that data into a round-robin database (RRD).  That way later on I can graph the data any way I want.

The big requirement before this script is run is to have existing RRD files. I used a Perl script to create these RRD files. This script would need to be updated for each sensor:
#!/usr/bin/perl -w

use Time::Local;
use RRDp;

# Create the database
RRDp::start "/usr/bin/rrdtool";
RRDp::cmd "create Living_Room.rrd
-b 1373820664
-s 60
" ;

Building that specification for the RRD is a bit of a dark-art. Here is the best way I can explain the options.

  • The “-b 1373820664” is the earliest data point allowed into the RRD. It is in epoch form. I did this because I wanted to back-fill my log data. This is optional if you are starting your graph from scratch.
  • The “-s 60” option is the data interval time in seconds. The “DS:temp:GAUGE:180:U:U” is the data point to be entered – “temp” is a label on that data point so it can be easily queried later on.
  • The RRA blocks are repeated for AVERAGE, MIN, and MAX so I will only describe one. “RRA:AVERAGE:0.5:1:10080” tells the RRD to keep 10080 data rows with 1 step. Each step is 1 minute. This ends up being 7 full days of data. “RRA:AVERAGE:0.5:5:4032” is similar in that it keeps 4032 data rows, but this time with a step of 5. This ends up being 14 days of data on a 5 minute interval. “RRA:AVERAGE:0.5:30:1344” keeps 28 days of data on a 30 minute interval. And “RRA:AVERAGE:0.5:120:21900” keeps 1825 days of data (about 5 years) with a 2 hour interval.

All of this data will be stored in a file that is 879K. Not bad for 5 years of data.

Here is the new digitemp_gather script. This script runs every minute via a cronjob:

DIGITEMP_CONF="-c /etc/digitemprc"


# Function to call digitemp with a given sensor ID and location.
# Generates a log message in $LOGFILE
function ProcessSensor {

cur_date=$(date +"%Y/%m/%d %H:%M:%S")
dateEpoch=$(date -d "$cur_date" +%s)
cur_temp=$(/usr/bin/digitemp -t $sensor_id -q -c /etc/digitemprc -o%.2F)
echo $cur_date $sensor_location F: $cur_temp >> $LOGFILE

rrdtool update $RRD_PATH/$sensor_location.rrd $dateEpoch:$cur_temp

ProcessSensor 0 Attic
ProcessSensor 1 Garage
ProcessSensor 2 Living_Room
ProcessSensor 3 Master_Bedroom

Now your cronjob is filling your RRD and it also continues to update the log file. It is not useful to graph data until you have at least 15 or 30 minutes worth of data- so time for a break.

Assuming you now have a bunch of data stored in your RRDs, it is pretty easy to extract that data with rrdtool and graph it as a PNG. This script creates the graphs in a temporary directory and I run it every 15 minutes. In my case, the last step is to copy the graphs to my web host so I can see them wherever I am.


# Function that builds graphs for a specific sensor on a given interval
# Usage: CreateGraph Sensor_Name Interval
# Example: CreateGraph Living_Room hour
function CreateGraph {

rrdtool graph $GRAPHS_DIR/$png_file
-h 80 -w 600
–start -1$time_length –end now
-t "$sensor_name :: last $time_length"
-v "degrees F"
GPRINT:temp:AVERAGE:"Avg\: %6.1lf"
GPRINT:temp:MAX:"Max\: %6.1lf"
GPRINT:temp:MIN:"Min\: %6.1lf"
GPRINT:temp:LAST:"Current\: %6.1lf degrees F\n"
> /dev/null

# Remove all of the existing graphs and recreate the graphs directory
if [ -e $GRAPHS_DIR ] ; then
/bin/rm -rf $GRAPHS_DIR

# Build all of the graphs
CreateGraph Attic hour
CreateGraph Attic day
CreateGraph Attic week
CreateGraph Garage hour
CreateGraph Garage day
CreateGraph Garage week
CreateGraph Living_Room hour
CreateGraph Living_Room day
CreateGraph Living_Room week
CreateGraph Master_Bedroom hour
CreateGraph Master_Bedroom day
CreateGraph Master_Bedroom week

# Copy the graphs to my webhost
scp -q $GRAPHS_DIR/*.png

This is a continuation post documenting my installation of a 1-Wire Temperature monitoring system in my house. Part 1 can be found here.

Ultimately I want to monitor 5 different sensors in and around my house. However because I don’t feel like climbing around in my attic when it is well north of 100 degrees, I am only going to hook up four.

In my last post, I documented the process of hooking up a weatherproof sensor to a RJ-11 jack. While that works and will work well, I previously wired RJ-45 jacks for ethernet so I switched to that size wherever I could.

Next problem I had to solve is how to distribute the 1-Wire system to multiple plugs. I found this Leviton 1×9 Structured Telephone Module which is typically used to distribute phone services up to 9 plugs. Since 1-wire uses three wires, this will work great. It is a $20 part, but well worth it.

I wired up three RJ-45 plugs into about 18″ of four-wire phone wire and then punched the wires down into the telephone module. I could then use my Ethernet panel to connect the USB sensor and the two internal sensors. I then punched down one of the weatherproof sensors into the same block. Lastly, I soldered a final sensor to a longer length of four wire phone cord. I ran that cable up into my attic and zip tied it to an attic brace. After I punched it into the block and plugged my two internal sensors in, I was set to test the system.

First up is to run the initialization:
stevet@neon:$ sudo /usr/bin/digitemp_DS2490 -i
DigiTemp v3.5.0 Copyright 1996-2007 by Brian C. Lane
GNU Public License v2.0 –
Found DS2490 device #1 at 001/019
Turning off all DS2409 Couplers
Searching the 1-Wire LAN
28C092C80400000E : DS18B20 Temperature Sensor
2881D1C8040000EB : DS18B20 Temperature Sensor
28355AD90400003C : DS18B20 Temperature Sensor
287B69C7040000BD : DS18B20 Temperature Sensor
ROM #0 : 28C092C80400000E
ROM #1 : 2881D1C8040000EB
ROM #2 : 28355AD90400003C
ROM #3 : 287B69C7040000BD
Wrote .digitemprc

Four sensors! Awesome. Now how hot is it at all of these sensors:
stevet@neon:$ sudo /usr/bin/digitemp_DS2490 -i
DigiTemp v3.5.0 Copyright 1996-2007 by Brian C. Lane
GNU Public License v2.0 –
Found DS2490 device #1 at 001/019
2013/07/14 13:07:31 Sensor 0 F: 110.53
2013/07/14 13:07:32 Sensor 1 F: 91.51
2013/07/14 13:07:33 Sensor 2 F: 78.69
2013/07/14 13:07:34 Sensor 3 F: 79.93

A bit warm in my attic. But every sensor worked.

In my last post I created a /etc/digitemprc file that is used as part of my cronjob. That config needs to be modified with the current sensors. Just like the last post, I used the .digitemprc file created by the initialization and changed the log format.

Because I added three sensors and the order has changed, my digitemp_rename script needs to be updated as well. Here is the new version. Very similar to before, but it handles the new sensors:

sed -e “s/Sensor 0/Attic/” -e “s/#0 : 28C092C80400000E//”
-e “s/Sensor 1/Garage/” -e “s/#1 : 2881D1C8040000EB//”
-e “s/Sensor 2/Living_Room/” -e “s/#2 : 28355AD90400003C//”
-e “s/Sensor 3/Master_Bedroom/” -e “s/#3 : 287B69C7040000BD//”

While I was doing all of this work, I disabled the crontab. It would error out while sensors were disconnected and moving around anyway. I cleared the log file and re-enabled the cronjob to run every minute.

After a few minutes, this is what my log looks like:
2013/07/14 13:08:02 Attic F: 110.53
2013/07/14 13:08:03 Garage F: 91.51
2013/07/14 13:08:04 Living_Room F: 78.69
2013/07/14 13:08:05 Master_Bedroom F: 79.93
2013/07/14 13:09:02 Attic F: 110.75
2013/07/14 13:09:03 Garage F: 91.51
2013/07/14 13:09:04 Living_Room F: 78.69
2013/07/14 13:09:05 Master_Bedroom F: 79.93
2013/07/14 13:10:02 Attic F: 110.86
2013/07/14 13:10:03 Garage F: 91.51
2013/07/14 13:10:05 Living_Room F: 78.57
2013/07/14 13:10:06 Master_Bedroom F: 79.81

Everything looks good from a logging perspective.

Part 3 is to graph the data that I am gathering and see how things look visually over time.

I have an older house with not so good insulation and windows. It gets too hot in the summer and too cold in the winter. My furnace and AC have to work extra hard to maintain a decent environment.

Before I begin spending a lot of money on upgrades, I wanted to get a baseline of the environment.

1-Wire is a fairly simple system that lets you monitor temperature with various sensors spread around the house. It also has support to monitor humidity, but I am only doing temperature for now.

First thing you need is a One-Wire adapter for your computer. I picked up a USB model that I am hooking up to my linux server. It is model DS9490R that I got from Hobby Boards for about $40 shipped. I picked up 10 waterproof DS18B20 sensors from a Chinese seller on eBay for about $20 shipped.

The DSR9490R has a six pin RJ-11 connector, but the sensors have just three wires. I picked up some four-wire telephone wire and some empty RJ-11 plugs at Home Depot and then it was time to start wiring.

It took me quite a while to figure out the pin-out. There seemed to be a bunch of conflicting info so I did a bunch of test crimps and patch wiring. There are three important wires that matter, voltage, data, and ground. On the sensors voltage is red, data is yellow (on some it is white), and ground is black. For the RJ-11 connector, the layout is voltage on pin 1, the data feed is on pin 3, and the ground feed is on pin 4. If you look at the top of a RJ-11 connector with catch on top and the opening pointing away from you, the pins go from 1 to 6 from left to right.

I could not get the waterproof sensor wires to fit and crimp into the RJ-11 plugs I had, so I took three short lengths of wire stripped from a phone cord to make a tail that is a couple inches long. I then wound and soldered the sensor wires to the tail.

Now I have a sensor that will plug into the USB adapter. Time to test it!

There are two main ways to read data from the sensors. DigiTemp and OWFS. To start and debug I decided to use DigiTemp.

First up, install digitemp. I am on a CentOS box so I used this command:
stevet@neon:$ sudo yum install -y digitemp

Then I plugged in my USB adapter and checked /var/log/messages to make sure it connected. I started a tail and left it running:
stevet@neon:$ tail -f /var/log/messages

Then I plugged in the sensor to the USB adapter. If there is a wiring problem, you may see the USB device get disconnected. If so, check that your wiring is going into the correct pins. If it looks good, time to detect your sensor.
stevet@neon:$ /usr/bin/digitemp_DS2490 -i
DigiTemp v3.5.0 Copyright 1996-2007 by Brian C. Lane
GNU Public License v2.0 –
Found DS2490 device #1 at 001/016
Turning off all DS2409 Couplers
Searching the 1-Wire LAN
287B69C7040000BD : DS18B20 Temperature Sensor
ROM #0 : 287B69C7040000BD
Wrote .digitemprc

Look a sensor! Now run a query and make sure the sensor is giving back a temperature:
stevet@neon:~$ sudo /usr/bin/digitemp_DS2490 -a
DigiTemp v3.5.0 Copyright 1996-2007 by Brian C. Lane
GNU Public License v2.0 –
Found DS2490 device #1 at 001/016
Jul 13 18:03:53 Sensor 0 C: 25.94 F: 78.69

It is 25.94 Celsius and 78.69 Fahrenheit at my desk. Nice!

Now it is time to log this data over time. First, we want to copy the DigiTemp config file to a standard location so we can script the data gathering.
stevet@neon:~$ sudo cp .digitemprc /etc/digitemprc

If you look at that config file – you will see the one sensor listed along with the log format. The log format is OK, but it can be better. I commented out the exiting log format and added this one:
# LOG_FORMAT “%b %d %H:%M:%S Sensor %s C: %.2C F: %.2F”
LOG_FORMAT “%Y/%m/%d %H:%M:%S Sensor %s F: %.2F”

Sensor 0 is not a very clear sensor name. This sensor will be in my living room, so I wrote a small script to change the output from DigiTemp to be even more human friendly

sed -e “s/Sensor 0/Living_Room/” -e “s/#10 : 287B69C7040000BD//”

Then I setup a cron job that runs as root. This job runs every minute and takes the output from digitemp, does the rename, and writes it to a log file. It looks like this in my crontab:
[code language=bash]
* * * * * /usr/bin/digitemp_DS2490 -q -a -c /etc/digitemprc | /home/stevet/bin/digitemp_rename | sort >> /var/log/temperatures

Now let it run for a few minutes and your temperatures log file should begin to add lines of data. It will looks something like:
stevet@neon:~$ tail /var/log/temperatures
2013/07/13 18:08:02 12 Living Room F: 79.14
2013/07/13 18:09:02 12 Living Room F: 79.25
2013/07/13 18:10:02 12 Living Room F: 79.36
2013/07/13 18:11:02 12 Living Room F: 79.47
2013/07/13 18:12:02 12 Living Room F: 79.47

You now are gathering specific sensor data and putting it into a log file to be processed later.

In Part 2, I will add a bunch of sensors to the 1-wire system and show how they all are logged. In Part 3, I will detail how I graphed that data so I can visually see the temperature changes.

Samsung Captivate

So, I lied in my last post. My newest toy is a Samsung Captivate smart phone. It is powered by Android.

I do like it, but all it does take some getting used to the touch screen.

My biggest annoyance is the bloatware, shovelware, crapware, whatever you want to call it. AT&T installs a ton of stuff. Time to get rid of it!

First you need to gain super-user privileges. Here is how to do that:

  1. Download and install the Android SDK (download and install guide)
  2. Install the Samsung Drivers (download location)
  3. Set your phone to connect in Mass Storage mode (Settings->Applications->USB Settings->Mass storage)
  4. Connect the phone via USB. Mount the drive (select Mount from the USB drop down notification).
  5. Download the Root Update Zip and rename it
  6. Copy the to your internal SD card on the phone
  7. Disconnect your phone’s USB
  8. Turn on USB Debugging Mode (Settings->Applications->Development->USB Debugging)
  9. Connect the phone via USB again
  10. Use a command prompt to cd to the SDK’s tools directory. Mine is c:androidtools.
  11. Run the recovery mode reboot command: adb reboot recovery
  12. The phone will reboot into recovery mode. Select Reinstall Packages on the phone’s menu using the Volume Up/Down buttons and select using the Power button. The phone will install the update and reboot.
  13. You should now see a Superuser Permission application in the Applications panels.

Now it is time to remove some crap!

  1. Make sure your phone is connected via USB and the USB Debugging mode is still turned on.
  2. From a command prompt, cd to the SDK’s tools directory.
  3. Run the SDK shell: adb shell
  4. Become root: su
  5. To remove apps, we will just rename them. For example this removes the AT&T Nav app: mv /system/app/ATTNav-Samsung-Vega-1488.apk /system/app/ATTNav-Samsung-Vega-1488.tmp
  6. Here is a list of applications and their actual application file names:
    • AT&T Nav — /system/app/ATTNav-Samsung-Vega-1488.apk
    • AT&T Radio — /system/app/ATT_Radio_2.1.07.apk
    • MobiTV — /system/app/MobiTV_800x480_320_20100610_1.0.0.15-118829.apk
    • MobileBanking — mv /system/app/MobileBanking.apk
    • AT&T Maps — /system/app/attmaps20-1094.apk
    • Where — /system/app/WHERE_Samsung_GT-I900_Vegas_EN_1.9.3_GM_06112010.apk
    • AT&T Hotspots — /system/app/WISPr_v41.apk /system/app/WISPr_v41.tmp
    • AT&T FamilyMap — mv /system/app/androidlauncher2.1-61x612010_06_11t15_49.apk
    • AT&T Music mv /system/app/ATT-P11_PROD.apk
    • Instant Messaging — /system/app/IM-Signed.apk
    • AllShare — /system/app/Dlna.apk
  7. Disconnect your USB, turn off USB Debugging and see how your apps are missing!

Here are the list of sources I used to get this going:

Renaming JIRA Users

So you use JIRA do you? Nice, so do I.

Ever have someone get married? divorced? a typo in their user name? Every try and change it? Yeah, not so easy.

Atlassian has not set a release where there will be a fix, so we humble JIRA administrators have to make due with what we can. At this current job we are using version 4.0 (with plans to upgrade this summer). We also used email addresses as the user name rather than the AD based user name. If you want to use AD integration, it is best to match user names. So we had a pressing need to rename everyone. What is the right way? Atlassian tells us to export, search and replace, then import. Yep. Kludgey. Plus my import was not working for some reason. What else can we do? Database Updates! Yeah!

I found my first SQL example in the 7 year old rename user bug. It was published by Jeff Turner. It mostly works on the 4.0 scheme. Some updates are needed.

Here is the updated SQL for a 4.0 schema:

update jiraissue set reporter='newuser' where reporter='';
update jiraissue set assignee='newuser' where assignee='';
update jiraaction set AUTHOR='newuser' where AUTHOR='';
update changegroup set AUTHOR='newuser' where AUTHOR='';
update changeitem set OLDVALUE='newuser' where OLDVALUE='' and FIELD='assignee';
update changeitem set NEWVALUE='newuser' where NEWVALUE='' and FIELD='assignee';
update searchrequest set authorname='newuser' where authorname='';
update searchrequest set username='newuser' where username='';
update schemepermissions set perm_parameter='newuser' where perm_parameter='' and perm_type="user";
update schemepermissions set perm_parameter='newuser' where perm_parameter='' and perm_type="user";
update searchrequest set authorname='newuser' where authorname='';
update membershipbase set USER_NAME='newuser' where USER_NAME='';
update OS_CURRENTSTEP set owner='newuser' where owner='';
update OS_CURRENTSTEP set caller='newuser' where caller='';
update OS_HISTORYSTEP set owner='newuser' where owner='';
update OS_HISTORYSTEP set caller='newuser' where caller='';
update fileattachment set author='newuser' where author='';
update filtersubscription set username='newuser' where username='';
update project set lead='newuser' where lead='';
update userbase set username='newuser' where username='';
update customfieldvalue set stringvalue='newuser' where stringvalue='';
update columnlayout set username='newuser' where username='';
update portalpage set username='newuser' where username='';
update userhistoryitem set USERNAME='newuser' where USERNAME='';
update worklog set AUTHOR='newuser' where AUTHOR='';
update worklog set UPDATEAUTHOR='newuser' where UPDATEAUTHOR='';
update notification set notif_parameter='newuser' where notif_parameter='';
update component set lead='newuser' where lead='';
update columnlayout set username='newuser' where username='';

Once you update your DB with all of those update statements you need to refresh your JIRA indexes. This is done via the JIRA Administrator->Indexes page.

I have done this for a couple of users today and everything looks OK so far. I will be doing it for bunches of users in the next couple of days and will update this post if needed.

We use a couple of external hard drive enclosures for offline backups at work. The best connectivity is via eSATA (USB being a bit flakier and much slower).

It works great on my Ubuntu 10.04 install on my Dell laptop, but that is my personal box. I was able to provision a Dell desktop and a PCI SATA card with two eSATA ports. It is a Rosewill RC-209-EX with the SIL3114 chipset.

After plugging it all in, my drives were just not recognized. No matter the boot order or what I did- no go. So, I buckled and read the directions. 🙂 As it turns out, this card can only do four total SATA ports and the four internal are on by default and the two external are off. I reset the jumpers to turn on both external and two internal.

Now it detects the drives. Well, actually it detects one drive. There are two in the enclosure.

So far I have had no luck getting the other drive in the enclosure detected. This is quite frustrating.

If anyone happens to read this and know what I can do to solve this, please leave a comment. If I fix it, I will add and update to this post.

UPDATE: I have emailed Rosewill (no response yet). I also set the jumpers on the WD drives to force them to be 150 MB/s. This had no effect either. I am still without a solution and am pretty frustrated.

UPDATE 2: I heard back from Rosewill. No assistance at all, I responded- but no word back yet. I have now also tried a SIL-3512 eSATA card (the only eSATA card Fry’s had) and it does not work either. This is very frustrating.

UPDATE 3: I returned the SIL-3512 to Fry’s (no problems there) and hit up NewEgg for a SNT SNT-PCIX Card Silicon Image 3132 SATA II PCI Express 2 x eSATA Port Multiplier RAID Controller Card. It is PCI-E but I have a slot (it appears anyway) and it works with a drive array with multiple drives. About the same price as the other two as well. Why is this so hard? I should get it next week. I also ordered an additional eSATA cable so I have two. This looks really cool as well if you just need eSATA ports and you have spare SATA ones eSATA bracket.

UPDATE 4: The card I ordered from NewEgg works. Well mostly. Sometimes I do not get both drives showing up. I re-seat the cables, and power the enclosure back on and all is well. This was pretty darn annoying if I say so myself.

I spent a little time recently creating a new blog to act as a business landing page.

To make it simple, I am going to use WordPress. Actually installing WordPress is very simple; just unzip it in the right place and follow the wizard to create a wp-config.php file.

The trick I had was creating the database and user. I ran these commands:
mysql> CREATE DATABASE newdatabase;
mysql> GRANT ALL PRIVILEGES ON newusername.* TO “newdatabase”@”localhost”
-> IDENTIFIED BY “somepassword”;

The FLUSH PRIVILEGES command had an error:
ERROR 1146 (42S02): Table ‘mysql.servers’ doesn’t exist

A bit of google-fu revealed some SQL to run. My supposition is that during a recent upgrade of mysql server, this table became a requirement but was not created as part of the upgrade.

Here is the SQL to create an empty table in the mysql database.
CREATE TABLE `servers` (
`Server_name` char(64) NOT NULL,
`Host` char(64) NOT NULL,
`Db` char(64) NOT NULL,
`Username` char(64) NOT NULL,
`Password` char(64) NOT NULL,
`Port` int(4) DEFAULT NULL,
`Socket` char(64) DEFAULT NULL,
`Wrapper` char(64) NOT NULL,
`Owner` char(64) NOT NULL,
PRIMARY KEY (`Server_name`)
COMMENT='MySQL Foreign Servers table';

Once I created that table, the FLUSH PRIVILEGES command worked without error and WordPress did all the DB work needed without complaint.

The Gmail gadget does not support the “Always use https” preference.  Does this annoy you?

iGoogle Error

I started getting that awhile back when on my iGoogle personalized home page and it looks like Google is not going to fix it.  Boo.

So what is a person to do?  I want the conveince of iGoogle, but I want the security of HTTPS when sending and reading email.  Enter Greasemonkey on Firefox!

If you install the Greasemonkey Firefox Extension.  You have lots of neat scripts available to you.  Here is a list of 25 Useful Ones.

The one that is big for me is: Google Secure Pro.  This script forces Gmail, Google Docs, and other Google services to use Secure HTTP rather than the normal un-secure.

Once you get those two items in place you are golden!  You iGoogle will now display you top five messages and when you head to Gmail it will switch you to the secure mode.  Don’t forget to switch off “Always use https” as a Gmail setting.

The only drawback to this approach is that you have to install both of these items on every machine you check Gmail for and this is a Firefox only solution.

If you think that is a pretty good setup for Gmail, take a look at Better Gmail 2 as well.  Lots of neat stuff in that extension as well.