1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

api: expose output signals via API

This commit is contained in:
Steffen Vogel 2020-07-01 17:02:22 +02:00
parent 67de039d07
commit 6f72bc832c
8 changed files with 113 additions and 32 deletions

View file

@ -71,7 +71,12 @@ struct node {
uint64_t sequence; /**< This is a counter of received samples, in case the node-type does not generate sequence numbers itself. */
std::shared_ptr<villas::Stats> stats; /**< Statistic counters. This is a pointer to the statistic hooks private data. */
/** The path which uses this node as a destination.
* Usually every node should be used only by a single path as destination.
* Otherwise samples from different paths would be interleaved.
*/
struct vpath *output_path;
std::shared_ptr<villas::Stats> stats; /**< Statistic counters. This is a pointer to the statistic hooks private data. */
struct node_direction in, out;
@ -176,6 +181,12 @@ char * node_name(struct node *n);
*/
char * node_name_long(struct node *n);
/** Return a list of signals which are sent to this node.
*
* This list is derived from the path which uses the node as destination.
*/
struct vlist * node_output_signals(struct node *n);
/** Reverse local and remote socket address.
*
* @see node_type::reverse

View file

@ -142,6 +142,9 @@ void path_print_stats(struct vpath *p);
*/
const char * path_name(struct vpath *p);
/** Get a list of signals which is emitted by the path. */
struct vlist * path_output_signals(struct vpath *n);
/** Reverse a path */
int path_reverse(struct vpath *p, struct vpath *r);

View file

@ -121,6 +121,7 @@ int signal_list_generate(struct vlist *list, unsigned len, enum SignalType fmt);
int signal_list_generate2(struct vlist *list, const char *dt);
void signal_list_dump(const struct vlist *list, const union signal_data *data, unsigned len);
int signal_list_copy(struct vlist *dst, const struct vlist *src);
json_t * signal_list_to_json(struct vlist *list);
enum SignalType signal_type_from_str(const char *str);
@ -140,4 +141,6 @@ int signal_data_parse_str(union signal_data *data, const struct signal *sig, con
int signal_data_parse_json(union signal_data *data, const struct signal *sig, json_t *cfg);
json_t * signal_data_to_json(union signal_data *data, const struct signal *sig);
void signal_data_set(union signal_data *data, const struct signal *sig, double val);

View file

@ -48,18 +48,33 @@ public:
for (size_t i = 0; i < vlist_length(nodes); i++) {
struct node *n = (struct node *) vlist_at(nodes, i);
struct vlist *output_signals;
json_t *json_node;
json_t *json_signals_in = nullptr;
json_t *json_signals_out = nullptr;
char uuid[37];
uuid_unparse(n->uuid, uuid);
json_t *json_node = json_pack("{ s: s, s: s, s: s, s: i, s: { s: i }, s: { s: i } }",
output_signals = node_output_signals(n);
json_signals_in = signal_list_to_json(&n->in.signals);
if (output_signals)
json_signals_out = signal_list_to_json(output_signals);
json_node = json_pack("{ s: s, s: s, s: s, s: i, s: { s: i, s: o? }, s: { s: i, s: o? } }",
"name", node_name_short(n),
"uuid", uuid,
"state", state_print(n->state),
"affinity", n->affinity,
"in",
"vectorize", n->in.vectorize,
"signals", json_signals_in,
"out",
"vectorize", n->out.vectorize
"vectorize", n->out.vectorize,
"signals", json_signals_out
);
if (n->stats)

View file

@ -123,32 +123,9 @@ static int json_pack_sample(struct io *io, json_t **j, struct sample *smp)
json_t *json_data = json_array();
for (unsigned i = 0; i < smp->length; i++) {
enum SignalType fmt = sample_format(smp, i);
struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, i);
json_t *json_value;
switch (fmt) {
case SignalType::INTEGER:
json_value = json_integer(smp->data[i].i);
break;
case SignalType::FLOAT:
json_value = json_real(smp->data[i].f);
break;
case SignalType::BOOLEAN:
json_value = json_boolean(smp->data[i].b);
break;
case SignalType::COMPLEX:
json_value = json_pack("{ s: f, s: f }",
"real", std::real(smp->data[i].z),
"imag", std::imag(smp->data[i].z)
);
break;
case SignalType::INVALID:
return -1;
}
json_t *json_value = signal_data_to_json(&smp->data[i], sig);
json_array_append(json_data, json_value);
}

View file

@ -29,6 +29,7 @@
#include <villas/hook_list.hpp>
#include <villas/sample.h>
#include <villas/node.h>
#include <villas/path.h>
#include <villas/utils.hpp>
#include <villas/colors.hpp>
#include <villas/plugin.h>
@ -58,7 +59,11 @@ int node_init(struct node *n, struct node_type *vt)
memset(n->_vd, 0, vt->size);
//n->stats = nullptr;
using stats_ptr = std::shared_ptr<Stats>;
new (&n->stats) stats_ptr();
n->output_path = nullptr;
n->name = nullptr;
n->_name = nullptr;
n->_name_long = nullptr;
@ -409,6 +414,10 @@ int node_destroy(struct node *n)
rtnl_cls_put(n->tc_classifier);
#endif /* WITH_NETEM */
using stats_ptr = std::shared_ptr<Stats>;
n->stats.~stats_ptr();
n->state = State::DESTROYED;
return 0;
@ -549,6 +558,14 @@ const char * node_name_short(struct node *n)
return n->name;
}
struct vlist * node_output_signals(struct node *n)
{
if (n->output_path)
return path_output_signals(n->output_path);
return nullptr;
}
int node_reverse(struct node *n)
{
return node_type(n)->reverse ? node_type(n)->reverse(n) : -1;

View file

@ -403,9 +403,13 @@ int path_parse(struct vpath *p, json_t *cfg, struct vlist *nodes)
for (size_t i = 0; i < vlist_length(&destinations); i++) {
struct node *n = (struct node *) vlist_at(&destinations, i);
if (!n->output_path)
throw ConfigError(cfg, "node-config-path", "Every node must only be used by a single path as destination");
auto *pd = new struct vpath_destination;
pd->node = n;
pd->node->output_path = p;
if (!node_is_enabled(pd->node)) {
p->logger->error("Destination {} of path {} is not enabled", node_name(pd->node), path_name(p));
@ -754,6 +758,11 @@ const char * path_name(struct vpath *p)
return p->_name;
}
struct vlist * path_output_signals(struct vpath *p)
{
return &p->signals;
}
int path_uses_node(struct vpath *p, struct node *n)
{
for (size_t i = 0; i < vlist_length(&p->destinations); i++) {

View file

@ -354,16 +354,37 @@ int signal_list_copy(struct vlist *dst, const struct vlist *src)
assert(dst->state == State::INITIALIZED);
for (size_t i = 0; i < vlist_length(src); i++) {
struct signal *s = (struct signal *) vlist_at_safe(src, i);
struct signal *sig = (struct signal *) vlist_at_safe(src, i);
signal_incref(s);
signal_incref(sig);
vlist_push(dst, s);
vlist_push(dst, sig);
}
return 0;
}
json_t * signal_list_to_json(struct vlist *list)
{
json_t *json_signals = json_array();
for (size_t i = 0; i < vlist_length(list); i++) {
struct signal *sig = (struct signal *) vlist_at_safe(list, i);
json_t *json_signal = json_pack("{ s: s?, s: s?, s: s, s: b, s: o }",
"name", sig->name,
"unit", sig->unit,
"type", signal_type_to_str(sig->type),
"enabled", sig->enabled,
"init", signal_data_to_json(&sig->init, sig)
);
json_array_append_new(json_signals, json_signal);
}
return json_signals;
}
/* Signal type */
enum SignalType signal_type_from_str(const char *str)
@ -660,6 +681,31 @@ int signal_data_parse_json(union signal_data *data, const struct signal *sig, js
return 0;
}
json_t * signal_data_to_json(union signal_data *data, const struct signal *sig)
{
switch (sig->type) {
case SignalType::INTEGER:
return json_integer(data->i);
case SignalType::FLOAT:
return json_real(data->f);
case SignalType::BOOLEAN:
return json_boolean(data->b);
case SignalType::COMPLEX:
return json_pack("{ s: f, s: f }",
"real", std::real(data->z),
"imag", std::imag(data->z)
);
case SignalType::INVALID:
return nullptr;
}
return nullptr;
}
int signal_data_print_str(const union signal_data *data, const struct signal *sig, char *buf, size_t len)
{
switch (sig->type) {