TroX-oO / homebridge-freemote

This Homebridge plugin exposes Freebox v6 remote to Apple's Homekit.
3 stars 4 forks source link

Sound volume controle #2

Closed Erokani closed 5 years ago

Erokani commented 6 years ago

Hi,

I’m not skilled enough to do it myself, but could you evaluate introducing sound volume controle via a 2nd accessory? Some existing homebridge plugins are doing this via a dedicated bulb (brightness) or fan (speed) accessory?

This is really the missing feature to make this plugin perfect :)

Thanks Mat

TroX-oO commented 6 years ago

Hi, this is totally possible and not very hard to do.

As it's been almost two years since I did this code, and I have no thing to test on anymore, I'm sorry that you'll have to get your hand in it to get it working, but I will give you some directions.

There are 2 possibles ways to do it : 1) You add another command to the same lightbulb like change color, or whatever (I don't know the list of possible command) This would be easy to implement but not really easy to use :/

2) As you propose, you create another accessory.

I will deep into the 2) as it is a little bit more complicate to implement (but not so hard)

All the work is in index.js

First you duplicate all the FreemoteAccessory class (from line 21 to the 104)

Here is what it should look like:

Paste in the bottom of the file:


//
// Freemote AccessoryVolume
//

function FreemoteAccessoryVolume(log, config) {
    this.log = log;
    this.config = config;
    this.name = config["name"] + " Volume";

    this.remote_code = config["remote_code"];
    this.freebox_ip = config["freebox_ip"];
    this.send_delay = config["send_delay"] || 1;
    this.appid = config["appid"];
    this.token = config["token"];

    if (!this.remote_code) throw new Error("You must provide a config value for 'remote_code'.");
    if (!this.freebox_ip) throw new Error("You must provide a config value for 'freebox_ip'.");

    this.Api = new FreemoteApi(this.log, this.freebox_ip, this.appid, this.token, this.remote_code);

    this.channel = 1;

    this.service = new Service.Lightbulb(this.name);

    this.service
        .getCharacteristic(Characteristic.On)
        .on('get', this._getOn.bind(this))
        .on('set', this._setOn.bind(this));

    this.service
        .addCharacteristic(new Characteristic.Brightness())
        .on('get', this._getChannel.bind(this))
        .on('set', this._setChannel.bind(this));
}

FreemoteAccessoryVolume.prototype.getInformationService = function() {
    var informationService = new Service.AccessoryInformation();
    informationService
        .setCharacteristic(Characteristic.Name, this.name)
        .setCharacteristic(Characteristic.Manufacturer, 'Freebox Remote')
        .setCharacteristic(Characteristic.Model, '1.0.0')
        .setCharacteristic(Characteristic.SerialNumber, this.remote_code);
    return informationService;
};

FreemoteAccessoryVolume.prototype.getServices = function() {
    return [this.service, this.getInformationService()];
};

FreemoteAccessoryVolume.prototype._getOn = function(callback) {
    callback(null, true);
};

FreemoteAccessoryVolume.prototype._setOn = function(on, callback) {
    callback(null);
};

FreemoteAccessoryVolume.prototype._getChannel = function(callback) {
    callback(null, this.channel);
};

function changeChannel(callback) {
    this.Api.volume(this.channel !== '0' ? 'up' : 'down');
    callback(null, this.channel);
}

FreemoteAccessoryVolume.prototype._setChannel = function(channel, callback) {
    this.log('Changing volume to %s.', JSON.stringify(channel));
    this.channel = '' + channel;
    this._chTmo = setTimeout(changeChannel.bind(this, callback), 2000);
};

Paste this in the index.js line 18: under the the registration of the first accessory

    homebridge.registerAccessory("homebridge-freemote", "Freemote", FreemoteAccessoryVolume);

The drawback, is that you cannot know the current volume value, so with this code, you will be able to

If you want to tweak the "20" value, go in FreemoteApi.js line 129

That's all :D

I hope I helped you.

Erokani commented 6 years ago

Hi,

Thanks a lot for your time & assistance! Much appreciated :)

I did the changes (this one and the power one) in a fork. Once back home I’ll test them and commit to your branch once ok.

However there is one thing I can’t succeed to understand: where is called the function FreemoteApi.prototype.volume for the new volume accessory??

Thanks Mat

PS: not sure this approach will pass the WAF. I may end instead with 2 stateless switches to increase/decrease volume.

TroX-oO commented 6 years ago

The function is called in this snippet (in the new accessory)

function changeChannel(callback) {
    this.Api.volume(this.channel !== '0' ? 'up' : 'down');  // <--  Here
    callback(null, this.channel);
}