Compare commits

...

22 Commits

Author SHA1 Message Date
cb8403f1b0 zmq 2020-03-18 12:38:06 +01:00
b751238fc1 ZmqSocket 2020-03-18 12:12:01 +01:00
5479d3a198 fix 2020-03-18 11:11:00 +01:00
e1768905dd build interface 2020-03-18 11:06:37 +01:00
775d0842e9 build interface 2020-03-18 11:00:54 +01:00
e7e201bd2a export and include 2020-03-18 10:20:01 +01:00
ec9f8305e9 not export gui 2020-03-18 08:41:25 +01:00
3307bfab1b fix 2020-03-17 19:11:29 +01:00
ce2c62000d include cmake in build 2020-03-17 18:57:19 +01:00
cf817c4ec1 WIP 2020-03-17 18:29:51 +01:00
bd01a5f2d2 cmake pkg 2020-03-16 19:36:18 +01:00
b059ba7c90 Merge branch 'developer' of github.com:slsdetectorgroup/slsDetectorPackage into developer 2020-03-16 15:43:55 +01:00
89d70097f6 WIP 2020-03-16 15:43:46 +01:00
41d115a394 Merge branch 'developer' of github.com:slsdetectorgroup/slsDetectorPackage into developer 2020-03-13 19:36:38 +01:00
45c1d3a553 gotthard2: burst mode fix for all the registers 2020-03-13 19:36:23 +01:00
17227be4df gotthard2: burst mode fix 2020-03-13 17:39:16 +01:00
7f4f8e8f09 help bug emax 2020-03-13 09:56:11 +01:00
6809bd6567 removed header 2020-03-12 12:38:00 +01:00
711d40a56e added sendToReceiver 2020-03-12 11:45:12 +01:00
81911fae3c new version of send to detector 2020-03-11 19:18:26 +01:00
f940397e3a cleaning 2020-03-11 18:10:37 +01:00
dc53887a48 minor clean 2020-03-11 17:49:32 +01:00
35 changed files with 1178 additions and 914 deletions

View File

@ -203,11 +203,9 @@ if(SLS_BUILD_DOCS)
add_subdirectory(docs) add_subdirectory(docs)
endif(SLS_BUILD_DOCS) endif(SLS_BUILD_DOCS)
if(SLS_MASTER_PROJECT) if(SLS_MASTER_PROJECT)
# Set install dir CMake packages # 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 the list of exported targets
set(PROJECT_LIBRARIES slsSupportLib slsDetectorShared slsReceiverShared) set(PROJECT_LIBRARIES slsSupportLib slsDetectorShared slsReceiverShared)
# Generate and install package config file and version # Generate and install package config file and version

View File

@ -15,17 +15,20 @@ configure_package_config_file(
write_basic_package_version_file( write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake"
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion) COMPATIBILITY SameMajorVersion
)
install(FILES install(FILES
"${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config.cmake"
"${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME_LOWER}-config-version.cmake"
COMPONENT devel COMPONENT devel
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME_LOWER}) DESTINATION ${CMAKE_INSTALL_DIR}
)
if (PROJECT_LIBRARIES OR PROJECT_STATIC_LIBRARIES) if (PROJECT_LIBRARIES OR PROJECT_STATIC_LIBRARIES)
install( install(
EXPORT "${TARGETS_EXPORT_NAME}" EXPORT "${TARGETS_EXPORT_NAME}"
FILE ${PROJECT_NAME_LOWER}-targets.cmake FILE ${PROJECT_NAME_LOWER}-targets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME_LOWER}) DESTINATION ${CMAKE_INSTALL_DIR}
)
endif () endif ()

View File

@ -5,18 +5,20 @@ mkdir $PREFIX/include
mkdir $PREFIX/include/slsDetectorPackage mkdir $PREFIX/include/slsDetectorPackage
#Shared and static libraries #Shared and static libraries
cp build/bin/libSlsDetector.so $PREFIX/lib/. # cp build/bin/libSlsDetector.so $PREFIX/lib/.
cp build/bin/libSlsReceiver.so $PREFIX/lib/. # cp build/bin/libSlsReceiver.so $PREFIX/lib/.
cp build/bin/libSlsSupport.so $PREFIX/lib/. # cp build/bin/libSlsSupport.so $PREFIX/lib/.
cp build/install/lib/* $PREFIX/lib/
#Binaries #Binaries
cp build/bin/sls_detector_acquire $PREFIX/bin/. cp build/install/bin/sls_detector_acquire $PREFIX/bin/.
cp build/bin/sls_detector_get $PREFIX/bin/. cp build/install/bin/sls_detector_get $PREFIX/bin/.
cp build/bin/sls_detector_put $PREFIX/bin/. cp build/install/bin/sls_detector_put $PREFIX/bin/.
cp build/bin/sls_detector_help $PREFIX/bin/. cp build/install/bin/sls_detector_help $PREFIX/bin/.
cp build/bin/slsReceiver $PREFIX/bin/. cp build/install/bin/slsReceiver $PREFIX/bin/.
cp build/bin/slsMultiReceiver $PREFIX/bin/. cp build/install/bin/slsMultiReceiver $PREFIX/bin/.
#Which headers do we need for development??
cp build/install/include/* $PREFIX/include/slsDetectorPackage/ cp build/install/include/* $PREFIX/include/
# cp include/some_lib.h $PREFIX/include/. cp -r build/install/share/ $PREFIX/share

View File

@ -7,7 +7,7 @@ source:
- path: .. - path: ..
build: build:
number: 2 number: 0
binary_relocation: True binary_relocation: True
rpaths: rpaths:
- lib/ - lib/
@ -37,6 +37,7 @@ requirements:
host: host:
- libstdcxx-ng - libstdcxx-ng
- libgcc-ng - libgcc-ng
- zeromq
- xorg-libx11 - xorg-libx11
- xorg-libice - xorg-libice
- xorg-libxext - xorg-libxext
@ -46,6 +47,7 @@ requirements:
- xorg-libxfixes - xorg-libxfixes
run: run:
- zeromq
- libstdcxx-ng - libstdcxx-ng
- libgcc-ng - libgcc-ng

View File

@ -3,7 +3,7 @@ find_package(Sphinx)
if (DOXYGEN_FOUND AND SPHINX_FOUND) 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 # Utility to generate command line documentation
add_executable(gendoc src/gendoc.cpp) add_executable(gendoc src/gendoc.cpp)
# This is a bit hacky, but better than exposing stuff? # This is a bit hacky, but better than exposing stuff?
@ -30,6 +30,7 @@ if (DOXYGEN_FOUND AND SPHINX_FOUND)
set(SPHINX_SOURCE_FILES set(SPHINX_SOURCE_FILES
src/commandline.rst src/commandline.rst
src/container_utils.rst src/container_utils.rst
src/consuming.rst
src/dependencies.rst src/dependencies.rst
src/detector.rst src/detector.rst
src/index.rst src/index.rst
@ -41,6 +42,7 @@ if (DOXYGEN_FOUND AND SPHINX_FOUND)
src/result.rst src/result.rst
src/type_traits.rst src/type_traits.rst
src/ToString.rst src/ToString.rst
src/examples.rst
) )

95
docs/src/consuming.rst Normal file
View 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

View File

@ -13,7 +13,7 @@ To use the basic building blocks, meaning sls_detector_get/put and
the shared libraries these are needed: the shared libraries these are needed:
* Linux, preferably recent kernel (currently no cross platform support) * 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) * C++11 compatible compiler. (We test with gcc and clang)
* ZeroMQ version 4 * ZeroMQ version 4
@ -24,7 +24,7 @@ GUI
The GUI is currently using Qt4 but watch out for an upgrade to 5. The GUI is currently using Qt4 but watch out for an upgrade to 5.
* Qt 4.8 * Qt 4.8
* Qwt 6 * Qwt 6.1
----------------------- -----------------------
Python bindings Python bindings

115
docs/src/examples.rst Normal file
View 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);

View File

@ -6,12 +6,18 @@
Welcome to slsDetectorPackage's documentation! 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:: .. toctree::
:maxdepth: 1 :maxdepth: 1
:caption: Installation: :caption: Installation:
installation installation
dependencies dependencies
consuming
.. toctree:: .. toctree::
:caption: C++ API :caption: C++ API
@ -20,6 +26,7 @@ Welcome to slsDetectorPackage's documentation!
detector detector
result result
receiver receiver
examples
.. toctree:: .. toctree::
:caption: Python API :caption: Python API

View File

@ -2,4 +2,24 @@
Installation 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

View File

@ -1,9 +1,9 @@
Detector Detector
===================================================== =====================================================
.. py:currentmodule:: sls_detector .. py:currentmodule:: slsdet
.. autoclass:: ExperimentalDetector .. autoclass:: Detector
:members: :members:
:undoc-members: :undoc-members:
:show-inheritance: :show-inheritance:

View File

@ -45,7 +45,7 @@ ext_modules = [
# get_pybind_include(), # get_pybind_include(),
# get_pybind_include(user=True), # get_pybind_include(user=True),
os.path.join('../libs/pybind11/include'), 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'], libraries=['SlsDetector', 'SlsReceiver', 'zmq'],

View File

@ -103,10 +103,10 @@ set_target_properties(slsDetectorGui PROPERTIES
) )
install(TARGETS slsDetectorGui install(TARGETS slsDetectorGui
EXPORT "${TARGETS_EXPORT_NAME}" # EXPORT "${TARGETS_EXPORT_NAME}"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
) )

View File

@ -1,5 +1,5 @@
#include "SlsQt2DPlot.h" #include "SlsQt2DPlot.h"
#include "ansi.h" // #include "ansi.h"
#include <qlist.h> #include <qlist.h>
#include <qprinter.h> #include <qprinter.h>

View File

@ -47,9 +47,10 @@ int injectedChannelsIncrement = 0;
int vetoReference[NCHIP][NCHAN]; int vetoReference[NCHIP][NCHAN];
uint8_t adcConfiguration[NCHIP][NADC]; uint8_t adcConfiguration[NCHIP][NADC];
int burstMode = BURST_INTERNAL; int burstMode = BURST_INTERNAL;
int64_t numTriggers = 1; int64_t numTriggersReg = 1;
int64_t numBursts = 1; int64_t delayReg = 0;
int64_t burstPeriodNs = 0; int64_t numBurstsReg = 1;
int64_t burstPeriodReg = 0;
int detPos[2] = {}; int detPos[2] = {};
int isInitCheckDone() { int isInitCheckDone() {
@ -354,9 +355,10 @@ void setupDetector() {
injectedChannelsOffset = 0; injectedChannelsOffset = 0;
injectedChannelsIncrement = 0; injectedChannelsIncrement = 0;
burstMode = BURST_INTERNAL; burstMode = BURST_INTERNAL;
numTriggers = 1; numTriggersReg = 1;
numBursts = 1; delayReg = 0;
burstPeriodNs = 0; numBurstsReg = 1;
burstPeriodReg = 0;
{ {
int i, j; int i, j;
for (i = 0; i < NUM_CLOCKS; ++i) { for (i = 0; i < NUM_CLOCKS; ++i) {
@ -736,32 +738,31 @@ int setDynamicRange(int dr){
/* parameters - timer */ /* parameters - timer */
void setNumFrames(int64_t val) { void setNumFrames(int64_t val) {
if (val > 0) { if (val > 0) {
LOG(logINFO, ("Setting number of frames %lld [local]\n", val));
// continuous mode
if (burstMode == BURST_OFF) { if (burstMode == BURST_OFF) {
setNumFramesCont(val); LOG(logINFO, ("Setting number of frames %lld [Continuous mode]\n", val));
setNumFramesBurst(1); set64BitReg(val, SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
} else { } else {
setNumFramesBurst(val); LOG(logINFO, ("Setting number of frames %d [Burst mode]\n", (int)val));
setNumFramesCont(1); 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() { int64_t getNumFrames() {
if (burstMode == BURST_OFF) { if (burstMode == BURST_OFF) {
return getNumFramesCont(); return get64BitReg(SET_FRAMES_LSB_REG, SET_FRAMES_MSB_REG);
} else { } else {
return getNumFramesBurst(); return ((bus_r(ASIC_INT_FRAMES_REG) & ASIC_INT_FRAMES_MSK) >> ASIC_INT_FRAMES_OFST);
} }
} }
void setNumTriggers(int64_t val) { void setNumTriggers(int64_t val) {
if (val > 0) { if (val > 0) {
LOG(logINFO, ("Setting number of triggers %lld\n", val)); LOG(logINFO, ("Setting number of triggers %lld\n", val));
numTriggers = val; if (getTiming() == AUTO_TIMING) {
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) { LOG(logINFO, ("\tNot trigger mode: not writing to register\n"));
LOG(logINFO, ("\tBurst and Auto mode: not writing #triggers to register\n")); numTriggersReg = val;
} else { } else {
set64BitReg(val, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG); set64BitReg(val, SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
} }
@ -769,8 +770,8 @@ void setNumTriggers(int64_t val) {
} }
int64_t getNumTriggers() { int64_t getNumTriggers() {
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) { if (getTiming() == AUTO_TIMING) {
return numTriggers; return numTriggersReg;
} }
return get64BitReg(SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG); return get64BitReg(SET_CYCLES_LSB_REG, SET_CYCLES_MSB_REG);
} }
@ -778,20 +779,20 @@ int64_t getNumTriggers() {
void setNumBursts(int64_t val) { void setNumBursts(int64_t val) {
if (val > 0) { if (val > 0) {
LOG(logINFO, ("Setting number of bursts %lld\n", val)); LOG(logINFO, ("Setting number of bursts %lld\n", val));
numBursts = val;
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) { 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 { } 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() { int64_t getNumBursts() {
if (burstMode != BURST_OFF && getTiming() == AUTO_TIMING) { 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) { int setExpTime(int64_t val) {
@ -799,17 +800,21 @@ int setExpTime(int64_t val) {
LOG(logERROR, ("Invalid exptime: %lld ns\n", val)); LOG(logERROR, ("Invalid exptime: %lld ns\n", val));
return FAIL; return FAIL;
} }
LOG(logINFO, ("Setting exptime %lld ns [local]\n", val)); LOG(logINFO, ("Setting exptime %lld ns\n", val));
// continuous mode val *= (1E-9 * systemFrequency);
if (burstMode == BURST_OFF) { set64BitReg(val, ASIC_INT_EXPTIME_LSB_REG, ASIC_INT_EXPTIME_MSB_REG);
return setExptimeCont(val);
} else { // validate for tolerance
return setExptimeBurst(val); int64_t retval = getExpTime();
val /= (1E-9 * systemFrequency);
if (val != retval) {
return FAIL;
} }
return OK;
} }
int64_t getExpTime() { 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) { int setPeriod(int64_t val) {
@ -817,108 +822,29 @@ int setPeriod(int64_t val) {
LOG(logERROR, ("Invalid period: %lld ns\n", val)); LOG(logERROR, ("Invalid period: %lld ns\n", val));
return FAIL; return FAIL;
} }
LOG(logINFO, ("Setting period %lld ns [local]\n", val)); val *= (1E-9 * systemFrequency);
// continuous mode
if (burstMode == BURST_OFF) { if (burstMode == BURST_OFF) {
setPeriodBurst(0); LOG(logINFO, ("Setting period %lld ns [Continuous mode]\n", val));
return setPeriodCont(val); set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
} else { } else {
//setPeriodCont(0); LOG(logINFO, ("Setting period %lld ns [Burst mode]\n", val));
return setPeriodBurst(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() { int64_t getPeriod() {
if (burstMode == BURST_OFF) { if (burstMode == BURST_OFF) {
return getPeriodCont();
} else {
return getPeriodBurst();
}
}
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); return get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
} else {
return get64BitReg(ASIC_INT_PERIOD_LSB_REG, ASIC_INT_PERIOD_MSB_REG)/ (1E-9 * systemFrequency);
}
} }
int setDelayAfterTrigger(int64_t val) { int setDelayAfterTrigger(int64_t val) {
@ -928,8 +854,12 @@ int setDelayAfterTrigger(int64_t val) {
} }
LOG(logINFO, ("Setting delay after trigger %lld ns\n", val)); LOG(logINFO, ("Setting delay after trigger %lld ns\n", val));
val *= (1E-9 * systemFrequency); val *= (1E-9 * systemFrequency);
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); set64BitReg(val, SET_TRIGGER_DELAY_LSB_REG, SET_TRIGGER_DELAY_MSB_REG);
}
// validate for tolerance // validate for tolerance
int64_t retval = getDelayAfterTrigger(); int64_t retval = getDelayAfterTrigger();
val /= (1E-9 * systemFrequency); val /= (1E-9 * systemFrequency);
@ -940,6 +870,9 @@ int setDelayAfterTrigger(int64_t val) {
} }
int64_t getDelayAfterTrigger() { 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); 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; return FAIL;
} }
LOG(logINFO, ("Setting burst period %lld ns\n", val)); LOG(logINFO, ("Setting burst period %lld ns\n", val));
burstPeriodNs = val;
val *= (1E-9 * systemFrequency); 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); set64BitReg(val, SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG);
} else { } 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 // validate for tolerance
@ -967,10 +900,10 @@ int setBurstPeriod(int64_t val) {
} }
int64_t getBurstPeriod() { 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 get64BitReg(SET_PERIOD_LSB_REG, SET_PERIOD_MSB_REG) / (1E-9 * systemFrequency);
} }
return burstPeriodNs; return burstPeriodReg / (1E-9 * systemFrequency);
} }
int64_t getNumFramesLeft() { int64_t getNumFramesLeft() {
@ -1185,6 +1118,18 @@ int setHighVoltage(int val){
/* parameters - timing */ /* parameters - timing */
void setTiming( enum timingMode arg){ 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){ switch(arg){
case AUTO_TIMING: case AUTO_TIMING:
LOG(logINFO, ("Set Timing: Auto\n")); LOG(logINFO, ("Set Timing: Auto\n"));
@ -1198,9 +1143,32 @@ void setTiming( enum timingMode arg){
LOG(logERROR, ("Unknown timing mode %d\n", arg)); LOG(logERROR, ("Unknown timing mode %d\n", arg));
} }
LOG(logINFO, ("\tUpdating trigger/burst and delay/burst period registers\n")) LOG(logINFO, ("\tUpdating registers\n"))
setNumTriggers(numTriggers); // trigger
setNumBursts(numBursts); 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() { enum timingMode getTiming() {
@ -1875,23 +1843,62 @@ int setBurstModeinFPGA(enum burstMode value) {
int setBurstMode(enum burstMode burst) { int setBurstMode(enum burstMode burst) {
LOG(logINFO, ("Setting burst mode to %s\n", burst == BURST_OFF ? "off" : (burst == BURST_INTERNAL ? "internal" : "external"))); 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) // update
int64_t frames = getNumFrames(); int64_t framesReg = 0;
int64_t period = getPeriod(); 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) { if (setBurstModeinFPGA(burst) == FAIL) {
return FAIL; return FAIL;
} }
LOG(logINFO, ("\tUpdating trigger/burst and burst period registers\n")) LOG(logINFO, ("\tUpdating registers\n"));
setNumTriggers(numTriggers); // continuous
setNumBursts(numBursts); if (burstMode == BURST_OFF) {
setBurstPeriod(burstPeriodNs); 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, ("\tInt. Frame reg: 1, Int. Period reg: 0\n"))
LOG(logINFO, ("\tUpdating #frames and period registers\n")); bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) &~ ASIC_INT_FRAMES_MSK);
setNumFrames(frames); bus_w(ASIC_INT_FRAMES_REG, bus_r(ASIC_INT_FRAMES_REG) | ((1 << ASIC_INT_FRAMES_OFST) & ASIC_INT_FRAMES_MSK));
setPeriod(period); 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")); LOG(logINFO, ("\tSetting %s Mode in Chip\n", burstMode == BURST_OFF ? "Continuous" : "Burst"));
int value = burstMode ? ASIC_GLOBAL_BURST_VALUE : ASIC_GLOBAL_CONT_VALUE; int value = burstMode ? ASIC_GLOBAL_BURST_VALUE : ASIC_GLOBAL_CONT_VALUE;

View File

@ -14,15 +14,12 @@ add_executable(jungfrauDetectorServer_virtual
../slsDetectorServer/src/communication_funcs_UDP.c ../slsDetectorServer/src/communication_funcs_UDP.c
) )
include_directories( target_include_directories(jungfrauDetectorServer_virtual
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
../slsDetectorServer/include ../slsDetectorServer/include
../../slsSupportLib/include ../../slsSupportLib/include
) )
target_include_directories(jungfrauDetectorServer_virtual
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
)
target_compile_definitions(jungfrauDetectorServer_virtual target_compile_definitions(jungfrauDetectorServer_virtual
PUBLIC JUNGFRAUD VIRTUAL STOP_SERVER PUBLIC JUNGFRAUD VIRTUAL STOP_SERVER
) )
@ -36,5 +33,6 @@ set_target_properties(jungfrauDetectorServer_virtual PROPERTIES
) )
install(TARGETS jungfrauDetectorServer_virtual install(TARGETS jungfrauDetectorServer_virtual
EXPORT "${TARGETS_EXPORT_NAME}"
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
) )

View File

@ -202,19 +202,6 @@ void setNumBursts(int64_t val);
int64_t getNumBursts(); int64_t getNumBursts();
int setBurstPeriod(int64_t val); int setBurstPeriod(int64_t val);
int64_t getBurstPeriod(); 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 #endif
#ifdef EIGERD #ifdef EIGERD
int setSubExpTime(int64_t val); int setSubExpTime(int64_t val);

View File

@ -15,7 +15,6 @@ add_library(slsDetectorShared SHARED
${HEADERS} ${HEADERS}
) )
# Do we have link time optimization? # Do we have link time optimization?
check_ipo_supported(RESULT LTO_AVAILABLE) check_ipo_supported(RESULT LTO_AVAILABLE)
if(LTO_AVAILABLE) if(LTO_AVAILABLE)
@ -28,15 +27,18 @@ target_include_directories(slsDetectorShared PUBLIC
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
) )
target_link_libraries(slsDetectorShared PUBLIC target_link_libraries(slsDetectorShared
slsProjectOptions PUBLIC
slsProjectWarnings
slsSupportLib slsSupportLib
${ZeroMQ_LIBRARIES}
pthread pthread
rt rt
slsProjectOptions
PRIVATE
slsProjectWarnings
${ZeroMQ_LIBRARIES}
) )
set(PUBLICHEADERS set(PUBLICHEADERS
include/slsDetectorUsers.h include/slsDetectorUsers.h
include/detectorData.h include/detectorData.h
@ -69,7 +71,7 @@ foreach(val RANGE ${len2})
target_link_libraries(${val1} target_link_libraries(${val1}
slsDetectorShared slsDetectorShared
pthread pthread
${ZeroMQ_LIBRARIES} zmq
rt rt
) )
set_target_properties(${val1} PROPERTIES set_target_properties(${val1} PROPERTIES

View File

@ -1,15 +1,17 @@
#pragma once #pragma once
#include "Result.h" #include "Result.h"
#include "network_utils.h"
#include "sls_detector_defs.h" #include "sls_detector_defs.h"
#include <chrono> #include <chrono>
#include <memory> #include <memory>
#include <vector> #include <vector>
class DetectorImpl;
class detectorData; class detectorData;
namespace sls { namespace sls {
using ns = std::chrono::nanoseconds; using ns = std::chrono::nanoseconds;
class DetectorImpl;
class MacAddr; class MacAddr;
class IpAddr; class IpAddr;

View File

@ -1782,7 +1782,7 @@ std::string CmdProxy::MinMaxEnergyThreshold(int action) {
os << "[n_value]\n\t[Moench] Minimum energy threshold (soft " os << "[n_value]\n\t[Moench] Minimum energy threshold (soft "
"setting) for processor." "setting) for processor."
<< '\n'; << '\n';
} else if (cmd == "emin") { } else if (cmd == "emax") {
os << "[n_value]\n\t[Moench] Maximum energy threshold (soft " os << "[n_value]\n\t[Moench] Maximum energy threshold (soft "
"setting) for processor." "setting) for processor."
<< '\n'; << '\n';

View File

@ -7,6 +7,7 @@
#include "DetectorImpl.h" #include "DetectorImpl.h"
#include "Module.h" #include "Module.h"
#include "sls_detector_defs.h" #include "sls_detector_defs.h"
#include "versionAPI.h"
#include <fstream> #include <fstream>
@ -97,11 +98,11 @@ void Detector::setVirtualDetectorServers(int numServers, int startingPort) {
int Detector::getShmId() const { return pimpl->getMultiId(); } int Detector::getShmId() const { return pimpl->getMultiId(); }
std::string Detector::getPackageVersion() const { std::string Detector::getPackageVersion() const {
return pimpl->getPackageVersion(); return GITBRANCH;
} }
int64_t Detector::getClientVersion() const { int64_t Detector::getClientVersion() const {
return pimpl->getClientSoftwareVersion(); return APILIB;
} }
Result<int64_t> Detector::getFirmwareVersion(Positions pos) const { Result<int64_t> Detector::getFirmwareVersion(Positions pos) const {

View File

@ -26,7 +26,7 @@
#include <future> #include <future>
#include <vector> #include <vector>
using namespace sls; namespace sls{
DetectorImpl::DetectorImpl(int multi_id, bool verify, bool update) DetectorImpl::DetectorImpl(int multi_id, bool verify, bool update)
: multiId(multi_id), multi_shm(multi_id, -1) { : multiId(multi_id), multi_shm(multi_id, -1) {
@ -49,10 +49,6 @@ void DetectorImpl::setAcquiringFlag(bool flag) {
int DetectorImpl::getMultiId() const { return multiId; } 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) { void DetectorImpl::freeSharedMemory(int multiId, int detPos) {
// single // single
if (detPos >= 0) { if (detPos >= 0) {
@ -160,7 +156,6 @@ void DetectorImpl::initializeDetectorStructure() {
multi_shm()->numberOfChannels.x = 0; multi_shm()->numberOfChannels.x = 0;
multi_shm()->numberOfChannels.y = 0; multi_shm()->numberOfChannels.y = 0;
multi_shm()->acquiringFlag = false; multi_shm()->acquiringFlag = false;
multi_shm()->receiver_upstream = false;
multi_shm()->initialChecks = true; multi_shm()->initialChecks = true;
} }
@ -822,46 +817,6 @@ bool DetectorImpl::enableDataStreamingToClient(int enable) {
return client_downstream; 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 DetectorImpl::registerAcquisitionFinishedCallback(void (*func)(double, int,
void *), void *),
void *pArg) { void *pArg) {
@ -1199,3 +1154,5 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
LOG(logINFO) << "Read file into memory"; LOG(logINFO) << "Read file into memory";
return buffer; return buffer;
} }
}//namespace sls

View File

@ -5,10 +5,6 @@
#include "logger.h" #include "logger.h"
#include "sls_detector_defs.h" #include "sls_detector_defs.h"
namespace sls{
class Module;
}
class ZmqSocket; class ZmqSocket;
class detectorData; class detectorData;
@ -25,6 +21,11 @@ class detectorData;
#include <future> #include <future>
#include <numeric> #include <numeric>
namespace sls{
class Module;
/** /**
* @short structure allocated in shared memory to store detector settings * @short structure allocated in shared memory to store detector settings
* for IPC and cache * for IPC and cache
@ -64,9 +65,6 @@ struct sharedMultiSlsDetector {
/** flag for acquiring */ /** flag for acquiring */
bool acquiringFlag; bool acquiringFlag;
/** data streaming (up stream) enable in receiver */
bool receiver_upstream;
/** initial checks */ /** initial checks */
bool initialChecks; bool initialChecks;
}; };
@ -202,10 +200,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** return multi detector shared memory ID */ /** return multi detector shared memory ID */
int getMultiId() const; int getMultiId() const;
std::string getPackageVersion() const;
int64_t getClientSoftwareVersion() const;
/** Free specific shared memory from the command line without creating object */ /** Free specific shared memory from the command line without creating object */
static void freeSharedMemory(int multiId, int detPos = -1); static void freeSharedMemory(int multiId, int detPos = -1);
@ -255,8 +249,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
*/ */
bool enableDataStreamingToClient(int enable = -1); bool enableDataStreamingToClient(int enable = -1);
void savePattern(const std::string &fname);
/** /**
* register callback for accessing acquisition final data * register callback for accessing acquisition final data
* @param func function to be called at the end of the acquisition. * @param func function to be called at the end of the acquisition.
@ -393,14 +385,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
*/ */
int kbhit(); 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 */ /** Multi detector Id */
const int multiId{0}; const int multiId{0};
@ -448,3 +432,5 @@ class DetectorImpl : public virtual slsDetectorDefs {
void (*dataReady)(detectorData *, uint64_t, uint32_t, void *){nullptr}; void (*dataReady)(detectorData *, uint64_t, uint32_t, void *){nullptr};
void *pCallbackArg{nullptr}; void *pCallbackArg{nullptr};
}; };
}//namespace sls

View File

@ -164,6 +164,29 @@ void Module::sendToDetector(int fnum) {
sendToDetector(fnum, nullptr, 0, nullptr, 0); 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, void Module::sendToDetectorStop(int fnum, const void *args,
size_t args_size, void *retval, size_t args_size, void *retval,
size_t retval_size) { 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)); sendToReceiver(fnum, nullptr, 0, &retval, sizeof(retval));
} }
void Module::sendToReceiver(int fnum) { template <typename Ret>
sendToReceiver(fnum, nullptr, 0, nullptr, 0); 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 { template <typename Ret>
sendToReceiver(fnum, nullptr, 0, nullptr, 0); 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() { void Module::freeSharedMemory() {
if (shm.IsExisting()) { if (shm.IsExisting()) {
shm.RemoveSharedMemory(); shm.RemoveSharedMemory();
@ -1277,10 +1344,7 @@ void Module::setNumberOfDigitalSamples(int value) {
} }
int64_t Module::getExptime() { int64_t Module::getExptime() {
int64_t retval = -1; return sendToDetector<int64_t>(F_GET_EXPTIME);
sendToDetector(F_GET_EXPTIME, nullptr, retval);
LOG(logDEBUG1) << "exptime :" << retval << "ns";
return retval;
} }
void Module::setExptime(int64_t value) { void Module::setExptime(int64_t value) {
@ -1303,10 +1367,7 @@ void Module::setExptime(int64_t value) {
} }
int64_t Module::getPeriod() { int64_t Module::getPeriod() {
int64_t retval = -1; return sendToDetector<int64_t>(F_GET_PERIOD);
sendToDetector(F_GET_PERIOD, nullptr, retval);
LOG(logDEBUG1) << "period :" << retval << "ns";
return retval;
} }
void Module::setPeriod(int64_t value) { void Module::setPeriod(int64_t value) {
@ -1319,10 +1380,7 @@ void Module::setPeriod(int64_t value) {
} }
int64_t Module::getDelayAfterTrigger() { int64_t Module::getDelayAfterTrigger() {
int64_t retval = -1; return sendToDetector<int64_t>(F_GET_DELAY_AFTER_TRIGGER);
sendToDetector(F_GET_DELAY_AFTER_TRIGGER, nullptr, retval);
LOG(logDEBUG1) << "delay after trigger :" << retval << "ns";
return retval;
} }
void Module::setDelayAfterTrigger(int64_t value) { void Module::setDelayAfterTrigger(int64_t value) {
@ -1331,10 +1389,7 @@ void Module::setDelayAfterTrigger(int64_t value) {
} }
int64_t Module::getBurstPeriod() { int64_t Module::getBurstPeriod() {
int64_t retval = -1; return sendToDetector<int64_t>(F_GET_BURST_PERIOD);
sendToDetector(F_GET_BURST_PERIOD, nullptr, retval);
LOG(logDEBUG1) << "burst period :" << retval << "ns";
return retval;
} }
void Module::setBurstPeriod(int64_t value) { void Module::setBurstPeriod(int64_t value) {
@ -1343,10 +1398,7 @@ void Module::setBurstPeriod(int64_t value) {
} }
int64_t Module::getSubExptime() { int64_t Module::getSubExptime() {
int64_t retval = -1; return sendToDetector<int64_t>(F_GET_SUB_EXPTIME);
sendToDetector(F_GET_SUB_EXPTIME, nullptr, retval);
LOG(logDEBUG1) << "sub exptime :" << retval << "ns";
return retval;
} }
void Module::setSubExptime(int64_t value) { void Module::setSubExptime(int64_t value) {
@ -1369,10 +1421,7 @@ void Module::setSubExptime(int64_t value) {
} }
int64_t Module::getSubDeadTime() { int64_t Module::getSubDeadTime() {
int64_t retval = -1; return sendToDetector<int64_t>(F_GET_SUB_DEADTIME);
sendToDetector(F_GET_SUB_DEADTIME, nullptr, retval);
LOG(logDEBUG1) << "sub deadtime :" << retval << "ns";
return retval;
} }
void Module::setSubDeadTime(int64_t value) { void Module::setSubDeadTime(int64_t value) {
@ -1623,31 +1672,17 @@ void Module::setInterruptSubframe(const bool enable) {
} }
bool Module::getInterruptSubframe() { bool Module::getInterruptSubframe() {
int retval = -1; auto retval = sendToDetector<int>(F_GET_INTERRUPT_SUBFRAME);
LOG(logDEBUG1) << "Getting Interrupt subframe";
sendToDetector(F_GET_INTERRUPT_SUBFRAME, nullptr, retval);
LOG(logDEBUG1) << "Interrupt subframe: " << retval;
return static_cast<bool>(retval); return static_cast<bool>(retval);
} }
uint32_t Module::writeRegister(uint32_t addr, uint32_t val) { uint32_t Module::writeRegister(uint32_t addr, uint32_t val) {
uint32_t args[]{addr, val}; uint32_t args[]{addr, val};
uint32_t retval = -1; return sendToDetector<uint32_t>(F_WRITE_REGISTER, args);
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;
} }
uint32_t Module::readRegister(uint32_t addr) { uint32_t Module::readRegister(uint32_t addr) {
uint32_t retval = -1; return sendToDetector<uint32_t>(F_READ_REGISTER, addr);
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;
} }
uint32_t Module::setBit(uint32_t addr, int n) { 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; } int Module::getClientStreamingPort() { return shm()->zmqport; }
void Module::setReceiverStreamingPort(int port) { 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) { if (shm()->useReceiverFlag) {
sendToReceiver(fnum, port, retval); auto retval = sendToReceiver<int>(F_SET_RECEIVER_STREAMING_PORT, port);
LOG(logDEBUG1) << "Receiver streaming port: " << retval; LOG(logDEBUG1) << "Receiver streaming port: " << retval;
shm()->rxZmqport = retval; shm()->rxZmqport = retval;
} else { } else {
@ -2278,14 +2309,7 @@ int64_t Module::getReceiverUDPSocketBufferSize() {
} }
int64_t Module::getReceiverRealUDPSocketBufferSize() const { int64_t Module::getReceiverRealUDPSocketBufferSize() const {
int64_t retval = -1; return sendToReceiver<int64_t>(F_RECEIVER_REAL_UDP_SOCK_BUF_SIZE);
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;
} }
void Module::executeFirmwareTest() { void Module::executeFirmwareTest() {
@ -3136,7 +3160,7 @@ sls::IpAddr Module::getReceiverLastClientIP() const {
void Module::exitReceiver() { void Module::exitReceiver() {
LOG(logDEBUG1) << "Sending exit command to receiver server"; LOG(logDEBUG1) << "Sending exit command to receiver server";
if (shm()->useReceiverFlag) { if (shm()->useReceiverFlag) {
sendToReceiver(F_EXIT_RECEIVER); sendToReceiver(F_EXIT_RECEIVER, nullptr, nullptr);
} }
} }
@ -3431,7 +3455,7 @@ int64_t Module::incrementFileIndex() {
void Module::startReceiver() { void Module::startReceiver() {
LOG(logDEBUG1) << "Starting Receiver"; LOG(logDEBUG1) << "Starting Receiver";
if (shm()->useReceiverFlag) { 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() { void Module::restreamStopFromReceiver() {
LOG(logDEBUG1) << "Restream stop dummy from Receiver via zmq"; LOG(logDEBUG1) << "Restream stop dummy from Receiver via zmq";
if (shm()->useReceiverFlag) { if (shm()->useReceiverFlag) {
sendToReceiver(F_RESTREAM_STOP_FROM_RECEIVER); sendToReceiver(F_RESTREAM_STOP_FROM_RECEIVER, nullptr, nullptr);
} }
} }

View File

@ -1915,6 +1915,12 @@ class Module : public virtual slsDetectorDefs {
void sendToDetector(int fnum, std::nullptr_t, Ret &retval); void sendToDetector(int fnum, std::nullptr_t, Ret &retval);
void sendToDetector(int fnum); 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) * Send function parameters to detector (stop server)
* @param fnum function enum * @param fnum function enum
@ -1983,9 +1989,17 @@ class Module : public virtual slsDetectorDefs {
template <typename Ret> template <typename Ret>
void sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const; 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) * Get Detector Type from Shared Memory (opening shm without verifying size)

View File

@ -8,7 +8,6 @@
*@short functions basic implemenation of shared memory *@short functions basic implemenation of shared memory
*/ */
#include "ansi.h"
#include "logger.h" #include "logger.h"
#include "sls_detector_exceptions.h" #include "sls_detector_exceptions.h"
@ -18,7 +17,7 @@
#include <fcntl.h> // O_CREAT, O_TRUNC.. #include <fcntl.h> // O_CREAT, O_TRUNC..
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <stdio.h> // printf // #include <stdio.h> // printf
#include <sys/mman.h> // shared memory #include <sys/mman.h> // shared memory
#include <sys/stat.h> // fstat #include <sys/stat.h> // fstat
#include <unistd.h> #include <unistd.h>

View File

@ -9,7 +9,6 @@
*/ */
#include "ansi.h"
#include "logger.h" #include "logger.h"
#include <string> #include <string>

View File

@ -15,6 +15,7 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <sys/stat.h> // stat #include <sys/stat.h> // stat
#include <unistd.h>
/** cosntructor & destructor */ /** cosntructor & destructor */

View File

@ -6,6 +6,7 @@ set(SOURCES
src/ServerSocket.cpp src/ServerSocket.cpp
src/ServerInterface.cpp src/ServerInterface.cpp
src/network_utils.cpp src/network_utils.cpp
src/ZmqSocket.cpp
) )
set(HEADERS set(HEADERS
@ -20,7 +21,6 @@ set(PUBLICHEADERS
include/file_utils.h include/file_utils.h
include/container_utils.h include/container_utils.h
include/string_utils.h include/string_utils.h
include/genericSocket.h
include/logger.h include/logger.h
include/ClientSocket.h include/ClientSocket.h
include/DataSocket.h include/DataSocket.h
@ -44,22 +44,36 @@ if(result)
endif() endif()
target_include_directories(slsSupportLib PUBLIC target_include_directories(slsSupportLib PUBLIC
${ZeroMQ_INCLUDE_DIRS}
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>" "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
) )
target_include_directories(slsSupportLib PRIVATE
${ZeroMQ_INCLUDE_DIRS}
)
set_target_properties(slsSupportLib PROPERTIES set_target_properties(slsSupportLib PROPERTIES
LIBRARY_OUTPUT_NAME SlsSupport LIBRARY_OUTPUT_NAME SlsSupport
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
PUBLIC_HEADER "${PUBLICHEADERS}" PUBLIC_HEADER "${PUBLICHEADERS}"
) )
message(${ZeroMQ_LIBRARIES})
target_link_libraries(slsSupportLib target_link_libraries(slsSupportLib
PUBLIC
slsProjectOptions slsProjectOptions
# ${ZeroMQ_LIBRARIES}
zmq
PRIVATE
slsProjectWarnings slsProjectWarnings
${ZeroMQ_LIBRARIES} PUBLIC
rapidjson) rapidjson
)
if (SLS_USE_TESTS) if (SLS_USE_TESTS)
add_subdirectory(tests) add_subdirectory(tests)

View File

@ -9,7 +9,6 @@ this might be deprecated in the future
*/ */
// #include "genericSocket.h"
#include "network_utils.h" #include "network_utils.h"
#include "sls_detector_exceptions.h" #include "sls_detector_exceptions.h"
#include <cstdint> #include <cstdint>

View File

@ -7,20 +7,8 @@
*@short functions to open/close zmq sockets *@short functions to open/close zmq sockets
*/ */
#include "ansi.h"
#include "sls_detector_exceptions.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 <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 #define MAX_STR_LENGTH 1000
@ -28,14 +16,14 @@ using namespace rapidjson;
#define ROIVERBOSITY #define ROIVERBOSITY
class zmq_msg_t;
class ZmqSocket { class ZmqSocket {
public: public:
// Socket Options for optimization
//Socket Options for optimization // ZMQ_LINGER default is already -1 means no messages discarded. use this
//ZMQ_LINGER default is already -1 means no messages discarded. use this options if optimizing required // options if optimizing required ZMQ_SNDHWM default is 0 means no limit. use
//ZMQ_SNDHWM default is 0 means no limit. use this to optimize if optimizing required // this to optimize if optimizing required
// eg. int value = -1; // eg. int value = -1;
// if (zmq_setsockopt(socketDescriptor, ZMQ_LINGER, &value,sizeof(value))) { // if (zmq_setsockopt(socketDescriptor, ZMQ_LINGER, &value,sizeof(value))) {
// Close(); // Close();
@ -45,55 +33,7 @@ public:
* @param hostname hostname or ip of server * @param hostname hostname or ip of server
* @param portnumber port number * @param portnumber port number
*/ */
ZmqSocket (const char* const hostname_or_ip, const uint32_t portnumber): 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");
}
};
/** /**
* Constructor for a server * Constructor for a server
@ -102,90 +42,47 @@ public:
* @param portnumber port number * @param portnumber port number
* @param ethip is the ip of the ethernet interface to stream zmq from * @param ethip is the ip of the ethernet interface to stream zmq from
*/ */
ZmqSocket (const uint32_t portnumber, const char *ethip): 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);
};
/** /**
* Destructor * Destructor
*/ */
~ZmqSocket () { ~ZmqSocket() = default;
//mySocketDescriptor destructor also gets called
};
/** /**
* Returns Port Number * Returns Port Number
* @returns Port Number * @returns Port Number
*/ */
uint32_t GetPortNumber () { return portno; }; uint32_t GetPortNumber() { return portno; }
/** /**
* Returns Server Address * Returns Server Address
* @returns Server Address * @returns Server Address
*/ */
char* GetZmqServerAddress () { return sockfd.serverAddress; }; char *GetZmqServerAddress() { return sockfd.serverAddress; }
/** /**
* Returns Socket Descriptor * Returns Socket Descriptor
* @reutns Socket descriptor * @reutns Socket descriptor
*/ */
void* GetsocketDescriptor () { return sockfd.socketDescriptor; }; void *GetsocketDescriptor() { return sockfd.socketDescriptor; }
/** /**
* Connect client socket to server socket * Connect client socket to server socket
* @returns 1 for fail, 0 for success * @returns 1 for fail, 0 for success
*/ */
int Connect() { int Connect();
if (zmq_connect(sockfd.socketDescriptor, sockfd.serverAddress) < 0) {
PrintError ();
return 1;
}
return 0;
}
/** /**
* Unbinds the Socket * Unbinds the Socket
*/ */
void Disconnect () {sockfd.Disconnect();}; void Disconnect() { sockfd.Disconnect(); };
/** /**
* Close Socket and destroy Context * Close Socket and destroy Context
*/ */
void Close () { sockfd.Close(); }; void Close() { sockfd.Close(); };
/** /**
* Convert Hostname to Internet address info structure * Convert Hostname to Internet address info structure
@ -195,28 +92,8 @@ public:
* @return 1 for fail, 0 for success * @return 1 for fail, 0 for success
*/ */
// Do not make this static (for multi threading environment) // Do not make this static (for multi threading environment)
int ConvertHostnameToInternetAddress (const char* const hostname, struct addrinfo **res) { int ConvertHostnameToInternetAddress(const char *const hostname,
// criteria in selecting socket address structures returned by res struct addrinfo **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*) * Convert Internet Address structure pointer to ip string (char*)
@ -227,16 +104,8 @@ public:
* @return 1 for fail, 0 for success * @return 1 for fail, 0 for success
*/ */
// Do not make this static (for multi threading environment) // Do not make this static (for multi threading environment)
int ConvertInternetAddresstoIpString (struct addrinfo *res, char* ip, const int ipsize) { int ConvertInternetAddresstoIpString(struct addrinfo *res, char *ip,
if (inet_ntop (res->ai_family, &((struct sockaddr_in *) res->ai_addr)->sin_addr, ip, ipsize) != NULL) { const int ipsize);
freeaddrinfo(res);
return 0;
}
LOG(logERROR) << "Could not convert internet address to ip string";
return 1;
}
/** /**
* Send Message Header * Send Message Header
@ -263,95 +132,25 @@ public:
* @param roundRNumber not used yet * @param roundRNumber not used yet
* @param detType detector enum * @param detType detector enum
* @param version detector header version * @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 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 flippedDataX if it is flipped across x axis
* @param quadEnable if quad is enabled * @param quadEnable if quad is enabled
* @param additionalJsonHeader additional json header * @param additionalJsonHeader additional json header
* @returns 0 if error, else 1 * @returns 0 if error, else 1
*/ */
int SendHeaderData ( int index, bool dummy, uint32_t jsonversion, uint32_t dynamicrange = 0, uint64_t fileIndex = 0, int SendHeaderData(
uint32_t ndetx = 0, uint32_t ndety = 0, uint32_t npixelsx = 0, uint32_t npixelsy = 0, uint32_t imageSize = 0, int index, bool dummy, uint32_t jsonversion, uint32_t dynamicrange = 0,
uint64_t acqIndex = 0, uint64_t fIndex = 0, const char* fname = NULL, uint64_t fileIndex = 0, uint32_t ndetx = 0, uint32_t ndety = 0,
uint64_t frameNumber = 0, uint32_t expLength = 0, uint32_t packetNumber = 0, uint32_t npixelsx = 0, uint32_t npixelsy = 0, uint32_t imageSize = 0,
uint64_t bunchId = 0, uint64_t timestamp = 0, uint64_t acqIndex = 0, uint64_t fIndex = 0, const char *fname = nullptr,
uint16_t modId = 0, uint16_t row = 0, uint16_t column = 0, uint16_t reserved = 0, uint64_t frameNumber = 0, uint32_t expLength = 0,
uint32_t debug = 0, uint16_t roundRNumber = 0, uint32_t packetNumber = 0, uint64_t bunchId = 0, uint64_t timestamp = 0,
uint8_t detType = 0, uint8_t version = 0, int gapPixelsEnable = 0, int flippedDataX = 0, uint16_t modId = 0, uint16_t row = 0, uint16_t column = 0,
uint32_t quadEnable = 0, uint16_t reserved = 0, uint32_t debug = 0, uint16_t roundRNumber = 0,
std::string* additionalJsonHeader = 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 * Send Message Body
@ -359,73 +158,19 @@ public:
* @param length length of message * @param length length of message
* @returns 0 if error, else 1 * @returns 0 if error, else 1
*/ */
int SendData (char* buf, int length) { 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) * Receive Header (Important to close message after parsing header)
* @param index self index for debugging * @param index self index for debugging
* @param document parsed document reference * @param document parsed document reference
* @param version version that has to match, -1 to not care * @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) * @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) int ReceiveHeader(const int index, rapidjson::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;
};
/** /**
* Close Header Message. Call this function if ReceiveHeader returned 1 * Close Header Message. Call this function if ReceiveHeader returned 1
@ -445,33 +190,8 @@ public:
* @param version version that has to match, -1 to not care * @param version version that has to match, -1 to not care
* @returns true if successful else false * @returns true if successful else false
*/ */
int ParseHeader(const int index, int length, char* buff, int ParseHeader(const int index, int length, char *buff, rapidjson::Document &document,
Document& document, bool& dummy, uint32_t version) 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;
};
/** /**
* Receive Data * Receive Data
@ -480,99 +200,22 @@ public:
* @param size size of image * @param size size of image
* @returns length of data received * @returns length of data received
*/ */
int ReceiveData(const int index, char* buf, const int size) 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 * Print error
*/ */
void PrintError () { 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:
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 * Class to close socket descriptors automatically
* upon encountering exceptions in the ZmqSocket constructor * upon encountering exceptions in the ZmqSocket constructor
@ -580,45 +223,24 @@ private:
class mySocketDescriptors { class mySocketDescriptors {
public: public:
/** Constructor */ /** Constructor */
mySocketDescriptors(): mySocketDescriptors();
server(false),
contextDescriptor(0),
socketDescriptor(0) {};
/** Destructor */ /** Destructor */
~mySocketDescriptors() { ~mySocketDescriptors();
Disconnect();
Close();
}
/** Unbinds the Socket */ /** Unbinds the Socket */
void Disconnect () { void Disconnect();
if (server)
zmq_unbind (socketDescriptor, serverAddress);
else
zmq_disconnect (socketDescriptor, serverAddress);
};
/** Close Socket and destroy Context */ /** Close Socket and destroy Context */
void Close () { void Close();
if (socketDescriptor != NULL) {
zmq_close (socketDescriptor);
socketDescriptor = NULL;
}
if (contextDescriptor != NULL) {
zmq_ctx_destroy (contextDescriptor);
contextDescriptor = NULL;
}
};
/** true if server, else false */ /** true if server, else false */
bool server; bool server;
/** Server Address */ /** Server Address */
char serverAddress[1000]; char serverAddress[1000];
/** Context Descriptor */ /** Context Descriptor */
void* contextDescriptor; void *contextDescriptor;
/** Socket Descriptor */ /** Socket Descriptor */
void* socketDescriptor; void *socketDescriptor;
}; };
private: private:
/** Port Number */ /** Port Number */
uint32_t portno; uint32_t portno;

View File

@ -14,8 +14,6 @@
#define __cplusplus #define __cplusplus
#endif #endif
#include "ansi.h"
#ifdef __cplusplus #ifdef __cplusplus
//C++ includes //C++ includes
#include "sls_detector_exceptions.h" #include "sls_detector_exceptions.h"

View File

@ -5,8 +5,8 @@
#define APIGUI 0x200227 #define APIGUI 0x200227
#define APICTB 0x200310 #define APICTB 0x200310
#define APIGOTTHARD 0x200310 #define APIGOTTHARD 0x200310
#define APIGOTTHARD2 0x200310
#define APIJUNGFRAU 0x200310 #define APIJUNGFRAU 0x200310
#define APIMYTHEN3 0x200310 #define APIMYTHEN3 0x200310
#define APIMOENCH 0x200310 #define APIMOENCH 0x200310
#define APIEIGER 0x200310 #define APIEIGER 0x200310
#define APIGOTTHARD2 0x200313

View 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;
}
};