Last active
April 17, 2016 22:12
-
-
Save sjparkinson/9064be59cf0318ae91fd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Gatekeeper.h" | |
const int kPinDrRelay = D0; | |
const int kPinS1Relay = D1; | |
const int kPinS2Relay = D2; | |
const int kPinDsLine = D3; | |
const int kPinBzLine = D4; | |
int primed_; | |
volatile int last_bz_interrupt_; | |
Gatekeeper::Gatekeeper() {} | |
void Gatekeeper::Begin() { | |
// Register Particle functions. | |
Particle.function("unlock", &Gatekeeper::Unlock, this); | |
Particle.function("prime", &Gatekeeper::Prime, this); | |
// Setup the relay signals. | |
pinMode(kPinDrRelay, OUTPUT); | |
pinMode(kPinS1Relay, OUTPUT); | |
pinMode(kPinS2Relay, OUTPUT); | |
// Setup the BS line to read the door status. | |
pinMode(kPinDsLine, INPUT_PULLUP); | |
// Setup the BZ line to read the call tone with an interrupt. | |
pinMode(kPinBzLine, INPUT_PULLDOWN); | |
attachInterrupt(kPinBzLine, &Gatekeeper::CallToneInteruptHandler, this, RISING); | |
// Initalise the output pins. | |
digitalWrite(kPinDrRelay, LOW); | |
digitalWrite(kPinS1Relay, LOW); | |
digitalWrite(kPinS2Relay, LOW); | |
Particle.publish("gatekeeper/setup", PRIVATE); | |
} | |
bool Gatekeeper::Unlock() { | |
// If the handset is not active, or the door's already open we can't unlock it. | |
if (! IsHandsetActive() || IsDoorOpen()) { | |
return false; | |
} | |
// "Pickup" the handset and "press" the door release button. | |
digitalWrite(kPinS1Relay, HIGH); | |
digitalWrite(kPinS2Relay, HIGH); | |
delay(300); | |
digitalWrite(kPinDrRelay, HIGH); | |
delay(200); | |
// Finally resetting all the relays. | |
digitalWrite(kPinDrRelay, LOW); | |
digitalWrite(kPinS1Relay, LOW); | |
digitalWrite(kPinS2Relay, LOW); | |
// Ensure we unprime the system. | |
primed_ = 0; | |
Particle.publish("gatekeeper/unlocked", PRIVATE); | |
return true; | |
} | |
bool Gatekeeper::Prime() { | |
// If the door's open, what's the point in priming? | |
if (IsDoorOpen()) { | |
return false; | |
} | |
primed_ = Time.now(); | |
return true; | |
} | |
bool Gatekeeper::IsDoorOpen() { | |
return (digitalRead(kPinDsLine) == LOW); | |
} | |
bool Gatekeeper::IsHandsetActive() { | |
return (last_bz_interrupt_ > Time.now() - 1 && pulseIn(kPinBzLine, HIGH) > 0); | |
} | |
bool Gatekeeper::IsPrimed() { | |
return (primed_ > Time.now() - 120); | |
} | |
void Gatekeeper::CallToneInteruptHandler() { | |
last_bz_interrupt_ = Time.now(); | |
} | |
int Gatekeeper::Unlock(String command) { | |
return Unlock() ? 0 : -1; | |
} | |
int Gatekeeper::Prime(String command) { | |
return Prime() ? 0 : -1; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef Gatekeeper_H_ | |
#define Gatekeeper_H_ | |
#include "application.h" | |
// | |
// A library for interacting with the Gatekeeper system. | |
// | |
class Gatekeeper | |
{ | |
public: | |
Gatekeeper(); | |
void Begin(); | |
bool Unlock(); | |
bool Prime(); | |
bool IsDoorOpen(); | |
bool IsHandsetActive(); | |
bool IsPrimed(); | |
void CallToneInteruptHandler(); | |
private: | |
int Unlock(String command); | |
int Prime(String command); | |
}; | |
#endif // Gatekeeper_H_ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This #include statement was automatically added by the Particle IDE. | |
#include "Gatekeeper.h" | |
// Create an instance of the Gatekeeper library. | |
Gatekeeper gatekeeper; | |
// The variables we will publish to the Particle service. | |
int is_door_open_; | |
int is_handset_active_; | |
int is_primed_; | |
void setup() { | |
gatekeeper.Begin(); | |
Particle.variable("isActive", is_handset_active_); | |
Particle.variable("isDoorOpen", is_door_open_); | |
Particle.variable("isPrimed", is_primed_); | |
} | |
void check(int &variable, bool (Gatekeeper::*function)(), String triggerEventName, String detriggerEventName) { | |
bool cachedValue = (gatekeeper.*function)(); | |
if (! variable && cachedValue) { | |
variable = 1; | |
Particle.publish(String("gatekeeper/" + triggerEventName), PRIVATE); | |
} else if (variable && ! cachedValue) { | |
variable = 0; | |
Particle.publish(String("gatekeeper/" + detriggerEventName), PRIVATE); | |
} | |
} | |
void loop() { | |
check(is_primed_, &Gatekeeper::IsPrimed, "primed", "unprimed"); | |
check(is_door_open_, &Gatekeeper::IsDoorOpen, "door-opened", "door-closed"); | |
check(is_handset_active_, &Gatekeeper::IsHandsetActive, "handset-activated", "handset-deactivated"); | |
// Unlock the door if the handset is active and primed. | |
if (is_handset_active_ && is_primed_) { | |
gatekeeper.Unlock(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment