homebridge-z2m
Version:
Expose your Zigbee devices to HomeKit with ease, by integrating Zigbee2MQTT with Homebridge.
172 lines • 8.37 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.072310) + (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.011530);
// 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