mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-16 06:47:14 +02:00
Compare commits
22 Commits
2020.03.11
...
2020.03.18
Author | SHA1 | Date | |
---|---|---|---|
cb8403f1b0 | |||
b751238fc1 | |||
5479d3a198 | |||
e1768905dd | |||
775d0842e9 | |||
e7e201bd2a | |||
ec9f8305e9 | |||
3307bfab1b | |||
ce2c62000d | |||
cf817c4ec1 | |||
bd01a5f2d2 | |||
b059ba7c90 | |||
89d70097f6 | |||
41d115a394 | |||
45c1d3a553 | |||
17227be4df | |||
7f4f8e8f09 | |||
6809bd6567 | |||
711d40a56e | |||
81911fae3c | |||
f940397e3a | |||
dc53887a48 |
@ -203,11 +203,9 @@ if(SLS_BUILD_DOCS)
|
||||
add_subdirectory(docs)
|
||||
endif(SLS_BUILD_DOCS)
|
||||
|
||||
|
||||
|
||||
if(SLS_MASTER_PROJECT)
|
||||
# Set install dir CMake packages
|
||||
set(CMAKE_INSTALL_DIR ${CMAKE_INSTALL_DATADIR}/cmake/sls)
|
||||
set(CMAKE_INSTALL_DIR "share/cmake/${PROJECT_NAME}")
|
||||
# Set the list of exported targets
|
||||
set(PROJECT_LIBRARIES slsSupportLib slsDetectorShared slsReceiverShared)
|
||||
# Generate and install package config file and version
|
||||
|
@ -15,17 +15,20 @@ configure_package_config_file(
|
||||
write_basic_package_version_file(
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config.cmake"
|
||||
"${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake"
|
||||
COMPONENT devel
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME_LOWER})
|
||||
DESTINATION ${CMAKE_INSTALL_DIR}
|
||||
)
|
||||
|
||||
if (PROJECT_LIBRARIES OR PROJECT_STATIC_LIBRARIES)
|
||||
install(
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
FILE ${PROJECT_NAME_LOWER}-targets.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME_LOWER})
|
||||
DESTINATION ${CMAKE_INSTALL_DIR}
|
||||
)
|
||||
endif ()
|
||||
|
@ -5,18 +5,20 @@ mkdir $PREFIX/include
|
||||
mkdir $PREFIX/include/slsDetectorPackage
|
||||
|
||||
#Shared and static libraries
|
||||
cp build/bin/libSlsDetector.so $PREFIX/lib/.
|
||||
cp build/bin/libSlsReceiver.so $PREFIX/lib/.
|
||||
cp build/bin/libSlsSupport.so $PREFIX/lib/.
|
||||
# cp build/bin/libSlsDetector.so $PREFIX/lib/.
|
||||
# cp build/bin/libSlsReceiver.so $PREFIX/lib/.
|
||||
# cp build/bin/libSlsSupport.so $PREFIX/lib/.
|
||||
|
||||
cp build/install/lib/* $PREFIX/lib/
|
||||
|
||||
#Binaries
|
||||
cp build/bin/sls_detector_acquire $PREFIX/bin/.
|
||||
cp build/bin/sls_detector_get $PREFIX/bin/.
|
||||
cp build/bin/sls_detector_put $PREFIX/bin/.
|
||||
cp build/bin/sls_detector_help $PREFIX/bin/.
|
||||
cp build/bin/slsReceiver $PREFIX/bin/.
|
||||
cp build/bin/slsMultiReceiver $PREFIX/bin/.
|
||||
cp build/install/bin/sls_detector_acquire $PREFIX/bin/.
|
||||
cp build/install/bin/sls_detector_get $PREFIX/bin/.
|
||||
cp build/install/bin/sls_detector_put $PREFIX/bin/.
|
||||
cp build/install/bin/sls_detector_help $PREFIX/bin/.
|
||||
cp build/install/bin/slsReceiver $PREFIX/bin/.
|
||||
cp build/install/bin/slsMultiReceiver $PREFIX/bin/.
|
||||
|
||||
#Which headers do we need for development??
|
||||
cp build/install/include/* $PREFIX/include/slsDetectorPackage/
|
||||
# cp include/some_lib.h $PREFIX/include/.
|
||||
|
||||
cp build/install/include/* $PREFIX/include/
|
||||
cp -r build/install/share/ $PREFIX/share
|
||||
|
@ -7,7 +7,7 @@ source:
|
||||
- path: ..
|
||||
|
||||
build:
|
||||
number: 2
|
||||
number: 0
|
||||
binary_relocation: True
|
||||
rpaths:
|
||||
- lib/
|
||||
@ -37,6 +37,7 @@ requirements:
|
||||
host:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
- zeromq
|
||||
- xorg-libx11
|
||||
- xorg-libice
|
||||
- xorg-libxext
|
||||
@ -46,6 +47,7 @@ requirements:
|
||||
- xorg-libxfixes
|
||||
|
||||
run:
|
||||
- zeromq
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
|
||||
|
@ -3,7 +3,7 @@ find_package(Sphinx)
|
||||
|
||||
|
||||
if (DOXYGEN_FOUND AND SPHINX_FOUND)
|
||||
message(${CMAKE_PROJECT_SORURCE_DIR}/slsDetectorSoftware/src)
|
||||
# message(${CMAKE_PROJECT_SORURCE_DIR}/slsDetectorSoftware/src)
|
||||
# Utility to generate command line documentation
|
||||
add_executable(gendoc src/gendoc.cpp)
|
||||
# This is a bit hacky, but better than exposing stuff?
|
||||
@ -30,6 +30,7 @@ if (DOXYGEN_FOUND AND SPHINX_FOUND)
|
||||
set(SPHINX_SOURCE_FILES
|
||||
src/commandline.rst
|
||||
src/container_utils.rst
|
||||
src/consuming.rst
|
||||
src/dependencies.rst
|
||||
src/detector.rst
|
||||
src/index.rst
|
||||
@ -41,6 +42,7 @@ if (DOXYGEN_FOUND AND SPHINX_FOUND)
|
||||
src/result.rst
|
||||
src/type_traits.rst
|
||||
src/ToString.rst
|
||||
src/examples.rst
|
||||
|
||||
)
|
||||
|
||||
|
95
docs/src/consuming.rst
Normal file
95
docs/src/consuming.rst
Normal file
@ -0,0 +1,95 @@
|
||||
Consuming slsDetectorPackage
|
||||
===============================
|
||||
|
||||
Depending on how you want to build your integration with
|
||||
slsDetectorPackage there are a few different ways to
|
||||
consume our package. The recommended way is to use one of the
|
||||
CMake approaches.
|
||||
|
||||
|
||||
|
||||
CMake: slsDetectorPackage as submodule in your project
|
||||
---------------------------------------
|
||||
|
||||
If you are using CMake to build your integration and want to build everything
|
||||
in one go, we support adding slsDetectorPackage as a subfolder in your cmake project.
|
||||
|
||||
A minimal CMakeLists.txt could look like this:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
project(myDetectorIntegration)
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
add_subdirectory(slsDetectorPackage)
|
||||
|
||||
#Add your executable
|
||||
add_executable(example main.cpp)
|
||||
target_compile_features(example PRIVATE cxx_std_11)
|
||||
|
||||
#Link towards slsDetectorShared
|
||||
target_link_libraries(example slsDetectorShared)
|
||||
|
||||
A fully working example can be found at:
|
||||
|
||||
https://github.com/slsdetectorgroup/cmake-subfolder-example
|
||||
|
||||
|
||||
CMake: find_package(slsDetectorPackage)
|
||||
------------------------------------------
|
||||
|
||||
If you have compiled and installed slsDetectorPackage we also support
|
||||
find_package in CMake. If installed in a system wide location no path
|
||||
should be needed, otherwise specify cmake prefix path.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(myintegration)
|
||||
|
||||
find_package(slsDetectorPackage 5.0 REQUIRED)
|
||||
add_executable(example main.cpp)
|
||||
target_link_libraries(example slsDetectorShared)
|
||||
|
||||
|
||||
Then assuming the slsDetectorPackage is installed in /path/to/sls/install
|
||||
you should be able to configure and build your project in this way.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cmake ../path/to/your/source -DCMAKE_PREFIX_PATH=/path/to/sls/install
|
||||
make
|
||||
|
||||
|
||||
A minimal example is available at: https://github.com/slsdetectorgroup/minimal-cmake
|
||||
|
||||
No tools minimal approach
|
||||
-----------------------------
|
||||
|
||||
While not recommended it is still possible to specify the include and library paths
|
||||
manually when invoking g++. This can sometimes be handy for a quick try.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "Detector.h"
|
||||
#include <iostream>
|
||||
int main(){
|
||||
|
||||
sls::Detector det;
|
||||
|
||||
//Get all values and print them
|
||||
std::cout << "Hostname: " << det.getHostname() << "\n";
|
||||
std::cout << "Type: " << det.getDetectorType() << "\n";
|
||||
std::cout << "Udp ip: " << det.getSourceUDPIP() << "\n";
|
||||
|
||||
|
||||
//Get mac addr
|
||||
const int module = 0;
|
||||
auto mac = det.getSourceUDPMAC()[module];
|
||||
std::cout << "Mac addr of module "<< module << " is " << mac.str() << '\n';
|
||||
|
||||
}
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
g++ -I/install/path/include/ -L/install/path/lib64/ myapp.cpp -lSlsDetector -lSlsSupport -Wl,-rpath=../install/path/lib64
|
@ -13,7 +13,7 @@ To use the basic building blocks, meaning sls_detector_get/put and
|
||||
the shared libraries these are needed:
|
||||
|
||||
* Linux, preferably recent kernel (currently no cross platform support)
|
||||
* CMake > 3.9
|
||||
* CMake > 3.12
|
||||
* C++11 compatible compiler. (We test with gcc and clang)
|
||||
* ZeroMQ version 4
|
||||
|
||||
@ -24,7 +24,7 @@ GUI
|
||||
The GUI is currently using Qt4 but watch out for an upgrade to 5.
|
||||
|
||||
* Qt 4.8
|
||||
* Qwt 6
|
||||
* Qwt 6.1
|
||||
|
||||
-----------------------
|
||||
Python bindings
|
||||
|
115
docs/src/examples.rst
Normal file
115
docs/src/examples.rst
Normal file
@ -0,0 +1,115 @@
|
||||
|
||||
|
||||
|
||||
Examples
|
||||
===========
|
||||
|
||||
Setup
|
||||
------------
|
||||
|
||||
The examples here assume that you have compiled and installed slsDetectorPackage
|
||||
to ~/sls/install and that the option for SLS_USE_SIMULATOR was enabled. This also builds
|
||||
the virtual detector servers that we will be using for testing.
|
||||
|
||||
We also add ~/sls/detector/install/bin to the path for convenience.
|
||||
|
||||
Compile examples
|
||||
-------------------
|
||||
|
||||
The source code of the examples is available at:
|
||||
https://github.com/slsdetectorgroup/api-examples
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/slsdetectorgroup/api-examples.git
|
||||
mkdir build && cd build
|
||||
cmake ../api-examples -DCMAKE_PREFIX_PATH=~/sls/detector/install
|
||||
make
|
||||
|
||||
Below follows a short description of what is included in the examples.
|
||||
|
||||
|
||||
Running a config file [e1]
|
||||
-----------------------------
|
||||
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "Detector.h"
|
||||
...
|
||||
sls::Detector det;
|
||||
det.loadConfig("path/to/config/file.config");
|
||||
|
||||
|
||||
|
||||
To configure the connection between PC and detector the easiest
|
||||
is to run a config file. For this example we first launch a virtual Jungfrau server and
|
||||
then set up the detector.
|
||||
|
||||
**Launch a virtual detector server**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
jungfrauDetectorServer_virtual
|
||||
|
||||
This launches a virtual Jungfrau detector server. As default is uses port 1952 and 1953
|
||||
for communication over TCP. Most commands go on 1952 and only stop and status on 1953.
|
||||
|
||||
**Run example to configure**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./e1-config one_det_no_receiver.config
|
||||
- 12:01:06.371 INFO: Shared memory deleted /slsDetectorPackage_multi_0_sls_0
|
||||
- 12:01:06.371 INFO: Shared memory deleted /slsDetectorPackage_multi_0
|
||||
- 12:01:06.372 INFO: Shared memory created /slsDetectorPackage_multi_0
|
||||
- 12:01:06.376 INFO: Loading configuration file: one_det_no_receiver.config
|
||||
- 12:01:06.376 INFO: Adding detector localhost
|
||||
- 12:01:06.377 INFO: Shared memory created /slsDetectorPackage_multi_0_sls_0
|
||||
- 12:01:06.377 INFO: Checking Detector Version Compatibility
|
||||
- 12:01:06.378 INFO: Detector connecting - updating!
|
||||
hostname [localhost]
|
||||
|
||||
|
||||
Jungfrau detector with 1 modules configured
|
||||
|
||||
|
||||
Using the return type sls::Result [e2]
|
||||
-----------------------------------------
|
||||
|
||||
Since many our detectors have multiple modules we cannot return
|
||||
a single value when reading from the Detector. Hostname, Ip and also
|
||||
for example exposure time can differ between modules.
|
||||
|
||||
Therefore we return Result<T> which is a thin wrapper around
|
||||
std::vector.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
sls::Result<int> res1{1, 1, 1};
|
||||
std::cout << "res1: " << res1 << '\n';
|
||||
res1.squash();
|
||||
res1.squash(-1);
|
||||
|
||||
|
||||
|
||||
Setting exposure time [e3]
|
||||
-----------------------------------------
|
||||
|
||||
For setting times, like exposure time, period, delay etc.
|
||||
we use std::chrono::duration.
|
||||
|
||||
Example 3 shows how to set and read exposure time as well
|
||||
as converting to floating point.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "Detector.h"
|
||||
#include <chrono>
|
||||
...
|
||||
std::chrono::microseconds t0{500};
|
||||
det.setExptime(t0);
|
||||
|
||||
|
||||
|
@ -6,12 +6,18 @@
|
||||
Welcome to slsDetectorPackage's documentation!
|
||||
==============================================
|
||||
|
||||
.. note ::
|
||||
|
||||
This is the documentation for the latest development version of slsDetectorPackage
|
||||
For documentation on current and previous releases visit the official page: https://www.psi.ch/en/detectors/documentation
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Installation:
|
||||
|
||||
installation
|
||||
dependencies
|
||||
consuming
|
||||
|
||||
.. toctree::
|
||||
:caption: C++ API
|
||||
@ -20,6 +26,7 @@ Welcome to slsDetectorPackage's documentation!
|
||||
detector
|
||||
result
|
||||
receiver
|
||||
examples
|
||||
|
||||
.. toctree::
|
||||
:caption: Python API
|
||||
|
@ -2,4 +2,24 @@
|
||||
Installation
|
||||
==============================================
|
||||
|
||||
get the source etc.
|
||||
Build from source using CMake
|
||||
---------------------------------
|
||||
|
||||
.. note ::
|
||||
|
||||
The default branch of our git repository is developer. It contains the
|
||||
latest development version. It is expected to compile and work but
|
||||
features might be added or tweaked. In some cases the API might also change
|
||||
without being communicated. If absolute stability of the API is needed please
|
||||
use one of the release versions.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git
|
||||
mkdir build && cd build
|
||||
cmake ../slsDetectorPackage -DCMAKE_INSTALL_PREFIX=/your/install/path
|
||||
make -j12
|
||||
make install
|
||||
|
||||
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
Detector
|
||||
=====================================================
|
||||
|
||||
.. py:currentmodule:: sls_detector
|
||||
.. py:currentmodule:: slsdet
|
||||
|
||||
.. autoclass:: ExperimentalDetector
|
||||
.. autoclass:: Detector
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
@ -45,7 +45,7 @@ ext_modules = [
|
||||
# get_pybind_include(),
|
||||
# get_pybind_include(user=True),
|
||||
os.path.join('../libs/pybind11/include'),
|
||||
os.path.join(get_conda_path(), 'include/slsDetectorPackage'),
|
||||
os.path.join(get_conda_path(), 'include'),
|
||||
|
||||
],
|
||||
libraries=['SlsDetector', 'SlsReceiver', 'zmq'],
|
||||
|
@ -103,10 +103,10 @@ set_target_properties(slsDetectorGui PROPERTIES
|
||||
)
|
||||
|
||||
install(TARGETS slsDetectorGui
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
# EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
# ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
# PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "SlsQt2DPlot.h"
|
||||
#include "ansi.h"
|
||||
// #include "ansi.h"
|
||||
|
||||
#include <qlist.h>
|
||||
#include <qprinter.h>
|
||||
|
Binary file not shown.
@ -47,9 +47,10 @@ int injectedChannelsIncrement = 0;
|
||||
int vetoReference[NCHIP][NCHAN];
|
||||
uint8_t adcConfiguration[NCHIP][NADC];
|
||||
int burstMode = BURST_INTERNAL;
|
||||
int64_t numTriggers = 1;
|
||||
int64_t numBursts = 1;
|
||||
int64_t burstPeriodNs = 0;
|
||||
int64_t numTriggersReg = 1;
|
||||
int64_t delayReg = 0;
|
||||
int64_t numBurstsReg = 1;
|
||||
int64_t burstPeriodReg = 0;
|
||||
int detPos[2] = {};
|
||||
|
||||
int isInitCheckDone() {
|
||||
@ -354,9 +355,10 @@ void setupDetector() {
|
||||
injectedChannelsOffset = 0;
|
||||
injectedChannelsIncrement = 0;
|
||||
burstMode = BURST_INTERNAL;
|
||||
numTriggers = 1;
|
||||
numBursts = 1;
|
||||
burstPeriodNs = 0;
|
||||
numTriggersReg = 1;
|
||||
delayReg = 0;
|
||||
numBurstsReg = 1;
|
||||
burstPeriodReg = 0;
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < NUM_CLOCKS; ++i) {
|
||||
@ -736,32 +738,31 @@ int setDynamicRange(int dr){
|
||||
/* parameters - timer */
|
||||
void setNumFrames(int64_t val) {
|
||||
if (val > 0) {
|
||||
LOG(logINFO, ("Setting number of frames %lld [local]\n", val));
|
||||
// continuous mode
|
||||
if (burstMode == BURST_OFF) {
|
||||
setNumFramesCont(val);
|
||||
setNumFramesBurst(1);
|
||||
LOG(logINFO, ("Setting number of frames %lld [Continuous mode]\n", val));
|
||||
set64BitReg(val, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
} else {
|
||||
setNumFramesBurst(val);
|
||||
setNumFramesCont(1);
|
||||
LOG(logINFO, ("Setting number of frames %d [Burst mode]\n", (int)val));
|
||||
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) &~ ASIC_INT_FRAMES_MSK);
|
||||
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) | (((int)val << ASIC_INT_FRAMES_OFST) & ASIC_INT_FRAMES_MSK));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t getNumFrames() {
|
||||
if (burstMode == BURST_OFF) {
|
||||
return getNumFramesCont();
|
||||
return get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
} else {
|
||||
return getNumFramesBurst();
|
||||
return ((bus_r(ASIC_INT_FRAMES_REG) & ASIC_INT_FRAMES_MSK) >> ASIC_INT_FRAMES_OFST);
|
||||
}
|
||||
}
|
||||
|
||||
void setNumTriggers(int64_t val) {
|
||||
if (val > 0) {
|
||||
LOG(logINFO, ("Setting number of triggers %lld\n", val));
|
||||
numTriggers = val;
|
||||
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
|
||||
LOG(logINFO, ("\tBurst and Auto mode: not writing #triggers to register\n"));
|
||||
if (getTiming() == AUTO_TIMING) {
|
||||
LOG(logINFO, ("\tNot trigger mode: not writing to register\n"));
|
||||
numTriggersReg = val;
|
||||
} else {
|
||||
set64BitReg(val, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
|
||||
}
|
||||
@ -769,8 +770,8 @@ void setNumTriggers(int64_t val) {
|
||||
}
|
||||
|
||||
int64_t getNumTriggers() {
|
||||
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
|
||||
return numTriggers;
|
||||
if (getTiming() == AUTO_TIMING) {
|
||||
return numTriggersReg;
|
||||
}
|
||||
return get64BitReg(SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
|
||||
}
|
||||
@ -778,20 +779,20 @@ int64_t getNumTriggers() {
|
||||
void setNumBursts(int64_t val) {
|
||||
if (val > 0) {
|
||||
LOG(logINFO, ("Setting number of bursts %lld\n", val));
|
||||
numBursts = val;
|
||||
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
|
||||
set64BitReg(val, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
|
||||
set64BitReg(val, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
} else {
|
||||
LOG(logINFO, ("\tNot (Burst and Auto mode): not writing #bursts to register\n"));
|
||||
LOG(logINFO, ("\tNot (Burst and Auto mode): not writing to register\n"));
|
||||
numBurstsReg = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t getNumBursts() {
|
||||
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
|
||||
return get64BitReg(SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
|
||||
return get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
}
|
||||
return numBursts;
|
||||
return numBurstsReg;
|
||||
}
|
||||
|
||||
int setExpTime(int64_t val) {
|
||||
@ -799,17 +800,21 @@ int setExpTime(int64_t val) {
|
||||
LOG(logERROR, ("Invalid exptime: %lld ns\n", val));
|
||||
return FAIL;
|
||||
}
|
||||
LOG(logINFO, ("Setting exptime %lld ns [local]\n", val));
|
||||
// continuous mode
|
||||
if (burstMode == BURST_OFF) {
|
||||
return setExptimeCont(val);
|
||||
} else {
|
||||
return setExptimeBurst(val);
|
||||
}
|
||||
LOG(logINFO, ("Setting exptime %lld ns\n", val));
|
||||
val *= (1E-9 * systemFrequency);
|
||||
set64BitReg(val, ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG);
|
||||
|
||||
// validate for tolerance
|
||||
int64_t retval = getExpTime();
|
||||
val /= (1E-9 * systemFrequency);
|
||||
if (val != retval) {
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int64_t getExpTime() {
|
||||
return getExptimeBoth();
|
||||
return get64BitReg(ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG) / (1E-9 * systemFrequency);
|
||||
}
|
||||
|
||||
int setPeriod(int64_t val) {
|
||||
@ -817,110 +822,31 @@ int setPeriod(int64_t val) {
|
||||
LOG(logERROR, ("Invalid period: %lld ns\n", val));
|
||||
return FAIL;
|
||||
}
|
||||
LOG(logINFO, ("Setting period %lld ns [local]\n", val));
|
||||
// continuous mode
|
||||
val *= (1E-9 * systemFrequency);
|
||||
if (burstMode == BURST_OFF) {
|
||||
setPeriodBurst(0);
|
||||
return setPeriodCont(val);
|
||||
LOG(logINFO, ("Setting period %lld ns [Continuous mode]\n", val));
|
||||
set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
} else {
|
||||
//setPeriodCont(0);
|
||||
return setPeriodBurst(val);
|
||||
LOG(logINFO, ("Setting period %lld ns [Burst mode]\n", val));
|
||||
set64BitReg(val, ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
|
||||
}
|
||||
// validate for tolerance
|
||||
int64_t retval = getPeriod();
|
||||
val /= (1E-9 * systemFrequency);
|
||||
if (val != retval) {
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int64_t getPeriod() {
|
||||
if (burstMode == BURST_OFF) {
|
||||
return getPeriodCont();
|
||||
return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
|
||||
} else {
|
||||
return getPeriodBurst();
|
||||
return get64BitReg(ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
|
||||
}
|
||||
}
|
||||
|
||||
void setNumFramesBurst(int64_t val) {
|
||||
LOG(logINFO, ("Setting number of frames %d [Burst mode]\n", (int)val));
|
||||
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) &~ ASIC_INT_FRAMES_MSK);
|
||||
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) | (((int)val << ASIC_INT_FRAMES_OFST) & ASIC_INT_FRAMES_MSK));
|
||||
}
|
||||
|
||||
int64_t getNumFramesBurst() {
|
||||
return ((bus_r(ASIC_INT_FRAMES_REG) & ASIC_INT_FRAMES_MSK) >> ASIC_INT_FRAMES_OFST);
|
||||
}
|
||||
|
||||
void setNumFramesCont(int64_t val) {
|
||||
LOG(logINFO, ("Setting number of frames %lld [Continuous mode]\n", val));
|
||||
set64BitReg(val, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
}
|
||||
|
||||
int64_t getNumFramesCont() {
|
||||
return get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
}
|
||||
|
||||
int setExptimeBurst(int64_t val) {
|
||||
LOG(logINFO, ("Setting exptime %lld ns [Burst mode]\n", val));
|
||||
return setExptimeBoth(val);
|
||||
}
|
||||
|
||||
int setExptimeCont(int64_t val) {
|
||||
LOG(logINFO, ("Setting exptime %lld ns [Continuous mode]\n", val));
|
||||
return setExptimeBoth(val);
|
||||
}
|
||||
|
||||
int setExptimeBoth(int64_t val) {
|
||||
val *= (1E-9 * systemFrequency);
|
||||
set64BitReg(val, ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG);
|
||||
|
||||
// validate for tolerance
|
||||
int64_t retval = getExptimeBoth();
|
||||
val /= (1E-9 * systemFrequency);
|
||||
if (val != retval) {
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int64_t getExptimeBoth() {
|
||||
return get64BitReg(ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG) / (1E-9 * systemFrequency);
|
||||
}
|
||||
|
||||
|
||||
int setPeriodBurst(int64_t val) {
|
||||
LOG(logINFO, ("Setting period %lld ns [Burst mode]\n", val));
|
||||
val *= (1E-9 * systemFrequency);
|
||||
set64BitReg(val, ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
|
||||
|
||||
// validate for tolerance
|
||||
int64_t retval = getPeriodBurst();
|
||||
val /= (1E-9 * systemFrequency);
|
||||
if (val != retval) {
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int64_t getPeriodBurst() {
|
||||
LOG(logDEBUG, ("Getting period [Burst mode]\n"));
|
||||
return get64BitReg(ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
|
||||
}
|
||||
|
||||
int setPeriodCont(int64_t val) {
|
||||
LOG(logINFO, ("Setting period %lld ns [Continuous mode]\n", val));
|
||||
val *= (1E-9 * systemFrequency);
|
||||
set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
|
||||
// validate for tolerance
|
||||
int64_t retval = getPeriodCont();
|
||||
val /= (1E-9 * systemFrequency);
|
||||
if (val != retval) {
|
||||
return FAIL;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int64_t getPeriodCont() {
|
||||
LOG(logDEBUG, ("Getting period [Continuous mode]\n"));
|
||||
return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
|
||||
}
|
||||
|
||||
int setDelayAfterTrigger(int64_t val) {
|
||||
if (val < 0) {
|
||||
LOG(logERROR, ("Invalid delay after trigger: %lld ns\n", val));
|
||||
@ -928,8 +854,12 @@ int setDelayAfterTrigger(int64_t val) {
|
||||
}
|
||||
LOG(logINFO, ("Setting delay after trigger %lld ns\n", val));
|
||||
val *= (1E-9 * systemFrequency);
|
||||
set64BitReg(val, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
|
||||
|
||||
if (getTiming() == AUTO_TIMING) {
|
||||
LOG(logINFO, ("\tNot trigger mode: not writing to register\n"));
|
||||
delayReg = val;
|
||||
} else {
|
||||
set64BitReg(val, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
|
||||
}
|
||||
// validate for tolerance
|
||||
int64_t retval = getDelayAfterTrigger();
|
||||
val /= (1E-9 * systemFrequency);
|
||||
@ -940,6 +870,9 @@ int setDelayAfterTrigger(int64_t val) {
|
||||
}
|
||||
|
||||
int64_t getDelayAfterTrigger() {
|
||||
if (getTiming() == AUTO_TIMING) {
|
||||
return delayReg / (1E-9 * systemFrequency);
|
||||
}
|
||||
return get64BitReg(SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG) / (1E-9 * systemFrequency);
|
||||
}
|
||||
|
||||
@ -949,12 +882,12 @@ int setBurstPeriod(int64_t val) {
|
||||
return FAIL;
|
||||
}
|
||||
LOG(logINFO, ("Setting burst period %lld ns\n", val));
|
||||
burstPeriodNs = val;
|
||||
val *= (1E-9 * systemFrequency);
|
||||
if (burstMode != BURST_OFF) {
|
||||
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
|
||||
set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
} else {
|
||||
LOG(logINFO, ("\t(Continuous mode): not writing burst period to register\n"));
|
||||
LOG(logINFO, ("\tNot (Burst and Auto mode): not writing to register\n"));
|
||||
burstPeriodReg = val;
|
||||
}
|
||||
|
||||
// validate for tolerance
|
||||
@ -967,10 +900,10 @@ int setBurstPeriod(int64_t val) {
|
||||
}
|
||||
|
||||
int64_t getBurstPeriod() {
|
||||
if (burstMode != BURST_OFF) {
|
||||
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) {
|
||||
return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG) / (1E-9 * systemFrequency);
|
||||
}
|
||||
return burstPeriodNs;
|
||||
return burstPeriodReg / (1E-9 * systemFrequency);
|
||||
}
|
||||
|
||||
int64_t getNumFramesLeft() {
|
||||
@ -1185,6 +1118,18 @@ int setHighVoltage(int val){
|
||||
|
||||
/* parameters - timing */
|
||||
void setTiming( enum timingMode arg){
|
||||
// update
|
||||
// trigger
|
||||
if (getTiming() == TRIGGER_EXPOSURE) {
|
||||
numTriggersReg = get64BitReg(SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
|
||||
delayReg = get64BitReg(SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
|
||||
}
|
||||
// auto and burst
|
||||
else if (burstMode != BURST_OFF) {
|
||||
numBurstsReg = get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
burstPeriodReg = get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
}
|
||||
|
||||
switch(arg){
|
||||
case AUTO_TIMING:
|
||||
LOG(logINFO, ("Set Timing: Auto\n"));
|
||||
@ -1198,9 +1143,32 @@ void setTiming( enum timingMode arg){
|
||||
LOG(logERROR, ("Unknown timing mode %d\n", arg));
|
||||
}
|
||||
|
||||
LOG(logINFO, ("\tUpdating trigger/burst and delay/burst period registers\n"))
|
||||
setNumTriggers(numTriggers);
|
||||
setNumBursts(numBursts);
|
||||
LOG(logINFO, ("\tUpdating registers\n"))
|
||||
// trigger
|
||||
if (getTiming() == TRIGGER_EXPOSURE) {
|
||||
set64BitReg(numTriggersReg, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
|
||||
set64BitReg(delayReg, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
|
||||
LOG(logINFO, ("\tTriggers reg: %lld, Delay reg: %lldns\n", getNumTriggers(), getDelayAfterTrigger()));
|
||||
// burst
|
||||
if (burstMode != BURST_OFF) {
|
||||
LOG(logINFO, ("\tFrame reg: 1, Period reg: 0\n"))
|
||||
set64BitReg(1, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
set64BitReg(0, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
}
|
||||
}
|
||||
// auto
|
||||
else {
|
||||
LOG(logINFO, ("\tTrigger reg: 1, Delay reg: 0\n"))
|
||||
set64BitReg(1, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
|
||||
set64BitReg(0, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
|
||||
// burst
|
||||
if (burstMode != BURST_OFF) {
|
||||
set64BitReg(numBurstsReg, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
set64BitReg(burstPeriodReg, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
LOG(logINFO, ("\tFrames reg (bursts): %lld, Period reg(burst period): %lldns\n", getNumBursts(), getBurstPeriod()));
|
||||
}
|
||||
}
|
||||
LOG(logINFO, ("\tDone Updating registers\n"))
|
||||
}
|
||||
|
||||
enum timingMode getTiming() {
|
||||
@ -1875,23 +1843,62 @@ int setBurstModeinFPGA(enum burstMode value) {
|
||||
int setBurstMode(enum burstMode burst) {
|
||||
LOG(logINFO, ("Setting burst mode to %s\n", burst == BURST_OFF ? "off" : (burst == BURST_INTERNAL ? "internal" : "external")));
|
||||
|
||||
// remember the number of frames and period (before changing burst mode)
|
||||
int64_t frames = getNumFrames();
|
||||
int64_t period = getPeriod();
|
||||
// update
|
||||
int64_t framesReg = 0;
|
||||
int64_t periodReg = 0;
|
||||
// burst
|
||||
if (burstMode != BURST_OFF) {
|
||||
framesReg = ((bus_r(ASIC_INT_FRAMES_REG) & ASIC_INT_FRAMES_MSK) >> ASIC_INT_FRAMES_OFST);
|
||||
periodReg = get64BitReg(ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
|
||||
// auto
|
||||
if (getTiming() == AUTO_TIMING) {
|
||||
numBurstsReg = get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
burstPeriodReg = get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
}
|
||||
}
|
||||
// continuous
|
||||
else {
|
||||
framesReg = get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
periodReg = get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
}
|
||||
|
||||
if (setBurstModeinFPGA(burst) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
LOG(logINFO, ("\tUpdating trigger/burst and burst period registers\n"))
|
||||
setNumTriggers(numTriggers);
|
||||
setNumBursts(numBursts);
|
||||
setBurstPeriod(burstPeriodNs);
|
||||
LOG(logINFO, ("\tUpdating registers\n"));
|
||||
// continuous
|
||||
if (burstMode == BURST_OFF) {
|
||||
set64BitReg(framesReg, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
set64BitReg(periodReg, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
LOG(logINFO, ("\tFrames reg: %lld, Period reg: %lldns\n", getNumFrames(), getPeriod()));
|
||||
|
||||
// set number of frames and period again (set registers according to timing mode)
|
||||
LOG(logINFO, ("\tUpdating #frames and period registers\n"));
|
||||
setNumFrames(frames);
|
||||
setPeriod(period);
|
||||
LOG(logINFO, ("\tInt. Frame reg: 1, Int. Period reg: 0\n"))
|
||||
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) &~ ASIC_INT_FRAMES_MSK);
|
||||
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) | ((1 << ASIC_INT_FRAMES_OFST) & ASIC_INT_FRAMES_MSK));
|
||||
set64BitReg(0, ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
|
||||
}
|
||||
// burst
|
||||
else {
|
||||
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) &~ ASIC_INT_FRAMES_MSK);
|
||||
bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) | (((int)framesReg << ASIC_INT_FRAMES_OFST) & ASIC_INT_FRAMES_MSK));
|
||||
set64BitReg(periodReg, ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG);
|
||||
LOG(logINFO, ("\tInt. Frames reg: %lld, Int. Period reg: %lldns\n", getNumFrames(), getPeriod()));
|
||||
|
||||
// trigger
|
||||
if (getTiming() == TRIGGER_EXPOSURE) {
|
||||
LOG(logINFO, ("\tFrame reg: 1, Period reg: 0\n"))
|
||||
set64BitReg(1, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
set64BitReg(0, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
}
|
||||
//auto
|
||||
else {
|
||||
set64BitReg(numBurstsReg, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
|
||||
set64BitReg(burstPeriodReg, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
|
||||
LOG(logINFO, ("\tFrames reg (bursts): %lld, Period reg(burst period): %lldns\n", getNumBursts(), getBurstPeriod()));
|
||||
}
|
||||
}
|
||||
LOG(logINFO, ("\tDone Updating registers\n"))
|
||||
|
||||
LOG(logINFO, ("\tSetting %s Mode in Chip\n", burstMode == BURST_OFF ? "Continuous" : "Burst"));
|
||||
int value = burstMode ? ASIC_GLOBAL_BURST_VALUE : ASIC_GLOBAL_CONT_VALUE;
|
||||
|
@ -14,15 +14,12 @@ add_executable(jungfrauDetectorServer_virtual
|
||||
../slsDetectorServer/src/communication_funcs_UDP.c
|
||||
)
|
||||
|
||||
include_directories(
|
||||
target_include_directories(jungfrauDetectorServer_virtual
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
../slsDetectorServer/include
|
||||
../../slsSupportLib/include
|
||||
)
|
||||
|
||||
target_include_directories(jungfrauDetectorServer_virtual
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
target_compile_definitions(jungfrauDetectorServer_virtual
|
||||
PUBLIC JUNGFRAUD VIRTUAL STOP_SERVER
|
||||
)
|
||||
@ -36,5 +33,6 @@ set_target_properties(jungfrauDetectorServer_virtual PROPERTIES
|
||||
)
|
||||
|
||||
install(TARGETS jungfrauDetectorServer_virtual
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
||||
EXPORT "${TARGETS_EXPORT_NAME}"
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
@ -202,19 +202,6 @@ void setNumBursts(int64_t val);
|
||||
int64_t getNumBursts();
|
||||
int setBurstPeriod(int64_t val);
|
||||
int64_t getBurstPeriod();
|
||||
|
||||
void setNumFramesBurst(int64_t val);
|
||||
int64_t getNumFramesBurst();
|
||||
void setNumFramesCont(int64_t val);
|
||||
int64_t getNumFramesCont();
|
||||
int setExptimeBurst(int64_t val);
|
||||
int setExptimeCont(int64_t val);
|
||||
int setExptimeBoth(int64_t val);
|
||||
int64_t getExptimeBoth();
|
||||
int setPeriodBurst(int64_t val);
|
||||
int64_t getPeriodBurst();
|
||||
int setPeriodCont(int64_t val);
|
||||
int64_t getPeriodCont();
|
||||
#endif
|
||||
#ifdef EIGERD
|
||||
int setSubExpTime(int64_t val);
|
||||
|
@ -15,7 +15,6 @@ add_library(slsDetectorShared SHARED
|
||||
${HEADERS}
|
||||
)
|
||||
|
||||
|
||||
# Do we have link time optimization?
|
||||
check_ipo_supported(RESULT LTO_AVAILABLE)
|
||||
if(LTO_AVAILABLE)
|
||||
@ -28,15 +27,18 @@ target_include_directories(slsDetectorShared PUBLIC
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
)
|
||||
|
||||
target_link_libraries(slsDetectorShared PUBLIC
|
||||
slsProjectOptions
|
||||
slsProjectWarnings
|
||||
target_link_libraries(slsDetectorShared
|
||||
PUBLIC
|
||||
slsSupportLib
|
||||
${ZeroMQ_LIBRARIES}
|
||||
pthread
|
||||
rt
|
||||
slsProjectOptions
|
||||
PRIVATE
|
||||
slsProjectWarnings
|
||||
${ZeroMQ_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
set(PUBLICHEADERS
|
||||
include/slsDetectorUsers.h
|
||||
include/detectorData.h
|
||||
@ -69,7 +71,7 @@ foreach(val RANGE ${len2})
|
||||
target_link_libraries(${val1}
|
||||
slsDetectorShared
|
||||
pthread
|
||||
${ZeroMQ_LIBRARIES}
|
||||
zmq
|
||||
rt
|
||||
)
|
||||
set_target_properties(${val1} PROPERTIES
|
||||
|
@ -1,15 +1,17 @@
|
||||
#pragma once
|
||||
#include "Result.h"
|
||||
#include "network_utils.h"
|
||||
#include "sls_detector_defs.h"
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class DetectorImpl;
|
||||
|
||||
class detectorData;
|
||||
|
||||
namespace sls {
|
||||
using ns = std::chrono::nanoseconds;
|
||||
class DetectorImpl;
|
||||
class MacAddr;
|
||||
class IpAddr;
|
||||
|
||||
|
@ -1782,7 +1782,7 @@ std::string CmdProxy::MinMaxEnergyThreshold(int action) {
|
||||
os << "[n_value]\n\t[Moench] Minimum energy threshold (soft "
|
||||
"setting) for processor."
|
||||
<< '\n';
|
||||
} else if (cmd == "emin") {
|
||||
} else if (cmd == "emax") {
|
||||
os << "[n_value]\n\t[Moench] Maximum energy threshold (soft "
|
||||
"setting) for processor."
|
||||
<< '\n';
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "DetectorImpl.h"
|
||||
#include "Module.h"
|
||||
#include "sls_detector_defs.h"
|
||||
#include "versionAPI.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
@ -97,11 +98,11 @@ void Detector::setVirtualDetectorServers(int numServers, int startingPort) {
|
||||
int Detector::getShmId() const { return pimpl->getMultiId(); }
|
||||
|
||||
std::string Detector::getPackageVersion() const {
|
||||
return pimpl->getPackageVersion();
|
||||
return GITBRANCH;
|
||||
}
|
||||
|
||||
int64_t Detector::getClientVersion() const {
|
||||
return pimpl->getClientSoftwareVersion();
|
||||
return APILIB;
|
||||
}
|
||||
|
||||
Result<int64_t> Detector::getFirmwareVersion(Positions pos) const {
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <future>
|
||||
#include <vector>
|
||||
|
||||
using namespace sls;
|
||||
namespace sls{
|
||||
|
||||
DetectorImpl::DetectorImpl(int multi_id, bool verify, bool update)
|
||||
: multiId(multi_id), multi_shm(multi_id, -1) {
|
||||
@ -49,10 +49,6 @@ void DetectorImpl::setAcquiringFlag(bool flag) {
|
||||
|
||||
int DetectorImpl::getMultiId() const { return multiId; }
|
||||
|
||||
std::string DetectorImpl::getPackageVersion() const { return GITBRANCH; }
|
||||
|
||||
int64_t DetectorImpl::getClientSoftwareVersion() const { return APILIB; }
|
||||
|
||||
void DetectorImpl::freeSharedMemory(int multiId, int detPos) {
|
||||
// single
|
||||
if (detPos >= 0) {
|
||||
@ -160,7 +156,6 @@ void DetectorImpl::initializeDetectorStructure() {
|
||||
multi_shm()->numberOfChannels.x = 0;
|
||||
multi_shm()->numberOfChannels.y = 0;
|
||||
multi_shm()->acquiringFlag = false;
|
||||
multi_shm()->receiver_upstream = false;
|
||||
multi_shm()->initialChecks = true;
|
||||
}
|
||||
|
||||
@ -822,46 +817,6 @@ bool DetectorImpl::enableDataStreamingToClient(int enable) {
|
||||
return client_downstream;
|
||||
}
|
||||
|
||||
void DetectorImpl::savePattern(const std::string &fname) {
|
||||
// std::ofstream outfile;
|
||||
// outfile.open(fname.c_str(), std::ios_base::out);
|
||||
// if (!outfile.is_open()) {
|
||||
// throw RuntimeError("Could not create file to save pattern");
|
||||
// }
|
||||
// // get pattern limits
|
||||
// auto r = Parallel(&Module::setPatternLoopAddresses, {}, -1, -1, -1)
|
||||
// .tsquash("Inconsistent pattern limits");
|
||||
// // pattern words
|
||||
// for (int i = r[0]; i <= r[1]; ++i) {
|
||||
// std::ostringstream os;
|
||||
// os << "patword 0x" << std::hex << i;
|
||||
// std::string cmd = os.str();
|
||||
// multiSlsDetectorClient(cmd, GET_ACTION, this, outfile);
|
||||
// }
|
||||
// // rest of pattern file
|
||||
// const std::vector<std::string> commands{
|
||||
// "patioctrl",
|
||||
// "patclkctrl",
|
||||
// "patlimits",
|
||||
// "patloop0",
|
||||
// "patnloop0",
|
||||
// "patloop1",
|
||||
// "patnloop1",
|
||||
// "patloop2",
|
||||
// "patnloop2",
|
||||
// "patwait0",
|
||||
// "patwaittime0",
|
||||
// "patwait1",
|
||||
// "patwaittime1",
|
||||
// "patwait2",
|
||||
// "patwaittime2",
|
||||
// "patmask",
|
||||
// "patsetbit",
|
||||
// };
|
||||
// for (const auto &cmd : commands)
|
||||
// multiSlsDetectorClient(cmd, GET_ACTION, this, outfile);
|
||||
}
|
||||
|
||||
void DetectorImpl::registerAcquisitionFinishedCallback(void (*func)(double, int,
|
||||
void *),
|
||||
void *pArg) {
|
||||
@ -1199,3 +1154,5 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
|
||||
LOG(logINFO) << "Read file into memory";
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}//namespace sls
|
@ -5,10 +5,6 @@
|
||||
#include "logger.h"
|
||||
#include "sls_detector_defs.h"
|
||||
|
||||
namespace sls{
|
||||
class Module;
|
||||
}
|
||||
|
||||
class ZmqSocket;
|
||||
class detectorData;
|
||||
|
||||
@ -25,6 +21,11 @@ class detectorData;
|
||||
|
||||
#include <future>
|
||||
#include <numeric>
|
||||
|
||||
namespace sls{
|
||||
|
||||
class Module;
|
||||
|
||||
/**
|
||||
* @short structure allocated in shared memory to store detector settings
|
||||
* for IPC and cache
|
||||
@ -64,9 +65,6 @@ struct sharedMultiSlsDetector {
|
||||
/** flag for acquiring */
|
||||
bool acquiringFlag;
|
||||
|
||||
/** data streaming (up stream) enable in receiver */
|
||||
bool receiver_upstream;
|
||||
|
||||
/** initial checks */
|
||||
bool initialChecks;
|
||||
};
|
||||
@ -202,10 +200,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
|
||||
/** return multi detector shared memory ID */
|
||||
int getMultiId() const;
|
||||
|
||||
std::string getPackageVersion() const;
|
||||
|
||||
int64_t getClientSoftwareVersion() const;
|
||||
|
||||
/** Free specific shared memory from the command line without creating object */
|
||||
static void freeSharedMemory(int multiId, int detPos = -1);
|
||||
|
||||
@ -255,8 +249,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
|
||||
*/
|
||||
bool enableDataStreamingToClient(int enable = -1);
|
||||
|
||||
void savePattern(const std::string &fname);
|
||||
|
||||
/**
|
||||
* register callback for accessing acquisition final data
|
||||
* @param func function to be called at the end of the acquisition.
|
||||
@ -393,14 +385,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
|
||||
*/
|
||||
int kbhit();
|
||||
|
||||
/**
|
||||
* Convert a double holding time in seconds to an int64_t with nano seconds
|
||||
* Used for conversion when sending time to detector
|
||||
* @param t time in seconds
|
||||
* @returns time in nano seconds
|
||||
*/
|
||||
int64_t secondsToNanoSeconds(double t);
|
||||
|
||||
/** Multi detector Id */
|
||||
const int multiId{0};
|
||||
|
||||
@ -448,3 +432,5 @@ class DetectorImpl : public virtual slsDetectorDefs {
|
||||
void (*dataReady)(detectorData *, uint64_t, uint32_t, void *){nullptr};
|
||||
void *pCallbackArg{nullptr};
|
||||
};
|
||||
|
||||
}//namespace sls
|
@ -164,6 +164,29 @@ void Module::sendToDetector(int fnum) {
|
||||
sendToDetector(fnum, nullptr, 0, nullptr, 0);
|
||||
}
|
||||
|
||||
template <typename Ret>
|
||||
Ret Module::sendToDetector(int fnum){
|
||||
LOG(logDEBUG1) << "Sending: ["
|
||||
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
|
||||
<< ", nullptr, 0, " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
||||
Ret retval{};
|
||||
sendToDetector(fnum, nullptr, 0, &retval, sizeof(retval));
|
||||
LOG(logDEBUG1) << "Got back: " << retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
template <typename Ret, typename Arg>
|
||||
Ret Module::sendToDetector(int fnum, const Arg &args){
|
||||
LOG(logDEBUG1) << "Sending: ["
|
||||
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
|
||||
<< ", " << args << ", " << sizeof(args) << ", " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
||||
Ret retval{};
|
||||
sendToDetector(fnum, &args, sizeof(args), &retval, sizeof(retval));
|
||||
LOG(logDEBUG1) << "Got back: " << retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
void Module::sendToDetectorStop(int fnum, const void *args,
|
||||
size_t args_size, void *retval,
|
||||
size_t retval_size) {
|
||||
@ -265,14 +288,58 @@ void Module::sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const {
|
||||
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
|
||||
}
|
||||
|
||||
void Module::sendToReceiver(int fnum) {
|
||||
sendToReceiver(fnum, nullptr, 0, nullptr, 0);
|
||||
template <typename Ret>
|
||||
Ret Module::sendToReceiver(int fnum){
|
||||
LOG(logDEBUG1) << "Sending: ["
|
||||
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
|
||||
<< ", nullptr, 0, " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
||||
Ret retval{};
|
||||
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
|
||||
LOG(logDEBUG1) << "Got back: " << retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Module::sendToReceiver(int fnum) const {
|
||||
sendToReceiver(fnum, nullptr, 0, nullptr, 0);
|
||||
template <typename Ret>
|
||||
Ret Module::sendToReceiver(int fnum) const{
|
||||
LOG(logDEBUG1) << "Sending: ["
|
||||
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
|
||||
<< ", nullptr, 0, " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
||||
Ret retval{};
|
||||
sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
|
||||
LOG(logDEBUG1) << "Got back: " << retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
template <typename Ret, typename Arg>
|
||||
Ret Module::sendToReceiver(int fnum, const Arg &args){
|
||||
LOG(logDEBUG1) << "Sending: ["
|
||||
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
|
||||
<< ", " << args << ", " << sizeof(args) << ", " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
||||
Ret retval{};
|
||||
sendToReceiver(fnum, &args, sizeof(args), &retval, sizeof(retval));
|
||||
LOG(logDEBUG1) << "Got back: " << retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
template <typename Ret, typename Arg>
|
||||
Ret Module::sendToReceiver(int fnum, const Arg &args) const{
|
||||
LOG(logDEBUG1) << "Sending: ["
|
||||
<< getFunctionNameFromEnum(static_cast<slsDetectorDefs::detFuncs>(fnum))
|
||||
<< ", " << args << ", " << sizeof(args) << ", " << typeid(Ret).name() << ", " << sizeof(Ret) << "]";
|
||||
Ret retval{};
|
||||
sendToReceiver(fnum, &args, sizeof(args), &retval, sizeof(retval));
|
||||
LOG(logDEBUG1) << "Got back: " << retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
// void Module::sendToReceiver(int fnum) {
|
||||
// sendToReceiver(fnum, nullptr, 0, nullptr, 0);
|
||||
// }
|
||||
|
||||
// void Module::sendToReceiver(int fnum) const {
|
||||
// sendToReceiver(fnum, nullptr, 0, nullptr, 0);
|
||||
// }
|
||||
|
||||
void Module::freeSharedMemory() {
|
||||
if (shm.IsExisting()) {
|
||||
shm.RemoveSharedMemory();
|
||||
@ -1277,10 +1344,7 @@ void Module::setNumberOfDigitalSamples(int value) {
|
||||
}
|
||||
|
||||
int64_t Module::getExptime() {
|
||||
int64_t retval = -1;
|
||||
sendToDetector(F_GET_EXPTIME, nullptr, retval);
|
||||
LOG(logDEBUG1) << "exptime :" << retval << "ns";
|
||||
return retval;
|
||||
return sendToDetector<int64_t>(F_GET_EXPTIME);
|
||||
}
|
||||
|
||||
void Module::setExptime(int64_t value) {
|
||||
@ -1303,10 +1367,7 @@ void Module::setExptime(int64_t value) {
|
||||
}
|
||||
|
||||
int64_t Module::getPeriod() {
|
||||
int64_t retval = -1;
|
||||
sendToDetector(F_GET_PERIOD, nullptr, retval);
|
||||
LOG(logDEBUG1) << "period :" << retval << "ns";
|
||||
return retval;
|
||||
return sendToDetector<int64_t>(F_GET_PERIOD);
|
||||
}
|
||||
|
||||
void Module::setPeriod(int64_t value) {
|
||||
@ -1319,10 +1380,7 @@ void Module::setPeriod(int64_t value) {
|
||||
}
|
||||
|
||||
int64_t Module::getDelayAfterTrigger() {
|
||||
int64_t retval = -1;
|
||||
sendToDetector(F_GET_DELAY_AFTER_TRIGGER, nullptr, retval);
|
||||
LOG(logDEBUG1) << "delay after trigger :" << retval << "ns";
|
||||
return retval;
|
||||
return sendToDetector<int64_t>(F_GET_DELAY_AFTER_TRIGGER);
|
||||
}
|
||||
|
||||
void Module::setDelayAfterTrigger(int64_t value) {
|
||||
@ -1331,10 +1389,7 @@ void Module::setDelayAfterTrigger(int64_t value) {
|
||||
}
|
||||
|
||||
int64_t Module::getBurstPeriod() {
|
||||
int64_t retval = -1;
|
||||
sendToDetector(F_GET_BURST_PERIOD, nullptr, retval);
|
||||
LOG(logDEBUG1) << "burst period :" << retval << "ns";
|
||||
return retval;
|
||||
return sendToDetector<int64_t>(F_GET_BURST_PERIOD);
|
||||
}
|
||||
|
||||
void Module::setBurstPeriod(int64_t value) {
|
||||
@ -1343,10 +1398,7 @@ void Module::setBurstPeriod(int64_t value) {
|
||||
}
|
||||
|
||||
int64_t Module::getSubExptime() {
|
||||
int64_t retval = -1;
|
||||
sendToDetector(F_GET_SUB_EXPTIME, nullptr, retval);
|
||||
LOG(logDEBUG1) << "sub exptime :" << retval << "ns";
|
||||
return retval;
|
||||
return sendToDetector<int64_t>(F_GET_SUB_EXPTIME);
|
||||
}
|
||||
|
||||
void Module::setSubExptime(int64_t value) {
|
||||
@ -1369,10 +1421,7 @@ void Module::setSubExptime(int64_t value) {
|
||||
}
|
||||
|
||||
int64_t Module::getSubDeadTime() {
|
||||
int64_t retval = -1;
|
||||
sendToDetector(F_GET_SUB_DEADTIME, nullptr, retval);
|
||||
LOG(logDEBUG1) << "sub deadtime :" << retval << "ns";
|
||||
return retval;
|
||||
return sendToDetector<int64_t>(F_GET_SUB_DEADTIME);
|
||||
}
|
||||
|
||||
void Module::setSubDeadTime(int64_t value) {
|
||||
@ -1623,31 +1672,17 @@ void Module::setInterruptSubframe(const bool enable) {
|
||||
}
|
||||
|
||||
bool Module::getInterruptSubframe() {
|
||||
int retval = -1;
|
||||
LOG(logDEBUG1) << "Getting Interrupt subframe";
|
||||
sendToDetector(F_GET_INTERRUPT_SUBFRAME, nullptr, retval);
|
||||
LOG(logDEBUG1) << "Interrupt subframe: " << retval;
|
||||
auto retval = sendToDetector<int>(F_GET_INTERRUPT_SUBFRAME);
|
||||
return static_cast<bool>(retval);
|
||||
}
|
||||
|
||||
uint32_t Module::writeRegister(uint32_t addr, uint32_t val) {
|
||||
uint32_t args[]{addr, val};
|
||||
uint32_t retval = -1;
|
||||
LOG(logDEBUG1) << "Writing to reg 0x" << std::hex << addr << "data: 0x"
|
||||
<< std::hex << val << std::dec;
|
||||
sendToDetector(F_WRITE_REGISTER, args, retval);
|
||||
LOG(logDEBUG1) << "Reg 0x" << std::hex << addr << ": 0x" << std::hex
|
||||
<< retval << std::dec;
|
||||
return retval;
|
||||
return sendToDetector<uint32_t>(F_WRITE_REGISTER, args);
|
||||
}
|
||||
|
||||
uint32_t Module::readRegister(uint32_t addr) {
|
||||
uint32_t retval = -1;
|
||||
LOG(logDEBUG1) << "Reading reg 0x" << std::hex << addr << std::dec;
|
||||
sendToDetector(F_READ_REGISTER, addr, retval);
|
||||
LOG(logDEBUG1) << "Reg 0x" << std::hex << addr << ": 0x" << std::hex
|
||||
<< retval << std::dec;
|
||||
return retval;
|
||||
return sendToDetector<uint32_t>(F_READ_REGISTER, addr);
|
||||
}
|
||||
|
||||
uint32_t Module::setBit(uint32_t addr, int n) {
|
||||
@ -2032,12 +2067,8 @@ void Module::setClientStreamingPort(int port) { shm()->zmqport = port; }
|
||||
int Module::getClientStreamingPort() { return shm()->zmqport; }
|
||||
|
||||
void Module::setReceiverStreamingPort(int port) {
|
||||
int fnum = F_SET_RECEIVER_STREAMING_PORT;
|
||||
int retval = -1;
|
||||
LOG(logDEBUG1) << "Sending receiver streaming port to receiver: "
|
||||
<< port;
|
||||
if (shm()->useReceiverFlag) {
|
||||
sendToReceiver(fnum, port, retval);
|
||||
auto retval = sendToReceiver<int>(F_SET_RECEIVER_STREAMING_PORT, port);
|
||||
LOG(logDEBUG1) << "Receiver streaming port: " << retval;
|
||||
shm()->rxZmqport = retval;
|
||||
} else {
|
||||
@ -2278,14 +2309,7 @@ int64_t Module::getReceiverUDPSocketBufferSize() {
|
||||
}
|
||||
|
||||
int64_t Module::getReceiverRealUDPSocketBufferSize() const {
|
||||
int64_t retval = -1;
|
||||
LOG(logDEBUG1) << "Getting real UDP Socket Buffer size from receiver";
|
||||
if (shm()->useReceiverFlag) {
|
||||
sendToReceiver(F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE, nullptr, retval);
|
||||
LOG(logDEBUG1)
|
||||
<< "Real Receiver UDP Socket Buffer size: " << retval;
|
||||
}
|
||||
return retval;
|
||||
return sendToReceiver<int64_t>(F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE);
|
||||
}
|
||||
|
||||
void Module::executeFirmwareTest() {
|
||||
@ -3136,7 +3160,7 @@ sls::IpAddr Module::getReceiverLastClientIP() const {
|
||||
void Module::exitReceiver() {
|
||||
LOG(logDEBUG1) << "Sending exit command to receiver server";
|
||||
if (shm()->useReceiverFlag) {
|
||||
sendToReceiver(F_EXIT_RECEIVER);
|
||||
sendToReceiver(F_EXIT_RECEIVER, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3431,7 +3455,7 @@ int64_t Module::incrementFileIndex() {
|
||||
void Module::startReceiver() {
|
||||
LOG(logDEBUG1) << "Starting Receiver";
|
||||
if (shm()->useReceiverFlag) {
|
||||
sendToReceiver(F_START_RECEIVER);
|
||||
sendToReceiver(F_START_RECEIVER, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3635,7 +3659,7 @@ bool Module::setReceiverSilentMode(int value) {
|
||||
void Module::restreamStopFromReceiver() {
|
||||
LOG(logDEBUG1) << "Restream stop dummy from Receiver via zmq";
|
||||
if (shm()->useReceiverFlag) {
|
||||
sendToReceiver(F_RESTREAM_STOP_FROM_RECEIVER);
|
||||
sendToReceiver(F_RESTREAM_STOP_FROM_RECEIVER, nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1915,6 +1915,12 @@ class Module : public virtual slsDetectorDefs {
|
||||
void sendToDetector(int fnum, std::nullptr_t, Ret &retval);
|
||||
void sendToDetector(int fnum);
|
||||
|
||||
template <typename Ret>
|
||||
Ret sendToDetector(int fnum);
|
||||
|
||||
template <typename Ret, typename Arg>
|
||||
Ret sendToDetector(int fnum, const Arg &args);
|
||||
|
||||
/**
|
||||
* Send function parameters to detector (stop server)
|
||||
* @param fnum function enum
|
||||
@ -1983,9 +1989,17 @@ class Module : public virtual slsDetectorDefs {
|
||||
template <typename Ret>
|
||||
void sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const;
|
||||
|
||||
void sendToReceiver(int fnum);
|
||||
template <typename Ret>
|
||||
Ret sendToReceiver(int fnum);
|
||||
|
||||
void sendToReceiver(int fnum) const;
|
||||
template <typename Ret>
|
||||
Ret sendToReceiver(int fnum) const;
|
||||
|
||||
template <typename Ret, typename Arg>
|
||||
Ret sendToReceiver(int fnum, const Arg &args);
|
||||
|
||||
template <typename Ret, typename Arg>
|
||||
Ret sendToReceiver(int fnum, const Arg &args) const;
|
||||
|
||||
/**
|
||||
* Get Detector Type from Shared Memory (opening shm without verifying size)
|
||||
|
@ -8,7 +8,6 @@
|
||||
*@short functions basic implemenation of shared memory
|
||||
*/
|
||||
|
||||
#include "ansi.h"
|
||||
#include "logger.h"
|
||||
#include "sls_detector_exceptions.h"
|
||||
|
||||
@ -18,7 +17,7 @@
|
||||
#include <fcntl.h> // O_CREAT, O_TRUNC..
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdio.h> // printf
|
||||
// #include <stdio.h> // printf
|
||||
#include <sys/mman.h> // shared memory
|
||||
#include <sys/stat.h> // fstat
|
||||
#include <unistd.h>
|
||||
|
@ -9,7 +9,6 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "ansi.h"
|
||||
#include "logger.h"
|
||||
|
||||
#include <string>
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sys/stat.h> // stat
|
||||
#include <unistd.h>
|
||||
|
||||
/** cosntructor & destructor */
|
||||
|
||||
|
@ -6,6 +6,7 @@ set(SOURCES
|
||||
src/ServerSocket.cpp
|
||||
src/ServerInterface.cpp
|
||||
src/network_utils.cpp
|
||||
src/ZmqSocket.cpp
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
@ -20,7 +21,6 @@ set(PUBLICHEADERS
|
||||
include/file_utils.h
|
||||
include/container_utils.h
|
||||
include/string_utils.h
|
||||
include/genericSocket.h
|
||||
include/logger.h
|
||||
include/ClientSocket.h
|
||||
include/DataSocket.h
|
||||
@ -44,22 +44,36 @@ if(result)
|
||||
endif()
|
||||
|
||||
target_include_directories(slsSupportLib PUBLIC
|
||||
${ZeroMQ_INCLUDE_DIRS}
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
)
|
||||
|
||||
target_include_directories(slsSupportLib PRIVATE
|
||||
${ZeroMQ_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
|
||||
set_target_properties(slsSupportLib PROPERTIES
|
||||
LIBRARY_OUTPUT_NAME SlsSupport
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
PUBLIC_HEADER "${PUBLICHEADERS}"
|
||||
)
|
||||
|
||||
message(${ZeroMQ_LIBRARIES})
|
||||
|
||||
target_link_libraries(slsSupportLib
|
||||
PUBLIC
|
||||
slsProjectOptions
|
||||
# ${ZeroMQ_LIBRARIES}
|
||||
zmq
|
||||
PRIVATE
|
||||
|
||||
slsProjectWarnings
|
||||
${ZeroMQ_LIBRARIES}
|
||||
rapidjson)
|
||||
PUBLIC
|
||||
rapidjson
|
||||
)
|
||||
|
||||
|
||||
|
||||
if (SLS_USE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
|
@ -9,7 +9,6 @@ this might be deprecated in the future
|
||||
|
||||
*/
|
||||
|
||||
// #include "genericSocket.h"
|
||||
#include "network_utils.h"
|
||||
#include "sls_detector_exceptions.h"
|
||||
#include <cstdint>
|
||||
|
@ -7,20 +7,8 @@
|
||||
*@short functions to open/close zmq sockets
|
||||
*/
|
||||
|
||||
#include "ansi.h"
|
||||
#include "sls_detector_exceptions.h"
|
||||
|
||||
#include <arpa/inet.h> //inet_ntoa
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
#include <netdb.h> //gethostbyname()
|
||||
#include <rapidjson/document.h> //json header in zmq stream
|
||||
#include <string.h>
|
||||
#include <unistd.h> //usleep in some machines
|
||||
#include <vector>
|
||||
#include <zmq.h>
|
||||
using namespace rapidjson;
|
||||
|
||||
|
||||
#define MAX_STR_LENGTH 1000
|
||||
|
||||
@ -28,404 +16,161 @@ using namespace rapidjson;
|
||||
#define ROIVERBOSITY
|
||||
|
||||
|
||||
|
||||
class zmq_msg_t;
|
||||
class ZmqSocket {
|
||||
|
||||
public:
|
||||
public:
|
||||
// Socket Options for optimization
|
||||
// ZMQ_LINGER default is already -1 means no messages discarded. use this
|
||||
// options if optimizing required ZMQ_SNDHWM default is 0 means no limit. use
|
||||
// this to optimize if optimizing required
|
||||
// eg. int value = -1;
|
||||
// if (zmq_setsockopt(socketDescriptor, ZMQ_LINGER, &value,sizeof(value))) {
|
||||
// Close();
|
||||
/**
|
||||
* Constructor for a client
|
||||
* Creates socket, context and connects to server
|
||||
* @param hostname hostname or ip of server
|
||||
* @param portnumber port number
|
||||
*/
|
||||
ZmqSocket(const char *const hostname_or_ip, const uint32_t portnumber);
|
||||
|
||||
//Socket Options for optimization
|
||||
//ZMQ_LINGER default is already -1 means no messages discarded. use this options if optimizing required
|
||||
//ZMQ_SNDHWM default is 0 means no limit. use this to optimize if optimizing required
|
||||
// eg. int value = -1;
|
||||
// if (zmq_setsockopt(socketDescriptor, ZMQ_LINGER, &value,sizeof(value))) {
|
||||
// Close();
|
||||
/**
|
||||
* Constructor for a client
|
||||
* Creates socket, context and connects to server
|
||||
* @param hostname hostname or ip of server
|
||||
* @param portnumber port number
|
||||
*/
|
||||
ZmqSocket (const char* const hostname_or_ip, const uint32_t portnumber):
|
||||
portno (portnumber)
|
||||
// headerMessage(0)
|
||||
{
|
||||
char ip[MAX_STR_LENGTH] = "";
|
||||
memset(ip, 0, MAX_STR_LENGTH);
|
||||
/**
|
||||
* Constructor for a server
|
||||
* Creates socket, context and connects to server
|
||||
* @param hostname hostname or ip of server
|
||||
* @param portnumber port number
|
||||
* @param ethip is the ip of the ethernet interface to stream zmq from
|
||||
*/
|
||||
ZmqSocket(const uint32_t portnumber, const char *ethip);
|
||||
|
||||
// convert hostname to ip (not required, but a test that returns if failed)
|
||||
struct addrinfo *result;
|
||||
if ((ConvertHostnameToInternetAddress(hostname_or_ip, &result)) ||
|
||||
(ConvertInternetAddresstoIpString(result, ip, MAX_STR_LENGTH)))
|
||||
throw sls::ZmqSocketError("Could convert IP to string");
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ZmqSocket() = default;
|
||||
|
||||
// construct address
|
||||
sprintf (sockfd.serverAddress, "tcp://%s:%d", ip, portno);
|
||||
#ifdef VERBOSE
|
||||
cprintf(BLUE,"address:%s\n",sockfd.serverAddress);
|
||||
#endif
|
||||
/**
|
||||
* Returns Port Number
|
||||
* @returns Port Number
|
||||
*/
|
||||
uint32_t GetPortNumber() { return portno; }
|
||||
|
||||
// create context
|
||||
sockfd.contextDescriptor = zmq_ctx_new();
|
||||
if (sockfd.contextDescriptor == 0)
|
||||
throw sls::ZmqSocketError("Could not create contextDescriptor");
|
||||
/**
|
||||
* Returns Server Address
|
||||
* @returns Server Address
|
||||
*/
|
||||
char *GetZmqServerAddress() { return sockfd.serverAddress; }
|
||||
|
||||
// create publisher
|
||||
sockfd.socketDescriptor = zmq_socket (sockfd.contextDescriptor, ZMQ_SUB);
|
||||
if (sockfd.socketDescriptor == 0) {
|
||||
PrintError ();
|
||||
Close ();
|
||||
throw sls::ZmqSocketError("Could not create socket");
|
||||
}
|
||||
/**
|
||||
* Returns Socket Descriptor
|
||||
* @reutns Socket descriptor
|
||||
*/
|
||||
|
||||
//Socket Options provided above
|
||||
// an empty string implies receiving any messages
|
||||
if ( zmq_setsockopt(sockfd.socketDescriptor, ZMQ_SUBSCRIBE, "", 0)) {
|
||||
PrintError ();
|
||||
Close();
|
||||
throw sls::ZmqSocketError("Could set socket opt");
|
||||
}
|
||||
//ZMQ_LINGER default is already -1 means no messages discarded. use this options if optimizing required
|
||||
//ZMQ_SNDHWM default is 0 means no limit. use this to optimize if optimizing required
|
||||
// eg. int value = -1;
|
||||
int value = 0;
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_LINGER, &value,sizeof(value))) {
|
||||
PrintError ();
|
||||
Close();
|
||||
throw sls::ZmqSocketError("Could not set ZMQ_LINGER");
|
||||
}
|
||||
};
|
||||
void *GetsocketDescriptor() { return sockfd.socketDescriptor; }
|
||||
|
||||
/**
|
||||
* Constructor for a server
|
||||
* Creates socket, context and connects to server
|
||||
* @param hostname hostname or ip of server
|
||||
* @param portnumber port number
|
||||
* @param ethip is the ip of the ethernet interface to stream zmq from
|
||||
*/
|
||||
ZmqSocket (const uint32_t portnumber, const char *ethip):
|
||||
/**
|
||||
* Connect client socket to server socket
|
||||
* @returns 1 for fail, 0 for success
|
||||
*/
|
||||
int Connect();
|
||||
|
||||
portno (portnumber)
|
||||
// headerMessage(0)
|
||||
{
|
||||
sockfd.server = true;
|
||||
/**
|
||||
* Unbinds the Socket
|
||||
*/
|
||||
void Disconnect() { sockfd.Disconnect(); };
|
||||
|
||||
// create context
|
||||
sockfd.contextDescriptor = zmq_ctx_new();
|
||||
if (sockfd.contextDescriptor == 0)
|
||||
throw sls::ZmqSocketError("Could not create contextDescriptor");
|
||||
// create publisher
|
||||
sockfd.socketDescriptor = zmq_socket (sockfd.contextDescriptor, ZMQ_PUB);
|
||||
if (sockfd.socketDescriptor == 0) {
|
||||
PrintError ();
|
||||
Close ();
|
||||
throw sls::ZmqSocketError("Could not create socket");
|
||||
}
|
||||
/**
|
||||
* Close Socket and destroy Context
|
||||
*/
|
||||
void Close() { sockfd.Close(); };
|
||||
|
||||
//Socket Options provided above
|
||||
/**
|
||||
* Convert Hostname to Internet address info structure
|
||||
* One must use freeaddrinfo(res) after using it
|
||||
* @param hostname hostname
|
||||
* @param res address of pointer to address info structure
|
||||
* @return 1 for fail, 0 for success
|
||||
*/
|
||||
// Do not make this static (for multi threading environment)
|
||||
int ConvertHostnameToInternetAddress(const char *const hostname,
|
||||
struct addrinfo **res);
|
||||
|
||||
// construct addresss
|
||||
sprintf (sockfd.serverAddress,"tcp://%s:%d", ethip, portno);
|
||||
#ifdef VERBOSE
|
||||
cprintf(BLUE,"address:%s\n",sockfd.serverAddress);
|
||||
#endif
|
||||
// bind address
|
||||
if (zmq_bind (sockfd.socketDescriptor, sockfd.serverAddress) < 0) {
|
||||
PrintError ();
|
||||
Close ();
|
||||
throw sls::ZmqSocketError("Could not bind socket");
|
||||
}
|
||||
/**
|
||||
* Convert Internet Address structure pointer to ip string (char*)
|
||||
* Clears the internet address structure as well
|
||||
* @param res pointer to internet address structure
|
||||
* @param ip pointer to char array to store result in
|
||||
* @param ipsize size available in ip buffer
|
||||
* @return 1 for fail, 0 for success
|
||||
*/
|
||||
// Do not make this static (for multi threading environment)
|
||||
int ConvertInternetAddresstoIpString(struct addrinfo *res, char *ip,
|
||||
const int ipsize);
|
||||
|
||||
//sleep for a few milliseconds to allow a slow-joiner
|
||||
usleep(200* 1000);
|
||||
};
|
||||
/**
|
||||
* Send Message Header
|
||||
* @param index self index for debugging
|
||||
* @param dummy true if a dummy message for end of acquisition
|
||||
* @param jsonversion json version
|
||||
* @param dynamicrange dynamic range
|
||||
* @param fileIndex file or acquisition index
|
||||
* @param ndetx number of detectors in x axis
|
||||
* @param ndety number of detectors in y axis
|
||||
* @param npixelsx number of pixels/channels in x axis for this zmq socket
|
||||
* @param npixelsy number of pixels/channels in y axis for this zmq socket
|
||||
* @param imageSize number of bytes for an image in this socket
|
||||
* @param frameNumber current frame number
|
||||
* @param expLength exposure length or subframe index if eiger
|
||||
* @param packetNumber number of packets caught for this frame
|
||||
* @param bunchId bunch id
|
||||
* @param timestamp time stamp
|
||||
* @param modId module Id
|
||||
* @param row row index in complete detector
|
||||
* @param column column index in complete detector
|
||||
* @param reserved reserved
|
||||
* @param debug debug
|
||||
* @param roundRNumber not used yet
|
||||
* @param detType detector enum
|
||||
* @param version detector header version
|
||||
* @param gapPixelsEnable gap pixels enable (exception: if gap pixels enable
|
||||
* for 4 bit mode, data is not yet gap pixel enabled in receiver)
|
||||
* @param flippedDataX if it is flipped across x axis
|
||||
* @param quadEnable if quad is enabled
|
||||
* @param additionalJsonHeader additional json header
|
||||
* @returns 0 if error, else 1
|
||||
*/
|
||||
int SendHeaderData(
|
||||
int index, bool dummy, uint32_t jsonversion, uint32_t dynamicrange = 0,
|
||||
uint64_t fileIndex = 0, uint32_t ndetx = 0, uint32_t ndety = 0,
|
||||
uint32_t npixelsx = 0, uint32_t npixelsy = 0, uint32_t imageSize = 0,
|
||||
uint64_t acqIndex = 0, uint64_t fIndex = 0, const char *fname = nullptr,
|
||||
uint64_t frameNumber = 0, uint32_t expLength = 0,
|
||||
uint32_t packetNumber = 0, uint64_t bunchId = 0, uint64_t timestamp = 0,
|
||||
uint16_t modId = 0, uint16_t row = 0, uint16_t column = 0,
|
||||
uint16_t reserved = 0, uint32_t debug = 0, uint16_t roundRNumber = 0,
|
||||
uint8_t detType = 0, uint8_t version = 0, int gapPixelsEnable = 0,
|
||||
int flippedDataX = 0, uint32_t quadEnable = 0,
|
||||
std::string *additionalJsonHeader = 0);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~ZmqSocket () {
|
||||
//mySocketDescriptor destructor also gets called
|
||||
};
|
||||
/**
|
||||
* Send Message Body
|
||||
* @param buf message
|
||||
* @param length length of message
|
||||
* @returns 0 if error, else 1
|
||||
*/
|
||||
int SendData(char *buf, int length);
|
||||
|
||||
/**
|
||||
* Returns Port Number
|
||||
* @returns Port Number
|
||||
*/
|
||||
uint32_t GetPortNumber () { return portno; };
|
||||
|
||||
/**
|
||||
* Returns Server Address
|
||||
* @returns Server Address
|
||||
*/
|
||||
char* GetZmqServerAddress () { return sockfd.serverAddress; };
|
||||
|
||||
/**
|
||||
* Returns Socket Descriptor
|
||||
* @reutns Socket descriptor
|
||||
*/
|
||||
|
||||
void* GetsocketDescriptor () { return sockfd.socketDescriptor; };
|
||||
|
||||
/**
|
||||
* Connect client socket to server socket
|
||||
* @returns 1 for fail, 0 for success
|
||||
*/
|
||||
int Connect() {
|
||||
if (zmq_connect(sockfd.socketDescriptor, sockfd.serverAddress) < 0) {
|
||||
PrintError ();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbinds the Socket
|
||||
*/
|
||||
void Disconnect () {sockfd.Disconnect();};
|
||||
|
||||
/**
|
||||
* Close Socket and destroy Context
|
||||
*/
|
||||
void Close () { sockfd.Close(); };
|
||||
|
||||
/**
|
||||
* Convert Hostname to Internet address info structure
|
||||
* One must use freeaddrinfo(res) after using it
|
||||
* @param hostname hostname
|
||||
* @param res address of pointer to address info structure
|
||||
* @return 1 for fail, 0 for success
|
||||
*/
|
||||
// Do not make this static (for multi threading environment)
|
||||
int ConvertHostnameToInternetAddress (const char* const hostname, struct addrinfo **res) {
|
||||
// criteria in selecting socket address structures returned by res
|
||||
struct addrinfo hints;
|
||||
memset (&hints, 0, sizeof (hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
// get host info into res
|
||||
int errcode = getaddrinfo (hostname, NULL, &hints, res);
|
||||
if (errcode != 0) {
|
||||
LOG(logERROR) << "Error: Could not convert hostname " << hostname << " to internet address (zmq):"
|
||||
<< gai_strerror(errcode);
|
||||
} else {
|
||||
if (*res == NULL) {
|
||||
LOG(logERROR) << "Could not convert hostname " << hostname << " to internet address (zmq): "
|
||||
"gettaddrinfo returned null";
|
||||
} else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
LOG(logERROR) << "Could not convert hostname to internet address";
|
||||
return 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert Internet Address structure pointer to ip string (char*)
|
||||
* Clears the internet address structure as well
|
||||
* @param res pointer to internet address structure
|
||||
* @param ip pointer to char array to store result in
|
||||
* @param ipsize size available in ip buffer
|
||||
* @return 1 for fail, 0 for success
|
||||
*/
|
||||
// Do not make this static (for multi threading environment)
|
||||
int ConvertInternetAddresstoIpString (struct addrinfo *res, char* ip, const int ipsize) {
|
||||
if (inet_ntop (res->ai_family, &((struct sockaddr_in *) res->ai_addr)->sin_addr, ip, ipsize) != NULL) {
|
||||
freeaddrinfo(res);
|
||||
return 0;
|
||||
}
|
||||
LOG(logERROR) << "Could not convert internet address to ip string";
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Send Message Header
|
||||
* @param index self index for debugging
|
||||
* @param dummy true if a dummy message for end of acquisition
|
||||
* @param jsonversion json version
|
||||
* @param dynamicrange dynamic range
|
||||
* @param fileIndex file or acquisition index
|
||||
* @param ndetx number of detectors in x axis
|
||||
* @param ndety number of detectors in y axis
|
||||
* @param npixelsx number of pixels/channels in x axis for this zmq socket
|
||||
* @param npixelsy number of pixels/channels in y axis for this zmq socket
|
||||
* @param imageSize number of bytes for an image in this socket
|
||||
* @param frameNumber current frame number
|
||||
* @param expLength exposure length or subframe index if eiger
|
||||
* @param packetNumber number of packets caught for this frame
|
||||
* @param bunchId bunch id
|
||||
* @param timestamp time stamp
|
||||
* @param modId module Id
|
||||
* @param row row index in complete detector
|
||||
* @param column column index in complete detector
|
||||
* @param reserved reserved
|
||||
* @param debug debug
|
||||
* @param roundRNumber not used yet
|
||||
* @param detType detector enum
|
||||
* @param version detector header version
|
||||
* @param gapPixelsEnable gap pixels enable (exception: if gap pixels enable for 4 bit mode, data is not yet gap pixel enabled in receiver)
|
||||
* @param flippedDataX if it is flipped across x axis
|
||||
* @param quadEnable if quad is enabled
|
||||
* @param additionalJsonHeader additional json header
|
||||
* @returns 0 if error, else 1
|
||||
*/
|
||||
int SendHeaderData ( int index, bool dummy, uint32_t jsonversion, uint32_t dynamicrange = 0, uint64_t fileIndex = 0,
|
||||
uint32_t ndetx = 0, uint32_t ndety = 0, uint32_t npixelsx = 0, uint32_t npixelsy = 0, uint32_t imageSize = 0,
|
||||
uint64_t acqIndex = 0, uint64_t fIndex = 0, const char* fname = NULL,
|
||||
uint64_t frameNumber = 0, uint32_t expLength = 0, uint32_t packetNumber = 0,
|
||||
uint64_t bunchId = 0, uint64_t timestamp = 0,
|
||||
uint16_t modId = 0, uint16_t row = 0, uint16_t column = 0, uint16_t reserved = 0,
|
||||
uint32_t debug = 0, uint16_t roundRNumber = 0,
|
||||
uint8_t detType = 0, uint8_t version = 0, int gapPixelsEnable = 0, int flippedDataX = 0,
|
||||
uint32_t quadEnable = 0,
|
||||
std::string* additionalJsonHeader = 0) {
|
||||
|
||||
|
||||
|
||||
/** Json Header Format */
|
||||
const char jsonHeaderFormat[] =
|
||||
"{"
|
||||
"\"jsonversion\":%u, "
|
||||
"\"bitmode\":%u, "
|
||||
"\"fileIndex\":%lu, "
|
||||
"\"detshape\":[%u, %u], "
|
||||
"\"shape\":[%u, %u], "
|
||||
"\"size\":%u, "
|
||||
"\"acqIndex\":%lu, "
|
||||
"\"fIndex\":%lu, "
|
||||
"\"fname\":\"%s\", "
|
||||
"\"data\": %d, "
|
||||
|
||||
"\"frameNumber\":%lu, "
|
||||
"\"expLength\":%u, "
|
||||
"\"packetNumber\":%u, "
|
||||
"\"bunchId\":%lu, "
|
||||
"\"timestamp\":%lu, "
|
||||
"\"modId\":%u, "
|
||||
"\"row\":%u, "
|
||||
"\"column\":%u, "
|
||||
"\"reserved\":%u, "
|
||||
"\"debug\":%u, "
|
||||
"\"roundRNumber\":%u, "
|
||||
"\"detType\":%u, "
|
||||
"\"version\":%u, "
|
||||
|
||||
//additional stuff
|
||||
"\"gappixels\":%u, "
|
||||
"\"flippedDataX\":%u, "
|
||||
"\"quad\":%u"
|
||||
|
||||
;//"}\n";
|
||||
char buf[MAX_STR_LENGTH] = "";
|
||||
sprintf(buf, jsonHeaderFormat,
|
||||
jsonversion, dynamicrange, fileIndex, ndetx, ndety, npixelsx, npixelsy, imageSize,
|
||||
acqIndex, fIndex, (fname == NULL)? "":fname, dummy?0:1,
|
||||
|
||||
frameNumber, expLength, packetNumber, bunchId, timestamp,
|
||||
modId, row, column, reserved, debug, roundRNumber,
|
||||
detType, version,
|
||||
|
||||
//additional stuff
|
||||
gapPixelsEnable,
|
||||
flippedDataX,
|
||||
quadEnable
|
||||
);
|
||||
|
||||
if (additionalJsonHeader && !((*additionalJsonHeader).empty())) {
|
||||
strcat(buf, ", ");
|
||||
strcat(buf, (*additionalJsonHeader).c_str());
|
||||
}
|
||||
strcat(buf, "}\n");
|
||||
int length = strlen(buf);
|
||||
|
||||
#ifdef VERBOSE
|
||||
//if(!index)
|
||||
cprintf(BLUE,"%d : Streamer: buf: %s\n", index, buf);
|
||||
#endif
|
||||
|
||||
if(zmq_send (sockfd.socketDescriptor, buf, length, dummy?0:ZMQ_SNDMORE) < 0) {
|
||||
PrintError ();
|
||||
return 0;
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
cprintf(GREEN,"[%u] send header data\n",portno);
|
||||
#endif
|
||||
return 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Send Message Body
|
||||
* @param buf message
|
||||
* @param length length of message
|
||||
* @returns 0 if error, else 1
|
||||
*/
|
||||
int SendData (char* buf, int length) {
|
||||
if(zmq_send (sockfd.socketDescriptor, buf, length, 0) < 0) {
|
||||
PrintError ();
|
||||
return 0;
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
cprintf(GREEN,"[%u] send data\n",portno);
|
||||
#endif
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Receive Message
|
||||
* @param index self index for debugging
|
||||
* @param message message
|
||||
* @returns length of message, -1 if error
|
||||
*/
|
||||
int ReceiveMessage(const int index, zmq_msg_t& message) {
|
||||
int length = zmq_msg_recv (&message, sockfd.socketDescriptor, 0);
|
||||
if (length == -1) {
|
||||
PrintError ();
|
||||
LOG(logERROR) << "Could not read header for socket " << index;
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
else
|
||||
cprintf( RED,"Message %d Length: %d Header:%s \n", index, length, (char*) zmq_msg_data (&message) );
|
||||
#endif
|
||||
return length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Receive Header (Important to close message after parsing header)
|
||||
* @param index self index for debugging
|
||||
* @param document parsed document reference
|
||||
* @param version version that has to match, -1 to not care
|
||||
* @returns 0 if error or end of acquisition, else 1 (call CloseHeaderMessage after parsing header)
|
||||
*/
|
||||
int ReceiveHeader(const int index, Document& document, uint32_t version)
|
||||
{
|
||||
std::vector<char>buffer(MAX_STR_LENGTH);
|
||||
int len = zmq_recv(sockfd.socketDescriptor, buffer.data(), buffer.size(),0);
|
||||
if ( len > 0 ) {
|
||||
bool dummy = false;
|
||||
#ifdef ZMQ_DETAIL
|
||||
cprintf( BLUE,"Header %d [%d] Length: %d Header:%s \n", index, portno, len, buffer.data());
|
||||
#endif
|
||||
if ( ParseHeader (index, len, buffer.data(), document, dummy, version)) {
|
||||
#ifdef ZMQ_DETAIL
|
||||
cprintf( RED,"Parsed Header %d [%d] Length: %d Header:%s \n", index, portno, len, buffer.data() );
|
||||
#endif
|
||||
if (dummy) {
|
||||
#ifdef ZMQ_DETAIL
|
||||
cprintf(RED,"%d [%d] Received end of acquisition\n", index, portno );
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#ifdef ZMQ_DETAIL
|
||||
cprintf(GREEN,"%d [%d] data\n",index, portno );
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Receive Header (Important to close message after parsing header)
|
||||
* @param index self index for debugging
|
||||
* @param document parsed document reference
|
||||
* @param version version that has to match, -1 to not care
|
||||
* @returns 0 if error or end of acquisition, else 1 (call
|
||||
* CloseHeaderMessage after parsing header)
|
||||
*/
|
||||
int ReceiveHeader(const int index, rapidjson::Document &document, uint32_t version);
|
||||
|
||||
/**
|
||||
* Close Header Message. Call this function if ReceiveHeader returned 1
|
||||
@ -445,183 +190,60 @@ public:
|
||||
* @param version version that has to match, -1 to not care
|
||||
* @returns true if successful else false
|
||||
*/
|
||||
int ParseHeader(const int index, int length, char* buff,
|
||||
Document& document, bool& dummy, uint32_t version)
|
||||
{
|
||||
if ( document.Parse( buff, length).HasParseError() ) {
|
||||
LOG(logERROR) << index << " Could not parse. len:" << length << ": Message:" << buff;
|
||||
fflush ( stdout );
|
||||
// char* buf = (char*) zmq_msg_data (&message);
|
||||
for ( int i= 0; i < length; ++i ) {
|
||||
cprintf(RED,"%02x ",buff[i]);
|
||||
}
|
||||
printf("\n");
|
||||
fflush( stdout );
|
||||
return 0;
|
||||
}
|
||||
int ParseHeader(const int index, int length, char *buff, rapidjson::Document &document,
|
||||
bool &dummy, uint32_t version);
|
||||
|
||||
if (document["jsonversion"].GetUint() != version) {
|
||||
LOG(logERROR) << "version mismatch. required " << version << ", got " << document["jsonversion"].GetUint();
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* Receive Data
|
||||
* @param index self index for debugging
|
||||
* @param buf buffer to copy image data to
|
||||
* @param size size of image
|
||||
* @returns length of data received
|
||||
*/
|
||||
int ReceiveData(const int index, char *buf, const int size);
|
||||
|
||||
dummy = false;
|
||||
int temp = document["data"].GetUint();
|
||||
dummy = temp ? false : true;
|
||||
/**
|
||||
* Print error
|
||||
*/
|
||||
void PrintError();
|
||||
|
||||
return 1;
|
||||
private:
|
||||
|
||||
/**
|
||||
* Receive Message
|
||||
* @param index self index for debugging
|
||||
* @param message message
|
||||
* @returns length of message, -1 if error
|
||||
*/
|
||||
int ReceiveMessage(const int index, zmq_msg_t &message);
|
||||
/**
|
||||
* Class to close socket descriptors automatically
|
||||
* upon encountering exceptions in the ZmqSocket constructor
|
||||
*/
|
||||
class mySocketDescriptors {
|
||||
public:
|
||||
/** Constructor */
|
||||
mySocketDescriptors();
|
||||
/** Destructor */
|
||||
~mySocketDescriptors();
|
||||
/** Unbinds the Socket */
|
||||
void Disconnect();
|
||||
/** Close Socket and destroy Context */
|
||||
void Close();
|
||||
/** true if server, else false */
|
||||
bool server;
|
||||
/** Server Address */
|
||||
char serverAddress[1000];
|
||||
/** Context Descriptor */
|
||||
void *contextDescriptor;
|
||||
/** Socket Descriptor */
|
||||
void *socketDescriptor;
|
||||
};
|
||||
|
||||
private:
|
||||
/** Port Number */
|
||||
uint32_t portno;
|
||||
|
||||
/**
|
||||
* Receive Data
|
||||
* @param index self index for debugging
|
||||
* @param buf buffer to copy image data to
|
||||
* @param size size of image
|
||||
* @returns length of data received
|
||||
*/
|
||||
int ReceiveData(const int index, char* buf, const int size)
|
||||
{
|
||||
zmq_msg_t message;
|
||||
zmq_msg_init (&message);
|
||||
int length = ReceiveMessage(index, message);
|
||||
|
||||
//actual data
|
||||
if (length == size) {
|
||||
#ifdef VERBOSE
|
||||
cprintf(BLUE,"%d actual data\n", index);
|
||||
#endif
|
||||
memcpy(buf, (char*)zmq_msg_data(&message), size);
|
||||
}
|
||||
|
||||
//incorrect size (smaller)
|
||||
else if (length < size){
|
||||
#ifdef ROIVERBOSITY
|
||||
cprintf(RED,"Error: Received smaller packet size %d for socket %d\n", length, index);
|
||||
#endif
|
||||
memcpy(buf, (char*)zmq_msg_data(&message), length);
|
||||
memset(buf+length,0xFF,size-length);
|
||||
}
|
||||
//incorrect size (larger)
|
||||
else {
|
||||
LOG(logERROR) << "Received weird packet size " << length << " for socket " << index;
|
||||
memset(buf,0xFF,size);
|
||||
}
|
||||
|
||||
zmq_msg_close(&message);
|
||||
return length;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Print error
|
||||
*/
|
||||
void PrintError () {
|
||||
switch (errno) {
|
||||
case EINVAL:
|
||||
LOG(logERROR) << "The socket type/option or value/endpoint supplied is invalid (zmq)";
|
||||
break;
|
||||
case EAGAIN:
|
||||
LOG(logERROR) << "Non-blocking mode was requested and the message cannot be sent/available at the moment (zmq)";
|
||||
break;
|
||||
case ENOTSUP:
|
||||
LOG(logERROR) << "The zmq_send()/zmq_msg_recv() operation is not supported by this socket type (zmq)";
|
||||
break;
|
||||
case EFSM:
|
||||
LOG(logERROR) << "The zmq_send()/zmq_msg_recv() unavailable now as socket in inappropriate state (eg. ZMQ_REP). Look up messaging patterns (zmq)";
|
||||
break;
|
||||
case EFAULT:
|
||||
LOG(logERROR) << "The provided context/message is invalid (zmq)";
|
||||
break;
|
||||
case EMFILE:
|
||||
LOG(logERROR) << "The limit on the total number of open ØMQ sockets has been reached (zmq)";
|
||||
break;
|
||||
case EPROTONOSUPPORT:
|
||||
LOG(logERROR) << "The requested transport protocol is not supported (zmq)";
|
||||
break;
|
||||
case ENOCOMPATPROTO:
|
||||
LOG(logERROR) << "The requested transport protocol is not compatible with the socket type (zmq)";
|
||||
break;
|
||||
case EADDRINUSE:
|
||||
LOG(logERROR) << "The requested address is already in use (zmq)";
|
||||
break;
|
||||
case EADDRNOTAVAIL:
|
||||
LOG(logERROR) << "The requested address was not local (zmq)";
|
||||
break;
|
||||
case ENODEV:
|
||||
LOG(logERROR) << "The requested address specifies a nonexistent interface (zmq)";
|
||||
break;
|
||||
case ETERM:
|
||||
LOG(logERROR) << "The ØMQ context associated with the specified socket was terminated (zmq)";
|
||||
break;
|
||||
case ENOTSOCK:
|
||||
LOG(logERROR) << "The provided socket was invalid (zmq)";
|
||||
break;
|
||||
case EINTR:
|
||||
LOG(logERROR) << "The operation was interrupted by delivery of a signal (zmq)";
|
||||
break;
|
||||
case EMTHREAD:
|
||||
LOG(logERROR) << "No I/O thread is available to accomplish the task (zmq)";
|
||||
break;
|
||||
default:
|
||||
LOG(logERROR) << "Unknown socket error (zmq)";
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Class to close socket descriptors automatically
|
||||
* upon encountering exceptions in the ZmqSocket constructor
|
||||
*/
|
||||
class mySocketDescriptors {
|
||||
public:
|
||||
/** Constructor */
|
||||
mySocketDescriptors():
|
||||
server(false),
|
||||
contextDescriptor(0),
|
||||
socketDescriptor(0) {};
|
||||
/** Destructor */
|
||||
~mySocketDescriptors() {
|
||||
Disconnect();
|
||||
Close();
|
||||
}
|
||||
/** Unbinds the Socket */
|
||||
void Disconnect () {
|
||||
if (server)
|
||||
zmq_unbind (socketDescriptor, serverAddress);
|
||||
else
|
||||
zmq_disconnect (socketDescriptor, serverAddress);
|
||||
};
|
||||
/** Close Socket and destroy Context */
|
||||
void Close () {
|
||||
if (socketDescriptor != NULL) {
|
||||
zmq_close (socketDescriptor);
|
||||
socketDescriptor = NULL;
|
||||
}
|
||||
|
||||
if (contextDescriptor != NULL) {
|
||||
zmq_ctx_destroy (contextDescriptor);
|
||||
contextDescriptor = NULL;
|
||||
}
|
||||
};
|
||||
/** true if server, else false */
|
||||
bool server;
|
||||
/** Server Address */
|
||||
char serverAddress[1000];
|
||||
/** Context Descriptor */
|
||||
void* contextDescriptor;
|
||||
/** Socket Descriptor */
|
||||
void* socketDescriptor;
|
||||
};
|
||||
|
||||
private:
|
||||
/** Port Number */
|
||||
uint32_t portno;
|
||||
|
||||
/** Socket descriptor */
|
||||
mySocketDescriptors sockfd;
|
||||
/** Socket descriptor */
|
||||
mySocketDescriptors sockfd;
|
||||
};
|
||||
|
@ -14,8 +14,6 @@
|
||||
#define __cplusplus
|
||||
#endif
|
||||
|
||||
#include "ansi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
//C++ includes
|
||||
#include "sls_detector_exceptions.h"
|
||||
|
@ -5,8 +5,8 @@
|
||||
#define APIGUI 0x200227
|
||||
#define APICTB 0x200310
|
||||
#define APIGOTTHARD 0x200310
|
||||
#define APIGOTTHARD2 0x200310
|
||||
#define APIJUNGFRAU 0x200310
|
||||
#define APIMYTHEN3 0x200310
|
||||
#define APIMOENCH 0x200310
|
||||
#define APIEIGER 0x200310
|
||||
#define APIGOTTHARD2 0x200313
|
||||
|
410
slsSupportLib/src/ZmqSocket.cpp
Normal file
410
slsSupportLib/src/ZmqSocket.cpp
Normal file
@ -0,0 +1,410 @@
|
||||
#include "ZmqSocket.h"
|
||||
#include <zmq.h>
|
||||
#include <vector>
|
||||
#include <arpa/inet.h> //inet_ntoa
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
#include <netdb.h> //gethostbyname()
|
||||
#include <string.h>
|
||||
#include <unistd.h> //usleep in some machines
|
||||
|
||||
using namespace rapidjson;
|
||||
ZmqSocket::ZmqSocket(const char *const hostname_or_ip,
|
||||
const uint32_t portnumber)
|
||||
: portno(portnumber)
|
||||
// headerMessage(0)
|
||||
{
|
||||
char ip[MAX_STR_LENGTH] = "";
|
||||
memset(ip, 0, MAX_STR_LENGTH);
|
||||
|
||||
// convert hostname to ip (not required, but a test that returns if failed)
|
||||
struct addrinfo *result;
|
||||
if ((ConvertHostnameToInternetAddress(hostname_or_ip, &result)) ||
|
||||
(ConvertInternetAddresstoIpString(result, ip, MAX_STR_LENGTH)))
|
||||
throw sls::ZmqSocketError("Could convert IP to string");
|
||||
|
||||
// construct address
|
||||
sprintf(sockfd.serverAddress, "tcp://%s:%d", ip, portno);
|
||||
#ifdef VERBOSE
|
||||
cprintf(BLUE, "address:%s\n", sockfd.serverAddress);
|
||||
#endif
|
||||
|
||||
// create context
|
||||
sockfd.contextDescriptor = zmq_ctx_new();
|
||||
if (sockfd.contextDescriptor == 0)
|
||||
throw sls::ZmqSocketError("Could not create contextDescriptor");
|
||||
|
||||
// create publisher
|
||||
sockfd.socketDescriptor = zmq_socket(sockfd.contextDescriptor, ZMQ_SUB);
|
||||
if (sockfd.socketDescriptor == 0) {
|
||||
PrintError();
|
||||
Close();
|
||||
throw sls::ZmqSocketError("Could not create socket");
|
||||
}
|
||||
|
||||
// Socket Options provided above
|
||||
// an empty string implies receiving any messages
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_SUBSCRIBE, "", 0)) {
|
||||
PrintError();
|
||||
Close();
|
||||
throw sls::ZmqSocketError("Could set socket opt");
|
||||
}
|
||||
// ZMQ_LINGER default is already -1 means no messages discarded. use this
|
||||
// options if optimizing required ZMQ_SNDHWM default is 0 means no limit.
|
||||
// use this to optimize if optimizing required eg. int value = -1;
|
||||
int value = 0;
|
||||
if (zmq_setsockopt(sockfd.socketDescriptor, ZMQ_LINGER, &value,
|
||||
sizeof(value))) {
|
||||
PrintError();
|
||||
Close();
|
||||
throw sls::ZmqSocketError("Could not set ZMQ_LINGER");
|
||||
}
|
||||
}
|
||||
|
||||
ZmqSocket::ZmqSocket(const uint32_t portnumber, const char *ethip)
|
||||
:
|
||||
|
||||
portno(portnumber)
|
||||
// headerMessage(0)
|
||||
{
|
||||
sockfd.server = true;
|
||||
|
||||
// create context
|
||||
sockfd.contextDescriptor = zmq_ctx_new();
|
||||
if (sockfd.contextDescriptor == 0)
|
||||
throw sls::ZmqSocketError("Could not create contextDescriptor");
|
||||
// create publisher
|
||||
sockfd.socketDescriptor = zmq_socket(sockfd.contextDescriptor, ZMQ_PUB);
|
||||
if (sockfd.socketDescriptor == 0) {
|
||||
PrintError();
|
||||
Close();
|
||||
throw sls::ZmqSocketError("Could not create socket");
|
||||
}
|
||||
|
||||
// Socket Options provided above
|
||||
|
||||
// construct addresss
|
||||
sprintf(sockfd.serverAddress, "tcp://%s:%d", ethip, portno);
|
||||
#ifdef VERBOSE
|
||||
cprintf(BLUE, "address:%s\n", sockfd.serverAddress);
|
||||
#endif
|
||||
// bind address
|
||||
if (zmq_bind(sockfd.socketDescriptor, sockfd.serverAddress) < 0) {
|
||||
PrintError();
|
||||
Close();
|
||||
throw sls::ZmqSocketError("Could not bind socket");
|
||||
}
|
||||
|
||||
// sleep for a few milliseconds to allow a slow-joiner
|
||||
usleep(200 * 1000);
|
||||
};
|
||||
|
||||
int ZmqSocket::Connect() {
|
||||
if (zmq_connect(sockfd.socketDescriptor, sockfd.serverAddress) < 0) {
|
||||
PrintError();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ZmqSocket::ConvertHostnameToInternetAddress(const char *const hostname,
|
||||
struct addrinfo **res) {
|
||||
// criteria in selecting socket address structures returned by res
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
// get host info into res
|
||||
int errcode = getaddrinfo(hostname, NULL, &hints, res);
|
||||
if (errcode != 0) {
|
||||
LOG(logERROR) << "Error: Could not convert hostname " << hostname
|
||||
<< " to internet address (zmq):" << gai_strerror(errcode);
|
||||
} else {
|
||||
if (*res == NULL) {
|
||||
LOG(logERROR) << "Could not convert hostname " << hostname
|
||||
<< " to internet address (zmq): "
|
||||
"gettaddrinfo returned null";
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
LOG(logERROR) << "Could not convert hostname to internet address";
|
||||
return 1;
|
||||
};
|
||||
|
||||
int ZmqSocket::ConvertInternetAddresstoIpString(struct addrinfo *res, char *ip,
|
||||
const int ipsize) {
|
||||
if (inet_ntop(res->ai_family,
|
||||
&((struct sockaddr_in *)res->ai_addr)->sin_addr, ip,
|
||||
ipsize) != NULL) {
|
||||
freeaddrinfo(res);
|
||||
return 0;
|
||||
}
|
||||
LOG(logERROR) << "Could not convert internet address to ip string";
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ZmqSocket::PrintError() {
|
||||
switch (errno) {
|
||||
case EINVAL:
|
||||
LOG(logERROR) << "The socket type/option or value/endpoint supplied is "
|
||||
"invalid (zmq)";
|
||||
break;
|
||||
case EAGAIN:
|
||||
LOG(logERROR) << "Non-blocking mode was requested and the message "
|
||||
"cannot be sent/available at the moment (zmq)";
|
||||
break;
|
||||
case ENOTSUP:
|
||||
LOG(logERROR) << "The zmq_send()/zmq_msg_recv() operation is not "
|
||||
"supported by this socket type (zmq)";
|
||||
break;
|
||||
case EFSM:
|
||||
LOG(logERROR) << "The zmq_send()/zmq_msg_recv() unavailable now as "
|
||||
"socket in inappropriate state (eg. ZMQ_REP). Look up "
|
||||
"messaging patterns (zmq)";
|
||||
break;
|
||||
case EFAULT:
|
||||
LOG(logERROR) << "The provided context/message is invalid (zmq)";
|
||||
break;
|
||||
case EMFILE:
|
||||
LOG(logERROR) << "The limit on the total number of open ØMQ sockets "
|
||||
"has been reached (zmq)";
|
||||
break;
|
||||
case EPROTONOSUPPORT:
|
||||
LOG(logERROR)
|
||||
<< "The requested transport protocol is not supported (zmq)";
|
||||
break;
|
||||
case ENOCOMPATPROTO:
|
||||
LOG(logERROR) << "The requested transport protocol is not compatible "
|
||||
"with the socket type (zmq)";
|
||||
break;
|
||||
case EADDRINUSE:
|
||||
LOG(logERROR) << "The requested address is already in use (zmq)";
|
||||
break;
|
||||
case EADDRNOTAVAIL:
|
||||
LOG(logERROR) << "The requested address was not local (zmq)";
|
||||
break;
|
||||
case ENODEV:
|
||||
LOG(logERROR)
|
||||
<< "The requested address specifies a nonexistent interface (zmq)";
|
||||
break;
|
||||
case ETERM:
|
||||
LOG(logERROR) << "The ØMQ context associated with the specified socket "
|
||||
"was terminated (zmq)";
|
||||
break;
|
||||
case ENOTSOCK:
|
||||
LOG(logERROR) << "The provided socket was invalid (zmq)";
|
||||
break;
|
||||
case EINTR:
|
||||
LOG(logERROR)
|
||||
<< "The operation was interrupted by delivery of a signal (zmq)";
|
||||
break;
|
||||
case EMTHREAD:
|
||||
LOG(logERROR)
|
||||
<< "No I/O thread is available to accomplish the task (zmq)";
|
||||
break;
|
||||
default:
|
||||
LOG(logERROR) << "Unknown socket error (zmq)";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ZmqSocket::ReceiveData(const int index, char *buf, const int size) {
|
||||
zmq_msg_t message;
|
||||
zmq_msg_init(&message);
|
||||
int length = ReceiveMessage(index, message);
|
||||
if (length == size) {
|
||||
memcpy(buf, (char *)zmq_msg_data(&message), size);
|
||||
} else if (length < size) {
|
||||
memcpy(buf, (char *)zmq_msg_data(&message), length);
|
||||
memset(buf + length, 0xFF, size - length);
|
||||
} else {
|
||||
LOG(logERROR) << "Received weird packet size " << length
|
||||
<< " for socket " << index;
|
||||
memset(buf, 0xFF, size);
|
||||
}
|
||||
|
||||
zmq_msg_close(&message);
|
||||
return length;
|
||||
}
|
||||
|
||||
int ZmqSocket::ParseHeader(const int index, int length, char *buff,
|
||||
Document &document, bool &dummy, uint32_t version) {
|
||||
if (document.Parse(buff, length).HasParseError()) {
|
||||
LOG(logERROR) << index << " Could not parse. len:" << length
|
||||
<< ": Message:" << buff;
|
||||
fflush(stdout);
|
||||
// char* buf = (char*) zmq_msg_data (&message);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
cprintf(RED, "%02x ", buff[i]);
|
||||
}
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (document["jsonversion"].GetUint() != version) {
|
||||
LOG(logERROR) << "version mismatch. required " << version << ", got "
|
||||
<< document["jsonversion"].GetUint();
|
||||
return 0;
|
||||
}
|
||||
|
||||
dummy = false;
|
||||
int temp = document["data"].GetUint();
|
||||
dummy = temp ? false : true;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ZmqSocket::ReceiveHeader(const int index, Document &document,
|
||||
uint32_t version) {
|
||||
std::vector<char> buffer(MAX_STR_LENGTH);
|
||||
int len =
|
||||
zmq_recv(sockfd.socketDescriptor, buffer.data(), buffer.size(), 0);
|
||||
if (len > 0) {
|
||||
bool dummy = false;
|
||||
#ifdef ZMQ_DETAIL
|
||||
cprintf(BLUE, "Header %d [%d] Length: %d Header:%s \n", index, portno,
|
||||
len, buffer.data());
|
||||
#endif
|
||||
if (ParseHeader(index, len, buffer.data(), document, dummy, version)) {
|
||||
#ifdef ZMQ_DETAIL
|
||||
cprintf(RED, "Parsed Header %d [%d] Length: %d Header:%s \n", index,
|
||||
portno, len, buffer.data());
|
||||
#endif
|
||||
if (dummy) {
|
||||
#ifdef ZMQ_DETAIL
|
||||
cprintf(RED, "%d [%d] Received end of acquisition\n", index,
|
||||
portno);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#ifdef ZMQ_DETAIL
|
||||
cprintf(GREEN, "%d [%d] data\n", index, portno);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
int ZmqSocket::ReceiveMessage(const int index, zmq_msg_t &message) {
|
||||
int length = zmq_msg_recv(&message, sockfd.socketDescriptor, 0);
|
||||
if (length == -1) {
|
||||
PrintError();
|
||||
LOG(logERROR) << "Could not read header for socket " << index;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
int ZmqSocket::SendData(char *buf, int length) {
|
||||
if (zmq_send(sockfd.socketDescriptor, buf, length, 0) < 0) {
|
||||
PrintError();
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ZmqSocket::SendHeaderData(
|
||||
int index, bool dummy, uint32_t jsonversion, uint32_t dynamicrange,
|
||||
uint64_t fileIndex, uint32_t ndetx, uint32_t ndety, uint32_t npixelsx,
|
||||
uint32_t npixelsy, uint32_t imageSize, uint64_t acqIndex, uint64_t fIndex,
|
||||
const char *fname, uint64_t frameNumber, uint32_t expLength,
|
||||
uint32_t packetNumber, uint64_t bunchId, uint64_t timestamp, uint16_t modId,
|
||||
uint16_t row, uint16_t column, uint16_t reserved, uint32_t debug,
|
||||
uint16_t roundRNumber, uint8_t detType, uint8_t version,
|
||||
int gapPixelsEnable, int flippedDataX, uint32_t quadEnable,
|
||||
std::string *additionalJsonHeader) {
|
||||
|
||||
/** Json Header Format */
|
||||
const char jsonHeaderFormat[] = "{"
|
||||
"\"jsonversion\":%u, "
|
||||
"\"bitmode\":%u, "
|
||||
"\"fileIndex\":%lu, "
|
||||
"\"detshape\":[%u, %u], "
|
||||
"\"shape\":[%u, %u], "
|
||||
"\"size\":%u, "
|
||||
"\"acqIndex\":%lu, "
|
||||
"\"fIndex\":%lu, "
|
||||
"\"fname\":\"%s\", "
|
||||
"\"data\": %d, "
|
||||
|
||||
"\"frameNumber\":%lu, "
|
||||
"\"expLength\":%u, "
|
||||
"\"packetNumber\":%u, "
|
||||
"\"bunchId\":%lu, "
|
||||
"\"timestamp\":%lu, "
|
||||
"\"modId\":%u, "
|
||||
"\"row\":%u, "
|
||||
"\"column\":%u, "
|
||||
"\"reserved\":%u, "
|
||||
"\"debug\":%u, "
|
||||
"\"roundRNumber\":%u, "
|
||||
"\"detType\":%u, "
|
||||
"\"version\":%u, "
|
||||
|
||||
// additional stuff
|
||||
"\"gappixels\":%u, "
|
||||
"\"flippedDataX\":%u, "
|
||||
"\"quad\":%u"
|
||||
|
||||
; //"}\n";
|
||||
char buf[MAX_STR_LENGTH] = "";
|
||||
sprintf(buf, jsonHeaderFormat, jsonversion, dynamicrange, fileIndex, ndetx,
|
||||
ndety, npixelsx, npixelsy, imageSize, acqIndex, fIndex,
|
||||
(fname == NULL) ? "" : fname, dummy ? 0 : 1,
|
||||
|
||||
frameNumber, expLength, packetNumber, bunchId, timestamp, modId,
|
||||
row, column, reserved, debug, roundRNumber, detType, version,
|
||||
|
||||
// additional stuff
|
||||
gapPixelsEnable, flippedDataX, quadEnable);
|
||||
|
||||
if (additionalJsonHeader && !((*additionalJsonHeader).empty())) {
|
||||
strcat(buf, ", ");
|
||||
strcat(buf, (*additionalJsonHeader).c_str());
|
||||
}
|
||||
strcat(buf, "}\n");
|
||||
int length = strlen(buf);
|
||||
|
||||
#ifdef VERBOSE
|
||||
// if(!index)
|
||||
cprintf(BLUE, "%d : Streamer: buf: %s\n", index, buf);
|
||||
#endif
|
||||
|
||||
if (zmq_send(sockfd.socketDescriptor, buf, length,
|
||||
dummy ? 0 : ZMQ_SNDMORE) < 0) {
|
||||
PrintError();
|
||||
return 0;
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
cprintf(GREEN, "[%u] send header data\n", portno);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//Nested class to do RAII handling of socket descriptors
|
||||
ZmqSocket::mySocketDescriptors::mySocketDescriptors()
|
||||
: server(false), contextDescriptor(0), socketDescriptor(0){};
|
||||
ZmqSocket::mySocketDescriptors::~mySocketDescriptors() {
|
||||
Disconnect();
|
||||
Close();
|
||||
}
|
||||
void ZmqSocket::mySocketDescriptors::Disconnect() {
|
||||
if (server)
|
||||
zmq_unbind(socketDescriptor, serverAddress);
|
||||
else
|
||||
zmq_disconnect(socketDescriptor, serverAddress);
|
||||
};
|
||||
void ZmqSocket::mySocketDescriptors::Close() {
|
||||
if (socketDescriptor != NULL) {
|
||||
zmq_close(socketDescriptor);
|
||||
socketDescriptor = NULL;
|
||||
}
|
||||
|
||||
if (contextDescriptor != NULL) {
|
||||
zmq_ctx_destroy(contextDescriptor);
|
||||
contextDescriptor = NULL;
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user