分类: 树莓派
捕捉系统按键ctrl-c等
捕捉Ctrl-C键盘事件
import time
import signal
def signal_handler(signal,frame):
print('You pressed Ctrl+C!')
signal.signal(signal.SIGINT,signal_handler)
print('Press Ctrl+C')
for x in range(1,100):
time.sleep(2)
print(x)
import time
if __name__ == "__main__":
try:
time.sleep(10)
except KeyboardInterrupt:
print("Application exit!")
# 自定义信号处理函数
def my_handler(signum, frame):
global stop
stop = True
print("终止")
# 设置相应信号处理的handler
signal.signal(signal.SIGINT, my_handler) #读取Ctrl+c信号
stop = False
while True:
try:
#读取到Ctrl+c前进行的操作
if stop:
# 中断时需要处理的代码
pass
# break #break只能退出当前循坏
#中断程序需要用 raise
except Exception as e:
print(str(e))
break
esp32 wifi 配置
【摘要】 我们购买智能家居产品后,买回来拆箱后第一件事通常就是给这个新的硬件进行配网,所谓配网,也就是让这个新的物联网设备联入我们的局域网内,让这个物联网设备可以进行网络通讯。我们在上一篇文章《MicroPython(ESP32/ESP8266) 实现web控制GPIO》中已经了解到了如何使用ESP32和ESP8266通过联网来实现在Web中控制板载的 LED 灯开关。本文将介绍…
我们购买智能家居产品后,买回来拆箱后第一件事通常就是给这个新的硬件进行配网,所谓配网,也就是让这个新的物联网设备联入我们的局域网内,让这个物联网设备可以进行网络通讯。我们在上一篇文章《MicroPython(ESP32/ESP8266) 实现web控制GPIO》中已经了解到了如何使用ESP32和ESP8266通过联网来实现在Web中控制板载的 LED 灯开关。本文将介绍基于 MicroPython 来实现的 ESP32/ESP8266 Wifi配网。
准备工作
在开始代码之前,需要先准备以下:
- 刷好 MicroPython 的 ESP32/ESP8266 开发版 如果不了解如何给开发版配置 Micropython的,可以参考《保姆级超详细 ESP8266 MicroPython 部署攻略》
- 有些开发版上可能没有板载的 led灯,需要自行接线到引脚上
配网流程
回想以下我们的智能家居物联网设备,以小米生态圈的设备为例,新设备开箱通电后,一般是打开米家APP,然后搜索到新买的设备,然后需要手动将wifi连接到这个设配上,然后在 APP 中填入 SSID 和 wifi密码信息,等待传输,传输完成后,就算完成配网,在 APP 的界面中就可以看到新的设备了。

配网的流程总结如上图所示。然而我们的使用当中,配网通常只发生在新设备加入或者网络环境改变的时候才需要,正常情况下设备重启,是不需要每一次都要来一次配网操作的。所以一般情况下,在一次配网之后,我们会将我们的Wifi信息保存下来,设备重启后如果有存在的配网信息,会自动直接联网。

而针对我们整个开发版的程序,我们可以在 main.py
执行在开始,就先执行网络检查,然后根据是否成功联网来判断是否需要配网操作,流程如下:

MicroPython Wifi 操作
上文梳理了整个配网过程的流程。在这个流程中,最开始的步骤就是判断网络是否连接。以下将介绍如何使用 MicroPython 操作开发板的 Wifi。
我们开发板(ESP32/ESP8266)的wifi有AP和STA模式,AP就是开发版上创建一个热点,其他设备连接到AP上,而STA模式和我们普通的手机电脑使用Wifi联网类似。这里的要点就是我们需要检查STA模式下开发版是否能正常联网,如果不能,我们利用开发板的AP模式,让我们的其他设备连接开发板,把我们局域网Wifi的配置信息告知开发板,从而使开发板能正常联网。
import network
wlan_sta = network.WLAN(network.STA_IF)
wlan_sta.isconnected()
通过调用 isconnected()
函数,可以获取到开发板是否正常联网,如果正常联网,返回结果会是 True
否则为 False
。
wlan_sta.scan()
scan()
函数扫描设备附近可以搜索到的 Wifi,会返回一个列表,列表中每一条为可连接wifi的信息。
[(b'WifiSSID', b'LPw\xb7\xs8\x94', 1, -48, 3, 0),...]
以上是省略了部分信息的返回值,可以看到,每一条记录中有6个信息,它们分别代表了 SSID名称
BSSID(MAC地址)
频道
RSSI信号强度
加密模式
是否隐藏
。其中加密模式,包含了 WEP、WPA-PSK、WPA2-PSK、WPA/WPA2-PSK等。
接下来,我们就可以尝试连接Wifi。
wlan_sta.connect('ssid', 'password')
wlan_sta.isconnected()
如果连接成功,则返回 True
。如果需要断开连接,可以使用 disconnect()
函数。
wlan_sta.disconnect()
MicroPython AP操作
完成了 Wifi 连接和检查网络是否正常后,我们开始解决利用 AP 配网的问题。
先看代码:
import network
import socket
wlan_ap = network.WLAN(network.AP_IF)
wlan_ap.active(True)
wlan_ap.config(essid='MyESP8266',authmode=0)
server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 80))
server_socket.listen(3)
def web_page(): return b"""<html> <head> <title>MYESP8266 AP Test</title> </head> <body> <h1>This is MyESP8266 AP Test Page.</h1> </body> </html>"""
while True: conn, addr = server_socket.accept() print('Connection: %s ' % str(addr)) response = web_page() conn.send('HTTP/1.1 200 OK\n') conn.send('Content-Type: text/html\n') conn.send('Connection: close\n\n') conn.sendall(response) conn.close()
从上面的代码我们可以看到,当我们创建好AP后,就打开一个 socket ,并且绑定80端口开始监听,然后开启一个循环,当接受到连接后就给客户端发送页面代码。如果对 socket 不了解的,可以参考《快速了解Python socket编程》。
这时用手机或者电脑的 wifi 连接 SSID 名为 MYESP8266 的 Wifi 热点,因为我们authmode选择了 open
所以不需要密码。连接成功后,用浏览器打开地址 192.168.4.1
,就可以看到我们上面的页面。
针对 MicroPython 的 Web 编程
我们一般情况下,如果要进行 Web 开发,通常会使用 Flask 或者 Django 之类的框架。而针对开发版这种运算能力有限的硬件,也有对应的框架可以用。但我们这里为了能深入的了解,就通过自己完成最基本的功能来了解整个程序的运行方式。
封装HTML响应
根据上面的示例代码,我们可以了解到,如果要在客户端正常显示页面,我们需要先给客户端发一个HTTP的Header信息,然后再发送具体的页面内容。所以,为了方便日后的调用,我们对上面的代码进行修改:
import network
import socket
wlan_ap = network.WLAN(network.AP_IF)
wlan_ap.active(True)
wlan_ap.config(essid='MyESP8266',authmode=0)
server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 80))
server_socket.listen(3)
def send_header(conn, status_code=200, content_length=None ): conn.sendall("HTTP/1.0 {} OK\r\n".format(status_code)) conn.sendall("Content-Type: text/html\r\n") if content_length is not None: conn.sendall("Content-Length: {}\r\n".format(content_length)) conn.sendall("\r\n")
def send_response(conn, payload, status_code=200): content_length = len(payload) send_header(conn, status_code, content_length) if content_length > 0: conn.sendall(payload) conn.close()
def config_page(): return b"""<html> <head> <title>MYESP8266 AP Test</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>Wifi 配网</h1> <form action="configure" method="post"> <div> <label>SSID</label> <input type="text" name="ssid"> </div> <div> <label>PASSWORD</label> <input type="password" name="password"> </div> <input type="submit" value="连接"> <form> </body> </html>"""
while True: conn, addr = server_socket.accept() print('Connection: %s ' % str(addr)) try: conn.settimeout(3) request = b"" try: while "\r\n\r\n" not in request: request += conn.recv(512) except OSError: pass print(request) response = config_page() send_response(conn, response)
finally: conn.close()
我们添加了三个函数,分别为 send_header()
send_response()
config_page()
。其中 send_header()
把我们需要发送的 Header 信息打包,config_page()
则是创建我们的 HTML 页面,最后由 send_response()
将其整合,发送给客户端。

运行代码,如果正常,用手机连接开发板的AP,打开 192.168.4.1
,就可以看到上图的页面。
路由
上面的代码中,页面中有一个 form
,里面可以输入 SSID 和 Wifi 密码,当我们输入完成后,点击连接,将会将我们输入的内容 POST 到 /configure 路径中。处理这个问题,在 Web 框架中,会有现成的路由模块,但这里我们需要自己用代码进行处理。
我们的代码中,当客户端连接后,我们的开发板会接受来自客户端传来的信息——request
,打印这个变量看看客户端传来的内存:
# 连接 192.168.4.1
Connection: ('192.168.4.2', 44794)
b'GET / HTTP/1.1\r\nUser-Agent: Dalvik/2.1.0 (Linux; U; Android 9; MIX 2 MIUI/20.6.18)\r\nHost: 192.168.4.1\r\nConnection: Keep-Alive\r\nAccept-Encoding: gzip\r\n\r\n'
# 连接 192.168.4.1/test
b'GET /test HTTP/1.1\r\nHost: 192.168.4.1\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nUser-Agent: Mozilla/5.0 (Linux; Android 9; MIX 2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.82 Mobile Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n\r\n'
# 输入信息,点击连接按钮
b'POST /configure HTTP/1.1\r\nHost: 192.168.4.1\r\nConnection: keep-alive\r\nContent-Length: 26\r\nCache-Control: max-age=0\r\nUpgrade-Insecure-Requests: 1\r\nOrigin: http://192.168.4.1\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/5.0 (Linux; Android 9; MIX 2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.82 Mobile Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nReferer: http://192.168.4.1/\r\nAccept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n\r\nssid=xdbdh&password=ddjxdj'
可以看到,当我们连接不同的地址,开发板接受到的信息是不同的,我们就可以通过正则表达式来抓去不同的内容即可实现类似 Web 框架路由的功能。
try: url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).decode("utf-8").rstrip("/") except Exception: url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).rstrip("/") print("URL is {}".format(url))
我们将上面 print()
函数替换乘上面的代码,再尝试上面三个地址:
# 连接 192.168.4.1
URL is
# 连接 192.168.4.1/test
URL is test
# 输入信息,点击连接按钮
URL is configure
这样,我们的精简版路由功能就完成了。
POST 传参获取
解决了页面显示和路由,剩下就是如何获取 POST 的传参了。我们再看一次当我们使用 POST 时,返回过来的信息:
b'POST /configure HTTP/1.1\r\n
Host: 192.168.4.1\r\n
Connection: keep-alive\r\n
Content-Length: 26\r\n
Cache-Control: max-age=0\r\n
Upgrade-Insecure-Requests: 1\r\n
Origin: http://192.168.4.1\r\n
Content-Type: application/x-www-form-urlencoded\r\nUser-Agent: Mozilla/5.0 (Linux; Android 9; MIX 2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.82 Mobile Safari/537.36\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nReferer: http://192.168.4.1/\r\n
Accept-Encoding: gzip, deflate\r\nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n\r\n
ssid=xdbdh&password=ddjxdj'
可以看到,信息开头是 POST 方法,然后结 ssid=....&password=...
就是我们传过来的参数,和处理路由的方法类似,我们使用正则表达式过滤一下,即可获取到我们需要的 ssid 和 Wifi 密码了。
# POST 参数解析
def get_wifi_conf(request): match = ure.search("ssid=([^&]*)&password=(.*)", request) if match is None: return False try: ssid = match.group(1).decode("utf-8").replace("%3F", "?").replace("%21", "!") password = match.group(2).decode("utf-8").replace("%3F", "?").replace("%21", "!") except Exception: ssid = match.group(1).replace("%3F", "?").replace("%21", "!") password = match.group(2).replace("%3F", "?").replace("%21", "!") if len(ssid) == 0: return False return (ssid, password)
我们再修改一下代码,添加一个新页面,用来显示 ssid 和 Wifi 密码,来确认我们的路由功能和 POST 参数正常获取。
def wifi_conf_page(ssid, passwd): return b"""<html> <head> <title>Wifi Conf Info</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>Post data:</h1> <p>SSID: %s</p> <p>PASSWD: %s</p> <a href="https://bbs.huaweicloud.com/">Return Configure Page</a> </body> </html>""" % (ssid, passwd)
修改后的代码:
# 前面相同的部分省略
while True: conn, addr = server_socket.accept() print('Connection: %s ' % str(addr)) try: conn.settimeout(3) request = b"" try: while "\r\n\r\n" not in request: request += conn.recv(512) except OSError: pass # url process try: url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).decode("utf-8").rstrip("/") except Exception: url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).rstrip("/") print("URL is {}".format(url)) if url == "": response = config_page() send_response(conn, response) elif url == "configure": ret = get_wifi_conf(request) response = wifi_conf_page(ret[0], ret[1]) send_response(conn, response) finally: conn.close()
执行代码,输入 ssid 和密码后,点击连接,应该能跳转到新页面并且显示刚才输入的 ssid 和密码。点击返回,能重新跳回信息输入的页面。

Wifi连接
在《MicroPython(ESP32/ESP8266) 实现web控制GPIO》中,我们已经介绍了如何通过 connect()
方法来连接我们已知的 Wifi。接下来,我们要做的也很简单,就是创建一个 do_connect()
方法来处理我们上面传过来的 ssid 和密码。
def do_connect(ssid, password): wlan_sta.active(True) if wlan_sta.isconnected(): return None print('Connect to %s' % ssid) wlan_sta.connect(ssid, password) for retry in range(100): connected = wlan_sta.isconnected() if connected: break time.sleep(0.1) print('.', end='') if connected: print('\nConnected : ', wlan_sta.ifconfig()) else: print('\nFailed. Not Connected to: ' + ssid) return connected
可以看到,这个函数会接受传来的 wifi 配置参数,进行连接,如果成功,会返回 True。然后我们还还需要一个执行连接的方法,这个方法用于连接成功,就自动获取连如局域网后的ip地址。
def handle_wifi_configure(ssid, password): if do_connect(ssid, password): new_ip = wlan_sta.ifconfig()[0] return new_ip else: print('connect fail') return False
这些都完成后,我们只需要把开发板 AP 联网配置部分封装好,成为一个 start_ap()
方法,即可:
# response 的方法都为创建 HTML 代码方法,这里省略
# 可以在文末完整代码中查看
def startAP(): global server_socket stop() wlan_ap.active(True) wlan_ap.config(essid='MyEsp8266',authmode=0) server_socket = socket.socket() server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind(('0.0.0.0', 80)) server_socket.listen(3) while not wlan_sta.isconnected(): conn, addr = server_socket.accept() print('Connection: %s ' % str(addr)) try: conn.settimeout(3) request = b"" try: while "\r\n\r\n" not in request: request += conn.recv(512) except OSError: pass # url process try: url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).decode("utf-8").rstrip("/") except Exception: url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).rstrip("/") print("URL is {}".format(url)) if url == "": response = config_page() send_response(conn, response) elif url == "configure": ret = get_wifi_conf(request) ret = handle_wifi_configure(ret[0], ret[1]) if ret is not None: response = connect_sucess(ret) send_response(conn, response) print('connect sucess') elif url == "disconnect": wlan_sta.disconnect() finally: conn.close() wlan_ap.active(False) print('ap exit')
这里我们实现的功能为让开发板创建AP,生成一个 Wifi 信息的配置页面,然后通过路由来处理输入和参数,最后执行 Wifi 联网,如果连接成功,即退出循环,关闭 AP 热点。
我们从用手机输入完成点击连接后,如果连接成功,将会自动返回成功连接的页面:

到这里,我们的 wifi 配网就已经基本完成了。
总结
本文开始先从配网的需求、流程进行分析,然后一步步分别介绍 MicroPython Wifi的操作,AP的使用以及简单的 Web 实现,然后将上述的要点结合我们的配网需求,完成完整的设配配网代码开发。
但是,文章为了比较清晰的展示内容,因此在代码上可能会显得比较冗长和繁复,有很大的优化空间。大家可以根据自己的实际情况,对代码进行进一步的优化和调整,以下给出几个可以调整方法:
- 优化代码结构,模块化部分功能
- 将 web 部分整合成一个模块,比如带有 html 模板渲染功能的模块、路由模块灯
- 尝试在用户体验上优化配网的流程
- 其他创新的需求等……
此外,还存还存在一个问题,就是可能因为 ESP8266 的内存和算力问题,代码运行的时候有时会出错和跳出,需要重启或者断电,但同样的代码在 ESP32 开发板上,却没有问题。可能是 MircoPython 的问题,也有可能是因为代码设计问题,这方面需要进一步研究和尝试。
物联网开发涉及到很多硬件和软件的问题,但是在实践中,经常会遇到各种奇怪的问题,这很可能打击了学习的热情,加上网上的教程和示例不多,初学者更容易遇到问题解决不了而不得不放弃。本文尽可能的详细解释代码和原理,但由于水平经验有限,难免会有所疏漏, 望读者见谅,并且欢迎大家一起来交流进步。
希望本文对你有用。如果你觉得文章对你用,记得关注收藏。你的关注和收藏是继续更新的动力哦。
附:完整代码
import network
import socket
import ure
import time
NETWORK_PROFILES = 'wifi.dat'
wlan_ap = network.WLAN(network.AP_IF)
wlan_sta = network.WLAN(network.STA_IF)
server_socket = None
def send_header(conn, status_code=200, content_length=None ): conn.sendall("HTTP/1.0 {} OK\r\n".format(status_code)) conn.sendall("Content-Type: text/html\r\n") if content_length is not None: conn.sendall("Content-Length: {}\r\n".format(content_length)) conn.sendall("\r\n")
def send_response(conn, payload, status_code=200): content_length = len(payload) send_header(conn, status_code, content_length) if content_length > 0: conn.sendall(payload) conn.close()
def config_page(): return b"""<html> <head> <title>MYESP8266 AP Test</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>Wifi 配网</h1> <form action="configure" method="post"> <div> <label>SSID</label> <input type="text" name="ssid"> </div> <div> <label>PASSWORD</label> <input type="password" name="password"> </div> <input type="submit" value="连接"> <form> </body> </html>"""
def wifi_conf_page(ssid, passwd): return b"""<html> <head> <title>Wifi Conf Info</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>Post data:</h1> <p>SSID: %s</p> <p>PASSWD: %s</p> <a href="https://bbs.huaweicloud.com/">Return Configure Page</a> </body> </html>""" % (ssid, passwd)
def connect_sucess(new_ip): return b"""<html> <head> <title>Connect Sucess!</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <p>Wifi Connect Sucess</p> <p>IP Address: %s</p> <a href="http://%s">Home</a> <a href="https://bbs.huaweicloud.com/disconnect">Disconnect</a> </body> </html>""" % (new_ip, new_ip)
def get_wifi_conf(request): match = ure.search("ssid=([^&]*)&password=(.*)", request) if match is None: return False try: ssid = match.group(1).decode("utf-8").replace("%3F", "?").replace("%21", "!") password = match.group(2).decode("utf-8").replace("%3F", "?").replace("%21", "!") except Exception: ssid = match.group(1).replace("%3F", "?").replace("%21", "!") password = match.group(2).replace("%3F", "?").replace("%21", "!") if len(ssid) == 0: return False return (ssid, password)
def handle_wifi_configure(ssid, password): if do_connect(ssid, password):
# try:
# profiles = read_profiles()
# except OSError:
# profiles = {}
# profiles[ssid] = password
# write_profiles(profiles)
#
# time.sleep(5)
# new_ip = wlan_sta.ifconfig()[0] return new_ip else: print('connect fail') return False
def check_wlan_connected(): if wlan_sta.isconnected(): return True else: return False def do_connect(ssid, password): wlan_sta.active(True) if wlan_sta.isconnected(): return None print('Connect to %s' % ssid) wlan_sta.connect(ssid, password) for retry in range(100): connected = wlan_sta.isconnected() if connected: break time.sleep(0.1) print('.', end='') if connected: print('\nConnected : ', wlan_sta.ifconfig()) else: print('\nFailed. Not Connected to: ' + ssid) return connected
def read_profiles(): with open(NETWORK_PROFILES) as f: lines = f.readlines() profiles = {} for line in lines: ssid, password = line.strip("\n").split(";") profiles[ssid] = password return profiles
def write_profiles(profiles): lines = [] for ssid, password in profiles.items(): lines.append("%s;%s\n" % (ssid, password)) with open(NETWORK_PROFILES, "w") as f: f.write(''.join(lines)) def stop(): global server_socket if server_socket: server_socket.close() server_socket = None
def startAP(): global server_socket stop() wlan_ap.active(True) wlan_ap.config(essid='MyEsp8266',authmode=0) server_socket = socket.socket() server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind(('0.0.0.0', 80)) server_socket.listen(3) while not wlan_sta.isconnected(): conn, addr = server_socket.accept() print('Connection: %s ' % str(addr)) try: conn.settimeout(3) request = b"" try: while "\r\n\r\n" not in request: request += conn.recv(512) except OSError: pass # url process try: url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).decode("utf-8").rstrip("/") except Exception: url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).rstrip("/") print("URL is {}".format(url)) if url == "": response = config_page() send_response(conn, response) elif url == "configure": ret = get_wifi_conf(request) ret = handle_wifi_configure(ret[0], ret[1]) if ret is not None: response = connect_sucess(ret) send_response(conn, response) print('connect sucess') elif url == "disconnect": wlan_sta.disconnect() finally: conn.close() wlan_ap.active(False) print('ap exit')
def home(): global server_socket stop() wlan_sta.active(True) ip_addr = wlan_sta.ifconfig()[0] print('wifi connected') server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind(('0.0.0.0', 80)) server_socket.listen(3) while check_wlan_connected(): conn, addr = server_socket.accept() try: conn.settimeout(3) request = b"" try: while "\r\n\r\n" not in request: request += conn.recv(512) except OSError: pass # url process try: url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).decode("utf-8").rstrip("/") except Exception: url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).rstrip("/") if url == "": response = connect_sucess(ip_addr) send_response(conn, response) elif url == "disconnect": wlan_sta.disconnect() finally: conn.close() wlan_sta.active(False) print('sta exit')
def main(): while True: if not check_wlan_connected(): startAP() else: home() main()
原文链接:
更新树莓派固件
树莓派固件更新,一些版本使用sudo UPDATE_SELF=0 rpi-update失败,可以按以下方式更新:
sudo apt update && sudo apt full-upgrade -y
sudo reboot
sudo rpi-eeprom-update -a
sudo reboot
sudo rpi-eeprom-update
基于miropython环境下esp32的wifi配网
python 基础
去除Envo Storefront主题的底部版权信息
今天发现一个wordpress的主题不错,风格超赞,但底部的“自豪地采用wordprss及Envo Storefront”极其刺眼,到网上找了一圈,没有看到去除的方法,于是自己动手,发现这个主题厂家很鬼,将版权信息放在了一个特殊的地方,修改如下:




密码保护:树莓派系统一键安装wordpress并设置网站无人值守程序
密码保护:自动浇灌电路
常用元器件英文翻译
部分分立元件名称中英对照表
AND ————与门
ANTENNA ——天线
BATTERY—— 直流电源
BELL ————铃,钟
BVC—— ——同轴电缆接插件
BRIDEG 1 ——整流桥(二极管)
BRIDEG 2 ——整流桥(集成块)
BUFFER ——缓冲器
BUZZER—— 蜂鸣器
CAP ————电容
CAPACITOR ——电容
CAPACITOR POL ——有极性电容
CAPVAR ——————可调电容
CIRCUIT BREAKER ——熔断丝
COAX ——————同轴电缆
CON ——————插口
CRYSTAL ————晶体整荡器
DB* ————并行插口
DIODE ————二极管
DIODE SCHOTTKY ——稳压二极管
DIODE VARACTOR ——变容二极管
DPY_3-SEG ————3段LED
DPY_7-SEG ————7段LED
DPY_7-SEG_DP ———7段LED(带小数点)
ELECTRO ————电解电容
FUSE ————熔断器
INDUCTOR———— 电感
INDUCTOR IRON ———带铁芯电感
INDUCTOR3 ————可调电感
JFET N ————n沟道场效应管
JFET P ————P沟道场效应管
LAMP ————灯泡
LAMP NEDN ——起辉器
LED ————发光二极管
METER ——————仪表
MICROPHONE ————麦克风
MOSFET———— mos管
MOTOR AC ————交流电机
MOTOR SERVO ——伺服电机
NAND ——————与非门
NOR ——————或非门
NOT ——————非门
NPN ————NPN型三极管
NPN-PHOTO—— 感光三极管
OPAMP ————运放
OR ————或门
PHOTO ————感光二极管
PNP ————PNP型三极管
NPN DAR ————NPN三极管
PNP DAR ————PNP三极管
POT 1和POT2————滑线变阻器
PELAY-DPDT ————双刀双掷继电器
RES1和RES2——电阻
RES3和RES4 ——可变电阻
RESISTOR BRIDGE ——桥式电阻
RESPACK1~~RESPACK4 ——排阻
SCR ———晶闸管
PLUG——插头
PLUG AC FEMALE和PLUG AC MALE ——三相交流插头
SOCKET——插座
SOURCE CURRENT—— 电流源
SOURCE VOLTAGE ——电压源
SPEAKER—— 扬声器
SW-DIP2~~SW-DIP9————开关
SW-DPDT ———— 双刀双掷开关
SW-DPST ———— 双刀单掷开关
SW-SPST————单刀单掷开关
SW-SPPT————单刀双掷开关
SW-PB ————按钮(开关)
THERMISTOR ————电热调节器
TRANS1 ————变压器
TRANS2 ————可调变压器
TRIAC———— 三端双向可控硅
TRIODE ————三极真空管
VARISTOR ————变阻器
ZENER1~~ZENER3————稳压二极管
DPY_7-SEG和DPY_7-SEG_DP ————数码管
Protel DOS Schematic Libraries.ddb 元件库及部分元件中英对照表
Protel Dos Schematic 4000 Cmos .Lib ———— 40.系列CMOS管集成块元件库( 例:4013 D 触发器 和4027 JK 触发器 )
来源:xiangtan.ourtimes.ren
Protel Dos Schematic analog Digital.Lib ———— 模拟数字式集成块元件库(AD系列 DAC系列 HD系列 MC系列 )
Protel Dos Schematic Comparator.Lib ————比较放大器元件库
Protel Dos Shcematic Intel.Lib ———————INTEL公司生产的80系列CPU集成块元件库
Protel Dos Schematic linear.lib ————————线性元件库( 例:555 )
Protel Dos Schemattic Memory Devices.Lib ————内存存储器元件库
Protel Dos Schematic SYnertek.Lib ————————SY系列集成块元件库
Protes Dos Schematic Motorlla.Lib———— ————摩托罗拉公司生产的元件库
Protes Dos Schematic NEC.lib———— ————NEC公司生产的集成块元件库
Protes Dos Schematic Operationel Amplifers.lib ————运算放大器元件库
Protes Dos Schematic TTL.Lib ————————晶体管集成块元件库 74系列
Protel Dos Schematic Voltage Regulator.lib ————电压调整集成块元件库
Protes Dos Schematic Zilog.Lib ————————齐格格公司生产的Z80系列CPU集成块元件库
74系列:
74LS00 ————TTL 2输入端四与非门
74LS01 ————TTL 集电极开路2输入端四与非门
74LS02 ————TTL 2输入端四或非门来源:xiangtan.ourtimes.ren
74LS03 ————TTL 集电极开路2输入端四与非门
74LS122———— TTL 可再触发单稳态多谐振荡器
74LS123 ————TTL 双可再触发单稳态多谐振荡器
74LS125 ————TTL 三态输出高有效四总线缓冲门
74LS126 ————TTL 三态输出低有效四总线缓冲门
74LS13 ————TTL 4输入端双与非施密特触发器
74LS132 ————TTL 2输入端四与非施密特触发器
74LS133 ————TTL 13输入端与非门
74LS136 ————TTL 四异或门
74LS138 ————TTL 3-8线译码器/复工器
74LS139 ————TTL 双2-4线译码器/复工器
74LS14 ————TTL 六反相施密特触发器
74LS145 ————TTL BCD—十进制译码/驱动器
74LS15 ————TTL 开路输出3输入端三与门
74LS150 ————TTL 16选1数据选择/多路开关
74LS151 ————TTL 8选1数据选择器
74LS153 ————TTL 双4选1数据选择器
74LS154 ————TTL 4线—16线译码器
74LS155———— TTL 图腾柱输出译码器/分配器
74LS156 ————TTL 开路输出译码器/分配器
74LS157 ————TTL 同相输出四2选1数据选择器
74LS158———— TTL 反相输出四2选1数据选择器
74LS16 ————TTL 开路输出六反相缓冲/驱动器
74LS160———— TTL 可预置BCD异步清除计数器
74LS161 ————TTL 可予制四位二进制异步清除计数器
74LS162 ————TTL 可预置BCD同步清除计数器
74LS163 ————TTL 可予制四位二进制同步清除计数器
74LS164 ————TTL 八位串行入/并行输出移位寄存器
74LS165 ————TTL 八位并行入/串行输出移位寄存器
74LS166 ————TTL 八位并入/串出移位寄存器
74LS169 ————TTL 二进制四位加/减同步计数器
74LS17 ————TTL 开路输出六同相缓冲/驱动器
74LS170 ————TTL 开路输出4×4寄存器堆
74LS173 ————TTL 三态输出四位D型寄存器
74LS174 ————TTL 带公共时钟和复位六D触发器
74LS175 ————TTL 带公共时钟和复位四D触发器
74LS180 ————TTL 9位奇数/偶数发生器/校验器
74LS181 ————TTL 算术逻辑单元/函数发生器
74LS185 ————TTL 二进制—BCD代码转换器
74LS190 ————TTL BCD同步加/减计数器
74LS191 ————TTL 二进制同步可逆计数器
74LS192———— TTL 可预置BCD双时钟可逆计数器
74LS193 ————TTL 可预置四位二进制双时钟可逆计数器
74LS194 ————TTL 四位双向通用移位寄存器
来源:xiangtan.ourtimes.ren
74LS195————TTL 四位并行通道移位寄存器
74LS196 ————TTL 十进制/二-十进制可预置计数锁存器
74LS197 ————TTL 二进制可预置锁存器/计数器
74LS20 ————TTL 4输入端双与非门
74LS21 ————TTL 4输入端双与门
74LS22 ————TTL 开路输出4输入端双与非门
74LS221 ————TTL 双/单稳态多谐振荡器
74LS240 ————TTL 八反相三态缓冲器/线驱动器
74LS241 ————TTL 八同相三态缓冲器/线驱动器
74LS243 ————TTL 四同相三态总线收发器
74LS244 ————TTL 八同相三态缓冲器/线驱动器
74LS245 ————TTL 八同相三态总线收发器
74LS247 ————TTL BCD—7段15V输出译码/驱动器
74LS248 ————TTL BCD—7段译码/升压输出驱动器
74LS249 ————TTL BCD—7段译码/开路输出驱动器
74LS251 ————TTL 三态输出8选1数据选择器/复工器
74LS253 ————TTL 三态输出双4选1数据选择器/复工器