- Timestamp:
- 02/04/10 15:26:55 (15 years ago)
- Location:
- Evidence
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
Evidence/Alarm.cc
r154 r159 109 109 110 110 // Update State: unavailable or current severity of status 111 if (getInfo()->getSize()==strlen(NO_LINK)+1 && 112 strcmp(getInfo()->getString(), NO_LINK)==0) State[i] = 4; 111 if (!ServiceOK(getInfo())) State[i] = 4; 113 112 else { 114 113 State[i] = *(getInfo()->getString()+getInfo()->getSize()-1); 115 114 116 printf("*** String length: %d Message length: %d Last number: %d\n",strlen(getInfo()->getString()),getInfo()->getSize(),State[i]);117 115 // Print message 118 116 time_t RawTime = getInfo()->getTimestamp(); -
Evidence/DColl.cc
r152 r159 38 38 #include <regex.h> 39 39 40 using namespace std; 41 40 42 // 41 43 // Class declaration … … 47 49 DimStampedInfo *DataItem; 48 50 DimService *HistService; 49 struct EvidenceHistoryItem *HistBuffer;50 int HistPointer;51 char *Buffer; 52 int Next; 51 53 double LastValue; 52 54 double MinAbsChange; … … 101 103 // Request configuration data 102 104 char *Change = GetConfig(SERVER_NAME " minchange"); 103 104 105 DataDir = GetConfig(SERVER_NAME " datadir"); 105 106 106 char *Logname = GetConfig(SERVER_NAME " logfile"); 107 108 107 SizeUpdateDelay = atoi(GetConfig(SERVER_NAME " sizeupdate")); 109 110 108 HistSize = atoi(GetConfig(SERVER_NAME " histsize")); 111 if (HistSize < 1) HistSize = 1; // Minimum one items 112 109 if (HistSize < 3*sizeof(int)) HistSize = 3*sizeof(int); 113 110 HistDir = GetConfig(SERVER_NAME " histdir"); 114 111 … … 163 160 // Subscribe to list of servers at DIS_DNS 164 161 AddService("DIS_DNS/SERVER_LIST"); 165 166 DimClient::sendCommand("DColl/Log", SERVER_NAME" *** Logging started ***");167 162 } 168 163 … … 171 166 // 172 167 DataHandler::~DataHandler() { 173 174 DimClient::sendCommand("DColl/Log", SERVER_NAME" *** Logging stopped ***");175 168 176 169 // Delete DIM subscriptions and command first so handlers and not called anymore … … 179 172 } 180 173 delete LogCommand; 181 174 182 175 // Save history buffers to files (replace '/' by '_') 176 State(INFO, "Writing history buffers to files"); 177 183 178 for (int i=0; i<List.size(); i++) { 184 179 string Name = List[i].HistService->getName(); … … 186 181 FILE *File = fopen((HistDir + "/" + Name).c_str(), "wb"); 187 182 if (File != NULL) { 188 fwrite(&List[i]. HistPointer, sizeof(List[i].HistPointer), 1, File);189 fwrite(List[i]. HistBuffer, sizeof(EvidenceHistoryItem), HistSize, File);183 fwrite(&List[i].Next, sizeof(List[i].Next), 1, File); 184 fwrite(List[i].Buffer, sizeof(char), HistSize, File); 190 185 fclose(File); 191 186 } 192 187 delete List[i].HistService; 193 delete[] List[i]. HistBuffer;188 delete[] List[i].Buffer; 194 189 } 195 190 … … 223 218 void DataHandler::infoHandler() { 224 219 220 static const int WrapMark[] = {0, -1}; 221 static const int EndMark[] = {0, 0}; 222 225 223 DimInfo *Info = getInfo(); 226 224 227 225 // Check if service available 228 if (Info->getSize()==strlen(NO_LINK)+1 && strcmp(Info->getString(), NO_LINK)==0) return; 229 226 if (!ServiceOK(Info)) return; 227 228 // 229 // ====== Part A: Handle service subscriptions === 230 // 231 230 232 // If service is DIS_DNS/SERVER_LIST, subscribe to all SERVICE_LIST services 231 233 if (strcmp(Info->getName(), "DIS_DNS/SERVER_LIST") == 0) { … … 259 261 } 260 262 263 // 264 // ====== Part B: Handle opening data files === 265 // 266 261 267 // If it is time to open new data file, close the current one 262 268 if (time(NULL) >= TimeForNextFile) { … … 296 302 TimeForNextFile = mktime(T); 297 303 } 298 304 305 // 306 // ====== Part C: Handle writing to data file === 307 // 308 299 309 // Identify index of service 300 int Service; 310 int Service; 301 311 for (Service=0; Service<List.size(); Service++) if (Info == List[Service].DataItem) break; 302 312 if (Service == List.size()) return; // Service not found 303 313 304 // If negative value for absolute change, ignore this entry305 if (List[Service].MinAbsChange < 0) return;314 // If negative value for absolute change, do not write to file 315 if (List[Service].MinAbsChange >= 0) { 306 316 307 317 // Write data header … … 313 323 // Translate data into ASCII 314 324 char *Text = EvidenceServer::ToString(Info); 325 315 326 if (Text != NULL) { 316 327 // Replace all control characters by white space … … 320 331 fprintf(DataFile, "%s\n", Text); 321 332 322 // Add to history buffer if change large enough323 if ((fabs(atof(Text)-List[Service].LastValue) > List[Service].MinAbsChange)) {324 List[Service].HistBuffer[List[Service].HistPointer].Seconds = Info->getTimestamp();325 List[Service].HistBuffer[List[Service].HistPointer].Value = atof(Text);326 List[Service].HistService->updateService();327 List[Service].HistPointer++;328 if (List[Service].HistPointer >= HistSize) List[Service].HistPointer = 0;329 List[Service].LastValue = atof(Text);330 }331 333 free(Text); 332 334 } 333 335 else fprintf(DataFile, "Cannot interpret format identifier\n"); 334 336 335 fflush(DataFile);336 337 337 // Terminate if error because otherwise infinite loop might result as 338 338 // next call to this infoHandler() will try to (re-)open file … … 343 343 } 344 344 345 // Update datafile size service 345 // Update datafile size service (not every time to avoid infinite loop) 346 346 if (time(NULL) - DataSizeLastUpdate > SizeUpdateDelay) { 347 fflush(DataFile); // not continuously to reduce load 348 347 349 DataSizekB = FileSize(DataFile); 348 350 DataSizeService->updateService(); 349 351 DataSizeLastUpdate = time(NULL); 350 352 } 353 354 } // Check for MinAbsChange 355 356 // 357 // ====== Part D: Handle history service === 358 // 359 360 if (Info->getSize() == 0) return; 361 362 // Check if data should be added to history buffer 363 char *Text = EvidenceServer::ToString(Info); 364 if (Text != NULL && strcmp(Info->getFormat(),"C") != 0 365 && fabs(atof(Text)-List[Service].LastValue) < fabs(List[Service].MinAbsChange)) { 366 free(Text); 367 return; 368 } 369 free(Text); 370 371 // Check if data fits into buffer 372 if (HistSize < Info->getSize() + 5*sizeof(int)) return; 373 374 int Size = Info->getSize() + 4*sizeof(int), Next = List[Service].Next; 375 void *WrapPos = NULL; 376 char *Buffer = List[Service].Buffer; 377 int Oldest = *(int *) Buffer; 378 379 // Check if buffer wrap-around (write wrap mark after Oldest is adjusted) 380 if (Next + Size >= HistSize) { 381 WrapPos = Buffer + Next; 382 Next = 4; 383 } 384 385 // Adapt pointer to oldest entry 386 while ((Oldest < Next + Size) && 387 (Oldest + *((int *) (Buffer + Oldest) + 1) + 2*sizeof(int) > Next)) { 388 // Check for wrap-around 389 if (memcmp(Buffer + Oldest, WrapMark, sizeof(WrapMark)) == 0) { 390 Oldest = 4; 391 continue; 392 } 393 // Check if end marker reached, then only one event fits buffer 394 if (memcmp(Buffer + Oldest, EndMark, sizeof(EndMark)) == 0) { 395 Oldest = Next; 396 break; 397 } 398 // Move to next entry 399 Oldest += *((int *) (Buffer + Oldest) + 1) + 2*sizeof(int); 400 } 401 // Update pointer in buffer 402 *(int *) Buffer = Oldest; 403 404 // Write wrap mark if necessary 405 if (WrapPos != NULL) memcpy(WrapPos, WrapMark, sizeof(WrapMark)); 406 407 // Copy data into ring buffer 408 *((int *) (Buffer + Next)) = Info->getTimestamp(); 409 *((int *) (Buffer + Next + sizeof(int))) = Info->getSize(); 410 memcpy(Buffer + Next + 2*sizeof(int), Info->getData(), Info->getSize()); 411 412 // Adjust pointer for next entry and write end marker to buffer 413 Next += Info->getSize() + 2*sizeof(int); 414 memcpy(Buffer + Next, EndMark, sizeof(EndMark)); 415 416 List[Service].Next = Next; 351 417 } 352 418 … … 403 469 } 404 470 405 // Create new entry in item list406 471 struct Item New; 407 472 … … 413 478 } 414 479 } 415 480 416 481 // Create history service 417 New.HistBuffer = new struct EvidenceHistoryItem [HistSize]; 418 memset(New.HistBuffer, 0, HistSize*sizeof(EvidenceHistoryItem)); 419 New.HistPointer = 0; 482 New.Buffer = new char [HistSize]; 483 memset(New.Buffer, 0, HistSize); 484 *(int *) New.Buffer = 4; 485 New.Next = 4; 420 486 New.LastValue = DBL_MAX; 421 487 New.HistService = new DimService ((Name+".hist").c_str(), (char *) "C", 422 New. HistBuffer, HistSize*sizeof(EvidenceHistoryItem));423 488 New.Buffer, HistSize); 489 424 490 // Load history buffer from file if existing 425 491 string Filename = New.HistService->getName(); … … 427 493 FILE *File = fopen((HistDir + "/" + Filename).c_str(), "rb"); 428 494 if (File != NULL) { 429 fread(&New.HistPointer, sizeof(New.HistPointer), 1, File); 430 fread(New.HistBuffer, sizeof(EvidenceHistoryItem), HistSize, File); 431 fclose(File); 495 // Only load if current buffer size if equal or larger 496 if (FileSize(File) <= HistSize*sizeof(char)+sizeof(New.Next) && FileSize(File) != -1) { 497 fread(&New.Next, sizeof(New.Next), 1, File); 498 fread(New.Buffer, sizeof(char), HistSize, File); 499 fclose(File); 500 } 432 501 } 433 502 -
Evidence/Edd/Edd.cc
r154 r159 9 9 a DIM status service 10 10 11 December 2009, Oliver Grimm11 February 2010, Oliver Grimm 12 12 13 13 ============================================================ */ … … 35 35 36 36 // Connect to DIM handler 37 if (connect(Handler, SIGNAL(YEP(DimInfo*, int, Q String, QByteArray, QString)), SLOT(Update(DimInfo*, int, QString, QByteArray, QString))) == false) {37 if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QByteArray, QString)), SLOT(Update(DimInfo*, int, QByteArray, QString))) == false) { 38 38 printf("Failed connection for %s\n", DIMService.toAscii().data()); 39 39 } … … 43 43 Menu->addAction("Open history", this, SLOT(MenuOpenHistory())); 44 44 Menu->addAction("Copy service", this, SLOT(MenuCopyService())); 45 Menu->addAction("Copy data", this, SLOT(MenuCopyData())); 45 46 46 47 // DIM client 47 Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, (char *)NO_LINK, Handler);48 Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, NO_LINK, Handler); 48 49 } 49 50 … … 54 55 55 56 // Update widget 56 void Edd_Indicator::Update(DimInfo *Info, int Time, Q String Format, QByteArray Data, QString Text) {57 58 if (Info != this->Data) return;57 void Edd_Indicator::Update(DimInfo *Info, int Time, QByteArray Array, QString Text) { 58 59 if (Info != Data) return; 59 60 60 61 QPalette Pal = palette(); … … 67 68 } 68 69 else { 69 // If this is a status indicator, adapt background colour 70 if (Data.size() == Text.size()+2) { 71 switch (Data[Text.size() + 1]) { 72 case 0: Pal.setColor(QPalette::Base, Qt::white); break; 73 case 1: Pal.setColor(QPalette::Base, Qt::yellow); break; 74 case 2: Pal.setColor(QPalette::Base, Qt::red); break; 75 case 3: Pal.setColor(QPalette::Base, Qt::red); break; 76 default: break; 77 } 70 // Backgound colour determined by last byte 71 switch (Array[Array.size()]) { 72 case 0: Pal.setColor(QPalette::Base, Qt::white); break; 73 case 1: Pal.setColor(QPalette::Base, Qt::yellow); break; 74 case 2: Pal.setColor(QPalette::Base, Qt::red); break; 75 case 3: Pal.setColor(QPalette::Base, Qt::red); break; 76 default: break; 78 77 } 79 else Pal.setColor(QPalette::Base, Qt::white);80 78 81 79 if (!ShowAsTime) setText(Text); … … 83 81 84 82 // Update status tip 85 setStatusTip(QString("%1: Last update %2 Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg( Format));83 setStatusTip(QString("%1: Last update %2 Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg(Info->getFormat())); 86 84 } 87 85 … … 134 132 } 135 133 136 // Open history plot134 // Menu: Open history plot 137 135 void Edd_Indicator::MenuOpenHistory() { 138 136 … … 141 139 } 142 140 143 // Copy service name141 // Menu: Copy service name 144 142 void Edd_Indicator::MenuCopyService() { 145 143 146 144 QApplication::clipboard()->setText(QString(Data->getName())); 145 } 146 147 // Menu: Copy data 148 void Edd_Indicator::MenuCopyData() { 149 150 QApplication::clipboard()->setText(text()); 147 151 } 148 152 … … 154 158 // Constructor 155 159 // 156 Edd_Plot::Edd_Plot(QString DIMService, QWidget *P): QwtPlot(P) {160 Edd_Plot::Edd_Plot(QString DIMService, QWidget *P): QwtPlot(P), EvidenceHistory() { 157 161 158 162 setAcceptDrops(true); … … 180 184 181 185 // Connect to DIM handler 182 if (connect(Handler, SIGNAL(YEP(DimInfo *, int, Q String, QByteArray, QString)), SLOT(Update(DimInfo *, int, QString, QByteArray, QString))) == false) {186 if (connect(Handler, SIGNAL(YEP(DimInfo *, int, QByteArray, QString)), SLOT(Update(DimInfo *, int, QByteArray, QString))) == false) { 183 187 printf("Failed connection for %s\n", DIMService.toAscii().data()); 184 188 } … … 211 215 212 216 for (int i=0; i<Items.size(); i++) { 213 delete Items[i].Data;214 217 delete Items[i].LiveData; 215 218 delete Items[i].Signal; 216 delete[] Items[i].x;217 delete[] Items[i].y;218 219 } 219 220 delete Grid; … … 225 226 void Edd_Plot::AddService(QString Name) { 226 227 227 QString HistName = Name+".hist";228 229 228 // Lock before accessing Items list 230 229 QMutexLocker Locker(&Mutex); 231 230 232 // Check if already subs ribed to service231 // Check if already subscribed to service 233 232 for (int i=0; i<Items.size(); i++) { 234 if ( HistName == Items[i].Data->getName()) {235 QMessageBox::warning(this, "Edd Message", HistName+"already present",QMessageBox::Ok);233 if (Name == Items[i].LiveData->getName()) { 234 QMessageBox::warning(this, "Edd Message",Name+".hist already present",QMessageBox::Ok); 236 235 return; 237 236 } … … 242 241 New.Signal = new QwtPlotCurve; 243 242 New.Signal->attach(this); 244 New.Signal->setTitle( HistName);243 New.Signal->setTitle(Name+".hist"); 245 244 New.Signal->setPen(QColor(LineColors[Items.size() % (sizeof(LineColors)/sizeof(Qt::GlobalColor))])); 246 New.x = NULL; 247 New.y = NULL; 248 New.Count = 0; 249 New.Data = new DimStampedInfo(HistName.toAscii().data(), (char *) NO_LINK, Handler); 250 New.LiveData = new DimStampedInfo(Name.toAscii().data(), (char *) NO_LINK, Handler); 245 New.SizeLimit = 5000; 246 New.LiveData = new DimStampedInfo(Name.toAscii().data(), NO_LINK, Handler); 251 247 252 248 Items.append(New); … … 254 250 255 251 // Update widget (must happen in GUI thread) 256 void Edd_Plot::Update(DimInfo *Info, int Time, Q String Format, QByteArray Data, QString Text) {252 void Edd_Plot::Update(DimInfo *Info, int Time, QByteArray, QString Text) { 257 253 258 254 // Check if service available … … 266 262 // Determine which plot item this call belongs to 267 263 int ItemNo; 268 for (ItemNo=0; ItemNo<Items.size(); ItemNo++) if (Info == Items[ItemNo].Data) { 269 // This is a history service 270 EvidenceHistoryItem *Curr = (EvidenceHistoryItem *) Data.data(); 271 int Count=0, DataPoints = Data.size()/sizeof(struct EvidenceHistoryItem); 272 273 delete[] Items[ItemNo].x; 274 delete[] Items[ItemNo].y; 275 Items[ItemNo].x = new int [DataPoints]; 276 Items[ItemNo].y = new double [DataPoints]; 277 278 // Find oldest item 279 int Oldest; 280 for (Oldest=1; Oldest<DataPoints; Oldest++) { 281 if (Curr[Oldest].Seconds < Curr[Oldest-1].Seconds) break; 264 for (ItemNo=0; ItemNo<Items.size(); ItemNo++) if (Info == Items[ItemNo].LiveData) { 265 266 // If size limit reached, clear buffer 267 if (Items[ItemNo].x.size() > Items[ItemNo].SizeLimit) { 268 Items[ItemNo].x.clear(); 269 Items[ItemNo].y.clear(); 282 270 } 283 271 284 // Plot data starting with oldest value 285 for (int i=0; i<DataPoints; i++) { 286 Items[ItemNo].x[Count] = Curr[(i+Oldest)%DataPoints].Seconds; 287 Items[ItemNo].y[Count] = Curr[(i+Oldest)%DataPoints].Value; 288 if (Items[ItemNo].x[Count] != 0) Count++; 289 } 290 291 // Find smallest and largest item 292 double Smallest = DBL_MAX, Largest = DBL_MIN; 293 for (int i=0; i<Count; i++) { 294 if (Largest < Items[ItemNo].y[i]) Largest = Items[ItemNo].y[i]; 295 if (Smallest > Items[ItemNo].y[i]) Smallest = Items[ItemNo].y[i]; 296 } 297 Items[ItemNo].Smallest = Smallest; 298 Items[ItemNo].Largest = Largest; 299 Items[ItemNo].Count = Count; 300 301 // Clear local history 302 Items[ItemNo].Live.clear(); 272 // If buffer empty, request new history buffer 273 if (Items[ItemNo].x.isEmpty()) { 274 int Time, Size; 275 void *Data; 276 277 if (GetHistory(Items[ItemNo].LiveData->getName())) { 278 double Smallest = DBL_MAX, Largest = DBL_MIN; 279 double Number=0; 280 while (Next(Time, Size, Data)) { 281 switch (*(Info->getFormat())) { 282 case 'I': Number = *(int *) Data; break; 283 case 'S': Number = *(short *) Data; break; 284 case 'F': Number = *(float *) Data; break; 285 case 'D': Number = *(double *) Data; break; 286 case 'X': Number = *(long long *) Data; break; 287 default: break; 288 } 289 290 Items[ItemNo].x.append(Time); 291 Items[ItemNo].y.append(Number); 292 293 if (Largest < Items[ItemNo].y.last()) Largest = Items[ItemNo].y.last(); 294 if (Smallest > Items[ItemNo].y.last()) Smallest = Items[ItemNo].y.last(); 295 } 296 297 Items[ItemNo].Smallest = Smallest; 298 Items[ItemNo].Largest = Largest; 299 300 // Local buffer always at least twice as large as history 301 if (Items[ItemNo].SizeLimit < 2*Items[ItemNo].x.size()) { 302 Items[ItemNo].SizeLimit = 2*Items[ItemNo].x.size(); 303 } 304 } 305 } 306 307 // Append data 308 Items[ItemNo].x.append(Time); 309 Items[ItemNo].y.append(atof(Text.toAscii().data())); 310 311 // Update largest and smallest value 312 if (Items[ItemNo].y.last() > Items[ItemNo].Largest) Items[ItemNo].Largest = Items[ItemNo].y.last(); 313 if (Items[ItemNo].y.last() < Items[ItemNo].Smallest) Items[ItemNo].Smallest = Items[ItemNo].y.last(); 303 314 304 315 // Update status tip 305 316 QDateTime Timex = QDateTime::fromTime_t(Time); 306 StatusTip = QString("%1: Last update %2 Format '%3'").arg(Info->getName(), Timex.toString()).arg(Format); 307 308 } else if (Info == Items[ItemNo].LiveData) { 309 // This is a live service 310 311 // Limit size of list 312 if (Items[ItemNo].Live.size() > 1000) Items[ItemNo].Live.removeFirst(); 313 314 // Append data 315 struct EvidenceHistoryItem Data; 316 Data.Seconds = Time; 317 Data.Value = atof(Text.toAscii().data()); 318 Items[ItemNo].Live.append(Data); 319 320 // Update largest and smallest value 321 if (Data.Value > Items[ItemNo].Largest) Items[ItemNo].Largest = Data.Value; 322 if (Data.Value < Items[ItemNo].Smallest) Items[ItemNo].Smallest = Data.Value; 317 StatusTip = QString("%1: Last update %2 Format '%3'").arg(Info->getName(), Timex.toString()).arg(Info->getFormat()); 323 318 } 324 319 … … 352 347 else Items[ItemNo].Signal->setSymbol(Sym1); 353 348 354 int DataPoints = Items[ItemNo]. Count + Items[ItemNo].Live.size();349 int DataPoints = Items[ItemNo].x.size(); 355 350 356 351 if (DataPoints == 0) continue; … … 361 356 // Adapt time scale and normalize y scale if requested 362 357 for (int i=0; i<DataPoints; i++) { 363 if (i < Items[ItemNo].Count) { 364 x[i] = Items[ItemNo].x[i] / 86400.0 + 40587.5 - 55200; 365 y[i] = Items[ItemNo].y[i]; 366 } 367 else { 368 x[i]= Items[ItemNo].Live[i-Items[ItemNo].Count].Seconds / 86400.0 + 40587.5 - 55200; 369 y[i] = Items[ItemNo].Live[i-Items[ItemNo].Count].Value; 370 } 358 x[i] = Items[ItemNo].x[i] / 86400.0 + 40587.5 - 55200; 359 y[i] = Items[ItemNo].y[i]; 371 360 372 361 if (NormAction->isChecked()) { 373 if (Items[ItemNo].Smallest != Items[ItemNo].Largest) y[i] = (y[i] - Items[ItemNo].Smallest)/(Items[ItemNo].Largest-Items[ItemNo].Smallest); 374 else y[i] = 1; 362 if (Items[ItemNo].Smallest != Items[ItemNo].Largest) { 363 y[i] = (y[i] - Items[ItemNo].Smallest)/(Items[ItemNo].Largest-Items[ItemNo].Smallest); 364 } 365 else y[i] = 1; 375 366 } 376 367 } 377 368 378 // Plot data s369 // Plot data 379 370 Items[ItemNo].Signal->setData(x, y, DataPoints); 380 371 Items[ItemNo].Signal->show(); … … 443 434 444 435 while (Items.size() > 1) { 445 delete Items.last().Data;446 436 delete Items.last().LiveData; 447 437 delete Items.last().Signal; 448 delete[] Items.last().x;449 delete[] Items.last().y;450 438 Items.takeLast(); 451 439 } … … 473 461 // Write x and y data for all signals to file 474 462 for (int ItemNo=0; ItemNo<Items.size(); ItemNo++) { 475 Stream << QString("# ")+Items[ItemNo]. Data->getName()<< endl;463 Stream << QString("# ")+Items[ItemNo].LiveData->getName()+".hist" << endl; 476 464 for (int i=0; i<Items[ItemNo].Signal->dataSize(); i++) { 477 Stream << (int) Items[ItemNo].x [i]<< " " << Items[ItemNo].Signal->y(i) << endl;465 Stream << (int) Items[ItemNo].x.at(i) << " " << Items[ItemNo].Signal->y(i) << endl; 478 466 } 479 467 } … … 514 502 515 503 504 /////////////////////////////////////// 505 // History text box for DIM service // 506 ////////////////////////////////////// 507 508 // 509 // Constructor 510 // 511 Edd_TextHist::Edd_TextHist(QString DIMService, QWidget *P): QTextEdit(P), EvidenceHistory() { 512 513 // Widget properties 514 setReadOnly(true); 515 setAttribute(Qt::WA_DeleteOnClose); 516 setAutoFillBackground(true); 517 document()->setMaximumBlockCount(1000); 518 519 // Connect to DIM handler 520 if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QByteArray, QString)), SLOT(Update(DimInfo*, int, QByteArray, QString))) == false) { 521 printf("Failed connection for %s\n", DIMService.toAscii().data()); 522 } 523 524 // Get history for this service 525 int Time, Size; 526 void *Data; 527 528 if (GetHistory(DIMService.toAscii().data())) { 529 while (Next(Time, Size, Data)) { 530 moveCursor (QTextCursor::Start); 531 insertPlainText(QString("(")+QDateTime::fromTime_t(Time).toString()+") "); 532 insertPlainText(QString((char *) Data) + "\n"); 533 } 534 } 535 536 // DIM client 537 Service = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, NO_LINK, Handler); 538 } 539 540 // Destructor 541 Edd_TextHist::~Edd_TextHist() { 542 543 delete Service; 544 } 545 546 547 // Update widget (must happen in GUI thread) 548 void Edd_TextHist::Update(DimInfo *Info, int Time, QByteArray, QString Text) { 549 550 if (Info != this->Service) return; 551 552 // Check if service available 553 if (Time == -1) { 554 setStatusTip(QString("%1: unavailable").arg(Info->getName())); 555 return; 556 } 557 558 QDateTime Timex = QDateTime::fromTime_t(Time); 559 560 moveCursor(QTextCursor::Start); 561 insertPlainText(QString("(")+Timex.toString()+QString(") ")); 562 insertPlainText(Text + "\n"); 563 564 // Update status tip 565 StatusTip = QString("%1: Last update %2 Format '%3'").arg(Info->getName(), Timex.toString()).arg(Info->getFormat()); 566 } 567 568 516 569 ////////////////// 517 570 // Text display // … … 528 581 529 582 // Connect to DIM handler 530 if (connect(Handler, SIGNAL(YEP(DimInfo*, int, Q String, QByteArray, QString)), SLOT(Update(DimInfo*, int, QString, QByteArray, QString))) == false) {583 if (connect(Handler, SIGNAL(YEP(DimInfo*, int, QByteArray, QString)), SLOT(Update(DimInfo*, int, QByteArray, QString))) == false) { 531 584 printf("Failed connection for %s\n", DIMService.toAscii().data()); 532 585 } 533 586 534 587 // DIM client 535 Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, (char *)NO_LINK, Handler);588 Data = new DimStampedInfo(DIMService.toAscii().data(), INT_MAX, NO_LINK, Handler); 536 589 } 537 590 … … 543 596 544 597 // Handling of DIM service update 545 void Edd_Textout::Update(DimInfo *Info, int Time, Q String Format, QByteArray, QString Text) {598 void Edd_Textout::Update(DimInfo *Info, int Time, QByteArray, QString Text) { 546 599 547 600 if (Info != this->Data) return; … … 561 614 562 615 // Add if service contains only a string 563 if ( Format == "C") insertPlainText(Text);616 if (strcmp(Info->getFormat(), "C") == 0) insertPlainText(Text); 564 617 565 618 // Update status tip 566 setStatusTip(QString("%1: Last update %2 Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg( Format));619 setStatusTip(QString("%1: Last update %2 Format '%3'").arg(Info->getName(), QDateTime::fromTime_t(Time).toString()).arg(Info->getFormat())); 567 620 } 568 621 setPalette(Pal); … … 652 705 MainLayout->addWidget(Value, 7, 0, 1, 1); 653 706 707 QPushButton *Button = new QPushButton(); 708 Button->setText("Start DIM browser"); 709 connect(Button, SIGNAL(released()), SLOT(StartDIMBrowser())); 710 MainLayout->addWidget(Button, 7, 1, 1, 1); 711 712 Edd_TextHist *Bla; 713 Bla = new Edd_TextHist("DColl/CurrentFile"); 714 MainLayout->addWidget(Bla, 8, 0, 1, 1); 654 715 655 716 // Layout of all widgets … … 669 730 Text = Text.sprintf("Bias/VOLT/ID00/00-%.3d",i); 670 731 Value = new Edd_Indicator(Text); 732 671 733 BiasLayout->addWidget(Value, i%9+1, 0+i/9, 1, 1); 672 734 Graph->AddService(Text); … … 686 748 Textout->setFixedWidth(400); 687 749 BiasLayout->addWidget(Textout, 10, 0, 4, 4); 688 750 689 751 // Environment page 690 752 EnvironmentWidget = new QWidget(); … … 772 834 773 835 // Check if service available 774 if (getInfo()->getSize() == strlen(NO_LINK)+1 && strcmp(getInfo()->getString(), NO_LINK) == 0) { 775 YEP(getInfo(), -1); 776 } 836 if (!EvidenceServer::ServiceOK(getInfo())) YEP(getInfo(), -1); 777 837 else { 778 838 char *Txt = EvidenceServer::ToString(getInfo()); 779 839 780 YEP(getInfo(), getInfo()->getTimestamp(), getInfo()->getFormat(), QByteArray((char *) getInfo()->getData(), getInfo()->getSize()), QString(Txt)); 781 free(Txt); 782 } 783 } 840 YEP(getInfo(), getInfo()->getTimestamp(), QByteArray((char *) getInfo()->getData(), getInfo()->getSize()), QString(Txt)); 841 free(Txt); 842 } 843 } 844 845 // Start DIM Browser 846 void GUI::StartDIMBrowser() { 847 848 QProcess::startDetached("did", QStringList(), QString(getenv("DIMDIR"))+"/linux/"); 849 } 850 784 851 785 852 //--------------------------------------------------------------------- -
Evidence/Edd/Edd.h
r152 r159 46 46 47 47 private slots: 48 void Update(DimInfo *, int, Q String, QByteArray, QString);48 void Update(DimInfo *, int, QByteArray, QString); 49 49 void contextMenuEvent(QContextMenuEvent *); 50 50 void MenuOpenHistory(); 51 51 void MenuCopyService(); 52 void MenuCopyData(); 52 53 }; 53 54 54 55 // Graph class for history display 55 class Edd_Plot: public QwtPlot, public DimClient{56 class Edd_Plot: public QwtPlot, public EvidenceHistory { 56 57 Q_OBJECT 57 58 58 59 struct PlotItem { 59 DimInfo *Data;60 60 DimInfo *LiveData; 61 61 QwtPlotCurve *Signal; 62 int *x;63 double *y;64 int Count;65 62 double Smallest; 66 63 double Largest; 67 QList<struct EvidenceHistoryItem> Live; 64 int SizeLimit; 65 QVector<double> x; 66 QVector<double> y; 68 67 }; 69 68 … … 93 92 private slots: 94 93 void UpdatePlot(); 95 void Update(DimInfo* Info, int, Q String, QByteArray, QString);94 void Update(DimInfo* Info, int, QByteArray, QString); 96 95 97 96 void HandleZoom(const QwtDoubleRect &); … … 106 105 }; 107 106 107 // Text history class 108 class Edd_TextHist: public QTextEdit, public EvidenceHistory { 109 Q_OBJECT 110 111 QString StatusTip; 112 DimStampedInfo *Service; 113 114 public: 115 Edd_TextHist(QString, QWidget * = NULL); 116 ~Edd_TextHist(); 117 118 private slots: 119 void Update(DimInfo* Info, int, QByteArray, QString); 120 }; 121 108 122 // Textout indicator for DIM service 109 class Edd_Textout: public QTextEdit, public DimClient{123 class Edd_Textout: public QTextEdit, public EvidenceHistory { 110 124 Q_OBJECT 111 125 … … 119 133 120 134 private slots: 121 void Update(DimInfo* Info, int, Q String, QByteArray, QString);135 void Update(DimInfo* Info, int, QByteArray, QString); 122 136 }; 123 137 … … 143 157 void MenuAbout(); 144 158 void MenuNewHistory(); 159 void StartDIMBrowser(); 145 160 146 161 signals: 147 void YEP(DimInfo *, int, Q String = QString(), QByteArray = QByteArray(), QString = QString());162 void YEP(DimInfo *, int, QByteArray = QByteArray(), QString = QString()); 148 163 }; 149 164 -
Evidence/Evidence.cc
r154 r159 25 25 #include "Evidence.h" 26 26 27 using namespace std; 28 29 ////////////////////////// 30 // EvidenceServer Class // 31 ////////////////////////// 32 27 33 EvidenceServer *ThisServer; 28 34 … … 50 56 start(Name); 51 57 addExitHandler(this); 52 53 58 } 54 59 … … 56 61 EvidenceServer::~EvidenceServer() { 57 62 63 State(INFO, "Server stopped"); 64 58 65 for (unsigned int i=0; i<ConfigList.size(); i++) { 59 66 delete[] ConfigList[i].Name; … … 64 71 // DIM exit handler 65 72 void EvidenceServer::exitHandler(int Code) { 66 State(INFO, " Server stopped (DIM exit code %d)", Code);73 State(INFO, "Exit handler called (DIM exit code %d)", Code); 67 74 exit(EXIT_SUCCESS); 68 75 } … … 104 111 // Send message to console and log file 105 112 printf("%s\n", TBuf); 106 if (Severity != INFO) DimClient::sendCommand("DColl/Log", TBuf);113 DimClient::sendCommandNB("DColl/Log", TBuf); 107 114 108 115 // Update DIM status service (including severity encoding) … … 188 195 189 196 // Translates DIMInfo to string (memory has to be freed by caller) 190 // No DIM structures are supported (only a single number or string is converted)197 // DIM structures are converted to hexadecimal representation 191 198 // For string conversion, a terminating \0 is enforced. 192 199 char *EvidenceServer::ToString(DimInfo *Item) { 193 200 194 201 char *Text; 195 int R; 196 197 if (strlen(Item->getFormat()) != 1) return NULL; 198 199 switch (*(Item->getFormat())) { 200 case 'I': R = asprintf(&Text, "%d", Item->getInt()); break; 201 case 'S': R = asprintf(&Text, "%hd", Item->getShort()); break; 202 case 'F': R = asprintf(&Text, "%.5f", Item->getFloat()); break; 203 case 'D': R = asprintf(&Text, "%.5f", Item->getDouble()); break; 204 case 'X': R = asprintf(&Text, "%lld", Item->getLonglong()); break; 205 case 'C': *(Item->getString() + Item->getSize()) = '\0'; 206 R = asprintf(&Text, "%s", Item->getString()); 207 break; 208 default: return NULL; 209 } 210 202 int R=0; 203 204 if (strlen(Item->getFormat()) != 1) { 205 if ((Text = (char *) malloc(3*Item->getSize()+1)) != NULL) { 206 for (int i=0; i<Item->getSize(); i++) sprintf(Text+3*i, "%02x", *((char *) Item->getData() + i)); 207 } 208 } 209 else { 210 switch (*(Item->getFormat())) { 211 case 'I': R = asprintf(&Text, "%d", Item->getInt()); break; 212 case 'S': R = asprintf(&Text, "%hd", Item->getShort()); break; 213 case 'F': R = asprintf(&Text, "%.5f", Item->getFloat()); break; 214 case 'D': R = asprintf(&Text, "%.5f", Item->getDouble()); break; 215 case 'X': R = asprintf(&Text, "%lld", Item->getLonglong()); break; 216 case 'C': *(Item->getString() + Item->getSize() - 1) = '\0'; 217 R = asprintf(&Text, "%s", Item->getString()); 218 break; 219 default: return NULL; 220 } 221 } 222 211 223 return (R == -1) ? NULL : Text; 212 224 } 225 226 // Checks if service contents indicates not available 227 bool EvidenceServer::ServiceOK(DimInfo *Item) { 228 229 return !((Item->getSize() == strlen(NO_LINK)+1) && 230 (memcmp(Item->getData(), NO_LINK, Item->getSize()) == 0)); 231 232 } 233 234 235 /////////////////////////// 236 // EvidenceHistory Class // 237 /////////////////////////// 238 239 // Organisaztion of history buffer 240 // F | T S D | T S D | 0 0 ...... | T S D | T S D | 0 -1 241 // 242 // F: Offset of oldest entry T: Time S: Size D: Data 243 // F, T, S: int 244 245 // Marker for history buffer 246 const int EvidenceHistory::WrapMark[] = {0, -1}; 247 const int EvidenceHistory::EndMark[] = {0, 0}; 248 249 // Constructor 250 EvidenceHistory::EvidenceHistory() { 251 252 Buffer = NULL; 253 } 254 255 // Destructor 256 EvidenceHistory::~EvidenceHistory() { 257 258 delete[] Buffer; 259 } 260 261 // Requests service history 262 bool EvidenceHistory::GetHistory(char *Name) { 263 264 DimCurrentInfo Info((string(Name)+".hist").c_str(), NO_LINK); 265 266 // Check if service available 267 if (((Info.getSize() == strlen(NO_LINK)+1) && 268 (memcmp(Info.getData(), NO_LINK, Info.getSize()) == 0))) return false; 269 270 delete[] Buffer; 271 BufferSize = Info.getSize(); 272 Buffer = new char [BufferSize]; 273 274 memcpy(Buffer, Info.getData(), BufferSize); 275 Offset = *(int *) Buffer; 276 277 return true; 278 } 279 280 // Returns next item in history buffer 281 bool EvidenceHistory::Next(int &Time, int &Size, void *&Data) { 282 283 if (Buffer == NULL) return false; 284 285 // Check for wrap around 286 if (memcmp(Buffer+Offset, WrapMark, sizeof(WrapMark)) == 0) Offset = 4; 287 288 // Check if at end of ring buffer 289 if (memcmp(Buffer+Offset, EndMark, sizeof(EndMark)) == 0) return false; 290 291 Time = *(int *) (Buffer + Offset); 292 Size = *(int *) (Buffer + Offset + sizeof(int)); 293 Data = Buffer + Offset + 2*sizeof(int); 294 295 Offset += *((int *) (Buffer + Offset) + 1) + 2*sizeof(int); 296 297 return true; 298 } -
Evidence/Evidence.h
r154 r159 15 15 #define STATUS_SIZE 1000 // Bytes for status service string 16 16 17 using namespace std;18 19 // Declaration of item for history buffer (see DColl.cc)20 struct EvidenceHistoryItem {21 int Seconds;22 double Value;23 } __attribute__((__packed__));24 25 17 // Class declation of Evidence server 26 18 class EvidenceServer: public DimServer { … … 32 24 int Time; 33 25 }; 34 vector<struct ConfigItem> ConfigList;26 std::vector<struct ConfigItem> ConfigList; 35 27 36 28 DimService *Status; … … 50 42 char* GetConfig(const char *, const char * = NULL); 51 43 static char* ToString(DimInfo *); 44 static bool ServiceOK(DimInfo *); 52 45 53 46 bool ExitRequest; 54 47 }; 55 48 49 class EvidenceHistory: public DimClient { 50 51 static const int WrapMark[]; 52 static const int EndMark[]; 53 54 std::string HistoryName; 55 char *Buffer; 56 int BufferSize; 57 int Offset; 58 59 public: 60 EvidenceHistory(); 61 ~EvidenceHistory(); 62 63 bool GetHistory(char *); 64 bool Next(int &, int &, void *&); 65 }; 56 66 #endif
Note:
See TracChangeset
for help on using the changeset viewer.