magichome-platform
Version:
discover, control, and receive status for magichome devices
177 lines (176 loc) • 8.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isCommandEqual = exports.adjustCommandToAPI = exports.getAPI = exports.discoverProtoDevices = void 0;
const miscUtils_1 = require("magichome-core/dist/utils/miscUtils");
const deviceTypesMap_1 = require("./deviceTypesMap");
const miscUtils_2 = require("./miscUtils");
const magichome_core_1 = require("magichome-core");
const errorTypes_1 = require("../models/errorTypes");
async function discoverProtoDevices(subnets) {
let discoveredDevices = await (0, magichome_core_1.discoverDevices)(1000, subnets);
for (let scans = 0; scans < 5; scans++) {
if (discoveredDevices.length > 0)
break;
discoveredDevices = await (0, magichome_core_1.discoverDevices)(1000, subnets);
}
return discoveredDevices;
}
exports.discoverProtoDevices = discoverProtoDevices;
function getAPI(deviceMetaData) {
const { controllerHardwareVersion } = deviceMetaData;
if (!deviceTypesMap_1.deviceTypesMap.has(controllerHardwareVersion))
throw new errorTypes_1.NoMatchingAPIError(deviceMetaData);
const deviceAPI = deviceTypesMap_1.deviceTypesMap.get(controllerHardwareVersion);
// if (matchingFirmwareVersions.has(controllerFirmwareVersion)) adjustedProtocols = matchingFirmwareVersions.get(controllerFirmwareVersion);
return deviceAPI;
}
exports.getAPI = getAPI;
function adjustCommandToAPI(deviceCommand, commandOptions, deviceAPI) {
const { byteOrder, simultaneousCCT, hasCCT, hasColor } = deviceAPI;
if (!hasColor || !commandOptions.colorAssist)
return deviceCommand;
let newDeviceCommand = (0, miscUtils_1.cloneDeep)(deviceCommand);
newDeviceCommand.colorMask = determineColorMask(newDeviceCommand, simultaneousCCT, hasCCT);
newDeviceCommand = adjustCCT(newDeviceCommand, deviceAPI);
newDeviceCommand.isOn = adjustIsOn(newDeviceCommand);
newDeviceCommand = setRGBOrder(newDeviceCommand, byteOrder); //this must be done last as to not interfere with the other adjustments
return newDeviceCommand;
}
exports.adjustCommandToAPI = adjustCommandToAPI;
function determineColorMask(deviceCommand, simultaneousCCT, hasCCT) {
let { RGB: { red, green, blue }, CCT: { warmWhite, coldWhite }, colorMask, } = deviceCommand;
if (simultaneousCCT)
colorMask = magichome_core_1.ColorMask.BOTH;
if (!hasCCT)
colorMask = magichome_core_1.ColorMask.RGB;
const colorMin = Math.min(red, green, blue);
const colorMax = Math.max(red, green, blue);
const whiteMax = Math.max(warmWhite, coldWhite);
//catch all for when the colorMask is not explicitly defined by above conditions
if (!colorMask)
colorMask =
colorMax >= whiteMax || colorMax - colorMin >= 1
? magichome_core_1.ColorMask.RGB
: magichome_core_1.ColorMask.CCT;
return colorMask;
}
function setRGBOrder(deviceCommand, byteOrder) {
if (byteOrder.length < 3)
return deviceCommand;
const { RGB: { red, green, blue }, } = deviceCommand;
const colorList = [0, 0, 0];
let i = 0;
for (const byte of byteOrder) {
if (i > colorList.length - 1)
break;
switch (byte) {
case "r":
colorList[i] = red;
break;
case "g":
colorList[i] = green;
break;
case "b":
colorList[i] = blue;
break;
default:
break;
}
i++;
}
return (0, miscUtils_1.combineDeep)(deviceCommand, {
RGB: {
red: colorList[0] || 0,
green: colorList[1] || 0,
blue: colorList[2] || 0,
},
});
}
//TODO: these need to be changed so this function is skippable in configuration. This is not the same as the other functions and is more subjective to personal preference
//this could be done at a device object level which could be enabled/disabled on the fly from a GUI
function adjustCCT(deviceCommand, deviceAPI) {
let newDeviceCommand = (0, miscUtils_1.cloneDeep)(deviceCommand);
const { byteOrder, simultaneousCCT } = deviceAPI;
const { RGB: { red, green, blue }, CCT: { warmWhite, coldWhite }, colorMask, } = deviceCommand;
const cwAdj = Math.round(coldWhite / 2), wwRedAdj = Math.round(warmWhite / 2), wwGreenAdj = Math.round(warmWhite / 6.8), wwBlueAdj = Math.round(warmWhite / 28.4);
//todo handle non RGB devices, single brightness devices
// simultaneousCCT, 5-colors, ColorMask set to CCT
if (byteOrder.length == 5 && simultaneousCCT && colorMask == magichome_core_1.ColorMask.CCT) {
/*do nothing for now */
}
// non-simultaneousCCT, 5-colors, ColorMask set to CCT
else if (byteOrder.length == 5 &&
!simultaneousCCT &&
colorMask == magichome_core_1.ColorMask.CCT) {
/*do nothing for now */
}
// non-simultaneousCCT, 5-colors, ColorMask not explicitly defined or is defined as RGB/BOTH
else if (byteOrder.length == 5 && !simultaneousCCT) {
/*do nothing for now*/
}
// simultaneousCCT, 4-colors, ColorMask not explicitly defined or is defined as RGB/BOTH
// (adjusts the color channels to account for the lack of a 2nd white channel by modifying the RGB channels to be cooler)
else if (byteOrder.length == 4 && simultaneousCCT && coldWhite > 0) {
newDeviceCommand = (0, miscUtils_1.combineDeep)(deviceCommand, {
RGB: {
red: (0, miscUtils_2.clamp)(red + cwAdj, 0, 255),
green: (0, miscUtils_2.clamp)(green + cwAdj, 0, 255),
blue: (0, miscUtils_2.clamp)(blue + cwAdj, 0, 255),
},
CCT: { warmWhite: Math.max(coldWhite, warmWhite), coldWhite },
colorMask: magichome_core_1.ColorMask.BOTH,
});
}
// non-simultaneousCCT, 4-colors, ColorMask set to CCT
// (adjusts for the lack of a 2nd white channel by using the highest value for both warm and cold white)
else if (byteOrder.length == 4 &&
!simultaneousCCT &&
colorMask == magichome_core_1.ColorMask.CCT) {
newDeviceCommand = (0, miscUtils_1.combineDeep)(deviceCommand, {
CCT: { warmWhite: Math.max(warmWhite, coldWhite), coldWhite: 0 },
});
}
// non-simultaneousCCT, 4-colors, ColorMask not explicitly defined or is defined as RGB
// (adjusts for the lack of simultaneous CCT and RGB by adding adjustments calculated from both warmWhite and coldWhite to the RGB channels)
else if (!simultaneousCCT && byteOrder.length == 4) {
newDeviceCommand = (0, miscUtils_1.combineDeep)(deviceCommand, {
RGB: {
red: (0, miscUtils_2.clamp)(red + cwAdj + wwRedAdj, 0, 255),
green: (0, miscUtils_2.clamp)(green + cwAdj + wwGreenAdj, 0, 255),
blue: (0, miscUtils_2.clamp)(blue + cwAdj + wwBlueAdj, 0, 255),
},
colorMask: magichome_core_1.ColorMask.RGB,
});
}
//non-simultaneousCCT, 3-colors, ColorMask not explicitly defined or is defined as RGB
// (adjusts for the lack of simultaneous CCT and RGB by adding adjustments calculated from both warmWhite and coldWhite to the RGB channels)
else if (!simultaneousCCT && byteOrder.length == 3) {
newDeviceCommand = (0, miscUtils_1.combineDeep)(deviceCommand, {
RGB: {
red: (0, miscUtils_2.clamp)(red + cwAdj + wwRedAdj, 0, 255),
green: (0, miscUtils_2.clamp)(green + cwAdj + wwGreenAdj, 0, 255),
blue: (0, miscUtils_2.clamp)(blue + cwAdj + wwBlueAdj, 0, 255),
},
colorMask: magichome_core_1.ColorMask.RGB,
});
}
return newDeviceCommand;
}
function adjustIsOn(deviceCommand) {
let isOn = false;
const { RGB: { red, green, blue }, CCT: { warmWhite, coldWhite }, } = deviceCommand;
if (Math.max(red, green, blue, warmWhite, coldWhite) > 0)
isOn = true;
return isOn;
}
function isCommandEqual(colorStart, colorTarget) {
let isEqual = false;
try {
isEqual = (0, miscUtils_1.deepEqual)(colorStart, colorTarget, ["colorMask"]);
}
catch (error) {
console.log("Error in isCommandEqual: ", error);
}
return isEqual;
}
exports.isCommandEqual = isCommandEqual;