add network support

meow
vuko 2023-12-06 23:01:34 +01:00
parent 0ba4b41917
commit b3fd037cd9
1 changed files with 120 additions and 2 deletions

View File

@ -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()
)