I'm trying to use Python and pywinusb-0.3.2 to read data from a USB weighing scale when a valid request hits the web server (requested_serial_number
is coming from the query string).
So I have the following code inside my do_GET
:
all_hids = hid.find_all_hid_devices()
if all_hids:
for index, device in enumerate(all_hids):
if device.serial_number == requested_serial_number:
device.open()
try:
device.set_raw_data_handler(scales_handler)
while True:
sleep(0.1)
except GotStableWeightException as e:
self.do_HEAD(200)
self.send_body(e.value)
And this is my scales_handler (plus custom exception definition):
def scales_handler(data):
print("Byte 0: {0}".format(data[0]))
print("Byte 1: {0}".format(data[1]))
print("Byte 2: {0}".format(data[2]))
print("Byte 3: {0}".format(data[3]))
print("Byte 4: {0}".format(data[4]))
print("Byte 5: {0}".format(data[5]))
print("All: {0}".format(data))
if data[1] == 4:
raise GotStableWeightException(data[4] + (256 * data[5]))
class GotStableWeightException(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
So the process is:
HTTPServer
and BaseHTTPRequestHandler
do_GET
function.do_GET
performs some basic validation and then searches for a matching USB HID (my first code sample).What I'm trying to achieve:
I want to allow the data handler to keep reading from the scale until data[1] == 4
(which indicates a stable reading from the scale). At that point, I want to retrieve this reading in my do_GET
and send it to the waiting HTTP client, close the device and end the function.
However, my GotStableWeightException
isn't caught inside my do_GET
, I think because it is thrown in a different thread. I'm new to programming with multiple threads, and I'm having trouble working out how I can get the result back to do_GET
once it matches the data[1] == 4
condition.
EDIT
What I get:
Here's the output I see in the terminal from scales_handler
:
Byte 0: 3
Byte 1: 4
Byte 2: 2
Byte 3: 0
Byte 4: 204
Byte 5: 0
All: [3, 4, 2, 0, 204, 0]
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python33\lib\threading.py", line 639, in _bootstrap_inner
self.run()
File "C:\Python33\lib\site-packages\pywinusb-0.3.2-py3.3.egg\pywinusb\hid\core.py", line 886, in run
hid_object._process_raw_report(raw_report)
File "C:\Python33\lib\site-packages\pywinusb-0.3.2-py3.3.egg\pywinusb\hid\helpers.py", line 64, in new_function
return function_target(*args, **kw)
File "C:\Python33\lib\site-packages\pywinusb-0.3.2-py3.3.egg\pywinusb\hid\core.py", line 714, in _process_raw_report
self.__raw_handler(helpers.ReadOnlyList(raw_report))
File "C:\USB HID Scales\server.py", line 28, in scales_handler
raise GotStableWeightException(data[4] + (256 * data[5]))
GotStableWeightException: 204
So device
is a threaded HidDevice
class. As you point out, raising an exception in this threaded object won't get caught by the handler (your do_GET
).
However, I'm wondering if raising an exception is really easiest thing to do (exceptions tend to be reserved for errors and problems). To achieve your aims, is it possible to use a global
variable and do something like this;
global e_value
e_value = None
def scales_handler(data):
print("Byte 0: {0}".format(data[0]))
print("Byte 1: {0}".format(data[1]))
print("Byte 2: {0}".format(data[2]))
print("Byte 3: {0}".format(data[3]))
print("Byte 4: {0}".format(data[4]))
print("Byte 5: {0}".format(data[5]))
print("All: {0}".format(data))
if data[1] == 4:
e_value = data[4] + (256 * data[5]))
devices = []
try:
for index, device in enumerate(all_hids):
if device.serial_number == requested_serial_number:
devices.append(device)
device.open()
device.set_raw_data_handler(sample_handler)
while True:
time.sleep(0.1)
finally:
for device in devices:
device.close()
if e_value is not None:
self.do_HEAD(200)
self.send_body(e_value)
I can't attest to what your devices are, so I should warn that this isn't thread safe - if more than one device has data[1] == 4
you will only have e_value
set by the last device to access it. (Though fixing this would be simple with a global array and counter object).