Example Simple Data Acquisition Unit¶
This is an example of a simple data acquisition unit that is put on network using caproto library. . The data comes from your computer onboard sensors e.g.: CPU utilization, battery capacity and memory utilization.
The example is purposely divided into several different files to explicitly show the modularity and hierarchy. The files(modules) are: driver, device, server, gui, and client.

The driver file contains one Driver class. The instantiation of the class connects to a data acquisition unit(this case on-board sensors). A simple read() function provides higher level command to retrieve data from the sensors. The result is returned as a numpy array, in this case 1x4 with entries sorted as following: time, CPU utilization in %, memory utilization in GB, battery capacity in %.
The next level in the hierarchy is device level. The device code consists of one Device class. The purpose of the device class is to collect data on a clock and put it in a circular buffer which can be accessed later. The initialization of the device instance creates circular buffer where the data from the data acquisition unit will be stored. This example does not take advantage of the circular buffer explicitly, but it can be used to expand the example in future and add more fields like mean CPU usage, etc.
The server code puts entire example on the network using caproto library. The server level data base (record) has six Process Variables(PVs): TIME, CPU, MEMORY, BATTERY, dt.
TIME - time of last read (UnixTime)
CPU - CPU utilization value during last read
MEMORY - MEMORY utilization value during last read
BATTERY - BATTERY utilization value during last read
dt - update frequency in seconds
During each cycle of data acquisition the record is updated via async queue. The update of the record triggers subsequent updates in all subscribed clients over the netowkr.
The GUI code uses wxPython in combination with PyEpics. The GUI code is heavily utilizing wxPython BoxSizers to make the code modular and hierarchical.
The client code is a simple example of line based communications. This example can be incorporate into a higher level IOCs that can talk to the lower level IOCs without GUI interface.
Example of usage¶
to test the driver code and device code separately.
from caproto_sandbox.simple_daq.driver import Driver
driver = Driver()
driver.read()
.. code-block:: python
> from caproto_sandbox.simple_daq.device import Device
> driver = Driver()
> device = Device(driver = driver)
> device.driver.read()
> device.buffer.pointer
-1
the circular buffer has no data. Now we can read once and chech the circular buffer.
> device.run_once() > device.buffer.pointer 0
You would need to open multiple terminal tabs in one window. But first start terminal and change directory to the location of the library.
In the first terminal tab,
> from caproto_sandbox.simple_daq.server import run_server > run_server()
In the second terminal tab,
> from caproto_sandbox.simple_daq.gui import run_gui > run_gui()
Below is the example of inline python shell client or what can be embedded into a higher level code.
> from caproto_sandbox.simple_daq.client import Client > client = Client() > client.cpu.read().data array([41.4])
Driver¶
Simple data acquisition driver example.
Device¶
Simple data acquisition device example.
Server (CA IOC)¶
Simple data acquisition device example.
Graphical User Interface¶
Graphical user interface module written in PyEpics and wxPython
Client¶
The line base client written in caproto
Unfortunately, On Friday April 29th 2022, developers of caproto announced that they are no longer available to maintaine the library and are looking for developers and maintainers.
There are four mentioned alternatives to the caproto library:
PyDevice https://github.com/klemenv/PyDevice
p4p (PVAccess) https://github.com/mdavidsaver/p4p
I have decided to check all four libraries and to make it more fun I will recreate my simple_daq caproto server with each library. My modular and hierarchical design should require me to rewrite only CA server and keep the rest of the code intact
PyDevice¶
It seems that PyDevice relies on EPICS base to be installed on the computer before it can be used.
from https://github.com/klemenv/PyDevice/issues/14
> these are the rough steps to get the demo IOC running from beginning:
>
> * download and compile EPICS base from https://epics.anl.gov/download/base/index.php
> * download PyDevice from this repo, ideally using one of the tagged versions like https://github.com/klemenv/PyDevice/releases/tag/R1.1.1
> * point PyDevice to your EPICS base folder by creating configure/RELEASE.local file with a single line, ie. `echo EPICS_BASE=/ics/epics/7.0.6.1/base > configure/RELEASE.local`
> * compile PyDevice with `make`
> * `cd iocBoot/iocpydev/`
> * start the IOC with `./st.cmd`
pyDevSup¶
This library seem to heavily rely on EPICS base as well.
pcaspy¶
Great library which can be used to create simple CA servers. I do have issues with creating a simple CA server after I had success. I am going to reboor the computer to see if I can get it work. It seems lacing documentation and there is not much tools available to debug.