mavlink and UDP server working
authorNils Forssén <forssennils@gmail.com>
Mon, 2 Jun 2025 20:50:51 +0000 (22:50 +0200)
committerNils Forssén <forssennils@gmail.com>
Mon, 2 Jun 2025 20:50:51 +0000 (22:50 +0200)
.vscode/c_cpp_properties.json [deleted file]
.vscode/settings.json [deleted file]
processes/udp_server/CMakeLists.txt
processes/udp_server/include/mavlink_handler.h [deleted file]
processes/udp_server/include/udp_server.h
processes/udp_server/main.cpp
processes/udp_server/udp_server.cpp

diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
deleted file mode 100644 (file)
index 44f86bc..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-    "configurations": [
-        {
-            "name": "Linux",
-            "includePath": [
-                "${workspaceFolder}/**",
-                "${workspaceFolder}/processes/**",
-            ],
-            "defines": [],
-            "compilerPath": "/usr/bin/gcc",
-            "cStandard": "c17",
-            "cppStandard": "gnu++17",
-            "intelliSenseMode": "linux-gcc-x64"
-        }
-    ],
-    "version": 4
-}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644 (file)
index 16961f3..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-{
-    "files.associations": {
-        "array": "cpp",
-        "atomic": "cpp",
-        "bit": "cpp",
-        "*.tcc": "cpp",
-        "bitset": "cpp",
-        "cctype": "cpp",
-        "charconv": "cpp",
-        "chrono": "cpp",
-        "clocale": "cpp",
-        "cmath": "cpp",
-        "codecvt": "cpp",
-        "compare": "cpp",
-        "concepts": "cpp",
-        "condition_variable": "cpp",
-        "cstdarg": "cpp",
-        "cstddef": "cpp",
-        "cstdint": "cpp",
-        "cstdio": "cpp",
-        "cstdlib": "cpp",
-        "cstring": "cpp",
-        "ctime": "cpp",
-        "cwchar": "cpp",
-        "cwctype": "cpp",
-        "deque": "cpp",
-        "map": "cpp",
-        "string": "cpp",
-        "unordered_map": "cpp",
-        "vector": "cpp",
-        "exception": "cpp",
-        "algorithm": "cpp",
-        "functional": "cpp",
-        "iterator": "cpp",
-        "memory": "cpp",
-        "memory_resource": "cpp",
-        "numeric": "cpp",
-        "optional": "cpp",
-        "random": "cpp",
-        "ratio": "cpp",
-        "regex": "cpp",
-        "source_location": "cpp",
-        "string_view": "cpp",
-        "system_error": "cpp",
-        "tuple": "cpp",
-        "type_traits": "cpp",
-        "utility": "cpp",
-        "fstream": "cpp",
-        "future": "cpp",
-        "initializer_list": "cpp",
-        "iomanip": "cpp",
-        "iosfwd": "cpp",
-        "iostream": "cpp",
-        "istream": "cpp",
-        "limits": "cpp",
-        "mutex": "cpp",
-        "new": "cpp",
-        "numbers": "cpp",
-        "ostream": "cpp",
-        "semaphore": "cpp",
-        "span": "cpp",
-        "sstream": "cpp",
-        "stdexcept": "cpp",
-        "stop_token": "cpp",
-        "streambuf": "cpp",
-        "thread": "cpp",
-        "typeinfo": "cpp",
-        "variant": "cpp",
-        "stdint.h": "c",
-        "spi.h": "c"
-    },
-    "C_Cpp.errorSquiggles": "enabled"
-}
\ No newline at end of file
index 6060c8b4ba46b5d35aadf22c6f58cc3f30add6f1..1e5ac002517958d47b3a9ce8c9fca5d5aa2a0a37 100755 (executable)
@@ -1,7 +1,6 @@
 add_executable(udp_server
     main.cpp
     udp_server.cpp
-    mavlink_handler.cpp
 )
 
 target_include_directories(udp_server PRIVATE include)
diff --git a/processes/udp_server/include/mavlink_handler.h b/processes/udp_server/include/mavlink_handler.h
deleted file mode 100644 (file)
index 7f73f3c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef MAVLINK_HANDLER_H
-#define MAVLINK_HANDLER_H
-
-// Standard
-#include <memory>
-
-// Libs
-#include <spdlog/spdlog.h>
-#include <common/mavlink.h>
-
-void init_mavlink_handler(std::shared_ptr<spdlog::logger> logg);
-
-void handle_heartbeat(const mavlink_message_t* message);
-
-#endif
\ No newline at end of file
index fffb0fbb75feee60fceef8892fbdb8c0f51576ce..6902b61f7bbe777a5083f3abec8ad0b9089ddbfe 100644 (file)
@@ -3,39 +3,29 @@
 
 // Standard
 #include <memory>
-#include <thread>
 
 // Socket
-#include <arpa/inet.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
 
-// Pipes
-#include <unistd.h>
-
 // Libs
 #include <spdlog/spdlog.h>
-#include <common/mavlink.h>
 
 // Local
-#include "util.h"
 #include "pipe_def.h"
-#include "mavlink_handler.h"
+#include "util.h"
 
 #define UDP_PORT 14552
 #define UDP_RECV_BUF_SIZE 2048 // enough for MTU 1500 bytes
 
-typedef int socket_fd_t;
-
 typedef struct {
-    socket_fd_t socket_fd;
+    int socket_fd;
     struct sockaddr_in addr;
     socklen_t addr_len;
     bool addr_set;
 } gcs_t;
 
-err_t udp_server_init(std::shared_ptr<spdlog::logger> logg);
-
-err_t udp_server_run(pipe_fd_t recvpipe_fd, pipe_fd_t sendpipe_fd);
+err_t udp_server_init(std::shared_ptr<spdlog::logger> logg, const pipe_fd_t recvpipe_fd, const pipe_fd_t sendpipe_fd);
+err_t udp_server_run();
 
 #endif
\ No newline at end of file
index 8f39fb4952d77d4d9099ca37424b98810c77d5c0..6c67a9de98d963253b5945760562250eef822d43 100755 (executable)
 
 static std::shared_ptr<spdlog::logger> logger;
 
-void receive_thread(gcs_t* src);
-void handle_heartbeat(const mavlink_message_t* message);
-void send_some(gcs_t* src);
-void send_heartbeat(gcs_t* src);
-
 // Main
 int main(int argc, char* argv[])
 {
     logger = spdlog::stdout_color_mt("udp_server");
     logger->set_level(UDP_LOGLEVEL);
 
-    udp_server_init(logger);
-
-    logger->debug("Opening pipes, waiting for writing process to start");
+    logger->debug("Opening pipes, waiting for writing process to start.");
     pipe_fd_t sendpipe_fd = open(SEND_PIPE, O_RDONLY);
     pipe_fd_t recvpipe_fd = open(RECV_PIPE, O_WRONLY);
-    
-    logger->debug("Pipes opened");
+
+    udp_server_init(logger, recvpipe_fd, sendpipe_fd);
 
     // Server mainloop, only exits on error
-    udp_server_run(recvpipe_fd, sendpipe_fd);
+    udp_server_run();
 
-    logger->debug("Closing sendpipe");
+    logger->debug("Closing sendpipe.");
     close(sendpipe_fd);
 
-    logger->debug("Closing recvpipe");
+    logger->debug("Closing recvpipe.");
     close(recvpipe_fd);
 
     return -1;
index 4e1ade5991c9f9f67bbb1384314c77727c702849..2053b19a785fd3e91553994214acf34c0e916d96 100644 (file)
@@ -1,18 +1,86 @@
 #include "udp_server.h"
 
+// Standard
+#include <thread>
+#include <memory>
+
+// Socket
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+// Pipes
+#include <unistd.h>
+
+// Libs
+#include <common/mavlink.h>
+#include <spdlog/spdlog.h>
+
+// Local
+#include "system_def.h"
+#include "pipe_def.h"
+#include "util.h"
+
 static std::shared_ptr<spdlog::logger> logger;
 
 static bool recv_thread_running = true;
 static gcs_t gcs = {};
 
+static pipe_fd_t recvpipe; 
+static pipe_fd_t sendpipe; 
+
 // Declarations
-static void recv_thread(pipe_fd_t sendpipe_fd);
+static void handle_request_autopilot_capabilities(const mavlink_command_long_t& cmd_long);
+static void handle_heartbeat(const mavlink_message_t& message);
+static void recv_thread();
 static void heartbeat_thread();
 static void handle_mavlink(mavlink_message_t& message);
 
 // Definitions
+static void handle_heartbeat(const mavlink_message_t& message)
+{
+    // Determine source of heartbeat
+    mavlink_heartbeat_t heartbeat;
+    mavlink_msg_heartbeat_decode(&message, &heartbeat);
+
+    switch (heartbeat.type) {
+        case MAV_TYPE_GCS:
+            logger->debug("Heartbeat from GCS!");
+            break;
+        default:
+            logger->warn("Heartbeat from unknown type: {}", heartbeat.type);
+            break;
+    }
+}
+
+static void handle_request_autopilot_capabilities(const mavlink_command_long_t& cmd_long)
+{
+    // No need to handle the message, only send out a response
+    mavlink_message_t response_msg;
+    mavlink_autopilot_version_t version_struct = 
+    {
+
+    };
+
+    mavlink_msg_autopilot_version_encode(
+        MAV_SYS_ID,
+        MAV_COMP_ID_AUTOPILOT1,
+        &response_msg,
+        &version_struct
+    );
 
-static void recv_thread(pipe_fd_t recvpipe_fd)
+    uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
+    auto len = mavlink_msg_to_send_buffer(buffer, &response_msg);
+
+    auto ret = sendto(gcs.socket_fd, buffer, len, 0, (struct sockaddr*)(&(gcs.addr)), gcs.addr_len);
+    if (ret != len) {
+        logger->error("Autopilot version message error: {}.", strerror(errno));
+    } else {
+        logger->info("Sent Autopilot version!");
+    }
+}
+
+static void recv_thread()
 {
     char buffer[UDP_RECV_BUF_SIZE]; // enough for MTU 1500 bytes
 
@@ -26,7 +94,7 @@ static void recv_thread(pipe_fd_t recvpipe_fd)
             break;
         } else if (ret == 0) {
             // peer has done an orderly shutdown
-            logger->info("Peer has done an orderly shutdown");
+            logger->info("Peer has done an orderly shutdown.");
             break;
         }
 
@@ -40,32 +108,21 @@ static void recv_thread(pipe_fd_t recvpipe_fd)
                 handle_mavlink(message);
             }
         }
-        logger->debug("Socket -> recvpipe: {} bytes", ret);
-        ret = write(recvpipe_fd, buffer, ret);
-        if (ret < 0) {
-            logger->error("Error while writing message. {}", strerror(errno));
-        }
     }
 }
 
 static void heartbeat_thread()
 {
-
     mavlink_message_t message;
-
-    const uint8_t system_id = 42;
-    const uint8_t base_mode = 0;
-    const uint8_t custom_mode = 0;
-
     mavlink_msg_heartbeat_pack_chan(
-        system_id,
-        MAV_COMP_ID_PERIPHERAL,
+        1,  // System ID
+        MAV_COMP_ID_AUTOPILOT1,
         MAVLINK_COMM_0,
         &message,
         MAV_TYPE_GENERIC,
         MAV_AUTOPILOT_GENERIC,
-        base_mode,
-        custom_mode,
+        0,
+        0,
         MAV_STATE_STANDBY);
 
     uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
@@ -75,7 +132,7 @@ static void heartbeat_thread()
 
         int ret = sendto(gcs.socket_fd, buffer, len, 0, (struct sockaddr*)(&(gcs.addr)), gcs.addr_len);
         if (ret != len) {
-            logger->error("Heartbeat sendto error: {}", strerror(errno));
+            logger->error("Heartbeat sendto error: {}.", strerror(errno));
         } else {
             logger->debug("Sent Heartbeat!");
         }
@@ -88,21 +145,41 @@ static void handle_mavlink(mavlink_message_t& message)
 {
     switch (message.msgid) {
     case MAVLINK_MSG_ID_HEARTBEAT:
-        handle_heartbeat(&message);
+        handle_heartbeat(message);
+        break;
+    case MAVLINK_MSG_ID_COMMAND_LONG:
+        mavlink_command_long_t cmd_long;
+        mavlink_msg_command_long_decode(&message, &cmd_long);
+        
+        switch (cmd_long.command) {
+        case MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES:
+            logger->debug("Got autopilot capabilities request.");
+            handle_request_autopilot_capabilities(cmd_long);
+            break;
+        default:
+            logger->warn("Unhandled command {} from {}/{}.", (int) cmd_long.command, message.sysid, message.compid);
+            break;
+        }
         break;
     default:
-        logger->debug("Received message {} from {}/{}", (int) message.msgid, message.sysid, message.compid);
+        logger->warn("Unhandled message {} from {}/{}.", (int) message.msgid, message.sysid, message.compid);
+        
+        logger->warn("Sending unhandled message to recvpipe: {} bytes.", message.len);
+        auto ret = write(recvpipe, message.payload64, message.len);
+        if (ret < 0) {
+            logger->error("Error while writing message to recvpipe. Errno {}.", strerror(errno));
+        }
         break;
     }
 }
 
-err_t udp_server_init(std::shared_ptr<spdlog::logger> logg)
+err_t udp_server_init(std::shared_ptr<spdlog::logger> logg, const pipe_fd_t recvpipe_fd, const pipe_fd_t sendpipe_fd)
 {
     logger = logg;
+    sendpipe = sendpipe_fd;
+    recvpipe = recvpipe_fd;
 
-    init_mavlink_handler(logger);
-
-    socket_fd_t socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
+    auto socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
 
     if (socket_fd < 0) {
         logger->error("socket error: {}", strerror(errno));
@@ -134,9 +211,9 @@ err_t udp_server_init(std::shared_ptr<spdlog::logger> logg)
     return OK;
 }
 
-err_t udp_server_run(pipe_fd_t recvpipe_fd, pipe_fd_t sendpipe_fd)
+err_t udp_server_run()
 {
-    std::thread r_thread(recv_thread, recvpipe_fd);
+    std::thread r_thread(recv_thread);
 
     while (!(gcs.addr_set)) {
         logger->info("Waiting for GCS to connect...");
@@ -152,8 +229,10 @@ err_t udp_server_run(pipe_fd_t recvpipe_fd, pipe_fd_t sendpipe_fd)
     mavlink_message_t message;
     mavlink_status_t status;
 
+    message.msgid = 0;
+
     while (true) {
-        ret = read(sendpipe_fd, &buffer, sizeof(buffer));
+        ret = read(sendpipe, &buffer, sizeof(buffer));
 
         if (ret == 0) {
             logger->error("No writing process on sendpipe. Exiting.");
@@ -162,26 +241,25 @@ err_t udp_server_run(pipe_fd_t recvpipe_fd, pipe_fd_t sendpipe_fd)
         else if (ret < 0)
             logger->error("Error while reading message. {}", strerror(errno));
         else {
-            /*
+            
             for (int i = 0; i < ret; ++i) {
-                if (mavlink_parse_char(MAVLINK_COMM_0, buffer[i], &message, &status) == 1) {
-                    logger->debug("sendpipe -> socket: mavlink message id={},", (int) message.msgid);
+                if (mavlink_parse_char(MAVLINK_COMM_0, buffer[i], &message, &status)) {
+                    logger->debug("sendpipe -> socket: mavlink message id={}, bytes: {}", (int) message.msgid, ret);
                 }
             }
-            */
-            logger->debug("sendpipe -> socket: {} bytes", ret);
+            
             ret = sendto(gcs.socket_fd, buffer, ret, 0, (struct sockaddr*)(&(gcs.addr)), gcs.addr_len);
             if (ret < 0) {
-                logger->error("Sending mavlink message to GCS sendto error {}", strerror(errno));
+                logger->error("Sending mavlink message to GCS sendto error {}.", strerror(errno));
             }
 
         }
     }
 
-    logger->debug("Closing recv_thread");
+    logger->debug("Closing recv_thread.");
     recv_thread_running = false;
 
-    logger->debug("Closing socket");
+    logger->debug("Closing socket.");
     close(gcs.socket_fd);
 
     return ERR;