def __init__(self): self.brightness = 0 self.mode = Mode.CLOCK self.sta_if = network.WLAN(network.STA_IF) self.credentials = Creds().load() self.settings = Settings().load() routes = { b"/": b"./index.html", b"/connect": self.connect, b"/action/color": self.set_color, b"/action/clock/display": self.display_clock, b"/action/brightness/more": self.brightness_more, b"/action/brightness/less": self.brightness_less, b"/action/scoreboard/display": self.display_scoreboard, b"/action/scoreboard/green/more": self.scoreboard_green_more, b"/action/scoreboard/green/less": self.scoreboard_green_less, b"/action/scoreboard/red/more": self.scoreboard_red_more, b"/action/scoreboard/red/less": self.scoreboard_red_less, b"/action/scoreboard/reset": self.scoreboard_reset, b"/settings/values": self.settings_values, b"/settings/net": self.settings_net, b"/settings/group": self.settings_group } self.poller = poll() self.http = HTTPServer(self.poller, CaptivePortal.AP_IP, routes) print("> HTTP server started") self.clock = Clock(self.settings.color) self.loop = get_event_loop() self.loop.create_task(self.check_wifi()) self.loop.create_task(self.poll_web_server())
def __init__(self, essid=None): self.local_ip = AP_IP self.sta_if = WLAN(STA_IF) self.ap_if = WLAN(AP_IF) if essid is None: essid = b"ESP8266-%s" % binascii.hexlify(self.ap_if.config("mac")[-3:]) self.essid = essid self.creds = Creds() # Turn off station and AP interface to force a reconnect self.sta_if.active(True) self.ap_if.active(False) self.loop = asyncio.get_event_loop() self.loop.create_task(self.check_wifi())
def __init__(self, essid=None): self.local_ip = self.AP_IP self.sta_if = network.WLAN(network.STA_IF) self.ap_if = network.WLAN(network.AP_IF) if essid is None: # essid = b"ESP8266-%s" % binascii.hexlify(self.ap_if.config("mac")[-3:]) essid = 'GTurn' self.essid = essid self.creds = Creds() self.dns_server = None self.http_server = None self.poller = select.poll() self.conn_time_start = None
def login(self, params): ssid = unquote(params.get(b"ssid", None)) password = unquote(params.get(b"password", None)) # Write out credentials Creds(ssid=ssid, password=password).write() headers = (b"HTTP/1.1 307 Temporary Redirect\r\n" b"Location: http://{:s}\r\n".format(self.local_ip)) return b"", headers
class WifiManager: def __init__(self, essid=None): self.local_ip = AP_IP self.sta_if = WLAN(STA_IF) self.ap_if = WLAN(AP_IF) if essid is None: essid = b"ESP8266-%s" % binascii.hexlify(self.ap_if.config("mac")[-3:]) self.essid = essid self.creds = Creds() # Turn off station and AP interface to force a reconnect self.sta_if.active(True) self.ap_if.active(False) self.loop = asyncio.get_event_loop() self.loop.create_task(self.check_wifi()) async def start_access_point(self): while not self.ap_if.active(): self.ap_if.active(True) await asyncio.sleep(1) # IP address, netmask, gateway, DNS self.ap_if.ifconfig( (self.local_ip, "255.255.255.0", self.local_ip, self.local_ip) ) self.ap_if.config(essid=self.essid, authmode=AUTH_OPEN) print("> AP mode configured: {} ".format(self.essid.decode("utf-8")), self.ap_if.ifconfig()) async def check_wifi(self): while True: self.loop.create_task(self.connect(True)) if self.creds.load().is_valid(): await asyncio.sleep(WAIT_FOR_CONNECT) if not self.sta_if.isconnected(): self.loop.create_task(self.start_access_point()) while not self.sta_if.isconnected(): await asyncio.sleep(1) self.ap_if.active(False) while self.sta_if.isconnected(): await asyncio.sleep(1) async def connect(self, autoLoop=False): if not self.sta_if.isconnected(): if self.creds.load().is_valid(): print("> Connecting to {:s}/{:s}".format(self.creds.essid, self.creds.password)) self.sta_if.connect(self.creds.essid, self.creds.password) await asyncio.sleep(WAIT_FOR_CONNECT) if not self.sta_if.isconnected(): print("> Connection failed. WLAN status={:d}".format(self.sta_if.status())) if autoLoop: self.loop.create_task(self.connect(True)) else: print("> No valid credentials file: {}".format(Creds.CRED_FILE))
class ClockManager: def __init__(self): self.brightness = 0 self.mode = Mode.CLOCK self.sta_if = network.WLAN(network.STA_IF) self.credentials = Creds().load() self.settings = Settings().load() routes = { b"/": b"./index.html", b"/connect": self.connect, b"/action/color": self.set_color, b"/action/clock/display": self.display_clock, b"/action/brightness/more": self.brightness_more, b"/action/brightness/less": self.brightness_less, b"/action/scoreboard/display": self.display_scoreboard, b"/action/scoreboard/green/more": self.scoreboard_green_more, b"/action/scoreboard/green/less": self.scoreboard_green_less, b"/action/scoreboard/red/more": self.scoreboard_red_more, b"/action/scoreboard/red/less": self.scoreboard_red_less, b"/action/scoreboard/reset": self.scoreboard_reset, b"/settings/values": self.settings_values, b"/settings/net": self.settings_net, b"/settings/group": self.settings_group } self.poller = poll() self.http = HTTPServer(self.poller, CaptivePortal.AP_IP, routes) print("> HTTP server started") self.clock = Clock(self.settings.color) self.loop = get_event_loop() self.loop.create_task(self.check_wifi()) self.loop.create_task(self.poll_web_server()) async def check_wifi(self): while True: collect() threshold(mem_free() // 4 + mem_alloc()) print("> Free memory: {}".format(mem_free())) # self.clock.play_spinner(SPINNER_RATE, ORANGE) self.portal = CaptivePortal(PUBLIC_NAME + b"-%s" % self.settings.net_id) self.portal.start() while not self.sta_if.isconnected(): await sleep_ms(1000) ip = self.sta_if.ifconfig()[0] self.http.set_ip(ip) print("> Connected to {:s} ({:s})".format(self.credentials.essid, ip)) self.portal = None collect() print("> Free memory: {}".format(mem_free())) self.clock.stop_clock() self.clock.stop_effect_init = True self.clock.display() while self.sta_if.isconnected(): await sleep_ms(1000) async def poll_web_server(self): while True: for response in self.poller.ipoll(1000): sock, event, *others = response self.http.handle(sock, event, others) await sleep_ms(50) def settings_values(self, params): essid = self.credentials.essid if not essid: essid = "" result = b'{"ip": "' + self.http.local_ip + '", "netId": "' + self.settings.net_id + '", "group": "' + \ self.settings.group + '", "essid": "' + essid + '"}' return result, b"HTTP/1.1 200 OK\r\n" def connect(self, params): if self.portal: # Write out credentials self.credentials.essid = params.get(b"essid", None) self.credentials.password = params.get(b"password", None) self.credentials.write() self.loop.create_task(self.portal.connect_to_wifi()) return b"", b"HTTP/1.1 200 OK\r\n" def display_clock(self, params=None): if self.mode == Mode.SCOREBOARD: self.mode = Mode.CLOCK self.clock.display() return b"", b"HTTP/1.1 200 OK\r\n" def display_scoreboard(self, params=None): if self.mode == Mode.CLOCK: self.clock.stop_clock() self.mode = Mode.SCOREBOARD self.clock.display_scoreboard() return b"", b"HTTP/1.1 200 OK\r\n" def set_color(self, params): self.display_clock() color = params.get(b"hex", None) if color: self.clock.set_color(color) # Comment the following lines in order to NOT save the selected color for the next boot self.settings.color = color self.settings.write() return b"", b"HTTP/1.1 200 OK\r\n" def scoreboard_green_more(self, params): return self.scoreboard_update(Player.GREEN, 1) def scoreboard_green_less(self, params): return self.scoreboard_update(Player.GREEN, -1) def scoreboard_red_more(self, params): return self.scoreboard_update(Player.RED, 1) def scoreboard_red_less(self, params): return self.scoreboard_update(Player.RED, -1) def scoreboard_update(self, player, increment): if player == Player.GREEN: self.clock.update_scoreboard_green(increment) else: self.clock.update_scoreboard_red(increment) return self.display_scoreboard() def brightness_more(self, params): self.display_clock() self.clock.set_brighter() self.settings.color = b"" + self.clock.hex self.settings.write() return b"", b"HTTP/1.1 200 OK\r\n" def brightness_less(self, params): self.display_clock() self.clock.set_darker() self.settings.color = b"" + self.clock.hex self.settings.write() return b"", b"HTTP/1.1 200 OK\r\n" def scoreboard_reset(self, params): self.display_scoreboard() self.clock.reset_scoreboard() return b"", b"HTTP/1.1 200 OK\r\n" def settings_net(self, params): id = params.get(b"id", None) if id: self.settings.net_id = id self.settings.write() return b"", b"HTTP/1.1 200 OK\r\n" def settings_group(self, params): name = params.get(b"name", None) if name: self.settings.group = name self.settings.write() return b"", b"HTTP/1.1 200 OK\r\n"
def display_credentials(): return Creds.reveal_credentials()
def test_remove_credentials(self): self.new_credential.save_creds() test_credentials = Creds('Pinterest','1234asdf') test_credentials.save_creds() self.new_credential.rm_creds() self.assertEqual(len(Creds.creds_list),1)
def locate_credential(account): return Creds.find_by_acc_name(account)
def create_new_creds(account,password): new_credential = Creds(account,password) return new_credential
def setUp(self): self.new_credential = Creds('Instagram', '1234qwer')
def test_show_allcreds(self): self.assertEqual(Creds.reveal_credentials(),Creds.creds_list)
def test_credential_exists(self): self.new_credential.save_creds() test_credentials = Creds('Pinterest', '1234asdf') test_credentials.save_creds() credential_exists = Creds.credential_exists('Pinterest') self.assertTrue(credential_exists)
class TestCreds(unittest.TestCase): def setUp(self): self.new_credential = Creds('Instagram', '1234qwer') def test_init(self): self.assertEqual(self.new_credential.account,'Instagram') self.assertEqual(self.new_credential.password,'1234qwer') def test_save_cred(self): self.new_credential.save_creds() self.assertEqual(len(Creds.creds_list),1) def tearDown(self): Creds.creds_list = [] def test_save_many_credentials(self): self.new_credential.save_creds() test_credentials = Creds('Instagram', '1234qwer') test_credentials.save_creds() self.assertEqual(len(Creds.creds_list),2) def test_remove_credentials(self): self.new_credential.save_creds() test_credentials = Creds('Pinterest','1234asdf') test_credentials.save_creds() self.new_credential.rm_creds() self.assertEqual(len(Creds.creds_list),1) def test_find_credential_by_name(self): self.new_credential.save_creds() test_credentials = Creds('Pinterest', '1234asdf') test_credentials.save_creds() found_cred = Creds.find_by_acc_name('Pinterest') self.assertEqual(found_cred.account,test_credentials.account) def test_credential_exists(self): self.new_credential.save_creds() test_credentials = Creds('Pinterest', '1234asdf') test_credentials.save_creds() credential_exists = Creds.credential_exists('Pinterest') self.assertTrue(credential_exists) def test_show_allcreds(self): self.assertEqual(Creds.reveal_credentials(),Creds.creds_list) if __name__ == '__main__': unittest.main()
def test_find_credential_by_name(self): self.new_credential.save_creds() test_credentials = Creds('Pinterest', '1234asdf') test_credentials.save_creds() found_cred = Creds.find_by_acc_name('Pinterest') self.assertEqual(found_cred.account,test_credentials.account)
class CaptivePortal: AP_IP = "192.168.4.1" AP_OFF_DELAY = const(10 * 1000) MAX_CONN_ATTEMPTS = 10 def __init__(self, essid=None): self.local_ip = self.AP_IP self.sta_if = network.WLAN(network.STA_IF) self.ap_if = network.WLAN(network.AP_IF) if essid is None: # essid = b"ESP8266-%s" % binascii.hexlify(self.ap_if.config("mac")[-3:]) essid = 'GTurn' self.essid = essid self.creds = Creds() self.dns_server = None self.http_server = None self.poller = select.poll() self.conn_time_start = None def start_access_point(self): # sometimes need to turn off AP before it will come up properly self.ap_if.active(False) while not self.ap_if.active(): print("Waiting for access point to turn on") self.ap_if.active(True) time.sleep(1) # IP address, netmask, gateway, DNS self.ap_if.ifconfig( (self.local_ip, "255.255.255.0", self.local_ip, self.local_ip)) self.ap_if.config(essid=self.essid, authmode=network.AUTH_OPEN) print("AP mode configured:", self.ap_if.ifconfig()) def connect_to_wifi(self): print("Trying to connect to SSID '{:s}' with password {:s}".format( self.creds.ssid, self.creds.password)) #disable ap connection if self.ap_if.active(): self.ap_if.active(False) # initiate the connection if not self.ap_if.active(): self.sta_if.active(True) self.sta_if.connect(self.creds.ssid, self.creds.password) attempts = 1 while attempts <= self.MAX_CONN_ATTEMPTS: if not self.sta_if.isconnected(): print("Connection attempt {:d}/{:d} ...".format( attempts, self.MAX_CONN_ATTEMPTS)) time.sleep(2) attempts += 1 else: print("Connected to {:s}".format(self.creds.ssid)) self.local_ip = self.sta_if.ifconfig()[0] print("Server connect @", self.local_ip) return True print("Failed to connect to {:s} with {:s}. WLAN status={:d}".format( self.creds.ssid, self.creds.password, self.sta_if.status())) # forget the credentials since they didn't work, and turn off station mode self.creds.remove() self.sta_if.active(False) return False def check_valid_wifi(self): if not self.sta_if.isconnected(): if self.creds.load().is_valid(): # have credentials to connect, but not yet connected # return value based on whether the connection was successful return self.connect_to_wifi() # not connected, and no credentials to connect yet return False if not self.ap_if.active(): # access point is already off; do nothing return False # already connected to WiFi, so turn off Access Point after a delay if self.conn_time_start is None: self.conn_time_start = time.ticks_ms() remaining = self.AP_OFF_DELAY else: remaining = self.AP_OFF_DELAY - time.ticks_diff( time.ticks_ms(), self.conn_time_start) if remaining <= 0: self.ap_if.active(False) print("Turned off access point") return False def captive_portal(self): print("Starting captive portal") self.start_access_point() if self.http_server is None: self.http_server = HTTPServer(self.poller, self.local_ip) print("Configured HTTP server") if self.dns_server is None: self.dns_server = DNSServer(self.poller, self.local_ip) print("Configured DNS server") try: while True: gc.collect() # check for socket events and handle them for response in self.poller.ipoll(1000): sock, event, *others = response is_handled = self.handle_dns(sock, event, others) if not is_handled: self.handle_http(sock, event, others) if self.check_valid_wifi(): print("Connected to WiFi!") self.http_server.set_ip(self.local_ip, self.creds.ssid) self.dns_server.stop(self.poller) break except KeyboardInterrupt: print("Captive portal stopped") self.cleanup() def handle_dns(self, sock, event, others): if sock is self.dns_server.sock: # ignore UDP socket hangups if event == select.POLLHUP: return True self.dns_server.handle(sock, event, others) return True return False def handle_http(self, sock, event, others): self.http_server.handle(sock, event, others) def cleanup(self): print("Cleaning up") if self.dns_server: self.dns_server.stop(self.poller) gc.collect() def try_connect_from_file(self): if self.creds.load().is_valid(): if self.connect_to_wifi(): return True # WiFi Connection failed - remove credentials from disk self.creds.remove() return False def start(self): # turn off station interface to force a reconnect self.sta_if.active(False) if not self.try_connect_from_file(): self.captive_portal()
def look_existing_credential(account): return Creds.credential_exists(account)
def test_save_many_credentials(self): self.new_credential.save_creds() test_credentials = Creds('Instagram', '1234qwer') test_credentials.save_creds() self.assertEqual(len(Creds.creds_list),2)