Skip to content

Instantly share code, notes, and snippets.

@Samfox2
Created March 27, 2018 19:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Samfox2/712eb2a012d36d0a43e83968043addf9 to your computer and use it in GitHub Desktop.
Save Samfox2/712eb2a012d36d0a43e83968043addf9 to your computer and use it in GitHub Desktop.
Domotiga + waterlevel
//"use strict";
var Accessory, Service, Characteristic, UUIDGen;
var JSONRequest = require("jsonrequest");
var inherits = require('util').inherits;
var path = require('path');
var fs = require('fs');
var moment = require('moment');
let localCache;
let localPath;
let _homebridge;
module.exports = function (homebridge) {
console.log("homebridge API version: " + homebridge.version);
// Paths
localCache = path.join(homebridge.user.storagePath(), 'domotiga.json');
localPath = homebridge.user.storagePath()
_homebridge = homebridge;
// Accessory must be created from PlatformAccessory Constructor
Accessory = homebridge.platformAccessory;
// Service and Characteristic are from hap-nodejs
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
UUIDGen = homebridge.hap.uuid;
////////////////////////////// Custom characteristics //////////////////////////////
Characteristic.EvePowerConsumption = function () {
Characteristic.call(this, 'Consumption', 'E863F10D-079E-48FF-8F27-9C2605A29F52');
this.setProps({
format: Characteristic.Formats.UINT16,
unit: "watts",
maxValue: 1000000000,
minValue: 0,
minStep: 1,
perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY]
});
this.value = this.getDefaultValue();
};
inherits(Characteristic.EvePowerConsumption, Characteristic);
Characteristic.EvePowerConsumption.UUID = 'E863F10D-079E-48FF-8F27-9C2605A29F52';
Characteristic.EveTotalPowerConsumption = function () {
Characteristic.call(this, 'Total Consumption', 'E863F10C-079E-48FF-8F27-9C2605A29F52');
this.setProps({
format: Characteristic.Formats.FLOAT, // Deviation from Eve Energy observed type
unit: "kilowatthours",
maxValue: 1000000000,
minValue: 0,
minStep: 0.001,
perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY]
});
this.value = this.getDefaultValue();
};
inherits(Characteristic.EveTotalPowerConsumption, Characteristic);
Characteristic.EveTotalPowerConsumption.UUID = 'E863F10C-079E-48FF-8F27-9C2605A29F52';
Characteristic.EveRoomAirQuality = function () {
Characteristic.call(this, 'Air Quality PM25', 'E863F10B-079E-48FF-8F27-9C2605A29F52');
this.setProps({
format: Characteristic.Formats.UINT16,
unit: "ppm",
maxValue: 5000,
minValue: 0,
minStep: 1,
perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY]
});
this.value = this.getDefaultValue();
};
inherits(Characteristic.EveRoomAirQuality, Characteristic);
Characteristic.EveRoomAirQuality.UUID = 'E863F10B-079E-48FF-8F27-9C2605A29F52';
Characteristic.EveBatteryLevel = function () {
Characteristic.call(this, 'Eve Battery Level', 'E863F11B-079E-48FF-8F27-9C2605A29F52');
this.setProps({
format: Characteristic.Formats.UINT16,
unit: "PERCENTAGE",
maxValue: 100,
minValue: 0,
minStep: 1,
perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY]
});
this.value = this.getDefaultValue();
};
inherits(Characteristic.EveBatteryLevel, Characteristic);
Characteristic.EveBatteryLevel.UUID = 'E863F11B-079E-48FF-8F27-9C2605A29F52';
Characteristic.EveAirPressure = function () {
//todo: only rough guess of extreme values -> use correct min/max if known
Characteristic.call(this, 'Eve AirPressure', 'E863F10F-079E-48FF-8F27-9C2605A29F52');
this.setProps({
format: Characteristic.Formats.UINT16,
unit: "hPa",
maxValue: 1085,
minValue: 870,
minStep: 1,
perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY]
});
this.value = this.getDefaultValue();
};
inherits(Characteristic.EveAirPressure, Characteristic);
Characteristic.EveAirPressure.UUID = 'E863F10F-079E-48FF-8F27-9C2605A29F52';
////////////////////////////// Custom services //////////////////////////////
Service.PowerMeterService = function (displayName, subtype) {
Service.call(this, displayName, '00000001-0000-1777-8000-775D67EC4377', subtype);
// Required Characteristics
this.addCharacteristic(Characteristic.EvePowerConsumption);
// Optional Characteristics
this.addOptionalCharacteristic(Characteristic.EveTotalPowerConsumption);
};
inherits(Service.PowerMeterService, Service);
Service.PowerMeterService.UUID = '00000001-0000-1777-8000-775D67EC4377';
// Eve service (custom UUID)
Service.EveRoomService = function (displayName, subtype) {
Service.call(this, displayName, 'E863F002-079E-48FF-8F27-9C2605A29F52', subtype);
// Required Characteristics
this.addCharacteristic(Characteristic.EveRoomAirQuality);
// Optional Characteristics
this.addOptionalCharacteristic(Characteristic.CurrentRelativeHumidity);
};
inherits(Service.EveRoomService, Service);
Service.EveRoomService.UUID = 'E863F002-079E-48FF-8F27-9C2605A29F52';
// Eve service (custom UUID)
Service.EveWeatherService = function (displayName, subtype) {
Service.call(this, displayName, 'E863F001-079E-48FF-8F27-9C2605A29F52', subtype);
// Required Characteristics
this.addCharacteristic(Characteristic.EveAirPressure);
// Optional Characteristics
this.addOptionalCharacteristic(Characteristic.CurrentRelativeHumidity);
this.addOptionalCharacteristic(Characteristic.CurrentTemperature);
this.addOptionalCharacteristic(Characteristic.EveBatteryLevel);
};
inherits(Service.EveWeatherService, Service);
Service.EveWeatherService.UUID = 'E863F001-079E-48FF-8F27-9C2605A29F52';
// Eve logging service (custom UUID)
Service.FakeGatoHistoryService = require('fakegato-history')(homebridge);
inherits(Service.FakeGatoHistoryService, Service);
Service.FakeGatoHistoryService.UUID = 'E863F007-079E-48FF-8F27-9C2605A29F52';
/////////////////////////////////////////////////////////////////////////////////////////////
// Consider platform plugin as dynamic platform plugin
homebridge.registerPlatform("homebridge-domotiga", "DomotiGa", DomotigaPlatform, true);
}
function DomotigaPlatform(log, config, api) {
this.log = log;
this.config = config;
this.log("DomotiGa Plugin Version " + this.getVersion());
this.log("Plugin by Samfox2 https://github.com/samfox2");
this.log("DomotiGa is a Open Source Home Automation Software for Linux");
this.log("Please report any issues to https://github.com/samfox2/homebridge-domotiga/issues");
var self = this;
self.fetch_npmVersion("homebridge-domotiga", function (npmVersion) {
npmVersion = npmVersion.replace('\n', '');
self.log("NPM %s vs Local %s", npmVersion, self.getVersion());
if (npmVersion > self.getVersion()) {
self.log.warn("There is a new Version available. Please update with sudo npm -g update homebridge-domotiga");
}
});
if (config) {
// Global configuration
this.host = this.config.host || 'localhost';
this.port = this.config.port || 9090;
// Device specific configuration
this.devices = this.config.devices || [];
this.accessories = {};
this.polling = {};
if (api) {
this.api = api;
this.api.on('didFinishLaunching', this.didFinishLaunching.bind(this));
}
}
}
// Method to restore accessories from cache
DomotigaPlatform.prototype.configureAccessory = function (accessory) {
this.setService(accessory);
this.accessories[accessory.context.name] = accessory;
}
// Method to setup accessories from config.json
DomotigaPlatform.prototype.didFinishLaunching = function () {
if (!this.devices.length) {
this.log.error("No devices configured. Please check your 'config.json' file!");
}
// Add or update accessories defined in config.json
for (var i in this.devices) this.addAccessory(this.devices[i]);
// Remove extra accessories in cache
for (var name in this.accessories) {
var accessory = this.accessories[name];
if (!accessory.reachable) this.removeAccessory(accessory);
}
// Check number of devices
const noD = this.accessories.length;
this.log("Number of mapped devices : " + noD);
if (noD > 100) {
this.log.error("********************************************");
this.log.error("* You are using more than 100 HomeKit *");
this.log.error("* devices behind a bridge. At this time *");
this.log.error("* HomeKit only supports up to 100 devices. *");
this.log.error("* This may end up that iOS is not able to *");
this.log.error("* connect to the bridge anymore. *");
this.log.error("********************************************");
} else {
if (noD > 90) {
this.log.warn("You are using more than 90 HomeKit");
this.log.warn("devices behind a bridge. At this time");
this.log.warn("HomeKit only supports up to 100 devices.");
this.log.warn("This is just a warning. Everything should");
this.log.warn("work fine until you are below that 100.");
}
}
}
// Method to add and update HomeKit accessories
DomotigaPlatform.prototype.addAccessory = function (data) {
this.log("Initializing platform accessory '" + data.name + "'...");
// Retrieve accessory from cache
var accessory = this.accessories[data.name];
if (!accessory) {
var uuid = UUIDGen.generate(data.name);
// Setup accessory category.
accessory = new Accessory(data.name, uuid, 8);
// Store and initialize logfile into context
accessory.context.name = data.name || "NA";
accessory.context.service = data.service;
accessory.context.device = data.device;
accessory.context.manufacturer = data.manufacturer || "NA";
accessory.context.model = data.model || "NA";
accessory.context.valueTemperature = data.valueTemperature;
accessory.context.valueHumidity = data.valueHumidity;
accessory.context.valueAirPressure = data.valueAirPressure;
accessory.context.valueBattery = data.valueBattery;
accessory.context.lowbattery = data.lowbattery;
accessory.context.valueContact = data.valueContact;
accessory.context.valueSwitch = data.valueSwitch;
accessory.context.valueDoor = data.valueDoor;
accessory.context.valueWindow = data.valueWindow;
accessory.context.valueWindowCovering = data.valueWindowCovering;
accessory.context.valueAirQuality = data.valueAirQuality;
accessory.context.valueOutlet = data.valueOutlet;
accessory.context.valueLeakSensor = data.valueLeakSensor;
accessory.context.valueMotionSensor = data.valueMotionSensor;
accessory.context.valuePowerConsumption = data.valuePowerConsumption;
accessory.context.valueTotalPowerConsumption = data.valueTotalPowerConsumption;
accessory.context.valueWaterLevel = data.valueWaterLevel;
accessory.context.valueLight = data.valueLight;
accessory.context.brightness = data.brightness;
accessory.context.color = data.color;
// if color is enabled, we need all three properties
if (accessory.context.color) {
accessory.context.hue = true;
accessory.context.staturation = true;
accessory.context.brightness = true;
}
accessory.context.valueTargetTemperature = data.valueTargetTemperature;
accessory.context.CurrentHeatingCoolingState = Characteristic.CurrentHeatingCoolingState.AUTO; //fixed as DomotiGa doesn't expose this property
accessory.context.TargetHeatingCoolingState = Characteristic.TargetHeatingCoolingState.AUTO; //fixed as DomotiGa doesn't expose this property
accessory.context.CurrentTemperature = data.CurrentTemperature;
accessory.context.TargetTemperature = data.TargetTemperature;
accessory.context.TemperatureDisplayUnits = Characteristic.TemperatureDisplayUnits.CELSIUS; //fixed
accessory.context.polling = data.polling;
accessory.context.pollingInterval = data.pollingInterval * 1000 || 1000;
accessory.context.logType = "unknown";
var primaryservice;
// Setup HomeKit service(-s)
switch (accessory.context.service) {
case "TemperatureSensor":
primaryservice = new Service.TemperatureSensor(accessory.context.name);
if (!accessory.context.valueTemperature) {
this.log.error('%s: missing definition of valueTemperature in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "room";
break;
case "HumiditySensor":
primaryservice = new Service.HumiditySensor(accessory.context.name);
if (!accessory.context.valueHumidity) {
this.log.error('%s: missing definition of valueHumidity in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "room";
break;
case "HumidifierDehumidifier":
primaryservice = new Service.HumidifierDehumidifier(accessory.context.name);
if (!accessory.context.valueWaterLevel) {
this.log.error('%s: missing definition of valueWaterLevel in config.json!', accessory.context.name);
return;
}
break;
case "Contact":
primaryservice = new Service.ContactSensor(accessory.context.name);
if (!accessory.context.valueContact) {
this.log.error('%s: missing definition of valueContact in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "door";
break;
case "LeakSensor":
primaryservice = new Service.LeakSensor(accessory.context.name);
if (!accessory.context.valueLeakSensor) {
this.log.error('%s: missing definition of valueLeakSensor in config.json!', accessory.context.name);
return;
}
break;
case "MotionSensor":
primaryservice = new Service.MotionSensor(accessory.context.name);
if (!accessory.context.valueMotionSensor) {
this.log.error('%s: missing definition of valueMotionSensor in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "motion";
break;
case "Switch":
primaryservice = new Service.Switch(accessory.context.name);
if (!accessory.context.valueSwitch) {
this.log.error('%s: missing definition of valueSwitch in config.json!', accessory.context.name);
return;
}
break;
case "Door":
primaryservice = new Service.Door(accessory.context.name);
if (!accessory.context.valueDoor) {
this.log.error('%s: missing definition of valueDoor in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "door";
break;
case "Window":
primaryservice = new Service.Window(accessory.context.name);
if (!accessory.context.valueWindow) {
this.log.error('%s: missing definition of valueWindow in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "door";
break;
case "WindowCovering":
primaryservice = new Service.WindowCovering(accessory.context.name);
if (!accessory.context.valueWindowCovering) {
this.log.error('%s: missing definition of valueWindowCovering in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "door";
break;
case "Outlet":
primaryservice = new Service.Outlet(accessory.context.name);
if (!accessory.context.valueOutlet) {
this.log.error('%s: missing definition of valueOutlet in config.json!', accessory.context.name);
return;
}
break;
case "AirQualitySensor":
primaryservice = new Service.AirQualitySensor(accessory.context.name);
if (!accessory.context.valueAirQuality) {
this.log.error('%s: missing definition of valueAirQuality in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "room";
break;
case "FakeEveAirQualitySensor":
primaryservice = new Service.EveRoomService("Eve Room");
if (!accessory.context.valueAirQuality) {
this.log.error('%s: missing definition of valueAirQuality in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "room";
break;
case "FakeEveWeatherSensor":
primaryservice = new Service.EveWeatherService("Eve Weather");
if (!accessory.context.valueAirPressure) {
this.log.error('%s: missing definition of valueAirPressure in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "weather";
break;
case "Powermeter":
primaryservice = new Service.PowerMeterService(accessory.context.name);
if (!accessory.context.valuePowerConsumption) {
this.log.error('%s: missing definition of valuePowerConsumption in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "energy";
break;
case "Lightbulb":
primaryservice = new Service.Lightbulb(accessory.context.name);
if (!accessory.context.valueLight) {
this.log.warn('%s: missing definition of valueLight in config.json!', accessory.context.name);
return;
}
break;
case "Thermostat":
primaryservice = new Service.Thermostat(accessory.context.name);
if (!accessory.context.valueTemperature) {
this.log.error('%s: missing definition of valueTemperature in config.json!', accessory.context.name);
return;
}
if (!accessory.context.valueTargetTemperature) {
this.log.warn('%s: missing definition of valueThermostat in config.json!', accessory.context.name);
return;
}
accessory.context.logType = "thermo";
break;
default:
this.log.error('Service %s %s unknown for add, skipping...', accessory.context.service, accessory.context.name);
return;
break;
}
// Setup HomeKit switch service
accessory.addService(primaryservice, data.name);
// Everything outside the primary service gets added as additional characteristics...
if (accessory.context.valueTemperature && (accessory.context.service != "TemperatureSensor") && (accessory.context.service != "Thermostat")) {
accessory.addService(new Service.TemperatureSensor(accessory.context.name), data.name + accessory.context.valueTemperature );
}
if (accessory.context.valueHumidity && (accessory.context.service != "HumiditySensor")) {
accessory.addService(new Service.HumiditySensor(accessory.context.name), data.name + accessory.context.valueHumidity);
}
if (accessory.context.valueAirQuality&& (accessory.context.service != "AirQualitySensor") ) {
accessory.addService(new Service.AirQualitySensor(accessory.context.name), data.name + accessory.context.valueAirQuality).addCharacteristic(Characteristic.VOCDensity);
}
if (accessory.context.valueWaterLevel) {
primaryservice.addCharacteristic(Characteristic.WaterLevel);
}
if (accessory.context.valueBattery) {
primaryservice.addCharacteristic(Characteristic.BatteryLevel);
}
if (accessory.context.lowbattery) {
primaryservice.addCharacteristic(Characteristic.StatusLowBattery);
}
// Eve characteristic (custom UUID)
if (accessory.context.valueAirPressure &&
(accessory.context.service != "FakeEveWeatherSensor")) {
primaryservice.addCharacteristic(Characteristic.EveAirPressure);
accessory.context.logType = "weather";
}
// Eve characteristic (custom UUID)
if (accessory.context.valueAirQuality &&
(accessory.context.service != "AirQualitySensor") && (accessory.context.service != "FakeEveAirQualitySensor")) {
primaryservice.addCharacteristic(Characteristic.AirQuality);
accessory.context.logType = "room";
}
// Eve characteristic (custom UUID)
if (accessory.context.valuePowerConsumption && (accessory.context.service != "Powermeter")) {
primaryservice.addCharacteristic(Characteristic.EvePowerConsumption);
}
// Eve characteristic (custom UUID)
if (accessory.context.valueTotalPowerConsumption) {
primaryservice.addCharacteristic(Characteristic.EveTotalPowerConsumption);
}
// New accessory is always reachable
accessory.reachable = true;
// Setup listeners for different events
this.setService(accessory);
// Register accessory in HomeKit
this.api.registerPlatformAccessories("homebridge-domotiga", "DomotiGa", [accessory]);
// Store accessory in cache
this.accessories[data.name] = accessory;
}
// Confirm variable type
data.polling = data.polling === true;
data.pollingInterval = parseInt(data.pollingInterval, 10) * 1000 || 1000; // [s] -> [ms]
// Store and initialize variables into context
accessory.context.cacheCurrentTemperature = 0;
accessory.context.cacheCurrentRelativeHumidity = 99;
accessory.context.cacheWaterLevel = 0.0;
accessory.context.cacheCurrentAirPressure = 1000;
accessory.context.cacheContactSensorState = Characteristic.ContactSensorState.CONTACT_DETECTED;
accessory.context.cacheLeakSensorState = Characteristic.LeakDetected.LEAK_NOT_DETECTED;
accessory.context.cacheOutletState = 0;
accessory.context.cacheOutletInUse = false;
accessory.context.cacheCurrentAirQuality = Characteristic.AirQuality.POOR;
accessory.context.cacheCurrentEveAirQuality = 0;
accessory.context.cachePowerConsumption = 0;
accessory.context.cacheTotalPowerConsumption = 0;
accessory.context.cacheCurrentBatteryLevel = 0;
accessory.context.cacheStatusLowBattery = Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
accessory.context.cacheMotionSensorState = 0;
accessory.context.cacheSwitchState = 0;
accessory.context.cacheDoorPosition = 0;
accessory.context.cacheWindowPosition = 0;
accessory.context.cacheWindowCoveringPosition = 0;
accessory.context.cacheLightState = 0;
accessory.context.cacheLightSaturation = 0;
accessory.context.cacheLightHue = 0;
accessory.context.cacheLightBrightness = 0;
accessory.context.cacheTargetTemperature = 0;
accessory.context.cacheTargetHeatingCoolingState = Characteristic.TargetHeatingCoolingState.AUTO;
accessory.context.cacheCurrentHeatingCoolingStatee = Characteristic.CurrentHeatingCoolingState.AUTO;
accessory.context.initHistory = false;
// Retrieve initial state
this.getInitState(accessory);
// Configure state polling
if (data.polling) this.doPolling(data.name);
}
// Function to remove accessory dynamically from outside event
DomotigaPlatform.prototype.removeAccessory = function (accessory) {
if (accessory) {
var name = accessory.context.name;
this.log.warn("Removing accessory: " + name + ". No longer reachable or configured.");
this.api.unregisterPlatformAccessories("homebridge-domotiga", "DomotiGa", [accessory]);
delete this.accessories[name];
}
}
// Method to determine current state
DomotigaPlatform.prototype.doPolling = function (name) {
this.log("Polling... ");
var accessory = this.accessories[name];
var thisDevice = accessory.context;
// Clear polling
clearTimeout(this.polling[name]);
//var name = accessory.context.name;
// // Get accessory service list
// var services = this.accessories[name].services;
// // Loop over assigned services
// for (var index in services) {
// var service = services[index];
// // Loop over assigned characteristics
// for (var cIndex in service.characteristics) {
// var mcharacteristic = service.characteristics[cIndex];
// mcharacteristic.getValue();
// }
// }
// Get primary service
var primaryservice;
switch (thisDevice.service) {
case "TemperatureSensor":
primaryservice = accessory.getService(Service.TemperatureSensor);
this.readCurrentTemperature(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheCurrentTemperature) {
thisDevice.cacheCurrentTemperature = value;
//primaryservice.getCharacteristic(Characteristic.CurrentTemperature).getValue();
primaryservice.getCharacteristic(Characteristic.CurrentTemperature).updateValue(parseFloat(value)); // why do we not just use updateValue?
}
});
break;
case "HumiditySensor":
primaryservice = accessory.getService(Service.HumiditySensor);
this.readCurrentRelativeHumidity(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheCurrentRelativeHumidity) {
thisDevice.cacheCurrentRelativeHumidity = value;
primaryservice.getCharacteristic(Characteristic.CurrentRelativeHumidity).getValue();
}
});
break;
case "Contact":
primaryservice = accessory.getService(Service.ContactSensor);
this.readContactState(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheContactSensorState) {
thisDevice.cacheContactSensorState = value;
primaryservice.getCharacteristic(Characteristic.cacheContactSensorState).getValue();
}
});
break;
case "LeakSensor":
primaryservice = accessory.getService(Service.LeakSensor);
this.readLeakSensorState(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheLeakSensorState) {
thisDevice.cacheLeakSensorState = value;
primaryservice.getCharacteristic(Characteristic.LeakDetected).getValue();
}
});
break;
case "MotionSensor":
primaryservice = accessory.getService(Service.MotionSensor);
this.readMotionSensorState(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheMotionSensorState) {
thisDevice.cacheMotionSensorState = value;
primaryservice.getCharacteristic(Characteristic.MotionDetected).getValue();
}
});
break;
case "Switch":
primaryservice = accessory.getService(Service.Switch);
this.readSwitchState(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheSwitchState) {
thisDevice.cacheSwitchState = value;
primaryservice.getCharacteristic(Characteristic.On).getValue();
}
});
break;
case "Door":
primaryservice = accessory.getService(Service.Door);
this.readDoorPosition(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheDoorPosition) {
thisDevice.cacheDoorPosition = value;
primaryservice.getCharacteristic(Characteristic.CurrentPosition).getValue();
}
});
primaryservice.getCharacteristic(Characteristic.PositionState).getValue();
break;
case "Window":
primaryservice = accessory.getService(Service.Window);
this.readWindowPosition(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheWindowPosition) {
thisDevice.cacheWindowPosition = value;
primaryservice.getCharacteristic(Characteristic.CurrentPosition).getValue();
}
});
primaryservice.getCharacteristic(Characteristic.PositionState).getValue();
break;
case "WindowCovering":
primaryservice = accessory.getService(Service.WindowCovering);
this.readWindowCoveringPosition(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheWindowCoveringPosition) {
thisDevice.cacheWindowCoveringPosition = value;
primaryservice.getCharacteristic(Characteristic.CurrentPosition).getValue();
}
});
primaryservice.getCharacteristic(Characteristic.PositionState).getValue();
break;
case "Outlet":
primaryservice = accessory.getService(Service.Outlet);
this.readOutletState(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheOutletState) {
thisDevice.cacheOutletState = value;
primaryservice.getCharacteristic(Characteristic.On).getValue();
}
});
this.readOutletInUse(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheOutletInUse) {
thisDevice.cacheOutletInUse = value;
primaryservice.getCharacteristic(Characteristic.OutletInUse).getValue();
}
});
break;
case "AirQualitySensor":
primaryservice = accessory.getService(Service.AirQualitySensor);
this.readCurrentAirQuality(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheCurrentAirQuality) {
thisDevice.cacheCurrentAirQuality = value;
primaryservice.getCharacteristic(Characteristic.AirQuality).getValue();
}
});
break;
case "FakeEveAirQualitySensor":
primaryservice = accessory.getService(Service.EveRoomService);
this.readCurrentEveAirQuality(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheCurrentAirQuality) {
thisDevice.cacheCurrentEveAirQuality = value;
primaryservice.getCharacteristic(Characteristic.EveRoomAirQuality).getValue();
}
});
break;
case "FakeEveWeatherSensor":
primaryservice = accessory.getService(Service.EveWeatherService);
this.readCurrentAirPressure(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheCurrentAirPressure) {
thisDevice.cacheCurrentAirPressure = value;
primaryservice.getCharacteristic(Characteristic.EveAirPressure).getValue();
}
});
break;
case "Powermeter":
primaryservice = accessory.getService(Service.PowerMeterService);
this.readEvePowerConsumption(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cachePowerConsumption) {
thisDevice.cachePowerConsumption = value;
primaryservice.getCharacteristic(Characteristic.EvePowerConsumption).getValue();
}
});
break;
case "Lightbulb":
primaryservice = accessory.getService(Service.Lightbulb);
this.readLightState(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheLightState) {
thisDevice.cacheLightState = value;
primaryservice.getCharacteristic(Characteristic.On).getValue();
}
});
if (accessory.context.brightness || accessory.context.color) {
this.readLightBrightnessState(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheLightBrightness) {
thisDevice.cacheLightBrightness = value;
primaryservice.getCharacteristic(Characteristic.Brightness).getValue();
}
});
}
if (accessory.context.color) {
this.readHueState(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheLightHue) {
thisDevice.cacheLightHue = value;
primaryservice.getCharacteristic(Characteristic.Hue).getValue();
}
});
this.readSaturationState(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheLightSaturation) {
thisDevice.cacheLightSaturation = value;
primaryservice.getCharacteristic(Characteristic.Saturation).getValue();
}
});
}
break;
case "Thermostat":
primaryservice = accessory.getService(Service.Thermostat);
this.readTargetTemperature(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheTargetTemperature) {
thisDevice.cacheTargetTemperature = value;
primaryservice.getCharacteristic(Characteristic.CurrentTemperature).getValue();
}
});
case "HumidifierDehumidifier":
primaryservice = accessory.getService(Service.HumidifierDehumidifier);
default:
this.log.error('Service %s %s unknown for polling, skipping...', accessory.context.service, accessory.context.name);
break;
}
// Additional/optional characteristics...
if (accessory.context.valueTemperature && (accessory.context.service != "TemperatureSensor")) {
this.readCurrentTemperature(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheCurrentTemperature) {
thisDevice.cacheCurrentTemperature = value;
accessory.getService(Service.TemperatureSensor).getCharacteristic(Characteristic.CurrentTemperature).getValue();
}
});
}
if (accessory.context.valueHumidity && (accessory.context.service != "HumiditySensor")) {
this.readCurrentRelativeHumidity(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheCurrentRelativeHumidity) {
thisDevice.cacheCurrentRelativeHumidity = value;
accessory.getService(Service.HumiditySensor).getCharacteristic(Characteristic.CurrentRelativeHumidity).getValue();
}
});
}
if (accessory.context.valueWaterLevel) {
this.readWaterLevel(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheWaterLevel) {
thisDevice.cacheWaterLevel = value;
primaryservice.getCharacteristic(Characteristic.WaterLevel).getValue();
}
});
}
if (accessory.context.valueBattery) {
this.readCurrentBatteryLevel(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheCurrentBatteryLevel) {
thisDevice.cacheCurrentBatteryLevel = value;
primaryservice.getCharacteristic(Characteristic.BatteryLevel).getValue();
}
});
}
if (accessory.context.lowbattery) {
this.readLowBatteryStatus(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheStatusLowBattery) {
thisDevice.cacheStatusLowBattery = value;
primaryservice.getCharacteristic(Characteristic.StatusLowBattery).getValue();
}
});
}
// Eve characteristic (custom UUID)
if (accessory.context.valueAirPressure &&
(accessory.context.service != "FakeEveWeatherSensor")) {
this.readCurrentAirPressure(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheCurrentAirPressure) {
thisDevice.cacheCurrentAirPressure = value;
primaryservice.getCharacteristic(Characteristic.EveAirPressure).getValue();
}
});
}
// Eve characteristic (custom UUID)
if (accessory.context.valueAirQuality &&
(accessory.context.service != "AirQualitySensor") && (accessory.context.service != "FakeEveAirQualitySensor")) {
this.readCurrentEveAirQuality(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheCurrentAirQuality) {
thisDevice.cacheCurrentAirQuality = value;
primaryservice.getCharacteristic(Characteristic.AirQuality).getValue();
accessory.getService(Service.AirQualitySensor).getCharacteristic(Characteristic.AirQuality).getValue();
}
});
}
// Eve characteristic (custom UUID)
if (accessory.context.valuePowerConsumption && (accessory.context.service != "Powermeter")) {
this.readEvePowerConsumption(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cachePowerConsumption) {
thisDevice.cachePowerConsumption = value;
primaryservice.getCharacteristic(Characteristic.EvePowerConsumption).getValue();
}
});
}
// Eve characteristic (custom UUID)
if (accessory.context.valueTotalPowerConsumption) {
this.readEveTotalPowerConsumption(thisDevice, function (error, value) {
// Update value if there's no error
if (!error && value !== thisDevice.cacheTotalPowerConsumption) {
thisDevice.cacheTotalPowerConsumption = value;
primaryservice.getCharacteristic(Characteristic.EveTotalPowerConsumption).getValue();
}
});
}
// History
this.addValuesToHistory(accessory);
// Setup for next polling
this.polling[name] = setTimeout(this.doPolling.bind(this, name), thisDevice.pollingInterval);
}
// Method to setup listeners for different events
DomotigaPlatform.prototype.setService = function (accessory) {
var primaryservice;
// Setup HomeKit service(-s)
switch (accessory.context.service) {
case "TemperatureSensor":
primaryservice = accessory.getService(Service.TemperatureSensor);
primaryservice.getCharacteristic(Characteristic.CurrentTemperature)
.setProps({ minValue: -55, maxValue: 100 })
.on('get', this.getCurrentTemperature.bind(this, accessory.context));
accessory.context.logType = "room";
break;
case "HumiditySensor":
primaryservice = accessory.getService(Service.HumiditySensor);
primaryservice.getCharacteristic(Characteristic.CurrentRelativeHumidity)
.on('get', this.getCurrentRelativeHumidity.bind(this, accessory.context));
accessory.context.logType = "room";
break;
case "Contact":
primaryservice = accessory.getService(Service.ContactSensor);
primaryservice.getCharacteristic(Characteristic.ContactSensorState)
.on('get', this.getContactState.bind(this, accessory.context));
accessory.context.logType = "door";
break;
case "LeakSensor":
primaryservice = accessory.getService(Service.LeakSensor);
primaryservice.getCharacteristic(Characteristic.LeakDetected)
.on('get', this.getLeakSensorState.bind(this, accessory.context));
break;
case "MotionSensor":
primaryservice = accessory.getService(Service.MotionSensor);
primaryservice.getCharacteristic(Characteristic.MotionDetected)
.on('get', this.getMotionSensorState.bind(this, accessory.context));
accessory.context.logType = "motion";
break;
case "Switch":
primaryservice = accessory.getService(Service.Switch);
primaryservice.getCharacteristic(Characteristic.On)
.on('get', this.getSwitchState.bind(this, accessory.context))
.on('set', this.setSwitchState.bind(this, accessory.context))
break;
case "Door":
primaryservice = accessory.getService(Service.Door);
primaryservice.getCharacteristic(Characteristic.CurrentPosition)
.on('get', this.getDoorPosition.bind(this, accessory.context))
primaryservice.getCharacteristic(Characteristic.TargetPosition)
.on('get', this.getDoorPosition.bind(this, accessory.context))
.on('set', this.setDoorPosition.bind(this, accessory.context))
primaryservice.getCharacteristic(Characteristic.PositionState)
.on('get', this.getDoorPositionState.bind(this, accessory.context))
accessory.context.logType = "door";
break;
case "Window":
primaryservice = accessory.getService(Service.Window);
primaryservice.getCharacteristic(Characteristic.CurrentPosition)
.on('get', this.getWindowPosition.bind(this, accessory))
primaryservice.getCharacteristic(Characteristic.TargetPosition)
.on('get', this.getWindowPosition.bind(this, accessory))
.on('set', this.setWindowPosition.bind(this, accessory))
primaryservice.getCharacteristic(Characteristic.PositionState)
.on('get', this.getWindowPositionState.bind(this, accessory))
accessory.context.logType = "door";
break;
case "WindowCovering":
primaryservice = accessory.getService(Service.WindowCovering);
primaryservice.getCharacteristic(Characteristic.CurrentPosition)
.on('get', this.getWindowCoveringPosition.bind(this, accessory.context))
primaryservice.getCharacteristic(Characteristic.TargetPosition)
.on('get', this.getWindowCoveringPosition.bind(this, accessory.context))
.on('set', this.setWindowCoveringPosition.bind(this, accessory.context))
primaryservice.getCharacteristic(Characteristic.PositionState)
.on('get', this.getWindowCoveringPositionState.bind(this, accessory.context))
accessory.context.logType = "door";
break;
case "Outlet":
primaryservice = accessory.getService(Service.Outlet);
primaryservice.getCharacteristic(Characteristic.On)
.on('get', this.getOutletState.bind(this, accessory.context))
.on('set', this.setOutletState.bind(this, accessory.context));
primaryservice.getCharacteristic(Characteristic.OutletInUse)
.on('get', this.getOutletInUse.bind(this, accessory.context));
break;
case "AirQualitySensor":
primaryservice = accessory.getService(Service.AirQualitySensor);
primaryservice.getCharacteristic(Characteristic.AirQuality)
.on('get', this.getCurrentAirQuality.bind(this, accessory.context));
accessory.context.logType = "room";
break;
case "FakeEveAirQualitySensor":
primaryservice = accessory.getService(Service.EveRoomService);
primaryservice.getCharacteristic(Characteristic.EveRoomAirQuality)
.on('get', this.getCurrentEveAirQuality.bind(this, accessory.context));
accessory.context.logType = "room";
break;
case "FakeEveWeatherSensor":
primaryservice = accessory.getService(Service.EveWeatherService);
primaryservice.getCharacteristic(Characteristic.EveAirPressure)
.on('get', this.getCurrentAirPressure.bind(this, accessory.context));
accessory.context.logType = "weather";
break;
case "Powermeter":
primaryservice = accessory.getService(Service.PowerMeterService);
primaryservice.getCharacteristic(Characteristic.EvePowerConsumption)
.on('get', this.getEvePowerConsumption.bind(this, accessory.context));
accessory.context.logType = "energy";
break;
case "Lightbulb":
primaryservice = accessory.getService(Service.Lightbulb);
primaryservice.getCharacteristic(Characteristic.On)
.on('get', this.getLightState.bind(this, accessory.context))
.on('set', this.setLightState.bind(this, accessory.context));
if (accessory.context.color) {
primaryservice.getCharacteristic(Characteristic.Hue)
.on('get', this.getLightHue.bind(this, accessory.context))
.on('set', this.setLightHue.bind(this, accessory.context));
primaryservice.getCharacteristic(Characteristic.Saturation)
.on('get', this.getLightSaturation.bind(this, accessory.context))
.on('set', this.setLightSaturation.bind(this, accessory.context));
}
if (accessory.context.brightness || accessory.context.color) {
primaryservice.getCharacteristic(Characteristic.Brightness)
.on('get', this.getLightBrightnessState.bind(this, accessory.context))
.on('set', this.setLightBrightnessState.bind(this, accessory.context));
}
break;
case "Thermostat":
primaryservice = accessory.getService(Service.Thermostat);
primaryservice.getCharacteristic(Characteristic.TargetTemperature)
.on('get', this.getTargetTemperature.bind(this, accessory.context))
.on('set', this.setTargetTemperature.bind(this, accessory.context))
primaryservice.getCharacteristic(Characteristic.CurrentHeatingCoolingState)
.on('get', this.getCurrentHeatingCoolingState.bind(this, accessory.context))
primaryservice.getCharacteristic(Characteristic.TargetHeatingCoolingState)
.on('get', this.getTargetHeatingCoolingState.bind(this, accessory.context))
.on('set', this.setTargetHeatingCoolingState.bind(this, accessory.context))
primaryservice.getCharacteristic(Characteristic.TemperatureDisplayUnits)
.on('get', this.getTemperatureDisplayUnits.bind(this, accessory.context))
.on('set', this.setTemperatureDisplayUnits.bind(this, accessory.context));
accessory.context.logType = "thermo";
break;
default:
this.log.error('Service %s %s unknown for set, skipping...', accessory.context.service, accessory.context.name);
break;
}
// Everything outside the primary service gets added as additional characteristics...
if (primaryservice) {
if (accessory.context.valueTemperature && (accessory.context.service != "TemperatureSensor")) {
accessory.getService(Service.TemperatureSensor).getCharacteristic(Characteristic.CurrentTemperature)
.setProps({ minValue: -55, maxValue: 100 })
.on('get', this.getCurrentTemperature.bind(this, accessory.context));
}
if (accessory.context.valueHumidity && (accessory.context.service != "HumiditySensor")) {
accessory.getService(Service.HumiditySensor).getCharacteristic(Characteristic.CurrentRelativeHumidity)
.on('get', this.getCurrentRelativeHumidity.bind(this, accessory.context));
}
if (accessory.context.valueWaterLevel) {
primaryservice.getCharacteristic(Characteristic.WaterLevel)
.on('get', this.getWaterLevel.bind(this, accessory.context));
}
if (accessory.context.valueBattery) {
primaryservice.getCharacteristic(Characteristic.BatteryLevel)
.on('get', this.getCurrentBatteryLevel.bind(this, accessory.context));
}
if (accessory.context.lowbattery) {
primaryservice.getCharacteristic(Characteristic.StatusLowBattery)
.on('get', this.getLowBatteryStatus.bind(this, accessory.context));
}
if (accessory.context.valueAirQuality) {
accessory.getService(Service.AirQualitySensor).getCharacteristic(Characteristic.VOCDensity)
.on('get', this.getCurrentVOCDensity.bind(this, accessory.context));
}
// Eve characteristic (custom UUID)
if (accessory.context.valueAirPressure &&
(accessory.context.service != "FakeEveWeatherSensor")) {
primaryservice.getCharacteristic(Characteristic.EveAirPressure)
.on('get', this.getCurrentAirPressure.bind(this, accessory.context));
accessory.context.logType = "weather";
}
// Eve characteristic (custom UUID)
if (accessory.context.valueAirQuality &&
(accessory.context.service != "AirQualitySensor") && (accessory.context.service != "FakeEveAirQualitySensor")) {
accessory.getService(Service.AirQualitySensor).getCharacteristic(Characteristic.AirQuality)
.on('get', this.getCurrentEveAirQuality.bind(this, accessory.context));
accessory.context.logType = "room";
}
if (accessory.context.valueAirQuality &&
(accessory.context.service === "AirQualitySensor")) {
primaryservice.getCharacteristic(Characteristic.EveRoomAirQuality)
.on('get', this.getCurrentEveAirQuality.bind(this, accessory.context));
}
// Eve characteristic (custom UUID)
if (accessory.context.valuePowerConsumption && (accessory.context.service != "Powermeter")) {
primaryservice.getCharacteristic(Characteristic.EvePowerConsumption)
.on('get', this.getEvePowerConsumption.bind(this, accessory.context));
}
// Eve characteristic (custom UUID)
if (accessory.context.valueTotalPowerConsumption) {
primaryservice.getCharacteristic(Characteristic.EveTotalPowerConsumption)
.on('get', this.getEveTotalPowerConsumption.bind(this, accessory.context));
}
}
accessory.on('identify', this.identify.bind(this, accessory.context));
}
// Initialize accessory
DomotigaPlatform.prototype.getInitState = function (accessory) {
// Update HomeKit accessory information
accessory.getService(Service.AccessoryInformation)
.setCharacteristic(Characteristic.Manufacturer, accessory.context.manufacturer)
.setCharacteristic(Characteristic.Model, accessory.context.model)
.setCharacteristic(Characteristic.SerialNumber, ("Domotiga device %s %s", accessory.context.device, accessory.context.name));
// Get accessory service list
var name = accessory.context.name;
var services = this.accessories[name].services;
// Loop over assigned services
for (var index in services) {
var service = services[index];
// Loop over assigned characteristics
for (var cIndex in service.characteristics) {
var mcharacteristic = service.characteristics[cIndex];
mcharacteristic.getValue();
}
}
// Retrieve initial state if polling is disabled
//if (!accessory.context.polling) { //<---- we do also need an init state if polling is activated
// // Get primary service
// var primaryservice;
// switch (accessory.context.service) {
// case "TemperatureSensor":
// primaryservice = accessory.getService(Service.TemperatureSensor);
// primaryservice.getCharacteristic(Characteristic.CurrentTemperature).getValue();
// break;
// case "HumiditySensor":
// primaryservice = accessory.getService(Service.HumiditySensor);
// primaryservice.getCharacteristic(Characteristic.CurrentRelativeHumidity).getValue();
// break;
// case "Contact":
// primaryservice = accessory.getService(Service.ContactSensor);
// primaryservice.getCharacteristic(Characteristic.ContactSensorState).getValue();
// break;
// case "LeakSensor":
// primaryservice = accessory.getService(Service.LeakSensor);
// primaryservice.getCharacteristic(Characteristic.LeakDetected).getValue();
// break;
// case "MotionSensor":
// primaryservice = accessory.getService(Service.MotionSensor);
// primaryservice.getCharacteristic(Characteristic.MotionDetected).getValue();
// break;
// case "Switch":
// primaryservice = accessory.getService(Service.Switch);
// primaryservice.getCharacteristic(Characteristic.On).getValue();
// break;
// case "Door":
// primaryservice = accessory.getService(Service.Door);
// primaryservice.getCharacteristic(Characteristic.CurrentPosition).getValue();
// primaryservice.getCharacteristic(Characteristic.PositionState).getValue();
// break;
// case "Window":
// primaryservice = accessory.getService(Service.Window);
// primaryservice.getCharacteristic(Characteristic.CurrentPosition).getValue();
// primaryservice.getCharacteristic(Characteristic.PositionState).getValue();
// break;
// case "WindowCovering":
// primaryservice = accessory.getService(Service.WindowCovering);
// primaryservice.getCharacteristic(Characteristic.CurrentPosition).getValue();
// primaryservice.getCharacteristic(Characteristic.PositionState).getValue();
// break;
// case "Outlet":
// primaryservice = accessory.getService(Service.Outlet);
// primaryservice.getCharacteristic(Characteristic.On).getValue();
// primaryservice.getCharacteristic(Characteristic.OutletInUse).getValue();
// break;
// case "AirQualitySensor":
// primaryservice = accessory.getService(Service.AirQualitySensor);
// primaryservice.getCharacteristic(Characteristic.AirQuality).getValue();
// break;
// case "FakeEveAirQualitySensor":
// primaryservice = accessory.getService(Service.EveRoomService);
// primaryservice.getCharacteristic(Characteristic.EveRoomAirQuality).getValue();
// break;
// case "FakeEveWeatherSensor":
// primaryservice = accessory.getService(Service.EveWeatherService);
// primaryservice.getCharacteristic(Characteristic.EveAirPressure).getValue();
// break;
// case "Powermeter":
// primaryservice = accessory.getService(Service.PowerMeterService);
// primaryservice.getCharacteristic(Characteristic.EvePowerConsumption).getValue();
// break;
// case "Lightbulb":
// primaryservice = accessory.getService(Service.Lightbulb);
// if (accessory.context.color) {
// primaryservice.getCharacteristic(Characteristic.Hue).getValue();
// primaryservice.getCharacteristic(Characteristic.Saturation).getValue();
// }
// if (accessory.context.color || accessory.context.brightness) {
// primaryservice.getCharacteristic(Characteristic.Brightness).getValue();
// }
// break;
// case "Thermostat":
// primaryservice = accessory.getService(Service.Thermostat);
// primaryservice.getCharacteristic(Characteristic.TargetTemperature).getValue();
// primaryservice.getCharacteristic(Characteristic.CurrentHeatingCoolingState).getValue();
// primaryservice.getCharacteristic(Characteristic.TargetHeatingCoolingState).getValue();
// break;
// default:
// this.log.error('Service %s %s unknown for initstate, skipping...', accessory.context.service, accessory.context.name);
// break;
// }
// // Additional/optional characteristics...
// if (primaryservice) {
// if (accessory.context.valueTemperature && (accessory.context.service != "TemperatureSensor")) {
// accessory.getService(Service.TemperatureSensor).getCharacteristic(Characteristic.CurrentTemperature).getValue();
// }
// if (accessory.context.valueHumidity && (accessory.context.service != "HumiditySensor")) {
// accessory.getService(Service.HumiditySensor).getCharacteristic(Characteristic.CurrentRelativeHumidity).getValue();
// }
// if (accessory.context.valueBattery) {
// primaryservice.getCharacteristic(Characteristic.BatteryLevel).getValue();
// }
// if (accessory.context.lowbattery) {
// primaryservice.getCharacteristic(Characteristic.StatusLowBattery).getValue();
// }
// // Eve characteristic (custom UUID)
// if (accessory.context.valueAirPressure && (accessory.context.service != "FakeEveWeatherSensor")) {
// primaryservice.getCharacteristic(Characteristic.EveAirPressure).getValue();
// }
// // Eve characteristic (custom UUID)
// if (accessory.context.valueAirQuality &&
// (accessory.context.service != "AirQualitySensor") && (accessory.context.service != "FakeEveAirQualitySensor")) {
// accessory.getService(Service.AirQualitySensor).getCharacteristic(Characteristic.AirQuality).getValue();
// }
// // Eve characteristic (custom UUID)
// if (accessory.context.valuePowerConsumption && (accessory.context.service != "Powermeter")) {
// primaryservice.getCharacteristic(Characteristic.EvePowerConsumption).getValue();
// }
// // Eve characteristic (custom UUID)
// if (accessory.context.valueTotalPowerConsumption) {
// primaryservice.getCharacteristic(Characteristic.EveTotalPowerConsumption).getValue();
// }
// }
//}
// History
//this.addValuesToHistory(accessory); <-- at this time we do logging only with activated polling
// Configured accessory is reachable
accessory.updateReachability(true);
}
DomotigaPlatform.prototype.addValuesToHistory = function (accessory) {
var self = this;
this.log.debug("Logging history %s for %s", accessory.context.logType, accessory.context.name);
if (accessory.context.polling) {
if (!accessory.context.initHistory) {
// Add history logging service
accessory.context.loggingService = new Service.FakeGatoHistoryService(accessory.context.logType, accessory, { storage: 'fs', path: this.localCache, disableTimer: false });
accessory.context.initHistory = true;
}
else {
switch (accessory.context.logType) {
case "weather":
this.log.debug("Temp: %s Press: %s Humi: %s",
accessory.context.cacheCurrentTemperature,
accessory.context.cacheCurrentAirPressure,
accessory.context.cacheCurrentRelativeHumidity);
accessory.context.loggingService.addEntry({
time: moment().unix(),
temp: parseFloat(accessory.context.cacheCurrentTemperature),
pressure: parseFloat(accessory.context.cacheCurrentAirPressure),
humidity: parseFloat(accessory.context.cacheCurrentRelativeHumidity)
});
break;
case "room":
this.log.debug("Temp: %s Humi: %s Qual: %s",
accessory.context.cacheCurrentTemperature,
accessory.context.cacheCurrentRelativeHumidity,
accessory.context.cacheCurrentEveAirQuality);
accessory.context.loggingService.addEntry({
time: moment().unix(),
temp: parseFloat(accessory.context.cacheCurrentTemperature),
humidity: parseFloat(accessory.context.cacheCurrentRelativeHumidity),
ppm: Number(accessory.context.cacheCurrentEveAirQuality)
});
break;
case "thermo":
this.log.debug("Temp: %s Targettemp: %s Valve pos: %s",
accessory.context.cacheCurrentTemperature,
accessory.context.cacheTargetTemperature,
0);
accessory.context.loggingService.addEntry({
time: moment().unix(),
currentTemp: parseFloat(accessory.context.cacheCurrentTemperature),
setTemp: parseFloat(accessory.context.cacheTargetTemperature),
valvePosition: 0
});
// todo: valve position
break;
case "energy":
this.log.debug("Power: %s", accessory.context.cachePowerConsumption);
accessory.context.loggingService.addEntry({ time: moment().unix(), power: accessory.context.cachePowerConsumption });
// todo: conversation needed? -> check unit
break;
case "door":
this.log.debug("Position: %s", accessory.context.cacheDoorPosition);
accessory.context.loggingService.addEntry({ time: moment().unix(), status: parseFloat(accessory.context.cacheDoorPosition) });
break;
case "motion":
this.log.debug("Motion: %s", accessory.context.cacheMotionSensorState);
accessory.context.loggingService.addEntry({ time: moment().unix(), status: parseFloat(accessory.context.cacheMotionSensorState) });
break;
default:
this.log.error('Unknown log type %s %s, skipping...', accessory.context.logType, accessory.context.name);
break;
}
}
}
//this.remoteGetValue("ACTUAL_TEMPERATURE", function (value) {
// that.currentTemperature = parseFloat(value);
// that.remoteGetValue("ACTUAL_HUMIDITY", function (value) {
// that.currentHumidity = parseFloat(value);
// if ((that.currentTemperature > -255) && (that.currentHumidity > -255)) {
// that.loggingService.addEntry({ time: moment().unix(), temp: that.currentTemperature, pressure: 0, humidity: that.currentHumidity });
// }
// that.currentTemperatureCharacteristic.updateValue(that.currentTemperature, null);
// });
//});
}
DomotigaPlatform.prototype.readCurrentTemperature = function (thisDevice, callback) {
var self = this;
self.log("%s: getting temperature...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueTemperature, function (error, result) {
if (error) {
self.log.error('%s: readCurrentTemperature failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = Number(result);
self.log('%s: temperature: %s', thisDevice.name, value);
callback(null, value);
}
});
}
// Method to determine current temperature
DomotigaPlatform.prototype.getCurrentTemperature = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached temperature is: %s', thisDevice.name, thisDevice.cacheCurrentTemperature);
callback(null, thisDevice.cacheCurrentTemperature);
} else {
// Check value if polling is disabled
this.readCurrentTemperature(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheCurrentTemperature = value;
callback(error, thisDevice.cacheCurrentTemperature);
});
}
}
DomotigaPlatform.prototype.readCurrentRelativeHumidity = function (thisDevice, callback) {
var self = this;
self.log("%s: getting relative humidity...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueHumidity, function (error, result) {
if (error) {
self.log.error('%s: readCurrentRelativeHumidity failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = Number(result);
self.log('%s: relative humidity: %s', thisDevice.name, value);
callback(null, value);
}
});
}
// Method to determine current relative humidity
DomotigaPlatform.prototype.getCurrentRelativeHumidity = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached relative humidity is: %s', thisDevice.name, thisDevice.cacheCurrentRelativeHumidity);
callback(null, thisDevice.cacheCurrentRelativeHumidity);
} else {
// Check value if polling is disabled
this.readCurrentRelativeHumidity(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheCurrentRelativeHumidity = value;
callback(error, thisDevice.cacheCurrentRelativeHumidity);
});
}
}
DomotigaPlatform.prototype.readWaterLevel = function (thisDevice, callback) {
var self = this;
self.log("%s: getting waterlevel...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueWaterLevel, function (error, result) {
if (error) {
self.log.error('%s: readWaterLevel failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = parseFloat(result);
self.log('%s: waterlevel: %s', thisDevice.name, value);
callback(null, value);
}
});
}
// Method to determine current waterlevel
DomotigaPlatform.prototype.getWaterLevel = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached waterlevel is: %s', thisDevice.name, thisDevice.cacheWaterLevel);
callback(null, thisDevice.cacheWaterLevel);
} else {
// Check value if polling is disabled
this.readWaterLevel(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheWaterLevel = value;
callback(error, thisDevice.cacheWaterLevel);
});
}
}
DomotigaPlatform.prototype.getTemperatureUnits = function (thisDevice, callback) {
this.log("%s: getting temperature unit...", thisDevice.name);
// 1 = F and 0 = C
callback(null, 0);
}
DomotigaPlatform.prototype.setTemperatureUnits = function (thisDevice, value, callback) {
this.log("%s: ignore setting temperature unit to %s", thisDevice.name, value);
// 1 = F and 0 = C
callback(null, 0);
}
DomotigaPlatform.prototype.readCurrentAirPressure = function (thisDevice, callback) {
var self = this;
self.log("%s: getting air pressure...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueAirPressure, function (error, result) {
if (error) {
self.log.error('%s: readCurrentAirPressure failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = Number(result);
self.log('%s: air pressure: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getCurrentAirPressure = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: Cached air pressure is: %s', thisDevice.name, thisDevice.cacheCurrentAirPressure);
callback(null, thisDevice.cacheCurrentAirPressure);
} else {
// Check value if polling is disabled
this.readCurrentAirPressure(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheCurrentAirPressure = value;
callback(error, thisDevice.cacheCurrentAirPressure);
});
}
}
DomotigaPlatform.prototype.readContactState = function (thisDevice, callback) {
var self = this;
self.log("%s: getting contact state...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueContact, function (error, result) {
if (error) {
self.log.error('%s: readContactState failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = (result.toLowerCase() == "on") ? Characteristic.ContactSensorState.CONTACT_DETECTED : ContactSensorState.CONTACT_NOT_DETECTED;
self.log('%s: contact state: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getContactState = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached contact state is: %s', thisDevice.name, thisDevice.cacheContactSensorState);
callback(null, thisDevice.cacheContactSensorState);
} else {
// Check value if polling is disabled
this.readContactState(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheContactSensorState = value;
callback(error, thisDevice.cacheContactSensorState);
});
}
}
DomotigaPlatform.prototype.readLeakSensorState = function (thisDevice, callback) {
var self = this;
self.log("%s: getting leaksensor state...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueLeakSensor, function (error, result) {
if (error) {
self.log.error('%s: readLeakSensorState failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = (Number(result) == 0) ? Characteristic.LeakDetected.LEAK_NOT_DETECTED : Characteristic.LeakDetected.LEAK_DETECTED;
self.log('%s: leaksensor state: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getLeakSensorState = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached leaksensor state is: %s', thisDevice.name, thisDevice.cacheLeakSensorState);
callback(null, thisDevice.cacheLeakSensorState);
} else {
// Check value if polling is disabled
this.readLeakSensorState(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheLeakSensorState = value;
callback(error, thisDevice.cacheLeakSensorState);
});
}
}
DomotigaPlatform.prototype.readOutletState = function (thisDevice, callback) {
var self = this;
self.log("%s: getting outlet state...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueOutlet, function (error, result) {
if (error) {
self.log.error('%s: readOutletState failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = (result.toLowerCase() == "on") ? 0 : 1;
self.log('%s: outlet state: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getOutletState = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached outlet state is: %s', thisDevice.name, thisDevice.cacheOutletState);
callback(null, thisDevice.cacheOutletState);
} else {
// Check value if polling is disabled
this.readOutletState(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheOutletState = value;
callback(error, thisDevice.cacheOutletState);
});
}
}
DomotigaPlatform.prototype.setOutletState = function (thisDevice, boolvalue, callback) {
var self = this;
self.log("%s: Setting outlet state to %s", thisDevice.name, boolvalue);
thisDevice.cacheOutletState = boolvalue;
var OnOff = (boolvalue == 1) ? "On" : "Off";
var callbackWasCalled = false;
// Update position state to iOS
var accessory = this.accessories[thisDevice.name];
if (accessory) {
accessory.getService(Service.Outlet).getCharacteristic(Characteristic.On).updateValue(boolvalue);
}
this.domotigaSetValue(thisDevice.device, thisDevice.valueOutlet, OnOff, function (err) {
if (callbackWasCalled)
self.log.warn("WARNING: domotigaSetValue called its callback more than once! Discarding the second one.");
callbackWasCalled = true;
if (!err) {
self.log("%s: successfully set outlet state to %s", thisDevice.name, OnOff);
callback(null);
} else {
self.log.error("%s: error setting outlet state to %s", thisDevice.name, OnOff);
callback(err);
}
});
}
DomotigaPlatform.prototype.readOutletInUse = function (thisDevice, callback) {
var self = this;
self.log("%s: getting outletInUse...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueOutlet, function (error, result) {
if (error) {
self.log.error('%s: readOutletInUse failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = (result.toLowerCase() == "on") ? false : true;
self.log('%s: OutletInUse: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getOutletInUse = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached OutletInUse is: %s', thisDevice.name, thisDevice.cacheOutletInUse);
callback(null, thisDevice.cacheOutletInUse);
} else {
// Check value if polling is disabled
this.readOutletInUse(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheOutletInUse = value;
callback(error, thisDevice.cacheOutletInUse);
});
}
}
DomotigaPlatform.prototype.readCurrentAirQuality = function (thisDevice, callback) {
var self = this;
self.log("%s: getting air quality...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueAirQuality, function (error, result) {
if (error) {
self.log.error('%s: readCurrentAirQuality failed: %s', thisDevice.name, error.message);
callback(error);
} else {
voc = Number(result);
self.log('%s: current air quality level: %s', thisDevice.name, voc);
var value;
if (voc > 1500)
value = Characteristic.AirQuality.POOR;
else if (voc > 1000)
value = Characteristic.AirQuality.INFERIOR;
else if (voc > 800)
value = Characteristic.AirQuality.FAIR;
else if (voc > 600)
value = Characteristic.AirQuality.GOOD;
else if (voc > 0)
value = Characteristic.AirQuality.EXCELLENT;
else
value = Characteristic.AirQuality.UNKNOWN;
// Addition for fakegato-history: save original voc value
if (value != Characteristic.AirQuality.UNKNOWN)
thisDevice.cacheCurrentEveAirQuality = voc;
self.log('%s: current air quality: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getCurrentAirQuality = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached air quality is: %s', thisDevice.name, thisDevice.cacheCurrentAirQuality);
callback(null, thisDevice.cacheCurrentAirQuality);
} else {
// Check value if polling is disabled
this.readCurrentAirQuality(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheCurrentAirQuality = value;
callback(error, thisDevice.cacheCurrentAirQuality);
});
}
}
// Additional VOCDensity mapping
DomotigaPlatform.prototype.getCurrentVOCDensity = function (thisDevice, callback) {
var voc = parseFloat(thisDevice.cacheCurrentEveAirQuality);
if (voc < 0.0)
voc = 0.0;
if (voc > 1000.0)
voc = 1000.0;
callback(null, voc);
}
// Eve characteristic (custom UUID)
DomotigaPlatform.prototype.readCurrentEveAirQuality = function (thisDevice, callback) {
// Custom Eve intervals:
// 0... 700 : Exzellent
// 700...1100 : Good
// 1100...1600 : Acceptable
// 1600...2000 : Moderate
// > 2000 : Bad
var self = this;
self.log("%s: getting Eve air quality...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueAirQuality, function (error, result) {
if (error) {
self.log.error('%s: readCurrentEveAirQuality failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var voc = Number(result);
if (voc < 0)
voc = 0;
self.log('%s: Eve air quality: %s', thisDevice.name, voc);
callback(null, voc);
}
});
}
DomotigaPlatform.prototype.getCurrentEveAirQuality = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached Eve air quality is: %s', thisDevice.name, thisDevice.cacheCurrentEveAirQuality);
callback(null, thisDevice.cacheCurrentEveAirQuality);
} else {
// Check value if polling is disabled
this.readCurrentEveAirQuality(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheCurrentEveAirQuality= value;
callback(error, thisDevice.cacheCurrentEveAirQuality);
});
}
}
// Eve characteristic (custom UUID)
DomotigaPlatform.prototype.readEvePowerConsumption = function (thisDevice, callback) {
var self = this;
self.log("%s: getting Eve power consumption...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueOutlet, function (error, result) {
if (error) {
self.log.error('%s: readEvePowerConsumption failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = Math.round(Number(result)); // W
self.log('%s: Eve power consumption: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getEvePowerConsumption = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached Eve power consumption is: %s', thisDevice.name, thisDevice.cachePowerConsumption);
callback(null, thisDevice.cachePowerConsumption);
} else {
// Check value if polling is disabled
this.readEvePowerConsumption(thisDevice, function (error, value) {
// Update cache
thisDevice.cachePowerConsumption = value;
callback(error, thisDevice.cachePowerConsumption);
});
}
}
// Eve characteristic (custom UUID)
DomotigaPlatform.prototype.readEveTotalPowerConsumption = function (thisDevice, callback) {
var self = this;
self.log("%s: getting Eve total power consumption...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueOutlet, function (error, result) {
if (error) {
self.log.error('%s: readEveTotalPowerConsumption failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = Math.round(Number(result) * 1000.0) / 1000.0; // kWh
self.log('%s: Eve total power consumption: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getEveTotalPowerConsumption = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached Eve total power consumption is: %s', thisDevice.name, thisDevice.cacheTotalPowerConsumption);
callback(null, thisDevice.cacheTotalPowerConsumption);
} else {
// Check value if polling is disabled
this.readEveTotalPowerConsumption(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheTotalPowerConsumption = value;
callback(error, thisDevice.cacheTotalPowerConsumption);
});
}
}
DomotigaPlatform.prototype.readCurrentBatteryLevel = function (thisDevice, callback) {
var self = this;
self.log("%s: getting battery level...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueBattery, function (error, result) {
if (error) {
self.log.error('%s: readCurrentBatteryLevel failed: %s', thisDevice.name, error.message);
callback(error);
} else {
thisDevice.lastBatteryLevel = (Number(result));
//this.log('CurrentBattery level Number(result): %s', Number(result));
var value = parseInt(thisDevice.lastBatteryLevel * 100 / 5000, 10);
if (value > 100)
value = 100;
else if (value < 0)
value = 0;
self.log('%s: current battery level: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getCurrentBatteryLevel = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached battery level is: %s', thisDevice.name, thisDevice.cacheCurrentBatteryLevel);
callback(null, thisDevice.cacheCurrentBatteryLevel);
} else {
// Check value if polling is disabled
this.readCurrentBatteryLevel(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheCurrentBatteryLevel = value;
callback(error, thisDevice.cacheCurrentBatteryLevel);
});
}
}
DomotigaPlatform.prototype.readLowBatteryStatus = function (thisDevice, callback) {
var self = this;
self.log("%s: getting battery status...", thisDevice.name);
var value = (thisDevice.lastBatteryLevel < Number(thisDevice.lowbattery)) ? Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
self.log('%s: battery status: %s', thisDevice.name, value);
callback(null, value);
}
DomotigaPlatform.prototype.getLowBatteryStatus = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached battery status is: %s', thisDevice.name, thisDevice.cacheStatusLowBattery);
callback(null, thisDevice.cacheStatusLowBattery);
} else {
// Check value if polling is disabled
this.readLowBatteryStatus(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheStatusLowBattery = value;
callback(error, thisDevice.cacheStatusLowBattery);
});
}
}
DomotigaPlatform.prototype.readMotionSensorState = function (thisDevice, callback) {
var self = this;
self.log("%s: getting motion sensor state...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueMotionSensor, function (error, result) {
if (error) {
self.log.error('%s: readMotionSensorState failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = (Number(result) == 0) ? 1 : 0;
self.log('%s: motion sensor state: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getMotionSensorState = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached motion sensor state is: %s', thisDevice.name, thisDevice.cacheMotionSensorState);
callback(null, thisDevice.cacheMotionSensorState);
} else {
// Check value if polling is disabled
this.readMotionSensorState(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheMotionSensorState = value;
callback(error, thisDevice.cacheMotionSensorState);
});
}
}
DomotigaPlatform.prototype.readSwitchState = function (thisDevice, callback) {
var self = this;
self.log("%s: getting switch state...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueSwitch, function (error, result) {
if (error) {
self.log.error('%s: readSwitchState failed: %s', thisDevice.name, error.message);
callback(error);
} else {
self.log('%s: switch state: %s', thisDevice.name, result);
callback(null, result);
}
});
}
DomotigaPlatform.prototype.getSwitchState = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached switch state is: %s', thisDevice.name, thisDevice.cacheSwitchState);
callback(null, thisDevice.cacheSwitchState);
} else {
// Check value if polling is disabled
this.readSwitchState(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheSwitchState = value;
callback(error, thisDevice.cacheSwitchState);
});
}
}
DomotigaPlatform.prototype.setSwitchState = function (thisDevice, switchOn, callback) {
var self = this;
self.log("%s: setting switch state to %s", thisDevice.name, switchOn);
var switchCommand;
if (switchOn == 1) {
switchCommand = "On";
}
else {
switchCommand = "Off";
}
// Update cache
thisDevice.cacheSwitchState = switchOn;
// Update position state to iOS
var accessory = this.accessories[thisDevice.name];
if (accessory) {
accessory.getService(Service.Switch).getCharacteristic(Characteristic.On).updateValue(switchOn);
}
var callbackWasCalled = false;
this.domotigaSetValue(thisDevice.device, thisDevice.valueSwitch, switchCommand, function (err) {
if (callbackWasCalled) {
self.log.warn("WARNING: domotigaSetValue called its callback more than once! Discarding the second one.");
}
callbackWasCalled = true;
if (!err) {
self.log("%s: successfully set switch state to %s", thisDevice.name, switchCommand);
callback(null);
} else {
self.log.error("%s: error setting switch state to %s", thisDevice.name, switchCommand);
callback(err);
}
});
}
DomotigaPlatform.prototype.getDoorPositionState = function (thisDevice, callback) {
// At this time the value property of PositionState is always mapped to stopped
callback(null, Characteristic.PositionState.STOPPED);
}
DomotigaPlatform.prototype.readDoorPosition = function (thisDevice, callback) {
var self = this;
self.log("%s: getting door position...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueDoor, function (error, result) {
if (error) {
self.log.error('%s: readDoorPosition failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = (result == "0") ? 0 : 100;
self.log('%s: door position: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getDoorPosition = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached door position is: %s', thisDevice.name, thisDevice.cacheDoorPosition);
callback(null, thisDevice.cacheDoorPosition);
} else {
// Check value if polling is disabled
this.readDoorPosition(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheDoorPosition = value;
callback(error, thisDevice.cacheDoorPosition);
});
}
}
DomotigaPlatform.prototype.setDoorPosition = function (thisDevice, targetPosition, callback) {
var self = this;
self.log("%s: setting door position to %s", thisDevice.name, targetPosition);
// At this time we do not use percentage values: 1 = open, 0 = closed
var doorPosition;
if (targetPosition == 0) {
doorPosition = "0";
}
else {
doorPosition = "1";
}
// Update cache
thisDevice.cacheDoorPosition = doorPosition;
// Update position state
var accessory = this.accessories[thisDevice.name];
if (accessory) {
accessory.getService(Service.Door).setCharacteristic(Characteristic.PositionState, Characteristic.PositionState.STOPPED);
}
var callbackWasCalled = false;
this.domotigaSetValue(thisDevice.device, thisDevice.valueDoor, doorPosition, function (err) {
if (callbackWasCalled) {
self.log.warn("WARNING: domotigaSetValue called its callback more than once! Discarding the second one.");
}
callbackWasCalled = true;
if (!err) {
self.log("%s: successfully set door position to %s", thisDevice.name, targetPosition);
callback(null, targetPosition);
} else {
self.log.error("%s: error setting door position to %s", thisDevice.name, targetPosition);
callback(err);
}
});
}
DomotigaPlatform.prototype.getWindowPositionState = function (accessory, callback) {
//var thisDevice = accessory.context;
accessory.getService(Service.Window).setCharacteristic(Characteristic.PositionState, Characteristic.PositionState.STOPPED);
// At this time the value property of PositionState is always mapped to stopped
callback(null, Characteristic.PositionState.STOPPED);
}
DomotigaPlatform.prototype.readWindowPosition = function (thisDevice, callback) {
var self = this;
self.log("%s: getting window position...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueWindow, function (error, result) {
if (error) {
self.log.error('%s: readWindowPosition failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = (result.toLowerCase() == "0") ? 0 : 100;
self.log('%s: window position: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getWindowPosition = function (accessory, callback) {
var self = this;
var thisDevice = accessory.context;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: Cached window position is: %s', thisDevice.name, thisDevice.cacheWindowPosition);
callback(null, thisDevice.cacheWindowPosition);
} else {
// Check value if polling is disabled
this.readWindowPosition(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheWindowPosition = value;
callback(error, thisDevice.cacheWindowPosition);
});
}
}
DomotigaPlatform.prototype.setWindowPosition = function (accessory, targetPosition, callback) {
var self = this;
var thisDevice = accessory.context;
self.log("%s: setting window position to %s", thisDevice.name, targetPosition);
// At this time we do not use percentage values: 1 = open, 0 = closed
var windowPosition;
if (targetPosition == 0) {
windowPosition = "0";
}
else {
windowPosition = "100";
}
//var moveUp = (windowPosition >= thisDevice.cacheWindowPosition);
// Update cache
thisDevice.cacheWindowPosition = windowPosition;
// Update position state
accessory.getService(Service.Window).setCharacteristic(Characteristic.CurrentPosition, windowPosition);
accessory.getService(Service.Window).setCharacteristic(Characteristic.PositionState, Characteristic.PositionState.STOPPED);
//Update the value to iOS
accessory.getService(Service.Window).getCharacteristic(Characteristic.CURRENTPosition).updateValue(windowPosition);
var callbackWasCalled = false;
this.domotigaSetValue(thisDevice.device, thisDevice.valueWindow, windowPosition, function (err) {
if (callbackWasCalled) {
self.log.warn("WARNING: domotigaSetValue called its callback more than once! Discarding the second one.");
}
callbackWasCalled = true;
if (!err) {
self.log("%s: successfully set window position to %s", thisDevice.name, targetPosition);
callback(null, windowPosition);
} else {
self.log.error("%s: error setting window position to %s", thisDevice.name, targetPosition);
callback(err);
}
});
}
DomotigaPlatform.prototype.getWindowCoveringPositionState = function (thisDevice, callback) {
// At this time the value property of PositionState is always mapped to stopped
callback(null, Characteristic.PositionState.STOPPED);
}
DomotigaPlatform.prototype.readWindowCoveringPosition = function (thisDevice, callback) {
var self = this;
self.log("%s: getting window covering position...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueWindowCovering, function (error, result) {
if (error) {
self.log.error('%s: readWindowCoveringPosition failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = (result.toLowerCase() == "0") ? 0 : 100;
self.log('%s: window covering position: %s', thisDevice.name, value);
callback(null, value);
}
});
}
DomotigaPlatform.prototype.getWindowCoveringPosition = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached window covering position is: %s', thisDevice.name, thisDevice.cacheWindowCoveringPosition);
callback(null, thisDevice.cacheWindowCoveringPosition);
} else {
// Check value if polling is disabled
this.readWindowCoveringPosition(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheWindowCoveringPosition = value;
callback(error, thisDevice.cacheWindowCoveringPosition);
});
}
}
DomotigaPlatform.prototype.setWindowCoveringPosition = function (thisDevice, targetPosition, callback) {
var self = this;
self.log("%s: setting window covering position to %s", thisDevice.name, targetPosition);
// At this time we do not use percentage values: 1 = open, 0 = closed
var windowcoveringPosition;
if (targetPosition == 0) {
windowcoveringPosition = "0";
}
else {
windowcoveringPosition = "1";
}
// Update cache
thisDevice.cacheWindowCoveringPosition = windowcoveringPosition;
// Update position state
var accessory = this.accessories[thisDevice.name];
if (accessory) {
accessory.getService(Service.WindowCovering).setCharacteristic(Characteristic.PositionState, Characteristic.PositionState.STOPPED);
//Update the value to iOS
accessory.getService(Service.WindowCovering).getCharacteristic(Characteristic.TargetPosition).updateValue(windowcoveringPosition);
}
var callbackWasCalled = false;
this.domotigaSetValue(thisDevice.device, thisDevice.valueWindowCovering, windowcoveringPosition, function (err) {
if (callbackWasCalled) {
self.log.warn("WARNING: domotigaSetValue called its callback more than once! Discarding the second one.");
}
callbackWasCalled = true;
if (!err) {
self.log("%s: successfully set window covering position to %s", thisDevice.name, targetPosition);
callback(null, windowcoveringPosition);
} else {
self.log.error("%s: error setting window covering position to %s", thisDevice.name, targetPosition);
callback(err);
}
});
}
// Lightbulb
DomotigaPlatform.prototype.setLightState = function (thisDevice, value, callback) {
var self = this;
if (thisDevice.cacheLightState && thisDevice.brightness && value) {
callback(null);
} else {
var LightState = (value == false) ? "Off" : "On";
if (!thisDevice.cacheLightState && thisDevice.brightness && value) {
LightState = "Dim " + thisDevice.cacheLightBrightness;
}
self.log("%s: setting light state to %s", thisDevice.name, LightState);
// Update cache
thisDevice.cacheLightState = value;
var callbackWasCalled = false;
this.domotigaSetValue(thisDevice.device, thisDevice.valueLight, LightState, function (err) {
if (callbackWasCalled) {
self.log.warn("WARNING: domotigaSetValue called its callback more than once! Discarding the second one.");
}
callbackWasCalled = true;
if (!err) {
self.log("%s: successfully set light state to %s", thisDevice.name, LightState);
callback(null);
} else {
self.log.error("%s: error setting light state to %s", thisDevice.name, LightState);
callback(err);
}
});
}
}
DomotigaPlatform.prototype.readLightState = function (thisDevice, callback) {
var self = this;
self.log("%s: getting light state...", thisDevice.name);
self.domotigaGetValue(thisDevice.device, thisDevice.valueLight, function (error, result) {
if (error) {
self.log.error('%s: readLightState failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var LightState = (result == "0") ? 0 : 1;
self.log('%s: light state: %s', thisDevice.name, LightState);
callback(null, LightState);
}
});
}
DomotigaPlatform.prototype.getLightState = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
self.log('%s: cached light.state is: %s', thisDevice.name, thisDevice.cacheLightState);
callback(null, thisDevice.cacheLightState);
} else {
this.readLightState(thisDevice, function (error, value) {
if (thisDevice.Brightness == true) {
if (value == 0) {
thisDevice.cacheLightState = 0;
} else {
thisDevice.cacheLightState = value
}
} else {
thisDevice.cacheLightState = value;
}
callback(error, thisDevice.cacheLightState);
});
}
}
DomotigaPlatform.prototype.setLightBrightnessState = function (thisDevice, value, callback) {
var self = this;
var BrightnessState = value;
switch (value) {
case 0:
BrightnessState = "Off";
break;
case 100:
BrightnessState = "On";
break;
default:
BrightnessState = "Dim " + value;
break;
}
self.log("%s: setting light brightness to %s", thisDevice.name, value);
// Update cache
thisDevice.cacheLightBrightness = value;
var callbackWasCalled = false;
this.domotigaSetValue(thisDevice.device, thisDevice.valueLight, BrightnessState, function (err) {
if (callbackWasCalled) {
self.log.warn("WARNING: domotigaSetValue called its callback more than once! Discarding the second one.");
}
callbackWasCalled = true;
if (!err) {
self.log("%s: successfully set light brightness to %s", thisDevice.name, BrightnessState);
callback(null);
} else {
self.log.error("%s: error setting light brightness to %s", thisDevice.name, BrightnessState);
callback(err);
}
});
}
DomotigaPlatform.prototype.readLightBrightnessState = function (thisDevice, callback) {
var self = this;
self.log("%s: getting light brightness...", thisDevice.name);
self.domotigaGetValue(thisDevice.device, thisDevice.valueLight, function (error, result) {
if (error) {
self.log.error('%s: readLightBrightnessState failed: %s', thisDevice.name, error.message);
callback(error);
} else {
self.log('%s: light brightness: %s', thisDevice.name, result);
callback(null, result);
}
});
}
DomotigaPlatform.prototype.getLightBrightnessState = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
self.log('%s: cached light.brightness is: %s', thisDevice.name, thisDevice.cacheLightBrightness);
callback(null, thisDevice.cacheLightBrightness);
} else {
this.readLightBrightnessState(thisDevice, function (error, value) {
thisDevice.cacheLightBrightness = value;
callback(error, thisDevice.cacheLightBrightness);
});
}
}
DomotigaPlatform.prototype.setTargetTemperature = function (thisDevice, value, callback) {
var self = this;
self.log("%s: setting target temperature to %s", thisDevice.name, value);
// Update cache
thisDevice.cacheTargetTemperature = value;
var callbackWasCalled = false;
this.domotigaSetValue(thisDevice.device, thisDevice.valueTargetTemperature, value, function (err) {
if (callbackWasCalled) {
self.log.warn("WARNING: domotigaSetValue called its callback more than once! Discarding the second one.");
}
callbackWasCalled = true;
if (!err) {
self.log("%s: successfully set target temperature to %s", thisDevice.name, value);
callback(null);
} else {
self.log.error("%s: error setting target temperature to %s", thisDevice.name, value);
callback(err);
}
});
}
DomotigaPlatform.prototype.readTargetTemperature = function (thisDevice, callback) {
var self = this;
self.log("%s: getting target temperature...", thisDevice.name);
this.domotigaGetValue(thisDevice.device, thisDevice.valueTargetTemperature, function (error, result) {
if (error) {
self.log.error('%s: readTargetTemperature failed: %s', thisDevice.name, error.message);
callback(error);
} else {
var value = Number(result);
self.log('%s: target temperature: %s', thisDevice.name, value);
callback(null, value);
}
});
}
// Method to determine target temperature
DomotigaPlatform.prototype.getTargetTemperature = function (thisDevice, callback) {
var self = this;
if (thisDevice.polling && thisDevice.initHistory) {
// Get value directly from cache if polling is enabled
self.log('%s: cached temperature is: %s', thisDevice.name, thisDevice.cacheTargetTemperature);
callback(null, thisDevice.cacheTargetTemperature);
} else {
// Check value if polling is disabled
this.readTargetTemperature(thisDevice, function (error, value) {
// Update cache
thisDevice.cacheTargetTemperature = value;
callback(error, thisDevice.cacheTargetTemperature);
});
}
}
DomotigaPlatform.prototype.getTargetHeatingCoolingState = function (thisDevice, callback) {
this.log("%s: getting TargetHeatingCoolingState...", thisDevice.name);
callback(null, thisDevice.cacheTargetHeatingCoolingState);
}
DomotigaPlatform.prototype.setTargetHeatingCoolingState = function (thisDevice, value, callback) {
var self = this;
var command = "0";
this.log("%s: setting TargetHeatingCoolingState to %s", thisDevice.name, value);
//value must be one of the following:
//Characteristic.TargetHeatingCoolingState.OFF = 0;
//Characteristic.TargetHeatingCoolingState.HEAT = 1;
//Characteristic.TargetHeatingCoolingState.COOL = 2;
//Characteristic.TargetHeatingCoolingState.AUTO = 3;
// Update cache
thisDevice.cacheTargetHeatingCoolingState = value;
//Only turn off Thermostat override if TargetHeatingCoolingState.OFF
if (value == Characteristic.TargetHeatingCoolingState.OFF) {
var callbackWasCalled = false;
this.domotigaSetValue(thisDevice.device, thisDevice.valueTargetTemperature, command, function (err) {
if (callbackWasCalled) {
self.log.warn("WARNING: domotigaSetValue called its callback more than once! Discarding the second one.");
}
callbackWasCalled = true;
if (!err) {
self.log("%s: successfully send turning off thermostat override command.", thisDevice.name);
callback(null);
} else {
self.log.error("%s: error sending turning off thermostat override command.", thisDevice.name);
callback(err);
}
});
} else {
self.log("%s: ignore setting TargetHeatingCoolingState because of no support at DomotiGa.", thisDevice.name);
callback(null);
}
}
// Method to handle identify request
DomotigaPlatform.prototype.identify = function (thisDevice, paired, callback) {
this.log("%s: identify requested", thisDevice.name);
callback();
}
// Set value at domotiga database
DomotigaPlatform.prototype.domotigaSetValue = function (device, deviceValueNo, value, callback) {
var self = this;
JSONRequest('http://' + this.host + ':' + this.port, {
jsonrpc: "2.0",
method: "device.set",
params: {
"device_id": device,
"valuenum": deviceValueNo,
"value": value
},
id: 1
}, function (err, data) {
//this.log("data:", data);
if (err) {
self.log.error("Sorry err: ", err);
callback(err);
} else {
callback();
}
});
}
// Get value from domotiga database
DomotigaPlatform.prototype.domotigaGetValue = function (device, deviceValueNo, callback) {
//skip request if value doesn't exist in domotiga
if (deviceValueNo != 99) {
var self = this;
//self.log( "domotigaGetValue, device : %s - deviceValueNo : ",device, deviceValueNo);
JSONRequest('http://' + self.host + ':' + self.port, {
jsonrpc: "2.0",
method: "value.get",
params: {
"device_id": device,
"valuenum": deviceValueNo,
"command": "value"
},
id: 1
}, function (err, data) {
if (err) {
self.log.error("Sorry err: ", err);
callback(err);
} else {
let item = Number(deviceValueNo) - 1;
//self.log("data.result:", data.result);
//self.log("data.result.value:", data.result.value);
if (data.result != undefined) {
// try to convert
if (typeof data.result.value == "string" && (data.result.value.toLowerCase() == "on" || data.result.value.toLowerCase() == "true")) {
callback(null, 1);
} else if (typeof data.result.value == "string" && (data.result.value.toLowerCase() == "off" || data.result.value.toLowerCase() == "false")) {
callback(null, 0);
} else if (typeof data.result.value == "string" && (data.result.value.substr(0, 3).toLowerCase() == "dim")) {
callback(null, data.result.value.substr(4).toLowerCase())
} else {
callback(null, data.result.value);
}
} else {
self.log.warn("Undefined data for device %s, value %s", device, deviceValueNo);
callback();
}
}
});
} else {
callback(null, 0)
}
}
DomotigaPlatform.prototype.getVersion = function () {
var pjPath = path.join(__dirname, './package.json');
var pj = JSON.parse(fs.readFileSync(pjPath));
return pj.version;
}
DomotigaPlatform.prototype.fetch_npmVersion = function (pck, callback) {
var exec = require('child_process').exec;
var cmd = 'npm view ' + pck + ' version';
exec(cmd, function (error, stdout, stderr) {
var npm_version = stdout;
npm_version = npm_version.replace('\n', '');
callback(npm_version);
});
}
// Method to handle plugin configuration in HomeKit app
DomotigaPlatform.prototype.configurationRequestHandler = function (context, request, callback) {
if (request && request.type === "Terminate") {
return;
}
// Instruction
if (!context.step) {
var instructionResp = {
"type": "Interface",
"interface": "instruction",
"title": "Before You Start...",
"detail": "Please make sure homebridge is running with elevated privileges.",
"showNextButton": true
}
context.step = 1;
callback(instructionResp);
} else {
switch (context.step) {
case 1:
// Operation choices
var respDict = {
"type": "Interface",
"interface": "list",
"title": "What do you want to do?",
"items": [
"Add New Device",
"Modify Existing Device",
"Remove Existing Device"
]
}
context.step = 2;
callback(respDict);
break;
case 2:
var selection = request.response.selections[0];
if (selection === 0) {
// Info for new accessory
var respDict = {
"type": "Interface",
"interface": "input",
"title": "New Device",
"items": [{
"id": "name",
"title": "Name (Required)",
"placeholder": "HTPC"
}]
};
context.operation = 0;
context.step = 3;
callback(respDict);
} else {
var self = this;
var names = Object.keys(this.accessories).map(function (k) { return self.accessories[k].context.name });
if (names.length > 0) {
// Select existing accessory for modification or removal
if (selection === 1) {
var title = "Which device do you want to modify?";
context.operation = 1;
} else {
var title = "Which device do you want to remove?";
context.operation = 2;
}
var respDict = {
"type": "Interface",
"interface": "list",
"title": title,
"items": names
};
context.list = names;
context.step = 3;
} else {
var respDict = {
"type": "Interface",
"interface": "instruction",
"title": "Unavailable",
"detail": "No device is configured.",
"showNextButton": true
};
context.step = 1;
}
callback(respDict);
}
break;
case 3:
if (context.operation === 2) {
// Remove selected accessory from HomeKit
var selection = context.list[request.response.selections[0]];
var accessory = this.accessories[selection];
this.removeAccessory(accessory);
var respDict = {
"type": "Interface",
"interface": "instruction",
"title": "Success",
"detail": "The device is now removed.",
"showNextButton": true
};
context.step = 5;
}
else {
if (context.operation === 0) {
var data = request.response.inputs;
} else if (context.operation === 1) {
var selection = context.list[request.response.selections[0]];
var data = this.accessories[selection].context;
}
// if (data.name) {
// // Add/Modify info of selected accessory
// var respDict = {
// "type": "Interface",
// "interface": "input",
// "title": data.name,
// "items": [{
// "id": "on_cmd",
// "title": "CMD to Turn On",
// "placeholder": context.operation ? "Leave blank if unchanged" : "wakeonlan XX:XX:XX:XX:XX:XX"
// }, {
// "id": "off_cmd",
// "title": "CMD to Turn Off",
// "placeholder": context.operation ? "Leave blank if unchanged" : "net rpc shutdown -I XXX.XXX.XXX.XXX -U user%password"
// }, {
// "id": "state_cmd",
// "title": "CMD to Check ON State",
// "placeholder": context.operation ? "Leave blank if unchanged" : "ping -c 2 -W 1 XXX.XXX.XXX.XXX | grep -i '2 received'"
// }, {
// "id": "polling",
// "title": "Enable Polling (true/false)",
// "placeholder": context.operation ? "Leave blank if unchanged" : "false"
// }, {
// "id": "interval",
// "title": "Polling Interval",
// "placeholder": context.operation ? "Leave blank if unchanged" : "1"
// }, {
// "id": "manufacturer",
// "title": "Manufacturer",
// "placeholder": context.operation ? "Leave blank if unchanged" : "Default-Manufacturer"
// }, {
// "id": "model",
// "title": "Model",
// "placeholder": context.operation ? "Leave blank if unchanged" : "Default-Model"
// }, {
// "id": "serial",
// "title": "Serial",
// "placeholder": context.operation ? "Leave blank if unchanged" : "Default-SerialNumber"
// }]
// };
// delete context.list;
// delete context.operation;
// context.name = data.name;
// context.step = 4;
// }
else {
// Error if required info is missing
var respDict = {
"type": "Interface",
"interface": "instruction",
"title": "Error",
"detail": "Name of the device is missing.",
"showNextButton": true
};
context.step = 1;
}
}
callback(respDict);
break;
//case 4:
// var userInputs = request.response.inputs;
// var newSwitch = {};
// // Setup input for addAccessory
// if (this.accessories[context.name]) {
// newSwitch = JSON.parse(JSON.stringify(this.accessories[context.name].context));
// }
// newAccessory.name = context.name;
// newAccessory.on_cmd = userInputs.on_cmd || newSwitch.on_cmd;
// newAccessory.off_cmd = userInputs.off_cmd || newSwitch.off_cmd;
// newAccessory.state_cmd = userInputs.state_cmd || newSwitch.state_cmd;
// newAccessory.polling = userInputs.polling || newSwitch.polling;
// newAccessory.interval = userInputs.interval || newSwitch.interval;
// newAccessory.manufacturer = userInputs.manufacturer;
// newAccessory.model = userInputs.model;
// newAccessory.serial = userInputs.serial;
// // Register or update accessory in HomeKit
// this.addAccessory(newAccessory);
// var respDict = {
// "type": "Interface",
// "interface": "instruction",
// "title": "Success",
// "detail": "The new device is now updated.",
// "showNextButton": true
// };
// context.step = 5;
// callback(respDict);
// break;
//case 5:
// // Update config.json accordingly
// var self = this;
// delete context.step;
// var newConfig = this.config;
// var newSwitches = Object.keys(this.accessories).map(function (k) {
// var accessory = self.accessories[k];
// var data = {
// 'name': accessory.context.name,
// 'on_cmd': accessory.context.on_cmd,
// 'off_cmd': accessory.context.off_cmd,
// 'state_cmd': accessory.context.state_cmd,
// 'polling': accessory.context.polling,
// 'interval': accessory.context.interval,
// 'manufacturer': accessory.context.manufacturer,
// 'model': accessory.context.model,
// 'serial': accessory.context.serial
// };
// return data;
// });
// newConfig.switches = newSwitches;
// callback(null, "platform", true, newConfig);
// break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment