/* Node direction. * * Author: Steffen Vogel * SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include using namespace villas; using namespace villas::node; using namespace villas::utils; NodeDirection::NodeDirection(enum NodeDirection::Direction dir, Node *n) : direction(dir), path(nullptr), node(n), enabled(1), builtin(1), vectorize(1), config(nullptr) {} int NodeDirection::parse(json_t *json) { int ret; json_error_t err; json_t *json_hooks = nullptr; json_t *json_signals = nullptr; config = json; ret = json_unpack_ex(json, &err, 0, "{ s?: o, s?: o, s?: i, s?: b, s?: b }", "hooks", &json_hooks, "signals", &json_signals, "vectorize", &vectorize, "builtin", &builtin, "enabled", &enabled); if (ret) throw ConfigError(json, err, "node-config-node-in"); if (node->getFactory()->getFlags() & (int)NodeFactory::Flags::PROVIDES_SIGNALS) { // Do nothing.. Node-type will provide signals signals = std::make_shared(); if (!signals) throw MemoryAllocationError(); } else if (json_is_object(json_signals) || json_is_array(json_signals)) { signals = std::make_shared(); if (!signals) throw MemoryAllocationError(); if (json_is_object(json_signals)) { json_t *json_name, *json_signal = json_signals; int count; ret = json_unpack_ex(json_signal, &err, 0, "{ s: i }", "count", &count); if (ret) throw ConfigError(json_signals, "node-config-node-signals", "Invalid signal definition"); json_signals = json_array(); for (int i = 0; i < count; i++) { json_t *json_signal_copy = json_copy(json_signal); json_object_del(json_signal, "count"); // Append signal index json_name = json_object_get(json_signal_copy, "name"); if (json_name) { const char *name = json_string_value(json_name); char *name_new; int ret __attribute__((unused)); ret = asprintf(&name_new, "%s%d", name, i); json_string_set(json_name, name_new); } json_array_append_new(json_signals, json_signal_copy); } json_object_set_new(json, "signals", json_signals); } ret = signals->parse(json_signals); if (ret) throw ConfigError(json_signals, "node-config-node-signals", "Failed to parse signal definition"); } else if (json_is_string(json_signals)) { const char *dt = json_string_value(json_signals); signals = std::make_shared(dt); if (!signals) return -1; } else { signals = std::make_shared(DEFAULT_SAMPLE_LENGTH, SignalType::FLOAT); if (!signals) return -1; } #ifdef WITH_HOOKS if (json_hooks) { int m = direction == NodeDirection::Direction::OUT ? (int)Hook::Flags::NODE_WRITE : (int)Hook::Flags::NODE_READ; hooks.parse(json_hooks, m, nullptr, node); } #endif // WITH_HOOKS return 0; } void NodeDirection::check() { if (vectorize <= 0) throw RuntimeError( "Invalid setting 'vectorize' with value {}. Must be natural number!", vectorize); #ifdef WITH_HOOKS hooks.check(); #endif // WITH_HOOKS } int NodeDirection::prepare() { #ifdef WITH_HOOKS int t = direction == NodeDirection::Direction::OUT ? (int)Hook::Flags::NODE_WRITE : (int)Hook::Flags::NODE_READ; int m = builtin ? t | (int)Hook::Flags::BUILTIN : 0; hooks.prepare(signals, m, nullptr, node); #endif // WITH_HOOKS return 0; } int NodeDirection::start() { #ifdef WITH_HOOKS hooks.start(); #endif // WITH_HOOKS return 0; } int NodeDirection::stop() { #ifdef WITH_HOOKS hooks.stop(); #endif // WITH_HOOKS return 0; } SignalList::Ptr NodeDirection::getSignals(int after_hooks) const { #ifdef WITH_HOOKS if (after_hooks && hooks.size() > 0) return hooks.getSignals(); #endif // WITH_HOOKS return signals; } unsigned NodeDirection::getSignalsMaxCount() const { #ifdef WITH_HOOKS if (hooks.size() > 0) return MAX(signals->size(), hooks.getSignalsMaxCount()); #endif // WITH_HOOKS return signals->size(); }