使ESP32进入wifi的STA和AP混合模式进行配网(micropython环境)

       我们在用ESP32做开发时,由于初始化配网的需要,往往是需要工作在AP模式,但是也要能使用STA模式的扫描功能,列出周围可用的wifi热点列表,方便用户通过选择的方式输入热点名。这就需要进入STA和AP的混合模式。

       但是,在micropython的标准文档中,wifi的模式只有STA和AP两种模式,似乎没有混合模式。并且STA模式和AP模式的切换很容易出现扫描不到周围的wifi热点、wifi模块报unknown error 0x0102错误导致wifi模块失效等问题。

       为此,笔者经过研究发现,micropython可以通过以下代码方法(注意代码中的注释)稳妥操作wifi模块进入STA与AP的混合模式,充当AP的同时,可以扫描出周围的wifi热点供配网使用。

       具体场景是这样的:

       1.ESP32启动时,尝试读取设备上保存的wifi热点配置文件。如果找不到配置文件,或者连接不上配置文件中的热点,就进入AP模式,启动web服务,等待用户登录web进行热点信息配置(所谓配网)。

       wifi热点配置文件wificonfig.json内容如下:

       {"wifiname": "YourRouterName", "wifipassword": "YourRouterPassword"}

       该文件的自动生成和WEB服务配网部分代码不是此文重点,不在此叙述,需要的可以私信我。测试后述代码时,人工生成一个wificonfig.json在根目录即可。

       2.ESP32启动时,如果能顺利连接到配置文件中的热点,就直接进入STA正常模式,不开启AP功能。该模式也就是完成了配网之后设备的正常运行模式,该模式下也应该通过WEB提供热点信息的修改功能,以方便用户修改。

       以下为代码。




class myWifiSet:
    def __init__(self) :
        self.Mode          =""
        self.APList        ={}#保存热点扫描结果
        #先尝试进入STA模式,连接热点,如果出错,就进入STA和AP混合模式
        if self.StaMode()==False:
            self.APMode()
            print("连接热点失败,进入STA&AP混合模式...")
            self.Mode="Hybrid"
        else:
            print("已进入STA模式,连接热点成功!")
            self.Mode="STA"
            
    def scanAP(self):
        #此方法只能在本类实例化后才能调用,即wifi变量已存在
        import utime,ujson
        #try:
        #    self.wifi.scan()#先尝试一次扫描
        #except:
        #    pass
        print("now in %s mode"%self.Mode)
        #self.wifi.active(False)#启停一次,确保扫描成功
        #utime.sleep(0.5)
        #self.wifi.active(True)
        #utime.sleep(0.5)
        #有时模块会读不出来信号弱的路由器名,因此写一段把名字为空的热点全部干掉!
        try:
            self.APList=self.wifi.scan()
            print("扫描AP结束,列表如下:")
            print(self.APList)
            f=open("/wifiAPList.json","w")
            #print(APList_json)
            for item in self.APList:
                print(item)
                if item[0]==b'':
                    print("one item deleted!")
                    self.APList.remove(item)
            for item in self.APList:
                print(item)
                if item[0]==b'':
                    print("one item deleted!")
                    self.APList.remove(item)
            APList_json=ujson.dumps(self.APList)
            f.write(APList_json)
            f.flush()
            f.close()
        except Exception as e:
            print("扫描AP错误:%s"%str(e))

    def StaMode(self):
        import json,utime,network
        try:
            with open('/wificonfig.json','r') as f:
                config = json.loads(f.read())
        # 若初次运行,则将进入excpet     
        except:
            print('WIFI配置文件错误!')
            return False
        #以下为正常的WIFI连接流程        
        self.wifi = network.WLAN(network.STA_IF)
        self.wifi.active(True)
        utime.sleep(0.5)

        if not self.wifi.isconnected(): 
            print('正在连接到热点%s...'%config['wifiname'])
            self.wifi.active(True)
            self.wifi.connect(config['wifiname'], config['wifipassword']) 
            import utime

            for i in range(10):
                print('第{}次尝试连接WIFI热点'.format(i+1))
                if self.wifi.isconnected():
                    break
                utime.sleep(2) #一般睡个5-10秒,应该绰绰有余
            
            if not self.wifi.isconnected():
                return False
            else:
                print('network config:',self.wifi.ifconfig())
                return True
        else:
            print('network config:', self.wifi.ifconfig())
            return True
            
    def APMode(self):
        #此方法为重点
        import utime,network
        try:
            if self.wifi.status()==network.STAT_CONNECTING:
                #变量wifi不存在的话,也会进入except
                print("强制退出STAT_CONNECTING状态...")
                #要想进入混合模式,就先进STA模式。
                #进入STA模式后,如果连接路由器失败,会一直停留在STA_CONNECTING状态
                #因此,先active(False)强制退出STA_CONNECTING状态,再active(True)回到STA初始状态
                #这样会避免后面scan()出现STA_CONNECTING状态禁止扫描的问题,同时也能进入混合模式
                self.wifi.active(False)
                self.wifi.active(True)
        except:
            pass
        self.wifi=network.WLAN(network.AP_IF)
        self.wifi.active(False)
        self.wifi.active(True)
        
#以下为测试代码
if __name__ == "__main__":
    import network
    #初始化时直接尝试进入STA模式连接热点,连接出错时进入STA与AP混合模式
    x=myWifiSet()
    if x.Mode=="STA":
        print("11111")
    elif x.Mode=="Hybrid":
        print("22222")
    #尝试扫描AP。不管在STA还是STA与AP混合模式,均可用以下方法正确扫描周围的AP列表
    x.scanAP()
    print(x.APList)
    



以上代码可以单独存为一个.py文件,由main.py通过import方式调用即可。

注意:

1.不要尝试直接去单独调用STAMode()和APMode()两个方法,在初始化时,操作wifi的步骤已经隐含在内了(先STA后AP),操作流程错误可能导致wifi模块出错。

2.不管x=myWifiSet()的结果是进入了STA模式还是AP与STA混合模式,都可在你的配网部分代码中随时调用x.scanAP()来动态扫描周围的热点。

你可能感兴趣的:(python,开发语言)