モチベーション
Windows で Wi-Fi の SSID と BSSID を取得したいと思ったのがきっかけ。
はじめはコマンドラインで netsh wlan show networks mode=bssid
で Wi-Fi の一覧を取得しようかと考えていたのですが、[参考資料](# 参考資料)にある通り、何度実行しても同一のSSID/BSSIDになってしまったり、複数あるはずのSSIDが接続中のSSID1つだけになってしまったりしました。
解決方法を以下に引用します。
C#を使ってWindowsAPIを呼び出すことでWifiの電波強度一覧を取得することができました。
使用したAPIはWlanScan()です。NativeWifiというオープンソースのライブラリを使って使用することができました。
上記を Python でもできないか調べたところ、win32wifi
を見つけました。
環境
- Windows 10
- Python 3.6
- 追加ライブラリ
win32wifi
※ 3.7 以上で実行しようとすると import comtypes でエラーが生じます。[参考資料](# 参考資料)の方法で回避できるかもしれません。
プログラム
実行をする場合は中身を確認しながら自己責任でお願いします。
WlanRegisterNotification
にて通知がきても Wi-Fi 情報が空の場合があるため3回実行しています。
(何か使い方が間違っているのでしょうか...)
from win32wifi import Win32Wifi as ww
import threading
def get_ssid(trial=3):
## Wlanが変更を登録するEvent
th_ev = threading.Event()
def callback(wnd, p):
th_ev.set()
interfaces = ww.getWirelessInterfaces()
handle = ww.WlanOpenHandle()
## 試行回数
for i in range(trial):
ssid_dict = {}
for interface in interfaces:
## 検索
ws = ww.WlanScan(handle, interface.guid)
## 登録完了を最大10秒待機する。
cb = ww.WlanRegisterNotification(handle, callback)
th_ev.wait(10)
th_ev.clear()
networks = ww.getWirelessNetworkBssList(interface)
for network in networks:
ssid = network.ssid.decode()
bssid = network.bssid
quality = network.link_quality
## ssid がなければリストを追加
if ssid not in ssid_dict.keys():
ssid_dict[ssid] = []
## bssid と電波強度を追加
ssid_dict[ssid].append((bssid, quality))
## 空でなければ break
if ssid_dict != {}:
break
ww.WlanCloseHandle(handle)
return ssid_dict
if __name__ == "__main__":
print(get_ssid())
実行結果(例)
実行毎に更新し、周囲の SSID と BSSID、電波強度を取得できました。
win32wifi
のソースコードを確認するとより多くの情報を取得できると思います。
{'SampleSSID1': [('XX:XX:XX:XX:XX:XX', 100)], 'SampleSSID2': [('YY:YY:YY:YY:YY:YY',80)], ..... }