diff --git a/main.py b/main.py index 96094f4..2956982 100644 --- a/main.py +++ b/main.py @@ -10,7 +10,7 @@ from machine import I2C, Pin, ADC from secrets import secrets import sht4x.sht4x as sht4x from web_tools import result_ok, result_notfound -from tools import connect_wifi, set_time, with_fallback, with_fallback_to_str +from tools import connect_wifi, disconnect_wifi, set_time, with_fallback_to_str from ht16k33.ht16k33segmentbig import HT16K33SegmentBig # GPIO devices @@ -57,7 +57,10 @@ display.draw() wlan_mac = wlan.config('mac') mac_readable = ubinascii.hexlify(wlan_mac).decode() -sht4x = sht4x.SHT4X(i2c) +if devices.count(0x44) > 0: + sensor_sht4x = sht4x.SHT4X(i2c) +else: + sensor_sht4x = None update_time = False try: @@ -82,6 +85,7 @@ motion_timeout_ms = 18000 # Default value, it will be recalculated motion_started_ms = 0 motion_state_on = False +running = True def web_thread(): global temp_sht4x @@ -92,6 +96,10 @@ def web_thread(): global dim_light global enable_auto_brightness global enable_motion_detection + + global wlan + + global running GET_PATH_START = 4 POST_PATH_START = 5 @@ -100,12 +108,43 @@ def web_thread(): print('Binding to ' + str(addr)) serverSocket = socket.socket() + serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) serverSocket.bind(addr) - serverSocket.listen(1) + serverSocket.listen() + + last_wlan_status = wlan.status() + + while running: + try: + reconnect_wifi = False + + if wlan.status() != last_wlan_status: + last_wlan_status = wlan.status() + print('WLAN status changed to ' + str(last_wlan_status)) + + if wlan.status() < 0 or wlan.status() > 3: + reconnect_wifi = True + + if last_wlan_status == network.STAT_IDLE: + reconnect_wifi = True + + if not wlan.isconnected(): + reconnect_wifi = True + + if reconnect_wifi: + print('Disconnecting from WiFi') + disconnect_wifi(wlan) + print('Reconnecting to WiFi') + while not connect_wifi(wlan, ssid, pw, blink_onboard_led): + print('Could not connect to WiFi, retrying in 5 seconds') + time.sleep(5) + print('Reconnected to WiFi') + except Exception as e: + print("caught exception in web loop in wlan checking {} {}".format(type(e).__name__, e)) + sys.print_exception(e) + time.sleep_ms(100) - while True: try: - #print('waiting for client') cl, addr = serverSocket.accept() #print('client connected from', addr) request = cl.recv(1024) @@ -204,18 +243,26 @@ humidity""" + attrs + with_fallback_to_str(humidity, "NaN")) result_ok(cl, content) else: result_notfound(cl) + except KeyboardInterrupt: - serverSocket.close() + print('Closing web socket due to KeyboardInterrupt') + running = False break except Exception as e: - print("caught exception in main loop {} {}".format(type(e).__name__, e)) + print("caught exception in web loop {} {}".format(type(e).__name__, e)) sys.print_exception(e) time.sleep_ms(100) - try: + try: + gc_lock.acquire() gc.collect() - except: - pass + finally: + gc_lock.release() + + print('Web thread exiting...') + serverSocket.close() + disconnect_wifi(wlan) + print('Web thread exited') def display_thread(): global temp_sht4x @@ -236,22 +283,34 @@ def display_thread(): global display global sensor_lock + global gc_lock + + global running current_time = time.time_ns() - last_display_mode_time = int(current_time // 1_000_000) + current_time_ms = int(current_time // 1_000_000) + last_display_mode_time = current_time_ms display_mode = 0 - while True: + sensor_update_delta = 3000 + last_sensor_update_time = current_time_ms - sensor_update_delta - 1000 + + while running: try: + sensor_lock_acquired = False try: - sensor_lock.acquire() - temp_sht4x, humidity_sht4x = sht4x.measurements - except KeyboardInterrupt: - break + if current_time_ms >= last_sensor_update_time + sensor_update_delta: + sensor_lock_acquired = True + sensor_lock.acquire() + temp_sht4x, humidity_sht4x = sensor_sht4x.measurements if sensor_sht4x is not None else (0.0, 0.0) + last_sensor_update_time = current_time_ms except Exception as e: print("caught exception in main loop {} {}".format(type(e).__name__, e)) sys.print_exception(e) - sensor_lock.release() + + if sensor_lock_acquired: + sensor_lock.release() + sensor_lock_acquired = False current_time = time.time_ns() current_time_ms = int(current_time // 1_000_000) @@ -262,7 +321,7 @@ def display_thread(): minute = ltime[4] # Light on a 0 - 65535 scale - light = light_raw = photoRes.read_u16() + light = photoRes.read_u16() # We want to use the minimum brightness in darker environments # So we scale the light value to a 0 - 15 scale but uses a 18 (0-17) scale with zeroes at the beggining @@ -274,10 +333,6 @@ def display_thread(): light = 0 if enable_auto_brightness: - #if hour <= 7 or hour >= 20: - # brighness = 1 - #else: - # brighness = 15 brightness = light if brightness != last_brightness: @@ -354,8 +409,6 @@ def display_thread(): display.clear() display.draw() - except KeyboardInterrupt: - break except Exception as e: print("caught exception in main loop {} {}".format(type(e).__name__, e)) sys.print_exception(e) @@ -363,41 +416,54 @@ def display_thread(): if current_time_ms >= last_display_mode_time + 3000: last_display_mode_time = current_time_ms display_mode = display_mode + 1 - + if display_mode == 1 and not enable_temp: display_mode = display_mode + 1 - + if display_mode == 2 and not enable_hum: display_mode = display_mode + 1 if display_mode > 2: display_mode = 0 - - gc.collect() + #print(wlan.isconnected(), wlan.status(), wlan.ifconfig()) + + try: + gc_lock.acquire() + gc.collect() + finally: + gc_lock.release() try: if update_time: try: set_time() + + motion_state_on = False update_time = False + + current_time = time.time_ns() + current_time_ms = int(current_time // 1_000_000) + last_display_mode_time = current_time_ms except: print('Could not set time') update_time = True - except KeyboardInterrupt: - break except Exception as e: print("caught exception in main loop {} {}".format(type(e).__name__, e)) sys.print_exception(e) time.sleep_ms(100) except KeyboardInterrupt: + running = False break except Exception as e: print("caught exception in main loop {} {}".format(type(e).__name__, e)) sys.print_exception(e) time.sleep_ms(100) + print('Display thread exited...') + sensor_lock = _thread.allocate_lock() +gc_lock = _thread.allocate_lock() print('Starting Display thread') second_thread = _thread.start_new_thread(display_thread, ()) diff --git a/tools.py b/tools.py index 06a2760..c82ca0f 100644 --- a/tools.py +++ b/tools.py @@ -24,6 +24,7 @@ def set_time(): NTP_QUERY = bytearray(48) NTP_QUERY[0] = 0x1B addr = socket.getaddrinfo(host, 123)[0][-1] + print('NTP query to ' + str(addr) + '...') s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.settimeout(10)