def __init__(self, signals, signalsLock):
     threading.Thread.__init__(self)
     self.signals = signals
     self.signalsLock = signalsLock
     self.sm = IPCMemory()
     self.smCounter = 0
     self.knob = powermate.Powermate(devicePath)
    def __init__(self, signals, signalsLock):
        threading.Thread.__init__(self)
        self.signals = signals
        self.signalsLock = signalsLock
        self.sm = IPCMemory()
        self.smCounter = 0

        self.motionManager = MotionManager()
示例#3
0
class TurnListener(threading.Thread):
    def __init__(self, bareSignals, bareSignalsLock):
        threading.Thread.__init__(self)

        self.bareSignals = bareSignals
        self.bareSignalsLock = bareSignalsLock

        self.sm = IPCMemory()
        self.smCounter = 0

        self.knob = powermate.Powermate(devicePath)

    def run(self):
        print('Starting Listening Thread')
        self.startListening()

    def startListening(self):
        self.sum = 0

        while True:
            self.checkSharedMemory()

            pollResult = self.knob.read_event(0)
            if pollResult is None:
                continue

            (time, event, val) = pollResult
            time = Decimal('{}'.format(time)).normalize()
            val = Decimal('{}'.format(val)).normalize()

            if event == EVENT_ROTATE:
                self.sum = Decimal(self.sum) + val
                event = RotationEvent(time, val, self.sum)
            elif event == EVENT_BUTTON:
                event = ButtonEvent(time, val)

            self.bareSignalsLock.acquire()
            self.bareSignals.append(event)
            self.bareSignalsLock.release()

        self.cleanUp()

    def checkSharedMemory(self):
        import time
        if self.smCounter < self.sm.getSize():
            message = self.sm.get(self.smCounter)
            self.smCounter = self.smCounter + 1

            if message == IPCMemory.SHUTDOWN:
                print('I shall shutdown')
                time.sleep(2)
                self.cleanUp()
                sys.exit()
            elif message == IPCMemory.NEW_MOTION:
                self.sum = 0

    def cleanUp(self):
        print('McListener wird beendet')
示例#4
0
    def __init__(self, bareSignals, bareSignalsLock):
        threading.Thread.__init__(self)
        self.bareSignals = bareSignals
        self.bareSignalsLock = bareSignalsLock

        self.sm = IPCMemory()
        self.smCounter = 0

        self.ser = serial.Serial(self.usbPath, self.baudrate)
        self.ser.flush()
示例#5
0
    def __init__(self, signals, signalsLock):
        threading.Thread.__init__(self)

        self.signals = signals
        self.signalsLock = signalsLock
        self.signalsCounter = 0

        self.sm = IPCMemory()
        self.smCounter = 0

        self.motionManager = MotionManager()
        self.firstMotion = False

        ###
        #Teil der Bachelorarbeit
        self.subscriptionService = SubscriptionService()
class Controller:
    def __init__(self):
        self.signals = []
        self.initManager()
        #self.startRestServer()
        self.start()

    def start(self):

        signalsLock = threading.Lock()
        self.sm = IPCMemory()

        listenerThread = MicroControllerListener(self.signals, signalsLock)
        tThread = TouchListener(self.signals, signalsLock)
        detectionThread = MotionDetecter(self.signals, signalsLock)

        listenerThread.start()
        tThread.start()
        detectionThread.start()

        #self.initMultishutdown(10)

        listenerThread.join()
        tThread.join()
        detectionThread.join()

        print('Controller wird beendet')

    def startRestServer(self):
        restServer = RestServer()
        restServer.start()

    def initMultishutdown(self, time):
        print('Multishutdown incomming')
        for i in range(time, -1, -1):
            print(i)
            time.sleep(1)
        self.sm.add(IPCMemory.SHUTDOWN)

    def initManager(self):
        deviceManager = DeviceManager()
        deviceManager.initDevices()

        motionManager = MotionManager()
        motionManager.initMotions()
    def start(self):

        signalsLock = threading.Lock()
        self.sm = IPCMemory()

        listenerThread = MicroControllerListener(self.signals, signalsLock)
        tThread = TouchListener(self.signals, signalsLock)
        detectionThread = MotionDetecter(self.signals, signalsLock)

        listenerThread.start()
        tThread.start()
        detectionThread.start()

        #self.initMultishutdown(10)

        listenerThread.join()
        tThread.join()
        detectionThread.join()

        print('Controller wird beendet')
示例#8
0
    def read_frame(self):
        mem_header_size = 7 * 4
        # 7x uint32_t's

        if self.memory == None:
            print "Allocating memory: {0}".format(mem_header_size)
            self.memory = IPCMemory("/picamera_grabber_mem", mem_header_size)
            self.memory.bringup()

        mem_struct_data = self.memory.read(0, mem_header_size)
        memory_size, xres, yres, format, slot1_offset, slot2_offset, current_slot = struct.unpack(
            '@IIIIIII', mem_struct_data)

        if self.memory.size != memory_size:
            print "Reallocating memory: {0}".format(memory_size)
            self.memory = IPCMemory("/picamera_grabber_mem", memory_size)
            self.memory.bringup()

        if current_slot == 0:
            frame_offset = slot1_offset
        else:
            frame_offset = slot2_offset

        frame_header_size = (2 * 4) + 1 + (3 * 1)
        # 2x uint32_t's + bool + 3x uint8_t packing
        frame_struct_data = self.memory.read(frame_offset, frame_header_size)
        real_size, compressed_size, compressed, _, _, _ = struct.unpack(
            '@IIBBBB', frame_struct_data)
        if compressed == IPCGrabber.CompNone:
            size = real_size
        else:
            size = compressed_size

        print "Slot: {0} | size: {1} | compressed: {2}".format(
            current_slot, size, compressed),
        frame = self.memory.read(frame_offset + frame_header_size, size)
        return frame, xres, yres, compressed
示例#9
0
    def __init__(self, bareSignals, bareSignalsLock, signals, signalsLock):
        threading.Thread.__init__(self)

        self.bareSignals = bareSignals
        self.bareSignalsLock = bareSignalsLock
        self.bareSignalsCounter = 0
        
        self.signals = signals
        self.signalsLock = signalsLock

        self.sm = IPCMemory()
        self.smCounter = 0

        self.currentTouches = 0

        #TouchCheckerStuff
        self.touchEventsMetaInfo = dict()
        self.threshhold = 0.2

        ###
        #Bachelorarbeit
        self.lastButton = None
        self.intTimeout = 0.5
        self.buttonTimeout = Decimal('{}'.format(self.intTimeout)).normalize()
示例#10
0
class MicroControllerListener(threading.Thread):
    def __init__(self, signals, signalsLock):
        threading.Thread.__init__(self)
        self.signals = signals
        self.signalsLock = signalsLock
        self.sm = IPCMemory()
        self.smCounter = 0
        self.knob = powermate.Powermate(devicePath)

    def run(self):
        print('Starting Listening Thread')
        self.startListening()

    def startListening(self):
        tapTimeStamp = None
        timeout = 0.5

        self.sum = 0

        while True:
            self.checkSharedMemory()

            pollResult = self.knob.read_event(0)
            if pollResult is None:
                continue

            (time, event, val) = pollResult
            time = Decimal('{}'.format(time)).normalize()
            val = Decimal('{}'.format(val)).normalize()

            if event == EVENT_ROTATE:
                self.sum = Decimal(self.sum) + val
                event = RotationEvent(time, val, self.sum)
            elif event == EVENT_BUTTON:
                event = ButtonEvent(time, val)

            #Check For Double Tap
            if event.getEvent() == EVENT_BUTTON and event.getValue(
            ) == Decimal('0'):
                if tapTimeStamp != None and (event.getTime() -
                                             tapTimeStamp) <= Decimal(
                                                 '{}'.format(timeout)):
                    pass
                tapTimeStamp = event.getTime()

            self.signalsLock.acquire()
            self.signals.append(event)
            self.signalsLock.release()

        self.cleanUp()

    #ATTENTION NOT THREAD SAFE! LOCK ME REQUIRED BEFORE AND RELEASED AFTER
    def aboart(self):
        counter = 0
        for i in range(len(self.signals) - 1, -1, -1):
            if self.signals[i].getEvent() == EVENT_BUTTON and counter < 3:
                self.signals[i] = None
                counter = counter + 1
            elif counter == 3:
                break

    def checkSharedMemory(self):
        import time
        if self.smCounter < self.sm.getSize():
            message = self.sm.get(self.smCounter)
            self.smCounter = self.smCounter + 1

            if message == IPCMemory.SHUTDOWN:
                print('I shall shutdown')
                time.sleep(2)
                self.cleanUp()
                sys.exit()
            elif message == IPCMemory.RESET_ROTATION_SUM:
                print('I shall reset the rotation sum')
                self.sum = 0

    def cleanUp(self):
        print('McListener wird beendet')
示例#11
0
class Executioner(threading.Thread):
    def __init__(self, signals, signalsLock):
        threading.Thread.__init__(self)

        self.signals = signals
        self.signalsLock = signalsLock
        self.signalsCounter = 0

        self.sm = IPCMemory()
        self.smCounter = 0

        self.motionManager = MotionManager()
        self.firstMotion = False

        ###
        #Teil der Bachelorarbeit
        self.subscriptionService = SubscriptionService()
        ###

    def run(self):
        print('Executioner is running')
        #Wenn keine Motions vorhanden sind
        if not self.motionManager.getAllMotions():
            self.firstMotion = True
            print("Bitte die erste Geste anlernen")
            self.startLearning()
        self.firstMotion = False
        self.startExecution()

    def startExecution(self):
        self.sm.put(IPCMemory.NEW_MOTION)
        #ggf kurze wartezeit um sicherzustellen dass der befehl auch ankommt?

        while True:
            self.checkSharedMemory()
            self.signalsLock.acquire()
            if not self.signalsCounter < len(self.signals):
                self.signalsLock.release()
                continue

            event = self.signals[self.signalsCounter]
            self.signalsCounter = self.signalsCounter + 1
            self.signalsLock.release()

            if isinstance(event, AboartEvent):
                ###
                #Bachelorarbeit
                self.removeRedundance()
                ###
                self.signalsLock.acquire()
                signalsCopy = self.signals[:]
                self.signalsLock.release()

                self.sm.put(IPCMemory.NEW_MOTION)

                self.startRecognition(signalsCopy)
            else:
                continue

    def startRecognition(self, signalsCopy):
        motion = self.transformMotion(signalsCopy)

        #Vergleiche die Motion mit allen anderen
        calculator = Calculator()
        knownMotions = self.motionManager.getAllMotions()
        bestMatch = None
        bestScore = None
        print('')
        for knownMotionName in knownMotions:
            knownMotion = self.motionManager.getMotion(knownMotionName)
            score = calculator.getMatchingScore(motion, knownMotion)

            print('{} - {} %'.format(knownMotionName, score))

            if bestMatch == None or score > bestScore:
                bestMatch = knownMotionName
                bestScore = score

        print('')
        print('Den besten Match gab es mit: {} - {} %'.format(
            bestMatch, bestScore))

        #Funktionalität der erkannten Geste ausführen
        print('Hier wird nun function.execute ausgeführt')
        print('')

        if bestMatch == 'learningMotion':
            print('lerne')
            self.startLearning()

        ###
        #Teil der Bachelorarbeit
        else:
            print('Firing new event')
            topic = 'newMotionEvent'
            values = dict()
            values['name'] = bestMatch
            event = Event(topic, values)
            self.subscriptionService.onEvent(event)
        ###

    def startLearning(self):
        #Send all Signals to reset Inputs
        #Zur Sicherheit hier einmal zuviel, damit wirklich
        #erst mit beginn des lernens die Signale aufgenommen werden
        self.sm.put(IPCMemory.NEW_MOTION)

        while True:
            self.checkSharedMemory()
            self.signalsLock.acquire()
            if not self.signalsCounter < len(self.signals):
                self.signalsLock.release()
                continue

            event = self.signals[self.signalsCounter]
            self.signalsCounter = self.signalsCounter + 1
            self.signalsLock.release()

            if isinstance(event, AboartEvent):
                ###
                #Bachelorarbeit
                self.removeRedundance()
                ###

                self.signalsLock.acquire()
                signalsCopy = self.signals[:]
                self.signalsLock.release()

                self.sm.put(IPCMemory.NEW_MOTION)

                self.transformAndSafeMotion(signalsCopy)
                break
            else:
                continue

    def transformAndSafeMotion(self, signalsCopy):
        motion = self.transformMotion(signalsCopy)

        if self.firstMotion:
            motion.setName('learningMotion')
        else:
            name = input('Wie heißt die Motion\n')
            motion.setName(name)

        self.motionManager.saveOrUpdateMotion(motion)

    def transformMotion(self, signalsCopy):
        del signalsCopy[len(signalsCopy) - 1]

        transformer = MotionTransformer()
        motion = transformer.transformMotion(signalsCopy)

        return motion

    ###
    #Bachelorarbeit
    def removeRedundance(self):
        self.signalsLock.acquire()
        #Remove aboartEvent
        del self.signals[-1]

        #Remove allAboartButtonEvents
        deleted = False
        i = -1
        while not deleted:
            if isinstance(self.signals[i],
                          ButtonEvent) and self.signals[i].value == 1:
                #print('Found ButtonEvent with Value {} @ {}'.format(self.signals[i].value, i))
                del self.signals[i]
                deleted = True
            else:
                i = i - 1

        deleted = False
        i = -1
        while not deleted:
            if isinstance(self.signals[i],
                          ButtonEvent) and self.signals[i].value == 0:
                #print('Found ButtonEvent with Value {} @ {}'.format(self.signals[i].value, i))
                del self.signals[i]
                deleted = True
            else:
                i = i - 1

        deleted = False
        i = -1
        while not deleted:
            if isinstance(self.signals[i],
                          ButtonEvent) and self.signals[i].value == 1:
                #print('Found ButtonEvent with Value {} @ {}'.format(self.signals[i].value, i))
                del self.signals[i]
                deleted = True
            else:
                i = i - 1

        self.signalsLock.release()

    ###

    def checkSharedMemory(self):
        import time
        if self.smCounter < self.sm.getSize():
            message = self.sm.get(self.smCounter)
            self.smCounter = self.smCounter + 1

            if message == IPCMemory.SHUTDOWN:
                print('I shall shutdown')
                time.sleep(2)
                sys.exit()
            elif message == IPCMemory.NEW_MOTION:
                self.signalsCounter = 0
示例#12
0
class Verification(threading.Thread):

    def __init__(self, bareSignals, bareSignalsLock, signals, signalsLock):
        threading.Thread.__init__(self)

        self.bareSignals = bareSignals
        self.bareSignalsLock = bareSignalsLock
        self.bareSignalsCounter = 0
        
        self.signals = signals
        self.signalsLock = signalsLock

        self.sm = IPCMemory()
        self.smCounter = 0

        self.currentTouches = 0

        #TouchCheckerStuff
        self.touchEventsMetaInfo = dict()
        self.threshhold = 0.2

        ###
        #Bachelorarbeit
        self.lastButton = None
        self.intTimeout = 0.5
        self.buttonTimeout = Decimal('{}'.format(self.intTimeout)).normalize()
        ###

    def run(self):
        print('Started Verification')
        self.startVerification()

    def startVerification(self):
        while True:
            self.checkSharedMemory()
            ###
            #Bachelorarbeit Auskommentiert!!! Muss wieder rein!!!
            #Braucht erstmal nur Rotation
            #self.updateObservedTouchEvents()
            ###
            #Read bareSignals
            self.bareSignalsLock.acquire()
            if not self.bareSignalsCounter < len(self.bareSignals):
                self.bareSignalsLock.release()
                continue
            
            event = self.bareSignals[self.bareSignalsCounter]
            self.bareSignalsCounter = self.bareSignalsCounter + 1
            self.bareSignalsLock.release()

            #Stromabbruch checken
            ###
            #Bachelorarbeit Auskommentiert!!! Muss wieder rein!!!
            #if isinstance(event, TouchEvent):
            #    self.observeTouchEvent(event)
            ###

            #CheckIfItIsCorrect
            isValid = False
            if isinstance(event, RotationEvent) or isinstance(event, ButtonEvent):# or isinstance(event, TouchEvent):
                isValid = True

            ###
            #Bachelorarbeit
            if isinstance(event, ButtonEvent) and isValid and event.value == 0:
                #print('New Button Event Release')
                if self.lastButton is None:
                    self.lastButton = event.getTime()
                    #print('Erstes Event')
                elif (Decimal('{}'.format(event.getTime())).normalize() - Decimal('{}'.format(self.lastButton)).normalize()) > self.buttonTimeout:
                    self.lastButton = event.getTime()
                    #print('Replaced Event')
                else:
                    #Es handelt sich um ein Doppelklick und ein Aboart Event muss generiert werden
                    #print('Removing')
                    aboartEvent = AboartEvent(time.time())
                    self.signalsLock.acquire()
                    self.signals.append(aboartEvent)
                    #print('Put aboart')
                    #print(self.signals)
                    self.signalsLock.release()
                    self.lastButton = None
                    continue
            ###

            #Put it into queue or delete it
            if isValid:
                self.addEvent(event)

            #GGF in einen eigenen Event Thread? Achtung: Auf die Reihenfolge
            #der Events dann achten. Nicht dass das Aboart Event for dem Touch
            #Event auftritt und das Touch Release Event somit dann verloren geht
            #self.touchedAreasAndAboartEvent(event)

        self.cleanUp()

    def touchedAreasAndAboartEvent(self, event):
        tmpCurrentTouches = self.currentTouches
        if isinstance(event, TouchEvent):
            #print(event.getValue())
            if event.getValue() == 0:
                self.currentTouches = self.currentTouches - 1
                if self.currentTouches == 0:
                    aboartEvent = AboartEvent(time.time())
                    self.signalsLock.acquire()
                    self.signals.append(aboartEvent)
                    self.signalsLock.release()
            else:
                self.currentTouches = self.currentTouches + 1

        if tmpCurrentTouches != self.currentTouches:
            print("Anzahl der berührten Flächen: {}".format(self.currentTouches))

    def addEvent(self, event):
        self.signalsLock.acquire()
        self.signals.append(event)
        self.signalsLock.release()

    def observeTouchEvent(self, event):
        subDic = None
        if event.getLocation() in self.touchEventsMetaInfo:
            subDic = self.touchEventsMetaInfo[event.getLocation()]
        else:
            subDic = {}
            subDic['lastEventValue'] = None
            subDic['event'] = None
            self.touchEventsMetaInfo[event.getLocation()] = subDic

        subDic['event'] = event
        #print('added')
            
    def updateObservedTouchEvents(self):
        for key in self.touchEventsMetaInfo:
            subDic = self.touchEventsMetaInfo[key]
            subDic['timeSinceLastEvent'] = Decimal(time.time()) - subDic['event'].getTime()

        for key in self.touchEventsMetaInfo:
            subDic = self.touchEventsMetaInfo[key]
            if subDic['timeSinceLastEvent'] > self.threshhold:
                if subDic['lastEventValue'] == None or subDic['lastEventValue'] != subDic['event'].getValue():
                    self.addEvent(subDic['event'])
                    self.touchedAreasAndAboartEvent(subDic['event'])
                    #print('finally')
                    subDic['lastEventValue'] = subDic['event'].getValue()
                    
    def checkSharedMemory(self):
        import time
        if self.smCounter < self.sm.getSize():
            message = self.sm.get(self.smCounter)
            self.smCounter = self.smCounter + 1

            if message == IPCMemory.SHUTDOWN:
                print('I shall shutdown')
                time.sleep(2)
                sys.exit()
            elif message == IPCMemory.NEW_MOTION:
                #print('A new Motion appeared')
                self.signalsLock.acquire()
                del self.signals[:]
                self.signalsLock.release()
                self.bareSignalsLock.acquire()
                del self.bareSignals[:]
                self.bareSignalsCounter = 0
                self.bareSignalsLock.release()

    def cleanUp(self):
        print('Verfication finished')
示例#13
0
class IPCGrabber(object):
    CompNone, CompLZ4, CompJPEG = range(3)

    def __init__(self, frame_queue):
        self.frame_queue = frame_queue
        self.memory = None

    def start(self):
        self.can_run = True
        self.stopped = threading.Event()
        t_cap = threading.Thread(target=self.on_read_frames)
        t_cap.daemon = True
        t_cap.start()

    def stop(self, timeout=1):
        self.can_run = False
        self.stopped.wait(timeout)

    def read_frame(self):
        mem_header_size = 7 * 4
        # 7x uint32_t's

        if self.memory == None:
            print "Allocating memory: {0}".format(mem_header_size)
            self.memory = IPCMemory("/picamera_grabber_mem", mem_header_size)
            self.memory.bringup()

        mem_struct_data = self.memory.read(0, mem_header_size)
        memory_size, xres, yres, format, slot1_offset, slot2_offset, current_slot = struct.unpack(
            '@IIIIIII', mem_struct_data)

        if self.memory.size != memory_size:
            print "Reallocating memory: {0}".format(memory_size)
            self.memory = IPCMemory("/picamera_grabber_mem", memory_size)
            self.memory.bringup()

        if current_slot == 0:
            frame_offset = slot1_offset
        else:
            frame_offset = slot2_offset

        frame_header_size = (2 * 4) + 1 + (3 * 1)
        # 2x uint32_t's + bool + 3x uint8_t packing
        frame_struct_data = self.memory.read(frame_offset, frame_header_size)
        real_size, compressed_size, compressed, _, _, _ = struct.unpack(
            '@IIBBBB', frame_struct_data)
        if compressed == IPCGrabber.CompNone:
            size = real_size
        else:
            size = compressed_size

        print "Slot: {0} | size: {1} | compressed: {2}".format(
            current_slot, size, compressed),
        frame = self.memory.read(frame_offset + frame_header_size, size)
        return frame, xres, yres, compressed

    def on_read_frames(self):
        print "IPC Grabber starting"
        last_timestamp = time.time()
        time.sleep(0.1)

        sem_generate = IPCSemaphore("/picamera_grabber_generate")
        sem_generate.bringup()

        sem_notifier = IPCSemaphore("/picamera_grabber_notifier")
        sem_notifier.bringup()

        while True:
            if self.can_run == False:
                break

            data = None
            now_timestamp = None
            fps = 0
            if sem_notifier.acquire(1):
                now_timestamp = time.time()
                diff = now_timestamp - last_timestamp
                last_timestamp = now_timestamp
                fps = 1 / diff

                data, xres, yres, compression = self.read_frame()
                print " | FPS: {0:.2f}".format(fps)
                sem_generate.release()

            if data != None:
                try:
                    str_format = "str_"
                    if compression == IPCGrabber.CompNone:
                        str_format += "none"
                    elif compression == IPCGrabber.CompLZ4:
                        str_format += "lz4"
                    elif compression == IPCGrabber.CompJPEG:
                        str_format += "jpeg"
                    self.frame_queue.put(Frame(data, str_format, now_timestamp,
                                               fps, fps, xres, yres),
                                         block=True,
                                         timeout=0.001)
                except Exception, e:
                    print e
                    pass

        print "Grabber stopping"
        self.stopped.set()
示例#14
0
class TouchListener(threading.Thread):

    usbPath = '/dev/ttyACM0'
    baudrate = 9600

    def __init__(self, bareSignals, bareSignalsLock):
        threading.Thread.__init__(self)
        self.bareSignals = bareSignals
        self.bareSignalsLock = bareSignalsLock

        self.sm = IPCMemory()
        self.smCounter = 0

        self.ser = serial.Serial(self.usbPath, self.baudrate)
        self.ser.flush()

    def run(self):
        print('TouchListener is running')
        self.startListening()

    def startListening(self):
        while True:
            self.checkSharedMemory()
            if (self.ser.inWaiting() <= 0):
                continue

            event = self.getEvent()

            if event == None:
                continue

            self.bareSignalsLock.acquire()
            self.bareSignals.append(event)
            self.bareSignalsLock.release()

        self.cleanUp()

    def getEvent(self):
        input = self.ser.readline()
        input = self.convertText(input)

        event = input[:input.find(';')]
        input = input[input.find(';') + 1:]
        location = input[:input.find(';')]
        input = input[input.find(';') + 1:]
        val = input[:input.find(';')]
        val = Decimal('{}'.format(val)).normalize()

        t = time.time()
        t = Decimal('{}'.format(t)).normalize()

        if event == EVENT_TOUCH:
            return TouchEvent(t, location, val)
        else:
            return None

    def convertText(self, text=None):
        text = text[:len(text) - 2]
        text = text.decode('utf-8')
        return text

    def checkSharedMemory(self):
        import time
        if self.smCounter < self.sm.getSize():
            message = self.sm.get(self.smCounter)
            self.smCounter = self.smCounter + 1

            if message == IPCMemory.SHUTDOWN:
                print('I shall shutdown')
                time.sleep(2)
                self.cleanUp()
                sys.exit()

    def cleanUp(self):
        print('TouchListener wurde beendet')
class MotionDetecter(threading.Thread):

    MODE_RECOGNITION = 'recognition'
    MODE_LEARNING = 'learning'

    def __init__(self, signals, signalsLock):
        threading.Thread.__init__(self)
        self.signals = signals
        self.signalsLock = signalsLock
        self.sm = IPCMemory()
        self.smCounter = 0

        self.motionManager = MotionManager()

    def run(self):
        print("Motion Detecter is running")
        print(self.motionManager.getAllMotions())
        if not self.motionManager.getAllMotions():
            self.learnLearningMotion()
        self.startRecognition()

    def startRecognition(self):
        self.mode = self.MODE_RECOGNITION
        while True:
            self.waitForAboart()
            print('Geste wurde erkannt')
            self.sm.add(IPCMemory.RESET_ROTATION_SUM)

            transformer = MotionTransformer()
            motionToCompare = transformer.transformMotion(self.signalsCopy)

            c = Calculator()
            bestMotion = None
            bestScore = None
            for motion in self.motionManager.getAllMotions():
                matchingScore = c.getMatchingScore(self.motionManager.getMotion(motion), motionToCompare)
                print("Matching Score with '{}': {}".format(self.motionManager.getMotion(motion).getName(), matchingScore))

                if bestMotion == None:
                      bestScore = matchingScore
                      bestMotion = self.motionManager.getMotion(motion)
                      continue

                if matchingScore > bestScore:
                      bestScore = matchingScore
                      bestMotion = self.motionManager.getMotion(motion)

            if bestMotion == None:
                print("Es sind noch keine Motions angelernt")
            else:
                print("Motion {} für Device {} erkannt".format(bestMotion.getName(), bestMotion.getAssignedDevice()))

            if bestMotion.getName() == 'startLearning':
                self.sm.add(IPCMemory.START_LEARNING)

    def startLearning(self):
        self.mode = self.MODE_LEARNING
        self.signalsLock.acquire()
        del self.signals[:]
        self.signalsLock.release()

        self.waitForAboart()

        self.sm.add(IPCMemory.RESET_ROTATION_SUM)

        transformer = MotionTransformer()
        try :
            motion = transformer.transformMotion(self.signalsCopy)
        except NotEnoughSignals:
            print("Die Geste beinhaltet keine Aktionen. Sie wird nicht gespeichert")
            return

        name = input('Wie soll die Motion heißen?')
        motion.setName(name)

        self.motionManager.addMotion(motion)

        self.mode = self.MODE_RECOGNITION

    def learnLearningMotion(self):
        self.mode = self.MODE_LEARNING
        self.signalsLock.acquire()
        del self.signals[:]
        self.signalsLock.release()
        
        print('Jetzt bitte Geste ausführen mit der später neue Gesten angelernt werden sollen')

        self.waitForAboart()

        self.sm.add(IPCMemory.RESET_ROTATION_SUM)

        transformer = MotionTransformer()
        try :
            motion = transformer.transformMotion(self.signalsCopy)
        except NotEnoughSignals:
            print("Die Geste beinhaltet keine Aktionen. Sie wird nicht gespeichert")
            return

        motion.setName('startLearning')

        self.motionManager.addMotion(motion)

    def waitForAboart(self):
        print('Jetzt bitte Geste ausführen und mit Doppelklick bestätigen')
        counter = 0

        while True:
            self.checkSharedMemory()
            self.signalsLock.acquire()
            if len(self.signals) <= counter:
                self.signalsLock.release()
                continue
            event = self.signals[counter]

            if event != None and event.getEvent() == EVENT_ABOART:
                self.saveCopyOfSignals()
                self.removeAboartEvent(self.signalsCopy)
                self.removeNones(self.signalsCopy)
                del self.signals[:]
                self.signalsLock.release()
                break

            self.signalsLock.release()
            counter = counter + 1

    def removeAboartEvent(self, signals):
        for i in range(len(signals)-1, -1, -1):
            if signals[i].getEvent() == EVENT_ABOART:
                del signals[i]
                break

    #Signales that triggered the aboart are marked as None
    def removeNones(self, signals):
        for i in range(len(signals)-1, -1, -1):
            if signals[i] == None:
                del signals[i]

    #ATTENTION! LOCK MUST BE REQUIRED FIRST!!!
    def saveCopyOfSignals(self):
        self.signalsCopy = self.signals[:]

    def clearDoubleClick(self, signals):
        removedButtonEvents = 0
        for i in range(len(signals)-1, -1, -1):
            if removedButtonEvents == 4:
                break
            
            event = signals[i]
            if isinstance(event, ButtonEvent):
                del signals[i]
                removedButtonEvents = removedButtonEvents + 1

    def checkSharedMemory(self):
        import time
        #print('Checking Size')
        #print('SmCounter = {}'.format(self.smCounter))
        #print('SmSize = {}'.format(self.sm.getSize()))
        if self.smCounter < self.sm.getSize():
            message = self.sm.get(self.smCounter)
            #print(message)

            self.smCounter = self.smCounter + 1

            if message == IPCMemory.SHUTDOWN:
                print('I shall shutdown')
                time.sleep(2)
                sys.exit()
            elif message == IPCMemory.START_LEARNING:
                if self.mode == self.MODE_LEARNING:
                    print("I'm already learning")
                else:
                    print('I shall start learning')
                    time.sleep(2)
                    self.startLearning()
            elif message == IPCMemory.START_RECOGNIZING:
                if self.mode == self.MODE_RECOGNITION:
                    print("I'm already recognizing")
                else:
                    print('I shall start recognition')
                    time.sleep(2)
                    self.startRecognition()