homebridge-knx
Version:
homebridge shim for KNX home automation.
157 lines (140 loc) • 7.29 kB
JavaScript
/* jshint esversion: 6, strict: true, node: true */
/**
* The re-integrated knxdevice is alive again. This handles everything on the device level
*/
'use strict';
//requires**************************************************************************************************************
var ServiceKNX = require('./service-knx');
var iterate = require('./iterate');
//changes for plugin-2: the KNXDevice is not the accessory itself, it only creates an platformAccessory instance and holds it.
/**
* @classdesc KNXDevice represents an KNX accessory, containing a homekit accessory.
*/
class KNXDevice {
/**
*
* Creates a KNXDevice
* @param {object} globs - Global style object
* @param {object} config - config section for that device as Object (not JSON string).
* @param {API.platformAccessory} platformAccessory optional: if the accessory was restored by homebridge, it is passed for implementation here
* @return {KNXDevice}
*/
constructor (globs, config, platformAccessory) {
/** @type {globsObject} */
this.globs = globs;
/** @type {object} config - config section for that device as Object (not JSON string). */
this.config = config;
var accessoryServices = []; // for homeKit
/** @type {ServiceKNX[]} */
this.services = []; // for KNXDevice Objects (to keep)
/** @type {platformAccessory} */
this.platformAccessory = undefined;
if (config.DeviceName) {
/** @type {string} */
this.name = config.DeviceName;
}
if (!config.UUID) {
// default to name UNSAFE! --> create a random UUID base
this.uuid_base = 'KNX-' + Math.random() + Math.random() + Math.random() + '_device';
this.config.UUID = globs.API.hap.uuid.generate(this.uuid_base); // save for later reuse!
this.UUID = this.config.UUID; // for finding
}
// plugin-2 Accessory: If the accessory was restored by homebridge, we already have an instance
if (platformAccessory) {
this.platformAccessory = platformAccessory;
this.platformAccessory.existing = true;
globs.debug('Reused platformAccessory instance: ' + this.platformAccessory.displayName);
} else {
// create a new platformAccessory
// generate a context for reference on restarts
this.platformAccessory = new globs.API.platformAccessory(
this.name, // displayName property
(this.config.UUID), // UUID property - must not change later on
((config.HKCategory) ? globs.API.hap.Accessory.Categories[config.HKCategory] : undefined) // Category if present in in the config
);
//this.platformAccessory.context.ID = this.config.context;
// Test context:
//this.platformAccessory.context.TEST = 'Context-KNX' + Math.random() + Math.random() + Math.random();
this.platformAccessory.existing = false;
globs.debug('Created new platformAccessory instance: ' + this.platformAccessory.displayName);
}
//plugin-2
/******************
* The services are immediately prepared, and not waited for getServices() to be called
*/
var informationService = this.platformAccessory.getService(this.globs.Service.AccessoryInformation); //plugin-2
informationService.setCharacteristic(this.globs.Characteristic.Manufacturer, this.config.Manufacturer || "Opensource Community")
.setCharacteristic(this.globs.Characteristic.Model, this.config.Model || "KNX Universal Device by snowdd1")
.setCharacteristic(this.globs.Characteristic.SerialNumber,this.config.SerialNumber || "Build-" + (new Date()).toLocaleString());
accessoryServices.push(informationService);
this.platformAccessory.on('identify', function(paired, callback) {
this.globs.log(this.platformAccessory.displayName, "Identify!!!");
callback();
}.bind(this));
//iterate(this.config);
if (!this.config.Services) {
this.globs.log("warn","No 'Services' found in device?!");
}
/** @type {ServiceConfig[]}*/
var currServices = this.config.Services;
this.globs.debug("Preparing Services: " + currServices.length);
// go through the config thing and look for services
for (var int = 0; int < currServices.length; int++) {
var configService = currServices[int];
// services need to have type and name properties
if (!configService.ServiceType && !configService.ServiceName) {
this.globs.errorlog("[ERROR] must specify 'ServiceType' and 'ServiceName' properties for each service in knx_config.json. ");
throw new Error("Must specify 'ServiceType' and 'ServiceName' properties for each service in knx_config.json.");
}
this.globs.debug("Preparing Service: #" + int + " with name [" + configService.ServiceName + "] of ServiceType [" + configService.ServiceType + "]");
// find out if it is a known Service from the HomeKit types
var myKNXService = new ServiceKNX(this, configService, this.globs); // Service.ContactSensor(config.name,config.name);
if (myKNXService.failed) {
// something went wrong, could not establish valid service object
this.glob.errorlog("homebridge-knx couldn't create KNX service:" + configService.ServiceName);
} else {
// everything went fine!
this.globs.debug("KNX Service created");
this.services.push(myKNXService);
accessoryServices.push(myKNXService.getHomeKitService());
// the service is now successfully initialized
// (c) ctschach in https://github.com/ctschach/homebridge-knx/commit/5829bf2a1ccf2fa34e37b4d55d87c763a0d5e786
// changes: instead of onHKInit() now call onServiceInit()
// Let's check if we have a customHandler in this service and run the onHKInit function in case this exists
if (myKNXService.customServiceAPI && myKNXService.customServiceAPI.handler) {
if (typeof myKNXService.customServiceAPI.handler.onServiceInit === 'function') {
this.globs.debug("Custom Handler onServiceInit()");
myKNXService.customServiceAPI.handler.onServiceInit();
}
}
} // if-else
} //for
// if everything setup properly, we can inject it into homekit (if it wasn't existing before)
if (!this.platformAccessory.existing) {
globs.info('registering new Accessory ' + this.platformAccessory.displayName + ' with homebridge');
globs.API.registerPlatformAccessories("homebridge-knx", "KNX", [this.platformAccessory]);
} // if
// otherwise we were fine before.
this.platformAccessory.updateReachability(true);
} // constructor
/**
* Returns the inner homebridge PlatformAccessory member of the KNXDevice
*/
getPlatformAccessory () {
return this.platformAccessory;
}
/**
* Searches in returns a ServiceKNX object within the KNXDevice
* @param {string} name - The service Name to search for
* @returns {ServiceKNX}
*/
getServiceByName (name) {
for (var iSrv = 0; iSrv < this.services.length; iSrv++) {
var cSrv = this.services[iSrv];
if (name===cSrv.name) {return cSrv;}
}
return undefined;
}
}
// exports **************************************************************************************************************
module.exports = KNXDevice;