-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Library incompatible with newest version of Ticker library #9
Comments
Hi David, |
I’m using the 8266 with the Arduino Ide. If you can send me your working one, that would be helpful. For me it kept saying Logger wasn’t a type or something like that.
…Sent from my iPhone
David Duehren
On Mar 14, 2021, at 7:31 AM, Fabiano Riccardi ***@***.***> wrote:
Hi David,
I need to know which version of board you are using (esp8266 or esp32) and the version of the core. I had just tested the latest version of esp8266 and esp32 and both works.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
okI had used version arduino8266 version 2.7.4 to test the library. All the examples seem to compiled and work properly. Can you send me the code that do not compile? |
Hi Faviano,
Here’s my Class definition where I try to instantiate it. It follow the model I used for the BME library in another class. The message I get when I try to compile is 'LoggerSPIFFS' does not name a type. This exact same line, when put in the main ino, works fine, and I’ve made progress by declaring at external in my cpp file.
Thanks for your attention on this,
David Duehren
The includes are:
#ifndef MUSH_LOGGER_H
#define MUSH_LOGGER_H
#include <Arduino.h>
#include <stdarg.h>
#include <string.h>
#include <FS.h>
class Mush_Logger {
public:
Mush_Logger();
void init();
void setLogLevel(int const log_level);
void log(int const log_level, const char *fmt, ...);
void handle();
String getLogFile(int fileID) const;
String getLogLevel()const;
private:
LoggerSPIFFS mushLog("/log/Mushlog.log");
int log_type;
int _log_level;
int logcsvlevel;
void initArrays();
bool saveLogArray();
bool loadLogArray();
void lPrint(char const * fmt, va_list args);
void logCSVheader();
void logCSVdata();
bool shouldLog(int const log_level) const;
File loggerFile;
File configFile;
struct csvCell{
char colName[COL_WIDTH];
char colVal[VAL_WIDTH];
};
csvCell csvArray[NoCol];
String logFiles[FileNo]; // array for circulating log file names
int logFilePtr;
int dayCtr;
};
From: Fabiano Riccardi ***@***.***>
Sent: Sunday, March 14, 2021 9:58 AM
To: fabiuz7/esp-logger-lib ***@***.***>
Cc: David Duehren ***@***.***>; Author ***@***.***>
Subject: Re: [fabiuz7/esp-logger-lib] Library incompatible with newest version of Ticker library (#9)
I had used version ***@***.*** to test the library. All the examples seem to compiled and work properly. Can you send me the code that do not compile?
Fabiano Riccardi
Da: David ***@***.***>
Inviato: domenica 14 marzo 2021 17.53
A: ***@***.***>
Cc: Fabiano ***@***.***>; ***@***.***>
Oggetto: Re: [fabiuz7/esp-logger-lib] Library incompatible with newest version of Ticker library (#9)
I’m using the 8266 with the Arduino Ide. If you can send me your working one, that would be helpful. For me it kept saying Logger wasn’t a type or something like that.
…Sent from my iPhone
David Duehren
On Mar 14, 2021, at 7:31 AM, Fabiano Riccardi ***@***.***> wrote:
Hi David,
I need to know which version of board you are using (esp8266 or esp32) and the version of the core. I had just tested the latest version of esp8266 and esp32 and both works.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub<#9 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AB4R44A2G7RWKK4Q45UYCHDTDTSW3ANCNFSM4YYAHQTQ>.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#9 (comment)> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/ACAY6ZZSIRDVZXNBR7OLM3LTDTTI5ANCNFSM4YYAHQTQ> .
|
I’m using version 1.3, the latest installed via the Arduino library manager. Seems the IDE install is far behind. Are these the same version numbers?
…Sent from my iPhone
David Duehren
On Mar 14, 2021, at 9:58 AM, Fabiano Riccardi ***@***.***> wrote:
okI had used version arduino8266 version 2.7.4 to test the library. All the examples seem to compiled and work properly. Can you send me the code that do not compile?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
I was talking about your library. I am using version 2.7.4 of 8266 Arduino library
…Sent from my iPhone
David Duehren
On Mar 14, 2021, at 9:58 AM, Fabiano Riccardi ***@***.***> wrote:
okI had used version arduino8266 version 2.7.4 to test the library. All the examples seem to compiled and work properly. Can you send me the code that do not compile?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
As you'll see from my code, I'm trying to build a front end that is easy to
use, convert to CSV in the middle, and rather than do regular flushes, use a
rotating file system. I haven't fully tested it yet, but it's mostly
working with the extern declaration. I'm also attaching the .ino.
* David
#include "mushLogger.h"
#include "Arduino_DebugUtils.h"
#include <logger_spiffs.h>
#include <NTPClient.h>
extern LoggerSPIFFS mushLog; //I didn't find a way to make LoggerSPIFFS work inside a class
extern NTPClient timeClient;
/************************************************
CONSTANTS
**************************************************/
static int const DEFAULT_LOG_LEVEL = LOG_OPS;
const char COL_TMP[COL_WIDTH] PROGMEM = "TMP";
const char COL_HUM[COL_WIDTH] PROGMEM = "HUM";
const char COL_CO2[COL_WIDTH] PROGMEM = "CO2";
const char COL_A0I[COL_WIDTH] PROGMEM = "A0I";
const char COL_FSd[COL_WIDTH] PROGMEM = "FSd";
const char COL_OPN[COL_WIDTH] PROGMEM = "OPN";
const char COL_FAN[COL_WIDTH] PROGMEM = "FAN";
const char COL_LED[COL_WIDTH] PROGMEM = "LED";
const char COL_RL1[COL_WIDTH] PROGMEM = "RL1";
const char COL_RL2[COL_WIDTH] PROGMEM = "RL2";
const char COL_RL3[COL_WIDTH] PROGMEM = "RL3";
const char COL_RL4[COL_WIDTH] PROGMEM = "RL4";
const char COL_OP1[COL_WIDTH] PROGMEM = "OP1";
const char COL_OP2[COL_WIDTH] PROGMEM = "OP2";
const char COL_OP3[COL_WIDTH] PROGMEM = "OP3";
const char COL_OP4[COL_WIDTH] PROGMEM = "OP4";
const char COL_IF1[COL_WIDTH] PROGMEM = "IF1";
const char COL_IF2[COL_WIDTH] PROGMEM = "IF2";
const char COL_IF3[COL_WIDTH] PROGMEM = "IF3";
const char COL_IF4[COL_WIDTH] PROGMEM = "IF4";
/*************************************************
* LoggerSPIFFS call back function
* ***********************************************/
//place-holder based serial port.
// Flushing is initiated by mushlog.flush()
bool flush(char* buffer, int n){
int index=0;
// Check if there is another string to print
while(index<n && strlen(&buffer[index])>0){
Serial.print("---");
int bytePrinted=Serial.print(&buffer[index]);
Serial.println("---");
// +1, the '\0' is processed
index += bytePrinted+1;
}
return true;
}
/*************************************************
CTOR/DTOR
**************************************************/
Mush_Logger::Mush_Logger(){
setLogLevel(DEFAULT_LOG_LEVEL);
// initArrays();
}
/****************************************************
PUBLIC MEMBER FUNCTIONS
*****************************************************/
void Mush_Logger::log(int const log_level, const char *fmt, ...){
Debug.print(DBG_INFO, "log method: log_level: %d", log_level);
//extract the data, eventually creating a string for mushlog.append(record.c_str()
if (!shouldLog(log_level))
return;
String fmt_str(fmt);
va_list args;
va_start(args, fmt_str.c_str());
lPrint(fmt_str.c_str(), args);
va_end(args);
// sync inputs to the 1 second sensor logging
if(log_level==LOG_INPUTS){
logCSVdata();
}
}
void Mush_Logger::handle(){
// manage revolving log files. This handler should be started every 6 hours by external timer
// remove current filename
if(logFilePtr >= FileNo){
Debug.print(DBG_ERROR, "logFilePtr>=16!!!!!! %d", FileNo);
logFilePtr = 0;
}
String logFileName;
logFileName = logFiles[logFilePtr];
if (logFileName != "EMPTY"){
if (SPIFFS.exists(logFileName)){
if(SPIFFS.remove(logFileName)){
Debug.print(DBG_INFO, "File removed %s", logFileName.c_str());
} else {
Debug.print(DBG_ERROR, "log file removal failed %s", logFileName.c_str());
}
}
}
//create new file name
logFileName = "/log/"+String(dayCtr)+String(timeClient.getHours())+String(timeClient.getMinutes())+".log";
Debug.print(DBG_INFO, "New file name %s, logFilePtr: %d", logFileName.c_str(), logFilePtr);
if (SPIFFS.rename("/log/Mushlog.log",logFileName)){
logFiles[logFilePtr] = logFileName; //save new filename
//presume Mushlog.log doesn't exist because it's been renamed.
if (SPIFFS.exists("/log/Mushlog.log")){
Debug.print(DBG_WARNING, "Mushlog exists after renaming");
}
loggerFile=SPIFFS.open("/log/Mushlog.log","a");
logCSVheader(); //add header row
} else {
Debug.print(DBG_ERROR, "Rename of Mushlog failed");
}
// garbage collection
SPIFFS.gc();
// update pointers
logFilePtr++;
Debug.print(DBG_INFO,"Just after logFilePtr++, logFilePtr: %d", logFilePtr);
if(logFilePtr >= FileNo){ // This check is not being executed for some reason.
Debug.print(DBG_INFO, "Compare to FileNo succeeded");
logFilePtr==0;
}
Debug.print(DBG_INFO, "Just after compare, logFilePtr: %d", logFilePtr);
if ((logFilePtr % 4) == 0){
dayCtr++;
}
if (dayCtr > DayMax){
dayCtr=0;
}
// Save logArray // Because it's being saved here at 16.
if(!saveLogArray()){
Debug.print(DBG_ERROR, "Saving LogArray Failed");
}
}
void Mush_Logger::init(){
mushLog.begin();
mushLog.setFlusherCallback(flush);
mushLog.reset(); // for now until the file management system is working
mushLog.setSizeLimit(65535); //default is 1000
Serial.print("Log file size: ");
Serial.println(mushLog.getSizeLimit());
mushLog.setSizeLimitPerChunk(200); // default is 100
mushLog.setOneRecordPerChunk(true);
if(mushLog.getActualSize()<10){
logCSVheader(); //add header row
}
Serial.print("Log file size: ");
Serial.println(mushLog.getActualSize());
initArrays();
/* char temch[8];
for (int i=0; i<NoCol; i++){
strcpy(temch, csvArray[i].colName);
Serial.print(temch);
Serial.print(" : ");
strcpy (temch, csvArray[i].colVal);
Serial.println(temch);
}
*/
}
void Mush_Logger::setLogLevel(int const log_level){
_log_level = log_level;
logcsvlevel =0;
switch(_log_level){
case LOG_INPUTS:
logcsvlevel=LogInputLevel;
break;
case LOG_CONTROLS:
logcsvlevel=LogControlLevel;
break;
case LOG_OPS:
logcsvlevel=LogOpsLevel;
break;
case LOG_ALL:
logcsvlevel=NoCol;
break;
default:
logcsvlevel=NoCol;
break;
}
}
String Mush_Logger::getLogFile(int fileID) const {
return(logFiles[fileID]);
}
String Mush_Logger::getLogLevel() const {
switch(_log_level){
case LOG_NONE:
return("LOG_NONE");
break;
case LOG_INPUTS:
return("LOG_INPUTS");
break;
case LOG_CONTROLS:
return("LOG_CONTROLS");
break;
case LOG_OPS:
return("LOG_OPS");
break;
case LOG_ALL:
return("LOG_ALL");
break;
default:
return("LOG_ALL");
break;
}
}
/*****************************************************
Private member functions
******************************************************/
void Mush_Logger::initArrays(){
// Init csvArray
//first set all values to "NAN";
for (int i = 0; i < NoCol; i++) {
strcpy(csvArray[i].colVal, "NAN");
}
strcpy(csvArray[0].colName, "TIM");
strcpy(csvArray[1].colName, COL_TMP);
strcpy(csvArray[2].colName, COL_HUM);
strcpy(csvArray[3].colName, COL_CO2);
strcpy(csvArray[4].colName, COL_A0I);
strcpy(csvArray[5].colName, COL_FSd);
strcpy(csvArray[6].colName, COL_OPN);
strcpy(csvArray[7].colName, COL_FAN);
strcpy(csvArray[8].colName, COL_LED);
strcpy(csvArray[9].colName, COL_RL1);
strcpy(csvArray[10].colName, COL_RL2);
strcpy(csvArray[11].colName, COL_RL3);
strcpy(csvArray[12].colName, COL_RL4);
strcpy(csvArray[13].colName, COL_OP1);
strcpy(csvArray[14].colName, COL_OP2);
strcpy(csvArray[15].colName, COL_OP3);
strcpy(csvArray[16].colName, COL_OP4);
strcpy(csvArray[17].colName, COL_IF1);
strcpy(csvArray[18].colName, COL_IF2);
strcpy(csvArray[19].colName, COL_IF3);
strcpy(csvArray[20].colName, COL_IF4);
/******************************
* Init logFiles array
***************************/
if (!loadLogArray()){
//load defaults
Debug.print(DBG_DEBUG,"LoadLogArray failed");
for (int i=0; i<FileNo; i++){
logFiles[i]="EMPTY";
logFilePtr=0;
dayCtr =0;
}
}
}
void Mush_Logger::lPrint(char const * fmt, va_list args){
static size_t const MSG_BUF_SIZE = 120;
char msg_buf[MSG_BUF_SIZE] = {0};
vsprintf(msg_buf, fmt, args);
Debug.print(DBG_INFO, "msg_buf: %s", msg_buf);
// process the string into columns and values
char tempCol[COL_WIDTH];
char key1=':';
char key2=',';
char * pcol;
char * pcom;
char * ecol;
char colTemp[COL_WIDTH];
colTemp[3]='\0';
pcom = msg_buf;
ecol = strrchr(msg_buf, key1);
pcol = strchr(msg_buf, key1);
while (pcol!=NULL) {
strncpy(colTemp, pcom, COL_WIDTH-1);
if (pcol==ecol){
pcom = strchr(pcom+1, '\0'); //end of string
} else {
pcom = strchr(pcom+1, key2); //find comma, other way to end variable
}
for (int i=0; i<NoCol; i++){
if(strcmp(colTemp, csvArray[i].colName)==0){
Debug.print(DBG_VERBOSE,"Match %s", colTemp);
pcol++; //point to variable
strncpy(colTemp, pcol,(pcom-pcol));
if ((pcom-pcol)<3){
for(int i=(pcom-pcol); i<3; i++){
colTemp[i]='\0';
}
colTemp[3]='\0';
strcpy(csvArray[i].colVal, colTemp);
} else {
strncpy(csvArray[i].colVal, pcol,(pcom-pcol));
}
strcpy(colTemp, csvArray[i].colVal);
colTemp[3]='\0'; //reset colTemp after use for printingcol
i=NoCol; // end search
} else {
}
} // end of 4 loop
pcol = strchr(pcol+1, key1);
pcom++; //point to next column name
}
String record="";
record="";
for(int i=15; i<NoCol; i++){
record = record+csvArray[i].colVal+',';
}
Serial.printf("tail csvArray %s", record.c_str());
Serial.println("<>");
}
void Mush_Logger::logCSVheader(){
String record="";
for(int i=0; i<logcsvlevel; i++){
if (i<logcsvlevel-1){
record = record+csvArray[i].colName+',';
} else {
record = record+csvArray[i].colName;
}
}
Debug.print(DBG_INFO,"%s", record.c_str());
mushLog.append(record,0); //append adds CRLF
Serial.print("Log file size: ");
Serial.println(mushLog.getActualSize());
}
void Mush_Logger::logCSVdata(){
Debug.print(DBG_INFO,"logcsvlevel: %d", logcsvlevel);
String record="";
record= record+timeClient.getFormattedTime()+',';
for(int i=1; i<logcsvlevel; i++){
if (i<logcsvlevel-1){
record = record+csvArray[i].colVal+',';
} else {
record = record+csvArray[i].colVal;
}
}
Debug.print(DBG_INFO,"%s", record.c_str());
mushLog.append(record,0);
// clear array for next round
for (int i = 0; i < NoCol; i++) {
strcpy(csvArray[i].colVal, "NAN");
}
Serial.print("Log file size: ");
Serial.println(mushLog.getActualSize());
}
bool Mush_Logger::shouldLog(int const log_level) const
{
return((log_level > LOG_NONE) && (log_level <= LOG_ALL) && (log_level <= _log_level));
}
bool Mush_Logger::saveLogArray(){
configFile = SPIFFS.open("/logArray.txt", "w");
if (!configFile) {
Debug.print(DBG_ERROR,"Failed to open logArray file for writing");
return false;
}
configFile.seek(0); //rewind file so test data is not appended
for(int i=0; i<FileNo; i++){
configFile.print(logFiles[i]);
if(i<FileNo){
configFile.print(",");
}
}
char record[10];
snprintf(record, 10, "%d,%d,\n", logFilePtr, dayCtr);
configFile.print(record);
configFile.close();
Serial.println("********************************************");
Debug.print(DBG_DEBUG, "saveLogArray");
for (int i; i<FileNo; i++){
Serial.print(logFiles[i]);
Serial.print("|");
if(i%4==0){
Serial.print("\n");
}
}
Serial.println("<");
Serial.printf("logFilePtr: %d, dayCtr: %d", logFilePtr, dayCtr);
Serial.println(">");
return true;
}
bool Mush_Logger::loadLogArray(){
if (SPIFFS.exists("/logArray.txt")){
File configFile = SPIFFS.open("/logArray.txt", "r");
if (!configFile) {
Debug.print(DBG_ERROR, "Failed to open logArray file");
return false;
}
for (int i=0; i<FileNo; i++){
logFiles[i]=configFile.readStringUntil(',');
}
String srec = configFile.readStringUntil(',');
logFilePtr=srec.toInt();
srec = configFile.readStringUntil(',');
dayCtr=srec.toInt();
Serial.println("********************************************");
Debug.print(DBG_DEBUG, "loadLogArray");
for (int i; i<FileNo; i++){
Serial.print(logFiles[i]);
Serial.print("|");
if(i%4==0){
Serial.print("\n");
}
}
Serial.println("<");
Serial.printf("logFilePtr: %d, dayCtr: %d", logFilePtr, dayCtr);
Serial.println(">");
return true;
}
}
/************************************************************
CLASS INSTANTIATION
*************************************************************/
Mush_Logger mlog;
void setLogType(int const log_level){
mlog.setLogLevel(log_level);
}
/*
The interface to this class is modeled after the Arduino_DebugUtils.
It uses the esp-logger-lib found here: https://github.com/fabiuz7/esp-logger-lib for the backend
In between the interface and the backend, it puts the data into csv records and performs some amount of data compression
by only recording changes in the data. It also smooths the sensor data with a 3 sample moving average filter.
*/
#ifndef MUSH_LOGGER_H
#define MUSH_LOGGER_H
#include <Arduino.h>
#include <stdarg.h>
#include <string.h>
#include <FS.h>
//note: old version of ticker library used in convience library.
//csvArray defines
#define COL_WIDTH 4 // 3 plus termination character
#define VAL_WIDTH 9 //8 plus termination character - hh:mm:ss
#define NoCol 21
// defines for file management array
#define FileNo 16 // 4 days x 4 hrs each
#define DayMax 365 // days in a year
// defines for how many columns of data to store
#define LogInputLevel 7
#define LogControlLevel 13
#define LogOpsLevel 17
/*********************************************
LOG level control
**********************************************/
static int const LOG_NONE = -1; //no logging
static int const LOG_INPUTS = 0; // log only this level of data (e.g. sensors data)
static int const LOG_CONTROLS = 1; //
static int const LOG_OPS = 2; //
static int const LOG_ALL = 3; // log verbose mode
void setLogType(int const log_level);
/********************************************************
CSV COLUMN NAMES
*********************************************************/
extern const char COL_TMP[COL_WIDTH];
extern const char COL_HUM[COL_WIDTH];
extern const char COL_CO2[COL_WIDTH];
extern const char COL_A0I[COL_WIDTH];
extern const char COL_FSd[COL_WIDTH];
extern const char COL_OPN[COL_WIDTH];
extern const char COL_FAN[COL_WIDTH];
extern const char COL_LED[COL_WIDTH];
extern const char COL_RL1[COL_WIDTH];
extern const char COL_RL2[COL_WIDTH];
extern const char COL_RL3[COL_WIDTH];
extern const char COL_RL4[COL_WIDTH];
extern const char COL_OP1[COL_WIDTH];
extern const char COL_OP2[COL_WIDTH];
extern const char COL_OP3[COL_WIDTH];
extern const char COL_OP4[COL_WIDTH];
extern const char COL_IF1[COL_WIDTH];
extern const char COL_IF2[COL_WIDTH];
extern const char COL_IF3[COL_WIDTH];
extern const char COL_IF4[COL_WIDTH];
/*****************************************************
Class Declaration
******************************************************/
class Mush_Logger {
public:
Mush_Logger();
void init();
void setLogLevel(int const log_level);
void log(int const log_level, const char *fmt, ...);
void handle();
String getLogFile(int fileID) const;
String getLogLevel()const;
private:
// LoggerSPIFFS mushLog("/log/Mushlog.log");
int log_type;
int _log_level;
int logcsvlevel;
void initArrays();
bool saveLogArray();
bool loadLogArray();
void lPrint(char const * fmt, va_list args);
void logCSVheader();
void logCSVdata();
bool shouldLog(int const log_level) const;
File loggerFile;
File configFile;
struct csvCell{
char colName[COL_WIDTH];
char colVal[VAL_WIDTH];
};
csvCell csvArray[NoCol];
String logFiles[FileNo]; // array for circulating log file names
int logFilePtr;
int dayCtr;
};
/**********************************************************
EXTERN
***********************************************************/
extern Mush_Logger mlog;
#endif
|
Usually when you are reporting a bug you shouldn't report all your project, but only the relevant part. However, I think that the problem is in the class declaration: you missed to include LoggerSPIFFS in mush_logger.h:
Moreover, you can't initiate a class member like you have done:
This is wrong. You should only declare it:
And initialize the members in the constructor of MushLogger. |
Ok I’ll try it again, but I’m pretty sure I had the include for logger_SPIFFS when I was reporting the problem. I’ll get back to you.
Thanks
…Sent from my iPhone
David Duehren
On Mar 14, 2021, at 1:12 PM, Fabiano Riccardi ***@***.***> wrote:
Usually when you are reporting a bug you shouldn't report all your project, but only the relevant part. However, I think that the problem is in the class declaration: you missed to include LoggerSPIFFS in mush_logger.h:
#define <logger_spiffs.h>
Moreover, you can't initiate a class member like you have done:
LoggerSPIFFS mushLog("/log/Mushlog.log");
This is wrong. You should only declare it:
LoggerSPIFFS mushLog;
And initialize the members in the constructor of MushLogger.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Fabiano,
I think I did what you said but it’s still not working. I’m attaching the files with the changes I made and the compiler outputs below. I’m no expert on C++ so it’s quite possible I’m doing something stupid, but I know this hasn’t gone as smoothly as the bme library which I did the same thing and followed that example closely. One main difference is that it doesn’t have an initialization variable – you pass it the i2c address in the cpp file. I’ve attached those too.
Here’s the compiler output
:\Users\DAVIDD~1\AppData\Local\Temp\arduino_build_983165\sketch\mushLogger.cpp: In constructor 'Mush_Logger::Mush_Logger()':
mushLogger.cpp:54:26: error: no matching function for call to 'LoggerSPIFFS::LoggerSPIFFS()'
Mush_Logger::Mush_Logger(){
^
C:\Users\DAVIDD~1\AppData\Local\Temp\arduino_build_983165\sketch\mushLogger.cpp:54:26: note: candidates are:
In file included from C:\Users\DAVIDD~1\AppData\Local\Temp\arduino_build_983165\sketch\mushLogger.h:13:0,
from C:\Users\DAVIDD~1\AppData\Local\Temp\arduino_build_983165\sketch\mushLogger.cpp:1:
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src/logger_spiffs.h:40:3: note: LoggerSPIFFS::LoggerSPIFFS(String, Logger::DebugLevel)
LoggerSPIFFS(String file, DebugLevel debugVerbosity = DebugLevel::ERROR);
^
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src/logger_spiffs.h:40:3: note: candidate expects 2 arguments, 0 provided
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src/logger_spiffs.h:37:7: note: LoggerSPIFFS::LoggerSPIFFS(const LoggerSPIFFS&)
class LoggerSPIFFS : public Logger{
^
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src/logger_spiffs.h:37:7: note: candidate expects 1 argument, 0 provided
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src/logger_spiffs.h:37:7: note: LoggerSPIFFS::LoggerSPIFFS(LoggerSPIFFS&&)
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src/logger_spiffs.h:37:7: note: candidate expects 1 argument, 0 provided
mushLogger.cpp:56:29: error: 'mushlog' was not declared in this scope
mushlog("/log/Mushlog.log");
From: Fabiano Riccardi ***@***.***>
Sent: Sunday, March 14, 2021 1:12 PM
To: fabiuz7/esp-logger-lib ***@***.***>
Cc: David Duehren ***@***.***>; Author ***@***.***>
Subject: Re: [fabiuz7/esp-logger-lib] Library incompatible with newest version of Ticker library (#9)
Usually when you are reporting a bug you shouldn't report all your project, but only the relevant part. However, I think that the problem is in the class declaration: you missed to include LoggerSPIFFS in mush_logger.h:
#define <logger_spiffs.h>
Moreover, you can't initiate a class member like you have done:
LoggerSPIFFS mushLog("/log/Mushlog.log");
This is wrong. You should only declare it:
LoggerSPIFFS mushLog;
And initialize the members in the constructor of MushLogger.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#9 (comment)> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/ACAY6ZZHU7TILNOOXDFAOKLTDUKBVANCNFSM4YYAHQTQ> .
#include "mushLogger.h"
#include "Arduino_DebugUtils.h"
#include <logger_spiffs.h>
#include <NTPClient.h>
//extern LoggerSPIFFS mushLog; //I didn't find a way to make LoggerSPIFFS work inside a class
extern NTPClient timeClient;
/************************************************
CONSTANTS
**************************************************/
static int const DEFAULT_LOG_LEVEL = LOG_ALL;
const char COL_TMP[COL_WIDTH] PROGMEM = "TMP";
const char COL_HUM[COL_WIDTH] PROGMEM = "HUM";
const char COL_CO2[COL_WIDTH] PROGMEM = "CO2";
const char COL_A0I[COL_WIDTH] PROGMEM = "A0I";
const char COL_FSd[COL_WIDTH] PROGMEM = "FSd";
const char COL_OPN[COL_WIDTH] PROGMEM = "OPN";
const char COL_FAN[COL_WIDTH] PROGMEM = "FAN";
const char COL_LED[COL_WIDTH] PROGMEM = "LED";
const char COL_RL1[COL_WIDTH] PROGMEM = "RL1";
const char COL_RL2[COL_WIDTH] PROGMEM = "RL2";
const char COL_RL3[COL_WIDTH] PROGMEM = "RL3";
const char COL_RL4[COL_WIDTH] PROGMEM = "RL4";
const char COL_OP1[COL_WIDTH] PROGMEM = "OP1";
const char COL_OP2[COL_WIDTH] PROGMEM = "OP2";
const char COL_OP3[COL_WIDTH] PROGMEM = "OP3";
const char COL_OP4[COL_WIDTH] PROGMEM = "OP4";
const char COL_IF1[COL_WIDTH] PROGMEM = "IF1";
const char COL_IF2[COL_WIDTH] PROGMEM = "IF2";
const char COL_IF3[COL_WIDTH] PROGMEM = "IF3";
const char COL_IF4[COL_WIDTH] PROGMEM = "IF4";
/*************************************************
* LoggerSPIFFS call back function
* ***********************************************/
//place-holder based serial port.
// Flushing is initiated by mushlog.flush()
bool flush(char* buffer, int n){
int index=0;
// Check if there is another string to print
while(index<n && strlen(&buffer[index])>0){
Serial.print("---");
int bytePrinted=Serial.print(&buffer[index]);
Serial.println("---");
// +1, the '\0' is processed
index += bytePrinted+1;
}
return true;
}
/*************************************************
CTOR/DTOR
**************************************************/
Mush_Logger::Mush_Logger(){
setLogLevel(DEFAULT_LOG_LEVEL);
mushlog("/log/Mushlog.log");
// initArrays();
}
/****************************************************
PUBLIC MEMBER FUNCTIONS
*****************************************************/
void Mush_Logger::log(int const log_level, const char *fmt, ...){
Debug.print(DBG_INFO, "log method: log_level: %d", log_level);
//extract the data, eventually creating a string for mushlog.append(record.c_str()
if (!shouldLog(log_level))
return;
String fmt_str(fmt);
va_list args;
va_start(args, fmt_str.c_str());
lPrint(fmt_str.c_str(), args);
va_end(args);
// sync inputs to the 1 second sensor logging
if(log_level==LOG_INPUTS){
logCSVdata();
}
}
void Mush_Logger::handle(){
// manage revolving log files. This handler should be started every 6 hours by external timer
// remove current filename
if(logFilePtr >= FileNo){
Debug.print(DBG_ERROR, "logFilePtr>=16!!!!!! %d", FileNo);
logFilePtr = 0;
}
String logFileName;
logFileName = logFiles[logFilePtr];
if (logFileName != "EMPTY"){
if (SPIFFS.exists(logFileName)){
if(SPIFFS.remove(logFileName)){
Debug.print(DBG_INFO, "File removed %s", logFileName.c_str());
} else {
Debug.print(DBG_ERROR, "log file removal failed %s", logFileName.c_str());
}
}
}
//create new file name
logFileName = "/log/"+String(dayCtr)+String(timeClient.getHours())+String(timeClient.getMinutes())+".log";
Debug.print(DBG_INFO, "New file name %s, logFilePtr: %d", logFileName.c_str(), logFilePtr);
if (SPIFFS.rename("/log/Mushlog.log",logFileName)){
logFiles[logFilePtr] = logFileName; //save new filename
//presume Mushlog.log doesn't exist because it's been renamed.
if (SPIFFS.exists("/log/Mushlog.log")){
Debug.print(DBG_WARNING, "Mushlog exists after renaming");
}
loggerFile=SPIFFS.open("/log/Mushlog.log","a");
logCSVheader(); //add header row
} else {
Debug.print(DBG_ERROR, "Rename of Mushlog failed");
}
// garbage collection
SPIFFS.gc();
// update pointers
logFilePtr++;
Debug.print(DBG_INFO,"Just after logFilePtr++, logFilePtr: %d", logFilePtr);
if(logFilePtr >= FileNo){ // This check is not being executed for some reason.
Debug.print(DBG_INFO, "Compare to FileNo succeeded");
logFilePtr==0;
}
Debug.print(DBG_INFO, "Just after compare, logFilePtr: %d", logFilePtr);
if ((logFilePtr % 4) == 0){
dayCtr++;
}
if (dayCtr > DayMax){
dayCtr=0;
}
// Save logArray // Because it's being saved here at 16.
if(!saveLogArray()){
Debug.print(DBG_ERROR, "Saving LogArray Failed");
}
}
void Mush_Logger::init(){
mushLog.begin();
mushLog.setFlusherCallback(flush);
mushLog.reset(); // for now until the file management system is working
mushLog.setSizeLimit(65535); //default is 1000
Serial.print("Log file size: ");
Serial.println(mushLog.getSizeLimit());
mushLog.setSizeLimitPerChunk(200); // default is 100
mushLog.setOneRecordPerChunk(true);
if(mushLog.getActualSize()<10){
logCSVheader(); //add header row
}
Serial.print("Log file size: ");
Serial.println(mushLog.getActualSize());
initArrays();
/* char temch[8];
for (int i=0; i<NoCol; i++){
strcpy(temch, csvArray[i].colName);
Serial.print(temch);
Serial.print(" : ");
strcpy (temch, csvArray[i].colVal);
Serial.println(temch);
}
*/
}
void Mush_Logger::setLogLevel(int const log_level){
_log_level = log_level;
logcsvlevel =0;
switch(_log_level){
case LOG_INPUTS:
logcsvlevel=LogInputLevel;
break;
case LOG_CONTROLS:
logcsvlevel=LogControlLevel;
break;
case LOG_OPS:
logcsvlevel=LogOpsLevel;
break;
case LOG_ALL:
logcsvlevel=NoCol;
break;
default:
logcsvlevel=NoCol;
break;
}
}
String Mush_Logger::getLogFile(int fileID) const {
return(logFiles[fileID]);
}
String Mush_Logger::getLogLevel() const {
switch(_log_level){
case LOG_NONE:
return("LOG_NONE");
break;
case LOG_INPUTS:
return("LOG_INPUTS");
break;
case LOG_CONTROLS:
return("LOG_CONTROLS");
break;
case LOG_OPS:
return("LOG_OPS");
break;
case LOG_ALL:
return("LOG_ALL");
break;
default:
return("LOG_ALL");
break;
}
}
/*****************************************************
Private member functions
******************************************************/
void Mush_Logger::initArrays(){
// Init csvArray
//first set all values to "NAN";
for (int i = 0; i < NoCol; i++) {
strcpy(csvArray[i].colVal, "NAN");
}
strcpy(csvArray[0].colName, "TIM");
strcpy(csvArray[1].colName, COL_TMP);
strcpy(csvArray[2].colName, COL_HUM);
strcpy(csvArray[3].colName, COL_CO2);
strcpy(csvArray[4].colName, COL_A0I);
strcpy(csvArray[5].colName, COL_FSd);
strcpy(csvArray[6].colName, COL_OPN);
strcpy(csvArray[7].colName, COL_FAN);
strcpy(csvArray[8].colName, COL_LED);
strcpy(csvArray[9].colName, COL_RL1);
strcpy(csvArray[10].colName, COL_RL2);
strcpy(csvArray[11].colName, COL_RL3);
strcpy(csvArray[12].colName, COL_RL4);
strcpy(csvArray[13].colName, COL_OP1);
strcpy(csvArray[14].colName, COL_OP2);
strcpy(csvArray[15].colName, COL_OP3);
strcpy(csvArray[16].colName, COL_OP4);
strcpy(csvArray[17].colName, COL_IF1);
strcpy(csvArray[18].colName, COL_IF2);
strcpy(csvArray[19].colName, COL_IF3);
strcpy(csvArray[20].colName, COL_IF4);
/******************************
* Init logFiles array
***************************/
if (!loadLogArray()){
//load defaults
Debug.print(DBG_DEBUG,"LoadLogArray failed");
for (int i=0; i<FileNo; i++){
logFiles[i]="EMPTY";
logFilePtr=0;
dayCtr =0;
}
}
}
void Mush_Logger::lPrint(char const * fmt, va_list args){
static size_t const MSG_BUF_SIZE = 120;
char msg_buf[MSG_BUF_SIZE] = {0};
vsprintf(msg_buf, fmt, args);
Debug.print(DBG_INFO, "msg_buf: %s", msg_buf);
// process the string into columns and values
char tempCol[COL_WIDTH];
char key1=':';
char key2=',';
char * pcol;
char * pcom;
char * ecol;
char colTemp[COL_WIDTH];
colTemp[3]='\0';
pcom = msg_buf;
ecol = strrchr(msg_buf, key1);
pcol = strchr(msg_buf, key1);
while (pcol!=NULL) {
strncpy(colTemp, pcom, COL_WIDTH-1);
if (pcol==ecol){
pcom = strchr(pcom+1, '\0'); //end of string
} else {
pcom = strchr(pcom+1, key2); //find comma, other way to end variable
}
for (int i=0; i<NoCol; i++){
if(strcmp(colTemp, csvArray[i].colName)==0){
Debug.print(DBG_VERBOSE,"Match %s", colTemp);
pcol++; //point to variable
strncpy(colTemp, pcol,(pcom-pcol));
if ((pcom-pcol)<3){
for(int i=(pcom-pcol); i<3; i++){
colTemp[i]='\0';
}
colTemp[3]='\0';
strcpy(csvArray[i].colVal, colTemp);
} else {
strncpy(csvArray[i].colVal, pcol,(pcom-pcol));
}
strcpy(colTemp, csvArray[i].colVal);
colTemp[3]='\0'; //reset colTemp after use for printingcol
i=NoCol; // end search
} else {
}
} // end of 4 loop
pcol = strchr(pcol+1, key1);
pcom++; //point to next column name
}
String record="";
record="";
for(int i=15; i<NoCol; i++){
record = record+csvArray[i].colVal+',';
}
Serial.printf("tail csvArray %s", record.c_str());
Serial.println("<>");
}
void Mush_Logger::logCSVheader(){
String record="";
for(int i=0; i<logcsvlevel; i++){
if (i<logcsvlevel-1){
record = record+csvArray[i].colName+',';
} else {
record = record+csvArray[i].colName;
}
}
Debug.print(DBG_INFO,"%s", record.c_str());
mushLog.append(record,0); //append adds CRLF
Serial.print("Log file size: ");
Serial.println(mushLog.getActualSize());
}
void Mush_Logger::logCSVdata(){
Debug.print(DBG_INFO,"logcsvlevel: %d", logcsvlevel);
String record="";
record= record+timeClient.getFormattedTime()+',';
for(int i=1; i<logcsvlevel; i++){
if (i<logcsvlevel-1){
record = record+csvArray[i].colVal+',';
} else {
record = record+csvArray[i].colVal;
}
}
Debug.print(DBG_INFO,"%s", record.c_str());
mushLog.append(record,0);
// clear array for next round
for (int i = 0; i < NoCol; i++) {
strcpy(csvArray[i].colVal, "NAN");
}
Serial.print("Log file size: ");
Serial.println(mushLog.getActualSize());
}
bool Mush_Logger::shouldLog(int const log_level) const
{
return((log_level > LOG_NONE) && (log_level <= LOG_ALL) && (log_level <= _log_level));
}
bool Mush_Logger::saveLogArray(){
configFile = SPIFFS.open("/logArray.txt", "w");
if (!configFile) {
Debug.print(DBG_ERROR,"Failed to open logArray file for writing");
return false;
}
configFile.seek(0); //rewind file so test data is not appended
for(int i=0; i<FileNo; i++){
configFile.print(logFiles[i]);
if(i<FileNo){
configFile.print(",");
}
}
char record[10];
snprintf(record, 10, "%d,%d,\n", logFilePtr, dayCtr);
configFile.print(record);
configFile.close();
Serial.println("********************************************");
Debug.print(DBG_DEBUG, "saveLogArray");
for (int i; i<FileNo; i++){
Serial.print(logFiles[i]);
Serial.print("|");
if(i%4==0){
Serial.print("\n");
}
}
Serial.println("<");
Serial.printf("logFilePtr: %d, dayCtr: %d", logFilePtr, dayCtr);
Serial.println(">");
return true;
}
bool Mush_Logger::loadLogArray(){
if (SPIFFS.exists("/logArray.txt")){
File configFile = SPIFFS.open("/logArray.txt", "r");
if (!configFile) {
Debug.print(DBG_ERROR, "Failed to open logArray file");
return false;
}
for (int i=0; i<FileNo; i++){
logFiles[i]=configFile.readStringUntil(',');
}
String srec = configFile.readStringUntil(',');
logFilePtr=srec.toInt();
srec = configFile.readStringUntil(',');
dayCtr=srec.toInt();
Serial.println("********************************************");
Debug.print(DBG_DEBUG, "loadLogArray");
for (int i; i<FileNo; i++){
Serial.print(logFiles[i]);
Serial.print("|");
if(i%4==0){
Serial.print("\n");
}
}
Serial.println("<");
Serial.printf("logFilePtr: %d, dayCtr: %d", logFilePtr, dayCtr);
Serial.println(">");
return true;
}
}
/************************************************************
CLASS INSTANTIATION
*************************************************************/
Mush_Logger mlog;
void setLogType(int const log_level){
mlog.setLogLevel(log_level);
}
/*
The interface to this class is modeled after the Arduino_DebugUtils.
It uses the esp-logger-lib found here: https://github.com/fabiuz7/esp-logger-lib for the backend
In between the interface and the backend, it puts the data into csv records and performs some amount of data compression
by only recording changes in the data. It also smooths the sensor data with a 3 sample moving average filter.
*/
#ifndef MUSH_LOGGER_H
#define MUSH_LOGGER_H
#include <Arduino.h>
#include <stdarg.h>
#include <string.h>
#include <FS.h>
#include <logger_spiffs.h>
//note: old version of ticker library used in convience library.
//csvArray defines
#define COL_WIDTH 4 // 3 plus termination character
#define VAL_WIDTH 9 //8 plus termination character - hh:mm:ss
#define NoCol 21
// defines for file management array
#define FileNo 16 // 4 days x 4 hrs each
#define DayMax 365 // days in a year
// defines for how many columns of data to store
#define LogInputLevel 7
#define LogControlLevel 13
#define LogOpsLevel 17
/*********************************************
LOG level control
**********************************************/
static int const LOG_NONE = -1; //no logging
static int const LOG_INPUTS = 0; // log only this level of data (e.g. sensors data)
static int const LOG_CONTROLS = 1; //
static int const LOG_OPS = 2; //
static int const LOG_ALL = 3; // log verbose mode
void setLogType(int const log_level);
/********************************************************
CSV COLUMN NAMES
*********************************************************/
extern const char COL_TMP[COL_WIDTH];
extern const char COL_HUM[COL_WIDTH];
extern const char COL_CO2[COL_WIDTH];
extern const char COL_A0I[COL_WIDTH];
extern const char COL_FSd[COL_WIDTH];
extern const char COL_OPN[COL_WIDTH];
extern const char COL_FAN[COL_WIDTH];
extern const char COL_LED[COL_WIDTH];
extern const char COL_RL1[COL_WIDTH];
extern const char COL_RL2[COL_WIDTH];
extern const char COL_RL3[COL_WIDTH];
extern const char COL_RL4[COL_WIDTH];
extern const char COL_OP1[COL_WIDTH];
extern const char COL_OP2[COL_WIDTH];
extern const char COL_OP3[COL_WIDTH];
extern const char COL_OP4[COL_WIDTH];
extern const char COL_IF1[COL_WIDTH];
extern const char COL_IF2[COL_WIDTH];
extern const char COL_IF3[COL_WIDTH];
extern const char COL_IF4[COL_WIDTH];
/*****************************************************
Class Declaration
******************************************************/
class Mush_Logger {
public:
Mush_Logger();
void init();
void setLogLevel(int const log_level);
void log(int const log_level, const char *fmt, ...);
void handle();
String getLogFile(int fileID) const;
String getLogLevel()const;
private:
LoggerSPIFFS mushLog;
int log_type;
int _log_level;
int logcsvlevel;
void initArrays();
bool saveLogArray();
bool loadLogArray();
void lPrint(char const * fmt, va_list args);
void logCSVheader();
void logCSVdata();
bool shouldLog(int const log_level) const;
File loggerFile;
File configFile;
struct csvCell{
char colName[COL_WIDTH];
char colVal[VAL_WIDTH];
};
csvCell csvArray[NoCol];
String logFiles[FileNo]; // array for circulating log file names
int logFilePtr;
int dayCtr;
};
/**********************************************************
EXTERN
***********************************************************/
extern Mush_Logger mlog;
#endif
#include "sensors.h"
#include "Arduino_DebugUtils.h"
#include "boardconfig.h"
#include "mushLogger.h"
sensors sense;
void sensors::init(){
aConnected = false;
//default address bme280 - 0x77, SDO=GND=>0x76
if (!bme.begin(0x76)) {
Debug.print(DBG_WARNING, "BME280 sensor is offline");
return;
};
//bme.getLastError();
// uint8_t bme280ID = bme.readManufacturerId();
// uint8_t err = bme.getLastError();
// if (!err && bme280ID != 0x00 && bme280ID != 0xFF) {
// sensor online
aConnected = true;
/* } else {
Debug.print(DBG_WARNING, "BME280 sensor offline. error: %s", String(err));
}
*/
avgPtr=0;
}
void sensors::setMode(int tmode){
ltempMode = 0;
if (tmode>0) ltempMode = 1;
}
int sensors::getMode() const {
return ltempMode;
}
void sensors::handle(){
th_handle();
co2_handle();
gas_handle();
// manage pointer and send info
avgPtr++;
if(avgPtr >= maSize){
avgPtr = 0;
mlog.log(LOG_INPUTS, "%s:%3.2f,%s:%2.2f,%s:%6.1f,%s:%5.1f",COL_TMP,Temperature,COL_HUM,Humidity,COL_CO2,CO2Lvl,COL_A0I,GasLvl);
}
}
void sensors::th_handle(){
float t = bme.readTemperature();
float h = bme.readHumidity();
aConnected = true;
tempArr[avgPtr] = t;
humArr[avgPtr] = h;
t = (tempArr[0] + tempArr[1] + tempArr[2])/3;
if (ltempMode>0){
Temperature = 32+t*9/5;
} else {
Temperature = t;
}
Humidity = (humArr[0] + humArr[1] + humArr[2])/3;
if(isnan(Humidity) || isnan(Temperature)){
init();
}
Debug.print(DBG_INFO, "Humidity %5.2f%, Celcius Temp %4.1f degrees, Temperature %4.1f degrees", h, t, Temperature);
}
void sensors::co2_handle(){
float co2;
if(BD_VER < 3){
int sensorValue = analogRead(adcPin);
co2 = sensorValue*(5000/639.0); //upper value is 5000pm, 3.3V to 1V scaling of 2V upper CO2 sensor level on 1023 leads to 639 as upper value.
co2Arr[avgPtr]=co2;
if(co2 < 1){
Debug.print(DBG_ERROR, "CO2 sensor Fault");
} else {
if ((co2>1) && (co2< 127)) {
Debug.print(DBG_WARNING, "CO2 sensor pre-heating");
}
}
CO2Lvl = (co2Arr[0] + co2Arr[1] + co2Arr[2])/3;
} else {
//TBD = i2c based
}
}
void sensors::gas_handle(){
float gas;
if(BD_VER < 3){
gas = analogRead(adcPin);
gasArr[avgPtr] = gas;
GasLvl = (gasArr[0] + gasArr[1] + gasArr[2])/3;
} else {
// TBD
}
}
bool sensors::connected() {
return aConnected;
}
float sensors::getHumidity() const{
return Humidity;
}
float sensors::getTemp() const{
return Temperature;
}
float sensors::getCO2() const{
return CO2Lvl;
}
float sensors::getGas() const { // basically raw ADC reading.
return GasLvl;
}
#ifndef SENSORS_H
#define SENSORS_H
// Code borrowed from: https://github.com/merlokk/SmartHome/blob/master/lib/BME280.cpp and ...BME280.h
#include "Arduino.h"
#include <Wire.h>
#include <Adafruit_BME280.h> // original: https://github.com/adafruit/Adafruit_BME280_Library
// with error handling fix: https://github.com/merlokk/Adafruit_BME280_Library
#include "Arduino_DebugUtils.h"
#define maSize 3 //moving avearge array size
class sensors{
public:
void init();
void handle();
bool connected();
void setMode(int tmode);
int getMode() const;
float getTemp() const;
float getHumidity() const;
float getCO2() const;
float getGas() const;
private:
Adafruit_BME280 bme;
bool aConnected = false;
float Temperature;
float Humidity;
float CO2Lvl;
float GasLvl;
int ltempMode;
int trainStop;
float tempArr[maSize] = {0,0,0};
float humArr[maSize] = {0,0,0};
float co2Arr[maSize] = {0,0,0};
float gasArr[maSize] = {0,0,0};
int avgPtr; //arrays can share the pointer
void th_handle();
void co2_handle();
void gas_handle();
};
extern sensors sense;
#endif SENSORS_H
|
In this case, you have to know what initializer list is (you can search on google). Basically you must initialize all the members that do not have a default constructor (like LoggerSPIFFS) at the begin of your constructor. Example: Mush_Logger::Mush_Logger(): mushLog("path/to/file"){ |
I found out a bit of time to revise this library... I think I will integrate a circular logger in next release. |
Hi Fabiano,
I can send you my code for a circular logger in exchange if you figure put SPIFFSlogger in my code and get it to work.
…Sent from my iPhone
David Duehren
On Mar 28, 2021, at 1:10 PM, Fabiano Riccardi ***@***.***> wrote:
I found out a bit of time to revise this library... I think I will integrate a circular logger in next release.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Fabianno,
If you want to borrow any code from feel free. I’m semi-retired and never was a software engineer though I’ve written some code in my career. I’m slowly coming up the learning curve on C++ and that may be why I haven’t gotten your library to work in my Class directly. As you can see I’m using an external for it.
I have an array based circular logging buffer that I can upload via the web interface I’ve implemented. You may want a better file naming technique, etc. But I also store the array pointer and the array to SPIFFS so if the system is shut down it can start back up where it left off.
And if you want to comment on better coding etc feel free.
Thanks,
David
From: Fabiano Riccardi ***@***.***>
Sent: Sunday, March 28, 2021 1:11 PM
To: fabiuz7/esp-logger-lib ***@***.***>
Cc: David Duehren ***@***.***>; Author ***@***.***>
Subject: Re: [fabiuz7/esp-logger-lib] Library incompatible with newest version of Ticker library (#9)
I found out a bit of time to revise this library... I think I will integrate a circular logger in next release.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub <#9 (comment)> , or unsubscribe <https://github.com/notifications/unsubscribe-auth/ACAY6Z25QTHA6KXFB4UHU63TF6LNPANCNFSM4YYAHQTQ> .
#include "mushLogger.h"
#include "Arduino_DebugUtils.h"
#include <logger_spiffs.h>
#include "shroom.h"
#include <FS.h>
#include <NTPClient.h>
extern LoggerSPIFFS mushLog; //I didn't find a way to make LoggerSPIFFS work inside a class
extern FS SPIFFS;
extern NTPClient timeClient;
/************************************************
CONSTANTS
**************************************************/
static int const DEFAULT_LOG_LEVEL = LOG_ALL;
const char COL_TMP[COL_WIDTH] PROGMEM = "TMP";
const char COL_HUM[COL_WIDTH] PROGMEM = "HUM";
const char COL_CO2[COL_WIDTH] PROGMEM = "CO2";
const char COL_A0I[COL_WIDTH] PROGMEM = "A0I";
const char COL_FSd[COL_WIDTH] PROGMEM = "FSd";
const char COL_OPN[COL_WIDTH] PROGMEM = "OPN";
const char COL_FAN[COL_WIDTH] PROGMEM = "FAN";
const char COL_LED[COL_WIDTH] PROGMEM = "LED";
const char COL_RL1[COL_WIDTH] PROGMEM = "RL1";
const char COL_RL2[COL_WIDTH] PROGMEM = "RL2";
const char COL_RL3[COL_WIDTH] PROGMEM = "RL3";
const char COL_RL4[COL_WIDTH] PROGMEM = "RL4";
const char COL_OP1[COL_WIDTH] PROGMEM = "OP1";
const char COL_OP2[COL_WIDTH] PROGMEM = "OP2";
const char COL_OP3[COL_WIDTH] PROGMEM = "OP3";
const char COL_OP4[COL_WIDTH] PROGMEM = "OP4";
const char COL_IF1[COL_WIDTH] PROGMEM = "IF1";
const char COL_IF2[COL_WIDTH] PROGMEM = "IF2";
const char COL_IF3[COL_WIDTH] PROGMEM = "IF3";
const char COL_IF4[COL_WIDTH] PROGMEM = "IF4";
/*************************************************
* LoggerSPIFFS call back function
* ***********************************************/
//place-holder based serial port.
// Flushing is initiated by mushlog.flush()
bool flush(char* buffer, int n){
int index=0;
// Check if there is another string to print
while(index<n && strlen(&buffer[index])>0){
Serial.print("---");
int bytePrinted=Serial.print(&buffer[index]);
Serial.println("---");
// +1, the '\0' is processed
index += bytePrinted+1;
}
return true;
}
/*************************************************
CTOR/DTOR
**************************************************/
Mush_Logger::Mush_Logger(){
setLogLevel(DEFAULT_LOG_LEVEL);
// mushlog("/log/Mushlog.log");
// initArrays();
}
/****************************************************
PUBLIC MEMBER FUNCTIONS
*****************************************************/
void Mush_Logger::log(int const log_level, const char *fmt, ...){
Debug.print(DBG_INFO, "log method: log_level: %d", log_level);
//extract the data, eventually creating a string for mushlog.append(record.c_str()
if (!shouldLog(log_level))
return;
String fmt_str(fmt);
va_list args;
va_start(args, fmt_str.c_str());
lPrint(fmt_str.c_str(), args);
va_end(args);
// sync inputs to the 1 second sensor logging
if(log_level==LOG_INPUTS){
logCSVdata();
}
}
void Mush_Logger::handle(){
// manage revolving log files. This handler should be started every 6 hours by external timer
// remove current filename
if(logFilePtr >= FileNo){
Debug.print(DBG_ERROR, "logFilePtr>=16!!!!!! %d", FileNo);
logFilePtr = 0;
}
String logFileName;
logFileName = logFiles[logFilePtr];
if (logFileName != "EMPTY"){
if (SPIFFS.exists(logFileName)){
if(SPIFFS.remove(logFileName)){
Debug.print(DBG_INFO, "File removed %s", logFileName.c_str());
} else {
Debug.print(DBG_ERROR, "log file removal failed %s", logFileName.c_str());
}
}
}
//create new file name
logFileName = "/log/"+String(shroom.getDayCount())+String(timeClient.getHours())+String(timeClient.getMinutes())+".log";
Debug.print(DBG_INFO, "New file name %s, logFilePtr: %d", logFileName.c_str(), logFilePtr);
if (SPIFFS.rename("/log/Mushlog.log",logFileName)){
logFiles[logFilePtr] = logFileName; //save new filename
//presume Mushlog.log doesn't exist because it's been renamed.
if (SPIFFS.exists("/log/Mushlog.log")){
Debug.print(DBG_WARNING, "Mushlog exists after renaming");
}
loggerFile=SPIFFS.open("/log/Mushlog.log","a");
logCSVheader(); //add header row
} else {
Debug.print(DBG_ERROR, "Rename of Mushlog failed");
}
// garbage collection
SPIFFS.gc();
// update pointers
logFilePtr++;
Debug.print(DBG_INFO,"Just after logFilePtr++, logFilePtr: %d", logFilePtr);
if(logFilePtr >= FileNo){ // This check is not being executed for some reason.
Debug.print(DBG_INFO, "Compare to FileNo succeeded");
logFilePtr==0;
}
Debug.print(DBG_INFO, "Just after compare, logFilePtr: %d", logFilePtr);
// Save logArray // Because it's being saved here at 16.
if(!saveLogArray()){
Debug.print(DBG_ERROR, "Saving LogArray Failed");
}
}
void Mush_Logger::init(){
mushLog.begin();
mushLog.setFlusherCallback(flush);
//mushLog.reset(); // for now until the file management system is working
mushLog.setSizeLimit(65535); //default is 1000
Serial.print("Log file size: ");
Serial.println(mushLog.getSizeLimit());
mushLog.setSizeLimitPerChunk(200); // default is 100
mushLog.setOneRecordPerChunk(true);
if(mushLog.getActualSize()<10){
logCSVheader(); //add header row
}
Serial.print("Log file size: ");
Serial.println(mushLog.getActualSize());
initArrays();
/* char temch[8];
for (int i=0; i<NoCol; i++){
strcpy(temch, csvArray[i].colName);
Serial.print(temch);
Serial.print(" : ");
strcpy (temch, csvArray[i].colVal);
Serial.println(temch);
}
*/
}
void Mush_Logger::setLogLevel(int const log_level){
_log_level = log_level;
logcsvlevel =0;
switch(_log_level){
case LOG_INPUTS:
logcsvlevel=LogInputLevel;
break;
case LOG_CONTROLS:
logcsvlevel=LogControlLevel;
break;
case LOG_OPS:
logcsvlevel=LogOpsLevel;
break;
case LOG_ALL:
logcsvlevel=NoCol;
break;
default:
logcsvlevel=NoCol;
break;
}
}
String Mush_Logger::getLogFile(int fileID) const {
return(logFiles[fileID]);
}
String Mush_Logger::getLogLevel() const {
switch(_log_level){
case LOG_NONE:
return("LOG_NONE");
break;
case LOG_INPUTS:
return("LOG_INPUTS");
break;
case LOG_CONTROLS:
return("LOG_CONTROLS");
break;
case LOG_OPS:
return("LOG_OPS");
break;
case LOG_ALL:
return("LOG_ALL");
break;
default:
return("LOG_ALL");
break;
}
}
/*****************************************************
Private member functions
******************************************************/
void Mush_Logger::initArrays(){
// Init csvArray
//first set all values to "NAN";
for (int i = 0; i < NoCol; i++) {
strcpy(csvArray[i].colVal, "NAN");
}
strcpy(csvArray[0].colName, "TIM");
strcpy(csvArray[1].colName, COL_TMP);
strcpy(csvArray[2].colName, COL_HUM);
strcpy(csvArray[3].colName, COL_CO2);
strcpy(csvArray[4].colName, COL_A0I);
strcpy(csvArray[5].colName, COL_FSd);
strcpy(csvArray[6].colName, COL_OPN);
strcpy(csvArray[7].colName, COL_FAN);
strcpy(csvArray[8].colName, COL_LED);
strcpy(csvArray[9].colName, COL_RL1);
strcpy(csvArray[10].colName, COL_RL2);
strcpy(csvArray[11].colName, COL_RL3);
strcpy(csvArray[12].colName, COL_RL4);
strcpy(csvArray[13].colName, COL_OP1);
strcpy(csvArray[14].colName, COL_OP2);
strcpy(csvArray[15].colName, COL_OP3);
strcpy(csvArray[16].colName, COL_OP4);
strcpy(csvArray[17].colName, COL_IF1);
strcpy(csvArray[18].colName, COL_IF2);
strcpy(csvArray[19].colName, COL_IF3);
strcpy(csvArray[20].colName, COL_IF4);
/******************************
* Init logFiles array
***************************/
if (!loadLogArray()){
//load defaults
Debug.print(DBG_DEBUG,"LoadLogArray failed");
for (int i=0; i<FileNo; i++){
logFiles[i]="EMPTY";
logFilePtr=0;
}
}
}
void Mush_Logger::lPrint(char const * fmt, va_list args){
static size_t const MSG_BUF_SIZE = 120;
char msg_buf[MSG_BUF_SIZE] = {0};
vsprintf(msg_buf, fmt, args);
Debug.print(DBG_VERBOSE, "msg_buf: %s", msg_buf);
// process the string into columns and values
char tempCol[COL_WIDTH];
char key1=':';
char key2=',';
char * pcol;
char * pcom;
char * ecol;
char colTemp[COL_WIDTH];
colTemp[3]='\0';
pcom = msg_buf;
ecol = strrchr(msg_buf, key1);
pcol = strchr(msg_buf, key1);
while (pcol!=NULL) {
strncpy(colTemp, pcom, COL_WIDTH-1);
if (pcol==ecol){
pcom = strchr(pcom+1, '\0'); //end of string
} else {
pcom = strchr(pcom+1, key2); //find comma, other way to end variable
}
for (int i=0; i<NoCol; i++){
if(strcmp(colTemp, csvArray[i].colName)==0){
Debug.print(DBG_VERBOSE,"Match %s", colTemp);
pcol++; //point to variable
strncpy(colTemp, pcol,(pcom-pcol));
if ((pcom-pcol)<3){
for(int i=(pcom-pcol); i<3; i++){
colTemp[i]='\0';
}
colTemp[3]='\0';
strcpy(csvArray[i].colVal, colTemp);
} else {
strncpy(csvArray[i].colVal, pcol,(pcom-pcol));
}
strcpy(colTemp, csvArray[i].colVal);
colTemp[3]='\0'; //reset colTemp after use for printingcol
i=NoCol; // end search
} else {
}
} // end of 4 loop
pcol = strchr(pcol+1, key1);
pcom++; //point to next column name
}
String record="";
record="";
for(int i=15; i<NoCol; i++){
record = record+csvArray[i].colVal+',';
}
// Serial.printf("tail csvArray %s", record.c_str());
// Serial.println("<>");
}
void Mush_Logger::logCSVheader(){
String record="";
for(int i=0; i<logcsvlevel; i++){
if (i<logcsvlevel-1){
record = record+csvArray[i].colName+',';
} else {
record = record+csvArray[i].colName;
}
}
Debug.print(DBG_INFO,"%s", record.c_str());
mushLog.append(record,0); //append adds CRLF
Serial.print("Log file size: ");
Serial.println(mushLog.getActualSize());
}
void Mush_Logger::logCSVdata(){
Debug.print(DBG_INFO,"logcsvlevel: %d", logcsvlevel);
String record="";
record= record+timeClient.getFormattedTime()+',';
for(int i=1; i<logcsvlevel; i++){
if (i<logcsvlevel-1){
record = record+csvArray[i].colVal+',';
} else {
record = record+csvArray[i].colVal;
}
}
Debug.print(DBG_INFO,"%s", record.c_str());
mushLog.append(record,0);
// clear array for next round
for (int i = 0; i < NoCol; i++) {
strcpy(csvArray[i].colVal, "NAN");
}
Serial.print("Log file size: ");
Serial.println(mushLog.getActualSize());
}
bool Mush_Logger::shouldLog(int const log_level) const
{
return((log_level > LOG_NONE) && (log_level <= LOG_ALL) && (log_level <= _log_level));
}
bool Mush_Logger::saveLogArray(){
configFile = SPIFFS.open("/logArray.txt", "w");
if (!configFile) {
Debug.print(DBG_ERROR,"Failed to open logArray file for writing");
return false;
}
configFile.seek(0); //rewind file so test data is not appended
for(int i=0; i<FileNo; i++){
configFile.print(logFiles[i]);
if(i<FileNo){
configFile.print(",");
}
}
char record[10];
snprintf(record, 10, "%d,\n", logFilePtr);
configFile.print(record);
configFile.close();
Serial.println("********************************************");
Debug.print(DBG_DEBUG, "saveLogArray");
for (int i; i<FileNo; i++){
Serial.print(logFiles[i]);
Serial.print("|");
if(i%4==0){
Serial.print("\n");
}
}
Serial.println("<");
Serial.printf("logFilePtr: %d", logFilePtr);
Serial.println(">");
return true;
}
bool Mush_Logger::loadLogArray(){
if (SPIFFS.exists("/logArray.txt")){
File configFile = SPIFFS.open("/logArray.txt", "r");
if (!configFile) {
Debug.print(DBG_ERROR, "Failed to open logArray file");
return false;
}
for (int i=0; i<FileNo; i++){
logFiles[i]=configFile.readStringUntil(',');
}
String srec = configFile.readStringUntil(',');
logFilePtr=srec.toInt();
Serial.println("********************************************");
Debug.print(DBG_DEBUG, "loadLogArray");
for (int i; i<FileNo; i++){
Serial.print(logFiles[i]);
Serial.print("|");
if(i%4==0){
Serial.print("\n");
}
}
Serial.println("<");
Serial.printf("logFilePtr: %d", logFilePtr);
Serial.println(">");
return true;
}
}
/************************************************************
CLASS INSTANTIATION
*************************************************************/
Mush_Logger mlog;
void setLogType(int const log_level){
mlog.setLogLevel(log_level);
}
/*
The interface to this class is modeled after the Arduino_DebugUtils.
It uses the esp-logger-lib found here: https://github.com/fabiuz7/esp-logger-lib for the backend
In between the interface and the backend, it puts the data into csv records and performs some amount of data compression
by only recording changes in the data. It also smooths the sensor data with a 3 sample moving average filter.
*/
#ifndef MUSH_LOGGER_H
#define MUSH_LOGGER_H
#include <Arduino.h>
#include <stdarg.h>
#include <string.h>
#include <FS.h>
//note: old version of ticker library used in convience library.
//csvArray defines
#define COL_WIDTH 4 // 3 plus termination character
#define VAL_WIDTH 9 //8 plus termination character - hh:mm:ss
#define NoCol 21
// defines for file management array
#define FileNo 16 // 4 days x 4 hrs each
#define DayMax 365 // days in a year
// defines for how many columns of data to store
#define LogInputLevel 7
#define LogControlLevel 13
#define LogOpsLevel 17
/*********************************************
LOG level control
**********************************************/
static int const LOG_NONE = -1; //no logging
static int const LOG_INPUTS = 0; // log only this level of data (e.g. sensors data)
static int const LOG_CONTROLS = 1; //
static int const LOG_OPS = 2; //
static int const LOG_ALL = 3; // log verbose mode
void setLogType(int const log_level);
/********************************************************
CSV COLUMN NAMES
*********************************************************/
extern const char COL_TMP[COL_WIDTH];
extern const char COL_HUM[COL_WIDTH];
extern const char COL_CO2[COL_WIDTH];
extern const char COL_A0I[COL_WIDTH];
extern const char COL_FSd[COL_WIDTH];
extern const char COL_OPN[COL_WIDTH];
extern const char COL_FAN[COL_WIDTH];
extern const char COL_LED[COL_WIDTH];
extern const char COL_RL1[COL_WIDTH];
extern const char COL_RL2[COL_WIDTH];
extern const char COL_RL3[COL_WIDTH];
extern const char COL_RL4[COL_WIDTH];
extern const char COL_OP1[COL_WIDTH];
extern const char COL_OP2[COL_WIDTH];
extern const char COL_OP3[COL_WIDTH];
extern const char COL_OP4[COL_WIDTH];
extern const char COL_IF1[COL_WIDTH];
extern const char COL_IF2[COL_WIDTH];
extern const char COL_IF3[COL_WIDTH];
extern const char COL_IF4[COL_WIDTH];
/*****************************************************
Class Declaration
******************************************************/
class Mush_Logger {
public:
Mush_Logger();
void init();
void setLogLevel(int const log_level);
void log(int const log_level, const char *fmt, ...);
void handle();
String getLogFile(int fileID) const;
String getLogLevel()const;
private:
// LoggerSPIFFS mushLog;
int log_type;
int _log_level;
int logcsvlevel;
void initArrays();
bool saveLogArray();
bool loadLogArray();
void lPrint(char const * fmt, va_list args);
void logCSVheader();
void logCSVdata();
bool shouldLog(int const log_level) const;
File loggerFile;
File configFile;
struct csvCell{
char colName[COL_WIDTH];
char colVal[VAL_WIDTH];
};
csvCell csvArray[NoCol];
String logFiles[FileNo]; // array for circulating log file names
int logFilePtr;
};
/**********************************************************
EXTERN
***********************************************************/
extern Mush_Logger mlog;
#endif
|
Hi thanks for availability. I have already started to write a skeleton of the library, and I can see some similarity with yours. I will extend the virtual class Logger with a "Logger Rotate" class (or something similar) to make this extension more coherent to the rest of the library. |
`n file included from D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.cpp:29:0:
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.h: In constructor 'LoggerRoutine::LoggerRoutine(Logger&, float)':
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.h:44:20: error: no matching function for call to 'Ticker::Ticker()'
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.h:44:20: note: candidates are:
In file included from D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.h:32:0,
D:\David\MyDocuments\Arduino\libraries\Ticker/Ticker.h:74:2: note: Ticker::Ticker(fptr, uint32_t, uint32_t, resolution_t)
Ticker(fptr callback, uint32_t timer, uint32_t repeat = 0, resolution_t resolution = MICROS);
^
D:\David\MyDocuments\Arduino\libraries\Ticker/Ticker.h:74:2: note: candidate expects 4 arguments, 0 provided
D:\David\MyDocuments\Arduino\libraries\Ticker/Ticker.h:62:7: note: Ticker::Ticker(const Ticker&)
class Ticker {
D:\David\MyDocuments\Arduino\libraries\Ticker/Ticker.h:62:7: note: candidate expects 1 argument, 0 provided
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.cpp: In function 'void routine(LoggerRoutine*)':
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.cpp:33:17: error: 'class Ticker' has no member named 'attach'
logRun->ticker.attach(logRun->period,routine,logRun);
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.cpp: In member function 'bool LoggerRoutine::begin(bool)':
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.cpp:41:10: error: 'class Ticker' has no member named 'attach'
ticker.attach(period, routine, this);
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.cpp: In member function 'void LoggerRoutine::setPeriod(float, bool)':
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.cpp:53:10: error: 'class Ticker' has no member named 'detach'
ticker.detach();
D:\David\MyDocuments\Arduino\libraries\ESP_Logger\src\logger_routine.cpp:54:10: error: 'class Ticker' has no member named 'attach'
ticker.attach(period, routine, this);
The text was updated successfully, but these errors were encountered: