Hi.
I'm testing multi peripheral using pc-ble-driver-py.
I tested one peripheral device using heart_rate_collector.py.
It was ok.
But, when I try connecting two peripheral device in one central device, I got exception: Failed to ble_gap_connect. Error code: 18.
Is it impossible to connect two peripheral?
This is my code.
I just changed CONNECTIONS and device name.
# # Copyright (c) 2016 Nordic Semiconductor ASA # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # # 3. Neither the name of Nordic Semiconductor ASA nor the names of other # contributors to this software may be used to endorse or promote products # derived from this software without specific prior written permission. # # 4. This software must only be used in or with a processor manufactured by Nordic # Semiconductor ASA, or in or with a processor manufactured by a third party that # is used in combination with a processor manufactured by Nordic Semiconductor. # # 5. Any software provided in binary or object form under this license must not be # reverse engineered, decompiled, modified and/or disassembled. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # import sys import time from queue import Queue from pc_ble_driver_py.observers import * TARGET_DEV_NAME = "Nordic_HRM" CONNECTIONS = 2 CFG_TAG = 1 def init(conn_ic_id): # noinspection PyGlobalUndefined global config, BLEDriver, BLEAdvData, BLEEvtID, BLEAdapter, BLEEnableParams, BLEGapTimeoutSrc, BLEUUID, BLEConfigCommon, BLEConfig, BLEConfigConnGatt from pc_ble_driver_py import config config.__conn_ic_id__ = conn_ic_id # noinspection PyUnresolvedReferences from pc_ble_driver_py.ble_driver import ( BLEDriver, BLEAdvData, BLEEvtID, BLEEnableParams, BLEGapTimeoutSrc, BLEUUID, BLEConfigCommon, BLEConfig, BLEConfigConnGatt, ) # noinspection PyUnresolvedReferences from pc_ble_driver_py.ble_adapter import BLEAdapter global nrf_sd_ble_api_ver nrf_sd_ble_api_ver = config.sd_api_ver_get() class HRCollector(BLEDriverObserver, BLEAdapterObserver): def __init__(self, adapter): super(HRCollector, self).__init__() self.adapter = adapter self.conn_q = Queue() self.adapter.observer_register(self) self.adapter.driver.observer_register(self) self.adapter.default_mtu = 250 def open(self): self.adapter.driver.open() if config.__conn_ic_id__ == "NRF51": self.adapter.driver.ble_enable( BLEEnableParams( vs_uuid_count=1, service_changed=0, periph_conn_count=0, central_conn_count=1, central_sec_count=0, ) ) elif config.__conn_ic_id__ == "NRF52": gatt_cfg = BLEConfigConnGatt() gatt_cfg.att_mtu = self.adapter.default_mtu gatt_cfg.tag = CFG_TAG self.adapter.driver.ble_cfg_set(BLEConfig.conn_gatt, gatt_cfg) self.adapter.driver.ble_enable() def close(self): self.adapter.driver.close() def connect_and_discover(self): self.adapter.driver.ble_gap_scan_start() new_conn = self.conn_q.get(timeout=5) self.adapter.service_discovery(new_conn) self.adapter.enable_notification( new_conn, BLEUUID(BLEUUID.Standard.battery_level) ) self.adapter.enable_notification(new_conn, BLEUUID(BLEUUID.Standard.heart_rate)) return new_conn def on_gap_evt_connected( self, ble_driver, conn_handle, peer_addr, role, conn_params ): print("New connection: {}".format(conn_handle)) self.conn_q.put(conn_handle) def on_gap_evt_disconnected(self, ble_driver, conn_handle, reason): print("Disconnected: {} {}".format(conn_handle, reason)) def on_gap_evt_timeout(self, ble_driver, conn_handle, src): if src == BLEGapTimeoutSrc.scan: ble_driver.ble_gap_scan_start() def on_gap_evt_adv_report( self, ble_driver, conn_handle, peer_addr, rssi, adv_type, adv_data ): if BLEAdvData.Types.complete_local_name in adv_data.records: dev_name_list = adv_data.records[BLEAdvData.Types.complete_local_name] elif BLEAdvData.Types.short_local_name in adv_data.records: dev_name_list = adv_data.records[BLEAdvData.Types.short_local_name] else: return dev_name = "".join(chr(e) for e in dev_name_list) address_string = "".join("{0:02X}".format(b) for b in peer_addr.addr) print( "Received advertisment report, address: 0x{}, device_name: {}".format( address_string, dev_name ) ) if dev_name == TARGET_DEV_NAME or dev_name == 'HEH001 9F:0D' or dev_name == 'HEH001 EE:62': self.adapter.connect(peer_addr, tag=CFG_TAG) def on_notification(self, ble_adapter, conn_handle, uuid, data): if len(data) > 32: data = "({}...)".format(data[0:10]) print("Connection: {}, {} = {}".format(conn_handle, uuid, data)) def main(selected_serial_port): print("Serial port used: {}".format(selected_serial_port)) driver = BLEDriver( serial_port=selected_serial_port, auto_flash=False, baud_rate=1000000 ) adapter = BLEAdapter(driver) collector = HRCollector(adapter) collector.open() for i in range(CONNECTIONS): collector.connect_and_discover() time.sleep(10) print("Closing") collector.close() def item_choose(item_list): for i, it in enumerate(item_list): print("\t{} : {}".format(i, it)) print(" ") while True: try: choice = int(raw_input("Enter your choice: ")) if (choice >= 0) and (choice < len(item_list)): break except Exception: pass print("\tTry again...") return choice if __name__ == "__main__": serial_port = None if len(sys.argv) < 2: print("Please specify connectivity IC identifier (NRF51, NRF52)") exit(1) init(sys.argv[1]) if len(sys.argv) == 3: serial_port = sys.argv[2] else: descs = BLEDriver.enum_serial_ports() choices = ["{}: {}".format(d.port, d.serial_number) for d in descs] choice = item_choose(choices) serial_port = descs[choice].port main(serial_port) quit()