前情提要
近期在自身兴趣和朋友的引导下,尝试通过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接受棒,故把另外两个设备删了。
设备设置
点击自己的设备,首先进入设备自己的设置界面,大概如下:
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小站上了好几个机场的频段标记。