homebridge-rituals-patch
Version:
Rituals plugin for homebridge: https://github.com/nfarina/homebridge
440 lines (410 loc) • 18.6 kB
JavaScript
'use strict';
const os = require('os');
const path = require('path');
const store = require('node-storage');
const reqson = require('request-json');
const version = require('./package.json').version;
const author = require('./package.json').author.name;
let Service;
let Characteristic;
module.exports = function(homebridge) {
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
homebridge.registerAccessory(
'homebridge-rituals',
'Rituals',
RitualsAccessory
);
};
function RitualsAccessory(log, config) {
//logger = log;
this.log = log;
this.services = [];
this.hub = config.hub || '';
var dt = Math.floor(Math.random() * 10000) + 1;
this.log.debug('RitualsAccesory -> init :: RitualsAccessory(log, config)');
this.storage = new store(
path.join(os.homedir(), '.homebridge') + '/.uix-rituals-secrets_' + this.hub
);
this.user =
path.join(os.homedir(), '.homebridge') +
'/.uix-rituals-secrets_' +
this.hub;
this.log.debug('RitualsAccesory -> storage path is :: ' + this.user);
this.on_state;
this.fan_speed;
this.account = config.account;
this.password = config.password;
this.geniVersion = config.geniVersion;
this.key = this.storage.get('key') || 0;
this.log.debug('RitualsAccesory -> key :: ' + this.key);
this.name = this.storage.get('name') || config.name || 'Genie';
this.log.debug('RitualsAccesory -> name :: ' + this.name);
this.hublot = this.storage.get('hublot') || 'SN_RND' + dt;
this.log.debug('RitualsAccesory -> hublot :: ' + this.hublot);
this.version = this.storage.get('version') || version;
this.log.debug('RitualsAccesory -> version :: ' + this.version);
this.fragance = this.storage.get('fragance') || 'N/A';
this.log.debug('RitualsAccesory -> fragance :: ' + this.fragance);
// var determinate_model = this.version.split('.');
// if (determinate_model[determinate_model.length - 1] < 12) {
// this.model_version = '1.0';
// } else {
// this.model_version = '2.0';
// }
this.service = new Service.Fan(this.name, 'AirFresher');
this.service
.getCharacteristic(Characteristic.On)
.on('get', this.getCurrentState.bind(this))
.on('set', this.setActiveState.bind(this));
this.service
.getCharacteristic(Characteristic.RotationSpeed)
.setProps({
minValue: 1,
maxValue: 3,
})
.on('get', (callback) => callback(null, this.fan_speed))
.on('set', this.setFanSpeed.bind(this));
this.serviceInfo = new Service.AccessoryInformation();
this.serviceInfo
.setCharacteristic(Characteristic.Manufacturer, author)
.setCharacteristic(
Characteristic.Model,
'Rituals Genie ' + this.model_version
)
.setCharacteristic(Characteristic.SerialNumber, this.hublot)
.setCharacteristic(Characteristic.FirmwareRevision, this.version);
if (this.model_version == 1.0) {
this.serviceBatt = new Service.BatteryService('Battery', 'AirFresher');
this.serviceBatt
.setCharacteristic(Characteristic.BatteryLevel, '100')
.setCharacteristic(
Characteristic.ChargingState,
Characteristic.ChargingState.CHARGING
)
.setCharacteristic(
Characteristic.StatusLowBattery,
Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
)
.setCharacteristic(Characteristic.Name, 'Genie Battery');
}
this.serviceFilter = new Service.FilterMaintenance('Filter', 'AirFresher');
this.serviceFilter
.setCharacteristic(
Characteristic.FilterChangeIndication,
Characteristic.FilterChangeIndication.FILTER_OK
)
.setCharacteristic(Characteristic.Name, this.fragance);
//ChargingState.NOT_CHARGING (0)
//ChargingState.CHARGING (1)
//ChargingState.NOT_CHARGAEABLE (2)
//StatusLowBattery.BATTERY_LEVEL_NORMAL (0)
//StatusLowBattery.BATTERY_LEVEL_LOW (1)
this.services.push(this.service);
this.services.push(this.serviceInfo);
this.services.push(this.serviceBatt);
this.services.push(this.serviceFilter);
this.discover();
this.log.debug('RitualsAccesory -> finish :: RitualsAccessory(log, config)');
}
RitualsAccessory.prototype = {
discover: function() {
this.log.debug('RitualsAccesory -> init :: discover: function ()');
this.log.debug('RitualsAccesory -> package :: ' + version);
this.storage.put('hub', this.hub);
var hash = this.storage.get('hash') || null;
var hb = this.storage.get('hub') || null;
if (hash) {
this.log.debug('RitualsAccesory -> hash found in local storage');
this.log.debug('RitualsAccesory -> HASH :: ' + hash);
if (hb) {
this.log.debug('RitualsAccesory -> hub found in local storage');
this.log.debug('RitualsAccesory -> HUB :: ' + hb);
} else {
this.getHub();
}
} else {
this.getHash();
}
this.log.debug('RitualsAccesory -> finish :: discover: function ()');
},
getHash: function() {
const that = this;
this.log.debug('RitualsAccesory -> init :: getHash: function()');
var client = reqson.createClient('https://rituals.sense-company.com/');
var data = { email: this.account, password: this.password };
client.post('ocapi/login', data, function(err, res, body) {
if (err) {
that.log.info(
that.name + ' :: ERROR :: ocapi/login :: getHash() > ' + err
);
}
if (!err && res.statusCode != 200) {
that.log.debug(
'RitualsAccesory -> ajax :: ocapi/login -> INVALID STATUS CODE :: ' +
res.statusCode
);
} else {
that.log.debug(
'RitualsAccesory -> ajax :: ocapi/login :: OK ' + res.statusCode
);
that.log.debug(
'RitualsAccesory -> ajax :: ocapi/login :: RESPONSE :: ' + body
);
that.storage.put('hash', body.account_hash);
that.log.debug(
'RitualsAccesory -> ajax :: ocapi/login :: Setting hash in storage :: ' +
body.account_hash
);
that.getHub();
}
});
this.log.debug('RitualsAccesory -> finish :: getHash: function()');
},
getHub: function() {
const that = this;
this.log.debug('RitualsAccesory -> init :: getHub: function()');
var client = reqson.createClient('https://rituals.sense-company.com/');
client.get('api/account/hubs/' + that.storage.get('hash'), function(
err,
res,
body
) {
if (err) {
that.log.info(
that.name + ' :: ERROR :: api/account/hubs :: getHub() > ' + err
);
that.log.info('That means GENIE servers are down!');
} else {
if (!err && res.statusCode != 200) {
that.log.debug(
'RitualsAccesory -> ajax :: api/account/hubs/ -> INVALID STATUS CODE :: ' +
res.statusCode
);
} else {
that.log.debug(
'RitualsAccesory -> ajax :: api/account/hubs/ OK :: ' +
res.statusCode
);
that.log.debug(
'RitualsAccesory -> ajax :: api/account/hubs/ BODY.LENGTH :: ' +
body.length +
' Genie in your account'
);
if (body.length == 1) {
that.key = 0;
that.name = body[that.key].hub.attributes.roomnamec;
that.hublot = body[that.key].hub.hublot;
that.hub = body[that.key].hub.hash;
that.storage.put('key', that.key);
that.storage.put('name', body[that.key].hub.attributes.roomnamec);
that.storage.put('hublot', body[that.key].hub.hublot);
that.storage.put('hub', body[that.key].hub.hash);
that.storage.put(
'fragance',
body[that.key].hub.sensors.rfidc.title
);
that.log.debug('RitualsAccesory -> hub 1 genie updated');
} else {
var found = false;
Object.keys(body).forEach(function(key) {
if (body[key].hub.hash == that.hub) {
that.log.debug(
'RitualsAccesory -> ajax :: api/account/hubs/ :: HUB declared in config VALIDATED OK '
);
found = true;
that.key = key;
that.log.debug(
'RitualsAccesory -> ajax :: api/account/hubs/ :: HUB Key is :: ' +
key
);
that.name = body[key].hub.attributes.roomnamec;
that.log.debug(
'RitualsAccesory -> ajax :: api/account/hubs/ :: HUB Name :: ' +
body[key].hub.attributes.roomnamec
);
that.hublot = body[key].hub.hublot;
that.log.debug(
'RitualsAccesory -> ajax :: api/account/hubs/ :: HUB Hublot :: ' +
body[key].hub.hublot
);
that.fragance = body[that.key].hub.sensors.rfidc.title;
that.log.debug(
'RitualsAccesory -> ajax :: api/account/hubs/ :: SENSORS Fragance :: ' +
body[that.key].hub.sensors.rfidc.title
);
that.storage.put('key', key);
that.storage.put('name', body[key].hub.attributes.roomnamec);
that.storage.put('hublot', body[key].hub.hublot);
that.storage.put(
'fragance',
body[that.key].hub.sensors.rfidc.title
);
that.log.debug(
'RitualsAccesory -> ajax :: api/account/hubs/ :: Saved HUB preferences in Storage'
);
}
});
if (!found) {
that.log.info('************************************************');
that.log.info('HUB in Config NOT validated! or NOT in Config');
that.log.info('please declare a correct section in config.json');
that.log.info('************************************************');
that.log.info('There are multiple Genies found on your account');
that.log.info(
'The HUB Key to identify Genie in your config.json is invalid, select the proper HUB key.'
);
that.log.info(
'Put one of the following your config.json > https://github.com/myluna08/homebridge-rituals'
);
Object.keys(body).forEach(function(key) {
that.log.info('********************');
that.log.info('Name : ' + body[key].hub.attributes.roomnamec);
that.log.info('Hublot : ' + body[key].hub.hublot);
that.log.info('Hub : ' + body[key].hub.hash);
that.log.info('Key : ' + key);
});
that.log.info('************************************************');
}
}
}
}
});
this.log.debug('RitualsAccesory -> finish :: getHub: function()');
},
getCurrentState: function(callback) {
const that = this;
this.log.debug(
'RitualsAccesory -> init :: getCurrentState: function(callback)'
);
var client = reqson.createClient('https://rituals.sense-company.com/');
client.get('api/account/hub/' + that.storage.get('hub'), function(
err,
res,
body
) {
if (err) {
that.log.info(
that.name +
' :: ERROR :: api/account/hubs :: getCurrentState() > ' +
err
);
that.log.info('That means GENIE servers are down!');
}
if (!err && res.statusCode != 200) {
that.log.debug(
'RitualsAccesory -> ajax :: getCurrentState :: api/account/hubs/ -> INVALID STATUS CODE :: ' +
res.statusCode
);
that.log.info(
that.name + ' getCurrentState => ' + res.statusCode + ' :: ' + err
);
} else {
that.log.debug(
'RitualsAccesory -> ajax :: getCurrentState :: api/account/hubs/ OK :: ' +
res.statusCode
);
that.key = that.storage.get('key');
that.on_state =
body.hub.attributes.fanc == '0' ? false : true;
that.fan_speed = body.hub.attributes.speedc;
that.storage.put('version', body.hub.sensors.versionc);
}
callback(null, that.on_state);
});
this.log.debug(
'RitualsAccesory -> finish :: getCurrentState: function(callback)'
);
},
setActiveState: function(active, callback) {
const that = this;
this.log.debug(
'RitualsAccesory -> init :: setActiveState: function(active, callback)'
);
this.log.debug('RitualsAccesory -> setActiveState to ' + active);
this.log.info(that.name + ' :: Set ActiveState to => ' + active);
var setValue = active == true ? '1' : '0';
var client = reqson.createClient('https://rituals.sense-company.com/');
var data = { hub: that.hub, json: { attr: { fanc: setValue } } };
client.post('api/hub/update/attr', data, function(err, res, body) {
if (err) {
that.log.info(
that.name +
' :: ERROR :: api/account/hubs :: setActiveState() > ' +
err
);
callback(undefined, that.on_state);
} else {
if (!err && res.statusCode != 200) {
that.log.debug(
'RitualsAccesory -> ajax :: setActiveState :: api/hub/update/attr/ -> INVALID STATUS CODE :: ' +
res.statusCode
);
that.log.info(
that.name + ' :: setActiveState => ' + res.statusCode + ' :: ' + err
);
callback(undefined, that.on_state);
} else {
that.log.debug(
'RitualsAccesory -> ajax :: setActiveState :: api/hub/update/attr/ OK :: ' +
res.statusCode
);
that.log.debug(
'RitualsAccesory -> ajax :: setActiveState :: api/hub/update/attr/ BODY :: ' +
body
);
callback(undefined, active);
}
}
});
this.log.debug(
'RitualsAccesory -> finish :: setActiveState: function(active, callback)'
);
},
setFanSpeed: function(value, callback) {
const that = this;
this.log.debug(
'RitualsAccesory -> init :: setFanSpeed: function(value, callback)'
);
this.log.info(that.name + ' :: Set FanSpeed to => ' + value);
var client = reqson.createClient('https://rituals.sense-company.com/');
var data = { hub: that.hub, json: { attr: { speedc: value.toString() } } };
client.post('api/hub/update/attr', data, function(err, res, body) {
if (err) {
that.log.info(
that.name + ' :: ERROR :: api/account/hubs :: setFanSpeed() > ' + err
);
callback(undefined, that.fan_speed);
}
if (!err && res.statusCode != 200) {
that.log.debug(
'RitualsAccesory -> ajax :: setFanSpeed :: api/hub/update/attr/ -> INVALID STATUS CODE :: ' +
res.statusCode
);
that.log.info(
that.name + ' :: setFanSpeed => ' + res.statusCode + ' :: ' + err
);
callback(undefined, that.fan_speed);
} else {
that.log.debug(
'RitualsAccesory -> ajax :: setFanSpeed :: api/hub/update/attr/ OK :: ' +
res.statusCode
);
that.log.debug(
'RitualsAccesory -> ajax :: setFanSpeed :: api/hub/update/attr/ BODY :: ' +
body
);
callback(undefined, value);
}
});
this.log.debug(
'RitualsAccesory -> finish :: setFanSpeed: function(value, callback)'
);
},
identify: function(callback) {
callback();
},
getServices: function() {
return this.services;
},
};