Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detecting off status #65

Open
eliottrobson opened this issue Aug 12, 2019 · 0 comments
Open

Detecting off status #65

eliottrobson opened this issue Aug 12, 2019 · 0 comments

Comments

@eliottrobson
Copy link

eliottrobson commented Aug 12, 2019

I was reviewing the DACP protocol trying to find a way to detect when the Apple TV was turned off (so I could add play, pause and off lights) however the closest I got was detecting when the app is closed (or turned off). It works really well, is this something you would be happy for me to PR?

If not, and for anyone interested in setting this up for automation (I have only tested this on the alternate-playpause-switch) there's a few simple changes you need to make.

The first is to change the switch type to Outlet which enables on/off (playing/paused) and in use (on when playing / paused, off when app is closed).

getPlayerControlsService(homebridge) {
let service = Service.PlayerControlsService;
let characteristic = Characteristic.PlayPause;
if (this.config.features['alternate-playpause-switch'] === true) {
service = Service.Switch;
characteristic = Characteristic.On;
}
this._playerControlsService = new PlayerControlsService(homebridge, this.log, this.name, this._dacpClient, service, characteristic);
this._playStatusUpdateListeners.push(this._playerControlsService);
return this._playerControlsService.getService();
}

This needs to change to:

  getPlayerControlsService(homebridge) {
    let service = Service.PlayerControlsService;
    let characteristic = Characteristic.PlayPause;
    let characteristic2 = null;

    if (this.config.features['alternate-playpause-switch'] === true) {
      service = Service.Outlet;
      characteristic = Characteristic.On;
      characteristic2 = Characteristic.OutletInUse;
    }

    this._playerControlsService = new PlayerControlsService(homebridge, this.log, this.name, this._dacpClient, service, characteristic, characteristic2);
    this._playStatusUpdateListeners.push(this._playerControlsService);

    return this._playerControlsService.getService();
  }

And then the controls service needs to change too:

class PlayerControlsService {

The constructor needs to support the new parameter

constructor(homebridge, log, name, dacp, serviceCtor, characteristicCtor, characteristic2Ctor) {
    this.log = log;
    this.name = name;
    this._dacp = dacp;
    this._serviceCtor = serviceCtor;
    this._characteristicCtor = characteristicCtor;
    this._characteristic2Ctor = characteristic2Ctor;

    this._service = this.createService();
  }

The service needs to use the new characteristic

createService() {
    const svc = new this._serviceCtor(this.name);

    svc.getCharacteristic(this._characteristicCtor)
      .on('get', this._getPlayState.bind(this))
      .on('set', this._setPlayState.bind(this));

    if (this._characteristic2Ctor) {
      svc.getCharacteristic(this._characteristic2Ctor)
        .on('get', this._getOnState.bind(this))
        .on('set', this._setOnState.bind(this));
    }
    
    return svc;
  }

The update needs to track the new characteristic and determine the on state

update(response) {
    this._isPlaying = response.caps === 4;
    this._isOn = response.caps !== 0;

    this._service.getCharacteristic(this._characteristicCtor)
      .updateValue(this._isPlaying);

    if (this._characteristic2Ctor) {
      this._service.getCharacteristic(this._characteristic2Ctor)
        .updateValue(this._isOn);
    }
  }

And finally we need to add some state monitors for logging

_getOnState(callback) {
    this.log(`Returning current on state: ${this._isOn ? 'on' : 'off'}`);
    callback(undefined, this._isOn);
  }

  async _setOnState(isOn, callback) {
    this.log(`Setting current on state: ${isOn ? 'on' : 'off'}`);
    this._isOn = isOn;
  }

Once that is done, you should be able to listen to the power state going off to determine the Apple TV is off (or close enough at least).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant