This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Dynamic AdvertData update

Other Parts Discussed in Thread: BLE-STACK, CC2541, CC2540

Hi,

I am using your SimpleBLEPeripheral application code to try changing dynamically the AdvertData  field sent within the Advertisement Packet.

I am using the function GAPRole_SetParameter( GAPROLE_ADVERT_DATA, ... ) and it modifies succesfully the gapRole_AdvertData var. However, the data never goes on the air and I am always receiving the initial defined advert data.

Is it possible to make this dynamic update?. am I doing something wrong?

Thanks

  • Hello Javier,

    I am seeing same thing.  Try adding a GAP_UpdateAdvertisingData() the function GAPRole_SetParameter() in peripheral.c  and it should work.

     

        case GAPROLE_ADVERT_DATA:

          if ( len <= B_MAX_ADV_LEN )

          {

            VOID osal_memset( gapRole_AdvertData, 0, B_MAX_ADV_LEN );

            VOID osal_memcpy( gapRole_AdvertData, pValue, len ) ;

            // Update the advertising data

            GAP_UpdateAdvertisingData( gapRole_TaskID,TRUE, B_MAX_ADV_LEN, gapRole_AdvertData );

    Br,

    -Greg

     

  • Thanks Greg,

    It works!!.

  • Hi Greg,

    I was just trying the same thing as Javier and as of SDK 1.2.1 neither peripheral.c nor broadcaster.c contain the changes you suggested.

    Is it possible to incorporate this change in the next release of the SDK?

    Andre

    PS: IMHO the fix should look like this:

        case GAPROLE_ADVERT_DATA:
          if ( len <= B_MAX_ADV_LEN ) {
            VOID osal_memset( gapRole_AdvertData, 0, B_MAX_ADV_LEN );
            VOID osal_memcpy( gapRole_AdvertData, pValue, len );
            gapRole_AdvertDataLen = len;
            // Update the advertising data
            GAP_UpdateAdvertisingData( gapRole_TaskID,TRUE, len, gapRole_AdvertData );
          } else {
            ret = bleInvalidRange;
          }
          break;

    PPS: this goes even further: peripheralBroadcaster.c is missing the call to GAP_UpdateAdvertisingData(), too. And the case for GAPROLE_SCAN_RSP_DATA should call call the function as well...

  • Hi Andre,

    If i update advertising data successfully, how do i get these informations from host side?

  • I guess it depends on which host you are using.

    You need to be a little more specific and I might be able to help you :)

  • Hi Andre,

    i describe my question as following:

    device : miniKeyFob(BLE-stack 1.2.1 - simpleBLEBroadCaster), smartRF05(BLE-stack 1.2.1 - simpleBLEObserver), there is no connection between two devices.

    Q1:can i add battery level into advertising data in broadcaster side?

    Q2:can i display battery level in observer side?

    thank you for your help.

  • so you are using the TI BLE-stack on both sides?

    Q1: simply add the battery level in a way that convenient to you to the advertising message by using a GAP_ADTYPE_MANUFACTURER_SPECIFIC field in your advertisemet data.

    Q2: the received ADV-packet should be available to you via the gapObserverRoleEvent_t which is provided when your pfnGapObserverRoleEventCB_t is called. I guess it can be found in the pEvtData field of the gapDeviceInfoEvent_t. I never used the observer-role myself. I always acquired the ADV-data via the HCI interface where it is provided in the data-field of the DeviceInformation event...

    hope that helps

    Ilu

  • Hi Andre,

    it works, thank you for your help.

  • Hi,

    I would also like to dynamically update advertisement data (in my case, I do this by appending two variables to manufacturer data: a uint64 followed by a uint8).

    I've performed the patch suggested in the previous post (invoking GAP_UpdateAdvertisingData in peripheral.c), but it doesn't work and moves my software to an erroneous state (GAPROLE_ERROR).

    After a little debugging, I've figured out the call to GAP_UpdateAdvertisingData returns 0x12, which seems to mean one of the following:

    #define LL_STATUS_ERROR_UNEXPECTED_PARAMETER 0x12 // Invalid HCI Command Parameters
    #define LL_STATUS_ERROR_ILLEGAL_PARAM_COMBINATION 0x12 // Invalid HCI Command Parameters
    #define LL_STATUS_ERROR_BAD_PARAMETER 0x12 // Invalid HCI Command Parameters or 0x30: Parameter Out of Mandatory Range?
    #define LL_STATUS_ERROR_UNKNOWN_ADV_EVT_TYPE 0x12 // Invalid HCI Command Parameters or 0x30: Parameter Out of Mandatory Range?

    I'm using the latest BLE Stack to date (1.2.1).

    The initial (customized) value of advertData sets up properly, and is initialized as:


    uint8 advertData[] =
    {

        // Flags; this sets the device to use limited discoverable
        // mode (advertises for 30 seconds at a time) instead of general
        // discoverable mode (advertises indefinitely)
        2, // length of this data
        GAP_ADTYPE_FLAGS,
        DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,

        // service UUID, to notify central devices what services are included
        // in this peripheral
        3, // length of this data
        GAP_ADTYPE_16BIT_MORE, // some of the UUID's, but not all
        LO_UINT16( UUID ),
        HI_UINT16( UUID ),

        11, // length of this data
        GAP_ADTYPE_MANUFACTURER_SPECIFIC, // Manufacturer specific data
        HI_UINT16( UUID ), // Manufacturer Code (registered number TBD)
        0, 0, 0, 0, 0, 0, 0, 0, // Custom uint64 value to be modified dynamically
        0xBB, // Custom UINT8 value to be modified dynamically
    };

    In order to dynamically change the value, I've added a helper function to my Custom BleProfile Task (based on SimpleBleProfile), where the value I wish to modify is written directly to advertData prior to invoking this function:

    void UpdateAdvertData(void)
    {
        GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );
    }

    And, the modified version of the code snippet inside GAPRole_SetParameter at peripheral.c looks like:

    ...

    case GAPROLE_ADVERT_DATA:
    if ( len <= B_MAX_ADV_LEN )
    {
        VOID osal_memset( gapRole_AdvertData, 0, B_MAX_ADV_LEN );
        VOID osal_memcpy( gapRole_AdvertData, pValue, len );
        gapRole_AdvertDataLen = len;
        // Patched per instructions at [http://e2e.ti.com/support/low_power_rf/f/538/t/72681.aspx]
        advstat = GAP_UpdateAdvertisingData( gapRole_TaskID, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData );
    }
    else
    {
        ret = bleInvalidRange;
    }
    break;

    Where in peripheral.c I have defined:

    static volatile bStatus_t advstat = 0;

    Any help will be appreciated!

    Thanks,

  • I have another questio related to this post. Is it possible to embed channel information to ADV packets? If three of the channels are advertising at the same time, can I embed the info of which channel is used to the packet?

  • amir,

    just a wild guess: how long is your ADV-data in total?

  • See the contents of advertData[] I've posted before (edited to reflect entire buffer):

    19 bytes total, out of which my data includes:

    • 1 byte for GAP_ADTYPE_MANUFACTURER_SPECIFIC
    • 1 byte for manufacturer ID
    • 8 bytes for uint64 field
    • 1 byte for uint8 field
  • Hi Amir,

    Have you stepped through the process during debug to make sure that all data is handled correctly?

    Best Regards

  • Yes

    After a little debugging, I've figured out the call to GAP_UpdateAdvertisingData returns 0x12.

    Can't step into GAP_UpdateAdvertisingData, since I don't have the source (even though when I activated the license it said it's installing the sources somewhere in the PC - but I can't find them).

  • Hi Amir,

    I asked in other posts also but it seems like nobody is interested. I found this thread very interesting. I want to know what do you mean by "dynamically"? I understand you want to update you adv_data, but I don't know in which cases? In my case, I want to update my adv_data, each time a new adv_packet is sent so that I could count the number of sent ADV packets. However, since the source code is not fully open, I think this cannot be done. What is your opinion?

  • In our project we'd like to update the advertisement data whenever the value of one (or more) of the fields I've defined (one uint8 and another uint64) changes.

    Specifically, the uint8 changes whenever a button is pressed or released, and the uint64 changes whenever the state of an I/O device (connected via GPIO's and ADCs) changes - this doesn't usually happen more than once every 20 seconds.

    However, I believe the specific use case shouldn't matter. The advertisement data should be easily changeable regardless of the intended use.

    It seems like the data in the use case you describes changes very frequently (once every advertisement broadcast?), and you wish to embed this counter (essentially debug data) into the advertisement data. I'm far from being an expert on this matter, but it doesn't seem like the right way to go here. I believe you can use a simple broadcast characteristic to transmit such data. 

    Good luck!

  • Amir,

    if GAP_UpdateAdvertisingData() returns 0x12 it means bleIncorrectMode (bcomdef.h), which is stated in gap.h:

      /**
       * @brief       Setup or change advertising and scan response data.
       *
       *    NOTE:  if the return status from this function is SUCCESS,
       *           the task isn't complete until the GAP_ADV_DATA_UPDATE_DONE_EVENT
       *           is sent to the calling application task.
       *
       * @param       taskID - task ID of the app requesting the change
       * @param       adType - TRUE - advertisement data, FALSE  - scan response data
       * @param       dataLen - Octet length of advertData
       * @param       pAdvertData - advertising or scan response data
       *
       * @return      SUCCESS: data accepted,<BR>
       *              bleIncorrectMode: invalid profile role,<BR>
       */
      extern bStatus_t GAP_UpdateAdvertisingData( uint8 taskID, uint8 adType,
                                          uint8 dataLen, uint8 *pAdvertData );

    it seems like you are not using either peripheral or peripheralBroadcaster role?

  • I just want to count the number of sent adv packets. On the master side I can count the number of recieved adv packets so that I can estimate the number of lost and erronous packets. The reason why I want to use ADV packets is to eleminate the WiFi interference effect. Anyway, it seems like the function which sends the ADV packets are not open and I cannot embed info to each ADV packet.

    Thanks anyway and good luck with your project!

  • I'm using the peripheral role. 

    I know this because I've based the project on the SimpleBLEPeripheral sample, only compiling peripheral.c (and not any of the other roles), and I'm not a broadcaster.

  • ok, then I'm out of ideas. it simply worked for me with the described patch...

    maybe you can provide more information, e.g.:

    • does the initial call to GAPRole_SetParameter( GAPROLE_ADVERT_DATA, ... ) succeed?
    • are the following ADV-packets the way you expect them?
    • where/how do you call GAPRole_SetParameter( GAPROLE_ADVERT_DATA, ... ) when updating?
    • when stepping though peripheral.c, were all parameters to GAP_UpdateAdvertisingData() as expected?
    • does it work if you use smaller ADV-data?
    • how do you modify the data in advertData?
  • Here is how I am successfully changing advertising data on the fly:

    • Stop advertising by using GAPRole_SetParameter() to set GAPROLE_ADVERT_ENABLED false
    • Wait for the callback from gaprole that indicates advertising has stopped (the gaprole state moves from GAPROLE_ADVERTISING to something else).
    • Change the advertising data by using GAPRole_SetParameter() to set GAPROLE_ADVERT_DATA to whatever you want.
    • Start advertising by using GAPRole_SetParameter() to set GAPROLE_ADVERT_ENABLED true

    This is in addition to adding a call to GAP_UpdateAdvertisingData() to the GAPROLE_ADVERT_DATA clause in GAPRole_SetParameter() in peripheral.c as described earlier in this thread.

    The important part that you must stop and restart advertising, and you must wait for it to actually stop before trying to restart it. Just calling GAPRole_SetParameter() to set GAPROLE_ADVERT_ENABLED false only requests the stop; it takes a few ticks to complete.

  • Sounds like a promising idea...

    I'll give it a try next week and update on the results.

    Thanks Matthew!

  • Greetings Javier,

    I am a beginner in this. But I want to do something similar. Modify dinamically the AdvertData.

    Could you tell me exactly what you do it? as an example and then I modify it from then on for my purposses.

    I mean being a bit more explicit with 

    Javier Soriano said:

    I am using the function GAPRole_SetParameter( GAPROLE_ADVERT_DATA, ... ) and it modifies succesfully the gapRole_AdvertData var. 

    thanks a lot!

  • i try to add this function call, but still can't change the advertising data.

    i using BLE-stack 1.3

  • I am able to dynamically update the advertData. But I am running into a side effect that the HAL_KEY_SW_2 (right key on the CC2541 keyfob) key is not switching the advertising on/off. I am updating the advertData with the battery level in the peripheralStateNotificationCB() function as below. I have also tried to update the advertData() in the KFD_BATTERY_CHECK_EVT but it gives the same side effect. I will appreciate any help. Thanks in advance!!

        case GAPROLE_ADVERTISING:
          {
            // Visual feedback that we are advertising.
            HalLedSet( HAL_LED_2, HAL_LED_MODE_ON );
            // Update the battery level in the AdvertData
            uint8 newBattLevel;
            Batt_GetParameter( BATT_PARAM_LEVEL, &newBattLevel );
            advertData [10] = newBattLevel;
            GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );
          }

    In peripheral.c

        case GAPROLE_ADVERT_DATA:
          if ( len <= B_MAX_ADV_LEN )
          {
            VOID osal_memset( gapRole_AdvertData, 0, B_MAX_ADV_LEN );
            VOID osal_memcpy( gapRole_AdvertData, pValue, len );
            gapRole_AdvertDataLen = len;
     
            // Update the advertising data
            GAP_UpdateAdvertisingData( gapRole_TaskID, TRUE, gapRole_AdvertDataLen, gapRole_AdvertData );
          }

  • Hey Mohmmad,

    Looks like I'm a bit late, but I think I can help! I just came across the same issue, i'm using the SimpleBLEBroadcaster sample on a CC2540 MiniDK, but I'm pretty sure the problem (and fix) is due to the same thing. 

    In the original code, it seems GAP_UpdateAdvertisingData() is only called when initializing the device (in the GAP_DEVICE_INIT_DONE_EVENT callback in broadcaster.c/peripheral.c). GAP_UpdateAdvertisingData() also has a callback event GAP_ADV_DATA_UPDATE_DONE_EVENT, which is just below that. 

    If you examine it, it:
    -  Checks that the update event was a SUCCESS
    -  Checks if we have just updated Advertising or Scan Response data
         - If it was the Advertising Data, GAP_UpdateAdvertisingData() is called again with the Scan Response data
         - This will throw the same callback, so we're in the same spot but with both data sets updated 
    - It then creates a new OSAL event to start advertising

    And that's the problem. Since we're adding GAP_UpdateAdvertisingData() to other functions (your modified GAPROLE_ADVERT_DATA case), the callback is being thrown when there's already an advertising task running. I haven't looked into detail on exactly what issues this does cause, but I found that by simply commenting out the line:

    VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );

    inside the GAP_ADV_DATA_UPDATE_DONE_EVENT callback, the advertising data (and scan response) will update live without breaking the button functionality! 

    Obviously, that line was there for a reason, likely for the configurations that don't use the CC254X keyfobs. If you're trying to dynamically update your advertising data on those platforms, you may need to throw in an additional GAPRole_SetParameter call for GAPROLE_ADVERT_ENABLED = TRUE somewhere after initialization is complete so that the advertising does actually start. 

    Hope that helps!

  • Thanks Coen, this solved my problem.

  • FYI All: with the new 1.4.0 stack, dynamically updating the advertising data is finally easy - thanks, TI!

    I used to have to jump through all of those hoops with turn off, change and wait for callback, turn back on, yada yada...

    But now, it's just the flick of a switch:

    (void)GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);

    and your done.

  • codesmith:

    I'd like to get a clarification on what I think you said:

    > FYI All: with the new 1.4.0 stack, dynamically updating the advertising
    > data is finally easy - thanks, TI!

    So if I understand you correctly, what you're saying is:

    • In the old days (i.e., 1.3.2), if we wanted to modify either the Advertising data or the Scan Response data "on the fly", we HAD to use the GAP_UpdateAdvertisingData() call to do the work. If we used GAPRole_SetParameter(), the changes would be ineffective.
       
    • But now, with the 1.4.0 stack, we can simply call GAPRole_SetParameter() and the specified changes will have effect.

    Given this, is there still any need at all for GAP_UpdateAdvertisingData()?

    Atlant

  • The compiler indicates an error when I try to add an analog to digital conversion value in the GAP_ADTYPE_MANUFACTURER_SPECIFIC field.  

    "Error [Pe028]: expression must have a constant value"

    Any ideas on an expression for an adc reading and battery level value that are updated every 5 seconds which won't cause such a compiling error?

    Thanks,

    Pat

  • Could you post the code that does this? It would be easier to see what you are trying to do.

  • Lee,

    This code worked but I'm not sure why:

    void performPeriodicTask(void)
    {
      uint8 adc = HalAdcRead ( HAL_ADC_CHANNEL_7, HAL_ADC_RESOLUTION_8 );
      
      GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( adc ), &adc );
    }

     

    This is the code that produced the compliling error:

    void performPeriodicTask(void)
    {
      uint8 adc = HalAdcRead ( HAL_ADC_CHANNEL_7, HAL_ADC_RESOLUTION_8 );
      
      GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( adc ), adc )
    }

     

    Where might I find descriptions of the GAP functions and commands?  Thanks.

  • OK, I see what you mean. That third parameter in GAPRole_SetParameter requires a pointer to the advertData array. If you search for the extern to GAPRole_SetParameter you will find a description of the function and the parameters.

  • Updating the advertising data is not possible with GAPRole_SetParameter() if you are only broadcasting. Compare how the function looks in broadcaster.c vs peripheral.c.

    In peripheral.c, the parameters GAPROLE_ADVERT_DATA and GAPROLE_SCAN_RSP_DATA calls GAP_UpdateAdvertisingData() on the spot. 

    In broadcaster.c, gapRole_ScanRspData or gapRole_AdvertData are set in anticipation of the application layer calling GAPRole_StartDevice() which through some hidden part of the binary blob calls GAP_UpdateAdvertisingData().

    TI pls

  • Hi Peter,

    Peter Borenstein said:
    Why does this inconsistency exist? TI please

    Long time ago broadcaster.c was derived from peripheral.c The improvements and additions you mention has only been made to peripheral.c. That's the simple answer. Please modify broadcaster.c based on the peripheral.c improvements.

    Best Regards

    Joakim

  • Hi.  I am using an RF05 smart board kit.  I also found that Greg's modification to Broadcaster.c permitted me to continually update the advertising data with ADC readings taken from the RF05's potentiometer at 5 second intervals.  But after the first conversion the RF05's LCD changes from indicating "Advertising" in the 3rd line to indicating "Error".  The TI Packet Sniffer also indicates that the ADC readings continue to be successfully updated and transmitted after the "Error" message appears.  But the Advertising Data packet as seen on the Packet Sniffer expands from six bytes (before the first conversion and the appearance of the error message) to 31 bytes (the additional bytes all set to zeros).  From what I can tell from the code, the system is in an unreconizable state after the first ADC conversion but continues to successfully make and transmitt ADC readings.

    How can I transmitt just 6 bytes instead of 31 bytes of advertising data with each ADC and add data update?  How do I stop the Error message from being thrown?

    Here's my code within SimpleBLEBroadcaster_ProcessEvent in SimpleBLEBroadcaster.c

    ____________________________________________

    if ( events & SBP_PERIODIC_EVT )  

    {    

    // Restart timer     if ( SBP_PERIODIC_EVT_PERIOD )    

    {      

    osal_start_timerEx( simpleBLEBroadcaster_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );    

    }

        // Perform periodic application task    

           uint8 adc = HalAdcRead ( HAL_ADC_CHANNEL_7, HAL_ADC_RESOLUTION_8 );

           uint8 advertData[] =

    {  

    // Flags; this sets the device to use limited discoverable  

    // mode (advertises for 30 seconds at a time) instead of general  

    // discoverable mode (advertises indefinitely)

     0x03,   // length of this data  

    GAP_ADTYPE_FLAGS,  

    GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,

    // two-byte broadcast of the ADC data  

    0x03,   // length of this data including the data type byte  

    GAP_ADTYPE_MANUFACTURER_SPECIFIC,  

    adc      

    };    

    GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );    

    HalLcdWriteValue ( adc, 16, HAL_LCD_LINE_1 );         return (events ^ SBP_PERIODIC_EVT);  

    }

  • From Greg's suggestion, change the line 
            GAP_UpdateAdvertisingData( gapRole_TaskID,TRUE, B_MAX_ADV_LEN, gapRole_AdvertData );

    to
            GAP_UpdateAdvertisingData( gapRole_TaskID,TRUE, len, gapRole_AdvertData );

    The 3rd argument of GAP_UpdateAdvertisingData() tells the gap the byte length of the advertising data

  • Thank you.  That modification did the trick.  Only 6 bytes being broadcast now, as desired.  But line three of the Smart RF05's  LCD still indicates "Error" instead of "Advertising" after the first A/D conversion.  Other than that things are working fine.  Please let me know if anyone has any ideas on what's going on.  Thanks again.  

  • Hi,

    I am trying to include Battery status in UUID. As of now, just able to include that but it changes the value of battery percentage on power reset only.

    Please help to provide solution for this issue. I want to reflect the updated battery percentage value in UUID

    Thanks & Regards,
    Shruti
  • Hello,

    I am using the SensorTag platform running the SensorTag example without changing any line of code and I found that during the initialization, exactly during the SensorTag_init() function, setting the parameter GAPROLE_ADVERT_DATA with the GAPRole_SetParameter() API returns an error. Exactly the GAP_UpdateAdvertisingData() function returns a bleIncorrectMode error (0x12). This happens only during initialization but I am a bit afraid because this error means a mismatch with the ble role but I did not change anything in the Stack configuration, I am just debugging with a JTAG USB probe. Can you please let me know what is the situation?
    Thank you.

    Kind Regards,

    Simone Frau
  • Did you do any modification on the application side? If yes, can you post code snippet? Or do you have trouble even running default example program?
  • No, I did not do any modification on the application side. I am using the SensorTag example without changing any line of code, I have also tried in several SensorTags but the behaviour is always the same. The first advertisement data that you try to set with the API GAPRole_SetParameter() returns an error during the initialization, but it is possible to see only debugging. From outside you are not able to see any malfunctioning, then it is possible that this is a general situation but none has seen before because you need a breakpoint there.

    Kind Regards,


    Simone Frau
  • I found a way to have a SUCCESS return value when I set the GAPROLE_ADVERT_DATA inside the SensorTag_init() function. I changed only the following lines in the SensorTag example code:


    /*******************************************************************************
    * @fn SensorTag_init
    *
    * @brief Called during initialization and contains application
    * specific initialization (ie. hardware initialization/setup,
    * table initialization, power up notification, etc), and
    * profile initialization/setup.
    *
    * @param none
    *
    * @return none
    */
    static void SensorTag_init(void)
    {
    ...

    // Setup the GAP Peripheral Role Profile
    {
    // For all hardware platforms, device starts advertising upon initialization
    uint8_t initialAdvertEnable = FALSE;

    ...

    // Set the GAP Role Parameters
    GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
    &initialAdvertEnable);

    ...

    //GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);

    ...

    // Start the Device
    GAPRole_StartDevice(&SensorTag_gapRoleCBs);

    initialAdvertEnable = TRUE;

    GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
    &initialAdvertEnable);

    GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);

    ...
    }


    Then what I am doing now is just start the device without advertising, and only after the GAPRole_StartDevice() enable the advertising and set the data. Please let me know if this procedure is correct or there are side effects that I do not know, thank you.

    Kind Regards,


    Simone Frau