Davis Vantage Pro weather station protocol,
problems therein, and thoughts on Weather data display software.

This page logs my efforts at writing software to run under Linux to copy weather data from a Vantage Pro station to my WWW site. I am rather fond of a computer language named Python (as in Monty Python), and had been contemplating buying a Davis Vantage Pro Weather Station in part to offer an excuse to write more Python code. The Vantage Pro turns out to be a fine toy in that regard as I can even turn the screen backlight on and off! Don't laugh - that actually provided some useful information and exposed a couple flaws in my understanding of the protocol.

Those problems are not entirely mine. While Davis provides a document describing their protocol (it took quite a while to get similar information from Garmin about their GPS receiver protocol), their document is not well polished and simply wrong in places.

This page exists to help Davis fix errors in their document and to help other programmers trying to teach their computers to talk to their Vantage Pro.

Errors in Vantage Pro Serial Support 2.0 - 06-30-2003 document

This protocol document explains that Davis is a PC-centric company even before you can read it. It's a .zip file, but that's not much of a surprise. Inside are three .doc files including the protocol document. Microsoft Word doesn't come in a Linux version! No .pdf files. Grumble. Fortunately I have PC with Word at work.

Both the document and the protocol leave a bit to be desired. The following describe various errors in decreasing importance.

VII 3: Date/Time data off by 100 years.

When I started implementing the DMPAFT call, my requests were met by a stony silence. No ACK, no NAK, no page count. After spending a couple hours looking at the CRC calculation and everything else, I decided to see what I could get from the DMP command. That readily returned data, and I noticed that the date stamp looked significantly smaller than what I calculated. Decoding it I found the base year is 2000, not 1900. Section IX should say:
vantageDateStamp = day + month*32 + (year-2000)*512;
...and later on:
-- Send the Date and Time stamp --
><0xC6><0x06><0xA2><0x03>
(Note the document has an extra close parenthesis. Or extra open parenthesis if you want consistancy with the time stamp calculator.) In the hex data, 0x06 replaces 0xCE, the value derived from a base year of 1900. The CRC is probably wrong too.

With year 2000 as the base, things run much better. I guess that 1900 was the base year once upon a time but it was changed to defer a rollover problem in 66 years.

Temperatures are often recorded as Fahrenheit + 90

WeatherLink is happy to display today's High and Low (so far), but it's not quite as willing to report yesterday's High and Low. For the first several hours each day, today's High and Low temperatures are nearly meaningless. Even the HILOWS command doesn't provide yesterday's High and Low. The graph data does have High and low data for the previous 24 days and is readily available once you figure out where and what it is.

Section XIII (EEPROM Graph data locations) starts with a block of pointers, e.g. NEXT_DAY_PTR. Unfortunately the document doesn't say that they are important or what they really point to. Each set of graph data is in a 24 cell circular buffer. This is sensible, as it means logging each hour's/day's/etc data is done without copying the previous 23 values. The pointer points to the oldest data, the data next to be overwritten. On each update, the new data is stored using the pointer to index into the circular buffers and then the pointer is incremented modulo 24. To get to yesterday's data, I had to get to the daily data in the slot before the one the pointer refers to.

Once I figured out the pointers, the temperature data was still wrong. However, I quickly realized the data was too high by 90 degrees. Apparently Davis chose that to make negative temperatures fit in an unsigned byte.

In retrospect, I noticed that many of the temperature alarm data is documented as being stored with the 90 degree offset. That's several pages away from Section XIII. Section XIII merely describes the location, number, and size of each data set. Nothing describes the content, though most of it can be inferred. Python code to fetch yesterday's High/Low data is:

class yesterday:
    "Convert binary string to high/low temp data for yesterday."
    def int16(self, s):
        return ord(s[1]) * 256 + ord(s[0])

    def __init__(self, arg):
        ptr = arg[0]
        s = arg[1]
        ptr = ptr - 1
        if ptr < 0: ptr = ptr + 24
    
        self.day_low_out_temp = ord(s[24*3 + ptr]) - 90
        print 'low', self.day_low_out_temp
        self.day_high_out_temp = ord(s[0 + ptr]) - 90
        print 'high', self.day_high_out_temp
        i = 24*4 + ptr*2
        self.day_low_out_temp_time = self.int16(s[i:i+2])
        i = 24*1 + ptr*2
        self.day_high_out_temp_time = self.int16(s[i:i+2])

CR, LF, \r, and \n follies and rants.

Section VII (Command details) says "All commands must be followed by a Carriage Return character...." Fine. It soon says that <CR> is 0x0D is "\r" is Carriage return. Fine, other than inconsistant capitalization. Then the very first command it describes, TEST, says that you send "TEST"<LF> to the console. This is bogus. Should I send carriage return, line feed, or either? And what about the quotes, nothing says they're there to mark verbatim strings. And the reply that comes back is "TEST"<LF><CR>. Everyone who has ever used a Model 33 Teletype knows that it's <CR><LF>, generally just called <CRLF>, because the carriage return can take more than one character time.

Good data doesn't need to be complimented.


Contact Ric Werme or return to his home page.

Last updated 2003 December 27.