Added Python test, moved the cmd example script to /Test
[usb-relay-hid.git] / Test / test2m.py
CommitLineData
9769cad6 1"""
2Simple test for the USB relay DLL
3Just plain calling the C library, no fancy OOP stuff
4Uses CTYPES
5
6For python 2.7, 3
7"""
8import sys, os, time
9import ctypes
10
11print("Running on Python v." + str(sys.version))
12print("%d-bit mode" % ({4:32, 8:64}[ctypes.sizeof(ctypes.c_void_p)]) )
13
14# Fix the path below if the library is not in current dir.
15libpath = "."
16
17if sys.version_info.major >= 3:
18 def charpToString(charp):
19 return str(ctypes.string_at(charp), 'ascii')
20 def stringToCharp(s) :
21 return bytes(s, "ascii")
22else:
23 def charpToString(charp) :
24 return str(ctypes.string_at(charp))
25 def stringToCharp(s) :
26 return bytes(s) #bytes(s, "ascii")
27
28libfile = {'nt': "usb_relay_device.dll",
29 'posix': "usb_relay_device.so",
30 'darwin':"usb_relay_device.dylib",
31 } [os.name]
32
33#?? MAC => os.name == "posix" and sys.platform == "darwin"
34
35devids = []
36hdev = None
37
38def exc(msg): return Exception(msg)
39
40def fail(msg) : raise exc(msg)
41
42class L: pass # Global object for the DLL
43setattr(L, "dll", None)
44
45def loadLib():
46 # Load the C DLL ...
47 if not L.dll :
48 print("Loading DLL: %s" % ('/'.join([libpath, libfile])))
49 try:
50 L.dll = ctypes.CDLL( '/'.join([libpath, libfile]) )
51 except OSError:
52 fail("Failed load lib")
53 else:
54 print("lib already open")
55 #print(L.dll)
56
57usb_relay_lib_funcs = [
58 # TYpes: h=handle (pointer sized), p=pointer, i=int, e=error num (int), s=string
59 ("usb_relay_device_enumerate", 'h', None),
60 ("usb_relay_device_close", 'e', 'h'),
61 ("usb_relay_device_open_with_serial_number", 'h', 'si'),
62 ("usb_relay_device_get_num_relays", 'i', 'h'),
63 ("usb_relay_device_get_id_string", 's', 'h'),
64 ("usb_relay_device_next_dev", 'h', 'h'),
65 ("usb_relay_device_get_status_bitmap", 'i', 'h'),
66 ("usb_relay_device_open_one_relay_channel", 'e', 'hi'),
67 ("usb_relay_device_close_one_relay_channel", 'e', 'hi'),
68 ("usb_relay_device_close_all_relay_channel", 'e', None)
69 ]
70
71
72def getLibFunctions():
73 """ Get needed functions and configure types; call lib. init.
74 """
75 assert L.dll
76
77 #Get lib version (my extension, not in the original dll)
78 libver = L.dll.usb_relay_device_lib_version()
79 print("%s version: 0x%X" % (libfile,libver))
80
81 ret = L.dll.usb_relay_init()
82 if ret != 0 : fail("Failed lib init!")
83
84 """
85 Tweak imported C functions
86 This is required in 64-bit mode. Optional for 32-bit (pointer size=int size)
87 Functions that return and receive ints or void work without specifying types.
88 """
89 ctypemap = { 'e': ctypes.c_int, 'h':ctypes.c_void_p, 'p': ctypes.c_void_p,
90 'i': ctypes.c_int, 's': ctypes.c_char_p}
91 for x in usb_relay_lib_funcs :
92 fname, ret, param = x
93 try:
94 f = getattr(L.dll, fname)
95 except Exception:
96 fail("Missing lib export:" + fname)
97
98 ps = []
99 if param :
100 for p in param :
101 ps.append( ctypemap[p] )
102 f.restype = ctypemap[ret]
103 f.argtypes = ps
104 setattr(L, fname, f)
105
106def openDevById(idstr):
107 #Open by known ID:
108 print("Opening " + idstr)
109 h = L.usb_relay_device_open_with_serial_number(stringToCharp(idstr), 5)
110 if not h: fail("Cannot open device with id="+idstr)
111 global numch
112 numch = L.usb_relay_device_get_num_relays(h)
113 if numch <= 0 or numch > 8 : fail("Bad number of channels, can be 1-8")
114 global hdev
115 hdev = h
116 print("Number of relays on device with ID=%s: %d" % (idstr, numch))
117
118def closeDev():
119 global hdev
120 L.usb_relay_device_close(hdev)
121 hdev = None
122
123def enumDevs():
124 global devids
125 devids = []
126 enuminfo = L.usb_relay_device_enumerate()
127 while enuminfo :
128 idstrp = L.usb_relay_device_get_id_string(enuminfo)
129 idstr = charpToString(idstrp)
130 print(idstr)
131 assert len(idstr) == 5
132 if not idstr in devids : devids.append(idstr)
133 else : print("Warning! found duplicate ID=" + idstr)
134 enuminfo = L.usb_relay_device_next_dev(enuminfo)
135
136 print("Found devices: %d" % len(devids))
137
138def unloadLib():
139 global hdev, L
140 if hdev: closeDev()
141 L.dll.usb_relay_exit()
142 L.dll = None
143 print("Lib closed")
144
145def testR2():
146 """ Test one device with handle hdev, 1 or 2 channels """
147 global numch, hdev
148 if numch <=0 or numch > 8:
149 fail("Bad number of channels on relay device!")
150
151 ret = L.usb_relay_device_close_all_relay_channel(hdev)
152 if ret != 0:
153 fail("Failed OFF all!")
154
155 st = L.usb_relay_device_get_status_bitmap(hdev)
156 if st < 0: fail("Bad status bitmask")
157 print("Relay num ch=%d state=%x" % (numch, st))
158
159 ret = L.usb_relay_device_close_one_relay_channel(hdev, numch+1)
160 if ret == 0: fail("Succeeded with bad channel num!")
161 ret = L.usb_relay_device_close_one_relay_channel(hdev, 0)
162 if ret == 0: fail("Succeeded with bad channel num!")
163
164 # Play on/off
165 mask=0
166 ret = L.usb_relay_device_open_one_relay_channel(hdev,1)
167 if ret != 0: fail("Failed R1 on!")
168 mask |= 0x1
169
170 if numch > 1:
171 time.sleep(1)
172 ret = L.usb_relay_device_open_one_relay_channel(hdev,2)
173 if ret != 0: failed("Failed R2 on!")
174 mask |= 0x2
175
176 #Note: Checking relay state after successful open/close is redundant, because the library does it.
177 # We check state here as a sanity test.
178 st = L.usb_relay_device_get_status_bitmap(hdev)
179 if st != mask:
180 fail("Bad state after relays on!")
181
182 # Delays here are only for test, not really needed
183 time.sleep(1)
184
185 ret = L.usb_relay_device_close_all_relay_channel(hdev)
186 if ret != 0:
187 fail("Failed OFF all!")
188
189 st = L.usb_relay_device_get_status_bitmap(hdev)
190 if st != 0:
191 fail("Bad state after all off!")
192
193 print("*** test R2 PASS ***")
194
195# main
196def main():
197 print("Test 2-ch relay")
198 loadLib()
199 getLibFunctions()
200 try:
201 print("Searching for compatible devices")
202 enumDevs()
203 if len(devids) != 0 :
204 # Test any 1st found dev .
205 print("Testing relay with ID=" + devids[0])
206 openDevById(devids[0])
207 testR2()
208 closeDev()
209 finally:
210 unloadLib()
211
212if __name__ == "__main__" :
213 main()