Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,10 @@ pkg_check_modules(NANOMSG IMPORTED_TARGET nanomsg)
if(NOT NANOMSG_FOUND)
pkg_check_modules(NANOMSG IMPORTED_TARGET libnanomsg>=1.0.0)
endif()

pkg_check_modules(GRPC IMPORTED_TARGET grpc grpc++)
if (TARGET PkgConfig::GRPC)
set_property(TARGET PkgConfig::GRPC PROPERTY INTERFACE_COMPILE_OPTIONS "")
endif()

if (REDISPP_FOUND)
file(READ "${REDISPP_INCLUDEDIR}/sw/redis++/tls.h" CONTENTS)
Expand Down Expand Up @@ -187,6 +190,7 @@ cmake_dependent_option(WITH_SRC "Build executables"
cmake_dependent_option(WITH_TESTS "Run tests" "${WITH_DEFAULTS}" "TOPLEVEL_PROJECT" OFF)
cmake_dependent_option(WITH_TOOLS "Build auxilary tools" "${WITH_DEFAULTS}" "TOPLEVEL_PROJECT" OFF)
cmake_dependent_option(WITH_WEB "Build with internal webserver" "${WITH_DEFAULTS}" "LIBWEBSOCKETS_FOUND" OFF)
cmake_dependent_option(WITH_GRPC "Build with grpc api" "${WITH_DEFAULTS}" "GRPC_FOUND" OFF)

cmake_dependent_option(WITH_NODE_AMQP "Build with amqp node-type" "${WITH_DEFAULTS}" "RABBITMQ_C_FOUND" OFF)
cmake_dependent_option(WITH_NODE_CAN "Build with can node-type" "${WITH_DEFAULTS}" "" OFF)
Expand Down Expand Up @@ -297,6 +301,7 @@ add_feature_info(SRC WITH_SRC "Build execu
add_feature_info(TESTS WITH_TESTS "Run tests")
add_feature_info(TOOLS WITH_TOOLS "Build auxilary tools")
add_feature_info(WEB WITH_WEB "Build with internal webserver")
add_feature_info(GRPC_API WITH_GRPC "Build with gRPC API")

add_feature_info(NODE_AMQP WITH_NODE_AMQP "Build with amqp node-type")
add_feature_info(NODE_CAN WITH_NODE_CAN "Build with can node-type")
Expand Down
7 changes: 7 additions & 0 deletions doc/openapi/components/schemas/config/nodes/_gateway.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# yaml-language-server: $schema=http://json-schema.org/draft-07/schema
# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
# SPDX-License-Identifier: Apache-2.0
---
allOf:
- $ref: ../node_obj.yaml
- $ref: gateway.yaml
15 changes: 15 additions & 0 deletions doc/openapi/components/schemas/config/nodes/gateway.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# yaml-language-server: $schema=http://json-schema.org/draft-07/schema
# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
# SPDX-License-Identifier: Apache-2.0
---
allOf:
- type: object
properties:
format:
$ref: ../format_spec.yaml
gateway_type:
type: string
address:
type: string

- $ref: ../node.yaml
14 changes: 14 additions & 0 deletions etc/examples/nodes/gateway.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SPDX-FileCopyrightText: 2014-2023 Institute for Automation of Complex Power Systems, RWTH Aachen University
# SPDX-License-Identifier: Apache-2.0

nodes = {
gateway_node = {
type = "gateway"

format = "protobuf"
# API type
gateway_type = "gRPC"
# Address of remote server
address = "localhost:50051"
}
}
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@

opendssc = pkgs.callPackage (nixDir + "/opendssc.nix") { };
orchestra = pkgs.callPackage (nixDir + "/orchestra.nix") { };
grpc-server-reflection = pkgs.callPackage (nixDir + "/grpc_server_reflection.nix") { };
};
in
{
Expand Down
59 changes: 59 additions & 0 deletions include/villas/nodes/gateway.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* Node type for API gateway.
*
* Author: Jitpanu Maneeratpongsuk <jitpanu.maneeratpongsuk@rwth-aachen.de>
* SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, RWTH Aachen University
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <pthread.h>

#include <villas/format.hpp>
#include <villas/node.hpp>

namespace villas {
namespace node {

// Forward declarations
struct Sample;

class GatewayNode : public Node {
protected:
int parse(json_t *json) override;

int _read(struct Sample *smps[], unsigned cnt) override;
int _write(struct Sample *smps[], unsigned cnt) override;

public:
GatewayNode(const uuid_t &id = {}, const std::string &name = "");
enum ApiType { gRPC };

struct Direction {
Sample *sample;
pthread_cond_t cv;
pthread_mutex_t mutex;
char *buf;
size_t buflen;
size_t wbytes;
};

Direction read, write;
std::string address;
ApiType type;

Format::Ptr formatter;

int prepare() override;

int check() override;

int start() override;

int stop() override;

~GatewayNode();
};

} // namespace node
} // namespace villas
14 changes: 14 additions & 0 deletions lib/api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ if(WITH_GRAPHVIZ)
list(APPEND LIBRARIES PkgConfig::CGRAPH PkgConfig::GVC)
endif()

if (WITH_GRPC)
find_path(REFLECTION_INCLUDE_DIR
NAMES grpc/reflection/v1alpha/reflection.pb.cc
)
if (REFLECTION_INCLUDE_DIR)
list(APPEND API_SRC
requests/gateway/grpc.cpp
${REFLECTION_INCLUDE_DIR}/grpc/reflection/v1alpha/reflection.pb.cc
${REFLECTION_INCLUDE_DIR}/grpc/reflection/v1alpha/reflection.grpc.pb.cc
)
list(APPEND LIBRARIES PkgConfig::PROTOBUF PkgConfig::GRPC)
endif()
endif()

add_library(api STATIC ${API_SRC})
target_include_directories(api PUBLIC ${INCLUDE_DIRS})
target_link_libraries(api PUBLIC ${LIBRARIES})
2 changes: 1 addition & 1 deletion lib/api/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ std::string Request::toString() {

Request *RequestFactory::create(Session *s, const std::string &uri,
Session::Method meth, unsigned long ct) {
s->logger->info("Lookup request handler for: uri={}", uri);
s->logger->debug("Lookup request handler for: uri={}", uri);

for (auto *rf : plugin::registry->lookup<RequestFactory>()) {
std::smatch mr;
Expand Down
Loading