summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xresponsefile.c2
-rwxr-xr-xresponsevdrdir.c1
-rwxr-xr-xsmarttvfactory.c101
-rwxr-xr-xsmarttvfactory.h34
-rwxr-xr-xsmarttvweb.conf3
-rwxr-xr-xstvw_cfg.c14
-rwxr-xr-xstvw_cfg.h2
7 files changed, 147 insertions, 10 deletions
diff --git a/responsefile.c b/responsefile.c
index cdf47b4..66fb45f 100755
--- a/responsefile.c
+++ b/responsefile.c
@@ -23,6 +23,7 @@
#include "responsefile.h"
#include "httpresource.h"
+#include "smarttvfactory.h"
#include <vector>
#include <sys/stat.h>
@@ -53,6 +54,7 @@ cResponseFile::~cResponseFile() {
diff = (now.tv_sec - mResponseStart.tv_sec);
diff += (now.tv_usec - mResponseStart.tv_usec) /1000000.0;
+ (mRequest->mFactory->mUsageStatistics)->addUsageInfo(mRequest->mRemoteAddr, diff);
*(mLog->log())<< DEBUGPREFIX
<< " cResponseFile: Response duration= " << diff << " s"
<< " RemoteIP= " << mRequest->mRemoteAddr
diff --git a/responsevdrdir.c b/responsevdrdir.c
index 1813441..5727bd6 100755
--- a/responsevdrdir.c
+++ b/responsevdrdir.c
@@ -98,6 +98,7 @@ cResponseVdrDir::~cResponseVdrDir() {
char f[20];
snprintf(f, sizeof(f), "%.02f", diff);
+ (mRequest->mFactory->mUsageStatistics)->addUsageInfo(mRequest->mRemoteAddr, diff);
*(mLog->log())<< DEBUGPREFIX
<< " cResponseVdrDir: Response duration= " << f << " s"
<< " RemoteIP= " << mRequest->mRemoteAddr
diff --git a/smarttvfactory.c b/smarttvfactory.c
index dc425a5..7afb07d 100755
--- a/smarttvfactory.c
+++ b/smarttvfactory.c
@@ -1,7 +1,7 @@
/*
* smarttvfactory.c: VDR on Smart TV plugin
*
- * Copyright (C) 2012 - 2014 T. Lohmar
+ * Copyright (C) 2012 - 2016 T. Lohmar
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -93,7 +93,7 @@ cCmd::cCmd(string t) :mTitle(), mCommand(), mConfirm(false) {
void cCmd::trim(string &t) {
int m=0;
- for (int i=0; i<t.size(); i++)
+ for (uint i=0; i<t.size(); i++)
if (!((t[i] == 32) || (t[i] == 9)) ) {
m =i;
break;
@@ -191,7 +191,6 @@ int cRecEntry::writeXmlItem(string * msg, string own_ip, int own_port) {
hdr += "<item>\n";
hdr += "<title>" + mTitle +"</title>\n";
hdr += "<isfolder>false</isfolder>\n";
- // mRec->IsPesRecording();
snprintf(f, sizeof(f), "http://%s:%d%s", own_ip.c_str(), own_port,
cUrlEncode::doUrlSaveEncode(mRec->FileName()).c_str());
@@ -360,12 +359,101 @@ cRecFolder* cRecFolder::GetFolder(list<string> *folder_list) {
return NULL;
}
+sUsageStatistics::sUsageStatistics(string fn, Log* l) : collectionDay(), clientEntry(), enabled(true), collectionWindow(3600),
+ usageStatLogFilename(fn), mLog(l) {
+
+ time_t rawtime;
+ time (&rawtime);
+ struct tm * now = localtime (&rawtime);
+
+ now->tm_sec = 0;
+ collectionDay = mktime(now);
+
+ if (fn.length() == 0)
+ enabled = false;
+
+ if (enabled)
+ *(mLog->log()) << mLog->getTimeString()
+ << ": UsageStats is enabled, StatsFile= "
+ << usageStatLogFilename
+ << " collectionWindow=" << collectionWindow
+ << endl;
+ else
+ *(mLog->log()) << mLog->getTimeString()
+ << ": UsageStats is disabled "
+ << endl;
+};
+
+void sUsageStatistics::checkDay() {
+ time_t rawtime;
+ struct tm * now;
+
+ time (&rawtime);
+ now = localtime (&rawtime);
+
+ if ((collectionDay + collectionWindow ) > rawtime) {
+ *(mLog->log()) << mLog->getTimeString()
+ << ": UsageStats - check: Still not time to write time left= "
+ << (collectionDay + collectionWindow ) - rawtime
+ << endl;
+ return;
+ }
+
+ ofstream ofs;
+ ofs.open(usageStatLogFilename.c_str(), ios::out | ios::app);
+
+ *(mLog->log()) << mLog->getTimeString()
+ << ": UsageStats: appending " << clientEntry.size() << " entries to log" << endl;
+ now->tm_sec = 0;
+
+ for (uint i = 0; i < clientEntry.size(); i++) {
+ ofs << mLog->getTimeString() << " client " << clientEntry[i].ipAddr
+ << " Dur= " << clientEntry[i].usage
+ << " sec Count= " << clientEntry[i].count
+ << endl;
+ }
+
+ ofs.close();
+
+ while (collectionDay < rawtime) {
+ collectionDay += collectionWindow;
+ }
+
+ // Flush and reset
+ clientEntry.clear();
+}
+
+void sUsageStatistics::addUsageInfo (string ip, double dur) {
+ if (!enabled)
+ return;
+
+ checkDay();
+
+ bool found = false;
+ for (uint i = 0; i < clientEntry.size(); i++) {
+ if (clientEntry[i].ipAddr == ip) {
+ found = true;
+ clientEntry[i].usage += dur;
+ clientEntry[i].count += 1;
+ *(mLog->log()) << mLog->getTimeString()
+ << ": UsageStats: adding info for " << ip << " dur= " << dur << " sec to existing record" << endl;
+ break;
+ }
+ }
+ if (!found) {
+ sUsageStatsEntry elm (ip, dur);
+ *(mLog->log()) << mLog->getTimeString()
+ << ": UsageStats: adding info for " << ip << " dur= " << dur << " sec to a new record" << endl;
+ clientEntry.push_back(sUsageStatsEntry(ip, dur));
+ }
+}
SmartTvServer::SmartTvServer(): cStatus(), mRequestCount(0), isInited(false), serverPort(PORT), mServerFd(-1),
mSegmentDuration(10), mHasMinBufferTime(40), mLiveChannels(20),
clientList(), mConTvClients(), mRecCmds(), mCmdCmds(), mRecMsg(), mCmdMsg(), mActiveSessions(0), mHttpClientId(0),
mConfig(NULL), mMaxFd(0),
- mManagedUrls(NULL), mActRecordings(), mRecordings(NULL), mRecState(0), mClientBlackList() {
+ mManagedUrls(NULL), mActRecordings(), mRecordings(NULL), mRecState(0), mClientBlackList(),
+ mUsageStatistics(NULL){
}
@@ -399,7 +487,7 @@ void SmartTvServer::Recording(const cDevice *Device, const char *Name, const cha
*(mLog.log()) << mLog.getTimeString() << ": WARNING in SmartTvServer::Recording: Name and FileName are NULL. Return. " << endl;
return;
}
- // cRecording* rec = Recordings.GetByName(FileName);
+
#if APIVERSNUM > 20300
LOCK_RECORDINGS_READ;
const cRecording* rec = Recordings->GetByName(FileName);
@@ -1116,6 +1204,9 @@ void SmartTvServer::initServer(string dir, cSmartTvConfig* cfg) {
mHasMinBufferTime= mConfig->getHasMinBufferTime();
mLiveChannels = mConfig->getLiveChannels();
+ //mUsageStatistics = new sUsageStatistics("/multimedia/video/usage.txt", &mLog);
+ mUsageStatistics = new sUsageStatistics(mConfig->getUsageStatsLogFile(), &mLog);
+
*(mLog.log()) << mLog.getTimeString() <<": HTTP server listening on port " << serverPort << endl;
mServerFd = socket(PF_INET, SOCK_STREAM, 0);
diff --git a/smarttvfactory.h b/smarttvfactory.h
index 3e5b95b..c4699e1 100755
--- a/smarttvfactory.h
+++ b/smarttvfactory.h
@@ -1,7 +1,7 @@
/*
* smarttvfactory.h: VDR on Smart TV plugin
*
- * Copyright (C) 2012 - 2015 T. Lohmar
+ * Copyright (C) 2012 - 2016 T. Lohmar
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -47,8 +47,8 @@ class cStatus {
using namespace std;
-#define PLG_VERSION "1.0.3"
-#define SERVER "SmartTvWeb/1.0.3"
+#define PLG_VERSION "1.0.4"
+#define SERVER "SmartTvWeb/1.0.4"
class cLiveRelay;
@@ -146,6 +146,32 @@ class cRecEntry : public cRecEntryBase {
};
};
+//----------------------------
+struct sUsageStatsEntry {
+ string ipAddr;
+ double usage;
+ int count;
+sUsageStatsEntry() : ipAddr(""), usage(0.0), count (0) {};
+sUsageStatsEntry(string ip, double d) : ipAddr(ip), usage(d), count(1) {};
+};
+
+class sUsageStatistics {
+ private:
+ // struct tm collectionDay; // once the collectionDay is changed, the stats are written
+ time_t collectionDay; // once the collectionDay is changed, the stats are written
+ vector<sUsageStatsEntry> clientEntry;
+ bool enabled;
+ int collectionWindow;
+
+ string usageStatLogFilename;
+ Log *mLog;
+
+ void checkDay();
+
+ public:
+ sUsageStatistics(string fn, Log* mLog);
+ void addUsageInfo (string ip, double dur);
+};
class SmartTvServer : public cStatus {
@@ -264,6 +290,8 @@ class SmartTvServer : public cStatus {
void CreateRecDb();
list<string> mClientBlackList;
+ public:
+ sUsageStatistics *mUsageStatistics;
};
diff --git a/smarttvweb.conf b/smarttvweb.conf
index 97849ec..9f08201 100755
--- a/smarttvweb.conf
+++ b/smarttvweb.conf
@@ -44,3 +44,6 @@ BuiltInLiveBufDur 600
# Value of the access-control-allow-origin HTTP response header
#CorsHeader http://192.168.1.122 http://teefax:8000
+# Allows collecting of usage stats of recording
+# Intention is to allow parents to monitor TV recordings consumption
+# UsageStatsLogFile /var/log/smarttvweb/usagestats.log \ No newline at end of file
diff --git a/stvw_cfg.c b/stvw_cfg.c
index b3279b3..09e2934 100755
--- a/stvw_cfg.c
+++ b/stvw_cfg.c
@@ -1,7 +1,7 @@
/*
* stvw_cfg.h: VDR on Smart TV plugin
*
- * Copyright (C) 2012, 2013 T. Lohmar
+ * Copyright (C) 2012 - 2016 T. Lohmar
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -35,7 +35,7 @@ cSmartTvConfig::cSmartTvConfig(): mConfigDir(""), mLog(NULL), mCfgFile(NULL), mU
mLogFile(), mMediaFolder(), mSegmentDuration(), mHasMinBufferTime(), mHasBitrateCorrection(),
mLiveChannels(), mGroupSep(IGNORE), mServerAddress(""), mServerPort(8000), mCmds(false), mUseStreamDev4Live(true),
mBuiltInLiveStartMode (4), mBuiltInLivePktBuf4Hd(150), mBuiltInLivePktBuf4Sd(75), mBuiltInLiveBufDur(0.6),
- mAddCorsHeader(false), mCorsHeaderPyld() {
+ mAddCorsHeader(false), mCorsHeaderPyld(), mUsageStatsLogFile("") {
#ifndef STANDALONE
mLogFile= "";
@@ -79,6 +79,8 @@ void cSmartTvConfig::Store(cPlugin *mPlugin) {
mPlugin->SetupStore("CorsHeader", mCorsHeaderPyld.c_str());
else
mPlugin->SetupStore("CorsHeader");
+ if (mUsageStatsLogFile.length() != 0)
+ mPlugin->SetupStore("UsageStatsLogFile", mUsageStatsLogFile.c_str());
}
bool cSmartTvConfig::SetupParse(const char *name, const char *value) {
@@ -125,6 +127,9 @@ bool cSmartTvConfig::SetupParse(const char *name, const char *value) {
mAddCorsHeader = true;
mCorsHeaderPyld = value;
}
+ else if (strcmp(name, "UsageStatsLogFile") == 0) {
+ mUsageStatsLogFile = value;
+ }
else
return false;
@@ -303,6 +308,11 @@ void cSmartTvConfig::readConfig() {
mCorsHeaderPyld = value;
continue;
}
+
+ if (strcmp(attr, "UsageStatsLogFile") == 0) {
+ mUsageStatsLogFile = value;
+ continue;
+ }
#ifndef STANDALONE
esyslog("WARNING in SmartTvWeb: Attribute= %s with value= %s was not processed, thus ignored.", attr, value);
diff --git a/stvw_cfg.h b/stvw_cfg.h
index ce6342b..5f99c2a 100755
--- a/stvw_cfg.h
+++ b/stvw_cfg.h
@@ -97,6 +97,7 @@ class cSmartTvConfig {
bool mAddCorsHeader;
string mCorsHeaderPyld;
+ string mUsageStatsLogFile;
// cPlugin* mPlugin;
cWidgetConfigBase mWidgetConfigBase;
public:
@@ -131,6 +132,7 @@ class cSmartTvConfig {
bool addCorsHeader() { return mAddCorsHeader; };
string getCorsHeader() {return mCorsHeaderPyld; };
+ string getUsageStatsLogFile() { return mUsageStatsLogFile; };
string GetWidgetConf() { return mWidgetConfigBase.GetWidgetConf(); };
};