Пример #1
0
class BlueGigaModule(BlueGigaCallbacks, ProcedureManager):
    def __init__(self, port, baud=115200, timeout=0.1):
        super(BlueGigaModule, self).__init__()
        self._api = BlueGigaAPI(port, callbacks=self, baud=baud, timeout=timeout)
        self.address = None
        self._module_info = None
        self.scan_responses = None
        self.connections = {}
        self._api.start_daemon()
        self.procedure_in_progress = False

    def pipe_logs_to_terminal(self, level=logging.INFO):
        term = logging.StreamHandler(sys.stdout)
        formatter = logging.Formatter(self._api._serial.portstr + ': %(asctime)s - %(name)s - %(levelname)s - %(message)s')
        term.setFormatter(formatter)
        api_logger = logging.getLogger("bgapi")
        api_logger.addHandler(term)
        api_logger.setLevel(level=level)

    def shutdown(self):
        self._api.stop_daemon()

    def get_module_info(self, timeout=0.5):
        start = time.time()
        if not self._module_info:
            self._api.ble_cmd_system_get_info()
        while not self._module_info and time.time() < start + timeout:
            pass
        return self._module_info

    def get_ble_address(self, timeout=0.5):
        self.start_procedure(GET_ADDRESS)
        self._api.ble_cmd_system_address_get()
        if not self.wait_for_procedure(timeout=timeout):
            raise BlueGigaModuleException("No response to get_ble_address!")
        else:
            return self.address

    def reset_ble_state(self):
        """ Disconnect, End Procedure, and Disable Advertising """
        self._api.ble_cmd_gap_set_mode(gap_discoverable_mode['gap_non_discoverable'],
                                   gap_connectable_mode['gap_non_connectable'])
        for i in range(8):
            self.disconnect(i)
        self._api.ble_cmd_gap_end_procedure()

    def disconnect(self, connection):
        self.start_procedure(DISCONNECT)
        try:
            self._api.ble_cmd_connection_disconnect(connection=connection.handle)
        except AttributeError:
            self._api.ble_cmd_connection_disconnect(connection=connection)
        self.wait_for_procedure()

    def allow_bonding(self):
        self._api.ble_cmd_sm_set_bondable_mode(1)

    def disallow_bonding(self):
        self._api.ble_cmd_sm_set_bondable_mode(0)

    def delete_bonding(self):
        self._api.ble_cmd_sm_delete_bonding(0)

    def set_device_capabilities(self, mitm=True, keysize=16, io=sm_io_capability['sm_io_capability_noinputnooutput']):
        self._api.ble_cmd_sm_set_parameters(mitm=1 if mitm else 0, min_key_size=keysize, io_capabilities=io)

    def set_out_of_band_data(self, oob):
        self._api.ble_cmd_sm_set_oob_data(oob.decode("hex"))

#------------- Response and Event Callbacks  -------------#

    def ble_rsp_system_address_get(self, address):
        super(BlueGigaModule, self).ble_rsp_system_address_get(address)
        self.address = address
        self.procedure_complete(GET_ADDRESS)

    def ble_evt_connection_status(self, connection, flags, address, address_type, conn_interval, timeout, latency, bonding):
        super(BlueGigaModule, self).ble_evt_connection_status(connection, flags, address, address_type, conn_interval, timeout, latency, bonding)
        if flags & connection_status_mask['connection_completed']:
            conn = BLEConnection(api=self._api,
                                 handle=connection,
                                 address=address,
                                 address_type=address_type,
                                 interval=conn_interval,
                                 timeout=timeout,
                                 latency=latency,
                                 bonding=bonding)
            self.connections[connection] = conn
            self.most_recent_connection = conn
            self.procedure_complete(CONNECT)
        if flags & connection_status_mask['connection_encrypted']:
            self.connections[connection].flags = flags
            self.connections[connection].procedure_complete(START_ENCRYPTION)

    def ble_rsp_system_get_info(self, major, minor, patch, build, ll_version, protocol_version, hw):
        super(BlueGigaModule, self).ble_rsp_system_get_info(major, minor, patch, build, ll_version, protocol_version, hw)
        self._module_info = {"FW Version": "%d.%d.%d.%d" % (major, minor, patch, build),
                             "Link Layer Version": "%d" % ll_version,
                             "Protocol Version": "%d" % protocol_version,
                             "Hardware Version": "%d" % hw}

    def ble_rsp_connection_disconnect(self, connection, result):
        super(BlueGigaModule, self).ble_rsp_connection_disconnect(connection, result)
        if result == 0x0186: # Not Connected
            self.procedure_complete(DISCONNECT)

    def ble_evt_connection_disconnected(self, connection, reason):
        super(BlueGigaModule, self).ble_evt_connection_disconnected(connection, reason)
        self.procedure_complete(DISCONNECT)