The EPT Client API is an asynchronous, callback-oriented API. Part of the initial configuration for an EPT client instance is a set of function pointers (or abstract interface) for the library to use as callbacks. Callbacks are dispatched from the background thread that is started when the RDMnet library is initialized.
The EPT client should be shut down and destroyed gracefully before program termination. This will send a graceful disconnect message to any connected brokers and deallocate the EPT client's resources.
Shut down this EPT client and deallocate resources.
Definition: ept_client.h:200
Managing Scopes
An EPT client instance is initially created without any configured scopes. If the app has not been reconfigured by a user, the E1.33 RDMnet standard requires that the RDMnet default scope be configured automatically. There is a shortcut function for this. Otherwise, you can add a custom scope.
Per the requirements of RDMnet, a scope string is always UTF-8 and is thus represented by a char[] in C and a std::string in C++.
See the "Scopes" section in How RDMnet Works for more information on scopes.
A handle to a scope that an RDMnet client participates in.
Definition: client.h:447
Dynamic vs Static Scopes
Adding a scope will immediately begin the scope connection state machine from the RDMnet tick thread. If a static configuration is not provided (using the RDMNET_CLIENT_SET_SCOPE() macro to initialize an RdmnetScopeConfig, or calling rdmnet::EptClient::AddScope() with only one argument) the first action will be to attempt to discover brokers for this scope using DNS-SD. Once a broker is found, connection will be initiated automatically, and the result will be delivered via either the connected or connect_failed callback.
If a broker for a given scope has been configured with a static IP address and port, you can skip DNS-SD discovery by providing a static configuration:
The library will dispatch callback notifications from the background thread which is started when rdmnet_init() is called. It is safe to call any RDMnet API function from any callback; in fact, this is the recommended way of handling many callbacks.
For example, a very common EPT client behavior will be to fetch a client list from the broker after a successful connection:
It's worth noting connection failure as a special case here. RDMnet connections can fail for many reasons, including user misconfiguration, network misconfiguration, components starting up or shutting down, programming errors, and more.
The ClientConnectFailedInfo and ClientDisconnectedInfo structs passed back with the "connect failed" and "disconnected" callbacks respectively have comprehensive information about the failure, including enum values containing the library's categorization of the failure, protocol reason codes and socket errors where applicable. This information is typically used mostly for logging and debugging. Each of these codes has a respective to_string() function to aid in logging.
For programmatic use, the structs also contain a will_retry member which indicates whether the library plans to retry this connection in the background. The only circumstances under which the library will not retry is when a connection failure is determined to be either a programming error or a user misconfiguration. Some examples of these circumstances are:
The broker explicitly rejected a connection with a reason code indicating a configuration error, such as CONNECT_SCOPE_MISMATCH or CONNECT_DUPLICATE_UID.
The library failed to create a network socket before the connection was initiated.
Discovering Other Clients
To discover other EPT clients in RDMnet, you need to request a Client List from the broker you're connected to. In our API, this is very easy - as we saw in the callbacks section earlier, we can just call rdmnet_ept_client_request_client_list() or rdmnet::EptClient::RequestClientList(). This sends the appropriate request to the broker, and the reply will come back in the "Client List Update" callback:
Brokers also send Client List Update messages asynchronously when things change; these messages contain only the differences from the last client list sent to a given controller. This means you should only have to request a full client list when a new connection completes; after that, expect periodic callbacks notifying you of changes, with the client_list_action_t set appropriately as shown above.
Each EPT client entry structure contains a list of sub-protocols that client supports (along with its CID). This list should be checked for protocols that match those of the local EPT client to determine which clients you are interested in talking to. Make sure to save those clients' CIDs; that is the primary addressing identifier you will use to send data to them.
Sending Data
Send data to other EPT clients by providing the data, the EPT sub-protocol being used, and the destination client's CID.
EPT makes no distinction between requests and replies and has no method of correlating them; these features are up to sub-protocols to implement. When data arrives addressed to a local client, it will be delivered asynchronously through the "data received" callback.
Note that data received callbacks reference data buffers owned by the library, which will be invalid when the callback returns. See Data Ownership Paradigms in the RDMnet Library for more information.
Defer the response to the EPT message, either to be sent later or because no response is necessary.
Definition: common.h:198
Responding Synchronously to EPT Data
If you receive EPT data that motivates a response, and you can access the data with which to respond relatively quickly from the code path of the notification callback, it's convenient to respond synchronously. The EPT data received notification callbacks provide a way to set the response information directly from the callback, which the library will use to send a response after the callback returns.
Important note: Do not do this when accessing response data may block for a significant time.
When responding with EPT data, it should be copied into the buffer that was provided when the EPT client handle was created, before returning from the callback function. All notifications for any given RDMnet handle are delivered from the same thread, so accesses to this buffer from the callback context are thread-safe.
After copying the data, use the API-specific method to indicate that data should be sent in response as shown below.
// This buffer was provided as part of the RdmnetEptClientConfig when the device handle was created.
If EPT data does not require a response, or if you choose to defer the response to be sent at a later time, this can be indicated in the data received callback as well. Note that if you want to save the EPT data you received, it must be copied out (data delivered to callbacks is still owned by the library). There are RDMnet API functions to save EPT data using heap allocation; you can also use your own method of saving the data.
An EPT data message received over RDMnet and saved for later processing.
Definition: ept_data.h:76
Handling EPT Status Messages
If something went wrong while a broker or an EPT client was processing your message, you will get a response called an "EPT Status". There is a separate callback for handling these messages.