Files
Jungfraujoch/frame_serialize/ZMQBsreadImagePusher.cpp
2023-12-11 06:49:24 +01:00

82 lines
2.9 KiB
C++

// Copyright (2019-2023) Paul Scherrer Institute
#include "ZMQBsreadImagePusher.h"
#include <nlohmann/json.hpp>
#include <openssl/md5.h>
ZMQBsreadImagePusher::ZMQBsreadImagePusher(const std::string &addr, int32_t send_buffer_high_watermark,
int32_t send_buffer_size) : socket(context, ZMQSocketType::Push) {
if (send_buffer_size > 0)
socket.SendBufferSize(send_buffer_size);
if (send_buffer_high_watermark > 0)
socket.SendWaterMark(send_buffer_high_watermark);
socket.Bind(addr);
}
void ZMQBsreadImagePusher::StartDataCollection(const StartMessage &message) {
// Do nothing
}
void ZMQBsreadImagePusher::SendImage(const DataMessage &message) {
std::unique_lock<std::mutex> ul(m);
timespec ts{};
clock_gettime(CLOCK_REALTIME, &ts);
auto data_header = DataHeader(message);
auto main_header = MainHeader(message, data_header, ts);
socket.Send(main_header, true, true);
socket.Send(data_header, true, true);
socket.Send(message.image.data, message.image.size, true, true);
socket.Send(&ts, sizeof(ts), true, false);
}
void ZMQBsreadImagePusher::EndDataCollection(const EndMessage &message) {
// Do nothing
}
std::string ZMQBsreadImagePusher::MainHeader(const DataMessage &message, const std::string &data_header, timespec &ts) {
nlohmann::json j;
j["htype"] = "bsr_m-1.1";
j["pulse_id"] = message.bunch_id;
j["hash"] = MD5Hash(data_header);
j["global_timestamp"]["sec"] = ts.tv_sec;
j["global_timestamp"]["ns"] = ts.tv_nsec;
return j.dump();
}
std::string ZMQBsreadImagePusher::MD5Hash(const std::string &s) {
std::string ret;
uint8_t hash[MD5_DIGEST_LENGTH];
MD5(reinterpret_cast<const unsigned char *>(s.data()), s.length(), hash);
for (unsigned char i : hash) {
char buf[4];
sprintf(buf, "%02x", i);
ret.append(buf);
}
return ret;
}
std::string ZMQBsreadImagePusher::DataHeader(const DataMessage &message) {
nlohmann::json data;
data["htype"] = "bsr_d-1.1";
nlohmann::json image_channel;
image_channel["name"] = "JFJOCH:IMAGE";
if (message.image.pixel_depth_bytes == 2)
image_channel["type"] = (message.image.pixel_is_signed ? "int16" : "uint16");
else
image_channel["type"] = (message.image.pixel_is_signed ? "int32" : "uint32");
image_channel["shape"] = {message.image.ypixel, message.image.xpixel};
image_channel["encoding"] = "little";
if (message.image.algorithm == CompressionAlgorithm::BSHUF_LZ4)
image_channel["compression"] = "bitshuffle_lz4";
else if (message.image.algorithm == CompressionAlgorithm::NO_COMPRESSION)
image_channel["compression"] = "none";
else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Compression not allowed for BSRead data");
image_channel["modulo"] = 1;
image_channel["offset"] = 0;
data["channels"].push_back(image_channel);
return data.dump();
}