Line data Source code
1 : /********************************************************************\
2 :
3 : Name: mdev_mscb.cxx
4 : Created by: Stefan Ritt
5 :
6 : Contents: MIDAS device drivers class for MSCB devices
7 :
8 : \********************************************************************/
9 :
10 : #include <iostream>
11 :
12 : #include "midas.h"
13 : #include "odbxx.h"
14 :
15 : #include "mdev_mscb.h"
16 :
17 0 : void mdev_mscb::odb_setup(void) {
18 : // MPDC settings in ODB
19 : midas::odb settings = {
20 : { "Grid display", false },
21 0 : { "Names MSCB", std::string(31, '\0')},
22 0 : { "Unit MSCB", std::string(31, '\0')},
23 : { "Editable", false },
24 : { "Group", false },
25 0 : { "MSCB", {} },
26 0 : };
27 :
28 0 : settings.connect("/Equipment/" + m_equipment_name + "/Settings");
29 0 : m_settings.connect("/Equipment/" + m_equipment_name + "/Settings");
30 :
31 : // loop over all nodes
32 0 : m_n_variables = 0;
33 :
34 0 : for (auto & node : m_node) {
35 0 : if (!midas::odb::exists("/Equipment/" + m_equipment_name + "/Settings/MSCB/" +
36 0 : node.m_device + "/Enabled"))
37 0 : m_settings["MSCB"][node.m_device]["Enabled"] = true;
38 :
39 0 : node.m_enabled = m_settings["MSCB"][node.m_device]["Enabled"];
40 0 : m_settings["MSCB"][node.m_device]["Device"] = node.m_device;
41 0 : m_settings["MSCB"][node.m_device]["Pwd"] = node.m_pwd;
42 0 : m_settings["MSCB"][node.m_device]["Address"] = node.m_address;
43 :
44 : // loop over all variables
45 0 : for (int i=0 ; i<(int)node.m_mscb_var.size() ; i++) {
46 :
47 : // check for double names
48 0 : for (int j=0 ; j<m_n_variables ; j++)
49 0 : if (m_settings["Names MSCB"][j].s() == node.m_mscb_var[i].name)
50 0 : mthrow("Variable name \"" + node.m_mscb_var[i].name + "\" defined twice.");
51 :
52 : // set into in ODB
53 0 : m_settings["Names MSCB"][m_n_variables].set_string_size(node.m_mscb_var[i].name, 32);
54 0 : m_settings["Editable"][m_n_variables] = node.m_mscb_var[i].output;
55 0 : m_settings["MSCB"][node.m_device]["Variables"][i] = node.m_mscb_var[i].var;
56 0 : m_n_variables++;
57 : }
58 :
59 0 : m_settings["MSCB"][node.m_device]["Variables"].resize(node.m_mscb_var.size());
60 : }
61 :
62 0 : if (m_n_variables > 0) {
63 0 : m_settings["Names MSCB"].resize(m_n_variables);
64 0 : m_settings["Editable"].resize(m_n_variables);
65 0 : m_settings["Group"] = m_group;
66 : }
67 :
68 : // MSCB variables in ODB
69 0 : m_variables.connect("/Equipment/" + m_equipment_name + "/Variables");
70 0 : for (int i=0 ; i<m_n_variables ; i++)
71 0 : m_variables["MSCB"][i] = (float) ss_nan();
72 :
73 : // MSCB common tree
74 0 : m_common.connect("/Equipment/" + m_equipment_name + "/Common");
75 0 : }
76 :
77 0 : void mdev_mscb::init(void) {
78 :
79 0 : if (!m_common["Enabled"]) {
80 0 : std::cout << "Equipment \"" << m_equipment_name << "\" disabled" << std::endl;
81 0 : return;
82 : }
83 :
84 : // loop over all MSCB nodes
85 0 : int n_variables = 0;
86 0 : for (mscb_node &node : m_node) {
87 :
88 0 : if (!node.m_enabled)
89 0 : continue;
90 :
91 : try {
92 :
93 0 : node.m_mscb = new midas::mscb(node.m_device, node.m_address, node.m_pwd, node.m_enabled);
94 :
95 0 : } catch (mexception &e) {
96 0 : std::string s = "Cannot connect to MSCB device \"" + node.m_device + ":" +
97 0 : std::to_string(node.m_address) + "\"";
98 0 : mthrow1(s);
99 0 : }
100 :
101 : // loop over all variables for that node
102 0 : for (size_t i=0 ; i<node.m_mscb_var.size() ; i++) {
103 :
104 : // retrieve index for variable "var"
105 0 : if (node.m_mscb_var[i].var != "") {
106 0 : node.m_mscb_var[i].index = node.m_mscb->idx(node.m_mscb_var[i].var);
107 0 : if (node.m_mscb_var[i].index == -1) {
108 0 : std::string s = "Invalid MSCB variable name \"" + node.m_device + ":" +
109 0 : std::to_string(node.m_address) + ":" + node.m_mscb_var[i].var + "\"";
110 0 : mthrow1(s);
111 0 : }
112 : }
113 :
114 : try {
115 :
116 : // retrieve value for mirror
117 0 : m_mirror.push_back((float)(*node.m_mscb)[node.m_mscb_var[i].index]);
118 :
119 0 : } catch (mexception &e) {
120 0 : std::string s;
121 0 : if (node.m_mscb_var[i].var == "")
122 0 : s = "Cannot retrieve MSCB variable \"" + node.m_device + ":" +
123 0 : std::to_string(node.m_address) + ":" + std::to_string(node.m_mscb_var[i].index) + "\"";
124 : else
125 0 : s = "Cannot retrieve MSCB variable \"" + node.m_device + ":" +
126 0 : std::to_string(node.m_address) + ":" + node.m_mscb_var[i].var + "\"";
127 0 : mthrow1(s);
128 0 : }
129 :
130 : // retrieve unit from MSCB node
131 0 : std::string unit = node.m_mscb->get_unit_short(node.m_mscb_var[i].index);
132 :
133 : // overwrite if unit has been passed to constructor
134 0 : if (!node.m_mscb_var[i].unit.empty())
135 0 : unit = node.m_mscb_var[i].unit;
136 :
137 : // write unit to ODB
138 0 : m_settings["Unit MSCB"][n_variables].set_string_size(unit, 32);
139 :
140 : // write format to ODB
141 0 : if (node.m_mscb_var[i].format.empty())
142 0 : m_settings["Format MSCB"][n_variables].set_string_size("f2", 32);
143 : else
144 0 : m_settings["Format MSCB"][n_variables].set_string_size(node.m_mscb_var[i].format, 32);
145 :
146 0 : n_variables++;
147 0 : }
148 :
149 : }
150 :
151 : // install callback
152 0 : if (n_variables > 0)
153 0 : m_variables["MSCB"].watch([this](midas::odb &o) {
154 :
155 0 : int n_var = 0;
156 :
157 : // loop over all MSCB nodes
158 0 : for (mscb_node &node : m_node) {
159 : // loop over all variables for that node
160 0 : for (size_t i = 0; i < node.m_mscb_var.size(); i++, n_var++) {
161 :
162 0 : if (node.m_mscb_var[i].output) {
163 0 : float f = o[n_var];
164 :
165 : // check if data differs from mirror
166 0 : if (f != m_mirror[n_var] && !ss_isnan(f)) {
167 :
168 : // call confirm function if present
169 0 : if (node.m_mscb_var[i].confirm != nullptr) {
170 0 : bool confirm = node.m_mscb_var[i].confirm(node.m_mscb_var[i], f);
171 0 : if (!confirm)
172 0 : continue;
173 : }
174 :
175 : // store data in mirror
176 0 : m_mirror[n_var] = f;
177 :
178 : // write data to MSCB node
179 0 : int index = node.m_mscb_var[i].index;
180 0 : std::cout << "Write \"" << f << "\" to " << node.m_device << ":" << node.m_address << ":" << index << std::endl;
181 :
182 0 : (*node.m_mscb)[index] = f;
183 : }
184 : }
185 : }
186 : }
187 0 : });
188 : }
189 :
190 0 : void mdev_mscb::exit(void) {
191 0 : }
192 :
193 0 : void mdev_mscb::loop(void) {
194 :
195 : // read input values once per second
196 0 : if (ss_millitime() - m_readout_last > m_readout_period) {
197 :
198 0 : if (!m_common["Enabled"])
199 0 : return;
200 :
201 : // read all nodes
202 0 : int n_var = 0;
203 0 : std::string error_message = "";
204 0 : for (auto node : m_node) {
205 :
206 : // skip disabled nodes
207 0 : if (!node.m_enabled) {
208 0 : n_var += node.m_mscb_var.size();
209 0 : continue;
210 : }
211 :
212 : // read all node variables
213 0 : auto status = node.m_mscb->read_range();
214 0 : if (status != MSCB_SUCCESS) {
215 0 : for (size_t i = 0; i < node.m_mscb_var.size(); i++) {
216 0 : m_mirror[n_var] = (float) ss_nan();
217 0 : m_variables["MSCB"][n_var] = (float) ss_nan();
218 0 : n_var++;
219 : }
220 :
221 0 : error_message = "Communication error with \"" +
222 0 : node.m_mscb->get_submaster() + ":" +
223 0 : std::to_string(node.m_mscb->get_node_address()) + "\"";
224 :
225 : } else { // status == MSCB_SUCCESS
226 :
227 : // read all variables from MSCB
228 0 : for (size_t i = 0; i < node.m_mscb_var.size(); i++) {
229 0 : float f = (*node.m_mscb)[node.m_mscb_var[i].index];
230 0 : if (node.m_mscb_var[i].convert != nullptr) {
231 0 : f = node.m_mscb_var[i].convert(f);
232 : }
233 :
234 0 : m_mirror[n_var] = f;
235 0 : m_variables["MSCB"][n_var] = f;
236 0 : n_var++;
237 : }
238 : }
239 0 : }
240 :
241 0 : if (!error_message.empty())
242 0 : mthrow1(error_message);
243 :
244 0 : m_readout_last = ss_millitime();
245 0 : }
246 :
247 : }
248 :
249 0 : int mdev_mscb::read_event(char *pevent, int off) {
250 :
251 0 : if (!m_common["Enabled"])
252 0 : return 0;
253 :
254 : float *pdata;
255 :
256 : // init bank structure
257 0 : bk_init32a(pevent);
258 :
259 : // create a bank with values
260 0 : bk_create(pevent, "SMSC", TID_FLOAT, (void **)&pdata);
261 0 : for (int i = 0; i < m_n_variables; i++)
262 0 : *pdata++ = m_variables["MSCB"][i];
263 0 : bk_close(pevent, pdata);
264 :
265 0 : return bk_size(pevent);
266 : }
267 :
|