Сервер и клиент для удаленного управление радиостанцией

Идея об удаленном управлении радиостанцией уже давно будоражит умы радиолюбителей. Есть варианты с использованием удаленного рабочего стола, есть варианты с железной реализацией сервера со стороны трансивера и программного управления из любой точки, где есть интернет. Я постараюсь описать еще один вариант удаленки, при котором используется сервер, расположенный у трансивера, и клиент, который подключается там, где находится оператор.

Обзор

Система удаленного  управления и передачи звука, получившая имя ЦЕЗАРЬ (по первым буквам английских слов, образующих название, и потому, что он может делать сразу несколько дел одновременно), представляет собой два устройства — сервер и клиент. Сервер расположен у трансивера и подключен к нему с помощью CAT интерфейса, PTT, CW сигналов и аудио входа и выхода.

Сердцем обоих устройств является одноплатный миникомпьютер Orange Pi Zero. Это практически полноценный ПК с Linux на борту, что заметно упрощает его настройку и программирование.

Клиент располагается там же, где и оператор — то есть вдали от антенн и трансивера. В самом простом варианте клиент может быть использован только для передачи звука в обе стороны и PTT сигнала. То есть, в клиента втыкается только гарнитура и педаль. Управление трансивером происходит, например, через удаленный рабочий стол. Естественно, что в  таком упрощенном виде, в сервер подключается только шнурок PTT к трансиверу и аудио сигналы (микрофон и выход звука). Такое подключение позволяет упростить удаленную работу в SSB режиме.

Второй вариант использования — это полноценная удаленная работа через клиента. В таком случае клиент подключается к компьютеру с аппаратным журналом с помощью двух USB-COM портов. Один используется для CAT и PTT (параллельно с педалью), а второй для формирования CW манипуляции с помощью протокола winkey.

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

Аппаратная часть

Одноплатный компьютер, в отличие от настольного ПК, имеет ряд преимуществ. Одно из них — наличие программируемых портов ввода-вывода, которыми можно управлять прямо из операционной системы. Помимо этого, на борту Orange Pi Zero уже есть встроенная звуковая карта и два com-порта (UART1, UART2).

Основная идея работы устройства — передать состояние выводов с одного миниПК на другой по сети. То же самое со звуком — нужно организовать трансляцию аудиопотока с сервера к клиенту, и обратно. Что-то вроде IP-телефонии.

Для трансляции CAT протокола по сети используются встроенные com-порты, соединенные с внешними USB-UART преобразователями. На клиентской стороне для передачи PTT используется порт, настроенный на вход и сигнал RTS параллельно со входом для педали. На серверной стороне — простой транзисторный ключ, подключенный к порту, настроенному на выход.

Подключение к сети только по LAN (ethernet). Orange Pi Zero имеет встроенный WI-FI, но для минимизации задержек в передаче нужно использовать только проводное подключение.

При подключении к питанию и к сети, настроенные клиент и сервер сами находят друг друга и сигнализируют об этом светящимся светодиодом. Проверка доступности и клиента, и сервера происходит постоянно (3 раза в секунду), поэтому потеря связи будет оперативно замечена. Восстановление работы всех сервисов после потери связи или перезагрузке так же происходит автоматически.

Программная реализация

Исходный код проекта (с подробным ReadMe) выложен на GitHub. Для работы клиенту и серверу необходимы реальные IP адреса, либо настроенный VPN сервер (об этом варианте чуть позже). Если клиент и сервер находятся не в одной локальной сети, то необходимо произвести настройку проброса портов на обоих роутерах, раздающих интернет в точках подключения коробочек. Какие порты используются указано на GitHub.

Нагрузка на центральный процессор и используемая оперативная память в полностью рабочем режиме (CAT, CW, PTT, Audio) показана на рисунке выше. Вся функциональность устройств разбита на сервисы операционной системы, и все они работают независимо. ОС отслеживает их состояния и при необходимости перезапускает.

  • Для передачи звука используется утилита gst-launch и аудиокодек OPUS. Пример команды, транслирующей звук от сервера к клиенту (файл audio_server.sh):
    # Audio stream
    gst-launch-1.0   alsasrc device=hw:0 !   audioconvert !   audioresample !   capsfilter caps="audio/x-raw,rate=48000,channels=1,format=S16LE" !   opusenc bitrate=24000 frame-size=10 complexity=1 !   rtpopuspay !   udpsink host=$IP_ADDRESS port=5000 sync=false
  • Для отслеживания и передачи сигнала PTT используется библиотека wiringOP для Python. Данные о нажатии передаются по UDP от клиента к серверу. Пример кода из файла  ptt_client.py:
    #!/usr/bin/python3
    import wiringpi
    import socket
    import time
    
    
    CONFIG_FILE = 'server_ip.cfg'
    SERVER_PORT = 5001
    PTT_PIN = 12
    DEBOUNCE_DELAY = 0.01
    
    def read_ip_from_file(filename):
        try:
            with open(filename, 'r') as f:
                return f.readline().strip()
        except FileNotFoundError:
            print(f"Error: {filename} not found")
            return None
        except Exception as e:
            print(f"Error reading: {e}")
            return None
    
    def main():
        wiringpi.wiringPiSetup()
        wiringpi.pinMode(PTT_PIN, wiringpi.INPUT)
        server_ip = read_ip_from_file(CONFIG_FILE)
        if not server_ip:
            print("Using default IP: 192.168.0.201")
            server_ip = '192.168.0.201'
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        button_state =  wiringpi.digitalRead(PTT_PIN)
        try:
            print(f"PTT server is running {server_ip}:{SERVER_PORT}")
            print(f"Starting button state: {button_state}")
            
            while True:
                current_state = wiringpi.digitalRead(PTT_PIN)
                
                if current_state != button_state:
                    time.sleep(DEBOUNCE_DELAY)
                    current_state = wiringpi.digitalRead(PTT_PIN)
                    
                    if current_state != button_state:
                        button_state = current_state
                        send_value = 1 if button_state == 0 else 0
                        print(f"Current state: {button_state}")
                        sock.sendto(str(send_value).encode(), (server_ip, SERVER_PORT))
                
                time.sleep(0.01)
                
        except KeyboardInterrupt:
            print("\nFinished.")
        finally:
            sock.close()
    
    if __name__ == "__main__":
        main()
    
  • На стороне сервера примерно такой же код слушает нужный UDP порт и выставляет значение на выходе в соответствии с полученной информацией. Для обеспечения безопасности в случае потери связи во время передачи, сервис, отвечающий за проверку коннекта между клиентом и сервером, перезапускает PTT-сервис. Это позволяет не бояться, что трансивер останется на передаче в случае проблем с соединением.
  • За передачу CAT и Winkey протокола по сети отвечает утилита ser2net. По сути она транслирует данные из com-порта в сеть и обратно (UART — LAN преобразователь). На стороне клиента CAT и Winkey данные из сети перенаправляются на встроенные com порты. Пример кода такого ретранслятора (файл client_ser2net.sh):
    socat -d -d \
      "UDP:$SERVER_IP:3001" \
      "/dev/ttyS1,raw,echo=0,b19200,cs8,parenb=0,cstopb=0"
  • IP адреса сервера и клиента прописываются в соответствующих файлах — client_ip.cfg и server_ip.cfg

Задержка звука в локальной сети составляет порядка 300 мс. При работе через интернет эта величина, естественно, будет выше. На самом деле, высокое значение задержки не так уж и страшно, главное — стабильность этой задержки. Она не должна сильно меняться (оставаться в пределах +-3мс). Полоса, используемая для передачи звука и данных — порядка 64кб/с.

Для работы телеграфом необходим ключ с поддержкой протокола winkey. Это единственный известный мне способ передачи и формирования CW без задержек и рваной передачи.

Нет статических IP адресов. Что делать?

Если в точках подключения сервера и клиента нет возможности подключить статические IP адреса, на помощь приходит VPN. Можно воспользоваться услугами хостеров, которые предоставляют виртуальные выделенные серверы (VPS) с белыми IP адресами. На таком VPS развертывается vpn-сервер, в общую сеть которого подключаются коробочки клиента и сервера. Таким образом, они оказываются в одной виртуальной локальной сети. Это позволяет работать даже не имея статических IP адресов. Нужен только один VPS-сервер (цена вопроса порядка 300-400 руб. в месяц). Лучше выбирать провайдера VPS поближе к себе, чтобы уменьшить задержку в канале.

Я проверил работу через VPN сервер, установленный на московский VPS. Клиент и сервер находились в Иркутской области, задержка звука составила 600 мс (проверял в FT8). Неплохой результат, учитывая большое расстояние между виртуальным сервером и устройствами.

Сравнение с решением на базе удаленного рабочего стола

Плюсы:

  • Передача звука без привязки к компьютеру в шеке
  • Простое управление передачей при работе в SSB
  • Автоматическое восстановление канала (звук, CAT, PTT) при обрывах связи или питания
  • Более стабильная передача звука
  • Возможность не устанавливать стационарный ПК рядом с трансивером

Минусы:

  • Задержки в управлении трансивером из-за канала связи
  • Необходимость установки клиента в месте расположения оператора, помимо основного компьютера
  • Необходимость использования winkey совместимого ключа рядом с трансивером
  • Необходимость в статических IP адресах или VPN-сервере

С другой стороны никто не запрещает совместить два решения. Оставить удаленный рабочий стол для работы в CW и цифровых видах, а данный проект использовать для работы в SSB.

Что дальше?

Пока что система опробована на макетном варианте из модулей с АлиЭкспресс. В дальнейшем я планирую сделать печатную плату для полной версии устройства (с CAT и CW). Помимо этого, можно сделать устройство расширяемым — на Orange Pi Zero осталось еще много неиспользуемых портов, которые можно по аналогии с PTT использовать для включения антенн, доп. оборудования или чего угодно. Получится своеобразный пульт с управлением по интернету.

Для желающих повторить конструкцию предлагаю воспользоваться инструкцией из ReadMe на GitHub.

Запись опубликована в рубрике Linux, Python, Радио, Удаленка с метками , , . Добавьте в закладки постоянную ссылку.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *