mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
hook: adapt existing hooks to derive from {Multi,Single}SignalHook classes
This commit is contained in:
parent
870e563568
commit
d54fcdf5d8
6 changed files with 110 additions and 331 deletions
|
@ -25,7 +25,6 @@
|
|||
*/
|
||||
|
||||
#include <bitset>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <villas/hook.hpp>
|
||||
|
@ -36,34 +35,16 @@
|
|||
namespace villas {
|
||||
namespace node {
|
||||
|
||||
class AverageHook : public Hook {
|
||||
class AverageHook : public MultiSignalHook {
|
||||
|
||||
protected:
|
||||
unsigned offset;
|
||||
|
||||
std::bitset<MAX_SAMPLE_LENGTH> mask;
|
||||
vlist signal_names;
|
||||
|
||||
public:
|
||||
AverageHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) :
|
||||
Hook(p, n, fl, prio, en),
|
||||
MultiSignalHook(p, n, fl, prio, en),
|
||||
offset(0)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = vlist_init(&signal_names);
|
||||
if (ret)
|
||||
throw RuntimeError("Failed to intialize list");
|
||||
|
||||
state = State::INITIALIZED;
|
||||
}
|
||||
|
||||
virtual ~AverageHook()
|
||||
{
|
||||
int ret __attribute__((unused));
|
||||
|
||||
ret = vlist_destroy(&signal_names, nullptr, true);
|
||||
}
|
||||
{ }
|
||||
|
||||
virtual void prepare()
|
||||
{
|
||||
|
@ -72,19 +53,7 @@ public:
|
|||
|
||||
assert(state == State::CHECKED);
|
||||
|
||||
/* Setup mask */
|
||||
for (size_t i = 0; i < vlist_length(&signal_names); i++) {
|
||||
char *signal_name = (char *) vlist_at_safe(&signal_names, i);
|
||||
|
||||
int index = vlist_lookup_index<struct signal>(&signals, signal_name);
|
||||
if (index < 0)
|
||||
throw RuntimeError("Failed to find signal {}", signal_name);
|
||||
|
||||
mask.set(index);
|
||||
}
|
||||
|
||||
if (mask.none())
|
||||
throw RuntimeError("Invalid signal mask");
|
||||
MultiSignalHook::prepare();
|
||||
|
||||
/* Add averaged signal */
|
||||
avg_sig = signal_create("average", nullptr, SignalType::FLOAT);
|
||||
|
@ -101,39 +70,18 @@ public:
|
|||
virtual void parse(json_t *json)
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
json_error_t err;
|
||||
json_t *json_signals, *json_signal;
|
||||
|
||||
assert(state != State::STARTED);
|
||||
|
||||
Hook::parse(json);
|
||||
MultiSignalHook::parse(json);
|
||||
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s: i, s: o }",
|
||||
"offset", &offset,
|
||||
"signals", &json_signals
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s: i }",
|
||||
"offset", &offset
|
||||
);
|
||||
if (ret)
|
||||
throw ConfigError(json, err, "node-config-hook-average");
|
||||
|
||||
if (!json_is_array(json_signals))
|
||||
throw ConfigError(json_signals, "node-config-hook-average-signals", "Setting 'signals' must be a list of signal names");
|
||||
|
||||
json_array_foreach(json_signals, i, json_signal) {
|
||||
switch (json_typeof(json_signal)) {
|
||||
case JSON_STRING:
|
||||
vlist_push(&signal_names, strdup(json_string_value(json_signal)));
|
||||
break;
|
||||
|
||||
case JSON_INTEGER:
|
||||
mask.set(json_integer_value(json_signal));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ConfigError(json_signal, "node-config-hook-average-signals", "Invalid value for setting 'signals'");
|
||||
}
|
||||
}
|
||||
|
||||
state = State::PARSED;
|
||||
}
|
||||
|
||||
|
@ -144,17 +92,14 @@ public:
|
|||
|
||||
assert(state == State::STARTED);
|
||||
|
||||
for (unsigned k = 0; k < smp->length; k++) {
|
||||
if (!mask.test(k))
|
||||
continue;
|
||||
|
||||
switch (sample_format(smp, k)) {
|
||||
for (unsigned index : signalIndices) {
|
||||
switch (sample_format(smp, index)) {
|
||||
case SignalType::INTEGER:
|
||||
sum += smp->data[k].i;
|
||||
sum += smp->data[index].i;
|
||||
break;
|
||||
|
||||
case SignalType::FLOAT:
|
||||
sum += smp->data[k].f;
|
||||
sum += smp->data[index].f;
|
||||
break;
|
||||
|
||||
case SignalType::INVALID:
|
||||
|
|
|
@ -33,66 +33,40 @@
|
|||
namespace villas {
|
||||
namespace node {
|
||||
|
||||
class CastHook : public Hook {
|
||||
class CastHook : public MultiSignalHook {
|
||||
|
||||
protected:
|
||||
unsigned signal_index;
|
||||
char *signal_name;
|
||||
|
||||
enum SignalType new_type;
|
||||
char *new_name;
|
||||
char *new_unit;
|
||||
std::string new_name;
|
||||
std::string new_unit;
|
||||
|
||||
public:
|
||||
CastHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) :
|
||||
Hook(p, n, fl, prio, en),
|
||||
signal_index(-1),
|
||||
signal_name(nullptr),
|
||||
new_type(SignalType::INVALID),
|
||||
new_name(nullptr),
|
||||
new_unit(nullptr)
|
||||
MultiSignalHook(p, n, fl, prio, en),
|
||||
new_type(SignalType::INVALID)
|
||||
{ }
|
||||
|
||||
~CastHook()
|
||||
{
|
||||
if (signal_name)
|
||||
free(signal_name);
|
||||
|
||||
if (new_name)
|
||||
free(new_name);
|
||||
|
||||
if (new_unit)
|
||||
free(new_unit);
|
||||
}
|
||||
|
||||
virtual void prepare()
|
||||
{
|
||||
struct signal *orig_sig, *new_sig;
|
||||
|
||||
assert(state == State::CHECKED);
|
||||
|
||||
if (signal_name) {
|
||||
signal_index = vlist_lookup_index<struct signal>(&signals, signal_name);
|
||||
if (signal_index < 0)
|
||||
throw RuntimeError("Failed to find signal: {}", signal_name);
|
||||
MultiSignalHook::prepare();
|
||||
|
||||
for (auto index : signalIndices) {
|
||||
orig_sig = (struct signal *) vlist_at_safe(&signals, index);
|
||||
|
||||
auto type = new_type == SignalType::INVALID ? orig_sig->type : new_type;
|
||||
auto name = new_name.empty() ? orig_sig->name : new_name;
|
||||
auto unit = new_unit.empty() ? orig_sig->unit : new_unit;
|
||||
|
||||
new_sig = signal_create(name.c_str(), unit.c_str(), type);
|
||||
|
||||
vlist_set(&signals, index, new_sig);
|
||||
signal_decref(orig_sig);
|
||||
}
|
||||
|
||||
char *name, *unit;
|
||||
enum SignalType type;
|
||||
|
||||
orig_sig = (struct signal *) vlist_at_safe(&signals, signal_index);
|
||||
if (!orig_sig)
|
||||
throw RuntimeError("Failed to find signal: {}", signal_name);
|
||||
|
||||
type = new_type != SignalType::INVALID ? new_type : orig_sig->type;
|
||||
name = new_name ? new_name : orig_sig->name;
|
||||
unit = new_unit ? new_unit : orig_sig->unit;
|
||||
|
||||
new_sig = signal_create(name, unit, type);
|
||||
|
||||
vlist_set(&signals, signal_index, new_sig);
|
||||
signal_decref(orig_sig);
|
||||
|
||||
state = State::PREPARED;
|
||||
}
|
||||
|
||||
|
@ -101,18 +75,16 @@ public:
|
|||
int ret;
|
||||
|
||||
json_error_t err;
|
||||
json_t *json_signal;
|
||||
|
||||
assert(state != State::STARTED);
|
||||
|
||||
Hook::parse(json);
|
||||
MultiSignalHook::parse(json);
|
||||
|
||||
const char *name = nullptr;
|
||||
const char *unit = nullptr;
|
||||
const char *type = nullptr;
|
||||
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s: o, s?: s, s?: s, s?: s }",
|
||||
"signal", &json_signal,
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: s }",
|
||||
"new_type", &type,
|
||||
"new_name", &name,
|
||||
"new_unit", &unit
|
||||
|
@ -120,20 +92,6 @@ public:
|
|||
if (ret)
|
||||
throw ConfigError(json, err, "node-config-hook-cast");
|
||||
|
||||
switch (json_typeof(json_signal)) {
|
||||
case JSON_STRING:
|
||||
signal_name = strdup(json_string_value(json_signal));
|
||||
break;
|
||||
|
||||
case JSON_INTEGER:
|
||||
signal_name = nullptr;
|
||||
signal_index = json_integer_value(json_signal);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ConfigError(json_signal, "node-config-hook-cast-signals", "Invalid value for setting 'signal'");
|
||||
}
|
||||
|
||||
if (type) {
|
||||
new_type = signal_type_from_str(type);
|
||||
if (new_type == SignalType::INVALID)
|
||||
|
@ -144,10 +102,10 @@ public:
|
|||
new_type = SignalType::INVALID;
|
||||
|
||||
if (name)
|
||||
new_name = strdup(name);
|
||||
new_name = name;
|
||||
|
||||
if (unit)
|
||||
new_unit = strdup(unit);
|
||||
new_unit = unit;
|
||||
|
||||
state = State::PARSED;
|
||||
}
|
||||
|
@ -156,10 +114,12 @@ public:
|
|||
{
|
||||
assert(state == State::STARTED);
|
||||
|
||||
struct signal *orig_sig = (struct signal *) vlist_at(smp->signals, signal_index);
|
||||
struct signal *new_sig = (struct signal *) vlist_at(&signals, signal_index);
|
||||
for (auto index : signalIndices) {
|
||||
struct signal *orig_sig = (struct signal *) vlist_at(smp->signals, index);
|
||||
struct signal *new_sig = (struct signal *) vlist_at(&signals, index);
|
||||
|
||||
signal_data_cast(&smp->data[signal_index], orig_sig->type, new_sig->type);
|
||||
signal_data_cast(&smp->data[index], orig_sig->type, new_sig->type);
|
||||
}
|
||||
|
||||
return Reason::OK;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
namespace villas {
|
||||
namespace node {
|
||||
|
||||
class GateHook : public Hook {
|
||||
class GateHook : public SingleSignalHook {
|
||||
|
||||
protected:
|
||||
enum class Mode {
|
||||
|
@ -46,8 +46,6 @@ protected:
|
|||
FALLING_EDGE
|
||||
} mode;
|
||||
|
||||
std::string signalName;
|
||||
int signalIndex;
|
||||
double threshold;
|
||||
double duration;
|
||||
int samples;
|
||||
|
@ -59,10 +57,8 @@ protected:
|
|||
|
||||
public:
|
||||
GateHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) :
|
||||
Hook(p, n, fl, prio, en),
|
||||
SingleSignalHook(p, n, fl, prio, en),
|
||||
mode(Mode::RISING_EDGE),
|
||||
signalName(),
|
||||
signalIndex(0),
|
||||
threshold(0.5),
|
||||
duration(-1),
|
||||
samples(-1),
|
||||
|
@ -76,16 +72,14 @@ public:
|
|||
int ret;
|
||||
|
||||
json_error_t err;
|
||||
json_t *json_signal;
|
||||
|
||||
const char *mode_str;
|
||||
|
||||
assert(state != State::STARTED);
|
||||
|
||||
Hook::parse(json);
|
||||
SingleSignalHook::parse(json);
|
||||
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s: o, s?: F, s?: F, s?: i, s?: s }",
|
||||
"signal", &json_signal,
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F, s?: i, s?: s }",
|
||||
"threshold", &threshold,
|
||||
"duration", &duration,
|
||||
"samples", &samples,
|
||||
|
@ -105,20 +99,6 @@ public:
|
|||
mode = Mode::FALLING_EDGE;
|
||||
}
|
||||
|
||||
switch (json_typeof(json_signal)) {
|
||||
case JSON_STRING:
|
||||
signalName = json_string_value(json_signal);
|
||||
break;
|
||||
|
||||
case JSON_INTEGER:
|
||||
signalName.clear();
|
||||
signalIndex = json_integer_value(json_signal);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ConfigError(json_signal, "node-config-hook-cast-signals", "Invalid value for setting 'signal'");
|
||||
}
|
||||
|
||||
state = State::PARSED;
|
||||
}
|
||||
|
||||
|
@ -126,24 +106,14 @@ public:
|
|||
{
|
||||
assert(state == State::CHECKED);
|
||||
|
||||
if (!signalName.empty()) {
|
||||
signalIndex = vlist_lookup_index<struct signal>(&signals, signalName);
|
||||
if (signalIndex < 0)
|
||||
throw RuntimeError("Failed to find signal: {}", signalName);
|
||||
}
|
||||
|
||||
/* Check if signal type is float */
|
||||
auto sig = (struct signal *) vlist_at(&signals, signalIndex);
|
||||
if (!sig)
|
||||
throw RuntimeError("Invalid signal index: {}", signalIndex);
|
||||
|
||||
if (sig->type != SignalType::FLOAT)
|
||||
throw RuntimeError("Gate signal must be of type float");
|
||||
|
||||
state = State::PREPARED;
|
||||
}
|
||||
|
||||
|
||||
virtual Hook::Reason process(sample *smp)
|
||||
{
|
||||
assert(state == State::STARTED);
|
||||
|
|
|
@ -36,37 +36,20 @@
|
|||
namespace villas {
|
||||
namespace node {
|
||||
|
||||
class LimitValueHook : public Hook {
|
||||
class LimitValueHook : public MultiSignalHook {
|
||||
|
||||
protected:
|
||||
unsigned offset;
|
||||
|
||||
float min, max;
|
||||
|
||||
std::bitset<MAX_SAMPLE_LENGTH> mask;
|
||||
vlist signal_names;
|
||||
|
||||
public:
|
||||
LimitValueHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) :
|
||||
Hook(p, n, fl, prio, en),
|
||||
MultiSignalHook(p, n, fl, prio, en),
|
||||
offset(0),
|
||||
min(0), max(0)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = vlist_init(&signal_names);
|
||||
if (ret)
|
||||
throw RuntimeError("Failed to intialize list");
|
||||
|
||||
state = State::INITIALIZED;
|
||||
}
|
||||
|
||||
virtual ~LimitValueHook()
|
||||
{
|
||||
int ret __attribute__((unused));
|
||||
|
||||
ret = vlist_destroy(&signal_names, nullptr, true);
|
||||
}
|
||||
min(0),
|
||||
max(0)
|
||||
{ }
|
||||
|
||||
virtual void prepare()
|
||||
{
|
||||
|
@ -75,19 +58,7 @@ public:
|
|||
|
||||
assert(state == State::CHECKED);
|
||||
|
||||
/* Setup mask */
|
||||
for (size_t i = 0; i < vlist_length(&signal_names); i++) {
|
||||
char *signal_name = (char *) vlist_at_safe(&signal_names, i);
|
||||
|
||||
int index = vlist_lookup_index<struct signal>(&signals, signal_name);
|
||||
if (index < 0)
|
||||
throw RuntimeError("Failed to find signal {}", signal_name);
|
||||
|
||||
mask.set(index);
|
||||
}
|
||||
|
||||
if (mask.none())
|
||||
throw RuntimeError("Invalid signal mask");
|
||||
MultiSignalHook::prepare();
|
||||
|
||||
/* Add averaged signal */
|
||||
avg_sig = signal_create("average", nullptr, SignalType::FLOAT);
|
||||
|
@ -104,40 +75,19 @@ public:
|
|||
virtual void parse(json_t *json)
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
json_error_t err;
|
||||
json_t *json_signals, *json_signal;
|
||||
|
||||
assert(state != State::STARTED);
|
||||
|
||||
Hook::parse(json);
|
||||
MultiSignalHook::parse(json);
|
||||
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s: f, s: f, s: o }",
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s: f, s: f }",
|
||||
"min", &min,
|
||||
"min", &max,
|
||||
"signals", &json_signals
|
||||
"min", &max
|
||||
);
|
||||
if (ret)
|
||||
throw ConfigError(json, err, "node-config-hook-average");
|
||||
|
||||
if (!json_is_array(json_signals))
|
||||
throw ConfigError(json_signals, "node-config-hook-average-signals", "Setting 'signals' must be a list of signal names");
|
||||
|
||||
json_array_foreach(json_signals, i, json_signal) {
|
||||
switch (json_typeof(json_signal)) {
|
||||
case JSON_STRING:
|
||||
vlist_push(&signal_names, strdup(json_string_value(json_signal)));
|
||||
break;
|
||||
|
||||
case JSON_INTEGER:
|
||||
mask.set(json_integer_value(json_signal));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ConfigError(json_signal, "node-config-hook-average-signals", "Invalid value for setting 'signals'");
|
||||
}
|
||||
}
|
||||
|
||||
state = State::PARSED;
|
||||
}
|
||||
|
||||
|
@ -145,25 +95,22 @@ public:
|
|||
{
|
||||
assert(state == State::STARTED);
|
||||
|
||||
for (unsigned k = 0; k < smp->length; k++) {
|
||||
if (!mask.test(k))
|
||||
continue;
|
||||
|
||||
switch (sample_format(smp, k)) {
|
||||
for (auto index : signalIndices) {
|
||||
switch (sample_format(smp, index)) {
|
||||
case SignalType::INTEGER:
|
||||
if (smp->data[k].i > max)
|
||||
smp->data[k].i = max;
|
||||
if (smp->data[index].i > max)
|
||||
smp->data[index].i = max;
|
||||
|
||||
if (smp->data[k].i < min)
|
||||
smp->data[k].i = min;
|
||||
if (smp->data[index].i < min)
|
||||
smp->data[index].i = min;
|
||||
break;
|
||||
|
||||
case SignalType::FLOAT:
|
||||
if (smp->data[k].f > max)
|
||||
smp->data[k].f = max;
|
||||
if (smp->data[index].f > max)
|
||||
smp->data[index].f = max;
|
||||
|
||||
if (smp->data[k].f < min)
|
||||
smp->data[k].f = min;
|
||||
if (smp->data[index].f < min)
|
||||
smp->data[index].f = min;
|
||||
break;
|
||||
|
||||
case SignalType::INVALID:
|
||||
|
|
|
@ -34,47 +34,45 @@
|
|||
namespace villas {
|
||||
namespace node {
|
||||
|
||||
class PpsTsHook : public Hook {
|
||||
class PpsTsHook : public SingleSignalHook {
|
||||
|
||||
protected:
|
||||
double lastValue;
|
||||
double thresh;
|
||||
unsigned idx;
|
||||
double threshold;
|
||||
uint64_t lastSequence;
|
||||
|
||||
bool isSynced;
|
||||
bool isLocked;
|
||||
struct timespec tsVirt;
|
||||
double timeError; /**< In seconds */
|
||||
double periodEst; /**< In seconds */
|
||||
double periodErrComp; /**< In seconds */
|
||||
double periodEstimate; /**< In seconds */
|
||||
double periodErrorCompensation; /**< In seconds */
|
||||
double period; /**< In seconds */
|
||||
uintmax_t cntEdges;
|
||||
uintmax_t cntSmps;
|
||||
uintmax_t cntSmpsTotal;
|
||||
unsigned horizonComp;
|
||||
unsigned horizonEst;
|
||||
unsigned horizonCompensation;
|
||||
unsigned horizonEstimation;
|
||||
std::vector<uintmax_t> filterWindow;
|
||||
|
||||
public:
|
||||
PpsTsHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) :
|
||||
Hook(p, n, fl, prio, en),
|
||||
SingleSignalHook(p, n, fl, prio, en),
|
||||
lastValue(0),
|
||||
thresh(1.5),
|
||||
idx(0),
|
||||
threshold(1.5),
|
||||
lastSequence(0),
|
||||
isSynced(false),
|
||||
isLocked(false),
|
||||
timeError(0.0),
|
||||
periodEst(0.0),
|
||||
periodErrComp(0.0),
|
||||
periodEstimate(0.0),
|
||||
periodErrorCompensation(0.0),
|
||||
period(0.0),
|
||||
cntEdges(0),
|
||||
cntSmps(0),
|
||||
cntSmpsTotal(0),
|
||||
horizonComp(10),
|
||||
horizonEst(10),
|
||||
filterWindow(horizonEst + 1, 0)
|
||||
horizonCompensation(10),
|
||||
horizonEstimation(10),
|
||||
filterWindow(horizonEstimation + 1, 0)
|
||||
{ }
|
||||
|
||||
virtual void parse(json_t *json)
|
||||
|
@ -87,9 +85,8 @@ public:
|
|||
Hook::parse(json);
|
||||
|
||||
double fSmps = 0;
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s: i, s?: f, s: F}",
|
||||
"signal_index", &idx,
|
||||
"threshold", &thresh,
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s?: f, s: F }",
|
||||
"threshold", &threshold,
|
||||
"expected_smp_rate", &fSmps
|
||||
);
|
||||
if (ret)
|
||||
|
@ -97,7 +94,7 @@ public:
|
|||
|
||||
period = 1.0 / fSmps;
|
||||
|
||||
logger->debug("Parsed config thresh={} signal_index={} nominal_period={}", thresh, idx, period);
|
||||
logger->debug("Parsed config threshold={} signal_index={} nominal_period={}", threshold, signalIndex, period);
|
||||
|
||||
state = State::PARSED;
|
||||
}
|
||||
|
@ -107,10 +104,10 @@ public:
|
|||
assert(state == State::STARTED);
|
||||
|
||||
/* Get value of PPS signal */
|
||||
float value = smp->data[idx].f; // TODO check if it is really float
|
||||
float value = smp->data[signalIndex].f; // TODO check if it is really float
|
||||
|
||||
/* Detect Edge */
|
||||
bool isEdge = lastValue < thresh && value > thresh;
|
||||
bool isEdge = lastValue < threshold && value > threshold;
|
||||
|
||||
lastValue = value;
|
||||
|
||||
|
@ -123,12 +120,12 @@ public:
|
|||
|
||||
|
||||
filterWindow[cntEdges % filterWindow.size()] = cntSmpsTotal;
|
||||
/* Estimated sample period over last 'horizonEst' seconds */
|
||||
unsigned int tmp = cntEdges < filterWindow.size() ? cntEdges : horizonEst;
|
||||
/* Estimated sample period over last 'horizonEstimation' seconds */
|
||||
unsigned int tmp = cntEdges < filterWindow.size() ? cntEdges : horizonEstimation;
|
||||
double cntSmpsAvg = (cntSmpsTotal - filterWindow[(cntEdges - tmp) % filterWindow.size()]) / tmp;
|
||||
periodEst = 1.0 / cntSmpsAvg;
|
||||
periodErrComp = timeError / (cntSmpsAvg * horizonComp);
|
||||
period = periodEst + periodErrComp;
|
||||
periodEstimate = 1.0 / cntSmpsAvg;
|
||||
periodErrorCompensation = timeError / (cntSmpsAvg * horizonCompensation);
|
||||
period = periodEstimate + periodErrorCompensation;
|
||||
}
|
||||
else {
|
||||
tsVirt.tv_sec = time(nullptr);
|
||||
|
@ -140,7 +137,7 @@ public:
|
|||
cntSmps = 0;
|
||||
cntEdges++;
|
||||
|
||||
logger->debug("Time Error is: {} periodEst {} periodErrComp {}", timeError, periodEst, periodErrComp);
|
||||
logger->debug("Time Error is: {} periodEstimate {} periodErrorCompensation {}", timeError, periodEstimate, periodErrorCompensation);
|
||||
}
|
||||
|
||||
cntSmps++;
|
||||
|
|
|
@ -32,102 +32,62 @@
|
|||
namespace villas {
|
||||
namespace node {
|
||||
|
||||
class ScaleHook : public Hook {
|
||||
class ScaleHook : public MultiSignalHook {
|
||||
|
||||
protected:
|
||||
char *signal_name;
|
||||
unsigned signal_index;
|
||||
|
||||
double scale;
|
||||
double offset;
|
||||
|
||||
public:
|
||||
ScaleHook(struct vpath *p, struct vnode *n, int fl, int prio, bool en = true) :
|
||||
Hook(p, n, fl, prio, en),
|
||||
signal_name(nullptr),
|
||||
signal_index(0),
|
||||
scale(1),
|
||||
offset(0)
|
||||
MultiSignalHook(p, n, fl, prio, en),
|
||||
scale(1.0),
|
||||
offset(0.0)
|
||||
{ }
|
||||
|
||||
virtual void prepare()
|
||||
{
|
||||
assert(state != State::STARTED);
|
||||
|
||||
if (signal_name) {
|
||||
signal_index = vlist_lookup_index<struct signal>(&signals, signal_name);
|
||||
if (signal_index < 0)
|
||||
throw RuntimeError("Failed to find signal: {}", signal_name);
|
||||
}
|
||||
|
||||
state = State::PREPARED;
|
||||
}
|
||||
|
||||
virtual ~ScaleHook()
|
||||
{
|
||||
if (signal_name)
|
||||
free(signal_name);
|
||||
}
|
||||
|
||||
virtual void parse(json_t *json)
|
||||
{
|
||||
int ret;
|
||||
json_t *json_signal;
|
||||
json_error_t err;
|
||||
|
||||
assert(state != State::STARTED);
|
||||
|
||||
Hook::parse(json);
|
||||
MultiSignalHook::parse(json);
|
||||
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F, s: o }",
|
||||
ret = json_unpack_ex(json, &err, 0, "{ s?: F, s?: F }",
|
||||
"scale", &scale,
|
||||
"offset", &offset,
|
||||
"signal", &json_signal
|
||||
"offset", &offset
|
||||
);
|
||||
if (ret)
|
||||
throw ConfigError(json, err, "node-config-hook-scale");
|
||||
|
||||
switch (json_typeof(json_signal)) {
|
||||
case JSON_STRING:
|
||||
signal_name = strdup(json_string_value(json_signal));
|
||||
break;
|
||||
|
||||
case JSON_INTEGER:
|
||||
signal_name = nullptr;
|
||||
signal_index = json_integer_value(json_signal);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw ConfigError(json_signal, "node-config-hook-scale-signal", "Invalid value for setting 'signal'");
|
||||
}
|
||||
|
||||
state = State::PARSED;
|
||||
}
|
||||
|
||||
virtual Hook::Reason process(struct sample *smp)
|
||||
{
|
||||
unsigned k = signal_index;
|
||||
for (auto index : signalIndices) {
|
||||
assert(index < smp->length);
|
||||
assert(state == State::STARTED);
|
||||
|
||||
assert(k < smp->length);
|
||||
assert(state == State::STARTED);
|
||||
switch (sample_format(smp, index)) {
|
||||
case SignalType::INTEGER:
|
||||
smp->data[index].i *= scale;
|
||||
smp->data[index].i += offset;
|
||||
break;
|
||||
|
||||
switch (sample_format(smp, k)) {
|
||||
case SignalType::INTEGER:
|
||||
smp->data[k].i *= scale;
|
||||
smp->data[k].i += offset;
|
||||
break;
|
||||
case SignalType::FLOAT:
|
||||
smp->data[index].f *= scale;
|
||||
smp->data[index].f += offset;
|
||||
break;
|
||||
|
||||
case SignalType::FLOAT:
|
||||
smp->data[k].f *= scale;
|
||||
smp->data[k].f += offset;
|
||||
break;
|
||||
case SignalType::COMPLEX:
|
||||
smp->data[index].z *= scale;
|
||||
smp->data[index].z += offset;
|
||||
break;
|
||||
|
||||
case SignalType::COMPLEX:
|
||||
smp->data[k].z *= scale;
|
||||
smp->data[k].z += offset;
|
||||
break;
|
||||
|
||||
default: { }
|
||||
default: { }
|
||||
}
|
||||
}
|
||||
|
||||
return Reason::OK;
|
||||
|
|
Loading…
Add table
Reference in a new issue