From 578411d875c3e603f33da08ff96bfd0f9221becb Mon Sep 17 00:00:00 2001 From: Bob Kenny Date: Wed, 20 Jan 2016 01:15:15 -0500 Subject: [PATCH 1/2] Beginning parsing of Dreamstation headers --- .../SleepLib/loader_plugins/prs1_loader.cpp | 81 ++++++++++++++++--- .../SleepLib/loader_plugins/prs1_loader.h | 2 +- 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp b/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp index 2d8b930d..a23dd232 100644 --- a/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp +++ b/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp @@ -1809,7 +1809,7 @@ bool PRS1Import::ParseSummaryF5V1() return true; } -bool PRS1Import::ParseSummaryF6() +bool PRS1Import::ParseSummaryF0V6() { // DreamStation machines... @@ -1825,12 +1825,75 @@ bool PRS1Import::ParseSummaryF6() CPAPMode cpapmode = MODE_UNKNOWN; - int imin_epap = data[0x3]; - int imax_epap = data[0x4]; - int imin_ps = data[0x5]; - int imax_ps = data[0x6]; - int imax_pressure = data[0x2]; + int imin_epap = 0; + int imax_epap = 0; + int imin_ps = 0; + int imax_ps = 0; + int imax_pressure = 0; + int duration = 0; + // in 'data', we start with 3 bytes that don't follow the pattern + // pattern is varNumber, dataSize, dataValue(dataSize) + // examples, 0x0d 0x02 0x28 0xC8 , or 0x0a 0x01 0x64, + // first, verify that this dataSize is where we expect + // each var pair in headerblock should be (indexByte, valueByte) + if ( 0x01 != summary->m_headerblock[1 * 2] ) { + return false; //nope, not here + qDebug() << "PRS1Loader::ParseSummaryF0V6=" << "Bad datablock length"; + } + int dataBlockSize = summary->m_headerblock[1 * 2 + 1]; + int zero = 0; + const unsigned char *dataPtr; + // start at 3rd byte ; did we go past the end? ; increment for dataSize + varNumberByte + dataSizeByte + for ( dataPtr = data + 3; dataPtr < (data + 3 + dataBlockSize); dataPtr+= dataPtr[1] + 2) { + switch( *dataPtr) { + case 10: // 0x0a + cpapmode = MODE_CPAP; //might be C_CHECK? + if (dataPtr[1] != 1) qDebug() << "PRS1Loader::ParseSummaryF0V6=" << "Bad CPAP value"; + imin_epap = dataPtr[2]; + break; + case 13: // 0x0d + cpapmode = MODE_APAP; //might be C_CHECK? + if (dataPtr[1] != 2) qDebug() << "PRS1Loader::ParseSummaryF0V6=" << "Bad APAP value"; + imin_epap = dataPtr[2]; + imax_epap = dataPtr[3]; + break; + default: + // have not found this before + qDebug() << "PRS1Loader::ParseSummaryF0V6=" << "Unknown datablock value:" << (zero + *dataPtr) ; + } + } + // now we encounter yet a different format of data + const unsigned char *data2Ptr = data + 3 + dataBlockSize; + + switch(*data2Ptr){ + case 1: + //don't know yet. data size is the '1' plus 16 bytes + data2Ptr += 5; + break; + case 3: + //don't know yet. data size is the '3' plus 4 bytes + data2Ptr += 5; + break; + case 4: + // have seen multiple of these....may have to add them? + duration += ( data2Ptr[3] << 8 ) + data2Ptr[2]; + data2Ptr += 3; + break; + case 5: + //don't know yet. data size is the '5' plus 4 bytes + data2Ptr += 5; + break; + case 8: + //don't know yet. data size is the '8' plus 20 bytes (might be a '0' in here...not enough different types found yet) + data2Ptr += 21; + break; + default: + qDebug() << "PRS1Loader::ParseSummaryF0V6=" << "Unknown datablock2 value:" << (zero + *dataPtr) ; + } + +// need to use the proper data + return true; } bool PRS1Import::ParseSummary() @@ -1858,6 +1921,8 @@ bool PRS1Import::ParseSummary() case 0: if (summary->familyVersion == 4) { return ParseSummaryF0V4(); + } else if (summary->familyVersion == 6) { + return ParseSummaryF0V6(); } else { return ParseSummaryF0(); } @@ -1870,8 +1935,6 @@ bool PRS1Import::ParseSummary() } else { return ParseSummaryF5V1(); } - case 6: - ParseSummaryF6(); default: ; } @@ -2381,7 +2444,7 @@ QList PRS1Loader::ParseFile(QString path) delete chunk; return CHUNKS; } - char * header2 = chunk->m_headerblock.data(); + unsigned char * header2 = (unsigned char*) chunk->m_headerblock.data(); // Checksum the whole header for (int i=0; i < h2len-1; ++i) csum += header2[i]; diff --git a/sleepyhead/SleepLib/loader_plugins/prs1_loader.h b/sleepyhead/SleepLib/loader_plugins/prs1_loader.h index 68b6283d..6e8dbdcd 100644 --- a/sleepyhead/SleepLib/loader_plugins/prs1_loader.h +++ b/sleepyhead/SleepLib/loader_plugins/prs1_loader.h @@ -127,7 +127,7 @@ public: bool ParseSummaryF3(); bool ParseSummaryF5V0(); bool ParseSummaryF5V1(); - bool ParseSummaryF6(); + bool ParseSummaryF0V6(); //! \brief Parse a single data chunk from a .002 file containing event data for a standard system one machine From fa0a84ef127aa16244e4916b253719cb02e001f2 Mon Sep 17 00:00:00 2001 From: Bob Kenny Date: Wed, 20 Jan 2016 19:55:15 -0500 Subject: [PATCH 2/2] Finished first Dreamstation parsing .001 attempt --- .../SleepLib/loader_plugins/prs1_loader.cpp | 80 ++++++++++++------- 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp b/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp index a23dd232..d30ae194 100644 --- a/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp +++ b/sleepyhead/SleepLib/loader_plugins/prs1_loader.cpp @@ -1830,6 +1830,8 @@ bool PRS1Import::ParseSummaryF0V6() int imin_ps = 0; int imax_ps = 0; int imax_pressure = 0; + int min_pressure = 0; + int max_pressure = 0; int duration = 0; // in 'data', we start with 3 bytes that don't follow the pattern @@ -1855,8 +1857,8 @@ bool PRS1Import::ParseSummaryF0V6() case 13: // 0x0d cpapmode = MODE_APAP; //might be C_CHECK? if (dataPtr[1] != 2) qDebug() << "PRS1Loader::ParseSummaryF0V6=" << "Bad APAP value"; - imin_epap = dataPtr[2]; - imax_epap = dataPtr[3]; + min_pressure = dataPtr[2]; + max_pressure = dataPtr[3]; break; default: // have not found this before @@ -1865,34 +1867,58 @@ bool PRS1Import::ParseSummaryF0V6() } // now we encounter yet a different format of data const unsigned char *data2Ptr = data + 3 + dataBlockSize; + // pattern is byte/data, where length of data depends on value of 'byte' + bool data2Done = false; + while (!data2Done) { + switch(*data2Ptr){ + case 0: + //this appears to be the last one. '0' plus 5 bytes **eats crc** without checking + data2Ptr += 4; + data2Ptr += 2; //this is the **CRC**?? + data2Done = true; //hope this is always there, since we don't have blocksize from header + break; + case 1: + //don't know yet. data size is the '1' plus 16 bytes + data2Ptr += 5; + break; + case 2: + //don't know yet. data size is the '2' plus 16 bytes + data2Ptr += 3; + break; + case 3: + //don't know yet. data size is the '3' plus 4 bytes + // have seen multiple of these....may have to add them? + data2Ptr += 5; + break; + case 4: + // have seen multiple of these....may have to add them? + duration += ( data2Ptr[3] << 8 ) + data2Ptr[2]; + data2Ptr += 3; + break; + case 5: + //don't know yet. data size is the '5' plus 4 bytes + data2Ptr += 5; + break; + case 8: + //don't know yet. data size is the '8' plus 27 bytes (might be a '0' in here...not enough different types found yet) + data2Ptr += 28; + break; + default: + qDebug() << "PRS1Loader::ParseSummaryF0V6=" << "Unknown datablock2 value:" << (zero + *dataPtr) ; + } + } +// need to populate summary-> - switch(*data2Ptr){ - case 1: - //don't know yet. data size is the '1' plus 16 bytes - data2Ptr += 5; - break; - case 3: - //don't know yet. data size is the '3' plus 4 bytes - data2Ptr += 5; - break; - case 4: - // have seen multiple of these....may have to add them? - duration += ( data2Ptr[3] << 8 ) + data2Ptr[2]; - data2Ptr += 3; - break; - case 5: - //don't know yet. data size is the '5' plus 4 bytes - data2Ptr += 5; - break; - case 8: - //don't know yet. data size is the '8' plus 20 bytes (might be a '0' in here...not enough different types found yet) - data2Ptr += 21; - break; - default: - qDebug() << "PRS1Loader::ParseSummaryF0V6=" << "Unknown datablock2 value:" << (zero + *dataPtr) ; + summary->duration = duration; + session->settings[CPAP_Mode] = (int)cpapmode; + if (cpapmode == MODE_CPAP) { + session->settings[CPAP_Pressure] = imin_epap/10.0f; + + } else if (cpapmode == MODE_APAP) { + session->settings[CPAP_PressureMin] = min_pressure; + session->settings[CPAP_PressureMax] = max_pressure; } -// need to use the proper data return true; }