UNPKG

homebridge-homekit-proxy

Version:

Homebridge Homekit Proxy allows you to control HomeKit-enabled Devices directly from within HomeBridege. (Based on homebridge-homekit-controller by MartinPham)

524 lines 21.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SupportedServices = exports.classFromID = exports.listKnownCharacteristics = exports.listKnownServices = void 0; const util_1 = require("util"); const fakegato_history_1 = __importDefault(require("fakegato-history")); function listKnownServices(api, parent) { return [ api.hap.Service.HumiditySensor, api.hap.Service.TemperatureSensor, api.hap.Service.CarbonDioxideSensor, api.hap.Service.CarbonMonoxideSensor, api.hap.Service.AirQualitySensor, api.hap.Service.ProtocolInformation, api.hap.Service.AccessoryInformation, api.hap.Service.Switch, api.hap.Service.MotionSensor, api.hap.Service.BatteryService, api.hap.Service.Battery, api.hap.Service.Lightbulb, api.hap.Service.Outlet, api.hap.Service.LightSensor, api.hap.Service.IrrigationSystem, api.hap.Service.Valve, parent.LayoutDetectionService, parent.AnimationService, parent.FirmwareUpdateService, parent.CloudSyncService, ]; } exports.listKnownServices = listKnownServices; function listKnownCharacteristics(api, parent) { return [ api.hap.Characteristic.Identify, api.hap.Characteristic.Manufacturer, api.hap.Characteristic.Model, api.hap.Characteristic.Name, api.hap.Characteristic.SerialNumber, api.hap.Characteristic.FirmwareRevision, api.hap.Characteristic.HardwareRevision, api.hap.Characteristic.ProductData, api.hap.Characteristic.Version, api.hap.Characteristic.IsConfigured, api.hap.Characteristic.AirQuality, api.hap.Characteristic.PM2_5Density, api.hap.Characteristic.PM10Density, api.hap.Characteristic.CarbonDioxideDetected, api.hap.Characteristic.CarbonDioxideLevel, api.hap.Characteristic.CarbonDioxidePeakLevel, api.hap.Characteristic.CarbonMonoxideDetected, api.hap.Characteristic.CarbonMonoxideLevel, api.hap.Characteristic.CarbonMonoxidePeakLevel, api.hap.Characteristic.CurrentTemperature, api.hap.Characteristic.CurrentRelativeHumidity, api.hap.Characteristic.On, api.hap.Characteristic.OutletInUse, api.hap.Characteristic.MotionDetected, api.hap.Characteristic.StatusLowBattery, api.hap.Characteristic.BatteryLevel, api.hap.Characteristic.Brightness, api.hap.Characteristic.Hue, api.hap.Characteristic.ColorTemperature, api.hap.Characteristic.Saturation, api.hap.Characteristic.CurrentAmbientLightLevel, api.hap.Characteristic.AirParticulateDensity, api.hap.Characteristic.ChargingState, api.hap.Characteristic.Active, api.hap.Characteristic.ProgramMode, api.hap.Characteristic.InUse, api.hap.Characteristic.RemainingDuration, api.hap.Characteristic.StatusFault, api.hap.Characteristic.ValveType, api.hap.Characteristic.SetDuration, api.hap.Characteristic.ServiceLabelIndex, parent.CloudHomeSync, parent.CloudHomeSyncDescription, parent.CloudProvisioningHashString, parent.NanoleafColorTemperature, parent.AnimationSelect, parent.AnimationWrite, parent.AnimationRead, parent.AnimationList, parent.AnimationPlayList, parent.RythmActive, parent.RythmConnected, parent.RythmMode, parent.RythmAuxAvailable, parent.NanoleafCustomEventNotifications, parent.LayoutDetectionButton, parent.LayoutData, parent.GlobalOrientation, parent.ProductWarnings, parent.NewFirmwareVersion, parent.FirmwareAvailability, parent.InstallFirmwareUpdate, parent.SyncState, parent.RestoreFromCloud, ]; } exports.listKnownCharacteristics = listKnownCharacteristics; function shortType(type) { const parts = type.split('-'); if (parts.length > 0) { let p = 0; while (parts[0][p] === '0' && p < parts[0].length) { p++; } return parts[0].substring(p); } return type; } function mapShort(list) { const res = list .map((s) => { const item = [ { id: s.UUID, cls: s, }, { id: shortType(s.UUID), cls: s, }, ]; return item; }) .flat(1); return res; } function classFromID(list, id) { const result = list.find((item) => item.id === id); if (result) { return result.cls; } return undefined; } exports.classFromID = classFromID; function generateCharacteristic(api, name, UUID, perms) { const NewCharacteristic = function () { const self = this; api.hap.Characteristic.call(self, name, UUID, perms); self.value = self.getDefaultValue(); }; NewCharacteristic.UUID = UUID; NewCharacteristic.uuid = UUID; util_1.inherits(NewCharacteristic, api.hap.Characteristic); return NewCharacteristic; } function generateService(api, name, UUID, optionals) { if (optionals === undefined) { optionals = []; } const NewService = function (displayName, UUID, subtype) { const self = this; api.hap.Service.call(self, name, UUID, subtype); optionals === null || optionals === void 0 ? void 0 : optionals.forEach((o) => this.addOptionalCharacteristic(o)); }; NewService.UUID = UUID; NewService.uuid = UUID; util_1.inherits(NewService, api.hap.Service); return NewService; } //as defined here: https://github.com/simont77/fakegato-history/wiki/Services-and-characteristics-for-Elgato-Eve-devices function _buildEveAirQuality(api) { return generateCharacteristic(api, 'Air Quality PM25', 'E863F10B-079E-48FF-8F27-9C2605A29F52', { format: "uint16" /* UINT16 */, unit: 'ppm', maxValue: 65535, minValue: 450, minStep: 1, perms: ["pr" /* PAIRED_READ */, "ev" /* NOTIFY */], }); } function _buildCloudProvisioningHashString(api) { return generateCharacteristic(api, 'Cloud Provisioning Hash String', 'A18E8903-CFA1-4D37-A10F-0071CEEEEEBD', { format: "string" /* STRING */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */], }); } function _buildCloudHomeSync(api) { return generateCharacteristic(api, 'Cloud Home Sync Description', 'A18E8902-CFA1-4D37-A10F-0071CEEEEEBD', { format: "data" /* DATA */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */], }); } function _buildCloudHomeSyncDescription(api) { return generateCharacteristic(api, 'Cloud Home Sync Description', 'A18E8902-CFA1-4D37-A10F-0071CEEEEEBD', { format: "data" /* DATA */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */], }); } function _buildNanoleafColorTemperature(api) { return generateCharacteristic(api, 'Color Temperature', 'A18E5901-CFA1-4D37-A10F-0071CEEEEEBD', { format: "int" /* INT */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "pw" /* PAIRED_WRITE */, "ev" /* NOTIFY */], minValue: 1200, maxValue: 6500, minStep: 1, }); } function _buildAnimationSelect(api) { return generateCharacteristic(api, 'Animation Select', 'A18E6902-CFA1-4D37-A10F-0071CEEEEEBD', { format: "string" /* STRING */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "pw" /* PAIRED_WRITE */, "ev" /* NOTIFY */], }); } function _buildAnimationWrite(api) { return generateCharacteristic(api, 'Animation Write', 'A18E6903-CFA1-4D37-A10F-0071CEEEEEBD', { format: "data" /* DATA */, perms: ["pw" /* PAIRED_WRITE */, "hd" /* HIDDEN */], }); } function _buildAnimationRead(api) { return generateCharacteristic(api, 'Animation Read', 'A18E6904-CFA1-4D37-A10F-0071CEEEEEBD', { format: "data" /* DATA */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */], }); } function _buildAnimationList(api) { return generateCharacteristic(api, 'Animation List', 'A18E6905-CFA1-4D37-A10F-0071CEEEEEBD', { format: "data" /* DATA */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "ev" /* NOTIFY */], }); } function _buildAnimationPlayList(api) { return generateCharacteristic(api, 'Animation Playlist', 'A18E690B-CFA1-4D37-A10F-0071CEEEEEBD', { format: "string" /* STRING */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "ev" /* NOTIFY */], }); } function _buildRythmActive(api) { return generateCharacteristic(api, 'Rhythm Active', 'A18E6907-CFA1-4D37-A10F-0071CEEEEEBD', { format: "bool" /* BOOL */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "ev" /* NOTIFY */], }); } function _buildRythmConnected(api) { return generateCharacteristic(api, 'Rhythm Connected', 'A18E6906-CFA1-4D37-A10F-0071CEEEEEBD', { format: "bool" /* BOOL */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "ev" /* NOTIFY */], }); } function _buildRythmMode(api) { return generateCharacteristic(api, 'Rhythm Mode', 'A18E6908-CFA1-4D37-A10F-0071CEEEEEBD', { format: "int" /* INT */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "ev" /* NOTIFY */, "pw" /* PAIRED_WRITE */], maxValue: 1, minValue: 0, minStep: 1, unit: 'int', }); } function _buildRythmAuxAvailable(api) { return generateCharacteristic(api, 'Rhythm Aux Available', 'A18E6909-CFA1-4D37-A10F-0071CEEEEEBD', { format: "bool" /* BOOL */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "ev" /* NOTIFY */], }); } function _buildNanoleafCustomEventNotifications(api) { return generateCharacteristic(api, 'Custom Event Notifications', 'A18E690A-CFA1-4D37-A10F-0071CEEEEEBD', { format: "data" /* DATA */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "ev" /* NOTIFY */], }); } function _buildLayoutDetectionButton(api) { return generateCharacteristic(api, 'Layout Detection Button', 'A18E7902-CFA1-4D37-A10F-0071CEEEEEBD', { format: "bool" /* BOOL */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "pw" /* PAIRED_WRITE */], }); } function _buildLayoutData(api) { return generateCharacteristic(api, 'Layout Data', 'A18E7903-CFA1-4D37-A10F-0071CEEEEEBD', { format: "data" /* DATA */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "ev" /* NOTIFY */], }); } function _buildGlobalOrientation(api) { return generateCharacteristic(api, 'Global Orientation', 'A18E7904-CFA1-4D37-A10F-0071CEEEEEBD', { format: "int" /* INT */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "ev" /* NOTIFY */, "pw" /* PAIRED_WRITE */], maxValue: 360, minValue: 0, minStep: 1, }); } function _buildProductWarning(api) { return generateCharacteristic(api, 'Product Warnings', 'A18E7905-CFA1-4D37-A10F-0071CEEEEEBD', { format: "data" /* DATA */, perms: ["pr" /* PAIRED_READ */, "ev" /* NOTIFY */, "hd" /* HIDDEN */], }); } function _buildNewFirmwareVersion(api) { return generateCharacteristic(api, 'New Firmware Version', 'A18E1905-CFA1-4D37-A10F-0071CEEEEEBD', { format: "string" /* STRING */, perms: ["pr" /* PAIRED_READ */, "ev" /* NOTIFY */], }); } function _buildFirmwareAvailability(api) { return generateCharacteristic(api, 'Firmware Availability', 'A18E1904-CFA1-4D37-A10F-0071CEEEEEBD', { format: "bool" /* BOOL */, perms: ["pr" /* PAIRED_READ */, "ev" /* NOTIFY */, "hd" /* HIDDEN */], }); } function _buildInstallFirmwareUpdate(api) { return generateCharacteristic(api, 'Install Firmware Update', 'A18E1902-CFA1-4D37-A10F-0071CEEEEEBD', { format: "bool" /* BOOL */, perms: ["pr" /* PAIRED_READ */, "hd" /* HIDDEN */, "pw" /* PAIRED_WRITE */], }); } function _buildSyncState(api) { return generateCharacteristic(api, 'Sync State', 'A18EB902-CFA1-4D37-A10F-0071CEEEEEBD', { format: "int" /* INT */, perms: ["pr" /* PAIRED_READ */, "pw" /* PAIRED_WRITE */, "pw" /* PAIRED_WRITE */], maxValue: 2, minValue: 0, minStep: 1, }); } function _buildRestoreFromCloud(api) { return generateCharacteristic(api, 'Restore From Cloud', 'A18EB903-CFA1-4D37-A10F-0071CEEEEEBD', { format: "bool" /* BOOL */, perms: ["pw" /* PAIRED_WRITE */], }); } function _buildLayoutDetectionService(api, parent) { return generateService(api, 'Layout Detection Service', 'A18E7901-CFA1-4D37-A10F-0071CEEEEEBD', [parent.LayoutDetectionButton, parent.LayoutData, parent.GlobalOrientation, parent.ProductWarnings]); } function _buildAnimationService(api, parent) { return generateService(api, 'Animation Service', 'A18E6901-CFA1-4D37-A10F-0071CEEEEEBD', [ parent.AnimationSelect, parent.AnimationWrite, parent.AnimationRead, parent.AnimationList, parent.AnimationPlayList, parent.RythmActive, parent.RythmConnected, parent.RythmMode, parent.RythmAuxAvailable, parent.NanoleafCustomEventNotifications, ]); } function _buildFirmwareUpdateService(api, parent) { return generateService(api, 'Firmware Update Service', 'A18E1901-CFA1-4D37-A10F-0071CEEEEEBD', [parent.NewFirmwareVersion, parent.FirmwareAvailability, parent.InstallFirmwareUpdate]); } function _buildCloudSyncService(api, parent) { return generateService(api, 'Cloud Sync', 'A18EB901-CFA1-4D37-A10F-0071CEEEEEBD', [parent.SyncState, parent.RestoreFromCloud]); } class SupportedServices { constructor(api) { this.api = api; this.EveAirQuality = _buildEveAirQuality(api); this.FakeGatoService = fakegato_history_1.default(api); this.CloudProvisioningHashString = _buildCloudProvisioningHashString(api); this.CloudHomeSyncDescription = _buildCloudHomeSyncDescription(api); this.CloudHomeSync = _buildCloudHomeSync(api); this.NanoleafColorTemperature = _buildNanoleafColorTemperature(api); this.AnimationSelect = _buildAnimationSelect(api); this.AnimationRead = _buildAnimationRead(api); this.AnimationWrite = _buildAnimationWrite(api); this.AnimationList = _buildAnimationList(api); this.AnimationPlayList = _buildAnimationPlayList(api); this.RythmActive = _buildRythmActive(api); this.RythmConnected = _buildRythmConnected(api); this.RythmMode = _buildRythmMode(api); this.RythmAuxAvailable = _buildRythmAuxAvailable(api); this.NanoleafCustomEventNotifications = _buildNanoleafCustomEventNotifications(api); this.LayoutDetectionButton = _buildLayoutDetectionButton(api); this.LayoutData = _buildLayoutData(api); this.GlobalOrientation = _buildGlobalOrientation(api); this.ProductWarnings = _buildProductWarning(api); this.NewFirmwareVersion = _buildNewFirmwareVersion(api); this.FirmwareAvailability = _buildFirmwareAvailability(api); this.InstallFirmwareUpdate = _buildInstallFirmwareUpdate(api); this.SyncState = _buildSyncState(api); this.RestoreFromCloud = _buildRestoreFromCloud(api); this.LayoutDetectionService = _buildLayoutDetectionService(api, this); this.AnimationService = _buildAnimationService(api, this); this.FirmwareUpdateService = _buildFirmwareUpdateService(api, this); this.CloudSyncService = _buildCloudSyncService(api, this); this._KnownServiceMap = mapShort(listKnownServices(api, this)); this._KnownCharMap = mapShort(listKnownCharacteristics(api, this)); // this.EveAirQuality = class EveAirQuality extends api.hap.Characteristic { // static readonly UUID: string = 'E863F10B-079E-48FF-8F27-9C2605A29F52' // constructor() { // super('Air Quality PM25', EveAirQuality.UUID, { // format: Formats.UINT16, // perms: [Perms.NOTIFY, Perms.PAIRED_READ], // maxValue: 65535, // minValue: 500, // minStep: 1, // }) // this.value = this.getDefaultValue() // } // } } get KnownServiceMap() { return this._KnownServiceMap; } get KnownCharMap() { return this._KnownCharMap; } isID(needle, haystack) { needle = needle.toLocaleUpperCase().trim(); haystack = haystack.toLocaleUpperCase().trim(); if (needle === haystack) { return true; } while (needle.length < 8) { needle = '0' + needle; } haystack = haystack.substring(0, 8); return needle === haystack; } toPerm(inp) { return inp.map((p) => { if (p === 'pw') { return "pw" /* PAIRED_WRITE */; } if (p === 'wr') { return "wr" /* WRITE_RESPONSE */; } if (p === 'pr') { return "pr" /* PAIRED_READ */; } if (p === 'ev') { return "ev" /* EVENTS */; } if (p === 'aa') { return "aa" /* ADDITIONAL_AUTHORIZATION */; } if (p === 'tw') { return "tw" /* TIMED_WRITE */; } if (p === 'hd') { return "hd" /* HIDDEN */; } return "hd" /* HIDDEN */; }); } classForService(type, source) { const cl = classFromID(this._KnownServiceMap, type); if (source === undefined) { return cl; } //auto-create new service if (cl == undefined) { const allKeys = Object.keys(this.api.hap.Service); const matches = allKeys .filter((key) => this.api.hap.Service[key].UUID != undefined) .map((key) => this.api.hap.Service[key]) .filter((service) => this.isID(type, service.UUID)); if (matches.length == 1 || matches.length == 0) { let s; if (matches.length == 1) { s = matches[0]; } else { const characteristics = source.characteristics.map((cIn) => this.classForChar(cIn.type, cIn)); const names = source.characteristics.filter((c) => c.type === '23' || c.type === this.api.hap.Characteristic.Name.UUID); const name = names.length > 0 ? names[0].value : undefined; s = generateService(this.api, name == undefined ? '' : name, type, characteristics); } this._KnownServiceMap.push({ id: s.UUID, cls: s, }); this._KnownServiceMap.push({ id: shortType(s.UUID), cls: s, }); return s; } } return cl; } copyCharacteristic(type, source) { const name = source.description; return generateCharacteristic(this.api, name === undefined ? '' : name, type, { format: source.format, perms: this.toPerm(source.perms), unit: source.unit, description: source.description, minValue: source.minValue, maxValue: source.maxValue, minStep: source.minStep, maxLen: source.maxLen, maxDataLen: source.format === "data" /* DATA */ ? undefined : source.maxDataLen, validValues: source.validValues, validValueRanges: source.validValueRanges, adminOnlyAccess: source.adminOnlyAccess, }); } classForChar(type, source) { const cl = classFromID(this._KnownCharMap, type); if (source === undefined) { return cl; } //auto-create new characteristic if (cl == undefined) { const allKeys = Object.keys(this.api.hap.Characteristic); const matches = allKeys .filter((key) => this.api.hap.Characteristic[key].UUID != undefined) .map((key) => this.api.hap.Characteristic[key]) .filter((char) => this.isID(type, char.UUID)); if (matches.length == 1 || matches.length == 0) { const c = matches.length == 1 ? matches[0] : this.copyCharacteristic(type, source); this._KnownCharMap.push({ id: c.UUID, cls: c, }); this._KnownCharMap.push({ id: shortType(c.UUID), cls: c, }); return c; } } return cl; } } exports.SupportedServices = SupportedServices; //# sourceMappingURL=SupportedDevices.js.map