Skip to content

Commit

Permalink
feat: add lock functionality to ElectricMat device and Navien API
Browse files Browse the repository at this point in the history
  • Loading branch information
kyle-seongwoo-jun committed Feb 22, 2024
1 parent ead56f6 commit 10fb265
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 10 deletions.
29 changes: 27 additions & 2 deletions src/homebridge/electric-mat.device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export default class ElectricMat {
TargetHeaterCoolerState,
CurrentTemperature,
HeatingThresholdTemperature,
LockPhysicalControls,
TemperatureDisplayUnits,
},
Service: {
Expand Down Expand Up @@ -104,6 +105,11 @@ export default class ElectricMat {
.onGet(this.getTemperature.bind(this))
.onSet(this.setTemperature.bind(this));

// lock
heater.getCharacteristic(LockPhysicalControls)
.onGet(this.getLocked.bind(this))
.onSet(this.setLocked.bind(this));

// subscribe to device events
device.activeChanges.subscribe((isActive) => {
heater.updateCharacteristic(Active, isActive ? Active.ACTIVE : Active.INACTIVE);
Expand All @@ -112,6 +118,9 @@ export default class ElectricMat {
heater.updateCharacteristic(CurrentTemperature, temperature);
heater.updateCharacteristic(HeatingThresholdTemperature, temperature);
});
device.lockedChanges.subscribe((isLocked) => {
heater.updateCharacteristic(LockPhysicalControls, isLocked);
});

return heater;
}
Expand Down Expand Up @@ -214,7 +223,7 @@ export default class ElectricMat {

this.log.info('Set Active:', isActive ? 'ACTIVE' : 'INACTIVE');

await this.service.setActive(this.device, isActive);
await this.service.activate(this.device, isActive);
}

private async getHeaterState(): Promise<CharacteristicValue> {
Expand Down Expand Up @@ -251,7 +260,7 @@ export default class ElectricMat {

this.log.info('Set Heating State:', isActive ? 'HEAT' : 'OFF');

await this.service.setActive(this.device, isActive);
await this.service.activate(this.device, isActive);
}

private async getTemperature(): Promise<CharacteristicValue> {
Expand All @@ -269,4 +278,20 @@ export default class ElectricMat {

await this.service.setTemperature(this.device, temperature);
}

private async getLocked(): Promise<CharacteristicValue> {
const { isLocked } = this.device;

this.log.info('Get Locked:', isLocked);

return isLocked;
}

private async setLocked(value: CharacteristicValue) {
const isLocked = !!value;

this.log.info('Set Locked:', isLocked);

await this.service.lock(this.device, isLocked);
}
}
11 changes: 9 additions & 2 deletions src/navien/navien.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import assert from 'assert';
import { Logger } from 'homebridge';
import fetch, { BodyInit, HeadersInit, Response } from 'node-fetch';

import { OperationMode } from '../aws/interfaces';
import { API_URL } from './constants';
import { ApiException } from './exceptions';
import { CommonResponse, Device, DevicesResponse, ResponseCode } from './interfaces';
Expand Down Expand Up @@ -152,9 +153,9 @@ export class NavienApi {
return this.controlDevice(device);
}

public setActive(device: Device, isActive: boolean) {
public setOperationMode(device: Device, value: OperationMode) {
return this.controlDevice(device, {
operationMode: isActive ? 1 : 0,
operationMode: value,
});
}

Expand Down Expand Up @@ -185,4 +186,10 @@ export class NavienApi {
},
});
}

public setChildLock(device: Device, isLocked: boolean) {
return this.controlDevice(device, {
childLock: isLocked,
});
}
}
32 changes: 28 additions & 4 deletions src/navien/navien.device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import { NavienApi } from './navien.api';

const DEFALUT_IS_ACTIVE = false;
const DEFALUT_TEMPERATURE = 30;
const DEFALUT_IS_LOCKED = false;

export class NavienDevice {
private _isActive = DEFALUT_IS_ACTIVE;
private _temperature = DEFALUT_TEMPERATURE;
private _isLocked = DEFALUT_IS_LOCKED;

private readonly isActiveSubject = new BehaviorSubject<boolean>(DEFALUT_IS_ACTIVE);
private readonly temperatureSubject = new BehaviorSubject<number>(DEFALUT_TEMPERATURE);
private readonly isLockedSubject = new BehaviorSubject<boolean>(DEFALUT_IS_LOCKED);
private readonly subcription: Subscription;

constructor(
Expand All @@ -32,11 +35,12 @@ export class NavienDevice {
const leftTemperature = state.heater.left.temperature.set;
const rightTemperature = state.heater.right.temperature.set;
const temperature = leftTemperature; // TODO: handle left and right
const locked = state.childLock;
this.log.info('[AWS PubSub] current status:', { name: this.name, isActive, leftTemperature, rightTemperature, locked });
const isLocked = state.childLock;
this.log.info('[AWS PubSub] current status:', { name: this.name, isActive, leftTemperature, rightTemperature, isLocked });

this.isActive = isActive;
this.temperature = temperature;
this.isLocked = isLocked;
});
}

Expand Down Expand Up @@ -97,6 +101,18 @@ export class NavienDevice {
this.temperatureSubject.next(value);
}

get isLocked() {
return this._isLocked;
}

set isLocked(value: boolean) {
if (this._isLocked === value) {
return;
}
this._isLocked = value;
this.isLockedSubject.next(value);
}

get activeChanges() {
return this.isActiveSubject.asObservable();
}
Expand All @@ -105,18 +121,26 @@ export class NavienDevice {
return this.temperatureSubject.asObservable();
}

get lockedChanges() {
return this.isLockedSubject.asObservable();
}

initialize() {
return this.api.initializeDevice(this.json);
}

setActive(isActive: boolean) {
return this.api.setActive(this.json, isActive);
activate(isActive: boolean) {
return this.api.setOperationMode(this.json, isActive ? OperationMode.ON : OperationMode.OFF);
}

setTemperature(temperature: number) {
return this.api.setTemperature(this.json, temperature, this.functions.heatRange);
}

lock(isLocked: boolean) {
return this.api.setChildLock(this.json, isLocked);
}

dispose() {
this.subcription.unsubscribe();
}
Expand Down
22 changes: 20 additions & 2 deletions src/navien/navien.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ export class NavienService {
return devices;
}

public async setActive(device: NavienDevice, isActive: boolean) {
public async activate(device: NavienDevice, isActive: boolean) {
this.log.info('Setting active to', isActive, 'for device', device.name);

const success = await device.setActive(isActive).then(() => true).catch((error) => {
const success = await device.activate(isActive).then(() => true).catch((error) => {
if (error instanceof NavienException) {
this.log.error(error.toString());
return false;
Expand Down Expand Up @@ -113,6 +113,24 @@ export class NavienService {
} else {
this.log.error('Failed to set temperature to', temperature, 'for device', device.name);
}
}

public async lock(device: NavienDevice, isLocked: boolean) {
this.log.info('Setting lock to', isLocked, 'for device', device.name);

const success = await device.lock(isLocked).then(() => true).catch((error) => {
if (error instanceof NavienException) {
this.log.error(error.toString());
return false;
}
this.log.error('Unknown error while setting lock for device', device.name, ':', error);
return false;
});

if (success) {
this.log.info('Lock set to', isLocked, 'for device', device.name);
} else {
this.log.error('Failed to set lock to', isLocked, 'for device', device.name);
}
}
}

0 comments on commit 10fb265

Please sign in to comment.