Skip to content

Commit

Permalink
version 2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
plhyhc committed Jun 15, 2020
1 parent 7561d93 commit 742c4a1
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 128 deletions.
31 changes: 18 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# Homebridge Pi Garage Door Opener With Sensor


This is a [homebridge](https://github.com/nfarina/homebridge) plugin to make a Raspberry Pi connected with a Relay Board into a Garage Door Opener, via the Home app on iOS using Homekit. It uses a magnetic switch to determine the state of the garage door, open or closed. Tested with iOS 11.
This is a [homebridge](https://github.com/nfarina/homebridge) plugin to make a Raspberry Pi connected with a Relay Board into a Garage Door Opener, via the Home app on iOS using Homekit. It uses a magnetic switch to determine the state of the garage door, open or closed. The wires from the Relay go into the same ports as the wired button for the garage door. When the Relay closes the circuit it acts like the button was pushed. Tested with iOS 13.

Homebridge works best I have found when run in sudo.

### Start on boot

Have the "homebridge" command run at boot.


### Sample Config

Config to be placed in .homebridge/config.json
* If you run homebridge from sudo, place config in /root/.homebridge/config.json
* If you run homebridge without sudo, place config in /home/pi/.homebridge/config.json
Rename config.sample.json to config.json and place in .homebridge/config.json

```json
{
Expand All @@ -28,21 +29,25 @@ Config to be placed in .homebridge/config.json
"accessory": "Garage Door Opener",
"name": "Garage Door",
"doorRelayPin": 11,
"doorSensorPin": 10
"doorSensorPin": 16,
"invertDoorState": false,
"invertSensorState": false,
"duration_ms": 500 //number of milliseconds relay will close the circuit
}]
}
```

### How to Setup

```
sudo apt-get install libavahi-compat-libdnssd-dev
git clone git://github.com/quick2wire/quick2wire-gpio-admin.git
cd quick2wire-gpio-admin
make
sudo make install
sudo adduser $USER gpio
sudo npm install -g --unsafe-perm homebridge
sudo npm install -g homebridge-garage-door-wsensor
sudo homebridge
```
Rename config.sample.json to config.json and place in .homebridge/config.json


### How to Start
Run the following command
```
homebridge
```
7 changes: 5 additions & 2 deletions config.sample.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"bridge": {
"name": "Garage Homebridge",
"username": "CC:22:3D:E3:CE:30",
"username": "CC:22:3D:E3:CE:34",
"port": 51826,
"pin":"031-45-154",
"manufacturer": "@nfarina",
Expand All @@ -13,6 +13,9 @@
"accessory": "Garage Door Opener",
"name": "Garage Door",
"doorRelayPin": 11,
"doorSensorPin": 10
"doorSensorPin": 16,
"invertDoorState": false,
"invertSensorState": false,
"duration_ms": 500
}]
}
215 changes: 109 additions & 106 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,116 +1,119 @@
var gpio = require('pi-gpio');
let Service, Characteristic, TargetDoorState, CurrentDoorState;
const OFF = true;
const ON = false;

module.exports = function(homebridge) {
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
TargetDoorState = Characteristic.TargetDoorState;
CurrentDoorState = Characteristic.CurrentDoorState;
DoorState = homebridge.hap.Characteristic.CurrentDoorState;
homebridge.registerAccessory('homebridge-garage-door-opener', 'Garage Door Opener', GarageDoorOpener);
};

class GarageDoorOpener {
constructor(log, config) {
var Service, Characteristic, TargetDoorState, CurrentDoorState;
var rpio = require('rpio');

module.exports = function (homebridge) {
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
TargetDoorState = Characteristic.TargetDoorState;
CurrentDoorState = Characteristic.CurrentDoorState;
DoorState = homebridge.hap.Characteristic.CurrentDoorState;
homebridge.registerAccessory('homebridge-garage-door-wsensor', 'Garage Door Opener', GarageDoorOpener);
}

function GarageDoorOpener(log, config) {
this.log = log;
this.name = config.name;
this.doorRelayPin = config.doorRelayPin;
this.doorSensorPin = config.doorSensorPin;
this.checkSensor();
this.currentDoorState = CurrentDoorState.CLOSED;
this.targetDoorState = TargetDoorState.CLOSED;
this.DoorState = 1;
this.pinChange = 0;
}

identify(callback) {
this.log('Identify requested!');
callback(null);
}

openCloseGarage(callback) {
var self = this;
gpio.open(self.doorRelayPin, 'output', function() {
gpio.write(self.doorRelayPin, 1, function() {
// SET VALUE 1 TO SET RELAY HIGH
});
});
setTimeout(() => {
gpio.open(self.doorRelayPin, 'output', function() {
gpio.write(self.doorRelayPin, 0, function() {
// SET VALUE 0 TO SET RELAY LOW
});
});
}, 700);
}

checkSensor(){
var self = this;
setTimeout(function(){
gpio.open(self.doorSensorPin, 'input', function() {
gpio.read(self.doorSensorPin, function(gself,value) {
if(value === 1){
if(self.DoorState != value){
self.pinChange = 1;
self.service.setCharacteristic(TargetDoorState, TargetDoorState.OPEN);
}
self.pinChange = 0;
self.service.setCharacteristic(CurrentDoorState, CurrentDoorState.OPEN);
self.targetDoorState = 0;
} else {
if(self.DoorState != value){
self.pinChange = 1;
self.service.setCharacteristic(TargetDoorState, TargetDoorState.CLOSED);
}
self.pinChange = 0;
self.service.setCharacteristic(CurrentDoorState, CurrentDoorState.CLOSED);
self.targetDoorState = 1;
}
self.DoorState = value;
self.checkSensor();
});
});
},500);
}

getServices() {
const informationService = new Service.AccessoryInformation();

informationService
.setCharacteristic(Characteristic.Manufacturer, 'Encore Dev Labs')
.setCharacteristic(Characteristic.Model, 'Kraft Garage Door Opener')
.setCharacteristic(Characteristic.SerialNumber, 'Raspberry Pi');
this.invertDoorState = defaultVal(config["invertDoorState"], false);
this.invertSensorState = defaultVal(config['invertSensorState'], false);
this.default = defaultVal(config["default_state"], false);
this.duration = defaultVal(config["duration_ms"], 0);
this.doorState = 0;
this.sensorChange = 0;
this.service = null;

if (!this.doorRelayPin) throw new Error("You must provide a config value for 'doorRelayPin'.");
if (!this.doorSensorPin) throw new Error("You must provide a config value for 'doorSensorPin'.");
if (!is_int(this.duration)) throw new Error("The config value 'duration' must be an integer number of milliseconds.");

this.log("Creating a garage door relay named '%s', initial state: %s", this.name, (this.invertDoorState ? "OPEN" : "CLOSED"));
rpio.open(this.doorRelayPin, rpio.OUTPUT, this.gpioDoorVal(this.invertDoorState));
rpio.open(this.doorSensorPin, rpio.OUTPUT, this.gpioSensorVal(this.invertSensorState));
this.checkSensor(e => {});
}

GarageDoorOpener.prototype.getServices = function () {
this.service = new Service.GarageDoorOpener(this.name, this.name);
this.service.setCharacteristic(TargetDoorState, TargetDoorState.CLOSED);
this.service.setCharacteristic(CurrentDoorState, CurrentDoorState.CLOSED);

this.service.getCharacteristic(TargetDoorState)
.on('get', (callback) => {
callback(null, this.targetDoorState);
})
.on('set', (value, callback) => {
this.targetDoorState = value;
if (this.targetDoorState === TargetDoorState.OPEN) {
if(this.pinChange == 0 ){
this.openCloseGarage();
}
} else if (this.targetDoorState === TargetDoorState.CLOSED) {
if(this.pinChange == 0 ){
this.openCloseGarage();
}
}
this.pinChange = 0;
callback();
});
this.service
.getCharacteristic(Characteristic.Name)
.on('get', callback => {
callback(null, this.name);
});

return [informationService, this.service];
}
this.service.setCharacteristic(CurrentDoorState, CurrentDoorState.CLOSED);
this.service.getCharacteristic(CurrentDoorState)
.on('get', this.getSensorStatus.bind(this))
this.service.getCharacteristic(TargetDoorState)
.on('get', this.getSensorStatus.bind(this))
.on('set', this.setDoorOpen.bind(this));
return [this.service];
}

GarageDoorOpener.prototype.getSensorStatus = function (callback) {
callback(null, this.readSensorState());
}

GarageDoorOpener.prototype.checkSensor = function (callback) {
setTimeout(e => {
this.doorState = this.readSensorState();
if (this.doorState !== this.sensorChange){
this.service.getCharacteristic(TargetDoorState).updateValue(this.doorState);
this.service.getCharacteristic(CurrentDoorState).updateValue(this.doorState);
this.sensorChange = this.doorState;
}
this.checkSensor(callback);
}, 500);

callback(null);
}

GarageDoorOpener.prototype.readSensorState = function () {
var val = this.gpioSensorVal(rpio.read(this.doorSensorPin));
console.log('readSensorState: ' + val);
return val == rpio.HIGH;
}

GarageDoorOpener.prototype.setState = function (val) {
rpio.write(this.doorRelayPin, this.gpioDoorVal(val));
}

GarageDoorOpener.prototype.setDoorOpen = function (newState, callback) {
console.log('setDoorOpen: ' + newState);
if (this.timerid !== -1) {
clearTimeout(this.timerid);
this.timerid = -1;
}

this.setState(newState);

if (this.duration > 0) {
this.timerid = setTimeout(this.timeOutCB, this.duration, this);
}

callback(null);
}

GarageDoorOpener.prototype.timeOutCB = function (o) {
o.setState(0);
o.timerid = -1;
}

GarageDoorOpener.prototype.gpioSensorVal = function (val) {
if (!this.invertSensorState) val = !val;
return val ? rpio.HIGH : rpio.LOW;
}

GarageDoorOpener.prototype.gpioDoorVal = function (val) {
if (this.invertDoorState) val = !val;
return val ? rpio.HIGH : rpio.LOW;
}

var is_int = function (n) {
return n % 1 === 0;
}

var is_defined = function (v) {
return typeof v !== 'undefined';
}

var defaultVal = function (v, dflt) {
return is_defined(v) ? v : dflt;
}
10 changes: 3 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,13 @@
"_shasum": "73e7b822fe3761c305958587b2135cf9c3d3dd3e",
"_spec": "homebridge-garage-door-wsensor",
"_where": "/home/pi",
"author": {
"name": "Josh Kraft",
"email": "josh.h.kraft@gmail.com",
"url": "http://www.joshkraft.com"
},
"author": "plhyhc",
"bugs": {
"url": "https://github.com/plhyhc/homebridge-garage-door-wsensor/issues"
},
"bundleDependencies": false,
"dependencies": {
"pi-gpio": "^0.0.8"
"rpio": "^2.1.0"
},
"deprecated": false,
"description": "Hombridge plugin for Garage Door Opener - Raspberry Pi",
Expand All @@ -58,5 +54,5 @@
"type": "git",
"url": "git+https://github.com/plhyhc/homebridge-garage-door-wsensor.git"
},
"version": "1.0.3"
"version": "2.0.0"
}

0 comments on commit 742c4a1

Please sign in to comment.