UNPKG

homebridge-z2m

Version:

Expose your Zigbee devices to HomeKit with ease, by integrating Zigbee2MQTT with Homebridge.

172 lines 8.37 kB
"use strict"; 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