//OpenSCADA file: tdaqs.cpp /*************************************************************************** * Copyright (C) 2003-2023 by Roman Savochenko, * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; version 2 of the License. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include "tsys.h" #include "tmess.h" #include "tcontroller.h" #include "tmodule.h" #include "tvalue.h" #include "tdaqs.h" using namespace OSCADA; //************************************************* //* TDAQS * //************************************************* TDAQS::TDAQS( ) : TSubSYS(SDAQ_ID, true), mElErr("Error"), mRdRestDtTm(1) { mTmpLib = grpAdd("tmplb_"); //Templates lib db structure mElLib.fldAdd(new TFld("ID",trS("Identifier"),TFld::String,TCfg::Key,i2s(limObjID_SZ).c_str())); mElLib.fldAdd(new TFld("NAME",trS("Name"),TFld::String,TFld::TransltText,i2s(limObjNm_SZ).c_str())); mElLib.fldAdd(new TFld("DESCR",trS("Description"),TFld::String,TFld::FullText|TFld::TransltText,"1000")); mElLib.fldAdd(new TFld("DB",trS("Data base"),TFld::String,TFld::NoFlag,"30")); //????[v1.0] Remove //Template DB structure mElTmpl.fldAdd(new TFld("ID",trS("Identifier"),TFld::String,TCfg::Key,i2s(limObjID_SZ).c_str())); mElTmpl.fldAdd(new TFld("NAME",trS("Name"),TFld::String,TFld::TransltText,i2s(limObjNm_SZ).c_str())); mElTmpl.fldAdd(new TFld("DESCR",trS("Description"),TFld::String,TFld::FullText|TFld::TransltText,"1000")); mElTmpl.fldAdd(new TFld("MAXCALCTM",trS("Maximum calculate time, seconds"),TFld::Integer,TFld::NoFlag,"4","10","0;3600")); mElTmpl.fldAdd(new TFld("PR_TR",trS("Completely translate the procedure"),TFld::Boolean,TFld::NoFlag,"1","0")); mElTmpl.fldAdd(new TFld("PROGRAM",trS("Procedure"),TFld::String,TFld::TransltText,"1000000")); mElTmpl.fldAdd(new TFld("TIMESTAMP",trS("Date of modification"),TFld::Integer,TFld::DateTimeDec)); //Parameter template IO DB structure mElTmplIO.fldAdd(new TFld("TMPL_ID",trS("Template identifier"),TFld::String,TCfg::Key,i2s(limObjID_SZ).c_str())); mElTmplIO.fldAdd(new TFld("ID",trS("Identifier"),TFld::String,TCfg::Key,i2s(limObjID_SZ*1.5).c_str())); mElTmplIO.fldAdd(new TFld("NAME",trS("Name"),TFld::String,TFld::TransltText,i2s(limObjNm_SZ).c_str())); mElTmplIO.fldAdd(new TFld("TYPE",trS("Value type"),TFld::Integer,TFld::NoFlag,"1")); mElTmplIO.fldAdd(new TFld("FLAGS",trS("Flags"),TFld::Integer,TFld::NoFlag,"4")); mElTmplIO.fldAdd(new TFld("VALUE",trS("Value"),TFld::String,TFld::TransltText,"50")); mElTmplIO.fldAdd(new TFld("POS",trS("Real position"),TFld::Integer,TFld::NoFlag,"4")); //Error attributes mElErr.fldAdd(new TFld("err",trS("Error"),TFld::String,TFld::NoWrite|TVal::DirRead)); if(mess_lev() == TMess::Debug) SYS->cntrIter(objName(), 1); } TDAQS::~TDAQS( ) { nodeDelAll(); if(mess_lev() == TMess::Debug) SYS->cntrIter(objName(), -1); } string TDAQS::objName( ) { return TSubSYS::objName()+":TDAQS"; } void TDAQS::rdActCntrList( vector &ls, bool isRun ) { AutoHD cntr; ls.clear(); vector mls, cls; modList(mls); for(unsigned iM = 0; iM < mls.size(); iM++) { if(!at(mls[iM]).at().redntAllow()) continue; at(mls[iM]).at().list(cls); for(unsigned iC = 0; iC < cls.size(); iC++) { cntr = at(mls[iM]).at().at(cls[iC]); if(cntr.at().startStat() && (!isRun || !cntr.at().redntUse(TController::Any))) ls.push_back(cntr.at().workId()); } } } void TDAQS::ctrListPrmAttr( XMLNode *opt, const string &ilPrm, bool toPrm, char sep, const string &pref, TCntrNode *ndBase ) { string cPath = "", cEl; vector ls; string lPrm = ilPrm; if(pref.size() && lPrm.find(pref) == 0) lPrm = lPrm.substr(pref.size()); if(sep || cPath.size()) opt->childAdd("el")->setText(pref+cPath); AutoHD DAQnd = this; const char *cGrp = "mod_"; int cLv = 0; for(int cOff = 0; (sep && (cEl=TSYS::strSepParse(lPrm,0,sep,&cOff)).size()) || (!sep && (cEl=TSYS::pathLev(lPrm,0,true,&cOff)).size()); ++cLv) { if(cEl == ".") { if(ndBase && cLv == 0 && lPrm[0] == '.') { DAQnd = ndBase; cPath += cEl; } else cPath += "/"+cEl; } else if(cEl == "..") { if(ndBase && cLv == 0 && lPrm.find("..") == 0) { DAQnd = ndBase; cPath += cEl; } else cPath += "/"+cEl; if(&DAQnd.at() != this) DAQnd = DAQnd.at().nodePrev(); } else { cPath += sep ? (cLv?sep+cEl:cEl) : "/"+cEl; DAQnd = DAQnd.at().nodeAt(cGrp+cEl, 0, sep, 0, true); } if(DAQnd.freeStat()) break; opt->childAdd("el")->setText(pref+cPath); cGrp = dynamic_cast(&DAQnd.at()) ? "cntr_" : "prm_"; } if(sep && cLv) cPath += sep; if(!sep && ndBase) { if(cPath.size()) opt->childAdd("el")->setText(pref+cPath+"/.."); else { opt->childAdd("el")->setText(pref+"."); opt->childAdd("el")->setText(pref+".."); } } if(!DAQnd.freeStat()) { DAQnd.at().chldList(DAQnd.at().grpId(cGrp), ls, true); for(unsigned iL = 0; iL < ls.size(); iL++) opt->childAdd("el")->setText(pref+cPath+(sep?ls[iL]:("/"+ls[iL]))); //Get attributes if(!toPrm && strcmp(cGrp,"prm_") == 0) { DAQnd.at().chldList(DAQnd.at().grpId("a_"), ls, true); if(ls.size()) opt->childAdd("el")->setText(_("=== Attributes ===")); for(unsigned iL = 0; iL < ls.size(); iL++) opt->childAdd("el")->setText(pref+cPath+(sep?ls[iL]:("/"+ls[iL]))); } } } void TDAQS::load_( ) { //Load parameters from command line map itReg; //Loading the template libraries of the DAQ-parameter try { // Search and create new libraries TConfig cEl(&elLib()); //cEl.cfgViewAll(false); vector dbLs; // Search in DB TBDS::dbList(dbLs, TBDS::LsCheckSel|TBDS::LsInclGenFirst); for(unsigned iIt = 0; iIt < dbLs.size(); iIt++) for(int libCnt = 0; TBDS::dataSeek(dbLs[iIt]+"."+tmplLibTable(),nodePath()+"tmplib",libCnt++,cEl,TBDS::UseCache); ) { string lId = cEl.cfg("ID").getS(); if(!tmplLibPresent(lId)) tmplLibReg(new TPrmTmplLib(lId.c_str(),"",dbLs[iIt])); if(tmplLibAt(lId).at().DB() == dbLs[iIt]) tmplLibAt(lId).at().load(&cEl); tmplLibAt(lId).at().setDB(dbLs[iIt], true); itReg[lId] = true; } // Check for remove items removed from DB if(SYS->chkSelDB(SYS->selDB(),true)) { tmplLibList(dbLs); for(unsigned iIt = 0; iIt < dbLs.size(); iIt++) if(itReg.find(dbLs[iIt]) == itReg.end() && SYS->chkSelDB(tmplLibAt(dbLs[iIt]).at().DB())) tmplLibUnreg(dbLs[iIt]); } } catch(TError &err) { mess_err(err.cat.c_str(), "%s", err.mess.c_str()); mess_sys(TMess::Error, _("Error loading template libraries.")); } //Loading the DAQ-controller objects try { AutoHD wmod; vector modLs, dbLs; modList(modLs); for(unsigned iMd = 0; iMd < modLs.size(); iMd++) { wmod = at(modLs[iMd]); TConfig gCfg(&wmod.at()); //gCfg.cfgViewAll(false); itReg.clear(); // Search in the storage and create new controller objects TBDS::dbList(dbLs, TBDS::LsCheckSel|TBDS::LsInclGenFirst); for(unsigned iIt = 0; iIt < dbLs.size(); iIt++) for(int fldCnt = 0; TBDS::dataSeek(dbLs[iIt]+"."+subId()+"_"+wmod.at().modId(),wmod.at().nodePath()+"DAQ",fldCnt++,gCfg,TBDS::UseCache); ) { string mId = gCfg.cfg("ID").getS(); try { if(!wmod.at().present(mId)) wmod.at().add(mId, dbLs[iIt]); if(wmod.at().at(mId).at().DB() == dbLs[iIt]) wmod.at().at(mId).at().load(&gCfg); wmod.at().at(mId).at().setDB(dbLs[iIt], true); itReg[mId] = true; } catch(TError &err) { mess_err(err.cat.c_str(), "%s", err.mess.c_str()); mess_sys(TMess::Error, _("Error adding controller '%s'."), mId.c_str()); } } // Check for remove items removed from DB wmod.at().list(dbLs); for(unsigned iIt = 0; iIt < dbLs.size(); iIt++) if(itReg.find(dbLs[iIt]) == itReg.end() && SYS->chkSelDB(wmod.at().at(dbLs[iIt]).at().DB())) wmod.at().del(dbLs[iIt]); } } catch(TError &err) { mess_err(err.cat.c_str(), "%s", err.mess.c_str()); } //Load parameters from the config-file and SYS DB setRdRestDtTm(s2r(TBDS::genPrmGet(nodePath()+"RdRestDtTm",r2s(rdRestDtTm())))); } void TDAQS::load__( ) { //Early starting for template libraries, after the whole loading vector tmpl_lst; tmplLibList(tmpl_lst); for(unsigned iLb = 0; iLb < tmpl_lst.size(); iLb++) try { tmplLibAt(tmpl_lst[iLb]).at().start(true); } catch(TError &err) { } } void TDAQS::save_( ) { //Save parameters to SYS DB TBDS::genPrmSet(nodePath()+"RdRestDtTm", r2s(rdRestDtTm())); } TVariant TDAQS::objFuncCall( const string &iid, vector &prms, const string &user_lang ) { // TCntrNodeObj daqAt(string path, string sep = "", waitForAttr = true) - attaches to a DAQ node (controller object, parameter, attribute) in the ''path'' // or the separated string by the separator ''sep'', from the DAQ-subsystem. Check for an attribute in the path last element, at ''waitForAttr''. // path - path to the DAQ-node // sep - the symbol separator for separated string path // waitForAttr - wait for an attribute or other if(iid == "daqAt" && prms.size() >= 1) { AutoHD nd = daqAt(prms[0].getS(), (prms.size()>=2 && prms[1].getS().size())?prms[1].getS()[0]:0, true, (prms.size()>=3)?prms[2].getB():true); return nd.freeStat() ? TVariant(false) : TVariant(new TCntrNodeObj(nd,user_lang)); } // bool funcCall(string progLang, TVarObj args, string prog, string fixId = "", string err = "") - // Call function text whith arguments for program language // and with the fixed identifier (automatic for this empty). Return "true" on a well call. // For the fixed function recreate you need change the program or clean up by the function original id. // progLang - program procedure language or the stored function's address, after call with ; // args - function arguments; // prog - function text; // fixId - two direction field of fixed identifier of the function; // for the field empty the function id will be automatic and destroy at end, // else the id will used on the function creation and replaced by an address to it. // err - to place here all errors if(iid == "funcCall" && prms.size() >= 3 && prms[1].type() == TVariant::Object) { string fixId = (prms.size() >= 4) ? prms[3].getS() : ""; string faddr; AutoHD wFnc; if(fixId.size()) wFnc = SYS->nodeAt(fixId, 0, 0, 0, true); AutoHD args = prms[1].getO(); vector als; args.at().propList(als); TVariant aVal; try { //New call environment preparing or modifying presented if(wFnc.freeStat() || prms[2].getS() != wFnc.at().prog()) { // Update present function if(!wFnc.freeStat()) { wFnc.at().setStart(false); wFnc.at().setProg(prms[2].getS()); wFnc.at().setStart(true); } else { string langMod = TSYS::strParse(prms[0].getS(), 0, "."); if(!modPresent(langMod)) return false; //Prepare arguments structure TFunction argStr(fixId.size()?"uf_"+TSYS::strEncode(fixId,TSYS::oscdID):""); for(unsigned iA = 0; iA < als.size(); iA++) { aVal = args.at().propGet(als[iA]); IO::Type tp = IO::String; switch(aVal.type()) { case TVariant::Boolean: tp = IO::Boolean; break; case TVariant::Integer: tp = IO::Integer; break; case TVariant::Real: tp = IO::Real; break; case TVariant::String: tp = IO::String; break; case TVariant::Object: tp = IO::Object; break; default: break; } argStr.ioAdd(new IO(als[iA].c_str(),als[iA].c_str(),tp,IO::Default)); } //Get function id and compile. faddr = at(langMod).at().compileFunc(TSYS::strParse(prms[0].getS(),1,"."), argStr, prms[2].getS()); wFnc = SYS->nodeAt(faddr); } } //Prepare and execute TValFunc wCtx("UserFunc", &wFnc.at(), true, TSYS::strLine(user_lang,0)); // Load values for(unsigned iA = 0; iA < als.size(); iA++) switch((aVal=args.at().propGet(als[iA])).type()) { case TVariant::Boolean: wCtx.setB(iA, aVal.getB()); break; case TVariant::Integer: wCtx.setI(iA, aVal.getI()); break; case TVariant::Real: wCtx.setR(iA, aVal.getR()); break; case TVariant::String: wCtx.setS(iA, aVal.getS()); break; case TVariant::Object: wCtx.setO(iA, aVal.getO()); break; default: break; } // Call function wCtx.calc(); // Place the call results and remove function object. for(int iA = 0; iA < wCtx.ioSize(); iA++) switch(wCtx.ioType(iA)) { case IO::Boolean: args.at().propSet(als[iA], wCtx.getB(iA)); break; case IO::Integer: args.at().propSet(als[iA], wCtx.getI(iA)); break; case IO::Real: args.at().propSet(als[iA], wCtx.getR(iA)); break; case IO::String: args.at().propSet(als[iA], wCtx.getS(iA)); break; case IO::Object: args.at().propSet(als[iA], wCtx.getO(iA)); break; default: break; } // Remove compiled function object wCtx.setFunc(NULL); wFnc.free(); if(faddr.size()) { if(fixId.size()) { prms[3].setS(faddr); prms[3].setModify(); } else SYS->nodeDel(faddr); } return true; } catch(TError &err) { if(prms.size() >= 5) { prms[4].setS(err.mess); prms[4].setModify(); } mess_err(err.cat.c_str(), "%s", err.mess.c_str()); } return false; } // string funcSnthHgl(string progLang) - Requesting the program language syntax highlight rules. // progLang - program procedure language; if(iid == "funcSnthHgl" && prms.size() >= 1) { string langMod = TSYS::strParse(prms[0].getS(), 0, "."); if(!modPresent(langMod)) return ""; XMLNode hgl_req("SnthHgl"); at(langMod).at().compileFuncSnthHgl(TSYS::strParse(prms[0].getS(),1,"."), hgl_req); return hgl_req.childSize() ? hgl_req.save() : string(""); } return TCntrNode::objFuncCall(iid, prms, user_lang); } void TDAQS::unload( ) { TSubSYS::unload(); mRdRes.lock(true); mRdRestDtTm = 1; mRdCntr.clear(); mRdRes.unlock(); } void TDAQS::subStart( ) { vector mL, tmpl_lst; bool reply = false; int try_cnt = 0; do { //Start template's libraries tmplLibList(tmpl_lst); for(unsigned iLb = 0; iLb < tmpl_lst.size(); iLb++) try { tmplLibAt(tmpl_lst[iLb]).at().start(true); } catch(TError &err) { if(try_cnt) { mess_err(err.cat.c_str(), "%s", err.mess.c_str()); mess_sys(TMess::Error, _("Error starting the templates library '%s'."), tmpl_lst[iLb].c_str()); } reply = true; } //Enable controllers modList(mL); for(unsigned iM = 0; iM < mL.size(); iM++) { vector cL; at(mL[iM]).at().list(cL); for(unsigned iC = 0; iC < cL.size(); iC++) { AutoHD cntr = at(mL[iM]).at().at(cL[iC]); if(/*!cntr.at().enableStat() &&*/ cntr.at().toEnable()) try{ cntr.at().enable(); } catch(TError &err) { if(try_cnt) { mess_err(err.cat.c_str(), "%s", err.mess.c_str()); mess_sys(TMess::Error, _("Error enabling the controller object '%s'."), (mL[iM]+"."+cL[iC]).c_str()); } reply = true; } } } try_cnt++; } while(reply && try_cnt < 2); //Archive subsystem start if(!SYS->archive().at().subStartStat() || !SYS->stopSignal()) SYS->archive().at().subStart(); //Controllers start TSubSYS::subStart(); } void TDAQS::subStop( ) { vector mL; //Stop modList(mL); for(unsigned iM = 0; iM < mL.size(); iM++) { vector cL; at(mL[iM]).at().list(cL); for(unsigned iC = 0; iC < cL.size(); iC++) { AutoHD cntr = at(mL[iM]).at().at(cL[iC]); if(cntr.at().startStat()) try{ cntr.at().stop(); } catch(TError &err) { mess_err(err.cat.c_str(), "%s", err.mess.c_str()); mess_sys(TMess::Error, _("Error stopping the controller object '%s'."), (mL[iM]+"."+cL[iC]).c_str()); } } } //Disable for(unsigned iM = 0; iM < mL.size(); iM++) { vector cL; at(mL[iM]).at().list(cL); for(unsigned iC = 0; iC < cL.size(); iC++) { AutoHD cntr = at(mL[iM]).at().at(cL[iC]); if(cntr.at().enableStat()) try{ cntr.at().disable(); } catch(TError &err) { mess_err(err.cat.c_str(), "%s", err.mess.c_str()); mess_sys(TMess::Error, _("Error disabling the controller object '%s'."), (mL[iM]+"."+cL[iC]).c_str()); } } } //Stop template's libraries tmplLibList(mL); for(unsigned iLb = 0; iLb < mL.size(); iLb++) tmplLibAt(mL[iLb]).at().start(false); TSubSYS::subStop(); } AutoHD TDAQS::daqAt( const string &path, char sep, bool noex, bool waitForAttr, TCntrNode *ndBase ) const { string cEl; AutoHD DAQnd = const_cast(this); const char *cGrp = "mod_"; for(int cOff = 0, cLv = 0; (sep && (cEl=TSYS::strSepParse(path,0,sep,&cOff)).size()) || (!sep && (cEl=TSYS::pathLev(path,0,true,&cOff)).size()); ++cLv) { bool lastEl = (/*cLv > 2 &&*/ cOff >= (int)path.size()); if(waitForAttr && lastEl) cGrp = "a_"; AutoHD tNd; if(cEl == ".") { if(ndBase && cLv == 0 && path[0] == '.') tNd = ndBase; else tNd = DAQnd; } else if(cEl == "..") { if(ndBase && cLv == 0 && path.find("..") == 0) DAQnd = ndBase; if(&DAQnd.at() != this) tNd = DAQnd.at().nodePrev(); else tNd = DAQnd; } else tNd = DAQnd.at().nodeAt(cGrp+cEl, 0, sep, 0, true); if(tNd.freeStat() && !(strcmp(cGrp,"a_") != 0 && lastEl && !(tNd=DAQnd.at().nodeAt("a_"+cEl,0,sep,0,true)).freeStat())) { if(noex) return AutoHD(); else throw err_sys(_("Missing the DAQ node '%s'."), path.c_str()); } cGrp = dynamic_cast(&tNd.at()) ? "cntr_" : "prm_"; DAQnd = tNd; } return DAQnd; } AutoHD TDAQS::prmAt( const string &path, char sep, bool noex, TCntrNode *ndBase ) const { AutoHD DAQnd = daqAt(path, sep, noex, false, ndBase); if(DAQnd.freeStat() || !dynamic_cast(&DAQnd.at())) { if(noex) return AutoHD(); else throw err_sys(_("The specified node is not the parameter '%s'."), path.c_str()); } return DAQnd; } AutoHD TDAQS::attrAt( const string &path, char sep, bool noex, TCntrNode *ndBase ) const { AutoHD DAQnd = daqAt(path, sep, noex, true, ndBase); if(DAQnd.freeStat() || !dynamic_cast(&DAQnd.at())) { if(noex) return AutoHD(); else throw err_sys(_("The specified node is not the attribute '%s'."), path.c_str()); } return DAQnd; } bool TDAQS::rdProcess( XMLNode *reqSt ) { if(reqSt) { string StId = reqSt->attr("StId"); ResAlloc res(mRdRes, true); mRdCntr[StId].clear(); for(unsigned iC = 0; iC < reqSt->childSize(); iC++) if(reqSt->childGet(iC)->name() == "cntr") mRdCntr[StId][reqSt->childGet(iC)->attr("id")] = s2i(reqSt->childGet(iC)->attr("run")); return true; } //Planing controllers' run and process requests to remote run controllers map sts = SYS->rdSts(); map::iterator sit; map::iterator cit; vector cls; rdActCntrList(cls); for(unsigned iC = 0; iC < cls.size(); iC++) { AutoHD cntr = at(TSYS::strParse(cls[iC],0,".")).at().at(TSYS::strParse(cls[iC],1,".")); // Process remote run controllers, before the redundancy status change // !!!! Moved here from the end if(cntr.at().startStat() && cntr.at().redntUse()) cntr.at().redntDataUpdate(); // Check contoller run plane if(cntr.at().redntMode() == TController::Off) cntr.at().setRedntUse(false); else { ResAlloc res(mRdRes, false); if(cntr.at().redntRun() == "") { int wLev = SYS->rdStLevel(); for(sit = sts.begin(); sit != sts.end(); ++sit) if(sit->second.isLive && (cit=mRdCntr[sit->first].find(cntr.at().workId())) != mRdCntr[sit->first].end() && cit->second) wLev = vmax(wLev, sit->second.lev); cntr.at().setRedntUse(SYS->rdStLevel() < wLev); } else if(cntr.at().redntRun() == "") { int wLev = SYS->rdStLevel(); for(sit = sts.begin(); sit != sts.end(); sit++) if(sit->second.isLive && (cit=mRdCntr[sit->first].find(cntr.at().workId())) != mRdCntr[sit->first].end() && cit->second) wLev = vmin(wLev, sit->second.lev); cntr.at().setRedntUse(SYS->rdStLevel() > wLev); } else if(cntr.at().redntRun() == "") { vector cls_lc; rdActCntrList(cls_lc, true); bool remPresent = false; for(sit = sts.begin(); sit != sts.end(); sit++) if(sit->second.isLive && (cit=mRdCntr[sit->first].find(cntr.at().workId())) != mRdCntr[sit->first].end()) { if(!remPresent) remPresent = cit->second; int aCntr = 0; for(map::iterator scit = mRdCntr[sit->first].begin(); scit != mRdCntr[sit->first].end(); scit++) if(scit->second) aCntr++; if(((int)cls_lc.size()-aCntr) >= 0 && cit->second) break; } cntr.at().setRedntUse(sit != sts.end()); } else { for(sit = sts.begin(); sit != sts.end(); sit++) if(sit->second.isLive && (cit=mRdCntr[sit->first].find(cntr.at().workId())) != mRdCntr[sit->first].end() && cit->second && cntr.at().redntRun() == sit->first) break; cntr.at().setRedntUse(sit != sts.end()); } res.release(); } cntr.free(); } return true; } string TDAQS::rdStRequest( const string &cntr, XMLNode &req, const string &prevSt, bool toRun ) { string lcPath = req.attr("path"); bool prevPresent = false; string rez; map::iterator sit; map::iterator cit; ResAlloc res(mRdRes, false); map > sts = mRdCntr; res.unlock(); for(map >::iterator sit = sts.begin(); sit != sts.end(); ++sit) if((cit=sit->second.find(cntr)) != sit->second.end() && (!toRun || cit->second)) { if(prevSt.size() && !prevPresent) { if(sit->first == prevSt) prevPresent = true; continue; } if((rez=SYS->rdStRequest(req,sit->first)).size()) return rez; res.lock(true); mRdCntr.erase(sit->first); res.unlock(); } if(prevSt.empty()) at(TSYS::strParse(cntr,0,".")).at().at(TSYS::strParse(cntr,1,".")).at().setRedntUse(false); return ""; } string TDAQS::optDescr( ) { return TSYS::strMess(_( "=================== Subsystem \"Data acquisition\" options ================\n" "------ Parameters of the section '%s' of the configuration file ------\n" "RdRestDtTm Depth of recovery time of archive data from the reserve station, when startup, in hours.\n\n" ),nodePath().c_str()) + TSubSYS::optDescr(); } void TDAQS::cntrCmdProc( XMLNode *opt ) { string a_path = opt->attr("path"); //Service commands process // Redundant service requests if(a_path == "/serv/redundant") { if(ctrChkNode(opt,"st",RWRWR_,"root",SDAQ_ID,SEC_RD)) { //State opt->setAttr("inProc", "1"); opt->setAttr("StLevel", i2s(SYS->rdStLevel())); map cntrLs; vector cls; rdActCntrList(cls); for(unsigned iL = 0; iL < cls.size(); iL++) cntrLs[cls[iL]] = false; rdActCntrList(cls,true); for(unsigned iL = 0; iL < cls.size(); iL++) cntrLs[cls[iL]] = true; for(map::iterator cit = cntrLs.begin(); cit != cntrLs.end(); cit++) opt->childAdd("cntr")->setAttr("id",cit->first)->setAttr("run",cit->second?"1":"0"); return; } } // Parameter and/or attributes list-browse else if(a_path == "/serv/PrmAttr" && ctrChkNode(opt,"list",RWRWR_,"root",SDAQ_ID,SEC_RD)) { ctrListPrmAttr(opt, opt->attr("base"), s2i(opt->attr("toPrm")), opt->attr("sep")[0], opt->attr("pref")); return; } //Get page info if(opt->name() == "info") { TSubSYS::cntrCmdProc(opt); ctrMkNode("oscada_cntr",opt,-1,"/",EVAL_STR,R_R_R_,"root","root",1,"doc",(subId()+"|Documents/"+subId()).c_str()); ctrMkNode("grp",opt,-1,"/br/tmplb_",_("Templates library"),RWRWR_,"root",SDAQ_ID,2,"idm",i2s(limObjNm_SZ).c_str(),"idSz",i2s(limObjID_SZ).c_str()); if(SYS->rdEnable() && ctrMkNode("area",opt,0,"/redund",_("Redundancy"))) { ctrMkNode("fld",opt,-1,"/redund/restDtTm",_("Depth time of restoring data at the starting, hours"),RWRWR_,"root",SDAQ_ID,1, "tp","real"); if(ctrMkNode("table",opt,-1,"/redund/cntr",_("Controllers"),RWRWR_,"root",SDAQ_ID,1,"key","id")) { ctrMkNode("list",opt,-1,"/redund/cntr/id",_("Controller"),R_R_R_,"root",SDAQ_ID,1,"tp","str"); ctrMkNode("list",opt,-1,"/redund/cntr/nm",_("Name"),R_R_R_,"root",SDAQ_ID,1,"tp","str"); ctrMkNode("list",opt,-1,"/redund/cntr/start",_("Run."),RWRWR_,"root",SDAQ_ID,1,"tp","bool"); ctrMkNode("list",opt,-1,"/redund/cntr/rdndt",_("Redund."),RWRWR_,"root",SDAQ_ID,4, "tp","dec", "dest","select", "sel_id",(i2s(TController::Off)+";"+i2s(TController::Asymmetric)+";"+i2s(TController::OnlyAlarms)).c_str(), "sel_list",_("Off;Asymmetric;Only alarms")); ctrMkNode("list",opt,-1,"/redund/cntr/prefRun",_("Pref. to run"),RWRWR_,"root",SDAQ_ID,4,"tp","str", "idm","1","dest","select","select","/redund/lsMode"); ctrMkNode("list",opt,-1,"/redund/cntr/remoted",_("Remote"),R_R_R_,"root",SDAQ_ID,1,"tp","bool"); } } if(ctrMkNode("area",opt,1,"/tpllibs",_("Template libraries"))) ctrMkNode("list",opt,-1,"/tpllibs/lb",_("Template libraries"),RWRWR_,"root",SDAQ_ID,5, "tp","br","idm",i2s(limObjNm_SZ).c_str(),"s_com","add,del","br_pref","tmplb_","idSz",i2s(limObjID_SZ).c_str()); return; } //Process command to page if(a_path == "/br/tmplb_" || a_path == "/tpllibs/lb") { if(ctrChkNode(opt,"get",RWRWR_,"root",SDAQ_ID,SEC_RD)) { vector lst; tmplLibList(lst); for(unsigned iA = 0; iA < lst.size(); iA++) opt->childAdd("el")->setAttr("id",lst[iA])->setText(trD(tmplLibAt(lst[iA]).at().name())); } if(ctrChkNode(opt,"add",RWRWR_,"root",SDAQ_ID,SEC_WR)) tmplLibReg(new TPrmTmplLib(TSYS::strEncode(opt->attr("id"),TSYS::oscdID).c_str(),opt->text().c_str(),DB_GEN)); if(ctrChkNode(opt,"del",RWRWR_,"root",SDAQ_ID,SEC_WR)) tmplLibUnreg(opt->attr("id"),1); } else if(a_path == "/redund/restDtTm") { if(ctrChkNode(opt,"get",RWRWR_,"root",SDAQ_ID,SEC_RD)) opt->setText(r2s(rdRestDtTm())); if(ctrChkNode(opt,"set",RWRWR_,"root",SDAQ_ID,SEC_WR)) setRdRestDtTm(s2r(opt->text())); } else if(a_path == "/redund/cntr") { if(ctrChkNode(opt,"get",RWRWR_,"root",SDAQ_ID,SEC_RD)) { XMLNode *nId = ctrMkNode("list",opt,-1,"/redund/cntr/id","",R_R_R_,"root",SDAQ_ID); XMLNode *nNm = ctrMkNode("list",opt,-1,"/redund/cntr/nm","",R_R_R_,"root",SDAQ_ID); XMLNode *nStart = ctrMkNode("list",opt,-1,"/redund/cntr/start","",RWRWR_,"root",SDAQ_ID); XMLNode *nRdndt = ctrMkNode("list",opt,-1,"/redund/cntr/rdndt","",RWRWR_,"root",SDAQ_ID); XMLNode *nPrefRun = ctrMkNode("list",opt,-1,"/redund/cntr/prefRun","",RWRWR_,"root",SDAQ_ID); XMLNode *nRem = ctrMkNode("list",opt,-1,"/redund/cntr/remoted","",R_R_R_,"root",SDAQ_ID); vector mls, cls; modList(mls); AutoHD cntr; for(unsigned iM = 0; iM < mls.size(); iM++) { if(!at(mls[iM]).at().redntAllow()) continue; at(mls[iM]).at().list(cls); for(unsigned iC = 0; iC < cls.size(); iC++) { cntr = at(mls[iM]).at().at(cls[iC]); if(nId) nId->childAdd("el")->setText(mls[iM]+"."+cls[iC]); if(nNm) nNm->childAdd("el")->setText(cntr.at().name()); if(nStart) nStart->childAdd("el")->setText(cntr.at().startStat()?"1":"0"); if(nRdndt) nRdndt->childAdd("el")->setText(i2s(cntr.at().redntMode())); if(nPrefRun) nPrefRun->childAdd("el")->setText(cntr.at().redntRun()); if(nRem) nRem->childAdd("el")->setText(cntr.at().redntUse(TController::Any)?"1":"0"); } } } if(ctrChkNode(opt,"set",RWRWR_,"root",SDAQ_ID,SEC_WR)) { string col = opt->attr("col"); AutoHD cntr = at(TSYS::strSepParse(opt->attr("key_id"),0,'.')).at(). at(TSYS::strSepParse(opt->attr("key_id"),1,'.')); if(col == "start") s2i(opt->text()) ? cntr.at().start() : cntr.at().stop(); else if(col == "rdndt") cntr.at().setRedntMode((TController::Redundant)(s2i(opt->text()))); else if(col == "prefRun") cntr.at().setRedntRun(opt->text()); } } else if(a_path == "/redund/lsMode" && ctrChkNode(opt)) { opt->childAdd("el")->setAttr("id","")->setText(_("")); opt->childAdd("el")->setAttr("id","")->setText(_("")); opt->childAdd("el")->setAttr("id","")->setText(_("")); vector sls; SYS->rdStList(sls); for(unsigned iS = 0; iS < sls.size(); iS++) opt->childAdd("el")->setAttr("id",sls[iS])->setText(SYS->transport().at().extHostGet("*",sls[iS]).name); } else TSubSYS::cntrCmdProc(opt); }