string Hddtemp::getHDDTemp( ) { string val; char buf[20]; ResAlloc res(m_res, true); //Check connect and start if(!SYS->transport().at().at(t_tr).at().outPresent(n_tr)) SYS->transport().at().at(t_tr).at().outAdd(n_tr); AutoHD<TTransportOut> tr = SYS->transport().at().at(t_tr).at().outAt(n_tr); MtxAlloc resN(tr.at().reqRes(), true); tr.at().setName(_("Parameter Hddtemp")); tr.at().setAddr("TCP:127.0.0.1:7634"); tr.at().setTimings("5:0.01"); if(tr.at().startStat()) tr.at().stop(); tr.at().start(); //Request int len; do { len = tr.at().messIO(NULL, 0, buf, sizeof(buf)); val.append(buf,len); }while(len); tr.at().stop(); return val; }
void HddStat::makeActiveDA( TMdContr *aCntr ) { string ap_nm = "Statistic_"; vector<string> list; dList(list,true); for(unsigned i_hd = 0; i_hd < list.size(); i_hd++) { vector<string> pLs; // Find propper parameter's object aCntr->list(pLs); unsigned i_p; for(i_p = 0; i_p < pLs.size(); i_p++) { AutoHD<TMdPrm> p = aCntr->at(pLs[i_p]); if(p.at().cfg("TYPE").getS() == id() && p.at().cfg("SUBT").getS() == list[i_hd]) break; } if(i_p < pLs.size()) continue; string hddprm = ap_nm+list[i_hd]; while(aCntr->present(hddprm)) hddprm = TSYS::strLabEnum(hddprm); aCntr->add(hddprm, 0); AutoHD<TMdPrm> dprm = aCntr->at(hddprm); dprm.at().setName(_("HD statistic: ")+list[i_hd]); dprm.at().autoC(true); dprm.at().cfg("TYPE").setS(id()); dprm.at().cfg("SUBT").setS(list[i_hd]); dprm.at().cfg("EN").setB(true); if(aCntr->enableStat()) dprm.at().enable(); } }
void Hddtemp::makeActiveDA( TMdContr *aCntr ) { string ap_nm = "Temperature_hd"; vector<string> list; dList(list); try { for(unsigned i_hd = 0; i_hd < list.size(); i_hd++) { vector<string> pLs; // Find propper parameter's object aCntr->list(pLs); unsigned i_p; for(i_p = 0; i_p < pLs.size(); i_p++) { AutoHD<TMdPrm> p = aCntr->at(pLs[i_p]); if(p.at().cfg("TYPE").getS() == id() && p.at().cfg("SUBT").getS() == list[i_hd]) break; } if(i_p < pLs.size()) continue; string hddprm = ap_nm+i2s(i_hd); while(aCntr->present(hddprm)) hddprm = TSYS::strLabEnum(hddprm); aCntr->add(hddprm,0); AutoHD<TMdPrm> dprm = aCntr->at(hddprm); dprm.at().setName(_("HD temperature: ")+i2s(i_hd)); dprm.at().autoC(true); dprm.at().cfg("TYPE").setS(id()); dprm.at().cfg("SUBT").setS(list[i_hd]); dprm.at().cfg("EN").setB(true); if(aCntr->enableStat()) dprm.at().enable(); } } catch(TError &err) { /*mess_err(err.cat.c_str(),"%s",err.mess.c_str());*/ } }
bool ModVArchEl::setValsProc( TValBuf &buf, int64_t beg, int64_t end ) { if(needMeta && (needMeta=!readMeta())) return false; //Check border if(!buf.vOK(beg,end)) return false; beg = vmax(beg, buf.begin()); end = vmin(end, buf.end()); beg = (beg/period())*period(); end = (end/period())*period(); //Table struct init TConfig cfg((archive().valType()==TFld::Real) ? (&mod->vlRealEl()) : (archive().valType()==TFld::String) ? (&mod->vlStrEl()) : &mod->vlIntEl()); AutoHD<TTable> tbl = SYS->db().at().open(archivator().addr()+"."+archTbl(), true); if(tbl.freeStat()) return false; //Write data to table for(int64_t ctm; beg <= end; beg++) { switch(archive().valType()) { case TFld::Boolean: cfg.cfg("VAL").setI(buf.getB(&beg,true)); break; case TFld::Integer: cfg.cfg("VAL").setI(buf.getI(&beg,true)); break; case TFld::Real: cfg.cfg("VAL").setR(buf.getR(&beg,true)); break; case TFld::String: cfg.cfg("VAL").setS(buf.getS(&beg,true)); break; default: break; } ctm = (beg/period())*period(); cfg.cfg("TM").setI(ctm/1000000); cfg.cfg("TMU").setI(ctm%1000000); tbl.at().fieldSet(cfg); //Archive time border update mBeg = mBeg ? vmin(mBeg,ctm) : ctm; mEnd = mEnd ? vmax(mEnd,ctm) : ctm; } //Archive size limit process if((mEnd-mBeg) > (int64_t)(archivator().maxSize()*3600e6)) { int64_t n_end = ((mEnd-(int64_t)(archivator().maxSize()*3600e6))/period())*period(); for(int64_t t_c = vmax(mBeg,n_end-3600ll*period()); t_c < n_end; t_c += period()) { cfg.cfg("TM").setI(t_c/1000000, true); cfg.cfg("TMU").setI(t_c%1000000, true); tbl.at().fieldDel(cfg); } mBeg = n_end; } tbl.free(); SYS->db().at().close(archivator().addr()+"."+archTbl()); //Update archive info cfg.setElem(&mod->archEl()); cfg.cfgViewAll(false); cfg.cfg("TBL").setS(archTbl(), true); cfg.cfg("BEGIN").setS(ll2s(mBeg), true); cfg.cfg("END").setS(ll2s(mEnd), true); cfg.cfg("PRM1").setS(ll2s(mPer), true); return SYS->db().at().dataSet(archivator().addr()+"."+mod->mainTbl(),"",cfg,false,true); }
//!!! Inherited (virtual) start archivator functions. void ModVArch::start() { //> Connection to DB and enable status check string wdb = TBDS::realDBName(addr()); AutoHD<TBD> db = SYS->db().at().nodeAt(wdb,0,'.'); if( !db.at().enableStat( ) ) db.at().enable(); //> Start getting data cycle TVArchivator::start(); }
void ModMArch::start( ) { //Connection to DB and enable status check string wdb = TBDS::realDBName(addr()); AutoHD<TBD> db = SYS->db().at().nodeAt(wdb, 0, '.'); try { if(!db.at().enableStat()) db.at().enable(); } catch(TError err) { mess_warning(nodePath().c_str(), _("Enable target DB error: %s"), err.mess.c_str()); } TMArchivator::start(); }
bool ModMArch::put( vector<TMess::SRec> &mess, bool force ) { if(needMeta && (needMeta=!readMeta())) return false; TMArchivator::put(mess, force); //Allow redundancy if(!runSt) throw TError(nodePath().c_str(), _("The archive is not started!")); AutoHD<TTable> tbl = SYS->db().at().open(addr()+"."+archTbl(), true); if(tbl.freeStat()) return false; TConfig cfg(&reqEl); int64_t t_cnt = TSYS::curTime(); for(unsigned i_m = 0; i_m < mess.size(); i_m++) { if(!chkMessOK(mess[i_m].categ,mess[i_m].level)) continue; //Put record to DB cfg.cfg("MIN").setI(mess[i_m].time/60); cfg.cfg("TM").setI(mess[i_m].time); cfg.cfg("TMU").setI(mess[i_m].utime); cfg.cfg("CATEG").setS(mess[i_m].categ); cfg.cfg("MESS").setS(mess[i_m].mess); cfg.cfg("LEV").setI(mess[i_m].level); tbl.at().fieldSet(cfg); //Archive time border update mBeg = mBeg ? vmin(mBeg,mess[i_m].time) : mess[i_m].time; mEnd = mEnd ? vmax(mEnd,mess[i_m].time) : mess[i_m].time; } //Archive size limit process if(maxSize() && (mEnd-mBeg) > (time_t)(maxSize()*86400)) { time_t nEnd = mEnd - (time_t)(maxSize()*86400); cfg.cfg("TM").setKeyUse(false); for(int tC = mBeg/60; tC < nEnd/60; tC++) { cfg.cfg("MIN").setI(tC, true); tbl.at().fieldDel(cfg); } mBeg = nEnd; } tbl.free(); //SYS->db().at().close(addr()+"."+archTbl()); //!!! No close the table manually //Update archive info cfg.setElem(&mod->archEl()); cfg.cfgViewAll(false); cfg.cfg("TBL").setS(archTbl(),true); cfg.cfg("BEGIN").setS(i2s(mBeg),true); cfg.cfg("END").setS(i2s(mEnd),true); bool rez = SYS->db().at().dataSet(addr()+"."+mod->mainTbl(),"",cfg,false,true); tmProc = TSYS::curTime() - t_cnt; tmProcMax = vmax(tmProcMax, tmProc); return rez; }
void MBD::transCloseCheck( ) { if(enableStat()) { vector<string> t_list; list(t_list); for(unsigned i_l = 0; i_l < t_list.size(); i_l++) { AutoHD<MTable> t = at(t_list[i_l]); if(t.at().mModify && (SYS->sysTm()-t.at().mModify) > 10) t.at().save(); } } }
void TProt::discoveryUrls( vector<string> &ls ) { ls.clear(); //Get allowed enpoints list vector<string> epLs; epList(epLs); for(unsigned i_ep = 0; i_ep < epLs.size(); i_ep++) { AutoHD<OPCEndPoint> ep = epAt(epLs[i_ep]); if(!ep.at().enableStat()) continue; ls.push_back(ep.at().url()); break; } }
bool ModMArch::put( vector<TMess::SRec> &mess ) { if(!run_st) throw TError(nodePath().c_str(), _("Archive is not started!")); AutoHD<TTable> tbl = SYS->db().at().open(addr()+"."+archTbl(), true); if(tbl.freeStat()) return false; TConfig cfg(&mod->messEl()); int64_t t_cnt = TSYS::curTime(); for(unsigned i_m = 0; i_m < mess.size(); i_m++) { if(!chkMessOK(mess[i_m].categ,mess[i_m].level)) continue; //Put record to DB cfg.cfg("TM").setI(mess[i_m].time); cfg.cfg("TMU").setI(mess[i_m].utime); cfg.cfg("CATEG").setS(mess[i_m].categ); cfg.cfg("MESS").setS(mess[i_m].mess); cfg.cfg("LEV").setI(mess[i_m].level); tbl.at().fieldSet(cfg); //Archive time border update mBeg = mBeg ? vmin(mBeg,mess[i_m].time) : mess[i_m].time; mEnd = mEnd ? vmax(mEnd,mess[i_m].time) : mess[i_m].time; } //Archive size limit process if((mEnd-mBeg) > (time_t)(maxSize()*3600)) { time_t n_end = mEnd-(time_t)(maxSize()*3600); for(time_t t_c = vmax(mBeg,n_end-3600); t_c < n_end; t_c++) { cfg.cfg("TM").setI(t_c,true); tbl.at().fieldDel(cfg); } mBeg = n_end; } tbl.free(); SYS->db().at().close(addr()+"."+archTbl()); //Update archive info cfg.setElem(&mod->archEl()); cfg.cfgViewAll(false); cfg.cfg("TBL").setS(archTbl(),true); cfg.cfg("BEGIN").setS(i2s(mBeg),true); cfg.cfg("END").setS(i2s(mEnd),true); bool rez = SYS->db().at().dataSet(addr()+"."+mod->mainTbl(),"",cfg,false,true); tm_calc = 1e-3*(TSYS::curTime()-t_cnt); return rez; }
void Contr::start_( ) { //Schedule process mPer = TSYS::strSepParse(cron(),1,' ').empty() ? vmax(0,1e9*s2r(cron())) : 0; if(messLev() == TMess::Debug) mess_debug_(nodePath().c_str(), _("Start stage 1: set all blocks to process.")); //Make process all bloks vector<string> lst; blkList(lst); for(unsigned i_l = 0; i_l < lst.size(); i_l++) if(blkAt(lst[i_l]).at().enable() && blkAt(lst[i_l]).at().toProcess()) try { blkAt(lst[i_l]).at().setProcess(true); } catch(TError err) { mess_warning(err.cat.c_str(),"%s",err.mess.c_str()); mess_warning(nodePath().c_str(),_("Process block '%s' error."),lst[i_l].c_str()); } if(messLev() == TMess::Debug) mess_debug_(nodePath().c_str(), _("Start stage 2: sort blocks for need sequence.")); //Sort blocks ResAlloc res(hdRes, true); string pvl; for(int iBe = 0, mvCnt = 0, iBlk = 0; iBe < (int)calcBlks.size(); ) { AutoHD<Block> cBlk = calcBlks[iBe]; bool isMoved = false; for(int off = 0, curPos = iBe; (pvl=TSYS::strSepParse(cBlk.at().prior(),0,';',&off)).size(); ) { for(iBlk = curPos+1; iBlk < (int)calcBlks.size(); iBlk++) if(pvl == calcBlks[iBlk].at().id()) { if(messLev() == TMess::Debug) mess_debug_(nodePath().c_str(), _("Reshuffle blocks '%s'(%d) <-> '%s'(%d)."), calcBlks[curPos].at().id().c_str(), curPos, calcBlks[iBlk].at().id().c_str(), iBlk); calcBlks[curPos] = calcBlks[iBlk]; calcBlks[iBlk] = cBlk; curPos = iBlk; isMoved = true; break; } } if(isMoved) mvCnt++; if(!isMoved || mvCnt >= (int)(calcBlks.size()/2)) { iBe++; mvCnt = 0; } } res.release(); if(messLev() == TMess::Debug) mess_debug_(nodePath().c_str(), _("Start stage 3: task create: prcSt=%d."), prcSt); //Start the request and calc data task if(!prcSt) SYS->taskCreate(nodePath('.',true), mPrior, Contr::Task, this); }
void Prm::vlGet( TVal &val ) { if(val.name() == "err") { if(!enableStat()) val.setS(_("1:Parameter is disabled."),0,true); else if(!owner().startStat()) val.setS(_("2:Controller is stopped."),0,true); else val.setS("0",0,true); return; } if(owner().redntUse()) return; try { //if( !enableStat() ) return; AutoHD<Block> blk = ((Contr &)owner()).blkAt(TSYS::strSepParse(val.fld().reserve(),0,'.')); int io_id = blk.at().ioId(TSYS::strSepParse(val.fld().reserve(),1,'.')); if( io_id < 0 ) disable(); else val.set((enableStat()&&owner().startStat()) ? blk.at().get(io_id) : EVAL_STR, 0, true); }catch(TError err) { disable(); } }
void ModMArch::start( ) { if(!runSt) { reqEl.fldClear(); reqEl.fldAdd(new TFld("MIN",_("In minutes"),TFld::Integer,TCfg::Key,"15")); //Mostly for fast reading next, by minutes reqEl.fldAdd(new TFld("TM",_("Time, seconds"),TFld::Integer,TCfg::Key|(tmAsStr()?TFld::DateTimeDec:0),"20")); reqEl.fldAdd(new TFld("TMU",_("Time, microseconds"),TFld::Integer,TCfg::Key,"6","0")); reqEl.fldAdd(new TFld("CATEG",_("Category"),TFld::String,TCfg::Key,"100")); reqEl.fldAdd(new TFld("MESS",_("Message"),TFld::String,TFld::NoFlag/*TCfg::Key*/,"100000")); reqEl.fldAdd(new TFld("LEV",_("Level"),TFld::Integer,TFld::NoFlag,"2")); } //Connection to DB and enable status check string wdb = TBDS::realDBName(addr()); AutoHD<TBD> db = SYS->db().at().nodeAt(wdb, 0, '.'); try { if(!db.at().enableStat()) db.at().enable(); } catch(TError &err) { mess_warning(nodePath().c_str(), _("Error enabling the target DB: %s"), err.mess.c_str()); } TMArchivator::start(); }
//************************************************* //* Control request * //************************************************* void xmlCntrReq::calc( TValFunc *val ) { try { XMLNode req; AutoHD<XMLNodeObj> xnd = val->getO(1); if(xnd.freeStat()) { val->setS(0,_("1:Request is not object!")); return; } xnd.at().toXMLNode(req); string path = req.attr("path"); if(val->getS(2).empty()) { req.setAttr("user", val->user()); SYS->cntrCmd(&req); } else { req.setAttr("path", "/"+val->getS(2)+path); SYS->transport().at().cntrIfCmd(req, "xmlCntrReq"); req.setAttr("path", path); } xnd.at().fromXMLNode(req); val->setS(0, "0"); }catch(TError err){ val->setS(0, TSYS::strMess(_("1:Request error: %s"),err.mess.c_str())); } }
void Prm::vlSet( TVal &vo, const TVariant &vl, const TVariant &pvl ) { if(!enableStat() || !owner().startStat()) return; //Send to active reserve station if(owner().redntUse()) { if(vl == pvl) return; XMLNode req("set"); req.setAttr("path",nodePath(0,true)+"/%2fserv%2fattr")->childAdd("el")->setAttr("id",vo.name())->setText(vl.getS()); SYS->daq().at().rdStRequest(owner().workId(),req); return; } //Direct write try { AutoHD<Block> blk = ((Contr &)owner()).blkAt(TSYS::strSepParse(vo.fld().reserve(),0,'.')); int io_id = blk.at().ioId(TSYS::strSepParse(vo.fld().reserve(),1,'.')); if(io_id < 0) disable(); else { MtxAlloc sres(owner().calcRes, true); blk.at().set(io_id, vl); } }catch(TError err) { disable(); } }
void CPU::makeActiveDA( TMdContr *aCntr ) { char buf[256]; FILE *f = fopen("/proc/stat","r"); if(f == NULL) return; //Check for allow CPU for(int n_cpu; fgets(buf,sizeof(buf),f) != NULL; ) if(sscanf(buf,"cpu%d",&n_cpu)) { string pId = "CPULoad"; string pNm = _("Full CPU Load"); string pSTp = "gen"; if(isdigit(buf[3])) { pId = "CPU"+i2s(n_cpu)+"Load"; pNm = _("CPU Load: ")+i2s(n_cpu); pSTp = i2s(n_cpu); } vector<string> pLs; // Find propper parameter's object aCntr->list(pLs); unsigned i_p; for(i_p = 0; i_p < pLs.size(); i_p++) { AutoHD<TMdPrm> p = aCntr->at(pLs[i_p]); if(p.at().cfg("TYPE").getS() == id() && p.at().cfg("SUBT").getS() == pSTp) break; } if(i_p < pLs.size()) continue; while(aCntr->present(pId)) pId = TSYS::strLabEnum(pId); aCntr->add(pId, 0); AutoHD<TMdPrm> dprm = aCntr->at(pId); dprm.at().setName(pNm); dprm.at().autoC(true); dprm.at().cfg("TYPE").setS(id()); dprm.at().cfg("SUBT").setS(pSTp); dprm.at().cfg("EN").setB(true); if(aCntr->enableStat()) dprm.at().enable(); } fclose(f); }
void TTpContr::perSYSCall( unsigned int cnt ) { //Check for restart some conrollers need vector<string> cls, pls; list(cls); for(unsigned i_c = 0; i_c < cls.size(); i_c++) { AutoHD<TController> cntr = at(cls[i_c]); if(!cntr.at().startStat()) continue; cntr.at().list(pls); for(unsigned i_p = 0; i_p < pls.size(); i_p++) { int errCode = cntr.at().at(pls[i_p]).at().vlAt("err").at().getI(); if(errCode == 21) { //By MR/MC bus lost mess_warning(cntr.at().nodePath().c_str(), _("Re-enable by Reinit flag for MC/MR module.")); cntr.at().disable(); cntr.at().start(); break; } } } }
void HddStat::makeActiveDA( TMdContr *a_cntr ) { string ap_nm = "Statistic_"; vector<string> list; dList(list,true); for(unsigned i_hd = 0; i_hd < list.size(); i_hd++) { string hddprm = ap_nm+list[i_hd]; if(!a_cntr->present(hddprm)) { a_cntr->add(hddprm,0); AutoHD<TMdPrm> dprm = a_cntr->at(hddprm); dprm.at().setName(_("HD statistic: ")+list[i_hd]); dprm.at().autoC(true); dprm.at().cfg("TYPE").setS(id()); dprm.at().cfg("SUBT").setS(list[i_hd]); dprm.at().cfg("EN").setB(true); if(a_cntr->enableStat()) dprm.at().enable(); } } }
void TMdPrm::enable( ) { if(enableStat()) return; //Init to direction and the reverse flag load vector<string> ls; pEl.fldList(ls); for(unsigned iEl = 0; iEl < ls.size(); iEl++) { if(ls[iEl].compare(0,4,"gpio") != 0) continue; int pin = atoi(ls[iEl].c_str()+4); AutoHD<TVal> cVl = vlAt(ls[iEl]); switch(s2i(modPrm(TSYS::strMess("GPIOmode%d",pin)))) { case 0: //Disabled cVl.at().fld().setFlg(cVl.at().fld().flg()|TFld::NoWrite); break; case 1: //Input cVl.at().fld().setFlg(cVl.at().fld().flg()|TFld::NoWrite); bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT); bcm2835_gpio_set_pud(pin, BCM2835_GPIO_PUD_OFF); break; case 2: //Input (pull up) cVl.at().fld().setFlg(cVl.at().fld().flg()|TFld::NoWrite); bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT); bcm2835_gpio_set_pud(pin, BCM2835_GPIO_PUD_UP); break; case 3: //Input (pull down) cVl.at().fld().setFlg(cVl.at().fld().flg()|TFld::NoWrite); bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT); bcm2835_gpio_set_pud(pin, BCM2835_GPIO_PUD_DOWN); break; case 4: //Output cVl.at().fld().setFlg(cVl.at().fld().flg()&(~TFld::NoWrite)); bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP); break; } cVl.at().fld().setReserve(modPrm(TSYS::strMess("GPIOrev%d",pin))); } //Functions start fList(ls); for(unsigned iL = 0; iL < ls.size(); iL++) fAt(ls[iL]).at().setStart(true); TParamContr::enable(); }
string TUIS::docGet( const string &inm, string *tp, unsigned opt ) { unsigned i_tr = 0, i_t = 0; string rez, pathi, nm = TSYS::strParse(inm, 0, "|"); vector<string> transl; //Find the offline document into filesystem int hd = -1; char types[][5] = {"pdf", "html", "odt"}; transl.push_back(""); transl.push_back(Mess->lang2Code()); transl.push_back("en"); for(int off = 0; hd == -1 && (pathi=TSYS::strParse(SYS->docDir(),0,";",&off)).size(); ) for(i_tr = 0; i_tr < transl.size(); ++i_tr) { for(i_t = 0; i_t < sizeof(types)/5; ++i_t) if((hd=open((pathi+"/"+transl[i_tr]+"/"+nm+"."+types[i_t]).c_str(),O_RDONLY)) != -1) break; if(hd != -1) break; } if(hd != -1) { if(tp) *tp = types[i_t]; if(opt == GetFilePath) rez = pathi+"/"+transl[i_tr]+"/"+nm+"."+types[i_t]; else if(opt == GetExecCommand) rez = "xdg-open "+pathi+"/"+transl[i_tr]+"/"+nm+"."+types[i_t]; else { char buf[STR_BUF_LEN]; for(int len = 0; (len=read(hd,buf,sizeof(buf))) > 0; ) rez.append(buf,len); } close(hd); } //Find the online document into network if(rez.empty() && (nm=TSYS::strParse(inm,1,"|")).size()) { const char *docHost = "wiki.oscada.org", *docURI = "/Doc", *tTr = "Sockets", *nTr = "docCheck"; transl.clear(); transl.push_back((Mess->lang2Code()=="ru")?"":Mess->lang2Code()); transl.push_back("en"); try { //Check connect and start AutoHD<TTransportOut> tr; if(!SYS->transport().at().at(tTr).at().outPresent(nTr)) { SYS->transport().at().at(tTr).at().outAdd(nTr); tr = SYS->transport().at().at(tTr).at().outAt(nTr); tr.at().setName(_("Doc check")); } else tr = SYS->transport().at().at(tTr).at().outAt(nTr); XMLNode req("GET"); for(i_tr = 0; i_tr < transl.size(); ++i_tr) { req.setAttr("URI", (transl[i_tr].size()?"/HomePage"+transl[i_tr]:"/")+docURI+"/"+nm+"?tm="+i2s(SYS->sysTm()))-> setAttr("Host", string(docHost)+":80")-> setAttr("onlyHeader", (opt!=GetContent)?"1":"0"); tr.at().messProtIO(req, "HTTP"); if(s2i(req.attr("RezCod")) == 200) { if(opt == GetFilePath) rez = string("http://")+docHost+TSYS::strParse(req.attr("URI"),0,"?"); else if(opt == GetExecCommand) rez = string("xdg-open ")+"http://"+docHost+TSYS::strParse(req.attr("URI"),0,"?"); else rez = req.text(); break; } } } catch(TError) { } } return rez; }
int TMdContr::recordCallback( const void *iBuf, void *oBuf, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ) { TMdContr &cntr = *(TMdContr*)userData; cntr.prcSt = true; const char *bptr = (const char*)iBuf; if(cntr.redntUse()) { cntr.prcSt = false; return cntr.endrunReq; } //Set priority for call task if(cntr.firstCall) { int policy = SCHED_OTHER; struct sched_param prior; pthread_getschedparam(pthread_self(), &policy, &prior); #if __GLIBC_PREREQ(2,4) if(cntr.prior() < 0) policy = SCHED_BATCH; #endif if(cntr.prior() > 0) { policy = SCHED_RR; prior.sched_priority = cntr.prior(); } if(pthread_setschedparam(pthread_self(), SCHED_FIFO, &prior) == EPERM) setpriority(PRIO_PROCESS, syscall(SYS_gettid), -cntr.prior()/5); cntr.firstCall = false; } //Check for current time correction int64_t t_sz = (1000000ll*framesPerBuffer)/cntr.sRt; double err = ((timeInfo->inputBufferAdcTime-cntr.inAdcTimePrev)-1e-6*t_sz)/(1e-6*t_sz); //Pass short framesPerBuffer by incorrect cntr.framesPerBufferMax = vmax(cntr.framesPerBufferMax,framesPerBuffer); if(framesPerBuffer < cntr.framesPerBufferMax) { cntr.inAdcTimePrev = timeInfo->inputBufferAdcTime; return paContinue; } // Lost frames process if(cntr.inAdcTimePrev > 0 && err > 0.001) { cntr.wTm += (int64_t)((double)t_sz*err); mess_warning(cntr.nodePath().c_str(), _("CallBack: Lost frames correct: framesPerBuffer=%lu; sRt=%d; t_sz=%lld; err=%g; diff=%lld."), framesPerBuffer, cntr.sRt, t_sz, err, (TSYS::curTime()-cntr.wTm)); cntr.lostFrmsCntr++; } // Sound counter difference from time clock correction else if(cntr.inAdcTimeAdj < 0 || (timeInfo->inputBufferAdcTime-cntr.inAdcTimeAdj) >= 60) { int64_t dTm = TSYS::curTime()-cntr.wTm; if(cntr.inAdcTimeAdj > 0) cntr.sRt -= (dTm-cntr.tmAdj)*cntr.sRt/60000000; if(cntr.messLev() == TMess::Debug) mess_debug_(cntr.nodePath().c_str(), _("CallBack: Sound counter difference fix: sRt=%d; dTm=%lld."), cntr.sRt, dTm); cntr.tmAdj = dTm; cntr.inAdcTimeAdj = timeInfo->inputBufferAdcTime; } cntr.inAdcTimePrev = timeInfo->inputBufferAdcTime; //Input buffer process ResAlloc res(cntr.nodeRes(),false); for(unsigned i_p = 0; i_p < cntr.pHd.size(); i_p++) { int chn = cntr.pHd[i_p].at().iCnl(); AutoHD<TVal> val = cntr.pHd[i_p].at().vlAt("val"); AutoHD<TVArchive> arch = val.at().arch(); bool archAllow = (!arch.freeStat() && arch.at().srcMode() == TVArchive::PassiveAttr); switch(cntr.mSmplType) { case paFloat32: if(archAllow) for(int64_t i_t = 0; i_t < t_sz; i_t += arch.at().period()) arch.at().setR(*(float*)(bptr+cntr.smplSize*((i_t*framesPerBuffer/t_sz)*cntr.numChan+chn)), cntr.wTm+i_t); if(SYS->sysTm() > cntr.cTm) { val.at().setR(*(float*)(bptr+cntr.smplSize*((framesPerBuffer-1)*cntr.numChan+chn)),cntr.wTm+(1000000ll*(framesPerBuffer-1))/cntr.sRt,true); cntr.cTm = SYS->sysTm(); } break; case paInt32: if(archAllow) for(int64_t i_t = 0; i_t < t_sz; i_t += arch.at().period()) arch.at().setI(*(int32_t*)(bptr+cntr.smplSize*((i_t*framesPerBuffer/t_sz)*cntr.numChan+chn)), cntr.wTm+i_t); if(SYS->sysTm() > cntr.cTm) { val.at().setI(*(int32_t*)(bptr+cntr.smplSize*((framesPerBuffer-1)*cntr.numChan+chn)),cntr.wTm+(1000000ll*(framesPerBuffer-1))/cntr.sRt,true); cntr.cTm = SYS->sysTm(); } break; case paInt16: if(archAllow) for(int64_t i_t = 0; i_t < t_sz; i_t += arch.at().period()) arch.at().setI(*(int16_t*)(bptr+cntr.smplSize*((i_t*framesPerBuffer/t_sz)*cntr.numChan+chn)), cntr.wTm+i_t); if(SYS->sysTm() > cntr.cTm) { val.at().setI(*(int16_t*)(bptr+cntr.smplSize*((framesPerBuffer-1)*cntr.numChan+chn)),cntr.wTm+(1000000ll*(framesPerBuffer-1))/cntr.sRt,true); cntr.cTm = SYS->sysTm(); } break; } } cntr.wTm += t_sz; cntr.acqSize += (float)(framesPerBuffer*cntr.smplSize*cntr.numChan)/1048576; cntr.prcSt = false; return cntr.endrunReq; }
string TMdContr::modBusReq( string &pdu, bool MC, bool broadCast ) { char buf[1024]; string mbap, rez, err; try { //> Transport creation for MC and MR busses and connect AutoHD<TTransportOut> tro = SYS->transport().at().nodeAt(MC?"Serial.out_SMH2Gi_MC":"Serial.out_SMH2Gi_MR", 0, '.', 0, true); if(tro.freeStat()) { SYS->transport().at().at("Serial").at().outAdd(MC?"SMH2Gi_MC":"SMH2Gi_MR"); tro = SYS->transport().at().nodeAt(MC?"Serial.out_SMH2Gi_MC":"Serial.out_SMH2Gi_MR", 0, '.', 0, true); //>> Typical parameters set tro.at().setDscr(TSYS::strMess(_("Segnetics SMH2Gi automatic created transport for '%s' bus"),MC?"MC":"MR")); tro.at().setAddr(MC?(cfg("MC_DEV").getS()+":230400:8N1"):(cfg("MR_DEV").getS()+":230400:8N2")); } ResAlloc resN(tro.at().nodeRes(), true); //> Start stoped transport if(!tro.at().startStat()) tro.at().start(); //> Prepare request mbap.reserve(pdu.size()+2); mbap += pdu; uint16_t crc = CRC16(mbap); mbap += (crc>>8); mbap += crc; //> Send request for(int i_tr = 0; i_tr < connTry; i_tr++) { if(messLev() == TMess::Debug) mess_debug_(nodePath().c_str(), _("ModBUS REQ -> '%s': %s"), tro.at().id().c_str(), TSYS::strDecode(mbap,TSYS::Bin," ").c_str()); int resp_len = tro.at().messIO(mbap.data(), mbap.size(), (broadCast?NULL:buf), sizeof(buf), 0, true); if(broadCast) { err = ""; break; } rez.assign(buf, resp_len); //> Wait tail while(resp_len) { try{ resp_len = tro.at().messIO(NULL, 0, buf, sizeof(buf), 0, true); } catch(TError err){ break; } rez.append(buf, resp_len); } if(rez.size() < 2) { err = _("13:Error respond: Too short."); continue; } if(CRC16(rez.substr(0,rez.size()-2)) != (uint16_t)((rez[rez.size()-2]<<8)+(uint8_t)rez[rez.size()-1])) { err = _("13:Error respond: CRC check error."); continue; } if(messLev() == TMess::Debug) mess_debug_(nodePath().c_str(), _("ModBUS RESP -> '%s': %s"), tro.at().id().c_str(), TSYS::strDecode(rez,TSYS::Bin," ").c_str()); pdu = rez.substr(0, rez.size()-2); err = ""; break; } } catch(TError ierr) { err = "10:"+ierr.mess; } if(messLev() >= TMess::Error && err.size()) mess_err(nodePath().c_str(), "%s", err.c_str()); if(messLev() == TMess::Debug && err.size()) mess_debug_(nodePath().c_str(), _("ModBUS ERR -> %s: %s"), TSYS::strDecode(mbap,TSYS::Bin," ").c_str(), err.c_str()); return err; }
void SUNXI::enable( TParamContr *ip ) { TMdPrm *p = (TMdPrm *)ip; if(sunxi_gpio_init() != 0) throw TError(p->nodePath().c_str(),_("Init SUNXI GPIO library error whether that is not SUNXI or there is not access.")); MtxAlloc res(p->owner().dataRes(), true); if(use) throw TError(p->nodePath().c_str(), _("SUNXI GPIO is already used.")); use = true; //Init for loading the direction and reversion flag vector<string> ls; p->pEl.fldList(ls); for(unsigned iEl = 0; iEl < ls.size(); iEl++) { if(ls[iEl].compare(0,4,"gpio") != 0) continue; int pin = atoi(ls[iEl].c_str()+4); AutoHD<TVal> cVl = p->vlAt(ls[iEl]); switch(s2i(p->modPrm(TSYS::strMess("GPIOmode%d",pin)))) { case 0: //Disabled cVl.at().fld().setFlg(cVl.at().fld().flg()|TFld::NoWrite); break; case 1: //Input cVl.at().fld().setFlg(cVl.at().fld().flg()|TFld::NoWrite); sunxi_gpio_set_cfgpin(pin, SUNXI_GPIO_INPUT); sunxi_gpio_pullup(pin, SUNXI_PULL_NONE); break; case 2: //Input (pull up) cVl.at().fld().setFlg(cVl.at().fld().flg()|TFld::NoWrite); sunxi_gpio_set_cfgpin(pin, SUNXI_GPIO_INPUT); //Or SUNXI_GPIO_PER sunxi_gpio_pullup(pin, SUNXI_PULL_UP); break; case 3: //Input (pull down) cVl.at().fld().setFlg(cVl.at().fld().flg()|TFld::NoWrite); sunxi_gpio_set_cfgpin(pin, SUNXI_GPIO_INPUT); //Or SUNXI_GPIO_PER sunxi_gpio_pullup(pin, SUNXI_PULL_DOWN); break; case 4: //Output cVl.at().fld().setFlg(cVl.at().fld().flg()&(~TFld::NoWrite)); sunxi_gpio_set_cfgpin(pin, SUNXI_GPIO_OUTPUT); break; } cVl.at().fld().setReserve(p->modPrm(TSYS::strMess("GPIOrev%d",pin))); } //Register the functions p->fReg(new GPIO_mode()); p->fReg(new GPIO_get()); p->fReg(new GPIO_put()); }
void *TMdContr::Task( void *icntr ) { vector<string> als; string nId; TMdContr &cntr = *(TMdContr *)icntr; cntr.endrun_req = false; cntr.prc_st = true; bool firstCall = true; XML_N req("opc.tcp"); req.setAttr("id", "Read")->setAttr("timestampsToReturn", TSYS::int2str(TS_NEITHER)); try { for(unsigned int it_cnt = cntr.p_hd.size(); !cntr.endrun_req; it_cnt++) { if(cntr.redntUse()) { TSYS::sysSleep(1); continue; } if(cntr.tmDelay > 0){ TSYS::sysSleep(1); cntr.tmDelay = vmax(0,cntr.tmDelay-1); continue; } int64_t t_cnt = TSYS::curTime(); cntr.call_st = true; unsigned int div = cntr.period() ? (unsigned int)(cntr.syncPer()/(1e-9*cntr.period())) : 0; ResAlloc res(cntr.en_res, false); if(!req.childSize() || cntr.mPCfgCh || (div && (it_cnt%div) < cntr.p_hd.size())) { if(div && (it_cnt%div) < cntr.p_hd.size()) cntr.p_hd[it_cnt%div].at().attrPrc(); //> Prepare nodes list req.childClear(); req.childAdd("node")->setAttr("prmId", "OPC_UA_Server")->setAttr("prmAttr", "ServerStatus_State")-> setAttr("nodeId", "2259")->setAttr("attributeId", "13"); for(unsigned i_p = 0; i_p < cntr.p_hd.size(); i_p++) { if(firstCall) cntr.p_hd[i_p].at().attrPrc(); cntr.p_hd[i_p].at().vlList(als); for(unsigned i_a = 0; i_a < als.size(); i_a++) { nId = TSYS::strLine(cntr.p_hd[i_p].at().vlAt(als[i_a]).at().fld().reserve(), 0); if(nId.empty()) continue; req.childAdd("node")->setAttr("prmId", cntr.p_hd[i_p].at().id())-> setAttr("prmAttr", als[i_a])->setAttr("nodeId", nId)->setAttr("attributeId", "13"); } } cntr.mPCfgCh = false; } res.release(); cntr.reqService(req); //> Place results bool isErr = !req.attr("err").empty(), ndSt = 0; AutoHD<TVal> vl; res.request(false); for(unsigned i_c = 0, i_p = 0; i_c < req.childSize() && i_p < cntr.p_hd.size(); i_c++) { XML_N *cnX = req.childGet(i_c); if(cnX->attr("prmId") == "OPC_UA_Server" && cnX->attr("prmAttr") == "ServerStatus_State") { cntr.servSt = strtoul(cnX->text().c_str(),NULL,10); continue; } while(cnX->attr("prmId") != cntr.p_hd[i_p].at().id()) i_p++; if(i_p >= cntr.p_hd.size()) break; if(cntr.p_hd[i_p].at().vlPresent(cnX->attr("prmAttr"))) { ndSt = strtol(cnX->attr("Status").c_str(),NULL,0); vl = cntr.p_hd[i_p].at().vlAt(cnX->attr("prmAttr")); vl.at().setS((isErr||ndSt)?EVAL_STR:cnX->text(),0,true); vl.at().fld().setLen(ndSt); } } if(isErr) { cntr.acq_err.setVal(req.attr("err")); mess_err(cntr.nodePath().c_str(), "%s", cntr.acq_err.getVal().c_str()); cntr.tmDelay = cntr.syncPer(); continue; } else if(cntr.tmDelay == -1) cntr.acq_err.setVal(""); res.release(); firstCall = false; cntr.tm_gath = TSYS::curTime()-t_cnt; cntr.call_st = false; TSYS::taskSleep(cntr.period(), cntr.period() ? 0 : TSYS::cron(cntr.cron())); } } catch(TError err){ mess_err(err.cat.c_str(), err.mess.c_str()); } cntr.prc_st = false; return NULL; }
void UpTime::makeActiveDA( TMdContr *aCntr ) { vector<string> pLs; aCntr->list(pLs); unsigned i_p; for(i_p = 0; i_p < pLs.size(); i_p++) { AutoHD<TMdPrm> p = aCntr->at(pLs[i_p]); if(p.at().cfg("TYPE").getS() == id() && p.at().cfg("SUBT").getS() == "sys") break; } if(i_p >= pLs.size()) { string ap_nm = "UpTimeSystem"; while(aCntr->present(ap_nm)) ap_nm = TSYS::strLabEnum(ap_nm); FILE *f = fopen("/proc/uptime","r"); if(f != NULL) { aCntr->add(ap_nm, 0); AutoHD<TMdPrm> dprm = aCntr->at(ap_nm); dprm.at().setName(_("System up time")); dprm.at().autoC(true); dprm.at().cfg("TYPE").setS(id()); dprm.at().cfg("SUBT").setS("sys"); dprm.at().cfg("EN").setB(true); if(aCntr->enableStat()) dprm.at().enable(); fclose(f); } } for(i_p = 0; i_p < pLs.size(); i_p++) { AutoHD<TMdPrm> p = aCntr->at(pLs[i_p]); if(p.at().cfg("TYPE").getS() == id() && p.at().cfg("SUBT").getS() == "stat") break; } if(i_p >= pLs.size()) { string ap_nm = "UpTimeStation"; while(aCntr->present(ap_nm)) ap_nm = TSYS::strLabEnum(ap_nm); aCntr->add(ap_nm, 0); AutoHD<TMdPrm> dprm = aCntr->at(ap_nm); dprm.at().setName(_("Station up time")); dprm.at().autoC(true); dprm.at().cfg("TYPE").setS(id()); dprm.at().cfg("SUBT").setS("stat"); dprm.at().cfg("EN").setB(true); if(aCntr->enableStat()) dprm.at().enable(); } }
bool TProt::inReq( string &request, const string &inPrtId, string *answ ) { ResAlloc res(enRes, false); bool rez = Server::inReq(request, inPrtId, answ); res.unlock(); #ifdef POOL_OF_TR //Pool for subscriptions process AutoHD<TProtIn> ip = at(inPrtId); if(ip.at().waitReqTm() && !ip.at().mSubscrIn && epPresent(ip.at().mEp)) { int64_t wTm = SYS->curTime(); AutoHD<OPCEndPoint> ep = epAt(ip.at().mEp); bool tmToCall = (wTm-ip.at().mPrevTm)/1000 >= ip.at().waitReqTm(); if(tmToCall || ep.at().forceSubscrQueue) { if(tmToCall) ep.at().forceSubscrQueue = false; if(!ep.at().forceSubscrQueue) ip.at().mSubscrCntr++; ip.at().mPrevTm = wTm; ip.at().mSubscrIn = true; epAt(ip.at().mEp).at().subScrCycle(ip.at().mSubscrCntr, answ, inPrtId); ip.at().mSubscrIn = false; } } #endif return rez; }
void TSocketIn::messPut( int sock, string &request, string &answer, string sender, AutoHD<TProtocolIn> &prot_in ) { AutoHD<TProtocol> proto; string n_pr = mod->modId()+"_"+id()+"_"+TSYS::int2str(sock); try { proto = SYS->protocol().at().modAt(protocol()); if( prot_in.freeStat() ) { if( !proto.at().openStat(n_pr) ) proto.at().open( n_pr, workId() ); prot_in = proto.at().at( n_pr ); } if( prot_in.at().mess(request,answer,sender) ) return; prot_in.free(); if( proto.at().openStat(n_pr) ) proto.at().close(n_pr); }catch(TError err) { prot_in.free(); if( !proto.freeStat() && proto.at().openStat(n_pr) ) proto.at().close( n_pr ); mess_err(nodePath().c_str(),"%s",err.mess.c_str() ); mess_err(nodePath().c_str(),_("Error request to protocol.")); } }
void *TSocketIn::ClTask( void *s_inf ) { SSockIn &s = *(SSockIn *)s_inf; int rez; char err[255]; char buf[s.s->bufLen()*1024]; string req, answ; AutoHD<TProtocolIn> prot_in; SSL *ssl; int cSock = s.s->clientReg(pthread_self()); if(mess_lev() == TMess::Debug) mess_debug(s.s->nodePath().c_str(),_("Socket has been connected by '%s'!"),s.sender.c_str()); if(BIO_do_handshake(s.bio) <= 0) { if(BIO_should_retry(s.bio)) while(BIO_should_retry(s.bio) && !s.s->endrun_cl) { BIO_do_handshake(s.bio); TSYS::sysSleep(STD_WAIT_DELAY*1e-3); } else { if(ERR_peek_last_error()) { ERR_error_string_n(ERR_peek_last_error(),err,sizeof(err)); mess_err(s.s->nodePath().c_str(),"BIO_should_retry: %s",err); } BIO_flush(s.bio); delete (SSockIn*)s_inf; return NULL; } } int sock_fd = BIO_get_fd(s.bio,NULL); BIO_get_ssl(s.bio,&ssl); //> Select mode struct timeval tv; fd_set rd_fd; int cnt = 0; //> Requests counter int tm = time(NULL); //> Last connection time do { if(!SSL_pending(ssl)) { tv.tv_sec = 0; tv.tv_usec = STD_WAIT_DELAY*1000; FD_ZERO(&rd_fd); FD_SET(sock_fd,&rd_fd); int kz = select(sock_fd+1,&rd_fd,NULL,NULL,&tv); if( kz == 0 || (kz == -1 && errno == EINTR) || kz < 0 || !FD_ISSET(sock_fd,&rd_fd) ) continue; } rez = BIO_read(s.bio,buf,sizeof(buf)); if(rez <= 0) break; //Connection closed by client if(mess_lev() == TMess::Debug) mess_debug(s.s->nodePath().c_str(),_("The message is received with the size '%d'."),rez); req.assign(buf,rez); s.s->sock_res.resRequestW(); s.s->trIn += rez; s.s->sock_res.resRelease(); s.s->messPut(cSock,req,answ,s.sender,prot_in); if(answ.size()) { if(mess_lev() == TMess::Debug) mess_debug(s.s->nodePath().c_str(),_("The message is replied with the size '%d'."),answ.size()); do { rez = BIO_write(s.bio,answ.data(),answ.size()); } while(rez < 0 && SSL_get_error(ssl,rez) == SSL_ERROR_WANT_WRITE); s.s->sock_res.resRequestW(); s.s->trOut += vmax(0, rez); s.s->sock_res.resRelease(); answ = ""; cnt++; tm = time(NULL); } } while(!s.s->endrun_cl && (!s.s->keepAliveCon() || cnt < s.s->keepAliveCon()) && (!s.s->keepAliveTm() || (time(NULL)-tm) < s.s->keepAliveTm())); BIO_flush(s.bio); close(sock_fd); //BIO_reset(s.bio); BIO_free(s.bio); //> Close protocol on broken connection if( !prot_in.freeStat() ) { string n_pr = prot_in.at().name(); prot_in.free(); AutoHD<TProtocol> proto = SYS->protocol().at().modAt(s.s->protocol()); if( proto.at().openStat(n_pr) ) proto.at().close(n_pr); } s.s->clientUnreg( pthread_self() ); if(mess_lev() == TMess::Debug) mess_debug(s.s->nodePath().c_str(),_("Socket has been disconnected (%d)."),s.s->cl_id.size()); delete (SSockIn*)s_inf; return NULL; }
void Prm::enable( ) { if(enableStat()) return; string ioLs = cfg("IO").getS(); //Check and delete no used fields /*for(int i_fld = 0; i_fld < (int)v_el.fldSize(); i_fld++) { if(v_el.fldAt(i_fld).reserve().empty()) continue; string fel; for(int io_off = 0; (fel=TSYS::strSepParse(ioLs,0,'\n',&io_off)).size(); ) if(TSYS::strSepParse(fel,0,':') == v_el.fldAt(i_fld).reserve()) break; if(fel.empty()) { try{ v_el.fldDel(i_fld); i_fld--; } catch(TError err) { mess_err(err.cat.c_str(),"%s",err.mess.c_str()); } } }*/ //Init elements vector<string> pls; AutoHD<Block> blk; int io, if_off, id_off; string mio, ioaddr, ioblk, ioid, aid, anm; for(int io_off = 0; (mio=TSYS::strParse(ioLs,0,"\n",&io_off)).size(); ) { if(mio[0] == '#') continue; if_off = id_off = 0; ioaddr = TSYS::strParse(mio,0,":",&if_off); ioblk = TSYS::strParse(ioaddr,0,".",&id_off); ioid = ioaddr.substr(id_off); aid = TSYS::strParse(mio,0,":",&if_off); anm = TSYS::strParse(mio,0,":",&if_off); if(ioblk.empty() || ioid.empty()) continue; unsigned flg = 0; TFld::Type tp = TFld::String; string reserve; // Constant attributes if(ioblk[0] == '*') { if(aid.empty()) continue; if(anm.empty()) anm = aid; if(ioblk.size() > 1) switch(ioblk[1]) { case 's': case 'S': tp = TFld::String; break; case 'i': case 'I': tp = TFld::Integer; break; case 'r': case 'R': tp = TFld::Real; break; case 'b': case 'B': tp = TFld::Boolean; break; } flg = TFld::NoWrite; } // Links to block's io else { if(aid.empty()) aid = ioblk+"_"+ioid; if(!((Contr&)owner()).blkPresent(ioblk)) continue; blk = ((Contr&)owner()).blkAt(ioblk); if((io=blk.at().ioId(ioid)) < 0) continue; if(anm.empty()) anm = blk.at().func()->io(io)->name(); tp = TFld::type(blk.at().ioType(io)); flg = TVal::DirWrite|TVal::DirRead; reserve = ioaddr; } // Attribute creation if(!v_el.fldPresent(aid) || v_el.fldAt(v_el.fldId(aid)).type() != tp || v_el.fldAt(v_el.fldId(aid)).flg() != flg) { if(v_el.fldPresent(aid)) v_el.fldDel(v_el.fldId(aid)); v_el.fldAdd(new TFld(aid.c_str(),"",tp,flg)); } int el_id = v_el.fldId(aid); v_el.fldAt(el_id).setDescr(anm); v_el.fldAt(el_id).setReserve(ioaddr); if(ioblk[0] == '*') vlAt(aid).at().setS(ioid,0,true); pls.push_back(aid); } //Check and delete no used attrs for(int i_fld = 0; i_fld < (int)v_el.fldSize(); i_fld++) { int i_p; for(i_p = 0; i_p < (int)pls.size(); i_p++) if(pls[i_p] == v_el.fldAt(i_fld).name()) break; if(i_p < (int)pls.size()) continue; try{ v_el.fldDel(i_fld); i_fld--; } catch(TError err) { mess_err(err.cat.c_str(),"%s",err.mess.c_str()); } } TParamContr::enable(); }