ubuntu linux 控制wifi功能 dbus控制
dbus 控制wifi功能
原理:ubuntu系统自带的NetworkManager 守护进程专门接管了系统网络的功能,避免了用户手动写代码调用系统函数驱动来间接操作硬件。
所以有这个NetworkManager来管理这个这部分网络功能,并且提供dbus通信,让各个应用来共享该功能,避免了各个不同的应用都控制该功能导致冲突。
⚠️ 重要前提:
- 你的系统使用 NetworkManager(检查:
systemctl is-active NetworkManager
应为 active)- 你有无线网卡,设备名如
wlan0
(可通过ip link
或nmcli device
查看,但后者是工具,我们尽量不用)- 所有命令需在终端以普通用户或 root 执行(部分需 root,我会标注)
🎯 1. 开启 WiFi(启用无线射频)
dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager \org.freedesktop.DBus.Properties.Set \string:"org.freedesktop.NetworkManager" \string:"WirelessEnabled" \variant:boolean:true
🎯 2. 关闭 WiFi(禁用无线射频)
dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager \org.freedesktop.DBus.Properties.Set \string:"org.freedesktop.NetworkManager" \string:"WirelessEnabled" \variant:boolean:false
🎯 3. 连接指定的 WiFi(SSID + 密码)
这需要 3 步:
Step 1️⃣:扫描 WiFi(可选,确保目标 AP 可见)
该命令行相当于查看当前的网络设备有哪些
dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager \org.freedesktop.NetworkManager.GetDevices
从返回结果中找到你的无线设备路径,比如:/org/freedesktop/NetworkManager/Devices/3
dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager/Devices/7 \org.freedesktop.DBus.Properties.Get \string:"org.freedesktop.NetworkManager.Device" \string:"Interface"
它会告诉你 /Devices/7 对应的名字(比如 docker0 或 virbr0)。
方法 2:用 dbus-send 查类型
dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager/Devices/3 \org.freedesktop.DBus.Properties.Get \string:"org.freedesktop.NetworkManager.Device" \string:"DeviceType"# 返回值是一个数字:
| 数字 | 类型 |
| -- | --------------------------------------------------- |
| 0 | Unknown |
| 1 | Ethernet |
| 2 | Wi-Fi (802.11 wireless LAN) |
| 3 | Unused (保持兼容) |
| 5 | Bridge |
| 6 | VLAN |
| 7 | Modem (GSM/UMTS/LTE, CDMA, etc.) ← 📡 就是 4G/USB 上网卡 |
| 8 | Infiniband |
| 9 | Bond |
| 10 | Veth |
| 11 | Macvlan |
| 12 | VXLAN |
| 13 | VethPair |
| 14 | Tun/Tap |
| … | 其他虚拟设备类型 |# 等等
然后请求扫描:
RequestScan 只是触发扫描,不返回结果(dbus会扫到wifi会增加对应的AccessPoint的路径对象,每个都表示一个wifi)
# 无问题busctl call \org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager/Devices/3 \org.freedesktop.NetworkManager.Device.Wireless \RequestScan \a{sv} 0
Step 2️⃣:获取目标 AP 的对象路径
等待几秒(5s)让扫描完成。(会触发信号当扫描到wifi的时候)
# 监听信号
dbus-monitor --system "interface='org.freedesktop.NetworkManager.Device.Wireless'"
获取对应的AccessPoint 与SSId的输出
for ap in $(dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager/Devices/3 \org.freedesktop.NetworkManager.Device.Wireless.GetAllAccessPoints \| grep object | awk '{print $3}' | tr -d '"'); dossid=$(dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \$ap \org.freedesktop.DBus.Properties.Get \string:"org.freedesktop.NetworkManager.AccessPoint" \string:"Ssid" \
)if [ -n "$ssid" ]; thenecho "$ap"echo "$ssid"echo ""fidone
# 获取可连接的wifi 上面扫描完成之后 会增加AccessPoint的对象这里,列出来所有的可连接的wifidbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager/Devices/3 \org.freedesktop.NetworkManager.Device.Wireless.GetAccessPoints
# 包括不可访问的wifi
dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager/Devices/3 \org.freedesktop.NetworkManager.Device.Wireless.GetAllAccessPoints
在返回列表中找到你要连接的 SSID 对应的路径,如:/org/freedesktop/NetworkManager/AccessPoint/123
Step 3️⃣:创建并激活连接
先创建一个临时连接配置(一次性,不保存):
用命令行很难做出来,这里给出python调用dbus功能连接指定的wifi
wifi名字叫gt 密码是12345678
python 连接指定的wifi
#!/usr/bin/env python3
import dbus
import uuid
import sysSSID = "gt"
PASSWORD = "12345678"bus = dbus.SystemBus()
NM_BUS_NAME = "org.freedesktop.NetworkManager"
NM_OBJECT_PATH = "/org/freedesktop/NetworkManager"nm_proxy = bus.get_object(NM_BUS_NAME, NM_OBJECT_PATH)
nm_iface = dbus.Interface(nm_proxy, NM_BUS_NAME)# 1️⃣ 找到无线设备
devices = nm_iface.GetDevices()
wifi_device = None
interface_name = Nonefor dev_path in devices:dev_proxy = bus.get_object(NM_BUS_NAME, dev_path)dev_props = dbus.Interface(dev_proxy, "org.freedesktop.DBus.Properties")dev_type = dev_props.Get("org.freedesktop.NetworkManager.Device", "DeviceType")if dev_type == 2: # wirelesswifi_device = dev_pathinterface_name = dev_props.Get("org.freedesktop.NetworkManager.Device", "Interface")print("wireless path:", wifi_device, "| type:", type(wifi_device))print("interface_name:", interface_name, "| type:", type(interface_name))breakif wifi_device is None:print("没有找到无线设备")sys.exit(1)# 2️⃣ 构造连接字典
connection = {'connection': dbus.Dictionary({'id': dbus.String(SSID),'type': dbus.String('802-11-wireless'),'uuid': dbus.String(str(uuid.uuid4())),'interface-name': dbus.String(interface_name)}, signature='sv'),'802-11-wireless': dbus.Dictionary({'ssid': dbus.ByteArray(SSID.encode())}, signature='sv'),'802-11-wireless-security': dbus.Dictionary({'key-mgmt': dbus.String('wpa-psk'),'psk': dbus.String(PASSWORD)}, signature='sv')
}# 3️⃣ 调用 AddAndActivateConnection
conn_path, active_path = nm_iface.AddAndActivateConnection(connection,dbus.ObjectPath(wifi_device),dbus.ObjectPath("/") # 不指定 AP, 自动选择
)print("连接成功!")
print("Connection path:", conn_path)
print("Active path:", active_path)
✅ 此时 WiFi 应该已连接。
🎯 4. 断开当前 WiFi 连接
获取当前激活的连接:
dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager \org.freedesktop.NetworkManager.GetActiveConnections
找到返回中类型为 802-11-wireless
的连接路径,如:/org/freedesktop/NetworkManager/ActiveConnection/5
然后停用它:
busctl call org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager \org.freedesktop.NetworkManager DeactivateConnection \o /org/freedesktop/NetworkManager/ActiveConnection/5
🎯 5. 创建并打开 WiFi 热点(AP 模式)
Step 1:创建热点连接配置
Step 2:激活热点
#!/usr/bin/env python3
import dbus# -------------------------------
# 配置热点信息
SSID = b"MyHotspot" # 热点名称(Byte)
PASSWORD = "12345678" # 热点密码
# -------------------------------# 连接到系统总线
bus = dbus.SystemBus()# 获取 NetworkManager 对象
nm_proxy = bus.get_object('org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager')
nm_iface = dbus.Interface(nm_proxy, 'org.freedesktop.NetworkManager')# 获取 NetworkManager 设置接口
settings_proxy = bus.get_object('org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager/Settings')
settings_iface = dbus.Interface(settings_proxy, 'org.freedesktop.NetworkManager.Settings')# 获取所有设备,找到第一个无线设备
device_paths = nm_iface.GetDevices()
wifi_device_path = None
wifi_iface_name = None
for path in device_paths:dev_proxy = bus.get_object('org.freedesktop.NetworkManager', path)dev_props = dbus.Interface(dev_proxy, 'org.freedesktop.DBus.Properties')dev_type = dev_props.Get('org.freedesktop.NetworkManager.Device', 'DeviceType')# DeviceType 2 = Wi-Fiif dev_type == 2:wifi_device_path = pathwifi_iface_name = dev_props.Get('org.freedesktop.NetworkManager.Device', 'Interface')breakif not wifi_device_path:raise RuntimeError("未找到无线设备,请检查你的网络接口。")print(f"使用无线接口: {wifi_iface_name}")# 构造热点连接配置
connection = {'connection': {'id': 'MyHotspot','type': '802-11-wireless','interface-name': wifi_iface_name,'autoconnect': False,},'802-11-wireless': {'ssid': dbus.ByteArray(SSID),'mode': 'ap',},'802-11-wireless-security': {'key-mgmt': 'wpa-psk','psk': PASSWORD,},
}# 调用 AddConnection 添加热点
connection_path = settings_iface.AddConnection(connection)
print("连接已添加,路径:", connection_path)# 激活热点(使用 ActivateConnection)
active_path = nm_iface.ActivateConnection(connection_path, wifi_device_path, '/')
print("热点已激活,Active path:", active_path)
print(f"SSID: {SSID.decode()}, Password: {PASSWORD}")
✅ 热点已启动!
🎯 6. 关闭热点
和“断开 WiFi”一样:
如之前使用了打开热点的的时候输出的内容:
使用无线接口: wlp7s0 连接已添加,路径: /org/freedesktop/NetworkManager/Settings/15 热点已激活,Active path: /org/freedesktop/NetworkManager/ActiveConnection/12 SSID: MyHotspot, Password: 12345678
或着找到类型为 802-11-wireless
且模式是 ap
的连接路径,如:/org/freedesktop/NetworkManager/ActiveConnection/6
关键要想办法得到这个ActiveConnection
然后:
busctl call org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager \org.freedesktop.NetworkManager DeactivateConnection \o /org/freedesktop/NetworkManager/ActiveConnection/12
📌 附录:如何获取设备路径(不用 nmcli)
dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager \org.freedesktop.NetworkManager.GetDevices
遍历返回的设备路径,对每个设备查询设备类型:
dbus-send --system --print-reply \--dest=org.freedesktop.NetworkManager \/org/freedesktop/NetworkManager/Devices/3 \org.freedesktop.DBus.Properties.Get \string:"org.freedesktop.NetworkManager.Device" \string:"DeviceType"
返回值 2
表示无线设备(NM_DEVICE_TYPE_WIFI)。
✅ 总结命令表(纯 dbus-send)
功能 | 命令摘要 |
---|---|
开启 WiFi | Set WirelessEnabled true |
关闭 WiFi | Set WirelessEnabled false |
连接 WiFi | AddConnection + ActivateConnection (需 SSID 字节数组) |
断开 WiFi | DeactivateConnection (需 ActiveConnection 路径) |
打开热点 | AddConnection(mode=ap) + ActivateConnection |
关闭热点 | DeactivateConnection (找 AP 类型的 ActiveConnection) |
💡 温馨提示:
- 使用
dbus-send
busctl
操作 NetworkManager 极其繁琐,参数结构复杂,错误难调试。 - 生产环境或脚本中强烈建议使用
nmcli
。 - 如果想要更详细的控制就调用dbus的功能通信,nmcli 也是这么做的
- 如果你是为了学习 D-Bus 或嵌入式定制系统,这些命令非常有价值。
(可以用命令先跑通,然后再转换具体的代码)