Health Server and Health Client models.

Hello All,

I am currently developing a mesh application with several nodes. I wish to add the health server faults for monitoring the nodes in the network. As of now I am able to receive the health messages with no faults detected. Health Client was referred from the 'Provisioner Sample'. example where the callbacks printed out the detected errors.

Now I am already running a sensor server on the node and I required the faults occurring in the nodes to be sent to the client. As of now I am not able to find any samples regarding this issue.

I have referred to this documentation for the health server and this documentation for the health client, but do not understand how to actually send the faults to the client.

Could someone send any samples for the same?

Currently developing using nRF Connect SDK v2.1.2 and nRF52840 dongle for evaluation.

  • Hello Andreas,

    Is there any update regarding the topic? We are still waiting for the response.

    Regards,

    Sumedh L.

  • Hi Sumedh,

    Our apologies for the long wait. My sickness came at a bad time and coincided with Andreas' out of office period.
    I have now recovered and returned to office and will take over once more.

    A colleague helped me find some clue in the Bluetooth Mesh Shell application and we believe that the codes below serve as sample implementation.
    Could you please try to follow it and see if it works?
    Sorry I haven't been able to verify it before sharing it with you, but I don't want to keep you waiting any longer. 

    // From zephyr/subsys/bluetooth/mesh/shell.c
    
    static uint8_t cur_faults[BT_MESH_SHELL_CUR_FAULTS_MAX];
    static uint8_t reg_faults[BT_MESH_SHELL_CUR_FAULTS_MAX * 2];
    
    static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count)
    {
    	uint8_t i, limit = *count;
    
    	for (i = 0U, *count = 0U; i < faults_size && *count < limit; i++) {
    		if (faults[i]) {
    			*dst++ = faults[i];
    			(*count)++;
    		}
    	}
    }
    
    static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id,
    			 uint16_t *company_id, uint8_t *faults, uint8_t *fault_count)
    {
    	shell_print_ctx("Sending current faults");
    
    	*test_id = 0x00;
    	*company_id = BT_COMP_ID_LF;
    
    	get_faults(cur_faults, sizeof(cur_faults), faults, fault_count);
    
    	return 0;
    }
    
    static int fault_get_reg(struct bt_mesh_model *model, uint16_t cid,
    			 uint8_t *test_id, uint8_t *faults, uint8_t *fault_count)
    {
    	if (cid != CONFIG_BT_COMPANY_ID) {
    		shell_print_ctx("Faults requested for unknown Company ID"
    				" 0x%04x", cid);
    		return -EINVAL;
    	}
    
    	shell_print_ctx("Sending registered faults");
    
    	*test_id = 0x00;
    
    	get_faults(reg_faults, sizeof(reg_faults), faults, fault_count);
    
    	return 0;
    }
    
    static int fault_clear(struct bt_mesh_model *model, uint16_t cid)
    {
    	if (cid != CONFIG_BT_COMPANY_ID) {
    		return -EINVAL;
    	}
    
    	(void)memset(reg_faults, 0, sizeof(reg_faults));
    
    	return 0;
    }
    
    static int fault_test(struct bt_mesh_model *model, uint8_t test_id,
    		      uint16_t cid)
    {
    	if (cid != CONFIG_BT_COMPANY_ID) {
    		return -EINVAL;
    	}
    
    	if (test_id != 0x00) {
    		return -EINVAL;
    	}
    
    	return 0;
    }
    
    static const struct bt_mesh_health_srv_cb health_srv_cb = {
    	.fault_get_cur = fault_get_cur,
    	.fault_get_reg = fault_get_reg,
    	.fault_clear = fault_clear,
    	.fault_test = fault_test,
    };
    
    static int cmd_add_fault(const struct shell *shell, size_t argc, char *argv[])
    {
    	uint8_t fault_id;
    	uint8_t i;
    	struct bt_mesh_elem *elem;
    	int err = 0;
    
    	elem = primary_element();
    	if (elem == NULL) {
    		shell_print(shell, "Element not found!");
    		return -EINVAL;
    	}
    
    	fault_id = shell_strtoul(argv[1], 0, &err);
    	if (err) {
    		shell_warn(shell, "Unable to parse input string argument");
    		return err;
    	}
    
    	if (!fault_id) {
    		shell_print(shell, "The Fault ID must be non-zero!");
    		return -EINVAL;
    	}
    
    	for (i = 0U; i < sizeof(cur_faults); i++) {
    		if (!cur_faults[i]) {
    			cur_faults[i] = fault_id;
    			break;
    		}
    	}
    
    	if (i == sizeof(cur_faults)) {
    		shell_print(shell, "Fault array is full. Use \"del-fault\" to "
    			    "clear it");
    		return 0;
    	}
    
    	for (i = 0U; i < sizeof(reg_faults); i++) {
    		if (!reg_faults[i]) {
    			reg_faults[i] = fault_id;
    			break;
    		}
    	}
    
    	if (i == sizeof(reg_faults)) {
    		shell_print(shell, "No space to store more registered faults");
    	}
    
    	bt_mesh_fault_update(elem);
    
    	return 0;
    }

    Please let me know if there are any problems.

    Best regards,

    Hieu

  • Hello Hieu,

    I did refer to this code and it did help me set the faults as required. 

    Regards,

    Sumedh L.

Related