// Copyright (2019-2023) Paul Scherrer Institute #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(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 exception; try { logger.Info("Wait for receiver done"); *ret.mutable_receiver() = receiver.Stop(); logger.Info(" ... Receiver efficiency: {} % Max delay: {} Compression ratio {}x", static_cast(ret.receiver().efficiency()*100.0), ret.receiver().max_receive_delay(), static_cast(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(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(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(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(); }