Skip to content

Commit

Permalink
ElectricitySensor OK, Alarm OK
Browse files Browse the repository at this point in the history
  • Loading branch information
Romain DUBOC committed Apr 5, 2017
1 parent e4197ae commit 5bc0647
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 72 deletions.
96 changes: 61 additions & 35 deletions accessories/Alarm.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var Service, Characteristic, Command, ExecutionState, State, AbstractAccessory;

var sharedCurrentState, sharedTargetState, initCurrentState, initTargetState;

module.exports = function(homebridge, abstractAccessory, api) {
AbstractAccessory = abstractAccessory;
Service = homebridge.hap.Service;
Expand All @@ -21,13 +23,17 @@ Alarm = function(log, api, device, config) {
this.stayZones = config.STAY_ARM || 'A';
this.nightZones = config.NIGHT_ARM || 'B';

var service = new Service.SecuritySystem(device.label);

this.currentState = service.getCharacteristic(Characteristic.SecuritySystemCurrentState);
this.targetState = service.getCharacteristic(Characteristic.SecuritySystemTargetState)
this.targetState.on('set', this.setState.bind(this));

this.services.push(service);
var service = new Service.SecuritySystem(device.label);
this.currentState = service.getCharacteristic(Characteristic.SecuritySystemCurrentState);
this.targetState = service.getCharacteristic(Characteristic.SecuritySystemTargetState);
this.targetState.on('set', this.setState.bind(this));

// Store a static shared state for splited alarm component
if(this.device.widget == 'StatelessAlarmController') {
this.currentState.updateValue(Characteristic.SecuritySystemCurrentState.DISARMED);
this.targetState.updateValue(Characteristic.SecuritySystemTargetState.DISARM);
}
this.services.push(service);
};

Alarm.UUID = 'Alarm';
Expand All @@ -40,32 +46,32 @@ Alarm.prototype = {
setState: function(value, callback) {
var that = this;
var command = null;
switch(value) {
default:
case Characteristic.SecuritySystemTargetState.STAY_ARM:
command = new Command('alarmZoneOn');
command.parameters = [this.stayZones];
break;
case Characteristic.SecuritySystemTargetState.NIGHT_ARM:
command = new Command('alarmZoneOn');
command.parameters = [this.nightZones];
break;
case Characteristic.SecuritySystemTargetState.AWAY_ARM:
command = new Command('alarmOn');
break;
case Characteristic.SecuritySystemTargetState.DISARM:
command = new Command('alarmOff');
break;
}
switch(value) {
default:
case Characteristic.SecuritySystemTargetState.STAY_ARM:
command = new Command('alarmZoneOn');
command.parameters = [this.stayZones];
break;
case Characteristic.SecuritySystemTargetState.NIGHT_ARM:
command = new Command('alarmZoneOn');
command.parameters = [this.nightZones];
break;
case Characteristic.SecuritySystemTargetState.AWAY_ARM:
command = new Command('alarmOn');
break;
case Characteristic.SecuritySystemTargetState.DISARM:
command = new Command('alarmOff');
break;
}
this.executeCommand(command, function(status, error, data) {
switch (status) {
case ExecutionState.INITIALIZED:
callback(error);
break;
case ExecutionState.COMPLETED:
if(that.device.widget == 'StatelessAlarmController') { // If stateless alarm, update target immediately
that.currentState.updateValue(value);
}
if(that.device.widget == 'StatelessAlarmController') {
this.currentState.updateValue(value);
}
break;
case ExecutionState.FAILED:
// Restore current state as target
Expand All @@ -78,22 +84,42 @@ Alarm.prototype = {
},

onStateUpdate: function(name, value) {
//this.log.debug('['+this.name+'] ' + name + '=' + value); // For analysis
//this.log('['+this.name+'] ' + name + '=' + value); // For analysis
if (name == State.STATE_ACTIVE_ZONES) {
var converted = null;
var target = null;
switch(value) {
default:
case '': target = converted = Characteristic.SecuritySystemCurrentState.DISARMED; break;
case 'A': target = converted = Characteristic.SecuritySystemCurrentState.STAY_ARM; break;
case 'A,B,C': target = converted = Characteristic.SecuritySystemCurrentState.AWAY_ARM; break;
case 'B': target = converted = Characteristic.SecuritySystemCurrentState.NIGHT_ARM; break;
case 'triggered': converted = Characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED; break;
}
default:
case '': target = converted = Characteristic.SecuritySystemCurrentState.DISARMED; break;
case this.stayZones: target = converted = Characteristic.SecuritySystemCurrentState.STAY_ARM; break;
case 'A,B,C': target = converted = Characteristic.SecuritySystemCurrentState.AWAY_ARM; break;
case this.nightZones: target = converted = Characteristic.SecuritySystemCurrentState.NIGHT_ARM; break;
case 'triggered': converted = Characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED; break;
}

this.currentState.updateValue(converted);
if (!this.isCommandInProgress()) // if no command running, update target
this.targetState.updateValue(target);
} else if (name == 'internal:CurrentAlarmModeState') {
var converted = null;
switch(value) {
default:
case 'off': converted = Characteristic.SecuritySystemCurrentState.DISARMED; break;
case 'partial1': converted = Characteristic.SecuritySystemCurrentState.STAY_ARM; break;
case 'total': converted = Characteristic.SecuritySystemCurrentState.AWAY_ARM; break;
case 'partial2': converted = Characteristic.SecuritySystemCurrentState.NIGHT_ARM; break;
}
this.currentState.updateValue(converted);
} else if (name == 'internal:TargetAlarmModeState') {
var converted = null;
switch(value) {
default:
case 'off': converted = Characteristic.SecuritySystemTargetState.DISARM; break;
case 'partial1': converted = Characteristic.SecuritySystemTargetState.STAY_ARM; break;
case 'total': converted = Characteristic.SecuritySystemTargetState.AWAY_ARM; break;
case 'partial2': converted = Characteristic.SecuritySystemTargetState.NIGHT_ARM; break;
}
this.targetState.updateValue(converted);
}
}
}
93 changes: 93 additions & 0 deletions accessories/ElectricitySensor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
var Service, Characteristic, Command, ExecutionState, State, AbstractAccessory;

var PowerConsumption, EnergyConsumption;

var inherits = function (ctor, superCtor) {

if (ctor === undefined || ctor === null)
throw new TypeError('The constructor to "inherits" must not be ' +
'null or undefined');

if (superCtor === undefined || superCtor === null)
throw new TypeError('The super constructor to "inherits" must not ' +
'be null or undefined');

if (superCtor.prototype === undefined)
throw new TypeError('The super constructor to "inherits" must ' +
'have a prototype');

ctor.super_ = superCtor;
Object.setPrototypeOf(ctor.prototype, superCtor.prototype);
}

module.exports = function(homebridge, abstractAccessory, api) {
AbstractAccessory = abstractAccessory;
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
Command = api.Command;
ExecutionState = api.ExecutionState;
State = api.State;

makeCharacteristics();

return ElectricitySensor;
}

/**
* Accessory "ElectricitySensor"
*/

ElectricitySensor = function(log, api, device) {
AbstractAccessory.call(this, log, api, device);
var service = new Service.Outlet(device.label);
service.addCharacteristic(EnergyConsumption);
service.addCharacteristic(PowerConsumption);

this.energyState = service.getCharacteristic(EnergyConsumption);
this.powerState = service.getCharacteristic(PowerConsumption);

this.services.push(service);
};

ElectricitySensor.UUID = 'ElectricitySensor';

ElectricitySensor.prototype = {

onStateUpdate: function(name, value) {
if (name == 'core:ElectricEnergyConsumptionState') {
this.energyState.updateValue(value);
} else if (name == 'core:ElectricPowerConsumptionState') {
this.powerState.updateValue(value);
}
}
}

function makeCharacteristics() {
PowerConsumption = function() {
Characteristic.call(this, 'Current Consumption', 'E863F10D-079E-48FF-8F27-9C2605A29F52');
this.setProps({
format: Characteristic.Formats.INT,
maxValue: 65535,
minValue: 0,
minStep: 1,
unit: "W",
perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY]
});
this.value = this.getDefaultValue();
};
inherits(PowerConsumption, Characteristic);

EnergyConsumption = function() {
Characteristic.call(this, 'Total Consumption', 'E863F10C-079E-48FF-8F27-9C2605A29F52');
this.setProps({
format: Characteristic.Formats.FLOAT,
maxValue: 4294967295,
minValue: 0,
minStep: 0.01,
unit: "kWh",
perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY]
});
this.value = this.getDefaultValue();
};
inherits(EnergyConsumption, Characteristic);
}
22 changes: 12 additions & 10 deletions accessories/GarageDoor.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ GarageDoor = function(log, api, device) {
this.currentState = service.getCharacteristic(Characteristic.CurrentDoorState);
this.targetState = service.getCharacteristic(Characteristic.TargetDoorState)
if(this.device.widget == 'UpDownGarageDoor4T') {
this.currentState.updateValue(Characteristic.CurrentDoorState.CLOSED);
this.targetState.updateValue(Characteristic.TargetDoorState.CLOSED);
this.targetState.on('set', this.cycle.bind(this));
} else {
this.targetState.on('set', this.setState.bind(this));
Expand Down Expand Up @@ -94,16 +96,16 @@ GarageDoor.prototype = {
var converted = null;
var target = null;
switch(value) {
case 'unknown':
case 'open' :
converted = Characteristic.CurrentDoorState.OPEN;
target = Characteristic.TargetDoorState.OPEN;
break;
case 'closed' :
converted = Characteristic.CurrentDoorState.CLOSED;
target = Characteristic.TargetDoorState.CLOSED;
break;
}
case 'unknown':
case 'open' :
converted = Characteristic.CurrentDoorState.OPEN;
target = Characteristic.TargetDoorState.OPEN;
break;
case 'closed' :
converted = Characteristic.CurrentDoorState.CLOSED;
target = Characteristic.TargetDoorState.CLOSED;
break;
}

this.currentState.updateValue(converted);
if (!this.isCommandInProgress()) // if no command running, update target
Expand Down
2 changes: 2 additions & 0 deletions accessories/Gate.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Gate = function(log, api, device) {
this.currentState = service.getCharacteristic(Characteristic.CurrentDoorState);
this.targetState = service.getCharacteristic(Characteristic.TargetDoorState)
if(this.device.widget == 'OpenCloseGate4T') {
this.currentState.updateValue(Characteristic.CurrentDoorState.CLOSED);
this.targetState.updateValue(Characteristic.TargetDoorState.CLOSED);
this.targetState.on('set', this.cycle.bind(this));
} else {
this.targetState.on('set', this.setState.bind(this));
Expand Down
7 changes: 2 additions & 5 deletions accessories/RollerShutter.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ RollerShutter = function(log, api, device, config) {
AbstractAccessory.call(this, log, api, device);
var service = new Service.WindowCovering(device.label);

this.stayZones = config.STAY_ARM || 'A';
this.nightZones = config.NIGHT_ARM || 'B';

this.currentPosition = service.getCharacteristic(Characteristic.CurrentPosition);
this.targetPosition = service.getCharacteristic(Characteristic.TargetPosition);
if(this.device.widget == 'UpDownRollerShutter') {
Expand Down Expand Up @@ -59,7 +56,7 @@ RollerShutter.prototype = {
case ExecutionState.IN_PROGRESS:
var newValue = (value == 100 || value > that.currentPosition.value) ? Characteristic.PositionState.INCREASING : Characteristic.PositionState.DECREASING;
that.positionState.updateValue(newValue);
that.log('['+that.name+'] Command in progress, state='+newValue);
that.log.debug('['+that.name+'] Command in progress, state='+newValue);
break;
case ExecutionState.COMPLETED:
case ExecutionState.FAILED:
Expand Down Expand Up @@ -112,7 +109,7 @@ RollerShutter.prototype = {

onStateUpdate: function(name, value) {
if (name == State.STATE_CLOSURE) {
this.log('['+this.name+'] ' + name + '=' + value); // For analysis
this.log.debug('['+this.name+'] ' + name + '=' + value); // For analysis
var converted = 100 - value;
this.currentPosition.updateValue(converted);
if (!this.isCommandInProgress()) // if no command running, update target
Expand Down
42 changes: 21 additions & 21 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function TahomaPlatform(log, config, api) {

this.exclusions = config.exclude || [];
this.exclusions.push('internal'); // Exclude internal devices
this.api = new OverkizService.Api(log, config);
this.api = new OverkizService.Api(log, config);

this.platformAccessories = [];

Expand All @@ -48,27 +48,27 @@ TahomaPlatform.prototype = {
this.log.info("Fetching accessories...");
if (that.platformAccessories.length == 0) {
this.api.getDevices(function(error, data) {
if (!error) {
for (device of data) {
var accessory = null;
var protocol = device.controllableName.split(':').shift(); // Get device protocol name
var accessoryConfig = that.config[device.uiClass] || {};
if(DeviceAccessory[device.uiClass] != null && that.exclusions.indexOf(protocol) == -1 && that.exclusions.indexOf(device.label) == -1) {
accessory = new DeviceAccessory[device.uiClass](that.log, that.api, device, accessoryConfig);
} else {
that.log.info('Device ' + device.uiClass + ' ignored');
}
if(accessory != null) {
if(device.states != null) {
for (state of device.states) {
accessory.onStateUpdate(state.name, state.value);
}
}
that.platformAccessories.push(accessory);
}
}
if (!error) {
for (device of data) {
var accessory = null;
var protocol = device.controllableName.split(':').shift(); // Get device protocol name
var accessoryConfig = that.config[device.uiClass] || {};
if(DeviceAccessory[device.uiClass] != null && that.exclusions.indexOf(protocol) == -1 && that.exclusions.indexOf(device.label) == -1) {
accessory = new DeviceAccessory[device.uiClass](that.log, that.api, device, accessoryConfig);
} else {
that.log.info('Device ' + device.uiClass + ' ignored');
}
if(accessory != null) {
if(device.states != null) {
for (state of device.states) {
accessory.onStateUpdate(state.name, state.value);
}
}
that.platformAccessories.push(accessory);
}
}
callback(that.platformAccessories);
}
callback(that.platformAccessories);
});
} else {
callback(this.platformAccessories);
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"name": "homebridge-tahoma",
"version": "0.0.8",
"version": "0.1.0",
"description": "Sample Platform plugin for TaHoma and Cozytouch services (Somfy,Atlantic,Thermor,Sauter): https://github.com/dubocr/homebridge-tahoma",
"author": "Romain DUBOC",
"license": "ISC",
"keywords": [
"homebridge-plugin"
Expand All @@ -17,6 +18,7 @@
"node": ">=0.12.0",
"homebridge": ">=0.2.0"
},
"homepage": "https://github.com/dubocr/homebridge-tahoma#readme",
"dependencies": {
"request": "^2.65.0",
"polling-to-event": ">=2.0.2",
Expand Down

0 comments on commit 5bc0647

Please sign in to comment.