hjdhjd / homebridge-doorbird

Homebridge plugin for Doorbird
Apache License 2.0
54 stars 14 forks source link

Change from polling for doorbell/motion to doorbird "notification request API" #6

Closed mrhund closed 7 years ago

mrhund commented 7 years ago

Hi,

since polling for events as implemented in the current solution did not work for me, I changed the implementation to provide an http-server which can be used by the dorrbird API to be called when an event (doorbell, motion) is triggered. This works (at least for me) more reliable than the polling mechanism.

In my case I registered the doorbird api using: wget -q 'http://doorbird-ip/bha-api/notification.cgi?http-user=XXX&http-password=XXX&event=doorbell&subscribe=1&url=http://homebridge-ip:8080/doorbell.html'

If you are interested in including my code to your solution, please contact me.

Thanks, Bernhard

brownad commented 7 years ago

That's pretty cool. It does work 'most' of the time as I used the same on zipatile before.

I'd still appreciate the view on what you did if you commit somewhere it would need a few changes on my side (removal mainly).

But I am still convinced it's the doorbird api at the moment - they just haven't confirmed yet:

Also more importantly the latest changes with apple are making it more likely this can be turned into a native community app to work as a real video doorbell - although we are missing bi-directional Audio

Great work glad to hear someone is back in business with doorbird and homebridge

Thanks

Sent from my iPhone

On 11 Jun 2017, at 11:45, mrhund notifications@github.com wrote:

Hi,

since polling for events as implemented in the current solution did not work for me, I changed the implementation to provide an http-server which can be used by the dorrbird API to be called when an event (doorbell, motion) is triggered. This works (at least for me) more reliable than the polling mechanism.

In my case I registered the doorbird api using: wget -q 'http://doorbird-ip/bha-api/notification.cgi?http-user=XXX&http-password=XXX&event=doorbell&subscribe=1&url=http://homebridge-ip:8080/doorbell.html'

If you are interested in including my code to your solution, please contact me.

Thanks, Bernhard

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

adrian-brown commented 7 years ago

Ping it over, I think I could support both options, and make it an option for people to use either.

@mrhund :+1:

brownad commented 7 years ago

Well in that case, do you want to make a PR I didn't realise you went as far as to bring it al together so nicely.

I'd be more than happy to merge it 👍

The readme needs a couple of setup instructions but looks sweet

Sent from my iPhone

On 12 Jun 2017, at 17:46, mrhund notifications@github.com wrote:

`var Service, Characteristic; var http = require("http");

module.exports = function (homebridge) { Service = homebridge.hap.Service; Characteristic = homebridge.hap.Characteristic;

homebridge.registerPlatform("homebridge-doorbird", "DoorBird", DoorBirdPlatform); };

function DoorBirdPlatform(log, config) { this.log = log; this.devices = config["doorbird"]; log("Starting discovery..."); }

DoorBirdPlatform.prototype = { accessories: function (callback) { var foundAccessories = []; var count = this.devices.length;

for (index = 0; index < count; index++) {
    var doorBird = new DoorBird(this.log, this.devices[index]);
    foundAccessories.push(doorBird);
}
callback(foundAccessories);

} };

function DoorBird(log, config) { var self = this; this.log = log; this.name = config["name"]; this.username = config["doorbird_username"]; this.password = config["doorbird_password"]; this.ip = config["doorbird_ip"]; this.monitor = '/bha-api/monitor.cgi?ring=doorbell,motionsensor'; this.open = '/bha-api/open-door.cgi?'; this.light = '/bha-api/light-on.cgi?'; this.serial = config["doorbird_serial"] || "4260423860001"; this.model = config["doorbird_model"] || "D101"; this.currentState = true; this.binaryState = 0; this.timeout = 2; this.httpport = config["http_port"]; this.doorbellService = new Service.MotionSensor(this.name + ' Doorbell', 'Doorbell'); this.motionService = new Service.MotionSensor(this.name + ' Motion', 'Motion'); this.lightService = new Service.Lightbulb(this.name + ' Light'); this.lockService = new Service.LockMechanism(this.name + ' Lock');

this.log("Starting a homebridge-doorbird device with name '" + this.name + "'...");

//Start HTTP server to listen for events var server = http.createServer(function (req, resp) { if (req.url == "/doorbell.html") { server.status_code = 204 resp.writeHead(204, { "Content-Type": "text/plain" }); resp.end("GET 204 " + http.STATUS_CODES[204] + " " + req.url + "\nThe server successfully processed the request and is not returning any content.") self.log("HTTP Server: doorbell.html was called, sending event to homebridge.") setTimeout(function () { self.doorbellService.getCharacteristic(Characteristic.MotionDetected).updateValue(true); }.bind(self), 10);

    setTimeout(function () {
        self.log('DoorBird resetting doorbell')
        self.doorbellService.getCharacteristic(Characteristic.MotionDetected).updateValue(false);
    }.bind(self), 5000);
} else if (req.url == "/motion.html") {
    server.status_code = 204
    resp.writeHead(204, {
        "Content-Type": "text/plain"
    });
    resp.end("GET 204 " + http.STATUS_CODES[204] + " " + req.url + "\nThe server successfully processed the request and is not returning any content.")
    self.log("HTTP Server: motion.html was called, sending event to homebridge.")
    setTimeout(function () {
        self.motionService.getCharacteristic(Characteristic.MotionDetected).updateValue(true);
    }.bind(self), 10);

    setTimeout(function () {
        self.log('DoorBird resetting mtion')
        self.motionService.getCharacteristic(Characteristic.MotionDetected).updateValue(false);
    }.bind(self), 5000);
} else {
    server.status_code = 404
    resp.writeHead(404, {
        "Content-Type": "text/plain"
    });
    resp.end("GET 404 " + http.STATUS_CODES[404] + " " + req.url + "\nThat File cannot be found")
    self.log("HTTP Server: GET 404 " + http.STATUS_CODES[404] + " " + req.url)
}

}); server.listen(this.httpport, "0.0.0.0") this.log("HTTP Server started on port " + this.httpport);

//Definde URLs for actions this.lockUrl = "http://" + this.ip + this.open + "&http-user=" + this.username + "&http-password=" + this.password var lightUrl = "http://" + this.ip + this.light + "&http-user=" + this.username + "&http-password=" + this.password

//Unlock door event this.lockService .getCharacteristic(Characteristic.LockCurrentState) .on('get', this.getState.bind(this));

this.lockService .getCharacteristic(Characteristic.LockTargetState) .on('get', this.getState.bind(this)) .on('set', this.setState.bind(this));

//Night vision event this.lightService.getCharacteristic(Characteristic.On) .on('set', function (value, callback) { request.get({ url: lightUrl, }, function (err, response, body) { if (!err && response.statusCode == 200) { self.log('DoorBird night vision activated for 3 minutes'); setTimeout(function () { this.log('DoorBird resetting light event'); this.lightService.getCharacteristic(Characteristic.On).updateValue(0); }.bind(self), 5000); } else { self.log("DoorBird error '%s' setting light. Response: %s", err, body); callback(err || new Error("Error setting light state")); } }); callback(); }); }

DoorBird.prototype.setState = function (state, callback) { var lockState = (state == Characteristic.LockTargetState.SECURED) ? "lock" : "unlock"; var update = (state == Characteristic.LockTargetState.SECURED) ? true : false; self = this;

self.log("DoorBird set state to ", lockState); self = this; self.currentState = (state == Characteristic.LockTargetState.SECURED) ? Characteristic.LockCurrentState.SECURED : Characteristic.LockCurrentState.UNSECURED;

if (lockState == "unlock") { request.get({ url: this.lockUrl, }, function (err, response, body) { if (!err && response.statusCode == 200) {

        //set state to unlocked
        self.lockService
            .setCharacteristic(Characteristic.LockCurrentState, self.currentState);
        self.log("DoorBird lock opened")

        if (!update) {
            setTimeout(function () {
                //set state to unlocked
                self.lockService
                    .setCharacteristic(Characteristic.LockTargetState, Characteristic.LockTargetState.SECURED)
                    .setCharacteristic(Characteristic.LockCurrentState, self.currentState);
                update = true;
                self.log("DoorBird auto lock initiated")
            }.bind(this), 4000);
        }
    }

    else {
        self.log("DoorBird error '%s' opening lock. Response: %s", err, body);
        callback(err || new Error("DoorBird error setting lock state"));
    }
});

}

callback(null); };

DoorBird.prototype.getState = function (callback) { callback(null, this.currentState); }

DoorBird.prototype.getServices = function () { var informationService = new Service.AccessoryInformation(); informationService .setCharacteristic(Characteristic.Manufacturer, "DoorBird") .setCharacteristic(Characteristic.Model, this.model) .setCharacteristic(Characteristic.SerialNumber, this.serial);

return [this.doorbellService, this.motionService, this.lightService, this.lockService, informationService]; }; `

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

mrhund commented 7 years ago

done :)

mrhund commented 7 years ago

Also more importantly the latest changes with apple are making it more likely this can be turned into a native community app to work as a real video doorbell - although we are missing bi-directional Audio

I found a guy who made an addon for HAP NodeJS in order to provide video doorbell functionality. maybe this could be a good base to start: https://github.com/Maxmudjon/HAP-NodeJS-accessories

brownad commented 7 years ago

Not quite yet, I have been talking to the same guy about combining the doorbell with ip camera which he did with mqtt so it's possible. but I'd rather go native instead.

However doorbird themselves said they would support HomeKit - now there's no hardware requirement it might happen - well I hope it does. Along with audio.

If you test the HomeKit simulator video doorbell it's all there...

Sent from my iPhone

On 12 Jun 2017, at 18:18, mrhund notifications@github.com wrote:

Also more importantly the latest changes with apple are making it more likely this can be turned into a native community app to work as a real video doorbell - although we are missing bi-directional Audio

I found a guy who made an addon for HAP NodeJS in order to provide video doorbell functionality. maybe this could be a good base to start: https://github.com/Maxmudjon/HAP-NodeJS-accessories

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

brownad commented 7 years ago

Done thanks.

I've looked into the current streaming API with Doorbird, I think we'll use this approach for now

brownad commented 7 years ago

I checked quickly, motion and doorbell from the API look great (nice to see it working again)

Light and door lock seem to error out, I need to check why, is it good for you? @mrhund

mrhund commented 7 years ago

Sorry for that, accidently removed the require statement for "request". Should work again, created a new PR.