| gclib 2.0.7 Communications API for Galil controllers and PLCs |

gclib.py
Go to the documentation of this file.
1 '''! \file gclib.py
2 '''
3 """
4 Python wrapper for Galil gclib.
5 Contact softwaresupport@galil.com with questions, comments, and suggestions.
6 """
7
11 import platform #for distinguishing 'Windows', 'Linux', 'Darwin'
12 from ctypes import *
13
14 if platform.system() == 'Windows':
15 if '64 bit' in platform.python_compiler():
16 WinDLL(r'C:\Program Files (x86)\Galil\gclib\dll\x64\libcrypto-1_1-x64.dll')
17 WinDLL(r'C:\Program Files (x86)\Galil\gclib\dll\x64\libssl-1_1-x64.dll')
18 _gclib_path = r'C:\Program Files (x86)\Galil\gclib\dll\x64\gclib.dll'
19 _gclibo_path = r'C:\Program Files (x86)\Galil\gclib\dll\x64\gclibo.dll'
20 _gclib = WinDLL(_gclib_path)
21 _gclibo = WinDLL(_gclibo_path)
22 else:
23 WinDLL(r'C:\Program Files (x86)\Galil\gclib\dll\x86\libcrypto-1_1.dll')
24 WinDLL(r'C:\Program Files (x86)\Galil\gclib\dll\x86\libssl-1_1.dll')
25 _gclib_path = r'C:\Program Files (x86)\Galil\gclib\dll\x86\gclib.dll'
26 _gclibo_path = r'C:\Program Files (x86)\Galil\gclib\dll\x86\gclibo.dll'
27 _gclib = WinDLL(_gclib_path)
28 _gclibo = WinDLL(_gclibo_path)
29 #Reassign symbol name, Python doesn't like @ in function names
30 #gclib calls
31 setattr(_gclib, 'GArrayDownload', getattr(_gclib, '_GArrayDownload@20'))
32 setattr(_gclib, 'GArrayUpload', getattr(_gclib, '_GArrayUpload@28'))
33 setattr(_gclib, 'GClose', getattr(_gclib, '_GClose@4'))
34 setattr(_gclib, 'GCommand', getattr(_gclib, '_GCommand@20'))
35 setattr(_gclib, 'GFirmwareDownload', getattr(_gclib, '_GFirmwareDownload@8'))
36 setattr(_gclib, 'GInterrupt', getattr(_gclib, '_GInterrupt@8'))
37 setattr(_gclib, 'GMessage', getattr(_gclib, '_GMessage@12'))
38 setattr(_gclib, 'GOpen', getattr(_gclib, '_GOpen@8'))
39 setattr(_gclib, 'GProgramDownload', getattr(_gclib, '_GProgramDownload@12'))
40 setattr(_gclib, 'GProgramUpload', getattr(_gclib, '_GProgramUpload@12'))
41 #gclibo calls (open source component/convenience functions)
42 setattr(_gclibo, 'GAddresses', getattr(_gclibo, '_GAddresses@8'))
43 setattr(_gclibo, 'GArrayDownloadFile', getattr(_gclibo, '_GArrayDownloadFile@8'))
44 setattr(_gclibo, 'GArrayUploadFile', getattr(_gclibo, '_GArrayUploadFile@12'))
45 setattr(_gclibo, 'GAssign', getattr(_gclibo, '_GAssign@8'))
46 setattr(_gclibo, 'GError', getattr(_gclibo, '_GError@12'))
47 setattr(_gclibo, 'GInfo', getattr(_gclibo, '_GInfo@12'))
48 setattr(_gclibo, 'GIpRequests', getattr(_gclibo, '_GIpRequests@8'))
49 setattr(_gclibo, 'GMotionComplete', getattr(_gclibo, '_GMotionComplete@8'))
50 setattr(_gclibo, 'GProgramDownloadFile', getattr(_gclibo, '_GProgramDownloadFile@12'))
51 setattr(_gclibo, 'GSleep', getattr(_gclibo, '_GSleep@4'))
52 setattr(_gclibo, 'GProgramUploadFile', getattr(_gclibo, '_GProgramUploadFile@8'))
53 setattr(_gclibo, 'GTimeout', getattr(_gclibo, '_GTimeout@8'))
54 setattr(_gclibo, 'GVersion', getattr(_gclibo, '_GVersion@8'))
55 setattr(_gclibo, 'GSetupDownloadFile', getattr(_gclibo, '_GSetupDownloadFile@20'))
56 setattr(_gclibo, 'GServerStatus', getattr(_gclibo, '_GServerStatus@8'))
57 setattr(_gclibo, 'GSetServer', getattr(_gclibo, '_GSetServer@4'))
58 setattr(_gclibo, 'GListServers', getattr(_gclibo, '_GListServers@8'))
59 setattr(_gclibo, 'GPublishServer', getattr(_gclibo, '_GPublishServer@12'))
60 setattr(_gclibo, 'GRemoteConnections', getattr(_gclibo, '_GRemoteConnections@8'))
61
62 elif platform.system() == 'Linux':
63 cdll.LoadLibrary("libgclib.so.2")
64 _gclib = CDLL("libgclib.so.2")
65 cdll.LoadLibrary("libgclibo.so.2")
66 _gclibo = CDLL("libgclibo.so.2")
67
68 elif platform.system() == 'Darwin': #OSX
69 _gclib_path = '/Applications/gclib/dylib/gclib.0.dylib'
70 _gclibo_path = '/Applications/gclib/dylib/gclibo.0.dylib'
71 cdll.LoadLibrary(_gclib_path)
72 _gclib = CDLL(_gclib_path)
73 cdll.LoadLibrary(_gclibo_path)
74 _gclibo = CDLL(_gclibo_path)
75
76
77
78 # Python "typedefs"
79 _GReturn = c_int #type for a return code
80 _GCon = c_void_p #type for a Galil connection handle
81 _GCon_ptr = POINTER(_GCon) #used for argtypes declaration
82 _GSize = c_ulong #type for a Galil size variable
83 _GSize_ptr = POINTER(_GSize) #used for argtypes declaration
84 _GCStringIn = c_char_p #char*. In C it's const.
85 _GCStringOut = c_char_p #char*
86 _GOption = c_int #type for option variables, e.g. GArrayDownload
87 _GStatus = c_ubyte #type for interrupt status bytes
88 _GStatus_ptr = POINTER(_GStatus) #used for argtypes declaration
89
90 #Define arguments and result type (if not C int type)
91 #gclib calls
92 _gclib.GArrayDownload.argtypes = [_GCon, _GCStringIn, _GOption, _GOption, _GCStringIn]
93 _gclib.GArrayUpload.argtypes = [_GCon, _GCStringIn, _GOption, _GOption, _GOption, _GCStringOut, _GSize]
94 _gclib.GClose.argtypes = [_GCon]
95 _gclib.GCommand.argtypes = [_GCon, _GCStringIn, _GCStringOut, _GSize, _GSize_ptr]
96 _gclib.GFirmwareDownload.argtypes = [_GCon, _GCStringIn]
97 _gclib.GInterrupt.argtypes = [_GCon, _GStatus_ptr]
98 _gclib.GMessage.argtypes = [_GCon, _GCStringOut, _GSize]
99 _gclib.GOpen.argtypes = [_GCStringIn, _GCon_ptr]
100 _gclib.GProgramDownload.argtypes = [_GCon, _GCStringIn, _GCStringIn]
101 _gclib.GProgramUpload.argtypes = [_GCon, _GCStringOut, _GSize]
102 #gclibo calls (open source component/convenience functions)
103 _gclibo.GAddresses.argtypes = [_GCStringOut, _GSize]
104 _gclibo.GArrayDownloadFile.argtypes = [_GCon, _GCStringIn]
105 _gclibo.GArrayUploadFile.argtypes = [_GCon, _GCStringIn, _GCStringIn]
106 _gclibo.GAssign.argtypes = [_GCStringIn, _GCStringIn]
107 _gclibo.GError.argtypes = [_GReturn, _GCStringOut, _GSize]
108 _gclibo.GError.restype = None
109 _gclibo.GError.argtypes = [_GCon, _GCStringOut, _GSize]
110 _gclibo.GIpRequests.argtypes = [_GCStringOut, _GSize]
111 _gclibo.GMotionComplete.argtypes = [_GCon, _GCStringIn]
112 _gclibo.GProgramDownloadFile.argtypes = [_GCon, _GCStringIn, _GCStringIn]
113 _gclibo.GSleep.argtypes = [c_uint]
114 _gclibo.GSleep.restype = None
115 _gclibo.GProgramUploadFile.argtypes = [_GCon, _GCStringIn]
116 _gclibo.GTimeout.argtypes = [_GCon, c_int]
117 _gclibo.GVersion.argtypes = [_GCStringOut, _GSize]
118 _gclibo.GServerStatus.argtypes = [_GCStringOut, _GSize]
119 _gclibo.GSetServer.argtypes = [_GCStringIn]
120 _gclibo.GListServers.argtypes = [_GCStringOut, _GSize]
121 _gclibo.GPublishServer.argtypes = [_GCStringIn, _GOption, _GOption]
122 _gclibo.GRemoteConnections.argtypes = [_GCStringOut, _GSize]
123 _gclibo.GSetupDownloadFile.argtypes = [_GCon, _GCStringIn, _GOption, _GCStringOut, _GSize]
124
125 #Set up some constants
126 _enc = "ASCII" #byte encoding for going between python strings and c strings.
127 _buf_size = 500000 #size of response buffer. Big enough to fit entire 4000 program via UL/LS, or 24000 elements of array data.
128 _error_buf = create_string_buffer(128) #buffer for retrieving error code descriptions.
129
130 def _rc(return_code):
131 """Checks return codes from gclib and raises a python error if result is exceptional."""
132 if return_code != 0:
133 _gclibo.GError(return_code, _error_buf, 128) #Get the library's error description
134 raise GclibError(str(_error_buf.value.decode(_enc)))
135 return
136
137 class GclibError(Exception):
138 """Error class for non-zero gclib return codes."""
139 pass
140
141 class py:
142 """Represents a single Python connection to a Galil Controller or PLC."""
143
144 def __init__(self):
145 """Constructor for the Connection class. Initializes gclib's handle and read buffer."""
146 self._gcon_gcon = _GCon(0) #handle to connection
147 self._buf_buf = create_string_buffer(_buf_size)
148 self._timeout_timeout = 5000
149 return
150
151 def __del__(self):
152 """Destructor for the Connection class. Ensures close gets called to release Galil resource (Sockets, Kernel Driver, Com Port, etc)."""
153 self.GCloseGClose()
154 return
155
156 def _cc(self):
157 """Checks if connection is established, throws error if not."""
158 if self._gcon_gcon.value == None:
159 _rc(-1201) #G_CONNECTION_NOT_ESTABLISHED
160
161 def GOpen(self, address):
162 """
163 Opens a connection a galil controller.
164 See the gclib docs for address string formatting.
165 """
166 c_address = _GCStringIn(address.encode(_enc))
167 _rc(_gclib.GOpen(c_address, byref(self._gcon_gcon)))
168 return
169
170
171 def GClose(self):
172 """
173 Closes a connection to a Galil Controller.
174 """
175 if self._gcon_gcon.value != None:
176 _rc(_gclib.GClose(self._gcon_gcon))
177 self._gcon_gcon = _GCon(0)
178 return
179
180
181 def GCommand(self, command):
182 """
183 Performs a command-and-response transaction on the connection.
184 Trims the response.
185 """
186 self._cc_cc()
187 c_command = _GCStringIn(command.encode(_enc))
188 _rc(_gclib.GCommand(self._gcon_gcon, c_command, self._buf_buf, _buf_size, None))
189 response = str(self._buf_buf.value.decode(_enc))
190 return response[:-3].strip() # trim trailing /r/n: and leading space
191
192
193 def GSleep(self, val):
194 """
195 Provides a blocking sleep call which can be useful for timing-based chores.
196 """
197 _gclibo.GSleep(val)
198 return
199
200
201 def GVersion(self):
202 """
203 Provides the gclib version number. Please include the output of this function on all support cases.
204 """
205 _rc(_gclibo.GVersion(self._buf_buf, _buf_size))
206 return "py." + str(self._buf_buf.value.decode(_enc))
207
208 def GServerStatus(self):
209 _rc(_gclibo.GServerStatus(self._buf_buf, _buf_size))
210 return str(self._buf_buf.value.decode(_enc))
211
212 def GSetServer(self, server_name):
213 c_server_name = _GCStringIn(server_name.encode(_enc))
214 _rc(_gclibo.GSetServer(c_server_name))
215 return
216
217 def GListServers(self):
218 _rc(_gclibo.GListServers(self._buf_buf, _buf_size))
219 return str(self._buf_buf.value.decode(_enc))
220
221 def GPublishServer(self, server_name, publish, save):
222 c_server_name = _GCStringIn(server_name.encode(_enc))
223 _rc(_gclibo.GPublishServer(c_server_name, publish, save))
224 return
225
226 def GRemoteConnections(self):
227 _rc(_gclibo.GRemoteConnections(self._buf_buf, _buf_size))
228 return str(self._buf_buf.value.decode(_enc))
229
230 def GInfo(self):
231 """
232 Provides a useful connection string. Please include the output of this function on all support cases.
233 """
234 _rc(_gclibo.GInfo(self._gcon_gcon, self._buf_buf, _buf_size))
235 return str(self._buf_buf.value.decode(_enc))
236
237
238 def GIpRequests(self):
239 """
240 Provides a dictionary of all Galil controllers requesting IP addresses via BOOT-P or DHCP.
241
242 Returns a dictionary mapping 'model-serial' --> 'mac address'
243 e.g. {'DMC4000-783': '00:50:4c:20:03:0f', 'DMC4103-9998': '00:50:4c:38:27:0e'}
244
245 Linux/OS X users must be root to use GIpRequests() and have UDP access to bind and listen on port 67.
246 """
247 _rc(_gclibo.GIpRequests(self._buf_buf, _buf_size)) #get the c string from gclib
248 ip_req_dict = {}
249 for line in str(self._buf_buf.value.decode(_enc)).splitlines():
250 line = line.replace(' ', '') #trim spaces throughout
251 if (line == ""): continue
252 fields = line.split(',')
253 #fields go [model, serial number, mac]
254 ip_req_dict[fields[0] + '-' + fields[1]] = fields[2] # e.g. DMC4000-783 maps to its MAC addr.
255 return ip_req_dict
256
257
258 def GAssign(self, ip, mac):
259 """
260 Assigns IP address over the Ethernet to a controller at a given MAC address.
261 Linux/OS X users must be root to use GAssign() and have UDP access to send on port 68.
262 """
263 c_ip = _GCStringIn(ip.encode(_enc))
264 c_mac = _GCStringIn(mac.encode(_enc))
265 _rc(_gclibo.GAssign(c_ip, c_mac))
266 return
267
268
269 def GAddresses(self):
270 """
271 Provides a dictionary of all available connection addresses.
272
273 Returns a dictionary mapping 'address' -> 'revision reports', where possible
274 e.g. {}
275 """
276 _rc(_gclibo.GAddresses(self._buf_buf, _buf_size))
277 addr_dict = {}
278 for line in str(self._buf_buf.value.decode(_enc)).splitlines():
279 fields = line.split(',')
280 if len(fields) >= 2:
281 addr_dict[fields[0]] = fields[1]
282 else:
283 addr_dict[fields[0]] = ''
284
285 return addr_dict
286
287
288 def GProgramDownload(self, program, preprocessor=""):
289 """
290 Downloads a program to the controller's program buffer.
291 See the gclib docs for preprocessor options.
292 """
293 self._cc_cc()
294 c_prog = _GCStringIn(program.encode(_enc))
295 c_pre = _GCStringIn(preprocessor.encode(_enc))
296 _rc(_gclib.GProgramDownload(self._gcon_gcon, c_prog, c_pre))
297 return
298
299
300 def GProgramUpload(self):
301 """
302 Uploads a program from the controller's program buffer.
303 """
304 self._cc_cc()
305 _rc(_gclib.GProgramUpload(self._gcon_gcon, self._buf_buf, _buf_size))
306 return str(self._buf_buf.value.decode(_enc))
307
308
309 def GProgramDownloadFile(self, file_path, preprocessor=""):
310 """
311 Program download from file.
312 See the gclib docs for preprocessor options.
313 """
314 self._cc_cc()
315 c_path = _GCStringIn(file_path.encode(_enc))
316 c_pre = _GCStringIn(preprocessor.encode(_enc))
317 _rc(_gclibo.GProgramDownloadFile(self._gcon_gcon, c_path, c_pre))
318 return
319
320 def GProgramUploadFile(self, file_path):
321 """
322 Program upload to file.
323 """
324 self._cc_cc()
325 c_path = _GCStringIn(file_path.encode(_enc))
326 _rc(_gclibo.GProgramUploadFile(self._gcon_gcon, c_path))
327 return
328
329 def GArrayDownload(self, name, first, last, array_data):
330 """
331 Downloads array data to a pre-dimensioned array in the controller's array table.
332 array_data should be a list of values (e.g. int or float)
333 """
334 self._cc_cc()
335 c_name = _GCStringIn(name.encode(_enc))
336 array_string = ""
337 for val in array_data:
338 array_string += str(val) + ","
339 c_data = _GCStringIn(array_string[:-1].encode(_enc)) #trim trailing command
340 _rc(_gclib.GArrayDownload(self._gcon_gcon, c_name, first, last, c_data))
341 return
342
343
344 def GArrayUploadFile(self, file_path, names = []):
345 """
346 Uploads the entire controller array table or a subset and saves the data as a csv file specified by file_path.
347 names is optional and should be a list of array names on the controller.
348 """
349 self._cc_cc()
350 c_path = _GCStringIn(file_path.encode(_enc))
351 names_string = ''
352 c_names = _GCStringIn(''.encode(_enc)) #in case empty list provided
353 for name in names:
354 names_string += name + ' '
355
356 c_names = _GCStringIn(names_string[:-1].encode(_enc)) #trim trailing space
357 _rc(_gclibo.GArrayUploadFile(self._gcon_gcon, c_path, c_names))
358 return
359
360
361 def GArrayDownloadFile(self, file_path):
362 """
363 Downloads a csv file containing array data at file_path.
364 """
365 self._cc_cc()
366 c_path = _GCStringIn(file_path.encode(_enc))
367 _rc(_gclibo.GArrayDownloadFile(self._gcon_gcon, c_path))
368 return
369
370
371 def GArrayUpload(self, name, first, last):
372 """
373 Uploads array data from the controller's array table.
374 """
375 self._cc_cc()
376 c_name = _GCStringIn(name.encode(_enc))
377 _rc(_gclib.GArrayUpload(self._gcon_gcon, c_name, first, last, 1, self._buf_buf, _buf_size)) #1 is comma delimiter
378 string_list = str(self._buf_buf.value.decode(_enc)).split(',')
379 float_list = []
380 for s in string_list:
381 float_list.append(float(s))
382 return float_list
383
384
385 def GTimeout(self, timeout):
386 """
387 Set the library timeout. Set to -1 to use the intitial library timeout, as specified in GOpen.
388 """
389 self._cc_cc()
390 _rc(_gclibo.GTimeout(self._gcon_gcon, timeout))
391 self._timeout_timeout = timeout
392 return
393
394
395 @property
396 def timeout(self):
397 """
398 Convenience property read access to timeout value. If -1, gclib uses the initial library timeout, as specified in GOpen.
399 """
400 return self._timeout_timeout
401
402 @timeout.setter
403 def timeout(self, timeout):
404 """
405 Convenience property write access to timeout value. Set to -1 to use the initial library timeout, as specified in GOpen.
406 """
407 self.GTimeoutGTimeout(timeout)
408 return
409
410
411 def GFirmwareDownload(self, file_path):
412 """
413 Upgrade firmware.
414 """
415 self._cc_cc()
416 c_path = _GCStringIn(file_path.encode(_enc))
417 _rc(_gclib.GFirmwareDownload(self._gcon_gcon, c_path))
418 return
419
420
421 def GMessage(self):
422 """
423 Provides access to unsolicited messages from the controller.
424 """
425 self._cc_cc()
426 _rc(_gclib.GMessage(self._gcon_gcon, self._buf_buf, _buf_size))
427 return str(self._buf_buf.value.decode(_enc))
428
429
430 def GMotionComplete(self, axes):
431 """
432 Blocking call that returns once all axes specified have completed their motion.
433 """
434 self._cc_cc()
435 c_axes = _GCStringIn(axes.encode(_enc))
436 _rc(_gclibo.GMotionComplete(self._gcon_gcon, c_axes))
437 return
438
439 def GInterrupt(self):
440 """
441 Provides access to PCI and UDP interrupts from the controller.
442 """
443 self._cc_cc()
444 status = _GStatus(0)
445 _rc(_gclib.GInterrupt(self._gcon_gcon, byref(status)))
446 return status.value
447
448 def GSetupDownloadFile(self, file_path, options):
449 """
450 Downloads specified sectors from a Galil compressed backup (gcb) file to a controller.
451
452 Returns a dictionary with the controller information stored in the gcb file.
453 If options is specified as 0, an additional "options" key will be in the dictionary indicating the info sectors available in the gcb
454 """
455 self._cc_cc()
456 c_path = _GCStringIn(file_path.encode(_enc))
457
458 rc = _gclibo.GSetupDownloadFile(self._gcon_gcon, c_path, options, self._buf_buf, _buf_size)
459 if (options != 0):
460 _rc(rc)
461
462 info_dict = {}
463 for line in str(self._buf_buf.value.decode(_enc)).split("\"\n"):
464 fields = line.split(',',1)
465
466 if (fields[0] == ""): continue
467 elif len(fields) >= 2:
468 info_dict[fields[0].strip("\"\'")] = fields[1].strip("\"\'")
469 else:
470 info_dict[fields[0].strip("\"\'")] = ''
471
472 if (options == 0):
473 info_dict["options"] = rc
474
475 return info_dict
gclib.GclibError
Definition: gclib.py:137
gclib.py.GInterrupt
def GInterrupt(self)
Definition: gclib.py:439
gclib.py.GFirmwareDownload
def GFirmwareDownload(self, file_path)
Definition: gclib.py:411
gclib.py.GMotionComplete
def GMotionComplete(self, axes)
Definition: gclib.py:430
gclib.py.GProgramDownload
def GProgramDownload(self, program, preprocessor="")
Definition: gclib.py:288
gclib.py.GProgramDownloadFile
def GProgramDownloadFile(self, file_path, preprocessor="")
Definition: gclib.py:309
gclib.py.GTimeout
def GTimeout(self, timeout)
Definition: gclib.py:385
gclib.py.GOpen
def GOpen(self, address)
Definition: gclib.py:161
gclib.py.GArrayUploadFile
def GArrayUploadFile(self, file_path, names=[])
Definition: gclib.py:344
gclib.py.timeout
def timeout(self)
Definition: gclib.py:396
gclib.py.GArrayDownloadFile
def GArrayDownloadFile(self, file_path)
Definition: gclib.py:361
gclib.py.GCommand
def GCommand(self, command)
Definition: gclib.py:181
gclib.py.__del__
def __del__(self)
Definition: gclib.py:151
gclib.py.GAddresses
def GAddresses(self)
Definition: gclib.py:269
gclib.py.GProgramUploadFile
def GProgramUploadFile(self, file_path)
Definition: gclib.py:320
gclib.py.GArrayUpload
def GArrayUpload(self, name, first, last)
Definition: gclib.py:371
gclib.py.GProgramUpload
def GProgramUpload(self)
Definition: gclib.py:300
gclib.py.GArrayDownload
def GArrayDownload(self, name, first, last, array_data)
Definition: gclib.py:329
gclib.py.GMessage
def GMessage(self)
Definition: gclib.py:421
gclib.py.GSleep
def GSleep(self, val)
Definition: gclib.py:193
gclib.py.GSetupDownloadFile
def GSetupDownloadFile(self, file_path, options)
Definition: gclib.py:448
gclib.py.GVersion
def GVersion(self)
Definition: gclib.py:201
gclib.py.GAssign
def GAssign(self, ip, mac)
Definition: gclib.py:258
gclib.py.GClose
def GClose(self)
Definition: gclib.py:171
gclib.py.__init__
def __init__(self)
Definition: gclib.py:144
gclib.py.GInfo
def GInfo(self)
Definition: gclib.py:230
gclib.py.GIpRequests
def GIpRequests(self)
Definition: gclib.py:238
gclib.py._timeout
_timeout
Definition: gclib.py:148
gclib.py._cc
def _cc(self)
Definition: gclib.py:156
gclib.py._gcon
_gcon
Definition: gclib.py:146
gclib.py._buf
_buf
Definition: gclib.py:147