diff --git a/main.py b/main.py
index 019d8f33548175768801f7c9ec07a48d3d85e13b..2ffd4dcfcc47969184737d4671c8e2141dc82608 100644
--- a/main.py
+++ b/main.py
@@ -3,7 +3,9 @@ from grove_rgb_lcd import *
 import time
 import datetime
 import threading
-
+import paho.mqtt.client as mqtt
+import json
+    
 # === Variables ===
 # Port Assignments
 light_port = 1     # A1
@@ -11,6 +13,11 @@ pir_port = 4       # D4
 button_port = 3    # D2 (FOR SOME REASON THIS BOARD THINKS D3 IS D2)
 buzzer_port = 7    # D7
 
+# Thingsboard Connection
+client = None
+THINGSBOARD_HOST = "thingsboard.cs.cf.ac.uk"
+ACCESS_TOKEN = "ad9EfCbasXFLokL3tkC1"
+
 # Notification Preferences
 preferences = {"Thingsboard": True,
                  "Visual": True,
@@ -27,9 +34,17 @@ light_trigger_delay = 15  # Scans every 0.2 seconds
                         # 3/0.2 = 15
                         # This means if we want a delay of 3 seconds to use a TriggerDelay value of 15
 
-# Detection variables
+# motion variables
 motion_detected = False
+motion_counter = 0
 no_motion_counter = 0
+last_motion_time = 0
+
+motion_trigger_delay = 7
+no_motion_release_delay = 15 # 15 no motion reads to reset
+motion_cooldown = 3 #3s between alerts
+
+# button variables
 last_button_state = 1  # For state change detection
 
 # === Initilisation Functions ===
@@ -39,6 +54,20 @@ def initialise_sensors():
     pinMode(buzzer_port, "OUTPUT")
     return
 
+def initilise_thingsboard():
+    global client
+    try:
+        client = mqtt.Client()
+        client.username_pw_set(ACCESS_TOKEN)
+        client.connect(THINGSBOARD_HOST, 1883, 60)
+        client.loop_start()
+        client.subscribe("v1/devices/me/attributes")
+        client.on_message = handle_attribute_update
+        log_event("INFO","Connected to thingsboard")
+    except Exception as e:
+        log_event("ERROR",f"MQTT Connection failed: {e}")
+        return
+    
 # === Notification Functions ===
 def notify(preferences, message = "visitor", duration = 0.2):
     if preferences.get("Thingsboard"):
@@ -78,28 +107,37 @@ def detect_button_press():
         set_display("Ringing")
         notify(preferences)
         time.sleep(2)
-        set_display("Rung")
+        set_display("Doorbell System Ready")
 
     last_button_state = button
     return
 
 def detect_motion():
-    global motion_detected, no_motion_counter
-
+    global motion_detected, motion_counter, last_motion_time, no_motion_counter
+    
     motion = digitalRead(pir_port)
-
-    if motion == 1 and not motion_detected:
-        log_event("EVENT", "Motion detected!")
-        motion_detected = True
+    now = time.time()
+    
+    if motion == 1:
+        motion_counter += 1
         no_motion_counter = 0
-        notify(preferences, message="Motion Detected")
-
-    elif motion == 0:
-        no_motion_counter += 1
-        if motion_detected and no_motion_counter > 5:
-            log_event("EVENT", "Motion stopped.")
-            motion_detected = False
-
+        
+        if motion_counter >= motion_trigger_delay and not motion_detected:
+            if now - last_motion_time >= motion_cooldown:
+                motion_detected = True
+                last_motion_time = now
+                print("MOTION")
+    else:
+        if motion_detected:
+            no_motion_counter += 1
+            if no_motion_counter >= no_motion_release_delay:
+                motion_detected = False
+                motion_counter = 0
+                print("MOTION ENDED")
+        else:
+            motion_counter = 0
+            no_motion_counter = 0
+    
 def detect_light_level():
     global light_dark_counter, light_trigger_delay, night_mode
     light = analogRead(light_port)
@@ -112,7 +150,7 @@ def detect_light_level():
         else:
             if night_mode:
                 #log_event("EVENT", "SIGNIFICANT LIGHT DETECTED")
-                adjust_lights()
+                light_dark_counter = 0
     else:
         light_dark_counter = 0  # Reset if it's bright
 
@@ -178,6 +216,7 @@ def self_check():
     try:
         set_display("Running self check...")
         time.sleep(1)
+        log_event("PASS", "LCD ON")
         status["LCD"] = True
     except:
         log_event("ERROR", "LCD not responding.")
@@ -185,7 +224,7 @@ def self_check():
     # Check PIR
     try:
         motion = digitalRead(pir_port)
-        print(f"[PASS] PIR motion sensor: {motion}")
+        log_event("PASS", f"PIR motion sensor: {motion}")
         status["PIR"] = True
     except:
         log_event("ERROR", "PIR motion sensor not responding")
@@ -219,7 +258,40 @@ def self_check():
         set_display("SENSORS FAILED: ".join(failed))
         log_event("FAILED", f"Sensors failed: {', '.join(failed)}")
         return False
+
+def send_data_thingsboard(payload):
+    global client
+    if not client:
+        log_event("ERROR","MQTT Client not initilised")
+        return
     
+    try:
+        client.publish("v1/devices/me/telemetry", json.dumps(payload), qos=1)
+        log_event("THINGSBOARD",f"Data sent: {payload}")
+    except Exception as e:
+        log_event("ERROR",f"failed to send data to thingsboard: {e}")
+     
+def handle_attribute_update(client, userdata, msg):
+    global preferences
+    try:
+        data = json.loads(msg.payload.decode("utf-8"))
+        updated = []
+        for key in preferences:
+            if key in data:
+                preferences[key] = data[key]
+                updated.append(f"{key} = {data[key]}")
+        if updated:
+            log_event("THINGSBOARD", "Preferences Updated: " + ", ".join(updated))
+    except Exception as e:
+        log_event("ERROR",f"Failed to handle attribute update: {e}")
+        
+def report_preferences():
+    try:
+        client.publish("v1/devices/me/attributes", json.dumps(preferences), qos =1)
+        log_event("THINGSBOARD","Reported current preferences")
+    except Exception as e:
+        log_event("ERROR","Failed to report preferences: {e}")
+        
 # === Main Reaction Loop ===
 def main_loop():
     print("System Starting")
@@ -230,7 +302,7 @@ def main_loop():
             detect_button_press()
             detect_motion()
             detect_light_level()
-            print("[DEBUG]: LOOP")
+            #print("[DEBUG]: LOOP")
             time.sleep(0.2)
 
     except KeyboardInterrupt:
@@ -240,5 +312,7 @@ def main_loop():
 # Run
 if __name__ == "__main__":
     initialise_sensors()
+    initilise_thingsboard()
+    report_preferences()
     self_check()
     main_loop()