예제 #1
0
파일: val.cpp 프로젝트: Strongc/openscada
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);
}
예제 #2
0
파일: module.cpp 프로젝트: gavioto/oscada
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;
}
예제 #3
0
파일: mess.cpp 프로젝트: alimon/oscada
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;
}
예제 #4
0
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."));
    }
}
예제 #5
0
파일: mess.cpp 프로젝트: Strongc/openscada
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;
}
예제 #6
0
//*************************************************
//* 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())); }
}
예제 #7
0
파일: sound.cpp 프로젝트: Strongc/openscada
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;
}