from flask import Flask, request
import RPi.GPIO as GPIO
import smbus
import time
from threading import Timer

app = Flask(__name__)

# Setup GPIO
GPIO.setmode(GPIO.BCM)
rgb_r = 5
rgb_g = 6
rgb_b = 13
servo_pin = 18
pir_pin = 24  # PIR sensor pin
rgb_pins = (rgb_r, rgb_g, rgb_b)

GPIO.setup(rgb_pins, GPIO.OUT)
GPIO.setup(servo_pin, GPIO.OUT)
GPIO.setup(pir_pin, GPIO.IN)

rgb_r_pwm = GPIO.PWM(rgb_r, 100)
rgb_g_pwm = GPIO.PWM(rgb_g, 100)
rgb_b_pwm = GPIO.PWM(rgb_b, 100)
servo_pwm = GPIO.PWM(servo_pin, 50)  # 50Hz for the servo

rgb_r_pwm.start(0)
rgb_g_pwm.start(0)
rgb_b_pwm.start(0)
servo_pwm.start(0)  # Do not move the servo initially

# Setup LCD
LCD_ADDRESS = 0x27
LCD_CHR = 1
LCD_CMD = 0

LCD_WIDTH = 16
LCD_LINE_1 = 0x80
LCD_LINE_2 = 0xC0

E_PULSE = 0.0005
E_DELAY = 0.0005

bus = smbus.SMBus(1)

def lcd_init():
    lcd_byte(0x33, LCD_CMD)
    lcd_byte(0x32, LCD_CMD)
    lcd_byte(0x06, LCD_CMD)
    lcd_byte(0x0C, LCD_CMD)
    lcd_byte(0x28, LCD_CMD)
    lcd_byte(0x01, LCD_CMD)
    time.sleep(E_DELAY)

def lcd_byte(bits, mode):
    bits_high = mode | (bits & 0xF0) | 0x08
    bits_low = mode | ((bits << 4) & 0xF0) | 0x08

    bus.write_byte(LCD_ADDRESS, bits_high)
    lcd_toggle_enable(bits_high)

    bus.write_byte(LCD_ADDRESS, bits_low)
    lcd_toggle_enable(bits_low)

def lcd_toggle_enable(bits):
    time.sleep(E_DELAY)
    bus.write_byte(LCD_ADDRESS, (bits | 0x04))
    time.sleep(E_DELAY)
    bus.write_byte(LCD_ADDRESS, (bits & ~0x04))
    time.sleep(E_DELAY)

def lcd_string1(message, line=LCD_LINE_1):
    message = message.ljust(LCD_WIDTH, " ")
    lcd_byte(line, LCD_CMD)
    for i in range(LCD_WIDTH):
        lcd_byte(ord(message[i]), LCD_CHR)

def lcd_string2(message, line=LCD_LINE_2):
    message = message.ljust(LCD_WIDTH, " ")
    lcd_byte(line, LCD_CMD)
    for i in range(LCD_WIDTH):
        lcd_byte(ord(message[i]), LCD_CHR)

lcd_init()

cat_detected = False
servo_open = False
last_detection_time = 0

@app.route('/control-light', methods=['POST'])
def control_light():
    global cat_detected, last_detection_time, servo_open
    data = request.json
    print(f"Received data: {data}")  # Print the received data for debugging
    if 'detection' in data and 'accuracy' in data:
        detection = data['detection']
        accuracy = data['accuracy']
        current_time = time.time()
        
        # Update the LCD with the detection and accuracy
        lcd_string1(f"{detection} {accuracy}%")
        
        if detection == 'Tai-Lung' and accuracy >= 30 and not servo_open:
            if not cat_detected:
                cat_detected = True
                last_detection_time = current_time
            elif current_time - last_detection_time >= 1.5 and GPIO.input(pir_pin):  # Cat detected for at least 1.5 seconds and PIR sensor detects motion
                servo_open = True
                cat_detected = False
                rgb_value = (0, 100, 0)
                set_rgb_color(rgb_value)
                open_servo()
                Timer(10, close_servo).start()  # Close the servo after 10 seconds
                print(f"Detection: {detection} with accuracy {accuracy}% and PIR sensor detected motion")
                return "Light turned on and door opened", 200
        elif detection != 'Tai-Lung':
            cat_detected = False
            rgb_value = (100, 0, 0)
            set_rgb_color(rgb_value)
            print(f"Detection: {detection} with accuracy {accuracy}%")
            return "Light turned on", 200

    print("Invalid request")  # Print message for invalid requests
    return "Invalid request", 400

def set_rgb_color(rgb_value):
    r, g, b = rgb_value
    rgb_r_pwm.ChangeDutyCycle(100 - r)  
    rgb_g_pwm.ChangeDutyCycle(100 - g)
    rgb_b_pwm.ChangeDutyCycle(100 - b)

def open_servo():
    print("Opening servo to 90 degrees")
    servo_pwm.ChangeDutyCycle(7.5)  # 90 degrees

def close_servo():
    global servo_open
    print("Closing servo to 0 degrees")
    servo_pwm.ChangeDutyCycle(2.5)  # 0 degrees
    servo_open = False

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
