Hi folks.
This patch introduces a feature which allows an idle device (a device which is not currently recording or streaming) to enter a power-down mode after some period of time. Given two timeout values, PowerdownTimeoutM and PowerdownWakeupH, it works like this: when a device becomes idle, it is kept powered up for PowerdownTimeoutM minutes doing, for instance, an EPG scan before it is powered down. If the device is still idle and has been powered down for PowerdownWakeupH hours it is powered up for PowerdownTimeoutM minutes and so on. When recording, streaming or a forced EPG scan starts, the device is powered up and it's idle timer is disabled. This implies that PowerdownTimeoutM should be enough for a full round of EPG scanning (20 seconds * number_of_transponders). Another option is to run EPG scans from cron (at night) and use SVDRP SCAN command.
Actual implementation of power saving facilities is left to a derived device class. In the case of a DVB device it is implemented by closing it's frontend device. For a DVB-S/S2 tuner this usually means powering the LNB off. My measurements show 3-4W power consumption drops per tuner for various DVB-S/S2 tuners. So, this feature (together with HDD spin-down) is especially valuable while running a headless 24/7 VDR server and/or using several tuners. A SATIP device can also implement power saving if it is supported by a server.
I know about the dynamite plugin, but 1) it does much more then this, 2) still requires a VDR patch, which is bigger, 3) doesn't work reliably for me and 4) I think this functionality should be part of the VDR core.
A copy of the patch is here: http://pastebin.com/FRi0kTjf
Please review, Sergey Chernyavskiy.
--- config.c | 9 ++++++ config.h | 3 ++ device.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- device.h | 29 +++++++++++++++++++ dvbdevice.c | 39 +++++++++++++++++++++++++ dvbdevice.h | 7 +++++ eitscan.c | 7 ++++- menu.c | 9 +++++- vdr.c | 6 ++++ 9 files changed, 201 insertions(+), 4 deletions(-)
diff --git a/config.c b/config.c index e5f5463..794c9f8 100644 --- a/config.c +++ b/config.c @@ -395,6 +395,9 @@ cSetup::cSetup(void) PositionerSpeed = 15; PositionerSwing = 650; PositionerLastLon = 0; + PowerdownEnabled = 0; + PowerdownTimeoutM = 15; + PowerdownWakeupH = 4; SetSystemTime = 0; TimeSource = 0; TimeTransponder = 0; @@ -622,6 +625,9 @@ bool cSetup::Parse(const char *Name, const char *Value) else if (!strcasecmp(Name, "PositionerSpeed")) PositionerSpeed = atoi(Value); else if (!strcasecmp(Name, "PositionerSwing")) PositionerSwing = atoi(Value); else if (!strcasecmp(Name, "PositionerLastLon")) PositionerLastLon = atoi(Value); + else if (!strcasecmp(Name, "PowerdownEnabled")) PowerdownEnabled = atoi(Value); + else if (!strcasecmp(Name, "PowerdownTimeoutM")) PowerdownTimeoutM = atoi(Value); + else if (!strcasecmp(Name, "PowerdownWakeupH")) PowerdownWakeupH = atoi(Value); else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value); else if (!strcasecmp(Name, "TimeSource")) TimeSource = cSource::FromString(Value); else if (!strcasecmp(Name, "TimeTransponder")) TimeTransponder = atoi(Value); @@ -753,6 +759,9 @@ bool cSetup::Save(void) Store("PositionerSpeed", PositionerSpeed); Store("PositionerSwing", PositionerSwing); Store("PositionerLastLon", PositionerLastLon); + Store("PowerdownEnabled", PowerdownEnabled); + Store("PowerdownTimeoutM", PowerdownTimeoutM); + Store("PowerdownWakeupH", PowerdownWakeupH); Store("SetSystemTime", SetSystemTime); Store("TimeSource", cSource::ToString(TimeSource)); Store("TimeTransponder", TimeTransponder); diff --git a/config.h b/config.h index e5565da..7a73d9d 100644 --- a/config.h +++ b/config.h @@ -273,6 +273,9 @@ public: int PositionerSpeed; int PositionerSwing; int PositionerLastLon; + int PowerdownEnabled; + int PowerdownTimeoutM; + int PowerdownWakeupH; int SetSystemTime; int TimeSource; int TimeTransponder; diff --git a/device.c b/device.c index 542d120..9306adb 100644 --- a/device.c +++ b/device.c @@ -104,6 +104,9 @@ cDevice::cDevice(void) dvbSubtitleConverter = NULL; autoSelectPreferredSubtitleLanguage = true;
+ idleTimerExpires = time(NULL) + Setup.PowerdownTimeoutM * 60; + wakeupTimerExpires = 0; + for (int i = 0; i < MAXRECEIVERS; i++) receiver[i] = NULL;
@@ -745,6 +748,11 @@ bool cDevice::SwitchChannel(int Direction) return result; }
+// While switching to a channel, the device will be kept powered up +// for at least this number of seconds before a receiver is attached. +// Must be less than cEITScanner::ScanTimeout. +#define CHANNEL_SWITCH_POWERUP_TIMEOUT 10 + eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) { cStatus::MsgChannelSwitch(this, 0, LiveView); @@ -778,6 +786,8 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) Result = scrNotAvailable; } else { + // Power up the device + PowerUp(CHANNEL_SWITCH_POWERUP_TIMEOUT); // Stop section handling: if (sectionHandler) { sectionHandler->SetStatus(false); @@ -843,8 +853,11 @@ int cDevice::Occupied(void) const
void cDevice::SetOccupied(int Seconds) { - if (Seconds >= 0) + if (Seconds >= 0) { occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT); + // avoid short power-down/power-up cycles + SetIdleTimer(true, Seconds + 30); + } }
bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) @@ -1675,6 +1688,7 @@ bool cDevice::AttachReceiver(cReceiver *Receiver) startScrambleDetection = time(NULL); } Start(); + SetIdleTimer(false); return true; } } @@ -1708,8 +1722,10 @@ void cDevice::Detach(cReceiver *Receiver) camSlot->Assign(NULL); } } - if (!receiversLeft) + if (!receiversLeft) { Cancel(-1); + SetIdleTimer(true); + } }
void cDevice::DetachAll(int Pid) @@ -1731,6 +1747,82 @@ void cDevice::DetachAllReceivers(void) Detach(receiver[i]); }
+void cDevice::CheckIdle(void) +{ + if (!SupportsPowerDown() || !Setup.PowerdownEnabled) + return; + cMutexLock MutexLock(&mutexPowerSaving); + if (idleTimerExpires != 0 && time(NULL) > idleTimerExpires) { + // idle, powered up + dsyslog("power saving: device %d idle timer expired", CardIndex() + 1); + SetIdleTimer(false); + if (Setup.PowerdownWakeupH != 0) + wakeupTimerExpires = time(NULL) + Setup.PowerdownWakeupH * 3600; + else + dsyslog("power saving: waking up is disabled"); + if (!IsPoweredDown()) { + dsyslog("power saving: powering device %d down", CardIndex() + 1); + if (sectionHandler) { + sectionHandler->SetStatus(false); + sectionHandler->SetChannel(NULL); + } + PowerDown(true); + } + } + if (wakeupTimerExpires != 0 && time(NULL) > wakeupTimerExpires) { + // idle, powered down + dsyslog("power saving: device %d wakeup timer expired", CardIndex() + 1); + SetIdleTimer(true); + if (IsPoweredDown()) { + dsyslog("power saving: waking up device %d", CardIndex() + 1); + PowerDown(false); + } + } +} + +void cDevice::SetIdleTimer(bool On, int ExtraTimeoutS) +{ + if (!SupportsPowerDown()) + return; + cMutexLock MutexLock(&mutexPowerSaving); + if (On) { + int Tout = Setup.PowerdownTimeoutM * 60; + time_t Now = time(NULL); + if (ExtraTimeoutS > 0) { + if (idleTimerExpires >= Now + ExtraTimeoutS) + return; + Tout = ExtraTimeoutS; + } + idleTimerExpires = Now + Tout; + if (Setup.PowerdownEnabled) + dsyslog("power saving: set device %d idle timer to %d sec", CardIndex() + 1, Tout); + } + else { + idleTimerExpires = 0; + if (Setup.PowerdownEnabled) + dsyslog("power saving: disable device %d idle timer", CardIndex() + 1); + } + wakeupTimerExpires = 0; +} + +bool cDevice::PoweredDown(void) +{ + if (SupportsPowerDown() && Setup.PowerdownEnabled) { + cMutexLock MutexLock(&mutexPowerSaving); + return IsPoweredDown(); + } + else + return false; +} + +void cDevice::PowerUp(int ExtraTimeoutS) +{ + cMutexLock MutexLock(&mutexPowerSaving); + SetIdleTimer(true, ExtraTimeoutS); + if (SupportsPowerDown() && IsPoweredDown()) + PowerDown(false); +} + // --- cTSBuffer -------------------------------------------------------------
cTSBuffer::cTSBuffer(int File, int Size, int CardIndex) diff --git a/device.h b/device.h index 31ee303..6c1fdfb 100644 --- a/device.h +++ b/device.h @@ -821,6 +821,35 @@ public: ///< Detaches all receivers from this device for this pid. virtual void DetachAllReceivers(void); ///< Detaches all receivers from this device. + +// Power saving facilities + +private: + cMutex mutexPowerSaving; + time_t idleTimerExpires, wakeupTimerExpires; + void PowerUp(int ExtraTimeoutS); + ///< If the device is powered down, powers it up and keeps it + ///< powered up for at least ExtraTimeoutS seconds (see + ///< cDevice::SetIdleTimer()). +public: + void CheckIdle(void); + ///< Should be called periodically in the main loop. + bool PoweredDown(void); + ///< Returns true if the device is powered down "logically", that is, + ///< idle tasks like EPG scanning are disabled. + void SetIdleTimer(bool On, int ExtraTimeoutS = 0); + ///< Starts/disables the idle timer. This timer must be started when + ///< a device gets idle and must be disabled when it is receiving. + ///< If ExtraTimeoutS is greater than zero and On is true, a new timer + ///< won't be set, but the device will be kept powered up for at least + ///< ExtraTimeoutS seconds. +protected: + virtual bool IsPoweredDown(void) {return false;} + ///< Returns true if the device is powered down "physically". + virtual void PowerDown(bool On) {}; + ///< Actually powers the device down/up. + virtual bool SupportsPowerDown() {return false;} + ///< Returns true if a derived device supports power saving. };
/// Derived cDevice classes that can receive channels will have to provide diff --git a/dvbdevice.c b/dvbdevice.c index 63af52e..cdadbff 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -348,6 +348,8 @@ public: const cPositioner *Positioner(void) const { return positioner; } int GetSignalStrength(void) const; int GetSignalQuality(void) const; + bool IsPoweredDown(void) {return fd_frontend < 0;} + void PowerDown(bool On); };
cMutex cDvbTuner::bondMutex; @@ -544,6 +546,8 @@ void cDvbTuner::ClearEventQueue(void) const
bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const { + if (fd_frontend < 0) + return false; ClearEventQueue(); while (1) { if (ioctl(fd_frontend, FE_READ_STATUS, &Status) != -1) @@ -559,6 +563,8 @@ bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
int cDvbTuner::GetSignalStrength(void) const { + if (fd_frontend < 0) + return -1; ClearEventQueue(); uint16_t Signal; while (1) { @@ -1001,6 +1007,26 @@ void cDvbTuner::Action(void) } }
+void cDvbTuner::PowerDown(bool On) +{ + cMutexLock MutexLock(&mutex); + if (On && fd_frontend >= 0) { + isyslog("dvb tuner: power-down - closing frontend %d/%d", adapter, frontend); + tunerStatus = tsIdle; + close(fd_frontend); + fd_frontend = -1; + } + if (!On && fd_frontend < 0) { + cString Filename = cString::sprintf("%s/%s%d/%s%d", + DEV_DVB_BASE, DEV_DVB_ADAPTER, adapter, DEV_DVB_FRONTEND, frontend); + isyslog("dvb tuner: power-up - opening frontend %d/%d", adapter, frontend); + fd_frontend = open(Filename, O_RDWR | O_NONBLOCK); + if (fd_frontend < 0) + esyslog("ERROR: can't open DVB device frontend %d/%d", adapter, frontend); + tunerStatus = tsIdle; + } +} + // --- cDvbSourceParam -------------------------------------------------------
class cDvbSourceParam : public cSourceParam { @@ -1712,6 +1738,19 @@ void cDvbDevice::DetachAllReceivers(void) needsDetachBondedReceivers = false; }
+bool cDvbDevice::IsPoweredDown(void) +{ + if (dvbTuner) + return dvbTuner->IsPoweredDown(); + return false; +} + +void cDvbDevice::PowerDown(bool On) +{ + if (dvbTuner) + dvbTuner->PowerDown(On); +} + // --- cDvbDeviceProbe -------------------------------------------------------
cList<cDvbDeviceProbe> DvbDeviceProbes; diff --git a/dvbdevice.h b/dvbdevice.h index 5ae4952..15d1ff8 100644 --- a/dvbdevice.h +++ b/dvbdevice.h @@ -290,6 +290,13 @@ protected: virtual void CloseDvr(void); virtual bool GetTSPacket(uchar *&Data); virtual void DetachAllReceivers(void); + +// Power saving facilities + +protected: + virtual bool IsPoweredDown(void); + virtual void PowerDown(bool On); + virtual bool SupportsPowerDown() {return true;} };
// A plugin that implements a DVB device derived from cDvbDevice needs to create diff --git a/eitscan.c b/eitscan.c index 41ac25e..765055c 100644 --- a/eitscan.c +++ b/eitscan.c @@ -144,7 +144,8 @@ void cEITScanner::Process(void) bool AnyDeviceSwitched = false; for (int i = 0; i < cDevice::NumDevices(); i++) { cDevice *Device = cDevice::GetDevice(i); - if (Device && Device->ProvidesEIT()) { + if (Device && Device->ProvidesEIT() + && (!Device->PoweredDown() || lastActivity == 0)) { // powered up or forced scan for (cScanData *ScanData = scanList->First(); ScanData; ScanData = scanList->Next(ScanData)) { const cChannel *Channel = ScanData->GetChannel(); if (Channel) { @@ -165,6 +166,10 @@ void cEITScanner::Process(void) } } //dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); + if (lastActivity == 0) + // forced scan - set idle timer for each channel switch; + // this prevents powering down while scanning a transponder + Device->SetIdleTimer(true, ScanTimeout + 5); Device->SwitchChannel(Channel, false); scanList->Del(ScanData); AnyDeviceSwitched = true; diff --git a/menu.c b/menu.c index 569900c..5a89771 100644 --- a/menu.c +++ b/menu.c @@ -3715,6 +3715,12 @@ void cMenuSetupLNB::Setup(void) Add(new cMenuEditIntxItem(tr("Setup.LNB$Positioner speed (degrees/s)"), &data.PositionerSpeed, 1, 1800, 10)); }
+ Add(new cMenuEditBoolItem(tr("Setup.LNB$Enable power saving"), &data.PowerdownEnabled)); + if (data.PowerdownEnabled) { + Add(new cMenuEditIntItem(tr("Setup.LNB$Power down an idle device after (min)"), &data.PowerdownTimeoutM)); + Add(new cMenuEditIntItem(tr("Setup.LNB$Wake up from power-down after (h)"), &data.PowerdownWakeupH)); + } + SetCurrent(Get(current)); Display(); } @@ -3723,6 +3729,7 @@ eOSState cMenuSetupLNB::ProcessKey(eKeys Key) { int oldDiSEqC = data.DiSEqC; int oldUsePositioner = data.UsePositioner; + int oldPowerdownEnabled = data.PowerdownEnabled; bool DeviceBondingsChanged = false; if (Key == kOk) { cString NewDeviceBondings = satCableNumbers.ToString(); @@ -3731,7 +3738,7 @@ eOSState cMenuSetupLNB::ProcessKey(eKeys Key) } eOSState state = cMenuSetupBase::ProcessKey(Key);
- if (Key != kNone && (data.DiSEqC != oldDiSEqC || data.UsePositioner != oldUsePositioner)) + if (Key != kNone && (data.DiSEqC != oldDiSEqC || data.UsePositioner != oldUsePositioner || data.PowerdownEnabled != oldPowerdownEnabled)) Setup(); else if (DeviceBondingsChanged) cDvbDevice::BondDevices(data.DeviceBondings); diff --git a/vdr.c b/vdr.c index 6b0bf2b..c8de702 100644 --- a/vdr.c +++ b/vdr.c @@ -1515,6 +1515,12 @@ int main(int argc, char *argv[])
ReportEpgBugFixStats();
+ for (int i = 0; i < cDevice::NumDevices(); i++) { + cDevice *d = cDevice::GetDevice(i); + if (d) + d->CheckIdle(); + } + // Main thread hooks of plugins: PluginManager.MainThreadHook(); }
Interesting. How long have you been running it / testing it? Have you tested with VPS timers enabled ?
Thanks Richard
On 26/05/2016 16:36, glenvt18 wrote:
Hi folks.
This patch introduces a feature which allows an idle device (a device which is not currently recording or streaming) to enter a power-down mode after some period of time. Given two timeout values, PowerdownTimeoutM and PowerdownWakeupH, it works like this: when a device becomes idle, it is kept powered up for PowerdownTimeoutM minutes doing, for instance, an EPG scan before it is powered down. If the device is still idle and has been powered down for PowerdownWakeupH hours it is powered up for PowerdownTimeoutM minutes and so on. When recording, streaming or a forced EPG scan starts, the device is powered up and it's idle timer is disabled. This implies that PowerdownTimeoutM should be enough for a full round of EPG scanning (20 seconds * number_of_transponders). Another option is to run EPG scans from cron (at night) and use SVDRP SCAN command.
For about a month now. Tested with 3 different DVB-S/S2 tuners with VDR 2.3.1 and VDR 2.2.0 (requires minor changes to the patch) - rock solid. I don't have VPS, so I can't test it. The same is about DVB-T/C tuners. After all, if something doesn't work this feature can be disabled (and it is disabled by default),
Best, Sergey Chernyavskiy.
2016-05-26 20:15 GMT+03:00 Richard F lists@keynet-technology.com:
Interesting. How long have you been running it / testing it? Have you tested with VPS timers enabled ?
Thanks Richard
On 26/05/2016 16:36, glenvt18 wrote:
Hi folks.
This patch introduces a feature which allows an idle device (a device which is not currently recording or streaming) to enter a power-down mode after some period of time. Given two timeout values, PowerdownTimeoutM and PowerdownWakeupH, it works like this: when a device becomes idle, it is kept powered up for PowerdownTimeoutM minutes doing, for instance, an EPG scan before it is powered down. If the device is still idle and has been powered down for PowerdownWakeupH hours it is powered up for PowerdownTimeoutM minutes and so on. When recording, streaming or a forced EPG scan starts, the device is powered up and it's idle timer is disabled. This implies that PowerdownTimeoutM should be enough for a full round of EPG scanning (20 seconds * number_of_transponders). Another option is to run EPG scans from cron (at night) and use SVDRP SCAN command.
vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
I'd like to give it a go on DVB & DVBT-2 tuners (1 PCI, 1 USB) Would you be kind enough to post a version for VDR2.20 or advise changes necessary?
Thanks Richard
On 26/05/2016 18:44, glenvt18 wrote:
For about a month now. Tested with 3 different DVB-S/S2 tuners with VDR 2.3.1 and VDR 2.2.0 (requires minor changes to the patch) - rock solid. I don't have VPS, so I can't test it. The same is about DVB-T/C tuners. After all, if something doesn't work this feature can be disabled (and it is disabled by default),
Yes, sure. The patch against VDR-2.2.0: http://pastebin.com/D4VQd1rG
While testing set VDR log level to 3 (--log=3) and use this helper script to monitor your frontends: http://pastebin.com/uW4NW0rZ
Don't forget to enable power saving in the Setup->LNB menu.
If you don't have sudo (you're not on Debian or Ubuntu), remove it and run the script as root. It would be great if you could measure the power consumption of you tuners (at least the USB one).
Best, Sergey Chernyavskiy.
On Fri, May 27, 2016 at 09:59:06AM +0100, Richard F wrote:
I'd like to give it a go on DVB & DVBT-2 tuners (1 PCI, 1 USB) Would you be kind enough to post a version for VDR2.20 or advise changes necessary?
Thanks Richard
On 26/05/2016 18:44, glenvt18 wrote:
For about a month now. Tested with 3 different DVB-S/S2 tuners with VDR 2.3.1 and VDR 2.2.0 (requires minor changes to the patch) - rock solid. I don't have VPS, so I can't test it. The same is about DVB-T/C tuners. After all, if something doesn't work this feature can be disabled (and it is disabled by default),
vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
Thanks - I built it and and have had it running for about 24 hours:
A couple of observations: I'm seeing this about every 30 - 60 mins as expected, but the timeout seems to be short - not the PowerdownTimeoutM (I assume minutes?) set at 15 in the config file
May 30 08:51:02 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 1/0 May 30 08:51:46 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 1/0
So during the start of recordings and other programme changes, I see quite a lot of activity - e.g
May 29 15:32:32 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 1/0 May 29 15:32:36 ha-server vdr: [2306] channel 41 (Channel 4 HD) event Sun 29.05.2016 15:25-16:30 (VPS: 29.05. 15:25) 'Location, Location, Location' status 4 May 29 15:32:37 ha-server vdr: [2306] channel 4 (BBC TWO HD) event Sun 29.05.2016 15:30-18:00 (VPS: 29.05. 15:30) 'Gymnastics' status 4 May 29 15:33:17 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 1/0 May 29 15:33:38 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 1/0 May 29 15:33:41 ha-server vdr: [2306] channel 45 (Film4) event Sun 29.05.2016 15:05-16:50 (VPS: 29.05. 15:05) 'Catch That Kid' status 4 May 29 15:33:42 ha-server vdr: [2306] channel 40 (Channel 4) event Sun 29.05.2016 15:25-16:30 (VPS: 29.05. 15:25) 'Location, Location, Location' status 4 May 29 15:34:23 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 1/0
Start of (VPS) recording:
May 29 19:50:07 ha-server vdr: [2296] timer 2 (3 2000-2100 VPS 'Top Gear~2016.05.29-20:00-Sun') entered VPS margin May 29 19:50:07 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:50:08 ha-server vdr: [2303] channel 3 (BBC TWO) event Sun 29.05.2016 19:00-20:00 (VPS: 29.05. 19:00) 'Rugby Union' status 4 May 29 19:50:09 ha-server vdr: [2303] channel 7 (BBC NEWS) event Sun 29.05.2016 19:45-20:00 (VPS: 29.05. 19:45) 'Meet The Author' status 4 May 29 19:50:46 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:50:51 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:51:30 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:51:35 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:52:14 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:52:19 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:52:58 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:53:03 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:53:42 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:53:47 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:54:26 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:54:31 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:55:10 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:55:15 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:55:54 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:55:59 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:56:38 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:56:43 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:57:22 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:57:27 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:58:06 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:58:11 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:58:50 ha-server vdr: [2296] dvb tuner: power-down - closing frontend 0/0 May 29 19:58:55 ha-server vdr: [2296] dvb tuner: power-up - opening frontend 0/0 May 29 19:59:10 ha-server vdr: [2306] channel 61 (Channel 5 HD) event Sun 29.05.2016 20:00-21:00 (VPS: 29.05. 20:00) 'Secrets of Egypt' status 4 May 29 19:59:11 ha-server vdr: [2296] timer 1 (61 1900-2000 VPS 'Cricket on 5~England v Sri Lanka: Second Test Day Thr') stop
I haven't had a chance to take the server down to insert the power monitor yet, but will do so at convenient time in the next few days
Thanks Richard
On 27/05/2016 14:51, glenvt18 wrote:
Yes, sure. The patch against VDR-2.2.0: http://pastebin.com/D4VQd1rG
While testing set VDR log level to 3 (--log=3) and use this helper script to monitor your frontends: http://pastebin.com/uW4NW0rZ
Don't forget to enable power saving in the Setup->LNB menu.
If you don't have sudo (you're not on Debian or Ubuntu), remove it and run the script as root. It would be great if you could measure the power consumption of you tuners (at least the USB one).
Best, Sergey Chernyavskiy.
On Fri, May 27, 2016 at 09:59:06AM +0100, Richard F wrote:
I'd like to give it a go on DVB & DVBT-2 tuners (1 PCI, 1 USB) Would you be kind enough to post a version for VDR2.20 or advise changes necessary?
Thanks Richard
On 26/05/2016 18:44, glenvt18 wrote:
For about a month now. Tested with 3 different DVB-S/S2 tuners with VDR 2.3.1 and VDR 2.2.0 (requires minor changes to the patch) - rock solid. I don't have VPS, so I can't test it. The same is about DVB-T/C tuners. After all, if something doesn't work this feature can be disabled (and it is disabled by default),
vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
Could you attach (or, better, upload to pastebin.com) the whole log file. Are you running vdr with --log=3? I need to see 'idle timer' debug messages and some other debug stuff. Could you also apply this change
diff --git a/eitscan.c b/eitscan.c index 3899e00..b1c8c13 100644 --- a/eitscan.c +++ b/eitscan.c @@ -159,7 +159,7 @@ void cEITScanner::Process(void) Skins.Message(mtInfo, tr("Starting EPG scan")); } } - //dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); + dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); if (lastActivity == 0) // forced scan - set idle timer for each channel switch; // this prevents powering down while scanning a transponder --
Thanks for testing.
Best, Sergey Chernyavskiy.
On Mon, May 30, 2016 at 09:59:46AM +0100, Richard F wrote:
Thanks - I built it and and have had it running for about 24 hours:
A couple of observations: I'm seeing this about every 30 - 60 mins as expected, but the timeout seems to be short - not the PowerdownTimeoutM (I assume minutes?) set at 15 in the config file
...
I haven't had a chance to take the server down to insert the power monitor yet, but will do so at convenient time in the next few days
Thanks Richard
On 27/05/2016 14:51, glenvt18 wrote:
Yes, sure. The patch against VDR-2.2.0: http://pastebin.com/D4VQd1rG
While testing set VDR log level to 3 (--log=3) and use this helper script to monitor your frontends: http://pastebin.com/uW4NW0rZ
Don't forget to enable power saving in the Setup->LNB menu.
If you don't have sudo (you're not on Debian or Ubuntu), remove it and run the script as root. It would be great if you could measure the power consumption of you tuners (at least the USB one).
Best, Sergey Chernyavskiy.
On Fri, May 27, 2016 at 09:59:06AM +0100, Richard F wrote:
I'd like to give it a go on DVB & DVBT-2 tuners (1 PCI, 1 USB) Would you be kind enough to post a version for VDR2.20 or advise changes necessary?
Thanks Richard
On 26/05/2016 18:44, glenvt18 wrote:
For about a month now. Tested with 3 different DVB-S/S2 tuners with VDR 2.3.1 and VDR 2.2.0 (requires minor changes to the patch) - rock solid. I don't have VPS, so I can't test it. The same is about DVB-T/C tuners. After all, if something doesn't work this feature can be disabled (and it is disabled by default),
vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
OK Sergey, I've posted a log with your patch applied + log level 3 - about 3 hours worth There was a recording 16:15 to 16:45, other than that idle I can run it for longer if you need it, though it's creating a fair bit of log. I seem to get a lot of erroneous EPGsearch results at level 3, not sure why. http://pastebin.com/8DbYQdTX
Let me know what it tells you Thanks Richard
On 30/05/2016 15:19, glenvt18 wrote:
Could you attach (or, better, upload to pastebin.com) the whole log file. Are you running vdr with --log=3? I need to see 'idle timer' debug messages and some other debug stuff. Could you also apply this change
diff --git a/eitscan.c b/eitscan.c index 3899e00..b1c8c13 100644 --- a/eitscan.c +++ b/eitscan.c @@ -159,7 +159,7 @@ void cEITScanner::Process(void) Skins.Message(mtInfo, tr("Starting EPG scan")); } }
//dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder());
dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); if (lastActivity == 0) // forced scan - set idle timer for each channel switch; // this prevents powering down while scanning a transponder
--
Thanks for testing.
Best, Sergey Chernyavskiy.
From what I can see, everything works as expected. You can safely lessen
the power-down timeout to 3 minutes. This will be enough for EPG scan as you have at most 8 transponders/multiplexes which gives 8 * 1/3 = 2m40s - see 'EIT scan ...' messages.
As for those small intervals of activity you mentioned, it happens because some 'preparation' work is done before a timer starts. VDR tries to switch to the timer's transponder and gather EPG data. For a VPS timer this begins within VPS margin and an hour before the timer start time. For a non-VPS timer it begins one minute before the timer start time. I've added 30 seconds to the occupied timeout (see my cDevice::SetOccupied() comment) to avoid frequent on/off switching. So, you're likely to see 38-second (or, sometimes, a bit more) periods of activity. If you still worry about it, keep you server idle for 2 hours before a nearest VPS timer starts and paste the log.
I've removed 'sudo' from the monitor script: http://pastebin.com/8JDffAXF
Run it as user 'vdr' for some time. It will draw you a nice 'map' of your devices' activity.
If you notice channel switch failures, let me know.
Do your tuners get warm when active?
Thanks again for testing.
Best, Sergey Chernyavskiy.
On Tue, May 31, 2016 at 08:43:01PM +0100, Richard F wrote:
OK Sergey, I've posted a log with your patch applied + log level 3 - about 3 hours worth There was a recording 16:15 to 16:45, other than that idle I can run it for longer if you need it, though it's creating a fair bit of log. I seem to get a lot of erroneous EPGsearch results at level 3, not sure why. http://pastebin.com/8DbYQdTX
Let me know what it tells you Thanks Richard
On 30/05/2016 15:19, glenvt18 wrote:
Could you attach (or, better, upload to pastebin.com) the whole log file. Are you running vdr with --log=3? I need to see 'idle timer' debug messages and some other debug stuff. Could you also apply this change
diff --git a/eitscan.c b/eitscan.c index 3899e00..b1c8c13 100644 --- a/eitscan.c +++ b/eitscan.c @@ -159,7 +159,7 @@ void cEITScanner::Process(void) Skins.Message(mtInfo, tr("Starting EPG scan")); } } - //dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); + dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); if (lastActivity == 0) // forced scan - set idle timer for each channel switch; // this prevents powering down while scanning a transponder --
Thanks for testing.
Best, Sergey Chernyavskiy.
_______________________________________________ vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
On 1/06/2016 03:49, glenvt18 wrote:
From what I can see, everything works as expected. You can safely lessen
the power-down timeout to 3 minutes. This will be enough for EPG scan as you have at most 8 transponders/multiplexes which gives 8 * 1/3 = 2m40s
- see 'EIT scan ...' messages.
I reduced it to 5 mins to give it some margin
As for those small intervals of activity you mentioned, it happens because some 'preparation' work is done before a timer starts. VDR tries to switch to the timer's transponder and gather EPG data. For a VPS timer this begins within VPS margin and an hour before the timer start time. For a non-VPS timer it begins one minute before the timer start time. I've added 30 seconds to the occupied timeout (see my cDevice::SetOccupied() comment) to avoid frequent on/off switching. So, you're likely to see 38-second (or, sometimes, a bit more) periods of activity. If you still worry about it, keep you server idle for 2 hours before a nearest VPS timer starts and paste the log.
OK, I'll keep an eye on it. No adverse effects yet - good work, thanks.
I'm doing some other testing and stuff atm so want to keep the server up - I'll possibly take it down at the weekend, make some power measurements and post them
I've removed 'sudo' from the monitor script: http://pastebin.com/8JDffAXF
Run it as user 'vdr' for some time. It will draw you a nice 'map' of your devices' activity.
If you notice channel switch failures, let me know.
Do your tuners get warm when active?
Yes, the TV tuners always did run warm, and I recall that when VDR is stopped the power is several watts lower (not because of VDR/CPU load itself according to stats, it's when the tuners go active - hence my interest in your patch).
As the server also runs the home automation/lights/heating/security, CCTV, mail server, and file storage/Owncloud it's not an option to shut it down when not recording, and I have t choose when to take it down !
Richard
Thanks again for testing.
Best, Sergey Chernyavskiy.
On Tue, May 31, 2016 at 08:43:01PM +0100, Richard F wrote:
OK Sergey, I've posted a log with your patch applied + log level 3 - about 3 hours worth There was a recording 16:15 to 16:45, other than that idle I can run it for longer if you need it, though it's creating a fair bit of log. I seem to get a lot of erroneous EPGsearch results at level 3, not sure why. http://pastebin.com/8DbYQdTX
Let me know what it tells you Thanks Richard
On 30/05/2016 15:19, glenvt18 wrote:
Could you attach (or, better, upload to pastebin.com) the whole log file. Are you running vdr with --log=3? I need to see 'idle timer' debug messages and some other debug stuff. Could you also apply this change
diff --git a/eitscan.c b/eitscan.c index 3899e00..b1c8c13 100644 --- a/eitscan.c +++ b/eitscan.c @@ -159,7 +159,7 @@ void cEITScanner::Process(void) Skins.Message(mtInfo, tr("Starting EPG scan")); } } - //dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); + dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); if (lastActivity == 0) // forced scan - set idle timer for each channel switch; // this prevents powering down while scanning a transponder --
Thanks for testing.
Best, Sergey Chernyavskiy.
_______________________________________________ vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
As the server also runs the home automation/lights/heating/security, CCTV, mail server, and file storage/Owncloud ...
That's the main purpose of this feature. You don't have to switch off your tuners physically, close your connections or put your server into sleep (and ARM devices usually don't have a sleep mode at all). You can stream your recordings, watch movies and do other stuff with your server and, at the same time, keep your tuners cold.
OK, I'll keep an eye on it. No adverse effects yet - good work, thanks.
I've modified the monitor script: http://pastebin.com/DR4gUdZR
Now it prints timestamps and it's output can be searched and grep-ed. Run it with '|tee' for several days.
Best, Sergey Chernyavskiy.
On Thu, Jun 02, 2016 at 03:35:49PM +0100, Richard F wrote:
On 1/06/2016 03:49, glenvt18 wrote:
From what I can see, everything works as expected. You can safely lessen
the power-down timeout to 3 minutes. This will be enough for EPG scan as you have at most 8 transponders/multiplexes which gives 8 * 1/3 = 2m40s
- see 'EIT scan ...' messages.
I reduced it to 5 mins to give it some margin
As for those small intervals of activity you mentioned, it happens because some 'preparation' work is done before a timer starts. VDR tries to switch to the timer's transponder and gather EPG data. For a VPS timer this begins within VPS margin and an hour before the timer start time. For a non-VPS timer it begins one minute before the timer start time. I've added 30 seconds to the occupied timeout (see my cDevice::SetOccupied() comment) to avoid frequent on/off switching. So, you're likely to see 38-second (or, sometimes, a bit more) periods of activity. If you still worry about it, keep you server idle for 2 hours before a nearest VPS timer starts and paste the log.
OK, I'll keep an eye on it. No adverse effects yet - good work, thanks.
I'm doing some other testing and stuff atm so want to keep the server up - I'll possibly take it down at the weekend, make some power measurements and post them
I've removed 'sudo' from the monitor script: http://pastebin.com/8JDffAXF
Run it as user 'vdr' for some time. It will draw you a nice 'map' of your devices' activity.
If you notice channel switch failures, let me know.
Do your tuners get warm when active?
Yes, the TV tuners always did run warm, and I recall that when VDR is stopped the power is several watts lower (not because of VDR/CPU load itself according to stats, it's when the tuners go active - hence my interest in your patch).
As the server also runs the home automation/lights/heating/security, CCTV, mail server, and file storage/Owncloud it's not an option to shut it down when not recording, and I have t choose when to take it down !
Richard
Thanks again for testing.
Best, Sergey Chernyavskiy.
On Tue, May 31, 2016 at 08:43:01PM +0100, Richard F wrote:
OK Sergey, I've posted a log with your patch applied + log level 3 - about 3 hours worth There was a recording 16:15 to 16:45, other than that idle I can run it for longer if you need it, though it's creating a fair bit of log. I seem to get a lot of erroneous EPGsearch results at level 3, not sure why. http://pastebin.com/8DbYQdTX
Let me know what it tells you Thanks Richard
On 30/05/2016 15:19, glenvt18 wrote:
Could you attach (or, better, upload to pastebin.com) the whole log file. Are you running vdr with --log=3? I need to see 'idle timer' debug messages and some other debug stuff. Could you also apply this change
diff --git a/eitscan.c b/eitscan.c index 3899e00..b1c8c13 100644 --- a/eitscan.c +++ b/eitscan.c @@ -159,7 +159,7 @@ void cEITScanner::Process(void) Skins.Message(mtInfo, tr("Starting EPG scan")); } } - //dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); + dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); if (lastActivity == 0) // forced scan - set idle timer for each channel switch; // this prevents powering down while scanning a transponder --
Thanks for testing.
Best, Sergey Chernyavskiy.
_______________________________________________ vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
Sergey,
I took down the server at the weekend to install a newly built kernel and insert the power monitor.
47W - All services running at idle, tuner power saving disabled 44W - All services running at idle, tuner power saving enabled
As tuners are powered down most of the time, that's a handy 6% average saving.
The hardware is an HP 8300CMT with high efficiency PSU, G2130 Ivy bridge CPU and a 3 x 2T RAID + KMC4400R for CCTV video capture, the tuners are PCTV Nanostick 290e for HD/SD (USB2) and an old Leadtek DTV1000 T (PCI) for SD - both of which are super-reliable BTW.
Obviously other tuners will vary, and if the PSU isn't the efficient 90% one like this, the savings will be marginally more.
Richard
On 2/06/2016 17:15, glenvt18 wrote:
As the server also runs the home automation/lights/heating/security, CCTV, mail server, and file storage/Owncloud ...
That's the main purpose of this feature. You don't have to switch off your tuners physically, close your connections or put your server into sleep (and ARM devices usually don't have a sleep mode at all). You can stream your recordings, watch movies and do other stuff with your server and, at the same time, keep your tuners cold.
OK, I'll keep an eye on it. No adverse effects yet - good work, thanks.
I've modified the monitor script: http://pastebin.com/DR4gUdZR
Now it prints timestamps and it's output can be searched and grep-ed. Run it with '|tee' for several days.
Best, Sergey Chernyavskiy.
Hi Richard,
Unlike DVB-S/S2 tuners your DVB-T/T2 ones don't have to supply power to a LNB (which draws at least 2W). So, your 3W drop can be considered as "normal". For your USB stick even 1W saving can be helpful.
Thanks again for testing.
Sergey.
On Mon, Jun 06, 2016 at 11:21:24AM +0100, Richard F wrote:
Sergey,
I took down the server at the weekend to install a newly built kernel and insert the power monitor.
47W - All services running at idle, tuner power saving disabled 44W - All services running at idle, tuner power saving enabled
As tuners are powered down most of the time, that's a handy 6% average saving.
The hardware is an HP 8300CMT with high efficiency PSU, G2130 Ivy bridge CPU and a 3 x 2T RAID + KMC4400R for CCTV video capture, the tuners are PCTV Nanostick 290e for HD/SD (USB2) and an old Leadtek DTV1000 T (PCI) for SD - both of which are super-reliable BTW.
Obviously other tuners will vary, and if the PSU isn't the efficient 90% one like this, the savings will be marginally more.
Richard
On 2/06/2016 17:15, glenvt18 wrote:
As the server also runs the home automation/lights/heating/security, CCTV, mail server, and file storage/Owncloud ...
That's the main purpose of this feature. You don't have to switch off your tuners physically, close your connections or put your server into sleep (and ARM devices usually don't have a sleep mode at all). You can stream your recordings, watch movies and do other stuff with your server and, at the same time, keep your tuners cold.
OK, I'll keep an eye on it. No adverse effects yet - good work, thanks.
I've modified the monitor script: http://pastebin.com/DR4gUdZR
Now it prints timestamps and it's output can be searched and grep-ed. Run it with '|tee' for several days.
Best, Sergey Chernyavskiy.
vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
I'm happy with just a modest power saving.
Put in context, on my system, 3Wh ~ 25 mins SD content transcoding to H264/AAC = 30-40% disk space reduction with no noticeable loss of quality. So ~70Wh saving / day pays for ongoing SD recording compression and multi-TB historical library compression in about 3 months. I free up a 1TB or so of RAID :-)
Thanks Richard
On 7/06/2016 14:45, glenvt18 wrote:
Hi Richard,
Unlike DVB-S/S2 tuners your DVB-T/T2 ones don't have to supply power to a LNB (which draws at least 2W). So, your 3W drop can be considered as "normal". For your USB stick even 1W saving can be helpful.
Thanks again for testing.
Sergey.
That's cool:)
On Wed, Jun 08, 2016 at 05:23:43PM +0100, Richard F wrote:
I'm happy with just a modest power saving.
Put in context, on my system, 3Wh ~ 25 mins SD content transcoding to H264/AAC = 30-40% disk space reduction with no noticeable loss of quality. So ~70Wh saving / day pays for ongoing SD recording compression and multi-TB historical library compression in about 3 months. I free up a 1TB or so of RAID :-)
Thanks Richard
On 7/06/2016 14:45, glenvt18 wrote:
Hi Richard,
Unlike DVB-S/S2 tuners your DVB-T/T2 ones don't have to supply power to a LNB (which draws at least 2W). So, your 3W drop can be considered as "normal". For your USB stick even 1W saving can be helpful.
Thanks again for testing.
Sergey.
vdr mailing list vdr@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
Hi,
I've tried this as well now.
I have two Cine S2 dual-tuner cards (an older 5.5 running on ngene driver and a 6.5 running with the ddbridge driver) attached to a cascadable multiswitch.
The VDR (2.2) runs as a headless server with the vnsi plugin to allow to connect Kodi clients to the VDR.
With all adapters active, I see a power consumption of about 50W. When your power-saving patch kicks in, this is reduced by about 7W to 43W.
So far this seems to work fine. Thanks for this patch!
+1 for including this into vanilla VDR.
bye,
Tobias
Hi Sergey,
My VDR setup started having a bit of a fit last night, and has been doing this for the last 8 hours (no changes my end) Before I restart VDR, any tests I can do to diagnose?
It seems to have started after a live stream (Kodi/VNSI) + a recording stopped - here's the VDR-related log from where the connection started to where the problem seemed to start It may be that the VNSI plugin is keeping the receiver active ? (the VNSI-Error: cxSocket::read error occurs 2 or 3 times a day - not unusual, nor is any other log entry)
Jun 24 01:12:59 ha-server vdr: [8690] loading /etc/vdr/plugins/vnsiserver/allowed_hosts.conf Jun 24 01:12:59 ha-server vdr: [8690] VNSI: Client with ID 75 connected: 10.0.0.90:52606 Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Welcome client 'XBMC Media Center' with protocol version '8' Jun 24 01:12:59 ha-server vdr: [15789] VNSI: LiveStreamer::Close - close Jun 24 01:12:59 ha-server vdr: [15789] VNSI: close video input ... Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Successfully found following device: 0x91cef0 (1) for receiving Jun 24 01:12:59 ha-server vdr: [15789] dvb tuner: power-up - opening frontend 0/0 Jun 24 01:12:59 ha-server vdr: [15789] VNSI: activate live receiver: 1, pmt change: 1 Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Successfully switched to channel 1 - BBC ONE Lon Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Started streaming of channel BBC ONE Lon (timeout 5 seconds) Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=101 and type=7 Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=102 and type=2 Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=106 and type=2 Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=105 and type=9 Jun 24 01:13:00 ha-server vdr: [8686] channel 3 (BBC TWO) event Fri 24.06.2016 01:05-02:05 (VPS: 24.06. 01:05) 'The Big C & Me' status 4 Jun 24 01:13:05 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 01:13:10 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 24 01:13:46 ha-server vdr: [15789] VNSI-Error: cxSocket::read(fd=18): read() error at 0/4 Jun 24 01:13:46 ha-server vdr: [15793] VNSI: exit streamer thread Jun 24 01:13:46 ha-server vdr: [15789] VNSI: LiveStreamer::Close - close Jun 24 01:13:46 ha-server vdr: [15789] VNSI: close video input ... Jun 24 01:13:46 ha-server vdr: [15789] VNSI: activate live receiver: 0, pmt change: 0 Jun 24 01:13:46 ha-server vdr: [15789] VNSI: close video input ... Jun 24 01:13:46 ha-server vdr: [8692] VNSI: Client with ID 75 seems to be disconnected, removing from client list Jun 24 01:13:49 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 01:13:51 ha-server vdr: [8690] loading /etc/vdr/plugins/vnsiserver/allowed_hosts.conf Jun 24 01:13:51 ha-server vdr: [8690] VNSI: Client with ID 76 connected: 10.0.0.90:52610 Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Welcome client 'XBMC Media Center' with protocol version '8' Jun 24 01:13:51 ha-server vdr: [15824] VNSI: LiveStreamer::Close - close Jun 24 01:13:51 ha-server vdr: [15824] VNSI: close video input ... Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Successfully found following device: 0x91cef0 (1) for receiving Jun 24 01:13:51 ha-server vdr: [15824] VNSI: activate live receiver: 1, pmt change: 1 Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Successfully switched to channel 1 - BBC ONE Lon Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Started streaming of channel BBC ONE Lon (timeout 5 seconds) Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=101 and type=7 Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=102 and type=2 Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=106 and type=2 Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=105 and type=9 Jun 24 01:13:54 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 24 01:13:59 ha-server vdr: [7056] VNSI-Error: cxSocket::read(fd=6): read() error at 0/4 Jun 24 01:13:59 ha-server vdr: [8692] VNSI: Client with ID 72 seems to be disconnected, removing from client list Jun 24 01:14:33 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 01:14:38 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 24 01:15:17 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 01:15:22 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 24 01:16:01 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 01:16:06 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 24 01:16:43 ha-server vdr: [15824] VNSI-Error: cxSocket::read(fd=8): read() error at 0/4 Jun 24 01:16:43 ha-server vdr: [15826] VNSI: exit streamer thread Jun 24 01:16:43 ha-server vdr: [15824] VNSI: LiveStreamer::Close - close Jun 24 01:16:43 ha-server vdr: [15824] VNSI: close video input ... Jun 24 01:16:43 ha-server vdr: [15824] VNSI: activate live receiver: 0, pmt change: 0 Jun 24 01:16:43 ha-server vdr: [15824] VNSI: close video input ... Jun 24 01:16:43 ha-server vdr: [8692] VNSI: Client with ID 76 seems to be disconnected, removing from client list Jun 24 01:16:45 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 01:16:50 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 24 01:16:56 ha-server vdr: [8690] loading /etc/vdr/plugins/vnsiserver/allowed_hosts.conf Jun 24 01:16:56 ha-server vdr: [8690] VNSI: Client with ID 77 connected: 10.0.0.90:52614 Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Welcome client 'XBMC Media Center' with protocol version '8' Jun 24 01:16:56 ha-server vdr: [16255] VNSI: LiveStreamer::Close - close Jun 24 01:16:56 ha-server vdr: [16255] VNSI: close video input ... Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Successfully found following device: 0x91cef0 (1) for receiving Jun 24 01:16:56 ha-server vdr: [16255] VNSI: activate live receiver: 1, pmt change: 1 Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Successfully switched to channel 20 - ITV Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Started streaming of channel ITV (timeout 5 seconds) Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1701 and type=7 Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1702 and type=2 Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1703 and type=2 Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1731 and type=9 Jun 24 01:17:29 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 01:35:42 ha-server vdr: [8686] channel 45 (Film4) event Fri 24.06.2016 01:35-03:50 (VPS: 24.06. 01:35) 'Greenberg' status 4 Jun 24 01:35:45 ha-server vdr: [8679] timer 1 (45 1635-1850 VPS '-Films~The Spy Who Came In from the Cold~2016.06.23-16:35-Thu') set to no event Jun 24 01:36:11 ha-server vdr: [8679] deleting timer 1 (45 1635-1850 VPS '-Films~The Spy Who Came In from the Cold~2016.06.23-16:35-Thu') Jun 24 01:36:11 ha-server vdr: [8692] VNSI: Timers state changed (71) Jun 24 01:36:11 ha-server vdr: [8692] VNSI: Requesting clients to reload timers Jun 24 02:15:32 ha-server vdr: [16255] VNSI-Error: cxSocket::read(fd=23): read() error at 0/4 Jun 24 02:15:33 ha-server vdr: [16257] VNSI: exit streamer thread Jun 24 02:15:33 ha-server vdr: [16255] VNSI: LiveStreamer::Close - close Jun 24 02:15:33 ha-server vdr: [16255] VNSI: close video input ... Jun 24 02:15:33 ha-server vdr: [16255] VNSI: activate live receiver: 0, pmt change: 0 Jun 24 02:15:33 ha-server vdr: [16255] VNSI: close video input ... Jun 24 02:15:33 ha-server vdr: [8692] VNSI: Client with ID 77 seems to be disconnected, removing from client list Jun 24 02:15:40 ha-server vdr: [15117] VNSI: cxSocket::read(fd=17): eof, connection closed Jun 24 02:15:40 ha-server vdr: [8692] VNSI: Client with ID 74 seems to be disconnected, removing from client list Jun 24 02:20:34 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 0/0 Jun 24 02:20:38 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 24 02:21:17 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 02:21:22 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 24 02:22:01 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 02:22:06 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 .....
Jun 25 09:50:17 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 25 09:50:22 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 25 09:51:01 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 25 09:51:06 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 25 09:51:45 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 25 09:51:50 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0 Jun 25 09:52:29 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
Thanks Richard
On 7/06/2016 14:45, glenvt18 wrote:
Hi Richard,
Unlike DVB-S/S2 tuners your DVB-T/T2 ones don't have to supply power to a LNB (which draws at least 2W). So, your 3W drop can be considered as "normal". For your USB stick even 1W saving can be helpful.
Thanks again for testing.
Sergey.
On Mon, Jun 06, 2016 at 11:21:24AM +0100, Richard F wrote:
Hi Richard,
As there are no debug messages in your log I tried to reconstruct some of them (power-related) - see my comments. Note that an extra second is added to all timeouts due to the 'greater than' comparison. It was done on purpose to add some save margin. Power-saving looks to work OK. But. I don't see any 'timer ... start/stop' or 'record ...' messages in your log. So, I have some questions: 1) Did you fail to record 'The Big C & Me' at 01:05 and 'Greenberg' at 01:35? 2) Did you cancel 'Greenberg'? 3) Was your streaming interrupted? 4) What is your vnsi streaming priority? 5) What is your recording priority? 6) Are the channels you recorded and the channels you streamed on the same transponder? I'm asking this because I see device 1 being idle all that time. 7) What happens with your VDR when a vnsi streaming is interrupted by a higher priority recording on the same device but on another transponder? 8) What timers (their dates) did you have from Jun 24 00:00 to Jun 24 04:00? 9) What is your Vps Margin setting?
Jun 24 01:12:59 ha-server vdr: [8690] loading /etc/vdr/plugins/vnsiserver/allowed_hosts.conf Jun 24 01:12:59 ha-server vdr: [8690] VNSI: Client with ID 75 connected: 10.0.0.90:52606 Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Welcome client 'XBMC Media Center' with protocol version '8' Jun 24 01:12:59 ha-server vdr: [15789] VNSI: LiveStreamer::Close - close Jun 24 01:12:59 ha-server vdr: [15789] VNSI: close video input ... Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Successfully found following device: 0x91cef0 (1) for receiving Jun 24 01:12:59 ha-server vdr: [15789] dvb tuner: power-up - opening frontend 0/0
streaming started on device 0, wake up device 0
Jun 24 01:12:59 ha-server vdr: [15789] VNSI: activate live receiver: 1, pmt change: 1 Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Successfully switched to channel 1 - BBC ONE Lon Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Started streaming of channel BBC ONE Lon (timeout 5 seconds) Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=101 and type=7 Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=102 and type=2 Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=106 and type=2 Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=105 and type=9 Jun 24 01:13:00 ha-server vdr: [8686] channel 3 (BBC TWO) event Fri 24.06.2016 01:05-02:05 (VPS: 24.06. 01:05) 'The Big C & Me' status 4 Jun 24 01:13:05 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 01:13:10 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:13:46 ha-server vdr: [15789] VNSI-Error: cxSocket::read(fd=18): read() error at 0/4 Jun 24 01:13:46 ha-server vdr: [15793] VNSI: exit streamer thread Jun 24 01:13:46 ha-server vdr: [15789] VNSI: LiveStreamer::Close - close Jun 24 01:13:46 ha-server vdr: [15789] VNSI: close video input ... Jun 24 01:13:46 ha-server vdr: [15789] VNSI: activate live receiver: 0, pmt change: 0 Jun 24 01:13:46 ha-server vdr: [15789] VNSI: close video input ... Jun 24 01:13:46 ha-server vdr: [8692] VNSI: Client with ID 75 seems to be disconnected, removing from client list Jun 24 01:13:49 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:13:51 ha-server vdr: [8690] loading /etc/vdr/plugins/vnsiserver/allowed_hosts.conf Jun 24 01:13:51 ha-server vdr: [8690] VNSI: Client with ID 76 connected: 10.0.0.90:52610 Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Welcome client 'XBMC Media Center' with protocol version '8' Jun 24 01:13:51 ha-server vdr: [15824] VNSI: LiveStreamer::Close - close Jun 24 01:13:51 ha-server vdr: [15824] VNSI: close video input ... Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Successfully found following device: 0x91cef0 (1) for receiving Jun 24 01:13:51 ha-server vdr: [15824] VNSI: activate live receiver: 1, pmt change: 1 Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Successfully switched to channel 1 - BBC ONE Lon Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Started streaming of channel BBC ONE Lon (timeout 5 seconds) Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=101 and type=7 Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=102 and type=2 Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=106 and type=2 Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=105 and type=9 Jun 24 01:13:54 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:13:59 ha-server vdr: [7056] VNSI-Error: cxSocket::read(fd=6): read() error at 0/4 Jun 24 01:13:59 ha-server vdr: [8692] VNSI: Client with ID 72 seems to be disconnected, removing from client list Jun 24 01:14:33 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:14:38 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:15:17 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:15:22 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:16:01 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:16:06 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:16:43 ha-server vdr: [15824] VNSI-Error: cxSocket::read(fd=8): read() error at 0/4 Jun 24 01:16:43 ha-server vdr: [15826] VNSI: exit streamer thread Jun 24 01:16:43 ha-server vdr: [15824] VNSI: LiveStreamer::Close - close Jun 24 01:16:43 ha-server vdr: [15824] VNSI: close video input ... Jun 24 01:16:43 ha-server vdr: [15824] VNSI: activate live receiver: 0, pmt change: 0 Jun 24 01:16:43 ha-server vdr: [15824] VNSI: close video input ... Jun 24 01:16:43 ha-server vdr: [8692] VNSI: Client with ID 76 seems to be disconnected, removing from client list Jun 24 01:16:45 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:16:50 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:16:56 ha-server vdr: [8690] loading /etc/vdr/plugins/vnsiserver/allowed_hosts.conf Jun 24 01:16:56 ha-server vdr: [8690] VNSI: Client with ID 77 connected: 10.0.0.90:52614 Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Welcome client 'XBMC Media Center' with protocol version '8' Jun 24 01:16:56 ha-server vdr: [16255] VNSI: LiveStreamer::Close - close Jun 24 01:16:56 ha-server vdr: [16255] VNSI: close video input ... Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Successfully found following device: 0x91cef0 (1) for receiving Jun 24 01:16:56 ha-server vdr: [16255] VNSI: activate live receiver: 1, pmt change: 1 Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Successfully switched to channel 20 - ITV Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Started streaming of channel ITV (timeout 5 seconds) Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1701 and type=7 Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1702 and type=2 Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1703 and type=2 Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1731 and type=9 Jun 24 01:17:29 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:35:42 ha-server vdr: [8686] channel 45 (Film4) event Fri 24.06.2016 01:35-03:50 (VPS: 24.06. 01:35) 'Greenberg' status 4 Jun 24 01:35:45 ha-server vdr: [8679] timer 1 (45 1635-1850 VPS '-Films~The Spy Who Came In from the Cold~2016.06.23-16:35-Thu') set to no event Jun 24 01:36:11 ha-server vdr: [8679] deleting timer 1 (45 1635-1850 VPS '-Films~The Spy Who Came In from the Cold~2016.06.23-16:35-Thu') Jun 24 01:36:11 ha-server vdr: [8692] VNSI: Timers state changed (71) Jun 24 01:36:11 ha-server vdr: [8692] VNSI: Requesting clients to reload timers Jun 24 02:15:32 ha-server vdr: [16255] VNSI-Error: cxSocket::read(fd=23): read() error at 0/4 Jun 24 02:15:33 ha-server vdr: [16257] VNSI: exit streamer thread Jun 24 02:15:33 ha-server vdr: [16255] VNSI: LiveStreamer::Close - close
streaming on device 0 has ended, set device 0 idle timer to 5 min (your setting)
Jun 24 02:15:33 ha-server vdr: [16255] VNSI: close video input ... Jun 24 02:15:33 ha-server vdr: [16255] VNSI: activate live receiver: 0, pmt change: 0 Jun 24 02:15:33 ha-server vdr: [16255] VNSI: close video input ... Jun 24 02:15:33 ha-server vdr: [8692] VNSI: Client with ID 77 seems to be disconnected, removing from client list Jun 24 02:15:40 ha-server vdr: [15117] VNSI: cxSocket::read(fd=17): eof, connection closed Jun 24 02:15:40 ha-server vdr: [8692] VNSI: Client with ID 74 seems to be disconnected, removing from client list Jun 24 02:20:34 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 0/0
device 0 has been idle for 300 sec - power it down
Jun 24 02:20:38 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 02:21:17 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 02:21:22 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 02:22:01 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 02:22:06 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
.....
Jun 25 09:50:17 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 25 09:50:22 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 25 09:51:01 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 25 09:51:06 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 25 09:51:45 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 25 09:51:50 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 25 09:52:29 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
On 28/06/2016 03:14, glenvt18 wrote:
Hi Richard,
As there are no debug messages in your log I tried to reconstruct some of them (power-related) - see my comments. Note that an extra second is added to all timeouts due to the 'greater than' comparison. It was done on purpose to add some save margin. Power-saving looks to work OK. But. I don't see any 'timer ... start/stop' or 'record ...' messages in your log. So, I have some questions:
Yes, I turned off debug as it's been running awhile.
- Did you fail to record 'The Big C & Me' at 01:05 and 'Greenberg' at
01:35?
No, that was just a (standard) notification from VDR that the running status of a program had changed
- Did you cancel 'Greenberg'?
No, VDR was idle before I started up Kodi/VNSI at around 01:00.
Actually looking back through the log some more, it seems that Kodi had one of it's regular hiccup startup problems here. Basically it starts, then crashes, then starts, often 2 or 3 times. This is a known issue - the Kodi devs say they've changed the startup mechanism in newer versions, but these aren't stable enough for regular use for various other reasons.
- Was your streaming interrupted?
- What is your vnsi streaming priority?
Not sure I have a VNSI priority, at least there isn't a setup variable for it.
- What is your recording priority?
Generally 50 or 99. But in this case it wasn't recording, just streaming.
- Are the channels you recorded and the channels you streamed on the same
transponder? I'm asking this because I see device 1 being idle all that time.
As above, there was only 1
- What happens with your VDR when a vnsi streaming is interrupted by a
higher priority recording on the same device but on another transponder?
Not tested.
- What timers (their dates) did you have from Jun 24 00:00 to Jun 24
04:00?
None
- What is your Vps Margin setting?
600
On reflection I think this is really a VNSI problem, possibly a side-effect of locking up the VNSI process. I have had a similar situation in the past (before adding your patch) where VNSI server plugin locks up after a client hiccup start, then any client trying to connect keeps trying to attach and times out. This time the client didn't time out (as I recall), but it was late, so I left it and went to bed...!
I'll monitor for any other effects.
thanks Richard
Jun 24 01:12:59 ha-server vdr: [8690] loading /etc/vdr/plugins/vnsiserver/allowed_hosts.conf Jun 24 01:12:59 ha-server vdr: [8690] VNSI: Client with ID 75 connected: 10.0.0.90:52606 Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Welcome client 'XBMC Media Center' with protocol version '8' Jun 24 01:12:59 ha-server vdr: [15789] VNSI: LiveStreamer::Close - close Jun 24 01:12:59 ha-server vdr: [15789] VNSI: close video input ... Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Successfully found following device: 0x91cef0 (1) for receiving Jun 24 01:12:59 ha-server vdr: [15789] dvb tuner: power-up - opening frontend 0/0
streaming started on device 0, wake up device 0
Jun 24 01:12:59 ha-server vdr: [15789] VNSI: activate live receiver: 1, pmt change: 1 Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Successfully switched to channel 1 - BBC ONE Lon Jun 24 01:12:59 ha-server vdr: [15789] VNSI: Started streaming of channel BBC ONE Lon (timeout 5 seconds) Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=101 and type=7 Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=102 and type=2 Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=106 and type=2 Jun 24 01:12:59 ha-server vdr: [15793] VNSI: Created stream for pid=105 and type=9 Jun 24 01:13:00 ha-server vdr: [8686] channel 3 (BBC TWO) event Fri 24.06.2016 01:05-02:05 (VPS: 24.06. 01:05) 'The Big C & Me' status 4 Jun 24 01:13:05 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 24 01:13:10 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:13:46 ha-server vdr: [15789] VNSI-Error: cxSocket::read(fd=18): read() error at 0/4 Jun 24 01:13:46 ha-server vdr: [15793] VNSI: exit streamer thread Jun 24 01:13:46 ha-server vdr: [15789] VNSI: LiveStreamer::Close - close Jun 24 01:13:46 ha-server vdr: [15789] VNSI: close video input ... Jun 24 01:13:46 ha-server vdr: [15789] VNSI: activate live receiver: 0, pmt change: 0 Jun 24 01:13:46 ha-server vdr: [15789] VNSI: close video input ... Jun 24 01:13:46 ha-server vdr: [8692] VNSI: Client with ID 75 seems to be disconnected, removing from client list Jun 24 01:13:49 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:13:51 ha-server vdr: [8690] loading /etc/vdr/plugins/vnsiserver/allowed_hosts.conf Jun 24 01:13:51 ha-server vdr: [8690] VNSI: Client with ID 76 connected: 10.0.0.90:52610 Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Welcome client 'XBMC Media Center' with protocol version '8' Jun 24 01:13:51 ha-server vdr: [15824] VNSI: LiveStreamer::Close - close Jun 24 01:13:51 ha-server vdr: [15824] VNSI: close video input ... Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Successfully found following device: 0x91cef0 (1) for receiving Jun 24 01:13:51 ha-server vdr: [15824] VNSI: activate live receiver: 1, pmt change: 1 Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Successfully switched to channel 1 - BBC ONE Lon Jun 24 01:13:51 ha-server vdr: [15824] VNSI: Started streaming of channel BBC ONE Lon (timeout 5 seconds) Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=101 and type=7 Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=102 and type=2 Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=106 and type=2 Jun 24 01:13:52 ha-server vdr: [15826] VNSI: Created stream for pid=105 and type=9 Jun 24 01:13:54 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:13:59 ha-server vdr: [7056] VNSI-Error: cxSocket::read(fd=6): read() error at 0/4 Jun 24 01:13:59 ha-server vdr: [8692] VNSI: Client with ID 72 seems to be disconnected, removing from client list Jun 24 01:14:33 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:14:38 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:15:17 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:15:22 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:16:01 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:16:06 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:16:43 ha-server vdr: [15824] VNSI-Error: cxSocket::read(fd=8): read() error at 0/4 Jun 24 01:16:43 ha-server vdr: [15826] VNSI: exit streamer thread Jun 24 01:16:43 ha-server vdr: [15824] VNSI: LiveStreamer::Close - close Jun 24 01:16:43 ha-server vdr: [15824] VNSI: close video input ... Jun 24 01:16:43 ha-server vdr: [15824] VNSI: activate live receiver: 0, pmt change: 0 Jun 24 01:16:43 ha-server vdr: [15824] VNSI: close video input ... Jun 24 01:16:43 ha-server vdr: [8692] VNSI: Client with ID 76 seems to be disconnected, removing from client list Jun 24 01:16:45 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:16:50 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 01:16:56 ha-server vdr: [8690] loading /etc/vdr/plugins/vnsiserver/allowed_hosts.conf Jun 24 01:16:56 ha-server vdr: [8690] VNSI: Client with ID 77 connected: 10.0.0.90:52614 Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Welcome client 'XBMC Media Center' with protocol version '8' Jun 24 01:16:56 ha-server vdr: [16255] VNSI: LiveStreamer::Close - close Jun 24 01:16:56 ha-server vdr: [16255] VNSI: close video input ... Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Successfully found following device: 0x91cef0 (1) for receiving Jun 24 01:16:56 ha-server vdr: [16255] VNSI: activate live receiver: 1, pmt change: 1 Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Successfully switched to channel 20 - ITV Jun 24 01:16:56 ha-server vdr: [16255] VNSI: Started streaming of channel ITV (timeout 5 seconds) Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1701 and type=7 Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1702 and type=2 Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1703 and type=2 Jun 24 01:16:57 ha-server vdr: [16257] VNSI: Created stream for pid=1731 and type=9 Jun 24 01:17:29 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 01:35:42 ha-server vdr: [8686] channel 45 (Film4) event Fri 24.06.2016 01:35-03:50 (VPS: 24.06. 01:35) 'Greenberg' status 4 Jun 24 01:35:45 ha-server vdr: [8679] timer 1 (45 1635-1850 VPS '-Films~The Spy Who Came In from the Cold~2016.06.23-16:35-Thu') set to no event Jun 24 01:36:11 ha-server vdr: [8679] deleting timer 1 (45 1635-1850 VPS '-Films~The Spy Who Came In from the Cold~2016.06.23-16:35-Thu') Jun 24 01:36:11 ha-server vdr: [8692] VNSI: Timers state changed (71) Jun 24 01:36:11 ha-server vdr: [8692] VNSI: Requesting clients to reload timers Jun 24 02:15:32 ha-server vdr: [16255] VNSI-Error: cxSocket::read(fd=23): read() error at 0/4 Jun 24 02:15:33 ha-server vdr: [16257] VNSI: exit streamer thread Jun 24 02:15:33 ha-server vdr: [16255] VNSI: LiveStreamer::Close - close
streaming on device 0 has ended, set device 0 idle timer to 5 min (your setting)
Jun 24 02:15:33 ha-server vdr: [16255] VNSI: close video input ... Jun 24 02:15:33 ha-server vdr: [16255] VNSI: activate live receiver: 0, pmt change: 0 Jun 24 02:15:33 ha-server vdr: [16255] VNSI: close video input ... Jun 24 02:15:33 ha-server vdr: [8692] VNSI: Client with ID 77 seems to be disconnected, removing from client list Jun 24 02:15:40 ha-server vdr: [15117] VNSI: cxSocket::read(fd=17): eof, connection closed Jun 24 02:15:40 ha-server vdr: [8692] VNSI: Client with ID 74 seems to be disconnected, removing from client list Jun 24 02:20:34 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 0/0
device 0 has been idle for 300 sec - power it down
Jun 24 02:20:38 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 02:21:17 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 02:21:22 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 24 02:22:01 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 24 02:22:06 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
.....
Jun 25 09:50:17 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0 Jun 25 09:50:22 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 25 09:51:01 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 25 09:51:06 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 25 09:51:45 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
Jun 25 09:51:50 ha-server vdr: [8679] dvb tuner: power-up - opening frontend 1/0
tune to a transponder on device 1 to refresh EPG before a (VPS) timer starts, call cDevice::SetOccupied(), set device 1 idle timer to 38 sec
Jun 25 09:52:29 ha-server vdr: [8679] dvb tuner: power-down - closing frontend 1/0
device 1 has been idle for 38 sec - power it down
No, that was just a (standard) notification from VDR that the running status of a program had changed
Sorry. I was a bit sleepy that night:) It was a false alarm.
Not sure I have a VNSI priority, at least there isn't a setup variable for it.
It's under Settings->Add-ons->My add-ons->PVR clients-> VDR VNSI Client->Configure->General->Priority. I have it set to 0.
- What timers (their dates) did you have from Jun 24 00:00 to Jun 24
04:00?
None
- What is your Vps Margin setting?
600
In this case your VDR might have been trying to update EPG for the timers scheduled later, probably, next night. Anyway, it's all about VDR's internal logic for updating timers' EPG events and has nothing to do with power saving. Every time a VDR decides to update EPG for a channel with a timer scheduled the device's frontend must be opened prior to zapping and kept open for a while (38 sec as you see in the log). If you have power-related issues you're likely to see ioctl() errors in the log and emergency exits after a recording starts (VDR will be restarted in this case).
I'll monitor for any other effects.
Let me know.
Hi,
Am 26.05.2016 um 17:36 schrieb glenvt18:
I know about the dynamite plugin, but 1) it does much more then this, 2) still requires a VDR patch, which is bigger, 3) doesn't work reliably for me and 4) I think this functionality should be part of the VDR core.
I agree with you. I hope, dynamite was a little inspiration for you. :)
I plan (for several years now, sadly) to break out the udev-part of dynamite to make the vdr more dynamic in device management. The idle-part is a good first step in that direction.
- virtual void PowerDown(bool On) {};
///< Actually powers the device down/up.
I think the name of the parameter is a bit misleading. With On == true you mean, that the device is powered down. Either rename the parameter to "Down" or the function to something like "PowerSaveMode".
Lars.
I agree with you. I hope, dynamite was a little inspiration for you. :)
Yes, I used it for some time. Thanks a lot for your work, Lars!
I plan (for several years now, sadly) to break out the udev-part of dynamite to make the vdr more dynamic in device management. The idle-part is a good first step in that direction.
I remember I've read somewhere (may be at vdr-portal.de) that you had plans to re-work the dynamite plugin and implement the idle part separately.
- virtual void PowerDown(bool On) {}; + ///< Actually powers
the device down/up.
I think the name of the parameter is a bit misleading. With On == true you mean, that the device is powered down. Either rename the parameter to "Down" or the function to something like "PowerSaveMode".
Well, it's a matter of style. "On" is a typical VDR name for such arguments. "Down" looks good as well as "PowerSaveMode" or "PowerDownMode". I'll consider this change. Thanks.
Best, Sergey Chernyavskiy.
I've renamed PowerDown() to PowerDownMode() as Lars suggested and added a comment on IsTunedToTransponder().
Klaus, could you take a look at this please.
A copy of this patch: http://pastebin.com/skxw80hN
VDR 2.2.0 version: http://pastebin.com/JQLjMKvu
Add a newline to the end of a patch file downloaded from pastebin.com.
This patch introduces a feature which allows an idle device (a device which is not currently recording or streaming) to enter a power-down mode after some period of time. Given two timeout values, PowerdownTimeoutM and PowerdownWakeupH, it works like this: when a device becomes idle, it is kept powered up for PowerdownTimeoutM minutes doing, for instance, an EPG scan before it is powered down. If the device is still idle and has been powered down for PowerdownWakeupH hours it is powered up for PowerdownTimeoutM minutes and so on. When recording, streaming or a forced EPG scan starts, the device is powered up and it's idle timer is disabled. This implies that PowerdownTimeoutM should be enough for a full round of EPG scanning (20 seconds * number_of_transponders). Another option is to run EPG scans from cron (at night) and use SVDRP SCAN command.
Actual implementation of power saving facilities is left to a derived device class. In the case of a DVB device it is implemented by closing it's frontend device. For a DVB-S/S2 tuner this usually means powering the LNB off. My measurements show 3-4W power consumption drops per tuner for various DVB-S/S2 tuners. So, this feature (together with HDD spin-down) is especially valuable while running a headless 24/7 VDR server and/or using several tuners. A SATIP device can also implement power saving if it is supported by a server. --- config.c | 9 ++++++ config.h | 3 ++ device.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- device.h | 31 ++++++++++++++++++++ dvbdevice.c | 39 +++++++++++++++++++++++++ dvbdevice.h | 7 +++++ eitscan.c | 7 ++++- menu.c | 9 +++++- vdr.c | 6 ++++ 9 files changed, 203 insertions(+), 4 deletions(-)
diff --git a/config.c b/config.c index e5f5463..794c9f8 100644 --- a/config.c +++ b/config.c @@ -395,6 +395,9 @@ cSetup::cSetup(void) PositionerSpeed = 15; PositionerSwing = 650; PositionerLastLon = 0; + PowerdownEnabled = 0; + PowerdownTimeoutM = 15; + PowerdownWakeupH = 4; SetSystemTime = 0; TimeSource = 0; TimeTransponder = 0; @@ -622,6 +625,9 @@ bool cSetup::Parse(const char *Name, const char *Value) else if (!strcasecmp(Name, "PositionerSpeed")) PositionerSpeed = atoi(Value); else if (!strcasecmp(Name, "PositionerSwing")) PositionerSwing = atoi(Value); else if (!strcasecmp(Name, "PositionerLastLon")) PositionerLastLon = atoi(Value); + else if (!strcasecmp(Name, "PowerdownEnabled")) PowerdownEnabled = atoi(Value); + else if (!strcasecmp(Name, "PowerdownTimeoutM")) PowerdownTimeoutM = atoi(Value); + else if (!strcasecmp(Name, "PowerdownWakeupH")) PowerdownWakeupH = atoi(Value); else if (!strcasecmp(Name, "SetSystemTime")) SetSystemTime = atoi(Value); else if (!strcasecmp(Name, "TimeSource")) TimeSource = cSource::FromString(Value); else if (!strcasecmp(Name, "TimeTransponder")) TimeTransponder = atoi(Value); @@ -753,6 +759,9 @@ bool cSetup::Save(void) Store("PositionerSpeed", PositionerSpeed); Store("PositionerSwing", PositionerSwing); Store("PositionerLastLon", PositionerLastLon); + Store("PowerdownEnabled", PowerdownEnabled); + Store("PowerdownTimeoutM", PowerdownTimeoutM); + Store("PowerdownWakeupH", PowerdownWakeupH); Store("SetSystemTime", SetSystemTime); Store("TimeSource", cSource::ToString(TimeSource)); Store("TimeTransponder", TimeTransponder); diff --git a/config.h b/config.h index e5565da..7a73d9d 100644 --- a/config.h +++ b/config.h @@ -273,6 +273,9 @@ public: int PositionerSpeed; int PositionerSwing; int PositionerLastLon; + int PowerdownEnabled; + int PowerdownTimeoutM; + int PowerdownWakeupH; int SetSystemTime; int TimeSource; int TimeTransponder; diff --git a/device.c b/device.c index 542d120..adbe973 100644 --- a/device.c +++ b/device.c @@ -104,6 +104,9 @@ cDevice::cDevice(void) dvbSubtitleConverter = NULL; autoSelectPreferredSubtitleLanguage = true;
+ idleTimerExpires = time(NULL) + Setup.PowerdownTimeoutM * 60; + wakeupTimerExpires = 0; + for (int i = 0; i < MAXRECEIVERS; i++) receiver[i] = NULL;
@@ -745,6 +748,11 @@ bool cDevice::SwitchChannel(int Direction) return result; }
+// While switching to a channel, the device will be kept powered up +// for at least this number of seconds before a receiver is attached. +// Must be less than cEITScanner::ScanTimeout. +#define CHANNEL_SWITCH_POWERUP_TIMEOUT 10 + eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) { cStatus::MsgChannelSwitch(this, 0, LiveView); @@ -778,6 +786,8 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) Result = scrNotAvailable; } else { + // Power up the device + PowerUp(CHANNEL_SWITCH_POWERUP_TIMEOUT); // Stop section handling: if (sectionHandler) { sectionHandler->SetStatus(false); @@ -843,8 +853,11 @@ int cDevice::Occupied(void) const
void cDevice::SetOccupied(int Seconds) { - if (Seconds >= 0) + if (Seconds >= 0) { occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT); + // avoid short power-down/power-up cycles + SetIdleTimer(true, Seconds + 30); + } }
bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) @@ -1675,6 +1688,7 @@ bool cDevice::AttachReceiver(cReceiver *Receiver) startScrambleDetection = time(NULL); } Start(); + SetIdleTimer(false); return true; } } @@ -1708,8 +1722,10 @@ void cDevice::Detach(cReceiver *Receiver) camSlot->Assign(NULL); } } - if (!receiversLeft) + if (!receiversLeft) { Cancel(-1); + SetIdleTimer(true); + } }
void cDevice::DetachAll(int Pid) @@ -1731,6 +1747,82 @@ void cDevice::DetachAllReceivers(void) Detach(receiver[i]); }
+void cDevice::CheckIdle(void) +{ + if (!SupportsPowerDown() || !Setup.PowerdownEnabled) + return; + cMutexLock MutexLock(&mutexPowerSaving); + if (idleTimerExpires != 0 && time(NULL) > idleTimerExpires) { + // idle, powered up + dsyslog("power saving: device %d idle timer expired", CardIndex() + 1); + SetIdleTimer(false); + if (Setup.PowerdownWakeupH != 0) + wakeupTimerExpires = time(NULL) + Setup.PowerdownWakeupH * 3600; + else + dsyslog("power saving: waking up is disabled"); + if (!IsPoweredDown()) { + dsyslog("power saving: powering device %d down", CardIndex() + 1); + if (sectionHandler) { + sectionHandler->SetStatus(false); + sectionHandler->SetChannel(NULL); + } + PowerDownMode(true); + } + } + if (wakeupTimerExpires != 0 && time(NULL) > wakeupTimerExpires) { + // idle, powered down + dsyslog("power saving: device %d wakeup timer expired", CardIndex() + 1); + SetIdleTimer(true); + if (IsPoweredDown()) { + dsyslog("power saving: waking up device %d", CardIndex() + 1); + PowerDownMode(false); + } + } +} + +void cDevice::SetIdleTimer(bool On, int ExtraTimeoutS) +{ + if (!SupportsPowerDown()) + return; + cMutexLock MutexLock(&mutexPowerSaving); + if (On) { + int Tout = Setup.PowerdownTimeoutM * 60; + time_t Now = time(NULL); + if (ExtraTimeoutS > 0) { + if (idleTimerExpires >= Now + ExtraTimeoutS) + return; + Tout = ExtraTimeoutS; + } + idleTimerExpires = Now + Tout; + if (Setup.PowerdownEnabled) + dsyslog("power saving: set device %d idle timer to %d sec", CardIndex() + 1, Tout); + } + else { + idleTimerExpires = 0; + if (Setup.PowerdownEnabled) + dsyslog("power saving: disable device %d idle timer", CardIndex() + 1); + } + wakeupTimerExpires = 0; +} + +bool cDevice::PoweredDown(void) +{ + if (SupportsPowerDown() && Setup.PowerdownEnabled) { + cMutexLock MutexLock(&mutexPowerSaving); + return IsPoweredDown(); + } + else + return false; +} + +void cDevice::PowerUp(int ExtraTimeoutS) +{ + cMutexLock MutexLock(&mutexPowerSaving); + SetIdleTimer(true, ExtraTimeoutS); + if (SupportsPowerDown() && IsPoweredDown()) + PowerDownMode(false); +} + // --- cTSBuffer -------------------------------------------------------------
cTSBuffer::cTSBuffer(int File, int Size, int CardIndex) diff --git a/device.h b/device.h index 31ee303..cc40bb7 100644 --- a/device.h +++ b/device.h @@ -821,6 +821,37 @@ public: ///< Detaches all receivers from this device for this pid. virtual void DetachAllReceivers(void); ///< Detaches all receivers from this device. + +// Power saving facilities + +private: + cMutex mutexPowerSaving; + time_t idleTimerExpires, wakeupTimerExpires; + void PowerUp(int ExtraTimeoutS); + ///< If the device is powered down, powers it up and keeps it + ///< powered up for at least ExtraTimeoutS seconds (see + ///< cDevice::SetIdleTimer()). +public: + void CheckIdle(void); + ///< Should be called periodically in the main loop. + bool PoweredDown(void); + ///< Returns true if the device is powered down "logically", that is, + ///< idle tasks like EPG scanning are disabled. + void SetIdleTimer(bool On, int ExtraTimeoutS = 0); + ///< Starts/disables the idle timer. This timer must be started when + ///< a device gets idle and must be disabled when it is receiving. + ///< If ExtraTimeoutS is greater than zero and On is true, a new timer + ///< won't be set, but the device will be kept powered up for at least + ///< ExtraTimeoutS seconds. +protected: + ///< NOTE: IsTunedToTransponder() should return false if the + ///< device is powered down. + virtual bool IsPoweredDown(void) {return false;} + ///< Returns true if the device is powered down "physically". + virtual void PowerDownMode(bool On) {}; + ///< Actually powers the device down/up. + virtual bool SupportsPowerDown() {return false;} + ///< Returns true if a derived device supports power saving. };
/// Derived cDevice classes that can receive channels will have to provide diff --git a/dvbdevice.c b/dvbdevice.c index 63af52e..87555b7 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -348,6 +348,8 @@ public: const cPositioner *Positioner(void) const { return positioner; } int GetSignalStrength(void) const; int GetSignalQuality(void) const; + bool IsPoweredDown(void) {return fd_frontend < 0;} + void PowerDownMode(bool On); };
cMutex cDvbTuner::bondMutex; @@ -544,6 +546,8 @@ void cDvbTuner::ClearEventQueue(void) const
bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const { + if (fd_frontend < 0) + return false; ClearEventQueue(); while (1) { if (ioctl(fd_frontend, FE_READ_STATUS, &Status) != -1) @@ -559,6 +563,8 @@ bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
int cDvbTuner::GetSignalStrength(void) const { + if (fd_frontend < 0) + return -1; ClearEventQueue(); uint16_t Signal; while (1) { @@ -1001,6 +1007,26 @@ void cDvbTuner::Action(void) } }
+void cDvbTuner::PowerDownMode(bool On) +{ + cMutexLock MutexLock(&mutex); + if (On && fd_frontend >= 0) { + isyslog("dvb tuner: power-down - closing frontend %d/%d", adapter, frontend); + tunerStatus = tsIdle; + close(fd_frontend); + fd_frontend = -1; + } + if (!On && fd_frontend < 0) { + cString Filename = cString::sprintf("%s/%s%d/%s%d", + DEV_DVB_BASE, DEV_DVB_ADAPTER, adapter, DEV_DVB_FRONTEND, frontend); + isyslog("dvb tuner: power-up - opening frontend %d/%d", adapter, frontend); + fd_frontend = open(Filename, O_RDWR | O_NONBLOCK); + if (fd_frontend < 0) + esyslog("ERROR: can't open DVB device frontend %d/%d", adapter, frontend); + tunerStatus = tsIdle; + } +} + // --- cDvbSourceParam -------------------------------------------------------
class cDvbSourceParam : public cSourceParam { @@ -1712,6 +1738,19 @@ void cDvbDevice::DetachAllReceivers(void) needsDetachBondedReceivers = false; }
+bool cDvbDevice::IsPoweredDown(void) +{ + if (dvbTuner) + return dvbTuner->IsPoweredDown(); + return false; +} + +void cDvbDevice::PowerDownMode(bool On) +{ + if (dvbTuner) + dvbTuner->PowerDownMode(On); +} + // --- cDvbDeviceProbe -------------------------------------------------------
cList<cDvbDeviceProbe> DvbDeviceProbes; diff --git a/dvbdevice.h b/dvbdevice.h index 5ae4952..e21c652 100644 --- a/dvbdevice.h +++ b/dvbdevice.h @@ -290,6 +290,13 @@ protected: virtual void CloseDvr(void); virtual bool GetTSPacket(uchar *&Data); virtual void DetachAllReceivers(void); + +// Power saving facilities + +protected: + virtual bool IsPoweredDown(void); + virtual void PowerDownMode(bool On); + virtual bool SupportsPowerDown() {return true;} };
// A plugin that implements a DVB device derived from cDvbDevice needs to create diff --git a/eitscan.c b/eitscan.c index 41ac25e..765055c 100644 --- a/eitscan.c +++ b/eitscan.c @@ -144,7 +144,8 @@ void cEITScanner::Process(void) bool AnyDeviceSwitched = false; for (int i = 0; i < cDevice::NumDevices(); i++) { cDevice *Device = cDevice::GetDevice(i); - if (Device && Device->ProvidesEIT()) { + if (Device && Device->ProvidesEIT() + && (!Device->PoweredDown() || lastActivity == 0)) { // powered up or forced scan for (cScanData *ScanData = scanList->First(); ScanData; ScanData = scanList->Next(ScanData)) { const cChannel *Channel = ScanData->GetChannel(); if (Channel) { @@ -165,6 +166,10 @@ void cEITScanner::Process(void) } } //dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder()); + if (lastActivity == 0) + // forced scan - set idle timer for each channel switch; + // this prevents powering down while scanning a transponder + Device->SetIdleTimer(true, ScanTimeout + 5); Device->SwitchChannel(Channel, false); scanList->Del(ScanData); AnyDeviceSwitched = true; diff --git a/menu.c b/menu.c index 569900c..5a89771 100644 --- a/menu.c +++ b/menu.c @@ -3715,6 +3715,12 @@ void cMenuSetupLNB::Setup(void) Add(new cMenuEditIntxItem(tr("Setup.LNB$Positioner speed (degrees/s)"), &data.PositionerSpeed, 1, 1800, 10)); }
+ Add(new cMenuEditBoolItem(tr("Setup.LNB$Enable power saving"), &data.PowerdownEnabled)); + if (data.PowerdownEnabled) { + Add(new cMenuEditIntItem(tr("Setup.LNB$Power down an idle device after (min)"), &data.PowerdownTimeoutM)); + Add(new cMenuEditIntItem(tr("Setup.LNB$Wake up from power-down after (h)"), &data.PowerdownWakeupH)); + } + SetCurrent(Get(current)); Display(); } @@ -3723,6 +3729,7 @@ eOSState cMenuSetupLNB::ProcessKey(eKeys Key) { int oldDiSEqC = data.DiSEqC; int oldUsePositioner = data.UsePositioner; + int oldPowerdownEnabled = data.PowerdownEnabled; bool DeviceBondingsChanged = false; if (Key == kOk) { cString NewDeviceBondings = satCableNumbers.ToString(); @@ -3731,7 +3738,7 @@ eOSState cMenuSetupLNB::ProcessKey(eKeys Key) } eOSState state = cMenuSetupBase::ProcessKey(Key);
- if (Key != kNone && (data.DiSEqC != oldDiSEqC || data.UsePositioner != oldUsePositioner)) + if (Key != kNone && (data.DiSEqC != oldDiSEqC || data.UsePositioner != oldUsePositioner || data.PowerdownEnabled != oldPowerdownEnabled)) Setup(); else if (DeviceBondingsChanged) cDvbDevice::BondDevices(data.DeviceBondings); diff --git a/vdr.c b/vdr.c index 6b0bf2b..c8de702 100644 --- a/vdr.c +++ b/vdr.c @@ -1515,6 +1515,12 @@ int main(int argc, char *argv[])
ReportEpgBugFixStats();
+ for (int i = 0; i < cDevice::NumDevices(); i++) { + cDevice *d = cDevice::GetDevice(i); + if (d) + d->CheckIdle(); + } + // Main thread hooks of plugins: PluginManager.MainThreadHook(); }
On 18.08.2016 17:32, glenvt18 wrote:
I've renamed PowerDown() to PowerDownMode() as Lars suggested and added a comment on IsTunedToTransponder().
Klaus, could you take a look at this please.
Just a few comments that came up while quickly looking over the diff.
... diff --git a/config.c b/config.c index e5f5463..794c9f8 100644 --- a/config.c +++ b/config.c @@ -395,6 +395,9 @@ cSetup::cSetup(void) PositionerSpeed = 15; PositionerSwing = 650; PositionerLastLon = 0;
- PowerdownEnabled = 0;
- PowerdownTimeoutM = 15;
- PowerdownWakeupH = 4;
Couldn't PowerdownEnabled be replaced by checking for 'PowerdownTimeoutM != 0'?
Why exactly do we need PowerdownWakeupH? A device gets woken up if it is used, so why the extra wakeup? Am I missing something here?
... diff --git a/device.c b/device.c index 542d120..adbe973 100644 --- a/device.c +++ b/device.c ... @@ -843,8 +853,11 @@ int cDevice::Occupied(void) const
void cDevice::SetOccupied(int Seconds) {
- if (Seconds >= 0)
- if (Seconds >= 0) { occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT);
// avoid short power-down/power-up cycles
SetIdleTimer(true, Seconds + 30);
Is '30' some magic number? Maybe define a macro or at least add some comment that explains it. Besides, see below about the necessity of ExtraTimeoutS.
... @@ -1731,6 +1747,82 @@ void cDevice::DetachAllReceivers(void) Detach(receiver[i]); }
+void cDevice::CheckIdle(void) +{
- if (!SupportsPowerDown() || !Setup.PowerdownEnabled)
Better check Setup.PowerdownEnabled first (just a feeling ;-).
... diff --git a/device.h b/device.h index 31ee303..cc40bb7 100644 --- a/device.h +++ b/device.h @@ -821,6 +821,37 @@ public: ///< Detaches all receivers from this device for this pid. virtual void DetachAllReceivers(void); ///< Detaches all receivers from this device.
+// Power saving facilities
+private:
- cMutex mutexPowerSaving;
- time_t idleTimerExpires, wakeupTimerExpires;
- void PowerUp(int ExtraTimeoutS);
///< If the device is powered down, powers it up and keeps it
///< powered up for at least ExtraTimeoutS seconds (see
///< cDevice::SetIdleTimer()).
What's the need for this ExtraTimeoutS? Apparently this is only used with CHANNEL_SWITCH_POWERUP_TIMEOUT, which is 10 seconds. The smallest power down timeout is one minute, so why these extra 10 seconds?
Why do we need a PowerUp() function in the first place? Wouldn't it suffice to call SetIdleTimer(false) and have it call [Set]PowerDownMode() accordingly? (see below about the [Set]).
Come to think of it, [Set]PowerDownMode(false) actually turns a device *on*, right? This feels, well, uncomfortable to me. I'd rather have a function that turns the device *on* when the parameter is *true*. These "double negations" always feel somewhat strange to me. Maybe rename that function to SetPowerMode()?
+public:
- void CheckIdle(void);
///< Should be called periodically in the main loop.
- bool PoweredDown(void);
///< Returns true if the device is powered down "logically", that is,
///< idle tasks like EPG scanning are disabled.
- void SetIdleTimer(bool On, int ExtraTimeoutS = 0);
///< Starts/disables the idle timer. This timer must be started when
///< a device gets idle and must be disabled when it is receiving.
///< If ExtraTimeoutS is greater than zero and On is true, a new timer
///< won't be set, but the device will be kept powered up for at least
///< ExtraTimeoutS seconds.
I'm afraid I don't quite understand what this ExtraTimeoutS is about? If every call to SetIdleTimer(true) sets the timer to at least one minute from the time of the call, what's the need for an extra timeout?
+protected:
///< NOTE: IsTunedToTransponder() should return false if the
///< device is powered down.
- virtual bool IsPoweredDown(void) {return false;}
///< Returns true if the device is powered down "physically".
- virtual void PowerDownMode(bool On) {};
///< Actually powers the device down/up.
Hmm, "PowerDownMode()" sounds more like a *query* to me than an actual setting function. Personally I'd consider the original "PowerDown()" more appropriate. Or, if it has to contain "Mode", maybe "SetPowerDownMode()". See above for a general remark about "double negations" ;-).
... diff --git a/dvbdevice.c b/dvbdevice.c index 63af52e..87555b7 100644 --- a/dvbdevice.c +++ b/dvbdevice.c ... @@ -1001,6 +1007,26 @@ void cDvbTuner::Action(void) } }
+void cDvbTuner::PowerDownMode(bool On) +{
- cMutexLock MutexLock(&mutex);
- if (On && fd_frontend >= 0) {
isyslog("dvb tuner: power-down - closing frontend %d/%d", adapter, frontend);
tunerStatus = tsIdle;
close(fd_frontend);
fd_frontend = -1;
}
- if (!On && fd_frontend < 0) {
cString Filename = cString::sprintf("%s/%s%d/%s%d",
DEV_DVB_BASE, DEV_DVB_ADAPTER, adapter, DEV_DVB_FRONTEND, frontend);
Is there a reason why you are not using DvbOpen() here?
... diff --git a/eitscan.c b/eitscan.c index 41ac25e..765055c 100644 --- a/eitscan.c +++ b/eitscan.c @@ -144,7 +144,8 @@ void cEITScanner::Process(void) bool AnyDeviceSwitched = false; for (int i = 0; i < cDevice::NumDevices(); i++) { cDevice *Device = cDevice::GetDevice(i);
if (Device && Device->ProvidesEIT()) {
if (Device && Device->ProvidesEIT()
&& (!Device->PoweredDown() || lastActivity == 0)) { // powered up or forced scan for (cScanData *ScanData = scanList->First(); ScanData; ScanData = scanList->Next(ScanData)) { const cChannel *Channel = ScanData->GetChannel(); if (Channel) {
@@ -165,6 +166,10 @@ void cEITScanner::Process(void) } } //dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder());
if (lastActivity == 0)
// forced scan - set idle timer for each channel switch;
// this prevents powering down while scanning a transponder
Device->SetIdleTimer(true, ScanTimeout + 5);
'5' - another magic number?
... diff --git a/menu.c b/menu.c index 569900c..5a89771 100644 --- a/menu.c +++ b/menu.c @@ -3715,6 +3715,12 @@ void cMenuSetupLNB::Setup(void) Add(new cMenuEditIntxItem(tr("Setup.LNB$Positioner speed (degrees/s)"), &data.PositionerSpeed, 1, 1800, 10)); }
- Add(new cMenuEditBoolItem(tr("Setup.LNB$Enable power saving"), &data.PowerdownEnabled));
- if (data.PowerdownEnabled) {
Add(new cMenuEditIntItem(tr("Setup.LNB$Power down an idle device after (min)"), &data.PowerdownTimeoutM));
Add(new cMenuEditIntItem(tr("Setup.LNB$Wake up from power-down after (h)"), &data.PowerdownWakeupH));
}
This could be simplified if (as mentioned above) we replace PowerdownEnabled with 'PowerdownTimeoutM != 0' and lose the PowerdownWakeupH (which's rationale I don't see).
Klaus
Hi Klaus,
Thanks for reviewing.
diff --git a/config.c b/config.c index e5f5463..794c9f8 100644 --- a/config.c +++ b/config.c @@ -395,6 +395,9 @@ cSetup::cSetup(void) PositionerSpeed = 15; PositionerSwing = 650; PositionerLastLon = 0;
- PowerdownEnabled = 0;
- PowerdownTimeoutM = 15;
- PowerdownWakeupH = 4;
Couldn't PowerdownEnabled be replaced by checking for 'PowerdownTimeoutM != 0'?
PowerdownTimeoutM == 0 means that a device will be powered down immediately after it's receiving thread has ended. It can be useful if, for instance, you want to schedule EPG scan using SVDRP SCAN command or, you don't use EIT at all and collect EPG data from external sources like XMLTV.
Why exactly do we need PowerdownWakeupH? A device gets woken up if it is used, so why the extra wakeup? Am I missing something here?
I see three major reasons for having this setting:
1. If a device is inactive (and is powered down) for a very long period of time, periodic wake-ups for an EPG scan keep EPG up-to-date. Of course, EPGScanTimeout can be used to achieve the same but, 1) it follows it's own logic (for example, it can interrupt streaming with priority=-1 and a single tuner - a known issue with VNSI) and, 2) is set separately (not connected to power saving) and can be disabled (set to a very big value). On the other hand, PowerdownWakeupH's logic is simple and straightforward.
2. If you don't want to have a device powered down for long periods of time to avoid freezing/hanging (give it kicks from time to time or, in the case of a general device, let it do some housekeeping). It's quite typical for a power saving function to have both timeouts.
3. These two timeouts together with scheduled scans give more flexibility.
As long as PowerdownTimeoutM == o(PowerdownWakeupH) wake-ups don't add much to the average power consumption. Setting PowerdownWakeupH to 0 disables waking up completely (device.c:1759). This can be made default.
Here and below, when I refer to source line numbers I mean vanilla VDR 2.3.1 from https://projects.vdr-developer.org/git/vdr.git/snapshot/vdr-2.3.1.tar.bz2 with only this patch applied.
diff --git a/device.c b/device.c index 542d120..adbe973 100644 --- a/device.c +++ b/device.c ... @@ -843,8 +853,11 @@ int cDevice::Occupied(void) const
void cDevice::SetOccupied(int Seconds) {
- if (Seconds >= 0)
- if (Seconds >= 0) { occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT);
// avoid short power-down/power-up cycles
SetIdleTimer(true, Seconds + 30);
Is '30' some magic number? Maybe define a macro or at least add some comment that explains it.
SetOccupied() is called with TIMERDEVICETIMEOUT which is 8 seconds. SetChannel() powers up a device for CHANNEL_SWITCH_POWERUP_TIMEOUT (=10) seconds. When SetOccupied() is called sequentially, the device is powered up for 10 seconds (the largest of the two), then it is powered down and is immediately powered up again. Though my tuners handle those quick up/down transitions correctly, I limited them to a reasonable time interval - not less than 30 seconds. It's a kind of a filter. Maybe the comment should be
// avoid short (less than 30 seconds) power-down/power-up cycles
I don't think defining a local constant here will make the code look clearer.
Besides, see below about the necessity of ExtraTimeoutS.
Below.
@@ -1731,6 +1747,82 @@ void cDevice::DetachAllReceivers(void) Detach(receiver[i]); }
+void cDevice::CheckIdle(void) +{
- if (!SupportsPowerDown() || !Setup.PowerdownEnabled)
Better check Setup.PowerdownEnabled first (just a feeling ;-).
The statement here is: if a device doesn't support power saving, don't execute any power-related code after this check. I can't imagine an overridden function other than '{return true;}' but if calling a function first is confusing, they can be swapped. It really doesn't matter here.
diff --git a/device.h b/device.h index 31ee303..cc40bb7 100644 --- a/device.h +++ b/device.h @@ -821,6 +821,37 @@ public: ///< Detaches all receivers from this device for this pid. virtual void DetachAllReceivers(void); ///< Detaches all receivers from this device.
+// Power saving facilities
+private:
- cMutex mutexPowerSaving;
- time_t idleTimerExpires, wakeupTimerExpires;
- void PowerUp(int ExtraTimeoutS);
///< If the device is powered down, powers it up and keeps it
///< powered up for at least ExtraTimeoutS seconds (see
///< cDevice::SetIdleTimer()).
What's the need for this ExtraTimeoutS? Apparently this is only used with CHANNEL_SWITCH_POWERUP_TIMEOUT, which is 10 seconds. The smallest power down timeout is one minute, so why these extra 10 seconds?
ExtraTimeoutS is passed to SetIdleTimer(). It has nothing to do with Setup.PowerdownTimeoutM. When SetIdleTimer() is called without ExtraTimeoutS (defaults to 0), it just arms the idle timer with Setup.PowerdownTimeoutM. When it is called with ExtraTimeoutS it behaves differently. It checks if the idle timer expires in ExtraTimeoutS seconds from now and, if it does, *prolongs* it. If the idle timer is not armed it is armed with ExtraTimeoutS seconds. In other words, SetIdleTimer(true, T) guarantees that the device won't be unexpectedly powered down in T seconds time from now.
CHANNEL_SWITCH_POWERUP_TIMEOUT is used to ensure the device won't be powered up forever if AttachReceiver() for some reason fails or is not called at all. If AttachReceiver() succeeds, the idle timer is disabled until the last receiver is detached. The value of 10 seconds should be enough for SetChannelDevice()->AttachReceiver() chain to complete. As SetChannelDevice() is non-blocking this is the case (even if WAIT_FOR_TUNER_LOCK is defined - device.c:1663).
CHANNEL_SWITCH_POWERUP_TIMEOUT must be less than cEITScanner::ScanTimeout (device.c:753). Otherwise, an EPG scan will never end - PoweredDown() will be returning false every time.
Why do we need a PowerUp() function in the first place? Wouldn't it suffice to call SetIdleTimer(false) and have it call [Set]PowerDownMode() accordingly? (see below about the [Set]).
We don't really. Any modern compiler will inline it anyway. I just don't like the idea of spreading power-related code over cDevice, especially mutex locking. It's like a nested class. That's why PowerUp() (as a nested class method) accepts an argument.
Come to think of it, [Set]PowerDownMode(false) actually turns a device *on*, right? This feels, well, uncomfortable to me. I'd rather have a function that turns the device *on* when the parameter is *true*. These "double negations" always feel somewhat strange to me. Maybe rename that function to SetPowerMode()?
Well, talking about power-down we also say 'enter/leave power-down [mode]'. In this case there is no double negation :). I don't care much about this name but, I think, it's better (for a derived class developer) to have one 2-in-1 virtual function than 2 on/off functions. SetPowerDownMode() sounds OK. How about EnterPowerDown[Mode]()? SetPowerMode() - hmm, what is 'power mode'? I'm running out of names...
+public:
- void CheckIdle(void);
///< Should be called periodically in the main loop.
- bool PoweredDown(void);
///< Returns true if the device is powered down "logically", that is,
///< idle tasks like EPG scanning are disabled.
- void SetIdleTimer(bool On, int ExtraTimeoutS = 0);
///< Starts/disables the idle timer. This timer must be started when
///< a device gets idle and must be disabled when it is receiving.
///< If ExtraTimeoutS is greater than zero and On is true, a new timer
///< won't be set, but the device will be kept powered up for at least
///< ExtraTimeoutS seconds.
I'm afraid I don't quite understand what this ExtraTimeoutS is about? If every call to SetIdleTimer(true) sets the timer to at least one minute from the time of the call, what's the need for an extra timeout?
Explained above - see PowerUp().
+protected:
///< NOTE: IsTunedToTransponder() should return false if the
///< device is powered down.
- virtual bool IsPoweredDown(void) {return false;}
///< Returns true if the device is powered down "physically".
- virtual void PowerDownMode(bool On) {};
///< Actually powers the device down/up.
Hmm, "PowerDownMode()" sounds more like a *query* to me than an actual setting function. Personally I'd consider the original "PowerDown()" more appropriate. Or, if it has to contain "Mode", maybe "SetPowerDownMode()". See above for a general remark about "double negations" ;-).
IsPoweredDown() should sound like a query too I hope ;-)
diff --git a/dvbdevice.c b/dvbdevice.c index 63af52e..87555b7 100644 --- a/dvbdevice.c +++ b/dvbdevice.c ... @@ -1001,6 +1007,26 @@ void cDvbTuner::Action(void) } }
+void cDvbTuner::PowerDownMode(bool On) +{
- cMutexLock MutexLock(&mutex);
- if (On && fd_frontend >= 0) {
isyslog("dvb tuner: power-down - closing frontend %d/%d", adapter, frontend);
tunerStatus = tsIdle;
close(fd_frontend);
fd_frontend = -1;
}
- if (!On && fd_frontend < 0) {
cString Filename = cString::sprintf("%s/%s%d/%s%d",
DEV_DVB_BASE, DEV_DVB_ADAPTER, adapter, DEV_DVB_FRONTEND, frontend);
Is there a reason why you are not using DvbOpen() here?
cDvbDevice::DvbOpen() is 'protected' and we are in a cDvbTuner member here.
diff --git a/eitscan.c b/eitscan.c index 41ac25e..765055c 100644 --- a/eitscan.c +++ b/eitscan.c @@ -144,7 +144,8 @@ void cEITScanner::Process(void) bool AnyDeviceSwitched = false; for (int i = 0; i < cDevice::NumDevices(); i++) { cDevice *Device = cDevice::GetDevice(i);
if (Device && Device->ProvidesEIT()) {
if (Device && Device->ProvidesEIT()
&& (!Device->PoweredDown() || lastActivity == 0)) { // powered up or forced scan for (cScanData *ScanData = scanList->First(); ScanData; ScanData = scanList->Next(ScanData)) { const cChannel *Channel = ScanData->GetChannel(); if (Channel) {
@@ -165,6 +166,10 @@ void cEITScanner::Process(void) } } //dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder());
if (lastActivity == 0)
// forced scan - set idle timer for each channel switch;
// this prevents powering down while scanning a transponder
Device->SetIdleTimer(true, ScanTimeout + 5);
'5' - another magic number?
5 here means '1', but a bit bigger. In other words, it's O(1) and o(ScanTimeout). It's a small margin used to ensure consecutive scans overlap so that a device is powered up before the first transponder and is powered down after the last one. This is done only if a forced scan is requested.
diff --git a/menu.c b/menu.c index 569900c..5a89771 100644 --- a/menu.c +++ b/menu.c @@ -3715,6 +3715,12 @@ void cMenuSetupLNB::Setup(void) Add(new cMenuEditIntxItem(tr("Setup.LNB$Positioner speed (degrees/s)"), &data.PositionerSpeed, 1, 1800, 10)); }
- Add(new cMenuEditBoolItem(tr("Setup.LNB$Enable power saving"), &data.PowerdownEnabled));
- if (data.PowerdownEnabled) {
Add(new cMenuEditIntItem(tr("Setup.LNB$Power down an idle device after (min)"), &data.PowerdownTimeoutM));
Add(new cMenuEditIntItem(tr("Setup.LNB$Wake up from power-down after (h)"), &data.PowerdownWakeupH));
}
This could be simplified if (as mentioned above) we replace PowerdownEnabled with 'PowerdownTimeoutM != 0' and lose the PowerdownWakeupH (which's rationale I don't see).
I think hiding timeout options when power saving is disabled and expanding them when it is enabled looks pretty nice in UI - just like BIOS settings ;-)