create or replace package UDO_PKG_EQUIPDS_SEND is /* Описание: Обеспечивает формироание и отправку тела запроса. Проект: Интеграция ПП «Парус 8» и «Фреймворка оценки и прогнозирования состояния оборудования» Разработчик: ЦИТК-ПАРУС Отественный: Селианов А.Е. Дата последнего изменения: 24.03.2025 */ /* Константы */ SDEF_SEND_POINT_PRM constant PKG_STD.tSTRING := 'EXSService_AppServer'; -- Адрес сервера приложений (сервисы обмена) /* отправка запроса */ procedure SEND_PACKGE ( NEXSSERVICEFN in number, -- Рег. номер функции обработки NLNK_NEXSQUEUE in number default null, -- Рег.номер сязанной очереди NCOMPANY in number := null, -- Рег. номер связанной организации NDOCUMENT in number := null, -- Рег. номер связанной записи документа SUNITCODE in varchar2 := null, -- Код связанного раздела SHOST in varchar2 := null, -- host SPORT in varchar2 := null, -- port SUSER in varchar2 := null, -- username SPASS in varchar2 := null, -- password bAUTH in boolean := false, -- Требуется авторизация SPATCH_LOKAL in varchar2 := null, -- Путь размещения файла на локальном сервере NEQUIPDSCMN in number := null, -- Рег. номер класса оборудования выборки данных SPATCH_FSERV in varchar2 := null, -- Путь размещения файла на сервере CSP SDESCR in varchar2 := null, -- Описание выборки данных NPRIORITY in number default 0, -- Приоритет (0- поумолчанию; 100- наиысший приоритет) BMSG in blob -- Загружаемый XML с данными запроса в СКУД; ); /* Подготока данных для Загрузки файла на SCP */ procedure SCP_DATA_MAKE ( NEXSSERVICEFN in number, -- Рег. номер функции обработки SHOST out varchar2, -- host SPORT out varchar2, -- port SUSER out varchar2, -- username SPASS out varchar2, -- password --SPATCH_LOKAL out varchar2, -- Путь размещения файла на локальном сервере SPATCH_FSERV out varchar2 -- Путь размещения файла на сервере CSP ); /* Подготока данных для Загрузки файла на Фреймворк */ procedure AUTH_DATA_MAKE ( NEXSSERVICEFN in number, -- Рег. номер функции обработки sAUTH out varchar2 -- Данные авторизции ("Authorization Basic base64(login:pass)) ); /* Подготока данных для для передачи внешней системе */ procedure METADATA_MAKE ( NIDENT in number, -- Идентификатор Selectlis NEQUIPDSCM in number, -- регистрационный номер записи Выборки данных класса оборудования» NDATASET_ID out number, -- DATASET_ID BXML out blob -- Тело файла ); /* Подготока данных для передачи Фреймворку запроса на обучение модели */ procedure REQUIREMENTS_MAKE ( NEQUIPDSCMML in number, -- регистрационный номер записи Выборки Модели» BXML out blob -- Тело файла ); end UDO_PKG_EQUIPDS_SEND; / create or replace package body UDO_PKG_EQUIPDS_SEND is /* Получение URL для обработки результата */ function GET_URL_END_POINT ( NEXSSERVICEFN in varchar2 -- Мнемокод функции сервиса обмена )return varchar2 -- URL для обработки результата is REXSSERVICEFN EXSSERVICEFN%rowtype; -- REXSSERVICE EXSSERVICE%rowtype; -- Запись сервиса обмена SURL PKG_STD.tSTRING; -- Адрес сервера приложений (сервисы обмена) begin /* Считывание записи функции сервиса обмена */ REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => NEXSSERVICEFN); /* Считывание записи сервиса обмена */ REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN); /*Считывание параметра - Адрес сервера приложений (сервисы обмена)*/ SURL := get_options_str(sCODE => SDEF_SEND_POINT_PRM, nCOMP_VERS => null ); /* Формирование полного URL END_POINT */ SURL := SURL||REXSSERVICE.SRV_ROOT||'/'||REXSSERVICEFN.FN_URL; return SURL; end GET_URL_END_POINT; /* отправка запроса */ procedure SEND_PACKGE ( NEXSSERVICEFN in number, -- Рег. номер функции обработки NLNK_NEXSQUEUE in number default null, -- Рег.номер сязанной очереди NCOMPANY in number := null, -- Рег. номер связанной организации NDOCUMENT in number := null, -- Рег. номер связанной записи документа SUNITCODE in varchar2 := null, -- Код связанного раздела SHOST in varchar2 := null, -- host SPORT in varchar2 := null, -- port SUSER in varchar2 := null, -- username SPASS in varchar2 := null, -- password bAUTH in boolean := false, -- Требуется авторизация SPATCH_LOKAL in varchar2 := null, -- Путь размещения файла на локальном сервере NEQUIPDSCMN in number := null, -- Рег. номер класса оборудования выборки данных SPATCH_FSERV in varchar2 := null, -- Путь размещения файла на сервере CSP SDESCR in varchar2 := null, -- Описание выборки данных NPRIORITY in number default 0, -- Приоритет (0- поумолчанию; 100- наиысший приоритет) BMSG in blob -- Загружаемый XML с данными запроса в СКУД; ) is NQ PKG_STD.TREF; -- Рег. номер очереди обмена OPTS PKG_EXS.TOPTIONS; -- Параметры запроса HDR_HEADERS PKG_EXS.TOPTIONS; -- Заголоок запроса sAUTH PKG_STD.tLSTRING; -- Строка аторизации begin PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => 'NEXSSERVICEFN', SVALUE => NEXSSERVICEFN); if SHOST is not null then PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => 'SHOST_SCP', SVALUE => SHOST); end if; if SPORT is not null then PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => 'SPORT_SCP', SVALUE => SPORT); end if; if SUSER is not null then PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => 'SUSER_SCP', SVALUE => SUSER); end if; if SPASS is not null then PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => 'SPASS_SCP', SVALUE => SPASS); end if; if (bAUTH) then AUTH_DATA_MAKE(NEXSSERVICEFN => NEXSSERVICEFN, sAUTH => sAUTH); if sAUTH is not null then /* authorization */ PKG_EXS.OPTIONS_SET(OPTIONS => HDR_HEADERS, SCODE => pkg_exs.SHTP_HDR_AUTHORIZATION, SVALUE => sAUTH); PKG_EXS.OPTIONS_SET(OPTIONS => HDR_HEADERS, SCODE => pkg_exs.SHTP_HDR_CNT_TP, SVALUE => pkg_exs.SHTP_HDR_CNT_TP_JSON); end if; end if; if SPATCH_LOKAL is not null then PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => 'SPATCH_LOCAL', SVALUE => SPATCH_LOKAL); end if; if NEQUIPDSCMN is not null then PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => 'NEQUIPDSCMN', SVALUE => NEQUIPDSCMN); end if; if SPATCH_FSERV is not null then PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => 'SPATCH_FSERV', SVALUE => SPATCH_FSERV); end if; if SDESCR is not null then PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => 'SDESCR', SVALUE => SDESCR); end if; PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => PKG_EXS.SMSG_OPTION_CODE_SIMPLE, SVALUE => PKG_EXS.SMSG_OPTION_SIMPLE_FALSE); /* Формируем параметры запроса */ PKG_EXS.OPTIONS_SET(OPTIONS => OPTS, SCODE => pkg_exs.SMSG_OPTION_CODE_HEADERS, SVALUE => PKG_EXS.OPTIONS_SERIALIZE(OPTIONS => HDR_HEADERS, BROOT => false)); /* Постанока запроса в очередь */ PKG_EXS.QUEUE_PUT(NEXSSERVICEFN => NEXSSERVICEFN, BMSG => BMSG, NEXSQUEUE => NLNK_NEXSQUEUE, NLNK_COMPANY => nCOMPANY, NLNK_DOCUMENT => NDOCUMENT, SLNK_UNITCODE => SUNITCODE, SOPTIONS => PKG_EXS.OPTIONS_SERIALIZE(OPTIONS => OPTS), NPRIORITY => NPRIORITY, NNEW_EXSQUEUE => NQ); end SEND_PACKGE; /* Подготока данных для Загрузки файла на SCP */ procedure SCP_DATA_MAKE ( NEXSSERVICEFN in number, -- Рег. номер функции обработки SHOST out varchar2, -- host SPORT out varchar2, -- port SUSER out varchar2, -- username SPASS out varchar2, -- password SPATCH_FSERV out varchar2 -- Путь размещения файла на сервере CSP ) is REXSSERVICEFN EXSSERVICEFN%rowtype; -- REXSSERVICE EXSSERVICE%rowtype; -- Запись сервиса обмена begin /* Считывание записи функции сервиса обмена */ REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => NEXSSERVICEFN); /* Считывание записи сервиса обмена */ REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN); /**/ SHOST := REGEXP_SUBSTR(REGEXP_SUBSTR(REXSSERVICE.SRV_ROOT,'(.*?)(//|$)', 1,2,NULL,1),'(.*?)(:|$)', 1,1,NULL,1); SPORT := REGEXP_SUBSTR(REGEXP_SUBSTR(REXSSERVICE.SRV_ROOT,'(.*?)(//|$)', 1,2,NULL,1),'(.*?)(:|$)', 1,2,NULL,1); /* Считаем параметры пользователя логин и пароль */ SUSER := REXSSERVICE.SRV_USER; SPASS := BLOB2CLOB(lbDATA => BASE64_DECODE(REXSSERVICE.SRV_PASS),sCHARSET => PKG_CHARSET.CHARSET_UTF_); /**/ SPATCH_FSERV := REXSSERVICEFN.FN_URL; end SCP_DATA_MAKE; /* Подготока данных для Загрузки файла на Фреймворк */ procedure AUTH_DATA_MAKE ( NEXSSERVICEFN in number, -- Рег. номер функции обработки sAUTH out varchar2 -- Данные авторизции ("Authorization Basic base64(login:pass)) ) is REXSSERVICEFN EXSSERVICEFN%rowtype; -- Запись функции сервиса обмена REXSSERVICE EXSSERVICE%rowtype; -- Запись сервиса обмена SUSER PKG_STD.tSTRING; -- username SPASS PKG_STD.tSTRING; -- password begin /* Считывание записи функции сервиса обмена */ REXSSERVICEFN := GET_EXSSERVICEFN_ID(NFLAG_SMART => 0, NRN => NEXSSERVICEFN); /* Считывание записи сервиса обмена */ REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN); /* Считаем параметры пользователя логин и пароль */ SUSER := REXSSERVICE.SRV_USER; SPASS := BLOB2CLOB(lbDATA => BASE64_DECODE(REXSSERVICE.SRV_PASS),sCHARSET => PKG_CHARSET.CHARSET_UTF_); /**/ sAUTH := 'Basic'||' '||BASE64_ENCODE(lbSRCE => CLOB2BLOB(lcDATA => SUSER||':'||SPASS,sCHARSET => PKG_CHARSET.CHARSET_UTF_)); end AUTH_DATA_MAKE; /* Подготока данных для для передачи внешней системе */ procedure METADATA_MAKE ( NIDENT in number, -- Идентификатор Selectlis NEQUIPDSCM in number, -- регистрационный номер записи Выборки данных класса оборудования» NDATASET_ID out number, -- DATASET_ID BXML out blob -- Тело файла ) is SEND_POINT PKG_STD.tSTRING; -- URL для обработки результата xNODE PKG_XMAKE.tNODE; -- Подчиненный узел xNODE_FL PKG_XMAKE.tNODE; -- Подчиненный узел Имён файлов XDOC integer; -- Документ для размещения XML-элемента DATACONFIG PKG_XMAKE.tNODE; -- DATACONFIG ATRIBS PKG_XMAKE.tATTRIBUTES; -- Атрибуты RDOCUMENT PKG_XPATH.TDOCUMENT; -- XML документ RROOT PKG_XPATH.TNODE; -- Корневой узел XML документа FIRSTNODE PKG_XPATH.TNODE; -- Корневой узел XML документа RNODE PKG_XPATH.TNODE; -- RNODES PKG_XPATH.TNODES; -- Узлы XML документа NCURS_COUNT PKG_STD.tNUMBER; -- Количество узлов BONLYONE boolean := true; begin XDOC := PKG_XMAKE.OPEN_CURSOR(); for REQUIPDSCM in (select E.CODE SEQOBJKIND, t.* from UDO_T_EQUIPDSCM T, EQOBJKIND E where T.RN = NEQUIPDSCM and T.EQOBJKIND = E.RN)loop RDOCUMENT := PKG_XPATH.PARSE_FROM_CLOB(REQUIPDSCM.DATA_CONFIG); RROOT := PKG_XPATH.ROOT_NODE(RDOCUMENT); FIRSTNODE := PKG_XPATH.FIRST_NODE(RROOT); RNODES := PKG_XPATH.LIST_NODES(FIRSTNODE, 'item'); NCURS_COUNT := PKG_XPATH.COUNT_NODES(RNODES); for I in 1 .. NCURS_COUNT loop RNODE := PKG_XPATH.ITEM_NODE(RNODES, I); ATRIBS := PKG_XMAKE.ATTRIBUTES(iCURSOR => XDOC, rATTRIBUTE00 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC,sNAME => 'col_name',sVALUE => PKG_XPATH.ATTRIBUTE(RNODE, 'col_code')), rATTRIBUTE01 => PKG_XMAKE.ATTRIBUTE(iCURSOR => XDOC,sNAME => 'data_type',sVALUE => PKG_XPATH.ATTRIBUTE(RNODE, 'data_type')) ); DATACONFIG := PKG_XMAKE.CONCAT(iCURSOR => XDOC, rNODE00 => DATACONFIG, rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC,sNAME => 'data_config',rATTRIBUTES => ATRIBS) ); end loop; PKG_XPATH.FREE(rDOCUMENT => RDOCUMENT); /* Сформируем полный URL */ SEND_POINT := GET_URL_END_POINT(NEXSSERVICEFN => REQUIPDSCM.EXSSERVICEFN_SEND_MDCB); /* Перечень файлов */ for REQUIPDSCMFL in (select FL.* from UDO_T_EQUIPDSCMFL FL, SELECTLIST SL Where FL.RN = SL.DOCUMENT and SL.IDENT = NIDENT)loop /* Идентификатор dataset */ if (BONLYONE) then xNODE := PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'dataset_ID', rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, sVALUE => REQUIPDSCMFL.DATASET_ID)); BONLYONE := false; NDATASET_ID := REQUIPDSCMFL.DATASET_ID; end if; xNODE_FL := PKG_XMAKE.CONCAT(iCURSOR => XDOC, rNODE00 => xNODE_FL, rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'ftp_filepath', rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, sVALUE => REQUIPDSCMFL.FILE_NAME))); end loop; xNODE := PKG_XMAKE.CONCAT(iCURSOR => XDOC, rNODE00 => xNODE, /* Тип оборудования */ rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'class_machine', rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, sVALUE => TRIM(REQUIPDSCM.SEQOBJKIND))), rNODE02 => xNODE_FL, /* url для результата отпраки */ rNODE03 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'end_point', rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, sVALUE => SEND_POINT)), /* Описание полей dataset */ rNODE04 => DATACONFIG ); end loop; BXML := PKG_XMAKE.SERIALIZE_TO_BLOB(iCURSOR => XDOC, iTYPE => PKG_XMAKE.DOCUMENT_, rNODE => PKG_XMAKE.CONCAT(iCURSOR => XDOC, rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'root', rNODE00 => xNODE)), rHEADER => PKG_XHEADER.WRAP_ALL(PKG_XHEADER.VERSION_1_0_, PKG_XHEADER.ENCODING_UTF_, PKG_XHEADER.STANDALONE_NONE_) ); PKG_XMAKE.CLOSE_CURSOR(iCURSOR => XDOC); end METADATA_MAKE; /* Подготока данных для передачи Фреймворку запроса на обучение модели */ procedure REQUIREMENTS_MAKE ( NEQUIPDSCMML in number, -- регистрационный номер записи Выборки Модели» BXML out blob -- Тело файла ) is SEND_POINT PKG_STD.tSTRING; -- URL для обработки результата xNODE PKG_XMAKE.tNODE; -- Подчиненный узел xNODE_ML PKG_XMAKE.tNODE; -- Подчиненный узел обучение модели XDOC integer; -- Документ для размещения XML-элемента BONLYONE boolean := true; begin /*Старт сборки XML*/ XDOC := PKG_XMAKE.OPEN_CURSOR(); /* Перечень файлов */ for REQUIPDSCMML in (select M.EQOBJKIND, M.EXSSERVICEFN_SEND_RQCB, TRIM(E.CODE) SEQOBJKIND, ML.* from UDO_T_EQUIPDSCMML ML, UDO_T_EQUIPDSCM M, EQOBJKIND E Where ML.RN = NEQUIPDSCMML and ML.PRN = M.RN and M.EQOBJKIND = E.RN) loop /* Сформируем полный URL */ if (BONLYONE) then SEND_POINT := GET_URL_END_POINT(NEXSSERVICEFN => REQUIPDSCMML.EXSSERVICEFN_SEND_RQCB); BONLYONE := false; end if; /* Ссобирем узел запроса */ xNODE_ML := PKG_XMAKE.CONCAT(iCURSOR => XDOC, rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'dataset_ID', rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, sVALUE => REQUIPDSCMML.DATASET_ID)), rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'task', rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, sVALUE => REQUIPDSCMML.TASK)), rNODE02 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'precision', rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, sVALUE => 100))); /* Ссобирем узел запроса */ xNODE := PKG_XMAKE.CONCAT(iCURSOR => XDOC, rNODE00 => xNODE_ML, /* Тип оборудования */ rNODE01 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'class_machine', rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, sVALUE => REQUIPDSCMML.SEQOBJKIND)), /* url для результата отпраки */ rNODE02 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'end_point', rVALUE00 => PKG_XMAKE.VALUE(iCURSOR => XDOC, sVALUE => SEND_POINT))); end loop; /* Формируем тело запроса */ BXML := PKG_XMAKE.SERIALIZE_TO_BLOB(iCURSOR => XDOC, iTYPE => PKG_XMAKE.DOCUMENT_, rNODE => PKG_XMAKE.CONCAT(iCURSOR => XDOC, rNODE00 => PKG_XMAKE.ELEMENT(iCURSOR => XDOC, sNAME => 'root', rNODE00 => xNODE)), rHEADER => PKG_XHEADER.WRAP_ALL(PKG_XHEADER.VERSION_1_0_, PKG_XHEADER.ENCODING_UTF_, PKG_XHEADER.STANDALONE_NONE_)); PKG_XMAKE.CLOSE_CURSOR(iCURSOR => XDOC); end REQUIREMENTS_MAKE; end UDO_PKG_EQUIPDS_SEND; /