2014-08-31 77 views
0

我想用我的Raspberry Pi來記錄一系列傳感器的溫度。爲此,我正在編寫一個使用librrd的C++程序。使用C++在Raspberry上創建RRD文件的行爲很奇怪

對於每個連接的傳感器,我想創建一個12 rra的rrd。下面的調用應創造我想要的RRD:

rrd_create(mNumberOfCreateParams, mCreateParams); 

mNumberOfCreateParams是17和mCreateParams的內容如下:

rrdcreate 
28-000005fd934f.rrd 
--step=300 
--no-overwrite 
DS:temperature:GAUGE:600:-55:125 
RRA:AVERAGE:0.5:1:288 
RRA:AVERAGE:0.5:3:672 
RRA:AVERAGE:0.5:12:744 
RRA:AVERAGE:0.5:72:1464 
RRA:MAX:0.5:1:288 
RRA:MAX:0.5:3:672 
RRA:MAX:0.5:12:744 
RRA:MAX:0.5:72:1464 
RRA:MIN:0.5:1:288 
RRA:MIN:0.5:3:672 
RRA:MIN:0.5:12:744 
RRA:MIN:0.5:72:1464 

第二行對應的傳感器的ID每次都有改變。

現在的問題:有一段時間,對rrd_create的調用按預期工作,但在某些時候它停止工作,只是在進一步調用時創建錯誤。如果我想重新創建一個之前成功創建的rrd,這也是如此。

通過改變mNumberOfCreateParams我可以改變分析參數的數量。如果參數在13到17的範圍內,則rrd_get_error()返回的錯誤是「無法解析參數''」(爲了可讀性,在兩者之間增加了空格)。如果我讓函數解析10到12個參數,它將在第一次「工作」並返回「打開'@':沒有這樣的文件或目錄」第二次因爲第一次創建以下文件:

image of created file in file browser

如果解析參數的數量低於10,則按預期工作。

如果我改變RRA線的順序,沒有任何區別。

如果我打電話給rrdtool,從終端創建[...與上面相同的參數],那麼一切工作正常,無關緊要,多少個參數被解析。

爲了rrd_create再次工作,我重新啓動了Raspberry serveral時間,它甚至在短時間內運行了一次(我的應用程序運行一次)。

有什麼建議我做錯了什麼,或者我如何將rrd_create移動到更穩定的狀態?

編輯: 我正在使用版本1.4.7的RRDtool(shell中的rrdtool版本)。 這裏是我使用的用於創建RRD文件的代碼:

// mCreateParams & mNumberOfCreateParams will be set here 
setupRrdCreateParamsDS18B20(lStepSize); 
char lCurrentPath[255]; 
getcwd(lCurrentPath, sizeof(lCurrentPath)); 
// since I wasn't able to create rrd files outside current working directory I 
// change working directory to where I want all files 
chdir(DS18B20_PATH.c_str()); 
// the dump of mCreateParams postet above was created here 
int lStatus = rrd_create(mNumberOfCreateParams, mCreateParams); 

因爲我只是打電話rrd_create(......)我覺得他們不應該被破壞之前傾倒mCreateParams。

我目前的解決方法使用popen()和mCreateParams用於創建調用rrdtool的shell命令。

stringstream ss; 
// create shell command from create params 
ss << "rrdtool create "; 
for (int i = 1; i < mNumberOfCreateParams - 1; i++) { 
    ss << mCreateParams[i] << " "; 
} 
ss << mCreateParams[mNumberOfCreateParams - 1]; 
// needed for capturing output from executed command 
FILE * in; 
char buff[512]; 
if(!(in = popen(ss.str().c_str(), "r"))){ 
    return false; 
} 
ss.str(""); 
ss.clear(); 
// get output 
while(fgets(buff, sizeof(buff), in)!=NULL){ 
    ss << buff; 
} 
lRrdError = ss.str(); 
ss.str(""); 
ss.clear(); 
int lTemp = pclose(in); 
// get exit code from rrdtool create 
lStatus = WEXITSTATUS(lTemp); 

我很感謝每一個建議。

+0

您正在使用哪個版本的RRDtool庫?你能發佈你正在使用的實際代碼(或其中的一部分)嗎?在呼叫之前,您的呼叫參數可能會被破壞掉?也許,出於測試目的,在調用之前打印出通過的argv列表來驗證。另外,請確保在調用此函數時不使用線程或類似函數 - 許多調用都不是線程安全的。 最後,你附加的文件沒有正確完成 - 我只是得到一個二進制文件圖標:) – 2014-08-31 22:29:37

+0

是的,沒錯。它只是創建了一個二進制文件。但據我所見,rrdtool忽略提供的文件名。 – Nazrim 2014-09-01 01:08:13

回答

2

當您撥打rrd_create(int argc, char**argv)時,您需要傳遞ARGV列表中的參數,這與正常的C main()函數採用其參數的方式非常相似。

尤其是,您不需要通過create函數名稱(這是隱式的),當然,argc參數必須與argv陣列中的元素數量相匹配。

因此,簡而言之:您的rrd_create參數列表不應包含rrdcreate參數,並且您的argc必須與傳遞的argv參數數量相匹配。

如果仍然收到rrd_create函數調用返回的錯誤,則打印出錯誤消息。

+0

我從參數列表中刪除了'rrdcreate',並將參數數量設置爲16.剩下的參數在RRA:溫度的心跳旁邊未被觸及。我沒有收到錯誤「無法識別的整合功能」。對我來說令人困惑的事實是相同的參數正在使用'popen()'。 – Nazrim 2014-09-04 00:07:07

+0

「無法識別的合併函數」應緊跟在無效函數名稱後面。如果你什麼也沒得到,那麼看起來好像你沒有正確設置你的mCreateParams。這需要是一個char **,其中包含一個以null結尾的char數組。我注意到你正在使用C++,因此請確保你沒有使用一些與C庫不兼容的類。 – 2014-09-04 03:28:20

+0

是的,沒有任何後續的「無法識別的整合功能」。 mCreateParams被聲明爲'char * mCreateParams [mNumberOfCreateParams]',但引用http://stackoverflow.com/questions/5192068/c-char-argv-vs-char-argv這應該等於'char **'。也許從字符串到char *('mCreateParams [i] =(char *)lConstructedString')的對話不會添加空終止?我會看看這個。 – Nazrim 2014-09-12 08:25:22