magichome-platform
Version:
discover, control, and receive status for magichome devices
222 lines (221 loc) • 9.49 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseController = void 0;
const magichome_core_1 = require("magichome-core");
const platformUtils_1 = require("../utils/platformUtils");
const colorConversions_1 = require("../utils/colorConversions");
const { POWER, ANIMATION_FRAME, LED } = magichome_core_1.CommandType;
const DEFAULT_COMMAND_OPTIONS = {
waitForResponse: false,
maxRetries: 0,
commandType: LED,
isEightByteProtocol: false,
colorAssist: true,
};
class BaseController {
// Buffering-related properties
get ledStateRGB() {
if (this._ledStateRGB === null) {
throw Error('ledStateRGB is null');
}
//return a deep copy of the ledStateRGB
return (0, magichome_core_1.cloneDeep)(this._ledStateRGB);
}
set ledStateRGB(ledStateRGB) {
if (ledStateRGB === null) {
throw Error('Trying to set ledStateRGB but it is null');
}
this._ledStateRGB = (0, magichome_core_1.cloneDeep)(ledStateRGB);
}
get ledStateHSV() {
if (this._ledStateRGB === null) {
throw Error('ledStateRGB is null and cannot be converted to HSV');
}
const HSV = (0, colorConversions_1.RGBtoHSV)(this._ledStateRGB.RGB);
//iterate through the rgb values and if all are 0, then the hue data has been lost and we need to use the last known hue
const allRGBValuesAreZero = Object.values(this._ledStateRGB.RGB).every(value => value === 0);
if (allRGBValuesAreZero) {
HSV.hue = this.lastKnownHue;
}
return { isOn: this._ledStateRGB.isOn, HSV, CCT: this._ledStateRGB.CCT }; // already a deep copy from the ledStateRGB
}
get command() {
return {
get: (partial) => {
return (0, magichome_core_1.combineDeep)(magichome_core_1.DEFAULT_COMMAND, partial);
},
};
}
get fullDeviceInformation() {
if (this.deviceBundle.completeDevice.fetchStateResponse.deviceMetaData === null) {
throw Error('DeviceMetaData is null');
}
if (this.deviceBundle.completeDevice.protoDevice === null) {
throw Error('ProtoDevice is null');
}
if (this.deviceBundle.completeDevice.fetchStateResponse.ledStateRGB === null) {
throw Error('DeviceState is null');
}
if (this.deviceAPI === null) {
throw Error('DeviceAPI is null');
}
return {
deviceAPI: this.deviceAPI,
protoDevice: this.deviceBundle.completeDevice.protoDevice,
ledStateRGB: this.ledStateRGB,
deviceMetaData: this.deviceBundle.completeDevice.fetchStateResponse.deviceMetaData,
};
}
get deviceManager() {
if (this._deviceManager === null) {
throw Error('DeviceManager is null');
}
return this._deviceManager;
}
set deviceManager(deviceManager) {
this._deviceManager = deviceManager;
}
constructor(deviceBundle) {
this.deviceBundle = deviceBundle;
this._ledStateRGB = null;
this.lastKnownHue = 0;
this.lastOutboundCommand = null;
this._deviceManager = null;
this.manuallyControlled = false;
this.id = null;
this.animationList = [];
this.deviceManager = deviceBundle.deviceManager;
this.ledStateRGB = deviceBundle.completeDevice.fetchStateResponse.ledStateRGB; //already cloning the ledStateRGB at the setter
this.deviceAPI = (0, platformUtils_1.getAPI)(deviceBundle.completeDevice.fetchStateResponse.deviceMetaData);
this.id = deviceBundle.completeDevice.protoDevice.uniqueId;
}
async setOn(value, maxRetries = 0) {
// Use our buffered partial update with just the isOn property
const deviceCommand = (0, magichome_core_1.mergeDeep)(magichome_core_1.DEFAULT_COMMAND, { isOn: value });
return await this.deviceManager.sendCommand(deviceCommand, this.generateCommandOptions(POWER, maxRetries));
}
async setLEDRGB(deviceCommandRGB, maxRetries = 0, colorAssist = true) {
const commandOptions = this.generateCommandOptions(LED, maxRetries, colorAssist);
return await this.sendCommandRGB(deviceCommandRGB, commandOptions);
}
async setLEDHSV(deviceCommandHSV, maxRetries = 0, colorAssist = true) {
if (deviceCommandHSV.HSV.hue !== undefined) {
this.lastKnownHue = deviceCommandHSV.HSV.hue;
}
const deviceCommandRGB = this.hsvCommandToRGB(deviceCommandHSV);
return await this.setLEDRGB(deviceCommandRGB, maxRetries, colorAssist);
}
hsvCommandToRGB(deviceCommandHSV) {
const rgb = (0, colorConversions_1.HSVtoRGB)(deviceCommandHSV.HSV);
return { isOn: deviceCommandHSV.isOn, RGB: rgb, CCT: deviceCommandHSV.CCT };
}
async sendCommandRGB(deviceCommand, commandOptions) {
const newDeviceCommand = (0, platformUtils_1.adjustCommandToAPI)(deviceCommand, commandOptions, this.deviceAPI);
(0, magichome_core_1.mergeDeep)(this.lastOutboundCommand, newDeviceCommand);
await this.deviceManager.sendCommand(newDeviceCommand, commandOptions);
// this.ledStateRGB = completeResponse.fetchStateResponse.ledStateRGB;
// return completeResponse;
}
generateCommandOptions(commandType, maxRetries = 0, colorAssist = true) {
let commandOptions = (0, magichome_core_1.combineDeep)(DEFAULT_COMMAND_OPTIONS, {
isEightByteProtocol: this.deviceAPI.isEightByteProtocol,
commandType,
});
if (maxRetries > 0) {
commandOptions = (0, magichome_core_1.combineDeep)(commandOptions, { maxRetries, waitForResponse: true });
}
if (!colorAssist) {
commandOptions = (0, magichome_core_1.combineDeep)(commandOptions, { colorAssist: false });
}
return commandOptions;
}
async fetchDeviceStateRGB() {
let scans = 0, fetchStateResponse;
do {
fetchStateResponse = await this.deviceManager.queryState();
const byteOrder = this.deviceAPI.byteOrder;
if (byteOrder[0] === 'g' && byteOrder[1] === 'r' && byteOrder[2] === 'b') {
const { red, green, blue } = fetchStateResponse.ledStateRGB.RGB;
fetchStateResponse.ledStateRGB.RGB = { red: green, green: red, blue };
}
scans++;
} while (fetchStateResponse?.ledStateRGB == null && scans < 5);
if (scans >= 5) {
throw Error('fetchStateRGB - No response given');
}
if (typeof fetchStateResponse == 'undefined') {
throw Error('fetchStateRGB - No response given');
}
this.ledStateRGB = fetchStateResponse.ledStateRGB;
return fetchStateResponse.ledStateRGB;
}
async fetchDeviceStateHSV() {
const state = await this.fetchDeviceStateRGB();
return { isOn: state.isOn, HSV: (0, colorConversions_1.RGBtoHSV)(state.RGB), CCT: state.CCT };
}
//#region Animation
getAnimationList() {
return this.animationList;
}
hasAnimation(animationName) {
return this.animationList.includes(animationName);
}
appendAnimationList(animationName) {
if (Array.isArray(animationName)) {
animationName.forEach((name) => {
if (!this.animationList.includes(name)) {
this.animationList.push(name);
}
});
}
else if (!this.animationList.includes(animationName)) {
this.animationList.push(animationName);
}
}
removeAnimationFromList(animationName) {
if (Array.isArray(animationName)) {
animationName.forEach((name) => {
const index = this.animationList.indexOf(name);
if (index > -1) {
this.animationList.splice(index, 1);
}
});
}
else {
const index = this.animationList.indexOf(animationName);
if (index > -1) {
this.animationList.splice(index, 1);
}
}
}
setLEDColorAnimation(color) {
// console.log(this.fullDeviceInformation.protoDevice.)
const COLOR = {
red: 0,
green: 0,
blue: 0,
warmWhite: 0,
coldWhite: 0,
};
// Use a type assertion to handle the index access
for (const colorKey in color) {
const key = colorKey;
const typedKey = colorKey;
COLOR[typedKey] = color[key];
}
const deviceCommand = {
isOn: true,
RGB: { red: COLOR.red, green: COLOR.green, blue: COLOR.blue },
CCT: { warmWhite: COLOR.warmWhite, coldWhite: COLOR.coldWhite },
};
const commandOptions = {
waitForResponse: false,
isEightByteProtocol: this.deviceAPI.isEightByteProtocol,
maxRetries: 0,
commandType: ANIMATION_FRAME,
colorAssist: true,
};
this.sendCommandRGB(deviceCommand, commandOptions);
}
}
exports.BaseController = BaseController;