131131# pylint: disable=too-many-lines 
132132
133133
134+ class  Network :
135+     """A wifi network provided by a nearby access point.""" 
136+ 
137+     def  __init__ (  # pylint: disable=too-many-arguments 
138+         self ,
139+         esp_spi_control = None ,
140+         raw_ssid = None ,
141+         raw_bssid = None ,
142+         raw_rssi = None ,
143+         raw_channel = None ,
144+         raw_country = None ,
145+         raw_authmode = None ,
146+     ):
147+         self ._esp_spi_control  =  esp_spi_control 
148+         self ._raw_ssid  =  raw_ssid 
149+         self ._raw_bssid  =  raw_bssid 
150+         self ._raw_rssi  =  raw_rssi 
151+         self ._raw_channel  =  raw_channel 
152+         self ._raw_country  =  raw_country 
153+         self ._raw_authmode  =  raw_authmode 
154+ 
155+     def  _get_response (self , cmd ):
156+         respose  =  self ._esp_spi_control ._send_command_get_response (  # pylint: disable=protected-access 
157+             cmd , [b"\xFF " ]
158+         )
159+         return  respose [0 ]
160+ 
161+     @property  
162+     def  ssid (self ):
163+         """String id of the network""" 
164+         if  self ._raw_ssid :
165+             response  =  self ._raw_ssid 
166+         else :
167+             response  =  self ._get_response (_GET_CURR_SSID_CMD )
168+         return  response .decode ("utf-8" )
169+ 
170+     @property  
171+     def  bssid (self ):
172+         """BSSID of the network (usually the AP’s MAC address)""" 
173+         if  self ._raw_bssid :
174+             response  =  self ._raw_bssid 
175+         else :
176+             response  =  self ._get_response (_GET_CURR_BSSID_CMD )
177+         return  bytes (response )
178+ 
179+     @property  
180+     def  rssi (self ):
181+         """Signal strength of the network""" 
182+         if  self ._raw_bssid :
183+             response  =  self ._raw_rssi 
184+         else :
185+             response  =  self ._get_response (_GET_CURR_RSSI_CMD )
186+         return  struct .unpack ("<i" , response )[0 ]
187+ 
188+     @property  
189+     def  channel (self ):
190+         """Channel number the network is operating on""" 
191+         if  self ._raw_channel :
192+             return  self ._raw_channel [0 ]
193+         return  None 
194+ 
195+     @property  
196+     def  country (self ):
197+         """String id of the country code""" 
198+         return  self ._raw_country 
199+ 
200+     @property  
201+     def  authmode (self ):
202+         """String id of the authmode 
203+ 
204+         derived from Nina code: 
205+         https://github.com/adafruit/nina-fw/blob/master/arduino/libraries/WiFi/src/WiFi.cpp#L385 
206+         """ 
207+         if  self ._raw_authmode :
208+             response  =  self ._raw_authmode [0 ]
209+         else :
210+             response  =  self ._get_response (_GET_CURR_ENCT_CMD )[0 ]
211+ 
212+         if  response  ==  7 :
213+             return  "OPEN" 
214+         if  response  ==  5 :
215+             return  "WEP" 
216+         if  response  ==  2 :
217+             return  "PSK" 
218+         if  response  ==  4 :
219+             return  "WPA2" 
220+         return  "UNKNOWN" 
221+ 
222+ 
134223class  ESP_SPIcontrol :  # pylint: disable=too-many-public-methods, too-many-instance-attributes 
135224    """A class that will talk to an ESP32 module programmed with special firmware 
136225    that lets it act as a fast an efficient WiFi co-processor""" 
@@ -359,7 +448,7 @@ def firmware_version(self):
359448        if  self ._debug :
360449            print ("Firmware version" )
361450        resp  =  self ._send_command_get_response (_GET_FW_VERSION_CMD )
362-         return  resp [0 ]
451+         return  resp [0 ]. decode ( "utf-8" ). replace ( " \x00 " ,  "" ) 
363452
364453    @property  
365454    def  MAC_address (self ):  # pylint: disable=invalid-name 
@@ -397,16 +486,19 @@ def get_scan_networks(self):
397486        # print("SSID names:", names) 
398487        APs  =  []  # pylint: disable=invalid-name 
399488        for  i , name  in  enumerate (names ):
400-             a_p  =  {"ssid" : name }
401-             rssi  =  self ._send_command_get_response (_GET_IDX_RSSI_CMD , ((i ,),))[0 ]
402-             a_p ["rssi" ] =  struct .unpack ("<i" , rssi )[0 ]
403-             encr  =  self ._send_command_get_response (_GET_IDX_ENCT_CMD , ((i ,),))[0 ]
404-             a_p ["encryption" ] =  encr [0 ]
405489            bssid  =  self ._send_command_get_response (_GET_IDX_BSSID_CMD , ((i ,),))[0 ]
406-             a_p ["bssid" ] =  bssid 
407-             chan  =  self ._send_command_get_response (_GET_IDX_CHAN_CMD , ((i ,),))[0 ]
408-             a_p ["channel" ] =  chan [0 ]
409-             APs .append (a_p )
490+             rssi  =  self ._send_command_get_response (_GET_IDX_RSSI_CMD , ((i ,),))[0 ]
491+             channel  =  self ._send_command_get_response (_GET_IDX_CHAN_CMD , ((i ,),))[0 ]
492+             authmode  =  self ._send_command_get_response (_GET_IDX_ENCT_CMD , ((i ,),))[0 ]
493+             APs .append (
494+                 Network (
495+                     raw_ssid = name ,
496+                     raw_bssid = bssid ,
497+                     raw_rssi = rssi ,
498+                     raw_channel = channel ,
499+                     raw_authmode = authmode ,
500+                 )
501+             )
410502        return  APs 
411503
412504    def  scan_networks (self ):
@@ -512,23 +604,12 @@ def _wifi_set_ap_passphrase(self, ssid, passphrase, channel):
512604            raise  OSError ("Failed to setup AP password" )
513605
514606    @property  
515-     def  ssid (self ):
516-         """The name of the access point we're connected to""" 
517-         resp  =  self ._send_command_get_response (_GET_CURR_SSID_CMD , [b"\xFF " ])
518-         return  resp [0 ]
519- 
520-     @property  
521-     def  bssid (self ):
522-         """The MAC-formatted service set ID of the access point we're connected to""" 
523-         resp  =  self ._send_command_get_response (_GET_CURR_BSSID_CMD , [b"\xFF " ])
524-         return  resp [0 ]
525- 
526-     @property  
527-     def  rssi (self ):
528-         """The receiving signal strength indicator for the access point we're 
529-         connected to""" 
530-         resp  =  self ._send_command_get_response (_GET_CURR_RSSI_CMD , [b"\xFF " ])
531-         return  struct .unpack ("<i" , resp [0 ])[0 ]
607+     def  ap_info (self ):
608+         """Network object containing BSSID, SSID, authmode, channel, country and RSSI when 
609+         connected to an access point. None otherwise.""" 
610+         if  self .is_connected :
611+             return  Network (esp_spi_control = self )
612+         return  None 
532613
533614    @property  
534615    def  network_data (self ):
@@ -942,7 +1023,7 @@ def set_digital_read(self, pin):
9421023        :param int pin: ESP32 GPIO pin to read from. 
9431024        """ 
9441025        # Verify nina-fw => 1.5.0 
945-         fw_semver_maj  =  bytes ( self .firmware_version ). decode ( "utf-8" ) [2 ]
1026+         fw_semver_maj  =  self .firmware_version [2 ]
9461027        assert  int (fw_semver_maj ) >=  5 , "Please update nina-fw to 1.5.0 or above." 
9471028
9481029        resp  =  self ._send_command_get_response (_SET_DIGITAL_READ_CMD , ((pin ,),))[0 ]
@@ -961,7 +1042,7 @@ def set_analog_read(self, pin, atten=ADC_ATTEN_DB_11):
9611042        :param int atten: attenuation constant 
9621043        """ 
9631044        # Verify nina-fw => 1.5.0 
964-         fw_semver_maj  =  bytes ( self .firmware_version ). decode ( "utf-8" ) [2 ]
1045+         fw_semver_maj  =  self .firmware_version [2 ]
9651046        assert  int (fw_semver_maj ) >=  5 , "Please update nina-fw to 1.5.0 or above." 
9661047
9671048        resp  =  self ._send_command_get_response (_SET_ANALOG_READ_CMD , ((pin ,), (atten ,)))
0 commit comments