satdump/src-core/dsp/flowgraph/flowgraph.cpp

225 lines
8.3 KiB
C++
Raw Permalink Normal View History

2025-03-09 10:16:40 +01:00
#include "flowgraph.h"
#include "core/exception.h"
#include "dsp/flowgraph/missing_node.h"
2026-03-09 20:21:34 +01:00
#include "libs/muparser/muParser.h"
2025-03-09 10:16:40 +01:00
#include "logger.h"
2026-03-10 18:04:18 +01:00
#include <limits>
2026-03-02 07:50:57 +01:00
#include <mutex>
2025-04-21 23:17:21 +02:00
2025-03-09 10:16:40 +01:00
namespace satdump
{
namespace ndsp
{
2026-03-10 18:04:18 +01:00
namespace flowgraph
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
int Flowgraph::getNewNodeID()
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
for (int i = 0; i < std::numeric_limits<int>::max(); i++)
{
bool already_contained = false;
for (auto &n : nodes)
if (n->id == i)
2025-03-09 10:16:40 +01:00
already_contained = true;
2026-03-10 18:04:18 +01:00
if (already_contained)
continue;
return i;
}
2025-03-09 10:16:40 +01:00
2026-03-10 18:04:18 +01:00
throw satdump_exception("No valid ID found for new node ID!");
2025-03-09 10:16:40 +01:00
}
2026-03-10 18:04:18 +01:00
int Flowgraph::getNewNodeIOID(std::vector<Node::InOut> *ptr)
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
for (int i = 0; i < std::numeric_limits<int>::max(); i++)
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
bool already_contained = false;
for (auto &n : nodes) // Check all nodes currently in flowgraph
for (auto &io : n->node_io)
if (io.id == i)
already_contained = true;
if (ptr != nullptr)
for (auto &io : *ptr) // Check in node being added if required (on creation!)
if (io.id == i)
already_contained = true;
if (already_contained)
continue;
return i;
2025-03-09 10:16:40 +01:00
}
2026-03-10 18:04:18 +01:00
throw satdump_exception("No valid ID found for new node IO ID!");
}
2025-03-09 10:16:40 +01:00
2026-03-10 18:04:18 +01:00
int Flowgraph::getNewLinkID()
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
for (int i = 0; i < std::numeric_limits<int>::max(); i++)
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
bool already_contained = false;
for (auto &l : links) // Check all links
if (l.id == i)
already_contained = true;
if (already_contained)
continue;
return i;
2025-03-09 10:16:40 +01:00
}
2026-03-10 18:04:18 +01:00
throw satdump_exception("No valid ID found for new link ID!");
2025-03-09 10:16:40 +01:00
}
2026-03-10 18:04:18 +01:00
void Flowgraph::updateVars()
2026-01-16 18:16:43 +01:00
{
2026-03-10 18:04:18 +01:00
std::lock_guard<std::mutex> lg(flow_mtx);
2026-02-03 16:32:37 +01:00
2026-03-10 18:04:18 +01:00
// For each node, check variables that have an expression set, parse it & set them.
2026-01-16 18:16:43 +01:00
for (auto &n : nodes)
{
2026-03-10 18:04:18 +01:00
for (auto &v : n->vars)
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
try
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
mu::Parser equParser;
equParser.SetExpr(v.second);
2025-03-09 10:16:40 +01:00
2026-03-10 18:04:18 +01:00
for (auto &var : variables)
equParser.DefineConst(var.first, var.second);
2026-02-03 16:32:37 +01:00
2026-03-10 18:04:18 +01:00
int nout = 0;
double *out = equParser.Eval(nout);
2026-02-03 16:32:37 +01:00
2026-03-10 18:04:18 +01:00
nlohmann::json sv;
sv[v.first] = *out;
2026-02-03 16:32:37 +01:00
2026-03-10 18:04:18 +01:00
if (nout == 1)
n->internal->setP(sv);
else
logger->error("Error parsing expression for %s!", v.first.c_str());
2026-01-16 18:16:43 +01:00
}
2026-03-10 18:04:18 +01:00
catch (mu::ParserError &e)
2026-03-09 20:21:34 +01:00
{
2026-03-10 18:04:18 +01:00
logger->error("Error parsing expression for %s (%s)!", v.first.c_str(), e.GetMsg().c_str());
2026-03-09 20:21:34 +01:00
}
}
}
}
2026-03-10 18:04:18 +01:00
std::shared_ptr<Flowgraph::Node> Flowgraph::addNode(std::string id, std::shared_ptr<NodeInternal> i)
2026-03-09 20:21:34 +01:00
{
2026-03-10 18:04:18 +01:00
auto ptr = std::make_shared<Node>(this, id, i);
nodes.push_back(ptr);
return ptr;
2026-03-09 20:21:34 +01:00
}
2026-03-10 18:04:18 +01:00
nlohmann::json Flowgraph::getJSON()
2026-03-09 20:21:34 +01:00
{
2026-03-10 18:04:18 +01:00
std::lock_guard<std::mutex> lg(flow_mtx);
2026-03-09 20:21:34 +01:00
2026-03-10 18:04:18 +01:00
nlohmann::json j;
2026-03-09 20:21:34 +01:00
2026-03-10 18:04:18 +01:00
for (auto &n : nodes)
j["nodes"][n->id] = n->getJSON();
j["links"] = links;
j["vars"] = variables;
2026-03-09 20:21:34 +01:00
2026-03-10 18:04:18 +01:00
return j;
2026-03-09 20:21:34 +01:00
}
2025-03-09 10:16:40 +01:00
2026-03-10 18:04:18 +01:00
void Flowgraph::setJSON(nlohmann::json j)
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
std::lock_guard<std::mutex> lg(flow_mtx);
2026-03-09 20:21:34 +01:00
2026-03-10 18:04:18 +01:00
if (j.contains("vars"))
variables = j["vars"];
2026-01-27 21:17:35 +01:00
2026-03-10 18:04:18 +01:00
nodes.clear();
links.clear();
2025-03-09 10:16:40 +01:00
2026-03-10 18:04:18 +01:00
for (auto &n : j["nodes"].items())
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
if (n.value().contains("int_id"))
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
if (node_internal_registry.count(n.value()["int_id"]))
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
try
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
auto i = node_internal_registry[n.value()["int_id"]].func(this);
auto nn = std::make_shared<Node>(this, n.value(), i);
nodes.push_back(nn);
2025-03-09 10:16:40 +01:00
}
2026-03-10 18:04:18 +01:00
catch (std::exception &e)
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
logger->error("Error adding node with ID : " + n.value()["int_id"].get<std::string>() + ", Error : %s", e.what());
2025-03-09 10:16:40 +01:00
}
}
2026-03-10 18:04:18 +01:00
else
2025-03-09 10:16:40 +01:00
{
2026-03-10 18:04:18 +01:00
logger->error("Could not find node with ID : " + n.value()["int_id"].get<std::string>());
try
{
int ni = 0, no = 0;
for (auto &io : n.value()["io"])
if (io["is_out"].get<bool>())
no++;
else
ni++;
auto i = std::make_shared<NodeMissing>(this, ni, no);
auto nn = std::make_shared<Node>(this, n.value(), i);
nodes.push_back(nn);
}
catch (std::exception &e)
{
logger->error("Error adding missing node with ID : " + n.value()["int_id"].get<std::string>() + ", Error : %s", e.what());
}
2025-03-09 10:16:40 +01:00
}
}
2026-03-10 18:04:18 +01:00
else
2026-01-27 21:17:35 +01:00
{
2026-03-10 18:04:18 +01:00
logger->error("Node is missing int_id!");
2026-01-27 21:17:35 +01:00
}
2025-03-09 10:16:40 +01:00
}
2026-03-10 18:04:18 +01:00
// Links need to be filtered in case some blocks are missing!
std::vector<Link> tmp_links = j["links"];
2025-04-21 23:17:21 +02:00
2026-03-10 18:04:18 +01:00
for (auto &link : tmp_links)
{
bool got_in = false, got_ou = false;
for (auto &n : nodes)
{
for (auto &io : n->node_io)
{
if (io.id == link.start)
got_in = true;
if (io.id == link.end)
got_ou = true;
}
}
2025-03-09 10:16:40 +01:00
2026-03-10 18:04:18 +01:00
if (got_in && got_ou)
links.push_back(link);
}
2026-03-10 18:04:18 +01:00
// Update node IOs to reflect the proper types on links
2025-03-10 20:05:31 +01:00
for (auto &n : nodes)
{
2026-03-10 18:04:18 +01:00
size_t ic = 0, oc = 0;
for (auto &io : n->node_io)
2025-03-10 20:05:31 +01:00
{
2026-03-10 18:04:18 +01:00
if (io.is_out)
{
2026-03-10 18:04:18 +01:00
if (n->internal->blk->get_outputs().size() > oc)
io.type = n->internal->blk->get_outputs()[oc].type;
oc++;
}
else
{
if (n->internal->blk->get_inputs().size() > ic)
io.type = n->internal->blk->get_inputs()[ic++].type;
ic++;
}
2025-03-10 20:05:31 +01:00
}
}
2025-03-09 10:16:40 +01:00
}
2026-03-10 18:04:18 +01:00
} // namespace flowgraph
2025-04-15 19:06:12 +01:00
} // namespace ndsp
2026-03-10 18:04:18 +01:00
} // namespace satdump