Line data Source code
1 : /*
2 : mdevice.h
3 :
4 : Base class mdevice to create proper ODB settings under
5 : /Equipment/<name>/Settings
6 :
7 : Derived class mdevice_mscb for MSCB devices
8 :
9 : Created S. Ritt 11.04.2022
10 : */
11 :
12 : #include <cmath>
13 : #include <history.h>
14 : #include "mstrlcpy.h"
15 :
16 : #define FORMULA_SIZE 64
17 :
18 : //---- generic class ------------------------------------------------
19 :
20 : class mdevice {
21 :
22 : public:
23 :
24 : EQUIPMENT *mEq;
25 : std::string mDevName;
26 : std::vector<std::string> mName;
27 : midas::odb mOdbDev;
28 : midas::odb mOdbSettings;
29 : midas::odb mOdbVars;
30 : int mDevIndex;
31 : int mNchannels;
32 : int mNblocks;
33 : double mThreshold;
34 : double mFactor;
35 : double mOffset;
36 :
37 : public:
38 0 : mdevice(std::string eq_name, std::string dev_name,
39 : DWORD flags,
40 0 : INT(*dd) (INT cmd, ...)) {
41 :
42 : // search equipment in equipment table
43 : int idx;
44 0 : for (idx = 0; equipment[idx].name[0]; idx++)
45 0 : if (equipment[idx].name == eq_name)
46 0 : break;
47 0 : if (equipment[idx].name[0] == 0) {
48 : char str[256];
49 0 : snprintf(str, sizeof(str), "Equipment \"%s\" not found in equipment table", eq_name.c_str());
50 0 : cm_msg(MERROR, "device::device", "%s", str);
51 0 : mthrow(str);
52 : return;
53 : }
54 0 : mEq = &equipment[idx];
55 :
56 0 : if (mEq->driver == nullptr) { // create new device driver list
57 0 : mEq->driver = (DEVICE_DRIVER *) calloc(2, sizeof(DEVICE_DRIVER));
58 0 : mDevIndex = 0;
59 :
60 : } else { // extend existing device driver list
61 :
62 : // check for double name
63 : int n;
64 0 : for (n = 0; mEq->driver[n].name[0]; n++) {
65 0 : if (mEq->driver[n].name == dev_name) {
66 : char str[256];
67 0 : snprintf(str, sizeof(str), "Device \"%s\" defined twice for equipment \"%s\"", dev_name.c_str(),
68 : eq_name.c_str());
69 0 : cm_msg(MERROR, "device::device", "%s", str);
70 0 : mthrow(str);
71 : return;
72 : }
73 : }
74 0 : int size = (n + 2) * sizeof(DEVICE_DRIVER);
75 0 : mEq->driver = (DEVICE_DRIVER *) realloc(mEq->driver, size);
76 0 : memset((void *) &mEq->driver[n + 1], 0, sizeof(DEVICE_DRIVER));
77 0 : mDevIndex = n;
78 : }
79 :
80 0 : mstrlcpy(mEq->driver[mDevIndex].name, dev_name.c_str(), sizeof(mEq->driver[mDevIndex].name));
81 0 : mDevName = dev_name;
82 0 : mEq->driver[mDevIndex].pequipment_name = new std::string(eq_name);
83 0 : mEq->driver[mDevIndex].flags = flags;
84 0 : mEq->driver[mDevIndex].dd = dd;
85 0 : mEq->driver[mDevIndex].channels = 0;
86 0 : mNchannels = 0;
87 0 : mNblocks = 0;
88 0 : mThreshold = 0;
89 0 : mFactor = 1;
90 0 : mOffset = 0;
91 :
92 0 : mOdbDev.connect("/Equipment/" + eq_name + "/Settings/Devices/" + dev_name);
93 0 : mOdbSettings.connect("/Equipment/" + eq_name + "/Settings");
94 0 : mOdbVars.connect("/Equipment/" + eq_name + "/Variables");
95 0 : }
96 :
97 0 : void define_var(std::string name = "", double threshold = std::nan(""),
98 : double factor = std::nan(""), double offset = std::nan(""))
99 : {
100 0 : int chn_index = 0;
101 :
102 : // individual variable can overwrite standard value
103 0 : if (std::isnan(threshold))
104 0 : threshold = mThreshold;
105 0 : if (std::isnan(factor))
106 0 : factor = mFactor;
107 0 : if (std::isnan(offset))
108 0 : offset = mOffset;
109 :
110 : // put info into settings subtree
111 0 : if (mEq->driver[mDevIndex].flags & DF_INPUT) {
112 : // count total number of input channels
113 0 : for (int i=0 ; i <= mDevIndex ; i++)
114 0 : if (mEq->driver[i].flags & DF_INPUT)
115 0 : chn_index += mEq->driver[i].channels;
116 :
117 0 : mOdbSettings["Update Threshold"][chn_index] = (float) threshold;
118 0 : mOdbSettings["Input Factor"][chn_index] = (float) factor;
119 0 : mOdbSettings["Input Offset"][chn_index] = (float) offset;
120 0 : mOdbSettings["Names Input"][chn_index].set_string_size(name, 32);
121 0 : mName.push_back(name);
122 :
123 0 : std::vector<float> inp = mOdbVars["Input"];
124 0 : if ((int)inp.size() < chn_index+1) {
125 0 : inp.resize(chn_index+1);
126 0 : mOdbVars["Input"] = inp;
127 : }
128 0 : }
129 :
130 0 : else if (mEq->driver[mDevIndex].flags & DF_OUTPUT) {
131 : // count total number of output channels
132 0 : for (int i=0 ; i <= mDevIndex ; i++)
133 0 : if (mEq->driver[i].flags & DF_OUTPUT)
134 0 : chn_index += mEq->driver[i].channels;
135 :
136 0 : mOdbSettings["Output Factor"][chn_index] = (float) factor;
137 0 : mOdbSettings["Output Offset"][chn_index] = (float) offset;
138 0 : mOdbSettings["Names Output"][chn_index].set_string_size(name, 32);
139 0 : mName.push_back(name);
140 :
141 0 : std::vector<float> outp = mOdbVars["Output"];
142 0 : if ((int)outp.size() < chn_index+1) {
143 0 : outp.resize(chn_index+1);
144 0 : mOdbVars["Output"] = outp;
145 : }
146 0 : }
147 :
148 : else {
149 : // count total number of channels
150 0 : for (int i=0 ; i <= mDevIndex ; i++)
151 0 : chn_index += mEq->driver[i].channels;
152 :
153 0 : mOdbSettings["Names"][chn_index].set_string_size(name, 32);
154 0 : mName.push_back(name);
155 : }
156 :
157 0 : mEq->driver[mDevIndex].channels++;
158 0 : mNchannels++;
159 0 : }
160 :
161 : void define_varf(std::string name = "", double threshold = std::nan(""),
162 : std::string formula = "", std::string unit = "")
163 : {
164 : int chn_index = 0;
165 :
166 : // individual variable can overwrite standard value
167 : if (std::isnan(threshold))
168 : threshold = mThreshold;
169 :
170 : // put info into settings subtree
171 : if (mEq->driver[mDevIndex].flags & DF_INPUT) {
172 : // count total number of input channels
173 : for (int i=0 ; i <= mDevIndex ; i++)
174 : if (mEq->driver[i].flags & DF_INPUT)
175 : chn_index += mEq->driver[i].channels;
176 :
177 : mOdbSettings["Update Threshold"][chn_index] = (float) threshold;
178 : mOdbSettings["Input Formula"][chn_index].set_string_size(formula, FORMULA_SIZE);
179 : mOdbSettings["Input Unit"][chn_index].set_string_size(unit, 32);
180 : mOdbSettings["Names Input"][chn_index].set_string_size(name, 32);
181 : mName.push_back(name);
182 :
183 : std::vector<float> inp = mOdbVars["Input"];
184 : if ((int)inp.size() < chn_index+1) {
185 : inp.resize(chn_index+1);
186 : mOdbVars["Input"] = inp;
187 : }
188 : }
189 :
190 : else if (mEq->driver[mDevIndex].flags & DF_OUTPUT) {
191 : // count total number of output channels
192 : for (int i=0 ; i <= mDevIndex ; i++)
193 : if (mEq->driver[i].flags & DF_OUTPUT)
194 : chn_index += mEq->driver[i].channels;
195 :
196 : mOdbSettings["Output Formula"][chn_index] = formula;
197 : mOdbSettings["Input Unit"][chn_index].set_string_size(unit, 32);
198 : mOdbSettings["Names Output"][chn_index].set_string_size(name, 32);
199 : mName.push_back(name);
200 :
201 : std::vector<float> outp = mOdbVars["Output"];
202 : if ((int)outp.size() < chn_index+1) {
203 : outp.resize(chn_index+1);
204 : mOdbVars["Output"] = outp;
205 : }
206 : }
207 :
208 : else {
209 : // count total number of channels
210 : for (int i=0 ; i <= mDevIndex ; i++)
211 : chn_index += mEq->driver[i].channels;
212 :
213 : mOdbSettings["Names"][chn_index].set_string_size(name, 32);
214 : mName.push_back(name);
215 : }
216 :
217 : mEq->driver[mDevIndex].channels++;
218 : mNchannels++;
219 : }
220 :
221 : void add_func(void func(midas::odb &)) {
222 : mOdbVars["Input"].watch(func);
223 : }
224 :
225 : midas::odb *odbDevice()
226 : {
227 : return &mOdbDev;
228 : }
229 :
230 : void define_param(int i, std::string name, std::string str)
231 : {
232 : mOdbDev[name][i].set_string_size(str, 32);
233 : }
234 :
235 : void define_param(int i, std::string name, int p)
236 : {
237 : mOdbDev[name][i] = p;
238 : }
239 :
240 0 : void define_history_panel(std::string panelName, int i1, int i2 = -1)
241 : {
242 0 : std::vector<std::string> vars;
243 :
244 0 : if (i2 == -1)
245 0 : vars.push_back(mEq->name + std::string(":") + mName[i1]);
246 : else
247 0 : for (int i=i1 ; i<=i2 ; i++)
248 0 : vars.push_back(mEq->name + std::string(":") + mName[i]);
249 :
250 0 : hs_define_panel(mEq->name, panelName.c_str(), vars);
251 0 : }
252 :
253 : void define_history_panel(std::string panelName, std::vector<std::string> vars)
254 : {
255 : for (std::size_t i=0 ; i<vars.size() ; i++)
256 : if (vars[i].find(":") == std::string::npos)
257 : vars[i] = std::string(mEq->name) + ":" + vars[i];
258 : hs_define_panel(mEq->name, panelName.c_str(), vars);
259 : }
260 :
261 : void set_threshold(double threshold)
262 : {
263 : mThreshold = threshold;
264 : }
265 :
266 : void set_factor_offset(double factor, double offset)
267 : {
268 : mFactor = factor;
269 : mOffset = offset;
270 : }
271 :
272 : };
|