add network support
parent
0ba4b41917
commit
b3fd037cd9
122
esp32/main.py
122
esp32/main.py
|
@ -4,6 +4,10 @@ import machine
|
|||
import hashlib
|
||||
import os
|
||||
import asyncio
|
||||
import network
|
||||
import requests
|
||||
import _thread
|
||||
from umqtt.simple import MQTTClient
|
||||
|
||||
DEBUG = True
|
||||
|
||||
|
@ -45,6 +49,115 @@ class Keypad:
|
|||
return data[:4]
|
||||
|
||||
|
||||
class Net:
|
||||
def __init__(self):
|
||||
self._connected = False
|
||||
self._wlan = network.WLAN(network.STA_IF)
|
||||
|
||||
self._events = []
|
||||
# keepalive is needed due to: https://github.com/eclipse/mosquitto/issues/2462
|
||||
self._mqtt = MQTTClient("lock", "10.11.1.1", keepalive=5)
|
||||
self._mqtt.set_callback(self._mqtt_cb)
|
||||
|
||||
async def loop(self):
|
||||
self.start()
|
||||
while True:
|
||||
self.update()
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
def _mqtt_cb(self, topic, msg):
|
||||
if topic == b'locks/internal/command':
|
||||
if msg == b'sync':
|
||||
try:
|
||||
print("starting sync")
|
||||
# TODO: add auth support to http server
|
||||
url = "http://10.11.1.1:8000/hashes/internal"
|
||||
print(f"fetching: {url}")
|
||||
rsp = requests.get(url)
|
||||
print(f"sync code: {rsp.status_code}")
|
||||
with open('hashes_new', 'wb') as f:
|
||||
if 200 <= rsp.status_code < 300:
|
||||
while True:
|
||||
chunk = rsp.raw.read(512)
|
||||
if not chunk:
|
||||
break
|
||||
f.write(chunk)
|
||||
os.rename('hashes_new', 'hashes')
|
||||
print("sync finished")
|
||||
self.send_event("sync", 'success'.encode())
|
||||
except Exception as e:
|
||||
print(f"sync error: {e}")
|
||||
self.send_event("sync", 'fail'.encode())
|
||||
else:
|
||||
print(f"uncrecognised command: {msg}")
|
||||
|
||||
|
||||
def send_event(self, name, payload):
|
||||
# TODO: limit number of events in queue
|
||||
self._events.append((name, payload))
|
||||
|
||||
|
||||
def _run_mqtt(self):
|
||||
mqtt = self._mqtt
|
||||
while True:
|
||||
try:
|
||||
while True:
|
||||
mqtt.connect()
|
||||
mqtt.publish("locks/internal/mac", self._wlan.config('mac').hex())
|
||||
mqtt.subscribe("locks/internal/command")
|
||||
|
||||
i = 0
|
||||
while True:
|
||||
try:
|
||||
while True:
|
||||
name, payload = self._events.pop()
|
||||
print("sending event")
|
||||
mqtt.sock.setblocking(True)
|
||||
mqtt.publish(f"locks/internal/events/{name}", payload)
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
if i == 10:
|
||||
i = 0
|
||||
mqtt.ping()
|
||||
else:
|
||||
i += 1
|
||||
|
||||
mqtt.check_msg()
|
||||
utime.sleep(0.25)
|
||||
|
||||
except Exception as e:
|
||||
print(f"mqtt exception: {e}")
|
||||
utime.sleep(6)
|
||||
|
||||
def start(self):
|
||||
self._wlan.active(True)
|
||||
# for net in self._wlan.scan():
|
||||
# print(f'scan: {net}')
|
||||
print("mac:", self._wlan.config('mac').hex())
|
||||
|
||||
_thread.start_new_thread(self._run_mqtt, ())
|
||||
|
||||
with open('wifi', 'r') as f:
|
||||
ssid = f.readline().strip()
|
||||
key = f.readline().strip()
|
||||
|
||||
if not self._wlan.isconnected():
|
||||
print(f'connecting to network ssid={ssid!r}')
|
||||
self._wlan.connect(ssid, key)
|
||||
|
||||
|
||||
def update(self):
|
||||
if self._wlan.isconnected():
|
||||
if not self._connected:
|
||||
print('network config:', self._wlan.ifconfig())
|
||||
self._connected = True
|
||||
else:
|
||||
if self._connected:
|
||||
print('disconnected')
|
||||
self._connected = False
|
||||
|
||||
|
||||
class Door:
|
||||
def __init__(self, pin):
|
||||
self._pin = pin
|
||||
|
@ -64,7 +177,7 @@ def generate_hash(card_uid, pin):
|
|||
return hash
|
||||
|
||||
|
||||
async def handle_auth(nfc, keypad, door):
|
||||
async def handle_auth(nfc, keypad, door, net):
|
||||
while True:
|
||||
card_uid = await nfc.wait_uid()
|
||||
print("Card UUID: " + ''.join('{:02x}'.format(x) for x in card_uid))
|
||||
|
@ -89,6 +202,8 @@ async def handle_auth(nfc, keypad, door):
|
|||
hash_found = True
|
||||
break
|
||||
|
||||
net.send_event("hash", hash.encode())
|
||||
|
||||
try:
|
||||
if hash_found:
|
||||
print('Known hash, opening door')
|
||||
|
@ -163,9 +278,12 @@ async def main():
|
|||
door = Door(machine.Pin(2, machine.Pin.OUT))
|
||||
door.lock()
|
||||
|
||||
net = Net()
|
||||
|
||||
await asyncio.gather(
|
||||
handle_auth(nfc, keypad, door),
|
||||
handle_auth(nfc, keypad, door, net),
|
||||
nfc.loop(),
|
||||
net.loop()
|
||||
)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue