Channel Access Client Programming in C - PowerPoint PPT Presentation

channel access client programming in c n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Channel Access Client Programming in C PowerPoint Presentation
Download Presentation
Channel Access Client Programming in C

play fullscreen
1 / 56
Channel Access Client Programming in C
160 Views
Download Presentation
Download Presentation

Channel Access Client Programming in C

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

  1. Channel Access Client Programming in C Advanced EPICS Training

  2. Contents • What is Channel Access? • About channels • Channel Access data types • Connecting • Reading • Monitoring • Writing • Channel Access Security • Channel Access details Advanced EPICS Training, Dirk Zimoch 2007

  3. What is Channel Access? • The EPICS network protocol • Based on UDP and TCP, default ports 5064 and 5065 • Provides reading, writing and monitoring values • Typical Channel Access servers are • EPICS IOCs • Channel Access Gateways • Typical Channel Access clients are • EPICS IOCs • medm • caget Advanced EPICS Training, Dirk Zimoch 2007

  4. Vocabulary • Record: The building blocks of EPICS IOCs holding data. • Field: Part of a record, e.g. VAL=value, EGU=units • A field is one atomic piece of data, e.g. a number or a string • A record consists of many fields, VAL is only the "default" field. • PV (Process Variable): A piece of data with attributes • It usually gets the value from a record field, often the VAL field. • The attributes may come from other fields. • You always work with local copies of remote PVs. • Channel: The connection to a remote PV on a server Often "record", "PV", and "channel" are mixed up. Advanced EPICS Training, Dirk Zimoch 2007

  5. The CA view to the world • CA connects to remote PVs, not to records or fields. • CA does not know about records or record types. • CA only knows about data types. Example: • caget ARIDI-PCT:CURRENT tries to read a PV • The IOC ARIDI-VME-PCT has an ai record with that name • The IOC returns the VAL field of that record to the client • The client gets a copy of a DOUBLE PV • caget ARIDI-PCT:CURRENT.VAL gets the same value Advanced EPICS Training, Dirk Zimoch 2007

  6. About channels • A channel connects to a remote PV by name. • PV names must be unique within the network. • ca_create_channel() assigns a channel ID to a PV name and allocates necessary resources (memory). • Channel IDs are unique within the program • A channel starts disconnected. • Only after connection, data can be transferred. • Reading: ca_get() • Writing: ca_put() • Monitoring: ca_create_subscription() Advanced EPICS Training, Dirk Zimoch 2007

  7. Channel status • Get the connection status • ca_state(channel) returns: • cs_never_conn before 1st connection or when PV is not found • cs_conn after connection, when channel can be used • cs_prev_conn after disconnect, e.g. server shut down • cs_closed after ca_clear_channel() • Close a channel and free resources • ca_clear_channel(channel) • also uninstalls all handlers (callbacks) for channel • can be called before client exits for clean shutdown Advanced EPICS Training, Dirk Zimoch 2007

  8. Other channel information • Read back the PV name which is connected to the channel • ca_name(channel) • Get the native data type of the channel (the remote PV) • ca_field_type(channel) • available after connection • returns TYPENOTCONN if the channel is not connected • Get number of elements or array PVs • ca_element_count(channel) • available after connection • returns 1 for scalar PVs Advanced EPICS Training, Dirk Zimoch 2007

  9. Channel Access data types • 7 basic fundamental data base field types: • DBF_STRING: a string of max 40 characters (incl null-byte) • DBF_CHAR: one unsigned byte • DBF_SHORT: signed 16 bit integer, alias DBF_INT • DBF_LONG: signed 32 bit integer • DBF_ENUM: one of up to 16 predefined strings • DBF_FLOAT: 32 bit floating point • DBF_DOUBLE: 64 bit floating point • 1 dimensional arrays of fundamental types • "annotated" types with meta-data for local PVs Advanced EPICS Training, Dirk Zimoch 2007

  10. Annotated CA data types (with meta-data) • 5 flavours (detail levels) of data base request types • DBR_*: The naked DBF_* value • DBR_STS_*: value + status + severity • DBR_TIME_*: value + status + severity + (time-) stamp • DBR_GR_*: value + status + severity + display infos • DBR_CTRL_*: value + status + severity + control infos • The local copy of a PV always uses one of the DBR types Note: • Control infos supersede display infos • DBR_GR_* and DBR_CTRL_* don't inclue timestamps Advanced EPICS Training, Dirk Zimoch 2007

  11. Display and control infos for integers Note: • If the PV is the VAL field of a record, the info maps to other fields. • Numeric infos have the same data type as the value. • Display info • units (string max 8 chars incl null-byte) (EGU) • upper_disp_limit and lower_disp_limit (HOPR and LOPR) • upper_warning_limit and lower_warning_limit (HIGH and LOW) • upper_alarm_limit and lower_alarm_limit (HIHI and LOLO) • Control info (in addition to display info) • upper_ctrl_limit and lower_ctrl_limit (DRVH and DRVL) Advanced EPICS Training, Dirk Zimoch 2007

  12. Display and control info for floating point • Display info • Everything integer display info has but with floating point data type • precision (short integer) • It is not really defined, what e.g. precision=3 means. • digits after decimal point like in %.3f (e.g. 12345.678) • total valid digits like in %.3g (e.g. 1.23e+04) • digits after decimal point in exponential notation like in %.3e (e.g. 1.235e+04) • It is not defined what precision<0 means. • Control info (in addition to display info) • Like integer control info but with floating point format Advanced EPICS Training, Dirk Zimoch 2007

  13. Display and control info for enums Note: • Value is an index (unsigned short integer) to a string list. • Display info • no_str (short integer) number of defined strings • strs (16 strings of max 26 chars incl null-byte) • Control info • Same as display info Note: • Enums have no units and no limit infos. • Be careful with string conversion when value >= no_str. Advanced EPICS Training, Dirk Zimoch 2007

  14. When to use which detail level • To read static information once after the channel connected • Use DBR_CTRL_* if you plan to write to the channel. • You may use DBR_GR_* if you only want to read the channel. • If in doubt, use DBR_CTRL_* always. • To read or monitor dynamic (changing) values • Use DBR_TIME_*. • The naked value might be invalid or old without notice! • To write values • use the naked DBR_*. • I know no use for DBR_STS_* (and DBR_GR_*) Advanced EPICS Training, Dirk Zimoch 2007

  15. Caveats • There is no signed char type. • There are no unsigned short or long types. PVs of those types will be converted to a sufficiently large type on the server: • unsigned short → DBF_LONG • unsigned long → DBF_DOUBLE • There are no 64 bit integers. • Strings are limited to 40 bytes, but arrays of char can be used. • There are no user-defined structures. • There are no multi-dimensional arrays. • Arrays have constant length (while connected) Advanced EPICS Training, Dirk Zimoch 2007

  16. Converting DBF types to DBR types • A channel has a native DBF type. • This is the data type of the value of the remote PV. • ca_field_type(channel) returns the native DBF_* type • Reading and writing requires a DBR type. • This is the type and detail level of the local copy of the PV. • It is possible to do automatic conversion (on the server), e.g. read a DBF_SHORT PV as DBR_STRING or DBR_DOUBLE. • It is more efficient to use use a matching DBR type. • CA provides conversion macros to find matching DBR types: • dbf_type_to_DBR_CTRL(field_type) and similar Advanced EPICS Training, Dirk Zimoch 2007

  17. Mapping of CA types to C types • DBR_* and DBF_* are macros for code numbers used in channel access functions. • Each DBR_<XXX>_<TYPE> code has a corresponding C data type: struct dbr_<xxx>_<type> (all lowercase letters) • These structures should be used for the local copies of PVs. • There are no dbr_gr_string or dbr_ctrl_string types. • Codes and structures are defined in db_access.h • Channel Access provides a macro to calculate the required amount of memory for a PV (also for arrays). • dbr_size_n(DBR_type, element_count) Advanced EPICS Training, Dirk Zimoch 2007

  18. Creating a channel • A channel starts disconnected and without network traffic • ca_create_channel(name, connhandler, user, prio, pchannel) • name PV name (const char*) to conenct to • connhandler handler function to be called on connection change can be NULL • user arbitrary user data (void*) associated with channel • prio priority on server, 0 lowest, 99 highest CA_PRIORITY_DEFAULT=0 CA_PRIORITY_ARCHIVE=20 • pchannel pointer to channel ID to be filled in (chid*) • First create all needed channels before connecting them. • Connecting is an expensive operation. Advanced EPICS Training, Dirk Zimoch 2007

  19. Connecting channels • Channels without connection handler • ca_pend_io(timeoutSec) sends pending requests and waits. • Returns early with ECA_NORMAL after all channels connected. • Returns after timeoutSec with ECA_TIMEOUT. • Check all channels with ca_state(channel) to find not connected channels. • Channels with connection handler • ca_flush_io() sends pending requests and returns immediately. • ca_pend_io(timeoutSec) would also return immediately. • Whenever a channel (dis-/re-)connects, its handler is called. • All connect requests are processed in parallel. Advanced EPICS Training, Dirk Zimoch 2007

  20. Wait or call back? • When to wait for connections • Command line tools • Simple linear programs • Short lived programs • When to use connection handlers • Graphical user interfaces • Servers • Event driven programs • Long lived programs • Always Advanced EPICS Training, Dirk Zimoch 2007

  21. Connection handling • Disconnecting and reconnecting are normal. • In a distributed system, remote IOCs may be rebooted at any time. • This should never put the client in an undefined state. • Late connecting is normal. • The IOC may be started after the client. • This is handled automatically by Channel Access. • Write a connection handler to perform action on (dis-)connection. • void handler(struct connection_handler_args args) • args.chid channel id • args.opCA_OP_CONN_UP or CA_OP_CONN_DOWN Advanced EPICS Training, Dirk Zimoch 2007

  22. What to avoid • Do not call ca_pend_io() or ca_flush_io() separately for each channel. • When writing PV wrappers, do not connect in the constructor! • When building a GUI, do not connect each widget separately! • When processing a list of PVs, do not connect each PV separately! • First create all PVs, widgets, etc. then connect in parallel. • Do not call ca_create_channel() twice for the same PV. • When a channel disconnects, do not call ca_create_channel() again! • When a connect times out, do not call ca_create_channel() again! • Use connection handlers instead of timeouts. Advanced EPICS Training, Dirk Zimoch 2007

  23. Providing buffer space • Use ca_field_type(channel) for native field type. • Use dbf_type_to_DBR_*(field_type) for matching DBR type. • Choose the appropriate DBR_* type for your application. • Use ca_element_count(channel) for array length. • Use dbr_size_n(dbr_type, elements) for required size. • Allocate buffer memory. malloc(dbr_size_n(dbf_type_to_DBR_TIME(ca_field_type(channel))), ca_element_count(channel)) • Or choose a DBR type manually and let the server convert • This increases the load on the server. Advanced EPICS Training, Dirk Zimoch 2007

  24. Reading channels • Prepare a read request • ca_array_get(dbr_type, elements, channel, buffer) • dbr_type requested data type (should match buffer size) • elements maximum array size to read (may be smaller than native size) • channel channel ID • buffer pointer to buffer (min dbr_size_n(dbr_type, elements) bytes long) • ca_get(dbr_type, channel, buffer) • Same as above with elements=1 • Send request and wait for reply • ca_pend_io(timeoutSec) Advanced EPICS Training, Dirk Zimoch 2007

  25. Increasing read performance • If possible, do many ca_get() with one ca_pend_io() • Requests are sent in parallel. • Timeout for replies runs in parallel. • Problem: Error detection • ca_pend_io() returns ECA_TIMEOUT when any get fails. • No way to find out which get failed. • Caution: ca_pend_io() delays the program. • GUIs, servers and other event driven programs should block. • Better use callbacks. Advanced EPICS Training, Dirk Zimoch 2007

  26. Reading with callbacks • Prepeare read request • ca_array_get_callback(dbr_type, elements, channel, callback, usr) • dbr_type, elements, channel as in ca_array_get() • callback function to be called when data arrives • usr arbitrary user argument to callback function • No need to provide buffer! • ca_get_callback(dbr_type, channel, callback, arg) • Send read requests and continue • ca_flush_io() • If possible, do many ca_get_callback() with one ca_flush_io() Advanced EPICS Training, Dirk Zimoch 2007

  27. Receiving read callbacks • Write a callback function • void readCallback(struct event_handler_args args) • args.usr user data from ca_get_callback() call • args.chid channel ID • args.type DBR type of data • args.count number of elements in array (1 for scalars) • args.dbr pointer to data buffer (void*) • args.status a ECA_* status code for the operation, e.g. ECA_SUCCESS • Copy the data from *dbr to your private buffer. • You have to implement timeouts yourself, if required. • ca_pend_io(timeoutSec) does not wait for get with callback! Advanced EPICS Training, Dirk Zimoch 2007

  28. What can go wrong while reading • The channel is disconnected • ca_get then returns ECA_DISCONN • This can happen at any time, even if a previous call to ca_state(channel) returned cs_connected. • IOCs may be rebooted. • Network may be overloaded. • The server does not reply in time • ca_pend_io(timeoutSec) times out. • The server may be too busy. • The network latency may be too high. Advanced EPICS Training, Dirk Zimoch 2007

  29. What else can go wrong • PV is not readable • CA security on the server forbits reading. • The PV has no readable data type (DBF_NOACCESS). • The PV cannot be converted to the requested DBR type. • Invalid parameters • invalid (e.g. closed) channel ID • invalid DBR type code • requested elements larger than PV array size • Out of memory • Check return value of all ca_* functions! Advanced EPICS Training, Dirk Zimoch 2007

  30. Exercise 1 (2 hours) • Write a simple program that connects to a remote PV (e.g. a record on an IOC), reads the value and prints it. • CA functions: #include <cadef.h> • CA datatypes: see db_access.h • status and severity: see alarm.h • Format the value nicely (precision, units, alarms). • Read more than one value efficiently. • Read the values repeatedly. • What if a PV does not exit or disconnects (when IOC reboots)? • What if you request a “wrong” DBR type? Advanced EPICS Training, Dirk Zimoch 2007

  31. Contexts, threads and callbacks • Multi-threaded context • ca_context_create(ca_enable_preemtive_callbacks) • Callbacks may be called at any time except during other callbacks. • You need to know how to use mutex semaphores. • Single-threaded context • ca_context_create(ca_disable_preemtive_callbacks) • Is created automatically when ca_* functions are used without context. • Callbacks are only called from within a ca_* function. • The program must call ca_pend_io(), ca_flush_io(), ca_pend_event() or ca_poll() regularly to receive any data (e.g. in event/idle loop). Advanced EPICS Training, Dirk Zimoch 2007

  32. Doing network traffic in single-theaded context • Four functions send pending output and wait for input • ca_pend_io(timeoutSec) send, wait until get and connect requests without callback complete • ca_pend_event(waitSec) send, wait for input, does not return before waitSec are over • ca_poll() send, handle only pending input, does not wait for more input • ca_flush_io() send, don’t process input • Output is also sent when output buffers are full. • For efficiency send as much output as possible together. Advanced EPICS Training, Dirk Zimoch 2007

  33. Doing network traffic in multi-threaded context • The single-threaded networking functions can be used to force sending output and to wait. • Output may also be sent at any other time. • Most probably when all threads are idle (waiting for something) • Input may be received at any time. • There is no need to call ca_pend_io() and friends. • Don't forget to protect your data with mutex semaphores! • A callback may modify your local PV copy while you are accessing it! Advanced EPICS Training, Dirk Zimoch 2007

  34. Monitoring cannels • Subscribe for monitor events • ca_create_subscription(dbr_type, elements, channel, eventmask, callback, usr, pmonid) • dbr_type, elements, channel, callback and usr are the same as in ca_array_get_callback() • eventmask combination of bits DBE_VALUE, DBE_LOG, DBE_ALARM Normally use DBE_VALUE| DBE_ALARM. • pmonid pointer to monitor ID, needed to delete monitor (evid*) • The same callback as for ca_array_get_callack() may be used. • Send monitor requests, e.g with ca_flush_io(). • Monitors will come whenever value or alarm status changes. Advanced EPICS Training, Dirk Zimoch 2007

  35. Using monitors efficiently • First create all subscriptions before sending them • Do not call ca_flush_io() after every single ca_create_subscription() • Especially when writing wrappers, classes, GUIs, make sure that not every single monitor request is sent individually. • Separate static and dynamic data • Read large DBR_CTRL_* only once after connection with ca_get(). • Can be done in connection handler. • Don’t read arrays here. • Subscribe for small DBR_TIME_* types. • Prefer monitors to ca_get() polling. Advanced EPICS Training, Dirk Zimoch 2007

  36. Monitor or get? • When to use get • When a value is read only once. • When a value must be read at a specific time. • To take a snapshot (e.g. save a setup). • In short lived programs (command line tools). • When to use monitors • Whenever a PV changes frequently. • When short pulses (off-on-off) should not be missed. • In GUIs, servers, other long lived programs. • Always. Advanced EPICS Training, Dirk Zimoch 2007

  37. Waiting for PV changes ("done"-flags, etc) • Use monitors instead of repeated gets (polling) • Polling can miss short pulses (e.g. off-on-off) • Polling wastes network bandwidth and server (IOC) resources. • Simple single-threaded solution • Monitor callback updates value • Loop over ca_pend_even(0.1) and check value. • Sophisticated multi-threaded solution • Monitor callback updates and checks value and triggers event semaphore. • Wait for event semaphore. Advanced EPICS Training, Dirk Zimoch 2007

  38. Caveats • Monitors trigger only at significant value changes. • The server decides what is significant. • Some servers don’t support monitors on all PVs. • You will not be informed when they change. • No monitor is sent when meta-data change (e.g. limits change) • This usually happen only on restart of the server. • Update meta-data in connection handler. • A monitor may miss intermediate values during rapid changes. • Happens when client or network are too slow. • But: It always gets the first and the last change. Advanced EPICS Training, Dirk Zimoch 2007

  39. What is forbidden in a monitor callback • You must not call ca_pend_io() or similar in callbacks. • Re-entrancy problem: callbacks are called from ca_pend_io(). • That means you can’t read via ca_get() from within a callback. • Workaround: Trigger (non-EPICS) event handler from callback that performs the ca_get(). • Or use monitors for everything. • You must not block inside a callback. • Only one callback runs at a time. • Blocking delays all other callbacks (get, monitor, connect, …) Advanced EPICS Training, Dirk Zimoch 2007

  40. Writing channels • Prepare write request • ca_array_put(type, elements, channel, pvalue) • type use a naked DBR_* type, if type does not match native DBF type, the value is converted on the server. • elements number of array elements to write, 1 for scalar values • channel the channel id • pvalue a pointer to the data to send • ca_put(type, channel, pvalue) • Same as above with elements=1 • Send write request, e.g. with ca_flush_io() • Send as many PVs as possible together. Advanced EPICS Training, Dirk Zimoch 2007

  41. Caveats • ca_put()/ca_flush_io() only sends data to the network layer. • It does not wait until … • actions on the server have been performed. • actions on the server have even been started. • the value has actually been written on the network cable. • It just promises that the current value will be sent in the near future unless the channel disconnects. • Intermediate values may be lost when values change rapidly. • When server or network is slow. • But: First and last value are always written Advanced EPICS Training, Dirk Zimoch 2007

  42. Synchronous put • Create a synchonous group • ca_sg_create(pgroup) • pgroup pointer to a group ID to be filled in (CA_SYNC_GID*) • Perform one or more puts inside synchonous group • ca_sg_array_put(group, type, elements, channel, pvalue) • group group ID • Wait until all puts in the same group have completed • ca_sg_block(group, timeoutSec) • Delete group • ca_sg_delete(group) Advanced EPICS Training, Dirk Zimoch 2007

  43. Synchronous put remarks • Creating and deleting synchronous groups is cheap. • Create and delete them on demand. • No need to store them somewhere globally. • The execution order inside a group is undefined. • Use separate groups and ca_sg_block() when oder matters. • If one put inside a group fails and ca_sg_block() times out, there is no way to find out which one failed. • The program is delayed while blocking • This may be inappropriate for (single-threaded) GUIs and servers • This is what you probably need for scripts. Advanced EPICS Training, Dirk Zimoch 2007

  44. Synchronous put versus asynchronous put • When to use synchronous puts • When time order matters. • First write parameters then write "start". • First write "start", then check "done". • When successful execution must be checked. • First write then read back and check severity. • When intermediate values must not be lost (sequence) • When to use asynchronous puts • When blocking is not allowed (e.g. GUI, server). • When many intermediate values are written (e.g. slider). Advanced EPICS Training, Dirk Zimoch 2007

  45. Put with callback • Prepare write request • ca_array_put_callback(type, elements, channel, pvalue, callback, usr) • type, elements, channel, pvalue are the same as for ca_array_put() • callback a function that is called when the put has completed on the server • usr arbitrary user data to be passed to callback function (void*) • Send write request(s) • ca_flush_io() • Receive callback • Callback function has the same form as a get callback. • In single-threaded model call ca_pend_event() or similar regularly. Advanced EPICS Training, Dirk Zimoch 2007

  46. Put with callback versus synchronous put • Put with callback does not delay the program. • You can still use event semaphores to wait for callbacks. • Response is channel specific. • You can wait for feedback in parallel but still on individual channels. • Synchronous groups only work on a per group basis and only one group after the other. • Programming effort is higher. • Callbacks, semaphores, timeouts must be implemented. • Use put with callback for GUIs and servers. • Use synchronous put for command line tools and scripts. Advanced EPICS Training, Dirk Zimoch 2007

  47. Exiting the program • Destroy the Channel Access context • ca_context_destroy() • This should be the first thing to do before any resources are freed. • All pending output is sent on the network. • All handlers / callbacks are disabled. • For multi-threaded clients it is important to clean up. • Avoids crash on exit, e.g when callbacks access buffers which are already deleted by another thread. Advanced EPICS Training, Dirk Zimoch 2007

  48. Exercise 2 • Modify the polling program from Exercise 1 to use monitors. • Wait without polling until a PV fulfills a condition. • Write 2 other programs that set 1000 different values with asynchonous put and with synchonous put. Verify with your monitoring program what happens to the PV. • Write a program that sets a value from user input and checks the written value for consistency and alarms. • Try PVs with different data types (floating point, string) Advanced EPICS Training, Dirk Zimoch 2007

  49. Channel Access Security • Remote PVs can be readonly or even unreadable. • CA provides functions to check access • ca_read_access(channel) returns 1 if readable • ca_write_access(channel) returns 1 if writable • CA provides a handler when access rights change • ca_replace_access_rights_event(channel, handler) • handler user supplied callback function • void accessHandler (struct access_rights_handler_args args) • args.chid channel ID • args.caar.read_access 1 if readable, 0 if not • args.caar.write_access 1 if writable, 0 if not Advanced EPICS Training, Dirk Zimoch 2007

  50. Channel Access details: Searching PVs • A client sends UDP packages to find PVs • Requests are repeated with decreasing rate until all PVs are found or 100 requests have been sent (after approx. 8 minutes) • Unresolved requests are re-issued when a new server starts. • E.g. when an IOC boots. • Default is to broadcast on all local network interfaces. • This is an expensive action. • All servers on the network have to check their list of PVs. • Many requests can be put into one package for efficiency. Advanced EPICS Training, Dirk Zimoch 2007