// MyMonModuleZVEI.cpp: Implementierung der Klasse MonitorModuleZVEI. // // Edited 02/2007 - demod rewritten, fully functional but to be tested "in the wild": // Martin Diedrich (martin@mdiedrich.de) ////////////////////////////////////////////////////////////////////// #include <iostream> #include <fstream> #include "math.h" #include "time.h" #include "convert.h" #include "MonitorModuleZVEI.h" #include "MonitorLogging.h" using namespace std; #ifdef WIN32 #include <vector> #include <algorithm> #include <functional> #endif #ifdef _DEBUG #undef THIS_FILE //static char THIS_FILE[]=__FILE__; #endif #ifdef WIN32 #ifndef M_PI const float M_PI = 3.14159265358979 ; #endif #endif #define COS(x) costabf[(((x) >> 6) & 0x3ffu)] #define SIN(x) COS((x) + 0xc000) #define BLOCKNUM 4 ////////////////////////////////////////////////////////////////////// // Konstruktion/Destruktion ////////////////////////////////////////////////////////////////////// int MonitorModuleZVEI::PHINC(int x) { return (x * 0x10000 / FREQ_SAMP) ; } /** * @brief constructor, initializing most of our little ZVEI universe ;) * @param sampleRate sample rate of data from soundcard to be analyzed by demod() */ MonitorModuleZVEI::MonitorModuleZVEI(int sampleRate,XMLNode* pConfig) { unsigned int i ; debugmodus = getNodeInt(*pConfig,"debugmodus",0); int gm900 = getNodeInt(*pConfig,"gm900",0); // ONLY FOR GM900 AT FHD OSTERODE squelch = getNodeInt(*pConfig,"squelch",51); squelch = squelch/100; m_lpszName="ZVEI" ; FREQ_SAMP=sampleRate ; BLOCKLEN=sampleRate / 100 ; // Definition der zu betrachtenden Frequenzen zvei_freq[0]=PHINC(2400) ; // Ziffer 0 if(gm900 == 1) { zvei_freq[0]=PHINC(2410) ; // Ziffer 0 for slightly too high tone by motorola gm900 in use at fhd osterode } zvei_freq[1]=PHINC(1060) ; // Ziffer 1 zvei_freq[2]=PHINC(1160) ; // Ziffer 2 zvei_freq[3]=PHINC(1270) ; // Ziffer 3 zvei_freq[4]=PHINC(1400) ; // Ziffer 4 zvei_freq[5]=PHINC(1530) ; // Ziffer 5 zvei_freq[6]=PHINC(1670) ; // Ziffer 6 zvei_freq[7]=PHINC(1830) ; // Ziffer 7 zvei_freq[8]=PHINC(2000) ; // Ziffer 8 zvei_freq[9]=PHINC(2200) ; // Ziffer 9 zvei_freq[10]=PHINC(2800) ; // A = N / Spezialfall Gruppenruf zvei_freq[11]=PHINC(810) ; // C zvei_freq[12]=PHINC(675) ; // Sirenendoppelton I zvei_freq[13]=PHINC(1240) ; // Sirenendoppelton II zvei_freq[14]=PHINC(2600) ; // E = W (Wiederholungs- und Melderweckton) zvei_freq[15]=PHINC(0) ; // Stille/Rauschen/keine eindeutige Frequenz zvei_freq[16]=PHINC(1860) ; // Sirenendoppelton III zvei_freq[17]=PHINC(825) ; // Sirenendoppelton IV zvei_freq[18]=PHINC(2280) ; // Sirenendoppelton V zvei_freq[19]=PHINC(1010) ; // Sirenendoppelton VI // Definition der zu betrachtenden Frequenzen zvei_character[0]='0' ; // Ziffer 0 zvei_character[1]='1' ; // Ziffer 1 zvei_character[2]='2' ; // Ziffer 2 zvei_character[3]='3' ; // Ziffer 3 zvei_character[4]='4' ; // Ziffer 4 zvei_character[5]='5' ; // Ziffer 5 zvei_character[6]='6' ; // Ziffer 6 zvei_character[7]='7' ; // Ziffer 7 zvei_character[8]='8' ; // Ziffer 8 zvei_character[9]='9' ; // Ziffer 9 zvei_character[10]='A' ; // A = N / Spezialfall Gruppenruf zvei_character[11]='C' ; // C zvei_character[12]='S' ; // Sirenendoppelton I zvei_character[13]='S' ; // Sirenendoppelton II zvei_character[14]='W' ; // E = W (Wiederholungs- und Melderweckton) zvei_character[15]='-' ; // Stille/Rauschen/keine eindeutige Frequenz zvei_character[16]='S' ; // Sirenendoppelton III zvei_character[17]='S' ; // Sirenendoppelton IV zvei_character[18]='S' ; // Sirenendoppelton V zvei_character[19]='S' ; // Sirenendoppelton VI // initializing our matrixes -> zeroing for (i=0; i <= sizeof(zvei_freq)/sizeof(zvei_freq[0]); i++) { ph[i]=0; } for (i=0; i < 4 ;i++) { energy[i]=0; } for (i=0; i< 4; i++) { for (unsigned int j=0; j <= 2*sizeof(zvei_freq)/sizeof(zvei_freq[0]); j++) { tenergy[i][j]=0; } } blkcount=0 ; folge_position = 0; // gibt die aktuelle Position bei der Erkennung an, in gewisser Weise der "Zustandsautomat" timeout = 0; // Zu lange Pause nach Tonfolge -> triggert Ausgabe und Resets pause_length = 0; // Laenge der bisher gemessenen Pause, reset bei 100 tone_count = 0; // wie oft wurde der ton erkannt? seven_count = 0; siren_count = 0; maxlength = sizeof(zvei_folge)/sizeof(zvei_folge[0]); // Laenge der n-Tonfolge. Normalerweise 5. Es gab einen Request fuer 7. /* * Format des Arrays fount_tones: * [0] - energiereichste Frequenz, [1] - zweitenergier. Freq., [2] - drittenergier. Freq., [3] - Energie I, [4] - Energie II - [5] - Energie III, * [6] - Totale Energie; damit stehen drei Toene und Energien zur Verfuegung fuer Auswertung und Filter */ found_tones = new int[7]; // Rueckgabe der process_block()-Methode for (i=0; i < 7; i++) { for(int j=0; j<7; j++) { detected_seven[i][j] = -1; } } for(i=0; i < maxlength; i++) { zvei_folge[i] = -2; } for (i = 0; i < COSTABSIZE; i++) { costabf[i] = (float) cos(M_PI*2.0*i/COSTABSIZE); } } MonitorModuleZVEI::~MonitorModuleZVEI() { } /** * @brief demodulates raw sounddata from card to ZVEI-Tonfolgen * @param buffer pointer to sound buffer * @param length length of that buffer * @author Martin Diedrich (mdi) * @date 11/2007 */ void MonitorModuleZVEI::demod(float *buffer, int length) { unsigned int i ; float s_in=0; short int last_zvei_last_character = -2; // uebernommen aus dem vorherigen code for (; length > 0; length--, buffer++) { s_in = *buffer; energy[0] += fsqr(s_in); /* Berechnen und Aufaddieren der Spalte 0 der tenergy-Matrix * mit 220 (BLOCKLEN) aufeinanderfolgenden Bufferwerten: * Zeilen 0-17: Cos-Werte, Zeilen 18-35: Sin-Werte */ for (i = 0; i < sizeof(zvei_freq)/sizeof(zvei_freq[0]); i++) { tenergy[0][i] += COS(ph[i]) * s_in; tenergy[0][i + sizeof(zvei_freq)/sizeof(zvei_freq[0])] += SIN(ph[i]) * s_in; ph[i] += zvei_freq[i]; } if ((blkcount--) <= 0) { blkcount = BLOCKLEN; found_tones = process_block(found_tones); memcpy(detected_seven[seven_count], found_tones, sizeof(int)*7); int f = fuzzyseven(); if( debugmodus > 5 && ((f >= 0 && f <= 11) || f == 14)) { cout << " -> " << f << " -> " << zvei_character[f] << endl; } // ZVEI digit or repeating tone found, not end of ZVEI quintett if(((f >= 0 && f <= 11) || f == 14) && folge_position != maxlength) { if(folge_position != 0) { if(f != zvei_folge[folge_position-1]) { zvei_folge[folge_position] = f; folge_position++; } } else { zvei_folge[folge_position] = f; folge_position++; } pause_length = 0; } // wakeup found shortly before maximum pause time if(f == 14 && folge_position == maxlength && pause_length > 52) { if(zvei_ok()) { if(debugmodus > 2) { cout << endl; for(i=0; i<5; i++) { cout << (zvei_folge[i] == 14 ? zvei_folge[(i+(maxlength-1))%maxlength] : zvei_folge[i]); } cout << " (Melderausloesung)" << endl << endl; } std::string numString=""; for(unsigned int counter=0;counter<maxlength;counter++) { // numString+=convertIntToHexString((zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])); numString+=zvei_character[(zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])]; } DisplayResult(numString,1,"Melderausloesung"); } for(i=0; i<maxlength; i++) { zvei_folge[i] = -2; } folge_position = 0; pause_length = 0; siren_count = 0; } // normal pause handling if ((f == 15 || f == -1) && folge_position != maxlength ) { pause_length++; if(pause_length == 6) { for(i=0; i<maxlength; i++) { zvei_folge[i] = -2; } folge_position = 0; pause_length = 0; } if(debugmodus > 5) { cout << " Pause: " << pause_length; } } // waiting for siren or wakeup - or reacting on timeout if ((f == 15 || f == -1) && folge_position == maxlength ) { pause_length++; if(debugmodus > 5) { cout << " Pause: " << pause_length; } if(pause_length == 64) { // timeout if(zvei_ok()) { if(debugmodus > 2) { cout << endl; for(i=0; i<maxlength; i++) { cout << (zvei_folge[i] == 14 ? zvei_folge[(i+(maxlength-1))%maxlength] : zvei_folge[i]); } cout << " (Timeout)" << endl << endl; } std::string numString=""; for(unsigned int counter=0;counter<maxlength;counter++) { // numString+=convertIntToHexString((zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])); numString+=zvei_character[(zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])]; } DisplayResult(numString,0,"unklare Ausloesung"); } for(i=0; i<maxlength; i++) { zvei_folge[i] = -2; } last_zvei_last_character = -2; folge_position = 0; pause_length = 0; siren_count = 0; } } // got siren tone 12/13 - fire if ( ((found_tones[0] == 12 && found_tones[1] == 13) || (found_tones[1] == 12 && found_tones[0] == 13)) && folge_position == maxlength) { siren_count++; pause_length = 0; if(siren_count > 20) { if(zvei_ok()) { if(debugmodus > 2) { cout << endl; for(i=0; i<maxlength; i++) { cout << (zvei_folge[i] == 14 ? zvei_folge[(i+(maxlength-1))%maxlength] : zvei_folge[i]); } cout << " (Siren2)" << endl << endl; } std::string numString=""; for(unsigned int counter=0;counter<maxlength;counter++) { // numString+=convertIntToHexString((zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])); numString+=zvei_character[(zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])]; } DisplayResult(numString,2,"Sirenenausloesung: Feueralarm"); } for(i=0; i<maxlength; i++) { zvei_folge[i] = -2; } folge_position = 0; siren_count = 0; } } // got siren tone 12/19 - ZVS-Entwarnung if ( ((found_tones[0] == 12 && found_tones[1] == 19) || (found_tones[1] == 12 && found_tones[0] == 19)) && folge_position == maxlength) { siren_count++; pause_length = 0; if(siren_count > 20) { if(zvei_ok()) { if(debugmodus > 2) { cout << endl; for(i=0; i<maxlength; i++) { cout << (zvei_folge[i] == 14 ? zvei_folge[(i+(maxlength-1))%maxlength] : zvei_folge[i]); } cout << " (Siren6)" << endl << endl; } std::string numString=""; for(unsigned int counter=0;counter<maxlength;counter++) { // numString+=convertIntToHexString((zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])); numString+=zvei_character[(zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])]; } DisplayResult(numString,6,"Sirenenausloesung: Entwarnung"); } for(i=0; i<maxlength; i++) { zvei_folge[i] = -2; } folge_position = 0; siren_count = 0; } } // got siren tone 12/16 - Probe if ( ((found_tones[0] == 12 && found_tones[1] == 16) || (found_tones[1] == 12 && found_tones[0] == 16)) && folge_position == maxlength) { siren_count++; pause_length = 0; if(siren_count > 20) { if(zvei_ok()) { if(debugmodus > 2) { cout << endl; for(i=0; i<maxlength; i++) { cout << (zvei_folge[i] == 14 ? zvei_folge[(i+(maxlength-1))%maxlength] : zvei_folge[i]); } cout << " (Siren3)" << endl << endl; } std::string numString=""; for(unsigned int counter=0;counter<maxlength;counter++) { // numString+=convertIntToHexString((zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])); numString+=zvei_character[(zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])]; } DisplayResult(numString,3,"Sirenenausloesung: Probe"); } for(i=0; i<maxlength; i++) { zvei_folge[i] = -2; } folge_position = 0; siren_count = 0; } } // got siren tone 12/17 - ZVS-Alarm if ( ((found_tones[0] == 12 && found_tones[1] == 17) || (found_tones[1] == 12 && found_tones[0] == 17)) && folge_position == maxlength) { siren_count++; pause_length = 0; if(siren_count > 20) { if(zvei_ok()) { if(debugmodus > 2) { cout << endl; for(i=0; i<maxlength; i++) { cout << (zvei_folge[i] == 14 ? zvei_folge[(i+(maxlength-1))%maxlength] : zvei_folge[i]); } cout << " (Siren4): " << found_tones[0] << " " << found_tones[1] << endl << endl; } std::string numString=""; for(unsigned int counter=0;counter<maxlength;counter++) { // numString+=convertIntToHexString((zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])); numString+=zvei_character[(zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])]; } DisplayResult(numString,4,"Sirenenausloesung: ZVS-Alarm"); } for(i=0; i<maxlength; i++) { zvei_folge[i] = -2; } folge_position = 0; siren_count = 0; } } // got siren tone 12/18 - ZVS-Warnung if ( ((found_tones[0] == 12 && found_tones[1] == 18) || (found_tones[1] == 12 && found_tones[0] == 18)) && folge_position == maxlength) { siren_count++; pause_length = 0; if(siren_count > 20) { if(zvei_ok()) { if(debugmodus > 2) { cout << endl; for(i=0; i<maxlength; i++) { cout << (zvei_folge[i] == 14 ? zvei_folge[(i+(maxlength-1))%maxlength] : zvei_folge[i]); } cout << " (Siren5)" << endl << endl; } std::string numString=""; for(unsigned int counter=0;counter<maxlength;counter++) { // numString+=convertIntToHexString((zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])); numString+=zvei_character[(zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])]; } DisplayResult(numString,5,"Sirenenausloesung: ZVS-Warnung"); } for(i=0; i<maxlength; i++) { zvei_folge[i] = -2; } folge_position = 0; siren_count = 0; } } // new digit after full zvei_folge if(((f >= 0 && f <= 11) || f == 14) && folge_position == maxlength && zvei_ok() && (zvei_folge[4] != f || pause_length > 10 )) { if(debugmodus > 2) { cout << endl; for(i=0; i<maxlength; i++) { cout << (zvei_folge[i] == 14 ? zvei_folge[(i+(maxlength-1))%maxlength] : zvei_folge[i]); } cout << " (Nachfolger): " << f << endl; } // Motorola Sonderbehandlung if(zvei_folge[0] == 14) { zvei_folge[0] = last_zvei_last_character; } std::string numString=""; for(unsigned int counter=0;counter<maxlength;counter++) { // numString+=convertIntToHexString((zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])); numString+=zvei_character[(zvei_folge[counter] == 14 ? zvei_folge[(counter+(maxlength-1))%maxlength] : zvei_folge[counter])]; } DisplayResult(numString,0,"unklare Ausloesung"); // first tone 14 not in ZVEI-Standard but used by Motorola radios when two select5 are sent directly following, this saves last character of decoded select5. if(zvei_folge[4] == 14) { last_zvei_last_character = zvei_folge[3]; } else { last_zvei_last_character = zvei_folge[4]; } for(i=0; i<maxlength; i++) { zvei_folge[i] = -2; } folge_position = 0; zvei_folge[folge_position] = f; folge_position++; pause_length = 0; siren_count = 0; } seven_count++; // just resetting our counter for the buffer of seven detected tones if(seven_count == 7) { seven_count = 0; if(false) { // DEBUG for(int i=0; i<7; i++) { cout << detected_seven[i][0] << " - " << detected_seven[i][1] << endl; } cout << endl; } } } } } /** * @brief fourier transformation (Goertzel) on given block of sound data */ int *MonitorModuleZVEI::process_block(int *found_tones) { float tote = 0; float totte[2*sizeof(zvei_freq)/sizeof(zvei_freq[0])]; unsigned int i, j; /* Aufaddieren der energy-Eintraege nach TOTal-Energy (tote) */ for (i = 0; i < BLOCKNUM; i++) tote += energy[i]; /* Aufaddieren der Zeilen der tenergy-Matrix nach TOTal-TEnergy (totte) */ for (i = 0; i < 2*sizeof(zvei_freq)/sizeof(zvei_freq[0]); i++) { totte[i] = 0; for (j = 0; j < BLOCKNUM; j++) totte[i] += tenergy[j][i]; } // tote *= (BLOCKNUM * BLOCKLEN * 0.5); /* adjust for block lengths */ /* Summe der Quadrate der korrespondierenden Sinus- und Cosinuseintraege */ for (i = 0; i < sizeof(zvei_freq)/sizeof(zvei_freq[0]); i++) totte[i] = fsqr(totte[i]) + fsqr(totte[i+sizeof(zvei_freq)/sizeof(zvei_freq[0])]); /* Weiterschieben der energy-Eintraege, Ruecksetzen Feld [0] */ memmove(energy + 1, energy, sizeof(energy) - sizeof(energy[0])); energy[0] = 0; /* Weiterschieben der tenergy-Spalten, Ruecksetzen Spalte [0] */ memmove(tenergy + 1, tenergy, sizeof(tenergy) - sizeof(tenergy[0])); memset(tenergy, 0, sizeof(tenergy[0])); tote = 0; for( i = 0; i < 2*sizeof(zvei_freq)/sizeof(zvei_freq[0]) ; i++ ) { tote += totte[i]; } if(false) { // DEBUG printf("ZVEI: Energies: %8.5f\n0->%8.5f\t1->%8.5f\t2->%8.5f\n3->%8.5f\t4->%8.5f\t5->%8.5f\n6->%8.5f\t7->%8.5f\t" "8->%8.5f\n9->%8.5f\t10(2800)->%8.5f\t11(810)->%8.5f\n12(675)->%8.5f\t13(1240)->%8.5f\t14(w)->%8.5f\n15(NULL)->%8.5f\t16(1860)->%8.5f\t17(825)->%8.5f\n18(2280)->%8.5f\t19(1010)->%8.5f\n\n", tote, totte[0], totte[1], totte[2], totte[3], totte[4], totte[5], totte[6], totte[7], totte[8], totte[9], totte[10], totte[11], totte[12], totte[13], totte[14], totte[15], totte[16], totte[17], totte[18], totte[19]); } if(debugmodus > 9) { //DEBUG, USE WITH CAUTION, generates possibly big logfile on long runtime! ofstream outfile; outfile.open ("freq_dmp.txt", ios_base::app); outfile << tote << "|"; for(unsigned int count = 0; count < sizeof(zvei_freq)/sizeof(zvei_freq[0]); count++) { outfile << (int)totte[count] << "|"; } outfile << endl; outfile.close(); } // kein groesster index gefunden -> -1 zurueckgeben /*if ((i = find_max_index(totte, -1, -1)) < 0) { //return -1; } */ found_tones[0] = find_max_index(totte, -1, -1); // groesste Energie found_tones[1] = find_max_index(totte, found_tones[0], -1); // zweitgroesste Energie found_tones[2] = find_max_index(totte, found_tones[0], found_tones[1]); // drittgroesste Energie found_tones[3] = (int) totte[found_tones[0]]; // Energie I found_tones[4] = (int) totte[found_tones[1]]; // Energie II found_tones[5] = (int) totte[found_tones[2]]; // Energie III found_tones[6] = (int) tote; // Total Energie if(false) { // DEBUG cout << "process_block/found_tones: " << endl; cout << found_tones[0] << " -> " << totte[found_tones[0]] << ", " << found_tones[1] << " -> " << totte[found_tones[1]] << ", " << found_tones[2] << " -> " << totte[found_tones[2]] << endl; cout << found_tones[3] << ", " << found_tones[4] << ", " << "Squelch: " << (squelch * found_tones[6]) << " (" << (found_tones[3] > (squelch * found_tones[6])) << ")" << endl << endl; } if(false) { // DEBUG cout << "Tone index: " << found_tones[0] << " above squelch: " << (found_tones[3] > (squelch * found_tones[6])) << endl; } // Energielevel passen nicht (hier ist der Energielevel des gefundenen Tons kleiner als 40% der Gesamtenergie, zu geringer Rauschabstand) //if ((tote * 0.4) > totte[index1]) return -1; return found_tones; } /** * @brief finds maximum energy from energies matrix given by MonitorModuleZVEI::process_block() * @param totte energies matrix created in MonitorModuleZVEI::process_block() * @return index pointing to frequency holding maximum energy/-1 if problem/filter */ int MonitorModuleZVEI::find_max_index(const float *totte, int index1, int index2) { float en = 0; int index = -1; int i; /* Ermitteln des Index' fuer den (erst-, zweit-, dritt-) groessten Eintrag */ for (i = 0; i < (int)(sizeof(zvei_freq)/sizeof(zvei_freq[0])); i++) { if (totte[i] > en && i != index1 && i != index2){ en = totte[i]; index = i; } } /* en *= 0.25; // sirenenton ab 0.8 detektiert - Gruetze irgendwo/Algorithmus sinnvoll? for (i = 0; i < 16; i++) { if (index != i && totte[i] > en) return -1; } */ return index; } /** * @brief finds a digit out of o block of seven buffers; must be same digit four times following for detection */ int MonitorModuleZVEI::fuzzyseven() { int tone0count = 0; int fail = 0; int tone0 = detected_seven[(seven_count + 1) % 7][0]; if(debugmodus > 5) { cout << endl; for(int i=0; i<7; i++) { cout << detected_seven[(seven_count + i + 1) % 7][0] << " "; } } if(detected_seven[(seven_count + 1) % 7][0] == -1) { return -1; // deleted entry, already being detected } if(detected_seven[(seven_count + 1) % 7][3] < (squelch * detected_seven[(seven_count + 1) % 7][6])) { if(debugmodus > 3) { cout << "SQUELCH (" << detected_seven[(seven_count + 1) % 7][0] << ")!" << endl; } return -1; // Rauschsperre zu } for(int i = 0; i < 5; i++) { if(detected_seven[(seven_count + i + 1) % 7][0] == tone0) { tone0count++; } else { fail++; } if(debugmodus > 6) { cout << "tone0count: " << tone0count << " " << "(" << tone0 << ")"; } if(tone0count == 4) { return tone0; } } return -1; } /** * @brief checks zvei tones for correctness */ bool MonitorModuleZVEI::zvei_ok() { // Geloeschte Folge oder Pause in der Tonfolge: for(unsigned int i = 0; i < maxlength; i++) { if(zvei_folge[i] == -1 || zvei_folge[i] == -2) { return false; } } // Fehlerfall: Doppeleintraege for(int i = 0; i < 4; i++) { if(zvei_folge[i] == zvei_folge[i+1]) { return false; } } // sonst: ok. return true; } /** * @brief output alarm/ZVEI-Tonfolge to connected clients (NO storing of data!) * @param Adresse ZVEI-Tonfolge * @param typ alarm type [0|1|2] * @param Text free text (human readable type) */ void MonitorModuleZVEI::DisplayResult(std::string Adresse,int typ, std::string Text) { std::string alarmTypString ; std::string jetzt ; char dateStr[9]; char timeStr[9]; alarmTypString = convertIntToString(typ) ; // aktuelle Uhrzeit holen (Klartext & unix timestamp) currentTime(jetzt) ; struct tm* tm_time= localtime(&m_time) ; // FIXME warum nur ein zweistelliges Jahr? strftime(dateStr,9,"%d.%m.%y" ,tm_time) ; strftime(timeStr,9,"%H:%M:%S" ,tm_time) ; ModuleResultBase *pRes =new ModuleResultBase() ; pRes->set("timestamp",jetzt); pRes->set("uhrzeit",timeStr) ; pRes->set("datum",dateStr) ; pRes->set("servernamehex",m_serverNameHex); pRes->set("channelnamehex",m_channelNameHex); pRes->set("channelnum",convertIntToString(m_iChannelNum)); pRes->set("typ","zvei"); pRes->set("zvei",Adresse) ; pRes->set("weckton",alarmTypString) ; pRes->set("text",Text) ; pRes->Dump(); GlobalDispatcher->addResult(pRes) ; } /** * @brief output alarm/ZVEI-Tonfolge to some storage engine (NO displaying!) * @param Adresse ZVEI-Tonfolge * @param typ alarm type [0|1|2] * @param text free text (human readable type) */ void MonitorModuleZVEI::StoreResult(std::string Adresse,int typ, std::string text) { }