Click here to Skip to main content
15,890,506 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi all,

can anyone help me or has anyone solved such a Project.
I have bought two of TEMPer1F USB Thermometers and I want to Access them and get the temperature values read from them and written them to a SQL database.
I would like to do this likely in AutoIT (preferred) or another script language like VBS, JS or powershell.

I have found sample code in C# which communicates with this Kind of device. Some using a dll calle RDingUSB.dll some directly using Windows API/DLL'S like USBlib and/or HID

The device is a HID Standard device.

Here is the code I found in the INET (is for LINUX, but I Need it for Windows 7+)
The only Thing I Need is to get a list of devices => Array with same VID and PID and read Temperatur from them in °C in 0,1° accuracy
The rst I can do myself.

Any help is welcome
The found code sample:
#include <usb.h>
#include <stdio.h>
#include <time.h>

#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h> 
 
 
#define VERSION "0.0.1"
 
#define VENDOR_ID  0x0c45
#define PRODUCT_ID 0x7401
 
#define INTERFACE1 0x00
#define INTERFACE2 0x01
 
const static int reqIntLen=8;
const static int reqBulkLen=8;
const static int endpoint_Int_in=0x82; /* endpoint 0x81 address for IN */
const static int endpoint_Int_out=0x00; /* endpoint 1 address for OUT */
const static int endpoint_Bulk_in=0x82; /* endpoint 0x81 address for IN */
const static int endpoint_Bulk_out=0x00; /* endpoint 1 address for OUT */
const static int timeout=5000; /* timeout in ms */
 
const static char uTemperatura[] = { 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 };
const static char uIni1[] = { 0x01, 0x82, 0x77, 0x01, 0x00, 0x00, 0x00, 0x00 };
const static char uIni2[] = { 0x01, 0x86, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00 };
 /* Offset of temperature in read buffer; varies by product */
static size_t tempOffset;

static int bsalir=1;
static int debug=0;
static int seconds=5;
static int formato=0;
static int mrtg=0;

/* Even within the same VENDOR_ID / PRODUCT_ID, there are hardware variations
 * which we can detect by reading the USB product ID string. This determines
 * where the temperature offset is stored in the USB read buffer. */
const static struct product_hw {
    size_t      offset;
    const char *id_string;
} product_ids[] = {
    { 4, "TEMPer1F_V1.3" },
    { 2, 0 } /* default offset is 2 */
};

void bad(const char *why) {
        fprintf(stderr,"Fatal error> %s\n",why);
        exit(17);
}
 
 
usb_dev_handle *find_lvr_winusb();
 
void usb_detach(usb_dev_handle *lvr_winusb, int iInterface) {
        int ret;
 
	ret = usb_detach_kernel_driver_np(lvr_winusb, iInterface);
	if(ret) {
		if(errno == ENODATA) {
			if(debug) {
				printf("Device already detached\n");
			}
		} else {
			if(debug) {
				printf("Detach failed: %s[%d]\n",
				       strerror(errno), errno);
				printf("Continuing anyway\n");
			}
		}
	} else {
		if(debug) {
			printf("detach successful\n");
		}
	}
} 

usb_dev_handle* setup_libusb_access() {
     usb_dev_handle *lvr_winusb;

     if(debug) {
        usb_set_debug(255);
     } else {
        usb_set_debug(0);
     }
     usb_init();
     usb_find_busses();
     usb_find_devices();
             
 
     if(!(lvr_winusb = find_lvr_winusb())) {
                printf("Couldn't find the USB device, Exiting\n");
                return NULL;
        }
        
        
        usb_detach(lvr_winusb, INTERFACE1);
        

        usb_detach(lvr_winusb, INTERFACE2);
        
 
        if (usb_set_configuration(lvr_winusb, 0x01) < 0) {
                printf("Could not set configuration 1\n");
                return NULL;
        }
 

        // Microdia tiene 2 interfaces
        if (usb_claim_interface(lvr_winusb, INTERFACE1) < 0) {
                printf("Could not claim interface\n");
                return NULL;
        }
 
        if (usb_claim_interface(lvr_winusb, INTERFACE2) < 0) {
                printf("Could not claim interface\n");
                return NULL;
        }
 
        return lvr_winusb;
}
 

static void read_product_string(usb_dev_handle *handle, struct usb_device *dev)
{
    char prodIdStr[256];
    const struct product_hw *p;
    int strLen;

    memset(prodIdStr, 0, sizeof(prodIdStr));
    strLen = usb_get_string_simple(handle, dev->descriptor.iProduct, prodIdStr,
                                   sizeof(prodIdStr)-1);
    if (debug) {
        if (strLen < 0)
            puts("Couldn't read iProduct string");
        else
            printf("iProduct: %s\n", prodIdStr);
    }

    for (p = product_ids; p->id_string; ++p) {
        if (!strncmp(p->id_string, prodIdStr, sizeof(prodIdStr)))
            break;
    }
    tempOffset = p->offset;
}


usb_dev_handle *find_lvr_winusb() {
 
     struct usb_bus *bus;
        struct usb_device *dev;
 
        for (bus = usb_busses; bus; bus = bus->next) {
        for (dev = bus->devices; dev; dev = dev->next) {
                        if (dev->descriptor.idVendor == VENDOR_ID && 
                                dev->descriptor.idProduct == PRODUCT_ID ) {
                                usb_dev_handle *handle;
                                if(debug) {
                                  printf("lvr_winusb with Vendor Id: %x and Product Id: %x found.\n", VENDOR_ID, PRODUCT_ID);
                                }
 
                                if (!(handle = usb_open(dev))) {
                                        printf("Could not open USB device\n");
                                        return NULL;
                                }
                                read_product_string(handle, dev);
                                return handle;
                        }
                }
        }
        return NULL;
}
 
 
void ini_control_transfer(usb_dev_handle *dev) {
    int r,i;

    char question[] = { 0x01,0x01 };

    r = usb_control_msg(dev, 0x21, 0x09, 0x0201, 0x00, (char *) question, 2, timeout);
    if( r < 0 )
    {
          perror("USB control write"); bad("USB write failed"); 
    }


    if(debug) {
      for (i=0;i<reqIntLen; i++) printf("%02x ",question[i] & 0xFF);
      printf("\n");
    }
}
 
void control_transfer(usb_dev_handle *dev, const char *pquestion) {
    int r,i;

    char question[reqIntLen];
    
    memcpy(question, pquestion, sizeof question);

    r = usb_control_msg(dev, 0x21, 0x09, 0x0200, 0x01, (char *) question, reqIntLen, timeout);
    if( r < 0 )
    {
          perror("USB control write"); bad("USB write failed"); 
    }

    if(debug) {
        for (i=0;i<reqIntLen; i++) printf("%02x ",question[i]  & 0xFF);
        printf("\n");
    }
}

void interrupt_transfer(usb_dev_handle *dev) {
 
    int r,i;
    char answer[reqIntLen];
    char question[reqIntLen];
    for (i=0;i<reqIntLen; i++) question[i]=i;
    r = usb_interrupt_write(dev, endpoint_Int_out, question, reqIntLen, timeout);
    if( r < 0 )
    {
          perror("USB interrupt write"); bad("USB write failed"); 
    }
    r = usb_interrupt_read(dev, endpoint_Int_in, answer, reqIntLen, timeout);
    if( r != reqIntLen )
    {
          perror("USB interrupt read"); bad("USB read failed"); 
    }

    if(debug) {
       for (i=0;i<reqIntLen; i++) printf("%i, %i, \n",question[i],answer[i]);
    }
 
    usb_release_interface(dev, 0);
}

void interrupt_read(usb_dev_handle *dev) {
 
    int r,i;
    unsigned char answer[reqIntLen];
    bzero(answer, reqIntLen);
    
    r = usb_interrupt_read(dev, 0x82, (char*)answer, reqIntLen, timeout);
    if( r != reqIntLen )
    {
          perror("USB interrupt read"); bad("USB read failed"); 
    }

    if(debug) {
       for (i=0;i<reqIntLen; i++) printf("%02x ",answer[i]  & 0xFF);
    
       printf("\n");
    }
}

void interrupt_read_temperatura(usb_dev_handle *dev, float *tempC) {
 
    int r,i;
    unsigned char answer[reqIntLen];
    bzero(answer, reqIntLen);
    
    r = usb_interrupt_read(dev, 0x82, (char*)answer, reqIntLen, timeout);
    if( r != reqIntLen )
    {
          perror("USB interrupt read"); bad("USB read failed"); 
    }


    if(debug) {
      for (i=0;i<reqIntLen; i++) printf("%02x ",answer[i]  & 0xFF);
    
      printf("\n");
    }
    
    /* Temperature in C is a 16-bit signed fixed-point number, big-endian */
    *tempC = (float)(signed char)answer[tempOffset] +
             answer[tempOffset+1] / 256.0f;
}

void bulk_transfer(usb_dev_handle *dev) {
 
    int r,i;
    char answer[reqBulkLen];

    r = usb_bulk_write(dev, endpoint_Bulk_out, NULL, 0, timeout);
    if( r < 0 )
    {
          perror("USB bulk write"); bad("USB write failed"); 
    }
    r = usb_bulk_read(dev, endpoint_Bulk_in, answer, reqBulkLen, timeout);
    if( r != reqBulkLen )
    {
          perror("USB bulk read"); bad("USB read failed"); 
    }


    if(debug) {
      for (i=0;i<reqBulkLen; i++) printf("%02x ",answer[i]  & 0xFF);
    }
 
    usb_release_interface(dev, 0);
}
 

void ex_program(int sig) {
      bsalir=1;
 
      (void) signal(SIGINT, SIG_DFL);
}
 
int main( int argc, char **argv) {
 
     usb_dev_handle *lvr_winusb = NULL;
     float tempc;
     int c;
     struct tm *local;
     time_t t;

     while ((c = getopt (argc, argv, "mfcvhl::")) != -1)
     switch (c)
       {
       case 'v':
         debug = 1;
         break;
       case 'c':
         formato=1; //Celsius
         break;
       case 'f':
         formato=2; //Fahrenheit
         break;
       case 'm':
         mrtg=1;
         break;
       case 'l':
         if (optarg!=NULL){
           if (!sscanf(optarg,"%i",&seconds)==1) {
             fprintf (stderr, "Error: '%s' is not numeric.\n", optarg);
             exit(EXIT_FAILURE);
           } else {           
              bsalir = 0;
              break;
           }
         } else {
           bsalir = 0;
           seconds = 5;
           break;
         }
       case '?':
       case 'h':
         printf("pcsensor version %s\n",VERSION);
	 printf("      Aviable options:\n");
	 printf("          -h help\n");
	 printf("          -v verbose\n");
	 printf("          -l[n] loop every 'n' seconds, default value is 5s\n");
	 printf("          -c output only in Celsius\n");
	 printf("          -f output only in Fahrenheit\n");
	 printf("          -m output for mrtg integration\n");
  
	 exit(EXIT_FAILURE);
       default:
         if (isprint (optopt))
           fprintf (stderr, "Unknown option `-%c'.\n", optopt);
         else
           fprintf (stderr,
                    "Unknown option character `\\x%x'.\n",
                    optopt);
         exit(EXIT_FAILURE);
       }

     if (optind < argc) {
        fprintf(stderr, "Non-option ARGV-elements, try -h for help.\n");
        exit(EXIT_FAILURE);
     }
 
     if ((lvr_winusb = setup_libusb_access()) == NULL) {
         exit(EXIT_FAILURE);
     } 

     (void) signal(SIGINT, ex_program);

     ini_control_transfer(lvr_winusb);
      
     control_transfer(lvr_winusb, uTemperatura );
     interrupt_read(lvr_winusb);
 
     control_transfer(lvr_winusb, uIni1 );
     interrupt_read(lvr_winusb);
 
     control_transfer(lvr_winusb, uIni2 );
     interrupt_read(lvr_winusb);
     interrupt_read(lvr_winusb);


 
     do {
           control_transfer(lvr_winusb, uTemperatura );
           interrupt_read_temperatura(lvr_winusb, &tempc);

           t = time(NULL);
           local = localtime(&t);

           if (mrtg) {
              if (formato==2) {
                  printf("%.2f\n", (9.0 / 5.0 * tempc + 32.0));
                  printf("%.2f\n", (9.0 / 5.0 * tempc + 32.0));
              } else {
                  printf("%.2f\n", tempc);
                  printf("%.2f\n", tempc);
              }
              
              printf("%02d:%02d\n", 
                          local->tm_hour,
                          local->tm_min);

              printf("pcsensor\n");
           } else {
              printf("%04d/%02d/%02d %02d:%02d:%02d ", 
                          local->tm_year +1900, 
                          local->tm_mon + 1, 
                          local->tm_mday,
                          local->tm_hour,
                          local->tm_min,
                          local->tm_sec);

              if (formato==2) {
                  printf("Temperature %.2fF\n", (9.0 / 5.0 * tempc + 32.0));
              } else if (formato==1) {
                  printf("Temperature %.2fC\n", tempc);
              } else {
                  printf("Temperature %.2fF %.2fC\n", (9.0 / 5.0 * tempc + 32.0), tempc);
              }
              fflush(stdout);
           }
           
           if (!bsalir)
              sleep(seconds);
     } while (!bsalir);
                                       
     usb_release_interface(lvr_winusb, INTERFACE1);
     usb_release_interface(lvr_winusb, INTERFACE2);
     
     usb_close(lvr_winusb); 
      
     return 0; 
}


What I have tried:

I tried to Analyse the C# code, but since I have no knowledge or experience in C#
I cannot get anything from the code that I can use as base for realizing it in my known languages.
Posted
Updated 22-Mar-18 3:59am
v2
Comments
phil.o 22-Mar-18 9:08am    
This is not C#; this is C++C.
#realJSOP 22-Mar-18 9:13am    
WERD!
phil.o 22-Mar-18 9:26am    
What does that mean?
#realJSOP 22-Mar-18 9:48am    
It's street slang for "you are correct sir". I was just trying to street-up the question - you know - make it legit for the kit.
Jochen Arndt 22-Mar-18 9:19am    
It is C, not C++.

Don't try to convert C code to C#: what you get won't work very well - if at all - and will not be easy to maintain.

Instead, look at the code you have, and work out exactly what it is doing. Then use that as a specification for the C# code you need. You will need a SerialPort[^] to comunicate with the device.

Me? I'd start with the manufacturers website, and see if they have any sample code in C# and then work from there...
 
Share this answer
 
Accessing such devices requires communication with a device driver. Such might be not possible with scripting languages but I can't tell for sure. It is possible with programming languages including .Net languages like C# and VB.Net and also with the PowerShell. I don't know about VBS (which I suggest anyway to be removed from your list) and AutoIt.

Because each language (or group for .Net) has it's own method(s) for accessing such devices, you should choose the language first. Choose a language that you know already. Then look for the supported method(s) for that specific language. Ignore any examples for a different language because they won't help you.

The C example code from your question uses the (low level) libusb library on Linux. There is a Windows versions for that library so that the code can be also used with C/C++ on Windows. There are also .Net class libraries providing similar - but not identical - functions.

The simplest solution would be when a virtual COM port driver for your device exists. Then you can communicate using serial interface functions which should be supported by all languages including script languages.

Most manufacturers of such devices provide also an SDK including a library, a DLL and header file(s) for C/C++. The information from these can be used to access the DLL from .Net using PInvoke.

[EDIT]
A quick research unveiled that AutoIt supports DLL calls: DllCall[^]

The function names and the corresponding return types and parameter types should be documented by the supplier of the DLL or can be found in the C header file.

I suggest to use the DLL provided by the device manufacturer because using that will result in less code than the low level libusb from the C code you found.
[/EDIT]
 
Share this answer
 
v2
Comments
Ingo Beckmann 22-Mar-18 10:03am    
There doesn't exist any converters or Drivers providing COM-ports
it is a real HID device. I have a dll doing that communication with the USB device, called RDingUSB.dll. It would be helpfull for me to know how to Access the functions of it and how to work with more than 1 device with same VID and PID
Then I can realize it in AutoIT e.g.
Jochen Arndt 22-Mar-18 10:25am    
A virtual COM port driver uses the device DLL (DRingUsb.dll) to simulate a serial port in software. I mentioned it just for the case it exists.

Accessing multiple devices that have the same PID and VID requires that the devices have serial numbers. If not, Windows will assign a GUID according to the USB port which makes it difficult to identify a specific device.

You have to check first if AutoIt supports calling functions from an imported DLL. If that is not supported, you can't use AutoIt. For other languages it depends on the language as already explained. There is no general solution / method.
Ingo Beckmann 22-Mar-18 10:04am    
I only wanted to use the code I found to find out how to call the functions and get the value read in my known langs
Jochen Arndt 22-Mar-18 10:13am    
To use the code you need a Windows port of the libusb library (which contains it own DLL) and access it like any other DLL. But scripting languages usually don't support direct DLL access (besides PowerShell) and .Net requires using PInvoke.
Ingo Beckmann 22-Mar-18 10:08am    
The RDingUSB.dll is used by the Software coming on CDROM with the device.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900