diff --git a/Htmldocs/release_notes.html b/Htmldocs/release_notes.html
index 0da963e9..faf057be 100644
--- a/Htmldocs/release_notes.html
+++ b/Htmldocs/release_notes.html
@@ -15,6 +15,13 @@
Portions of OSCAR are © 2019-2020 by
The OSCAR Team
+ - [new] Additional Philips Respironics devices tested and fully supported:
+
+ - DreamStation Go Auto (500G120)
+ - DreamStation Auto CPAP with A-Flex (500X140)
+
+
+ - [new] Add support for DreamStation Go humidifier Target Time setting.
- [fix] Correct calculation of average leak rate on Welcome page.
- [fix] Correct installation of non-English Release Notes on Windows.
- [fix] About/Credits page now offers Google translations to other languages.
diff --git a/oscar/SleepLib/loader_plugins/prs1_loader.cpp b/oscar/SleepLib/loader_plugins/prs1_loader.cpp
index 3cd673ed..7c9e6f95 100644
--- a/oscar/SleepLib/loader_plugins/prs1_loader.cpp
+++ b/oscar/SleepLib/loader_plugins/prs1_loader.cpp
@@ -1238,6 +1238,7 @@ enum PRS1ParsedSettingType
PRS1_SETTING_LOW_TV_ALARM,
PRS1_SETTING_MASK_ALERT,
PRS1_SETTING_SHOW_AHI,
+ PRS1_SETTING_HUMID_TARGET_TIME,
};
@@ -1781,6 +1782,7 @@ static QString parsedSettingTypeName(PRS1ParsedSettingType t)
ENUMSTRING(PRS1_SETTING_HUMID_MODE);
ENUMSTRING(PRS1_SETTING_HEATED_TUBE_TEMP);
ENUMSTRING(PRS1_SETTING_HUMID_LEVEL);
+ ENUMSTRING(PRS1_SETTING_HUMID_TARGET_TIME);
ENUMSTRING(PRS1_SETTING_MASK_RESIST_LOCK);
ENUMSTRING(PRS1_SETTING_MASK_RESIST_SETTING);
ENUMSTRING(PRS1_SETTING_HOSE_DIAMETER);
@@ -7468,11 +7470,12 @@ bool PRS1DataChunk::ParseSettingsF0V6(const unsigned char* data, int size)
break;
case 0x45: // Target Time, specific to DreamStation Go
CHECK_VALUE(len, 1);
- // Not shown on reports when humidifier is in Fixed mode, unclear whether that means it's in use or not.
+ // Included in the data, but not shown on reports when humidifier is in Fixed mode.
+ // According to the FAQ, this setting is only available in Adaptive mode.
if (data[pos] < 40 || data[pos] > 100) { // 4.0 through 10.0 hours in 0.5-hour increments
CHECK_VALUES(data[pos], 0, 1); // Off and Auto
}
- // TODO: Add target time setting.
+ this->AddEvent(new PRS1ScaledSettingEvent(PRS1_SETTING_HUMID_TARGET_TIME, data[pos], 0.1));
break;
default:
UNEXPECTED_VALUE(code, "known setting");
@@ -8092,6 +8095,7 @@ bool PRS1Import::ImportSummary()
PRS1Mode nativemode = PRS1_MODE_UNKNOWN;
CPAPMode cpapmode = MODE_UNKNOWN;
+ bool humidifierConnected = false;
for (int i=0; i < summary->m_parsedData.count(); i++) {
PRS1ParsedEvent* e = summary->m_parsedData.at(i);
if (e->m_type == PRS1ParsedSliceEvent::TYPE) {
@@ -8162,7 +8166,8 @@ bool PRS1Import::ImportSummary()
session->settings[PRS1_RampType] = e->m_value;
break;
case PRS1_SETTING_HUMID_STATUS:
- session->settings[PRS1_HumidStatus] = (bool) e->m_value;
+ humidifierConnected = (bool) e->m_value;
+ session->settings[PRS1_HumidStatus] = humidifierConnected;
break;
case PRS1_SETTING_HUMID_MODE:
session->settings[PRS1_HumidMode] = e->m_value;
@@ -8173,6 +8178,20 @@ bool PRS1Import::ImportSummary()
case PRS1_SETTING_HUMID_LEVEL:
session->settings[PRS1_HumidLevel] = e->m_value;
break;
+ case PRS1_SETTING_HUMID_TARGET_TIME:
+ // Only import this setting if there's a humidifier connected.
+ // (This setting appears in the data even when it's disconnected.)
+ // TODO: Consider moving this logic into the parser for target time.
+ if (humidifierConnected) {
+ if (e->m_value > 1) {
+ // use scaled numeric value
+ session->settings[PRS1_HumidTargetTime] = e->value();
+ } else {
+ // use unscaled 0 or 1 for Off or Auto respectively
+ session->settings[PRS1_HumidTargetTime] = e->m_value;
+ }
+ }
+ break;
case PRS1_SETTING_MASK_RESIST_LOCK:
session->settings[PRS1_MaskResistLock] = (bool) e->m_value;
break;
@@ -9405,10 +9424,19 @@ void PRS1Loader::initChannels()
"PRS1HumidLevel",
QObject::tr("Humidifier"), // label varies in reports, "Humidifier Setting" in 50-series, "Humidity Level" in 60-series, "Humidifier" in DreamStation
QObject::tr("PRS1 Humidifier Setting"),
- QObject::tr("Humid. Lvl"),
+ QObject::tr("Humid. Level"),
"", LOOKUP, Qt::blue));
chan->addOption(0, STR_TR_Off);
+ channel.add(GRP_CPAP, chan = new Channel(PRS1_HumidTargetTime = 0xe11b, SETTING, MT_CPAP, SESSION,
+ "PRS1HumidTargetTime",
+ QObject::tr("Target Time"),
+ QObject::tr("PRS1 Humidifier Target Time"),
+ QObject::tr("Hum. Tgt Time"),
+ STR_UNIT_Hours, DEFAULT, Qt::green));
+ chan->addOption(0, STR_TR_Off);
+ chan->addOption(1, QObject::tr("Auto"));
+
channel.add(GRP_CPAP, chan = new Channel(PRS1_MaskResistSet = 0xe104, SETTING, MT_CPAP, SESSION,
"MaskResistSet",
QObject::tr("Mask Resistance Setting"),
diff --git a/oscar/SleepLib/machine_common.cpp b/oscar/SleepLib/machine_common.cpp
index 65da71ff..c6008bc0 100644
--- a/oscar/SleepLib/machine_common.cpp
+++ b/oscar/SleepLib/machine_common.cpp
@@ -31,7 +31,7 @@ ChannelID RMS9_E01, RMS9_E02, RMS9_SetPressure, RMS9_MaskOnTime;
ChannelID INTELLIPAP_Unknown1, INTELLIPAP_Unknown2;
ChannelID CPAP_LargeLeak,
- PRS1_BND, PRS1_FlexMode, PRS1_FlexLevel, PRS1_HumidStatus, PRS1_HumidLevel, PRS1_MaskResistLock,
+ PRS1_BND, PRS1_FlexMode, PRS1_FlexLevel, PRS1_HumidStatus, PRS1_HumidLevel, PRS1_HumidTargetTime, PRS1_MaskResistLock,
PRS1_MaskResistSet, PRS1_HoseDiam, PRS1_AutoOn, PRS1_AutoOff, PRS1_MaskAlert, PRS1_ShowAHI;
ChannelID OXI_Pulse, OXI_SPO2, OXI_Perf, OXI_PulseChange, OXI_SPO2Drop, OXI_Plethy;
diff --git a/oscar/SleepLib/machine_common.h b/oscar/SleepLib/machine_common.h
index 4e4b5413..6e54a10e 100644
--- a/oscar/SleepLib/machine_common.h
+++ b/oscar/SleepLib/machine_common.h
@@ -160,7 +160,8 @@ extern ChannelID CPAP_IPAP, CPAP_IPAPLo, CPAP_IPAPHi, CPAP_EPAP, CPAP_EPAPLo, CP
extern ChannelID RMS9_E01, RMS9_E02, RMS9_SetPressure, RMS9_MaskOnTime;
extern ChannelID CPAP_LargeLeak, PRS1_BND,
- PRS1_FlexMode, PRS1_FlexLevel, PRS1_HumidStatus, PRS1_HumidLevel, CPAP_HumidSetting, PRS1_MaskResistLock,
+ PRS1_FlexMode, PRS1_FlexLevel, PRS1_HumidStatus, PRS1_HumidLevel, PRS1_HumidTargetTime, PRS1_MaskResistLock,
+ CPAP_HumidSetting,
PRS1_MaskResistSet, PRS1_HoseDiam, PRS1_AutoOn, PRS1_AutoOff, PRS1_MaskAlert, PRS1_ShowAHI;
extern ChannelID INTELLIPAP_Unknown1, INTELLIPAP_Unknown2;
diff --git a/oscar/daily.cpp b/oscar/daily.cpp
index 7bff1515..00e5ea61 100644
--- a/oscar/daily.cpp
+++ b/oscar/daily.cpp
@@ -1142,7 +1142,12 @@ QString Daily::getMachineSettings(Day * day) {
} else if (chan.datatype() == schema::DOUBLE) {
data = QString().number(it.value().toDouble(),'f',2) + " "+chan.units();
} else if (chan.datatype() == schema::DEFAULT) {
- data = QString().number(it.value().toDouble(),'f',2) + " "+chan.units();
+ // Check for any options that override the default numeric display.
+ int value = it.value().toInt();
+ data = chan.option(value);
+ if (data.isEmpty()) {
+ data = QString().number(it.value().toDouble(),'f',2) + " "+chan.units();
+ }
} else {
data = it.value().toString() + " "+ chan.units();
diff --git a/oscar/tests/sessiontests.cpp b/oscar/tests/sessiontests.cpp
index 0b7a4103..d66402c8 100644
--- a/oscar/tests/sessiontests.cpp
+++ b/oscar/tests/sessiontests.cpp
@@ -95,6 +95,7 @@ static QString settingChannel(ChannelID i)
CHANNELNAME(PRS1_HumidMode);
CHANNELNAME(PRS1_TubeTemp);
CHANNELNAME(PRS1_HumidLevel);
+ CHANNELNAME(PRS1_HumidTargetTime);
CHANNELNAME(PRS1_MaskResistLock);
CHANNELNAME(PRS1_MaskResistSet);
CHANNELNAME(PRS1_TimedBreath);