gclib 2.0.9
Communications API for Galil controllers and PLCs
 
Loading...
Searching...
No Matches
gcl_galil.cpp
Go to the documentation of this file.
1
4#include "gcl_galil.h"
5using namespace std;
6
7
8void ec(GReturn rc)
9{
10
11 switch (rc)
12 {
13 case G_NO_ERROR:
14 return;
15
16 case G_TIMEOUT:
17 throw string("1010 TIMEOUT ERROR. Galil::command() took longer than timeout to return\n");
18 break;
19
20 case G_OPEN_ERROR:
21 throw string("5002 OPEN ERROR. Galil::Galil() failed to open device\n");
22 break;
23
25 throw string("7020 INVALID COMMAND ERROR. DL, ED, and QD are not allowed from Galil::command()\n");
26 break;
27
29 throw string("6150 WRONG BUS ERROR. Galil::record(\"DR\") not supported on RS-232. Use Ethernet or Galil::record(\"QR\")\n");
30 break;
31
33 throw string("6130 WRONG BUS ERROR. Galil::firmwareDownloadFile() isn't allowed via Ethernet. Use RS-232\n"); //21x3 etc.
34 break;
35
37 throw string("7060 INVALID CHARACTER ERROR. Galil::programDownload() can't download program with backslash \\ character. Use {^92} in MG commands\n");
38 break;
39
41 throw string("7061 INVALID LENGTH ERROR. Galil::programDownload() can't compress\n");
42 break;
43
45 throw string("2010 COMMAND ERROR. Galil::command() got ? instead of : response.\n");
46 break;
47
48 case G_BAD_FILE:
49 throw string("4000 FILE ERROR. Galil::Galil() failed to open file\n");
50 break;
51
53 throw string("6000 WRONG BUG ERROR. Function isn't allowed on this bus\n");
54 break;
55
56
57 /*
58 case G_DATA_RECORD_ERROR:
59 case G_BAD_ADDRESS:
60 case G_BAD_LOST_DATA:
61 case G_BAD_VALUE_RANGE:
62 case G_BAD_FULL_MEMORY:
63 case G_ARRAY_NOT_DIMENSIONED:
64 case G_GCLIB_ERROR:
65 case G_GCLIB_UTILITY_ERROR:
66 case G_INVALID_PREPROCESSOR_OPTIONS:
67 */
68
69 default: //couldn't find error map, make a gcl-like error from gclib error code
70 {
71 char buf[G_SMALL_BUFFER];
72 GError(rc, buf, sizeof(buf)); //get the error message
73 throw (to_string(rc) + " GCLIB ERROR. " + string(buf) + '\n');
74 }
75
76 }//switch
77}
78
80string AddressConvert(const string& gcl_address)
81{
82 if (gcl_address.size() == 0) //this implementation does not present the user with a connections dialog if a nullstring is passed.
83 throw string("5005 OPEN ERROR. Null string specified in Galil::Galil()\n");
84
85 if (gcl_address.find("OFFLINE") != string::npos)
86 throw string("5001 OPEN ERROR. OFFLINE specified to Galil::Galil()\n");
87
89 size_t start = 0;
90 size_t i;
91 for (i = 0; i < gcl_address.size(); i++) //split into tokens
92 {
93 if (gcl_address[i] == ' ')
94 {
95 if (start < i) //if not zero length
96 args.push_back(gcl_address.substr(start, i - start));
97
98 start = i + 1; //jump over space
99 }
100 }
101 if (start < i) //one token still remaining
102 args.push_back(gcl_address.substr(start, i - start));
103
104 bool ei = true; //bools to remember if data streams should be subscribed to, gcl subscribes by default
105 bool mg = true;
106 bool dr = true;
107 string address;
108 args.push_back(""); //allow safe indexing one past the end of the tokens list
109 for (i = 0; i < args.size() - 1; i++)
110 {
111 if (args[i] == "-p1") address.append("--p1 " + args[++i] + " ");
112 else if (args[i] == "-p2") address.append("--p2 " + args[++i] + " ");
113 else if (args[i] == "-udp") address.append("--command UDP "); //TCP is default in gclib
114 else if ((args[i] == "-ei") && (args[++i] == "0")) ei = false;
115 else if ((args[i] == "-mg") && (args[++i] == "0")) mg = false;
116 else if ((args[i] == "-dr") && (args[++i] == "0")) dr = false;
117 else if (args[i] == "-t") address.append("-t " + args[++i] + " ");
118 else if (args[i] == "-s")
119 {
120 address.append("-s NONE ");
121 ei = false;
122 mg = false;
123 dr = false;
124 }
125 else if (args[i] == "-d") ++i; //Debug not yet supported
126 else if (args[i] == "-l") ++i; //Long-timeout not used
127 else if (args[i].find("COM") != string::npos)
128 {
129 address.append(args[i] + " --baud " + args[i + 1] + " "); //COM1 --baud 115200
130 i++;// jump over baud rate on next pass
131 }
132 else address.append(args[i] + " "); //keep unrecognized tokens, e.g. 192.168.0.123
133 }
134
135 if (ei) address.append("-s EI ");
136 if (mg) address.append("-s MG ");
137 if (dr) address.append("-s DR ");
138
139 address.append("-d "); //add direct-connect switch
140
141 return address;
142}
143
144string Galil::libraryVersion()
145{
146 char buf[G_SMALL_BUFFER]; //function is static, so can't access GalilPrivate members
147 ec(GVersion(buf, sizeof(buf)));
148 return "Galil2.dll wrapper, gclib " + string(buf);
149}
150
151vector<string> Galil::addresses()
152{
153 vector<string> addresses; //this is the return collection
154 char buf[1024];
155 ec(GAddresses(buf, sizeof(buf)));
156 //buf now holds the list, but the gcl only holds the first cell
157
158 short commas = 0; //counter for comma delimiters
159 string address; //temp buffer for holding chars
160 size_t len = strlen(buf); //don't call strlen every iteration
161 for (size_t i = 0; i < len; i++)
162 {
163 if (buf[i] == '\n') //end of line
164 {
165 addresses.push_back(address);
166 address.clear();
167 commas = 0; //start counting commas from zero
168 continue;
169 }
170
171 if (commas) //already saw first comma, keep looking for end of line
172 continue;
173
174 if (buf[i] == ',')
175 {
176 commas++; //count it
177 continue;
178 }
179
180 address.push_back(buf[i]); //keep the char
181 }//for
182
183 return addresses;
184}
185
186Galil::Galil(std::string address)
187{
188 GCon g;
189 timeout_ms = 500; //default value for gcl
190 ec(GOpen(AddressConvert(address).c_str(), &g));
191 d = new GalilPrivate(this, g);
192 d->InitializeDataRecord();
193}
194
195Galil::~Galil()
196{
197 GClose(d->g); //close the connection in gclib
198 delete d; //free memory
199}
200
201string Galil::connection()
202{
203 ec(GInfo(d->g, d->tbuf, sizeof(d->tbuf)));
204 return string(d->tbuf);
205}
206
207string Galil::command(const std::string& command, const std::string& terminator, const std::string& ack, bool trim)
208{
209 /*
210 * Note: This wrapper ignores terminator and ack. GCommand does not require them to operate.
211 * If terminator and/or ack are desired, this function can be implemented with GRead and GWrite.
212 * Please contact softwaresupport@galil.com with questions/concerns.
213 */
214 ec(GTimeout(d->g, (short)timeout_ms)); //obey timeout_ms setting
216 char* response;
217 if (trim)
218 ec(GCmdT(d->g, command.c_str(), d->tbuf, sizeof(d->tbuf), &response));
219 else
220 {
221 ec(GCommand(d->g, command.c_str(), d->tbuf, sizeof(d->tbuf), &bytes_read));
222 response = d->tbuf;
223 }
224 ec(GTimeout(d->g, -1)); //replace timeout
225
226 return string(response);
227}
228
229double Galil::commandValue(const std::string& command)
230{
231 double value;
232 ec(GTimeout(d->g, (short)timeout_ms));
233 ec(GCmdD(d->g, command.c_str(), &value));
234 ec(GTimeout(d->g, -1));
235 return value;
236}
237
238string Galil::message(int timeout_ms)
239{
240 /*
241 * From GCL documentation, http://www.galil.com/sw/pub/all/doc/galiltools/html/library.html#message
242 * "If a zero timeout is specified, no errors will be thrown; message() will simply return the waiting queue (even if it is empty, "").
243 * A -1 timeout will cause message() to block until a message is received."
244 */
246 short t = 5000; //nominal timeout, to be used if -1 is specified
247 if (timeout_ms >= 0)
248 t = (short) timeout_ms;
249
250 ec(GTimeout(d->g, t));
251
252 do
253 {
254 rc = GMessage(d->g, d->tbuf, sizeof(d->tbuf));
255 } while(timeout_ms == -1 && rc == G_TIMEOUT);
256
257 ec(GTimeout(d->g, -1));
258
260 return "";
261
262 ec(rc); //check the other possible return codes
263 return string(d->tbuf);
264
265}
266
267int Galil::interrupt(int timeout_ms)
268{
269 ec(GTimeout(d->g, (short)timeout_ms));
271 ec(GInterrupt(d->g, &status));
272 ec(GTimeout(d->g, -1));
273 return (int)status;
274}
275
276
277string Galil::programUpload()
278{
279 ec(GTimeout(d->g, (short)timeout_ms));
280 ec(GProgramUpload(d->g, d->tbuf, sizeof(d->tbuf)));
281 ec(GTimeout(d->g, -1));
282 return string(d->tbuf);
283}
284
285void Galil::programDownload(const std::string& program)
286{
287 ec(GTimeout(d->g, (short)timeout_ms));
288 ec(GProgramDownload(d->g, program.c_str(), 0)); //no special preprocessor directives
289 ec(GTimeout(d->g, -1));
290}
291
292void Galil::programUploadFile(const std::string& file)
293{
294 ec(GTimeout(d->g, (short)timeout_ms));
295 ec(GProgramUploadFile(d->g, file.c_str()));
296 ec(GTimeout(d->g, -1));
297}
298
299void Galil::programDownloadFile(const std::string& file)
300{
301 ec(GTimeout(d->g, (short)timeout_ms));
302 ec(GProgramDownloadFile(d->g, file.c_str(), 0)); //no special preprocessor directives
303 ec(GTimeout(d->g, -1));
304}
305
306vector<double> Galil::arrayUpload(const std::string& name)
307{
308 ec(GTimeout(d->g, (short)timeout_ms));
309 ec(GArrayUpload(d->g, name.c_str(), G_BOUNDS, G_BOUNDS, G_CR, d->tbuf, sizeof(d->tbuf)));
310 ec(GTimeout(d->g, -1));
311
313 int len = strlen(d->tbuf); //gclib null terminates array buf
314 char* start = d->tbuf; //start hold pointer to begining of string to atof
315 for (int i = 0; i < len; i++)
316 {
317 if (d->tbuf[i] == '\r')
318 {
319 vals.push_back(atof(start));
320 start = d->tbuf + i;
321 }
322 }
323 vals.push_back(atof(start)); //last number still left in tbuf
324 return vals;
325}
326
327void Galil::arrayDownload(const std::vector<double>& array, const std::string& name)
328{
329 //GArrayDownload requires a cstring containing the data
330 string array_str;
331 for (size_t i = 0; i < array.size(); i++)
332 {
333 sprintf(d->tbuf, "%0.4f\r", array[i]);
334 array_str.append(d->tbuf);
335 }
336 ec(GTimeout(d->g, (short)timeout_ms));
337
338 //Galil::arrayDownload auto-dimensions the array table
339 string command = "DA " + name + "[]";
340 ec(GCmd(d->g, command.c_str())); //Deallocate array
341 command = "DM " + name + "[" + to_string(array.size()) + "]";
342 ec(GCmd(d->g, command.c_str())); //Allocate array with correct dimension
343
344 ec(GArrayDownload(d->g, name.c_str(), G_BOUNDS, G_BOUNDS, array_str.c_str()));
345 ec(GTimeout(d->g, -1));
346}
347
348void Galil::arrayUploadFile(const std::string& file, const std::string& names)
349{
350 ec(GTimeout(d->g, (short)timeout_ms));
351 ec(GArrayUploadFile(d->g, file.c_str(), names.c_str()));
352 ec(GTimeout(d->g, -1));
353}
354
355void Galil::arrayDownloadFile(const std::string& file)
356{
357 ec(GTimeout(d->g, (short)timeout_ms));
358 ec(GArrayDownloadFile(d->g, file.c_str()));
359 ec(GTimeout(d->g, -1));
360}
361
362void Galil::firmwareDownloadFile(const std::string& file)
363{
364 ec(GTimeout(d->g, (short)timeout_ms));
365 ec(GFirmwareDownload(d->g, file.c_str()));
366 ec(GTimeout(d->g, -1));
367}
368
369int Galil::write(const std::string& bytes)
370{
371 ec(GTimeout(d->g, (short)timeout_ms));
372 ec(GWrite(d->g, bytes.data(), bytes.length()));
373 ec(GTimeout(d->g, -1));
374 return bytes.length();
375}
376
377string Galil::read()
378{
379 ec(GTimeout(d->g, (short)timeout_ms));
381 ec(GRead(d->g, d->tbuf, sizeof(d->tbuf), &bytes_read));
382 ec(GTimeout(d->g, -1));
383 return string(d->tbuf, bytes_read); //data is not null-terminatated, so construct string "from buffer"
384}
385
string AddressConvert(const string &gcl_address)
Takes a GCL address string and returns the equivalent gclib address string.
Definition gcl_galil.cpp:80
#define G_BAD_RESPONSE_QUESTION_MARK
Operation received a ?, indicating controller has a TC error.
#define G_DATA_RECORD_ERROR
Data record error, e.g. DR attempted on serial connection.
GCLIB_DLL_EXPORTED GReturn GCALL GCmdT(GCon g, GCStringIn command, GCStringOut trimmed_response, GSize response_len, GCStringOut *front)
Wrapper around GCommand that trims the response.
Definition gclibo.c:243
#define G_COMMAND_CALLED_WITH_ILLEGAL_COMMAND
GCommand() was called with an illegal command, e.g. ED, DL or QD.
#define G_CR
For GArrayUpload(), use this value in the delim field to delimit with carriage returns.
Definition gclib.h:53
GCLIB_DLL_EXPORTED GReturn GCALL GArrayDownloadFile(GCon g, GCStringIn file_path)
Array download from file.
Definition arrays.c:380
int GReturn
Every function returns a value of type GReturn. See gclib_errors.h for possible values.
Definition gclib.h:93
GCLIB_DLL_EXPORTED GReturn GCALL GFirmwareDownload(GCon g, GCStringIn filepath)
Upgrade firmware.
GCLIB_DLL_EXPORTED GReturn GCALL GArrayUploadFile(GCon g, GCStringIn file_path, GCStringIn names)
Array upload to file.
Definition arrays.c:408
GCLIB_DLL_EXPORTED GReturn GCALL GClose(GCon g)
Closes a connection to a Galil Controller.
GCLIB_DLL_EXPORTED GReturn GCALL GProgramDownloadFile(GCon g, GCStringIn file_path, GCStringIn preprocessor)
Program download from file.
Definition gclibo.c:387
#define G_SMALL_BUFFER
Most reads from Galil are small. This value will easily hold most, e.g. TH, TZ, etc.
Definition gclib.h:89
GCLIB_DLL_EXPORTED GReturn GCALL GTimeout(GCon g, short timeout_ms)
Uses GUtility() and G_UTIL_TIMEOUT_OVERRIDE to set the library timeout.
Definition gclibo.c:65
unsigned char GStatus
Interrupt status byte.
Definition gclib.h:101
GCLIB_DLL_EXPORTED GReturn GCALL GVersion(GCStringOut ver, GSize ver_len)
Uses GUtility(), G_UTIL_VERSION and G_UTIL_GCAPS_VERSION to provide the library and gcaps version num...
Definition gclibo.c:29
#define G_OPEN_ERROR
Device could not be opened. E.G. Serial port or PCI device already open.
#define G_NO_ERROR
Return value if function succeeded.
#define G_BOUNDS
For functions that take range options, e.g. GArrayUpload(), use this value for full range.
Definition gclib.h:52
GCLIB_DLL_EXPORTED GReturn GCALL GCommand(GCon g, GCStringIn command, GBufOut buffer, GSize buffer_len, GSize *bytes_returned)
Performs a command-and-response transaction on the connection.
GCLIB_DLL_EXPORTED GReturn GCALL GInterrupt(GCon g, GStatus *status_byte)
Provides access to PCI and UDP interrupts from the controller.
unsigned int GSize
Size of buffers, etc.
Definition gclib.h:95
GCLIB_DLL_EXPORTED GReturn GCALL GWrite(GCon g, GBufIn buffer, GSize buffer_len)
Performs a write on the connection.
GCLIB_DLL_EXPORTED GReturn GCALL GArrayDownload(GCon g, const GCStringIn array_name, GOption first, GOption last, GCStringIn buffer)
Downloads array data to a pre-dimensioned array in the controller's array table.
GCLIB_DLL_EXPORTED GReturn GCALL GProgramUpload(GCon g, GBufOut buffer, GSize buffer_len)
Uploads a program from the controller's program buffer.
#define G_FIRMWARE_LOAD_NOT_SUPPORTED
Firmware is not supported on this bus, e.g. Ethernet for the DMC-21x3 series.
void * GCon
Connection handle. Unique for each connection in process. Assigned a non-zero value in GOpen().
Definition gclib.h:94
GCLIB_DLL_EXPORTED void GCALL GError(GReturn rc, GCStringOut error, GSize error_len)
Provides a human-readable description string for return codes.
Definition gclibo.c:459
GCLIB_DLL_EXPORTED GReturn GCALL GProgramUploadFile(GCon g, GCStringIn file_path)
Program upload to file.
Definition gclibo.c:430
GCLIB_DLL_EXPORTED GReturn GCALL GMessage(GCon g, GCStringOut buffer, GSize buffer_len)
Provides access to unsolicited messages from the controller.
#define G_UNSUPPORTED_FUNCTION
Function cannot be called on this bus. E.G. GInterrupt() on serial.
#define G_BAD_FILE
Bad file path, bad file contents, or bad write.
GCLIB_DLL_EXPORTED GReturn GCALL GProgramDownload(GCon g, GCStringIn program, GCStringIn preprocessor)
Downloads a program to the controller's program buffer.
GCLIB_DLL_EXPORTED GReturn GCALL GInfo(GCon g, GCStringOut info, GSize info_len)
Uses GUtility() and G_UTIL_INFO to provide a useful connection string.
Definition gclibo.c:49
GCLIB_DLL_EXPORTED GReturn GCALL GCmdD(GCon g, GCStringIn command, double *value)
Wrapper around GCommand that provides the return value of a command parsed into a double.
Definition gclibo.c:289
#define G_GCLIB_NON_BLOCKING_READ_EMPTY
GMessage, GInterrupt, and GRecord can be called with a zero timeout. If there wasn't data waiting in ...
GCLIB_DLL_EXPORTED GReturn GCALL GRead(GCon g, GBufOut buffer, GSize buffer_len, GSize *bytes_read)
Performs a read on the connection.
GCLIB_DLL_EXPORTED GReturn GCALL GCmd(GCon g, GCStringIn command)
Wrapper around GCommand for use when the return value is not desired.
Definition gclibo.c:237
#define G_UNABLE_TO_COMPRESS_PROGRAM_TO_FIT
Program preprocessor could not compress the program within the user's constraints.
GCLIB_DLL_EXPORTED GReturn GCALL GAddresses(GCStringOut addresses, GSize addresses_len)
Uses GUtility(), G_UTIL_GCAPS_ADDRESSES or G_UTIL_ADDRESSES to provide a listing of all available con...
Definition gclibo.c:54
GCLIB_DLL_EXPORTED GReturn GCALL GOpen(GCStringIn address, GCon *g)
Open a connection to a Galil Controller.
#define G_TIMEOUT
Operation timed out. Timeout is set by the –timeout option in GOpen() and can be overriden by GSettin...
GCLIB_DLL_EXPORTED GReturn GCALL GArrayUpload(GCon g, const GCStringIn array_name, GOption first, GOption last, GOption delim, GBufOut buffer, GSize buffer_len)
Uploads array data from the controller's array table.
#define G_ILLEGAL_DATA_IN_PROGRAM
Data to download not valid, e.g. \ in data.
GReturn vector(GCon g, char *file)
Puts controller into Vector Mode and accepts a file defining vector points.
Definition vector.cpp:36