mpd-avr-client
Version:
AVR as a MPD client
93 lines (80 loc) • 2.45 kB
JavaScript
const { readFile } = require('fs');
const { Observable, of } = require('rxjs');
const { take, shareReplay, switchMap, catchError } = require('rxjs/operators');
const {
getInstance: getBluetoothClient,
} = require('../clients/bluetooth-client');
const GoveeService = function (_ledLaunchProfilePath) {
return ((ledLaunchProfilePath) => {
const ledLaunchProfile$ =
/** @type Observable<LedLaunchProfile> */ new Observable((subscriber) => {
readFile(ledLaunchProfilePath, (err, data) => {
if (err) {
return subscriber.error(err);
}
try {
subscriber.next(JSON.parse(data.toString()));
subscriber.complete();
} catch (err) {
subscriber.error(err);
subscriber.complete();
}
});
return () => {};
}).pipe(shareReplay());
/**
* Generates a Govee BLE payload with the correct checksum.
* @param {boolean} ledOn - Desired power state
* @returns {string} 40-character (i.e. 20 Bytes) long hex string
*/
function generateGoveePowerPayload(ledOn) {
const payload = Buffer.alloc(20, 0x00);
payload[0] = 0x33; // Command header
payload[1] = 0x01; // Command: Power
payload[2] = ledOn ? 0x01 : 0x00;
payload[19] = payload.reduce((acc, item) => acc ^ item, 0);
return payload.toString('hex');
}
const wake = () =>
ledLaunchProfile$
.pipe(
switchMap(({ macAddress, rowNumberHex }) =>
getBluetoothClient().write(
macAddress,
rowNumberHex,
generateGoveePowerPayload(true)
)
),
catchError(() => of(null)),
take(1)
)
.subscribe();
const standBy = () =>
ledLaunchProfile$
.pipe(
switchMap(({ macAddress, rowNumberHex }) =>
getBluetoothClient().write(
macAddress,
rowNumberHex,
generateGoveePowerPayload(false)
)
),
catchError(() => of(null)),
take(1)
)
.subscribe();
return {
wake,
standBy,
};
})(_ledLaunchProfilePath);
};
let instance;
module.exports = {
getInstance: (ledLaunchProfilePath) => {
if (!instance) {
instance = new GoveeService(ledLaunchProfilePath);
}
return /** @type {LedService} */ instance;
},
};