Fixed bugs.

Began to implement Fan Control.
This commit is contained in:
hg
2014-06-18 01:41:12 +02:00
parent 3992e5f7d0
commit 6c5ea5a39f
23 changed files with 862 additions and 46 deletions
+29
View File
@@ -0,0 +1,29 @@
/*
* GCFanProfile.h
*
* Created on: 18.06.2014
* Author: matzman
*/
#ifndef GCFANPROFILE_H_
#define GCFANPROFILE_H_
#include <string>
namespace growcontrol {
class GCFanProfile {
private:
std::string name;
public:
GCFanProfile(std::string name) : name(name) {}
virtual ~GCFanProfile() {}
std::string getName() { return name; }
public:
};
} /* namespace growcontrol */
#endif /* GCFANPROFILE_H_ */
+84 -12
View File
@@ -13,13 +13,21 @@
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <chrono>
#include <ctime>
#include <thread>
#include "fanprofile/DummyProfile.h"
#include "fanprofile/Dummy2Profile.h"
namespace growcontrol {
log4cpp::Category& GrowControl::logger = log4cpp::Category::getInstance("growcontrol");
GrowControl::GrowControl() {
GrowControl::GrowControl() : lcd(*this) {
fanProfiles.push_back(new DummyProfile());
fanProfiles.push_back(new Dummy2Profile());
fan1ActiveProfile = fanProfiles.at(0);
}
GrowControl::~GrowControl() {
@@ -107,8 +115,8 @@ void GrowControl::newDeviceCallback(TfConnection& conn, TfDevice& device) {
&& device.getDeviceState() == TfDeviceState::AVAILABLE ) {
io16Bricklet = (TfIO16Bricklet*)&device;
io16Bricklet->connect();
io16Bricklet->setPortConfiguration('a', 0x7F, 'o', false);
io16Bricklet->setPort('a', 1);
io16Bricklet->setPortConfiguration('a', fan1PinMask, 'o', false);
setFan1Level(fan1Level);
logger << log4cpp::Priority::INFO << "Added io16 device " << device.getDeviceName(true) << ".";
}
break;
@@ -187,14 +195,16 @@ double GrowControl::getHum1() {
return ret;
}
int GrowControl::getFan1() {
unsigned GrowControl::getFan1Level(bool force) {
std::lock_guard<std::mutex> lock(controlMutex);
int ret = 0;
unsigned ret = 0;
if (force) {
return fan1Level;
}
if (hum1Bricklet != nullptr) {
if (hum1Bricklet->getDeviceState() == TfDeviceState::CONNECTED) {
try {
// ToDo
throw GCException("Fan not implemented yet.", GCErrorCode::NOT_INITIALIZED);
ret = fan1Level;
} catch (TfError &e) {
std::ostringstream ss;
ss << "unknown exception while getting fan1: " << e.what();
@@ -210,6 +220,64 @@ int GrowControl::getFan1() {
}
bool GrowControl::isFan1Connected() {
return (io16Bricklet != nullptr && io16Bricklet->getDeviceState() == TfDeviceState::CONNECTED);
}
void GrowControl::setFan1Level(unsigned level) {
if (level > fan1UpperLimit) {
level = fan1UpperLimit;
}
if (level != fan1Level) {
fan1Level = level;
if (isFan1Connected()) {
if (fan1Level <= 0) {
io16Bricklet->setPort('a', fan1PinMask, false);
} else {
io16Bricklet->setPort('a', fan1PinMask, false);
usleep(100000); // Wait for 100 ms (Just to be sure)
io16Bricklet->setPort('a', 1 << (fan1Level - 1), true);
}
}
}
}
unsigned GrowControl::getFan1UpperLimit() {
return fan1UpperLimit;
}
void GrowControl::setFan1UpperLimit(unsigned limit) {
fan1UpperLimit = limit;
if (fan1Level > fan1UpperLimit) {
setFan1Level(fan1UpperLimit);
}
}
unsigned GrowControl::getFan1Max() {
return fan1Max;
}
bool GrowControl::getFan1AutoMode() {
return fan1AutoMode;
}
void GrowControl::setFan1AutoMode(bool mode) {
fan1AutoMode = mode;
}
GCFanProfile* GrowControl::getFan1Profile() {
return fan1ActiveProfile;
}
void GrowControl::setFan1Profile(GCFanProfile* profile) {
fan1ActiveProfile = profile;
}
const std::vector<GCFanProfile*>& GrowControl::getFanProfiles() {
return fanProfiles;
}
void GrowControl::shutdownController() {
std::lock_guard<std::mutex> lock(controlMutex);
mainLoopFlag = false;
@@ -222,6 +290,7 @@ void GrowControl::mainLoop() {
// Fetch sensor values
GCSensorsInfo sensorValues;
sensorValues.timestamp = std::chrono::system_clock::now();
try {
sensorValues.temp1.value = getTemp1();
sensorValues.temp1.valid = true;
@@ -244,17 +313,20 @@ void GrowControl::mainLoop() {
sensorValues.hum1.error = e;
}
try {
sensorValues.fan1.value = getFan1();
sensorValues.fan1.valid = true;
sensorValues.fan1UpperLimit = getFan1UpperLimit();
sensorValues.fan1AutoMode = getFan1AutoMode();
sensorValues.fan1Profile = getFan1Profile();
sensorValues.fan1Level.value = getFan1Level();
sensorValues.fan1Level.valid = true;
} catch (GCException &e) {
sensorValues.fan1.valid = false;
sensorValues.fan1.error = e;
sensorValues.fan1Level.valid = false;
sensorValues.fan1Level.error = e;
}
lcd.controlMainLoopCallback(sensorValues);
if (mainLoopFlag) {
sleep(sleepDuration);
std::this_thread::sleep_until(sensorValues.timestamp + std::chrono::seconds(1));
}
}
+29 -2
View File
@@ -13,11 +13,16 @@
#include <log4cpp/Category.hh>
#include <mutex>
#include "LCD.h"
#include <vector>
#include <string>
#include <chrono>
using namespace tfcppsimple;
namespace growcontrol {
class GCFanProfile;
template<class T>
struct CGSensorValue {
@@ -27,10 +32,14 @@ struct CGSensorValue {
};
struct GCSensorsInfo {
std::chrono::system_clock::time_point timestamp;
CGSensorValue<double> temp1;
CGSensorValue<double> temp2;
CGSensorValue<double> hum1;
CGSensorValue<int> fan1;
CGSensorValue<unsigned> fan1Level;
int fan1UpperLimit;
bool fan1AutoMode;
GCFanProfile* fan1Profile;
};
@@ -52,6 +61,13 @@ private:
unsigned int sleepDuration = 1;
bool mainLoopFlag = true;
unsigned fan1Max = 7;
unsigned fan1UpperLimit = 7;
uint8_t fan1PinMask = 0x7F;
bool fan1AutoMode = true;
unsigned fan1Level = 0;
GCFanProfile* fan1ActiveProfile = nullptr;
std::vector<GCFanProfile*> fanProfiles;
public:
@@ -71,7 +87,18 @@ public:
double getHum1();
int getFan1();
bool isFan1Connected();
unsigned getFan1Level(bool force = false);
void setFan1Level(unsigned level);
unsigned getFan1UpperLimit();
void setFan1UpperLimit(unsigned limit);
unsigned getFan1Max();
bool getFan1AutoMode();
void setFan1AutoMode(bool mode);
GCFanProfile* getFan1Profile();
void setFan1Profile(GCFanProfile* profile);
const std::vector<GCFanProfile*>& getFanProfiles();
void shutdownController();
};
+8 -4
View File
@@ -17,6 +17,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <error.h>
namespace growcontrol {
@@ -51,7 +52,7 @@ void IPCManager::workerThreadFunc(IPCManager* obj, int socket, std::thread* self
logger << log4cpp::Priority::INFO << "ipc connection closed by peer.";
loopFlag = false;
} else if (rsize < 0) { // Error while receive
logger << log4cpp::Priority::ERROR << "error during ipc recv.";
logger << log4cpp::Priority::ERROR << "error during ipc recv: " << strerror(errno);
loopFlag = false;
} else {
// Check if '\0' appears in command (our end-of-command)
@@ -106,7 +107,7 @@ void IPCManager::init(GrowControl& growControl, std::string socketPath) {
this->socketPath = socketPath;
// Create Socket
if ((socketFD = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
logger << log4cpp::Priority::ERROR << "Could not create socket";
logger << log4cpp::Priority::ERROR << "Could not create socket: " << strerror(errno);
throw GCException("Could not create socket", GCErrorCode::OTHER_ERROR);
}
// Create address struct
@@ -117,12 +118,12 @@ void IPCManager::init(GrowControl& growControl, std::string socketPath) {
unlink(local.sun_path);
// bind socket
if (bind(socketFD, (struct sockaddr *)&local, sizeof(local)) == -1) {
logger << log4cpp::Priority::ERROR << "Could not bind socket";
logger << log4cpp::Priority::ERROR << "Could not bind socket: " << strerror(errno);
throw GCException("Could not bind socket", GCErrorCode::OTHER_ERROR);
}
// mark as listen connection
if (listen(socketFD, 5) == -1) {
logger << log4cpp::Priority::ERROR << "Could not switch socket to accepting mode";
logger << log4cpp::Priority::ERROR << "Could not switch socket to accepting mode: " << strerror(errno);
throw GCException("Could not switch socket to accepting mode", GCErrorCode::OTHER_ERROR);
}
logger << log4cpp::Priority::INFO << "Successfully created new ipc socket " << socketPath << ".";
@@ -138,6 +139,8 @@ IPCManager::~IPCManager() {
void IPCManager::shutdown() {
/* There's a deadlock somewhere
if (configFlag) {
if (socketFD > 0) {
close(socketFD);
@@ -155,6 +158,7 @@ void IPCManager::shutdown() {
}
configFlag = false;
}
*/
}
+1 -1
View File
@@ -12,7 +12,7 @@ namespace growcontrol {
log4cpp::Category& LCD::logger = log4cpp::Category::getInstance("growcontrol");
LCD::LCD() : pageRoot(*this) {
LCD::LCD(GrowControl& controller) : controller(controller), pageRoot(*this) {
activePage = &pageRoot;
for (int t = 0; t < 4; t++) {
for (int i = 0; i < 20; i++) {
+6 -2
View File
@@ -17,6 +17,7 @@ using namespace tfcppsimple;
namespace growcontrol {
class GrowControl;
struct GCSensorsInfo;
class LCD : public TfLCD20x4Listener, public TfDeviceStateListener {
@@ -29,14 +30,15 @@ private:
char lcdBuffer[4][21];
bool lineFlags[4] = {false, false, false, false};
int lcdLightCountdown = 0;
int lcdLightMaxCountdown = 10;
int lcdLightMaxCountdown = 30;
bool lcdLightCountdownFlag = false;
LCDPage* activePage = nullptr;
GrowControl& controller;
MainPage pageRoot;
public:
LCD();
LCD(GrowControl& controller);
virtual ~LCD();
void setTfObject(TfLCD20x4Bricklet& lcd);
@@ -54,6 +56,8 @@ public:
void resetLightCountdown();
void setLight(bool light);
GrowControl& getGrowControl() { return controller; }
void controlMainLoopCallback(GCSensorsInfo& sensors);
bool isLCDConnected();
+1
View File
@@ -6,3 +6,4 @@ SRC_FILES += src/main.cpp \
include src/lcdpages/config.mk
include src/third-party/config.mk
include src/fanprofile/config.mk
+18
View File
@@ -0,0 +1,18 @@
/*
* Dummy2Profile.cpp
*
* Created on: 18.06.2014
* Author: matzman
*/
#include "Dummy2Profile.h"
namespace growcontrol {
Dummy2Profile::Dummy2Profile() : GCFanProfile("Dummy2") {
}
Dummy2Profile::~Dummy2Profile() {
}
} /* namespace growcontrol */
+23
View File
@@ -0,0 +1,23 @@
/*
* Dummy2Profile.h
*
* Created on: 18.06.2014
* Author: matzman
*/
#ifndef DUMMY2PROFILE_H_
#define DUMMY2PROFILE_H_
#include "../GCFanProfile.h"
namespace growcontrol {
class Dummy2Profile: public GCFanProfile {
public:
Dummy2Profile();
virtual ~Dummy2Profile();
};
} /* namespace growcontrol */
#endif /* DUMMY2PROFILE_H_ */
+18
View File
@@ -0,0 +1,18 @@
/*
* DummyProfile.cpp
*
* Created on: 18.06.2014
* Author: matzman
*/
#include "DummyProfile.h"
namespace growcontrol {
DummyProfile::DummyProfile() : GCFanProfile("Dummy") {
}
DummyProfile::~DummyProfile() {
}
} /* namespace growcontrol */
+23
View File
@@ -0,0 +1,23 @@
/*
* DummyProfile.h
*
* Created on: 18.06.2014
* Author: matzman
*/
#ifndef DUMMYPROFILE_H_
#define DUMMYPROFILE_H_
#include "../GCFanProfile.h"
namespace growcontrol {
class DummyProfile: public GCFanProfile {
public:
DummyProfile();
virtual ~DummyProfile();
};
} /* namespace growcontrol */
#endif /* DUMMYPROFILE_H_ */
+3
View File
@@ -0,0 +1,3 @@
SRC_FILES += src/fanprofile/DummyProfile.cpp \
src/fanprofile/Dummy2Profile.cpp
+140
View File
@@ -0,0 +1,140 @@
/*
* FanLevelSettings.cpp
*
* Created on: 17.06.2014
* Author: matzman
*/
#include "FanLevelSettings.h"
#include "../LCD.h"
#include "../GrowControl.h"
#include "../GCException.h"
#include <iostream>
#include <sstream>
#include <cstdlib>
namespace growcontrol {
FanLevelSettings::FanLevelSettings(LCD& lcd, LCDPage* parent) : LCDPage(lcd, parent) {
}
FanLevelSettings::~FanLevelSettings() {
}
void FanLevelSettings::fillItemVector(unsigned upperLimit) {
if (lastUpperLimit != upperLimit) {
items.clear();
items.push_back("Auto");
items.push_back("Off");
for (unsigned t = 1; t <= upperLimit; t++) {
std::ostringstream ss;
ss << t;
items.push_back(ss.str());
}
lastUpperLimit = upperLimit;
}
}
void FanLevelSettings::reset() {
itemsStart = 0;
cursorPos = 0;
}
void FanLevelSettings::refreshDisplay() {
if (lcd.isLCDConnected()) {
fillItemVector(lcd.getGrowControl().getFan1UpperLimit());
int diff = (items.size()-1) - (itemsStart + cursorPos);
if (diff < -3) {
reset();
} else if (diff < 0) {
cursorPos += diff;
}
if (lcd.getGrowControl().getFan1AutoMode()) {
activePos = 0;
} else {
activePos = lcd.getGrowControl().getFan1Level(true) + 1;
}
char buffer[21];
lcd.writeLine(0, "Fan Level:");
for (unsigned t = itemsStart; t < items.size() && t < itemsStart + 3; t++) {
char cursor = ' ';
if (t == itemsStart + cursorPos) {
cursor = 0x7e;
}
char navhint = ' ';
if (t == itemsStart && t >0 ) {
navhint = '<';
} else if (t == itemsStart + 2 && items.size() - itemsStart > 3) {
navhint = '>';
}
char aPosHint1 = ' ';
char aPosHint2 = ' ';
if (t == activePos) {
aPosHint1 = '*';
aPosHint2 = '*';
}
snprintf(buffer, 21, "%c %c%c%.14s%c", navhint, cursor, aPosHint1, items.at(t).c_str(), aPosHint2);
lcd.writeLine(t - itemsStart + 1, buffer);
}
try {
lcd.writeLCDBuffer();
} catch (GCException &e) {
}
}
}
void FanLevelSettings::buttonStateCallback(uint8_t button, bool state) {
if (state) {
bool refresh = false;
switch (button) {
case 0: // enter
{
unsigned pos = itemsStart + cursorPos;
if (pos != activePos) {
if (pos == 0) {
lcd.getGrowControl().setFan1AutoMode(true);
} else {
lcd.getGrowControl().setFan1AutoMode(false);
lcd.getGrowControl().setFan1Level(pos-1);
}
}
refresh = true;
}
break;
case 1: // up
if (cursorPos > 0) {
cursorPos--;
} else if (cursorPos == 0 && itemsStart > 0) {
itemsStart--;
}
refresh = true;
break;
case 2: // down
if (cursorPos < 2) {
cursorPos++;
} else if (cursorPos == 2 && items.size() - itemsStart > 3) {
itemsStart++;
}
refresh = true;
break;
case 3: // cancel
lcd.setActivePage(*parent, true);
break;
default:
break;
}
if (refresh) {
refreshDisplay();
}
}
}
void FanLevelSettings::stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate) {
}
void FanLevelSettings::controlMainLoopCallback(GCSensorsInfo& sensors) {
}
} /* namespace growcontrol */
+41
View File
@@ -0,0 +1,41 @@
/*
* FanLevelSettings.h
*
* Created on: 17.06.2014
* Author: matzman
*/
#ifndef FANLEVELSETTINGS_H_
#define FANLEVELSETTINGS_H_
#include "../LCDPage.h"
#include <vector>
#include <string>
namespace growcontrol {
class FanLevelSettings: public LCDPage {
private:
std::vector<std::string> items;
unsigned itemsStart = 0;
unsigned cursorPos = 0;
unsigned lastUpperLimit = 0;
unsigned activePos = 0;
void fillItemVector(unsigned upperLimit);
public:
FanLevelSettings(LCD& lcd, LCDPage* parent);
virtual ~FanLevelSettings();
virtual void reset();
virtual void refreshDisplay();
virtual void buttonStateCallback(uint8_t button, bool state);
virtual void stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate);
virtual void controlMainLoopCallback(GCSensorsInfo& sensors);
};
} /* namespace growcontrol */
#endif /* FANLEVELSETTINGS_H_ */
+116
View File
@@ -0,0 +1,116 @@
/*
* FanProfileSettings.cpp
*
* Created on: 18.06.2014
* Author: matzman
*/
#include "FanProfileSettings.h"
#include "../GCFanProfile.h"
#include "../LCD.h"
#include "../GrowControl.h"
#include "../GCException.h"
#include <iostream>
#include <sstream>
#include <cstdlib>
namespace growcontrol {
FanProfileSettings::FanProfileSettings(LCD& lcd, LCDPage* parent) : LCDPage(lcd, parent) {
}
FanProfileSettings::~FanProfileSettings() {
}
void FanProfileSettings::reset() {
itemsStart = 0;
cursorPos = 0;
}
void FanProfileSettings::refreshDisplay() {
if (items.size() == 0) {
items = lcd.getGrowControl().getFanProfiles();
}
if (lcd.isLCDConnected()) {
auto activeProfile = lcd.getGrowControl().getFan1Profile();
char buffer[21];
lcd.writeLine(0, "Fan Profiles:");
for (unsigned t = itemsStart; t < items.size() && t < itemsStart + 3; t++) {
auto ai = items.at(t);
char cursor = ' ';
if (t == itemsStart + cursorPos) {
cursor = 0x7e;
}
char navhint = ' ';
if (t == itemsStart && t >0 ) {
navhint = '<';
} else if (t == itemsStart + 2 && items.size() - itemsStart > 3) {
navhint = '>';
}
char aPosHint1 = ' ';
char aPosHint2 = ' ';
if (ai == activeProfile) {
aPosHint1 = '*';
aPosHint2 = '*';
}
snprintf(buffer, 21, "%c %c%c%.14s%c", navhint, cursor, aPosHint1, ai->getName().c_str(), aPosHint2);
lcd.writeLine(t - itemsStart + 1, buffer);
}
try {
lcd.writeLCDBuffer();
} catch (GCException &e) {
}
}
}
void FanProfileSettings::buttonStateCallback(uint8_t button, bool state) {
if (state) {
bool refresh = false;
switch (button) {
case 0: // enter
{
unsigned pos = itemsStart + cursorPos;
auto pi = items.at(pos);
if (lastActiveProfile != pi) {
lcd.getGrowControl().setFan1Profile(pi);
}
refresh = true;
}
break;
case 1: // up
if (cursorPos > 0) {
cursorPos--;
} else if (cursorPos == 0 && itemsStart > 0) {
itemsStart--;
}
refresh = true;
break;
case 2: // down
if (cursorPos < 2) {
cursorPos++;
} else if (cursorPos == 2 && items.size() - itemsStart > 3) {
itemsStart++;
}
refresh = true;
break;
case 3: // cancel
lcd.setActivePage(*parent, true);
break;
default:
break;
}
if (refresh) {
refreshDisplay();
}
}
}
void FanProfileSettings::stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate) {
}
void FanProfileSettings::controlMainLoopCallback(GCSensorsInfo& sensors) {
}
} /* namespace growcontrol */
+41
View File
@@ -0,0 +1,41 @@
/*
* FanProfileSettings.h
*
* Created on: 18.06.2014
* Author: matzman
*/
#ifndef FANPROFILESETTINGS_H_
#define FANPROFILESETTINGS_H_
#include "../LCDPage.h"
#include <vector>
#include <string>
namespace growcontrol {
class GCFanProfile;
class FanProfileSettings: public LCDPage {
public:
std::vector<GCFanProfile*> items;
unsigned itemsStart = 0;
unsigned cursorPos = 0;
GCFanProfile* lastActiveProfile = nullptr;
public:
FanProfileSettings(LCD& lcd, LCDPage* parent);
virtual ~FanProfileSettings();
virtual void reset();
virtual void refreshDisplay();
virtual void buttonStateCallback(uint8_t button, bool state);
virtual void stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate);
virtual void controlMainLoopCallback(GCSensorsInfo& sensors);
};
} /* namespace growcontrol */
#endif /* FANPROFILESETTINGS_H_ */
+71 -5
View File
@@ -11,21 +11,41 @@
namespace growcontrol {
FanSettings::FanSettings(LCD& lcd, LCDPage* parent) : LCDPage(lcd, parent) {
FanSettings::FanSettings(LCD& lcd, LCDPage* parent)
: LCDPage(lcd, parent), levelSettings(lcd, this)
, upperLimitSettings(lcd, this), profileSettings(lcd, this) {
items.push_back("Fan Level");
items.push_back("Fan Profile");
items.push_back("Upper Limit");
items.push_back("Back");
}
FanSettings::~FanSettings() {
}
void FanSettings::reset() {
itemsStart = 0;
cursorPos = 0;
}
void FanSettings::refreshDisplay() {
if (lcd.isLCDConnected()) {
lcd.clearDisplay();
char buffer[21];
lcd.writeLine(0, "Fan Settings:");
lcd.writeLine(1, " ToDo");
for (unsigned t = itemsStart; t < items.size() && t < itemsStart + 3; t++) {
char cursor = ' ';
if (t == itemsStart + cursorPos) {
cursor = 0x7e;
}
char navhint = ' ';
if (t == itemsStart && t >0 ) {
navhint = '<';
} else if (t == itemsStart + 2 && items.size() - itemsStart > 3) {
navhint = '>';
}
snprintf(buffer, 21, "%c %c%-17.17s", navhint, cursor, items.at(t).c_str());
lcd.writeLine(t - itemsStart + 1, buffer);
}
try {
lcd.writeLCDBuffer();
} catch (GCException &e) {
@@ -35,7 +55,53 @@ void FanSettings::refreshDisplay() {
void FanSettings::buttonStateCallback(uint8_t button, bool state) {
if (state) {
lcd.setActivePage(*parent);
bool refresh = false;
switch (button) {
case 0: // enter
switch (itemsStart + cursorPos) {
case 0: // Fan Settings
lcd.setActivePage(levelSettings, true);
break;
case 1: // Profiles
lcd.setActivePage(profileSettings, true);
break;
case 2: // Upper Limit
lcd.setActivePage(upperLimitSettings, true);
break;
case 3: // back
lcd.setActivePage(*parent, true);
break;
default:
break;
}
break;
case 1: // up
if (cursorPos > 0) {
cursorPos--;
refresh = true;
} else if (cursorPos == 0 && itemsStart > 0) {
itemsStart--;
refresh = true;
}
break;
case 2: // down
if (cursorPos < 2 && cursorPos < items.size() - 1 ) {
cursorPos++;
refresh = true;
} else if (cursorPos == 2 && items.size() - itemsStart > 3) {
itemsStart++;
refresh = true;
}
break;
case 3: // cancel
lcd.setActivePage(*parent, true);
break;
default:
break;
}
if (refresh) {
refreshDisplay();
}
}
}
+12
View File
@@ -9,11 +9,23 @@
#define FANSETTINGS_H_
#include "../LCDPage.h"
#include "FanLevelSettings.h"
#include "FanUpperLimitSettings.h"
#include "FanProfileSettings.h"
#include <string>
namespace growcontrol {
class FanSettings : public LCDPage {
private:
std::vector<std::string> items;
unsigned itemsStart = 0;
unsigned cursorPos = 0;
FanLevelSettings levelSettings;
FanUpperLimitSettings upperLimitSettings;
FanProfileSettings profileSettings;
public:
FanSettings(LCD& lcd, LCDPage* parent);
virtual ~FanSettings();
+117
View File
@@ -0,0 +1,117 @@
/*
* FanUpperLimitSettings.cpp
*
* Created on: 18.06.2014
* Author: matzman
*/
#include "FanUpperLimitSettings.h"
#include "../LCD.h"
#include "../GrowControl.h"
#include "../GCException.h"
#include <iostream>
#include <sstream>
#include <cstdlib>
namespace growcontrol {
FanUpperLimitSettings::FanUpperLimitSettings(LCD& lcd, LCDPage* parent) : LCDPage(lcd, parent) {
}
FanUpperLimitSettings::~FanUpperLimitSettings() {
}
void FanUpperLimitSettings::reset() {
itemsStart = 0;
cursorPos = 0;
}
void FanUpperLimitSettings::refreshDisplay() {
if (items.size() == 0) {
for (unsigned t = 1; t <= lcd.getGrowControl().getFan1Max(); t++) {
std::ostringstream ss;
ss << t;
items.push_back(ss.str());
}
}
if (lcd.isLCDConnected()) {
activePos = lcd.getGrowControl().getFan1UpperLimit() - 1;
char buffer[21];
lcd.writeLine(0, "Fan Upper Limit:");
for (unsigned t = itemsStart; t < items.size() && t < itemsStart + 3; t++) {
char cursor = ' ';
if (t == itemsStart + cursorPos) {
cursor = 0x7e;
}
char navhint = ' ';
if (t == itemsStart && t >0 ) {
navhint = '<';
} else if (t == itemsStart + 2 && items.size() - itemsStart > 3) {
navhint = '>';
}
char aPosHint1 = ' ';
char aPosHint2 = ' ';
if (t == activePos) {
aPosHint1 = '*';
aPosHint2 = '*';
}
snprintf(buffer, 21, "%c %c%c%.14s%c", navhint, cursor, aPosHint1, items.at(t).c_str(), aPosHint2);
lcd.writeLine(t - itemsStart + 1, buffer);
}
try {
lcd.writeLCDBuffer();
} catch (GCException &e) {
}
}
}
void FanUpperLimitSettings::buttonStateCallback(uint8_t button, bool state) {
if (state) {
bool refresh = false;
switch (button) {
case 0: // enter
{
unsigned pos = itemsStart + cursorPos;
if (pos != activePos) {
lcd.getGrowControl().setFan1UpperLimit(pos+1);
}
refresh = true;
}
break;
case 1: // up
if (cursorPos > 0) {
cursorPos--;
} else if (cursorPos == 0 && itemsStart > 0) {
itemsStart--;
}
refresh = true;
break;
case 2: // down
if (cursorPos < 2) {
cursorPos++;
} else if (cursorPos == 2 && items.size() - itemsStart > 3) {
itemsStart++;
}
refresh = true;
break;
case 3: // cancel
lcd.setActivePage(*parent, true);
break;
default:
break;
}
if (refresh) {
refreshDisplay();
}
}
}
void FanUpperLimitSettings::stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate) {
}
void FanUpperLimitSettings::controlMainLoopCallback(GCSensorsInfo& sensors) {
}
} /* namespace growcontrol */
+39
View File
@@ -0,0 +1,39 @@
/*
* FanUpperLimitSettings.h
*
* Created on: 18.06.2014
* Author: matzman
*/
#ifndef FanUpperLimitSettings_H_
#define FanUpperLimitSettings_H_
#include "../LCDPage.h"
#include <vector>
#include <string>
namespace growcontrol {
class FanUpperLimitSettings: public LCDPage {
private:
std::vector<std::string> items;
unsigned itemsStart = 0;
unsigned cursorPos = 0;
unsigned lastUpperLimit = 0;
unsigned activePos = 0;
public:
FanUpperLimitSettings(LCD& lcd, LCDPage* parent);
virtual ~FanUpperLimitSettings();
virtual void reset();
virtual void refreshDisplay();
virtual void buttonStateCallback(uint8_t button, bool state);
virtual void stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate);
virtual void controlMainLoopCallback(GCSensorsInfo& sensors);
};
} /* namespace growcontrol */
#endif /* FanUpperLimitSettings_H_ */
+37 -18
View File
@@ -7,7 +7,14 @@
#include "MainPage.h"
#include "../GrowControl.h"
#include "../GCFanProfile.h"
#include <stdio.h>
#include <string>
#include <sstream>
#include <chrono>
#include <iostream>
#include <iomanip>
#include <ctime>
namespace growcontrol {
@@ -71,9 +78,6 @@ void MainPage::controlMainLoopCallback(GCSensorsInfo& sensors) {
snprintf(temp1, 21, "%4.2lf%cC", sensors.temp1.value, 0xdf);
} else {
switch (sensors.temp1.error.getErrorCode()) {
case GCErrorCode::SENSOR_DISCONNECTED:
snprintf(temp1, 21, "DISCON");
break;
default:
snprintf(temp1, 21, " ERROR");
break;
@@ -84,9 +88,6 @@ void MainPage::controlMainLoopCallback(GCSensorsInfo& sensors) {
snprintf(temp2, 21, "%4.2lf%cC", sensors.temp2.value, 0xdf);
} else {
switch (sensors.temp2.error.getErrorCode()) {
case GCErrorCode::SENSOR_DISCONNECTED:
snprintf(temp2, 21, "DISCON");
break;
default:
snprintf(temp2, 21, " ERROR");
break;
@@ -97,33 +98,51 @@ void MainPage::controlMainLoopCallback(GCSensorsInfo& sensors) {
snprintf(hum1, 21, "%4.1lf%% ", sensors.hum1.value);
} else {
switch (sensors.hum1.error.getErrorCode()) {
case GCErrorCode::SENSOR_DISCONNECTED:
snprintf(hum1, 21, "DISCON");
break;
default:
snprintf(hum1, 21, "ERROR ");
break;
}
}
// fan1
if (sensors.fan1.valid) {
snprintf(fan1, 21, "ToDo");
if (sensors.fan1Level.valid) {
std::ostringstream ss;
if (sensors.fan1Level.value == 0) {
ss << "off";
} else {
ss << sensors.fan1Level.value;
}
if (sensors.fan1AutoMode) {
auto profile = lcd.getGrowControl().getFan1Profile();
if (profile == nullptr) {
ss << " (Auto?)";
} else {
ss << " (" << profile->getName() << ")";
}
} else {
ss << " (Manual)";
}
std::string fanString = ss.str();
snprintf(fan1, 21, fanString.c_str());
} else {
switch (sensors.fan1.error.getErrorCode()) {
case GCErrorCode::SENSOR_DISCONNECTED:
snprintf(fan1, 21, "DISCON");
break;
switch (sensors.fan1Level.error.getErrorCode()) {
default:
snprintf(fan1, 21, " ERROR");
break;
}
}
// date
std::chrono::system_clock::time_point test;
auto time = std::chrono::system_clock::to_time_t(sensors.timestamp);
auto ltime = std::localtime(&time);
strftime(buffer[0], 20, " %d.%m.%y %H:%M:%S ", ltime );
// line 0
snprintf(buffer[1], 21, "T: %7.7s %7.7s ", temp1, temp2);
// line 1
snprintf(buffer[0], 21, "T: %7.7s %7.7s ", temp1, temp2);
snprintf(buffer[1], 21, "T: %7.7s %7.7s ", temp1, temp2);
// line 2
snprintf(buffer[1], 21, "Humidity: %5.5s ", hum1);
snprintf(buffer[2], 21, "Humidity: %5.5s ", hum1);
// line 3
snprintf(buffer[2], 21, "Fan: %-15.15s", fan1);
snprintf(buffer[3], 21, "Fan: %-15.15s", fan1);
refreshDisplay();
}
+4 -1
View File
@@ -3,4 +3,7 @@ SRC_FILES += src/lcdpages/MainPage.cpp \
src/lcdpages/MainMenu.cpp \
src/lcdpages/AboutPage.cpp \
src/lcdpages/FanSettings.cpp \
src/lcdpages/PCSettings.cpp
src/lcdpages/PCSettings.cpp \
src/lcdpages/FanLevelSettings.cpp \
src/lcdpages/FanUpperLimitSettings.cpp \
src/lcdpages/FanProfileSettings.cpp
+1 -1
View File
@@ -28,7 +28,7 @@ using namespace growcontrol;
static log4cpp::Category& logger = log4cpp::Category::getInstance("growcontrol");
std::string pidFile = "/var/run/growcontrold.pid";
std::string socketPath = "/var/run/growcontrol.socket";
std::string socketPath = "/opt/growcontrol/growcontrold.socket";
std::string log4cppConfig = "log4cpp.config";
std::string host = "localhost";
uint16_t port = 4223;