Line data Source code
1 : /********************************************************************\
2 :
3 : Name: mscbxx.h
4 : Created by: Stefan Ritt
5 :
6 : Contents: Implementation of MSCB++ API
7 :
8 : \********************************************************************/
9 :
10 : /****
11 :
12 : Usage of MSCB++ Example:
13 :
14 : #include <mscbxx.h>
15 :
16 : // connect to node 10 at submaster mscb123
17 : midas::mscb m("mscb123", 10);
18 :
19 : // print node info and all variables
20 : std::cout << m << std::endl;
21 :
22 : // refresh all variables
23 : m.read_range();
24 : std::cout << m[5] << std::endl; // index access
25 : std::cout << m["In0"] << std::endl; // name access
26 :
27 : // write value to MSCB
28 : m[5] = 1.234;
29 :
30 : // get index of a variable
31 : int i = m.idx("In0");
32 :
33 : ****/
34 : #ifndef _MSCBXX_HXX
35 : #define _MSCBXX_HXX
36 :
37 : #include <string>
38 : #include <stdexcept>
39 : #include <iostream>
40 : #include <iomanip>
41 : #include <vector>
42 : #include <map>
43 : #include <string>
44 : #include <cstring>
45 : #include <cstdint>
46 : #include <unordered_map>
47 :
48 : #include "mscb.h"
49 : #include "mexcept.h"
50 :
51 : /*------------------------------------------------------------------*/
52 :
53 : /**
54 : MIDAS Data Type Definitions min max */
55 : #define TID_BYTE 1 /**< DEPRECATED, use TID_UINT8 instead */
56 : #define TID_UINT8 1 /**< unsigned byte 0 255 */
57 : #define TID_SBYTE 2 /**< DEPRECATED, use TID_INT8 instead */
58 : #define TID_INT8 2 /**< signed byte -128 127 */
59 : #define TID_CHAR 3 /**< single character 0 255 */
60 : #define TID_WORD 4 /**< DEPRECATED, use TID_UINT16 instead */
61 : #define TID_UINT16 4 /**< two bytes 0 65535 */
62 : #define TID_SHORT 5 /**< DEPRECATED, use TID_INT16 instead */
63 : #define TID_INT16 5 /**< signed word -32768 32767 */
64 : #define TID_DWORD 6 /**< DEPRECATED, use TID_UINT32 instead */
65 : #define TID_UINT32 6 /**< four bytes 0 2^32-1 */
66 : #define TID_INT 7 /**< DEPRECATED, use TID_INT32 instead */
67 : #define TID_INT32 7 /**< signed dword -2^31 2^31-1 */
68 : #define TID_BOOL 8 /**< four bytes bool 0 1 */
69 : #define TID_FLOAT 9 /**< 4 Byte float format */
70 : #define TID_DOUBLE 10 /**< 8 Byte float format */
71 : #define TID_STRING 12 /**< zero terminated string */
72 :
73 : /*------------------------------------------------------------------*/
74 :
75 : namespace midas {
76 :
77 : class mscb;
78 :
79 : class u_mscb {
80 : private:
81 : // union to hold data
82 : union {
83 : uint8_t m_uint8;
84 : int8_t m_int8;
85 : uint16_t m_uint16;
86 : int16_t m_int16;
87 : uint32_t m_uint32;
88 : int32_t m_int32;
89 : uint64_t m_uint64;
90 : int64_t m_int64;
91 : bool m_bool;
92 : float m_float;
93 : double m_double;
94 : std::string *m_string;
95 : uint8_t m_data[8];
96 : };
97 :
98 : int m_tid;
99 : int m_size;
100 : int m_fd;
101 : int m_node_address;
102 : int m_var_index;
103 :
104 : public:
105 0 : u_mscb(int fd, int adr, int index, int tid, int size) :
106 0 : m_string{}, m_tid{tid}, m_size{size}, m_fd{fd},
107 0 : m_node_address{adr}, m_var_index{index} {};
108 :
109 : // Destructor
110 0 : ~u_mscb() {};
111 :
112 : // getters & setters
113 : int get_tid() { return m_tid; }
114 :
115 : // get value as certain type
116 : template<typename T>
117 : T get() {
118 : if (m_tid == TID_UINT8)
119 : return (T) m_uint8;
120 : else if (m_tid == TID_INT8)
121 : return (T) m_int8;
122 : else if (m_tid == TID_UINT16)
123 : return (T) m_uint16;
124 : else if (m_tid == TID_INT16)
125 : return (T) m_int16;
126 : else if (m_tid == TID_UINT32)
127 : return (T) m_uint32;
128 : else if (m_tid == TID_INT32)
129 : return (T) m_int32;
130 : else if (m_tid == TID_BOOL)
131 : return (T) m_bool;
132 : else if (m_tid == TID_FLOAT)
133 : return (T) m_float;
134 : else if (m_tid == TID_DOUBLE)
135 : return (T) m_double;
136 : else
137 : mthrow("Invalid type ID " + std::to_string(m_tid));
138 : }
139 :
140 : // get value as string
141 : void get(std::string &s) {
142 : if (m_tid == TID_UINT8)
143 : s = std::to_string(m_uint8);
144 : else if (m_tid == TID_INT8)
145 : s = std::to_string(m_int8);
146 : else if (m_tid == TID_UINT16)
147 : s = std::to_string(m_uint16);
148 : else if (m_tid == TID_INT16)
149 : s = std::to_string(m_int16);
150 : else if (m_tid == TID_UINT32)
151 : s = std::to_string(m_uint32);
152 : else if (m_tid == TID_INT32)
153 : s = std::to_string(m_int32);
154 : else if (m_tid == TID_BOOL)
155 : s = std::string(m_bool ? "true" : "false");
156 : else if (m_tid == TID_FLOAT)
157 : s = std::to_string(m_float);
158 : else if (m_tid == TID_DOUBLE)
159 : s = std::to_string(m_double);
160 : else if (m_tid == TID_STRING)
161 : s = *m_string;
162 : else
163 : mthrow("Invalid type ID " + std::to_string(m_tid));
164 : }
165 :
166 0 : void set_string(char* s) {
167 0 : if (m_string == nullptr)
168 0 : m_string = new std::string(s);
169 : else
170 0 : *m_string = s;
171 0 : }
172 :
173 0 : void set_data(const unsigned char *pdata) {
174 0 : std::memset(m_data, 0, sizeof(m_data));
175 0 : std::memcpy(m_data, pdata, m_size);
176 0 : }
177 :
178 : // write value to MSCB node
179 0 : int write(void) {
180 0 : if (m_tid == TID_STRING)
181 0 : mscb_write(m_fd, m_node_address, m_var_index, (void *)m_string->c_str(), m_size);
182 : else
183 0 : mscb_write(m_fd, m_node_address, m_var_index, &m_uint8, m_size);
184 0 : return 1;
185 : }
186 :
187 : // overload conversion operator
188 : template<typename T>
189 0 : operator T() {
190 0 : if (m_tid == TID_UINT8)
191 0 : return (T) m_uint8;
192 0 : else if (m_tid == TID_INT8)
193 0 : return (T) m_int8;
194 0 : else if (m_tid == TID_UINT16)
195 0 : return (T) m_uint16;
196 0 : else if (m_tid == TID_INT16)
197 0 : return (T) m_int16;
198 0 : else if (m_tid == TID_UINT32)
199 0 : return (T) m_uint32;
200 0 : else if (m_tid == TID_INT32)
201 0 : return (T) m_int32;
202 0 : else if (m_tid == TID_BOOL)
203 0 : return (T) m_bool;
204 0 : else if (m_tid == TID_FLOAT)
205 0 : return (T) m_float;
206 0 : else if (m_tid == TID_DOUBLE)
207 0 : return (T) m_double;
208 : else
209 0 : mthrow("Invalid type ID " + std::to_string(m_tid));
210 : }
211 :
212 : // string conversion operator
213 : operator std::string() {
214 : std::string s;
215 : get(s);
216 : return s;
217 : }
218 :
219 : // overload stream out operator
220 : friend std::ostream &operator<<(std::ostream &output, u_mscb &m) {
221 : std::string s = m;
222 : output << s;
223 : return output;
224 : };
225 :
226 : // Overload the Assignment Operators
227 : uint8_t operator=(uint8_t v) {
228 : if (m_tid == TID_UINT8)
229 : m_uint8 = (uint8_t)v;
230 : else if (m_tid == TID_INT8)
231 : m_int8 = (int8_t)v;
232 : else if (m_tid == TID_UINT16)
233 : m_uint16 = (uint16_t)v;
234 : else if (m_tid == TID_INT16)
235 : m_int16 = (int16_t)v;
236 : else if (m_tid == TID_UINT32)
237 : m_uint32 = (uint32_t)v;
238 : else if (m_tid == TID_INT32)
239 : m_int32 = (int32_t)v;
240 : else if (m_tid == TID_FLOAT)
241 : m_float = (float)v;
242 : else if (m_tid == TID_DOUBLE)
243 : m_double = (double)v;
244 : else if (m_tid == TID_BOOL)
245 : m_bool = (double)v;
246 : else
247 : mthrow("Invalid data type \"uint8_t\" for variable of type " + std::to_string(m_tid));
248 : write();
249 : return v;
250 : }
251 : int8_t operator=(int8_t v) {
252 : if (m_tid == TID_UINT8)
253 : m_uint8 = (uint8_t)v;
254 : else if (m_tid == TID_INT8)
255 : m_int8 = (int8_t)v;
256 : else if (m_tid == TID_UINT16)
257 : m_uint16 = (uint16_t)v;
258 : else if (m_tid == TID_INT16)
259 : m_int16 = (int16_t)v;
260 : else if (m_tid == TID_UINT32)
261 : m_uint32 = (uint32_t)v;
262 : else if (m_tid == TID_INT32)
263 : m_int32 = (int32_t)v;
264 : else if (m_tid == TID_FLOAT)
265 : m_float = (float)v;
266 : else if (m_tid == TID_DOUBLE)
267 : m_double = (double)v;
268 : else if (m_tid == TID_BOOL)
269 : m_bool = (double)v;
270 : else
271 : mthrow("Invalid data type \"int8_t\" for variable of type " + std::to_string(m_tid));
272 : write();
273 : return v;
274 : }
275 : uint16_t operator=(uint16_t v) {
276 : if (m_tid == TID_UINT8)
277 : m_uint8 = (uint8_t)v;
278 : else if (m_tid == TID_INT8)
279 : m_int8 = (int8_t)v;
280 : else if (m_tid == TID_UINT16)
281 : m_uint16 = (uint16_t)v;
282 : else if (m_tid == TID_INT16)
283 : m_int16 = (int16_t)v;
284 : else if (m_tid == TID_UINT32)
285 : m_uint32 = (uint32_t)v;
286 : else if (m_tid == TID_INT32)
287 : m_int32 = (int32_t)v;
288 : else if (m_tid == TID_FLOAT)
289 : m_float = (float)v;
290 : else if (m_tid == TID_DOUBLE)
291 : m_double = (double)v;
292 : else if (m_tid == TID_BOOL)
293 : m_bool = (double)v;
294 : else
295 : mthrow("Invalid data type \"uint16_t\" for variable of type " + std::to_string(m_tid));
296 : write();
297 : return v;
298 : }
299 : int16_t operator=(int16_t v) {
300 : if (m_tid == TID_UINT8)
301 : m_uint8 = (uint8_t)v;
302 : else if (m_tid == TID_INT8)
303 : m_int8 = (int8_t)v;
304 : else if (m_tid == TID_UINT16)
305 : m_uint16 = (uint16_t)v;
306 : else if (m_tid == TID_INT16)
307 : m_int16 = (int16_t)v;
308 : else if (m_tid == TID_UINT32)
309 : m_uint32 = (uint32_t)v;
310 : else if (m_tid == TID_INT32)
311 : m_int32 = (int32_t)v;
312 : else if (m_tid == TID_FLOAT)
313 : m_float = (float)v;
314 : else if (m_tid == TID_DOUBLE)
315 : m_double = (double)v;
316 : else if (m_tid == TID_BOOL)
317 : m_bool = (double)v;
318 : else
319 : mthrow("Invalid data type \"int16_t\" for variable of type " + std::to_string(m_tid));
320 : write();
321 : return v;
322 : }
323 : uint32_t operator=(uint32_t v) {
324 : if (m_tid == TID_UINT8)
325 : m_uint8 = (uint8_t)v;
326 : else if (m_tid == TID_INT8)
327 : m_int8 = (int8_t)v;
328 : else if (m_tid == TID_UINT16)
329 : m_uint16 = (uint16_t)v;
330 : else if (m_tid == TID_INT16)
331 : m_int16 = (int16_t)v;
332 : else if (m_tid == TID_UINT32)
333 : m_uint32 = (uint32_t)v;
334 : else if (m_tid == TID_INT32)
335 : m_int32 = (int32_t)v;
336 : else if (m_tid == TID_FLOAT)
337 : m_float = (float)v;
338 : else if (m_tid == TID_DOUBLE)
339 : m_double = (double)v;
340 : else if (m_tid == TID_BOOL)
341 : m_bool = (double)v;
342 : else
343 : mthrow("Invalid data type \"uint32_t\" for variable of type " + std::to_string(m_tid));
344 : write();
345 : return v;
346 : }
347 : int32_t operator=(int32_t v) {
348 : if (m_tid == TID_UINT8)
349 : m_uint8 = (uint8_t)v;
350 : else if (m_tid == TID_INT8)
351 : m_int8 = (int8_t)v;
352 : else if (m_tid == TID_UINT16)
353 : m_uint16 = (uint16_t)v;
354 : else if (m_tid == TID_INT16)
355 : m_int16 = (int16_t)v;
356 : else if (m_tid == TID_UINT32)
357 : m_uint32 = (uint32_t)v;
358 : else if (m_tid == TID_INT32)
359 : m_int32 = (int32_t)v;
360 : else if (m_tid == TID_FLOAT)
361 : m_float = (float)v;
362 : else if (m_tid == TID_DOUBLE)
363 : m_double = (double)v;
364 : else if (m_tid == TID_BOOL)
365 : m_bool = (double)v;
366 : else
367 : mthrow("Invalid data type \"int32_t\" for variable of type " + std::to_string(m_tid));
368 : write();
369 : return v;
370 : }
371 : bool operator=(bool v) {
372 : if (m_tid == TID_UINT8)
373 : m_uint8 = (uint8_t)v;
374 : else if (m_tid == TID_INT8)
375 : m_int8 = (int8_t)v;
376 : else if (m_tid == TID_UINT16)
377 : m_uint16 = (uint16_t)v;
378 : else if (m_tid == TID_INT16)
379 : m_int16 = (int16_t)v;
380 : else if (m_tid == TID_UINT32)
381 : m_uint32 = (uint32_t)v;
382 : else if (m_tid == TID_INT32)
383 : m_int32 = (int32_t)v;
384 : else if (m_tid == TID_FLOAT)
385 : m_float = (float)v;
386 : else if (m_tid == TID_DOUBLE)
387 : m_double = (double)v;
388 : else if (m_tid == TID_BOOL)
389 : m_bool = (double)v;
390 : else
391 : mthrow("Invalid data type \"bool\" for variable of type " + std::to_string(m_tid));
392 : write();
393 : return v;
394 : }
395 0 : float operator=(float v) {
396 0 : if (m_tid == TID_UINT8)
397 0 : m_uint8 = (uint8_t)v;
398 0 : else if (m_tid == TID_INT8)
399 0 : m_int8 = (int8_t)v;
400 0 : else if (m_tid == TID_UINT16)
401 0 : m_uint16 = (uint16_t)v;
402 0 : else if (m_tid == TID_INT16)
403 0 : m_int16 = (int16_t)v;
404 0 : else if (m_tid == TID_UINT32)
405 0 : m_uint32 = (uint32_t)v;
406 0 : else if (m_tid == TID_INT32)
407 0 : m_int32 = (int32_t)v;
408 0 : else if (m_tid == TID_FLOAT)
409 0 : m_float = (float)v;
410 0 : else if (m_tid == TID_DOUBLE)
411 0 : m_double = (double)v;
412 0 : else if (m_tid == TID_BOOL)
413 0 : m_bool = (double)v;
414 : else
415 0 : mthrow("Invalid data type \"float\" for variable of type " + std::to_string(m_tid));
416 0 : write();
417 0 : return v;
418 : }
419 : double operator=(double v) {
420 : if (m_tid == TID_UINT8)
421 : m_uint8 = (uint8_t)v;
422 : else if (m_tid == TID_INT8)
423 : m_int8 = (int8_t)v;
424 : else if (m_tid == TID_UINT16)
425 : m_uint16 = (uint16_t)v;
426 : else if (m_tid == TID_INT16)
427 : m_int16 = (int16_t)v;
428 : else if (m_tid == TID_UINT32)
429 : m_uint32 = (uint32_t)v;
430 : else if (m_tid == TID_INT32)
431 : m_int32 = (int32_t)v;
432 : else if (m_tid == TID_FLOAT)
433 : m_float = (float)v;
434 : else if (m_tid == TID_DOUBLE)
435 : m_double = (double)v;
436 : else if (m_tid == TID_BOOL)
437 : m_bool = (double)v;
438 : else
439 : mthrow("Invalid data type \"double\" for variable of type " + std::to_string(m_tid));
440 : write();
441 : return v;
442 : }
443 : const char *operator=(const char *v) {
444 : if (m_tid != TID_STRING)
445 : mthrow("Invalid data type \"const char *\" for variable of type " + std::to_string(m_tid));
446 : *m_string = std::string(v);
447 : write();
448 : return v;
449 : }
450 : std::string *operator=(std::string * v) {
451 : if (m_tid != TID_STRING)
452 : mthrow("Invalid data type \"std::string *\" for variable of type " + std::to_string(m_tid));
453 : *m_string = *v;
454 : write();
455 : return v;
456 : }
457 : std::string operator=(std::string v) {
458 : if (m_tid != TID_STRING)
459 : mthrow("Invalid data type \"std::string\" for variable of type " + std::to_string(m_tid));
460 : *m_string = v;
461 : write();
462 : return v;
463 : }
464 :
465 : };
466 :
467 : class mscb {
468 : private:
469 : std::string m_submaster;
470 : std::string m_password;
471 : int m_debug;
472 : int m_node_address;
473 :
474 : int m_fd;
475 :
476 : int m_protocol_version;
477 : int m_n_variables;
478 : int m_group_address;
479 : int m_revision;
480 : std::string m_node_name;
481 : std::string m_rtc;
482 : unsigned int m_uptime;
483 :
484 : std::vector<MSCB_INFO_VAR> m_var;
485 :
486 : std::vector<u_mscb> m_data;
487 :
488 : std::unordered_map<std::string, int> m_map;
489 :
490 : std::map<int, std::string> m_prefixMap;
491 : std::map<int, std::string> m_unitTable;
492 :
493 : public:
494 0 : mscb(std::string submaster, int address, std::string password = "", int debug = 0) {
495 0 : m_submaster = submaster;
496 0 : m_password = password;
497 0 : m_node_address = address;
498 0 : m_debug = debug;
499 :
500 0 : if (m_submaster.empty())
501 0 : mthrow("Please specify MSCB submaster to mscb() constructor");
502 :
503 : char str[80];
504 0 : strncpy(str, m_submaster.c_str(), sizeof(str)-1);
505 :
506 : // connect to submaster
507 0 : m_fd = mscb_init(str, sizeof(str), m_password.c_str(), m_debug);
508 0 : if (m_fd == EMSCB_WRONG_PASSWORD)
509 0 : mthrow("Wrong password for MSCB submaster \"" + m_submaster + "\"");
510 0 : if (m_fd == EMSCB_COMM_ERROR)
511 0 : mthrow("Cannot communicate with MSCB submaster \"" + m_submaster + "\"");
512 0 : if (m_fd == EMSCB_PROTOCOL_VERSION)
513 0 : mthrow("Submaster \"" + m_submaster + "\" runs old protocol version, please upgrade");
514 0 : if (m_fd == EMSCB_NOT_FOUND)
515 0 : mthrow("Submaster \"" + m_submaster + "\" not found, please check IP address");
516 0 : if (m_fd == EMSCB_LOCKED)
517 0 : mthrow("MSCB submaster \\\"\" + m_submaster + \"\\\" is locked by other process");
518 0 : if (m_fd < 0)
519 0 : mthrow("Submaster \"" + m_submaster + "\" not found, please check IP address");
520 :
521 : // get general info
522 : MSCB_INFO info;
523 0 : int status = mscb_info(m_fd, m_node_address, &info);
524 0 : if (status != 1) {
525 : // device might be stuck, so ping it to clear communication buffers
526 0 : mscb_ping(m_fd, m_node_address, 0, 10);
527 0 : status = mscb_info(m_fd, m_node_address, &info);
528 0 : if (status != 1)
529 0 : mthrow("Cannot find MSCB node " + m_submaster + ":" + std::to_string(m_node_address));
530 : }
531 :
532 0 : m_protocol_version = info.protocol_version;
533 0 : m_n_variables = info.n_variables;
534 0 : m_group_address = info.group_address;
535 0 : m_revision = info.revision;
536 0 : m_node_name = std::string(info.node_name);
537 0 : m_rtc = std::string((char *) info.rtc);
538 :
539 : // get uptime
540 : unsigned int uptime;
541 0 : mscb_uptime(m_fd, m_node_address, &uptime);
542 0 : m_uptime = uptime;
543 :
544 : // read variable definitions
545 0 : for (int i = 0; i < m_n_variables; i++) {
546 :
547 : MSCB_INFO_VAR info_var;
548 0 : mscb_info_variable(m_fd, m_node_address, i, &info_var);
549 0 : m_var.push_back(info_var);
550 0 : info_var.name[8] = 0;
551 0 : m_map[info_var.name] = i;
552 :
553 : // set tid from info
554 0 : int tid = 0;
555 0 : if (m_var[i].unit == UNIT_STRING)
556 0 : tid = TID_STRING;
557 0 : else if (m_var[i].flags & MSCBF_FLOAT)
558 0 : tid = TID_FLOAT;
559 0 : else if (m_var[i].flags & MSCBF_SIGNED) {
560 0 : if (m_var[i].width == 1)
561 0 : tid = TID_INT8;
562 0 : else if (m_var[i].width == 2)
563 0 : tid = TID_INT16;
564 0 : else if (m_var[i].width == 4)
565 0 : tid = TID_INT32;
566 : } else {
567 0 : if (m_var[i].width == 1)
568 0 : tid = TID_UINT8;
569 0 : else if (m_var[i].width == 2)
570 0 : tid = TID_UINT16;
571 0 : else if (m_var[i].width == 4)
572 0 : tid = TID_UINT32;
573 : }
574 :
575 0 : u_mscb d(m_fd, m_node_address, i, tid, m_var[i].width);
576 0 : m_data.push_back(d);
577 0 : }
578 :
579 0 : read_range();
580 0 : }
581 :
582 : void set_max_retry(int i) { mscb_set_max_retry(i); }
583 : void set_max_eth_retry(int i) { mscb_set_eth_max_retry(m_fd, i); }
584 :
585 : // Getter
586 : std::string get_node_name() { return m_node_name; }
587 0 : std::string get_submaster() { return m_submaster; }
588 0 : int get_node_address() { return m_node_address; }
589 : int get_protocol_version() { return m_protocol_version; }
590 : int get_n_variables() { return m_n_variables; }
591 :
592 : std::string get_unit(int i) {
593 : std::string s = "";
594 : if (i < 0 || i >= m_n_variables)
595 : mthrow("Invalid index \"" + std::to_string(i) + "\" in get_unit()");
596 :
597 : if (m_var[i].prefix)
598 : s += g_prefixMap[(int8_t)m_var[i].prefix];
599 : s += g_unitTable[m_var[i].unit];
600 : return s;
601 : }
602 :
603 0 : std::string get_unit_short(int i) {
604 0 : std::string s = "";
605 0 : if (i < 0 || i >= m_n_variables)
606 0 : mthrow("Invalid index \"" + std::to_string(i) + "\" in get_unit()");
607 :
608 0 : if (m_var[i].prefix)
609 0 : s += g_prefixMapShort[(int8_t)m_var[i].prefix];
610 0 : s += g_unitTableShort[m_var[i].unit];
611 0 : return s;
612 0 : }
613 :
614 0 : int read_range(int i1 = 0, int i2 = 0) {
615 : // read range of variables from i1 to i2 (including)
616 : unsigned char data[1024], *pdata;
617 :
618 0 : if (i1 == 0 && i2 == 0)
619 0 : i2 = m_n_variables-1;
620 :
621 0 : int size = sizeof(data);
622 0 : int status = mscb_read_range(m_fd, m_node_address, i1, i2, data, &size);
623 0 : if (status != MSCB_SUCCESS)
624 0 : return status;
625 :
626 0 : pdata = data;
627 0 : for (int i = i1; i <= i2; i++) {
628 :
629 0 : if (m_var[i].width == 2)
630 0 : WORD_SWAP(pdata);
631 0 : if (m_var[i].width == 4)
632 0 : DWORD_SWAP(pdata);
633 :
634 0 : if (m_var[i].unit == UNIT_STRING)
635 0 : m_data[i].set_string((char *) pdata);
636 : else
637 0 : m_data[i].set_data(pdata);
638 :
639 0 : pdata += m_var[i].width;
640 : }
641 :
642 0 : return status;
643 : }
644 :
645 : // overload stream out operator
646 : friend std::ostream &operator<<(std::ostream &output, mscb &m) {
647 : output << "Submaster : " << m.m_submaster << std::endl;
648 : output << "Node name : " << m.m_node_name << std::endl;
649 : output << "Node address : " << m.m_node_address <<
650 : " (0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << m.m_node_address << ")" <<
651 : std::dec << std::endl;
652 : output << "Group address : " << m.m_group_address <<
653 : " (0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << m.m_group_address << ")" <<
654 : std::dec << std::endl;
655 : output << "Protocol version : " << m.m_protocol_version << std::endl;
656 : output << "Revision : " << m.m_revision <<
657 : " (0x" << std::hex << std::uppercase << std::setw(4) << std::setfill('0') << m.m_revision << ")" <<
658 : std::dec << std::endl;
659 : output << "Uptime : ";
660 :
661 : output << m.m_uptime / (3600 * 24) << "d ";
662 : output << std::setw(2) << std::setfill('0') << (m.m_uptime % (3600 * 24)) / 3600 << "h ";
663 : output << std::setw(2) << std::setfill('0') << (m.m_uptime % 3600) / 60 << "m ";
664 : output << std::setw(2) << std::setfill('0') << m.m_uptime % 60 << "s ";
665 : output << std::endl;
666 :
667 : for (int i=0 ; i<m.m_n_variables ; i++) {
668 : output << std::dec << std::setw(2) << i << ": " <<
669 : std::setw(16) << std::setfill(' ') << std::left << m.m_var[i].name << std::dec;
670 :
671 : if (m.m_var[i].width == 0)
672 : output << " 0bit ";
673 : else if (m.m_var[i].width == 1)
674 : output << " 8bit ";
675 : else if (m.m_var[i].width == 2)
676 : output << "16bit ";
677 : else if (m.m_var[i].width == 3)
678 : output << "24bit ";
679 : else if (m.m_var[i].width == 4)
680 : output << "32bit ";
681 : else if (m.m_var[i].width == 8)
682 : output << "64bit ";
683 : else
684 : output << " ";
685 :
686 : if (m.m_var[i].flags & MSCBF_FLOAT)
687 : output << "F ";
688 : else if (m.m_var[i].flags & MSCBF_SIGNED)
689 : output << "S ";
690 : else
691 : output << "U ";
692 :
693 : output << std::right << std::setw(16);
694 :
695 : if (m.m_var[i].flags & MSCBF_FLOAT)
696 : output << (float)m.m_data[i];
697 : else
698 : output << m.m_data[i];
699 : if (!(m.m_var[i].flags & MSCBF_SIGNED) &&
700 : !(m.m_var[i].flags & MSCBF_FLOAT) &&
701 : !(m.m_var[i].unit == UNIT_STRING)) {
702 : output << " (0x";
703 : output << std::hex << std::setw(m.m_var[i].width * 2) << std::setfill('0');
704 : output << m.m_data[i] << ")" << std::dec;
705 : }
706 : output << " ";
707 :
708 : // evaluate prefix
709 : if (m.m_var[i].prefix) {
710 : if (m.m_prefixMap.count((int8_t)m.m_var[i].prefix) > 0)
711 : output << m.m_prefixMap[(int8_t)m.m_var[i].prefix];
712 : }
713 :
714 : // evaluate unit
715 : if (m.m_var[i].unit && m.m_var[i].unit != UNIT_STRING) {
716 : if (m.m_unitTable.count(m.m_var[i].unit) > 0)
717 : output << m.m_unitTable[m.m_var[i].unit];
718 : }
719 :
720 : output << std::endl;
721 : }
722 :
723 : output << std::dec << std::setw(0) << std::setfill(' ');
724 : return output;
725 : };
726 :
727 : // overload [<int>] operator
728 0 : u_mscb& operator[](int index) {
729 0 : if (index < 0 || index >= m_n_variables)
730 0 : mthrow("Invalid index \"" + std::to_string(index) + "\" for MSCB node \"" +
731 : m_node_name + "\" which has only " + std::to_string(m_n_variables) + " variables");
732 0 : return m_data[index];
733 : }
734 :
735 0 : int idx(const std::string& var_name) {
736 0 : if (m_map.count(var_name) == 0)
737 0 : mthrow("Variable \"" + var_name + "\" not found in MSCB node \"" + m_node_name + "\"");
738 :
739 0 : return m_map[var_name];
740 : }
741 :
742 : // overload [<std::string>] operator
743 : u_mscb& operator[](std::string var_name) {
744 :
745 : int index = idx(var_name);
746 : return m_data[index];
747 : }
748 :
749 : std::vector<u_mscb> vec(int i1, int i2) {
750 : std::vector<u_mscb> v;
751 :
752 : for (int i = i1 ; i<=i2 ; i++)
753 : v.push_back(m_data[i]);
754 :
755 : return v;
756 : }
757 :
758 : };
759 : }
760 :
761 : #endif
|