ifw-daq  3.0.0-pre2
IFW Data Acquisition modules
json.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup daq_common_libdaq
4  * @copyright (c) Copyright ESO 2022
5  * All Rights Reserved
6  * ESO (eso.org) is an Intergovernmental Organisation, and therefore special legal conditions apply.
7  *
8  * @brief Declares JSON support for serialization
9  */
10 #include <daq/json.hpp>
11 
12 #include <fmt/format.h>
13 
14 #include <daq/daqContext.hpp>
15 #include <daq/fits/json.hpp>
16 #include <daq/status.hpp>
17 
18 namespace daq {
19 
20 namespace {
21 template <class Clock, class Duration>
22 double MakeTimestamp(std::chrono::time_point<Clock, Duration> const& ts) {
23  using Seconds = std::chrono::duration<double, std::ratio<1>>;
24  return std::chrono::time_point_cast<Seconds>(ts).time_since_epoch().count();
25 }
26 
27 template <class Clock, class Duration>
28 void MakeTimepoint(std::chrono::time_point<Clock, Duration>& ts, double time) {
29  using Seconds = std::chrono::duration<double, std::ratio<1>>;
30  ts = std::chrono::time_point<Clock, Duration>(
31  std::chrono::duration_cast<Duration>(Seconds(time)));
32 }
33 
34 } // namespace
35 
36 // NOLINTNEXTLINE
37 void to_json(nlohmann::json& j, Status const& p) {
38  j = nlohmann::json{{"id", p.id},
39  {"fileId", p.file_id},
40  {"state", p.state},
41  {"error", p.error},
42  {"alerts", p.alerts},
43  {"result", p.result},
44  {"timestamp", MakeTimestamp(p.timestamp)}};
45 }
46 
47 // NOLINTNEXTLINE
48 void to_json(nlohmann::json& j, Alert const& p) {
49  j = nlohmann::json{{"category", p.id.category},
50  {"key", p.id.key},
51  {"description", p.description},
52  {"timestamp", MakeTimestamp(p.timestamp)}};
53 }
54 
55 // NOLINTNEXTLINE
56 void to_json(nlohmann::json& j, DaqContext const& p) {
58  j = nlohmann::json{
59  {"id", p.id},
60  {"fileId", p.file_id},
61  {"creationTime", std::chrono::nanoseconds(p.creation_time.time_since_epoch()).count()},
62  {"processName", p.process_name},
63  {"dpNamePrefix", p.dp_name_prefix},
64  {"primSources", p.prim_sources},
65  {"metaSources", p.meta_sources},
66  {"keywords", std::move(kws)},
67  {"awaitInterval", p.await_interval.count()},
68  {"dpParts", p.results}};
69 
70  // Optional specification
71  if (p.specification) {
72  j["specification"] = *p.specification;
73  }
74 }
75 //
76 // NOLINTNEXTLINE
77 void to_json(nlohmann::json& j, DaqContext::Source const& p) {
78  j = nlohmann::json{{"name", p.name}, {"rrUri", p.rr_uri}};
79 }
80 
81 // NOLINTNEXTLINE
82 void to_json(nlohmann::json& j, DpPart const& p) {
83  if (std::holds_alternative<fits::KeywordVector>(p.Part())) {
84  // keywords
85  auto kws = fits::SerializeJsonKeywords(std::get<fits::KeywordVector>(p.Part()));
86  j = nlohmann::json::object(
87  {{"type", "fitsKeywords"}, {"sourceName", p.SourceName()}, {"keywords", std::move(kws)}});
88  } else if (std::holds_alternative<std::string>(p.Part())) {
89  auto const& path = std::get<std::string>(p.Part());
90  j = nlohmann::json::object(
91  {{"type", "fitsFile"}, {"sourceName", p.SourceName()}, {"location", path}});
92  }
93 }
94 
95 // NOLINTNEXTLINE
96 void from_json(nlohmann::json const& j, Status& p) {
97  j.at("id").get_to(p.id);
98  j.at("fileId").get_to(p.file_id);
99  j.at("state").get_to(p.state);
100  j.at("error").get_to(p.error);
101  j.at("alerts").get_to(p.alerts);
102  j.at("result").get_to(p.result);
103  double ts;
104  j.at("timestamp").get_to(ts);
105  MakeTimepoint(p.timestamp, ts);
106 }
107 
108 // NOLINTNEXTLINE
109 void from_json(nlohmann::json const& j, Alert& p) {
110  j.at("category").get_to(p.id.category);
111  j.at("key").get_to(p.id.key);
112  j.at("description").get_to(p.description);
113  double ts;
114  j.at("timestamp").get_to(ts);
115  MakeTimepoint(p.timestamp, ts);
116 }
117 
118 // NOLINTNEXTLINE
119 void from_json(nlohmann::json const& j, DaqContext& p) {
120  j.at("id").get_to(p.id);
121  j.at("fileId").get_to(p.file_id);
122  j.at("processName").get_to(p.process_name);
123  j.at("dpNamePrefix").get_to(p.dp_name_prefix);
124  j.at("primSources").get_to(p.prim_sources);
125  j.at("metaSources").get_to(p.meta_sources);
126  unsigned interval;
127  j.at("awaitInterval").get_to(interval);
128  p.await_interval = decltype(p.await_interval)(interval);
129  j.at("dpParts").get_to(p.results);
130  p.keywords = fits::ParseJsonKeywords(j["keywords"]);
131  int64_t time_since_epoch_ns;
132  j.at("creationTime").get_to(time_since_epoch_ns);
133  using Time = std::chrono::system_clock::time_point;
134  p.creation_time = Time(std::chrono::nanoseconds(time_since_epoch_ns));
135 
136  if (j.contains("specification")) {
137  p.specification = json::ParseStartDaqV2Spec(j.at("specification"));
138  }
139 }
140 
141 // NOLINTNEXTLINE
142 void from_json(nlohmann::json const& j, DaqContext::Source& p) {
143  j.at("name").get_to(p.name);
144  j.at("rrUri").get_to(p.rr_uri);
145 }
146 
147 // NOLINTNEXTLINE
148 void from_json(nlohmann::json const& j, DpPart& p) {
149  std::string type;
150  std::string name;
151  j.at("type").get_to(type);
152  j.at("sourceName").get_to(p.SourceName());
153 
154  if (type == "fitsKeywords") {
155  p.Part() = fits::ParseJsonKeywords(j.at("keywords"));
156  } else if (type == "fitsFile") {
157  std::string path;
158  j.at("location").get_to(path);
159  p.Part() = path;
160  } else {
161  throw std::invalid_argument(fmt::format("Invalid type: {}", type));
162  }
163 }
164 
165 } // namespace daq
Provides information of the location and source of a FITS file or keywords produced by a data acquisi...
Definition: dpPart.hpp:26
auto Part() const noexcept -> PartTypes const &
Holds a std::string path [[user]@host:]path or FITS keywords.
Definition: dpPart.hpp:54
auto SourceName() const noexcept -> std::string const &
Source name of the part.
Definition: dpPart.hpp:44
Declares JSON support for serialization.
Contains data structure for FITS keywords.
Contains declaration of daq::Context.
nlohmann::json SerializeJsonKeywords(std::vector< KeywordVariant > const &keywords)
SerializeJsons keyword to JSON.
Definition: json.cpp:200
std::vector< KeywordVariant > ParseJsonKeywords(char const *keywords)
Parse and return FITS keywords.
Definition: json.cpp:124
StartDaqV2Spec ParseStartDaqV2Spec(nlohmann::json const &json)
Parse StartDaqSpec.
Definition: startDaqV2.cpp:46
AlertId id
Definition: status.hpp:76
std::string key
Unique key for each alert.
Definition: status.hpp:60
std::string description
Definition: status.hpp:77
TimePoint timestamp
Definition: status.hpp:78
void from_json(nlohmann::json const &j, Status &p)
Definition: json.cpp:96
std::string category
Standardized category.
Definition: status.hpp:56
NLOHMANN_JSON_SERIALIZE_ENUM(State, { {State::NotStarted, "NotStarted"}, {State::Starting, "Starting"}, {State::Acquiring, "Acquiring"}, {State::Stopping, "Stopping"}, {State::Stopped, "Stopped"}, {State::NotScheduled, "NotScheduled"}, {State::Scheduled, "Scheduled"}, {State::Transferring, "Transferring"}, {State::Merging, "Merging"}, {State::Releasing, "Releasing"}, {State::AbortingAcquiring, "AbortingAcquiring"}, {State::AbortingMerging, "AbortingMerging"}, {State::Aborted, "Aborted"}, {State::Completed, "Completed"}, }) void to_json(nlohmann void to_json(nlohmann::json &j, Alert const &p)
Definition: json.cpp:48
Describes an active Data Acquisition alert.
Definition: status.hpp:72
Contains declaration for Status and ObservableStatus.
Structure carrying context needed to start a Data Acquisition and construct a Data Product Specificat...
Definition: daqContext.hpp:44
std::vector< Source > meta_sources
Definition: daqContext.hpp:77
DpParts results
Results from Data Acquisition (FITS files and keywords).
Definition: daqContext.hpp:102
std::string process_name
User defined process name.
Definition: daqContext.hpp:70
std::vector< daq::fits::KeywordVariant > keywords
Keyword list provided by OCM to Data Product.
Definition: daqContext.hpp:87
std::vector< Source > prim_sources
Definition: daqContext.hpp:76
std::chrono::milliseconds await_interval
Interval (and thus duration) of the requests sent to primary sources to await end of recording.
Definition: daqContext.hpp:94
std::optional< json::StartDaqV2Spec > specification
Optional specification, if DAQ was started using StartDaqV2.
Definition: daqContext.hpp:116
std::string file_id
Data Product FileId as specified by OLAS ICD.
Definition: daqContext.hpp:65
std::string dp_name_prefix
Data product file name prefix.
Definition: daqContext.hpp:75
std::chrono::system_clock::time_point creation_time
Time when DAQ was created.
Definition: daqContext.hpp:108
std::string id
DAQ identfier, possibly provided by user.
Definition: daqContext.hpp:60
Non observable status object that keeps stores status of data acquisition.
Definition: status.hpp:124
State state
Definition: status.hpp:142
std::string id
Definition: status.hpp:140
std::string result
Path to resulting data product.
Definition: status.hpp:152
std::string file_id
Definition: status.hpp:141
bool error
Definition: status.hpp:143
std::vector< Alert > alerts
Active alerts.
Definition: status.hpp:147
TimePoint timestamp
Definition: status.hpp:153