예제 #1
0
    def _set_mv_led(self, pos, freq):
        """
        Set the leds on board according to pos array, used by `show_deltas`.
        """
        if self.connected is True:
            leds = [[0 for x in range(9)] for y in range(9)]
            cmd = "L" + clp.hex2(freq)
            for y in range(8):
                for x in range(8):
                    if pos[y][x] != 0:
                        if self.orientation == True:
                            leds[7 - x][y] |= pos[y][x]
                            leds[7 - x + 1][y] |= pos[y][x]
                            leds[7 - x][y + 1] |= pos[y][x]
                            leds[7 - x + 1][y + 1] |= pos[y][x]
                        else:
                            leds[x][7 - y] |= pos[y][x]
                            leds[x + 1][7 - y] |= pos[y][x]
                            leds[x][7 - y + 1] |= pos[y][x]
                            leds[x + 1][7 - y + 1] |= pos[y][x]

            for y in range(9):
                for x in range(9):
                    cmd = cmd + clp.hex2(leds[y][x])
            self.trans.write_mt(cmd)
        else:
            self.log.warning("Not connected to Chess Link.")
예제 #2
0
    def set_scan_time_ms(self, scan_ms=41):
        """
        Set the scan time value. Lower scan times make the board less susceptible to random unexpected
        events and can be used together with `set_debounce()` to prevent random fluke events.

        :param scan_ms: 30.72(fastest)-522.24(slowest), scan time in ms. A value around 100ms is 
                        recommended, board default is 41ms.
        """
        if self.connected is True:
            cmd = "W01"
            if scan_ms < 2.048 * 15.0 or scan_ms > 255.0 * 2.048:
                self.log.error(
                    'Invalid scan_ms {}, shouldbe between 30.72(fastest, might not work)..522.24(slowest, about 2 scans per sec))'
                    .format(scan_ms))
            else:
                iscans = int(scan_ms / 2.048)
                if iscans < 15:
                    iscans = 15
                if iscans > 255:
                    iscans = 255
                cmd += clp.hex2(iscans)
                self.trans.write_mt(cmd)
                self.log.debug(
                    "Setting scan_ms intervall to {} -> {}ms ({} scans per sec)"
                    .format(iscans, scan_ms, 1000.0 / scan_ms))
        else:
            self.log.warning("Not connected to Chess Link.")
예제 #3
0
    def get_led_brightness_percent(self):
        """
        Asynchronuosly request the current led brightness setting. The answer will be
        written to the queue `appqueue` given during initialization.

        See see `magic-link.md <https://github.com/domschl/python-mchess/blob/master/mchess/magic-board.md>`_.
        """
        if self.connected is True:
            cmd = "R" + clp.hex2(4)
            self.trans.write_mt(cmd)
        else:
            self.log.warning("Not connected to Chess Link.")
예제 #4
0
    def set_led(self, pos, freq, ontime1, ontime2):
        """
        Static blinking leds according to `position`.

        :param pos: `position` array, field != 0 indicates a led that should blink.
        :param freq: blink frequency, see `magic-link.md <https://github.com/domschl/python-mchess/blob/master/mchess/magic-board.md>`_.
        :param ontime1: 8-bit value, bits indicate cycles led is on.
        :param ontime2: 8-bit value, bits indicate cycles led is off.
        """
        if self.connected is True:
            leds = [[0 for x in range(9)] for y in range(9)]
            cmd = "L"+clp.hex2(freq)
            for y in range(8):
                for x in range(8):
                    if pos[y][x] != 0:
                        if self.orientation == True:
                            leds[7-x][y] = pos[y][x]
                            leds[7-x+1][y] = pos[y][x]
                            leds[7-x][y+1] = pos[y][x]
                            leds[7-x+1][y+1] = pos[y][x]
                        else:
                            leds[x][7-y] = pos[y][x]
                            leds[x+1][7-y] = pos[y][x]
                            leds[x][7-y+1] = pos[y][x]
                            leds[x+1][7-y+1] = pos[y][x]

            for y in range(9):
                for x in range(9):
                    if leds[y][x] == 0:
                        cmd = cmd + "00"
                    elif leds[y][x] == 1:
                        cmd = cmd + clp.hex2(ontime1)
                    else:
                        cmd = cmd + clp.hex2(ontime2)

            self.trans.write_mt(cmd)
        else:
            self.log.warning(
                "Not connected to Chess Link.")
예제 #5
0
    def set_led_brightness(self, level=1.0):
        """
        Set the led brighness.

        :param level: 0.0 - 1.0: 0(darkest) up to 1.0(brightest).
        """
        if self.connected is True:
            cmd = "W04"
            if level < 0.0 or level > 1.0:
                self.log.error(f'Invalid brightness level {level}, "\
                               "should be between 0(darkest)..1.0(brightest)')
            else:
                ilevel = int(level * 15)
                cmd += clp.hex2(ilevel)
                self.trans.write_mt(cmd)
                self.log.debug(
                    f"Setting led brightness to {ilevel} (bri={level})")
        else:
            self.log.warning("Not connected to Chess Link.")
예제 #6
0
    def set_debounce(self, count):
        """
        Set the debounce-value. Debouncing helps to prevent random fluke events. Should be tested
        together with different `set_scan_time_ms()` values.

        :param count: 0-4, 0: no debounce, 1-4: 1-4 scan times debounce.
        """
        if self.connected is True:
            cmd = "W02"
            if count < 0 or count > 4:
                self.log.error(f'Invalid debounce count {count}, "\
                               "should be 0: no debounce, 1 .. 4: 1-4  scan times debounce'
                               )
            else:
                # 3: no debounce, 4: 2 scans debounce, -> 7: 4 scans
                cmd += clp.hex2(count + 3)
                self.trans.write_mt(cmd)
                self.log.debug(f"Setting board scan debounce to {count}")
        else:
            self.log.warning("Not connected to Chess Link.")
예제 #7
0
    def worker_thread(self, log, address, wrque, que):
        """
        Background thread that handles bluetooth sending and forwards data received via 
        bluetooth to the queue `que`.
        """
        mil = None
        message_delta_time = 0.1  # least 0.1 sec between outgoing btle messages

        rx = None
        tx = None
        log.debug("bluepy_ble open_mt {}".format(address))
        # time.sleep(0.1)
        try:
            log.debug("per1")
            mil = Peripheral(address)
            log.debug("per2")
        except Exception as e:
            log.debug("per3")
            emsg = 'Failed to create BLE peripheral at {}, {}'.format(
                address, e)
            log.error(emsg)
            self.agent_state(que, 'offline', '{}'.format(e))
            self.conn_state = False
            return

        rx, tx = self.mil_open(address, mil, que, log)

        time_last_out = time.time()+0.2

        if rx is None or tx is None:
            bt_error = True
            self.conn_state = False
        else:
            bt_error = False
            self.conn_state = True
        while self.worker_thread_active is True:
            rep_err = False
            while bt_error is True:
                time.sleep(1)
                bt_error = False
                self.init = False
                try:
                    mil.connect(address)
                except Exception as e:
                    if rep_err is False:
                        self.log.warning(
                            "Reconnect failed: {} [Local bluetooth problem?]".format(e))
                        rep_err = True
                    bt_error = True
                if bt_error is False:
                    self.log.info(
                        "Bluetooth reconnected to {}".format(address))
                    rx, tx = self.mil_open(address, mil, que, log)
                    time_last_out = time.time()+0.2
                    self.init = True

            if wrque.empty() is False and time.time()-time_last_out > message_delta_time:
                msg = wrque.get()
                gpar = 0
                for b in msg:
                    gpar = gpar ^ ord(b)
                msg = msg+clp.hex2(gpar)
                if self.protocol_debug is True:
                    log.debug("blue_ble write: <{}>".format(msg))
                bts = ""
                for c in msg:
                    bo = chr(clp.add_odd_par(c))
                    bts += bo
                    btsx = bts.encode('latin1')
                if self.protocol_debug is True:
                    log.debug("Sending: <{}>".format(btsx))
                try:
                    tx.write(btsx, withResponse=True)
                    time_last_out = time.time()
                except Exception as e:
                    log.error(
                        "bluepy_ble: failed to write {}: {}".format(msg, e))
                    bt_error = True
                    self.agent_state(
                        que, 'offline', 'Connected to Bluetooth peripheral lost: {}'.format(e))
                wrque.task_done()

            try:
                rx.read()
                mil.waitForNotifications(0.05)
                # time.sleep(0.1)
            except Exception as e:
                self.log.warning("Bluetooth error {}".format(e))
                bt_error = True
                self.agent_state(
                    que, 'offline', 'Connected to Bluetooth peripheral lost: {}'.format(e))
                continue

        log.debug('wt-end')