mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
api: implement first version of universal data-exchange API
This commit is contained in:
parent
f09f91a9e2
commit
56fa561493
12 changed files with 604 additions and 3 deletions
|
@ -109,7 +109,7 @@ protected:
|
|||
void worker();
|
||||
|
||||
public:
|
||||
/** Initalize the API.
|
||||
/** Initialize the API.
|
||||
*
|
||||
* Save references to list of paths / nodes for command execution.
|
||||
*/
|
||||
|
|
49
include/villas/api/requests/universal.hpp
Normal file
49
include/villas/api/requests/universal.hpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
/** Universal Data-exchange API request.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASnode
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <villas/nodes/api.hpp>
|
||||
#include <villas/api/requests/node.hpp>
|
||||
|
||||
namespace villas {
|
||||
namespace node {
|
||||
|
||||
/* Forward declarations */
|
||||
class Node;
|
||||
|
||||
namespace api {
|
||||
|
||||
class UniversalRequest : public NodeRequest {
|
||||
|
||||
protected:
|
||||
APINode *api_node;
|
||||
|
||||
public:
|
||||
using NodeRequest::NodeRequest;
|
||||
|
||||
virtual void
|
||||
prepare();
|
||||
};
|
||||
|
||||
} /* namespace api */
|
||||
} /* namespace node */
|
||||
} /* namespace villas */
|
62
include/villas/nodes/api.hpp
Normal file
62
include/villas/nodes/api.hpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
/** Node type: Universal Data-exchange API
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASnode
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <villas/node.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace villas {
|
||||
namespace node {
|
||||
|
||||
/* Forward declarations */
|
||||
struct Sample;
|
||||
|
||||
class APINode : public Node {
|
||||
|
||||
public:
|
||||
APINode(const std::string &name = "");
|
||||
|
||||
struct Direction {
|
||||
Sample *sample;
|
||||
pthread_cond_t cv;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
// Accessed by api::universal::SignalRequest
|
||||
Direction read, write;
|
||||
|
||||
virtual
|
||||
int prepare();
|
||||
|
||||
protected:
|
||||
|
||||
virtual
|
||||
int _read(struct Sample *smps[], unsigned cnt);
|
||||
|
||||
virtual
|
||||
int _write(struct Sample *smps[], unsigned cnt);
|
||||
};
|
||||
|
||||
} /* namespace node */
|
||||
} /* namespace villas */
|
|
@ -129,13 +129,13 @@ public:
|
|||
|
||||
os << CLR_MAG("=>");
|
||||
|
||||
if (p.destinations.size() > 1)
|
||||
if (p.destinations.size() != 1)
|
||||
os << " [";
|
||||
|
||||
for (auto pd : p.destinations)
|
||||
os << " " << pd->getNode()->getNameShort();
|
||||
|
||||
if (p.destinations.size() > 1)
|
||||
if (p.destinations.size() != 1)
|
||||
os << " ]";
|
||||
|
||||
return os;
|
||||
|
|
|
@ -28,6 +28,7 @@ set(API_SRC
|
|||
|
||||
requests/node.cpp
|
||||
requests/path.cpp
|
||||
requests/universal.cpp
|
||||
|
||||
requests/status.cpp
|
||||
requests/capabiltities.cpp
|
||||
|
@ -43,6 +44,11 @@ set(API_SRC
|
|||
requests/paths.cpp
|
||||
requests/path_info.cpp
|
||||
requests/path_action.cpp
|
||||
|
||||
requests/universal/config.cpp
|
||||
requests/universal/info.cpp
|
||||
requests/universal/signal.cpp
|
||||
requests/universal/signals.cpp
|
||||
)
|
||||
|
||||
if(WITH_GRAPHVIZ)
|
||||
|
|
36
lib/api/requests/universal.cpp
Normal file
36
lib/api/requests/universal.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/** Universal Data-exchange API request
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASnode
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <villas/api/requests/universal.hpp>
|
||||
|
||||
using namespace villas::node;
|
||||
using namespace villas::node::api;
|
||||
|
||||
void UniversalRequest::prepare()
|
||||
{
|
||||
NodeRequest::prepare();
|
||||
|
||||
api_node = dynamic_cast<APINode*>(node);
|
||||
if (!api_node)
|
||||
throw BadRequest("Node {} is not an univeral API node!", node->getNameShort());
|
||||
}
|
57
lib/api/requests/universal/config.cpp
Normal file
57
lib/api/requests/universal/config.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/** The Universal Data-exchange API.
|
||||
*
|
||||
* @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASnode
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <villas/api/requests/universal.hpp>
|
||||
#include <villas/api/response.hpp>
|
||||
#include <villas/node.hpp>
|
||||
|
||||
namespace villas {
|
||||
namespace node {
|
||||
namespace api {
|
||||
namespace universal {
|
||||
|
||||
class ConfigRequest : public UniversalRequest {
|
||||
public:
|
||||
using UniversalRequest::UniversalRequest;
|
||||
|
||||
virtual Response * execute()
|
||||
{
|
||||
if (method != Session::Method::GET)
|
||||
throw InvalidMethod(this);
|
||||
|
||||
if (body != nullptr)
|
||||
throw BadRequest("This endpoint does not accept any body data");
|
||||
|
||||
return new JsonResponse(session, HTTP_STATUS_OK, node->getConfig());
|
||||
}
|
||||
};
|
||||
|
||||
/* Register API requests */
|
||||
static char n[] = "universal/config";
|
||||
static char r[] = "/universal/(" RE_NODE_NAME ")/config";
|
||||
static char d[] = "get configuration of universal data-exchange API";
|
||||
static RequestPlugin<ConfigRequest, n, r, d> p;
|
||||
|
||||
} /* namespace universal */
|
||||
} /* namespace api */
|
||||
} /* namespace node */
|
||||
} /* namespace villas */
|
74
lib/api/requests/universal/info.cpp
Normal file
74
lib/api/requests/universal/info.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
/** The Universal Data-exchange API.
|
||||
*
|
||||
* @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASnode
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <uuid.h>
|
||||
|
||||
#include <villas/api/requests/universal.hpp>
|
||||
#include <villas/api/response.hpp>
|
||||
#include <villas/node.hpp>
|
||||
|
||||
namespace villas {
|
||||
namespace node {
|
||||
namespace api {
|
||||
namespace universal {
|
||||
|
||||
class InfoRequest : public UniversalRequest {
|
||||
public:
|
||||
using UniversalRequest::UniversalRequest;
|
||||
|
||||
virtual Response * execute()
|
||||
{
|
||||
if (method != Session::Method::GET)
|
||||
throw InvalidMethod(this);
|
||||
|
||||
if (body != nullptr)
|
||||
throw BadRequest("This endpoint does not accept any body data");
|
||||
|
||||
auto uid = node->getUuid();
|
||||
|
||||
char uid_str[UUID_STR_LEN];
|
||||
uuid_unparse(uid, uid_str);
|
||||
|
||||
auto *info = json_pack("{ s: s, s: s, s: { s: s, s: s, s: s } }",
|
||||
"id", node->getNameShort().c_str(),
|
||||
"uuid", uid_str,
|
||||
|
||||
"transport",
|
||||
"type", "villas",
|
||||
"version", PROJECT_VERSION,
|
||||
"build", PROJECT_BUILD_ID
|
||||
);
|
||||
|
||||
return new JsonResponse(session, HTTP_STATUS_OK, info);
|
||||
}
|
||||
};
|
||||
|
||||
/* Register API requests */
|
||||
static char n[] = "universal/info";
|
||||
static char r[] = "/universal/(" RE_NODE_NAME ")/info";
|
||||
static char d[] = "get infos of universal data-exchange API";
|
||||
static RequestPlugin<InfoRequest, n, r, d> p;
|
||||
|
||||
} /* namespace universal */
|
||||
} /* namespace api */
|
||||
} /* namespace node */
|
||||
} /* namespace villas */
|
139
lib/api/requests/universal/signal.cpp
Normal file
139
lib/api/requests/universal/signal.cpp
Normal file
|
@ -0,0 +1,139 @@
|
|||
/** The Universal Data-exchange API.
|
||||
*
|
||||
* @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASnode
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <villas/api/requests/universal.hpp>
|
||||
#include <villas/api/response.hpp>
|
||||
#include <villas/timing.hpp>
|
||||
|
||||
namespace villas {
|
||||
namespace node {
|
||||
namespace api {
|
||||
namespace universal {
|
||||
|
||||
class SignalRequest : public UniversalRequest {
|
||||
public:
|
||||
using UniversalRequest::UniversalRequest;
|
||||
|
||||
Response * executeGet(const std::string &signalName)
|
||||
{
|
||||
if (body != nullptr)
|
||||
throw BadRequest("This endpoint does not accept any body data");
|
||||
|
||||
pthread_mutex_lock(&api_node->write.mutex);
|
||||
|
||||
auto *smp = api_node->write.sample;
|
||||
if (!smp) {
|
||||
pthread_mutex_unlock(&api_node->write.mutex);
|
||||
throw Error(HTTP_STATUS_NOT_FOUND, "No data available");
|
||||
}
|
||||
|
||||
auto idx = smp->signals->getIndexByName(signalName);
|
||||
if (idx < 0) {
|
||||
pthread_mutex_unlock(&api_node->write.mutex);
|
||||
throw Error(HTTP_STATUS_NOT_FOUND, "Unknown signal id: {}", signalName);
|
||||
}
|
||||
|
||||
auto sig = smp->signals->getByIndex(idx);
|
||||
auto *json_signal = json_pack("{ s: f, s: o }",
|
||||
"timestamp", time_to_double(&smp->ts.origin),
|
||||
"value", smp->data[idx].toJson(sig->type)
|
||||
);
|
||||
|
||||
if (smp->length <= (unsigned) idx)
|
||||
smp->length = idx + 1;
|
||||
|
||||
smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_DATA;
|
||||
|
||||
pthread_mutex_unlock(&api_node->write.mutex);
|
||||
|
||||
logger->info("resp: {}", (void *) json_signal);
|
||||
|
||||
return new JsonResponse(session, HTTP_STATUS_OK, json_signal);
|
||||
}
|
||||
|
||||
Response * executePut(const std::string &signalName)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pthread_mutex_lock(&api_node->read.mutex);
|
||||
|
||||
auto *smp = api_node->read.sample;
|
||||
if (!smp) {
|
||||
pthread_mutex_unlock(&api_node->read.mutex);
|
||||
throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Not initialized yet");
|
||||
}
|
||||
|
||||
auto idx = smp->signals->getIndexByName(signalName);
|
||||
if (idx < 0) {
|
||||
pthread_mutex_unlock(&api_node->read.mutex);
|
||||
throw BadRequest("Unknown signal id: {}", signalName);
|
||||
}
|
||||
|
||||
auto sig = smp->signals->getByIndex(idx);
|
||||
|
||||
double timestamp = 0;
|
||||
double value = 0;
|
||||
|
||||
json_error_t err;
|
||||
ret = json_unpack_ex(body, &err, 0, "{ s: f, s: f }",
|
||||
"timestamp", ×tamp,
|
||||
"value", &value
|
||||
);
|
||||
if (ret) {
|
||||
pthread_mutex_unlock(&api_node->read.mutex);
|
||||
throw BadRequest("Malformed body: {}", err.text);
|
||||
}
|
||||
|
||||
smp->ts.origin = time_from_double(timestamp);
|
||||
smp->data[idx].f = value;
|
||||
|
||||
pthread_cond_signal(&api_node->read.cv);
|
||||
pthread_mutex_unlock(&api_node->read.mutex);
|
||||
|
||||
return new JsonResponse(session, HTTP_STATUS_OK, json_object());
|
||||
}
|
||||
|
||||
virtual Response * execute()
|
||||
{
|
||||
auto const &signalName = matches[2];
|
||||
|
||||
switch (method) {
|
||||
case Session::Method::GET:
|
||||
return executeGet(signalName);
|
||||
case Session::Method::PUT:
|
||||
return executePut(signalName);
|
||||
default:
|
||||
throw InvalidMethod(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Register API requests */
|
||||
static char n[] = "universal/signal";
|
||||
static char r[] = "/universal/(" RE_NODE_NAME ")/signal/([a-z0-9_-]+)/state";
|
||||
static char d[] = "get or set signal of universal data-exchange API";
|
||||
static RequestPlugin<SignalRequest, n, r, d> p;
|
||||
|
||||
} /* namespace universal */
|
||||
} /* namespace api */
|
||||
} /* namespace node */
|
||||
} /* namespace villas */
|
81
lib/api/requests/universal/signals.cpp
Normal file
81
lib/api/requests/universal/signals.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
/** The Universal Data-exchange API.
|
||||
*
|
||||
* @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASnode
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <villas/api/requests/universal.hpp>
|
||||
#include <villas/api/response.hpp>
|
||||
|
||||
namespace villas {
|
||||
namespace node {
|
||||
namespace api {
|
||||
namespace universal {
|
||||
|
||||
class SignalsRequest : public UniversalRequest {
|
||||
public:
|
||||
using UniversalRequest::UniversalRequest;
|
||||
|
||||
virtual Response * execute()
|
||||
{
|
||||
if (method != Session::Method::GET)
|
||||
throw InvalidMethod(this);
|
||||
|
||||
if (body != nullptr)
|
||||
throw BadRequest("This endpoint does not accept any body data");
|
||||
|
||||
auto *json_sigs = json_array();
|
||||
for (auto const &sig : *node->getOutputSignals()) {
|
||||
auto *json_sig = json_pack("{ s: s, s: s, s: b, s: b, s: o }",
|
||||
"id", fmt::format("out/{}", sig->name).c_str(),
|
||||
"source", node->getNameShort().c_str(),
|
||||
"readable", true,
|
||||
"writable", false,
|
||||
"value", json_null()
|
||||
);
|
||||
|
||||
json_array_append(json_sigs, json_sig);
|
||||
}
|
||||
|
||||
for (auto const &sig : *node->getInputSignals()) {
|
||||
auto *json_sig = json_pack("{ s: s, s: s, s: b, s: b, s: o }",
|
||||
"id", fmt::format("in/{}", sig->name).c_str(),
|
||||
"source", node->getNameShort().c_str(),
|
||||
"readable", false,
|
||||
"writable", true,
|
||||
"value", json_null()
|
||||
);
|
||||
|
||||
json_array_append(json_sigs, json_sig);
|
||||
}
|
||||
|
||||
return new JsonResponse(session, HTTP_STATUS_OK, json_sigs);
|
||||
}
|
||||
};
|
||||
|
||||
/* Register API requests */
|
||||
static char n[] = "universal/signals";
|
||||
static char r[] = "/universal/(" RE_NODE_NAME ")/signals";
|
||||
static char d[] = "get signals of universal data-exchange API node";
|
||||
static RequestPlugin<SignalsRequest, n, r, d> p;
|
||||
|
||||
} /* namespace universal */
|
||||
} /* namespace api */
|
||||
} /* namespace node */
|
||||
} /* namespace villas */
|
|
@ -24,6 +24,10 @@ set(NODE_SRC
|
|||
loopback_internal.cpp
|
||||
)
|
||||
|
||||
if(WITH_WEB)
|
||||
list(APPEND NODE_SRC api.cpp)
|
||||
endif()
|
||||
|
||||
# Enable Golang support
|
||||
if(WITH_NODE_GO)
|
||||
list(APPEND NODE_SRC go.cpp)
|
||||
|
|
93
lib/nodes/api.cpp
Normal file
93
lib/nodes/api.cpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
/** Node type: Universal Data-exchange API
|
||||
*
|
||||
* @author Steffen Vogel <svogel2@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014-2022, Institute for Automation of Complex Power Systems, EONERC
|
||||
* @license GNU General Public License (version 3)
|
||||
*
|
||||
* VILLASnode
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <vector>
|
||||
#include <villas/exceptions.hpp>
|
||||
#include <villas/nodes/api.hpp>
|
||||
|
||||
using namespace villas;
|
||||
using namespace villas::node;
|
||||
|
||||
APINode::APINode(const std::string &name) :
|
||||
Node(name)
|
||||
{
|
||||
int ret;
|
||||
auto dirs = std::vector{&read, &write};
|
||||
|
||||
for (auto dir : dirs) {
|
||||
ret = pthread_mutex_init(&dir->mutex, nullptr);
|
||||
if (ret)
|
||||
throw RuntimeError("failed to initialize mutex");
|
||||
|
||||
ret = pthread_cond_init(&dir->cv, nullptr);
|
||||
if (ret)
|
||||
throw RuntimeError("failed to initialize mutex");
|
||||
}
|
||||
}
|
||||
|
||||
int APINode::prepare()
|
||||
{
|
||||
auto signals_in = getInputSignals(false);
|
||||
|
||||
read.sample = sample_alloc_mem(signals_in->size());
|
||||
if (!read.sample)
|
||||
throw MemoryAllocationError();
|
||||
|
||||
write.sample = sample_alloc_mem(64);
|
||||
if (!write.sample)
|
||||
throw MemoryAllocationError();
|
||||
|
||||
unsigned j = 0;
|
||||
for (auto sig : *signals_in)
|
||||
read.sample->data[j++] = sig->init;
|
||||
|
||||
read.sample->length = j;
|
||||
read.sample->signals = signals_in;
|
||||
|
||||
return Node::prepare();
|
||||
}
|
||||
|
||||
int APINode::_read(struct Sample *smps[], unsigned cnt)
|
||||
{
|
||||
assert(cnt == 1);
|
||||
|
||||
pthread_cond_wait(&read.cv, &read.mutex);
|
||||
|
||||
sample_copy(smps[0], read.sample);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int APINode::_write(struct Sample *smps[], unsigned cnt)
|
||||
{
|
||||
assert(cnt == 1);
|
||||
|
||||
sample_copy(write.sample, smps[0]);
|
||||
|
||||
pthread_cond_signal(&write.cv);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char n[] = "api";
|
||||
static char d[] = "A node providing a HTTP REST interface";
|
||||
static NodePlugin<APINode, n , d, (int) NodeFactory::Flags::SUPPORTS_READ | (int) NodeFactory::Flags::SUPPORTS_WRITE, 1> p;
|
Loading…
Add table
Reference in a new issue