UNPKG

@shadman-a/homebridge-my-ac

Version:

A Homebridge plugin for controlling/monitoring LG ThinQ devices via LG ThinQ platform.

1,010 lines (1,009 loc) 92 kB
/** * Special thank to carlosgamezvillegas (https://github.com/carlosgamezvillegas) for the initial work on the Oven device. */ import { BaseDevice } from '../baseDevice.js'; import { normalizeBoolean, normalizeNumber } from '../helper.js'; var OvenState; (function (OvenState) { OvenState["INITIAL"] = "@OV_STATE_INITIAL_W"; OvenState["PREHEATING"] = "@OV_STATE_PREHEAT_W"; OvenState["COOKING_IN_PROGRESS"] = "@OV_STATE_COOK_W"; OvenState["DONE"] = "@OV_STATE_COOK_COMPLETE_W"; OvenState["COOLING"] = "@OV_TERM_COOLING_W"; OvenState["CLEANING"] = "@OV_STATE_CLEAN_W"; OvenState["CLEANING_DONE"] = "@OV_STATE_CLEAN_COMPLETE_W"; })(OvenState || (OvenState = {})); /* enum OvenMode { NONE = '@NONE', BAKE = '@OV_TERM_BAKE_W', ROAST = '@OV_TERM_ROAST_W', CONVECTION_BAKE = '@OV_TERM_CONV_BAKE_W', CONVECTION_ROAST = '@OV_TERM_CONV_ROAST_W', CRISP_CONVECTION = '@OV_TERM_CRISP_CONV_W', FAVORITE = '@OV_TERM_COOKMODE_FAVORITE_W', BROIL = '@OV_TERM_BROIL_W', WARM = '@OV_TERM_WARM_W', PROOF = '@OV_TERM_PROOF_W', FROZEN_MEAL = '@OV_TERM_FROZEN_MEAL_W', SLOW_COOK = '@OV_TERM_SLOW_COOK_W', PROBE_SET = '@OV_TERM_PROBE_SET_W', EASY_CLEAN = '@OV_TERM_EASY_CLEAN_W', SPEED_BROIL = '@OV_TERM_SPEED_BROIL_W', SELF_CLEAN = '@OV_TERM_SELF_CLEAN_W', SPEED_ROAST = '@OV_TERM_SPEED_ROAST_W', AIR_FRY = '@OV_TERM_AIR_FRY_W', PIZZA = '@OV_TERM_PIZZA_W', AIR_SOUSVIDE = '@OV_TERM_AIR_SOUSVIDE_W', } */ export default class Oven extends BaseDevice { platform; accessory; inputNameStatus = 'Oven Status'; inputNameMode = 'Oven Mode'; probeName = 'Oven Probe Status'; inputNameTempString = 'Oven Temperature'; courseStartString = 'Oven Start Time Not Set'; courseTimeString = 'Oven Cook Time Not Set'; courseTimerString = 'Oven Timer Not Set'; courseTimeEndString = 'Oven End Time Not Set'; inputNameOptions = 'Oven Options'; inputNameBurner1 = 'Front Left Burner Status'; inputNameBurner2 = 'Back Left Burner Status'; inputNameBurner3 = 'Center Burner Status'; inputNameBurner4 = 'Front Right Burner Status'; inputNameBurner5 = 'Back Right Burner Status'; firstStart = true; firstDuration = 0; firstTimer = 0; courseStartMS = 0; inputID = 1; temperatureFCommand = 0; thermostatSel = 0; timerAlarmSec = 0; pauseUpdate = false; firstPause = true; localTemperature = 22; localHumidity = 50; ovenCommandList = { ovenMode: 'BAKE', ovenSetTemperature: 350, tempUnits: 'FAHRENHEIT', ovenSetDuration: 1800, probeTemperature: 0, ovenKeepWarm: 'DISABLE', }; monitorOnly = true; homekitMonitorOnly = true; waitingForCommand = false; // flag showProbe = false; showTime = false; showTimer = false; showBurner1 = false; showBurner2 = false; showBurner3 = false; showBurner4 = false; showBurner5 = false; /** service */ ovenService; ovenState; ovenMode; ovenTemp; prove; ovenOptions; ovenStart; ovenTimer; ovenTime; ovenEndTime; burner1; burner2; burner3; burner4; burner5; ovenTimerService; ovenAlarmService; bakeSwitch; convectionBakeSwitch; convectionRoastSwitch; frozenMealSwitch; airFrySwitch; airSousvideSwitch; warmModeSwitch; cancelSwitch; monitorOnlySwitch; startOvenSwitch; keepWarmSwitch; ovenDoorOpened; rangeOn; remoteEnabled; burnersOnNumber; ovenTempControl; probeTempControl; createInputSourceService(name, subtype, identifier, configuredName, isShow) { return this.accessory.getService(name) || this.accessory.addService(this.platform.Service.InputSource, name, subtype) .setCharacteristic(this.platform.Characteristic.Identifier, identifier) .setCharacteristic(this.platform.Characteristic.ConfiguredName, configuredName) .setCharacteristic(this.platform.Characteristic.IsConfigured, this.platform.Characteristic.IsConfigured.CONFIGURED) .setCharacteristic(this.platform.Characteristic.InputSourceType, this.platform.Characteristic.InputSourceType.APPLICATION) .setCharacteristic(this.platform.Characteristic.TargetVisibilityState, isShow ? this.platform.Characteristic.TargetVisibilityState.SHOWN : this.platform.Characteristic.TargetVisibilityState.HIDDEN) .setCharacteristic(this.platform.Characteristic.CurrentVisibilityState, isShow ? this.platform.Characteristic.CurrentVisibilityState.SHOWN : this.platform.Characteristic.CurrentVisibilityState.HIDDEN); } constructor(platform, accessory, logger) { super(platform, accessory, logger); this.platform = platform; this.accessory = accessory; const { Characteristic } = this.platform; this.ovenService = this.accessory.getService(this.config.name) || this.accessory.addService(this.platform.Service.Television, this.config.name, 'NicoCataGaTa-OvenOven7'); this.ovenService.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'LG Range'); this.ovenService.setPrimaryService(true); this.ovenService.setCharacteristic(this.platform .Characteristic.SleepDiscoveryMode, this.platform.Characteristic.SleepDiscoveryMode.ALWAYS_DISCOVERABLE); this.ovenService.getCharacteristic(this.platform.Characteristic.Active) .on('get', (callback) => { const currentValue = this.ovenServiceActive(); callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (!enabled) { this.stopOven(); } else { this.sendOvenCommand(); } callback(null); }); this.ovenService .setCharacteristic(this.platform.Characteristic.ActiveIdentifier, this.inputID); this.ovenService.getCharacteristic(this.platform.Characteristic.ActiveIdentifier) .on('set', (inputIdentifier, callback) => { const vNum = normalizeNumber(inputIdentifier); if (vNum === null) { this.platform.log.error('ActiveIdentifier is not a number'); callback(); return; } if (vNum > 14 || vNum < 1) { this.inputID = 1; } else { this.inputID = vNum; } callback(); }) .on('get', (callback) => { const currentValue = this.inputID; callback(null, currentValue); }); this.ovenState = this.createInputSourceService('Oven Status', 'NicoCataGaTa-Oven1003', 1, this.ovenStatus(), true); this.ovenState.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.ovenStatus(); callback(null, currentValue); }); this.ovenService.addLinkedService(this.ovenState); this.ovenMode = this.createInputSourceService('Oven Mode', 'NicoCataGaTa-Oven1004', 2, this.ovenModeName(), this.ovenOnStatus()); this.ovenMode.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.ovenModeName(); callback(null, currentValue); }); this.ovenService.addLinkedService(this.ovenMode); this.ovenTemp = this.createInputSourceService('Oven Temperature', 'NicoCataGaTa-Oven1004T', 3, this.ovenTemperature(), this.ovenOnStatus()); this.ovenTemp.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.ovenTemperature(); callback(null, currentValue); }); this.ovenService.addLinkedService(this.ovenTemp); this.prove = this.createInputSourceService('Probe Status', 'NicoCata-Always15', 4, this.proveStatus(), this.showProbe); this.prove.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.proveStatus(); callback(null, currentValue); }); this.ovenService.addLinkedService(this.prove); this.ovenOptions = this.createInputSourceService('Oven Options', 'NicoCata-Always4', 5, this.oventOptions(), this.ovenOnStatus()); this.ovenOptions.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.oventOptions(); callback(null, currentValue); }); this.ovenService.addLinkedService(this.ovenOptions); this.ovenStart = this.createInputSourceService('Oven Start Time', 'NicoCata-Always1', 6, this.courseStartString, this.showTime); this.ovenStart.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.courseStartString; callback(null, currentValue); }); this.ovenService.addLinkedService(this.ovenStart); this.ovenTimer = this.createInputSourceService('Oven Timer Status', 'NicoCata-Always2', 7, this.courseTimerString, this.showTimer); this.ovenTimer.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.courseTimerString; callback(null, currentValue); }); this.ovenService.addLinkedService(this.ovenTimer); this.ovenTime = this.createInputSourceService('Oven Cook Time Status', 'NicoCata-Always2T', 8, this.courseTimeString, this.showTime); this.ovenTime.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.courseTimeString; callback(null, currentValue); }); this.ovenService.addLinkedService(this.ovenTime); this.ovenEndTime = this.createInputSourceService('Oven End Time', 'NicoCata-Always3', 9, this.courseTimeEndString, this.showTime); this.ovenEndTime.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.courseTimeEndString; callback(null, currentValue); }); this.ovenService.addLinkedService(this.ovenEndTime); this.burner1 = this.createInputSourceService('Front Left Burner Status', 'NicoCataGaTa-Oven001', 10, this.burner1State(), this.showBurner1); this.burner1.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.burner1State(); callback(null, currentValue); }); this.ovenService.addLinkedService(this.burner1); this.burner2 = this.createInputSourceService('Back Left Burner Status', 'NicoCataGaTa-Oven002', 11, this.burner2State(), this.showBurner2); this.burner2.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.burner2State(); callback(null, currentValue); }); this.ovenService.addLinkedService(this.burner2); this.burner3 = this.createInputSourceService('Center Burner Status', 'NicoCataGaTa-Oven003', 12, this.burner3State(), this.showBurner3); this.burner3.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.burner3State(); callback(null, currentValue); }); this.ovenService.addLinkedService(this.burner3); this.burner4 = this.createInputSourceService('Front Right Burner Status', 'NicoCataGaTa-Oven004', 13, this.burner4State(), this.showBurner4); this.burner4.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.burner4State(); callback(null, currentValue); }); this.ovenService.addLinkedService(this.burner4); this.burner5 = this.createInputSourceService('Back Right Burner Status', 'NicoCataGaTa-Oven005', 14, this.burner5State(), this.showBurner5); this.burner5.getCharacteristic(this.platform.Characteristic.ConfiguredName) .on('get', (callback) => { const currentValue = this.burner5State(); callback(null, currentValue); }); this.ovenService.addLinkedService(this.burner5); //////////Timers this.ovenTimerService = this.accessory.getService('Oven Cook Time') || this.accessory.addService(this.platform.Service.Valve, 'Oven Cook Time', 'NicoCataGaTa-OvenT2'); this.ovenTimerService.setCharacteristic(Characteristic.Name, 'Oven Cook Time'); this.ovenTimerService.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.ovenTimerService.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Oven Cook Time'); this.ovenTimerService.setCharacteristic(Characteristic.ValveType, Characteristic.ValveType.IRRIGATION); this.ovenTimerService.getCharacteristic(Characteristic.Active) .on('get', (callback) => { let currentValue = 0; if (this.remainTime() !== 0) { currentValue = 1; } callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (!enabled) { this.stopOven(); this.ovenTimerService.updateCharacteristic(Characteristic.Active, 0); this.ovenTimerService.updateCharacteristic(Characteristic.RemainingDuration, 0); this.ovenTimerService.updateCharacteristic(Characteristic.InUse, 0); } else { this.sendOvenCommand(); } callback(null); }); this.ovenTimerService.setCharacteristic(Characteristic.InUse, this.remainTime() > 0 ? Characteristic.InUse.IN_USE : Characteristic.InUse.NOT_IN_USE); this.ovenTimerService.getCharacteristic(Characteristic.RemainingDuration) .setProps({ maxValue: (86400 / 2) - 1, // 12hours }) .on('get', (callback) => { const currentValue = this.remainTime(); callback(null, currentValue); }); this.ovenTimerService.getCharacteristic(this.platform.Characteristic.SetDuration) .setProps({ maxValue: (86400 / 2) - 1, // 12hours }) .on('get', (callback) => { const currentValue = this.oventTargetTime(); callback(null, currentValue); }) .on('set', (value, callback) => { const vNum = normalizeNumber(value); if (vNum === null) { this.platform.log.error('SetDuration is not a number'); callback(); return; } this.pauseUpdate = true; this.platform.log.debug('Cooking Duration set to to: ' + this.secondsToTime(vNum)); this.ovenCommandList.ovenSetDuration = vNum; callback(null); }); this.ovenAlarmService = this.accessory.getService('Oven Timer') || this.accessory.addService(this.platform.Service.Valve, 'Oven Timer', 'NicoCataGaTa-OvenT32'); this.ovenAlarmService.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.ovenAlarmService.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Oven Timer'); this.ovenAlarmService.setCharacteristic(Characteristic.Name, 'Oven Timer'); this.ovenAlarmService.setCharacteristic(Characteristic.ValveType, Characteristic.ValveType.IRRIGATION); this.ovenAlarmService.getCharacteristic(Characteristic.Active) .on('get', (callback) => { let currentValue = 0; if (this.ovenTimerTime() !== 0) { currentValue = 1; } callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (!enabled) { this.timerAlarmSec = 0; this.sendTimerCommand(0); this.ovenAlarmService.updateCharacteristic(Characteristic.Active, 0); this.ovenAlarmService.updateCharacteristic(Characteristic.RemainingDuration, 0); this.ovenAlarmService.updateCharacteristic(Characteristic.InUse, 0); } else { this.sendTimerCommand(this.timerAlarmSec); this.ovenAlarmService.updateCharacteristic(Characteristic.Active, 1); this.ovenAlarmService.updateCharacteristic(Characteristic.RemainingDuration, this.timerAlarmSec); this.ovenAlarmService.updateCharacteristic(Characteristic.InUse, 1); } callback(null); }); this.ovenAlarmService.setCharacteristic(Characteristic.InUse, this.ovenTimerTime() > 0 ? Characteristic.InUse.IN_USE : Characteristic.InUse.NOT_IN_USE); this.ovenAlarmService.getCharacteristic(Characteristic.RemainingDuration) .setProps({ maxValue: (86400 / 2), // 12hours }) .on('get', (callback) => { const currentValue = this.ovenTimerTime(); callback(null, currentValue); }); this.ovenAlarmService.getCharacteristic(this.platform.Characteristic.SetDuration) .setProps({ maxValue: (86400 / 2), // 12hours }) .on('get', (callback) => { const currentValue = this.timerAlarmSec; callback(null, currentValue); }) .on('set', (value, callback) => { let vNum = normalizeNumber(value); if (vNum === null) { this.platform.log.error('SetDuration is not a number'); callback(); return; } if (vNum >= (86400 / 2)) { vNum = (86400 / 2) - 1; } this.timerAlarmSec = vNum; callback(null); }); ////////////Buttons this.bakeSwitch = accessory.getService('Bake Mode') || accessory.addService(this.platform.Service.Switch, 'Bake Mode', 'CataNicoGaTa-80'); this.bakeSwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.bakeSwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Bake Mode'); this.bakeSwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { this.platform.log.debug('Bake Switch Get state'); const currentValue = false; callback(null, currentValue); }) .on('set', (value, callback) => { if (value) { this.ovenCommandList.ovenMode = 'BAKE'; } this.updateOvenModeSwitch(); callback(null); }); this.convectionBakeSwitch = accessory.getService('Convection Bake Mode') || accessory.addService(this.platform.Service.Switch, 'Convection Bake Mode', 'CataNicoGaTa-Control1'); this.convectionBakeSwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.convectionBakeSwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Convection Bake Mode'); this.convectionBakeSwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { const currentValue = false; callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (enabled) { this.ovenCommandList.ovenMode = 'CONVECTION_BAKE'; } this.updateOvenModeSwitch(); callback(null); }); this.convectionRoastSwitch = accessory.getService('Convection Roast Mode') || accessory.addService(this.platform.Service.Switch, 'Convection Roast Mode', 'CataNicoGaTa-Control2'); this.convectionRoastSwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.convectionRoastSwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Convection Roast Mode'); this.convectionRoastSwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { const currentValue = false; callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (enabled) { this.ovenCommandList.ovenMode = 'CONVECTION_ROST'; } this.updateOvenModeSwitch(); callback(null); }); this.frozenMealSwitch = accessory.getService('Frozen Meal Mode') || accessory.addService(this.platform.Service.Switch, 'Frozen Meal Mode', 'CataNicoGaTa-Control3'); this.frozenMealSwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.frozenMealSwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Frozen Meal Mode'); this.frozenMealSwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { const currentValue = false; callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (enabled) { this.ovenCommandList.ovenMode = 'FROZEN_MEAL'; } this.updateOvenModeSwitch(); callback(null); }); this.airFrySwitch = accessory.getService('Air Fry Mode') || accessory.addService(this.platform.Service.Switch, 'Air Fry Mode', 'CataNicoGaTa-Control4'); this.airFrySwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.airFrySwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Air Fry Mode'); this.airFrySwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { const currentValue = false; callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (enabled) { this.ovenCommandList.ovenMode = 'AIR_FRY'; } this.updateOvenModeSwitch(); callback(null); }); this.airSousvideSwitch = accessory.getService('Air Sousvide Mode') || accessory.addService(this.platform.Service.Switch, 'Air Sousvide Mode', 'CataNicoGaTa-Control5'); this.airSousvideSwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.airSousvideSwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Air Sousvide Mode'); this.airSousvideSwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { const currentValue = false; callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (enabled) { this.ovenCommandList.ovenMode = 'AIR_SOUSVIDE'; } this.updateOvenModeSwitch(); callback(null); }); this.warmModeSwitch = accessory.getService('Proof-Warm Mode') || accessory.addService(this.platform.Service.Switch, 'Proof-Warm Mode', 'CataNicoGaTa-Control5W'); this.warmModeSwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.warmModeSwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Proof-Warm Mode'); this.warmModeSwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { const currentValue = false; callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (enabled) { this.ovenCommandList.ovenMode = 'WARM'; } this.updateOvenModeSwitch(); callback(null); }); this.cancelSwitch = accessory.getService('Stop Oven') || accessory.addService(this.platform.Service.Switch, 'Stop Oven', 'CataNicoGaTa-Control6'); this.cancelSwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.cancelSwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Stop Oven'); this.cancelSwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { const currentValue = false; callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (enabled) { this.stopOven(); } setTimeout(() => { this.cancelSwitch.updateCharacteristic(this.platform.Characteristic.On, false); }, 1000); this.updateOvenModeSwitch(); callback(null); }); this.monitorOnlySwitch = accessory.getService('Monitor Only Mode') || accessory.addService(this.platform.Service.Switch, 'Monitor Only Mode', 'CataNicoGaTa-Control7'); this.monitorOnlySwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.monitorOnlySwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Monitor Only Mode'); this.monitorOnlySwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { if (this.Status.data?.upperRemoteStart.includes('DIS')) { this.monitorOnly = true; } const currentValue = this.monitorOnly; callback(null, currentValue); }) .on('set', (value, callback) => { const b = normalizeBoolean(value); this.homekitMonitorOnly = b; this.monitorOnly = b; callback(null); }); this.startOvenSwitch = accessory.getService('Start Oven') || accessory.addService(this.platform.Service.Switch, 'Start Oven', 'CataNicoGaTa-Control8'); this.startOvenSwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.startOvenSwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Start Oven'); this.startOvenSwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { const currentValue = false; callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (enabled) { this.sendOvenCommand(); setTimeout(() => { this.startOvenSwitch.updateCharacteristic(this.platform.Characteristic.On, false); }, 1000); } callback(null); }); if ('upperCookAndWarmStatus' in this.Status.data) { this.keepWarmSwitch = accessory.getService('Keep Warm') || accessory.addService(this.platform.Service.Switch, 'Keep Warm', 'CataNicoGaTa-Control9'); this.keepWarmSwitch.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.keepWarmSwitch.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Keep Warm'); this.keepWarmSwitch.getCharacteristic(this.platform.Characteristic.On) .on('get', (callback) => { const currentValue = !this.Status.data?.upperCookAndWarmStatus?.includes('DIS'); callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (enabled) { this.ovenCommandList.ovenKeepWarm = 'ENABLE'; } else { this.ovenCommandList.ovenKeepWarm = 'DISABLE'; } callback(null); }); } ////////Door sensor this.ovenDoorOpened = this.accessory.getService('Oven Door') || this.accessory.addService(this.platform.Service.ContactSensor, 'Oven Door', 'NicoCataGaTa-OvenTCBCS'); this.ovenDoorOpened.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.ovenDoorOpened.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Oven Door'); this.ovenDoorOpened.setCharacteristic(this.platform.Characteristic.StatusActive, this.onStatus()); this.ovenDoorOpened.setCharacteristic(this.platform.Characteristic.ContactSensorState, this.Status.data?.upperDoorOpen.includes('DIS') ? 0 : 1); ///Range Cooking this.rangeOn = this.accessory.getService('Range is Cooking') || this.accessory.addService(this.platform.Service.MotionSensor, 'Range is Cooking', 'NicoCataGaTa-OvenTCBCSMotion'); this.rangeOn.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.rangeOn.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Range is Cooking'); this.rangeOn.setCharacteristic(this.platform.Characteristic.StatusActive, this.onStatus()); this.rangeOn.setCharacteristic(this.platform.Characteristic.MotionDetected, this.onStatus()); ////Remote Enabled this.remoteEnabled = this.accessory.getService('Remote Control Enabled') || this.accessory.addService(this.platform.Service.ContactSensor, 'Remote Control Enabled', 'NicoCataGaTa-OvenTCRCS'); this.remoteEnabled.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.remoteEnabled.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Remote Control Enabled'); this.remoteEnabled.setCharacteristic(this.platform.Characteristic.StatusActive, this.onStatus()); this.remoteEnabled.setCharacteristic(this.platform.Characteristic.ContactSensorState, this.Status.data?.upperRemoteStart.includes('DIS') ? 0 : 1); /////////Burners On this.burnersOnNumber = this.accessory.getService('Number of Burners in Use') || this.accessory.addService(this.platform.Service.LightSensor, 'Number of Burners in Use', 'NicoCataGaTa-OvenTCB'); this.burnersOnNumber.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.burnersOnNumber.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Number of Burners in Use'); this.burnersOnNumber.setCharacteristic(this.platform.Characteristic.CurrentAmbientLightLevel, this.Status.data?.burnerOnCounter < 1 ? 0.0001 : this.Status.data?.burnerOnCounter); this.burnersOnNumber.setCharacteristic(this.platform.Characteristic.StatusActive, this.Status.data?.burnerOnCounter > 0 ? true : false); ///////Oven Temperature Control this.ovenTempControl = this.accessory.getService('Oven Temperature Control') || this.accessory.addService(this.platform.Service.Thermostat, 'Oven Temperature Control', 'NicoCataGaTa-OvenTC') .setCharacteristic(this.platform.Characteristic.Name, 'Oven Temperature Control') .setCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState, this.currentHeatingState()) .setCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits, 1); this.ovenTempControl.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.ovenTempControl.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Oven Temperature Control'); this.ovenTempControl.getCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState) .setProps({ validValues: [this.platform.Characteristic.TargetHeatingCoolingState.OFF, this.platform.Characteristic.TargetHeatingCoolingState.HEAT] }) .on('get', (callback) => { const currentValue = this.targetHeatingState(); callback(null, currentValue); }) .on('set', (value, callback) => { const enabled = normalizeBoolean(value); if (!enabled) { this.stopOven(); } else { this.pauseUpdate = true; } callback(null); }); this.ovenTempControl.getCharacteristic(this.platform.Characteristic.CurrentTemperature) .setProps({ minValue: 0, maxValue: 218, minStep: 0.5, }) .on('get', (callback) => { const currentValue = this.ovenCurrentTemperature(); callback(null, currentValue); }); this.ovenTempControl.getCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity) .on('get', (callback) => { const currentValue = this.localHumidity; callback(null, currentValue); }); this.ovenTempControl.getCharacteristic(this.platform.Characteristic.TargetTemperature) .setProps({ minValue: 38, maxValue: 218, minStep: 0.5, }) .on('get', (callback) => { const currentValue = this.ovenTargetTemperature(); // this.platform.log('Get Target Temp' + this.ovenTargetTemperature()) callback(null, currentValue); }) .on('set', (value, callback) => { const vNum = normalizeNumber(value); if (vNum === null) { this.platform.log.error('TargetTemperature is not a number'); callback(); return; } if (this.Status.data?.upperCurrentTemperatureUnit.includes('FAH')) { this.ovenCommandList.ovenSetTemperature = this.tempCtoF(vNum); } else { this.ovenCommandList.ovenSetTemperature = Math.round(vNum); } callback(null); }); this.probeTempControl = this.accessory.getService('Probe Temperature Control') || this.accessory.addService(this.platform.Service.Thermostat, 'Probe Temperature Control', 'NicoCataGaTa-OvenTCP2') .setCharacteristic(this.platform.Characteristic.Name, 'Probe Temperature Control') .setCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState, this.probeCurrentState()) .setCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits, 1); this.probeTempControl.addOptionalCharacteristic(this.platform.Characteristic.ConfiguredName); this.probeTempControl.setCharacteristic(this.platform.Characteristic.ConfiguredName, 'Probe Temperature Control'); this.probeTempControl.getCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState) .setProps({ validValues: [this.platform.Characteristic.TargetHeatingCoolingState.OFF, this.platform.Characteristic.TargetHeatingCoolingState.HEAT] }) .on('get', (callback) => { const currentValue = this.probeTargetState(); callback(null, currentValue); }) .on('set', (value, callback) => { this.pauseUpdate = true; callback(null); }); this.probeTempControl.getCharacteristic(this.platform.Characteristic.CurrentTemperature) .setProps({ minValue: 0, maxValue: 285, minStep: 0.1, }) .on('get', (callback) => { const currentValue = this.probeCurrentTemperature(); callback(null, currentValue); }); this.probeTempControl.getCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity) .on('get', (callback) => { const currentValue = this.localHumidity; callback(null, currentValue); }); this.probeTempControl.getCharacteristic(this.platform.Characteristic.TargetTemperature) .setProps({ minValue: 38, maxValue: 285, minStep: 0.1, }) .on('get', (callback) => { const currentValue = this.probeTargetTemperature(); callback(null, currentValue); }) .on('set', (value, callback) => { const v = normalizeNumber(value); if (v === null) { this.platform.log.error('TargetTemperature is not a valid number'); callback(null); return; } if (this.Status.data?.upperCurrentTemperatureUnit.includes('FAH')) { this.ovenCommandList.probeTemperature = this.tempCtoF(v); } else { this.ovenCommandList.probeTemperature = Math.round(v); } callback(null); }); } get Status() { return new OvenStatus(this.accessory.context.device.snapshot?.ovenState, this.accessory.context.device.deviceModel); } get config() { return Object.assign({}, { oven_trigger: false, }, super.config); } secondsToTime(seconds) { const h = Math.floor(seconds / 3600); const m = Math.floor(seconds % 3600 / 60); const s = Math.floor(seconds % 60); return h + ':' + m + ':' + s + ' Hours'; } async sendTimerCommand(time) { if (!this.waitingForCommand) { this.platform.log.debug('Alarm Set to: ' + this.secondsToTime(time)); const ctrlKey = 'SetTimer'; const device = this.accessory.context.device; this.platform.ThinQ?.deviceControl(device.id, { dataKey: null, dataValue: null, dataSetList: { ovenState: { 'cmdOptionContentsType': 'TIMER', 'cmdOptionDataLength': 'TIMER', 'lowerTimerHour': 128, 'lowerTimerMinute': 128, 'lowerTimerSecond': 128, 'upperTimerHour': Math.floor(time / 3600), 'upperTimerMinute': Math.floor(time % 3600 / 60), 'upperTimerSecond': Math.floor(time % 60), }, }, dataGetList: null, }, 'Set', ctrlKey); this.waitingForCommand = true; setTimeout(() => { this.pauseUpdate = false; this.firstPause = true; }, 10000); } setTimeout(() => { this.waitingForCommand = false; }, 1000); } async sendOvenCommand() { if (!this.monitorOnly) { if (!this.waitingForCommand) { this.pauseUpdate = true; this.ovenCommandList.tempUnits = this.Status.data?.upperCurrentTemperatureUnit; if (this.ovenCommandList.ovenSetDuration === 0) { this.ovenCommandList.ovenSetDuration = 1800; } if (this.ovenCommandList.ovenMode === 'NONE') { this.ovenCommandList.ovenMode = 'BAKE'; } if (this.ovenCommandList.ovenMode.includes('CONVECTION_BAKE') || this.ovenCommandList.ovenMode.includes('CONVECTION_ROST') || this.ovenCommandList.ovenMode.includes('FROZEN_MEAL') || this.ovenCommandList.ovenMode.includes('AIR_FRY')) { if (this.ovenCommandList.tempUnits.includes('FAH')) { if (this.ovenCommandList.ovenSetTemperature < 300) { this.ovenCommandList.ovenSetTemperature = 300; } if (this.ovenCommandList.ovenSetTemperature > 550) { this.ovenCommandList.ovenSetTemperature = 550; } } else { if (this.ovenCommandList.ovenSetTemperature < 150) { this.ovenCommandList.ovenSetTemperature = 150; } if (this.ovenCommandList.ovenSetTemperature > 285) { this.ovenCommandList.ovenSetTemperature = 285; } } } else if (this.ovenCommandList.ovenMode.includes('BAKE')) { if (this.ovenCommandList.tempUnits.includes('FAH')) { if (this.ovenCommandList.ovenSetTemperature < 170) { this.ovenCommandList.ovenSetTemperature = 170; } if (this.ovenCommandList.ovenSetTemperature > 550) { this.ovenCommandList.ovenSetTemperature = 550; } } else { if (this.ovenCommandList.ovenSetTemperature < 80) { this.ovenCommandList.ovenSetTemperature = 80; } if (this.ovenCommandList.ovenSetTemperature > 285) { this.ovenCommandList.ovenSetTemperature = 285; } } } else if (this.ovenCommandList.ovenMode.includes('AIR_SOUSVIDE')) { if (this.ovenCommandList.tempUnits.includes('FAH')) { if (this.ovenCommandList.ovenSetTemperature < 100) { this.ovenCommandList.ovenSetTemperature = 100; } if (this.ovenCommandList.ovenSetTemperature > 205) { this.ovenCommandList.ovenSetTemperature = 205; } } else { if (this.ovenCommandList.ovenSetTemperature < 380) { this.ovenCommandList.ovenSetTemperature = 38; } if (this.ovenCommandList.ovenSetTemperature > 96) { this.ovenCommandList.ovenSetTemperature = 96; } } } else if (this.ovenCommandList.ovenMode.includes('WARM')) { if (this.ovenCommandList.tempUnits.includes('FAH')) { this.ovenCommandList = { ovenMode: 'WARM', ovenSetTemperature: 0, tempUnits: 'FAHRENHEIT', ovenSetDuration: 0, probeTemperature: 0, ovenKeepWarm: 'DISABLE', }; } else { this.ovenCommandList = { ovenMode: 'WARM', ovenSetTemperature: 0, tempUnits: 'CELSIUS', ovenSetDuration: 0, probeTemperature: 0, ovenKeepWarm: 'DISABLE', }; } } this.platform.log.debug('Sending the Folowing Commands: ' + JSON.stringify(this.ovenCommandList)); const ctrlKey = 'SetCookStart'; const device = this.accessory.context.device; this.platform.ThinQ?.deviceControl(device.id, { dataKey: null, dataValue: null, dataSetList: { ovenState: { 'cmdOptionContentsType': 'REMOTE_COOK_START', 'cmdOptionDataLength': 'REMOTE_COOK_START', 'cmdOptionSetCookAndWarm': this.ovenCommandList.ovenKeepWarm, 'cmdOptionSetCookName': this.ovenCommandList.ovenMode, 'cmdOptionSetMyRecipeCookNumber': 0, 'cmdOptionSetSteamLevel': '', 'cmdOptionSetSubCookNumber': 0, 'cmdOptionSetTargetTemperatureUnit': this.ovenCommandList.tempUnits, 'cmdOptionSetTargetTimeHour': Math.floor(this.ovenCommandList.ovenSetDuration / 3600), 'cmdOptionSetTargetTimeMinute': Math.floor(this.ovenCommandList.ovenSetDuration % 3600 / 60), 'cmdOptionSetRapidPreheat': 'OFF', 'setTargetProveTemperature': this.ovenCommandList.probeTemperature, 'setTargetTemperature': this.ovenCommandList.ovenSetTemperature, }, }, dataGetList: null, }, 'Set', ctrlKey); this.waitingForCommand = true; setTimeout(() => { this.pauseUpdate = false; this.firstPause = true; }, 10000); } setTimeout(() => { this.waitingForCommand = false; }, 1000); } } async stopOven() { if (!this.monitorOnly) { if (!this.waitingForCommand) { this.pauseUpdate = true; this.platform.log.debug('Stop Command Sent to Oven'); const ctrlKey = 'SetCookStop'; const device = this.accessory.context.device; this.platform.ThinQ?.deviceControl(device.id, { dataKey: null, dataValue: null, dataSetList: { ovenState: { 'cmdOptionCookStop': 'UPPER', }, }, dataGetList: null, }, 'Set', ctrlKey); setTimeout(() => { this.pauseUpdate = false; this.firstPause = true; }, 10000); this.waitingForCommand = true; setTimeout(() => { this.waitingForCommand = false; }, 1000); } } } getMonitorState() { if (this.Status.data?.upperRemoteStart.includes('DIS')) { this.monitorOnly = true; } else { this.monitorOnly = this.homekitMonitorOnly; } return this.monitorOnly; } setActive() { this.platform.log.info('Oven Response 1', this.Status.data); // this.platform.log('Oven Response 2', this.Status.deviceModel.DeviceModel.data.ControlWifi); // this.platform.log('Oven Response 3', this.Status.deviceModel.DeviceModel.data.UpperManualCook); //this.platform.log('Oven Response 4', this.Status.deviceModel.DeviceModel.data.Monitoring); // this.platform.log('Dishwasher rinse', this.Status.data.rinseLevel); // this.platform.log('Dishwasher rinse typeof', typeof this.Status.data.rinseLevel); //this.updateRinseLevel(); // this.platform.log('Dishwasher rinse status', this.rinseStatus); // this.serviceDishwasher.updateCharacteristic(this.platform.Characteristic.StatusFault, this.rinseStatus); // this.platform.log('Dishwasher Response', this.Status); // throw new this.platform.api.hap.HapStatusError(-70412 /* this.platform.api.hap.HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE */); } ovenOnStatus() { return !this.Status.data?.upperState.includes('INITIAL'); } onStatus() { return !this.Status.data?.upperState.includes('INITIAL') || this.Status.data?.burnerOnCounter > 0; } nameLengthCheck(newName) { if (newName.length >= 64) { newName = newName.slice(0, 60) + '...'; } return newName; } remainTime() { let remainingDuration = 0; if (typeof this.Status.data?.upperRemainTimeHour !== 'undefined') { remainingDuration += this.Status.data?.upperRemainTimeHour * 3600; } if (typeof this.Status.data?.upperRemainTimeMinute !== 'undefined') { remainingDuration += this.Status.data?.upperRemainTimeMinute * 60; } if (typeof this.Status.data?.upperRemainTimeSecond !== 'undefined') { remainingDuration += this.Status.data?.upperRemainTimeSecond; } return remainingDuration; } ovenModeName() { this.inputNameMode = 'Oven Mode: '; switch (this.Status.data?.upperManualCookName) { case 'NONE': this.inputNameMode += 'None'; break; case 'BAKE': this.inputNameMode += 'Bake'; break; case 'ROAST': this.inputNameMode += 'Roast'; break; case 'CONVECTION_BAKE': this.inputNameMode += 'Convection Bake'; break; case 'CONVECTION_ROAST':