dev(UML-981): Переделана архитектура относительно модулей

Как оказалось, номера слотов и подслотов назначает profinet контроллер и
номера эти зависят от того в каком порядке модули были добавлены в
проекте plc, например в codesys. Теперь в ПО при старте конфигурируются
не слоты и подслоты, а модули и подмодули которые оно поддерживает, а
слоты и подслоты куда будут вставляться эти модули и подмодули
определяются позже профинет контроллером при установлени связи.
This commit is contained in:
Vadim Sychev 2022-07-21 17:00:41 +03:00
parent 6d6149bee9
commit 85eff4f7cd
13 changed files with 543 additions and 305 deletions

View File

@ -57,5 +57,7 @@ int main(int argc, char * argv[])
if (!profinet.Config(settings, profinet_settings)) if (!profinet.Config(settings, profinet_settings))
return 0; return 0;
/// Тестовый слот и модуль ECHO: module_id = 0x40
return 0; return 0;
} }

View File

@ -3,6 +3,8 @@ set(SRC_FILES ${SRC_FILES}
./profinet/profinet.cpp ./profinet/profinet.cpp
./profinet/profinet_slot.cpp ./profinet/profinet_slot.cpp
./profinet/profinet_subslot.cpp ./profinet/profinet_subslot.cpp
./profinet/profinet_module.cpp
./profinet/profinet_submodule.cpp
./profinet/profinet_cb_alarm_ack_cnf.cpp ./profinet/profinet_cb_alarm_ack_cnf.cpp
./profinet/profinet_cb_alarm_cnf.cpp ./profinet/profinet_cb_alarm_cnf.cpp
./profinet/profinet_cb_alarm_ind.cpp ./profinet/profinet_cb_alarm_ind.cpp

View File

@ -152,6 +152,7 @@ Profinet::Profinet(void) : m_pnet_data({nullptr, 0})
bool Profinet::Config(ProfinetSettings& Settings, ProfinetDeviceSettings& DevSettings) bool Profinet::Config(ProfinetSettings& Settings, ProfinetDeviceSettings& DevSettings)
{ {
bool ret = true;
pnet_cfg_t pnet_cfg = {0}; pnet_cfg_t pnet_cfg = {0};
utils_netif_namelist_t netif_name_list; utils_netif_namelist_t netif_name_list;
uint16_t number_of_ports = 1; uint16_t number_of_ports = 1;
@ -185,58 +186,33 @@ bool Profinet::Config(ProfinetSettings& Settings, ProfinetDeviceSettings& DevSet
if (m_pnet_data.pnet_ptr == nullptr) if (m_pnet_data.pnet_ptr == nullptr)
return false; return false;
/**
* @brief Создаем стандартный слот для модуля DAP 1 (Device Access Point)
* Это обязательный модуль для profinet device
*/
auto dap_slot = make_shared<ProfinetSlot>(PNET_SLOT_DAP_IDENT, PNET_MOD_DAP_IDENT, "DAP 1");
/**
* @brief Добавляем слот и подключаем модуль
*
*/
if (!addSlotAndPlugModule(dap_slot))
return false;
///
pnet_data_cfg_t dap_data_cfg = { PNET_DIR_NO_IO, 0, 0 }; pnet_data_cfg_t dap_data_cfg = { PNET_DIR_NO_IO, 0, 0 };
/// Создаем обязательный модуль DAP
auto dap_module = make_shared<ProfinetModule>(PNET_MOD_DAP_IDENT, "DAP 1");
/// Создаем обязательный подмодуль DAP Identity 1
auto dap_submodule_indent_1 = make_shared<ProfinetSubmodule>(PNET_SUBMOD_DAP_IDENT, "DAP Identity 1", dap_data_cfg);
/// Создаем обязательный подмодуль DAP IFACE1 IDENT
auto dap_submodule_iface_1_indent_1 = make_shared<ProfinetSubmodule>(PNET_SUBMOD_DAP_INTERFACE_1_IDENT, "DAP IFACE1 IDENT", dap_data_cfg);
/// Создаем обязательный подмодуль DAP Port 1
auto dap_subslot_iface_1_port1_ident = make_shared<ProfinetSubmodule>(PNET_SUBMOD_DAP_INTERFACE_1_PORT_1_IDENT, "DAP Port 1", dap_data_cfg);
/// Добавляем подмодули к модулю
ret&= dap_module->addSubmodule(dap_submodule_indent_1);
ret&= dap_module->addSubmodule(dap_submodule_iface_1_indent_1);
ret&= dap_module->addSubmodule(dap_subslot_iface_1_port1_ident);
/** /// Создаем слот для модуля DAP и доключаем к нему модуль dap_module
* @brief Создаем стандартный подслот для подмодуля identity 1 который входит в модуль DAP 1 ret&= addSlotAndPlugModule(PNET_SLOT_DAP_IDENT, dap_module);
* Это обязательный подслот для profinet device /// Добавляем подслоты к слоту и подключаем к подслоту подмодуль
*/ /// 1. Подмодуль "DAP Identity 1"
auto dap_subslot_identity_1 = make_shared<ProfinetSubslot>( PNET_SUBSLOT_DAP_IDENT, ret&= addSubslotAndPlugSubmodule(PNET_SLOT_DAP_IDENT, PNET_SUBSLOT_DAP_IDENT, dap_submodule_indent_1);
PNET_SUBMOD_DAP_IDENT, /// 2. Подмодуль "DAP IFACE1 IDENT"
"DAP Identity 1", ret&= addSubslotAndPlugSubmodule(PNET_SLOT_DAP_IDENT, PNET_SUBSLOT_DAP_INTERFACE_1_IDENT, dap_submodule_iface_1_indent_1);
dap_data_cfg ); /// 3. Подмодуль "DAP Port 1"
/** ret&= addSubslotAndPlugSubmodule(PNET_SLOT_DAP_IDENT, PNET_SUBSLOT_DAP_INTERFACE_1_PORT_1_IDENT, dap_subslot_iface_1_port1_ident);
* @brief Создаем стандартный подслот для подмодуля iface 1 ident который входит в модуль DAP 1
* Это обязательный подслот для profinet device
*/
auto dap_subslot_iface_1_ident = make_shared<ProfinetSubslot>( PNET_SUBSLOT_DAP_INTERFACE_1_IDENT,
PNET_SUBMOD_DAP_INTERFACE_1_IDENT,
"DAP IFACE1 IDENT",
dap_data_cfg );
/**
* @brief Создаем стандартный подслот для подмодуля iface 1.port 1 ident который входит в модуль DAP 1
* Это обязательный подслот для profinet device
*/
auto dap_subslot_iface_1_port1_ident = make_shared<ProfinetSubslot>( PNET_SUBSLOT_DAP_INTERFACE_1_PORT_1_IDENT,
PNET_SUBMOD_DAP_INTERFACE_1_PORT_1_IDENT,
"DAP Port 1",
dap_data_cfg );
/**
* @brief Добавляем подслоты в слот и поключаем подмодули в подслоты
*
*/
if (!dap_slot->addSubslotAndPlugSubmodule(m_pnet_data, dap_subslot_identity_1))
return false;
if (!dap_slot->addSubslotAndPlugSubmodule(m_pnet_data, dap_subslot_iface_1_ident)) return ret;
return false;
if (!dap_slot->addSubslotAndPlugSubmodule(m_pnet_data, dap_subslot_iface_1_port1_ident))
return false;
return true;
} }
bool Profinet::addSlot(std::shared_ptr<ProfinetSlot>& slot_ptr) bool Profinet::addSlot(std::shared_ptr<ProfinetSlot>& slot_ptr)
@ -249,36 +225,146 @@ bool Profinet::addSlot(std::shared_ptr<ProfinetSlot>& slot_ptr)
return true; return true;
} }
bool Profinet::addSlotAndPlugModule(std::shared_ptr<ProfinetSlot>& slot_ptr) std::shared_ptr<ProfinetSlot> Profinet::addSlot(uint16_t slot_nbr)
{ {
if (!addSlot(slot_ptr)) std::shared_ptr<ProfinetSlot> slot_ptr(nullptr);
return false;
if (!slot_ptr->plugModule(m_pnet_data)) if (m_slots.count(slot_nbr))
return false;
return true;
}
ProfinetSlot * Profinet::getSlotPtrAndCheckModule(uint16_t slot_nbr, uint32_t module_id)
{
ProfinetSlot * const slot_ptr = getSlotPtr(slot_nbr);
if (slot_ptr == nullptr)
{ {
return nullptr; slot_ptr = m_slots[slot_nbr];
}
else
{
slot_ptr = make_shared<ProfinetSlot>(slot_nbr);
} }
/// 2. Проверить, что в слоте slot идентификатор модуля m_module_id совпадает с module_ident if (slot_ptr != nullptr)
if (slot_ptr->m_module_id != module_id)
{ {
return nullptr; m_slots[slot_nbr] = slot_ptr;
} }
return slot_ptr; return slot_ptr;
} }
ProfinetSlot * Profinet::getSlotPtr(uint16_t slot_nbr) bool Profinet::addModule(std::shared_ptr<ProfinetModule>& module_ptr)
{
if (module_ptr == nullptr)
return false;
m_modules[module_ptr->m_id] = module_ptr;
return true;
}
std::shared_ptr<ProfinetModule> Profinet::getModule(uint32_t module_id)
{
if (!m_modules.count(module_id))
{
return nullptr;
}
return m_modules[module_id];
}
bool Profinet::addSlotAndPlugModule(uint16_t slot_nbr, std::shared_ptr<ProfinetModule>& module_ptr)
{
auto slot = addSlot(slot_nbr);
if (slot == nullptr)
{
return false;
}
return slot->plugModule(m_pnet_data, module_ptr);
}
bool Profinet::addSlotAndPlugModule(uint16_t slot_nbr, uint32_t module_id)
{
/// 1. Проверяем, что module_id поддерживается
auto module_ptr = getModule(module_id);
if (module_ptr == nullptr)
{
return false;
}
///2. Добавляет слот
auto slot = addSlot(slot_nbr);
if (slot == nullptr)
{
return false;
}
/// 3. Подключаем модуль к слоту
return slot->plugModule(m_pnet_data, module_ptr);
}
bool Profinet::addSubslotAndPlugSubmodule(uint16_t slot_nbr, uint16_t subslot_nbr, std::shared_ptr<ProfinetSubmodule>& submodule_ptr)
{
auto slot_ptr = getSlotPtr(slot_nbr);
if (slot_ptr == nullptr)
{
return false;
}
auto subslot_ptr = slot_ptr->addSubslot(subslot_nbr);
if (subslot_ptr == nullptr)
{
return false;
}
return subslot_ptr->plugSubmodule(m_pnet_data, submodule_ptr);
}
bool Profinet::addSubslotAndPlugSubmodule(uint16_t slot_nbr,
uint16_t subslot_nbr,
uint32_t module_id,
uint32_t submodule_id,
const pnet_data_cfg_t * p_exp_data)
{
///1. Проверяем наличие слота
auto slot_ptr = getSlotPtr(slot_nbr);
if (slot_ptr == nullptr)
{
return false;
}
///2. Проверяем, что к слоту подключен модуль с идентификатором module_id
auto module_ptr = slot_ptr->getModulePtr();
if (module_ptr == nullptr)
{
return false;
}
if (module_ptr->m_id != module_id)
{
return false;
}
///3. Проверяем, что в модуль входит подмодуль с идентфикатором submodule_id
auto submodule_ptr = module_ptr->getSubmodulePtr(submodule_id);
if (submodule_ptr == nullptr)
{
return false;
}
///4. Проверяем, что конфигурация данных совпадает
if ((submodule_ptr->m_data_cfg.data_dir != p_exp_data->data_dir) ||
(submodule_ptr->m_data_cfg.insize != p_exp_data->insize) ||
(submodule_ptr->m_data_cfg.outsize != p_exp_data->outsize))
{
return false;
}
return addSubslotAndPlugSubmodule(slot_nbr, subslot_nbr, submodule_ptr);
}
std::shared_ptr<ProfinetSlot> Profinet::getSlotPtr(uint16_t slot_nbr)
{ {
/// 1. Проверить, что слот slot добавлен в конфигурацию /// 1. Проверить, что слот slot добавлен в конфигурацию
if (!m_slots.count(slot_nbr)) if (!m_slots.count(slot_nbr))
@ -286,12 +372,12 @@ ProfinetSlot * Profinet::getSlotPtr(uint16_t slot_nbr)
return nullptr; return nullptr;
} }
return m_slots[slot_nbr].get(); return m_slots[slot_nbr];
} }
ProfinetSubslot * Profinet::getSubslotPtr(uint16_t slot_nbr, uint16_t subslot_nbr) std::shared_ptr<ProfinetSubslot> Profinet::getSubslotPtr(uint16_t slot_nbr, uint16_t subslot_nbr)
{ {
ProfinetSlot * const slot_ptr = getSlotPtr(slot_nbr); auto slot_ptr = getSlotPtr(slot_nbr);
if (slot_ptr == nullptr) if (slot_ptr == nullptr)
{ {
@ -301,6 +387,34 @@ ProfinetSubslot * Profinet::getSubslotPtr(uint16_t slot_nbr, uint16_t subslot_nb
return slot_ptr->getSubslotPtr(subslot_nbr); return slot_ptr->getSubslotPtr(subslot_nbr);
} }
std::shared_ptr<ProfinetParameter> Profinet::getSubmoduleParameter(uint16_t slot_nbr, uint16_t subslot_nbr, uint32_t param_index)
{
///1. Проверяем что существует подслот \a subslot_nbr входящий к \a slot_nbr
auto subslot_ptr = getSubslotPtr(slot_nbr, subslot_nbr);
if (subslot_ptr == nullptr)
{
return nullptr;
}
///2. Проверяем что к подслоту \a subslot_nbr подключен подмодуль
auto submodule_ptr = subslot_ptr->getSubmodulePtr();
if (submodule_ptr == nullptr)
{
return nullptr;
}
///3. Проверяем, что у подмодуля есть параметр с индексом idx
auto param_ptr = submodule_ptr->getParameterPtr(param_index);
if (param_ptr == nullptr)
{
return nullptr;
}
return param_ptr;
}
/**\ /**\
* ========================================================================================= * =========================================================================================
* Callbacks * Callbacks
@ -366,18 +480,8 @@ int Profinet::callbackReadInd ( uint32_t arep,
uint16_t * p_read_length, uint16_t * p_read_length,
pnet_result_t * p_result) pnet_result_t * p_result)
{ {
ProfinetSubslot * const subslot_ptr = getSubslotPtr(slot_nbr, subslot_nbr); ///1. Проверяем, что у подмодуля есть параметр с индексом idx
auto param_ptr = getSubmoduleParameter(slot_nbr, subslot_nbr, idx);
if (subslot_ptr == nullptr)
{
p_result->pnio_status.error_code = PNET_ERROR_CODE_READ;
p_result->pnio_status.error_decode = PNET_ERROR_DECODE_PNIORW;
p_result->pnio_status.error_code_1 = PNET_ERROR_CODE_1_APP_READ_ERROR;
p_result->pnio_status.error_code_2 = 0; /* User specific */
return -1;
}
ProfinetParameter * param_ptr = subslot_ptr->getParameterPtr(idx);
if (param_ptr == nullptr) if (param_ptr == nullptr)
{ {
@ -388,6 +492,7 @@ int Profinet::callbackReadInd ( uint32_t arep,
return -1; return -1;
} }
///2. Проверяем корректность длины данных (меньше быть не должно, если больше - это норм)
if (*p_read_length < param_ptr->length) if (*p_read_length < param_ptr->length)
{ {
p_result->pnio_status.error_code = PNET_ERROR_CODE_READ; p_result->pnio_status.error_code = PNET_ERROR_CODE_READ;
@ -397,6 +502,7 @@ int Profinet::callbackReadInd ( uint32_t arep,
return -1; return -1;
} }
///3. Передаем данные параметра
*pp_read_data = param_ptr->data_ptr; *pp_read_data = param_ptr->data_ptr;
*p_read_length = param_ptr->length; *p_read_length = param_ptr->length;
@ -412,18 +518,8 @@ int Profinet::callbackWriteInd ( uint32_t arep,
const uint8_t * p_write_data, const uint8_t * p_write_data,
pnet_result_t * p_result) pnet_result_t * p_result)
{ {
ProfinetSubslot * const subslot_ptr = getSubslotPtr(slot_nbr, subslot_nbr); ///1. Проверяем, что у подмодуля есть параметр с индексом idx
auto param_ptr = getSubmoduleParameter(slot_nbr, subslot_nbr, idx);
if (subslot_ptr == nullptr)
{
p_result->pnio_status.error_code = PNET_ERROR_CODE_WRITE;
p_result->pnio_status.error_decode = PNET_ERROR_DECODE_PNIORW;
p_result->pnio_status.error_code_1 = PNET_ERROR_CODE_1_APP_WRITE_ERROR;
p_result->pnio_status.error_code_2 = 0; /* User specific */
return -1;
}
ProfinetParameter * param_ptr = subslot_ptr->getParameterPtr(idx);
if (param_ptr == nullptr) if (param_ptr == nullptr)
{ {
@ -433,7 +529,7 @@ int Profinet::callbackWriteInd ( uint32_t arep,
p_result->pnio_status.error_code_2 = 0; /* User specific */ p_result->pnio_status.error_code_2 = 0; /* User specific */
return -1; return -1;
} }
///2. Проверяем корректность длины данных
if (write_length != param_ptr->length) if (write_length != param_ptr->length)
{ {
p_result->pnio_status.error_code = PNET_ERROR_CODE_WRITE; p_result->pnio_status.error_code = PNET_ERROR_CODE_WRITE;
@ -443,7 +539,7 @@ int Profinet::callbackWriteInd ( uint32_t arep,
return -1; return -1;
} }
/// ///3. Копируем данные
std::memcpy(param_ptr->data_ptr, p_write_data, param_ptr->length); std::memcpy(param_ptr->data_ptr, p_write_data, param_ptr->length);
return 0; return 0;
@ -451,19 +547,9 @@ int Profinet::callbackWriteInd ( uint32_t arep,
int Profinet::callbackExpModuleInd ( uint16_t slot, uint32_t module_ident) int Profinet::callbackExpModuleInd ( uint16_t slot, uint32_t module_ident)
{ {
ProfinetSlot * const slot_ptr = getSlotPtrAndCheckModule(slot, module_ident); bool ret = addSlotAndPlugModule(slot, module_ident);
/**
* @brief Проверка, что слот slot добавлен в конфигурацию и что
* идентификатор модуля m_module_id совпадает с module_ident
*
*/
if (slot_ptr == nullptr)
{
return -1;
}
/// Подключить модуль в слот if (ret == false)
if (!slot_ptr->plugModule(m_pnet_data))
{ {
return -1; return -1;
} }
@ -477,38 +563,9 @@ int Profinet::callbackExpSubmoduleInd ( uint16_t slot,
uint32_t submodule_id, uint32_t submodule_id,
const pnet_data_cfg_t * p_exp_data) const pnet_data_cfg_t * p_exp_data)
{ {
ProfinetSlot * const slot_ptr = getSlotPtrAndCheckModule(slot, module_id); bool ret = addSubslotAndPlugSubmodule(slot, subslot, module_id, submodule_id, p_exp_data);
/**
* @brief Проверка, что слот slot добавлен в конфигурацию и что
* идентификатор модуля m_module_id совпадает с module_ident
*
*/
if (slot_ptr == nullptr)
{
return -1;
}
/// Проверка, что модуль подключен к слоту if (ret == false)
if (!slot_ptr->isModulePlugged())
{
return -1;
}
ProfinetSubslot * const subslot_ptr = slot_ptr->getSubslotPtrAndCheckSubmodule(subslot, submodule_id, p_exp_data);
/**
* Проверка того, что:
* - подслот subslot добавлен в конфигурацию слота,
* - идентификатор модуля подслота m_module_id совпадает с submodule_id
* - конфигурация данных слота совпадает с p_exp_data
*/
if (subslot_ptr == nullptr)
{
return -1;
}
/// Подключить подмодуль submodule_id к подслоту subslot
if (!subslot_ptr->plugSubmodule(m_pnet_data))
{ {
return -1; return -1;
} }

View File

@ -14,38 +14,136 @@ public:
bool Config(ProfinetSettings& Settings, ProfinetDeviceSettings& DevSettings); bool Config(ProfinetSettings& Settings, ProfinetDeviceSettings& DevSettings);
/**
* @brief Добавляет ранее созданный слот slot_ptr
*
* @param slot_ptr слот
* @return true слот добавлен
* @return false слот не был добавлен
*/
bool addSlot(std::shared_ptr<ProfinetSlot>& slot_ptr); bool addSlot(std::shared_ptr<ProfinetSlot>& slot_ptr);
bool addSlotAndPlugModule(std::shared_ptr<ProfinetSlot>& slot_ptr); /**
* @brief Если слот с номером slot_nbr еще не добавлен, то создает слот и добавляет его
*
* @param slot_nbr номер слота
* @return указатель на слот
*/
std::shared_ptr<ProfinetSlot> addSlot(uint16_t slot_nbr);
/**
* @brief Добавляет слот с номером slot_nbr и подключает к нему модуль module_ptr.
* Если слота с номером slot_nbr еще не добавлено, то он будет создан и добавлен.
* Если слот с номером slot_nbr был добавлен ранее, то это штатная работа данной функции.
*
* @param slot_nbr номер слота
* @param module_ptr указатель на модуль
* @return true модуль успешно подключен
* @return false модуль не подключен
*/
bool addSlotAndPlugModule(uint16_t slot_nbr, std::shared_ptr<ProfinetModule>& module_ptr);
/**
* @brief Добавляет слот с номером slot_nbr и подключает к нему модуль из словаря \a m_modules чей
* идентификатор равен module_id.
* Если слота с номером slot_nbr еще не добавлено, то он будет создан и добавлен.
* Если слот с номером slot_nbr был добавлен ранее, то это штатная работа данной функции.
*
* @param slot_nbr номер слота
* @param module_id идентификатор модуля
* @return true модуль успешно подключен
* @return false модуль не подключен
*/
bool addSlotAndPlugModule(uint16_t slot_nbr, uint32_t module_id);
/**
* @brief Добавляет к слоту с номером \a slot_nbr подслот с номером \a subslot_nbr и подключает к нему подмодуль \a submodule_ptr.
* Если слота с номером \a slot_nbr еще не добавлено, то выполнене функции завершиться со значением \a false.
* Если подслота с номером \a subslot_nbr еще не добавлено в слот \a slot_nbr то он будет создан и добавлен.
*
* @param slot_nbr номер слота
* @param subslot_nbr номер подслота
* @param submodule_ptr указатель на подмодуль
* @return true подмодуль успешно подключен
* @return false подмодуль не подключен
*/
bool addSubslotAndPlugSubmodule(uint16_t slot_nbr, uint16_t subslot_nbr, std::shared_ptr<ProfinetSubmodule>& submodule_ptr);
/**
* @brief Добавляет к слоту с номером \a slot_nbr, к которому подключен модуль с идентификатором \a module_id, подслот
* с номером \a subslot_nbr и подключает к нему подмодуль с идентификатором \a submodule_id.
* Выполнение функции прекратиться с возвратом false, если:
* - слот \a slot_nbr не был добавлен ранее,
* - слот \a slot_nbr был добавлен ранее, но к нему подключен модуль с идентфикатором не равным \a module_id,
* - в модуль с идентификатором \a module_id не входит подмодуль с идентификатором \a submodule_id
* - описание данных подмодуля \a submodule_id не совпарадет с описанием данным в \a p_exp_data
*
* @param slot_nbr номер слота
* @param subslot_nbr номер подслота
* @param module_id идентификатор модуля
* @param submodule_id идентификатор подмодуля
* @param p_exp_data описание данныз подмодуля
* @return true подмодуль подключен
* @return false подмодуль не подключен
*/
bool addSubslotAndPlugSubmodule(uint16_t slot_nbr,
uint16_t subslot_nbr,
uint32_t module_id,
uint32_t submodule_id,
const pnet_data_cfg_t * p_exp_data);
/**
* @brief Добавляет модуль в конфигурацию
*
* @param module_ptr
* @return true
* @return false
*/
bool addModule(std::shared_ptr<ProfinetModule>& module_ptr);
/**
* @brief геттер модуля
*
* @param module_id идентификатор модуля
* @return std::shared_ptr<ProfinetModule> возвращает указатель на модуль или nullptr если такого модуля нет в \a m_modules
*/
std::shared_ptr<ProfinetModule> getModule(uint32_t module_id);
/**
* @brief геттер указателя на структуру данных параметра подмодуля с идексом \a param_index подключенного к подслоту
* \a subslot_nbr входящего в состав \a slot_nbr.
*
* @param slot_nbr номер слота
* @param subslot_nbr номер подслота
* @param param_index индекс параметра
* @return std::shared_ptr<ProfinetParameter> указатель на параметр или nullptr
*/
std::shared_ptr<ProfinetParameter> getSubmoduleParameter(uint16_t slot_nbr, uint16_t subslot_nbr, uint32_t param_index);
private: private:
ProfinetServiceData m_pnet_data; ProfinetServiceData m_pnet_data;
/** /**
* @brief Ключ - идентификатор модуля, Значение - структура слота * @brief Ключ - номер слота, Значение - указатель на слот
* *
*/ */
std::map<uint16_t, std::shared_ptr<ProfinetSlot>> m_slots; std::map<uint16_t, std::shared_ptr<ProfinetSlot>> m_slots;
/**
* @brief Ключ - идентиикатор модуля, Значение - указатель на модуль
*
*/
std::map<uint32_t, std::shared_ptr<ProfinetModule>> m_modules;
private: private:
/**
* @brief Геттер указателя на слот. Проверяет в конфигурации наличие слота slot_nbr
* с правильным module_id
*
* @param slot_nbr номер слота
* @param module_id идентификатор модуля
* @return ProfinetSlot* указатель на слот если слот сномером slot_nbr и идентификатором модуля module_id существует в конфигурации
*/
ProfinetSlot * getSlotPtrAndCheckModule(uint16_t slot_nbr, uint32_t module_id);
/** /**
* @brief Проверяет наличие слота slot_nbr в конфигурации * @brief Проверяет наличие слота slot_nbr в конфигурации
* *
* @param slot_nbr номер слота * @param slot_nbr номер слота
* @return ProfinetSlot* - указатель на слот, при успехе или nullptr есои слот в конфигурации отсутсвует * @return ProfinetSlot* - указатель на слот, при успехе или nullptr есои слот в конфигурации отсутсвует
*/ */
ProfinetSlot * getSlotPtr(uint16_t slot_nbr); std::shared_ptr<ProfinetSlot> getSlotPtr(uint16_t slot_nbr);
ProfinetSubslot * getSubslotPtr(uint16_t slot_nbr, uint16_t subslot_nbr); std::shared_ptr<ProfinetSubslot> getSubslotPtr(uint16_t slot_nbr, uint16_t subslot_nbr);
public: public:
/** /**

View File

@ -0,0 +1,25 @@
#include "profinet_module.hpp"
ProfinetModule::ProfinetModule(uint32_t module_id, std::string module_name) :
m_id(module_id),
m_name(module_name)
{
};
bool ProfinetModule::addSubmodule(std::shared_ptr<ProfinetSubmodule>& submodule_ptr)
{
auto ret = m_submodules.emplace(submodule_ptr->m_id, submodule_ptr);
return ret.second;
}
std::shared_ptr<ProfinetSubmodule> ProfinetModule::getSubmodulePtr(uint32_t submodule_id)
{
if (!m_submodules.count(submodule_id))
{
return nullptr;
}
return m_submodules[submodule_id];
}

View File

@ -0,0 +1,26 @@
#pragma once
#include <cstdint>
#include <string>
#include <map>
#include <memory>
#include "profinet_submodule.hpp"
class ProfinetModule {
public:
ProfinetModule(uint32_t module_id, std::string module_name);
bool addSubmodule(std::shared_ptr<ProfinetSubmodule>& submodule_ptr);
std::shared_ptr<ProfinetSubmodule> getSubmodulePtr(uint32_t submodule_id);
public:
const uint32_t m_id; /// module id
const std::string m_name; /// module name
private:
/// Набор поддерживаемых подмодулей
std::map<uint32_t, std::shared_ptr<ProfinetSubmodule>> m_submodules;
};

View File

@ -0,0 +1,19 @@
#pragma once
#include <cstdint>
#include <string>
#include <memory.h>
struct ProfinetParameter
{
ProfinetParameter(std::string Name, uint32_t Index, uint8_t * pData, uint16_t Length) :
name(Name),
index(Index),
data_ptr(pData),
length(Length) {};
const std::string name; /// Имя параметра
const uint32_t index; /// Идентфикатор параметра
uint8_t * const data_ptr; /// указатель на данные параметра
const uint16_t length; /// длина параметра в байтах
};

View File

@ -1,11 +1,8 @@
#include "profinet_slot.hpp" #include "profinet_slot.hpp"
ProfinetSlot::ProfinetSlot ( uint16_t slot_nbr, ProfinetSlot::ProfinetSlot ( uint16_t slot_nbr ) :
uint32_t module_id, m_slot_nbr(slot_nbr),
std::string module_name) : m_slot_nbr(slot_nbr), m_module_ptr(nullptr)
m_module_id(module_id),
m_module_name(module_name)
{ {
} }
@ -15,21 +12,25 @@ bool ProfinetSlot::pullModule(ProfinetServiceData& pnet_data)
{ {
int result = pnet_pull_module (pnet_data.pnet_ptr, pnet_data.api, m_slot_nbr); int result = pnet_pull_module (pnet_data.pnet_ptr, pnet_data.api, m_slot_nbr);
m_module_plugged = false; m_module_ptr = nullptr;
return (result == 0); return (result == 0);
} }
bool ProfinetSlot::plugModule(ProfinetServiceData& pnet_data) bool ProfinetSlot::plugModule(ProfinetServiceData& pnet_data, std::shared_ptr<ProfinetModule>& module_ptr)
{ {
/// Сначала отключаем модуль /// Сначала отключаем модуль
pullModule(pnet_data); pullModule(pnet_data);
/// Затем подключаем модуль /// Затем подключаем модуль
int result = pnet_plug_module (pnet_data.pnet_ptr, pnet_data.api, m_slot_nbr, m_module_id); int result = pnet_plug_module (pnet_data.pnet_ptr, pnet_data.api, m_slot_nbr, module_ptr->m_id);
m_module_plugged = (result == 0); if (result == 0)
{
m_module_ptr = module_ptr;
}
return m_module_plugged; return (m_module_ptr != nullptr);
} }
bool ProfinetSlot::addSubslot(std::shared_ptr<ProfinetSubslot>& subslot_ptr) bool ProfinetSlot::addSubslot(std::shared_ptr<ProfinetSubslot>& subslot_ptr)
@ -37,54 +38,39 @@ bool ProfinetSlot::addSubslot(std::shared_ptr<ProfinetSubslot>& subslot_ptr)
if (subslot_ptr == nullptr) if (subslot_ptr == nullptr)
return false; return false;
if (m_module_ptr == nullptr)
return false;
subslot_ptr->setSlotNumber(m_slot_nbr); subslot_ptr->setSlotNumber(m_slot_nbr);
subslot_ptr->setModuleId(m_module_id); subslot_ptr->setModuleId(m_module_ptr->m_id);
m_subslots[subslot_ptr->m_submodule_id] = subslot_ptr; m_subslots[subslot_ptr->m_subslot_nbr] = subslot_ptr;
return true; return true;
} }
std::shared_ptr<ProfinetSubslot> ProfinetSlot::addSubslot(uint16_t subslot_nbr)
bool ProfinetSlot::addSubslotAndPlugSubmodule(ProfinetServiceData& pnet_data, std::shared_ptr<ProfinetSubslot>& subslot_ptr)
{ {
if (!addSubslot(subslot_ptr)) std::shared_ptr<ProfinetSubslot> subslot_ptr(nullptr);
return false;
if (!subslot_ptr->plugSubmodule(pnet_data)) if (m_subslots.count(subslot_nbr))
return false;
return true;
}
ProfinetSubslot * ProfinetSlot::getSubslotPtrAndCheckSubmodule(uint16_t subslot_nbr, uint32_t submodule_id, const pnet_data_cfg_t * const p_data_cfg)
{
/// Проверка наличия подслота в конфигурации
ProfinetSubslot * const subslot_ptr = getSubslotPtr(subslot_nbr);
if (subslot_ptr == nullptr)
{ {
return nullptr; subslot_ptr = m_subslots[subslot_nbr];
}
else
{
subslot_ptr = std::make_shared<ProfinetSubslot>(subslot_nbr);
} }
/// Проверка совпадения идентификатора подмодуля if (subslot_ptr != nullptr)
if (subslot_ptr->m_submodule_id != submodule_id)
{ {
return nullptr; m_subslots[subslot_nbr] = subslot_ptr;
}
/// Проверка совпадения конфигурации данных
if ( (subslot_ptr->m_data_cfg.data_dir != p_data_cfg->data_dir) ||
(subslot_ptr->m_data_cfg.insize != p_data_cfg->insize) ||
(subslot_ptr->m_data_cfg.outsize != p_data_cfg->outsize)
)
{
return nullptr;
} }
return subslot_ptr; return subslot_ptr;
} }
ProfinetSubslot * ProfinetSlot::getSubslotPtr(uint16_t subslot_nbr) std::shared_ptr<ProfinetSubslot> ProfinetSlot::getSubslotPtr(uint16_t subslot_nbr)
{ {
/// Проверка наличия подслота в конфигурации /// Проверка наличия подслота в конфигурации
if (!m_subslots.count(subslot_nbr)) if (!m_subslots.count(subslot_nbr))
@ -92,5 +78,11 @@ ProfinetSubslot * ProfinetSlot::getSubslotPtr(uint16_t subslot_nbr)
return nullptr; return nullptr;
} }
return m_subslots[subslot_nbr].get(); return m_subslots[subslot_nbr];
} }
std::shared_ptr<ProfinetModule> ProfinetSlot::getModulePtr()
{
return m_module_ptr;
}

View File

@ -1,12 +1,12 @@
#pragma once #pragma once
#include <cstdint>
#include <map>
#include <memory>
#include "profinet_serv_data.hpp" #include "profinet_serv_data.hpp"
#include "profinet_subslot.hpp" #include "profinet_subslot.hpp"
#include "profinet_module.hpp"
#include <cstdint>
#include <string>
#include <map>
#include <memory>
class ProfinetSlot class ProfinetSlot
{ {
@ -15,14 +15,8 @@ public:
* @brief Construct a new Profinet Slot object * @brief Construct a new Profinet Slot object
* *
* @param slot_nbr номер слота * @param slot_nbr номер слота
* @param module_id идентификатор модуля который может поключиться к этому слоту
* @param module_name имя модуля
*/ */
ProfinetSlot ( ProfinetSlot(uint16_t slot_nbr);
uint16_t slot_nbr,
uint32_t module_id,
std::string module_name
);
/** /**
* @brief Подключает модуль к слоту * @brief Подключает модуль к слоту
* *
@ -30,7 +24,7 @@ public:
* @return true модуль подключен * @return true модуль подключен
* @return false модуль не подключен * @return false модуль не подключен
*/ */
bool plugModule(ProfinetServiceData& pnet_data); bool plugModule(ProfinetServiceData& pnet_data, std::shared_ptr<ProfinetModule>& module_ptr);
/** /**
* @brief Отключает модуль от слота * @brief Отключает модуль от слота
* *
@ -40,29 +34,35 @@ public:
*/ */
bool pullModule(ProfinetServiceData& pnet_data); bool pullModule(ProfinetServiceData& pnet_data);
/**
* @brief Добавляет ранее созданный подслот subslot_ptr
*
* @param subslot_ptr подслот
* @return true подслот добавлен
* @return false подслот был добавлен ранее
*/
bool addSubslot(std::shared_ptr<ProfinetSubslot>& subslot_ptr); bool addSubslot(std::shared_ptr<ProfinetSubslot>& subslot_ptr);
bool addSubslotAndPlugSubmodule(ProfinetServiceData& pnet_data, std::shared_ptr<ProfinetSubslot>& subslot_ptr); /**
* @brief Если подслот с номером subslot_nbr еще не добавлен, то создает подслот и добавляет его
*
* @param subslot_nbr номер подслота
* @return std::shared_ptr<ProfinetSubslot> указатель на подслот
*/
std::shared_ptr<ProfinetSubslot> addSubslot(uint16_t subslot_nbr);
bool isModulePlugged() { return m_module_plugged; } std::shared_ptr<ProfinetSubslot> getSubslotPtr(uint16_t subslot_nbr);
ProfinetSubslot * getSubslotPtrAndCheckSubmodule(uint16_t subslot_nbr, uint32_t submodule_id, const pnet_data_cfg_t * const p_data_cfg); std::shared_ptr<ProfinetModule> getModulePtr();
ProfinetSubslot * getSubslotPtr(uint16_t subslot_nbr);
public: public:
/// Номер слота /// Номер слота
const uint16_t m_slot_nbr; const uint16_t m_slot_nbr;
/// Идентификатор модуля который может быть подключен к данному слоту
const uint32_t m_module_id;
/// Имя подключаемого модуля
const std::string m_module_name;
private: private:
/// Флаг подключения модуля к слоту /// Модуль вставленный в этот слот
bool m_module_plugged; std::shared_ptr<ProfinetModule> m_module_ptr;
/// множество подслотов /// множество подслотов
std::map<uint16_t, std::shared_ptr<ProfinetSubslot>> m_subslots; std::map<uint16_t, std::shared_ptr<ProfinetSubslot>> m_subslots;
}; };

View File

@ -0,0 +1,28 @@
#include "profinet_submodule.hpp"
ProfinetSubmodule::ProfinetSubmodule(uint16_t submodule_id,
std::string submodule_name,
pnet_data_cfg_t& submodule_data_cfg) :
m_id(submodule_id),
m_name(submodule_name),
m_data_cfg(submodule_data_cfg)
{
}
bool ProfinetSubmodule::addParameter(std::shared_ptr<ProfinetParameter>& param)
{
auto ret = m_params.emplace(param->index, param);
return ret.second;
}
std::shared_ptr<ProfinetParameter> ProfinetSubmodule::getParameterPtr(uint32_t index)
{
if (!m_params.count(index))
{
return nullptr;
}
return m_params[index];
}

View File

@ -0,0 +1,31 @@
#pragma once
#include <cstdint>
#include <string>
#include <map>
#include <memory>
#include "profinet_parameter.hpp"
#include "../../libs/include/pnet_api.h"
class ProfinetSubmodule {
public:
ProfinetSubmodule(uint16_t submodule_id,
std::string submodule_name,
pnet_data_cfg_t& submodule_data_cfg);
bool addParameter(std::shared_ptr<ProfinetParameter>& param);
std::shared_ptr<ProfinetParameter> getParameterPtr(uint32_t index);
public:
const uint16_t m_id; /// Идентификатор подмодуля
const std::string m_name; /// Имя подмодуля
const pnet_data_cfg_t m_data_cfg; /// Конфигурация циклических данных подмодуля
private:
/// Набор параметров подмодуля
std::map<uint32_t, std::shared_ptr<ProfinetParameter>> m_params;
};

View File

@ -1,14 +1,12 @@
#include "profinet_subslot.hpp" #include "profinet_subslot.hpp"
ProfinetSubslot::ProfinetSubslot(uint16_t subslot_nbr, ProfinetSubslot::ProfinetSubslot(uint16_t subslot_nbr, uint16_t slot_nbr, uint32_t module_id) :
uint32_t submodule_id,
std::string submodule_name,
pnet_data_cfg_t data_cfg) :
m_subslot_nbr(subslot_nbr), m_subslot_nbr(subslot_nbr),
m_submodule_id(submodule_id), m_slot_nbr(slot_nbr),
m_submodule_name(submodule_name), m_module_id(module_id),
m_data_cfg(data_cfg), m_indata_iocs(0),
m_submodule_plugged(false) m_outdata_iops(0),
m_submodule_ptr(nullptr)
{ {
} }
@ -17,15 +15,17 @@ bool ProfinetSubslot::pullSubmodule(ProfinetServiceData& pnet_data)
{ {
int result = pnet_pull_submodule (pnet_data.pnet_ptr, pnet_data.api, m_slot_nbr, m_subslot_nbr); int result = pnet_pull_submodule (pnet_data.pnet_ptr, pnet_data.api, m_slot_nbr, m_subslot_nbr);
m_submodule_plugged = false; /// Очищаем указатель на подмодуль
m_submodule_ptr = nullptr;
return (result == 0); return (result == 0);
} }
bool ProfinetSubslot::plugSubmodule(ProfinetServiceData& pnet_data) bool ProfinetSubslot::plugSubmodule(ProfinetServiceData& pnet_data, std::shared_ptr<ProfinetSubmodule>& submodule_ptr)
{ {
/// Сначала отключаем подмодуль /// Сначала отключаем подмодуль
pullSubmodule(pnet_data); pullSubmodule(pnet_data);
/// Подключаем подмодуль /// Подключаем подмодуль
int result = pnet_plug_submodule ( int result = pnet_plug_submodule (
pnet_data.pnet_ptr, pnet_data.pnet_ptr,
@ -33,29 +33,15 @@ bool ProfinetSubslot::plugSubmodule(ProfinetServiceData& pnet_data)
m_slot_nbr, m_slot_nbr,
m_subslot_nbr, m_subslot_nbr,
m_module_id, m_module_id,
m_submodule_id, submodule_ptr->m_id,
m_data_cfg.data_dir, submodule_ptr->m_data_cfg.data_dir,
m_data_cfg.insize, submodule_ptr->m_data_cfg.insize,
m_data_cfg.outsize); submodule_ptr->m_data_cfg.outsize);
m_submodule_plugged = (result == 0); if (result == 0)
return m_submodule_plugged;
}
bool ProfinetSubslot::addParameter(std::shared_ptr<ProfinetParameter>& param)
{
auto ret = m_params.emplace(param->index, param);
return ret.second;
}
ProfinetParameter * ProfinetSubslot::getParameterPtr(uint32_t Index)
{
if (!m_params.count(Index))
{ {
return nullptr; m_submodule_ptr = submodule_ptr;
} }
return m_params[Index].get(); return (m_submodule_ptr != nullptr);
} }

View File

@ -1,65 +1,42 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <string>
#include "profinet_serv_data.hpp"
#include "profinet_parameter.hpp"
#include "../../libs/include/pnet_api.h"
#include <map> #include <map>
#include <memory> #include <memory>
/** #include "../../libs/include/pnet_api.h"
* Callback for updated cyclic data
* #include "profinet_serv_data.hpp"
* @param subslot InOut: Subslot structure #include "profinet_submodule.hpp"
* @param tag InOut: Typically a handle to a submodule
*/
typedef void (*ProfinetSubslotCallback) (void * subslot, void * tag);
class ProfinetSubslot class ProfinetSubslot
{ {
public: public:
ProfinetSubslot(uint16_t subslot_nbr, ProfinetSubslot(uint16_t subslot_nbr) : m_subslot_nbr(subslot_nbr) {};
uint32_t submodule_id,
std::string submodule_name,
pnet_data_cfg_t data_cfg);
bool plugSubmodule(ProfinetServiceData& pnet_data); ProfinetSubslot(uint16_t subslot_nbr, uint16_t slot_nbr, uint32_t module_id);
bool plugSubmodule(ProfinetServiceData& pnet_data, std::shared_ptr<ProfinetSubmodule>& submodule_ptr);
bool pullSubmodule(ProfinetServiceData& pnet_data); bool pullSubmodule(ProfinetServiceData& pnet_data);
bool addParameter(std::shared_ptr<ProfinetParameter>& param);
ProfinetParameter * getParameterPtr(uint32_t Index);
void setSlotNumber(uint16_t slot_nbr) { m_slot_nbr = slot_nbr; }; void setSlotNumber(uint16_t slot_nbr) { m_slot_nbr = slot_nbr; };
void setModuleId(uint16_t module_id) { m_module_id = module_id; }; void setModuleId(uint16_t module_id) { m_module_id = module_id; };
std::shared_ptr<ProfinetSubmodule> getSubmodulePtr() { return m_submodule_ptr; };
public: public:
/// Номер подслота /// Номер подслота
const uint16_t m_subslot_nbr; const uint16_t m_subslot_nbr;
/// Идентификатор подмодуля который вставлен в данный подслот
const uint32_t m_submodule_id;
/// Имя этого подмодуля
const std::string m_submodule_name;
/// Конфигурация данных подмодуля (направление данных, размер данных)
const pnet_data_cfg_t m_data_cfg;
private: private:
/// Флаг подключения подмодуля к подслоту
bool m_submodule_plugged;
/// Номер слота куда входит данный подслот /// Номер слота куда входит данный подслот
uint16_t m_slot_nbr; uint16_t m_slot_nbr;
/// Идентификатор модуля куда входит подключаемый подмодуль /// Идентификатор модуля куда входит подключаемый подмодуль
uint16_t m_module_id; uint32_t m_module_id;
/// iocs = I/O consumer status data (формат данных из pnet_ioxs_values_t) /// iocs = I/O consumer status data (формат данных из pnet_ioxs_values_t)
uint8_t m_indata_iocs; uint8_t m_indata_iocs;
@ -67,13 +44,8 @@ private:
/// iops = I/O provider status data (формат данных из pnet_ioxs_values_t) /// iops = I/O provider status data (формат данных из pnet_ioxs_values_t)
uint8_t m_outdata_iops; uint8_t m_outdata_iops;
std::map<uint32_t, std::shared_ptr<ProfinetParameter>> m_params; /// Подмодуль вставленный в этот подслот
std::shared_ptr<ProfinetSubmodule> m_submodule_ptr;
/** Callback for cyclic input- or output data, or NULL if not implemented */
ProfinetSubslotCallback m_cyclic_callback;
/// данные передающиеся в cyclic_callback вторым параметром.
void * m_tag;
}; };