Implement health server callbacks.

This commit is contained in:
h2zero 2020-10-25 08:29:54 -06:00
parent 56c68d7eea
commit afb76b8cb6
6 changed files with 159 additions and 14 deletions

View file

@ -13,13 +13,18 @@ static const char* LOG_TAG = "NimBLEMeshElement";
NimBLEMeshElement::NimBLEMeshElement() {
m_pElem_t = nullptr;
m_pHealthModel = nullptr;
}
NimBLEMeshElement::~NimBLEMeshElement() {
if(m_pElem_t != nullptr) {
delete m_pElem_t;
}
if(m_pHealthModel != nullptr) {
delete m_pHealthModel;
}
for(auto &it : m_modelsVec) {
if(it.id != BT_MESH_MODEL_ID_HEALTH_SRV) {
@ -30,6 +35,7 @@ NimBLEMeshElement::~NimBLEMeshElement() {
m_modelsVec.clear();
}
/**
* @brief Creates a model and adds it the the elements model vector.
* @param [in] type The type of model to create.
@ -58,7 +64,7 @@ NimBLEMeshModel* NimBLEMeshElement::createModel(uint16_t type, NimBLEMeshModelCa
case BT_MESH_MODEL_ID_HEALTH_SRV:
m_pHealthModel = new NimBLEHealthSrvModel(pCallbacks);
pModel = m_pHealthModel;
m_modelsVec.push_back(bt_mesh_model{{BT_MESH_MODEL_ID_HEALTH_SRV},0,0,0,&pModel->m_opPub,{0},{0},bt_mesh_health_srv_op,pModel->getHealth_t()});
m_modelsVec.push_back(bt_mesh_model{{type},0,0,0,&pModel->m_opPub,{0},{0},bt_mesh_health_srv_op,&m_pHealthModel->m_healthSrv});
return pModel;
default:
@ -70,6 +76,7 @@ NimBLEMeshModel* NimBLEMeshElement::createModel(uint16_t type, NimBLEMeshModelCa
return pModel;
}
/**
* @brief Adds a model created outside of element context to the elements model vector.
* @param [in] model A pointer to the model instance to add.
@ -79,6 +86,11 @@ void NimBLEMeshElement::addModel(bt_mesh_model* model) {
}
/**
* @brief Get a pointer to the model in the element with the type specified.
* @param [in] The model type requested.
* @returns A pointer to the model or nullptr if not found.
*/
NimBLEMeshModel* NimBLEMeshElement::getModel(uint16_t type) {
if(type == BT_MESH_MODEL_ID_HEALTH_SRV) {
return m_pHealthModel;
@ -94,6 +106,28 @@ NimBLEMeshModel* NimBLEMeshElement::getModel(uint16_t type) {
}
/**
* @brief Get a pointer to a model with matching type and ID.
* @param [in] eidx The element ID to compare.
* @param [in] midx The model ID to compare.
* @param [in] The model type requested.
* @returns A pointer to the model or nullptr if not found.
*/
NimBLEMeshModel* NimBLEMeshElement::getModelByIdx(uint8_t eidx, uint8_t midx, uint16_t type) {
for(auto &it : m_modelsVec) {
if(it.elem_idx == eidx && it.mod_idx == midx) {
if(type == BT_MESH_MODEL_ID_HEALTH_SRV) {
return m_pHealthModel;
} else {
return (NimBLEMeshModel*)it.user_data;
}
}
}
return nullptr;
}
/**
* @brief Creates a bt_mesh_elem for registering with the nimble stack.
* @returns A pointer to the bt_mesh_elem created.

View file

@ -26,6 +26,7 @@ class NimBLEMeshElement {
public:
NimBLEMeshModel* createModel(uint16_t type, NimBLEMeshModelCallbacks* pCallbacks=nullptr);
NimBLEMeshModel* getModel(uint16_t type);
NimBLEMeshModel* getModelByIdx(uint8_t eidx, uint8_t midx, uint16_t type);
private:
friend class NimBLEMeshNode;

View file

@ -12,6 +12,11 @@
#include "nimble/nimble_port.h"
#include "NimBLEDevice.h"
#define CID_VENDOR 0x05C3
#define STANDARD_TEST_ID 0x00
static const char* LOG_TAG = "NimBLEMeshModel";
static NimBLEMeshModelCallbacks defaultCallbacks;
@ -133,10 +138,6 @@ uint16_t NimBLEMeshModel::getDelayTime() {
}
bt_mesh_health_srv* NimBLEMeshModel::getHealth_t() {
return nullptr;
}
/**
* @brief Generic on/off server model constructor
* @param [in] pCallbacks, a pointer to a callback instance for model operations
@ -245,6 +246,7 @@ void NimBLEGenOnOffSrvModel::setOnOffUnack(bt_mesh_model *model,
}
}
void NimBLEGenOnOffSrvModel::tdTimerCb(ble_npl_event *event) {
NimBLEMeshModel *pModel = (NimBLEMeshModel*)event->arg;
if(pModel->m_delayTime > 0) {
@ -286,6 +288,7 @@ void NimBLEGenOnOffSrvModel::setPubMsg() {
}
}
void NimBLEGenOnOffSrvModel::setValue(uint8_t *val, size_t len) {
if(len != sizeof(uint8_t)) {
NIMBLE_LOGE(LOG_TAG, "NimBLEGenOnOffSrvModel: Incorrect value length");
@ -294,6 +297,7 @@ void NimBLEGenOnOffSrvModel::setValue(uint8_t *val, size_t len) {
m_value[0] = *val;
}
void NimBLEGenOnOffSrvModel::setTargetValue(uint8_t *val, size_t len) {
if(len != sizeof(uint8_t)) {
NIMBLE_LOGE(LOG_TAG, "NimBLEGenOnOffSrvModel: Incorrect target value length");
@ -302,6 +306,7 @@ void NimBLEGenOnOffSrvModel::setTargetValue(uint8_t *val, size_t len) {
m_targetValue[0] = *val;
}
/**
* @brief Generic level server model constructor
* @param [in] pCallbacks, a pointer to a callback instance for model operations
@ -543,11 +548,21 @@ NimBLEHealthSrvModel::NimBLEHealthSrvModel(NimBLEMeshModelCallbacks *pCallbacks)
{
memset(&m_healthSrv, 0, sizeof(m_healthSrv));
m_healthSrv.cb = &health_srv_cb;
m_opPub.msg = NET_BUF_SIMPLE(1 + 3);
m_hasFault = false;
m_testId = 0;
}
bt_mesh_health_srv* NimBLEHealthSrvModel::getHealth_t() {
return &m_healthSrv;
void NimBLEHealthSrvModel::setFault(uint8_t fault) {
m_faults.push_back(fault);
m_hasFault = true;
}
void NimBLEHealthSrvModel::clearFaults() {
m_faults.clear();
m_hasFault = false;
}
@ -574,6 +589,23 @@ int16_t NimBLEMeshModelCallbacks::getLevel(NimBLEMeshModel *pModel) {
return 0;
}
void NimBLEMeshModelCallbacks::attentionOn(NimBLEMeshModel *pModel) {
NIMBLE_LOGD(LOG_TAG, "Attention On Default");
}
void NimBLEMeshModelCallbacks::attentionOff(NimBLEMeshModel *pModel) {
NIMBLE_LOGD(LOG_TAG, "Attention Off Default");
}
void NimBLEMeshModelCallbacks::faultTest(NimBLEMeshModel *pModel) {
NIMBLE_LOGD(LOG_TAG, "Fault Test");
}
void NimBLEMeshModelCallbacks::faultClear(NimBLEMeshModel *pModel) {
NIMBLE_LOGD(LOG_TAG, "Fault Clear");
}
/**
* @brief Health server callbacks
*/
@ -582,6 +614,12 @@ int NimBLEHealthSrvCallbacks::faultGetCurrent(bt_mesh_model *model, uint8_t *tes
uint8_t *fault_count)
{
NIMBLE_LOGD(LOG_TAG, "faultGetCurrent - default");
NimBLEHealthSrvModel* pModel = (NimBLEHealthSrvModel*)NimBLEDevice::getMeshNode()->getHealthModel(model);
*test_id = pModel->m_testId;
*company_id = CID_VENDOR;
faults = &pModel->m_faults[0];
*fault_count = pModel->m_faults.size();
return 0;
}
@ -590,27 +628,64 @@ int NimBLEHealthSrvCallbacks::faultGetRegistered(bt_mesh_model *model, uint16_t
uint8_t *fault_count)
{
NIMBLE_LOGD(LOG_TAG, "faultGetRegistered - default");
if (company_id != CID_VENDOR) {
return -BLE_HS_EINVAL;
}
NimBLEHealthSrvModel* pModel = (NimBLEHealthSrvModel*)NimBLEDevice::getMeshNode()->getHealthModel(model);
*test_id = pModel->m_testId;
faults = &pModel->m_faults[0];
*fault_count = pModel->m_faults.size();
return 0;
}
int NimBLEHealthSrvCallbacks::faultClear(bt_mesh_model *model, uint16_t company_id)
{
NIMBLE_LOGD(LOG_TAG, "faultClear - default");
if (company_id != CID_VENDOR) {
return -BLE_HS_EINVAL;
}
NimBLEHealthSrvModel* pModel = (NimBLEHealthSrvModel*)NimBLEDevice::getMeshNode()->getHealthModel(model);
pModel->m_callbacks->faultClear(pModel);
pModel->clearFaults();
return 0;
}
int NimBLEHealthSrvCallbacks::faultTest(bt_mesh_model *model, uint8_t test_id, uint16_t company_id)
{
NIMBLE_LOGD(LOG_TAG, "faultTest - default");
if (company_id != CID_VENDOR) {
return -BLE_HS_EINVAL;
}
if (test_id != STANDARD_TEST_ID) {
return -BLE_HS_EINVAL;
}
NimBLEHealthSrvModel* pModel = (NimBLEHealthSrvModel*)NimBLEDevice::getMeshNode()->getHealthModel(model);
pModel->setFault(0);
pModel->m_testId = test_id;
pModel->m_callbacks->faultTest(pModel);
return 0;
}
void NimBLEHealthSrvCallbacks::attentionOn(bt_mesh_model *model)
{
NIMBLE_LOGD(LOG_TAG, "attentionOn - default");
NimBLEMeshModel* pModel = NimBLEDevice::getMeshNode()->getHealthModel(model);
pModel->m_callbacks->attentionOn(pModel);
}
void NimBLEHealthSrvCallbacks::attentionOff(bt_mesh_model *model)
{
NIMBLE_LOGD(LOG_TAG, "attentionOff - default");
NimBLEMeshModel* pModel = NimBLEDevice::getMeshNode()->getHealthModel(model);
pModel->m_callbacks->attentionOff(pModel);
}

View file

@ -33,7 +33,8 @@ public:
virtual void setPubMsg(){};
virtual void setValue(uint8_t *val, size_t len){};
virtual void setTargetValue(uint8_t *val, size_t len){};
virtual bt_mesh_health_srv* getHealth_t();
virtual void setFault(uint8_t){};
virtual void clearFaults(){};
template<typename T>
void setValue(const T &s) {
@ -138,13 +139,20 @@ class NimBLEGenLevelSrvModel : NimBLEMeshModel {
class NimBLEHealthSrvModel : NimBLEMeshModel {
friend class NimBLEMeshElement;
friend class NimBLEMeshNode;
friend class NimBLEHealthSrvCallbacks;
NimBLEHealthSrvModel(NimBLEMeshModelCallbacks *pCallbacks);
~NimBLEHealthSrvModel(){};
bt_mesh_health_srv* getHealth_t() override;
public:
void setFault(uint8_t) override;
void clearFaults() override;
private:
bt_mesh_health_srv m_healthSrv;
bool m_hasFault;
uint8_t m_testId;
std::vector<uint8_t> m_faults;
};
@ -155,6 +163,11 @@ public:
virtual uint8_t getOnOff(NimBLEMeshModel *pModel);
virtual void setLevel(NimBLEMeshModel *pModel, int16_t val);
virtual int16_t getLevel(NimBLEMeshModel *pModel);
virtual void attentionOn(NimBLEMeshModel *pModel);
virtual void attentionOff(NimBLEMeshModel *pModel);
virtual void faultTest(NimBLEMeshModel *pModel);
virtual void faultClear(NimBLEMeshModel *pModel);
};

View file

@ -128,6 +128,25 @@ NimBLEMeshElement* NimBLEMeshNode::createElement() {
}
/**
* @brief Get a pointer to the health model instance that matches the ID's of the input model.
* @param [in] model A pointer to the NimBLE internal model instance.
* @returns A pointer to the model.
*/
NimBLEMeshModel* NimBLEMeshNode::getHealthModel(bt_mesh_model *model) {
NimBLEMeshModel* pModel;
for(auto &it : m_elemVec) {
pModel = it->getModelByIdx(model->elem_idx, model->mod_idx, BT_MESH_MODEL_ID_HEALTH_SRV);
if(pModel != nullptr) {
return pModel;
}
}
return nullptr;
}
/**
* @brief Start the Mesh mode.
* @returns true on success.

View file

@ -29,6 +29,8 @@
#include <vector>
class NimBLEMeshModel;
typedef enum {
RELAY = 0x01 << 0,
BEACON = 0x01 << 1,
@ -43,6 +45,7 @@ public:
bool start();
NimBLEMeshElement* createElement();
NimBLEMeshElement* getElement(uint8_t index = 0);
NimBLEMeshModel* getHealthModel(bt_mesh_model *model);
private:
friend class NimBLEDevice;