Примечания (около [PyPI]: беспроводной 0.3.2 ]):
- Поддерживает ли не (пока) Python 3 : где-то в коде используется функция cmp (которая доступно в Python 2 )
- Я хотел отправить запрос на извлечение (так как исправление тривиально), но, по-видимому, на GitHub он уже был исправлен, но хранилище PyPI не обновлялось (с 2016 года)
- Работает ли не на Win (на домашней странице перечислены только драйверы Nix - в основном запускаются только команды shell )
Как следствие, я бы предложил поискать альтернативы:
Хорошо, после долгого просмотра:
- Win32Wifi исходный код
- Google :
, я смог что-то придумать.
code.py
#!/usr/bin/env python3
import sys
import time
import ctypes
import comtypes
import traceback
from win32wifi import Win32Wifi as ww
ERROR_SUCCESS = 0
WLAN_CONNECTION_HIDDEN_NETWORK = 0x00000001
class WLANException(Exception): pass
class ConnectCallbackContext(ctypes.Structure):
_fields_ = [
("guid", ctypes.c_wchar_p),
("start", ctypes.c_byte),
("end", ctypes.c_byte),
("fail", ctypes.c_byte),
]
def _wlan_connect_callback(data, context_addr):
if context_addr:
context = ConnectCallbackContext.from_address(context_addr)
if str(data.interfaceGuid) == context.guid and data.notificationSource == ww.WLAN_NOTIFICATION_SOURCE_DICT[ww.WLAN_NOTIFICATION_SOURCE_ACM]:
if data.notificationCode == ww.WLAN_NOTIFICATION_ACM_ENUM.wlan_notification_acm_connection_start.name:
context.start += 1
elif context.start:
if data.notificationCode == ww.WLAN_NOTIFICATION_ACM_ENUM.wlan_notification_acm_connection_complete.name:
context.end += 1
elif data.notificationCode == ww.WLAN_NOTIFICATION_ACM_ENUM.wlan_notification_acm_connection_attempt_fail.name:
context.fail += 1
def wireless_connect(
ssid,
password,
timeout=15, # secs
authentication="WPA2PSK", # "open",
encryption="AES", # "WEP",
key_type="passPhrase", # "networkKey",
interface_index=0, # Don't modify this (until PCs with more than 1 WLAN adapter arise :) )
):
interfaces = ww.getWirelessInterfaces()
if interface_index < 0 or len(interfaces) < interface_index:
raise WLANException(-1, "No WLAN interface for given index")
interface = interfaces[interface_index]
profile_name = ssid + "_profile_tmp"
ssid_hex = "".join((hex(ord(c))[2:] for c in ssid)).upper()
profile_string = f"""<?xml version=\"1.0\"?>
<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">
<name>{profile_name}</name>
<SSIDConfig>
<SSID>
<hex>{ssid_hex}</hex>
<name>{ssid}</name>
</SSID>
</SSIDConfig>
<connectionType>ESS</connectionType>
<connectionMode>manual</connectionMode>
<MSM>
<security>
<authEncryption>
<authentication>{authentication}</authentication>
<encryption>{encryption}</encryption>
<useOneX>false</useOneX>
</authEncryption>
<sharedKey>
<keyType>{key_type}</keyType>
<protected>false</protected>
<keyMaterial>{password}</keyMaterial>
</sharedKey>
</security>
</MSM>
</WLANProfile>
"""
connection_params = {
"connectionMode": "wlan_connection_mode_temporary_profile",
"profile": profile_string,
"ssid": None,
"bssidList": None,
"bssType": "dot11_BSS_type_infrastructure",
"flags": WLAN_CONNECTION_HIDDEN_NETWORK,
}
ctx = ConnectCallbackContext(interface.guid_string, 0, 0, 0)
notification_obj = ww.registerNotification(_wlan_connect_callback, context=ctypes.pointer(ctx))
try:
res = ww.connect(interface, connection_params)
except Exception as e:
ww.unregisterNotification(notification_obj)
raise WLANException("WlanConnect failed") from e
end_time = time.time() + timeout;
while time.time() < end_time:
time.sleep(0.5)
if ctx.end:
break
ww.unregisterNotification(notification_obj)
if ctx.end:
if ctx.fail:
raise WLANException(-2, "Connection failed")
else:
raise WLANException(-3, "Connection timed out")
return interface.guid_string
def wireless_disconnect(interface_guid): # Borrowed (and improved) this func from win32wifi.Win32Wifi, to avoid creting the interface when only its guid is required
handle = ww.WlanOpenHandle()
try:
ww.WlanDisconnect(handle, comtypes.GUID(interface_guid))
except Exception as e:
raise WLANException("WlanDisconnect failed") from e
finally:
ww.WlanCloseHandle(handle)
def main(argv):
if argv:
try:
guid = argv[0]
print("Disconnecting wireless interface {:s} ...".format(guid))
wireless_disconnect(guid)
except:
traceback.print_exc()
else:
try:
print("Connecting to wireless network ...")
ssid = "Network SSID" # ssid and pwd here are (deliberately) dummy
pwd = "Network password"
guid = wireless_connect(ssid, pwd)
print("Connected interface {:s}".format(guid))
except:
traceback.print_exc()
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main(sys.argv[1:])
print("\nDone.")
script.bat
time <nul
ping www.google.com
"e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code.py
ping www.google.com
"e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code.py {0C58E048-BC0B-4D5F-A21F-FCD4E4B31806}
ping www.google.com
time <nul
выход
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q056721759]> sopr.bat
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***
[prompt]> script.bat
[prompt]> time 0<nul
The current time is: 1:45:08.31
Enter the new time:
[prompt]> ping www.google.com
Ping request could not find host www.google.com. Please check the name and try again.
[prompt]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32
Connecting to wireless network ...
Connected interface {0C58E048-BC0B-4D5F-A21F-FCD4E4B31806}
Done.
[prompt]> ping www.google.com
Pinging www.google.com [2a00:1450:400d:809::2004] with 32 bytes of data:
Reply from 2a00:1450:400d:809::2004: time=11ms
Reply from 2a00:1450:400d:809::2004: time=12ms
Reply from 2a00:1450:400d:809::2004: time=12ms
Reply from 2a00:1450:400d:809::2004: time=19ms
Ping statistics for 2a00:1450:400d:809::2004:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 11ms, Maximum = 19ms, Average = 13ms
[prompt]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code.py {0C58E048-BC0B-4D5F-A21F-FCD4E4B31806}
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32
Disconnecting wireless interface {0C58E048-BC0B-4D5F-A21F-FCD4E4B31806} ...
Done.
[prompt]> ping www.google.com
Ping request could not find host www.google.com. Please check the name and try again.
[prompt]> time 0<nul
The current time is: 1:45:12.82
Enter the new time:
Примечания
- Чтобы создать POC , мне пришлось добавить некоторый код (например, wireless_disconnect ), не обязательно связанный с вопросом, что добавляет сложности.
КСТАТИ , код более сложный, чем я изначально ожидал (поэтому я не удосужился объяснить это - это было бы излишним), но я не вижу никакого способа обрезать его
- script.bat (и
time <nul
) просто для того, чтобы доказать в консоли, что код подключается / отключается от беспроводной сети (и что я не подключаюсь от Win в параллели)
- Я не знаю, откуда берется часть " 0 " из
time 0<nul
(на выходе)
- Как я указывал, это больше похоже на POC , в коде (my и Win32Wifi ) есть некоторые ограничения. Некоторые сценарии (сети) могут не работать без (небольших) изменений кода
- Хотя подключение к сети успешно (и работает ), в системном трее 1137 * состояние сети по-прежнему отображается как отключенное (фактически в течение доли секунды оно кажется подключенным, но тогда это автоматически меняется). Кроме того, значок сети System Tray отображается как Подключено . Я не уверен, что это на моей стороне (я забыл как-то уведомить Win - хотя это не имеет особого смысла), или Win не любит "кого-то другого" «для подключения к беспроводным сетям
САМОЕ ВАЖНОЕ ОДИН : вышеуказанный код не будет работать OOTB , поскольку Win32Wifi глючит . Я нашел 2 ошибки, которые фатальные (критические) для этого сценария , и кучу других более мелких ошибок.
Я только что отправил [GitHub]: kedos / win32wifi - Исправления (некоторые критические) и улучшения . Не уверен, каким будет его исход (учитывая период бездействия).
В качестве альтернативы вы можете скачать патч и применить изменения локально. Проверьте [SO]: запускать / отлаживать UnitTests приложения Django из контекстного меню, вызываемого правой кнопкой мыши, в PyCharm Community Edition? (@ Ответ CristiFati) ( Patching utrunner section) о том, как применять патчи к Win (в основном, каждая строка, начинающаяся с one) "+" знак входит, и каждая строка, которая начинается с one "-" знак гаснет). Я использую Cygwin , кстати .