Linux support for TFA Klima-Logger

4 minute read

Update 2012-03-01:
I just ordered 2 outdoor sensors and the plan is to connect the Klima-Logger to a Raspberry Pi Board to make the data available via browser on my home network. Here are some resources I found

Outdated:

I recently bought a hygrometer from TFA-Dostmann, called Klima-Logger. It is the cheapest thermometer and hygrometer with PC connectivity I could find on the market. Unfortunately only a Windows software is provided to get the recorded values for temperature and humidity. I thought a Linux driver would be cool and started searching for resources on the net.  Usually the Linux community is very fast in supporting new gadgets of any kind, but  nothing could be found.

That was driving me to think about writing support on my own. The first thing I did was to install the demo version of IDA Pro 4.8, a commercial disassembler for Windows, to look at any valuable information inside the executable. Some symbols I found were very narrative, for example CI2CDriver::setScl or CI2CDriver::setSda which indicated that some kind of I2C communication was used for accessing the device. The Windows API calls to GetCommModemStatus and EscapeCommFunction gave a hint that only serial flag lines were used for the I2C communication. At least for writing, informational and error messages from the data segement were indicating exactly which serial flag lines are used:

(newState == SdaHigh) ? CLRRTS : SETRTS

and

(newState == SclHigh) ? CLRDTR : SETDTR

That means RTS (Request To Send) is used for SDA (Serial Data) and DTR (Data Terminal Ready) is used for SCL (Serial Clock) write functionality. The EscapeCommFunction from the Win32 API is utilized to set or clear the RTS and DTR serial flag lines.

Reading is done by utilyzing the GetCommModemStatus Win32 API function. Unfortunately I haven’t found any strings from the data segment that reveal the assignment of the read flags directly. Assumptions are that DSR (Data Set Ready) and CTS (Clear To Send) lines are used for reading SCL and SDA lines. The problem is to find out whether SCL == DSR and SDA == CTS or whether SCL == CTS and SDA == DSR. The signals might additionally be inverted SCL == CLRCTS or SCL == SETCTS.

By looking at the board inside the hygrometer I found an Atmel 24C256 which is an EEPROM with an I2C interface and a capacity of 256KB (0x00000-0x39999).

The next step was trying to decipher the I2C protocol over the serial port status lines. I searched for a topic on how to install hooks for Win32 API system calls and found a solution from Microsoft Research on system call interception, called Detours (See article ‘Intercepting Win32 API system calls’ on how to use this tool).
My Detour dynamic link library with trampoline functions for all serial port Win32 API calls delivered a file with the recorded serial line status changes, but I forgot associating the SCL and SDA signals on a time basis. That made the data delivered by the Detours library unusable for analyzing the protocol. Further thinking about this solution led to the conclusion that it might be an uncomparably high effort to write this extension as it would require multiple threads being synchronized by timer interrupts in order to get this synchronization on a time basis.

Further looking through the data segment of the Windows application revealed that on top of the EEPROM some kind of Ringbuffer has been implemented.
The Ringbuffer seems to store the temperature and the humidity of each transmitter that is wirelessly connected to the device. The Windows software shows a list of 5 possible sensor pairs, but only the column for one pair is filled with values coming from the built in temperature- and humidity-sensor pair on the device. The conclusion for this observation is that 4 wireless transmitters can be connected and that the ring-buffer always seems to reserve space for all possible sensor pairs. Here as well, the structure of some data items haven’t been identified so far, for example start markers and end markers of data sets.
Without a claim of correctness, this might be the structure of the EEPROM:

   00000 RING_BUFFER_CONFIG  
   00000 NrOfTransmitters  
   00004 Start  
   00008 End  
   0000c ByteSize  
   00010 DatasetSize  
   00014 DatasetCount  
   00018 RING_BUFFER_START (earliest start)  

   Dataset #1  
   00018 TIMESTAMP (usually a long aka 8 Bytes)  
   00020 TEMPERATURE of Built In sensor (1 Byte)  
   00021 HUMIDITY of Built In sensor (1 Byte)  
   00022 TEMPERATURE of transmitter sensor #1 (1 Byte)  
   00023 HUMIDITY of transmitter sensor #1 (1 Byte)  
   00024 TEMPERATURE of transmitter sensor #2 (1 Byte)  
   00025 HUMIDITY of transmitter sensor #2 (1 Byte)  
   00026 TEMPERATURE of transmitter sensor #3 (1 Byte)  
   00027 HUMIDITY of transmitter sensor #3 (1 Byte)  
   00028 TEMPERATURE of transmitter sensor #4 (1 Byte)  
   00029 HUMIDITY of transmitter sensor #4 (1 Byte)  

   Dataset #2  
   0002a TIMESTAMP (usually a long aka 8 Bytes)  
   39999 RING_BUFFER_END  

What I found out so far:

  • Serial Port Interface (Writing: SDA High == CLRRTS, SDA Low == SETRTS, Reading: DSR, CTS)
  • EEPROM Atmel 24C256 with Ringbuffer for data sets and means to identify not yet read data sets.
  • Linux I2C layer might provide basis for a possible solution as it implements all the infrastructure with pluggable device support.

The next steps are to get familiar with the Linux I2C layer and to learn how to write external Linux kernel modules for the Linux 2.6 kernel, especially for Ubuntu Linux which I have installed on my notebook.