Initial commit.
This commit is contained in:
@@ -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=""${workspace_loc:/TinkerforgeCPPsimple/include}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/TinkerforgeCPPsimple/third-party/tinkerforge/include}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/TinkerforgeCPPsimple/third-party/log4cpp/include}""/>
|
||||||
|
</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=""${workspace_loc:/TinkerforgeCPPsimple/include}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/TinkerforgeCPPsimple/third-party/tinkerforge/include}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/TinkerforgeCPPsimple/third-party/log4cpp/include}""/>
|
||||||
|
</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=""${workspace_loc:/TinkerforgeCPPsimple/include}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/TinkerforgeCPPsimple/third-party/tinkerforge/include}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/TinkerforgeCPPsimple/third-party/log4cpp/include}""/>
|
||||||
|
</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>
|
||||||
@@ -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>
|
||||||
@@ -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 "${INPUTS}" -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>
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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_ */
|
||||||
@@ -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 */
|
||||||
@@ -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_ */
|
||||||
@@ -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 */
|
||||||
@@ -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
@@ -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 */
|
||||||
@@ -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_ */
|
||||||
@@ -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_ */
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
SRC_FILES += src/main.cpp \
|
||||||
|
src/GrowControl.cpp \
|
||||||
|
src/LCD.cpp \
|
||||||
|
src/IPCManager.cpp
|
||||||
|
|
||||||
|
include src/lcdpages/config.mk
|
||||||
@@ -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 */
|
||||||
@@ -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_ */
|
||||||
@@ -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 */
|
||||||
@@ -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_ */
|
||||||
@@ -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 */
|
||||||
@@ -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_ */
|
||||||
@@ -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 */
|
||||||
@@ -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_ */
|
||||||
@@ -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 */
|
||||||
@@ -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_ */
|
||||||
@@ -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
|
||||||
@@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user