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

multiple clients to server message on Mesh

 in the code below. implemented on a mesh form multiple Clients (Publication addresses)  to the  server (subscriped) to all the clients.

The code reads beacon data, removes the Minor ID, combine it with the Client UUID . This needs to be sent to the server.

I would like to know 

1.  how to use the function :  access_model_reliable_publish(); to transmit the array Result[24]  from the code below 

2. Max clients that can send data to 1 server on a mesh.


/* Models */
#include "generic_onoff_client.h"

/* Logging and RTT */
#include "log.h"
#include "rtt_input.h"

/* Example specific includes */
#include "app_config.h"
#include "nrf_mesh_config_examples.h"
#include "light_switch_example_common.h"
#include "example_common.h"
#include "ble_softdevice_support.h"
#include "nrf_delay.h"
#include "string.h"
#define APP_STATE_OFF                (0)
#define APP_STATE_ON                 (1)

#define APP_UNACK_MSG_REPEAT_COUNT   (2)

static generic_onoff_client_t m_clients[CLIENT_MODEL_INSTANCE_COUNT];
static bool                   m_device_provisioned;
char scanner_UUID[17]; // scanner 2 bytes + 1



//for below also investigate ? nrf_mesh_rx_cb_t This callback can be used to receive raw advertisement packets
static void rx_cb(const nrf_mesh_adv_packet_rx_data_t * p_rx_data) // used for listening for incoming packets  with function nrf_mesh_rx_cb_set(rx_cb);
{
    LEDS_OFF(BSP_LED_0_MASK);  /* @c LED_RGB_RED_MASK on pca10031 */
    char msg[64];
    char beacon_Minor_ID[5]; // the length of the eMbeacon unique ID
    char Result[24]; // 5+16+1 for nul term
    char beacon_uuid[37]; // the length of EM microelectronics packet**** check this it may be shorter
 

// copy the UUID of the beacon
    memcpy(beacon_uuid,p_rx_data->p_payload, p_rx_data->length); // copy the UUID of the beacon
 // check if it is a EMbeacon Beacon make in bit 2:9
       if ((beacon_uuid[2]==0x45)|(beacon_uuid[3]==0x4D)|(beacon_uuid[4]==0x42)|(beacon_uuid[5]==0x65)
          |(beacon_uuid[6]==0x61)|(beacon_uuid[7]==0x63)|(beacon_uuid[8]==0x6f)|(beacon_uuid[9]==0x6e)) // EMBeacon name check
// if it is a beacon send PCA10059 (scanner) UUID and Beacon UUID to the client on the mesh
    {     
      memcpy (beacon_Minor_ID,beacon_uuid + 10,5); // move the 5 unique beacon ID bytes for use in mesh to identify the beacon
      memcpy(Result, (void*) &scanner_UUID[0], 16);       // combine Beacon Minor UUID and Scanner complete UUID 
      memcpy(&Result[16], (void*) &beacon_Minor_ID[0], 8); // Advertisement address 
 
 // Transmit Result on the mesh  to the gateway server.


access_model_reliable_publish();

Thanks in advance

Parents
  • Hello,

    You must have a model that can transfer your packet. "Model" = Bluetooth mesh "service". 

    The light switch example uses an on_off_model. This can only transfer a single byte, and it actually only holds a bool, so you need to modify this model to contain a string. See how the publish function is used in the light switch example, and see if you can modify/create a model that holds this array instead of just an on_off state.

    Depending on the number of nodes in your mesh network, using access_model_reliable_publish may not be a good idea. This requires the node that subscribes to the messages to send an ACK, doubling the amount of messages travelling around in your network. If you don't have too many nodes subscribing, this will probably be ok, but if it was a lighting system, and all the lightbulbs in a warehouse were to ACK all messages, the mesh will be flooded with messages.  That being said, there is no maximum number of nodes that can publish on a channel which the server subscribes to. Only the maximum number of nodes in a network will be the theoretical limit for this, which  is around 32 000 nodes.

    Best regards,

    Edvin

  • Thanks Edvin

    Will the simple_message_client work

    for me here? Mesh V3.00

    If so where do I declare m_central_handel -  im getting a compile error.

    //simple send message example
    void address_set(uint16_t addr)                 //function for setting address
    {
      uint32_t err_code;
      err_code = dsm_address_publish_add(addr, &m_central_handle); //NRF_ERROR_NO_MEM
      ERROR_CHECK(err_code);
      ERROR_CHECK(access_model_publish_address_set(m_clients[0].model_handle, m_central_handle));
    }
    
    
    void send_message(void)                         //function for sending a simple message
    {
        uint32_t status=0;
        uint8_t buffer[5] = "hello";
        uint8_t length;
        uint16_t address;
        access_message_tx_t msg; // declare variable access.h
        length = sizeof(buffer); //SEGGER_RTT_Read(0, buffer, sizeof(buffer));
        
        if(length)
        {
          //no-need:SEGGER_RTT_WriteString(0, "entering message field\n");
          msg.opcode.opcode = simple_message_OPCODE_SEND;
          msg.opcode.company_id = 0x0059; // Nordic's company ID
    
          msg.p_buffer = (const uint8_t *) &buffer[0];
          msg.length = length;
          address = 0xCAFE;
          address_set(address);
          printf(0,"Sending to group address 0x%04x\n", address);
        status= access_model_publish(m_clients[3].model_handle, &msg);
      
          if(status == NRF_ERROR_INVALID_STATE ||
          status == NRF_ERROR_BUSY||
          status == NRF_ERROR_NO_MEM)
          {
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Cannot send. Device is busy.\n");
            hal_led_blink_ms(LEDS_MASK, 50, 4);
          }
          else
          {
             ERROR_CHECK(status);
          }
        }
    }
    

  • Hello,

    Try to disable optimization on your project (set it to -O0), and then set a break point on line 115 in app_error_weak.c. When it stops there check the variables:

    p_info->err_code. // it looks like this is 7
    pc, 
    p_info->p_file_name, //this should contain the file name of the file that received an ERROR_CHECK(err_code) where err_code != 0.
    p_info->line_num // This should point to what line number in that file the ERROR_CHECK is located.

    Now, when you find this, try to look at what function that returned the return value passed into ERROR_CHECK, and what it means when this function returns 7.

    Best regards,

    Edvin

  • It seems to be inside my send message function. in access_model_publish

    status= access_model_publish(m_clients[0].model_handle, &msg);

  • Ok. so access_model_publish can return NRF_ERROR_INVALID_PARAM which you can see in access.h.

    If you look at access_model_publish in access.c, you see that it can either return NRF_ERROR_NULL, or it returns the return value of packet_tx().

    Maybe your check_tx_params returns NRF_ERROR_INVALIT_PARAM. Try to debug in this function to figure out where/what function call that returns this value.

    Best regards,

    Edvin

  • It seems to give Mesh error 7 when the  client does not have app bind key and a broadcast address set up. Once these are set up, the mesh error 7 is gone. But it now returns, Cannot send. Device is Busy

    I just need to add here, up to this point I have only been working on the client, The server has not been set up for simple_message yet and is running standard on_off_model. do don't know if it may have something to do with that. I will now switch over to the server side.

  • If you are sending acknowledged messages, then it will matter, because it can only queue so many packets. I suggest you start with the server side, so that you have something that is actually acknowledging the messages. Start to set it up so that you can send one simple message between the two, and take it from there.

    BR,

    Edvin

Reply Children
  • HI Edvin thanks for the help so far.  I think my message is being sent correctly. I slowed it down by triggering it manually.

    On the server side Im facing the same problems as Narin here https://devzone.nordicsemi.com/f/nordic-q-a/31256/receiving-simple-message-mesh/123576

    As per Bjorn I have included the simple_message into main.c (Mesh v3) and changed access_model_publish() function, use this statement instead:  status= access_model_publish(m_server.model_handle, &msg);

    However

    1. m_server is undeclared. - 

    2. Where do I extract the message in mesh v3, in the access.c or in simple_message_server.c

    static void rx_get_cb(access_model_handle_t handle, const access_message_rx_t * p_message, void * p_args)
    {
    simple_message_server_t * p_server = p_args;
    NRF_MESH_ASSERT(p_server->get_cb != NULL);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Get--");
    reply_status(p_server, p_message);
    }

    Once again thank you fpr the help and insight into converting mesh v1 simple_message to mesh v3 simple_message it is highly appreciated.

  • Hi Edvin

    I have decided to discard this simple_message model from mesh v1. Its to old and I will now focus my research on the simple_on_off vendor model on mesh v3.1.

    I will start another thread.

Related