import socket, network, wifi, time, binascii, machine, select, _thread mac_address = wifi._STA_IF.config("mac") ap_ssid = "badge-{}".format(binascii.hexlify(mac_address).decode("ascii")) ap_password = None wifiList = [] def start_ap(): global ap_ssid, ap_password ap_if = network.WLAN(network.AP_IF) ap_if.active(True) if ap_password: ap_if.config(essid=ap_ssid, authmode=network.AUTH_WPA2_PSK, password=ap_password) else: ap_if.config(essid=ap_ssid, authmode=network.AUTH_OPEN) def stop_ap(): ap_if = network.WLAN(network.AP_IF) ap_if.active(False) def dnsserver(): global dns_socket ap_if = network.WLAN(network.AP_IF) dns_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) dns_socket.bind((ap_if.ifconfig()[0], 53)) http_socket.setblocking(True) def webserver(): global http_socket addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] http_socket = socket.socket() http_socket.bind(addr) http_socket.listen(True) http_socket.setblocking(True) def handle_dns(): global dns_socket ap_if = network.WLAN(network.AP_IF) try: data, addr = dns_socket.recvfrom(4096) if len(data) < 13: return domain = '' tipo = (data[2] >> 3) & 15 # Opcode bits if tipo == 0: # Standard query ini = 12 lon = data[ini] while lon != 0: domain += data[ini + 1:ini + lon + 1].decode('utf-8') + '.' ini += lon + 1 lon = data[ini] packet = data[:2] + b'\x81\x80' packet += data[4:6] + data[4:6] + b'\x00\x00\x00\x00' # Questions and Answers Counts packet += data[12:] # Original Domain Name Question packet += b'\xC0\x0C' # Pointer to domain name packet += b'\x00\x01\x00\x01\x00\x00\x00\x3C\x00\x04' # Response type, ttl and resource data length -> 4 bytes packet += bytes(map(int, ap_if.ifconfig()[0].split('.'))) # 4bytes of IP dns_socket.sendto(packet, addr) except: pass def handle_web(): global http_socket try: cl, addr = http_socket.accept() except: return try: cl_file = cl.makefile('rwb', 0) request = cl_file.recv(4096).decode("utf-8") request = request.split("\r\n") url = request[0].split(" ")[1] firstLine = True emptyCount = 0 formData = {} notFound = False for line in request: if line == '': emptyCount += 1 continue if firstLine: if not line.startswith("POST"): if not line.startswith("GET / "): notFound = True break firstLine = False continue if emptyCount > 0: formField = line.split("=") if len(formField) == 2: formData[formField[0]] = formField[1] result = "" if "ssid" in formData or "password" in formData: result += "
"
		if "ssid" in formData:
			machine.nvs_setstr("system", "wifi.ssid", formData["ssid"])
			result += "WiFi SSID set to '{}'.\r\n".format(formData["ssid"])
		if "password" in formData:
			password = formData["password"]
			if password == "":
				password = None
			if password:
				machine.nvs_setstr("system", "wifi.password", password)
				result += "WiFi password set to '{}'.\r\n".format(password)
			else:
				try:
					machine.nvs_erase("system", "wifi.password")
				except:
					pass
				result += "No WiFi password configured, expecting open network.\r\n"
				
		if "ssid" in formData or "password" in formData:
			result += "
" if not notFound: response = 'HTTP/1.0 200 OK\r\n\r\n' response += 'Badge setup' response += '
Badge setup
' if (result != ""): response += '

Response

{}

Return to the setup screen'.format(result) else: response += '

Configuration

' ssid = machine.nvs_getstr("system", "wifi.ssid") or '' password = machine.nvs_getstr("system", "wifi.password") or '' response += ''.format(ssid) response += ''.format(password) response += '
WiFi SSID
WiFi password

' response += 'Leave the WiFi password field empty when connecting to an open network
' response += 'Connecting to enterprise networks is currently not supported!
' response += '

List of networks

' response += 'Click on a name to copy it to the WiFi SSID text field

' for i in wifiList: ssid = i[0].decode("utf-8") sec = i[5] response += '{} [{}]
'.format(ssid, ssid, sec) response += '' response += '
' else: response = "HTTP/1.0 404 Not Found\r\n\r\n
Request could not be processed.
" cl.send(response) cl.close() except BaseException as e: pass def listen(): global poll while True: readyList = poll.poll() for readyItem in readyList: if readyItem[0] is dns_socket: handle_dns() if readyItem[0] is http_socket: handle_web() def start(): global wifiList, poll wifi._STA_IF.active(True) # Needed for WiFi SSID scan start_ap() webserver() dnsserver() wifiList = wifi.scan() poll = select.poll() poll.register(http_socket, select.POLLIN) poll.register(dns_socket, select.POLLIN) _thread.start_new_thread("listen", listen, ()) start()