diff --git a/oscar/SleepLib/loader_plugins/zeo_loader.cpp b/oscar/SleepLib/loader_plugins/zeo_loader.cpp index 8df0b9fe..647e709a 100644 --- a/oscar/SleepLib/loader_plugins/zeo_loader.cpp +++ b/oscar/SleepLib/loader_plugins/zeo_loader.cpp @@ -83,15 +83,17 @@ int ZEOLoader::Open(const QString & dirpath) int ZEOLoader::OpenFile(const QString & filename) { if (!openCSV(filename)) { - return 0; + return -1; } + int count = 0; Session* sess; while ((sess = readNextSession()) != nullptr) { sess->SetChanged(true); mach->AddSession(sess); + count++; } mach->Save(); - return true; + return count; } bool ZEOLoader::openCSV(const QString & filename) @@ -101,11 +103,11 @@ bool ZEOLoader::openCSV(const QString & filename) if (filename.toLower().endsWith(".csv")) { if (!file.open(QFile::ReadOnly)) { qDebug() << "Couldn't open zeo file" << filename; - return 0; + return false; } } else {// if (filename.toLower().endsWith(".dat")) { - return 0; + return false; // not supported. } @@ -211,15 +213,15 @@ Session* ZEOLoader::readNextSession() if (!ok) { dodgy = true; } - start_of_night = QDateTime::fromString(linecomp[idxStartOfNight], "MM/dd/yyyy HH:mm"); + start_of_night = readDateTime(linecomp[idxStartOfNight]); if (!start_of_night.isValid()) { dodgy = true; } - end_of_night = QDateTime::fromString(linecomp[idxEndOfNight], "MM/dd/yyyy HH:mm"); + end_of_night = readDateTime(linecomp[idxEndOfNight]); if (!end_of_night.isValid()) { dodgy = true; } - rise_time = QDateTime::fromString(linecomp[idxRiseTime], "MM/dd/yyyy HH:mm"); + rise_time = readDateTime(linecomp[idxRiseTime]); if (!rise_time.isValid()) { dodgy = true; } @@ -244,31 +246,31 @@ Session* ZEOLoader::readNextSession() // if (!ok) { dodgy = true; } if (!linecomp[idxFirstAlaramRing].isEmpty()) { - FirstAlarmRing = QDateTime::fromString(linecomp[idxFirstAlaramRing], "MM/dd/yyyy HH:mm"); + FirstAlarmRing = readDateTime(linecomp[idxFirstAlaramRing]); if (!FirstAlarmRing.isValid()) { dodgy = true; } } if (!linecomp[idxLastAlaramRing].isEmpty()) { - LastAlarmRing = QDateTime::fromString(linecomp[idxLastAlaramRing], "MM/dd/yyyy HH:mm"); + LastAlarmRing = readDateTime(linecomp[idxLastAlaramRing]); if (!LastAlarmRing.isValid()) { dodgy = true; } } if (!linecomp[idxFirstSnoozeTime].isEmpty()) { - FirstSnoozeTime = QDateTime::fromString(linecomp[idxFirstSnoozeTime], "MM/dd/yyyy HH:mm"); + FirstSnoozeTime = readDateTime(linecomp[idxFirstSnoozeTime]); if (!FirstSnoozeTime.isValid()) { dodgy = true; } } if (!linecomp[idxLastSnoozeTime].isEmpty()) { - LastSnoozeTime = QDateTime::fromString(linecomp[idxLastSnoozeTime], "MM/dd/yyyy HH:mm"); + LastSnoozeTime = readDateTime(linecomp[idxLastSnoozeTime]); if (!LastSnoozeTime.isValid()) { dodgy = true; } } if (!linecomp[idxSetAlarmTime].isEmpty()) { - SetAlarmTime = QDateTime::fromString(linecomp[idxSetAlarmTime], "MM/dd/yyyy HH:mm"); + SetAlarmTime = readDateTime(linecomp[idxSetAlarmTime]); if (!SetAlarmTime.isValid()) { dodgy = true; } } @@ -331,16 +333,22 @@ Session* ZEOLoader::readNextSession() } sess->really_set_last(tt); - int size = DSG.size(); - - - qDebug() << linecomp[0] << start_of_night << end_of_night << rise_time << size << - "30 second chunks"; + //int size = DSG.size(); + //qDebug() << linecomp[0] << start_of_night << end_of_night << rise_time << size << "30 second chunks"; } return sess; } +QDateTime ZEOLoader::readDateTime(const QString & text) +{ + QDateTime dt = QDateTime::fromString(text, "MM/dd/yyyy HH:mm"); + if (!dt.isValid()) { + dt = QDateTime::fromString(text, "yyyy-MM-dd HH:mm:ss"); + } + return dt; +} + static bool zeo_initialized = false; void ZEOLoader::Register() diff --git a/oscar/SleepLib/loader_plugins/zeo_loader.h b/oscar/SleepLib/loader_plugins/zeo_loader.h index 343d0af0..3fc2c4ee 100644 --- a/oscar/SleepLib/loader_plugins/zeo_loader.h +++ b/oscar/SleepLib/loader_plugins/zeo_loader.h @@ -43,6 +43,8 @@ class ZEOLoader : public MachineLoader Session* readNextSession(); protected: + QDateTime readDateTime(const QString & text); + private: QFile file; QTextStream text; diff --git a/oscar/SleepLib/schema.cpp b/oscar/SleepLib/schema.cpp index c998a639..24ee3dde 100644 --- a/oscar/SleepLib/schema.cpp +++ b/oscar/SleepLib/schema.cpp @@ -328,7 +328,7 @@ void init() schema::channel.add(GRP_SLEEP, ch = new Channel(ZEO_TimeInREM = 0x2005, DATA, MT_SLEEPSTAGE, SESSION, "TimeInREM", QObject::tr("Time In REM Sleep"), QObject::tr("Time spent in REM Sleep"), QObject::tr("Time in REM Sleep"), STR_UNIT_Minutes, INTEGER, Qt::black)); schema::channel.add(GRP_SLEEP, ch = new Channel(ZEO_TimeInLight= 0x2006, DATA, MT_SLEEPSTAGE, SESSION, "TimeInLight",QObject::tr("Time In Light Sleep"), QObject::tr("Time spent in light sleep"), QObject::tr("Time in Light Sleep"), STR_UNIT_Minutes, INTEGER, Qt::black)); schema::channel.add(GRP_SLEEP, ch = new Channel(ZEO_TimeInDeep = 0x2007, DATA, MT_SLEEPSTAGE, SESSION, "TimeInDeep", QObject::tr("Time In Deep Sleep"), QObject::tr("Time spent in deep sleep"), QObject::tr("Time in Deep Sleep"), STR_UNIT_Minutes, INTEGER, Qt::black)); - schema::channel.add(GRP_SLEEP, ch = new Channel(ZEO_TimeInDeep = 0x2008, DATA, MT_SLEEPSTAGE, SESSION, "TimeToZ", QObject::tr("Time to Sleep"), QObject::tr("Time taken to get to sleep"), QObject::tr("Time to Sleep"), STR_UNIT_Minutes, INTEGER, Qt::black)); + schema::channel.add(GRP_SLEEP, ch = new Channel(ZEO_TimeToZ = 0x2008, DATA, MT_SLEEPSTAGE, SESSION, "TimeToZ", QObject::tr("Time to Sleep"), QObject::tr("Time taken to get to sleep"), QObject::tr("Time to Sleep"), STR_UNIT_Minutes, INTEGER, Qt::black)); schema::channel.add(GRP_SLEEP, ch = new Channel(ZEO_ZQ = 0x2009, DATA, MT_SLEEPSTAGE, SESSION, "ZeoZQ", QObject::tr("Zeo ZQ"), QObject::tr("Zeo sleep quality measurement"), QObject::tr("ZEO ZQ"), QString(), INTEGER, Qt::black)); NoChannel = 0; diff --git a/oscar/mainwindow.cpp b/oscar/mainwindow.cpp index da47b36e..2006fafa 100644 --- a/oscar/mainwindow.cpp +++ b/oscar/mainwindow.cpp @@ -2309,12 +2309,17 @@ void MainWindow::on_actionImport_ZEO_Data_triggered() if (w.exec() == QFileDialog::Accepted) { QString filename = w.selectedFiles()[0]; - if (!zeo.OpenFile(filename)) { - Notify(tr("There was a problem opening ZEO File: ") + filename); - return; + qDebug() << "Loading ZEO data from" << filename; + int c = zeo.OpenFile(filename); + if (c > 0) { + Notify(tr("Imported %1 ZEO session(s) from\n\n%2").arg(c).arg(filename), tr("Import Success")); + qDebug() << "Imported" << c << "ZEO sessions"; + } else if (c == 0) { + Notify(tr("Already up to date with ZEO data at\n\n%1").arg(filename), tr("Up to date")); + } else { + Notify(tr("Couldn't find any valid ZEO CSV data at\n\n%1").arg(filename),tr("Import Problem")); } - Notify(tr("Zeo CSV Import complete")); daily->LoadDate(daily->getDate()); } diff --git a/oscar/tests/sessiontests.cpp b/oscar/tests/sessiontests.cpp index 05da7d68..5bb43b7c 100644 --- a/oscar/tests/sessiontests.cpp +++ b/oscar/tests/sessiontests.cpp @@ -90,6 +90,14 @@ static QString settingChannel(ChannelID i) CHANNELNAME(PRS1_MaskAlert); CHANNELNAME(PRS1_ShowAHI); CHANNELNAME(CPAP_BrokenSummary); + CHANNELNAME(ZEO_Awakenings); + CHANNELNAME(ZEO_MorningFeel); + CHANNELNAME(ZEO_TimeInWake); + CHANNELNAME(ZEO_TimeInREM); + CHANNELNAME(ZEO_TimeInLight); + CHANNELNAME(ZEO_TimeInDeep); + CHANNELNAME(ZEO_TimeToZ); + CHANNELNAME(ZEO_ZQ); s = hex(i); qDebug() << "setting channel" << qPrintable(s); } while(false); @@ -137,6 +145,7 @@ static QString eventChannel(ChannelID i) CHANNELNAME(CPAP_IPAPSet); CHANNELNAME(CPAP_EPAPSet); CHANNELNAME(POS_Movement); + CHANNELNAME(ZEO_SleepStage); s = hex(i); qDebug() << "event channel" << qPrintable(s); } while(false); diff --git a/oscar/tests/zeotests.cpp b/oscar/tests/zeotests.cpp index ede0e6aa..942a2900 100644 --- a/oscar/tests/zeotests.cpp +++ b/oscar/tests/zeotests.cpp @@ -12,7 +12,7 @@ #define TESTDATA_PATH "./testdata/" static ZEOLoader* s_loader = nullptr; -static QString zeoOutputPath(const QString & inpath, const QString & suffix); +static QString zeoOutputPath(const QString & inpath, int sid, const QString & suffix); void ZeoTests::initTestCase(void) { @@ -37,12 +37,19 @@ static void parseAndEmitSessionYaml(const QString & path) qDebug() << path; if (s_loader->openCSV(path)) { + int count = 0; Session* session; while ((session = s_loader->readNextSession()) != nullptr) { - QString outpath = zeoOutputPath(path, "-session.yml"); + QString outpath = zeoOutputPath(path, session->session(), "-session.yml"); SessionToYaml(outpath, session, true); delete session; + count++; } + if (count == 0) { + qWarning() << "no sessions found"; + } + } else { + qWarning() << "unable to open file"; } } @@ -67,18 +74,19 @@ void ZeoTests::testSessionsToYaml() // ==================================================================================================== -QString zeoOutputPath(const QString & inpath, const QString & suffix) +QString zeoOutputPath(const QString & inpath, int sid, const QString & suffix) { // Output to zeo/output/DIR/FILENAME(-session.yml, etc.) QFileInfo path(inpath); - QString basename = path.fileName(); + QString basename = path.baseName(); QString foldername = path.dir().dirName(); QDir outdir(TESTDATA_PATH "zeo/output/" + foldername); outdir.mkpath("."); - QString filename = QString("%1%2") + QString filename = QString("%1-%2%3") .arg(basename) + .arg(sid, 8, 10, QChar('0')) .arg(suffix); return outdir.path() + QDir::separator() + filename; }