From 85eff4f7cd45d8f50957e81164d7152f7cf7a92e Mon Sep 17 00:00:00 2001 From: Vadim Sychev Date: Thu, 21 Jul 2022 17:00:41 +0300 Subject: [PATCH] =?UTF-8?q?dev(UML-981):=20=D0=9F=D0=B5=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=B0=D0=BD=D0=B0=20=D0=B0=D1=80=D1=85=D0=B8=D1=82?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D1=83=D1=80=D0=B0=20=D0=BE=D1=82=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=B4=D1=83=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Как оказалось, номера слотов и подслотов назначает profinet контроллер и номера эти зависят от того в каком порядке модули были добавлены в проекте plc, например в codesys. Теперь в ПО при старте конфигурируются не слоты и подслоты, а модули и подмодули которые оно поддерживает, а слоты и подслоты куда будут вставляться эти модули и подмодули определяются позже профинет контроллером при установлени связи. --- src/main.cpp | 2 + src/profinet/profinet.cmake | 2 + src/profinet/profinet.cpp | 347 ++++++++++++++++------------ src/profinet/profinet.hpp | 126 ++++++++-- src/profinet/profinet_module.cpp | 25 ++ src/profinet/profinet_module.hpp | 26 +++ src/profinet/profinet_parameter.hpp | 19 ++ src/profinet/profinet_slot.cpp | 80 +++---- src/profinet/profinet_slot.hpp | 52 ++--- src/profinet/profinet_submodule.cpp | 28 +++ src/profinet/profinet_submodule.hpp | 31 +++ src/profinet/profinet_subslot.cpp | 52 ++--- src/profinet/profinet_subslot.hpp | 58 ++--- 13 files changed, 543 insertions(+), 305 deletions(-) create mode 100644 src/profinet/profinet_module.cpp create mode 100644 src/profinet/profinet_module.hpp create mode 100644 src/profinet/profinet_parameter.hpp create mode 100644 src/profinet/profinet_submodule.cpp create mode 100644 src/profinet/profinet_submodule.hpp diff --git a/src/main.cpp b/src/main.cpp index b0226be..cce6065 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,5 +57,7 @@ int main(int argc, char * argv[]) if (!profinet.Config(settings, profinet_settings)) return 0; + /// Тестовый слот и модуль ECHO: module_id = 0x40 + return 0; } \ No newline at end of file diff --git a/src/profinet/profinet.cmake b/src/profinet/profinet.cmake index a11d898..f99ff80 100644 --- a/src/profinet/profinet.cmake +++ b/src/profinet/profinet.cmake @@ -3,6 +3,8 @@ set(SRC_FILES ${SRC_FILES} ./profinet/profinet.cpp ./profinet/profinet_slot.cpp ./profinet/profinet_subslot.cpp + ./profinet/profinet_module.cpp + ./profinet/profinet_submodule.cpp ./profinet/profinet_cb_alarm_ack_cnf.cpp ./profinet/profinet_cb_alarm_cnf.cpp ./profinet/profinet_cb_alarm_ind.cpp diff --git a/src/profinet/profinet.cpp b/src/profinet/profinet.cpp index d3ff902..5f8b4d6 100644 --- a/src/profinet/profinet.cpp +++ b/src/profinet/profinet.cpp @@ -152,6 +152,7 @@ Profinet::Profinet(void) : m_pnet_data({nullptr, 0}) bool Profinet::Config(ProfinetSettings& Settings, ProfinetDeviceSettings& DevSettings) { + bool ret = true; pnet_cfg_t pnet_cfg = {0}; utils_netif_namelist_t netif_name_list; uint16_t number_of_ports = 1; @@ -185,58 +186,33 @@ bool Profinet::Config(ProfinetSettings& Settings, ProfinetDeviceSettings& DevSet if (m_pnet_data.pnet_ptr == nullptr) return false; - /** - * @brief Создаем стандартный слот для модуля DAP 1 (Device Access Point) - * Это обязательный модуль для profinet device - */ - auto dap_slot = make_shared(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 }; - - /** - * @brief Создаем стандартный подслот для подмодуля identity 1 который входит в модуль DAP 1 - * Это обязательный подслот для profinet device - */ - auto dap_subslot_identity_1 = make_shared( PNET_SUBSLOT_DAP_IDENT, - PNET_SUBMOD_DAP_IDENT, - "DAP Identity 1", - dap_data_cfg ); - /** - * @brief Создаем стандартный подслот для подмодуля iface 1 ident который входит в модуль DAP 1 - * Это обязательный подслот для profinet device - */ - auto dap_subslot_iface_1_ident = make_shared( 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( 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 false; - - if (!dap_slot->addSubslotAndPlugSubmodule(m_pnet_data, dap_subslot_iface_1_port1_ident)) - return false; + /// Создаем обязательный модуль DAP + auto dap_module = make_shared(PNET_MOD_DAP_IDENT, "DAP 1"); + /// Создаем обязательный подмодуль DAP Identity 1 + auto dap_submodule_indent_1 = make_shared(PNET_SUBMOD_DAP_IDENT, "DAP Identity 1", dap_data_cfg); + /// Создаем обязательный подмодуль DAP IFACE1 IDENT + auto dap_submodule_iface_1_indent_1 = make_shared(PNET_SUBMOD_DAP_INTERFACE_1_IDENT, "DAP IFACE1 IDENT", dap_data_cfg); + /// Создаем обязательный подмодуль DAP Port 1 + auto dap_subslot_iface_1_port1_ident = make_shared(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 + ret&= addSlotAndPlugModule(PNET_SLOT_DAP_IDENT, dap_module); + /// Добавляем подслоты к слоту и подключаем к подслоту подмодуль + /// 1. Подмодуль "DAP Identity 1" + ret&= addSubslotAndPlugSubmodule(PNET_SLOT_DAP_IDENT, PNET_SUBSLOT_DAP_IDENT, dap_submodule_indent_1); + /// 2. Подмодуль "DAP IFACE1 IDENT" + ret&= addSubslotAndPlugSubmodule(PNET_SLOT_DAP_IDENT, PNET_SUBSLOT_DAP_INTERFACE_1_IDENT, dap_submodule_iface_1_indent_1); + /// 3. Подмодуль "DAP Port 1" + ret&= addSubslotAndPlugSubmodule(PNET_SLOT_DAP_IDENT, PNET_SUBSLOT_DAP_INTERFACE_1_PORT_1_IDENT, dap_subslot_iface_1_port1_ident); - return true; + return ret; } bool Profinet::addSlot(std::shared_ptr& slot_ptr) @@ -249,36 +225,146 @@ bool Profinet::addSlot(std::shared_ptr& slot_ptr) return true; } -bool Profinet::addSlotAndPlugModule(std::shared_ptr& slot_ptr) +std::shared_ptr Profinet::addSlot(uint16_t slot_nbr) { - if (!addSlot(slot_ptr)) - return false; - - if (!slot_ptr->plugModule(m_pnet_data)) - return false; - - return true; -} + std::shared_ptr slot_ptr(nullptr); -ProfinetSlot * Profinet::getSlotPtrAndCheckModule(uint16_t slot_nbr, uint32_t module_id) -{ - ProfinetSlot * const slot_ptr = getSlotPtr(slot_nbr); - - if (slot_ptr == nullptr) + if (m_slots.count(slot_nbr)) { - return nullptr; + slot_ptr = m_slots[slot_nbr]; + } + else + { + slot_ptr = make_shared(slot_nbr); } - /// 2. Проверить, что в слоте slot идентификатор модуля m_module_id совпадает с module_ident - if (slot_ptr->m_module_id != module_id) + if (slot_ptr != nullptr) { - return nullptr; + m_slots[slot_nbr] = slot_ptr; } return slot_ptr; } -ProfinetSlot * Profinet::getSlotPtr(uint16_t slot_nbr) +bool Profinet::addModule(std::shared_ptr& module_ptr) +{ + if (module_ptr == nullptr) + return false; + + m_modules[module_ptr->m_id] = module_ptr; + + return true; +} + +std::shared_ptr 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& 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& 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 Profinet::getSlotPtr(uint16_t slot_nbr) { /// 1. Проверить, что слот slot добавлен в конфигурацию if (!m_slots.count(slot_nbr)) @@ -286,12 +372,12 @@ ProfinetSlot * Profinet::getSlotPtr(uint16_t slot_nbr) 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 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) { @@ -301,6 +387,34 @@ ProfinetSubslot * Profinet::getSubslotPtr(uint16_t slot_nbr, uint16_t subslot_nb return slot_ptr->getSubslotPtr(subslot_nbr); } +std::shared_ptr 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 @@ -366,18 +480,8 @@ int Profinet::callbackReadInd ( uint32_t arep, uint16_t * p_read_length, pnet_result_t * p_result) { - ProfinetSubslot * const subslot_ptr = getSubslotPtr(slot_nbr, subslot_nbr); - - 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); + ///1. Проверяем, что у подмодуля есть параметр с индексом idx + auto param_ptr = getSubmoduleParameter(slot_nbr, subslot_nbr, idx); if (param_ptr == nullptr) { @@ -388,6 +492,7 @@ int Profinet::callbackReadInd ( uint32_t arep, return -1; } + ///2. Проверяем корректность длины данных (меньше быть не должно, если больше - это норм) if (*p_read_length < param_ptr->length) { p_result->pnio_status.error_code = PNET_ERROR_CODE_READ; @@ -397,6 +502,7 @@ int Profinet::callbackReadInd ( uint32_t arep, return -1; } + ///3. Передаем данные параметра *pp_read_data = param_ptr->data_ptr; *p_read_length = param_ptr->length; @@ -411,29 +517,19 @@ int Profinet::callbackWriteInd ( uint32_t arep, uint16_t write_length, const uint8_t * p_write_data, pnet_result_t * p_result) -{ - ProfinetSubslot * const subslot_ptr = getSubslotPtr(slot_nbr, subslot_nbr); - - 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); +{ + ///1. Проверяем, что у подмодуля есть параметр с индексом idx + auto param_ptr = getSubmoduleParameter(slot_nbr, subslot_nbr, idx); if (param_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; } - + ///2. Проверяем корректность длины данных if (write_length != param_ptr->length) { p_result->pnio_status.error_code = PNET_ERROR_CODE_WRITE; @@ -443,7 +539,7 @@ int Profinet::callbackWriteInd ( uint32_t arep, return -1; } - /// + ///3. Копируем данные std::memcpy(param_ptr->data_ptr, p_write_data, param_ptr->length); return 0; @@ -451,23 +547,13 @@ int Profinet::callbackWriteInd ( uint32_t arep, int Profinet::callbackExpModuleInd ( uint16_t slot, uint32_t module_ident) { - ProfinetSlot * const slot_ptr = getSlotPtrAndCheckModule(slot, module_ident); - /** - * @brief Проверка, что слот slot добавлен в конфигурацию и что - * идентификатор модуля m_module_id совпадает с module_ident - * - */ - if (slot_ptr == nullptr) + bool ret = addSlotAndPlugModule(slot, module_ident); + + if (ret == false) { return -1; } - - /// Подключить модуль в слот - if (!slot_ptr->plugModule(m_pnet_data)) - { - return -1; - } - + return 0; } @@ -477,42 +563,13 @@ int Profinet::callbackExpSubmoduleInd ( uint16_t slot, uint32_t submodule_id, const pnet_data_cfg_t * p_exp_data) { - ProfinetSlot * const slot_ptr = getSlotPtrAndCheckModule(slot, module_id); - /** - * @brief Проверка, что слот slot добавлен в конфигурацию и что - * идентификатор модуля m_module_id совпадает с module_ident - * - */ - if (slot_ptr == nullptr) - { - return -1; - } - - /// Проверка, что модуль подключен к слоту - if (!slot_ptr->isModulePlugged()) - { - return -1; - } - - ProfinetSubslot * const subslot_ptr = slot_ptr->getSubslotPtrAndCheckSubmodule(subslot, submodule_id, p_exp_data); + bool ret = addSubslotAndPlugSubmodule(slot, subslot, module_id, submodule_id, p_exp_data); - /** - * Проверка того, что: - * - подслот subslot добавлен в конфигурацию слота, - * - идентификатор модуля подслота m_module_id совпадает с submodule_id - * - конфигурация данных слота совпадает с p_exp_data - */ - if (subslot_ptr == nullptr) + if (ret == false) { return -1; } - /// Подключить подмодуль submodule_id к подслоту subslot - if (!subslot_ptr->plugSubmodule(m_pnet_data)) - { - return -1; - } - return 0; } diff --git a/src/profinet/profinet.hpp b/src/profinet/profinet.hpp index db48b10..2c40b74 100644 --- a/src/profinet/profinet.hpp +++ b/src/profinet/profinet.hpp @@ -14,38 +14,136 @@ public: bool Config(ProfinetSettings& Settings, ProfinetDeviceSettings& DevSettings); + /** + * @brief Добавляет ранее созданный слот slot_ptr + * + * @param slot_ptr слот + * @return true слот добавлен + * @return false слот не был добавлен + */ bool addSlot(std::shared_ptr& slot_ptr); - bool addSlotAndPlugModule(std::shared_ptr& slot_ptr); + /** + * @brief Если слот с номером slot_nbr еще не добавлен, то создает слот и добавляет его + * + * @param slot_nbr номер слота + * @return указатель на слот + */ + std::shared_ptr 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& 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& 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& module_ptr); + + /** + * @brief геттер модуля + * + * @param module_id идентификатор модуля + * @return std::shared_ptr возвращает указатель на модуль или nullptr если такого модуля нет в \a m_modules + */ + std::shared_ptr 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 указатель на параметр или nullptr + */ + std::shared_ptr getSubmoduleParameter(uint16_t slot_nbr, uint16_t subslot_nbr, uint32_t param_index); private: ProfinetServiceData m_pnet_data; /** - * @brief Ключ - идентификатор модуля, Значение - структура слота + * @brief Ключ - номер слота, Значение - указатель на слот * */ std::map> m_slots; + /** + * @brief Ключ - идентиикатор модуля, Значение - указатель на модуль + * + */ + std::map> m_modules; 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 в конфигурации * * @param slot_nbr номер слота * @return ProfinetSlot* - указатель на слот, при успехе или nullptr есои слот в конфигурации отсутсвует */ - ProfinetSlot * getSlotPtr(uint16_t slot_nbr); + std::shared_ptr getSlotPtr(uint16_t slot_nbr); - ProfinetSubslot * getSubslotPtr(uint16_t slot_nbr, uint16_t subslot_nbr); + std::shared_ptr getSubslotPtr(uint16_t slot_nbr, uint16_t subslot_nbr); public: /** diff --git a/src/profinet/profinet_module.cpp b/src/profinet/profinet_module.cpp new file mode 100644 index 0000000..f9a0c43 --- /dev/null +++ b/src/profinet/profinet_module.cpp @@ -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& submodule_ptr) +{ + auto ret = m_submodules.emplace(submodule_ptr->m_id, submodule_ptr); + + return ret.second; +} + +std::shared_ptr ProfinetModule::getSubmodulePtr(uint32_t submodule_id) +{ + if (!m_submodules.count(submodule_id)) + { + return nullptr; + } + + return m_submodules[submodule_id]; +} \ No newline at end of file diff --git a/src/profinet/profinet_module.hpp b/src/profinet/profinet_module.hpp new file mode 100644 index 0000000..5a4bbaf --- /dev/null +++ b/src/profinet/profinet_module.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include + +#include "profinet_submodule.hpp" + + +class ProfinetModule { +public: + ProfinetModule(uint32_t module_id, std::string module_name); + + bool addSubmodule(std::shared_ptr& submodule_ptr); + + std::shared_ptr getSubmodulePtr(uint32_t submodule_id); + +public: + const uint32_t m_id; /// module id + const std::string m_name; /// module name + +private: + /// Набор поддерживаемых подмодулей + std::map> m_submodules; +}; \ No newline at end of file diff --git a/src/profinet/profinet_parameter.hpp b/src/profinet/profinet_parameter.hpp new file mode 100644 index 0000000..416cdfc --- /dev/null +++ b/src/profinet/profinet_parameter.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include + +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; /// длина параметра в байтах +}; diff --git a/src/profinet/profinet_slot.cpp b/src/profinet/profinet_slot.cpp index 8348d69..9beb247 100644 --- a/src/profinet/profinet_slot.cpp +++ b/src/profinet/profinet_slot.cpp @@ -1,11 +1,8 @@ #include "profinet_slot.hpp" -ProfinetSlot::ProfinetSlot ( uint16_t slot_nbr, - uint32_t module_id, - std::string module_name) : m_slot_nbr(slot_nbr), - m_module_id(module_id), - m_module_name(module_name) - +ProfinetSlot::ProfinetSlot ( uint16_t slot_nbr ) : + m_slot_nbr(slot_nbr), + m_module_ptr(nullptr) { } @@ -15,76 +12,65 @@ bool ProfinetSlot::pullModule(ProfinetServiceData& pnet_data) { 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); } -bool ProfinetSlot::plugModule(ProfinetServiceData& pnet_data) +bool ProfinetSlot::plugModule(ProfinetServiceData& pnet_data, std::shared_ptr& module_ptr) { /// Сначала отключаем модуль 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& subslot_ptr) { if (subslot_ptr == nullptr) return false; + + if (m_module_ptr == nullptr) + return false; 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; } - -bool ProfinetSlot::addSubslotAndPlugSubmodule(ProfinetServiceData& pnet_data, std::shared_ptr& subslot_ptr) +std::shared_ptr ProfinetSlot::addSubslot(uint16_t subslot_nbr) { - if (!addSubslot(subslot_ptr)) - return false; - - if (!subslot_ptr->plugSubmodule(pnet_data)) - return false; - - return true; -} + std::shared_ptr subslot_ptr(nullptr); -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) + if (m_subslots.count(subslot_nbr)) { - return nullptr; + subslot_ptr = m_subslots[subslot_nbr]; + } + else + { + subslot_ptr = std::make_shared(subslot_nbr); } - /// Проверка совпадения идентификатора подмодуля - if (subslot_ptr->m_submodule_id != submodule_id) + if (subslot_ptr != nullptr) { - return nullptr; - } - /// Проверка совпадения конфигурации данных - 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; + m_subslots[subslot_nbr] = subslot_ptr; } return subslot_ptr; } -ProfinetSubslot * ProfinetSlot::getSubslotPtr(uint16_t subslot_nbr) +std::shared_ptr ProfinetSlot::getSubslotPtr(uint16_t subslot_nbr) { /// Проверка наличия подслота в конфигурации if (!m_subslots.count(subslot_nbr)) @@ -92,5 +78,11 @@ ProfinetSubslot * ProfinetSlot::getSubslotPtr(uint16_t subslot_nbr) return nullptr; } - return m_subslots[subslot_nbr].get(); -} \ No newline at end of file + return m_subslots[subslot_nbr]; +} + +std::shared_ptr ProfinetSlot::getModulePtr() +{ + return m_module_ptr; +} + diff --git a/src/profinet/profinet_slot.hpp b/src/profinet/profinet_slot.hpp index 251e970..5791988 100644 --- a/src/profinet/profinet_slot.hpp +++ b/src/profinet/profinet_slot.hpp @@ -1,12 +1,12 @@ #pragma once +#include +#include +#include + #include "profinet_serv_data.hpp" #include "profinet_subslot.hpp" - -#include -#include -#include -#include +#include "profinet_module.hpp" class ProfinetSlot { @@ -15,14 +15,8 @@ public: * @brief Construct a new Profinet Slot object * * @param slot_nbr номер слота - * @param module_id идентификатор модуля который может поключиться к этому слоту - * @param module_name имя модуля */ - ProfinetSlot ( - uint16_t slot_nbr, - uint32_t module_id, - std::string module_name - ); + ProfinetSlot(uint16_t slot_nbr); /** * @brief Подключает модуль к слоту * @@ -30,7 +24,7 @@ public: * @return true модуль подключен * @return false модуль не подключен */ - bool plugModule(ProfinetServiceData& pnet_data); + bool plugModule(ProfinetServiceData& pnet_data, std::shared_ptr& module_ptr); /** * @brief Отключает модуль от слота * @@ -40,29 +34,35 @@ public: */ bool pullModule(ProfinetServiceData& pnet_data); + /** + * @brief Добавляет ранее созданный подслот subslot_ptr + * + * @param subslot_ptr подслот + * @return true подслот добавлен + * @return false подслот был добавлен ранее + */ bool addSubslot(std::shared_ptr& subslot_ptr); - bool addSubslotAndPlugSubmodule(ProfinetServiceData& pnet_data, std::shared_ptr& subslot_ptr); + /** + * @brief Если подслот с номером subslot_nbr еще не добавлен, то создает подслот и добавляет его + * + * @param subslot_nbr номер подслота + * @return std::shared_ptr указатель на подслот + */ + std::shared_ptr addSubslot(uint16_t subslot_nbr); - bool isModulePlugged() { return m_module_plugged; } + std::shared_ptr getSubslotPtr(uint16_t subslot_nbr); - ProfinetSubslot * getSubslotPtrAndCheckSubmodule(uint16_t subslot_nbr, uint32_t submodule_id, const pnet_data_cfg_t * const p_data_cfg); - - ProfinetSubslot * getSubslotPtr(uint16_t subslot_nbr); + std::shared_ptr getModulePtr(); public: /// Номер слота const uint16_t m_slot_nbr; - /// Идентификатор модуля который может быть подключен к данному слоту - const uint32_t m_module_id; - - /// Имя подключаемого модуля - const std::string m_module_name; - private: - /// Флаг подключения модуля к слоту - bool m_module_plugged; + /// Модуль вставленный в этот слот + std::shared_ptr m_module_ptr; + /// множество подслотов std::map> m_subslots; }; diff --git a/src/profinet/profinet_submodule.cpp b/src/profinet/profinet_submodule.cpp new file mode 100644 index 0000000..7a6e021 --- /dev/null +++ b/src/profinet/profinet_submodule.cpp @@ -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& param) +{ + auto ret = m_params.emplace(param->index, param); + + return ret.second; +} + +std::shared_ptr ProfinetSubmodule::getParameterPtr(uint32_t index) +{ + if (!m_params.count(index)) + { + return nullptr; + } + + return m_params[index]; +} \ No newline at end of file diff --git a/src/profinet/profinet_submodule.hpp b/src/profinet/profinet_submodule.hpp new file mode 100644 index 0000000..d99a43d --- /dev/null +++ b/src/profinet/profinet_submodule.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include +#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& param); + + std::shared_ptr 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> m_params; + +}; \ No newline at end of file diff --git a/src/profinet/profinet_subslot.cpp b/src/profinet/profinet_subslot.cpp index 0174d22..3d83764 100644 --- a/src/profinet/profinet_subslot.cpp +++ b/src/profinet/profinet_subslot.cpp @@ -1,14 +1,12 @@ #include "profinet_subslot.hpp" -ProfinetSubslot::ProfinetSubslot(uint16_t subslot_nbr, - uint32_t submodule_id, - std::string submodule_name, - pnet_data_cfg_t data_cfg) : - m_subslot_nbr(subslot_nbr), - m_submodule_id(submodule_id), - m_submodule_name(submodule_name), - m_data_cfg(data_cfg), - m_submodule_plugged(false) +ProfinetSubslot::ProfinetSubslot(uint16_t subslot_nbr, uint16_t slot_nbr, uint32_t module_id) : + m_subslot_nbr(subslot_nbr), + m_slot_nbr(slot_nbr), + m_module_id(module_id), + m_indata_iocs(0), + m_outdata_iops(0), + m_submodule_ptr(nullptr) { } @@ -16,16 +14,18 @@ ProfinetSubslot::ProfinetSubslot(uint16_t subslot_nbr, bool ProfinetSubslot::pullSubmodule(ProfinetServiceData& pnet_data) { 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); } -bool ProfinetSubslot::plugSubmodule(ProfinetServiceData& pnet_data) +bool ProfinetSubslot::plugSubmodule(ProfinetServiceData& pnet_data, std::shared_ptr& submodule_ptr) { /// Сначала отключаем подмодуль pullSubmodule(pnet_data); + /// Подключаем подмодуль int result = pnet_plug_submodule ( pnet_data.pnet_ptr, @@ -33,29 +33,15 @@ bool ProfinetSubslot::plugSubmodule(ProfinetServiceData& pnet_data) m_slot_nbr, m_subslot_nbr, m_module_id, - m_submodule_id, - m_data_cfg.data_dir, - m_data_cfg.insize, - m_data_cfg.outsize); + submodule_ptr->m_id, + submodule_ptr->m_data_cfg.data_dir, + submodule_ptr->m_data_cfg.insize, + submodule_ptr->m_data_cfg.outsize); - m_submodule_plugged = (result == 0); - - return m_submodule_plugged; -} - -bool ProfinetSubslot::addParameter(std::shared_ptr& param) -{ - auto ret = m_params.emplace(param->index, param); - - return ret.second; -} - -ProfinetParameter * ProfinetSubslot::getParameterPtr(uint32_t Index) -{ - if (!m_params.count(Index)) + if (result == 0) { - return nullptr; + m_submodule_ptr = submodule_ptr; } - return m_params[Index].get(); + return (m_submodule_ptr != nullptr); } \ No newline at end of file diff --git a/src/profinet/profinet_subslot.hpp b/src/profinet/profinet_subslot.hpp index bf8830f..7b43d84 100644 --- a/src/profinet/profinet_subslot.hpp +++ b/src/profinet/profinet_subslot.hpp @@ -1,65 +1,42 @@ #pragma once #include -#include - -#include "profinet_serv_data.hpp" -#include "profinet_parameter.hpp" -#include "../../libs/include/pnet_api.h" #include #include -/** - * Callback for updated cyclic data - * - * @param subslot InOut: Subslot structure - * @param tag InOut: Typically a handle to a submodule - */ -typedef void (*ProfinetSubslotCallback) (void * subslot, void * tag); +#include "../../libs/include/pnet_api.h" + +#include "profinet_serv_data.hpp" +#include "profinet_submodule.hpp" + class ProfinetSubslot { public: - ProfinetSubslot(uint16_t subslot_nbr, - uint32_t submodule_id, - std::string submodule_name, - pnet_data_cfg_t data_cfg); + ProfinetSubslot(uint16_t subslot_nbr) : m_subslot_nbr(subslot_nbr) {}; + + ProfinetSubslot(uint16_t subslot_nbr, uint16_t slot_nbr, uint32_t module_id); - bool plugSubmodule(ProfinetServiceData& pnet_data); + bool plugSubmodule(ProfinetServiceData& pnet_data, std::shared_ptr& submodule_ptr); bool pullSubmodule(ProfinetServiceData& pnet_data); - bool addParameter(std::shared_ptr& param); - - ProfinetParameter * getParameterPtr(uint32_t Index); - void setSlotNumber(uint16_t slot_nbr) { m_slot_nbr = slot_nbr; }; void setModuleId(uint16_t module_id) { m_module_id = module_id; }; + std::shared_ptr getSubmodulePtr() { return m_submodule_ptr; }; + public: /// Номер подслота - 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; + const uint16_t m_subslot_nbr; private: - - /// Флаг подключения подмодуля к подслоту - bool m_submodule_plugged; - /// Номер слота куда входит данный подслот 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) uint8_t m_indata_iocs; @@ -67,13 +44,8 @@ private: /// iops = I/O provider status data (формат данных из pnet_ioxs_values_t) uint8_t m_outdata_iops; - std::map> m_params; - - /** Callback for cyclic input- or output data, or NULL if not implemented */ - ProfinetSubslotCallback m_cyclic_callback; - - /// данные передающиеся в cyclic_callback вторым параметром. - void * m_tag; + /// Подмодуль вставленный в этот подслот + std::shared_ptr m_submodule_ptr; };