class ElevatorWrapper: topFloor = 3 botFloor = 0 def __init__(self): self.elevator = Driver() self.direction = 0 self.lastFloor = self.getFloor() if self.getFloor() != None else -1 self.destination = 0 self.externalFloorListener = None self.stop = self.elevator.stop self.addListener = self.elevator.addListener for i, floor in enumerate(INPUT.SENSORS): self.elevator.addListener(floor, partial(self.floorListener, i)) self.addListener(INPUT.STOP, self.stopstruction) self.addListener(INPUT.OBSTRUCTION, self.stopstruction) def moveToFloor(self, floor): if self.elevator.readChannel(INPUT.OBSTRUCTION): print "Obstruction" return if floor > self.topFloor: print "Too much floor: %i > %i , WAT" % (floor, self.topFloor) return print "Moving to floor", floor if floor > self.lastFloor: print "Going up" self.elevator.move(OUTPUT.MOTOR_UP) self.direction = 1 elif floor < self.lastFloor: print "Going down" self.elevator.move(OUTPUT.MOTOR_DOWN) self.direction = 0 else: print "Open doors" self.destination = floor def floorListener(self, floor, en, to): # TODO: en, to print "At floor", floor if floor == self.destination and self.floorListener == None: print "At destination" self.elevator.stop() elif floor >= self.topFloor and self.direction == 1: print "Stop it! (top)", floor, self.topFloor, self.direction self.elevator.stop() elif floor <= self.botFloor and self.direction == 0: print "Stop it! (bot)", floor, self.botFloor, self.direction self.elevator.stop() """if self.lastFloor < floor: self.direction = 1 elif self.lastFloor > floor: self.direction = 0 else: print "derp" """ self.lastFloor = floor; print type(floor) self.elevator.setFloorIndicator(floor) self.externalFloorListener(floor) def buttonListener(self, where, what, floor, en, to): #TODO en, to print where, what, floor if where == "in": self.moveToFloor(floor) elif where == "out": if what == "up": self.moveToFloor(floor) elif what == "down": self.moveToFloor(floor) else: raise ValueError("Invalid \"where\"") def stopstruction(self, en, to): # TODO: en, to self.elevator.stop() if self.lastFloor % 1.0 != 0.5 and self.getFloor() == None: self.lastFloor = self.lastFloor + (0.5 if self.direction else -0.5) print "Stopped, now at", self.lastFloor def isObstructed(self): return self.elevator.readChannel(INPUT.OBSTRUCTION) def down(self): self.elevator.move(OUTPUT.MOTOR_DOWN) sleep(2.0) self.elevator.stop() def getFloor(self): return self.elevator.getCurrentFloor() def addButtonListener(self, listener): self.addListener(INPUT.FLOOR_UP1, partial(listener, "out", "up", 0)) self.addListener(INPUT.FLOOR_UP2, partial(listener, "out", "up", 1)) self.addListener(INPUT.FLOOR_UP3, partial(listener, "out", "up", 2)) self.addListener(INPUT.FLOOR_DOWN2, partial(listener, "out", "down", 1)) self.addListener(INPUT.FLOOR_DOWN3, partial(listener, "out", "down", 2)) self.addListener(INPUT.FLOOR_DOWN4, partial(listener, "out", "down", 3)) self.addListener(INPUT.FLOOR_COMMAND1, partial(listener, "in", "", 0)) self.addListener(INPUT.FLOOR_COMMAND2, partial(listener, "in", "", 1)) self.addListener(INPUT.FLOOR_COMMAND3, partial(listener, "in", "", 2)) self.addListener(INPUT.FLOOR_COMMAND4, partial(listener, "in", "", 3)) def addFloorListener(self, listener): self.externalFloorListener = listener
class Elevator: DIRECTION_UP = 1 DIRECTION_DOWN = -1 DIRECTION_STAND = 0 LEAVE_DOORS_OPEN = 2 def __init__(self): self.driver = Driver() self.previous_floor = 1 self.direction = self.DIRECTION_UP self.queue = [] # A Queue of orders self.task = [] # The current order that is being taken care of self.motor_speed = 1000 self.elevator = None # *** hva brukes denne til og hvor settes den til en verdi? *** def go_to_floor(self, floor, lock): """does what its name implies""" current_floor = self.driver.getCurrentFloor() if not current_floor: current_floor = self.previous_floor if current_floor < floor: self.direction = self.DIRECTION_UP self.driver.move(OUTPUT.MOTOR_UP, self.motor_speed) elif current_floor == floor: self.driver.stop() self.pop_task(lock) elif current_floor > floor: self.driver.move(OUTPUT.MOTOR_DOWN, self.motor_speed) self.direction = self.DIRECTION_DOWN def pop_task(self, lock): """removes a task from the list of tasks and preforms cleanup""" lock.acquire() floor = self.task.pop() lock.release() light = self.driver.getAccordingLight(INPUT.IN_BUTTONS, floor) self.driver.setChannel(light, 0) self.open_doors() def open_doors(self): """simulates opening the doors of the elevator and waiting""" start = time.clock() while time.clock() < self.LEAVE_DOORS_OPEN + start: self.driver.stop() def add_job(self, floor, direction, lock): """adds a job to the queue or task""" if task: # check whether this could be added as a subtask if ( self.direction == self.DIRECTION_UP == direction and self.previous_floor < floor <= self.task[len(self.task) - 1][0] ): self.add_subtask(floor, direction, lock) elif ( self.direction == self.DIRECTION_DOWN == direction and self.previous_floor > floor >= self.task[len(self.task) - 1][0] ): self.add_subtask(floor, direction, lock) else: lock.acquire() self.queue.append((floor, direction)) lock.release() else: lock.acquire() task.append((floor, direction)) lock.release() def add_subtask(self, floor, direction, lock): """adds a subtask to the task in correct order""" lock.acquire() for i, sub in enumerate(self.task): if direction == self.DIRECTION_DOWN: if sub >= self.task[i]: self.task.insert(sub, i) else: if sub <= self.task[i]: self.task.insert(sub, i) lock.release() def read_inputs(self, lock): """reads inputs and processes them""" for sig in INPUT.BUTTONS: if self.driver.readChannel(sig): (floor, type) = self.driver.channelToFloor(sig) light = self.driver.getAccordingLight(type, floor) self.driver.setChannel(light, 1) if type == INPUT.IN_BUTTONS: self.add_subtask(floor, self.direction, lock) elif type == INPUT.DOWN_BUTTONS: job = (floor, self.DIRECTION_DOWN) if self.check_job(job): self.add_job(floor, self.DIRECTION_DOWN, lock) else: ElevatorProcess(target=self.elevator.send_job, args=(self.elevator, job)).start() elif type == INPUT.UP_BUTTONS: job = (floor, self.DIRECTION_UP) if self.check_job(job): self.add_job(floor, self.DIRECTION_UP, lock) else: ElevatorProcess(target=self.elevator.send_job, args=(self.elevator, job)).start() if self.driver.readChannel(INPUT.OBSTRUCTION): self.driver.stop() floor = self.driver.getCurrentFloor() if floor: self.driver.setFloorIndicator(floor) self.previous_floor = floor def check_job(self, job): """checks whether or not this elevator wants the given job""" (floor, direction) = job if not task: return True elif ( self.direction == self.DIRECTION_UP == direction and self.previous_floor < floor <= self.task[len(self.task) - 1][0] ): return True elif ( self.direction == self.DIRECTION_DOWN == direction and self.previous_floor > floor >= self.task[len(self.task) - 1][0] ): return True else: return False def reset_lights(self): for l in OUTPUT.LIGHTS: self.driver.setChannel(l, 0) def pick_from_queue(self): """picks the next suitable job from the queue""" counter = 0 while True: for i in len(self.queue): if abs(self.queue[i][0] - counter) <= counter: self.task.append(self.queue[i]) self.queue.remove(self.queue[i]) return counter += 1 def start(self, handler): """starts the elevator""" self.handler = handler lock = Lock() input_reader = ElevatorProcess(target=read_inputs, args=(self, lock)) input_reader.start() while True: if self.task: self.go_to_floor(self.task[0][0], lock) elif self.queue: lock.acquire() self.pick_from_queue() lock.release() input_reader.terminate()