180 lines
3.2 KiB
C++
180 lines
3.2 KiB
C++
/*
|
|
* RelayNode.cpp
|
|
* Homie Node for a Relay with optional status indicator LED
|
|
*
|
|
* Version: 1.1
|
|
* Author: Lübbe Onken (http://github.com/luebbe)
|
|
*/
|
|
|
|
#include "RelayNode.hpp"
|
|
|
|
RelayNode::RelayNode(const char *name, const int relayPin, const int ledPin, const bool reverseSignal)
|
|
: HomieNode(name, "RelayNode", "actor")
|
|
{
|
|
_relayPin = relayPin;
|
|
_ledPin = ledPin;
|
|
if (reverseSignal)
|
|
{
|
|
_relayOnValue = LOW;
|
|
_relayOffValue = HIGH;
|
|
}
|
|
else
|
|
{
|
|
_relayOnValue = HIGH;
|
|
_relayOffValue = LOW;
|
|
}
|
|
advertise("on")
|
|
.setDatatype("boolean")
|
|
.settable();
|
|
|
|
advertise("timeout")
|
|
.setDatatype("integer")
|
|
.settable();
|
|
}
|
|
|
|
HomieInternals::Uptime relayUptime;
|
|
|
|
bool RelayNode::handleOnOff(const String &value)
|
|
{
|
|
if (value == "true" || value == "false")
|
|
{
|
|
setRelay(value == "true");
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
#define IS_INTEGER(s) (s == String(s.toInt()))
|
|
|
|
bool RelayNode::handleTimeout(const String &value)
|
|
{
|
|
if (IS_INTEGER(value))
|
|
{
|
|
long timeout = value.toInt();
|
|
if (timeout > 0)
|
|
{
|
|
setRelay(true, timeout);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool RelayNode::handleInput(const HomieRange &range, const String &property, const String &value)
|
|
{
|
|
Homie.getLogger() << "Message: " << property << " " << value << endl;
|
|
|
|
if (property.equals("on"))
|
|
{
|
|
return handleOnOff(value);
|
|
}
|
|
else if (property.equals("timeout"))
|
|
{
|
|
return handleTimeout(value);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void RelayNode::printCaption()
|
|
{
|
|
Homie.getLogger() << cCaption << endl;
|
|
}
|
|
|
|
void RelayNode::setLed(bool on)
|
|
{
|
|
if (_ledPin > DEFAULTPIN)
|
|
{
|
|
digitalWrite(_ledPin, on ? LOW : HIGH); // LOW = LED on
|
|
}
|
|
}
|
|
|
|
void RelayNode::setRelay(bool on, long timeoutSecs)
|
|
{
|
|
printCaption();
|
|
|
|
if (_relayPin > DEFAULTPIN)
|
|
{
|
|
setRelayState(on);
|
|
if (on && timeoutSecs > 0)
|
|
{
|
|
_timeout = relayUptime.getSeconds() + timeoutSecs;
|
|
}
|
|
else
|
|
{
|
|
_timeout = 0;
|
|
}
|
|
sendState();
|
|
}
|
|
else
|
|
{
|
|
Homie.getLogger() << cIndent << "No Relay Pin!" << endl;
|
|
}
|
|
setLed(on);
|
|
}
|
|
|
|
void RelayNode::sendState()
|
|
{
|
|
bool on = getRelayState();
|
|
Homie.getLogger() << cIndent << "Relay is " << (on ? "on" : "off") << endl;
|
|
if (Homie.isConnected())
|
|
{
|
|
setProperty("on").send(on ? "true" : "false");
|
|
setProperty("timeout").send(String(long(_timeout)));
|
|
}
|
|
}
|
|
|
|
void RelayNode::setRelayState(bool on)
|
|
{
|
|
digitalWrite(_relayPin, on ? _relayOnValue : _relayOffValue);
|
|
}
|
|
|
|
bool RelayNode::getRelayState()
|
|
{
|
|
return digitalRead(_relayPin) == _relayOnValue;
|
|
}
|
|
|
|
void RelayNode::toggleRelay()
|
|
{
|
|
setRelay(!getRelayState());
|
|
}
|
|
|
|
void RelayNode::setupRelay()
|
|
{
|
|
pinMode(_relayPin, OUTPUT);
|
|
}
|
|
|
|
void RelayNode::setup()
|
|
{
|
|
printCaption();
|
|
|
|
Homie.getLogger() << cIndent << "Relay Pin: " << _relayPin << endl
|
|
<< cIndent << "Led Pin : " << _ledPin << endl;
|
|
|
|
if (_ledPin > DEFAULTPIN)
|
|
{
|
|
pinMode(_ledPin, OUTPUT);
|
|
setLed(false);
|
|
}
|
|
|
|
if (_relayPin > DEFAULTPIN)
|
|
{
|
|
setupRelay();
|
|
setRelay(false);
|
|
}
|
|
}
|
|
|
|
void RelayNode::loop()
|
|
{
|
|
relayUptime.update();
|
|
if ((_timeout > 0) && getRelayState() && (_timeout < relayUptime.getSeconds()))
|
|
{
|
|
setRelay(false);
|
|
}
|
|
}
|