import networkimport utime as time# open WiFi interface in STA mode wifi = network.WLAN( network.STA_IF )# activate the WiFi interface (if_up)wifi.active( True )print ('Press Ctrl+C to stop WiFi scanning...')try:whileTrue:# scan WiFi scan_results = wifi.scan()# print scan results (a list of tuples)print(60*'=')for ap in scan_results:print( ap )print(60*'-')exceptKeyboardInterrupt:print('Terminated...')# deactivate the WiFi interfacewifi.active(False)
import networkimport ujson as jsonparam_names = ['essid','mac','channel','rssi','authmode','hidden']authmodes = ['OPEN','WEP','WPA-PSK','WPA2-PSK','WPA/WPA2-PSK','MAX']defmac_bytes_to_hex_str( mac_bytes ):return':'.join(['%02X'% x for x in mac_bytes])defconvert_to_json( found_list ): results ={'count':len(found_list),'found_list': []}for ap in found_list: pairs =dict(zip(param_names,ap))for name in pairs: value = pairs.get(name)iftype(value)==bytes:if name=='mac'andlen(value)==6: value =mac_bytes_to_hex_str( value )else: value = value.decode('ascii')else:try: value =int(value)if name=='authmode'and0<= value <=5: value = authmodes[value]except (ValueError,TypeError):pass pairs[name]= value results['found_list'].append( pairs )return results# open WiFi interface in STA mode# activate the WiFi interfacewifi = network.WLAN( network.STA_IF )wifi.active(True)# scan WiFi and get the results as a list of tuplesscan_results = wifi.scan()# deactivate the WiFi interfacewifi.active(False)# convert a list of tuples to json dataresults =convert_to_json( scan_results )if results.get('count')>0:for item in results.get('found_list'):print( json.dumps(item) )# show JSON stringelse:print( 'No WiFi found')
3. Wi-Fi Connection in STA Mode
การเชื่อมต่อกับเครือข่าย Wi-Fi ในโหมด STA จะต้องระบุชื่อ SSID และรหัสผ่าน (Password) สำหรับเชื่อมต่ออุปกรณ์ไร้สาย เช่น Wireless Access Point / Router ตามตัวอย่างโค้ดต่อไปนี้
import networkimport utime as time# Specify the SSID and password of your WiFi networkWIFI_CFG ={'ssid':"XXXXXX",'pwd':"XXXXXXXXX"}defconnect_wifi( wifi_cfg,max_retries=10 ):# use WiFi in station mode (not AP) wifi_sta = network.WLAN( network.STA_IF )# activate the WiFi interface (up) wifi_sta.active(True)# connect to the specified WiFi AP wifi_sta.connect( wifi_cfg['ssid'], wifi_cfg['pwd'] ) retries =0whilenot wifi_sta.isconnected(): retries = retries +1if retries >= max_retries:returnNone time.sleep_ms(500)return wifi_sta# try to connect the networkwifi =connect_wifi( WIFI_CFG )if wifi isNone:print( 'WiFi connection failed' )else: ipaddr, netmask, gateway, dns = wifi.ifconfig()print("============================")print("IP address :", ipaddr)print("Net mask :", netmask)print("Gateway :", gateway)print("DNS server :", dns)print("----------------------------")
4. Wi-Fi in AP Mode + Simple HTTP Server
ตัวอย่างถัดไป สาธิตการเปิดใช้งาน Wi-Fi ในโหมด AP แบบ Open (ไม่มีการป้องกันด้วยรหัสผ่าน) โดยการสร้างและเรียกใช้ฟังก์ชัน start_wifi_ap() จากนั้นเมื่อ ESP32 ทำงานเป็น Wi-Fi AP แล้ว (จะมีหมายเลขไอพีตรงกับ 192.168.4.1 และเลือกใช้ช่องสัญญาณหมายเลข 11) ยังได้มีการสร้างและเรียกใช้ฟังก์ชัน start_web_server() เพื่อให้สามารถทำงานเป็น Web Server (HTTP protocol) อย่างง่ายได้ด้วย แสดงข้อความเป็นหน้าเว็บได้
ในตัวอย่างนี้ ถ้าต้องการจบการทำงานของ Web Server เราจะใช้วิธีตรวจสอบการกดปุ่ม ดังนั้นจะต้องมีการต่อวงจรกดปุ่มภายนอกแบบ Active-Low และเลือกใช้ขา GPIO23 เป็นอินพุตสำหรับปุ่มกด
import networkimport utime as time import usocket as socketfrom machine import PinAP_CFG ={'essid':'MyAP',# SSID for your AP'authmode': network.AUTH_OPEN,'channel':11,}defstart_wifi_ap( ap_cfg ):# open WiFi in AP mode ap = network.WLAN( network.AP_IF )# activate AP interface (up) ap.active(True)# configure the AP interfacetry: ap.config( **ap_cfg )exceptExceptionas ex:print ( 'Cannot set AP configuration...' )if ap.active():return apelse:returnFalsedefstart_web_server( btn=None ):global sock# create a socket (STREAM TCP socket) for network connection sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )# set socket option: reuse address sock.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 )# use socket in non-blocking mode sock.setblocking( False )# get the server address (localhost) addr = socket.getaddrinfo('0.0.0.0',80)[0][-1]# bind the socket to port 80 (HTTP) sock.bind( addr )# listen for an incoming connection sock.listen(1)whileTrue:try:# waiting for connection conn,addr = sock.accept()exceptOSError:if btn and btn.value()==0:# check button sock.close()# close socketbreak# break the loopelse:continue# read incoming request data request = conn.recv(1024)print( 'Content = %s'%str(request) )# send HTML as response html ='<html><head></head><body>' html +='<h1>Welcome to ESP32...</h1><br>' html +='<b>Client from {}<b><br>'.format(str(addr)) html +='</body></html>' conn.send( html )# send HTML response conn.close()# close HTTP connection time.sleep_ms(10)sock =Noneap =start_wifi_ap( AP_CFG )ipaddr = ap.ifconfig()[0]print ( 'IP address:', ipaddr )# 192.168.4.1BTN_GPIO =const(23)# use GPIO23 for push buttonbtn =Pin( BTN_GPIO, Pin.IN, Pin.PULL_UP )try:start_web_server( btn )# start web serverexceptKeyboardInterrupt:passfinally:if sock: sock.close() ap.active(False)# turn off WiFi AP
ถ้าจะเปลี่ยนจาก Open เป็นการตั้งรหัสป้องกันด้วยวิธี WPA2-PSK ก็กำหนดค่าสำหรับ Configuration ตามตัวอย่างดังนี้
ตัวอย่างถัดไปสาธิตการเปิดใช้งาน ESP32 ในโหมด STA และเชื่อมต่อกับอุปกรณ์ Wi-Fi AP ที่สามารถเชื่อมต่อไปยังอินเทอร์เน็ตได้ และใช้คำสั่ง ntptime.settime() เพื่อเชื่อมต่อกับคอมพิวเตอร์ในอินเทอร์เน็ตที่ทำหน้าที่เป็น NTP Server และอัปเดทเวลาปัจจุบันสำหรับการทำงานของวงจรของ RTC (Real-Time Clock) ของ ESP32
import networkimport utime as timeimport ntptimeimport machine# Specify the SSID and password of your WiFi networkWIFI_CFG ={'ssid':"XXXX",'pwd':"XXXXXXX"}defconnect_wifi( wifi_cfg ): wifi_sta = network.WLAN( network.STA_IF ) wifi_sta.active(True) wifi_sta.connect( wifi_cfg['ssid'], wifi_cfg['pwd'] )whilenot wifi_sta.isconnected(): time.sleep(1.0)print(wifi_sta.ifconfig())defsync_ntp():whileTrue:try:# synchronize RTC with NTP server ntptime.settime()breakexceptOSError:print('NTP server: connection timeout...')connect_wifi( WIFI_CFG )sync_ntp()rtc = machine.RTC()tm = rtc.datetime()# get current RTC datetime (now)tz_offset =+7# timezone offset (GMT+7)hh, mm, ss = (tm[4]+tz_offset) %24, tm[5], tm[6]print( 'Time: {}:{}:{}'.format( hh, mm, ss ) )y, m, d = tm[0], tm[1], tm[2]print( 'Date: {}-{:02d}-{:02d}'.format( y, m, d ) )
6. HTTP GET: Getting Datetime Using WorldTime API
ตัวอย่างถัดไปสาธิตการเปิดใช้งาน ESP32 ในโหมด STA และเชื่อมต่อกับอุปกรณ์ Wi-Fi AP ที่สามารถเชื่อมต่อไปยังอินเทอร์เน็ตได้ และร้องขอข้อมูลแบบ HTTP Request / GET Method ไปยัง World Time API ซึ่งเป็นผู้ให้บริการข้อมูลเกี่ยวกับวันและเวลาในปัจจุบันตามโซนเวลา (Timezone) ที่ระบุไว้ ข้อมูลที่ได้รับกลับมานั้น จะอยู่ในรูปแบบของ JSON String
import networkimport utime as timeimport ujson as jsonimport urequests as requestsURL ="http://worldtimeapi.org/api/timezone/Asia/Bangkok"# Specify the SSID and password of your WiFi networkWIFI_CFG ={'ssid':"XXXX",'pwd':"XXXXXXX"}defconnect_wifi( wifi_cfg,max_retries=10 ):# use WiFi in station mode (not AP) wifi_sta = network.WLAN( network.STA_IF )# activate the WiFi interface (up) wifi_sta.active(True)# connect to the specified WiFi AP wifi_sta.connect( wifi_cfg['ssid'], wifi_cfg['pwd'] ) retries =0whilenot wifi_sta.isconnected(): retries = retries +1if retries >= max_retries:returnNone time.sleep_ms(500)return wifi_stadefget_worldtime_data( url ): resp = requests.get( url )if resp.status_code==200:# request oktry: data = json.loads(resp.text)exceptExceptionas ex:print ('JSON data error...' )returnprint( 'Timezone:', data['timezone'] )print( 'Epoch time (Jan 1, 1970):', int(data['unixtime']) )print( 'UTC datetime:', data['utc_datetime'] )print( 'Local datetime:', data['datetime'] )print( 'UTC offset (hours):', data['utc_offset'] )print( 'UTC offset (seconds):', int(data['raw_offset']) )else:print ('HTTP request error...')# try to connect the networkwifi =connect_wifi( WIFI_CFG )if wifi isnotNone:get_worldtime_data( URL )else:print('No WiFi connection')
ตัวอย่างเอาต์พุตที่ได้
Timezone: Asia/Bangkok
Epoch time (Jan 1, 1970): 1609939805
UTC datetime: 2021-01-06T13:30:05.138524+00:00
Local datetime: 2021-01-06T20:30:05.138524+07:00
UTC offset (hours): +07:00
UTC offset (seconds): 25200
7. HTTPS GET: Thailand's COVID-19 Status Update
ตัวอย่างถัดไป สาธิตการดึงข้อมูลเกี่ยวกับผู้ป่วย COVID-19 สำหรับประเทศไทย ด้วยวิธี HTTPS GET จาก API ของเว็บ covid19.th-stat.comข้อมูลที่ได้จะอยู่ในรูปของ JSON String
import networkimport utime as timeimport urequests as requestsURL ="https://covid19.th-stat.com/api/open/today"# Specify the SSID and password of your WiFi networkWIFI_CFG ={'ssid':"XXXX",'pwd':"XXXXXXX"}WIFI_CFG ={'ssid':"esl_ap",'pwd':"cnch2687"}COVID19_NAMES = [ ('Confirmed',u'ยอดผู้ป่วยสะสม'), ('Recovered',u'ผู้ป่วยรักษาหายแล้ว'), ('Hospitalized',u'ผู้ป่วยรักษาตัวในโรงพยาบาล'), ('Deaths',u'ผู้เสียชีวิตสะสม'), ('NewConfirmed',u'ผู้ป่วยตรวจพบเพิ่มวันนี้'), ('NewRecovered',u'ผู้ป่วยรักษาหาย'), ('NewDeaths',u'ผู้เสียชีวิตวันนี้'), ('UpdateDate',u'อัปเดตล่าสุด') ]defget_covid19_data( url ): data =Nonetry: resp = requests.get( url ) data = resp.json()for name in COVID19_NAMES[:-1]:if name[0]in data: value =str(data[name[0]])print('{}:\t\t\t\t{}'.format(name[1],value) ) name = COVID19_NAMES[-1] update = data[ name[0]]print( '{}: {}'.format(name[1], update) )exceptExceptionas ex:print('error:', ex)return datadefconnect_wifi( wifi_cfg ): wifi_sta = network.WLAN( network.STA_IF ) wifi_sta.active(True) wifi_sta.connect( wifi_cfg['ssid'], wifi_cfg['pwd'] )whilenot wifi_sta.isconnected(): time.sleep(1.0)print(wifi_sta.ifconfig())connect_wifi( WIFI_CFG )import gcgc.collect()get_covid19_data( URL )
เราสามารถลองใช้ไลบรารี urequests ซึ่งเป็นโมดูลแบบ built-in สำหรับไมโครไพธอน และใช้คำสั่ง urequests.post() สำหรับส่งข้อมูลแบบ POST ได้ แต่จากการที่ได้ลองใช้กับ LINE Notify API พบว่า มีความผิดพลาดเกิดขึ้นในการรับข้อมูลตอบกลับ (Response) แต่ก็ได้รับข้อความใน LINE App
PING 8.8.8.8 (8.8.8.8): 44 data bytes
64 bytes from 8.8.8.8: icmp_seq=1, ttl=112, time=139.7 ms
64 bytes from 8.8.8.8: icmp_seq=2, ttl=112, time=64.4 ms
64 bytes from 8.8.8.8: icmp_seq=3, ttl=112, time=150.3 ms
64 bytes from 8.8.8.8: icmp_seq=4, ttl=112, time=61.7 ms
64 bytes from 8.8.8.8: icmp_seq=5, ttl=112, time=158.2 ms
5 packets transmitted, 5 packets received