$treeview $search $mathjax $extrastylesheet
otsdaq
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "otsdaq-core/FECore/FESlowControlsChannel.h" 00002 #include "otsdaq-core/Macros/CoutMacros.h" 00003 00004 #include <iostream> 00005 #include <sstream> 00006 #include <stdexcept> /*runtime_error*/ 00007 00008 using namespace ots; 00009 00011 // Packet Types sent in txBuffer: 00012 // 00013 // create value packet: 00014 // 1B type (0: value, 1: loloalarm, 2: loalarm, 3: hioalarm, 4: hihialarm) 00015 // 1B sequence count from channel 00016 // 8B time 00017 // 4B sz of name 00018 // name 00019 // 1B sz of value in bytes 00020 // 1B sz of value in bits 00021 // value or alarm threshold value 00022 // 00024 00025 //======================================================================================================================== 00026 FESlowControlsChannel::FESlowControlsChannel(const std::string& interfaceUID, 00027 const std::string& channelName, 00028 const std::string& dataType, 00029 unsigned int universalDataSize, 00030 unsigned int universalAddressSize, 00031 const std::string& universalAddress, 00032 unsigned int universalDataBitOffset, 00033 00034 bool readAccess, 00035 bool writeAccess, 00036 bool monitoringEnabled, 00037 bool recordChangesOnly, 00038 time_t delayBetweenSamples, 00039 bool saveEnabled, 00040 const std::string& savePath, 00041 const std::string& saveFileRadix, 00042 bool saveBinaryFormat, 00043 bool alarmsEnabled, 00044 bool latchAlarms, 00045 const std::string& lolo, 00046 const std::string& lo, 00047 const std::string& hi, 00048 const std::string& hihi) 00049 : interfaceUID_(interfaceUID) 00050 , channelName_(channelName) 00051 , fullChannelName_(interfaceUID_ + "/" + channelName_) 00052 , dataType_(dataType) 00053 , universalDataBitOffset_(universalDataBitOffset) 00054 , txPacketSequenceNumber_(0) 00055 , 00056 00057 readAccess_(readAccess) 00058 , writeAccess_(writeAccess) 00059 , monitoringEnabled_(monitoringEnabled) 00060 , recordChangesOnly_(recordChangesOnly) 00061 , delayBetweenSamples_(delayBetweenSamples) 00062 , saveEnabled_(saveEnabled) 00063 , savePath_(savePath) 00064 , saveFileRadix_(saveFileRadix) 00065 , saveBinaryFormat_(saveBinaryFormat) 00066 , alarmsEnabled_(alarmsEnabled) 00067 , latchAlarms_(latchAlarms) 00068 , 00069 00070 lastSampleTime_(0) 00071 , loloAlarmed_(false) 00072 , loAlarmed_(false) 00073 , hiAlarmed_(false) 00074 , hihiAlarmed_(false) 00075 , saveFullFileName_(savePath_ + "/" + saveFileRadix_ + "-" + 00076 underscoreString(fullChannelName_) + "-" + 00077 std::to_string(time(0)) + (saveBinaryFormat_ ? ".dat" : ".txt")) 00078 { 00079 __COUT__ << "dataType_ = " << dataType_ << std::endl; 00080 __COUT__ << "universalAddressSize = " << universalAddressSize << std::endl; 00081 __COUT__ << "universalAddress = " << universalAddress << std::endl; 00082 00083 // check for valid types: 00084 // if(dataType_ != "char" && 00085 // dataType_ != "short" && 00086 // dataType_ != "int" && 00087 // dataType_ != "unsigned int" && 00088 // dataType_ != "long long " && 00089 // dataType_ != "unsigned long long" && 00090 // dataType_ != "float" && 00091 // dataType_ != "double") 00092 // { 00093 if(dataType_[dataType_.size() - 1] == 'b') // if ends in 'b' then take that many bits 00094 sscanf(&dataType_[0], "%u", &sizeOfDataTypeBits_); 00095 else if(dataType_ == "char" || dataType_ == "unsigned char") 00096 sizeOfDataTypeBits_ = sizeof(char) * 8; 00097 else if(dataType_ == "short" || dataType_ == "unsigned short") 00098 sizeOfDataTypeBits_ = sizeof(short) * 8; 00099 else if(dataType_ == "int" || dataType_ == "unsigned int") 00100 sizeOfDataTypeBits_ = sizeof(int) * 8; 00101 else if(dataType_ == "long long" || dataType_ == "unsigned long long") 00102 sizeOfDataTypeBits_ = sizeof(long long) * 8; 00103 else if(dataType_ == "float") 00104 sizeOfDataTypeBits_ = sizeof(float) * 8; 00105 else if(dataType_ == "double") 00106 sizeOfDataTypeBits_ = sizeof(double) * 8; 00107 else 00108 { 00109 __SS__ << "Data type '" << dataType_ << "' is invalid. " 00110 << "Valid data types (w/size in bytes) are as follows: " 00111 << "#b (# bits)" 00112 << ", char (" << sizeof(char) << "B), unsigned char (" 00113 << sizeof(unsigned char) << "B), short (" << sizeof(short) 00114 << "B), unsigned short (" << sizeof(unsigned short) << "B), int (" 00115 << sizeof(int) << "B), unsigned int (" << sizeof(unsigned int) 00116 << "B), long long (" << sizeof(long long) << "B), unsigned long long (" 00117 << sizeof(unsigned long long) << "B), float (" << sizeof(float) 00118 << "B), double (" << sizeof(double) << "B)." << std::endl; 00119 __COUT_ERR__ << "\n" << ss.str(); 00120 __SS_THROW__; 00121 } 00122 00123 if(sizeOfDataTypeBits_ > 64) 00124 { 00125 __SS__ << "Invalid Data Type '" << dataType_ << "' (" << sizeOfDataTypeBits_ 00126 << "-bits)" 00127 ". Size in bits must be less than or equal to 64-bits." 00128 << std::endl; 00129 __COUT_ERR__ << "\n" << ss.str(); 00130 __SS_THROW__; 00131 } 00132 00133 if(universalDataSize * 8 < sizeOfDataTypeBits_) 00134 { 00135 __SS__ 00136 << "Invalid Data Type '" << dataType_ << "' (" << sizeOfDataTypeBits_ 00137 << "-bits) or Universal Data Size of " << universalDataSize * 8 00138 << "-bits. Data Type size must be less than or equal to Universal Data Size." 00139 << std::endl; 00140 __COUT_ERR__ << "\n" << ss.str(); 00141 __SS_THROW__; 00142 } 00143 00144 universalAddress_.resize(universalAddressSize); 00145 convertStringToBuffer(universalAddress, universalAddress_); 00146 00147 sizeOfDataTypeBytes_ = 00148 (sizeOfDataTypeBits_ / 8 + ((universalDataBitOffset_ % 8) ? 1 : 0)); 00149 00150 lolo_.resize(sizeOfDataTypeBytes_); 00151 convertStringToBuffer(lolo, lolo_, true); 00152 lo_.resize(sizeOfDataTypeBytes_); 00153 convertStringToBuffer(lo, lo_, true); 00154 hi_.resize(sizeOfDataTypeBytes_); 00155 convertStringToBuffer(hi, hi_, true); 00156 hihi_.resize(sizeOfDataTypeBytes_); 00157 convertStringToBuffer(hihi, hihi_, true); 00158 00159 // prepare for data to come 00160 sample_.resize(sizeOfDataTypeBytes_); 00161 lastSample_.resize(sizeOfDataTypeBytes_); 00162 } 00163 00164 //======================================================================================================================== 00165 FESlowControlsChannel::~FESlowControlsChannel(void) {} 00166 00167 //======================================================================================================================== 00168 // underscoreString 00169 // replace all non-alphanumeric with underscore 00170 std::string FESlowControlsChannel::underscoreString(const std::string& str) 00171 { 00172 std::string retStr; 00173 retStr.reserve(str.size()); 00174 for(unsigned int i = 0; i < str.size(); ++i) 00175 if((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || 00176 (str[i] >= '0' && str[i] <= '9')) 00177 retStr.push_back(str[i]); 00178 else 00179 retStr.push_back('_'); 00180 return retStr; 00181 } 00182 00183 //======================================================================================================================== 00184 // convertStringToBuffer 00185 // adds to txBuffer if sample should be sent to monitor server 00186 // if useDataType == false, then assume unsigned long long 00187 // 00188 // Note: buffer is expected to sized properly in advance, e.g. buffer.resize(#) 00189 void FESlowControlsChannel::convertStringToBuffer(const std::string& inString, 00190 std::string& buffer, 00191 bool useDataType) 00192 { 00193 __COUT__ << "Input Str Sz= \t" << inString.size() << std::endl; 00194 __COUT__ << "Input Str Val= \t'" << inString << "'" << std::endl; 00195 __COUT__ << "Output buffer Sz= \t" << buffer.size() << std::endl; 00196 00197 if(useDataType && (dataType_ == "float" || dataType_ == "double")) 00198 { 00199 __COUT__ << "Floating point spec'd" << std::endl; 00200 if(dataType_ == "float" && buffer.size() == sizeof(float)) 00201 { 00202 sscanf(&inString[0], "%f", (float*)&buffer[0]); 00203 __COUT__ << "float: " << *((float*)&buffer[0]) << std::endl; 00204 } 00205 else if(dataType_ == "double" && buffer.size() == sizeof(double)) 00206 { 00207 sscanf(&inString[0], "%lf", (double*)&buffer[0]); 00208 __COUT__ << "double: " << *((double*)&buffer[0]) << std::endl; 00209 } 00210 else 00211 { 00212 __SS__ << "Invalid floating point spec! " 00213 << "dataType_=" << dataType_ << " buffer.size()=" << buffer.size() 00214 << std::endl; 00215 __COUT_ERR__ << "\n" << ss.str(); 00216 __SS_THROW__; 00217 } 00218 00219 { // print 00220 __SS__ << "0x "; 00221 for(int i = (int)buffer.size() - 1; i >= 0; --i) 00222 ss << std::hex << (int)((buffer[i] >> 4) & 0xF) 00223 << (int)((buffer[i]) & 0xF) << " " << std::dec; 00224 ss << std::endl; 00225 __COUT__ << "\n" << ss.str(); 00226 } 00227 return; 00228 } 00229 00230 // clear buffer 00231 for(unsigned int i = 0; i < buffer.size(); ++i) 00232 buffer[i] = 0; 00233 00234 // { //print 00235 // __SS__ << "0x "; 00236 // for(int i=(int)buffer.size()-1;i>=0;--i) 00237 // ss << std::hex << (int)((buffer[i]>>4)&0xF) << 00238 // (int)((buffer[i])&0xF) << " " << std::dec; 00239 // ss << std::endl; 00240 // __COUT__ << "\n" << ss.str(); 00241 // } 00242 00243 if(inString.size()) 00244 { 00245 if(inString.size() > 2 && inString[0] == '0' && inString[1] == 'x') 00246 { 00247 // hex value 00248 00249 __COUT__ << "Hex." << std::endl; 00250 00251 unsigned int j; 00252 unsigned char val; 00253 for(unsigned int i = 0; i < inString.size(); ++i) 00254 { 00255 j = (inString.size() - 1 - i); 00256 if(inString[i] >= '0' && inString[i] <= '9') 00257 val = inString[i] - 48; 00258 else if(inString[i] >= 'A' && inString[i] <= 'F') 00259 val = inString[i] - 55; 00260 else if(inString[i] >= 'a' && inString[i] <= 'f') 00261 val = inString[i] - 87; 00262 else 00263 val = 0; 00264 00265 buffer[j / 2] |= val << ((j % 2) * 4); 00266 } 00267 } 00268 else // treat as decimal value 00269 { 00270 // assume not bigger than 64 bits if decimal 00271 00272 __COUT__ << "Decimal." << std::endl; 00273 unsigned long long val; 00274 00275 if(!useDataType || dataType_[0] == 'u') // then use unsigned long long 00276 { 00277 sscanf(&inString[0], "%llu", &val); 00278 } 00279 else // use long long 00280 { 00281 sscanf(&inString[0], "%lld", (long long*)&val); 00282 } 00283 // transfer the long long to the universal address 00284 for(unsigned int i = 0; i < sizeof(long long) && i < buffer.size(); ++i) 00285 buffer[i] = ((char*)&val)[i]; 00286 // assume rest of buffer bytes are 0, since decimal value was given 00287 } 00288 } 00289 00290 { // print 00291 __SS__ << "0x "; 00292 for(int i = (int)buffer.size() - 1; i >= 0; --i) 00293 ss << std::hex << (int)((buffer[i] >> 4) & 0xF) << (int)((buffer[i]) & 0xF) 00294 << " " << std::dec; 00295 ss << std::endl; 00296 __COUT__ << "\n" << ss.str(); 00297 } 00298 } 00299 00300 //======================================================================================================================== 00301 // handleSample 00302 // adds to txBuffer if sample should be sent to monitor server 00303 void FESlowControlsChannel::handleSample(const std::string& universalReadValue, 00304 std::string& txBuffer, 00305 FILE* fpAggregate, 00306 bool aggregateIsBinaryFormat) 00307 { 00308 __COUT__ << "txBuffer size=" << txBuffer.size() << std::endl; 00309 00310 // extract sample from universalReadValue 00311 // considering bit size and offset 00312 extractSample(universalReadValue); // sample_ = universalReadValue 00313 00314 // behavior: 00315 // if recordChangesOnly 00316 // if no change and not first value 00317 // return 00318 // 00319 // for interesting value 00320 // if monitoringEnabled 00321 // add packet to buffer 00322 // if alarmsEnabled 00323 // for each alarm add packet to buffer 00324 // if localSavingEnabled 00325 // append to file 00326 00328 00329 if(recordChangesOnly_) 00330 { 00331 if(lastSampleTime_ && lastSample_ == sample_) 00332 { 00333 __COUT__ << "no change." << std::endl; 00334 return; // no change 00335 } 00336 } 00337 00338 __COUT__ << "new value!" << std::endl; 00339 00340 // else we have an interesting value! 00341 lastSampleTime_ = time(0); 00342 lastSample_ = sample_; 00343 00344 char alarmMask = 0; 00345 00349 if(monitoringEnabled_) 00350 { 00351 // create value packet: 00352 // 1B type (0: value, 1: loloalarm, 2: loalarm, 3: hioalarm, 4: hihialarm) 00353 // 1B sequence count from channel 00354 // 8B time 00355 // 4B sz of name 00356 // name 00357 // 1B sz of value in bytes 00358 // 1B sz of value in bits 00359 // value 00360 00361 __COUT__ << "before txBuffer sz=" << txBuffer.size() << std::endl; 00362 txBuffer.push_back(0); // value type 00363 txBuffer.push_back(txPacketSequenceNumber_++); // sequence counter and increment 00364 00365 txBuffer.resize(txBuffer.size() + sizeof(lastSampleTime_)); 00366 memcpy(&txBuffer[txBuffer.size() - sizeof(lastSampleTime_)], 00367 &lastSampleTime_, 00368 sizeof(lastSampleTime_)); 00369 00370 unsigned int tmpSz = fullChannelName_.size(); 00371 00372 txBuffer.resize(txBuffer.size() + sizeof(tmpSz)); 00373 memcpy(&txBuffer[txBuffer.size() - sizeof(tmpSz)], &tmpSz, sizeof(tmpSz)); 00374 00375 txBuffer += fullChannelName_; 00376 00377 txBuffer.push_back((unsigned char)sample_.size()); // size in bytes 00378 txBuffer.push_back((unsigned char)sizeOfDataTypeBits_); // size in bits 00379 00380 txBuffer += sample_; 00381 __COUT__ << "after txBuffer sz=" << txBuffer.size() << std::endl; 00382 00383 { // print 00384 __SS__ << "txBuffer: \n"; 00385 for(unsigned int i = 0; i < txBuffer.size(); ++i) 00386 { 00387 ss << std::hex << (int)((txBuffer[i] >> 4) & 0xF) 00388 << (int)((txBuffer[i]) & 0xF) << " " << std::dec; 00389 if(i % 8 == 7) 00390 ss << std::endl; 00391 } 00392 ss << std::endl; 00393 __COUT__ << "\n" << ss.str(); 00394 } 00395 } 00396 00397 // check alarms 00398 if(alarmsEnabled_) 00399 alarmMask = checkAlarms(txBuffer); 00400 00401 // create array helper for saving 00402 std::string* alarmValueArray[] = {&lolo_, &lo_, &hi_, &hihi_}; 00403 00407 if(fpAggregate) // aggregate file means saving enabled at FE level 00408 { 00409 // append to file 00410 if(aggregateIsBinaryFormat) 00411 { 00412 // save binary format: 00413 // 8B time (save any alarms by marking with time = 1, 2, 3, 4) 00414 // 4B sz of name 00415 // name 00416 // 1B sz of value in bytes 00417 // 1B sz of value in bits 00418 // value or alarm threshold 00419 00420 __COUT__ << "Aggregate Binary File Format: " << sizeof(lastSampleTime_) << " " 00421 << sample_.size() << std::endl; 00422 00423 { 00424 fwrite(&lastSampleTime_, 00425 sizeof(lastSampleTime_), 00426 1, 00427 fpAggregate); // 8B time 00428 00429 unsigned int tmpSz = fullChannelName_.size(); 00430 fwrite(&tmpSz, sizeof(tmpSz), 1, fpAggregate); // 4B sz of name 00431 fwrite(&fullChannelName_[0], 00432 fullChannelName_.size(), 00433 1, 00434 fpAggregate); // name 00435 00436 unsigned char tmpChar = (unsigned char)sample_.size(); 00437 fwrite(&tmpChar, 1, 1, fpAggregate); // size in bytes 00438 00439 tmpChar = (unsigned char)sizeOfDataTypeBits_; 00440 fwrite(&tmpChar, 1, 1, fpAggregate); // size in bits 00441 fwrite(&sample_[0], sample_.size(), 1, fpAggregate); // value 00442 } 00443 00444 // save any alarms by marking with time 1, 2, 3, 4 00445 if(alarmMask) // if any alarms 00446 for(time_t i = 1; i < 5; ++i, alarmMask >>= 1) 00447 if(alarmMask & 1) 00448 { 00449 { 00450 fwrite(&i, 00451 sizeof(lastSampleTime_), 00452 1, 00453 fpAggregate); // 8B save any alarms by marking with 00454 // time = 1, 2, 3, 4 00455 00456 unsigned int tmpSz = fullChannelName_.size(); 00457 fwrite( 00458 &tmpSz, sizeof(tmpSz), 1, fpAggregate); // 4B sz of name 00459 fwrite(&fullChannelName_[0], 00460 fullChannelName_.size(), 00461 1, 00462 fpAggregate); // name 00463 00464 unsigned char tmpChar = (unsigned char)sample_.size(); 00465 fwrite(&tmpChar, 1, 1, fpAggregate); // size in bytes 00466 00467 tmpChar = (unsigned char)sizeOfDataTypeBits_; 00468 fwrite(&tmpChar, 1, 1, fpAggregate); // size in bits 00469 fwrite(&(*alarmValueArray[i - 1])[0], 00470 (*alarmValueArray[i - 1]).size(), 00471 1, 00472 fpAggregate); // alarm threshold 00473 } 00474 } 00475 } 00476 else 00477 { 00478 // save text format: 00479 // timestamp (save any alarms by marking with time 1, 2, 3, 4) 00480 // name 00481 // value 00482 00483 __COUT__ << "Aggregate Text File Format: " << dataType_ << std::endl; 00484 00485 fprintf(fpAggregate, "%lu\n", lastSampleTime_); 00486 fprintf(fpAggregate, "%s\n", fullChannelName_.c_str()); 00487 00488 if(dataType_[dataType_.size() - 1] == 00489 'b') // if ends in 'b' then take that many bits 00490 { 00491 std::stringstream ss; 00492 ss << "0x"; 00493 for(unsigned int i = 0; i < sample_.size(); ++i) 00494 ss << std::hex << (int)((sample_[i] >> 4) & 0xF) 00495 << (int)((sample_[i]) & 0xF) << std::dec; 00496 fprintf(fpAggregate, "%s\n", ss.str().c_str()); 00497 } 00498 else if(dataType_ == "char") 00499 fprintf(fpAggregate, "%d\n", *((char*)(&sample_[0]))); 00500 else if(dataType_ == "unsigned char") 00501 fprintf(fpAggregate, "%u\n", *((unsigned char*)(&sample_[0]))); 00502 else if(dataType_ == "short") 00503 fprintf(fpAggregate, "%d\n", *((short*)(&sample_[0]))); 00504 else if(dataType_ == "unsigned short") 00505 fprintf(fpAggregate, "%u\n", *((unsigned short*)(&sample_[0]))); 00506 else if(dataType_ == "int") 00507 fprintf(fpAggregate, "%d\n", *((int*)(&sample_[0]))); 00508 else if(dataType_ == "unsigned int") 00509 fprintf(fpAggregate, "%u\n", *((unsigned int*)(&sample_[0]))); 00510 else if(dataType_ == "long long") 00511 fprintf(fpAggregate, "%lld\n", *((long long*)(&sample_[0]))); 00512 else if(dataType_ == "unsigned long long") 00513 fprintf(fpAggregate, "%llu\n", *((unsigned long long*)(&sample_[0]))); 00514 else if(dataType_ == "float") 00515 fprintf(fpAggregate, "%f\n", *((float*)(&sample_[0]))); 00516 else if(dataType_ == "double") 00517 fprintf(fpAggregate, "%f\n", *((double*)(&sample_[0]))); 00518 00519 // save any alarms by marking with time 1, 2, 3, 4 00520 if(alarmMask) // if any alarms 00521 { 00522 char checkMask = 1; // use mask to maintain alarm mask 00523 for(time_t i = 1; i < 5; ++i, checkMask <<= 1) 00524 if(alarmMask & checkMask) 00525 { 00526 fprintf(fpAggregate, "%lu\n", i); 00527 fprintf(fpAggregate, "%s\n", fullChannelName_.c_str()); 00528 00529 if(dataType_[dataType_.size() - 1] == 00530 'b') // if ends in 'b' then take that many bits 00531 { 00532 std::stringstream ss; 00533 ss << "0x"; 00534 for(unsigned int j = 0; j < (*alarmValueArray[i - 1]).size(); 00535 ++i) 00536 ss << std::hex 00537 << (int)(((*alarmValueArray[i - 1])[j] >> 4) & 0xF) 00538 << (int)(((*alarmValueArray[i - 1])[j]) & 0xF) 00539 << std::dec; 00540 fprintf(fpAggregate, "%s\n", ss.str().c_str()); 00541 } 00542 else if(dataType_ == "char") 00543 fprintf(fpAggregate, 00544 "%d\n", 00545 *((char*)(&(*alarmValueArray[i - 1])[0]))); 00546 else if(dataType_ == "unsigned char") 00547 fprintf(fpAggregate, 00548 "%u\n", 00549 *((unsigned char*)(&(*alarmValueArray[i - 1])[0]))); 00550 else if(dataType_ == "short") 00551 fprintf(fpAggregate, 00552 "%d\n", 00553 *((short*)(&(*alarmValueArray[i - 1])[0]))); 00554 else if(dataType_ == "unsigned short") 00555 fprintf(fpAggregate, 00556 "%u\n", 00557 *((unsigned short*)(&(*alarmValueArray[i - 1])[0]))); 00558 else if(dataType_ == "int") 00559 fprintf(fpAggregate, 00560 "%d\n", 00561 *((int*)(&(*alarmValueArray[i - 1])[0]))); 00562 else if(dataType_ == "unsigned int") 00563 fprintf(fpAggregate, 00564 "%u\n", 00565 *((unsigned int*)(&(*alarmValueArray[i - 1])[0]))); 00566 else if(dataType_ == "long long") 00567 fprintf(fpAggregate, 00568 "%lld\n", 00569 *((long long*)(&(*alarmValueArray[i - 1])[0]))); 00570 else if(dataType_ == "unsigned long long") 00571 fprintf( 00572 fpAggregate, 00573 "%llu\n", 00574 *((unsigned long long*)(&(*alarmValueArray[i - 1])[0]))); 00575 else if(dataType_ == "float") 00576 fprintf(fpAggregate, 00577 "%f\n", 00578 *((float*)(&(*alarmValueArray[i - 1])[0]))); 00579 else if(dataType_ == "double") 00580 fprintf(fpAggregate, 00581 "%f\n", 00582 *((double*)(&(*alarmValueArray[i - 1])[0]))); 00583 } 00584 } 00585 } 00586 } 00587 00591 if(saveEnabled_) 00592 { 00593 FILE* fp = fopen(saveFullFileName_.c_str(), saveBinaryFormat_ ? "ab" : "a"); 00594 if(!fp) 00595 { 00596 __COUT_ERR__ << "Failed to open slow controls channel file: " 00597 << saveFullFileName_ << std::endl; 00598 return; 00599 } 00600 00601 // append to file 00602 if(saveBinaryFormat_) 00603 { 00604 __COUT__ << "Binary File Format: " << sizeof(lastSampleTime_) << " " 00605 << sample_.size() << std::endl; 00606 fwrite(&lastSampleTime_, sizeof(lastSampleTime_), 1, fp); 00607 fwrite(&sample_[0], sample_.size(), 1, fp); 00608 00609 // save any alarms by marking with time 1, 2, 3, 4 00610 if(alarmMask) // if any alarms 00611 for(time_t i = 1; i < 5; ++i, alarmMask >>= 1) 00612 if(alarmMask & 1) 00613 { 00614 fwrite(&i, sizeof(lastSampleTime_), 1, fp); 00615 fwrite(&(*alarmValueArray[i - 1])[0], 00616 (*alarmValueArray[i - 1]).size(), 00617 1, 00618 fp); 00619 } 00620 } 00621 else 00622 { 00623 __COUT__ << "Text File Format: " << dataType_ << std::endl; 00624 00625 fprintf(fp, "%lu\n", lastSampleTime_); 00626 00627 if(dataType_[dataType_.size() - 1] == 00628 'b') // if ends in 'b' then take that many bits 00629 { 00630 std::stringstream ss; 00631 ss << "0x"; 00632 for(unsigned int i = 0; i < sample_.size(); ++i) 00633 ss << std::hex << (int)((sample_[i] >> 4) & 0xF) 00634 << (int)((sample_[i]) & 0xF) << std::dec; 00635 fprintf(fp, "%s\n", ss.str().c_str()); 00636 } 00637 else if(dataType_ == "char") 00638 fprintf(fp, "%d\n", *((char*)(&sample_[0]))); 00639 else if(dataType_ == "unsigned char") 00640 fprintf(fp, "%u\n", *((unsigned char*)(&sample_[0]))); 00641 else if(dataType_ == "short") 00642 fprintf(fp, "%d\n", *((short*)(&sample_[0]))); 00643 else if(dataType_ == "unsigned short") 00644 fprintf(fp, "%u\n", *((unsigned short*)(&sample_[0]))); 00645 else if(dataType_ == "int") 00646 fprintf(fp, "%d\n", *((int*)(&sample_[0]))); 00647 else if(dataType_ == "unsigned int") 00648 fprintf(fp, "%u\n", *((unsigned int*)(&sample_[0]))); 00649 else if(dataType_ == "long long") 00650 fprintf(fp, "%lld\n", *((long long*)(&sample_[0]))); 00651 else if(dataType_ == "unsigned long long") 00652 fprintf(fp, "%llu\n", *((unsigned long long*)(&sample_[0]))); 00653 else if(dataType_ == "float") 00654 fprintf(fp, "%f\n", *((float*)(&sample_[0]))); 00655 else if(dataType_ == "double") 00656 fprintf(fp, "%f\n", *((double*)(&sample_[0]))); 00657 00658 // save any alarms by marking with time 1, 2, 3, 4 00659 if(alarmMask) // if any alarms 00660 { 00661 char checkMask = 1; // use mask to maintain alarm mask 00662 for(time_t i = 1; i < 5; ++i, checkMask <<= 1) 00663 if(alarmMask & checkMask) 00664 { 00665 fprintf(fp, "%lu\n", i); 00666 00667 if(dataType_[dataType_.size() - 1] == 00668 'b') // if ends in 'b' then take that many bits 00669 { 00670 std::stringstream ss; 00671 ss << "0x"; 00672 for(unsigned int j = 0; j < (*alarmValueArray[i - 1]).size(); 00673 ++i) 00674 ss << std::hex 00675 << (int)(((*alarmValueArray[i - 1])[j] >> 4) & 0xF) 00676 << (int)(((*alarmValueArray[i - 1])[j]) & 0xF) 00677 << std::dec; 00678 fprintf(fp, "%s\n", ss.str().c_str()); 00679 } 00680 else if(dataType_ == "char") 00681 fprintf( 00682 fp, "%d\n", *((char*)(&(*alarmValueArray[i - 1])[0]))); 00683 else if(dataType_ == "unsigned char") 00684 fprintf(fp, 00685 "%u\n", 00686 *((unsigned char*)(&(*alarmValueArray[i - 1])[0]))); 00687 else if(dataType_ == "short") 00688 fprintf( 00689 fp, "%d\n", *((short*)(&(*alarmValueArray[i - 1])[0]))); 00690 else if(dataType_ == "unsigned short") 00691 fprintf(fp, 00692 "%u\n", 00693 *((unsigned short*)(&(*alarmValueArray[i - 1])[0]))); 00694 else if(dataType_ == "int") 00695 fprintf(fp, "%d\n", *((int*)(&(*alarmValueArray[i - 1])[0]))); 00696 else if(dataType_ == "unsigned int") 00697 fprintf(fp, 00698 "%u\n", 00699 *((unsigned int*)(&(*alarmValueArray[i - 1])[0]))); 00700 else if(dataType_ == "long long") 00701 fprintf(fp, 00702 "%lld\n", 00703 *((long long*)(&(*alarmValueArray[i - 1])[0]))); 00704 else if(dataType_ == "unsigned long long") 00705 fprintf( 00706 fp, 00707 "%llu\n", 00708 *((unsigned long long*)(&(*alarmValueArray[i - 1])[0]))); 00709 else if(dataType_ == "float") 00710 fprintf( 00711 fp, "%f\n", *((float*)(&(*alarmValueArray[i - 1])[0]))); 00712 else if(dataType_ == "double") 00713 fprintf( 00714 fp, "%f\n", *((double*)(&(*alarmValueArray[i - 1])[0]))); 00715 } 00716 } 00717 } 00718 00719 fclose(fp); 00720 } 00721 } 00722 00723 //======================================================================================================================== 00724 // extractSample 00725 // extract sample from universalReadValue 00726 // considering bit size and offset 00727 void FESlowControlsChannel::extractSample(const std::string& universalReadValue) 00728 { 00729 // procedure: 00730 00731 { // print 00732 __SS__ << "Univ Read: "; 00733 for(unsigned int i = 0; i < universalReadValue.size(); ++i) 00734 ss << std::hex << (int)((universalReadValue[i] >> 4) & 0xF) 00735 << (int)((universalReadValue[i]) & 0xF) << " " << std::dec; 00736 ss << std::endl; 00737 __COUT__ << "\n" << ss.str(); 00738 } 00739 00740 unsigned int byteOffset = universalDataBitOffset_ / 8; 00741 unsigned int bitOffset = universalDataBitOffset_ % 8; 00742 unsigned int bitsLeft = sizeOfDataTypeBits_; 00743 00744 // copy to tmp (assume sample max size is 64 bits) 00745 unsigned long long tmp = 0; 00746 00747 if(bitOffset) // copy first partial byte 00748 { 00749 // __COUT__ << "bitsLeft=" << bitsLeft << 00750 // " byteOffset=" << byteOffset << 00751 // " bitOffset=" << bitOffset << 00752 // std::endl; 00753 00754 tmp = ((unsigned long long)(universalReadValue[byteOffset++])) >> bitOffset; 00755 bitsLeft = 8 - bitOffset; 00756 00757 // { //print 00758 // __SS__ << "Tmp: "; 00759 // for(unsigned int i=0; i<sizeof(tmp); ++i) 00760 // ss << std::hex << (int)((((char *)&tmp)[i]>>4)&0xF) << 00761 // (int)((((char *)&tmp)[i])&0xF) << " " << std::dec; 00762 // ss << std::endl; 00763 // __COUT__ << "\n" << ss.str(); 00764 // } 00765 } 00766 00767 while(bitsLeft > 7) // copy whole bytes 00768 { 00769 // __COUT__ << "bitsLeft=" << bitsLeft << 00770 // " byteOffset=" << byteOffset << 00771 // " bitOffset=" << bitOffset << 00772 // std::endl; 00773 00774 tmp |= ((unsigned long long)(universalReadValue[byteOffset++])) 00775 << (sizeOfDataTypeBits_ - bitsLeft); 00776 bitsLeft -= 8; 00777 00778 // { //print 00779 // __SS__ << "Tmp: "; 00780 // for(unsigned int i=0; i<sizeof(tmp); ++i) 00781 // ss << std::hex << (int)((((char *)&tmp)[i]>>4)&0xF) << 00782 // (int)((((char *)&tmp)[i])&0xF) << " " << std::dec; 00783 // ss << std::endl; 00784 // __COUT__ << "\n" << ss.str(); 00785 // } 00786 } 00787 00788 if(bitOffset) // copy last partial byte 00789 { 00790 // __COUT__ << "bitsLeft=" << bitsLeft << 00791 // " byteOffset=" << byteOffset << 00792 // " bitOffset=" << bitOffset << 00793 // std::endl; 00794 00795 tmp |= (((unsigned long long)(universalReadValue[byteOffset])) & 00796 (0xFF >> (8 - bitsLeft))) 00797 << (sizeOfDataTypeBits_ - bitsLeft); 00798 00799 // { //print 00800 // __SS__ << "Tmp: "; 00801 // for(unsigned int i=0; i<sizeof(tmp); ++i) 00802 // ss << std::hex << (int)((((char *)&tmp)[i]>>4)&0xF) << 00803 // (int)((((char *)&tmp)[i])&0xF) << " " << std::dec; 00804 // ss << std::endl; 00805 // __COUT__ << "\n" << ss.str(); 00806 // } 00807 } 00808 00809 __COUT__ << "Temp Long Long Sample: " << tmp << std::endl; 00810 00811 sample_.resize(0); // clear a la sample_ = ""; 00812 for(unsigned int i = 0; 00813 i < (sizeOfDataTypeBits_ / 8 + ((universalDataBitOffset_ % 8) ? 1 : 0)); 00814 ++i) 00815 sample_.push_back(((char*)&tmp)[i]); 00816 00817 __COUT__ << "sample_.size()= " << sample_.size() << std::endl; 00818 00819 { // print 00820 __SS__ << "Sample: "; 00821 for(unsigned int i = 0; i < sample_.size(); ++i) 00822 ss << std::hex << (int)((sample_[i] >> 4) & 0xF) << (int)((sample_[i]) & 0xF) 00823 << " " << std::dec; 00824 ss << std::endl; 00825 __COUT__ << "\n" << ss.str(); 00826 } 00827 } 00828 00829 //======================================================================================================================== 00830 // clearAlarms 00831 // clear target alarm 00832 // if -1 clear all 00833 void FESlowControlsChannel::clearAlarms(int targetAlarm) 00834 { 00835 if(targetAlarm == -1 || targetAlarm == 0) 00836 loloAlarmed_ = false; 00837 if(targetAlarm == -1 || targetAlarm == 1) 00838 loAlarmed_ = false; 00839 if(targetAlarm == -1 || targetAlarm == 2) 00840 hiAlarmed_ = false; 00841 if(targetAlarm == -1 || targetAlarm == 3) 00842 hihiAlarmed_ = false; 00843 } 00844 00845 //======================================================================================================================== 00846 // checkAlarms 00847 // if current value is a new alarm, set alarmed and add alarm packet to buffer 00848 // 00849 // return mask of alarms that fired during this check. 00850 char FESlowControlsChannel::checkAlarms(std::string& txBuffer) 00851 { 00852 // procedure: 00853 // for each alarm type 00854 // determine type and get value as proper type 00855 // i.e.: 00856 // 0 -- unsigned long long 00857 // 1 -- long long 00858 // 2 -- float 00859 // 3 -- double 00860 // do comparison with the type 00861 // alarm alarms 00862 00863 int useType = -1; 00864 char createPacketMask = 0; 00865 00866 if(dataType_[dataType_.size() - 1] == 'b') // if ends in 'b' then take that many bits 00867 useType = 0; 00868 else if(dataType_ == "char") 00869 useType = 1; 00870 else if(dataType_ == "unsigned char") 00871 useType = 0; 00872 else if(dataType_ == "short") 00873 useType = 1; 00874 else if(dataType_ == "unsigned short") 00875 useType = 0; 00876 else if(dataType_ == "int") 00877 useType = 1; 00878 else if(dataType_ == "unsigned int") 00879 useType = 0; 00880 else if(dataType_ == "long long") 00881 useType = 1; 00882 else if(dataType_ == "unsigned long long") 00883 useType = 0; 00884 else if(dataType_ == "float") 00885 useType = 2; 00886 else if(dataType_ == "double") 00887 useType = 3; 00888 00889 if(useType == 0) // unsigned long long 00890 { 00891 __COUT__ << "Using unsigned long long for alarms." << std::endl; 00892 // lolo 00893 if((!loloAlarmed_ || !latchAlarms_) && 00894 *((unsigned long long*)&sample_[0]) <= *((unsigned long long*)&lolo_[0])) 00895 { 00896 loloAlarmed_ = true; 00897 createPacketMask |= 1 << 0; 00898 } 00899 // lo 00900 if((!loAlarmed_ || !latchAlarms_) && 00901 *((unsigned long long*)&sample_[0]) <= *((unsigned long long*)&lo_[0])) 00902 { 00903 loAlarmed_ = true; 00904 createPacketMask |= 1 << 1; 00905 } 00906 // hi 00907 if((!hiAlarmed_ || !latchAlarms_) && 00908 *((unsigned long long*)&sample_[0]) >= *((unsigned long long*)&hi_[0])) 00909 { 00910 hiAlarmed_ = true; 00911 createPacketMask |= 1 << 2; 00912 } 00913 // hihi 00914 if((!hihiAlarmed_ || !latchAlarms_) && 00915 *((unsigned long long*)&sample_[0]) >= *((unsigned long long*)&hihi_[0])) 00916 { 00917 hihiAlarmed_ = true; 00918 createPacketMask |= 1 << 3; 00919 } 00920 } 00921 else if(useType == 1) // long long 00922 { 00923 __COUT__ << "Using long long for alarms." << std::endl; 00924 // lolo 00925 if((!loloAlarmed_ || !latchAlarms_) && 00926 *((long long*)&sample_[0]) <= *((long long*)&lolo_[0])) 00927 { 00928 loloAlarmed_ = true; 00929 createPacketMask |= 1 << 0; 00930 } 00931 // lo 00932 if((!loAlarmed_ || !latchAlarms_) && 00933 *((long long*)&sample_[0]) <= *((long long*)&lo_[0])) 00934 { 00935 loAlarmed_ = true; 00936 createPacketMask |= 1 << 1; 00937 } 00938 // hi 00939 if((!hiAlarmed_ || !latchAlarms_) && 00940 *((long long*)&sample_[0]) >= *((long long*)&hi_[0])) 00941 { 00942 hiAlarmed_ = true; 00943 createPacketMask |= 1 << 2; 00944 } 00945 // hihi 00946 if((!hihiAlarmed_ || !latchAlarms_) && 00947 *((long long*)&sample_[0]) >= *((long long*)&hihi_[0])) 00948 { 00949 hihiAlarmed_ = true; 00950 createPacketMask |= 1 << 3; 00951 } 00952 } 00953 else if(useType == 2) // float 00954 { 00955 __COUT__ << "Using float for alarms." << std::endl; 00956 // lolo 00957 if((!loloAlarmed_ || !latchAlarms_) && 00958 *((float*)&sample_[0]) <= *((float*)&lolo_[0])) 00959 { 00960 loloAlarmed_ = true; 00961 createPacketMask |= 1 << 0; 00962 } 00963 // lo 00964 if((!loAlarmed_ || !latchAlarms_) && *((float*)&sample_[0]) <= *((float*)&lo_[0])) 00965 { 00966 loAlarmed_ = true; 00967 createPacketMask |= 1 << 1; 00968 } 00969 // hi 00970 if((!hiAlarmed_ || !latchAlarms_) && *((float*)&sample_[0]) >= *((float*)&hi_[0])) 00971 { 00972 hiAlarmed_ = true; 00973 createPacketMask |= 1 << 2; 00974 } 00975 // hihi 00976 if((!hihiAlarmed_ || !latchAlarms_) && 00977 *((float*)&sample_[0]) >= *((float*)&hihi_[0])) 00978 { 00979 hihiAlarmed_ = true; 00980 createPacketMask |= 1 << 3; 00981 } 00982 } 00983 else if(useType == 3) // double 00984 { 00985 __COUT__ << "Using double for alarms." << std::endl; 00986 // lolo 00987 if((!loloAlarmed_ || !latchAlarms_) && 00988 *((double*)&sample_[0]) <= *((double*)&lolo_[0])) 00989 { 00990 loloAlarmed_ = true; 00991 createPacketMask |= 1 << 0; 00992 } 00993 // lo 00994 if((!loAlarmed_ || !latchAlarms_) && 00995 *((double*)&sample_[0]) <= *((double*)&lo_[0])) 00996 { 00997 loAlarmed_ = true; 00998 createPacketMask |= 1 << 1; 00999 } 01000 // hi 01001 if((!hiAlarmed_ || !latchAlarms_) && 01002 *((double*)&sample_[0]) >= *((double*)&hi_[0])) 01003 { 01004 hiAlarmed_ = true; 01005 createPacketMask |= 1 << 2; 01006 } 01007 // hihi 01008 if((!hihiAlarmed_ || !latchAlarms_) && 01009 *((double*)&sample_[0]) >= *((double*)&hihi_[0])) 01010 { 01011 hihiAlarmed_ = true; 01012 createPacketMask |= 1 << 3; 01013 } 01014 } 01015 01016 // create array helper for packet gen 01017 std::string* alarmValueArray[] = {&lolo_, &lo_, &hi_, &hihi_}; 01018 01019 if(monitoringEnabled_) // only create packet if monitoring 01020 { 01021 // create a packet for each bit in mask 01022 char checkMask = 1; // use mask to maintain return mask 01023 for(int i = 0; i < 4; ++i, checkMask <<= 1) 01024 if(createPacketMask & checkMask) 01025 { 01026 // create alarm packet: 01027 // 1B type (0: value, 1: loloalarm, 2: loalarm, 3: hioalarm, 4: 01028 // hihialarm) 01029 // 1B sequence count from channel 01030 // 8B time 01031 // 4B sz of name 01032 // name 01033 // 1B sz of alarm value in bytes 01034 // 1B sz of alarm value in bits 01035 // alarm value 01036 01037 __COUT__ << "Create packet type " << i + 1 01038 << " alarm value = " << *alarmValueArray[i] << std::endl; 01039 01040 __COUT__ << "before txBuffer sz=" << txBuffer.size() << std::endl; 01041 txBuffer.push_back(i + 1); // alarm packet type 01042 txBuffer.push_back( 01043 txPacketSequenceNumber_++); // sequence counter and increment 01044 01045 txBuffer.resize(txBuffer.size() + sizeof(lastSampleTime_)); 01046 memcpy(&txBuffer[txBuffer.size() - sizeof(lastSampleTime_)], 01047 &lastSampleTime_, 01048 sizeof(lastSampleTime_)); 01049 01050 unsigned int tmpSz = fullChannelName_.size(); 01051 01052 txBuffer.resize(txBuffer.size() + sizeof(tmpSz)); 01053 memcpy(&txBuffer[txBuffer.size() - sizeof(tmpSz)], &tmpSz, sizeof(tmpSz)); 01054 01055 txBuffer += fullChannelName_; 01056 01057 txBuffer.push_back( 01058 (unsigned char)(*alarmValueArray[i]).size()); // size in bytes 01059 txBuffer.push_back((unsigned char)sizeOfDataTypeBits_); // size in bits 01060 01061 txBuffer += (*alarmValueArray[i]); 01062 __COUT__ << "after txBuffer sz=" << txBuffer.size() << std::endl; 01063 01064 { // print 01065 __SS__ << "txBuffer: \n"; 01066 for(unsigned int i = 0; i < txBuffer.size(); ++i) 01067 { 01068 ss << std::hex << (int)((txBuffer[i] >> 4) & 0xF) 01069 << (int)((txBuffer[i]) & 0xF) << " " << std::dec; 01070 if(i % 8 == 7) 01071 ss << std::endl; 01072 } 01073 ss << std::endl; 01074 __COUT__ << "\n" << ss.str(); 01075 } 01076 } 01077 } 01078 01079 return createPacketMask; 01080 }