homebridge-homeassistant-mbmccormick
Version:
Homebridge plugin for Home Assistant: https://home-assistant.io
244 lines (232 loc) • 8.56 kB
JavaScript
;
let Service;
let Characteristic;
let communicationError;
function toTitleCase(str) {
return str.replace(/\w\S*/g, txt => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
}
class HomeAssistantBinarySensor {
constructor(log, data, client, service, characteristic, onValue, offValue, firmware) {
// device info
this.data = data;
this.entity_id = data.entity_id;
this.uuid_base = data.entity_id;
this.firmware = firmware;
if (data.attributes && data.attributes.friendly_name) {
this.name = data.attributes.friendly_name;
} else {
this.name = data.entity_id.split('.').pop().replace(/_/g, ' ');
}
if (data.attributes && data.attributes.homebridge_manufacturer) {
this.manufacturer = String(data.attributes.homebridge_manufacturer);
} else {
this.manufacturer = 'Home Assistant';
}
if (data.attributes && data.attributes.homebridge_model) {
this.model = String(data.attributes.homebridge_model);
} else {
this.model = `${toTitleCase(data.attributes.device_class)} Binary Sensor`;
}
if (data.attributes && data.attributes.homebridge_serial) {
this.serial = String(data.attributes.homebridge_serial);
} else {
this.serial = data.entity_id;
}
this.entity_type = data.entity_id.split('.')[0];
this.client = client;
this.log = log;
this.service = service;
this.characteristic = characteristic;
this.onValue = onValue;
this.offValue = offValue;
this.batterySource = data.attributes.homebridge_battery_source;
this.chargingSource = data.attributes.homebridge_charging_source;
}
onEvent(oldState, newState) {
if (newState.state) {
this.sensorService.getCharacteristic(this.characteristic)
.setValue(newState.state === 'on' ? this.onValue : this.offValue, null, 'internal');
}
}
identify(callback) {
this.log(`identifying: ${this.name}`);
callback();
}
getState(callback) {
this.log(`fetching state for: ${this.name}`);
this.client.fetchState(this.entity_id, (data) => {
if (data) {
callback(null, data.state === 'on' ? this.onValue : this.offValue);
} else {
callback(communicationError);
}
});
}
getBatteryLevel(callback) {
this.client.fetchState(this.batterySource, (data) => {
if (data) {
callback(null, parseFloat(data.state));
} else {
callback(communicationError);
}
});
}
getChargingState(callback) {
if (this.batterySource && this.chargingSource) {
this.client.fetchState(this.chargingSource, (data) => {
if (data) {
callback(null, data.state.toLowerCase() === 'charging' ? 1 : 0);
} else {
callback(communicationError);
}
});
} else {
callback(null, 2);
}
}
getLowBatteryStatus(callback) {
this.client.fetchState(this.batterySource, (data) => {
if (data) {
callback(null, parseFloat(data.state) > 20 ? 0 : 1);
} else {
callback(communicationError);
}
});
}
getServices() {
this.sensorService = new this.service(); // eslint-disable-line new-cap
this.sensorService
.getCharacteristic(this.characteristic)
.on('get', this.getState.bind(this));
const informationService = new Service.AccessoryInformation();
informationService
.setCharacteristic(Characteristic.Manufacturer, this.manufacturer)
.setCharacteristic(Characteristic.Model, this.model)
.setCharacteristic(Characteristic.SerialNumber, this.serial)
.setCharacteristic(Characteristic.FirmwareRevision, this.firmware);
if (this.batterySource) {
this.batteryService = new Service.BatteryService();
this.batteryService
.getCharacteristic(Characteristic.BatteryLevel)
.setProps({ maxValue: 100, minValue: 0, minStep: 1 })
.on('get', this.getBatteryLevel.bind(this));
this.batteryService
.getCharacteristic(Characteristic.ChargingState)
.setProps({ maxValue: 2 })
.on('get', this.getChargingState.bind(this));
this.batteryService
.getCharacteristic(Characteristic.StatusLowBattery)
.on('get', this.getLowBatteryStatus.bind(this));
return [informationService, this.batteryService, this.sensorService];
}
return [informationService, this.sensorService];
}
}
function HomeAssistantBinarySensorFactory(log, data, client, firmware) {
if (!(data.attributes && data.attributes.device_class)) {
return null;
}
switch (data.attributes.device_class) {
case 'door':
case 'garage_door':
case 'opening':
case 'window':
return new HomeAssistantBinarySensor(
log, data, client,
Service.ContactSensor,
Characteristic.ContactSensorState,
Characteristic.ContactSensorState.CONTACT_NOT_DETECTED,
Characteristic.ContactSensorState.CONTACT_DETECTED,
firmware
);
case 'gas':
if (!(data.attributes.homebridge_gas_type)) {
return new HomeAssistantBinarySensor(
log, data, client,
Service.CarbonMonoxideSensor,
Characteristic.CarbonMonoxideDetected,
Characteristic.LeakDetected.CO_LEVELS_ABNORMAL,
Characteristic.LeakDetected.CO_LEVELS_NORMAL,
firmware
);
}
switch (data.attributes.homebridge_gas_type) {
case 'co2':
return new HomeAssistantBinarySensor(
log, data, client,
Service.CarbonDioxideSensor,
Characteristic.CarbonDioxideDetected,
Characteristic.LeakDetected.CO2_LEVELS_ABNORMAL,
Characteristic.LeakDetected.CO2_LEVELS_NORMAL,
firmware
);
case 'co':
return new HomeAssistantBinarySensor(
log, data, client,
Service.CarbonMonoxideSensor,
Characteristic.CarbonMonoxideDetected,
Characteristic.LeakDetected.CO_LEVELS_ABNORMAL,
Characteristic.LeakDetected.CO_LEVELS_NORMAL,
firmware
);
default:
return new HomeAssistantBinarySensor(
log, data, client,
Service.CarbonMonoxideSensor,
Characteristic.CarbonMonoxideDetected,
Characteristic.LeakDetected.CO_LEVELS_ABNORMAL,
Characteristic.LeakDetected.CO_LEVELS_NORMAL,
firmware
);
}
case 'moisture':
return new HomeAssistantBinarySensor(
log, data, client,
Service.LeakSensor,
Characteristic.LeakDetected,
Characteristic.LeakDetected.LEAK_DETECTED,
Characteristic.LeakDetected.LEAK_NOT_DETECTED,
firmware
);
case 'motion':
return new HomeAssistantBinarySensor(
log, data, client,
Service.MotionSensor,
Characteristic.MotionDetected,
true,
false,
firmware
);
case 'occupancy':
return new HomeAssistantBinarySensor(
log, data, client,
Service.OccupancySensor,
Characteristic.OccupancyDetected,
Characteristic.OccupancyDetected.OCCUPANCY_DETECTED,
Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED,
firmware
);
case 'smoke':
return new HomeAssistantBinarySensor(
log, data, client,
Service.SmokeSensor,
Characteristic.SmokeDetected,
Characteristic.SmokeDetected.SMOKE_DETECTED,
Characteristic.SmokeDetected.SMOKE_NOT_DETECTED,
firmware
);
default:
log.error(`'${data.entity_id}' has a device_class of '${data.attributes.device_class}' which is not supported by ` +
'homebridge-homeassistant. Supported classes are \'gas\', \'moisture\', \'motion\', \'occupancy\', \'opening\' and \'smoke\'. ' +
'See the README.md for more information.');
return null;
}
}
function HomeAssistantBinarySensorPlatform(oService, oCharacteristic, oCommunicationError) {
Service = oService;
Characteristic = oCharacteristic;
communicationError = oCommunicationError;
return HomeAssistantBinarySensorFactory;
}
module.exports = HomeAssistantBinarySensorPlatform;
module.exports.HomeAssistantBinarySensorFactory = HomeAssistantBinarySensorFactory;