@dotwee/homebridge-z2m
Version:
Expose your Zigbee devices to HomeKit with ease, by integrating Zigbee2MQTT with Homebridge.
177 lines • 8.44 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertMiredColorTemperatureToXY = exports.convertMiredColorTemperatureToHueSat = exports.convertXyToHueSat = exports.convertHueSatToXy = void 0;
const color_convert = __importStar(require("color-convert"));
const helpers_1 = require("./helpers");
// The functions in this file are mostly based on the documentation/code provided by Philips Hue.
// See: https://developers.meethue.com/develop/application-design-guidance/color-conversion-formulas-rgb-to-xy-and-back/
function gammaCorrection(v) {
return v > 0.04045 ? Math.pow((v + 0.055) / (1.0 + 0.055), 2.4) : v / 12.92;
}
function reverseGammaCorrection(v) {
return v <= 0.0031308 ? 12.92 * v : (1.0 + 0.055) * Math.pow(v, 1.0 / 2.4) - 0.055;
}
function convertHueSatToXy(hue, saturation) {
const rgb = color_convert.hsv.rgb([hue, saturation, 100]);
const red = gammaCorrection(rgb[0] / 255);
const green = gammaCorrection(rgb[1] / 255);
const blue = gammaCorrection(rgb[2] / 255);
const X = red * 0.664511 + green * 0.154324 + blue * 0.162028;
const Y = red * 0.283881 + green * 0.668433 + blue * 0.047685;
const Z = red * 0.000088 + green * 0.07231 + blue * 0.986039;
const xyzSum = X + Y + Z;
// Round values to at most 5 decimal places, as Zigbee seems to define a 16 bit unsigned integer
// for these values, which makes the smallest possible step 1/65535 (or approximately 0.000015)
const x = (0, helpers_1.roundToDecimalPlaces)(X / xyzSum, 5);
const y = (0, helpers_1.roundToDecimalPlaces)(Y / xyzSum, 5);
return [x, y];
}
exports.convertHueSatToXy = convertHueSatToXy;
function convertXyToHueSat(x, y) {
// Based on: https://developers.meethue.com/develop/application-design-guidance/color-conversion-formulas-rgb-to-xy-and-back/
const z = 1.0 - x - y;
const Y = 1.0;
const X = (Y / y) * x;
const Z = (Y / y) * z;
// sRGB D65 conversion
let r = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
let g = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
let b = X * 0.051713 - Y * 0.121364 + Z * 1.01153;
// Remove negative values
const m = Math.min(r, g, b);
if (m < 0.0) {
r -= m;
g -= m;
b -= m;
}
// Normalize
if (r > b && r > g && r > 1.0) {
// red is too big
g = g / r;
b = b / r;
r = 1.0;
}
else if (g > b && g > r && g > 1.0) {
// green is too big
r = r / g;
b = b / g;
g = 1.0;
}
else if (b > r && b > g && b > 1.0) {
// blue is too big
r = r / b;
g = g / b;
b = 1.0;
}
// Gamma correction
r = reverseGammaCorrection(r);
g = reverseGammaCorrection(g);
b = reverseGammaCorrection(b);
// Maximize
const max = Math.max(r, g, b);
r = r === max ? 255 : 255 * (r / max);
g = g === max ? 255 : 255 * (g / max);
b = b === max ? 255 : 255 * (b / max);
const hsv = color_convert.rgb.hsv([r, g, b]);
return [hsv[0], hsv[1]];
}
exports.convertXyToHueSat = convertXyToHueSat;
function convertMiredColorTemperatureToHueSat(temperature) {
const xy = convertMiredColorTemperatureToXY(temperature);
return convertXyToHueSat(xy[0], xy[1]);
}
exports.convertMiredColorTemperatureToHueSat = convertMiredColorTemperatureToHueSat;
function convertMiredColorTemperatureToXY(temperature) {
// Based on MiredColorTemperatureToXY from:
// https://github.com/dresden-elektronik/deconz-rest-plugin/blob/78939ac4ee4b0646fbf542a0f6e83ee995f1a875/colorspace.cpp
const TEMPERATURE_TO_X_TEMPERATURE_THRESHOLD = 4000;
const TEMPERATURE_TO_Y_FIRST_TEMPERATURE_THRESHOLD = 2222;
const TEMPERATURE_TO_Y_SECOND_TEMPERATURE_THRESHOLD = 4000;
const TEMPERATURE_TO_X_FIRST_FACTOR_FIRST_EQUATION = 17440695910400;
const TEMPERATURE_TO_X_SECOND_FACTOR_FIRST_EQUATION = 15358885888;
const TEMPERATURE_TO_X_THIRD_FACTOR_FIRST_EQUATION = 57520658;
const TEMPERATURE_TO_X_FOURTH_FACTOR_FIRST_EQUATION = 11790;
const TEMPERATURE_TO_X_FIRST_FACTOR_SECOND_EQUATION = 198301902438400;
const TEMPERATURE_TO_X_SECOND_FACTOR_SECOND_EQUATION = 138086835814;
const TEMPERATURE_TO_X_THIRD_FACTOR_SECOND_EQUATION = 14590587;
const TEMPERATURE_TO_X_FOURTH_FACTOR_SECOND_EQUATION = 15754;
const TEMPERATURE_TO_Y_FIRST_FACTOR_FIRST_EQUATION = 18126;
const TEMPERATURE_TO_Y_SECOND_FACTOR_FIRST_EQUATION = 22087;
const TEMPERATURE_TO_Y_THIRD_FACTOR_FIRST_EQUATION = 35808;
const TEMPERATURE_TO_Y_FOURTH_FACTOR_FIRST_EQUATION = 3312;
const TEMPERATURE_TO_Y_FIRST_FACTOR_SECOND_EQUATION = 15645;
const TEMPERATURE_TO_Y_SECOND_FACTOR_SECOND_EQUATION = 22514;
const TEMPERATURE_TO_Y_THIRD_FACTOR_SECOND_EQUATION = 34265;
const TEMPERATURE_TO_Y_FOURTH_FACTOR_SECOND_EQUATION = 2744;
const TEMPERATURE_TO_Y_FIRST_FACTOR_THIRD_EQUATION = 50491;
const TEMPERATURE_TO_Y_SECOND_FACTOR_THIRD_EQUATION = 96229;
const TEMPERATURE_TO_Y_THIRD_FACTOR_THIRD_EQUATION = 61458;
const TEMPERATURE_TO_Y_FOURTH_FACTOR_THIRD_EQUATION = 6062;
let localX = 0;
let localY = 0;
const temp = 1000000 / temperature;
if (TEMPERATURE_TO_X_TEMPERATURE_THRESHOLD > temp) {
localX =
TEMPERATURE_TO_X_THIRD_FACTOR_FIRST_EQUATION / temp +
TEMPERATURE_TO_X_FOURTH_FACTOR_FIRST_EQUATION -
TEMPERATURE_TO_X_SECOND_FACTOR_FIRST_EQUATION / temp / temp -
TEMPERATURE_TO_X_FIRST_FACTOR_FIRST_EQUATION / temp / temp / temp;
}
else {
localX =
TEMPERATURE_TO_X_SECOND_FACTOR_SECOND_EQUATION / temp / temp +
TEMPERATURE_TO_X_THIRD_FACTOR_SECOND_EQUATION / temp +
TEMPERATURE_TO_X_FOURTH_FACTOR_SECOND_EQUATION -
TEMPERATURE_TO_X_FIRST_FACTOR_SECOND_EQUATION / temp / temp / temp;
}
if (TEMPERATURE_TO_Y_FIRST_TEMPERATURE_THRESHOLD > temp) {
localY =
(TEMPERATURE_TO_Y_THIRD_FACTOR_FIRST_EQUATION * localX) / 65536 -
(TEMPERATURE_TO_Y_FIRST_FACTOR_FIRST_EQUATION * localX * localX * localX) / 281474976710656 -
(TEMPERATURE_TO_Y_SECOND_FACTOR_FIRST_EQUATION * localX * localX) / 4294967296 -
TEMPERATURE_TO_Y_FOURTH_FACTOR_FIRST_EQUATION;
}
else if (TEMPERATURE_TO_Y_SECOND_TEMPERATURE_THRESHOLD > temp) {
localY =
(TEMPERATURE_TO_Y_THIRD_FACTOR_SECOND_EQUATION * localX) / 65536 -
(TEMPERATURE_TO_Y_FIRST_FACTOR_SECOND_EQUATION * localX * localX * localX) / 281474976710656 -
(TEMPERATURE_TO_Y_SECOND_FACTOR_SECOND_EQUATION * localX * localX) / 4294967296 -
TEMPERATURE_TO_Y_FOURTH_FACTOR_SECOND_EQUATION;
}
else {
localY =
(TEMPERATURE_TO_Y_THIRD_FACTOR_THIRD_EQUATION * localX) / 65536 +
(TEMPERATURE_TO_Y_FIRST_FACTOR_THIRD_EQUATION * localX * localX * localX) / 281474976710656 -
(TEMPERATURE_TO_Y_SECOND_FACTOR_THIRD_EQUATION * localX * localX) / 4294967296 -
TEMPERATURE_TO_Y_FOURTH_FACTOR_THIRD_EQUATION;
}
localY *= 4;
localX /= 0xffff;
localY /= 0xffff;
return [Math.round(localX * 10000) / 10000, Math.round(localY * 10000) / 10000];
}
exports.convertMiredColorTemperatureToXY = convertMiredColorTemperatureToXY;
//# sourceMappingURL=colorhelper.js.map