homebridge-hatch-baby-rest-volume
Version:
Homebridge plugin for Hatch Baby Rest bluetooth night light volume
133 lines (132 loc) • 4.89 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HatchBabyRestPlus = void 0;
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const util_1 = require("./util");
const rgb2hsv = require('pure-color/convert/rgb2hsv'), hsv2rgb = require('pure-color/convert/hsv2rgb');
const MAX_VALUE = 65535;
function convertFromPercentage(percentage) {
return Math.floor((percentage / 100) * MAX_VALUE);
}
function convertToPercentage(value) {
return Math.floor((value * 100) / MAX_VALUE);
}
function convertToHexRange(value) {
return Math.floor((value / MAX_VALUE) * 255);
}
function convertFromHexRange(value) {
return Math.floor((value * MAX_VALUE) / 255);
}
function colorToHsb({ r, g, b }) {
const [h, s, v] = rgb2hsv([r, g, b].map(convertToHexRange));
return { h, s, b: v };
}
function assignState(previousState, changes) {
const state = Object.assign({}, previousState);
for (const key in changes) {
if (typeof changes[key] === 'object') {
state[key] = Object.assign(previousState[key] || {}, changes[key]);
}
else {
state[key] = changes[key];
}
}
return state;
}
class HatchBabyRestPlus {
constructor(info) {
this.info = info;
this.onCurrentState = new rxjs_1.BehaviorSubject(null);
this.onState = this.onCurrentState.pipe(operators_1.filter((state) => state !== null));
this.onAudioOn = this.onState.pipe(operators_1.map((state) => state.a.t > 0), operators_1.distinctUntilChanged());
this.onVolume = this.onState.pipe(operators_1.map((state) => convertToPercentage(state.a.v)), operators_1.distinctUntilChanged());
this.onAudioTrack = this.onState.pipe(operators_1.map((state) => state.a.t), operators_1.distinctUntilChanged());
this.onIsPowered = this.onState.pipe(operators_1.map((state) => state.isPowered), operators_1.distinctUntilChanged());
this.onBrightness = this.onState.pipe(operators_1.map((state) => convertToPercentage(state.c.i)), operators_1.distinctUntilChanged());
this.onHsb = this.onState.pipe(operators_1.map((state) => colorToHsb(state.c)));
this.onHue = this.onHsb.pipe(operators_1.map(({ h }) => h), operators_1.distinctUntilChanged());
this.onSaturation = this.onHsb.pipe(operators_1.map(({ s }) => s), operators_1.distinctUntilChanged());
this.onBatteryLevel = this.onState.pipe(operators_1.map((state) => state.deviceInfo.b), operators_1.distinctUntilChanged());
}
get id() {
return this.info.id;
}
get name() {
return this.info.name;
}
registerMqttClient(mqttClient) {
const { thingName } = this.info;
let getClientToken;
this.mqttClient = mqttClient;
mqttClient.on('status', (topic, message, clientToken, status) => {
if (clientToken !== getClientToken) {
return;
}
const { state } = status;
this.onCurrentState.next(assignState(state.reported, state.desired));
});
mqttClient.on('foreignStateChange', (topic, message, s) => {
const currentState = this.onCurrentState.getValue();
if (!currentState) {
return;
}
this.onCurrentState.next(assignState(assignState(currentState, s.state.reported), s.state.desired));
});
mqttClient.on('connect', () => {
mqttClient.register(thingName, {}, () => {
getClientToken = mqttClient.get(thingName);
});
});
}
getCurrentState() {
return this.onState.pipe(operators_1.take(1)).toPromise();
}
update(update) {
if (!this.mqttClient) {
util_1.logError(`Unable to Update ${this.name} - No MQTT Client Registered`);
return;
}
this.mqttClient.update(this.info.thingName, {
state: {
desired: update,
},
});
}
setVolume(percentage) {
this.update({
a: {
v: convertFromPercentage(percentage),
},
});
}
setAudioTrack(audioTrack) {
this.update({
a: {
t: audioTrack,
},
});
}
setColor(color) {
this.update({
c: color,
});
}
setColorFromHueAndSaturation(hue, saturation) {
const [r, g, b] = hsv2rgb([hue, saturation, 100]).map(convertFromHexRange);
this.setColor({ r, g, b, R: false, W: false });
}
setBrightness(percentage) {
this.update({
c: {
i: convertFromPercentage(percentage),
},
});
}
setPower(on) {
this.update({
isPowered: on,
});
}
}
exports.HatchBabyRestPlus = HatchBabyRestPlus;