TEMPer USB Temperature Sensor

I picked up a TEMPer USB temperature sensor from Walmart for about $12. My goal was to use it with my Home Assistant home automation system.

The model that I picked up supports Windows and it can be used directly in Excel. There is also integration with Home Assistant.

I found that the integration for Linux was tricky. This blog looks at how I got things working with a Raspberry Pi.

USB Connections

The lsusb command can be used to see which USB devices are connected:

pi@pi4:~ $ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 007: ID 413d:2107  
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

It is important to identify the ID model. The TEMPer USB model that I purchased was 413d:2107.

When I searched the Internet I found that people had created different packages but they were based on specific models. (Check your model).

temper.py

There is a Python library file that can be used on the TEMPer family of sensors. This library component is designed to be run directly as a Python file. It can be accessed by:

pip install temper-py
# Or get the file 
wget  https://raw.githubusercontent.com/ccwienk/temper/master/temper.py

Using the file directly will show the TEMPer device information (Note: use sudo):

$ sudo python3 temper.py
Bus 001 Dev 007 413d:2107 TEMPerGold_V3.1 29.31C 84.76F - - - -

$ sudo python3 temper.py --v
Firmware query: b'0186ff0100000000'
Firmware value: b'54454d506572476f6c645f56332e3120' TEMPerGold_V3.1 
Data value: b'80800b6d4e200000'
Bus 001 Dev 007 413d:2107 TEMPerGold_V3.1 29.25C 84.65F - - - -

$ sudo python3 temper.py --json
[
    {
        "vendorid": 16701,
        "productid": 8455,
        "manufacturer": "",
        "product": "",
        "busnum": 1,
        "devnum": 7,
        "devices": [
            "hidraw0",
            "hidraw1"
        ],
        "port": "1-1.4",
        "firmware": "TEMPerGold_V3.1",
        "hex_firmware": "54454d506572476f6c645f56332e3120",
        "hex_data": "80800b6d4e200000",
        "internal temperature": 29.25
    }
]

I found that the Python app was useful and it could be used on a variety of sensors.

Human Interface Devices

The TEMPer sensor acts like a Human Interface Device. When the TEMPer sensor is connected the dmesg utility can be used to show kernel information:

 $ dmesg -H
[May 1 21:22] usb 1-1.4: USB disconnect, device number 6
[May 1 21:23] usb 1-1.4: new full-speed USB device number 7 using xhci_hcd
[  +0.135008] usb 1-1.4: New USB device found, idVendor=413d, idProduct=2107, bcdDevice= 0.00
[  +0.000020] usb 1-1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[  +0.011366] input: HID 413d:2107 as /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:
[  +0.064445] hid-generic 0003:413D:2107.0009: input,hidraw0: USB HID v1.11 Keyboard [HID 413
[  +0.007181] hid-generic 0003:413D:2107.000A: hiddev96,hidraw1: USB HID v1.10 Device [HID 41
(END)

From this output I can see that TEMPer sensor is on the raw human interface device of hidraw1. (For this example the hidraw0 acts like a keyboard but it can’t be used to get temperature info). When I move the TEMPer sensor to a different PC I need to run dmesg again to recheck the hidraw device number, it could be 2,3,4 etc.

A Bash Script

There are some excellent links that got me about 95% of the way. The Bash script below will return a temperature value for my series of TEMPer USB thermometers.

#!/bin/bash
# 
# Get the temperature from a USB Temper Thermometer
#   
#   find the HID device from the kernel msg via dmesg
#   parse the line get HID device
hidstr=$(dmesg | grep -E  -m 1 'Device.*413d:2107')
# find the postion of the "hidraw" string
hidpos=$(echo $hidstr | grep -b -o hidraw  | awk 'BEGIN {FS=":"}{print $1}')

if [ $hidpos  = "" ]; then
  echo "No TEMPer device found"
else
  #get the hidraw device from the string, Note: offset of 1
  hidpos1=$((hidpos +1))
  hid=$(echo "/dev/${hidstr:hidpos1:7}")
  exec 5<> $hid
  # send out query msg
  echo -e '\x00\x01\x80\x33\x01\x00\x00\x00\x00\c' >&5
  # get binary response
  OUT=$(dd count=1 bs=8 <&5 2>/dev/null | xxd -p)
  # characters 5-8 is the temp in hex x1000
  HEX4=${OUT:4:4}
  DVAL=$((16#$HEX4))
  CTEMP=$(bc <<< "scale=2; $DVAL/100")
  echo $CTEMP 
fi

If you are always using the TEMPer in only one place you could simplify the script by hard coding the HID number. I wanted to move the sensor between devices so I added a check find the device.

15 thoughts on “TEMPer USB Temperature Sensor

  1. Hi, I find your code simple and is exactly what I need. But I can’t get the temperature from my Temper (1a86:e025). I uncommented the line : echo “TEMPer device found on: $hid”. and removed the “2>/dev/null” from the OUT line to see what is happening. I get:
    TEMPer device found on: /dev/0003:1A (so the Temper is found)
    from dd, I get:
    0+0 records in
    0+0 records out
    0 bytes (0 B) copied, 7.159e-05 s, 0.0 kB/s

    You talked about changing the hidraw number: where do you change it in the code. Can’t figure it out…
    Any idea? I tried the Python and temperv14.c and pcsensor.c and I get similar results.
    from lsusb:
    Bus 004 Device 003: ID 1a86:e025 QinHeng Electronics
    from dmesg:
    [ 6.188363] hid-generic 0003:1A86:E025.0001: input,hidraw0: USB HID v1.11 Keyboard [HID 1a86:e025] on usb-0000:00:14.0-1/input0
    [ 6.188584] hid-generic 0003:1A86:E025.0002: hiddev0,hidraw1: USB HID v1.10 Device [HID 1a86:e025] on usb-0000:00:14.0-1/input1
    Thanks in advance

    Like

  2. Found the issue. In the line:
    awk ‘{ p=index($4,”,”); print “/dev/” substr($4,p+1,7) }’)
    changed to:
    awk ‘{ p=index($5,”,”); print “/dev/” substr($5,p+1,7) }’)
    On the dmesg, the number of fields is not the same…

    Like

    1. Hi Pierre,

      I’m glad to hear that you got things working. I did some playing with OpenWRT when I repurposed some home routers and I found that the dmsg output isn’t as standard as I had thought.

      Below is the code I used on OpenWRT. I hand coded hidraw0…1,2. So basically I started at 0, then 1… until I got a temperature output. I’d like to review the dsmg search to account for different output.

      Cheers
      Pete

      #!/bin/ash
      # Note: change to ash to bash for non OpenWRT
      #
      # temper.sh – get temperature from a USB thermometer
      #
      hid=”/dev/hidraw1″
      exec 5 $hid
      # send out query msg
      echo -e ‘\x00\x01\x80\x33\x01\x00\x00\x00\x00\c’ >&5
      # get binary response
      OUT=$(dd count=1 bs=8 /dev/null | xxd -p)
      # characters 5-8 is the temp in hex x1000
      HEX4=${OUT:4:4}
      DVAL=$(printf ‘%d’ “0x${HEX4}”)
      awk “BEGIN {print ($DVAL/100)}”

      Like

  3. Hi Pierre,

    The dmesg output doesn’t appear to be consistent between Linux OSs, so I changed the code to search for the position of the “hidraw” string.

    The new code is working fine in Ubuntu/Raspian. I wonder if you’d mind checking my temper Bash code in slackware?

    Thanks
    Pete

    #!/bin/bash
    #
    # Get the temperature from a USB Temper Thermometer
    #
    # find the HID device from the kernel msg via dmesg
    # parse the line get HID device
    hidstr=$(dmesg | grep -E -m 1 ‘Device.*413d:2107’)
    # find the postion of the “hidraw” string
    hidpos=$(echo $hidstr | grep -b -o hidraw | awk ‘BEGIN {FS=”:”}{print $1}’)

    if [ $hidpos = “” ]; then
    echo “No TEMPer device found”
    else
    #get the hidraw device from the string, Note: offset of 1
    hidpos1=$((hidpos +1))
    hid=$(echo “/dev/${hidstr:hidpos1:7}”)
    exec 5 $hid
    # send out query msg
    echo -e ‘\x00\x01\x80\x33\x01\x00\x00\x00\x00\c’ >&5
    # get binary response
    OUT=$(dd count=1 bs=8 /dev/null | xxd -p)
    # characters 5-8 is the temp in hex x1000
    HEX4=${OUT:4:4}
    DVAL=$((16#$HEX4))
    CTEMP=$(bc <<< "scale=2; $DVAL/100")
    echo $CTEMP
    fi

    Like

    1. Hi,

      the line:
      exec 5 $hid
      should be:
      exec 5 $hid
      the line:
      OUT=$(dd count=1 bs=8 /dev/null | xxd -p)
      should be:
      OUT=$(dd count=1 bs=8 /dev/null | xxd -p)

      It’s called “technician dyslexia” LOL!

      Here is the result from your script:
      root@husky2:/usr/pierre/bin/temper# ./tempernewtest
      0

      Here is the result from mine:
      root@husky2:/usr/pierre/bin/temper# ./tempertest
      23.87

      Even after a reboot, I still get the same result.

      Here is my code:
      #!/bin/bash
      #
      # Get the temperature from a USB Temper Thermometer
      #
      # find the HID device from the kernel msg via dmesg
      # parse the line get HID device
      hid=/dev/hidraw1
      if [ $hid = “” ]; then
      echo “No TEMPer device found”
      else
      #echo “TEMPer device found on: $hid”
      exec 5 $hid
      # send out query msg
      echo -e ‘\x00\x01\x80\x33\x01\x00\x00\x00\x00\c’ >&5
      # get binary response
      OUT=$(dd count=1 bs=8 /dev/null | xxd -p)
      # characters 5-8 is the temp in hex x1000
      HEX4=${OUT:4:4}
      DVAL=$((16#$HEX4))
      CTEMP=$(bc <<< "scale=2; $DVAL/100")
      echo $CTEMP
      fi

      One thing I noticed with my code: If I get the result ok, then disconnect the usb key and reconnect it right away, result is still ok. But if I try the script while the usb key is out, I get a 0 result, which is normal. But even after reconnecting the usb key, I still get the 0 result. I need to reboot to get back to normal.

      Like

    2. This is what I get when executing the script with debugging:

      root@husky2:/usr/pierre/bin/temper# ./tempernewtest
      hidstr found on: [ 6.623658] hid-generic 0003:1A86:E025.0002: hiddev0,hidraw1: USB HID v1.10 Device [HID 1a86:e025] on usb-0000:00:1d.0-1.8/input1
      hidpos found on: 53
      0

      Note the 53

      If I call it directly from the command line, I get:

      echo “[ 6.623658] hid-generic 0003:1A86:E025.0002: hiddev0,hidraw1: USB HID v1.10 Device [HID 1a86:e025] on usb-0000:00:1d.0-1.8/input1″ |grep -b -o hidraw| awk ‘BEGIN {FS=”:”}{print $1}’
      56

      Note the 56, which is accurate.

      Here is the complete script:

      #!/bin/bash
      #
      # Get the temperature from a USB Temper Thermometer
      #
      # find the HID device from the kernel msg via dmesg
      # parse the line get HID device
      hidstr=$(dmesg | grep -E -m 1 ‘Device.*1a86:e025’)
      # find the postion of the “hidraw” string
      hidpos=$(echo $hidstr | grep -b -o hidraw | awk ‘BEGIN {FS=”:”}{print $1}’)

      if [ $hidpos = “” ]; then
      echo “No TEMPer device found”
      else
      echo “hidstr found on: $hidstr”
      echo “hidpos found on: $hidpos”
      #get the hidraw device from the string, Note: offset of 1
      hidpos1=$((hidpos +1))
      hid=$(echo “/dev/${hidstr:hidpos1:7}”)
      exec 5 $hid
      # send out query msg
      echo -e ‘\x00\x01\x80\x33\x01\x00\x00\x00\x00\c’ >&5
      # get binary response
      OUT=$(dd count=1 bs=8 /dev/null | xxd -p)
      # characters 5-8 is the temp in hex x1000
      HEX4=${OUT:4:4}
      DVAL=$((16#$HEX4))
      CTEMP=$(bc <<< "scale=2; $DVAL/100")
      echo $CTEMP
      fi

      Like

    1. Hi,
      What is your hardware and OS? I found that this script worked on my Raspberry PI (Raspbian), and 2 nodes that I had at home.

      I was getting the USB temper device info from dmesg. I would suggest putting in some echo messages to check the positioning within the returned string.

      Like

  4. Hello, thank you for sharing your project with so much detail. I’m kind of a newbie for raspberry/programming and homeassistant. And that’s why I’m embarrassed to make you this question. I think I was able to get/install the temper.py but I’m not being able to run Sudo commands for following your remaining steps…I tried to go trough both the Home Assistant Add-on “Terminal & SSH” and with PuTTy using root to login. I always got the same message: “sudo: command not found”. I sense the solution might be very simple, and that’s the reason of my embarrassment…Sorry for upbringing the question anyway, and thank you in advance for giving an hand to a newbie.

    Like

    1. Hi Sergio,
      Hey no problem asking questions.

      If you’re on a Raspberry Pi with the Homeassistant image, only a subset of the Bash command set loaded, and “sudo” is not available.

      When I originally wrote the blog, there was no Temper HA add-in, however since then one has been added, see: https://www.home-assistant.io/integrations/temper/

      If you’re on a Pi with the generic Raspian or Debian image, you should have no problem with “sudo”. The only exception would be if you loaded a custom image for students and your user login is restricted.

      I hope that this helps. Good luck. Let me know if you get stuck.

      Cheers
      Pete

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s