From 9769cad663948f157d48e450ef844cb969c92f34 Mon Sep 17 00:00:00 2001 From: pavel Date: Mon, 30 Mar 2015 02:48:54 +0300 Subject: [PATCH] Added Python test, moved the cmd example script to /Test --- {commandline => Test}/relay1-pulse.sh | 0 Test/test2m.py | 213 ++++++++++++++++++++++++++ 2 files changed, 213 insertions(+) rename {commandline => Test}/relay1-pulse.sh (100%) create mode 100644 Test/test2m.py diff --git a/commandline/relay1-pulse.sh b/Test/relay1-pulse.sh similarity index 100% rename from commandline/relay1-pulse.sh rename to Test/relay1-pulse.sh diff --git a/Test/test2m.py b/Test/test2m.py new file mode 100644 index 0000000..21845e9 --- /dev/null +++ b/Test/test2m.py @@ -0,0 +1,213 @@ +""" +Simple test for the USB relay DLL +Just plain calling the C library, no fancy OOP stuff +Uses CTYPES + +For python 2.7, 3 +""" +import sys, os, time +import ctypes + +print("Running on Python v." + str(sys.version)) +print("%d-bit mode" % ({4:32, 8:64}[ctypes.sizeof(ctypes.c_void_p)]) ) + +# Fix the path below if the library is not in current dir. +libpath = "." + +if sys.version_info.major >= 3: + def charpToString(charp): + return str(ctypes.string_at(charp), 'ascii') + def stringToCharp(s) : + return bytes(s, "ascii") +else: + def charpToString(charp) : + return str(ctypes.string_at(charp)) + def stringToCharp(s) : + return bytes(s) #bytes(s, "ascii") + +libfile = {'nt': "usb_relay_device.dll", + 'posix': "usb_relay_device.so", + 'darwin':"usb_relay_device.dylib", + } [os.name] + +#?? MAC => os.name == "posix" and sys.platform == "darwin" + +devids = [] +hdev = None + +def exc(msg): return Exception(msg) + +def fail(msg) : raise exc(msg) + +class L: pass # Global object for the DLL +setattr(L, "dll", None) + +def loadLib(): + # Load the C DLL ... + if not L.dll : + print("Loading DLL: %s" % ('/'.join([libpath, libfile]))) + try: + L.dll = ctypes.CDLL( '/'.join([libpath, libfile]) ) + except OSError: + fail("Failed load lib") + else: + print("lib already open") + #print(L.dll) + +usb_relay_lib_funcs = [ + # TYpes: h=handle (pointer sized), p=pointer, i=int, e=error num (int), s=string + ("usb_relay_device_enumerate", 'h', None), + ("usb_relay_device_close", 'e', 'h'), + ("usb_relay_device_open_with_serial_number", 'h', 'si'), + ("usb_relay_device_get_num_relays", 'i', 'h'), + ("usb_relay_device_get_id_string", 's', 'h'), + ("usb_relay_device_next_dev", 'h', 'h'), + ("usb_relay_device_get_status_bitmap", 'i', 'h'), + ("usb_relay_device_open_one_relay_channel", 'e', 'hi'), + ("usb_relay_device_close_one_relay_channel", 'e', 'hi'), + ("usb_relay_device_close_all_relay_channel", 'e', None) + ] + + +def getLibFunctions(): + """ Get needed functions and configure types; call lib. init. + """ + assert L.dll + + #Get lib version (my extension, not in the original dll) + libver = L.dll.usb_relay_device_lib_version() + print("%s version: 0x%X" % (libfile,libver)) + + ret = L.dll.usb_relay_init() + if ret != 0 : fail("Failed lib init!") + + """ + Tweak imported C functions + This is required in 64-bit mode. Optional for 32-bit (pointer size=int size) + Functions that return and receive ints or void work without specifying types. + """ + ctypemap = { 'e': ctypes.c_int, 'h':ctypes.c_void_p, 'p': ctypes.c_void_p, + 'i': ctypes.c_int, 's': ctypes.c_char_p} + for x in usb_relay_lib_funcs : + fname, ret, param = x + try: + f = getattr(L.dll, fname) + except Exception: + fail("Missing lib export:" + fname) + + ps = [] + if param : + for p in param : + ps.append( ctypemap[p] ) + f.restype = ctypemap[ret] + f.argtypes = ps + setattr(L, fname, f) + +def openDevById(idstr): + #Open by known ID: + print("Opening " + idstr) + h = L.usb_relay_device_open_with_serial_number(stringToCharp(idstr), 5) + if not h: fail("Cannot open device with id="+idstr) + global numch + numch = L.usb_relay_device_get_num_relays(h) + if numch <= 0 or numch > 8 : fail("Bad number of channels, can be 1-8") + global hdev + hdev = h + print("Number of relays on device with ID=%s: %d" % (idstr, numch)) + +def closeDev(): + global hdev + L.usb_relay_device_close(hdev) + hdev = None + +def enumDevs(): + global devids + devids = [] + enuminfo = L.usb_relay_device_enumerate() + while enuminfo : + idstrp = L.usb_relay_device_get_id_string(enuminfo) + idstr = charpToString(idstrp) + print(idstr) + assert len(idstr) == 5 + if not idstr in devids : devids.append(idstr) + else : print("Warning! found duplicate ID=" + idstr) + enuminfo = L.usb_relay_device_next_dev(enuminfo) + + print("Found devices: %d" % len(devids)) + +def unloadLib(): + global hdev, L + if hdev: closeDev() + L.dll.usb_relay_exit() + L.dll = None + print("Lib closed") + +def testR2(): + """ Test one device with handle hdev, 1 or 2 channels """ + global numch, hdev + if numch <=0 or numch > 8: + fail("Bad number of channels on relay device!") + + ret = L.usb_relay_device_close_all_relay_channel(hdev) + if ret != 0: + fail("Failed OFF all!") + + st = L.usb_relay_device_get_status_bitmap(hdev) + if st < 0: fail("Bad status bitmask") + print("Relay num ch=%d state=%x" % (numch, st)) + + ret = L.usb_relay_device_close_one_relay_channel(hdev, numch+1) + if ret == 0: fail("Succeeded with bad channel num!") + ret = L.usb_relay_device_close_one_relay_channel(hdev, 0) + if ret == 0: fail("Succeeded with bad channel num!") + + # Play on/off + mask=0 + ret = L.usb_relay_device_open_one_relay_channel(hdev,1) + if ret != 0: fail("Failed R1 on!") + mask |= 0x1 + + if numch > 1: + time.sleep(1) + ret = L.usb_relay_device_open_one_relay_channel(hdev,2) + if ret != 0: failed("Failed R2 on!") + mask |= 0x2 + + #Note: Checking relay state after successful open/close is redundant, because the library does it. + # We check state here as a sanity test. + st = L.usb_relay_device_get_status_bitmap(hdev) + if st != mask: + fail("Bad state after relays on!") + + # Delays here are only for test, not really needed + time.sleep(1) + + ret = L.usb_relay_device_close_all_relay_channel(hdev) + if ret != 0: + fail("Failed OFF all!") + + st = L.usb_relay_device_get_status_bitmap(hdev) + if st != 0: + fail("Bad state after all off!") + + print("*** test R2 PASS ***") + +# main +def main(): + print("Test 2-ch relay") + loadLib() + getLibFunctions() + try: + print("Searching for compatible devices") + enumDevs() + if len(devids) != 0 : + # Test any 1st found dev . + print("Testing relay with ID=" + devids[0]) + openDevById(devids[0]) + testR2() + closeDev() + finally: + unloadLib() + +if __name__ == "__main__" : + main() -- 2.25.1