Skip to content

Commit

Permalink
Split appliances into different files for more specific features per …
Browse files Browse the repository at this point in the history
…model
  • Loading branch information
bwp91 committed Jul 15, 2024
1 parent d61ae53 commit 08f5866
Show file tree
Hide file tree
Showing 21 changed files with 1,194 additions and 109 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ This project tries to adhere to [Semantic Versioning](http://semver.org/). In pr
- `MINOR` version when a new device type is added, or when a new feature is added that is backwards-compatible
- `PATCH` version when backwards-compatible bug fixes are implemented

## 10.9.2 (2024-07-15)

### Changed

- Split appliances into different files for more specific features per model

## 10.9.1 (2024-07-13)

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ export default class {
return;
}

switch (command) {
const deviceFunction = `${getTwoItemPosition(hexParts, 2)}${getTwoItemPosition(hexParts, 3)}`;

switch (deviceFunction) {
default:
this.accessory.logWarn(`${platformLang.newScene}: [${command}] [${hexString}]`);
break;
Expand Down
157 changes: 157 additions & 0 deletions lib/device/dehumidifier-H7151.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import {
base64ToHex,
getTwoItemPosition,
hexToTwoItems,
parseError,
} from '../utils/functions.js';
import platformLang from '../utils/lang-en.js';

export default class {
constructor(platform, accessory) {
// Set up variables from the platform
this.hapChar = platform.api.hap.Characteristic;
this.hapErr = platform.api.hap.HapStatusError;
this.hapServ = platform.api.hap.Service;
this.platform = platform;

// Set up variables from the accessory
this.accessory = accessory;

// Rotation speed to value in {1, 2, ..., 8}
this.speed2Value = (speed) => Math.min(Math.max(parseInt(Math.round(speed / 10), 10), 1), 8);

// Speed codes
this.value2Code = {
1: 'MwUBAQAAAAAAAAAAAAAAAAAAADY=',
2: 'MwUBAgAAAAAAAAAAAAAAAAAAADU=',
3: 'MwUBAwAAAAAAAAAAAAAAAAAAADQ=',
4: 'MwUBBAAAAAAAAAAAAAAAAAAAADM=',
5: 'MwUBBQAAAAAAAAAAAAAAAAAAADI=',
6: 'MwUBBgAAAAAAAAAAAAAAAAAAADE=',
7: 'MwUBBwAAAAAAAAAAAAAAAAAAADA=',
8: 'MwUBCAAAAAAAAAAAAAAAAAAAAD8=',
};

// Add the fan service if it doesn't already exist
this.service = this.accessory.getService(this.hapServ.Fan) || this.accessory.addService(this.hapServ.Fan);

// Add the set handler to the fan on/off characteristic
this.service
.getCharacteristic(this.hapChar.On)
.onSet(async (value) => this.internalStateUpdate(value));
this.cacheState = this.service.getCharacteristic(this.hapChar.On).value ? 'on' : 'off';

// Add the set handler to the fan rotation speed characteristic
this.service
.getCharacteristic(this.hapChar.RotationSpeed)
.setProps({
minStep: 10,
validValues: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
})
.onSet(async (value) => this.internalSpeedUpdate(value));
this.cacheSpeed = this.service.getCharacteristic(this.hapChar.RotationSpeed).value;

// Output the customised options to the log
const opts = JSON.stringify({});
platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts);
}

async internalStateUpdate(value) {
try {
const newValue = value ? 'on' : 'off';

// Don't continue if the new value is the same as before
if (this.cacheState === newValue) {
return;
}

// Send the request to the platform sender function
await this.platform.sendDeviceUpdate(this.accessory, {
cmd: 'stateHumi',
value: value ? 1 : 0,
});

// Cache the new state and log if appropriate
this.cacheState = newValue;
this.accessory.log(`${platformLang.curState} [${newValue}]`);
} catch (err) {
// Catch any errors during the process
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`);

// Throw a 'no response' error and set a timeout to revert this after 2 seconds
setTimeout(() => {
this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on');
}, 2000);
throw new this.hapErr(-70402);
}
}

async internalSpeedUpdate(value) {
try {
// Don't continue if the speed is 0
if (value === 0) {
return;
}

// Get the single Govee value {1, 2, ..., 8}
const newValue = this.speed2Value(value);

// Don't continue if the speed value won't have effect
if (newValue * 10 === this.cacheSpeed) {
return;
}

// Get the scene code for this value
const newCode = this.value2Code[newValue];

// Send the request to the platform sender function
await this.platform.sendDeviceUpdate(this.accessory, {
cmd: 'ptReal',
value: newCode,
});

// Cache the new state and log if appropriate
this.cacheSpeed = newValue * 10;
this.accessory.log(`${platformLang.curSpeed} [${newValue}]`);
} catch (err) {
// Catch any errors during the process
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`);

// Throw a 'no response' error and set a timeout to revert this after 2 seconds
setTimeout(() => {
this.service.updateCharacteristic(this.hapChar.RotationSpeed, this.cacheSpeed);
}, 2000);
throw new this.hapErr(-70402);
}
}

externalUpdate(params) {
// Check for an ON/OFF change
if (params.state && params.state !== this.cacheState) {
this.cacheState = params.state;
this.service.updateCharacteristic(this.hapChar.On, this.cacheState === 'on');

// Log the change
this.accessory.log(`${platformLang.curState} [${this.cacheState}]`);
}

// Check for some other scene/mode change
(params.commands || []).forEach((command) => {
const hexString = base64ToHex(command);
const hexParts = hexToTwoItems(hexString);

// Return now if not a device query update code
if (getTwoItemPosition(hexParts, 1) !== 'aa') {
return;
}

const deviceFunction = `${getTwoItemPosition(hexParts, 2)}${getTwoItemPosition(hexParts, 3)}`;

switch (deviceFunction) {
default:
this.accessory.logWarn(`${platformLang.newScene}: [${command}] [${hexString}]`);
break;
}
});
}
}
File renamed without changes.
117 changes: 117 additions & 0 deletions lib/device/diffuser-H7162.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import {
base64ToHex,
getTwoItemPosition,
hexToTwoItems,
parseError,
} from '../utils/functions.js';
import platformLang from '../utils/lang-en.js';

export default class {
constructor(platform, accessory) {
// Set up variables from the platform
this.hapChar = platform.api.hap.Characteristic;
this.hapErr = platform.api.hap.HapStatusError;
this.hapServ = platform.api.hap.Service;
this.platform = platform;

// Set up variables from the accessory
this.accessory = accessory;

// Remove fan service if exists
if (this.accessory.getService(this.hapServ.Fan)) {
this.accessory.removeService(this.accessory.getService(this.hapServ.Fan));
}

// Add the purifier service if it doesn't already exist
this.service = this.accessory.getService(this.hapServ.AirPurifier)
|| this.accessory.addService(this.hapServ.AirPurifier);

// Add the set handler to the switch on/off characteristic
this.service.getCharacteristic(this.hapChar.Active).onSet(async (value) => {
await this.internalStateUpdate(value);
});
this.cacheState = this.service.getCharacteristic(this.hapChar.Active).value === 1 ? 'on' : 'off';

// Add options to the purifier target state characteristic
this.service
.getCharacteristic(this.hapChar.TargetAirPurifierState)
.updateValue(1)
.setProps({
minValue: 1,
maxValue: 1,
validValues: [1],
});

// Output the customised options to the log
const opts = JSON.stringify({});
platform.log('[%s] %s %s.', accessory.displayName, platformLang.devInitOpts, opts);
}

async internalStateUpdate(value) {
try {
const newValue = value === 1 ? 'on' : 'off';

// Don't continue if the new value is the same as before
if (this.cacheState === newValue) {
return;
}

// Send the request to the platform sender function
await this.platform.sendDeviceUpdate(this.accessory, {
cmd: 'stateHumi',
value,
});

// Cache the new state and log if appropriate
if (this.cacheState !== newValue) {
this.cacheState = newValue;
this.accessory.log(`${platformLang.curState} [${this.cacheState}]`);
}

this.service.updateCharacteristic(this.hapChar.CurrentAirPurifierState, value === 1 ? 2 : 0);
} catch (err) {
// Catch any errors during the process
this.accessory.logWarn(`${platformLang.devNotUpdated} ${parseError(err)}`);

// Throw a 'no response' error and set a timeout to revert this after 2 seconds
setTimeout(() => {
this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0);
}, 2000);
throw new this.hapErr(-70402);
}
}

externalUpdate(params) {
// Check for an ON/OFF change
if (params.state && params.state !== this.cacheState) {
this.cacheState = params.state;
this.service.updateCharacteristic(this.hapChar.Active, this.cacheState === 'on' ? 1 : 0);
this.service.updateCharacteristic(
this.hapChar.CurrentAirPurifierState,
this.cacheState === 'on' ? 2 : 0,
);

// Log the change
this.accessory.log(`${platformLang.curState} [${this.cacheState}]`);
}

// Check for some other scene/mode change
(params.commands || []).forEach((command) => {
const hexString = base64ToHex(command);
const hexParts = hexToTwoItems(hexString);

// Return now if not a device query update code
if (getTwoItemPosition(hexParts, 1) !== 'aa') {
return;
}

const deviceFunction = `${getTwoItemPosition(hexParts, 2)}${getTwoItemPosition(hexParts, 3)}`;

switch (deviceFunction) {
default:
this.accessory.logWarn(`${platformLang.newScene}: [${command}] [${hexString}]`);
break;
}
});
}
}
1 change: 1 addition & 0 deletions lib/device/fan.js
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ export default class {
}

const deviceFunction = `${getTwoItemPosition(hexParts, 2)}${getTwoItemPosition(hexParts, 3)}`;

switch (deviceFunction) {
case '0501': {
// Fan speed
Expand Down
Loading

0 comments on commit 08f5866

Please sign in to comment.