这个wifi解调安装起来很简单,没什么坑,就是老外按照gnuradio不同版本也分了几个版本,我下载的是3.7版本。
先安装3.7版本的gr-foo再安装gr-ieee802-11就行。
下面的安装脚本下载的是主分支的,如果要针对3.7或者3.8的,可以在网页里直接选择对应版本下载。
或者从这里下载:
链接:https://pan.baidu.com/s/1sBmPa1X2IInwJLV4qFDa3Q
提取码:udhu
这是我下载的3.7版本的
git clone https://github.com/bastibl/gr-foo.git
cd gr-foo
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfig
git clone git://github.com/bastibl/gr-ieee802-11.git
cd gr-ieee802-11
mkdir build
cd build
cmake ..
make
sudo make install
sudo ldconfig
还有一个问题,老外本来是用uhd模块做的收发,limesdr虽然能支持,但是很麻烦,osmocom也能用,但是噪声很多,我最后用的是gr-limesdr,把中心频率和采样率填进去就行,采样率还要填到几个滤波器带宽里去。
演示视频:https://www.bilibili.com/video/av73714958
我只实现了wifi接收和解调,能够看到我的路由器发出的星座图,并且可以把抓取的数据用wireshark分析数据包,我对比了gnuradio命令行输出的一些设备mac和路由器配置页面里的设备mac是一样的。但是发射还不行,如果用它的流图发射,我接收到的星座图很奇怪。老外还提供了一个transceiver流图,理论上可以用这个实现虚拟网卡和其他wifi设备做udp通信,但是我现在发射还不行,改天搞个usrp试试。
USRP B210发射:
https://www.bilibili.com/video/BV1UA411Y7b8/
不要装libuhd003.010.003,他现在配套的下载程序已经无法下载合适的firmware和gateware了。
要用新版的libuhd3.15.0,但是要添加ppa。
sudo add-apt-repository -y ppa:ettusresearch/uhd
sudo apt update
不要apt安装gnuradio,否则会自动安装libuhd003.010.003
从github下载gnuradio-maint-3.7 (3.7.13)然后编译安装
USRP B210 wifi虚拟网卡:
https://www.bilibili.com/video/BV1Sp4y1v7kq
电脑1运行:
sudo ifconfig tap0 down
sudo ifconfig tap0 hw ether 30:14:4a:e6:46:e4
sudo ifconfig tap0 mtu 440
sudo ifconfig tap0 up
sudo ifconfig tap0 192.168.123.2
sudo route del -net 192.168.123.0/24
sudo route add -net 192.168.123.0/24 mss 400 dev tap0
sudo tc qdisc add dev tap0 root netem delay 10ms
电脑1运行wifi_transceiver.py脚本
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
##################################################
# GNU Radio Python Flow Graph
# Title: Wifi Transceiver
# GNU Radio version: 3.7.13.5
##################################################
if __name__ == '__main__':
import ctypes
import sys
if sys.platform.startswith('linux'):
try:
x11 = ctypes.cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
except:
print "Warning: failed to XInitThreads()"
import os
import sys
sys.path.append(os.environ.get('GRC_HIER_PATH', os.path.expanduser('~/.grc_gnuradio')))
from PyQt4 import Qt
from PyQt4.QtCore import QObject, pyqtSlot
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio import qtgui
from gnuradio import uhd
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from gnuradio.qtgui import Range, RangeWidget
from optparse import OptionParser
from wifi_phy_hier import wifi_phy_hier # grc-generated hier_block
import foo
import ieee802_11
import sip
import time
from gnuradio import qtgui
class wifi_transceiver(gr.top_block, Qt.QWidget):
def __init__(self):
gr.top_block.__init__(self, "Wifi Transceiver")
Qt.QWidget.__init__(self)
self.setWindowTitle("Wifi Transceiver")
qtgui.util.check_set_qss()
try:
self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
except:
pass
self.top_scroll_layout = Qt.QVBoxLayout()
self.setLayout(self.top_scroll_layout)
self.top_scroll = Qt.QScrollArea()
self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
self.top_scroll_layout.addWidget(self.top_scroll)
self.top_scroll.setWidgetResizable(True)
self.top_widget = Qt.QWidget()
self.top_scroll.setWidget(self.top_widget)
self.top_layout = Qt.QVBoxLayout(self.top_widget)
self.top_grid_layout = Qt.QGridLayout()
self.top_layout.addLayout(self.top_grid_layout)
self.settings = Qt.QSettings("GNU Radio", "wifi_transceiver")
self.restoreGeometry(self.settings.value("geometry").toByteArray())
##################################################
# Variables
##################################################
self.tx_gain = tx_gain = 0.75
self.samp_rate = samp_rate = 5e6
self.rx_gain = rx_gain = 0.75
self.lo_offset = lo_offset = 0
self.freq = freq = 5890000000
self.encoding = encoding = 0
self.chan_est = chan_est = 0
##################################################
# Blocks
##################################################
self._tx_gain_range = Range(0, 1, 0.01, 0.75, 200)
self._tx_gain_win = RangeWidget(self._tx_gain_range, self.set_tx_gain, "tx_gain", "counter_slider", float)
self.top_grid_layout.addWidget(self._tx_gain_win)
self._samp_rate_options = [5e6, 10e6, 20e6]
self._samp_rate_labels = ["5 MHz", "10 MHz", "20 MHz"]
self._samp_rate_tool_bar = Qt.QToolBar(self)
self._samp_rate_tool_bar.addWidget(Qt.QLabel("samp_rate"+": "))
self._samp_rate_combo_box = Qt.QComboBox()
self._samp_rate_tool_bar.addWidget(self._samp_rate_combo_box)
for label in self._samp_rate_labels: self._samp_rate_combo_box.addItem(label)
self._samp_rate_callback = lambda i: Qt.QMetaObject.invokeMethod(self._samp_rate_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._samp_rate_options.index(i)))
self._samp_rate_callback(self.samp_rate)
self._samp_rate_combo_box.currentIndexChanged.connect(
lambda i: self.set_samp_rate(self._samp_rate_options[i]))
self.top_grid_layout.addWidget(self._samp_rate_tool_bar)
self._rx_gain_range = Range(0, 1, 0.01, 0.75, 200)
self._rx_gain_win = RangeWidget(self._rx_gain_range, self.set_rx_gain, "rx_gain", "counter_slider", float)
self.top_grid_layout.addWidget(self._rx_gain_win)
self._lo_offset_options = (0, 6e6, 11e6, )
self._lo_offset_labels = (str(self._lo_offset_options[0]), str(self._lo_offset_options[1]), str(self._lo_offset_options[2]), )
self._lo_offset_tool_bar = Qt.QToolBar(self)
self._lo_offset_tool_bar.addWidget(Qt.QLabel("lo_offset"+": "))
self._lo_offset_combo_box = Qt.QComboBox()
self._lo_offset_tool_bar.addWidget(self._lo_offset_combo_box)
for label in self._lo_offset_labels: self._lo_offset_combo_box.addItem(label)
self._lo_offset_callback = lambda i: Qt.QMetaObject.invokeMethod(self._lo_offset_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._lo_offset_options.index(i)))
self._lo_offset_callback(self.lo_offset)
self._lo_offset_combo_box.currentIndexChanged.connect(
lambda i: self.set_lo_offset(self._lo_offset_options[i]))
self.top_grid_layout.addWidget(self._lo_offset_tool_bar)
self._freq_options = [2412000000.0, 2417000000.0, 2422000000.0, 2427000000.0, 2432000000.0, 2437000000.0, 2442000000.0, 2447000000.0, 2452000000.0, 2457000000.0, 2462000000.0, 2467000000.0, 2472000000.0, 2484000000.0, 5170000000.0, 5180000000.0, 5190000000.0, 5200000000.0, 5210000000.0, 5220000000.0, 5230000000.0, 5240000000.0, 5250000000.0, 5260000000.0, 5270000000.0, 5280000000.0, 5290000000.0, 5300000000.0, 5310000000.0, 5320000000.0, 5500000000.0, 5510000000.0, 5520000000.0, 5530000000.0, 5540000000.0, 5550000000.0, 5560000000.0, 5570000000.0, 5580000000.0, 5590000000.0, 5600000000.0, 5610000000.0, 5620000000.0, 5630000000.0, 5640000000.0, 5660000000.0, 5670000000.0, 5680000000.0, 5690000000.0, 5700000000.0, 5710000000.0, 5720000000.0, 5745000000.0, 5755000000.0, 5765000000.0, 5775000000.0, 5785000000.0, 5795000000.0, 5805000000.0, 5825000000.0, 5860000000.0, 5870000000.0, 5880000000.0, 5890000000.0, 5900000000.0, 5910000000.0, 5920000000.0]
self._freq_labels = [' 1 | 2412.0 | 11g', ' 2 | 2417.0 | 11g', ' 3 | 2422.0 | 11g', ' 4 | 2427.0 | 11g', ' 5 | 2432.0 | 11g', ' 6 | 2437.0 | 11g', ' 7 | 2442.0 | 11g', ' 8 | 2447.0 | 11g', ' 9 | 2452.0 | 11g', ' 10 | 2457.0 | 11g', ' 11 | 2462.0 | 11g', ' 12 | 2467.0 | 11g', ' 13 | 2472.0 | 11g', ' 14 | 2484.0 | 11g', ' 34 | 5170.0 | 11a', ' 36 | 5180.0 | 11a', ' 38 | 5190.0 | 11a', ' 40 | 5200.0 | 11a', ' 42 | 5210.0 | 11a', ' 44 | 5220.0 | 11a', ' 46 | 5230.0 | 11a', ' 48 | 5240.0 | 11a', ' 50 | 5250.0 | 11a', ' 52 | 5260.0 | 11a', ' 54 | 5270.0 | 11a', ' 56 | 5280.0 | 11a', ' 58 | 5290.0 | 11a', ' 60 | 5300.0 | 11a', ' 62 | 5310.0 | 11a', ' 64 | 5320.0 | 11a', '100 | 5500.0 | 11a', '102 | 5510.0 | 11a', '104 | 5520.0 | 11a', '106 | 5530.0 | 11a', '108 | 5540.0 | 11a', '110 | 5550.0 | 11a', '112 | 5560.0 | 11a', '114 | 5570.0 | 11a', '116 | 5580.0 | 11a', '118 | 5590.0 | 11a', '120 | 5600.0 | 11a', '122 | 5610.0 | 11a', '124 | 5620.0 | 11a', '126 | 5630.0 | 11a', '128 | 5640.0 | 11a', '132 | 5660.0 | 11a', '134 | 5670.0 | 11a', '136 | 5680.0 | 11a', '138 | 5690.0 | 11a', '140 | 5700.0 | 11a', '142 | 5710.0 | 11a', '144 | 5720.0 | 11a', '149 | 5745.0 | 11a (SRD)', '151 | 5755.0 | 11a (SRD)', '153 | 5765.0 | 11a (SRD)', '155 | 5775.0 | 11a (SRD)', '157 | 5785.0 | 11a (SRD)', '159 | 5795.0 | 11a (SRD)', '161 | 5805.0 | 11a (SRD)', '165 | 5825.0 | 11a (SRD)', '172 | 5860.0 | 11p', '174 | 5870.0 | 11p', '176 | 5880.0 | 11p', '178 | 5890.0 | 11p', '180 | 5900.0 | 11p', '182 | 5910.0 | 11p', '184 | 5920.0 | 11p']
self._freq_tool_bar = Qt.QToolBar(self)
self._freq_tool_bar.addWidget(Qt.QLabel("freq"+": "))
self._freq_combo_box = Qt.QComboBox()
self._freq_tool_bar.addWidget(self._freq_combo_box)
for label in self._freq_labels: self._freq_combo_box.addItem(label)
self._freq_callback = lambda i: Qt.QMetaObject.invokeMethod(self._freq_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._freq_options.index(i)))
self._freq_callback(self.freq)
self._freq_combo_box.currentIndexChanged.connect(
lambda i: self.set_freq(self._freq_options[i]))
self.top_grid_layout.addWidget(self._freq_tool_bar)
self._encoding_options = [0, 1, 2, 3, 4, 5, 6, 7]
self._encoding_labels = ["BPSK 1/2", "BPSK 3/4", "QPSK 1/2", "QPSK 3/4", "16QAM 1/2", "16QAM 3/4", "64QAM 2/3", "64QAM 3/4"]
self._encoding_group_box = Qt.QGroupBox("encoding")
self._encoding_box = Qt.QHBoxLayout()
class variable_chooser_button_group(Qt.QButtonGroup):
def __init__(self, parent=None):
Qt.QButtonGroup.__init__(self, parent)
@pyqtSlot(int)
def updateButtonChecked(self, button_id):
self.button(button_id).setChecked(True)
self._encoding_button_group = variable_chooser_button_group()
self._encoding_group_box.setLayout(self._encoding_box)
for i, label in enumerate(self._encoding_labels):
radio_button = Qt.QRadioButton(label)
self._encoding_box.addWidget(radio_button)
self._encoding_button_group.addButton(radio_button, i)
self._encoding_callback = lambda i: Qt.QMetaObject.invokeMethod(self._encoding_button_group, "updateButtonChecked", Qt.Q_ARG("int", self._encoding_options.index(i)))
self._encoding_callback(self.encoding)
self._encoding_button_group.buttonClicked[int].connect(
lambda i: self.set_encoding(self._encoding_options[i]))
self.top_grid_layout.addWidget(self._encoding_group_box)
self._chan_est_options = [ieee802_11.LS, ieee802_11.LMS, ieee802_11.STA, ieee802_11.COMB]
self._chan_est_labels = ["LS", "LMS", "STA", "Linear Comb"]
self._chan_est_group_box = Qt.QGroupBox("chan_est")
self._chan_est_box = Qt.QHBoxLayout()
class variable_chooser_button_group(Qt.QButtonGroup):
def __init__(self, parent=None):
Qt.QButtonGroup.__init__(self, parent)
@pyqtSlot(int)
def updateButtonChecked(self, button_id):
self.button(button_id).setChecked(True)
self._chan_est_button_group = variable_chooser_button_group()
self._chan_est_group_box.setLayout(self._chan_est_box)
for i, label in enumerate(self._chan_est_labels):
radio_button = Qt.QRadioButton(label)
self._chan_est_box.addWidget(radio_button)
self._chan_est_button_group.addButton(radio_button, i)
self._chan_est_callback = lambda i: Qt.QMetaObject.invokeMethod(self._chan_est_button_group, "updateButtonChecked", Qt.Q_ARG("int", self._chan_est_options.index(i)))
self._chan_est_callback(self.chan_est)
self._chan_est_button_group.buttonClicked[int].connect(
lambda i: self.set_chan_est(self._chan_est_options[i]))
self.top_grid_layout.addWidget(self._chan_est_group_box)
self.wifi_phy_hier_0 = wifi_phy_hier(
bandwidth=samp_rate,
chan_est=chan_est,
encoding=encoding,
frequency=freq,
sensitivity=0.56,
)
self.uhd_usrp_source_0 = uhd.usrp_source(
",".join(('', "")),
uhd.stream_args(
cpu_format="fc32",
channels=range(1),
),
)
self.uhd_usrp_source_0.set_samp_rate(samp_rate)
self.uhd_usrp_source_0.set_time_now(uhd.time_spec(time.time()), uhd.ALL_MBOARDS)
self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(freq, rf_freq = freq - lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
self.uhd_usrp_source_0.set_normalized_gain(rx_gain, 0)
#self.uhd_usrp_source_0.set_auto_dc_offset("", 0)
#self.uhd_usrp_source_0.set_auto_iq_balance("", 0)
self.uhd_usrp_sink_0 = uhd.usrp_sink(
",".join(('', "")),
uhd.stream_args(
cpu_format="fc32",
channels=range(1),
),
'packet_len',
)
self.uhd_usrp_sink_0.set_samp_rate(samp_rate)
self.uhd_usrp_sink_0.set_time_now(uhd.time_spec(time.time()), uhd.ALL_MBOARDS)
self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(freq, rf_freq = freq - lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
self.uhd_usrp_sink_0.set_normalized_gain(tx_gain, 0)
self.qtgui_const_sink_x_0 = qtgui.const_sink_c(
48*10, #size
"", #name
1 #number of inputs
)
self.qtgui_const_sink_x_0.set_update_time(0.10)
self.qtgui_const_sink_x_0.set_y_axis(-2, 2)
self.qtgui_const_sink_x_0.set_x_axis(-2, 2)
self.qtgui_const_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, "")
self.qtgui_const_sink_x_0.enable_autoscale(False)
self.qtgui_const_sink_x_0.enable_grid(False)
self.qtgui_const_sink_x_0.enable_axis_labels(True)
if not True:
self.qtgui_const_sink_x_0.disable_legend()
labels = ['', '', '', '', '',
'', '', '', '', '']
widths = [1, 1, 1, 1, 1,
1, 1, 1, 1, 1]
colors = ["blue", "red", "red", "red", "red",
"red", "red", "red", "red", "red"]
styles = [0, 0, 0, 0, 0,
0, 0, 0, 0, 0]
markers = [0, 0, 0, 0, 0,
0, 0, 0, 0, 0]
alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0]
for i in xrange(1):
if len(labels[i]) == 0:
self.qtgui_const_sink_x_0.set_line_label(i, "Data {0}".format(i))
else:
self.qtgui_const_sink_x_0.set_line_label(i, labels[i])
self.qtgui_const_sink_x_0.set_line_width(i, widths[i])
self.qtgui_const_sink_x_0.set_line_color(i, colors[i])
self.qtgui_const_sink_x_0.set_line_style(i, styles[i])
self.qtgui_const_sink_x_0.set_line_marker(i, markers[i])
self.qtgui_const_sink_x_0.set_line_alpha(i, alphas[i])
self._qtgui_const_sink_x_0_win = sip.wrapinstance(self.qtgui_const_sink_x_0.pyqwidget(), Qt.QWidget)
self.top_grid_layout.addWidget(self._qtgui_const_sink_x_0_win)
self.ieee802_11_parse_mac_0 = ieee802_11.parse_mac(False, True)
self.ieee802_11_mac_0 = ieee802_11.mac(([0x30, 0x14, 0x4a, 0xe6, 0x46, 0xe4]), ([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]), ([0x42, 0x42, 0x42, 0x42, 0x42, 0x42]))
self.ieee802_11_ether_encap_0 = ieee802_11.ether_encap(False)
self.foo_packet_pad2_0 = foo.packet_pad2(False, False, 0.001, 10000, 10000)
(self.foo_packet_pad2_0).set_min_output_buffer(100000)
self.blocks_tuntap_pdu_0 = blocks.tuntap_pdu('tap0', 440, False)
self.blocks_pdu_to_tagged_stream_0_0 = blocks.pdu_to_tagged_stream(blocks.complex_t, 'packet_len')
self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vcc((0.6, ))
(self.blocks_multiply_const_vxx_0).set_min_output_buffer(100000)
##################################################
# Connections
##################################################
self.msg_connect((self.blocks_tuntap_pdu_0, 'pdus'), (self.ieee802_11_ether_encap_0, 'from tap'))
self.msg_connect((self.ieee802_11_ether_encap_0, 'to tap'), (self.blocks_tuntap_pdu_0, 'pdus'))
self.msg_connect((self.ieee802_11_ether_encap_0, 'to wifi'), (self.ieee802_11_mac_0, 'app in'))
self.msg_connect((self.ieee802_11_mac_0, 'phy out'), (self.wifi_phy_hier_0, 'mac_in'))
self.msg_connect((self.wifi_phy_hier_0, 'carrier'), (self.blocks_pdu_to_tagged_stream_0_0, 'pdus'))
self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_ether_encap_0, 'from wifi'))
self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_mac_0, 'phy in'))
self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_parse_mac_0, 'in'))
self.connect((self.blocks_multiply_const_vxx_0, 0), (self.foo_packet_pad2_0, 0))
self.connect((self.blocks_pdu_to_tagged_stream_0_0, 0), (self.qtgui_const_sink_x_0, 0))
self.connect((self.foo_packet_pad2_0, 0), (self.uhd_usrp_sink_0, 0))
self.connect((self.uhd_usrp_source_0, 0), (self.wifi_phy_hier_0, 0))
self.connect((self.wifi_phy_hier_0, 0), (self.blocks_multiply_const_vxx_0, 0))
def closeEvent(self, event):
self.settings = Qt.QSettings("GNU Radio", "wifi_transceiver")
self.settings.setValue("geometry", self.saveGeometry())
event.accept()
def get_tx_gain(self):
return self.tx_gain
def set_tx_gain(self, tx_gain):
self.tx_gain = tx_gain
self.uhd_usrp_sink_0.set_normalized_gain(self.tx_gain, 0)
def get_samp_rate(self):
return self.samp_rate
def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate
self._samp_rate_callback(self.samp_rate)
self.wifi_phy_hier_0.set_bandwidth(self.samp_rate)
self.uhd_usrp_source_0.set_samp_rate(self.samp_rate)
self.uhd_usrp_sink_0.set_samp_rate(self.samp_rate)
def get_rx_gain(self):
return self.rx_gain
def set_rx_gain(self, rx_gain):
self.rx_gain = rx_gain
self.uhd_usrp_source_0.set_normalized_gain(self.rx_gain, 0)
def get_lo_offset(self):
return self.lo_offset
def set_lo_offset(self, lo_offset):
self.lo_offset = lo_offset
self._lo_offset_callback(self.lo_offset)
self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
def get_freq(self):
return self.freq
def set_freq(self, freq):
self.freq = freq
self._freq_callback(self.freq)
self.wifi_phy_hier_0.set_frequency(self.freq)
self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
def get_encoding(self):
return self.encoding
def set_encoding(self, encoding):
self.encoding = encoding
self._encoding_callback(self.encoding)
self.wifi_phy_hier_0.set_encoding(self.encoding)
def get_chan_est(self):
return self.chan_est
def set_chan_est(self, chan_est):
self.chan_est = chan_est
self._chan_est_callback(self.chan_est)
self.wifi_phy_hier_0.set_chan_est(self.chan_est)
def main(top_block_cls=wifi_transceiver, options=None):
from distutils.version import StrictVersion
if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
style = gr.prefs().get_string('qtgui', 'style', 'raster')
Qt.QApplication.setGraphicsSystem(style)
qapp = Qt.QApplication(sys.argv)
tb = top_block_cls()
tb.start()
tb.show()
def quitting():
tb.stop()
tb.wait()
qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
qapp.exec_()
if __name__ == '__main__':
main()
最后,电脑1命令行再运行:
sudo arp -s 192.168.123.1 12:34:56:78:90:ab
电脑2命令行运行:
sudo ifconfig tap0 down
sudo ifconfig tap0 hw ether 12:34:56:78:90:ab
sudo ifconfig tap0 mtu 440
sudo ifconfig tap0 up
sudo ifconfig tap0 192.168.123.1
sudo route del -net 192.168.123.0/24
sudo route add -net 192.168.123.0/24 mss 400 dev tap0
sudo tc qdisc del dev tap0 root
sudo tc qdisc add dev tap0 root netem delay 10ms
电脑2运行wifi_transceiver.py脚本
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
##################################################
# GNU Radio Python Flow Graph
# Title: Wifi Transceiver
# GNU Radio version: 3.7.13.5
##################################################
if __name__ == '__main__':
import ctypes
import sys
if sys.platform.startswith('linux'):
try:
x11 = ctypes.cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
except:
print "Warning: failed to XInitThreads()"
import os
import sys
sys.path.append(os.environ.get('GRC_HIER_PATH', os.path.expanduser('~/.grc_gnuradio')))
from PyQt4 import Qt
from PyQt4.QtCore import QObject, pyqtSlot
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import gr
from gnuradio import qtgui
from gnuradio import uhd
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from gnuradio.qtgui import Range, RangeWidget
from optparse import OptionParser
from wifi_phy_hier import wifi_phy_hier # grc-generated hier_block
import foo
import ieee802_11
import sip
import time
from gnuradio import qtgui
class wifi_transceiver(gr.top_block, Qt.QWidget):
def __init__(self):
gr.top_block.__init__(self, "Wifi Transceiver")
Qt.QWidget.__init__(self)
self.setWindowTitle("Wifi Transceiver")
qtgui.util.check_set_qss()
try:
self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
except:
pass
self.top_scroll_layout = Qt.QVBoxLayout()
self.setLayout(self.top_scroll_layout)
self.top_scroll = Qt.QScrollArea()
self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
self.top_scroll_layout.addWidget(self.top_scroll)
self.top_scroll.setWidgetResizable(True)
self.top_widget = Qt.QWidget()
self.top_scroll.setWidget(self.top_widget)
self.top_layout = Qt.QVBoxLayout(self.top_widget)
self.top_grid_layout = Qt.QGridLayout()
self.top_layout.addLayout(self.top_grid_layout)
self.settings = Qt.QSettings("GNU Radio", "wifi_transceiver")
self.restoreGeometry(self.settings.value("geometry").toByteArray())
##################################################
# Variables
##################################################
self.tx_gain = tx_gain = 0.75
self.samp_rate = samp_rate = 5e6
self.rx_gain = rx_gain = 0.75
self.lo_offset = lo_offset = 0
self.freq = freq = 5890000000
self.encoding = encoding = 0
self.chan_est = chan_est = 0
##################################################
# Blocks
##################################################
self._tx_gain_range = Range(0, 1, 0.01, 0.75, 200)
self._tx_gain_win = RangeWidget(self._tx_gain_range, self.set_tx_gain, "tx_gain", "counter_slider", float)
self.top_grid_layout.addWidget(self._tx_gain_win)
self._samp_rate_options = [5e6, 10e6, 20e6]
self._samp_rate_labels = ["5 MHz", "10 MHz", "20 MHz"]
self._samp_rate_tool_bar = Qt.QToolBar(self)
self._samp_rate_tool_bar.addWidget(Qt.QLabel("samp_rate"+": "))
self._samp_rate_combo_box = Qt.QComboBox()
self._samp_rate_tool_bar.addWidget(self._samp_rate_combo_box)
for label in self._samp_rate_labels: self._samp_rate_combo_box.addItem(label)
self._samp_rate_callback = lambda i: Qt.QMetaObject.invokeMethod(self._samp_rate_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._samp_rate_options.index(i)))
self._samp_rate_callback(self.samp_rate)
self._samp_rate_combo_box.currentIndexChanged.connect(
lambda i: self.set_samp_rate(self._samp_rate_options[i]))
self.top_grid_layout.addWidget(self._samp_rate_tool_bar)
self._rx_gain_range = Range(0, 1, 0.01, 0.75, 200)
self._rx_gain_win = RangeWidget(self._rx_gain_range, self.set_rx_gain, "rx_gain", "counter_slider", float)
self.top_grid_layout.addWidget(self._rx_gain_win)
self._lo_offset_options = (0, 6e6, 11e6, )
self._lo_offset_labels = (str(self._lo_offset_options[0]), str(self._lo_offset_options[1]), str(self._lo_offset_options[2]), )
self._lo_offset_tool_bar = Qt.QToolBar(self)
self._lo_offset_tool_bar.addWidget(Qt.QLabel("lo_offset"+": "))
self._lo_offset_combo_box = Qt.QComboBox()
self._lo_offset_tool_bar.addWidget(self._lo_offset_combo_box)
for label in self._lo_offset_labels: self._lo_offset_combo_box.addItem(label)
self._lo_offset_callback = lambda i: Qt.QMetaObject.invokeMethod(self._lo_offset_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._lo_offset_options.index(i)))
self._lo_offset_callback(self.lo_offset)
self._lo_offset_combo_box.currentIndexChanged.connect(
lambda i: self.set_lo_offset(self._lo_offset_options[i]))
self.top_grid_layout.addWidget(self._lo_offset_tool_bar)
self._freq_options = [2412000000.0, 2417000000.0, 2422000000.0, 2427000000.0, 2432000000.0, 2437000000.0, 2442000000.0, 2447000000.0, 2452000000.0, 2457000000.0, 2462000000.0, 2467000000.0, 2472000000.0, 2484000000.0, 5170000000.0, 5180000000.0, 5190000000.0, 5200000000.0, 5210000000.0, 5220000000.0, 5230000000.0, 5240000000.0, 5250000000.0, 5260000000.0, 5270000000.0, 5280000000.0, 5290000000.0, 5300000000.0, 5310000000.0, 5320000000.0, 5500000000.0, 5510000000.0, 5520000000.0, 5530000000.0, 5540000000.0, 5550000000.0, 5560000000.0, 5570000000.0, 5580000000.0, 5590000000.0, 5600000000.0, 5610000000.0, 5620000000.0, 5630000000.0, 5640000000.0, 5660000000.0, 5670000000.0, 5680000000.0, 5690000000.0, 5700000000.0, 5710000000.0, 5720000000.0, 5745000000.0, 5755000000.0, 5765000000.0, 5775000000.0, 5785000000.0, 5795000000.0, 5805000000.0, 5825000000.0, 5860000000.0, 5870000000.0, 5880000000.0, 5890000000.0, 5900000000.0, 5910000000.0, 5920000000.0]
self._freq_labels = [' 1 | 2412.0 | 11g', ' 2 | 2417.0 | 11g', ' 3 | 2422.0 | 11g', ' 4 | 2427.0 | 11g', ' 5 | 2432.0 | 11g', ' 6 | 2437.0 | 11g', ' 7 | 2442.0 | 11g', ' 8 | 2447.0 | 11g', ' 9 | 2452.0 | 11g', ' 10 | 2457.0 | 11g', ' 11 | 2462.0 | 11g', ' 12 | 2467.0 | 11g', ' 13 | 2472.0 | 11g', ' 14 | 2484.0 | 11g', ' 34 | 5170.0 | 11a', ' 36 | 5180.0 | 11a', ' 38 | 5190.0 | 11a', ' 40 | 5200.0 | 11a', ' 42 | 5210.0 | 11a', ' 44 | 5220.0 | 11a', ' 46 | 5230.0 | 11a', ' 48 | 5240.0 | 11a', ' 50 | 5250.0 | 11a', ' 52 | 5260.0 | 11a', ' 54 | 5270.0 | 11a', ' 56 | 5280.0 | 11a', ' 58 | 5290.0 | 11a', ' 60 | 5300.0 | 11a', ' 62 | 5310.0 | 11a', ' 64 | 5320.0 | 11a', '100 | 5500.0 | 11a', '102 | 5510.0 | 11a', '104 | 5520.0 | 11a', '106 | 5530.0 | 11a', '108 | 5540.0 | 11a', '110 | 5550.0 | 11a', '112 | 5560.0 | 11a', '114 | 5570.0 | 11a', '116 | 5580.0 | 11a', '118 | 5590.0 | 11a', '120 | 5600.0 | 11a', '122 | 5610.0 | 11a', '124 | 5620.0 | 11a', '126 | 5630.0 | 11a', '128 | 5640.0 | 11a', '132 | 5660.0 | 11a', '134 | 5670.0 | 11a', '136 | 5680.0 | 11a', '138 | 5690.0 | 11a', '140 | 5700.0 | 11a', '142 | 5710.0 | 11a', '144 | 5720.0 | 11a', '149 | 5745.0 | 11a (SRD)', '151 | 5755.0 | 11a (SRD)', '153 | 5765.0 | 11a (SRD)', '155 | 5775.0 | 11a (SRD)', '157 | 5785.0 | 11a (SRD)', '159 | 5795.0 | 11a (SRD)', '161 | 5805.0 | 11a (SRD)', '165 | 5825.0 | 11a (SRD)', '172 | 5860.0 | 11p', '174 | 5870.0 | 11p', '176 | 5880.0 | 11p', '178 | 5890.0 | 11p', '180 | 5900.0 | 11p', '182 | 5910.0 | 11p', '184 | 5920.0 | 11p']
self._freq_tool_bar = Qt.QToolBar(self)
self._freq_tool_bar.addWidget(Qt.QLabel("freq"+": "))
self._freq_combo_box = Qt.QComboBox()
self._freq_tool_bar.addWidget(self._freq_combo_box)
for label in self._freq_labels: self._freq_combo_box.addItem(label)
self._freq_callback = lambda i: Qt.QMetaObject.invokeMethod(self._freq_combo_box, "setCurrentIndex", Qt.Q_ARG("int", self._freq_options.index(i)))
self._freq_callback(self.freq)
self._freq_combo_box.currentIndexChanged.connect(
lambda i: self.set_freq(self._freq_options[i]))
self.top_grid_layout.addWidget(self._freq_tool_bar)
self._encoding_options = [0, 1, 2, 3, 4, 5, 6, 7]
self._encoding_labels = ["BPSK 1/2", "BPSK 3/4", "QPSK 1/2", "QPSK 3/4", "16QAM 1/2", "16QAM 3/4", "64QAM 2/3", "64QAM 3/4"]
self._encoding_group_box = Qt.QGroupBox("encoding")
self._encoding_box = Qt.QHBoxLayout()
class variable_chooser_button_group(Qt.QButtonGroup):
def __init__(self, parent=None):
Qt.QButtonGroup.__init__(self, parent)
@pyqtSlot(int)
def updateButtonChecked(self, button_id):
self.button(button_id).setChecked(True)
self._encoding_button_group = variable_chooser_button_group()
self._encoding_group_box.setLayout(self._encoding_box)
for i, label in enumerate(self._encoding_labels):
radio_button = Qt.QRadioButton(label)
self._encoding_box.addWidget(radio_button)
self._encoding_button_group.addButton(radio_button, i)
self._encoding_callback = lambda i: Qt.QMetaObject.invokeMethod(self._encoding_button_group, "updateButtonChecked", Qt.Q_ARG("int", self._encoding_options.index(i)))
self._encoding_callback(self.encoding)
self._encoding_button_group.buttonClicked[int].connect(
lambda i: self.set_encoding(self._encoding_options[i]))
self.top_grid_layout.addWidget(self._encoding_group_box)
self._chan_est_options = [ieee802_11.LS, ieee802_11.LMS, ieee802_11.STA, ieee802_11.COMB]
self._chan_est_labels = ["LS", "LMS", "STA", "Linear Comb"]
self._chan_est_group_box = Qt.QGroupBox("chan_est")
self._chan_est_box = Qt.QHBoxLayout()
class variable_chooser_button_group(Qt.QButtonGroup):
def __init__(self, parent=None):
Qt.QButtonGroup.__init__(self, parent)
@pyqtSlot(int)
def updateButtonChecked(self, button_id):
self.button(button_id).setChecked(True)
self._chan_est_button_group = variable_chooser_button_group()
self._chan_est_group_box.setLayout(self._chan_est_box)
for i, label in enumerate(self._chan_est_labels):
radio_button = Qt.QRadioButton(label)
self._chan_est_box.addWidget(radio_button)
self._chan_est_button_group.addButton(radio_button, i)
self._chan_est_callback = lambda i: Qt.QMetaObject.invokeMethod(self._chan_est_button_group, "updateButtonChecked", Qt.Q_ARG("int", self._chan_est_options.index(i)))
self._chan_est_callback(self.chan_est)
self._chan_est_button_group.buttonClicked[int].connect(
lambda i: self.set_chan_est(self._chan_est_options[i]))
self.top_grid_layout.addWidget(self._chan_est_group_box)
self.wifi_phy_hier_0 = wifi_phy_hier(
bandwidth=samp_rate,
chan_est=chan_est,
encoding=encoding,
frequency=freq,
sensitivity=0.56,
)
self.uhd_usrp_source_0 = uhd.usrp_source(
",".join(('', "")),
uhd.stream_args(
cpu_format="fc32",
channels=range(1),
),
)
self.uhd_usrp_source_0.set_samp_rate(samp_rate)
self.uhd_usrp_source_0.set_time_now(uhd.time_spec(time.time()), uhd.ALL_MBOARDS)
self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(freq, rf_freq = freq - lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
self.uhd_usrp_source_0.set_normalized_gain(rx_gain, 0)
#self.uhd_usrp_source_0.set_auto_dc_offset("", 0)
#self.uhd_usrp_source_0.set_auto_iq_balance("", 0)
self.uhd_usrp_sink_0 = uhd.usrp_sink(
",".join(('', "")),
uhd.stream_args(
cpu_format="fc32",
channels=range(1),
),
'packet_len',
)
self.uhd_usrp_sink_0.set_samp_rate(samp_rate)
self.uhd_usrp_sink_0.set_time_now(uhd.time_spec(time.time()), uhd.ALL_MBOARDS)
self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(freq, rf_freq = freq - lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
self.uhd_usrp_sink_0.set_normalized_gain(tx_gain, 0)
self.qtgui_const_sink_x_0 = qtgui.const_sink_c(
48*10, #size
"", #name
1 #number of inputs
)
self.qtgui_const_sink_x_0.set_update_time(0.10)
self.qtgui_const_sink_x_0.set_y_axis(-2, 2)
self.qtgui_const_sink_x_0.set_x_axis(-2, 2)
self.qtgui_const_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, "")
self.qtgui_const_sink_x_0.enable_autoscale(False)
self.qtgui_const_sink_x_0.enable_grid(False)
self.qtgui_const_sink_x_0.enable_axis_labels(True)
if not True:
self.qtgui_const_sink_x_0.disable_legend()
labels = ['', '', '', '', '',
'', '', '', '', '']
widths = [1, 1, 1, 1, 1,
1, 1, 1, 1, 1]
colors = ["blue", "red", "red", "red", "red",
"red", "red", "red", "red", "red"]
styles = [0, 0, 0, 0, 0,
0, 0, 0, 0, 0]
markers = [0, 0, 0, 0, 0,
0, 0, 0, 0, 0]
alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0]
for i in xrange(1):
if len(labels[i]) == 0:
self.qtgui_const_sink_x_0.set_line_label(i, "Data {0}".format(i))
else:
self.qtgui_const_sink_x_0.set_line_label(i, labels[i])
self.qtgui_const_sink_x_0.set_line_width(i, widths[i])
self.qtgui_const_sink_x_0.set_line_color(i, colors[i])
self.qtgui_const_sink_x_0.set_line_style(i, styles[i])
self.qtgui_const_sink_x_0.set_line_marker(i, markers[i])
self.qtgui_const_sink_x_0.set_line_alpha(i, alphas[i])
self._qtgui_const_sink_x_0_win = sip.wrapinstance(self.qtgui_const_sink_x_0.pyqwidget(), Qt.QWidget)
self.top_grid_layout.addWidget(self._qtgui_const_sink_x_0_win)
self.ieee802_11_parse_mac_0 = ieee802_11.parse_mac(False, True)
self.ieee802_11_mac_0 = ieee802_11.mac(([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]), ([0x30, 0x14, 0x4a, 0xe6, 0x46, 0xe4]), ([0x42, 0x42, 0x42, 0x42, 0x42, 0x42]))
self.ieee802_11_ether_encap_0 = ieee802_11.ether_encap(False)
self.foo_wireshark_connector_0 = foo.wireshark_connector(127, False)
self.foo_packet_pad2_0 = foo.packet_pad2(False, False, 0.001, 10000, 10000)
(self.foo_packet_pad2_0).set_min_output_buffer(100000)
self.blocks_tuntap_pdu_0 = blocks.tuntap_pdu('tap0', 440, False)
self.blocks_pdu_to_tagged_stream_0_0 = blocks.pdu_to_tagged_stream(blocks.complex_t, 'packet_len')
self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vcc((0.6, ))
(self.blocks_multiply_const_vxx_0).set_min_output_buffer(100000)
self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_char*1, '/tmp/wifi.pcap', True)
self.blocks_file_sink_0.set_unbuffered(True)
##################################################
# Connections
##################################################
self.msg_connect((self.blocks_tuntap_pdu_0, 'pdus'), (self.ieee802_11_ether_encap_0, 'from tap'))
self.msg_connect((self.ieee802_11_ether_encap_0, 'to tap'), (self.blocks_tuntap_pdu_0, 'pdus'))
self.msg_connect((self.ieee802_11_ether_encap_0, 'to wifi'), (self.ieee802_11_mac_0, 'app in'))
self.msg_connect((self.ieee802_11_mac_0, 'phy out'), (self.wifi_phy_hier_0, 'mac_in'))
self.msg_connect((self.wifi_phy_hier_0, 'carrier'), (self.blocks_pdu_to_tagged_stream_0_0, 'pdus'))
self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.foo_wireshark_connector_0, 'in'))
self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_ether_encap_0, 'from wifi'))
self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_mac_0, 'phy in'))
self.msg_connect((self.wifi_phy_hier_0, 'mac_out'), (self.ieee802_11_parse_mac_0, 'in'))
self.connect((self.blocks_multiply_const_vxx_0, 0), (self.foo_packet_pad2_0, 0))
self.connect((self.blocks_pdu_to_tagged_stream_0_0, 0), (self.qtgui_const_sink_x_0, 0))
self.connect((self.foo_packet_pad2_0, 0), (self.uhd_usrp_sink_0, 0))
self.connect((self.foo_wireshark_connector_0, 0), (self.blocks_file_sink_0, 0))
self.connect((self.uhd_usrp_source_0, 0), (self.wifi_phy_hier_0, 0))
self.connect((self.wifi_phy_hier_0, 0), (self.blocks_multiply_const_vxx_0, 0))
def closeEvent(self, event):
self.settings = Qt.QSettings("GNU Radio", "wifi_transceiver")
self.settings.setValue("geometry", self.saveGeometry())
event.accept()
def get_tx_gain(self):
return self.tx_gain
def set_tx_gain(self, tx_gain):
self.tx_gain = tx_gain
self.uhd_usrp_sink_0.set_normalized_gain(self.tx_gain, 0)
def get_samp_rate(self):
return self.samp_rate
def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate
self._samp_rate_callback(self.samp_rate)
self.wifi_phy_hier_0.set_bandwidth(self.samp_rate)
self.uhd_usrp_source_0.set_samp_rate(self.samp_rate)
self.uhd_usrp_sink_0.set_samp_rate(self.samp_rate)
def get_rx_gain(self):
return self.rx_gain
def set_rx_gain(self, rx_gain):
self.rx_gain = rx_gain
self.uhd_usrp_source_0.set_normalized_gain(self.rx_gain, 0)
def get_lo_offset(self):
return self.lo_offset
def set_lo_offset(self, lo_offset):
self.lo_offset = lo_offset
self._lo_offset_callback(self.lo_offset)
self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
def get_freq(self):
return self.freq
def set_freq(self, freq):
self.freq = freq
self._freq_callback(self.freq)
self.wifi_phy_hier_0.set_frequency(self.freq)
self.uhd_usrp_source_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
self.uhd_usrp_sink_0.set_center_freq(uhd.tune_request(self.freq, rf_freq = self.freq - self.lo_offset, rf_freq_policy=uhd.tune_request.POLICY_MANUAL), 0)
def get_encoding(self):
return self.encoding
def set_encoding(self, encoding):
self.encoding = encoding
self._encoding_callback(self.encoding)
self.wifi_phy_hier_0.set_encoding(self.encoding)
def get_chan_est(self):
return self.chan_est
def set_chan_est(self, chan_est):
self.chan_est = chan_est
self._chan_est_callback(self.chan_est)
self.wifi_phy_hier_0.set_chan_est(self.chan_est)
def main(top_block_cls=wifi_transceiver, options=None):
from distutils.version import StrictVersion
if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
style = gr.prefs().get_string('qtgui', 'style', 'raster')
Qt.QApplication.setGraphicsSystem(style)
qapp = Qt.QApplication(sys.argv)
tb = top_block_cls()
tb.start()
tb.show()
def quitting():
tb.stop()
tb.wait()
qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
qapp.exec_()
if __name__ == '__main__':
main()
最后电脑2运行:
sudo arp -s 192.168.123.2 30:14:4a:e6:46:e4
两个电脑运行的东西都差不多,主要是ip和mac不一样,另外wifi_transceiver里的dst和src的mac地址也要调换一下。
HackRF接收
如果你没有LimeSDR或者USRP这些昂贵的设备,你也可以用HackRF来接收WiFi数据包。
它的DC offset比较大,所以不能直接用wifi_rx.grc流图,而是要在osmocom source后面接一个FFT Filter实现的高通滤波器。如下图:
然后你保持采样率20MHz不变,耐心地切换各个中心频点,直到观察到类似上面的QAM图形或者2PSK图像就说明能解出数据包了。
这时回到gnuradio界面,左下角会有数据包里对应的Mac地址信息。
流图下载:
https://github.com/bastibl/gr-ieee802-11/files/6813359/wifi_rx_hackrf.zip