Tüm eğitimler
TEKNİK REHBERGÖMÜLÜ LİNUXDAĞITIK SİSTEMLER2026

DDS
Dağıtık Veri Servisi Middleware

OMG DDS standardının gömülü sistemlerde kullanımı, Cyclone DDS ve Fast-DDS ile yayın/abonelik haberleşmesi, QoS politikaları ve gerçek zamanlı veri dağıtımı.

00 DDS Neden? Broker-less Mimari

MQTT ve AMQP gibi broker tabanlı sistemler tek nokta hata riski taşır ve gecikme ekler. DDS broker gerektirmeyen, şema-farkında, gerçek zamanlı bir yayın/abonelik middleware'idir.

Broker Tabanlı Mimarinin Sınırları

Tek nokta hatası (SPOF)Broker çökerse tüm iletişim durur; özerk araç veya tıbbi sistemlerde kabul edilemez
Ekstra gecikmeYayıncı - broker - abone zinciri minimum 2 ağ sıçraması ekler; gerçek zamanlı sistemlerde kritik
Ölçeklenme darboğazıTüm trafik merkezi broker üzerinden geçer; yüksek frekanslı sensör verisi için yetersiz
Şema farkındalığı yokMQTT mesaj gövdesi ham bayt; tip uyumsuzluğu çalışma zamanında ortaya çıkar
Kısıtlı QoSMQTT QoS 0/1/2 yeterli değil; tarihsel veri, deadline, bağımsız kuyruk derinliği yönetilemiyor

DDS'in Kullanıldığı Alanlar

AlanKullanım ÖrneğiStandart
Otonom araçSensör füzyonu, aktüatör komutları, araç durumuAUTOSAR Adaptive
Robot yazılımıROS 2 middleware katmanı (rmw)OMG DDS
Savunma / havacılıkUçuş veri bus alternatifi (FACE standardı)OMG DDS-FACE
Tıbbi cihazGerçek zamanlı hasta verisi dağıtımıOMG DDS
Endüstriyel SCADAPLC ile HMI ve tarihsel veri tabanıIEC 62541 + DDS
Deniz sistemleriSTANAG 4586 UAV kontrol sistemiSTANAG + DDS

Topoloji Karşılaştırması

[MQTT]    Yayinci --> Broker --> Abone
          (2 sicrama, merkezi, SPOF)

[DDS]     Yayinci <--RTPS/UDP--> Abone
          (dogrudan, dagitik, broker yok)

[gRPC]    Istemci --> Sunucu
          (istek/yanit, noktadan noktaya)

[DDS]     DataWriter ---(kesif)---> DataReader
          (veri merkezli, cok-cok)
  

01 DDS Kavramları ve Hiyerarşi

DDS varlık hiyerarşisi Domain, Participant, Publisher/Subscriber, DataWriter/DataReader zincirinden oluşur. Topic ortak veri sözleşmesini tanımlar.

Temel Varlık Hiyerarşisi

Domain (sayisal kimlik: 0, 1, ...)
  |
  +-- DomainParticipant (surec / makine temsili)
       |
       +-- Publisher
       |    +-- DataWriter (Topic'e veri yazar)
       |
       +-- Subscriber
       |    +-- DataReader (Topic'ten veri okur)
       |
       +-- Topic (ad + tip + QoS)
  

Domain ve Katılımcı

Domain, DDS iletişimini mantıksal olarak yalıtır. Farklı domain kimliklerine sahip katılımcılar birbirini göremez. Bu özellik alt sistemlerin birbirinden izole edilmesini sağlar:

Domain 0Varsayılan üretim domain'i; tüm düğümler varsayılan olarak burada
Domain 100Test ve geliştirme ortamı; üretim ile çakışmaz
Domain 200Güvenlik kritik alt sistem; izole edilmiş erişim

Topic ve IDL Veri Tipi Tanımı

Topic, konuya özgü veri yapısını (IDL ile tanımlanan) ve adını birleştirir. IDL (Interface Definition Language) dil bağımsız veri tanımı sağlar:

// sensors.idl
module Sensors {
  struct Temperature {
    @key string sensor_id;   // @key: katilimci kimligi (instance)
    float        value;      // Celsius cinsinden sicaklik
    long         timestamp;  // Unix millisaniye
    boolean      alarmed;    // Esik asimi bayragi
  };

  struct IMUData {
    @key string unit_id;
    float accel_x;
    float accel_y;
    float accel_z;
    float gyro_x;
    float gyro_y;
    float gyro_z;
  };
};

IDL'den C Kodu Üretimi (fastddsgen)

# eProsima Fast-DDS ile IDL derleyici
fastddsgen -cs sensors.idl

# Uretilen dosyalar:
# sensors.h             -- struct tanimlari
# sensorsPubSubTypes.h  -- serializasyon/deserializasyon
# sensorsCdrAux.h       -- CDR (Common Data Representation)

# Cyclone DDS ile IDL derleyici
idlc -l c sensors.idl
# Uretilen: sensors.h, sensors.c

DataWriter ve DataReader İlişkisi

VarlıkGörevi
DomainParticipantDomain'e giriş noktası; keşif (discovery) başlatır
TopicVeri adı + tipi + QoS tanımı; paylaşılan sözleşme
PublisherDataWriter'ların konteyner nesnesi
DataWriterTopic'e veri yazar; yayıncı rolü
SubscriberDataReader'ların konteyner nesnesi
DataReaderTopic'ten veri okur; abone rolü

02 QoS Politikaları

QoS (Quality of Service) politikaları veri teslimat davranışını kontrol eder. DataWriter ve DataReader QoS'larının uyumlu olması eşleşme için zorunludur; uyumsuzluk sessiz eşleşme başarısızlığına yol açar.

Temel QoS Politikaları

PolitikaDeğerlerEtkisiUyum Kuralı
RELIABILITYBEST_EFFORT / RELIABLEKayıp veri toleransıDW >= DR gerekir
DURABILITYVOLATILE / TRANSIENT_LOCAL / TRANSIENTYeni abonelere geçmiş veriDW >= DR gerekir
HISTORYKEEP_LAST(n) / KEEP_ALLKuyruk derinliğiBağımsız
DEADLINEperiod = DurationYeni veri beklenen maksimum aralıkDW <= DR gerekir
LIVELINESSAUTOMATIC / MANUALYayıncı canlılık teyidiDW >= DR gerekir
LIFESPANDurationVeri geçerlilik süresi; eskiyen veri atılırBağımsız
RESOURCE_LIMITSmax_samples, max_instancesBellek tüketim sınırıBağımsız

DURABILITY Politikası Davranışı

VOLATILE:
  [W yazar] [R baginlir] --> yalnizca baginlanmadan sonraki veri alinir
  Sensor verisi, canli kontrol komutu icin uygundur

TRANSIENT_LOCAL:
  [W yazar] [R baginlir] --> HISTORY derinligi kadar gecmis alinir
  Konfigurasyonu gec gelen abone icin uygundur

TRANSIENT:
  [W kapanir] [W tekrar acar] --> veri ayri servis tarafindan korunur
  Sistem yeniden baslatmalarinda veri kaybi olmaz
  

Gömülü Sistem için Önerilen QoS Kombinasyonları

Sensör verisi (yüksek frekans)BEST_EFFORT + VOLATILE + KEEP_LAST(1): düşük yük, hafıza dostu
Kontrol komutu (güvenilir)RELIABLE + VOLATILE + KEEP_LAST(10): kayıpsız iletim
Konfigürasyon verisiRELIABLE + TRANSIENT_LOCAL + KEEP_LAST(1): yeni düğümler güncel bilgi alır
Alarm bildirimiRELIABLE + TRANSIENT_LOCAL + KEEP_ALL: hiçbir alarm kaçırılmaz

03 Cyclone DDS Kurulumu

Eclipse Cyclone DDS, OMG DDS standardının hafif ve hızlı C/C++ implementasyonudur. ROS 2 ile birlikte çalışır ve Yocto meta-ros katmanıyla gömülü sistemlere entegre edilir.

Ubuntu / Debian Kurulumu

# Paket yoneticisi ile
sudo apt install ros-humble-cyclonedds   # ROS 2 ile
# veya bagimsiz:
sudo apt install cyclonedds-dev

# Kaynak koddan derleme
git clone https://github.com/eclipse-cyclonedds/cyclonedds.git
cd cyclonedds
mkdir build && cd build
cmake .. \
    -DCMAKE_BUILD_TYPE=Release \
    -DBUILD_EXAMPLES=ON \
    -DENABLE_SSL=ON
make -j$(nproc)
sudo make install

CMake Entegrasyonu

cmake_minimum_required(VERSION 3.16)
project(dds_sensor_app C)

find_package(CycloneDDS REQUIRED)

# IDL dosyasindan kod uret
idlc_generate(TARGET sensors_idl
              FILES sensors.idl
              WARNINGS no-implicit-extensibility)

# Uygulamayi derle
add_executable(sensor_publisher publisher.c)
target_link_libraries(sensor_publisher
    sensors_idl
    CycloneDDS::ddsc)

add_executable(sensor_subscriber subscriber.c)
target_link_libraries(sensor_subscriber
    sensors_idl
    CycloneDDS::ddsc)

Yocto Meta-ROS ile Gömülü Linux

# meta-ros katmanini ekle
git clone https://github.com/ros/meta-ros.git \
    /path/to/poky/meta-ros

# bblayers.conf
BBLAYERS += " \
  /path/to/poky/meta-ros/meta-ros2 \
  /path/to/poky/meta-ros/meta-ros2-humble \
"

# local.conf -- minimal DDS imaji
IMAGE_INSTALL:append = " \
    ros-humble-cyclonedds \
    ros-humble-rmw-cyclonedds-cpp \
"

# Sadece Cyclone DDS (ROS 2 olmadan)
IMAGE_INSTALL:append = " cyclonedds"

Cross-Compilation (ARM64)

# toolchain-aarch64.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER   aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
set(CMAKE_SYSROOT /usr/aarch64-linux-gnu)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

# Cross-compile komutu
cmake .. \
    -DCMAKE_TOOLCHAIN_FILE=toolchain-aarch64.cmake \
    -DCMAKE_BUILD_TYPE=Release \
    -DBUILD_SHARED_LIBS=ON \
    -DENABLE_SSL=OFF \
    -DBUILD_EXAMPLES=OFF

make -j$(nproc)

04 İlk Yayın / Abonelik Uygulaması

Cyclone DDS C API'si ile tam işlevsel yayın/abonelik uygulaması yazılır. Participant, topic, writer ve reader oluşturma adımları gösterilir.

Yayıncı (Publisher) — Tam C Örneği

#include "dds/dds.h"
#include "sensors.h"   /* IDL'den uretildi */
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    dds_entity_t participant, topic, writer;
    dds_qos_t   *qos;
    dds_return_t rc;
    Sensors_Temperature msg;

    /* 1. Domain Participant olustur (domain 0) */
    participant = dds_create_participant(0, NULL, NULL);
    if (participant < 0) {
        fprintf(stderr, "Participant olusturulamadi: %s\n",
                dds_strretcode(-participant));
        return 1;
    }

    /* 2. Topic olustur */
    topic = dds_create_topic(
        participant,
        &Sensors_Temperature_desc,
        "SensorTemperature",
        NULL, NULL);
    if (topic < 0) {
        fprintf(stderr, "Topic olusturulamadi\n");
        return 1;
    }

    /* 3. QoS ayarla -- guvenilir, gecici yerel */
    qos = dds_create_qos();
    dds_qset_reliability(qos,
        DDS_RELIABILITY_RELIABLE,
        DDS_MSECS(1000));
    dds_qset_durability(qos,
        DDS_DURABILITY_TRANSIENT_LOCAL);
    dds_qset_history(qos,
        DDS_HISTORY_KEEP_LAST, 10);

    /* 4. DataWriter olustur */
    writer = dds_create_writer(participant, topic, qos, NULL);
    dds_delete_qos(qos);
    if (writer < 0) {
        fprintf(stderr, "Writer olusturulamadi\n");
        return 1;
    }

    printf("Yayinci baslatildi. Veri gonderiliyor...\n");

    /* 5. Veri gonder */
    memset(&msg, 0, sizeof(msg));
    for (int i = 0; i < 20; i++) {
        msg.sensor_id = "rpi4-sensor-01";
        msg.value     = 20.0f + (float)i * 0.5f;
        msg.timestamp = (long)(i * 1000);
        msg.alarmed   = (msg.value > 27.0f);

        rc = dds_write(writer, &msg);
        if (rc != DDS_RETCODE_OK) {
            fprintf(stderr, "Yazma hatasi: %s\n",
                    dds_strretcode(-rc));
        } else {
            printf("[%d] Gonderildi: %.1f C%s\n",
                   i, msg.value,
                   msg.alarmed ? " [ALARM]" : "");
        }
        sleep(1);
    }

    /* 6. Temizlik */
    dds_delete(participant);
    return 0;
}

Abone (Subscriber) — Tam C Örneği

#include "dds/dds.h"
#include "sensors.h"
#include <stdio.h>
#include <string.h>

/* Listener callback: veri hazir oldugunda cagirilir */
static void
on_data_available(dds_entity_t reader, void *arg)
{
    Sensors_Temperature msg;
    void *samples[1] = { &msg };
    dds_sample_info_t info[1];
    int32_t n;

    (void)arg;
    memset(&msg, 0, sizeof(msg));

    n = dds_take(reader, samples, info, 1, 1);
    if (n < 0) {
        fprintf(stderr, "Okuma hatasi: %s\n",
                dds_strretcode(-n));
        return;
    }

    if (n > 0 && info[0].valid_data) {
        printf("Alindi [%s]: %.1f C, alarm=%s\n",
               msg.sensor_id,
               msg.value,
               msg.alarmed ? "EVET" : "hayir");
    }
}

int main(void)
{
    dds_entity_t   participant, topic, subscriber, reader;
    dds_listener_t *listener;
    dds_qos_t      *qos;

    participant = dds_create_participant(0, NULL, NULL);

    topic = dds_create_topic(
        participant,
        &Sensors_Temperature_desc,
        "SensorTemperature",
        NULL, NULL);

    qos = dds_create_qos();
    dds_qset_reliability(qos,
        DDS_RELIABILITY_RELIABLE,
        DDS_MSECS(1000));
    dds_qset_durability(qos,
        DDS_DURABILITY_TRANSIENT_LOCAL);

    /* Listener ile asenkron okuma */
    listener = dds_create_listener(NULL);
    dds_lset_data_available(listener, on_data_available);

    reader = dds_create_reader(
        participant, topic, qos, listener);
    dds_delete_qos(qos);

    printf("Abone bekleniyor... Ctrl+C ile dur.\n");

    /* Mesaj alindi bildirimi bekle */
    uint32_t mask = DDS_DATA_AVAILABLE_STATUS;
    while (1) {
        dds_waitset_wait(
            dds_create_waitset(participant),
            NULL, 0, DDS_INFINITY);
    }

    dds_delete(participant);
    return 0;
}

05 Güvenilir İletim

RELIABLE QoS, HEARTBEAT/ACKNACK mekanizması ile kayıpsız veri teslimatını garanti eder. Sample kaybı tespiti ve deadline miss bildirimleri uygulamada ele alınmalıdır.

RELIABLE İletim Akışı

DataWriter                     DataReader
   |                                |
   |-- DATA (seq=1) --------------->|  Alindi
   |-- DATA (seq=2) --------------->|  Alindi
   |-- DATA (seq=3) -------X        |  KAYIP
   |-- DATA (seq=4) --------------->|
   |                                |
   |<-- HEARTBEAT talep (seq 1-4) --|
   |                                |
   |-- GAP (seq=3 eksik) ---------->|
   veya
   |-- DATA (seq=3) tekrar --------->|  Yeniden gonderildi
   |                                |
   |<-- ACKNACK (seq 1-4 OK) -------|  Tum alinanlarin teyidi
  

Sample Kaybı Dinleyicisi

#include "dds/dds.h"

/* Sample kaybi callback'i */
static void
on_sample_lost(dds_entity_t reader,
               const dds_sample_lost_status_t *status,
               void *arg)
{
    printf("SAMPLE KAYBI: toplam=%d, son_artas=%d\n",
           status->total_count,
           status->total_count_change);
}

/* Deadline miss callback'i */
static void
on_requested_deadline_missed(
    dds_entity_t reader,
    const dds_requested_deadline_missed_status_t *status,
    void *arg)
{
    printf("DEADLINE GECILDI: toplam=%d\n",
           status->total_count);
    /* Yayincinin olup olmadigini kontrol et */
}

/* QoS uyumsuzlugu callback'i */
static void
on_requested_incompatible_qos(
    dds_entity_t reader,
    const dds_requested_incompatible_qos_status_t *status,
    void *arg)
{
    printf("QoS UYUMSUZLUGU: politika kimlik=%d\n",
           status->last_policy_id);
    /* 11 = RELIABILITY, 7 = DURABILITY */
}

/* Listener kaydi */
void setup_reader_listeners(dds_entity_t reader)
{
    dds_listener_t *l = dds_create_listener(NULL);
    dds_lset_sample_lost(l, on_sample_lost);
    dds_lset_requested_deadline_missed(
        l, on_requested_deadline_missed);
    dds_lset_requested_incompatible_qos(
        l, on_requested_incompatible_qos);
    dds_set_listener(reader, l);
    dds_delete_listener(l);
}

Deadline QoS Yapılandırması

/* Writer tarafinda deadline: her 100 ms'de en az 1 ornek */
dds_qos_t *wqos = dds_create_qos();
dds_qset_deadline(wqos, DDS_MSECS(100));
dds_qset_reliability(wqos,
    DDS_RELIABILITY_RELIABLE, DDS_MSECS(500));

dds_entity_t writer = dds_create_writer(
    participant, topic, wqos, NULL);

/* Reader tarafinda deadline: 100 ms gecerse bildir */
dds_qos_t *rqos = dds_create_qos();
dds_qset_deadline(rqos, DDS_MSECS(100));
dds_qset_reliability(rqos,
    DDS_RELIABILITY_RELIABLE, DDS_MSECS(500));

dds_entity_t reader = dds_create_reader(
    participant, topic, rqos, listener);

06 Gömülü Kaynak Yönetimi

Bellek kısıtlı gömülü Linux sistemlerinde DDS ayak izini küçültmek için BEST_EFFORT modu, küçük HISTORY derinlikleri ve statik discovery yapılandırması kullanılır.

BEST_EFFORT Modu — Düşük Yük

/* Yuksek frekanslı sensör verisi için BEST_EFFORT */
dds_qos_t *qos = dds_create_qos();

/* BEST_EFFORT: kayip kabul edilebilir, ACK/NACK mekanizmasi yok */
dds_qset_reliability(qos,
    DDS_RELIABILITY_BEST_EFFORT, 0);

/* KEEP_LAST(1): yalnizca en son deger tutulur */
dds_qset_history(qos, DDS_HISTORY_KEEP_LAST, 1);

/* VOLATILE: gecmis veri gonderilmez */
dds_qset_durability(qos, DDS_DURABILITY_VOLATILE);

/* Kaynak limitleri: bellek tasarrufu */
dds_qset_resource_limits(qos,
    4,   /* max_samples */
    2,   /* max_instances */
    2);  /* max_samples_per_instance */

dds_entity_t writer = dds_create_writer(
    participant, topic, qos, NULL);

Statik Discovery (Dinamik Multicast Yok)

# cyclonedds.xml -- statik katilimci yapılandırmasi
# Dinamik SPDP multicast yerine bilinen adresler kullan
<CycloneDDS xmlns="https://cdds.io/config">
  <Domain id="any">
    <General>
      <Interfaces>
        <NetworkInterface name="eth0" />
      </Interfaces>
    </General>
    <Discovery>
      <!-- Multicast devre disi -- bilinen adresler kullan -->
      <Peers>
        <Peer address="192.168.1.10"/>
        <Peer address="192.168.1.20"/>
      </Peers>
      <MaxAutoParticipantIndex>5</MaxAutoParticipantIndex>
    </Discovery>
    <Internal>
      <!-- Fragment boyutu: kucuk paketler icin -->
      <FragmentSize>1344</FragmentSize>
      <!-- Gonlarim buffer boyutu azalt -->
      <SendRevisionPeriod>0 s</SendRevisionPeriod>
    </Internal>
  </Domain>
</CycloneDDS>

# Ortam degiskeni ile yukle
export CYCLONEDDS_URI=file:///etc/cyclonedds.xml

Bellek Kullanımı — Kıyaslama

Kısıtlı ARM Cortex-A5/A7
YapılandırmaRAM KullanımıUygun Senaryo
RELIABLE + KEEP_ALL + dinamik discovery~15-30 MBGüçlü gömülü Linux (i.MX8)
RELIABLE + KEEP_LAST(10) + statik discovery~5-10 MBRaspberry Pi, BeagleBone
BEST_EFFORT + KEEP_LAST(1) + statik discovery~2-4 MB
Micro XRCE-DDS (MCU tarafı)<64 KBSTM32, ESP32, FreeRTOS

07 DDS-XRCE ile MCU Entegrasyonu

Micro XRCE-DDS, kaynak kısıtlı mikrodenetleyicileri (STM32, ESP32, FreeRTOS) DDS ağına bağlar. XRCE-DDS protokolü bir Agent aracısı üzerinden çalışır; MCU tarafında çalışan istemci, agent üzerinden tam DDS varlıkları oluşturur.

XRCE-DDS Mimarisi

[MCU -- FreeRTOS / Zephyr]         [Linux Agent]      [DDS Agi]
 micro-XRCE istemci                XRCE-DDS Agent
   |                                    |                  |
   |---(UART / UDP / SPI)--->           |                  |
   |   XRCE Protocol                    |---(Cyclone DDS)-->|
   |<-----------------------------------|<------------------|
   |   komut yaniti / veri              |                  |
  

Linux'ta XRCE-DDS Agent Kurulumu

git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
cd Micro-XRCE-DDS-Agent
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
sudo make install

# UDP Agent (MCU UDP 2018 portuna baglanir)
MicroXRCEAgent udp4 --port 2018

# UART Agent (STM32 seri port, 115200 baud)
MicroXRCEAgent serial --dev /dev/ttyUSB0 -b 115200

# CAN-FD Agent (otomotiv)
MicroXRCEAgent canfd --dev can0

MCU Tarafı — FreeRTOS + Micro-XRCE İstemci

/* STM32 / FreeRTOS -- Micro-XRCE istemci ornegi */
#include <uxr/client/client.h>
#include <ucdr/microcdr.h>

#define AGENT_IP   "192.168.1.100"
#define AGENT_PORT 2018

void dds_sensor_task(void *pvParameters)
{
    uxrUDPTransport transport;
    uxrUDPPlatform  platform;

    /* Agent baglantisi */
    uxr_init_udp_transport(&transport, &platform,
                           UXR_IPv4, AGENT_IP, AGENT_PORT);

    /* Oturum baslatma */
    uxrSession session;
    uxr_init_session(&session, &transport.comm,
                     0xAAAABBBB /* oturum ID */);
    if (!uxr_create_session(&session)) {
        /* Baglanti hatasi */
        vTaskDelete(NULL);
        return;
    }

    /* Guvenilir cikis stream */
    uint8_t output_buf[512];
    uxrStreamId rel_out = uxr_create_output_reliable_stream(
        &session, output_buf, sizeof(output_buf), 1);

    /* Participant olustur (XML ile) */
    uxrObjectId pid = uxr_object_id(1, UXR_PARTICIPANT_ID);
    uxr_buffer_create_participant_xml(
        &session, rel_out, pid, 0,
        "<dds><participant><rtps>"
        "<name>mcu_participant</name>"
        "</rtps></participant></dds>",
        UXR_REPLACE);

    /* Topic, Publisher, DataWriter olustur */
    uxrObjectId tid = uxr_object_id(1, UXR_TOPIC_ID);
    uxr_buffer_create_topic_xml(
        &session, rel_out, tid, pid, 0,
        "<dds><topic>"
        "<name>SensorTemperature</name>"
        "<dataType>Sensors::Temperature</dataType>"
        "</topic></dds>",
        UXR_REPLACE);

    uxrObjectId pub_id = uxr_object_id(1, UXR_PUBLISHER_ID);
    uxr_buffer_create_publisher_xml(
        &session, rel_out, pub_id, pid, 0,
        "<publisher/>", UXR_REPLACE);

    uxrObjectId dw_id = uxr_object_id(1, UXR_DATAWRITER_ID);
    uxr_buffer_create_datawriter_xml(
        &session, rel_out, dw_id, pub_id, 0,
        "<datawriter>"
        "<topic><kind>NO_KEY</kind></topic>"
        "</datawriter>",
        UXR_REPLACE);

    uxr_run_session_time(&session, 500);

    /* Veri yayini dongusu */
    uint8_t topic_buf[64];
    while (1) {
        float temp = read_adc_temperature();

        ucdrBuffer ub;
        ucdr_init_buffer(&ub, topic_buf, sizeof(topic_buf));
        ucdr_serialize_string(&ub, "stm32-sensor-01");
        ucdr_serialize_float(&ub, temp);
        ucdr_serialize_int32_t(&ub, xTaskGetTickCount());
        ucdr_serialize_bool(&ub, temp > 75.0f);

        uxr_prepare_output_stream(
            &session, rel_out, dw_id,
            &ub, ucdr_buffer_length(&ub));
        uxr_run_session_time(&session, 100);

        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

08 Hata Ayıklama

Cyclone ddsperf ile performans ölçümü yapılır; OpenDDS Monitor veya Fast-DDS Monitor ile varlıklar izlenir; Wireshark RTPS dissector ile ağ paketleri analiz edilir.

ddsperf ile Performans Ölçümü

# Cyclone DDS ile birlikte gelen performans araci
# Gecikme olcumu (publisher <--> subscriber)
ddsperf pub &
ddsperf sub

# Verim testi (throughput)
ddsperf --size 1024 --duration 30 pub &
ddsperf --size 1024 sub

# Ornek cikti:
# Round-trip latency: avg=45 us, min=12 us, max=200 us
# Throughput: 850 MB/s (loopback, SHM transport)

# Uzak makine arasi gecikme
ddsperf --peer 192.168.1.20 pub &
ddsperf sub
# Ortalama gecikme: ~200 us (UDP, LAN)

Wireshark RTPS Dissector

# Wireshark ile RTPS trafigi yakalama
tcpdump -i eth0 -w rtps.pcap udp

# Wireshark filtreleri:
# Tum RTPS:
rtps

# Yalnizca DATA alt mesajlari:
rtps.sm.id == 0x15

# SPDP kesif mesajlari (multicast, port 7400):
udp.dstport == 7400

# Belirli GUID ile filtrele:
rtps.guid_prefix == 01:0f:1a:2b:3c:4d:5e:6f:7a:8b:9c:0d

# Yalnizca HEARTBEAT mesajlari:
rtps.sm.id == 0x07

# RTPS paket boyutuna gore siralama Wireshark'ta:
# Statistics -> Protocol Hierarchy -> RTPS

Cyclone DDS Log Seviyeleri

# cyclonedds.xml ile log yapilandirmasi
<CycloneDDS>
  <Domain>
    <Tracing>
      <!-- Seviyeler: FINEST, FINER, FINE, CONFIG,
                      INFO, WARNING, SEVERE -->
      <Verbosity>CONFIG</Verbosity>
      <OutputFile>/var/log/cyclonedds.log</OutputFile>
    </Tracing>
  </Domain>
</CycloneDDS>

# Ortam degiskeni ile hizli degistirme
export CYCLONEDDS_URI="<CycloneDDS><Domain><Tracing>\
<Verbosity>FINE</Verbosity></Tracing></Domain></CycloneDDS>"

Yaygın Sorunlar ve Çözümleri

SorunOlası NedenÇözüm
DataWriter/DataReader eşleşmiyorQoS uyumsuzluğu (RELIABILITY veya DURABILITY)on_requested_incompatible_qos callback'ini incele, politika ID'sini bul
Keşif yok — multicast engeliGüvenlik duvarı UDP 7400 portunu engelliyorsudo ufw allow 7400/udp; veya statik peers kullan
Yüksek gecikme (aynı makine)SHM transport devre dışıcyclonedds.xml'de SharedMemory transport etkinleştir
Sample kaybı (RELIABLE mod)HISTORY derinliği çok az, gönderici hızı fazlaKEEP_LAST derinliğini artır veya RESOURCE_LIMITS ayarla
Yüksek CPU (keşif)SPDP çok sık gönderiliyorDiscovery/LeaseDuration artır; statik discovery'e geç
XRCE-DDS agent bağlantısı kurulamıyorFirewall UDP 2018 engelliyoriptables -I INPUT -p udp --dport 2018 -j ACCEPT

Fast-DDS Monitor ile Görsel İzleme

# Fast-DDS Monitor kurulumu (Qt5 gerektirir)
git clone https://github.com/eProsima/Fast-DDS-monitor.git
cd Fast-DDS-monitor && mkdir build && cd build
cmake .. && make -j$(nproc)

./bin/fastdds_monitor

# Monitorde gorulebilecekler:
# - Domain katilimcilari listesi
# - Topic listesi ve DataWriter/DataReader ciftleri
# - QoS bilgisi ve uyumsuzluk uyarilari
# - GUID ve locator (IP:port) bilgisi
# - Gercek zamanli mesaj sayaci ve verim grafigi

# Fast-DDS discovery CLI ile hizli kontrol
fastdds discovery -d 0 -v
# Cikti: tum katilimci GUID'leri, topic'ler, QoS ayarlari