基于树莓派和RTL-SDRV3搭建无线电在线收听服务

前情提要

近期在自身兴趣和朋友的引导下,尝试通过SDR来接触业余无线电(无限垫)。在朋友的推荐下在某宝购买了一个RTL-SDR V3,其本质上只是修改了部分电路的一根电视棒。随后通过SDR#成功听到了深圳本地的相关广播台,并尝试通过ADSB成功掌握了附近航班的动态。

然而SDR#只能做到自己听,而无法直观的展现/分享给友人终归还是不太方便。出门在外,也不方便随身携带SDR设备。故搭建一个可以通过网页收听无线电波的服务是更为便捷的选择。

类似的服务包括:KiwiSdr,WebSDR,然而前两种服务需要购买专门的接收机,也无现有的部署教程。在一番搜索下,OpenWebRX无疑是更方便的选择。

为了更低的功耗,笔者拿出了吃灰已久的NanoPI Neo,然而NanoPI Neo性能较低,无法使用ADSB的解码功能。故拿出了吃灰更久的树莓派4B。理论上使用NAS/其他开发板也可行。

安装RTL-SDR驱动

本段落参考RTL-SDR官网的Quick Start Guide:https://www.rtl-sdr.com/rtl-sdr-quick-start-guide/

在开始搭建服务之前,需要安装RTL-SDR的驱动。此处专门介绍Linux环境下如何安装。

执行下列命令,用于移除可能的曾经安装过的旧版本驱动:

sudo apt purge ^librtlsdr
sudo rm -rvf /usr/lib/librtlsdr* /usr/include/rtl-sdr* /usr/local/lib/librtlsdr* /usr/local/include/rtl-sdr* /usr/local/include/rtl_* /usr/local/bin/rtl_*

在移除完旧的驱动后,就可以正式开始安装驱动:

sudo apt-get install libusb-1.0-0-dev git cmake pkg-config
git clone https://github.com/rtlsdrblog/rtl-sdr-blog
cd rtl-sdr-blog/
mkdir build
cd build
cmake ../ -DINSTALL_UDEV_RULES=ON
make
sudo make install
sudo cp ../rtl-sdr.rules /etc/udev/rules.d/
sudo ldconfig

我们有可能还需要禁用系统自带的电视棒驱动,可以尝试输入“sudo rmmod dvb_usb_rtl28xxu”指令来禁用自带的驱动(重启后无效),随后重新插拔SDR棒子。为了更方便日后使用,推荐执行下列指令永久禁用自带驱动:

echo 'blacklist dvb_usb_rtl28xxu' | sudo tee --append /etc/modprobe.d/blacklist-dvb_usb_rtl28xxu.conf

完成操作后,我们就可以尝试使用 “rtl_test” 指令来测试SDR设备,会得到以下输出:

$ rtl_test
Found 1 device(s):
  0:  Realtek, RTL2838UHIDIR, SN: 00000001

Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
Supported gain values (29): 0.0 0.9 1.4 2.7 3.7 7.7 8.7 12.5 14.4 15.7 16.6 19.7 20.7 22.9 25.4 28.0 29.7 32.8 33.8 36.4 37.2 38.6 40.2 42.1 43.4 43.9 44.5 48.0 49.6
Enabled direct sampling mode, input 2
Sampling at 2048000 S/s.

Info: This tool will continuously read from the device, and report if
samples get lost. If you observe no further output, everything is fine.

Reading samples in async mode...

如果没有后续输出的话,那么说明棒子已经能够在树莓派上正常使用了。接下来,可以尝试使用dump1090看看附近的航班,也可以直接开始搭建OpenWebRX+服务。

搭建OpenWebRX+服务

很不幸,在实践的时候,OpenWebRX已经停止维护。但是目前有人fork了代码,迭代出了OpenWebRX+,功能对比OpenWebRX更多(解码数字信号更加方便),下文中所有的“OpenWebRX”均指代OpenWebRX+。

Github传送门:https://github.com/0xAF/openwebrxplus

搭建的方式也多种多样,如果是树莓派设备,其实可以直接下载一键镜像包。也可以使用Debian源、Docker镜像、手动安装等方式。为了后续维护方便,这边使用Docker镜像部署该服务。

https://hub.docker.com/search?q=openwebrxplus

在DockerHub上可以搜索到很多由slechev发布的openwebrxplus镜像,其中“slechev/openwebrxplus-softmbe”内置了SoftMBE,可以解码DMR等信号,推荐部署该镜像。

利用Docker-Compose部署

Docker-Compose文件如下(仅供参考,可根据自身需要做修改)

version: '3'
services:
  openwebrxplus:
    image: slechev/openwebrxplus-softmbe
    container_name: openwebrxplus-container
    ports:
      - "8073:8073"
      - "8074:8074"
    devices:
      - /dev/bus/usb:/dev/bus/usb
    restart: always
    volumes:
      - ./openwebrx:/var/lib/openwebrx
      - ./config:/etc/openwebrx

在你想要的地方,nano一个docker-compose.yml,然后输入以上内容,即可完成编辑。

然后使用"sudo docker-compose up"命令运行容器,第一次运行需要从dockerhub拉取镜像。如果网络缓慢,可以尝试使用docker镜像源。

拉取完成后,访问树莓派IP:8073端口,即可看到OpenWebRX+的界面了。不出意外的话,此时你已经能够听到大量的电子噪声了。可以通过右下角的界面切换监听的频道。

主界面

该图片为完成大部分设置后的界面,你看到的界面大概率不长这样,需要进一步配置才行。

创建OpenWebRX+管理员账户

首先你应该留意到了界面左上角的Settings,当你进入后,就看到一个无情的登录框框。你在百度、github项目中到处找,也无法找到账号密码。

OpenWebRX+的管理员账号需要我们自行创建,而创建账号呢需要进入容器中操作,操作步骤如下:

首先,查询docker容器ID,使用docker ps指令查询,但是不要忘记docker命令需要root权限!

Nature@ayabe:~/openwebrx $ sudo docker ps
CONTAINER ID   IMAGE                           COMMAND   CREATED         STATUS         PORTS
                                NAMES
9bef864dd6b1   slechev/openwebrxplus-softmbe   "/init"   6 minutes ago   Up 6 minutes   0.0.0.0:8073-8074->8073-8074/tcp, :::8073-8074->8073-8074/tcp   openwebrxplus-container

查询到容器ID之后,我们就可以通过docker exec指令进入容器内

Nature@ayabe:~/openwebrx $ sudo docker exec - it 9bef864dd6b1(修改成你的容器ID!) bash
root@9bef864dd6b1:/opt/openwebrx# 

随后我们就能执行命令来建立管理员用户:

root@9bef864dd6b1:/opt/openwebrx# python3 openwebrx.py admin
usage: openwebrx.py admin [-h] [--noninteractive] [--silent]
                          {adduser,removeuser,resetpassword,listusers,disableuser,enableuser,hasuser} ...

optional arguments:
  -h, --help            show this help message and exit
  --noninteractive      Don't ask for any user input (useful for automation)
  --silent              Ignore errors (useful for automation)

Commands:
  {adduser,removeuser,resetpassword,listusers,disableuser,enableuser,hasuser}
    adduser             Add a new user
    removeuser          Remove an existing user
    resetpassword       Reset a user's password
    listusers           List enabled users
    disableuser         Disable a user
    enableuser          Enable a user
    hasuser             Test if a user exists
root@9bef864dd6b1:/opt/openwebrx# python3 openwebrx.py adduser (修改为用户名)

然后便会提示输入密码,输入完成后,就可以进入设置界面啦。

设置界面简介

设置界面

你需要专门注意的设定

General Settings -> 基本设定

输入你的呼号(如果你有),经纬度,海拔,联系方式等。

Maximum number of clients是限制同时连接数,建议调整到合适的数字(官网说法树莓派3-5)。

“Map settings”->“Map type"修改为OpenStreetMap。如果希望使用默认的谷歌地图则需要输入APIKey,保存完成后点击“Apply And Save”即可。该地图用于渲染ADSB协议解析出来的飞机,但是要想飞机显示的准需要你把自己的经纬度设置的比较准。

SDR devices and profiles -> SDR设备设定

这个设定用于设定设备,默认已经添加了RTLSDR和AIRSPY啥的,现实中根据需要添加或删除设备。笔者只有RTL-SDR接受棒,故把另外两个设备删了。

SDR设定菜单

设备设置

点击自己的设备,首先进入设备自己的设置界面,大概如下:

设备设置界面

Device name不必多说,其他大部分都是在Additional opeional settings中添加的额外设置。

需要注意的是Oscillator Offset,这个是纠偏用的,之后会专门发一个文章介绍如何利用GSM基站校准天线,此处可以先填写0。

可以选择是否一直保持设备开启(否则设备只会在有人访问的时候开启),这个看个人。

Profile

接下来讲解Profile,在openwebsdr中,需要切换profile才能实现监听。其中profile是一个在中心点附近,左右一定范围内东西。故如果你想监听多个频段(比如:70cm和2m的ham波段),也需要多个profile。

频段修改

其中介绍几个重点参数,其中Profile name就是显示在前台的名字,Device Gain则是设备增益,根据需要修改(包括手动增益和启用AGC),Center frequency表示在频谱图中的正中心频率,Sample rate(采样率)根据实际效果修改(1090ADSB需要修改为2.4MS/s以上),Inital frequency代表打开页面时自动收听的频段,Initial modulation为该方案默认的解码方式(Tips:机场一般是AM),Tuning step则是调整的步长。

你还可以在底下的“额外可选设置”中添加诸如Direct samping的参数,此处不做赘述。

在添加完自己喜欢的频段后,便可尝试在web界面中进行收听。

至此,openwebrx+服务已经完成部署,你下一次运行可以使用 “docker-compose up -d"指令让容器在后台运行。

(半/不)公开你的OpenWebRX+服务

为什么说是半公开呢,因为涉及有关规定——无线电爱好者可以收听频段,但是不允许泄露听到的内容。然而一个公开的OpenWebRX服务无疑是违反该规定的。所以你需要根据实际情况来(半)公开你的OpenWebRX+服务。

对外直接公开SDR服务注意需要能够传输WebSocket,比较简单的方法包括:

  • 在cloudflare zero trust控制面板中创建一个tunnel,并在树莓派上运行cloudflare tunnel,进而通过设置将OpenWebRX+服务公开到公网。
  • 直接用FRP服务将将OpenWebRX+服务直接暴露在公网。
  • 你有公网IP,直接映射。
  • 公网有个小鸡,利用tailscale/wireguard/zerotier这类组网工具的允许小鸡和树莓派互访,然后小鸡做个反代(注意要允许WebSocket)。
  • 其他更好,能跑的方法。

半公开的话,可以考虑在某一端运行一个cady/nginx作为反代,设置一个Basic Auth作为简单鉴权。或者更干脆地:Cookies != something, return sadpanda。

如果你只是希望在旅途中听一下家里的SDR,通过tailscale/wireguard/zeotier这类组网工具将树莓派和你的设备组到一个内网是更加安全、便捷、私密的选择。

笔者有对外共享的需求,故选择半公开方案,用headscale+tailscale的方式允许小鸡和树莓派互访,随后在小鸡端设置Basic Auth鉴权。完成架设后,将该站点共享给了一个曾在航空行业的朋友,托他指点,给SDR小站上了好几个机场的频段标记。