## @file  Multiple_Connection_Master_Role.py
## @brief This script implements a multiple connection scenario: one BlueNRG/BlueNRG-MS Master connected to up 8 BlueNRG/BlueNRG-MS Slaves devices. This script implements the Master role which configures a BlueNRG/BlueNRG-MS device as Central, Mode 3. Then it  look for BlueNRG/BlueNRG-MS Slave devices and connect to each of them. Once connected, Master device enables characteristic notification on each Slave device and it receives related characteristics notifications. 
## @li The script is implemented using the new BlueNRG GUI language scripts based on the BlueNRG/BlueNRG-MS ACI APIs. The BlueNRG GUI with script engine is delivered within BlueNRG DK 1.7.0 SW package and coming next versions.
## @li A PC running Windows Vista/7 operating systems (64 and 32 bit version) or Windows XP operating systems (32 bit edition), with available USB ports is required for installing the BlueNRG/BlueNRG-MS DK SW package.
##
## <!-- Copyright 2015 by STMicroelectronics.  All rights reserved.       *80*-->
##
##  @section S3 Multiple_Connection_Master_Role script, preliminary setup steps: configure up to 8 BlueNRG/BlueNRG-MS devices as slaves by using the Multiple_Connection_Slave_Role.py script
##
##  @li Open BlueNRG GUI available within BlueNRG DK 1.7.0 SW package (and coming next versions)
##  @li Connect a BlueNRG/BlueNRG-MS platform to a PC USB port
##  @li Put the BlueNRG/BlueNRG-MS platform in DFU mode and download the "C:\Program Files (x86)\STMicroelectronics\BlueNRG DK 1.x.0\Firmware\STM32L1_prebuilt_images\BlueNRG_VCOM_1_x.hex" using the BlueNRG GUI, Tools, Flash Motherboard FW... utility
##  @li On BlueNRG GUI, open the USB Port associated to the plugged BlueNRG/BlueNRG-MS platform
##  @li On BlueNRG GUI, select the Scripts window 
##  @li On BlueNRG GUI, Scripts window, Scripts Engine section, click on ... tab and browse to the Multiple_Connection_Slave_Role.py script location and select  it
##  @li On BlueNRG GUI, click on  Run Script tab for running the selected script
##  @li BlueNRG/BlueNRG-MS Slave device adds a service with a characteristic and it enters in discoverable mode. When connected, it continuosly notifies the added characteristic value
##
##  @li NOTE: Repeat previous steps in order to configure another BlueNRG/BlueNRG-MS device as Slave (up to 8 connections are supported from a BlueNRG/BlueNRG-MS Master device, Mode 3). 
##
##  @section S31 Multiple_Connection_Master_Role.py script execution steps through BlueNRG GUI Script Engine
##
##  @li Open BlueNRG GUI available within BlueNRG DK 1.7.0 SW package (and coming next versions)
##  @li Connect a BlueNRG/BlueNRG-MS platform to a PC USB port
##  @li Put the BlueNRG/BlueNRG-MS platform in DFU mode and download the "C:\Program Files (x86)\STMicroelectronics\BlueNRG DK 1.x.0\Firmware\STM32L1_prebuilt_images\BlueNRG_VCOM_1_x.hex" using the BlueNRG GUI, Tools, Flash Motherboard FW... utility
##  @li On BlueNRG GUI, open the USB Port associated to the plugged BlueNRG/BlueNRG-MS platform
##  @li On BlueNRG GUI, select the Scripts window 
##  @li On BlueNRG GUI, Scripts window, Scripts Engine section, click on ... tab and browse to the Multiple_Connection_Master_Role.py script location and select  it
##  @li On BlueNRG GUI, click on  Run Script tab for running the selected script
##  @li BlueNRG/BlueNRG-MS Master device will look for BlueNRG/BlueNRG-MS advertising devices. Then it will connect to each discovered BlueNRG/BlueNRG-MS Slave device and it will enable the related characteristic notification
##  @li At this stage, BlueNRG/BlueNRG-MS Master device receive the characteristic value notification from each Slave device and it displays each of them
##  @li For terminating the script (and closing the current active BLE connections), click on "Terminate Script" tab
##
##  @section S32 Supported BlueNRG/BlueNRG-MS platforms
##
##  @li BlueNRG development platform (order code: STEVAL-IDB002V1)
##  @li BlueNRG USB dongle (order code: STEVAL-IDB003V1)
##  @li BlueNRG-MS development platform (order code: STEVAL-IDB005V1) 
##  @li BlueNRG-MS Daughter Board (order code: STEVAL-IDB005V1D)
##  @li BlueNRG-MS USB dongle (order code: STEVAL-IDB006V1)
## 
##  @section S33 Supported BLE devices and stack versions
##
##  @li BlueNRG stack v6.4
##  @li BlueNRG-MS stack v7.x
##

## \addtogroup BlueNRG_and_BlueNRG_MS_scripts
## @{
## \see Multiple_Connection_Master_Role.py for documentation.
## 
## @} 

## @cond DOXYGEN_SHOULD_SKIP_THIS


HW_RESET()
SET_MODE(3)
SET_PUBLIC_ADDRESS()
ACI_HAL_SET_TX_POWER_LEVEL(En_High_Power=1,PA_Level = 4)

ACI_GATT_INIT()

status,_,_,_=  ACI_GAP_INIT(Role=CENTRAL)
if status !=0x00:
    ERROR('ACI_GAP_INIT CALL FAILED')

## Start general discovery procedure
Status =  ACI_GAP_START_GENERAL_DISCOVERY_PROC(LE_Scan_Interval=0x10,
                                      LE_Scan_Window=0x10)
if Status !=0x00:
    ERROR('ACI_GAP_START_GENERAL_DISCOVERY_PROC CALL FAILED')    

## Wait for device found event and store the devices addresses and types:
## Expected advertising device name is "test": refer to serverScript.py

listOfDeviceInADV=[]
while (True):
    
    event = WAIT_EVENT()
    if event.event_code==HCI_VENDOR_EVENT and event.get_param('Ecode').val==ACI_GAP_PROC_COMPLETE_EVENT:
        break
    elif (event.event_code==HCI_VENDOR_EVENT and event.get_param('Ecode').val==ACI_GAP_DEVICE_FOUND_EVENT and event.get_param('Event_Type').val != 0x4) :  #SCAN_RSP    :
            name=GET_NAME(event.get_param('Data').val)
            if name==None:
                continue

            #Check Device name in advertising message
            if name=='test':
                #type_address, address = GET_ADDRESS(event.get_param('Data').val)               
                type_address =event.get_param('Address_Type').val
                address =event.get_param('Address').val                
                if type_address!=None and address!=None:
                    #If the device is not already inserted, insert it in the list of device in advertising
                    if ([type_address,address] in listOfDeviceInADV)==False:
                        listOfDeviceInADV.insert(0,[type_address,address])
                        
    elif event.event_code==HCI_LE_META_EVENT and event.get_param('Subevent_Code').val==HCI_LE_ADVERTISING_REPORT_EVENT and event.get_param('Event_Type').val[0] != 0x4:  #SCAN_RSP    :
        name=GET_NAME(event.get_param('Data').val[0])
        if name==None:
            continue

        #Check Device name in advertising message
        if name=='test':               
            type_address =event.get_param('Address_Type').val[0]
            address =event.get_param('Address').val[0]              
            if type_address!=None and address!=None:
                #If the device is not already inserted, insert it in the list of device in advertising
                if ([type_address,address] in listOfDeviceInADV)==False:
                    listOfDeviceInADV.insert(0,[type_address,address])
        
conn_handle=[]
PRINT('Nun. Device in ADV= ' + str(len(listOfDeviceInADV)))

#A master can establish a connection until up 8 slaves, therefore at most 8 connections
for i in range (0,min(8,len(listOfDeviceInADV))) :
    status=ACI_GAP_CREATE_CONNECTION(LE_Scan_Interval=0x0010,
                                     LE_Scan_Window=0x0010,
                                     Peer_Address_Type=listOfDeviceInADV[i][0],
                                     Peer_Address=listOfDeviceInADV[i][1],
                                     Conn_Interval_Min=0x6c,
                                     Conn_Interval_Max=0x6c,
                                     Conn_Latency=0x00,
                                     Supervision_Timeout=0xc80,
                                     Minimum_CE_Length=0x000c,
                                     Maximum_CE_Length=0x000c)
    if Status !=0x00:
        ERROR('ACI_GAP_CREATE_CONNECTION CALL FAILED') 
    
    WAIT_EVENT(HCI_VENDOR_EVENT,Ecode=ACI_GAP_PROC_COMPLETE_EVENT )

    event = WAIT_EVENT(HCI_LE_META_EVENT,Subevent_Code=HCI_LE_CONNECTION_COMPLETE_EVENT )
    if event.get_param('Status').val==0x00:
        conn_handle.insert(0, event.get_param('Connection_Handle').val)


App_Start_Handle=[]

#For each connection, identify the handle of attribute to enable notification
for i in range (0,len(conn_handle) ) :     
    #DISCOVERY OF GAP SERVICE   IN ORDER TO UNDERSTAND THE FIRST ATTRIBUTE HANDLE AVAILABLE
    status=ACI_GATT_DISC_PRIMARY_SERVICE_BY_UUID(Connection_Handle=conn_handle[i], UUID_Type=0x01, UUID_16=0x1800)
    if (status != 0x00):
        ERROR('DISCOVERY GAP SERVICE FAILED')
                                                 
    eCode = ACI_GATT_DISC_READ_CHAR_BY_UUID_RESP_EVENT
    while (eCode != ACI_GATT_PROC_COMPLETE_EVENT):
        e = WAIT_EVENT(HCI_VENDOR_EVENT, timeout=30)
        eCode = e.get_param('Ecode').val
        if (eCode == ACI_GATT_ERROR_RESP_EVENT):
            App_Start_Handle.insert(i, e.get_param('Attribute_Handle').val) 

    
 #Enable Notification for each connection
for i in range (0,len(conn_handle) ) :   
    Status = ACI_GATT_WRITE_CHAR_DESC(Connection_Handle= conn_handle[i],Attr_Handle = App_Start_Handle[i] + 0x03,
                                              Attribute_Val_Length=0x02,Attribute_Val=0x0001 )
    if Status !=0x00:
        ERROR('ACI_GATT_WRITE_CHAR_DESC CALL FAILED') 
       
#Receive Notification
while(True):
    e = WAIT_EVENT(HCI_VENDOR_EVENT) 
    eCode = e.get_param('Ecode').val
    if (eCode == ACI_GATT_NOTIFICATION_EVENT):
        PRINT('Notification from connection: ' + str(e.get_param('Connection_Handle').val))
  

## @endcond

            
