Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 7 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ jobs:
--proto_path=proto \
--python_out=clients/python/src \
--grpc_python_out=clients/python/src \
proto/mavlink_bridge.proto proto/mavlink/common.proto
proto/mavlink2grpc/mavlink2grpc.proto proto/mavlink2grpc/mavlink/common.proto

# Add __init__.py files to make it a package
touch clients/python/src/__init__.py
mkdir -p clients/python/src/mavlink
touch clients/python/src/mavlink/__init__.py
mkdir -p clients/python/src/mavlink2grpc/mavlink
touch clients/python/src/mavlink2grpc/__init__.py
touch clients/python/src/mavlink2grpc/mavlink/__init__.py

- name: Build Python Package
run: |
Expand Down Expand Up @@ -132,9 +132,9 @@ jobs:
python3 generator/main.py --dialect common --proto-out proto --cpp-out bridge/src/mavlink

# Copy proto files to npm package folder
mkdir -p clients/node/proto/mavlink
cp proto/mavlink_bridge.proto clients/node/proto/
cp proto/mavlink/*.proto clients/node/proto/mavlink/
mkdir -p clients/node/proto/mavlink2grpc/mavlink
cp proto/mavlink2grpc/mavlink2grpc.proto clients/node/proto/mavlink2grpc/
cp proto/mavlink2grpc/mavlink/*.proto clients/node/proto/mavlink2grpc/mavlink/

- name: Publish to npm
env:
Expand Down
7 changes: 4 additions & 3 deletions bridge/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ set(PROTO_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../proto)
set(GENERATED_PROTOBUF_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../generated)

file(MAKE_DIRECTORY ${GENERATED_PROTOBUF_PATH})
file(MAKE_DIRECTORY ${GENERATED_PROTOBUF_PATH}/mavlink)
file(MAKE_DIRECTORY ${GENERATED_PROTOBUF_PATH}/mavlink2grpc)
file(MAKE_DIRECTORY ${GENERATED_PROTOBUF_PATH}/mavlink2grpc/mavlink)

# Collect all proto files
file(GLOB MAVLINK_PROTO_FILES "${PROTO_PATH}/mavlink/*.proto")
file(GLOB ROOT_PROTO_FILES "${PROTO_PATH}/*.proto")
file(GLOB MAVLINK_PROTO_FILES "${PROTO_PATH}/mavlink2grpc/mavlink/*.proto")
file(GLOB ROOT_PROTO_FILES "${PROTO_PATH}/mavlink2grpc/*.proto")

# Combine all proto files and their outputs
set(ALL_PROTO_FILES ${MAVLINK_PROTO_FILES} ${ROOT_PROTO_FILES})
Expand Down
2 changes: 1 addition & 1 deletion bridge/src/Bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ Bridge::Bridge(const std::string& connection_url,
// Create gRPC service with router and send callback
service_ = std::make_shared<MavlinkBridgeServiceImpl>(
*router_,
[this](const mavlink::MavlinkMessage& proto_msg) -> bool {
[this](const mavlink2grpc::MavlinkMessage& proto_msg) -> bool {
if (!active_connection_ || !active_connection_->alive()) {
Logger::Warn("Cannot send message: No active MAVLink connection");
return false;
Expand Down
6 changes: 3 additions & 3 deletions bridge/src/service/Router.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace mavlink2grpc {

bool StreamSubscription::matches(const mavlink::MavlinkMessage& msg) const {
bool StreamSubscription::matches(const mavlink2grpc::MavlinkMessage& msg) const {
// Check system ID filter (0 = all systems)
if (filter.system_id() != 0 && msg.system_id() != filter.system_id()) {
return false;
Expand Down Expand Up @@ -39,7 +39,7 @@ bool StreamSubscription::matches(const mavlink::MavlinkMessage& msg) const {
}

uint64_t Router::subscribe(
const mavlink::StreamFilter& filter,
const mavlink2grpc::StreamFilter& filter,
StreamSubscription::WriteCallback write_func) {

std::lock_guard<std::mutex> lock(subscriptions_mutex_);
Expand Down Expand Up @@ -85,7 +85,7 @@ bool Router::unsubscribe(uint64_t subscription_id) {
return false;
}

size_t Router::route_message(const mavlink::MavlinkMessage& msg) {
size_t Router::route_message(const mavlink2grpc::MavlinkMessage& msg) {
std::lock_guard<std::mutex> lock(subscriptions_mutex_);

size_t delivered = 0;
Expand Down
12 changes: 6 additions & 6 deletions bridge/src/service/Router.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#pragma once

#include <mavlink_bridge.pb.h>
#include <mavlink2grpc/mavlink2grpc.pb.h>

#include <vector>
#include <mutex>
Expand All @@ -26,11 +26,11 @@ namespace mavlink2grpc {
* optional filtering by system ID, component ID, and message IDs.
*/
struct StreamSubscription {
using WriteCallback = std::function<bool(const mavlink::MavlinkMessage&)>;
using WriteCallback = std::function<bool(const mavlink2grpc::MavlinkMessage&)>;

uint64_t id; ///< Unique subscription ID
WriteCallback write_func; ///< Function to write message to stream
mavlink::StreamFilter filter; ///< Filter criteria
mavlink2grpc::StreamFilter filter; ///< Filter criteria
bool active; ///< Is subscription still active

/**
Expand All @@ -39,7 +39,7 @@ struct StreamSubscription {
* @param msg Message to check
* @return true if message passes filter, false otherwise
*/
bool matches(const mavlink::MavlinkMessage& msg) const;
bool matches(const mavlink2grpc::MavlinkMessage& msg) const;
};

/**
Expand Down Expand Up @@ -87,7 +87,7 @@ class Router {
* @return Subscription ID (use for unsubscribe)
*/
uint64_t subscribe(
const mavlink::StreamFilter& filter,
const mavlink2grpc::StreamFilter& filter,
StreamSubscription::WriteCallback write_func);

/**
Expand All @@ -107,7 +107,7 @@ class Router {
* @param msg Message to route
* @return Number of subscribers that received the message
*/
size_t route_message(const mavlink::MavlinkMessage& msg);
size_t route_message(const mavlink2grpc::MavlinkMessage& msg);

/**
* @brief Get number of active subscriptions.
Expand Down
12 changes: 6 additions & 6 deletions bridge/src/service/Service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ MavlinkBridgeServiceImpl::MavlinkBridgeServiceImpl(

grpc::Status MavlinkBridgeServiceImpl::StreamMessages(
grpc::ServerContext* context,
const mavlink::StreamFilter* request,
grpc::ServerWriter<mavlink::MavlinkMessage>* writer) {
const mavlink2grpc::StreamFilter* request,
grpc::ServerWriter<mavlink2grpc::MavlinkMessage>* writer) {

{
std::ostringstream oss;
Expand All @@ -33,7 +33,7 @@ grpc::Status MavlinkBridgeServiceImpl::StreamMessages(
// Subscribe to router with filter
uint64_t sub_id = router_.subscribe(
*request,
[writer](const mavlink::MavlinkMessage& msg) -> bool {
[writer](const mavlink2grpc::MavlinkMessage& msg) -> bool {
// Write to gRPC stream
return writer->Write(msg);
}
Expand Down Expand Up @@ -62,11 +62,11 @@ grpc::Status MavlinkBridgeServiceImpl::StreamMessages(

grpc::Status MavlinkBridgeServiceImpl::SendMessage(
grpc::ServerContext* /* context */,
const mavlink::MavlinkMessage* request,
mavlink::SendResponse* response) {
const mavlink2grpc::MavlinkMessage* request,
mavlink2grpc::SendResponse* response) {

// Validate request has payload
if (request->payload_case() == mavlink::MavlinkMessage::PAYLOAD_NOT_SET) {
if (request->payload_case() == mavlink2grpc::MavlinkMessage::PAYLOAD_NOT_SET) {
response->set_success(false);
response->set_error("No payload in message");
Logger::Warn("SendMessage RPC failed: No payload");
Expand Down
14 changes: 7 additions & 7 deletions bridge/src/service/Service.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#include "Router.h"

#include <mavlink_bridge.grpc.pb.h>
#include <mavlink2grpc/mavlink2grpc.grpc.pb.h>
#include <grpcpp/grpcpp.h>

#include <memory>
Expand All @@ -32,15 +32,15 @@ namespace mavlink2grpc {
*
* Thread-safe and supports multiple concurrent clients.
*/
class MavlinkBridgeServiceImpl final : public mavlink::MavlinkBridge::Service {
class MavlinkBridgeServiceImpl final : public mavlink2grpc::MavlinkBridge::Service {
public:
/**
* @brief Callback type for sending MAVLink messages.
*
* @param msg Proto message to convert and send
* @return true if sent successfully, false otherwise
*/
using SendMessageCallback = std::function<bool(const mavlink::MavlinkMessage&)>;
using SendMessageCallback = std::function<bool(const mavlink2grpc::MavlinkMessage&)>;

/**
* @brief Construct service with router and send callback.
Expand All @@ -65,8 +65,8 @@ class MavlinkBridgeServiceImpl final : public mavlink::MavlinkBridge::Service {
*/
grpc::Status StreamMessages(
grpc::ServerContext* context,
const mavlink::StreamFilter* request,
grpc::ServerWriter<mavlink::MavlinkMessage>* writer) override;
const mavlink2grpc::StreamFilter* request,
grpc::ServerWriter<mavlink2grpc::MavlinkMessage>* writer) override;

/**
* @brief Send MAVLink message to connected system.
Expand All @@ -80,8 +80,8 @@ class MavlinkBridgeServiceImpl final : public mavlink::MavlinkBridge::Service {
*/
grpc::Status SendMessage(
grpc::ServerContext* context,
const mavlink::MavlinkMessage* request,
mavlink::SendResponse* response) override;
const mavlink2grpc::MavlinkMessage* request,
mavlink2grpc::SendResponse* response) override;

/**
* @brief Shutdown the service and notify all active streams.
Expand Down
24 changes: 12 additions & 12 deletions bridge/test/test_router.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ void test_router_basic() {
TEST_ASSERT(router.subscription_count() == 0);

// Subscribe client 1 with no filters (system_id=0, component_id=0)
mavlink::StreamFilter filter1;
mavlink2grpc::StreamFilter filter1;
filter1.set_system_id(0);
filter1.set_component_id(0);

size_t client1_received = 0;
uint64_t sub1 = router.subscribe(filter1, [&](const mavlink::MavlinkMessage&) {
uint64_t sub1 = router.subscribe(filter1, [&](const mavlink2grpc::MavlinkMessage&) {
client1_received++;
return true;
});
Expand All @@ -33,7 +33,7 @@ void test_router_basic() {
TEST_ASSERT(router.subscription_count() == 1);

// Send a message
mavlink::MavlinkMessage msg1;
mavlink2grpc::MavlinkMessage msg1;
msg1.set_system_id(1);
msg1.set_component_id(1);
msg1.set_message_id(0); // HEARTBEAT
Expand All @@ -59,43 +59,43 @@ void test_router_filters() {
Router router;

// Filter for system 1, component 1, message 30 (ATTITUDE) only
mavlink::StreamFilter filter;
mavlink2grpc::StreamFilter filter;
filter.set_system_id(1);
filter.set_component_id(1);
filter.add_message_ids(30);

size_t received = 0;
router.subscribe(filter, [&](const mavlink::MavlinkMessage&) {
router.subscribe(filter, [&](const mavlink2grpc::MavlinkMessage&) {
received++;
return true;
});

// Message 1: Matches all
mavlink::MavlinkMessage msg1;
mavlink2grpc::MavlinkMessage msg1;
msg1.set_system_id(1);
msg1.set_component_id(1);
msg1.set_message_id(30);
router.route_message(msg1);
TEST_ASSERT(received == 1);

// Message 2: Different system ID (2)
mavlink::MavlinkMessage msg2;
mavlink2grpc::MavlinkMessage msg2;
msg2.set_system_id(2);
msg2.set_component_id(1);
msg2.set_message_id(30);
router.route_message(msg2);
TEST_ASSERT(received == 1); // shouldn't increase

// Message 3: Different component ID (2)
mavlink::MavlinkMessage msg3;
mavlink2grpc::MavlinkMessage msg3;
msg3.set_system_id(1);
msg3.set_component_id(2);
msg3.set_message_id(30);
router.route_message(msg3);
TEST_ASSERT(received == 1); // shouldn't increase

// Message 4: Different message ID (0 - HEARTBEAT)
mavlink::MavlinkMessage msg4;
mavlink2grpc::MavlinkMessage msg4;
msg4.set_system_id(1);
msg4.set_component_id(1);
msg4.set_message_id(0);
Expand All @@ -109,17 +109,17 @@ void test_router_cleanup() {
std::cout << "Running test_router_cleanup..." << std::endl;
Router router;

mavlink::StreamFilter filter;
mavlink2grpc::StreamFilter filter;

// Client whose write fails (simulates disconnected client)
router.subscribe(filter, [](const mavlink::MavlinkMessage&) {
router.subscribe(filter, [](const mavlink2grpc::MavlinkMessage&) {
return false; // write failed
});

TEST_ASSERT(router.subscription_count() == 1);

// Route a message - this will trigger write failure and mark inactive
mavlink::MavlinkMessage msg;
mavlink2grpc::MavlinkMessage msg;
size_t routed = router.route_message(msg);

TEST_ASSERT(routed == 0);
Expand Down
2 changes: 1 addition & 1 deletion clients/node/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/

/**
* Path to the main MAVLink bridge proto definition file (mavlink_bridge.proto)
* Path to the main MAVLink bridge proto definition file (mavlink2grpc.proto)
*/
export const protoPath: string;

Expand Down
2 changes: 1 addition & 1 deletion clients/node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ const path = require('path');

module.exports = {
protoDir: path.join(__dirname, 'proto'),
protoPath: path.join(__dirname, 'proto', 'mavlink_bridge.proto')
protoPath: path.join(__dirname, 'proto', 'mavlink2grpc', 'mavlink2grpc.proto')
};
2 changes: 1 addition & 1 deletion examples/inspector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"proto:generate": "grpc_tools_node_protoc --js_out=import_style=commonjs,binary:./generated --grpc_out=grpc_js:./generated --proto_path=../proto ../proto/mavlink_bridge.proto ../proto/mavlink/common.proto"
"proto:generate": "grpc_tools_node_protoc --js_out=import_style=commonjs,binary:./generated --grpc_out=grpc_js:./generated --proto_path=../proto ../proto/mavlink2grpc/mavlink2grpc.proto ../proto/mavlink2grpc/mavlink/common.proto"
},
"keywords": [
"mavlink",
Expand Down
4 changes: 2 additions & 2 deletions examples/inspector/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ class GRPCClient {
async connect() {
try {
// Load proto file
const PROTO_PATH = path.join(__dirname, '..', '..', 'proto', 'mavlink_bridge.proto');
const PROTO_PATH = path.join(__dirname, '..', '..', 'proto', 'mavlink2grpc', 'mavlink2grpc.proto');
const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
Expand All @@ -147,7 +147,7 @@ class GRPCClient {
const proto = grpc.loadPackageDefinition(packageDefinition);

// Create client - note: service name is MavlinkBridge (capital B in proto, but proto loader makes it camelCase)
this.client = new proto.mavlink.MavlinkBridge(
this.client = new proto.mavlink2grpc.MavlinkBridge(
this.serverAddress,
grpc.credentials.createInsecure()
);
Expand Down
2 changes: 1 addition & 1 deletion examples/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Python examples demonstrating how to use the mavlink2grpc bridge.
pip install grpcio grpcio-tools

# Create python files from generated protos
python3 -m grpc_tools.protoc -I./proto --python_out=./generated --grpc_python_out=./generated ./proto/mavlink_bridge.proto ./proto/mavlink/common.proto
python3 -m grpc_tools.protoc -I./proto --python_out=./generated --grpc_python_out=./generated ./proto/mavlink2grpc/mavlink2grpc.proto ./proto/mavlink2grpc/mavlink/common.proto
```

## Available Examples
Expand Down
10 changes: 5 additions & 5 deletions examples/python/stream_telemetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
# Add generated proto files to path
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "generated"))

import mavlink_bridge_pb2
import mavlink_bridge_pb2_grpc
from mavlink import common_pb2
from mavlink2grpc import mavlink2grpc_pb2
from mavlink2grpc import mavlink2grpc_pb2_grpc
from mavlink2grpc.mavlink import common_pb2


def main():
Expand All @@ -32,14 +32,14 @@ def main():
# 1. Connect to gRPC channel
print(f"Connecting to gRPC bridge at {args.host}...")
channel = grpc.insecure_channel(args.host)
stub = mavlink_bridge_pb2_grpc.MavlinkBridgeStub(channel)
stub = mavlink2grpc_pb2_grpc.MavlinkBridgeStub(channel)

# 2. Define message filters
# We filter by message IDs:
# 0 = HEARTBEAT
# 30 = ATTITUDE
# 33 = GLOBAL_POSITION_INT
stream_filter = mavlink_bridge_pb2.StreamFilter(
stream_filter = mavlink2grpc_pb2.StreamFilter(
system_id=0, # 0 means listen to all systems
component_id=0, # 0 means listen to all components
message_ids=[0, 30, 33]
Expand Down
Loading
Loading