gclib 2.4.0
Galil Communications Library
Loading...
Searching...
No Matches
Unsolicited Data

Get unsolicited messages, interrupts, or data records, in blocking or callback mode. More...

Functions

gclib_result gclib_set_interrupts (gclib_handle h, gclib_interrupt_type interrupt_mask, gclib_axis_flags motion_complete_axes, gclib_digital_input_flags digital_inputs)
 Configure which interrupts will be generated by the controller.
gclib_result gclib_set_data_records (gclib_handle h, size_t period_ms)
 Configure controller data records.
gclib_result gclib_subscribe_messages (gclib_handle h, void(callback)(void *user_data, const char *message), void *user_data)
 Subscribe to unsolicited messages.
gclib_result gclib_subscribe_interrupts (gclib_handle h, void(callback)(void *user_data, gclib_interrupt_t interrupt), void *user_data)
 Subscribe to interrupts.
gclib_result gclib_subscribe_data_records (gclib_handle h, void(callback)(void *user_data, gclib_data_record_handle data_record), void *user_data)
 Subscribe to data records.
gclib_result gclib_subscribe_progress (gclib_handle h, void(callback)(void *user_data, size_t current, size_t max), void *user_data)
 Subscribe to progress for gclib_set_program(), gclib_set_array(), and gclib_set_firmware().
gclib_result gclib_unsubscribe (gclib_handle h, void *callback)
 Unsubscribe from messages, interrupts, data records, or progress.
gclib_result gclib_message (gclib_handle h, char *message, size_t len, int timeout)
 Get a queued unsolicited message, or wait up to timeout ms for one to arrive.
gclib_result gclib_interrupt (gclib_handle h, gclib_interrupt_t *interrupt, int timeout)
 Get a queued interrupt, or wait up to timeout ms for one to arrive.
gclib_result gclib_data_record (gclib_handle h, gclib_data_record_handle *data_record, int timeout)
 Get a queued data record, or wait up to timeout ms for one to arrive.

Detailed Description

Get unsolicited messages, interrupts, or data records, in blocking or callback mode.

Blocking Mode

Blocking mode is simpler to use, but has tradeoffs. If you want unsolicited data as soon as it arrives, you must block the thread to wait for it, which may not be ideal. If you want to keep the thread running, then you must periodically check for queued unsolicited data, which can add unwanted latency.

To subscribe in blocking mode, simply do not pass a callback or data pointer when you subscribe. These methods will begin queueing any unsolicited data sent by the controller.

gclib_subscribe_messages(h, NULL, NULL);
gclib_result gclib_subscribe_data_records(gclib_handle h, void(callback)(void *user_data, gclib_data_record_handle data_record), void *user_data)
Subscribe to data records.
gclib_result gclib_subscribe_interrupts(gclib_handle h, void(callback)(void *user_data, gclib_interrupt_t interrupt), void *user_data)
Subscribe to interrupts.
gclib_result gclib_subscribe_messages(gclib_handle h, void(callback)(void *user_data, const char *message), void *user_data)
Subscribe to unsolicited messages.

Callback Mode

Callback mode allows your thread to stay running while enabling immediate response to unsolicited data. When data arrives, your callback function will be invoked on a separate, dedicated thread. Due to this, callback mode can be more complicated to use if you are not familiar with thread synchronization.

To subscribe in callback mode, pass a callback function and an optional data pointer when you subscribe. When unsolicited data arrives, your callback will be invoked and passed the data pointer. Use this to allow the callback function access to any data it needs, and to allow data to persist between callbacks.

void handle_message(void* user_data, const char* message) {
printf("Message received: %s\n", message);
}
void handle_interrupt(void* user_data, gclib_interrupt_t interrupt) {
printf("Interrupt received, type %i, raw status byte %i": interrupt.type, interrupt.status);
}
void handle_data_record(void* user_data, gclib_data_record_handle data_record) {
printf("Data record received, sample %i", gclib_data_record_sample(data_record));
}
gclib_interrupt_type type
Definition gclib.h:56
uint8_t status
The raw status byte generated by the controller. See the EI command reference for all possible values...
Definition gclib.h:62
struct DataRecord * gclib_data_record_handle
A handle to a data record, for use in Data Record API calls.
Definition gclib.h:25
uint16_t gclib_data_record_sample(gclib_data_record_handle h)
The sample in which this data record was generated.
An interrupt generated by the controller.
Definition gclib.h:55
gclib_subscribe_messages(h, handle_messages, user_data);
gclib_subscribe_interrupts(h, handle_interrupts, user_data);
gclib_subscribe_data_records(h, handle_data_records, user_data);

User Data

The user data pointer can be used to pass arbitrary data to the callback function. The following example uses a struct to provide the callback access to the gclib handle itself, a count to increment when messages are received, and an atomic bool to signal when the program is ready to exit. Note that the handle is safe to use concurrently, and the count doesn't need to be atomic (since it is only used in the callback thread). As soon as the tenth message is received, the program is stopped and the connection is closed from the callback method, and the main thread is signaled to exit.

#include <gclib.h>
#include <stdio.h>
#include <stdatomic.h>
#include "sleep.h"
struct context {
gclib_handle h; // gclib is thread-safe
int count; // Only used in the callback thread
atomic_bool done; // Used in both threads
};
void handle_message(void* user_data, const char* message) {
struct context* ctx = user_data;
ctx->count = ctx->count + 1;
printf("Received message #%i at TIME %i\n", ctx->count, (int)atof(message));
if (ctx->count == 10) {
gclib_command(ctx->h, "ST", NULL, 0);
gclib_close(&ctx->h);
ctx->done = true;
}
};
int main(int argc, char* argv[]) {
struct context ctx = {NULL, 0, 0};
gclib_open(&ctx.h, argv[1]);
gclib_subscribe_messages(ctx.h, handle_message, &ctx);
gclib_set_program(ctx.h, "#msg\nMGTIME\nWT100\nJP#msg\nEN", NULL);
gclib_command(ctx.h, "XQ", NULL, 0);
while (!ctx.done) {
msleep(100 * 1000); // Do work
}
}
gclib_result gclib_close(gclib_handle *h)
Close connection to controller.
gclib_result gclib_open(gclib_handle *h, const char *address)
Open a connection to a controller.
gclib_result gclib_command(gclib_handle h, const char *command, char *buf, size_t len)
Issues a command to the controller and provides the response.
gclib_result gclib_set_program(gclib_handle h, const char *program, const char *insert)
Set the program on the controller.
struct Context * gclib_handle
A handle to an open connection given by gclib_open() for use in future API calls.
Definition gclib.h:23

Function Documentation

◆ gclib_set_interrupts()

gclib_result gclib_set_interrupts ( gclib_handle h,
gclib_interrupt_type interrupt_mask,
gclib_axis_flags motion_complete_axes,
gclib_digital_input_flags digital_inputs )

Configure which interrupts will be generated by the controller.

By default, the controller will not generate any interrupts.

Controllers can be configured to send only an exact list of desired interrupts, to avoid unnecessary processing and network traffic.

Example usage:

gclib_set_interrupts(h, GCLIB_ALL_INTERRUPTS, 0, 0); // Enable all interrupts.
GCLIB_MOTION_COMPLETE | GCLIB_DIGITAL_INPUT_LOW, // Only enable two interrupts
GCLIB_AXIS_A | GCLIB_AXIS_F, // Only trigger GCLIB_MOTION_COMPLETE on axis A or F
GCLIB_DIGITAL_INPUT_1 | GCLIB_DIGITAL_INPUT_4); // Only trigger GCLIB_DIGITAL_INPUT_LOW on digital input 1 and 4.
gclib_set_interrupts(h, 0, 0, 0); // Disable interrupts
gclib_result gclib_set_interrupts(gclib_handle h, gclib_interrupt_type interrupt_mask, gclib_axis_flags motion_complete_axes, gclib_digital_input_flags digital_inputs)
Configure which interrupts will be generated by the controller.
@ GCLIB_DIGITAL_INPUT_4
Definition gclib.h:70
@ GCLIB_DIGITAL_INPUT_1
Definition gclib.h:67
@ GCLIB_AXIS_F
Definition gclib.h:85
@ GCLIB_AXIS_A
Definition gclib.h:80
@ GCLIB_ALL_INTERRUPTS
Definition gclib.h:52
@ GCLIB_MOTION_COMPLETE
Definition gclib.h:44
@ GCLIB_DIGITAL_INPUT_LOW
Must be reenabled with gclib_set_interrupts() after each occurrence.
Definition gclib.h:51

See gclib_subscribe_interrupts() to enable receiving interrupts from the controller.

Parameters
hHandle to an open connection.
interrupt_maskBitmask of desired interrupts. Use GCLIB_NO_INTERRUPTS (0) to disable interrupts. Note that User Interrupts cannot be disabled.
axis_maskWhen GCLIB_MOTION_COMPLETE is in interrupt_mask, this axis mask controls which axes will trigger a GCLIB_MOTION_COMPLETE interrupt. interrupts. If 0, all axes will be selected.
digital_input_maskWhen GCLIB_DIGITAL_INPUT_LOW is in interrupt_mask, this bitmask selects which digital inputs will trigger an interrupt. If 0, all digital inputs will be selected.
Returns
GCLIB_TIMEOUT if no response from controller after configuring interrupts.

◆ gclib_set_data_records()

gclib_result gclib_set_data_records ( gclib_handle h,
size_t period_ms )

Configure controller data records.

By default, data records are not sent by the controller.

See gclib_subscribe_data_records() to enable receiving data records from the controller.

Parameters
hHandle to an open connection.
period_msPeriod between data records. Pass 0 to disable data records.
Returns
GCLIB_TIMEOUT if no response from controller after configuring data records.

◆ gclib_subscribe_messages()

gclib_result gclib_subscribe_messages ( gclib_handle h,
void(callback)(void *user_data, const char *message) ,
void * user_data )

Subscribe to unsolicited messages.

This method registers a callback to be run every time an unsolicited message is received from the controller.

Note
The callback will be invoked on a separate, dedicated thread. Be careful when accessing any shared state.

When a callback is not provided, messages are instead queued for later retrieval by gclib_message().

On ethernet connections, a handle is opened for unsolicited data (if not already open) and the controller is configured to use it for messages.

Parameters
hHandle to an open connection.
callbackPass a callback function to get messages asynchronously, or NULL if you would like to use the gclib_message() blocking API.
user_dataAn arbitrary pointer that will be passed to your callback function. Can be used to provide state that persists between callbacks.
Returns
GCLIB_NOT_SUBSCRIBED if unable to subscribe to messages.

◆ gclib_subscribe_interrupts()

gclib_result gclib_subscribe_interrupts ( gclib_handle h,
void(callback)(void *user_data, gclib_interrupt_t interrupt) ,
void * user_data )

Subscribe to interrupts.

This method registers a callback to be run every time an interrupt is received from the controller. See gclib_set_interrupts() to enable and configure controller interrupts.

Note
The callback will be invoked on a separate, dedicated thread. Be careful when accessing any shared state.

When a callback is not provided, interrupts are instead queued for later retrieval by gclib_interrupt().

On ethernet connections, a handle is opened for unsolicited data (if not already open) and the controller is configured to use it for interrupts.

Parameters
hHandle to an open connection.
callbackPass a callback function to get interrupts asynchronously, or NULL if you would like to use the gclib_interrupt() blocking API.
user_dataAn arbitrary pointer that will be passed to your callback function. Can be used to provide state that persists between callbacks.
Returns
GCLIB_NOT_SUBSCRIBED if unable to subscribe to interrupts.

◆ gclib_subscribe_data_records()

gclib_result gclib_subscribe_data_records ( gclib_handle h,
void(callback)(void *user_data, gclib_data_record_handle data_record) ,
void * user_data )

Subscribe to data records.

This method registers a callback to be run every time a data record is received from the controller. See gclib_set_data_records() to enable data records and configure how often they will be generated by the controller.

Note
The callback will be invoked on a separate, dedicated thread. Be careful when accessing any shared state.

When a callback is not provided, data records are instead queued for later retrieval by gclib_data_record().

On ethernet connections, a handle is opened for unsolicited data (if not already open) and the controller is configured to use it for data records.

Parameters
hHandle to an open connection.
callbackPass a callback function to get data records asynchronously, or NULL if you would like to use the gclib_data_record() blocking API.
user_dataAn arbitrary pointer that will be passed to your callback function. Can be used to provide state that persists between callbacks.
Returns
GCLIB_NOT_SUBSCRIBED if unable to subscribe to data records.

◆ gclib_subscribe_progress()

gclib_result gclib_subscribe_progress ( gclib_handle h,
void(callback)(void *user_data, size_t current, size_t max) ,
void * user_data )

Subscribe to progress for gclib_set_program(), gclib_set_array(), and gclib_set_firmware().

Note
The callback will be invoked on a separate, dedicated thread. Be careful when accessing any shared state.
Parameters
hHandle to an open connection.
callbackA callback function that will get called anytime part of a large write is completed.
user_dataAn arbitrary pointer that will be passed to your callback function. Can be used to provide state that persists between callbacks.
Returns
GCLIB_INVALID_ARGUMENT if callback is NULL.

◆ gclib_unsubscribe()

gclib_result gclib_unsubscribe ( gclib_handle h,
void * callback )

Unsubscribe from messages, interrupts, data records, or progress.

Parameters
hHandle to an open connection.
callbackThe callback function that was previously used to subscribe. If NULL, all subscriptions will be cleared.
Returns
GCLIB_INVALID_ARGUMENT if callback doesn't match any existing subscription.

◆ gclib_message()

gclib_result gclib_message ( gclib_handle h,
char * message,
size_t len,
int timeout )

Get a queued unsolicited message, or wait up to timeout ms for one to arrive.

Parameters
hHandle to an open connection.
messageOutput buffer for the message.
lenLength of output buffer.
timeoutTimeout value in milliseconds. If -1, wait forever.
Returns

◆ gclib_interrupt()

gclib_result gclib_interrupt ( gclib_handle h,
gclib_interrupt_t * interrupt,
int timeout )

Get a queued interrupt, or wait up to timeout ms for one to arrive.

Parameters
hHandle to an open connection.
interruptOutput interrupt.
timeoutTimeout value in milliseconds. If -1, wait forever.
Returns
GCLIB_TIMEOUT if no interrupt arrives after timeout ms.

◆ gclib_data_record()

gclib_result gclib_data_record ( gclib_handle h,
gclib_data_record_handle * data_record,
int timeout )

Get a queued data record, or wait up to timeout ms for one to arrive.

The returned handle remains valid until the next call to gclib_data_record().

Parameters
hHandle to an open connection.
data_recordOutput data record handle.
timeoutTimeout value in milliseconds. If -1, wait forever.
Returns
GCLIB_TIMEOUT if no data record arrives after timeout ms.