mirror of
https://github.com/binary-kitchen/doorlockd
synced 2024-12-22 18:34:25 +01:00
392763f720
Signed-off-by: Ralf Ramsauer <ralf@ramses-pyramidenbau.de>
136 lines
3.1 KiB
C++
136 lines
3.1 KiB
C++
#include <iostream>
|
|
|
|
#include <wiringPi.h>
|
|
#include <unistd.h>
|
|
|
|
#include "config.h"
|
|
#include "logger.h"
|
|
#include "door.h"
|
|
|
|
using namespace std;
|
|
|
|
Door::Door() :
|
|
_l(Logger::get())
|
|
{
|
|
_l(LogLevel::info, "Initializing Raspberry Pi GPIOs");
|
|
wiringPiSetup();
|
|
pinMode(_HEARTBEATPIN, OUTPUT);
|
|
pinMode(_SCHNAPPERPIN, OUTPUT);
|
|
pinMode(_LOCKPIN, INPUT);
|
|
pullUpDnControl(_LOCKPIN, PUD_UP);
|
|
lock();
|
|
}
|
|
|
|
Door::~Door()
|
|
{
|
|
lock();
|
|
}
|
|
|
|
Door &Door::get()
|
|
{
|
|
static Door d;
|
|
return d;
|
|
}
|
|
|
|
Door::State Door::state() const
|
|
{
|
|
return _state;
|
|
}
|
|
|
|
void Door::lock()
|
|
{
|
|
std::lock_guard<std::mutex> l(_mutex);
|
|
|
|
_l(LogLevel::notice, "Executing Pre Lock Script");
|
|
system(PRE_LOCK_SCRIPT);
|
|
|
|
digitalWrite(_SCHNAPPERPIN, HIGH);
|
|
_l(LogLevel::info, "Door closed");
|
|
|
|
if (_state == State::Unlocked)
|
|
{
|
|
// Stop the Heartbeat Thread
|
|
_state = State::Locked;
|
|
_heartbeat.join();
|
|
}
|
|
|
|
_l(LogLevel::notice, "Executing Post Lock Script");
|
|
system(POST_LOCK_SCRIPT);
|
|
}
|
|
|
|
void Door::unlock()
|
|
{
|
|
_l(LogLevel::notice, "Executing Pre Unlock Script");
|
|
system(PRE_UNLOCK_SCRIPT);
|
|
|
|
// In any case, klacker the schnapper
|
|
_schnapper = true;
|
|
|
|
// If heartbeat is already running, return
|
|
if (_state == State::Unlocked)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// If not, first set state to unlocked
|
|
_state = State::Unlocked;
|
|
|
|
// Start the Heartbeat Thread
|
|
_heartbeat = std::thread([this] () {
|
|
|
|
// One "beat" is one complete cycle of the heartbeat clock
|
|
auto beat = [this] () {
|
|
digitalWrite(_HEARTBEATPIN, HIGH);
|
|
usleep(10000);
|
|
digitalWrite(_HEARTBEATPIN, LOW);
|
|
usleep(10000);
|
|
};
|
|
|
|
// The default of the Schnapperpin: always high
|
|
digitalWrite(_SCHNAPPERPIN, HIGH);
|
|
|
|
// Heartbeat while the state is unlocked
|
|
while (_state == State::Unlocked) {
|
|
|
|
// In case of schnapper, send 0x55 resp. 0xaa to the schnapperpin
|
|
if (_schnapper == true)
|
|
{
|
|
for (int i = 0; i < 32 ; i++)
|
|
{
|
|
// Set '0'
|
|
digitalWrite(_SCHNAPPERPIN, LOW);
|
|
// cycle and send
|
|
beat();
|
|
// Set '1'
|
|
digitalWrite(_SCHNAPPERPIN, HIGH);
|
|
// cycle and send
|
|
beat();
|
|
}
|
|
|
|
// Reset schnapperpin
|
|
digitalWrite(_SCHNAPPERPIN, HIGH);
|
|
// and deactivate schnapper for the next round
|
|
_schnapper = false;
|
|
}
|
|
|
|
// Heartbeat
|
|
beat();
|
|
|
|
if (!digitalRead(_LOCKPIN)) {
|
|
std::thread([this] () {
|
|
_l(LogLevel::info, "Incoming door close request on button press");
|
|
lock();
|
|
}).detach();
|
|
|
|
// Busy wait till door is locked
|
|
while(_state == State::Unlocked);
|
|
}
|
|
}
|
|
});
|
|
|
|
_l(LogLevel::info, "Door opened");
|
|
|
|
_l(LogLevel::notice, "Executing Post Unlock Script");
|
|
system(POST_UNLOCK_SCRIPT);
|
|
}
|