Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
hfedcba committed Jun 21, 2017
2 parents 2f3af6f + ef8a494 commit c2ec325
Show file tree
Hide file tree
Showing 39 changed files with 2,202 additions and 60 deletions.
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4 -I cfg
SUBDIRS = basic-logic comment debug function gpio light link mqtt passthrough timers tls-config variable
SUBDIRS = basic-logic comment debug function gpio light link mqtt passthrough template timers tls-config variable
8 changes: 7 additions & 1 deletion basic-logic/switch/MyNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ void MyNode::convertType(Flows::PVariable& value, Flows::VariableType vt)
{
if(vt == Flows::VariableType::tInteger)
{
value->setType(vt);
value->setType(Flows::VariableType::tInteger64);
value->integerValue = Flows::Math::getNumber(value->stringValue);
value->integerValue64 = value->integerValue;
}
else if(vt == Flows::VariableType::tInteger64)
{
Expand Down Expand Up @@ -230,6 +231,11 @@ bool MyNode::match(Rule& rule, Flows::PVariable& value)
{
try
{
if(value->type == Flows::VariableType::tInteger)
{
value->setType(Flows::VariableType::tInteger64);
value->integerValue64 = value->integerValue;
}
if(rule.previousValue)
{
rule.v = _previousInputValue;
Expand Down
2 changes: 1 addition & 1 deletion comment/comment.hni
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
</script>
<script type="text/javascript">
RED.nodes.registerType('comment',{
category: 'function',
category: 'general',
color:"#ffffff",
defaults: {
name: {value:""},
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ esac
#AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [enable debugging, default: no]), [case "${enableval}" in yes) debug=true ;; no) debug=false ;; *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;; esac], [debug=false])
#AM_CONDITIONAL(DEBUG, test x"$debug" = x"true")

AC_OUTPUT(Makefile basic-logic/Makefile comment/Makefile debug/Makefile function/Makefile gpio/Makefile light/Makefile link/Makefile mqtt/Makefile passthrough/Makefile timers/Makefile tls-config/Makefile variable/Makefile)
AC_OUTPUT(Makefile basic-logic/Makefile comment/Makefile debug/Makefile function/Makefile gpio/Makefile light/Makefile link/Makefile mqtt/Makefile passthrough/Makefile template/Makefile timers/Makefile tls-config/Makefile variable/Makefile)
1 change: 0 additions & 1 deletion debug/debug.hni
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,6 @@
} else if (msg.event === "mouseLeave") {
options.messageMouseLeave(msg.id);
} else if (msg.event === "mouseClick") {
console.log("Moin0");
options.messageSourceClick(msg.id);
} else if (msg.event === "clear") {
options.clear();
Expand Down
71 changes: 59 additions & 12 deletions function/function.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?php
declare(strict_types=1);

$nodeInfo;

function getNodeData(string $key)
Expand All @@ -13,50 +15,95 @@ function setNodeData(string $key, $value)
\Homegear\Homegear::setNodeData($nodeInfo['id'], $key, $value);
}

function getFlowData(string $key)
{
global $nodeInfo;
return \Homegear\Homegear::getNodeData($nodeInfo['info']['z'], $key);
}

function setFlowData(string $key, $value)
{
global $nodeInfo;
\Homegear\Homegear::setNodeData($nodeInfo['info']['z'], $key, $value);
}

function getGlobalData(string $key)
{
global $nodeInfo;
return \Homegear\Homegear::getNodeData('global', $key);
}

function setGlobalData(string $key, $value)
{
global $nodeInfo;
\Homegear\Homegear::setNodeData('global', $key, $value);
}

function output(int $outputIndex, array $message)
{
global $nodeInfo;
\Homegear\Homegear::nodeOutput($nodeInfo['id'], $outputIndex, $message);
}

function executeCode(int $inputIndex, array $message)
class HomegearNode extends HomegearNodeBase
{
global $nodeInfo;
$code = $nodeInfo["info"]["func"];
$hg = new \Homegear\Homegear();
return eval($code);

private $hg = NULL;
private $nodeInfo = NULL;

public function __construct()
{
$this->hg = new \Homegear\Homegear();
}

function input(array $localNodeInfo, int $inputIndex, array $message)
public function executeCode(int $inputIndex, array $message)
{
try
{
$code = $this->nodeInfo["info"]["func"];
$hg = new \Homegear\Homegear();
return eval($code);
}
catch(Exception $e)
{
$this->log(2, $e->message);
}
return NULL;
}

public function input(array $nodeInfoLocal, int $inputIndex, array $message)
{
global $nodeInfo;
$nodeInfo = $localNodeInfo;
$result = executeCode($inputIndex, $message);
$nodeInfo = $nodeInfoLocal;
$this->nodeInfo = $nodeInfoLocal;
$result = $this->executeCode($inputIndex, $message);
if($result)
{
if(array_key_exists('payload', $result))
{
\Homegear\Homegear::nodeOutput($nodeInfo['id'], 0, $result);
$this->hg->nodeOutput($this->nodeInfo['id'], 0, $result);
}
else
{
$wireCount = count($nodeInfo['wiresOut']);
$wireCount = count($this->nodeInfo['wiresOut']);
foreach($result as $index => $value)
{
if(!$value || !is_numeric($index) || $index >= $wireCount) continue;
if(array_key_exists('payload', $value))
{
\Homegear\Homegear::nodeOutput($nodeInfo['id'], $index, $value);
$this->hg->nodeOutput($this->nodeInfo['id'], $index, $value);
}
else
{
foreach($value as $value2)
{
if(!$value2) continue;
\Homegear\Homegear::nodeOutput($nodeInfo['id'], $index, $value2);
$this->hg->nodeOutput($this->nodeInfo['id'], $index, $value2);
}
}
}
}
}
}

}
2 changes: 1 addition & 1 deletion function/locales/en-US/function
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"tip": "Tip: See the Info tab for help writing functions.",
"paletteHelp": "<p>A function block where you can write PHP code to do more interesting things.</p>",
"help": "<p>A function block where you can write PHP code to do more interesting things.</p><p>By convention it will have a <code>$message['payload']</code> property containing the body of the message.</p><p>The message is passed in as an associative array called <code>$message</code>. Information about the node can be found in the associative array <code>$nodeInfo</code>. The input index is passed in <code>$inputIndex</code></p><h4>Data storage</h4><p>Data can be stored by calling <code>setNodeData($key, $value)</code> and retrieved with <code>getNodeData($key)</code>.</p><h4>Sending messages</h4><p>The function can either return the messages it wants to pass on to the next nodes in the flow, or can call <code>output($outputIndex, $message)</code>.</p><p>It can return:</p><ul><li>a single message object - passed to nodes connected to the first output</li><li>an array of message objects - passed to nodes connected to the corresponding outputs</li></ul><p>If any element of the array is itself an array of messages, multiple messages are sent to the corresponding output.</p><p>If NULL is returned, either by itself or as an element of the array, no message is passed on.</p><p>See the <a target=\"_blank\" href=\"https://ref.homegear.eu\">online reference</a> for more help.</p>"
"help": "<p>A function block where you can write PHP code to do more interesting things.</p><p>By convention it will have a <code>$message['payload']</code> property containing the body of the message.</p><p>The message is passed in as an associative array called <code>$message</code>. Information about the node can be found in the associative array <code>$nodeInfo</code>. The input index is passed in <code>$inputIndex</code></p><h4>Data storage</h4><p>Data can be stored by calling <code>setNodeData($key, $value)</code>, <code>setFlowData($key, $value)</code> or <code>setGlobalData($key, $value)</code> and retrieved with <code>getNodeData($key)</code>, <code>getFlowData($key)</code> or <code>getGlobalData($key)</code>.</p><h4>Sending messages</h4><p>The function can either return the messages it wants to pass on to the next nodes in the flow, or can call <code>output($outputIndex, $message)</code>.</p><p>It can return:</p><ul><li>a single message object - passed to nodes connected to the first output</li><li>an array of message objects - passed to nodes connected to the corresponding outputs</li></ul><p>If any element of the array is itself an array of messages, multiple messages are sent to the corresponding output.</p><p>If NULL is returned, either by itself or as an element of the array, no message is passed on.</p><p>See the <a target=\"_blank\" href=\"https://ref.homegear.eu\">online reference</a> for more help.</p>"
}
}
}
174 changes: 165 additions & 9 deletions light/MyNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,17 @@ bool MyNode::init(Flows::PNodeInfo info)
}

settingsIterator = info->info->structValue->find("lighttype");
if(settingsIterator != info->info->structValue->end()) _isDimmer = settingsIterator->second->stringValue == "dimmer";
if(settingsIterator != info->info->structValue->end())
{
std::string lightType = settingsIterator->second->stringValue;
if(lightType == "dimmerstate") _lightType = LightType::dimmerState;
else if(lightType == "dimmer") _lightType = LightType::dimmer;
}

settingsIterator = info->info->structValue->find("twoinputs");
if(settingsIterator != info->info->structValue->end()) _twoInputs = settingsIterator->second->booleanValue;

if(_isDimmer)
if(_lightType == LightType::dimmerState)
{
std::string offValue = "0";
settingsIterator = info->info->structValue->find("offvalue");
Expand All @@ -90,6 +95,52 @@ bool MyNode::init(Flows::PNodeInfo info)
if(offValue.find('.') != std::string::npos) _offValue = std::make_shared<Flows::Variable>(Flows::Math::getDouble(offValue));
else _offValue = std::make_shared<Flows::Variable>(Flows::Math::getNumber(offValue));
}
else if(_lightType == LightType::dimmer)
{
std::string offValue = "0";
settingsIterator = info->info->structValue->find("offvalue2");
if(settingsIterator != info->info->structValue->end()) offValue = settingsIterator->second->stringValue;

std::string minValue = "15";
settingsIterator = info->info->structValue->find("minvalue");
if(settingsIterator != info->info->structValue->end()) minValue = settingsIterator->second->stringValue;

std::string maxValue = "0";
settingsIterator = info->info->structValue->find("maxvalue");
if(settingsIterator != info->info->structValue->end()) maxValue = settingsIterator->second->stringValue;

settingsIterator = info->info->structValue->find("step");
if(settingsIterator != info->info->structValue->end()) _step = Flows::Math::getDouble(settingsIterator->second->stringValue);
if(_step <= 0.0) _step = 0.001;

settingsIterator = info->info->structValue->find("factor");
if(settingsIterator != info->info->structValue->end()) _factor = Flows::Math::getDouble(settingsIterator->second->stringValue);
if(_factor < 0) _factor = 0;

settingsIterator = info->info->structValue->find("interval");
if(settingsIterator != info->info->structValue->end()) _interval = Flows::Math::getDouble(settingsIterator->second->stringValue);
if(_interval < 10) _interval = 10;

if(offValue.find('.') != std::string::npos) _offValue = std::make_shared<Flows::Variable>(Flows::Math::getDouble(offValue));
else _offValue = std::make_shared<Flows::Variable>(Flows::Math::getNumber(offValue));

if(minValue.find('.') != std::string::npos) _minValue = std::make_shared<Flows::Variable>(Flows::Math::getDouble(minValue));
else
{
_minValue = std::make_shared<Flows::Variable>(Flows::Math::getNumber(minValue));
_minValue->floatValue = _minValue->integerValue;
}

if(maxValue.find('.') != std::string::npos) _maxValue = std::make_shared<Flows::Variable>(Flows::Math::getDouble(maxValue));
else
{
_maxValue = std::make_shared<Flows::Variable>(Flows::Math::getNumber(maxValue));
_maxValue->floatValue = _maxValue->integerValue;
}

_onValue = getNodeData("currentvalue");
if(!(*_onValue)) _onValue = _maxValue;
}
else
{
_onValue = std::make_shared<Flows::Variable>(true);
Expand All @@ -109,22 +160,127 @@ bool MyNode::init(Flows::PNodeInfo info)
return false;
}

void MyNode::input(Flows::PNodeInfo info, uint32_t index, Flows::PVariable message)
void MyNode::stop()
{
try
{
_stopThread = true;
}
catch(const std::exception& ex)
{
Flows::Output::printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
}
catch(...)
{
Flows::Output::printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
}
}

void MyNode::waitForStop()
{
try
{
std::lock_guard<std::mutex> timerGuard(_timerMutex);
if(_timerThread.joinable()) _timerThread.join();
}
catch(const std::exception& ex)
{
Flows::Output::printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
}
catch(...)
{
Flows::Output::printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
}
}

void MyNode::dim(bool up)
{
try
{
bool value = message->structValue->at("payload")->booleanValue;
if(_twoInputs && !value) return;
bool state = _twoInputs ? (index == 0 ? true : false) : value;
Flows::PArray parameters = std::make_shared<Flows::Array>();
parameters->reserve(4);
parameters->push_back(std::make_shared<Flows::Variable>(_peerId));
parameters->push_back(std::make_shared<Flows::Variable>(_channel));
parameters->push_back(std::make_shared<Flows::Variable>(_variable));
parameters->push_back(state ? _onValue : _offValue);
Flows::PVariable startValue = invoke("getValue", parameters);

double currentValue = 0;
if(startValue->type == Flows::VariableType::tInteger) currentValue = startValue->integerValue;
else if(startValue->type == Flows::VariableType::tInteger64) currentValue = startValue->integerValue64;
else
{
startValue->type = Flows::VariableType::tFloat;
currentValue = startValue->floatValue;
}

Flows::PVariable result = invoke("setValue", parameters);
if(result->errorStruct) Flows::Output::printError("Error setting variable (Peer ID: " + std::to_string(_peerId) + ", channel: " + std::to_string(_channel) + ", name: " + _variable + "): " + result->structValue->at("faultString")->stringValue);
parameters->push_back(startValue);

while(!_stopThread)
{
if(up) currentValue += (_step + (_factor * currentValue));
else currentValue -= (_step + (_factor * currentValue));

if(currentValue > _maxValue->floatValue) currentValue = _maxValue->floatValue;
else if(currentValue < _minValue->floatValue) currentValue = _minValue->floatValue;

if(startValue->type == Flows::VariableType::tInteger) parameters->at(3)->integerValue = std::lround(currentValue);
else if(startValue->type == Flows::VariableType::tInteger64) parameters->at(3)->integerValue64 = std::lround(currentValue);
else if(startValue->type == Flows::VariableType::tFloat) parameters->at(3)->floatValue = currentValue;
invoke("setValue", parameters);
std::this_thread::sleep_for(std::chrono::milliseconds(_interval));
if(up && currentValue == _maxValue->floatValue) break;
else if(!up && currentValue == _minValue->floatValue) break;
}

setNodeData("currentvalue", startValue);
_onValue = startValue;
}
catch(const std::exception& ex)
{
Flows::Output::printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__, ex.what());
}
catch(...)
{
Flows::Output::printEx(__FILE__, __LINE__, __PRETTY_FUNCTION__);
}
}

void MyNode::input(Flows::PNodeInfo info, uint32_t index, Flows::PVariable message)
{
try
{
bool value = *(message->structValue->at("payload"));

if(_lightType == LightType::dimmer && index > 0)
{
std::lock_guard<std::mutex> timerGuard(_timerMutex);
_stopThread = true;
if(value)
{
if(_timerThread.joinable()) _timerThread.join();
_stopThread = false;
_timerThread = std::thread(&MyNode::dim, this, index == 1);
}
else
{
if(_timerThread.joinable()) _timerThread.join();
}
}
else
{
Flows::PArray parameters = std::make_shared<Flows::Array>();
parameters->reserve(4);
parameters->push_back(std::make_shared<Flows::Variable>(_peerId));
parameters->push_back(std::make_shared<Flows::Variable>(_channel));
parameters->push_back(std::make_shared<Flows::Variable>(_variable));

if(_twoInputs && !value) return;
bool state = _twoInputs ? (index == 0 ? true : false) : value;
parameters->push_back(state ? _onValue : _offValue);

Flows::PVariable result = invoke("setValue", parameters);
if(result->errorStruct) Flows::Output::printError("Error setting variable (Peer ID: " + std::to_string(_peerId) + ", channel: " + std::to_string(_channel) + ", name: " + _variable + "): " + result->structValue->at("faultString")->stringValue);
}
}
catch(const std::exception& ex)
{
Expand Down
Loading

0 comments on commit c2ec325

Please sign in to comment.