Initial Weinmann Support, Pressure Relief Fixes, Pressure String Fixes

This commit is contained in:
Mark Watkins 2014-08-03 23:00:13 +10:00
parent 740de82170
commit 5e5bcd9e4a
37 changed files with 1540 additions and 412 deletions

View File

@ -12,4 +12,5 @@ TRANSLATIONS += \
Translations/Svenska.se.ts \ Translations/Svenska.se.ts \
Translations/Espaniol.es.ts \ Translations/Espaniol.es.ts \
Translations/Bulgarian.bg.ts \ Translations/Bulgarian.bg.ts \
Translations/English.en_UK.ts Translations/English.en_UK.ts \
Translations/Portugues.pt.ts

View File

@ -95,6 +95,7 @@ const QString STR_MACH_ResMed = "ResMed";
const QString STR_MACH_PRS1 = "PRS1"; const QString STR_MACH_PRS1 = "PRS1";
const QString STR_MACH_Journal = "Journal"; const QString STR_MACH_Journal = "Journal";
const QString STR_MACH_Intellipap = "Intellipap"; const QString STR_MACH_Intellipap = "Intellipap";
const QString STR_MACH_Weinmann= "Weinmann";
const QString STR_MACH_FPIcon = "FPIcon"; const QString STR_MACH_FPIcon = "FPIcon";
const QString STR_MACH_MSeries = "MSeries"; const QString STR_MACH_MSeries = "MSeries";
const QString STR_MACH_CMS50 = "CMS50"; const QString STR_MACH_CMS50 = "CMS50";

View File

@ -959,7 +959,9 @@ bool Day::removeSession(Session *sess)
QString Day::getCPAPMode() QString Day::getCPAPMode()
{ {
CPAPMode mode = (CPAPMode)(int)settings_max(CPAP_Mode); Q_ASSERT(machine_type() == MT_CPAP);
CPAPMode mode = (CPAPMode)(int)qRound(settings_wavg(CPAP_Mode));
if (mode == MODE_CPAP) { if (mode == MODE_CPAP) {
return QObject::tr("Fixed"); return QObject::tr("Fixed");
} else if (mode == MODE_APAP) { } else if (mode == MODE_APAP) {
@ -968,6 +970,8 @@ QString Day::getCPAPMode()
return QObject::tr("Fixed Bi-Level"); return QObject::tr("Fixed Bi-Level");
} else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) { } else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) {
return QObject::tr("Auto Bi-Level (Fixed PS)"); return QObject::tr("Auto Bi-Level (Fixed PS)");
} else if (mode == MODE_BILEVEL_AUTO_VARIABLE_PS) {
return QObject::tr("Auto Bi-Level (Variable PS)");
} else if (mode == MODE_ASV) { } else if (mode == MODE_ASV) {
return QObject::tr("ASV Fixed EPAP"); return QObject::tr("ASV Fixed EPAP");
} else if (mode == MODE_ASV_VARIABLE_EPAP) { } else if (mode == MODE_ASV_VARIABLE_EPAP) {
@ -976,23 +980,49 @@ QString Day::getCPAPMode()
return STR_TR_Unknown; return STR_TR_Unknown;
} }
QString Day::getPressureRelief()
{
CPAPLoader * loader = qobject_cast<CPAPLoader *>(machine->loader());
if (!loader) return STR_MessageBox_Error;
QString pr_str;
ChannelID pr_level_chan = loader->PresReliefLevel();
ChannelID pr_mode_chan = loader->PresReliefMode();
if ((pr_level_chan != NoChannel) && settingExists(pr_level_chan)) {
int pr_level = qRound(settings_wavg(pr_level_chan));
int pr_mode = qRound(settings_wavg(pr_mode_chan));
pr_str = QObject::tr("%1%2").arg(loader->PresReliefLabel()).
arg(schema::channel[pr_mode_chan].option(pr_mode));
if (pr_mode > 0) pr_str += QString(" %1").arg(schema::channel[pr_level_chan].option(pr_level));
} else pr_str = STR_TR_None;
return pr_str;
}
QString Day::getPressureSettings() QString Day::getPressureSettings()
{ {
Q_ASSERT(machine_type() == MT_CPAP);
CPAPMode mode = (CPAPMode)(int)settings_max(CPAP_Mode); CPAPMode mode = (CPAPMode)(int)settings_max(CPAP_Mode);
QString units = schema::channel[CPAP_Pressure].units(); QString units = schema::channel[CPAP_Pressure].units();
if (mode == MODE_CPAP) { if (mode == MODE_CPAP) {
return QObject::tr("%1 %2").arg(settings_min(CPAP_Pressure)).arg(units); return QObject::tr("Fixed %1 (%2)").arg(settings_min(CPAP_Pressure)).arg(units);
} else if (mode == MODE_APAP) { } else if (mode == MODE_APAP) {
return QObject::tr("%1-%2 %3").arg(settings_min(CPAP_PressureMin)).arg(settings_max(CPAP_PressureMax)).arg(units); return QObject::tr("Min %1 Max %2 (%3)").arg(settings_min(CPAP_PressureMin)).arg(settings_max(CPAP_PressureMax)).arg(units);
} else if (mode == MODE_BILEVEL_FIXED ) { } else if (mode == MODE_BILEVEL_FIXED ) {
return QObject::tr("%1-%2 %3").arg(settings_min(CPAP_EPAP),0,'f',1).arg(settings_max(CPAP_IPAP),0,'f',1).arg(units); return QObject::tr("IPAP %1 EPAP %2 (%3)").arg(settings_min(CPAP_EPAP),0,'f',1).arg(settings_max(CPAP_IPAP),0,'f',1).arg(units);
} else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) { } else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) {
return QObject::tr("PS %3 over %1-%2 %4 ").arg(settings_min(CPAP_EPAPLo),0,'f',1).arg(settings_max(CPAP_IPAPHi),0,'f',1).arg(settings_max(CPAP_PS),0,'f',1).arg(units); return QObject::tr("PS %3 over %1-%2 (%4)").arg(settings_min(CPAP_EPAPLo),0,'f',1).arg(settings_max(CPAP_IPAPHi),0,'f',1).arg(settings_max(CPAP_PS),0,'f',1).arg(units);
} else if (mode == MODE_BILEVEL_AUTO_VARIABLE_PS) {
return QObject::tr("Min EPAP %3 Max IPAP %4 PS %1-%2 (%5)").arg(settings_min(CPAP_PSMin),0,'f',1).arg(settings_max(CPAP_PSMax),0,'f',1).arg(settings_min(CPAP_EPAPLo),0,'f',1).arg(settings_max(CPAP_IPAPHi),0,'f',1).arg(units);
} else if (mode == MODE_ASV) { } else if (mode == MODE_ASV) {
return QObject::tr("PS %4-%5 over %1-%3 %6").arg(settings_min(CPAP_EPAP),0,'f',1).arg(settings_max(CPAP_IPAP),0,'f',1).arg(settings_min(CPAP_PSMin),0,'f',1).arg(settings_max(CPAP_PSMax),0,'f',1).arg(units); return QObject::tr("PS %4-%5 over %1-%3 (%6)").arg(settings_min(CPAP_EPAP),0,'f',1).arg(settings_max(CPAP_IPAP),0,'f',1).arg(settings_min(CPAP_PSMin),0,'f',1).arg(settings_max(CPAP_PSMax),0,'f',1).arg(units);
} else if (mode == MODE_ASV_VARIABLE_EPAP) { } else if (mode == MODE_ASV_VARIABLE_EPAP) {
return QObject::tr("PS %4-%5 over EPAP %1-%2 Max %3 %6").arg(settings_min(CPAP_EPAPLo),0,'f',1).arg(settings_max(CPAP_EPAPHi),0,'f',1).arg(settings_max(CPAP_IPAPHi),0,'f',1).arg(settings_min(CPAP_PSMin),0,'f',1).arg(settings_max(CPAP_PSMax),0,'f',1).arg(units); return QObject::tr("PS %4-%5 over EPAP %1-%2 Max %3 (%6)").arg(settings_min(CPAP_EPAPLo),0,'f',1).arg(settings_max(CPAP_EPAPHi),0,'f',1).arg(settings_max(CPAP_IPAPHi),0,'f',1).arg(settings_min(CPAP_PSMin),0,'f',1).arg(settings_max(CPAP_PSMax),0,'f',1).arg(units);
} }
return STR_TR_Unknown; return STR_TR_Unknown;

View File

@ -179,8 +179,11 @@ class Day
bool removeSession(Session *sess); bool removeSession(Session *sess);
// Some ugly CPAP specific stuff
QString getCPAPMode(); QString getCPAPMode();
QString getPressureRelief();
QString getPressureSettings(); QString getPressureSettings();
QList<Session *> sessions; QList<Session *> sessions;
protected: protected:

View File

@ -39,7 +39,7 @@ Q_OBJECT
virtual const QString &loaderName() { return cms50_class_name; } virtual const QString &loaderName() { return cms50_class_name; }
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_OXIMETER, cms50_class_name, QObject::tr("Contec"), QObject::tr("CMS50"), QString(), QString(), QObject::tr("CMS50"), QDateTime::currentDateTime(), cms50_data_version); return MachineInfo(MT_OXIMETER, 0, cms50_class_name, QObject::tr("Contec"), QObject::tr("CMS50"), QString(), QString(), QObject::tr("CMS50"), QDateTime::currentDateTime(), cms50_data_version);
} }

View File

@ -537,6 +537,7 @@ bool FPIconLoader::OpenFLW(Machine *mach, QString filename)
const int samples_per_block = 50; const int samples_per_block = 50;
const double rate = 1000.0 / double(samples_per_block); const double rate = 1000.0 / double(samples_per_block);
// F&P Overwrites this file, not appends to it. // F&P Overwrites this file, not appends to it.
flow = new EventList(EVL_Waveform, 1.0F, 0, 0, 0, rate); flow = new EventList(EVL_Waveform, 1.0F, 0, 0, 0, rate);
pressure = new EventList(EVL_Event, 0.01F, 0, 0, 0, rate * double(samples_per_block)); pressure = new EventList(EVL_Event, 0.01F, 0, 0, 0, rate * double(samples_per_block));

View File

@ -48,7 +48,7 @@ const QString fpicon_class_name = STR_MACH_FPIcon;
This is only relatively recent addition and still needs more work This is only relatively recent addition and still needs more work
*/ */
class FPIconLoader : public MachineLoader class FPIconLoader : public CPAPLoader
{ {
public: public:
FPIconLoader(); FPIconLoader();
@ -76,13 +76,23 @@ class FPIconLoader : public MachineLoader
//Machine *CreateMachine(QString serial); //Machine *CreateMachine(QString serial);
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_CPAP, fpicon_class_name, QObject::tr("Fisher & Paykel"), QString(), QString(), QString(), QObject::tr("ICON"), QDateTime::currentDateTime(), fpicon_data_version); return MachineInfo(MT_CPAP, 0, fpicon_class_name, QObject::tr("Fisher & Paykel"), QString(), QString(), QString(), QObject::tr("ICON"), QDateTime::currentDateTime(), fpicon_data_version);
} }
//! \brief Registers this MachineLoader with the master list, so F&P Icon data can load //! \brief Registers this MachineLoader with the master list, so F&P Icon data can load
static void Register(); static void Register();
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Now for some CPAPLoader overrides
////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual QString presRelType() { return QObject::tr(""); } // might not need this one
virtual ChannelID presRelSet() { return NoChannel; }
virtual ChannelID presRelLevel() { return NoChannel; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected: protected:
QDateTime readFPDateTime(quint8 *data); QDateTime readFPDateTime(quint8 *data);

View File

@ -17,6 +17,8 @@
extern QProgressBar *qprogress; extern QProgressBar *qprogress;
ChannelID INTP_SmartFlexMode, INTP_SmartFlexLevel;
Intellipap::Intellipap(MachineID id) Intellipap::Intellipap(MachineID id)
: CPAP(id) : CPAP(id)
{ {
@ -339,6 +341,7 @@ int IntellipapLoader::Open(QString path)
sess->AddEventList(CPAP_Snore, EVL_Event); sess->AddEventList(CPAP_Snore, EVL_Event);
sess->AddEventList(CPAP_Obstructive, EVL_Event); sess->AddEventList(CPAP_Obstructive, EVL_Event);
sess->AddEventList(CPAP_VSnore, EVL_Event);
sess->AddEventList(CPAP_Hypopnea, EVL_Event); sess->AddEventList(CPAP_Hypopnea, EVL_Event);
sess->AddEventList(CPAP_NRI, EVL_Event); sess->AddEventList(CPAP_NRI, EVL_Event);
sess->AddEventList(CPAP_LeakFlag, EVL_Event); sess->AddEventList(CPAP_LeakFlag, EVL_Event);
@ -371,6 +374,8 @@ int IntellipapLoader::Open(QString path)
sid = 0; sid = 0;
SessionID lastsid = 0; SessionID lastsid = 0;
int last_minp=0, last_maxp=0, last_ps=0, last_pres = 0;
for (int i = 0; i < recs; i++) { for (int i = 0; i < recs; i++) {
// convert timestamp to real epoch // convert timestamp to real epoch
ts1 = ((m_buffer[pos] << 24) | (m_buffer[pos + 1] << 16) | (m_buffer[pos + 2] << 8) | m_buffer[pos + 3]) + ep; ts1 = ((m_buffer[pos] << 24) | (m_buffer[pos + 1] << 16) | (m_buffer[pos + 2] << 8) | m_buffer[pos + 3]) + ep;
@ -393,32 +398,21 @@ int IntellipapLoader::Open(QString path)
int pres = m_buffer[pos + 0xd]; int pres = m_buffer[pos + 0xd];
if (mode >= MODE_BILEVEL_FIXED) { if (mode >= MODE_BILEVEL_FIXED) {
sess->settings[CPAP_EPAP] = float(minp) / 10.0;
sess->settings[CPAP_IPAP] = float(maxp) / 10.0;
sess->settings[CPAP_PS] = float(ps) / 10.0;
sess->eventlist[CPAP_IPAP][0]->AddEvent(time, float(pres) / 10.0);
sess->eventlist[CPAP_EPAP][0]->AddEvent(time, float(pres-ps) / 10.0);
rampval = maxp; rampval = maxp;
} else { } else {
sess->eventlist[CPAP_Pressure][0]->AddEvent(time, float(pres) / 10.0); // current pressure
rampval = minp; rampval = minp;
}
if (mode == MODE_APAP) {
sess->settings[CPAP_PressureMin] = float(minp) / 10.0;
sess->settings[CPAP_PressureMax] = float(maxp) / 10.0;
} else if (mode == MODE_CPAP) {
sess->settings[CPAP_Pressure] = float(maxp) / 10.0;
}
}
qint64 rs = rampstart[sid]; qint64 rs = rampstart[sid];
if (pres < rampval) { if (pres < rampval) {
if (!rs) { if (!rs) {
// ramp started
// int rv = pres-rampval;
// double ramp =
rampstart[sid] = time; rampstart[sid] = time;
} }
rampend[sid] = time; rampend[sid] = time;
@ -430,8 +424,34 @@ int IntellipapLoader::Open(QString path)
int duration = (time - rs) / 1000L; int duration = (time - rs) / 1000L;
sess->eventlist[CPAP_Ramp][0]->AddEvent(time, duration); sess->eventlist[CPAP_Ramp][0]->AddEvent(time, duration);
rampstart[sid] = 0; rampstart.remove(sid);
//rampend[sid] = 0; // don't need to rampend.remove(sid);
}
}
// Do this after ramp, because ramp calcs might need to insert interpolated pressure samples
if (mode >= MODE_BILEVEL_FIXED) {
sess->settings[CPAP_EPAP] = float(minp) / 10.0;
sess->settings[CPAP_IPAP] = float(maxp) / 10.0;
sess->settings[CPAP_PS] = float(ps) / 10.0;
sess->eventlist[CPAP_IPAP][0]->AddEvent(time, float(pres) / 10.0);
sess->eventlist[CPAP_EPAP][0]->AddEvent(time, float(pres-ps) / 10.0);
// rampval = maxp;
} else {
sess->eventlist[CPAP_Pressure][0]->AddEvent(time, float(pres) / 10.0); // current pressure
// rampval = minp;
if (mode == MODE_APAP) {
sess->settings[CPAP_PressureMin] = float(minp) / 10.0;
sess->settings[CPAP_PressureMax] = float(maxp) / 10.0;
} else if (mode == MODE_CPAP) {
sess->settings[CPAP_Pressure] = float(maxp) / 10.0;
} }
} }
@ -446,6 +466,10 @@ int IntellipapLoader::Open(QString path)
sess->eventlist[CPAP_Snore][0]->AddEvent(time, m_buffer[pos + 0x4]); //4/5?? sess->eventlist[CPAP_Snore][0]->AddEvent(time, m_buffer[pos + 0x4]); //4/5??
if (m_buffer[pos+0x4] > 0) {
sess->eventlist[CPAP_VSnore][0]->AddEvent(time, m_buffer[pos + 0x5]);
}
// 0x0f == Leak Event // 0x0f == Leak Event
// 0x04 == Snore? // 0x04 == Snore?
if (m_buffer[pos + 0xf] > 0) { // Leak Event if (m_buffer[pos + 0xf] > 0) { // Leak Event
@ -477,6 +501,7 @@ int IntellipapLoader::Open(QString path)
EventDataType mv = tv * rr; // MinuteVent=TidalVolume * Respiratory Rate EventDataType mv = tv * rr; // MinuteVent=TidalVolume * Respiratory Rate
sess->eventlist[CPAP_MinuteVent][0]->AddEvent(time, mv / 1000.0); sess->eventlist[CPAP_MinuteVent][0]->AddEvent(time, mv / 1000.0);
break; break;
} else {
} }
lastsid = sid; lastsid = sid;
} }
@ -521,14 +546,12 @@ int IntellipapLoader::Open(QString path)
// sess->really_set_last(last); // sess->really_set_last(last);
sess->settings[CPAP_PresReliefType] = (PRTypes)PR_SMARTFLEX; sess->settings[INTP_SmartFlexLevel] = smartflex;
sess->settings[CPAP_PresReliefSet] = smartflex;
if (smartflexmode == 0) { if (smartflexmode == 0) {
sess->settings[CPAP_PresReliefMode] = PM_FullTime; sess->settings[INTP_SmartFlexMode] = PM_FullTime;
} else { } else {
sess->settings[CPAP_PresReliefMode] = PM_RampOnly; sess->settings[INTP_SmartFlexMode] = PM_RampOnly;
} }
sess->settings[CPAP_RampPressure] = ramp_pressure; sess->settings[CPAP_RampPressure] = ramp_pressure;
@ -567,4 +590,23 @@ void IntellipapLoader::Register()
RegisterLoader(new IntellipapLoader()); RegisterLoader(new IntellipapLoader());
//InitModelMap(); //InitModelMap();
intellipap_initialized = true; intellipap_initialized = true;
using namespace schema;
Channel * chan = nullptr;
channel.add(GRP_CPAP, chan = new Channel(INTP_SmartFlexMode = 0x1165, SETTING, SESSION,
"INTPSmartFlexMode", QObject::tr("SmartFlex Mode"),
QObject::tr("Intellipap pressure relief mode."),
QObject::tr("SmartFlex Mode"),
"", DEFAULT, Qt::green));
chan->addOption(0, STR_TR_Off);
chan->addOption(1, QObject::tr("Ramp Only"));
chan->addOption(2, QObject::tr("Full Time"));
channel.add(GRP_CPAP, chan = new Channel(INTP_SmartFlexLevel = 0x1169, SETTING, SESSION,
"INTPSmartFlexLevel", QObject::tr("SmartFlex Level"),
QObject::tr("Intellipap pressure relief level."),
QObject::tr("SmartFlex Level"),
"", DEFAULT, Qt::green));
} }

View File

@ -39,6 +39,8 @@ class Intellipap: public CPAP
const int intellipap_load_buffer_size = 1024 * 1024; const int intellipap_load_buffer_size = 1024 * 1024;
extern ChannelID INTP_SmartFlexMode;
extern ChannelID INTP_SmartFlexLevel;
const QString intellipap_class_name = STR_MACH_Intellipap; const QString intellipap_class_name = STR_MACH_Intellipap;
@ -46,7 +48,7 @@ const QString intellipap_class_name = STR_MACH_Intellipap;
\brief Loader for DeVilbiss Intellipap Auto data \brief Loader for DeVilbiss Intellipap Auto data
This is only relatively recent addition and still needs more work This is only relatively recent addition and still needs more work
*/ */
class IntellipapLoader : public MachineLoader class IntellipapLoader : public CPAPLoader
{ {
public: public:
IntellipapLoader(); IntellipapLoader();
@ -71,8 +73,18 @@ class IntellipapLoader : public MachineLoader
static void Register(); static void Register();
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_CPAP, intellipap_class_name, QObject::tr("DeVilbiss"), QString(), QString(), QString(), QObject::tr("Intellipap"), QDateTime::currentDateTime(), intellipap_data_version); return MachineInfo(MT_CPAP, 0, intellipap_class_name, QObject::tr("DeVilbiss"), QString(), QString(), QString(), QObject::tr("Intellipap"), QDateTime::currentDateTime(), intellipap_data_version);
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Now for some CPAPLoader overrides
////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual QString presRelLabel() { return QObject::tr("SmartFlex Settings"); } // might not need this one
virtual ChannelID presReliefMode() { return INTP_SmartFlexMode; }
virtual ChannelID presRelLevel() { return INTP_SmartFlexLevel; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected: protected:
QString last; QString last;

View File

@ -41,7 +41,7 @@ Q_OBJECT
// Machine *CreateMachine(); // Machine *CreateMachine();
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_OXIMETER, md300w1_class_name, QObject::tr("ChoiceMMed"), QString(), QString(), QString(), QObject::tr("MD300"), QDateTime::currentDateTime(), md300w1_data_version); return MachineInfo(MT_OXIMETER, 0, md300w1_class_name, QObject::tr("ChoiceMMed"), QString(), QString(), QString(), QObject::tr("MD300"), QDateTime::currentDateTime(), md300w1_data_version);
} }

View File

@ -63,7 +63,7 @@ class MSeriesLoader : public MachineLoader
// Machine *CreateMachine(QString serial); // Machine *CreateMachine(QString serial);
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_CPAP, mseries_class_name, QObject::tr("Respironics"), QString(), QString(), QString(), QObject::tr("M-Series"), QDateTime::currentDateTime(), mseries_data_version); return MachineInfo(MT_CPAP, 0, mseries_class_name, QObject::tr("Respironics"), QString(), QString(), QString(), QObject::tr("M-Series"), QDateTime::currentDateTime(), mseries_data_version);
} }
//! \brief Register this Module to the list of Loaders, so it knows to search for PRS1 data. //! \brief Register this Module to the list of Loaders, so it knows to search for PRS1 data.

View File

@ -99,6 +99,10 @@ crc_t CRC16(const unsigned char *data, size_t data_len)
} }
#endif #endif
enum FlexMode { FLEX_None, FLEX_CFlex, FLEX_CFlexPlus, FLEX_AFlex, FLEX_RiseTime, FLEX_BiFlex, FLEX_Unknown };
PRS1::PRS1(MachineID id): CPAP(id) PRS1::PRS1(MachineID id): CPAP(id)
{ {
} }
@ -213,6 +217,8 @@ int PRS1Loader::Open(QString path)
if ((filename[0] == 'P') && (isdigit(filename[1])) && (isdigit(filename[2]))) { if ((filename[0] == 'P') && (isdigit(filename[1])) && (isdigit(filename[2]))) {
SerialNumbers.push_back(filename); SerialNumbers.push_back(filename);
} else if (isdigit(filename[0]) && isdigit(filename[1])) {
SerialNumbers.push_back(filename);
} else if (filename.toLower() == "last.txt") { // last.txt points to the current serial number } else if (filename.toLower() == "last.txt") { // last.txt points to the current serial number
QString file = fi.canonicalFilePath(); QString file = fi.canonicalFilePath();
QFile f(file); QFile f(file);
@ -359,7 +365,7 @@ int PRS1Loader::OpenMachine(Machine *m, QString path)
if ((filename[0].toLower() == 'p') && (isdigit(filename[1]))) { if ((filename[0].toLower() == 'p') && (isdigit(filename[1]))) {
// p0, p1, p2.. etc.. folders contain the session data // p0, p1, p2.. etc.. folders contain the session data
paths.push_back(fi.canonicalFilePath()); paths.push_back(fi.canonicalFilePath());
} else if (filename.toLower() == "properties.txt") { } else if ((filename.toLower() == "properties.txt") || (filename.toLower() == "prop.txt")) {
ParseProperties(m, fi.canonicalFilePath()); ParseProperties(m, fi.canonicalFilePath());
} else if (filename.toLower() == "e") { } else if (filename.toLower() == "e") {
// Error files.. // Error files..
@ -839,19 +845,22 @@ bool PRS1SessionData::ParseF0Events()
EventList *LEAK = session->AddEventList(CPAP_LeakTotal, EVL_Event); EventList *LEAK = session->AddEventList(CPAP_LeakTotal, EVL_Event);
EventList *SNORE = session->AddEventList(CPAP_Snore, EVL_Event); EventList *SNORE = session->AddEventList(CPAP_Snore, EVL_Event);
EventList *CA = nullptr; //session->AddEventList(CPAP_ClearAirway, EVL_Event); EventList *PP = session->AddEventList(CPAP_PressurePulse, EVL_Event);
EventList *VS = nullptr; EventList *RE = session->AddEventList(CPAP_RERA, EVL_Event);
EventList *VS2 = nullptr; EventList *CA = session->AddEventList(CPAP_ClearAirway, EVL_Event);
EventList *FL = nullptr; EventList *FL = session->AddEventList(CPAP_FlowLimit, EVL_Event);
EventList *RE = nullptr; EventList *VS = session->AddEventList(CPAP_VSnore, EVL_Event);
EventList *VS2 = session->AddEventList(CPAP_VSnore2, EVL_Event);
Code[12] = session->AddEventList(PRS1_0B, EVL_Event);
Code[17] = session->AddEventList(PRS1_0E, EVL_Event);
Code[20] = session->AddEventList(CPAP_LargeLeak, EVL_Event);
EventList *PRESSURE = nullptr; EventList *PRESSURE = nullptr;
EventList *EPAP = nullptr; EventList *EPAP = nullptr;
EventList *IPAP = nullptr; EventList *IPAP = nullptr;
EventList *PS = nullptr; EventList *PS = nullptr;
EventList *PP = nullptr;
//session->AddEventList(CPAP_VSnore, EVL_Event); //session->AddEventList(CPAP_VSnore, EVL_Event);
//EventList * VS=session->AddEventList(CPAP_Obstructive, EVL_Event); //EventList * VS=session->AddEventList(CPAP_Obstructive, EVL_Event);
unsigned char lastcode3 = 0, lastcode2 = 0, lastcode = 0; unsigned char lastcode3 = 0, lastcode2 = 0, lastcode = 0;
@ -961,9 +970,6 @@ bool PRS1SessionData::ParseF0Events()
break; break;
case 0x04: // Pressure Pulse case 0x04: // Pressure Pulse
if (!PP) {
if (!(PP = session->AddEventList(CPAP_PressurePulse, EVL_Event))) { return false; }
}
PP->AddEvent(t, buffer[pos++]); PP->AddEvent(t, buffer[pos++]);
break; break;
@ -972,10 +978,6 @@ bool PRS1SessionData::ParseF0Events()
data[0] = buffer[pos++]; data[0] = buffer[pos++];
tt = t - (qint64(data[0]) * 1000L); tt = t - (qint64(data[0]) * 1000L);
if (!RE) {
if (!(RE = session->AddEventList(CPAP_RERA, EVL_Event))) { return false; }
}
RE->AddEvent(tt, data[0]); RE->AddEvent(tt, data[0]);
break; break;
@ -989,10 +991,6 @@ bool PRS1SessionData::ParseF0Events()
data[0] = buffer[pos++]; data[0] = buffer[pos++];
tt = t - (qint64(data[0]) * 1000L); tt = t - (qint64(data[0]) * 1000L);
if (!CA) {
if (!(CA = session->AddEventList(CPAP_ClearAirway, EVL_Event))) { return false; }
}
CA->AddEvent(tt, data[0]); CA->AddEvent(tt, data[0]);
break; break;
@ -1006,10 +1004,6 @@ bool PRS1SessionData::ParseF0Events()
data[0] = buffer[pos++]; data[0] = buffer[pos++];
tt = t - (qint64(data[0]) * 1000L); tt = t - (qint64(data[0]) * 1000L);
if (!FL) {
if (!(FL = session->AddEventList(CPAP_FlowLimit, EVL_Event))) { return false; }
}
FL->AddEvent(tt, data[0]); FL->AddEvent(tt, data[0]);
break; break;
@ -1017,19 +1011,11 @@ bool PRS1SessionData::ParseF0Events()
data[0] = buffer[pos++]; data[0] = buffer[pos++];
data[1] = buffer[pos++]; data[1] = buffer[pos++];
if (!Code[12]) {
if (!(Code[12] = session->AddEventList(PRS1_0B, EVL_Event))) { return false; }
}
// FIXME // FIXME
Code[12]->AddEvent(t, data[0]); Code[12]->AddEvent(t, data[0]);
break; break;
case 0x0d: // Vibratory Snore case 0x0d: // Vibratory Snore
if (!VS) {
if (!(VS = session->AddEventList(CPAP_VSnore, EVL_Event))) { return false; }
}
VS->AddEvent(t, 0); VS->AddEvent(t, 0);
break; break;
@ -1041,10 +1027,6 @@ bool PRS1SessionData::ParseF0Events()
SNORE->AddEvent(t, data[1]); SNORE->AddEvent(t, data[1]);
if (data[1] > 0) { if (data[1] > 0) {
if (!VS2) {
if (!(VS2 = session->AddEventList(CPAP_VSnore2, EVL_Event))) { return false; }
}
VS2->AddEvent(t, data[1]); VS2->AddEvent(t, data[1]);
} }
@ -1061,10 +1043,6 @@ bool PRS1SessionData::ParseF0Events()
//pos+=2; //pos+=2;
data[2] = buffer[pos++]; data[2] = buffer[pos++];
if (!Code[17]) {
if (!(Code[17] = session->AddEventList(PRS1_0E, EVL_Event))) { return false; }
}
tdata = unsigned(data[1]) << 8 | unsigned(data[0]); tdata = unsigned(data[1]) << 8 | unsigned(data[0]);
Code[17]->AddEvent(t, tdata); Code[17]->AddEvent(t, tdata);
//qDebug() << hex << data[0] << data[1] << data[2]; //qDebug() << hex << data[0] << data[1] << data[2];
@ -1078,10 +1056,6 @@ bool PRS1SessionData::ParseF0Events()
pos += 2; pos += 2;
data[1] = buffer[pos++]; data[1] = buffer[pos++];
if (!Code[20]) {
if (!(Code[20] = session->AddEventList(CPAP_LargeLeak, EVL_Event))) { return false; }
}
tt = t - qint64(data[1]) * 1000L; tt = t - qint64(data[1]) * 1000L;
Code[20]->AddEvent(tt, data[0]); Code[20]->AddEvent(tt, data[0]);
break; break;
@ -1129,20 +1103,193 @@ bool PRS1SessionData::ParseF0Events()
bool PRS1SessionData::ParseCompliance() bool PRS1SessionData::ParseCompliance()
{ {
// Bleh!! There is probably 10 different formats for these useless piece of junk machines
if (!compliance) return false; if (!compliance) return false;
return true; return true;
} }
bool PRS1SessionData::ParseSummary() bool PRS1SessionData::ParseSummaryF0()
{ {
if (!summary) return false;
if (summary->m_data.size() < 59) {
return false;
}
const unsigned char * data = (unsigned char *)summary->m_data.constData(); const unsigned char * data = (unsigned char *)summary->m_data.constData();
CPAPMode cpapmode = MODE_UNKNOWN;
switch (data[0x02]) { // PRS1 mode // 0 = CPAP, 2 = APAP
case 0x00:
cpapmode = MODE_CPAP;
break;
case 0x01:
cpapmode = MODE_BILEVEL_FIXED;
break;
case 0x02:
cpapmode = MODE_APAP;
break;
case 0x03:
cpapmode = MODE_BILEVEL_AUTO_VARIABLE_PS;
}
EventDataType min_pressure = float(data[0x03]) / 10.0;
EventDataType max_pressure = float(data[0x04]) / 10.0;
EventDataType ps = float(data[0x05]) / 10.0; // pressure support
if (cpapmode == MODE_CPAP) {
session->settings[CPAP_Pressure] = min_pressure;
} else if (cpapmode == MODE_APAP) {
session->settings[CPAP_PressureMin] = min_pressure;
session->settings[CPAP_PressureMax] = max_pressure;
} else if (cpapmode == MODE_BILEVEL_FIXED) {
session->settings[CPAP_EPAP] = min_pressure;
session->settings[CPAP_IPAP] = max_pressure;
session->settings[CPAP_PS] = ps;
} else if (cpapmode == MODE_BILEVEL_AUTO_VARIABLE_PS) {
session->settings[CPAP_EPAPLo] = min_pressure;
session->settings[CPAP_EPAPHi] = max_pressure - 2.0;
session->settings[CPAP_IPAPLo] = min_pressure + 2.0;
session->settings[CPAP_IPAPHi] = max_pressure;
session->settings[CPAP_PSMin] = 2.0f;
session->settings[CPAP_PSMax] = ps;
}
session->settings[CPAP_Mode] = (int)cpapmode;
int ramp_time = data[0x06];
EventDataType ramp_pressure = float(data[0x07]) / 10.0;
session->settings[CPAP_RampTime] = (int)ramp_time;
session->settings[CPAP_RampPressure] = ramp_pressure;
// Tubing lock has no setting byte
// int SysOneResistance = (data[0x0a] & 7);
// bool SysOneResistanceOn = (data[0x0a] & 0x40) ? true : false;
// bool SysOneResistanceLock = (data[0x0a] & 0x80) ? true : false;
// int humidifier = (data[0x09] & 7);
// bool autoOn = (data[0x0b] & 0x40) ? true : false; //?
// Menu Options
session->settings[PRS1_SysLock] = (bool) (data[0x0a] & 0x80); // System One Resistance Lock Setting
session->settings[PRS1_SysOneResistSet] = (int)data[0x0a] & 7; // SYstem One Resistance setting value
session->settings[PRS1_SysOneResistStat] = (bool) (data[0x0a] & 0x40); // System One Resistance Status bit
session->settings[PRS1_HoseDiam] = (data[0x0a] & 0x08) ? QObject::tr("15mm") : QObject::tr("22mm");
session->settings[PRS1_AutoOn] = (bool) (data[0x0b] & 0x40);
session->settings[PRS1_AutoOff] = (bool) (data[0x0c] & 0x10);
session->settings[PRS1_MaskAlert] = (bool) (data[0x0c] & 0x08);
session->settings[PRS1_ShowAHI] = (bool) (data[0x0c] & 0x04);
session->settings[PRS1_HumidStatus] = (bool)(data[0x09] & 0x80); // Humidifier Connected
session->settings[PRS1_HumitSetting] = (int)(data[0x09] & 7); // Humidifier Value
// session->
quint8 flex = data[0x08];
int flexlevel = flex & 0x03;
FlexMode flexmode = FLEX_Unknown;
// 88 CFlex+ / AFlex (depending on CPAP mode)
// 80 CFlex
// 00 NoFlex
// c0 Split CFlex then None
// c8 Split CFlex+ then None
flex &= 0xf8;
bool split = false;
if (flex & 0x40) { // This bit defines the Flex setting for the CPAP component of the Split night
split = true;
}
if (flex & 0x80) { // CFlex bit
if (flex & 0x10) {
flexmode = FLEX_RiseTime;
} else if (flex & 8) { // Plus bit
if (split || (cpapmode == MODE_CPAP)) {
flexmode = FLEX_CFlexPlus;
} else if (cpapmode == MODE_APAP) {
flexmode = FLEX_AFlex;
}
} else {
// CFlex bits refer to Rise Time on BiLevel machines
flexmode = (cpapmode >= MODE_BILEVEL_FIXED) ? FLEX_BiFlex : FLEX_CFlex;
}
} else flexmode = FLEX_None;
session->settings[PRS1_FlexMode] = (int)flexmode;
session->settings[PRS1_FlexLevel] = (int)flexlevel;
int duration = data[0x14] | data[0x15] << 8;
session->set_last(qint64(summary->timestamp+duration) * 1000L);
return true;
}
bool PRS1SessionData::ParseSummaryF0V4()
{
return true;
}
bool PRS1SessionData::ParseSummaryF3()
{
const unsigned char * data = (unsigned char *)summary->m_data.constData();
EventDataType epap = data[0x04] | (data[0x05] << 8);
EventDataType ipap = data[0x06] | (data[0x07] << 8);
EventDataType f1 = data[0x08] | (data[0x09] << 8);
return true;
}
bool PRS1SessionData::ParseSummaryF5()
{
return true;
}
bool PRS1SessionData::ParseSummary()
{
// Family 0 = XPAP
// Family 3 = BIPAP AVAPS
// Family 5 = BIPAP AutoSV
if (!summary) return false;
if (summary->m_data.size() < 59) {
//return false;
}
session->setPhysMax(CPAP_LeakTotal, 120);
session->setPhysMin(CPAP_LeakTotal, 0);
session->setPhysMax(CPAP_Pressure, 25);
session->setPhysMin(CPAP_Pressure, 4);
session->setPhysMax(CPAP_IPAP, 25);
session->setPhysMin(CPAP_IPAP, 4);
session->setPhysMax(CPAP_EPAP, 25);
session->setPhysMin(CPAP_EPAP, 4);
session->setPhysMax(CPAP_PS, 25);
session->setPhysMin(CPAP_PS, 0);
session->set_first(qint64(summary->timestamp) * 1000L); session->set_first(qint64(summary->timestamp) * 1000L);
if (this->session->session() == 3880) {
int i=5;
}
switch (summary->family) {
case 0:
return ParseSummaryF0();
case 3:
return ParseSummaryF3();
case 5:
return ParseSummaryF5();
}
const unsigned char * data = (unsigned char *)summary->m_data.constData();
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// ASV Codes (Family 5) Recheck 17/10/2013 // ASV Codes (Family 5) Recheck 17/10/2013
// These are all confirmed off Encore reports // These are all confirmed off Encore reports
@ -1226,22 +1373,23 @@ bool PRS1SessionData::ParseSummary()
session->settings[CPAP_Pressure] = (EventDataType)min; session->settings[CPAP_Pressure] = (EventDataType)min;
} }
if (data[offset + 0x08] & 0x80) { // Flex Setting if (data[offset + 0x08] & 0x80) { // Flex Setting
if (data[offset + 0x08] & 0x08) { if (data[offset + 0x08] & 0x08) {
if (max > 0) { if (max > 0) {
if (summary->family == 5) { if (summary->family == 5) {
session->settings[CPAP_PresReliefType] = (int)PR_BIFLEX; session->settings[PRS1_FlexMode] = (int)PR_BIFLEX;
} else { } else {
session->settings[CPAP_PresReliefType] = (int)PR_AFLEX; session->settings[PRS1_FlexMode] = (int)PR_AFLEX;
} }
} else { session->settings[CPAP_PresReliefType] = (int)PR_CFLEXPLUS; } } else { session->settings[PRS1_FlexMode] = (int)PR_CFLEXPLUS; }
} else { session->settings[CPAP_PresReliefType] = (int)PR_CFLEX; } } else { session->settings[PRS1_FlexMode] = (int)PR_CFLEX; }
} else { session->settings[CPAP_PresReliefType] = (int)PR_NONE; } } else { session->settings[PRS1_FlexMode] = (int)PR_NONE; }
session->settings[CPAP_PresReliefMode] = (int)PM_FullTime; // only has one mode // Map the channels
session->settings[PRS1_FlexLevel] = (int)(data[offset + 0x08] & 7);
session->settings[CPAP_PresReliefSet] = (int)(data[offset + 0x08] & 7);
session->settings[PRS1_SysLock] = (data[offset + 0x0a] & 0x80) == 0x80; session->settings[PRS1_SysLock] = (data[offset + 0x0a] & 0x80) == 0x80;
session->settings[PRS1_HoseDiam] = ((data[offset + 0x0a] & 0x08) ? "15mm" : "22mm"); session->settings[PRS1_HoseDiam] = ((data[offset + 0x0a] & 0x08) ? "15mm" : "22mm");
session->settings[PRS1_AutoOff] = (data[offset + 0x0c] & 0x10) == 0x10; session->settings[PRS1_AutoOff] = (data[offset + 0x0c] & 0x10) == 0x10;
@ -1274,16 +1422,7 @@ bool PRS1SessionData::ParseSummary()
// Set recommended Graph values.. // Set recommended Graph values..
session->setPhysMax(CPAP_LeakTotal, 120);
session->setPhysMin(CPAP_LeakTotal, 0);
session->setPhysMax(CPAP_Pressure, 25);
session->setPhysMin(CPAP_Pressure, 4);
session->setPhysMax(CPAP_IPAP, 25);
session->setPhysMin(CPAP_IPAP, 4);
session->setPhysMax(CPAP_EPAP, 25);
session->setPhysMin(CPAP_EPAP, 4);
session->setPhysMax(CPAP_PS, 25);
session->setPhysMin(CPAP_PS, 0);
if (summary->family == 0 && summary->familyVersion == 0) { if (summary->family == 0 && summary->familyVersion == 0) {
@ -1307,32 +1446,34 @@ bool PRS1SessionData::ParseEvents()
qDebug() << "Unknown PRS1 familyVersion" << event->familyVersion; qDebug() << "Unknown PRS1 familyVersion" << event->familyVersion;
return false; return false;
} }
if (res) { if (res) {
if (session->count(CPAP_IPAP) > 0) { if (session->count(CPAP_IPAP) > 0) {
if (session->settings[CPAP_Mode].toInt() != (int)MODE_ASV) { // if (session->settings[CPAP_Mode].toInt() != (int)MODE_ASV) {
session->settings[CPAP_Mode] = MODE_BILEVEL_FIXED; // session->settings[CPAP_Mode] = MODE_BILEVEL_FIXED;
} // }
if (session->settings[CPAP_PresReliefType].toInt() != PR_NONE) { // if (session->settings[CPAP_PresReliefType].toInt() != PR_NONE) {
session->settings[CPAP_PresReliefType] = PR_BIFLEX; // session->settings[CPAP_PresReliefType] = PR_BIFLEX;
} // }
EventDataType min = session->settings[CPAP_PressureMin].toDouble(); // EventDataType min = session->settings[CPAP_PressureMin].toDouble();
EventDataType max = session->settings[CPAP_PressureMax].toDouble(); // EventDataType max = session->settings[CPAP_PressureMax].toDouble();
session->settings[CPAP_EPAP] = min; // session->settings[CPAP_EPAP] = min;
session->settings[CPAP_IPAP] = max; // session->settings[CPAP_IPAP] = max;
session->settings[CPAP_PS] = max - min; // session->settings[CPAP_PS] = max - min;
session->settings.erase(session->settings.find(CPAP_PressureMin)); // session->settings.erase(session->settings.find(CPAP_PressureMin));
session->settings.erase(session->settings.find(CPAP_PressureMax)); // session->settings.erase(session->settings.find(CPAP_PressureMax));
session->m_valuesummary.erase(session->m_valuesummary.find(CPAP_Pressure)); // session->m_valuesummary.erase(session->m_valuesummary.find(CPAP_Pressure));
session->m_wavg.erase(session->m_wavg.find(CPAP_Pressure)); // session->m_wavg.erase(session->m_wavg.find(CPAP_Pressure));
session->m_min.erase(session->m_min.find(CPAP_Pressure)); // session->m_min.erase(session->m_min.find(CPAP_Pressure));
session->m_max.erase(session->m_max.find(CPAP_Pressure)); // session->m_max.erase(session->m_max.find(CPAP_Pressure));
session->m_gain.erase(session->m_gain.find(CPAP_Pressure)); // session->m_gain.erase(session->m_gain.find(CPAP_Pressure));
} else { } else {
session->setSummaryOnly(true);
if (!session->settings.contains(CPAP_Pressure) && !session->settings.contains(CPAP_PressureMin)) { if (!session->settings.contains(CPAP_Pressure) && !session->settings.contains(CPAP_PressureMin)) {
session->settings[CPAP_BrokenSummary] = true; session->settings[CPAP_BrokenSummary] = true;
@ -1691,6 +1832,7 @@ void InitModelMap()
ModelMap[0x37] = "RemStar BiPAP Auto with Bi-Flex"; ModelMap[0x37] = "RemStar BiPAP Auto with Bi-Flex";
ModelMap[0x38] = "RemStar Plus :("; // 150/250P/260P ModelMap[0x38] = "RemStar Plus :("; // 150/250P/260P
ModelMap[0x41] = "BiPAP autoSV Advanced"; ModelMap[0x41] = "BiPAP autoSV Advanced";
ModelMap[0x4E] = "BiPAP AVAPS";
} }
bool initialized = false; bool initialized = false;
@ -1709,11 +1851,41 @@ void PRS1Loader::Register()
initialized = true; initialized = true;
channel.add(GRP_CPAP, new Channel(CPAP_PressurePulse = 0x1009, MINOR_FLAG, SESSION, channel.add(GRP_CPAP, new Channel(CPAP_PressurePulse = 0x1009, MINOR_FLAG, SESSION,
"PressurePulse", QObject::tr("Pressure Pulse"), "PressurePulse",
QObject::tr("Pressure Pulse"),
QObject::tr("A pulse of pressure 'pinged' to detect a closed airway."), QObject::tr("A pulse of pressure 'pinged' to detect a closed airway."),
QObject::tr("PP"), STR_UNIT_EventsPerHour, DEFAULT, QColor("dark red"))); QObject::tr("PP"),
STR_UNIT_EventsPerHour, DEFAULT, QColor("dark red")));
Channel * chan = nullptr;
channel.add(GRP_CPAP, chan = new Channel(PRS1_FlexMode = 0xe105, SETTING, SESSION,
"PRS1FlexMode", QObject::tr("Flex Mode"),
QObject::tr("PRS1 pressure relief mode."),
QObject::tr("Flex Mode"),
"", DEFAULT, Qt::green));
chan->addOption(FLEX_None, STR_TR_None);
chan->addOption(FLEX_CFlex, QObject::tr("C-Flex"));
chan->addOption(FLEX_CFlexPlus, QObject::tr("C-Flex+"));
chan->addOption(FLEX_AFlex, QObject::tr("A-Flex"));
chan->addOption(FLEX_RiseTime, QObject::tr("Rise Time"));
chan->addOption(FLEX_BiFlex, QObject::tr("Bi-Flex"));
channel.add(GRP_CPAP, chan = new Channel(PRS1_FlexLevel = 0xe106, SETTING, SESSION,
"PRS1FlexSet",
QObject::tr("Flex Level"),
QObject::tr("PRS1 pressure relief setting."),
QObject::tr("Flex Level"),
"", DEFAULT, Qt::blue));
chan->addOption(0, STR_TR_Off);
chan->addOption(1, QObject::tr("x1"));
chan->addOption(2, QObject::tr("x2"));
chan->addOption(3, QObject::tr("x3"));
QString unknowndesc=QObject::tr("Unknown PRS1 Code %1"); QString unknowndesc=QObject::tr("Unknown PRS1 Code %1");
QString unknownname=QObject::tr("PRS1_%1"); QString unknownname=QObject::tr("PRS1_%1");
QString unknownshort=QObject::tr("PRS1_%1"); QString unknownshort=QObject::tr("PRS1_%1");

View File

@ -115,6 +115,12 @@ public:
bool ParseEvents(); bool ParseEvents();
bool ParseWaveforms(); bool ParseWaveforms();
bool ParseSummaryF0();
bool ParseSummaryF0V4();
bool ParseSummaryF3();
bool ParseSummaryF5();
//! \brief Parse a single data chunk from a .002 file containing event data for a standard system one machine //! \brief Parse a single data chunk from a .002 file containing event data for a standard system one machine
bool ParseF0Events(); bool ParseF0Events();
@ -174,7 +180,7 @@ protected:
/*! \class PRS1Loader /*! \class PRS1Loader
\brief Philips Respironics System One Loader Module \brief Philips Respironics System One Loader Module
*/ */
class PRS1Loader : public MachineLoader class PRS1Loader : public CPAPLoader
{ {
public: public:
PRS1Loader(); PRS1Loader();
@ -199,9 +205,12 @@ class PRS1Loader : public MachineLoader
static void Register(); static void Register();
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_CPAP, prs1_class_name, QObject::tr("Philips Respironics"), QString(), QString(), QString(), QObject::tr("System One"), QDateTime::currentDateTime(), prs1_data_version); return MachineInfo(MT_CPAP, 0, prs1_class_name, QObject::tr("Philips Respironics"), QString(), QString(), QString(), QObject::tr("System One"), QDateTime::currentDateTime(), prs1_data_version);
} }
virtual QString PresReliefLabel() { return QObject::tr(""); }
virtual ChannelID PresReliefMode() { return PRS1_FlexMode; }
virtual ChannelID PresReliefLevel() { return PRS1_FlexLevel; }
QHash<SessionID, PRS1FileGroup*> prs1sessions; QHash<SessionID, PRS1FileGroup*> prs1sessions;

View File

@ -34,6 +34,9 @@ QHash<QString, QList<quint16> > Resmed_Model_Map;
const QString STR_UnknownModel = "Resmed S9 ???"; const QString STR_UnknownModel = "Resmed S9 ???";
ChannelID RMS9_EPR, RMS9_EPRLevel;
// Return the model name matching the supplied model number. // Return the model name matching the supplied model number.
const QString & lookupModel(quint16 model) const QString & lookupModel(quint16 model)
{ {
@ -274,26 +277,38 @@ void ResmedLoader::ParseSTR(Machine *mach, QStringList strfiles)
if ((sig = str.lookupSignal(CPAP_PSMin))) { if ((sig = str.lookupSignal(CPAP_PSMin))) {
R.min_ps = EventDataType(sig->data[rec]) * sig->gain + sig->offset; R.min_ps = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
} }
EventDataType epr = -1, epr_level = -1;
if ((sig = str.lookupSignal(RMS9_EPR))) { if ((sig = str.lookupSignal(RMS9_EPR))) {
R.epr = EventDataType(sig->data[rec]) * sig->gain + sig->offset; epr= EventDataType(sig->data[rec]) * sig->gain + sig->offset;
} }
if ((sig = str.lookupSignal(RMS9_EPRLevel))) { if ((sig = str.lookupSignal(RMS9_EPRLevel))) {
R.epr_level = EventDataType(sig->data[rec]) * sig->gain + sig->offset; epr_level= EventDataType(sig->data[rec]) * sig->gain + sig->offset;
}
if ((epr >= 0) && (epr_level >= 0)) {
R.epr_level = epr_level;
R.epr = epr;
} else {
if (epr >= 0) {
static bool warn=false;
if (!warn) { // just nag once
qDebug() << "If you can read this, please tell Jedimark you found a ResMed with EPR but no EPR_LEVEL so he can remove this warning";
warn = true;
}
R.epr = (epr > 0) ? 1 : 0;
R.epr_level = epr;
} else if (epr_level >= 0) {
R.epr_level = epr_level;
R.epr = (epr_level > 0) ? 1 : 0;
}
} }
if ((sig = str.lookupSignal(CPAP_Mode))) { if ((sig = str.lookupSignal(CPAP_Mode))) {
int mod = EventDataType(sig->data[rec]) * sig->gain + sig->offset; int mod = EventDataType(sig->data[rec]) * sig->gain + sig->offset;
CPAPMode mode; CPAPMode mode;
// if (R.epap > 0) {
// if (R.max_epap < 0) R.max_epap = R.epap;
// if (R.min_epap < 0) R.min_epap = R.epap;
// }
// if (R.ipap > 0) {
// if (R.max_ipap < 0) R.max_ipap = R.ipap;
// if (R.min_ipap < 0) R.min_ipap = R.ipap;
// }
if (mod >= 8) { // mod 8 == vpap adapt variable epap if (mod >= 8) { // mod 8 == vpap adapt variable epap
mode = MODE_ASV_VARIABLE_EPAP; mode = MODE_ASV_VARIABLE_EPAP;
if (!haveipap) { if (!haveipap) {
@ -720,12 +735,9 @@ void ResmedImport::run()
if (R.epr >= 0) { if (R.epr >= 0) {
sess->settings[RMS9_EPR] = (int)R.epr; sess->settings[RMS9_EPR] = (int)R.epr;
sess->settings[CPAP_PresReliefType] = (int)PR_EPR;
sess->settings[CPAP_PresReliefSet] = (int)R.epr;
} }
if (R.epr_level >= 0) { if (R.epr_level >= 0) {
sess->settings[RMS9_EPRLevel] = (int)R.epr_level; sess->settings[RMS9_EPRLevel] = (int)R.epr_level;
sess->settings[CPAP_PresReliefMode] = (int)R.epr_level;
} }
// Ignore all the rest of the sumary data, because there is enough available to calculate it with higher accuracy. // Ignore all the rest of the sumary data, because there is enough available to calculate it with higher accuracy.
@ -788,12 +800,9 @@ void ResmedImportStage2::run()
if (R.mode >= 0) sess->settings[CPAP_Mode] = R.mode; if (R.mode >= 0) sess->settings[CPAP_Mode] = R.mode;
if (R.epr >= 0) { if (R.epr >= 0) {
sess->settings[RMS9_EPR] = (int)R.epr; sess->settings[RMS9_EPR] = (int)R.epr;
sess->settings[CPAP_PresReliefType] = (int)PR_EPR;
sess->settings[CPAP_PresReliefSet] = (int)R.epr;
} }
if (R.epr_level >= 0) { if (R.epr_level >= 0) {
sess->settings[RMS9_EPRLevel] = (int)R.epr_level; sess->settings[RMS9_EPRLevel] = (int)R.epr_level;
sess->settings[CPAP_PresReliefMode] = (int)R.epr_level;
} }
if (R.leakmax >= 0) sess->setMax(CPAP_Leak, R.leakmax); if (R.leakmax >= 0) sess->setMax(CPAP_Leak, R.leakmax);
if (R.leakmax >= 0) sess->setMin(CPAP_Leak, 0); if (R.leakmax >= 0) sess->setMin(CPAP_Leak, 0);
@ -2341,6 +2350,21 @@ void ResInitModelMap()
resmed_codes[CPAP_PressureMin].push_back("Min tryck"); resmed_codes[CPAP_PressureMin].push_back("Min tryck");
} }
//<channel id="0xe201" class="setting" scope="!session" name="EPR" details="EPR Mode" label="EPR Mode" type="integer">
// <Option id="0" value="Off"/>
// <Option id="1" value="Ramp Only"/>
// <Option id="2" value="Full Time"/>
// <Option id="3" value="EPR?"/>
//</channel>
//<channel id="0xe202" class="setting" scope="!session" name="EPRLevel" details="EPR Setting" label="EPR Setting" type="integer">
// <Option id="0" value="0"/>
// <Option id="1" value="1"/>
// <Option id="2" value="2"/>
// <Option id="3" value="3"/>
//</channel>
ChannelID ResmedLoader::PresReliefMode() { return RMS9_EPR; }
ChannelID ResmedLoader::PresReliefLevel() { return RMS9_EPRLevel; }
bool resmed_initialized = false; bool resmed_initialized = false;
void ResmedLoader::Register() void ResmedLoader::Register()
@ -2351,6 +2375,31 @@ void ResmedLoader::Register()
RegisterLoader(new ResmedLoader()); RegisterLoader(new ResmedLoader());
ResInitModelMap(); ResInitModelMap();
resmed_initialized = true; resmed_initialized = true;
using namespace schema;
Channel * chan = nullptr;
channel.add(GRP_CPAP, chan = new Channel(RMS9_EPR = 0xe201, SETTING, SESSION,
"EPR", QObject::tr("EPR Mode"),
QObject::tr("ResMed Exhale Pressure Relief Mode."),
QObject::tr("EPR Mode"),
"", DEFAULT, Qt::green));
chan->addOption(0, STR_TR_Off);
chan->addOption(1, QObject::tr("Ramp Only"));
chan->addOption(2, QObject::tr("Full Time"));
channel.add(GRP_CPAP, chan = new Channel(RMS9_EPRLevel = 0xe202, SETTING, SESSION,
"EPRLevel", QObject::tr("EPR Level"),
QObject::tr("Exhale Pressure Relief Level"),
QObject::tr("EPR Level"),
"", DEFAULT, Qt::blue));
chan->addOption(0, QObject::tr("0cmH2O"));
chan->addOption(1, QObject::tr("1cmH2O"));
chan->addOption(2, QObject::tr("2cmH2O"));
chan->addOption(3, QObject::tr("3cmH2O"));
chan->addOption(4, QObject::tr("Patient"));
} }
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -328,7 +328,7 @@ protected:
/*! \class ResmedLoader /*! \class ResmedLoader
\brief Importer for ResMed S9 Data \brief Importer for ResMed S9 Data
*/ */
class ResmedLoader : public MachineLoader class ResmedLoader : public CPAPLoader
{ {
friend class ResmedImport; friend class ResmedImport;
friend class ResmedImportStage2; friend class ResmedImportStage2;
@ -377,10 +377,20 @@ class ResmedLoader : public MachineLoader
bool LoadPLD(Session *sess, const QString & path); bool LoadPLD(Session *sess, const QString & path);
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_CPAP, resmed_class_name, QObject::tr("ResMed"), QString(), QString(), QString(), QObject::tr("S9"), QDateTime::currentDateTime(), resmed_data_version); return MachineInfo(MT_CPAP, 0, resmed_class_name, QObject::tr("ResMed"), QString(), QString(), QString(), QObject::tr("S9"), QDateTime::currentDateTime(), resmed_data_version);
} }
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Now for some CPAPLoader overrides
////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual QString PresReliefLabel() { return QObject::tr("EPR: "); }
virtual ChannelID PresReliefMode();
virtual ChannelID PresReliefLevel();
////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected: protected:
void ParseSTR(Machine *mach, QStringList strfiles); void ParseSTR(Machine *mach, QStringList strfiles);

View File

@ -36,7 +36,7 @@ class SomnoposeLoader : public MachineLoader
virtual const QString &loaderName() { return somnopose_class_name; } virtual const QString &loaderName() { return somnopose_class_name; }
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_POSITION, somnopose_class_name, QObject::tr("Somnopose"), QString(), QString(), QString(), QObject::tr("Somnopose Software"), QDateTime::currentDateTime(), somnopose_data_version); return MachineInfo(MT_POSITION, 0, somnopose_class_name, QObject::tr("Somnopose"), QString(), QString(), QString(), QObject::tr("Somnopose Software"), QDateTime::currentDateTime(), somnopose_data_version);
} }

View File

@ -0,0 +1,556 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*
* SleepLib (DeVilbiss) Weinmann Loader Implementation
* Notes: Weinmann requires the SmartLink attachment to access this data.
*
* Copyright (c) 2011-2014 Mark Watkins <jedimark@users.sourceforge.net>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the Linux
* distribution for more details. */
#include <QDir>
#include <QFile>
#include <QProgressBar>
#include <QDomDocument>
#include <QDomElement>
#include <QDomNode>
#include "weinmann_loader.h"
extern QProgressBar *qprogress;
Weinmann::Weinmann(MachineID id)
: CPAP(id)
{
}
Weinmann::~Weinmann()
{
}
WeinmannLoader::WeinmannLoader()
{
m_buffer = nullptr;
m_type = MT_CPAP;
}
WeinmannLoader::~WeinmannLoader()
{
}
bool WeinmannLoader::Detect(const QString & givenpath)
{
QDir dir(givenpath);
if (!dir.exists()) {
return false;
}
// Weinman has a...
if (!dir.cd("SOMNOsoft2")) {
return false;
}
// Check for the settings file inside the .. folder
if (!dir.exists("WM_DATA.TDF")) {
return false;
}
return true;
}
int WeinmannLoader::ParseIndex(QFile & wmdata)
{
QByteArray xml;
do {
xml += wmdata.readLine(250);
} while (!wmdata.atEnd());
QDomDocument index_xml("weinmann");
index_xml.setContent(xml);
QDomElement docElem = index_xml.documentElement();
QDomNode n = docElem.firstChild();
index.clear();
while (!n.isNull()) {
QDomElement e = n.toElement();
if (!e.isNull()) {
bool ok;
int val = e.attribute("val").toInt(&ok);
if (ok) {
index[e.attribute("name")] = val;
qDebug() << e.attribute("name") << "=" << hex << val;
}
}
n = n.nextSibling();
}
return index.size();
}
const QString DayComplianceCount = "DayComplianceCount";
const QString CompOffset = "DayComplianceOffset";
const QString FlowOffset = "TID_Flow_Offset";
const QString StatusOffset = "TID_Status_Offset";
const QString PresOffset = "TID_P_Offset";
const QString AMVOffset = "TID_AMV_Offset";
const QString EventsOffset = "TID_Events_Offset";
void HighPass(char * data, int samples, float cutoff, float dt)
{
float Y[samples];
for (int i=0; i < samples; ++i) Y[i] = 0.0f;
Y[0] = ((unsigned char *)data)[0] ;
float RC = 1.0 / (cutoff * 2 * 3.1415926);
float alpha = RC / (RC + dt);
for (int i=1; i < samples; ++i) {
float x = ((unsigned char *)data)[i] ;
float x1 = ((unsigned char *)data)[i-1] ;
Y[i] = alpha * (Y[i-1] + x - x1);
}
for (int i=0; i< samples; ++i) {
data[i] = Y[i];
}
}
int WeinmannLoader::Open(QString path)
{
QString newpath;
path = path.replace("\\", "/");
QString dirtag = "SOMNOsoft2";
if (path.endsWith("/" + dirtag)) {
return -1;
} else {
newpath = path + "/" + dirtag;
}
QFile wmdata(newpath + "/WM_DATA.TDF");
if (!wmdata.open(QFile::ReadOnly)) {
return -1;
}
int res = ParseIndex(wmdata);
if (res < 0) return -1;
MachineInfo info = newInfo();
info.serial = "141819";
Machine * mach = CreateMachine(info);
//////////////////////////////////////////////////////////////////////
// Read Day Compliance Information....
//////////////////////////////////////////////////////////////////////
int comp_start = index[CompOffset];
int comp_end = index[FlowOffset];
int comp_size = comp_end - comp_start;
unsigned char comp[comp_size];
memset((char *)comp, 0, comp_size);
wmdata.seek(comp_start);
wmdata.read((char *)comp, comp_size);
unsigned char * p = comp;
QDateTime dt_epoch(QDate(2000,1,1), QTime(0,0,0));
int epoch = dt_epoch.toTime_t();
epoch = 0;
float flow_sample_duration = 1000.0 / 5;
float pressure_sample_duration = 1000.0 / 2;
float amv_sample_duration = 200 * 10;
int c = index[DayComplianceCount];
for (int i=0; i < 5; i++) {
int year = QString().sprintf("%02i%02i", p[0], p[1]).toInt();
int month = p[2];
int day = p[3];
int hour = p[5];
int minute = p[6];
int second = p[7];
QDateTime date = QDateTime(QDate(year,month,day), QTime(hour,minute,second));
quint32 ts = date.toTime_t();
if (mach->SessionExists(ts)) continue;
Session * sess = new Session(mach, ts);
// Flow Waveform
quint32 fs = p[8] | p[9] << 8 | p[10] << 16 | p[11] << 24;
quint32 fl = p[0x44] | p[0x45] << 8 | p[0x46] << 16 | p[0x47] << 24;
// Status
quint32 ss = p[12] | p[13] << 8 | p[14] << 16 | p[15] << 24;
quint32 sl = p[0x48] | p[0x49] << 8 | p[0x4a] << 16 | p[0x4b] << 24;
// Pressure
quint32 ps = p[16] | p[17] << 8 | p[18] << 16 | p[19] << 24;
quint32 pl = p[0x4c] | p[0x4d] << 8 | p[0x4e] << 16 | p[0x4f] << 24;
// AMV
quint32 ms = p[20] | p[21] << 8 | p[22] << 16 | p[23] << 24;
quint32 ml = p[0x50] | p[0x51] << 8 | p[0x52] << 16 | p[0x53] << 24;
// Events
quint32 es = p[24] | p[25] << 8 | p[26] << 16 | p[27] << 24;
quint32 er = p[0x54] | p[0x55] << 8 | p[0x56] << 16 | p[0x57] << 24; // number of records
compinfo.append(CompInfo(sess, date, fs, fl, ss, sl, ps, pl, ms, ml, es, er));
int dur = fl / 5;
sess->really_set_first(qint64(ts) * 1000L);
sess->really_set_last(qint64(ts+dur) * 1000L);
sessions[ts] = sess;
qDebug() << date << ts << dur << QString().sprintf("%02i:%02i:%02i", dur / 3600, dur/60 % 60, dur % 60);
p += 0xd6;
}
//////////////////////////////////////////////////////////////////////
// Read Flow Waveform....
//////////////////////////////////////////////////////////////////////
int flowstart = index[FlowOffset];
int flowend = index[StatusOffset];
wmdata.seek(flowstart);
int flowsize = flowend - flowstart;
char data[flowsize];
memset((char *)data, 0, flowsize);
wmdata.read((char *)data, flowsize);
float dt = 1.0 / (1000.0 / flow_sample_duration); // samples per second
// Centre Waveform using High Pass Filter
HighPass(data, flowsize, 0.6, dt);
//////////////////////////////////////////////////////////////////////
// Read Status....
//////////////////////////////////////////////////////////////////////
int st_start = index[StatusOffset];
int st_end = index[PresOffset];
int st_size = st_end - st_start;
char st[st_size];
memset(st, 0, st_size);
wmdata.seek(st_start);
wmdata.read(st, st_size);
//////////////////////////////////////////////////////////////////////
// Read Mask Pressure....
//////////////////////////////////////////////////////////////////////
int pr_start = index[PresOffset];
int pr_end = index[AMVOffset];
int pr_size = pr_end - pr_start;
char pres[pr_size];
memset(pres, 0, pr_size);
wmdata.seek(pr_start);
wmdata.read(pres, pr_size);
//////////////////////////////////////////////////////////////////////
// Read AMV....
//////////////////////////////////////////////////////////////////////
int mv_start = index[AMVOffset];
int mv_end = index[EventsOffset];
int mv_size = mv_end - mv_start;
char mv[mv_size];
memset(mv, 0, mv_size);
wmdata.seek(mv_start);
wmdata.read(mv, mv_size);
//////////////////////////////////////////////////////////////////////
// Read Events....
//////////////////////////////////////////////////////////////////////
int ev_start = index[EventsOffset];
int ev_end = wmdata.size();
int ev_size = ev_end - ev_start;
unsigned char ev[ev_size];
memset((char *) ev, 0, ev_size);
wmdata.seek(ev_start);
wmdata.read((char *) ev, ev_size);
//////////////////////////////////////////////////////////////////////
// Process sessions
//////////////////////////////////////////////////////////////////////
for (int i=0; i< compinfo.size(); ++i) {
const CompInfo & ci = compinfo.at(i);
Session * sess = ci.session;
qint64 ti = sess->first();
EventList * flow = sess->AddEventList(CPAP_FlowRate, EVL_Waveform, 1.0, 0.0, 0.0, 0.0, flow_sample_duration);
flow->AddWaveform(ti, &data[ci.flow_start], ci.flow_size, (ci.flow_size/(1000.0/flow_sample_duration)) * 1000.0);
EventList * PR = sess->AddEventList(CPAP_MaskPressure, EVL_Waveform, 0.1f, 0.0, 0.0, 0.0, pressure_sample_duration);
PR->AddWaveform(ti, (unsigned char *)&pres[ci.pres_start], ci.pres_size, (ci.pres_size/(1000.0/pressure_sample_duration)) * 1000.0);
// Weinmann's MV graph is pretty dodgy... commenting this out and using my flow calced ones instead (the code below is mapped to snore for comparison purposes)
//EventList * MV = sess->AddEventList(CPAP_Snore, EVL_Waveform, 1.0f, 0.0, 0.0, 0.0, amv_sample_duration);
//MV->AddWaveform(ti, (unsigned char *)&mv[ci.amv_start], ci.amv_size, (ci.amv_size/(1000/amv_sample_duration)) * 1000L);
EventList * L = sess->AddEventList(CPAP_Leak, EVL_Event);
EventList * S = sess->AddEventList(CPAP_Snore, EVL_Event);
EventList * OA = sess->AddEventList(CPAP_Obstructive, EVL_Event);
EventList * A = sess->AddEventList(CPAP_Apnea, EVL_Event);
EventList * H = sess->AddEventList(CPAP_Hypopnea, EVL_Event);
EventList * FL = sess->AddEventList(CPAP_FlowLimit, EVL_Event);
EventList * VS = sess->AddEventList(CPAP_VSnore, EVL_Event);
quint64 tt = ti;
quint64 step = sess->length() / ci.event_recs;
unsigned char *p = &ev[ci.event_start];
for (quint32 j=0; j < ci.event_recs; ++j) {
QDate evdate = ci.time.date();
QTime evtime(p[1], p[2], p[3]);
if (evtime < ci.time.time()) {
evdate = evdate.addDays(1);
}
quint64 ts = QDateTime(evdate, evtime).toMSecsSinceEpoch();
// I think p[0] is amount of flow restriction..
unsigned char evcode = p[0];
EventStoreType data = p[4] | p[5] << 8;
if (evcode == '@') {
OA->AddEvent(ts,data/10.0);
} else if (evcode =='A') {
A->AddEvent(ts,data/10.0);
} else if (evcode == 'F') {
FL->AddEvent(ts,data/10.0);
} else if (evcode == '*') {
H->AddEvent(ts,data/10.0);
}
/* switch (evcode) {
case 0x03:
break;
case 0x04:
break;
case 0x08:
break;
case 0x09:
break;
case 0x0a:
break;
case 0x0b:
break;
case 0x0c:
break;
case 0x10:
break;
case 0x11:
break;
case 0x12:
break;
case 0x13:
S->AddEvent(ts, data);
break;
case 0x22:
// VS->AddEvent(ts, data/10.0);
break;
case 0x28:
VS->AddEvent(ts, data/10.0);
break;
case 'F':
FL->AddEvent(ts, data/10.0);
break;
case '@':
OA->AddEvent(ts, data/10.0);
break;
case '\'':
//A->AddEvent(ts, data/10.0);
break;
case 'a':
A->AddEvent(ts, data/10.0);
break;
case 'A':
// A->AddEvent(ts, data/10.0);
break;
case '*':
H->AddEvent(ts, data/10.0);
break;
case 'd':
break;
case 0x91:
break;
case 0x96:
break;
case 0x84:
break;
default:
qDebug() << (int)evcode << endl;
}*/
// S->AddEvent(ts, p[5]);
// p[5] == 0 corresponds to peak events
// p[5] == 1 corresponds to hypopnea/bstructive events
//if (p[5] == 2) OA->AddEvent(ts, p[4]);
// This is ugggggly...
tt += step;
p += 6;
}
sess->UpdateSummaries();
mach->AddSession(sess);
}
return 1;
/*
// Center the waveform
HighPass(data, flowsize, 0.6, dt);
EventList * flow = sess->AddEventList(CPAP_FlowRate, EVL_Waveform, 1.0, 0.0, 0.0, 0.0, sample_duration);
flow->AddWaveform(tt, (char *)data, flowsize, (flowsize/(1000/sample_duration)) * 1000L);
qint64 ti = tt;
for (int i=0; i < pr_size; ++i) {
EventStoreType c = ((unsigned char *)pres)[i];
PR->AddEvent(ti, c);
ti += sample_duration * 2.5; //46296296296296;
}
// Their calcs is uglier than mine!
EventList * MV = sess->AddEventList(CPAP_Snore, EVL_Event, 1.0);
ti = tt;
for (int i=0; i < mv_size; ++i) {
EventStoreType c = ((unsigned char *)mv)[i];
MV->AddEvent(ti, c);
ti += sample_duration * 9;
}
// Their calcs is uglier than mine!
EventList * ST = sess->AddEventList(CPAP_Leak, EVL_Event, 1.0);
int st_start = index[StatusOffset];
int st_end = index[PresOffset];
int st_size = st_end - st_start;
char st[st_size];
memset(st, 0, st_size);
wmdata.seek(st_start);
wmdata.read(st, st_size);
ti = tt;
for (int i=0; i < st_size; ++i) {
EventStoreType c = ((unsigned char *)st)[i];
// if (c & 0x80) {
ST->AddEvent(ti, c & 0x10);
// }
ti += sample_duration*4; // *9
}
// EventList * LEAK = sess->AddEventList(CPAP_Leak, EVL_Event);
// EventList * SNORE = sess->AddEventList(CPAP_Snore, EVL_Event);
// int ev_start = index[EventsOffset];
// int ev_end = wmdata.size();
// int ev_size = ev_end - ev_start;
// int recs = ev_size / 0x12;
// unsigned char ev[ev_size];
// memset((char *) ev, 0, ev_size);
// wmdata.seek(ev_start);
// wmdata.read((char *) ev, ev_size);
sess->really_set_last(flow->last());
// int pos = 0;
// ti = tt;
// // 6 byte repeating structure.. No Leaks :(
// do {
// //EventStoreType c = ((unsigned char*)ev)[pos+0]; // TV?
// //c = ((unsigned char*)ev)[pos+6]; // MV?
// EventStoreType c = ((EventStoreType*)ev)[pos+0];
// LEAK->AddEvent(ti, c);
// SNORE->AddEvent(ti, ((unsigned char*)ev)[pos+2]);
// pos += 0x6;
// ti += 30000;
// if (ti > sess->last())
// break;
// } while (pos < (ev_size - 0x12));
m->AddSession(sess);
sess->UpdateSummaries();
return 1;*/
}
bool weinmann_initialized = false;
void WeinmannLoader::Register()
{
if (weinmann_initialized) { return; }
qDebug() << "Registering WeinmannLoader";
RegisterLoader(new WeinmannLoader());
//InitModelMap();
weinmann_initialized = true;
using namespace schema;
Channel * chan = nullptr;
// channel.add(GRP_CPAP, chan = new Channel(INTP_SmartFlex = 0x1165, SETTING, SESSION,
// "INTPSmartFlex", QObject::tr("SmartFlex"),
// QObject::tr("Weinmann pressure relief setting."),
// QObject::tr("SmartFlex"),
// "", DEFAULT, Qt::green));
// chan->addOption(1, STR_TR_None);
}

View File

@ -0,0 +1,142 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*
* Weiman Loader Header
*
* Copyright (c) 2011-2014 Mark Watkins <jedimark@users.sourceforge.net>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the Linux
* distribution for more details. */
#ifndef WEINMANN_LOADER_H
#define WEINMANN_LOADER_H
#include "SleepLib/machine.h" // Base class: MachineLoader
#include "SleepLib/machine_loader.h"
#include "SleepLib/profiles.h"
//********************************************************************************************
/// IMPORTANT!!!
//********************************************************************************************
// Please INCREMENT the following value when making changes to this loaders implementation.
//
const int weinmann_data_version = 3;
//
//********************************************************************************************
/*! \class Weinmann
\brief Weinmann customized machine object
*/
class Weinmann: public CPAP
{
public:
Weinmann(MachineID id = 0);
virtual ~Weinmann();
};
struct CompInfo
{
CompInfo() {
session = nullptr;
flow_start = 0; flow_size = 0;
stat_start = 0; stat_size = 0;
pres_start = 0; pres_size = 0;
amv_start = 0; amv_size =0;
event_start = 0; event_recs = 0;
}
CompInfo(const CompInfo & copy) {
session = copy.session;
time = copy.time;
flow_start = copy.flow_start;
flow_size= copy.flow_size;
stat_start = copy.flow_start;
stat_size= copy.flow_size;
pres_start = copy.pres_start;
pres_size = copy.pres_size;
amv_start = copy.amv_start;
amv_size = copy.amv_size;
event_start = copy.event_start;
event_recs = copy.event_recs;
}
CompInfo(Session * sess, QDateTime dt, quint32 fs, quint32 fl, quint32 ss, quint32 sl,quint32 ps, quint32 pl, quint32 ms, quint32 ml, quint32 es, quint32 er):
session(sess), time(dt),
flow_start(fs), flow_size(fl),
stat_start(ss), stat_size(sl),
pres_start(ps), pres_size(pl),
amv_start(ms), amv_size(ml),
event_start(es), event_recs(er) {}
Session * session;
QDateTime time;
quint32 flow_start;
quint32 flow_size;
quint32 stat_start;
quint32 stat_size;
quint32 pres_start;
quint32 pres_size;
quint32 amv_start;
quint32 amv_size;
quint32 event_start;
quint32 event_recs;
};
const QString weinmann_class_name = STR_MACH_Weinmann;
/*! \class WeinmannLoader
\brief Loader for Weinmann CPAP data
This is only relatively recent addition and still needs more work
*/
class WeinmannLoader : public CPAPLoader
{
public:
WeinmannLoader();
virtual ~WeinmannLoader();
//! \brief Detect if the given path contains a valid Folder structure
virtual bool Detect(const QString & path);
//! \brief Scans path for Weinmann data signature, and Loads any new data
virtual int Open(QString path);
//! \brief Returns SleepLib database version of this Weinmann loader
virtual int Version() { return weinmann_data_version; }
//! \brief Returns the machine loader name of this class
virtual const QString &loaderName() { return weinmann_class_name; }
int ParseIndex(QFile & wmdata);
//! \brief Creates a machine object, indexed by serial number
// Machine *CreateMachine(QString serial);
//! \brief Registers this MachineLoader with the master list, so Weinmann data can load
static void Register();
virtual MachineInfo newInfo() {
return MachineInfo(MT_CPAP, 0, weinmann_class_name, QObject::tr("Weinmann"), QString(), QString(), QString(), QObject::tr("Weinmann"), QDateTime::currentDateTime(), weinmann_data_version);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Now for some CPAPLoader overrides
////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual QString presRelType() { return QObject::tr("Unknown"); } // might not need this one
virtual ChannelID presRelSet() { return NoChannel; }
virtual ChannelID presRelLevel() { return NoChannel; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected:
QHash<QString, int> index;
QList<CompInfo> compinfo;
QMap<SessionID, Session *> sessions;
QString last;
unsigned char *m_buffer;
};
#endif // WEINMANN_LOADER_H

View File

@ -37,7 +37,7 @@ class ZEOLoader : public MachineLoader
//Machine *CreateMachine(); //Machine *CreateMachine();
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_SLEEPSTAGE, zeo_class_name, QObject::tr("Zeo"), QString(), QString(), QString(), QObject::tr("Personal Sleep Coach"), QDateTime::currentDateTime(), zeo_data_version); return MachineInfo(MT_SLEEPSTAGE, 0, zeo_class_name, QObject::tr("Zeo"), QString(), QString(), QString(), QObject::tr("Personal Sleep Coach"), QDateTime::currentDateTime(), zeo_data_version);
} }
protected: protected:

View File

@ -45,6 +45,7 @@ Machine::Machine(MachineID id)
m_id = temp; m_id = temp;
} else { m_id = id; } } else { m_id = id; }
m_loader = nullptr;
// qDebug() << "Create Machine: " << hex << m_id; //%lx",m_id); // qDebug() << "Create Machine: " << hex << m_id; //%lx",m_id);
m_type = MT_UNKNOWN; m_type = MT_UNKNOWN;
@ -363,6 +364,19 @@ bool Machine::Purge(int secret)
return true; return true;
} }
void Machine::setLoaderName(QString value)
{
info.loadername = value;
m_loader = GetLoader(value);
}
void Machine::setInfo(MachineInfo inf)
{
info = inf;
m_loader = GetLoader(inf.loadername);
}
//const quint32 channel_version=1; //const quint32 channel_version=1;
const QString Machine::getDataPath() const QString Machine::getDataPath()
@ -701,44 +715,3 @@ PositionSensor::PositionSensor(MachineID id): Machine(id)
PositionSensor::~PositionSensor() PositionSensor::~PositionSensor()
{ {
} }
ChannelID NoChannel, SESSION_ENABLED, CPAP_SummaryOnly;
ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CPAP_EPAPHi, CPAP_Pressure,
CPAP_PS, CPAP_Mode, CPAP_AHI,
CPAP_PressureMin, CPAP_PressureMax, CPAP_Ramp, CPAP_RampTime, CPAP_RampPressure, CPAP_Obstructive,
CPAP_Hypopnea,
CPAP_ClearAirway, CPAP_Apnea, CPAP_CSR, CPAP_LeakFlag, CPAP_ExP, CPAP_NRI, CPAP_VSnore,
CPAP_VSnore2,
CPAP_RERA, CPAP_PressurePulse, CPAP_FlowLimit, CPAP_SensAwake, CPAP_FlowRate, CPAP_MaskPressure,
CPAP_MaskPressureHi,
CPAP_RespEvent, CPAP_Snore, CPAP_MinuteVent, CPAP_RespRate, CPAP_TidalVolume, CPAP_PTB, CPAP_Leak,
CPAP_LeakMedian, CPAP_LeakTotal, CPAP_MaxLeak, CPAP_FLG, CPAP_IE, CPAP_Te, CPAP_Ti, CPAP_TgMV,
CPAP_UserFlag1, CPAP_UserFlag2, CPAP_UserFlag3, CPAP_BrokenSummary, CPAP_BrokenWaveform, CPAP_RDI,
CPAP_PresReliefSet, CPAP_PresReliefMode, CPAP_PresReliefType, CPAP_PSMin, CPAP_PSMax, CPAP_Test1,
CPAP_Test2;
ChannelID RMS9_E01, RMS9_E02, RMS9_EPR, RMS9_EPRLevel, RMS9_SetPressure, RMS9_MaskOnTime;
ChannelID INTP_SmartFlex;
ChannelID INTELLIPAP_Unknown1, INTELLIPAP_Unknown2;
ChannelID PRS1_00, PRS1_01, PRS1_08, PRS1_0A, PRS1_0B, PRS1_0C, PRS1_0E, PRS1_0F, CPAP_LargeLeak, PRS1_12,
PRS1_FlexMode, PRS1_FlexSet, PRS1_HumidStatus, CPAP_HumidSetting, PRS1_SysLock,
PRS1_SysOneResistStat,
PRS1_SysOneResistSet, PRS1_HoseDiam, PRS1_AutoOn, PRS1_AutoOff, PRS1_MaskAlert, PRS1_ShowAHI;
ChannelID OXI_Pulse, OXI_SPO2, OXI_PulseChange, OXI_SPO2Drop, OXI_Plethy;
ChannelID Journal_Notes, Journal_Weight, Journal_BMI, Journal_ZombieMeter, Bookmark_Start,
Bookmark_End, Bookmark_Notes;
ChannelID ZEO_SleepStage, ZEO_ZQ, ZEO_TotalZ, ZEO_TimeToZ, ZEO_TimeInWake, ZEO_TimeInREM,
ZEO_TimeInLight, ZEO_TimeInDeep, ZEO_Awakenings,
ZEO_AlarmReason, ZEO_SnoozeTime, ZEO_WakeTone, ZEO_WakeWindow, ZEO_AlarmType, ZEO_MorningFeel,
ZEO_FirmwareVersion,
ZEO_FirstAlarmRing, ZEO_LastAlarmRing, ZEO_FirstSnoozeTime, ZEO_LastSnoozeTime, ZEO_SetAlarmTime,
ZEO_RiseTime;
ChannelID POS_Orientation, POS_Inclination;

View File

@ -68,7 +68,7 @@ public:
virtual void run() {} virtual void run() {}
}; };
class MachineLaoder; class MachineLoader;
/*! \class Machine /*! \class Machine
\brief This Machine class is the Heart of SleepyLib, representing a single Machine and holding it's data \brief This Machine class is the Heart of SleepyLib, representing a single Machine and holding it's data
@ -182,20 +182,26 @@ class Machine
inline QString modelnumber() const { return info.modelnumber; } inline QString modelnumber() const { return info.modelnumber; }
inline QString serial() const { return info.serial; } inline QString serial() const { return info.serial; }
inline QString series() const { return info.series; } inline QString series() const { return info.series; }
inline quint32 cap() const { return info.cap; }
inline int version() const { return info.version; } inline int version() const { return info.version; }
inline QDateTime lastImported() const { return info.lastimported; } inline QDateTime lastImported() const { return info.lastimported; }
inline void setModel(QString value) { info.model = value; } inline void setModel(QString value) { info.model = value; }
inline void setSerial(QString value) { info.serial = value; } inline void setSerial(QString value) { info.serial = value; }
inline void setType(MachineType type) { info.type = type; } inline void setType(MachineType type) { info.type = type; }
inline void setLoaderName(QString value) { info.loadername = value; } inline void setCap(quint32 value) { info.cap = value; }
void setLoaderName(QString value);
MachineLoader * loader() { return m_loader; }
// much more simpler multithreading... // much more simpler multithreading...
void queTask(ImportTask * task); void queTask(ImportTask * task);
void runTasks(); void runTasks();
QMutex saveMutex; QMutex saveMutex;
void setInfo(MachineInfo inf) { info = inf; } void setInfo(MachineInfo inf);
const MachineInfo getInfo() { return info; } const MachineInfo getInfo() { return info; }
protected: protected:
@ -206,6 +212,8 @@ class Machine
MachineType m_type; MachineType m_type;
QString m_path; QString m_path;
MachineLoader * m_loader;
bool changed; bool changed;
bool firstsession; bool firstsession;
int m_totaltasks; int m_totaltasks;
@ -226,6 +234,7 @@ class CPAP: public Machine
public: public:
CPAP(MachineID id = 0); CPAP(MachineID id = 0);
virtual ~CPAP(); virtual ~CPAP();
}; };

View File

@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*
* SleepLib Common Machine Stuff
*
* Copyright (c) 2011-2014 Mark Watkins <jedimark@users.sourceforge.net>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the Linux
* distribution for more details. */
#include "machine_common.h"
ChannelID NoChannel, SESSION_ENABLED, CPAP_SummaryOnly;
ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CPAP_EPAPHi, CPAP_Pressure,
CPAP_PS, CPAP_Mode, CPAP_AHI,
CPAP_PressureMin, CPAP_PressureMax, CPAP_Ramp, CPAP_RampTime, CPAP_RampPressure, CPAP_Obstructive,
CPAP_Hypopnea,
CPAP_ClearAirway, CPAP_Apnea, CPAP_CSR, CPAP_LeakFlag, CPAP_ExP, CPAP_NRI, CPAP_VSnore,
CPAP_VSnore2,
CPAP_RERA, CPAP_PressurePulse, CPAP_FlowLimit, CPAP_SensAwake, CPAP_FlowRate, CPAP_MaskPressure,
CPAP_MaskPressureHi,
CPAP_RespEvent, CPAP_Snore, CPAP_MinuteVent, CPAP_RespRate, CPAP_TidalVolume, CPAP_PTB, CPAP_Leak,
CPAP_LeakMedian, CPAP_LeakTotal, CPAP_MaxLeak, CPAP_FLG, CPAP_IE, CPAP_Te, CPAP_Ti, CPAP_TgMV,
CPAP_UserFlag1, CPAP_UserFlag2, CPAP_UserFlag3, CPAP_BrokenSummary, CPAP_BrokenWaveform, CPAP_RDI,
CPAP_PresReliefMode, CPAP_PresReliefLevel, CPAP_PSMin, CPAP_PSMax, CPAP_Test1,
CPAP_Test2, CPAP_HumidSetting;
ChannelID RMS9_E01, RMS9_E02, RMS9_SetPressure, RMS9_MaskOnTime;
ChannelID INTELLIPAP_Unknown1, INTELLIPAP_Unknown2;
ChannelID PRS1_00, PRS1_01, PRS1_08, PRS1_0A, PRS1_0B, PRS1_0C, PRS1_0E, PRS1_0F, CPAP_LargeLeak, PRS1_12,
PRS1_FlexMode, PRS1_FlexLevel, PRS1_HumidStatus, PRS1_HumitSetting, PRS1_SysLock,
PRS1_SysOneResistStat,
PRS1_SysOneResistSet, PRS1_HoseDiam, PRS1_AutoOn, PRS1_AutoOff, PRS1_MaskAlert, PRS1_ShowAHI;
ChannelID OXI_Pulse, OXI_SPO2, OXI_PulseChange, OXI_SPO2Drop, OXI_Plethy;
ChannelID Journal_Notes, Journal_Weight, Journal_BMI, Journal_ZombieMeter, Bookmark_Start,
Bookmark_End, Bookmark_Notes;
ChannelID ZEO_SleepStage, ZEO_ZQ, ZEO_TotalZ, ZEO_TimeToZ, ZEO_TimeInWake, ZEO_TimeInREM,
ZEO_TimeInLight, ZEO_TimeInDeep, ZEO_Awakenings,
ZEO_AlarmReason, ZEO_SnoozeTime, ZEO_WakeTone, ZEO_WakeWindow, ZEO_AlarmType, ZEO_MorningFeel,
ZEO_FirmwareVersion,
ZEO_FirstAlarmRing, ZEO_LastAlarmRing, ZEO_FirstSnoozeTime, ZEO_LastSnoozeTime, ZEO_SetAlarmTime,
ZEO_RiseTime;
ChannelID POS_Orientation, POS_Inclination;

View File

@ -1,7 +1,7 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99: * vim: set ts=8 sts=4 et sw=4 tw=99:
* *
* SleepLib Machine Loader Class Header * SleepLib Common Machine Header
* *
* Copyright (c) 2011-2014 Mark Watkins <jedimark@users.sourceforge.net> * Copyright (c) 2011-2014 Mark Watkins <jedimark@users.sourceforge.net>
* *
@ -54,12 +54,31 @@ enum SummaryType { ST_CNT, ST_SUM, ST_AVG, ST_WAVG, ST_PERC, ST_90P, ST_MIN, ST_
enum MachineType { MT_UNKNOWN = 0, MT_CPAP, MT_OXIMETER, MT_SLEEPSTAGE, MT_JOURNAL, MT_POSITION }; enum MachineType { MT_UNKNOWN = 0, MT_CPAP, MT_OXIMETER, MT_SLEEPSTAGE, MT_JOURNAL, MT_POSITION };
//void InitMapsWithoutAwesomeInitializerLists(); //void InitMapsWithoutAwesomeInitializerLists();
// PAP Device Capabilities
const quint32 CAP_Fixed = 0x0000001; // Constant PAP
const quint32 CAP_Variable = 0x0000002; // Variable Base (EPAP) pressure
const quint32 CAP_BiLevel = 0x0000004; // Fixed Pressure Support
const quint32 CAP_Variable_PS = 0x0000008; // Pressure support can range
const quint32 CAP_PressureRelief = 0x0000010; // Device has a pressure relief mode (EPR; Flex; SmartFlex)
const quint32 CAP_Humidification = 0x0000020; // Device has a humidifier attached
// PAP Mode Capabilities
const quint32 PAP_CPAP = 0x0001; // Fixed Pressure PAP
const quint32 PAP_APAP = 0x0002; // Auto Ranging PAP
const quint32 PAP_BiLevelFixed = 0x0004; // Fixed BiLevel
const quint32 PAP_BiLevelAutoFixed = 0x0008; // Auto BiLevel with Fixed EPAP
const quint32 PAP_BiLevelAutoVariable = 0x0010; // Auto BiLevel with full ranging capabilities
const quint32 PAP_ASV_Fixed = 0x0020; // ASV with fixed EPAP
const quint32 PAP_ASV_Variable = 0x0040; // ASV with full ranging capabilities
const quint32 PAP_SplitNight = 0x8000; // Split night capabilities
/*! \enum CPAPMode /*! \enum CPAPMode
\brief CPAP Machines mode of operation \brief CPAP Machines mode of operation
*/ */
enum CPAPMode { //:short enum CPAPMode { //:short
MODE_UNKNOWN = 0, MODE_CPAP, MODE_APAP, MODE_BILEVEL_FIXED, MODE_BILEVEL_AUTO_FIXED_PS, MODE_ASV, MODE_ASV_VARIABLE_EPAP MODE_UNKNOWN = 0, MODE_CPAP, MODE_APAP, MODE_BILEVEL_FIXED, MODE_BILEVEL_AUTO_FIXED_PS, MODE_BILEVEL_AUTO_VARIABLE_PS, MODE_ASV, MODE_ASV_VARIABLE_EPAP
}; };
/*! \enum PRTypes /*! \enum PRTypes
@ -68,13 +87,13 @@ enum CPAPMode { //:short
enum PRTypes { //:short enum PRTypes { //:short
PR_UNKNOWN = 0, PR_NONE, PR_CFLEX, PR_CFLEXPLUS, PR_AFLEX, PR_BIFLEX, PR_EPR, PR_SMARTFLEX, PR_EASYBREATHE, PR_SENSAWAKE PR_UNKNOWN = 0, PR_NONE, PR_CFLEX, PR_CFLEXPLUS, PR_AFLEX, PR_BIFLEX, PR_EPR, PR_SMARTFLEX, PR_EASYBREATHE, PR_SENSAWAKE
}; };
enum PRModes { //:short enum PRTimeModes { //:short
PM_UNKNOWN = 0, PM_RampOnly, PM_FullTime PM_UNKNOWN = 0, PM_RampOnly, PM_FullTime
}; };
struct MachineInfo { struct MachineInfo {
MachineInfo() { type = MT_UNKNOWN; version = 0; } MachineInfo() { type = MT_UNKNOWN; version = 0; cap=0; }
MachineInfo(const MachineInfo & copy) { MachineInfo(const MachineInfo & copy) {
type = copy.type; type = copy.type;
loadername = copy.loadername; loadername = copy.loadername;
@ -85,12 +104,14 @@ struct MachineInfo {
series = copy.series; series = copy.series;
version = copy.version; version = copy.version;
lastimported = copy.lastimported; lastimported = copy.lastimported;
cap = copy.cap;
} }
MachineInfo(MachineType type, QString loadername, QString brand, QString model, QString modelnumber, QString serial, QString series, QDateTime lastimported, int version) : MachineInfo(MachineType type, quint32 cap, QString loadername, QString brand, QString model, QString modelnumber, QString serial, QString series, QDateTime lastimported, int version) :
type(type), loadername(loadername), brand(brand), model(model), modelnumber(modelnumber), serial(serial), series(series), lastimported(lastimported), version(version) {} type(type), cap(cap), loadername(loadername), brand(brand), model(model), modelnumber(modelnumber), serial(serial), series(series), lastimported(lastimported), version(version) {}
MachineType type; MachineType type;
quint32 cap;
QString loadername; QString loadername;
QString brand; QString brand;
QString model; QString model;
@ -128,13 +149,12 @@ extern ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CP
CPAP_RespEvent, CPAP_Snore, CPAP_MinuteVent, CPAP_RespRate, CPAP_TidalVolume, CPAP_PTB, CPAP_Leak, CPAP_RespEvent, CPAP_Snore, CPAP_MinuteVent, CPAP_RespRate, CPAP_TidalVolume, CPAP_PTB, CPAP_Leak,
CPAP_LeakMedian, CPAP_LeakTotal, CPAP_MaxLeak, CPAP_FLG, CPAP_IE, CPAP_Te, CPAP_Ti, CPAP_TgMV, CPAP_LeakMedian, CPAP_LeakTotal, CPAP_MaxLeak, CPAP_FLG, CPAP_IE, CPAP_Te, CPAP_Ti, CPAP_TgMV,
CPAP_UserFlag1, CPAP_UserFlag2, CPAP_UserFlag3, CPAP_BrokenSummary, CPAP_BrokenWaveform, CPAP_RDI, CPAP_UserFlag1, CPAP_UserFlag2, CPAP_UserFlag3, CPAP_BrokenSummary, CPAP_BrokenWaveform, CPAP_RDI,
CPAP_PresReliefSet, CPAP_PresReliefMode, CPAP_PresReliefType, CPAP_Test1, CPAP_Test2; CPAP_PresReliefMode, CPAP_PresReliefLevel, CPAP_Test1, CPAP_Test2;
extern ChannelID RMS9_E01, RMS9_E02, RMS9_EPR, RMS9_EPRLevel, RMS9_SetPressure, RMS9_MaskOnTime; extern ChannelID RMS9_E01, RMS9_E02, RMS9_SetPressure, RMS9_MaskOnTime;
extern ChannelID INTP_SmartFlex;
extern ChannelID PRS1_00, PRS1_01, PRS1_08, PRS1_0A, PRS1_0B, PRS1_0C, PRS1_0E, PRS1_0F, CPAP_LargeLeak, extern ChannelID PRS1_00, PRS1_01, PRS1_08, PRS1_0A, PRS1_0B, PRS1_0C, PRS1_0E, PRS1_0F, CPAP_LargeLeak,
PRS1_12, PRS1_12,
PRS1_FlexMode, PRS1_FlexSet, PRS1_HumidStatus, CPAP_HumidSetting, PRS1_SysLock, PRS1_FlexMode, PRS1_FlexLevel, PRS1_HumidStatus, PRS1_HumitSetting, CPAP_HumidSetting, PRS1_SysLock,
PRS1_SysOneResistStat, PRS1_SysOneResistStat,
PRS1_SysOneResistSet, PRS1_HoseDiam, PRS1_AutoOn, PRS1_AutoOff, PRS1_MaskAlert, PRS1_ShowAHI; PRS1_SysOneResistSet, PRS1_HoseDiam, PRS1_AutoOn, PRS1_AutoOff, PRS1_MaskAlert, PRS1_ShowAHI;

View File

@ -221,6 +221,26 @@ void MachineLoader::runTasks(bool threaded)
} }
} }
QList<ChannelID> CPAPLoader::eventFlags(Day * day)
{
Machine * mach = day->machine;
QList<ChannelID> list;
if (mach->loader() != this) {
qDebug() << "Trying to ask" << loaderName() << "for" << mach->loaderName() << "data";
return list;
}
list.push_back(CPAP_ClearAirway);
list.push_back(CPAP_Obstructive);
list.push_back(CPAP_Hypopnea);
list.push_back(CPAP_Apnea);
return list;
}
/*const QString machine_profile_name="MachineList.xml"; /*const QString machine_profile_name="MachineList.xml";
void MachineLoader::LoadMachineList() void MachineLoader::LoadMachineList()

View File

@ -59,15 +59,6 @@ class MachineLoader: public QObject
virtual const QString &loaderName() = 0; virtual const QString &loaderName() = 0;
inline MachineType type() { return m_type; } inline MachineType type() { return m_type; }
// virtual bool openDevice() { return false; }
// virtual void closeDevice() {}
// virtual bool scanDevice(QString keyword="", quint16 vendor_id=0, quint16 product_id=0) {
// Q_UNUSED(keyword)
// Q_UNUSED(vendor_id)
// Q_UNUSED(product_id)
// return false;
// }
void queTask(ImportTask * task); void queTask(ImportTask * task);
void addSession(Session * sess) void addSession(Session * sess)
@ -77,7 +68,6 @@ class MachineLoader: public QObject
sessionMutex.unlock(); sessionMutex.unlock();
} }
//! \brief Process Task list using all available threads. //! \brief Process Task list using all available threads.
void runTasks(bool threaded=true); void runTasks(bool threaded=true);
@ -96,16 +86,6 @@ class MachineLoader: public QObject
signals: signals:
void updateProgress(int cnt, int total); void updateProgress(int cnt, int total);
// void updateDisplay(MachineLoader *);
//protected slots:
// virtual void dataAvailable() {}
// virtual void resetImportTimeout() {}
// virtual void startImportTimeout() {}
//protected:
// virtual void killTimers(){}
// virtual void resetDevice(){}
protected: protected:
//! \brief Contains a list of Machine records known by this loader //! \brief Contains a list of Machine records known by this loader
@ -130,6 +110,21 @@ signals:
}; };
class CPAPLoader:public MachineLoader
{
Q_OBJECT
public:
CPAPLoader() : MachineLoader() {}
virtual ~CPAPLoader() {}
virtual QList<ChannelID> eventFlags(Day * day);
virtual QString PresReliefLabel() { return QString(""); }
virtual ChannelID PresReliefMode() { return NoChannel; }
virtual ChannelID PresReliefLevel() { return NoChannel; }
};
struct ImportPath struct ImportPath
{ {
ImportPath() { ImportPath() {

View File

@ -218,7 +218,7 @@ bool Preferences::Open(QString filename)
if (!e.isNull()) { if (!e.isNull()) {
QString name = e.tagName(); QString name = e.tagName();
QString type = e.attribute("type").toLower(); QString type = e.attribute("type").toLower();
QString value = e.text();; QString value = e.text();
if (type == "double") { if (type == "double") {
double d; double d;

View File

@ -686,7 +686,7 @@ int Profile::Import(QString path)
MachineLoader *GetLoader(QString name) MachineLoader *GetLoader(QString name)
{ {
QList<MachineLoader *>loaders = GetLoaders(MT_CPAP); QList<MachineLoader *>loaders = GetLoaders();
Q_FOREACH(MachineLoader * loader, loaders) { Q_FOREACH(MachineLoader * loader, loaders) {
if (loader->loaderName() == name) { if (loader->loaderName() == name) {
@ -848,7 +848,7 @@ Profile *Create(QString name)
p_profile->Set(STR_GEN_DataFolder, QString("{home}/Profiles/{") + QString(STR_UI_UserName) + QString("}")); p_profile->Set(STR_GEN_DataFolder, QString("{home}/Profiles/{") + QString(STR_UI_UserName) + QString("}"));
Machine *m = new Machine(0); Machine *m = new Machine(0);
MachineInfo info(MT_JOURNAL, STR_MACH_Journal, "SleepyHead", STR_MACH_Journal, QString(), m->hexid(), QString(), QDateTime::currentDateTime(), 0); MachineInfo info(MT_JOURNAL, 0, STR_MACH_Journal, "SleepyHead", STR_MACH_Journal, QString(), m->hexid(), QString(), QDateTime::currentDateTime(), 0);
m->setInfo(info); m->setInfo(info);
p_profile->AddMachine(m); p_profile->AddMachine(m);

View File

@ -392,9 +392,34 @@ void init()
schema::channel.add(GRP_CPAP, new Channel(CPAP_SummaryOnly = 0x1026, SETTING, SESSION, schema::channel.add(GRP_CPAP, new Channel(CPAP_SummaryOnly = 0x1026, SETTING, SESSION,
"SummaryOnly", QObject::tr("Summary Only"), "SummaryOnly", QObject::tr("Summary Only"),
QObject::tr("CPAP Session contains summary data onlyf"), QObject::tr("Summary Only"), STR_UNIT_Unknown, QObject::tr("CPAP Session contains summary data only"), QObject::tr("Summary Only"), STR_UNIT_Unknown,
DEFAULT, Qt::black)); DEFAULT, Qt::black));
Channel *ch;
schema::channel.add(GRP_CPAP, ch = new Channel(CPAP_Mode = 0x1200, SETTING, SESSION,
"PAPMode", QObject::tr("PAP Mode"),
QObject::tr("PAP Mode"), QObject::tr("PAP_Mode"), STR_UNIT_Unknown,
LOOKUP, Qt::black));
ch->addOption(0, STR_TR_Unknown);
ch->addOption(1, STR_TR_CPAP);
ch->addOption(2, STR_TR_APAP);
ch->addOption(3, QObject::tr("Fixed Bi-Level"));
ch->addOption(4, QObject::tr("Auto Bi-Level (Fixed PS)"));
ch->addOption(5, QObject::tr("Auto Bi-Level (Variable PS)"));
ch->addOption(6, QObject::tr("ASV (Fixed EPAP)"));
ch->addOption(7, QObject::tr("ASV (Variable EPAP)"));
// <channel id="0x1200" class="setting" scope="!session" name="PAPMode" details="PAP Mode" label="PAP Mode" type="integer">
// <option id="0" value="CPAP"/>
// <option id="1" value="Auto"/>
// <option id="2" value="Fixed Bi-Level"/>
// <option id="3" value="Auto Bi-Level"/>
// <option id="4" value="ASV"/>
// <option id="5" value="ASV Auto EPAP"/>
// </channel>
NoChannel = 0; NoChannel = 0;
// CPAP_IPAP=schema::channel["IPAP"].id(); // CPAP_IPAP=schema::channel["IPAP"].id();
@ -405,7 +430,7 @@ void init()
// CPAP_PS=schema::channel["PS"].id(); // CPAP_PS=schema::channel["PS"].id();
// CPAP_PSMin=schema::channel["PSMin"].id(); // CPAP_PSMin=schema::channel["PSMin"].id();
// CPAP_PSMax=schema::channel["PSMax"].id(); // CPAP_PSMax=schema::channel["PSMax"].id();
CPAP_Mode = schema::channel["PAPMode"].id(); // CPAP_Mode = schema::channel["PAPMode"].id();
CPAP_BrokenSummary = schema::channel["BrokenSummary"].id(); CPAP_BrokenSummary = schema::channel["BrokenSummary"].id();
CPAP_BrokenWaveform = schema::channel["BrokenWaveform"].id(); CPAP_BrokenWaveform = schema::channel["BrokenWaveform"].id();
// CPAP_PressureMin=schema::channel["PressureMin"].id(); // CPAP_PressureMin=schema::channel["PressureMin"].id();
@ -446,20 +471,12 @@ void init()
CPAP_Test1 = schema::channel["TestChan1"].id(); CPAP_Test1 = schema::channel["TestChan1"].id();
CPAP_Test2 = schema::channel["TestChan2"].id(); CPAP_Test2 = schema::channel["TestChan2"].id();
CPAP_PresReliefSet = schema::channel["PresRelSet"].id();
CPAP_PresReliefMode = schema::channel["PresRelMode"].id();
CPAP_PresReliefType = schema::channel["PresRelType"].id();
// CPAP_UserFlag1=schema::channel["UserFlag1"].id(); // CPAP_UserFlag1=schema::channel["UserFlag1"].id();
// CPAP_UserFlag2=schema::channel["UserFlag2"].id(); // CPAP_UserFlag2=schema::channel["UserFlag2"].id();
// CPAP_UserFlag3=schema::channel["UserFlag3"].id(); // CPAP_UserFlag3=schema::channel["UserFlag3"].id();
RMS9_E01 = schema::channel["RMS9_E01"].id(); RMS9_E01 = schema::channel["RMS9_E01"].id();
RMS9_E02 = schema::channel["RMS9_E02"].id(); RMS9_E02 = schema::channel["RMS9_E02"].id();
RMS9_EPR = schema::channel["EPR"].id(); RMS9_SetPressure = schema::channel["SetPressure"].id(); // TODO: this isn't needed anymore
RMS9_EPRLevel = schema::channel["EPRLevel"].id();
RMS9_SetPressure = schema::channel["SetPressure"].id();
PRS1_FlexMode = schema::channel["FlexMode"].id();
PRS1_FlexSet = schema::channel["FlexSet"].id();
PRS1_HumidStatus = schema::channel["HumidStat"].id(); PRS1_HumidStatus = schema::channel["HumidStat"].id();
CPAP_HumidSetting = schema::channel["HumidSet"].id(); CPAP_HumidSetting = schema::channel["HumidSet"].id();
PRS1_SysLock = schema::channel["SysLock"].id(); PRS1_SysLock = schema::channel["SysLock"].id();

View File

@ -38,7 +38,7 @@ enum ChanType {
}; };
enum DataType { enum DataType {
DEFAULT = 0, INTEGER, BOOL, DOUBLE, STRING, RICHTEXT, DATE, TIME, DATETIME DEFAULT = 0, INTEGER, BOOL, DOUBLE, STRING, RICHTEXT, DATE, TIME, DATETIME, LOOKUP
}; };
enum ScopeType { enum ScopeType {
GLOBAL = 0, MACHINE, DAY, SESSION GLOBAL = 0, MACHINE, DAY, SESSION

View File

@ -48,7 +48,7 @@ public:
virtual int Version()=0; virtual int Version()=0;
virtual const QString &loaderName()=0; virtual const QString &loaderName()=0;
virtual MachineInfo newInfo() { virtual MachineInfo newInfo() {
return MachineInfo(MT_OXIMETER, "", QString(), QString(), QString(), QString(), "Generic", QDateTime::currentDateTime(), 0); return MachineInfo(MT_OXIMETER, 0, "", QString(), QString(), QString(), QString(), "Generic", QDateTime::currentDateTime(), 0);
} }
// Serial Stuff // Serial Stuff

View File

@ -154,13 +154,13 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
for (int i=0; i < cpapsize; ++i) { for (int i=0; i < cpapsize; ++i) {
ChannelID code = cpapcodes[i]; ChannelID code = cpapcodes[i];
graphlist[schema::channel[code].label()] = new gGraph(schema::channel[code].code(), GraphView, schema::channel[code].label(), channelInfo(code), default_height); graphlist[schema::channel[code].code()] = new gGraph(schema::channel[code].code(), GraphView, schema::channel[code].label(), channelInfo(code), default_height);
} }
int oxigrp=p_profile->ExistsAndTrue("SyncOximetry") ? 0 : 1; // Contemplating killing this setting... int oxigrp=p_profile->ExistsAndTrue("SyncOximetry") ? 0 : 1; // Contemplating killing this setting...
for (int i=0; i < oxisize; ++i) { for (int i=0; i < oxisize; ++i) {
ChannelID code = oxicodes[i]; ChannelID code = oxicodes[i];
graphlist[schema::channel[code].label()] = new gGraph(schema::channel[code].code(), GraphView, schema::channel[code].label(), channelInfo(code), default_height, oxigrp); graphlist[schema::channel[code].code()] = new gGraph(schema::channel[code].code(), GraphView, schema::channel[code].label(), channelInfo(code), default_height, oxigrp);
} }
if (p_profile->general->calculateRDI()) { if (p_profile->general->calculateRDI()) {
@ -251,7 +251,7 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
gLineOverlaySummary *los=new gLineOverlaySummary(tr("Selection AHI"),5,-4); gLineOverlaySummary *los=new gLineOverlaySummary(tr("Selection AHI"),5,-4);
AddCPAP(l); AddCPAP(l);
gGraph *FRW = graphlist[schema::channel[CPAP_FlowRate].label()]; gGraph *FRW = graphlist[schema::channel[CPAP_FlowRate].code()];
// Draw layer is important... spans first.. // Draw layer is important... spans first..
FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_CSR, COLOR_CSR, STR_TR_CSR, FT_Span))); FRW->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_CSR, COLOR_CSR, STR_TR_CSR, FT_Span)));
@ -294,7 +294,10 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
bool square=p_profile->appearance->squareWavePlots(); bool square=p_profile->appearance->squareWavePlots();
gLineChart *pc=new gLineChart(CPAP_Pressure, COLOR_Pressure, square); gLineChart *pc=new gLineChart(CPAP_Pressure, COLOR_Pressure, square);
graphlist[schema::channel[CPAP_Pressure].label()]->AddLayer(AddCPAP(pc)); graphlist[schema::channel[CPAP_Pressure].code()]->AddLayer(AddCPAP(pc));
graphlist[schema::channel[CPAP_Pressure].code()]->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_Ramp, COLOR_Ramp, schema::channel[CPAP_Ramp].label(), FT_Span)));
pc->addPlot(CPAP_EPAP, COLOR_EPAP, square); pc->addPlot(CPAP_EPAP, COLOR_EPAP, square);
pc->addPlot(CPAP_IPAPLo, COLOR_IPAPLo, square); pc->addPlot(CPAP_IPAPLo, COLOR_IPAPLo, square);
pc->addPlot(CPAP_IPAP, COLOR_IPAP, square); pc->addPlot(CPAP_IPAP, COLOR_IPAP, square);
@ -310,54 +313,54 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
// this is class wide because the leak redline can be reset in preferences.. // this is class wide because the leak redline can be reset in preferences..
// Better way would be having a search for linechart layers in graphlist[...] // Better way would be having a search for linechart layers in graphlist[...]
gLineChart *leakchart=new gLineChart(CPAP_Leak, COLOR_LeakTotal, square); gLineChart *leakchart=new gLineChart(CPAP_Leak, COLOR_LeakTotal, square);
graphlist[schema::channel[CPAP_Leak].label()]->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_LargeLeak, COLOR_LargeLeak, STR_TR_LL, FT_Span))); graphlist[schema::channel[CPAP_Leak].code()]->AddLayer(AddCPAP(new gLineOverlayBar(CPAP_LargeLeak, COLOR_LargeLeak, STR_TR_LL, FT_Span)));
leakchart->addPlot(CPAP_LeakTotal, COLOR_Leak, square); leakchart->addPlot(CPAP_LeakTotal, COLOR_Leak, square);
leakchart->addPlot(CPAP_MaxLeak, COLOR_MaxLeak, square); leakchart->addPlot(CPAP_MaxLeak, COLOR_MaxLeak, square);
schema::channel[CPAP_Leak].setUpperThresholdColor(Qt::red); schema::channel[CPAP_Leak].setUpperThresholdColor(Qt::red);
schema::channel[CPAP_Leak].setLowerThresholdColor(Qt::green); schema::channel[CPAP_Leak].setLowerThresholdColor(Qt::green);
graphlist[schema::channel[CPAP_Leak].label()]->AddLayer(AddCPAP(leakchart)); graphlist[schema::channel[CPAP_Leak].code()]->AddLayer(AddCPAP(leakchart));
//LEAK->AddLayer(AddCPAP(new gLineChart(CPAP_Leak, COLOR_Leak,square))); //LEAK->AddLayer(AddCPAP(new gLineChart(CPAP_Leak, COLOR_Leak,square)));
//LEAK->AddLayer(AddCPAP(new gLineChart(CPAP_MaxLeak, COLOR_MaxLeak,square))); //LEAK->AddLayer(AddCPAP(new gLineChart(CPAP_MaxLeak, COLOR_MaxLeak,square)));
graphlist[schema::channel[CPAP_Snore].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_Snore, COLOR_Snore, true))); graphlist[schema::channel[CPAP_Snore].code()]->AddLayer(AddCPAP(new gLineChart(CPAP_Snore, COLOR_Snore, true)));
graphlist[schema::channel[CPAP_PTB].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_PTB, COLOR_PTB, square))); graphlist[schema::channel[CPAP_PTB].code()]->AddLayer(AddCPAP(new gLineChart(CPAP_PTB, COLOR_PTB, square)));
gLineChart *lc = nullptr; gLineChart *lc = nullptr;
graphlist[schema::channel[CPAP_MaskPressure].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_MaskPressure, COLOR_MaskPressure, false))); graphlist[schema::channel[CPAP_MaskPressure].code()]->AddLayer(AddCPAP(new gLineChart(CPAP_MaskPressure, COLOR_MaskPressure, false)));
graphlist[schema::channel[CPAP_RespRate].label()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_RespRate, COLOR_RespRate, square))); graphlist[schema::channel[CPAP_RespRate].code()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_RespRate, COLOR_RespRate, square)));
graphlist[schema::channel[POS_Inclination].label()]->AddLayer(AddPOS(new gLineChart(POS_Inclination))); graphlist[schema::channel[POS_Inclination].code()]->AddLayer(AddPOS(new gLineChart(POS_Inclination)));
graphlist[schema::channel[POS_Orientation].label()]->AddLayer(AddPOS(new gLineChart(POS_Orientation))); graphlist[schema::channel[POS_Orientation].code()]->AddLayer(AddPOS(new gLineChart(POS_Orientation)));
graphlist[schema::channel[CPAP_MinuteVent].label()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_MinuteVent, COLOR_MinuteVent, square))); graphlist[schema::channel[CPAP_MinuteVent].code()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_MinuteVent, COLOR_MinuteVent, square)));
lc->addPlot(CPAP_TgMV,COLOR_TgMV,square); lc->addPlot(CPAP_TgMV,COLOR_TgMV,square);
graphlist[schema::channel[CPAP_TidalVolume].label()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_TidalVolume,COLOR_TidalVolume,square))); graphlist[schema::channel[CPAP_TidalVolume].code()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_TidalVolume,COLOR_TidalVolume,square)));
//lc->addPlot(CPAP_Test2,COLOR_DarkYellow,square); //lc->addPlot(CPAP_Test2,COLOR_DarkYellow,square);
//graphlist[schema::channel[CPAP_TidalVolume].label()]->AddLayer(AddCPAP(new gLineChart("TidalVolume2",COLOR_Magenta,square))); //graphlist[schema::channel[CPAP_TidalVolume].code()]->AddLayer(AddCPAP(new gLineChart("TidalVolume2",COLOR_Magenta,square)));
graphlist[schema::channel[CPAP_FLG].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_FLG, COLOR_FLG, true))); graphlist[schema::channel[CPAP_FLG].code()]->AddLayer(AddCPAP(new gLineChart(CPAP_FLG, COLOR_FLG, true)));
//graphlist[schema::channel[CPAP_RespiratoryEvent].label()]->AddLayer(AddCPAP(new gLineChart(CPAP_RespiratoryEvent,COLOR_Magenta,true))); //graphlist[schema::channel[CPAP_RespiratoryEvent].code()]->AddLayer(AddCPAP(new gLineChart(CPAP_RespiratoryEvent,COLOR_Magenta,true)));
graphlist[schema::channel[CPAP_IE].label()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_IE, COLOR_IE, square))); graphlist[schema::channel[CPAP_IE].code()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_IE, COLOR_IE, square)));
graphlist[schema::channel[CPAP_Te].label()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_Te, COLOR_Te, square))); graphlist[schema::channel[CPAP_Te].code()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_Te, COLOR_Te, square)));
graphlist[schema::channel[CPAP_Ti].label()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_Ti, COLOR_Ti, square))); graphlist[schema::channel[CPAP_Ti].code()]->AddLayer(AddCPAP(lc=new gLineChart(CPAP_Ti, COLOR_Ti, square)));
//lc->addPlot(CPAP_Test2,COLOR:DarkYellow,square); //lc->addPlot(CPAP_Test2,COLOR:DarkYellow,square);
graphlist[schema::channel[ZEO_SleepStage].label()]->AddLayer(AddSTAGE(new gLineChart(ZEO_SleepStage, COLOR_SleepStage, true))); graphlist[schema::channel[ZEO_SleepStage].code()]->AddLayer(AddSTAGE(new gLineChart(ZEO_SleepStage, COLOR_SleepStage, true)));
gLineOverlaySummary *los1=new gLineOverlaySummary(STR_UNIT_EventsPerHour,5,-4); gLineOverlaySummary *los1=new gLineOverlaySummary(STR_UNIT_EventsPerHour,5,-4);
gLineOverlaySummary *los2=new gLineOverlaySummary(STR_UNIT_EventsPerHour,5,-4); gLineOverlaySummary *los2=new gLineOverlaySummary(STR_UNIT_EventsPerHour,5,-4);
graphlist[schema::channel[OXI_Pulse].label()]->AddLayer(AddOXI(los1->add(new gLineOverlayBar(OXI_PulseChange, COLOR_PulseChange, STR_TR_PC,FT_Span)))); graphlist[schema::channel[OXI_Pulse].code()]->AddLayer(AddOXI(los1->add(new gLineOverlayBar(OXI_PulseChange, COLOR_PulseChange, STR_TR_PC,FT_Span))));
graphlist[schema::channel[OXI_Pulse].label()]->AddLayer(AddOXI(los1)); graphlist[schema::channel[OXI_Pulse].code()]->AddLayer(AddOXI(los1));
graphlist[schema::channel[OXI_SPO2].label()]->AddLayer(AddOXI(los2->add(new gLineOverlayBar(OXI_SPO2Drop, COLOR_SPO2Drop, STR_TR_O2,FT_Span)))); graphlist[schema::channel[OXI_SPO2].code()]->AddLayer(AddOXI(los2->add(new gLineOverlayBar(OXI_SPO2Drop, COLOR_SPO2Drop, STR_TR_O2,FT_Span))));
graphlist[schema::channel[OXI_SPO2].label()]->AddLayer(AddOXI(los2)); graphlist[schema::channel[OXI_SPO2].code()]->AddLayer(AddOXI(los2));
graphlist[schema::channel[OXI_Pulse].label()]->AddLayer(AddOXI(new gLineChart(OXI_Pulse, COLOR_Pulse, square))); graphlist[schema::channel[OXI_Pulse].code()]->AddLayer(AddOXI(new gLineChart(OXI_Pulse, COLOR_Pulse, square)));
graphlist[schema::channel[OXI_SPO2].label()]->AddLayer(AddOXI(new gLineChart(OXI_SPO2, COLOR_SPO2, true))); graphlist[schema::channel[OXI_SPO2].code()]->AddLayer(AddOXI(new gLineChart(OXI_SPO2, COLOR_SPO2, true)));
graphlist[schema::channel[OXI_Plethy].label()]->AddLayer(AddOXI(new gLineChart(OXI_Plethy, COLOR_Plethy,false))); graphlist[schema::channel[OXI_Plethy].code()]->AddLayer(AddOXI(new gLineChart(OXI_Plethy, COLOR_Plethy,false)));
// Fix me // Fix me
@ -370,8 +373,8 @@ Daily::Daily(QWidget *parent,gGraphView * shared)
graphlist["INTSPO2"]->AddLayer(AddCPAP(los4)); graphlist["INTSPO2"]->AddLayer(AddCPAP(los4));
graphlist["INTSPO2"]->AddLayer(AddCPAP(new gLineChart(OXI_SPO2, COLOR_SPO2, true))); graphlist["INTSPO2"]->AddLayer(AddCPAP(new gLineChart(OXI_SPO2, COLOR_SPO2, true)));
graphlist[schema::channel[CPAP_PTB].label()]->setForceMaxY(100); graphlist[schema::channel[CPAP_PTB].code()]->setForceMaxY(100);
graphlist[schema::channel[OXI_SPO2].label()]->setForceMaxY(100); graphlist[schema::channel[OXI_SPO2].code()]->setForceMaxY(100);
for (it = graphlist.begin(); it != graphlist.end(); ++it) { for (it = graphlist.begin(); it != graphlist.end(); ++it) {
if (skipgraph.contains(it.key())) continue; if (skipgraph.contains(it.key())) continue;
@ -967,23 +970,23 @@ QString Daily::getMachineSettings(Day * cpap) {
return html; return html;
} }
if (cpap->settingExists(CPAP_PresReliefType)) { ChannelID pr_level_chan = NoChannel;
int i=cpap->settings_max(CPAP_PresReliefType); ChannelID pr_mode_chan = NoChannel;
int j=cpap->settings_max(CPAP_PresReliefMode); CPAPLoader * loader = dynamic_cast<CPAPLoader *>(cpap->machine->loader());
QString flexstr; if (loader) {
pr_level_chan = loader->PresReliefLevel();
if (cpap->machine->loaderName() == STR_MACH_ResMed) { pr_mode_chan = loader->PresReliefMode();
// this is temporary..
flexstr = QString(tr("EPR:%1 EPR_LEVEL:%2")).arg(cpap->settings_max(RMS9_EPR)).arg(cpap->settings_max(RMS9_EPRLevel));
} else {
flexstr = (i>1) ? schema::channel[CPAP_PresReliefType].option(i)+" x"+QString::number(j) : STR_TR_None;
} }
if ((pr_level_chan != NoChannel) && (cpap->settingExists(pr_level_chan))) {
QString flexstr = cpap->getPressureRelief();
html+=QString("<tr><td><a class='info' href='#'>%1<span>%2</span></a></td><td colspan=4>%3</td></tr>") html+=QString("<tr><td><a class='info' href='#'>%1<span>%2</span></a></td><td colspan=4>%3</td></tr>")
.arg(STR_TR_PrRelief) .arg(schema::channel[pr_mode_chan].label())
.arg(schema::channel[CPAP_PresReliefType].description()) .arg(schema::channel[pr_mode_chan].description())
.arg(flexstr); .arg(flexstr);
} }
QString mclass=cpap->machine->loaderName(); QString mclass=cpap->machine->loaderName();
if (mclass==STR_MACH_PRS1 || mclass==STR_MACH_FPIcon) { if (mclass==STR_MACH_PRS1 || mclass==STR_MACH_FPIcon) {
int humid=round(cpap->settings_wavg(CPAP_HumidSetting)); int humid=round(cpap->settings_wavg(CPAP_HumidSetting));

View File

@ -20,19 +20,10 @@ Important: One id code per item, DO NOT CHANGE ID NUMBERS!!!
<channel id="0x1163" class="data" name="BrokenSummary" details="Broken Summary" label="Broken Summary" unit="" color="black"/> <channel id="0x1163" class="data" name="BrokenSummary" details="Broken Summary" label="Broken Summary" unit="" color="black"/>
<channel id="0x1164" class="data" name="BrokenWaveform" details="Broken Waveform" label="Broken Waveform" unit="" color="black"/> <channel id="0x1164" class="data" name="BrokenWaveform" details="Broken Waveform" label="Broken Waveform" unit="" color="black"/>
<channel id="0x1165" class="setting" scope="!session" name="SmartFlex" details="SmartFlex" label="SmartFlex" type="integer"/>
<channel id="0x1166" class="data" name="PRS1_0F" details="Unknown 0F" label="U0F" unit="?" color="dark green"/> <channel id="0x1166" class="data" name="PRS1_0F" details="Unknown 0F" label="U0F" unit="?" color="dark green"/>
<channel id="0x1167" class="data" name="IntUnk1" details="Unknown 1" label="Unknown 1" unit="?" color="dark green"/> <channel id="0x1167" class="data" name="IntUnk1" details="Unknown 1" label="Unknown 1" unit="?" color="dark green"/>
<channel id="0x1168" class="data" name="IntUnk2" details="Unknown 2" label="Unknown 2" unit="?" color="dark green"/> <channel id="0x1168" class="data" name="IntUnk2" details="Unknown 2" label="Unknown 2" unit="?" color="dark green"/>
<channel id="0x1200" class="setting" scope="!session" name="PAPMode" details="PAP Mode" label="PAP Mode" type="integer">
<option id="0" value="CPAP"/>
<option id="1" value="Auto"/>
<option id="2" value="Fixed Bi-Level"/>
<option id="3" value="Auto Bi-Level"/>
<option id="4" value="ASV"/>
<option id="5" value="ASV Auto EPAP"/>
</channel>
<channel id="0x1201" class="setting" scope="!session" name="PresRelType" details="Pressure Relief" label="Pres. Relief" type="integer"> <channel id="0x1201" class="setting" scope="!session" name="PresRelType" details="Pressure Relief" label="Pres. Relief" type="integer">
<Option id="0" value=""/> <Option id="0" value=""/>
<Option id="1" value="None"/> <Option id="1" value="None"/>
@ -105,19 +96,6 @@ Important: One id code per item, DO NOT CHANGE ID NUMBERS!!!
<Option id="4" value="x4"/> <Option id="4" value="x4"/>
<Option id="5" value="x5"/> <Option id="5" value="x5"/>
</channel> </channel>
<channel id="0xe105" class="setting" scope="!session" name="FlexMode" details="Pressure Relief Mode" label="Flex Mode" type="integer">
<Option id="1" value="None"/>
<Option id="2" value="C-Flex"/>
<Option id="3" value="C-Flex+"/>
<Option id="4" value="A-Flex"/>
<Option id="5" value="Bi-Flex"/>
</channel>
<channel id="0xe106" class="setting" scope="!session" name="FlexSet" details="Pressure Relief Setting" label="Flex Set." type="integer">
<Option id="0" value=""/>
<Option id="1" value="x1"/>
<Option id="2" value="x2"/>
<Option id="3" value="x3"/>
</channel>
<channel id="0xe107" class="setting" scope="!session" name="HoseDiam" details="Hose Diameter" label="Hose Diameter" type="bool"> <channel id="0xe107" class="setting" scope="!session" name="HoseDiam" details="Hose Diameter" label="Hose Diameter" type="bool">
<Option id="0" value="22mm"/> <Option id="0" value="22mm"/>
<Option id="1" value="15mm"/> <Option id="1" value="15mm"/>
@ -158,18 +136,6 @@ Important: One id code per item, DO NOT CHANGE ID NUMBERS!!!
<Option id="2" value="VPAP"/> <Option id="2" value="VPAP"/>
<Option id="3" value="ASV"/> <Option id="3" value="ASV"/>
</channel> </channel>
<channel id="0xe201" class="setting" scope="!session" name="EPR" details="EPR Mode" label="EPR Mode" type="integer">
<Option id="0" value="Off"/>
<Option id="1" value="Ramp Only"/>
<Option id="2" value="Full Time"/>
<Option id="3" value="EPR?"/>
</channel>
<channel id="0xe202" class="setting" scope="!session" name="EPRLevel" details="EPR Setting" label="EPR Setting" type="integer">
<Option id="0" value="0"/>
<Option id="1" value="1"/>
<Option id="2" value="2"/>
<Option id="3" value="3"/>
</channel>
</group> </group>
<group name="MACHINE"> <group name="MACHINE">
<!-- General Per Machine Settings --> <!-- General Per Machine Settings -->

View File

@ -46,6 +46,7 @@
#include "SleepLib/loader_plugins/resmed_loader.h" #include "SleepLib/loader_plugins/resmed_loader.h"
#include "SleepLib/loader_plugins/intellipap_loader.h" #include "SleepLib/loader_plugins/intellipap_loader.h"
#include "SleepLib/loader_plugins/icon_loader.h" #include "SleepLib/loader_plugins/icon_loader.h"
#include "SleepLib/loader_plugins/weinmann_loader.h"
#ifdef Q_WS_X11 #ifdef Q_WS_X11
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -267,6 +268,7 @@ retry_directory:
ResmedLoader::Register(); ResmedLoader::Register();
IntellipapLoader::Register(); IntellipapLoader::Register();
FPIconLoader::Register(); FPIconLoader::Register();
WeinmannLoader::Register();
CMS50Loader::Register(); CMS50Loader::Register();
MD300W1Loader::Register(); MD300W1Loader::Register();
//ZEOLoader::Register(); // Use outside of directory importer.. //ZEOLoader::Register(); // Use outside of directory importer..

View File

@ -232,8 +232,9 @@ Overview::Overview(QWidget *parent, gGraphView *shared) :
set = new SummaryChart("", GT_POINTS); set = new SummaryChart("", GT_POINTS);
//set->addSlice(PRS1_SysOneResistSet,COLOR_Gray,ST_SETAVG); //set->addSlice(PRS1_SysOneResistSet,COLOR_Gray,ST_SETAVG);
set->addSlice(CPAP_HumidSetting, COLOR_Blue, ST_SETWAVG); set->addSlice(CPAP_HumidSetting, COLOR_Blue, ST_SETWAVG);
set->addSlice(CPAP_PresReliefSet, COLOR_Red, ST_SETWAVG); set->addSlice(CPAP_PresReliefLevel, COLOR_Red, ST_SETWAVG);
set->addSlice(RMS9_EPRLevel,COLOR_Green,ST_SETWAVG); set->addSlice(CPAP_PresReliefMode, COLOR_Red, ST_SETWAVG);
// set->addSlice(RMS9_EPRLevel,COLOR_Green,ST_SETWAVG);
//set->addSlice(INTP_SmartFlex,COLOR_Purple,ST_SETWAVG); //set->addSlice(INTP_SmartFlex,COLOR_Purple,ST_SETWAVG);
SET->AddLayer(set); SET->AddLayer(set);

View File

@ -425,7 +425,7 @@ SleepyHead can keep a copy of this data if you ever need to reinstall.
(Highly recomended, unless your short on disk space or don't care about the graph data)</string> (Highly recomended, unless your short on disk space or don't care about the graph data)</string>
</property> </property>
<property name="text"> <property name="text">
<string>Create SD Card Backups during Import (This is fairly important for ResMed and FP ICON)</string> <string>Create SD Card Backups during Import (Turn this off at your own peril!)</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -177,7 +177,9 @@ SOURCES += \
SleepLib/loader_plugins/md300w1_loader.cpp \ SleepLib/loader_plugins/md300w1_loader.cpp \
Graphs/gSessionTimesChart.cpp \ Graphs/gSessionTimesChart.cpp \
logger.cpp \ logger.cpp \
welcome.cpp welcome.cpp \
SleepLib/machine_common.cpp \
SleepLib/loader_plugins/weinmann_loader.cpp
HEADERS += \ HEADERS += \
common_gui.h \ common_gui.h \
@ -232,7 +234,8 @@ HEADERS += \
SleepLib/serialoximeter.h \ SleepLib/serialoximeter.h \
SleepLib/loader_plugins/md300w1_loader.h \ SleepLib/loader_plugins/md300w1_loader.h \
Graphs/gSessionTimesChart.h \ Graphs/gSessionTimesChart.h \
logger.h logger.h \
SleepLib/loader_plugins/weinmann_loader.h
FORMS += \ FORMS += \
daily.ui \ daily.ui \

View File

@ -261,8 +261,8 @@ struct RXChange {
per2 = copy.per2; per2 = copy.per2;
highlight = copy.highlight; highlight = copy.highlight;
weighted = copy.weighted; weighted = copy.weighted;
prelief = copy.prelief; pressure_string = copy.pressure_string;
prelset = copy.prelset; pr_relief_string = copy.pr_relief_string;
} }
QDate first; QDate first;
QDate last; QDate last;
@ -270,6 +270,8 @@ struct RXChange {
EventDataType ahi; EventDataType ahi;
EventDataType fl; EventDataType fl;
CPAPMode mode; CPAPMode mode;
QString pressure_string;
QString pr_relief_string;
EventDataType min; EventDataType min;
EventDataType max; EventDataType max;
EventDataType ps; EventDataType ps;
@ -278,9 +280,7 @@ struct RXChange {
EventDataType per1; EventDataType per1;
EventDataType per2; EventDataType per2;
EventDataType weighted; EventDataType weighted;
PRTypes prelief;
Machine *machine; Machine *machine;
short prelset;
short highlight; short highlight;
}; };
@ -744,8 +744,7 @@ QString Statistics::GenerateHTML()
EventDataType cmin = 0, cmax = 0, cps = 0, cpshi = 0, cmaxipap = 0, min = 0, max = 0, maxipap = 0, EventDataType cmin = 0, cmax = 0, cps = 0, cpshi = 0, cmaxipap = 0, min = 0, max = 0, maxipap = 0,
ps = 0, pshi = 0; ps = 0, pshi = 0;
Machine *mach = nullptr, *lastmach = nullptr; Machine *mach = nullptr, *lastmach = nullptr;
PRTypes lastpr = PR_UNKNOWN, prelief = PR_UNKNOWN; QString last_prel_str, last_pressure_str, prel_str, pressure_str;
short prelset = 0, lastprelset = -1;
QDate date = lastcpap; QDate date = lastcpap;
Day *day; Day *day;
bool lastchanged = false; bool lastchanged = false;
@ -757,7 +756,12 @@ QString Statistics::GenerateHTML()
do { do {
day = p_profile->GetGoodDay(date, MT_CPAP); day = p_profile->GetGoodDay(date, MT_CPAP);
if (day) {
CPAPLoader * loader = nullptr;
if (day) loader = dynamic_cast<CPAPLoader *>(day->machine->loader());
if (day && loader) {
lastchanged = false; lastchanged = false;
hours = day->hours(); hours = day->hours();
@ -766,17 +770,20 @@ QString Statistics::GenerateHTML()
compliant++; compliant++;
} }
EventDataType ahi = day->count(CPAP_Obstructive) + day->count(CPAP_Hypopnea) + day->count( EventDataType ahi = day->count(CPAP_Obstructive) + day->count(CPAP_Hypopnea) + day->count(CPAP_Apnea) + day->count(CPAP_ClearAirway);
CPAP_Apnea) + day->count(CPAP_ClearAirway);
if (p_profile->general->calculateRDI()) { ahi += day->count(CPAP_RERA); } if (p_profile->general->calculateRDI()) { ahi += day->count(CPAP_RERA); }
ahi /= hours; ahi /= hours;
AHI.push_back(UsageData(date, ahi, hours)); AHI.push_back(UsageData(date, ahi, hours));
prelief = (PRTypes)(int)round(day->settings_wavg(CPAP_PresReliefType)); prel_str = day->getPressureRelief();
prelset = round(day->settings_max(CPAP_PresReliefSet)); pressure_str = day->getPressureSettings();
mode = (CPAPMode)(int)round(day->settings_wavg(CPAP_Mode)); mode = (CPAPMode)(int)round(day->settings_wavg(CPAP_Mode));
if (mode ==0) {
mode = (CPAPMode)(int)round(day->settings_wavg(CPAP_Mode));
}
mach = day->machine; mach = day->machine;
min = max = ps = pshi = maxipap = 0; min = max = ps = pshi = maxipap = 0;
@ -794,6 +801,12 @@ QString Statistics::GenerateHTML()
min = day->settings_min(CPAP_EPAPLo); min = day->settings_min(CPAP_EPAPLo);
maxipap = max = day->settings_max(CPAP_IPAPHi); maxipap = max = day->settings_max(CPAP_IPAPHi);
ps = day->settings_min(CPAP_PS); ps = day->settings_min(CPAP_PS);
} else if (mode == MODE_BILEVEL_AUTO_VARIABLE_PS) { // Similar pressure control as ASV Variable EPAP
min = day->settings_min(CPAP_EPAPLo);
max = day->settings_min(CPAP_EPAPHi);
ps = day->settings_min(CPAP_PSMin);
pshi = day->settings_max(CPAP_PSMax);
maxipap = max = day->settings_max(CPAP_IPAPHi);
} else if (mode == MODE_ASV) { } else if (mode == MODE_ASV) {
min = day->settings_min(CPAP_EPAPLo); min = day->settings_min(CPAP_EPAPLo);
ps = day->settings_min(CPAP_PSMin); ps = day->settings_min(CPAP_PSMin);
@ -805,11 +818,18 @@ QString Statistics::GenerateHTML()
ps = day->settings_min(CPAP_PSMin); ps = day->settings_min(CPAP_PSMin);
pshi = day->settings_max(CPAP_PSMax); pshi = day->settings_max(CPAP_PSMax);
maxipap = max + pshi; maxipap = max + pshi;
} }
if ((mode != cmode) || (min != cmin) || (max != cmax) || (ps != cps) || (pshi != cpshi) if (lastmach == nullptr) {
|| (maxipap != cmaxipap) || (mach != lastmach) || (prelset != lastprelset)) { lastmach = mach;
if ((cmode != MODE_UNKNOWN) && (lastmach != nullptr)) { cmode = mode;
last_pressure_str = pressure_str;
last_prel_str = prel_str;
}
if ((mode != cmode) || (pressure_str != last_pressure_str) || (prel_str != last_prel_str) || (mach != lastmach)) {
first = date.addDays(1); first = date.addDays(1);
int days = p_profile->countDays(MT_CPAP, first, last); int days = p_profile->countDays(MT_CPAP, first, last);
RXChange rx; RXChange rx;
@ -819,13 +839,13 @@ QString Statistics::GenerateHTML()
rx.ahi = calcAHI(first, last); rx.ahi = calcAHI(first, last);
rx.fl = calcFL(first, last); rx.fl = calcFL(first, last);
rx.mode = cmode; rx.mode = cmode;
rx.pressure_string = last_pressure_str;
rx.pr_relief_string = last_prel_str;
rx.min = cmin; rx.min = cmin;
rx.max = cmax; rx.max = cmax;
rx.ps = cps; rx.ps = cps;
rx.pshi = cpshi; rx.pshi = cpshi;
rx.maxipap = cmaxipap; rx.maxipap = cmaxipap;
rx.prelief = lastpr;
rx.prelset = lastprelset;
rx.machine = lastmach; rx.machine = lastmach;
rx.per1 = 0; rx.per1 = 0;
rx.per2 = 0; rx.per2 = 0;
@ -836,6 +856,9 @@ QString Statistics::GenerateHTML()
} else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) { } else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) {
rx.per1 = p_profile->calcPercentile(CPAP_EPAP, percentile, MT_CPAP, first, last); rx.per1 = p_profile->calcPercentile(CPAP_EPAP, percentile, MT_CPAP, first, last);
rx.per2 = p_profile->calcPercentile(CPAP_IPAP, percentile, MT_CPAP, first, last); rx.per2 = p_profile->calcPercentile(CPAP_IPAP, percentile, MT_CPAP, first, last);
} else if (mode == MODE_BILEVEL_AUTO_VARIABLE_PS) {
rx.per1 = p_profile->calcPercentile(CPAP_EPAP, percentile, MT_CPAP, first, last);
rx.per2 = p_profile->calcPercentile(CPAP_PS, percentile, MT_CPAP, first, last);
} else if (mode == MODE_ASV) { } else if (mode == MODE_ASV) {
rx.per1 = p_profile->calcPercentile(CPAP_PS, percentile, MT_CPAP, first, last); rx.per1 = p_profile->calcPercentile(CPAP_PS, percentile, MT_CPAP, first, last);
rx.per2 = p_profile->calcPercentile(CPAP_PS, percentile, MT_CPAP, first, last); rx.per2 = p_profile->calcPercentile(CPAP_PS, percentile, MT_CPAP, first, last);
@ -846,7 +869,6 @@ QString Statistics::GenerateHTML()
rx.weighted = float(rx.days) / float(cpapdays) * rx.ahi; rx.weighted = float(rx.days) / float(cpapdays) * rx.ahi;
rxchange.push_back(rx); rxchange.push_back(rx);
}
cmode = mode; cmode = mode;
cmin = min; cmin = min;
@ -854,8 +876,8 @@ QString Statistics::GenerateHTML()
cps = ps; cps = ps;
cpshi = pshi; cpshi = pshi;
cmaxipap = maxipap; cmaxipap = maxipap;
lastpr = prelief; last_prel_str = prel_str;
lastprelset = prelset; last_pressure_str = pressure_str;
last = date; last = date;
lastmach = mach; lastmach = mach;
lastchanged = true; lastchanged = true;
@ -871,6 +893,7 @@ QString Statistics::GenerateHTML()
lastchanged = false; lastchanged = false;
// Add the final entry
if (!lastchanged && (mach != nullptr)) { if (!lastchanged && (mach != nullptr)) {
// last=date.addDays(1); // last=date.addDays(1);
first = firstcpap; first = firstcpap;
@ -887,16 +910,20 @@ QString Statistics::GenerateHTML()
rx.ps = ps; rx.ps = ps;
rx.pshi = pshi; rx.pshi = pshi;
rx.maxipap = maxipap; rx.maxipap = maxipap;
rx.prelief = prelief;
rx.prelset = prelset;
rx.machine = mach; rx.machine = mach;
rx.pressure_string = pressure_str;
rx.pr_relief_string = prel_str;
// Todo: Clean up by Calculating this crap later..
if (mode == MODE_APAP) { if (mode == MODE_APAP) {
rx.per1 = p_profile->calcPercentile(CPAP_Pressure, percentile, MT_CPAP, first, last); rx.per1 = p_profile->calcPercentile(CPAP_Pressure, percentile, MT_CPAP, first, last);
rx.per2 = 0; rx.per2 = 0;
} else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) { } else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) {
rx.per1 = p_profile->calcPercentile(CPAP_EPAP, percentile, MT_CPAP, first, last); rx.per1 = p_profile->calcPercentile(CPAP_EPAP, percentile, MT_CPAP, first, last);
rx.per2 = p_profile->calcPercentile(CPAP_IPAP, percentile, MT_CPAP, first, last); rx.per2 = p_profile->calcPercentile(CPAP_IPAP, percentile, MT_CPAP, first, last);
} else if (mode == MODE_BILEVEL_AUTO_VARIABLE_PS) {
rx.per1 = p_profile->calcPercentile(CPAP_EPAP, percentile, MT_CPAP, first, last);
rx.per2 = p_profile->calcPercentile(CPAP_PS, percentile, MT_CPAP, first, last);
} else if (mode == MODE_ASV) { } else if (mode == MODE_ASV) {
rx.per1 = p_profile->calcPercentile(CPAP_PS, percentile, MT_CPAP, first, last); rx.per1 = p_profile->calcPercentile(CPAP_PS, percentile, MT_CPAP, first, last);
rx.per2 = p_profile->calcPercentile(CPAP_PS, percentile, MT_CPAP, first, last); rx.per2 = p_profile->calcPercentile(CPAP_PS, percentile, MT_CPAP, first, last);
@ -1013,12 +1040,15 @@ QString Statistics::GenerateHTML()
modestr = STR_TR_BiLevel; modestr = STR_TR_BiLevel;
} else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) { } else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) {
modestr = QObject::tr("Auto Bi-Level"); modestr = QObject::tr("Auto Bi-Level");
} else if (mode == MODE_BILEVEL_AUTO_VARIABLE_PS) {
modestr = QObject::tr("Auto Bi-Level");
} else if (mode == MODE_ASV) { } else if (mode == MODE_ASV) {
modestr = QObject::tr("ASV"); modestr = QObject::tr("ASV Fixed EPAP");
} else if (mode == MODE_ASV_VARIABLE_EPAP) { } else if (mode == MODE_ASV_VARIABLE_EPAP) {
modestr = QObject::tr("ASV AutoEPAP"); modestr = QObject::tr("ASV Auto EPAP");
} else modestr = STR_TR_Unknown; } else modestr = STR_TR_Unknown;
recbox += QString("<tr><td colspan=2><table width=100% border=0 cellpadding=1 cellspacing=0><tr><td colspan=2 align=center><b>%3</b></td></tr>") recbox += QString("<tr><td colspan=2><table width=100% border=0 cellpadding=1 cellspacing=0><tr><td colspan=2 align=center><b>%3</b></td></tr>")
.arg(idxstr[i]); .arg(idxstr[i]);
recbox += QString("<tr><td valign=top>") + STR_TR_Start + "<br/>" + STR_TR_End + recbox += QString("<tr><td valign=top>") + STR_TR_Start + "<br/>" + STR_TR_End +
@ -1080,7 +1110,7 @@ QString Statistics::GenerateHTML()
hdrlist.push_back(STR_TR_SA); hdrlist.push_back(STR_TR_SA);
} }
hdrlist.push_back(STR_TR_Machine); hdrlist.push_back(STR_TR_Machine);
hdrlist.push_back(tr("Pr. Rel.")); hdrlist.push_back(tr("Pressure Relief"));
hdrlist.push_back(STR_TR_Mode); hdrlist.push_back(STR_TR_Mode);
hdrlist.push_back(tr("Pressure Settings")); hdrlist.push_back(tr("Pressure Settings"));
@ -1135,40 +1165,38 @@ QString Statistics::GenerateHTML()
// QString("=%1<br/>%2% ").arg(rx.per1,0,'f',decimals).arg(percentile*100.0)+ // QString("=%1<br/>%2% ").arg(rx.per1,0,'f',decimals).arg(percentile*100.0)+
// STR_TR_IPAP+QString("=%1").arg(rx.per2,0,'f',decimals); // STR_TR_IPAP+QString("=%1").arg(rx.per2,0,'f',decimals);
tooltip = QString("%1").arg(machstr); tooltip = QString("%1").arg(machstr);
if (mode == MODE_CPAP) {
extratxt += "<td colspan=2>"+QString(tr("Fixed %1 %2")+"</td>").arg(rx.min, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units()); extratxt += "<td colspan=2>"+rx.pressure_string+"</td>";
} else if (mode == MODE_APAP) { // if (mode == MODE_CPAP) {
extratxt += "<td colspan=2>"+QString(tr("%1 - %2 %3")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.max, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units()); // extratxt += "<td colspan=2>"+QString(tr("Fixed %1 %2")+"</td>").arg(rx.min, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units());
} else if (mode == MODE_BILEVEL_FIXED) { // } else if (mode == MODE_APAP) {
extratxt += "<td colspan=2>"+QString(tr("EPAP %1 %3 IPAP %2 %3")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.max, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units()); // extratxt += "<td colspan=2>"+QString(tr("%1 - %2 %3")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.max, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units());
} else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) { // } else if (mode == MODE_BILEVEL_FIXED) {
extratxt += "<td colspan=2>"+QString(tr("PS %4 over %1 - %2 %3")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.max, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units()).arg(rx.ps, 4, 'f', 1); // extratxt += "<td colspan=2>"+QString(tr("EPAP %1 %3 IPAP %2 %3")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.max, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units());
} else if (mode == MODE_ASV) { // } else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) {
extratxt += "<td colspan=2>"+QString(tr("EPAP %1, PS %2-%3 %4")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.ps, 4, 'f', 1).arg(rx.pshi, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units()); // extratxt += "<td colspan=2>"+QString(tr("PS %4 over %1 - %2 %3")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.max, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units()).arg(rx.ps, 4, 'f', 1);
tooltip = QString("%1 %2% ").arg(machstr).arg(percentile * 100.0) + // } else if (mode == MODE_BILEVEL_AUTO_VARIABLE_PS) {
STR_TR_EPAP + // extratxt += "<td colspan=2>"+QString(tr("EPAP %1-%2, PS %3-%4 %5")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.max, 4, 'f', 1).arg(rx.ps, 4, 'f', 1).arg(rx.pshi, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units());
QString("=%1<br/>%2% ").arg(rx.per1, 0, 'f', decimals) // } else if (mode == MODE_ASV) {
.arg(percentile * 100.0) // extratxt += "<td colspan=2>"+QString(tr("EPAP %1, PS %2-%3 %4")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.ps, 4, 'f', 1).arg(rx.pshi, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units());
+ STR_TR_IPAP + QString("=%1").arg(rx.per2, 0, 'f', decimals); // tooltip = QString("%1 %2% ").arg(machstr).arg(percentile * 100.0) +
} else if (mode == MODE_ASV_VARIABLE_EPAP) { // STR_TR_EPAP +
extratxt += "<td colspan=2>"+QString(tr("EPAP %1-%2, PS %3-%4 %5")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.max, 4, 'f', 1).arg(rx.ps, 4, 'f', 1).arg(rx.pshi, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units()); // QString("=%1<br/>%2% ").arg(rx.per1, 0, 'f', decimals)
tooltip = QString("%1 %2% ").arg(machstr).arg(percentile * 100.0) + // .arg(percentile * 100.0)
STR_TR_EPAP + // + STR_TR_IPAP + QString("=%1").arg(rx.per2, 0, 'f', decimals);
QString("=%1<br/>%2% ").arg(rx.per1, 0, 'f', decimals) // } else if (mode == MODE_ASV_VARIABLE_EPAP) {
.arg(percentile * 100.0) // extratxt += "<td colspan=2>"+QString(tr("EPAP %1-%2, PS %3-%4 %5")+"</td>").arg(rx.min, 4, 'f', 1).arg(rx.max, 4, 'f', 1).arg(rx.ps, 4, 'f', 1).arg(rx.pshi, 4, 'f', 1).arg(schema::channel[CPAP_Pressure].units());
+ STR_TR_IPAP + QString("=%1").arg(rx.per2, 0, 'f', decimals); // tooltip = QString("%1 %2% ").arg(machstr).arg(percentile * 100.0) +
} else { // STR_TR_EPAP +
extratxt += ""; // QString("=%1<br/>%2% ").arg(rx.per1, 0, 'f', decimals)
tooltip = ""; // .arg(percentile * 100.0)
} // + STR_TR_IPAP + QString("=%1").arg(rx.per2, 0, 'f', decimals);
// } else {
// extratxt += "";
// tooltip = "";
// }
extratxt += "</tr></table>"; extratxt += "</tr></table>";
QString presrel;
if (rx.prelset > 0) {
presrel = schema::channel[CPAP_PresReliefType].option(int(rx.prelief));
presrel += QString(" x%1").arg(rx.prelset);
} else { presrel = STR_TR_None; }
QString tooltipshow, tooltiphide; QString tooltipshow, tooltiphide;
@ -1198,8 +1226,8 @@ QString Statistics::GenerateHTML()
html += QString("<td>%1</td>").arg(calcSA(rx.first, rx.last), 0, 'f', decimals); html += QString("<td>%1</td>").arg(calcSA(rx.first, rx.last), 0, 'f', decimals);
} }
html += QString("<td>%1</td>").arg(rx.machine->loaderName()); html += QString("<td>%1</td>").arg(rx.machine->loaderName());
html += QString("<td>%1</td>").arg(presrel); html += QString("<td>%1</td>").arg(rx.pr_relief_string);
html += QString("<td>%1</td>").arg(schema::channel[CPAP_Mode].option(int(rx.mode) - 1)); html += QString("<td>%1</td>").arg(schema::channel[CPAP_Mode].option(int(rx.mode)));
html += QString("<td>%1</td>").arg(extratxt); html += QString("<td>%1</td>").arg(extratxt);
html += "</tr>"; html += "</tr>";
} }