176 lines
5.7 KiB
C++
176 lines
5.7 KiB
C++
// Copyright (2019-2022) Paul Scherrer Institute
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include "JFJochServices.h"
|
|
#include "../common/JFJochException.h"
|
|
|
|
uint64_t current_time_ms() {
|
|
auto curr_time = std::chrono::system_clock::now();
|
|
return std::chrono::duration_cast<std::chrono::milliseconds>(curr_time.time_since_epoch()).count();
|
|
}
|
|
|
|
JFJochServices::JFJochServices(Logger &in_logger) : logger(in_logger) {}
|
|
|
|
void JFJochServices::Start(const DiffractionExperiment& experiment, const JFCalibration &calibration) {
|
|
logger.Info("Measurement start for: {}", experiment.GetFilePrefix());
|
|
|
|
if ((experiment.GetImageNum() > 0) && (!experiment.GetFilePrefix().empty())) {
|
|
logger.Info(" ... writer start");
|
|
writer.Start(writer_zmq_addr, 0);
|
|
writer_running = true;
|
|
} else
|
|
writer_running = false;
|
|
|
|
logger.Info(" ... receiver start");
|
|
if (experiment.GetDetectorMode() == DetectorMode::Conversion)
|
|
receiver.Start(experiment, &calibration);
|
|
else
|
|
receiver.Start(experiment, nullptr);
|
|
|
|
if (!experiment.IsUsingInternalPacketGen()) {
|
|
logger.Info(" ... detector start");
|
|
detector.Start(experiment);
|
|
}
|
|
logger.Info(" Done!");
|
|
}
|
|
|
|
void JFJochServices::Off() {
|
|
detector.Off();
|
|
}
|
|
|
|
void JFJochServices::On(const DiffractionExperiment &x) {
|
|
logger.Info("Detector on");
|
|
|
|
JFJochProtoBuf::DetectorConfig config = x.DetectorConfig(receiver.GetNetworkConfig());
|
|
|
|
detector.On(config);
|
|
logger.Info(" ... done");
|
|
}
|
|
|
|
JFJochProtoBuf::BrokerFullStatus JFJochServices::Stop(const JFCalibration &calibration) {
|
|
JFJochProtoBuf::BrokerFullStatus ret;
|
|
|
|
std::unique_ptr<JFJochException> exception;
|
|
|
|
try {
|
|
logger.Info("Wait for receiver done");
|
|
*ret.mutable_receiver() = receiver.Stop();
|
|
|
|
logger.Info(" ... Receiver efficiency: {} % Max delay: {} Compression ratio {}x",
|
|
static_cast<int>(ret.receiver().efficiency()*100.0),
|
|
ret.receiver().max_receive_delay(),
|
|
static_cast<int>(std::round(ret.receiver().compressed_ratio())));
|
|
if (ret.receiver().efficiency() < 1.0) {
|
|
for (int i = 0; i < ret.receiver().device_statistics_size(); i++) {
|
|
for (int j = 0; j < ret.receiver().device_statistics(i).packets_received_per_module_size(); j++) {
|
|
logger.Info(" ... Device: {} Module: {} Packets received: {}", i, j,
|
|
ret.receiver().device_statistics(i).packets_received_per_module(j));
|
|
}
|
|
}
|
|
}
|
|
} catch (const JFJochException &e) {
|
|
logger.Error(" ... finished with error {}",e.what());
|
|
exception = std::make_unique<JFJochException>(e);
|
|
}
|
|
logger.Info("Receiver finished with success");
|
|
|
|
if (writer_running) {
|
|
logger.Info("Stopping writer");
|
|
try {
|
|
auto stats = writer.Stop();
|
|
logger.Info(" ... finished with success");
|
|
for (int i = 0; i < stats.size(); i++) {
|
|
*ret.add_writer() = stats[i];
|
|
logger.Info("Writer {}: Images = {} Throughput = {:.0f} MB/s Frame rate = {:.0f} Hz",
|
|
i, stats[i].nimages(), stats[i].performance_mbs(), stats[i].performance_hz());
|
|
}
|
|
} catch (JFJochException &e) {
|
|
logger.Error(" ... finished with error {}",e.what());
|
|
exception = std::make_unique<JFJochException>(e);
|
|
}
|
|
}
|
|
|
|
logger.Info("Stopping detector");
|
|
try {
|
|
detector.Stop();
|
|
logger.Info(" ... done");
|
|
} catch (JFJochException &e) {
|
|
logger.Error(" ... finished with error {}",e.what());
|
|
exception = std::make_unique<JFJochException>(e);
|
|
}
|
|
|
|
if (exception)
|
|
throw JFJochException(*exception);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void JFJochServices::Abort() {
|
|
// Abort should try to achieve the best outcome possible
|
|
// but it OK if things fail (for example lost connection)
|
|
try {
|
|
receiver.Abort();
|
|
} catch (const std::exception &e) {
|
|
logger.Error(e.what());
|
|
}
|
|
}
|
|
|
|
void JFJochServices::Cancel() {
|
|
detector.Stop();
|
|
receiver.Cancel();
|
|
}
|
|
|
|
JFJochServices &JFJochServices::Receiver(const std::string &addr) {
|
|
receiver.Connect(addr);
|
|
logger.Info("Using receiver service with gRPC " + addr);
|
|
return *this;
|
|
}
|
|
|
|
JFJochServices &JFJochServices::Writer(const std::string &addr, const std::string &zmq_push_addr) {
|
|
writer.AddClient(addr);
|
|
writer_zmq_addr.push_back(zmq_push_addr);
|
|
logger.Info("Using writer service with gRPC {} listening for images from ZeroMQ {}", addr, zmq_push_addr);
|
|
return *this;
|
|
}
|
|
|
|
JFJochServices &JFJochServices::Detector(const std::string &addr) {
|
|
detector.Connect(addr);
|
|
logger.Info("Using detector service with gRPC {}", addr);
|
|
return *this;
|
|
}
|
|
|
|
JFJochProtoBuf::ReceiverStatus JFJochServices::GetReceiverStatus() {
|
|
return receiver.GetStatus();
|
|
}
|
|
|
|
JFJochProtoBuf::Plot JFJochServices::GetPlots(const JFJochProtoBuf::PlotRequest &request) {
|
|
try {
|
|
return receiver.GetPlots(request);
|
|
} catch (...) {
|
|
return JFJochProtoBuf::Plot();
|
|
}
|
|
}
|
|
|
|
JFJochProtoBuf::RadialIntegrationProfiles JFJochServices::GetRadialIntegrationProfiles() {
|
|
try {
|
|
return receiver.GetRadialIntegrationProfiles();
|
|
} catch (...) {
|
|
return JFJochProtoBuf::RadialIntegrationProfiles();
|
|
}
|
|
}
|
|
|
|
void JFJochServices::SetDataProcessingSettings(const JFJochProtoBuf::DataProcessingSettings &settings) {
|
|
receiver.SetDataProcessingSettings(settings);
|
|
}
|
|
|
|
JFJochProtoBuf::PreviewFrame JFJochServices::GetPreviewFrame() {
|
|
return receiver.GetPreviewFrame();
|
|
}
|
|
|
|
void JFJochServices::Trigger() {
|
|
detector.Trigger();
|
|
}
|
|
|
|
size_t JFJochServices::WriterZMQCount() const {
|
|
return writer_zmq_addr.size();
|
|
} |