Skip to content

johntothee/garage

Repository files navigation

Garage is an internet of things garage door lock and opener for the raspberry pi. It uses nodejs and jwt to receive signed tokens to command a garage door to unlock and then trigger the opener. It's currently installed in my garage.

General Info When a token is verified and the open-close command is received, GPIO 17 (pin 11) will go active low to trigger the lock solenoid. Then GPIO 27 (pin 13) will go active low for half a second triggering the opener. 15 seconds later GPIO pin 17 will go back to inactive releasing the lock solenoid. You could use any GPIO pins, but these are right next to each other and a ground pin. The times for simulated button press, delay from lock activation to similated button press, and time that lock is activacted are configurable in config.json

GPIO 22 (pin 15) will also trigger the lock and opener. This pin has an internal pull down. It is intended that this and 3v3 Power (pin 1) get connected to one's existing opener button to manually open/close.

The lock is expected to work with a 120VAC solenoid and metal rod that will block the path of a garage door's rollers.

A door magnet sensor detects when the garage door is opened for an unknown reason. The sensor is wired in the Normally Closed configuration. When the matching magnet moves away the circuit closes, pulling GPIO3 (pin 5) low. Open-Close timestamps are saved to a sqlite3 database. When a door open condition is detected (The signal is also debounced by 3 seconds.) that time is compared to the last open-close timestamp. If it has been more than 120 seconds it is assumed this shouldn't happen and a notification should be sent. We're using Twilio. In case the magnet is placed just at the threshold of detection, when SMS messages are sent they are also timestamped. Any within 5 minutes of the last send are ignored.

An iOS app has also been started which will generate keys, and send signed open-close requests. Presently keys must be generated elsewhere and the private key and other info saved to the app.

Needed info to setup: API Key - random string of characters saved to ./keys/config.json Each request needs this query parameter and will be checked first. This is mainly to keep lurkers away.

https keys - You can get these from https://letsencrypt.org. Set the path to these files in ./keys/config.json.

IP Address and port - to access the raspberry pi. If one's ip address isn't static a Dynamic Domain Name System service could be used instead. You'll also need to forward the port in your router and/or modem. Even after soldering on a connector for an exteral antenna, 2.4GHz wifi wasn't strong enough to reliably reach from my access point at the front of the house to my garage. So I added powerline ethernet adapters. Configuring a static IP address through that took some trial and error. This is what I needed in /etc/dhcpcd.conf: interface [NAME OF ETHERNET ADAPTER] ipv4only inform [STATIC IP] static routers=[AP IP] static domain_name_servers=[AP IP]

User ID - any integer to identify amongst multiple users.

Private, public rsa key generated by openssl (one per user). The private key is used to sign jwt tokens. The public key is used to verify the signature and should be installed in ./keys/ with a filename format of [USER_ID]-public.pem

A number of node packages are defined in package.json. Install them with npm install. As of npm v6 npm audix fix can be used to upgrade packages with security vulnerabilities. If the npm sqlite3 package tries to compile from source and fails you may need to do the following first: sudo apt-get update sudo apt-get upgrade sudo apt-get install libsqlite3-dev sudo npm install sqlite3 --build-from-source --sqlite=/usr

The database is expected to be read and written in the directory ./db/ . This directory must be created. To set up for the first time run node install.js.

Relays and a solenoid. I found a board with two 5v relays locally similar to this: https://www.sainsmart.com/products/2-channel-5v-relay-module When complete I'll include drawings and/or wiring diagrams.

This application can be run from the command line with node app.js

To generate a test token use node genJwt.js [USERID] [COMMAND]. From a web browser the url takes the format: "https://[IP]:[PORT]/api/garage?apikey=[API_KEY]&token=[JWT]" A response including the word 'verify' is successful. The payload of the jwt has the following format: {"uid": 1, "command": "verify", "iat": TIMESTAMP}

Security info: We're using jwt tokens with the RS256 algorithm for extra security. A private key signs tokens for which verification can only be done with the matching public key. Tokens older than two minutes are rejected. Even if one were to get a copy of a token it would soon be invalid. Communicating over https provides further protection. New ssl cert files can be generated by running certbot and updating certbot.js certbot command example: sudo letsencrypt certonly --manual --email [YOUR EMAIL] -d [DOMAIN]

./keys/config.json uses the following format: { "rpi": false, "apiKey": "API KEY string", "authToken": "TWILIO AUTH TOKEN", "accountSid": "TWILIO ACCOUNT SID", "from": "FROM TWILIO NUMBER", "to": "PHONE NUMBER TO SEND SMS", "keyPath": "LOCAL PATH TO SSL CERT FILES", "buttonPress": 2000, "buttonDelay": 1000, "unlockTime": 20000 }

Services

extra_files/garage.service and extra_files/garage-certbot.service are sample files that can be modified and copied or moved to /etc/sytemd/system (if running a debian based linux). The run sudo systemctl daemon-reload for these new services to be recognized. Run sudo systemctl enable garage.service to allow app.js to start as a service on boot. Systemd will also try to restart the service if it ever fails.

Certbot

To set up letsencrypt the first time, start certbot.js with sudo node certbot.js then run sudo certbot certonly --manual. It will prompt you for an email address and your domain. Next you'll get two long strings. One of these is to be created as a file in [path to garage]/.wellknown/acme-challenge/ The contents of this file will be the longer string. Certbot will wait for you to create these.

Certbot renewal

Once letsencrypt has been run once manually, certbot renew or certbot-auto service can be started to check and generate new files when a cert is due for renewal. extra_files/YOURDOMAIN.conf is a sample certbot config file. certbot will create this but you'll likly need to modify the line that starts with 'authenticator' and add a line that starts with 'webroot_path'.

You can copy extra_files/001-start-node-certbot.sh to /etc/letsencrypt/renewal-hooks/pre and extra_files/001-restart.sh to /etc/letsencrypt/renewal-hooks/post. These will start and stop certbot.js only when renewal is needed and restart app.js so it picks up the new certificate.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published