Provides an extensible and standardised framework for input-output devices.
Devices provide a c++ interface (usually on top of a lower level api such as posix) for input-output manipulation.
It's pretty hard to find a library that treats devices in anything but an ad-hoc way. There is no consistent interface. This attempts to bring that to the subset of devices that control systems use. It also allows hooking of streams to each and any of the devices.
Also of interest, there are a few very theoretical approaches to writing c++ devices. The ecl's first version too was along these lines, but ultimately for control systems, being practical wins over syntactic correctness.
The devices here are kept as consistent and practical as possible without sacrificing speed.
Include the following at the top of any translation unit which requires this library:
#include <ecl/devices.hpp> // Device Classes using ecl::OFile; using ecl::SharedFile; using ecl::Serial; using ecl::OConsole; // Also IConsole, EConsole, but dont use directly, use console streams instead. using ecl::String; // Dont use directly, use StringStream instead. using ecl::SocketClient; // Simple and does ipv4 only. using ecl::SocketServer; // Simple and does ipv4 only.
You will also need to link to -lecl_devices.
All devices have both RAII and non-RAII setup methods. In practice, this means you either bundle all configuration into the constructor, or you utilise the open() method to do configuration yourself. Usually RAII is the more ideal approach, but sometimes its inconvenient so the latter method is also available. For example, the serial class:
Serial serial_raii("/dev/ttyS0",BaudRate_115200,DataBits_8,StopBits_1,NoParity); // RAII Serial serial_nonraii; serial.open("/dev/ttyS0",BaudRate_115200,DataBits_8,StopBits_1,NoParity); // non-RAII
Cleanup is always done in the destructor, though if you need to manually open/close a device frequently, a close() method is also provided.
Some class are output devices (only write), others are input devices (only read) and some can do both. The read and write modes will sometimes be configurable, (e.g. timeout or non-blocking for serial reads), however the actual read and write operations will always be the same.
int n; char buffer[256]; n = source.read(buffer,256); n = sink.write("dude\n",5);
Essentially, a device class can be written in any way you please. However, if you wish to connect it to higher level components, in particular, streams, you must ensure you class satisfies certain device concepts. Refer to the documentation in ecl_concepts for more information.
This is the logger class. Since its primary purpose is to serve logging, the option to make it seekable was dropped to keep it nice and simple.
This is a multithreaded version of the SharedFile class. Multiple instances can open the same file (uniquely identified by a string) and each contains its own buffer that is utilised between flushing (this protects your output from getting tangled unnecessarily).
The most important thing to note with the serial class is that it really doesn't implement much of the underlying api. Rather it wraps a configuration appropriate for control and keeps it as simple as possible.
Of the possible read modes, it utilises only a timeout mode and a non-blocking mode. The other modes generally do not work very well at the speed that control loops need to run.
This is a virtual device used for storing and converting strings (similar to Converters, but more general). It is not intended for direct use, but as a mechanism for the stringstream class which functions very similarly to the c++ stringstream classes.
These are a very simple/rough implementation of ipv4. It isn't designed to be an industrial strength tool - just something for simple cross platform connections to enable quick and simple remote debugging program builds (or similar).
Of the possible read modes, it utilises only a timeout mode and a non-blocking mode. The other modes generally do not work very well at the speed that control loops need to run.