Cautionary note: this is not official information from any manufacturer. It has been compiled from various sources, including careful “reverse engineering” of data from a small number of users’ weather stations. Use at your own risk.
An essential precursor to writing software for the Fine offset weather stations (WH1080, WH1081, W-8681, WH3080, WH3081 etc.) was to decode the data read from them. This was discussed in Michael Pendec’s weather station forum a few years ago. Michael had decoded the current and stored data, and Dave Wells contributed an almost complete map of the remaining data. That forum message has since been deleted (Michael had a spam problem, and wiping everything was his only option) so I’ve reproduced the info here, with a few additions of my own. Credit is also due to Steve from Sandaysoft for decoding the strange wind speed layout and to Chris Naunton for decoding the extra data stored by the ‘3080’ family of stations.
Note that there are gaps and overlaps in the memory layout, with different models using the same locations for different data. Writing software that works with all the different models (and different generations of firmware) can be tricky!
Data is read from the weather station, via USB, in 32-byte chunks. Each chunk has an address, in the range 0 to 65504, so it is convenient to describe the data as a memory map with an address range of 0 to 65535.
The first 256 bytes of the memory map is a “fixed” block, containing data such as maximum and minimum temperature records and alarm settings. The remaining data is an array of 4080 16-byte records (or 3264 20-byte records), which store the weather history.
Note that there are some pecularities about the data formats. Signed numbers use the most significant bit to indicate sign, so -1 would be represented in binary as 1000 0001 (signed byte) or 1000 0000 0000 0001 (signed short). Date-time values are stored as year (last two digits), month, day, hour and minute in binary coded decimal, two digits per byte.
Weather record layout
The weather station’s history is stored in 4080 16-byte records (3264 20-byte records in the 3080), each of which has the following layout.
Address | Bytes | Item | Format | Comments |
---|---|---|---|---|
0 | 1 | delay | unsigned byte | Minutes since last stored reading. |
1 | 1 | indoor humidity | unsigned byte | |
2 | 2 | indoor temperature | signed short | Multiply by 0.1 to get °C. |
4 | 1 | outdoor humidity | unsigned byte | |
5 | 2 | outdoor temperature | signed short | Multiply by 0.1 to get °C. |
7 | 2 | absolute pressure | unsigned short | Multiply by 0.1 to get hPa. |
9 | 1 | average wind speed, low bits | unsigned byte | Multiply by 0.1 to get m/s. |
10 | 1 | gust wind speed, low bits | unsigned byte | Multiply by 0.1 to get m/s. |
11 | 1 | wind speed, high bits | unsigned byte | Lower 4 bits are the average wind speed high bits, upper 4 bits are the gust wind speed high bits. |
12 | 1 | wind direction | unsigned byte | Multiply by 22.5 to get ° from north. |
13 | 2 | total rain | unsigned short | Multiply by 0.3 to get mm. |
15 | 1 | status | bits | bit 6: 1 = loss of contact with sensors bit 7: 1 = rain counter overflow |
16 | 3 | (3080 only) illuminance | unsigned 3-byte integer | Multiply by 0.1 to get lux. |
19 | 1 | (3080 only) UV | unsigned byte |
Fixed block layout
Other weather station data is stored in a 256 byte “fixed block”, which has the following layout.
Address | Bytes | Item | Format | Access | Comments |
---|---|---|---|---|---|
0 | 2 | EEPROM initialised flag | raw | R/W | Should be 0x55AA. |
2 | 2 | (2080 only) model | unsigned short | R/W | Expected to be 0x8010 (i.e. big-endian 1080) |
2 | 2 | (3080 only) rain factor (?) | unsigned short | R | Divide by 8192 |
4 | 1 | (2080 only) version | unsigned byte | R/W | Expected to be 0x20 |
4 | 2 | (3080 only) wind factor (?) | unsigned short | R | Divide by 8192 |
5 | 2 | (2080 only) ID | unsigned short | R/W | ? |
6 | 5 | (3080 only) maximum, UV, when | date-time | R/W | |
7 | 2 | (2080 only) rain factor (?) | unsigned short | R/W | Divide by 8192 |
9 | 2 | (2080 only) wind factor (?) | unsigned short | R/W | Divide by 8192 |
11 | 2 | (2080 only) inverted rain factor (?) | unsigned short | R/W | Rain factor ^ 0xffff |
11 | 5 | (3080 only) maximum, illuminance, when | date-time | R/W | |
13 | 2 | (2080 only) inverted wind factor (?) | unsigned short | R/W | Wind factor ^ 0xffff |
16 | 1 | read period | unsigned byte | R/W | Minutes between each stored reading |
17 | 1 | unit settings 1 | bits | R/W | bit 0: indoor temperature: 0 = °C, 1 = °F bit 1: outdoor temperature: 0 = °C, 1 = °F bit 2: rain: 0 = mm, 1 = inch bit 5: pressure: 1 = hPa bit 6: pressure: 1 = inHg bit 7: pressure: 1 = mmHg |
18 | 1 | unit settings 2 | bits | R/W | bit 0: wind speed: 1 = m/s bit 1: wind speed: 1 = km/h bit 2: wind speed: 1 = knot bit 3: wind speed: 1 = m/h bit 4: wind speed: 1 = bft |
19 | 1 | display options 1 | bits | R/W | bit 0: pressure: 0 = absolute, 1 = relative bit 1: wind speed: 0 = average, 1 = gust bit 2: time: 0 = 24 hour, 1 = 12 hour bit 3: date: 0 = day-month-year, 1 = month-day-year bit 4: time scale(?): 0 = 12 hour, 1 = 24 hour bit 5: date: 1 = show year year bit 6: date: 1 = show day name bit 7: date: 1 = alarm time |
20 | 1 | display options 2 | bits | R/W | bit 0: outdoor temperature: 1 = temperature bit 1: outdoor temperature: 1 = wind chill bit 2: outdoor temperature: 1 = dew point bit 3: rain: 1 = hour bit 4: rain: 1 = day bit 5: rain: 1 = week bit 6: rain: 1 = month bit 7: rain: 1 = total |
21 | 1 | alarm enable 1 | bits | R/W | bit 1: time bit 2: wind direction bit 4: indoor humidity low bit 5: indoor humidity high bit 6: outdoor humidity low bit 7: outdoor humidity high |
22 | 1 | alarm enable 2 | bits | R/W | bit 0: wind average bit 1: wind gust bit 2: rain hourly bit 3: rain daily bit 4: absolute pressure low bit 5: absolute pressure high bit 6: relative pressure low bit 7: relative pressure high |
23 | 1 | alarm enable 3 | bits | R/W | bit 0: indoor temperature low bit 1: indoor temperature high bit 2: outdoor temperature low bit 3: outdoor temperature high bit 4: wind chill low bit 5: wind chill high bit 6: dew point low bit 7: dew point high |
24 | 1 | time zone | signed byte | R/W | Hours offset from Central European Time, so in the UK this should be set to -1. In stations without a radio controlled clock this is always zero. |
25 | |||||
26 | 1 | data refreshed | raw | R/W | Computer writes 0xAA to indicate a change of settings. Weather station clears value to acknowledge. |
27 | 2 | data count | unsigned short | R/W | Number of stored readings. Starts at one, rises to 4080 (3264 in the 3080). |
29 | 1 | (3080 only) display options 3 | bits | R/W | bit 0: illuminance: 0 = lux, 1 = foot-candle bit 1: illuminance high alarm bit 2: UV high alarm bit 5: illuminance: 1 = W/m2 |
30 | 2 | current position | unsigned short | R/W | Address of the stored reading currently being created. Starts at 256, rises to 65520 in steps of 16 (or 65516 in steps of 20 in the 3080), then loops back to 256. The data at this address is updated every 48 seconds or so, until the read period is reached. Then the address is incremented and the next record becomes current. |
32 | 2 | relative pressure | unsigned short | R | Current relative (sea level) atmospheric pressure, multiply by 0.1 to get hPa. |
34 | 2 | absolute pressure | unsigned short | R | Current absolute atmospheric pressure, multiply by 0.1 to get hPa. |
36 | 2 | (3080 only) Lux to W/m2 coefficient | unsigned short | R/W | Divide by 10. |
38 | 2 | (2080 only?) wind correction factor | unsigned short | R/W | Percent in range 75..125 |
40 | 2 | (2080 only?) outdoor temperature offset | signed short | R/W | Multiply by 0.1 to get °C? |
42 | 2 | (2080 only?) indoor temperature offset | signed short | R/W | Multiply by 0.1 to get °C? |
43 | 5 | (1080 only?) current date & time | date-time | R | |
44 | 2 | (2080 only?) outdoor humidity offset | signed short | R/W | Unknown units |
46 | 2 | (2080 only?) indoor humidity offset | signed short | R/W | Unknown units |
48 | 1 | alarm, indoor humidity, high | unsigned byte | R/W | |
49 | 1 | alarm, indoor humidity, low | unsigned byte | R/W | |
50 | 2 | alarm, indoor temperature, high | signed short | R/W | Multiply by 0.1 to get °C. |
52 | 2 | alarm, indoor temperature, low | signed short | R/W | Multiply by 0.1 to get °C. |
54 | 1 | alarm, outdoor humidity, high | unsigned byte | R/W | |
55 | 1 | alarm, outdoor humidity, low | unsigned byte | R/W | |
56 | 2 | alarm, outdoor temperature, high | signed short | R/W | Multiply by 0.1 to get °C. |
58 | 2 | alarm, outdoor temperature, low | signed short | R/W | Multiply by 0.1 to get °C. |
60 | 2 | alarm, wind chill, high | signed short | R/W | Multiply by 0.1 to get °C. |
62 | 2 | alarm, wind chill, low | signed short | R/W | Multiply by 0.1 to get °C. |
64 | 2 | alarm, dew point, high | signed short | R/W | Multiply by 0.1 to get °C. |
66 | 2 | alarm, dew point, low | signed short | R/W | Multiply by 0.1 to get °C. |
68 | 2 | alarm, absolute pressure, high | unsigned short | R/W | Multiply by 0.1 to get hPa. |
70 | 2 | alarm, absolute pressure, low | unsigned short | R/W | Multiply by 0.1 to get hPa. |
72 | 2 | alarm, relative pressure, high | unsigned short | R/W | Multiply by 0.1 to get hPa. |
74 | 2 | alarm, relative pressure, low | unsigned short | R/W | Multiply by 0.1 to get hPa. |
76 | 1 | alarm, average wind speed, Beaufort | unsigned byte | R/W | |
77 | 2 | alarm, average wind speed, m/s | unsigned short | R/W | Multiply by 0.1 to get m/s. |
79 | 1 | alarm, gust wind speed, Beaufort | unsigned byte | R/W | |
80 | 2 | alarm, gust wind speed, m/s | unsigned short | R/W | Multiply by 0.1 to get m/s. |
82 | 1 | alarm, wind direction | unsigned byte | R/W | Multiply by 22.5 to get ° from north. |
83 | 2 | alarm, rain, hourly | unsigned short | R/W | Multiply by 0.1 to get mm. |
85 | 2 | alarm, rain, daily | unsigned short | R/W | Multiply by 0.1 to get mm. |
87 | 2 | alarm, time | BCD | R/W | Hour & minute. |
89 | 3 | (3080 only) alarm, illuminance | unsigned 3-byte integer | R/W | Multiply by 0.1 to get lux or fc, according to setting at address 29 bit 0. |
92 | 1 | (3080 only) alarm, UV | unsigned byte | R/W | |
93 | 1 | (3080 only) maximum, UV, value | unsigned byte | R/W | |
94 | 3 | (3080 only) maximum, illuminance, value | unsigned 3-byte integer | R/W | Multiply by 0.1 to get lux. |
97 | |||||
98 | 1 | maximum, indoor humidity, value | unsigned byte | R/W | |
99 | 1 | minimum, indoor humidity, value | unsigned byte | R/W | |
100 | 1 | maximum, outdoor humidity, value | unsigned byte | R/W | |
101 | 1 | minimum, outdoor humidity, value | unsigned byte | R/W | |
102 | 2 | maximum, indoor temperature, value | signed short | R/W | Multiply by 0.1 to get °C. |
104 | 2 | minimum, indoor temperature, value | signed short | R/W | Multiply by 0.1 to get °C. |
106 | 2 | maximum, outdoor temperature, value | signed short | R/W | Multiply by 0.1 to get °C. |
108 | 2 | minimum, outdoor temperature, value | signed short | R/W | Multiply by 0.1 to get °C. |
110 | 2 | maximum, wind chill, value | signed short | R/W | Multiply by 0.1 to get °C. |
112 | 2 | minimum, wind chill, value | signed short | R/W | Multiply by 0.1 to get °C. |
114 | 2 | maximum, dew point, value | signed short | R/W | Multiply by 0.1 to get °C. |
116 | 2 | minimum, dew point, value | signed short | R/W | Multiply by 0.1 to get °C. |
118 | 2 | maximum, absolute pressure, value | unsigned short | R/W | Multiply by 0.1 to get hPa. |
120 | 2 | minimum, absolute pressure, value | unsigned short | R/W | Multiply by 0.1 to get hPa. |
122 | 2 | maximum, relative pressure, value | unsigned short | R/W | Multiply by 0.1 to get hPa. |
124 | 2 | minimum, relative pressure, value | unsigned short | R/W | Multiply by 0.1 to get hPa. |
126 | 2 | maximum, average wind speed, value | unsigned short | R/W | Multiply by 0.1 to get m/s. |
128 | 2 | maximum, gust wind speed, value | unsigned short | R/W | Multiply by 0.1 to get m/s. |
130 | 2 | maximum, rain hourly, value | unsigned short | R/W | Multiply by 0.1 to get mm. |
132 | 2 | maximum, rain daily, value | unsigned short | R/W | Multiply by 0.1 to get mm. |
134 | 2 | maximum, rain weekly, value | unsigned short | R/W | Multiply by 0.1 to get mm. |
136 | 2 | maximum, rain monthly, value | unsigned short | R/W | Multiply by 0.1 to get mm. |
138 | 2 | maximum, rain total, value | unsigned short | R/W | Multiply by 0.1 to get mm. |
140 | 1 | high nibble for month and total rainfall | R/W | high nibble – month rainfall, low nibble – total rainfall | |
141 | 5 | maximum, indoor humidity, when | date-time | R/W | |
146 | 5 | minimum, indoor humidity, when | date-time | R/W | |
151 | 5 | maximum, outdoor humidity, when | date-time | R/W | |
156 | 5 | minimum, outdoor humidity, when | date-time | R/W | |
161 | 5 | maximum, indoor temperature, when | date-time | R/W | |
166 | 5 | minimum, indoor temperature, when | date-time | R/W | |
171 | 5 | maximum, outdoor temperature, when | date-time | R/W | |
176 | 5 | minimum, outdoor temperature, when | date-time | R/W | |
181 | 5 | maximum, wind chill, when | date-time | R/W | |
186 | 5 | minimum, wind chill, when | date-time | R/W | |
191 | 5 | maximum, dew point, when | date-time | R/W | |
196 | 5 | minimum, dew point, when | date-time | R/W | |
201 | 5 | maximum, absolute pressure, when | date-time | R/W | |
206 | 5 | minimum, absolute pressure, when | date-time | R/W | |
211 | 5 | maximum, relative pressure, when | date-time | R/W | |
216 | 5 | minimum, relative pressure, when | date-time | R/W | |
221 | 5 | maximum, average wind speed, when | date-time | R/W | |
226 | 5 | maximum, gust wind speed, when | date-time | R/W | |
231 | 5 | maximum, rain hourly, when | date-time | R/W | |
236 | 5 | maximum, rain daily, when | date-time | R/W | |
241 | 5 | maximum, rain weekly, when | date-time | R/W | |
246 | 5 | maximum, rain monthly, when | date-time | R/W | |
251 | 5 | maximum, rain total, when | date-time | R/W |