Skip to content

Instantly share code, notes, and snippets.

@MartinEnders
Forked from anonymous/hid_relay_test.py
Last active December 18, 2017 12:07
Show Gist options
  • Save MartinEnders/dbc2474040ed5311896067788e51a438 to your computer and use it in GitHub Desktop.
Save MartinEnders/dbc2474040ed5311896067788e51a438 to your computer and use it in GitHub Desktop.
Controlling USB-HIT Relays connected to different USB-Ports from Linux (Debian) with Python 3
from __future__ import print_function
import hid
import time
# Ziel des Skripts: Ansteuern von USB-Relais via HID
# Durch die Identifikation der HID-Devices via device_path
# koennen z.B. zwei Relais an zwei USB-Anschluessen angesteuert werden.
# Problem: Nach an- und abstecken der Relais bekommen die Relais neue
# Pfade zugewiesen. Eine eindeutige Identifikation scheint nicht mgl. zu sein.
#######################################################################
# QUELLEN:
# https://github.com/patrickjahns/simpleusbrelay/blob/master/simpleusbrelay/__init__.py
# Aus diesem Paket habe ich ide Byte-Reihenfolgen fuer an und aus gezogen.
# https://github.com/trezor/cython-hidapi
# Installation des hid-packages (s. Readme von Link)
#######################################################################
# ANMERKUNGEN:
# Forked from anonymus because I didn't recognize that I was not logged in when I created the Gist.
# HIDAPI library for Windows, Linux, FreeBSD and Mac OS X
# Basis fuer python hidapi
# https://github.com/signal11/hidapi
# https://github.com/pavel-a/usb-relay-hid/releases
# -> Kommandozeilentool ist nicht schlecht
# kommt aber nicht mit multiplen relais an unterschiedlichen
# USB-Anschluessen zurecht
# Python Code-Suche: http://nullege.com --> einfach cool
#devices on array
byte_devices_on = [\
[0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFF, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFF, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFF, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFF, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]\
]
#devices off array
byte_devices_off = [\
[0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFD, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFD, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFD, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFD, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFD, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFD, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],\
[0xFD, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]\
]
device_paths = []
# Hier werden alle HID-Devices mit der Vendor-ID 0x16c0 ausgegeben.
# Falls man enumerate keinen Parameter uebergibt werden alle Devices ausgegeben
# Das kann man verweneden um die Vendor-ID zu ermitteln
# oder die Vendor-ID kann via lsusb ermittelt werden
for d in hid.enumerate(0x16c0):
print("-------------")
device_paths.append(d['path'])
keys = list(d.keys())
keys.sort()
for key in keys:
print("%s : %s" % (key, d[key]))
print()
# Ausgabe der HID Device Paths
print("-------------------\n" + str(device_paths) + "\n-------------------")
try:
print("Opening the device")
# Erzeugen der Device-Objekte
h1 = hid.device()
h2 = hid.device()
# Oeffnen der Device-Objekte basierend auf dem PATH
# Path ist in meinem Fall das einzige was die beiden USB-Relais unterscheidet
h1.open_path(device_paths[0])
h2.open_path(device_paths[1])
# Beispiele fuer zugriff auf Device Parameter
# print("Manufacturer: %s" % h1.get_manufacturer_string())
# print("Product: %s" % h1.get_product_string())
# print("Serial No: %s" % h1.get_serial_number_string())
# Serial Number ist bei meinen beiden Relais identisch.
# Daher auch nicht zum unterscheiden geeignet.
print("Serial No 1: %s" % h1.get_serial_number_string())
print("Serial No 2: %s" % h2.get_serial_number_string())
s1 = h1.get_serial_number_string()
s2 = h2.get_serial_number_string()
print(s1,s2,s1==s2) # s1==s2 --> True
# enable non-blocking mode
h1.set_nonblocking(1)
h2.set_nonblocking(1)
# write some data to the device
print("Write the data")
# Relais abwechselnd ein und ausschalten
for x in range(2):
h1.write(byte_devices_on[0])
time.sleep(0.5)
h1.write(byte_devices_off[0])
h2.write(byte_devices_on[0])
time.sleep(0.5)
h2.write(byte_devices_off[0])
# read back the answer
# Kann eigentlich auskommentriet werden weil man aus den Relais
# wahrscheinlich nichts auslesen kann.
print("Read the data")
while True:
d1 = h1.read(64)
if d1:
print(d)
else:
break
# Kann eigentlich in finally Block
print("Closing the device")
h1.close()
h2.close()
except IOError as ex:
print(ex)
print("You probably don't have the hard coded device. Update the hid.device line")
print("in this script with one from the enumeration list output above and try again.")
print("Done")
@MartinEnders
Copy link
Author

MartinEnders commented Dec 18, 2017

File: /etc/udev/rules.d/99-hid.rules

UDEV-Rules for usage of hid-devices as normal user:
Source: https://github.com/signal11/hidapi/blob/master/udev/99-hid.rules

# If you are using the libusb implementation of hidapi (libusb/hid.c), then
# use something like the following line, substituting the VID and PID with
# those of your device. Note that for kernels before 2.6.24, you will need
# to substitute "usb" with "usb_device". It shouldn't hurt to use two lines
# (one each way) for compatibility with older systems.

# HIDAPI/libusb
SUBSYSTEM=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05df", MODE="0666"


# If you are using the hidraw implementation (linux/hid.c), then do something
# like the following, substituting the VID and PID with your device. Busnum 1
# is USB.

# HIDAPI/hidraw
KERNEL=="hidraw*", ATTRS{busnum}=="1", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05df", MODE="0666"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment