OpenWebRX:配合RTL-SDR设备可视化SDRSharp

RTL-SDR是一个具有DVB-T USB接口的接收器,该设备广泛应用于软件定义无线电领域,DVB-T接收器基于Realtek的RTL2832U芯片外加一个诸如Elonics E4000一类的高频头而构成。RTL2832U芯片有一些没有用到的命令/寄存器,基于此便可将其配置使得可以将没有处理的原始的基带采样信号(可高达 2.8 MS/s 8-bit I+Q)通过高速USB传递到PC,最后到达GNURadio。而OpenWebRX是具有Web界面的多用户SDR接收器软件,较为遗憾的是该程序的作者已经宣布自2019年12月29日起不再维护该仓库。

简介

OpenWebRX可以支持基于csdr的解调器(AM/FM/SSB/CW/BPSK31),可以通过GUI设置滤波器通带,瀑布流显示并且可以向后移动,当前支持RTL-SDR,HackRF,SDRplay,AirSpy和许多其他设备,该Web界面运行于8073端口。

唯一美中不足的是,该程序不支持广播电台的WFM,仅支持NFM方式。

安装

下面开始介绍手动安装OpenWebRX的过程,本人是基于Raspberry Pi 3的开发板,安装树莓派官方Pi Buster系统构建而来,具体关于frp的部分可以参考本人博客的另一篇文章:树莓派配合frp内网穿透及ADS-B信号捕获的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#安装编译时必要的包
root@pi:/home# curl https://raw.githubusercontent.com/bclswl0827/openwebrx-installer/master/rtl-sdr_installer.sh | bash

#拉取 RTL-SDR 之驱动源码并编译
root@pi:/home# git clone https://github.com/keenerd/rtl-sdr.git
root@pi:/home# cd rtl-sdr
root@pi:/home/rtl-sdr# mkdir build
root@pi:/home/rtl-sdr# cd build
root@pi:/home/rtl-sdr/build# cmake ../ -DDETACH_KERNEL_DRIVER=ON -DINSTALL_UDEV_RULES=ON
root@pi:/home/rtl-sdr/build# make
root@pi:/home/rtl-sdr/build# make install
root@pi:/home/rtl-sdr/build# ldconfig
root@pi:/home/rtl-sdr/build# cd /home

#然后拉取OpenWebRX及其依赖项csdr的源码,并编译 csdr。
root@pi:/home# git clone https://github.com/simonyiszk/openwebrx.git
root@pi:/home# git clone https://github.com/jketterl/csdr
root@pi:/home# cd csdr
root@pi:/home/csdr# git checkout 32958ce37eb765f7f5511fe5f7c2c244c13f264b
root@pi:/home/csdr# make
root@pi:/home/csdr# make install
root@pi:/home/csdr# cd /home

#某些内核模块会锁定 USB 设备,需要在使用 SDR 设备之前将其禁用。
#如果内核模块未正确列入黑名单,则可能会出现 Device not found 的错误。
root@pi:/home# bash -c 'echo -e "\n# for RTL-SDR:\nblacklist dvb_usb_rtl28xxu\n" >> /etc/modprobe.d/blacklist.conf'
root@pi:/home# update-initramfs -u
root@pi:/home# rmmod dvb_usb_rtl28xxu
#倘若执行第三条命令出现错误,属于正常现象,等待程序安装完成即可。

之后需要进行的就是测试该设备是否正常工作,插入 RTL-SDR,然后重启系统。

1
2
3
4
5
6
root@pi:~# lsusb
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 002: ID 0bda:2838 Realtek Semiconductor Corp. RTL2838 DVB-T
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

列出 USB 设备,RTL-SDR 位列其中。

1
2
3
4
root@pi:~# cd /home/openwebrx
#运行命令,可使用screen -S [screen_name]后台运行,screen -r [screen_name]恢复
#Ctrl+a+d最小化 当然也可以写成service作为系统服务开机自动运行
root@pi:/home/openwebrx# ./openwebrx.py

运行

运行OpenWebRX以测试,倘若一切正常,命令行显示字样如下所示,即安装成功。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
OpenWebRX - Open Source SDR Web App for Everyone!  | for license see LICENSE file in the package
_________________________________________________________________________________________________

Author contact info: Andras Retzler, HA7ILM <randras@sdr.hu>

[openwebrx-main] Configuration script not specified. I will use: "config_webrx.py"
[openwebrx-main] nmux_bufsize = 253952, nmux_bufcnt = 505
[openwebrx-main] Started rtl_thread: rtl_sdr -D2 -s 2048000 -f 9500000 -p 0 -g 90 -| nmux --bufsize 253952 --bufcnt 505 --port 4951 --address 127.0.0.1
[openwebrx-main] Waiting for I/Q server to start...
nmux: listening on 127.0.0.1:4951
Found 1 device(s):
0: Realtek, RTL2838UHIDIR, SN: 00000001

Using device 0: Generic RTL2832U OEM
[openwebrx-main] I/Q server started.
[openwebrx-main] Starting watchdog threads.
nmux: pthread_create() done, clients now: 1
client 0x231a0f8: started!
[openwebrx-main] Starting spectrum thread.
[openwebrx-spectrum] Spectrum thread initialized successfully.
[openwebrx-dsp-plugin:csdr] Command = nc -v 127.0.0.1 4951 | csdr convert_u8_f | csdr fft_cc 2048 204 | csdr logaveragepower_cf -70 2048 1628 | csdr fft_exchange_sides_ff 2048 | csdr compress_fft_adpcm_f_u8 2048
[openwebrx-main] Starting HTTP server.
[openwebrx-spectrum] Spectrum thread started.
nmux: pthread_create() done, clients now: 2
client 0x231a1e0: started!
Connection to 127.0.0.1 4951 port [tcp/*] succeeded!
Found Rafael Micro R820T tuner
Enabled direct sampling mode, input 2
Enabled direct sampling mode, input 2/Q.
Exact sample rate is: 20480000.026491 Hz
Sampling at 20480000 S/s.
Tuned to 9500000 Hz.
Tuner gain set to 49.60 dB.
Reading samples in async mode...
Allocating 15 zero-copy buffers
client 0x231a0f8: CS_THREAD_FINISHED, client_goto_source = 2, errno = 32

自定义配置

修改配置文件config_webrx.py,该文件路径为:/home/openwebrx/config_webrx.py 。代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# -*- coding: utf-8 -*-

"""
config_webrx: configuration options for OpenWebRX

This file is part of OpenWebRX,
an open-source SDR receiver software with a web UI.
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

In addition, as a special exception, the copyright holders
state that config_rtl.py and config_webrx.py are not part of the
Corresponding Source defined in GNU AGPL version 3 section 1.

(It means that you do not have to redistribute config_rtl.py and
config_webrx.py if you make any changes to these two configuration files,
and use them for running your web service with OpenWebRX.)
"""

# NOTE: you can find additional information about configuring OpenWebRX in the Wiki:
# https://github.com/simonyiszk/openwebrx/wiki

# ==== Server settings ====
web_port=8073
server_hostname="sdr.kixcs.com" # If this contains an incorrect value, the web UI may freeze on load (it can't open websocket)
max_clients=20

# ==== Web GUI configuration ====
receiver_name="RTL-SDR Radio"
receiver_location="Zhengzhou , Henan, China"
receiver_qra="OM64tr"
receiver_asl=200
receiver_ant="Longwire"
receiver_device="RTL-SDR"
receiver_admin="yourEmail"
receiver_gps=(34.000, 114.000)
photo_height=350
photo_title="Panorama of Budapest from Sch枚nherz Zolt谩n Dormitory"
photo_desc="""
You can add your own background photo and receiver information.<br />
Receiver is operated by: <a href="mailto:%[RX_ADMIN]">%[RX_ADMIN]</a><br/>
Device: %[RX_DEVICE]<br />
Antenna: %[RX_ANT]<br />
Welcome to visit my Website: <a href="https://kixcs.com" target="_blank">https://kixcs.com</a>
"""

# ==== sdr.hu listing ====
# If you want your ham receiver to be listed publicly on sdr.hu, then take the following steps:
# 1. Register at: http://sdr.hu/register
# 2. You will get an unique key by email. Copy it and paste here:
sdrhu_key = ""
# 3. Set this setting to True to enable listing:
sdrhu_public_listing = False

# ==== DSP/RX settings ====
fft_fps=9
fft_size=4096 #Should be power of 2
fft_voverlap_factor=0.3 #If fft_voverlap_factor is above 0, multiple FFTs will be used for creating a line on the diagram.

# samp_rate = 250000
samp_rate = 2048000
center_freq = 93900000
rf_gain = 0 #in dB. For an RTL-SDR, rf_gain=0 will set the tuner to auto gain mode, else it will be in manual gain mode.
ppm = 0

audio_compression="adpcm" #valid values: "adpcm", "none"
fft_compression="adpcm" #valid values: "adpcm", "none"

digimodes_enable=True #Decoding digimodes come with higher CPU usage.
digimodes_fft_size=2048

start_rtl_thread=True

"""
Note: if you experience audio underruns while CPU usage is 100%, you can:
- decrease `samp_rate`,
- set `fft_voverlap_factor` to 0,
- decrease `fft_fps` and `fft_size`,
- limit the number of users by decreasing `max_clients`.
"""

# ==== I/Q sources ====
# (Uncomment the appropriate by removing # characters at the beginning of the corresponding lines.)

#################################################################################################
# Is my SDR hardware supported? #
# Check here: https://github.com/simonyiszk/openwebrx/wiki#guides-for-receiver-hardware-support #
#################################################################################################

# You can use other SDR hardware as well, by giving your own command that outputs the I/Q samples... Some examples of configuration are available here (default is RTL-SDR):

# >> RTL-SDR via rtl_sdr

start_rtl_command="rtl_sdr -s {samp_rate} -f {center_freq} -p {ppm} -g {rf_gain} -".format(rf_gain=rf_gain, center_freq=center_freq, samp_rate=samp_rate, ppm=ppm)
#start_rtl_command="rtl_sdr -D2 -s {samp_rate} -f {center_freq} -p {ppm} -g {rf_gain} -".format(rf_gain=rf_gain, center_freq=center_freq, samp_rate=samp_rate, ppm=ppm)
format_conversion="csdr convert_u8_f"

#lna_gain=8
#rf_amp=1
#start_rtl_command="hackrf_transfer -s {samp_rate} -f {center_freq} -g {rf_gain} -l{lna_gain} -a{rf_amp} -r-".format(rf_gain=rf_gain, center_freq=center_freq, samp_rate=samp_rate, ppm=ppm, rf_amp=rf_amp, lna_gain=lna_gain)
#format_conversion="csdr convert_s8_f"
"""
To use a HackRF, compile the HackRF host tools from its "stdout" branch:
git clone https://github.com/mossmann/hackrf/
cd hackrf
git fetch
git checkout origin/stdout
cd host
mkdir build
cd build
cmake .. -DINSTALL_UDEV_RULES=ON
make
sudo make install
"""

# >> Sound card SDR (needs ALSA)
# I did not have the chance to properly test it.
#samp_rate = 96000
#start_rtl_command="arecord -f S16_LE -r {samp_rate} -c2 -".format(samp_rate=samp_rate)
#format_conversion="csdr convert_s16_f | csdr gain_ff 30"

# >> /dev/urandom test signal source
# samp_rate = 2400000
# start_rtl_command="cat /dev/urandom | (pv -qL `python -c 'print int({samp_rate} * 2.2)'` 2>&1)".format(rf_gain=rf_gain, center_freq=center_freq, samp_rate=samp_rate)
# format_conversion="csdr convert_u8_f"

# >> Pre-recorded raw I/Q file as signal source
# You will have to correctly specify: samp_rate, center_freq, format_conversion in order to correctly play an I/Q file.
#start_rtl_command="(while true; do cat my_iq_file.raw; done) | csdr flowcontrol {sr} 20 ".format(sr=samp_rate*2*1.05)
#format_conversion="csdr convert_u8_f"

#>> The rx_sdr command works with a variety of SDR harware: RTL-SDR, HackRF, SDRplay, UHD, Airspy, Red Pitaya, audio devices, etc.
# It will auto-detect your SDR hardware if the following tools are installed:
# * the vendor provided driver and library,
# * the vendor-specific SoapySDR wrapper library,
# * and SoapySDR itself.
# Check out this article on the OpenWebRX Wiki: https://github.com/simonyiszk/openwebrx/wiki/Using-rx_tools-with-OpenWebRX/
#start_rtl_command="rx_sdr -F CF32 -s {samp_rate} -f {center_freq} -p {ppm} -g {rf_gain} -".format(rf_gain=rf_gain, center_freq=center_freq, samp_rate=samp_rate, ppm=ppm)
#format_conversion=""

# >> gr-osmosdr signal source using GNU Radio (follow this guide: https://github.com/simonyiszk/openwebrx/wiki/Using-GrOsmoSDR-as-signal-source)
#start_rtl_command="cat /tmp/osmocom_fifo"
#format_conversion=""

# ==== Misc settings ====

shown_center_freq = center_freq #you can change this if you use an upconverter

client_audio_buffer_size = 5
#increasing client_audio_buffer_size will:
# - also increase the latency
# - decrease the chance of audio underruns

start_freq = 93900000
start_mod = "nfm" #nfm, am, lsb, usb, cw

iq_server_port = 4951 #TCP port for ncat to listen on. It will send I/Q data over its connections, for internal use in OpenWebRX. It is only accessible from the localhost by default.

#access_log = "~/openwebrx_access.log"

# ==== Color themes ====

#A guide is available to help you set these values: https://github.com/simonyiszk/openwebrx/wiki/Calibrating-waterfall-display-levels

### default theme by teejez:
waterfall_colors = "[0x000000ff,0x0000ffff,0x00ffffff,0x00ff00ff,0xffff00ff,0xff0000ff,0xff00ffff,0xffffffff]"
waterfall_min_level = -89 #in dB
waterfall_max_level = -18
waterfall_auto_level_margin = (5, 40)
### old theme by HA7ILM:
#waterfall_colors = "[0x000000ff,0x2e6893ff, 0x69a5d0ff, 0x214b69ff, 0x9dc4e0ff, 0xfff775ff, 0xff8a8aff, 0xb20000ff]"
#waterfall_min_level = -115 #in dB
#waterfall_max_level = 0
#waterfall_auto_level_margin = (20, 30)
##For the old colors, you might also want to set [fft_voverlap_factor] to 0.

#Note: When the auto waterfall level button is clicked, the following happens:
# [waterfall_min_level] = [current_min_power_level] - [waterfall_auto_level_margin[0]]
# [waterfall_max_level] = [current_max_power_level] + [waterfall_auto_level_margin[1]]
#
# ___|____________________________________|____________________________________|____________________________________|___> signal power
# \_waterfall_auto_level_margin[0]_/ |__ current_min_power_level | \_waterfall_auto_level_margin[1]_/
# current_max_power_level __|

# 3D view settings
mathbox_waterfall_frequency_resolution = 128 #bins
mathbox_waterfall_history_length = 10 #seconds
mathbox_waterfall_colors = "[0x000000ff,0x2e6893ff, 0x69a5d0ff, 0x214b69ff, 0x9dc4e0ff, 0xfff775ff, 0xff8a8aff, 0xb20000ff]"

# === Experimental settings ===
#Warning! The settings below are very experimental.
csdr_dynamic_bufsize = False # This allows you to change the buffering mode of csdr.
csdr_print_bufsizes = False # This prints the buffer sizes used for csdr processes.
csdr_through = False # Setting this True will print out how much data is going into the DSP chains.

nmux_memory = 50 #in megabytes. This sets the approximate size of the circular buffer used by nmux.

#Look up external IP address automatically from icanhazip.com, and use it as [server_hostname]
"""
print "[openwebrx-config] Detecting external IP address..."
import urllib2
server_hostname=urllib2.urlopen("http://icanhazip.com").read()[:-1]
print "[openwebrx-config] External IP address detected:", server_hostname
"""

frp映射至公网

不用多说,这里介绍一种本人正在使用的通解通法,frp配置Nginx反向代理至frps端口来使用,下面给出Nginx虚拟主机配置文件。

注:这里7080端口为frps服务端http代理端口,映射流程大抵为域名的https 443端口反向代理至frps http的7080端口,再在frpc(旁路由或者连接至互联网的本地设备的frp客户端)中设置自定义域名,设置http协议类型,远程端口7080,并且本地端口为该程序OpenWebRX的8073端口,即可完成映射。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
server
{
listen 80;
server_name ***;

if ($scheme = http ) {
return 301 https://$host$request_uri;
}

location /{
proxy_pass http://127.0.0.1:7080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header X-Powered-By;
}

access_log /home/wwwlogs/***;
}

server
{
listen 443 ssl http2;
server_name ***;

ssl_certificate /usr/local/nginx/conf/ssl/kixcs.com/kixcs.com.cer;
ssl_certificate_key /usr/local/nginx/conf/ssl/kixcs.com/kixcs.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
ssl_session_cache builtin:1000 shared:SSL:10m;
# openssl dhparam -out /usr/local/nginx/conf/ssl/dhparam.pem 2048
ssl_dhparam /usr/local/nginx/conf/ssl/dhparam.pem;

location / {
#关于frp与Nginx配合使用的问题:https://blog.csdn.net/rfrftt/article/details/89317529
#https://www.v2ex.com/t/378393
proxy_pass http://127.0.0.1:7080/;
proxy_ssl_server_name on;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
add_header Content-Security-Policy upgrade-insecure-requests;

}

location /ws/{
proxy_pass http://127.0.0.1:7080/ws/;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
}

access_log /home/wwwlogs/***.log;
}

配置WebSockets(可选)

关于这部分内容,详细步骤可以移步开发者ha7ilm的Github仓库,在此感谢ibcl.us做出的汉化工作。

关于WebSockets,能赘述的内容实在有限,在不开启CDN的情况下无需去考虑这个问题,倘若你希望你所有的二级域名都配置CDN,那么你需要考虑你的站点所选择的CDN是否支持WebSockets这种用于服务端主动推送协议(比方说弹幕,消息推送等待),Cloudflare CDN/阿里云的全站加速DCDN,抑或是腾讯云CDN应该都可以较为完善的支持该协议。

1
2
3
4
#纵然 CloudFlare 已经要求用户与服务器通信实现底层安全协议传输,但是OpenWebRX仍然会让用户与后端建立未加密的WebSocket连接,即ws://,而不是wss://。
#所以接下来修改openwebrx.js这个文件(位于OpenWebRX目录的htdocs文件夹)第1698行,将 ws_url="ws://"+(window.location.origin.split("://")[1])+"/ws/";
#修改为 ws_url="wss://***/ws/";,这里的***填写你的域名。然后修改OpenWebRX的核心文件(位于OpenWebRX根目录)openwebrx.py,第673行,
#将ws_url="ws://"+(window.location.origin.split("://")[1])+"/ws/"; 修改为 ws_url="wss://***/ws/"; 。最后重启OpenWebRX即可。

终章

感谢OpenWebRX官方Github仓库OpenWebRX开发者,尤其感谢一位优秀的高中生小伙伴一直以来给我的热心帮助和耐心解答,同时也祝你学业有成,天天开心 :)