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:
parent
67de039d07
commit
6f72bc832c
8 changed files with 113 additions and 32 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
19
lib/node.cpp
19
lib/node.cpp
|
@ -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;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue