otsdaq  v1_01_04
 All Classes Namespaces Functions
FESlowControlsChannel.cc
1 #include "otsdaq-core/FECore/FESlowControlsChannel.h"
2 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
3 
4 
5 #include <iostream>
6 #include <sstream>
7 #include <stdexcept> /*runtime_error*/
8 
9 
10 using namespace ots;
11 
13 //Packet Types sent in txBuffer:
14 //
15 // create value packet:
16 // 1B type (0: value, 1: loloalarm, 2: loalarm, 3: hioalarm, 4: hihialarm)
17 // 1B sequence count from channel
18 // 8B time
19 // 4B sz of name
20 // name
21 // 1B sz of value in bytes
22 // 1B sz of value in bits
23 // value or alarm threshold value
24 //
26 
27 
28 //========================================================================================================================
29 FESlowControlsChannel::FESlowControlsChannel(
30  const std::string& interfaceUID,
31  const std::string& channelName,
32  const std::string& dataType,
33  unsigned int universalDataSize,
34  unsigned int universalAddressSize,
35  const std::string& universalAddress,
36  unsigned int universalDataBitOffset,
37 
38  bool readAccess,
39  bool writeAccess,
40  bool monitoringEnabled,
41  bool recordChangesOnly,
42  time_t delayBetweenSamples,
43  bool saveEnabled,
44  const std::string& savePath,
45  const std::string& saveFileRadix,
46  bool saveBinaryFormat,
47  bool alarmsEnabled,
48  bool latchAlarms,
49  const std::string& lolo,
50  const std::string& lo,
51  const std::string& hi,
52  const std::string& hihi
53 )
54 : interfaceUID_ (interfaceUID),
55  channelName_ (channelName),
56  fullChannelName_ (interfaceUID_ + "/" + channelName_),
57  dataType_ (dataType),
58  universalDataBitOffset_ (universalDataBitOffset),
59  txPacketSequenceNumber_ (0),
60 
61  readAccess_ (readAccess),
62  writeAccess_ (writeAccess),
63  monitoringEnabled_ (monitoringEnabled),
64  recordChangesOnly_ (recordChangesOnly),
65  delayBetweenSamples_ (delayBetweenSamples),
66  saveEnabled_ (saveEnabled),
67  savePath_ (savePath),
68  saveFileRadix_ (saveFileRadix),
69  saveBinaryFormat_ (saveBinaryFormat),
70  alarmsEnabled_ (alarmsEnabled),
71  latchAlarms_ (latchAlarms),
72 
73  lastSampleTime_ (0),
74  loloAlarmed_ (false),
75  loAlarmed_ (false),
76  hiAlarmed_ (false),
77  hihiAlarmed_ (false),
78  saveFullFileName_ (savePath_ + "/" + saveFileRadix_ + "-" + underscoreString(fullChannelName_) + "-" + std::to_string(time(0)) + (saveBinaryFormat_?".dat":".txt"))
79 {
80  __COUT__ << "dataType_ = " << dataType_ << std::endl;
81  __COUT__ << "universalAddressSize = " << universalAddressSize << std::endl;
82  __COUT__ << "universalAddress = " << universalAddress << std::endl;
83 
84  //check for valid types:
85  // if(dataType_ != "char" &&
86  // dataType_ != "short" &&
87  // dataType_ != "int" &&
88  // dataType_ != "unsigned int" &&
89  // dataType_ != "long long " &&
90  // dataType_ != "unsigned long long" &&
91  // dataType_ != "float" &&
92  // dataType_ != "double")
93  // {
94  if(dataType_[dataType_.size()-1] == 'b') //if ends in 'b' then take that many bits
95  sscanf(&dataType_[0],"%u",&sizeOfDataTypeBits_);
96  else if(dataType_ == "char" || dataType_ == "unsigned char")
97  sizeOfDataTypeBits_ = sizeof(char)*8;
98  else if(dataType_ == "short" || dataType_ == "unsigned short")
99  sizeOfDataTypeBits_ = sizeof(short)*8;
100  else if(dataType_ == "int" || dataType_ == "unsigned int")
101  sizeOfDataTypeBits_ = sizeof(int)*8;
102  else if(dataType_ == "long long" || dataType_ == "unsigned long long")
103  sizeOfDataTypeBits_ = sizeof(long long)*8;
104  else if(dataType_ == "float")
105  sizeOfDataTypeBits_ = sizeof(float)*8;
106  else if(dataType_ == "double")
107  sizeOfDataTypeBits_ = sizeof(double)*8;
108  else
109  {
110  __SS__ << "Data type '" << dataType_ << "' is invalid. " <<
111  "Valid data types (w/size in bytes) are as follows: " <<
112  "#b (# bits)" <<
113  ", char (" << sizeof(char) <<
114  "B), unsigned char (" << sizeof(unsigned char) <<
115  "B), short (" << sizeof(short) <<
116  "B), unsigned short (" << sizeof(unsigned short) <<
117  "B), int (" << sizeof(int) <<
118  "B), unsigned int (" << sizeof(unsigned int) <<
119  "B), long long (" << sizeof(long long) <<
120  "B), unsigned long long (" << sizeof(unsigned long long) <<
121  "B), float (" << sizeof(float) <<
122  "B), double (" << sizeof(double) <<
123  "B)." << std::endl;
124  __COUT_ERR__ << "\n" << ss.str();
125  throw std::runtime_error(ss.str());
126  }
127 
128  if(sizeOfDataTypeBits_ > 64)
129  {
130  __SS__ << "Invalid Data Type '" << dataType_ <<
131  "' (" << sizeOfDataTypeBits_ << "-bits)"
132  ". Size in bits must be less than or equal to 64-bits." <<
133  std::endl;
134  __COUT_ERR__ << "\n" << ss.str();
135  throw std::runtime_error(ss.str());
136  }
137 
138  if(universalDataSize*8 < sizeOfDataTypeBits_)
139  {
140  __SS__ << "Invalid Data Type '" << dataType_ <<
141  "' (" << sizeOfDataTypeBits_ << "-bits) or Universal Data Size of " <<
142  universalDataSize*8 <<
143  "-bits. Data Type size must be less than or equal to Universal Data Size." <<
144  std::endl;
145  __COUT_ERR__ << "\n" << ss.str();
146  throw std::runtime_error(ss.str());
147  }
148 
149 
150  universalAddress_.resize(universalAddressSize);
151  convertStringToBuffer(universalAddress,universalAddress_);
152 
153  sizeOfDataTypeBytes_ = (sizeOfDataTypeBits_/8 +
154  ((universalDataBitOffset_%8)?1:0));
155 
156  lolo_.resize(sizeOfDataTypeBytes_);
157  convertStringToBuffer(lolo,lolo_,true);
158  lo_.resize(sizeOfDataTypeBytes_);
159  convertStringToBuffer(lo,lo_,true);
160  hi_.resize(sizeOfDataTypeBytes_);
161  convertStringToBuffer(hi,hi_,true);
162  hihi_.resize(sizeOfDataTypeBytes_);
163  convertStringToBuffer(hihi,hihi_,true);
164 
165  //prepare for data to come
166  sample_.resize(sizeOfDataTypeBytes_);
167  lastSample_.resize(sizeOfDataTypeBytes_);
168 }
169 
170 //========================================================================================================================
171 FESlowControlsChannel::~FESlowControlsChannel(void)
172 {}
173 
174 //========================================================================================================================
175 //underscoreString
176 // replace all non-alphanumeric with underscore
177 std::string FESlowControlsChannel::underscoreString(const std::string& str)
178 {
179  std::string retStr;
180  retStr.reserve(str.size());
181  for(unsigned int i=0;i<str.size();++i)
182  if(
183  (str[i] >= 'a' && str[i] <= 'z') ||
184  (str[i] >= 'A' && str[i] <= 'Z') ||
185  (str[i] >= '0' && str[i] <= '9'))
186  retStr.push_back(str[i]);
187  else
188  retStr.push_back('_');
189  return retStr;
190 }
191 
192 //========================================================================================================================
193 //convertStringToBuffer
194 // adds to txBuffer if sample should be sent to monitor server
195 // if useDataType == false, then assume unsigned long long
196 //
197 // Note: buffer is expected to sized properly in advance, e.g. buffer.resize(#)
198 void FESlowControlsChannel::convertStringToBuffer(const std::string& inString, std::string& buffer, bool useDataType)
199 {
200  __COUT__ << "Input Str Sz= \t" << inString.size() << std::endl;
201  __COUT__ << "Input Str Val= \t'" << inString << "'" << std::endl;
202  __COUT__ << "Output buffer Sz= \t" << buffer.size() << std::endl;
203 
204  if(useDataType &&
205  (dataType_ == "float" || dataType_ == "double"))
206  {
207  __COUT__ << "Floating point spec'd" << std::endl;
208  if(dataType_ == "float" && buffer.size() == sizeof(float))
209  {
210  sscanf(&inString[0],"%f",(float *)&buffer[0]);
211  __COUT__ << "float: " << *((float *)&buffer[0]) << std::endl;
212  }
213  else if(dataType_ == "double" && buffer.size() == sizeof(double))
214  {
215  sscanf(&inString[0],"%lf",(double *)&buffer[0]);
216  __COUT__ << "double: " << *((double *)&buffer[0]) << std::endl;
217  }
218  else
219  {
220  __SS__ << "Invalid floating point spec! " <<
221  "dataType_=" << dataType_ <<
222  " buffer.size()=" << buffer.size() << std::endl;
223  __COUT_ERR__ << "\n" << ss.str();
224  throw std::runtime_error(ss.str());
225  }
226 
227  { //print
228  __SS__ << "0x ";
229  for(int i=(int)buffer.size()-1;i>=0;--i)
230  ss << std::hex << (int)((buffer[i]>>4)&0xF) <<
231  (int)((buffer[i])&0xF) << " " << std::dec;
232  ss << std::endl;
233  __COUT__ << "\n" << ss.str();
234  }
235  return;
236  }
237 
238 
239  //clear buffer
240  for(unsigned int i=0;i<buffer.size();++i)
241  buffer[i] = 0;
242 
243  // { //print
244  // __SS__ << "0x ";
245  // for(int i=(int)buffer.size()-1;i>=0;--i)
246  // ss << std::hex << (int)((buffer[i]>>4)&0xF) <<
247  // (int)((buffer[i])&0xF) << " " << std::dec;
248  // ss << std::endl;
249  // __COUT__ << "\n" << ss.str();
250  // }
251 
252 
253  if(inString.size())
254  {
255  if(inString.size() > 2 && inString[0] == '0' && inString[1] == 'x')
256  {
257  //hex value
258 
259  __COUT__ << "Hex." << std::endl;
260 
261  unsigned int j;
262  unsigned char val;
263  for(unsigned int i=0;i<inString.size();++i)
264  {
265  j = (inString.size()-1-i);
266  if(inString[i] >= '0' &&
267  inString[i] <= '9')
268  val = inString[i] - 48;
269  else if(inString[i] >= 'A' &&
270  inString[i] <= 'F')
271  val = inString[i] - 55;
272  else if(inString[i] >= 'a' &&
273  inString[i] <= 'f')
274  val = inString[i] - 87;
275  else
276  val = 0;
277 
278  buffer[j/2] |= val<<((j%2)*4);
279  }
280  }
281  else //treat as decimal value
282  {
283  //assume not bigger than 64 bits if decimal
284 
285  __COUT__ << "Decimal." << std::endl;
286  unsigned long long val;
287 
288  if(!useDataType || dataType_[0] == 'u') //then use unsigned long long
289  {
290  sscanf(&inString[0],"%llu",&val);
291  }
292  else //use long long
293  {
294  sscanf(&inString[0],"%lld",(long long *)&val);
295  }
296  //transfer the long long to the universal address
297  for(unsigned int i=0;i<sizeof(long long) && i<buffer.size();++i)
298  buffer[i] = ((char *)&val)[i];
299  //assume rest of buffer bytes are 0, since decimal value was given
300  }
301  }
302 
303 
304  { //print
305  __SS__ << "0x ";
306  for(int i=(int)buffer.size()-1;i>=0;--i)
307  ss << std::hex << (int)((buffer[i]>>4)&0xF) <<
308  (int)((buffer[i])&0xF) << " " << std::dec;
309  ss << std::endl;
310  __COUT__ << "\n" << ss.str();
311  }
312 }
313 
314 
315 //========================================================================================================================
316 //handleSample
317 // adds to txBuffer if sample should be sent to monitor server
318 void FESlowControlsChannel::handleSample(const std::string& universalReadValue, std::string& txBuffer,
319  FILE *fpAggregate, bool aggregateIsBinaryFormat)
320 {
321  __COUT__ << "txBuffer size=" << txBuffer.size() << std::endl;
322 
323 
324  //extract sample from universalReadValue
325  // considering bit size and offset
326  extractSample(universalReadValue); //sample_ = universalReadValue
327 
328  //behavior:
329  // if recordChangesOnly
330  // if no change and not first value
331  // return
332  //
333  // for interesting value
334  // if monitoringEnabled
335  // add packet to buffer
336  // if alarmsEnabled
337  // for each alarm add packet to buffer
338  // if localSavingEnabled
339  // append to file
340 
342 
343  if(recordChangesOnly_)
344  {
345  if(lastSampleTime_ &&
346  lastSample_ == sample_)
347  {
348  __COUT__ << "no change." << std::endl;
349  return; //no change
350  }
351  }
352 
353  __COUT__ << "new value!" << std::endl;
354 
355  //else we have an interesting value!
356  lastSampleTime_ = time(0);
357  lastSample_ = sample_;
358 
359  char alarmMask = 0;
360 
364  if(monitoringEnabled_)
365  {
366  //create value packet:
367  // 1B type (0: value, 1: loloalarm, 2: loalarm, 3: hioalarm, 4: hihialarm)
368  // 1B sequence count from channel
369  // 8B time
370  // 4B sz of name
371  // name
372  // 1B sz of value in bytes
373  // 1B sz of value in bits
374  // value
375 
376  __COUT__ << "before txBuffer sz=" << txBuffer.size() << std::endl;
377  txBuffer.push_back(0); //value type
378  txBuffer.push_back(txPacketSequenceNumber_++); //sequence counter and increment
379 
380  txBuffer.resize(txBuffer.size() + sizeof(lastSampleTime_));
381  memcpy(&txBuffer[txBuffer.size() - sizeof(lastSampleTime_)],&lastSampleTime_,sizeof(lastSampleTime_));
382 
383  unsigned int tmpSz = fullChannelName_.size();
384 
385  txBuffer.resize(txBuffer.size() + sizeof(tmpSz));
386  memcpy(&txBuffer[txBuffer.size() - sizeof(tmpSz)],&tmpSz,sizeof(tmpSz));
387 
388  txBuffer += fullChannelName_;
389 
390  txBuffer.push_back((unsigned char)sample_.size()); //size in bytes
391  txBuffer.push_back((unsigned char)sizeOfDataTypeBits_); //size in bits
392 
393  txBuffer += sample_;
394  __COUT__ << "after txBuffer sz=" << txBuffer.size() << std::endl;
395 
396  { //print
397  __SS__ << "txBuffer: \n";
398  for(unsigned int i=0; i<txBuffer.size(); ++i)
399  {
400  ss << std::hex << (int)((txBuffer[i]>>4)&0xF) <<
401  (int)((txBuffer[i])&0xF) << " " << std::dec;
402  if(i%8 == 7) ss << std::endl;
403  }
404  ss << std::endl;
405  __COUT__ << "\n" << ss.str();
406  }
407  }
408 
409  //check alarms
410  if(alarmsEnabled_)
411  alarmMask = checkAlarms(txBuffer);
412 
413  //create array helper for saving
414  std::string *alarmValueArray[] = {
415  &lolo_, &lo_, &hi_, &hihi_
416  };
417 
421  if(fpAggregate) //aggregate file means saving enabled at FE level
422  {
423  //append to file
424  if(aggregateIsBinaryFormat)
425  {
426  //save binary format:
427  // 8B time (save any alarms by marking with time = 1, 2, 3, 4)
428  // 4B sz of name
429  // name
430  // 1B sz of value in bytes
431  // 1B sz of value in bits
432  // value or alarm threshold
433 
434  __COUT__ << "Aggregate Binary File Format: " <<
435  sizeof(lastSampleTime_) << " " << sample_.size() << std::endl;
436 
437  {
438  fwrite(&lastSampleTime_,sizeof(lastSampleTime_),1,fpAggregate);// 8B time
439 
440  unsigned int tmpSz = fullChannelName_.size();
441  fwrite(&tmpSz,sizeof(tmpSz),1,fpAggregate); //4B sz of name
442  fwrite(&fullChannelName_[0],fullChannelName_.size(),1,fpAggregate); //name
443 
444  unsigned char tmpChar = (unsigned char)sample_.size();
445  fwrite(&tmpChar,1,1,fpAggregate); //size in bytes
446 
447  tmpChar = (unsigned char)sizeOfDataTypeBits_;
448  fwrite(&tmpChar,1,1,fpAggregate); //size in bits
449  fwrite(&sample_[0],sample_.size(),1,fpAggregate); //value
450  }
451 
452  //save any alarms by marking with time 1, 2, 3, 4
453  if(alarmMask) //if any alarms
454  for(time_t i=1;i<5;++i, alarmMask >>= 1)
455  if(alarmMask & 1)
456  {
457  {
458  fwrite(&i,sizeof(lastSampleTime_),1,fpAggregate);// 8B save any alarms by marking with time = 1, 2, 3, 4
459 
460  unsigned int tmpSz = fullChannelName_.size();
461  fwrite(&tmpSz,sizeof(tmpSz),1,fpAggregate); //4B sz of name
462  fwrite(&fullChannelName_[0],fullChannelName_.size(),1,fpAggregate); //name
463 
464  unsigned char tmpChar = (unsigned char)sample_.size();
465  fwrite(&tmpChar,1,1,fpAggregate); //size in bytes
466 
467  tmpChar = (unsigned char)sizeOfDataTypeBits_;
468  fwrite(&tmpChar,1,1,fpAggregate); //size in bits
469  fwrite(&(*alarmValueArray[i-1])[0],(*alarmValueArray[i-1]).size(),1,fpAggregate); //alarm threshold
470  }
471  }
472  }
473  else
474  {
475  //save text format:
476  // timestamp (save any alarms by marking with time 1, 2, 3, 4)
477  // name
478  // value
479 
480  __COUT__ << "Aggregate Text File Format: " << dataType_ << std::endl;
481 
482  fprintf(fpAggregate,"%lu\n",lastSampleTime_);
483  fprintf(fpAggregate,"%s\n",fullChannelName_.c_str());
484 
485  if(dataType_[dataType_.size()-1] == 'b') //if ends in 'b' then take that many bits
486  {
487  std::stringstream ss;
488  ss << "0x";
489  for(unsigned int i=0; i<sample_.size(); ++i)
490  ss << std::hex << (int)((sample_[i]>>4)&0xF) <<
491  (int)((sample_[i])&0xF) << std::dec;
492  fprintf(fpAggregate,"%s\n",ss.str().c_str());
493  }
494  else if(dataType_ == "char")
495  fprintf(fpAggregate,"%d\n",*((char *)(&sample_[0])));
496  else if(dataType_ == "unsigned char")
497  fprintf(fpAggregate,"%u\n",*((unsigned char *)(&sample_[0])));
498  else if(dataType_ == "short")
499  fprintf(fpAggregate,"%d\n",*((short *)(&sample_[0])));
500  else if(dataType_ == "unsigned short")
501  fprintf(fpAggregate,"%u\n",*((unsigned short *)(&sample_[0])));
502  else if(dataType_ == "int")
503  fprintf(fpAggregate,"%d\n",*((int *)(&sample_[0])));
504  else if(dataType_ == "unsigned int")
505  fprintf(fpAggregate,"%u\n",*((unsigned int *)(&sample_[0])));
506  else if(dataType_ == "long long")
507  fprintf(fpAggregate,"%lld\n",*((long long *)(&sample_[0])));
508  else if(dataType_ == "unsigned long long")
509  fprintf(fpAggregate,"%llu\n",*((unsigned long long *)(&sample_[0])));
510  else if(dataType_ == "float")
511  fprintf(fpAggregate,"%f\n",*((float *)(&sample_[0])));
512  else if(dataType_ == "double")
513  fprintf(fpAggregate,"%f\n",*((double *)(&sample_[0])));
514 
515 
516  //save any alarms by marking with time 1, 2, 3, 4
517  if(alarmMask) //if any alarms
518  {
519  char checkMask = 1; //use mask to maintain alarm mask
520  for(time_t i=1;i<5;++i, checkMask <<= 1)
521  if(alarmMask & checkMask)
522  {
523  fprintf(fpAggregate,"%lu\n",i);
524  fprintf(fpAggregate,"%s\n",fullChannelName_.c_str());
525 
526  if(dataType_[dataType_.size()-1] == 'b') //if ends in 'b' then take that many bits
527  {
528  std::stringstream ss;
529  ss << "0x";
530  for(unsigned int j=0; j<(*alarmValueArray[i-1]).size(); ++i)
531  ss << std::hex << (int)(((*alarmValueArray[i-1])[j]>>4)&0xF) <<
532  (int)(((*alarmValueArray[i-1])[j])&0xF) << std::dec;
533  fprintf(fpAggregate,"%s\n",ss.str().c_str());
534  }
535  else if(dataType_ == "char")
536  fprintf(fpAggregate,"%d\n",*((char *)(&(*alarmValueArray[i-1])[0])));
537  else if(dataType_ == "unsigned char")
538  fprintf(fpAggregate,"%u\n",*((unsigned char *)(&(*alarmValueArray[i-1])[0])));
539  else if(dataType_ == "short")
540  fprintf(fpAggregate,"%d\n",*((short *)(&(*alarmValueArray[i-1])[0])));
541  else if(dataType_ == "unsigned short")
542  fprintf(fpAggregate,"%u\n",*((unsigned short *)(&(*alarmValueArray[i-1])[0])));
543  else if(dataType_ == "int")
544  fprintf(fpAggregate,"%d\n",*((int *)(&(*alarmValueArray[i-1])[0])));
545  else if(dataType_ == "unsigned int")
546  fprintf(fpAggregate,"%u\n",*((unsigned int *)(&(*alarmValueArray[i-1])[0])));
547  else if(dataType_ == "long long")
548  fprintf(fpAggregate,"%lld\n",*((long long *)(&(*alarmValueArray[i-1])[0])));
549  else if(dataType_ == "unsigned long long")
550  fprintf(fpAggregate,"%llu\n",*((unsigned long long *)(&(*alarmValueArray[i-1])[0])));
551  else if(dataType_ == "float")
552  fprintf(fpAggregate,"%f\n",*((float *)(&(*alarmValueArray[i-1])[0])));
553  else if(dataType_ == "double")
554  fprintf(fpAggregate,"%f\n",*((double *)(&(*alarmValueArray[i-1])[0])));
555  }
556  }
557  }
558  }
559 
563  if(saveEnabled_)
564  {
565  FILE *fp = fopen(saveFullFileName_.c_str(),saveBinaryFormat_?"ab":"a");
566  if(!fp)
567  {
568  __COUT_ERR__ << "Failed to open slow controls channel file: " <<
569  saveFullFileName_ << std::endl;
570  return;
571  }
572 
573  //append to file
574  if(saveBinaryFormat_)
575  {
576  __COUT__ << "Binary File Format: " << sizeof(lastSampleTime_) << " " << sample_.size() << std::endl;
577  fwrite(&lastSampleTime_,sizeof(lastSampleTime_),1,fp);
578  fwrite(&sample_[0],sample_.size(),1,fp);
579 
580  //save any alarms by marking with time 1, 2, 3, 4
581  if(alarmMask) //if any alarms
582  for(time_t i=1;i<5;++i, alarmMask >>= 1)
583  if(alarmMask & 1)
584  {
585  fwrite(&i,sizeof(lastSampleTime_),1,fp);
586  fwrite(&(*alarmValueArray[i-1])[0],(*alarmValueArray[i-1]).size(),1,fp);
587  }
588  }
589  else
590  {
591  __COUT__ << "Text File Format: " << dataType_ << std::endl;
592 
593  fprintf(fp,"%lu\n",lastSampleTime_);
594 
595  if(dataType_[dataType_.size()-1] == 'b') //if ends in 'b' then take that many bits
596  {
597  std::stringstream ss;
598  ss << "0x";
599  for(unsigned int i=0; i<sample_.size(); ++i)
600  ss << std::hex << (int)((sample_[i]>>4)&0xF) <<
601  (int)((sample_[i])&0xF) << std::dec;
602  fprintf(fp,"%s\n",ss.str().c_str());
603  }
604  else if(dataType_ == "char")
605  fprintf(fp,"%d\n",*((char *)(&sample_[0])));
606  else if(dataType_ == "unsigned char")
607  fprintf(fp,"%u\n",*((unsigned char *)(&sample_[0])));
608  else if(dataType_ == "short")
609  fprintf(fp,"%d\n",*((short *)(&sample_[0])));
610  else if(dataType_ == "unsigned short")
611  fprintf(fp,"%u\n",*((unsigned short *)(&sample_[0])));
612  else if(dataType_ == "int")
613  fprintf(fp,"%d\n",*((int *)(&sample_[0])));
614  else if(dataType_ == "unsigned int")
615  fprintf(fp,"%u\n",*((unsigned int *)(&sample_[0])));
616  else if(dataType_ == "long long")
617  fprintf(fp,"%lld\n",*((long long *)(&sample_[0])));
618  else if(dataType_ == "unsigned long long")
619  fprintf(fp,"%llu\n",*((unsigned long long *)(&sample_[0])));
620  else if(dataType_ == "float")
621  fprintf(fp,"%f\n",*((float *)(&sample_[0])));
622  else if(dataType_ == "double")
623  fprintf(fp,"%f\n",*((double *)(&sample_[0])));
624 
625 
626  //save any alarms by marking with time 1, 2, 3, 4
627  if(alarmMask) //if any alarms
628  {
629  char checkMask = 1; //use mask to maintain alarm mask
630  for(time_t i=1;i<5;++i, checkMask <<= 1)
631  if(alarmMask & checkMask)
632  {
633  fprintf(fp,"%lu\n",i);
634 
635  if(dataType_[dataType_.size()-1] == 'b') //if ends in 'b' then take that many bits
636  {
637  std::stringstream ss;
638  ss << "0x";
639  for(unsigned int j=0; j<(*alarmValueArray[i-1]).size(); ++i)
640  ss << std::hex << (int)(((*alarmValueArray[i-1])[j]>>4)&0xF) <<
641  (int)(((*alarmValueArray[i-1])[j])&0xF) << std::dec;
642  fprintf(fp,"%s\n",ss.str().c_str());
643  }
644  else if(dataType_ == "char")
645  fprintf(fp,"%d\n",*((char *)(&(*alarmValueArray[i-1])[0])));
646  else if(dataType_ == "unsigned char")
647  fprintf(fp,"%u\n",*((unsigned char *)(&(*alarmValueArray[i-1])[0])));
648  else if(dataType_ == "short")
649  fprintf(fp,"%d\n",*((short *)(&(*alarmValueArray[i-1])[0])));
650  else if(dataType_ == "unsigned short")
651  fprintf(fp,"%u\n",*((unsigned short *)(&(*alarmValueArray[i-1])[0])));
652  else if(dataType_ == "int")
653  fprintf(fp,"%d\n",*((int *)(&(*alarmValueArray[i-1])[0])));
654  else if(dataType_ == "unsigned int")
655  fprintf(fp,"%u\n",*((unsigned int *)(&(*alarmValueArray[i-1])[0])));
656  else if(dataType_ == "long long")
657  fprintf(fp,"%lld\n",*((long long *)(&(*alarmValueArray[i-1])[0])));
658  else if(dataType_ == "unsigned long long")
659  fprintf(fp,"%llu\n",*((unsigned long long *)(&(*alarmValueArray[i-1])[0])));
660  else if(dataType_ == "float")
661  fprintf(fp,"%f\n",*((float *)(&(*alarmValueArray[i-1])[0])));
662  else if(dataType_ == "double")
663  fprintf(fp,"%f\n",*((double *)(&(*alarmValueArray[i-1])[0])));
664  }
665  }
666  }
667 
668  fclose(fp);
669  }
670 }
671 
672 //========================================================================================================================
673 //extractSample
674 // extract sample from universalReadValue
675 // considering bit size and offset
676 void FESlowControlsChannel::extractSample(const std::string& universalReadValue)
677 {
678  //procedure:
679 
680  { //print
681  __SS__ << "Univ Read: ";
682  for(unsigned int i=0; i<universalReadValue.size(); ++i)
683  ss << std::hex << (int)((universalReadValue[i]>>4)&0xF) <<
684  (int)((universalReadValue[i])&0xF) << " " << std::dec;
685  ss << std::endl;
686  __COUT__ << "\n" << ss.str();
687  }
688 
689  unsigned int byteOffset = universalDataBitOffset_/8;
690  unsigned int bitOffset = universalDataBitOffset_%8;
691  unsigned int bitsLeft = sizeOfDataTypeBits_;
692 
693  //copy to tmp (assume sample max size is 64 bits)
694  unsigned long long tmp = 0;
695 
696  if(bitOffset) //copy first partial byte
697  {
698  // __COUT__ << "bitsLeft=" << bitsLeft <<
699  // " byteOffset=" << byteOffset <<
700  // " bitOffset=" << bitOffset <<
701  // std::endl;
702 
703  tmp = ((unsigned long long)(universalReadValue[byteOffset++])) >> bitOffset;
704  bitsLeft = 8 - bitOffset;
705 
706  // { //print
707  // __SS__ << "Tmp: ";
708  // for(unsigned int i=0; i<sizeof(tmp); ++i)
709  // ss << std::hex << (int)((((char *)&tmp)[i]>>4)&0xF) <<
710  // (int)((((char *)&tmp)[i])&0xF) << " " << std::dec;
711  // ss << std::endl;
712  // __COUT__ << "\n" << ss.str();
713  // }
714  }
715 
716  while(bitsLeft > 7) //copy whole bytes
717  {
718  // __COUT__ << "bitsLeft=" << bitsLeft <<
719  // " byteOffset=" << byteOffset <<
720  // " bitOffset=" << bitOffset <<
721  // std::endl;
722 
723  tmp |= ((unsigned long long)(universalReadValue[byteOffset++])) <<
724  (sizeOfDataTypeBits_ - bitsLeft);
725  bitsLeft -= 8;
726 
727  // { //print
728  // __SS__ << "Tmp: ";
729  // for(unsigned int i=0; i<sizeof(tmp); ++i)
730  // ss << std::hex << (int)((((char *)&tmp)[i]>>4)&0xF) <<
731  // (int)((((char *)&tmp)[i])&0xF) << " " << std::dec;
732  // ss << std::endl;
733  // __COUT__ << "\n" << ss.str();
734  // }
735  }
736 
737  if(bitOffset) //copy last partial byte
738  {
739  // __COUT__ << "bitsLeft=" << bitsLeft <<
740  // " byteOffset=" << byteOffset <<
741  // " bitOffset=" << bitOffset <<
742  // std::endl;
743 
744  tmp |= (((unsigned long long)(universalReadValue[byteOffset])) &
745  (0xFF >> (8-bitsLeft))) <<
746  (sizeOfDataTypeBits_ - bitsLeft);
747 
748  // { //print
749  // __SS__ << "Tmp: ";
750  // for(unsigned int i=0; i<sizeof(tmp); ++i)
751  // ss << std::hex << (int)((((char *)&tmp)[i]>>4)&0xF) <<
752  // (int)((((char *)&tmp)[i])&0xF) << " " << std::dec;
753  // ss << std::endl;
754  // __COUT__ << "\n" << ss.str();
755  // }
756  }
757 
758  __COUT__ << "Temp Long Long Sample: " << tmp << std::endl;
759 
760  sample_.resize(0); //clear a la sample_ = "";
761  for(unsigned int i=0; i<(sizeOfDataTypeBits_/8 +
762  ((universalDataBitOffset_%8)?1:0)); ++i)
763  sample_.push_back(((char *)&tmp)[i]);
764 
765  __COUT__ << "sample_.size()= " << sample_.size() << std::endl;
766 
767  { //print
768  __SS__ << "Sample: ";
769  for(unsigned int i=0; i<sample_.size(); ++i)
770  ss << std::hex << (int)((sample_[i]>>4)&0xF) <<
771  (int)((sample_[i])&0xF) << " " << std::dec;
772  ss << std::endl;
773  __COUT__ << "\n" << ss.str();
774  }
775 
776 }
777 
778 
779 //========================================================================================================================
780 //clearAlarms
781 // clear target alarm
782 // if -1 clear all
783 void FESlowControlsChannel::clearAlarms(int targetAlarm)
784 {
785  if(targetAlarm == -1 || targetAlarm == 0)
786  loloAlarmed_ = false;
787  if(targetAlarm == -1 || targetAlarm == 1)
788  loAlarmed_ = false;
789  if(targetAlarm == -1 || targetAlarm == 2)
790  hiAlarmed_ = false;
791  if(targetAlarm == -1 || targetAlarm == 3)
792  hihiAlarmed_ = false;
793 }
794 
795 //========================================================================================================================
796 //checkAlarms
797 // if current value is a new alarm, set alarmed and add alarm packet to buffer
798 //
799 // return mask of alarms that fired during this check.
800 char FESlowControlsChannel::checkAlarms(std::string& txBuffer)
801 {
802  //procedure:
803  // for each alarm type
804  // determine type and get value as proper type
805  // i.e.:
806  // 0 -- unsigned long long
807  // 1 -- long long
808  // 2 -- float
809  // 3 -- double
810  // do comparison with the type
811  // alarm alarms
812 
813 
814  int useType = -1;
815  char createPacketMask = 0;
816 
817 
818  if(dataType_[dataType_.size()-1] == 'b') //if ends in 'b' then take that many bits
819  useType = 0;
820  else if(dataType_ == "char")
821  useType = 1;
822  else if(dataType_ == "unsigned char")
823  useType = 0;
824  else if(dataType_ == "short")
825  useType = 1;
826  else if(dataType_ == "unsigned short")
827  useType = 0;
828  else if(dataType_ == "int")
829  useType = 1;
830  else if(dataType_ == "unsigned int")
831  useType = 0;
832  else if(dataType_ == "long long")
833  useType = 1;
834  else if(dataType_ == "unsigned long long")
835  useType = 0;
836  else if(dataType_ == "float")
837  useType = 2;
838  else if(dataType_ == "double")
839  useType = 3;
840 
841 
842  if(useType == 0) //unsigned long long
843  {
844  __COUT__ << "Using unsigned long long for alarms." << std::endl;
845  //lolo
846  if((!loloAlarmed_ || !latchAlarms_) &&
847  *((unsigned long long *)&sample_[0]) <=
848  *((unsigned long long *)&lolo_[0]) )
849  {
850  loloAlarmed_ = true;
851  createPacketMask |= 1 << 0;
852  }
853  //lo
854  if((!loAlarmed_ || !latchAlarms_) &&
855  *((unsigned long long *)&sample_[0]) <=
856  *((unsigned long long *)&lo_[0]) )
857  {
858  loAlarmed_ = true;
859  createPacketMask |= 1 << 1;
860  }
861  //hi
862  if((!hiAlarmed_ || !latchAlarms_) &&
863  *((unsigned long long *)&sample_[0]) >=
864  *((unsigned long long *)&hi_[0]) )
865  {
866  hiAlarmed_ = true;
867  createPacketMask |= 1 << 2;
868  }
869  //hihi
870  if((!hihiAlarmed_ || !latchAlarms_) &&
871  *((unsigned long long *)&sample_[0]) >=
872  *((unsigned long long *)&hihi_[0]) )
873  {
874  hihiAlarmed_ = true;
875  createPacketMask |= 1 << 3;
876  }
877  }
878  else if(useType == 1) //long long
879  {
880  __COUT__ << "Using long long for alarms." << std::endl;
881  //lolo
882  if((!loloAlarmed_ || !latchAlarms_) &&
883  *((long long *)&sample_[0]) <=
884  *((long long *)&lolo_[0]) )
885  {
886  loloAlarmed_ = true;
887  createPacketMask |= 1 << 0;
888  }
889  //lo
890  if((!loAlarmed_ || !latchAlarms_) &&
891  *((long long *)&sample_[0]) <=
892  *((long long *)&lo_[0]) )
893  {
894  loAlarmed_ = true;
895  createPacketMask |= 1 << 1;
896  }
897  //hi
898  if((!hiAlarmed_ || !latchAlarms_) &&
899  *((long long *)&sample_[0]) >=
900  *((long long *)&hi_[0]) )
901  {
902  hiAlarmed_ = true;
903  createPacketMask |= 1 << 2;
904  }
905  //hihi
906  if((!hihiAlarmed_ || !latchAlarms_) &&
907  *((long long *)&sample_[0]) >=
908  *((long long *)&hihi_[0]) )
909  {
910  hihiAlarmed_ = true;
911  createPacketMask |= 1 << 3;
912  }
913  }
914  else if(useType == 2) //float
915  {
916  __COUT__ << "Using float for alarms." << std::endl;
917  //lolo
918  if((!loloAlarmed_ || !latchAlarms_) &&
919  *((float *)&sample_[0]) <=
920  *((float *)&lolo_[0]) )
921  {
922  loloAlarmed_ = true;
923  createPacketMask |= 1 << 0;
924  }
925  //lo
926  if((!loAlarmed_ || !latchAlarms_) &&
927  *((float *)&sample_[0]) <=
928  *((float *)&lo_[0]) )
929  {
930  loAlarmed_ = true;
931  createPacketMask |= 1 << 1;
932  }
933  //hi
934  if((!hiAlarmed_ || !latchAlarms_) &&
935  *((float *)&sample_[0]) >=
936  *((float *)&hi_[0]) )
937  {
938  hiAlarmed_ = true;
939  createPacketMask |= 1 << 2;
940  }
941  //hihi
942  if((!hihiAlarmed_ || !latchAlarms_) &&
943  *((float *)&sample_[0]) >=
944  *((float *)&hihi_[0]) )
945  {
946  hihiAlarmed_ = true;
947  createPacketMask |= 1 << 3;
948  }
949  }
950  else if(useType == 3) //double
951  {
952  __COUT__ << "Using double for alarms." << std::endl;
953  //lolo
954  if((!loloAlarmed_ || !latchAlarms_) &&
955  *((double *)&sample_[0]) <=
956  *((double *)&lolo_[0]) )
957  {
958  loloAlarmed_ = true;
959  createPacketMask |= 1 << 0;
960  }
961  //lo
962  if((!loAlarmed_ || !latchAlarms_) &&
963  *((double *)&sample_[0]) <=
964  *((double *)&lo_[0]) )
965  {
966  loAlarmed_ = true;
967  createPacketMask |= 1 << 1;
968  }
969  //hi
970  if((!hiAlarmed_ || !latchAlarms_) &&
971  *((double *)&sample_[0]) >=
972  *((double *)&hi_[0]) )
973  {
974  hiAlarmed_ = true;
975  createPacketMask |= 1 << 2;
976  }
977  //hihi
978  if((!hihiAlarmed_ || !latchAlarms_) &&
979  *((double *)&sample_[0]) >=
980  *((double *)&hihi_[0]) )
981  {
982  hihiAlarmed_ = true;
983  createPacketMask |= 1 << 3;
984  }
985  }
986 
987 
988  //create array helper for packet gen
989  std::string *alarmValueArray[] = {
990  &lolo_, &lo_, &hi_, &hihi_
991  };
992 
993  if(monitoringEnabled_) //only create packet if monitoring
994  {
995  //create a packet for each bit in mask
996  char checkMask = 1; //use mask to maintain return mask
997  for(int i=0;i<4;++i, checkMask <<= 1)
998  if(createPacketMask & checkMask)
999  {
1000  //create alarm packet:
1001  // 1B type (0: value, 1: loloalarm, 2: loalarm, 3: hioalarm, 4: hihialarm)
1002  // 1B sequence count from channel
1003  // 8B time
1004  // 4B sz of name
1005  // name
1006  // 1B sz of alarm value in bytes
1007  // 1B sz of alarm value in bits
1008  // alarm value
1009 
1010  __COUT__ << "Create packet type " << i+1 <<
1011  " alarm value = " << *alarmValueArray[i] << std::endl;
1012 
1013  __COUT__ << "before txBuffer sz=" << txBuffer.size() << std::endl;
1014  txBuffer.push_back(i+1); //alarm packet type
1015  txBuffer.push_back(txPacketSequenceNumber_++); //sequence counter and increment
1016 
1017  txBuffer.resize(txBuffer.size() + sizeof(lastSampleTime_));
1018  memcpy(&txBuffer[txBuffer.size() - sizeof(lastSampleTime_)],&lastSampleTime_,sizeof(lastSampleTime_));
1019 
1020  unsigned int tmpSz = fullChannelName_.size();
1021 
1022  txBuffer.resize(txBuffer.size() + sizeof(tmpSz));
1023  memcpy(&txBuffer[txBuffer.size() - sizeof(tmpSz)],&tmpSz,sizeof(tmpSz));
1024 
1025  txBuffer += fullChannelName_;
1026 
1027  txBuffer.push_back((unsigned char)(*alarmValueArray[i]).size()); //size in bytes
1028  txBuffer.push_back((unsigned char)sizeOfDataTypeBits_); //size in bits
1029 
1030  txBuffer += (*alarmValueArray[i]);
1031  __COUT__ << "after txBuffer sz=" << txBuffer.size() << std::endl;
1032 
1033  { //print
1034  __SS__ << "txBuffer: \n";
1035  for(unsigned int i=0; i<txBuffer.size(); ++i)
1036  {
1037  ss << std::hex << (int)((txBuffer[i]>>4)&0xF) <<
1038  (int)((txBuffer[i])&0xF) << " " << std::dec;
1039  if(i%8 == 7) ss << std::endl;
1040  }
1041  ss << std::endl;
1042  __COUT__ << "\n" << ss.str();
1043  }
1044  }
1045  }
1046 
1047  return createPacketMask;
1048 }
1049 
1050 
1051 
1052 
1053 
1054 
1055 
1056 
1057 
1058 
1059 
1060 
1061 
1062 
1063 
1064 
1065 
1066 
1067 
1068 
1069 
1070 
1071 
1072 
1073 
1074 
1075 
1076 
1077