import serial
import time


def hex_to_bin(hex_code):
    if hex_code != "":
        binary_int = format(int(hex_code, 16), 'b')
        binary_str = str(binary_int).rjust(24,'0')
    else:
        binary_str = None

    return binary_str
    
def reset_projectors(p1, p2):
    byteData = [0x05, 0x2C, 0x00]
    p1_reset = p1.write(byteData)
    p2_reset = p2.write(byteData)
    return p1_reset, p2_reset


def get_position(p):
    byteData = [0x07,0xA0,0x00]
    p_position_write = p.write(byteData)
    p_position_read = p.read(3)

    p_position_read_hex = p_position_read.hex()
    p_position_read_binary_str = hex_to_bin(p_position_read_hex)

    if p_position_read_binary_str != None:
        n = 8
        p_position_binary = p_position_read_binary_str[-n:]
        p_position_decimal = int(p_position_binary, 2)
    else:
        p_position_binary = None
        p_position_decimal = None
    return p_position_binary, p_position_decimal

    
def slide_forward(p1, p2):
    byteData = [0x05, 0x00, 0x00]

    p1.write(byteData)
    p2.write(byteData)
    

def standby_on(p):
    byteData = [0x03, 0x1E, 0x00]
    p_standby_on = p.write(byteData)
    return p_standby_on
    

def standby_off(p):   
    byteData = [0x03, 0x1C, 0x00]
    p_standby_off = p.write(byteData)
    return p_standby_off

def reset_sys(slide, p1, p2):
    p1_reset, p2_reset = reset_projectors(p1, p2)
    print(f"Reset Projector 1: {p1_reset}")
    print(f"Reset Projector 2: {p2_reset}")
    
    ####################################################################################
    ## Start Loop only when position is 0
    p1_position_binary, p1_position_decimal = get_position(p1)
    p2_position_binary, p2_position_decimal = get_position(p2)
    print(f"Postion Projector 1: {p1_position_binary, p1_position_decimal}")
    print(f"Postion Projector 2: {p2_position_binary, p2_position_decimal}")

    if p2_position_decimal == 0:
        slide = 0
        print(slide)
    return slide

def process():
    p1 = None
    p2 = None
    
    try:
        p1 = serial.Serial("/dev/ttyUSB0", 9600, timeout=1)
        p2 = serial.Serial("/dev/ttyUSB1", 9600, timeout=1)
        print(f"Projector 1: {p1}")
        print(f"Projector 2: {p2}")
        
        slide = 1000
        slide = reset_sys(slide, p1, p2)
 
        # wait after reset
        time.sleep(1)
        
        while slide <= 80:
            print("--------")
            print(f"Slide: {slide} -> Slide: {slide + 1}")
        
            p1_position_binary, p1_position_decimal = get_position(p1)
            p2_position_binary, p2_position_decimal = get_position(p2)
            print(f"Postion Projector 1: {p1_position_binary, p1_position_decimal}")
            print(f"Postion Projector 2: {p2_position_binary, p2_position_decimal}")
        
            ############################## If projectors are not both on the position of the counted slide, reset projectors
            if slide == p1_position_decimal and slide == p2_position_decimal:
                slide_forward(p1, p2)
                slide = slide + 1
            
                if slide == 81:
                    continue
                else:
                    time.sleep(15)
            else:       
                print("slides position mismatch")
                p1_standby_on = standby_on(p1)
                p2_standby_on = standby_on(p2)
                print(f"Standby Projector 1: {p1_standby_on}")
                print(f"Standby Projector 2: {p2_standby_on}")
                break
                slide = reset_sys(slide, p1, p2)

        time.sleep(1)
        p1_standby_on = standby_on(p1)
        p2_standby_on = standby_on(p2)
        print(f"Standby Projector 1: {p1_standby_on}")
        print(f"Standby Projector 2: {p2_standby_on}")
    
    except Exception as e:
        print("ERROR:", e)

    finally:
        print("Cleanup")

        try:
            if p1:
                standby_on(p1)
                p1.close()
        except:
            pass

        try:
            if p2:
                standby_on(p2)
                p2.close()
        except:   
            pass
    
process()
