Communicating with a RDing TemperHum sensor

This summer I purchased some TemperHum devices from DX. The goal was to track humidity and temperature levels and store the results in a database using my own software. It was sort of a summer project, but I never got around to finishing it. The included software didn’t work properly on 64bit Win7, but I found the ThermoHID freeware that worked most of the time. It froze about once a week, but at least I had readings. It didn’t support database exports though, and I still wanted to write the software myself Smilefjes

The manufacturers site clearly states that writing your own software is possible, but the details were at best sketchy. Searching revealed that I was not the only one with trouble connecting to these devices. One of the main issues seems to be that there are several versions that look exactly the same. To be specific, the version I have is detected by Windows as hardware id 1130, PID 660C. Furthermore you have to interface with a DLL from the manufacturer, for which I have yet to find an official API. This also exists in several versions. The one I’m using is called HidFTDll.dll, is 176 194bytes and last modified 2009.08.29.

Connecting to the HidFTDll.dll

I made a separate class to interface with the DLL. It took a lot of experimentation to find a working import string, so I suspect that the interface might change a lot between versions.

/// 
///  Made for HIDFTDll.dll dated 29.08.2009 - 17:54 and 172KiB, delivered as part of original software TemperHum V10.5
/// 
class HIDFTDll
{
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention=CallingConvention.Cdecl)]
	public static extern void EMyCloseDevice();
	
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
	public static extern int EMyDetectDevice(long myhwnd);
	
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
	public static extern bool EMyInitConfig(bool dOrc);
	
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
	public static extern bool EMyReadEP(ref byte up1, ref byte up2, ref byte up3, ref byte up4, ref byte up5, ref byte up6);
	
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
	public static extern bool EMyReadHid([MarshalAs(UnmanagedType.AnsiBStr)] ref string pcBuffer, byte btUrlIndex, int btUrlLen);
	
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
	public static extern double EMyReadHUM(ref double temp, ref double hum);
	
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
	public static extern double EMyReadTemp(bool flag);
	
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
	public static extern void EMySetCurrentDev(int nCurDev);
	
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
	public static extern bool EMyWriteEP(ref byte fd1, ref byte fd2, ref byte fd3, ref byte fd4, ref byte fd5);
	
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
	public static extern bool EMyWriteHid(ref char[] pcBuffer, byte btUrlIndex, int btUrlLen);
	
	[DllImport("HidFTDll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
	public static extern bool EMyWriteTempText(bool flag);
}

Code for reading the data:

HIDFTDll.EMyCloseDevice();
int intDevices = HIDFTDll.EMyDetectDevice(0);

for (int i = 0; i < intDevices; i++)
{
	//Select the chosen device.
	HIDFTDll.EMySetCurrentDev(i);
	Thread.Sleep(100);

	//Initialize 
	HIDFTDll.EMyInitConfig(true);
	Thread.Sleep(100);
	//Read data
	double dblTemp1 = 0.0; 
	double dblHum = 0.0;
	double dblTemp2 = HIDFTDll.EMyReadHUM(ref dblTemp1, ref dblHum);
	//Both the temp variables are set to the same value, but both seem to be needed to genreate a result. 
	//It migth be used for devices with two temperature sensors
	txtResult.AppendText("Device:\t" + i + "\tTemp:\t" + dblTemp2 + "\tHum:\t" + dblHum + NL);
}

I have yet to figure out how to distinguish between sensors when you have more than one connected to the same computer. The code will read all connected sensors though, and the device index (zero based) seems to be constant as long as you don’t disconnect or add devices. I was hoping to find a way to uniquely identify a specific sensor, but so far I’ve struck out.

Sample code: https://lokna.no/?attachment_id=1044

Author: DizzyBadger

SQL Server DBA, Cluster expert, Principal Analyst

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.