Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
ragaller committed Oct 27, 2019
0 parents commit 7058e6f
Show file tree
Hide file tree
Showing 6 changed files with 830 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*~
/temper
/temper-*

674 changes: 674 additions & 0 deletions LICENSE-GPL-3.0.txt

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
temper: temper.c
@gcc $< -l hidapi-hidraw -o $@

release: temper
@cp temper temper-linux-$$(git tag -l --points-at HEAD | cut -d/ -f2)-$$(uname -m) \
&& strip temper-linux-$$(git tag -l --points-at HEAD | cut -d/ -f2)-$$(uname -m) \
&& sha256sum temper-linux-$$(git tag -l --points-at HEAD | cut -d/ -f2)-$$(uname -m) > temper-linux-$$(git tag -l --points-at HEAD | cut -d/ -f2)-$$(uname -m).sha256sum

clean:
@rm -f temper temper-* *~ .*~

45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Read the temperature of a TEMPer device with ID 413d:2107
There are many libraries (C, Python) out there for reading the TEMPer
family of thermometer and hygrometer devices.

Since I own only one device with USB ID `413d:2107` and wanted just simple JSON output, I
wrote yet another program to read from this kind of USB device.

## Dependencies
It uses the [HIDAPI](https://github.com/signal11/hidapi) library as dependency.

On Debian (based):

sudo apt install libhidapi-hidraw0

On Arch:

sudo pacman -S hidapi

## Device

### `dmesg`

Example `dmesg` output:

[35813.492854] usb 2-1.3: new full-speed USB device number 25 using ehci-pci
[35813.591045] usb 2-1.3: New USB device found, idVendor=413d, idProduct=2107, bcdDevice= 0.00
[35813.591053] usb 2-1.3: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[35813.603164] input: HID 413d:2107 as /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.3/2-1.3:1.0/0003:413D:2107.0027/input/input39
[35813.660537] hid-generic 0003:413D:2107.0027: input,hidraw0: USB HID v1.11 Keyboard [HID 413d:2107] on usb-0000:00:1d.0-1.3/input0
[35813.662589] hid-generic 0003:413D:2107.0028: hiddev1,hidraw1: USB HID v1.10 Device [HID 413d:2107] on usb-0000:00:1d.0-1.3/input1

### `lsusb`

Example `lsusb -d 413d:2107` output:

Bus 002 Device 025: ID 413d:2107

### Photo

Photo of my TEMPer device:

![](TEMPer_413d_2107.jpg)

## License
The program is licensed under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.txt) ([local copy](LICENSE-GPL-3.0.txt)).
Binary file added TEMPer_413d_2107.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
96 changes: 96 additions & 0 deletions temper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hidapi/hidapi.h>

#define MAX_STR 255

char* find_device_path(unsigned short vendor_id, unsigned short product_id);
bool read_temperature(hid_device *handle, int* result);

#define TEMPer_VendorId 0x413d
#define TEMPer_ProductId 0x2107

int main(int argc, char* argv[]) {
if(hid_init()) {
fwprintf(stderr,L"failed to initialize HID API\n");
return EXIT_FAILURE;
}

char* path = find_device_path(TEMPer_VendorId, TEMPer_ProductId);

if(!path) {
fwprintf(stderr,L"cannot find matching HID device ID %x:%x, try 'lsusb' or 'lsusb -d %x:%x'\n",
TEMPer_VendorId,TEMPer_ProductId,
TEMPer_VendorId,TEMPer_ProductId);
return EXIT_FAILURE;
} else {
hid_device *handle = hid_open_path(path);

if (!handle) {
fwprintf(stderr,L"failed to open device %s\n"
"to avoid running this program as root, put the following udev rule in e.g. /etc/udev/rules.d/90-temper.rules\n\n"
"SUBSYSTEMS==\"usb\", ACTION==\"add\", ATTRS{idVendor}==\"%x\", ATTRS{idProduct}==\"%x\", MODE=\"666\"\n\n",
path,TEMPer_VendorId,TEMPer_ProductId);
free(path);
return EXIT_FAILURE;
}

int temperature = INT_MIN;
if(read_temperature(handle,&temperature)) {
printf("{ \"temp_celsius\": %d.%d }\n",temperature/100,temperature%100);
}
hid_close(handle);
free(path);
}

if(hid_exit()) {
fwprintf(stderr,L"failed to shutdown HID API\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

bool read_temperature(hid_device *handle, int* result) {
unsigned char buf[16];
unsigned char cmd[8] = { 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 };

memset(&buf,0,sizeof(buf));

int rc = hid_write(handle, cmd, sizeof(cmd));

if(-1 == rc) {
return false;
}

// expected response is exactly 8 bytes
bool ok = (8 == hid_read(handle, buf, sizeof(buf)));

if (ok) {
// temperature is stored in byte 2&3 => return value is a hundreth of °C
*result = (buf[2]*256 + buf[3]);
}
return ok;
}


char* find_device_path(unsigned short vendor_id, unsigned short product_id) {

struct hid_device_info *devices = hid_enumerate(vendor_id,product_id);
struct hid_device_info *cur_dev = devices;

while (cur_dev) {
// the hardware provides two devices, we need the second one
if (1 == cur_dev->interface_number && cur_dev->path) {
char* path = malloc(strlen(cur_dev->path)+1);
strcpy(path,cur_dev->path);
hid_free_enumeration(devices);
return path;
}
cur_dev = cur_dev->next;
}
hid_free_enumeration(devices);
return NULL;
}

0 comments on commit 7058e6f

Please sign in to comment.