Initial commit.

This commit is contained in:
matzman
2014-06-16 11:22:51 +02:00
commit ae0b6fdcd0
27 changed files with 1685 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?>
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1852549565">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1852549565" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.1852549565" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.base.1852549565.386309499" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.base.1306476319" name="cdt.managedbuild.toolchain.gnu.base" superClass="cdt.managedbuild.toolchain.gnu.base">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.1884941368" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
<builder id="cdt.managedbuild.target.gnu.builder.base.1785575647" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.target.gnu.builder.base"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.1168079033" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1593421472" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
<option id="gnu.cpp.compiler.option.include.paths.44640853" superClass="gnu.cpp.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/TinkerforgeCPPsimple/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/TinkerforgeCPPsimple/third-party/tinkerforge/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/TinkerforgeCPPsimple/third-party/log4cpp/include}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.380923382" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1995252296" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
<option id="gnu.c.compiler.option.include.paths.313509086" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/TinkerforgeCPPsimple/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/TinkerforgeCPPsimple/third-party/tinkerforge/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/TinkerforgeCPPsimple/third-party/log4cpp/include}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.315870798" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.base.429004895" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.1364527360" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.608792542" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.base.1564809540" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
<option id="gnu.both.asm.option.include.paths.163241950" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/TinkerforgeCPPsimple/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/TinkerforgeCPPsimple/third-party/tinkerforge/include}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/TinkerforgeCPPsimple/third-party/log4cpp/include}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1586145345" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="src"/>
</sourceEntries>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings">
<externalSettings containerId="TinkerforgeCPPsimple;" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"/>
</storageModule>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="growcontrold.null.1471269554" name="growcontrold"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/growcontrold"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
<buildTargets>
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>all</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
<target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>true</runAllBuilders>
</target>
</buildTargets>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1852549565;cdt.managedbuild.toolchain.gnu.base.1852549565.386309499;cdt.managedbuild.tool.gnu.cpp.compiler.base.1593421472;cdt.managedbuild.tool.gnu.cpp.compiler.input.380923382">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.1852549565;cdt.managedbuild.toolchain.gnu.base.1852549565.386309499;cdt.managedbuild.tool.gnu.c.compiler.base.1995252296;cdt.managedbuild.tool.gnu.c.compiler.input.315870798">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
</cproject>
+4
View File
@@ -0,0 +1,4 @@
syntax: regexp
^bin/
^build/
+28
View File
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>growcontrold</name>
<comment></comment>
<projects>
<project>TinkerforgeCPPsimple</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
</projectDescription>
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="cdt.managedbuild.toolchain.gnu.base.1852549565" name="Default">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser" keep-relative-paths="false" name="CDT GCC Build Output Parser" parameter="(gcc)|([gc]\+\+)|(clang)" prefer-non-shared="true"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-1226846246929179048" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot; -std=c++11">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
</extension>
</configuration>
</project>
+29
View File
@@ -0,0 +1,29 @@
include Makefile.local
SRC_FILES =
include src/config.mk
OBJS = $(SRC_FILES:src/%.cpp=build/%.o)
all : bin/growcontrold
bin :
mkdir -p bin
build :
mkdir -p build
bin/growcontrold : bin $(OBJS)
$(CXX) $(LD_FLAGS) $(OBJS) $(LD_LIBS) -o $@
$(OBJS) : build/%.o : src/%.cpp
mkdir -p $(dir $@)
$(CXX) $(CXX_FLAGS) $(CXX_INCL) -c $< -o $@
clean :
rm -rf build
distclean : clean
rm -rf bin
+29
View File
@@ -0,0 +1,29 @@
CXX_FLAGS = -O0 -g3 -Wall -std=c++11
CXX_INCL = -I ../TinkerforgeCPPsimple/include -I ../TinkerforgeCPPsimple/third-party/tinkerforge/include -I ../TinkerforgeCPPsimple/third-party/log4cpp/include -I /usr/include
LD_FLAGS = -pthread
LD_LIBS = -L ../TinkerforgeCPPsimple/lib -ltfcppsimple -ltinkerforge -llog4cpp
GCC_HOME =
GCC_PREFIX =
GCC = ${GCC_PREFIX}-gcc
CXX = ${GCC_PREFIX}-g++
CPP = ${GCC_PREFIX}-cpp
AR = ${GCC_PREFIX}-ar
OBJDUMP = ${GCC_PREFIX}-objdump
RANLIB = ${GCC_PREFIX}-ranlib
SIZE = ${GCC_PREFIX}-size
#GCC = ${GCC_HOME}/bin/${GCC_PREFIX}-gcc
#CXX = ${GCC_HOME}/bin/${GCC_PREFIX}-g++
#CPP = ${GCC_HOME}/bin/${GCC_PREFIX}-cpp
#AR = ${GCC_HOME}/bin/${GCC_PREFIX}-ar
#OBJDUMP = ${GCC_HOME}/bin/${GCC_PREFIX}-objdump
#RANLIB = ${GCC_HOME}/bin/${GCC_PREFIX}-ranlib
#SIZE = ${GCC_HOME}/bin/${GCC_PREFIX}-size
+37
View File
@@ -0,0 +1,37 @@
/*
* GCException.h
*
* Created on: 14.06.2014
* Author: matzman
*/
#ifndef GCEXCEPTION_H_
#define GCEXCEPTION_H_
#include <TfCPPsimple.h>
enum class GCErrorCode : int {
NO_ERROR,
NO_SENSOR,
SENSOR_DISCONNECTED,
UNKNOWN_TFERROR,
NOT_INITIALIZED,
OTHER_ERROR
};
class GCException : public std::runtime_error {
protected:
GCErrorCode errorCode;
public:
GCException()
: std::runtime_error(""), errorCode(GCErrorCode::NO_ERROR) {}
GCException(std::string msg, GCErrorCode errorCode)
: std::runtime_error(msg), errorCode(errorCode) {}
virtual ~GCException() {}
GCErrorCode getErrorCode() { return errorCode; }
};
#endif /* GCEXCEPTION_H_ */
+251
View File
@@ -0,0 +1,251 @@
/*
* GrowControl.cpp
*
* Created on: 14.06.2014
* Author: matzman
*/
#include "GrowControl.h"
#include <sstream>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
namespace growcontrol {
log4cpp::Category& GrowControl::logger = log4cpp::Category::getInstance("growcontrol");
GrowControl::GrowControl() {
}
GrowControl::~GrowControl() {
}
bool GrowControl::connect(std::string host , uint16_t port, bool retry) {
tfConnection.addListener(*this);
bool breakFlag = false;
do {
try {
tfConnection.connect(host, port);
breakFlag = true;
} catch (TfError &e) {
logger << log4cpp::Priority::ERROR << "Error while connecting to brickd: " << e.what();
}
if (!breakFlag) {
logger << log4cpp::Priority::ERROR << "Waiting for 3 sec before retrying.";
sleep(3);
} else {
logger << log4cpp::Priority::INFO << "Successfully connected to brickd ("
<< tfConnection.getHost() << ":" << tfConnection.getPort() << ").";
}
} while (retry && !breakFlag);
return breakFlag;
}
void GrowControl::newDeviceCallback(TfConnection& conn, TfDevice& device) {
std::lock_guard<std::mutex> lock(controlMutex);
switch (device.getDeviceIdentifier()) {
case TfDeviceIdentifier::MASTER:
if ( (rootBrick == nullptr || rootBrick->getDeviceState() != TfDeviceState::CONNECTED)
&& device.getDeviceState() == TfDeviceState::AVAILABLE && device.getParent() == nullptr ) {
rootBrick = (TfMasterBrick*)&device;
rootBrick->connect();
logger << log4cpp::Priority::INFO << "Added root device " << device.getDeviceName(true) << ".";
}
break;
case TfDeviceIdentifier::TEMPERATURE:
{
int prioT1 = 10000;
int prioT2 = 10000;
int prioNew = 10000;
if (temp1Bricklet != nullptr && temp1Bricklet->getDeviceState() == TfDeviceState::CONNECTED) {
char pPos = ((char)temp1Bricklet->getParent()->getPosition()) - ((char)TfDevicePosition::BRICK0);
char pos = ((char)temp1Bricklet->getPosition()) - ((char)TfDevicePosition::BRICKLET0);
prioT1 = (pPos * 5 + pos);
}
if (temp2Bricklet != nullptr && temp2Bricklet->getDeviceState() == TfDeviceState::CONNECTED) {
char pPos = ((char)temp2Bricklet->getParent()->getPosition()) - ((char)TfDevicePosition::BRICK0);
char pos = ((char)temp2Bricklet->getPosition()) - ((char)TfDevicePosition::BRICKLET0);
prioT2 = (pPos * 5 + pos);
}
if (device.getDeviceState() == TfDeviceState::AVAILABLE) {
char pPos = ((char)device.getParent()->getPosition()) - ((char)TfDevicePosition::BRICK0);
char pos = ((char)device.getPosition()) - ((char)TfDevicePosition::BRICKLET0);
prioNew = (pPos * 5 + pos);
}
if (prioNew < 10000) { // new device is alive
if (prioNew < prioT1) { // new device has lower priority than current temp1
if (prioT1 < 10000) { // current temp1 is alive and is moved to temp2
temp2Bricklet = temp1Bricklet;
logger << log4cpp::Priority::INFO << "Moving temp1 to temp2.";
}
temp1Bricklet = (TfTemperatureBricklet*)&device;
temp1Bricklet->connect();
logger << log4cpp::Priority::INFO << "Added temp1 device" << device.getDeviceName(true) << ".";
} else if (prioNew < prioT2) { // new device has lower priority than current temp2
temp2Bricklet = (TfTemperatureBricklet*)&device;
temp2Bricklet->connect();
logger << log4cpp::Priority::INFO << "Added temp2 device " << device.getDeviceName(true) << ".";
}
}
break;
}
case TfDeviceIdentifier::HUMIDITY:
if ( (hum1Bricklet == nullptr || hum1Bricklet->getDeviceState() != TfDeviceState::CONNECTED)
&& device.getDeviceState() == TfDeviceState::AVAILABLE ) {
hum1Bricklet = (TfHumidityBricklet*)&device;
hum1Bricklet->connect();
logger << log4cpp::Priority::INFO << "Added hum1 device " << device.getDeviceName(true) << ".";
}
break;
case TfDeviceIdentifier::IO16:
if ( (io16Bricklet == nullptr || io16Bricklet->getDeviceState() != TfDeviceState::CONNECTED)
&& device.getDeviceState() == TfDeviceState::AVAILABLE ) {
io16Bricklet = (TfIO16Bricklet*)&device;
io16Bricklet->connect();
logger << log4cpp::Priority::INFO << "Added io16 device " << device.getDeviceName(true) << ".";
}
break;
case TfDeviceIdentifier::LCD20x4:
lcd.setTfObject((TfLCD20x4Bricklet&)device);
break;
default:
break;
}
}
void GrowControl::shutdownCallback() {
std::lock_guard<std::mutex> lock(controlMutex);
}
double GrowControl::getTemp1() {
std::lock_guard<std::mutex> lock(controlMutex);
double ret = 0;
if (temp1Bricklet != nullptr) {
if (temp1Bricklet->getDeviceState() == TfDeviceState::CONNECTED) {
try {
ret = ((double)temp1Bricklet->getTemperature())/100.0;
} catch (TfError &e) {
std::ostringstream ss;
ss << "unknown exception while getting temp1: " << e.what();
throw GCException(ss.str(), GCErrorCode::UNKNOWN_TFERROR);
}
} else {
throw GCException("temp1 sensor not connected.", GCErrorCode::SENSOR_DISCONNECTED);
}
} else {
throw GCException("No temp1 sensor present.", GCErrorCode::NO_SENSOR);
}
return ret;
}
double GrowControl::getTemp2() {
std::lock_guard<std::mutex> lock(controlMutex);
double ret = 0;
if (temp2Bricklet != nullptr) {
if (temp2Bricklet->getDeviceState() == TfDeviceState::CONNECTED) {
try {
ret = ((double)temp2Bricklet->getTemperature())/100.0;
} catch (TfError &e) {
std::ostringstream ss;
ss << "unknown exception while getting temp2: " << e.what();
throw GCException(ss.str(), GCErrorCode::UNKNOWN_TFERROR);
}
} else {
throw GCException("temp2 sensor not connected.", GCErrorCode::SENSOR_DISCONNECTED);
}
} else {
throw GCException("No temp2 sensor present.", GCErrorCode::NO_SENSOR);
}
return ret;
}
double GrowControl::getHum1() {
std::lock_guard<std::mutex> lock(controlMutex);
double ret = 0;
if (hum1Bricklet != nullptr) {
if (hum1Bricklet->getDeviceState() == TfDeviceState::CONNECTED) {
try {
ret = ((double)hum1Bricklet->getHumidity())/10.0;
} catch (TfError &e) {
std::ostringstream ss;
ss << "unknown exception while getting hum1: " << e.what();
throw GCException(ss.str(), GCErrorCode::UNKNOWN_TFERROR);
}
} else {
throw GCException("hum1 sensor not connected.", GCErrorCode::SENSOR_DISCONNECTED);
}
} else {
throw GCException("No hum1 sensor present.", GCErrorCode::NO_SENSOR);
}
return ret;
}
int GrowControl::getFan1() {
std::lock_guard<std::mutex> lock(controlMutex);
int ret = 0;
if (hum1Bricklet != nullptr) {
if (hum1Bricklet->getDeviceState() == TfDeviceState::CONNECTED) {
try {
// ToDo
throw GCException("Fan not implemented yet.", GCErrorCode::NOT_INITIALIZED);
} catch (TfError &e) {
std::ostringstream ss;
ss << "unknown exception while getting fan1: " << e.what();
throw GCException(ss.str(), GCErrorCode::UNKNOWN_TFERROR);
}
} else {
throw GCException("fan1 not connected.", GCErrorCode::SENSOR_DISCONNECTED);
}
} else {
throw GCException("No fan1 present.", GCErrorCode::NO_SENSOR);
}
return ret;
}
void GrowControl::mainLoop() {
while (mainLoopFlag) {
// Fetch sensor values
GCSensorsInfo sensorValues;
try {
sensorValues.temp1.value = getTemp1();
sensorValues.temp1.valid = true;
} catch (GCException &e) {
sensorValues.temp1.valid = false;
sensorValues.temp1.error = e;
}
try {
sensorValues.temp2.value = getTemp2();
sensorValues.temp2.valid = true;
} catch (GCException &e) {
sensorValues.temp2.valid = false;
sensorValues.temp2.error = e;
}
try {
sensorValues.hum1.value = getHum1();
sensorValues.hum1.valid = true;
} catch (GCException &e) {
sensorValues.hum1.valid = false;
sensorValues.hum1.error = e;
}
try {
sensorValues.fan1.value = getFan1();
sensorValues.fan1.valid = true;
} catch (GCException &e) {
sensorValues.fan1.valid = false;
sensorValues.fan1.error = e;
}
lcd.controlMainLoopCallback(sensorValues);
sleep(sleepDuration);
}
}
} /* namespace growcontrol */
+79
View File
@@ -0,0 +1,79 @@
/*
* GrowControl.h
*
* Created on: 14.06.2014
* Author: matzman
*/
#ifndef GROWCONTROL_H_
#define GROWCONTROL_H_
#include <TfCPPsimple.h>
#include "GCException.h"
#include <log4cpp/Category.hh>
#include <mutex>
#include "LCD.h"
using namespace tfcppsimple;
namespace growcontrol {
template<class T>
struct CGSensorValue {
T value;
bool valid = false;
GCException error;
};
struct GCSensorsInfo {
CGSensorValue<double> temp1;
CGSensorValue<double> temp2;
CGSensorValue<double> hum1;
CGSensorValue<int> fan1;
};
class GrowControl : public TfConnectionListener {
private:
static log4cpp::Category& logger;
LCD lcd;
TfConnection tfConnection;
TfMasterBrick* rootBrick = nullptr;
TfTemperatureBricklet* temp1Bricklet = nullptr;
TfTemperatureBricklet* temp2Bricklet = nullptr;
TfHumidityBricklet* hum1Bricklet = nullptr;
TfIO16Bricklet* io16Bricklet = nullptr;
std::mutex controlMutex;
unsigned int sleepDuration = 1;
bool mainLoopFlag = true;
public:
GrowControl();
virtual ~GrowControl();
bool connect(std::string host , uint16_t port, bool retry = true);
void newDeviceCallback(TfConnection& conn, TfDevice& device);
void shutdownCallback();
void mainLoop();
double getTemp1();
double getTemp2();
double getHum1();
int getFan1();
};
} /* namespace growcontrol */
#endif /* GROWCONTROL_H_ */
+156
View File
@@ -0,0 +1,156 @@
/*
* IPCManager.cpp
*
* Created on: 15.06.2014
* Author: matzman
*/
#include "IPCManager.h"
#include "GCException.h"
#include <algorithm>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
namespace growcontrol {
log4cpp::Category& IPCManager::logger = log4cpp::Category::getInstance("growcontrol.ipc");
void IPCManager::listenerThreadFunc(IPCManager* obj) {
logger << log4cpp::Priority::INFO << "Starting ipc listener.";
while(obj->listenerThreadFlag) {
int cSocketFD;
// accept connection
if ((cSocketFD = accept(obj->socketFD, nullptr, nullptr)) == -1) {
perror("Error while trying to accept incoming connection");
logger << log4cpp::Priority::ERROR << "Error while trying to accept incoming connection";
} else {
logger << log4cpp::Priority::INFO << "Successfully accepted new ipc connection.";
// Now we create a new thread that handles the established connection
std::thread* handleThread = new std::thread(workerThreadFunc, obj, cSocketFD, handleThread);
obj->workerThreads.insert(handleThread);
}
}
}
void IPCManager::workerThreadFunc(IPCManager* obj, int socket, std::thread* self) {
// To something
bool loopFlag = true;
while (loopFlag) {
char buffer[100];
std::string response;
// Receive command
int rsize = recv(socket, buffer, sizeof(buffer), 0);
if (rsize == 0) { // Connection closed
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.";
loopFlag = false;
} else {
// Check if '\0' appears in command (our end-of-command)
int msglen = strnlen(buffer, sizeof(buffer));
if (msglen <= 0 || msglen >= (int)sizeof(buffer)) {
logger << log4cpp::Priority::ERROR << "received faulty ipc data.";
loopFlag = false;
} else {
// Parse command
std::istringstream commandStream(buffer);
std::string firstPart;
std::getline(commandStream, firstPart, ' ');
std::transform(firstPart.begin(), firstPart.end(), firstPart.begin(), ::toupper);
if (firstPart.compare("GETVAL") == 0) { // get value command (several arguments)
std::vector<std::string> args;
for (std::string arg; std::getline(commandStream, arg, ' '); ) {
args.push_back(arg);
}
if (args.size() == 0) {
response = "ERROR NO_ARGS";
} else {
response = obj->handleGetValCommand(args);
}
} else if (firstPart.compare("SET") == 0) { // set command
response = "ERROR TODO";
} else {
logger << log4cpp::Priority::ERROR << "Received unknown ipc command: " << buffer << ".";
response = "ERROR UNKNOWN_COMMAND";
}
if (!response.empty()) {
int ssize = send(socket, response.c_str(), response.size() + 1 , 0);
if (ssize <= 0) {
logger << log4cpp::Priority::ERROR << "error while sending ipc response: " << response << ".";
loopFlag = false;
}
}
}
}
}
// Cleanup resources
close(socket);
obj->workerThreads.erase(self);
}
IPCManager::IPCManager() {}
void IPCManager::init(GrowControl& growControl, std::string socketPath) {
this->growControl = &growControl;
this->socketPath = socketPath;
// Create Socket
if ((socketFD = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
logger << log4cpp::Priority::ERROR << "Could not create socket";
throw GCException("Could not create socket", GCErrorCode::OTHER_ERROR);
}
// Create address struct
struct sockaddr_un local;
local.sun_family = AF_UNIX;
strncpy(local.sun_path, socketPath.c_str(), sizeof(local.sun_path));
// Unlink the socket path (remove possible remains?)
unlink(local.sun_path);
// bind socket
if (bind(socketFD, (struct sockaddr *)&local, sizeof(local)) == -1) {
logger << log4cpp::Priority::ERROR << "Could not bind socket";
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";
throw GCException("Could not switch socket to accepting mode", GCErrorCode::OTHER_ERROR);
}
logger << log4cpp::Priority::INFO << "Successfully created new ipc socket " << socketPath << ".";
listenerThreadFlag = true;
listenerThread = new std::thread(listenerThreadFunc, this);
}
IPCManager::~IPCManager() {
if (socketFD > 0) {
close(socketFD);
unlink(socketPath.c_str());
}
if (listenerThread != nullptr) {
listenerThreadFlag = false;
listenerThread->join();
delete listenerThread;
}
std::set<std::thread*> workers(workerThreads);
for (auto w : workers) {
w->join();
delete w;
}
}
std::string IPCManager::handleGetValCommand(std::vector<std::string> args) {
return "ERROR TODO";
}
} /* namespace growcontrol */
+47
View File
@@ -0,0 +1,47 @@
/*
* IPCManager.h
*
* Created on: 15.06.2014
* Author: matzman
*/
#ifndef IPCMANAGER_H_
#define IPCMANAGER_H_
#include <string>
#include <thread>
#include <set>
#include <log4cpp/Category.hh>
namespace growcontrol {
class GrowControl;
class IPCManager {
private:
static log4cpp::Category& logger;
GrowControl* growControl = nullptr;
std::string socketPath;
int socketFD = -1;
std::thread* listenerThread = nullptr;
bool listenerThreadFlag = false;
std::set<std::thread*> workerThreads;
public:
IPCManager();
virtual ~IPCManager();
void init(GrowControl& growControl, std::string socketPath);
static void listenerThreadFunc(IPCManager* obj);
static void workerThreadFunc(IPCManager* obj, int socket, std::thread* self);
std::string handleGetValCommand(std::vector<std::string> args);
};
} /* namespace growcontrol */
#endif /* IPCMANAGER_H_ */
+182
View File
@@ -0,0 +1,182 @@
/*
* LCD.cpp
*
* Created on: 15.06.2014
* Author: matzman
*/
#include "LCD.h"
#include "GCException.h"
namespace growcontrol {
log4cpp::Category& LCD::logger = log4cpp::Category::getInstance("growcontrol");
LCD::LCD() : pageRoot(*this) {
activePage = &pageRoot;
for (int t = 0; t < 4; t++) {
for (int i = 0; i < 20; i++) {
lcdBuffer[t][i] = ' ';
}
}
lcdBuffer[0][20] = '\0';
lcdBuffer[1][20] = '\0';
lcdBuffer[2][20] = '\0';
lcdBuffer[3][20] = '\0';
}
LCD::~LCD() {
}
bool LCD::isLCDConnected() {
return (lcdBricklet != nullptr && lcdBricklet->getDeviceState() == TfDeviceState::CONNECTED);
}
void LCD::startLightCountdown() {
if (!lcdLightCountdownFlag) {
lcdLightCountdown = lcdLightMaxCountdown;
lcdLightCountdownFlag = true;
}
}
void LCD::stopLightCountdown() {
lcdLightCountdownFlag = false;
}
void LCD::resetLightCountdown() {
lcdLightCountdown = lcdLightMaxCountdown;
}
void LCD::setLight(bool light) {
if (!light) {
stopLightCountdown();
activePage = &pageRoot;
activePage->refreshDisplay();
lcdLightCountdown = -1;
if (lcdBricklet != nullptr && lcdBricklet->getDeviceState() == TfDeviceState::CONNECTED) {
lcdBricklet->setBacklight(false);
}
} else {
startLightCountdown();
if (lcdBricklet != nullptr && lcdBricklet->getDeviceState() == TfDeviceState::CONNECTED) {
lcdBricklet->setBacklight(true);
}
}
}
void LCD::setTfObject(TfLCD20x4Bricklet& lcd) {
if ( (lcdBricklet == nullptr || lcdBricklet->getDeviceState() != TfDeviceState::CONNECTED)
&& lcd.getDeviceState() == TfDeviceState::AVAILABLE ) {
if (lcdBricklet != nullptr) {
lcdBricklet->removeLcdListener(*this);
}
lcdBricklet = &lcd;
lcdBricklet->addLcdListener(*this);
lcdBricklet->connect();
setLight(true);
lcdBricklet->setCursor(false, false);
lcdBricklet->clearDisplay();
if (activePage != nullptr) {
activePage->refreshDisplay();
}
logger << log4cpp::Priority::INFO << "Added lcd device " << lcd.getDeviceName(true) << ".";
}
}
void LCD::buttonStateCallback(TfLCD20x4Bricklet& lcd, uint8_t button, bool state) {
if (lcdLightCountdown < 0) {
if (state) {
setLight(true);
}
} else if (&lcd == lcdBricklet && activePage != nullptr) {
resetLightCountdown();
activePage->buttonStateCallback(button, state);
}
}
void LCD::writeLine(int line, std::string txt) {
std::lock_guard<std::mutex> lock(lcdMutex);
snprintf(lcdBuffer[line], 21, "%-20.20s", txt.c_str());
lineFlags[line] = true;
}
int LCD::writeLCDBuffer() {
std::lock_guard<std::mutex> lock(lcdMutex);
int written = 0;
if (lcdBricklet != nullptr) {
if (lcdBricklet->getDeviceState() == TfDeviceState::CONNECTED) {
try {
for (int t = 0; t < 4; t++) {
if (lineFlags[t] == true) {
lcdBricklet->writeLine(t, 0, lcdBuffer[t]);
lineFlags[t] = false;
written++;
}
}
} catch (TfError &e) {
std::ostringstream ss;
ss << "unknown exception while writing lcd: " << e.what();
throw GCException(ss.str(), GCErrorCode::UNKNOWN_TFERROR);
}
} else {
throw GCException("lcd not connected.", GCErrorCode::SENSOR_DISCONNECTED);
}
} else {
throw GCException("No lcd present.", GCErrorCode::NO_SENSOR);
}
return written;
}
void LCD::stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate) {
if (newstate == TfDeviceState::CONNECTED) {
clearDisplay();
activePage->refreshDisplay();
}
if (&device == lcdBricklet && activePage != nullptr) {
activePage->stateChangeCallback(device, oldstate, newstate);
}
}
void LCD::setActivePage(LCDPage& page, bool reset) {
activePage = &page;
if (reset) {
page.reset();
}
clearDisplay();
page.refreshDisplay();
}
void LCD::controlMainLoopCallback(GCSensorsInfo& sensors) {
if (activePage != nullptr) {
activePage->controlMainLoopCallback(sensors);
}
if (lcdLightCountdownFlag && lcdLightCountdown > 0) {
lcdLightCountdown--;
} else if (lcdLightCountdownFlag && lcdLightCountdown == 0) {
setLight(false);
}
}
void LCD::clearDisplay() {
for (int t = 0; t < 4; t++) {
for (int i = 0; i < 20; i++) {
lcdBuffer[t][i] = ' ';
}
}
lcdBuffer[0][20] = '\0';
lcdBuffer[1][20] = '\0';
lcdBuffer[2][20] = '\0';
lcdBuffer[3][20] = '\0';
if (isLCDConnected()) {
try {
lcdBricklet->clearDisplay();
} catch (TfError &e) {
}
}
}
} /* namespace growcontrol */
+65
View File
@@ -0,0 +1,65 @@
/*
* LCD.h
*
* Created on: 15.06.2014
* Author: matzman
*/
#ifndef LCD_H_
#define LCD_H_
#include "TfCPPsimple.h"
#include "lcdpages/MainPage.h"
#include <mutex>
using namespace tfcppsimple;
namespace growcontrol {
struct GCSensorsInfo;
class LCD : public TfLCD20x4Listener, public TfDeviceStateListener {
private:
static log4cpp::Category& logger;
TfLCD20x4Bricklet* lcdBricklet = nullptr;
std::mutex lcdMutex;
char lcdBuffer[4][21];
bool lineFlags[4] = {false, false, false, false};
int lcdLightCountdown = 0;
int lcdLightMaxCountdown = 10;
bool lcdLightCountdownFlag = false;
LCDPage* activePage = nullptr;
MainPage pageRoot;
public:
LCD();
virtual ~LCD();
void setTfObject(TfLCD20x4Bricklet& lcd);
void buttonStateCallback(TfLCD20x4Bricklet& lcd, uint8_t button, bool state);
void stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate);
void writeLine(int line, std::string txt);
int writeLCDBuffer();
void clearDisplay();
void setActivePage(LCDPage& page, bool reset = false);
void startLightCountdown();
void stopLightCountdown();
void resetLightCountdown();
void setLight(bool light);
void controlMainLoopCallback(GCSensorsInfo& sensors);
bool isLCDConnected();
};
} /* namespace growcontrol */
#endif /* LCD_H_ */
+39
View File
@@ -0,0 +1,39 @@
/*
* LCDPage.h
*
* Created on: 15.06.2014
* Author: matzman
*/
#ifndef LCDPAGE_H_
#define LCDPAGE_H_
#include "TfCPPsimple.h"
using namespace tfcppsimple;
namespace growcontrol {
class LCD;
struct GCSensorsInfo;
class LCDPage {
protected:
LCD& lcd;
LCDPage* parent;
public:
LCDPage(LCD& lcd, LCDPage* parent = nullptr) : lcd(lcd), parent(parent) {}
virtual ~LCDPage() {}
virtual void reset() = 0;
virtual void refreshDisplay() = 0;
virtual void buttonStateCallback(uint8_t button, bool state) = 0;
virtual void stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate) = 0;
virtual void controlMainLoopCallback(GCSensorsInfo& sensors) = 0;
};
} /* namespace growcontrol */
#endif /* LCDPAGE_H_ */
+7
View File
@@ -0,0 +1,7 @@
SRC_FILES += src/main.cpp \
src/GrowControl.cpp \
src/LCD.cpp \
src/IPCManager.cpp
include src/lcdpages/config.mk
+52
View File
@@ -0,0 +1,52 @@
/*
* AboutPage.cpp
*
* Created on: 15.06.2014
* Author: matzman
*/
#include "AboutPage.h"
#include "../LCD.h"
#include "../GCException.h"
namespace growcontrol {
AboutPage::AboutPage(LCD& lcd, LCDPage* parent) : LCDPage(lcd, parent) {
}
AboutPage::~AboutPage() {
}
void AboutPage::reset() {
}
void AboutPage::refreshDisplay() {
if (lcd.isLCDConnected()) {
lcd.clearDisplay();
lcd.writeLine(1, " GrowControl v1.0");
lcd.writeLine(2, " by Matzman, 2014");
try {
lcd.writeLCDBuffer();
} catch (GCException &e) {
}
}
}
void AboutPage::buttonStateCallback(uint8_t button, bool state) {
if (state) {
lcd.setActivePage(*parent);
}
}
void AboutPage::stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate) {
}
void AboutPage::controlMainLoopCallback(GCSensorsInfo& sensors) {
}
} /* namespace growcontrol */
+31
View File
@@ -0,0 +1,31 @@
/*
* AboutPage.h
*
* Created on: 15.06.2014
* Author: matzman
*/
#ifndef ABOUTPAGE_H_
#define ABOUTPAGE_H_
#include "../LCDPage.h"
#include <string>
namespace growcontrol {
class AboutPage: public LCDPage {
public:
AboutPage(LCD& lcd, LCDPage* parent);
virtual ~AboutPage();
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 /* ABOUTPAGE_H_ */
+48
View File
@@ -0,0 +1,48 @@
/*
* FanSettings.cpp
*
* Created on: 15.06.2014
* Author: matzman
*/
#include "FanSettings.h"
#include "../LCD.h"
#include "../GCException.h"
namespace growcontrol {
FanSettings::FanSettings(LCD& lcd, LCDPage* parent) : LCDPage(lcd, parent) {
}
FanSettings::~FanSettings() {
}
void FanSettings::reset() {
}
void FanSettings::refreshDisplay() {
if (lcd.isLCDConnected()) {
lcd.clearDisplay();
lcd.writeLine(0, "Fan Settings:");
lcd.writeLine(1, " ToDo");
try {
lcd.writeLCDBuffer();
} catch (GCException &e) {
}
}
}
void FanSettings::buttonStateCallback(uint8_t button, bool state) {
if (state) {
lcd.setActivePage(*parent);
}
}
void FanSettings::stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate) {
}
void FanSettings::controlMainLoopCallback(GCSensorsInfo& sensors) {
}
} /* namespace growcontrol */
+31
View File
@@ -0,0 +1,31 @@
/*
* FanSettings.h
*
* Created on: 15.06.2014
* Author: matzman
*/
#ifndef FANSETTINGS_H_
#define FANSETTINGS_H_
#include "../LCDPage.h"
#include <string>
namespace growcontrol {
class FanSettings : public LCDPage {
public:
FanSettings(LCD& lcd, LCDPage* parent);
virtual ~FanSettings();
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 /* FANSETTINGS_H_ */
+113
View File
@@ -0,0 +1,113 @@
/*
* MainMenu.cpp
*
* Created on: 15.06.2014
* Author: matzman
*/
#include "MainMenu.h"
#include "../LCD.h"
#include "../GCException.h"
namespace growcontrol {
MainMenu::MainMenu(LCD& lcd, LCDPage* parent) : LCDPage(lcd, parent),
aboutPage(lcd, this), fanSettings(lcd, this), pcSettings(lcd, this) {
items.push_back("Fan Settings");
items.push_back("PC Control");
items.push_back("About");
items.push_back("Back");
}
MainMenu::~MainMenu() {
}
void MainMenu::reset() {
itemsStart = 0;
cursorPos = 0;
}
void MainMenu::refreshDisplay() {
if (lcd.isLCDConnected()) {
char buffer[21];
lcd.writeLine(0, "Main Menu:");
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) {
}
}
}
void MainMenu::buttonStateCallback(uint8_t button, bool state) {
if (state) {
bool refresh = false;
switch (button) {
case 0: // enter
switch (itemsStart + cursorPos) {
case 0: // Fan Settings
lcd.setActivePage(fanSettings, true);
break;
case 1: // PC Settings
lcd.setActivePage(pcSettings, true);
break;
case 2: // About
lcd.setActivePage(aboutPage, true);
break;
case 3: // back
lcd.setActivePage(*parent, true);
break;
default:
break;
}
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 MainMenu::stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate) {
}
void MainMenu::controlMainLoopCallback(GCSensorsInfo& sensors) {
}
} /* namespace growcontrol */
+44
View File
@@ -0,0 +1,44 @@
/*
* MainMenu.h
*
* Created on: 15.06.2014
* Author: matzman
*/
#ifndef MAINMENU_H_
#define MAINMENU_H_
#include "../LCDPage.h"
#include "AboutPage.h"
#include "FanSettings.h"
#include "PCSettings.h"
#include <vector>
#include <string>
namespace growcontrol {
class MainMenu: public LCDPage {
private:
std::vector<std::string> items;
unsigned itemsStart = 0;
unsigned cursorPos = 0;
AboutPage aboutPage;
FanSettings fanSettings;
PCSettings pcSettings;
public:
MainMenu(LCD& lcd, LCDPage* parent);
virtual ~MainMenu();
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 /* MAINMENU_H_ */
+133
View File
@@ -0,0 +1,133 @@
/*
* MainPage.cpp
*
* Created on: 15.06.2014
* Author: matzman
*/
#include "MainPage.h"
#include "../GrowControl.h"
#include <stdio.h>
namespace growcontrol {
MainPage::MainPage(LCD& lcd) : LCDPage(lcd), menu(lcd, this) {
for (int t = 0; t < 4; t++) {
for (int i = 0; i < 20; i++) {
buffer[t][i] = ' ';
}
}
buffer[0][20] = '\0';
buffer[1][20] = '\0';
buffer[2][20] = '\0';
buffer[3][20] = '\0';
snprintf(buffer[1], 21, "%-20.20s", " GrowControl");
snprintf(buffer[2], 21, "%-20.20s", " loading ...");
}
MainPage::~MainPage() {
}
void MainPage::reset() {
}
void MainPage::refreshDisplay(){
if (lcd.isLCDConnected()) {
lcd.writeLine(0, buffer[0]);
lcd.writeLine(1, buffer[1]);
lcd.writeLine(2, buffer[2]);
lcd.writeLine(3, buffer[3]);
try {
lcd.writeLCDBuffer();
} catch (GCException &e) {
//std::ostringstream ss;
//ss << "unknown exception while writing lcd: " << e.what();
}
}
}
void MainPage::buttonStateCallback(uint8_t button, bool state) {
if (button == 3 && state) {
lcd.setLight(false);
} else if (button == 0 && state) {
lcd.setActivePage(menu, true);
}
}
void MainPage::stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate) {
}
void MainPage::controlMainLoopCallback(GCSensorsInfo& sensors) {
if (lcd.isLCDConnected()) {
char temp1[21];
char temp2[21];
char hum1[21];
char fan1[21];
// temp1
if (sensors.temp1.valid) {
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;
}
}
// temp2
if (sensors.temp2.valid) {
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;
}
}
// hum1
if (sensors.hum1.valid) {
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");
} else {
switch (sensors.fan1.error.getErrorCode()) {
case GCErrorCode::SENSOR_DISCONNECTED:
snprintf(fan1, 21, "DISCON");
break;
default:
snprintf(fan1, 21, " ERROR");
break;
}
}
// line 1
snprintf(buffer[0], 21, "T: %7.7s %7.7s ", temp1, temp2);
// line 2
snprintf(buffer[1], 21, "Humidity: %5.5s ", hum1);
// line 3
snprintf(buffer[2], 21, "Fan: %-15.15s", fan1);
refreshDisplay();
}
}
} /* namespace growcontrol */
+35
View File
@@ -0,0 +1,35 @@
/*
* MainPage.h
*
* Created on: 15.06.2014
* Author: matzman
*/
#ifndef MAINPAGE_H_
#define MAINPAGE_H_
#include "../LCDPage.h"
#include "MainMenu.h"
namespace growcontrol {
class MainPage: public LCDPage {
private:
char buffer[4][21];
MainMenu menu;
public:
MainPage(LCD& lcd);
virtual ~MainPage();
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 /* MAINPAGE_H_ */
+49
View File
@@ -0,0 +1,49 @@
/*
* PCSettings.cpp
*
* Created on: 15.06.2014
* Author: matzman
*/
#include "PCSettings.h"
#include "../LCD.h"
#include "../GCException.h"
namespace growcontrol {
PCSettings::PCSettings(LCD& lcd, LCDPage* parent) : LCDPage(lcd, parent) {
}
PCSettings::~PCSettings() {
// TODO Auto-generated destructor stub
}
void PCSettings::reset() {
}
void PCSettings::refreshDisplay() {
if (lcd.isLCDConnected()) {
lcd.clearDisplay();
lcd.writeLine(0, "PC Control:");
lcd.writeLine(1, " ToDo");
try {
lcd.writeLCDBuffer();
} catch (GCException &e) {
}
}
}
void PCSettings::buttonStateCallback(uint8_t button, bool state) {
if (state) {
lcd.setActivePage(*parent);
}
}
void PCSettings::stateChangeCallback(TfDevice& device, TfDeviceState oldstate, TfDeviceState newstate) {
}
void PCSettings::controlMainLoopCallback(GCSensorsInfo& sensors) {
}
} /* namespace growcontrol */
+31
View File
@@ -0,0 +1,31 @@
/*
* PCSettings.h
*
* Created on: 15.06.2014
* Author: matzman
*/
#ifndef PCSETTINGS_H_
#define PCSETTINGS_H_
#include "../LCDPage.h"
#include <string>
namespace growcontrol {
class PCSettings: public LCDPage {
public:
PCSettings(LCD& lcd, LCDPage* parent);
virtual ~PCSettings();
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 /* PCSETTINGS_H_ */
+6
View File
@@ -0,0 +1,6 @@
SRC_FILES += src/lcdpages/MainPage.cpp \
src/lcdpages/MainMenu.cpp \
src/lcdpages/AboutPage.cpp \
src/lcdpages/FanSettings.cpp \
src/lcdpages/PCSettings.cpp
+37
View File
@@ -0,0 +1,37 @@
/*
* main.cpp
*
* Created on: 10.06.2014
* Author: matzman
*/
#include <TfCPPsimple.h>
#include "GrowControl.h"
#include "IPCManager.h"
#include <unistd.h>
#include <iostream>
#include <sstream>
#include <string>
using namespace tfcppsimple;
using namespace growcontrol;
#define HOST "localhost"
#define PORT 4223
GrowControl controller;
IPCManager ipcManager;
int main(int argc, char **argv) {
TfUtils::configureLog4CPP("log4cpp.config");
controller.connect(HOST, PORT);
sleep(2);
try {
ipcManager.init(controller, "/tmp/growcontrol.socket");
} catch (GCException &e) {
}
controller.mainLoop();
}