From 4c24d7a8340d8491b686f9cc7f5490b4b2ee4db8 Mon Sep 17 00:00:00 2001 From: hg Date: Thu, 19 Jun 2014 00:40:58 +0200 Subject: [PATCH] Bug-fixes & persistent saving of important parameters --- Makefile | 1 + src/GCFanProfile.h | 17 +++- src/GrowControl.cpp | 137 ++++++++++++++++++++++++++-- src/GrowControl.h | 10 +- src/fanprofile/Dummy2Profile.cpp | 26 +++++- src/fanprofile/Dummy2Profile.h | 9 +- src/fanprofile/DummyProfile.cpp | 30 +++++- src/fanprofile/DummyProfile.h | 9 +- src/lcdpages/FanProfileSettings.cpp | 2 +- src/main.cpp | 17 +++- src/savefile.h | 76 +++++++++++++++ 11 files changed, 314 insertions(+), 20 deletions(-) create mode 100644 src/savefile.h diff --git a/Makefile b/Makefile index 6a7d565..693f59a 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ distclean : clean install: bin/growcontrold mkdir -p /opt/growcontrol/bin mkdir -p /opt/growcontrol/log + mkdir -p /opt/growcontrol/save cp bin/growcontrold /opt/growcontrol/bin cp -r config /opt/growcontrol diff --git a/src/GCFanProfile.h b/src/GCFanProfile.h index b099331..bd3506a 100644 --- a/src/GCFanProfile.h +++ b/src/GCFanProfile.h @@ -12,16 +12,29 @@ namespace growcontrol { +class GrowControl; +struct GCSensorsInfo; + class GCFanProfile { private: + long id; std::string name; + GrowControl& controller; public: - GCFanProfile(std::string name) : name(name) {} + GCFanProfile(GrowControl& controller, long id, std::string name) : id(id), name(name), controller(controller) {} virtual ~GCFanProfile() {} std::string getName() { return name; } -public: + long getID() { return id; } + + virtual void startCallback() = 0; + virtual void stopCallback() = 0; + virtual void pauseCallback() = 0; + virtual void continueCallback() = 0; + virtual void upperLimitChangedCallback(unsigned oldlimit, unsigned newlimit) = 0; + virtual void mainLoopCallback(GCSensorsInfo& sensors) = 0; + }; } /* namespace growcontrol */ diff --git a/src/GrowControl.cpp b/src/GrowControl.cpp index 3b89878..931cb30 100644 --- a/src/GrowControl.cpp +++ b/src/GrowControl.cpp @@ -18,6 +18,7 @@ #include #include "fanprofile/DummyProfile.h" #include "fanprofile/Dummy2Profile.h" +#include "savefile.h" namespace growcontrol { @@ -25,16 +26,50 @@ namespace growcontrol { log4cpp::Category& GrowControl::logger = log4cpp::Category::getInstance("growcontrol"); GrowControl::GrowControl() : lcd(*this) { - fanProfiles.push_back(new DummyProfile()); - fanProfiles.push_back(new Dummy2Profile()); + fanProfiles.push_back(new DummyProfile(*this)); + fanProfiles.push_back(new Dummy2Profile(*this)); fan1ActiveProfile = fanProfiles.at(0); } GrowControl::~GrowControl() { } -bool GrowControl::connect(std::string host , uint16_t port, bool retry) { +bool GrowControl::connect(std::string workDir, std::string host , uint16_t port, bool retry) { tfConnection.addListener(*this); + this->workDirString = workDir; + std::ostringstream ss; + ss << workDir << "/" << "save"; + saveDirString = ss.str(); + + try { + fan1UpperLimit = saveFileRead(saveDirString, "fan1UpperLimit.save"); + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + try { + fan1AutoMode = saveFileRead(saveDirString, "fan1AutoMode.save"); + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + if (!fan1AutoMode) { + try { + fan1Level = saveFileRead(saveDirString, "fan1Level.save"); + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + } + try { + long pid = saveFileRead(saveDirString, "fan1Profile.save"); + for (auto p : fanProfiles) { + if (p->getID() == pid) { + fan1ActiveProfile = p; + break; + } + } + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + bool breakFlag = false; do { try { @@ -239,6 +274,13 @@ void GrowControl::setFan1Level(unsigned level) { io16Bricklet->setPort('a', 1 << (fan1Level - 1), true); } } + if (!fan1AutoMode) { + try { + saveFileWrite(saveDirString, "fan1Level.save", fan1Level); + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + } } } @@ -247,9 +289,20 @@ unsigned GrowControl::getFan1UpperLimit() { } void GrowControl::setFan1UpperLimit(unsigned limit) { - fan1UpperLimit = limit; - if (fan1Level > fan1UpperLimit) { - setFan1Level(fan1UpperLimit); + if (fan1UpperLimit != limit) { + unsigned old = fan1UpperLimit; + fan1UpperLimit = limit; + if (fan1Level > fan1UpperLimit) { + setFan1Level(fan1UpperLimit); + } + if (fan1ActiveProfile != nullptr) { + fan1ActiveProfile->upperLimitChangedCallback(old, limit); + } + try { + saveFileWrite(saveDirString, "fan1UpperLimit.save", fan1UpperLimit); + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } } } @@ -262,7 +315,21 @@ bool GrowControl::getFan1AutoMode() { } void GrowControl::setFan1AutoMode(bool mode) { - fan1AutoMode = mode; + if (fan1AutoMode != mode) { + fan1AutoMode = mode; + if (fan1ActiveProfile != nullptr) { + if (fan1AutoMode) { + fan1ActiveProfile->continueCallback(); + } else { + fan1ActiveProfile->pauseCallback(); + } + } + try { + saveFileWrite(saveDirString, "fan1AutoMode.save", fan1AutoMode); + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + } } GCFanProfile* GrowControl::getFan1Profile() { @@ -270,7 +337,22 @@ GCFanProfile* GrowControl::getFan1Profile() { } void GrowControl::setFan1Profile(GCFanProfile* profile) { - fan1ActiveProfile = profile; + if (fan1ActiveProfile != profile) { + if (fan1ActiveProfile != nullptr) { + fan1ActiveProfile->stopCallback(); + } + fan1ActiveProfile = profile; + if (fan1ActiveProfile != nullptr) { + fan1ActiveProfile->startCallback(); + } + try { + if (fan1ActiveProfile != nullptr) { + saveFileWrite(saveDirString, "fan1Profile.save", fan1ActiveProfile->getID()); + } + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + } } const std::vector& GrowControl::getFanProfiles() { @@ -286,6 +368,10 @@ void GrowControl::shutdownController() { void GrowControl::mainLoop() { + if (fan1ActiveProfile != nullptr) { + fan1ActiveProfile->startCallback(); + } + while (mainLoopFlag) { // Fetch sensor values @@ -325,11 +411,46 @@ void GrowControl::mainLoop() { lcd.controlMainLoopCallback(sensorValues); + if (fan1AutoMode && fan1ActiveProfile != nullptr) { + fan1ActiveProfile->mainLoopCallback(sensorValues); + } + if (mainLoopFlag) { std::this_thread::sleep_until(sensorValues.timestamp + std::chrono::seconds(1)); } } + try { + saveFileWrite(saveDirString, "fan1UpperLimit.save", fan1UpperLimit); + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + try { + saveFileWrite(saveDirString, "fan1AutoMode.save", fan1AutoMode); + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + if (!fan1AutoMode) { + try { + saveFileWrite(saveDirString, "fan1Level.save", fan1Level); + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + } else { + try { + saveFileWrite(saveDirString, "fan1Level.save", 0); + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + } + try { + if (fan1ActiveProfile != nullptr) { + saveFileWrite(saveDirString, "fan1Profile.save", fan1ActiveProfile->getID()); + } + } catch (GCException &e) { + logger << log4cpp::Priority::INFO << e.what(); + } + } diff --git a/src/GrowControl.h b/src/GrowControl.h index e5bbe02..3a89211 100644 --- a/src/GrowControl.h +++ b/src/GrowControl.h @@ -37,7 +37,7 @@ struct GCSensorsInfo { CGSensorValue temp2; CGSensorValue hum1; CGSensorValue fan1Level; - int fan1UpperLimit; + unsigned fan1UpperLimit; bool fan1AutoMode; GCFanProfile* fan1Profile; }; @@ -69,12 +69,15 @@ private: GCFanProfile* fan1ActiveProfile = nullptr; std::vector fanProfiles; + std::string workDirString; + std::string saveDirString; + public: GrowControl(); virtual ~GrowControl(); - bool connect(std::string host , uint16_t port, bool retry = true); + bool connect(std::string workDir, std::string host , uint16_t port, bool retry = true); void newDeviceCallback(TfConnection& conn, TfDevice& device); void shutdownCallback(); @@ -101,6 +104,9 @@ public: void shutdownController(); + + const std::string getSaveDir() { return saveDirString; } + const std::string getWorkDir() { return workDirString; } }; } /* namespace growcontrol */ diff --git a/src/fanprofile/Dummy2Profile.cpp b/src/fanprofile/Dummy2Profile.cpp index f65269c..d040f3a 100644 --- a/src/fanprofile/Dummy2Profile.cpp +++ b/src/fanprofile/Dummy2Profile.cpp @@ -9,10 +9,34 @@ namespace growcontrol { -Dummy2Profile::Dummy2Profile() : GCFanProfile("Dummy2") { +Dummy2Profile::Dummy2Profile(GrowControl& controller) : GCFanProfile(controller, 2, "Dummy2") { } Dummy2Profile::~Dummy2Profile() { } +void Dummy2Profile::startCallback() { + +} + +void Dummy2Profile::stopCallback() { + +} + +void Dummy2Profile::upperLimitChangedCallback(unsigned oldlimit, unsigned newlimit) { + +} + +void Dummy2Profile::mainLoopCallback(GCSensorsInfo& sensors) { + +} + +void Dummy2Profile::pauseCallback() { + +} + +void Dummy2Profile::continueCallback() { + +} + } /* namespace growcontrol */ diff --git a/src/fanprofile/Dummy2Profile.h b/src/fanprofile/Dummy2Profile.h index 5bedcfd..7a72d50 100644 --- a/src/fanprofile/Dummy2Profile.h +++ b/src/fanprofile/Dummy2Profile.h @@ -14,8 +14,15 @@ namespace growcontrol { class Dummy2Profile: public GCFanProfile { public: - Dummy2Profile(); + Dummy2Profile(GrowControl& controller); virtual ~Dummy2Profile(); + + virtual void startCallback(); + virtual void stopCallback(); + virtual void pauseCallback(); + virtual void continueCallback(); + virtual void upperLimitChangedCallback(unsigned oldlimit, unsigned newlimit); + virtual void mainLoopCallback(GCSensorsInfo& sensors); }; } /* namespace growcontrol */ diff --git a/src/fanprofile/DummyProfile.cpp b/src/fanprofile/DummyProfile.cpp index 7536e94..2ca7113 100644 --- a/src/fanprofile/DummyProfile.cpp +++ b/src/fanprofile/DummyProfile.cpp @@ -6,13 +6,41 @@ */ #include "DummyProfile.h" +#include namespace growcontrol { -DummyProfile::DummyProfile() : GCFanProfile("Dummy") { +static log4cpp::Category& logger = log4cpp::Category::getInstance("growcontrol"); + +DummyProfile::DummyProfile(GrowControl& controller) : GCFanProfile(controller, 1, "Dummy") { } DummyProfile::~DummyProfile() { + logger << log4cpp::Priority::INFO << "DummyProfile::~DummyProfile()"; +} + +void DummyProfile::startCallback() { + logger << log4cpp::Priority::INFO << "DummyProfile::startCallback()"; +} + +void DummyProfile::stopCallback() { + logger << log4cpp::Priority::INFO << "DummyProfile::stopCallback()"; +} + +void DummyProfile::upperLimitChangedCallback(unsigned oldlimit, unsigned newlimit) { + logger << log4cpp::Priority::INFO << "DummyProfile::upperLimitChangedCallback(" << oldlimit << ", " << newlimit << ")"; +} + +void DummyProfile::mainLoopCallback(GCSensorsInfo& sensors) { + logger << log4cpp::Priority::INFO << "DummyProfile::mainLoopCallback()"; +} + +void DummyProfile::pauseCallback() { + logger << log4cpp::Priority::INFO << "DummyProfile::pauseCallback()"; +} + +void DummyProfile::continueCallback() { + logger << log4cpp::Priority::INFO << "DummyProfile::continueCallback()"; } } /* namespace growcontrol */ diff --git a/src/fanprofile/DummyProfile.h b/src/fanprofile/DummyProfile.h index 63a7fee..2413bdb 100644 --- a/src/fanprofile/DummyProfile.h +++ b/src/fanprofile/DummyProfile.h @@ -14,8 +14,15 @@ namespace growcontrol { class DummyProfile: public GCFanProfile { public: - DummyProfile(); + DummyProfile(GrowControl& controller); virtual ~DummyProfile(); + + virtual void startCallback(); + virtual void stopCallback(); + virtual void pauseCallback(); + virtual void continueCallback(); + virtual void upperLimitChangedCallback(unsigned oldlimit, unsigned newlimit); + virtual void mainLoopCallback(GCSensorsInfo& sensors); }; } /* namespace growcontrol */ diff --git a/src/lcdpages/FanProfileSettings.cpp b/src/lcdpages/FanProfileSettings.cpp index ab19419..b040b50 100644 --- a/src/lcdpages/FanProfileSettings.cpp +++ b/src/lcdpages/FanProfileSettings.cpp @@ -88,7 +88,7 @@ void FanProfileSettings::buttonStateCallback(uint8_t button, bool state) { refresh = true; break; case 2: // down - if (cursorPos < 2) { + if (cursorPos < 2 && cursorPos < items.size() - 1) { cursorPos++; } else if (cursorPos == 2 && items.size() - itemsStart > 3) { itemsStart++; diff --git a/src/main.cpp b/src/main.cpp index 56baf0b..3915669 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,6 +31,7 @@ std::string pidFile = "/var/run/growcontrold.pid"; std::string socketPath = "/opt/growcontrol/growcontrold.socket"; std::string log4cppConfig = "log4cpp.config"; std::string host = "localhost"; +std::string workDir = "/opt/growcontrol"; uint16_t port = 4223; bool daemonMode = false; int pid_fd = 0; @@ -60,13 +61,14 @@ void signalHandler(int signum) { void printUsage(std::ostream& stream, std::string name) { - stream << "Usage: " << name << " [-d] [-pid pid-file] [-s socket-path] [-l log4cpp-config] [-h host] [-p port]" << std::endl + stream << "Usage: " << name << " [-d] [-pid pid-file] [-s socket-path] [-l log4cpp-config] [-h host] [-p port] [-w work-dir]" << std::endl << "\t-d ... daemon mode" << std::endl << "\t-pid ... pid-file" << std::endl << "\t-s ... path of ipc socket" << std::endl << "\t-l ... path to log4cpp config file" << std::endl << "\t-h ... brickd address" << std::endl - << "\t-p ... brickd port" << std::endl; + << "\t-p ... brickd port" << std::endl + << "\t-w ... working directory" << std::endl; } @@ -106,6 +108,15 @@ int main(int argc, char **argv) { printUsage(std::cerr, argv[0]); exit(1); } + } else if (strcmp(argv[t], "-w") == 0) { + if (t+1 < argc && argv[t+1][0] != '-') { + t++; + workDir = argv[t]; + } else { + std::cerr << "Option -w is missing an argument." << std::endl << std::endl; + printUsage(std::cerr, argv[0]); + exit(1); + } } else if (strcmp(argv[t], "-h") == 0) { if (t+1 < argc && argv[t+1][0] != '-') { t++; @@ -156,7 +167,7 @@ int main(int argc, char **argv) { signal(SIGINT, signalHandler); signal(SIGHUP, signalHandler); - controller.connect(host, port); + controller.connect(workDir, host, port); if (!termSignalCaught) { sleep(2); diff --git a/src/savefile.h b/src/savefile.h new file mode 100644 index 0000000..0f55ce8 --- /dev/null +++ b/src/savefile.h @@ -0,0 +1,76 @@ +/* + * savefile.h + * + * Created on: 18.06.2014 + * Author: matzman + */ + +#ifndef SAVEFILE_H_ +#define SAVEFILE_H_ + +#include "GCException.h" +#include +#include +#include + + + +namespace growcontrol { + + +template +void saveFileWrite(std::string file, T value) { + std::ofstream fs(file, std::ios::out | std::ios::binary); + fs << value; + if (!fs) { + std::ostringstream msg; + msg << "Could not write to save file " << file; + throw GCException(msg.str(), GCErrorCode::OTHER_ERROR); + } +} + +template +T saveFileRead(std::string file) { + T ret; + std::ifstream fs(file, std::ios::out | std::ios::binary); + fs >> ret; + if (!fs) { + std::ostringstream msg; + msg << "Could not read from save file " << file; + throw GCException(msg.str(), GCErrorCode::OTHER_ERROR); + } + return ret; +} + +template +void saveFileWrite(std::string base, std::string file, T value) { + std::ostringstream ss; + ss << base << "/" << file; + std::ofstream fs(ss.str(), std::ios::out | std::ios::binary); + fs << value; + if (!fs) { + std::ostringstream msg; + msg << "Could not write to save file " << ss.str(); + throw GCException(msg.str(), GCErrorCode::OTHER_ERROR); + } +} + +template +T saveFileRead(std::string base, std::string file) { + T ret; + std::ostringstream ss; + ss << base << "/" << file; + std::ifstream fs(ss.str(), std::ios::out | std::ios::binary); + fs >> ret; + if (!fs) { + std::ostringstream msg; + msg << "Could not read from save file " << ss.str(); + throw GCException(msg.str(), GCErrorCode::OTHER_ERROR); + } + return ret; +} + + +} /* namespace growcontrol */ + +#endif /* SAVEFILE_H_ */