Package: liteserver
liteserver 3.1.0Very Lightweight Data Object Server.
It hosts Lite Data Objects (LDO, analog of Process Variables in
EPICS) and provides info/set/get/read/subscribe remote access to them using
UDP protocol. Data encoding is implemented usingCBORspecification,
which makes it very fast and efficient.Data logging and retrievingData objects can be logged and retrieved using anapstrimpackage (https://pypi.org/project/apstrim).FeaturesSimplicity. The network protocol isUDP, error correction of
late/missing/mangled data is implemented. Binary serialization protocolCBOR.
Programming interface is very similar to JSON.Low latency, connection-less.Supported requests:info(), returns dictionary with information on requested LDOs and
parametersget(), returns dictionary of values of requested LDOs and parametersread(), returns dictionary of changed readable (non-constant)
parameters of requested LDOsset(), set values or attributes of requested LDO parameterssubscribe(callback), subscribe to a set of the objects, if any object
of the requested LDOs have been changed, the server will publish the changed
objects to client and the callback function on the client will be invoked.Multidimensional data (numpy arrays) are supported.Access control info (username, program name) supplied in every requestName servicefile-basednetwork-based using a dedicated liteServer  (not commissioned yet)Basic spreadsheet-based GUI:pypetoArchitectures. All programs are 100% python. Tested on Linux and partially on Windows.Companion applications:liteAccess: Access to liteServer'spvplot: Dynamic plotting toolapstrim: Data LoggerImagin: Image analysisSupported devicesServer implementations for various devices are located in .device sub-package.
A device server can be started using following command:python3 -m liteserv.device.device.litePeakSimulator: Waveform simulator with multiple peaks and a background noise.device.liteScaler: Test implementation of the liteServer,
supporting 1000 of up/down counters as well as multi-dimensional arrays.device.senstation: Server for various devices, connected to Raspberry Pi
GPIOs: 1-wire temperature sensor, Pulse Counter, Fire alarm and Spark detector,
Buzzer, RGB LED indicator, OmegaBus serial sensors.
Various I2C devices: ADC: ADS1x15, Magnetometers: MMC5983MA, HMC5883, QMC5983,
TLV493D.
I2C multiplexing using TCA9548 or PCA9546.
NUCLEO-STM33 mixed signal MCU boards, connected to Raspberry Pi over USB.device.liteGQ: Geiger Counter and a gyro sensor GMC-500 from GQ Electronics.device.liteWLM: Wavelength Meter WS6-600 from HighFinesse.device.liteLabjack: LabJack U3 analog and digital IO module.device.liteUSBCam: Server for USB cameras.device.liteUvcCam: Server for USB cameras using UVC library.device.liteVGM: (Obsolete) Server for multiple gaussmeters from AlphaLab Inc.InstallationDependencies:Python3 3.6 or higher.CBOR2Installation:python3 -m pip install liteserverAdditional libraries may be required for specific devices.ExamplesMost convenient way to test a base class functionality is by usingipython3,Test server: liteScalerStart liteScaler on a local host:python -m liteserver.device.liteScaler -iloTo monitor, use:python -m pvplot L:localhost:dev1:countersPeak simulatorpython -m liteserver.device.litePeakSimulator -iloTo monitor, use:python -m pvplot -s.01 -a'L:localhost:dev1' 'x,y'Labjack U3-HVpython -m liteserver.device.liteLabjack -iloTo monitor, use:python -m pvplot -a'L:localhost:dev1' 'tempU3 ADC_HV[0] ADC_HV[1] ADC_HV[2] ADC_HV[3] ADC_LV'Server for all supported peripherals: senstation:I2C SupportTo detect available devices on the multiplexed I2C chain:python -m utils.i2cmux -M 112If multiplexer address on your board is not 112, you can find it using:i2cdetect -y 1Start the senstation serverStart the senstation server through default network interface:python -m liteserver.device.senstationInterfacing to senstation using pythonfromliteserverimportliteAccessasLAfrompprintimportpprintHost='localhost'LAserver=Host+':server'LAdev1=Host+':dev1'LAdev2=Host+':dev2'#``````````````````Programmatic way, using Access`````````````````````````````LA.Access.info((Host+':*','*'))# map of all devices and parameters the HostLA.Access.info((LAserver,'*'))LA.Access.get((LAserver,'*'))LA.Access.set((LAdev1,'frequency',2.0))LA.Access.subscribe(LA.testCallback,(LAdev1,'cycle'))LA.Access.unsubscribe()#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#``````````````````Object-oriented way````````````````````````````````````````# Advantage: The previuosly created PVs are reused.allServerParameters=LA.PVs((LAserver,'*'))pprint(allServerParameters.info())pprint(allServerParameters.get())# get all parameters from device LAserver# get all readable parameters from device Scaler1:server, which have been# modified since the last read:pprint(allServerParameters.read())allDev1Parameters=LA.PVs((LAdev1,'*'))print(allDev1Parameters.info())server_performance=LA.PVs((LAserver,'perf'))pprint(server_performance.info())pprint(server_performance.get())# simplified get: returns (value,timestamp) of a parameter 'perf'pprint(server_performance.value)server_multiple_parameters=LA.PVs((LAserver,('perf','run')))pprint(server_multiple_parameters.info())pprint(server_multiple_parameters.get())server_multiple_devPars=LA.PVs((LAdev1,('time','frequency')),(LAserver,('statistics','perf')))pprint(server_multiple_devPars.get())# settingdev1_frequency=LA.PVs((LAdev1,'frequency'))dev1_frequency.set([1.5])dev1_frequency.valuedev1_multiple_parameters=LA.PVs([LAdev1,('frequency','coordinate')])dev1_multiple_parameters.set([8.,[3.,4.]])# subscribingldo=LA.PVs([LAdev1,'cycle'])ldo.subscribe()# it will print image data periodicallyldo.unsubscribe()# cancel the subscruption# test for timeout, should timeout in 10s:#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,#``````````````````Observations```````````````````````````````````````````````TimingofAccess.getusingipythononlocalhost.fromliteserverimportliteAccessasLAHost='localhost'LAdev1=Host+':dev1'%timeitimage=LA.Access.get((LAdev1,['image']))145µs±1.95µsperloop(mean±std.dev.of7runs,10000loopseach)image[(LAdev1,'image')]['value'].shape(120,160,3)Retrievingtimeof57600values(120*160*3)is145µs,whichcorrespondsto400mValues/sRetrievingtimeof57600values(120*160*3)220µs,whichcorrespondsto260MValues/s(onentry-levelworkstation).Itwas400MValues/sontop-levelworkstation.Note:Msgpackwas4%faster.#``````````````````Tips```````````````````````````````````````````````````````# To enable debugging: LA.PVs.Dbg = True# To enable transaction timing: LA.Channel.Perf = True