The short-ish version:
-temperature value:GAUGE:U:U +temperature value:GAUGE:-100:300
The long version:
I recently had a Triangle Tube Prestige Trimax Solo high efficiency modulating/condensing (Mod/Con) residential boiler installed in our home. (Yes, it totally needs more names, doesn't it?)
These high efficiency boilers eke out the last few percent of efficiency by condensing the flue gas, and extracting the energy that happens during that condensation. But for this to work, the return water supply needs to be at or below the dew point of natural gas, about 135 °F. To achieve this, things need to be set up and configured properly. But how would we know?
As it turns out, this boiler has a ModBus interface built in, designed for industrial control applications. But it's well documented in the Prestige Control Supplement document published by Triangle Tube. We can use this to query the boiler and retrieve information like setpoint, supply and return temp, boiler firing rate, domestic hot water storage temp, etc, as seen in the graph above.
The physical ModBus interface in the device is ModBus/RTU, on an RS-485 serial port. So we'll need an interface to that; this will do nicely (image link goes to Amazon):
# gcc -o tt-status -lmodbus tt-status.cand give it a shot:
root@raspberrypi:/home/pi# ./tt-status -s /dev/ttyUSB0 Status: DHW Mode Flame Present DHW Pump Supply temp: 168 °F Return temp: 145 °F DHW Storage temp: 102 °F Flue temp: 132 °F Outdoor temp: 35 °F Flame Ionization: 11 μA Firing rate: 25 % Boiler Setpoint: 170 °F CH1 Maximum Setpoint: 143 °F DHW Setpoint: 125 °FWoo!
At this point, things are working, and we can do whatever we like with the data. My first approach to quickly get data collection up and running was to use collectd, because it already had a ModBus plugin.
However, that plugin was limited, and didn't know how to read the registers I was interested in. So I wrote two patches, one which teaches the plugin about command 0x04 ("Read Input Registers"), and another which allows it to talk directly to /dev/ttyUSB0 rather than requiring a ModBus/TCP target. (That 2nd patch is a bit less tested; I'm currently running with the mbus daemon below, and ModBus/TCP in collectd.) Update: those patches are included as of collectd v5.5, with slightly different config syntax.
Having a ModBus/TCP target is nice, because it makes it easy to collect data from remote hosts; if you wish to do this, just install mbusd with this initscript and the data will be accessible from anywhere on your network. Note, however, that things aren't happy if you try to access /dev/ttyUSB0 directly at the same time as mbusd is running on top of it.
(If you're running raspbian on your pi, here are some debs I built with these patches (NOTE: SOME REPORTS OF BROKENNESS NOT YET SORTED OUT); and my outbound link is slow, just warning you).
At this point we're almost done; install the modified collectd, with the rrdtool and modbus plugins, and add this config which has all the right definitions and transformations to read data from the boiler. Edit it as needed, specifying either your ModBus/TCP host, or the serial device name and baud rate. The config file does two basic things, first it defines each address that we wish to read, for example:
<Data "supply-temp"> RegisterBase 768 RegisterCmd ReadInput RegisterType Int16 Type temperature Instance "supply" </Data>and tells collectd to gather that data. It then converts temperatures from 0.1C units to C units as needed, and converts all temperatures into Fahrenheit degrees. If you don't want Fahrenheit, just remove this rule at the bottom of the config:
# Boiler temps are in degrees C <Rule "c_to_f"> <Match "regex"> Plugin "^modbus$" Type "^temperature$" </Match> # F = (C * 9) / 5 + 32 <Target "scale"> Factor 9 </Target> <Target "scale"> Factor 0.2 </Target> <Target "scale"> Offset 32 </Target> </Rule>
Fire up collectd, and it should be happily storing data to an rrd file. You might want to configure a syslog or logfile plugin so you can keep an eye on what it's doing.
One thing I ran into is that if the boiler isn't firing, then the setpoint comes back as 0x8000, which is specified as an "invalid value" in the boiler docs. Having this value in the graphs makes the scale all wrong, of course, so we want to ignore it. I failed at writing a filter for the config file, so I just modified collectd's types.db like this to ignore invalid temperatures:
-temperature value:GAUGE:U:U +temperature value:GAUGE:-100:300
Finally, to get pretty graphs, you'll need some collectd client; I used Visage simply because it seemed easiest to get up and running quickly. Install instructions are on the page, but essentially it's a ruby gem, so you need to install dependencies like:
# apt-get install -y build-essential librrd-ruby ruby ruby-dev rubygemsor
# yum install -y ruby-RRDtool ruby rubygemsthen get the gem with
# gem install visage-appand start it with
# visage-app startand it should start running on http port 9292, i.e. http://raspberrypi:9292. Go to the builder link, select the host to use (the config file above calls it "rpi"), and add as many metrics as you like to the graph. Voila! (There are some oddities with timestamps on the graph which I also hacked around to fix, see this patch if that bugs you.)
There are a lot of things we could do with this; the first thing that comes to mind is collecting fine-grained data on firing rate, and using that as a gas meter. In my case, this is the only natural gas device in my house, so it would be interesting to see how accurate it is compared to the gas meter outside.
If you do anything interesting with all this, let me know!