Software Defined Radio — как это работает? Часть 7

в 18:38, , рубрики: lora, LoRaWAN, radio, rn2483, SDR, гаджеты, Научно-популярное, Программирование, Разработка систем связи, Электроника для начинающих

Привет.

В предыдущей части про передачу в GNU Radio был задан вопрос о том, можно ли декодировать протокол LoRa (передача данных для устройств с низким энергопотреблением) с помощью SDR. Мне эта тема показалась интересной, тем более что и сам сигнал у LoRa довольно-таки необычный — так называемая Chirp Spread Spectrum modulation, или «модуляция чирпами».

Software Defined Radio — как это работает? Часть 7 - 1

Как это работает, продолжение под катом.

Кстати, дословный перевод Chirp modulation звучал бы как «модуляция чириканием», но это звучит уж совсем сюрреалистично, так что лучше оставлю простое слово «чирп».

Модуляция LoRa

Как было сказано выше, при передаче LoRa используется способ модуляции при помощи «чирпов», кстати запатентованный компанией Semtech. Если кто хочет подробностей реализации с формулами, можно почитать PDF на сайте semtech или здесь, ну а если совсем грубо, то один «чирп» — это одно изменение частоты, такими изменениями и кодируется битовый поток, как показано на картинке выше. Параметрами сигнала в LoRa являются SF (spreading factor — по сути, длительность одного «чирпа») и bandwidth — ширина полосы передачи. Параметр SF задается предопределенными значениями SF7 — SF12, где 7 самый быстрый, а 12 — самый медленный режим (для примера можно посмотреть картинку с иллюстрацией разных скоростей «чирпования» с researchgate).

Очевидно, чем меньше длина «чирпа» и чем шире полоса, тем больше можно получить скорость передачи. Все это связано примерно такой таблицей:

Software Defined Radio — как это работает? Часть 7 - 2

С точки зрения дальности и помехозащищенности выгодно передавать медленно и печально, но при этом мы во-первых, теряем в скорости, во-вторых, проигрываем во времени, а по правилам LoRa, устройство может передавать не более 1% времени, чтобы не мешать другим устройствам. Так что выбор оптимальной скорости передачи для малопотребляющих устройств задача тоже не простая.

С общим принципом надеюсь, ясно, теперь перейдем к SDR и декодированию.

Железо

Для тестирования я использовал LoRa Click RN2483 и Arduino M0, просто потому что они были в наличии.

Software Defined Radio — как это работает? Часть 7 - 3

Это достаточно удобный форм-фактор для прототипирования, т.к. позволяет легко заменить плату одну на другую без пайки (в этом формате, называемом MikroBUS доступно много разной периферии).

Код в черновом варианте, не претендующий на production, добавлен под спойлер. В качестве теста передается значение «1234».

rn2483_tx.ino

// RN2483 Modem and LoRa Click test TX. Tested with Arduino M0

int reset = A2;
int rts = 9; // CS
int cts = 3; // INT

// the setup routine runs once when you press reset:
void setup()
{
    Serial1.begin(57600); // Serial port to radio

    // output LED pin
    pinMode(LED_BUILTIN, OUTPUT);
    
    pinMode(cts, INPUT);
    
    pinMode(rts, OUTPUT);
    digitalWrite(rts, HIGH);

    // Reset rn2483
    pinMode(reset, OUTPUT);
    digitalWrite(reset, LOW);
    delay(100);
    digitalWrite(reset, HIGH);

    delay(100);

    sendCommand("sys get verrn");
    sendCommand("sys get hweuirn");

    sendCommand("mac pausern");
    sendCommand("radio set mod lorarn");
    sendCommand("radio set pwr -3rn"); // the transceiver output power, from -3 to 15
    sendCommand("radio set sf sf8rn"); // sf7..sf12, sf7 the fastest spreading factor but gives the shortest range
    // sendCommand("mac set dr 0rn"); // data rate: 0-4, 4 faster
    sendCommand("radio set freq 869100000rn");
    // sendCommand("radio set afcbw 41.7rn");
    sendCommand("radio set rxbw 125rn");
    // sendCommand("radio set prlen 8rn");
    sendCommand("radio set crc onrn");
    // sendCommand("radio set iqi offrn");
    sendCommand("radio set cr 4/8rn");
    // sendCommand("radio set wdt 60000rn"); // disable for continuous reception
    // sendCommand("radio set sync 12rn");
    sendCommand("radio set bw 125rn");
}

void sendCommand(const char *cmd) 
{
    Serial1.print(cmd);
    String incoming = Serial1.readString();
    // SerialUSB.print(cmd); 
    // SerialUSB.println(incoming); 
}

// the loop routine runs over and over again forever:
void loop()
{
    char data[64] = {0};

    //  hexadecimal value representing the data to be transmitted, from 0 to 255 bytes for LoRa modulation and from 0 to 64 bytes for FSK modulation.
    sprintf(data, "radio tx 1234rn");
    sendCommand(data);

    if (msg_num > 10000) msg_num=0;

    digitalWrite(LED_BUILTIN, 1);
    delay(400);
    digitalWrite(LED_BUILTIN, 0);
    delay(600);
}

Кстати, максимальная заявленная дальность передачи для RN2483 составляет до 15км, на практике, при наличии одноэтажной застройки сигнал пропадает уже за 1км, и может быть не более 100м в городских «муравейниках».

Запускаем модем, и приступаем к декодированию.

Декодирование

В самом GNU Radio поддержки LoRa нет, так что придется использовать сторонние компоненты. Их нашлось всего два, и к сожалению, оба автора не проявили никакой фантазии в названии, и назвали их совершенно одинаково — gr-lora (https://github.com/rpp0/gr-lora и https://github.com/BastilleResearch/gr-lora соответственно). «К сожалению» потому, что в GNU Radio не получится иметь оба компонента сразу, инсталлятор одного компонента затирает файлы другого.

rpp0/gr-lora

Скачать исходники декодера можно с github, сборка стандартна и затруднений не вызывает:

git clone https://github.com/rpp0/gr-lora.git
cd gr-lora
mkdir build
cd build
cmake ..
make && sudo make install && sudo ldconfig

После установки в GNU Radio появляются дополнительные блоки, из которых несложно собрать декодер. В качестве параметров декодера необходимо указать ширину полосы передачи, spreading factor, центральную частоту SDR и частоту приема.

Software Defined Radio — как это работает? Часть 7 - 4

Блоки в GNU Radio стандартизированы, так что можно использовать любой приемник, например RTL-SDR. Я использовал SDRPlay. Для вывода данных в консоль использовалась простая программа на Python.

udp_receive.py

import socket

UDP_IP = "127.0.0.1"
UDP_PORT = 40868

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((UDP_IP, UDP_PORT))
sock.settimeout(0.5)

while True:
    try:
        data, addr = sock.recvfrom(128) # buffer size is 1024 bytes
        print("Msg:", ' '.join('{:02x}'.format(x) for x in data))

    except socket.timeout:
        pass

Результат работы показан на рисунке.

Software Defined Radio — как это работает? Часть 7 - 5

Как можно видеть, в строке есть блоки заголовка и окончания передачи, а в середине мы видим наши данные «1234».

BastilleResearch/gr-lora

Этот модуль примечателен тем, что может работать не только на прием, но и на передачу. Установка примерно такая же: компонент нужно собрать из исходников.

git clone git://github.com/BastilleResearch/gr-lora.git
cd gr-lora
mkdir build
cd build
cmake ..
make && sudo make install && sudo ldconfig

Connection Graph для данного декодера показан на рисунке.

Software Defined Radio — как это работает? Часть 7 - 6

Как можно видеть, блоков тут побольше. Rotator и Polyphase Resampler выделяют нужную частоту и обрезают лишнее, Demodulator преобразует «чирпы» в бинарный код (на выходе получается последовательность вроде «17 00 3e 00 38 00 2f 00 01 00 39 00 2c 00 30 00 c6 00 18 00 7e 00 d5 00 85 00 e9 00 d8 00 67 00 c4 00»), а Decoder формирует окончательный пакет.

К сожалению, нормально оно так и не заработало. Декодирование определенно работает, во время работы модема данные появляются, но принимаемые сообщения не имеют ничего общего с передаваемыми.

Software Defined Radio — как это работает? Часть 7 - 7

Причину я так и не понял, то ли где-то ошибся в настройках, то ли этот декодер совместим только со своим же кодером. Желающие могут проверить самостоятельно с помощью Channel Model.

LoRaWAN

Как можно видеть, выше рассматривался нижний, физический уровень передачи. В более высокоуровневом протоколе LoRaWAN поверх помещается еще один логический уровень — с шифрованием, ключами и прочими сервисами. Желающие посмотреть как устроено кодирование, могут попробовать онлайн-декодер здесь.

Заключение

Как можно видеть, декодирование LoRa средствами SDR вполне возможно. Конечно, реальный gateway делать на базе SDR вряд ли целесообразно — его чувствительность будет хуже чувствительности «настоящих» модемов, которые специально рассчитаны на прием слабых сигналов, и имеют более узкополосные фильтры и LNA. Но для тестирования или исследования это может быть вполне интересно.

Для тех, кто захочет попробовать самостоятельно, исходные grc-файлы GNU Radio под спойлером.

receive1.grc

<?xml version='1.0' encoding='utf-8'?>
<?grc format='1' created='3.7.11'?>
<flow_graph>
  <timestamp>Mon Jun  3 09:39:45 2019</timestamp>
  <block>
    <key>options</key>
    <param>
      <key>author</key>
      <value></value>
    </param>
    <param>
      <key>window_size</key>
      <value></value>
    </param>
    <param>
      <key>category</key>
      <value>[GRC Hier Blocks]</value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>description</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(8, 8)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>generate_options</key>
      <value>wx_gui</value>
    </param>
    <param>
      <key>hier_block_src_path</key>
      <value>.:</value>
    </param>
    <param>
      <key>id</key>
      <value>top_block</value>
    </param>
    <param>
      <key>max_nouts</key>
      <value>0</value>
    </param>
    <param>
      <key>qt_qss_theme</key>
      <value></value>
    </param>
    <param>
      <key>realtime_scheduling</key>
      <value></value>
    </param>
    <param>
      <key>run_command</key>
      <value>{python} -u {filename}</value>
    </param>
    <param>
      <key>run_options</key>
      <value>prompt</value>
    </param>
    <param>
      <key>run</key>
      <value>True</value>
    </param>
    <param>
      <key>thread_safe_setters</key>
      <value></value>
    </param>
    <param>
      <key>title</key>
      <value></value>
    </param>
  </block>
  <block>
    <key>variable</key>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(760, 12)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>bw</value>
    </param>
    <param>
      <key>value</key>
      <value>125000.0</value>
    </param>
  </block>
  <block>
    <key>variable</key>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>1</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(936, 12)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>code_rate</value>
    </param>
    <param>
      <key>value</key>
      <value>4</value>
    </param>
  </block>
  <block>
    <key>variable</key>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>1</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(848, 12)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>header</value>
    </param>
    <param>
      <key>value</key>
      <value>True</value>
    </param>
  </block>
  <block>
    <key>variable</key>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>1</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(680, 12)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>ldr</value>
    </param>
    <param>
      <key>value</key>
      <value>True</value>
    </param>
  </block>
  <block>
    <key>variable</key>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(400, 12)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>offset</value>
    </param>
    <param>
      <key>value</key>
      <value>-100000.0</value>
    </param>
  </block>
  <block>
    <key>variable</key>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(8, 76)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>samp_rate</value>
    </param>
    <param>
      <key>value</key>
      <value>1000000</value>
    </param>
  </block>
  <block>
    <key>variable</key>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>1</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(544, 12)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>spreading_factor</value>
    </param>
    <param>
      <key>value</key>
      <value>8</value>
    </param>
  </block>
  <block>
    <key>blocks_rotator_cc</key>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>1</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(416, 252)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>blocks_rotator_cc_0</value>
    </param>
    <param>
      <key>maxoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>minoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>phase_inc</key>
      <value>(2 * math.pi * offset) / samp_rate</value>
    </param>
  </block>
  <block>
    <key>blocks_socket_pdu</key>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>1</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(944, 452)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>host</key>
      <value>127.0.0.1</value>
    </param>
    <param>
      <key>id</key>
      <value>blocks_socket_pdu_0</value>
    </param>
    <param>
      <key>mtu</key>
      <value>10000</value>
    </param>
    <param>
      <key>maxoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>minoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>port</key>
      <value>40868</value>
    </param>
    <param>
      <key>tcp_no_delay</key>
      <value>False</value>
    </param>
    <param>
      <key>type</key>
      <value>"UDP_CLIENT"</value>
    </param>
  </block>
  <block>
    <key>import</key>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(296, 12)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>import_0</value>
    </param>
    <param>
      <key>import</key>
      <value>import math</value>
    </param>
  </block>
  <block>
    <key>lora_decode</key>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>code_rate</key>
      <value>code_rate</value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>1</value>
    </param>
    <param>
      <key>header</key>
      <value>header</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(648, 452)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>lora_decode_0</value>
    </param>
    <param>
      <key>low_data_rate</key>
      <value>ldr</value>
    </param>
    <param>
      <key>maxoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>minoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>spreading_factor</key>
      <value>spreading_factor</value>
    </param>
  </block>
  <block>
    <key>lora_demod</key>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>1</value>
    </param>
    <param>
      <key>fft_factor</key>
      <value>2</value>
    </param>
    <param>
      <key>beta</key>
      <value>25.0</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(384, 452)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>lora_demod_0</value>
    </param>
    <param>
      <key>low_data_rate</key>
      <value>ldr</value>
    </param>
    <param>
      <key>maxoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>minoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>spreading_factor</key>
      <value>spreading_factor</value>
    </param>
  </block>
  <block>
    <key>pfb_arb_resampler_xxx</key>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>1</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(656, 292)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>pfb_arb_resampler_xxx_0</value>
    </param>
    <param>
      <key>maxoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>minoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>nfilts</key>
      <value>32</value>
    </param>
    <param>
      <key>rrate</key>
      <value>bw/samp_rate</value>
    </param>
    <param>
      <key>samp_delay</key>
      <value>0</value>
    </param>
    <param>
      <key>atten</key>
      <value>100</value>
    </param>
    <param>
      <key>taps</key>
      <value></value>
    </param>
    <param>
      <key>type</key>
      <value>ccf</value>
    </param>
  </block>
  <block>
    <key>sdrplay_rsp2_source</key>
    <param>
      <key>agc_enabled</key>
      <value>False</value>
    </param>
    <param>
      <key>antenna</key>
      <value>'A'</value>
    </param>
    <param>
      <key>bw</key>
      <value>400</value>
    </param>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>dc_offset_mode</key>
      <value>True</value>
    </param>
    <param>
      <key>debug_enabled</key>
      <value>False</value>
    </param>
    <param>
      <key>device_serial</key>
      <value>'0'</value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(144, 196)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>sdrplay_rsp2_source_0</value>
    </param>
    <param>
      <key>if_atten_db</key>
      <value>30</value>
    </param>
    <param>
      <key>ifType</key>
      <value>0</value>
    </param>
    <param>
      <key>iq_balance_mode</key>
      <value>True</value>
    </param>
    <param>
      <key>lna_atten_step</key>
      <value>3</value>
    </param>
    <param>
      <key>lo_mode</key>
      <value>1</value>
    </param>
    <param>
      <key>maxoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>minoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>rf_freq</key>
      <value>869.0e6</value>
    </param>
    <param>
      <key>sample_rate</key>
      <value>samp_rate</value>
    </param>
  </block>
  <block>
    <key>wxgui_fftsink2</key>
    <param>
      <key>avg_alpha</key>
      <value>0</value>
    </param>
    <param>
      <key>average</key>
      <value>False</value>
    </param>
    <param>
      <key>baseband_freq</key>
      <value>0</value>
    </param>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>fft_size</key>
      <value>1024</value>
    </param>
    <param>
      <key>freqvar</key>
      <value>None</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(1000, 116)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>grid_pos</key>
      <value></value>
    </param>
    <param>
      <key>id</key>
      <value>wxgui_fftsink2_0</value>
    </param>
    <param>
      <key>notebook</key>
      <value></value>
    </param>
    <param>
      <key>peak_hold</key>
      <value>False</value>
    </param>
    <param>
      <key>ref_level</key>
      <value>0</value>
    </param>
    <param>
      <key>ref_scale</key>
      <value>2.0</value>
    </param>
    <param>
      <key>fft_rate</key>
      <value>15</value>
    </param>
    <param>
      <key>samp_rate</key>
      <value>samp_rate</value>
    </param>
    <param>
      <key>title</key>
      <value>FFT Plot</value>
    </param>
    <param>
      <key>type</key>
      <value>complex</value>
    </param>
    <param>
      <key>win_size</key>
      <value></value>
    </param>
    <param>
      <key>win</key>
      <value>None</value>
    </param>
    <param>
      <key>y_divs</key>
      <value>10</value>
    </param>
    <param>
      <key>y_per_div</key>
      <value>10</value>
    </param>
  </block>
  <connection>
    <source_block_id>blocks_rotator_cc_0</source_block_id>
    <sink_block_id>pfb_arb_resampler_xxx_0</sink_block_id>
    <source_key>0</source_key>
    <sink_key>0</sink_key>
  </connection>
  <connection>
    <source_block_id>blocks_rotator_cc_0</source_block_id>
    <sink_block_id>wxgui_fftsink2_0</sink_block_id>
    <source_key>0</source_key>
    <sink_key>0</sink_key>
  </connection>
  <connection>
    <source_block_id>lora_decode_0</source_block_id>
    <sink_block_id>blocks_socket_pdu_0</sink_block_id>
    <source_key>out</source_key>
    <sink_key>pdus</sink_key>
  </connection>
  <connection>
    <source_block_id>lora_demod_0</source_block_id>
    <sink_block_id>lora_decode_0</sink_block_id>
    <source_key>out</source_key>
    <sink_key>in</sink_key>
  </connection>
  <connection>
    <source_block_id>pfb_arb_resampler_xxx_0</source_block_id>
    <sink_block_id>lora_demod_0</sink_block_id>
    <source_key>0</source_key>
    <sink_key>0</sink_key>
  </connection>
  <connection>
    <source_block_id>sdrplay_rsp2_source_0</source_block_id>
    <sink_block_id>blocks_rotator_cc_0</sink_block_id>
    <source_key>0</source_key>
    <sink_key>0</sink_key>
  </connection>
</flow_graph>

receive2.grc

<?xml version='1.0' encoding='utf-8'?>
<?grc format='1' created='3.7.11'?>
<flow_graph>
  <timestamp>Mon Jun  3 09:39:45 2019</timestamp>
  <block>
    <key>options</key>
    <param>
      <key>author</key>
      <value></value>
    </param>
    <param>
      <key>window_size</key>
      <value></value>
    </param>
    <param>
      <key>category</key>
      <value>[GRC Hier Blocks]</value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>description</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(8, 8)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>generate_options</key>
      <value>wx_gui</value>
    </param>
    <param>
      <key>hier_block_src_path</key>
      <value>.:</value>
    </param>
    <param>
      <key>id</key>
      <value>top_block</value>
    </param>
    <param>
      <key>max_nouts</key>
      <value>0</value>
    </param>
    <param>
      <key>qt_qss_theme</key>
      <value></value>
    </param>
    <param>
      <key>realtime_scheduling</key>
      <value></value>
    </param>
    <param>
      <key>run_command</key>
      <value>{python} -u {filename}</value>
    </param>
    <param>
      <key>run_options</key>
      <value>prompt</value>
    </param>
    <param>
      <key>run</key>
      <value>True</value>
    </param>
    <param>
      <key>thread_safe_setters</key>
      <value></value>
    </param>
    <param>
      <key>title</key>
      <value></value>
    </param>
  </block>
  <block>
    <key>variable</key>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(184, 12)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>samp_rate</value>
    </param>
    <param>
      <key>value</key>
      <value>1000000</value>
    </param>
  </block>
  <block>
    <key>lora_lora_receiver</key>
    <param>
      <key>bandwidth</key>
      <value>125000</value>
    </param>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>crc</key>
      <value>True</value>
    </param>
    <param>
      <key>center_freq</key>
      <value>869e6</value>
    </param>
    <param>
      <key>channel_list</key>
      <value>[869.1e6]</value>
    </param>
    <param>
      <key>cr</key>
      <value>4</value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>conj</key>
      <value>False</value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>decimation</key>
      <value>1</value>
    </param>
    <param>
      <key>disable_channelization</key>
      <value>False</value>
    </param>
    <param>
      <key>disable_drift_correction</key>
      <value>False</value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(456, 332)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>lora_lora_receiver_0</value>
    </param>
    <param>
      <key>implicit</key>
      <value>False</value>
    </param>
    <param>
      <key>maxoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>minoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>reduced_rate</key>
      <value>False</value>
    </param>
    <param>
      <key>samp_rate</key>
      <value>1e6</value>
    </param>
    <param>
      <key>sf</key>
      <value>8</value>
    </param>
  </block>
  <block>
    <key>lora_message_socket_sink</key>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(696, 364)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>lora_message_socket_sink_0</value>
    </param>
    <param>
      <key>ip</key>
      <value>127.0.0.1</value>
    </param>
    <param>
      <key>layer</key>
      <value>1</value>
    </param>
    <param>
      <key>port</key>
      <value>40868</value>
    </param>
  </block>
  <block>
    <key>sdrplay_rsp2_source</key>
    <param>
      <key>agc_enabled</key>
      <value>False</value>
    </param>
    <param>
      <key>antenna</key>
      <value>'A'</value>
    </param>
    <param>
      <key>bw</key>
      <value>400</value>
    </param>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>dc_offset_mode</key>
      <value>True</value>
    </param>
    <param>
      <key>debug_enabled</key>
      <value>False</value>
    </param>
    <param>
      <key>device_serial</key>
      <value>'0'</value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(72, 148)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>id</key>
      <value>sdrplay_rsp2_source_0</value>
    </param>
    <param>
      <key>if_atten_db</key>
      <value>30</value>
    </param>
    <param>
      <key>ifType</key>
      <value>0</value>
    </param>
    <param>
      <key>iq_balance_mode</key>
      <value>True</value>
    </param>
    <param>
      <key>lna_atten_step</key>
      <value>3</value>
    </param>
    <param>
      <key>lo_mode</key>
      <value>1</value>
    </param>
    <param>
      <key>maxoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>minoutbuf</key>
      <value>0</value>
    </param>
    <param>
      <key>rf_freq</key>
      <value>869.0e6</value>
    </param>
    <param>
      <key>sample_rate</key>
      <value>samp_rate</value>
    </param>
  </block>
  <block>
    <key>wxgui_fftsink2</key>
    <param>
      <key>avg_alpha</key>
      <value>0</value>
    </param>
    <param>
      <key>average</key>
      <value>True</value>
    </param>
    <param>
      <key>baseband_freq</key>
      <value>0</value>
    </param>
    <param>
      <key>alias</key>
      <value></value>
    </param>
    <param>
      <key>comment</key>
      <value></value>
    </param>
    <param>
      <key>affinity</key>
      <value></value>
    </param>
    <param>
      <key>_enabled</key>
      <value>True</value>
    </param>
    <param>
      <key>fft_size</key>
      <value>1024</value>
    </param>
    <param>
      <key>freqvar</key>
      <value>None</value>
    </param>
    <param>
      <key>_coordinate</key>
      <value>(688, 108)</value>
    </param>
    <param>
      <key>_rotation</key>
      <value>0</value>
    </param>
    <param>
      <key>grid_pos</key>
      <value></value>
    </param>
    <param>
      <key>id</key>
      <value>wxgui_fftsink2_0</value>
    </param>
    <param>
      <key>notebook</key>
      <value></value>
    </param>
    <param>
      <key>peak_hold</key>
      <value>True</value>
    </param>
    <param>
      <key>ref_level</key>
      <value>0</value>
    </param>
    <param>
      <key>ref_scale</key>
      <value>2.0</value>
    </param>
    <param>
      <key>fft_rate</key>
      <value>15</value>
    </param>
    <param>
      <key>samp_rate</key>
      <value>samp_rate</value>
    </param>
    <param>
      <key>title</key>
      <value>FFT Plot</value>
    </param>
    <param>
      <key>type</key>
      <value>complex</value>
    </param>
    <param>
      <key>win_size</key>
      <value></value>
    </param>
    <param>
      <key>win</key>
      <value>None</value>
    </param>
    <param>
      <key>y_divs</key>
      <value>10</value>
    </param>
    <param>
      <key>y_per_div</key>
      <value>10</value>
    </param>
  </block>
  <connection>
    <source_block_id>lora_lora_receiver_0</source_block_id>
    <sink_block_id>lora_message_socket_sink_0</sink_block_id>
    <source_key>frames</source_key>
    <sink_key>in</sink_key>
  </connection>
  <connection>
    <source_block_id>sdrplay_rsp2_source_0</source_block_id>
    <sink_block_id>lora_lora_receiver_0</sink_block_id>
    <source_key>0</source_key>
    <sink_key>0</sink_key>
  </connection>
  <connection>
    <source_block_id>sdrplay_rsp2_source_0</source_block_id>
    <sink_block_id>wxgui_fftsink2_0</sink_block_id>
    <source_key>0</source_key>
    <sink_key>0</sink_key>
  </connection>
</flow_graph>

Всем удачных экспериментов.

Автор: DmitrySpb79

Источник

* - обязательные к заполнению поля