So, I currently live in a walkup in New York City. No doorman, no lobby. My frequent Amazon orders come in via a variety of carriers - Fedex, UPS, USPS, and various local logistics third parties that Amazon partners with. The standard protocol is that the deliveryman leaves packages inside my mailroom area, behind the (locked) front door. Quite often, the deliveryman does not have keys to my building's front door, which means he isn't able to leave the package. This makes receiving deliveries quite difficult for me, since I have to take time off to be home to await packages. Even worse, the delivery window is usually "somewhere between 10AM and 8PM" so I can't even go anywhere for fear of missing the package.
All I needed was a way to remotely open the front door when the deliveryman arrives so he can drop off the package. This seemed like an idea for an electronics project! I started off with an Arduino Uno kit but halfway through I realized having the Uno board tetheredf to my computer long term wasn't going to be an option, so I swapped out the hardware with an ESP8266, a neat little SoC that includes a Wifi antenna. There's an Arduino-compatibility library for it so I can use the standard Arduino Studio workflow with it.
The server code is 59 lines of typescript at https://github.com/talyian/door_server/blob/master/src/index.ts. Dependencies:
Nothing particularly outrageous, just a standard nodejs+express server that accepts a /door query and holds it open while waiting on another client to respond on the /open endpoint with the appropriate secret token. The token in question is simply a global variable, secret
, but without too much further work this could be adapted to support multiple doors and email addresses.
// endpoint for Button to notify us
app.get('/button', function(req, resp, next) {
var mailer = Sendmail();
secret = Crypto.randomBytes(32).toString('hex');
mailer({
'from': 'door-server@app.example.com'
'to': 'admin-email@example.com'
'subject': 'door',
'html': `Requesting Access: <a href="http://${req.hostname}/open/${secret}">Click Here</a>`
}, function(err: any, reply: any) {
if (!err) {
...
The client side code is 106 lines of Arduino-flavored C. (https://gist.github.com/talyian/58b93d15451dcb418808213faa7e5a35) Okay, I'll be the first to admit, I'm not an Arduino expert. I kind of bumbled my way through implementing a state-machine-via-giant-switch-statement in the main loop for this application, although it smells like something you'd really want a coroutine library for.
void loop() {
static int state = STARTING, counter = 0, status = 0;
switch(state) {
case STARTING:
status = WiFi.status();
if (status == WL_CONNECTED) {
state = READY;
}
case READY: // connected to wifi, wait for button press
if (check_button_pressed()) {
state = NOTIFYING;
}
break;
// Ask the internet for permission to open the door
// will mutate state when done
case NOTIFYING: return client_loop(state);
...
void client_loop (int &main_state) {
enum { BEGIN, CONNECTING, RECEIVING, ...
static int state = BEGIN;
switch(state) {
...
case RECEIVING:
if (!client.connected()) { // disconnected from web server
main_state = READY;
state = BEGIN;
return;
}
else if (!client.available()) { // waiting on bytes to come in
return;
}
// process response!
String content = client.readString();
....
My door intercom unit is a Lee Dan IR-204E station. I found some schematics on www.leedan.com website, but mainly I just poked around with a multimeter to figure out which wire led where. There are 4 wires, two of which power the buzzer and two of which control the door.
Currently, the USB connection is providing the power. This is kind of a pain -- I'd like to drive it directly off the 11V wires powering the doorbell itself. I have a few buck converters lying around I can use for this.
I need to move this project to a prototype board to cut down on the bulk.
My phone doesn't do a great job of getting emails reliably. I may want to use twilio or something to send texts instead. Also, instead of having to click the link in the email, perhaps just replying "open" or "Y"/"N" would be easier to do from my phone's lock screen.