예제 #1
0
    def __init__(self):
        super(ApplicationWindow, self).__init__()
        self.bus_num = Logic.bus_num
        self.bus = SMBus(self.bus_num)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Get easy access to UI elements
        self.rgb = self.ui.lid_display.layout()
        self.minutes = self.ui.lcdMinutes
        self.seconds = self.ui.lcdSeconds
        self.potentiometer = self.ui.dial

        # TODO Make connections to functions

        # TODO Listen on the SMBus for messages and then call the right functions

        for h, button in self.keypad.items():
            button.clicked.connect(
                partial(lambda: self.bus.write_byte(self.bus_num, I2C.ARDUINO),
                        h))

        for _, checkbox in self.photo_resistor.items():
            checkbox.clicked.connect(
                partial(lambda: self.bus.write_byte_data(
                    self.bus_num, I2C.LASERS, self.laser_mask)))

        self.potentiometer.valueChanged.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.ROTARY,
                                             self.potentiometer.value()))

        for _, switch in self.switches.items():
            switch.valueChanged.connect(lambda: self.bus.write_byte_data(
                self.bus_num, I2C.SWITCHES, self.switch_mask))

        # Colored disconnectable wires
        self.ui.wire_red.clicked.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.WIRE, 0xd))
        self.ui.wire_blue.clicked.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.WIRE, 0xb))
        self.ui.wire_green.clicked.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.WIRE, 0xe))

        # Reset button
        self.ui.start_reset.clicked.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.RESET, 0x1))

        self.ui.ultrasonicSlider.valueChanged.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.ULTRASONIC,
                                             self.ui.ultrasonicSlider.value()))

        self.scheduler = APScheduler(scheduler=BackgroundScheduler())
        self.scheduler.add_job("poll",
                               self.poll_sensors,
                               max_instances=2,
                               replace_existing=False)
예제 #2
0
    def __init__(self):
        self.laserPattern = LaserPattern.ONE_CYCLES
        self._timer = 0
        self._patternIndex = 0

        # Initialize ICc Devices
        self._bus = SMBus(self.bus_num)
        self.lasers = LaserControl(self._bus)
        self.arduino = SevenSeg(self._bus)
        self.photo_resistors = ReceptorControl(self._bus)
예제 #3
0
class Logic:
    bus_num = 1
    db = Database()
    shared = Manager().dict()
    scheduler = None
    lasers = None
    _comQueue = Queue()
    _process = Lock()
    _solenoid = SOLENOID_STATE.UNLOCKED
    _ultrasonic = ULTRASONIC_STATE.ENABLED
    _laserState = LaserPattern.LASER_OFF
    _laserCounter = 0
    _patternIndex = 0
    _laserValue = 0x00

    def __init__(self):
        self.laserPattern = LaserPattern.ONE_CYCLES
        self._timer = 0
        self._patternIndex = 0

        # Initialize ICc Devices
        self._bus = SMBus(self.bus_num)
        self.lasers = LaserControl(self._bus)
        self.arduino = SevenSeg(self._bus)
        self.photo_resistors = ReceptorControl(self._bus)

    @property
    def patternIndex(self) -> int:
        return self._patternIndex

    @patternIndex.setter
    def patternIndex(self, value: int):
        self._patternIndex = value

    @property
    def laserCounter(self) -> int:
        return self._laserCounter

    @laserCounter.setter
    def laserCounter(self, value: int):
        self._laserCounter = value

    def laserCounterIncrement(self):
        self.laserCounter = self.laserCounter + 1

    @property
    def laserState(self) -> LaserPattern:
        return LaserPattern(
            self.shared.get("laserpattern", LaserPattern.LASER_OFF.value))

    @laserState.setter
    def laserState(self, value: LaserPattern):
        self.shared["laserpattern"] = value.value

    @property
    def laserValue(self) -> int:
        return self.shared.get("laservalue", 0x00)

    @laserValue.setter
    def laserValue(self, value: int):
        self.shared["laservalue"] = value

    @property
    def timer_text(self) -> str:
        newDatetime = datetime.now() - self.start_time
        seconds = MAX_TIME - newDatetime.seconds
        minutes = seconds // 60
        secondsToPrint = seconds - minutes * 60
        if self.state is STATE.WAIT:
            return "RESET"
        if self.state is STATE.RUNNING:
            if minutes < 0 or seconds < 0:
                ComQueue().getComQueue().put([INTERRUPT.KILL_PLAYER])
                return "DEAD"
        elif self.state is STATE.EXPLODE:
            return "DEAD"
        elif self.state is STATE.WIN:
            return "SUCCESS!"
        return "{}:{:2}".format(minutes, str(secondsToPrint).zfill(2))

    @property
    def start_time(self) -> datetime:
        return self.shared.get("start time", datetime.now())

    @start_time.setter
    def start_time(self, value: datetime):
        self.shared["start time"] = value

    @property
    def ultrasonic(self) -> ULTRASONIC_STATE:
        return ULTRASONIC_STATE(
            self.shared.get("ultrasonic", ULTRASONIC_STATE.ENABLED.value))

    @ultrasonic.setter
    def ultrasonic(self, value: ULTRASONIC_STATE):
        # TODO send the new ultrasonic logic over I2C
        log.debug("Ultrasonic logic changed from {} to {}".format(
            self.ultrasonic.value, value.value))
        self.shared["ultrasonic"] = value.value

    @property
    def comQueue(self) -> Queue:
        return self._comQueue

    @comQueue.setter
    def comQueue(self, value):
        log.debug("Queue was created")
        self._comQueue = value

    @property
    def solenoid(self) -> SOLENOID_STATE:
        return SOLENOID_STATE(
            self.shared.get("solenoid", SOLENOID_STATE.UNLOCKED.value))

    @solenoid.setter
    def solenoid(self, value: SOLENOID_STATE):
        # TODO send the new solenoid logic over I2C
        log.debug("Solenoid logic changed from {} to {}".format(
            self.solenoid.value, value.value))
        self.shared["solenoid"] = value.value

    @property
    def state(self):
        return STATE(self.shared.get("logic", STATE.WAIT.value))

    @state.setter
    def state(self, value: STATE):
        log.debug("State changed from {} to {}".format(self.state.value,
                                                       value.value))
        self.shared["logic"] = value.value

    @property
    def keypad_code(self) -> hex:
        return self.shared.get("code", 0x000)

    @keypad_code.setter
    def keypad_code(self, value: hex):
        assert 0x0 <= value <= 0xfff
        log.debug("Setting new keypad code: 0x{}".format(value))
        self.shared["code"] = value

    @property
    def team(self) -> str:
        return self.shared.get(
            "team", self.db.last.name if self.db.get_rows() else "--")

    @team.setter
    def team(self, value: str):
        log.debug("Setting current team name to: {}".format(value))
        self.shared["team"] = value
        if self.db.get_rows():
            self.db.last = Row(name=value)

    @property
    def rgb_color(self) -> RGBColor:
        return RGBColor(self.shared.get("rgb", RGBColor.BLANK.value))

    @rgb_color.setter
    def rgb_color(self, value: RGBColor):
        log.debug("Setting new rgb color: {}".format(value))
        # TODO send the command over i2c to change the rgb color
        self.shared["rgb"] = value.value

    def run(self, queue: Queue, mock: bool):
        """
        Start the game and make sure there is only a single instance of this process
        This is the setup function, when it is done, it will start the game loop
        """
        with self._process:
            # Initialize I2C server
            self.state = STATE.WAIT  # Change logic of game to WAIT
            self.solenoid = SOLENOID_STATE.LOCKED
            self.comQueue = queue
            self.ultrasonic = ULTRASONIC_STATE.ENABLED
            self.laserPattern = LaserPattern.ONE_CYCLES
            self.scheduler = APScheduler(scheduler=BackgroundScheduler(),
                                         app=current_app)
            self.scheduler.add_job("loop",
                                   self._loop,
                                   trigger='interval',
                                   seconds=1,
                                   max_instances=1,
                                   replace_existing=False)
            self.scheduler.start()

            # TODO start thread polling sensors
            try:
                while True:
                    self.poll_sensors()
            except KeyboardInterrupt:
                return

    def poll_sensors(self):
        """
        Poll all of the sensors and raise a flag if one of them has tripped.
        If the right wire was clipped at the end of the puzzle, raise the win flag
        """
        """
        for i in I2C:
            word = self._bus.read_byte_data(self.bus_num, i)
            if word is not None:
                # log.info("{}: {}".format(i.name, hex(word)))
                if i is I2C.RESET:
                    ComQueue().getComQueue().put([INTERRUPT.TOGGLE_TIMER])
                elif i is I2C.LASERS:
                    if self.laserValue != word:
                        ComQueue().getComQueue().put([INTERRUPT.KILL_PLAYER])
        """

        # self._bus.write_byte_data(I2C.LASERS.value, 0, 9) # for i2c in I2C:
        #     log.debug("Reading from I2C on {}".format(i2c.name))
        #     foo = self._bus.read_word_data(i2c.value, 0)
        #     self._send(I2C.SEVEN_SEG, "Hello!")

    def getNextLaserPatternList(self):
        if self.laserState is LaserPattern.ONE_CYCLES:
            return LaserPattern.TWO_CYCLES
        elif self.laserState is LaserPattern.TWO_CYCLES:
            return LaserPattern.UP_AND_DOWN
        elif self.laserState is LaserPattern.UP_AND_DOWN:
            return LaserPattern.INVERSION
        elif self.laserState is LaserPattern.INVERSION:
            return LaserPattern.LASER_OFF
        else:
            return self.laserState

    def getLaserPattern(self):
        if self.laserState is LaserPattern.ONE_CYCLES:
            pattern = LaserPatternValues.ONE_CYCLES.value
        elif self.laserState is LaserPattern.TWO_CYCLES:
            pattern = LaserPatternValues.TWO_CYCLES.value
        elif self.laserState is LaserPattern.UP_AND_DOWN:
            pattern = LaserPatternValues.UP_AND_DOWN.value
        elif self.laserState is LaserPattern.INVERSION:
            pattern = LaserPatternValues.INVERSION.value
        elif self.laserState is LaserPattern.LASER_OFF:
            pattern = LaserPatternValues.LASER_OFF.value
        elif self.laserState is LaserPattern.RANDOM:
            pattern = LaserPatternValues.RANDOM.value
        elif self.laserState is LaserPattern.STATIC:
            return self.laserValue
        else:
            pattern = None

        # Increment the patternIndex
        if pattern is not None:
            if self.patternIndex < len(pattern):
                retValue = pattern[self.patternIndex]
                self.patternIndex += 1
            else:
                self.patternIndex = 0
                retValue = pattern[self.patternIndex]

            if retValue == 0xFF:
                return random.randint(0, 0x3F)
            else:
                return retValue
        else:
            # All lasers turn
            return 0x3F

    def updateLaserPattern(self):
        if self.laserCounter < SECONDS_PER_PATTERN:
            self.laserCounterIncrement()
        else:
            self.laserState = self.getNextLaserPatternList()
            self.patternIndex = 0  # So that we start at the beginning
            self.laserCounter = 0

        # Time per element of pattern
        self.laserValue = self.getLaserPattern()

        # Set laser pattern
        setVar = 0
        while setVar < NUMBER_OF_LASERS:
            self.lasers.state[setVar] = self.laserValue & (1 << setVar)
            setVar += 1
        self.lasers.update()

    def _loop(self):
        command_id = None
        if not self.comQueue.empty():
            command = self.comQueue.get()
            command_id = command[0]

        # State Actions
        if self.state is STATE.WAIT:
            self.laserState = LaserPattern.LASER_OFF
        elif self.state is STATE.RUNNING:
            self.updateLaserPattern()
        elif self.state is STATE.EXPLODE:
            pass
            # TODO randomize laser pattern so that they flash
        elif self.state is STATE.WIN:
            pass
        else:
            log.error("Reached an unknown state: {}".format(self.state))

        # State Transitions
        if self.state is STATE.WAIT:
            if command_id is INTERRUPT.TOGGLE_TIMER:
                # TODO? Verify that the box is reset before starting the game
                self.state = STATE.RUNNING
                self.start_game()
        elif self.state is STATE.RUNNING:
            if command_id is INTERRUPT.RESET_GAME or command_id is INTERRUPT.TOGGLE_TIMER:
                self.state = STATE.WAIT
                # FIXME? Delete last row on reset
                self.end_game(success=False)
            elif command_id is INTERRUPT.KILL_PLAYER:
                self.state = STATE.EXPLODE
                self.end_game(success=False)
            elif command_id is INTERRUPT.DEFUSED:
                self.state = STATE.WIN
                self.end_game(success=True)
        elif self.state is STATE.EXPLODE:
            if command_id is INTERRUPT.RESET_GAME or command_id is INTERRUPT.TOGGLE_TIMER:
                self.state = STATE.WAIT
        elif self.state is STATE.WIN:
            if command_id is INTERRUPT.RESET_GAME or command_id is INTERRUPT.TOGGLE_TIMER:
                self.state = STATE.WAIT

    def _send(self, device: I2C, message: str):
        """
        Send a command to a device over I2c.  Nothing external should call this, only "loop"
        :param device:
        :param message:
        :return:
        """
        assert len(message) < 32
        log.debug("Address: 0x{:02x}  Message: '{}'".format(
            device.value, message))
        try:
            self._bus.write_i2c_block_data(device.value, 0x00,
                                           [ord(c) for c in message])
        except IOError:
            pass

    @staticmethod
    def random_laser_pattern() -> int:
        # TODO make sure the laser pattern conforms to certain rules
        return random.randint(0, 0x3f)

    def start_game(self):
        """
        Add a row to the database, generate random data for all the puzzles
        """
        self.solenoid = SOLENOID_STATE.LOCKED
        self.start_time = datetime.now()
        self.keypad_code = random.randint(0, 0xfff)
        self.rgb_color = random.choice([RGBColor.RED, RGBColor.BLUE])
        self.laserState = LaserPattern.ONE_CYCLES
        row = Row(
            name=self.team,
            lasers=self.laserValue,
            code=self.keypad_code,
            success=False,
            time=MAX_TIME,
            color=self.rgb_color.value,
        )
        log.debug("Adding new row to the database:\n{}".format(row))
        self.db.add_row(row)

    def end_game(self, success: bool = False):
        log.debug("Game Over")
        self.db.last = Row(name=self.team,
                           code=self.keypad_code,
                           lasers=self.laserValue,
                           success=success,
                           time=(datetime.now() - self.start_time).seconds)
예제 #4
0
        self.current_color = color
        self.write_byte(color)

    @property
    def keypad(self) -> chr:
        # TODO device won't read data unless listening on serial too
        success, data = self.read_bytes(16)
        if success and data[0] != self.NO_DATA:
            return [chr(x) for x in data]
        else:
            return []


if __name__ == "__main__":
    from time import sleep

    device = ArduinoI2C(SMBus(1))

    # Test RGB
    for c in COLOR:
        device.RGB(c)
        sleep(1)
    device.RGB(COLOR.BLANK)

    # Test Keypad
    while True:
        sleep(1)
        rcv = device.keypad
        if rcv:
            print(rcv)
예제 #5
0
from threading import Thread
from time import sleep

from i2c import SMBus
from i2c.laser_i2c import LaserControl
from i2c.lid_kit import ArduinoI2C, COLOR
from i2c.sevenseg import SevenSeg
from mockpi.mock_box_ui import ApplicationWindow

bus = SMBus(1)

arduino = ArduinoI2C(bus)
lasers = LaserControl(bus)
seven = SevenSeg(bus)


def run_sevenseg():
    while True:
        for n in range(0xffff):
            seven.sevenseg(value=n)
            sleep(.1)


def run_rgb():
    while True:
        for c in COLOR:
            arduino.RGB(c)
            sleep(1)
        arduino.RGB(COLOR.BLANK)

예제 #6
0
        super().__init__(bus, address)
        self.receptors = [0] * self.RECEPTOR_COUNT
        self.write_reg_bytes(ReceptorRegisters.Config, self.CONFIG)

    def read_all(self) -> List[bool]:
        # TODO return a list with a boolean for each photoresistor's state
        _, data = self.read_reg_bytes(self.READ_ALL, 2 * self.RECEPTOR_COUNT)
        self.receptors = list(
            unpack(self.UNPACK_ALL,
                   array('B', data).tostring()))
        return self.receptors

    def read(self, n) -> bool:
        # TODO return True if the laser is HIGH else False
        if n >= self.RECEPTOR_COUNT:
            return None
        _, data = self.read_reg_bytes(self.CHANNEL[n], 2)
        data2 = unpack('>H', array('B', data).tostring())
        self.receptors[n] = data2[0]
        return self.receptors[n]


if __name__ == '__main__':
    master = SMBus(1)
    read = ReceptorControl(master)
    while True:
        # print('{}, {}, {}, {}, {}, {}'.format(*[read.read(n) for n in range(6)]))
        # print(read.read_all())
        print(read.read(1))
        sleep(1)
예제 #7
0
class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(ApplicationWindow, self).__init__()
        self.bus_num = Logic.bus_num
        self.bus = SMBus(self.bus_num)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Get easy access to UI elements
        self.rgb = self.ui.lid_display.layout()
        self.minutes = self.ui.lcdMinutes
        self.seconds = self.ui.lcdSeconds
        self.potentiometer = self.ui.dial

        # TODO Make connections to functions

        # TODO Listen on the SMBus for messages and then call the right functions

        for h, button in self.keypad.items():
            button.clicked.connect(
                partial(lambda: self.bus.write_byte(self.bus_num, I2C.ARDUINO),
                        h))

        for _, checkbox in self.photo_resistor.items():
            checkbox.clicked.connect(
                partial(lambda: self.bus.write_byte_data(
                    self.bus_num, I2C.LASERS, self.laser_mask)))

        self.potentiometer.valueChanged.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.ROTARY,
                                             self.potentiometer.value()))

        for _, switch in self.switches.items():
            switch.valueChanged.connect(lambda: self.bus.write_byte_data(
                self.bus_num, I2C.SWITCHES, self.switch_mask))

        # Colored disconnectable wires
        self.ui.wire_red.clicked.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.WIRE, 0xd))
        self.ui.wire_blue.clicked.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.WIRE, 0xb))
        self.ui.wire_green.clicked.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.WIRE, 0xe))

        # Reset button
        self.ui.start_reset.clicked.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.RESET, 0x1))

        self.ui.ultrasonicSlider.valueChanged.connect(
            lambda: self.bus.write_byte_data(self.bus_num, I2C.ULTRASONIC,
                                             self.ui.ultrasonicSlider.value()))

        self.scheduler = APScheduler(scheduler=BackgroundScheduler())
        self.scheduler.add_job("poll",
                               self.poll_sensors,
                               max_instances=2,
                               replace_existing=False)
        # self.scheduler.start()

    def poll_sensors(self):
        for i in I2C:
            word = self.bus.read_byte_data(i, 0)
            if word is not None:
                log.info("{}: {}".format(i.name, hex(word)))
                if i is I2C.SEVENSEG:
                    pass
        self.scheduler.add_job("poll",
                               self.poll_sensors,
                               max_instances=2,
                               replace_existing=False)

    @property
    def time(self) -> str:
        """
        :return: The current time shown on the lcd
        """

    @time.setter
    def time(self, value):
        """
        TODO set the value on the timer
        :param value:
        :return:
        """

    @property
    def switches(self) -> Dict[int, QSlider]:
        return {
            4: self.ui.verticalSlider_1,
            3: self.ui.verticalSlider_2,
            2: self.ui.verticalSlider_3,
            1: self.ui.verticalSlider_4,
            0: self.ui.verticalSlider_5,
        }

    @property
    def switch_mask(self) -> bin:
        result = 0b00000
        for offset, sw in self.switches.items():
            result ^= ((1 if sw.value() else 0) << offset)
        return result

    @property
    def laser_mask(self) -> bin:
        """
        :return: An integer that represents all the photo resistors that have a laser shining on them
        """
        result = 0b000000
        for offset, box in self.photo_resistor.items():
            result ^= ((1 if box.isChecked() else 0) << offset)
        return result

    @property
    def laser(self) -> Dict[int, QCheckBox]:
        return {
            5: self.ui.laser_0,
            4: self.ui.laser_1,
            3: self.ui.laser_2,
            2: self.ui.laser_3,
            1: self.ui.laser_4,
            0: self.ui.laser_5,
        }

    @property
    def photo_resistor(self) -> Dict[int, QCheckBox]:
        return {
            5: self.ui.photodiode_0,
            4: self.ui.photodiode_1,
            3: self.ui.photodiode_2,
            2: self.ui.photodiode_3,
            1: self.ui.photodiode_4,
            0: self.ui.photodiode_5,
        }

    @property
    def led(self) -> Dict[int, QCheckBox]:
        return {
            0: self.ui.led_0,
            1: self.ui.led_1,
            2: self.ui.led_2,
            3: self.ui.led_3,
            4: self.ui.led_4,
            5: self.ui.led_5,
            6: self.ui.led_6,
            7: self.ui.led_7,
        }

    @property
    def keypad(self) -> Dict[hex, QPushButton]:
        return {
            0x0: self.ui.pushButton0,
            0x1: self.ui.pushButton1,
            0x2: self.ui.pushButton2,
            0x3: self.ui.pushButton3,
            0x4: self.ui.pushButton4,
            0x5: self.ui.pushButton5,
            0x6: self.ui.pushButton6,
            0x7: self.ui.pushButton7,
            0x8: self.ui.pushButton8,
            0x9: self.ui.pushButton9,
            0xa: self.ui.pushButtona,
            0xb: self.ui.pushButtonb,
            0xc: self.ui.pushButtonc,
            0xd: self.ui.pushButtond,
            0xe: self.ui.pushButtone,
            0xf: self.ui.pushButtonf,
        }

    @staticmethod
    def run():
        app = QtWidgets.QApplication(sys.argv)
        application = ApplicationWindow()
        application.show()
        return app.exec_()
예제 #8
0
            buffer.append((dots[i] << 7) | chars[i])
            buffer.append(0)
            if i == 1:
                buffer.append(self.COLON if colon else 0)
                buffer.append(0)

        try:
            with self._lock:
                self.bus.write_i2c_block_data(self.ADDRESS, 0, buffer)
        except OSError as c:
            logger.error("{}:{}".format(c, hex(value)))

    def brightness(self, level: int):
        level = 0 if level > 15 else level
        self.write(self.CMD_BRIGHTNESS | level)

    def blink_rate(self, rate: int = 0):
        rate = rate if rate <= 3 else 0
        self.write(self.BLINK_CMD | self.BLINK_DISPLAY_ON | (rate << 1))


if __name__ == '__main__':
    from time import sleep

    kit = SevenSeg(SMBus(1), brightness=3)

    while True:
        for n in range(0xffff):
            kit.sevenseg(value=n)
            sleep(.1)