homebridge-miot
Version:
Homebridge plugin for devices supporting the miot protocol
1,152 lines (908 loc) • 28.8 kB
JavaScript
const AbstractDevice = require('./AbstractDevice.js');
const MiotDevice = require('../protocol/MiotDevice.js');
const MiotProperty = require('../protocol/MiotProperty.js');
const Constants = require('../constants/Constants.js');
const Events = require('../constants/Events.js');
const DevTypes = require('../constants/DevTypes.js');
const PropFormat = require('../constants/PropFormat.js');
const PropUnit = require('../constants/PropUnit.js');
const PropAccess = require('../constants/PropAccess.js');
// DEVICES: http://miot-spec.org/miot-spec-v2/instances?status=released
class BaseDevice extends AbstractDevice {
constructor(miotDevice, name, logger) {
if (new.target === BaseDevice) {
throw new Error("Cannot instantiate BaseDevice directly!")
}
super(miotDevice, name, logger);
}
/*----------========== INIT ==========----------*/
initialPropertyFetchDone() {
// log the the use time when supported
if (this.supportsUseTimeReporting()) {
this.logger.info(`Use time: ${this.getUseTime()} minutes.`);
}
}
/*----------========== DEVICE INFO ==========----------*/
/*----------========== INFO ==========----------*/
/*----------========== CONFIG ==========----------*/
commonProperties() {
return ['physical-controls-locked:physical-controls-locked', 'alarm:alarm', 'indicator-light:on', 'indicator-light:brightness',
'indicator-light:indicator-light', 'screen:on', 'screen:brightness', 'environment:temperature',
'environment:relative-humidity', 'environment:pm2.5-density', 'environment:pm10-density', 'environment:air-quality',
'environment:tvoc-density', 'environment:co2-density', 'environment:hcho-density', 'battery:battery-level',
'battery:charging-state', 'filter:filter-left-time', 'filter:filter-used-time', 'filter:filter-life-level',
'use-time:use-time'
];
}
/*----------========== VALUES ==========----------*/
statusChargingValue() {
return this.getValueForStatus('Charging');
}
statusIdleValue() {
return this.getValueForStatus('Idle');
}
statusBusyValue() {
return this.getValueForStatus('Busy');
}
chargingStateChargingValue() {
return this.getValueForChargingState('Charging');
}
chargingStateNotChargingValue() {
return this.getValueForChargingState('Not Charging');
}
chargingStateNotChargeableValue() {
return this.getValueForChargingState('Not Chargeable');
}
chargingStateGoChargingValue() {
return this.getValueForChargingState('Go Charging');
}
/*----------========== PROPERTIES ==========----------*/
onProp() {
return this.getPropFromMainService('on');
}
statusProp() {
return this.getPropFromMainService('status');
}
faultProp() {
return this.getPropFromMainService('fault');
}
modeProp() {
return this.getPropFromMainService('mode');
}
physicalControlsLockedProp() {
return this.getProperty('physical-controls-locked:physical-controls-locked');
}
alarmProp() {
return this.getProperty('alarm:alarm');
}
indicatorLightOnProp() {
return this.getProperty('indicator-light:on');
}
indicatorLightBrightnessProp() {
return this.getProperty('indicator-light:brightness');
}
indicatorLightIndicatorLightProp() {
return this.getProperty('indicator-light:indicator-light');
}
screenOnProp() {
return this.getProperty('screen:on');
}
screenBrightnessProp() {
return this.getProperty('screen:brightness');
}
offDelayProp() {
return this.getProperty('fan:off-delay');
}
speedLevelProp() {
return this.getProperty('custom-service:speed-level');
}
fanLevelProp() {
return this.getProperty('fan:fan-level');
}
anionProp() {
return this.getProperty('fan:anion');
}
brightnessProp() {
return this.getProperty('light:brightness');
}
colorTemperatureProp() {
return this.getProperty('light:color-temperature');
}
colorProp() {
return this.getProperty('light:color');
}
targetTemperatureProp() {
return this.getPropFromMainService('target-temperature');
}
temperatureProp() {
return this.getProperty('environment:temperature') || this.getPropFromMainService('temperature');
}
relativeHumidityProp() {
return this.getProperty('environment:relative-humidity') || this.getPropFromMainService('relative-humidity');
}
illuminationProp() {
return this.getPropFromMainService('illumination');
}
pm25DensityProp() {
return this.getProperty('environment:pm2.5-density');
}
pm10DensityProp() {
return this.getProperty('environment:pm10-density');
}
airQualityProp() {
return this.getProperty('environment:air-quality');
}
tvocDensityProp() {
return this.getProperty('environment:tvoc-density');
}
co2DensityProp() {
return this.getProperty('environment:co2-density');
}
hchoDensityProp() {
return this.getProperty('environment:hcho-density');
}
batteryLevelProp() {
return this.getProperty('battery:battery-level');
}
chargingStateProp() {
return this.getProperty('battery:charging-state');
}
filterLeftTimeProp() {
return this.getProperty('filter:filter-left-time');
}
filterUsedTimeProp() {
return this.getProperty('filter:filter-used-time');
}
filterLifeLevelProp() {
return this.getProperty('filter:filter-life-level');
}
acStateProp() {
return this.getProperty('custom-service:ac-state');
}
batteryStateProp() {
return this.getProperty('custom-service:battery-state');
}
useTimeProp() {
return this.getProperty('use-time:use-time');
}
speedNowProp() {
return null;
}
actaulSpeedProp() {
return this.getProperty('other:actual-speed');
}
/*----------========== ACTIONS ==========----------*/
resetFilterLifeAction() {
this.getAction('filter:reset-filter-life');
}
/*----------========== SERVICES ==========----------*/
getLightService() {
return this.getServiceByType('light');
}
getAmbientLightService() {
return this.getServiceByType('ambient-light');
}
/*----------========== FEATURES ==========----------*/
// on
supportsOn() {
return !!this.onProp();
}
// status
supportsStatusReporting() {
return !!this.statusProp();
}
// fault
supportsFaultReporting() {
return !!this.faultProp();
}
// modes
supportsModes() {
return !!this.modeProp();
}
//physical controls locked
supportsChildLock() {
return !!this.physicalControlsLockedProp();
}
// off delay
supportsOffDelay() {
return !!this.offDelayProp();
}
// alarm
supportsBuzzerControl() {
return !!this.alarmProp();
}
// indicator light - on
supportsIndicatorLightOnControl() {
return !!this.indicatorLightOnProp();
}
// indicator light - brightness
supportsIndicatorLightBrightnessControl() {
return !!this.indicatorLightBrightnessProp();
}
// indicator light - indicator light
supportsIndicatorLightIndicatorLightControl() {
return !!this.indicatorLightIndicatorLightProp();
}
// screen - on
supportsScreenOnControl() {
return !!this.screenOnProp();
}
// screen - brightness
supportsScreenBrightnessControl() {
return !!this.screenBrightnessProp();
}
//speed level
supportsSpeedLevel() {
return !!this.speedLevelProp();
}
isSpeeLeveldRpm() {
let range = this.getPropertyValueRange(this.speedLevelProp());
let isRpm = false;
if (range && range.length > 2) {
let rangeDif = range[1] - range[0];
if (rangeDif > 200) {
isRpm = true;
}
}
return isRpm || this.getPropertyUnit(this.speedLevelProp()) === PropUnit.RPM;
}
// rotation speed
supportsRotationSpeed() {
return this.supportsSpeedLevel() || this.supportsFanLevel();
}
// fan levels
supportsFanLevel() {
return !!this.fanLevelProp();
}
fanLevelsList() {
return this.getPropertyValueList(this.fanLevelProp());
}
supportsFanLevelList() {
return this.fanLevelsList().length > 2;
}
fanLevelRange() {
return this.getPropertyValueRange(this.fanLevelProp());
}
supportsFanLevelRange() {
return this.fanLevelRange().length > 2;
}
// ioniser
supportsIoniser() {
return !!this.anionProp();
}
// brightness
supportsBrightness() {
return !!this.brightnessProp();
}
// color temperature
supportsColorTemperature() {
return !!this.colorTemperatureProp();
}
// color
supportsColor() {
return !!this.colorProp();
}
// target temperature
supportsTargetTemperature() {
return !!this.targetTemperatureProp();
}
targetTemperatureRange() {
let range = this.getPropertyValueRange(this.targetTemperatureProp());
return (range.length > 2) ? range : [10, 35, 1];
}
// temperature
supportsTemperatureReporting() {
return !!this.temperatureProp();
}
// relative humidity
supportsRelativeHumidityReporting() {
return !!this.relativeHumidityProp();
}
// illumination
supportsIlluminationReporting() {
return !!this.illuminationProp();
}
// pm2.5 density
supportsPm25DensityReporting() {
return !!this.pm25DensityProp();
}
// pm10 density
supportsPm10DensityReporting() {
return !!this.pm10DensityProp();
}
//air quality
supportsAirQualityReporting() {
return !!this.airQualityProp();
}
//tvoc density
supportsTvocDensityReporting() {
return !!this.tvocDensityProp();
}
tvocDensityUnit() {
return this.supportsTvocDensityReporting() ? this.getPropertyUnit(this.tvocDensityProp()) : PropUnit.UGM3;
}
tvocDensityRange() {
let range = this.getPropertyValueRange(this.tvocDensityProp());
return (range.length > 2) ? this.convertToHomekitTvocRange(range, this.tvocDensityUnit()) : [0, 1000, 1];
}
//co2 density
supportsCo2DensityReporting() {
return !!this.co2DensityProp();
}
//hcho density
supportsHchoDensityReporting() {
return !!this.hchoDensityProp();
}
hchoDensityUnit() {
return this.supportsHchoDensityReporting() ? this.getPropertyUnit(this.hchoDensityProp()) : PropUnit.UGM3;
}
hchoDensityRange() {
let range = this.getPropertyValueRange(this.hchoDensityProp());
return (range.length > 2) ? this.convertToHomekitTvocRange(range, this.hchoDensityUnit()) : [0, 1000, 1];
}
// battery
supportsBatteryLevelReporting() {
return !!this.batteryLevelProp();
}
//charging state
supportsChargingStateReporting() {
return !!this.chargingStateProp();
}
// filter
supportsFilterLeftTimeReporting() {
return !!this.filterLeftTimeProp();
}
supportsFilterUsedTimeReporting() {
return !!this.filterUsedTimeProp();
}
supportsFilterLifeLevelReporting() {
return !!this.filterLifeLevelProp();
}
supportsFilterLifeResetAction() {
return !!this.resetFilterLifeAction();
}
//ac power
supportsAcStateReporting() {
return !!this.acStateProp();
}
// bvattery state
supportsBatteryStateReporting() {
return !!this.batteryStateProp();
}
//charging
supportsStatusCharging() {
return this.supportsStatusReporting() && this.statusChargingValue() !== -1;
}
supportsChargingReporting() {
return this.supportsChargingStateReporting() || this.supportsStatusCharging() || this.supportsBatteryStateReporting() || this.supportsAcStateReporting();
}
// use time
supportsUseTimeReporting() {
return !!this.useTimeProp();
}
useTimeUnit() {
return this.supportsUseTimeReporting() ? this.getPropertyUnit(this.useTimeProp()) : PropUnit.MINUTES;
}
//speed now reporting
supportsSpeedNowReporting() {
return !!this.speedNowProp();
}
// actual speed reporting
supportsActualSpeedReporting() {
return !!this.actaulSpeedProp();
}
// light service
hasLightService() {
return !!this.getLightService();
}
// ambient light service
hasAmbientLightService() {
return !!this.getAmbientLightService();
}
/*----------========== GETTERS ==========----------*/
isOn() {
return this.getPropertyValue(this.onProp());
}
getStatus() {
return this.getPropertyValue(this.statusProp());
}
getFault() {
return this.getPropertyValue(this.faultProp());
}
getMode() {
return this.getPropertyValue(this.modeProp());
}
isChildLockActive() {
return this.getPropertyValue(this.physicalControlsLockedProp());
}
isBuzzerEnabled() {
return this.getPropertyValue(this.alarmProp());
}
isIndicatorLightOn() {
return this.getPropertyValue(this.indicatorLightOnProp());
}
getIndicatorLightBrightness() {
return this.getPropertyValue(this.indicatorLightBrightnessProp());
}
getIndicatorLightIndicatorLight() {
return this.getPropertyValue(this.indicatorLightIndicatorLightProp());
}
isScreenOn() {
return this.getPropertyValue(this.screenOnProp());
}
getScreenBrightness() {
return this.getPropertyValue(this.screenBrightnessProp());
}
getOffDelay() {
return this.getPropertyValue(this.offDelayProp());
}
getSpeedLevel() {
return this.getPropertyValue(this.speedLevelProp());
}
getFanLevel() {
return this.getPropertyValue(this.fanLevelProp());
}
isIoniserEnabled() {
return this.getPropertyValue(this.anionProp());
}
getBrightness() {
return this.getPropertyValue(this.brightnessProp());
}
getColorTemperature() {
return this.getPropertyValue(this.colorTemperatureProp());
}
getColor() {
return this.getPropertyValue(this.colorProp());
}
getTargetTemperature() {
return this.getPropertyValue(this.targetTemperatureProp());
}
getTemperature() {
return this.getPropertyValue(this.temperatureProp());
}
getRelativeHumidity() {
return this.getPropertyValue(this.relativeHumidityProp());
}
getIllumination() {
return this.getPropertyValue(this.illuminationProp());
}
getPm25Density() {
return this.getPropertyValue(this.pm25DensityProp());
}
getPm10Density() {
return this.getPropertyValue(this.pm10DensityProp());
}
getAirQuality() {
return this.getPropertyValue(this.airQualityProp());
}
getTvocDensity() {
let tvoc = this.getPropertyValue(this.tvocDensityProp());
tvoc = this.convertToHomekitTvoc(tvoc, this.tvocDensityUnit());
return tvoc;
}
getCo2Density() {
return this.getPropertyValue(this.co2DensityProp());
}
getHchoDensity() {
let hcho = this.getPropertyValue(this.hchoDensityProp());
hcho = this.convertToHomekitTvoc(hcho, this.hchoDensityUnit());
return hcho;
}
getBatteryLevel() {
return this.getPropertyValue(this.batteryLevelProp());
}
getChargingState() {
return this.getPropertyValue(this.chargingStateProp());
}
getFilterLeftTime() {
return this.getPropertyValue(this.filterLeftTimeProp());
}
getFilterUsedTime() {
return this.getPropertyValue(this.filterUsedTimeProp());
}
getFilterLifeLevel() {
return this.getPropertyValue(this.filterLifeLevelProp());
}
isOnAcPower() {
return this.getPropertyValue(this.acStateProp());
}
isOnBatteryPower() {
return this.getPropertyValue(this.batteryStateProp());
}
getUseTime() {
let useTime = this.getPropertyValue(this.useTimeProp());
useTime = this.convertToMinutes(useTime, this.useTimeUnit());
return useTime;
}
getSpeedNow() {
return this.getPropertyValue(this.speedNowProp());
}
getActualSpeed() {
return this.getPropertyValue(this.actaulSpeedProp());
}
/*----------========== SETTERS ==========----------*/
async setOn(isOn) {
return this.setPropertyValue(this.onProp(), isOn);
}
async setMode(mode) {
return this.setPropertyValue(this.modeProp(), mode);
}
async setChildLock(active) {
return this.setPropertyValue(this.physicalControlsLockedProp(), active);
}
async setBuzzerEnabled(enabled) {
return this.setPropertyValue(this.alarmProp(), enabled);
}
async setIndicatorLightOn(value) {
return this.setPropertyValue(this.indicatorLightOnProp(), value);
}
async setIndicatorLightBrightness(value) {
return this.setPropertyValue(this.indicatorLightBrightnessProp(), value);
}
async setIndicatorLightIndicatorLight(value) {
return this.setPropertyValue(this.indicatorLightIndicatorLightProp(), value);
}
async setScreenOn(value) {
return this.setPropertyValue(this.screenOnProp(), value);
}
async setScreenBrightness(value) {
return this.setPropertyValue(this.screenBrightnessProp(), value);
}
async setOffDelay(value) {
return this.setPropertyValue(this.offDelayProp(), value);
}
async setSpeedLevel(speed) {
return this.setPropertyValue(this.speedLevelProp(), speed);
}
async setFanLevel(level) {
return this.setPropertyValue(this.fanLevelProp(), level);
}
async setIoniserEnabled(enabled) {
return this.setPropertyValue(this.anionProp(), enabled);
}
async setBrightness(value) {
return this.setPropertyValue(this.brightnessProp(), value);
}
async setColorTemperature(value) {
return this.setPropertyValue(this.colorTemperatureProp(), value);
}
async setColor(value) {
return this.setPropertyValue(this.colorProp(), value);
}
async setTargetTemperature(value) {
return this.setPropertyValue(this.targetTemperatureProp(), value);
}
/*----------========== CONVENIENCE ==========----------*/
isDeviceOn() {
return this.isOn();
}
isDeviceCharging() {
if (this.supportsChargingStateReporting()) {
return this.isChargingStateCharging();
} else if (this.supportsStatusCharging()) {
return this.isStatusCharging();
} else if (this.supportsBatteryStateReporting()) {
return !this.isOnBatteryPower();
} else if (this.supportsAcStateReporting()) {
return this.isOnAcPower();
}
return false;
}
// rotation speed
getRotationSpeedPercentage() {
if (this.supportsSpeedLevel()) {
if (this.isSpeeLeveldRpm()) {
return this.convertPropValueToPercentage(this.speedLevelProp());
} else {
return this.getSpeedLevel();
}
} else if (this.supportsFanLevel()) {
return this.convertFanLevelToRotationSpeed();
}
return 0;
}
async setRotationSpeedPercentage(percentage) {
if (this.supportsSpeedLevel()) {
let fanSpeedToSet = percentage;
if (this.isSpeeLeveldRpm()) {
fanSpeedToSet = this.convertPercentageToPropValue(percentage, this.speedLevelProp())
}
this.setSpeedLevel(fanSpeedToSet);
} else if (this.supportsFanLevel()) {
let levelToSet = this.convertRotationSpeedToFanLevel(percentage);
this.setFanLevel(levelToSet);
}
}
// set on
turnOnIfNecessary() {
// if the device is turned off then turn it on
if (this.isOn() === false) {
this.setOn(true);
}
}
// filter
resetFilterLife() {
return this.fireAction(this.resetFilterLifeAction());
}
//target temp
getTargetTemperatureSafe() {
return Math.max(this.targetTemperatureRange()[0], this.getTargetTemperature());
}
// VOCDensity sensor
supportsVOCDenstiy() {
return this.supportsTvocDensityReporting() || this.supportsHchoDensityReporting();
}
getVOCDenstiyRange() {
if (this.supportsTvocDensityReporting()) {
return this.tvocDensityRange();
} else if (this.supportsHchoDensityReporting()) {
return this.hchoDensityRange();
}
return [0, 1000, 1];
}
getVOCDenstiyValue() {
if (this.supportsTvocDensityReporting()) {
return this.getTvocDensity();
} else if (this.supportsHchoDensityReporting()) {
return this.getHchoDensity();
}
return 0;
}
/*----------========== VALUE CONVENIENCE ==========----------*/
isStatusCharging() {
return this.getStatus() === this.statusChargingValue();
}
isStatusIdle() {
return this.getStatus() === this.statusIdleValue();
}
isStatusBusy() {
return this.getStatus() === this.statusBusyValue();
}
isChargingStateCharging() {
return this.getChargingState() === this.chargingStateChargingValue();
}
isChargingStateNotCharging() {
return this.getChargingState() === this.chargingStateNotChargingValue();
}
isChargingStateNotChargeable() {
return this.getChargingState() === this.chargingStateNotChargeableValue();
}
isChargingStateGoCharging() {
return this.getChargingState() === this.chargingStateGoChargingValue();
}
/*----------========== PROPERTY MONITORING ==========----------*/
monitorTemperatureProp() {
this.addPropertyToMonitor(this.temperatureProp());
}
monitorRelativeHumidityProp() {
this.addPropertyToMonitor(this.relativeHumidityProp());
}
monitorIlluminationProp() {
this.addPropertyToMonitor(this.illuminationProp());
}
/*----------========== HELPERS ==========----------*/
getActionFriendlyName(miotAction) {
let action = this.getAction(miotAction);
if (action) {
return action.getName().split(':')[1].split('-').map((item) => {
return item.charAt(0).toUpperCase() + item.substring(1);
}).join(' ');
}
return miotAction;
}
getPropertyFriendlyName(miotProp) {
let prop = this.getProperty(miotProp);
if (prop) {
let itemArr = prop.getName().split(':').map((item) => {
return item.charAt(0).toUpperCase().slice(0, 6) + item.substring(1);
})
// if service name longer then 6 chars then just return the property name since the overall name might be too long
if (itemArr[0].length > 6) {
return itemArr[1];
}
return itemArr.join(' - ');
}
return miotProp;
}
// time
convertToMinutes(value, unit) {
if (unit === PropUnit.HOURS) {
value = value * 60;
} else if (unit === PropUnit.SECONDS) {
value = Math.ceil(value / 60);
}
return value;
}
convertMinutesToUnit(minutes, unit) {
let converted = minutes;
if (unit === PropUnit.SECONDS) {
converted = minutes * 60;
} else if (unit === PropUnit.HOURS) {
converted = Math.ceil(minutes / 60);
}
return converted;
}
// fan speed
convertRotationSpeedToFanLevel(fanSpeed) {
let level = 0;
if (this.supportsFanLevelList()) {
let numberOfFanLevels = this.fanLevelsList().length;
let firstValue = this.fanLevelsList()[0].value;
let lastValue = this.fanLevelsList()[numberOfFanLevels - 1].value;
let speedPerLevel = 100 / numberOfFanLevels;
level = firstValue + Math.floor(fanSpeed / speedPerLevel); // round down
if (level > lastValue) level = lastValue; // make sure we stay in range
} else if (this.supportsFanLevelRange()) {
let minLevel = this.fanLevelRange()[0];
let maxLevel = this.fanLevelRange()[1];
let numberOfFanLevels = (maxLevel - minLevel) + 1;
let speedPerLevel = 100 / numberOfFanLevels;
level = minLevel + Math.floor(fanSpeed / speedPerLevel); // round down
if (level > maxLevel) level = maxLevel; // make sure we stay in range
}
return level;
}
convertFanLevelToRotationSpeed() {
let fanSpeed = 0;
if (this.supportsFanLevelList()) {
let numberOfFanLevels = this.fanLevelsList().length;
let speedPerLevel = 100 / numberOfFanLevels;
fanSpeed = Math.round(speedPerLevel * this.getFanLevel());
} else if (this.supportsFanLevelRange()) {
let minLevel = this.fanLevelRange()[0];
let maxLevel = this.fanLevelRange()[1];
let numberOfFanLevels = (maxLevel - minLevel) + 1;
let speedPerLevel = 100 / numberOfFanLevels;
fanSpeed = Math.round(speedPerLevel * this.getFanLevel());
}
if (fanSpeed > 100) fanSpeed = 100; // make sure we stay in range
return fanSpeed;
}
convertPropValueToPercentage(prop) {
if (prop && prop.hasValueRange()) {
let propValue = prop.getSafeValue();
let propValRange = prop.getValueRange();
let from = propValRange[0];
let to = propValRange[1];
let valuePercentage = (((propValue - from) * 100) / (to - from));
return Math.round(valuePercentage);
}
return null;
}
convertPercentageToPropValue(percentage, prop) {
if (prop && prop.hasValueRange()) {
let propValRange = prop.getValueRange();
let from = propValRange[0];
let to = propValRange[1];
let value = (percentage * (to - from) / 100) + from;
return Math.round(value);
}
return percentage;
}
//convert tvoc to µg/m3 (homekit)
convertToHomekitTvoc(value, unit) {
if (unit === PropUnit.MGM3) {
value = value * 1000;
}
return value;
}
convertToHomekitTvocRange(range, unit) {
if (unit === PropUnit.MGM3) {
range = range.map(val => val * 1000);
}
return range;
}
//prop value extractor
getValueForStatus(statusDesc, getAll = false) {
if (statusDesc && this.supportsStatusReporting()) {
if (getAll) {
return this._getAllValuesForDescription(this.statusProp(), statusDesc); // sometimes there are multiple values with exact same description, in that case if desired get all of them
} else {
return this._getValueForDescription(this.statusProp(), statusDesc); // get only the first found value
}
}
return -1;
}
getValueForMode(modeDesc) {
if (modeDesc && this.supportsModes()) {
return this._getValueForDescription(this.modeProp(), modeDesc);
}
return -1;
}
getValueForChargingState(chargingStateDesc) {
if (chargingStateDesc && this.supportsChargingStateReporting()) {
return this._getValueForDescription(this.chargingStateProp(), chargingStateDesc);
}
return -1;
}
getValueForFault(faultDesc) {
if (faultDesc && this.supportsFaultReporting()) {
return this._getValueForDescription(this.faultProp(), faultDesc);
}
return -1;
}
//prop value checker
statusContainsOrEqualsValue(value) {
if (this.supportsStatusReporting()) {
return this._checkPropValueContainsOrEqualsValue(this.statusProp(), value);
}
return false;
}
//retrieve a property from main service
getPropFromMainService(propType) {
if (!this.mainServicePropCache) {
this.mainServicePropCache = {}; // init the main service prop cache, saves properties which has been automatically discovered for reuse, stores also not found ones as "null" (key without value)
}
if (propType in this.mainServicePropCache) {
return this.mainServicePropCache[propType];
}
const mainService = this.getMainService();
let foundProp = null;
if (mainService) {
foundProp = mainService.getPropertyByType(propType);
}
this.mainServicePropCache[propType] = foundProp; // store even not found properties so we do not have to search again
return foundProp;
}
/*----------========== PRIVATE STUFF ==========----------*/
_getValueForDescription(prop, desc) {
if (desc && prop) {
const valList = this.getPropertyValueList(prop);
if (valList) {
let foundObj = valList.find(item => this._areDescriptionsEqual(item.description, desc));
if (foundObj) {
return foundObj.value;
}
}
}
return -1;
}
_getAllValuesForDescription(prop, desc) {
if (desc && prop) {
const valList = this.getPropertyValueList(prop);
if (valList) {
let foundObjs = valList.filter(item => this._areDescriptionsEqual(item.description, desc));
if (foundObjs && foundObjs.length > 0) {
if (foundObjs.length > 1) {
return foundObjs.map((item) => item.value);
} else {
return foundObjs[0].value;
}
}
}
}
return -1;
}
_areDescriptionsEqual(desc1, desc2) {
if (desc1 && desc2) {
if (Array.isArray(desc2)) {
let foundDesc = desc2.find(tmpDesc => this._normalizedEqualCompare(desc1, tmpDesc));
if (foundDesc) {
return true;
}
} else {
return this._normalizedEqualCompare(desc1, desc2);
}
}
return false;
}
_normalizedEqualCompare(text1, text2) {
if (text1 && text2) {
const normalizedText1 = text1.replace(/\s+/g, '').toLowerCase();
const normalizedText2 = text2.replace(/\s+/g, '').toLowerCase();
if (normalizedText1 === normalizedText2) {
return true;
}
}
return false;
}
_checkPropValueContainsOrEqualsValue(prop, value) {
let propVal = this.getPropertyValue(prop);
if (value != null && propVal != null && Array.isArray(value)) {
return value.includes(propVal);
} else {
return propVal === value;
}
}
}
module.exports = BaseDevice;