ifw-daq  3.0.1
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  {"receivers", p.receivers},
44  {"result", p.result},
45  {"timestamp", MakeTimestamp(p.timestamp)}};
46 }
47 
48 // NOLINTNEXTLINE
49 void to_json(nlohmann::json& j, Alert const& p) {
50  j = nlohmann::json{{"category", p.id.category},
51  {"key", p.id.key},
52  {"description", p.description},
53  {"timestamp", MakeTimestamp(p.timestamp)}};
54 }
55 
56 // NOLINTNEXTLINE
57 void to_json(nlohmann::json& j, ReceiverStatus const& p) {
58  j = nlohmann::json{{"state", p.state}};
59 }
60 
61 // NOLINTNEXTLINE
62 void to_json(nlohmann::json& j, DaqContext const& p) {
64  j = nlohmann::json{
65  {"id", p.id},
66  {"fileId", p.file_id},
67  {"creationTime", std::chrono::nanoseconds(p.creation_time.time_since_epoch()).count()},
68  {"processName", p.process_name},
69  {"dpNamePrefix", p.dp_name_prefix},
70  {"primSources", p.prim_sources},
71  {"metaSources", p.meta_sources},
72  {"keywords", std::move(kws)},
73  {"awaitInterval", p.await_interval.count()},
74  {"dpParts", p.results}};
75 
76  // Optional specification
77  if (p.specification) {
78  j["specification"] = *p.specification;
79  }
80 }
81 //
82 // NOLINTNEXTLINE
83 void to_json(nlohmann::json& j, DaqContext::Source const& p) {
84  j = nlohmann::json{{"name", p.name}, {"rrUri", p.rr_uri}};
85 }
86 
87 // NOLINTNEXTLINE
88 void to_json(nlohmann::json& j, DpPart const& p) {
89  if (std::holds_alternative<fits::KeywordVector>(p.Part())) {
90  // keywords
91  auto kws = fits::SerializeJsonKeywords(std::get<fits::KeywordVector>(p.Part()));
92  j = nlohmann::json::object(
93  {{"type", "fitsKeywords"}, {"sourceName", p.SourceName()}, {"keywords", std::move(kws)}});
94  } else if (std::holds_alternative<std::string>(p.Part())) {
95  auto const& path = std::get<std::string>(p.Part());
96  j = nlohmann::json::object(
97  {{"type", "fitsFile"}, {"sourceName", p.SourceName()}, {"location", path}});
98  }
99 }
100 
101 // NOLINTNEXTLINE
102 void from_json(nlohmann::json const& j, Status& p) {
103  j.at("id").get_to(p.id);
104  j.at("fileId").get_to(p.file_id);
105  j.at("state").get_to(p.state);
106  j.at("error").get_to(p.error);
107  j.at("alerts").get_to(p.alerts);
108  j.at("receivers").get_to(p.receivers);
109  j.at("result").get_to(p.result);
110  double ts;
111  j.at("timestamp").get_to(ts);
112  MakeTimepoint(p.timestamp, ts);
113 }
114 
115 // NOLINTNEXTLINE
116 void from_json(nlohmann::json const& j, Alert& p) {
117  j.at("category").get_to(p.id.category);
118  j.at("key").get_to(p.id.key);
119  j.at("description").get_to(p.description);
120  double ts;
121  j.at("timestamp").get_to(ts);
122  MakeTimepoint(p.timestamp, ts);
123 }
124 
125 // NOLINTNEXTLINE
126 void from_json(nlohmann::json const& j, ReceiverStatus& p) {
127  j.at("state").get_to(p.state);
128 }
129 
130 // NOLINTNEXTLINE
131 void from_json(nlohmann::json const& j, DaqContext& p) {
132  j.at("id").get_to(p.id);
133  j.at("fileId").get_to(p.file_id);
134  j.at("processName").get_to(p.process_name);
135  j.at("dpNamePrefix").get_to(p.dp_name_prefix);
136  j.at("primSources").get_to(p.prim_sources);
137  j.at("metaSources").get_to(p.meta_sources);
138  unsigned interval;
139  j.at("awaitInterval").get_to(interval);
140  p.await_interval = decltype(p.await_interval)(interval);
141  j.at("dpParts").get_to(p.results);
142  p.keywords = fits::ParseJsonKeywords(j["keywords"]);
143  int64_t time_since_epoch_ns;
144  j.at("creationTime").get_to(time_since_epoch_ns);
145  using Time = std::chrono::system_clock::time_point;
146  p.creation_time = Time(std::chrono::nanoseconds(time_since_epoch_ns));
147 
148  if (j.contains("specification")) {
149  p.specification = json::ParseStartDaqV2Spec(j.at("specification"));
150  }
151 }
152 
153 // NOLINTNEXTLINE
154 void from_json(nlohmann::json const& j, DaqContext::Source& p) {
155  j.at("name").get_to(p.name);
156  j.at("rrUri").get_to(p.rr_uri);
157 }
158 
159 // NOLINTNEXTLINE
160 void from_json(nlohmann::json const& j, DpPart& p) {
161  std::string type;
162  std::string name;
163  j.at("type").get_to(type);
164  j.at("sourceName").get_to(p.SourceName());
165 
166  if (type == "fitsKeywords") {
167  p.Part() = fits::ParseJsonKeywords(j.at("keywords"));
168  } else if (type == "fitsFile") {
169  std::string path;
170  j.at("location").get_to(path);
171  p.Part() = path;
172  } else {
173  throw std::invalid_argument(fmt::format("Invalid type: {}", type));
174  }
175 }
176 
177 } // 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:90
std::string key
Unique key for each alert.
Definition: status.hpp:67
std::string description
Definition: status.hpp:91
TimePoint timestamp
Definition: status.hpp:92
void from_json(nlohmann::json const &j, Status &p)
Definition: json.cpp:102
std::string category
Standardized category.
Definition: status.hpp:63
void to_json(nlohmann::json &j, Status const &p)
Definition: json.cpp:37
Describes an active Data Acquisition alert.
Definition: status.hpp:86
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
Persistent status for receiver delivery.
Definition: status.hpp:134
Non observable status object that keeps stores status of data acquisition.
Definition: status.hpp:153
State state
Definition: status.hpp:176
std::string id
Definition: status.hpp:174
std::string result
Path to resulting data product.
Definition: status.hpp:193
std::map< std::size_t, ReceiverStatus > receivers
Receiver processing (e.g.
Definition: status.hpp:188
std::string file_id
Definition: status.hpp:175
bool error
Definition: status.hpp:177
std::vector< Alert > alerts
Active alerts.
Definition: status.hpp:181
TimePoint timestamp
Timestamp of last update.
Definition: status.hpp:198