Updated with reed relais and debouncing button
This commit is contained in:
139
lib/HomieNodes/ButtonNode.cpp
Normal file
139
lib/HomieNodes/ButtonNode.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* ButtonNode.cpp
|
||||
* Homie Node for a button with optional callback function
|
||||
*
|
||||
* Version: 1.0
|
||||
* Author: Lübbe Onken (http://github.com/luebbe)
|
||||
*/
|
||||
|
||||
#include "ButtonNode.hpp"
|
||||
|
||||
ButtonNode::ButtonNode(const char *name,
|
||||
const int buttonPin,
|
||||
TButtonPressCallback buttonPressCallback,
|
||||
TButtonChangeCallback buttonChangeCallback)
|
||||
: HomieNode(name, "ButtonNode", "sensor")
|
||||
{
|
||||
_buttonPin = buttonPin;
|
||||
_buttonPressCallback = buttonPressCallback;
|
||||
_buttonChangeCallback = buttonChangeCallback;
|
||||
}
|
||||
|
||||
void ButtonNode::handleButtonPress(unsigned long dt)
|
||||
{
|
||||
if (Homie.isConnected())
|
||||
{
|
||||
setProperty("duration").send(String(dt));
|
||||
}
|
||||
|
||||
printCaption();
|
||||
Homie.getLogger() << cIndent << "pressed: " << dt << " ms" << endl;
|
||||
|
||||
if (_buttonPressCallback)
|
||||
{
|
||||
_buttonPressCallback();
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonNode::handleButtonChange(bool down) {
|
||||
if (Homie.isConnected())
|
||||
{
|
||||
setProperty("down").send(down ? "true" : "false");
|
||||
}
|
||||
|
||||
printCaption();
|
||||
Homie.getLogger() << cIndent << (down ? "down" : "up") << endl;
|
||||
|
||||
if (_buttonChangeCallback)
|
||||
{
|
||||
_buttonChangeCallback(down);
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonNode::onPress(TButtonPressCallback buttonCallback)
|
||||
{
|
||||
_buttonPressCallback = buttonCallback;
|
||||
}
|
||||
|
||||
void ButtonNode::onChange(TButtonChangeCallback buttonCallback)
|
||||
{
|
||||
_buttonChangeCallback = buttonCallback;
|
||||
}
|
||||
|
||||
void ButtonNode::setMinButtonDownTime(unsigned short downTime)
|
||||
{
|
||||
_minButtonDownTime = downTime;
|
||||
}
|
||||
|
||||
void ButtonNode::setMaxButtonDownTime(unsigned short downTime)
|
||||
{
|
||||
_maxButtonDownTime = downTime;
|
||||
}
|
||||
|
||||
void ButtonNode::printCaption()
|
||||
{
|
||||
Homie.getLogger() << cCaption << endl;
|
||||
}
|
||||
|
||||
void ButtonNode::loop()
|
||||
{
|
||||
// Detect a single press between 90ms and 900ms
|
||||
// This could be improved to detect multiple quick or long presses
|
||||
// and:
|
||||
// a) report them via MQTT
|
||||
// b) react by calling different callbacks
|
||||
if (_buttonPin > DEFAULTPIN)
|
||||
{
|
||||
byte reading = digitalRead(_buttonPin);
|
||||
|
||||
if (reading != _lastReading) {
|
||||
// reset the debouncing timer
|
||||
_lastDebounceTime = millis();
|
||||
}
|
||||
|
||||
if ((millis() - _lastDebounceTime) > _minButtonDownTime) {
|
||||
// whatever the reading is at, it's been there for longer than the debounce
|
||||
// delay, so take it as the actual current state:
|
||||
if (reading != _buttonState)
|
||||
{
|
||||
_buttonState = reading;
|
||||
|
||||
if (_buttonState == LOW)
|
||||
{
|
||||
handleButtonChange(true);
|
||||
_buttonChangeHandled = true;
|
||||
_buttonDownTime = millis();
|
||||
_buttonPressHandled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
handleButtonChange(false);
|
||||
_buttonChangeHandled = true;
|
||||
|
||||
unsigned long dt = millis() - _buttonDownTime;
|
||||
if (dt >= _minButtonDownTime && dt <= _maxButtonDownTime && !_buttonPressHandled)
|
||||
{
|
||||
handleButtonPress(dt);
|
||||
_buttonPressHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_lastReading = reading;
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonNode::setup()
|
||||
{
|
||||
advertise("down").setDatatype("boolean");
|
||||
advertise("duration").setDatatype("integer").setUnit("ms");
|
||||
|
||||
printCaption();
|
||||
Homie.getLogger() << cIndent << "Pin: " << _buttonPin << endl;
|
||||
|
||||
if (_buttonPin > DEFAULTPIN)
|
||||
{
|
||||
pinMode(_buttonPin, INPUT_PULLUP);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user