2017年12月26日 星期二

MicroPython on ESP8266 (二十四) : 掃描無線基地台 (AP)

最近網友問我一個問題 : 為何 ESP8266 用 AT 指令掃描附近的無線基地台結果不是有亂碼, 就是不完整? 其實這問題很早以前我用 Arduino + ESP8266 做測試時就發現了這個問題, 由於掃描 AP 需要時間, 因此迴圈內的 delay() 不可太短. 但即使設得夠長 (至少 5 秒以上), 還是有亂碼與結果不完整問題. 所以我就想說何不改用 MicroPython on ESP8266 試試看, 測試結果可以完整掃描, 但是 MAC 位址卻仍不完整.

本系列 MicroPython on ESP8266 測試文章參考 :

MicroPython on ESP8266 (一) : 燒錄韌體
MicroPython on ESP8266 (二) : 數值型別測試
MicroPython on ESP8266 (三) : 序列型別測試
MicroPython on ESP8266 (四) : 字典與集合型別測試
MicroPython on ESP8266 (五) : WiFi 連線與 WebREPL 測試
MicroPython on ESP8266 (六) : 檔案系統測試
MicroPython on ESP8266 (七) : 時間日期測試
MicroPython on ESP8266 (八) : GPIO 測試
MicroPython on ESP8266 (九) : PIR 紅外線移動偵測
MicroPython v1.9.1 版韌體測試
MicroPython on ESP8266 (十) : socket 模組測試
MicroPython on ESP8266 (十一) : urllib.urequest 模組測試
MicroPython on ESP8266 (十二) : urequests 模組測試
MicroPython on ESP8266 (十三) : DHT11 溫溼度感測器測試
MicroPython 使用 ampy 突然無法上傳檔案問題
MicroPython on ESP8266 (十四) : 網頁伺服器測試
WeMOS D1 Mini 開發板測試
MicroPython on ESP8266 (十五) : 光敏電阻與 ADC 測試
MicroPython on ESP8266 (十六) : 蜂鳴器測試
MicroPython on ESP8266 (十七) : 液晶顯示器 1602A 測試
MicroPython on ESP8266 (十八) : SSD1306 液晶顯示器測試
MicroPython v1.9.2 版釋出
MicroPython on ESP8266 (十九) : 太陽能測候站與移動偵測控制照明
MicroPython on ESP8266 (二十) : 從 ThingSpeak 讀取資料
MicroPython on ESP8266 (二十一) : 使用 ThingTweet 傳送推文
MicroPython on ESP8266 (二十二) : UART 串列埠測試
MicroPython on ESP8266 (二十三) : 超音波模組 HC-SR04 測試

掃描 AP 須匯入 network 模組, 然後呼叫 network.WLAN().scan() 將 ESP8266 設定為 STATION 模式即會傳回附近基地台訊息所組成之串列 :

<<< import network
<<< wlan=network.WLAN(network.STA_IF)
<<< wlan.config('mac')    #查詢 ESP8266 本身 MAC 位址
b'`\x01\x94<\xcb\xab'
<<< aps=wlan.scan()        #掃描附近無線基地台
<<< aps
[(b'edimax.setup', b't\xda8\x15\x16\x00', 1, -78, 2, 0),
(b'ching', b'T\xb8\n\x84\xf4p', 1, -91, 4, 0),
(b'Gary-Home', b',MT\x1c\x90\x08', 4, -88, 3, 0),
(b'64N3F', b'\x00\xfc\x8d\xa9\xc9(', 6, -76, 4, 0),
(b'family', b'l\x19\x8f\xb7\x9ay',1, -92, 3, 0),
(b'leeyunyun', b'\xb9\xa3\x86\x94\xf8\xe8', 1, -92, 3, 0),
(b'TP-LINK_601A04', b"\xe8\xde'`\x1a\x04", 8, -79, 4, 0),
(b'My ASUS', b',MT%\x18\xd7', 9, -83, 3, 0),
(b'Home', b'\xc4\xe9\x84f3\xc1', 11, -73, 3, 0),
(b'EDIMAX-tony', b'\x90\x1f\x02-Z\x9b', 11, -51, 4, 0),
(b'CHT5668', b'\xd8\xfe\xe3\\\xc0\xfb', 11, -85, 3, 0)]

函數 scan() 會將各 AP 資訊以 tuple 形式放入串列中傳回, tuple 的第一元素為 SSID, 第二元素即為 AP 的 MAC 位址, 第三參數為通道號碼, 第四參數為信號強度, 第五參數為加密模式, 參考 :

wlan.scan()

list of tuples with the information about WiFi access points:

(ssid, bssid, channel, RSSI, authmode, hidden)
bssid is hardware address of an access point, in binary form, returned as bytes object. You can use ubinascii.hexlify() to convert it to ASCII form.

可見雖然掃描完全, 但是除了 SSID 為 leeyunyun 的那個外 MAC 位址都不完整. 其中 EDIMAX-tony 是我自己的無線基地台, scan() 掃到的 MAC 位址只有 4 個 bytes, 漏失了中間的兩個. 檢查無線基地台的管理頁面即可知完整的 MAC 位址應該是 90:1F:02:2D:5A:9B 才對, 結果 2D 與 5A 不見了 :




因此要用 ESP8266 的 scan() 掃描 AP 取得 MAC 來做室內定位似乎有困難.

參考 :

Connecting to your home router
How to get the infomation of wifi devices, such as mac
https://docs.micropython.org/en/latest/esp8266/library/network.html#network.wlan.scan
https://docs.micropython.org/en/latest/esp8266/library/network.html#network.config

2019-07-04 補充 :

感謝匿名網友之前提供的資訊, 但這兩天因為測試 ESP32 才有時間重新研究這個問題, 網友的建議是對的, 這完全是資料型態的問題, 並非 scan() 傳回不全之 mac 位址, 上面的測試結論是我對 MicroPython 了解不足.

亂碼的原因是傳回的 mac 位址的資料型態為 bytes (二進位), 而 print() 用 ASCII 格式印出當然會變成亂碼, 解決之道就是使用網友所說的 ubinascii.hexlify() 方法將 bytes 轉成 ASCII 即可, 完整程式如下 :

import network
import ubinascii

sta=network.WLAN(0)
sta.active(1)
aps=sta.scan()
for ap in aps:
    ssid=ap[0].decode()
    mac=ubinascii.hexlify(ap[1], ':').decode()
    print('{:>20} {:>20}'.format(ssid, mac))

參考 :

MicroPython on ESP32 學習筆記 (三) : WiFi 連線

2 則留言 :

匿名 提到...

使用 ubinascii 來處理就可以取得 MAC Address
ubinascii.hexlify(b'\x90\x1f\x02-Z\x9b')

小狐狸事務所 提到...

感謝您!