NAME

thermd - Thermometer Daemon supporting HA7Net, EM1, TEMP08, RoomAlert, TemPageR, WeatherGoose (and their ilk), RacSense, serial port host adapters (ibuttonlink, DS9097E, DS9097, and DS2480B) and USB host adapters (DS9490 or PuceBaboon), QK145, VK011, and EnerSure data collectors, the Poseidon and Damocles series from HWg, LX-4008 and IR5150 from MRV (and other SNMP devices), Veris H8030, H8031, H8035 and H8036, Smart-Watt, Smart-SenseRH, and Smart-PDU from Smart Works, MaxBotix Sonar sensors, and the Proliphix line of IP-enabled thermostats.


DESCRIPTION

Thermd is a four-function program to work with a very large family of environmental monitors.

Currently, thermd supports the following hardware and software devices:

HA7Net
Embedded Data Systems http://embeddeddatasystems.com

EM1
Sensatronics http://www.sensatronics.com

TEMP08
Midon Design http://www.midondesign

RoomAlert 7E, RoomAlert 11E, RoomAlert 24E, RoomAlert 26W, and TemPageR
RoomAlert http://www.roomalert.com

MiniGoose, WeatherGoose, SuperGoose, RacSense or PowerGoose
Geist Manufacturing http://www.geistmfg.com/ and ITWatchDogs http://www.itwatchdogs.com

owfs, owhttpd, owshell
http://www. owfs.org and http://owfs.sourceforge.net

Serial port adaptors based on ibuttonlink, DS9097E, DS9097 and USB port adaptors based on DS9490 or PuceBaboon
Hobby Boards http://www.hobby-boards.com, AAG Electronica http://www.aagelectronica.com, and others (via owfs, owhttpd, and owshell)

QK145 and VK011
Quality Kits http://www.qkits.com

Enersure
Trendpoint http://www.trendpoint.com

A wide variety of SNMP-enabled devices, including
Poseidon and Damocles
HWg http://www.hw-group.com/index_en.html,

MRV LX-4008 and IR5150
MRV http://www.mrv.com

SmartWatt, SmartSenseTH, SmartNet and SmartPDU
Smart Works http://www.smart-works.com

Veris
Veris H8030, H8031, H8035, and H8035 Modbus Energy Meters http://www.veris.com/modbus.asp

MaxBotix
MaxBotix EZ1, EZ2, EZ3, and EZ4 sonar rangefinders from http://www.maxbotix.com/

Proliphix line of IP-enabled thermostats
Proliphix http://www.proliphix.com

Newport and Omega iBTX, iBTX-M, iBTHX, iPTX-D, iPTX-W, iTCX, iTHX-M, iTHX-W, and iTHX-2 Microservers
From Newport Electronics http://www.newportus.com/iServer/ or Omega Engineering http://www.omega.com/

Personal weather stations
Weather Underground http://www.wunderground.com (both writing your data and reading other stations' data).

Command line
Command line programs (such as sysctl or snmpwalk can be called to extract data that is otherwise not accessable through thermd.

The three operational modes of thermd are:

  1. Logging daemon
  2. The program will sample temperature readings and log them to a data file (one log file per sensor). The program will also optionally generate an RSS feed, with graphs (see below). The program will also optionally send weather information to Weather Underground (http://www.wunderground.com/) for local weather station information.

  3. Plotting/Printing/Image-annotating program
  4. The program will also create Portable Network Graphic (PNG) files, text files which plot/list sensor readings, or will annotate an image with sensor readings (using ImageMagick)

  5. CGI script
  6. The program will act as a CGI script to interactively plot data, and allow a web surfer to step forwards and backwards in the logged data, looking a different views of the data.


INTERNATIONALIZATION

Thermd natively supports English, Swedish, German, Dutch, Russian, and Spanish (translations to other languages will be welcomed). Web pages will be translated to the language of the person viewing them, while all other actions are done in the language in which the host machine resides.

Documentation and configuration error messages remain in English.


REQUIRED MODULES

You must download and install the following modules from the CPAN in order to get thermd to function (thermd uses other modules, but they are part of the Perl default distribution).

HTTP::Date
Config::General
GD
GD::Graph
The GD and GD::Graph modules are only necessary if you want thermd to plot graphical data (used in the CGI script and the RSS feed). You will also need the GD libraries, of course (see http://www.libgd.org/). NOTE: I have not been able to get this working on Windows, so currently any reference to GD is disabled when running on Windows.

LWP::UserAgent
Crypt::SSLeay
The LWP::UserAgent module is usually all that is needed if you specify the HA7Net Room Alert, TemPageR, EM1, Proliphix, or owhttpd in the configuration file (or if you have a View of type Wunderground). If you need SSL (that is, if you access a device via port 443) then you will also need the Crypt::SSLeay module.

XML::Simple
If you use the MiniGoose, WeatherGoose, SuperGoose, RacSense or PowerGoose, of have a collector of type Poseidon or Wunderground you will need the XML::Simple module in addition to LWP::UserAgent.

If you use the ``XML'' output format, you will also need the XML::Simple module.

Net::SNMP
If you use the SNMP Subtype for Poseidon or Damocles series from HWg, or the MRV LX-4008, IR5150, from MRV, or other SNMP-based devices, you will also need the Net::SNMP module.

Modbus::Client
If you use the Enersure or any of the Veris Energy Meters, you will also need Modbus::Client

DBI (and DBD)
If you use LogFormat SQL, then you will also need the DBI module and the DBD module that matches your database.

Digest::CRC
If you use the HA7Net, you will need the Digest::CRC module

Net::Telnet
If you use any of the Newport Electronics or Omega Engineering iServer Microservers, you will need the Net::Telnet module.

Image::Magick
If you use the Type=Image in any View in the config-file, you will need the Image::Magick module as well as the ImageMagick libraries (see http://www.imagemagick.org/). You will need a version greater or equal to 6.3.0.

RPC::XML and RPC::XML::Client
If you use the SmartWatt, SmartNet, SmartSenseRH, or SmartPDU, you'll need RPC::XML and RPC::XML::Client

Spreadsheet::WriteExcel
If you use the Excel output feature, you will also need Spreadsheet::WriteExcel. This feature is also exposed to the web, so you may want to include this module to be nice to anyone who can view your website.

Authen::SASL
If you use the SMTPHost configuration option, and your SMPT Host requires authentication (which means you will also need to use the SMTPUsername and SMTPPassword configuration options), then you will also need the Authen::SASL module.


OPERATION

When run from the command line, thermd can run either as a logging daemon, or as a plotting/reporting script. ALL RUNTIME FLAGS MAY BE ABBREVIATED! Note that when a flag is specified, it overrides any corresponding value in the config file (so specifying -width overrides the value of the GraphWidth configuration item).

Logging daemon

    thermd -daemon [-config file] [-nofork [-verbose]]
        -config file    Use this as a config file (default=/etc/thermd.conf)
        -nofork         Don't fork to background (usually only for debugging)
        -verbose        Verbose output (definitely for debugging :-)

Sending a HUP signal to the daemon will cause it to restart and re-read it's configuration file. The daemon automatically restarts every week to avoid possible memory leaks.

Reporting

    thermd -report [report-args] [config-args, unit-args, range-args]
        -format type    One of CSV (comma separated values), TSV (tab
                        separated values), XML, CER (Eddy Common Event
                        Record) or Excel.
                        Default format is TSV
        -epochtime      When printing time, print Unix time(2), instead of
                        the default human-readable time
        -current        Print current values only
        -raw            Print all current values, in raw form

Graphing

    thermd -graph [graph-args] [config-args, unit-args, range-args]
        -width pixels   Override the width of the graph.  If not specified
                        here, default value comes from the config file, and
                        that default value is 750
        -height pixels  Override the height of the graph.  If not specified
                        here, default value comes from the config file, and
                        that default value is 300
        -hilo           Graph 24-hour extremes instead of individual datapoints
                            This may get a bit hard to read if you have too
                            many sensors being graphed
        -nosmooth       When graphs get dense (typ. > 1 month of data), graph
                            data is automatically smoothed.  This switch
                            defeats that function.

Image Annotation

    thermd -annotate [annotate-args] [config-args, unit-args]
        -current        Print current temperatures only (default)

Shared arguments available to reporting, graphing and annotating

    Common config-args
        -config file    Use this as a config file (default=/etc/thermd.conf)
        -outfile file   Output graph/table to this file (instead of STDOUT)
        -view name      Show a named view (defined in config file, default=all)
        -all_sensors    Ignore/override any -view, and show *all* sensors
        -nowarn         Do not print configuration warnings
    Common unit-args
        -units {English|Metric}
                        Use English/Metric units (override config file)
        -temperature {C|F}
                        Show temperature values as (override config and -units)
        -windspeed {mph|kph|mps|knots}
                        Show windspeed values as (override config and -units)
        -rainfall {inches|mm}
                        Show rainfall values as (override config and -units)
                        (also affects MaxBotix "range" values)
        -barometer {inHg|mmHg|hPa|kPa|mBar|millibar}
                        Show barometer values as (override config and -units)
    Common range-args
        -from daytime   From date/time *
        -to daytime     To date/time *
        -center daytime Center chart on date/time *
        -span reltime   Span for centered chart **
        * Date/time values may be specified as:
            absolute (ex: "20030228" or "20030228T1535" - actually, any
                format allowed by HTTP::Date)
            relative (ex: 3d, -2.5h, 3w, +5m3d1h, etc., suffixes are y=>year,
                m=>month, w=>week, d=>day, h=>hour)  Note: sign is highly
                significant, and changes what it is relative to...
            named (i.e., "now", "today", "yesterday"), considered absolute
                times as far as discussion below is considered
            If -from and -to are both missing, we assume: -from -1d -to now
            If -from is specified but -to is missing, we assume: -to now
            If -from is missing but -to is specified, we assume that -from
                is 1d before -from
            If -from is relative and -to is absolute, we assume that -from
                is relative to now and comes before -to (which means that
                sign is ignored!), so that if today is 20030327:
                    -from -1m -to 20030228       means the same as:
                    -from 20030227 -to 20030228
                Since sign is ignored here, you could also say:
                    -from 1m -to 20030228       or:
                    -from 1m -to yesterday      or:
                    -from +1m -to 20030228      (counterituitive, but legal)
            If -from is absolute and -to is relative, we assume that -to
                is relative to -from and comes after -from, so that:
                    -from 20030228 -to 1d       means the same as:
                    -from 20030228 -to +1d      means the same as:
                    -from 20030228 -to 20030301
                There is one special case: if -to is negative, it
                is interpreted as relative to "now", so:
                    -from 20030228 -to -1d      (from 20030228 to yesterday)
            If both -from and -to are relative, then both are considered to
                be relative to "now" (with one exception), so that:
                    -from -5d -to -4d           means the same as:
                    -from +5d -to 4d            ignore sign on -from, same as:
                    -from 5d -to 4d             but:
                    -from -4d -to -5d           illegal reverse range!
                There is one special case: if -to is positive (i.e., +time),
                then it is relative to -from, so:
                    -from -5d -to +1d           means the same as:
                    -from -5d -to -4d
        ** Span values may only be relative, see above
            If -center is specified, but -span is missing, then -span
            defaults to 1d (i.e., from 12h before to 12h after -center)

Checking your configuration

    thermd -checkconfig [check-args]
        -checkconfig    Check the validity of the config file, and exit
        -config file    Use this as a config file (default=/etc/thermd.conf)
        -verbose        Output a full config file, with all defaults expressed
        -list           Prints a list of logfiles used by thermd (overrides
                        -verbose, and only prints the list)

CGI Script

Theoretically, just put thermd in your CGI area (or a link to the program, if you want to run the daemon froma different directory), and the rest should happen automatically :-) If you don't know how to set up a CGI script, you'll need to familiarize yourself more with your web server - there are too many variables to deal with in this document.

One word of advice - if it doesn't work as expected, look at the error logs for your web server (a lot of people forget to do this).


CONFIGURATION FILE

The configuration file (located in /etc/thermd.conf by default, and specified by the -config runtime option).

Contents of the file (overview)

The configuration file is read once at program startup.

Case Sensitivity
Field names are case-insensitive, but case is preserved (but ignored) in the values.

Style
Configuration entries resemble an Apache config file. If you really want to learn what that looks like, read the documentation for the Perl module Config::General

Comments
Comments start with a pound sign (#) and continue until the end of the line. If you want a pound sign to be part of a name or string, precede it with a backslash, like this:
    Name    Sensor \#1      # That wasn't a comment, but this is

Blank lines
Blank lines are ignored. Erroneous lines will generate warnings, but thermd will try not abort unless it has to.

Global Configuration Attributes

The following attributes are used to configure many of the global attributes of thermd. All of them are optional, and have reasonable default values.

MailFrom
Who alarm messages come from (in email). Default value is ``Thermometer Daemon <root>''. Email addresses are checked for compliance with RFC822. Note that a compliant email address may still not be a valid address, but at least it stands a fighting chance!

PIDFile
Where the process ID of the current instance of the thermd daemon is running (this file is also used as a lockfile to prevent multiple daemons from running - if you want multiple daemons, you will need to specify a different value in each configuration file). Default value is /var/run/thermd.pid.

If you specify a PIDFile of ``/dev/null'' (or whatever your local equivalent of the ``null file'' is), no PIDFile will be created (but you will also lose the ability to lock against competing simultaneous thermd daemons).

SMTPHost
Which mail transfer host to use to send email. If you have qmail, sendmail, postfix, Exchange, etc. running on a different machine from thermd, specify its IP address or hostname (with optional port numbers); you can also specify localhost if your mailer is running on the same machine as thermd. For historical reasons, if you do not specify an SMTPHost, the default is to use a local copy of sendmail. This will change in Version 3.x of thermd.

We strongly recommend using -checkconfig -email to test the correctness of your email setup before putting thermd into production.

SMTPUsername
If you use SMTPHost and the host requires authentication, the username to authenticate with. Default value is not to use authentication.

We strongly recommend using -checkconfig -email to test the correctness of your email setup before putting thermd into production.

SMTPPassword
If you use SMTPHost and the host requires authentication, the password to authenticate with. Default value is not to use authentication.

We strongly recommend using -checkconfig -email to test the correctness of your email setup before putting thermd into production.

Sendmail
Where the locally executable copy of Sendmail is located. Default value is /usr/sbin/sendmail. If you use qmail, postfix, Exchange, etc, then you probably want to specify an SMTPHost instead.

We strongly recommend using -checkconfig -email to test the correctness of your email setup before putting thermd into production.

LogFormat
The format used to store the log data. The two acceptable LogFormat types are (currently) Text and SQL. Default value is Text.

If LogFormat SQL is used, then the remainder of the line contains information about the database and server. The additional parameters are the database type (e.g., mysql, Oracle, etc.), the database name (I use thermd, but you may use any name you like), and the ``standard'' user:pass@host describing the location of the database server.

Valid examples of the LogFormat declaration are:

        LogFormat Text
        LogFormat SQL mysql thermd root@localhost
        LogFormat SQL Informix thermd dvk:monKey@dbhost.klein.com

If LogFormat Text is used, then thermd will create one logfile for each sensor as well as a ``current'' values file. If LogFormat SQL is used, then thermd will create three tables - one for filename to id mapping, another for current values, and a third for historical logging of values.

If LogFormat SQL is used, then three tables will be created. The logfiles table will contain the name of the sensor and a unique SQL log_id (NOTE: if you wish to access the tables with other applications, you may wish to add other descriptive columns to this table). The readings table will contain all historical readings (the columns are the logtime, the log_id for the reading, and the value of the reading. The current table will contain the most recent readings (akin to the current file for LogFormat Text).

LogWrite
Where the logfiles will be written by the daemon. Default value is /var/log/thermd. If LogFormat is SQL, then this directive is ignored.

LogRead
Where the files are read from. Default value is whatever value LogWrite has (which has its own defaults - see above). The reason for the two different variables is when you have an asymmetric system - for example, a chrooted webserver, or a webserver that reads NFS data from a thermd daemon on a different machine. If LogFormat is SQL, then this directive is ignored.

LogInterval
How often we write data to the logfiles. Default value is 10m (10 minutes). Values less than 15s or greater than 30m will generate a warning as possibly too extreme...

TimeZone
If the timezone string is two letters long, it will be printed as-is. If it is three letters long, the script will replace the middle letter with 'D' if daylight savings time is in effect. I would have loved to not use this variable, but there is no neat cross platform way of finding out your current timezone (that I know of - please tell me if there is). Default value is GMT.

DisplayIn
This field now deprecated - thermd will choose a value based on your locale (so the US gets English, the rest of the world gets Metric). Note that if you specificy a value for DisplayIn, it also affects how people viewing your web page will see your data.

What units are used when reporting or graphing (you can choose between English and Metric). This is field is IRRESPECTIVE of how the sensors actually collect data (which for some collectors can be hardware or firmware configured to either C or F for temperature). Default value is Metric (because even though I live in the United States, and in the past 30 years, we have proven ourselves to be in incapable of converting to the metric system, I want to effect change). For backwards compatability, you can also use F (which is equivalent to English) and C (which is equivalent to Metric).

Temperature
What temperature units are used when reporting or graphing (you can choose between C and F). Default value depends on the value of DisplayIn. For English, the default is F, and for Metric the default value is C.

Rainfall
What rainfall units are used when reporting or graphing (you can choose between Inches and mm). Default value depends on the value of DisplayIn. For English, the default is Inches, and for Metric the default value is mm.

Rainfall units also affect the way the MaxBotix range sensors report their values (that is, the MaxBotix will report ranges in Inches or MM, and the C<Rainfall> units also affect C<Range>s)

Barometer
What barometric units are used when reporting or graphing (you can choose between inHg, mmHg, hPa, kPa, millibar or mBar). Default value depends on the value of DisplayIn and/or the language preferences of the web browser being used. For English, the default is inHg, and for Metric the default value is hPa (but kPa for Canada and mBar for England).

WindSpeed
What windspeed units are used when reporting or graphing (you can choose between MPH, KPH, MPS (meters/sec), and Knots). Default value depends on the value of DisplayIn. For English, the default value is MPH, and for Metric the default value is KPH.

Location
Where you have the sensors (I use ``Klone's House''). This value is displayed at the top of the CGI page. Default value is an empty location string.

GPSCoordinates
Also displayed at the top of the CGI page, the text surrounding the MapURL configuration item. Default value is the empty string.

MapURL
Also displayed at the top of the CGI page, the hyperlink of (usually) a map when you click on the GPSCoordinates configuration item text. Default value is the empty string.

SensorOrder
The order in which sensors are displayed in graphs and reports. You may specify ``ID'' (which will sort by sensor ID), ``SubID'' (which will sort by collector name, and then by sensor ID) ``Name'' (which will sort by the names you assign the sensor), ``SubName'' (which will sort by collector name, and then by sensor name), ``PopUp'' (which will sort by the PopUp description of the sensor, and if that is absent, by name), or ``NoSort'' (which will put the sensors in whatever order the hash tables put them. The default value is Name.

GraphWidth
The width of the graph that is created from the CGI script or the -graph option. Default value is 750.

GraphHeight
The height of the graph that is created from the CGI script or the -graph option. Default value is 300.

DefaultView
If this qualifier is used, then that View is marked as the default view, and the view named ``All'' will not be automatically generated. If this qualifier is not used, the the view named ``All'' will be the default.

RefreshRate
The number of minutes between automatic refresh of the CGI page. Default value is 30m.

Blurb
A (potentially long) string that is printed near the top of the CGI page. Default value is the empty string. The string may contain HTML elements.

Blurb2
A (potentially long) string that is printed near the bottom of the CGI page. Default value is the empty string. The string may contain HTML elements.

SyslogFacility
The facility to which syslog messages are logged. Syslog is mainly used for Alarm conditions, but is also used for sensor failure, etc. You can specify the facility which thermd uses. Your choices are console, daemon, user, and local0 through local7. The default value is user. This option is ignored on Windows machines.

SNMPTrapPort
The port number to use for SNMP traps. These are presently only used for the OnOff sensors for the Poseidon and Damocles series from HWg (future expansion depends on user feedback). NOTE: You can use SNMP traps wven if you use the HTTP SubType for the Poseidon and Damocles series.

There is only one trap handler used in thermd, regardless of how many collectors exist that can generate SNMP traps (that is, one handler is responsible for all the traps, and it will figure out which device has sent the trap). This means that all SNMP devices that thermd monitors for traps need to be configured to send traps to this same port.

RSS Block

If it is present, then the RSS block defines the directory where the RSS information is written. If the RSS block is missing, no RSS feed will be generated. Note that it is an RSS block, so you must say something like:

    <RSS /var/www/KLEIN/thermd>
        URL             http://www.klein.com/thermd/
        Webmaster       dan@klein.com
    </RSS>

Unless some other View is marked as the DefaultView, the View named 'all' is automatically included in the RSS feed. See the View block and the RSSName directive below to learn what else can be shown in the RSS feed.

URL
The URL that is listed in the generated XML files. If there is an RSS block, then this field is required and has no default value.

Webmaster
The email address of the webmaster. If there is an RSS block, then this field is required and has no default value.

Every
If present, the value of the Every attribute says ``Every N times the logfiles are written, also generate the RSS files''. The default value is 1, but if you specify a small LogInterval, you may want to say ``Every 2'' or ``Every 3'' to reduce your CPU load a bit...

Nice
In order to conserve CPU resources, the RSS-generting commands are run with the nice command. However, some low-horsepower machines may need to throttle back even more. If present, the value of the Nice attribute is the nicevalue parameter added to the nice command. The default value is blank, which means that the RSS-generating commands will be run at the default nice value. NOTE: The format of the nicevalue argument has become nonstandard across operating systems. Look at the man-pages for your system and shell before using this, and check the syslog files for errors after changing it.

Collector, Sensor, and Actuator Blocks

Thermd supports multiple collectors (something that has one or more sensors on it), and multiple sensors (something that reports a temperature, humidity, wind speed, etc.). Your sensor network can be homo- or heterogenous (my development network has had dozens of sensors on 9 collectors of 7 different types active at one time).

Collector blocks are named (and the name can be anything you like, as long as each collector has a unique name)), so for example you would say:

    <Collector Fred>
        Type    QK145
        Device  /dev/cuaa0
        Scale   F
        <Sensor 1>
            Name        "Computer exhaust"
        </Sensor>
        <Sensor 2>
            Name        Refrigerator
            Adjust      -1
        </Sensor>
        ...
    </Collector>
    <Collector Ethel>
        Type            HA7Net
        IPAddress       wumpus.klein.com
        <Sensor 68000800141A8B10>
            Name        Basement
            Type        Temperature
        </Sensor>
        ...
    </Collector>

Each collector has a number of attributes, and also has included Sensor blocks (one for each sensor that is configured). The attributes for a collector block are as follows:

Type
The type of the collector. The Type is required, and there is no default value. The valid types of collector are:

NOTE: AVTECH Software used to manufacture a serial-line version of the TemPageR. If you have one of these, specify its Type as QK145, and it'll work just fine.

Device
The serial device to which the collector is connected. The Device is required for the QK145, VK011, TEMP08, MaxBotix, and Enersure, and there is no default value. For all other collector types, the Device directive is not allowed (see IPAddress and MountPoint, instead).

NOTE: Thermd also supports the notion of terminal servers for serial devices. In this way, a device like the Digi One SP http://www.digi.com/products/serialservers/digionesp.jsp can be used to provide ether-to-serial connectivity. Any device which requires a Device attribute can also use an IPaddress and Port instead. For configurations such as this, you probably want to configure the device for binary communication with no flow control, and then specify the IPAddress of the device using Port 2101.

NOTE: Some terminal servers do not properly handle binary communications. For example, older versions of the Avocent terminal servers do not pass the NUL character. This is not a problem for ASCII communications, but will cause binary communications used by the Modbus to fail. Caveat emptor!

BaudRate
The speed at which to communicate with the serial device. Generally, you should not specify a baud rate, because the defaults should work. An exception is when you use RealPort mode for a Digi serial interface that works over TCP/IP. In this case, you should try 115200 (and on Linux systems, if this fails, try 0010002). The default value for BaudRate is 2400 for the QK145, and 9600 for all other serial collectors.

IPAddress
The IP Address for the HTTP-based, SNMP-based or terminal-server device that is connected. The address may either be a host name (e.g., sensor.yourcompany.com) or a numeric value (e.g., 10.0.1.2). The Address is required and there is no default value. For other collector types, see Device and MountPoint, instead.

Note: If you are concerned about speed, specify numeric addresses. If you want reliability, names are better. Usually, the speed difference is negligible, but your mileage may vary if your name server is flaky.

Port
The port number to use for IP based connections. For most devices, the default value is 80, the normal value for http. For SNMP-based devices, the default value is 161. For Newport and Omega collectors, the default value is 2000. For serial devices connected via a terminal server, there is no default value.

Username
The username to use for devices that require a username and password (such as the Proliphix thermostats). The default behavior is to not use authentication, so the default value is ``no username''.

Password
The password to use for devices that require a username and password (such as the Proliphix thermostats). The default behavior is to not use authentication, so the default value is ``no password''.

MountPoint
The directory that the one wire file system is mounted for owfs or the top-level file component for owhttpd (this attribute is not used for owshell). If you specify the base directory (that is, '/'), then thermd will read the cached values (note that you specify the cache time when you start owfs or owhttpd). If you want to have thermd read up-to-the-second values, the use the uncached subdirectory of the owfs or owhttpd directory as your MountPoint. For other collector types, the MountPoint directive is not allowed (see Device and IPAddress, instead).>

For owhttpd, the default value is '/'. For owfs, there is no default value - it must be explicitly specified. NOTE that for owhttpd, you must also specify an IPAddress and may specify a Port.

BaseOID
For sensors in an SNMP-based collector, the BaseOID specifies the ``base address'' upon which non-rooted OIDs are based. See the SNMP section for complete details. For the Poseidon series from HWg, the default BaseOID is .1.3.6.1.4.1.21796.3.3 and for the Damocles series from HWg, the default BaseOID is .1.3.6.1.4.1.21796.3.4, (i.e., .iso.org.dod.internet.private.enterprises.hwgroup.charonII); for all other SNMP-based collectors it is .1.3.6.1.2.1 (i.e., .iso.org.dod.internet.mgmt.mib-2). The BaseOID is automatically set for the the Poseidon and Damocles series from HWg, and cannot be changed.

Community
For sensors in an SNMP-based collector, the Community attribute specifies the SNMP community string. Only SNMPv1 is currently supported. The default Community is ``public''.

ModbusAddress
For Modbus devices, the device address on the bus (presently, only the Enersure and Veris use Modbus for communication). The default value is 1.

Scale
The degree scale that the collector reads temperature in - you may choose either C or F for certain collectors. The scale that is reported is set with the Temperature, WindSpeed and Rainfall attributes. The default value for Scale is F (because I live in the United States, and in the past 30 years, we have proven ourselves to be in incapable of converting to the metric system, sorry, my government and business leaders are stupid).
QK145 and VK011
You must specify the scale manually for these devices. Yes, I know that both the QK145 and the VK011 advertise the scale that they read in. However, in order to ascertain that scale, you must open the device and read from it - and if the logging daemon is running, the reporting and CGI scripts cannot open the device. I could change the script so that it would record the value in the log files, but that would require users to manually alter their log data, and that is more ``risky'' than many people would like. So, you must specify the scale manually.

owfs, owhttpd and owshell
The default Scale is C, but may be overridden.

HA7Net
Scale is not allowed (it only reads in C).

TEMP08, RoomAlert, TemPageR, MiniGoose, WeatherGoose, SuperGoose, RacSense, PowerGoose, HWg and Enersure
Scale is also not allowed, because it is automatically configured by thermd to read in C

Note that the scale thermd reads in is distinct from the scale it reports values in - see English, Metric, Temperature, Rainfall, etc., as well as information on Localization. For non-temperature devices (humidity, rainfall, power, etc.), the Scale attribute is not allowed.

ReadOnly
Any collector which is marked ReadOnly will not attempt to collect or log data, but thermd will report on existing historical log data. This is useful if you have decommissioned a collector, but still wish to view its data. See also ReadOnly for sensors.

NOTE that if you do not specify a sensor's name, thermd will attempt to read the sensor names from the device for some collectors. If the collector is marked ReadOnly, thermd will not attempt to contact the device at all (and some default names or types may be not available).

PollInterval
Any collector which must be polled for data (which means anything except the QK145, VK011, MaxBotix, or TEMP08, is typically polled once every minute or so for its data. These values are averaged or summed and then logged every LogInterval minutes. Setting PollInterval can change the speed at which the collector is polled.

The polling interval has two effects. The first is how granular the logged averages are - if you have a sensor which changes rapidly or has spiky values, you may want a shorter PollInterval to catch the changes. Second is how often the current-values-logfile is updated. While the historical logs are updated every LogInterval minutes, the ``current'' file is updated as fast as the most quickly changing PollInterval.

PollInterval may be any value between 5s (for 5 seconds) and 5m (for 5 minutes). In no event can PollInterval be longer than LogInterval. The default value is such that a collector will be polled roughly 10 times for every LogInterval. For SmartNet devices, the default value is 5m, to reduce rounding errors on the WattHour sensor.

StaleAfter
This attribute is only value for Wunderground collectors, and indicates when the collector should consider the personal weather station data to be stale. Each personal weather station is supposed to update its information at least every hour, and data that is older than StaleAfter will not be reported to your local thermd logfiles. The default value is 65m, which is fine for hourly-updated weather stations, but you might want to decrease it when monitoring rapid-fire weather stations.

Amperage
For the Veris H8030, H8031, H8035, and H8036, this specifies the amperage at which the Power Meter is operating. For the H8030/H8031, the possible values are 100 or 300; for the H8035/H8036 the possible values are 100, 300, 400, 800, 1600, and 2400. There is no default value.

Sensors

Sensors report on their environment - for example, temperature, humidity, etc. (some collectors also have Actuators, see below). A sensor block (which must have a name) specifies all the attributes of a specific sensor. The sensor naming system depends on the collector, but each sensor must have a unique name:

QK145 and VK011
For the QK145 and the VK011, the sensor name must be an integer number between 1..4, and corresponds to the physical sensor number.

MaxBotix
For the MaxBotix, there is only one sensor, and it is named Range (you must nevertheless still specify both a Collector and a Sensor).

One Wire bus devices
For the HA7Net, SmartNet family, WeatherGoose family, RacSense, PowerGoose, owfs, and TEMP08, the sensor name must be the 16-digit hexadecimal 1-wire sensor serial number (for owfs and owhttpd, this number may be in any of the allowed f[.]i[[.]c] formats; for the SmartNet, sensors on a SmartPDU may have a hyphenated suffix).

Some sensors measure more than one thing (for example, temperature and humidity on DS2438-based sensors, pressure and temperature for the AAG TAI8570 and for the multiple built-in sensors for the RacSense, WeatherGoose or SmartNet family). For these sensors, you must specify distinct sensor blocks to read each value, and the thermd sensor names must be unique. To do this, append a .N to the hexadecimal sensor number, where N is a number or letter (see the Sample configuration file for an example).

Enersure
For the Enersure, the sensor names are of the format Keyn, where Key is one of:
        V (for VRMS)
        I (for IRMS)
        P (for Power Factor)
        W (for Watts)
        K (for Watt Hours)

and n is a number between 1 and 84 (up to 4 analog boards with up to 21 circuits monitored per board). Thus for circuit #1, there could be up to 5 sensors named V1, I1, P1, W1, and K1 (then V2, I2, etc. for circuit #2, and so on).

Veris
For the Veris H8030 and Veris H8035, the sensor names are the Modbus register address between 40001 and 40003

For the Veris H8031 and Veris H8036, the sensor names are the Modbus register address between 40001 and 40027.

In all cases, the type of the sensor type is directly corellated with the value that can be read from it. NOTE: On the hardware device, register 40001 and 40002 are the LSW and MSW of the Energy consumption, respectively. In thermd, sensor 40001 is the combination of both values, and sensor 40002 is not accessable. NOTE: these are the integer registers - thermd does not use the floating point registers, but instead reads the integer values and multipies by a constant determined by the Amperage setting for the unit).

EM1
For the EM1, the sensor name must be one of T1, H1, W1, T2, H2, W2, T3, H3, W3, T4, H4, or W4 (for Block 1 temperature, humidity, and wetness sensors, etc).

Proliphix
For the Proliphix thermostats, the sensor name must be one of T1, T2, or T3 for temperature (external sensors T2 and T3 are not available on the NT10e nor the NT100e/h), or H1 (for the external humidity sensor on the NT150e/h or TM250e/h). Additionally, the sensor TA is the averaged temperature as returned by the Proliphix. This is available for all models, but only really makes sense for those thermostats with external sensors that are enabled for averaging.

Additionally, the sensor name may be S, which is the state of the HVAC, and can have the following values: 1=Initializing, 2=Off, 3=Heat, 4=Heat2 (professional series only), 5=Heat3 (Heat Pump only), 6=Cool, 7=Cool2 (professional series only), 8=Delay, 9=ResetRelays. Future versions of thermd will make prettier graphs using these values.

The device type must be specified as a full model number (e.g., Proliphix NT120h or Proliphix 10e).

AVTECH Devices
TemPageR
For the TemPageR, the sensor name must be one of T1 (temperature sensor in plug #1), T2, T3, or T4.

RoomAlert 7E
For the RoomAlert 7E, the sensor name must be one of T1, T2, T3, T4 (temperature), S1, S2, or S3 (switch).

RoomAlert 11E
For the RoomAlert 11E, the sensor name must be one of T1, T2, T3 (temperature), H1, H2, H3 (humidity), S1, S2 ... S8 (switch).

RoomAlert 24e
For the RoomAlert 24e, the sensor name must be one of T1, T2 ... T6 (temperature), H1, H2 ... H6 (humidity), S1, S2 ... S16 (switch), InternalT or InternalH..

RoomAlert 26W
For the RoomAlert 26W, the sensor name must be one of T0 (the internal temperature sensor) T1, T2 ... T6 (external temperature sensors), H0 (the internal humidity sensor) H1, H2 ... H6 (external humidity sensors), S1, S2 ... S16 (switch), Flood, or Power. Additionally, WiSH sensors are identified by their 12-hexdigit serial numbers and the sensor type.

The sensor type may be T0 for internal temperature sensor or T1, T2, H1, H2, or S1 for external temperature, humidity or switch sensors (for example, ``DAEDA8000000T0'' is the temperature sensor inside WiSH serial number DAEDA8000000, and ``DAEDA8000000T1'' and ``DAEDA8000000H1'' are temperature and humidity for external device #1 connected to that WiSH.

Newport and Omega iServer Microservers
NOTE: Almost all of the Newport and Omega iServer Microservers all provide a means for reading temperature (and dewpoint) in either Celsius or Fahrenheit, and pressure in inHG, mmHg, kPA, or PSI (depending on what is being measured). However, thermd only monitors in Celsius, inHG or kPA, and then displays the monitored values in the units of your choice. Therefore, use SRTC for temperature readings and not SRTF, etc. If you must override the locale settings for graphing, see the DisplayIn directive.
iBTHX and IBTX
For the iBTX and iBTHX, the sensor name may be SRTC for temperature, SRH2 for humidity, SRDC2 for dewpoint, and SRHi for barometric pressure.

IBTX-M
For the iBTX-M the sensor name may be SRTC for temperature, or SRHi for barometric pressure.

IPTX-D and IPTX-W
For the iPTX-D and IPTX-W the sensor name may be SRTC for temperature or SRHb for pressure.

ICTX
For the iCTX the sensor name may be SRTC, SRHC, or SRDC for the three temperatures available on the device.

iTHX-M
For the iTHX-M the sensor name may be SRT for temperature, SRH for humidity, SRD for dewpoint.

iTHX-W and iTHX-2
For the iTHX-W and iTHX-2 the sensor name may be SRTC or SRTC2 for temperature, SRH or SRH2 for humidity, and SRDC or SRDC2 for dewpoint.

Poseidon and Damocles series from HWg
For the Poseidon series from HWg, sensor names must either be the letter B followed by a single digit (for dry contact inputs) or the 2 through 5-digit Sensor IDs.

For the Damocles series from HWg, sensor names must be the letter B followed by one or two digits (for binary dry contact inputs).

The sensor type (which may be explicitly specified for clarity with SubType SNMP configuratuon, but which is automatically checked for validity; and which must be explicitly set if you use SubType HTTP configuration) and OID are dynamically determined based on the sensor names. Note that the HWg collectors use SNMP or HTTP for communication, but many of the details of SNMP are hidden from view to ease configuration.

One detail that is exposed is the SNMP trap handling behavior (which is usable regardless of query SubType). See the SNMPTrapPort global attribute and AllowSNMPTraps in the OnOff sensor type for details.

Other SNMP-based devices
For all other SNMP-based devices, the sensor name must simply be an alphanumeric string. We recommend using the OID name, but any alphanumeric string is acceptable. See also the Instance block.

CommandLine collector
The sensor name is any mix of letters, digits, and underscores you wish to use. See the Command attribute for important details.

Wunderground collector
The Wunderground collectors allow you to read data published by other personal weather stations (see the special StaleAfter attribute). This enables you to compare other stations' data with your own. The sensor names are limited to 7 types, and must be: T for temperature, H for humidity, B for barometer, P for dewpoint, S for wind speed, G for wind gust, and D for wind direction.

Sensor Attributes

Regardless of the collector or sensor type, the sensor attributes are:

Name
A descriptive name for the sensor. You can use any description you like. Some data collectors (the EM1, SmartNet, RoomAlert series, the Poseidon and Damocles series from HWg) have the ability to configure the sensor name on the data collector. For these collectors, the default value will be obtained from the collector. For all other collectors, the default value is Sensor N@K, where N is the sensor name and K is the collector name.

Type
The kind of sensor this is. This field is optional for DS1820, DS18B20 and DS1822 sensors (since they can only be temperature sensors), for all sensors on the QK145 and VK011 (since they can only be temperature sensors), for all sensors on the Enersure, RoomAlert, EM1 or Proliphix (since their name specifies their type), and for all sensors on the Poseidon and Damocles series from HWg (since the sensor type can be queried from the device), and for the Range sensor on the MaxBotix sonar sensor, but is required for other sensors. (For devices that do not use 1wire sensors, ignore the ``DSnnnn'' numbers). The valid types are:
Temperature
This is the default for all DS1820, DS18S20, DS18B20, DS1822 or DS2760 devices (and for the temperature sensors in the QK145, VK011, RoomAlert, EM1 and Proliphix) but still needs to be specified for DS2438 temperature + A/D devices. For the TEMP08, if Temperature is the only type specified for a dual sensor, the only temperature will be recorded.

NOTE: for DS2760 devices, a Thermocouple type must also be specified (presently only available for owfs, owhttpd, and HA7Net data collectors).

Humidity
For the TEMP08, HA7Net and OWFS, a single DS2438 can provide two measurements (temperature and humidity). For the Poseidon series from HWg, the DS2438 sensors only measure humidity. For the WeatherGoose (etc.), and the RacSense, some sensors can also read airflow. If you wish to log humidity, use this type (and use temperature with a separate sensor ID for the other measurement from the DS2438 sensor). For the HA7Net, a DS2406 or DS2407 is also used to measure humidity, and has a single sensor per device. For the RoomAlert, EM1 and Proliphix>, humidity is measured with a device with a single address.

DewPoint
This sensor is available natively on the SmartSenseTH, and is available as a built-in computation for any pair of temperature and humidity devices. See Derived Sensors for details.

Range
This sensor is only available on the MaxBotix line of sonar rangefinders.

Humidex
This sensor is available as a built-in computation for any pair of temperature and humidity devices. See Derived Sensors for details.

HeatIndex
This sensor is available as a built-in computation for any pair of temperature and humidity devices. See Derived Sensors for details.

Barometer
For the TEMP08, HA7Net and OWFS, a Hobby Boards barometer sensor (built on the DS2438) can provide two measurements. If you wish to log barometric pressure, use this type (temperature is the other measurement from the DS2438 sensor). See also Slope and Intercept for barometer calibration.

Sunlight
For the HA7Net, a Hobby Boards solar radiation detector (built on the DS2438) can provide two measurements. If you wish to log sunlight, use this type (temperature is the other measurement from the DS2438 sensor). See also MultiplyBy.

Direction
For the One Wire Weather device, wind direction is measured using a DS2450. See also AdjustBy and Inverted.

Speed
For the One Wire Weather device, wind speed is measured with a DS2423. If you specify type ``Speed'', only speed (and not gusts) will be recorded. See next for how to record gusts with a re-specification of the same sensor name and a numeric suffix. See also Channel (which defaults to Channel A).

The Speed sensor is implemented internally as a Counter with a SubType ``AvgRate''.

Gust
This type allows you to record gusts in wind speed from the One Wire Weather device. See also Channel (which defaults to Channel A).

The Gust sensor is implemented internally as a Counter with a SubType ``MaxRate''.

WindChill
This sensor is available as a built-in computation for any pair of temperature and wind speed devices. See Derived Sensors for details.

Rain
AAG sells a TAI8575B rain gauge that is based on the La Crosse Technology WS-7047U. The gauge uses a DS2423 to measure 0.01`` increments in rainfall. If you specify type ''Rain``, then this device is assumed. See also InactivityReset (which defaults to 12h for rain sensors) and Channel (which defaults to Channel A).

The Rain sensor is implemented internally as a Counter with a SubType ``Total''.

Lightning
The lightning gauge uses a DS2423 to count nearby lightning strikes. If you specify type ``Lightning'', then this device is assumed. See also Channel (which defaults to Channel A).

The Lightning sensor is implemented internally as a Counter with a SubType ``Count''.

Wetness
This sensor type is currently only valid for the wetness sensor on the EM1. If you have a HobbyBoards Leaf Wetness sensor, please contact me for support.

OnOff
This sensor is a on/off sensor currently supported only on the Poseidon and Damocles collectors from HWg, the HA7Net, and the Room Alert. A closed (shorted) sensor is considered ``on''. See also OnValue and OffValue. For SNMP devices, see also SNMPOnValue and SNMPOffValue. For the HA7Net, see also PIO.

For the Poseison and the Damocles series from HWg, the sensor name must be the letter B followed by a one or two digit sensor number (B1, B2, etc.). They are normally only read when the device is polled. This means that if your PollInterval is 1m, changes in OnOff sensors will only be tested every minute. If the OnOff sensor is connected to a door-sensor, and the door opens and closes between readings, the state-change will not be detected.

However, thermd can also use an SNMP trap handler to register changes to the OnOff sensors. You must configure your Poseidon or Damocles collectors to send SNMP traps to the same machine that thermd is running on. See the global TrapPort attribute and the sensor-specific AllowTraps.

Airflow
This is the airflow sensor available only with the WeatherGoose and RacSense family, and measures relative airflow.

Sound
This is the sound sensor available only with the WeatherGoose and RacSense family.

Light
This is the light sensor available only with the WeatherGoose and RacSense family.

IO
This is the IO sensor available only with the WeatherGoose and RacSense family.

Volts
This is the voltage sensor available only with the PowerGoose, Veris, RacSense, EnerSure, and Poseidon series.

Volts-Min
This is the voltage sensor available only with the PowerGoose and RacSense.

Volts-Max
This is the voltage sensor available only with the PowerGoose and RacSense.

Volts-Peak
This is the voltage sensor available only with the PowerGoose and RacSense.

VA
This is the volt-amp sensor available only with the Veris.

VAR
This is the reactive power volt-amp sensor available only with the Veris.

Amps
This is the amperage sensor available only with the PowerGoose, Veris, RacSense, and EnerSure.

Amps-Peak
This is the amperage sensor available only with the PowerGoose and RacSense.

MilliAmps
This is the milliamperage sensor available only with the Poseidon series.

Real-Power
This is the power sensor available only with the PowerGoose and RacSense.

Apparent-Power
This is the power sensor available only with the PowerGoose and RacSense.

Watts
This is the wattage sensor available on the EnerSure (and is a derived value for the SmartWatt). Wattage is logged as the average value measured over the LogInterval.

KWatts
This is the wattage sensor available on the Veris.

Wh
This is the watt-hour sensor available with the EnerSure and SmartWatt. Watt-hours measured cumulatively over the LogInterval.

KWh
This is the Kwatt-hour sensor available with the RacSense and Veris.

Power-Factor
This is the power sensor available only with the PowerGoose, Veris, RacSense, and EnerSure.

Counter
This is a generic use of a DS2423 2-channel counter, or a generic SNMP counter value (that is, a reading whose current value is measured relative to the previous value, and which recognizes rollover of a 32-bit numbers). See also SubType, Channel, MultiplyBy, Units, and InactivityReset.

Counters have five distinct SubTypes, one of which must be chosen.

AvgRate
The value supplied by the counter is the average number of counts per second for the logging period (see LogInterval). You may wish to adjust the value to an appropriate Scale by using MultiplyBy.

The Speed sensor is implemented as a special ``AvgRate'' counter.

MinRate
The value supplied by the counter is the minimum number of counts per second for the logging period (see LogInterval), measured every PollInterval. You may wish to adjust the value to an appropriate scale by using MultiplyBy.

MaxRate
The value supplied by the counter is the maximum number of counts per second for the logging period (see LogInterval), measured every PollInterval. You may wish to adjust the value to an appropriate scale by using MultiplyBy.

The Gust sensor is implemented as a special ``MaxRate'' counter.

Count
The value supplied by the counter is the number of counts for the logging period (see LogInterval). You may wish to adjust the value to an appropriate Scale by using MultiplyBy.

The Lightning sensor is implemented as a special ``Count'' counter.

Total
The value supplied by the counter is the sum of number of counts. You must also specify a value for InactvityReset, which is the the time after which (if there is no activity on the counter), the accumulated value will be reset to 0. You may wish to adjust the value to an appropriate Scale by using MultiplyBy.

The Rain sensor is implemented as a special ``Total'' counter.

Raw
The value supplied by the counter is the raw number of counts provided by the counter. For those counters with a ``memory'' (that is, a battery backup), the value will never decrease until it wraps around (typically when it exceeds a 32-bit signed or unsigned number, either 2,147,483,648 or 4,294,967,296). You may wish to adjust the value to an appropriate Scale by using MultiplyBy.

Gauge
This is a generic SNMP gauge (that is, a reading whose current value is significant, irrespective of the previous value). See also MultiplyBy and Units.

The Gauge sensor is implemented as a special ``Raw'' counter.

Math
This sensor provides a mathematical computation based on other sensors. See Derived Sensors for details.

GraphColor
The color that this sensor is graphed in (see also Show+ for the ability to override this value in a specific View). Your choices are red, teal, blue, fuschia, olive, aqua, green, black, orange, purple, silver, white, pink, yellow, lime, gray, navy, and maroon. The default value is an as-yet unused color (excluding white, gray, or silver). Note: due to the non-linear nature of parsing the configuration file, we cannot guarantee that colors will be unique unless every color is automatically selected. We therefore make a best-effort to pick an unused color, but mistakes are guaranteed to be possible.

If you do not like the colors listed above, you can specify a color as a 6-digit hexadecimal RGB color starting with a #-sign. Note that you need to escape the #-sign (since it is a comment character) as:

        GraphColor      \#a0a0FF

LineType
The type of line that this sensor is graphed in (see also Show+ for the ability to override this value in a specific View). Your choices are solid or dotted. The default value is solid. The values of dashed and dotdashed may also be used, but these do not show up well.

PopUp
If this attribute is present, a popup tooltip will appear when you mouse-over the current readings of the sensor. PopUp may contain multiple lines of text if you use the ``here document'' format (see Blurb in the sample config file below. Default value is no popup.

NOTE: Single quote characters must be escaped, as \'.

LogFile
Where the data is logged. An absolute filename (that is, a file starting with a '/') is put where you say, otherwise the filenames are relative to LogRead and LogWrite, as appropriate. The default filename is in a directory with the same name as the collector, and a filename the same as the sensor name. So for
        <Collector Upstairs>
            <Sensor 1>

the default logfile would be $LogRead/Upstairs/1. Each sensor must have a unique filename.

ReadOnly
Any Sensor which is marked ReadOnly will not collect or log data, but thermd will report on existing historical log data. This is useful if you have decommissioned a sensor (or it is behaving erratically), but still wish to view it's data. See also ReadOnly for collectors.

AdjustBy
The number to add (or subtract) from every data reading. Not all DS1820's are the same, and there is an expected variance (likewise, humidity and barometer sensors may vary). If you calibrate your sensors, then this is a means whereby you can define that calibration. Note that the value is adjusted after the value is read, but before it is logged, so your logs will reflect the adjusted values. Note also that the scale of AdjustBy is the same as whatever Scale your collector is configured for. Thermd does not allow you to adjust wind speed, wind gust, lightning, rainfall, or on/off sensors. For Counter sensors, see MultiplyBy; for OnOff sensors, see OnValue and OffValue; for Direction sensors, AdjustBy is always calculated so that the direction value will always be in the range of [0,360). If you use the Temp08 collector, you should probably use the NOR command on the Temp08 to set the North value.

MultiplyBy
For counters, the value to attribute to each ``click'' of the counter. For gauges, the scaling factor for the gauge. For Sunlight sensors, the scaling factor for the raw current measurement.

For example, certain European power meters have an LED that blinks 500 times for every kWH (and with a photodetector coupled with a counter, you can measure your power consumption). With a LogInterval of 5 minutes, a MultiplyBy of 24 will display the counter value as Watts. The MultiplyBy value may be fractional value if you really want to divide instead. The default value is 1. MultiplyBy may not be 0.

Inverted
In rare cases the sensor board in the OneWireWeather system is mounted upside down (or maybe you mounted the whole unit upside down - the anemometer goes on top!). There is a WDR command on the Temp08 to handle this, and the Inverted attribute will do the same.

Resolution
This attribute is only valid for DS18B20 and DS1822 sensors and the HA7Net, owfs and owhttpd collectors. It specifies the number of bits of resolution that the DS18B20 or DS1822 should read (the fewer bits, the faster the sensor may be polled). The default resolution is 12 bits, and if specified, must be a value between 9 and 12.

Thermocouple
This attribute is only valid for DS2790 sensors and owfs, owhttpd, and HA7Net collectors. It specifies the thermocouple type being used, and must be one of B, E, J, K, N, R, S or T. There is no default value.

InactivityReset
This attribute is only valid for Rain and Counter (SubType Total) sensors. Since rainfall is measured cumulatively for at most a period of time (and not forever), the InactivityReset attribute allows you to specify a time after which the counter will be reset. When there has not been any activity on a counter for the InactivityReset period (that is, the counter has not increased at all), it will be reset to zero. The default value is 12h for Rain, but must be specified for any other Total type Counter.

Channel
This attribute is valid for Lightning, Rain, Speed, Gust, and Counter sensors. Since DS2423 sensors have two counters, you must specifiy either Channel A or Channel B. The default value for Lignting, Rain, Speed, and Gust sensors is Channel A (since they come pre-built and usually use Channel A), but there is no default value for Counters (since they are usually home-brew and can use either or both channels).

Hide
By default, thermd puts all sensors into a view named ``All'' (see the View documentation, below). If you wish to exclude a sensor from this global view, the Hide attribute is used (or you can disable the ``All'' view by specifying that another view is the DefaultView. Note that data is still collected for the sensor even if it is hidden! However, unless the sensor is explicitly placed in a View, the data will be invisible.

OnValue
For sensors of type OnOff, this attribute specifies the numeric value the sensor will be logged at when it is on. Optionally combined with OffValue, these allow you to graph many OnOff sensors on the same graph and still be able to see them as separate lines. The default value for OnValue is 1.

OffValue
For sensors of type OnOff, this attribute specifies the numeric value the sensor will be logged at when it is off. The default value for OffValue is 0.

SNMPOnValue
For SNMP sensors of type OnOff, this attribute specifies the numeric value that the sensor reports when it is on. The default value is 1.

SNMPOffValue
For SNMP sensors of type OnOff, this attribute specifies the numeric value that the sensor reports when it is off. The default value is 2.

AllowSNMPTraps
For SNMP sensors of type OnOff (this includes the Poseison and Damocles data collectors), this attribute states that the sensor will also respond to SNMP Traps (see SNMPTrapPort) in addition to changes detected by periodically polling its value.

You must configure your SNMP-enabled device to send SNMP traps - they do not happen by default. The AllowSNMPTraps directive merely instructs Ithermd> to pay attention to them if they are received.

PIO
For sensors of type OnOff on the HA7Net (the D2P family, built from the DS2406 with two PIO sensors), this attribute specifies the PIO channel. The allowable values are A or B. There is no default value for the PIO attribute, and it is required for the D2P sensors.

OID
For sensors in an SNMP-based collector, the OID specifies the ``address'' to read. The OID may be relative to the BaseOID or absolute. See the SNMP section for complete details. For the Poseidon and Damocles series from HWg, the OID is not used - instead the sensor name is used to automatically determine the OID.

Instance
For sensors in an SNMP-based collector, an Instance block is used to define an address class. See the SNMP section for complete details. This is not used for the Poseidon and Damocles series from HWg.

Units
For sensors of type Counter or Gauge, the units that measurements are reported in (for example 'W' for Watts, 'F' for degrees Fahrenheit, or 'Bq' for Becquerel, number of recorded decays per second in a Geiger counter). The default values are Count and Gauge, respectively.

Slope
This attribute is only valid for DS2438-based barometer sensors. For sensors of type Barometer (presently, this is only supported as a HobbyBoards sensor http://www.hobby-boards.com/catalog/product_info.php on the HA7Net), you must specify a slope and intercept value for barometric pressure caluculations. If you have purchased your barometer as a precalibrated product, these numbers can be calculated at http://www.hobby-boards.com/catalog/baro_calc.php. If you have built your barometer as a kit, or have changed your elevation, you must first (re)calibrate your barometer via this page: http://www.hobby-boards.com/catalog/howto_barometer.php. Once you have done this, specify the Slope and an Intercept attributes that have been computed.

There is no default value, and a Slope must be specified for all sensors of type Barometer. Incorrect values will result in errorneous barometric pressure readings.

Intercept
This attribute is only valid for DS2438-based barometer sensors. See Slope (above) for an explanation of Intercept.

There is no default value, and an Intercept must be specified for all sensors of type Barometer. Incorrect values will result in errorneous barometric pressure readings.

Command
This attribute is valid only for sensors in a CommandLine collector. This causes the specified command to be run (which output a single value on a single line). The command may be a pipeline to edit the output of a more general command. NOTE that the command(s) run with the same UID as thermd, and depending on your configuration, this may present a security risk to your system! The program string is passed UNEDITED and UNCHECKED to the shell. Caveat Emptor!
        <Collector DiskTemperartures>
            Type        CommandLine
            <Sensor Temp_ad0>
                Name    "DiskTemp-ad0"
                Type    Temperature
                Command "/usr/local/sbin/smartctl --attributes /dev/ad0 | egrep '^194' | cut -c88-"
            </Sensor>
            <Sensor Temp_ad3>
                Name    "DiskTemp-ad3"
                Type    Temperature
                Command "/usr/local/sbin/smartctl --attributes /dev/ad3 | egrep '^194' | cut -c88-"
            </Sensor>
        </Collector>

Alarms

An Alarm block defines an extraordinary condition that you want to know about. Each Alarm must be named, and contains one or more alarm-related directives. The name of the alarm is arbitrary, so long as no two alarms for a single sensor have the same name. It is legal to specify multiple alarms per sensor, so you can have an Above and a Below alarm, three different Above alarms, etc. An alarm might look like this:

            <Alarm Roasting>
                Above   95
                ResetAt 90
                Times   08:00 - 23:59
                Notify  Fred Murwick <fred@lonewolf.com>
                Notify  fred-page@lonewolf.com, quincy-page@lonewolf.com
                Syslog  crit
                Close           A1@Mambo
                LockClose       A3@Salsa
                Open            A2@Rhumba
                Exec    "shutdown -h 5"
            </Alarm>

This would cause an alarm to be sounded when the temperature exceeded 95 degrees, and both Fred and Quincy would receive a pager message (in addition Fred receiving a regular email, a message being recorded in syslog, the switches A1 on the collector named Mambo and A3 on Salsa being closed, the switch A2 on the collector Rhumba being opened, and the ``shutdown'' program will be run) - but only if the alarm action occurred between 8am and one minute before midnight.

Once triggered, the alarm condition will reset only after the temperature drops below 90 degrees (note that resetting the alarm will also cause the switch A1@Mambo (but not A3@Salsa) to be Opened, and A2@Rhumba to be Closed, but the shutdown program will NOT be stopped if it is still running).

NOTE: See the global configuration options SMTPHost and Sendmail and the switches -checkconfig -email before using email-alarms.

IMPLEMENTATION NOTE: Since some sensors can occasionally give erratic values, Alarms are (generally) only triggered after the average of 5 consecutive readings exceeds the alarm criteria. This means that Alarms are triggered after some delay. If you wish a speedier response, you may consider changing the collector's PollInterval. If you need the ability to have alarms trigger on the first reading that exceeds the alarm criteria, write to dan@klein.com, and I will implement the necessary changes as a configuration option.

IMPLEMENTATION NOTE: Alarms are not evaluated in any particular order. Thus if one alarm opens a switch and another alarm closes a switch, and both alarms trigger (or reset) at the same time, the final state of the switch cannot be predicted.

The attributes for Alarm blocks are:

Above
The value (in whatever Scale the sensor reads) above which the alarm will be sounded. There is no default value, and you must specify either Above or Below if you have an alarm block.

Below
The value (in whatever Scale the sensor reads) below which the alarm will be sounded. There is no default value, and you must specify either Above or Below if you have an alarm block.

ResetAt
The value (in whatever Scale the sensor reads) at which the alarm reset for reissuance. If the alarm is an Above alarm, then ResetAt must be less than the Above value (and greated than a Below value). The default value is 2 units above/below the alarm value.

Alarm Actions
For every Alarm, you must specify at least one of the Notify, Syslog, Open, LockOpen, Close, LockClose, or Exec actions. You may specify more than one action, and more than one instance of any action.. There is no default alarm action - you must choose one or more action.
Notify
Who to notify (via email) if the alarm condition exists. You may specify more than one Notify field, and all will be notified (you can also combine multiple Notify fields into a comma-separated list of reciepients on one line). Email addresses are checked for compliance with RFC822. Note that a compliant email address may still not be a valid address, but at least it stands a fighting chance!

Syslog priority
Notify via syslog that the the alarm condition exists (see also the SyslogFacility global parameter). The default is not to use Syslog for alarms, although syslog will still be used to flag other conditions such as failed sensors, system startup, restart, etc. The value of this attribute is the message priority. Your choices are (in order of increasing severity) info, notice, warning, err, crit, alert, emerg. This option is ignored on Windows machines.

Open
Cause a specied OnOff switch to be opened (if the switch is defined to be Normally Open, it will remain open). When the alarm is reset, the same switch will be closed. Actuator names are referenced the same as in Show and Show+, below. You may specify more than one Open attribute.

NOTE: The actuator and collector names referenced in Open and LockOpen are Case SeNSiTive, and must exactly match the declared names.

LockOpen
Cause a specied OnOff switch to be opened (if the switch is defined to be Normally Open, it will remain open). As opposed to Open, with LockOpen, when the alarm is reset, the switch stays open (if you want it to close, you must have a different alarm to close it, or restart the server, which will set the switch to its Normally position). Actuator names are referenced the same as in Show and Show+, below. You may specify more than one LockOpen attribute.

Close
Cause a specified OnOff switch to be closed (if the switch is defined to be Normally Closed, it will remain closed). When the alarm is reset, the same switch will be opened. Actuator names are referenced the same as was in Show and Show+, below. You may specify more than one Close attribute.

NOTE: The actuator and collector names referenced in Close and LockClose are Case SeNSiTive, and must exactly match the declared names.

LockClose
Cause a specied OnOff switch to be closed (if the switch is defined to be Normally Closed, it will remain closed). As opposed to Close, with LockClose, when the alarm is reset, the switch stays closed (if you want it to open, you must have a different alarm to open it, or restart the server, which will set the switch to its Normally position). Actuator names are referenced the same as in Show and Show+, below. You may specify more than one LockClose attribute.

Exec
Cause the specified program to be run. NOTE that the program runs with the same UID as thermd, and depending on your configuration, this may present a security risk to your system! The program string is passed UNEDITED and UNCHECKED to the shell. Caveat Emptor!

Dates
The (inclusive) range of dates on which the alarm will be sounded. Dates are represented as a hyphen-separated pair of dates, each expressed as DayNum MonthName (where MonthName is exactly 3 letters long, for example, 12 Aug or Aug 12). The default value is 1 Jan - 31 Dec. Dates are assumed to be sequential, so it is legal to have a date range that wraps around the new year, for example 21 Dec - 21 Mar.

The month names used in Dates may either be the English abbreviations or if the appropriate internationalization code exists, the locale month names of the server (so on a German server, you can use either of 31 Oct - 25 Dec or 31 Okt - 25 Dez).

Times
The (inclusive) range of times on which the alarm will be sounded. Times are represented as a hyphen-separated pair of times, each expressed as Hour:Minute in 24-hour format (for example, 13:27). The default value is 00:00 - 23:59. Times are assumed to be sequential, so it is legal to have a time range that wraps around midnight, for example 23:00 - 01:15.

Subject
If the Notify action is selected for an alarm, this attribute specifies the subject message in the alarm email. The default value is ``Temperature Alert!''.

Message
If the Notify action is selected for an alarm, this attribute specifies the message text in the alarm email. This field is a printf string, and has three parameters - the name of the sensor, the temperature, and the scale. The default is "The temperature in %s is %.3f degrees %s". If you do not want to print a field (because you want to use a short version, for example, then the printf field of %.0s will supress it, so your message might be as simple as "Alarm 2:%.0s%d%s" or "%s over temp". Since thermd is designed for temperature, you'll need to change the message if you're reporting on humidity or wind speed, for example. Remember this is written in Perl, so even though the temperature is a floating point number, you can print it as %d if you want.

Derived Sensors

There is a special type of pseudo-collector whose type is Derived. Within this collector, there can be a number of special computed sensors (that is, sensors whose value is mathematically based on other sensors). These sensors have all of the standard attributes (Name, Type, GraphColor, Alarm, etc), but also have special attributes found only in derived sensors. The sensor types and their special attributes are:

Math
The Math sensor is used to compute values based on arbitrary mathematical equations using other sensors (the sensors are referenced by their names N@K, where N is the sensor name and K is the collector name). The one special Math attribute is:
Value
This attribute contains the mathematical expression used to compute the sensor's value. The following example shows four real sensors on two real collectors (Temperature, Speed and Gust are builtin types, and Slack is a special Counter that measures the minimum windspeed for a LogInterval). It also shows three computed sensors on a derived collector. The first derived sensor computes the turbulence (the difference between the highest and lowest windspeed), while the second computes the mean of the highest and lowest windspeed (which is different from the average windspeed calculated by the Speed sensor). The third sensor computes WindChill (see below), and the fourth sensor (for people living in Southern California) only shows winds which are above 20MPH and between NNW and ENE (the Santa Ana's).
    <Collector Winken>
        Type            QK145
        <Sensor 1>
            Name        Outside
            Type        Temperature
        </Sensor>
    </Collector>
    <Collector Blinken>
        Type            HA7Net
        IPAddress       ha7net.klein.com
        <Sensor 1500000001622C1D.s>
            Name        Speed
            Type        Speed
        </Sensor>
        <Sensor 1500000001622C1D.g>
            Name        Gust
            Type        Gust
        </Sensor>
        <Sensor 1500000001622C1D.m>
            Name        Slack
            Type        Counter
            SubType     MinRate
            Units       MPH
            MultiplyBy  2.453
        </Sensor>
        <Sensor C2000000012E0B20>
            Name        Wind Direction
            Type        Direction
        </Sensor>
    </Collector>
    <Collector ExtraStuff>
        Type Derived
        <Sensor Turbulence>
            Type  Math
            Value 1500000001622C1D.g@Blinken - 1500000001622C1D.m@Blinken
            Units MPH
        </Sensor>
        <Sensor MeanSpeed>
            Type  Math
            Value (1500000001622C1D.g@Blinken + 1500000001622C1D.n@Blinken)/2
            Units MPH
        </Sensor>
        <Sensor WindChill>
            Type  WindChill
            Temperature 1@Winken
            Speed       1500000001622C1D.s@Blinken
            Units C
        </Sensor>
        <Sensor SantaAna>
            Type  Math
            Value (C2000000012E0B20@Blinken > 355 || \
                    C2000000012E0B20@Blinken < 75) && \
                6A00000000DB141D@Blinken > 20 \
                    ? 6A00000000DB141D@Blinken \
                    : 0
            Units MPH
        </Sensor>
    </Collector>

All of the standard Perl math operators are allowed (+ - * / % ! & | and so on), boolean operators (&& and ||) as well as the ternary operator ?: and the functions abs(x), sign(x), min(a,b), max(a,b), sin(x), cos(x), atan(x), and log(x) (natural logarithm). It does not support full Perl syntax, of course, but if I have missed anything that you need, please let me know!

WindChill
The WindChill sensor computes the wind chill using the formula found in http://en.wikipedia.org/wiki/Dew_point (NOTE: the WindChill is only computed if the temperature is between -50C/-58F and 5C/41F, and the windspeed is at least 3KPH/1.86MPH). The required two special WindChill attributes are:
Temperature
The name of the temperature sensor to use for the computation (specified as N@K, where N is the sensor name and K is the collector name).

Speed
The name of the speed sensor to use for the computation (specified as N@K, where N is the sensor name and K is the collector name).

See the Math sensor for an example of WindChill.

HeatIndex
The HeatIndex sensor computes the wind chill using the formula found in http://en.wikipedia.org/wiki/Heat_index (NOTE: the HeatIndex is only computed if the temperature is at least 80F/26.67C and the relative humidity is at least 40%). The required two special HeatIndex attributes are:
Temperature
The name of the temperature sensor to use for the computation (specified as N@K, where N is the sensor name and K is the collector name).

Humidity
The name of the humidity sensor to use for the computation (specified as N@K, where N is the sensor name and K is the collector name).

Humidex
The Humidex sensor computes the wind chill using the formula found in http://everything2.com/ (see http://en.wikipedia.org/wiki/Humidex for an uglier equation). (NOTE: the Humidex is only computed if the temperture is at least 20C/68F and the relative humidity is at least 40%). The required two special Humidex attributes are:
Temperature
The name of the temperature sensor to use for the computation (specified as N@K, where N is the sensor name and K is the collector name).

Humidity
The name of the humidity sensor to use for the computation (specified as N@K, where N is the sensor name and K is the collector name).

DewPoint
The DewPoint sensor computes the wind chill using the formula found in http://en.wikipedia.org/wiki/Dew_point (NOTE: the DewPoint is only computed if the temperature between 0C/32F and 60C/140F). The required two special DewPoint attributes are:
Temperature
The name of the temperature sensor to use for the computation (specified as N@K, where N is the sensor name and K is the collector name).

Humidity
The name of the humidity sensor to use for the computation (specified as N@K, where N is the sensor name and K is the collector name).

Actuators and Actuator Attributes

An Actuator block is available for some Collectors (for example, the built-in relays on the Poseidon and Damocles series from HWg, and ``relays'' for Modbus devices). Presently, actuators are used exclusively with Alarms (so when an alarm is triggered, an actuator can be opened or closed). This functionality may be expanded in the future - suggestions are welcome).

Actuators are also logged (so you can graph when they are actuated or not). With the exception of an Alarm block, all of the attributes that are valid for a Sensor are also valid for an Actuator. This includes the Name, and Type, but also the LogFile, Hide, ReadOnly, OnValue, OffValue, SNMPOnValue, SNMPOffValue, Instance, GraphColor, and LineType attributes (etc).

Actuators change their environment. An Actuator block (which must have a unique name that is distinct from any Sensor names)) specifies all the attributes of a specific actuator. The actuator naming system depends on the collector:

Poseidon and Damocles
For the Poseison and the Damocles series from HWg, the actuator name must be the letter A followed by a one or two digit actuator number (A1, A2, etc.).

SNMP devices
The actuator name may be any string you like, but an OID must also be specified.

HA7Net
The actuator name must be a 16-digit hexadecimal 1-wire sensor serial number (with an optionally appended a .N, where N is a number or letter, to maintain the uniqueness of the name). Currently, the only actuator supported on the HA7Net is the LED in the DS2760-based TAI3560 thermocouple adapter http://www.aagelectronica.com/pdf%20docs/Thermocouple(TAI8560).pdf, but I will add support for any devices that you are willing to help me with...

Regardless of the collector or actuator type, the actuator-specific attributes are:

Name
A descriptive name for the actuator. You can use any description you like. Some data collectors (e.g., the Poseidon and Damocles series from HWg) have the ability to configure the sensor name on the data collector. For these collectors, the default value will be obtained from the collector. For all other collectors, the default value is Actuator N@K, where N is the actuator name and K is the collector name.

Type
The kind of actuator this is. The valid types are:
OnOff
This is the default for all actuators in the Poseidon and Damocles series from HWg, SNMP, and HA7Net actuators. When Type OnOff is specified, one of ``Normally Open'' and ``Normally Closed'' must also be specified.

Normally
When the Type of actuator is OnOff, the Normally attribute specifies what the normal state of the switch is to be (this is the state it is initialized to when thermd starts up). You can either specify Normally Open or Normally Closed. See also the Open, LockOpen, Close, and LockClose attributes of an Alarm.

SNMPOnValue
For SNMP actuators of type OnOff switch, this attribute specifies the numeric value that the actuator must be set to in order to turn on (close) the switch. The default value is 1.

SNMPOffValue
For SNMP actuators of type OnOff switch, this attribute specifies the numeric value that the actuator must be set to in order to turn off (open) the switch. The default value is 2.

View Block

A View block defines a way of looking at your data. When you have a lot of sensors, you can have multiple Views to allow you to look at your data in a variety of ways (for example, a view of upstairs data and a view of downstairs data, another for inside, outside, etc.) Each View much be named, and contains one or more Show or Show+ declarations. You may use any name for the view except All, which is reserved and automatically defined to contain every sensor (see the Sensor attribute Hide for specific exceptions to this rule).

There are three kinds of View: Graph (the default), which displays a time-based graph of data; Image, which writes only the current temperatures on top of a picture or drawing that you supply; and Wunderground, which sends weather data to Weather Underground (http://www.wunderground.com/) for personal weather station information (you can also have a collector of type Wunderground - see above). The Graph and Image Views are listed in the output of the CGI script, and are also accessible from the command line via the -view option with -graph, -annotate, and -report. The Wunderground Views are silently sent to Weather Underground every LogInterval.

A sample graphical View block could look as follows. This would cause the View named ``Inside'' to be created, which would contain three sensors to show. It uses simple Show statements and more complicated Show+ blocks to define how sensors are graphed.

    <View Inside>
        RSSName Inside the House
        Show    1@Upstairs              # Sensor "1" on collector "Upstairs"
        <Show+  3@Upstairs>             # Sensor "3" on collector "Upstairs"
            GraphColor  black
            LineType    dotted
        </Show>
        Show    1@Downstairs
    </View>

NOTE: The sensor and collector names referenced in Show and Show+ are Case SeNSiTive, and must exactly match the declared names.

Another View block could look as follows. This would create an annotated image, where the values of the same sensors were overlaid on the image of the house (along with the date and time). Image views can only use the more complicated Show+ blocks to define how sensors are displayed.

    <View Overview>
        RSSName Picture View
        Type    Image
        Image   /var/www/images/house.png
        <Date>
            X   400
            Y   402
        </Date>
        <Time>
            X   400
            Y   425
        </Time>
        <Show+  1@Upstairs>
            X   100
            Y   125
        </Show+>
        <Show+  3@Upstairs>
            X   327
            Y   125
        </Show+>
        <Show+  1@Downstairs>
            X   95
            Y   262
        </Show+>
    </View>

Note that if graphical View contains more than one class of sensor (for example, temperature and humidity), then the y-axis will be adjusted to contain the range of samples. This adjustment does not, of course, apply to annotated images (since there is no axis).

Another View block could look as follows. This would Send data to Weather Underground, where most of the sensor keys are automatically determines, but one of them is specified as sending indoor temperature.

    <View Weather>
        Type Wunderground
        StationID       KPAPITTS33
        Password        smashpunk3
        Show 1500000001622C1D.s@HA7Net  # Wind speed
        Show 1500000001622C1D.g@HA7Net  # Wind gust
        Show C2000000012E0B20@HA7Net    # Wind direction        
        <Show+  3@Upstairs>
            Key indoortempf             # Indoor temperature
        </Show>
        Show B80000004FC30A26@HA7Net    # Outdoor temperature
    </View>

Common View Attributes

The following attributes can be used in any View:

Type
The type of the View, which may either be Graph (a graph of historical values) or Image (an image which is annotated with the current values). The default value is Graph.

Show (only valid when Type=Graph)
Each show item contains the sensor@collector name of a sensor. There is no default Show value. Sensor names are a combination of the Sensor name and the Collector name, separated by an at sign ('@'), e.g, ``3@upstairs''. NOTE: It is also legal (but now deprecated) to specify sensors as ``Upstairs/3''. This alternate format will soon become unavailable...

You may use a sensor in more than one view, and sensors are not required to be present in any view (remember that the view named all automatically contains all the sensors that are not explicitly hidden with the Hide attribute).

Show+
Each Show+ block contains the collector/sensor name of a sensor (Show+ is a bit of a hack - it will be eliminated in favor a more consistent use of Show as soon as a bug in Config::General is fixed). Sensor names are the same as in a Show item, however you may override the following attributes of any sensor in a Show+ block:

View attributes for Type=Graph and Type=Image

RSSName
If a View is given an RSSName, then that view is also shown in the RSS feed (if it is enabled).

RSSOrder
If Views are given an RSSOrder, then they are shown in that order in the RSS feed (if it is enabled). RSSOrder is numeric in ascending order. The default value for RSSOrder is 999 (i.e., ``last''), but you can use larger values if you want things listed after the default ``last''. Views with the same view order are listed alphabetically.

ButtonOrder
If Views are given an ButtonOrder, then they are shown in that order in the list of radio buttons in the main CGI window. ButtonOrder is numeric in ascending order. The default value for ButtonOrder is 999 (i.e., ``last''), but you can use larger values if you want things listed after the default ``last''. Views with the same view order are listed alphabetically.

View attributes for Type=Graph

GraphType
Specifies the type of graph that is generated for the View. This option currently only works for graphs which contain only wind (speed, gust, and direction) data. GraphType Natural is the default, and plots wind speed and gusts as lines with the wind direction as lettered annotation. GraphType Radar plots the wind speed and gusts in a radial plot using wind direction for the value of theta (the number of times a direction has been seen is also used as the direction summary plot). GraphType Lines forces wind direction to be plotted as a line (IMHO this is ugly, as angles wrap around to zero from 359 degrees, and generally dwarf wind speeds).

MinMax
This specifies the minimum value that the maximum of the graph can be - that is, the top of the graph will never be lower than this value. Yes, it sounds odd - consider this. You have a lightning sensor, which usually only shows 1 or 2 clicks every minute, but when there is a storm, you get hundreds or more. Specifying a MinMax value of 100 means that the top of the graph is at least always 100 (but it may be more if the data has values larger than this). The default value for MinMax is automatically determined by the data beng graphed.

ClipHi
This specifies the maximum value a value may have when graphing. Any values higher than this are clipped. Note: If you set MinMax and ClipHi to be the same value, then you are setting the top of the graph to be that value (because any larger values will be clipped). There is no default value for ClipHi, and ``no clipping'' is the default graphing behavior.

MaxMin
This specifies the maximum value that the minimum of the graph can be - that is, the bottom of the graph will never be higher than this value (but it may be lower if the data has values lower than this). The default value for MaxMin is automatically determined by the data being graphed.

ClipLo
This specifies the minimum value a value may have when graphing. Any values lower than this are clipped. Note: If you set MaxMin and ClipLo to be the same value, then you are setting the bottom of the graph to be that value (because any smaller values will be clipped). There is no default value for ClipLo, and ``no clipping'' is the default graphing behavior.

View attributes for Type=Image

Image
The filename where the ``master'' image may be found. This image will have the values of the specified sensors overwritten upon it. A relative filename (that is, one which does not start with a '/') will be relative to the RSS directory. If the RSS block is not defined, the filename must be specified as an absolute path (starting with a '/').

Font
The name of the font to be used to annotate the image. The fonts that are available will vary from system to system. The default value for Font is ``Helvetica''.

FontSize
The size of the font to be used to annotate the image. The default value for FontSize is 14.

TextColor
The color of the text used to annotate the image. The color may be one of a large set described on http://www.imagemagick.org/script/color.php, or may be a 6-digit hexadecimal RGB color starting with a #-sign. Note that you need to escape the #-sign (since it is a comment character) as:
        TextColor       \#a0a0FF

The default value for TextColor is ``black''.

TextAngle
The rotation angle to apply to the text used to annotate the image. The angle for left-to-right text is 0, top-to-bottom text is 90, and bottom to top text is -90 (or 270). The default value for TextRotation is 0. NOTE: ImageMagic does weird things with the X and Y positions any time text is rotated. If you want rotated text, be prepared to tweak these values.

TextAlign
The alignment which is applied to the text when annotating the image, the choices are ``left'', ``right'' and ``center''. Note that TextClign changes how the values of X and Y are intepreted (that is, the coordinates are where the left, right or center of the text is placed).

Precision
The number of digits of floating point precision to annotate. A value of ``0'' will result in only the integer portion being displayed. The default value for Precision is 1.

Date
If there is a Date block (see the example above), the date will be annotated on the image at the specified X and Y coordinates. The Date block may also contain values that override Font, FontSize and Precision. There is no default value for the Date block, and the default behavior is to not overlay the date on the image.

Time
If there is a Time block (see the example above), the time will be annotated on the image at the specified X and Y coordinates. The Time block may also contain values that override Font, FontSize and Precision. There is no default value for the Time block, and the default behavior is to not overlay the time on the image.

X (only in Show+, Date, or Time blocks)
The X coordinate at which the the annotated value is placed. The X must be specified for Show+, Date, and Time blocks - there is no default value.

Y (only in Show+, Date, or Time blocks)
The Y coordinate at which the the annotated value is placed. The Y must be specified for Show+, Date, and Time blocks - there is no default value.

View attributes for Type=Wunderground

Key
The key used when marking data - generally, this is only needed to distinguish an indoor temperature (or humidity) from an outdoor temperature (or humidity). The legal Key values are humidity, tempf, dewptf, winddir, windspeedmph, windgustmph, dailyrainin, baromin, soiltempf, soilmoisture, indoortempf, and indoorhumidity. See http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol for details (if you have more than one type of the same sensor, thermd will automatically add the disambiguating numbers that wunderground requires). The default value is determined automatically based on the sensor type, with thermd assuming the sensors are located outdoors.

SNMP details

SNMP is pretty complicated, and thermd only supports the small fraction of it that it needs to get its job done (namely measuring and logging values). Thermd only supports static OIDs - not OIDs which are based on the contents of other OIDs, or ``mapping'' as it is sometimes called.

OIDs are expressed one of three ways in a sensor block (for the Poseidon and Damocles series from HWg, the OIDs are automatically determined from the sensor name, and do not need to be specified).

Absolute OID
These are OID values which start with a '.', for example, .1.3.6.1.4.1.33.100.2.4.1.3.1.1

Relative OID
These are OID values which start with a number, and which are relative to whatever value has been specified for the BaseOID. For example, if the BaseOID is .1.3.6.1.4.1.33.100.2 and an OID is specified as a relative (that is, not starting with a '.') value of 4.1.3.1.1, the resulting OID is the concatenation of the two, or .1.3.6.1.4.1.33.100.2.4.1.3.1.1

Instance-based OID
These are OIDs based on a template defined in an Instance block. An Instance is a named block with an OID that contains non-numeric variable names. For example:
    <Instance Outlet>
        OID 7.1.4.N.M
        Type Counter
    </Instance>

defines an instance of a SNMP Counter (named ``Outlet''), with two parameters name ``N'' and ``M''. An OID in a sensor may then be specified as

    OID Instance=Outlet, N=3, M=1

This will be expanded into 7.1.4.3.1 (where 3 replaces the ``N'' and 1 replaces the ``M''. Further, since 7.1.4.3.1 is a relative OID, this will be concatenated with the BaseOID, resulting in .1.3.6.1.4.1.33.100.2.7.1.4.3.1. The sensor Type is also inherited from the Instance definition (although if it is specified in the specific sensor, that value will override the Type defined in the Instance). Instance definitions and use must be specified inside a collector block, and apply only to that block.

Sample configuration file

This is a simple configuration file, which resembles (but is not exactly the same as) that used on http://www.klein.com/thermd

    MailFrom    Thermometer Daemon <root@klein.com>
    <RSS /var/www/KLEIN/thermd>
        URL             http://www.klein.com/thermd/
        Webmaster       dan@klein.com
    </RSS>
    TimeZone    EST
    Location    "Klone's House"
    GPSCoordinates      "N40.441242456 W79.927382469 (WGS84)"
    MapURL              "http://maps.google.com/maps?q=5606+Northumberland,+Pittsburgh+PA&spn=0.032227,0.064703&hl=en"
    <Collector CheesePuff>
        Type    QK145
        Device  /dev/cuaa0
        Scale   F
        <Sensor 1>
            Name                "Computer exhaust"
            GraphColor  red
            <Alarm DangerWillRobinson>
                Above   95
                Subject "Maxwell over temp!"
                Message "%.0s%.1f%s"
                Notify  dvks-pager@lonewolf.com
            </Alarm>
        </Sensor>
        <Sensor 2>
            Name        "Basement"
            GraphColor  green
            LineType    dashed
            AdjustBy    +4
        </Sensor>
        <Sensor 3>
            Name        "Outside 1st floor"
            GraphColor  blue
            AdjustBy    +6
            <Alarm Freezing>
                Below   33
                ResetAt 40
                Dates   1 Apr - 1 Dec
                Times   08:00 - 23:59
                Notify  dan@klein.com
                Notify  dvks-pager@lonewolf.com
            </Alarm>
            <Alarm Roasting>
                Above   95
                Times   08:00 - 23:59
                Notify  dvks-pager@lonewolf.com
            </Alarm>
        </Sensor>
        <Sensor 4>
            Name        "Inside 3rd floor"
            GraphColor  purple
            AdjustBy    +3
        </Sensor>
    </Collector>
    <Collector BaconBits>
        Type    TEMP08
        Device  /dev/cuaa1
        <Sensor B80000004FC30A26>
            Name        Garage
            Type        Temperature
        </Sensor>
        <Sensor B80000004FC30A26.1>
            Name        Garage Humidity
            Type        Humidity
        </Sensor>
        <Sensor 1500000001622C1D.s>
            Name        Wind Speed
            Type        Speed
            <Alarm Hurricane>
                Above   75
                Notify  dan@klein.com
                Message "%.0s Hurricane Force Winds - %.1fMPH!"
            </Alarm>
        </Sensor>
        <Sensor 1500000001622C1D.g>
            Name        Wind Gusts
            Type        Gust
        </Sensor>
        <Sensor C2000000012E0B20>
            Name        Wind Direction
            Type        Direction
        </Sensor>
        <Sensor 4300000005B9FA1D>
            Name        Rainfall
            Type        Rain
        </Sensor>
    </Collector>
    <Collector MRV>
        Type SNMP
        IPAddress 10.10.1.243
        Community ShrimpSalad
        BaseOID .1.3.6.1.4.1.33.100.2  # mrvBpd.mrvLx.irCharMib
        <Instance Temperature>
            OID 4.1.3.N.1       # irTempValue
            Type Gauge          # Type will be inherited
        </Instance>
        <Instance Humidity>
            OID 5.1.3.N.1       # irHumidityValue
            Type Gauge          # Type will be inherited
        </Instance>
        # The IR5150 power outlet controller
        <Instance Power>
            OID 6.1.2.N         # PowerCurrentLoad
            Type Gauge
        </Instance>
        <Instance Outlet>
            OID 7.1.4.N.M       # irPowerOutletStatus
            Type OnOff
        </Instance>
        # T1 uses a relative OID, T2, H2 and the outlets use instances instead
        <Sensor T1>
            OID  4.1.3.1.1      # Or .1.3.6.1.4.1.33.100.2.4.1.3.1.1 (port 1)
        </Sensor>
        <Sensor T2>
            Name        Computer Temp
            OID Instance=Temperature, N=2       # port 2
        </Sensor>
        <Sensor H2>
            Name        Computer Hum
            OID Instance=Humidity, N=2          # port 2
        </Sensor>
        <Sensor O1>
            Name        Computer Power
            OID Instance=Outlet, N=3, M=1       # port 3, outlet 1
        </Sensor>
        <Sensor O2>
            Name        Router Power
            OID Instance=Outlet, N=3, M=2       # port 3, outlet 2
            Type        Gauge                   # Overrides Type from Instance
        </Sensor>
        <Sensor O3>
            Name        Switch Power
            OID Instance=Outlet, N=3, M=3       # port 3, outlet 3
        </Sensor>
    </Collector>
    Blurb = <<EndOfBlurb
    I bought an inexpensive <a target="_blank"
    href="http://www.qkits.com/serv/qkits/diy/pages/QK145.asp">serial
    interface temperature sensor kit</a> (about US$30) from
    <a target="_blank" href="http://www.qkits.com">QKits</a>
    and after I built the kit, I also purchased an extra 3 Dallas
    Semiconductor sensors (another US$18).  It is a very easy kit
    to build (it doesn't even need a power supply, it derives power
    from the RS-232 line it talks on), and the
    <a target="_blank" href="http://www.qkits.com">QKits</a>
    folks are pleasant people to deal with.  Then I wrote a nice
    Perl-based thermometer logging daemon, log dumper, and CGI script
    (one program does all three functions!) available with both
    <a target="_blank" href="http://www.klein.com/thermd/thermd">source code</a>
    and <a target="_blank"
    href="http://www.klein.com/thermd/t2.cgi?docs=1">documentation.</a>
    This latest version of the Thermometer Daemon supports multiple sensors.
    <p />
    EndOfBlurb
    <View Inside>
        Show    1@CheesePuff
        Show    2@CheesePuff
        Show    4@CheesePuff
        <Show+  T2@MRV>
            LineType    Dashed
            Color       Green
        </Show+>
    </View>
    <View Outside>
        Show    3@CheesePuff
        Show    B80000004FC30A26@BaconBits
        Show    B80000004FC30A26.1@BaconBits
    </View>
    <View Pix>
        Type            Image
        Image           /home/dvk/house.jpg
        Font            Helvetica
        FontSize        14
        Precision       1
        <Date>
           X            610
           Y            41
        </Date>
        <Time>
           X            620
           Y            58
        </Time>
        <Show+  1@CheesePuff>
            X           15
            Y           125
        </Show+>
        <Show+  B80000004FC30A26@BaconBits>
            X           50
            Y           17
            Font        CourierBold
            FontSize    18
            TextColor   red
            Precision   3
            TextAlign   Center
            TextAngle   90
        </Show+>
    </View>


DEVICE SPECIFIC NOTES

RacSense and WeatherGoose series

Each sensor has a Sensor Name and a Friendly Name (configurable by the Display tab on the device's web interface). Thermd uses the Sensor Name to read the sensors, so you may need to determine what the sensor's name is before configuring thermd.

It is also possible to configure temperature units that the web interfce uses. Since thermd reads the XML values from the device (which provides both Celsius and Fahrenheit), you may set the web interface to whatever you like, without worrying about how it will affect thermd.

Poseidon and Damocles series from HWg

SubType

You may specify a SubType of either HTTP (the default) or SNMP. The subtype determines how sensors are read. In SNMP mode, the sensors can be autoconfigured, but we no longer recommend this, as autoconfiguration must be done for every daemon, CGI script, RSS feed, etc.

Actuators

If you plan on using Actuators on the Poseidon or Damocles, you must:

  1. Create a read-write community in the ``SNMP Setup'' tab of the device's Flash Setup).

  2. Specify the same community name in the thermd configuration file (see the Community attribute for the collector).

If you specify the name of a read-only Community in your config file, thermd will be unable to change the values of the actuators. Check the syslog files for error messages on daemon startup.

SNMP Traps and fast-reading dry-contact sensors

In order to take advantantage of the SNMP trap information for rapidly changing dry-contact values, a few specific details need to be configured to match on the Poseidon or Damocles and in thermd:

  1. You must have NET-SNMP version 5.3.0 or greater available on the same machine that thermd is running. This version will contain the correct version of snmptrapd.

  2. You must enable trap reception in the thermd configuration file. See the SNMPTrapPort and AllowSNMPTraps directives.

  3. You must enable the generation of traps on the Poseidon or Damocles. This means that in the Sensor Setup tab, you need to select one of the Active alarm states for each sensor you wish to be SNMP-trap monitored.

  4. In the SNMP Setup tab of the Poseidon or Damocles, for one of the SNMP Trap Destinations, you must check the ``enable'' checkbox and select a trap destination that is the same IP address as the machine upon which thermd is running, with a Port that is specified in the SNMPTrapPort attribute in the thermd configuraion file.


FILES

/etc/thermd.conf
Default location of configuration file for thermometer program

/var/log/thermd/
Default directory for logging temperature information (if LogFormat is SQL, then this directory is not used).

/var/log/thermd/current
Current temperatures (values are updated every 10 seconds or so; if LogFormat is SQL, then this directory is not used).

/var/run/thermd.pid
Default location of process ID of the logging daemon, if daemon is running.


AUTHOR and CREDITS

This program was written by Daniel V. Klein, and is Copyright 2001-2009. All rights reserved - this program may be freely distributed so long as all copyright claims are preserved. Neither this program nor any derived programs may be sold without express written agreement by Daniel V. Klein, dan@klein.com.

Contributions of code have also been made by Aaron J Trevena (the original radial plot module) and Chris Kampmeier (the original image annotation code), along with contributions from numerous sources, as noted in the changelog.

Lars Karlander, Adam Thomas, Michael G. Petry, Nathan Glaser, Mario Berges, Tom Buskey, and Anders Brownworth have provided access to their networks for feature development, and Embedded Data Systems, Midon Design, AVTECH Software, SensaTronics, Trendline Data Systems, HW Group (of the Czech Republic), and Applied Power Technologies (APT) have graciously provided hardware.

Thank you to the following translators for internationalization: Roger Andersson for Swedish; Patrick Ben Koetter for German; Kristian Vilmann for Danish; Frank Kuiper for Dutch; Vladas Leonas for Russian; Mario Berges for Spanish.


VERSION

 $Revision: 2.85 $
 $Date: 2014/08/24 15:21:31 $


CHANGELOG

 $Log: thermd,v $
 Revision 2.85  2014/08/24 15:21:31  root
 Wunderground was getting mm listed as in for rainfall
 Revision 2.84  2012/10/28 15:59:34  root
 Fixed bug in Newport/IOmega (thanks stillman@kernelworks.org!) and in Gauges
 Revision 2.83  2010/02/16 20:00:51  root
 Drat - I forgot to take out the debug essages from the last checkin :-/
 Revision 2.82  2010/02/08 19:39:41  root
 Stupid error - I broke wind plotting before...
 Revision 2.81  2010/01/10 02:53:06  root
 Fixed readings for Omega/Newport iTHX-2 sensors (there were problems when
 there were more than one digit past the decimal point - a common occurance).
 Thank you to John Kielkopf for finding the bug.
 Revision 2.80  2009/12/30 22:37:57  root
 1) Added hPa and kPa (hecto- and kilo-Pascals) as Metric measures of
    barometric pressure, and made the default be hPa for everywhere except
    Canada (which is kPa) and England (which is mBar) - as opposed to my
    original wrong-sighted use of mmHg.
 2) Added XML as a web-based display type (it was previously added in v2.62
    as a command-line option, but now it is on the web).  The web display
    shows the current values for ALL sensors (regardless of View).
 3) Rewrote the interface for the Poseidon and Damocles series of collectors.
    Previously, they used SNMP to autoconfigure, read data, and deal with
    asynchronous events - now HTTP/XML is the default value with SNMP only used
    *optionally* used for asynchronous events (although you can still use SNMP
    for everything if you like)
 Revision 2.79  2009/11/13 01:09:23  root
 Discovered an OLD :-( bug in AdjustBy, wheree if you specified a value in
 degrees C and the sensor was in degrees F (or vise versa), it would asjust
 by the wrong value...
 Also, cleaned up some crap in the RoomAlert code
 Revision 2.78  2009/08/27 18:24:06  root
 1) Although owfs, owhttpd, owshell all read in C by default, the daemon
    can be started to read in F.  I now allow the Scale directive for them.
 2) Improved backgrounding a little.
 3) The 'current' table in MySql is now created with "ENGINE=innodb" to allow
    for table locking (the default is MyISAM, which did not allow locking).
 Revision 2.77  2009/06/16 22:53:35  root
 1) When a child process dies (that is, a poller process), thermd will now
    automatically restart it.  This should help with data dropouts.
 2) Fixed a bug in the Temp08 where rain sensors were being multiplied by .01
   (.01" is the multiplier for all rain sensors EXCEPT the Temp08)
 3) Largely rehacked the way readinglines and timing works in the daemon, so
    as to avoid the occasional data dropouts that I (and others) were seeing
    when the system was loaded.  It works better, but I still see dropouts :-(
 4) Updated the round-robin scheduler when a collector gets "stuck" (a rare,
    but annoying).
 5) Also fixed a bug in Math sensors, where you were penalized for not
    specifying Units.  I whine now, but don't crash.
 Revision 2.76  2009/04/30 14:31:52  root
 Added support for the MaxBotix line of sonar rangefinders
 Revision 2.75  2009/03/09 20:56:54  root
 New data collectors:
 --------------------
 1) Added a new CommandLine collector type.  This type executes shell commands
    to read sensor values, for those systems for which you have existing
    commands to extract values (for example, sysctl can be used to determine
    the temperature of the CPU).  Thanks to Todd Giles for the idea and
    preliminary version of the code!
 2) Added the Newport/Omega Engineering iServer family of collectors (thanks to
    help from Steve Lancaster of Xerox).  This includes the
 New sensors/actuators:
 ---------------------
 1) The TAI8560 thermocouple module now works on the HA7Net (previously it
    only worked with owfs/owhttpd).  Thanks to Thomas Olson for the detective
    work needed to figure out the 1wire commands and the link to NIST.
 2) The LED in the TAI8560 thermocouple module now works on the HA7Net as an
    actuator (thanks again to Thomas Olson).
 Bug fixes and enhancements:
 ---------------------------
 1) Found and fixed a bug in HTTP authorization (thanks to Todd Giles)
 2) Fixed a few bugs in OWFS Sunlight and Barometer sensors (thanks Iain Mason)
 3) Fixed parsing of Wunderground data, so that empty data does not report
    as having the value 0 (but instead reports as "undefined").
 4) It seems that the multiplier tables for the Veris H8030/H8031 are somewhat
    different than the H8035/H8036, so these tables have now been fixed.  Also
    fixed a bug where register 40001 was not being reported (both thanks to
    Dan Hassler).
 5) Alarm thresholds (Above, Below, and ResetAt) and AdjustBy values used to
    be assumed to be in the Scale of the collector (which was an *optional*
    field, and might be C or F depending on the collector).  To avoid possible
    confusion, you must now specify temperature units in all these attributes.
 6) Actuators are now more correctly logged and reported on.
 Revision 2.74  2008/11/30 01:49:16  root
 A small bug in relative-date parsing was found and fixed by Joe Peters
 Revision 2.73  2008/11/23 23:36:06  root
 A new sensor family and some bug fixes
 1) Added support for the Veris Industries H8030, H8031, H8035, and H8036
    energy meters.
 2) Fixed a bug in HUP restart (found thanks to Dan Hassler)
 3) When I originally released them, I orgot to add dewpoint to Wunderground
    remote weather stations (also found thanks to Dan Hassler)
 Revision 2.72  2008/09/22 14:09:50  root
 Fixed two minor bugs in Derived collectors
 1) Would not correctly recognize the F.IC sensor naming format for owfs
 2) Would not properly handle floating point numbers
 Revision 2.71  2008/09/16 12:40:41  root
 This release features a large number of new features but also introduces a
 couple backwards incompatabilities (I apologize, but I feel it is all for the
 best, especially as they all have simple work-arounds).
 1) Added a new collector type Derived, which allows for "computed" sensors
    (that is, sensors whose value is derived from mathematical equations that
    involve other sensors).  The most flexible type is Math (which allows an
    arbitrary expression), but there are also builtin convenience types for
    WindChill, DewPoint, HeatIndex, and Humidex.
 2) Extended the Wunderground Collector (and View) to allow DewPoint
 3) There are six new Counter types, supported with the SubType attribute
    a) AvgRate - the number of clicks/second, averaged over LogInterval
    b) MaxRate - the highest value of clicks/second over LogInterval
    c) MinRate - the lowest value of clicks/second over LogInterval
    d) Count - the number of clicks over LogInterval
    e) Total - the cumulative number of clicks.  Resets to 0 after the time
       specified in InactivityReset has passed with no further increase.
    f) Raw - the number on the dial
    All the old counting types are still supported as special instances of the
    above (Speed is an AvgRate, Gust is a MaxRate, Lightning is a Count, Rain
    is a Total, and Gauge is a Raw).  You can us the old types without change.
 4) In general, you may now specify multiple reads per sensor (this means that
    you can, for example, show the raw and adjusted temperatures, or the CuFt
    and BTU equivalent for your gas meter, etc)
 5) For the HA7Net collector:
    a) The HA7Net firmware must be upgraded to at least version 1.0.0.22.
       Keeping track of special cases was getting too difficult.
    b) For rate calculations, I now use the time field from HA7net (which means
       greater accuracy, since network delays no longer figure in calculations)
    c) You can now read either Channel A or Channel B (or both) on DS2423
       (previously, only Channel A was supported).
 6) For the RacSense collectors:
    a) Added KWh, Volts-Min and Volts-Max sensors for devices that support it.
    b) Cleaned up how sensors are detected (but based on revised information
       from Geist Manufacturing, it is no longer possible to detect impossible
       sensor/collector combinations).
 7) Added a Nice attribute to the RSS block for cycle-saving on low-power CPUs
 8) INCOMPATABILITIES (and work-arounds):
    a) All counters must have a Subtype.  If you want to preserve your existing
       behavior, use Subtype Count.
    b) I changed ResetAfter to InactivityReset (the documentation was confusing
       and I fixed both the attribute and the wording)
    c) The Lightning sensor type no longer allows ResetAfter.  If you *really*
       want that behavior, create a Counter with Subtype Total.
    d) The Combo attribute is gone.  There were very few sensors that needed it,
       it was confusing, and was there to allow a negligible optimization.
       Just delete it from your config files.
 Revision 2.70  2008/08/26 20:08:13  root
 Sigh - when I fixed a bug for thermocouples, I introduced on for other
 temperature sensors, which is now fixed.
 Revision 2.69  2008/08/25 22:46:23  root
 Martin Strandbygaard found a bug with DS18S20 and owhttpd
 Revision 2.68  2008/08/21 20:14:22  root
 Someone finally used the thermocouple code, and uncovered a few bugs, which
 are now fixed.
 Revision 2.67  2008/06/18 00:22:46  root
 Autoconfigure had some problems - if a Poseison collector was not found,
 then daemon startup could be compomised.  Not anymore!
 Revision 2.66  2008/05/10 16:16:20  root
 Fixed a bug with multiple pollers, where one of them exiting (an unusual
 event) might kill the other pollers.  Hopefully fixed another bug where
 the CGI script might report that the daemon was not running.
 Revision 2.65  2008/04/03 04:32:29  root
 Whoops!  Barometric pressure was being incorrectly reported to Wunderground
 Revision 2.64  2008/04/01 03:19:12  root
 1) Documented the PopUp configuration option (it has been available for
    a while now - oops)
 2) Added configuration options SMTPUsername and SMTPPassword for those
    users who need to specify SMTP SASL authentication to send email.
 Revision 2.63  2008/03/25 03:37:41  root
 1) Eliminated "Daemon not running" errors
 2) Added ModbusAddress qualifier for Enersure (and other future devices)
 3) Added experimental use of the MIT Timeplot graphing system (see the
    -format timeplot directive and the TimePlot button in the CGI interface)
 Revision 2.62  2008/03/13 19:49:13  root
 1) Added Excel and XML as an output format.  See the -format option.
 2) Added generic email usage (we no longer rely on Sendmail) as well as the
    configuration option SMTPHost (this and #3 suggested by Anthony Watts).
 3) Added -email flag to -checkconfig, to test email messages.
 4) Any cumulating sensor (rain, lighting, or counter sensor) with a non-zero
    ResetAfter will now retain its value when the daemon is restarted.  This
    used to only apply to rain gauges.  Suggested by Adam Crewe.
 4) Fixed a degenerate case where Wunderground would report a date and
    str2time would fail to parse it correctly.
 5) Fixed a small bug in RSS and "funny characters", found by Adam Crewe.
 6) Fixed a bug in SQL tables (where new sensors could not be created if the
    user has added additional columns to the sensors table), found by Ethan
    Goldman of CMU.
 7) Changed the behavior of -current.  When -current is used now, the -from
    and -to values are both set to "now".  The old behavior of dumping all
    current readings is assumed by the new -raw option.
 8) Although the "why" of it makes no sense, I fixed a bug which would cause
    the daemon to sometimes crash on startup when a previous daemon had just
    been stopped.
 Revision 2.61  2008/03/06 03:19:00  root
 1) Reduced the number of processes used for Wunderground (since all remote
    personal weather stations are read from the same wunderground site, we
    don't need a separate polling collector for each one).
 2) Cosmetic cleanups to wunderground that I missed in the previous version
 3) Fixed an "uninitialized hash" error in the internal GD::Graph::Radial
 4) Fixed a bug where a sensor's Name (if overwritten in a View) would not
    be reflected in the current readings
 Revision 2.60  2008/02/27 01:29:18  root
 The latest revision provides a boatload of new features as well as a bunch
 of bug fixes (and a couple of minor incompatabilities).  Enough of them that
 I felt it was better to divide them up:
 New Features:
  1) Added Actuators.  This is a BIG FEATURE - it means that you can now
     turn switches on or off in response to alarm conditions.  You can also
     run external programs.  Because of the potential for harm to whatever
     system you are controlling, there are special configuration issues that
     must be satisfied before you can use this feature.
  2) Added support for the HWg series of Poseidon data collector (these
     devices have actuators included in them)
  3) Added the ability to publish weather information to Weather Underground
     http://www.wunderground.com/ as a "personal weather station"
  4) Added support for Weather Underground as a data collector (so you can
     compare your weather data with other stations).
  5) Added support for owshell, in addition to the existing owfs and owhttpd.
  6) Added support for the TAI8570 pressure sensor from AAG to owfs, owhttpd,
     and owshell
  7) Added support for DS2760 (thermocouple-based temperature sensors) for
     owfs, owhhtp, and owshell
  8) Added ability to auto-fetch sensor names from certain collectors (EM1,
     RoomAlert series, SmartWatt and HWg series), which means that you can
     delete the Name attributes from the config file and simply configure
     your collector (eliminating "version skew")
  9) Added Spanish internationalization (thank you to Mario Berges).
 10) Added ability to specify Type in an SNMP Instance declaration (which
     allows Type to be inherited, simplifying SNMP collectors in configuration
     files).
 11) Added SNMPOnValue and SNMPOffValue to SNMP OnOff sensors - the default
     values are 1 and 2 respectively, but some MIBs may use different values.
 12) Added SensorOrder global configuration attribute to change how sensors
     are ordered in reports and graphs
 13) Since the USA (and Liberia and Burma) are the only countries that use
     English units, I made Metric be the default units for all other countries.
 14) Thermd now uses the PIDFile as a lockfile, so it will warn you if you are
     trying to start a daemon when one is already running.  I also allow you
     to specify /dev/null for a PID file, which also disables locking.
 15) Added "MultiplyBy" to Gauges (was previously only available for counters).
 Incompatabilities:
  1) All relative time values (like ResetAfter, LogInterval, PollInterval, etc)
     must now have associated units (for example, 30s, or 1m30s or 1d6h)
 Bug Fixes:
  1) In alarms - the open mode is "|-" not "|".  This was causing monitoring
     daemon crashes :-(
  2) If SQL logging is enabled, the DB connection is remade every time the
     daemon needs to log data (this becomes necessary if the SQL server is
     restarted without also restarting thermd)
  3) Fixed a small bug in SQL reporting/graphing if there is insufficient
     log data available.
  4) WattHours for the EnerSure and SmartNet are the "wattage values since the
     last reading we made".  We used to (incorrectly) average those values
     over LogInterval minutes - now we (correctly) accumulate them.
  5) Lowered the minimum value of LogInterval to 15s
  6) Some Linux versions of strftime do not recognize "%+", so I reverted to
     "%c" in the internatonalization code
  7) Fixed a bug where we would sometimes erroneously report that the logging
     daemon was not running.
  8) Maybe I have graph limits right this time?  I think I have fixed the
     algorithms properly.
  9) Sometimes, when errors were encountered during -daemon parsing, some
     superflous child processes would be left running (config file parsing
     has been largely overhauled).
 10) PollInterval was being ignored for SNMP collectors
 11) It was possible to start two simultaneous SQL-based daemons (text-based
     daemons were locked out by logfiles).  I changed the pidfile to also be
     a lock, preventing duplicate daemons of any form.
 12) Added a few missing (Slope, Intercept) or unclear (lots) components to
     documentation.
 13) Fixed Metric display of barometer readings (they used to be stuck on inHg)
 14) If a collector is marked as ReadOnly, we don't try to talk to it at all now
     Likewise, if a collector is ReadOnly, all of the sensors on it are also
     ReadOnly (but now you can have a ReadOnly sensor on a read/write collector)
 15) Lots of general code cleanup, getting rid of cruft, modularizing, etc.
 Revision 2.59  2007/12/29 18:27:37  root
 I rethought server I18N.  You may use locale-based month names in yourr
 config file now (for alarms).
 Revision 2.58  2007/12/29 16:40:18  root
 Cleaned up I18N a little (problems with mixed encodings in a single
 string.  Added Russian language encoding.
 It is a known bug that some weird characters may appear in graphs when
 using I18N - I may need to take this up with the author of GD::Graph
 Revision 2.57  2007/12/19 23:50:02  root
 1) Added Danish I18N thanks for Kristian Vilmann
 2) Added Dutch I18N thanks to Frank Kuiper
 3) Deprecated DisplayIn - thermd will now choose the appropriate value based
    on the locale (setting DisplayIn will force an initial scale on all
    viewers, regardless of locale)
 Revision 2.56  2007/11/29 22:02:30  root
 NOTE: You must restart the thermd logging daemon when you install this new
 version, otherwise the CGI script will always report that the daemon is not
 running.
 1) Added SmartNet (and SmartWatt, SmartPDU, and SmartSenseTH) XmlRpc sensors.
 2) If the "current" values are too old, the CGI script and other reports will
    advise you that the logging daemon may not be running.
 3) DefaultView was not working - fixed
 4) Added -i18n option to check completeness of internationalization strings
 Revision 2.55  2007/11/14 18:05:58  root
 Thanks to Anders Brownworth, I verified the correctness of the Proliphix
 additions, and also fixed a few minor bugs introduced when I did the
 internationalization.
 Revision 2.54  2007/11/10 18:34:20  root
 Cleaned up error mesages a bit, and after much consultation, removed the
 usage message from the internationalized code.
 Revision 2.53  2007/11/07 19:54:28  root
 1)  Internationalization (or I18N).  We now support Swedish (thank you to
     Roger Andersson of bjorktorp.se) and German (thank you to Patrick Ben
     Koetter of state of mind).
 2)  Added support for Proliphix IP enabled thermostats.  The devices themselves
     are read-write (that is, you can program your thermostat from the web), but
     thermd just reads the values from the thermostat.
 3)  Added UserName and Password for IP-based connections (in case your device
     requires it).  This was necessitated by the Proliphix, and is now supported
     for all IP devices.
 4)  Added Baudrate for serial-based devices.  In general, the default is correct
     but when you use a Digi IP-to-serial device in RealPort mode, it is
     sometime necessary to change the baudrate, so baudrate changes are now
     supported for all serial devices.
 5)  Added restart support for the Enersure.  In my setup, my computers are on
     a battery backup, but the Enersure is not.  When my power company drops
     power, the computers stay up, but the enersure resets - and the IP
     connectiion gets all messed up.  I now attempt to fix it.
 6)  Yet again, fixed the boundary conditions of graphs (sometimes graphs would
     print as solid blue blobs).
 7)  Fixed runaway rain sensors (by rejecting counts of > .1"/minute)
 8)  Added the ability to continue with the last Rain value after a restart (so
     it doesn't automatically reset to 0 when you restart the daemon).  I have
     not tested this on SQL, so feedback would be appreciated.  Thermd will make
     a note in syslog if it sees a recent value...
 9)  Cleaned up units code, so expressed values should be more consistent
 10) Cleaned up a few bugs in image annotation (color of text in CGI wrapper,
     units annotation, wind direction values, etc).
 11) Cleaned up SQL a little to guard against injection attacks from the web
 Revision 2.52  2007/09/23 16:46:00  root
 A few minor changes and tweaks:
 1) SNMP sensor names may now also have '-' characters in them
 2) Counters may now have a negative "MultiplyBy" (so you can graph two
    counters against each other up/down
 3) Annotated images are now displayed fullsize, not scaled to the same
    dimensions as the graphs
 4) Counters are now displayed as integers, when appropriate (which is
    usually, since counters are integral unless altered by MultiplyBy)
 Revision 2.51  2007/09/18 16:15:40  root
 1) With thanks to Chris Kampmeier for the concept (and the initial patches!),
    we have an exciting new feature!  It is now possible to annotate an image
    with the current readings from thermd - which means that you can have a
    an image (photo or drawing) of your site, and you can have thermd label
    it.  Look at http://blogs.kampmeier.com/?p=3 - the graph is generated by
    thermd, but the diagram under it has been annotated by thermd, too!  Look
    in the documentation for View for details.
 2) Further improved the timeout behavior from the previous version
 3) Added a ButtonOrder attribute to views, so you don't need to have your
    radio buttons in alphabetical order if you don't want.
 4) Changed the (default) maximum sort value for RSSOrder from 999999 to 999,
    so numbers greater than 1000 sort after the default "last" value
 5) An important format change in Views.  Sensors used to be labelled as
    Collector/Sensor, and now they are better specified as Sensor@Collector
    (this is anticipation of a future development of computational sensors).
    The old style will work for a while, and there is a conversion script
    on the main webpage
 6) Changed the scale for Power Factor from "%" to "PF", and for relative
    humidity from "%" to "% RH" to avoid ambiguous readings.
 7) Made Unicode the internal standard, to avoid switching between &deg; in
    HTML, \a in GD::Graph, and \N{U+00b0} in Image::Magick (the latter is now
    used throughout).
 Revision 2.50  2007/09/06 20:22:14  root
 Some BSD and some Linux systems have a highly intermittent bug in select()
 but Linux and BSD have different signal behavior, so this latest fix to
 my_select() just forgets about using signals and does its magic manually.
 Revision 2.49  2007/08/22 04:11:14  root
 What a difference a single character in a regex can make :-)  I messed
 up the RoomAlert humidity readings - and just noticed :-(
 Revision 2.48  2007/08/11 17:26:51  root
 Added a test for TAI humidity sensors for the HA7Net.  Version 1.0.0.16 of
 the HA7Net understands the new EDS humidity sensors, but not the old-style
 TAI version.  EDS was supposed to release a new version of the firmware, but
 have fallen behind, so since one of my users complained, I installed a
 temporary workaround.
 Revision 2.47  2007/07/03 03:27:32  root
 Added support for the RoomAlert 24E and RoomAlert 26W
 Revision 2.46  2007/06/07 15:16:11  root
 1) Added more control over how graphs are rendered, by adding the MinMin,
    MinMax, MaxMin, and MaxMax attributes to View's
 2) Added support for Postgres, in addition to MySQL.  It seems that they are
    very slightly different...
 3) Fixed small bug IXON/IXOFF for enersure that was causing some data to
    be missed
 4) It seems that Linux behaves slightly differently for signals than does
    my FreeBSD system.  This manifested itself in a timeout/my_select bug on
    Linux, which is now fixed.
 5) Eliminated reference to "temperature" in the RSS feed, since some folks
    use thermd for just power monitoring :-)
 Revision 2.45  2007/05/02 21:43:58  root
 The HA7Net code now looks at CRCs of returned data values, and reports when
 the CRC check fails.  Also fixed a small bug in PollInterval.
 Revision 2.44  2007/04/18 00:19:28  root
  1) The EnerSure is now ready for release.  You must now download the
     Modbus::Client module from the CPAN to use it.  A number of additions
     are still planned...
  2) Any serial device may now be addressed by IPAddress/Port in addition to
     Device.  I have a DigiOne SP ether-to-serial interface, and I now provide
     support for that too.
  3) Improved behavior of HA7Net Data aquisition with regards to locking.  We
     now grab the lock once per transaction, instead of once per device, which
     should speed up data acquisition and reduce network traffic.
  4) Better tweaking of graph ranges - the closer together the minimum and
     maximums of a graph, the closer the limits of the axes
  5) Changed format of the "current" logfile - instead of referencing sensors
     by the name gien in the config file, I now use the -> Collector and Sensor
     number.  No one should care, but it's better and faster this way, and lets
     you change a sensor name and still have views work without restarting the
     daemon.
  6) Changed logformat - it no longer pads values with leading zeros (this was
     a holdover from the days of fixed-length logfile records - why waste disk
     space when we don't need to?)
  7) Added the ReadOnly attribute to sensors.
  8) Added PopUp attribute for sensors.
  9) Added PollInterval for changing the scan rate of collectors.
 10) Changed LogFrequency to LogInterval, which is a more accurate term.  I
     still allow LogFrequency, though :-)
 11) Allow European format numbers (0,15) in addition to American format (0.15)
 Revision 2.43  2007/03/15 03:51:37  root
 This version is the preliminary release of support for the Enersure
 power monitor from Trendline.  I have tested it on my system (which is
 operational, but not connected to my circuit-breaker box).
 Revision 2.42  2007/03/14 15:04:47  root
 After a short amount of experience with the barometer, added a custom
 graph type if the only thing being plotted is barometric pressure (so
 you can actually see the changes :-)
 Revision 2.41  2007/03/13 20:12:51  root
 One (important) bug fix, two new sensors!
 1) I now support the Hobby Boards barometer and solar radiation sensors
 2) While implementing them, I discovered a bug in my temperature conversion
    routines for all DS2438 sensors :-(  This would affect humidity sensors
    and temperature readings when the temperature is below 0C
 Revision 2.40  2007/03/12 04:51:27  root
 This month was pretty productive, and a rather large change to thermd is
 the result.  A big THANK YOU goes to Lars Karlander, of N64.45 E20.52 in
 Northern part of Sweden for items 1, 2, and 4 below - he helped specify and
 debug the code as it was being written.  Thank you also to Daniel Johnson of
 Computer Resources who originally suggest the idea, and then was patient
 during the 6 months it took me to get started :-)
 NEW DATA COLLECTORS
 -------------------
 1)  Added support for OWFS (see http://owfs.sourceforge.net).  This means
     that thermd now supports the serial port host adapters (ibuttonlink,
     DS9097E, DS9097, and DS2480B) or USB host adapters (DS9490 or PuceBaboon),
     available from HobbyBoards and elsewhere.
 2)  Added support for OWHTTPD (see http://owfs.sourceforge.net/owhttpd.1.html)
 3)  Added support for SNMP-based devices, such as the MRV LX-4008 and IR5150
 4)  Added a new sensor type Counter.  This is just a raw counter device (for
     1-Wire and SNMP collectors), and reports how many "clicks" have gone by
     in the past LogMinute interval.
 5)  Added a new sensor type Gauge.  This is just a raw measure, and is only
     available on an SNMP collector.
 6)  Added Units attribute for Counters and Gauges, and MultiplyBy for Counters.
 7)  Refactored how the lightning gauges read.  I used to show them a count of
     strikes over a long interval (like rain) but now that I actually *have*
     a lightning sensor, I see it makes more sense simply to show a count of
     strikes per measurement period.  If you like it better the other way,
     you can fake it with Counter :-)
 8)  Cleaned up the counter code for lightning & rain - they are now just
     special cases of type Counter
 9)  Added support for the low-precision DS1822
 10) Cleaned up logging/error messages (so now they go to STDERR and/or syslog
     as appropriate)
 11) Fixed a bug with upper/lower case hexadecimal strings in the HA7Net
 12) Added a Port directive (for non-standard HTTP connections, and for SNMP)
 Revision 2.39  2007/01/16 14:29:35  root
 Added Blurb2 keyword - someone wanted to be able to add text after the
 chart instead of before it (you can actually use both if you want)
 Revision 2.38  2007/01/14 17:45:21  root
 We had more than 1" of rain in 24 hours, and I discovered a bug in my
 scaling algorithm for graphing rain :-/
 Revision 2.37  2007/01/02 12:47:23  root
 A small graphing improvement: if the graph ends "now", the graphs now
 include the current readings (which have not yet been logged into the
 every-LogInterval-minutes file)
 Revision 2.36  2006/12/27 23:45:16  root
 1) By popular request, log data may now be stored in SQL format.  I have only
    tested the MySQL interface, but I don't do any "funny" SQL calls, so it
    ought to work with any SQL interface.  An external program convert_to_sql.pl
    is available to help you translate your logfiles.
 2) Added options -list and -nowarn to -checkconfig, in support of conversion
    of databases to SQL
 3) Fixed a rare crash when the AAG wind sensor is used with the HA7Net.  I
    was correcting for AdjustBy values in the wrong place, and so in addition
    to crashing, I was recording incorrect wind directions IF you tried to
    adjust the wind direction.  Both bugs are fixed.
 Revision 2.35  2006/12/16 00:58:25  root
 A number of changes, enhancements, and bug fixes
 1) Added support for the ITWatchDogs WeatherGoose, MiniGoose, SuperGoose,
    PowerGoose and RacSense data collectors.  Thank you to Adam Thomas for
    his assistance.
 2) A small but noteworthy change to logfile parsing - if you have a sensor
    name that has lowercase letters in it (the sensor names are usually
    16 character 1Wire names with hexadecimal characters), the logfile will
    be stored as an uppercase name (unless you explicitly set a LogFile
    directive, which will be untouched).
 3) Fixed autoscale on a Rain-only graph - now sets limits of 0-1" in English
    mode, and uses 2-digit labels (so you can see small amounts of rain)
 4) Fixed conversion on rain values when displaying in Metric
 5) Fixed one last bug in Rain counting, so the rain values correctly reset
    after ResetAfter hours
 Revision 2.34  2006/12/01 22:50:34  root
 Theoretically, theory is harder than practice.  Practically speaking, it
 is the other way around.
 The rain sensor worked fine on the TEMP08, so theoretically it should have
 worked on the HA7Net.  Practically, that was not true.  I fixed that bug,
 so now it works on both.  Theoretically.
 Revision 2.33  2006/11/27 06:21:54  root
 Fixed bug in wind direction measurement (could have halted daemon)
 Made some diagnostics more friendly
 Revision 2.32  2006/11/26 14:56:42  root
 A few bug fixes to the previous release - you always find them after you
 release the code :-(  Also added autosubmit when you change any radio
 button or checkbox.
 Revision 2.31  2006/11/24 18:30:44  root
 1) Added support for EmbeddedDataSystems D2C switch sensors
 2) Removed the restriction that OnValue need to be larger than OffValue
 3) Added support for new HA7Net high-level humidity-reading to support
    their new sensor design.
 Revision 2.30  2006/10/22 03:54:34  root
 1) Added override of Name in Show+ block
 2) Fixed small bug in overtemp reporting
 3) Fixed up pod documentation a little
 Revision 2.29  2006/10/13 20:49:06  root
 1) AVTECH Software released new firmware for the Room Alert, which changed
    the URL that they used to fetch data.  Updated to allow both new and old
    style URLs
 2) Cleaned up POD documentation (I missed a few closing '>'s before)
 Revision 2.28  2006/09/12 22:49:34  root
 It turns out that in practice, wind direction measured from the OneWire
 Weather station is a lot more erratic than it should be in theory.  So
 the voting average that I implemented did not work well.  I have replaced
 this with a consensus average algorithm which seems to give better results.
 Revision 2.27  2006/09/10 18:02:35  root
 OWW! One big bug, one small one, one new feature
 1) Wind gusts were being accumulated, instead of maximized.  This resulted
    in ridiculously high gust values.  Whoops!
 2) Small bug in View's and Show+
 3) Added a Wind Direction graph to radar, to show the weighted average of
    wind direction (the more measurements in a given direction, the larger
    the measurement shown, so you can see teh predominant wind direction)
 Revision 2.26  2006/09/04 05:02:02  root
 Once a production release is made, it seems that there are always one
 or two bugs.  They are fixed, and not worth mentioning...
 Revision 2.25  2006/09/03 18:24:40  root
 This is a big release with a lot of changes.  I owe a BIG "thank you" to
 Michael G. Petry who reported the bugs addressed in items 2 and 10, and who
 helped me with the low-level OneWire protocol and the code necessary to get
 items 4, 5, and 6 working (all of those mean that thermd now supports the
 OneWireWeather station on the HA7Net! :-)
 1)  Added initial support for the Room Alert 7E, Room Alert 11E, and
     TemPageR systems
 2)  Fixed an off-by-one bug in my HA7Net data-collection code, where thermd
     read too much too often
 3)  Added support for the Lightning and Barometer sensors for TEMP08
 4)  Added support for DS2438-based Humidity sensors for HA7Net
 5)  Added support for DS2423-based windspeed, gust, lighting and rainfall
     sensors to the HA7Net
 6)  Added support for DS2450-based wind directon sensors to the HA7Net
 7)  Added a Show+ block to Views, and added GraphColor and LineType in these
     blocks to override the lines/colors specified in the Sensor blocks
 8)  Added a new GraphType qualifier to Views, to support the new Radar chart
     for wind history
 9)  Added a DefaultView configuration item, to change what the default radio
     button is selected
 10) Version 1.0.0.13 of the HA7Net firmware had a bug where if you read more
     than 10 DS1820 sensors, it would hang.  The bug has been fixed in 1.0.0.14
     but thermd will currently only read blocks of 10 sensors.
 11) Changed DisplayIn to accept English or Metric (C and F will still work).
     This will change all units of display, but all can be overridden.
 12) Added Temperature, Rainfall and WindSpeed to override DisplayIn.
 13) Changed -units switch to accept English or Metric (C and F will still
     work).  This will change all units of display, overrides the config file,
     but all individual units can be overridden.
 14) Added -temperature, -rainfall, and -windspeed override switches, too.
 15) Improved periodicity of readings for HA7Net and EM1.  New reading starts
     are based on the completion of past readings - now we read darn close to
     every 60 seconds (extremely important for wind seed measurements).
 16) Fixed averaging of wind direction.  Previously, an equal number of N & NW
     readings would correctly yield NNW, but since a compass is round, an
     equal number of NNW and NNE readings would incorrectly yield S!  Now it
     gives the correct value of N.
 Revision 2.24  2006/07/22 19:49:50  root
 The best laid plans... fixed over/under range sensor check.
 Revision 2.23  2006/07/21 21:09:59  root
 Added the RSSOrder attribute to View's
 Revision 2.22  2006/07/21 18:14:40  root
 1) Added support for the EM1
 2) I apologize, but I renamed the BaseURL attribute to IPAddress (and
    slightly changed the semantics).  This was necessary as I find that
    the Trendline power monitoring uses an IP address but not a URL, and
    I wanted to be consistent...
 3) Underdriven sensors (humidity and wind speeds less than 0) will now
    be ignored
 Revision 2.21  2006/07/16 14:37:32  root
 1) Fixed a bug in the rain measurement code - it now works a lot better :-)
 2) Started adding Trendpoint EnerSure and Sensatronics EM1
 3) Deleted some old unused code for decaying stale data
 Revision 2.20  2006/07/05 15:33:17  root
 1) Found a synchronization bug in initializing the TEMP08, fixed.
 2) Wind directions are now represented as a compass point (and not degrees)
    in current log and RSS feed
 Revision 2.19  2006/06/30 16:16:20  root
 1) Fixed a bug in RSS - previously, all the values in the "current readings"
    file were in Degrees F.  They are now in their correct units.
 2) Made a special wind-only graph format.  If a view has only wind speed
    and direction (and optionally gusts), this format is automatically used.
    I don't think it will work if other readings ar used, so it is not a
    selectable type.
 3) If you don't like my choice of named colors, you can now also use an
    RGB 6-digit hexadecimal value.
 4) Occasionally erroneous data will be seen on 1-Wire busses.  Thermd now
    ignores temperatures of 85C/185F, as well as humidities and windspeeds
    that are >= 100 %/MPH.  I may make this a configurable option...
 5) The code has been rock solid without any obvious memory leaks.  I changed
    the automatic restart from weekly to monthly.
 Revision 2.18  2006/06/13 13:22:17  root
 Embedded Data Systems released firmware version 1.0.0.13, which fixed the
 bug I had to make a workaround for in thermd version 2.12, so this release
 backs out that section of code to the more efficient use of the HA7Net
 code.  Now, if a sensor fails or is simply unplugged, it will "go missing"
 instead of invalidating all of the sensor readings.
 Revision 2.17  2006/05/30 17:44:29  root
 Added start of customized RSS - see the "RSSName" keyword in View's
 Revision 2.16  2006/05/24 15:56:07  root
 One small change, one big one
 1) Added support for the One Wire Weather rain gauge on the Temp08
 2) Completely rethought how I read data fromn sensors (for the THIRD time)
    When I just supported a single QK145, it was easy - just read streaming
    data.  Adding the HA7Net meant changing to a polled structure, and then
    when I saw I was getting data dropouts, I switched to a raw-mode polling
    system.  Dropouts kept occurring, and I discovered what I think is a bug
    in the select() call, *and* I was using a LOT of CPU time, so now I have
    a raw-mode polling system with an exception-raising mechanism if there
    is a blockage in sysread() or select(), and I only collect data every
    30 seconds (although it buffers up in the interval).  This means no more
    heavy CPU load, no more missed data, and no more missed log intervals.
 Revision 2.15  2006/05/02 18:19:48  root
 Someone complained that the new data collection wasn't working, and for
 their flawed logfile, they were right,  We now handle errors in logfiles
 a bit better, as well as fixed an error in default MailFrom.
 Revision 2.14  2006/05/01 20:17:13  root
 1) Added support for the TEMP08 data collector from Midon Design.  Also
    added suppot for the DS2438 temperature (and humidity) sensor, plus the
    DS2423 wind speed and the DS2450 wind direction sensor in the AAG One Wire
    Weather system!  Note that OWW will not be fully supported until I mount
    give a degree value between 0 and 359, instead of something more pretty).
    I have plans to add the rain gauge, too.
 2) Added the Type attribute to <Sensor>.  This is optional for temperature
    sensors.
 3) Completely rethought how data is collected - this was because of yet
 4) Added the Type attribute to <Sensor>.  This is optional for temperature
    sensors.
 5) Completely rethought how to log data and report dead sensors.  Since Perl
    after version 5.7.3 has safe signals, I now use alarm timeouts to do both
    functions, which means enhanced reliability and more accurate logging,
    even when the RSS feature slows down measurements.  This also entailed
    dealing with interrupted selects and restarting system calls.
 6) Reduced the frequency with which I poll the HA7Net.  Originallym this was
    even when the RSS feature slows down measurements.  This also entailed
    dealing with interrupted selects and restarting system calls.
    of continually.  This also helps reduce network traffic from the daemon.
 7) Improved restarting of the daemon when HUPped or on the weekly autorestart.
 8) At the request of a user of the old system, I reincorporated Hi/Lo graphs.
    They are no longer restricted to 1 year, but will show highs and lows for
    every 24-hour period that is graphed.
 9) Changed the way ticks are generated on the X axis.  Now completely general,
    instead of being special-cased for each range.
 10)Graphing now should behave correctly even if you change LogFrequency
 11)Return a special image when no data is available to be plotted in the date
    range specified.
 Revision 2.13  2006/04/18 17:04:22  root
 Added "Combo" keyword to support combination sensors from Embedded Data
 Systems (such as the HMP2001S)
 Revision 2.12  2006/04/18 16:24:52  root
 There is a problem with the HA7Net... It allows you to read multiple
 sensors at one go, but if any single requested sensor is missing, the
 entire request fails.  This means that if you disconnect a sensor, it
 appears that all sensors of that type have failed.  The solution is
 to read each sensor individually, which means slightly more network
 traffic and processing.  No big deal, but it is annoying...
 Revision 2.11  2006/04/14 22:17:32  root
 Correctly handles sensors which do not read temperature - so the relative
 humidity sensor will no longer have readings converted to Fahrenheit :-/
 Revision 2.10  2006/04/13 12:26:27  root
 1) Prettied up latest readings when there are > 5 sensors
 2) Fixed bug where there was no relevant data in the first file looked at
    caused a doubling of dates for the remaining files
 Revision 2.9  2006/04/07 13:45:24  root
 Added LineType attribute - my graphs were getting crowded, and having a
 discriminator was nice
 Revision 2.8  2006/04/07 03:33:45  root
 1) Improved I/O - you aren't supposed to use buffered I/O with select(2),
    and I was.  So now, we use only unbuffered I/O for reading from the
    sensors.  There are no longer any dropouts (I hope)
 2) Fixed a bug where failed sensors would not be detected if they had
    had _any_ previous readings
 3) Closed some unused file descriptors on read
 Revision 2.7  2006/03/28 03:25:29  root
 1) Fixed bugs alluded to in previous version
 2) Added Hide attribute to sensors
 3) Beefed up printing of current temps in graph to only show what is in
    the current View
 Revision 2.6  2006/03/27 04:53:07  root
 First major pass at integrating the HA7Net - but be forewarned, there
 are still some bugs that need to be fixed
 Revision 2.5  2006/03/22 17:36:21  root
 Found an interesting graphing bug when there is no data for a sensor
 (that was not the last sensor examined!) in the selected time period.
 Revision 2.4  2006/03/21 17:04:51  root
 1) Fixed fatal bug when a collector fails (it used to die when it wrote the
    logfiles (I had previously only checked at the update of "current")
 2) Fixed bug where collector log subdirectories were checked before the names
    of the actual logfiles were specified.
 3) Started adding HA7Net from Embedded Data Systems - they say they'll send
    me a unit to evaluate and integrate.
 Revision 2.3  2006/03/12 17:58:15  root
 We now allow fractional relative times (so, -1.5d is the same as -1d12h
 or if you want to be perverse -1.25d6h :-)
 Revision 2.2  2006/02/26 00:13:25  root
 Fixed bad bug in averaging software.  I forgot to zero out the sum and
 count after logging, so it wound up calculating avergage since reboot
 instead of average since last logging.
 Revision 2.1  2006/02/25 00:11:01  root
 There's always one... last... bug... after you make a release :-/
 Revision 2.0  2006/02/25 00:00:45  root
 Massive update and complete rewrite!  Notable changes are:
 0) Complete rewrite of code.  Much more readable and modular, and designed to
    be a new release (instead of a accumulation of features over time :-)
 1) New configuration file format (now resembles Apache config file), and
    all parameters are in config file (no more changing Perl code).  Just
    about everything is tunable.
 2) Supports multiple data collection devices, no limit on number of sensors.
 3) Supports QK145 and VK011 devices from QKits.  Other devices may follow...
 4) Dramatically increased graphing speed.
 5) Enhanced display ranges (arbitrary start/end points).
 6) Named views (so you can choose groups of sensors to display).
 7) Improved alarms - can specify multiple alarms per sensor, with multiple
    delivery options, can also specify when an alarm resets, when it can be
    delivered, etc.
 8) Improved argument processing (uses long options, instead of 1-letter).
 9) Improved documentation (I hope!)
 10) Lots of bug fixes, more robust behavior!
 Revision 1.77  2006/01/06 00:28:05  www
 Final version 1 release - now contains graphics, tracking, trend analysis,
 alarms, and lots more...
 *Revision* 1.1  2001/07/31 20:43:36  www
 Initial release - a pretty simple program