def onEnter(self): self.__durationSeconds = self.configuration['pedestrianTimer'] self.logger.info('Pedestrian crossing initialized') sendNotification(NotificationLevel.INFO, 'Pedestrians can now cross', {'pedestriansCrossing': True}) self.__nextLightState = self.engine.nextLightDirection + '_green' self.__startTimeSeconds = time.time()
def __tryExecuteStateTransition(self): ''' (Internal, for engine use only) This internal method will actually transition the state machine into the state that was requested by 'gotoState'. If we are in 'state stepper mode', we will first pause the machine. ''' if self.__nextRequestedState == None: return False if self.__inStateStepperMode and not self.__hasPausedForStepper: self.pause() self.__hasPausedForStepper = True return True # Return True so that we can get a clean update loop self.__hasPausedForStepper = False # We have paused for the stepper at this point, so let's reset it if not self.__currentState == None: prevState = self.getCurrentState() if prevState != None: prevState.onLeave() prevState.freeCallbacks() sendNotification(NotificationLevel.APP_STATE_CHANGE, 'Entered MachineApp state: {}'.format(self.__nextRequestedState)) self.__currentState = self.__nextRequestedState self.__nextRequestedState = None nextState = self.getCurrentState() if nextState != None: nextState.onEnter() return True
def __mqttEventCallback(self, topic, msg): topicParts = topic.split('/') deviceType = topicParts[1] if deviceType != 'io-expander': return if (topicParts[3] == 'available'): return isInput = False if topicParts[3] == 'digital-output': isInput = False elif topicParts[3] == 'digital-input': isInput = True device = int(topicParts[2]) pin = int(topicParts[4]) value = msg for monitorItem in self.__monitorList: if monitorItem.isEqual(isInput, device, pin): monitorItem.state = value sendNotification(NotificationLevel.IO_STATE, '', monitorItem.toJson()) break
def onEnter(self): self.logger.info('{} direction entered the RED light state'.format( self.__direction)) sendNotification( NotificationLevel.INFO, 'Set light to RED for {} conveyor'.format(self.__direction), { "direction": self.__direction, "color": 'red', "speed": 0 }) self.__startTimeSeconds = time.time()
def onEnter(self): self.__startTimeSeconds = time.time() self.logger.info('{} direction entered the YELLOW light state'.format( self.__direction)) sendNotification( NotificationLevel.INFO, 'Set light to YELLOW for {} conveyor'.format(self.__direction), { "direction": self.__direction, "color": 'yellow', "speed": self.__speed }) def __onPedestrianButtonClicked(topic, msg): if msg == 'true': self.engine.isPedestrianButtonTriggered = True self.engine.nextLightDirection = 'vertical' if self.__direction == 'horizontal' else 'horizontal' self.registerCallback(self.engine.primaryMachineMotion, 'push_button_1', __onPedestrianButtonClicked) self.__machineMotion.setContinuousMove(self.__axis, self.__speed)
def onEnter(self): self.logger.info('{} direction entered the GREEN light state'.format( self.__direction)) # Record the time that we entered this state self.__startTimeSeconds = time.time() # Inform the frontend's console that we've entered this state. See Notifier::sendMessage for more information # on the parameters defined here. sendNotification( NotificationLevel.INFO, 'Set light to GREEN for {} conveyor'.format(self.__direction), { "direction": self.__direction, "color": 'green', "speed": self.__speed }) # Register a callback that gets set when the push button is clicked def __onPedestrianButtonClicked(topic, msg): if msg == 'true': self.engine.isPedestrianButtonTriggered = True self.engine.nextLightDirection = 'vertical' if self.__direction == 'horizontal' else 'horizontal' self.gotoState(self.__direction + '_yellow') # Register to listen to the hardware IO (like a push button)... self.registerCallback(self.engine.primaryMachineMotion, 'push_button_1', __onPedestrianButtonClicked) # Or register to listern to the software IO (like a button in your web page)! self.registerCallbackOnTopic(self.engine.primaryMachineMotion, 'software_button', __onPedestrianButtonClicked) # Set the axis moving self.__machineMotion.setContinuousMove(self.__axis, self.__speed) sendNotification( NotificationLevel.INFO, 'Green light with axis={}, speed={}'.format( self.__axis, self.__speed))
def loop(self, inStateStepperMode, configuration): ''' Main loop of your MachineApp. ''' if self.__isRunning: return False sendNotification(NotificationLevel.APP_START, 'MachineApp started') self.logger.info('Starting the main MachineApp loop') # Configure run time variables self.__inStateStepperMode = inStateStepperMode self.configuration = configuration self.__isRunning = True # Run initialization sequence self.initialize() self.__stateDictionary = self.buildStateDictionary() # Begin the Application by moving to the default state self.gotoState(self.getDefaultState()) # Inner Loop running the actual MachineApp program while self.__isRunning: if self.__shouldStop: # Running stop behavior self.__shouldStop = False self.__isRunning = False self.onStop() currentState = self.getCurrentState() if currentState != None: currentState.onStop() break if self.__shouldPause: # Running pause behavior if self.__hasPausedForStepper: sendNotification( NotificationLevel.APP_PAUSE, 'Paused for stepper mode: Moving from {} state to {} state' .format(self.__currentState, self.__nextRequestedState)) else: sendNotification(NotificationLevel.APP_PAUSE, 'MachineApp paused') self.__shouldPause = False self.__isPaused = True if not self.__hasPausedForStepper: # Only do pause behavior if we're not doing the stepper-mandated pause self.onPause() currentState = self.getCurrentState() if currentState != None: currentState.onPause() if self.__shouldResume: # Running resume behavior sendNotification(NotificationLevel.APP_RESUME, 'MachineApp resumed') self.__shouldResume = False self.__isPaused = False if not self.__hasPausedForStepper: # Only do resume behavior if we're not doing the stepper-mandated pause self.onResume() currentState = self.getCurrentState() if currentState != None: currentState.onResume() if self.__isPaused: # While paused, don't do anything time.sleep(BaseMachineAppEngine.UPDATE_INTERVAL_SECONDS) continue if self.__nextRequestedState != None: # Running state transition behavior if self.__tryExecuteStateTransition(): continue # If the transition is executed successfully, let's get a clean update loop currentState = self.getCurrentState() if currentState == None: self.logger.error('Currently in an invalid state') continue currentState.updateCallbacks() currentState.update() time.sleep(BaseMachineAppEngine.UPDATE_INTERVAL_SECONDS) self.logger.info('Exiting MachineApp loop') sendNotification(NotificationLevel.APP_COMPLETE, 'MachineApp completed') self.afterRun() return True
def onLeave(self): sendNotification(NotificationLevel.INFO, 'Pedestrians can NOT cross anymore', {'pedestriansCrossing': False}) self.engine.isPedestrianButtonTriggered = False
def onEnter(self): self.engine.primaryMachineMotion.emitSpeed(25) self.engine.primaryMachineMotion.emitCombinedAxisRelativeMove( [1, 2], ['positive', 'positive'], [250, 250]) sendNotification(NotificationLevel.INFO, 'Moving to the start position')
def onEnter(self): self.engine.primaryMachineMotion.emitHomeAll() sendNotification(NotificationLevel.INFO, 'Moving to home') self.gotoState('horizontal_green')