/********************************************************************\ Name: mdev_mscb.cxx Created by: Stefan Ritt Contents: MIDAS device drivers class for MSCB devices \********************************************************************/ #include #include "midas.h" #include "odbxx.h" #include "mdev_mscb.h" mdev_mscb::mdev_mscb(int event_id, std::string equipment_name) : mdev(event_id, equipment_name) { } mdev_mscb::~mdev_mscb(void) {} void mdev_mscb::odb_setup(void) { // MPDC settings in ODB midas::odb settings = { {"Enabled", true}, {"Grid display", false}, {"Editable", "Output"}, {"MSCB", {}}, }; settings.connect("/Equipment/" + m_equipment_name + "/Settings"); m_settings.connect("/Equipment/" + m_equipment_name + "/Settings"); // loop over all nodes m_n_variables_input = 0; m_n_variables_output = 0; for (auto & node : m_node) { try { bool e = m_settings["MSCB"][node.m_device]["Enabled"]; } catch (mexception &e) { m_settings["MSCB"][node.m_device]["Enabled"] = true; } node.m_enabled = m_settings["MSCB"][node.m_device]["Enabled"]; m_settings["MSCB"][node.m_device]["Device"] = node.m_device; m_settings["MSCB"][node.m_device]["Pwd"] = node.m_pwd; m_settings["MSCB"][node.m_device]["Address"] = node.m_address; // loop over all variables int n_input = 0; int n_output = 0; for (size_t i=0 ; i 0) m_settings["MSCB"][node.m_device]["Input"].resize(n_input); if (n_output > 0) m_settings["MSCB"][node.m_device]["Output"].resize(n_output); m_n_variables_input += n_input; m_n_variables_output += n_output; } if (m_n_variables_input > 0) m_settings["Names Input"].resize(m_n_variables_input); if (m_n_variables_output > 0) m_settings["Names Output"].resize(m_n_variables_output); // MSCB variables in ODB m_variables.connect("/Equipment/" + m_equipment_name + "/Variables"); if (m_n_variables_input > 0) { m_variables["Input"] = (float) ss_nan(); m_variables["Input"].resize(m_n_variables_input); } if (m_n_variables_output > 0) { m_variables["Output"][0] = (float) ss_nan(); m_variables["Output"].resize(m_n_variables_output); } } void mdev_mscb::init(void) { if (!m_settings["Enabled"]) { std::cout << "Equipment \"" << m_equipment_name << "\" disabled" << std::endl; return; } int n_input = 0; int n_output = 0; // loop over all MSCB nodes for (mscb_node &node : m_node) { if (!node.m_enabled) continue; try { node.m_mscb = new midas::mscb(node.m_device, node.m_address, node.m_pwd, node.m_enabled); } catch (mexception &e) { std::string s = "Cannot connect to MSCB device \"" + node.m_device + ":" + std::to_string(node.m_address) + "\""; mthrow1(s); } // loop over all variables for that node for (size_t i=0 ; iidx(node.m_mscb_var[i].var); if (node.m_mscb_var[i].index == -1) { std::string s = "Invalid MSCB variable name \"" + node.m_device + ":" + std::to_string(node.m_address) + ":" + node.m_mscb_var[i].var + "\""; mthrow1(s); } } try { // retrieve value for mirror if (node.m_mscb_var[i].output) m_output_mirror.push_back((float)(*node.m_mscb)[node.m_mscb_var[i].index]); } catch (mexception &e) { std::string s; if (node.m_mscb_var[i].var == "") s = "Cannot retrieve MSCB variable \"" + node.m_device + ":" + std::to_string(node.m_address) + ":" + std::to_string(node.m_mscb_var[i].index) + "\""; else s = "Cannot retrieve MSCB variable \"" + node.m_device + ":" + std::to_string(node.m_address) + ":" + node.m_mscb_var[i].var + "\""; mthrow1(s); } // retrieve unit and write it to ODB std::string unit = node.m_mscb->get_unit_short(node.m_mscb_var[i].index); if (node.m_mscb_var[i].output) m_settings["Unit Output"][n_output++].set_string_size(unit, 32); else m_settings["Unit Input"][n_input++].set_string_size(unit, 32); } } // install callback if (n_output > 0) m_variables["Output"].watch([this](midas::odb &o) { int n_output = 0; // loop over all MSCB nodes for (mscb_node &node : m_node) { // loop over all variables for that node for (size_t i = 0; i < node.m_mscb_var.size(); i++) { if (node.m_mscb_var[i].output) { float f = o[n_output]; // check if data differs from mirror if (f != m_output_mirror[n_output]) { // call confirm function if present if (node.m_mscb_var[i].confirm != nullptr) { bool confirm = node.m_mscb_var[i].confirm(node.m_mscb_var[i], f); if (!confirm) continue; } // store data in mirror m_output_mirror[n_output] = f; // write data to MSCB node (*node.m_mscb)[node.m_mscb_var[i].index] = f; std::cout << "Write " << f << std::endl; } n_output++; } } } }); } void mdev_mscb::exit(void) { } void mdev_mscb::loop(void) { if (!m_settings["Enabled"]) return; static DWORD last_time_measured_input = 0; static DWORD last_time_measured_output = 0; // read input values once per second if (ss_millitime() - last_time_measured_input > 1000) { // read all nodes int n_input = 0; for (auto node : m_node) { // skip disabled nodes if (!node.m_enabled) continue; // read all node variables node.m_mscb->read_range(); // read all variables from MSCB int n = node.m_mscb_var.size(); for (int i = 0; i < n; i++) if (!node.m_mscb_var[i].output) m_variables["Input"][n_input++] = (float) (*node.m_mscb)[node.m_mscb_var[i].index]; } last_time_measured_input = ss_millitime(); } // read output values once per minute if (ss_millitime() - last_time_measured_output > 60000) { int n_output = 0; for (auto node : m_node) { // skip disabled nodes if (!node.m_enabled) continue; int n = node.m_mscb_var.size(); for (int i = 0; i < n; i++) if (node.m_mscb_var[i].output) m_variables["Output"][n_output++] = (float) (*node.m_mscb)[node.m_mscb_var[i].index]; } last_time_measured_output = ss_millitime(); } } int mdev_mscb::read_event(char *pevent, int off) { if (!m_settings["Enabled"]) return 0; float *pdata; // init bank structure bk_init32a(pevent); // create a bank with input values bk_create(pevent, "SMIN", TID_FLOAT, (void **)&pdata); for (int i = 0; i < m_n_variables_input; i++) *pdata++ = m_variables["Input"][i]; bk_close(pevent, pdata); // create a bank with output values bk_create(pevent, "SMOU", TID_FLOAT, (void **)&pdata); for (int i = 0; i < m_n_variables_output; i++) *pdata++ = m_variables["Output"][i]; bk_close(pevent, pdata); return bk_size(pevent); }