mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-16 00:00:02 +01:00
145 lines
3.6 KiB
C++
145 lines
3.6 KiB
C++
/** API Response.
|
|
*
|
|
* @file
|
|
* @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
|
|
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
|
|
* @license Apache 2.0
|
|
*********************************************************************************/
|
|
|
|
#include <limits>
|
|
#include <cmath>
|
|
|
|
#include <villas/exceptions.hpp>
|
|
#include <villas/api/universal.hpp>
|
|
|
|
using namespace villas::node::api::universal;
|
|
|
|
void ChannelList::parse(json_t *json, bool readable, bool writable)
|
|
{
|
|
if (!json_is_array(json))
|
|
throw ConfigError(json, "node-config-node-api-signals", "Signal list of API node must be an array");
|
|
|
|
clear();
|
|
|
|
size_t i;
|
|
json_t *json_channel;
|
|
json_array_foreach(json, i, json_channel) {
|
|
auto channel = std::make_shared<Channel>();
|
|
|
|
channel->parse(json_channel);
|
|
channel->readable = readable;
|
|
channel->writable = writable;
|
|
|
|
push_back(channel);
|
|
}
|
|
}
|
|
|
|
void Channel::parse(json_t *json)
|
|
{
|
|
const char *desc = nullptr;
|
|
const char *pl = nullptr;
|
|
json_t *json_range = nullptr;
|
|
|
|
json_error_t err;
|
|
int ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: o, s?: F }",
|
|
"description", &desc,
|
|
"payload", &pl,
|
|
"range", &json_range,
|
|
"rate", &rate
|
|
);
|
|
if (ret)
|
|
throw ConfigError(json, err, "node-config-node-api-signals");
|
|
|
|
if (desc)
|
|
description = desc;
|
|
|
|
if (pl) {
|
|
if (!strcmp(pl, "samples"))
|
|
payload = PayloadType::SAMPLES;
|
|
else if (!strcmp(pl, "events"))
|
|
payload = PayloadType::EVENTS;
|
|
else
|
|
throw ConfigError(json, "node-config-node-api-signals-payload", "Invalid payload type: {}", pl);
|
|
}
|
|
|
|
range_min = std::numeric_limits<double>::quiet_NaN();
|
|
range_max = std::numeric_limits<double>::quiet_NaN();
|
|
if (json_range) {
|
|
if (json_is_array(json_range)) {
|
|
ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F }",
|
|
"min", &range_min,
|
|
"max", &range_max
|
|
);
|
|
if (ret)
|
|
throw ConfigError(json, err, "node-config-node-api-signals-range", "Failed to parse channel range");
|
|
} else if (json_is_object(json_range)) {
|
|
size_t i;
|
|
json_t *json_option;
|
|
|
|
range_options.clear();
|
|
|
|
json_array_foreach(json_range, i, json_option) {
|
|
if (!json_is_string(json_option))
|
|
throw ConfigError(json, err, "node-config-node-api-signals-range", "Channel range options must be strings");
|
|
|
|
auto *option = json_string_value(json_option);
|
|
range_options.push_back(option);
|
|
}
|
|
} else
|
|
throw ConfigError(json, "node-config-node-api-signals-range", "Channel range must be an array or object");
|
|
}
|
|
}
|
|
|
|
json_t * Channel::toJson(Signal::Ptr sig) const
|
|
{
|
|
json_error_t err;
|
|
json_t *json_ch = json_pack_ex(&err, 0, "{ s: s, s: s, s: b, s: b }",
|
|
"id", sig->name.c_str(),
|
|
"datatype", signalTypeToString(sig->type).c_str(),
|
|
"readable", (int) readable,
|
|
"writable", (int) writable
|
|
);
|
|
|
|
if (!description.empty())
|
|
json_object_set(json_ch, "description", json_string(description.c_str()));
|
|
|
|
if (!sig->unit.empty())
|
|
json_object_set(json_ch, "unit", json_string(sig->unit.c_str()));
|
|
|
|
if (rate > 0)
|
|
json_object_set(json_ch, "rate", json_real(rate));
|
|
|
|
switch (payload) {
|
|
case PayloadType::EVENTS:
|
|
json_object_set(json_ch, "payload", json_string("events"));
|
|
break;
|
|
|
|
case PayloadType::SAMPLES:
|
|
json_object_set(json_ch, "payload", json_string("samples"));
|
|
break;
|
|
|
|
default: {}
|
|
}
|
|
|
|
switch (sig->type) {
|
|
case SignalType::FLOAT: {
|
|
if (std::isnan(range_min) && std::isnan(range_max))
|
|
break;
|
|
|
|
json_t *json_range = json_object();
|
|
|
|
if (!std::isnan(range_min))
|
|
json_object_set(json_range, "min", json_real(range_min));
|
|
|
|
if (!std::isnan(range_max))
|
|
json_object_set(json_range, "max", json_real(range_max));
|
|
|
|
json_object_set(json_ch, "range", json_range);
|
|
break;
|
|
}
|
|
|
|
default: {}
|
|
}
|
|
|
|
return json_ch;
|
|
}
|