mirror of
https://github.com/mtan93/homebridge.git
synced 2026-03-08 05:31:55 +00:00
Merge branch 'nfarina/master'
This commit is contained in:
@@ -30,7 +30,31 @@ HomeMatic.prototype = {
|
||||
}
|
||||
});
|
||||
},
|
||||
getPowerState: function(callback) {
|
||||
var that = this;
|
||||
|
||||
this.log("Getting Power State of CCU");
|
||||
request.get({
|
||||
url: "http://"+this.ccuIP+"/config/xmlapi/state.cgi?datapoint_id="+this.ccuID,
|
||||
}, function(err, response, body) {
|
||||
|
||||
if (!err && response.statusCode == 200) {
|
||||
|
||||
//that.log("Response:"+response.body);
|
||||
var responseString = response.body.substring(83,87);
|
||||
//that.log(responseString);
|
||||
switch(responseString){
|
||||
case "true": {modvalue = "1";break;}
|
||||
case "fals": {modvalue = "0";break;}
|
||||
}
|
||||
callback(parseInt(modvalue));
|
||||
that.log("Getting Power State complete.");
|
||||
}
|
||||
else {
|
||||
that.log("Error '"+err+"' getting Power State: " + body);
|
||||
}
|
||||
});
|
||||
},
|
||||
getServices: function() {
|
||||
var that = this;
|
||||
return [{
|
||||
@@ -101,6 +125,7 @@ HomeMatic.prototype = {
|
||||
},{
|
||||
cType: types.POWER_STATE_CTYPE,
|
||||
onUpdate: function(value) { that.setPowerState(value); },
|
||||
onRead: function(callback) { that.getPowerState(callback); },
|
||||
perms: ["pw","pr","ev"],
|
||||
format: "bool",
|
||||
initialValue: false,
|
||||
|
||||
264
accessories/HomeMaticThermo.js
Normal file
264
accessories/HomeMaticThermo.js
Normal file
@@ -0,0 +1,264 @@
|
||||
var types = require("HAP-NodeJS/accessories/types.js");
|
||||
var request = require("request");
|
||||
|
||||
function HomeMaticThermo(log, config) {
|
||||
this.log = log;
|
||||
this.name = config["name"];
|
||||
this.ccuIDTargetTemp = config["ccu_id_TargetTemp"];
|
||||
this.ccuIDCurrentTemp = config["ccu_id_CurrentTemp"];
|
||||
this.ccuIDControlMode = config["ccu_id_ControlMode"];
|
||||
this.ccuIDManuMode = config["ccu_id_ManuMode"];
|
||||
this.ccuIDAutoMode = config["ccu_id_AutoMode"];
|
||||
this.ccuIP = config["ccu_ip"];
|
||||
}
|
||||
|
||||
HomeMaticThermo.prototype = {
|
||||
|
||||
setTargetTemperature: function(value) {
|
||||
|
||||
var that = this;
|
||||
|
||||
this.log("Setting target Temperature of CCU to " + value);
|
||||
this.log(this.ccuIDTargetTemp + " " + value);
|
||||
|
||||
request.put({
|
||||
url: "http://"+this.ccuIP+"/config/xmlapi/statechange.cgi?ise_id="+this.ccuIDTargetTemp+"&new_value="+ value,
|
||||
}, function(err, response, body) {
|
||||
|
||||
if (!err && response.statusCode == 200) {
|
||||
that.log("State change complete.");
|
||||
}
|
||||
else {
|
||||
that.log("Error '"+err+"' setting Temperature: " + body);
|
||||
}
|
||||
});
|
||||
},
|
||||
getCurrentTemperature: function(callback) {
|
||||
|
||||
var that = this;
|
||||
|
||||
this.log("Getting current Temperature of CCU");
|
||||
request.get({
|
||||
url: "http://"+this.ccuIP+"/config/xmlapi/state.cgi?datapoint_id="+this.ccuIDCurrentTemp,
|
||||
}, function(err, response, body) {
|
||||
|
||||
if (!err && response.statusCode == 200) {
|
||||
|
||||
//that.log("Response:"+response.body);
|
||||
var responseString = response.body.substring(83,87);
|
||||
//that.log(responseString);
|
||||
callback(parseFloat(responseString));
|
||||
//that.log("Getting current temperature complete.");
|
||||
}
|
||||
else {
|
||||
that.log("Error '"+err+"' getting Temperature: " + body);
|
||||
}
|
||||
});
|
||||
},
|
||||
getTargetTemperature: function(callback) {
|
||||
|
||||
var that = this;
|
||||
|
||||
this.log("Getting target Temperature of CCU");
|
||||
request.get({
|
||||
url: "http://"+this.ccuIP+"/config/xmlapi/state.cgi?datapoint_id="+this.ccuIDTargetTemp,
|
||||
}, function(err, response, body) {
|
||||
|
||||
if (!err && response.statusCode == 200) {
|
||||
|
||||
//that.log("Response:"+response.body);
|
||||
var responseString = response.body.substring(83,87);
|
||||
//that.log(responseString);
|
||||
callback(parseFloat(responseString));
|
||||
//that.log("Getting target temperature complete.");
|
||||
}
|
||||
else {
|
||||
that.log("Error '"+err+"' getting Temperature: " + body);
|
||||
}
|
||||
});
|
||||
},
|
||||
getMode: function(callback) {
|
||||
|
||||
var that = this;
|
||||
|
||||
//this.log("Getting target Mode of CCU");
|
||||
//this.log(this.ccuID+ value);
|
||||
|
||||
request.get({
|
||||
url: "http://"+this.ccuIP+"/config/xmlapi/state.cgi?datapoint_id="+this.ccuIDControlMode,
|
||||
}, function(err, response, body) {
|
||||
|
||||
if (!err && response.statusCode == 200) {
|
||||
|
||||
//that.log("Response:"+response.body);
|
||||
var responseInt = response.body.substring(83,84);
|
||||
//that.log(responseString);
|
||||
if (responseInt == 1)
|
||||
{ callback(parseInt("0")); }
|
||||
if (responseInt == 0)
|
||||
{ callback(parseInt("1")); }
|
||||
//that.log("Getting mode complete.");
|
||||
}
|
||||
else {
|
||||
that.log("Error '"+err+"' getting Mode: " + body);
|
||||
}
|
||||
});
|
||||
},
|
||||
setMode: function(value) {
|
||||
|
||||
var that = this;
|
||||
|
||||
//this.log("Seting target Mode of CCU:" + value);
|
||||
var modvalue;
|
||||
var dpID;
|
||||
switch(value) {
|
||||
case 3: {modvalue = "true";dpID=this.ccuIDAutoMode;break;} //auto
|
||||
case 1: {modvalue = "true";dpID=this.ccuIDAutoMode;break;} //heating => auto
|
||||
default: {modvalue = "1";dpID=this.ccuIDManuMode;} //default => off (manual)
|
||||
}
|
||||
|
||||
request.put({
|
||||
url: "http://"+this.ccuIP+"/config/xmlapi/statechange.cgi?ise_id="+dpID+"&new_value="+ modvalue,
|
||||
}, function(err, response, body) {
|
||||
|
||||
if (!err && response.statusCode == 200) {
|
||||
//that.log("Setting Mode complete.");
|
||||
}
|
||||
else {
|
||||
that.log("Error '"+err+"' setting Mode: " + body);
|
||||
}
|
||||
});
|
||||
},
|
||||
getServices: function() {
|
||||
var that = this;
|
||||
return [{
|
||||
sType: types.ACCESSORY_INFORMATION_STYPE,
|
||||
characteristics: [{
|
||||
cType: types.NAME_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr"],
|
||||
format: "string",
|
||||
initialValue: this.name,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Name of the accessory",
|
||||
designedMaxLength: 255
|
||||
},{
|
||||
cType: types.MANUFACTURER_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr"],
|
||||
format: "string",
|
||||
initialValue: "test",
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Manufacturer",
|
||||
designedMaxLength: 255
|
||||
},{
|
||||
cType: types.MODEL_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr"],
|
||||
format: "string",
|
||||
initialValue: "test",
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Model",
|
||||
designedMaxLength: 255
|
||||
},{
|
||||
cType: types.SERIAL_NUMBER_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr"],
|
||||
format: "string",
|
||||
initialValue: "A1S2NREF88EW",
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "SN",
|
||||
designedMaxLength: 255
|
||||
},{
|
||||
cType: types.IDENTIFY_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pw"],
|
||||
format: "bool",
|
||||
initialValue: false,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Identify Accessory",
|
||||
designedMaxLength: 1
|
||||
}]
|
||||
},{
|
||||
sType: types.THERMOSTAT_STYPE,
|
||||
characteristics: [{
|
||||
cType: types.NAME_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr"],
|
||||
format: "string",
|
||||
initialValue: this.name,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Name of service",
|
||||
designedMaxLength: 255
|
||||
},{
|
||||
cType: types.CURRENTHEATINGCOOLING_CTYPE,
|
||||
onRead: function(callback) { that.getMode(callback); },
|
||||
perms: ["pr","ev"],
|
||||
format: "int",
|
||||
initialValue: 0,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Current Mode",
|
||||
designedMaxLength: 1,
|
||||
designedMinValue: 0,
|
||||
designedMaxValue: 2,
|
||||
designedMinStep: 1,
|
||||
},{
|
||||
cType: types.TARGETHEATINGCOOLING_CTYPE,
|
||||
onRead: function(callback) { that.getMode(callback); },
|
||||
onUpdate: function(value) { that.setMode(value);},
|
||||
perms: ["pw","pr","ev"],
|
||||
format: "int",
|
||||
initialValue: 0,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Target Mode",
|
||||
designedMinValue: 0,
|
||||
designedMaxValue: 3,
|
||||
designedMinStep: 1,
|
||||
},{
|
||||
cType: types.CURRENT_TEMPERATURE_CTYPE,
|
||||
onRead: function(callback) { that.getCurrentTemperature(callback); },
|
||||
onUpdate: null,
|
||||
perms: ["pr","ev"],
|
||||
format: "float",
|
||||
initialValue: 13.0,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Current Temperature",
|
||||
unit: "celsius"
|
||||
},{
|
||||
cType: types.TARGET_TEMPERATURE_CTYPE,
|
||||
onUpdate: function(value) { that.setTargetTemperature(value); },
|
||||
onRead: function(callback) { that.getTargetTemperature(callback); },
|
||||
perms: ["pw","pr","ev"],
|
||||
format: "float",
|
||||
initialValue: 19.0,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Target Temperature",
|
||||
designedMinValue: 4,
|
||||
designedMaxValue: 25,
|
||||
designedMinStep: 0.1,
|
||||
unit: "celsius"
|
||||
},{
|
||||
cType: types.TEMPERATURE_UNITS_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr","ev"],
|
||||
format: "int",
|
||||
initialValue: 0,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Unit"
|
||||
}]
|
||||
}];
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.accessory = HomeMaticThermo;
|
||||
123
accessories/HomeMaticWindow.js
Normal file
123
accessories/HomeMaticWindow.js
Normal file
@@ -0,0 +1,123 @@
|
||||
var types = require("HAP-NodeJS/accessories/types.js");
|
||||
var Characteristic = require("HAP-NodeJS").Characteristic;
|
||||
var request = require("request");
|
||||
|
||||
function HomeMaticWindow(log, config) {
|
||||
this.log = log;
|
||||
this.name = config["name"];
|
||||
this.ccuID = config["ccu_id"];
|
||||
this.ccuIP = config["ccu_ip"];
|
||||
}
|
||||
|
||||
HomeMaticWindow.prototype = {
|
||||
|
||||
|
||||
getPowerState: function(callback) {
|
||||
var that = this;
|
||||
|
||||
this.log("Getting Window State of CCU");
|
||||
request.get({
|
||||
url: "http://"+this.ccuIP+"/config/xmlapi/state.cgi?datapoint_id="+this.ccuID,
|
||||
}, function(err, response, body) {
|
||||
|
||||
if (!err && response.statusCode == 200) {
|
||||
|
||||
//that.log("Response:"+response.body);
|
||||
var responseString = response.body.substring(83,84);
|
||||
//that.log(responseString);
|
||||
switch(responseString){
|
||||
case "0": {callback(Characteristic.ContactSensorState.CONTACT_DETECTED);break;}
|
||||
case "1": {callback(Characteristic.ContactSensorState.CONTACT_NOT_DETECTED);break;}
|
||||
case "2": {callback(Characteristic.ContactSensorState.CONTACT_NOT_DETECTED);break;}
|
||||
}
|
||||
that.log("Getting Window State complete.");
|
||||
}
|
||||
else {
|
||||
that.log("Error '"+err+"' getting Window State: " + body);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getServices: function() {
|
||||
var that = this;
|
||||
return [{
|
||||
sType: types.ACCESSORY_INFORMATION_STYPE,
|
||||
characteristics: [{
|
||||
cType: types.NAME_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr"],
|
||||
format: "string",
|
||||
initialValue: this.name,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Name of the accessory",
|
||||
designedMaxLength: 255
|
||||
},{
|
||||
cType: types.MANUFACTURER_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr"],
|
||||
format: "string",
|
||||
initialValue: "Homematic",
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Manufacturer",
|
||||
designedMaxLength: 255
|
||||
},{
|
||||
cType: types.MODEL_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr"],
|
||||
format: "string",
|
||||
initialValue: "HM-Sec-RHS",
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Model",
|
||||
designedMaxLength: 255
|
||||
},{
|
||||
cType: types.SERIAL_NUMBER_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr"],
|
||||
format: "string",
|
||||
initialValue: "A1S2NASF88EW",
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "SN",
|
||||
designedMaxLength: 255
|
||||
},{
|
||||
cType: types.IDENTIFY_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pw"],
|
||||
format: "bool",
|
||||
initialValue: false,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Identify Accessory",
|
||||
designedMaxLength: 1
|
||||
}]
|
||||
},{
|
||||
sType: types.CONTACT_SENSOR_STYPE,
|
||||
characteristics: [{
|
||||
cType: types.NAME_CTYPE,
|
||||
onUpdate: null,
|
||||
perms: ["pr"],
|
||||
format: "string",
|
||||
initialValue: this.name,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Name of service",
|
||||
designedMaxLength: 255
|
||||
},{
|
||||
cType: types.CONTACT_SENSOR_STATE_CTYPE,
|
||||
onRead: function(callback) { that.getPowerState(callback); },
|
||||
perms: ["pr","ev"],
|
||||
format: "bool",
|
||||
initialValue: false,
|
||||
supportEvents: false,
|
||||
supportBonjour: false,
|
||||
manfDescription: "Get Window state of a Variable",
|
||||
designedMaxLength: 1
|
||||
}]
|
||||
}];
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.accessory = HomeMaticWindow;
|
||||
@@ -153,6 +153,24 @@
|
||||
"ccu_id": "The XMP-API id of your HomeMatic device",
|
||||
"ccu_ip": "The IP-Adress of your HomeMatic CCU device"
|
||||
},
|
||||
{
|
||||
"accessory": "HomeMaticWindow",
|
||||
"name": "Contact",
|
||||
"description": "Control HomeMatic devices (The XMP-API addon for the CCU is required)",
|
||||
"ccu_id": "The XMP-API id of your HomeMatic device (type HM-Sec-RHS)",
|
||||
"ccu_ip": "The IP-Adress of your HomeMatic CCU device"
|
||||
},
|
||||
{
|
||||
"accessory": "HomeMaticThermo",
|
||||
"name": "Contact",
|
||||
"description": "Control HomeMatic devices (The XMP-API addon for the CCU is required)",
|
||||
"ccu_id_TargetTemp": "The XMP-API id of your HomeMatic device (type HM-CC-RT-DN )",
|
||||
"ccu_id_CurrentTemp": "The XMP-API id of your HomeMatic device (type HM-CC-RT-DN )",
|
||||
"ccu_id_ControlMode": "The XMP-API id of your HomeMatic device (type HM-CC-RT-DN )",
|
||||
"ccu_id_ManuMode": "The XMP-API id of your HomeMatic device (type HM-CC-RT-DN )",
|
||||
"ccu_id_AutoMode": "The XMP-API id of your HomeMatic device (type HM-CC-RT-DN )",
|
||||
"ccu_ip": "The IP-Adress of your HomeMatic CCU device"
|
||||
},
|
||||
{
|
||||
"accessory": "X10",
|
||||
"name": "Lamp",
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
// - Added Battery support
|
||||
// - Added low battery support for all sensors
|
||||
// - Added HomeSeer event support (using HomeKit switches...)
|
||||
// V0.7 - Jean-Michel Joudrier (stipus at stipus dot com) - 2015/10/13
|
||||
// - You can add multiple HomeKit devices for the same HomeSeer device reference
|
||||
// - Added CarbonMonoxide sensor
|
||||
// - Added CarbonDioxide sensor
|
||||
// - Added onValues option to all binary sensors
|
||||
// V0.8 - Jean-Michel Joudrier (stipus at stipus dot com) - 2015/10/14
|
||||
// - Added uuid_base parameter to all accessories
|
||||
//
|
||||
//
|
||||
// Remember to add platform to config.json.
|
||||
@@ -35,7 +42,8 @@
|
||||
// {
|
||||
// "eventGroup":"My Group", // Required - The HomeSeer event group
|
||||
// "eventName":"My Event", // Required - The HomeSeer event name
|
||||
// "name":"Test" // Optional - HomeSeer event name is the default
|
||||
// "name":"Test", // Optional - HomeSeer event name is the default
|
||||
// "uuid_base":"SomeUniqueId" // Optional - HomeKit identifier will be derived from this parameter instead of the name
|
||||
// }
|
||||
// ],
|
||||
//
|
||||
@@ -46,7 +54,8 @@
|
||||
// "name":"My Light", // Optional - HomeSeer device name is the default
|
||||
// "offValue":"0", // Optional - 0 is the default
|
||||
// "onValue":"100", // Optional - 100 is the default
|
||||
// "can_dim":true // Optional - true is the default - false for a non dimmable lightbulb
|
||||
// "can_dim":true, // Optional - true is the default - false for a non dimmable lightbulb
|
||||
// "uuid_base":"SomeUniqueId2" // Optional - HomeKit identifier will be derived from this parameter instead of the name
|
||||
// },
|
||||
// {
|
||||
// "ref":9 // This is a dimmable Lightbulb by default
|
||||
@@ -64,6 +73,22 @@
|
||||
// "batteryThreshold":15 // Optional - If sensor battery level is below this value, the HomeKit LowBattery characteristic is set to 1. Default is 10
|
||||
// },
|
||||
// {
|
||||
// "ref":34, // Required - HomeSeer Device Reference for your sensor
|
||||
// "type":"SmokeSensor", // Required for a smoke sensor
|
||||
// "name":"Kichen smoke detector", // Optional - HomeSeer device name is the default
|
||||
// "batteryRef":35, // Optional - HomeSeer device reference for the sensor battery level
|
||||
// "batteryThreshold":15, // Optional - If sensor battery level is below this value, the HomeKit LowBattery characteristic is set to 1. Default is 10
|
||||
// "onValues":[1,1.255] // Optional - List of all HomeSeer values triggering a "ON" sensor state - Default is any value different than 0
|
||||
// },
|
||||
// {
|
||||
// "ref":34, // Required - HomeSeer Device Reference for your sensor (Here it's the same device as the SmokeSensor above)
|
||||
// "type":"CarbonMonoxideSensor", // Required for a carbon monoxide sensor
|
||||
// "name":"Kichen CO detector", // Optional - HomeSeer device name is the default
|
||||
// "batteryRef":35, // Optional - HomeSeer device reference for the sensor battery level
|
||||
// "batteryThreshold":15, // Optional - If sensor battery level is below this value, the HomeKit LowBattery characteristic is set to 1. Default is 10
|
||||
// "onValues":[2,2.255] // Optional - List of all HomeSeer values triggering a "ON" sensor state - Default is any value different than 0
|
||||
// },
|
||||
// {
|
||||
// "ref":113, // Required - HomeSeer Device Reference of the Current Temperature Device
|
||||
// "type":"Thermostat", // Required for a Thermostat
|
||||
// "name":"Température Salon", // Optional - HomeSeer device name is the default
|
||||
@@ -76,10 +101,10 @@
|
||||
// "stateCoolValues":[2], // Required - List of the HomeSeer device values for a HomeKit state=COOL
|
||||
// "stateAutoValues":[3], // Required - List of the HomeSeer device values for a HomeKit state=AUTO
|
||||
// "controlRef":168, // Required - HomeSeer device reference for your thermostat mode control (It can be the same as stateRef for some thermostats)
|
||||
// "controlOffValue":0, // Required - Value for OFF
|
||||
// "controlHeatValue":1, // Required - Value for HEAT
|
||||
// "controlCoolValue":2, // Required - Value for COOL
|
||||
// "controlAutoValue":3, // Required - Value for AUTO
|
||||
// "controlOffValue":0, // Required - HomeSeer device control value for OFF
|
||||
// "controlHeatValue":1, // Required - HomeSeer device control value for HEAT
|
||||
// "controlCoolValue":2, // Required - HomeSeer device control value for COOL
|
||||
// "controlAutoValue":3, // Required - HomeSeer device control value for AUTO
|
||||
// "coolingThresholdRef":169, // Optional - Not-implemented-yet - HomeSeer device reference for your thermostat cooling threshold
|
||||
// "heatingThresholdRef":170 // Optional - Not-implemented-yet - HomeSeer device reference for your thermostat heating threshold
|
||||
// },
|
||||
@@ -95,20 +120,22 @@
|
||||
//
|
||||
//
|
||||
// SUPORTED TYPES:
|
||||
// - Lightbulb (can_dim, onValue, offValue options)
|
||||
// - Fan (onValue, offValue options)
|
||||
// - Switch (onValue, offValue options)
|
||||
// - Outlet (onValue, offValue options)
|
||||
// - Thermostat (temperatureUnit, setPoint, state, control options)
|
||||
// - TemperatureSensor (temperatureUnit=C|F)
|
||||
// - ContactSensor (0=no contact, 1=contact - batteryRef, batteryThreshold option)
|
||||
// - MotionSensor (0=no motion, 1=motion - batteryRef, batteryThreshold option)
|
||||
// - LeakSensor (0=no leak, 1=leak - batteryRef, batteryThreshold option)
|
||||
// - LightSensor (HomeSeer device value in Lux - batteryRef, batteryThreshold option)
|
||||
// - HumiditySensor (HomeSeer device value in % - batteryRef, batteryThreshold option)
|
||||
// - OccupancySensor (0=no occupancy, 1=occupancy - batteryRef, batteryThreshold option)
|
||||
// - SmokeSensor (0=no smoke, 1=smoke - batteryRef, batteryThreshold option)
|
||||
// - Battery (batteryThreshold option)
|
||||
// - Lightbulb (can_dim, onValue, offValue options)
|
||||
// - Fan (onValue, offValue options)
|
||||
// - Switch (onValue, offValue options)
|
||||
// - Outlet (onValue, offValue options)
|
||||
// - Thermostat (temperatureUnit, setPoint, state, control options)
|
||||
// - TemperatureSensor (temperatureUnit=C|F)
|
||||
// - HumiditySensor (HomeSeer device value in % - batteryRef, batteryThreshold options)
|
||||
// - LightSensor (HomeSeer device value in Lux - batteryRef, batteryThreshold options)
|
||||
// - ContactSensor (onValues, batteryRef, batteryThreshold options)
|
||||
// - MotionSensor (onValues, batteryRef, batteryThreshold options)
|
||||
// - LeakSensor (onValues, batteryRef, batteryThreshold options)
|
||||
// - OccupancySensor (onValues, batteryRef, batteryThreshold options)
|
||||
// - SmokeSensor (onValues, batteryRef, batteryThreshold options)
|
||||
// - CarbonMonoxideSensor (onValues, batteryRef, batteryThreshold options)
|
||||
// - CarbonDioxideSensor (onValues, batteryRef, batteryThreshold options)
|
||||
// - Battery (batteryThreshold option)
|
||||
// - Door
|
||||
|
||||
|
||||
@@ -163,9 +190,14 @@ HomeSeerPlatform.prototype = {
|
||||
else {
|
||||
this.log('HomeSeer status function succeeded!');
|
||||
var response = JSON.parse( body );
|
||||
for( var i=0; i<response.Devices.length; i++ ) {
|
||||
var accessory = new HomeSeerAccessory( that.log, that.config, response.Devices[i] );
|
||||
foundAccessories.push( accessory );
|
||||
for( var i=0; i<this.config.accessories.length; i++ ) {
|
||||
for( var j=0; j<response.Devices.length; j++ ) {
|
||||
if( this.config.accessories[i].ref == response.Devices[j].ref ) {
|
||||
var accessory = new HomeSeerAccessory( that.log, that.config, this.config.accessories[i], response.Devices[j] );
|
||||
foundAccessories.push( accessory );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
callback( foundAccessories );
|
||||
}
|
||||
@@ -173,29 +205,25 @@ HomeSeerPlatform.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
function HomeSeerAccessory(log, platformConfig, status ) {
|
||||
function HomeSeerAccessory(log, platformConfig, accessoryConfig, status ) {
|
||||
this.log = log;
|
||||
this.config = accessoryConfig;
|
||||
this.ref = status.ref;
|
||||
this.name = status.name
|
||||
this.model = status.device_type_string;
|
||||
this.onValue = "100";
|
||||
this.offValue = "0";
|
||||
this.onValue = 100;
|
||||
this.offValue = 0;
|
||||
|
||||
this.access_url = platformConfig["host"] + "/JSON?";
|
||||
this.control_url = this.access_url + "request=controldevicebyvalue&ref=" + this.ref + "&value=";
|
||||
this.status_url = this.access_url + "request=getstatus&ref=" + this.ref;
|
||||
|
||||
for( var i=0; i<platformConfig.accessories.length; i++ ) {
|
||||
if( platformConfig.accessories[i].ref == this.ref )
|
||||
{
|
||||
this.config = platformConfig.accessories[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( this.config.name )
|
||||
this.name = this.config.name;
|
||||
|
||||
if( this.config.uuid_base )
|
||||
this.uuid_base = this.config.uuid_base;
|
||||
|
||||
if( this.config.onValue )
|
||||
this.onValue = this.config.onValue;
|
||||
|
||||
@@ -254,6 +282,35 @@ HomeSeerAccessory.prototype = {
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
getBinarySensorState: function(callback) {
|
||||
var url = this.status_url;
|
||||
|
||||
httpRequest(url, 'GET', function(error, response, body) {
|
||||
if (error) {
|
||||
this.log('HomeSeer get binary sensor state function failed: %s', error.message);
|
||||
callback( error, 0 );
|
||||
}
|
||||
else {
|
||||
var status = JSON.parse( body );
|
||||
var value = status.Devices[0].value;
|
||||
|
||||
this.log('HomeSeer get binary sensor state function succeeded: value=' + value );
|
||||
if( this.config.onValues ) {
|
||||
if( this.config.onValues.indexOf(value) != -1 )
|
||||
callback( null, 1 );
|
||||
else
|
||||
callback( null, 0 );
|
||||
}
|
||||
else {
|
||||
if( value != 0 )
|
||||
callback( null, 1 );
|
||||
else
|
||||
callback( null, 0 );
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
||||
setValue: function(level, callback) {
|
||||
var url = this.control_url + level;
|
||||
@@ -534,11 +591,37 @@ HomeSeerAccessory.prototype = {
|
||||
services.push( temperatureSensorService );
|
||||
break;
|
||||
}
|
||||
case "CarbonMonoxideSensor": {
|
||||
var carbonMonoxideSensorService = new Service.CarbonMonoxideSensor();
|
||||
carbonMonoxideSensorService
|
||||
.getCharacteristic(Characteristic.CarbonMonoxideDetected)
|
||||
.on('get', this.getBinarySensorState.bind(this));
|
||||
if( this.config.batteryRef ) {
|
||||
carbonMonoxideSensorService
|
||||
.addCharacteristic(new Characteristic.StatusLowBattery())
|
||||
.on('get', this.getLowBatteryStatus.bind(this));
|
||||
}
|
||||
services.push( carbonMonoxideSensorService );
|
||||
break;
|
||||
}
|
||||
case "CarbonDioxideSensor": {
|
||||
var carbonDioxideSensorService = new Service.CarbonDioxideSensor();
|
||||
carbonDioxideSensorService
|
||||
.getCharacteristic(Characteristic.CarbonDioxideDetected)
|
||||
.on('get', this.getBinarySensorState.bind(this));
|
||||
if( this.config.batteryRef ) {
|
||||
carbonDioxideSensorService
|
||||
.addCharacteristic(new Characteristic.StatusLowBattery())
|
||||
.on('get', this.getLowBatteryStatus.bind(this));
|
||||
}
|
||||
services.push( carbonDioxideSensorService );
|
||||
break;
|
||||
}
|
||||
case "ContactSensor": {
|
||||
var contactSensorService = new Service.ContactSensor();
|
||||
contactSensorService
|
||||
.getCharacteristic(Characteristic.ContactSensorState)
|
||||
.on('get', this.getPowerState.bind(this));
|
||||
.on('get', this.getBinarySensorState.bind(this));
|
||||
if( this.config.batteryRef ) {
|
||||
contactSensorService
|
||||
.addCharacteristic(new Characteristic.StatusLowBattery())
|
||||
@@ -551,7 +634,7 @@ HomeSeerAccessory.prototype = {
|
||||
var motionSensorService = new Service.MotionSensor();
|
||||
motionSensorService
|
||||
.getCharacteristic(Characteristic.MotionDetected)
|
||||
.on('get', this.getPowerState.bind(this));
|
||||
.on('get', this.getBinarySensorState.bind(this));
|
||||
if( this.config.batteryRef ) {
|
||||
motionSensorService
|
||||
.addCharacteristic(new Characteristic.StatusLowBattery())
|
||||
@@ -564,7 +647,7 @@ HomeSeerAccessory.prototype = {
|
||||
var leakSensorService = new Service.LeakSensor();
|
||||
leakSensorService
|
||||
.getCharacteristic(Characteristic.LeakDetected)
|
||||
.on('get', this.getPowerState.bind(this));
|
||||
.on('get', this.getBinarySensorState.bind(this));
|
||||
if( this.config.batteryRef ) {
|
||||
leakSensorService
|
||||
.addCharacteristic(new Characteristic.StatusLowBattery())
|
||||
@@ -573,6 +656,32 @@ HomeSeerAccessory.prototype = {
|
||||
services.push( leakSensorService );
|
||||
break;
|
||||
}
|
||||
case "OccupancySensor": {
|
||||
var occupancySensorService = new Service.OccupancySensor();
|
||||
occupancySensorService
|
||||
.getCharacteristic(Characteristic.OccupancyDetected)
|
||||
.on('get', this.getBinarySensorState.bind(this));
|
||||
if( this.config.batteryRef ) {
|
||||
occupancySensorService
|
||||
.addCharacteristic(new Characteristic.StatusLowBattery())
|
||||
.on('get', this.getLowBatteryStatus.bind(this));
|
||||
}
|
||||
services.push( occupancySensorService );
|
||||
break;
|
||||
}
|
||||
case "SmokeSensor": {
|
||||
var smokeSensorService = new Service.SmokeSensor();
|
||||
smokeSensorService
|
||||
.getCharacteristic(Characteristic.SmokeDetected)
|
||||
.on('get', this.getBinarySensorState.bind(this));
|
||||
if( this.config.batteryRef ) {
|
||||
temperatureSensorService
|
||||
.addCharacteristic(new Characteristic.StatusLowBattery())
|
||||
.on('get', this.getLowBatteryStatus.bind(this));
|
||||
}
|
||||
services.push( smokeSensorService );
|
||||
break;
|
||||
}
|
||||
case "LightSensor": {
|
||||
var lightSensorService = new Service.LightSensor();
|
||||
lightSensorService
|
||||
@@ -599,32 +708,6 @@ HomeSeerAccessory.prototype = {
|
||||
services.push( humiditySensorService );
|
||||
break;
|
||||
}
|
||||
case "OccupancySensor": {
|
||||
var occupancySensorService = new Service.OccupancySensor();
|
||||
occupancySensorService
|
||||
.getCharacteristic(Characteristic.OccupancyDetected)
|
||||
.on('get', this.getPowerState.bind(this));
|
||||
if( this.config.batteryRef ) {
|
||||
occupancySensorService
|
||||
.addCharacteristic(new Characteristic.StatusLowBattery())
|
||||
.on('get', this.getLowBatteryStatus.bind(this));
|
||||
}
|
||||
services.push( occupancySensorService );
|
||||
break;
|
||||
}
|
||||
case "SmokeSensor": {
|
||||
var smokeSensorService = new Service.SmokeSensor();
|
||||
smokeSensorService
|
||||
.getCharacteristic(Characteristic.SmokeDetected)
|
||||
.on('get', this.getPowerState.bind(this));
|
||||
if( this.config.batteryRef ) {
|
||||
temperatureSensorService
|
||||
.addCharacteristic(new Characteristic.StatusLowBattery())
|
||||
.on('get', this.getLowBatteryStatus.bind(this));
|
||||
}
|
||||
services.push( smokeSensorService );
|
||||
break;
|
||||
}
|
||||
case "Door": {
|
||||
var doorService = new Service.Door();
|
||||
doorService
|
||||
@@ -708,6 +791,9 @@ function HomeSeerEvent(log, platformConfig, eventConfig ) {
|
||||
|
||||
if( this.config.name )
|
||||
this.name = this.config.name;
|
||||
|
||||
if( this.config.uuid_base )
|
||||
this.uuid_base = this.config.uuid_base;
|
||||
}
|
||||
|
||||
HomeSeerEvent.prototype = {
|
||||
|
||||
@@ -131,8 +131,11 @@ ZWayServerPlatform.prototype = {
|
||||
gdid = vdev.id.replace(/^(.*?)_zway_(\d+-\d+)-\d.*/, '$1_$2');
|
||||
}
|
||||
|
||||
var gd = groupedDevices[gdid] || (groupedDevices[gdid] = {devices: [], types: {}, extras: {}, primary: undefined});
|
||||
var gd = groupedDevices[gdid] || (groupedDevices[gdid] = { devices: [], types: {}, extras: {}, primary: undefined, cxmap: {} });
|
||||
|
||||
gd.devices.push(vdev);
|
||||
var vdevIndex = gd.devices.length - 1;
|
||||
|
||||
var tk = ZWayServerPlatform.getVDevTypeKey(vdev);
|
||||
|
||||
// If this is explicitly set as primary, set it now...
|
||||
@@ -143,17 +146,24 @@ ZWayServerPlatform.prototype = {
|
||||
gd.extras[tk].push(gd.types[tk]);
|
||||
delete gd.types[tk]; // clear the way for this one to be set here below...
|
||||
}
|
||||
gd.primary = gd.devices.length - 1;
|
||||
gd.primary = vdevIndex;
|
||||
//gd.types[tk] = gd.primary;
|
||||
}
|
||||
|
||||
if(gd.types[tk] === undefined){
|
||||
gd.types[tk] = gd.devices.length - 1;
|
||||
gd.types[tk] = vdevIndex;
|
||||
} else {
|
||||
gd.extras[tk] = gd.extras[tk] || [];
|
||||
gd.extras[tk].push(gd.devices.length - 1);
|
||||
gd.extras[tk].push(vdevIndex);
|
||||
}
|
||||
if(tk !== vdev.deviceType) gd.types[vdev.deviceType] = vdevIndex; // also include the deviceType only as a possibility
|
||||
|
||||
// Create a map entry when Homebridge.Characteristic.Type is set...
|
||||
var ctype = this.getTagValue(vdev, "Characteristic.Type");
|
||||
if(ctype && Characteristic[ctype]){
|
||||
var cx = new Characteristic[ctype]();
|
||||
gd.cxmap[cx.UUID] = vdevIndex;
|
||||
}
|
||||
if(tk !== vdev.deviceType) gd.types[vdev.deviceType] = gd.devices.length - 1; // also include the deviceType only as a possibility
|
||||
}
|
||||
|
||||
for(var gdid in groupedDevices) {
|
||||
@@ -357,6 +367,11 @@ ZWayServerAccessory.prototype = {
|
||||
case "sensorMultilevel.Luminiscence":
|
||||
services.push(new Service.LightSensor(vdev.metrics.title, vdev.id));
|
||||
break;
|
||||
case "sensorBinary":
|
||||
var stype = this.platform.getTagValue(vdev, "Service.Type");
|
||||
if(stype === "MotionSensor"){
|
||||
services.push(new Service.MotionSensor(vdev.metrics.title, vdev.id));
|
||||
}
|
||||
}
|
||||
|
||||
var validServices =[];
|
||||
@@ -377,6 +392,12 @@ ZWayServerAccessory.prototype = {
|
||||
}
|
||||
,
|
||||
getVDevForCharacteristic: function(cx, vdevPreferred){
|
||||
|
||||
// If we know which vdev should be used for this Characteristic, we're done!
|
||||
if(this.devDesc.cxmap[cx.UUID] !== undefined){
|
||||
return this.devDesc.devices[this.devDesc.cxmap[cx.UUID]];
|
||||
}
|
||||
|
||||
var map = this.uuidToTypeKeyMap;
|
||||
if(!map){
|
||||
this.uuidToTypeKeyMap = map = {};
|
||||
@@ -399,7 +420,7 @@ ZWayServerAccessory.prototype = {
|
||||
}
|
||||
|
||||
if(cx instanceof Characteristic.Name) return vdevPreferred;
|
||||
|
||||
|
||||
// Special case!: If cx is a CurrentTemperature, ignore the preferred device...we want the sensor if available!
|
||||
if(cx instanceof Characteristic.CurrentTemperature) vdevPreferred = null;
|
||||
//
|
||||
@@ -438,7 +459,6 @@ ZWayServerAccessory.prototype = {
|
||||
debug("Getting value for " + vdev.metrics.title + ", characteristic \"" + cx.displayName + "\"...");
|
||||
callback(false, accessory.name);
|
||||
});
|
||||
cx.writable = false;
|
||||
return cx;
|
||||
}
|
||||
|
||||
@@ -525,12 +545,6 @@ ZWayServerAccessory.prototype = {
|
||||
});
|
||||
}.bind(this));
|
||||
|
||||
cx.writeable = false;
|
||||
//cx.on('set', function(level, callback){
|
||||
// this.command(vdev, "exact", {level: "on", "color.r": 255, "color.g": 0, "color.b": 0}).then(function(result){
|
||||
// callback();
|
||||
// });
|
||||
//}.bind(this));
|
||||
return cx;
|
||||
}
|
||||
|
||||
@@ -560,12 +574,6 @@ ZWayServerAccessory.prototype = {
|
||||
});
|
||||
}.bind(this));
|
||||
|
||||
cx.writeable = false;
|
||||
//cx.on('set', function(level, callback){
|
||||
// this.command(vdev, "exact", {level: "on", "color.r": 255, "color.g": 0, "color.b": 0}).then(function(result){
|
||||
// callback();
|
||||
// });
|
||||
//}.bind(this));
|
||||
return cx;
|
||||
}
|
||||
|
||||
@@ -581,8 +589,10 @@ ZWayServerAccessory.prototype = {
|
||||
callback(false, cx.zway_getValueFromVDev(result.data));
|
||||
});
|
||||
}.bind(this));
|
||||
cx.minimumValue = vdev.metrics && vdev.metrics.min !== undefined ? vdev.metrics.min : -40;
|
||||
cx.maximumValue = vdev.metrics && vdev.metrics.max !== undefined ? vdev.metrics.max : 999;
|
||||
cx.setProps({
|
||||
minValue: vdev.metrics && vdev.metrics.min !== undefined ? vdev.metrics.min : -40,
|
||||
maxValue: vdev.metrics && vdev.metrics.max !== undefined ? vdev.metrics.max : 999
|
||||
});
|
||||
return cx;
|
||||
}
|
||||
|
||||
@@ -604,8 +614,10 @@ ZWayServerAccessory.prototype = {
|
||||
callback();
|
||||
});
|
||||
}.bind(this));
|
||||
cx.minimumValue = vdev.metrics && vdev.metrics.min !== undefined ? vdev.metrics.min : 5;
|
||||
cx.maximumValue = vdev.metrics && vdev.metrics.max !== undefined ? vdev.metrics.max : 40;
|
||||
cx.setProps({
|
||||
minValue: vdev.metrics && vdev.metrics.min !== undefined ? vdev.metrics.min : 5,
|
||||
maxValue: vdev.metrics && vdev.metrics.max !== undefined ? vdev.metrics.max : 40
|
||||
});
|
||||
return cx;
|
||||
}
|
||||
|
||||
@@ -619,7 +631,9 @@ ZWayServerAccessory.prototype = {
|
||||
debug("Getting value for " + vdev.metrics.title + ", characteristic \"" + cx.displayName + "\"...");
|
||||
callback(false, Characteristic.TemperatureDisplayUnits.CELSIUS);
|
||||
});
|
||||
cx.writable = false;
|
||||
cx.setProps({
|
||||
perms: [Characteristic.Perms.READ]
|
||||
});
|
||||
return cx;
|
||||
}
|
||||
|
||||
@@ -647,7 +661,6 @@ ZWayServerAccessory.prototype = {
|
||||
callback(false, Characteristic.TargetHeatingCoolingState.HEAT);
|
||||
});
|
||||
// Hmm... apparently if this is not setable, we can't add a thermostat change to a scene. So, make it writable but a no-op.
|
||||
cx.writable = true;
|
||||
cx.on('set', function(newValue, callback){
|
||||
debug("WARN: Set of TargetHeatingCoolingState not yet implemented, resetting to HEAT!")
|
||||
callback(undefined, Characteristic.TargetHeatingCoolingState.HEAT);
|
||||
@@ -682,8 +695,9 @@ ZWayServerAccessory.prototype = {
|
||||
debug("Getting value for " + vdev.metrics.title + ", characteristic \"" + cx.displayName + "\"...");
|
||||
callback(false, Characteristic.TargetDoorState.CLOSED);
|
||||
});
|
||||
//cx.readable = false;
|
||||
cx.writable = false;
|
||||
cx.setProps({
|
||||
perms: [Characteristic.Perms.READ]
|
||||
});
|
||||
}
|
||||
|
||||
if(cx instanceof Characteristic.ObstructionDetected){
|
||||
@@ -696,8 +710,6 @@ ZWayServerAccessory.prototype = {
|
||||
debug("Getting value for " + vdev.metrics.title + ", characteristic \"" + cx.displayName + "\"...");
|
||||
callback(false, false);
|
||||
});
|
||||
//cx.readable = false;
|
||||
cx.writable = false;
|
||||
}
|
||||
|
||||
if(cx instanceof Characteristic.BatteryLevel){
|
||||
@@ -738,8 +750,6 @@ ZWayServerAccessory.prototype = {
|
||||
debug("Getting value for " + vdev.metrics.title + ", characteristic \"" + cx.displayName + "\"...");
|
||||
callback(false, Characteristic.ChargingState.NOT_CHARGING);
|
||||
});
|
||||
//cx.readable = false;
|
||||
cx.writable = false;
|
||||
}
|
||||
|
||||
if(cx instanceof Characteristic.CurrentAmbientLightLevel){
|
||||
@@ -748,8 +758,8 @@ ZWayServerAccessory.prototype = {
|
||||
// Completely unscientific guess, based on test-fit data and Wikipedia real-world lux values.
|
||||
// This will probably change!
|
||||
var lux = 0.0005 * (vdev.metrics.level^3.6);
|
||||
if(lux < cx.minimumValue) return cx.minimumValue;
|
||||
if(lux > cx.maximumValue) return cx.maximumValue;
|
||||
// Bounds checking now done upstream!
|
||||
//if(lux < cx.minimumValue) return cx.minimumValue; if(lux > cx.maximumValue) return cx.maximumValue;
|
||||
return lux;
|
||||
} else {
|
||||
return vdev.metrics.level;
|
||||
@@ -768,6 +778,43 @@ ZWayServerAccessory.prototype = {
|
||||
});
|
||||
return cx;
|
||||
}
|
||||
|
||||
if(cx instanceof Characteristic.MotionDetected){
|
||||
cx.zway_getValueFromVDev = function(vdev){
|
||||
return vdev.metrics.level === "off" ? false : true;
|
||||
};
|
||||
cx.value = cx.zway_getValueFromVDev(vdev);
|
||||
cx.on('get', function(callback, context){
|
||||
debug("Getting value for " + vdev.metrics.title + ", characteristic \"" + cx.displayName + "\"...");
|
||||
this.getVDev(vdev).then(function(result){
|
||||
debug("Got value: " + cx.zway_getValueFromVDev(result.data) + ", for " + vdev.metrics.title + ".");
|
||||
callback(false, cx.zway_getValueFromVDev(result.data));
|
||||
});
|
||||
}.bind(this));
|
||||
cx.on('change', function(ev){
|
||||
debug("Device " + vdev.metrics.title + ", characteristic " + cx.displayName + " changed from " + ev.oldValue + " to " + ev.newValue);
|
||||
});
|
||||
return cx;
|
||||
}
|
||||
|
||||
if(cx instanceof Characteristic.StatusTampered){
|
||||
cx.zway_getValueFromVDev = function(vdev){
|
||||
return vdev.metrics.level === "off" ? Characteristic.StatusTampered.NOT_TAMPERED : Characteristic.StatusTampered.TAMPERED;
|
||||
};
|
||||
cx.value = cx.zway_getValueFromVDev(vdev);
|
||||
cx.on('get', function(callback, context){
|
||||
debug("Getting value for " + vdev.metrics.title + ", characteristic \"" + cx.displayName + "\"...");
|
||||
this.getVDev(vdev).then(function(result){
|
||||
debug("Got value: " + cx.zway_getValueFromVDev(result.data) + ", for " + vdev.metrics.title + ".");
|
||||
callback(false, cx.zway_getValueFromVDev(result.data));
|
||||
});
|
||||
}.bind(this));
|
||||
cx.on('change', function(ev){
|
||||
debug("Device " + vdev.metrics.title + ", characteristic " + cx.displayName + " changed from " + ev.oldValue + " to " + ev.newValue);
|
||||
});
|
||||
return cx;
|
||||
}
|
||||
|
||||
}
|
||||
,
|
||||
configureService: function(service, vdev){
|
||||
|
||||
Reference in New Issue
Block a user