This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to process received Mesh message with scheduler

Hi, team.

**********
environment :
SDK : Mesh v3.2  (w/ SDK v15.3.0)
SoC : nRF52840
IDE : SES
**********


I am challenging to handle each event, such as Mesh receive interrupt and timer interrupt with the scheduler.
I have confirmed that simple GPIO interrupts and timer interrupts can be handled using the scheduler according to the tutorial.

However, I did not know how to process the received Mesh message using the scheduler, so I asked a question...

For example, in the simple light_switch sample, multiple structures are passed to the application as arguments, as shown below.

static void app_generic_onoff_client_status_cb(const generic_onoff_client_t * p_self,
                                               const access_message_rx_meta_t * p_meta,
                                               const generic_onoff_status_params_t * p_in)
{
    // some process...
}


At this time, for example, how can I push all the structures (pointers) received as arguments to the event queue of the scheduler?

I tried declaring the original structure as shown below and trying to copy the argument pointers,
but the parameters I received  in the scheduled function were not the intended values at all.

typedef struct
{
    const generic_onoff_client_t * pp_self;
    const access_message_rx_meta_t * pp_meta;
    const generic_onoff_status_params_t * pp_in;
} my_event_packet_t;



Copy pointer as shown below.

static void app_generic_onoff_client_status_cb(const generic_onoff_client_t * p_self,
                                               const access_message_rx_meta_t * p_meta,
                                               const generic_onoff_status_params_t * p_in)
{
    my_event_packet_t * packet_datas;
    
    packet_datas->pp_self = p_self;
    packet_datas->pp_meta = p_meta;
    packet_datas->pp_in = p_in;

    app_sched_event_put(&packet_datas, sizeof(* packet_datas), scheduled_status_cb);
}



Scheduled function.

static void scheduled_status_cb(void * p_event, uint16_t event_size)
{
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "%s called.\n", __func__);

    my_event_packet_t * check_struct = (my_event_packet_t *) p_event;

    /*
        Various processing such as log output
    */
}



Perhaps it is related to the fact that the structure being communicated is  a pointer, but no good approach could found so far.

Can you tell me if there is any good approach?
Also, if you have any points to be careful about using the scheduler to perform processing related to Bluetooth (Mesh) communication, please also provide a guide.


I hope you will be able to provide the information.

Best regards,
Wataru

Parents
  • Hello,

    You might have been trying to give me some guide, but I seem to have solved it myself.
    However, since I am not confident about whether this method is safe, I would be grateful if you could comment.


    I modified the structure to extract only the data needed for the application:

    typedef struct
    {
        uint16_t src_addr;
        uint16_t dst_addr;
        int8_t rssi;
        generic_onoff_status_params_t pp_in;
    } my_event_packet_t;
    



    In the callback function called in the interrupt handler mode, only necessary information is copied and pushed to the event queue as follows.

    static void app_generic_onoff_client_status_cb(const generic_onoff_client_t * p_self,
                                                   const access_message_rx_meta_t * p_meta,
                                                   const generic_onoff_status_params_t * p_in)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "%s called.\n", __func__);
    
        my_event_packet_t packet_datas = {0};
    
        packet_datas.src_addr = p_meta->src.value;
        packet_datas.dst_addr = p_meta->dst.value;
        packet_datas.rssi = p_meta->p_core_metadata->params.scanner.rssi;
        memcpy(&packet_datas.pp_in, p_in, sizeof(generic_onoff_status_params_t));
    
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "src : %X, rssi : %d, dst : %X.\n",
              p_meta->src.value, p_meta->p_core_metadata->params.scanner.rssi, p_meta->dst.value);
    
        app_sched_event_put((void *)&packet_datas, sizeof(packet_datas), scheduled_status_cb);
    }
    



    The function executed by the scheduler gets the data as follows:

    static void scheduled_status_cb(void * p_event, uint16_t event_size)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "%s called.\n", __func__);
    
        my_event_packet_t * check_struct = (my_event_packet_t *) p_event;
        
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "src : %X, RSSI : %d, dst : %X, onoff : %d.\n",
              check_struct->src_addr,
              check_struct->rssi,
              check_struct->dst_addr,
              check_struct->pp_in.present_on_off);
        
        /*
            some process...
        */
    }
    



    Paste the run time log below.

    <t:     478980>, main.c,  250, app_generic_onoff_client_status_cb called.
    <t:     478983>, main.c,  288, src : 18, rssi : -29, dst : C005.
    <t:     478991>, main.c,  196, scheduled_status_cb called.
    <t:     478993>, main.c,  227, src : 18, RSSI : -29, dst : C005, onoff : 1.
    



    In this way, it seems that I could handled the same data between the callback function when receiving a message and the function executed by the scheduler.

    Can you find any fatal drawbacks to the above methods?
    If you feel that there are no shortcomings, my next goal is to send a message from a function that is executed from the scheduler.

    If I call the send function, mesh assert will occur. . .
    Can you tell me how to send a message with a function executed from the scheduler?


    I hope you will be able to provide the information.

    Best regards,
    Wataru

  • Hi.

    Thanks for sharing you solution. 

    At first look, I couldn't find anything to put my finger on in the code. But I will take a closer look to make sure. 

    wataru_m said:
    If I call the send function, mesh assert will occur.

     Do you have any more specific information about the assert? Where the assert is originating from? Error codes etc?

    Br, 
    Joakim

  • Hi, Joakim

    Thank you for your reply.
    I will continue this question assuming that there was no fatal problem with the way I handled the data received in Mesh messages.


    I'm sorry for the lack of information about asserts.
    Now I will supplement.

    As a premise, core.irq_priority of init_params is set to NRF_MESH_IRQ_PRIORITY_LOWEST in mesh_init function.

    I tried to send a message to the Server as shown below in the function that processes the message received from the Server using the method shown in this thread.

    static void scheduled_status_cb(void * p_event, uint16_t event_size)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "src : %X, RSSI : %d, dst : %X, onoff : %d.\n",
              check_struct->src_addr,
              check_struct->rssi,
              check_struct->dst_addr,
              check_struct->pp_in.present_on_off);
    
        // Send message to Server after LOG output
        // packet send test <--
        uint32_t status = NRF_SUCCESS;
        generic_onoff_set_params_t set_params;
        model_transition_t transition_params;
        static uint8_t tid = 0;
    
        set_params.on_off = APP_STATE_ON;
        set_params.on_off = APP_STATE_OFF;
        set_params.tid = tid++;
    
        transition_params.delay_ms = APP_CONFIG_ONOFF_DELAY_MS;
        transition_params.transition_time_ms = APP_CONFIG_ONOFF_TRANSITION_TIME_MS;
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Sending msg: ONOFF SET %d\n", set_params.on_off);
    
        /* Demonstrate acknowledged transaction, using 1st client model instance */
        /* In this examples, users will not be blocked if the model is busy */
        (void)access_model_reliable_cancel(m_clients[0].model_handle);
        status = generic_onoff_client_set(&m_clients[0], &set_params, &transition_params);
        hal_led_pin_set(BSP_LED_0, set_params.on_off);
    
        switch (status)
        {
            case NRF_SUCCESS:
                break;
    
            case NRF_ERROR_NO_MEM:
            case NRF_ERROR_BUSY:
            case NRF_ERROR_INVALID_STATE:
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Client %u cannot send\n", set_params.on_off);
                hal_led_blink_ms(LEDS_MASK, LED_BLINK_SHORT_INTERVAL_MS, LED_BLINK_CNT_NO_REPLY);
                break;
    
            case NRF_ERROR_INVALID_PARAM:
                /* Publication not enabled for this client. One (or more) of the following is wrong:
                 * - An application key is missing, or there is no application key bound to the model
                 * - The client does not have its publication state set
                 *
                 * It is the provisioner that adds an application key, binds it to the model and sets
                 * the model's publication state.
                 */
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Publication not configured for client %u\n", set_params.on_off);
                break;
    
            default:
                ERROR_CHECK(status);
                break;
        }
        // packet send test -->
    }



    Paste the LOG after receiving the message from Server.

    <t:          0>, main.c,  505, ----- BLE Mesh Light Switch Client Demo -----
    <t:      12630>, main.c,  473, Initializing and adding models
    <t:      12668>, mesh_app_utils.c,   65, Device UUID (raw): 895C84CA03636D46B2C2043C2899D709
    <t:      12671>, mesh_app_utils.c,   70, Device UUID : CA845C89-6303-466D-B2C2-043C2899D709
    <t:      86589>, main.c,  311, app_generic_onoff_client_status_cb called.
    <t:      86592>, main.c,  349, src : 22, rssi : -24, dst : C005.
    <t:      86599>, main.c,  196, scheduled_status_cb called.
    <t:      86602>, main.c,  227, src : 22, RSSI : -24, dst : C005, onoff : 1.
    <t:      86605>, main.c,  244, Sending msg: ONOFF SET 0
    <t:      86615>, app_error_weak.c,  108, Mesh assert at 0x0002AC62 (:0)
    


    Breaking the debug and confirmed asserted part.
    It caused by "NRF_MESH_ASSERT_DEBUG (bearer_event_in_correct_irq_priority ());" on line 214 of timer_scheduler.c. .


    So, I changed the core_irq_priority of init_params from NRF_MESH_IRQ_PRIORITY_LOWEST to NRF_MESH_IRQ_PRIORITY_THREAD in the mesh_init function of main.c.
    Then I can no longer receive messages from Server.
    Perhaps it is receiving as a device, but it does not seem to reach the application layer.


    Can you tell me an approach to solve this problem?

    Best regards,
    Wataru

  • ### Update ###

    It seems that the cause was not calling nrf_mesh_process () function.

    I couldn't spend much time analyzing this problem, so I hoped that the support team could solve it if possible...
    But fortunately I was able to solve the problem.


    If I get stuck in future developments, please let me consult again.

    Best regards,
    Wataru

  • Thanks for sharing the solution.

    You are very welcome to open a new ticket if you have any questions in the future.

    Best regards,
    Joakim

Reply Children
No Data
Related