//OpenSCADA module DAQ.Fastwel file: module.cpp /*************************************************************************** * Copyright (C) 2014-2016 by Maxim Kochetkov * * fido_max@inbox.ru * * * * 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 #include #include #include #include #include #include #include "module.h" //************************************************* //* Module info! * #define MOD_ID "Fastwel" #define MOD_NAME _("Fastwel IO") #define MOD_TYPE SDAQ_ID #define VER_TYPE SDAQ_VER #define MOD_VER "0.1.26" #define AUTHORS _("Maxim Kochetkov") #define DESCRIPTION _("Fastwel IO FBUS client implementation") #define LICENSE "GPL2" //************************************************* ModFastwel::TTpContr * ModFastwel::mod; //Pointer for direct access to the module //!!! Required section for binding OpenSCADA core to this module. It provides information and create module root object. //!!! Do not remove this section! extern "C" { #ifdef MOD_INCL TModule::SAt daq_Fastwel_module(int n_mod) #else TModule::SAt module(int n_mod) #endif { if(n_mod == 0) return TModule::SAt(MOD_ID, MOD_TYPE, VER_TYPE); return TModule::SAt(""); } #ifdef MOD_INCL TModule *daq_Fastwel_attach(const TModule::SAt & AtMod, const string & source) #else TModule *attach(const TModule::SAt & AtMod, const string & source) #endif { if(AtMod == TModule::SAt(MOD_ID, MOD_TYPE, VER_TYPE)) return new ModFastwel::TTpContr(source); return NULL; } } using namespace ModFastwel; //************************************************* //* TTpContr * //************************************************* TTpContr::TTpContr(string name) : TTypeDAQ(MOD_ID) { mod = this; modInfoMainSet(MOD_NAME, MOD_TYPE, MOD_VER, AUTHORS, DESCRIPTION, LICENSE, name); } TTpContr::~TTpContr() { } void TTpContr::load_() { FBUS_Start(); } void TTpContr::save_() { } void TTpContr::FBUS_Start() { // modif(); ResAlloc res(FBUSRes, true); if(FBUS_initOK) FBUS_finish(); if(fbusInitialize() != FBUS_RES_OK) { throw TError(nodePath(), _("FBUS init failed.")); } else { FBUS_initOK = true; for(int i = 0; i < FBUS_MAX_NET; i++) { hNet[i] = FBUS_INVALID_HANDLE; } FBUS_fbusGetVersion(); } } void TTpContr::FBUS_finish() { ResAlloc res(FBUSRes, true); fbusDeInitialize(); FBUS_initOK = false; } void TTpContr::FBUS_fbusGetVersion() { ResAlloc res(FBUSRes, true); fbusGetVersion(&verMajor, &verMinor); mModVers=TSYS::strMess("%s FBUS: %d.%d", MOD_VER, verMajor, verMinor); } void TTpContr::FBUS_fbusOpen(int n) { if(hNet[n] == FBUS_INVALID_HANDLE) { if(fbusOpen(n, &hNet[n]) != FBUS_RES_OK) { hNet[n] = FBUS_INVALID_HANDLE; throw TError(nodePath().c_str(), _("FBUS open net #%d failed."), n); } } } void TTpContr::FBUS_fbusClose(int n) { if(hNet[n] != FBUS_INVALID_HANDLE) { if(fbusClose(n) != FBUS_RES_OK) { throw TError(nodePath().c_str(), _("FBUS open net #%d failed."), n); } else { hNet[n] = FBUS_INVALID_HANDLE; } } } void TTpContr::FBUS_fbusRescan(int n) { if(fbusRescan(hNet[n], &(modCount[n])) != FBUS_RES_OK) { throw TError(nodePath().c_str(), _("FBUS rescan net #%d failed."), n); } } void TTpContr::FBUS_fbusGetNodeDescription(int n, int id, PFIO_MODULE_DESC modDesc) { if(fbusGetNodeDescription(hNet[n], id, modDesc, sizeof(*modDesc)) != FBUS_RES_OK) { throw TError(nodePath().c_str(), _("FBUS GetNodeDescription net #%d, #id%d failed."), n, id); } } int TTpContr::FBUS_fbusReadInputs(int n, int id, void *Buf, size_t offset, size_t size) { return fbusReadInputs(hNet[n], id, Buf, offset, size); } int TTpContr::FBUS_fbusSetNodeSpecificParameters(int n, int id, void *Buf, size_t offset, size_t size) { return fbusSetNodeSpecificParameters(hNet[n], id, Buf, offset, size); } int TTpContr::FBUS_fbusGetNodeSpecificParameters(int n, int id, void *Buf, size_t offset, size_t size) { return fbusGetNodeSpecificParameters(hNet[n], id, Buf, offset, size); } int TTpContr::FBUS_fbusGetNodeCommonParameters(int n, int id, PFIO_MODULE_COMMON_CONF Buf, size_t size) { return fbusGetNodeCommonParameters(hNet[n], id, Buf, size); } int TTpContr::FBUS_fbusSetNodeCommonParameters(int n, int id, PFIO_MODULE_COMMON_CONF Buf, size_t size) { return fbusSetNodeCommonParameters(hNet[n], id, Buf, size); } int TTpContr::FBUS_fbusWriteConfig(int n, int id) { return fbusWriteConfig(hNet[n], id); } int TTpContr::FBUS_fbusReadConfig(int n, int id) { return fbusReadConfig(hNet[n], id); } int TTpContr::FBUS_fbusSaveConfig(int n, int id) { return fbusSaveConfig(hNet[n], id); } int TTpContr::FBUS_fbusWriteOutputs(int n, int id, void *Buf, size_t offset, size_t size) { return fbusWriteOutputs(hNet[n], id, Buf, offset, size); } void TTpContr::postEnable(int flag) { TTypeDAQ::postEnable(flag); //> Controler's bd structure fldAdd(new TFld("PRM_BD_DIM762", _("DIM762 Parameters table"), TFld::String, TFld::NoFlag, "30", "")); //????[v1.0] Remove fldAdd(new TFld("PRM_BD_DIM716", _("DIM716 Parameters table"), TFld::String, TFld::NoFlag, "30", "")); //????[v1.0] Remove fldAdd(new TFld("PRM_BD_DIM718", _("DIM718 Parameters table"), TFld::String, TFld::NoFlag, "30", "")); //????[v1.0] Remove fldAdd(new TFld("PRM_BD_AIM791", _("AIM791 Parameters table"), TFld::String, TFld::NoFlag, "30", "")); //????[v1.0] Remove fldAdd(new TFld("PRM_BD_AIM726", _("AIM726 Parameters table"), TFld::String, TFld::NoFlag, "30", "")); //????[v1.0] Remove fldAdd(new TFld("PRM_BD_AIM730", _("AIM730 Parameters table"), TFld::String, TFld::NoFlag, "30", "")); //????[v1.0] Remove fldAdd(new TFld("PRM_BD_AIM725", _("AIM725 Parameters table"), TFld::String, TFld::NoFlag, "30", "")); //????[v1.0] Remove fldAdd(new TFld("PRM_BD_DIM765", _("DIM765 Parameters table"), TFld::String, TFld::NoFlag, "30", "")); //????[v1.0] Remove fldAdd(new TFld("SCHEDULE", _("Acquisition schedule"), TFld::String, TFld::NoFlag, "100", "1")); fldAdd(new TFld("PRIOR", _("Priority of the acquisition task"), TFld::Integer, TFld::NoFlag, "2", "0", "-1;199")); fldAdd(new TFld("NET_ID", _("Network number"), TFld::Integer, TFld::NoFlag, "0", "0", "0;63")); //> Parameter DIM762 bd structure int t_prm = tpParmAdd("DIM762", "PRM_BD_DIM762", _("DIM762"), true); tpPrmAt(t_prm).fldAdd(new TFld("DEV_ID", _("Device address"), TFld::Integer, TCfg::NoVal, "2", "0", "0;63")); tpPrmAt(t_prm).fldAdd(new TFld("DI_DEBOUNCE", _("Debounce"), TFld::Integer, TFld::Selectable | TCfg::NoVal, "1", "0", "0;1;2", _("No;200us;3ms"))); tpPrmAt(t_prm).fldAdd(new TFld("DI_COUNT", _("Enable counting"), TFld::Boolean, TCfg::NoVal, "1", "0")); //> Parameter DIM716 bd structure t_prm = tpParmAdd("DIM716", "PRM_BD_DIM716", _("DIM716"), true); tpPrmAt(t_prm).fldAdd(new TFld("DEV_ID", _("Device address"), TFld::Integer, TCfg::NoVal, "2", "0", "0;63")); tpPrmAt(t_prm).fldAdd(new TFld("DI_DEBOUNCE", _("Debounce"), TFld::Integer, TFld::Selectable | TCfg::NoVal, "1", "0", "0;1;2", _("No;200us;3ms"))); tpPrmAt(t_prm).fldAdd(new TFld("DI_COUNT", _("Enable counting"), TFld::Boolean, TCfg::NoVal, "1", "0")); //> Parameter DIM718 bd structure t_prm = tpParmAdd("DIM718", "PRM_BD_DIM718", _("DIM718"), true); tpPrmAt(t_prm).fldAdd(new TFld("DEV_ID", _("Device address"), TFld::Integer, TCfg::NoVal, "2", "0", "0;63")); //> Parameter AIM791 bd structure t_prm = tpParmAdd("AIM791", "PRM_BD_AIM791", _("AIM791")); tpPrmAt(t_prm).fldAdd(new TFld("DEV_ID", _("Device address"), TFld::Integer, TCfg::NoVal, "2", "0", "0;63")); tpPrmAt(t_prm).fldAdd(new TFld("AI_RANGE", _("Input range"), TFld::Integer, TFld::Selectable | TCfg::NoVal, "1", "0", "0;1;2", _("0..5mA;0..20mA;4..20mA"))); tpPrmAt(t_prm).fldAdd(new TFld("AI_SCANRATE", _("Scan Rate"), TFld::Integer, TCfg::NoVal, "3", "1", "1;250")); tpPrmAt(t_prm).fldAdd(new TFld("AI_FILTER", _("Filter depth"), TFld::Integer, TCfg::NoVal, "3", "0", "0;255")); //> Parameter AIM726 bd structure t_prm = tpParmAdd("AIM726", "PRM_BD_AIM726", _("AIM726")); tpPrmAt(t_prm).fldAdd(new TFld("DEV_ID", _("Device address"), TFld::Integer, TCfg::NoVal, "2", "0", "0;63")); tpPrmAt(t_prm).fldAdd(new TFld("AI_FILTER", _("Filter depth"), TFld::Integer, TFld::Selectable | TCfg::NoVal, "1", "0", "0;1:2", _("50Hz;500Hz;1000Hz"))); //> Parameter AIM730 bd structure t_prm = tpParmAdd("AIM730", "PRM_BD_AIM730", _("AIM730")); tpPrmAt(t_prm).fldAdd(new TFld("DEV_ID", _("Device address"), TFld::Integer, TCfg::NoVal, "2", "0", "0;63")); tpPrmAt(t_prm).fldAdd(new TFld("AO_RANGE", _("Output range"), TFld::Integer, TFld::Selectable | TCfg::NoVal, "1", "0", "0;1", _("0..20mA;4..20mA"))); //> Parameter AIM725 bd structure t_prm = tpParmAdd("AIM725", "PRM_BD_AIM725", _("AIM725")); tpPrmAt(t_prm).fldAdd(new TFld("DEV_ID", _("Device address"), TFld::Integer, TCfg::NoVal, "2", "0", "0;63")); tpPrmAt(t_prm).fldAdd( new TFld("AI_RANGE", _("Sensor range"), TFld::Integer, TFld::Selectable | TCfg::NoVal, "1", "0", "13;0;1;2;3;4;5;7;14;8;9;10;11;12", _("PT50;PT100;PT200;PT500;PT1000;NI100;NI120;CU100;CU50;0-150 Ohm;0-300 Ohm;0-600 Ohm;0-1500 Ohm; 0-3000 Ohm"))); tpPrmAt(t_prm).fldAdd(new TFld("AI_TYPE", _("Sensor type"), TFld::Integer, TFld::Selectable | TCfg::NoVal, "1", "0", "0;1", _("2-wire;3-wire"))); //> Parameter DIM765/766 bd structure t_prm = tpParmAdd("DIM765_766", "PRM_BD_DIM765", _("DIM765/766")); tpPrmAt(t_prm).fldAdd(new TFld("DEV_ID", _("Device address"), TFld::Integer, TCfg::NoVal, "2", "0", "0;63")); for(int i = 0; i < 8; i++) { tpPrmAt(t_prm).fldAdd( new TFld(TSYS::strMess("DI_TYPE_%d", i).c_str(), TSYS::strMess(_("Type %d"), i).c_str(), TFld::Integer, TFld::Selectable | TCfg::NoVal, "1", "0", "0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;255", _("No break detection;1K8;2K2;2K7;3K3;3K9;4K7;5K6;6K8;8K2;10K;12K;15K;18K;20K;22K;24K;27K;30K;33K;Type 2"))); tpPrmAt(t_prm).fldAdd( new TFld(TSYS::strMess("DI_DEBOUNCE_ON_%d", i).c_str(), TSYS::strMess(_("Debounce on %d"), i).c_str(), TFld::Integer, TFld::Selectable | TCfg::NoVal, "1", "0", "0;1;2;3;4;5;6;7;8;9", _("OFF;1.4ms;2.8ms;4.2ms;9.8ms;2" "0ms;50ms;100ms;200ms;300ms"))); tpPrmAt(t_prm).fldAdd( new TFld(TSYS::strMess("DI_DEBOUNCE_OFF_%d", i).c_str(), TSYS::strMess(_("Debounce off %d"), i).c_str(), TFld::Integer, TFld::Selectable | TCfg::NoVal, "1", "0", "0;1;2;3;4;5;6;7;8;9", _("OFF;1.4ms;2.8ms;4.2ms;9.8ms;20ms;50ms;100ms;200ms;300ms"))); } } TController *TTpContr::ContrAttach(const string & name, const string & daq_db) { return new TMdContr(name, daq_db, this); } //************************************************* //* TMdContr * //************************************************* TMdContr::TMdContr(string name_c, const string & daq_db, ::TElem * cfgelem) : ::TController(name_c, daq_db, cfgelem), prcSt(false), callSt(false), endrunReq(false), tmGath(0), enRes(true), dataRes(true), mSched(cfg("SCHEDULE")), mPrior(cfg("PRIOR")), mNet(cfg("NET_ID")), mPer(1e9) { //????[v1.0] Remove cfg("PRM_BD_DIM762").setS("FBUSPrmDIM762_" + name_c); cfg("PRM_BD_DIM716").setS("FBUSPrmDIM716_" + name_c); cfg("PRM_BD_DIM718").setS("FBUSPrmDIM718_" + name_c); cfg("PRM_BD_AIM791").setS("FBUSPrmAIM791_" + name_c); cfg("PRM_BD_AIM726").setS("FBUSPrmAIM726_" + name_c); cfg("PRM_BD_AIM730").setS("FBUSPrmAIM730_" + name_c); cfg("PRM_BD_AIM725").setS("FBUSPrmAIM725_" + name_c); cfg("PRM_BD_DIM765").setS("FBUSPrmDIM765_" + name_c); } TMdContr::~TMdContr() { if(startStat()) stop(); } string TMdContr::tblStd( const TTypeParam &tP ) const { if(tP.name == "DIM762") return "FBUSPrmDIM762_"+id(); else if(tP.name == "DIM716") return "FBUSPrmDIM716_"+id(); else if(tP.name == "DIM718") return "FBUSPrmDIM718_"+id(); else if(tP.name == "AIM791") return "FBUSPrmAIM791_"+id(); else if(tP.name == "AIM726") return "FBUSPrmAIM726_"+id(); else if(tP.name == "AIM730") return "FBUSPrmAIM730_"+id(); else if(tP.name == "AIM725") return "FBUSPrmAIM725_"+id(); else if(tP.name == "DIM765_766") return "FBUSPrmDIM765_"+id(); else return TController::tblStd(tP); } void TMdContr::GetNodeDescription(int id, PFIO_MODULE_DESC modDesc) { mod->FBUS_fbusGetNodeDescription(mNet, id, modDesc); } int TMdContr::ReadInputs(int id, void *buf, size_t offset, size_t size) { return mod->FBUS_fbusReadInputs(mNet, id, buf, offset, size); } int TMdContr::WriteOutputs(int id, void *buf, size_t offset, size_t size) { return mod->FBUS_fbusWriteOutputs(mNet, id, buf, offset, size); } int TMdContr::SetNodeSpecificParameters(int id, void *buf, size_t offset, size_t size) { return mod->FBUS_fbusSetNodeSpecificParameters(mNet, id, buf, offset, size); } int TMdContr::GetNodeSpecificParameters(int id, void *buf, size_t offset, size_t size) { return mod->FBUS_fbusGetNodeSpecificParameters(mNet, id, buf, offset, size); } int TMdContr::GetNodeCommonParameters(int id, PFIO_MODULE_COMMON_CONF buf, size_t size) { return mod->FBUS_fbusGetNodeCommonParameters(mNet, id, buf, size); } int TMdContr::SetNodeCommonParameters(int id, PFIO_MODULE_COMMON_CONF buf, size_t size) { return mod->FBUS_fbusSetNodeCommonParameters(mNet, id, buf, size); } int TMdContr::WriteConfig(int id) { return mod->FBUS_fbusWriteConfig(mNet, id); } int TMdContr::ReadConfig(int id) { return mod->FBUS_fbusReadConfig(mNet, id); } int TMdContr::SaveConfig(int id) { return mod->FBUS_fbusSaveConfig(mNet, id); } string TMdContr::getStatus() { string rez = TController::getStatus(); if(startStat() && !redntUse()) { if(callSt) rez += TSYS::strMess(_("Acquisition. ")); if(period()) rez += TSYS::strMess(_("Acquisition with the period %s. "), tm2s(1e-9*period()).c_str()); else rez += TSYS::strMess(_("Next acquisition by the cron '%s'. "), atm2s(TSYS::cron(cron()), "%d-%m-%Y %R").c_str()); rez += TSYS::strMess(_("Spent time %s."), tm2s(1e-6*tmGath).c_str()); } return rez; } TParamContr *TMdContr::ParamAttach(const string & name, int type) { return new TMdPrm(name, &owner().tpPrmAt(type)); } void TMdContr::enable_() { mod->FBUS_fbusOpen(mNet); mod->FBUS_fbusRescan(mNet); } void TMdContr::start_() { //Start the gathering data task SYS->taskCreate(nodePath('.', true), mPrior, TMdContr::Task, this); } void TMdContr::stop_() { //Stop the request and calc data task SYS->taskDestroy(nodePath('.', true), &endrunReq); mod->FBUS_fbusClose(mNet); } void TMdContr::prmEn(const string & id, bool val) { int i_prm; MtxAlloc res(enRes, true); for(i_prm = 0; i_prm < p_hd.size(); i_prm++) if(p_hd[i_prm].at().id() == id) break; if(val && i_prm >= p_hd.size()) p_hd.push_back(at(id)); if(!val && i_prm < p_hd.size()) p_hd.erase(p_hd.begin() + i_prm); } void *TMdContr::Task(void *icntr) { TMdContr & cntr = *(TMdContr *) icntr; cntr.endrunReq = false; cntr.prcSt = true; while(!cntr.endrunReq) { int64_t t_cnt = TSYS::curTime(); //> Update controller's data //!!! Your code for gather data MtxAlloc prmRes(cntr.enRes, true); cntr.callSt = true; for(unsigned i_p = 0; i_p < cntr.p_hd.size() && !cntr.redntUse(); i_p++) try { cntr.p_hd[i_p].at().getVals(); } catch (TError err) { mess_err(err.cat.c_str(), "%s", err.mess.c_str()); } cntr.callSt = false; prmRes.unlock(); cntr.tmGath = TSYS::curTime() - t_cnt; //!!! Wait for next iteration TSYS::taskSleep(cntr.period(), cntr.period() ? "" : cntr.cron()); } cntr.prcSt = false; return NULL; } void TMdContr::cntrCmdProc(XMLNode * opt) { //Get page info if(opt->name() == "info") { TController::cntrCmdProc(opt); ctrMkNode("fld", opt, -1, "/cntr/cfg/SCHEDULE", EVAL_STR, startStat() ? R_R_R_ : RWRWR_, "root", SDAQ_ID, 3, "dest", "sel_ed", "sel_list",TMess::labSecCRONsel().c_str(), "help",TMess::labSecCRON().c_str()); ctrMkNode("fld", opt, -1, "/cntr/cfg/PRIOR", EVAL_STR, startStat() ? R_R_R_ : RWRWR_, "root", SDAQ_ID, 1, "help",TMess::labTaskPrior().c_str()); return; } //Process command to page TController::cntrCmdProc(opt); } bool TMdContr::cfgChange( TCfg &co, const TVariant &pc ) { TController::cfgChange(co, pc); if(co.fld().name() == "SCHEDULE") mPer = TSYS::strSepParse(cron(), 1, ' ').empty() ? vmax(0, (int64_t ) (1e9 * s2r(cron()))) : 0; return true; } //************************************************* //* TMdPrm * //************************************************* TMdPrm::TMdPrm(string name, TTypeParam * tp_prm) : TParamContr(name, tp_prm), p_el("w_attr"), mID(cfg("DEV_ID")), mState(StateUndef) { } TMdPrm::~TMdPrm() { //!!! Call for prevent access to data the object from included nodes on destruction. nodeDelAll(); } void TMdPrm::postEnable(int flag) { TParamContr::postEnable(flag); if(!vlElemPresent(&p_el)) vlElemAtt(&p_el); } TMdContr & TMdPrm::owner( ) const { return (TMdContr &) TParamContr::owner(); } bool TMdPrm::InitDI(DIM_CONFIGURATION* pConfig) { bool fConfig; for(unsigned i_p = 0; i_p < nDI; i_p++) { p_el.fldAdd( new TFld(TSYS::strMess("DI%d", i_p).c_str(), TSYS::strMess("DI%d", i_p).c_str(), TFld::Boolean, TFld::NoWrite | TVal::DirRead, "", "", "", "", "")); } p_el.fldAdd(new TFld("C0", "C0", TFld::Integer, TFld::NoWrite | TVal::DirRead, "", "", "", "", "")); p_el.fldAdd(new TFld("C1", "C1", TFld::Integer, TFld::NoWrite | TVal::DirRead, "", "", "", "", "")); if(pConfig->debounce != cfg("DI_DEBOUNCE").getI()) { fConfig = true; pConfig->debounce = cfg("DI_DEBOUNCE").getI(); } if(pConfig->enableCounting != cfg("DI_COUNT").getI()) { fConfig = true; pConfig->enableCounting = cfg("DI_COUNT").getI(); } return fConfig; } bool TMdPrm::InitDIM718(DIM718_CONFIGURATION* pConfig) { bool fConfig = false; mDOState = 0; for(unsigned i_p = 0; i_p < nDO; i_p++) { p_el.fldAdd( new TFld(TSYS::strMess("DO%d", i_p).c_str(), TSYS::strMess("DO%d", i_p).c_str(), TFld::Boolean, TVal::DirRead | TVal::DirWrite, "", "", "", "", "")); } return fConfig; } bool TMdPrm::InitAIM726(AIM726_CONFIGURATION* pConfig) { bool fConfig = false; kAI = 40.0 / 8388607; for(unsigned i_p = 0; i_p < nAI; i_p++) { p_el.fldAdd( new TFld(TSYS::strMess("AI%d", i_p).c_str(), TSYS::strMess("AI%d", i_p).c_str(), TFld::Double, TFld::NoWrite | TVal::DirRead, "", "", "", "", "")); } if(pConfig->filterOptions0 != cfg("AI_FILTER").getI()) { fConfig = true; pConfig->filterOptions0 = cfg("AI_FILTER").getI(); } if(pConfig->filterOptions1 != cfg("AI_FILTER").getI()) { fConfig = true; pConfig->filterOptions1 = cfg("AI_FILTER").getI(); } return fConfig; } bool TMdPrm::InitAIM730(AIM730_CONFIGURATION* pConfig) { bool fConfig = false; for(unsigned i_p = 0; i_p < nAO; i_p++) { p_el.fldAdd( new TFld(TSYS::strMess("AO%d", i_p).c_str(), TSYS::strMess("AO%d", i_p).c_str(), TFld::Double, TVal::DirRead | TVal::DirWrite, "", "", "", "", "")); } if(pConfig->outputRange0 != cfg("AO_RANGE").getI()) { fConfig = true; pConfig->outputRange0 = cfg("AO_RANGE").getI(); } if(pConfig->outputRange1 != cfg("AO_RANGE").getI()) { fConfig = true; pConfig->outputRange1 = cfg("AO_RANGE").getI(); } switch(cfg("AO_RANGE").getI()) { case 0: kAO = 20.0 / 65535; dAO = 0; break; case 1: kAO = 16.0 / 65535; dAO = 4; break; } return fConfig; } bool TMdPrm::InitAIM791(AIM791_CONFIGURATION* pConfig) { bool fConfig = false; for(unsigned i_p = 0; i_p < nAI; i_p++) { if(pConfig->channelRanges[i_p] != cfg("AI_RANGE").getI()) { fConfig = true; pConfig->channelRanges[i_p] = cfg("AI_RANGE").getI(); } if(pConfig->lowLimit[i_p] != 0) { fConfig = true; pConfig->lowLimit[i_p] = 0; } if(pConfig->highLimit[i_p] != 0xFFFF) { fConfig = true; pConfig->highLimit[i_p] = 0xFFFF; } } switch(cfg("AI_RANGE").getI()) { case 0: kAI = 5.125 / 65535; break; case 1: case 2: kAI = 20.5 / 65535; break; } for(unsigned i_p = 0; i_p < nAI; i_p++) { p_el.fldAdd( new TFld(TSYS::strMess("AI%d", i_p).c_str(), TSYS::strMess("AI%d", i_p).c_str(), TFld::Double, TFld::NoWrite | TVal::DirRead, "", "", "", "", "")); } return fConfig; } bool TMdPrm::InitAIM725(AIM725_CONFIGURATION* pConfig) { bool fConfig = false; if(pConfig->scanRate != 0) { fConfig = true; pConfig->scanRate = 0; } if(pConfig->channels_selection != AIM724_5_USE_BOTH_CHANNELS) { fConfig = true; pConfig->channels_selection = AIM724_5_USE_BOTH_CHANNELS; } if(pConfig->inputRange != cfg("AI_RANGE").getI()) { fConfig = true; pConfig->inputRange = cfg("AI_RANGE").getI(); } if(pConfig->connectionType != cfg("AI_TYPE").getI()) { fConfig = true; pConfig->connectionType = cfg("AI_TYPE").getI(); } kAI = 1; for(unsigned i_p = 0; i_p < nAI; i_p++) { p_el.fldAdd( new TFld(TSYS::strMess("AI%d", i_p).c_str(), TSYS::strMess("AI%d", i_p).c_str(), TFld::Double, TFld::NoWrite | TVal::DirRead, "", "", "", "", "")); } return fConfig; } bool TMdPrm::InitDIM7656(DIM7656_CONFIGURATION* pConfig, FIO_MODULE_TYPE type) { bool fConfig = false; if(pConfig->shunt0 != cfg("DI_TYPE_0").getI()) { fConfig = true; pConfig->shunt0 = cfg("DI_TYPE_0").getI(); } if(pConfig->shunt1 != cfg("DI_TYPE_1").getI()) { fConfig = true; pConfig->shunt1 = cfg("DI_TYPE_1").getI(); } if(pConfig->shunt2 != cfg("DI_TYPE_2").getI()) { fConfig = true; pConfig->shunt2 = cfg("DI_TYPE_2").getI(); } if(pConfig->shunt3 != cfg("DI_TYPE_3").getI()) { fConfig = true; pConfig->shunt3 = cfg("DI_TYPE_3").getI(); } if(pConfig->shunt4 != cfg("DI_TYPE_4").getI()) { fConfig = true; pConfig->shunt4 = cfg("DI_TYPE_4").getI(); } if(pConfig->shunt5 != cfg("DI_TYPE_5").getI()) { fConfig = true; pConfig->shunt5 = cfg("DI_TYPE_5").getI(); } if(pConfig->shunt6 != cfg("DI_TYPE_6").getI()) { fConfig = true; pConfig->shunt6 = cfg("DI_TYPE_6").getI(); } if(pConfig->shunt7 != cfg("DI_TYPE_7").getI()) { fConfig = true; pConfig->shunt7 = cfg("DI_TYPE_7").getI(); } if(pConfig->switchOnDelay0 != cfg("DI_DEBOUNCE_ON_0").getI()) { fConfig = true; pConfig->switchOnDelay0 = cfg("DI_DEBOUNCE_ON_0").getI(); } if(pConfig->switchOnDelay1 != cfg("DI_DEBOUNCE_ON_1").getI()) { fConfig = true; pConfig->switchOnDelay1 = cfg("DI_DEBOUNCE_ON_1").getI(); } if(pConfig->switchOnDelay2 != cfg("DI_DEBOUNCE_ON_2").getI()) { fConfig = true; pConfig->switchOnDelay2 = cfg("DI_DEBOUNCE_ON_2").getI(); } if(pConfig->switchOnDelay3 != cfg("DI_DEBOUNCE_ON_3").getI()) { fConfig = true; pConfig->switchOnDelay3 = cfg("DI_DEBOUNCE_ON_3").getI(); } if(pConfig->switchOnDelay4 != cfg("DI_DEBOUNCE_ON_4").getI()) { fConfig = true; pConfig->switchOnDelay4 = cfg("DI_DEBOUNCE_ON_4").getI(); } if(pConfig->switchOnDelay5 != cfg("DI_DEBOUNCE_ON_5").getI()) { fConfig = true; pConfig->switchOnDelay5 = cfg("DI_DEBOUNCE_ON_5").getI(); } if(pConfig->switchOnDelay6 != cfg("DI_DEBOUNCE_ON_6").getI()) { fConfig = true; pConfig->switchOnDelay6 = cfg("DI_DEBOUNCE_ON_6").getI(); } if(pConfig->switchOnDelay7 != cfg("DI_DEBOUNCE_ON_7").getI()) { fConfig = true; pConfig->switchOnDelay7 = cfg("DI_DEBOUNCE_ON_7").getI(); } if(pConfig->switchOffDelay0 != cfg("DI_DEBOUNCE_OFF_0").getI()) { fConfig = true; pConfig->switchOffDelay0 = cfg("DI_DEBOUNCE_OFF_0").getI(); } if(pConfig->switchOffDelay1 != cfg("DI_DEBOUNCE_OFF_1").getI()) { fConfig = true; pConfig->switchOffDelay1 = cfg("DI_DEBOUNCE_OFF_1").getI(); } if(pConfig->switchOffDelay2 != cfg("DI_DEBOUNCE_OFF_2").getI()) { fConfig = true; pConfig->switchOffDelay2 = cfg("DI_DEBOUNCE_OFF_2").getI(); } if(pConfig->switchOffDelay3 != cfg("DI_DEBOUNCE_OFF_3").getI()) { fConfig = true; pConfig->switchOffDelay3 = cfg("DI_DEBOUNCE_OFF_3").getI(); } if(pConfig->switchOffDelay4 != cfg("DI_DEBOUNCE_OFF_4").getI()) { fConfig = true; pConfig->switchOffDelay4 = cfg("DI_DEBOUNCE_OFF_4").getI(); } if(pConfig->switchOffDelay5 != cfg("DI_DEBOUNCE_OFF_5").getI()) { fConfig = true; pConfig->switchOffDelay5 = cfg("DI_DEBOUNCE_OFF_5").getI(); } if(pConfig->switchOffDelay6 != cfg("DI_DEBOUNCE_OFF_6").getI()) { fConfig = true; pConfig->switchOffDelay6 = cfg("DI_DEBOUNCE_OFF_6").getI(); } if(pConfig->switchOffDelay7 != cfg("DI_DEBOUNCE_OFF_7").getI()) { fConfig = true; pConfig->switchOffDelay7 = cfg("DI_DEBOUNCE_OFF_7").getI(); } kAI = 7.4655; if(type == FIO_MODULE_DIM765) { kAIC = 4.0161; } else { kAIC = 3.7422; } for(unsigned i_p = 0; i_p < nDI; i_p++) { p_el.fldAdd( new TFld(TSYS::strMess("DI%d", i_p).c_str(), TSYS::strMess("DI%d", i_p).c_str(), TFld::Boolean, TFld::NoWrite | TVal::DirRead, "", "", "", "", "")); p_el.fldAdd( new TFld(TSYS::strMess("BREAK%d", i_p).c_str(), TSYS::strMess(_("Break %d"), i_p).c_str(), TFld::Boolean, TFld::NoWrite | TVal::DirRead, "", "", "", "", "")); p_el.fldAdd( new TFld(TSYS::strMess("V%d", i_p).c_str(), TSYS::strMess("V%d", i_p).c_str(), TFld::Double, TFld::NoWrite | TVal::DirRead, "", "", "", "", "")); p_el.fldAdd( new TFld(TSYS::strMess("I%d", i_p).c_str(), TSYS::strMess("I%d", i_p).c_str(), TFld::Double, TFld::NoWrite | TVal::DirRead, "", "", "", "", "")); } return fConfig; } void TMdPrm::enable() { if(enableStat()) return; TParamContr::enable(); //Delete DAQ parameter's attributes for(unsigned i_f = 0; i_f < p_el.fldSize();) { try { p_el.fldDel(i_f); continue; } catch (TError err) { mess_warning(err.cat.c_str(), err.mess.c_str()); } i_f++; } bool fConfig = false; owner().prmEn(id(), true); try { owner().GetNodeDescription(mID, &mModDesc); owner().ReadConfig(mID); owner().GetNodeSpecificParameters(mID, mModConfig, 0, mModDesc.specificRwSize); owner().GetNodeCommonParameters(mID, &mModComConfig, sizeof(mModComConfig)); if(mModComConfig.inputSync != FBUS_UNDEFINED_SYNC_ID) { fConfig = true; mModComConfig.inputSync = FBUS_UNDEFINED_SYNC_ID; } if(mModComConfig.outputSync != FBUS_UNDEFINED_SYNC_ID) { fConfig = true; mModComConfig.outputSync = FBUS_UNDEFINED_SYNC_ID; } mTypeName = mModDesc.typeName; mState = StateWork; switch(mModDesc.type) { case FIO_MODULE_DIM762: nDI = 8; fConfig |= InitDI((DIM_CONFIGURATION *) mModConfig); break; case FIO_MODULE_DIM716: nDI = 2; fConfig |= InitDI((DIM_CONFIGURATION *) mModConfig); break; case FIO_MODULE_DIM718: nDO = 8; fConfig |= InitDIM718((DIM718_CONFIGURATION *) mModConfig); break; case FIO_MODULE_AIM726: nAI = 2; fConfig |= InitAIM726((AIM726_CONFIGURATION *) mModConfig); break; case FIO_MODULE_AIM730: nAO = 2; fConfig |= InitAIM730((AIM730_CONFIGURATION *) mModConfig); break; case FIO_MODULE_AIM791: nAI = 8; fConfig |= InitAIM791((AIM791_CONFIGURATION *) mModConfig); break; case FIO_MODULE_AIM725: nAI = 2; fConfig |= InitAIM725((AIM725_CONFIGURATION *) mModConfig); break; case FIO_MODULE_DIM765: case FIO_MODULE_DIM766: nDI = 8; nAI = 8; fConfig |= InitDIM7656((DIM7656_CONFIGURATION *) mModConfig, mModDesc.type); break; default: mState = StateWrongType; break; } if(fConfig) { owner().SetNodeSpecificParameters(mID, mModConfig, 0, mModDesc.specificRwSize); owner().SetNodeCommonParameters(mID, &mModComConfig, sizeof(mModComConfig)); owner().WriteConfig(mID); owner().SaveConfig(mID); } } catch (TError err) { mess_err(err.cat.c_str(), "%s", err.mess.c_str()); disable(); } } void TMdPrm::disable() { if(!enableStat()) return; owner().prmEn(id(), false); TParamContr::disable(); //> Set EVAL to parameter attributes vector ls; elem().fldList(ls); for(int i_el = 0; i_el < ls.size(); i_el++) vlAt(ls[i_el]).at().setS(EVAL_STR, 0, true); } void TMdPrm::vlGet(TVal & val) { if(!enableStat() || !owner().startStat()) { if(val.name() == "err") { if(!enableStat()) val.setS(_("1:Parameter disabled."), 0, true); else if(!owner().startStat()) val.setS(_("2:Acquisition stopped."), 0, true); } else val.setS(EVAL_STR, 0, true); return; } if(owner().redntUse()) return; if(val.name() == "err") { switch(mState) { case StateWork: val.setS(_("0: Normal"), 0, true); break; case StateWrongType: val.setS(TSYS::strMess(_("3: Wrong type: %s"), mModDesc.typeName), 0, true); break; } } } void TMdPrm::getVals() { uint8_t buf[256]; if(mState == StateWork) { if(owner().ReadInputs(mID, buf, 0, mModDesc.inputsSize) == FBUS_RES_OK) { switch(mModDesc.type) { case FIO_MODULE_DIM762: case FIO_MODULE_DIM716: for(unsigned i_p = 0; i_p < nDI; i_p++) { vlAt(TSYS::strMess("DI%d", i_p).c_str()).at().setB(((((DIM_INPUTS_COUNTERS *) buf)->inputStates) >> i_p) & 1, 0, true); } vlAt("C0").at().setI((((DIM_INPUTS_COUNTERS *) buf)->counter0), 0, true); vlAt("C1").at().setI((((DIM_INPUTS_COUNTERS *) buf)->counter1), 0, true); break; case FIO_MODULE_AIM726: vlAt(TSYS::strMess("AI0").c_str()).at().setR(((AIM726_INPUTS *) buf)->input0 * kAI, 0, true); vlAt(TSYS::strMess("AI1").c_str()).at().setR(((AIM726_INPUTS *) buf)->input1 * kAI, 0, true); break; case FIO_MODULE_AIM730: vlAt(TSYS::strMess("AO0").c_str()).at().setR(((AIM730_INPUTS *) buf)->outputValue0 * kAO + dAO, 0, true); vlAt(TSYS::strMess("AO1").c_str()).at().setR(((AIM730_INPUTS *) buf)->outputValue1 * kAO + dAO, 0, true); break; case FIO_MODULE_AIM791: for(unsigned i_p = 0; i_p < nAI; i_p++) { vlAt(TSYS::strMess("AI%d", i_p).c_str()).at().setR(((AIM791_INPUTS *) buf)->values[i_p] * kAI, 0, true); } break; case FIO_MODULE_AIM725: if(((((AIM725_INPUTS *) buf)->diagnostics) & 0x0D) == 0) { vlAt(TSYS::strMess("AI0").c_str()).at().setR(((AIM725_INPUTS *) buf)->channel0, 0, true); } else { vlAt(TSYS::strMess("AI0").c_str()).at().setR(EVAL_REAL, 0, true); } if(((((AIM725_INPUTS *) buf)->diagnostics) & 0x0E) == 0) { vlAt(TSYS::strMess("AI1").c_str()).at().setR(((AIM725_INPUTS *) buf)->channel1, 0, true); } else { vlAt(TSYS::strMess("AI1").c_str()).at().setR(EVAL_REAL, 0, true); } break; case FIO_MODULE_DIM765: case FIO_MODULE_DIM766: for(unsigned i_p = 0; i_p < nDI; i_p++) { vlAt(TSYS::strMess("DI%d", i_p).c_str()).at().setB(((((DIM7656_INPUTS *) buf)->channelsState) >> i_p) & 1, 0, true); vlAt(TSYS::strMess("BREAK%d", i_p).c_str()).at().setB(((((DIM7656_INPUTS *) buf)->wireBreaks) >> i_p) & 1, 0, true); } vlAt(TSYS::strMess("V0").c_str()).at().setR(((DIM7656_INPUTS *) buf)->v0 * kAI, 0, true); vlAt(TSYS::strMess("V1").c_str()).at().setR(((DIM7656_INPUTS *) buf)->v1 * kAI, 0, true); vlAt(TSYS::strMess("V2").c_str()).at().setR(((DIM7656_INPUTS *) buf)->v2 * kAI, 0, true); vlAt(TSYS::strMess("V3").c_str()).at().setR(((DIM7656_INPUTS *) buf)->v3 * kAI, 0, true); vlAt(TSYS::strMess("V4").c_str()).at().setR(((DIM7656_INPUTS *) buf)->v4 * kAI, 0, true); vlAt(TSYS::strMess("V5").c_str()).at().setR(((DIM7656_INPUTS *) buf)->v5 * kAI, 0, true); vlAt(TSYS::strMess("V6").c_str()).at().setR(((DIM7656_INPUTS *) buf)->v6 * kAI, 0, true); vlAt(TSYS::strMess("V7").c_str()).at().setR(((DIM7656_INPUTS *) buf)->v7 * kAI, 0, true); vlAt(TSYS::strMess("I0").c_str()).at().setR(((DIM7656_INPUTS *) buf)->i0 * kAIC, 0, true); vlAt(TSYS::strMess("I1").c_str()).at().setR(((DIM7656_INPUTS *) buf)->i1 * kAIC, 0, true); vlAt(TSYS::strMess("I2").c_str()).at().setR(((DIM7656_INPUTS *) buf)->i2 * kAIC, 0, true); vlAt(TSYS::strMess("I3").c_str()).at().setR(((DIM7656_INPUTS *) buf)->i3 * kAIC, 0, true); vlAt(TSYS::strMess("I4").c_str()).at().setR(((DIM7656_INPUTS *) buf)->i4 * kAIC, 0, true); vlAt(TSYS::strMess("I5").c_str()).at().setR(((DIM7656_INPUTS *) buf)->i5 * kAIC, 0, true); vlAt(TSYS::strMess("I6").c_str()).at().setR(((DIM7656_INPUTS *) buf)->i6 * kAIC, 0, true); vlAt(TSYS::strMess("I7").c_str()).at().setR(((DIM7656_INPUTS *) buf)->i7 * kAIC, 0, true); break; default: break; } } } } void TMdPrm::vlSet(TVal & vo, const TVariant & vl, const TVariant & pvl) { MtxAlloc prmRes(owner().enRes, true); uint8_t buf[256]; uint16_t i; if(!enableStat() || !owner().startStat()) { vo.setS(EVAL_STR, 0, true); return; } if(vl.isEVal() || vl == pvl) return; //Send to active reserve station if(vlSetRednt(vo,vl,pvl)) return; switch(mModDesc.type) { case FIO_MODULE_DIM718: if(vo.name().compare(0, 2, "DO") == 0) { if(vl.getB()) { mDOState |= 1 << s2i(vo.name().substr(2, vo.name().size() - 2)); } else { mDOState &= ~(1 << s2i(vo.name().substr(2, vo.name().size() - 2))); } owner().WriteOutputs(mID, &mDOState, 0, 1); } break; case FIO_MODULE_AIM730: if(vo.name().compare(0, 2, "AO") == 0) { for(int i = 0; i < nAO; i++) { switch(i) { case 0: if(s2i(vo.name().substr(2, vo.name().size() - 2)) == 0) { ((AIM730_OUTPUTS *) buf)->output0 = (vl.getR() - dAO) / kAO; } else { ((AIM730_OUTPUTS *) buf)->output0 = (vlAt(TSYS::strMess("AO0").c_str()).at().getR() - dAO) / kAO; } break; case 1: if(s2i(vo.name().substr(2, vo.name().size() - 2)) == 1) { ((AIM730_OUTPUTS *) buf)->output1 = (vl.getR() - dAO) / kAO; } else { ((AIM730_OUTPUTS *) buf)->output1 = (vlAt(TSYS::strMess("AO1").c_str()).at().getR() - dAO) / kAO; } break; } } owner().WriteOutputs(mID, buf, 0, nAO * 2); } break; default: break; } } void TMdPrm::cntrCmdProc(XMLNode * opt) { //> Service commands process string a_path = opt->attr("path"); if(a_path.find("/serv/") == 0) { TParamContr::cntrCmdProc(opt); return; } //> Get page info if(opt->name() == "info") { TParamContr::cntrCmdProc(opt); //ctrMkNode("fld",opt,-1,"/prm/cfg/OID_LS",EVAL_STR,enableStat()?R_R_R_:RWRWR_,"root",SDAQ_ID); return; } //> Process command to page else TParamContr::cntrCmdProc(opt); } void TMdPrm::vlArchMake(TVal & val) { TParamContr::vlArchMake(val); if(val.arch().freeStat()) return; val.arch().at().setSrcMode(TVArchive::DAQAttr); val.arch().at().setPeriod((int64_t) (owner().period() * 1000000)); val.arch().at().setHardGrid(true); val.arch().at().setHighResTm(true); }