diff --git a/CHANGELOG.md b/CHANGELOG.md index aaec5e1d..bb62f59f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Added - Adaptive Lighting support [#335](https://github.com/NRCHKB/node-red-contrib-homekit-bridged/issues/335) +- By default, registered Eve.app Characteristics for power management - for existing setup, requires old custom characteristics file to be removed ### Changed diff --git a/package-lock.json b/package-lock.json index 680e5b73..b9b09a81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "1.7.0-dev.3", + "version": "1.7.0-dev.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "node-red-contrib-homekit-bridged", - "version": "1.7.0-dev.3", + "version": "1.7.0-dev.4", "license": "Apache-2.0", "dependencies": { "@nrchkb/logger": "^3.0.0", diff --git a/package.json b/package.json index cf2907d3..7e59dfab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-red-contrib-homekit-bridged", - "version": "1.7.0-dev.3", + "version": "1.7.0-dev.4", "description": "Node-RED nodes to simulate Apple HomeKit devices.", "main": "build/nodes/nrchkb.js", "scripts": { diff --git a/src/lib/api.ts b/src/lib/api.ts index b4ee2311..40e407c2 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -3,6 +3,7 @@ import express from 'express' import { Characteristic, Perms, SerializedService, Service } from 'hap-nodejs' import { NodeAPI } from 'node-red' +import EveCharacteristics from './hap/eve-app/EveCharacteristics' import { Storage } from './Storage' import CustomCharacteristicType from './types/CustomCharacteristicType' import HapCategories from './types/hap-nodejs/HapCategories' @@ -151,27 +152,27 @@ module.exports = function (RED: NodeAPI) { // NRCHKB Custom Characteristics API const _initNRCHKBCustomCharacteristicsAPI = async () => { - const getCustomCharacteristics = () => { - return Storage.loadCustomCharacteristics() - .then((value) => { - log.trace('loadCustomCharacteristics()') - log.trace(value) - - if (Array.isArray(value)) { - return value - } else { - log.debug( - 'customCharacteristics is not Array, returning empty value' - ) - return [] - } - }) - .catch((error) => { - log.error( - `Failed to get customCharacteristics in nrchkbStorage due to ${error}` + const getCustomCharacteristics = async () => { + try { + const value = await Storage.loadCustomCharacteristics() + + log.trace('loadCustomCharacteristics()') + log.trace(value) + + if (Array.isArray(value)) { + return value + } else { + log.debug( + 'customCharacteristics is not Array, returning empty value' ) - return [] - }) + return EveCharacteristics + } + } catch (error) { + log.error( + `Failed to get customCharacteristics in nrchkbStorage due to ${error}` + ) + return EveCharacteristics + } } const characteristicNameToKey = (name: string) => { @@ -353,7 +354,7 @@ module.exports = function (RED: NodeAPI) { RED.auth.needsPermission('nrchkb.write'), async (req: express.Request, res: express.Response) => { const customCharacteristics: CustomCharacteristicType[] = - req.body.customCharacteristics || [] + req.body.customCharacteristics || EveCharacteristics Storage.saveCustomCharacteristics(customCharacteristics) .then(() => { diff --git a/src/lib/hap/HAPCharacteristic.ts b/src/lib/hap/HAPCharacteristic.ts new file mode 100644 index 00000000..569f1898 --- /dev/null +++ b/src/lib/hap/HAPCharacteristic.ts @@ -0,0 +1,17 @@ +import { Characteristic } from 'hap-nodejs' + +import { + EveS2R1, + EveS2R2, + EveS2W1, + EveS2W2, +} from './eve-app/EveCharacteristics' + +class HAPCharacteristic extends Characteristic { + static EveS2R1: typeof EveS2R1 + static EveS2R2: typeof EveS2R2 + static EveS2W1: typeof EveS2W1 + static EveS2W2: typeof EveS2W2 +} + +export default HAPCharacteristic diff --git a/src/lib/hap/HAPService.ts b/src/lib/hap/HAPService.ts new file mode 100644 index 00000000..f6b45d26 --- /dev/null +++ b/src/lib/hap/HAPService.ts @@ -0,0 +1,9 @@ +import { Service } from 'hap-nodejs' + +import { EveHistoryData } from './eve-app/EveServices' + +class HAPService extends Service { + static EveHistoryData: typeof EveHistoryData +} + +export default HAPService diff --git a/src/lib/hap/eve-app/EveCharacteristics.ts b/src/lib/hap/eve-app/EveCharacteristics.ts new file mode 100644 index 00000000..cf70784e --- /dev/null +++ b/src/lib/hap/eve-app/EveCharacteristics.ts @@ -0,0 +1,101 @@ +import { Formats, Perms } from 'hap-nodejs/dist/lib/Characteristic' + +import CustomCharacteristicType from '../../types/CustomCharacteristicType' +import HAPCharacteristic from '../HAPCharacteristic' + +/** + * Based upon + * - https://gist.github.com/simont77/3f4d4330fa55b83f8ca96388d9004e7d + * - https://gist.github.com/gomfunkel/b1a046d729757120907c + * - https://github.com/simont77/fakegato-history/blob/master/fakegato-history.js + */ + +const EveCharacteristics: CustomCharacteristicType[] = [ + { + UUID: 'E863F10A-079E-48FF-8F27-9C2605A29F52', + name: 'Eve-Volt', + format: Formats.FLOAT, + perms: [Perms.PAIRED_READ], + description: 'Volt (V) value. Used by Eve.app.', + }, + { + UUID: 'E863F126-079E-48FF-8F27-9C2605A29F52', + name: 'Eve-Ampere', + format: Formats.FLOAT, + perms: [Perms.PAIRED_READ], + description: 'Ampere (A) value. Used by Eve.app.', + }, + { + UUID: 'E863F10D-079E-48FF-8F27-9C2605A29F52', + name: 'Eve-Watt', + format: Formats.FLOAT, + perms: [Perms.PAIRED_READ], + description: + 'Watt (W) value. Used by Eve.app, reported as "Consumption".', + }, + { + UUID: 'E863F10C-079E-48FF-8F27-9C2605A29F52', + name: 'Eve-Kilowatt-hour', + format: Formats.FLOAT, + perms: [Perms.PAIRED_READ], + description: + 'Kilowatt-hour (kWh) value. Used by Eve.app, reported as Total Consumption.', + }, + { + UUID: 'E863F110-079E-48FF-8F27-9C2605A29F52', + name: 'Eve-Volt-Ampere', + format: Formats.UINT16, + perms: [Perms.PAIRED_READ], + description: 'Volt-Ampere (VA) value. Used by Eve.app.', + }, +] + +export class EveS2R1 extends HAPCharacteristic { + public static readonly UUID: string = 'E863F116-079E-48FF-8F27-9C2605A29F52' + + constructor() { + super('Eve-S2R1', EveS2R1.UUID, { + format: Formats.DATA, + perms: [Perms.PAIRED_READ, Perms.NOTIFY, Perms.HIDDEN], + }) + } +} +HAPCharacteristic.EveS2R1 = EveS2R1 + +export class EveS2R2 extends HAPCharacteristic { + public static readonly UUID: string = 'E863F117-079E-48FF-8F27-9C2605A29F52' + + constructor() { + super('Eve-S2R2', EveS2R2.UUID, { + format: Formats.DATA, + perms: [Perms.PAIRED_READ, Perms.NOTIFY, Perms.HIDDEN], + }) + } +} +HAPCharacteristic.EveS2R2 = EveS2R2 + +export class EveS2W1 extends HAPCharacteristic { + public static readonly UUID: string = 'E863F11C-079E-48FF-8F27-9C2605A29F52' + + constructor() { + super('Eve-S2W1', EveS2W1.UUID, { + format: Formats.DATA, + perms: [Perms.PAIRED_WRITE, Perms.HIDDEN], + }) + } +} +HAPCharacteristic.EveS2W1 = EveS2W1 + +export class EveS2W2 extends HAPCharacteristic { + public static readonly UUID: string = 'E863F121-079E-48FF-8F27-9C2605A29F52' + + constructor() { + super('Eve-S2W2', EveS2W2.UUID, { + format: Formats.DATA, + perms: [Perms.PAIRED_WRITE, Perms.HIDDEN], + }) + } +} +HAPCharacteristic.EveS2W2 = EveS2W2 + +export default EveCharacteristics diff --git a/src/lib/hap/eve-app/EveServices.ts b/src/lib/hap/eve-app/EveServices.ts new file mode 100644 index 00000000..3e638ec1 --- /dev/null +++ b/src/lib/hap/eve-app/EveServices.ts @@ -0,0 +1,23 @@ +import HAPCharacteristic from '../HAPCharacteristic' +import HAPService from '../HAPService' + +/** + * Based on https://github.com/simont77/fakegato-history/blob/master/fakegato-history.js + */ + +export class EveHistoryData extends HAPService { + // Custom service for meta and/or historical information. Characteristics for logging: E863F11C, E863F121, E863F116, E863F117. Used by Eve.app. + public static readonly UUID: string = 'E863F007-079E-48FF-8F27-9C2605A29F52' + + constructor() { + super('EveHistoryData', EveHistoryData.UUID) + + // Required Characteristics + this.addCharacteristic(HAPCharacteristic.EveS2R1) + this.addCharacteristic(HAPCharacteristic.EveS2R2) + this.addCharacteristic(HAPCharacteristic.EveS2W1) + this.addCharacteristic(HAPCharacteristic.EveS2W2) + } +} + +HAPService.EveHistoryData = EveHistoryData