homebridge-dacp
homebridge-dacp copied to clipboard
Detecting off status
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).
https://github.com/grover/homebridge-dacp/blob/8a8f472f72eab24eb9b0c7ce0e9c599a7be723f3/src/DacpAccessory.js#L95-L108
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:
https://github.com/grover/homebridge-dacp/blob/8a8f472f72eab24eb9b0c7ce0e9c599a7be723f3/src/PlayerControlsService.js#L3
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).